From f308ba93aae9de462b1b46e68b47bd77a843eed6 Mon Sep 17 00:00:00 2001 From: Nicholas Marriott Date: Fri, 9 Dec 2011 16:28:18 +0000 Subject: [PATCH] Change the way the working directory for new processes is discovered. If default-path isn't empty, it is used. Otherwise: 1) If tmux neww is run from the command line, the working directory of the client is used. 2) Otherwise sysctl KERN_PROC_CWD is used to retrieve the current working directory of the process in the active pane. 3) If that fails, the directory where the session was created is used. Support code by Romain Francois, OpenBSD specific bits by me. Note this requires a recent userland and kernel with KERN_PROC_CWD. --- cmd-new-window.c | 8 +------- cmd-split-window.c | 8 +------- cmd.c | 25 +++++++++++++++++++++++++ procname.c | 15 ++++++++++++++- tmux.1 | 8 ++++---- tmux.h | 2 ++ 6 files changed, 47 insertions(+), 19 deletions(-) diff --git a/cmd-new-window.c b/cmd-new-window.c index 955f6449..cdf45006 100644 --- a/cmd-new-window.c +++ b/cmd-new-window.c @@ -98,13 +98,7 @@ cmd_new_window_exec(struct cmd *self, struct cmd_ctx *ctx) cmd = options_get_string(&s->options, "default-command"); else cmd = args->argv[0]; - cwd = options_get_string(&s->options, "default-path"); - if (*cwd == '\0') { - if (ctx->cmdclient != NULL && ctx->cmdclient->cwd != NULL) - cwd = ctx->cmdclient->cwd; - else - cwd = s->cwd; - } + cwd = cmd_get_default_path(ctx); if (idx == -1) idx = -1 - options_get_number(&s->options, "base-index"); diff --git a/cmd-split-window.c b/cmd-split-window.c index b1b738b1..7184d964 100644 --- a/cmd-split-window.c +++ b/cmd-split-window.c @@ -78,13 +78,7 @@ cmd_split_window_exec(struct cmd *self, struct cmd_ctx *ctx) cmd = options_get_string(&s->options, "default-command"); else cmd = args->argv[0]; - cwd = options_get_string(&s->options, "default-path"); - if (*cwd == '\0') { - if (ctx->cmdclient != NULL && ctx->cmdclient->cwd != NULL) - cwd = ctx->cmdclient->cwd; - else - cwd = s->cwd; - } + cwd = cmd_get_default_path(ctx); type = LAYOUT_TOPBOTTOM; if (args_has(args, 'h')) diff --git a/cmd.c b/cmd.c index db72337d..6a87f90f 100644 --- a/cmd.c +++ b/cmd.c @@ -1213,3 +1213,28 @@ cmd_template_replace(char *template, const char *s, int idx) return (buf); } + +/* Return the default path for a new pane. */ +char * +cmd_get_default_path(struct cmd_ctx *ctx) +{ + char *cwd; + struct session *s; + struct window_pane *wp; + + if ((s = cmd_current_session(ctx, 0)) == NULL) + return (NULL); + + cwd = options_get_string(&s->options, "default-path"); + if (*cwd == '\0') { + if (ctx->cmdclient != NULL && ctx->cmdclient->cwd != NULL) + return (ctx->cmdclient->cwd); + if (ctx->curclient != NULL) { + wp = s->curw->window->active; + if ((cwd = get_proc_cwd(wp->pid)) != NULL) + return (cwd); + } + return (s->cwd); + } + return (cwd); +} diff --git a/procname.c b/procname.c index 30f71847..370fe342 100644 --- a/procname.c +++ b/procname.c @@ -35,7 +35,8 @@ ((p)->p_stat == SSTOP || (p)->p_stat == SZOMB || (p)->p_stat == SDEAD) struct kinfo_proc *cmp_procs(struct kinfo_proc *, struct kinfo_proc *); -char *get_proc_name(int, char *); +char *get_proc_name(int, char *); +char *get_proc_cwd(pid_t); struct kinfo_proc * cmp_procs(struct kinfo_proc *p1, struct kinfo_proc *p2) @@ -130,3 +131,15 @@ error: free(buf); return (NULL); } + +char* +get_proc_cwd(pid_t pid) +{ + int name[] = { CTL_KERN, KERN_PROC_CWD, (int)pid }; + static char path[MAXPATHLEN]; + size_t pathlen = sizeof path; + + if (sysctl(name, 3, path, &pathlen, NULL, 0) != 0) + return (NULL); + return (path); +} diff --git a/tmux.1 b/tmux.1 index 29a2a92d..4c09de68 100644 --- a/tmux.1 +++ b/tmux.1 @@ -1841,10 +1841,10 @@ to create a login shell using the value of the .Ic default-shell option. .It Ic default-path Ar path -Set the default working directory for processes created from keys, or -interactively from the prompt. -The default is empty, which means to use the working directory of the shell -from which the server was started if it is available or the user's home if not. +Set the default working directory for new panes. +If empty (the default), the working directory is determined from the process +running in the active pane, from the command line environment or from the +working directory where the session was created. .It Ic default-shell Ar path Specify the default shell. This is used as the login shell for new windows when the diff --git a/tmux.h b/tmux.h index 83b07ba7..45e41888 100644 --- a/tmux.h +++ b/tmux.h @@ -1562,6 +1562,7 @@ int cmd_find_index( struct winlink *cmd_find_pane(struct cmd_ctx *, const char *, struct session **, struct window_pane **); char *cmd_template_replace(char *, const char *, int); +char *cmd_get_default_path(struct cmd_ctx *ctx); extern const struct cmd_entry *cmd_table[]; extern const struct cmd_entry cmd_attach_session_entry; extern const struct cmd_entry cmd_bind_key_entry; @@ -2079,6 +2080,7 @@ u_int utf8_split2(u_int, u_char *); /* procname.c */ char *get_proc_name(int, char *); +char *get_proc_cwd(pid_t); /* log.c */ void log_open_tty(int);