summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNicolas Viennot <nicolas@viennot.biz>2016-03-27 23:32:32 -0400
committerNicolas Viennot <nicolas@viennot.biz>2016-03-28 02:18:09 -0400
commit02694d2a966b5d1e3a5d2cbd1b76c627eb4b6ec2 (patch)
tree221dc794ec78897473baa62c9406a4f57e45b53c
parentc88870b0a38acdfb598057ec344cc3d5e3991933 (diff)
Send commands with their arguments in an array
-rw-r--r--cmd-queue.c7
-rw-r--r--server.c8
-rw-r--r--tmate-decoder.c56
-rw-r--r--tmate-encoder.c79
-rw-r--r--tmate-protocol.h14
-rw-r--r--tmate.h8
6 files changed, 144 insertions, 28 deletions
diff --git a/cmd-queue.c b/cmd-queue.c
index fad9760b..f08a724e 100644
--- a/cmd-queue.c
+++ b/cmd-queue.c
@@ -201,12 +201,13 @@ cmdq_continue_one(struct cmd_q *cmdq)
char *tmp;
int flags = !!(cmd->flags & CMD_CONTROL);
- tmp = cmd_print(cmd);
- log_debug("cmdq %p: %s", cmdq, tmp);
#ifdef TMATE
if (tmate_should_replicate_cmd(cmd->entry))
- tmate_exec_cmd(tmp);
+ tmate_exec_cmd(cmd);
#endif
+
+ tmp = cmd_print(cmd);
+ log_debug("cmdq %p: %s", cmdq, tmp);
free(tmp);
cmdq->time = time(NULL);
diff --git a/server.c b/server.c
index 7313b711..81334f1e 100644
--- a/server.c
+++ b/server.c
@@ -135,13 +135,13 @@ server_create_socket(void)
static void tmate_set_editor_mode(void)
{
switch (options_get_number(global_s_options, "status-keys")) {
- case MODEKEY_EMACS: tmate_exec_cmd("set-option -g status-keys emacs"); break;
- case MODEKEY_VI: tmate_exec_cmd("set-option -g status-keys vi"); break;
+ case MODEKEY_EMACS: tmate_exec_cmd_args(4, (const char *[]){"set-option", "-g", "status-keys", "emacs"}); break;
+ case MODEKEY_VI: tmate_exec_cmd_args(4, (const char *[]){"set-option", "-g", "status-keys", "vi"}); break;
}
switch (options_get_number(global_w_options, "mode-keys")) {
- case MODEKEY_EMACS: tmate_exec_cmd("set-window-option -g mode-keys emacs"); break;
- case MODEKEY_VI: tmate_exec_cmd("set-window-option -g mode-keys vi"); break;
+ case MODEKEY_EMACS: tmate_exec_cmd_args(4, (const char *[]){"set-window-option", "-g", "status-keys", "emacs"}); break;
+ case MODEKEY_VI: tmate_exec_cmd_args(4, (const char *[]){"set-window-option", "-g", "status-keys", "vi"}); break;
}
}
#endif
diff --git a/tmate-decoder.c b/tmate-decoder.c
index 9669c4c0..3b1e31af 100644
--- a/tmate-decoder.c
+++ b/tmate-decoder.c
@@ -78,8 +78,8 @@ static void handle_resize(struct tmate_session *session,
extern char **cfg_causes;
extern u_int cfg_ncauses;
-static void handle_exec_cmd(__unused struct tmate_session *session,
- struct tmate_unpacker *uk)
+static void handle_exec_cmd_str(__unused struct tmate_session *session,
+ struct tmate_unpacker *uk)
{
struct cmd_q *cmd_q;
struct cmd_list *cmdlist;
@@ -114,6 +114,55 @@ out:
free(cmd_str);
}
+static void handle_exec_cmd(__unused struct tmate_session *session,
+ struct tmate_unpacker *uk)
+{
+ struct cmd_q *cmd_q;
+ struct cmd_list *cmdlist;
+ struct cmd *cmd;
+ char *cause;
+ u_int i;
+ unsigned int argc;
+ char **argv;
+
+ int client_id = unpack_int(uk);
+
+ argc = uk->argc;
+ argv = xmalloc(sizeof(char *) * argc);
+ for (i = 0; i < argc; i++)
+ argv[i] = unpack_string(uk);
+
+ cmd = cmd_parse(argc, argv, NULL, 0, &cause);
+ if (!cmd) {
+ tmate_failed_cmd(client_id, cause);
+ free(cause);
+ goto out;
+ }
+
+ cmdlist = xcalloc(1, sizeof *cmdlist);
+ cmdlist->references = 1;
+ TAILQ_INIT(&cmdlist->list);
+ TAILQ_INSERT_TAIL(&cmdlist->list, cmd, qentry);
+
+ cmd_q = cmdq_new(NULL);
+ cmdq_run(cmd_q, cmdlist, NULL);
+ cmd_list_free(cmdlist);
+ cmdq_free(cmd_q);
+
+ /* error messages land in cfg_causes */
+ for (i = 0; i < cfg_ncauses; i++) {
+ tmate_failed_cmd(client_id, cfg_causes[i]);
+ free(cfg_causes[i]);
+ }
+
+ free(cfg_causes);
+ cfg_causes = NULL;
+ cfg_ncauses = 0;
+
+out:
+ cmd_free_argv(argc, argv);
+}
+
static void maybe_save_reconnection_data(struct tmate_session *session,
const char *name, const char *value)
{
@@ -152,10 +201,11 @@ void tmate_dispatch_slave_message(struct tmate_session *session,
dispatch(TMATE_IN_NOTIFY, handle_notify);
dispatch(TMATE_IN_LEGACY_PANE_KEY, handle_legacy_pane_key);
dispatch(TMATE_IN_RESIZE, handle_resize);
- dispatch(TMATE_IN_EXEC_CMD, handle_exec_cmd);
+ dispatch(TMATE_IN_EXEC_CMD_STR, handle_exec_cmd_str);
dispatch(TMATE_IN_SET_ENV, handle_set_env);
dispatch(TMATE_IN_READY, handle_ready);
dispatch(TMATE_IN_PANE_KEY, handle_pane_key);
+ dispatch(TMATE_IN_EXEC_CMD, handle_exec_cmd);
default: tmate_info("Bad message type: %d", cmd);
}
}
diff --git a/tmate-encoder.c b/tmate-encoder.c
index 1a6c7b19..d4be7c6e 100644
--- a/tmate-encoder.c
+++ b/tmate-encoder.c
@@ -152,44 +152,99 @@ int tmate_should_replicate_cmd(const struct cmd_entry *cmd)
#define sc (&session->saved_tmux_cmds)
#define SAVED_TMUX_CMD_INITIAL_SIZE 256
-static void __tmate_exec_cmd(const char *cmd);
+static void __tmate_exec_cmd_args(int argc, const char **argv);
static void append_saved_cmd(struct tmate_session *session,
- const char *cmd)
+ int argc, const char **argv)
{
if (!sc->cmds) {
sc->capacity = SAVED_TMUX_CMD_INITIAL_SIZE;
- sc->cmds = xmalloc(sizeof(char *) * sc->capacity);
+ sc->cmds = xmalloc(sizeof(*sc->cmds) * sc->capacity);
sc->tail = 0;
}
if (sc->tail == sc->capacity) {
sc->capacity *= 2;
- sc->cmds = xrealloc(sc->cmds, sizeof(char *) * sc->capacity);
+ sc->cmds = xrealloc(sc->cmds, sizeof(*sc->cmds) * sc->capacity);
}
- sc->cmds[sc->tail++] = xstrdup(cmd);
+ sc->cmds[sc->tail].argc = argc;
+ sc->cmds[sc->tail].argv = cmd_copy_argv(argc, (char **)argv);
+
+ sc->tail++;
}
static void replay_saved_cmd(struct tmate_session *session)
{
unsigned int i;
for (i = 0; i < sc->tail; i++)
- __tmate_exec_cmd(sc->cmds[i]);
+ __tmate_exec_cmd_args(sc->cmds[i].argc, (const char **)sc->cmds[i].argv);
}
#undef sc
-static void __tmate_exec_cmd(const char *cmd)
+struct args_entry {
+ u_char flag;
+ char *value;
+ RB_ENTRY(args_entry) entry;
+};
+
+static void extract_cmd(struct cmd *cmd, int *_argc, char ***_argv)
{
- pack(array, 2);
+ struct args_entry *entry;
+ struct args* args = cmd->args;
+ int argc = 0;
+ char **argv;
+ int next = 0, i;
+
+ argc++; /* cmd name */
+ RB_FOREACH(entry, args_tree, &args->tree) {
+ argc++;
+ if (entry->value != NULL)
+ argc++;
+ }
+ argc += args->argc;
+ argv = xmalloc(sizeof(char *) * argc);
+
+ argv[next++] = xstrdup(cmd->entry->name);
+
+ RB_FOREACH(entry, args_tree, &args->tree) {
+ xasprintf(&argv[next++], "-%c", entry->flag);
+ if (entry->value != NULL)
+ argv[next++] = xstrdup(entry->value);
+ }
+
+ for (i = 0; i < args->argc; i++)
+ argv[next++] = xstrdup(args->argv[i]);
+
+ *_argc = argc;
+ *_argv = argv;
+}
+
+static void __tmate_exec_cmd_args(int argc, const char **argv)
+{
+ int i;
+
+ pack(array, argc + 1);
pack(int, TMATE_OUT_EXEC_CMD);
- pack(string, cmd);
+
+ for (i = 0; i < argc; i++)
+ pack(string, argv[i]);
}
-void tmate_exec_cmd(const char *cmd)
+void tmate_exec_cmd_args(int argc, const char **argv)
{
- __tmate_exec_cmd(cmd);
- append_saved_cmd(&tmate_session, cmd);
+ __tmate_exec_cmd_args(argc, argv);
+ append_saved_cmd(&tmate_session, argc, argv);
+}
+
+void tmate_exec_cmd(struct cmd *cmd)
+{
+ int argc;
+ char **argv;
+
+ extract_cmd(cmd, &argc, &argv);
+ tmate_exec_cmd_args(argc, (const char **)argv);
+ cmd_free_argv(argc, argv);
}
void tmate_failed_cmd(int client_id, const char *cause)
diff --git a/tmate-protocol.h b/tmate-protocol.h
index 93c65ba3..ebae07a9 100644
--- a/tmate-protocol.h
+++ b/tmate-protocol.h
@@ -45,7 +45,7 @@ enum tmate_daemon_out_msg_types {
TMATE_OUT_HEADER,
TMATE_OUT_SYNC_LAYOUT,
TMATE_OUT_PTY_DATA,
- TMATE_OUT_EXEC_CMD,
+ TMATE_OUT_EXEC_CMD_STR,
TMATE_OUT_FAILED_CMD,
TMATE_OUT_STATUS,
TMATE_OUT_SYNC_COPY_MODE,
@@ -54,6 +54,7 @@ enum tmate_daemon_out_msg_types {
TMATE_OUT_READY,
TMATE_OUT_RECONNECT,
TMATE_OUT_SNAPSHOT,
+ TMATE_OUT_EXEC_CMD,
};
/*
@@ -62,7 +63,7 @@ enum tmate_daemon_out_msg_types {
[[int: pane_id, int: sx, int: sy, int: xoff, int: yoff], ...],
int: active_pane_id], ...], int: active_win_id]
[TMATE_OUT_PTY_DATA, int: pane_id, binary: buffer]
-[TMATE_OUT_EXEC_CMD, string: cmd]
+[TMATE_OUT_EXEC_CMD_STR, string: cmd]
[TMATE_OUT_FAILED_CMD, int: client_id, string: cause]
[TMATE_OUT_STATUS, string: left, string: right]
[TMATE_OUT_SYNC_COPY_MODE, int: pane_id, [int: backing, int: oy, int: cx, int: cy,
@@ -72,26 +73,31 @@ enum tmate_daemon_out_msg_types {
[TMATE_OUT_WRITE_COPY_MODE, int: pane_id, string: str]
[TMATE_OUT_FIN]
[TMATE_OUT_READY]
+[TMATE_OUT_RECONNECT, string: reconnection_data]
+[TMATE_OUT_SNAPSHOT, ...]
+[TMATE_OUT_EXEC_CMD, string: cmd_name, ...string: args]
*/
enum tmate_daemon_in_msg_types {
TMATE_IN_NOTIFY,
TMATE_IN_LEGACY_PANE_KEY,
TMATE_IN_RESIZE,
- TMATE_IN_EXEC_CMD,
+ TMATE_IN_EXEC_CMD_STR,
TMATE_IN_SET_ENV,
TMATE_IN_READY,
TMATE_IN_PANE_KEY,
+ TMATE_IN_EXEC_CMD,
};
/*
[TMATE_IN_NOTIFY, string: msg]
[TMATE_IN_PANE_KEY, int: key]
[TMATE_IN_RESIZE, int: sx, int: sy] // sx == -1: no clients
-[TMATE_IN_EXEC_CMD, int: client_id, string: cmd]
+[TMATE_IN_EXEC_CMD_STR, int: client_id, string: cmd]
[TMATE_IN_SET_ENV, string: name, string: value]
[TMATE_IN_READY]
[TMATE_IN_PANE_KEY, int: pane_id, uint64 keycode] // pane_id == -1: active pane
+[TMATE_IN_EXEC_CMD, int: client_id, ...string: args]
*/
#endif
diff --git a/tmate.h b/tmate.h
index e6d3ef09..fb764c54 100644
--- a/tmate.h
+++ b/tmate.h
@@ -84,7 +84,8 @@ extern void tmate_write_ready(void);
extern void tmate_sync_layout(void);
extern void tmate_pty_data(struct window_pane *wp, const char *buf, size_t len);
extern int tmate_should_replicate_cmd(const struct cmd_entry *cmd);
-extern void tmate_exec_cmd(const char *cmd);
+extern void tmate_exec_cmd_args(int argc, const char **argv);
+extern void tmate_exec_cmd(struct cmd *cmd);
extern void tmate_failed_cmd(int client_id, const char *cause);
extern void tmate_status(const char *left, const char *right);
extern void tmate_sync_copy_mode(struct window_pane *wp);
@@ -184,7 +185,10 @@ struct tmate_session {
struct {
unsigned int capacity;
unsigned int tail;
- char **cmds;
+ struct {
+ int argc;
+ char **argv;
+ } *cmds;
} saved_tmux_cmds;
};