Send commands with their arguments in an array

This commit is contained in:
Nicolas Viennot 2016-03-27 23:32:32 -04:00
parent c88870b0a3
commit 02694d2a96
6 changed files with 145 additions and 29 deletions

View File

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

View File

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

View File

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

View File

@ -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);
pack(int, TMATE_OUT_EXEC_CMD);
pack(string, cmd);
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;
}
void tmate_exec_cmd(const char *cmd)
static void __tmate_exec_cmd_args(int argc, const char **argv)
{
__tmate_exec_cmd(cmd);
append_saved_cmd(&tmate_session, cmd);
int i;
pack(array, argc + 1);
pack(int, TMATE_OUT_EXEC_CMD);
for (i = 0; i < argc; i++)
pack(string, argv[i]);
}
void tmate_exec_cmd_args(int argc, const char **argv)
{
__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)

View File

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

View File

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