Exemplo n.º 1
0
Arquivo: zio.c Projeto: trws/flux-core
zio_t *zio_pipe_reader_create (const char *name, void *arg)
{
    zio_t *zio;
    int pfds[2];

    if (pipe (pfds) < 0)
        return (NULL);

    if ((zio = zio_reader_create (name, pfds[0], arg)) == NULL) {
        close (pfds[0]);
        close (pfds[1]);
        return (NULL);
    }
    zio->dstfd = pfds[1];
    //fd_set_nonblocking (zio->dstfd);

    return (zio);
}
Exemplo n.º 2
0
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;
}