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 ~

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.
This commit is contained in:
nicm 2013-10-10 12:26:34 +00:00
parent 165aa59760
commit 282c5f9644
17 changed files with 363 additions and 300 deletions

View File

@ -53,7 +53,6 @@ int client_attached;
int client_get_lock(char *); int client_get_lock(char *);
int client_connect(char *, int); int client_connect(char *, int);
void client_send_identify(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_one(enum msgtype, int, const void *, size_t);
int client_write_server(enum msgtype, const void *, size_t); int client_write_server(enum msgtype, const void *, size_t);
void client_update_event(void); void client_update_event(void);
@ -257,8 +256,7 @@ client_main(int argc, char **argv, int flags)
/* Establish signal handlers. */ /* Establish signal handlers. */
set_signals(client_signal); set_signals(client_signal);
/* Send initial environment. */ /* Send identify messages. */
client_send_environ();
client_send_identify(flags); client_send_identify(flags);
/* Send first command. */ /* Send first command. */
@ -316,45 +314,39 @@ client_main(int argc, char **argv, int flags)
return (client_exitval); return (client_exitval);
} }
/* Send identify message to server with the file descriptors. */ /* Send identify messages to server. */
void void
client_send_identify(int flags) client_send_identify(int flags)
{ {
struct msg_identify_data data; const char *s;
char *term; char **ss;
int fd; int fd;
data.flags = flags; client_write_one(MSG_IDENTIFY_FLAGS, -1, &flags, sizeof flags);
if (getcwd(data.cwd, sizeof data.cwd) == NULL) if ((s = getenv("TERM")) == NULL)
*data.cwd = '\0'; s = "";
client_write_one(MSG_IDENTIFY_TERM, -1, s, strlen(s) + 1);
term = getenv("TERM"); if ((s = ttyname(STDIN_FILENO)) == NULL)
if (term == NULL || s = "";
strlcpy(data.term, term, sizeof data.term) >= sizeof data.term) client_write_one(MSG_IDENTIFY_TTYNAME, -1, s, strlen(s) + 1);
*data.term = '\0';
if ((fd = open(".", O_RDONLY)) == -1)
fd = open("/", O_RDONLY);
client_write_one(MSG_IDENTIFY_CWD, fd, NULL, 0);
if ((fd = dup(STDIN_FILENO)) == -1) if ((fd = dup(STDIN_FILENO)) == -1)
fatal("dup failed"); fatal("dup failed");
imsg_compose(&client_ibuf, client_write_one(MSG_IDENTIFY_STDIN, fd, NULL, 0);
MSG_IDENTIFY, PROTOCOL_VERSION, -1, fd, &data, sizeof data);
for (ss = environ; *ss != NULL; ss++)
client_write_one(MSG_IDENTIFY_ENVIRON, -1, *ss, strlen(*ss) + 1);
client_write_one(MSG_IDENTIFY_DONE, -1, NULL, 0);
client_update_event(); client_update_event();
} }
/* Forward entire environment to server. */
void
client_send_environ(void)
{
struct msg_environ_data data;
char **var;
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);
}
}
/* Helper to send one message. */ /* Helper to send one message. */
int int
client_write_one(enum msgtype type, int fd, const void *buf, size_t len) client_write_one(enum msgtype type, int fd, const void *buf, size_t len)
@ -595,8 +587,6 @@ client_dispatch_wait(void *data0)
case MSG_EXITED: case MSG_EXITED:
imsg_free(&imsg); imsg_free(&imsg);
return (-1); return (-1);
default:
fatalx("unexpected message");
} }
imsg_free(&imsg); imsg_free(&imsg);
@ -675,8 +665,6 @@ client_dispatch_attached(void)
system(data); system(data);
client_write_server(MSG_UNLOCK, NULL, 0); client_write_server(MSG_UNLOCK, NULL, 0);
break; break;
default:
fatalx("unexpected message");
} }
imsg_free(&imsg); imsg_free(&imsg);

View File

@ -18,7 +18,11 @@
#include <sys/types.h> #include <sys/types.h>
#include <errno.h>
#include <fcntl.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "tmux.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 = { const struct cmd_entry cmd_attach_session_entry = {
"attach-session", "attach", "attach-session", "attach",
"drt:", 0, 0, "c:drt:", 0, 0,
"[-dr] " CMD_TARGET_SESSION_USAGE, "[-dr] [-c working-directory] " CMD_TARGET_SESSION_USAGE,
CMD_CANTNEST|CMD_STARTSERVER, CMD_CANTNEST|CMD_STARTSERVER,
NULL, NULL,
cmd_attach_session_exec cmd_attach_session_exec
}; };
enum cmd_retval 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 session *s;
struct client *c; struct client *c;
const char *update; const char *update;
char *cause; char *cause;
u_int i; u_int i;
int fd;
struct format_tree *ft;
char *cp;
if (RB_EMPTY(&sessions)) { if (RB_EMPTY(&sessions)) {
cmdq_error(cmdq, "no 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; cmdq->client->session = s;
notify_attached_session_changed(cmdq->client); notify_attached_session_changed(cmdq->client);
session_update_activity(s); 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); 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) if (rflag)
cmdq->client->flags |= CLIENT_READONLY; 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; struct args *args = self->args;
return (cmd_attach_session(cmdq, args_get(args, 't'), 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')));
} }

View File

@ -19,6 +19,7 @@
#include <sys/types.h> #include <sys/types.h>
#include <errno.h> #include <errno.h>
#include <fcntl.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.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 client *c = cmdq->client;
struct session *s; struct session *s;
FILE *f; FILE *f;
const char *path, *newpath, *wd; const char *path;
char *pdata, *new_pdata, *cause; char *pdata, *new_pdata, *cause;
size_t psize; size_t psize;
u_int limit; u_int limit;
int ch, error, buffer, *buffer_ptr; int ch, error, buffer, *buffer_ptr, cwd, fd;
if (!args_has(args, 'b')) if (!args_has(args, 'b'))
buffer = -1; buffer = -1;
@ -81,20 +82,17 @@ cmd_load_buffer_exec(struct cmd *self, struct cmd_q *cmdq)
return (CMD_RETURN_WAIT); return (CMD_RETURN_WAIT);
} }
if (c != NULL) if (c != NULL && c->session == NULL)
wd = c->cwd; cwd = c->cwd;
else if ((s = cmd_current_session(cmdq, 0)) != NULL) { else if ((s = cmd_current_session(cmdq, 0)) != NULL)
wd = options_get_string(&s->options, "default-path"); cwd = s->cwd;
if (*wd == '\0') else
wd = s->cwd; cwd = AT_FDCWD;
} else
wd = NULL; if ((fd = openat(cwd, path, O_RDONLY)) == -1 ||
if (wd != NULL && *wd != '\0') { (f = fdopen(fd, "rb")) == NULL) {
newpath = get_full_path(wd, path); if (fd != -1)
if (newpath != NULL) close(fd);
path = newpath;
}
if ((f = fopen(path, "rb")) == NULL) {
cmdq_error(cmdq, "%s: %s", path, strerror(errno)); cmdq_error(cmdq, "%s: %s", path, strerror(errno));
return (CMD_RETURN_ERROR); return (CMD_RETURN_ERROR);
} }

View File

@ -18,6 +18,8 @@
#include <sys/types.h> #include <sys/types.h>
#include <errno.h>
#include <fcntl.h>
#include <pwd.h> #include <pwd.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
@ -47,18 +49,15 @@ enum cmd_retval
cmd_new_session_exec(struct cmd *self, struct cmd_q *cmdq) cmd_new_session_exec(struct cmd *self, struct cmd_q *cmdq)
{ {
struct args *args = self->args; struct args *args = self->args;
struct client *c = cmdq->client; struct client *c = cmdq->client, *c0;
struct session *s, *groupwith; struct session *s, *groupwith;
struct window *w; struct window *w;
struct environ env; struct environ env;
struct termios tio, *tiop; struct termios tio, *tiop;
struct passwd *pw; const char *newname, *target, *update, *errstr, *template;
const char *newname, *target, *update, *base, *cwd;
const char *errstr, *template;
char *cmd, *cause, *cp; char *cmd, *cause, *cp;
int detached, idx; int detached, already_attached, idx, cwd, fd = -1;
u_int sx, sy; u_int sx, sy;
int already_attached;
struct format_tree *ft; struct format_tree *ft;
if (args_has(args, 't') && (args->argc != 0 || args_has(args, 'n'))) { 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 (session_find(newname) != NULL) {
if (args_has(args, 'A')) { if (args_has(args, 'A')) {
return (cmd_attach_session(cmdq, newname, return (cmd_attach_session(cmdq, newname,
args_has(args, 'D'), 0)); args_has(args, 'D'), 0, NULL));
} }
cmdq_error(cmdq, "duplicate session: %s", newname); cmdq_error(cmdq, "duplicate session: %s", newname);
return (CMD_RETURN_ERROR); 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) if (c != NULL && c->session != NULL)
already_attached = 1; 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 * Save the termios settings, part of which is used for new windows in
* this session. * 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) { if (server_client_open(c, NULL, &cause) != 0) {
cmdq_error(cmdq, "open terminal failed: %s", cause); cmdq_error(cmdq, "open terminal failed: %s", cause);
free(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. */ /* Find new session size. */
if (c != NULL) { if (c != NULL) {
sx = c->tty.sx; 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); sx = strtonum(args_get(args, 'x'), 1, USHRT_MAX, &errstr);
if (errstr != NULL) { if (errstr != NULL) {
cmdq_error(cmdq, "width %s", errstr); cmdq_error(cmdq, "width %s", errstr);
return (CMD_RETURN_ERROR); goto error;
} }
} }
if (detached && args_has(args, 'y')) { if (detached && args_has(args, 'y')) {
sy = strtonum(args_get(args, 'y'), 1, USHRT_MAX, &errstr); sy = strtonum(args_get(args, 'y'), 1, USHRT_MAX, &errstr);
if (errstr != NULL) { if (errstr != NULL) {
cmdq_error(cmdq, "height %s", errstr); cmdq_error(cmdq, "height %s", errstr);
return (CMD_RETURN_ERROR); goto error;
} }
} }
if (sy > 0 && options_get_number(&global_s_options, "status")) 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) { if (s == NULL) {
cmdq_error(cmdq, "create session failed: %s", cause); cmdq_error(cmdq, "create session failed: %s", cause);
free(cause); free(cause);
return (CMD_RETURN_ERROR); goto error;
} }
environ_free(&env); environ_free(&env);
@ -241,8 +249,8 @@ cmd_new_session_exec(struct cmd *self, struct cmd_q *cmdq)
template = NEW_SESSION_TEMPLATE; template = NEW_SESSION_TEMPLATE;
ft = format_create(); ft = format_create();
if ((c = cmd_find_client(cmdq, NULL, 1)) != NULL) if ((c0 = cmd_find_client(cmdq, NULL, 1)) != NULL)
format_client(ft, c); format_client(ft, c0);
format_session(ft, s); format_session(ft, s);
cp = format_expand(ft, template); cp = format_expand(ft, template);
@ -254,5 +262,13 @@ cmd_new_session_exec(struct cmd *self, struct cmd_q *cmdq)
if (!detached) if (!detached)
cmdq->client_exit = 0; cmdq->client_exit = 0;
if (fd != -1)
close(fd);
return (CMD_RETURN_NORMAL); return (CMD_RETURN_NORMAL);
error:
if (fd != -1)
close(fd);
return (CMD_RETURN_ERROR);
} }

View File

@ -18,7 +18,11 @@
#include <sys/types.h> #include <sys/types.h>
#include <errno.h>
#include <fcntl.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "tmux.h" #include "tmux.h"
@ -45,9 +49,9 @@ cmd_new_window_exec(struct cmd *self, struct cmd_q *cmdq)
struct session *s; struct session *s;
struct winlink *wl; struct winlink *wl;
struct client *c; struct client *c;
const char *cmd, *cwd, *template; const char *cmd, *template;
char *cause, *cp; char *cause, *cp;
int idx, last, detached; int idx, last, detached, cwd, fd = -1;
struct format_tree *ft; struct format_tree *ft;
if (args_has(args, 'a')) { 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"); cmd = options_get_string(&s->options, "default-command");
else else
cmd = args->argv[0]; 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) if (idx == -1)
idx = -1 - options_get_number(&s->options, "base-index"); 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) { if (wl == NULL) {
cmdq_error(cmdq, "create window failed: %s", cause); cmdq_error(cmdq, "create window failed: %s", cause);
free(cause); free(cause);
return (CMD_RETURN_ERROR); goto error;
} }
if (!detached) { if (!detached) {
session_select(s, wl->idx); session_select(s, wl->idx);
@ -136,5 +162,12 @@ cmd_new_window_exec(struct cmd *self, struct cmd_q *cmdq)
format_free(ft); format_free(ft);
} }
if (fd != -1)
close(fd);
return (CMD_RETURN_NORMAL); return (CMD_RETURN_NORMAL);
error:
if (fd != -1)
close(fd);
return (CMD_RETURN_ERROR);
} }

View File

@ -283,27 +283,3 @@ cmdq_flush(struct cmd_q *cmdq)
} }
cmdq->item = NULL; 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 = get_proc_cwd(s->curw->window->active->fd);
else
current = NULL;
return (cmd_default_path(s->cwd, current, cwd));
}

View File

@ -20,8 +20,10 @@
#include <sys/stat.h> #include <sys/stat.h>
#include <errno.h> #include <errno.h>
#include <fcntl.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <unistd.h>
#include <vis.h> #include <vis.h>
#include "tmux.h" #include "tmux.h"
@ -54,17 +56,14 @@ enum cmd_retval
cmd_save_buffer_exec(struct cmd *self, struct cmd_q *cmdq) cmd_save_buffer_exec(struct cmd *self, struct cmd_q *cmdq)
{ {
struct args *args = self->args; struct args *args = self->args;
struct client *c; struct client *c = cmdq->client;
struct session *s; struct session *s;
struct paste_buffer *pb; struct paste_buffer *pb;
const char *path, *newpath, *wd; const char *path;
char *cause, *start, *end; char *cause, *start, *end, *msg;
size_t size, used; size_t size, used, msglen;
int buffer; int cwd, fd, buffer;
mode_t mask;
FILE *f; FILE *f;
char *msg;
size_t msglen;
if (!args_has(args, 'b')) { if (!args_has(args, 'b')) {
if ((pb = paste_get_top(&global_buffers)) == NULL) { if ((pb = paste_get_top(&global_buffers)) == NULL) {
@ -91,7 +90,6 @@ cmd_save_buffer_exec(struct cmd *self, struct cmd_q *cmdq)
else else
path = args->argv[0]; path = args->argv[0];
if (strcmp(path, "-") == 0) { if (strcmp(path, "-") == 0) {
c = cmdq->client;
if (c == NULL) { if (c == NULL) {
cmdq_error(cmdq, "can't write to stdout"); cmdq_error(cmdq, "can't write to stdout");
return (CMD_RETURN_ERROR); return (CMD_RETURN_ERROR);
@ -101,28 +99,26 @@ cmd_save_buffer_exec(struct cmd *self, struct cmd_q *cmdq)
goto do_print; goto do_print;
} }
c = cmdq->client; if (c != NULL && c->session == NULL)
if (c != NULL) cwd = c->cwd;
wd = c->cwd; else if ((s = cmd_current_session(cmdq, 0)) != NULL)
else if ((s = cmd_current_session(cmdq, 0)) != NULL) { cwd = s->cwd;
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");
else else
f = fopen(path, "wb"); cwd = AT_FDCWD;
umask(mask);
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 (f == NULL) {
if (fd != -1)
close(fd);
cmdq_error(cmdq, "%s: %s", path, strerror(errno)); cmdq_error(cmdq, "%s: %s", path, strerror(errno));
return (CMD_RETURN_ERROR); return (CMD_RETURN_ERROR);
} }

View File

@ -18,8 +18,11 @@
#include <sys/types.h> #include <sys/types.h>
#include <errno.h>
#include <fcntl.h>
#include <paths.h> #include <paths.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h>
#include <unistd.h> #include <unistd.h>
#include "tmux.h" #include "tmux.h"
@ -58,16 +61,14 @@ cmd_split_window_exec(struct cmd *self, struct cmd_q *cmdq)
struct window *w; struct window *w;
struct window_pane *wp, *new_wp = NULL; struct window_pane *wp, *new_wp = NULL;
struct environ env; struct environ env;
const char *cmd, *cwd, *shell; const char *cmd, *shell, *template;
char *cause, *new_cause; char *cause, *new_cause, *cp;
u_int hlimit; u_int hlimit;
int size, percentage; int size, percentage, cwd, fd = -1;
enum layout_type type; enum layout_type type;
struct layout_cell *lc; struct layout_cell *lc;
const char *template;
struct client *c; struct client *c;
struct format_tree *ft; struct format_tree *ft;
char *cp;
if ((wl = cmd_find_pane(cmdq, args_get(args, 't'), &s, &wp)) == NULL) if ((wl = cmd_find_pane(cmdq, args_get(args, 't'), &s, &wp)) == NULL)
return (CMD_RETURN_ERROR); return (CMD_RETURN_ERROR);
@ -83,7 +84,29 @@ cmd_split_window_exec(struct cmd *self, struct cmd_q *cmdq)
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 = 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; type = LAYOUT_TOPBOTTOM;
if (args_has(args, 'h')) if (args_has(args, 'h'))
@ -156,6 +179,9 @@ cmd_split_window_exec(struct cmd *self, struct cmd_q *cmdq)
format_free(ft); format_free(ft);
} }
notify_window_layout_changed(w); notify_window_layout_changed(w);
if (fd != -1)
close(fd);
return (CMD_RETURN_NORMAL); return (CMD_RETURN_NORMAL);
error: error:
@ -164,5 +190,7 @@ error:
window_remove_pane(w, new_wp); window_remove_pane(w, new_wp);
cmdq_error(cmdq, "create pane failed: %s", cause); cmdq_error(cmdq, "create pane failed: %s", cause);
free(cause); free(cause);
if (fd != -1)
close(fd);
return (CMD_RETURN_ERROR); return (CMD_RETURN_ERROR);
} }

View File

@ -403,7 +403,6 @@ format_client(struct format_tree *ft, struct client *c)
time_t t; time_t t;
struct session *s; struct session *s;
format_add(ft, "client_cwd", "%s", c->cwd);
format_add(ft, "client_height", "%u", c->tty.sy); format_add(ft, "client_height", "%u", c->tty.sy);
format_add(ft, "client_width", "%u", c->tty.sx); format_add(ft, "client_width", "%u", c->tty.sx);
if (c->tty.path != NULL) 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); format_add(ft, "pane_pid", "%ld", (long) wp->pid);
if (wp->cmd != NULL) if (wp->cmd != NULL)
format_add(ft, "pane_start_command", "%s", wp->cmd); format_add(ft, "pane_start_command", "%s", wp->cmd);
if (wp->cwd != NULL)
format_add(ft, "pane_start_path", "%s", wp->cwd);
if ((cwd = get_proc_cwd(wp->fd)) != NULL) if ((cwd = get_proc_cwd(wp->fd)) != NULL)
format_add(ft, "pane_current_path", "%s", cwd); format_add(ft, "pane_current_path", "%s", cwd);
if ((cmd = get_proc_name(wp->fd, wp->tty)) != NULL) { if ((cmd = get_proc_name(wp->fd, wp->tty)) != NULL) {

View File

@ -126,11 +126,6 @@ const struct options_table_entry session_options_table[] = {
.default_str = "" .default_str = ""
}, },
{ .name = "default-path",
.type = OPTIONS_TABLE_STRING,
.default_str = "~"
},
{ .name = "default-shell", { .name = "default-shell",
.type = OPTIONS_TABLE_STRING, .type = OPTIONS_TABLE_STRING,
.default_str = _PATH_BSHELL .default_str = _PATH_BSHELL

View File

@ -41,8 +41,7 @@ int server_client_assume_paste(struct session *);
int server_client_msg_dispatch(struct client *); int server_client_msg_dispatch(struct client *);
void server_client_msg_command(struct client *, struct imsg *); void server_client_msg_command(struct client *, struct imsg *);
void server_client_msg_identify( void server_client_msg_identify(struct client *, struct imsg *);
struct client *, struct msg_identify_data *, int);
void server_client_msg_shell(struct client *); void server_client_msg_shell(struct client *);
/* Create a new client. */ /* Create a new client. */
@ -151,6 +150,8 @@ server_client_lost(struct client *c)
*/ */
if (c->flags & CLIENT_TERMINAL) if (c->flags & CLIENT_TERMINAL)
tty_free(&c->tty); tty_free(&c->tty);
free(c->ttyname);
free(c->term);
evbuffer_free (c->stdin_data); evbuffer_free (c->stdin_data);
evbuffer_free (c->stdout_data); evbuffer_free (c->stdout_data);
@ -162,6 +163,7 @@ server_client_lost(struct client *c)
screen_free(&c->status); screen_free(&c->status);
free(c->title); free(c->title);
close(c->cwd);
evtimer_del(&c->repeat_timer); evtimer_del(&c->repeat_timer);
@ -179,7 +181,6 @@ server_client_lost(struct client *c)
free(c->prompt_string); free(c->prompt_string);
free(c->prompt_buffer); free(c->prompt_buffer);
free(c->cwd);
c->cmdq->dead = 1; c->cmdq->dead = 1;
cmdq_free(c->cmdq); cmdq_free(c->cmdq);
@ -786,8 +787,6 @@ int
server_client_msg_dispatch(struct client *c) server_client_msg_dispatch(struct client *c)
{ {
struct imsg imsg; struct imsg imsg;
struct msg_identify_data identifydata;
struct msg_environ_data environdata;
struct msg_stdin_data stdindata; struct msg_stdin_data stdindata;
const char *data; const char *data;
ssize_t n, datalen; ssize_t n, datalen;
@ -813,12 +812,14 @@ server_client_msg_dispatch(struct client *c)
log_debug("got %d from client %d", imsg.hdr.type, c->ibuf.fd); log_debug("got %d from client %d", imsg.hdr.type, c->ibuf.fd);
switch (imsg.hdr.type) { switch (imsg.hdr.type) {
case MSG_IDENTIFY: case MSG_IDENTIFY_FLAGS:
if (datalen != sizeof identifydata) case MSG_IDENTIFY_TERM:
fatalx("bad MSG_IDENTIFY size"); case MSG_IDENTIFY_TTYNAME:
memcpy(&identifydata, imsg.data, sizeof identifydata); case MSG_IDENTIFY_CWD:
case MSG_IDENTIFY_STDIN:
server_client_msg_identify(c, &identifydata, imsg.fd); case MSG_IDENTIFY_ENVIRON:
case MSG_IDENTIFY_DONE:
server_client_msg_identify(c, &imsg);
break; break;
case MSG_COMMAND: case MSG_COMMAND:
server_client_msg_command(c, &imsg); server_client_msg_command(c, &imsg);
@ -876,23 +877,12 @@ server_client_msg_dispatch(struct client *c)
server_redraw_client(c); server_redraw_client(c);
recalculate_sizes(); recalculate_sizes();
break; 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: case MSG_SHELL:
if (datalen != 0) if (datalen != 0)
fatalx("bad MSG_SHELL size"); fatalx("bad MSG_SHELL size");
server_client_msg_shell(c); server_client_msg_shell(c);
break; break;
default:
fatalx("unexpected message");
} }
imsg_free(&imsg); imsg_free(&imsg);
@ -951,46 +941,99 @@ error:
/* Handle identify message. */ /* Handle identify message. */
void void
server_client_msg_identify( server_client_msg_identify(struct client *c, struct imsg *imsg)
struct client *c, struct msg_identify_data *data, int fd)
{ {
c->cwd = NULL; const char *data;
data->cwd[(sizeof data->cwd) - 1] = '\0'; size_t datalen;
if (*data->cwd != '\0') int flags;
c->cwd = xstrdup(data->cwd);
if (data->flags & CLIENT_CONTROL) { 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;
#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; c->stdin_callback = control_callback;
evbuffer_free(c->stderr_data); evbuffer_free(c->stderr_data);
c->stderr_data = c->stdout_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"); evbuffer_add_printf(c->stdout_data, "\033P1000p");
server_write_client(c, MSG_STDIN, NULL, 0); server_write_client(c, MSG_STDIN, NULL, 0);
c->tty.fd = -1; c->tty.fd = -1;
c->tty.log_fd = -1; c->tty.log_fd = -1;
close(fd); close(c->fd);
c->fd = -1;
return; return;
} }
if (fd == -1) if (c->fd == -1)
return; return;
if (!isatty(fd)) { if (!isatty(c->fd)) {
close(fd); close(c->fd);
c->fd = -1;
return; return;
} }
data->term[(sizeof data->term) - 1] = '\0'; tty_init(&c->tty, c, c->fd, c->term);
tty_init(&c->tty, c, fd, data->term); if (c->flags & CLIENT_UTF8)
if (data->flags & CLIENT_UTF8)
c->tty.flags |= TTY_UTF8; c->tty.flags |= TTY_UTF8;
if (data->flags & CLIENT_256COLOURS) if (c->flags & CLIENT_256COLOURS)
c->tty.term_flags |= TERM_256COLOURS; c->tty.term_flags |= TERM_256COLOURS;
tty_resize(&c->tty); tty_resize(&c->tty);
if (!(data->flags & CLIENT_CONTROL)) if (!(c->flags & CLIENT_CONTROL))
c->flags |= CLIENT_TERMINAL; c->flags |= CLIENT_TERMINAL;
} }

View File

@ -56,8 +56,8 @@ server_write_ready(struct client *c)
} }
int int
server_write_client( server_write_client(struct client *c, enum msgtype type, const void *buf,
struct client *c, enum msgtype type, const void *buf, size_t len) size_t len)
{ {
struct imsgbuf *ibuf = &c->ibuf; struct imsgbuf *ibuf = &c->ibuf;
int error; int error;
@ -73,8 +73,8 @@ server_write_client(
} }
void void
server_write_session( server_write_session(struct session *s, enum msgtype type, const void *buf,
struct session *s, enum msgtype type, const void *buf, size_t len) size_t len)
{ {
struct client *c; struct client *c;
u_int i; u_int i;

View File

@ -85,9 +85,8 @@ session_find_by_id(u_int id)
/* Create a new session. */ /* Create a new session. */
struct session * struct session *
session_create(const char *name, const char *cmd, const char *cwd, session_create(const char *name, const char *cmd, int cwd, struct environ *env,
struct environ *env, struct termios *tio, int idx, u_int sx, u_int sy, struct termios *tio, int idx, u_int sx, u_int sy, char **cause)
char **cause)
{ {
struct session *s; struct session *s;
@ -99,7 +98,7 @@ session_create(const char *name, const char *cmd, const char *cwd,
fatal("gettimeofday failed"); fatal("gettimeofday failed");
session_update_activity(s); session_update_activity(s);
s->cwd = xstrdup(cwd); s->cwd = dup(cwd);
s->curw = NULL; s->curw = NULL;
TAILQ_INIT(&s->lastw); TAILQ_INIT(&s->lastw);
@ -171,7 +170,7 @@ session_destroy(struct session *s)
winlink_remove(&s->windows, wl); winlink_remove(&s->windows, wl);
} }
free(s->cwd); close(s->cwd);
RB_INSERT(sessions, &dead_sessions, s); RB_INSERT(sessions, &dead_sessions, s);
} }
@ -227,8 +226,8 @@ session_previous_session(struct session *s)
/* Create a new window on a session. */ /* Create a new window on a session. */
struct winlink * struct winlink *
session_new(struct session *s, session_new(struct session *s, const char *name, const char *cmd, int cwd,
const char *name, const char *cmd, const char *cwd, int idx, char **cause) int idx, char **cause)
{ {
struct window *w; struct window *w;
struct winlink *wl; struct winlink *wl;
@ -251,8 +250,8 @@ session_new(struct session *s,
shell = _PATH_BSHELL; shell = _PATH_BSHELL;
hlimit = options_get_number(&s->options, "history-limit"); hlimit = options_get_number(&s->options, "history-limit");
w = window_create( w = window_create(name, cmd, shell, cwd, &env, s->tio, s->sx, s->sy,
name, cmd, shell, cwd, &env, s->tio, s->sx, s->sy, hlimit, cause); hlimit, cause);
if (w == NULL) { if (w == NULL) {
winlink_remove(&s->windows, wl); winlink_remove(&s->windows, wl);
environ_free(&env); environ_free(&env);

24
tmux.1
View File

@ -564,6 +564,7 @@ The following commands are available to manage clients and sessions:
.Bl -tag -width Ds .Bl -tag -width Ds
.It Xo Ic attach-session .It Xo Ic attach-session
.Op Fl dr .Op Fl dr
.Op Fl c Ar working-directory
.Op Fl t Ar target-session .Op Fl t Ar target-session
.Xc .Xc
.D1 (alias: Ic attach ) .D1 (alias: Ic attach )
@ -597,6 +598,10 @@ needs to select the most recently used session, it will prefer the most
recently used recently used
.Em unattached .Em unattached
session. session.
.Pp
.Fl c
will set the session working directory (used for new windows) to
.Ar working-directory .
.It Xo Ic detach-client .It Xo Ic detach-client
.Op Fl P .Op Fl P
.Op Fl a .Op Fl a
@ -1509,13 +1514,6 @@ is not specified, the value of the
option is used. option is used.
.Fl c .Fl c
specifies the working directory in which the new window is created. 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 .Pp
When the shell command completes, the window closes. When the shell command completes, the window closes.
See the See the
@ -2175,17 +2173,6 @@ The default is an empty string, which instructs
to create a login shell using the value of the to create a login shell using the value of the
.Ic default-shell .Ic default-shell
option. option.
.It Ic default-path Ar path
Set the default working directory for new panes.
If empty, 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 .
The default is
.Ql ~ .
.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
@ -3054,7 +3041,6 @@ The following variables are available, where appropriate:
.It Li "client_activity_string" Ta "" Ta "String time client last had activity" .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" Ta "" Ta "Integer time client created"
.It Li "client_created_string" Ta "" Ta "String 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_height" Ta "" Ta "Height of client"
.It Li "client_last_session" Ta "" Ta "Name of the client's last session" .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" .It Li "client_prefix" Ta "" Ta "1 if prefix key has been pressed"

28
tmux.c
View File

@ -124,30 +124,6 @@ areshell(const char *shell)
return (0); 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 void
parseenvironment(void) parseenvironment(void)
{ {
@ -246,7 +222,7 @@ int
main(int argc, char **argv) main(int argc, char **argv)
{ {
struct passwd *pw; struct passwd *pw;
char *s, *path, *label, *home, **var; char *s, *path, *label, *home, **var, tmp[MAXPATHLEN];
int opt, flags, quiet, keys; int opt, flags, quiet, keys;
#ifdef DEBUG #ifdef DEBUG
@ -327,6 +303,8 @@ main(int argc, char **argv)
environ_init(&global_environ); environ_init(&global_environ);
for (var = environ; *var != NULL; var++) for (var = environ; *var != NULL; var++)
environ_put(&global_environ, *var); environ_put(&global_environ, *var);
if (getcwd(tmp, sizeof tmp) != NULL)
environ_set(&global_environ, "PWD", tmp);
options_init(&global_options, NULL); options_init(&global_options, NULL);
options_table_populate_tree(server_options_table, &global_options); options_table_populate_tree(server_options_table, &global_options);

52
tmux.h
View File

@ -58,13 +58,6 @@ extern char **environ;
/* Automatic name refresh interval, in milliseconds. */ /* Automatic name refresh interval, in milliseconds. */
#define NAME_INTERVAL 500 #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 * UTF-8 data size. This must be big enough to hold combined characters as well
* as single. * as single.
@ -463,9 +456,6 @@ enum msgtype {
MSG_SUSPEND, MSG_SUSPEND,
MSG_UNLOCK, MSG_UNLOCK,
MSG_WAKEUP, MSG_WAKEUP,
MSG_IDENTIFY = 300,
MSG_ENVIRON
}; };
/* /*
@ -480,17 +470,6 @@ struct msg_command_data {
int argc; int argc;
}; /* followed by packed argv */ }; /* followed by packed argv */
struct msg_identify_data {
char cwd[MAXPATHLEN];
char term[TERMINAL_LENGTH];
int flags;
};
struct msg_environ_data {
char var[ENVIRON_LENGTH];
};
struct msg_stdin_data { struct msg_stdin_data {
ssize_t size; ssize_t size;
char data[BUFSIZ]; char data[BUFSIZ];
@ -937,7 +916,7 @@ struct window_pane {
char *cmd; char *cmd;
char *shell; char *shell;
char *cwd; int cwd;
pid_t pid; pid_t pid;
char tty[TTY_NAME_MAX]; char tty[TTY_NAME_MAX];
@ -1084,7 +1063,7 @@ struct session {
u_int id; u_int id;
char *name; char *name;
char *cwd; int cwd;
struct timeval creation_time; struct timeval creation_time;
struct timeval activity_time; struct timeval activity_time;
@ -1284,6 +1263,7 @@ RB_HEAD(status_out_tree, status_out);
struct client { struct client {
struct imsgbuf ibuf; struct imsgbuf ibuf;
int fd;
struct event event; struct event event;
int retval; int retval;
@ -1293,8 +1273,10 @@ struct client {
struct environ environ; struct environ environ;
char *title; char *title;
char *cwd; int cwd;
char *term;
char *ttyname;
struct tty tty; struct tty tty;
void (*stdin_callback)(struct client *, int, void *); void (*stdin_callback)(struct client *, int, void *);
@ -1527,7 +1509,6 @@ void logfile(const char *);
const char *getshell(void); const char *getshell(void);
int checkshell(const char *); int checkshell(const char *);
int areshell(const char *); int areshell(const char *);
const char* get_full_path(const char *, const char *);
void setblocking(int, int); void setblocking(int, int);
__dead void shell_exec(const char *, const char *); __dead void shell_exec(const char *, const char *);
@ -1763,7 +1744,6 @@ int cmd_find_index(struct cmd_q *, const char *,
struct winlink *cmd_find_pane(struct cmd_q *, const char *, struct session **, struct winlink *cmd_find_pane(struct cmd_q *, const char *, struct session **,
struct window_pane **); struct window_pane **);
char *cmd_template_replace(const char *, const char *, int); 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_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;
@ -1854,7 +1834,8 @@ extern const struct cmd_entry cmd_up_pane_entry;
extern const struct cmd_entry cmd_wait_for_entry; extern const struct cmd_entry cmd_wait_for_entry;
/* cmd-attach-session.c */ /* 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 */ /* cmd-list.c */
struct cmd_list *cmd_list_parse(int, char **, const char *, u_int, char **); struct cmd_list *cmd_list_parse(int, char **, const char *, u_int, char **);
@ -1872,7 +1853,6 @@ void cmdq_run(struct cmd_q *, struct cmd_list *);
void cmdq_append(struct cmd_q *, struct cmd_list *); void cmdq_append(struct cmd_q *, struct cmd_list *);
int cmdq_continue(struct cmd_q *); int cmdq_continue(struct cmd_q *);
void cmdq_flush(struct cmd_q *); void cmdq_flush(struct cmd_q *);
const char *cmdq_default_path(struct cmd_q *, const char *);
/* cmd-string.c */ /* cmd-string.c */
int cmd_string_parse(const char *, struct cmd_list **, const char *, int cmd_string_parse(const char *, struct cmd_list **, const char *,
@ -2144,9 +2124,9 @@ void winlink_stack_remove(struct winlink_stack *, struct winlink *);
int window_index(struct window *, u_int *); int window_index(struct window *, u_int *);
struct window *window_find_by_id(u_int); struct window *window_find_by_id(u_int);
struct window *window_create1(u_int, u_int); struct window *window_create1(u_int, u_int);
struct window *window_create(const char *, const char *, const char *, struct window *window_create(const char *, const char *, const char *, int,
const char *, struct environ *, struct termios *, struct environ *, struct termios *, u_int, u_int, u_int,
u_int, u_int, u_int, char **); char **);
void window_destroy(struct window *); void window_destroy(struct window *);
struct window_pane *window_get_active_at(struct window *, u_int, u_int); struct window_pane *window_get_active_at(struct window *, u_int, u_int);
void window_set_active_at(struct window *, u_int, u_int); void window_set_active_at(struct window *, u_int, u_int);
@ -2170,8 +2150,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_destroy(struct window_pane *);
void window_pane_timer_start(struct window_pane *); void window_pane_timer_start(struct window_pane *);
int window_pane_spawn(struct window_pane *, const char *, int window_pane_spawn(struct window_pane *, const char *,
const char *, const char *, struct environ *, const char *, int, struct environ *, struct termios *,
struct termios *, char **); char **);
void window_pane_resize(struct window_pane *, u_int, u_int); void window_pane_resize(struct window_pane *, u_int, u_int);
void window_pane_alternate_on(struct window_pane *, void window_pane_alternate_on(struct window_pane *,
struct grid_cell *, int); struct grid_cell *, int);
@ -2307,7 +2287,7 @@ RB_PROTOTYPE(sessions, session, entry, session_cmp);
int session_alive(struct session *); int session_alive(struct session *);
struct session *session_find(const char *); struct session *session_find(const char *);
struct session *session_find_by_id(u_int); 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, struct environ *, struct termios *, int, u_int, u_int,
char **); char **);
void session_destroy(struct session *); void session_destroy(struct session *);
@ -2315,8 +2295,8 @@ int session_check_name(const char *);
void session_update_activity(struct session *); void session_update_activity(struct session *);
struct session *session_next_session(struct session *); struct session *session_next_session(struct session *);
struct session *session_previous_session(struct session *); struct session *session_previous_session(struct session *);
struct winlink *session_new(struct session *, struct winlink *session_new(struct session *, const char *, const char *, int,
const char *, const char *, const char *, int, char **); int, char **);
struct winlink *session_attach( struct winlink *session_attach(
struct session *, struct window *, int, char **); struct session *, struct window *, int, char **);
int session_detach(struct session *, struct winlink *); int session_detach(struct session *, struct winlink *);

View File

@ -309,7 +309,7 @@ window_create1(u_int sx, u_int sy)
struct window * struct window *
window_create(const char *name, const char *cmd, const char *shell, 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) u_int sx, u_int sy, u_int hlimit, char **cause)
{ {
struct window *w; struct window *w;
@ -675,7 +675,7 @@ window_pane_create(struct window *w, u_int sx, u_int sy, u_int hlimit)
wp->cmd = NULL; wp->cmd = NULL;
wp->shell = NULL; wp->shell = NULL;
wp->cwd = NULL; wp->cwd = -1;
wp->fd = -1; wp->fd = -1;
wp->event = NULL; wp->event = NULL;
@ -730,7 +730,7 @@ window_pane_destroy(struct window_pane *wp)
RB_REMOVE(window_pane_tree, &all_window_panes, wp); RB_REMOVE(window_pane_tree, &all_window_panes, wp);
free(wp->cwd); close(wp->cwd);
free(wp->shell); free(wp->shell);
free(wp->cmd); free(wp->cmd);
free(wp); free(wp);
@ -738,7 +738,7 @@ window_pane_destroy(struct window_pane *wp)
int int
window_pane_spawn(struct window_pane *wp, const char *cmd, const char *shell, 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; struct winsize ws;
char *argv0, paneid[16]; char *argv0, paneid[16];
@ -757,9 +757,9 @@ window_pane_spawn(struct window_pane *wp, const char *cmd, const char *shell,
free(wp->shell); free(wp->shell);
wp->shell = xstrdup(shell); wp->shell = xstrdup(shell);
} }
if (cwd != NULL) { if (cwd != -1) {
free(wp->cwd); close(wp->cwd);
wp->cwd = xstrdup(cwd); wp->cwd = dup(cwd);
} }
log_debug("spawn: %s -- %s", wp->shell, wp->cmd); log_debug("spawn: %s -- %s", wp->shell, wp->cmd);
@ -774,7 +774,7 @@ window_pane_spawn(struct window_pane *wp, const char *cmd, const char *shell,
xasprintf(cause, "%s: %s", cmd, strerror(errno)); xasprintf(cause, "%s: %s", cmd, strerror(errno));
return (-1); return (-1);
case 0: case 0:
if (chdir(wp->cwd) != 0) if (fchdir(wp->cwd) != 0)
chdir("/"); chdir("/");
if (tcgetattr(STDIN_FILENO, &tio2) != 0) if (tcgetattr(STDIN_FILENO, &tio2) != 0)