aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas <thomas@xteddy.org>2013-10-11 14:33:29 +0100
committerThomas <thomas@xteddy.org>2013-10-11 14:33:29 +0100
commit7f479ffdce8f49f6c57d575b708c4cbe8cbe18df (patch)
treec0b1ddfb340c9bd59bbc02e83f30bf34aeb29a88
parentc190c73240576aa2a8274a305844f1fa7fcb0e71 (diff)
parent4901d9ddc8d8c33ecdca363dcb67e66482745fa5 (diff)
downloadrtmux-7f479ffdce8f49f6c57d575b708c4cbe8cbe18df.tar.gz
rtmux-7f479ffdce8f49f6c57d575b708c4cbe8cbe18df.tar.bz2
rtmux-7f479ffdce8f49f6c57d575b708c4cbe8cbe18df.zip
Merge branch 'obsd-master' into mtemp
-rw-r--r--client.c220
-rw-r--r--cmd-attach-session.c81
-rw-r--r--cmd-bind-key.c27
-rw-r--r--cmd-break-pane.c1
-rw-r--r--cmd-capture-pane.c1
-rw-r--r--cmd-choose-buffer.c1
-rw-r--r--cmd-choose-client.c1
-rw-r--r--cmd-choose-list.c1
-rw-r--r--cmd-choose-tree.c4
-rw-r--r--cmd-clear-history.c1
-rw-r--r--cmd-clock-mode.c1
-rw-r--r--cmd-command-prompt.c2
-rw-r--r--cmd-confirm-before.c1
-rw-r--r--cmd-copy-mode.c1
-rw-r--r--cmd-delete-buffer.c1
-rw-r--r--cmd-detach-client.c23
-rw-r--r--cmd-display-message.c7
-rw-r--r--cmd-display-panes.c1
-rw-r--r--cmd-find-window.c1
-rw-r--r--cmd-has-session.c1
-rw-r--r--cmd-if-shell.c4
-rw-r--r--cmd-join-pane.c2
-rw-r--r--cmd-kill-pane.c1
-rw-r--r--cmd-kill-server.c1
-rw-r--r--cmd-kill-session.c1
-rw-r--r--cmd-kill-window.c1
-rw-r--r--cmd-link-window.c1
-rw-r--r--cmd-list-buffers.c1
-rw-r--r--cmd-list-clients.c1
-rw-r--r--cmd-list-commands.c1
-rw-r--r--cmd-list-keys.c1
-rw-r--r--cmd-list-panes.c1
-rw-r--r--cmd-list-sessions.c1
-rw-r--r--cmd-list-windows.c1
-rw-r--r--cmd-load-buffer.c31
-rw-r--r--cmd-lock-server.c3
-rw-r--r--cmd-move-window.c1
-rw-r--r--cmd-new-session.c93
-rw-r--r--cmd-new-window.c42
-rw-r--r--cmd-paste-buffer.c1
-rw-r--r--cmd-pipe-pane.c1
-rw-r--r--cmd-queue.c22
-rw-r--r--cmd-refresh-client.c3
-rw-r--r--cmd-rename-session.c1
-rw-r--r--cmd-rename-window.c1
-rw-r--r--cmd-resize-pane.c1
-rw-r--r--cmd-respawn-pane.c3
-rw-r--r--cmd-respawn-window.c3
-rw-r--r--cmd-rotate-window.c1
-rw-r--r--cmd-run-shell.c1
-rw-r--r--cmd-save-buffer.c57
-rw-r--r--cmd-select-layout.c3
-rw-r--r--cmd-select-pane.c2
-rw-r--r--cmd-select-window.c4
-rw-r--r--cmd-send-keys.c2
-rw-r--r--cmd-server-info.c1
-rw-r--r--cmd-set-buffer.c1
-rw-r--r--cmd-set-environment.c1
-rw-r--r--cmd-set-option.c2
-rw-r--r--cmd-show-environment.c1
-rw-r--r--cmd-show-messages.c1
-rw-r--r--cmd-show-options.c2
-rw-r--r--cmd-source-file.c4
-rw-r--r--cmd-split-window.c42
-rw-r--r--cmd-start-server.c1
-rw-r--r--cmd-string.c29
-rw-r--r--cmd-suspend-client.c1
-rw-r--r--cmd-swap-pane.c1
-rw-r--r--cmd-swap-window.c1
-rw-r--r--cmd-switch-client.c1
-rw-r--r--cmd-unbind-key.c23
-rw-r--r--cmd-unlink-window.c1
-rw-r--r--cmd-wait-for.c3
-rw-r--r--cmd.c94
-rw-r--r--control.c4
-rw-r--r--format.c153
-rw-r--r--grid.c13
-rw-r--r--input.c151
-rw-r--r--job.c2
-rw-r--r--layout.c5
-rw-r--r--names.c58
-rw-r--r--options-table.c12
-rw-r--r--osdep-openbsd.c24
-rw-r--r--resize.c2
-rw-r--r--server-client.c189
-rw-r--r--server-fn.c24
-rw-r--r--session.c20
-rw-r--r--tmux.160
-rw-r--r--tmux.c72
-rw-r--r--tmux.h170
-rw-r--r--tty-keys.c16
-rw-r--r--window-choose.c25
-rw-r--r--window.c17
93 files changed, 1002 insertions, 896 deletions
diff --git a/client.c b/client.c
index b9e3b30a..e7fa4b71 100644
--- a/client.c
+++ b/client.c
@@ -48,13 +48,14 @@ enum {
} client_exitreason = CLIENT_EXIT_NONE;
int client_exitval;
enum msgtype client_exittype;
+const char *client_exitsession;
int client_attached;
int client_get_lock(char *);
int client_connect(char *, int);
void client_send_identify(int);
-void client_send_environ(void);
-void client_write_server(enum msgtype, void *, size_t);
+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);
void client_signal(int, short, void *);
void client_stdin_callback(int, short, void *);
@@ -138,12 +139,24 @@ failed:
const char *
client_exit_message(void)
{
+ static char msg[256];
+
switch (client_exitreason) {
case CLIENT_EXIT_NONE:
break;
case CLIENT_EXIT_DETACHED:
+ if (client_exitsession != NULL) {
+ xsnprintf(msg, sizeof msg, "detached "
+ "(from session %s)", client_exitsession);
+ return (msg);
+ }
return ("detached");
case CLIENT_EXIT_DETACHED_HUP:
+ if (client_exitsession != NULL) {
+ xsnprintf(msg, sizeof msg, "detached and SIGHUP "
+ "(from session %s)", client_exitsession);
+ return (msg);
+ }
return ("detached and SIGHUP");
case CLIENT_EXIT_LOST_TTY:
return ("lost tty");
@@ -165,12 +178,13 @@ client_main(int argc, char **argv, int flags)
{
struct cmd *cmd;
struct cmd_list *cmdlist;
- struct msg_command_data cmddata;
- int cmdflags, fd;
+ struct msg_command_data *data;
+ int cmdflags, fd, i;
pid_t ppid;
enum msgtype msg;
char *cause;
struct termios tio, saved_tio;
+ size_t size;
/* Set up the initial command. */
cmdflags = 0;
@@ -179,7 +193,7 @@ client_main(int argc, char **argv, int flags)
cmdflags = CMD_STARTSERVER;
} else if (argc == 0) {
msg = MSG_COMMAND;
- cmdflags = CMD_STARTSERVER|CMD_SENDENVIRON|CMD_CANTNEST;
+ cmdflags = CMD_STARTSERVER|CMD_CANTNEST;
} else {
msg = MSG_COMMAND;
@@ -197,8 +211,6 @@ client_main(int argc, char **argv, int flags)
TAILQ_FOREACH(cmd, &cmdlist->list, qentry) {
if (cmd->entry->flags & CMD_STARTSERVER)
cmdflags |= CMD_STARTSERVER;
- if (cmd->entry->flags & CMD_SENDENVIRON)
- cmdflags |= CMD_SENDENVIRON;
if (cmd->entry->flags & CMD_CANTNEST)
cmdflags |= CMD_CANTNEST;
}
@@ -238,7 +250,7 @@ client_main(int argc, char **argv, int flags)
setblocking(STDIN_FILENO, 0);
event_set(&client_stdin, STDIN_FILENO, EV_READ|EV_PERSIST,
client_stdin_callback, NULL);
- if (flags & IDENTIFY_TERMIOS) {
+ if (flags & CLIENT_CONTROLCONTROL) {
if (tcgetattr(STDIN_FILENO, &saved_tio) != 0) {
fprintf(stderr, "tcgetattr failed: %s\n",
strerror(errno));
@@ -261,26 +273,33 @@ client_main(int argc, char **argv, int flags)
/* Establish signal handlers. */
set_signals(client_signal);
- /* Send initial environment. */
- if (cmdflags & CMD_SENDENVIRON)
- client_send_environ();
+ /* Send identify messages. */
client_send_identify(flags);
/* Send first command. */
if (msg == MSG_COMMAND) {
- /* Fill in command line arguments. */
- cmddata.pid = environ_pid;
- cmddata.session_id = environ_session_id;
+ /* How big is the command? */
+ size = 0;
+ for (i = 0; i < argc; i++)
+ size += strlen(argv[i]) + 1;
+ data = xmalloc((sizeof *data) + size);
/* Prepare command for server. */
- cmddata.argc = argc;
- if (cmd_pack_argv(
- argc, argv, cmddata.argv, sizeof cmddata.argv) != 0) {
+ data->argc = argc;
+ if (cmd_pack_argv(argc, argv, (char*)(data + 1), size) != 0) {
fprintf(stderr, "command too long\n");
+ free(data);
return (1);
}
+ size += sizeof *data;
- client_write_server(msg, &cmddata, sizeof cmddata);
+ /* Send the command. */
+ if (client_write_server(msg, data, size) != 0) {
+ fprintf(stderr, "failed to send command\n");
+ free(data);
+ return (1);
+ }
+ free(data);
} else if (msg == MSG_SHELL)
client_write_server(msg, NULL, 0);
@@ -296,37 +315,39 @@ client_main(int argc, char **argv, int flags)
ppid = getppid();
if (client_exittype == MSG_DETACHKILL && ppid > 1)
kill(ppid, SIGHUP);
- } else if (flags & IDENTIFY_TERMIOS) {
- if (flags & IDENTIFY_CONTROL) {
- if (client_exitreason != CLIENT_EXIT_NONE)
- printf("%%exit %s\n", client_exit_message());
- else
- printf("%%exit\n");
- printf("\033\\");
- }
+ } else if (flags & CLIENT_CONTROLCONTROL) {
+ if (client_exitreason != CLIENT_EXIT_NONE)
+ printf("%%exit %s\n", client_exit_message());
+ else
+ printf("%%exit\n");
+ printf("\033\\");
tcsetattr(STDOUT_FILENO, TCSAFLUSH, &saved_tio);
}
setblocking(STDIN_FILENO, 1);
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",
@@ -334,32 +355,39 @@ client_send_identify(int flags)
#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_write_one(MSG_IDENTIFY_STDIN, fd, NULL, 0);
+
+ 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();
}
-/* Forward entire environment to server. */
-void
-client_send_environ(void)
+/* Helper to send one message. */
+int
+client_write_one(enum msgtype type, int fd, const void *buf, size_t len)
{
- struct msg_environ_data data;
- char **var;
+ int retval;
- 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);
- }
+ retval = imsg_compose(&client_ibuf, type, PROTOCOL_VERSION, -1, fd,
+ (void*)buf, len);
+ if (retval != 1)
+ return (-1);
+ return (0);
}
/* Write a message to the server without a file descriptor. */
-void
-client_write_server(enum msgtype type, void *buf, size_t len)
+int
+client_write_server(enum msgtype type, const void *buf, size_t len)
{
- imsg_compose(&client_ibuf, type, PROTOCOL_VERSION, -1, -1, buf, len);
- client_update_event();
+ int retval;
+
+ retval = client_write_one(type, -1, buf, len);
+ if (retval == 0)
+ client_update_event();
+ return (retval);
}
/* Update client event based on whether it needs to read or read and write. */
@@ -493,33 +521,33 @@ client_write(int fd, const char *data, size_t size)
/* Dispatch imsgs when in wait state (before MSG_READY). */
int
-client_dispatch_wait(void *data)
+client_dispatch_wait(void *data0)
{
- struct imsg imsg;
- ssize_t n, datalen;
- struct msg_shell_data shelldata;
- struct msg_exit_data exitdata;
- struct msg_stdout_data stdoutdata;
- struct msg_stderr_data stderrdata;
- const char *shellcmd = data;
+ struct imsg imsg;
+ char *data;
+ ssize_t n, datalen;
+ struct msg_stdout_data stdoutdata;
+ struct msg_stderr_data stderrdata;
+ int retval;
for (;;) {
if ((n = imsg_get(&client_ibuf, &imsg)) == -1)
fatalx("imsg_get failed");
if (n == 0)
return (0);
+
+ data = imsg.data;
datalen = imsg.hdr.len - IMSG_HEADER_SIZE;
log_debug("got %d from server", imsg.hdr.type);
switch (imsg.hdr.type) {
case MSG_EXIT:
case MSG_SHUTDOWN:
- if (datalen != sizeof exitdata) {
- if (datalen != 0)
- fatalx("bad MSG_EXIT size");
- } else {
- memcpy(&exitdata, imsg.data, sizeof exitdata);
- client_exitval = exitdata.retcode;
+ if (datalen != sizeof retval && datalen != 0)
+ fatalx("bad MSG_EXIT size");
+ if (datalen == sizeof retval) {
+ memcpy(&retval, data, sizeof retval);
+ client_exitval = retval;
}
imsg_free(&imsg);
return (-1);
@@ -539,17 +567,19 @@ client_dispatch_wait(void *data)
break;
case MSG_STDOUT:
if (datalen != sizeof stdoutdata)
- fatalx("bad MSG_STDOUT");
- memcpy(&stdoutdata, imsg.data, sizeof stdoutdata);
+ fatalx("bad MSG_STDOUT size");
+ memcpy(&stdoutdata, data, sizeof stdoutdata);
- client_write(STDOUT_FILENO, stdoutdata.data, stdoutdata.size);
+ client_write(STDOUT_FILENO, stdoutdata.data,
+ stdoutdata.size);
break;
case MSG_STDERR:
if (datalen != sizeof stderrdata)
- fatalx("bad MSG_STDERR");
- memcpy(&stderrdata, imsg.data, sizeof stderrdata);
+ fatalx("bad MSG_STDERR size");
+ memcpy(&stderrdata, data, sizeof stderrdata);
- client_write(STDERR_FILENO, stderrdata.data, stderrdata.size);
+ client_write(STDERR_FILENO, stderrdata.data,
+ stderrdata.size);
break;
case MSG_VERSION:
if (datalen != 0)
@@ -563,23 +593,19 @@ client_dispatch_wait(void *data)
imsg_free(&imsg);
return (-1);
case MSG_SHELL:
- if (datalen != sizeof shelldata)
- fatalx("bad MSG_SHELL size");
- memcpy(&shelldata, imsg.data, sizeof shelldata);
- shelldata.shell[(sizeof shelldata.shell) - 1] = '\0';
+ if (datalen == 0 || data[datalen - 1] != '\0')
+ fatalx("bad MSG_SHELL string");
clear_signals(0);
-
- shell_exec(shelldata.shell, shellcmd);
+ shell_exec(data, data0);
/* NOTREACHED */
case MSG_DETACH:
+ case MSG_DETACHKILL:
client_write_server(MSG_EXITING, NULL, 0);
break;
case MSG_EXITED:
imsg_free(&imsg);
return (-1);
- default:
- fatalx("unexpected message");
}
imsg_free(&imsg);
@@ -590,25 +616,28 @@ client_dispatch_wait(void *data)
int
client_dispatch_attached(void)
{
- struct imsg imsg;
- struct msg_lock_data lockdata;
- struct sigaction sigact;
- ssize_t n, datalen;
+ struct imsg imsg;
+ struct sigaction sigact;
+ char *data;
+ ssize_t n, datalen;
for (;;) {
if ((n = imsg_get(&client_ibuf, &imsg)) == -1)
fatalx("imsg_get failed");
if (n == 0)
return (0);
+
+ data = imsg.data;
datalen = imsg.hdr.len - IMSG_HEADER_SIZE;
log_debug("got %d from server", imsg.hdr.type);
switch (imsg.hdr.type) {
- case MSG_DETACHKILL:
case MSG_DETACH:
- if (datalen != 0)
- fatalx("bad MSG_DETACH size");
+ case MSG_DETACHKILL:
+ if (datalen == 0 || data[datalen - 1] != '\0')
+ fatalx("bad MSG_DETACH string");
+ client_exitsession = xstrdup(data);
client_exittype = imsg.hdr.type;
if (imsg.hdr.type == MSG_DETACHKILL)
client_exitreason = CLIENT_EXIT_DETACHED_HUP;
@@ -617,8 +646,7 @@ client_dispatch_attached(void)
client_write_server(MSG_EXITING, NULL, 0);
break;
case MSG_EXIT:
- if (datalen != 0 &&
- datalen != sizeof (struct msg_exit_data))
+ if (datalen != 0 && datalen != sizeof (int))
fatalx("bad MSG_EXIT size");
client_write_server(MSG_EXITING, NULL, 0);
@@ -651,16 +679,12 @@ client_dispatch_attached(void)
kill(getpid(), SIGTSTP);
break;
case MSG_LOCK:
- if (datalen != sizeof lockdata)
- fatalx("bad MSG_LOCK size");
- memcpy(&lockdata, imsg.data, sizeof lockdata);
+ if (datalen == 0 || data[datalen - 1] != '\0')
+ fatalx("bad MSG_LOCK string");
- lockdata.cmd[(sizeof lockdata.cmd) - 1] = '\0';
- system(lockdata.cmd);
+ 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 07185737..e4c0b232 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,22 +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,
- CMD_CANTNEST|CMD_STARTSERVER|CMD_SENDENVIRON,
- NULL,
+ "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");
@@ -70,10 +77,33 @@ cmd_attach_session(struct cmd_q *cmdq, const char* tflag, int dflag, int rflag)
continue;
if (c == cmdq->client)
continue;
- server_write_client(c, MSG_DETACH, NULL, 0);
+ server_write_client(c, MSG_DETACH,
+ c->session->name,
+ strlen(c->session->name) + 1);
}
}
+ 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);
@@ -86,11 +116,34 @@ 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;
- if (dflag)
- server_write_session(s, MSG_DETACH, NULL, 0);
+ if (dflag) {
+ server_write_session(s, MSG_DETACH, s->name,
+ strlen(s->name) + 1);
+ }
update = options_get_string(&s->options, "update-environment");
environ_update(update, &cmdq->client->environ, &s->environ);
@@ -116,5 +169,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-bind-key.c b/cmd-bind-key.c
index 71e79ea0..4ff3ac84 100644
--- a/cmd-bind-key.c
+++ b/cmd-bind-key.c
@@ -27,7 +27,6 @@
* Bind a key to a command, this recurses through cmd_*.
*/
-enum cmd_retval cmd_bind_key_check(struct args *);
enum cmd_retval cmd_bind_key_exec(struct cmd *, struct cmd_q *);
enum cmd_retval cmd_bind_key_table(struct cmd *, struct cmd_q *, int);
@@ -38,24 +37,10 @@ const struct cmd_entry cmd_bind_key_entry = {
"[-cnr] [-t key-table] key command [arguments]",
0,
NULL,
- cmd_bind_key_check,
cmd_bind_key_exec
};
enum cmd_retval
-cmd_bind_key_check(struct args *args)
-{
- if (args_has(args, 't')) {
- if (args->argc != 2 && args->argc != 3)
- return (CMD_RETURN_ERROR);
- } else {
- if (args->argc < 2)
- return (CMD_RETURN_ERROR);
- }
- return (CMD_RETURN_NORMAL);
-}
-
-enum cmd_retval
cmd_bind_key_exec(struct cmd *self, struct cmd_q *cmdq)
{
struct args *args = self->args;
@@ -63,6 +48,18 @@ cmd_bind_key_exec(struct cmd *self, struct cmd_q *cmdq)
struct cmd_list *cmdlist;
int key;
+ if (args_has(args, 't')) {
+ if (args->argc != 2 && args->argc != 3) {
+ cmdq_error(cmdq, "not enough arguments");
+ return (CMD_RETURN_ERROR);
+ }
+ } else {
+ if (args->argc < 2) {
+ cmdq_error(cmdq, "not enough arguments");
+ return (CMD_RETURN_ERROR);
+ }
+ }
+
key = key_string_lookup_string(args->argv[0]);
if (key == KEYC_NONE) {
cmdq_error(cmdq, "unknown key: %s", args->argv[0]);
diff --git a/cmd-break-pane.c b/cmd-break-pane.c
index 8ed9a1a6..d0a5a450 100644
--- a/cmd-break-pane.c
+++ b/cmd-break-pane.c
@@ -34,7 +34,6 @@ const struct cmd_entry cmd_break_pane_entry = {
"[-dP] [-F format] " CMD_TARGET_PANE_USAGE,
0,
NULL,
- NULL,
cmd_break_pane_exec
};
diff --git a/cmd-capture-pane.c b/cmd-capture-pane.c
index f59dc2d6..e157e3cb 100644
--- a/cmd-capture-pane.c
+++ b/cmd-capture-pane.c
@@ -42,7 +42,6 @@ const struct cmd_entry cmd_capture_pane_entry = {
CMD_TARGET_PANE_USAGE,
0,
NULL,
- NULL,
cmd_capture_pane_exec
};
diff --git a/cmd-choose-buffer.c b/cmd-choose-buffer.c
index e6b79d91..d79f6fdc 100644
--- a/cmd-choose-buffer.c
+++ b/cmd-choose-buffer.c
@@ -35,7 +35,6 @@ const struct cmd_entry cmd_choose_buffer_entry = {
CMD_TARGET_WINDOW_USAGE " [-F format] [template]",
0,
NULL,
- NULL,
cmd_choose_buffer_exec
};
diff --git a/cmd-choose-client.c b/cmd-choose-client.c
index 40752a70..93671987 100644
--- a/cmd-choose-client.c
+++ b/cmd-choose-client.c
@@ -37,7 +37,6 @@ const struct cmd_entry cmd_choose_client_entry = {
CMD_TARGET_WINDOW_USAGE " [-F format] [template]",
0,
NULL,
- NULL,
cmd_choose_client_exec
};
diff --git a/cmd-choose-list.c b/cmd-choose-list.c
index 15f87294..c3caabba 100644
--- a/cmd-choose-list.c
+++ b/cmd-choose-list.c
@@ -39,7 +39,6 @@ const struct cmd_entry cmd_choose_list_entry = {
"[-l items] " CMD_TARGET_WINDOW_USAGE "[template]",
0,
NULL,
- NULL,
cmd_choose_list_exec
};
diff --git a/cmd-choose-tree.c b/cmd-choose-tree.c
index a9b6ffbc..be3bd69a 100644
--- a/cmd-choose-tree.c
+++ b/cmd-choose-tree.c
@@ -41,7 +41,6 @@ const struct cmd_entry cmd_choose_tree_entry = {
"[-W format] " CMD_TARGET_WINDOW_USAGE,
0,
NULL,
- NULL,
cmd_choose_tree_exec
};
@@ -51,7 +50,6 @@ const struct cmd_entry cmd_choose_session_entry = {
CMD_TARGET_WINDOW_USAGE " [-F format] [template]",
0,
NULL,
- NULL,
cmd_choose_tree_exec
};
@@ -61,7 +59,6 @@ const struct cmd_entry cmd_choose_window_entry = {
CMD_TARGET_WINDOW_USAGE "[-F format] [template]",
0,
NULL,
- NULL,
cmd_choose_tree_exec
};
@@ -228,7 +225,6 @@ windows_only:
free(final_win_template_last);
window_choose_ready(wl->window->active, cur_win, NULL);
- window_choose_collapse_all(wl->window->active);
if (args_has(args, 'u')) {
window_choose_expand_all(wl->window->active);
diff --git a/cmd-clear-history.c b/cmd-clear-history.c
index aebaa27d..cce3ea18 100644
--- a/cmd-clear-history.c
+++ b/cmd-clear-history.c
@@ -32,7 +32,6 @@ const struct cmd_entry cmd_clear_history_entry = {
CMD_TARGET_PANE_USAGE,
0,
NULL,
- NULL,
cmd_clear_history_exec
};
diff --git a/cmd-clock-mode.c b/cmd-clock-mode.c
index 872f3d53..50e4ab8b 100644
--- a/cmd-clock-mode.c
+++ b/cmd-clock-mode.c
@@ -32,7 +32,6 @@ const struct cmd_entry cmd_clock_mode_entry = {
CMD_TARGET_PANE_USAGE,
0,
NULL,
- NULL,
cmd_clock_mode_exec
};
diff --git a/cmd-command-prompt.c b/cmd-command-prompt.c
index 3bb79ed9..759d578b 100644
--- a/cmd-command-prompt.c
+++ b/cmd-command-prompt.c
@@ -30,7 +30,6 @@
*/
void cmd_command_prompt_key_binding(struct cmd *, int);
-int cmd_command_prompt_check(struct args *);
enum cmd_retval cmd_command_prompt_exec(struct cmd *, struct cmd_q *);
int cmd_command_prompt_callback(void *, const char *);
@@ -42,7 +41,6 @@ const struct cmd_entry cmd_command_prompt_entry = {
"[-I inputs] [-p prompts] " CMD_TARGET_CLIENT_USAGE " [template]",
0,
cmd_command_prompt_key_binding,
- NULL,
cmd_command_prompt_exec
};
diff --git a/cmd-confirm-before.c b/cmd-confirm-before.c
index e670f69c..9266721f 100644
--- a/cmd-confirm-before.c
+++ b/cmd-confirm-before.c
@@ -38,7 +38,6 @@ const struct cmd_entry cmd_confirm_before_entry = {
"[-p prompt] " CMD_TARGET_CLIENT_USAGE " command",
0,
cmd_confirm_before_key_binding,
- NULL,
cmd_confirm_before_exec
};
diff --git a/cmd-copy-mode.c b/cmd-copy-mode.c
index 40584a28..f11c7aff 100644
--- a/cmd-copy-mode.c
+++ b/cmd-copy-mode.c
@@ -33,7 +33,6 @@ const struct cmd_entry cmd_copy_mode_entry = {
"[-u] " CMD_TARGET_PANE_USAGE,
0,
cmd_copy_mode_key_binding,
- NULL,
cmd_copy_mode_exec
};
diff --git a/cmd-delete-buffer.c b/cmd-delete-buffer.c
index bc3982ca..b8f55db4 100644
--- a/cmd-delete-buffer.c
+++ b/cmd-delete-buffer.c
@@ -34,7 +34,6 @@ const struct cmd_entry cmd_delete_buffer_entry = {
CMD_BUFFER_USAGE,
0,
NULL,
- NULL,
cmd_delete_buffer_exec
};
diff --git a/cmd-detach-client.c b/cmd-detach-client.c
index 6e00e079..f0867364 100644
--- a/cmd-detach-client.c
+++ b/cmd-detach-client.c
@@ -18,6 +18,8 @@
#include <sys/types.h>
+#include <string.h>
+
#include "tmux.h"
/*
@@ -32,7 +34,6 @@ const struct cmd_entry cmd_detach_client_entry = {
"[-P] [-a] [-s target-session] " CMD_TARGET_CLIENT_USAGE,
CMD_READONLY,
NULL,
- NULL,
cmd_detach_client_exec
};
@@ -41,8 +42,8 @@ cmd_detach_client_exec(struct cmd *self, struct cmd_q *cmdq)
{
struct args *args = self->args;
struct client *c, *c2;
- struct session *s;
- enum msgtype msgtype;
+ struct session *s;
+ enum msgtype msgtype;
u_int i;
if (args_has(args, 'P'))
@@ -57,8 +58,10 @@ cmd_detach_client_exec(struct cmd *self, struct cmd_q *cmdq)
for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
c = ARRAY_ITEM(&clients, i);
- if (c != NULL && c->session == s)
- server_write_client(c, msgtype, NULL, 0);
+ if (c == NULL || c->session != s)
+ continue;
+ server_write_client(c, msgtype, c->session->name,
+ strlen(c->session->name) + 1);
}
} else {
c = cmd_find_client(cmdq, args_get(args, 't'), 0);
@@ -70,10 +73,14 @@ cmd_detach_client_exec(struct cmd *self, struct cmd_q *cmdq)
c2 = ARRAY_ITEM(&clients, i);
if (c2 == NULL || c == c2)
continue;
- server_write_client(c2, msgtype, NULL, 0);
+ server_write_client(c2, msgtype,
+ c2->session->name,
+ strlen(c2->session->name) + 1);
}
- } else
- server_write_client(c, msgtype, NULL, 0);
+ } else {
+ server_write_client(c, msgtype, c->session->name,
+ strlen(c->session->name) + 1);
+ }
}
return (CMD_RETURN_STOP);
diff --git a/cmd-display-message.c b/cmd-display-message.c
index 485ccf08..78752f86 100644
--- a/cmd-display-message.c
+++ b/cmd-display-message.c
@@ -36,7 +36,6 @@ const struct cmd_entry cmd_display_message_entry = {
" [message]",
0,
NULL,
- NULL,
cmd_display_message_exec
};
@@ -71,9 +70,9 @@ cmd_display_message_exec(struct cmd *self, struct cmd_q *cmdq)
}
if (args_has(args, 'c')) {
- c = cmd_find_client(cmdq, args_get(args, 'c'), 0);
- if (c == NULL)
- return (CMD_RETURN_ERROR);
+ c = cmd_find_client(cmdq, args_get(args, 'c'), 0);
+ if (c == NULL)
+ return (CMD_RETURN_ERROR);
} else {
c = cmd_current_client(cmdq);
if (c == NULL && !args_has(self->args, 'p')) {
diff --git a/cmd-display-panes.c b/cmd-display-panes.c
index 4a8731a4..c137feef 100644
--- a/cmd-display-panes.c
+++ b/cmd-display-panes.c
@@ -32,7 +32,6 @@ const struct cmd_entry cmd_display_panes_entry = {
CMD_TARGET_CLIENT_USAGE,
0,
NULL,
- NULL,
cmd_display_panes_exec
};
diff --git a/cmd-find-window.c b/cmd-find-window.c
index 02f19307..647cc8fb 100644
--- a/cmd-find-window.c
+++ b/cmd-find-window.c
@@ -48,7 +48,6 @@ const struct cmd_entry cmd_find_window_entry = {
"[-CNT] [-F format] " CMD_TARGET_WINDOW_USAGE " match-string",
0,
NULL,
- NULL,
cmd_find_window_exec
};
diff --git a/cmd-has-session.c b/cmd-has-session.c
index c4286b86..38a92f61 100644
--- a/cmd-has-session.c
+++ b/cmd-has-session.c
@@ -32,7 +32,6 @@ const struct cmd_entry cmd_has_session_entry = {
CMD_TARGET_SESSION_USAGE,
0,
NULL,
- NULL,
cmd_has_session_exec
};
diff --git a/cmd-if-shell.c b/cmd-if-shell.c
index d1cbd7f3..9b6dcf30 100644
--- a/cmd-if-shell.c
+++ b/cmd-if-shell.c
@@ -41,7 +41,6 @@ const struct cmd_entry cmd_if_shell_entry = {
"[-b] " CMD_TARGET_PANE_USAGE " shell-command command [command]",
0,
NULL,
- NULL,
cmd_if_shell_exec
};
@@ -148,6 +147,9 @@ cmd_if_shell_done(struct cmd_q *cmdq1)
struct cmd_if_shell_data *cdata = cmdq1->data;
struct cmd_q *cmdq = cdata->cmdq;
+ if (cmdq1->client_exit >= 0)
+ cmdq->client_exit = cmdq1->client_exit;
+
if (!cmdq_free(cmdq) && !cdata->bflag)
cmdq_continue(cmdq);
diff --git a/cmd-join-pane.c b/cmd-join-pane.c
index 2cf587e0..1a710cec 100644
--- a/cmd-join-pane.c
+++ b/cmd-join-pane.c
@@ -39,7 +39,6 @@ const struct cmd_entry cmd_join_pane_entry = {
"[-bdhv] [-p percentage|-l size] [-s src-pane] [-t dst-pane]",
0,
cmd_join_pane_key_binding,
- NULL,
cmd_join_pane_exec
};
@@ -49,7 +48,6 @@ const struct cmd_entry cmd_move_pane_entry = {
"[-bdhv] [-p percentage|-l size] [-s src-pane] [-t dst-pane]",
0,
NULL,
- NULL,
cmd_join_pane_exec
};
diff --git a/cmd-kill-pane.c b/cmd-kill-pane.c
index 40761350..bf486eb3 100644
--- a/cmd-kill-pane.c
+++ b/cmd-kill-pane.c
@@ -34,7 +34,6 @@ const struct cmd_entry cmd_kill_pane_entry = {
"[-a] " CMD_TARGET_PANE_USAGE,
0,
NULL,
- NULL,
cmd_kill_pane_exec
};
diff --git a/cmd-kill-server.c b/cmd-kill-server.c
index a6065460..ba63faa3 100644
--- a/cmd-kill-server.c
+++ b/cmd-kill-server.c
@@ -35,7 +35,6 @@ const struct cmd_entry cmd_kill_server_entry = {
"",
0,
NULL,
- NULL,
cmd_kill_server_exec
};
diff --git a/cmd-kill-session.c b/cmd-kill-session.c
index a12cc8a4..54b0c31b 100644
--- a/cmd-kill-session.c
+++ b/cmd-kill-session.c
@@ -35,7 +35,6 @@ const struct cmd_entry cmd_kill_session_entry = {
"[-a] " CMD_TARGET_SESSION_USAGE,
0,
NULL,
- NULL,
cmd_kill_session_exec
};
diff --git a/cmd-kill-window.c b/cmd-kill-window.c
index 34b97499..ca8fe3d6 100644
--- a/cmd-kill-window.c
+++ b/cmd-kill-window.c
@@ -32,7 +32,6 @@ const struct cmd_entry cmd_kill_window_entry = {
"[-a] " CMD_TARGET_WINDOW_USAGE,
0,
NULL,
- NULL,
cmd_kill_window_exec
};
diff --git a/cmd-link-window.c b/cmd-link-window.c
index 2be8ace0..d94eb38a 100644
--- a/cmd-link-window.c
+++ b/cmd-link-window.c
@@ -34,7 +34,6 @@ const struct cmd_entry cmd_link_window_entry = {
"[-dk] " CMD_SRCDST_WINDOW_USAGE,
0,
NULL,
- NULL,
cmd_link_window_exec
};
diff --git a/cmd-list-buffers.c b/cmd-list-buffers.c
index 58af0020..02a4183e 100644
--- a/cmd-list-buffers.c
+++ b/cmd-list-buffers.c
@@ -35,7 +35,6 @@ const struct cmd_entry cmd_list_buffers_entry = {
"[-F format]",
0,
NULL,
- NULL,
cmd_list_buffers_exec
};
diff --git a/cmd-list-clients.c b/cmd-list-clients.c
index 59f63099..904ec005 100644
--- a/cmd-list-clients.c
+++ b/cmd-list-clients.c
@@ -36,7 +36,6 @@ const struct cmd_entry cmd_list_clients_entry = {
"[-F format] " CMD_TARGET_SESSION_USAGE,
CMD_READONLY,
NULL,
- NULL,
cmd_list_clients_exec
};
diff --git a/cmd-list-commands.c b/cmd-list-commands.c
index 1bf6e703..06e48378 100644
--- a/cmd-list-commands.c
+++ b/cmd-list-commands.c
@@ -32,7 +32,6 @@ const struct cmd_entry cmd_list_commands_entry = {
"",
0,
NULL,
- NULL,
cmd_list_commands_exec
};
diff --git a/cmd-list-keys.c b/cmd-list-keys.c
index 78998b66..615c5ce1 100644
--- a/cmd-list-keys.c
+++ b/cmd-list-keys.c
@@ -35,7 +35,6 @@ const struct cmd_entry cmd_list_keys_entry = {
"[-t key-table]",
0,
NULL,
- NULL,
cmd_list_keys_exec
};
diff --git a/cmd-list-panes.c b/cmd-list-panes.c
index 0d498e28..c989eba1 100644
--- a/cmd-list-panes.c
+++ b/cmd-list-panes.c
@@ -41,7 +41,6 @@ const struct cmd_entry cmd_list_panes_entry = {
"[-as] [-F format] " CMD_TARGET_WINDOW_USAGE,
0,
NULL,
- NULL,
cmd_list_panes_exec
};
diff --git a/cmd-list-sessions.c b/cmd-list-sessions.c
index 61c12f4e..a3613c87 100644
--- a/cmd-list-sessions.c
+++ b/cmd-list-sessions.c
@@ -36,7 +36,6 @@ const struct cmd_entry cmd_list_sessions_entry = {
"[-F format]",
0,
NULL,
- NULL,
cmd_list_sessions_exec
};
diff --git a/cmd-list-windows.c b/cmd-list-windows.c
index 5c2a2b95..ce122f45 100644
--- a/cmd-list-windows.c
+++ b/cmd-list-windows.c
@@ -39,7 +39,6 @@ const struct cmd_entry cmd_list_windows_entry = {
"[-a] [-F format] " CMD_TARGET_SESSION_USAGE,
0,
NULL,
- NULL,
cmd_list_windows_exec
};
diff --git a/cmd-load-buffer.c b/cmd-load-buffer.c
index 3be14d6a..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>
@@ -39,7 +40,6 @@ const struct cmd_entry cmd_load_buffer_entry = {
CMD_BUFFER_USAGE " path",
0,
NULL,
- NULL,
cmd_load_buffer_exec
};
@@ -50,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;
@@ -82,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-lock-server.c b/cmd-lock-server.c
index 0b6aafe8..2b591ecf 100644
--- a/cmd-lock-server.c
+++ b/cmd-lock-server.c
@@ -36,7 +36,6 @@ const struct cmd_entry cmd_lock_server_entry = {
"",
0,
NULL,
- NULL,
cmd_lock_server_exec
};
@@ -46,7 +45,6 @@ const struct cmd_entry cmd_lock_session_entry = {
CMD_TARGET_SESSION_USAGE,
0,
NULL,
- NULL,
cmd_lock_server_exec
};
@@ -56,7 +54,6 @@ const struct cmd_entry cmd_lock_client_entry = {
CMD_TARGET_CLIENT_USAGE,
0,
NULL,
- NULL,
cmd_lock_server_exec
};
diff --git a/cmd-move-window.c b/cmd-move-window.c
index 1a147c7e..21606755 100644
--- a/cmd-move-window.c
+++ b/cmd-move-window.c
@@ -34,7 +34,6 @@ const struct cmd_entry cmd_move_window_entry = {
"[-dkr] " CMD_SRCDST_WINDOW_USAGE,
0,
NULL,
- NULL,
cmd_move_window_exec
};
diff --git a/cmd-new-session.c b/cmd-new-session.c
index 4eebe632..ad083a44 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>
@@ -30,46 +32,39 @@
* Create a new session and attach to the current terminal unless -d is given.
*/
-enum cmd_retval cmd_new_session_check(struct args *);
enum cmd_retval cmd_new_session_exec(struct cmd *, struct cmd_q *);
const struct cmd_entry cmd_new_session_entry = {
"new-session", "new",
- "AdDF:n:Ps:t:x:y:", 0, 1,
- "[-AdDP] [-F format] [-n window-name] [-s session-name] "
- CMD_TARGET_SESSION_USAGE " [-x width] [-y height] [command]",
- CMD_STARTSERVER|CMD_CANTNEST|CMD_SENDENVIRON,
+ "Ac:dDF:n:Ps:t:x:y:", 0, 1,
+ "[-AdDP] [-c start-directory] [-F format] [-n window-name] "
+ "[-s session-name] " CMD_TARGET_SESSION_USAGE " [-x width] [-y height] "
+ "[command]",
+ CMD_STARTSERVER|CMD_CANTNEST,
NULL,
- cmd_new_session_check,
cmd_new_session_exec
};
enum cmd_retval
-cmd_new_session_check(struct args *args)
-{
- if (args_has(args, 't') && (args->argc != 0 || args_has(args, 'n')))
- return (CMD_RETURN_ERROR);
- return (CMD_RETURN_NORMAL);
-}
-
-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, *cwd, *errstr;
- const char *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'))) {
+ cmdq_error(cmdq, "command or window name given with target");
+ return (CMD_RETURN_ERROR);
+ }
+
newname = args_get(args, 's');
if (newname != NULL) {
if (!session_check_name(newname)) {
@@ -79,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);
@@ -104,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 != NULL && 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.
@@ -125,21 +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)
- cwd = c->cwd;
- else {
- pw = getpwuid(getuid());
- if (pw->pw_dir != NULL && *pw->pw_dir != '\0')
- cwd = pw->pw_dir;
- else
- cwd = "/";
- }
-
/* Find new session size. */
if (c != NULL) {
sx = c->tty.sx;
@@ -152,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"))
@@ -189,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);
@@ -240,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);
@@ -253,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 cfc0b8bd..5c2cbe40 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"
@@ -35,7 +39,6 @@ const struct cmd_entry cmd_new_window_entry = {
CMD_TARGET_WINDOW_USAGE " [command]",
0,
NULL,
- NULL,
cmd_new_window_exec
};
@@ -46,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')) {
@@ -103,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 = cmd_get_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 != NULL && cmdq->client->session == NULL)
+ cwd = cmdq->client->cwd;
+ else
+ cwd = s->cwd;
if (idx == -1)
idx = -1 - options_get_number(&s->options, "base-index");
@@ -111,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);
@@ -137,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-paste-buffer.c b/cmd-paste-buffer.c
index b07c9faf..5305b7e6 100644
--- a/cmd-paste-buffer.c
+++ b/cmd-paste-buffer.c
@@ -38,7 +38,6 @@ const struct cmd_entry cmd_paste_buffer_entry = {
"[-dpr] [-s separator] [-b buffer-index] " CMD_TARGET_PANE_USAGE,
0,
NULL,
- NULL,
cmd_paste_buffer_exec
};
diff --git a/cmd-pipe-pane.c b/cmd-pipe-pane.c
index aa72c699..611ad8cf 100644
--- a/cmd-pipe-pane.c
+++ b/cmd-pipe-pane.c
@@ -41,7 +41,6 @@ const struct cmd_entry cmd_pipe_pane_entry = {
"[-o] " CMD_TARGET_PANE_USAGE " [command]",
0,
NULL,
- NULL,
cmd_pipe_pane_exec
};
diff --git a/cmd-queue.c b/cmd-queue.c
index 243f73dd..c5905bdb 100644
--- a/cmd-queue.c
+++ b/cmd-queue.c
@@ -35,7 +35,7 @@ cmdq_new(struct client *c)
cmdq->dead = 0;
cmdq->client = c;
- cmdq->client_exit = 0;
+ cmdq->client_exit = -1;
TAILQ_INIT(&cmdq->queue);
cmdq->item = NULL;
@@ -143,7 +143,7 @@ cmdq_error(struct cmd_q *cmdq, const char *fmt, ...)
evbuffer_add(c->stderr_data, "\n", 1);
server_push_stderr(c);
- c->retcode = 1;
+ c->retval = 1;
} else {
*msg = toupper((u_char) *msg);
status_message_set(c, "%s", msg);
@@ -154,18 +154,15 @@ cmdq_error(struct cmd_q *cmdq, const char *fmt, ...)
/* Print a guard line. */
int
-cmdq_guard(struct cmd_q *cmdq, const char *guard)
+cmdq_guard(struct cmd_q *cmdq, const char *guard, int flags)
{
struct client *c = cmdq->client;
- int flags;
if (c == NULL)
return 0;
if (!(c->flags & CLIENT_CONTROL))
return 0;
- flags = !!(cmdq->cmd->flags & CMD_CONTROL);
-
evbuffer_add_printf(c->stdout_data, "%%%s %ld %u %d\n", guard,
(long) cmdq->time, cmdq->number, flags);
server_push_stdout(c);
@@ -202,7 +199,7 @@ cmdq_continue(struct cmd_q *cmdq)
{
struct cmd_q_item *next;
enum cmd_retval retval;
- int empty, guard;
+ int empty, guard, flags;
char s[1024];
notify_disable();
@@ -228,13 +225,16 @@ cmdq_continue(struct cmd_q *cmdq)
cmdq->time = time(NULL);
cmdq->number++;
- guard = cmdq_guard(cmdq, "begin");
+ flags = !!(cmdq->cmd->flags & CMD_CONTROL);
+ guard = cmdq_guard(cmdq, "begin", flags);
+
retval = cmdq->cmd->entry->exec(cmdq->cmd, cmdq);
+
if (guard) {
if (retval == CMD_RETURN_ERROR)
- cmdq_guard(cmdq, "error");
+ cmdq_guard(cmdq, "error", flags);
else
- cmdq_guard(cmdq, "end");
+ cmdq_guard(cmdq, "end", flags);
}
if (retval == CMD_RETURN_ERROR)
@@ -259,7 +259,7 @@ cmdq_continue(struct cmd_q *cmdq)
} while (cmdq->item != NULL);
empty:
- if (cmdq->client_exit)
+ if (cmdq->client_exit > 0)
cmdq->client->flags |= CLIENT_EXIT;
if (cmdq->emptyfn != NULL)
cmdq->emptyfn(cmdq); /* may free cmdq */
diff --git a/cmd-refresh-client.c b/cmd-refresh-client.c
index 7d9d539f..45804fbe 100644
--- a/cmd-refresh-client.c
+++ b/cmd-refresh-client.c
@@ -29,10 +29,9 @@ enum cmd_retval cmd_refresh_client_exec(struct cmd *, struct cmd_q *);
const struct cmd_entry cmd_refresh_client_entry = {
"refresh-client", "refresh",
"C:St:", 0, 0,
- "[-S] [-C size]" CMD_TARGET_CLIENT_USAGE,
+ "[-S] [-C size] " CMD_TARGET_CLIENT_USAGE,
0,
NULL,
- NULL,
cmd_refresh_client_exec
};
diff --git a/cmd-rename-session.c b/cmd-rename-session.c
index 3f8a9d8f..4c8ae122 100644
--- a/cmd-rename-session.c
+++ b/cmd-rename-session.c
@@ -34,7 +34,6 @@ const struct cmd_entry cmd_rename_session_entry = {
CMD_TARGET_SESSION_USAGE " new-name",
0,
NULL,
- NULL,
cmd_rename_session_exec
};
diff --git a/cmd-rename-window.c b/cmd-rename-window.c
index c756ba1f..f647abb3 100644
--- a/cmd-rename-window.c
+++ b/cmd-rename-window.c
@@ -34,7 +34,6 @@ const struct cmd_entry cmd_rename_window_entry = {
CMD_TARGET_WINDOW_USAGE " new-name",
0,
NULL,
- NULL,
cmd_rename_window_exec
};
diff --git a/cmd-resize-pane.c b/cmd-resize-pane.c
index ca2a6cd3..d31f8868 100644
--- a/cmd-resize-pane.c
+++ b/cmd-resize-pane.c
@@ -35,7 +35,6 @@ const struct cmd_entry cmd_resize_pane_entry = {
"[-DLRUZ] [-x width] [-y height] " CMD_TARGET_PANE_USAGE " [adjustment]",
0,
cmd_resize_pane_key_binding,
- NULL,
cmd_resize_pane_exec
};
diff --git a/cmd-respawn-pane.c b/cmd-respawn-pane.c
index 4486c91f..bcde2754 100644
--- a/cmd-respawn-pane.c
+++ b/cmd-respawn-pane.c
@@ -36,7 +36,6 @@ const struct cmd_entry cmd_respawn_pane_entry = {
"[-k] " CMD_TARGET_PANE_USAGE " [command]",
0,
NULL,
- NULL,
cmd_respawn_pane_exec
};
@@ -78,7 +77,7 @@ cmd_respawn_pane_exec(struct cmd *self, struct cmd_q *cmdq)
cmd = args->argv[0];
else
cmd = NULL;
- if (window_pane_spawn(wp, cmd, NULL, NULL, &env, s->tio, &cause) != 0) {
+ if (window_pane_spawn(wp, cmd, NULL, -1, &env, s->tio, &cause) != 0) {
cmdq_error(cmdq, "respawn pane failed: %s", cause);
free(cause);
environ_free(&env);
diff --git a/cmd-respawn-window.c b/cmd-respawn-window.c
index 35bd3471..e6d913cf 100644
--- a/cmd-respawn-window.c
+++ b/cmd-respawn-window.c
@@ -35,7 +35,6 @@ const struct cmd_entry cmd_respawn_window_entry = {
"[-k] " CMD_TARGET_WINDOW_USAGE " [command]",
0,
NULL,
- NULL,
cmd_respawn_window_exec
};
@@ -80,7 +79,7 @@ cmd_respawn_window_exec(struct cmd *self, struct cmd_q *cmdq)
cmd = args->argv[0];
else
cmd = NULL;
- if (window_pane_spawn(wp, cmd, NULL, NULL, &env, s->tio, &cause) != 0) {
+ if (window_pane_spawn(wp, cmd, NULL, -1, &env, s->tio, &cause) != 0) {
cmdq_error(cmdq, "respawn window failed: %s", cause);
free(cause);
environ_free(&env);
diff --git a/cmd-rotate-window.c b/cmd-rotate-window.c
index 75ca7292..9f4cc751 100644
--- a/cmd-rotate-window.c
+++ b/cmd-rotate-window.c
@@ -33,7 +33,6 @@ const struct cmd_entry cmd_rotate_window_entry = {
"[-DU] " CMD_TARGET_WINDOW_USAGE,
0,
cmd_rotate_window_key_binding,
- NULL,
cmd_rotate_window_exec
};
diff --git a/cmd-run-shell.c b/cmd-run-shell.c
index 7c7d333c..f5231814 100644
--- a/cmd-run-shell.c
+++ b/cmd-run-shell.c
@@ -41,7 +41,6 @@ const struct cmd_entry cmd_run_shell_entry = {
"[-b] " CMD_TARGET_PANE_USAGE " shell-command",
0,
NULL,
- NULL,
cmd_run_shell_exec
};
diff --git a/cmd-save-buffer.c b/cmd-save-buffer.c
index 52914a94..fc56dd8f 100644
--- a/cmd-save-buffer.c
+++ b/cmd-save-buffer.c
@@ -20,8 +20,11 @@
#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"
@@ -37,7 +40,6 @@ const struct cmd_entry cmd_save_buffer_entry = {
"[-a] " CMD_BUFFER_USAGE " path",
0,
NULL,
- NULL,
cmd_save_buffer_exec
};
@@ -47,7 +49,6 @@ const struct cmd_entry cmd_show_buffer_entry = {
CMD_BUFFER_USAGE,
0,
NULL,
- NULL,
cmd_save_buffer_exec
};
@@ -55,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) {
@@ -92,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);
@@ -102,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-select-layout.c b/cmd-select-layout.c
index ae1be4c4..053f3e40 100644
--- a/cmd-select-layout.c
+++ b/cmd-select-layout.c
@@ -33,7 +33,6 @@ const struct cmd_entry cmd_select_layout_entry = {
"[-np] " CMD_TARGET_WINDOW_USAGE " [layout-name]",
0,
cmd_select_layout_key_binding,
- NULL,
cmd_select_layout_exec
};
@@ -43,7 +42,6 @@ const struct cmd_entry cmd_next_layout_entry = {
CMD_TARGET_WINDOW_USAGE,
0,
NULL,
- NULL,
cmd_select_layout_exec
};
@@ -53,7 +51,6 @@ const struct cmd_entry cmd_previous_layout_entry = {
CMD_TARGET_WINDOW_USAGE,
0,
NULL,
- NULL,
cmd_select_layout_exec
};
diff --git a/cmd-select-pane.c b/cmd-select-pane.c
index b8a12671..c342fef3 100644
--- a/cmd-select-pane.c
+++ b/cmd-select-pane.c
@@ -33,7 +33,6 @@ const struct cmd_entry cmd_select_pane_entry = {
"[-lDLRU] " CMD_TARGET_PANE_USAGE,
0,
cmd_select_pane_key_binding,
- NULL,
cmd_select_pane_exec
};
@@ -43,7 +42,6 @@ const struct cmd_entry cmd_last_pane_entry = {
CMD_TARGET_WINDOW_USAGE,
0,
NULL,
- NULL,
cmd_select_pane_exec
};
diff --git a/cmd-select-window.c b/cmd-select-window.c
index c15d5858..73196200 100644
--- a/cmd-select-window.c
+++ b/cmd-select-window.c
@@ -35,7 +35,6 @@ const struct cmd_entry cmd_select_window_entry = {
"[-lnpT] " CMD_TARGET_WINDOW_USAGE,
0,
cmd_select_window_key_binding,
- NULL,
cmd_select_window_exec
};
@@ -45,7 +44,6 @@ const struct cmd_entry cmd_next_window_entry = {
"[-a] " CMD_TARGET_SESSION_USAGE,
0,
cmd_select_window_key_binding,
- NULL,
cmd_select_window_exec
};
@@ -55,7 +53,6 @@ const struct cmd_entry cmd_previous_window_entry = {
"[-a] " CMD_TARGET_SESSION_USAGE,
0,
cmd_select_window_key_binding,
- NULL,
cmd_select_window_exec
};
@@ -65,7 +62,6 @@ const struct cmd_entry cmd_last_window_entry = {
CMD_TARGET_SESSION_USAGE,
0,
NULL,
- NULL,
cmd_select_window_exec
};
diff --git a/cmd-send-keys.c b/cmd-send-keys.c
index a2041656..50cb70e2 100644
--- a/cmd-send-keys.c
+++ b/cmd-send-keys.c
@@ -35,7 +35,6 @@ const struct cmd_entry cmd_send_keys_entry = {
"[-lR] " CMD_TARGET_PANE_USAGE " key ...",
0,
NULL,
- NULL,
cmd_send_keys_exec
};
@@ -45,7 +44,6 @@ const struct cmd_entry cmd_send_prefix_entry = {
"[-2] " CMD_TARGET_PANE_USAGE,
0,
NULL,
- NULL,
cmd_send_keys_exec
};
diff --git a/cmd-server-info.c b/cmd-server-info.c
index 8eba172a..3aa5df8a 100644
--- a/cmd-server-info.c
+++ b/cmd-server-info.c
@@ -38,7 +38,6 @@ const struct cmd_entry cmd_server_info_entry = {
"",
0,
NULL,
- NULL,
cmd_server_info_exec
};
diff --git a/cmd-set-buffer.c b/cmd-set-buffer.c
index 46d28ff2..fade4fe3 100644
--- a/cmd-set-buffer.c
+++ b/cmd-set-buffer.c
@@ -35,7 +35,6 @@ const struct cmd_entry cmd_set_buffer_entry = {
CMD_BUFFER_USAGE " data",
0,
NULL,
- NULL,
cmd_set_buffer_exec
};
diff --git a/cmd-set-environment.c b/cmd-set-environment.c
index 0f0365aa..8d067c35 100644
--- a/cmd-set-environment.c
+++ b/cmd-set-environment.c
@@ -35,7 +35,6 @@ const struct cmd_entry cmd_set_environment_entry = {
"[-gru] " CMD_TARGET_SESSION_USAGE " name [value]",
0,
NULL,
- NULL,
cmd_set_environment_exec
};
diff --git a/cmd-set-option.c b/cmd-set-option.c
index c246743c..3acf125d 100644
--- a/cmd-set-option.c
+++ b/cmd-set-option.c
@@ -67,7 +67,6 @@ const struct cmd_entry cmd_set_option_entry = {
"[-agosquw] [-t target-session|target-window] option [value]",
0,
NULL,
- NULL,
cmd_set_option_exec
};
@@ -77,7 +76,6 @@ const struct cmd_entry cmd_set_window_option_entry = {
"[-agoqu] " CMD_TARGET_WINDOW_USAGE " option [value]",
0,
NULL,
- NULL,
cmd_set_option_exec
};
diff --git a/cmd-show-environment.c b/cmd-show-environment.c
index ffe98bcc..2238929e 100644
--- a/cmd-show-environment.c
+++ b/cmd-show-environment.c
@@ -35,7 +35,6 @@ const struct cmd_entry cmd_show_environment_entry = {
"[-g] " CMD_TARGET_SESSION_USAGE " [name]",
0,
NULL,
- NULL,
cmd_show_environment_exec
};
diff --git a/cmd-show-messages.c b/cmd-show-messages.c
index bc2424ad..256570cd 100644
--- a/cmd-show-messages.c
+++ b/cmd-show-messages.c
@@ -35,7 +35,6 @@ const struct cmd_entry cmd_show_messages_entry = {
CMD_TARGET_CLIENT_USAGE,
0,
NULL,
- NULL,
cmd_show_messages_exec
};
diff --git a/cmd-show-options.c b/cmd-show-options.c
index e2f78e12..943353f6 100644
--- a/cmd-show-options.c
+++ b/cmd-show-options.c
@@ -40,7 +40,6 @@ const struct cmd_entry cmd_show_options_entry = {
"[-gqsvw] [-t target-session|target-window] [option]",
0,
NULL,
- NULL,
cmd_show_options_exec
};
@@ -50,7 +49,6 @@ const struct cmd_entry cmd_show_window_options_entry = {
"[-gv] " CMD_TARGET_WINDOW_USAGE " [option]",
0,
NULL,
- NULL,
cmd_show_options_exec
};
diff --git a/cmd-source-file.c b/cmd-source-file.c
index 45a3a39b..eb7e1490 100644
--- a/cmd-source-file.c
+++ b/cmd-source-file.c
@@ -37,7 +37,6 @@ const struct cmd_entry cmd_source_file_entry = {
"path",
0,
NULL,
- NULL,
cmd_source_file_exec
};
@@ -96,6 +95,9 @@ cmd_source_file_done(struct cmd_q *cmdq1)
{
struct cmd_q *cmdq = cmdq1->data;
+ if (cmdq1->client_exit >= 0)
+ cmdq->client_exit = cmdq1->client_exit;
+
cmdq_free(cmdq1);
cfg_references--;
diff --git a/cmd-split-window.c b/cmd-split-window.c
index 601dcb17..506c8033 100644
--- a/cmd-split-window.c
+++ b/cmd-split-window.c
@@ -18,7 +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"
@@ -37,7 +41,6 @@ const struct cmd_entry cmd_split_window_entry = {
CMD_TARGET_PANE_USAGE " [command]",
0,
cmd_split_window_key_binding,
- NULL,
cmd_split_window_exec
};
@@ -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 = cmd_get_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 != NULL && 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/cmd-start-server.c b/cmd-start-server.c
index cba2403b..33b28b4a 100644
--- a/cmd-start-server.c
+++ b/cmd-start-server.c
@@ -32,7 +32,6 @@ const struct cmd_entry cmd_start_server_entry = {
"",
CMD_STARTSERVER,
NULL,
- NULL,
cmd_start_server_exec
};
diff --git a/cmd-string.c b/cmd-string.c
index 7e84eda6..e793ea02 100644
--- a/cmd-string.c
+++ b/cmd-string.c
@@ -318,10 +318,13 @@ cmd_string_expand_tilde(const char *s, size_t *p)
{
struct passwd *pw;
struct environ_entry *envent;
- char *home, *path, *username;
+ char *home, *path, *user, *cp;
+ int last;
home = NULL;
- if (cmd_string_getc(s, p) == '/') {
+
+ last = cmd_string_getc(s, p);
+ if (last == EOF || last == '/' || last == ' '|| last == '\t') {
envent = environ_find(&global_environ, "HOME");
if (envent != NULL && *envent->value != '\0')
home = envent->value;
@@ -329,15 +332,27 @@ cmd_string_expand_tilde(const char *s, size_t *p)
home = pw->pw_dir;
} else {
cmd_string_ungetc(p);
- if ((username = cmd_string_string(s, p, '/', 0)) == NULL)
- return (NULL);
- if ((pw = getpwnam(username)) != NULL)
+
+ cp = user = xmalloc(strlen(s));
+ for (;;) {
+ last = cmd_string_getc(s, p);
+ if (last == EOF || last == '/' || last == ' '|| last == '\t')
+ break;
+ *cp++ = last;
+ }
+ *cp = '\0';
+
+ if ((pw = getpwnam(user)) != NULL)
home = pw->pw_dir;
- free(username);
+ free(user);
}
+
if (home == NULL)
return (NULL);
- xasprintf(&path, "%s/", home);
+ if (last != EOF)
+ xasprintf(&path, "%s%c", home, last);
+ else
+ xasprintf(&path, "%s", home);
return (path);
}
diff --git a/cmd-suspend-client.c b/cmd-suspend-client.c
index 101658b1..e0e375fc 100644
--- a/cmd-suspend-client.c
+++ b/cmd-suspend-client.c
@@ -35,7 +35,6 @@ const struct cmd_entry cmd_suspend_client_entry = {
CMD_TARGET_CLIENT_USAGE,
0,
NULL,
- NULL,
cmd_suspend_client_exec
};
diff --git a/cmd-swap-pane.c b/cmd-swap-pane.c
index 05317260..b8ff7690 100644
--- a/cmd-swap-pane.c
+++ b/cmd-swap-pane.c
@@ -35,7 +35,6 @@ const struct cmd_entry cmd_swap_pane_entry = {
"[-dDU] " CMD_SRCDST_PANE_USAGE,
0,
cmd_swap_pane_key_binding,
- NULL,
cmd_swap_pane_exec
};
diff --git a/cmd-swap-window.c b/cmd-swap-window.c
index f9a2cb1b..1591d403 100644
--- a/cmd-swap-window.c
+++ b/cmd-swap-window.c
@@ -34,7 +34,6 @@ const struct cmd_entry cmd_swap_window_entry = {
"[-d] " CMD_SRCDST_WINDOW_USAGE,
0,
NULL,
- NULL,
cmd_swap_window_exec
};
diff --git a/cmd-switch-client.c b/cmd-switch-client.c
index 9adb2146..d101c52b 100644
--- a/cmd-switch-client.c
+++ b/cmd-switch-client.c
@@ -36,7 +36,6 @@ const struct cmd_entry cmd_switch_client_entry = {
"[-lnpr] [-c target-client] [-t target-session]",
CMD_READONLY,
cmd_switch_client_key_binding,
- NULL,
cmd_switch_client_exec
};
diff --git a/cmd-unbind-key.c b/cmd-unbind-key.c
index dc037dde..cf6ad506 100644
--- a/cmd-unbind-key.c
+++ b/cmd-unbind-key.c
@@ -26,7 +26,6 @@
* Unbind key from command.
*/
-enum cmd_retval cmd_unbind_key_check(struct args *);
enum cmd_retval cmd_unbind_key_exec(struct cmd *, struct cmd_q *);
enum cmd_retval cmd_unbind_key_table(struct cmd *, struct cmd_q *, int);
@@ -36,21 +35,10 @@ const struct cmd_entry cmd_unbind_key_entry = {
"[-acn] [-t key-table] key",
0,
NULL,
- cmd_unbind_key_check,
cmd_unbind_key_exec
};
enum cmd_retval
-cmd_unbind_key_check(struct args *args)
-{
- if (args_has(args, 'a') && args->argc != 0)
- return (CMD_RETURN_ERROR);
- if (!args_has(args, 'a') && args->argc != 1)
- return (CMD_RETURN_ERROR);
- return (CMD_RETURN_NORMAL);
-}
-
-enum cmd_retval
cmd_unbind_key_exec(struct cmd *self, struct cmd_q *cmdq)
{
struct args *args = self->args;
@@ -58,13 +46,22 @@ cmd_unbind_key_exec(struct cmd *self, struct cmd_q *cmdq)
int key;
if (!args_has(args, 'a')) {
+ if (args->argc != 1) {
+ cmdq_error(cmdq, "missing key");
+ return (CMD_RETURN_ERROR);
+ }
key = key_string_lookup_string(args->argv[0]);
if (key == KEYC_NONE) {
cmdq_error(cmdq, "unknown key: %s", args->argv[0]);
return (CMD_RETURN_ERROR);
}
- } else
+ } else {
+ if (args->argc != 0) {
+ cmdq_error(cmdq, "key given with -a");
+ return (CMD_RETURN_ERROR);
+ }
key = KEYC_NONE;
+ }
if (args_has(args, 't'))
return (cmd_unbind_key_table(self, cmdq, key));
diff --git a/cmd-unlink-window.c b/cmd-unlink-window.c
index 39cdd8ed..ec69b91f 100644
--- a/cmd-unlink-window.c
+++ b/cmd-unlink-window.c
@@ -32,7 +32,6 @@ const struct cmd_entry cmd_unlink_window_entry = {
"[-k] " CMD_TARGET_WINDOW_USAGE,
0,
NULL,
- NULL,
cmd_unlink_window_exec
};
diff --git a/cmd-wait-for.c b/cmd-wait-for.c
index d40ba49e..e251863d 100644
--- a/cmd-wait-for.c
+++ b/cmd-wait-for.c
@@ -33,10 +33,9 @@ enum cmd_retval cmd_wait_for_exec(struct cmd *, struct cmd_q *);
const struct cmd_entry cmd_wait_for_entry = {
"wait-for", "wait",
"LSU", 1, 1,
- "[-LSU] channel",
+ "[-L|-S|-U] channel",
0,
NULL,
- NULL,
cmd_wait_for_exec
};
diff --git a/cmd.c b/cmd.c
index 282fb112..414c9067 100644
--- a/cmd.c
+++ b/cmd.c
@@ -254,8 +254,6 @@ cmd_parse(int argc, char **argv, const char *file, u_int line, char **cause)
goto usage;
if (entry->args_upper != -1 && args->argc > entry->args_upper)
goto usage;
- if (entry->check != NULL && entry->check(args) != 0)
- goto usage;
cmd = xcalloc(1, sizeof *cmd);
cmd->entry = entry;
@@ -315,7 +313,6 @@ cmd_print(struct cmd *cmd, char *buf, size_t len)
struct session *
cmd_current_session(struct cmd_q *cmdq, int prefer_unattached)
{
- struct msg_command_data *data = cmdq->msgdata;
struct client *c = cmdq->client;
struct session *s;
struct sessionslist ss;
@@ -357,13 +354,6 @@ cmd_current_session(struct cmd_q *cmdq, int prefer_unattached)
return (s);
}
- /* Use the session from the TMUX environment variable. */
- if (data != NULL && data->pid == getpid() && data->session_id != -1) {
- s = session_find_by_id(data->session_id);
- if (s != NULL)
- return (s);
- }
-
return (cmd_choose_session(prefer_unattached));
}
@@ -1278,87 +1268,3 @@ cmd_template_replace(const char *template, const char *s, int idx)
return (buf);
}
-
-/*
- * Return the default path for a new pane, using the given path or the
- * default-path option if it is NULL. Several special values are accepted: the
- * empty string or relative path for the current pane's working directory, ~
- * for the user's home, - for the session working directory, . for the tmux
- * server's working directory. The default on failure is the session's working
- * directory.
- */
-const char *
-cmd_get_default_path(struct cmd_q *cmdq, const char *cwd)
-{
- struct client *c = cmdq->client;
- struct session *s;
- struct environ_entry *envent;
- const char *root;
- char tmp[MAXPATHLEN];
- struct passwd *pw;
- int n;
- size_t skip;
- static char path[MAXPATHLEN];
-
- if ((s = cmd_current_session(cmdq, 0)) == NULL)
- return (NULL);
-
- if (cwd == NULL)
- cwd = options_get_string(&s->options, "default-path");
-
- skip = 1;
- if (strcmp(cwd, "$HOME") == 0 || strncmp(cwd, "$HOME/", 6) == 0) {
- /* User's home directory - $HOME. */
- skip = 5;
- goto find_home;
- } else if (cwd[0] == '~' && (cwd[1] == '\0' || cwd[1] == '/')) {
- /* User's home directory - ~. */
- goto find_home;
- } else if (cwd[0] == '-' && (cwd[1] == '\0' || cwd[1] == '/')) {
- /* Session working directory. */
- root = s->cwd;
- goto complete_path;
- } else if (cwd[0] == '.' && (cwd[1] == '\0' || cwd[1] == '/')) {
- /* Server working directory. */
- if (getcwd(tmp, sizeof tmp) != NULL) {
- root = tmp;
- goto complete_path;
- }
- return (s->cwd);
- } else if (*cwd == '/') {
- /* Absolute path. */
- return (cwd);
- } else {
- /* Empty or relative path. */
- if (c != NULL && c->session == NULL && c->cwd != NULL)
- root = c->cwd;
- else if (s->curw != NULL)
- root = osdep_get_cwd(s->curw->window->active->fd);
- else
- return (s->cwd);
- skip = 0;
- if (root != NULL)
- goto complete_path;
- }
-
- return (s->cwd);
-
-find_home:
- envent = environ_find(&global_environ, "HOME");
- if (envent != NULL && *envent->value != '\0')
- root = envent->value;
- else if ((pw = getpwuid(getuid())) != NULL)
- root = pw->pw_dir;
- else
- return (s->cwd);
-
-complete_path:
- if (root[skip] == '\0') {
- strlcpy(path, root, sizeof path);
- return (path);
- }
- n = snprintf(path, sizeof path, "%s/%s", root, cwd + skip);
- if (n > 0 && (size_t)n < sizeof path)
- return (path);
- return (s->cwd);
-}
diff --git a/control.c b/control.c
index aa79085a..52fdb524 100644
--- a/control.c
+++ b/control.c
@@ -73,9 +73,9 @@ control_callback(struct client *c, int closed, unused void *data)
c->cmdq->time = time(NULL);
c->cmdq->number++;
- cmdq_guard(c->cmdq, "begin");
+ cmdq_guard(c->cmdq, "begin", 1);
control_write(c, "parse error: %s", cause);
- cmdq_guard(c->cmdq, "error");
+ cmdq_guard(c->cmdq, "error", 1);
free(cause);
} else {
diff --git a/format.c b/format.c
index 8c4c7842..d8d34fe7 100644
--- a/format.c
+++ b/format.c
@@ -18,6 +18,8 @@
#include <sys/types.h>
+#include <ctype.h>
+#include <errno.h>
#include <netdb.h>
#include <stdarg.h>
#include <stdlib.h>
@@ -32,9 +34,10 @@
* string.
*/
-int format_replace(struct format_tree *, const char *, size_t, char **,
- size_t *, size_t *);
-void format_window_pane_tabs(struct format_tree *, struct window_pane *);
+int format_replace(struct format_tree *, const char *, size_t, char **,
+ size_t *, size_t *);
+char *format_get_command(struct window_pane *);
+void format_window_pane_tabs(struct format_tree *, struct window_pane *);
/* Format key-value replacement entry. */
RB_GENERATE(format_tree, format_entry, entry, format_cmp);
@@ -118,7 +121,7 @@ format_create(void)
if (gethostname(host, sizeof host) == 0) {
format_add(ft, "host", "%s", host);
- if ((ptr = strrchr(host, '.')) != NULL)
+ if ((ptr = strchr(host, '.')) != NULL)
*ptr = '\0';
format_add(ft, "host_short", "%s", host);
}
@@ -151,6 +154,7 @@ void
format_add(struct format_tree *ft, const char *key, const char *fmt, ...)
{
struct format_entry *fe;
+ struct format_entry *fe_now;
va_list ap;
fe = xmalloc(sizeof *fe);
@@ -160,7 +164,13 @@ format_add(struct format_tree *ft, const char *key, const char *fmt, ...)
xvasprintf(&fe->value, fmt, ap);
va_end(ap);
- RB_INSERT(format_tree, ft, fe);
+ fe_now = RB_INSERT(format_tree, ft, fe);
+ if (fe_now != NULL) {
+ free(fe_now->value);
+ fe_now->value = fe->value;
+ free(fe->key);
+ free(fe);
+ }
}
/* Find a format entry. */
@@ -181,18 +191,40 @@ format_find(struct format_tree *ft, const char *key)
* #{?blah,a,b} is replace with a if blah exists and is nonzero else b.
*/
int
-format_replace(struct format_tree *ft,
- const char *key, size_t keylen, char **buf, size_t *len, size_t *off)
+format_replace(struct format_tree *ft, const char *key, size_t keylen,
+ char **buf, size_t *len, size_t *off)
{
- char *copy, *ptr;
+ char *copy, *copy0, *endptr, *ptr, *saved;
const char *value;
size_t valuelen;
+ u_long limit = ULONG_MAX;
/* Make a copy of the key. */
- copy = xmalloc(keylen + 1);
+ copy0 = copy = xmalloc(keylen + 1);
memcpy(copy, key, keylen);
copy[keylen] = '\0';
+ /* Is there a length limit or whatnot? */
+ if (!islower((u_char) *copy) && *copy != '?') {
+ while (*copy != ':' && *copy != '\0') {
+ switch (*copy) {
+ case '=':
+ errno = 0;
+ limit = strtoul(copy + 1, &endptr, 10);
+ if (errno == ERANGE && limit == ULONG_MAX)
+ goto fail;
+ copy = endptr;
+ break;
+ default:
+ copy++;
+ break;
+ }
+ }
+ if (*copy != ':')
+ goto fail;
+ copy++;
+ }
+
/*
* Is this a conditional? If so, check it exists and extract either the
* first or second element. If not, look up the key directly.
@@ -216,13 +248,20 @@ format_replace(struct format_tree *ft,
goto fail;
value = ptr + 1;
}
+ saved = format_expand(ft, value);
+ value = saved;
} else {
value = format_find(ft, copy);
if (value == NULL)
value = "";
+ saved = NULL;
}
valuelen = strlen(value);
+ /* Truncate the value if needed. */
+ if (valuelen > limit)
+ valuelen = limit;
+
/* Expand the buffer and copy in the value. */
while (*len - *off < valuelen + 1) {
*buf = xrealloc(*buf, 2, *len);
@@ -231,11 +270,12 @@ format_replace(struct format_tree *ft,
memcpy(*buf + *off, value, valuelen);
*off += valuelen;
- free(copy);
+ free(saved);
+ free(copy0);
return (0);
fail:
- free(copy);
+ free(copy0);
return (-1);
}
@@ -243,10 +283,10 @@ fail:
char *
format_expand(struct format_tree *ft, const char *fmt)
{
- char *buf, *ptr;
- const char *s;
+ char *buf;
+ const char *ptr, *s;
size_t off, len, n;
- int ch;
+ int ch, brackets;
len = 64;
buf = xmalloc(len);
@@ -264,11 +304,16 @@ format_expand(struct format_tree *ft, const char *fmt)
fmt++;
ch = (u_char) *fmt++;
-
switch (ch) {
case '{':
- ptr = strchr(fmt, '}');
- if (ptr == NULL)
+ brackets = 1;
+ for (ptr = fmt; *ptr != '\0'; ptr++) {
+ if (*ptr == '{')
+ brackets++;
+ if (*ptr == '}' && --brackets == 0)
+ break;
+ }
+ if (*ptr != '}' || brackets != 0)
break;
n = ptr - fmt;
@@ -304,6 +349,26 @@ format_expand(struct format_tree *ft, const char *fmt)
return (buf);
}
+/* Get command name for format. */
+char *
+format_get_command(struct window_pane *wp)
+{
+ char *cmd, *out;
+
+ cmd = get_proc_name(wp->fd, wp->tty);
+ if (cmd == NULL || *cmd == '\0') {
+ free(cmd);
+ cmd = xstrdup(wp->cmd);
+ if (cmd == NULL || *cmd == '\0') {
+ free(cmd);
+ cmd = xstrdup(wp->shell);
+ }
+ }
+ out = parse_window_name(cmd);
+ free(cmd);
+ return (out);
+}
+
/* Set default format keys for a session. */
void
format_session(struct format_tree *ft, struct session *s)
@@ -343,11 +408,12 @@ 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);
- format_add(ft, "client_tty", "%s", c->tty.path);
- format_add(ft, "client_termname", "%s", c->tty.termname);
+ if (c->tty.path != NULL)
+ format_add(ft, "client_tty", "%s", c->tty.path);
+ if (c->tty.termname != NULL)
+ format_add(ft, "client_termname", "%s", c->tty.termname);
t = c->creation_time.tv_sec;
format_add(ft, "client_created", "%lld", (long long) t);
@@ -381,30 +447,52 @@ format_client(struct format_tree *ft, struct client *c)
format_add(ft, "client_last_session", "%s", s->name);
}
-/* Set default format keys for a winlink. */
+/* Set default format keys for a window. */
void
-format_winlink(struct format_tree *ft, struct session *s, struct winlink *wl)
+format_window(struct format_tree *ft, struct window *w)
{
- struct window *w = wl->window;
- char *layout, *flags;
+ char *layout;
layout = layout_dump(w);
- flags = window_printable_flags(s, wl);
format_add(ft, "window_id", "@%u", w->id);
- format_add(ft, "window_index", "%d", wl->idx);
format_add(ft, "window_name", "%s", w->name);
format_add(ft, "window_width", "%u", w->sx);
format_add(ft, "window_height", "%u", w->sy);
- format_add(ft, "window_flags", "%s", flags);
format_add(ft, "window_layout", "%s", layout);
- format_add(ft, "window_active", "%d", wl == s->curw);
format_add(ft, "window_panes", "%u", window_count_panes(w));
- free(flags);
free(layout);
}
+/* Set default format keys for a winlink. */
+void
+format_winlink(struct format_tree *ft, struct session *s, struct winlink *wl)
+{
+ struct window *w = wl->window;
+ char *flags;
+
+ flags = window_printable_flags(s, wl);
+
+ format_window(ft, w);
+
+ format_add(ft, "window_index", "%d", wl->idx);
+ format_add(ft, "window_flags", "%s", flags);
+ format_add(ft, "window_active", "%d", wl == s->curw);
+
+ format_add(ft, "window_bell_flag", "%u",
+ !!(wl->flags & WINLINK_BELL));
+ format_add(ft, "window_content_flag", "%u",
+ !!(wl->flags & WINLINK_CONTENT));
+ format_add(ft, "window_activity_flag", "%u",
+ !!(wl->flags & WINLINK_ACTIVITY));
+ format_add(ft, "window_silence_flag", "%u",
+ !!(wl->flags & WINLINK_SILENCE));
+
+
+ free(flags);
+}
+
/* Add window pane tabs. */
void
format_window_pane_tabs(struct format_tree *ft, struct window_pane *wp)
@@ -435,7 +523,6 @@ format_window_pane(struct format_tree *ft, struct window_pane *wp)
struct grid_line *gl;
unsigned long long size;
u_int i, idx;
- const char *cwd;
char *cmd;
size = 0;
@@ -468,11 +555,7 @@ 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 = osdep_get_name(wp->fd, wp->tty)) != NULL) {
+ if ((cmd = format_get_command(wp)) != NULL) {
format_add(ft, "pane_current_command", "%s", cmd);
free(cmd);
}
diff --git a/grid.c b/grid.c
index 2955e8ba..9e800243 100644
--- a/grid.c
+++ b/grid.c
@@ -268,8 +268,7 @@ grid_get_cell(struct grid *gd, u_int px, u_int py)
/* Set cell at relative position. */
void
-grid_set_cell(
- struct grid *gd, u_int px, u_int py, const struct grid_cell *gc)
+grid_set_cell(struct grid *gd, u_int px, u_int py, const struct grid_cell *gc)
{
if (grid_check_y(gd, py) != 0)
return;
@@ -592,6 +591,7 @@ grid_string_cells(struct grid *gd, u_int px, u_int py, u_int nx,
char *buf, code[128];
size_t len, off, size, codelen;
u_int xx;
+ const struct grid_line *gl;
GRID_DEBUG(gd, "px=%u, py=%u, nx=%u", px, py, nx);
@@ -604,8 +604,11 @@ grid_string_cells(struct grid *gd, u_int px, u_int py, u_int nx,
buf = xmalloc(len);
off = 0;
+ gl = grid_peek_line(gd, py);
for (xx = px; xx < px + nx; xx++) {
- gc = grid_peek_cell(gd, xx, py);
+ if (gl == NULL || xx >= gl->cellsize)
+ break;
+ gc = &gl->celldata[xx];
if (gc->flags & GRID_FLAG_PADDING)
continue;
grid_cell_get(gc, &ud);
@@ -653,8 +656,8 @@ grid_string_cells(struct grid *gd, u_int px, u_int py, u_int nx,
* available.
*/
void
-grid_duplicate_lines(
- struct grid *dst, u_int dy, struct grid *src, u_int sy, u_int ny)
+grid_duplicate_lines(struct grid *dst, u_int dy, struct grid *src, u_int sy,
+ u_int ny)
{
struct grid_line *dstl, *srcl;
u_int yy;
diff --git a/input.c b/input.c
index 30d3bb98..259fad16 100644
--- a/input.c
+++ b/input.c
@@ -70,6 +70,10 @@ int input_input(struct input_ctx *);
int input_c0_dispatch(struct input_ctx *);
int input_esc_dispatch(struct input_ctx *);
int input_csi_dispatch(struct input_ctx *);
+void input_csi_dispatch_rm(struct input_ctx *);
+void input_csi_dispatch_rm_private(struct input_ctx *);
+void input_csi_dispatch_sm(struct input_ctx *);
+void input_csi_dispatch_sm_private(struct input_ctx *);
void input_csi_dispatch_sgr(struct input_ctx *);
int input_dcs_dispatch(struct input_ctx *);
int input_utf8_open(struct input_ctx *);
@@ -1071,7 +1075,6 @@ int
input_csi_dispatch(struct input_ctx *ictx)
{
struct screen_write_ctx *sctx = &ictx->ctx;
- struct window_pane *wp = ictx->wp;
struct screen *s = sctx->s;
struct input_table_entry *entry;
int n, m;
@@ -1230,7 +1233,60 @@ input_csi_dispatch(struct input_ctx *ictx)
screen_write_cursormove(sctx, ictx->old_cx, ictx->old_cy);
break;
case INPUT_CSI_RM:
- switch (input_get(ictx, 0, 0, -1)) {
+ input_csi_dispatch_rm(ictx);
+ break;
+ case INPUT_CSI_RM_PRIVATE:
+ input_csi_dispatch_rm_private(ictx);
+ break;
+ case INPUT_CSI_SCP:
+ memcpy(&ictx->old_cell, &ictx->cell, sizeof ictx->old_cell);
+ ictx->old_cx = s->cx;
+ ictx->old_cy = s->cy;
+ break;
+ case INPUT_CSI_SGR:
+ input_csi_dispatch_sgr(ictx);
+ break;
+ case INPUT_CSI_SM:
+ input_csi_dispatch_sm(ictx);
+ break;
+ case INPUT_CSI_SM_PRIVATE:
+ input_csi_dispatch_sm_private(ictx);
+ break;
+ case INPUT_CSI_TBC:
+ switch (input_get(ictx, 0, 0, 0)) {
+ case 0:
+ if (s->cx < screen_size_x(s))
+ bit_clear(s->tabs, s->cx);
+ break;
+ case 3:
+ bit_nclear(s->tabs, 0, screen_size_x(s) - 1);
+ break;
+ default:
+ log_debug("%s: unknown '%c'", __func__, ictx->ch);
+ break;
+ }
+ break;
+ case INPUT_CSI_VPA:
+ n = input_get(ictx, 0, 1, 1);
+ screen_write_cursormove(sctx, s->cx, n - 1);
+ break;
+ case INPUT_CSI_DECSCUSR:
+ n = input_get(ictx, 0, 0, 0);
+ screen_set_cursor_style(s, n);
+ break;
+ }
+
+ return (0);
+}
+
+/* Handle CSI RM. */
+void
+input_csi_dispatch_rm(struct input_ctx *ictx)
+{
+ u_int i;
+
+ for (i = 0; i < ictx->param_list_len; i++) {
+ switch (input_get(ictx, i, 0, -1)) {
case 4: /* IRM */
screen_write_mode_clear(&ictx->ctx, MODE_INSERT);
break;
@@ -1238,10 +1294,18 @@ input_csi_dispatch(struct input_ctx *ictx)
log_debug("%s: unknown '%c'", __func__, ictx->ch);
break;
}
- break;
- case INPUT_CSI_RM_PRIVATE:
- switch (input_get(ictx, 0, 0, -1)) {
- case 1: /* GATM */
+ }
+}
+
+/* Handle CSI private RM. */
+void
+input_csi_dispatch_rm_private(struct input_ctx *ictx)
+{
+ u_int i;
+
+ for (i = 0; i < ictx->param_list_len; i++) {
+ switch (input_get(ictx, i, 0, -1)) {
+ case 1: /* DECCKM */
screen_write_mode_clear(&ictx->ctx, MODE_KCURSOR);
break;
case 3: /* DECCOLM */
@@ -1271,10 +1335,10 @@ input_csi_dispatch(struct input_ctx *ictx)
break;
case 47:
case 1047:
- window_pane_alternate_off(wp, &ictx->cell, 0);
+ window_pane_alternate_off(ictx->wp, &ictx->cell, 0);
break;
case 1049:
- window_pane_alternate_off(wp, &ictx->cell, 1);
+ window_pane_alternate_off(ictx->wp, &ictx->cell, 1);
break;
case 2004:
screen_write_mode_clear(&ictx->ctx, MODE_BRACKETPASTE);
@@ -1283,17 +1347,17 @@ input_csi_dispatch(struct input_ctx *ictx)
log_debug("%s: unknown '%c'", __func__, ictx->ch);
break;
}
- break;
- case INPUT_CSI_SCP:
- memcpy(&ictx->old_cell, &ictx->cell, sizeof ictx->old_cell);
- ictx->old_cx = s->cx;
- ictx->old_cy = s->cy;
- break;
- case INPUT_CSI_SGR:
- input_csi_dispatch_sgr(ictx);
- break;
- case INPUT_CSI_SM:
- switch (input_get(ictx, 0, 0, -1)) {
+ }
+}
+
+/* Handle CSI SM. */
+void
+input_csi_dispatch_sm(struct input_ctx *ictx)
+{
+ u_int i;
+
+ for (i = 0; i < ictx->param_list_len; i++) {
+ switch (input_get(ictx, i, 0, -1)) {
case 4: /* IRM */
screen_write_mode_set(&ictx->ctx, MODE_INSERT);
break;
@@ -1301,10 +1365,18 @@ input_csi_dispatch(struct input_ctx *ictx)
log_debug("%s: unknown '%c'", __func__, ictx->ch);
break;
}
- break;
- case INPUT_CSI_SM_PRIVATE:
- switch (input_get(ictx, 0, 0, -1)) {
- case 1: /* GATM */
+ }
+}
+
+/* Handle CSI private SM. */
+void
+input_csi_dispatch_sm_private(struct input_ctx *ictx)
+{
+ u_int i;
+
+ for (i = 0; i < ictx->param_list_len; i++) {
+ switch (input_get(ictx, i, 0, -1)) {
+ case 1: /* DECCKM */
screen_write_mode_set(&ictx->ctx, MODE_KCURSOR);
break;
case 3: /* DECCOLM */
@@ -1330,10 +1402,10 @@ input_csi_dispatch(struct input_ctx *ictx)
screen_write_mode_set(&ictx->ctx, MODE_MOUSE_ANY);
break;
case 1004:
- if (s->mode & MODE_FOCUSON)
+ if (ictx->ctx.s->mode & MODE_FOCUSON)
break;
screen_write_mode_set(&ictx->ctx, MODE_FOCUSON);
- wp->flags |= PANE_FOCUSPUSH; /* force update */
+ ictx->wp->flags |= PANE_FOCUSPUSH; /* force update */
break;
case 1005:
screen_write_mode_set(&ictx->ctx, MODE_MOUSE_UTF8);
@@ -1343,10 +1415,10 @@ input_csi_dispatch(struct input_ctx *ictx)
break;
case 47:
case 1047:
- window_pane_alternate_on(wp, &ictx->cell, 0);
+ window_pane_alternate_on(ictx->wp, &ictx->cell, 0);
break;
case 1049:
- window_pane_alternate_on(wp, &ictx->cell, 1);
+ window_pane_alternate_on(ictx->wp, &ictx->cell, 1);
break;
case 2004:
screen_write_mode_set(&ictx->ctx, MODE_BRACKETPASTE);
@@ -1355,32 +1427,7 @@ input_csi_dispatch(struct input_ctx *ictx)
log_debug("%s: unknown '%c'", __func__, ictx->ch);
break;
}
- break;
- case INPUT_CSI_TBC:
- switch (input_get(ictx, 0, 0, 0)) {
- case 0:
- if (s->cx < screen_size_x(s))
- bit_clear(s->tabs, s->cx);
- break;
- case 3:
- bit_nclear(s->tabs, 0, screen_size_x(s) - 1);
- break;
- default:
- log_debug("%s: unknown '%c'", __func__, ictx->ch);
- break;
- }
- break;
- case INPUT_CSI_VPA:
- n = input_get(ictx, 0, 1, 1);
- screen_write_cursormove(sctx, s->cx, n - 1);
- break;
- case INPUT_CSI_DECSCUSR:
- n = input_get(ictx, 0, 0, 0);
- screen_set_cursor_style(s, n);
- break;
}
-
- return (0);
}
/* Handle CSI SGR. */
diff --git a/job.c b/job.c
index b2c2251c..d7bd852b 100644
--- a/job.c
+++ b/job.c
@@ -144,7 +144,7 @@ job_write_callback(unused struct bufferevent *bufev, void *data)
size_t len = EVBUFFER_LENGTH(EVBUFFER_OUTPUT(job->event));
log_debug("job write %p: %s, pid %ld, output left %zu", job, job->cmd,
- (long) job->pid, len);
+ (long) job->pid, len);
if (len == 0) {
shutdown(job->fd, SHUT_WR);
diff --git a/layout.c b/layout.c
index b74bd789..646d1bd9 100644
--- a/layout.c
+++ b/layout.c
@@ -533,6 +533,9 @@ layout_resize_pane_mouse(struct client *c)
pane_border = 0;
if (m->event & MOUSE_EVENT_DRAG && m->flags & MOUSE_RESIZE_PANE) {
TAILQ_FOREACH(wp, &w->panes, entry) {
+ if (!window_pane_visible(wp))
+ continue;
+
if (wp->xoff + wp->sx == m->lx &&
wp->yoff <= 1 + m->ly &&
wp->yoff + wp->sy >= m->ly) {
@@ -550,7 +553,7 @@ layout_resize_pane_mouse(struct client *c)
}
if (pane_border)
server_redraw_window(w);
- } else if (~m->event & MOUSE_EVENT_UP) {
+ } else if (m->event & MOUSE_EVENT_DOWN) {
TAILQ_FOREACH(wp, &w->panes, entry) {
if ((wp->xoff + wp->sx == m->x &&
wp->yoff <= 1 + m->y &&
diff --git a/names.c b/names.c
index f536d2fc..7c02961c 100644
--- a/names.c
+++ b/names.c
@@ -22,12 +22,10 @@
#include <libgen.h>
#include <stdlib.h>
#include <string.h>
-#include <unistd.h>
#include "tmux.h"
void window_name_callback(unused int, unused short, void *);
-char *parse_window_name(const char *);
void
queue_window_name(struct window *w)
@@ -47,7 +45,7 @@ void
window_name_callback(unused int fd, unused short events, void *data)
{
struct window *w = data;
- char *name, *wname;
+ char *name;
if (w->active == NULL)
return;
@@ -59,50 +57,40 @@ window_name_callback(unused int fd, unused short events, void *data)
}
queue_window_name(w);
- if (w->active->screen != &w->active->base)
- name = NULL;
- else
- name = osdep_get_name(w->active->fd, w->active->tty);
- if (name == NULL)
- wname = default_window_name(w);
- else {
- /*
- * If tmux is using the default command, it will be a login
- * shell and argv[0] may have a - prefix. Remove this if it is
- * present. Ick.
- */
- if (w->active->cmd != NULL && *w->active->cmd == '\0' &&
- name != NULL && name[0] == '-' && name[1] != '\0')
- wname = parse_window_name(name + 1);
- else
- wname = parse_window_name(name);
- free(name);
- }
-
- if (w->active->fd == -1) {
- xasprintf(&name, "%s[dead]", wname);
- free(wname);
- wname = name;
- }
-
- if (strcmp(wname, w->name)) {
- window_set_name(w, wname);
+ name = format_window_name(w);
+ if (strcmp(name, w->name) != 0) {
+ window_set_name(w, name);
server_status_window(w);
}
- free(wname);
+ free(name);
}
char *
default_window_name(struct window *w)
{
- if (w->active->screen != &w->active->base)
- return (xstrdup("[tmux]"));
if (w->active->cmd != NULL && *w->active->cmd != '\0')
return (parse_window_name(w->active->cmd));
return (parse_window_name(w->active->shell));
}
char *
+format_window_name(struct window *w)
+{
+ struct format_tree *ft;
+ char *fmt, *name;
+
+ ft = format_create();
+ format_window(ft, w);
+ format_window_pane(ft, w->active);
+
+ fmt = options_get_string(&w->options, "automatic-rename-format");
+ name = format_expand(ft, fmt);
+
+ format_free(ft);
+ return (name);
+}
+
+char *
parse_window_name(const char *in)
{
char *copy, *name, *ptr;
@@ -111,7 +99,7 @@ parse_window_name(const char *in)
if (strncmp(name, "exec ", (sizeof "exec ") - 1) == 0)
name = name + (sizeof "exec ") - 1;
- while (*name == ' ')
+ while (*name == ' ' || *name == '-')
name++;
if ((ptr = strchr(name, ' ')) != NULL)
*ptr = '\0';
diff --git a/options-table.c b/options-table.c
index 2281d652..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
@@ -386,7 +381,7 @@ const struct options_table_entry session_options_table[] = {
{ .name = "status-right",
.type = OPTIONS_TABLE_STRING,
- .default_str = "\"#22T\" %H:%M %d-%b-%y"
+ .default_str = "\"#{=22:pane_title}\" %H:%M %d-%b-%y"
},
{ .name = "status-right-attr",
@@ -481,6 +476,11 @@ const struct options_table_entry window_options_table[] = {
.default_num = 1
},
+ { .name = "automatic-rename-format",
+ .type = OPTIONS_TABLE_STRING,
+ .default_str = "#{?pane_in_mode,[tmux],#{pane_current_command}}#{?pane_dead,[dead],}"
+ },
+
{ .name = "c0-change-trigger",
.type = OPTIONS_TABLE_NUMBER,
.default_num = 250,
diff --git a/osdep-openbsd.c b/osdep-openbsd.c
index 7be38a91..c61d90e7 100644
--- a/osdep-openbsd.c
+++ b/osdep-openbsd.c
@@ -37,9 +37,7 @@
((p)->p_stat == SSTOP || (p)->p_stat == SZOMB || (p)->p_stat == SDEAD)
struct kinfo_proc *cmp_procs(struct kinfo_proc *, struct kinfo_proc *);
-char *osdep_get_name(int, char *);
-char *osdep_get_cwd(int);
-struct event_base *osdep_event_init(void);
+char *get_proc_name(int, char *);
struct kinfo_proc *
cmp_procs(struct kinfo_proc *p1, struct kinfo_proc *p2)
@@ -134,23 +132,3 @@ error:
free(buf);
return (NULL);
}
-
-char*
-osdep_get_cwd(int fd)
-{
- int name[] = { CTL_KERN, KERN_PROC_CWD, 0 };
- static char path[MAXPATHLEN];
- size_t pathlen = sizeof path;
-
- if ((name[2] = tcgetpgrp(fd)) == -1)
- return (NULL);
- if (sysctl(name, 3, path, &pathlen, NULL, 0) != 0)
- return (NULL);
- return (path);
-}
-
-struct event_base *
-osdep_event_init(void)
-{
- return (event_init());
-}
diff --git a/resize.c b/resize.c
index 5c365dfe..8d0bd275 100644
--- a/resize.c
+++ b/resize.c
@@ -92,7 +92,7 @@ recalculate_sizes(void)
for (i = 0; i < ARRAY_LENGTH(&windows); i++) {
w = ARRAY_ITEM(&windows, i);
- if (w == NULL)
+ if (w == NULL || w->active == NULL)
continue;
flag = options_get_number(&w->options, "aggressive-resize");
diff --git a/server-client.c b/server-client.c
index 5923eb0e..cc18a96f 100644
--- a/server-client.c
+++ b/server-client.c
@@ -40,9 +40,8 @@ void server_client_reset_state(struct client *);
int server_client_assume_paste(struct session *);
int server_client_msg_dispatch(struct client *);
-void server_client_msg_command(struct client *, struct msg_command_data *);
-void server_client_msg_identify(
- struct client *, struct msg_identify_data *, int);
+void server_client_msg_command(struct client *, struct imsg *);
+void server_client_msg_identify(struct client *, struct imsg *);
void server_client_msg_shell(struct client *);
/* Create a new client. */
@@ -63,6 +62,8 @@ server_client_create(int fd)
fatal("gettimeofday failed");
memcpy(&c->activity_time, &c->creation_time, sizeof c->activity_time);
+ environ_init(&c->environ);
+
c->cmdq = cmdq_new(c);
c->cmdq->client_exit = 1;
@@ -151,6 +152,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 +165,7 @@ server_client_lost(struct client *c)
screen_free(&c->status);
free(c->title);
+ close(c->cwd);
evtimer_del(&c->repeat_timer);
@@ -179,7 +183,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);
@@ -695,8 +698,6 @@ server_client_repeat_timer(unused int fd, unused short events, void *data)
void
server_client_check_exit(struct client *c)
{
- struct msg_exit_data exitdata;
-
if (!(c->flags & CLIENT_EXIT))
return;
@@ -707,9 +708,7 @@ server_client_check_exit(struct client *c)
if (EVBUFFER_LENGTH(c->stderr_data) != 0)
return;
- exitdata.retcode = c->retcode;
- server_write_client(c, MSG_EXIT, &exitdata, sizeof exitdata);
-
+ server_write_client(c, MSG_EXIT, &c->retval, sizeof c->retval);
c->flags &= ~CLIENT_EXIT;
}
@@ -790,10 +789,8 @@ int
server_client_msg_dispatch(struct client *c)
{
struct imsg imsg;
- struct msg_command_data commanddata;
- struct msg_identify_data identifydata;
- struct msg_environ_data environdata;
struct msg_stdin_data stdindata;
+ const char *data;
ssize_t n, datalen;
if ((n = imsg_read(&c->ibuf)) == -1 || n == 0)
@@ -804,40 +801,37 @@ server_client_msg_dispatch(struct client *c)
return (-1);
if (n == 0)
return (0);
+
+ data = imsg.data;
datalen = imsg.hdr.len - IMSG_HEADER_SIZE;
if (imsg.hdr.peerid != PROTOCOL_VERSION) {
server_write_client(c, MSG_VERSION, NULL, 0);
c->flags |= CLIENT_BAD;
+ if (imsg.fd != -1)
+ close(imsg.fd);
imsg_free(&imsg);
continue;
}
log_debug("got %d from client %d", imsg.hdr.type, c->ibuf.fd);
switch (imsg.hdr.type) {
- case MSG_COMMAND:
- if (datalen != sizeof commanddata)
- fatalx("bad MSG_COMMAND size");
- memcpy(&commanddata, imsg.data, sizeof commanddata);
-
- server_client_msg_command(c, &commanddata);
+ 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_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
- if (imsg.fd == -1)
- fatalx("MSG_IDENTIFY missing fd");
-
- server_client_msg_identify(c, &identifydata, imsg.fd);
+ case MSG_COMMAND:
+ server_client_msg_command(c, &imsg);
break;
case MSG_STDIN:
if (datalen != sizeof stdindata)
fatalx("bad MSG_STDIN size");
- memcpy(&stdindata, imsg.data, sizeof stdindata);
+ memcpy(&stdindata, data, sizeof stdindata);
if (c->stdin_callback == NULL)
break;
@@ -887,23 +881,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);
@@ -912,15 +895,26 @@ server_client_msg_dispatch(struct client *c)
/* Handle command message. */
void
-server_client_msg_command(struct client *c, struct msg_command_data *data)
+server_client_msg_command(struct client *c, struct imsg *imsg)
{
- struct cmd_list *cmdlist = NULL;
- int argc;
- char **argv, *cause;
-
- argc = data->argc;
- data->argv[(sizeof data->argv) - 1] = '\0';
- if (cmd_unpack_argv(data->argv, sizeof data->argv, argc, &argv) != 0) {
+ struct msg_command_data data;
+ char *buf;
+ size_t len;
+ struct cmd_list *cmdlist = NULL;
+ int argc;
+ char **argv, *cause;
+
+ if (imsg->hdr.len - IMSG_HEADER_SIZE < sizeof data)
+ fatalx("bad MSG_COMMAND size");
+ memcpy(&data, imsg->data, sizeof data);
+
+ buf = (char*)imsg->data + sizeof data;
+ len = imsg->hdr.len - IMSG_HEADER_SIZE - sizeof data;
+ if (len > 0 && buf[len - 1] != '\0')
+ fatalx("bad MSG_COMMAND string");
+
+ argc = data.argc;
+ if (cmd_unpack_argv(buf, len, argc, &argv) != 0) {
cmdq_error(c->cmdq, "command too long");
goto error;
}
@@ -951,44 +945,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 (datalen == 0 || data[datalen - 1] != '\0')
+ fatalx("bad MSG_IDENTIFY_TERM string");
+ c->term = xstrdup(data);
+ break;
+ case MSG_IDENTIFY_TTYNAME:
+ if (datalen == 0 || 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 (datalen == 0 || 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 (data->flags & IDENTIFY_CONTROL) {
+ 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 & IDENTIFY_TERMIOS)
+
+ 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 (!isatty(fd)) {
- close(fd);
+ if (c->fd == -1)
+ return;
+ 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 & IDENTIFY_UTF8)
+ tty_init(&c->tty, c, c->fd, c->term);
+ if (c->flags & CLIENT_UTF8)
c->tty.flags |= TTY_UTF8;
- if (data->flags & IDENTIFY_256COLOURS)
+ if (c->flags & CLIENT_256COLOURS)
c->tty.term_flags |= TERM_256COLOURS;
tty_resize(&c->tty);
- if (!(data->flags & IDENTIFY_CONTROL))
+ if (!(c->flags & CLIENT_CONTROL))
c->flags |= CLIENT_TERMINAL;
}
@@ -996,16 +1045,12 @@ server_client_msg_identify(
void
server_client_msg_shell(struct client *c)
{
- struct msg_shell_data data;
- const char *shell;
+ const char *shell;
shell = options_get_string(&global_s_options, "default-shell");
-
if (*shell == '\0' || areshell(shell))
shell = _PATH_BSHELL;
- if (strlcpy(data.shell, shell, sizeof data.shell) >= sizeof data.shell)
- strlcpy(data.shell, _PATH_BSHELL, sizeof data.shell);
+ server_write_client(c, MSG_SHELL, shell, strlen(shell) + 1);
- server_write_client(c, MSG_SHELL, &data, sizeof data);
c->flags |= CLIENT_BAD; /* it will die after exec */
}
diff --git a/server-fn.c b/server-fn.c
index 86e2054e..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;
@@ -235,9 +235,7 @@ server_lock_session(struct session *s)
void
server_lock_client(struct client *c)
{
- const char *cmd;
- size_t cmdlen;
- struct msg_lock_data lockdata;
+ const char *cmd;
if (c->flags & CLIENT_CONTROL)
return;
@@ -246,8 +244,7 @@ server_lock_client(struct client *c)
return;
cmd = options_get_string(&c->session->options, "lock-command");
- cmdlen = strlcpy(lockdata.cmd, cmd, sizeof lockdata.cmd);
- if (cmdlen >= sizeof lockdata.cmd)
+ if (strlen(cmd) + 1 > MAX_IMSGSIZE - IMSG_HEADER_SIZE)
return;
tty_stop_tty(&c->tty);
@@ -256,7 +253,7 @@ server_lock_client(struct client *c)
tty_raw(&c->tty, tty_term_string(c->tty.term, TTYC_E3));
c->flags |= CLIENT_SUSPENDED;
- server_write_client(c, MSG_LOCK, &lockdata, sizeof lockdata);
+ server_write_client(c, MSG_LOCK, cmd, strlen(cmd) + 1);
}
void
@@ -398,14 +395,15 @@ void
server_destroy_session_group(struct session *s)
{
struct session_group *sg;
+ struct session *s1;
if ((sg = session_group_find(s)) == NULL)
server_destroy_session(s);
else {
- TAILQ_FOREACH(s, &sg->sessions, gentry)
+ TAILQ_FOREACH_SAFE(s, &sg->sessions, gentry, s1) {
server_destroy_session(s);
- TAILQ_REMOVE(&session_groups, sg, entry);
- free(sg);
+ session_destroy(s);
+ }
}
}
diff --git a/session.c b/session.c
index 74eb06a5..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);
@@ -150,6 +149,7 @@ void
session_destroy(struct session *s)
{
struct winlink *wl;
+
log_debug("session %s destroyed", s->name);
RB_REMOVE(sessions, &sessions, s);
@@ -169,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);
}
@@ -225,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;
@@ -249,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);
@@ -614,7 +614,7 @@ session_renumber_windows(struct session *s)
memcpy(&old_lastw, &s->lastw, sizeof old_lastw);
TAILQ_INIT(&s->lastw);
TAILQ_FOREACH(wl, &old_lastw, sentry) {
- wl_new = winlink_find_by_index(&s->windows, wl->idx);
+ wl_new = winlink_find_by_window(&s->windows, wl->window);
if (wl_new != NULL)
TAILQ_INSERT_TAIL(&s->lastw, wl_new, sentry);
}
diff --git a/tmux.1 b/tmux.1
index 11251790..56cb3f8f 100644
--- a/tmux.1
+++ b/tmux.1
@@ -99,7 +99,9 @@ Force
.Nm
to assume the terminal supports 256 colours.
.It Fl C
-Start in control mode.
+Start in control mode (see the
+.Sx CONTROL MODE
+section).
Given twice
.Xo ( Fl CC ) Xc
disables echo.
@@ -566,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 )
@@ -599,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
@@ -626,9 +633,10 @@ If it does exist, exit with 0.
Kill the
.Nm
server and clients and destroy all sessions.
-.It Ic kill-session
+.It Xo Ic kill-session
.Op Fl a
.Op Fl t Ar target-session
+.Xc
Destroy the given session, closing any windows linked to it and no other
sessions, and detaching all clients attached to it.
If
@@ -673,6 +681,7 @@ Lock all clients attached to
.Ar target-session .
.It Xo Ic new-session
.Op Fl AdDP
+.Op Fl c Ar start-directory
.Op Fl F Ar format
.Op Fl n Ar window-name
.Op Fl s Ar session-name
@@ -1509,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
@@ -2175,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
@@ -2710,8 +2703,8 @@ The default is on.
Control automatic window renaming.
When this setting is enabled,
.Nm
-will attempt - on supported platforms - to rename the window to reflect the
-command currently running in it.
+will rename the window automatically using the format specified by
+.Ic automatic-rename-format .
This flag is automatically disabled for an individual window when a name
is specified at creation with
.Ic new-window
@@ -2725,6 +2718,13 @@ It may be switched off globally with:
set-window-option -g automatic-rename off
.Ed
.Pp
+.It Ic automatic-rename-format Ar format
+The format (see
+.Sx FORMATS )
+used when the
+.Ic automatic-rename
+option is enabled.
+.Pp
.It Ic c0-change-interval Ar interval
.It Ic c0-change-trigger Ar trigger
These two options configure a simple form of rate limiting for a pane.
@@ -2738,8 +2738,8 @@ instead redraw it entirely every
.Ar interval
milliseconds.
This helps to prevent fast output (such as
-.Xr yes 1
-overwhelming the terminal).
+.Xr yes 1 )
+overwhelming the terminal.
The default is a trigger of 250 and an interval of 100.
A trigger of zero disables the rate limiting.
.Pp
@@ -3026,6 +3026,12 @@ will include the string
if the session is attached and the string
.Ql not attached
if it is unattached.
+A limit may be placed on the length of the resultant string by prefixing it
+by an
+.Ql = ,
+a number and a colon, so
+.Ql #{=10:pane_title}
+will include at most the first 10 characters of the pane title.
.Pp
The following variables are available, where appropriate:
.Bl -column "XXXXXXXXXXXXXXXXXXX" "XXXXX"
@@ -3039,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"
@@ -3067,7 +3072,6 @@ The following variables are available, where appropriate:
.It Li "mouse_utf8_flag" Ta "" Ta "Pane mouse UTF-8 flag"
.It Li "pane_active" Ta "" Ta "1 if active pane"
.It Li "pane_current_command" Ta "" Ta "Current command if available"
-.It Li "pane_current_path" Ta "" Ta "Current path if available"
.It Li "pane_dead" Ta "" Ta "1 if pane is dead"
.It Li "pane_height" Ta "" Ta "Height of pane"
.It Li "pane_id" Ta "#D" Ta "Unique pane ID"
@@ -3096,6 +3100,9 @@ The following variables are available, where appropriate:
.It Li "session_width" Ta "" Ta "Width of session"
.It Li "session_windows" Ta "" Ta "Number of windows in session"
.It Li "window_active" Ta "" Ta "1 if window active"
+.It Li "window_activity_flag" Ta "" Ta "1 if window has activity alert"
+.It Li "window_bell_flag" Ta "" Ta "1 if window has bell"
+.It Li "window_content_flag" Ta "" Ta "1 if window has content alert"
.It Li "window_find_matches" Ta "" Ta "Matched data from the find-window"
.It Li "window_flags" Ta "#F" Ta "Window flags"
.It Li "window_height" Ta "" Ta "Height of window"
@@ -3104,6 +3111,7 @@ The following variables are available, where appropriate:
.It Li "window_layout" Ta "" Ta "Window layout description"
.It Li "window_name" Ta "#W" Ta "Name of window"
.It Li "window_panes" Ta "" Ta "Number of panes in window"
+.It Li "window_silence_flag" Ta "" Ta "1 if window has silence alert"
.It Li "window_width" Ta "" Ta "Width of window"
.It Li "wrap_flag" Ta "" Ta "Pane wrap flag"
.El
@@ -3562,7 +3570,7 @@ If the command doesn't return success, the exit status is also displayed.
.D1 (alias: Ic info )
Show server information and terminal details.
.It Xo Ic wait-for
-.Fl LSU
+.Op Fl L | S | U
.Ar channel
.Xc
.D1 (alias: Ic wait )
@@ -3803,4 +3811,4 @@ bind-key S command-prompt "new-window -n %1 'ssh %1'"
.Sh SEE ALSO
.Xr pty 4
.Sh AUTHORS
-.An Nicholas Marriott Aq nicm@users.sourceforge.net
+.An Nicholas Marriott Aq Mt nicm@users.sourceforge.net
diff --git a/tmux.c b/tmux.c
index 606c574f..1e6edd90 100644
--- a/tmux.c
+++ b/tmux.c
@@ -48,11 +48,8 @@ time_t start_time;
char socket_path[MAXPATHLEN];
int login_shell;
char *environ_path;
-pid_t environ_pid = -1;
-int environ_session_id = -1;
__dead void usage(void);
-void parseenvironment(void);
char *makesocketpath(const char *);
#ifndef HAVE___PROGNAME
@@ -127,39 +124,6 @@ areshell(const char *shell)
return (0);
}
-const char*
-get_full_path(const char *wd, const char *path)
-{
- static char newpath[MAXPATHLEN];
- char oldpath[MAXPATHLEN];
-
- if (getcwd(oldpath, sizeof oldpath) == NULL)
- return (NULL);
- if (chdir(wd) != 0)
- return (NULL);
- if (realpath(path, newpath) != 0)
- return (NULL);
- chdir(oldpath);
- return (newpath);
-}
-
-void
-parseenvironment(void)
-{
- char *env, path[256];
- long pid;
- int id;
-
- if ((env = getenv("TMUX")) == NULL)
- return;
-
- if (sscanf(env, "%255[^,],%ld,%d", path, &pid, &id) != 3)
- return;
- environ_path = xstrdup(path);
- environ_pid = pid;
- environ_session_id = id;
-}
-
char *
makesocketpath(const char *label)
{
@@ -184,7 +148,8 @@ makesocketpath(const char *label)
errno = ENOTDIR;
return (NULL);
}
- if (sb.st_uid != uid || (sb.st_mode & (S_IRWXG|S_IRWXO)) != 0) {
+ if (sb.st_uid != uid || (!S_ISDIR(sb.st_mode) &&
+ sb.st_mode & (S_IRWXG|S_IRWXO)) != 0) {
errno = EACCES;
return (NULL);
}
@@ -240,8 +205,10 @@ int
main(int argc, char **argv)
{
struct passwd *pw;
- char *s, *path, *label, *home, **var;
- int opt, flags, quiet, keys;
+ char *s, *path, *label, *home, **var, tmp[MAXPATHLEN];
+ char in[256];
+ long long pid;
+ int opt, flags, quiet, keys, session;
#if defined(DEBUG) && defined(__OpenBSD__)
malloc_options = (char *) "AFGJPX";
@@ -255,17 +222,17 @@ main(int argc, char **argv)
while ((opt = getopt(argc, argv, "2c:Cdf:lL:qS:uUVv")) != -1) {
switch (opt) {
case '2':
- flags |= IDENTIFY_256COLOURS;
+ flags |= CLIENT_256COLOURS;
break;
case 'c':
free(shell_cmd);
shell_cmd = xstrdup(optarg);
break;
case 'C':
- if (flags & IDENTIFY_CONTROL)
- flags |= IDENTIFY_TERMIOS;
+ if (flags & CLIENT_CONTROL)
+ flags |= CLIENT_CONTROLCONTROL;
else
- flags |= IDENTIFY_CONTROL;
+ flags |= CLIENT_CONTROL;
break;
case 'V':
printf("%s %s\n", __progname, VERSION);
@@ -289,7 +256,7 @@ main(int argc, char **argv)
path = xstrdup(optarg);
break;
case 'u':
- flags |= IDENTIFY_UTF8;
+ flags |= CLIENT_UTF8;
break;
case 'v':
debug_level++;
@@ -304,7 +271,7 @@ main(int argc, char **argv)
if (shell_cmd != NULL && argc != 0)
usage();
- if (!(flags & IDENTIFY_UTF8)) {
+ if (!(flags & CLIENT_UTF8)) {
/*
* If the user has set whichever of LC_ALL, LC_CTYPE or LANG
* exist (in that order) to contain UTF-8, it is a safe
@@ -318,12 +285,14 @@ main(int argc, char **argv)
}
if (s != NULL && (strcasestr(s, "UTF-8") != NULL ||
strcasestr(s, "UTF8") != NULL))
- flags |= IDENTIFY_UTF8;
+ flags |= CLIENT_UTF8;
}
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);
@@ -337,7 +306,7 @@ main(int argc, char **argv)
options_table_populate_tree(window_options_table, &global_w_options);
/* Enable UTF-8 if the first client is on UTF-8 terminal. */
- if (flags & IDENTIFY_UTF8) {
+ if (flags & CLIENT_UTF8) {
options_set_number(&global_s_options, "status-utf8", 1);
options_set_number(&global_s_options, "mouse-utf8", 1);
options_set_number(&global_w_options, "utf8", 1);
@@ -370,11 +339,15 @@ main(int argc, char **argv)
}
}
+ /* Get path from environment. */
+ s = getenv("TMUX");
+ if (s != NULL && sscanf(s, "%255[^,],%lld,%d", in, &pid, &session) == 3)
+ environ_path = xstrdup(in);
+
/*
* Figure out the socket path. If specified on the command-line with -S
* or -L, use it, otherwise try $TMUX or assume -L default.
*/
- parseenvironment();
if (path == NULL) {
/* If no -L, use the environment. */
if (label == NULL) {
@@ -387,7 +360,8 @@ main(int argc, char **argv)
/* -L or default set. */
if (label != NULL) {
if ((path = makesocketpath(label)) == NULL) {
- fprintf(stderr, "can't create socket\n");
+ fprintf(stderr, "can't create socket: %s\n",
+ strerror(errno));
exit(1);
}
}
diff --git a/tmux.h b/tmux.h
index cc1c79e8..3a298840 100644
--- a/tmux.h
+++ b/tmux.h
@@ -19,7 +19,7 @@
#ifndef TMUX_H
#define TMUX_H
-#define PROTOCOL_VERSION 7
+#define PROTOCOL_VERSION 8
#include <sys/param.h>
#include <sys/time.h>
@@ -52,14 +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 COMMAND_LENGTH 2048 /* packed argv size */
-#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.
*/
@@ -144,7 +136,7 @@ extern char **environ;
"[layout #{window_layout}] #{window_id}" \
"#{?window_active, (active),}";
#define LIST_WINDOWS_WITH_SESSION_TEMPLATE \
- "#{session_name}: " \
+ "#{session_name}:" \
"#{window_index}: #{window_name}#{window_flags} " \
"(#{window_panes} panes) " \
"[#{window_width}x#{window_height}] "
@@ -430,27 +422,33 @@ ARRAY_DECL(causelist, char *);
/* Message codes. */
enum msgtype {
- MSG_COMMAND,
+ MSG_VERSION = 12,
+
+ MSG_IDENTIFY_FLAGS = 100,
+ MSG_IDENTIFY_TERM,
+ MSG_IDENTIFY_TTYNAME,
+ MSG_IDENTIFY_CWD,
+ MSG_IDENTIFY_STDIN,
+ MSG_IDENTIFY_ENVIRON,
+ MSG_IDENTIFY_DONE,
+
+ MSG_COMMAND = 200,
MSG_DETACH,
- MSG_ERROR,
+ MSG_DETACHKILL,
MSG_EXIT,
MSG_EXITED,
MSG_EXITING,
- MSG_IDENTIFY,
- MSG_STDIN,
+ MSG_LOCK,
MSG_READY,
MSG_RESIZE,
- MSG_SHUTDOWN,
- MSG_SUSPEND,
- MSG_VERSION,
- MSG_WAKEUP,
- MSG_ENVIRON,
- MSG_UNLOCK,
- MSG_LOCK,
MSG_SHELL,
+ MSG_SHUTDOWN,
MSG_STDERR,
+ MSG_STDIN,
MSG_STDOUT,
- MSG_DETACHKILL
+ MSG_SUSPEND,
+ MSG_UNLOCK,
+ MSG_WAKEUP,
};
/*
@@ -459,45 +457,8 @@ enum msgtype {
* Don't forget to bump PROTOCOL_VERSION if any of these change!
*/
struct msg_command_data {
- pid_t pid; /* from $TMUX or -1 */
- int session_id; /* from $TMUX or -1 */
-
- int argc;
- char argv[COMMAND_LENGTH];
-};
-
-struct msg_identify_data {
- char cwd[MAXPATHLEN];
-
- char term[TERMINAL_LENGTH];
-
-#ifdef __CYGWIN__
- char ttyname[TTY_NAME_MAX];
-#endif
-
-#define IDENTIFY_UTF8 0x1
-#define IDENTIFY_256COLOURS 0x2
-/* 0x4 unused */
-#define IDENTIFY_CONTROL 0x8
-#define IDENTIFY_TERMIOS 0x10
- int flags;
-};
-
-struct msg_lock_data {
- char cmd[COMMAND_LENGTH];
-};
-
-struct msg_environ_data {
- char var[ENVIRON_LENGTH];
-};
-
-struct msg_shell_data {
- char shell[MAXPATHLEN];
-};
-
-struct msg_exit_data {
- int retcode;
-};
+ int argc;
+}; /* followed by packed argv */
struct msg_stdin_data {
ssize_t size;
@@ -945,7 +906,7 @@ struct window_pane {
char *cmd;
char *shell;
- char *cwd;
+ int cwd;
pid_t pid;
char tty[TTY_NAME_MAX];
@@ -1005,6 +966,7 @@ struct window {
#define WINDOW_REDRAW 0x4
#define WINDOW_SILENCE 0x8
#define WINDOW_ZOOMED 0x10
+#define WINDOW_ALERTFLAGS (WINDOW_BELL|WINDOW_ACTIVITY|WINDOW_SILENCE)
struct options options;
@@ -1091,7 +1053,7 @@ struct session {
u_int id;
char *name;
- char *cwd;
+ int cwd;
struct timeval creation_time;
struct timeval activity_time;
@@ -1290,8 +1252,10 @@ RB_HEAD(status_out_tree, status_out);
/* Client connection. */
struct client {
struct imsgbuf ibuf;
+
+ int fd;
struct event event;
- int retcode;
+ int retval;
struct timeval creation_time;
struct timeval activity_time;
@@ -1299,8 +1263,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 *);
@@ -1322,7 +1288,7 @@ struct client {
#define CLIENT_EXIT 0x4
#define CLIENT_REDRAW 0x8
#define CLIENT_STATUS 0x10
-#define CLIENT_REPEAT 0x20 /* allow command to repeat within repeat time */
+#define CLIENT_REPEAT 0x20
#define CLIENT_SUSPENDED 0x40
#define CLIENT_BAD 0x80
#define CLIENT_IDENTIFY 0x100
@@ -1331,7 +1297,11 @@ struct client {
#define CLIENT_READONLY 0x800
#define CLIENT_REDRAWWINDOW 0x1000
#define CLIENT_CONTROL 0x2000
-#define CLIENT_FOCUSED 0x4000
+#define CLIENT_CONTROLCONTROL 0x4000
+#define CLIENT_FOCUSED 0x8000
+#define CLIENT_UTF8 0x10000
+#define CLIENT_256COLOURS 0x20000
+#define CLIENT_IDENTIFIED 0x40000
int flags;
struct event identify_timer;
@@ -1428,8 +1398,6 @@ struct cmd_q {
void (*emptyfn)(struct cmd_q *);
void *data;
- struct msg_command_data *msgdata;
-
TAILQ_ENTRY(cmd_q) waitentry;
};
@@ -1446,12 +1414,10 @@ struct cmd_entry {
#define CMD_STARTSERVER 0x1
#define CMD_CANTNEST 0x2
-#define CMD_SENDENVIRON 0x4
-#define CMD_READONLY 0x8
+#define CMD_READONLY 0x4
int flags;
void (*key_binding)(struct cmd *, int);
- int (*check)(struct args *);
enum cmd_retval (*exec)(struct cmd *, struct cmd_q *);
};
@@ -1525,13 +1491,10 @@ extern time_t start_time;
extern char socket_path[MAXPATHLEN];
extern int login_shell;
extern char *environ_path;
-extern pid_t environ_pid;
-extern int environ_session_id;
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 *);
@@ -1549,16 +1512,19 @@ int format_cmp(struct format_entry *, struct format_entry *);
RB_PROTOTYPE(format_tree, format_entry, entry, format_cmp);
struct format_tree *format_create(void);
void format_free(struct format_tree *);
-void printflike3 format_add(
- struct format_tree *, const char *, const char *, ...);
+void printflike3 format_add(struct format_tree *, const char *, const char *,
+ ...);
const char *format_find(struct format_tree *, const char *);
char *format_expand(struct format_tree *, const char *);
void format_session(struct format_tree *, struct session *);
void format_client(struct format_tree *, struct client *);
-void format_winlink(
- struct format_tree *, struct session *, struct winlink *);
-void format_window_pane(struct format_tree *, struct window_pane *);
-void format_paste_buffer(struct format_tree *, struct paste_buffer *);
+void format_window(struct format_tree *, struct window *);
+void format_winlink(struct format_tree *, struct session *,
+ struct winlink *);
+void format_window_pane(struct format_tree *,
+ struct window_pane *);
+void format_paste_buffer(struct format_tree *,
+ struct paste_buffer *);
/* mode-key.c */
extern const struct mode_key_table mode_key_tables[];
@@ -1764,7 +1730,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_get_default_path(struct cmd_q *, 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;
@@ -1855,7 +1820,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 **);
@@ -1868,7 +1834,7 @@ int cmdq_free(struct cmd_q *);
void printflike2 cmdq_print(struct cmd_q *, const char *, ...);
void printflike2 cmdq_info(struct cmd_q *, const char *, ...);
void printflike2 cmdq_error(struct cmd_q *, const char *, ...);
-int cmdq_guard(struct cmd_q *, const char *);
+int cmdq_guard(struct cmd_q *, const char *, int);
void cmdq_run(struct cmd_q *, struct cmd_list *);
void cmdq_append(struct cmd_q *, struct cmd_list *);
int cmdq_continue(struct cmd_q *);
@@ -1919,10 +1885,10 @@ void server_window_loop(void);
/* server-fn.c */
void server_fill_environ(struct session *, struct environ *);
void server_write_ready(struct client *);
-int server_write_client(
- struct client *, enum msgtype, const void *, size_t);
-void server_write_session(
- struct session *, enum msgtype, const void *, size_t);
+int server_write_client(struct client *, enum msgtype, const void *,
+ size_t);
+void server_write_session(struct session *, enum msgtype, const void *,
+ size_t);
void server_redraw_client(struct client *);
void server_status_client(struct client *);
void server_redraw_session(struct session *);
@@ -2144,9 +2110,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);
@@ -2170,8 +2136,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);
@@ -2272,8 +2238,10 @@ void window_choose_collapse_all(struct window_pane *);
void window_choose_set_current(struct window_pane *, u_int);
/* names.c */
-void queue_window_name(struct window *);
-char *default_window_name(struct window *);
+void queue_window_name(struct window *);
+char *default_window_name(struct window *);
+char *format_window_name(struct window *);
+char *parse_window_name(const char *);
/* signal.c */
void set_signals(void(*)(int, short, void *));
@@ -2305,7 +2273,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 *);
@@ -2313,8 +2281,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 *);
@@ -2340,10 +2308,8 @@ int utf8_append(struct utf8_data *, u_char);
u_int utf8_combine(const struct utf8_data *);
u_int utf8_split2(u_int, u_char *);
-/* osdep-*.c */
-char *osdep_get_name(int, char *);
-char *osdep_get_cwd(int);
-struct event_base *osdep_event_init(void);
+/* procname.c */
+char *get_proc_name(int, char *);
/* log.c */
void log_open(int, const char *);
diff --git a/tty-keys.c b/tty-keys.c
index 3055f399..595ad6e1 100644
--- a/tty-keys.c
+++ b/tty-keys.c
@@ -676,11 +676,17 @@ tty_keys_mouse(struct tty *tty, const char *buf, size_t len, size_t *size)
log_debug("mouse input: %.*s", (int) *size, buf);
/* Check and return the mouse input. */
- if (b < 32 || x < 33 || y < 33)
+ if (b < 32)
return (-1);
b -= 32;
- x -= 33;
- y -= 33;
+ if (x >= 33)
+ x -= 33;
+ else
+ x = 256 - x;
+ if (y >= 33)
+ y -= 33;
+ else
+ y = 256 - y;
} else if (buf[2] == '<') {
/* Read the three inputs. */
*size = 3;
@@ -740,6 +746,8 @@ tty_keys_mouse(struct tty *tty, const char *buf, size_t len, size_t *size)
m->sgr = sgr;
m->sgr_xb = sgr_b;
m->sgr_rel = sgr_rel;
+ m->x = x;
+ m->y = y;
if (b & 64) { /* wheel button */
b &= 3;
if (b == 0)
@@ -767,8 +775,6 @@ tty_keys_mouse(struct tty *tty, const char *buf, size_t len, size_t *size)
}
m->button = (b & 3);
}
- m->x = x;
- m->y = y;
return (0);
}
diff --git a/window-choose.c b/window-choose.c
index 5ed85f0e..572581a5 100644
--- a/window-choose.c
+++ b/window-choose.c
@@ -81,6 +81,7 @@ int window_choose_key_index(struct window_choose_mode_data *, u_int);
int window_choose_index_key(struct window_choose_mode_data *, int);
void window_choose_prompt_input(enum window_choose_input_type,
const char *, struct window_pane *, int);
+void window_choose_reset_top(struct window_pane *, u_int);
void
window_choose_add(struct window_pane *wp, struct window_choose_data *wcd)
@@ -107,8 +108,17 @@ window_choose_set_current(struct window_pane *wp, u_int cur)
struct screen *s = &data->screen;
data->selected = cur;
- if (data->selected > screen_size_y(s) - 1)
- data->top = ARRAY_LENGTH(&data->list) - screen_size_y(s);
+ window_choose_reset_top(wp, screen_size_y(s));
+}
+
+void
+window_choose_reset_top(struct window_pane *wp, u_int sy)
+{
+ struct window_choose_mode_data *data = wp->modedata;
+
+ data->top = 0;
+ if (data->selected > sy - 1)
+ data->top = data->selected - (sy - 1);
window_choose_redraw_screen(wp);
}
@@ -277,10 +287,7 @@ window_choose_resize(struct window_pane *wp, u_int sx, u_int sy)
struct window_choose_mode_data *data = wp->modedata;
struct screen *s = &data->screen;
- data->top = 0;
- if (data->selected > sy - 1)
- data->top = data->selected - (sy - 1);
-
+ window_choose_reset_top(wp, sy);
screen_resize(s, sx, sy, 0);
window_choose_redraw_screen(wp);
}
@@ -373,6 +380,7 @@ window_choose_collapse_all(struct window_pane *wp)
{
struct window_choose_mode_data *data = wp->modedata;
struct window_choose_mode_item *item;
+ struct screen *scr = &data->screen;
struct session *s, *chosen;
u_int i;
@@ -391,7 +399,7 @@ window_choose_collapse_all(struct window_pane *wp)
if (item->wcd->type & TREE_SESSION)
data->selected = i;
}
- window_choose_redraw_screen(wp);
+ window_choose_reset_top(wp, screen_size_y(scr));
}
void
@@ -399,6 +407,7 @@ window_choose_expand_all(struct window_pane *wp)
{
struct window_choose_mode_data *data = wp->modedata;
struct window_choose_mode_item *item;
+ struct screen *scr = &data->screen;
struct session *s;
u_int i;
@@ -414,7 +423,7 @@ window_choose_expand_all(struct window_pane *wp)
}
}
- window_choose_redraw_screen(wp);
+ window_choose_reset_top(wp, screen_size_y(scr));
}
void
diff --git a/window.c b/window.c
index 7678adc6..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)
@@ -1243,6 +1243,7 @@ winlink_clear_flags(struct winlink *wl)
continue;
wm->flags &= ~WINLINK_ALERTFLAGS;
+ wm->window->flags &= ~WINDOW_ALERTFLAGS;
server_status_session(s);
}
}