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.
pull/1/head
Nicholas Marriott 2011-12-09 16:37:29 +00:00
parent 76862acf3e
commit c1b9948525
15 changed files with 143 additions and 18 deletions

View File

@ -98,13 +98,7 @@ cmd_new_window_exec(struct cmd *self, struct cmd_ctx *ctx)
cmd = options_get_string(&s->options, "default-command"); cmd = options_get_string(&s->options, "default-command");
else else
cmd = args->argv[0]; cmd = args->argv[0];
cwd = options_get_string(&s->options, "default-path"); cwd = cmd_get_default_path(ctx);
if (*cwd == '\0') {
if (ctx->cmdclient != NULL && ctx->cmdclient->cwd != NULL)
cwd = ctx->cmdclient->cwd;
else
cwd = s->cwd;
}
if (idx == -1) if (idx == -1)
idx = -1 - options_get_number(&s->options, "base-index"); idx = -1 - options_get_number(&s->options, "base-index");

View File

@ -77,13 +77,7 @@ cmd_split_window_exec(struct cmd *self, struct cmd_ctx *ctx)
cmd = options_get_string(&s->options, "default-command"); cmd = options_get_string(&s->options, "default-command");
else else
cmd = args->argv[0]; cmd = args->argv[0];
cwd = options_get_string(&s->options, "default-path"); cwd = cmd_get_default_path(ctx);
if (*cwd == '\0') {
if (ctx->cmdclient != NULL && ctx->cmdclient->cwd != NULL)
cwd = ctx->cmdclient->cwd;
else
cwd = s->cwd;
}
type = LAYOUT_TOPBOTTOM; type = LAYOUT_TOPBOTTOM;
if (args_has(args, 'h')) if (args_has(args, 'h'))

25
cmd.c
View File

@ -1212,3 +1212,28 @@ cmd_template_replace(char *template, const char *s, int idx)
return (buf); 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);
}

View File

@ -28,6 +28,12 @@ osdep_get_name(unused int fd, unused char *tty)
return (NULL); return (NULL);
} }
char *
osdep_get_cwd(pid_t pid)
{
return (NULL);
}
struct event_base * struct event_base *
osdep_event_init(void) osdep_event_init(void)
{ {

View File

@ -25,6 +25,7 @@
#include <unistd.h> #include <unistd.h>
char *osdep_get_name(int, char *); char *osdep_get_name(int, char *);
char *osdep_get_cwd(pid_t);
struct event_base *osdep_event_init(void); struct event_base *osdep_event_init(void);
#define unused __attribute__ ((unused)) #define unused __attribute__ ((unused))
@ -48,6 +49,12 @@ osdep_get_name(int fd, unused char *tty)
return (strdup(kp.kp_proc.p_comm)); return (strdup(kp.kp_proc.p_comm));
} }
char *
osdep_get_cwd(pid_t pid)
{
return (NULL);
}
struct event_base * struct event_base *
osdep_event_init(void) osdep_event_init(void)
{ {

View File

@ -31,6 +31,7 @@
struct kinfo_proc *cmp_procs(struct kinfo_proc *, struct kinfo_proc *); struct kinfo_proc *cmp_procs(struct kinfo_proc *, struct kinfo_proc *);
char *osdep_get_name(int, char *); char *osdep_get_name(int, char *);
char *osdep_get_cwd(pid_t);
struct event_base *osdep_event_init(void); struct event_base *osdep_event_init(void);
#ifndef nitems #ifndef nitems
@ -119,6 +120,12 @@ error:
return (NULL); return (NULL);
} }
char *
osdep_get_cwd(pid_t pid)
{
return (NULL);
}
struct event_base * struct event_base *
osdep_event_init(void) osdep_event_init(void)
{ {

View File

@ -29,9 +29,11 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <unistd.h> #include <unistd.h>
#include <libutil.h>
struct kinfo_proc *cmp_procs(struct kinfo_proc *, struct kinfo_proc *); struct kinfo_proc *cmp_procs(struct kinfo_proc *, struct kinfo_proc *);
char *osdep_get_name(int, char *); char *osdep_get_name(int, char *);
char *osdep_get_cwd(pid_t);
struct event_base *osdep_event_init(void); struct event_base *osdep_event_init(void);
#ifndef nitems #ifndef nitems
@ -130,6 +132,28 @@ error:
return (NULL); 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 * struct event_base *
osdep_event_init(void) osdep_event_init(void)
{ {

View File

@ -28,6 +28,12 @@ osdep_get_name(unused int fd, unused char *tty)
return (NULL); return (NULL);
} }
char *
osdep_get_cwd(pid_t pid)
{
return (NULL);
}
struct event_base * struct event_base *
osdep_event_init(void) osdep_event_init(void)
{ {

View File

@ -60,6 +60,23 @@ osdep_get_name(int fd, unused char *tty)
return (buf); 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 * struct event_base *
osdep_event_init(void) osdep_event_init(void)
{ {

View File

@ -34,6 +34,7 @@
struct kinfo_proc2 *cmp_procs(struct kinfo_proc2 *, struct kinfo_proc2 *); struct kinfo_proc2 *cmp_procs(struct kinfo_proc2 *, struct kinfo_proc2 *);
char *osdep_get_name(int, char *); char *osdep_get_name(int, char *);
char *osdep_get_cwd(pid_t);
struct event_base *osdep_event_init(void); struct event_base *osdep_event_init(void);
struct kinfo_proc2 * struct kinfo_proc2 *
@ -123,6 +124,12 @@ error:
return (NULL); return (NULL);
} }
char *
osdep_get_cwd(pid_t pid)
{
return (NULL);
}
struct event_base * struct event_base *
osdep_event_init(void) osdep_event_init(void)
{ {

View File

@ -37,6 +37,7 @@
struct kinfo_proc *cmp_procs(struct kinfo_proc *, struct kinfo_proc *); struct kinfo_proc *cmp_procs(struct kinfo_proc *, struct kinfo_proc *);
char *osdep_get_name(int, char *); char *osdep_get_name(int, char *);
char *osdep_get_cwd(pid_t);
struct event_base *osdep_event_init(void); struct event_base *osdep_event_init(void);
struct kinfo_proc * struct kinfo_proc *
@ -133,6 +134,18 @@ error:
return (NULL); 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 * struct event_base *
osdep_event_init(void) osdep_event_init(void)
{ {

View File

@ -64,6 +64,23 @@ osdep_get_name(int fd, char *tty)
return (xstrdup(p.pr_fname)); 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 * struct event_base *
osdep_event_init(void) osdep_event_init(void)
{ {

View File

@ -28,6 +28,12 @@ osdep_get_name(unused int fd, unused char *tty)
return (NULL); return (NULL);
} }
char *
osdep_get_cwd(pid_t pid)
{
return (NULL);
}
struct event_base * struct event_base *
osdep_event_init(void) osdep_event_init(void)
{ {

8
tmux.1
View File

@ -1845,10 +1845,10 @@ to create a login shell using the value of the
.Ic default-shell .Ic default-shell
option. option.
.It Ic default-path Ar path .It Ic default-path Ar path
Set the default working directory for processes created from keys, or Set the default working directory for new panes.
interactively from the prompt. If empty (the default), the working directory is determined from the process
The default is empty, which means to use the working directory of the shell running in the active pane, from the command line environment or from the
from which the server was started if it is available or the user's home if not. working directory where the session was created.
.It Ic default-shell Ar path .It Ic default-shell Ar path
Specify the default shell. Specify the default shell.
This is used as the login shell for new windows when the This is used as the login shell for new windows when the

2
tmux.h
View File

@ -1558,6 +1558,7 @@ int cmd_find_index(
struct winlink *cmd_find_pane(struct cmd_ctx *, struct winlink *cmd_find_pane(struct cmd_ctx *,
const char *, struct session **, struct window_pane **); const char *, struct session **, struct window_pane **);
char *cmd_template_replace(char *, const char *, int); 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_table[];
extern const struct cmd_entry cmd_attach_session_entry; extern const struct cmd_entry cmd_attach_session_entry;
extern const struct cmd_entry cmd_bind_key_entry; extern const struct cmd_entry cmd_bind_key_entry;
@ -2075,6 +2076,7 @@ u_int utf8_split2(u_int, u_char *);
/* osdep-*.c */ /* osdep-*.c */
char *osdep_get_name(int, char *); char *osdep_get_name(int, char *);
char *osdep_get_cwd(pid_t);
struct event_base *osdep_event_init(void); struct event_base *osdep_event_init(void);
/* log.c */ /* log.c */