mirror of
				https://github.com/tmux/tmux.git
				synced 2025-11-04 00:56:10 +00:00 
			
		
		
		
	Because pledge(2) does not allow us to pass directory file descriptors
around, we can't use file descriptors for the working directory because we will be unable to pass it to a privileged process to tell it where to read or write files or spawn children. So move tmux back to using strings for the current working directory. We try to check it exists with access() when it is set but ultimately fall back to ~ if it fails at time of use (or / if that fails too).
This commit is contained in:
		
							
								
								
									
										4
									
								
								client.c
									
									
									
									
									
								
							
							
						
						
									
										4
									
								
								client.c
									
									
									
									
									
								
							@@ -273,8 +273,10 @@ client_main(struct event_base *base, int argc, char **argv, int flags)
 | 
			
		||||
	client_peer = proc_add_peer(client_proc, fd, client_dispatch, NULL);
 | 
			
		||||
 | 
			
		||||
	/* Save these before pledge(). */
 | 
			
		||||
	if ((cwd = getcwd(path, sizeof path)) == NULL)
 | 
			
		||||
	if ((cwd = getcwd(path, sizeof path)) == NULL) {
 | 
			
		||||
		if ((cwd = find_home()) == NULL)
 | 
			
		||||
			cwd = "/";
 | 
			
		||||
	}
 | 
			
		||||
	if ((ttynam = ttyname(STDIN_FILENO)) == NULL)
 | 
			
		||||
		ttynam = "";
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -51,9 +51,8 @@ cmd_attach_session(struct cmd_q *cmdq, const char *tflag, int dflag, int rflag,
 | 
			
		||||
	struct window_pane	*wp = NULL;
 | 
			
		||||
	const char		*update;
 | 
			
		||||
	char			*cause;
 | 
			
		||||
	int			 fd;
 | 
			
		||||
	struct format_tree	*ft;
 | 
			
		||||
	char			*cp;
 | 
			
		||||
	char			*cwd;
 | 
			
		||||
 | 
			
		||||
	if (RB_EMPTY(&sessions)) {
 | 
			
		||||
		cmdq_error(cmdq, "no sessions");
 | 
			
		||||
@@ -97,18 +96,17 @@ cmd_attach_session(struct cmd_q *cmdq, const char *tflag, int dflag, int rflag,
 | 
			
		||||
		ft = format_create();
 | 
			
		||||
		format_defaults(ft, cmd_find_client(cmdq, NULL, 1), s,
 | 
			
		||||
		    NULL, NULL);
 | 
			
		||||
		cp = format_expand(ft, cflag);
 | 
			
		||||
		cwd = format_expand(ft, cflag);
 | 
			
		||||
		format_free(ft);
 | 
			
		||||
 | 
			
		||||
		fd = open(cp, O_RDONLY|O_DIRECTORY);
 | 
			
		||||
		free(cp);
 | 
			
		||||
		if (fd == -1) {
 | 
			
		||||
		if (access(cwd, X_OK) != 0) {
 | 
			
		||||
			free((void *)cwd);
 | 
			
		||||
			cmdq_error(cmdq, "bad working directory: %s",
 | 
			
		||||
			    strerror(errno));
 | 
			
		||||
			return (CMD_RETURN_ERROR);
 | 
			
		||||
		}
 | 
			
		||||
		close(s->cwd);
 | 
			
		||||
		s->cwd = fd;
 | 
			
		||||
		free((void *)s->cwd);
 | 
			
		||||
		s->cwd = cwd;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (c->session != NULL) {
 | 
			
		||||
 
 | 
			
		||||
@@ -66,7 +66,7 @@ cmd_if_shell_exec(struct cmd *self, struct cmd_q *cmdq)
 | 
			
		||||
	struct winlink			*wl = NULL;
 | 
			
		||||
	struct window_pane		*wp = NULL;
 | 
			
		||||
	struct format_tree		*ft;
 | 
			
		||||
	int				 cwd;
 | 
			
		||||
	const char			*cwd;
 | 
			
		||||
 | 
			
		||||
	if (args_has(args, 't')) {
 | 
			
		||||
		wl = cmd_find_pane(cmdq, args_get(args, 't'), &s, &wp);
 | 
			
		||||
@@ -83,7 +83,7 @@ cmd_if_shell_exec(struct cmd *self, struct cmd_q *cmdq)
 | 
			
		||||
		else if (s != NULL)
 | 
			
		||||
			cwd = s->cwd;
 | 
			
		||||
		else
 | 
			
		||||
			cwd = -1;
 | 
			
		||||
			cwd = NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	ft = format_create();
 | 
			
		||||
 
 | 
			
		||||
@@ -49,10 +49,10 @@ cmd_load_buffer_exec(struct cmd *self, struct cmd_q *cmdq)
 | 
			
		||||
	struct client	*c = cmdq->client;
 | 
			
		||||
	struct session  *s;
 | 
			
		||||
	FILE		*f;
 | 
			
		||||
	const char	*path, *bufname;
 | 
			
		||||
	char		*pdata, *new_pdata, *cause;
 | 
			
		||||
	const char	*path, *bufname, *cwd;
 | 
			
		||||
	char		*pdata, *new_pdata, *cause, *file, resolved[PATH_MAX];
 | 
			
		||||
	size_t		 psize;
 | 
			
		||||
	int		 ch, error, cwd, fd;
 | 
			
		||||
	int		 ch, error;
 | 
			
		||||
 | 
			
		||||
	bufname = NULL;
 | 
			
		||||
	if (args_has(args, 'b'))
 | 
			
		||||
@@ -75,13 +75,16 @@ cmd_load_buffer_exec(struct cmd *self, struct cmd_q *cmdq)
 | 
			
		||||
	else if ((s = cmd_find_current(cmdq)) != NULL)
 | 
			
		||||
		cwd = s->cwd;
 | 
			
		||||
	else
 | 
			
		||||
		cwd = AT_FDCWD;
 | 
			
		||||
		cwd = ".";
 | 
			
		||||
 | 
			
		||||
	if ((fd = openat(cwd, path, O_RDONLY)) == -1 ||
 | 
			
		||||
	    (f = fdopen(fd, "rb")) == NULL) {
 | 
			
		||||
		if (fd != -1)
 | 
			
		||||
			close(fd);
 | 
			
		||||
		cmdq_error(cmdq, "%s: %s", path, strerror(errno));
 | 
			
		||||
	xasprintf(&file, "%s/%s", cwd, path);
 | 
			
		||||
	if (realpath(file, resolved) == NULL)
 | 
			
		||||
		f = NULL;
 | 
			
		||||
	else
 | 
			
		||||
		f = fopen(resolved, "rb");
 | 
			
		||||
	free(file);
 | 
			
		||||
	if (f == NULL) {
 | 
			
		||||
		cmdq_error(cmdq, "%s: %s", resolved, strerror(errno));
 | 
			
		||||
		return (CMD_RETURN_ERROR);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
@@ -97,7 +100,7 @@ cmd_load_buffer_exec(struct cmd *self, struct cmd_q *cmdq)
 | 
			
		||||
		pdata[psize++] = ch;
 | 
			
		||||
	}
 | 
			
		||||
	if (ferror(f)) {
 | 
			
		||||
		cmdq_error(cmdq, "%s: read error", path);
 | 
			
		||||
		cmdq_error(cmdq, "%s: read error", resolved);
 | 
			
		||||
		goto error;
 | 
			
		||||
	}
 | 
			
		||||
	if (pdata != NULL)
 | 
			
		||||
 
 | 
			
		||||
@@ -63,10 +63,9 @@ cmd_new_session_exec(struct cmd *self, struct cmd_q *cmdq)
 | 
			
		||||
	struct environ		*env;
 | 
			
		||||
	struct termios		 tio, *tiop;
 | 
			
		||||
	const char		*newname, *target, *update, *errstr, *template;
 | 
			
		||||
	const char		*path;
 | 
			
		||||
	const char		*path, *cwd, *to_free;
 | 
			
		||||
	char		       **argv, *cmd, *cause, *cp;
 | 
			
		||||
	int			 detached, already_attached, idx, cwd, fd = -1;
 | 
			
		||||
	int			 argc;
 | 
			
		||||
	int			 detached, already_attached, idx, argc;
 | 
			
		||||
	u_int			 sx, sy;
 | 
			
		||||
	struct format_tree	*ft;
 | 
			
		||||
	struct environ_entry	*envent;
 | 
			
		||||
@@ -118,32 +117,26 @@ cmd_new_session_exec(struct cmd *self, struct cmd_q *cmdq)
 | 
			
		||||
		already_attached = 1;
 | 
			
		||||
 | 
			
		||||
	/* Get the new session working directory. */
 | 
			
		||||
	to_free = NULL;
 | 
			
		||||
	if (args_has(args, 'c')) {
 | 
			
		||||
		ft = format_create();
 | 
			
		||||
		format_defaults(ft, cmd_find_client(cmdq, NULL, 1), NULL, NULL,
 | 
			
		||||
		    NULL);
 | 
			
		||||
		cp = format_expand(ft, args_get(args, 'c'));
 | 
			
		||||
		to_free = cwd = format_expand(ft, args_get(args, 'c'));
 | 
			
		||||
		format_free(ft);
 | 
			
		||||
 | 
			
		||||
		if (cp != NULL && *cp != '\0') {
 | 
			
		||||
			fd = open(cp, O_RDONLY|O_DIRECTORY);
 | 
			
		||||
			free(cp);
 | 
			
		||||
			if (fd == -1) {
 | 
			
		||||
		if (access(cwd, X_OK) != 0) {
 | 
			
		||||
			free((void *)cwd);
 | 
			
		||||
			cmdq_error(cmdq, "bad working directory: %s",
 | 
			
		||||
			    strerror(errno));
 | 
			
		||||
			return (CMD_RETURN_ERROR);
 | 
			
		||||
		}
 | 
			
		||||
		} else
 | 
			
		||||
			free(cp);
 | 
			
		||||
		cwd = fd;
 | 
			
		||||
	} else if (c != NULL && c->session == NULL)
 | 
			
		||||
		cwd = c->cwd;
 | 
			
		||||
	else if ((c0 = cmd_find_client(cmdq, NULL, 1)) != NULL)
 | 
			
		||||
		cwd = c0->session->cwd;
 | 
			
		||||
	else {
 | 
			
		||||
		fd = open(".", O_RDONLY);
 | 
			
		||||
		cwd = fd;
 | 
			
		||||
	}
 | 
			
		||||
	else
 | 
			
		||||
		cwd = ".";
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * If this is a new client, check for nesting and save the termios
 | 
			
		||||
@@ -311,12 +304,12 @@ cmd_new_session_exec(struct cmd *self, struct cmd_q *cmdq)
 | 
			
		||||
	if (!detached)
 | 
			
		||||
		cmdq->client_exit = 0;
 | 
			
		||||
 | 
			
		||||
	if (fd != -1)
 | 
			
		||||
		close(fd);
 | 
			
		||||
	if (to_free != NULL)
 | 
			
		||||
		free((void *)to_free);
 | 
			
		||||
	return (CMD_RETURN_NORMAL);
 | 
			
		||||
 | 
			
		||||
error:
 | 
			
		||||
	if (fd != -1)
 | 
			
		||||
		close(fd);
 | 
			
		||||
	if (to_free != NULL)
 | 
			
		||||
		free((void *)to_free);
 | 
			
		||||
	return (CMD_RETURN_ERROR);
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -49,9 +49,9 @@ cmd_new_window_exec(struct cmd *self, struct cmd_q *cmdq)
 | 
			
		||||
	struct args		*args = self->args;
 | 
			
		||||
	struct session		*s;
 | 
			
		||||
	struct winlink		*wl;
 | 
			
		||||
	const char		*cmd, *path, *template;
 | 
			
		||||
	const char		*cmd, *path, *template, *cwd, *to_free;
 | 
			
		||||
	char		       **argv, *cause, *cp;
 | 
			
		||||
	int			 argc, idx, detached, cwd, fd = -1;
 | 
			
		||||
	int			 argc, idx, detached;
 | 
			
		||||
	struct format_tree	*ft;
 | 
			
		||||
	struct environ_entry	*envent;
 | 
			
		||||
 | 
			
		||||
@@ -92,24 +92,20 @@ cmd_new_window_exec(struct cmd *self, struct cmd_q *cmdq)
 | 
			
		||||
	if (envent != NULL)
 | 
			
		||||
		path = envent->value;
 | 
			
		||||
 | 
			
		||||
	to_free = NULL;
 | 
			
		||||
	if (args_has(args, 'c')) {
 | 
			
		||||
		ft = format_create();
 | 
			
		||||
		format_defaults(ft, cmd_find_client(cmdq, NULL, 1), s, NULL,
 | 
			
		||||
		    NULL);
 | 
			
		||||
		cp = format_expand(ft, args_get(args, 'c'));
 | 
			
		||||
		cwd = format_expand(ft, args_get(args, 'c'));
 | 
			
		||||
		format_free(ft);
 | 
			
		||||
 | 
			
		||||
		if (cp != NULL && *cp != '\0') {
 | 
			
		||||
			fd = open(cp, O_RDONLY|O_DIRECTORY);
 | 
			
		||||
			free(cp);
 | 
			
		||||
			if (fd == -1) {
 | 
			
		||||
		if (access(cwd, X_OK) != 0) {
 | 
			
		||||
			free((void *)cwd);
 | 
			
		||||
			cmdq_error(cmdq, "bad working directory: %s",
 | 
			
		||||
			    strerror(errno));
 | 
			
		||||
			return (CMD_RETURN_ERROR);
 | 
			
		||||
		}
 | 
			
		||||
		} else
 | 
			
		||||
			free(cp);
 | 
			
		||||
		cwd = fd;
 | 
			
		||||
	} else if (cmdq->client != NULL && cmdq->client->session == NULL)
 | 
			
		||||
		cwd = cmdq->client->cwd;
 | 
			
		||||
	else
 | 
			
		||||
@@ -165,12 +161,12 @@ cmd_new_window_exec(struct cmd *self, struct cmd_q *cmdq)
 | 
			
		||||
		format_free(ft);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (fd != -1)
 | 
			
		||||
		close(fd);
 | 
			
		||||
	if (to_free != NULL)
 | 
			
		||||
		free((void *)to_free);
 | 
			
		||||
	return (CMD_RETURN_NORMAL);
 | 
			
		||||
 | 
			
		||||
error:
 | 
			
		||||
	if (fd != -1)
 | 
			
		||||
		close(fd);
 | 
			
		||||
	if (to_free != NULL)
 | 
			
		||||
		free((void *)to_free);
 | 
			
		||||
	return (CMD_RETURN_ERROR);
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -81,7 +81,7 @@ cmd_respawn_pane_exec(struct cmd *self, struct cmd_q *cmdq)
 | 
			
		||||
	if (envent != NULL)
 | 
			
		||||
		path = envent->value;
 | 
			
		||||
 | 
			
		||||
	if (window_pane_spawn(wp, args->argc, args->argv, path, NULL, -1, env,
 | 
			
		||||
	if (window_pane_spawn(wp, args->argc, args->argv, path, NULL, NULL, env,
 | 
			
		||||
	    s->tio, &cause) != 0) {
 | 
			
		||||
		cmdq_error(cmdq, "respawn pane failed: %s", cause);
 | 
			
		||||
		free(cause);
 | 
			
		||||
 
 | 
			
		||||
@@ -84,7 +84,7 @@ cmd_respawn_window_exec(struct cmd *self, struct cmd_q *cmdq)
 | 
			
		||||
	if (envent != NULL)
 | 
			
		||||
		path = envent->value;
 | 
			
		||||
 | 
			
		||||
	if (window_pane_spawn(wp, args->argc, args->argv, path, NULL, -1, env,
 | 
			
		||||
	if (window_pane_spawn(wp, args->argc, args->argv, path, NULL, NULL, env,
 | 
			
		||||
	    s->tio, &cause) != 0) {
 | 
			
		||||
		cmdq_error(cmdq, "respawn window failed: %s", cause);
 | 
			
		||||
		free(cause);
 | 
			
		||||
 
 | 
			
		||||
@@ -80,7 +80,7 @@ cmd_run_shell_exec(struct cmd *self, struct cmd_q *cmdq)
 | 
			
		||||
	struct winlink			*wl = NULL;
 | 
			
		||||
	struct window_pane		*wp = NULL;
 | 
			
		||||
	struct format_tree		*ft;
 | 
			
		||||
	int				 cwd;
 | 
			
		||||
	const char			*cwd;
 | 
			
		||||
 | 
			
		||||
	if (args_has(args, 't')) {
 | 
			
		||||
		wl = cmd_find_pane(cmdq, args_get(args, 't'), &s, &wp);
 | 
			
		||||
@@ -97,7 +97,7 @@ cmd_run_shell_exec(struct cmd *self, struct cmd_q *cmdq)
 | 
			
		||||
		else if (s != NULL)
 | 
			
		||||
			cwd = s->cwd;
 | 
			
		||||
		else
 | 
			
		||||
			cwd = -1;
 | 
			
		||||
			cwd = NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	ft = format_create();
 | 
			
		||||
 
 | 
			
		||||
@@ -57,10 +57,10 @@ cmd_save_buffer_exec(struct cmd *self, struct cmd_q *cmdq)
 | 
			
		||||
	struct client		*c = cmdq->client;
 | 
			
		||||
	struct session          *s;
 | 
			
		||||
	struct paste_buffer	*pb;
 | 
			
		||||
	const char		*path, *bufname, *bufdata, *start, *end;
 | 
			
		||||
	char			*msg;
 | 
			
		||||
	const char		*path, *bufname, *bufdata, *start, *end, *cwd;
 | 
			
		||||
	const char		*flags;
 | 
			
		||||
	char			*msg, *file, resolved[PATH_MAX];
 | 
			
		||||
	size_t			 size, used, msglen, bufsize;
 | 
			
		||||
	int			 cwd, fd;
 | 
			
		||||
	FILE			*f;
 | 
			
		||||
 | 
			
		||||
	if (!args_has(args, 'b')) {
 | 
			
		||||
@@ -97,26 +97,25 @@ cmd_save_buffer_exec(struct cmd *self, struct cmd_q *cmdq)
 | 
			
		||||
	else if ((s = cmd_find_current(cmdq)) != NULL)
 | 
			
		||||
		cwd = s->cwd;
 | 
			
		||||
	else
 | 
			
		||||
		cwd = AT_FDCWD;
 | 
			
		||||
		cwd = ".";
 | 
			
		||||
 | 
			
		||||
	flags = "wb";
 | 
			
		||||
	if (args_has(self->args, 'a'))
 | 
			
		||||
		flags = "ab";
 | 
			
		||||
 | 
			
		||||
	xasprintf(&file, "%s/%s", cwd, path);
 | 
			
		||||
	if (realpath(file, resolved) == NULL)
 | 
			
		||||
		f = NULL;
 | 
			
		||||
	if (args_has(self->args, 'a')) {
 | 
			
		||||
		fd = openat(cwd, path, O_CREAT|O_RDWR|O_APPEND, 0600);
 | 
			
		||||
		if (fd != -1)
 | 
			
		||||
			f = fdopen(fd, "ab");
 | 
			
		||||
	} else {
 | 
			
		||||
		fd = openat(cwd, path, O_CREAT|O_RDWR|O_TRUNC, 0600);
 | 
			
		||||
		if (fd != -1)
 | 
			
		||||
			f = fdopen(fd, "wb");
 | 
			
		||||
	}
 | 
			
		||||
	else
 | 
			
		||||
		f = fopen(resolved, flags);
 | 
			
		||||
	free(file);
 | 
			
		||||
	if (f == NULL) {
 | 
			
		||||
		if (fd != -1)
 | 
			
		||||
			close(fd);
 | 
			
		||||
		cmdq_error(cmdq, "%s: %s", path, strerror(errno));
 | 
			
		||||
		cmdq_error(cmdq, "%s: %s", resolved, strerror(errno));
 | 
			
		||||
		return (CMD_RETURN_ERROR);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (fwrite(bufdata, 1, bufsize, f) != bufsize) {
 | 
			
		||||
		cmdq_error(cmdq, "%s: fwrite error", path);
 | 
			
		||||
		cmdq_error(cmdq, "%s: write error", resolved);
 | 
			
		||||
		fclose(f);
 | 
			
		||||
		return (CMD_RETURN_ERROR);
 | 
			
		||||
	}
 | 
			
		||||
 
 | 
			
		||||
@@ -53,10 +53,10 @@ cmd_split_window_exec(struct cmd *self, struct cmd_q *cmdq)
 | 
			
		||||
	struct window		*w;
 | 
			
		||||
	struct window_pane	*wp, *new_wp = NULL;
 | 
			
		||||
	struct environ		*env;
 | 
			
		||||
	const char		*cmd, *path, *shell, *template;
 | 
			
		||||
	const char		*cmd, *path, *shell, *template, *cwd, *to_free;
 | 
			
		||||
	char		       **argv, *cause, *new_cause, *cp;
 | 
			
		||||
	u_int			 hlimit;
 | 
			
		||||
	int			 argc, size, percentage, cwd, fd = -1;
 | 
			
		||||
	int			 argc, size, percentage;
 | 
			
		||||
	enum layout_type	 type;
 | 
			
		||||
	struct layout_cell	*lc;
 | 
			
		||||
	struct format_tree	*ft;
 | 
			
		||||
@@ -86,24 +86,20 @@ cmd_split_window_exec(struct cmd *self, struct cmd_q *cmdq)
 | 
			
		||||
		argv = args->argv;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	to_free = NULL;
 | 
			
		||||
	if (args_has(args, 'c')) {
 | 
			
		||||
		ft = format_create();
 | 
			
		||||
		format_defaults(ft, cmd_find_client(cmdq, NULL, 1), s, NULL,
 | 
			
		||||
		    NULL);
 | 
			
		||||
		cp = format_expand(ft, args_get(args, 'c'));
 | 
			
		||||
		to_free = cwd = format_expand(ft, args_get(args, 'c'));
 | 
			
		||||
		format_free(ft);
 | 
			
		||||
 | 
			
		||||
		if (cp != NULL && *cp != '\0') {
 | 
			
		||||
			fd = open(cp, O_RDONLY|O_DIRECTORY);
 | 
			
		||||
			free(cp);
 | 
			
		||||
			if (fd == -1) {
 | 
			
		||||
		if (access(cwd, X_OK) != 0) {
 | 
			
		||||
			free((void *)cwd);
 | 
			
		||||
			cmdq_error(cmdq, "bad working directory: %s",
 | 
			
		||||
			    strerror(errno));
 | 
			
		||||
			return (CMD_RETURN_ERROR);
 | 
			
		||||
		}
 | 
			
		||||
		} else
 | 
			
		||||
			free(cp);
 | 
			
		||||
		cwd = fd;
 | 
			
		||||
	} else if (cmdq->client != NULL && cmdq->client->session == NULL)
 | 
			
		||||
		cwd = cmdq->client->cwd;
 | 
			
		||||
	else
 | 
			
		||||
@@ -188,8 +184,8 @@ cmd_split_window_exec(struct cmd *self, struct cmd_q *cmdq)
 | 
			
		||||
	}
 | 
			
		||||
	notify_window_layout_changed(w);
 | 
			
		||||
 | 
			
		||||
	if (fd != -1)
 | 
			
		||||
		close(fd);
 | 
			
		||||
	if (to_free != NULL)
 | 
			
		||||
		free((void *)to_free);
 | 
			
		||||
	return (CMD_RETURN_NORMAL);
 | 
			
		||||
 | 
			
		||||
error:
 | 
			
		||||
@@ -200,7 +196,8 @@ error:
 | 
			
		||||
	}
 | 
			
		||||
	cmdq_error(cmdq, "create pane failed: %s", cause);
 | 
			
		||||
	free(cause);
 | 
			
		||||
	if (fd != -1)
 | 
			
		||||
		close(fd);
 | 
			
		||||
 | 
			
		||||
	if (to_free != NULL)
 | 
			
		||||
		free((void *)to_free);
 | 
			
		||||
	return (CMD_RETURN_ERROR);
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										2
									
								
								format.c
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								format.c
									
									
									
									
									
								
							@@ -239,7 +239,7 @@ format_job_get(struct format_tree *ft, const char *cmd)
 | 
			
		||||
 | 
			
		||||
	t = time(NULL);
 | 
			
		||||
	if (fj->job == NULL && ((ft->flags & FORMAT_FORCE) || fj->last != t)) {
 | 
			
		||||
		fj->job = job_run(fj->cmd, NULL, -1, format_job_callback,
 | 
			
		||||
		fj->job = job_run(fj->cmd, NULL, NULL, format_job_callback,
 | 
			
		||||
		    NULL, fj);
 | 
			
		||||
		if (fj->job == NULL) {
 | 
			
		||||
			free(fj->out);
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										7
									
								
								job.c
									
									
									
									
									
								
							
							
						
						
									
										7
									
								
								job.c
									
									
									
									
									
								
							@@ -41,13 +41,14 @@ struct joblist	all_jobs = LIST_HEAD_INITIALIZER(all_jobs);
 | 
			
		||||
 | 
			
		||||
/* Start a job running, if it isn't already. */
 | 
			
		||||
struct job *
 | 
			
		||||
job_run(const char *cmd, struct session *s, int cwd,
 | 
			
		||||
job_run(const char *cmd, struct session *s, const char *cwd,
 | 
			
		||||
    void (*callbackfn)(struct job *), void (*freefn)(void *), void *data)
 | 
			
		||||
{
 | 
			
		||||
	struct job	*job;
 | 
			
		||||
	struct environ	*env;
 | 
			
		||||
	pid_t		 pid;
 | 
			
		||||
	int		 nullfd, out[2];
 | 
			
		||||
	const char	*home;
 | 
			
		||||
 | 
			
		||||
	if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, out) != 0)
 | 
			
		||||
		return (NULL);
 | 
			
		||||
@@ -67,8 +68,10 @@ job_run(const char *cmd, struct session *s, int cwd,
 | 
			
		||||
	case 0:		/* child */
 | 
			
		||||
		clear_signals(1);
 | 
			
		||||
 | 
			
		||||
		if (cwd != -1 && fchdir(cwd) != 0)
 | 
			
		||||
		if (cwd == NULL || chdir(cwd) != 0) {
 | 
			
		||||
			if ((home = find_home()) == NULL || chdir(home) != 0)
 | 
			
		||||
				chdir("/");
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		environ_push(env);
 | 
			
		||||
		environ_free(env);
 | 
			
		||||
 
 | 
			
		||||
@@ -98,7 +98,7 @@ server_client_create(int fd)
 | 
			
		||||
	c->environ = environ_create();
 | 
			
		||||
 | 
			
		||||
	c->fd = -1;
 | 
			
		||||
	c->cwd = -1;
 | 
			
		||||
	c->cwd = NULL;
 | 
			
		||||
 | 
			
		||||
	c->cmdq = cmdq_new(c);
 | 
			
		||||
	c->cmdq->client_exit = 1;
 | 
			
		||||
@@ -194,7 +194,7 @@ server_client_lost(struct client *c)
 | 
			
		||||
	screen_free(&c->status);
 | 
			
		||||
 | 
			
		||||
	free(c->title);
 | 
			
		||||
	close(c->cwd);
 | 
			
		||||
	free((void *)c->cwd);
 | 
			
		||||
 | 
			
		||||
	evtimer_del(&c->repeat_timer);
 | 
			
		||||
 | 
			
		||||
@@ -1099,7 +1099,7 @@ error:
 | 
			
		||||
void
 | 
			
		||||
server_client_dispatch_identify(struct client *c, struct imsg *imsg)
 | 
			
		||||
{
 | 
			
		||||
	const char	*data;
 | 
			
		||||
	const char	*data, *home;
 | 
			
		||||
	size_t	 	 datalen;
 | 
			
		||||
	int		 flags;
 | 
			
		||||
 | 
			
		||||
@@ -1132,8 +1132,12 @@ server_client_dispatch_identify(struct client *c, struct imsg *imsg)
 | 
			
		||||
	case MSG_IDENTIFY_CWD:
 | 
			
		||||
		if (datalen == 0 || data[datalen - 1] != '\0')
 | 
			
		||||
			fatalx("bad MSG_IDENTIFY_CWD string");
 | 
			
		||||
		if ((c->cwd = open(data, O_RDONLY)) == -1)
 | 
			
		||||
			c->cwd = open("/", O_RDONLY);
 | 
			
		||||
		if (access(data, X_OK) == 0)
 | 
			
		||||
			c->cwd = xstrdup(data);
 | 
			
		||||
		else if ((home = find_home()) != NULL)
 | 
			
		||||
			c->cwd = xstrdup(home);
 | 
			
		||||
		else
 | 
			
		||||
			c->cwd = xstrdup("/");
 | 
			
		||||
		log_debug("client %p IDENTIFY_CWD %s", c, data);
 | 
			
		||||
		break;
 | 
			
		||||
	case MSG_IDENTIFY_STDIN:
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										10
									
								
								session.c
									
									
									
									
									
								
							
							
						
						
									
										10
									
								
								session.c
									
									
									
									
									
								
							@@ -104,8 +104,8 @@ session_find_by_id(u_int id)
 | 
			
		||||
/* Create a new session. */
 | 
			
		||||
struct session *
 | 
			
		||||
session_create(const char *name, int argc, char **argv, const char *path,
 | 
			
		||||
    int cwd, struct environ *env, struct termios *tio, int idx, u_int sx,
 | 
			
		||||
    u_int sy, char **cause)
 | 
			
		||||
    const char *cwd, struct environ *env, struct termios *tio, int idx,
 | 
			
		||||
    u_int sx, u_int sy, char **cause)
 | 
			
		||||
{
 | 
			
		||||
	struct session	*s;
 | 
			
		||||
	struct winlink	*wl;
 | 
			
		||||
@@ -114,7 +114,7 @@ session_create(const char *name, int argc, char **argv, const char *path,
 | 
			
		||||
	s->references = 1;
 | 
			
		||||
	s->flags = 0;
 | 
			
		||||
 | 
			
		||||
	s->cwd = dup(cwd);
 | 
			
		||||
	s->cwd = xstrdup(cwd);
 | 
			
		||||
 | 
			
		||||
	s->curw = NULL;
 | 
			
		||||
	TAILQ_INIT(&s->lastw);
 | 
			
		||||
@@ -224,7 +224,7 @@ session_destroy(struct session *s)
 | 
			
		||||
		winlink_remove(&s->windows, wl);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	close(s->cwd);
 | 
			
		||||
	free((void *)s->cwd);
 | 
			
		||||
 | 
			
		||||
	session_unref(s);
 | 
			
		||||
}
 | 
			
		||||
@@ -315,7 +315,7 @@ session_previous_session(struct session *s)
 | 
			
		||||
/* Create a new window on a session. */
 | 
			
		||||
struct winlink *
 | 
			
		||||
session_new(struct session *s, const char *name, int argc, char **argv,
 | 
			
		||||
    const char *path, int cwd, int idx, char **cause)
 | 
			
		||||
    const char *path, const char *cwd, int idx, char **cause)
 | 
			
		||||
{
 | 
			
		||||
	struct window	*w;
 | 
			
		||||
	struct winlink	*wl;
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										20
									
								
								tmux.h
									
									
									
									
									
								
							
							
						
						
									
										20
									
								
								tmux.h
									
									
									
									
									
								
							@@ -829,7 +829,7 @@ struct window_pane {
 | 
			
		||||
	int		 argc;
 | 
			
		||||
	char	       **argv;
 | 
			
		||||
	char		*shell;
 | 
			
		||||
	int		 cwd;
 | 
			
		||||
	const char	*cwd;
 | 
			
		||||
 | 
			
		||||
	pid_t		 pid;
 | 
			
		||||
	char		 tty[TTY_NAME_MAX];
 | 
			
		||||
@@ -976,7 +976,7 @@ struct session {
 | 
			
		||||
	u_int		 id;
 | 
			
		||||
 | 
			
		||||
	char		*name;
 | 
			
		||||
	int		 cwd;
 | 
			
		||||
	const char	*cwd;
 | 
			
		||||
 | 
			
		||||
	struct timeval	 creation_time;
 | 
			
		||||
	struct timeval	 last_attached_time;
 | 
			
		||||
@@ -1181,7 +1181,7 @@ struct client {
 | 
			
		||||
	struct environ	*environ;
 | 
			
		||||
 | 
			
		||||
	char		*title;
 | 
			
		||||
	int		 cwd;
 | 
			
		||||
	const char	*cwd;
 | 
			
		||||
 | 
			
		||||
	char		*term;
 | 
			
		||||
	char		*ttyname;
 | 
			
		||||
@@ -1536,7 +1536,7 @@ int	options_table_find(const char *, const struct options_table_entry **,
 | 
			
		||||
 | 
			
		||||
/* job.c */
 | 
			
		||||
extern struct joblist all_jobs;
 | 
			
		||||
struct job *job_run(const char *, struct session *, int,
 | 
			
		||||
struct job *job_run(const char *, struct session *, const char *,
 | 
			
		||||
	    void (*)(struct job *), void (*)(void *), void *);
 | 
			
		||||
void	job_free(struct job *);
 | 
			
		||||
void	job_died(struct job *, int);
 | 
			
		||||
@@ -1982,8 +1982,8 @@ struct window	*window_find_by_id(u_int);
 | 
			
		||||
void		 window_update_activity(struct window *);
 | 
			
		||||
struct window	*window_create1(u_int, u_int);
 | 
			
		||||
struct window	*window_create(const char *, int, char **, const char *,
 | 
			
		||||
		     const char *, int, struct environ *, struct termios *,
 | 
			
		||||
		     u_int, u_int, u_int, char **);
 | 
			
		||||
		     const char *, const char *, struct environ *,
 | 
			
		||||
		     struct termios *, u_int, u_int, u_int, char **);
 | 
			
		||||
void		 window_destroy(struct window *);
 | 
			
		||||
struct window_pane *window_get_active_at(struct window *, u_int, u_int);
 | 
			
		||||
struct window_pane *window_find_string(struct window *, const char *);
 | 
			
		||||
@@ -2010,7 +2010,7 @@ struct window_pane *window_pane_find_by_id(u_int);
 | 
			
		||||
struct window_pane *window_pane_create(struct window *, u_int, u_int, u_int);
 | 
			
		||||
void		 window_pane_destroy(struct window_pane *);
 | 
			
		||||
int		 window_pane_spawn(struct window_pane *, int, char **,
 | 
			
		||||
		     const char *, const char *, int, struct environ *,
 | 
			
		||||
		     const char *, const char *, const char *, struct environ *,
 | 
			
		||||
		     struct termios *, char **);
 | 
			
		||||
void		 window_pane_resize(struct window_pane *, u_int, u_int);
 | 
			
		||||
void		 window_pane_alternate_on(struct window_pane *,
 | 
			
		||||
@@ -2144,8 +2144,8 @@ struct session	*session_find(const char *);
 | 
			
		||||
struct session	*session_find_by_id_str(const char *);
 | 
			
		||||
struct session	*session_find_by_id(u_int);
 | 
			
		||||
struct session	*session_create(const char *, int, char **, const char *,
 | 
			
		||||
		     int, struct environ *, struct termios *, int, u_int,
 | 
			
		||||
		     u_int, char **);
 | 
			
		||||
		     const char *, struct environ *, struct termios *, int,
 | 
			
		||||
		     u_int, u_int, char **);
 | 
			
		||||
void		 session_destroy(struct session *);
 | 
			
		||||
void		 session_unref(struct session *);
 | 
			
		||||
int		 session_check_name(const char *);
 | 
			
		||||
@@ -2153,7 +2153,7 @@ void		 session_update_activity(struct session *, struct timeval *);
 | 
			
		||||
struct session	*session_next_session(struct session *);
 | 
			
		||||
struct session	*session_previous_session(struct session *);
 | 
			
		||||
struct winlink	*session_new(struct session *, const char *, int, char **,
 | 
			
		||||
		     const char *, int, int, char **);
 | 
			
		||||
		     const char *, const char *, int, char **);
 | 
			
		||||
struct winlink	*session_attach(struct session *, struct window *, int,
 | 
			
		||||
		     char **);
 | 
			
		||||
int		 session_detach(struct session *, struct winlink *);
 | 
			
		||||
 
 | 
			
		||||
@@ -1488,7 +1488,7 @@ window_copy_copy_pipe(struct window_pane *wp, struct session *sess,
 | 
			
		||||
	format_defaults(ft, NULL, sess, NULL, wp);
 | 
			
		||||
	expanded = format_expand(ft, arg);
 | 
			
		||||
 | 
			
		||||
	job = job_run(expanded, sess, -1, NULL, NULL, NULL);
 | 
			
		||||
	job = job_run(expanded, sess, NULL, NULL, NULL, NULL);
 | 
			
		||||
	bufferevent_write(job->event, buf, len);
 | 
			
		||||
 | 
			
		||||
	free(expanded);
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										22
									
								
								window.c
									
									
									
									
									
								
							
							
						
						
									
										22
									
								
								window.c
									
									
									
									
									
								
							@@ -316,8 +316,8 @@ window_create1(u_int sx, u_int sy)
 | 
			
		||||
 | 
			
		||||
struct window *
 | 
			
		||||
window_create(const char *name, int argc, char **argv, const char *path,
 | 
			
		||||
    const char *shell, int cwd, struct environ *env, struct termios *tio,
 | 
			
		||||
    u_int sx, u_int sy, u_int hlimit, char **cause)
 | 
			
		||||
    const char *shell, const char *cwd, struct environ *env,
 | 
			
		||||
    struct termios *tio, u_int sx, u_int sy, u_int hlimit, char **cause)
 | 
			
		||||
{
 | 
			
		||||
	struct window		*w;
 | 
			
		||||
	struct window_pane	*wp;
 | 
			
		||||
@@ -736,7 +736,7 @@ window_pane_create(struct window *w, u_int sx, u_int sy, u_int hlimit)
 | 
			
		||||
	wp->argc = 0;
 | 
			
		||||
	wp->argv = NULL;
 | 
			
		||||
	wp->shell = NULL;
 | 
			
		||||
	wp->cwd = -1;
 | 
			
		||||
	wp->cwd = NULL;
 | 
			
		||||
 | 
			
		||||
	wp->fd = -1;
 | 
			
		||||
	wp->event = NULL;
 | 
			
		||||
@@ -796,7 +796,7 @@ window_pane_destroy(struct window_pane *wp)
 | 
			
		||||
 | 
			
		||||
	RB_REMOVE(window_pane_tree, &all_window_panes, wp);
 | 
			
		||||
 | 
			
		||||
	close(wp->cwd);
 | 
			
		||||
	free((void *)wp->cwd);
 | 
			
		||||
	free(wp->shell);
 | 
			
		||||
	cmd_free_argv(wp->argc, wp->argv);
 | 
			
		||||
	free(wp);
 | 
			
		||||
@@ -804,12 +804,12 @@ window_pane_destroy(struct window_pane *wp)
 | 
			
		||||
 | 
			
		||||
int
 | 
			
		||||
window_pane_spawn(struct window_pane *wp, int argc, char **argv,
 | 
			
		||||
    const char *path, const char *shell, int cwd, struct environ *env,
 | 
			
		||||
    const char *path, const char *shell, const char *cwd, struct environ *env,
 | 
			
		||||
    struct termios *tio, char **cause)
 | 
			
		||||
{
 | 
			
		||||
	struct winsize	 ws;
 | 
			
		||||
	char		*argv0, *cmd, **argvp, paneid[16];
 | 
			
		||||
	const char	*ptr, *first;
 | 
			
		||||
	const char	*ptr, *first, *home;
 | 
			
		||||
	struct termios	 tio2;
 | 
			
		||||
	int		 i;
 | 
			
		||||
 | 
			
		||||
@@ -826,9 +826,9 @@ window_pane_spawn(struct window_pane *wp, int argc, char **argv,
 | 
			
		||||
		free(wp->shell);
 | 
			
		||||
		wp->shell = xstrdup(shell);
 | 
			
		||||
	}
 | 
			
		||||
	if (cwd != -1) {
 | 
			
		||||
		close(wp->cwd);
 | 
			
		||||
		wp->cwd = dup(cwd);
 | 
			
		||||
	if (cwd != NULL) {
 | 
			
		||||
		free((void *)wp->cwd);
 | 
			
		||||
		wp->cwd = xstrdup(cwd);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	cmd = cmd_stringify_argv(wp->argc, wp->argv);
 | 
			
		||||
@@ -847,8 +847,10 @@ window_pane_spawn(struct window_pane *wp, int argc, char **argv,
 | 
			
		||||
		free(cmd);
 | 
			
		||||
		return (-1);
 | 
			
		||||
	case 0:
 | 
			
		||||
		if (fchdir(wp->cwd) != 0)
 | 
			
		||||
		if (chdir(wp->cwd) != 0) {
 | 
			
		||||
			if ((home = find_home()) == NULL || chdir(home) != 0)
 | 
			
		||||
				chdir("/");
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (tcgetattr(STDIN_FILENO, &tio2) != 0)
 | 
			
		||||
			fatal("tcgetattr failed");
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user