mirror of
				https://github.com/tmux/tmux.git
				synced 2025-11-04 00:56:10 +00:00 
			
		
		
		
	Add a flag to run a background process in a pty as well, not used for
anything yet.
This commit is contained in:
		@@ -144,7 +144,8 @@ cmd_if_shell_exec(struct cmd *self, struct cmdq_item *item)
 | 
				
			|||||||
	cmd_find_copy_state(&cdata->input.fs, fs);
 | 
						cmd_find_copy_state(&cdata->input.fs, fs);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (job_run(shellcmd, s, server_client_get_cwd(item->client, s), NULL,
 | 
						if (job_run(shellcmd, s, server_client_get_cwd(item->client, s), NULL,
 | 
				
			||||||
	    cmd_if_shell_callback, cmd_if_shell_free, cdata, 0) == NULL) {
 | 
						    cmd_if_shell_callback, cmd_if_shell_free, cdata, 0, -1,
 | 
				
			||||||
 | 
						    -1) == NULL) {
 | 
				
			||||||
		cmdq_error(item, "failed to run command: %s", shellcmd);
 | 
							cmdq_error(item, "failed to run command: %s", shellcmd);
 | 
				
			||||||
		free(shellcmd);
 | 
							free(shellcmd);
 | 
				
			||||||
		free(cdata);
 | 
							free(cdata);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -145,8 +145,8 @@ cmd_run_shell_timer(__unused int fd, __unused short events, void* arg)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	if (cdata->cmd != NULL) {
 | 
						if (cdata->cmd != NULL) {
 | 
				
			||||||
		if (job_run(cdata->cmd, cdata->s, cdata->cwd, NULL,
 | 
							if (job_run(cdata->cmd, cdata->s, cdata->cwd, NULL,
 | 
				
			||||||
		    cmd_run_shell_callback, cmd_run_shell_free, cdata,
 | 
							    cmd_run_shell_callback, cmd_run_shell_free, cdata, 0, -1,
 | 
				
			||||||
		    0) == NULL)
 | 
							    -1) == NULL)
 | 
				
			||||||
			cmd_run_shell_free(cdata);
 | 
								cmd_run_shell_free(cdata);
 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
		if (cdata->item != NULL)
 | 
							if (cdata->item != NULL)
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										2
									
								
								format.c
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								format.c
									
									
									
									
									
								
							@@ -354,7 +354,7 @@ format_job_get(struct format_tree *ft, const char *cmd)
 | 
				
			|||||||
	if (force || (fj->job == NULL && fj->last != t)) {
 | 
						if (force || (fj->job == NULL && fj->last != t)) {
 | 
				
			||||||
		fj->job = job_run(expanded, NULL,
 | 
							fj->job = job_run(expanded, NULL,
 | 
				
			||||||
		    server_client_get_cwd(ft->client, NULL), format_job_update,
 | 
							    server_client_get_cwd(ft->client, NULL), format_job_update,
 | 
				
			||||||
		    format_job_complete, NULL, fj, JOB_NOWAIT);
 | 
							    format_job_complete, NULL, fj, JOB_NOWAIT, -1, -1);
 | 
				
			||||||
		if (fj->job == NULL) {
 | 
							if (fj->job == NULL) {
 | 
				
			||||||
			free(fj->out);
 | 
								free(fj->out);
 | 
				
			||||||
			xasprintf(&fj->out, "<'%s' didn't start>", fj->cmd);
 | 
								xasprintf(&fj->out, "<'%s' didn't start>", fj->cmd);
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										46
									
								
								job.c
									
									
									
									
									
								
							
							
						
						
									
										46
									
								
								job.c
									
									
									
									
									
								
							@@ -25,6 +25,7 @@
 | 
				
			|||||||
#include <stdlib.h>
 | 
					#include <stdlib.h>
 | 
				
			||||||
#include <string.h>
 | 
					#include <string.h>
 | 
				
			||||||
#include <unistd.h>
 | 
					#include <unistd.h>
 | 
				
			||||||
 | 
					#include <util.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "tmux.h"
 | 
					#include "tmux.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -69,18 +70,15 @@ static LIST_HEAD(joblist, job) all_jobs = LIST_HEAD_INITIALIZER(all_jobs);
 | 
				
			|||||||
struct job *
 | 
					struct job *
 | 
				
			||||||
job_run(const char *cmd, struct session *s, const char *cwd,
 | 
					job_run(const char *cmd, struct session *s, const char *cwd,
 | 
				
			||||||
    job_update_cb updatecb, job_complete_cb completecb, job_free_cb freecb,
 | 
					    job_update_cb updatecb, job_complete_cb completecb, job_free_cb freecb,
 | 
				
			||||||
    void *data, int flags)
 | 
					    void *data, int flags, int sx, int sy)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct job	*job;
 | 
						struct job	*job;
 | 
				
			||||||
	struct environ	*env;
 | 
						struct environ	*env;
 | 
				
			||||||
	pid_t		 pid;
 | 
						pid_t		 pid;
 | 
				
			||||||
	int		 nullfd, out[2];
 | 
						int		 nullfd, out[2], master;
 | 
				
			||||||
	const char	*home;
 | 
						const char	*home;
 | 
				
			||||||
	sigset_t	 set, oldset;
 | 
						sigset_t	 set, oldset;
 | 
				
			||||||
 | 
						struct winsize	 ws;
 | 
				
			||||||
	if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, out) != 0)
 | 
					 | 
				
			||||||
		return (NULL);
 | 
					 | 
				
			||||||
	log_debug("%s: cmd=%s, cwd=%s", __func__, cmd, cwd == NULL ? "" : cwd);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/*
 | 
						/*
 | 
				
			||||||
	 * Do not set TERM during .tmux.conf, it is nice to be able to use
 | 
						 * Do not set TERM during .tmux.conf, it is nice to be able to use
 | 
				
			||||||
@@ -90,13 +88,26 @@ job_run(const char *cmd, struct session *s, const char *cwd,
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	sigfillset(&set);
 | 
						sigfillset(&set);
 | 
				
			||||||
	sigprocmask(SIG_BLOCK, &set, &oldset);
 | 
						sigprocmask(SIG_BLOCK, &set, &oldset);
 | 
				
			||||||
	switch (pid = fork()) {
 | 
					
 | 
				
			||||||
 | 
						if (flags & JOB_PTY) {
 | 
				
			||||||
 | 
							memset(&ws, 0, sizeof ws);
 | 
				
			||||||
 | 
							ws.ws_col = sx;
 | 
				
			||||||
 | 
							ws.ws_row = sy;
 | 
				
			||||||
 | 
							pid = fdforkpty(ptm_fd, &master, NULL, NULL, &ws);
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, out) != 0)
 | 
				
			||||||
 | 
								goto fail;
 | 
				
			||||||
 | 
							pid = fork();
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						log_debug("%s: cmd=%s, cwd=%s", __func__, cmd, cwd == NULL ? "" : cwd);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						switch (pid) {
 | 
				
			||||||
	case -1:
 | 
						case -1:
 | 
				
			||||||
		sigprocmask(SIG_SETMASK, &oldset, NULL);
 | 
							if (~flags & JOB_PTY) {
 | 
				
			||||||
		environ_free(env);
 | 
					 | 
				
			||||||
			close(out[0]);
 | 
								close(out[0]);
 | 
				
			||||||
			close(out[1]);
 | 
								close(out[1]);
 | 
				
			||||||
		return (NULL);
 | 
							}
 | 
				
			||||||
 | 
							goto fail;
 | 
				
			||||||
	case 0:
 | 
						case 0:
 | 
				
			||||||
		proc_clear_signals(server_proc, 1);
 | 
							proc_clear_signals(server_proc, 1);
 | 
				
			||||||
		sigprocmask(SIG_SETMASK, &oldset, NULL);
 | 
							sigprocmask(SIG_SETMASK, &oldset, NULL);
 | 
				
			||||||
@@ -109,6 +120,7 @@ job_run(const char *cmd, struct session *s, const char *cwd,
 | 
				
			|||||||
		environ_push(env);
 | 
							environ_push(env);
 | 
				
			||||||
		environ_free(env);
 | 
							environ_free(env);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (~flags & JOB_PTY) {
 | 
				
			||||||
			if (dup2(out[1], STDIN_FILENO) == -1)
 | 
								if (dup2(out[1], STDIN_FILENO) == -1)
 | 
				
			||||||
				fatal("dup2 failed");
 | 
									fatal("dup2 failed");
 | 
				
			||||||
			if (dup2(out[1], STDOUT_FILENO) == -1)
 | 
								if (dup2(out[1], STDOUT_FILENO) == -1)
 | 
				
			||||||
@@ -124,7 +136,7 @@ job_run(const char *cmd, struct session *s, const char *cwd,
 | 
				
			|||||||
				fatal("dup2 failed");
 | 
									fatal("dup2 failed");
 | 
				
			||||||
			if (nullfd != STDERR_FILENO)
 | 
								if (nullfd != STDERR_FILENO)
 | 
				
			||||||
				close(nullfd);
 | 
									close(nullfd);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
		closefrom(STDERR_FILENO + 1);
 | 
							closefrom(STDERR_FILENO + 1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		execl(_PATH_BSHELL, "sh", "-c", cmd, (char *) NULL);
 | 
							execl(_PATH_BSHELL, "sh", "-c", cmd, (char *) NULL);
 | 
				
			||||||
@@ -133,7 +145,6 @@ job_run(const char *cmd, struct session *s, const char *cwd,
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	sigprocmask(SIG_SETMASK, &oldset, NULL);
 | 
						sigprocmask(SIG_SETMASK, &oldset, NULL);
 | 
				
			||||||
	environ_free(env);
 | 
						environ_free(env);
 | 
				
			||||||
	close(out[1]);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	job = xmalloc(sizeof *job);
 | 
						job = xmalloc(sizeof *job);
 | 
				
			||||||
	job->state = JOB_RUNNING;
 | 
						job->state = JOB_RUNNING;
 | 
				
			||||||
@@ -150,7 +161,11 @@ job_run(const char *cmd, struct session *s, const char *cwd,
 | 
				
			|||||||
	job->freecb = freecb;
 | 
						job->freecb = freecb;
 | 
				
			||||||
	job->data = data;
 | 
						job->data = data;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (~flags & JOB_PTY) {
 | 
				
			||||||
 | 
							close(out[1]);
 | 
				
			||||||
		job->fd = out[0];
 | 
							job->fd = out[0];
 | 
				
			||||||
 | 
						} else
 | 
				
			||||||
 | 
							job->fd = master;
 | 
				
			||||||
	setblocking(job->fd, 0);
 | 
						setblocking(job->fd, 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	job->event = bufferevent_new(job->fd, job_read_callback,
 | 
						job->event = bufferevent_new(job->fd, job_read_callback,
 | 
				
			||||||
@@ -161,6 +176,11 @@ job_run(const char *cmd, struct session *s, const char *cwd,
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	log_debug("run job %p: %s, pid %ld", job, job->cmd, (long) job->pid);
 | 
						log_debug("run job %p: %s, pid %ld", job, job->cmd, (long) job->pid);
 | 
				
			||||||
	return (job);
 | 
						return (job);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					fail:
 | 
				
			||||||
 | 
						sigprocmask(SIG_SETMASK, &oldset, NULL);
 | 
				
			||||||
 | 
						environ_free(env);
 | 
				
			||||||
 | 
						return (NULL);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Kill and free an individual job. */
 | 
					/* Kill and free an individual job. */
 | 
				
			||||||
@@ -209,7 +229,7 @@ job_write_callback(__unused struct bufferevent *bufev, void *data)
 | 
				
			|||||||
	log_debug("job write %p: %s, pid %ld, output left %zu", job, job->cmd,
 | 
						log_debug("job write %p: %s, pid %ld, output left %zu", job, job->cmd,
 | 
				
			||||||
	    (long) job->pid, len);
 | 
						    (long) job->pid, len);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (len == 0) {
 | 
						if (len == 0 && (~job->flags & JOB_KEEPWRITE)) {
 | 
				
			||||||
		shutdown(job->fd, SHUT_WR);
 | 
							shutdown(job->fd, SHUT_WR);
 | 
				
			||||||
		bufferevent_disable(job->event, EV_WRITE);
 | 
							bufferevent_disable(job->event, EV_WRITE);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										5
									
								
								tmux.h
									
									
									
									
									
								
							
							
						
						
									
										5
									
								
								tmux.h
									
									
									
									
									
								
							@@ -1929,8 +1929,11 @@ typedef void (*job_update_cb) (struct job *);
 | 
				
			|||||||
typedef void (*job_complete_cb) (struct job *);
 | 
					typedef void (*job_complete_cb) (struct job *);
 | 
				
			||||||
typedef void (*job_free_cb) (void *);
 | 
					typedef void (*job_free_cb) (void *);
 | 
				
			||||||
#define JOB_NOWAIT 0x1
 | 
					#define JOB_NOWAIT 0x1
 | 
				
			||||||
 | 
					#define JOB_KEEPWRITE 0x2
 | 
				
			||||||
 | 
					#define JOB_PTY 0x4
 | 
				
			||||||
struct job	*job_run(const char *, struct session *, const char *,
 | 
					struct job	*job_run(const char *, struct session *, const char *,
 | 
				
			||||||
		     job_update_cb, job_complete_cb, job_free_cb, void *, int);
 | 
							     job_update_cb, job_complete_cb, job_free_cb, void *, int,
 | 
				
			||||||
 | 
							     int, int);
 | 
				
			||||||
void		 job_free(struct job *);
 | 
					void		 job_free(struct job *);
 | 
				
			||||||
void		 job_check_died(pid_t, int);
 | 
					void		 job_check_died(pid_t, int);
 | 
				
			||||||
int		 job_get_status(struct job *);
 | 
					int		 job_get_status(struct job *);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -3240,7 +3240,7 @@ window_copy_copy_buffer(struct window_mode_entry *wme, const char *prefix,
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
static void
 | 
					static void
 | 
				
			||||||
window_copy_copy_pipe(struct window_mode_entry *wme, struct session *s,
 | 
					window_copy_copy_pipe(struct window_mode_entry *wme, struct session *s,
 | 
				
			||||||
    const char *prefix, const char *command)
 | 
					    const char *prefix, const char *cmd)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	void		*buf;
 | 
						void		*buf;
 | 
				
			||||||
	size_t		 len;
 | 
						size_t		 len;
 | 
				
			||||||
@@ -3250,7 +3250,7 @@ window_copy_copy_pipe(struct window_mode_entry *wme, struct session *s,
 | 
				
			|||||||
	if (buf == NULL)
 | 
						if (buf == NULL)
 | 
				
			||||||
		return;
 | 
							return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	job = job_run(command, s, NULL, NULL, NULL, NULL, NULL, JOB_NOWAIT);
 | 
						job = job_run(cmd, s, NULL, NULL, NULL, NULL, NULL, JOB_NOWAIT, -1, -1);
 | 
				
			||||||
	bufferevent_write(job_get_event(job), buf, len);
 | 
						bufferevent_write(job_get_event(job), buf, len);
 | 
				
			||||||
	window_copy_copy_buffer(wme, prefix, buf, len);
 | 
						window_copy_copy_buffer(wme, prefix, buf, len);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user