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:
		
							
								
								
									
										80
									
								
								job.c
									
									
									
									
									
								
							
							
						
						
									
										80
									
								
								job.c
									
									
									
									
									
								
							@@ -25,6 +25,7 @@
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include <string.h>
 | 
			
		||||
#include <unistd.h>
 | 
			
		||||
#include <util.h>
 | 
			
		||||
 | 
			
		||||
#include "tmux.h"
 | 
			
		||||
 | 
			
		||||
@@ -69,18 +70,15 @@ static LIST_HEAD(joblist, job) all_jobs = LIST_HEAD_INITIALIZER(all_jobs);
 | 
			
		||||
struct job *
 | 
			
		||||
job_run(const char *cmd, struct session *s, const char *cwd,
 | 
			
		||||
    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 environ	*env;
 | 
			
		||||
	pid_t		 pid;
 | 
			
		||||
	int		 nullfd, out[2];
 | 
			
		||||
	int		 nullfd, out[2], master;
 | 
			
		||||
	const char	*home;
 | 
			
		||||
	sigset_t	 set, oldset;
 | 
			
		||||
 | 
			
		||||
	if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, out) != 0)
 | 
			
		||||
		return (NULL);
 | 
			
		||||
	log_debug("%s: cmd=%s, cwd=%s", __func__, cmd, cwd == NULL ? "" : cwd);
 | 
			
		||||
	struct winsize	 ws;
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * 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);
 | 
			
		||||
	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:
 | 
			
		||||
		sigprocmask(SIG_SETMASK, &oldset, NULL);
 | 
			
		||||
		environ_free(env);
 | 
			
		||||
		close(out[0]);
 | 
			
		||||
		close(out[1]);
 | 
			
		||||
		return (NULL);
 | 
			
		||||
		if (~flags & JOB_PTY) {
 | 
			
		||||
			close(out[0]);
 | 
			
		||||
			close(out[1]);
 | 
			
		||||
		}
 | 
			
		||||
		goto fail;
 | 
			
		||||
	case 0:
 | 
			
		||||
		proc_clear_signals(server_proc, 1);
 | 
			
		||||
		sigprocmask(SIG_SETMASK, &oldset, NULL);
 | 
			
		||||
@@ -109,22 +120,23 @@ job_run(const char *cmd, struct session *s, const char *cwd,
 | 
			
		||||
		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] != STDIN_FILENO && out[1] != STDOUT_FILENO)
 | 
			
		||||
			close(out[1]);
 | 
			
		||||
		close(out[0]);
 | 
			
		||||
 | 
			
		||||
		nullfd = open(_PATH_DEVNULL, O_RDWR, 0);
 | 
			
		||||
		if (nullfd == -1)
 | 
			
		||||
			fatal("open failed");
 | 
			
		||||
		if (dup2(nullfd, STDERR_FILENO) == -1)
 | 
			
		||||
			fatal("dup2 failed");
 | 
			
		||||
		if (nullfd != STDERR_FILENO)
 | 
			
		||||
			close(nullfd);
 | 
			
		||||
		if (~flags & JOB_PTY) {
 | 
			
		||||
			if (dup2(out[1], STDIN_FILENO) == -1)
 | 
			
		||||
				fatal("dup2 failed");
 | 
			
		||||
			if (dup2(out[1], STDOUT_FILENO) == -1)
 | 
			
		||||
				fatal("dup2 failed");
 | 
			
		||||
			if (out[1] != STDIN_FILENO && out[1] != STDOUT_FILENO)
 | 
			
		||||
				close(out[1]);
 | 
			
		||||
			close(out[0]);
 | 
			
		||||
 | 
			
		||||
			nullfd = open(_PATH_DEVNULL, O_RDWR, 0);
 | 
			
		||||
			if (nullfd == -1)
 | 
			
		||||
				fatal("open failed");
 | 
			
		||||
			if (dup2(nullfd, STDERR_FILENO) == -1)
 | 
			
		||||
				fatal("dup2 failed");
 | 
			
		||||
			if (nullfd != STDERR_FILENO)
 | 
			
		||||
				close(nullfd);
 | 
			
		||||
		}
 | 
			
		||||
		closefrom(STDERR_FILENO + 1);
 | 
			
		||||
 | 
			
		||||
		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);
 | 
			
		||||
	environ_free(env);
 | 
			
		||||
	close(out[1]);
 | 
			
		||||
 | 
			
		||||
	job = xmalloc(sizeof *job);
 | 
			
		||||
	job->state = JOB_RUNNING;
 | 
			
		||||
@@ -150,7 +161,11 @@ job_run(const char *cmd, struct session *s, const char *cwd,
 | 
			
		||||
	job->freecb = freecb;
 | 
			
		||||
	job->data = data;
 | 
			
		||||
 | 
			
		||||
	job->fd = out[0];
 | 
			
		||||
	if (~flags & JOB_PTY) {
 | 
			
		||||
		close(out[1]);
 | 
			
		||||
		job->fd = out[0];
 | 
			
		||||
	} else
 | 
			
		||||
		job->fd = master;
 | 
			
		||||
	setblocking(job->fd, 0);
 | 
			
		||||
 | 
			
		||||
	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);
 | 
			
		||||
	return (job);
 | 
			
		||||
 | 
			
		||||
fail:
 | 
			
		||||
	sigprocmask(SIG_SETMASK, &oldset, NULL);
 | 
			
		||||
	environ_free(env);
 | 
			
		||||
	return (NULL);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* 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,
 | 
			
		||||
	    (long) job->pid, len);
 | 
			
		||||
 | 
			
		||||
	if (len == 0) {
 | 
			
		||||
	if (len == 0 && (~job->flags & JOB_KEEPWRITE)) {
 | 
			
		||||
		shutdown(job->fd, SHUT_WR);
 | 
			
		||||
		bufferevent_disable(job->event, EV_WRITE);
 | 
			
		||||
	}
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user