diff options
author | Nicholas Marriott <nicholas.marriott@gmail.com> | 2013-03-21 14:24:33 +0000 |
---|---|---|
committer | Nicholas Marriott <nicholas.marriott@gmail.com> | 2013-03-21 14:24:33 +0000 |
commit | 6ddb06d37232a9d02da996e0a83d5acd52002ffc (patch) | |
tree | fb0e3bbd9f4f7e556a08f5e69a871505204efbec /job.c | |
parent | 69d97f6d4b7a373eb2c05ef2c3ca18be3271871b (diff) | |
download | rtmux-6ddb06d37232a9d02da996e0a83d5acd52002ffc.tar.gz rtmux-6ddb06d37232a9d02da996e0a83d5acd52002ffc.tar.bz2 rtmux-6ddb06d37232a9d02da996e0a83d5acd52002ffc.zip |
Extend jobs to support writing and use that for copy-pipe instead of popen,
from Chris Johnsen.
Diffstat (limited to 'job.c')
-rw-r--r-- | job.c | 34 |
1 files changed, 27 insertions, 7 deletions
@@ -32,13 +32,14 @@ */ void job_callback(struct bufferevent *, short, void *); +void job_write_callback(struct bufferevent *, void *); /* All jobs list. */ struct joblist all_jobs = LIST_HEAD_INITIALIZER(all_jobs); /* Start a job running, if it isn't already. */ struct job * -job_run(const char *cmd, +job_run(const char *cmd, struct session *s, void (*callbackfn)(struct job *), void (*freefn)(void *), void *data) { struct job *job; @@ -51,7 +52,9 @@ job_run(const char *cmd, environ_init(&env); environ_copy(&global_environ, &env); - server_fill_environ(NULL, &env); + if (s != NULL) + environ_copy(&s->environ, &env); + server_fill_environ(s, &env); switch (pid = fork()) { case -1: @@ -63,20 +66,20 @@ job_run(const char *cmd, environ_push(&env); environ_free(&env); + if (dup2(out[1], STDIN_FILENO) == -1) + fatal("dup2 failed"); if (dup2(out[1], STDOUT_FILENO) == -1) fatal("dup2 failed"); - if (out[1] != STDOUT_FILENO) + if (out[1] != STDIN_FILENO && out[1] != STDOUT_FILENO) close(out[1]); close(out[0]); nullfd = open(_PATH_DEVNULL, O_RDWR, 0); if (nullfd < 0) fatal("open failed"); - if (dup2(nullfd, STDIN_FILENO) == -1) - fatal("dup2 failed"); if (dup2(nullfd, STDERR_FILENO) == -1) fatal("dup2 failed"); - if (nullfd != STDIN_FILENO && nullfd != STDERR_FILENO) + if (nullfd != STDERR_FILENO) close(nullfd); closefrom(STDERR_FILENO + 1); @@ -103,7 +106,8 @@ job_run(const char *cmd, job->fd = out[0]; setblocking(job->fd, 0); - job->event = bufferevent_new(job->fd, NULL, NULL, job_callback, job); + job->event = bufferevent_new(job->fd, NULL, job_write_callback, + job_callback, job); bufferevent_enable(job->event, EV_READ); log_debug("run job %p: %s, pid %ld", job, job->cmd, (long) job->pid); @@ -132,6 +136,22 @@ job_free(struct job *job) free(job); } +/* Called when output buffer falls below low watermark (default is 0). */ +void +job_write_callback(unused struct bufferevent *bufev, void *data) +{ + struct job *job = data; + size_t len = EVBUFFER_LENGTH(EVBUFFER_OUTPUT(job->event)); + + log_debug("job write %p: %s, pid %ld, output left %lu", job, job->cmd, + (long) job->pid, (unsigned long) len); + + if (len == 0) { + shutdown(job->fd, SHUT_WR); + bufferevent_disable(job->event, EV_WRITE); + } +} + /* Job buffer error callback. */ void job_callback(unused struct bufferevent *bufev, unused short events, void *data) |