summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNicholas Marriott <nicm@cvs.openbsd.org>2013-03-25 11:43:02 +0000
committerNicholas Marriott <nicm@cvs.openbsd.org>2013-03-25 11:43:02 +0000
commite6067a65342859bdeda474215d5c768d7f60747a (patch)
tree71a50f261a0a07547367ff1faaf703180201cacb
parent34f3b58de497f4f6dde4580bd55ee63344d8c5f8 (diff)
Extend jobs to support writing and use that for copy-pipe instead of
popen, from Chris Johnsen.
-rw-r--r--usr.bin/tmux/cmd-if-shell.c4
-rw-r--r--usr.bin/tmux/cmd-run-shell.c4
-rw-r--r--usr.bin/tmux/job.c36
-rw-r--r--usr.bin/tmux/status.c4
-rw-r--r--usr.bin/tmux/tmux.h9
-rw-r--r--usr.bin/tmux/window-copy.c24
6 files changed, 49 insertions, 32 deletions
diff --git a/usr.bin/tmux/cmd-if-shell.c b/usr.bin/tmux/cmd-if-shell.c
index a5f23df285b..01a5d974349 100644
--- a/usr.bin/tmux/cmd-if-shell.c
+++ b/usr.bin/tmux/cmd-if-shell.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: cmd-if-shell.c,v 1.21 2013/03/25 11:36:42 nicm Exp $ */
+/* $OpenBSD: cmd-if-shell.c,v 1.22 2013/03/25 11:43:01 nicm Exp $ */
/*
* Copyright (c) 2009 Tiago Cunha <me@tiagocunha.org>
@@ -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/usr.bin/tmux/cmd-run-shell.c b/usr.bin/tmux/cmd-run-shell.c
index 6816d730d7d..44e63162e90 100644
--- a/usr.bin/tmux/cmd-run-shell.c
+++ b/usr.bin/tmux/cmd-run-shell.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: cmd-run-shell.c,v 1.21 2013/03/25 11:36:42 nicm Exp $ */
+/* $OpenBSD: cmd-run-shell.c,v 1.22 2013/03/25 11:43:01 nicm Exp $ */
/*
* Copyright (c) 2009 Tiago Cunha <me@tiagocunha.org>
@@ -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/usr.bin/tmux/job.c b/usr.bin/tmux/job.c
index 0cc690613db..749e9a698e5 100644
--- a/usr.bin/tmux/job.c
+++ b/usr.bin/tmux/job.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: job.c,v 1.28 2013/03/22 10:31:22 nicm Exp $ */
+/* $OpenBSD: job.c,v 1.29 2013/03/25 11:43:01 nicm Exp $ */
/*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -33,13 +33,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;
@@ -52,7 +53,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:
@@ -64,20 +67,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);
@@ -104,7 +107,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);
@@ -133,6 +137,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)
diff --git a/usr.bin/tmux/status.c b/usr.bin/tmux/status.c
index 08c4e3395ae..b9fbd56c52b 100644
--- a/usr.bin/tmux/status.c
+++ b/usr.bin/tmux/status.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: status.c,v 1.102 2013/03/22 15:55:22 nicm Exp $ */
+/* $OpenBSD: status.c,v 1.103 2013/03/25 11:43:01 nicm Exp $ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -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/usr.bin/tmux/tmux.h b/usr.bin/tmux/tmux.h
index 2fe98ff5a3c..ab46c3cedce 100644
--- a/usr.bin/tmux/tmux.h
+++ b/usr.bin/tmux/tmux.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: tmux.h,v 1.404 2013/03/25 11:41:16 nicm Exp $ */
+/* $OpenBSD: tmux.h,v 1.405 2013/03/25 11:43:01 nicm Exp $ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -780,9 +780,6 @@ struct job {
int fd;
struct bufferevent *event;
- struct bufferevent *out;
- int outdone;
-
void (*callbackfn)(struct job *);
void (*freefn)(void *);
void *data;
@@ -1614,8 +1611,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/usr.bin/tmux/window-copy.c b/usr.bin/tmux/window-copy.c
index a14f5698fc2..a5b597562fe 100644
--- a/usr.bin/tmux/window-copy.c
+++ b/usr.bin/tmux/window-copy.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: window-copy.c,v 1.89 2013/03/22 15:52:42 nicm Exp $ */
+/* $OpenBSD: window-copy.c,v 1.90 2013/03/25 11:43:01 nicm Exp $ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -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);
}