zio_t *zio_pipe_writer_create (const char *name, void *arg) { zio_t *zio; int pfds[2]; if (pipe (pfds) < 0) return (NULL); if ((zio = zio_writer_create (name, pfds[1], arg)) == NULL) { close (pfds[0]); close (pfds[1]); return (NULL); } zio->srcfd = pfds[0]; //fd_set_nonblocking (zio->srcfd); return (zio); }
static void forkzio_pipe_thd (void *args, zctx_t *zctx, void *zs) { forkzio_t ctx = args; zmq_pollitem_t zp = { .fd = -1, .socket = zs, .events = ZMQ_POLLIN }; zloop_t *zloop; pid_t pid; if (!(zloop = zloop_new ())) oom (); /* child stdin <= zs */ zloop_poller (zloop, &zp, (zloop_fn *)forkzio_zsock_cb, ctx); ctx->zio[0] = zio_pipe_writer_create ("stdin", NULL); if (zio_zloop_attach (ctx->zio[0], zloop) < 0) err_exit ("zio_zloop_attach %s", zio_name (ctx->zio[0])); /* child stdout => zs */ ctx->zio[1] = zio_pipe_reader_create ("stdout", zs, ctx); zio_set_close_cb (ctx->zio[1], forkzio_close_cb); if (zio_zloop_attach (ctx->zio[1], zloop) < 0) err_exit ("zio_zloop_attach %s", zio_name (ctx->zio[1])); ctx->readers++; /* child stderr => zs */ ctx->zio[2] = zio_pipe_reader_create ("stderr", zs, ctx); zio_set_close_cb (ctx->zio[2], forkzio_close_cb); if (zio_zloop_attach (ctx->zio[2], zloop) < 0) err_exit ("zio_zloop_attach %s", zio_name (ctx->zio[2])); ctx->readers++; pid = forkzio_fork (ctx); (void)zloop_start (zloop); forkzio_wait (pid); zio_destroy (ctx->zio[0]); zio_destroy (ctx->zio[1]); zio_destroy (ctx->zio[2]); zstr_send (zs, ""); /* signify EOF by sending an empty message */ } static void forkzio_pty_thd (void *args, zctx_t *zctx, void *zs) { forkzio_t ctx = args; zmq_pollitem_t zp = { .fd = -1, .socket = zs, .events = ZMQ_POLLIN }; zloop_t *zloop; pid_t pid; int ptyfd; if (!(zloop = zloop_new ())) oom (); switch ((pid = forkpty (&ptyfd, NULL, NULL, NULL))) { case -1: /* error */ err_exit ("forkpty"); case 0: /* child */ (void)execvp (ctx->av[0], ctx->av); err_exit ("%s", ctx->av[0]); default: /* parent */ break; } /* Data read from zs is written to pty master */ zloop_poller (zloop, &zp, (zloop_fn *)forkzio_zsock_cb, ctx); ctx->zio[0] = zio_writer_create ("stdin", ptyfd, NULL); zio_set_unbuffered (ctx->zio[0]); if (zio_zloop_attach (ctx->zio[0], zloop) < 0) err_exit ("zio_zloop_attach %s", zio_name (ctx->zio[0])); /* Data read from pty master is written to zs */ ctx->zio[1] = zio_reader_create ("stdout", ptyfd, zs, ctx); zio_set_unbuffered (ctx->zio[1]); zio_set_close_cb (ctx->zio[1], forkzio_close_cb); if (zio_zloop_attach (ctx->zio[1], zloop) < 0) err_exit ("zio_zloop_attach %s", zio_name (ctx->zio[1])); ctx->readers++; (void)zloop_start (zloop); forkzio_wait (pid); zio_destroy (ctx->zio[0]); zio_destroy (ctx->zio[1]); zstr_send (zs, ""); /* signify EOF by sending an empty message */ } forkzio_t forkzio_open (zctx_t *zctx, int ac, char **av, int flags) { zthread_attached_fn *thd = forkzio_pipe_thd; forkzio_t ctx = xzmalloc (sizeof (*ctx)); ctx->ac = ac; ctx->av = av; ctx->zctx = zctx; ctx->flags = flags; if ((ctx->flags & FORKZIO_FLAG_PTY)) thd = forkzio_pty_thd; if (!(ctx->zs = zthread_fork (zctx, thd, ctx))) { free (ctx); ctx = NULL; } return ctx; }