mirror of
https://github.com/tmate-io/tmate.git
synced 2025-08-17 17:11:38 +02:00
Extend jobs to support writing and use that for copy-pipe instead of popen,
from Chris Johnsen.
This commit is contained in:
34
job.c
34
job.c
@ -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)
|
||||
|
Reference in New Issue
Block a user