mirror of
				https://github.com/tmux/tmux.git
				synced 2025-11-04 00:56:10 +00:00 
			
		
		
		
	Merge branch 'obsd-master'
Conflicts: log.c proc.c tmux.c
This commit is contained in:
		
							
								
								
									
										94
									
								
								client.c
									
									
									
									
									
								
							
							
						
						
									
										94
									
								
								client.c
									
									
									
									
									
								
							@@ -52,33 +52,35 @@ enum msgtype	 client_exittype;
 | 
			
		||||
const char	*client_exitsession;
 | 
			
		||||
int		 client_attached;
 | 
			
		||||
 | 
			
		||||
__dead void	client_exec(const char *);
 | 
			
		||||
__dead void	client_exec(const char *,const char *);
 | 
			
		||||
int		client_get_lock(char *);
 | 
			
		||||
int		client_connect(struct event_base *, char *, int);
 | 
			
		||||
int		client_connect(struct event_base *, const char *, int);
 | 
			
		||||
void		client_send_identify(const char *, const char *);
 | 
			
		||||
void		client_stdin_callback(int, short, void *);
 | 
			
		||||
void		client_write(int, const char *, size_t);
 | 
			
		||||
void		client_signal(int);
 | 
			
		||||
void		client_dispatch(struct imsg *, void *);
 | 
			
		||||
void		client_dispatch_attached(struct imsg *);
 | 
			
		||||
void		client_dispatch_wait(struct imsg *);
 | 
			
		||||
void		client_dispatch_wait(struct imsg *, const char *);
 | 
			
		||||
const char     *client_exit_message(void);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Get server create lock. If already held then server start is happening in
 | 
			
		||||
 * another client, so block until the lock is released and return -1 to
 | 
			
		||||
 * retry. Ignore other errors - just continue and start the server without the
 | 
			
		||||
 * lock.
 | 
			
		||||
 * another client, so block until the lock is released and return -2 to
 | 
			
		||||
 * retry. Return -1 on failure to continue and start the server anyway.
 | 
			
		||||
 */
 | 
			
		||||
int
 | 
			
		||||
client_get_lock(char *lockfile)
 | 
			
		||||
{
 | 
			
		||||
	int lockfd;
 | 
			
		||||
 | 
			
		||||
	if ((lockfd = open(lockfile, O_WRONLY|O_CREAT, 0600)) == -1)
 | 
			
		||||
		fatal("open failed");
 | 
			
		||||
	log_debug("lock file is %s", lockfile);
 | 
			
		||||
 | 
			
		||||
	if ((lockfd = open(lockfile, O_WRONLY|O_CREAT, 0600)) == -1) {
 | 
			
		||||
		log_debug("open failed: %s", strerror(errno));
 | 
			
		||||
		return (-1);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (flock(lockfd, LOCK_EX|LOCK_NB) == -1) {
 | 
			
		||||
		log_debug("flock failed: %s", strerror(errno));
 | 
			
		||||
		if (errno != EAGAIN)
 | 
			
		||||
@@ -86,7 +88,7 @@ client_get_lock(char *lockfile)
 | 
			
		||||
		while (flock(lockfd, LOCK_EX) == -1 && errno == EINTR)
 | 
			
		||||
			/* nothing */;
 | 
			
		||||
		close(lockfd);
 | 
			
		||||
		return (-1);
 | 
			
		||||
		return (-2);
 | 
			
		||||
	}
 | 
			
		||||
	log_debug("flock succeeded");
 | 
			
		||||
 | 
			
		||||
@@ -95,7 +97,7 @@ client_get_lock(char *lockfile)
 | 
			
		||||
 | 
			
		||||
/* Connect client to server. */
 | 
			
		||||
int
 | 
			
		||||
client_connect(struct event_base *base, char *path, int start_server)
 | 
			
		||||
client_connect(struct event_base *base, const char *path, int start_server)
 | 
			
		||||
{
 | 
			
		||||
	struct sockaddr_un	sa;
 | 
			
		||||
	size_t			size;
 | 
			
		||||
@@ -113,10 +115,10 @@ client_connect(struct event_base *base, char *path, int start_server)
 | 
			
		||||
 | 
			
		||||
retry:
 | 
			
		||||
	if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1)
 | 
			
		||||
		fatal("socket failed");
 | 
			
		||||
		return (-1);
 | 
			
		||||
 | 
			
		||||
	log_debug("trying connect");
 | 
			
		||||
	if (connect(fd, (struct sockaddr *) &sa, sizeof(sa)) == -1) {
 | 
			
		||||
	if (connect(fd, (struct sockaddr *)&sa, sizeof sa) == -1) {
 | 
			
		||||
		log_debug("connect failed: %s", strerror(errno));
 | 
			
		||||
		if (errno != ECONNREFUSED && errno != ENOENT)
 | 
			
		||||
			goto failed;
 | 
			
		||||
@@ -126,12 +128,16 @@ retry:
 | 
			
		||||
 | 
			
		||||
		if (!locked) {
 | 
			
		||||
			xasprintf(&lockfile, "%s.lock", path);
 | 
			
		||||
			if ((lockfd = client_get_lock(lockfile)) == -1) {
 | 
			
		||||
				log_debug("didn't get lock");
 | 
			
		||||
			if ((lockfd = client_get_lock(lockfile)) < 0) {
 | 
			
		||||
				log_debug("didn't get lock (%d)", lockfd);
 | 
			
		||||
 | 
			
		||||
				free(lockfile);
 | 
			
		||||
				goto retry;
 | 
			
		||||
				lockfile = NULL;
 | 
			
		||||
 | 
			
		||||
				if (lockfd == -2)
 | 
			
		||||
					goto retry;
 | 
			
		||||
			}
 | 
			
		||||
			log_debug("got lock");
 | 
			
		||||
			log_debug("got lock (%d)", lockfd);
 | 
			
		||||
 | 
			
		||||
			/*
 | 
			
		||||
			 * Always retry at least once, even if we got the lock,
 | 
			
		||||
@@ -143,7 +149,7 @@ retry:
 | 
			
		||||
			goto retry;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (unlink(path) != 0 && errno != ENOENT) {
 | 
			
		||||
		if (lockfd >= 0 && unlink(path) != 0 && errno != ENOENT) {
 | 
			
		||||
			free(lockfile);
 | 
			
		||||
			close(lockfd);
 | 
			
		||||
			return (-1);
 | 
			
		||||
@@ -151,7 +157,7 @@ retry:
 | 
			
		||||
		fd = server_start(base, lockfd, lockfile);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (locked) {
 | 
			
		||||
	if (locked && lockfd >= 0) {
 | 
			
		||||
		free(lockfile);
 | 
			
		||||
		close(lockfd);
 | 
			
		||||
	}
 | 
			
		||||
@@ -206,7 +212,8 @@ client_exit_message(void)
 | 
			
		||||
 | 
			
		||||
/* Client main loop. */
 | 
			
		||||
int
 | 
			
		||||
client_main(struct event_base *base, int argc, char **argv, int flags)
 | 
			
		||||
client_main(struct event_base *base, int argc, char **argv, int flags,
 | 
			
		||||
    const char *shellcmd)
 | 
			
		||||
{
 | 
			
		||||
	struct cmd		*cmd;
 | 
			
		||||
	struct cmd_list		*cmdlist;
 | 
			
		||||
@@ -227,7 +234,7 @@ client_main(struct event_base *base, int argc, char **argv, int flags)
 | 
			
		||||
 | 
			
		||||
	/* Set up the initial command. */
 | 
			
		||||
	cmdflags = 0;
 | 
			
		||||
	if (shell_cmd != NULL) {
 | 
			
		||||
	if (shellcmd != NULL) {
 | 
			
		||||
		msg = MSG_SHELL;
 | 
			
		||||
		cmdflags = CMD_STARTSERVER;
 | 
			
		||||
	} else if (argc == 0) {
 | 
			
		||||
@@ -254,6 +261,9 @@ client_main(struct event_base *base, int argc, char **argv, int flags)
 | 
			
		||||
		cmd_list_free(cmdlist);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Create client process structure (starts logging). */
 | 
			
		||||
	client_proc = proc_start("client", base, 0, client_signal);
 | 
			
		||||
 | 
			
		||||
	/* Initialize the client socket and start the server. */
 | 
			
		||||
	fd = client_connect(base, socket_path, cmdflags & CMD_STARTSERVER);
 | 
			
		||||
	if (fd == -1) {
 | 
			
		||||
@@ -266,10 +276,8 @@ client_main(struct event_base *base, int argc, char **argv, int flags)
 | 
			
		||||
		}
 | 
			
		||||
		return (1);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Build process state. */
 | 
			
		||||
	client_proc = proc_start("client", base, 0, client_signal);
 | 
			
		||||
	client_peer = proc_add_peer(client_proc, fd, client_dispatch, NULL);
 | 
			
		||||
	client_peer = proc_add_peer(client_proc, fd, client_dispatch,
 | 
			
		||||
	    (void *)shellcmd);
 | 
			
		||||
 | 
			
		||||
	/* Save these before pledge(). */
 | 
			
		||||
	if ((cwd = getcwd(path, sizeof path)) == NULL) {
 | 
			
		||||
@@ -304,11 +312,8 @@ client_main(struct event_base *base, int argc, char **argv, int flags)
 | 
			
		||||
	event_set(&client_stdin, STDIN_FILENO, EV_READ|EV_PERSIST,
 | 
			
		||||
	    client_stdin_callback, NULL);
 | 
			
		||||
	if (client_flags & CLIENT_CONTROLCONTROL) {
 | 
			
		||||
		if (tcgetattr(STDIN_FILENO, &saved_tio) != 0) {
 | 
			
		||||
			fprintf(stderr, "tcgetattr failed: %s\n",
 | 
			
		||||
			    strerror(errno));
 | 
			
		||||
			return (1);
 | 
			
		||||
		}
 | 
			
		||||
		if (tcgetattr(STDIN_FILENO, &saved_tio) != 0)
 | 
			
		||||
			fatal("tcgetattr failed");
 | 
			
		||||
		cfmakeraw(&tio);
 | 
			
		||||
		tio.c_iflag = ICRNL|IXANY;
 | 
			
		||||
		tio.c_oflag = OPOST|ONLCR;
 | 
			
		||||
@@ -371,7 +376,8 @@ client_main(struct event_base *base, int argc, char **argv, int flags)
 | 
			
		||||
			printf("%%exit\n");
 | 
			
		||||
		printf("\033\\");
 | 
			
		||||
		tcsetattr(STDOUT_FILENO, TCSAFLUSH, &saved_tio);
 | 
			
		||||
	}
 | 
			
		||||
	} else if (client_exitreason != CLIENT_EXIT_NONE)
 | 
			
		||||
		fprintf(stderr, "%s\n", client_exit_message());
 | 
			
		||||
	setblocking(STDIN_FILENO, 1);
 | 
			
		||||
	return (client_exitval);
 | 
			
		||||
}
 | 
			
		||||
@@ -392,7 +398,8 @@ client_send_identify(const char *ttynam, const char *cwd)
 | 
			
		||||
		s = "";
 | 
			
		||||
	proc_send(client_peer, MSG_IDENTIFY_TERM, -1, s, strlen(s) + 1);
 | 
			
		||||
 | 
			
		||||
	proc_send(client_peer, MSG_IDENTIFY_TTYNAME, -1, ttynam, strlen(ttynam) + 1);
 | 
			
		||||
	proc_send(client_peer, MSG_IDENTIFY_TTYNAME, -1, ttynam,
 | 
			
		||||
	    strlen(ttynam) + 1);
 | 
			
		||||
	proc_send(client_peer, MSG_IDENTIFY_CWD, -1, cwd, strlen(cwd) + 1);
 | 
			
		||||
 | 
			
		||||
	if ((fd = dup(STDIN_FILENO)) == -1)
 | 
			
		||||
@@ -404,8 +411,9 @@ client_send_identify(const char *ttynam, const char *cwd)
 | 
			
		||||
 | 
			
		||||
	for (ss = environ; *ss != NULL; ss++) {
 | 
			
		||||
		sslen = strlen(*ss) + 1;
 | 
			
		||||
		if (sslen <= MAX_IMSGSIZE - IMSG_HEADER_SIZE)
 | 
			
		||||
			proc_send(client_peer, MSG_IDENTIFY_ENVIRON, -1, *ss, sslen);
 | 
			
		||||
		if (sslen > MAX_IMSGSIZE - IMSG_HEADER_SIZE)
 | 
			
		||||
			continue;
 | 
			
		||||
		proc_send(client_peer, MSG_IDENTIFY_ENVIRON, -1, *ss, sslen);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	proc_send(client_peer, MSG_IDENTIFY_DONE, -1, NULL, 0);
 | 
			
		||||
@@ -447,12 +455,12 @@ client_write(int fd, const char *data, size_t size)
 | 
			
		||||
 | 
			
		||||
/* Run command in shell; used for -c. */
 | 
			
		||||
__dead void
 | 
			
		||||
client_exec(const char *shell)
 | 
			
		||||
client_exec(const char *shell, const char *shellcmd)
 | 
			
		||||
{
 | 
			
		||||
	const char	*name, *ptr;
 | 
			
		||||
	char		*argv0;
 | 
			
		||||
 | 
			
		||||
	log_debug("shell %s, command %s", shell, shell_cmd);
 | 
			
		||||
	log_debug("shell %s, command %s", shell, shellcmd);
 | 
			
		||||
 | 
			
		||||
	ptr = strrchr(shell, '/');
 | 
			
		||||
	if (ptr != NULL && *(ptr + 1) != '\0')
 | 
			
		||||
@@ -470,7 +478,7 @@ client_exec(const char *shell)
 | 
			
		||||
	setblocking(STDERR_FILENO, 1);
 | 
			
		||||
	closefrom(STDERR_FILENO + 1);
 | 
			
		||||
 | 
			
		||||
	execl(shell, argv0, "-c", shell_cmd, (char *) NULL);
 | 
			
		||||
	execl(shell, argv0, "-c", shellcmd, (char *) NULL);
 | 
			
		||||
	fatal("execl failed");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -516,20 +524,24 @@ client_signal(int sig)
 | 
			
		||||
 | 
			
		||||
/* Callback for client read events. */
 | 
			
		||||
void
 | 
			
		||||
client_dispatch(struct imsg *imsg, __unused void *arg)
 | 
			
		||||
client_dispatch(struct imsg *imsg, void *arg)
 | 
			
		||||
{
 | 
			
		||||
	if (imsg == NULL) {
 | 
			
		||||
		client_exitreason = CLIENT_EXIT_LOST_SERVER;
 | 
			
		||||
		client_exitval = 1;
 | 
			
		||||
	} else if (client_attached)
 | 
			
		||||
		proc_exit(client_proc);
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (client_attached)
 | 
			
		||||
		client_dispatch_attached(imsg);
 | 
			
		||||
	else
 | 
			
		||||
		client_dispatch_wait(imsg);
 | 
			
		||||
		client_dispatch_wait(imsg, arg);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Dispatch imsgs when in wait state (before MSG_READY). */
 | 
			
		||||
void
 | 
			
		||||
client_dispatch_wait(struct imsg *imsg)
 | 
			
		||||
client_dispatch_wait(struct imsg *imsg, const char *shellcmd)
 | 
			
		||||
{
 | 
			
		||||
	char			*data;
 | 
			
		||||
	ssize_t			 datalen;
 | 
			
		||||
@@ -611,7 +623,7 @@ client_dispatch_wait(struct imsg *imsg)
 | 
			
		||||
			fatalx("bad MSG_SHELL string");
 | 
			
		||||
 | 
			
		||||
		clear_signals(0);
 | 
			
		||||
		client_exec(data);
 | 
			
		||||
		client_exec(data, shellcmd);
 | 
			
		||||
		/* NOTREACHED */
 | 
			
		||||
	case MSG_DETACH:
 | 
			
		||||
	case MSG_DETACHKILL:
 | 
			
		||||
 
 | 
			
		||||
@@ -31,7 +31,7 @@ enum cmd_retval	 cmd_detach_client_exec(struct cmd *, struct cmd_q *);
 | 
			
		||||
const struct cmd_entry cmd_detach_client_entry = {
 | 
			
		||||
	"detach-client", "detach",
 | 
			
		||||
	"as:t:P", 0, 0,
 | 
			
		||||
	"[-P] [-a] [-s target-session] " CMD_TARGET_CLIENT_USAGE,
 | 
			
		||||
	"[-aP] [-s target-session] " CMD_TARGET_CLIENT_USAGE,
 | 
			
		||||
	CMD_READONLY,
 | 
			
		||||
	cmd_detach_client_exec
 | 
			
		||||
};
 | 
			
		||||
 
 | 
			
		||||
@@ -31,8 +31,8 @@ enum cmd_retval	 cmd_kill_session_exec(struct cmd *, struct cmd_q *);
 | 
			
		||||
 | 
			
		||||
const struct cmd_entry cmd_kill_session_entry = {
 | 
			
		||||
	"kill-session", NULL,
 | 
			
		||||
	"at:", 0, 0,
 | 
			
		||||
	"[-a] " CMD_TARGET_SESSION_USAGE,
 | 
			
		||||
	"aCt:", 0, 0,
 | 
			
		||||
	"[-aC] " CMD_TARGET_SESSION_USAGE,
 | 
			
		||||
	0,
 | 
			
		||||
	cmd_kill_session_exec
 | 
			
		||||
};
 | 
			
		||||
@@ -42,11 +42,18 @@ cmd_kill_session_exec(struct cmd *self, struct cmd_q *cmdq)
 | 
			
		||||
{
 | 
			
		||||
	struct args	*args = self->args;
 | 
			
		||||
	struct session	*s, *sloop, *stmp;
 | 
			
		||||
	struct winlink	*wl;
 | 
			
		||||
 | 
			
		||||
	if ((s = cmd_find_session(cmdq, args_get(args, 't'), 0)) == NULL)
 | 
			
		||||
		return (CMD_RETURN_ERROR);
 | 
			
		||||
 | 
			
		||||
	if (args_has(args, 'a')) {
 | 
			
		||||
	if (args_has(args, 'C')) {
 | 
			
		||||
		RB_FOREACH(wl, winlinks, &s->windows) {
 | 
			
		||||
			wl->window->flags &= ~WINDOW_ALERTFLAGS;
 | 
			
		||||
			wl->flags &= ~WINLINK_ALERTFLAGS;
 | 
			
		||||
		}
 | 
			
		||||
		server_redraw_session(s);
 | 
			
		||||
	} else if (args_has(args, 'a')) {
 | 
			
		||||
		RB_FOREACH_SAFE(sloop, sessions, &sessions, stmp) {
 | 
			
		||||
			if (sloop != s) {
 | 
			
		||||
				server_destroy_session(sloop);
 | 
			
		||||
 
 | 
			
		||||
@@ -79,13 +79,13 @@ cmd_set_environment_exec(struct cmd *self, struct cmd_q *cmdq)
 | 
			
		||||
			cmdq_error(cmdq, "can't specify a value with -r");
 | 
			
		||||
			return (CMD_RETURN_ERROR);
 | 
			
		||||
		}
 | 
			
		||||
		environ_set(env, name, NULL);
 | 
			
		||||
		environ_clear(env, name);
 | 
			
		||||
	} else {
 | 
			
		||||
		if (value == NULL) {
 | 
			
		||||
			cmdq_error(cmdq, "no value specified");
 | 
			
		||||
			return (CMD_RETURN_ERROR);
 | 
			
		||||
		}
 | 
			
		||||
		environ_set(env, name, value);
 | 
			
		||||
		environ_set(env, name, "%s", value);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return (CMD_RETURN_NORMAL);
 | 
			
		||||
 
 | 
			
		||||
@@ -32,8 +32,8 @@ enum cmd_retval	 cmd_show_messages_exec(struct cmd *, struct cmd_q *);
 | 
			
		||||
 | 
			
		||||
const struct cmd_entry cmd_show_messages_entry = {
 | 
			
		||||
	"show-messages", "showmsgs",
 | 
			
		||||
	"IJTt:", 0, 0,
 | 
			
		||||
	"[-IJT] " CMD_TARGET_CLIENT_USAGE,
 | 
			
		||||
	"JTt:", 0, 0,
 | 
			
		||||
	"[-JT] " CMD_TARGET_CLIENT_USAGE,
 | 
			
		||||
	0,
 | 
			
		||||
	cmd_show_messages_exec
 | 
			
		||||
};
 | 
			
		||||
@@ -46,26 +46,9 @@ const struct cmd_entry cmd_server_info_entry = {
 | 
			
		||||
	cmd_show_messages_exec
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
int	cmd_show_messages_server(struct cmd_q *);
 | 
			
		||||
int	cmd_show_messages_terminals(struct cmd_q *, int);
 | 
			
		||||
int	cmd_show_messages_jobs(struct cmd_q *, int);
 | 
			
		||||
 | 
			
		||||
int
 | 
			
		||||
cmd_show_messages_server(struct cmd_q *cmdq)
 | 
			
		||||
{
 | 
			
		||||
	char	*tim;
 | 
			
		||||
 | 
			
		||||
	tim = ctime(&start_time);
 | 
			
		||||
	*strchr(tim, '\n') = '\0';
 | 
			
		||||
 | 
			
		||||
	cmdq_print(cmdq, "started %s", tim);
 | 
			
		||||
	cmdq_print(cmdq, "socket path %s", socket_path);
 | 
			
		||||
	cmdq_print(cmdq, "debug level %d", debug_level);
 | 
			
		||||
	cmdq_print(cmdq, "protocol version %d", PROTOCOL_VERSION);
 | 
			
		||||
 | 
			
		||||
	return (1);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int
 | 
			
		||||
cmd_show_messages_terminals(struct cmd_q *cmdq, int blank)
 | 
			
		||||
{
 | 
			
		||||
@@ -116,10 +99,6 @@ cmd_show_messages_exec(struct cmd *self, struct cmd_q *cmdq)
 | 
			
		||||
	int			 done, blank;
 | 
			
		||||
 | 
			
		||||
	done = blank = 0;
 | 
			
		||||
	if (args_has(args, 'I') || self->entry == &cmd_server_info_entry) {
 | 
			
		||||
		blank = cmd_show_messages_server(cmdq);
 | 
			
		||||
		done = 1;
 | 
			
		||||
	}
 | 
			
		||||
	if (args_has(args, 'T') || self->entry == &cmd_server_info_entry) {
 | 
			
		||||
		blank = cmd_show_messages_terminals(cmdq, blank);
 | 
			
		||||
		done = 1;
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										46
									
								
								environ.c
									
									
									
									
									
								
							
							
						
						
									
										46
									
								
								environ.c
									
									
									
									
									
								
							@@ -83,8 +83,12 @@ environ_copy(struct environ *srcenv, struct environ *dstenv)
 | 
			
		||||
{
 | 
			
		||||
	struct environ_entry	*envent;
 | 
			
		||||
 | 
			
		||||
	RB_FOREACH(envent, environ, srcenv)
 | 
			
		||||
		environ_set(dstenv, envent->name, envent->value);
 | 
			
		||||
	RB_FOREACH(envent, environ, srcenv) {
 | 
			
		||||
		if (envent->value == NULL)
 | 
			
		||||
			environ_clear(dstenv, envent->name);
 | 
			
		||||
		else
 | 
			
		||||
			environ_set(dstenv, envent->name, "%s", envent->value);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Find an environment variable. */
 | 
			
		||||
@@ -99,23 +103,37 @@ environ_find(struct environ *env, const char *name)
 | 
			
		||||
 | 
			
		||||
/* Set an environment variable. */
 | 
			
		||||
void
 | 
			
		||||
environ_set(struct environ *env, const char *name, const char *value)
 | 
			
		||||
environ_set(struct environ *env, const char *name, const char *fmt, ...)
 | 
			
		||||
{
 | 
			
		||||
	struct environ_entry	*envent;
 | 
			
		||||
	va_list			 ap;
 | 
			
		||||
 | 
			
		||||
	va_start(ap, fmt);
 | 
			
		||||
	if ((envent = environ_find(env, name)) != NULL) {
 | 
			
		||||
		free(envent->value);
 | 
			
		||||
		xvasprintf(&envent->value, fmt, ap);
 | 
			
		||||
	} else {
 | 
			
		||||
		envent = xmalloc(sizeof *envent);
 | 
			
		||||
		envent->name = xstrdup(name);
 | 
			
		||||
		xvasprintf(&envent->value, fmt, ap);
 | 
			
		||||
		RB_INSERT(environ, env, envent);
 | 
			
		||||
	}
 | 
			
		||||
	va_end(ap);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Clear an environment variable. */
 | 
			
		||||
void
 | 
			
		||||
environ_clear(struct environ *env, const char *name)
 | 
			
		||||
{
 | 
			
		||||
	struct environ_entry	*envent;
 | 
			
		||||
 | 
			
		||||
	if ((envent = environ_find(env, name)) != NULL) {
 | 
			
		||||
		free(envent->value);
 | 
			
		||||
		if (value != NULL)
 | 
			
		||||
			envent->value = xstrdup(value);
 | 
			
		||||
		else
 | 
			
		||||
			envent->value = NULL;
 | 
			
		||||
		envent->value = NULL;
 | 
			
		||||
	} else {
 | 
			
		||||
		envent = xmalloc(sizeof *envent);
 | 
			
		||||
		envent->name = xstrdup(name);
 | 
			
		||||
		if (value != NULL)
 | 
			
		||||
			envent->value = xstrdup(value);
 | 
			
		||||
		else
 | 
			
		||||
			envent->value = NULL;
 | 
			
		||||
		envent->value = NULL;
 | 
			
		||||
		RB_INSERT(environ, env, envent);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
@@ -134,7 +152,7 @@ environ_put(struct environ *env, const char *var)
 | 
			
		||||
	name = xstrdup(var);
 | 
			
		||||
	name[strcspn(name, "=")] = '\0';
 | 
			
		||||
 | 
			
		||||
	environ_set(env, name, value);
 | 
			
		||||
	environ_set(env, name, "%s", value);
 | 
			
		||||
	free(name);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -166,9 +184,9 @@ environ_update(const char *vars, struct environ *srcenv,
 | 
			
		||||
	copyvars = next = xstrdup(vars);
 | 
			
		||||
	while ((var = strsep(&next, " ")) != NULL) {
 | 
			
		||||
		if ((envent = environ_find(srcenv, var)) == NULL)
 | 
			
		||||
			environ_set(dstenv, var, NULL);
 | 
			
		||||
			environ_clear(dstenv, var);
 | 
			
		||||
		else
 | 
			
		||||
			environ_set(dstenv, envent->name, envent->value);
 | 
			
		||||
			environ_set(dstenv, envent->name, "%s", envent->value);
 | 
			
		||||
	}
 | 
			
		||||
	free(copyvars);
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										2
									
								
								format.c
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								format.c
									
									
									
									
									
								
							@@ -505,6 +505,8 @@ format_create_flags(int flags)
 | 
			
		||||
	format_add_cb(ft, "host", format_cb_host);
 | 
			
		||||
	format_add_cb(ft, "host_short", format_cb_host_short);
 | 
			
		||||
	format_add_cb(ft, "pid", format_cb_pid);
 | 
			
		||||
	format_add(ft, "socket_path", "%s", socket_path);
 | 
			
		||||
	format_add_tv(ft, "start_time", &start_time);
 | 
			
		||||
 | 
			
		||||
	return (ft);
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										35
									
								
								log.c
									
									
									
									
									
								
							
							
						
						
									
										35
									
								
								log.c
									
									
									
									
									
								
							@@ -22,29 +22,52 @@
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include <string.h>
 | 
			
		||||
#include <unistd.h>
 | 
			
		||||
 | 
			
		||||
#include "tmux.h"
 | 
			
		||||
 | 
			
		||||
FILE	*log_file;
 | 
			
		||||
static FILE	*log_file;
 | 
			
		||||
static int	 log_level;
 | 
			
		||||
 | 
			
		||||
void	 log_event_cb(int, const char *);
 | 
			
		||||
void	 log_vwrite(const char *, va_list);
 | 
			
		||||
static void	 log_event_cb(int, const char *);
 | 
			
		||||
static void	 log_vwrite(const char *, va_list);
 | 
			
		||||
 | 
			
		||||
/* Log callback for libevent. */
 | 
			
		||||
void
 | 
			
		||||
static void
 | 
			
		||||
log_event_cb(__unused int severity, const char *msg)
 | 
			
		||||
{
 | 
			
		||||
	log_debug("%s", msg);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Increment log level. */
 | 
			
		||||
void
 | 
			
		||||
log_add_level(void)
 | 
			
		||||
{
 | 
			
		||||
	log_level++;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Get log level. */
 | 
			
		||||
int
 | 
			
		||||
log_get_level(void)
 | 
			
		||||
{
 | 
			
		||||
	return (log_level);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Open logging to file. */
 | 
			
		||||
void
 | 
			
		||||
log_open(const char *path)
 | 
			
		||||
log_open(const char *name)
 | 
			
		||||
{
 | 
			
		||||
	char	*path;
 | 
			
		||||
 | 
			
		||||
	if (log_level == 0)
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
	if (log_file != NULL)
 | 
			
		||||
		fclose(log_file);
 | 
			
		||||
 | 
			
		||||
	xasprintf(&path, "tmux-%s-%ld.log", name, (long)getpid());
 | 
			
		||||
	log_file = fopen(path, "w");
 | 
			
		||||
	free(path);
 | 
			
		||||
	if (log_file == NULL)
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
@@ -64,7 +87,7 @@ log_close(void)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Write a log message. */
 | 
			
		||||
void
 | 
			
		||||
static void
 | 
			
		||||
log_vwrite(const char *msg, va_list ap)
 | 
			
		||||
{
 | 
			
		||||
	char		*fmt, *out;
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										8
									
								
								proc.c
									
									
									
									
									
								
							
							
						
						
									
										8
									
								
								proc.c
									
									
									
									
									
								
							@@ -18,6 +18,7 @@
 | 
			
		||||
 | 
			
		||||
#include <sys/types.h>
 | 
			
		||||
#include <sys/uio.h>
 | 
			
		||||
#include <sys/utsname.h>
 | 
			
		||||
 | 
			
		||||
#include <errno.h>
 | 
			
		||||
#include <event.h>
 | 
			
		||||
@@ -168,6 +169,7 @@ proc_start(const char *name, struct event_base *base, int forkflag,
 | 
			
		||||
    void (*signalcb)(int))
 | 
			
		||||
{
 | 
			
		||||
	struct tmuxproc	*tp;
 | 
			
		||||
	struct utsname	 u;
 | 
			
		||||
 | 
			
		||||
	if (forkflag) {
 | 
			
		||||
		switch (fork()) {
 | 
			
		||||
@@ -189,11 +191,17 @@ proc_start(const char *name, struct event_base *base, int forkflag,
 | 
			
		||||
	logfile(name);
 | 
			
		||||
 | 
			
		||||
#ifdef HAVE_SETPROCTITLE
 | 
			
		||||
	log_open(name);
 | 
			
		||||
	setproctitle("%s (%s)", name, socket_path);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
	if (uname(&u) < 0)
 | 
			
		||||
		memset(&u, 0, sizeof u);
 | 
			
		||||
 | 
			
		||||
	log_debug("%s started (%ld): socket %s, protocol %d", name,
 | 
			
		||||
	    (long)getpid(), socket_path, PROTOCOL_VERSION);
 | 
			
		||||
	log_debug("on %s %s %s; libevent %s (%s)", u.sysname, u.release,
 | 
			
		||||
	    u.version, event_get_version(), event_get_method());
 | 
			
		||||
 | 
			
		||||
	tp = xcalloc(1, sizeof *tp);
 | 
			
		||||
	tp->name = xstrdup(name);
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										11
									
								
								server-fn.c
									
									
									
									
									
								
							
							
						
						
									
										11
									
								
								server-fn.c
									
									
									
									
									
								
							@@ -32,20 +32,19 @@ void		server_callback_identify(int, short, void *);
 | 
			
		||||
void
 | 
			
		||||
server_fill_environ(struct session *s, struct environ *env)
 | 
			
		||||
{
 | 
			
		||||
	char	var[PATH_MAX], *term;
 | 
			
		||||
	u_int	idx;
 | 
			
		||||
	long	pid;
 | 
			
		||||
	char	*term;
 | 
			
		||||
	u_int	 idx;
 | 
			
		||||
	long	 pid;
 | 
			
		||||
 | 
			
		||||
	if (s != NULL) {
 | 
			
		||||
		term = options_get_string(global_options, "default-terminal");
 | 
			
		||||
		environ_set(env, "TERM", term);
 | 
			
		||||
		environ_set(env, "TERM", "%s", term);
 | 
			
		||||
 | 
			
		||||
		idx = s->id;
 | 
			
		||||
	} else
 | 
			
		||||
		idx = (u_int)-1;
 | 
			
		||||
	pid = getpid();
 | 
			
		||||
	xsnprintf(var, sizeof var, "%s,%ld,%u", socket_path, pid, idx);
 | 
			
		||||
	environ_set(env, "TMUX", var);
 | 
			
		||||
	environ_set(env, "TMUX", "%s,%ld,%u", socket_path, pid, idx);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										12
									
								
								server.c
									
									
									
									
									
								
							
							
						
						
									
										12
									
								
								server.c
									
									
									
									
									
								
							@@ -172,7 +172,7 @@ server_start(struct event_base *base, int lockfd, char *lockfile)
 | 
			
		||||
	}
 | 
			
		||||
	close(pair[0]);
 | 
			
		||||
 | 
			
		||||
	if (debug_level > 3)
 | 
			
		||||
	if (log_get_level() > 3)
 | 
			
		||||
		tty_create_log();
 | 
			
		||||
 | 
			
		||||
#ifdef __OpenBSD__
 | 
			
		||||
@@ -189,7 +189,7 @@ server_start(struct event_base *base, int lockfd, char *lockfile)
 | 
			
		||||
	mode_key_init_trees();
 | 
			
		||||
	key_bindings_init();
 | 
			
		||||
 | 
			
		||||
	start_time = time(NULL);
 | 
			
		||||
	gettimeofday(&start_time, NULL);
 | 
			
		||||
 | 
			
		||||
	server_fd = server_create_socket();
 | 
			
		||||
	if (server_fd == -1)
 | 
			
		||||
@@ -197,9 +197,11 @@ server_start(struct event_base *base, int lockfd, char *lockfile)
 | 
			
		||||
	server_update_socket();
 | 
			
		||||
	server_client_create(pair[1]);
 | 
			
		||||
 | 
			
		||||
	unlink(lockfile);
 | 
			
		||||
	free(lockfile);
 | 
			
		||||
	close(lockfd);
 | 
			
		||||
	if (lockfd >= 0) {
 | 
			
		||||
		unlink(lockfile);
 | 
			
		||||
		free(lockfile);
 | 
			
		||||
		close(lockfd);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	start_cfg();
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										16
									
								
								tmux.1
									
									
									
									
									
								
							
							
						
						
									
										16
									
								
								tmux.1
									
									
									
									
									
								
							@@ -718,8 +718,7 @@ is used,
 | 
			
		||||
.Ic update-environment
 | 
			
		||||
option will not be applied.
 | 
			
		||||
.It Xo Ic detach-client
 | 
			
		||||
.Op Fl P
 | 
			
		||||
.Op Fl a
 | 
			
		||||
.Op Fl aP
 | 
			
		||||
.Op Fl s Ar target-session
 | 
			
		||||
.Op Fl t Ar target-client
 | 
			
		||||
.Xc
 | 
			
		||||
@@ -745,7 +744,7 @@ Kill the
 | 
			
		||||
.Nm
 | 
			
		||||
server and clients and destroy all sessions.
 | 
			
		||||
.It Xo Ic kill-session
 | 
			
		||||
.Op Fl a
 | 
			
		||||
.Op Fl aC
 | 
			
		||||
.Op Fl t Ar target-session
 | 
			
		||||
.Xc
 | 
			
		||||
Destroy the given session, closing any windows linked to it and no other
 | 
			
		||||
@@ -753,6 +752,10 @@ sessions, and detaching all clients attached to it.
 | 
			
		||||
If
 | 
			
		||||
.Fl a
 | 
			
		||||
is given, all sessions but the specified one is killed.
 | 
			
		||||
The
 | 
			
		||||
.Fl C
 | 
			
		||||
flag clears alerts (bell, activity, or silence) in all windows linked to the
 | 
			
		||||
session.
 | 
			
		||||
.It Xo Ic list-clients
 | 
			
		||||
.Op Fl F Ar format
 | 
			
		||||
.Op Fl t Ar target-session
 | 
			
		||||
@@ -892,7 +895,7 @@ is specified, only update the client's status bar.
 | 
			
		||||
Rename the session to
 | 
			
		||||
.Ar new-name .
 | 
			
		||||
.It Xo Ic show-messages
 | 
			
		||||
.Op Fl IJT
 | 
			
		||||
.Op Fl JT
 | 
			
		||||
.Op Fl t Ar target-client
 | 
			
		||||
.Xc
 | 
			
		||||
.D1 (alias: Ic showmsgs )
 | 
			
		||||
@@ -905,11 +908,10 @@ With
 | 
			
		||||
.Fl t ,
 | 
			
		||||
display the log for
 | 
			
		||||
.Ar target-client .
 | 
			
		||||
.Fl I ,
 | 
			
		||||
.Fl J
 | 
			
		||||
and
 | 
			
		||||
.Fl T
 | 
			
		||||
show debugging information about the running server, jobs and terminals.
 | 
			
		||||
show debugging information about jobs and terminals.
 | 
			
		||||
.It Ic source-file Ar path
 | 
			
		||||
.D1 (alias: Ic source )
 | 
			
		||||
Execute commands from
 | 
			
		||||
@@ -3416,6 +3418,8 @@ The following variables are available, where appropriate:
 | 
			
		||||
.It Li "session_name" Ta "#S" Ta "Name of session"
 | 
			
		||||
.It Li "session_width" Ta "" Ta "Width of session"
 | 
			
		||||
.It Li "session_windows" Ta "" Ta "Number of windows in session"
 | 
			
		||||
.It Li "socket_path" Ta "" "Server socket path"
 | 
			
		||||
.It Li "start_time" Ta "" Ta "Server start time"
 | 
			
		||||
.It Li "window_activity" Ta "" Ta "Integer time of window last activity"
 | 
			
		||||
.It Li "window_active" Ta "" Ta "1 if window active"
 | 
			
		||||
.It Li "window_bell_flag" Ta "" Ta "1 if window has bell"
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										116
									
								
								tmux.c
									
									
									
									
									
								
							
							
						
						
									
										116
									
								
								tmux.c
									
									
									
									
									
								
							@@ -41,13 +41,11 @@ struct options	*global_s_options;	/* session options */
 | 
			
		||||
struct options	*global_w_options;	/* window options */
 | 
			
		||||
struct environ	*global_environ;
 | 
			
		||||
 | 
			
		||||
char		*shell_cmd;
 | 
			
		||||
int		 debug_level;
 | 
			
		||||
time_t		 start_time;
 | 
			
		||||
char		 socket_path[PATH_MAX];
 | 
			
		||||
struct timeval	 start_time;
 | 
			
		||||
const char	*socket_path;
 | 
			
		||||
 | 
			
		||||
__dead void	 usage(void);
 | 
			
		||||
char 		*makesocketpath(const char *);
 | 
			
		||||
static char	*make_label(const char *);
 | 
			
		||||
 | 
			
		||||
#ifndef HAVE___PROGNAME
 | 
			
		||||
char      *__progname = (char *) "tmux";
 | 
			
		||||
@@ -63,18 +61,6 @@ usage(void)
 | 
			
		||||
	exit(1);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
logfile(const char *name)
 | 
			
		||||
{
 | 
			
		||||
	char	*path;
 | 
			
		||||
 | 
			
		||||
	if (debug_level > 0) {
 | 
			
		||||
		xasprintf(&path, "tmux-%s-%ld.log", name, (long) getpid());
 | 
			
		||||
		log_open(path);
 | 
			
		||||
		free(path);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const char *
 | 
			
		||||
getshell(void)
 | 
			
		||||
{
 | 
			
		||||
@@ -121,38 +107,48 @@ areshell(const char *shell)
 | 
			
		||||
	return (0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
char *
 | 
			
		||||
makesocketpath(const char *label)
 | 
			
		||||
static char *
 | 
			
		||||
make_label(const char *label)
 | 
			
		||||
{
 | 
			
		||||
	char		base[PATH_MAX], realbase[PATH_MAX], *path, *s;
 | 
			
		||||
	struct stat	sb;
 | 
			
		||||
	u_int		uid;
 | 
			
		||||
	char		*base, resolved[PATH_MAX], *path, *s;
 | 
			
		||||
	struct stat	 sb;
 | 
			
		||||
	u_int		 uid;
 | 
			
		||||
	int		 saved_errno;
 | 
			
		||||
 | 
			
		||||
	if (label == NULL)
 | 
			
		||||
		label = "default";
 | 
			
		||||
 | 
			
		||||
	uid = getuid();
 | 
			
		||||
 | 
			
		||||
	if ((s = getenv("TMUX_TMPDIR")) != NULL && *s != '\0')
 | 
			
		||||
		xsnprintf(base, sizeof base, "%s/tmux-%u", s, uid);
 | 
			
		||||
		xasprintf(&base, "%s/tmux-%u", s, uid);
 | 
			
		||||
	else
 | 
			
		||||
		xsnprintf(base, sizeof base, "%s/tmux-%u", _PATH_TMP, uid);
 | 
			
		||||
		xasprintf(&base, "%s/tmux-%u", _PATH_TMP, uid);
 | 
			
		||||
 | 
			
		||||
	if (mkdir(base, S_IRWXU) != 0 && errno != EEXIST)
 | 
			
		||||
		return (NULL);
 | 
			
		||||
		goto fail;
 | 
			
		||||
 | 
			
		||||
	if (lstat(base, &sb) != 0)
 | 
			
		||||
		return (NULL);
 | 
			
		||||
		goto fail;
 | 
			
		||||
	if (!S_ISDIR(sb.st_mode)) {
 | 
			
		||||
		errno = ENOTDIR;
 | 
			
		||||
		return (NULL);
 | 
			
		||||
		goto fail;
 | 
			
		||||
	}
 | 
			
		||||
	if (sb.st_uid != uid || (sb.st_mode & S_IRWXO) != 0) {
 | 
			
		||||
		errno = EACCES;
 | 
			
		||||
		return (NULL);
 | 
			
		||||
		goto fail;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (realpath(base, realbase) == NULL)
 | 
			
		||||
		strlcpy(realbase, base, sizeof realbase);
 | 
			
		||||
 | 
			
		||||
	xasprintf(&path, "%s/%s", realbase, label);
 | 
			
		||||
	if (realpath(base, resolved) == NULL)
 | 
			
		||||
		strlcpy(resolved, base, sizeof resolved);
 | 
			
		||||
	xasprintf(&path, "%s/%s", resolved, label);
 | 
			
		||||
	return (path);
 | 
			
		||||
 | 
			
		||||
fail:
 | 
			
		||||
	saved_errno = errno;
 | 
			
		||||
	free(base);
 | 
			
		||||
	errno = saved_errno;
 | 
			
		||||
	return (NULL);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
@@ -193,7 +189,7 @@ find_home(void)
 | 
			
		||||
int
 | 
			
		||||
main(int argc, char **argv)
 | 
			
		||||
{
 | 
			
		||||
	char		*path, *label, **var, tmp[PATH_MAX];
 | 
			
		||||
	char		*path, *label, **var, tmp[PATH_MAX], *shellcmd = NULL;
 | 
			
		||||
	const char	*s;
 | 
			
		||||
	int		 opt, flags, keys;
 | 
			
		||||
 | 
			
		||||
@@ -216,8 +212,8 @@ main(int argc, char **argv)
 | 
			
		||||
			flags |= CLIENT_256COLOURS;
 | 
			
		||||
			break;
 | 
			
		||||
		case 'c':
 | 
			
		||||
			free(shell_cmd);
 | 
			
		||||
			shell_cmd = xstrdup(optarg);
 | 
			
		||||
			free(shellcmd);
 | 
			
		||||
			shellcmd = xstrdup(optarg);
 | 
			
		||||
			break;
 | 
			
		||||
		case 'C':
 | 
			
		||||
			if (flags & CLIENT_CONTROL)
 | 
			
		||||
@@ -248,7 +244,7 @@ main(int argc, char **argv)
 | 
			
		||||
			flags |= CLIENT_UTF8;
 | 
			
		||||
			break;
 | 
			
		||||
		case 'v':
 | 
			
		||||
			debug_level++;
 | 
			
		||||
			log_add_level();
 | 
			
		||||
			break;
 | 
			
		||||
		default:
 | 
			
		||||
			usage();
 | 
			
		||||
@@ -257,7 +253,7 @@ main(int argc, char **argv)
 | 
			
		||||
	argc -= optind;
 | 
			
		||||
	argv += optind;
 | 
			
		||||
 | 
			
		||||
	if (shell_cmd != NULL && argc != 0)
 | 
			
		||||
	if (shellcmd != NULL && argc != 0)
 | 
			
		||||
		usage();
 | 
			
		||||
 | 
			
		||||
#ifdef __OpenBSD__
 | 
			
		||||
@@ -292,7 +288,7 @@ main(int argc, char **argv)
 | 
			
		||||
	for (var = environ; *var != NULL; var++)
 | 
			
		||||
		environ_put(global_environ, *var);
 | 
			
		||||
	if (getcwd(tmp, sizeof tmp) != NULL)
 | 
			
		||||
		environ_set(global_environ, "PWD", tmp);
 | 
			
		||||
		environ_set(global_environ, "PWD", "%s", tmp);
 | 
			
		||||
 | 
			
		||||
	global_options = options_create(NULL);
 | 
			
		||||
	options_table_populate_tree(OPTIONS_TABLE_SERVER, global_options);
 | 
			
		||||
@@ -317,42 +313,24 @@ main(int argc, char **argv)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * Figure out the socket path. If specified on the command-line with -S
 | 
			
		||||
	 * or -L, use it, otherwise try $TMUX or assume -L default.
 | 
			
		||||
	 * If socket is specified on the command-line with -S or -L, it is
 | 
			
		||||
	 * used. Otherwise, $TMUX is checked and if that fails "default" is
 | 
			
		||||
	 * used.
 | 
			
		||||
	 */
 | 
			
		||||
	if (path == NULL) {
 | 
			
		||||
		/* If no -L, use the environment. */
 | 
			
		||||
		if (label == NULL) {
 | 
			
		||||
			s = getenv("TMUX");
 | 
			
		||||
			if (s != NULL) {
 | 
			
		||||
				path = xstrdup(s);
 | 
			
		||||
				path[strcspn (path, ",")] = '\0';
 | 
			
		||||
				if (*path == '\0') {
 | 
			
		||||
					free(path);
 | 
			
		||||
					label = xstrdup("default");
 | 
			
		||||
				}
 | 
			
		||||
			} else
 | 
			
		||||
				label = xstrdup("default");
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		/* -L or default set. */
 | 
			
		||||
		if (label != NULL) {
 | 
			
		||||
			if ((path = makesocketpath(label)) == NULL) {
 | 
			
		||||
				fprintf(stderr, "can't create socket: %s\n",
 | 
			
		||||
				    strerror(errno));
 | 
			
		||||
				exit(1);
 | 
			
		||||
			}
 | 
			
		||||
	if (path == NULL && label == NULL) {
 | 
			
		||||
		s = getenv("TMUX");
 | 
			
		||||
		if (s != NULL && *s != '\0' && *s != ',') {
 | 
			
		||||
			path = xstrdup(s);
 | 
			
		||||
			path[strcspn (path, ",")] = '\0';
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	free(label);
 | 
			
		||||
 | 
			
		||||
	if (strlcpy(socket_path, path, sizeof socket_path) >=
 | 
			
		||||
	    sizeof socket_path) {
 | 
			
		||||
		fprintf(stderr, "socket path too long: %s\n", path);
 | 
			
		||||
	if (path == NULL && (path = make_label(label)) == NULL) {
 | 
			
		||||
		fprintf(stderr, "can't create socket: %s\n", strerror(errno));
 | 
			
		||||
		exit(1);
 | 
			
		||||
	}
 | 
			
		||||
	free(path);
 | 
			
		||||
	socket_path = path;
 | 
			
		||||
	free(label);
 | 
			
		||||
 | 
			
		||||
	/* Pass control to the client. */
 | 
			
		||||
	exit(client_main(osdep_event_init(), argc, argv, flags));
 | 
			
		||||
	exit(client_main(event_init(), argc, argv, flags, shellcmd));
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										21
									
								
								tmux.h
									
									
									
									
									
								
							
							
						
						
									
										21
									
								
								tmux.h
									
									
									
									
									
								
							@@ -1433,11 +1433,8 @@ extern struct options *global_options;
 | 
			
		||||
extern struct options *global_s_options;
 | 
			
		||||
extern struct options *global_w_options;
 | 
			
		||||
extern struct environ *global_environ;
 | 
			
		||||
extern char	*shell_cmd;
 | 
			
		||||
extern int	 debug_level;
 | 
			
		||||
extern time_t	 start_time;
 | 
			
		||||
extern char	 socket_path[PATH_MAX];
 | 
			
		||||
void		 logfile(const char *);
 | 
			
		||||
extern struct timeval	 start_time;
 | 
			
		||||
extern const char	*socket_path;
 | 
			
		||||
const char	*getshell(void);
 | 
			
		||||
int		 checkshell(const char *);
 | 
			
		||||
int		 areshell(const char *);
 | 
			
		||||
@@ -1572,7 +1569,9 @@ struct environ_entry *environ_first(struct environ *);
 | 
			
		||||
struct environ_entry *environ_next(struct environ_entry *);
 | 
			
		||||
void	environ_copy(struct environ *, struct environ *);
 | 
			
		||||
struct environ_entry *environ_find(struct environ *, const char *);
 | 
			
		||||
void	environ_set(struct environ *, const char *, const char *);
 | 
			
		||||
void printflike(3, 4) environ_set(struct environ *, const char *, const char *,
 | 
			
		||||
	    ...);
 | 
			
		||||
void	environ_clear(struct environ *, const char *);
 | 
			
		||||
void	environ_put(struct environ *, const char *);
 | 
			
		||||
void	environ_unset(struct environ *, const char *);
 | 
			
		||||
void	environ_update(const char *, struct environ *, struct environ *);
 | 
			
		||||
@@ -1736,7 +1735,7 @@ int	cmd_string_parse(const char *, struct cmd_list **, const char *,
 | 
			
		||||
void	cmd_wait_for_flush(void);
 | 
			
		||||
 | 
			
		||||
/* client.c */
 | 
			
		||||
int	client_main(struct event_base *, int, char **, int);
 | 
			
		||||
int	client_main(struct event_base *, int, char **, int, const char *);
 | 
			
		||||
 | 
			
		||||
/* key-bindings.c */
 | 
			
		||||
RB_PROTOTYPE(key_bindings, key_binding, entry, key_bindings_cmp);
 | 
			
		||||
@@ -1744,7 +1743,7 @@ RB_PROTOTYPE(key_tables, key_table, entry, key_table_cmp);
 | 
			
		||||
extern struct key_tables key_tables;
 | 
			
		||||
int	 key_table_cmp(struct key_table *, struct key_table *);
 | 
			
		||||
int	 key_bindings_cmp(struct key_binding *, struct key_binding *);
 | 
			
		||||
struct	 key_table *key_bindings_get_table(const char *, int);
 | 
			
		||||
struct key_table *key_bindings_get_table(const char *, int);
 | 
			
		||||
void	 key_bindings_unref_table(struct key_table *);
 | 
			
		||||
void	 key_bindings_add(const char *, key_code, int, struct cmd_list *);
 | 
			
		||||
void	 key_bindings_remove(const char *, key_code);
 | 
			
		||||
@@ -2214,8 +2213,10 @@ char		*osdep_get_cwd(int);
 | 
			
		||||
struct event_base *osdep_event_init(void);
 | 
			
		||||
 | 
			
		||||
/* log.c */
 | 
			
		||||
void		 log_open(const char *);
 | 
			
		||||
void		 log_close(void);
 | 
			
		||||
void	log_add_level(void);
 | 
			
		||||
int	log_get_level(void);
 | 
			
		||||
void	log_open(const char *);
 | 
			
		||||
void	log_close(void);
 | 
			
		||||
void printflike(1, 2) log_debug(const char *, ...);
 | 
			
		||||
__dead void printflike(1, 2) fatal(const char *, ...);
 | 
			
		||||
__dead void printflike(1, 2) fatalx(const char *, ...);
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										7
									
								
								window.c
									
									
									
									
									
								
							
							
						
						
									
										7
									
								
								window.c
									
									
									
									
									
								
							@@ -810,7 +810,7 @@ window_pane_spawn(struct window_pane *wp, int argc, char **argv,
 | 
			
		||||
    struct termios *tio, char **cause)
 | 
			
		||||
{
 | 
			
		||||
	struct winsize	 ws;
 | 
			
		||||
	char		*argv0, *cmd, **argvp, paneid[16];
 | 
			
		||||
	char		*argv0, *cmd, **argvp;
 | 
			
		||||
	const char	*ptr, *first, *home;
 | 
			
		||||
	struct termios	 tio2;
 | 
			
		||||
#ifdef HAVE_UTEMPTER
 | 
			
		||||
@@ -871,9 +871,8 @@ window_pane_spawn(struct window_pane *wp, int argc, char **argv,
 | 
			
		||||
		closefrom(STDERR_FILENO + 1);
 | 
			
		||||
 | 
			
		||||
		if (path != NULL)
 | 
			
		||||
			environ_set(env, "PATH", path);
 | 
			
		||||
		xsnprintf(paneid, sizeof paneid, "%%%u", wp->id);
 | 
			
		||||
		environ_set(env, "TMUX_PANE", paneid);
 | 
			
		||||
			environ_set(env, "PATH", "%s", path);
 | 
			
		||||
		environ_set(env, "TMUX_PANE", "%%%u", wp->id);
 | 
			
		||||
		environ_push(env);
 | 
			
		||||
 | 
			
		||||
		clear_signals(1);
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user