#include #include #include #include #include #include #include static bool fddone; static pthread_cond_t cond = PTHREAD_COND_INITIALIZER; static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER; static int cb(struct ncfdplane* ncfd, const void* data, size_t len, void* curry){ int ret = -1; // FIXME unsafe -- input isn't necessarily nul-terminated! if(ncplane_putstr(ncfdplane_plane(ncfd), data) >= 0){ if(!notcurses_render(ncplane_notcurses(ncfdplane_plane(ncfd)))){ ret = 0; } } (void)len; (void)curry; return ret; } static int eofcb(struct ncfdplane* ncfd, int nerrno, void* curry){ (void)ncfd; (void)nerrno; (void)curry; pthread_mutex_lock(&lock); fddone = true; pthread_mutex_unlock(&lock); pthread_cond_signal(&cond); return nerrno; } int main(int argc, char** argv){ if(argc < 2){ fprintf(stderr, "usage: %s binary [ args... ]\n", *argv); return EXIT_FAILURE; } setlocale(LC_ALL, ""); notcurses_options opts = { .flags = NCOPTION_INHIBIT_SETLOCALE | NCOPTION_NO_ALTERNATE_SCREEN, }; struct notcurses* nc = notcurses_init(&opts, NULL); if(nc == NULL){ return EXIT_FAILURE; } ++argv; struct ncplane* n = notcurses_stdplane(nc); ncplane_set_scrolling(n, true); ncsubproc_options nopts = {}; struct ncsubproc* nsproc = ncsubproc_createvp(n, &nopts, *argv, argv, cb, eofcb); pthread_mutex_lock(&lock); while(!fddone){ pthread_cond_wait(&cond, &lock); } pthread_mutex_unlock(&lock); ncsubproc_destroy(nsproc); if(notcurses_stop(nc)){ return EXIT_FAILURE; } return EXIT_SUCCESS; }