summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNicholas Marriott <nicholas.marriott@gmail.com>2011-12-09 16:37:29 +0000
committerNicholas Marriott <nicholas.marriott@gmail.com>2011-12-09 16:37:29 +0000
commitc1b994852594b23b7443e01e05257c991684ba4e (patch)
tree7cbfc1dbdeff8197e63167dee96200d122a1be72
parent76862acf3e8ebd3573c1b9415b32731891e5545a (diff)
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 use some platform specific code 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. Idea and support code, Linux, Solaris, FreeBSD bits by Romain Francoise, OpenBSD bits by me.
-rw-r--r--cmd-new-window.c8
-rw-r--r--cmd-split-window.c8
-rw-r--r--cmd.c25
-rw-r--r--osdep-aix.c6
-rw-r--r--osdep-darwin.c7
-rw-r--r--osdep-dragonfly.c7
-rw-r--r--osdep-freebsd.c24
-rw-r--r--osdep-hpux.c6
-rw-r--r--osdep-linux.c17
-rw-r--r--osdep-netbsd.c7
-rw-r--r--osdep-openbsd.c13
-rw-r--r--osdep-sunos.c17
-rw-r--r--osdep-unknown.c6
-rw-r--r--tmux.18
-rw-r--r--tmux.h2
15 files changed, 143 insertions, 18 deletions
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 <unistd.h>
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 <stdlib.h>
#include <string.h>
#include <unistd.h>
+#include <libutil.h>
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 */