aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNicholas Marriott <nicholas.marriott@gmail.com>2013-10-06 21:02:23 +0100
committerNicholas Marriott <nicholas.marriott@gmail.com>2013-10-06 21:02:23 +0100
commit4538c269d0b366a770a5a5ebfe0c5007569edbc1 (patch)
tree9fac1bc826683d2187e69c3e748da92a7db6a225
parent446eb11cdeba97a24996cee36ba331491aba6211 (diff)
downloadrtmux-4538c269d0b366a770a5a5ebfe0c5007569edbc1.tar.gz
rtmux-4538c269d0b366a770a5a5ebfe0c5007569edbc1.tar.bz2
rtmux-4538c269d0b366a770a5a5ebfe0c5007569edbc1.zip
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 '#{pane_current_path}' The equivalent of default-path '~' is left as an exercise for the reader. 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.
-rw-r--r--client.c60
-rw-r--r--cmd-attach-session.c68
-rw-r--r--cmd-load-buffer.c30
-rw-r--r--cmd-new-session.c74
-rw-r--r--cmd-new-window.c41
-rw-r--r--cmd-queue.c24
-rw-r--r--cmd-save-buffer.c54
-rw-r--r--cmd-split-window.c40
-rw-r--r--format.c3
-rw-r--r--options-table.c5
-rw-r--r--server-client.c125
-rw-r--r--server-fn.c8
-rw-r--r--session.c17
-rw-r--r--tmux.122
-rw-r--r--tmux.c28
-rw-r--r--tmux.h56
-rw-r--r--window.c16
17 files changed, 363 insertions, 308 deletions
diff --git a/client.c b/client.c
index 0a1c8da5..61791876 100644
--- a/client.c
+++ b/client.c
@@ -53,7 +53,6 @@ int client_attached;
int client_get_lock(char *);
int client_connect(char *, int);
void client_send_identify(int);
-void client_send_environ(void);
int client_write_one(enum msgtype, int, const void *, size_t);
int client_write_server(enum msgtype, const void *, size_t);
void client_update_event(void);
@@ -261,8 +260,7 @@ client_main(int argc, char **argv, int flags)
/* Establish signal handlers. */
set_signals(client_signal);
- /* Send initial environment. */
- client_send_environ();
+ /* Send identify messages. */
client_send_identify(flags);
/* Send first command. */
@@ -320,48 +318,38 @@ client_main(int argc, char **argv, int flags)
return (client_exitval);
}
-/* Send identify message to server with the file descriptors. */
+/* Send identify messages to server. */
void
client_send_identify(int flags)
{
- struct msg_identify_data data;
- char *term;
- int fd;
+ const char *s;
+ char **ss;
+ int fd;
- data.flags = flags;
+ client_write_one(MSG_IDENTIFY_FLAGS, -1, &flags, sizeof flags);
- if (getcwd(data.cwd, sizeof data.cwd) == NULL)
- *data.cwd = '\0';
+ if ((s = getenv("TERM")) == NULL)
+ s = "";
+ client_write_one(MSG_IDENTIFY_TERM, -1, s, strlen(s) + 1);
- term = getenv("TERM");
- if (term == NULL ||
- strlcpy(data.term, term, sizeof data.term) >= sizeof data.term)
- *data.term = '\0';
+ if ((s = ttyname(STDIN_FILENO)) == NULL)
+ s = "";
+ client_write_one(MSG_IDENTIFY_TTYNAME, -1, s, strlen(s) + 1);
+
+ if ((fd = open(".", O_RDONLY)) == -1)
+ fd = open("/", O_RDONLY);
+ client_write_one(MSG_IDENTIFY_CWD, fd, NULL, 0);
-#ifdef __CYGWIN__
- snprintf(&data.ttyname, sizeof data.ttyname, "%s",
- ttyname(STDIN_FILENO));
-#else
if ((fd = dup(STDIN_FILENO)) == -1)
fatal("dup failed");
-#endif
- imsg_compose(&client_ibuf,
- MSG_IDENTIFY, PROTOCOL_VERSION, -1, fd, &data, sizeof data);
- client_update_event();
-}
+ client_write_one(MSG_IDENTIFY_STDIN, fd, NULL, 0);
-/* Forward entire environment to server. */
-void
-client_send_environ(void)
-{
- struct msg_environ_data data;
- char **var;
+ for (ss = environ; *ss != NULL; ss++)
+ client_write_one(MSG_IDENTIFY_ENVIRON, -1, *ss, strlen(*ss) + 1);
- for (var = environ; *var != NULL; var++) {
- if (strlcpy(data.var, *var, sizeof data.var) >= sizeof data.var)
- continue;
- client_write_server(MSG_ENVIRON, &data, sizeof data);
- }
+ client_write_one(MSG_IDENTIFY_DONE, -1, NULL, 0);
+
+ client_update_event();
}
/* Helper to send one message. */
@@ -604,8 +592,6 @@ client_dispatch_wait(void *data0)
case MSG_EXITED:
imsg_free(&imsg);
return (-1);
- default:
- fatalx("unexpected message");
}
imsg_free(&imsg);
@@ -684,8 +670,6 @@ client_dispatch_attached(void)
system(data);
client_write_server(MSG_UNLOCK, NULL, 0);
break;
- default:
- fatalx("unexpected message");
}
imsg_free(&imsg);
diff --git a/cmd-attach-session.c b/cmd-attach-session.c
index 7a952e59..f78a89fd 100644
--- a/cmd-attach-session.c
+++ b/cmd-attach-session.c
@@ -18,7 +18,11 @@
#include <sys/types.h>
+#include <errno.h>
+#include <fcntl.h>
#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
#include "tmux.h"
@@ -30,21 +34,25 @@ enum cmd_retval cmd_attach_session_exec(struct cmd *, struct cmd_q *);
const struct cmd_entry cmd_attach_session_entry = {
"attach-session", "attach",
- "drt:", 0, 0,
- "[-dr] " CMD_TARGET_SESSION_USAGE,
+ "c:drt:", 0, 0,
+ "[-dr] [-c working-directory] " CMD_TARGET_SESSION_USAGE,
CMD_CANTNEST|CMD_STARTSERVER,
NULL,
cmd_attach_session_exec
};
enum cmd_retval
-cmd_attach_session(struct cmd_q *cmdq, const char* tflag, int dflag, int rflag)
+cmd_attach_session(struct cmd_q *cmdq, const char *tflag, int dflag, int rflag,
+ const char *cflag)
{
- struct session *s;
- struct client *c;
- const char *update;
- char *cause;
- u_int i;
+ struct session *s;
+ struct client *c;
+ const char *update;
+ char *cause;
+ u_int i;
+ int fd;
+ struct format_tree *ft;
+ char *cp;
if (RB_EMPTY(&sessions)) {
cmdq_error(cmdq, "no sessions");
@@ -73,6 +81,27 @@ cmd_attach_session(struct cmd_q *cmdq, const char* tflag, int dflag, int rflag)
}
}
+ if (cflag != NULL) {
+ ft = format_create();
+ if ((c = cmd_find_client(cmdq, NULL, 1)) != NULL)
+ format_client(ft, c);
+ format_session(ft, s);
+ format_winlink(ft, s, s->curw);
+ format_window_pane(ft, s->curw->window->active);
+ cp = format_expand(ft, cflag);
+ 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);
+ }
+ close(s->cwd);
+ s->cwd = fd;
+ }
+
cmdq->client->session = s;
notify_attached_session_changed(cmdq->client);
session_update_activity(s);
@@ -85,6 +114,27 @@ cmd_attach_session(struct cmd_q *cmdq, const char* tflag, int dflag, int rflag)
return (CMD_RETURN_ERROR);
}
+ if (cflag != NULL) {
+ ft = format_create();
+ if ((c = cmd_find_client(cmdq, NULL, 1)) != NULL)
+ format_client(ft, c);
+ format_session(ft, s);
+ format_winlink(ft, s, s->curw);
+ format_window_pane(ft, s->curw->window->active);
+ cp = format_expand(ft, cflag);
+ 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);
+ }
+ close(s->cwd);
+ s->cwd = fd;
+ }
+
if (rflag)
cmdq->client->flags |= CLIENT_READONLY;
@@ -115,5 +165,5 @@ cmd_attach_session_exec(struct cmd *self, struct cmd_q *cmdq)
struct args *args = self->args;
return (cmd_attach_session(cmdq, args_get(args, 't'),
- args_has(args, 'd'), args_has(args, 'r')));
+ args_has(args, 'd'), args_has(args, 'r'), args_get(args, 'c')));
}
diff --git a/cmd-load-buffer.c b/cmd-load-buffer.c
index 82b8f574..4acbab5e 100644
--- a/cmd-load-buffer.c
+++ b/cmd-load-buffer.c
@@ -19,6 +19,7 @@
#include <sys/types.h>
#include <errno.h>
+#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -49,11 +50,11 @@ cmd_load_buffer_exec(struct cmd *self, struct cmd_q *cmdq)
struct client *c = cmdq->client;
struct session *s;
FILE *f;
- const char *path, *newpath, *wd;
+ const char *path;
char *pdata, *new_pdata, *cause;
size_t psize;
u_int limit;
- int ch, error, buffer, *buffer_ptr;
+ int ch, error, buffer, *buffer_ptr, cwd, fd;
if (!args_has(args, 'b'))
buffer = -1;
@@ -81,20 +82,17 @@ cmd_load_buffer_exec(struct cmd *self, struct cmd_q *cmdq)
return (CMD_RETURN_WAIT);
}
- if (c != NULL)
- wd = c->cwd;
- else if ((s = cmd_current_session(cmdq, 0)) != NULL) {
- wd = options_get_string(&s->options, "default-path");
- if (*wd == '\0')
- wd = s->cwd;
- } else
- wd = NULL;
- if (wd != NULL && *wd != '\0') {
- newpath = get_full_path(wd, path);
- if (newpath != NULL)
- path = newpath;
- }
- if ((f = fopen(path, "rb")) == NULL) {
+ if (c != NULL && c->session == NULL)
+ cwd = c->cwd;
+ else if ((s = cmd_current_session(cmdq, 0)) != NULL)
+ cwd = s->cwd;
+ else
+ cwd = AT_FDCWD;
+
+ if ((fd = openat(cwd, path, O_RDONLY)) == -1 ||
+ (f = fdopen(fd, "rb")) == NULL) {
+ if (fd != -1)
+ close(fd);
cmdq_error(cmdq, "%s: %s", path, strerror(errno));
return (CMD_RETURN_ERROR);
}
diff --git a/cmd-new-session.c b/cmd-new-session.c
index 38c79a6d..3ce24397 100644
--- a/cmd-new-session.c
+++ b/cmd-new-session.c
@@ -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);
}
diff --git a/cmd-new-window.c b/cmd-new-window.c
index e5658b37..f6a925b1 100644
--- a/cmd-new-window.c
+++ b/cmd-new-window.c
@@ -18,7 +18,11 @@
#include <sys/types.h>
+#include <errno.h>
+#include <fcntl.h>
#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
#include "tmux.h"
@@ -45,9 +49,9 @@ cmd_new_window_exec(struct cmd *self, struct cmd_q *cmdq)
struct session *s;
struct winlink *wl;
struct client *c;
- const char *cmd, *cwd, *template;
+ const char *cmd, *template;
char *cause, *cp;
- int idx, last, detached;
+ int idx, last, detached, cwd, fd = -1;
struct format_tree *ft;
if (args_has(args, 'a')) {
@@ -102,7 +106,29 @@ cmd_new_window_exec(struct cmd *self, struct cmd_q *cmdq)
cmd = options_get_string(&s->options, "default-command");
else
cmd = args->argv[0];
- cwd = cmdq_default_path(cmdq, args_get(args, 'c'));
+
+ if (args_has(args, 'c')) {
+ ft = format_create();
+ if ((c = cmd_find_client(cmdq, NULL, 1)) != NULL)
+ format_client(ft, c);
+ format_session(ft, s);
+ format_winlink(ft, s, s->curw);
+ format_window_pane(ft, s->curw->window->active);
+ 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 (cmdq->client->session == NULL)
+ cwd = cmdq->client->cwd;
+ else
+ cwd = s->cwd;
if (idx == -1)
idx = -1 - options_get_number(&s->options, "base-index");
@@ -110,7 +136,7 @@ cmd_new_window_exec(struct cmd *self, struct cmd_q *cmdq)
if (wl == NULL) {
cmdq_error(cmdq, "create window failed: %s", cause);
free(cause);
- return (CMD_RETURN_ERROR);
+ goto error;
}
if (!detached) {
session_select(s, wl->idx);
@@ -136,5 +162,12 @@ cmd_new_window_exec(struct cmd *self, struct cmd_q *cmdq)
format_free(ft);
}
+ if (fd != -1)
+ close(fd);
return (CMD_RETURN_NORMAL);
+
+error:
+ if (fd != -1)
+ close(fd);
+ return (CMD_RETURN_ERROR);
}
diff --git a/cmd-queue.c b/cmd-queue.c
index 7feb25ef..c5905bdb 100644
--- a/cmd-queue.c
+++ b/cmd-queue.c
@@ -283,27 +283,3 @@ cmdq_flush(struct cmd_q *cmdq)
}
cmdq->item = NULL;
}
-
-/* Get default path using command queue. */
-const char *
-cmdq_default_path(struct cmd_q *cmdq, const char *cwd)
-{
- struct client *c = cmdq->client;
- struct session *s;
- const char *current;
-
- if ((s = cmd_current_session(cmdq, 0)) == NULL)
- return (NULL);
-
- if (cwd == NULL)
- cwd = options_get_string(&s->options, "default-path");
-
- if (c != NULL && c->session == NULL && c->cwd != NULL)
- current = c->cwd;
- else if (s->curw != NULL)
- current = osdep_get_cwd(s->curw->window->active->fd);
- else
- current = NULL;
-
- return (cmd_default_path(s->cwd, current, cwd));
-}
diff --git a/cmd-save-buffer.c b/cmd-save-buffer.c
index c6c54019..3788fc22 100644
--- a/cmd-save-buffer.c
+++ b/cmd-save-buffer.c
@@ -20,8 +20,10 @@
#include <sys/stat.h>
#include <errno.h>
+#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
+#include <unistd.h>
#include "tmux.h"
@@ -53,17 +55,14 @@ enum cmd_retval
cmd_save_buffer_exec(struct cmd *self, struct cmd_q *cmdq)
{
struct args *args = self->args;
- struct client *c;
+ struct client *c = cmdq->client;
struct session *s;
struct paste_buffer *pb;
- const char *path, *newpath, *wd;
- char *cause, *start, *end;
- size_t size, used;
- int buffer;
- mode_t mask;
+ const char *path;
+ char *cause, *start, *end, *msg;
+ size_t size, used, msglen;
+ int cwd, fd, buffer;
FILE *f;
- char *msg;
- size_t msglen;
if (!args_has(args, 'b')) {
if ((pb = paste_get_top(&global_buffers)) == NULL) {
@@ -90,7 +89,6 @@ cmd_save_buffer_exec(struct cmd *self, struct cmd_q *cmdq)
else
path = args->argv[0];
if (strcmp(path, "-") == 0) {
- c = cmdq->client;
if (c == NULL) {
cmdq_error(cmdq, "can't write to stdout");
return (CMD_RETURN_ERROR);
@@ -100,28 +98,26 @@ cmd_save_buffer_exec(struct cmd *self, struct cmd_q *cmdq)
goto do_print;
}
- c = cmdq->client;
- if (c != NULL)
- wd = c->cwd;
- else if ((s = cmd_current_session(cmdq, 0)) != NULL) {
- wd = options_get_string(&s->options, "default-path");
- if (*wd == '\0')
- wd = s->cwd;
- } else
- wd = NULL;
- if (wd != NULL && *wd != '\0') {
- newpath = get_full_path(wd, path);
- if (newpath != NULL)
- path = newpath;
- }
-
- mask = umask(S_IRWXG | S_IRWXO);
- if (args_has(self->args, 'a'))
- f = fopen(path, "ab");
+ if (c != NULL && c->session == NULL)
+ cwd = c->cwd;
+ else if ((s = cmd_current_session(cmdq, 0)) != NULL)
+ cwd = s->cwd;
else
- f = fopen(path, "wb");
- umask(mask);
+ cwd = AT_FDCWD;
+
+ f = NULL;
+ if (args_has(self->args, 'a')) {
+ fd = openat(cwd, path, O_CREAT|O_RDWR|O_APPEND, 0600);
+ if (fd != -1)
+ f = fdopen(fd, "ab");
+ } else {
+ fd = openat(cwd, path, O_CREAT|O_RDWR, 0600);
+ if (fd != -1)
+ f = fdopen(fd, "wb");
+ }
if (f == NULL) {
+ if (fd != -1)
+ close(fd);
cmdq_error(cmdq, "%s: %s", path, strerror(errno));
return (CMD_RETURN_ERROR);
}
diff --git a/cmd-split-window.c b/cmd-split-window.c
index a2403253..ef1d3cbc 100644
--- a/cmd-split-window.c
+++ b/cmd-split-window.c
@@ -18,7 +18,10 @@
#include <sys/types.h>
+#include <errno.h>
+#include <fcntl.h>
#include <stdlib.h>
+#include <string.h>
#include <unistd.h>
#include "tmux.h"
@@ -57,16 +60,14 @@ cmd_split_window_exec(struct cmd *self, struct cmd_q *cmdq)
struct window *w;
struct window_pane *wp, *new_wp = NULL;
struct environ env;
- const char *cmd, *cwd, *shell;
- char *cause, *new_cause;
+ const char *cmd, *shell, *template;
+ char *cause, *new_cause, *cp;
u_int hlimit;
- int size, percentage;
+ int size, percentage, cwd, fd = -1;
enum layout_type type;
struct layout_cell *lc;
- const char *template;
struct client *c;
struct format_tree *ft;
- char *cp;
if ((wl = cmd_find_pane(cmdq, args_get(args, 't'), &s, &wp)) == NULL)
return (CMD_RETURN_ERROR);
@@ -82,7 +83,29 @@ cmd_split_window_exec(struct cmd *self, struct cmd_q *cmdq)
cmd = options_get_string(&s->options, "default-command");
else
cmd = args->argv[0];
- cwd = cmdq_default_path(cmdq, args_get(args, 'c'));
+
+ if (args_has(args, 'c')) {
+ ft = format_create();
+ if ((c = cmd_find_client(cmdq, NULL, 1)) != NULL)
+ format_client(ft, c);
+ format_session(ft, s);
+ format_winlink(ft, s, s->curw);
+ format_window_pane(ft, s->curw->window->active);
+ 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 (cmdq->client->session == NULL)
+ cwd = cmdq->client->cwd;
+ else
+ cwd = s->cwd;
type = LAYOUT_TOPBOTTOM;
if (args_has(args, 'h'))
@@ -155,6 +178,9 @@ cmd_split_window_exec(struct cmd *self, struct cmd_q *cmdq)
format_free(ft);
}
notify_window_layout_changed(w);
+
+ if (fd != -1)
+ close(fd);
return (CMD_RETURN_NORMAL);
error:
@@ -163,5 +189,7 @@ error:
window_remove_pane(w, new_wp);
cmdq_error(cmdq, "create pane failed: %s", cause);
free(cause);
+ if (fd != -1)
+ close(fd);
return (CMD_RETURN_ERROR);
}
diff --git a/format.c b/format.c
index ba4b95b2..a7f1fdee 100644
--- a/format.c
+++ b/format.c
@@ -403,7 +403,6 @@ format_client(struct format_tree *ft, struct client *c)
time_t t;
struct session *s;
- format_add(ft, "client_cwd", "%s", c->cwd);
format_add(ft, "client_height", "%u", c->tty.sy);
format_add(ft, "client_width", "%u", c->tty.sx);
if (c->tty.path != NULL)
@@ -552,8 +551,6 @@ format_window_pane(struct format_tree *ft, struct window_pane *wp)
format_add(ft, "pane_pid", "%ld", (long) wp->pid);
if (wp->cmd != NULL)
format_add(ft, "pane_start_command", "%s", wp->cmd);
- if (wp->cwd != NULL)
- format_add(ft, "pane_start_path", "%s", wp->cwd);
if ((cwd = osdep_get_cwd(wp->fd)) != NULL)
format_add(ft, "pane_current_path", "%s", cwd);
if ((cmd = format_get_command(wp)) != NULL) {
diff --git a/options-table.c b/options-table.c
index f6a15472..5da095b1 100644
--- a/options-table.c
+++ b/options-table.c
@@ -125,11 +125,6 @@ const struct options_table_entry session_options_table[] = {
.default_str = ""
},
- { .name = "default-path",
- .type = OPTIONS_TABLE_STRING,
- .default_str = ""
- },
-
{ .name = "default-shell",
.type = OPTIONS_TABLE_STRING,
.default_str = _PATH_BSHELL
diff --git a/server-client.c b/server-client.c
index 11f19376..8a99367c 100644
--- a/server-client.c
+++ b/server-client.c
@@ -41,8 +41,7 @@ int server_client_assume_paste(struct session *);
int server_client_msg_dispatch(struct client *);
void server_client_msg_command(struct client *, struct imsg *);
-void server_client_msg_identify(
- struct client *, struct msg_identify_data *, int);
+void server_client_msg_identify(struct client *, struct imsg *);
void server_client_msg_shell(struct client *);
/* Create a new client. */
@@ -151,6 +150,8 @@ server_client_lost(struct client *c)
*/
if (c->flags & CLIENT_TERMINAL)
tty_free(&c->tty);
+ free(c->ttyname);
+ free(c->term);
evbuffer_free (c->stdin_data);
evbuffer_free (c->stdout_data);
@@ -162,6 +163,7 @@ server_client_lost(struct client *c)
screen_free(&c->status);
free(c->title);
+ close(c->cwd);
evtimer_del(&c->repeat_timer);
@@ -179,7 +181,6 @@ server_client_lost(struct client *c)
free(c->prompt_string);
free(c->prompt_buffer);
- free(c->cwd);
c->cmdq->dead = 1;
cmdq_free(c->cmdq);
@@ -786,8 +787,6 @@ int
server_client_msg_dispatch(struct client *c)
{
struct imsg imsg;
- struct msg_identify_data identifydata;
- struct msg_environ_data environdata;
struct msg_stdin_data stdindata;
const char *data;
ssize_t n, datalen;
@@ -813,14 +812,14 @@ server_client_msg_dispatch(struct client *c)
log_debug("got %d from client %d", imsg.hdr.type, c->ibuf.fd);
switch (imsg.hdr.type) {
- case MSG_IDENTIFY:
- if (datalen != sizeof identifydata)
- fatalx("bad MSG_IDENTIFY size");
- memcpy(&identifydata, imsg.data, sizeof identifydata);
-#ifdef __CYGWIN__
- imsg.fd = open(identifydata.ttyname, O_RDWR|O_NOCTTY);
-#endif
- server_client_msg_identify(c, &identifydata, imsg.fd);
+ case MSG_IDENTIFY_FLAGS:
+ case MSG_IDENTIFY_TERM:
+ case MSG_IDENTIFY_TTYNAME:
+ case MSG_IDENTIFY_CWD:
+ case MSG_IDENTIFY_STDIN:
+ case MSG_IDENTIFY_ENVIRON:
+ case MSG_IDENTIFY_DONE:
+ server_client_msg_identify(c, &imsg);
break;
case MSG_COMMAND:
server_client_msg_command(c, &imsg);
@@ -878,23 +877,12 @@ server_client_msg_dispatch(struct client *c)
server_redraw_client(c);
recalculate_sizes();
break;
- case MSG_ENVIRON:
- if (datalen != sizeof environdata)
- fatalx("bad MSG_ENVIRON size");
- memcpy(&environdata, imsg.data, sizeof environdata);
-
- environdata.var[(sizeof environdata.var) - 1] = '\0';
- if (strchr(environdata.var, '=') != NULL)
- environ_put(&c->environ, environdata.var);
- break;
case MSG_SHELL:
if (datalen != 0)
fatalx("bad MSG_SHELL size");
server_client_msg_shell(c);
break;
- default:
- fatalx("unexpected message");
}
imsg_free(&imsg);
@@ -953,46 +941,99 @@ error:
/* Handle identify message. */
void
-server_client_msg_identify(
- struct client *c, struct msg_identify_data *data, int fd)
+server_client_msg_identify(struct client *c, struct imsg *imsg)
{
- c->cwd = NULL;
- data->cwd[(sizeof data->cwd) - 1] = '\0';
- if (*data->cwd != '\0')
- c->cwd = xstrdup(data->cwd);
+ const char *data;
+ size_t datalen;
+ int flags;
+
+ if (c->flags & CLIENT_IDENTIFIED)
+ fatalx("out-of-order identify message");
+
+ data = imsg->data;
+ datalen = imsg->hdr.len - IMSG_HEADER_SIZE;
+
+ switch (imsg->hdr.type) {
+ case MSG_IDENTIFY_FLAGS:
+ if (datalen != sizeof flags)
+ fatalx("bad MSG_IDENTIFY_FLAGS size");
+ memcpy(&flags, data, sizeof flags);
+ c->flags |= flags;
+ break;
+ case MSG_IDENTIFY_TERM:
+ if (data[datalen - 1] != '\0')
+ fatalx("bad MSG_IDENTIFY_TERM string");
+ c->term = xstrdup(data);
+ break;
+ case MSG_IDENTIFY_TTYNAME:
+ if (data[datalen - 1] != '\0')
+ fatalx("bad MSG_IDENTIFY_TTYNAME string");
+ c->ttyname = xstrdup(data);
+ break;
+ case MSG_IDENTIFY_CWD:
+ if (datalen != 0)
+ fatalx("bad MSG_IDENTIFY_CWD size");
+ c->cwd = imsg->fd;
+ break;
+ case MSG_IDENTIFY_STDIN:
+ if (datalen != 0)
+ fatalx("bad MSG_IDENTIFY_STDIN size");
+ c->fd = imsg->fd;
+ break;
+ case MSG_IDENTIFY_ENVIRON:
+ if (data[datalen - 1] != '\0')
+ fatalx("bad MSG_IDENTIFY_ENVIRON string");
+ if (strchr(data, '=') != NULL)
+ environ_put(&c->environ, data);
+ break;
+ default:
+ break;
+ }
+
+ if (imsg->hdr.type != MSG_IDENTIFY_DONE)
+ return;
+ c->flags |= CLIENT_IDENTIFIED;
- if (data->flags & CLIENT_CONTROL) {
+#ifdef __CYGWIN__
+ c->fd = open(c->ttyname, O_RDWR|O_NOCTTY);
+ c->cwd = open(".", O_RDONLY);
+#endif
+
+ if (c->flags & CLIENT_CONTROL) {
c->stdin_callback = control_callback;
+
evbuffer_free(c->stderr_data);
c->stderr_data = c->stdout_data;
- c->flags |= CLIENT_CONTROL;
- if (data->flags & CLIENT_CONTROLCONTROL)
+
+ if (c->flags & CLIENT_CONTROLCONTROL)
evbuffer_add_printf(c->stdout_data, "\033P1000p");
server_write_client(c, MSG_STDIN, NULL, 0);
c->tty.fd = -1;
c->tty.log_fd = -1;
- close(fd);
+ close(c->fd);
+ c->fd = -1;
+
return;
}
- if (fd == -1)
+ if (c->fd == -1)
return;
- if (!isatty(fd)) {
- close(fd);
+ if (!isatty(c->fd)) {
+ close(c->fd);
+ c->fd = -1;
return;
}
- data->term[(sizeof data->term) - 1] = '\0';
- tty_init(&c->tty, c, fd, data->term);
- if (data->flags & CLIENT_UTF8)
+ tty_init(&c->tty, c, c->fd, c->term);
+ if (c->flags & CLIENT_UTF8)
c->tty.flags |= TTY_UTF8;
- if (data->flags & CLIENT_256COLOURS)
+ if (c->flags & CLIENT_256COLOURS)
c->tty.term_flags |= TERM_256COLOURS;
tty_resize(&c->tty);
- if (!(data->flags & CLIENT_CONTROL))
+ if (!(c->flags & CLIENT_CONTROL))
c->flags |= CLIENT_TERMINAL;
}
diff --git a/server-fn.c b/server-fn.c
index 1b49985f..4fc4eb5c 100644
--- a/server-fn.c
+++ b/server-fn.c
@@ -56,8 +56,8 @@ server_write_ready(struct client *c)
}
int
-server_write_client(
- struct client *c, enum msgtype type, const void *buf, size_t len)
+server_write_client(struct client *c, enum msgtype type, const void *buf,
+ size_t len)
{
struct imsgbuf *ibuf = &c->ibuf;
int error;
@@ -73,8 +73,8 @@ server_write_client(
}
void
-server_write_session(
- struct session *s, enum msgtype type, const void *buf, size_t len)
+server_write_session(struct session *s, enum msgtype type, const void *buf,
+ size_t len)
{
struct client *c;
u_int i;
diff --git a/session.c b/session.c
index bb742d8f..66a52bc6 100644
--- a/session.c
+++ b/session.c
@@ -84,9 +84,8 @@ session_find_by_id(u_int id)
/* Create a new session. */
struct session *
-session_create(const char *name, const char *cmd, const char *cwd,
- struct environ *env, struct termios *tio, int idx, u_int sx, u_int sy,
- char **cause)
+session_create(const char *name, const char *cmd, int cwd, struct environ *env,
+ struct termios *tio, int idx, u_int sx, u_int sy, char **cause)
{
struct session *s;
@@ -98,7 +97,7 @@ session_create(const char *name, const char *cmd, const char *cwd,
fatal("gettimeofday failed");
session_update_activity(s);
- s->cwd = xstrdup(cwd);
+ s->cwd = dup(cwd);
s->curw = NULL;
TAILQ_INIT(&s->lastw);
@@ -170,7 +169,7 @@ session_destroy(struct session *s)
winlink_remove(&s->windows, wl);
}
- free(s->cwd);
+ close(s->cwd);
RB_INSERT(sessions, &dead_sessions, s);
}
@@ -226,8 +225,8 @@ session_previous_session(struct session *s)
/* Create a new window on a session. */
struct winlink *
-session_new(struct session *s,
- const char *name, const char *cmd, const char *cwd, int idx, char **cause)
+session_new(struct session *s, const char *name, const char *cmd, int cwd,
+ int idx, char **cause)
{
struct window *w;
struct winlink *wl;
@@ -250,8 +249,8 @@ session_new(struct session *s,
shell = _PATH_BSHELL;
hlimit = options_get_number(&s->options, "history-limit");
- w = window_create(
- name, cmd, shell, cwd, &env, s->tio, s->sx, s->sy, hlimit, cause);
+ w = window_create(name, cmd, shell, cwd, &env, s->tio, s->sx, s->sy,
+ hlimit, cause);
if (w == NULL) {
winlink_remove(&s->windows, wl);
environ_free(&env);
diff --git a/tmux.1 b/tmux.1
index ba5fe187..07eb93fb 100644
--- a/tmux.1
+++ b/tmux.1
@@ -568,6 +568,7 @@ The following commands are available to manage clients and sessions:
.Bl -tag -width Ds
.It Xo Ic attach-session
.Op Fl dr
+.Op Fl c Ar working-directory
.Op Fl t Ar target-session
.Xc
.D1 (alias: Ic attach )
@@ -601,6 +602,10 @@ needs to select the most recently used session, it will prefer the most
recently used
.Em unattached
session.
+.Pp
+.Fl c
+will set the session working directory (used for new windows) to
+.Ar working-directory .
.It Xo Ic detach-client
.Op Fl P
.Op Fl a
@@ -1513,13 +1518,6 @@ is not specified, the value of the
option is used.
.Fl c
specifies the working directory in which the new window is created.
-It may have an absolute path or one of the following values (or a subdirectory):
-.Bl -column "XXXXXXXXXXXX" "XXXXXXXXXXXXXXXXXXXXXXXX" -offset indent
-.It Li "Empty string" Ta "Current pane's directory"
-.It Li "~" Ta "User's home directory"
-.It Li "-" Ta "Where session was started"
-.It Li "." Ta "Where server was started"
-.El
.Pp
When the shell command completes, the window closes.
See the
@@ -2179,15 +2177,6 @@ The default is an empty string, which instructs
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 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.
-Otherwise the same options are available as for the
-.Fl c
-flag to
-.Ic new-window .
.It Ic default-shell Ar path
Specify the default shell.
This is used as the login shell for new windows when the
@@ -3056,7 +3045,6 @@ The following variables are available, where appropriate:
.It Li "client_activity_string" Ta "" Ta "String time client last had activity"
.It Li "client_created" Ta "" Ta "Integer time client created"
.It Li "client_created_string" Ta "" Ta "String time client created"
-.It Li "client_cwd" Ta "" Ta "Working directory of client"
.It Li "client_height" Ta "" Ta "Height of client"
.It Li "client_last_session" Ta "" Ta "Name of the client's last session"
.It Li "client_prefix" Ta "" Ta "1 if prefix key has been pressed"
diff --git a/tmux.c b/tmux.c
index 76b09cf4..a0359969 100644
--- a/tmux.c
+++ b/tmux.c
@@ -127,30 +127,6 @@ areshell(const char *shell)
return (0);
}
-const char *
-get_full_path(const char *wd, const char *path)
-{
- int fd;
- static char newpath[MAXPATHLEN];
- const char *retval;
-
- fd = open(".", O_RDONLY);
- if (fd == -1)
- return (NULL);
-
- retval = NULL;
- if (chdir(wd) == 0) {
- if (realpath(path, newpath) == 0)
- retval = newpath;
- }
-
- if (fchdir(fd) != 0)
- chdir("/");
- close(fd);
-
- return (retval);
-}
-
void
parseenvironment(void)
{
@@ -249,7 +225,7 @@ int
main(int argc, char **argv)
{
struct passwd *pw;
- char *s, *path, *label, *home, **var;
+ char *s, *path, *label, *home, **var, tmp[MAXPATHLEN];
int opt, flags, quiet, keys;
#if defined(DEBUG) && defined(__OpenBSD__)
@@ -333,6 +309,8 @@ main(int argc, char **argv)
environ_init(&global_environ);
for (var = environ; *var != NULL; var++)
environ_put(&global_environ, *var);
+ if (getcwd(tmp, sizeof tmp) != NULL)
+ environ_set(&global_environ, "PWD", tmp);
options_init(&global_options, NULL);
options_table_populate_tree(server_options_table, &global_options);
diff --git a/tmux.h b/tmux.h
index 5e6de257..a76d1024 100644
--- a/tmux.h
+++ b/tmux.h
@@ -52,13 +52,6 @@ extern char **environ;
#define NAME_INTERVAL 500
/*
- * Maximum sizes of strings in message data. Don't forget to bump
- * PROTOCOL_VERSION if any of these change!
- */
-#define TERMINAL_LENGTH 128 /* length of TERM environment variable */
-#define ENVIRON_LENGTH 1024 /* environment variable length */
-
-/*
* UTF-8 data size. This must be big enough to hold combined characters as well
* as single.
*/
@@ -456,9 +449,6 @@ enum msgtype {
MSG_SUSPEND,
MSG_UNLOCK,
MSG_WAKEUP,
-
- MSG_IDENTIFY = 300,
- MSG_ENVIRON
};
/*
@@ -473,21 +463,6 @@ struct msg_command_data {
int argc;
}; /* followed by packed argv */
-struct msg_identify_data {
- char cwd[MAXPATHLEN];
- char term[TERMINAL_LENGTH];
-
-#ifdef __CYGWIN__
- char ttyname[TTY_NAME_MAX];
-#endif
-
- int flags;
-};
-
-struct msg_environ_data {
- char var[ENVIRON_LENGTH];
-};
-
struct msg_stdin_data {
ssize_t size;
char data[BUFSIZ];
@@ -934,7 +909,7 @@ struct window_pane {
char *cmd;
char *shell;
- char *cwd;
+ int cwd;
pid_t pid;
char tty[TTY_NAME_MAX];
@@ -1081,7 +1056,7 @@ struct session {
u_int id;
char *name;
- char *cwd;
+ int cwd;
struct timeval creation_time;
struct timeval activity_time;
@@ -1281,6 +1256,7 @@ RB_HEAD(status_out_tree, status_out);
struct client {
struct imsgbuf ibuf;
+ int fd;
struct event event;
int retval;
@@ -1290,8 +1266,10 @@ struct client {
struct environ environ;
char *title;
- char *cwd;
+ int cwd;
+ char *term;
+ char *ttyname;
struct tty tty;
void (*stdin_callback)(struct client *, int, void *);
@@ -1524,7 +1502,6 @@ void logfile(const char *);
const char *getshell(void);
int checkshell(const char *);
int areshell(const char *);
-const char* get_full_path(const char *, const char *);
void setblocking(int, int);
__dead void shell_exec(const char *, const char *);
@@ -1760,7 +1737,6 @@ int cmd_find_index(struct cmd_q *, const char *,
struct winlink *cmd_find_pane(struct cmd_q *, const char *, struct session **,
struct window_pane **);
char *cmd_template_replace(const char *, const char *, int);
-const char *cmd_default_path(const char *, const char *, const char *);
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;
@@ -1851,7 +1827,8 @@ extern const struct cmd_entry cmd_up_pane_entry;
extern const struct cmd_entry cmd_wait_for_entry;
/* cmd-attach-session.c */
-enum cmd_retval cmd_attach_session(struct cmd_q *, const char*, int, int);
+enum cmd_retval cmd_attach_session(struct cmd_q *, const char *, int, int,
+ const char *);
/* cmd-list.c */
struct cmd_list *cmd_list_parse(int, char **, const char *, u_int, char **);
@@ -1869,7 +1846,6 @@ void cmdq_run(struct cmd_q *, struct cmd_list *);
void cmdq_append(struct cmd_q *, struct cmd_list *);
int cmdq_continue(struct cmd_q *);
void cmdq_flush(struct cmd_q *);
-const char *cmdq_default_path(struct cmd_q *, const char *);
/* cmd-string.c */
int cmd_string_parse(const char *, struct cmd_list **, const char *,
@@ -2141,9 +2117,9 @@ void winlink_stack_remove(struct winlink_stack *, struct winlink *);
int window_index(struct window *, u_int *);
struct window *window_find_by_id(u_int);
struct window *window_create1(u_int, u_int);
-struct window *window_create(const char *, const char *, const char *,
- const char *, struct environ *, struct termios *,
- u_int, u_int, u_int, char **);
+struct window *window_create(const char *, const char *, const char *, int,
+ struct environ *, struct termios *, u_int, u_int, u_int,
+ char **);
void window_destroy(struct window *);
struct window_pane *window_get_active_at(struct window *, u_int, u_int);
void window_set_active_at(struct window *, u_int, u_int);
@@ -2167,8 +2143,8 @@ struct window_pane *window_pane_create(struct window *, u_int, u_int, u_int);
void window_pane_destroy(struct window_pane *);
void window_pane_timer_start(struct window_pane *);
int window_pane_spawn(struct window_pane *, const char *,
- const char *, const char *, struct environ *,
- struct termios *, char **);
+ const char *, int, struct environ *, struct termios *,
+ char **);
void window_pane_resize(struct window_pane *, u_int, u_int);
void window_pane_alternate_on(struct window_pane *,
struct grid_cell *, int);
@@ -2304,7 +2280,7 @@ RB_PROTOTYPE(sessions, session, entry, session_cmp);
int session_alive(struct session *);
struct session *session_find(const char *);
struct session *session_find_by_id(u_int);
-struct session *session_create(const char *, const char *, const char *,
+struct session *session_create(const char *, const char *, int,
struct environ *, struct termios *, int, u_int, u_int,
char **);
void session_destroy(struct session *);
@@ -2312,8 +2288,8 @@ int session_check_name(const char *);
void session_update_activity(struct session *);
struct session *session_next_session(struct session *);
struct session *session_previous_session(struct session *);
-struct winlink *session_new(struct session *,
- const char *, const char *, const char *, int, char **);
+struct winlink *session_new(struct session *, const char *, const char *, int,
+ int, char **);
struct winlink *session_attach(
struct session *, struct window *, int, char **);
int session_detach(struct session *, struct winlink *);
diff --git a/window.c b/window.c
index 7912bd37..9f47f444 100644
--- a/window.c
+++ b/window.c
@@ -306,7 +306,7 @@ window_create1(u_int sx, u_int sy)
struct window *
window_create(const char *name, const char *cmd, const char *shell,
- const char *cwd, struct environ *env, struct termios *tio,
+ int cwd, struct environ *env, struct termios *tio,
u_int sx, u_int sy, u_int hlimit, char **cause)
{
struct window *w;
@@ -672,7 +672,7 @@ window_pane_create(struct window *w, u_int sx, u_int sy, u_int hlimit)
wp->cmd = NULL;
wp->shell = NULL;
- wp->cwd = NULL;
+ wp->cwd = -1;
wp->fd = -1;
wp->event = NULL;
@@ -727,7 +727,7 @@ window_pane_destroy(struct window_pane *wp)
RB_REMOVE(window_pane_tree, &all_window_panes, wp);
- free(wp->cwd);
+ close(wp->cwd);
free(wp->shell);
free(wp->cmd);
free(wp);
@@ -735,7 +735,7 @@ window_pane_destroy(struct window_pane *wp)
int
window_pane_spawn(struct window_pane *wp, const char *cmd, const char *shell,
- const char *cwd, struct environ *env, struct termios *tio, char **cause)
+ int cwd, struct environ *env, struct termios *tio, char **cause)
{
struct winsize ws;
char *argv0, paneid[16];
@@ -754,9 +754,9 @@ window_pane_spawn(struct window_pane *wp, const char *cmd, const char *shell,
free(wp->shell);
wp->shell = xstrdup(shell);
}
- if (cwd != NULL) {
- free(wp->cwd);
- wp->cwd = xstrdup(cwd);
+ if (cwd != -1) {
+ close(wp->cwd);
+ wp->cwd = dup(cwd);
}
log_debug("spawn: %s -- %s", wp->shell, wp->cmd);
@@ -771,7 +771,7 @@ window_pane_spawn(struct window_pane *wp, const char *cmd, const char *shell,
xasprintf(cause, "%s: %s", cmd, strerror(errno));
return (-1);
case 0:
- if (chdir(wp->cwd) != 0)
+ if (fchdir(wp->cwd) != 0)
chdir("/");
if (tcgetattr(STDIN_FILENO, &tio2) != 0)