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

Reply via email to