version 1.28, 2013/03/22 10:31:22 |
version 1.29, 2013/03/25 11:43:01 |
|
|
*/ |
*/ |
|
|
void job_callback(struct bufferevent *, short, void *); |
void job_callback(struct bufferevent *, short, void *); |
|
void job_write_callback(struct bufferevent *, void *); |
|
|
/* All jobs list. */ |
/* All jobs list. */ |
struct joblist all_jobs = LIST_HEAD_INITIALIZER(all_jobs); |
struct joblist all_jobs = LIST_HEAD_INITIALIZER(all_jobs); |
|
|
/* Start a job running, if it isn't already. */ |
/* Start a job running, if it isn't already. */ |
struct job * |
struct job * |
job_run(const char *cmd, |
job_run(const char *cmd, struct session *s, |
void (*callbackfn)(struct job *), void (*freefn)(void *), void *data) |
void (*callbackfn)(struct job *), void (*freefn)(void *), void *data) |
{ |
{ |
struct job *job; |
struct job *job; |
|
|
|
|
environ_init(&env); |
environ_init(&env); |
environ_copy(&global_environ, &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()) { |
switch (pid = fork()) { |
case -1: |
case -1: |
|
|
environ_push(&env); |
environ_push(&env); |
environ_free(&env); |
environ_free(&env); |
|
|
|
if (dup2(out[1], STDIN_FILENO) == -1) |
|
fatal("dup2 failed"); |
if (dup2(out[1], STDOUT_FILENO) == -1) |
if (dup2(out[1], STDOUT_FILENO) == -1) |
fatal("dup2 failed"); |
fatal("dup2 failed"); |
if (out[1] != STDOUT_FILENO) |
if (out[1] != STDIN_FILENO && out[1] != STDOUT_FILENO) |
close(out[1]); |
close(out[1]); |
close(out[0]); |
close(out[0]); |
|
|
nullfd = open(_PATH_DEVNULL, O_RDWR, 0); |
nullfd = open(_PATH_DEVNULL, O_RDWR, 0); |
if (nullfd < 0) |
if (nullfd < 0) |
fatal("open failed"); |
fatal("open failed"); |
if (dup2(nullfd, STDIN_FILENO) == -1) |
|
fatal("dup2 failed"); |
|
if (dup2(nullfd, STDERR_FILENO) == -1) |
if (dup2(nullfd, STDERR_FILENO) == -1) |
fatal("dup2 failed"); |
fatal("dup2 failed"); |
if (nullfd != STDIN_FILENO && nullfd != STDERR_FILENO) |
if (nullfd != STDERR_FILENO) |
close(nullfd); |
close(nullfd); |
|
|
closefrom(STDERR_FILENO + 1); |
closefrom(STDERR_FILENO + 1); |
|
|
job->fd = out[0]; |
job->fd = out[0]; |
setblocking(job->fd, 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); |
bufferevent_enable(job->event, EV_READ); |
|
|
log_debug("run job %p: %s, pid %ld", job, job->cmd, (long) job->pid); |
log_debug("run job %p: %s, pid %ld", job, job->cmd, (long) job->pid); |
|
|
close(job->fd); |
close(job->fd); |
|
|
free(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. */ |
/* Job buffer error callback. */ |