diff --git a/cmd-queue.c b/cmd-queue.c index 8a274305..7fe2793a 100644 --- a/cmd-queue.c +++ b/cmd-queue.c @@ -137,7 +137,14 @@ cmdq_error(struct cmd_q *cmdq, const char *fmt, ...) va_end(ap); if (c == NULL) { +#ifdef TMATE + if (cmd->file && cmd->line) + xasprintf(&cause, "%s:%u: %s", cmd->file, cmd->line, msg); + else + xasprintf(&cause, "%s", msg); +#else xasprintf(&cause, "%s:%u: %s", cmd->file, cmd->line, msg); +#endif ARRAY_ADD(&cfg_causes, cause); } else if (c->session == NULL || (c->flags & CLIENT_CONTROL)) { evbuffer_add(c->stderr_data, msg, msglen); @@ -228,7 +235,7 @@ cmdq_continue(struct cmd_q *cmdq) #ifdef TMATE if (tmate_should_replicate_cmd(cmdq->cmd->entry)) - tmate_cmd(s); + tmate_exec_cmd(s); #endif guard = cmdq_guard(cmdq, "begin"); diff --git a/tmate-decoder.c b/tmate-decoder.c index 00c4890f..0bdca7d4 100644 --- a/tmate-decoder.c +++ b/tmate-decoder.c @@ -115,23 +115,36 @@ static void tmate_client_resize(struct tmate_unpacker *uk) /* TODO Handle reconnection cases */ } -static void tmate_client_cmd(struct tmate_unpacker *uk) +static void tmate_client_exec_cmd(struct tmate_unpacker *uk) { struct cmd_q *cmd_q; struct cmd_list *cmdlist; - char *cmd_str; char *cause; - cmd_str = unpack_string(uk); + int client_id = unpack_int(uk); + char *cmd_str = unpack_string(uk); + if (cmd_string_parse(cmd_str, &cmdlist, NULL, 0, &cause) != 0) { + tmate_failed_cmd(client_id, cause); free(cause); goto out; } + /* error messages land in cfg_causes */ + ARRAY_FREE(&cfg_causes); + cmd_q = cmdq_new(NULL); cmdq_run(cmd_q, cmdlist); cmd_list_free(cmdlist); cmdq_free(cmd_q); + + if (!ARRAY_EMPTY(&cfg_causes)) { + cause = ARRAY_ITEM(&cfg_causes, 0); + tmate_failed_cmd(client_id, cause); + free(cause); + ARRAY_FREE(&cfg_causes); + } + out: free(cmd_str); } @@ -148,7 +161,7 @@ static void handle_message(msgpack_object obj) case TMATE_REPLY_HEADER: tmate_reply_header(uk); break; case TMATE_CLIENT_PANE_KEY: tmate_client_pane_key(uk); break; case TMATE_CLIENT_RESIZE: tmate_client_resize(uk); break; - case TMATE_CLIENT_CMD: tmate_client_cmd(uk); break; + case TMATE_CLIENT_EXEC_CMD: tmate_client_exec_cmd(uk); break; default: decoder_error(); } } diff --git a/tmate-encoder.c b/tmate-encoder.c index cf5d1e29..0e4a2c09 100644 --- a/tmate-encoder.c +++ b/tmate-encoder.c @@ -147,13 +147,21 @@ int tmate_should_replicate_cmd(const struct cmd_entry *cmd) return 0; } -void tmate_cmd(const char *cmd) +void tmate_exec_cmd(const char *cmd) { pack(array, 2); - pack(int, TMATE_CMD); + pack(int, TMATE_EXEC_CMD); pack(string, cmd); } +void tmate_failed_cmd(int client_id, const char *cause) +{ + pack(array, 3); + pack(int, TMATE_FAILED_CMD); + pack(int, client_id); + pack(string, cause); +} + void tmate_status(const char *left, const char *right) { static char *old_left, *old_right; diff --git a/tmate.h b/tmate.h index 612fc184..0ff4cd23 100644 --- a/tmate.h +++ b/tmate.h @@ -22,7 +22,8 @@ enum tmate_commands { TMATE_HEADER, TMATE_SYNC_LAYOUT, TMATE_PTY_DATA, - TMATE_CMD, + TMATE_EXEC_CMD, + TMATE_FAILED_CMD, TMATE_STATUS, }; @@ -38,7 +39,8 @@ extern void tmate_write_header(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_cmd(const char *cmd); +extern void tmate_exec_cmd(const char *cmd); +extern void tmate_failed_cmd(int client_id, const char *cause); extern void tmate_status(const char *left, const char *right); /* tmate-decoder.c */ @@ -47,7 +49,7 @@ enum tmate_client_commands { TMATE_REPLY_HEADER, TMATE_CLIENT_PANE_KEY, TMATE_CLIENT_RESIZE, - TMATE_CLIENT_CMD, + TMATE_CLIENT_EXEC_CMD, }; struct tmate_decoder {