summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--client.c54
-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.c123
-rw-r--r--server-fn.c8
-rw-r--r--session.c17
-rw-r--r--tmux.124
-rw-r--r--tmux.c28
-rw-r--r--tmux.h52
-rw-r--r--window.c16
17 files changed, 362 insertions, 299 deletions
diff --git a/client.c b/client.c
index 5be747dd..82e43992 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);
@@ -257,8 +256,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. */
@@ -316,43 +314,37 @@ 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);
if ((fd = dup(STDIN_FILENO)) == -1)
fatal("dup failed");
- 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);
+ client_write_one(MSG_IDENTIFY_DONE, -1, NULL, 0);
- 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_update_event();
}
/* Helper to send one message. */
@@ -595,8 +587,6 @@ client_dispatch_wait(void *data0)
case MSG_EXITED:
imsg_free(&imsg);
return (-1);
- default:
- fatalx("unexpected message");
}
imsg_free(&imsg);
@@ -675,8 +665,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 70fea988..8dcc5997 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 8c92ca32..85595285 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 7c6ede62..5e69a77c 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 e72a1196..445f0a33 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 b2030e69..bb3a09ec 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 = get_proc_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 57c3d65d..1b0a4e7b 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 <vis.h>
#include "tmux.h"
@@ -54,17 +56,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) {
@@ -91,7 +90,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);
@@ -101,28 +99,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 2e984de5..43d47c47 100644
--- a/cmd-split-window.c
+++ b/cmd-split-window.c
@@ -18,8 +18,11 @@
#include <sys/types.h>
+#include <errno.h>
+#include <fcntl.h>
#include <paths.h>
#include <stdlib.h>
+#include <string.h>
#include <unistd.h>
#include "tmux.h"
@@ -58,16 +61,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);
@@ -83,7 +84,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'))
@@ -156,6 +179,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:
@@ -164,5 +190,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 8f86eba3..19c4dc15 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 = get_proc_cwd(wp->fd)) != NULL)
format_add(ft, "pane_current_path", "%s", cwd);
if ((cmd = get_proc_name(wp->fd, wp->tty)) != NULL) {
diff --git a/options-table.c b/options-table.c
index 22913854..97ca90be 100644
--- a/options-table.c
+++ b/options-table.c
@@ -126,11 +126,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 4bba5f7d..a39f56d8 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,12 +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);
-
- 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);
@@ -876,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);
@@ -951,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 f6485b49..d0747628 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 f967de19..4f6ebed6 100644
--- a/session.c
+++ b/session.c
@@ -85,9 +85,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;
@@ -99,7 +98,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);
@@ -171,7 +170,7 @@ session_destroy(struct session *s)
winlink_remove(&s->windows, wl);
}
- free(s->cwd);
+ close(s->cwd);
RB_INSERT(sessions, &dead_sessions, s);
}
@@ -227,8 +226,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;
@@ -251,8 +250,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);