diff --git a/cmd-new-window.c b/cmd-new-window.c index 065e2b1f..30ddd643 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 258c6327..70891932 100644 --- a/cmd-split-window.c +++ b/cmd-split-window.c @@ -77,13 +77,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 2027f75b..aee095e6 100644 --- a/cmd.c +++ b/cmd.c @@ -1212,3 +1212,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 = osdep_get_cwd(wp->pid)) != NULL) + return (cwd); + } + return (s->cwd); + } + return (cwd); +} diff --git a/osdep-aix.c b/osdep-aix.c index 0dc07d6e..2a291655 100644 --- a/osdep-aix.c +++ b/osdep-aix.c @@ -28,6 +28,12 @@ osdep_get_name(unused int fd, unused char *tty) return (NULL); } +char * +osdep_get_cwd(pid_t pid) +{ + return (NULL); +} + struct event_base * osdep_event_init(void) { diff --git a/osdep-darwin.c b/osdep-darwin.c index 229a4931..c5820df6 100644 --- a/osdep-darwin.c +++ b/osdep-darwin.c @@ -25,6 +25,7 @@ #include char *osdep_get_name(int, char *); +char *osdep_get_cwd(pid_t); struct event_base *osdep_event_init(void); #define unused __attribute__ ((unused)) @@ -48,6 +49,12 @@ osdep_get_name(int fd, unused char *tty) return (strdup(kp.kp_proc.p_comm)); } +char * +osdep_get_cwd(pid_t pid) +{ + return (NULL); +} + struct event_base * osdep_event_init(void) { diff --git a/osdep-dragonfly.c b/osdep-dragonfly.c index b15abf96..22045c37 100644 --- a/osdep-dragonfly.c +++ b/osdep-dragonfly.c @@ -31,6 +31,7 @@ struct kinfo_proc *cmp_procs(struct kinfo_proc *, struct kinfo_proc *); char *osdep_get_name(int, char *); +char *osdep_get_cwd(pid_t); struct event_base *osdep_event_init(void); #ifndef nitems @@ -119,6 +120,12 @@ error: return (NULL); } +char * +osdep_get_cwd(pid_t pid) +{ + return (NULL); +} + struct event_base * osdep_event_init(void) { diff --git a/osdep-freebsd.c b/osdep-freebsd.c index 6b0c8886..1027a648 100644 --- a/osdep-freebsd.c +++ b/osdep-freebsd.c @@ -29,9 +29,11 @@ #include #include #include +#include struct kinfo_proc *cmp_procs(struct kinfo_proc *, struct kinfo_proc *); char *osdep_get_name(int, char *); +char *osdep_get_cwd(pid_t); struct event_base *osdep_event_init(void); #ifndef nitems @@ -130,6 +132,28 @@ error: return (NULL); } +char * +osdep_get_cwd(pid_t pid) +{ + static char wd[PATH_MAX]; + struct kinfo_file *info = NULL; + int nrecords, i; + + if ((info = kinfo_getfile(pid, &nrecords)) == NULL) + return (NULL); + + for (i = 0; i < nrecords; i++) { + if (info[i].kf_fd == KF_FD_TYPE_CWD) { + strlcpy(wd, info[i].kf_path, sizeof wd); + free(info); + return (wd); + } + } + + free(info); + return (NULL); +} + struct event_base * osdep_event_init(void) { diff --git a/osdep-hpux.c b/osdep-hpux.c index 3bec98ee..c962a1f7 100644 --- a/osdep-hpux.c +++ b/osdep-hpux.c @@ -28,6 +28,12 @@ osdep_get_name(unused int fd, unused char *tty) return (NULL); } +char * +osdep_get_cwd(pid_t pid) +{ + return (NULL); +} + struct event_base * osdep_event_init(void) { diff --git a/osdep-linux.c b/osdep-linux.c index b4a1a9f6..6e4430b8 100644 --- a/osdep-linux.c +++ b/osdep-linux.c @@ -60,6 +60,23 @@ osdep_get_name(int fd, unused char *tty) return (buf); } +char * +osdep_get_cwd(pid_t pid) +{ + static char target[MAXPATHLEN + 1]; + char *path; + ssize_t n; + + xasprintf(&path, "/proc/%d/cwd", pid); + n = readlink(path, target, MAXPATHLEN); + xfree(path); + if (n > 0) { + target[n] = '\0'; + return (target); + } + return (NULL); +} + struct event_base * osdep_event_init(void) { diff --git a/osdep-netbsd.c b/osdep-netbsd.c index 64fcb3e0..bb2676cc 100644 --- a/osdep-netbsd.c +++ b/osdep-netbsd.c @@ -34,6 +34,7 @@ struct kinfo_proc2 *cmp_procs(struct kinfo_proc2 *, struct kinfo_proc2 *); char *osdep_get_name(int, char *); +char *osdep_get_cwd(pid_t); struct event_base *osdep_event_init(void); struct kinfo_proc2 * @@ -123,6 +124,12 @@ error: return (NULL); } +char * +osdep_get_cwd(pid_t pid) +{ + return (NULL); +} + struct event_base * osdep_event_init(void) { diff --git a/osdep-openbsd.c b/osdep-openbsd.c index 9eefc44f..4fb75bff 100644 --- a/osdep-openbsd.c +++ b/osdep-openbsd.c @@ -37,6 +37,7 @@ struct kinfo_proc *cmp_procs(struct kinfo_proc *, struct kinfo_proc *); char *osdep_get_name(int, char *); +char *osdep_get_cwd(pid_t); struct event_base *osdep_event_init(void); struct kinfo_proc * @@ -133,6 +134,18 @@ error: return (NULL); } +char* +osdep_get_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); +} + struct event_base * osdep_event_init(void) { diff --git a/osdep-sunos.c b/osdep-sunos.c index 5d1e582e..6ba27691 100644 --- a/osdep-sunos.c +++ b/osdep-sunos.c @@ -64,6 +64,23 @@ osdep_get_name(int fd, char *tty) return (xstrdup(p.pr_fname)); } +char * +osdep_get_cwd(pid_t pid) +{ + static char target[MAXPATHLEN + 1]; + char *path; + ssize_t n; + + xasprintf(&path, "/proc/%u/path/cwd", (u_int) pid); + n = readlink(path, target, MAXPATHLEN); + xfree(path); + if (n > 0) { + target[n] = '\0'; + return (target); + } + return (NULL); +} + struct event_base * osdep_event_init(void) { diff --git a/osdep-unknown.c b/osdep-unknown.c index 3bec98ee..c962a1f7 100644 --- a/osdep-unknown.c +++ b/osdep-unknown.c @@ -28,6 +28,12 @@ osdep_get_name(unused int fd, unused char *tty) return (NULL); } +char * +osdep_get_cwd(pid_t pid) +{ + return (NULL); +} + struct event_base * osdep_event_init(void) { diff --git a/tmux.1 b/tmux.1 index 4c2a8866..556137c4 100644 --- a/tmux.1 +++ b/tmux.1 @@ -1845,10 +1845,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 dc168c9b..6553388b 100644 --- a/tmux.h +++ b/tmux.h @@ -1558,6 +1558,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; @@ -2075,6 +2076,7 @@ u_int utf8_split2(u_int, u_char *); /* osdep-*.c */ char *osdep_get_name(int, char *); +char *osdep_get_cwd(pid_t); struct event_base *osdep_event_init(void); /* log.c */