Merge branch 'obsd-master' into mtemp

This commit is contained in:
Thomas 2013-10-11 14:33:29 +01:00
commit 7f479ffdce
93 changed files with 1001 additions and 895 deletions

190
client.c
View File

@ -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) {
} 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;
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);
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;
char *data;
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;
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)
if (datalen != sizeof retval && datalen != 0)
fatalx("bad MSG_EXIT size");
} else {
memcpy(&exitdata, imsg.data, sizeof exitdata);
client_exitval = exitdata.retcode;
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);
@ -591,8 +617,8 @@ int
client_dispatch_attached(void)
{
struct imsg imsg;
struct msg_lock_data lockdata;
struct sigaction sigact;
char *data;
ssize_t n, datalen;
for (;;) {
@ -600,15 +626,18 @@ client_dispatch_attached(void)
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);

View File

@ -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;
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')));
}

View File

@ -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,23 +37,9 @@ 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)
{
@ -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]);

View File

@ -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
};

View File

@ -42,7 +42,6 @@ const struct cmd_entry cmd_capture_pane_entry = {
CMD_TARGET_PANE_USAGE,
0,
NULL,
NULL,
cmd_capture_pane_exec
};

View File

@ -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
};

View File

@ -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
};

View File

@ -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
};

View File

@ -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);

View File

@ -32,7 +32,6 @@ const struct cmd_entry cmd_clear_history_entry = {
CMD_TARGET_PANE_USAGE,
0,
NULL,
NULL,
cmd_clear_history_exec
};

View File

@ -32,7 +32,6 @@ const struct cmd_entry cmd_clock_mode_entry = {
CMD_TARGET_PANE_USAGE,
0,
NULL,
NULL,
cmd_clock_mode_exec
};

View File

@ -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
};

View File

@ -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
};

View File

@ -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
};

View File

@ -34,7 +34,6 @@ const struct cmd_entry cmd_delete_buffer_entry = {
CMD_BUFFER_USAGE,
0,
NULL,
NULL,
cmd_delete_buffer_exec
};

View File

@ -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
};
@ -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, c->session->name,
strlen(c->session->name) + 1);
}
} else
server_write_client(c, msgtype, NULL, 0);
}
return (CMD_RETURN_STOP);

View File

@ -36,7 +36,6 @@ const struct cmd_entry cmd_display_message_entry = {
" [message]",
0,
NULL,
NULL,
cmd_display_message_exec
};

View File

@ -32,7 +32,6 @@ const struct cmd_entry cmd_display_panes_entry = {
CMD_TARGET_CLIENT_USAGE,
0,
NULL,
NULL,
cmd_display_panes_exec
};

View File

@ -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
};

View File

@ -32,7 +32,6 @@ const struct cmd_entry cmd_has_session_entry = {
CMD_TARGET_SESSION_USAGE,
0,
NULL,
NULL,
cmd_has_session_exec
};

View File

@ -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);

View File

@ -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
};

View File

@ -34,7 +34,6 @@ const struct cmd_entry cmd_kill_pane_entry = {
"[-a] " CMD_TARGET_PANE_USAGE,
0,
NULL,
NULL,
cmd_kill_pane_exec
};

View File

@ -35,7 +35,6 @@ const struct cmd_entry cmd_kill_server_entry = {
"",
0,
NULL,
NULL,
cmd_kill_server_exec
};

View File

@ -35,7 +35,6 @@ const struct cmd_entry cmd_kill_session_entry = {
"[-a] " CMD_TARGET_SESSION_USAGE,
0,
NULL,
NULL,
cmd_kill_session_exec
};

View File

@ -32,7 +32,6 @@ const struct cmd_entry cmd_kill_window_entry = {
"[-a] " CMD_TARGET_WINDOW_USAGE,
0,
NULL,
NULL,
cmd_kill_window_exec
};

View File

@ -34,7 +34,6 @@ const struct cmd_entry cmd_link_window_entry = {
"[-dk] " CMD_SRCDST_WINDOW_USAGE,
0,
NULL,
NULL,
cmd_link_window_exec
};

View File

@ -35,7 +35,6 @@ const struct cmd_entry cmd_list_buffers_entry = {
"[-F format]",
0,
NULL,
NULL,
cmd_list_buffers_exec
};

View File

@ -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
};

View File

@ -32,7 +32,6 @@ const struct cmd_entry cmd_list_commands_entry = {
"",
0,
NULL,
NULL,
cmd_list_commands_exec
};

View File

@ -35,7 +35,6 @@ const struct cmd_entry cmd_list_keys_entry = {
"[-t key-table]",
0,
NULL,
NULL,
cmd_list_keys_exec
};

View File

@ -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
};

View File

@ -36,7 +36,6 @@ const struct cmd_entry cmd_list_sessions_entry = {
"[-F format]",
0,
NULL,
NULL,
cmd_list_sessions_exec
};

View File

@ -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
};

View File

@ -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);
}

View File

@ -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
};

View File

@ -34,7 +34,6 @@ const struct cmd_entry cmd_move_window_entry = {
"[-dkr] " CMD_SRCDST_WINDOW_USAGE,
0,
NULL,
NULL,
cmd_move_window_exec
};

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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
};

View File

@ -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
};

View File

@ -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 */

View File

@ -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
};

View File

@ -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
};

View File

@ -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
};

View File

@ -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
};

View File

@ -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);

View File

@ -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);

View File

@ -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
};

View File

@ -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
};

View File

@ -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);
}

View File

@ -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
};

View File

@ -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
};

View File

@ -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
};

View File

@ -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
};

View File

@ -38,7 +38,6 @@ const struct cmd_entry cmd_server_info_entry = {
"",
0,
NULL,
NULL,
cmd_server_info_exec
};

View File

@ -35,7 +35,6 @@ const struct cmd_entry cmd_set_buffer_entry = {
CMD_BUFFER_USAGE " data",
0,
NULL,
NULL,
cmd_set_buffer_exec
};

View File

@ -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
};

View File

@ -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
};

View File

@ -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
};

View File

@ -35,7 +35,6 @@ const struct cmd_entry cmd_show_messages_entry = {
CMD_TARGET_CLIENT_USAGE,
0,
NULL,
NULL,
cmd_show_messages_exec
};

View File

@ -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
};

View File

@ -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--;

View File

@ -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);
}

View File

@ -32,7 +32,6 @@ const struct cmd_entry cmd_start_server_entry = {
"",
CMD_STARTSERVER,
NULL,
NULL,
cmd_start_server_exec
};

View File

@ -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)
home = pw->pw_dir;
free(username);
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(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);
}

View File

@ -35,7 +35,6 @@ const struct cmd_entry cmd_suspend_client_entry = {
CMD_TARGET_CLIENT_USAGE,
0,
NULL,
NULL,
cmd_suspend_client_exec
};

View File

@ -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
};

View File

@ -34,7 +34,6 @@ const struct cmd_entry cmd_swap_window_entry = {
"[-d] " CMD_SRCDST_WINDOW_USAGE,
0,
NULL,
NULL,
cmd_swap_window_exec
};

View File

@ -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
};

View File

@ -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,20 +35,9 @@ 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)
{
@ -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));

View File

@ -32,7 +32,6 @@ const struct cmd_entry cmd_unlink_window_entry = {
"[-k] " CMD_TARGET_WINDOW_USAGE,
0,
NULL,
NULL,
cmd_unlink_window_exec
};

View File

@ -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
};

94
cmd.c
View File

@ -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);
}

View File

@ -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 {

143
format.c
View File

@ -18,6 +18,8 @@
#include <sys/types.h>
#include <ctype.h>
#include <errno.h>
#include <netdb.h>
#include <stdarg.h>
#include <stdlib.h>
@ -34,6 +36,7 @@
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. */
@ -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,10 +408,11 @@ format_client(struct format_tree *ft, struct client *c)
time_t t;
struct session *s;
format_add(ft, "client_cwd", "%s", c->cwd);
format_add(ft, "client_height", "%u", c->tty.sy);
format_add(ft, "client_width", "%u", c->tty.sx);
if (c->tty.path != NULL)
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;
@ -381,28 +447,50 @@ format_client(struct format_tree *ft, struct client *c)
format_add(ft, "client_last_session", "%s", s->name);
}
/* Set default format keys for a window. */
void
format_window(struct format_tree *ft, struct window *w)
{
char *layout;
layout = layout_dump(w);
format_add(ft, "window_id", "@%u", w->id);
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_layout", "%s", layout);
format_add(ft, "window_panes", "%u", window_count_panes(w));
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 *layout, *flags;
char *flags;
layout = layout_dump(w);
flags = window_printable_flags(s, wl);
format_add(ft, "window_id", "@%u", w->id);
format_window(ft, w);
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));
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);
free(layout);
}
/* Add window pane tabs. */
@ -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);
}

13
grid.c
View File

@ -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;

151
input.c
View File

@ -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. */

View File

@ -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 &&

58
names.c
View File

@ -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,49 +57,39 @@ 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)
{
@ -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';

View File

@ -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,

View File

@ -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());
}

View File

@ -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");

View File

@ -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 msg_command_data data;
char *buf;
size_t len;
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) {
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 (data->flags & IDENTIFY_CONTROL) {
if (c->flags & CLIENT_IDENTIFIED)
fatalx("out-of-order identify message");
data = imsg->data;
datalen = imsg->hdr.len - IMSG_HEADER_SIZE;
switch (imsg->hdr.type) {
case MSG_IDENTIFY_FLAGS:
if (datalen != sizeof flags)
fatalx("bad MSG_IDENTIFY_FLAGS size");
memcpy(&flags, data, sizeof flags);
c->flags |= flags;
break;
case MSG_IDENTIFY_TERM:
if (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 (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;
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 */
}

View File

@ -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;
@ -236,8 +236,6 @@ void
server_lock_client(struct client *c)
{
const char *cmd;
size_t cmdlen;
struct msg_lock_data lockdata;
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);
}
}
}

View File

@ -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);
}

60
tmux.1
View File

@ -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

72
tmux.c
View File

@ -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);
}
}

164
tmux.h
View File

@ -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>
@ -51,14 +51,6 @@ extern char **environ;
/* Automatic name refresh interval, in milliseconds. */
#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;
};
}; /* 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);
@ -2274,6 +2240,8 @@ void window_choose_set_current(struct window_pane *, u_int);
/* names.c */
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 *);

View File

@ -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;
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);
}

View File

@ -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

View File

@ -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);
}
}