Make all messages sent between the client and server fixed size.

This is the first of two changes to make the protocol more resilient and less
sensitive to other changes in the code, particularly with commands. The client
now packs argv into a buffer and sends it to the server for parsing, rather
than doing it itself and sending the parsed command data.

As a side-effect this also removes a lot of now-unused command marshalling
code.

Mixing a server without this change and a client with or vice versa will cause
tmux to hang or crash, please ensure that tmux is entirely killed before
upgrading.
pull/1/head
Nicholas Marriott 2009-07-26 12:58:44 +00:00
parent 2bb89bc5bc
commit 34a82e7629
82 changed files with 253 additions and 780 deletions

View File

@ -74,19 +74,3 @@ client_write_server(
if (buf != NULL && len > 0)
buffer_write(cctx->srv_out, buf, len);
}
void
client_write_server2(struct client_ctx *cctx,
enum hdrtype type, void *buf1, size_t len1, void *buf2, size_t len2)
{
struct hdr hdr;
hdr.type = type;
hdr.size = len1 + len2;
buffer_write(cctx->srv_out, &hdr, sizeof hdr);
if (buf1 != NULL && len1 > 0)
buffer_write(cctx->srv_out, buf1, len1);
if (buf2 != NULL && len2 > 0)
buffer_write(cctx->srv_out, buf2, len2);
}

View File

@ -70,16 +70,15 @@ client_msg_dispatch(struct client_ctx *cctx)
int
client_msg_fn_error(struct hdr *hdr, struct client_ctx *cctx)
{
char *errstr;
struct msg_print_data data;
if (hdr->size == SIZE_MAX)
fatalx("bad MSG_ERROR size");
if (hdr->size < sizeof data)
fatalx("bad MSG_PRINT size");
buffer_read(cctx->srv_in, &data, sizeof data);
errstr = xmalloc(hdr->size + 1);
buffer_read(cctx->srv_in, errstr, hdr->size);
errstr[hdr->size] = '\0';
data.msg[(sizeof data.msg) - 1] = '\0';
cctx->errstr = xstrdup(data.msg);
cctx->errstr = errstr;
return (-1);
}

View File

@ -44,8 +44,7 @@ client_init(char *path, struct client_ctx *cctx, int cmdflags, int flags)
struct winsize ws;
size_t size;
int mode;
struct buffer *b;
char *name;
char *name, *term;
char rpathbuf[MAXPATHLEN];
if (realpath(path, rpathbuf) == NULL)
@ -103,20 +102,24 @@ server_started:
data.flags = flags;
data.sx = ws.ws_col;
data.sy = ws.ws_row;
*data.tty = '\0';
if (getcwd(data.cwd, sizeof data.cwd) == NULL)
*data.cwd = '\0';
*data.term = '\0';
if ((term = getenv("TERM")) != NULL) {
if (strlcpy(data.term,
term, sizeof data.term) >= sizeof data.term)
*data.term = '\0';
}
*data.tty = '\0';
if ((name = ttyname(STDIN_FILENO)) == NULL)
fatal("ttyname failed");
if (strlcpy(data.tty, name, sizeof data.tty) >= sizeof data.tty)
fatalx("ttyname failed");
b = buffer_create(BUFSIZ);
cmd_send_string(b, getenv("TERM"));
client_write_server2(cctx, MSG_IDENTIFY,
&data, sizeof data, BUFFER_OUT(b), BUFFER_USED(b));
buffer_destroy(b);
client_write_server(cctx, MSG_IDENTIFY, &data, sizeof data);
}
return (0);

View File

@ -33,8 +33,6 @@ const struct cmd_entry cmd_attach_session_entry = {
cmd_target_init,
cmd_target_parse,
cmd_attach_session_exec,
cmd_target_send,
cmd_target_recv,
cmd_target_free,
cmd_target_print
};

View File

@ -26,8 +26,6 @@
int cmd_bind_key_parse(struct cmd *, int, char **, char **);
int cmd_bind_key_exec(struct cmd *, struct cmd_ctx *);
void cmd_bind_key_send(struct cmd *, struct buffer *);
void cmd_bind_key_recv(struct cmd *, struct buffer *);
void cmd_bind_key_free(struct cmd *);
size_t cmd_bind_key_print(struct cmd *, char *, size_t);
@ -44,8 +42,6 @@ const struct cmd_entry cmd_bind_key_entry = {
NULL,
cmd_bind_key_parse,
cmd_bind_key_exec,
cmd_bind_key_send,
cmd_bind_key_recv,
cmd_bind_key_free,
cmd_bind_key_print
};
@ -113,25 +109,6 @@ cmd_bind_key_exec(struct cmd *self, unused struct cmd_ctx *ctx)
return (0);
}
void
cmd_bind_key_send(struct cmd *self, struct buffer *b)
{
struct cmd_bind_key_data *data = self->data;
buffer_write(b, data, sizeof *data);
cmd_list_send(data->cmdlist, b);
}
void
cmd_bind_key_recv(struct cmd *self, struct buffer *b)
{
struct cmd_bind_key_data *data;
self->data = data = xmalloc(sizeof *data);
buffer_read(b, data, sizeof *data);
data->cmdlist = cmd_list_recv(b);
}
void
cmd_bind_key_free(struct cmd *self)
{

View File

@ -35,8 +35,6 @@ const struct cmd_entry cmd_break_pane_entry = {
cmd_pane_init,
cmd_pane_parse,
cmd_break_pane_exec,
cmd_pane_send,
cmd_pane_recv,
cmd_pane_free,
cmd_pane_print
};

View File

@ -35,8 +35,6 @@ const struct cmd_entry cmd_choose_session_entry = {
cmd_target_init,
cmd_target_parse,
cmd_choose_session_exec,
cmd_target_send,
cmd_target_recv,
cmd_target_free,
cmd_target_print
};

View File

@ -35,8 +35,6 @@ const struct cmd_entry cmd_choose_window_entry = {
cmd_target_init,
cmd_target_parse,
cmd_choose_window_exec,
cmd_target_send,
cmd_target_recv,
cmd_target_free,
cmd_target_print
};

View File

@ -33,8 +33,6 @@ const struct cmd_entry cmd_clear_history_entry = {
cmd_pane_init,
cmd_pane_parse,
cmd_clear_history_exec,
cmd_pane_send,
cmd_pane_recv,
cmd_pane_free,
cmd_pane_print
};

View File

@ -33,8 +33,6 @@ const struct cmd_entry cmd_clock_mode_entry = {
cmd_target_init,
cmd_target_parse,
cmd_clock_mode_exec,
cmd_target_send,
cmd_target_recv,
cmd_target_free,
cmd_target_print
};

View File

@ -40,8 +40,6 @@ const struct cmd_entry cmd_command_prompt_entry = {
cmd_command_prompt_init,
cmd_target_parse,
cmd_command_prompt_exec,
cmd_target_send,
cmd_target_recv,
cmd_target_free,
cmd_target_print
};

View File

@ -38,8 +38,6 @@ const struct cmd_entry cmd_confirm_before_entry = {
cmd_confirm_before_init,
cmd_target_parse,
cmd_confirm_before_exec,
cmd_target_send,
cmd_target_recv,
cmd_target_free,
cmd_target_print
};

View File

@ -26,8 +26,6 @@
int cmd_copy_buffer_parse(struct cmd *, int, char **, char **);
int cmd_copy_buffer_exec(struct cmd *, struct cmd_ctx *);
void cmd_copy_buffer_send(struct cmd *, struct buffer *);
void cmd_copy_buffer_recv(struct cmd *, struct buffer *);
void cmd_copy_buffer_free(struct cmd *);
void cmd_copy_buffer_init(struct cmd *, int);
size_t cmd_copy_buffer_print(struct cmd *, char *, size_t);
@ -46,8 +44,6 @@ const struct cmd_entry cmd_copy_buffer_entry = {
cmd_copy_buffer_init,
cmd_copy_buffer_parse,
cmd_copy_buffer_exec,
cmd_copy_buffer_send,
cmd_copy_buffer_recv,
cmd_copy_buffer_free,
cmd_copy_buffer_print
};
@ -160,27 +156,6 @@ cmd_copy_buffer_exec(struct cmd *self, struct cmd_ctx *ctx)
return (0);
}
void
cmd_copy_buffer_send(struct cmd *self, struct buffer *b)
{
struct cmd_copy_buffer_data *data = self->data;
buffer_write(b, data, sizeof *data);
cmd_send_string(b, data->dst_session);
cmd_send_string(b, data->src_session);
}
void
cmd_copy_buffer_recv(struct cmd *self, struct buffer *b)
{
struct cmd_copy_buffer_data *data;
self->data = data = xmalloc(sizeof *data);
buffer_read(b, data, sizeof *data);
data->dst_session = cmd_recv_string(b);
data->src_session = cmd_recv_string(b);
}
void
cmd_copy_buffer_free(struct cmd *self)
{

View File

@ -33,8 +33,6 @@ const struct cmd_entry cmd_copy_mode_entry = {
cmd_target_init,
cmd_target_parse,
cmd_copy_mode_exec,
cmd_target_send,
cmd_target_recv,
cmd_target_free,
NULL
};

View File

@ -35,8 +35,6 @@ const struct cmd_entry cmd_delete_buffer_entry = {
cmd_buffer_init,
cmd_buffer_parse,
cmd_delete_buffer_exec,
cmd_buffer_send,
cmd_buffer_recv,
cmd_buffer_free,
cmd_buffer_print
};

View File

@ -33,8 +33,6 @@ const struct cmd_entry cmd_detach_client_entry = {
cmd_target_init,
cmd_target_parse,
cmd_detach_client_exec,
cmd_target_send,
cmd_target_recv,
cmd_target_free,
cmd_target_print
};

View File

@ -35,8 +35,6 @@ const struct cmd_entry cmd_display_message_entry = {
cmd_target_init,
cmd_target_parse,
cmd_display_message_exec,
cmd_target_send,
cmd_target_recv,
cmd_target_free,
cmd_target_print
};

View File

@ -33,8 +33,6 @@ const struct cmd_entry cmd_down_pane_entry = {
cmd_target_init,
cmd_target_parse,
cmd_down_pane_exec,
cmd_target_send,
cmd_target_recv,
cmd_target_free,
cmd_target_print
};

View File

@ -38,8 +38,6 @@ const struct cmd_entry cmd_find_window_entry = {
cmd_target_init,
cmd_target_parse,
cmd_find_window_exec,
cmd_target_send,
cmd_target_recv,
cmd_target_free,
cmd_target_print
};

View File

@ -176,27 +176,6 @@ usage:
return (-1);
}
void
cmd_target_send(struct cmd *self, struct buffer *b)
{
struct cmd_target_data *data = self->data;
buffer_write(b, data, sizeof *data);
cmd_send_string(b, data->target);
cmd_send_string(b, data->arg);
}
void
cmd_target_recv(struct cmd *self, struct buffer *b)
{
struct cmd_target_data *data;
self->data = data = xmalloc(sizeof *data);
buffer_read(b, data, sizeof *data);
data->target = cmd_recv_string(b);
data->arg = cmd_recv_string(b);
}
void
cmd_target_free(struct cmd *self)
{
@ -278,29 +257,6 @@ usage:
return (-1);
}
void
cmd_srcdst_send(struct cmd *self, struct buffer *b)
{
struct cmd_srcdst_data *data = self->data;
buffer_write(b, data, sizeof *data);
cmd_send_string(b, data->src);
cmd_send_string(b, data->dst);
cmd_send_string(b, data->arg);
}
void
cmd_srcdst_recv(struct cmd *self, struct buffer *b)
{
struct cmd_srcdst_data *data;
self->data = data = xmalloc(sizeof *data);
buffer_read(b, data, sizeof *data);
data->src = cmd_recv_string(b);
data->dst = cmd_recv_string(b);
data->arg = cmd_recv_string(b);
}
void
cmd_srcdst_free(struct cmd *self)
{
@ -394,27 +350,6 @@ error:
return (-1);
}
void
cmd_buffer_send(struct cmd *self, struct buffer *b)
{
struct cmd_buffer_data *data = self->data;
buffer_write(b, data, sizeof *data);
cmd_send_string(b, data->target);
cmd_send_string(b, data->arg);
}
void
cmd_buffer_recv(struct cmd *self, struct buffer *b)
{
struct cmd_buffer_data *data;
self->data = data = xmalloc(sizeof *data);
buffer_read(b, data, sizeof *data);
data->target = cmd_recv_string(b);
data->arg = cmd_recv_string(b);
}
void
cmd_buffer_free(struct cmd *self)
{
@ -500,29 +435,6 @@ usage:
return (-1);
}
void
cmd_option_send(struct cmd *self, struct buffer *b)
{
struct cmd_option_data *data = self->data;
buffer_write(b, data, sizeof *data);
cmd_send_string(b, data->target);
cmd_send_string(b, data->option);
cmd_send_string(b, data->value);
}
void
cmd_option_recv(struct cmd *self, struct buffer *b)
{
struct cmd_option_data *data;
self->data = data = xmalloc(sizeof *data);
buffer_read(b, data, sizeof *data);
data->target = cmd_recv_string(b);
data->option = cmd_recv_string(b);
data->value = cmd_recv_string(b);
}
void
cmd_option_free(struct cmd *self)
{
@ -617,27 +529,6 @@ error:
return (-1);
}
void
cmd_pane_send(struct cmd *self, struct buffer *b)
{
struct cmd_pane_data *data = self->data;
buffer_write(b, data, sizeof *data);
cmd_send_string(b, data->target);
cmd_send_string(b, data->arg);
}
void
cmd_pane_recv(struct cmd *self, struct buffer *b)
{
struct cmd_pane_data *data;
self->data = data = xmalloc(sizeof *data);
buffer_read(b, data, sizeof *data);
data->target = cmd_recv_string(b);
data->arg = cmd_recv_string(b);
}
void
cmd_pane_free(struct cmd *self)
{

View File

@ -33,8 +33,6 @@ const struct cmd_entry cmd_has_session_entry = {
cmd_target_init,
cmd_target_parse,
cmd_has_session_exec,
cmd_target_send,
cmd_target_recv,
cmd_target_free,
cmd_target_print
};

View File

@ -30,8 +30,6 @@
int cmd_if_shell_parse(struct cmd *, int, char **, char **);
int cmd_if_shell_exec(struct cmd *, struct cmd_ctx *);
void cmd_if_shell_send(struct cmd *, struct buffer *);
void cmd_if_shell_recv(struct cmd *, struct buffer *);
void cmd_if_shell_free(struct cmd *);
void cmd_if_shell_init(struct cmd *, int);
size_t cmd_if_shell_print(struct cmd *, char *, size_t);
@ -48,8 +46,6 @@ const struct cmd_entry cmd_if_shell_entry = {
cmd_if_shell_init,
cmd_if_shell_parse,
cmd_if_shell_exec,
cmd_if_shell_send,
cmd_if_shell_recv,
cmd_if_shell_free,
cmd_if_shell_print
};
@ -126,27 +122,6 @@ cmd_if_shell_exec(struct cmd *self, struct cmd_ctx *ctx)
return (0);
}
void
cmd_if_shell_send(struct cmd *self, struct buffer *b)
{
struct cmd_if_shell_data *data = self->data;
buffer_write(b, data, sizeof *data);
cmd_send_string(b, data->cmd);
cmd_send_string(b, data->sh_cmd);
}
void
cmd_if_shell_recv(struct cmd *self, struct buffer *b)
{
struct cmd_if_shell_data *data;
self->data = data = xmalloc(sizeof *data);
buffer_read(b, data, sizeof *data);
data->cmd = cmd_recv_string(b);
data->sh_cmd = cmd_recv_string(b);
}
void
cmd_if_shell_free(struct cmd *self)
{

View File

@ -35,8 +35,6 @@ const struct cmd_entry cmd_kill_pane_entry = {
cmd_pane_init,
cmd_pane_parse,
cmd_kill_pane_exec,
cmd_pane_send,
cmd_pane_recv,
cmd_pane_free,
cmd_pane_print
};

View File

@ -37,8 +37,6 @@ const struct cmd_entry cmd_kill_server_entry = {
NULL,
cmd_kill_server_exec,
NULL,
NULL,
NULL,
NULL
};

View File

@ -36,8 +36,6 @@ const struct cmd_entry cmd_kill_session_entry = {
cmd_target_init,
cmd_target_parse,
cmd_kill_session_exec,
cmd_target_send,
cmd_target_recv,
cmd_target_free,
cmd_target_print
};

View File

@ -33,8 +33,6 @@ const struct cmd_entry cmd_kill_window_entry = {
cmd_target_init,
cmd_target_parse,
cmd_kill_window_exec,
cmd_target_send,
cmd_target_recv,
cmd_target_free,
cmd_target_print
};

View File

@ -33,8 +33,6 @@ const struct cmd_entry cmd_last_window_entry = {
cmd_target_init,
cmd_target_parse,
cmd_last_window_exec,
cmd_target_send,
cmd_target_recv,
cmd_target_free,
cmd_target_print
};

View File

@ -35,8 +35,6 @@ const struct cmd_entry cmd_link_window_entry = {
cmd_srcdst_init,
cmd_srcdst_parse,
cmd_link_window_exec,
cmd_srcdst_send,
cmd_srcdst_recv,
cmd_srcdst_free,
cmd_srcdst_print
};

View File

@ -35,8 +35,6 @@ const struct cmd_entry cmd_list_buffers_entry = {
cmd_target_init,
cmd_target_parse,
cmd_list_buffers_exec,
cmd_target_send,
cmd_target_recv,
cmd_target_free,
cmd_target_print
};

View File

@ -37,8 +37,6 @@ const struct cmd_entry cmd_list_clients_entry = {
NULL,
cmd_list_clients_exec,
NULL,
NULL,
NULL,
NULL
};

View File

@ -34,8 +34,6 @@ const struct cmd_entry cmd_list_commands_entry = {
NULL,
cmd_list_commands_exec,
NULL,
NULL,
NULL,
NULL
};

View File

@ -36,8 +36,6 @@ const struct cmd_entry cmd_list_keys_entry = {
NULL,
cmd_list_keys_exec,
NULL,
NULL,
NULL,
NULL
};

View File

@ -36,8 +36,6 @@ const struct cmd_entry cmd_list_sessions_entry = {
NULL,
cmd_list_sessions_exec,
NULL,
NULL,
NULL,
NULL
};

View File

@ -35,8 +35,6 @@ const struct cmd_entry cmd_list_windows_entry = {
cmd_target_init,
cmd_target_parse,
cmd_list_windows_exec,
cmd_target_send,
cmd_target_recv,
cmd_target_free,
cmd_target_print
};

View File

@ -86,41 +86,6 @@ cmd_list_exec(struct cmd_list *cmdlist, struct cmd_ctx *ctx)
return (0);
}
void
cmd_list_send(struct cmd_list *cmdlist, struct buffer *b)
{
struct cmd *cmd;
u_int n;
n = 0;
TAILQ_FOREACH(cmd, cmdlist, qentry)
n++;
buffer_write(b, &n, sizeof n);
TAILQ_FOREACH(cmd, cmdlist, qentry)
cmd_send(cmd, b);
}
struct cmd_list *
cmd_list_recv(struct buffer *b)
{
struct cmd_list *cmdlist;
struct cmd *cmd;
u_int n;
buffer_read(b, &n, sizeof n);
cmdlist = xmalloc(sizeof *cmdlist);
TAILQ_INIT(cmdlist);
while (n-- > 0) {
cmd = cmd_recv(b);
TAILQ_INSERT_TAIL(cmdlist, cmd, qentry);
}
return (cmdlist);
}
void
cmd_list_free(struct cmd_list *cmdlist)
{

View File

@ -39,8 +39,6 @@ const struct cmd_entry cmd_load_buffer_entry = {
cmd_buffer_init,
cmd_buffer_parse,
cmd_load_buffer_exec,
cmd_buffer_send,
cmd_buffer_recv,
cmd_buffer_free,
cmd_buffer_print
};

View File

@ -39,8 +39,6 @@ const struct cmd_entry cmd_lock_server_entry = {
cmd_lock_server_exec,
NULL,
NULL,
NULL,
NULL,
};
int

View File

@ -35,8 +35,6 @@ const struct cmd_entry cmd_move_window_entry = {
cmd_srcdst_init,
cmd_srcdst_parse,
cmd_move_window_exec,
cmd_srcdst_send,
cmd_srcdst_recv,
cmd_srcdst_free,
cmd_srcdst_print
};

View File

@ -26,8 +26,6 @@
int cmd_new_session_parse(struct cmd *, int, char **, char **);
int cmd_new_session_exec(struct cmd *, struct cmd_ctx *);
void cmd_new_session_send(struct cmd *, struct buffer *);
void cmd_new_session_recv(struct cmd *, struct buffer *);
void cmd_new_session_free(struct cmd *);
void cmd_new_session_init(struct cmd *, int);
size_t cmd_new_session_print(struct cmd *, char *, size_t);
@ -46,8 +44,6 @@ const struct cmd_entry cmd_new_session_entry = {
cmd_new_session_init,
cmd_new_session_parse,
cmd_new_session_exec,
cmd_new_session_send,
cmd_new_session_recv,
cmd_new_session_free,
cmd_new_session_print
};
@ -228,29 +224,6 @@ cmd_new_session_exec(struct cmd *self, struct cmd_ctx *ctx)
return (1); /* 1 means don't tell command client to exit */
}
void
cmd_new_session_send(struct cmd *self, struct buffer *b)
{
struct cmd_new_session_data *data = self->data;
buffer_write(b, data, sizeof *data);
cmd_send_string(b, data->newname);
cmd_send_string(b, data->winname);
cmd_send_string(b, data->cmd);
}
void
cmd_new_session_recv(struct cmd *self, struct buffer *b)
{
struct cmd_new_session_data *data;
self->data = data = xmalloc(sizeof *data);
buffer_read(b, data, sizeof *data);
data->newname = cmd_recv_string(b);
data->winname = cmd_recv_string(b);
data->cmd = cmd_recv_string(b);
}
void
cmd_new_session_free(struct cmd *self)
{

View File

@ -28,8 +28,6 @@
int cmd_new_window_parse(struct cmd *, int, char **, char **);
int cmd_new_window_exec(struct cmd *, struct cmd_ctx *);
void cmd_new_window_send(struct cmd *, struct buffer *);
void cmd_new_window_recv(struct cmd *, struct buffer *);
void cmd_new_window_free(struct cmd *);
void cmd_new_window_init(struct cmd *, int);
size_t cmd_new_window_print(struct cmd *, char *, size_t);
@ -49,8 +47,6 @@ const struct cmd_entry cmd_new_window_entry = {
cmd_new_window_init,
cmd_new_window_parse,
cmd_new_window_exec,
cmd_new_window_send,
cmd_new_window_recv,
cmd_new_window_free,
cmd_new_window_print
};
@ -173,29 +169,6 @@ cmd_new_window_exec(struct cmd *self, struct cmd_ctx *ctx)
return (0);
}
void
cmd_new_window_send(struct cmd *self, struct buffer *b)
{
struct cmd_new_window_data *data = self->data;
buffer_write(b, data, sizeof *data);
cmd_send_string(b, data->target);
cmd_send_string(b, data->name);
cmd_send_string(b, data->cmd);
}
void
cmd_new_window_recv(struct cmd *self, struct buffer *b)
{
struct cmd_new_window_data *data;
self->data = data = xmalloc(sizeof *data);
buffer_read(b, data, sizeof *data);
data->target = cmd_recv_string(b);
data->name = cmd_recv_string(b);
data->cmd = cmd_recv_string(b);
}
void
cmd_new_window_free(struct cmd *self)
{

View File

@ -33,8 +33,6 @@ const struct cmd_entry cmd_next_layout_entry = {
cmd_target_init,
cmd_target_parse,
cmd_next_layout_exec,
cmd_target_send,
cmd_target_recv,
cmd_target_free,
cmd_target_print
};

View File

@ -34,8 +34,6 @@ const struct cmd_entry cmd_next_window_entry = {
cmd_next_window_init,
cmd_target_parse,
cmd_next_window_exec,
cmd_target_send,
cmd_target_recv,
cmd_target_free,
cmd_target_print
};

View File

@ -36,8 +36,6 @@ const struct cmd_entry cmd_paste_buffer_entry = {
cmd_buffer_init,
cmd_buffer_parse,
cmd_paste_buffer_exec,
cmd_buffer_send,
cmd_buffer_recv,
cmd_buffer_free,
cmd_buffer_print
};

View File

@ -33,8 +33,6 @@ const struct cmd_entry cmd_previous_layout_entry = {
cmd_target_init,
cmd_target_parse,
cmd_previous_layout_exec,
cmd_target_send,
cmd_target_recv,
cmd_target_free,
cmd_target_print
};

View File

@ -34,8 +34,6 @@ const struct cmd_entry cmd_previous_window_entry = {
cmd_previous_window_init,
cmd_target_parse,
cmd_previous_window_exec,
cmd_target_send,
cmd_target_recv,
cmd_target_free,
cmd_target_print
};

View File

@ -33,8 +33,6 @@ const struct cmd_entry cmd_refresh_client_entry = {
cmd_target_init,
cmd_target_parse,
cmd_refresh_client_exec,
cmd_target_send,
cmd_target_recv,
cmd_target_free,
cmd_target_print
};

View File

@ -35,8 +35,6 @@ const struct cmd_entry cmd_rename_session_entry = {
cmd_target_init,
cmd_target_parse,
cmd_rename_session_exec,
cmd_target_send,
cmd_target_recv,
cmd_target_free,
cmd_target_print
};

View File

@ -35,8 +35,6 @@ const struct cmd_entry cmd_rename_window_entry = {
cmd_target_init,
cmd_target_parse,
cmd_rename_window_exec,
cmd_target_send,
cmd_target_recv,
cmd_target_free,
cmd_target_print
};

View File

@ -37,8 +37,6 @@ const struct cmd_entry cmd_resize_pane_entry = {
cmd_resize_pane_init,
cmd_pane_parse,
cmd_resize_pane_exec,
cmd_pane_send,
cmd_pane_recv,
cmd_pane_free,
cmd_pane_print
};

View File

@ -35,8 +35,6 @@ const struct cmd_entry cmd_respawn_window_entry = {
cmd_target_init,
cmd_target_parse,
cmd_respawn_window_exec,
cmd_target_send,
cmd_target_recv,
cmd_target_free,
cmd_target_print
};

View File

@ -34,8 +34,6 @@ const struct cmd_entry cmd_rotate_window_entry = {
cmd_rotate_window_init,
cmd_target_parse,
cmd_rotate_window_exec,
cmd_target_send,
cmd_target_recv,
cmd_target_free,
cmd_target_print
};

View File

@ -37,8 +37,6 @@ const struct cmd_entry cmd_save_buffer_entry = {
cmd_buffer_init,
cmd_buffer_parse,
cmd_save_buffer_exec,
cmd_buffer_send,
cmd_buffer_recv,
cmd_buffer_free,
cmd_buffer_print
};

View File

@ -34,8 +34,6 @@ const struct cmd_entry cmd_scroll_mode_entry = {
cmd_scroll_mode_init,
cmd_target_parse,
cmd_scroll_mode_exec,
cmd_target_send,
cmd_target_recv,
cmd_target_free,
cmd_target_print
};

View File

@ -34,8 +34,6 @@ const struct cmd_entry cmd_select_layout_entry = {
cmd_select_layout_init,
cmd_target_parse,
cmd_select_layout_exec,
cmd_target_send,
cmd_target_recv,
cmd_target_free,
cmd_target_print
};

View File

@ -33,8 +33,6 @@ const struct cmd_entry cmd_select_pane_entry = {
cmd_pane_init,
cmd_pane_parse,
cmd_select_pane_exec,
cmd_pane_send,
cmd_pane_recv,
cmd_pane_free,
cmd_pane_print
};

View File

@ -37,8 +37,6 @@ const struct cmd_entry cmd_select_prompt_entry = {
cmd_target_init,
cmd_target_parse,
cmd_select_prompt_exec,
cmd_target_send,
cmd_target_recv,
cmd_target_free,
cmd_target_print
};

View File

@ -36,8 +36,6 @@ const struct cmd_entry cmd_select_window_entry = {
cmd_select_window_init,
cmd_target_parse,
cmd_select_window_exec,
cmd_target_send,
cmd_target_recv,
cmd_target_free,
cmd_target_print
};

View File

@ -28,8 +28,6 @@
int cmd_send_keys_parse(struct cmd *, int, char **, char **);
int cmd_send_keys_exec(struct cmd *, struct cmd_ctx *);
void cmd_send_keys_send(struct cmd *, struct buffer *);
void cmd_send_keys_recv(struct cmd *, struct buffer *);
void cmd_send_keys_free(struct cmd *);
size_t cmd_send_keys_print(struct cmd *, char *, size_t);
@ -47,8 +45,6 @@ const struct cmd_entry cmd_send_keys_entry = {
NULL,
cmd_send_keys_parse,
cmd_send_keys_exec,
cmd_send_keys_send,
cmd_send_keys_recv,
cmd_send_keys_free,
cmd_send_keys_print
};
@ -127,28 +123,6 @@ cmd_send_keys_exec(struct cmd *self, struct cmd_ctx *ctx)
return (0);
}
void
cmd_send_keys_send(struct cmd *self, struct buffer *b)
{
struct cmd_send_keys_data *data = self->data;
buffer_write(b, data, sizeof *data);
cmd_send_string(b, data->target);
buffer_write(b, data->keys, data->nkeys * sizeof *data->keys);
}
void
cmd_send_keys_recv(struct cmd *self, struct buffer *b)
{
struct cmd_send_keys_data *data;
self->data = data = xmalloc(sizeof *data);
buffer_read(b, data, sizeof *data);
data->target = cmd_recv_string(b);
data->keys = xcalloc(data->nkeys, sizeof *data->keys);
buffer_read(b, data->keys, data->nkeys * sizeof *data->keys);
}
void
cmd_send_keys_free(struct cmd *self)
{

View File

@ -33,8 +33,6 @@ const struct cmd_entry cmd_send_prefix_entry = {
cmd_target_init,
cmd_target_parse,
cmd_send_prefix_exec,
cmd_target_send,
cmd_target_recv,
cmd_target_free,
cmd_target_print
};

View File

@ -41,8 +41,6 @@ const struct cmd_entry cmd_server_info_entry = {
NULL,
cmd_server_info_exec,
NULL,
NULL,
NULL,
NULL
};

View File

@ -35,8 +35,6 @@ const struct cmd_entry cmd_set_buffer_entry = {
cmd_buffer_init,
cmd_buffer_parse,
cmd_set_buffer_exec,
cmd_buffer_send,
cmd_buffer_recv,
cmd_buffer_free,
cmd_buffer_print
};

View File

@ -36,8 +36,6 @@ const struct cmd_entry cmd_set_option_entry = {
NULL,
cmd_option_parse,
cmd_set_option_exec,
cmd_option_send,
cmd_option_recv,
cmd_option_free,
cmd_option_print
};

View File

@ -29,8 +29,6 @@
int cmd_set_password_parse(struct cmd *, int, char **, char **);
int cmd_set_password_exec(struct cmd *, struct cmd_ctx *);
void cmd_set_password_send(struct cmd *, struct buffer *);
void cmd_set_password_recv(struct cmd *, struct buffer *);
void cmd_set_password_free(struct cmd *);
void cmd_set_password_init(struct cmd *, int);
size_t cmd_set_password_print(struct cmd *, char *, size_t);
@ -47,8 +45,6 @@ const struct cmd_entry cmd_set_password_entry = {
cmd_set_password_init,
cmd_set_password_parse,
cmd_set_password_exec,
cmd_set_password_send,
cmd_set_password_recv,
cmd_set_password_free,
cmd_set_password_print
};
@ -122,25 +118,6 @@ cmd_set_password_exec(struct cmd *self, struct cmd_ctx *ctx)
return (0);
}
void
cmd_set_password_send(struct cmd *self, struct buffer *b)
{
struct cmd_set_password_data *data = self->data;
buffer_write(b, data, sizeof *data);
cmd_send_string(b, data->password);
}
void
cmd_set_password_recv(struct cmd *self, struct buffer *b)
{
struct cmd_set_password_data *data;
self->data = data = xmalloc(sizeof *data);
buffer_read(b, data, sizeof *data);
data->password = cmd_recv_string(b);
}
void
cmd_set_password_free(struct cmd *self)
{

View File

@ -36,8 +36,6 @@ const struct cmd_entry cmd_set_window_option_entry = {
NULL,
cmd_option_parse,
cmd_set_window_option_exec,
cmd_option_send,
cmd_option_recv,
cmd_option_free,
cmd_option_print
};

View File

@ -35,8 +35,6 @@ const struct cmd_entry cmd_show_buffer_entry = {
cmd_buffer_init,
cmd_buffer_parse,
cmd_show_buffer_exec,
cmd_buffer_send,
cmd_buffer_recv,
cmd_buffer_free,
cmd_buffer_print
};

View File

@ -36,8 +36,6 @@ const struct cmd_entry cmd_show_options_entry = {
cmd_target_init,
cmd_target_parse,
cmd_show_options_exec,
cmd_target_send,
cmd_target_recv,
cmd_target_free,
cmd_target_print
};

View File

@ -36,8 +36,6 @@ const struct cmd_entry cmd_show_window_options_entry = {
cmd_target_init,
cmd_target_parse,
cmd_show_window_options_exec,
cmd_target_send,
cmd_target_recv,
cmd_target_free,
cmd_target_print
};

View File

@ -26,8 +26,6 @@
int cmd_source_file_parse(struct cmd *, int, char **, char **);
int cmd_source_file_exec(struct cmd *, struct cmd_ctx *);
void cmd_source_file_send(struct cmd *, struct buffer *);
void cmd_source_file_recv(struct cmd *, struct buffer *);
void cmd_source_file_free(struct cmd *);
void cmd_source_file_init(struct cmd *, int);
size_t cmd_source_file_print(struct cmd *, char *, size_t);
@ -43,8 +41,6 @@ const struct cmd_entry cmd_source_file_entry = {
cmd_source_file_init,
cmd_source_file_parse,
cmd_source_file_exec,
cmd_source_file_send,
cmd_source_file_recv,
cmd_source_file_free,
cmd_source_file_print
};
@ -103,25 +99,6 @@ cmd_source_file_exec(struct cmd *self, struct cmd_ctx *ctx)
return (0);
}
void
cmd_source_file_send(struct cmd *self, struct buffer *b)
{
struct cmd_source_file_data *data = self->data;
buffer_write(b, data, sizeof *data);
cmd_send_string(b, data->path);
}
void
cmd_source_file_recv(struct cmd *self, struct buffer *b)
{
struct cmd_source_file_data *data;
self->data = data = xmalloc(sizeof *data);
buffer_read(b, data, sizeof *data);
data->path = cmd_recv_string(b);
}
void
cmd_source_file_free(struct cmd *self)
{

View File

@ -29,8 +29,6 @@
int cmd_split_window_parse(struct cmd *, int, char **, char **);
int cmd_split_window_exec(struct cmd *, struct cmd_ctx *);
void cmd_split_window_send(struct cmd *, struct buffer *);
void cmd_split_window_recv(struct cmd *, struct buffer *);
void cmd_split_window_free(struct cmd *);
void cmd_split_window_init(struct cmd *, int);
size_t cmd_split_window_print(struct cmd *, char *, size_t);
@ -51,8 +49,6 @@ const struct cmd_entry cmd_split_window_entry = {
cmd_split_window_init,
cmd_split_window_parse,
cmd_split_window_exec,
cmd_split_window_send,
cmd_split_window_recv,
cmd_split_window_free,
cmd_split_window_print
};
@ -211,27 +207,6 @@ error:
return (-1);
}
void
cmd_split_window_send(struct cmd *self, struct buffer *b)
{
struct cmd_split_window_data *data = self->data;
buffer_write(b, data, sizeof *data);
cmd_send_string(b, data->target);
cmd_send_string(b, data->cmd);
}
void
cmd_split_window_recv(struct cmd *self, struct buffer *b)
{
struct cmd_split_window_data *data;
self->data = data = xmalloc(sizeof *data);
buffer_read(b, data, sizeof *data);
data->target = cmd_recv_string(b);
data->cmd = cmd_recv_string(b);
}
void
cmd_split_window_free(struct cmd *self)
{

View File

@ -34,8 +34,6 @@ const struct cmd_entry cmd_start_server_entry = {
NULL,
cmd_start_server_exec,
NULL,
NULL,
NULL,
NULL
};

View File

@ -41,8 +41,6 @@ const struct cmd_entry cmd_suspend_client_entry = {
cmd_target_init,
cmd_target_parse,
cmd_suspend_client_exec,
cmd_target_send,
cmd_target_recv,
cmd_target_free,
cmd_target_print
};

View File

@ -28,8 +28,6 @@
int cmd_swap_pane_parse(struct cmd *, int, char **, char **);
int cmd_swap_pane_exec(struct cmd *, struct cmd_ctx *);
void cmd_swap_pane_send(struct cmd *, struct buffer *);
void cmd_swap_pane_recv(struct cmd *, struct buffer *);
void cmd_swap_pane_free(struct cmd *);
void cmd_swap_pane_init(struct cmd *, int);
size_t cmd_swap_pane_print(struct cmd *, char *, size_t);
@ -50,8 +48,6 @@ const struct cmd_entry cmd_swap_pane_entry = {
cmd_swap_pane_init,
cmd_swap_pane_parse,
cmd_swap_pane_exec,
cmd_swap_pane_send,
cmd_swap_pane_recv,
cmd_swap_pane_free,
cmd_swap_pane_print
};
@ -234,25 +230,6 @@ cmd_swap_pane_exec(struct cmd *self, struct cmd_ctx *ctx)
return (0);
}
void
cmd_swap_pane_send(struct cmd *self, struct buffer *b)
{
struct cmd_swap_pane_data *data = self->data;
buffer_write(b, data, sizeof *data);
cmd_send_string(b, data->target);
}
void
cmd_swap_pane_recv(struct cmd *self, struct buffer *b)
{
struct cmd_swap_pane_data *data;
self->data = data = xmalloc(sizeof *data);
buffer_read(b, data, sizeof *data);
data->target = cmd_recv_string(b);
}
void
cmd_swap_pane_free(struct cmd *self)
{

View File

@ -35,8 +35,6 @@ const struct cmd_entry cmd_swap_window_entry = {
cmd_srcdst_init,
cmd_srcdst_parse,
cmd_swap_window_exec,
cmd_srcdst_send,
cmd_srcdst_recv,
cmd_srcdst_free,
cmd_srcdst_print
};

View File

@ -29,8 +29,6 @@
int cmd_switch_client_parse(struct cmd *, int, char **, char **);
int cmd_switch_client_exec(struct cmd *, struct cmd_ctx *);
void cmd_switch_client_send(struct cmd *, struct buffer *);
void cmd_switch_client_recv(struct cmd *, struct buffer *);
void cmd_switch_client_free(struct cmd *);
size_t cmd_switch_client_print(struct cmd *, char *, size_t);
@ -46,8 +44,6 @@ const struct cmd_entry cmd_switch_client_entry = {
NULL,
cmd_switch_client_parse,
cmd_switch_client_exec,
cmd_switch_client_send,
cmd_switch_client_recv,
cmd_switch_client_free,
cmd_switch_client_print
};
@ -111,27 +107,6 @@ cmd_switch_client_exec(struct cmd *self, struct cmd_ctx *ctx)
return (0);
}
void
cmd_switch_client_send(struct cmd *self, struct buffer *b)
{
struct cmd_switch_client_data *data = self->data;
buffer_write(b, data, sizeof *data);
cmd_send_string(b, data->name);
cmd_send_string(b, data->target);
}
void
cmd_switch_client_recv(struct cmd *self, struct buffer *b)
{
struct cmd_switch_client_data *data;
self->data = data = xmalloc(sizeof *data);
buffer_read(b, data, sizeof *data);
data->name = cmd_recv_string(b);
data->target = cmd_recv_string(b);
}
void
cmd_switch_client_free(struct cmd *self)
{

View File

@ -26,8 +26,6 @@
int cmd_unbind_key_parse(struct cmd *, int, char **, char **);
int cmd_unbind_key_exec(struct cmd *, struct cmd_ctx *);
void cmd_unbind_key_send(struct cmd *, struct buffer *);
void cmd_unbind_key_recv(struct cmd *, struct buffer *);
void cmd_unbind_key_free(struct cmd *);
struct cmd_unbind_key_data {
@ -41,8 +39,6 @@ const struct cmd_entry cmd_unbind_key_entry = {
NULL,
cmd_unbind_key_parse,
cmd_unbind_key_exec,
cmd_unbind_key_send,
cmd_unbind_key_recv,
cmd_unbind_key_free,
NULL
};
@ -99,23 +95,6 @@ cmd_unbind_key_exec(struct cmd *self, unused struct cmd_ctx *ctx)
return (0);
}
void
cmd_unbind_key_send(struct cmd *self, struct buffer *b)
{
struct cmd_unbind_key_data *data = self->data;
buffer_write(b, data, sizeof *data);
}
void
cmd_unbind_key_recv(struct cmd *self, struct buffer *b)
{
struct cmd_unbind_key_data *data;
self->data = data = xmalloc(sizeof *data);
buffer_read(b, data, sizeof *data);
}
void
cmd_unbind_key_free(struct cmd *self)
{

View File

@ -33,8 +33,6 @@ const struct cmd_entry cmd_unlink_window_entry = {
cmd_target_init,
cmd_target_parse,
cmd_unlink_window_exec,
cmd_target_send,
cmd_target_recv,
cmd_target_free,
cmd_target_print
};

View File

@ -33,8 +33,6 @@ const struct cmd_entry cmd_up_pane_entry = {
cmd_target_init,
cmd_target_parse,
cmd_up_pane_exec,
cmd_target_send,
cmd_target_recv,
cmd_target_free,
cmd_target_print
};

140
cmd.c
View File

@ -109,6 +109,64 @@ struct session *cmd_lookup_session(const char *, int *);
struct winlink *cmd_lookup_window(struct session *, const char *, int *);
int cmd_lookup_index(struct session *, const char *, int *);
int
cmd_pack_argv(int argc, char **argv, char *buf, size_t len)
{
size_t arglen;
int i;
*buf = '\0';
for (i = 0; i < argc; i++) {
if (strlcpy(buf, argv[i], len) >= len)
return (-1);
arglen = strlen(argv[i]) + 1;
buf += arglen;
len -= arglen;
}
return (0);
}
int
cmd_unpack_argv(char *buf, size_t len, int argc, char ***argv)
{
int i;
size_t arglen;
if (argc == 0)
return (0);
*argv = xcalloc(argc, sizeof **argv);
buf[len - 1] = '\0';
for (i = 0; i < argc; i++) {
if (len == 0) {
cmd_free_argv(argc, *argv);
return (-1);
}
arglen = strlen(buf) + 1;
(*argv)[i] = xstrdup(buf);
buf += arglen;
len -= arglen;
}
return (0);
}
void
cmd_free_argv(int argc, char **argv)
{
int i;
if (argc == 0)
return;
for (i = 0; i < argc; i++) {
if (argv[i] != NULL)
xfree(argv[i]);
}
xfree(argv);
}
struct cmd *
cmd_parse(int argc, char **argv, char **cause)
{
@ -204,53 +262,6 @@ cmd_exec(struct cmd *cmd, struct cmd_ctx *ctx)
return (cmd->entry->exec(cmd, ctx));
}
void
cmd_send(struct cmd *cmd, struct buffer *b)
{
const struct cmd_entry **entryp;
u_int n;
n = 0;
for (entryp = cmd_table; *entryp != NULL; entryp++) {
if (*entryp == cmd->entry)
break;
n++;
}
if (*entryp == NULL)
fatalx("command not found");
buffer_write(b, &n, sizeof n);
if (cmd->entry->send != NULL)
cmd->entry->send(cmd, b);
}
struct cmd *
cmd_recv(struct buffer *b)
{
const struct cmd_entry **entryp;
struct cmd *cmd;
u_int m, n;
buffer_read(b, &m, sizeof m);
n = 0;
for (entryp = cmd_table; *entryp != NULL; entryp++) {
if (n == m)
break;
n++;
}
if (*entryp == NULL)
fatalx("command not found");
cmd = xmalloc(sizeof *cmd);
cmd->entry = *entryp;
if (cmd->entry->recv != NULL)
cmd->entry->recv(cmd, b);
return (cmd);
}
void
cmd_free(struct cmd *cmd)
{
@ -268,41 +279,6 @@ cmd_print(struct cmd *cmd, char *buf, size_t len)
return (cmd->entry->print(cmd, buf, len));
}
void
cmd_send_string(struct buffer *b, const char *s)
{
size_t n;
if (s == NULL) {
n = 0;
buffer_write(b, &n, sizeof n);
return;
}
n = strlen(s) + 1;
buffer_write(b, &n, sizeof n);
buffer_write(b, s, n);
}
char *
cmd_recv_string(struct buffer *b)
{
char *s;
size_t n;
buffer_read(b, &n, sizeof n);
if (n == 0)
return (NULL);
s = xmalloc(n);
buffer_read(b, s, n);
s[n - 1] = '\0';
return (s);
}
/*
* Figure out the current session. Use: 1) the current session, if the command
* context has one; 2) the session specified in the TMUX variable from the

View File

@ -47,6 +47,15 @@ server_fill_environ(struct session *s)
return (env);
}
void
server_write_error(struct client *c, const char *msg)
{
struct msg_print_data printdata;
strlcpy(printdata.msg, msg, sizeof printdata.msg);
server_write_client(c, MSG_ERROR, &printdata, sizeof printdata);
}
void
server_write_client(
struct client *c, enum hdrtype type, const void *buf, size_t len)
@ -220,7 +229,7 @@ wrong:
password_failures++;
for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
c = ARRAY_ITEM(&clients, i);
if (c == NULL || c->prompt_buffer == NULL)
if (c == NULL || c->prompt_buffer == NULL)
continue;
*c->prompt_buffer = '\0';

View File

@ -83,46 +83,43 @@ server_msg_dispatch(struct client *c)
void printflike2
server_msg_fn_command_error(struct cmd_ctx *ctx, const char *fmt, ...)
{
va_list ap;
char *msg;
struct msg_print_data data;
va_list ap;
va_start(ap, fmt);
xvasprintf(&msg, fmt, ap);
xvsnprintf(data.msg, sizeof data.msg, fmt, ap);
va_end(ap);
server_write_client(ctx->cmdclient, MSG_ERROR, msg, strlen(msg));
xfree(msg);
server_write_client(ctx->cmdclient, MSG_ERROR, &data, sizeof data);
}
void printflike2
server_msg_fn_command_print(struct cmd_ctx *ctx, const char *fmt, ...)
{
va_list ap;
char *msg;
struct msg_print_data data;
va_list ap;
va_start(ap, fmt);
xvasprintf(&msg, fmt, ap);
xvsnprintf(data.msg, sizeof data.msg, fmt, ap);
va_end(ap);
server_write_client(ctx->cmdclient, MSG_PRINT, msg, strlen(msg));
xfree(msg);
server_write_client(ctx->cmdclient, MSG_PRINT, &data, sizeof data);
}
void printflike2
server_msg_fn_command_info(struct cmd_ctx *ctx, const char *fmt, ...)
{
va_list ap;
char *msg;
struct msg_print_data data;
va_list ap;
if (be_quiet)
return;
va_start(ap, fmt);
xvasprintf(&msg, fmt, ap);
xvsnprintf(data.msg, sizeof data.msg, fmt, ap);
va_end(ap);
server_write_client(ctx->cmdclient, MSG_PRINT, msg, strlen(msg));
xfree(msg);
server_write_client(ctx->cmdclient, MSG_PRINT, &data, sizeof data);
}
void
@ -130,14 +127,15 @@ server_msg_fn_command(struct hdr *hdr, struct client *c)
{
struct msg_command_data data;
struct cmd_ctx ctx;
struct cmd_list *cmdlist;
struct cmd_list *cmdlist = NULL;
struct cmd *cmd;
int argc;
char **argv, *cause;
if (hdr->size < sizeof data)
fatalx("bad MSG_COMMAND size");
buffer_read(c->in, &data, sizeof data);
cmdlist = cmd_list_recv(c->in);
server_activity = time(NULL);
ctx.error = server_msg_fn_command_error;
@ -150,15 +148,33 @@ server_msg_fn_command(struct hdr *hdr, struct client *c)
ctx.cmdclient = c;
argc = data.argc;
data.argv[(sizeof data.argv) - 1] = '\0';
if (cmd_unpack_argv(data.argv, sizeof data.argv, argc, &argv) != 0) {
server_msg_fn_command_error(&ctx, "command too long");
goto error;
}
if (argc == 0) {
argc = 1;
argv = xcalloc(1, sizeof *argv);
*argv = xstrdup("new-session");
}
if ((cmdlist = cmd_list_parse(argc, argv, &cause)) == NULL) {
server_msg_fn_command_error(&ctx, "%s", cause);
cmd_free_argv(argc, argv);
goto error;
}
cmd_free_argv(argc, argv);
if (data.pid != -1) {
TAILQ_FOREACH(cmd, cmdlist, qentry) {
if (cmd->entry->flags & CMD_CANTNEST) {
server_msg_fn_command_error(&ctx,
"sessions should be nested with care. "
"unset $TMUX to force");
cmd_list_free(cmdlist);
server_write_client(c, MSG_EXIT, NULL, 0);
return;
goto error;
}
}
}
@ -166,27 +182,28 @@ server_msg_fn_command(struct hdr *hdr, struct client *c)
if (cmd_list_exec(cmdlist, &ctx) != 1)
server_write_client(c, MSG_EXIT, NULL, 0);
cmd_list_free(cmdlist);
return;
error:
if (cmdlist != NULL)
cmd_list_free(cmdlist);
server_write_client(c, MSG_EXIT, NULL, 0);
}
void
server_msg_fn_identify(struct hdr *hdr, struct client *c)
{
struct msg_identify_data data;
char *term;
if (hdr->size < sizeof data)
fatalx("bad MSG_IDENTIFY size");
buffer_read(c->in, &data, sizeof data);
term = cmd_recv_string(c->in);
log_debug("identify msg from client: %u,%u (%d)",
data.sx, data.sy, data.version);
if (data.version != PROTOCOL_VERSION) {
#define MSG "protocol version mismatch"
server_write_client(c, MSG_ERROR, MSG, (sizeof MSG) - 1);
#undef MSG
server_write_client(c, MSG_EXIT, NULL, 0);
server_write_error(c, "protocol version mismatch");
return;
}
@ -199,7 +216,8 @@ server_msg_fn_identify(struct hdr *hdr, struct client *c)
c->cwd = xstrdup(data.cwd);
data.tty[(sizeof data.tty) - 1] = '\0';
tty_init(&c->tty, data.tty, term);
data.term[(sizeof data.term) - 1] = '\0';
tty_init(&c->tty, data.tty, data.term);
if (data.flags & IDENTIFY_UTF8)
c->tty.flags |= TTY_UTF8;
if (data.flags & IDENTIFY_256COLOURS)
@ -209,9 +227,6 @@ server_msg_fn_identify(struct hdr *hdr, struct client *c)
if (data.flags & IDENTIFY_HASDEFAULTS)
c->tty.term_flags |= TERM_HASDEFAULTS;
if (term != NULL)
xfree(term);
c->flags |= CLIENT_TERMINAL;
}
@ -262,24 +277,20 @@ server_msg_fn_exiting(struct hdr *hdr, struct client *c)
void
server_msg_fn_unlock(struct hdr *hdr, struct client *c)
{
char *pass;
struct msg_unlock_data data;
if (hdr->size == 0)
if (hdr->size != sizeof data)
fatalx("bad MSG_UNLOCK size");
pass = cmd_recv_string(c->in);
buffer_read(c->in, &data, sizeof data);
log_debug("unlock msg from client");
if (server_unlock(pass) != 0) {
#define MSG "bad password"
server_write_client(c, MSG_ERROR, MSG, (sizeof MSG) - 1);
#undef MSG
}
data.pass[(sizeof data.pass) - 1] = '\0';
if (server_unlock(data.pass) != 0)
server_write_error(c, "bad password");
memset(&data, 0, sizeof data);
server_write_client(c, MSG_EXIT, NULL, 0);
memset(pass, 0, strlen(pass));
xfree(pass);
}
void

126
tmux.c
View File

@ -57,6 +57,8 @@ char *socket_path;
__dead void usage(void);
char *makesockpath(const char *);
int prepare_unlock(enum hdrtype *, void **, size_t *, int);
int prepare_cmd(enum hdrtype *, void **, size_t *, int, char **);
__dead void
usage(void)
@ -200,19 +202,70 @@ makesockpath(const char *label)
return (path);
}
int
prepare_unlock(enum hdrtype *msg, void **buf, size_t *len, int argc)
{
static struct msg_unlock_data unlockdata;
char *pass;
if (argc != 0) {
log_warnx("can't specify a command when unlocking");
return (-1);
}
if ((pass = getpass("Password: ")) == NULL)
return (-1);
if (strlen(pass) >= sizeof unlockdata.pass) {
log_warnx("password too long");
return (-1);
}
strlcpy(unlockdata.pass, pass, sizeof unlockdata.pass);
memset(pass, 0, strlen(pass));
*buf = &unlockdata;
*len = sizeof unlockdata;
*msg = MSG_UNLOCK;
return (0);
}
int
prepare_cmd(enum hdrtype *msg, void **buf, size_t *len, int argc, char **argv)
{
static struct msg_command_data cmddata;
client_fill_session(&cmddata);
cmddata.argc = argc;
if (cmd_pack_argv(argc, argv, cmddata.argv, sizeof cmddata.argv) != 0) {
log_warnx("command too long");
return (-1);
}
*buf = &cmddata;
*len = sizeof cmddata;
*msg = MSG_COMMAND;
return (0);
}
int
main(int argc, char **argv)
{
struct client_ctx cctx;
struct msg_command_data cmddata;
struct buffer *b;
struct cmd_list *cmdlist;
struct cmd *cmd;
struct pollfd pfd;
enum hdrtype msg;
struct hdr hdr;
struct passwd *pw;
char *s, *path, *label, *cause, *home, *pass = NULL;
struct msg_print_data printdata;
char *s, *path, *label, *home, *cause;
char cwd[MAXPATHLEN];
void *buf;
size_t len;
int retcode, opt, flags, unlock, cmdflags = 0;
unlock = flags = 0;
@ -364,7 +417,7 @@ main(int argc, char **argv)
exit(1);
}
}
if (label == NULL)
label = xstrdup("default");
if (path == NULL && (path = makesockpath(label)) == NULL) {
@ -383,36 +436,35 @@ main(int argc, char **argv)
options_set_string(&global_s_options, "default-path", "%s", cwd);
if (unlock) {
if (argc != 0) {
log_warnx("can't specify a command when unlocking");
if (prepare_unlock(&msg, &buf, &len, argc) != 0)
exit(1);
}
cmdlist = NULL;
if ((pass = getpass("Password: ")) == NULL)
exit(1);
cmdflags &= ~CMD_STARTSERVER;
} else {
if (argc == 0) {
cmd = xmalloc(sizeof *cmd);
cmd->entry = &cmd_new_session_entry;
cmd->entry->init(cmd, 0);
if (prepare_cmd(&msg, &buf, &len, argc, argv) != 0)
exit(1);
}
cmdlist = xmalloc(sizeof *cmdlist);
TAILQ_INIT(cmdlist);
TAILQ_INSERT_HEAD(cmdlist, cmd, qentry);
} else {
cmdlist = cmd_list_parse(argc, argv, &cause);
if (cmdlist == NULL) {
log_warnx("%s", cause);
exit(1);
}
if (unlock)
cmdflags &= ~CMD_STARTSERVER;
else if (argc == 0)
cmdflags |= CMD_STARTSERVER;
else {
/*
* It sucks parsing the command string twice (in client and
* later in server) but it is necessary to get the start server
* flag.
*/
if ((cmdlist = cmd_list_parse(argc, argv, &cause)) == NULL) {
log_warnx("%s", cause);
exit(1);
}
cmdflags &= ~CMD_STARTSERVER;
TAILQ_FOREACH(cmd, cmdlist, qentry) {
if (cmd->entry->flags & CMD_STARTSERVER) {
cmdflags |= CMD_STARTSERVER;
break;
}
}
cmd_list_free(cmdlist);
}
memset(&cctx, 0, sizeof cctx);
@ -420,20 +472,8 @@ main(int argc, char **argv)
exit(1);
xfree(path);
b = buffer_create(BUFSIZ);
if (unlock) {
cmd_send_string(b, pass);
memset(pass, 0, strlen(pass));
client_write_server(
&cctx, MSG_UNLOCK, BUFFER_OUT(b), BUFFER_USED(b));
} else {
cmd_list_send(cmdlist, b);
cmd_list_free(cmdlist);
client_fill_session(&cmddata);
client_write_server2(&cctx, MSG_COMMAND,
&cmddata, sizeof cmddata, BUFFER_OUT(b), BUFFER_USED(b));
}
buffer_destroy(b);
client_write_server(&cctx, msg, buf, len);
memset(buf, 0, len);
retcode = 0;
for (;;) {
@ -467,12 +507,12 @@ main(int argc, char **argv)
retcode = 1;
/* FALLTHROUGH */
case MSG_PRINT:
if (hdr.size > INT_MAX - 1)
if (hdr.size < sizeof printdata)
fatalx("bad MSG_PRINT size");
log_info("%.*s",
(int) hdr.size, BUFFER_OUT(cctx.srv_in));
if (hdr.size != 0)
buffer_remove(cctx.srv_in, hdr.size);
buffer_read(cctx.srv_in, &printdata, sizeof printdata);
printdata.msg[(sizeof printdata.msg) - 1] = '\0';
log_info("%s", printdata.msg);
goto restart;
case MSG_READY:
retcode = client_main(&cctx);

58
tmux.h
View File

@ -19,7 +19,7 @@
#ifndef TMUX_H
#define TMUX_H
#define PROTOCOL_VERSION -14
#define PROTOCOL_VERSION -15
#include <sys/param.h>
#include <sys/time.h>
@ -62,6 +62,14 @@ extern char *__progname;
/* Maximum poll timeout (when attached). */
#define POLL_TIMEOUT 50
/*
* 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 PRINT_LENGTH 512 /* printed error/message size */
/* Fatal errors. */
#define fatal(msg) log_fatal("%s: %s", __func__, msg);
#define fatalx(msg) log_fatalx("%s: %s", __func__, msg);
@ -293,17 +301,29 @@ enum hdrtype {
MSG_WAKEUP,
};
/* Message header structure. */
/*
* Message header and data.
*
* Don't forget to bump PROTOCOL_VERSION if any of these change!
*
* Changing sizeof (struct hdr) or sizeof (struct msg_identify_data) will make
* the tmux client hang even if the protocol version is bumped.
*/
struct hdr {
enum hdrtype type;
size_t size;
};
struct msg_print_data {
char msg[PRINT_LENGTH];
};
struct msg_command_data {
pid_t pid; /* pid from $TMUX or -1 */
u_int idx; /* index from $TMUX */
size_t namelen;
int argc;
char argv[COMMAND_LENGTH];
};
struct msg_identify_data {
@ -312,6 +332,8 @@ struct msg_identify_data {
char cwd[MAXPATHLEN];
char term[TERMINAL_LENGTH];
#define IDENTIFY_UTF8 0x1
#define IDENTIFY_256COLOURS 0x2
#define IDENTIFY_88COLOURS 0x4
@ -320,8 +342,6 @@ struct msg_identify_data {
u_int sx;
u_int sy;
size_t termlen;
};
struct msg_resize_data {
@ -329,6 +349,10 @@ struct msg_resize_data {
u_int sy;
};
struct msg_unlock_data {
char pass[PASS_MAX];
};
/* Editing keys. */
enum mode_key_cmd {
MODEKEYCMD_BACKSPACE = 0x1000,
@ -907,8 +931,6 @@ struct cmd_entry {
void (*init)(struct cmd *, int);
int (*parse)(struct cmd *, int, char **, char **);
int (*exec)(struct cmd *, struct cmd_ctx *);
void (*send)(struct cmd *, struct buffer *);
void (*recv)(struct cmd *, struct buffer *);
void (*free)(struct cmd *);
size_t (*print)(struct cmd *, char *, size_t);
};
@ -1113,14 +1135,13 @@ int paste_replace(struct paste_stack *, u_int, char *);
void clock_draw(struct screen_write_ctx *, u_int, int);
/* cmd.c */
int cmd_pack_argv(int, char **, char *, size_t);
int cmd_unpack_argv(char *, size_t, int, char ***);
void cmd_free_argv(int, char **);
struct cmd *cmd_parse(int, char **, char **);
int cmd_exec(struct cmd *, struct cmd_ctx *);
void cmd_send(struct cmd *, struct buffer *);
struct cmd *cmd_recv(struct buffer *);
void cmd_free(struct cmd *);
size_t cmd_print(struct cmd *, char *, size_t);
void cmd_send_string(struct buffer *, const char *);
char *cmd_recv_string(struct buffer *);
struct session *cmd_current_session(struct cmd_ctx *);
struct client *cmd_find_client(struct cmd_ctx *, const char *);
struct session *cmd_find_session(struct cmd_ctx *, const char *);
@ -1205,8 +1226,6 @@ extern const struct cmd_entry cmd_up_pane_entry;
/* cmd-list.c */
struct cmd_list *cmd_list_parse(int, char **, char **);
int cmd_list_exec(struct cmd_list *, struct cmd_ctx *);
void cmd_list_send(struct cmd_list *, struct buffer *);
struct cmd_list *cmd_list_recv(struct buffer *);
void cmd_list_free(struct cmd_list *);
size_t cmd_list_print(struct cmd_list *, char *, size_t);
@ -1220,8 +1239,6 @@ size_t cmd_prarg(char *, size_t, const char *, char *);
#define CMD_TARGET_CLIENT_USAGE "[-t target-client]"
void cmd_target_init(struct cmd *, int);
int cmd_target_parse(struct cmd *, int, char **, char **);
void cmd_target_send(struct cmd *, struct buffer *);
void cmd_target_recv(struct cmd *, struct buffer *);
void cmd_target_free(struct cmd *);
size_t cmd_target_print(struct cmd *, char *, size_t);
#define CMD_SRCDST_WINDOW_USAGE "[-s src-window] [-t dst-window]"
@ -1229,8 +1246,6 @@ size_t cmd_target_print(struct cmd *, char *, size_t);
#define CMD_SRCDST_CLIENT_USAGE "[-s src-client] [-t dst-client]"
void cmd_srcdst_init(struct cmd *, int);
int cmd_srcdst_parse(struct cmd *, int, char **, char **);
void cmd_srcdst_send(struct cmd *, struct buffer *);
void cmd_srcdst_recv(struct cmd *, struct buffer *);
void cmd_srcdst_free(struct cmd *);
size_t cmd_srcdst_print(struct cmd *, char *, size_t);
#define CMD_BUFFER_WINDOW_USAGE "[-b buffer-index] [-t target-window]"
@ -1238,8 +1253,6 @@ size_t cmd_srcdst_print(struct cmd *, char *, size_t);
#define CMD_BUFFER_CLIENT_USAGE "[-b buffer-index] [-t target-client]"
void cmd_buffer_init(struct cmd *, int);
int cmd_buffer_parse(struct cmd *, int, char **, char **);
void cmd_buffer_send(struct cmd *, struct buffer *);
void cmd_buffer_recv(struct cmd *, struct buffer *);
void cmd_buffer_free(struct cmd *);
size_t cmd_buffer_print(struct cmd *, char *, size_t);
#define CMD_OPTION_WINDOW_USAGE "[-gu] [-t target-window] option [value]"
@ -1247,8 +1260,6 @@ size_t cmd_buffer_print(struct cmd *, char *, size_t);
#define CMD_OPTION_CLIENT_USAGE "[-gu] [-t target-client] option [value]"
void cmd_option_init(struct cmd *, int);
int cmd_option_parse(struct cmd *, int, char **, char **);
void cmd_option_send(struct cmd *, struct buffer *);
void cmd_option_recv(struct cmd *, struct buffer *);
void cmd_option_free(struct cmd *);
size_t cmd_option_print(struct cmd *, char *, size_t);
#define CMD_PANE_WINDOW_USAGE "[-t target-window] [-p pane-index]"
@ -1256,8 +1267,6 @@ size_t cmd_option_print(struct cmd *, char *, size_t);
#define CMD_PANE_CLIENT_USAGE "[-t target-client] [-p pane-index]"
void cmd_pane_init(struct cmd *, int);
int cmd_pane_parse(struct cmd *, int, char **, char **);
void cmd_pane_send(struct cmd *, struct buffer *);
void cmd_pane_recv(struct cmd *, struct buffer *);
void cmd_pane_free(struct cmd *);
size_t cmd_pane_print(struct cmd *, char *, size_t);
@ -1270,8 +1279,6 @@ int client_msg_dispatch(struct client_ctx *);
/* client-fn.c */
void client_write_server(struct client_ctx *, enum hdrtype, void *, size_t);
void client_write_server2(
struct client_ctx *, enum hdrtype, void *, size_t, void *, size_t);
void client_fill_session(struct msg_command_data *);
/* key-bindings.c */
@ -1303,6 +1310,7 @@ int server_msg_dispatch(struct client *);
/* server-fn.c */
const char **server_fill_environ(struct session *);
void server_write_error(struct client *, const char *);
void server_write_client(
struct client *, enum hdrtype, const void *, size_t);
void server_write_session(