mirror of
				https://github.com/tmux/tmux.git
				synced 2025-11-04 09:26:05 +00:00 
			
		
		
		
	Merge branch 'obsd-master'
Conflicts: cmd-pipe-pane.c proc.c tmux.c window.c
This commit is contained in:
		@@ -158,7 +158,6 @@ dist_tmux_SOURCES = \
 | 
			
		||||
	server-fn.c \
 | 
			
		||||
	server.c \
 | 
			
		||||
	session.c \
 | 
			
		||||
	signal.c \
 | 
			
		||||
	status.c \
 | 
			
		||||
	style.c \
 | 
			
		||||
	tmux.c \
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										27
									
								
								client.c
									
									
									
									
									
								
							
							
						
						
									
										27
									
								
								client.c
									
									
									
									
									
								
							@@ -63,7 +63,7 @@ static void		 client_write(int, const char *, size_t);
 | 
			
		||||
static void		 client_signal(int);
 | 
			
		||||
static void		 client_dispatch(struct imsg *, void *);
 | 
			
		||||
static void		 client_dispatch_attached(struct imsg *);
 | 
			
		||||
static void		 client_dispatch_wait(struct imsg *, const char *);
 | 
			
		||||
static void		 client_dispatch_wait(struct imsg *);
 | 
			
		||||
static const char	*client_exit_message(void);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
@@ -156,7 +156,7 @@ retry:
 | 
			
		||||
			close(lockfd);
 | 
			
		||||
			return (-1);
 | 
			
		||||
		}
 | 
			
		||||
		fd = server_start(base, lockfd, lockfile);
 | 
			
		||||
		fd = server_start(client_proc, base, lockfd, lockfile);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (locked && lockfd >= 0) {
 | 
			
		||||
@@ -214,8 +214,7 @@ client_exit_message(void)
 | 
			
		||||
 | 
			
		||||
/* Client main loop. */
 | 
			
		||||
int
 | 
			
		||||
client_main(struct event_base *base, int argc, char **argv, int flags,
 | 
			
		||||
    const char *shellcmd)
 | 
			
		||||
client_main(struct event_base *base, int argc, char **argv, int flags)
 | 
			
		||||
{
 | 
			
		||||
	struct cmd		*cmd;
 | 
			
		||||
	struct cmd_list		*cmdlist;
 | 
			
		||||
@@ -236,7 +235,7 @@ client_main(struct event_base *base, int argc, char **argv, int flags,
 | 
			
		||||
 | 
			
		||||
	/* Set up the initial command. */
 | 
			
		||||
	cmdflags = 0;
 | 
			
		||||
	if (shellcmd != NULL) {
 | 
			
		||||
	if (shell_command != NULL) {
 | 
			
		||||
		msg = MSG_SHELL;
 | 
			
		||||
		cmdflags = CMD_STARTSERVER;
 | 
			
		||||
	} else if (argc == 0) {
 | 
			
		||||
@@ -261,7 +260,8 @@ client_main(struct event_base *base, int argc, char **argv, int flags,
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Create client process structure (starts logging). */
 | 
			
		||||
	client_proc = proc_start("client", base, 0, client_signal);
 | 
			
		||||
	client_proc = proc_start("client");
 | 
			
		||||
	proc_set_signals(client_proc, client_signal);
 | 
			
		||||
 | 
			
		||||
	/* Initialize the client socket and start the server. */
 | 
			
		||||
	fd = client_connect(base, socket_path, cmdflags & CMD_STARTSERVER);
 | 
			
		||||
@@ -275,8 +275,7 @@ client_main(struct event_base *base, int argc, char **argv, int flags,
 | 
			
		||||
		}
 | 
			
		||||
		return (1);
 | 
			
		||||
	}
 | 
			
		||||
	client_peer = proc_add_peer(client_proc, fd, client_dispatch,
 | 
			
		||||
	    (void *)shellcmd);
 | 
			
		||||
	client_peer = proc_add_peer(client_proc, fd, client_dispatch, NULL);
 | 
			
		||||
 | 
			
		||||
	/* Save these before pledge(). */
 | 
			
		||||
	if ((cwd = getcwd(path, sizeof path)) == NULL) {
 | 
			
		||||
@@ -367,7 +366,7 @@ client_main(struct event_base *base, int argc, char **argv, int flags,
 | 
			
		||||
	if (client_exittype == MSG_EXEC) {
 | 
			
		||||
		if (client_flags & CLIENT_CONTROLCONTROL)
 | 
			
		||||
			tcsetattr(STDOUT_FILENO, TCSAFLUSH, &saved_tio);
 | 
			
		||||
		clear_signals(0);
 | 
			
		||||
		proc_clear_signals(client_proc);
 | 
			
		||||
		client_exec(client_execshell, client_execcmd);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
@@ -534,7 +533,7 @@ client_signal(int sig)
 | 
			
		||||
 | 
			
		||||
/* Callback for client read events. */
 | 
			
		||||
static void
 | 
			
		||||
client_dispatch(struct imsg *imsg, void *arg)
 | 
			
		||||
client_dispatch(struct imsg *imsg, __unused void *arg)
 | 
			
		||||
{
 | 
			
		||||
	if (imsg == NULL) {
 | 
			
		||||
		client_exitreason = CLIENT_EXIT_LOST_SERVER;
 | 
			
		||||
@@ -546,12 +545,12 @@ client_dispatch(struct imsg *imsg, void *arg)
 | 
			
		||||
	if (client_attached)
 | 
			
		||||
		client_dispatch_attached(imsg);
 | 
			
		||||
	else
 | 
			
		||||
		client_dispatch_wait(imsg, arg);
 | 
			
		||||
		client_dispatch_wait(imsg);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Dispatch imsgs when in wait state (before MSG_READY). */
 | 
			
		||||
static void
 | 
			
		||||
client_dispatch_wait(struct imsg *imsg, const char *shellcmd)
 | 
			
		||||
client_dispatch_wait(struct imsg *imsg)
 | 
			
		||||
{
 | 
			
		||||
	char			*data;
 | 
			
		||||
	ssize_t			 datalen;
 | 
			
		||||
@@ -630,8 +629,8 @@ client_dispatch_wait(struct imsg *imsg, const char *shellcmd)
 | 
			
		||||
		if (datalen == 0 || data[datalen - 1] != '\0')
 | 
			
		||||
			fatalx("bad MSG_SHELL string");
 | 
			
		||||
 | 
			
		||||
		clear_signals(0);
 | 
			
		||||
		client_exec(data, shellcmd);
 | 
			
		||||
		proc_clear_signals(client_proc);
 | 
			
		||||
		client_exec(data, shell_command);
 | 
			
		||||
		/* NOTREACHED */
 | 
			
		||||
	case MSG_DETACH:
 | 
			
		||||
	case MSG_DETACHKILL:
 | 
			
		||||
 
 | 
			
		||||
@@ -21,6 +21,7 @@
 | 
			
		||||
 | 
			
		||||
#include <errno.h>
 | 
			
		||||
#include <fcntl.h>
 | 
			
		||||
#include <signal.h>
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include <string.h>
 | 
			
		||||
#include <time.h>
 | 
			
		||||
@@ -61,6 +62,7 @@ cmd_pipe_pane_exec(struct cmd *self, struct cmdq_item *item)
 | 
			
		||||
	char			*cmd;
 | 
			
		||||
	int			 old_fd, pipe_fd[2], null_fd;
 | 
			
		||||
	struct format_tree	*ft;
 | 
			
		||||
	sigset_t		 set, oldset;
 | 
			
		||||
 | 
			
		||||
	/* Destroy the old pipe. */
 | 
			
		||||
	old_fd = wp->pipe_fd;
 | 
			
		||||
@@ -101,16 +103,20 @@ cmd_pipe_pane_exec(struct cmd *self, struct cmdq_item *item)
 | 
			
		||||
	format_free(ft);
 | 
			
		||||
 | 
			
		||||
	/* Fork the child. */
 | 
			
		||||
	sigfillset(&set);
 | 
			
		||||
	sigprocmask(SIG_BLOCK, &set, &oldset);
 | 
			
		||||
	switch (fork()) {
 | 
			
		||||
	case -1:
 | 
			
		||||
		sigprocmask(SIG_SETMASK, &oldset, NULL);
 | 
			
		||||
		cmdq_error(item, "fork error: %s", strerror(errno));
 | 
			
		||||
 | 
			
		||||
		free(cmd);
 | 
			
		||||
		return (CMD_RETURN_ERROR);
 | 
			
		||||
	case 0:
 | 
			
		||||
		/* Child process. */
 | 
			
		||||
		proc_clear_signals(server_proc);
 | 
			
		||||
		sigprocmask(SIG_SETMASK, &oldset, NULL);
 | 
			
		||||
		close(pipe_fd[0]);
 | 
			
		||||
		clear_signals(1);
 | 
			
		||||
 | 
			
		||||
		if (dup2(pipe_fd[1], STDIN_FILENO) == -1)
 | 
			
		||||
			_exit(1);
 | 
			
		||||
@@ -131,6 +137,7 @@ cmd_pipe_pane_exec(struct cmd *self, struct cmdq_item *item)
 | 
			
		||||
		_exit(1);
 | 
			
		||||
	default:
 | 
			
		||||
		/* Parent process. */
 | 
			
		||||
		sigprocmask(SIG_SETMASK, &oldset, NULL);
 | 
			
		||||
		close(pipe_fd[1]);
 | 
			
		||||
 | 
			
		||||
		wp->pipe_fd = pipe_fd[0];
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										11
									
								
								job.c
									
									
									
									
									
								
							
							
						
						
									
										11
									
								
								job.c
									
									
									
									
									
								
							@@ -50,6 +50,7 @@ job_run(const char *cmd, struct session *s, const char *cwd,
 | 
			
		||||
	pid_t		 pid;
 | 
			
		||||
	int		 nullfd, out[2];
 | 
			
		||||
	const char	*home;
 | 
			
		||||
	sigset_t	 set, oldset;
 | 
			
		||||
 | 
			
		||||
	if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, out) != 0)
 | 
			
		||||
		return (NULL);
 | 
			
		||||
@@ -60,14 +61,18 @@ job_run(const char *cmd, struct session *s, const char *cwd,
 | 
			
		||||
	 */
 | 
			
		||||
	env = environ_for_session(s, !cfg_finished);
 | 
			
		||||
 | 
			
		||||
	sigfillset(&set);
 | 
			
		||||
	sigprocmask(SIG_BLOCK, &set, &oldset);
 | 
			
		||||
	switch (pid = fork()) {
 | 
			
		||||
	case -1:
 | 
			
		||||
		sigprocmask(SIG_SETMASK, &oldset, NULL);
 | 
			
		||||
		environ_free(env);
 | 
			
		||||
		close(out[0]);
 | 
			
		||||
		close(out[1]);
 | 
			
		||||
		return (NULL);
 | 
			
		||||
	case 0:		/* child */
 | 
			
		||||
		clear_signals(1);
 | 
			
		||||
	case 0:
 | 
			
		||||
		proc_clear_signals(server_proc);
 | 
			
		||||
		sigprocmask(SIG_SETMASK, &oldset, NULL);
 | 
			
		||||
 | 
			
		||||
		if (cwd == NULL || chdir(cwd) != 0) {
 | 
			
		||||
			if ((home = find_home()) == NULL || chdir(home) != 0)
 | 
			
		||||
@@ -99,7 +104,7 @@ job_run(const char *cmd, struct session *s, const char *cwd,
 | 
			
		||||
		fatal("execl failed");
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* parent */
 | 
			
		||||
	sigprocmask(SIG_SETMASK, &oldset, NULL);
 | 
			
		||||
	environ_free(env);
 | 
			
		||||
	close(out[1]);
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										95
									
								
								proc.c
									
									
									
									
									
								
							
							
						
						
									
										95
									
								
								proc.c
									
									
									
									
									
								
							@@ -22,6 +22,7 @@
 | 
			
		||||
 | 
			
		||||
#include <errno.h>
 | 
			
		||||
#include <event.h>
 | 
			
		||||
#include <signal.h>
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include <string.h>
 | 
			
		||||
#include <unistd.h>
 | 
			
		||||
@@ -33,6 +34,14 @@ struct tmuxproc {
 | 
			
		||||
	int		  exit;
 | 
			
		||||
 | 
			
		||||
	void		(*signalcb)(int);
 | 
			
		||||
 | 
			
		||||
	struct event	  ev_sighup;
 | 
			
		||||
	struct event	  ev_sigchld;
 | 
			
		||||
	struct event	  ev_sigcont;
 | 
			
		||||
	struct event	  ev_sigterm;
 | 
			
		||||
	struct event	  ev_sigusr1;
 | 
			
		||||
	struct event	  ev_sigusr2;
 | 
			
		||||
	struct event	  ev_sigwinch;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct tmuxpeer {
 | 
			
		||||
@@ -159,36 +168,12 @@ proc_send(struct tmuxpeer *peer, enum msgtype type, int fd, const void *buf,
 | 
			
		||||
	return (0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int
 | 
			
		||||
proc_send_s(struct tmuxpeer *peer, enum msgtype type, const char *s)
 | 
			
		||||
{
 | 
			
		||||
	return (proc_send(peer, type, -1, s, strlen(s) + 1));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct tmuxproc *
 | 
			
		||||
proc_start(const char *name, struct event_base *base, int forkflag,
 | 
			
		||||
    void (*signalcb)(int))
 | 
			
		||||
proc_start(const char *name)
 | 
			
		||||
{
 | 
			
		||||
	struct tmuxproc	*tp;
 | 
			
		||||
	struct utsname	 u;
 | 
			
		||||
 | 
			
		||||
	if (forkflag) {
 | 
			
		||||
		switch (fork()) {
 | 
			
		||||
		case -1:
 | 
			
		||||
			fatal("fork failed");
 | 
			
		||||
		case 0:
 | 
			
		||||
			break;
 | 
			
		||||
		default:
 | 
			
		||||
			return (NULL);
 | 
			
		||||
		}
 | 
			
		||||
		if (daemon(1, 0) != 0)
 | 
			
		||||
			fatal("daemon failed");
 | 
			
		||||
 | 
			
		||||
		clear_signals(0);
 | 
			
		||||
		if (event_reinit(base) != 0)
 | 
			
		||||
			fatalx("event_reinit failed");
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	log_open(name);
 | 
			
		||||
	setproctitle("%s (%s)", name, socket_path);
 | 
			
		||||
 | 
			
		||||
@@ -203,9 +188,6 @@ proc_start(const char *name, struct event_base *base, int forkflag,
 | 
			
		||||
	tp = xcalloc(1, sizeof *tp);
 | 
			
		||||
	tp->name = xstrdup(name);
 | 
			
		||||
 | 
			
		||||
	tp->signalcb = signalcb;
 | 
			
		||||
	set_signals(proc_signal_cb, tp);
 | 
			
		||||
 | 
			
		||||
	return (tp);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -225,6 +207,63 @@ proc_exit(struct tmuxproc *tp)
 | 
			
		||||
	tp->exit = 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
proc_set_signals(struct tmuxproc *tp, void (*signalcb)(int))
 | 
			
		||||
{
 | 
			
		||||
	struct sigaction	sa;
 | 
			
		||||
 | 
			
		||||
	tp->signalcb = signalcb;
 | 
			
		||||
 | 
			
		||||
	memset(&sa, 0, sizeof sa);
 | 
			
		||||
	sigemptyset(&sa.sa_mask);
 | 
			
		||||
	sa.sa_flags = SA_RESTART;
 | 
			
		||||
	sa.sa_handler = SIG_IGN;
 | 
			
		||||
 | 
			
		||||
	sigaction(SIGINT, &sa, NULL);
 | 
			
		||||
	sigaction(SIGPIPE, &sa, NULL);
 | 
			
		||||
	sigaction(SIGUSR2, &sa, NULL);
 | 
			
		||||
	sigaction(SIGTSTP, &sa, NULL);
 | 
			
		||||
 | 
			
		||||
	signal_set(&tp->ev_sighup, SIGHUP, proc_signal_cb, tp);
 | 
			
		||||
	signal_add(&tp->ev_sighup, NULL);
 | 
			
		||||
	signal_set(&tp->ev_sigchld, SIGCHLD, proc_signal_cb, tp);
 | 
			
		||||
	signal_add(&tp->ev_sigchld, NULL);
 | 
			
		||||
	signal_set(&tp->ev_sigcont, SIGCONT, proc_signal_cb, tp);
 | 
			
		||||
	signal_add(&tp->ev_sigcont, NULL);
 | 
			
		||||
	signal_set(&tp->ev_sigterm, SIGTERM, proc_signal_cb, tp);
 | 
			
		||||
	signal_add(&tp->ev_sigterm, NULL);
 | 
			
		||||
	signal_set(&tp->ev_sigusr1, SIGUSR1, proc_signal_cb, tp);
 | 
			
		||||
	signal_add(&tp->ev_sigusr1, NULL);
 | 
			
		||||
	signal_set(&tp->ev_sigusr2, SIGUSR2, proc_signal_cb, tp);
 | 
			
		||||
	signal_add(&tp->ev_sigusr2, NULL);
 | 
			
		||||
	signal_set(&tp->ev_sigwinch, SIGWINCH, proc_signal_cb, tp);
 | 
			
		||||
	signal_add(&tp->ev_sigwinch, NULL);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
proc_clear_signals(struct tmuxproc *tp)
 | 
			
		||||
{
 | 
			
		||||
	struct sigaction	sa;
 | 
			
		||||
 | 
			
		||||
	memset(&sa, 0, sizeof sa);
 | 
			
		||||
	sigemptyset(&sa.sa_mask);
 | 
			
		||||
	sa.sa_flags = SA_RESTART;
 | 
			
		||||
	sa.sa_handler = SIG_DFL;
 | 
			
		||||
 | 
			
		||||
	sigaction(SIGINT, &sa, NULL);
 | 
			
		||||
	sigaction(SIGPIPE, &sa, NULL);
 | 
			
		||||
	sigaction(SIGUSR2, &sa, NULL);
 | 
			
		||||
	sigaction(SIGTSTP, &sa, NULL);
 | 
			
		||||
 | 
			
		||||
	event_del(&tp->ev_sighup);
 | 
			
		||||
	event_del(&tp->ev_sigchld);
 | 
			
		||||
	event_del(&tp->ev_sigcont);
 | 
			
		||||
	event_del(&tp->ev_sigterm);
 | 
			
		||||
	event_del(&tp->ev_sigusr1);
 | 
			
		||||
	event_del(&tp->ev_sigusr2);
 | 
			
		||||
	event_del(&tp->ev_sigwinch);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct tmuxpeer *
 | 
			
		||||
proc_add_peer(struct tmuxproc *tp, int fd,
 | 
			
		||||
    void (*dispatchcb)(struct imsg *, void *), void *arg)
 | 
			
		||||
 
 | 
			
		||||
@@ -369,7 +369,7 @@ server_client_detach(struct client *c, enum msgtype msgtype)
 | 
			
		||||
 | 
			
		||||
	c->flags |= CLIENT_DETACHING;
 | 
			
		||||
	notify_client("client-detached", c);
 | 
			
		||||
	proc_send_s(c->peer, msgtype, s->name);
 | 
			
		||||
	proc_send(c->peer, msgtype, -1, s->name, strlen(s->name) + 1);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Execute command to replace a client. */
 | 
			
		||||
@@ -1735,7 +1735,7 @@ server_client_dispatch_shell(struct client *c)
 | 
			
		||||
	shell = options_get_string(global_s_options, "default-shell");
 | 
			
		||||
	if (*shell == '\0' || areshell(shell))
 | 
			
		||||
		shell = _PATH_BSHELL;
 | 
			
		||||
	proc_send_s(c->peer, MSG_SHELL, shell);
 | 
			
		||||
	proc_send(c->peer, MSG_SHELL, -1, shell, strlen(shell) + 1);
 | 
			
		||||
 | 
			
		||||
	proc_kill_peer(c->peer);
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -171,7 +171,7 @@ server_lock_client(struct client *c)
 | 
			
		||||
	tty_raw(&c->tty, tty_term_string(c->tty.term, TTYC_E3));
 | 
			
		||||
 | 
			
		||||
	c->flags |= CLIENT_SUSPENDED;
 | 
			
		||||
	proc_send_s(c->peer, MSG_LOCK, cmd);
 | 
			
		||||
	proc_send(c->peer, MSG_LOCK, -1, cmd, strlen(cmd) + 1);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										23
									
								
								server.c
									
									
									
									
									
								
							
							
						
						
									
										23
									
								
								server.c
									
									
									
									
									
								
							@@ -135,20 +135,37 @@ server_create_socket(void)
 | 
			
		||||
 | 
			
		||||
/* Fork new server. */
 | 
			
		||||
int
 | 
			
		||||
server_start(struct event_base *base, int lockfd, char *lockfile)
 | 
			
		||||
server_start(struct tmuxproc *client, struct event_base *base, int lockfd,
 | 
			
		||||
    char *lockfile)
 | 
			
		||||
{
 | 
			
		||||
	int		 pair[2];
 | 
			
		||||
	struct job	*job;
 | 
			
		||||
	sigset_t	 set, oldset;
 | 
			
		||||
 | 
			
		||||
	if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, pair) != 0)
 | 
			
		||||
		fatal("socketpair failed");
 | 
			
		||||
 | 
			
		||||
	server_proc = proc_start("server", base, 1, server_signal);
 | 
			
		||||
	if (server_proc == NULL) {
 | 
			
		||||
	sigfillset(&set);
 | 
			
		||||
	sigprocmask(SIG_BLOCK, &set, &oldset);
 | 
			
		||||
	switch (fork()) {
 | 
			
		||||
	case -1:
 | 
			
		||||
		fatal("fork failed");
 | 
			
		||||
	case 0:
 | 
			
		||||
		break;
 | 
			
		||||
	default:
 | 
			
		||||
		sigprocmask(SIG_SETMASK, &oldset, NULL);
 | 
			
		||||
		close(pair[1]);
 | 
			
		||||
		return (pair[0]);
 | 
			
		||||
	}
 | 
			
		||||
	close(pair[0]);
 | 
			
		||||
	if (daemon(1, 0) != 0)
 | 
			
		||||
		fatal("daemon failed");
 | 
			
		||||
	proc_clear_signals(client);
 | 
			
		||||
	if (event_reinit(base) != 0)
 | 
			
		||||
		fatalx("event_reinit failed");
 | 
			
		||||
	server_proc = proc_start("server");
 | 
			
		||||
	proc_set_signals(server_proc, server_signal);
 | 
			
		||||
	sigprocmask(SIG_SETMASK, &oldset, NULL);
 | 
			
		||||
 | 
			
		||||
	if (log_get_level() > 1)
 | 
			
		||||
		tty_create_log();
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										111
									
								
								signal.c
									
									
									
									
									
								
							
							
						
						
									
										111
									
								
								signal.c
									
									
									
									
									
								
							@@ -1,111 +0,0 @@
 | 
			
		||||
/* $OpenBSD$ */
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
 | 
			
		||||
 * Copyright (c) 2010 Romain Francoise <rfrancoise@debian.org>
 | 
			
		||||
 *
 | 
			
		||||
 * Permission to use, copy, modify, and distribute this software for any
 | 
			
		||||
 * purpose with or without fee is hereby granted, provided that the above
 | 
			
		||||
 * copyright notice and this permission notice appear in all copies.
 | 
			
		||||
 *
 | 
			
		||||
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 | 
			
		||||
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 | 
			
		||||
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 | 
			
		||||
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 | 
			
		||||
 * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
 | 
			
		||||
 * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
 | 
			
		||||
 * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <sys/types.h>
 | 
			
		||||
 | 
			
		||||
#include <string.h>
 | 
			
		||||
#include <signal.h>
 | 
			
		||||
 | 
			
		||||
#include "tmux.h"
 | 
			
		||||
 | 
			
		||||
static struct event	ev_sighup;
 | 
			
		||||
static struct event	ev_sigchld;
 | 
			
		||||
static struct event	ev_sigcont;
 | 
			
		||||
static struct event	ev_sigterm;
 | 
			
		||||
static struct event	ev_sigusr1;
 | 
			
		||||
static struct event	ev_sigusr2;
 | 
			
		||||
static struct event	ev_sigwinch;
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
set_signals(void (*handler)(int, short, void *), void *arg)
 | 
			
		||||
{
 | 
			
		||||
	struct sigaction	sigact;
 | 
			
		||||
 | 
			
		||||
	memset(&sigact, 0, sizeof sigact);
 | 
			
		||||
	sigemptyset(&sigact.sa_mask);
 | 
			
		||||
	sigact.sa_flags = SA_RESTART;
 | 
			
		||||
	sigact.sa_handler = SIG_IGN;
 | 
			
		||||
	if (sigaction(SIGINT, &sigact, NULL) != 0)
 | 
			
		||||
		fatal("sigaction failed");
 | 
			
		||||
	if (sigaction(SIGPIPE, &sigact, NULL) != 0)
 | 
			
		||||
		fatal("sigaction failed");
 | 
			
		||||
	if (sigaction(SIGUSR2, &sigact, NULL) != 0)
 | 
			
		||||
		fatal("sigaction failed");
 | 
			
		||||
	if (sigaction(SIGTSTP, &sigact, NULL) != 0)
 | 
			
		||||
		fatal("sigaction failed");
 | 
			
		||||
 | 
			
		||||
	signal_set(&ev_sighup, SIGHUP, handler, arg);
 | 
			
		||||
	signal_add(&ev_sighup, NULL);
 | 
			
		||||
	signal_set(&ev_sigchld, SIGCHLD, handler, arg);
 | 
			
		||||
	signal_add(&ev_sigchld, NULL);
 | 
			
		||||
	signal_set(&ev_sigcont, SIGCONT, handler, arg);
 | 
			
		||||
	signal_add(&ev_sigcont, NULL);
 | 
			
		||||
	signal_set(&ev_sigterm, SIGTERM, handler, arg);
 | 
			
		||||
	signal_add(&ev_sigterm, NULL);
 | 
			
		||||
	signal_set(&ev_sigusr1, SIGUSR1, handler, arg);
 | 
			
		||||
	signal_add(&ev_sigusr1, NULL);
 | 
			
		||||
	signal_set(&ev_sigusr2, SIGUSR2, handler, arg);
 | 
			
		||||
	signal_add(&ev_sigusr2, NULL);
 | 
			
		||||
	signal_set(&ev_sigwinch, SIGWINCH, handler, arg);
 | 
			
		||||
	signal_add(&ev_sigwinch, NULL);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
clear_signals(int after_fork)
 | 
			
		||||
{
 | 
			
		||||
	struct sigaction	sigact;
 | 
			
		||||
 | 
			
		||||
	memset(&sigact, 0, sizeof sigact);
 | 
			
		||||
	sigemptyset(&sigact.sa_mask);
 | 
			
		||||
	sigact.sa_flags = SA_RESTART;
 | 
			
		||||
	sigact.sa_handler = SIG_DFL;
 | 
			
		||||
	if (sigaction(SIGINT, &sigact, NULL) != 0)
 | 
			
		||||
		fatal("sigaction failed");
 | 
			
		||||
	if (sigaction(SIGPIPE, &sigact, NULL) != 0)
 | 
			
		||||
		fatal("sigaction failed");
 | 
			
		||||
	if (sigaction(SIGUSR2, &sigact, NULL) != 0)
 | 
			
		||||
		fatal("sigaction failed");
 | 
			
		||||
	if (sigaction(SIGTSTP, &sigact, NULL) != 0)
 | 
			
		||||
		fatal("sigaction failed");
 | 
			
		||||
 | 
			
		||||
	if (after_fork) {
 | 
			
		||||
		if (sigaction(SIGHUP, &sigact, NULL) != 0)
 | 
			
		||||
			fatal("sigaction failed");
 | 
			
		||||
		if (sigaction(SIGCHLD, &sigact, NULL) != 0)
 | 
			
		||||
			fatal("sigaction failed");
 | 
			
		||||
		if (sigaction(SIGCONT, &sigact, NULL) != 0)
 | 
			
		||||
			fatal("sigaction failed");
 | 
			
		||||
		if (sigaction(SIGTERM, &sigact, NULL) != 0)
 | 
			
		||||
			fatal("sigaction failed");
 | 
			
		||||
		if (sigaction(SIGUSR1, &sigact, NULL) != 0)
 | 
			
		||||
			fatal("sigaction failed");
 | 
			
		||||
		if (sigaction(SIGUSR2, &sigact, NULL) != 0)
 | 
			
		||||
			fatal("sigaction failed");
 | 
			
		||||
		if (sigaction(SIGWINCH, &sigact, NULL) != 0)
 | 
			
		||||
			fatal("sigaction failed");
 | 
			
		||||
	} else {
 | 
			
		||||
		event_del(&ev_sighup);
 | 
			
		||||
		event_del(&ev_sigchld);
 | 
			
		||||
		event_del(&ev_sigcont);
 | 
			
		||||
		event_del(&ev_sigterm);
 | 
			
		||||
		event_del(&ev_sigusr1);
 | 
			
		||||
		event_del(&ev_sigusr2);
 | 
			
		||||
		event_del(&ev_sigwinch);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										12
									
								
								tmux.c
									
									
									
									
									
								
							
							
						
						
									
										12
									
								
								tmux.c
									
									
									
									
									
								
							@@ -41,6 +41,7 @@ struct hooks	*global_hooks;
 | 
			
		||||
struct timeval	 start_time;
 | 
			
		||||
const char	*socket_path;
 | 
			
		||||
int		 ptm_fd = -1;
 | 
			
		||||
const char	*shell_command;
 | 
			
		||||
 | 
			
		||||
static __dead void	 usage(void);
 | 
			
		||||
static char		*make_label(const char *);
 | 
			
		||||
@@ -187,8 +188,8 @@ find_home(void)
 | 
			
		||||
int
 | 
			
		||||
main(int argc, char **argv)
 | 
			
		||||
{
 | 
			
		||||
	char					*path, *label, tmp[PATH_MAX];
 | 
			
		||||
	char					*shellcmd = NULL, **var;
 | 
			
		||||
	char					*path, *label, **var;
 | 
			
		||||
	char					 tmp[PATH_MAX];
 | 
			
		||||
	const char				*s, *shell;
 | 
			
		||||
	int					 opt, flags, keys;
 | 
			
		||||
	const struct options_table_entry	*oe;
 | 
			
		||||
@@ -217,8 +218,7 @@ main(int argc, char **argv)
 | 
			
		||||
			flags |= CLIENT_256COLOURS;
 | 
			
		||||
			break;
 | 
			
		||||
		case 'c':
 | 
			
		||||
			free(shellcmd);
 | 
			
		||||
			shellcmd = xstrdup(optarg);
 | 
			
		||||
			shell_command = optarg;
 | 
			
		||||
			break;
 | 
			
		||||
		case 'C':
 | 
			
		||||
			if (flags & CLIENT_CONTROL)
 | 
			
		||||
@@ -258,7 +258,7 @@ main(int argc, char **argv)
 | 
			
		||||
	argc -= optind;
 | 
			
		||||
	argv += optind;
 | 
			
		||||
 | 
			
		||||
	if (shellcmd != NULL && argc != 0)
 | 
			
		||||
	if (shell_command != NULL && argc != 0)
 | 
			
		||||
		usage();
 | 
			
		||||
 | 
			
		||||
	if ((ptm_fd = getptmfd()) == -1)
 | 
			
		||||
@@ -348,5 +348,5 @@ main(int argc, char **argv)
 | 
			
		||||
	free(label);
 | 
			
		||||
 | 
			
		||||
	/* Pass control to the client. */
 | 
			
		||||
	exit(client_main(osdep_event_init(), argc, argv, flags, shellcmd));
 | 
			
		||||
	exit(client_main(osdep_event_init(), argc, argv, flags));
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										16
									
								
								tmux.h
									
									
									
									
									
								
							
							
						
						
									
										16
									
								
								tmux.h
									
									
									
									
									
								
							@@ -1489,7 +1489,9 @@ extern struct options	*global_w_options;
 | 
			
		||||
extern struct environ	*global_environ;
 | 
			
		||||
extern struct timeval	 start_time;
 | 
			
		||||
extern const char	*socket_path;
 | 
			
		||||
extern const char	*shell_command;
 | 
			
		||||
extern int		 ptm_fd;
 | 
			
		||||
extern const char	*shell_command;
 | 
			
		||||
int		 areshell(const char *);
 | 
			
		||||
void		 setblocking(int, int);
 | 
			
		||||
const char	*find_home(void);
 | 
			
		||||
@@ -1497,11 +1499,11 @@ const char	*find_home(void);
 | 
			
		||||
/* proc.c */
 | 
			
		||||
struct imsg;
 | 
			
		||||
int	proc_send(struct tmuxpeer *, enum msgtype, int, const void *, size_t);
 | 
			
		||||
int	proc_send_s(struct tmuxpeer *, enum msgtype, const char *);
 | 
			
		||||
struct tmuxproc *proc_start(const char *, struct event_base *, int,
 | 
			
		||||
	    void (*)(int));
 | 
			
		||||
struct tmuxproc *proc_start(const char *);
 | 
			
		||||
void	proc_loop(struct tmuxproc *, int (*)(void));
 | 
			
		||||
void	proc_exit(struct tmuxproc *);
 | 
			
		||||
void	proc_set_signals(struct tmuxproc *, void(*)(int));
 | 
			
		||||
void	proc_clear_signals(struct tmuxproc *);
 | 
			
		||||
struct tmuxpeer *proc_add_peer(struct tmuxproc *, int,
 | 
			
		||||
	    void (*)(struct imsg *, void *), void *);
 | 
			
		||||
void	proc_remove_peer(struct tmuxpeer *);
 | 
			
		||||
@@ -1825,7 +1827,7 @@ struct cmd_list	*cmd_string_parse(const char *, const char *, u_int, char **);
 | 
			
		||||
void	cmd_wait_for_flush(void);
 | 
			
		||||
 | 
			
		||||
/* client.c */
 | 
			
		||||
int	client_main(struct event_base *, int, char **, int, const char *);
 | 
			
		||||
int	client_main(struct event_base *, int, char **, int);
 | 
			
		||||
 | 
			
		||||
/* key-bindings.c */
 | 
			
		||||
RB_PROTOTYPE(key_bindings, key_binding, entry, key_bindings_cmp);
 | 
			
		||||
@@ -1861,7 +1863,7 @@ void	 server_clear_marked(void);
 | 
			
		||||
int	 server_is_marked(struct session *, struct winlink *,
 | 
			
		||||
	     struct window_pane *);
 | 
			
		||||
int	 server_check_marked(void);
 | 
			
		||||
int	 server_start(struct event_base *, int, char *);
 | 
			
		||||
int	 server_start(struct tmuxproc *, struct event_base *, int, char *);
 | 
			
		||||
void	 server_update_socket(void);
 | 
			
		||||
void	 server_add_accept(int);
 | 
			
		||||
 | 
			
		||||
@@ -2261,10 +2263,6 @@ void	 check_window_name(struct window *);
 | 
			
		||||
char	*default_window_name(struct window *);
 | 
			
		||||
char	*parse_window_name(const char *);
 | 
			
		||||
 | 
			
		||||
/* signal.c */
 | 
			
		||||
void	set_signals(void(*)(int, short, void *), void *);
 | 
			
		||||
void	clear_signals(int);
 | 
			
		||||
 | 
			
		||||
/* control.c */
 | 
			
		||||
void	control_callback(struct client *, int, void *);
 | 
			
		||||
void printflike(2, 3) control_write(struct client *, const char *, ...);
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										17
									
								
								window.c
									
									
									
									
									
								
							
							
						
						
									
										17
									
								
								window.c
									
									
									
									
									
								
							@@ -891,6 +891,7 @@ window_pane_spawn(struct window_pane *wp, int argc, char **argv,
 | 
			
		||||
	char		 s[32];
 | 
			
		||||
#endif
 | 
			
		||||
	int		 i;
 | 
			
		||||
	sigset_t	 set, oldset;
 | 
			
		||||
 | 
			
		||||
	if (wp->fd != -1) {
 | 
			
		||||
		bufferevent_free(wp->event);
 | 
			
		||||
@@ -920,14 +921,21 @@ window_pane_spawn(struct window_pane *wp, int argc, char **argv,
 | 
			
		||||
	ws.ws_col = screen_size_x(&wp->base);
 | 
			
		||||
	ws.ws_row = screen_size_y(&wp->base);
 | 
			
		||||
 | 
			
		||||
	wp->pid = fdforkpty(ptm_fd, &wp->fd, wp->tty, NULL, &ws);
 | 
			
		||||
	switch (wp->pid) {
 | 
			
		||||
	sigfillset(&set);
 | 
			
		||||
	sigprocmask(SIG_BLOCK, &set, &oldset);
 | 
			
		||||
	switch (wp->pid = fdforkpty(ptm_fd, &wp->fd, wp->tty, NULL, &ws)) {
 | 
			
		||||
	case -1:
 | 
			
		||||
		wp->fd = -1;
 | 
			
		||||
 | 
			
		||||
		xasprintf(cause, "%s: %s", cmd, strerror(errno));
 | 
			
		||||
		free(cmd);
 | 
			
		||||
 | 
			
		||||
		sigprocmask(SIG_SETMASK, &oldset, NULL);
 | 
			
		||||
		return (-1);
 | 
			
		||||
	case 0:
 | 
			
		||||
		proc_clear_signals(server_proc);
 | 
			
		||||
		sigprocmask(SIG_SETMASK, &oldset, NULL);
 | 
			
		||||
 | 
			
		||||
		if (chdir(wp->cwd) != 0) {
 | 
			
		||||
			if ((home = find_home()) == NULL || chdir(home) != 0)
 | 
			
		||||
				chdir("/");
 | 
			
		||||
@@ -944,6 +952,7 @@ window_pane_spawn(struct window_pane *wp, int argc, char **argv,
 | 
			
		||||
		if (tcsetattr(STDIN_FILENO, TCSANOW, &tio2) != 0)
 | 
			
		||||
			fatal("tcgetattr failed");
 | 
			
		||||
 | 
			
		||||
		log_close();
 | 
			
		||||
		closefrom(STDERR_FILENO + 1);
 | 
			
		||||
 | 
			
		||||
		if (path != NULL)
 | 
			
		||||
@@ -951,9 +960,6 @@ window_pane_spawn(struct window_pane *wp, int argc, char **argv,
 | 
			
		||||
		environ_set(env, "TMUX_PANE", "%%%u", wp->id);
 | 
			
		||||
		environ_push(env);
 | 
			
		||||
 | 
			
		||||
		clear_signals(1);
 | 
			
		||||
		log_close();
 | 
			
		||||
 | 
			
		||||
		setenv("SHELL", wp->shell, 1);
 | 
			
		||||
		ptr = strrchr(wp->shell, '/');
 | 
			
		||||
 | 
			
		||||
@@ -992,6 +998,7 @@ window_pane_spawn(struct window_pane *wp, int argc, char **argv,
 | 
			
		||||
	kill(getpid(), SIGCHLD);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
	sigprocmask(SIG_SETMASK, &oldset, NULL);
 | 
			
		||||
	setblocking(wp->fd, 0);
 | 
			
		||||
 | 
			
		||||
	wp->event = bufferevent_new(wp->fd, window_pane_read_callback, NULL,
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user