On Tue, Mar 19, 2013 at 4:29 AM, Nicholas Marriott <nicholas.marri...@gmail.com> wrote: > Did you forget to attach the code?
Sort of. I thought someone might have some comment on the general idea or the brief outline of the changes (e.g. if anyone had already explored related ideas). But I did end up with the lingering feeling that I should have sent the code, too. The changes I made are below, all in one batch. I also have them in separate chunks (in Git, with more details about the individual changes) like this: eafaa15 Remove unused out and outdone from struct job 2ffa3f2 Pass session to job_run, if available 898f154 Allow writing to job 4485207 Use a writable job in copy-pipe -->8-- cmd-if-shell.c | 2 +- cmd-run-shell.c | 2 +- job.c | 32 +++++++++++++++++++++++++------- status.c | 2 +- tmux.h | 7 ++----- window-copy.c | 22 +++++++++++----------- 6 files changed, 41 insertions(+), 26 deletions(-) diff --git a/cmd-if-shell.c b/cmd-if-shell.c index b22e326..dddd5d4 100644 --- a/cmd-if-shell.c +++ b/cmd-if-shell.c @@ -89,7 +89,7 @@ cmd_if_shell_exec(struct cmd *self, struct cmd_q *cmdq) cdata->cmdq = cmdq; cmdq->references++; - job_run(shellcmd, cmd_if_shell_callback, cmd_if_shell_free, cdata); + job_run(shellcmd, s, cmd_if_shell_callback, cmd_if_shell_free, cdata); free(shellcmd); if (cdata->bflag) diff --git a/cmd-run-shell.c b/cmd-run-shell.c index b163542..4df21ff 100644 --- a/cmd-run-shell.c +++ b/cmd-run-shell.c @@ -103,7 +103,7 @@ cmd_run_shell_exec(struct cmd *self, struct cmd_q *cmdq) cdata->cmdq = cmdq; cmdq->references++; - job_run(shellcmd, cmd_run_shell_callback, cmd_run_shell_free, cdata); + job_run(shellcmd, s, cmd_run_shell_callback, cmd_run_shell_free, cdata); if (cdata->bflag) return (CMD_RETURN_NORMAL); diff --git a/job.c b/job.c index 8885899..feb30c9 100644 --- a/job.c +++ b/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,7 @@ 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 +135,21 @@ 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) diff --git a/status.c b/status.c index 9166ea5..f120c38 100644 --- a/status.c +++ b/status.c @@ -594,7 +594,7 @@ status_find_job(struct client *c, char **iptr) /* If not found at all, start the job and add to the tree. */ if (so == NULL) { - job_run(cmd, status_job_callback, status_job_free, c); + job_run(cmd, NULL, status_job_callback, status_job_free, c); c->references++; so = xmalloc(sizeof *so); diff --git a/tmux.h b/tmux.h index 7c4c55b..834ac6e 100644 --- a/tmux.h +++ b/tmux.h @@ -776,9 +776,6 @@ struct job { int fd; struct bufferevent *event; - struct bufferevent *out; - int outdone; - void (*callbackfn)(struct job *); void (*freefn)(void *); void *data; @@ -1610,8 +1607,8 @@ int options_table_find(const char *, const struct options_table_entry **, /* job.c */ extern struct joblist all_jobs; -struct job *job_run( - const char *, void (*)(struct job *), void (*)(void *), void *); +struct job *job_run(const char *, struct session *, + void (*)(struct job *), void (*)(void *), void *); void job_free(struct job *); void job_died(struct job *, int); diff --git a/window-copy.c b/window-copy.c index 2228b38..2dd65eb 100644 --- a/window-copy.c +++ b/window-copy.c @@ -54,7 +54,8 @@ void window_copy_start_selection(struct window_pane *); int window_copy_update_selection(struct window_pane *); void *window_copy_get_selection(struct window_pane *, size_t *); void window_copy_copy_buffer(struct window_pane *, int, void *, size_t); -void window_copy_copy_pipe(struct window_pane *, int, const char *); +void window_copy_copy_pipe( + struct window_pane *, struct session *, int, const char *); void window_copy_copy_selection(struct window_pane *, int); void window_copy_clear_selection(struct window_pane *); void window_copy_copy_line( @@ -539,7 +540,7 @@ window_copy_key(struct window_pane *wp, struct session *sess, int key) break; case MODEKEYCOPY_COPYPIPE: if (sess != NULL) { - window_copy_copy_pipe(wp, data->numprefix, arg); + window_copy_copy_pipe(wp, sess, data->numprefix, arg); window_pane_reset_mode(wp); return; } @@ -1397,21 +1398,20 @@ window_copy_copy_buffer(struct window_pane *wp, int idx, void *buf, size_t len) } void -window_copy_copy_pipe(struct window_pane *wp, int idx, const char *arg) +window_copy_copy_pipe( + struct window_pane *wp, struct session *sess, int idx, const char *arg) { - void* buf; - size_t len; - FILE* f; + void *buf; + size_t len; + struct job *job; + buf = window_copy_get_selection(wp, &len); if (buf == NULL) return; - f = popen(arg, "w"); - if (f != NULL) { - fwrite(buf, 1, len, f); - pclose(f); - } + job = job_run(arg, sess, NULL, NULL, NULL); + bufferevent_write(job->event, buf, len); window_copy_copy_buffer(wp, idx, buf, len); } -- 1.8.1.3 ------------------------------------------------------------------------------ Everyone hates slow websites. So do we. Make your web apps faster with AppDynamics Download AppDynamics Lite for free today: http://p.sf.net/sfu/appdyn_d2d_mar _______________________________________________ tmux-users mailing list tmux-users@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/tmux-users