mirror of
				https://github.com/tmux/tmux.git
				synced 2025-11-04 09:26:05 +00:00 
			
		
		
		
	Alter how tmux handles the working directory to internally use file
descriptors rather than strings.
- Each session still has a current working directory.
- New sessions still get their working directory from the client that
  created them or its attached session if any.
- New windows are created by default in the session working directory.
- The -c flag to new, neww, splitw allows the working directory to be
  overridden.
- The -c flag to attach let's the session working directory be changed.
- The default-path option has been removed.
To get the equivalent to default-path '.', do:
        bind c neww -c $PWD
To get the equivalent of default-path '~', do:
        bind c neww -c ~
This also changes the client identify protocol to be a set of messages rather
than one as well as some other changes that should make it easier to make
backwards-compatible protocol changes in future.
			
			
This commit is contained in:
		@@ -18,6 +18,8 @@
 | 
			
		||||
 | 
			
		||||
#include <sys/types.h>
 | 
			
		||||
 | 
			
		||||
#include <errno.h>
 | 
			
		||||
#include <fcntl.h>
 | 
			
		||||
#include <pwd.h>
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include <string.h>
 | 
			
		||||
@@ -47,18 +49,15 @@ enum cmd_retval
 | 
			
		||||
cmd_new_session_exec(struct cmd *self, struct cmd_q *cmdq)
 | 
			
		||||
{
 | 
			
		||||
	struct args		*args = self->args;
 | 
			
		||||
	struct client		*c = cmdq->client;
 | 
			
		||||
	struct client		*c = cmdq->client, *c0;
 | 
			
		||||
	struct session		*s, *groupwith;
 | 
			
		||||
	struct window		*w;
 | 
			
		||||
	struct environ		 env;
 | 
			
		||||
	struct termios		 tio, *tiop;
 | 
			
		||||
	struct passwd		*pw;
 | 
			
		||||
	const char		*newname, *target, *update, *base, *cwd;
 | 
			
		||||
	const char		*errstr, *template;
 | 
			
		||||
	const char		*newname, *target, *update, *errstr, *template;
 | 
			
		||||
	char			*cmd, *cause, *cp;
 | 
			
		||||
	int			 detached, idx;
 | 
			
		||||
	int			 detached, already_attached, idx, cwd, fd = -1;
 | 
			
		||||
	u_int			 sx, sy;
 | 
			
		||||
	int			 already_attached;
 | 
			
		||||
	struct format_tree	*ft;
 | 
			
		||||
 | 
			
		||||
	if (args_has(args, 't') && (args->argc != 0 || args_has(args, 'n'))) {
 | 
			
		||||
@@ -75,7 +74,7 @@ cmd_new_session_exec(struct cmd *self, struct cmd_q *cmdq)
 | 
			
		||||
		if (session_find(newname) != NULL) {
 | 
			
		||||
			if (args_has(args, 'A')) {
 | 
			
		||||
				return (cmd_attach_session(cmdq, newname,
 | 
			
		||||
				    args_has(args, 'D'), 0));
 | 
			
		||||
				    args_has(args, 'D'), 0, NULL));
 | 
			
		||||
			}
 | 
			
		||||
			cmdq_error(cmdq, "duplicate session: %s", newname);
 | 
			
		||||
			return (CMD_RETURN_ERROR);
 | 
			
		||||
@@ -100,6 +99,31 @@ cmd_new_session_exec(struct cmd *self, struct cmd_q *cmdq)
 | 
			
		||||
	if (c != NULL && c->session != NULL)
 | 
			
		||||
		already_attached = 1;
 | 
			
		||||
 | 
			
		||||
	/* Get the new session working directory. */
 | 
			
		||||
	if (args_has(args, 'c')) {
 | 
			
		||||
		ft = format_create();
 | 
			
		||||
		if ((c0 = cmd_find_client(cmdq, NULL, 1)) != NULL)
 | 
			
		||||
			format_client(ft, c0);
 | 
			
		||||
		cp = format_expand(ft, args_get(args, 'c'));
 | 
			
		||||
		format_free(ft);
 | 
			
		||||
 | 
			
		||||
		fd = open(cp, O_RDONLY|O_DIRECTORY);
 | 
			
		||||
		free(cp);
 | 
			
		||||
		if (fd == -1) {
 | 
			
		||||
			cmdq_error(cmdq, "bad working directory: %s",
 | 
			
		||||
			    strerror(errno));
 | 
			
		||||
			return (CMD_RETURN_ERROR);
 | 
			
		||||
		}
 | 
			
		||||
		cwd = fd;
 | 
			
		||||
	} else if (c->session == NULL)
 | 
			
		||||
		cwd = c->cwd;
 | 
			
		||||
	else if ((c0 = cmd_current_client(cmdq)) != NULL)
 | 
			
		||||
		cwd = c0->session->cwd;
 | 
			
		||||
	else {
 | 
			
		||||
		fd = open(".", O_RDONLY);
 | 
			
		||||
		cwd = fd;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * Save the termios settings, part of which is used for new windows in
 | 
			
		||||
	 * this session.
 | 
			
		||||
@@ -121,26 +145,10 @@ cmd_new_session_exec(struct cmd *self, struct cmd_q *cmdq)
 | 
			
		||||
		if (server_client_open(c, NULL, &cause) != 0) {
 | 
			
		||||
			cmdq_error(cmdq, "open terminal failed: %s", cause);
 | 
			
		||||
			free(cause);
 | 
			
		||||
			return (CMD_RETURN_ERROR);
 | 
			
		||||
			goto error;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Get the new session working directory. */
 | 
			
		||||
	if (c != NULL && c->cwd != NULL)
 | 
			
		||||
		base = c->cwd;
 | 
			
		||||
	else {
 | 
			
		||||
		pw = getpwuid(getuid());
 | 
			
		||||
		if (pw->pw_dir != NULL && *pw->pw_dir != '\0')
 | 
			
		||||
			base = pw->pw_dir;
 | 
			
		||||
		else
 | 
			
		||||
			base = "/";
 | 
			
		||||
	}
 | 
			
		||||
	if (args_has(args, 'c'))
 | 
			
		||||
		cwd = args_get(args, 'c');
 | 
			
		||||
	else
 | 
			
		||||
		cwd = options_get_string(&global_s_options, "default-path");
 | 
			
		||||
	cwd = cmd_default_path(base, base, cwd);
 | 
			
		||||
 | 
			
		||||
	/* Find new session size. */
 | 
			
		||||
	if (c != NULL) {
 | 
			
		||||
		sx = c->tty.sx;
 | 
			
		||||
@@ -153,14 +161,14 @@ cmd_new_session_exec(struct cmd *self, struct cmd_q *cmdq)
 | 
			
		||||
		sx = strtonum(args_get(args, 'x'), 1, USHRT_MAX, &errstr);
 | 
			
		||||
		if (errstr != NULL) {
 | 
			
		||||
			cmdq_error(cmdq, "width %s", errstr);
 | 
			
		||||
			return (CMD_RETURN_ERROR);
 | 
			
		||||
			goto error;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	if (detached && args_has(args, 'y')) {
 | 
			
		||||
		sy = strtonum(args_get(args, 'y'), 1, USHRT_MAX, &errstr);
 | 
			
		||||
		if (errstr != NULL) {
 | 
			
		||||
			cmdq_error(cmdq, "height %s", errstr);
 | 
			
		||||
			return (CMD_RETURN_ERROR);
 | 
			
		||||
			goto error;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	if (sy > 0 && options_get_number(&global_s_options, "status"))
 | 
			
		||||
@@ -190,7 +198,7 @@ cmd_new_session_exec(struct cmd *self, struct cmd_q *cmdq)
 | 
			
		||||
	if (s == NULL) {
 | 
			
		||||
		cmdq_error(cmdq, "create session failed: %s", cause);
 | 
			
		||||
		free(cause);
 | 
			
		||||
		return (CMD_RETURN_ERROR);
 | 
			
		||||
		goto error;
 | 
			
		||||
	}
 | 
			
		||||
	environ_free(&env);
 | 
			
		||||
 | 
			
		||||
@@ -241,8 +249,8 @@ cmd_new_session_exec(struct cmd *self, struct cmd_q *cmdq)
 | 
			
		||||
			template = NEW_SESSION_TEMPLATE;
 | 
			
		||||
 | 
			
		||||
		ft = format_create();
 | 
			
		||||
		if ((c = cmd_find_client(cmdq, NULL, 1)) != NULL)
 | 
			
		||||
			format_client(ft, c);
 | 
			
		||||
		if ((c0 = cmd_find_client(cmdq, NULL, 1)) != NULL)
 | 
			
		||||
			format_client(ft, c0);
 | 
			
		||||
		format_session(ft, s);
 | 
			
		||||
 | 
			
		||||
		cp = format_expand(ft, template);
 | 
			
		||||
@@ -254,5 +262,13 @@ cmd_new_session_exec(struct cmd *self, struct cmd_q *cmdq)
 | 
			
		||||
 | 
			
		||||
	if (!detached)
 | 
			
		||||
		cmdq->client_exit = 0;
 | 
			
		||||
 | 
			
		||||
	if (fd != -1)
 | 
			
		||||
		close(fd);
 | 
			
		||||
	return (CMD_RETURN_NORMAL);
 | 
			
		||||
 | 
			
		||||
error:
 | 
			
		||||
	if (fd != -1)
 | 
			
		||||
		close(fd);
 | 
			
		||||
	return (CMD_RETURN_ERROR);
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user