mirror of
				https://github.com/tmux/tmux.git
				synced 2025-11-04 01:34:18 +00:00 
			
		
		
		
	Extend jobs to support writing and use that for copy-pipe instead of popen,
from Chris Johnsen.
This commit is contained in:
		@@ -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)
 | 
			
		||||
 
 | 
			
		||||
@@ -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);
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										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)
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										2
									
								
								status.c
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								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);
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										7
									
								
								tmux.h
									
									
									
									
									
								
							
							
						
						
									
										7
									
								
								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);
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -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);
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user