version 1.10, 2009/11/04 20:50:11 |
version 1.11, 2009/11/04 21:04:43 |
|
|
*/ |
*/ |
|
|
#include <sys/types.h> |
#include <sys/types.h> |
|
#include <sys/socket.h> |
|
|
#include <fcntl.h> |
#include <fcntl.h> |
#include <paths.h> |
#include <paths.h> |
|
|
|
|
RB_GENERATE(jobs, job, entry, job_cmp); |
RB_GENERATE(jobs, job, entry, job_cmp); |
|
|
|
void job_callback(struct bufferevent *, short, void *); |
|
|
int |
int |
job_cmp(struct job *job1, struct job *job2) |
job_cmp(struct job *job1, struct job *job2) |
{ |
{ |
|
|
job->client = c; |
job->client = c; |
|
|
job->fd = -1; |
job->fd = -1; |
job->out = buffer_create(BUFSIZ); |
job->event = NULL; |
memset(&job->event, 0, sizeof job->event); |
|
|
|
job->callbackfn = callbackfn; |
job->callbackfn = callbackfn; |
job->freefn = freefn; |
job->freefn = freefn; |
job->data = data; |
job->data = data; |
|
|
job->flags = flags|JOB_DONE; |
job->flags = flags; |
|
|
if (jobs != NULL) |
if (jobs != NULL) |
RB_INSERT(jobs, jobs, job); |
RB_INSERT(jobs, jobs, job); |
|
|
|
|
if (job->fd != -1) |
if (job->fd != -1) |
close(job->fd); |
close(job->fd); |
if (job->out != NULL) |
|
buffer_destroy(job->out); |
|
event_del(&job->event); |
|
|
|
|
if (job->event != NULL) |
|
bufferevent_free(job->event); |
|
|
xfree(job); |
xfree(job); |
} |
} |
|
|
|
|
{ |
{ |
int nullfd, out[2], mode; |
int nullfd, out[2], mode; |
|
|
if (!(job->flags & JOB_DONE)) |
if (job->fd != -1 || job->pid != -1) |
return (0); |
return (0); |
job->flags &= ~JOB_DONE; |
|
|
|
if (pipe(out) != 0) |
if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, out) != 0) |
return (-1); |
return (-1); |
|
|
switch (job->pid = fork()) { |
switch (job->pid = fork()) { |
|
|
if (fcntl(job->fd, F_SETFD, FD_CLOEXEC) == -1) |
if (fcntl(job->fd, F_SETFD, FD_CLOEXEC) == -1) |
fatal("fcntl failed"); |
fatal("fcntl failed"); |
|
|
if (BUFFER_USED(job->out) != 0) |
if (job->event != NULL) |
buffer_remove(job->out, BUFFER_USED(job->out)); |
bufferevent_free(job->event); |
|
job->event = |
|
bufferevent_new(job->fd, NULL, NULL, job_callback, job); |
|
bufferevent_enable(job->event, EV_READ); |
|
|
return (0); |
return (0); |
} |
} |
|
} |
|
|
|
/* Job buffer error callback. */ |
|
void |
|
job_callback(unused struct bufferevent *bufev, unused short events, void *data) |
|
{ |
|
struct job *job = data; |
|
|
|
bufferevent_disable(job->event, EV_READ); |
|
close(job->fd); |
|
job->fd = -1; |
|
|
|
if (job->pid == -1 && job->callbackfn != NULL) |
|
job->callbackfn(job); |
|
} |
|
|
|
/* Job died (waitpid() returned its pid). */ |
|
void |
|
job_died(struct job *job, int status) |
|
{ |
|
job->status = status; |
|
job->pid = -1; |
|
|
|
if (job->fd == -1 && job->callbackfn != NULL) |
|
job->callbackfn(job); |
} |
} |
|
|
/* Kill a job. */ |
/* Kill a job. */ |