diff --git a/Makefile b/Makefile index cebcac8e..f78b1615 100644 --- a/Makefile +++ b/Makefile @@ -60,12 +60,10 @@ SRCS= arguments.c \ cmd-select-pane.c \ cmd-select-window.c \ cmd-send-keys.c \ - cmd-send-prefix.c \ cmd-server-info.c \ cmd-set-buffer.c \ cmd-set-environment.c \ cmd-set-option.c \ - cmd-show-buffer.c \ cmd-show-environment.c \ cmd-show-messages.c \ cmd-show-options.c \ @@ -80,6 +78,7 @@ SRCS= arguments.c \ cmd-unbind-key.c \ cmd-unlink-window.c \ cmd.c \ + cmd-queue.c \ colour.c \ control.c \ control-notify.c \ diff --git a/cfg.c b/cfg.c index b7b0ec78..e4069d68 100644 --- a/cfg.c +++ b/cfg.c @@ -27,80 +27,27 @@ #include "tmux.h" -/* - * Config file parser. Pretty quick and simple, each line is parsed into a - * argv array and executed as a command. - */ - -void printflike2 cfg_print(struct cmd_ctx *, const char *, ...); -void printflike2 cfg_error(struct cmd_ctx *, const char *, ...); - -char *cfg_cause; +struct cmd_q *cfg_cmd_q; int cfg_finished; -int cfg_references; +int cfg_references; struct causelist cfg_causes; -void printflike2 -cfg_print(unused struct cmd_ctx *ctx, unused const char *fmt, ...) -{ -} - -void printflike2 -cfg_error(unused struct cmd_ctx *ctx, const char *fmt, ...) -{ - va_list ap; - - va_start(ap, fmt); - xvasprintf(&cfg_cause, fmt, ap); - va_end(ap); -} - -void printflike2 -cfg_add_cause(struct causelist *causes, const char *fmt, ...) -{ - char *cause; - va_list ap; - - va_start(ap, fmt); - xvasprintf(&cause, fmt, ap); - va_end(ap); - - ARRAY_ADD(causes, cause); -} - -/* - * Load configuration file. Returns -1 for an error with a list of messages in - * causes. Note that causes must be initialised by the caller! - */ -enum cmd_retval -load_cfg(const char *path, struct cmd_ctx *ctx, struct causelist *causes) +int +load_cfg(const char *path, struct cmd_q *cmdq, char **cause) { FILE *f; - u_int n; - char *buf, *copy, *line, *cause; + u_int n, found; + char *buf, *copy, *line, *cause1, *msg; size_t len, oldlen; struct cmd_list *cmdlist; - enum cmd_retval retval; if ((f = fopen(path, "rb")) == NULL) { - cfg_add_cause(causes, "%s: %s", path, strerror(errno)); - return (CMD_RETURN_ERROR); + xasprintf(cause, "%s: %s", path, strerror(errno)); + return (-1); } - cfg_references++; - - if (ctx != NULL) - cmd_ref_ctx(ctx); - else { - ctx = cmd_get_ctx(NULL, NULL); - ctx->error = cfg_error; - ctx->print = cfg_print; - ctx->info = cfg_print; - } - - n = 0; + n = found = 0; line = NULL; - retval = CMD_RETURN_NORMAL; while ((buf = fgetln(f, &len))) { /* Trim \n. */ if (buf[len - 1] == '\n') @@ -142,53 +89,47 @@ load_cfg(const char *path, struct cmd_ctx *ctx, struct causelist *causes) continue; } - if (cmd_string_parse(buf, &cmdlist, &cause) != 0) { + /* Parse and run the command. */ + if (cmd_string_parse(buf, &cmdlist, path, n, &cause1) != 0) { free(copy); - if (cause == NULL) + if (cause1 == NULL) continue; - cfg_add_cause(causes, "%s: %u: %s", path, n, cause); - free(cause); + xasprintf(&msg, "%s:%u: %s", path, n, cause1); + ARRAY_ADD(&cfg_causes, msg); + free(cause1); continue; } free(copy); + if (cmdlist == NULL) continue; - - cfg_cause = NULL; - switch (cmd_list_exec(cmdlist, ctx)) { - case CMD_RETURN_YIELD: - if (retval != CMD_RETURN_ATTACH) - retval = CMD_RETURN_YIELD; - break; - case CMD_RETURN_ATTACH: - retval = CMD_RETURN_ATTACH; - break; - case CMD_RETURN_ERROR: - case CMD_RETURN_NORMAL: - break; - } + cmdq_append(cmdq, cmdlist); cmd_list_free(cmdlist); - if (cfg_cause != NULL) { - cfg_add_cause(causes, "%s: %d: %s", path, n, cfg_cause); - free(cfg_cause); - } + found++; } - if (line != NULL) { - cfg_add_cause(causes, - "%s: %d: line continuation at end of file", path, n); + if (line != NULL) free(line); - } fclose(f); - cmd_free_ctx(ctx); - - cfg_references--; - - return (retval); + return (found); } void -show_cfg_causes(struct session *s) +cfg_default_done(unused struct cmd_q *cmdq) +{ + if (--cfg_references != 0) + return; + cfg_finished = 1; + + if (!RB_EMPTY(&sessions)) + cfg_show_causes(RB_MIN(sessions, &sessions)); + + cmdq_free(cfg_cmd_q); + cfg_cmd_q = NULL; +} + +void +cfg_show_causes(struct session *s) { struct window_pane *wp; char *cause; @@ -196,7 +137,6 @@ show_cfg_causes(struct session *s) if (s == NULL || ARRAY_EMPTY(&cfg_causes)) return; - wp = s->curw->window->active; window_pane_set_mode(wp, &window_copy_mode); diff --git a/client.c b/client.c index 92c3fca3..8693afeb 100644 --- a/client.c +++ b/client.c @@ -188,7 +188,8 @@ client_main(int argc, char **argv, int flags) * later in server) but it is necessary to get the start server * flag. */ - if ((cmdlist = cmd_list_parse(argc, argv, &cause)) == NULL) { + cmdlist = cmd_list_parse(argc, argv, NULL, 0, &cause); + if (cmdlist == NULL) { fprintf(stderr, "%s\n", cause); return (1); } diff --git a/cmd-attach-session.c b/cmd-attach-session.c index 30451389..0298dda1 100644 --- a/cmd-attach-session.c +++ b/cmd-attach-session.c @@ -26,7 +26,7 @@ * Attach existing session to the current terminal. */ -enum cmd_retval cmd_attach_session_exec(struct cmd *, struct cmd_ctx *); +enum cmd_retval cmd_attach_session_exec(struct cmd *, struct cmd_q *); const struct cmd_entry cmd_attach_session_entry = { "attach-session", "attach", @@ -39,7 +39,7 @@ const struct cmd_entry cmd_attach_session_entry = { }; enum cmd_retval -cmd_attach_session_exec(struct cmd *self, struct cmd_ctx *ctx) +cmd_attach_session_exec(struct cmd *self, struct cmd_q *cmdq) { struct args *args = self->args; struct session *s; @@ -49,17 +49,17 @@ cmd_attach_session_exec(struct cmd *self, struct cmd_ctx *ctx) u_int i; if (RB_EMPTY(&sessions)) { - ctx->error(ctx, "no sessions"); + cmdq_error(cmdq, "no sessions"); return (CMD_RETURN_ERROR); } - if ((s = cmd_find_session(ctx, args_get(args, 't'), 1)) == NULL) + if ((s = cmd_find_session(cmdq, args_get(args, 't'), 1)) == NULL) return (CMD_RETURN_ERROR); - if (ctx->cmdclient == NULL && ctx->curclient == NULL) + if (cmdq->client == NULL) return (CMD_RETURN_NORMAL); - if (ctx->cmdclient == NULL) { + if (cmdq->client->session != NULL) { if (args_has(self->args, 'd')) { /* * Can't use server_write_session in case attaching to @@ -69,43 +69,44 @@ cmd_attach_session_exec(struct cmd *self, struct cmd_ctx *ctx) c = ARRAY_ITEM(&clients, i); if (c == NULL || c->session != s) continue; - if (c == ctx->curclient) + if (c == cmdq->client) continue; server_write_client(c, MSG_DETACH, NULL, 0); } } - ctx->curclient->session = s; - notify_attached_session_changed(ctx->curclient); + cmdq->client->session = s; + notify_attached_session_changed(cmdq->client); session_update_activity(s); - server_redraw_client(ctx->curclient); + server_redraw_client(cmdq->client); s->curw->flags &= ~WINLINK_ALERTFLAGS; } else { - if (server_client_open(ctx->cmdclient, s, &cause) != 0) { - ctx->error(ctx, "open terminal failed: %s", cause); + if (server_client_open(cmdq->client, s, &cause) != 0) { + cmdq_error(cmdq, "open terminal failed: %s", cause); free(cause); return (CMD_RETURN_ERROR); } if (args_has(self->args, 'r')) - ctx->cmdclient->flags |= CLIENT_READONLY; + cmdq->client->flags |= CLIENT_READONLY; if (args_has(self->args, 'd')) server_write_session(s, MSG_DETACH, NULL, 0); - ctx->cmdclient->session = s; - notify_attached_session_changed(ctx->cmdclient); - session_update_activity(s); - server_write_ready(ctx->cmdclient); - update = options_get_string(&s->options, "update-environment"); - environ_update(update, &ctx->cmdclient->environ, &s->environ); + environ_update(update, &cmdq->client->environ, &s->environ); - server_redraw_client(ctx->cmdclient); + cmdq->client->session = s; + notify_attached_session_changed(cmdq->client); + session_update_activity(s); + server_redraw_client(cmdq->client); s->curw->flags &= ~WINLINK_ALERTFLAGS; + + server_write_ready(cmdq->client); + cmdq->client_exit = 0; } recalculate_sizes(); server_update_socket(); - return (CMD_RETURN_ATTACH); + return (CMD_RETURN_NORMAL); } diff --git a/cmd-bind-key.c b/cmd-bind-key.c index 086ac4ec..d9b65bec 100644 --- a/cmd-bind-key.c +++ b/cmd-bind-key.c @@ -28,9 +28,9 @@ */ enum cmd_retval cmd_bind_key_check(struct args *); -enum cmd_retval cmd_bind_key_exec(struct cmd *, struct cmd_ctx *); +enum cmd_retval cmd_bind_key_exec(struct cmd *, struct cmd_q *); -enum cmd_retval cmd_bind_key_table(struct cmd *, struct cmd_ctx *, int); +enum cmd_retval cmd_bind_key_table(struct cmd *, struct cmd_q *, int); const struct cmd_entry cmd_bind_key_entry = { "bind-key", "bind", @@ -56,7 +56,7 @@ cmd_bind_key_check(struct args *args) } enum cmd_retval -cmd_bind_key_exec(struct cmd *self, struct cmd_ctx *ctx) +cmd_bind_key_exec(struct cmd *self, struct cmd_q *cmdq) { struct args *args = self->args; char *cause; @@ -65,16 +65,17 @@ cmd_bind_key_exec(struct cmd *self, struct cmd_ctx *ctx) key = key_string_lookup_string(args->argv[0]); if (key == KEYC_NONE) { - ctx->error(ctx, "unknown key: %s", args->argv[0]); + cmdq_error(cmdq, "unknown key: %s", args->argv[0]); return (CMD_RETURN_ERROR); } if (args_has(args, 't')) - return (cmd_bind_key_table(self, ctx, key)); + return (cmd_bind_key_table(self, cmdq, key)); - cmdlist = cmd_list_parse(args->argc - 1, args->argv + 1, &cause); + cmdlist = cmd_list_parse(args->argc - 1, args->argv + 1, NULL, 0, + &cause); if (cmdlist == NULL) { - ctx->error(ctx, "%s", cause); + cmdq_error(cmdq, "%s", cause); free(cause); return (CMD_RETURN_ERROR); } @@ -86,7 +87,7 @@ cmd_bind_key_exec(struct cmd *self, struct cmd_ctx *ctx) } enum cmd_retval -cmd_bind_key_table(struct cmd *self, struct cmd_ctx *ctx, int key) +cmd_bind_key_table(struct cmd *self, struct cmd_q *cmdq, int key) { struct args *args = self->args; const char *tablename; @@ -97,25 +98,25 @@ cmd_bind_key_table(struct cmd *self, struct cmd_ctx *ctx, int key) tablename = args_get(args, 't'); if ((mtab = mode_key_findtable(tablename)) == NULL) { - ctx->error(ctx, "unknown key table: %s", tablename); + cmdq_error(cmdq, "unknown key table: %s", tablename); return (CMD_RETURN_ERROR); } cmd = mode_key_fromstring(mtab->cmdstr, args->argv[1]); if (cmd == MODEKEY_NONE) { - ctx->error(ctx, "unknown command: %s", args->argv[1]); + cmdq_error(cmdq, "unknown command: %s", args->argv[1]); return (CMD_RETURN_ERROR); } if (cmd != MODEKEYCOPY_COPYPIPE) { if (args->argc != 2) { - ctx->error(ctx, "no argument allowed"); + cmdq_error(cmdq, "no argument allowed"); return (CMD_RETURN_ERROR); } arg = NULL; } else { if (args->argc != 3) { - ctx->error(ctx, "no argument given"); + cmdq_error(cmdq, "no argument given"); return (CMD_RETURN_ERROR); } arg = args->argv[2]; diff --git a/cmd-break-pane.c b/cmd-break-pane.c index a5a78077..27ae1624 100644 --- a/cmd-break-pane.c +++ b/cmd-break-pane.c @@ -26,7 +26,7 @@ * Break pane off into a window. */ -enum cmd_retval cmd_break_pane_exec(struct cmd *, struct cmd_ctx *); +enum cmd_retval cmd_break_pane_exec(struct cmd *, struct cmd_q *); const struct cmd_entry cmd_break_pane_entry = { "break-pane", "breakp", @@ -39,7 +39,7 @@ const struct cmd_entry cmd_break_pane_entry = { }; enum cmd_retval -cmd_break_pane_exec(struct cmd *self, struct cmd_ctx *ctx) +cmd_break_pane_exec(struct cmd *self, struct cmd_q *cmdq) { struct args *args = self->args; struct winlink *wl; @@ -54,11 +54,11 @@ cmd_break_pane_exec(struct cmd *self, struct cmd_ctx *ctx) const char *template; char *cp; - if ((wl = cmd_find_pane(ctx, args_get(args, 't'), &s, &wp)) == NULL) + if ((wl = cmd_find_pane(cmdq, args_get(args, 't'), &s, &wp)) == NULL) return (CMD_RETURN_ERROR); if (window_count_panes(wl->window) == 1) { - ctx->error(ctx, "can't break with only one pane"); + cmdq_error(cmdq, "can't break with only one pane"); return (CMD_RETURN_ERROR); } @@ -97,14 +97,14 @@ cmd_break_pane_exec(struct cmd *self, struct cmd_ctx *ctx) template = BREAK_PANE_TEMPLATE; ft = format_create(); - if ((c = cmd_find_client(ctx, NULL, 1)) != NULL) + if ((c = cmd_find_client(cmdq, NULL, 1)) != NULL) format_client(ft, c); format_session(ft, s); format_winlink(ft, s, wl); format_window_pane(ft, wp); cp = format_expand(ft, template); - ctx->print(ctx, "%s", cp); + cmdq_print(cmdq, "%s", cp); free(cp); format_free(ft); diff --git a/cmd-capture-pane.c b/cmd-capture-pane.c index 6a10b7c9..aa032ce8 100644 --- a/cmd-capture-pane.c +++ b/cmd-capture-pane.c @@ -27,7 +27,7 @@ * Write the entire contents of a pane to a buffer or stdout. */ -enum cmd_retval cmd_capture_pane_exec(struct cmd *, struct cmd_ctx *); +enum cmd_retval cmd_capture_pane_exec(struct cmd *, struct cmd_q *); const struct cmd_entry cmd_capture_pane_entry = { "capture-pane", "capturep", @@ -41,7 +41,7 @@ const struct cmd_entry cmd_capture_pane_entry = { }; enum cmd_retval -cmd_capture_pane_exec(struct cmd *self, struct cmd_ctx *ctx) +cmd_capture_pane_exec(struct cmd *self, struct cmd_q *cmdq) { struct args *args = self->args; struct client *c; @@ -55,7 +55,7 @@ cmd_capture_pane_exec(struct cmd *self, struct cmd_ctx *ctx) struct grid_cell *gc; const struct grid_line *gl; - if (cmd_find_pane(ctx, args_get(args, 't'), NULL, &wp) == NULL) + if (cmd_find_pane(cmdq, args_get(args, 't'), NULL, &wp) == NULL) return (CMD_RETURN_ERROR); s = &wp->base; gd = s->grid; @@ -113,11 +113,10 @@ cmd_capture_pane_exec(struct cmd *self, struct cmd_ctx *ctx) } if (args_has(args, 'p')) { - c = ctx->curclient; - if (c == NULL || !(c->flags & CLIENT_CONTROL)) - c = ctx->cmdclient; - if (c == NULL) { - ctx->error(ctx, "can't write to stdout"); + c = cmdq->client; + if (c == NULL || + (c->session != NULL && !(c->flags & CLIENT_CONTROL))) { + cmdq_error(cmdq, "can't write to stdout"); return (CMD_RETURN_ERROR); } evbuffer_add(c->stdout_data, buf, len); @@ -131,14 +130,14 @@ cmd_capture_pane_exec(struct cmd *self, struct cmd_ctx *ctx) buffer = args_strtonum(args, 'b', 0, INT_MAX, &cause); if (cause != NULL) { - ctx->error(ctx, "buffer %s", cause); + cmdq_error(cmdq, "buffer %s", cause); free(buf); free(cause); return (CMD_RETURN_ERROR); } if (paste_replace(&global_buffers, buffer, buf, len) != 0) { - ctx->error(ctx, "no buffer %d", buffer); + cmdq_error(cmdq, "no buffer %d", buffer); free(buf); return (CMD_RETURN_ERROR); } diff --git a/cmd-choose-buffer.c b/cmd-choose-buffer.c index a58e38b7..8713815d 100644 --- a/cmd-choose-buffer.c +++ b/cmd-choose-buffer.c @@ -27,7 +27,7 @@ * Enter choice mode to choose a buffer. */ -enum cmd_retval cmd_choose_buffer_exec(struct cmd *, struct cmd_ctx *); +enum cmd_retval cmd_choose_buffer_exec(struct cmd *, struct cmd_q *); const struct cmd_entry cmd_choose_buffer_entry = { "choose-buffer", NULL, @@ -40,7 +40,7 @@ const struct cmd_entry cmd_choose_buffer_entry = { }; enum cmd_retval -cmd_choose_buffer_exec(struct cmd *self, struct cmd_ctx *ctx) +cmd_choose_buffer_exec(struct cmd *self, struct cmd_q *cmdq) { struct args *args = self->args; struct client *c; @@ -51,15 +51,15 @@ cmd_choose_buffer_exec(struct cmd *self, struct cmd_ctx *ctx) const char *template; u_int idx; - if ((c = cmd_current_client(ctx)) == NULL) { - ctx->error(ctx, "no client available"); + if ((c = cmd_current_client(cmdq)) == NULL) { + cmdq_error(cmdq, "no client available"); return (CMD_RETURN_ERROR); } if ((template = args_get(args, 'F')) == NULL) template = CHOOSE_BUFFER_TEMPLATE; - if ((wl = cmd_find_window(ctx, args_get(args, 't'), NULL)) == NULL) + if ((wl = cmd_find_window(cmdq, args_get(args, 't'), NULL)) == NULL) return (CMD_RETURN_ERROR); if (paste_get_top(&global_buffers) == NULL) diff --git a/cmd-choose-client.c b/cmd-choose-client.c index 962aefca..b32703c4 100644 --- a/cmd-choose-client.c +++ b/cmd-choose-client.c @@ -27,7 +27,7 @@ * Enter choice mode to choose a client. */ -enum cmd_retval cmd_choose_client_exec(struct cmd *, struct cmd_ctx *); +enum cmd_retval cmd_choose_client_exec(struct cmd *, struct cmd_q *); void cmd_choose_client_callback(struct window_choose_data *); @@ -46,7 +46,7 @@ struct cmd_choose_client_data { }; enum cmd_retval -cmd_choose_client_exec(struct cmd *self, struct cmd_ctx *ctx) +cmd_choose_client_exec(struct cmd *self, struct cmd_q *cmdq) { struct args *args = self->args; struct client *c; @@ -57,12 +57,12 @@ cmd_choose_client_exec(struct cmd *self, struct cmd_ctx *ctx) char *action; u_int i, idx, cur; - if ((c = cmd_current_client(ctx)) == NULL) { - ctx->error(ctx, "no client available"); + if ((c = cmd_current_client(cmdq)) == NULL) { + cmdq_error(cmdq, "no client available"); return (CMD_RETURN_ERROR); } - if ((wl = cmd_find_window(ctx, args_get(args, 't'), NULL)) == NULL) + if ((wl = cmd_find_window(cmdq, args_get(args, 't'), NULL)) == NULL) return (CMD_RETURN_ERROR); if (window_pane_set_mode(wl->window->active, &window_choose_mode) != 0) @@ -81,7 +81,7 @@ cmd_choose_client_exec(struct cmd *self, struct cmd_ctx *ctx) c1 = ARRAY_ITEM(&clients, i); if (c1 == NULL || c1->session == NULL) continue; - if (c1 == ctx->curclient) + if (c1 == cmdq->client) cur = idx; idx++; diff --git a/cmd-choose-list.c b/cmd-choose-list.c index 9634fef4..15f87294 100644 --- a/cmd-choose-list.c +++ b/cmd-choose-list.c @@ -31,7 +31,7 @@ * Enter choose mode to choose a custom list. */ -enum cmd_retval cmd_choose_list_exec(struct cmd *, struct cmd_ctx *); +enum cmd_retval cmd_choose_list_exec(struct cmd *, struct cmd_q *); const struct cmd_entry cmd_choose_list_entry = { "choose-list", NULL, @@ -44,7 +44,7 @@ const struct cmd_entry cmd_choose_list_entry = { }; enum cmd_retval -cmd_choose_list_exec(struct cmd *self, struct cmd_ctx *ctx) +cmd_choose_list_exec(struct cmd *self, struct cmd_q *cmdq) { struct args *args = self->args; struct client *c; @@ -53,15 +53,15 @@ cmd_choose_list_exec(struct cmd *self, struct cmd_ctx *ctx) char *template, *item, *copy, *list; u_int idx; - if ((c = cmd_current_client(ctx)) == NULL) { - ctx->error(ctx, "no client available"); + if ((c = cmd_current_client(cmdq)) == NULL) { + cmdq_error(cmdq, "no client available"); return (CMD_RETURN_ERROR); } if ((list1 = args_get(args, 'l')) == NULL) return (CMD_RETURN_ERROR); - if ((wl = cmd_find_window(ctx, args_get(args, 't'), NULL)) == NULL) + if ((wl = cmd_find_window(cmdq, args_get(args, 't'), NULL)) == NULL) return (CMD_RETURN_ERROR); if (window_pane_set_mode(wl->window->active, &window_choose_mode) != 0) diff --git a/cmd-choose-tree.c b/cmd-choose-tree.c index af85a3bf..f22f17c2 100644 --- a/cmd-choose-tree.c +++ b/cmd-choose-tree.c @@ -32,7 +32,7 @@ * Enter choice mode to choose a session and/or window. */ -enum cmd_retval cmd_choose_tree_exec(struct cmd *, struct cmd_ctx *); +enum cmd_retval cmd_choose_tree_exec(struct cmd *, struct cmd_q *); const struct cmd_entry cmd_choose_tree_entry = { "choose-tree", NULL, @@ -66,7 +66,7 @@ const struct cmd_entry cmd_choose_window_entry = { }; enum cmd_retval -cmd_choose_tree_exec(struct cmd *self, struct cmd_ctx *ctx) +cmd_choose_tree_exec(struct cmd *self, struct cmd_q *cmdq) { struct args *args = self->args; struct winlink *wl, *wm; @@ -84,15 +84,15 @@ cmd_choose_tree_exec(struct cmd *self, struct cmd_ctx *ctx) ses_template = win_template = NULL; ses_action = win_action = NULL; - if ((c = cmd_current_client(ctx)) == NULL) { - ctx->error(ctx, "no client available"); + if ((c = cmd_current_client(cmdq)) == NULL) { + cmdq_error(cmdq, "no client available"); return (CMD_RETURN_ERROR); } if ((s = c->session) == NULL) return (CMD_RETURN_ERROR); - if ((wl = cmd_find_window(ctx, args_get(args, 't'), NULL)) == NULL) + if ((wl = cmd_find_window(cmdq, args_get(args, 't'), NULL)) == NULL) return (CMD_RETURN_ERROR); if (window_pane_set_mode(wl->window->active, &window_choose_mode) != 0) diff --git a/cmd-clear-history.c b/cmd-clear-history.c index 8a88e46c..768ba86d 100644 --- a/cmd-clear-history.c +++ b/cmd-clear-history.c @@ -24,7 +24,7 @@ * Clear pane history. */ -enum cmd_retval cmd_clear_history_exec(struct cmd *, struct cmd_ctx *); +enum cmd_retval cmd_clear_history_exec(struct cmd *, struct cmd_q *); const struct cmd_entry cmd_clear_history_entry = { "clear-history", "clearhist", @@ -37,13 +37,13 @@ const struct cmd_entry cmd_clear_history_entry = { }; enum cmd_retval -cmd_clear_history_exec(struct cmd *self, struct cmd_ctx *ctx) +cmd_clear_history_exec(struct cmd *self, struct cmd_q *cmdq) { struct args *args = self->args; struct window_pane *wp; struct grid *gd; - if (cmd_find_pane(ctx, args_get(args, 't'), NULL, &wp) == NULL) + if (cmd_find_pane(cmdq, args_get(args, 't'), NULL, &wp) == NULL) return (CMD_RETURN_ERROR); gd = wp->base.grid; diff --git a/cmd-clock-mode.c b/cmd-clock-mode.c index f1d9eceb..b1837004 100644 --- a/cmd-clock-mode.c +++ b/cmd-clock-mode.c @@ -24,7 +24,7 @@ * Enter clock mode. */ -enum cmd_retval cmd_clock_mode_exec(struct cmd *, struct cmd_ctx *); +enum cmd_retval cmd_clock_mode_exec(struct cmd *, struct cmd_q *); const struct cmd_entry cmd_clock_mode_entry = { "clock-mode", NULL, @@ -37,12 +37,12 @@ const struct cmd_entry cmd_clock_mode_entry = { }; enum cmd_retval -cmd_clock_mode_exec(struct cmd *self, struct cmd_ctx *ctx) +cmd_clock_mode_exec(struct cmd *self, struct cmd_q *cmdq) { struct args *args = self->args; struct window_pane *wp; - if (cmd_find_pane(ctx, args_get(args, 't'), NULL, &wp) == NULL) + if (cmd_find_pane(cmdq, args_get(args, 't'), NULL, &wp) == NULL) return (CMD_RETURN_ERROR); window_pane_set_mode(wp, &window_clock_mode); diff --git a/cmd-command-prompt.c b/cmd-command-prompt.c index 3a43b24f..3b773316 100644 --- a/cmd-command-prompt.c +++ b/cmd-command-prompt.c @@ -31,7 +31,7 @@ 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_ctx *); +enum cmd_retval cmd_command_prompt_exec(struct cmd *, struct cmd_q *); int cmd_command_prompt_callback(void *, const char *); void cmd_command_prompt_free(void *); @@ -85,7 +85,7 @@ cmd_command_prompt_key_binding(struct cmd *self, int key) } enum cmd_retval -cmd_command_prompt_exec(struct cmd *self, struct cmd_ctx *ctx) +cmd_command_prompt_exec(struct cmd *self, struct cmd_q *cmdq) { struct args *args = self->args; const char *inputs, *prompts; @@ -94,7 +94,7 @@ cmd_command_prompt_exec(struct cmd *self, struct cmd_ctx *ctx) char *prompt, *ptr, *input = NULL; size_t n; - if ((c = cmd_find_client(ctx, args_get(args, 't'), 0)) == NULL) + if ((c = cmd_find_client(cmdq, args_get(args, 't'), 0)) == NULL) return (CMD_RETURN_ERROR); if (c->prompt_string != NULL) @@ -150,7 +150,6 @@ cmd_command_prompt_callback(void *data, const char *s) struct cmd_command_prompt_cdata *cdata = data; struct client *c = cdata->c; struct cmd_list *cmdlist; - struct cmd_ctx *ctx; char *cause, *new_template, *prompt, *ptr; char *input = NULL; @@ -175,7 +174,7 @@ cmd_command_prompt_callback(void *data, const char *s) return (1); } - if (cmd_string_parse(new_template, &cmdlist, &cause) != 0) { + if (cmd_string_parse(new_template, &cmdlist, NULL, 0, &cause) != 0) { if (cause != NULL) { *cause = toupper((u_char) *cause); status_message_set(c, "%s", cause); @@ -184,14 +183,8 @@ cmd_command_prompt_callback(void *data, const char *s) return (0); } - ctx = cmd_get_ctx(NULL, c); - ctx->error = key_bindings_error; - ctx->print = key_bindings_print; - ctx->info = key_bindings_info; - - cmd_list_exec(cmdlist, ctx); + cmdq_run(c->cmdq, cmdlist); cmd_list_free(cmdlist); - cmd_free_ctx(ctx); if (c->prompt_callbackfn != (void *) &cmd_command_prompt_callback) return (1); diff --git a/cmd-confirm-before.c b/cmd-confirm-before.c index 765f58df..6282be2e 100644 --- a/cmd-confirm-before.c +++ b/cmd-confirm-before.c @@ -27,7 +27,7 @@ */ void cmd_confirm_before_key_binding(struct cmd *, int); -enum cmd_retval cmd_confirm_before_exec(struct cmd *, struct cmd_ctx *); +enum cmd_retval cmd_confirm_before_exec(struct cmd *, struct cmd_q *); int cmd_confirm_before_callback(void *, const char *); void cmd_confirm_before_free(void *); @@ -43,8 +43,8 @@ const struct cmd_entry cmd_confirm_before_entry = { }; struct cmd_confirm_before_data { - struct client *c; char *cmd; + struct client *client; }; void @@ -66,7 +66,7 @@ cmd_confirm_before_key_binding(struct cmd *self, int key) } enum cmd_retval -cmd_confirm_before_exec(struct cmd *self, struct cmd_ctx *ctx) +cmd_confirm_before_exec(struct cmd *self, struct cmd_q *cmdq) { struct args *args = self->args; struct cmd_confirm_before_data *cdata; @@ -74,12 +74,7 @@ cmd_confirm_before_exec(struct cmd *self, struct cmd_ctx *ctx) char *cmd, *copy, *new_prompt, *ptr; const char *prompt; - if (ctx->curclient == NULL) { - ctx->error(ctx, "must be run interactively"); - return (CMD_RETURN_ERROR); - } - - if ((c = cmd_find_client(ctx, args_get(args, 't'), 0)) == NULL) + if ((c = cmd_find_client(cmdq, args_get(args, 't'), 0)) == NULL) return (CMD_RETURN_ERROR); if ((prompt = args_get(args, 'p')) != NULL) @@ -93,46 +88,44 @@ cmd_confirm_before_exec(struct cmd *self, struct cmd_ctx *ctx) cdata = xmalloc(sizeof *cdata); cdata->cmd = xstrdup(args->argv[0]); - cdata->c = c; - status_prompt_set(cdata->c, new_prompt, NULL, + + cdata->client = c; + cdata->client->references++; + + status_prompt_set(c, new_prompt, NULL, cmd_confirm_before_callback, cmd_confirm_before_free, cdata, PROMPT_SINGLE); free(new_prompt); - return (CMD_RETURN_YIELD); + return (CMD_RETURN_NORMAL); } int cmd_confirm_before_callback(void *data, const char *s) { struct cmd_confirm_before_data *cdata = data; - struct client *c = cdata->c; + struct client *c = cdata->client; struct cmd_list *cmdlist; - struct cmd_ctx *ctx; char *cause; + if (c->flags & CLIENT_DEAD) + return (0); + if (s == NULL || *s == '\0') return (0); if (tolower((u_char) s[0]) != 'y' || s[1] != '\0') return (0); - if (cmd_string_parse(cdata->cmd, &cmdlist, &cause) != 0) { + if (cmd_string_parse(cdata->cmd, &cmdlist, NULL, 0, &cause) != 0) { if (cause != NULL) { - *cause = toupper((u_char) *cause); - status_message_set(c, "%s", cause); + cmdq_error(c->cmdq, "%s", cause); free(cause); } return (0); } - ctx = cmd_get_ctx(NULL, c); - ctx->error = key_bindings_error; - ctx->print = key_bindings_print; - ctx->info = key_bindings_info; - - cmd_list_exec(cmdlist, ctx); + cmdq_run(c->cmdq, cmdlist); cmd_list_free(cmdlist); - cmd_free_ctx(ctx); return (0); } @@ -141,6 +134,9 @@ void cmd_confirm_before_free(void *data) { struct cmd_confirm_before_data *cdata = data; + struct client *c = cdata->client; + + c->references--; free(cdata->cmd); free(cdata); diff --git a/cmd-copy-mode.c b/cmd-copy-mode.c index 3f80cd8c..59b5a9e5 100644 --- a/cmd-copy-mode.c +++ b/cmd-copy-mode.c @@ -25,7 +25,7 @@ */ void cmd_copy_mode_key_binding(struct cmd *, int); -enum cmd_retval cmd_copy_mode_exec(struct cmd *, struct cmd_ctx *); +enum cmd_retval cmd_copy_mode_exec(struct cmd *, struct cmd_q *); const struct cmd_entry cmd_copy_mode_entry = { "copy-mode", NULL, @@ -46,12 +46,12 @@ cmd_copy_mode_key_binding(struct cmd *self, int key) } enum cmd_retval -cmd_copy_mode_exec(struct cmd *self, struct cmd_ctx *ctx) +cmd_copy_mode_exec(struct cmd *self, struct cmd_q *cmdq) { struct args *args = self->args; struct window_pane *wp; - if (cmd_find_pane(ctx, args_get(args, 't'), NULL, &wp) == NULL) + if (cmd_find_pane(cmdq, args_get(args, 't'), NULL, &wp) == NULL) return (CMD_RETURN_ERROR); if (window_pane_set_mode(wp, &window_copy_mode) != 0) diff --git a/cmd-delete-buffer.c b/cmd-delete-buffer.c index c3f8776a..6e425b57 100644 --- a/cmd-delete-buffer.c +++ b/cmd-delete-buffer.c @@ -26,7 +26,7 @@ * Delete a paste buffer. */ -enum cmd_retval cmd_delete_buffer_exec(struct cmd *, struct cmd_ctx *); +enum cmd_retval cmd_delete_buffer_exec(struct cmd *, struct cmd_q *); const struct cmd_entry cmd_delete_buffer_entry = { "delete-buffer", "deleteb", @@ -39,7 +39,7 @@ const struct cmd_entry cmd_delete_buffer_entry = { }; enum cmd_retval -cmd_delete_buffer_exec(struct cmd *self, struct cmd_ctx *ctx) +cmd_delete_buffer_exec(struct cmd *self, struct cmd_q *cmdq) { struct args *args = self->args; char *cause; @@ -52,13 +52,13 @@ cmd_delete_buffer_exec(struct cmd *self, struct cmd_ctx *ctx) buffer = args_strtonum(args, 'b', 0, INT_MAX, &cause); if (cause != NULL) { - ctx->error(ctx, "buffer %s", cause); + cmdq_error(cmdq, "buffer %s", cause); free(cause); return (CMD_RETURN_ERROR); } if (paste_free_index(&global_buffers, buffer) != 0) { - ctx->error(ctx, "no buffer %d", buffer); + cmdq_error(cmdq, "no buffer %d", buffer); return (CMD_RETURN_ERROR); } diff --git a/cmd-detach-client.c b/cmd-detach-client.c index a1d3a386..17b437ab 100644 --- a/cmd-detach-client.c +++ b/cmd-detach-client.c @@ -24,7 +24,7 @@ * Detach a client. */ -enum cmd_retval cmd_detach_client_exec(struct cmd *, struct cmd_ctx *); +enum cmd_retval cmd_detach_client_exec(struct cmd *, struct cmd_q *); const struct cmd_entry cmd_detach_client_entry = { "detach-client", "detach", @@ -37,7 +37,7 @@ const struct cmd_entry cmd_detach_client_entry = { }; enum cmd_retval -cmd_detach_client_exec(struct cmd *self, struct cmd_ctx *ctx) +cmd_detach_client_exec(struct cmd *self, struct cmd_q *cmdq) { struct args *args = self->args; struct client *c, *c2; @@ -51,7 +51,7 @@ cmd_detach_client_exec(struct cmd *self, struct cmd_ctx *ctx) msgtype = MSG_DETACH; if (args_has(args, 's')) { - s = cmd_find_session(ctx, args_get(args, 's'), 0); + s = cmd_find_session(cmdq, args_get(args, 's'), 0); if (s == NULL) return (CMD_RETURN_ERROR); @@ -61,7 +61,7 @@ cmd_detach_client_exec(struct cmd *self, struct cmd_ctx *ctx) server_write_client(c, msgtype, NULL, 0); } } else { - c = cmd_find_client(ctx, args_get(args, 't'), 0); + c = cmd_find_client(cmdq, args_get(args, 't'), 0); if (c == NULL) return (CMD_RETURN_ERROR); @@ -76,5 +76,5 @@ cmd_detach_client_exec(struct cmd *self, struct cmd_ctx *ctx) server_write_client(c, msgtype, NULL, 0); } - return (CMD_RETURN_NORMAL); + return (CMD_RETURN_STOP); } diff --git a/cmd-display-message.c b/cmd-display-message.c index 05c3a408..7f31d7e2 100644 --- a/cmd-display-message.c +++ b/cmd-display-message.c @@ -27,7 +27,7 @@ * Displays a message in the status line. */ -enum cmd_retval cmd_display_message_exec(struct cmd *, struct cmd_ctx *); +enum cmd_retval cmd_display_message_exec(struct cmd *, struct cmd_q *); const struct cmd_entry cmd_display_message_entry = { "display-message", "display", @@ -41,7 +41,7 @@ const struct cmd_entry cmd_display_message_entry = { }; enum cmd_retval -cmd_display_message_exec(struct cmd *self, struct cmd_ctx *ctx) +cmd_display_message_exec(struct cmd *self, struct cmd_q *cmdq) { struct args *args = self->args; struct client *c; @@ -56,17 +56,17 @@ cmd_display_message_exec(struct cmd *self, struct cmd_ctx *ctx) size_t len; if (args_has(args, 't')) { - wl = cmd_find_pane(ctx, args_get(args, 't'), &s, &wp); + wl = cmd_find_pane(cmdq, args_get(args, 't'), &s, &wp); if (wl == NULL) return (CMD_RETURN_ERROR); } else { - wl = cmd_find_pane(ctx, NULL, &s, &wp); + wl = cmd_find_pane(cmdq, NULL, &s, &wp); if (wl == NULL) return (CMD_RETURN_ERROR); } if (args_has(args, 'F') && args->argc != 0) { - ctx->error(ctx, "only one of -F or argument must be given"); + cmdq_error(cmdq, "only one of -F or argument must be given"); return (CMD_RETURN_ERROR); } @@ -77,7 +77,7 @@ cmd_display_message_exec(struct cmd *self, struct cmd_ctx *ctx) template = DISPLAY_MESSAGE_TEMPLATE; ft = format_create(); - if ((c = cmd_find_client(ctx, args_get(args, 'c'), 1)) != NULL) + if ((c = cmd_find_client(cmdq, args_get(args, 'c'), 1)) != NULL) format_client(ft, c); format_session(ft, s); format_winlink(ft, s, wl); @@ -89,11 +89,11 @@ cmd_display_message_exec(struct cmd *self, struct cmd_ctx *ctx) msg = format_expand(ft, out); if (args_has(self->args, 'p')) - ctx->print(ctx, "%s", msg); + cmdq_print(cmdq, "%s", msg); else status_message_set(c, "%s", msg); - free(msg); format_free(ft); + return (CMD_RETURN_NORMAL); } diff --git a/cmd-display-panes.c b/cmd-display-panes.c index b3e67fd2..a97a1809 100644 --- a/cmd-display-panes.c +++ b/cmd-display-panes.c @@ -24,7 +24,7 @@ * Display panes on a client. */ -enum cmd_retval cmd_display_panes_exec(struct cmd *, struct cmd_ctx *); +enum cmd_retval cmd_display_panes_exec(struct cmd *, struct cmd_q *); const struct cmd_entry cmd_display_panes_entry = { "display-panes", "displayp", @@ -37,12 +37,12 @@ const struct cmd_entry cmd_display_panes_entry = { }; enum cmd_retval -cmd_display_panes_exec(struct cmd *self, struct cmd_ctx *ctx) +cmd_display_panes_exec(struct cmd *self, struct cmd_q *cmdq) { struct args *args = self->args; struct client *c; - if ((c = cmd_find_client(ctx, args_get(args, 't'), 0)) == NULL) + if ((c = cmd_find_client(cmdq, args_get(args, 't'), 0)) == NULL) return (CMD_RETURN_ERROR); server_set_identify(c); diff --git a/cmd-find-window.c b/cmd-find-window.c index acd63c84..f757d10f 100644 --- a/cmd-find-window.c +++ b/cmd-find-window.c @@ -28,7 +28,7 @@ * Find window containing text. */ -enum cmd_retval cmd_find_window_exec(struct cmd *, struct cmd_ctx *); +enum cmd_retval cmd_find_window_exec(struct cmd *, struct cmd_q *); void cmd_find_window_callback(struct window_choose_data *); @@ -127,7 +127,7 @@ cmd_find_window_match(struct cmd_find_window_data_list *find_list, } enum cmd_retval -cmd_find_window_exec(struct cmd *self, struct cmd_ctx *ctx) +cmd_find_window_exec(struct cmd *self, struct cmd_q *cmdq) { struct args *args = self->args; struct client *c; @@ -139,13 +139,13 @@ cmd_find_window_exec(struct cmd *self, struct cmd_ctx *ctx) const char *template; u_int i, match_flags; - if ((c = cmd_current_client(ctx)) == NULL) { - ctx->error(ctx, "no client available"); + if ((c = cmd_current_client(cmdq)) == NULL) { + cmdq_error(cmdq, "no client available"); return (CMD_RETURN_ERROR); } s = c->session; - if ((wl = cmd_find_window(ctx, args_get(args, 't'), NULL)) == NULL) + if ((wl = cmd_find_window(cmdq, args_get(args, 't'), NULL)) == NULL) return (CMD_RETURN_ERROR); if ((template = args_get(args, 'F')) == NULL) @@ -162,7 +162,7 @@ cmd_find_window_exec(struct cmd *self, struct cmd_ctx *ctx) free(searchstr); if (ARRAY_LENGTH(&find_list) == 0) { - ctx->error(ctx, "no windows matching: %s", str); + cmdq_error(cmdq, "no windows matching: %s", str); ARRAY_FREE(&find_list); return (CMD_RETURN_ERROR); } diff --git a/cmd-has-session.c b/cmd-has-session.c index 8e77942a..28e3aea3 100644 --- a/cmd-has-session.c +++ b/cmd-has-session.c @@ -24,7 +24,7 @@ * Cause client to report an error and exit with 1 if session doesn't exist. */ -enum cmd_retval cmd_has_session_exec(struct cmd *, struct cmd_ctx *); +enum cmd_retval cmd_has_session_exec(struct cmd *, struct cmd_q *); const struct cmd_entry cmd_has_session_entry = { "has-session", "has", @@ -37,11 +37,11 @@ const struct cmd_entry cmd_has_session_entry = { }; enum cmd_retval -cmd_has_session_exec(struct cmd *self, struct cmd_ctx *ctx) +cmd_has_session_exec(struct cmd *self, struct cmd_q *cmdq) { struct args *args = self->args; - if (cmd_find_session(ctx, args_get(args, 't'), 0) == NULL) + if (cmd_find_session(cmdq, args_get(args, 't'), 0) == NULL) return (CMD_RETURN_ERROR); return (CMD_RETURN_NORMAL); diff --git a/cmd-if-shell.c b/cmd-if-shell.c index e0e2c230..e2a45972 100644 --- a/cmd-if-shell.c +++ b/cmd-if-shell.c @@ -29,15 +29,16 @@ * Executes a tmux command if a shell command returns true or false. */ -enum cmd_retval cmd_if_shell_exec(struct cmd *, struct cmd_ctx *); +enum cmd_retval cmd_if_shell_exec(struct cmd *, struct cmd_q *); void cmd_if_shell_callback(struct job *); +void cmd_if_shell_done(struct cmd_q *); void cmd_if_shell_free(void *); const struct cmd_entry cmd_if_shell_entry = { "if-shell", "if", - "t:", 2, 3, - CMD_TARGET_PANE_USAGE " shell-command command [command]", + "bt:", 2, 3, + "[-b] " CMD_TARGET_PANE_USAGE " shell-command command [command]", 0, NULL, NULL, @@ -47,11 +48,13 @@ const struct cmd_entry cmd_if_shell_entry = { struct cmd_if_shell_data { char *cmd_if; char *cmd_else; - struct cmd_ctx *ctx; + struct cmd_q *cmdq; + int bflag; + int started; }; enum cmd_retval -cmd_if_shell_exec(struct cmd *self, struct cmd_ctx *ctx) +cmd_if_shell_exec(struct cmd *self, struct cmd_q *cmdq) { struct args *args = self->args; struct cmd_if_shell_data *cdata; @@ -61,7 +64,7 @@ cmd_if_shell_exec(struct cmd *self, struct cmd_ctx *ctx) struct window_pane *wp; struct format_tree *ft; - wl = cmd_find_pane(ctx, args_get(args, 't'), &s, &wp); + wl = cmd_find_pane(cmdq, args_get(args, 't'), &s, &wp); if (wl == NULL) return (CMD_RETURN_ERROR); @@ -78,51 +81,83 @@ cmd_if_shell_exec(struct cmd *self, struct cmd_ctx *ctx) cdata->cmd_else = xstrdup(args->argv[2]); else cdata->cmd_else = NULL; + cdata->bflag = args_has(args, 'b'); - cdata->ctx = ctx; - cmd_ref_ctx(ctx); + cdata->started = 0; + cdata->cmdq = cmdq; + cmdq->references++; job_run(shellcmd, cmd_if_shell_callback, cmd_if_shell_free, cdata); free(shellcmd); - return (CMD_RETURN_YIELD); /* don't let client exit */ + if (cdata->bflag) + return (CMD_RETURN_NORMAL); + return (CMD_RETURN_WAIT); } void cmd_if_shell_callback(struct job *job) { struct cmd_if_shell_data *cdata = job->data; - struct cmd_ctx *ctx = cdata->ctx; + struct cmd_q *cmdq = cdata->cmdq, *cmdq1; struct cmd_list *cmdlist; char *cause, *cmd; - if (!WIFEXITED(job->status) || WEXITSTATUS(job->status) != 0) { + if (cmdq->dead) + return; + + if (!WIFEXITED(job->status) || WEXITSTATUS(job->status) != 0) cmd = cdata->cmd_else; - if (cmd == NULL) - return; - } else + else cmd = cdata->cmd_if; - if (cmd_string_parse(cmd, &cmdlist, &cause) != 0) { + if (cmd == NULL) + return; + + if (cmd_string_parse(cmd, &cmdlist, NULL, 0, &cause) != 0) { if (cause != NULL) { - ctx->error(ctx, "%s", cause); + cmdq_error(cmdq, "%s", cause); free(cause); } return; } - cmd_list_exec(cmdlist, ctx); + cdata->started = 1; + + cmdq1 = cmdq_new(cmdq->client); + cmdq1->emptyfn = cmd_if_shell_done; + cmdq1->data = cdata; + + cmdq_run(cmdq1, cmdlist); cmd_list_free(cmdlist); } +void +cmd_if_shell_done(struct cmd_q *cmdq1) +{ + struct cmd_if_shell_data *cdata = cmdq1->data; + struct cmd_q *cmdq = cdata->cmdq; + + if (!cmdq_free(cmdq) && !cdata->bflag) + cmdq_continue(cmdq); + + cmdq_free(cmdq1); + + free(cdata->cmd_else); + free(cdata->cmd_if); + free(cdata); +} + void cmd_if_shell_free(void *data) { struct cmd_if_shell_data *cdata = data; - struct cmd_ctx *ctx = cdata->ctx; + struct cmd_q *cmdq = cdata->cmdq; - if (ctx->cmdclient != NULL) - ctx->cmdclient->flags |= CLIENT_EXIT; - cmd_free_ctx(ctx); + if (cdata->started) + return; + + if (!cmdq_free(cmdq) && !cdata->bflag) + cmdq_continue(cmdq); free(cdata->cmd_else); free(cdata->cmd_if); diff --git a/cmd-join-pane.c b/cmd-join-pane.c index c792948c..2e7a59cd 100644 --- a/cmd-join-pane.c +++ b/cmd-join-pane.c @@ -30,9 +30,9 @@ */ void cmd_join_pane_key_binding(struct cmd *, int); -enum cmd_retval cmd_join_pane_exec(struct cmd *, struct cmd_ctx *); +enum cmd_retval cmd_join_pane_exec(struct cmd *, struct cmd_q *); -enum cmd_retval join_pane(struct cmd *, struct cmd_ctx *, int); +enum cmd_retval join_pane(struct cmd *, struct cmd_q *, int); const struct cmd_entry cmd_join_pane_entry = { "join-pane", "joinp", @@ -69,13 +69,13 @@ cmd_join_pane_key_binding(struct cmd *self, int key) } enum cmd_retval -cmd_join_pane_exec(struct cmd *self, struct cmd_ctx *ctx) +cmd_join_pane_exec(struct cmd *self, struct cmd_q *cmdq) { - return (join_pane(self, ctx, self->entry == &cmd_join_pane_entry)); + return (join_pane(self, cmdq, self->entry == &cmd_join_pane_entry)); } enum cmd_retval -join_pane(struct cmd *self, struct cmd_ctx *ctx, int not_same_window) +join_pane(struct cmd *self, struct cmd_q *cmdq, int not_same_window) { struct args *args = self->args; struct session *dst_s; @@ -87,23 +87,23 @@ join_pane(struct cmd *self, struct cmd_ctx *ctx, int not_same_window) enum layout_type type; struct layout_cell *lc; - dst_wl = cmd_find_pane(ctx, args_get(args, 't'), &dst_s, &dst_wp); + dst_wl = cmd_find_pane(cmdq, args_get(args, 't'), &dst_s, &dst_wp); if (dst_wl == NULL) return (CMD_RETURN_ERROR); dst_w = dst_wl->window; dst_idx = dst_wl->idx; - src_wl = cmd_find_pane(ctx, args_get(args, 's'), NULL, &src_wp); + src_wl = cmd_find_pane(cmdq, args_get(args, 's'), NULL, &src_wp); if (src_wl == NULL) return (CMD_RETURN_ERROR); src_w = src_wl->window; if (not_same_window && src_w == dst_w) { - ctx->error(ctx, "can't join a pane to its own window"); + cmdq_error(cmdq, "can't join a pane to its own window"); return (CMD_RETURN_ERROR); } if (!not_same_window && src_wp == dst_wp) { - ctx->error(ctx, "source and target panes must be different"); + cmdq_error(cmdq, "source and target panes must be different"); return (CMD_RETURN_ERROR); } @@ -115,14 +115,14 @@ join_pane(struct cmd *self, struct cmd_ctx *ctx, int not_same_window) if (args_has(args, 'l')) { size = args_strtonum(args, 'l', 0, INT_MAX, &cause); if (cause != NULL) { - ctx->error(ctx, "size %s", cause); + cmdq_error(cmdq, "size %s", cause); free(cause); return (CMD_RETURN_ERROR); } } else if (args_has(args, 'p')) { percentage = args_strtonum(args, 'p', 0, 100, &cause); if (cause != NULL) { - ctx->error(ctx, "percentage %s", cause); + cmdq_error(cmdq, "percentage %s", cause); free(cause); return (CMD_RETURN_ERROR); } @@ -133,7 +133,7 @@ join_pane(struct cmd *self, struct cmd_ctx *ctx, int not_same_window) } lc = layout_split_pane(dst_wp, type, size, args_has(args, 'b')); if (lc == NULL) { - ctx->error(ctx, "create pane failed: pane too small"); + cmdq_error(cmdq, "create pane failed: pane too small"); return (CMD_RETURN_ERROR); } diff --git a/cmd-kill-pane.c b/cmd-kill-pane.c index 51989768..1aa776d9 100644 --- a/cmd-kill-pane.c +++ b/cmd-kill-pane.c @@ -26,7 +26,7 @@ * Kill pane. */ -enum cmd_retval cmd_kill_pane_exec(struct cmd *, struct cmd_ctx *); +enum cmd_retval cmd_kill_pane_exec(struct cmd *, struct cmd_q *); const struct cmd_entry cmd_kill_pane_entry = { "kill-pane", "killp", @@ -39,13 +39,13 @@ const struct cmd_entry cmd_kill_pane_entry = { }; enum cmd_retval -cmd_kill_pane_exec(struct cmd *self, struct cmd_ctx *ctx) +cmd_kill_pane_exec(struct cmd *self, struct cmd_q *cmdq) { struct args *args = self->args; struct winlink *wl; struct window_pane *loopwp, *tmpwp, *wp; - if ((wl = cmd_find_pane(ctx, args_get(args, 't'), NULL, &wp)) == NULL) + if ((wl = cmd_find_pane(cmdq, args_get(args, 't'), NULL, &wp)) == NULL) return (CMD_RETURN_ERROR); if (window_count_panes(wl->window) == 1) { diff --git a/cmd-kill-server.c b/cmd-kill-server.c index fcf1e25c..808dca59 100644 --- a/cmd-kill-server.c +++ b/cmd-kill-server.c @@ -27,7 +27,7 @@ * Kill the server and do nothing else. */ -enum cmd_retval cmd_kill_server_exec(struct cmd *, struct cmd_ctx *); +enum cmd_retval cmd_kill_server_exec(struct cmd *, struct cmd_q *); const struct cmd_entry cmd_kill_server_entry = { "kill-server", NULL, @@ -40,7 +40,7 @@ const struct cmd_entry cmd_kill_server_entry = { }; enum cmd_retval -cmd_kill_server_exec(unused struct cmd *self, unused struct cmd_ctx *ctx) +cmd_kill_server_exec(unused struct cmd *self, unused struct cmd_q *cmdq) { kill(getpid(), SIGTERM); diff --git a/cmd-kill-session.c b/cmd-kill-session.c index 9ee6a928..095fb9bb 100644 --- a/cmd-kill-session.c +++ b/cmd-kill-session.c @@ -27,7 +27,7 @@ * Note this deliberately has no alias to make it hard to hit by accident. */ -enum cmd_retval cmd_kill_session_exec(struct cmd *, struct cmd_ctx *); +enum cmd_retval cmd_kill_session_exec(struct cmd *, struct cmd_q *); const struct cmd_entry cmd_kill_session_entry = { "kill-session", NULL, @@ -40,12 +40,12 @@ const struct cmd_entry cmd_kill_session_entry = { }; enum cmd_retval -cmd_kill_session_exec(struct cmd *self, struct cmd_ctx *ctx) +cmd_kill_session_exec(struct cmd *self, struct cmd_q *cmdq) { struct args *args = self->args; struct session *s, *s2, *s3; - if ((s = cmd_find_session(ctx, args_get(args, 't'), 0)) == NULL) + if ((s = cmd_find_session(cmdq, args_get(args, 't'), 0)) == NULL) return (CMD_RETURN_ERROR); if (args_has(args, 'a')) { diff --git a/cmd-kill-window.c b/cmd-kill-window.c index 01587fc8..dcb1fd28 100644 --- a/cmd-kill-window.c +++ b/cmd-kill-window.c @@ -24,7 +24,7 @@ * Destroy window. */ -enum cmd_retval cmd_kill_window_exec(struct cmd *, struct cmd_ctx *); +enum cmd_retval cmd_kill_window_exec(struct cmd *, struct cmd_q *); const struct cmd_entry cmd_kill_window_entry = { "kill-window", "killw", @@ -37,13 +37,13 @@ const struct cmd_entry cmd_kill_window_entry = { }; enum cmd_retval -cmd_kill_window_exec(struct cmd *self, struct cmd_ctx *ctx) +cmd_kill_window_exec(struct cmd *self, struct cmd_q *cmdq) { struct args *args = self->args; struct winlink *wl, *wl2, *wl3; struct session *s; - if ((wl = cmd_find_window(ctx, args_get(args, 't'), &s)) == NULL) + if ((wl = cmd_find_window(cmdq, args_get(args, 't'), &s)) == NULL) return (CMD_RETURN_ERROR); if (args_has(args, 'a')) { diff --git a/cmd-link-window.c b/cmd-link-window.c index 5c050904..c7dfa5aa 100644 --- a/cmd-link-window.c +++ b/cmd-link-window.c @@ -26,7 +26,7 @@ * Link a window into another session. */ -enum cmd_retval cmd_link_window_exec(struct cmd *, struct cmd_ctx *); +enum cmd_retval cmd_link_window_exec(struct cmd *, struct cmd_q *); const struct cmd_entry cmd_link_window_entry = { "link-window", "linkw", @@ -39,7 +39,7 @@ const struct cmd_entry cmd_link_window_entry = { }; enum cmd_retval -cmd_link_window_exec(struct cmd *self, struct cmd_ctx *ctx) +cmd_link_window_exec(struct cmd *self, struct cmd_q *cmdq) { struct args *args = self->args; struct session *src, *dst; @@ -47,15 +47,15 @@ cmd_link_window_exec(struct cmd *self, struct cmd_ctx *ctx) char *cause; int idx, kflag, dflag; - if ((wl = cmd_find_window(ctx, args_get(args, 's'), &src)) == NULL) + if ((wl = cmd_find_window(cmdq, args_get(args, 's'), &src)) == NULL) return (CMD_RETURN_ERROR); - if ((idx = cmd_find_index(ctx, args_get(args, 't'), &dst)) == -2) + if ((idx = cmd_find_index(cmdq, args_get(args, 't'), &dst)) == -2) return (CMD_RETURN_ERROR); kflag = args_has(self->args, 'k'); dflag = args_has(self->args, 'd'); if (server_link_window(src, wl, dst, idx, kflag, !dflag, &cause) != 0) { - ctx->error(ctx, "can't link window: %s", cause); + cmdq_error(cmdq, "can't link window: %s", cause); free(cause); return (CMD_RETURN_ERROR); } diff --git a/cmd-list-buffers.c b/cmd-list-buffers.c index b1d59f2f..54284d55 100644 --- a/cmd-list-buffers.c +++ b/cmd-list-buffers.c @@ -27,7 +27,7 @@ * List paste buffers. */ -enum cmd_retval cmd_list_buffers_exec(struct cmd *, struct cmd_ctx *); +enum cmd_retval cmd_list_buffers_exec(struct cmd *, struct cmd_q *); const struct cmd_entry cmd_list_buffers_entry = { "list-buffers", "lsb", @@ -40,7 +40,7 @@ const struct cmd_entry cmd_list_buffers_entry = { }; enum cmd_retval -cmd_list_buffers_exec(unused struct cmd *self, struct cmd_ctx *ctx) +cmd_list_buffers_exec(unused struct cmd *self, struct cmd_q *cmdq) { struct args *args = self->args; struct paste_buffer *pb; @@ -59,7 +59,7 @@ cmd_list_buffers_exec(unused struct cmd *self, struct cmd_ctx *ctx) format_paste_buffer(ft, pb); line = format_expand(ft, template); - ctx->print(ctx, "%s", line); + cmdq_print(cmdq, "%s", line); free(line); format_free(ft); diff --git a/cmd-list-clients.c b/cmd-list-clients.c index 70f6c809..e0f8558e 100644 --- a/cmd-list-clients.c +++ b/cmd-list-clients.c @@ -28,7 +28,7 @@ * List all clients. */ -enum cmd_retval cmd_list_clients_exec(struct cmd *, struct cmd_ctx *); +enum cmd_retval cmd_list_clients_exec(struct cmd *, struct cmd_q *); const struct cmd_entry cmd_list_clients_entry = { "list-clients", "lsc", @@ -41,7 +41,7 @@ const struct cmd_entry cmd_list_clients_entry = { }; enum cmd_retval -cmd_list_clients_exec(struct cmd *self, struct cmd_ctx *ctx) +cmd_list_clients_exec(struct cmd *self, struct cmd_q *cmdq) { struct args *args = self->args; struct client *c; @@ -52,7 +52,7 @@ cmd_list_clients_exec(struct cmd *self, struct cmd_ctx *ctx) char *line; if (args_has(args, 't')) { - s = cmd_find_session(ctx, args_get(args, 't'), 0); + s = cmd_find_session(cmdq, args_get(args, 't'), 0); if (s == NULL) return (CMD_RETURN_ERROR); } else @@ -75,7 +75,7 @@ cmd_list_clients_exec(struct cmd *self, struct cmd_ctx *ctx) format_client(ft, c); line = format_expand(ft, template); - ctx->print(ctx, "%s", line); + cmdq_print(cmdq, "%s", line); free(line); format_free(ft); diff --git a/cmd-list-commands.c b/cmd-list-commands.c index 05a31ec5..7073d5f8 100644 --- a/cmd-list-commands.c +++ b/cmd-list-commands.c @@ -24,7 +24,7 @@ * List all commands with usages. */ -enum cmd_retval cmd_list_commands_exec(struct cmd *, struct cmd_ctx *); +enum cmd_retval cmd_list_commands_exec(struct cmd *, struct cmd_q *); const struct cmd_entry cmd_list_commands_entry = { "list-commands", "lscm", @@ -37,16 +37,16 @@ const struct cmd_entry cmd_list_commands_entry = { }; enum cmd_retval -cmd_list_commands_exec(unused struct cmd *self, struct cmd_ctx *ctx) +cmd_list_commands_exec(unused struct cmd *self, struct cmd_q *cmdq) { const struct cmd_entry **entryp; for (entryp = cmd_table; *entryp != NULL; entryp++) { if ((*entryp)->alias != NULL) { - ctx->print(ctx, "%s (%s) %s", (*entryp)->name, + cmdq_print(cmdq, "%s (%s) %s", (*entryp)->name, (*entryp)->alias, (*entryp)->usage); } else { - ctx->print(ctx, "%s %s", (*entryp)->name, + cmdq_print(cmdq, "%s %s", (*entryp)->name, (*entryp)->usage); } } diff --git a/cmd-list-keys.c b/cmd-list-keys.c index dab6d545..1f568909 100644 --- a/cmd-list-keys.c +++ b/cmd-list-keys.c @@ -26,8 +26,8 @@ * List key bindings. */ -enum cmd_retval cmd_list_keys_exec(struct cmd *, struct cmd_ctx *); -enum cmd_retval cmd_list_keys_table(struct cmd *, struct cmd_ctx *); +enum cmd_retval cmd_list_keys_exec(struct cmd *, struct cmd_q *); +enum cmd_retval cmd_list_keys_table(struct cmd *, struct cmd_q *); const struct cmd_entry cmd_list_keys_entry = { "list-keys", "lsk", @@ -40,7 +40,7 @@ const struct cmd_entry cmd_list_keys_entry = { }; enum cmd_retval -cmd_list_keys_exec(struct cmd *self, struct cmd_ctx *ctx) +cmd_list_keys_exec(struct cmd *self, struct cmd_q *cmdq) { struct args *args = self->args; struct key_binding *bd; @@ -50,7 +50,7 @@ cmd_list_keys_exec(struct cmd *self, struct cmd_ctx *ctx) int width, keywidth; if (args_has(args, 't')) - return (cmd_list_keys_table(self, ctx)); + return (cmd_list_keys_table(self, cmdq)); width = 0; @@ -91,14 +91,14 @@ cmd_list_keys_exec(struct cmd *self, struct cmd_ctx *ctx) continue; cmd_list_print(bd->cmdlist, tmp + used, (sizeof tmp) - used); - ctx->print(ctx, "bind-key %s", tmp); + cmdq_print(cmdq, "bind-key %s", tmp); } return (CMD_RETURN_NORMAL); } enum cmd_retval -cmd_list_keys_table(struct cmd *self, struct cmd_ctx *ctx) +cmd_list_keys_table(struct cmd *self, struct cmd_q *cmdq) { struct args *args = self->args; const char *tablename; @@ -109,7 +109,7 @@ cmd_list_keys_table(struct cmd *self, struct cmd_ctx *ctx) tablename = args_get(args, 't'); if ((mtab = mode_key_findtable(tablename)) == NULL) { - ctx->error(ctx, "unknown key table: %s", tablename); + cmdq_error(cmdq, "unknown key table: %s", tablename); return (CMD_RETURN_ERROR); } @@ -138,7 +138,7 @@ cmd_list_keys_table(struct cmd *self, struct cmd_ctx *ctx) mode = "c"; cmdstr = mode_key_tostring(mtab->cmdstr, mbind->cmd); if (cmdstr != NULL) { - ctx->print(ctx, "bind-key -%st %s%s %*s %s%s%s%s", + cmdq_print(cmdq, "bind-key -%st %s%s %*s %s%s%s%s", mode, any_mode && *mode == '\0' ? " " : "", mtab->name, (int) width, key, cmdstr, mbind->arg != NULL ? " \"" : "", diff --git a/cmd-list-panes.c b/cmd-list-panes.c index 717562a4..910c19bc 100644 --- a/cmd-list-panes.c +++ b/cmd-list-panes.c @@ -27,13 +27,13 @@ * List panes on given window. */ -enum cmd_retval cmd_list_panes_exec(struct cmd *, struct cmd_ctx *); +enum cmd_retval cmd_list_panes_exec(struct cmd *, struct cmd_q *); -void cmd_list_panes_server(struct cmd *, struct cmd_ctx *); +void cmd_list_panes_server(struct cmd *, struct cmd_q *); void cmd_list_panes_session( - struct cmd *, struct session *, struct cmd_ctx *, int); + struct cmd *, struct session *, struct cmd_q *, int); void cmd_list_panes_window(struct cmd *, - struct session *, struct winlink *, struct cmd_ctx *, int); + struct session *, struct winlink *, struct cmd_q *, int); const struct cmd_entry cmd_list_panes_entry = { "list-panes", "lsp", @@ -46,51 +46,51 @@ const struct cmd_entry cmd_list_panes_entry = { }; enum cmd_retval -cmd_list_panes_exec(struct cmd *self, struct cmd_ctx *ctx) +cmd_list_panes_exec(struct cmd *self, struct cmd_q *cmdq) { struct args *args = self->args; struct session *s; struct winlink *wl; if (args_has(args, 'a')) - cmd_list_panes_server(self, ctx); + cmd_list_panes_server(self, cmdq); else if (args_has(args, 's')) { - s = cmd_find_session(ctx, args_get(args, 't'), 0); + s = cmd_find_session(cmdq, args_get(args, 't'), 0); if (s == NULL) return (CMD_RETURN_ERROR); - cmd_list_panes_session(self, s, ctx, 1); + cmd_list_panes_session(self, s, cmdq, 1); } else { - wl = cmd_find_window(ctx, args_get(args, 't'), &s); + wl = cmd_find_window(cmdq, args_get(args, 't'), &s); if (wl == NULL) return (CMD_RETURN_ERROR); - cmd_list_panes_window(self, s, wl, ctx, 0); + cmd_list_panes_window(self, s, wl, cmdq, 0); } return (CMD_RETURN_NORMAL); } void -cmd_list_panes_server(struct cmd *self, struct cmd_ctx *ctx) +cmd_list_panes_server(struct cmd *self, struct cmd_q *cmdq) { struct session *s; RB_FOREACH(s, sessions, &sessions) - cmd_list_panes_session(self, s, ctx, 2); + cmd_list_panes_session(self, s, cmdq, 2); } void cmd_list_panes_session( - struct cmd *self, struct session *s, struct cmd_ctx *ctx, int type) + struct cmd *self, struct session *s, struct cmd_q *cmdq, int type) { struct winlink *wl; RB_FOREACH(wl, winlinks, &s->windows) - cmd_list_panes_window(self, s, wl, ctx, type); + cmd_list_panes_window(self, s, wl, cmdq, type); } void cmd_list_panes_window(struct cmd *self, - struct session *s, struct winlink *wl, struct cmd_ctx *ctx, int type) + struct session *s, struct winlink *wl, struct cmd_q *cmdq, int type) { struct args *args = self->args; struct window_pane *wp; @@ -135,7 +135,7 @@ cmd_list_panes_window(struct cmd *self, format_window_pane(ft, wp); line = format_expand(ft, template); - ctx->print(ctx, "%s", line); + cmdq_print(cmdq, "%s", line); free(line); format_free(ft); diff --git a/cmd-list-sessions.c b/cmd-list-sessions.c index 81cc51cc..14ac4808 100644 --- a/cmd-list-sessions.c +++ b/cmd-list-sessions.c @@ -28,7 +28,7 @@ * List all sessions. */ -enum cmd_retval cmd_list_sessions_exec(struct cmd *, struct cmd_ctx *); +enum cmd_retval cmd_list_sessions_exec(struct cmd *, struct cmd_q *); const struct cmd_entry cmd_list_sessions_entry = { "list-sessions", "ls", @@ -41,7 +41,7 @@ const struct cmd_entry cmd_list_sessions_entry = { }; enum cmd_retval -cmd_list_sessions_exec(struct cmd *self, struct cmd_ctx *ctx) +cmd_list_sessions_exec(struct cmd *self, struct cmd_q *cmdq) { struct args *args = self->args; struct session *s; @@ -60,7 +60,7 @@ cmd_list_sessions_exec(struct cmd *self, struct cmd_ctx *ctx) format_session(ft, s); line = format_expand(ft, template); - ctx->print(ctx, "%s", line); + cmdq_print(cmdq, "%s", line); free(line); format_free(ft); diff --git a/cmd-list-windows.c b/cmd-list-windows.c index 0485e4a3..c709e471 100644 --- a/cmd-list-windows.c +++ b/cmd-list-windows.c @@ -27,11 +27,11 @@ * List windows on given session. */ -enum cmd_retval cmd_list_windows_exec(struct cmd *, struct cmd_ctx *); +enum cmd_retval cmd_list_windows_exec(struct cmd *, struct cmd_q *); -void cmd_list_windows_server(struct cmd *, struct cmd_ctx *); +void cmd_list_windows_server(struct cmd *, struct cmd_q *); void cmd_list_windows_session( - struct cmd *, struct session *, struct cmd_ctx *, int); + struct cmd *, struct session *, struct cmd_q *, int); const struct cmd_entry cmd_list_windows_entry = { "list-windows", "lsw", @@ -44,35 +44,35 @@ const struct cmd_entry cmd_list_windows_entry = { }; enum cmd_retval -cmd_list_windows_exec(struct cmd *self, struct cmd_ctx *ctx) +cmd_list_windows_exec(struct cmd *self, struct cmd_q *cmdq) { struct args *args = self->args; struct session *s; if (args_has(args, 'a')) - cmd_list_windows_server(self, ctx); + cmd_list_windows_server(self, cmdq); else { - s = cmd_find_session(ctx, args_get(args, 't'), 0); + s = cmd_find_session(cmdq, args_get(args, 't'), 0); if (s == NULL) return (CMD_RETURN_ERROR); - cmd_list_windows_session(self, s, ctx, 0); + cmd_list_windows_session(self, s, cmdq, 0); } return (CMD_RETURN_NORMAL); } void -cmd_list_windows_server(struct cmd *self, struct cmd_ctx *ctx) +cmd_list_windows_server(struct cmd *self, struct cmd_q *cmdq) { struct session *s; RB_FOREACH(s, sessions, &sessions) - cmd_list_windows_session(self, s, ctx, 1); + cmd_list_windows_session(self, s, cmdq, 1); } void cmd_list_windows_session( - struct cmd *self, struct session *s, struct cmd_ctx *ctx, int type) + struct cmd *self, struct session *s, struct cmd_q *cmdq, int type) { struct args *args = self->args; struct winlink *wl; @@ -102,7 +102,7 @@ cmd_list_windows_session( format_window_pane(ft, wl->window->active); line = format_expand(ft, template); - ctx->print(ctx, "%s", line); + cmdq_print(cmdq, "%s", line); free(line); format_free(ft); diff --git a/cmd-list.c b/cmd-list.c index d1e72e93..82ae7480 100644 --- a/cmd-list.c +++ b/cmd-list.c @@ -24,7 +24,8 @@ #include "tmux.h" struct cmd_list * -cmd_list_parse(int argc, char **argv, char **cause) +cmd_list_parse(int argc, char **argv, const char* file, u_int line, + char **cause) { struct cmd_list *cmdlist; struct cmd *cmd; @@ -34,7 +35,7 @@ cmd_list_parse(int argc, char **argv, char **cause) copy_argv = cmd_copy_argv(argc, argv); - cmdlist = xmalloc(sizeof *cmdlist); + cmdlist = xcalloc(1, sizeof *cmdlist); cmdlist->references = 1; TAILQ_INIT(&cmdlist->list); @@ -55,7 +56,7 @@ cmd_list_parse(int argc, char **argv, char **cause) if (arglen != 1) new_argc++; - cmd = cmd_parse(new_argc, new_argv, cause); + cmd = cmd_parse(new_argc, new_argv, file, line, cause); if (cmd == NULL) goto bad; TAILQ_INSERT_TAIL(&cmdlist->list, cmd, qentry); @@ -64,7 +65,8 @@ cmd_list_parse(int argc, char **argv, char **cause) } if (lastsplit != argc) { - cmd = cmd_parse(argc - lastsplit, copy_argv + lastsplit, cause); + cmd = cmd_parse(argc - lastsplit, copy_argv + lastsplit, + file, line, cause); if (cmd == NULL) goto bad; TAILQ_INSERT_TAIL(&cmdlist->list, cmd, qentry); @@ -79,76 +81,21 @@ bad: return (NULL); } -enum cmd_retval -cmd_list_exec(struct cmd_list *cmdlist, struct cmd_ctx *ctx) -{ - struct client *c = ctx->curclient; - struct cmd *cmd; - enum cmd_retval retval; - int guards, n; - - guards = 0; - if (c != NULL && c->session != NULL) - guards = c->flags & CLIENT_CONTROL; - - notify_disable(); - - retval = 0; - TAILQ_FOREACH(cmd, &cmdlist->list, qentry) { - if (guards) - ctx->print(ctx, "%%begin"); - n = cmd->entry->exec(cmd, ctx); - if (guards) - ctx->print(ctx, "%%end"); - - switch (n) - { - case CMD_RETURN_ERROR: - return (CMD_RETURN_ERROR); - case CMD_RETURN_ATTACH: - /* Client is being attached (send MSG_READY). */ - retval = CMD_RETURN_ATTACH; - - /* - * Mangle the context to treat any following commands - * as if they were called from inside. - */ - if (ctx->curclient == NULL) { - ctx->curclient = ctx->cmdclient; - ctx->cmdclient = NULL; - - ctx->error = key_bindings_error; - ctx->print = key_bindings_print; - ctx->info = key_bindings_info; - } - break; - case CMD_RETURN_YIELD: - if (retval == CMD_RETURN_NORMAL) - retval = CMD_RETURN_YIELD; - break; - case CMD_RETURN_NORMAL: - break; - } - } - - notify_enable(); - return (retval); -} - void cmd_list_free(struct cmd_list *cmdlist) { - struct cmd *cmd; + struct cmd *cmd, *cmd1; if (--cmdlist->references != 0) return; - while (!TAILQ_EMPTY(&cmdlist->list)) { - cmd = TAILQ_FIRST(&cmdlist->list); + TAILQ_FOREACH_SAFE(cmd, &cmdlist->list, qentry, cmd1) { TAILQ_REMOVE(&cmdlist->list, cmd, qentry); args_free(cmd->args); + free(cmd->file); free(cmd); } + free(cmdlist); } diff --git a/cmd-load-buffer.c b/cmd-load-buffer.c index bfb06842..698210d8 100644 --- a/cmd-load-buffer.c +++ b/cmd-load-buffer.c @@ -30,7 +30,7 @@ * Loads a paste buffer from a file. */ -enum cmd_retval cmd_load_buffer_exec(struct cmd *, struct cmd_ctx *); +enum cmd_retval cmd_load_buffer_exec(struct cmd *, struct cmd_q *); void cmd_load_buffer_callback(struct client *, int, void *); const struct cmd_entry cmd_load_buffer_entry = { @@ -44,10 +44,10 @@ const struct cmd_entry cmd_load_buffer_entry = { }; enum cmd_retval -cmd_load_buffer_exec(struct cmd *self, struct cmd_ctx *ctx) +cmd_load_buffer_exec(struct cmd *self, struct cmd_q *cmdq) { struct args *args = self->args; - struct client *c = ctx->cmdclient; + struct client *c = cmdq->client; struct session *s; FILE *f; const char *path, *newpath, *wd; @@ -61,7 +61,7 @@ cmd_load_buffer_exec(struct cmd *self, struct cmd_ctx *ctx) else { buffer = args_strtonum(args, 'b', 0, INT_MAX, &cause); if (cause != NULL) { - ctx->error(ctx, "buffer %s", cause); + cmdq_error(cmdq, "buffer %s", cause); free(cause); return (CMD_RETURN_ERROR); } @@ -75,16 +75,16 @@ cmd_load_buffer_exec(struct cmd *self, struct cmd_ctx *ctx) error = server_set_stdin_callback (c, cmd_load_buffer_callback, buffer_ptr, &cause); if (error != 0) { - ctx->error(ctx, "%s: %s", path, cause); + cmdq_error(cmdq, "%s: %s", path, cause); free(cause); return (CMD_RETURN_ERROR); } - return (CMD_RETURN_YIELD); + return (CMD_RETURN_WAIT); } if (c != NULL) wd = c->cwd; - else if ((s = cmd_current_session(ctx, 0)) != NULL) { + else if ((s = cmd_current_session(cmdq, 0)) != NULL) { wd = options_get_string(&s->options, "default-path"); if (*wd == '\0') wd = s->cwd; @@ -96,7 +96,7 @@ cmd_load_buffer_exec(struct cmd *self, struct cmd_ctx *ctx) path = newpath; } if ((f = fopen(path, "rb")) == NULL) { - ctx->error(ctx, "%s: %s", path, strerror(errno)); + cmdq_error(cmdq, "%s: %s", path, strerror(errno)); return (CMD_RETURN_ERROR); } @@ -105,14 +105,14 @@ cmd_load_buffer_exec(struct cmd *self, struct cmd_ctx *ctx) while ((ch = getc(f)) != EOF) { /* Do not let the server die due to memory exhaustion. */ if ((new_pdata = realloc(pdata, psize + 2)) == NULL) { - ctx->error(ctx, "realloc error: %s", strerror(errno)); + cmdq_error(cmdq, "realloc error: %s", strerror(errno)); goto error; } pdata = new_pdata; pdata[psize++] = ch; } if (ferror(f)) { - ctx->error(ctx, "%s: read error", path); + cmdq_error(cmdq, "%s: read error", path); goto error; } if (pdata != NULL) @@ -126,7 +126,7 @@ cmd_load_buffer_exec(struct cmd *self, struct cmd_ctx *ctx) return (CMD_RETURN_NORMAL); } if (paste_replace(&global_buffers, buffer, pdata, psize) != 0) { - ctx->error(ctx, "no buffer %d", buffer); + cmdq_error(cmdq, "no buffer %d", buffer); free(pdata); return (CMD_RETURN_ERROR); } @@ -153,12 +153,13 @@ cmd_load_buffer_callback(struct client *c, int closed, void *data) c->stdin_callback = NULL; c->references--; - c->flags |= CLIENT_EXIT; + if (c->flags & CLIENT_DEAD) + return; psize = EVBUFFER_LENGTH(c->stdin_data); if (psize == 0 || (pdata = malloc(psize + 1)) == NULL) { free(data); - return; + goto out; } memcpy(pdata, EVBUFFER_DATA(c->stdin_data), psize); pdata[psize] = '\0'; @@ -174,4 +175,7 @@ cmd_load_buffer_callback(struct client *c, int closed, void *data) } free(data); + +out: + cmdq_continue(c->cmdq); } diff --git a/cmd-lock-server.c b/cmd-lock-server.c index c95379ac..8491c8b1 100644 --- a/cmd-lock-server.c +++ b/cmd-lock-server.c @@ -28,7 +28,7 @@ * Lock commands. */ -enum cmd_retval cmd_lock_server_exec(struct cmd *, struct cmd_ctx *); +enum cmd_retval cmd_lock_server_exec(struct cmd *, struct cmd_q *); const struct cmd_entry cmd_lock_server_entry = { "lock-server", "lock", @@ -61,7 +61,7 @@ const struct cmd_entry cmd_lock_client_entry = { }; enum cmd_retval -cmd_lock_server_exec(struct cmd *self, unused struct cmd_ctx *ctx) +cmd_lock_server_exec(struct cmd *self, unused struct cmd_q *cmdq) { struct args *args = self->args; struct client *c; @@ -70,11 +70,13 @@ cmd_lock_server_exec(struct cmd *self, unused struct cmd_ctx *ctx) if (self->entry == &cmd_lock_server_entry) server_lock(); else if (self->entry == &cmd_lock_session_entry) { - if ((s = cmd_find_session(ctx, args_get(args, 't'), 0)) == NULL) + s = cmd_find_session(cmdq, args_get(args, 't'), 0); + if (s == NULL) return (CMD_RETURN_ERROR); server_lock_session(s); } else { - if ((c = cmd_find_client(ctx, args_get(args, 't'), 0)) == NULL) + c = cmd_find_client(cmdq, args_get(args, 't'), 0); + if (c == NULL) return (CMD_RETURN_ERROR); server_lock_client(c); } diff --git a/cmd-move-window.c b/cmd-move-window.c index 03d42a8d..945e9daa 100644 --- a/cmd-move-window.c +++ b/cmd-move-window.c @@ -26,7 +26,7 @@ * Move a window. */ -enum cmd_retval cmd_move_window_exec(struct cmd *, struct cmd_ctx *); +enum cmd_retval cmd_move_window_exec(struct cmd *, struct cmd_q *); const struct cmd_entry cmd_move_window_entry = { "move-window", "movew", @@ -39,7 +39,7 @@ const struct cmd_entry cmd_move_window_entry = { }; enum cmd_retval -cmd_move_window_exec(struct cmd *self, struct cmd_ctx *ctx) +cmd_move_window_exec(struct cmd *self, struct cmd_q *cmdq) { struct args *args = self->args; struct session *src, *dst, *s; @@ -48,7 +48,7 @@ cmd_move_window_exec(struct cmd *self, struct cmd_ctx *ctx) int idx, kflag, dflag; if (args_has(args, 'r')) { - if ((s = cmd_find_session(ctx, args_get(args, 't'), 0)) == NULL) + if ((s = cmd_find_session(cmdq, args_get(args, 't'), 0)) == NULL) return (CMD_RETURN_ERROR); session_renumber_windows(s); @@ -57,15 +57,15 @@ cmd_move_window_exec(struct cmd *self, struct cmd_ctx *ctx) return (CMD_RETURN_NORMAL); } - if ((wl = cmd_find_window(ctx, args_get(args, 's'), &src)) == NULL) + if ((wl = cmd_find_window(cmdq, args_get(args, 's'), &src)) == NULL) return (CMD_RETURN_ERROR); - if ((idx = cmd_find_index(ctx, args_get(args, 't'), &dst)) == -2) + if ((idx = cmd_find_index(cmdq, args_get(args, 't'), &dst)) == -2) return (CMD_RETURN_ERROR); kflag = args_has(self->args, 'k'); dflag = args_has(self->args, 'd'); if (server_link_window(src, wl, dst, idx, kflag, !dflag, &cause) != 0) { - ctx->error(ctx, "can't move window: %s", cause); + cmdq_error(cmdq, "can't move window: %s", cause); free(cause); return (CMD_RETURN_ERROR); } diff --git a/cmd-new-session.c b/cmd-new-session.c index ee161808..13ab667e 100644 --- a/cmd-new-session.c +++ b/cmd-new-session.c @@ -31,7 +31,7 @@ */ enum cmd_retval cmd_new_session_check(struct args *); -enum cmd_retval cmd_new_session_exec(struct cmd *, struct cmd_ctx *); +enum cmd_retval cmd_new_session_exec(struct cmd *, struct cmd_q *); const struct cmd_entry cmd_new_session_entry = { "new-session", "new", @@ -53,62 +53,52 @@ cmd_new_session_check(struct args *args) } enum cmd_retval -cmd_new_session_exec(struct cmd *self, struct cmd_ctx *ctx) +cmd_new_session_exec(struct cmd *self, struct cmd_q *cmdq) { - struct args *args = self->args; - struct session *s, *old_s, *groupwith; - struct window *w; - struct environ env; - struct termios tio, *tiop; - struct passwd *pw; - const char *newname, *target, *update, *cwd, *errstr; - char *cmd, *cause; - int detached, idx; - u_int sx, sy; + struct args *args = self->args; + struct client *c = cmdq->client; + struct session *s, *groupwith; + struct window *w; + struct environ env; + struct termios tio, *tiop; + struct passwd *pw; + const char *newname, *target, *update, *cwd, *errstr; + char *cmd, *cause; + int detached, idx; + u_int sx, sy; + int already_attached; + newname = args_get(args, 's'); if (newname != NULL) { if (!session_check_name(newname)) { - ctx->error(ctx, "bad session name: %s", newname); + cmdq_error(cmdq, "bad session name: %s", newname); return (CMD_RETURN_ERROR); } if (session_find(newname) != NULL) { - ctx->error(ctx, "duplicate session: %s", newname); + cmdq_error(cmdq, "duplicate session: %s", newname); return (CMD_RETURN_ERROR); } } target = args_get(args, 't'); if (target != NULL) { - groupwith = cmd_find_session(ctx, target, 0); + groupwith = cmd_find_session(cmdq, target, 0); if (groupwith == NULL) return (CMD_RETURN_ERROR); } else groupwith = NULL; - /* - * There are three cases: - * - * 1. If cmdclient is non-NULL, new-session has been called from the - * command-line - cmdclient is to become a new attached, interactive - * client. Unless -d is given, the terminal must be opened and then - * the client sent MSG_READY. - * - * 2. If cmdclient is NULL, new-session has been called from an - * existing client (such as a key binding). - * - * 3. Both are NULL, the command was in the configuration file. Treat - * this as if -d was given even if it was not. - * - * In all cases, a new additional session needs to be created and - * (unless -d) set as the current session for the client. - */ - /* Set -d if no client. */ detached = args_has(args, 'd'); - if (ctx->cmdclient == NULL && ctx->curclient == NULL) + if (c == NULL) detached = 1; + /* Is this client already attached? */ + already_attached = 0; + if (c != NULL && c->session != NULL) + already_attached = 1; + /* * Save the termios settings, part of which is used for new windows in * this session. @@ -118,25 +108,25 @@ cmd_new_session_exec(struct cmd *self, struct cmd_ctx *ctx) * before opening the terminal as that calls tcsetattr() to prepare for * tmux taking over. */ - if (ctx->cmdclient != NULL && ctx->cmdclient->tty.fd != -1) { - if (tcgetattr(ctx->cmdclient->tty.fd, &tio) != 0) + if (!detached && !already_attached && c->tty.fd != -1) { + if (tcgetattr(c->tty.fd, &tio) != 0) fatal("tcgetattr failed"); tiop = &tio; } else tiop = NULL; /* Open the terminal if necessary. */ - if (!detached && ctx->cmdclient != NULL) { - if (server_client_open(ctx->cmdclient, NULL, &cause) != 0) { - ctx->error(ctx, "open terminal failed: %s", cause); + if (!detached && !already_attached) { + if (server_client_open(c, NULL, &cause) != 0) { + cmdq_error(cmdq, "open terminal failed: %s", cause); free(cause); return (CMD_RETURN_ERROR); } } /* Get the new session working directory. */ - if (ctx->cmdclient != NULL && ctx->cmdclient->cwd != NULL) - cwd = ctx->cmdclient->cwd; + if (c != NULL && c->cwd != NULL) + cwd = c->cwd; else { pw = getpwuid(getuid()); if (pw->pw_dir != NULL && *pw->pw_dir != '\0') @@ -146,32 +136,25 @@ cmd_new_session_exec(struct cmd *self, struct cmd_ctx *ctx) } /* Find new session size. */ - if (ctx->cmdclient != NULL) { - sx = ctx->cmdclient->tty.sx; - sy = ctx->cmdclient->tty.sy; - } else if (ctx->curclient != NULL) { - sx = ctx->curclient->tty.sx; - sy = ctx->curclient->tty.sy; + if (c != NULL) { + sx = c->tty.sx; + sy = c->tty.sy; } else { sx = 80; sy = 24; } - if (detached) { - if (args_has(args, 'x')) { - sx = strtonum( - args_get(args, 'x'), 1, USHRT_MAX, &errstr); - if (errstr != NULL) { - ctx->error(ctx, "width %s", errstr); - return (CMD_RETURN_ERROR); - } + if (detached && args_has(args, 'x')) { + sx = strtonum(args_get(args, 'x'), 1, USHRT_MAX, &errstr); + if (errstr != NULL) { + cmdq_error(cmdq, "width %s", errstr); + return (CMD_RETURN_ERROR); } - if (args_has(args, 'y')) { - sy = strtonum( - args_get(args, 'y'), 1, USHRT_MAX, &errstr); - if (errstr != NULL) { - ctx->error(ctx, "height %s", errstr); - return (CMD_RETURN_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); } } if (sy > 0 && options_get_number(&global_s_options, "status")) @@ -192,14 +175,14 @@ cmd_new_session_exec(struct cmd *self, struct cmd_ctx *ctx) /* Construct the environment. */ environ_init(&env); update = options_get_string(&global_s_options, "update-environment"); - if (ctx->cmdclient != NULL) - environ_update(update, &ctx->cmdclient->environ, &env); + if (c != NULL) + environ_update(update, &c->environ, &env); /* Create the new session. */ idx = -1 - options_get_number(&global_s_options, "base-index"); s = session_create(newname, cmd, cwd, &env, tiop, idx, sx, sy, &cause); if (s == NULL) { - ctx->error(ctx, "create session failed: %s", cause); + cmdq_error(cmdq, "create session failed: %s", cause); free(cause); return (CMD_RETURN_ERROR); } @@ -208,9 +191,7 @@ cmd_new_session_exec(struct cmd *self, struct cmd_ctx *ctx) /* Set the initial window name if one given. */ if (cmd != NULL && args_has(args, 'n')) { w = s->curw->window; - window_set_name(w, args_get(args, 'n')); - options_set_number(&w->options, "automatic-rename", 0); } @@ -229,25 +210,14 @@ cmd_new_session_exec(struct cmd *self, struct cmd_ctx *ctx) * taking this session and needs to get MSG_READY and stay around. */ if (!detached) { - if (ctx->cmdclient != NULL) { - server_write_ready(ctx->cmdclient); - - old_s = ctx->cmdclient->session; - if (old_s != NULL) - ctx->cmdclient->last_session = old_s; - ctx->cmdclient->session = s; - notify_attached_session_changed(ctx->cmdclient); - session_update_activity(s); - server_redraw_client(ctx->cmdclient); - } else { - old_s = ctx->curclient->session; - if (old_s != NULL) - ctx->curclient->last_session = old_s; - ctx->curclient->session = s; - notify_attached_session_changed(ctx->curclient); - session_update_activity(s); - server_redraw_client(ctx->curclient); - } + if (!already_attached) + server_write_ready(c); + else if (c->session != NULL) + c->last_session = c->session; + c->session = s; + notify_attached_session_changed(c); + session_update_activity(s); + server_redraw_client(c); } recalculate_sizes(); server_update_socket(); @@ -257,7 +227,9 @@ cmd_new_session_exec(struct cmd *self, struct cmd_ctx *ctx) * session's current window into more mode and display them now. */ if (cfg_finished) - show_cfg_causes(s); + cfg_show_causes(s); - return (detached ? CMD_RETURN_NORMAL : CMD_RETURN_ATTACH); + if (!detached) + cmdq->client_exit = 0; + return (CMD_RETURN_NORMAL); } diff --git a/cmd-new-window.c b/cmd-new-window.c index 0ab05e26..161dc549 100644 --- a/cmd-new-window.c +++ b/cmd-new-window.c @@ -26,7 +26,7 @@ * Create a new window. */ -enum cmd_retval cmd_new_window_exec(struct cmd *, struct cmd_ctx *); +enum cmd_retval cmd_new_window_exec(struct cmd *, struct cmd_q *); const struct cmd_entry cmd_new_window_entry = { "new-window", "neww", @@ -40,7 +40,7 @@ const struct cmd_entry cmd_new_window_entry = { }; enum cmd_retval -cmd_new_window_exec(struct cmd *self, struct cmd_ctx *ctx) +cmd_new_window_exec(struct cmd *self, struct cmd_q *cmdq) { struct args *args = self->args; struct session *s; @@ -54,7 +54,7 @@ cmd_new_window_exec(struct cmd *self, struct cmd_ctx *ctx) char *cp; if (args_has(args, 'a')) { - wl = cmd_find_window(ctx, args_get(args, 't'), &s); + wl = cmd_find_window(cmdq, args_get(args, 't'), &s); if (wl == NULL) return (CMD_RETURN_ERROR); idx = wl->idx + 1; @@ -65,7 +65,7 @@ cmd_new_window_exec(struct cmd *self, struct cmd_ctx *ctx) break; } if (last == INT_MAX) { - ctx->error(ctx, "no free window indexes"); + cmdq_error(cmdq, "no free window indexes"); return (CMD_RETURN_ERROR); } @@ -76,7 +76,7 @@ cmd_new_window_exec(struct cmd *self, struct cmd_ctx *ctx) server_unlink_window(s, wl); } } else { - if ((idx = cmd_find_index(ctx, args_get(args, 't'), &s)) == -2) + if ((idx = cmd_find_index(cmdq, args_get(args, 't'), &s)) == -2) return (CMD_RETURN_ERROR); } detached = args_has(args, 'd'); @@ -105,13 +105,13 @@ cmd_new_window_exec(struct cmd *self, struct cmd_ctx *ctx) cmd = options_get_string(&s->options, "default-command"); else cmd = args->argv[0]; - cwd = cmd_get_default_path(ctx, args_get(args, 'c')); + cwd = cmd_get_default_path(cmdq, args_get(args, 'c')); if (idx == -1) idx = -1 - options_get_number(&s->options, "base-index"); wl = session_new(s, args_get(args, 'n'), cmd, cwd, idx, &cause); if (wl == NULL) { - ctx->error(ctx, "create window failed: %s", cause); + cmdq_error(cmdq, "create window failed: %s", cause); free(cause); return (CMD_RETURN_ERROR); } @@ -126,14 +126,14 @@ cmd_new_window_exec(struct cmd *self, struct cmd_ctx *ctx) template = NEW_WINDOW_TEMPLATE; ft = format_create(); - if ((c = cmd_find_client(ctx, NULL, 1)) != NULL) - format_client(ft, c); + if ((c = cmd_find_client(cmdq, NULL, 1)) != NULL) + format_client(ft, c); format_session(ft, s); format_winlink(ft, s, wl); format_window_pane(ft, wl->window->active); cp = format_expand(ft, template); - ctx->print(ctx, "%s", cp); + cmdq_print(cmdq, "%s", cp); free(cp); format_free(ft); diff --git a/cmd-paste-buffer.c b/cmd-paste-buffer.c index c957ba2f..1cfc17c8 100644 --- a/cmd-paste-buffer.c +++ b/cmd-paste-buffer.c @@ -28,7 +28,7 @@ * Paste paste buffer if present. */ -enum cmd_retval cmd_paste_buffer_exec(struct cmd *, struct cmd_ctx *); +enum cmd_retval cmd_paste_buffer_exec(struct cmd *, struct cmd_q *); void cmd_paste_buffer_filter(struct window_pane *, const char *, size_t, const char *, int); @@ -44,7 +44,7 @@ const struct cmd_entry cmd_paste_buffer_entry = { }; enum cmd_retval -cmd_paste_buffer_exec(struct cmd *self, struct cmd_ctx *ctx) +cmd_paste_buffer_exec(struct cmd *self, struct cmd_q *cmdq) { struct args *args = self->args; struct window_pane *wp; @@ -55,7 +55,7 @@ cmd_paste_buffer_exec(struct cmd *self, struct cmd_ctx *ctx) int buffer; int pflag; - if (cmd_find_pane(ctx, args_get(args, 't'), &s, &wp) == NULL) + if (cmd_find_pane(cmdq, args_get(args, 't'), &s, &wp) == NULL) return (CMD_RETURN_ERROR); if (!args_has(args, 'b')) @@ -63,7 +63,7 @@ cmd_paste_buffer_exec(struct cmd *self, struct cmd_ctx *ctx) else { buffer = args_strtonum(args, 'b', 0, INT_MAX, &cause); if (cause != NULL) { - ctx->error(ctx, "buffer %s", cause); + cmdq_error(cmdq, "buffer %s", cause); free(cause); return (CMD_RETURN_ERROR); } @@ -74,7 +74,7 @@ cmd_paste_buffer_exec(struct cmd *self, struct cmd_ctx *ctx) else { pb = paste_get_index(&global_buffers, buffer); if (pb == NULL) { - ctx->error(ctx, "no buffer %d", buffer); + cmdq_error(cmdq, "no buffer %d", buffer); return (CMD_RETURN_ERROR); } } diff --git a/cmd-pipe-pane.c b/cmd-pipe-pane.c index bb17c6be..5de675df 100644 --- a/cmd-pipe-pane.c +++ b/cmd-pipe-pane.c @@ -32,7 +32,7 @@ * Open pipe to redirect pane output. If already open, close first. */ -enum cmd_retval cmd_pipe_pane_exec(struct cmd *, struct cmd_ctx *); +enum cmd_retval cmd_pipe_pane_exec(struct cmd *, struct cmd_q *); void cmd_pipe_pane_error_callback(struct bufferevent *, short, void *); @@ -47,7 +47,7 @@ const struct cmd_entry cmd_pipe_pane_entry = { }; enum cmd_retval -cmd_pipe_pane_exec(struct cmd *self, struct cmd_ctx *ctx) +cmd_pipe_pane_exec(struct cmd *self, struct cmd_q *cmdq) { struct args *args = self->args; struct client *c; @@ -55,9 +55,9 @@ cmd_pipe_pane_exec(struct cmd *self, struct cmd_ctx *ctx) char *command; int old_fd, pipe_fd[2], null_fd; - if (cmd_find_pane(ctx, args_get(args, 't'), NULL, &wp) == NULL) + if (cmd_find_pane(cmdq, args_get(args, 't'), NULL, &wp) == NULL) return (CMD_RETURN_ERROR); - c = cmd_find_client(ctx, NULL, 1); + c = cmd_find_client(cmdq, NULL, 1); /* Destroy the old pipe. */ old_fd = wp->pipe_fd; @@ -82,14 +82,14 @@ cmd_pipe_pane_exec(struct cmd *self, struct cmd_ctx *ctx) /* Open the new pipe. */ if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, pipe_fd) != 0) { - ctx->error(ctx, "socketpair error: %s", strerror(errno)); + cmdq_error(cmdq, "socketpair error: %s", strerror(errno)); return (CMD_RETURN_ERROR); } /* Fork the child. */ switch (fork()) { case -1: - ctx->error(ctx, "fork error: %s", strerror(errno)); + cmdq_error(cmdq, "fork error: %s", strerror(errno)); return (CMD_RETURN_ERROR); case 0: /* Child process. */ diff --git a/cmd-queue.c b/cmd-queue.c new file mode 100644 index 00000000..07884df2 --- /dev/null +++ b/cmd-queue.c @@ -0,0 +1,258 @@ +/* $OpenBSD$ */ + +/* + * Copyright (c) 2013 Nicholas Marriott + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER + * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include + +#include +#include + +#include "tmux.h" + +/* Create new command queue. */ +struct cmd_q * +cmdq_new(struct client *c) +{ + struct cmd_q *cmdq; + + cmdq = xcalloc(1, sizeof *cmdq); + cmdq->references = 1; + cmdq->dead = 0; + + cmdq->client = c; + cmdq->client_exit = 0; + + TAILQ_INIT(&cmdq->queue); + cmdq->item = NULL; + cmdq->cmd = NULL; + + return (cmdq); +} + +/* Free command queue */ +int +cmdq_free(struct cmd_q *cmdq) +{ + if (--cmdq->references != 0) + return (cmdq->dead); + + cmdq_flush(cmdq); + free(cmdq); + return (1); +} + +/* Show message from command. */ +void printflike2 +cmdq_print(struct cmd_q *cmdq, const char *fmt, ...) +{ + struct client *c = cmdq->client; + struct window *w; + va_list ap; + + va_start(ap, fmt); + + if (c == NULL) + /* nothing */; + else if (c->session == NULL || (c->flags & CLIENT_CONTROL)) { + va_start(ap, fmt); + evbuffer_add_vprintf(c->stdout_data, fmt, ap); + va_end(ap); + + evbuffer_add(c->stdout_data, "\n", 1); + server_push_stdout(c); + } else { + w = c->session->curw->window; + if (w->active->mode != &window_copy_mode) { + window_pane_reset_mode(w->active); + window_pane_set_mode(w->active, &window_copy_mode); + window_copy_init_for_output(w->active); + } + window_copy_vadd(w->active, fmt, ap); + } + + va_end(ap); +} + +/* Show info from command. */ +void printflike2 +cmdq_info(struct cmd_q *cmdq, const char *fmt, ...) +{ + struct client *c = cmdq->client; + va_list ap; + char *msg; + + if (options_get_number(&global_options, "quiet")) + return; + + va_start(ap, fmt); + + if (c == NULL) + /* nothing */; + else if (c->session == NULL || (c->flags & CLIENT_CONTROL)) { + va_start(ap, fmt); + evbuffer_add_vprintf(c->stdout_data, fmt, ap); + va_end(ap); + + evbuffer_add(c->stdout_data, "\n", 1); + server_push_stdout(c); + } else { + xvasprintf(&msg, fmt, ap); + *msg = toupper((u_char) *msg); + status_message_set(c, "%s", msg); + free(msg); + } + + va_end(ap); + +} + +/* Show error from command. */ +void printflike2 +cmdq_error(struct cmd_q *cmdq, const char *fmt, ...) +{ + struct client *c = cmdq->client; + struct cmd *cmd = cmdq->cmd; + va_list ap; + char *msg, *cause; + size_t msglen; + + va_start(ap, fmt); + msglen = xvasprintf(&msg, fmt, ap); + va_end(ap); + + if (c == NULL) { + xasprintf(&cause, "%s:%u: %s", cmd->file, cmd->line, msg); + ARRAY_ADD(&cfg_causes, cause); + } else if (c->session == NULL || (c->flags & CLIENT_CONTROL)) { + evbuffer_add(c->stderr_data, msg, msglen); + evbuffer_add(c->stderr_data, "\n", 1); + + server_push_stderr(c); + c->retcode = 1; + } else { + *msg = toupper((u_char) *msg); + status_message_set(c, "%s", msg); + } + + free(msg); +} + +/* Add command list to queue and begin processing if needed. */ +void +cmdq_run(struct cmd_q *cmdq, struct cmd_list *cmdlist) +{ + cmdq_append(cmdq, cmdlist); + + if (cmdq->item == NULL) { + cmdq->cmd = NULL; + cmdq_continue(cmdq); + } +} + +/* Add command list to queue. */ +void +cmdq_append(struct cmd_q *cmdq, struct cmd_list *cmdlist) +{ + struct cmd_q_item *item; + + item = xcalloc(1, sizeof *item); + item->cmdlist = cmdlist; + TAILQ_INSERT_TAIL(&cmdq->queue, item, qentry); + cmdlist->references++; +} + +/* Continue processing command queue. Returns 1 if finishes empty. */ +int +cmdq_continue(struct cmd_q *cmdq) +{ + struct client *c = cmdq->client; + struct cmd_q_item *next; + enum cmd_retval retval; + int guards, empty; + + guards = 0; + if (c != NULL && c->session != NULL) + guards = c->flags & CLIENT_CONTROL; + + notify_disable(); + + empty = TAILQ_EMPTY(&cmdq->queue); + if (empty) + goto empty; + + if (cmdq->item == NULL) { + cmdq->item = TAILQ_FIRST(&cmdq->queue); + cmdq->cmd = TAILQ_FIRST(&cmdq->item->cmdlist->list); + } else + cmdq->cmd = TAILQ_NEXT(cmdq->cmd, qentry); + + do { + next = TAILQ_NEXT(cmdq->item, qentry); + + while (cmdq->cmd != NULL) { + if (guards) + cmdq_print(cmdq, "%%begin"); + retval = cmdq->cmd->entry->exec(cmdq->cmd, cmdq); + if (guards) + cmdq_print(cmdq, "%%end"); + + if (retval == CMD_RETURN_ERROR) + break; + if (retval == CMD_RETURN_WAIT) + goto out; + if (retval == CMD_RETURN_STOP) { + cmdq_flush(cmdq); + goto empty; + } + + cmdq->cmd = TAILQ_NEXT(cmdq->cmd, qentry); + } + + TAILQ_REMOVE(&cmdq->queue, cmdq->item, qentry); + cmd_list_free(cmdq->item->cmdlist); + free(cmdq->item); + + cmdq->item = next; + if (cmdq->item != NULL) + cmdq->cmd = TAILQ_FIRST(&cmdq->item->cmdlist->list); + } while (cmdq->item != NULL); + +empty: + if (cmdq->client_exit) + cmdq->client->flags |= CLIENT_EXIT; + if (cmdq->emptyfn != NULL) + cmdq->emptyfn(cmdq); /* may free cmdq */ + empty = 1; + +out: + notify_enable(); + return (empty); +} + +/* Flush command queue. */ +void +cmdq_flush(struct cmd_q *cmdq) +{ + struct cmd_q_item *item, *item1; + + TAILQ_FOREACH_SAFE(item, &cmdq->queue, qentry, item1) { + TAILQ_REMOVE(&cmdq->queue, item, qentry); + cmd_list_free(item->cmdlist); + free(item); + } + cmdq->item = NULL; +} diff --git a/cmd-refresh-client.c b/cmd-refresh-client.c index 25df230f..eff692dd 100644 --- a/cmd-refresh-client.c +++ b/cmd-refresh-client.c @@ -24,7 +24,7 @@ * Refresh client. */ -enum cmd_retval cmd_refresh_client_exec(struct cmd *, struct cmd_ctx *); +enum cmd_retval cmd_refresh_client_exec(struct cmd *, struct cmd_q *); const struct cmd_entry cmd_refresh_client_entry = { "refresh-client", "refresh", @@ -37,32 +37,32 @@ const struct cmd_entry cmd_refresh_client_entry = { }; enum cmd_retval -cmd_refresh_client_exec(struct cmd *self, struct cmd_ctx *ctx) +cmd_refresh_client_exec(struct cmd *self, struct cmd_q *cmdq) { struct args *args = self->args; struct client *c; const char *size; u_int w, h; - if ((c = cmd_find_client(ctx, args_get(args, 't'), 0)) == NULL) + if ((c = cmd_find_client(cmdq, args_get(args, 't'), 0)) == NULL) return (CMD_RETURN_ERROR); if (args_has(args, 'C')) { if ((size = args_get(args, 'C')) == NULL) { - ctx->error(ctx, "missing size"); + cmdq_error(cmdq, "missing size"); return (CMD_RETURN_ERROR); } if (sscanf(size, "%u,%u", &w, &h) != 2) { - ctx->error(ctx, "bad size argument"); + cmdq_error(cmdq, "bad size argument"); return (CMD_RETURN_ERROR); } if (w < PANE_MINIMUM || w > 5000 || h < PANE_MINIMUM || h > 5000) { - ctx->error(ctx, "size too small or too big"); + cmdq_error(cmdq, "size too small or too big"); return (CMD_RETURN_ERROR); } if (!(c->flags & CLIENT_CONTROL)) { - ctx->error(ctx, "not a control client"); + cmdq_error(cmdq, "not a control client"); return (CMD_RETURN_ERROR); } if (tty_set_size(&c->tty, w, h)) diff --git a/cmd-rename-session.c b/cmd-rename-session.c index fb8dd4ed..c94b460b 100644 --- a/cmd-rename-session.c +++ b/cmd-rename-session.c @@ -26,7 +26,7 @@ * Change session name. */ -enum cmd_retval cmd_rename_session_exec(struct cmd *, struct cmd_ctx *); +enum cmd_retval cmd_rename_session_exec(struct cmd *, struct cmd_q *); const struct cmd_entry cmd_rename_session_entry = { "rename-session", "rename", @@ -39,7 +39,7 @@ const struct cmd_entry cmd_rename_session_entry = { }; enum cmd_retval -cmd_rename_session_exec(struct cmd *self, struct cmd_ctx *ctx) +cmd_rename_session_exec(struct cmd *self, struct cmd_q *cmdq) { struct args *args = self->args; struct session *s; @@ -47,15 +47,15 @@ cmd_rename_session_exec(struct cmd *self, struct cmd_ctx *ctx) newname = args->argv[0]; if (!session_check_name(newname)) { - ctx->error(ctx, "bad session name: %s", newname); + cmdq_error(cmdq, "bad session name: %s", newname); return (CMD_RETURN_ERROR); } if (session_find(newname) != NULL) { - ctx->error(ctx, "duplicate session: %s", newname); + cmdq_error(cmdq, "duplicate session: %s", newname); return (CMD_RETURN_ERROR); } - if ((s = cmd_find_session(ctx, args_get(args, 't'), 0)) == NULL) + if ((s = cmd_find_session(cmdq, args_get(args, 't'), 0)) == NULL) return (CMD_RETURN_ERROR); RB_REMOVE(sessions, &sessions, s); diff --git a/cmd-rename-window.c b/cmd-rename-window.c index 099ab3b7..34b03f98 100644 --- a/cmd-rename-window.c +++ b/cmd-rename-window.c @@ -26,7 +26,7 @@ * Rename a window. */ -enum cmd_retval cmd_rename_window_exec(struct cmd *, struct cmd_ctx *); +enum cmd_retval cmd_rename_window_exec(struct cmd *, struct cmd_q *); const struct cmd_entry cmd_rename_window_entry = { "rename-window", "renamew", @@ -39,13 +39,13 @@ const struct cmd_entry cmd_rename_window_entry = { }; enum cmd_retval -cmd_rename_window_exec(struct cmd *self, struct cmd_ctx *ctx) +cmd_rename_window_exec(struct cmd *self, struct cmd_q *cmdq) { struct args *args = self->args; struct session *s; struct winlink *wl; - if ((wl = cmd_find_window(ctx, args_get(args, 't'), &s)) == NULL) + if ((wl = cmd_find_window(cmdq, args_get(args, 't'), &s)) == NULL) return (CMD_RETURN_ERROR); window_set_name(wl->window, args->argv[0]); diff --git a/cmd-resize-pane.c b/cmd-resize-pane.c index dbcebbcf..f31e3258 100644 --- a/cmd-resize-pane.c +++ b/cmd-resize-pane.c @@ -27,7 +27,7 @@ */ void cmd_resize_pane_key_binding(struct cmd *, int); -enum cmd_retval cmd_resize_pane_exec(struct cmd *, struct cmd_ctx *); +enum cmd_retval cmd_resize_pane_exec(struct cmd *, struct cmd_q *); const struct cmd_entry cmd_resize_pane_entry = { "resize-pane", "resizep", @@ -82,7 +82,7 @@ cmd_resize_pane_key_binding(struct cmd *self, int key) } enum cmd_retval -cmd_resize_pane_exec(struct cmd *self, struct cmd_ctx *ctx) +cmd_resize_pane_exec(struct cmd *self, struct cmd_q *cmdq) { struct args *args = self->args; struct winlink *wl; @@ -92,7 +92,7 @@ cmd_resize_pane_exec(struct cmd *self, struct cmd_ctx *ctx) u_int adjust; int x, y; - if ((wl = cmd_find_pane(ctx, args_get(args, 't'), NULL, &wp)) == NULL) + if ((wl = cmd_find_pane(cmdq, args_get(args, 't'), NULL, &wp)) == NULL) return (CMD_RETURN_ERROR); if (args->argc == 0) @@ -100,7 +100,7 @@ cmd_resize_pane_exec(struct cmd *self, struct cmd_ctx *ctx) else { adjust = strtonum(args->argv[0], 1, INT_MAX, &errstr); if (errstr != NULL) { - ctx->error(ctx, "adjustment %s", errstr); + cmdq_error(cmdq, "adjustment %s", errstr); return (CMD_RETURN_ERROR); } } @@ -109,7 +109,7 @@ cmd_resize_pane_exec(struct cmd *self, struct cmd_ctx *ctx) x = args_strtonum(self->args, 'x', PANE_MINIMUM, INT_MAX, &cause); if (cause != NULL) { - ctx->error(ctx, "width %s", cause); + cmdq_error(cmdq, "width %s", cause); free(cause); return (CMD_RETURN_ERROR); } @@ -119,7 +119,7 @@ cmd_resize_pane_exec(struct cmd *self, struct cmd_ctx *ctx) y = args_strtonum(self->args, 'y', PANE_MINIMUM, INT_MAX, &cause); if (cause != NULL) { - ctx->error(ctx, "height %s", cause); + cmdq_error(cmdq, "height %s", cause); free(cause); return (CMD_RETURN_ERROR); } diff --git a/cmd-respawn-pane.c b/cmd-respawn-pane.c index 3860dc93..0aae0331 100644 --- a/cmd-respawn-pane.c +++ b/cmd-respawn-pane.c @@ -28,7 +28,7 @@ * Respawn a pane (restart the command). Kill existing if -k given. */ -enum cmd_retval cmd_respawn_pane_exec(struct cmd *, struct cmd_ctx *); +enum cmd_retval cmd_respawn_pane_exec(struct cmd *, struct cmd_q *); const struct cmd_entry cmd_respawn_pane_entry = { "respawn-pane", "respawnp", @@ -41,7 +41,7 @@ const struct cmd_entry cmd_respawn_pane_entry = { }; enum cmd_retval -cmd_respawn_pane_exec(struct cmd *self, struct cmd_ctx *ctx) +cmd_respawn_pane_exec(struct cmd *self, struct cmd_q *cmdq) { struct args *args = self->args; struct winlink *wl; @@ -53,14 +53,14 @@ cmd_respawn_pane_exec(struct cmd *self, struct cmd_ctx *ctx) char *cause; u_int idx; - if ((wl = cmd_find_pane(ctx, args_get(args, 't'), &s, &wp)) == NULL) + if ((wl = cmd_find_pane(cmdq, args_get(args, 't'), &s, &wp)) == NULL) return (CMD_RETURN_ERROR); w = wl->window; if (!args_has(self->args, 'k') && wp->fd != -1) { if (window_pane_index(wp, &idx) != 0) fatalx("index not found"); - ctx->error(ctx, "pane still active: %s:%u.%u", + cmdq_error(cmdq, "pane still active: %s:%u.%u", s->name, wl->idx, idx); return (CMD_RETURN_ERROR); } @@ -79,7 +79,7 @@ cmd_respawn_pane_exec(struct cmd *self, struct cmd_ctx *ctx) else cmd = NULL; if (window_pane_spawn(wp, cmd, NULL, NULL, &env, s->tio, &cause) != 0) { - ctx->error(ctx, "respawn pane failed: %s", cause); + cmdq_error(cmdq, "respawn pane failed: %s", cause); free(cause); environ_free(&env); return (CMD_RETURN_ERROR); diff --git a/cmd-respawn-window.c b/cmd-respawn-window.c index a178a2ba..646882b0 100644 --- a/cmd-respawn-window.c +++ b/cmd-respawn-window.c @@ -27,7 +27,7 @@ * Respawn a window (restart the command). Kill existing if -k given. */ -enum cmd_retval cmd_respawn_window_exec(struct cmd *, struct cmd_ctx *); +enum cmd_retval cmd_respawn_window_exec(struct cmd *, struct cmd_q *); const struct cmd_entry cmd_respawn_window_entry = { "respawn-window", "respawnw", @@ -40,7 +40,7 @@ const struct cmd_entry cmd_respawn_window_entry = { }; enum cmd_retval -cmd_respawn_window_exec(struct cmd *self, struct cmd_ctx *ctx) +cmd_respawn_window_exec(struct cmd *self, struct cmd_q *cmdq) { struct args *args = self->args; struct winlink *wl; @@ -51,7 +51,7 @@ cmd_respawn_window_exec(struct cmd *self, struct cmd_ctx *ctx) const char *cmd; char *cause; - if ((wl = cmd_find_window(ctx, args_get(args, 't'), &s)) == NULL) + if ((wl = cmd_find_window(cmdq, args_get(args, 't'), &s)) == NULL) return (CMD_RETURN_ERROR); w = wl->window; @@ -59,7 +59,7 @@ cmd_respawn_window_exec(struct cmd *self, struct cmd_ctx *ctx) TAILQ_FOREACH(wp, &w->panes, entry) { if (wp->fd == -1) continue; - ctx->error(ctx, + cmdq_error(cmdq, "window still active: %s:%d", s->name, wl->idx); return (CMD_RETURN_ERROR); } @@ -81,7 +81,7 @@ cmd_respawn_window_exec(struct cmd *self, struct cmd_ctx *ctx) else cmd = NULL; if (window_pane_spawn(wp, cmd, NULL, NULL, &env, s->tio, &cause) != 0) { - ctx->error(ctx, "respawn window failed: %s", cause); + cmdq_error(cmdq, "respawn window failed: %s", cause); free(cause); environ_free(&env); server_destroy_pane(wp); diff --git a/cmd-rotate-window.c b/cmd-rotate-window.c index 7a6c60b3..7af592b3 100644 --- a/cmd-rotate-window.c +++ b/cmd-rotate-window.c @@ -25,7 +25,7 @@ */ void cmd_rotate_window_key_binding(struct cmd *, int); -enum cmd_retval cmd_rotate_window_exec(struct cmd *, struct cmd_ctx *); +enum cmd_retval cmd_rotate_window_exec(struct cmd *, struct cmd_q *); const struct cmd_entry cmd_rotate_window_entry = { "rotate-window", "rotatew", @@ -46,7 +46,7 @@ cmd_rotate_window_key_binding(struct cmd *self, int key) } enum cmd_retval -cmd_rotate_window_exec(struct cmd *self, struct cmd_ctx *ctx) +cmd_rotate_window_exec(struct cmd *self, struct cmd_q *cmdq) { struct args *args = self->args; struct winlink *wl; @@ -55,7 +55,7 @@ cmd_rotate_window_exec(struct cmd *self, struct cmd_ctx *ctx) struct layout_cell *lc; u_int sx, sy, xoff, yoff; - if ((wl = cmd_find_window(ctx, args_get(args, 't'), NULL)) == NULL) + if ((wl = cmd_find_window(cmdq, args_get(args, 't'), NULL)) == NULL) return (CMD_RETURN_ERROR); w = wl->window; diff --git a/cmd-run-shell.c b/cmd-run-shell.c index 3942fa11..5452ceff 100644 --- a/cmd-run-shell.c +++ b/cmd-run-shell.c @@ -29,7 +29,7 @@ * Runs a command without a window. */ -enum cmd_retval cmd_run_shell_exec(struct cmd *, struct cmd_ctx *); +enum cmd_retval cmd_run_shell_exec(struct cmd *, struct cmd_q *); void cmd_run_shell_callback(struct job *); void cmd_run_shell_free(void *); @@ -37,8 +37,8 @@ void cmd_run_shell_print(struct job *, const char *); const struct cmd_entry cmd_run_shell_entry = { "run-shell", "run", - "t:", 1, 1, - CMD_TARGET_PANE_USAGE " command", + "bt:", 1, 1, + "[-b] " CMD_TARGET_PANE_USAGE " shell-command", 0, NULL, NULL, @@ -47,7 +47,8 @@ const struct cmd_entry cmd_run_shell_entry = { struct cmd_run_shell_data { char *cmd; - struct cmd_ctx *ctx; + struct cmd_q *cmdq; + int bflag; u_int wp_id; }; @@ -55,12 +56,11 @@ void cmd_run_shell_print(struct job *job, const char *msg) { struct cmd_run_shell_data *cdata = job->data; - struct cmd_ctx *ctx = cdata->ctx; struct window_pane *wp; wp = window_pane_find_by_id(cdata->wp_id); if (wp == NULL) { - ctx->print(ctx, "%s", msg); + cmdq_print(cdata->cmdq, "%s", msg); return; } @@ -71,7 +71,7 @@ cmd_run_shell_print(struct job *job, const char *msg) } enum cmd_retval -cmd_run_shell_exec(struct cmd *self, struct cmd_ctx *ctx) +cmd_run_shell_exec(struct cmd *self, struct cmd_q *cmdq) { struct args *args = self->args; struct cmd_run_shell_data *cdata; @@ -81,7 +81,7 @@ cmd_run_shell_exec(struct cmd *self, struct cmd_ctx *ctx) struct window_pane *wp; struct format_tree *ft; - wl = cmd_find_pane(ctx, args_get(args, 't'), &s, &wp); + wl = cmd_find_pane(cmdq, args_get(args, 't'), &s, &wp); if (wl == NULL) return (CMD_RETURN_ERROR); @@ -94,35 +94,37 @@ cmd_run_shell_exec(struct cmd *self, struct cmd_ctx *ctx) cdata = xmalloc(sizeof *cdata); cdata->cmd = shellcmd; + cdata->bflag = args_has(args, 'b'); cdata->wp_id = wp->id; - cdata->ctx = ctx; - cmd_ref_ctx(ctx); + cdata->cmdq = cmdq; + cmdq->references++; job_run(shellcmd, cmd_run_shell_callback, cmd_run_shell_free, cdata); - return (CMD_RETURN_YIELD); /* don't let client exit */ + if (cdata->bflag) + return (CMD_RETURN_NORMAL); + return (CMD_RETURN_WAIT); } void cmd_run_shell_callback(struct job *job) { struct cmd_run_shell_data *cdata = job->data; - struct cmd_ctx *ctx = cdata->ctx; + struct cmd_q *cmdq = cdata->cmdq; char *cmd, *msg, *line; size_t size; int retcode; u_int lines; - if (ctx->cmdclient != NULL && ctx->cmdclient->flags & CLIENT_DEAD) - return; - if (ctx->curclient != NULL && ctx->curclient->flags & CLIENT_DEAD) + if (cmdq->dead) return; + cmd = cdata->cmd; lines = 0; do { if ((line = evbuffer_readline(job->event->input)) != NULL) { - cmd_run_shell_print (job, line); + cmd_run_shell_print(job, line); free(line); lines++; } @@ -140,8 +142,6 @@ cmd_run_shell_callback(struct job *job) free(line); } - cmd = cdata->cmd; - msg = NULL; if (WIFEXITED(job->status)) { if ((retcode = WEXITSTATUS(job->status)) != 0) @@ -152,7 +152,7 @@ cmd_run_shell_callback(struct job *job) } if (msg != NULL) { if (lines == 0) - ctx->info(ctx, "%s", msg); + cmdq_info(cmdq, "%s", msg); else cmd_run_shell_print(job, msg); free(msg); @@ -163,11 +163,10 @@ void cmd_run_shell_free(void *data) { struct cmd_run_shell_data *cdata = data; - struct cmd_ctx *ctx = cdata->ctx; + struct cmd_q *cmdq = cdata->cmdq; - if (ctx->cmdclient != NULL) - ctx->cmdclient->flags |= CLIENT_EXIT; - cmd_free_ctx(ctx); + if (!cmdq_free(cmdq) && !cdata->bflag) + cmdq_continue(cmdq); free(cdata->cmd); free(cdata); diff --git a/cmd-save-buffer.c b/cmd-save-buffer.c index 6031a562..29f71837 100644 --- a/cmd-save-buffer.c +++ b/cmd-save-buffer.c @@ -22,6 +22,7 @@ #include #include #include +#include #include "tmux.h" @@ -29,7 +30,7 @@ * Saves a paste buffer to a file. */ -enum cmd_retval cmd_save_buffer_exec(struct cmd *, struct cmd_ctx *); +enum cmd_retval cmd_save_buffer_exec(struct cmd *, struct cmd_q *); const struct cmd_entry cmd_save_buffer_entry = { "save-buffer", "saveb", @@ -41,83 +42,132 @@ const struct cmd_entry cmd_save_buffer_entry = { cmd_save_buffer_exec }; +const struct cmd_entry cmd_show_buffer_entry = { + "show-buffer", "showb", + "b:", 0, 0, + CMD_BUFFER_USAGE, + 0, + NULL, + NULL, + cmd_save_buffer_exec +}; + enum cmd_retval -cmd_save_buffer_exec(struct cmd *self, struct cmd_ctx *ctx) +cmd_save_buffer_exec(struct cmd *self, struct cmd_q *cmdq) { struct args *args = self->args; struct client *c; struct session *s; struct paste_buffer *pb; const char *path, *newpath, *wd; - char *cause; + char *cause, *start, *end; + size_t size, used; int buffer; mode_t mask; FILE *f; + char *msg; + size_t msglen; if (!args_has(args, 'b')) { if ((pb = paste_get_top(&global_buffers)) == NULL) { - ctx->error(ctx, "no buffers"); + cmdq_error(cmdq, "no buffers"); return (CMD_RETURN_ERROR); } } else { buffer = args_strtonum(args, 'b', 0, INT_MAX, &cause); if (cause != NULL) { - ctx->error(ctx, "buffer %s", cause); + cmdq_error(cmdq, "buffer %s", cause); free(cause); return (CMD_RETURN_ERROR); } pb = paste_get_index(&global_buffers, buffer); if (pb == NULL) { - ctx->error(ctx, "no buffer %d", buffer); + cmdq_error(cmdq, "no buffer %d", buffer); return (CMD_RETURN_ERROR); } } - path = args->argv[0]; + if (self->entry == &cmd_show_buffer_entry) + path = "-"; + else + path = args->argv[0]; if (strcmp(path, "-") == 0) { - c = ctx->curclient; - if (c == NULL || !(c->flags & CLIENT_CONTROL)) - c = ctx->cmdclient; + c = cmdq->client; if (c == NULL) { - ctx->error(ctx, "can't write to stdout"); + cmdq_error(cmdq, "can't write to stdout"); return (CMD_RETURN_ERROR); } - evbuffer_add(c->stdout_data, pb->data, pb->size); - server_push_stdout(c); - } else { - c = ctx->cmdclient; - if (c != NULL) - wd = c->cwd; - else if ((s = cmd_current_session(ctx, 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"); - else - f = fopen(path, "wb"); - umask(mask); - if (f == NULL) { - ctx->error(ctx, "%s: %s", path, strerror(errno)); - return (CMD_RETURN_ERROR); - } - if (fwrite(pb->data, 1, pb->size, f) != pb->size) { - ctx->error(ctx, "%s: fwrite error", path); - fclose(f); - return (CMD_RETURN_ERROR); - } - fclose(f); + if (c->session == NULL || (c->flags & CLIENT_CONTROL)) + goto do_stdout; + 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"); + else + f = fopen(path, "wb"); + umask(mask); + if (f == NULL) { + cmdq_error(cmdq, "%s: %s", path, strerror(errno)); + return (CMD_RETURN_ERROR); + } + if (fwrite(pb->data, 1, pb->size, f) != pb->size) { + cmdq_error(cmdq, "%s: fwrite error", path); + fclose(f); + return (CMD_RETURN_ERROR); + } + fclose(f); + + return (CMD_RETURN_NORMAL); + +do_stdout: + evbuffer_add(c->stdout_data, pb->data, pb->size); + server_push_stdout(c); + return (CMD_RETURN_NORMAL); + +do_print: + if (pb->size > (INT_MAX / 4) - 1) { + cmdq_error(cmdq, "buffer too big"); + return (CMD_RETURN_ERROR); + } + msg = NULL; + msglen = 0; + + used = 0; + while (used != pb->size) { + start = pb->data + used; + end = memchr(start, '\n', pb->size - used); + if (end != NULL) + size = end - start; + else + size = pb->size - used; + + msglen = size * 4 + 1; + msg = xrealloc(msg, 1, msglen); + + strvisx(msg, start, size, VIS_OCTAL|VIS_TAB); + cmdq_print(cmdq, "%s", msg); + + used += size + (end != NULL); + } + + free(msg); return (CMD_RETURN_NORMAL); } diff --git a/cmd-select-layout.c b/cmd-select-layout.c index c5f64a07..4b01a69d 100644 --- a/cmd-select-layout.c +++ b/cmd-select-layout.c @@ -25,7 +25,7 @@ */ void cmd_select_layout_key_binding(struct cmd *, int); -enum cmd_retval cmd_select_layout_exec(struct cmd *, struct cmd_ctx *); +enum cmd_retval cmd_select_layout_exec(struct cmd *, struct cmd_q *); const struct cmd_entry cmd_select_layout_entry = { "select-layout", "selectl", @@ -83,14 +83,14 @@ cmd_select_layout_key_binding(struct cmd *self, int key) } enum cmd_retval -cmd_select_layout_exec(struct cmd *self, struct cmd_ctx *ctx) +cmd_select_layout_exec(struct cmd *self, struct cmd_q *cmdq) { struct args *args = self->args; struct winlink *wl; const char *layoutname; int next, previous, layout; - if ((wl = cmd_find_window(ctx, args_get(args, 't'), NULL)) == NULL) + if ((wl = cmd_find_window(cmdq, args_get(args, 't'), NULL)) == NULL) return (CMD_RETURN_ERROR); next = self->entry == &cmd_next_layout_entry; @@ -106,7 +106,7 @@ cmd_select_layout_exec(struct cmd *self, struct cmd_ctx *ctx) else layout = layout_set_previous(wl->window); server_redraw_window(wl->window); - ctx->info(ctx, "arranging in: %s", layout_set_name(layout)); + cmdq_info(cmdq, "arranging in: %s", layout_set_name(layout)); return (CMD_RETURN_NORMAL); } @@ -117,18 +117,18 @@ cmd_select_layout_exec(struct cmd *self, struct cmd_ctx *ctx) if (layout != -1) { layout = layout_set_select(wl->window, layout); server_redraw_window(wl->window); - ctx->info(ctx, "arranging in: %s", layout_set_name(layout)); + cmdq_info(cmdq, "arranging in: %s", layout_set_name(layout)); return (CMD_RETURN_NORMAL); } if (args->argc != 0) { layoutname = args->argv[0]; if (layout_parse(wl->window, layoutname) == -1) { - ctx->error(ctx, "can't set layout: %s", layoutname); + cmdq_error(cmdq, "can't set layout: %s", layoutname); return (CMD_RETURN_ERROR); } server_redraw_window(wl->window); - ctx->info(ctx, "arranging in: %s", layoutname); + cmdq_info(cmdq, "arranging in: %s", layoutname); } return (CMD_RETURN_NORMAL); } diff --git a/cmd-select-pane.c b/cmd-select-pane.c index fce34784..459e98cf 100644 --- a/cmd-select-pane.c +++ b/cmd-select-pane.c @@ -25,7 +25,7 @@ */ void cmd_select_pane_key_binding(struct cmd *, int); -enum cmd_retval cmd_select_pane_exec(struct cmd *, struct cmd_ctx *); +enum cmd_retval cmd_select_pane_exec(struct cmd *, struct cmd_q *); const struct cmd_entry cmd_select_pane_entry = { "select-pane", "selectp", @@ -64,19 +64,19 @@ cmd_select_pane_key_binding(struct cmd *self, int key) } enum cmd_retval -cmd_select_pane_exec(struct cmd *self, struct cmd_ctx *ctx) +cmd_select_pane_exec(struct cmd *self, struct cmd_q *cmdq) { struct args *args = self->args; struct winlink *wl; struct window_pane *wp; if (self->entry == &cmd_last_pane_entry || args_has(args, 'l')) { - wl = cmd_find_window(ctx, args_get(args, 't'), NULL); + wl = cmd_find_window(cmdq, args_get(args, 't'), NULL); if (wl == NULL) return (CMD_RETURN_ERROR); if (wl->window->last == NULL) { - ctx->error(ctx, "no last pane"); + cmdq_error(cmdq, "no last pane"); return (CMD_RETURN_ERROR); } @@ -87,11 +87,11 @@ cmd_select_pane_exec(struct cmd *self, struct cmd_ctx *ctx) return (CMD_RETURN_NORMAL); } - if ((wl = cmd_find_pane(ctx, args_get(args, 't'), NULL, &wp)) == NULL) + if ((wl = cmd_find_pane(cmdq, args_get(args, 't'), NULL, &wp)) == NULL) return (CMD_RETURN_ERROR); if (!window_pane_visible(wp)) { - ctx->error(ctx, "pane not visible"); + cmdq_error(cmdq, "pane not visible"); return (CMD_RETURN_ERROR); } @@ -104,7 +104,7 @@ cmd_select_pane_exec(struct cmd *self, struct cmd_ctx *ctx) else if (args_has(self->args, 'D')) wp = window_pane_find_down(wp); if (wp == NULL) { - ctx->error(ctx, "pane not found"); + cmdq_error(cmdq, "pane not found"); return (CMD_RETURN_ERROR); } diff --git a/cmd-select-window.c b/cmd-select-window.c index 70d60bed..6206ae4b 100644 --- a/cmd-select-window.c +++ b/cmd-select-window.c @@ -27,7 +27,7 @@ */ void cmd_select_window_key_binding(struct cmd *, int); -enum cmd_retval cmd_select_window_exec(struct cmd *, struct cmd_ctx *); +enum cmd_retval cmd_select_window_exec(struct cmd *, struct cmd_q *); const struct cmd_entry cmd_select_window_entry = { "select-window", "selectw", @@ -84,7 +84,7 @@ cmd_select_window_key_binding(struct cmd *self, int key) } enum cmd_retval -cmd_select_window_exec(struct cmd *self, struct cmd_ctx *ctx) +cmd_select_window_exec(struct cmd *self, struct cmd_q *cmdq) { struct args *args = self->args; struct winlink *wl; @@ -102,31 +102,31 @@ cmd_select_window_exec(struct cmd *self, struct cmd_ctx *ctx) last = 1; if (next || previous || last) { - s = cmd_find_session(ctx, args_get(args, 't'), 0); + s = cmd_find_session(cmdq, args_get(args, 't'), 0); if (s == NULL) return (CMD_RETURN_ERROR); activity = args_has(self->args, 'a'); if (next) { if (session_next(s, activity) != 0) { - ctx->error(ctx, "no next window"); + cmdq_error(cmdq, "no next window"); return (CMD_RETURN_ERROR); } } else if (previous) { if (session_previous(s, activity) != 0) { - ctx->error(ctx, "no previous window"); + cmdq_error(cmdq, "no previous window"); return (CMD_RETURN_ERROR); } } else { if (session_last(s) != 0) { - ctx->error(ctx, "no last window"); + cmdq_error(cmdq, "no last window"); return (CMD_RETURN_ERROR); } } server_redraw_session(s); } else { - wl = cmd_find_window(ctx, args_get(args, 't'), &s); + wl = cmd_find_window(cmdq, args_get(args, 't'), &s); if (wl == NULL) return (CMD_RETURN_ERROR); @@ -136,7 +136,7 @@ cmd_select_window_exec(struct cmd *self, struct cmd_ctx *ctx) */ if (args_has(self->args, 'T') && wl == s->curw) { if (session_last(s) != 0) { - ctx->error(ctx, "no last window"); + cmdq_error(cmdq, "no last window"); return (-1); } server_redraw_session(s); diff --git a/cmd-send-keys.c b/cmd-send-keys.c index f6124d3a..3ee3dbe6 100644 --- a/cmd-send-keys.c +++ b/cmd-send-keys.c @@ -27,7 +27,7 @@ * Send keys to client. */ -enum cmd_retval cmd_send_keys_exec(struct cmd *, struct cmd_ctx *); +enum cmd_retval cmd_send_keys_exec(struct cmd *, struct cmd_q *); const struct cmd_entry cmd_send_keys_entry = { "send-keys", "send", @@ -39,8 +39,18 @@ const struct cmd_entry cmd_send_keys_entry = { cmd_send_keys_exec }; +const struct cmd_entry cmd_send_prefix_entry = { + "send-prefix", NULL, + "2t:", 0, 0, + "[-2] " CMD_TARGET_PANE_USAGE, + 0, + NULL, + NULL, + cmd_send_keys_exec +}; + enum cmd_retval -cmd_send_keys_exec(struct cmd *self, struct cmd_ctx *ctx) +cmd_send_keys_exec(struct cmd *self, struct cmd_q *cmdq) { struct args *args = self->args; struct window_pane *wp; @@ -49,9 +59,18 @@ cmd_send_keys_exec(struct cmd *self, struct cmd_ctx *ctx) const char *str; int i, key; - if (cmd_find_pane(ctx, args_get(args, 't'), &s, &wp) == NULL) + if (cmd_find_pane(cmdq, args_get(args, 't'), &s, &wp) == NULL) return (CMD_RETURN_ERROR); + if (self->entry == &cmd_send_prefix_entry) { + if (args_has(args, '2')) + key = options_get_number(&s->options, "prefix2"); + else + key = options_get_number(&s->options, "prefix"); + window_pane_key(wp, s, key); + return (CMD_RETURN_NORMAL); + } + if (args_has(args, 'R')) { ictx = &wp->ictx; diff --git a/cmd-server-info.c b/cmd-server-info.c index cefb70f4..a26fe705 100644 --- a/cmd-server-info.c +++ b/cmd-server-info.c @@ -31,7 +31,7 @@ * Show various information about server. */ -enum cmd_retval cmd_server_info_exec(struct cmd *, struct cmd_ctx *); +enum cmd_retval cmd_server_info_exec(struct cmd *, struct cmd_q *); const struct cmd_entry cmd_server_info_entry = { "server-info", "info", @@ -44,7 +44,7 @@ const struct cmd_entry cmd_server_info_entry = { }; enum cmd_retval -cmd_server_info_exec(unused struct cmd *self, struct cmd_ctx *ctx) +cmd_server_info_exec(unused struct cmd *self, struct cmd_q *cmdq) { struct tty_term *term; struct client *c; @@ -66,47 +66,47 @@ cmd_server_info_exec(unused struct cmd *self, struct cmd_ctx *ctx) tim = ctime(&start_time); *strchr(tim, '\n') = '\0'; - ctx->print(ctx, "pid %ld, started %s", (long) getpid(), tim); - ctx->print( - ctx, "socket path %s, debug level %d", socket_path, debug_level); + cmdq_print(cmdq, "pid %ld, started %s", (long) getpid(), tim); + cmdq_print(cmdq, "socket path %s, debug level %d", socket_path, + debug_level); if (uname(&un) >= 0) { - ctx->print(ctx, "system is %s %s %s %s", + cmdq_print(cmdq, "system is %s %s %s %s", un.sysname, un.release, un.version, un.machine); } if (cfg_file != NULL) - ctx->print(ctx, "configuration file is %s", cfg_file); + cmdq_print(cmdq, "configuration file is %s", cfg_file); else - ctx->print(ctx, "configuration file not specified"); - ctx->print(ctx, "protocol version is %d", PROTOCOL_VERSION); - ctx->print(ctx, "%s", ""); + cmdq_print(cmdq, "configuration file not specified"); + cmdq_print(cmdq, "protocol version is %d", PROTOCOL_VERSION); + cmdq_print(cmdq, "%s", ""); - ctx->print(ctx, "Clients:"); + cmdq_print(cmdq, "Clients:"); for (i = 0; i < ARRAY_LENGTH(&clients); i++) { c = ARRAY_ITEM(&clients, i); if (c == NULL || c->session == NULL) continue; - ctx->print(ctx,"%2d: %s (%d, %d): %s [%ux%u %s bs=%hho " + cmdq_print(cmdq,"%2d: %s (%d, %d): %s [%ux%u %s bs=%hho " "class=%u] [flags=0x%x/0x%x, references=%u]", i, c->tty.path, c->ibuf.fd, c->tty.fd, c->session->name, c->tty.sx, c->tty.sy, c->tty.termname, c->tty.tio.c_cc[VERASE], c->tty.class, c->flags, c->tty.flags, c->references); } - ctx->print(ctx, "%s", ""); + cmdq_print(cmdq, "%s", ""); - ctx->print(ctx, "Sessions: [%zu]", sizeof (struct grid_cell)); + cmdq_print(cmdq, "Sessions: [%zu]", sizeof (struct grid_cell)); RB_FOREACH(s, sessions, &sessions) { t = s->creation_time.tv_sec; tim = ctime(&t); *strchr(tim, '\n') = '\0'; - ctx->print(ctx, "%2u: %s: %u windows (created %s) [%ux%u] " + cmdq_print(cmdq, "%2u: %s: %u windows (created %s) [%ux%u] " "[flags=0x%x]", s->idx, s->name, winlink_count(&s->windows), tim, s->sx, s->sy, s->flags); RB_FOREACH(wl, winlinks, &s->windows) { w = wl->window; - ctx->print(ctx, "%4u: %s [%ux%u] [flags=0x%x, " + cmdq_print(cmdq, "%4u: %s [%ux%u] [flags=0x%x, " "references=%u, last layout=%d]", wl->idx, w->name, w->sx, w->sy, w->flags, w->references, w->lastlayout); @@ -122,7 +122,7 @@ cmd_server_info_exec(unused struct cmd *self, struct cmd_ctx *ctx) size += gl->cellsize * sizeof *gl->celldata; } - ctx->print(ctx, + cmdq_print(cmdq, "%6u: %s %lu %d %u/%u, %zu bytes", j, wp->tty, (u_long) wp->pid, wp->fd, lines, gd->hsize + gd->sy, size); @@ -130,43 +130,43 @@ cmd_server_info_exec(unused struct cmd *self, struct cmd_ctx *ctx) } } } - ctx->print(ctx, "%s", ""); + cmdq_print(cmdq, "%s", ""); - ctx->print(ctx, "Terminals:"); + cmdq_print(cmdq, "Terminals:"); LIST_FOREACH(term, &tty_terms, entry) { - ctx->print(ctx, "%s [references=%u, flags=0x%x]:", + cmdq_print(cmdq, "%s [references=%u, flags=0x%x]:", term->name, term->references, term->flags); for (i = 0; i < NTTYCODE; i++) { ent = &tty_term_codes[i]; code = &term->codes[ent->code]; switch (code->type) { case TTYCODE_NONE: - ctx->print(ctx, "%2u: %s: [missing]", + cmdq_print(cmdq, "%2u: %s: [missing]", ent->code, ent->name); break; case TTYCODE_STRING: strnvis(out, code->value.string, sizeof out, VIS_OCTAL|VIS_TAB|VIS_NL); - ctx->print(ctx, "%2u: %s: (string) %s", + cmdq_print(cmdq, "%2u: %s: (string) %s", ent->code, ent->name, out); break; case TTYCODE_NUMBER: - ctx->print(ctx, "%2u: %s: (number) %d", + cmdq_print(cmdq, "%2u: %s: (number) %d", ent->code, ent->name, code->value.number); break; case TTYCODE_FLAG: - ctx->print(ctx, "%2u: %s: (flag) %s", + cmdq_print(cmdq, "%2u: %s: (flag) %s", ent->code, ent->name, code->value.flag ? "true" : "false"); break; } } } - ctx->print(ctx, "%s", ""); + cmdq_print(cmdq, "%s", ""); - ctx->print(ctx, "Jobs:"); + cmdq_print(cmdq, "Jobs:"); LIST_FOREACH(job, &all_jobs, lentry) { - ctx->print(ctx, "%s [fd=%d, pid=%d, status=%d]", + cmdq_print(cmdq, "%s [fd=%d, pid=%d, status=%d]", job->cmd, job->fd, job->pid, job->status); } diff --git a/cmd-set-buffer.c b/cmd-set-buffer.c index e3b1656b..46450e21 100644 --- a/cmd-set-buffer.c +++ b/cmd-set-buffer.c @@ -27,7 +27,7 @@ * Add or set a paste buffer. */ -enum cmd_retval cmd_set_buffer_exec(struct cmd *, struct cmd_ctx *); +enum cmd_retval cmd_set_buffer_exec(struct cmd *, struct cmd_q *); const struct cmd_entry cmd_set_buffer_entry = { "set-buffer", "setb", @@ -40,7 +40,7 @@ const struct cmd_entry cmd_set_buffer_entry = { }; enum cmd_retval -cmd_set_buffer_exec(struct cmd *self, struct cmd_ctx *ctx) +cmd_set_buffer_exec(struct cmd *self, struct cmd_q *cmdq) { struct args *args = self->args; u_int limit; @@ -60,14 +60,14 @@ cmd_set_buffer_exec(struct cmd *self, struct cmd_ctx *ctx) buffer = args_strtonum(args, 'b', 0, INT_MAX, &cause); if (cause != NULL) { - ctx->error(ctx, "buffer %s", cause); + cmdq_error(cmdq, "buffer %s", cause); free(cause); free(pdata); return (CMD_RETURN_ERROR); } if (paste_replace(&global_buffers, buffer, pdata, psize) != 0) { - ctx->error(ctx, "no buffer %d", buffer); + cmdq_error(cmdq, "no buffer %d", buffer); free(pdata); return (CMD_RETURN_ERROR); } diff --git a/cmd-set-environment.c b/cmd-set-environment.c index 9cebc951..6e75a294 100644 --- a/cmd-set-environment.c +++ b/cmd-set-environment.c @@ -27,7 +27,7 @@ * Set an environment variable. */ -enum cmd_retval cmd_set_environment_exec(struct cmd *, struct cmd_ctx *); +enum cmd_retval cmd_set_environment_exec(struct cmd *, struct cmd_q *); const struct cmd_entry cmd_set_environment_entry = { "set-environment", "setenv", @@ -40,7 +40,7 @@ const struct cmd_entry cmd_set_environment_entry = { }; enum cmd_retval -cmd_set_environment_exec(struct cmd *self, struct cmd_ctx *ctx) +cmd_set_environment_exec(struct cmd *self, struct cmd_q *cmdq) { struct args *args = self->args; struct session *s; @@ -49,11 +49,11 @@ cmd_set_environment_exec(struct cmd *self, struct cmd_ctx *ctx) name = args->argv[0]; if (*name == '\0') { - ctx->error(ctx, "empty variable name"); + cmdq_error(cmdq, "empty variable name"); return (CMD_RETURN_ERROR); } if (strchr(name, '=') != NULL) { - ctx->error(ctx, "variable name contains ="); + cmdq_error(cmdq, "variable name contains ="); return (CMD_RETURN_ERROR); } @@ -65,26 +65,26 @@ cmd_set_environment_exec(struct cmd *self, struct cmd_ctx *ctx) if (args_has(self->args, 'g')) env = &global_environ; else { - if ((s = cmd_find_session(ctx, args_get(args, 't'), 0)) == NULL) + if ((s = cmd_find_session(cmdq, args_get(args, 't'), 0)) == NULL) return (CMD_RETURN_ERROR); env = &s->environ; } if (args_has(self->args, 'u')) { if (value != NULL) { - ctx->error(ctx, "can't specify a value with -u"); + cmdq_error(cmdq, "can't specify a value with -u"); return (CMD_RETURN_ERROR); } environ_unset(env, name); } else if (args_has(self->args, 'r')) { if (value != NULL) { - ctx->error(ctx, "can't specify a value with -r"); + cmdq_error(cmdq, "can't specify a value with -r"); return (CMD_RETURN_ERROR); } environ_set(env, name, NULL); } else { if (value == NULL) { - ctx->error(ctx, "no value specified"); + cmdq_error(cmdq, "no value specified"); return (CMD_RETURN_ERROR); } environ_set(env, name, value); diff --git a/cmd-show-environment.c b/cmd-show-environment.c index e7b9f7c9..cb53e84c 100644 --- a/cmd-show-environment.c +++ b/cmd-show-environment.c @@ -27,7 +27,7 @@ * Show environment. */ -enum cmd_retval cmd_show_environment_exec(struct cmd *, struct cmd_ctx *); +enum cmd_retval cmd_show_environment_exec(struct cmd *, struct cmd_q *); const struct cmd_entry cmd_show_environment_entry = { "show-environment", "showenv", @@ -40,7 +40,7 @@ const struct cmd_entry cmd_show_environment_entry = { }; enum cmd_retval -cmd_show_environment_exec(struct cmd *self, struct cmd_ctx *ctx) +cmd_show_environment_exec(struct cmd *self, struct cmd_q *cmdq) { struct args *args = self->args; struct session *s; @@ -50,7 +50,7 @@ cmd_show_environment_exec(struct cmd *self, struct cmd_ctx *ctx) if (args_has(self->args, 'g')) env = &global_environ; else { - if ((s = cmd_find_session(ctx, args_get(args, 't'), 0)) == NULL) + if ((s = cmd_find_session(cmdq, args_get(args, 't'), 0)) == NULL) return (CMD_RETURN_ERROR); env = &s->environ; } @@ -58,21 +58,21 @@ cmd_show_environment_exec(struct cmd *self, struct cmd_ctx *ctx) if (args->argc != 0) { envent = environ_find(env, args->argv[0]); if (envent == NULL) { - ctx->error(ctx, "unknown variable: %s", args->argv[0]); + cmdq_error(cmdq, "unknown variable: %s", args->argv[0]); return (CMD_RETURN_ERROR); } if (envent->value != NULL) - ctx->print(ctx, "%s=%s", envent->name, envent->value); + cmdq_print(cmdq, "%s=%s", envent->name, envent->value); else - ctx->print(ctx, "-%s", envent->name); + cmdq_print(cmdq, "-%s", envent->name); return (CMD_RETURN_NORMAL); } RB_FOREACH(envent, environ, env) { if (envent->value != NULL) - ctx->print(ctx, "%s=%s", envent->name, envent->value); + cmdq_print(cmdq, "%s=%s", envent->name, envent->value); else - ctx->print(ctx, "-%s", envent->name); + cmdq_print(cmdq, "-%s", envent->name); } return (CMD_RETURN_NORMAL); diff --git a/cmd-show-messages.c b/cmd-show-messages.c index 8394e3de..cbf083a7 100644 --- a/cmd-show-messages.c +++ b/cmd-show-messages.c @@ -27,7 +27,7 @@ * Show client message log. */ -enum cmd_retval cmd_show_messages_exec(struct cmd *, struct cmd_ctx *); +enum cmd_retval cmd_show_messages_exec(struct cmd *, struct cmd_q *); const struct cmd_entry cmd_show_messages_entry = { "show-messages", "showmsgs", @@ -40,7 +40,7 @@ const struct cmd_entry cmd_show_messages_entry = { }; enum cmd_retval -cmd_show_messages_exec(struct cmd *self, struct cmd_ctx *ctx) +cmd_show_messages_exec(struct cmd *self, struct cmd_q *cmdq) { struct args *args = self->args; struct client *c; @@ -48,7 +48,7 @@ cmd_show_messages_exec(struct cmd *self, struct cmd_ctx *ctx) char *tim; u_int i; - if ((c = cmd_find_client(ctx, args_get(args, 't'), 0)) == NULL) + if ((c = cmd_find_client(cmdq, args_get(args, 't'), 0)) == NULL) return (CMD_RETURN_ERROR); for (i = 0; i < ARRAY_LENGTH(&c->message_log); i++) { @@ -57,7 +57,7 @@ cmd_show_messages_exec(struct cmd *self, struct cmd_ctx *ctx) tim = ctime(&msg->msg_time); *strchr(tim, '\n') = '\0'; - ctx->print(ctx, "%s %s", tim, msg->msg); + cmdq_print(cmdq, "%s %s", tim, msg->msg); } return (CMD_RETURN_NORMAL); diff --git a/cmd-show-options.c b/cmd-show-options.c index b42c65cb..9b42ed46 100644 --- a/cmd-show-options.c +++ b/cmd-show-options.c @@ -27,11 +27,11 @@ * Show options. */ -enum cmd_retval cmd_show_options_exec(struct cmd *, struct cmd_ctx *); +enum cmd_retval cmd_show_options_exec(struct cmd *, struct cmd_q *); -enum cmd_retval cmd_show_options_one(struct cmd *, struct cmd_ctx *, +enum cmd_retval cmd_show_options_one(struct cmd *, struct cmd_q *, struct options *); -enum cmd_retval cmd_show_options_all(struct cmd *, struct cmd_ctx *, +enum cmd_retval cmd_show_options_all(struct cmd *, struct cmd_q *, const struct options_table_entry *, struct options *); const struct cmd_entry cmd_show_options_entry = { @@ -55,7 +55,7 @@ const struct cmd_entry cmd_show_window_options_entry = { }; enum cmd_retval -cmd_show_options_exec(struct cmd *self, struct cmd_ctx *ctx) +cmd_show_options_exec(struct cmd *self, struct cmd_q *cmdq) { struct args *args = self->args; struct session *s; @@ -72,7 +72,7 @@ cmd_show_options_exec(struct cmd *self, struct cmd_ctx *ctx) if (args_has(self->args, 'g')) oo = &global_w_options; else { - wl = cmd_find_window(ctx, args_get(args, 't'), NULL); + wl = cmd_find_window(cmdq, args_get(args, 't'), NULL); if (wl == NULL) return (CMD_RETURN_ERROR); oo = &wl->window->options; @@ -82,7 +82,7 @@ cmd_show_options_exec(struct cmd *self, struct cmd_ctx *ctx) if (args_has(self->args, 'g')) oo = &global_s_options; else { - s = cmd_find_session(ctx, args_get(args, 't'), 0); + s = cmd_find_session(cmdq, args_get(args, 't'), 0); if (s == NULL) return (CMD_RETURN_ERROR); oo = &s->options; @@ -90,13 +90,13 @@ cmd_show_options_exec(struct cmd *self, struct cmd_ctx *ctx) } if (args->argc != 0) - return (cmd_show_options_one(self, ctx, oo)); + return (cmd_show_options_one(self, cmdq, oo)); else - return (cmd_show_options_all(self, ctx, table, oo)); + return (cmd_show_options_all(self, cmdq, table, oo)); } enum cmd_retval -cmd_show_options_one(struct cmd *self, struct cmd_ctx *ctx, +cmd_show_options_one(struct cmd *self, struct cmd_q *cmdq, struct options *oo) { struct args *args = self->args; @@ -106,37 +106,37 @@ cmd_show_options_one(struct cmd *self, struct cmd_ctx *ctx, if (*args->argv[0] == '@') { if ((o = options_find1(oo, args->argv[0])) == NULL) { - ctx->error(ctx, "unknown option: %s", args->argv[0]); + cmdq_error(cmdq, "unknown option: %s", args->argv[0]); return (CMD_RETURN_ERROR); } if (args_has(self->args, 'v')) - ctx->print(ctx, "%s", o->str); + cmdq_print(cmdq, "%s", o->str); else - ctx->print(ctx, "%s \"%s\"", o->name, o->str); + cmdq_print(cmdq, "%s \"%s\"", o->name, o->str); return (CMD_RETURN_NORMAL); } table = oe = NULL; if (options_table_find(args->argv[0], &table, &oe) != 0) { - ctx->error(ctx, "ambiguous option: %s", args->argv[0]); + cmdq_error(cmdq, "ambiguous option: %s", args->argv[0]); return (CMD_RETURN_ERROR); } if (oe == NULL) { - ctx->error(ctx, "unknown option: %s", args->argv[0]); + cmdq_error(cmdq, "unknown option: %s", args->argv[0]); return (CMD_RETURN_ERROR); } if ((o = options_find1(oo, oe->name)) == NULL) return (CMD_RETURN_NORMAL); optval = options_table_print_entry(oe, o, args_has(self->args, 'v')); if (args_has(self->args, 'v')) - ctx->print(ctx, "%s", optval); + cmdq_print(cmdq, "%s", optval); else - ctx->print(ctx, "%s %s", oe->name, optval); + cmdq_print(cmdq, "%s %s", oe->name, optval); return (CMD_RETURN_NORMAL); } enum cmd_retval -cmd_show_options_all(struct cmd *self, struct cmd_ctx *ctx, +cmd_show_options_all(struct cmd *self, struct cmd_q *cmdq, const struct options_table_entry *table, struct options *oo) { const struct options_table_entry *oe; @@ -146,9 +146,9 @@ cmd_show_options_all(struct cmd *self, struct cmd_ctx *ctx, RB_FOREACH(o, options_tree, &oo->tree) { if (*o->name == '@') { if (args_has(self->args, 'v')) - ctx->print(ctx, "%s", o->str); + cmdq_print(cmdq, "%s", o->str); else - ctx->print(ctx, "%s \"%s\"", o->name, o->str); + cmdq_print(cmdq, "%s \"%s\"", o->name, o->str); } } @@ -158,9 +158,9 @@ cmd_show_options_all(struct cmd *self, struct cmd_ctx *ctx, optval = options_table_print_entry(oe, o, args_has(self->args, 'v')); if (args_has(self->args, 'v')) - ctx->print(ctx, "%s", optval); + cmdq_print(cmdq, "%s", optval); else - ctx->print(ctx, "%s %s", oe->name, optval); + cmdq_print(cmdq, "%s %s", oe->name, optval); } return (CMD_RETURN_NORMAL); diff --git a/cmd-source-file.c b/cmd-source-file.c index 0a180d89..3d69a544 100644 --- a/cmd-source-file.c +++ b/cmd-source-file.c @@ -26,7 +26,10 @@ * Sources a configuration file. */ -enum cmd_retval cmd_source_file_exec(struct cmd *, struct cmd_ctx *); +enum cmd_retval cmd_source_file_exec(struct cmd *, struct cmd_q *); + +void cmd_source_file_show(struct cmd_q *); +void cmd_source_file_done(struct cmd_q *); const struct cmd_entry cmd_source_file_entry = { "source-file", "source", @@ -39,35 +42,66 @@ const struct cmd_entry cmd_source_file_entry = { }; enum cmd_retval -cmd_source_file_exec(struct cmd *self, struct cmd_ctx *ctx) +cmd_source_file_exec(struct cmd *self, struct cmd_q *cmdq) { - struct args *args = self->args; - int retval; - u_int i; - char *cause; + struct args *args = self->args; + struct cmd_q *cmdq1; + char *cause; - retval = load_cfg(args->argv[0], ctx, &cfg_causes); + cmdq1 = cmdq_new(NULL); + cmdq1->emptyfn = cmd_source_file_done; + cmdq1->data = cmdq; - /* - * If the context for the cmdclient came from tmux's configuration - * file, then return the status of this command now, regardless of the - * error condition. Any errors from parsing a configuration file at - * startup will be handled for us by the server. - */ - if (cfg_references > 0 || - (ctx->curclient == NULL && ctx->cmdclient == NULL)) - return (retval); + switch (load_cfg(args->argv[0], cmdq1, &cause)) { + case -1: + if (cfg_references == 0) { + cmdq_free(cmdq1); + cmdq_error(cmdq, "%s", cause); + free(cause); + return (CMD_RETURN_ERROR); + } + ARRAY_ADD(&cfg_causes, cause); + /* FALLTHROUGH */ + case 0: + if (cfg_references == 0) + cmd_source_file_show(cmdq); + cmdq_free(cmdq1); + return (CMD_RETURN_NORMAL); + } + + cmdq->references++; + cfg_references++; + + cmdq_continue(cmdq1); + return (CMD_RETURN_WAIT); +} + +void +cmd_source_file_show(struct cmd_q *cmdq) +{ + u_int i; + char *cause; - /* - * We were called from the command-line in which case print the errors - * gathered here directly. - */ for (i = 0; i < ARRAY_LENGTH(&cfg_causes); i++) { cause = ARRAY_ITEM(&cfg_causes, i); - ctx->print(ctx, "%s", cause); + cmdq_print(cmdq, "%s", cause); free(cause); } ARRAY_FREE(&cfg_causes); - - return (retval); +} + +void +cmd_source_file_done(struct cmd_q *cmdq1) +{ + struct cmd_q *cmdq = cmdq1->data; + + cmdq_free(cmdq1); + + cfg_references--; + if (cmdq_free(cmdq) || cfg_references != 0) + return; + + cmd_source_file_show(cmdq); + + cmdq_continue(cmdq); } diff --git a/cmd-split-window.c b/cmd-split-window.c index b9eb92e3..87c0e6bc 100644 --- a/cmd-split-window.c +++ b/cmd-split-window.c @@ -29,7 +29,7 @@ */ void cmd_split_window_key_binding(struct cmd *, int); -enum cmd_retval cmd_split_window_exec(struct cmd *, struct cmd_ctx *); +enum cmd_retval cmd_split_window_exec(struct cmd *, struct cmd_q *); const struct cmd_entry cmd_split_window_entry = { "split-window", "splitw", @@ -51,7 +51,7 @@ cmd_split_window_key_binding(struct cmd *self, int key) } enum cmd_retval -cmd_split_window_exec(struct cmd *self, struct cmd_ctx *ctx) +cmd_split_window_exec(struct cmd *self, struct cmd_q *cmdq) { struct args *args = self->args; struct session *s; @@ -70,7 +70,7 @@ cmd_split_window_exec(struct cmd *self, struct cmd_ctx *ctx) struct format_tree *ft; char *cp; - if ((wl = cmd_find_pane(ctx, args_get(args, 't'), &s, &wp)) == NULL) + if ((wl = cmd_find_pane(cmdq, args_get(args, 't'), &s, &wp)) == NULL) return (CMD_RETURN_ERROR); w = wl->window; @@ -83,7 +83,7 @@ cmd_split_window_exec(struct cmd *self, struct cmd_ctx *ctx) cmd = options_get_string(&s->options, "default-command"); else cmd = args->argv[0]; - cwd = cmd_get_default_path(ctx, args_get(args, 'c')); + cwd = cmd_get_default_path(cmdq, args_get(args, 'c')); type = LAYOUT_TOPBOTTOM; if (args_has(args, 'h')) @@ -152,14 +152,14 @@ cmd_split_window_exec(struct cmd *self, struct cmd_ctx *ctx) template = SPLIT_WINDOW_TEMPLATE; ft = format_create(); - if ((c = cmd_find_client(ctx, NULL, 1)) != NULL) - format_client(ft, c); + if ((c = cmd_find_client(cmdq, NULL, 1)) != NULL) + format_client(ft, c); format_session(ft, s); format_winlink(ft, s, wl); format_window_pane(ft, new_wp); cp = format_expand(ft, template); - ctx->print(ctx, "%s", cp); + cmdq_print(cmdq, "%s", cp); free(cp); format_free(ft); @@ -171,7 +171,7 @@ error: environ_free(&env); if (new_wp != NULL) window_remove_pane(w, new_wp); - ctx->error(ctx, "create pane failed: %s", cause); + cmdq_error(cmdq, "create pane failed: %s", cause); free(cause); return (CMD_RETURN_ERROR); } diff --git a/cmd-start-server.c b/cmd-start-server.c index ae425a73..c926b5fe 100644 --- a/cmd-start-server.c +++ b/cmd-start-server.c @@ -24,7 +24,7 @@ * Start the server and do nothing else. */ -enum cmd_retval cmd_start_server_exec(struct cmd *, struct cmd_ctx *); +enum cmd_retval cmd_start_server_exec(struct cmd *, struct cmd_q *); const struct cmd_entry cmd_start_server_entry = { "start-server", "start", @@ -37,7 +37,7 @@ const struct cmd_entry cmd_start_server_entry = { }; enum cmd_retval -cmd_start_server_exec(unused struct cmd *self, unused struct cmd_ctx *ctx) +cmd_start_server_exec(unused struct cmd *self, unused struct cmd_q *cmdq) { return (CMD_RETURN_NORMAL); } diff --git a/cmd-string.c b/cmd-string.c index 5a27c5bd..f785b842 100644 --- a/cmd-string.c +++ b/cmd-string.c @@ -59,7 +59,8 @@ cmd_string_ungetc(size_t *p) * string, or NULL for empty command. */ int -cmd_string_parse(const char *s, struct cmd_list **cmdlist, char **cause) +cmd_string_parse(const char *s, struct cmd_list **cmdlist, const char *file, + u_int line, char **cause) { size_t p; int ch, i, argc, rval; @@ -131,7 +132,7 @@ cmd_string_parse(const char *s, struct cmd_list **cmdlist, char **cause) if (argc == 0) goto out; - *cmdlist = cmd_list_parse(argc, argv, cause); + *cmdlist = cmd_list_parse(argc, argv, file, line, cause); if (*cmdlist == NULL) goto out; diff --git a/cmd-suspend-client.c b/cmd-suspend-client.c index c3806c6f..dda0f977 100644 --- a/cmd-suspend-client.c +++ b/cmd-suspend-client.c @@ -27,7 +27,7 @@ * Suspend client with SIGTSTP. */ -enum cmd_retval cmd_suspend_client_exec(struct cmd *, struct cmd_ctx *); +enum cmd_retval cmd_suspend_client_exec(struct cmd *, struct cmd_q *); const struct cmd_entry cmd_suspend_client_entry = { "suspend-client", "suspendc", @@ -40,12 +40,12 @@ const struct cmd_entry cmd_suspend_client_entry = { }; enum cmd_retval -cmd_suspend_client_exec(struct cmd *self, struct cmd_ctx *ctx) +cmd_suspend_client_exec(struct cmd *self, struct cmd_q *cmdq) { struct args *args = self->args; struct client *c; - if ((c = cmd_find_client(ctx, args_get(args, 't'), 0)) == NULL) + if ((c = cmd_find_client(cmdq, args_get(args, 't'), 0)) == NULL) return (CMD_RETURN_ERROR); tty_stop_tty(&c->tty); diff --git a/cmd-swap-pane.c b/cmd-swap-pane.c index 6d9fcfeb..ae875946 100644 --- a/cmd-swap-pane.c +++ b/cmd-swap-pane.c @@ -27,7 +27,7 @@ */ void cmd_swap_pane_key_binding(struct cmd *, int); -enum cmd_retval cmd_swap_pane_exec(struct cmd *, struct cmd_ctx *); +enum cmd_retval cmd_swap_pane_exec(struct cmd *, struct cmd_q *); const struct cmd_entry cmd_swap_pane_entry = { "swap-pane", "swapp", @@ -50,7 +50,7 @@ cmd_swap_pane_key_binding(struct cmd *self, int key) } enum cmd_retval -cmd_swap_pane_exec(struct cmd *self, struct cmd_ctx *ctx) +cmd_swap_pane_exec(struct cmd *self, struct cmd_q *cmdq) { struct args *args = self->args; struct winlink *src_wl, *dst_wl; @@ -59,7 +59,7 @@ cmd_swap_pane_exec(struct cmd *self, struct cmd_ctx *ctx) struct layout_cell *src_lc, *dst_lc; u_int sx, sy, xoff, yoff; - dst_wl = cmd_find_pane(ctx, args_get(args, 't'), NULL, &dst_wp); + dst_wl = cmd_find_pane(cmdq, args_get(args, 't'), NULL, &dst_wp); if (dst_wl == NULL) return (CMD_RETURN_ERROR); dst_w = dst_wl->window; @@ -77,7 +77,7 @@ cmd_swap_pane_exec(struct cmd *self, struct cmd_ctx *ctx) } else return (CMD_RETURN_NORMAL); } else { - src_wl = cmd_find_pane(ctx, args_get(args, 's'), NULL, &src_wp); + src_wl = cmd_find_pane(cmdq, args_get(args, 's'), NULL, &src_wp); if (src_wl == NULL) return (CMD_RETURN_ERROR); src_w = src_wl->window; diff --git a/cmd-swap-window.c b/cmd-swap-window.c index b2e2c119..ed175480 100644 --- a/cmd-swap-window.c +++ b/cmd-swap-window.c @@ -26,7 +26,7 @@ * Swap one window with another. */ -enum cmd_retval cmd_swap_window_exec(struct cmd *, struct cmd_ctx *); +enum cmd_retval cmd_swap_window_exec(struct cmd *, struct cmd_q *); const struct cmd_entry cmd_swap_window_entry = { "swap-window", "swapw", @@ -39,7 +39,7 @@ const struct cmd_entry cmd_swap_window_entry = { }; enum cmd_retval -cmd_swap_window_exec(struct cmd *self, struct cmd_ctx *ctx) +cmd_swap_window_exec(struct cmd *self, struct cmd_q *cmdq) { struct args *args = self->args; const char *target_src, *target_dst; @@ -49,17 +49,17 @@ cmd_swap_window_exec(struct cmd *self, struct cmd_ctx *ctx) struct window *w; target_src = args_get(args, 's'); - if ((wl_src = cmd_find_window(ctx, target_src, &src)) == NULL) + if ((wl_src = cmd_find_window(cmdq, target_src, &src)) == NULL) return (CMD_RETURN_ERROR); target_dst = args_get(args, 't'); - if ((wl_dst = cmd_find_window(ctx, target_dst, &dst)) == NULL) + if ((wl_dst = cmd_find_window(cmdq, target_dst, &dst)) == NULL) return (CMD_RETURN_ERROR); sg_src = session_group_find(src); sg_dst = session_group_find(dst); if (src != dst && sg_src != NULL && sg_dst != NULL && sg_src == sg_dst) { - ctx->error(ctx, "can't move window, sessions are grouped"); + cmdq_error(cmdq, "can't move window, sessions are grouped"); return (CMD_RETURN_ERROR); } diff --git a/cmd-switch-client.c b/cmd-switch-client.c index 0fcf0146..ea5012ed 100644 --- a/cmd-switch-client.c +++ b/cmd-switch-client.c @@ -28,7 +28,7 @@ */ void cmd_switch_client_key_binding(struct cmd *, int); -enum cmd_retval cmd_switch_client_exec(struct cmd *, struct cmd_ctx *); +enum cmd_retval cmd_switch_client_exec(struct cmd *, struct cmd_q *); const struct cmd_entry cmd_switch_client_entry = { "switch-client", "switchc", @@ -58,45 +58,45 @@ cmd_switch_client_key_binding(struct cmd *self, int key) } enum cmd_retval -cmd_switch_client_exec(struct cmd *self, struct cmd_ctx *ctx) +cmd_switch_client_exec(struct cmd *self, struct cmd_q *cmdq) { struct args *args = self->args; struct client *c; struct session *s; - if ((c = cmd_find_client(ctx, args_get(args, 'c'), 0)) == NULL) + if ((c = cmd_find_client(cmdq, args_get(args, 'c'), 0)) == NULL) return (CMD_RETURN_ERROR); if (args_has(args, 'r')) { if (c->flags & CLIENT_READONLY) { c->flags &= ~CLIENT_READONLY; - ctx->info(ctx, "made client writable"); + cmdq_info(cmdq, "made client writable"); } else { c->flags |= CLIENT_READONLY; - ctx->info(ctx, "made client read-only"); + cmdq_info(cmdq, "made client read-only"); } } s = NULL; if (args_has(args, 'n')) { if ((s = session_next_session(c->session)) == NULL) { - ctx->error(ctx, "can't find next session"); + cmdq_error(cmdq, "can't find next session"); return (CMD_RETURN_ERROR); } } else if (args_has(args, 'p')) { if ((s = session_previous_session(c->session)) == NULL) { - ctx->error(ctx, "can't find previous session"); + cmdq_error(cmdq, "can't find previous session"); return (CMD_RETURN_ERROR); } } else if (args_has(args, 'l')) { if (c->last_session != NULL && session_alive(c->last_session)) s = c->last_session; if (s == NULL) { - ctx->error(ctx, "can't find last session"); + cmdq_error(cmdq, "can't find last session"); return (CMD_RETURN_ERROR); } } else - s = cmd_find_session(ctx, args_get(args, 't'), 0); + s = cmd_find_session(cmdq, args_get(args, 't'), 0); if (s == NULL) return (CMD_RETURN_ERROR); diff --git a/cmd-unbind-key.c b/cmd-unbind-key.c index 4a39f51b..88c81270 100644 --- a/cmd-unbind-key.c +++ b/cmd-unbind-key.c @@ -27,8 +27,8 @@ */ enum cmd_retval cmd_unbind_key_check(struct args *); -enum cmd_retval cmd_unbind_key_exec(struct cmd *, struct cmd_ctx *); -enum cmd_retval cmd_unbind_key_table(struct cmd *, struct cmd_ctx *, int); +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); const struct cmd_entry cmd_unbind_key_entry = { "unbind-key", "unbind", @@ -51,7 +51,7 @@ cmd_unbind_key_check(struct args *args) } enum cmd_retval -cmd_unbind_key_exec(struct cmd *self, unused struct cmd_ctx *ctx) +cmd_unbind_key_exec(struct cmd *self, struct cmd_q *cmdq) { struct args *args = self->args; struct key_binding *bd; @@ -60,14 +60,14 @@ cmd_unbind_key_exec(struct cmd *self, unused struct cmd_ctx *ctx) if (!args_has(args, 'a')) { key = key_string_lookup_string(args->argv[0]); if (key == KEYC_NONE) { - ctx->error(ctx, "unknown key: %s", args->argv[0]); + cmdq_error(cmdq, "unknown key: %s", args->argv[0]); return (CMD_RETURN_ERROR); } } else key = KEYC_NONE; if (args_has(args, 't')) - return (cmd_unbind_key_table(self, ctx, key)); + return (cmd_unbind_key_table(self, cmdq, key)); if (key == KEYC_NONE) { while (!RB_EMPTY(&key_bindings)) { @@ -84,7 +84,7 @@ cmd_unbind_key_exec(struct cmd *self, unused struct cmd_ctx *ctx) } enum cmd_retval -cmd_unbind_key_table(struct cmd *self, struct cmd_ctx *ctx, int key) +cmd_unbind_key_table(struct cmd *self, struct cmd_q *cmdq, int key) { struct args *args = self->args; const char *tablename; @@ -93,7 +93,7 @@ cmd_unbind_key_table(struct cmd *self, struct cmd_ctx *ctx, int key) tablename = args_get(args, 't'); if ((mtab = mode_key_findtable(tablename)) == NULL) { - ctx->error(ctx, "unknown key table: %s", tablename); + cmdq_error(cmdq, "unknown key table: %s", tablename); return (CMD_RETURN_ERROR); } diff --git a/cmd-unlink-window.c b/cmd-unlink-window.c index c3d3c2ee..78c4b390 100644 --- a/cmd-unlink-window.c +++ b/cmd-unlink-window.c @@ -24,7 +24,7 @@ * Unlink a window, unless it would be destroyed by doing so (only one link). */ -enum cmd_retval cmd_unlink_window_exec(struct cmd *, struct cmd_ctx *); +enum cmd_retval cmd_unlink_window_exec(struct cmd *, struct cmd_q *); const struct cmd_entry cmd_unlink_window_entry = { "unlink-window", "unlinkw", @@ -37,7 +37,7 @@ const struct cmd_entry cmd_unlink_window_entry = { }; enum cmd_retval -cmd_unlink_window_exec(struct cmd *self, struct cmd_ctx *ctx) +cmd_unlink_window_exec(struct cmd *self, struct cmd_q *cmdq) { struct args *args = self->args; struct winlink *wl; @@ -46,7 +46,7 @@ cmd_unlink_window_exec(struct cmd *self, struct cmd_ctx *ctx) struct session_group *sg; u_int references; - if ((wl = cmd_find_window(ctx, args_get(args, 't'), &s)) == NULL) + if ((wl = cmd_find_window(cmdq, args_get(args, 't'), &s)) == NULL) return (CMD_RETURN_ERROR); w = wl->window; @@ -59,7 +59,7 @@ cmd_unlink_window_exec(struct cmd *self, struct cmd_ctx *ctx) references = 1; if (!args_has(self->args, 'k') && w->references == references) { - ctx->error(ctx, "window is only linked to one session"); + cmdq_error(cmdq, "window is only linked to one session"); return (CMD_RETURN_ERROR); } diff --git a/cmd.c b/cmd.c index 6fe4d565..5f530299 100644 --- a/cmd.c +++ b/cmd.c @@ -127,48 +127,12 @@ int cmd_lookup_index(struct session *, const char *, int *); struct window_pane *cmd_lookup_paneid(const char *); struct winlink *cmd_lookup_winlink_windowid(struct session *, const char *); struct window *cmd_lookup_windowid(const char *); -struct session *cmd_window_session(struct cmd_ctx *, - struct window *, struct winlink **); +struct session *cmd_window_session(struct cmd_q *, struct window *, + struct winlink **); struct winlink *cmd_find_window_offset(const char *, struct session *, int *); int cmd_find_index_offset(const char *, struct session *, int *); struct window_pane *cmd_find_pane_offset(const char *, struct winlink *); -struct cmd_ctx * -cmd_get_ctx(struct client *cmdclient, struct client *curclient) -{ - struct cmd_ctx *ctx; - - ctx = xcalloc(1, sizeof *ctx); - ctx->references = 0; - - ctx->cmdclient = cmdclient; - ctx->curclient = curclient; - - cmd_ref_ctx(ctx); - return (ctx); -} - -void -cmd_free_ctx(struct cmd_ctx *ctx) -{ - if (ctx->cmdclient != NULL) - ctx->cmdclient->references--; - if (ctx->curclient != NULL) - ctx->curclient->references--; - if (--ctx->references == 0) - free(ctx); -} - -void -cmd_ref_ctx(struct cmd_ctx *ctx) -{ - ctx->references++; - if (ctx->cmdclient != NULL) - ctx->cmdclient->references++; - if (ctx->curclient != NULL) - ctx->curclient->references++; -} - int cmd_pack_argv(int argc, char **argv, char *buf, size_t len) { @@ -242,7 +206,7 @@ cmd_free_argv(int argc, char **argv) } struct cmd * -cmd_parse(int argc, char **argv, char **cause) +cmd_parse(int argc, char **argv, const char *file, u_int line, char **cause) { const struct cmd_entry **entryp, *entry; struct cmd *cmd; @@ -292,9 +256,14 @@ cmd_parse(int argc, char **argv, char **cause) if (entry->check != NULL && entry->check(args) != 0) goto usage; - cmd = xmalloc(sizeof *cmd); + cmd = xcalloc(1, sizeof *cmd); cmd->entry = entry; cmd->args = args; + + if (file != NULL) + cmd->file = xstrdup(file); + cmd->line = line; + return (cmd); ambiguous: @@ -343,31 +312,33 @@ cmd_print(struct cmd *cmd, char *buf, size_t len) * session from all sessions. */ struct session * -cmd_current_session(struct cmd_ctx *ctx, int prefer_unattached) +cmd_current_session(struct cmd_q *cmdq, int prefer_unattached) { - struct msg_command_data *data = ctx->msgdata; - struct client *c = ctx->cmdclient; + struct msg_command_data *data = cmdq->msgdata; + struct client *c = cmdq->client; struct session *s; struct sessionslist ss; struct winlink *wl; struct window_pane *wp; + const char *path; int found; - if (ctx->curclient != NULL && ctx->curclient->session != NULL) - return (ctx->curclient->session); + if (c != NULL && c->session != NULL) + return (c->session); /* * If the name of the calling client's pty is know, build a list of the * sessions that contain it and if any choose either the first or the * newest. */ - if (c != NULL && c->tty.path != NULL) { + path = c == NULL ? NULL : c->tty.path; + if (path != NULL) { ARRAY_INIT(&ss); RB_FOREACH(s, sessions, &sessions) { found = 0; RB_FOREACH(wl, winlinks, &s->windows) { TAILQ_FOREACH(wp, &wl->window->panes, entry) { - if (strcmp(wp->tty, c->tty.path) == 0) { + if (strcmp(wp->tty, path) == 0) { found = 1; break; } @@ -458,21 +429,21 @@ cmd_choose_session_list(struct sessionslist *ss) * then of all clients. */ struct client * -cmd_current_client(struct cmd_ctx *ctx) +cmd_current_client(struct cmd_q *cmdq) { struct session *s; struct client *c; struct clients cc; u_int i; - if (ctx->curclient != NULL) - return (ctx->curclient); + if (cmdq->client != NULL && cmdq->client->session != NULL) + return (cmdq->client); /* * No current client set. Find the current session and return the * newest of its clients. */ - s = cmd_current_session(ctx, 0); + s = cmd_current_session(cmdq, 0); if (s != NULL && !(s->flags & SESSION_UNATTACHED)) { ARRAY_INIT(&cc); for (i = 0; i < ARRAY_LENGTH(&clients); i++) { @@ -517,7 +488,7 @@ cmd_choose_client(struct clients *cc) /* Find the target client or report an error and return NULL. */ struct client * -cmd_find_client(struct cmd_ctx *ctx, const char *arg, int quiet) +cmd_find_client(struct cmd_q *cmdq, const char *arg, int quiet) { struct client *c; char *tmparg; @@ -525,9 +496,9 @@ cmd_find_client(struct cmd_ctx *ctx, const char *arg, int quiet) /* A NULL argument means the current client. */ if (arg == NULL) { - c = cmd_current_client(ctx); + c = cmd_current_client(cmdq); if (c == NULL && !quiet) - ctx->error(ctx, "no clients"); + cmdq_error(cmdq, "no clients"); return (c); } tmparg = xstrdup(arg); @@ -542,7 +513,7 @@ cmd_find_client(struct cmd_ctx *ctx, const char *arg, int quiet) /* If no client found, report an error. */ if (c == NULL && !quiet) - ctx->error(ctx, "client not found: %s", tmparg); + cmdq_error(cmdq, "client not found: %s", tmparg); free(tmparg); return (c); @@ -744,14 +715,14 @@ cmd_lookup_windowid(const char *arg) /* Find session and winlink for window. */ struct session * -cmd_window_session(struct cmd_ctx *ctx, struct window *w, struct winlink **wlp) +cmd_window_session(struct cmd_q *cmdq, struct window *w, struct winlink **wlp) { struct session *s; struct sessionslist ss; struct winlink *wl; /* If this window is in the current session, return that winlink. */ - s = cmd_current_session(ctx, 0); + s = cmd_current_session(cmdq, 0); if (s != NULL) { wl = winlink_find_by_window(&s->windows, w); if (wl != NULL) { @@ -776,7 +747,7 @@ cmd_window_session(struct cmd_ctx *ctx, struct window *w, struct winlink **wlp) /* Find the target session or report an error and return NULL. */ struct session * -cmd_find_session(struct cmd_ctx *ctx, const char *arg, int prefer_unattached) +cmd_find_session(struct cmd_q *cmdq, const char *arg, int prefer_unattached) { struct session *s; struct window_pane *wp; @@ -788,13 +759,13 @@ cmd_find_session(struct cmd_ctx *ctx, const char *arg, int prefer_unattached) /* A NULL argument means the current session. */ if (arg == NULL) - return (cmd_current_session(ctx, prefer_unattached)); + return (cmd_current_session(cmdq, prefer_unattached)); /* Lookup as pane id or window id. */ if ((wp = cmd_lookup_paneid(arg)) != NULL) - return (cmd_window_session(ctx, wp->window, NULL)); + return (cmd_window_session(cmdq, wp->window, NULL)); if ((w = cmd_lookup_windowid(arg)) != NULL) - return (cmd_window_session(ctx, w, NULL)); + return (cmd_window_session(cmdq, w, NULL)); /* Trim a single trailing colon if any. */ tmparg = xstrdup(arg); @@ -805,7 +776,7 @@ cmd_find_session(struct cmd_ctx *ctx, const char *arg, int prefer_unattached) /* An empty session name is the current session. */ if (*tmparg == '\0') { free(tmparg); - return (cmd_current_session(ctx, prefer_unattached)); + return (cmd_current_session(cmdq, prefer_unattached)); } /* Find the session, if any. */ @@ -818,9 +789,9 @@ cmd_find_session(struct cmd_ctx *ctx, const char *arg, int prefer_unattached) /* If no session found, report an error. */ if (s == NULL) { if (ambiguous) - ctx->error(ctx, "more than one session: %s", tmparg); + cmdq_error(cmdq, "more than one session: %s", tmparg); else - ctx->error(ctx, "session not found: %s", tmparg); + cmdq_error(cmdq, "session not found: %s", tmparg); } free(tmparg); @@ -829,7 +800,7 @@ cmd_find_session(struct cmd_ctx *ctx, const char *arg, int prefer_unattached) /* Find the target session and window or report an error and return NULL. */ struct winlink * -cmd_find_window(struct cmd_ctx *ctx, const char *arg, struct session **sp) +cmd_find_window(struct cmd_q *cmdq, const char *arg, struct session **sp) { struct session *s; struct winlink *wl; @@ -842,8 +813,8 @@ cmd_find_window(struct cmd_ctx *ctx, const char *arg, struct session **sp) * Find the current session. There must always be a current session, if * it can't be found, report an error. */ - if ((s = cmd_current_session(ctx, 0)) == NULL) { - ctx->error(ctx, "can't establish current session"); + if ((s = cmd_current_session(cmdq, 0)) == NULL) { + cmdq_error(cmdq, "can't establish current session"); return (NULL); } @@ -856,7 +827,7 @@ cmd_find_window(struct cmd_ctx *ctx, const char *arg, struct session **sp) /* Lookup as pane id. */ if ((wp = cmd_lookup_paneid(arg)) != NULL) { - s = cmd_window_session(ctx, wp->window, &wl); + s = cmd_window_session(cmdq, wp->window, &wl); if (sp != NULL) *sp = s; return (wl); @@ -937,17 +908,17 @@ lookup_session: no_session: if (ambiguous) - ctx->error(ctx, "multiple sessions: %s", arg); + cmdq_error(cmdq, "multiple sessions: %s", arg); else - ctx->error(ctx, "session not found: %s", arg); + cmdq_error(cmdq, "session not found: %s", arg); free(sessptr); return (NULL); not_found: if (ambiguous) - ctx->error(ctx, "multiple windows: %s", arg); + cmdq_error(cmdq, "multiple windows: %s", arg); else - ctx->error(ctx, "window not found: %s", arg); + cmdq_error(cmdq, "window not found: %s", arg); free(sessptr); return (NULL); } @@ -979,7 +950,7 @@ cmd_find_window_offset(const char *winptr, struct session *s, int *ambiguous) * example if it is going to be created). */ int -cmd_find_index(struct cmd_ctx *ctx, const char *arg, struct session **sp) +cmd_find_index(struct cmd_q *cmdq, const char *arg, struct session **sp) { struct session *s; struct winlink *wl; @@ -991,8 +962,8 @@ cmd_find_index(struct cmd_ctx *ctx, const char *arg, struct session **sp) * Find the current session. There must always be a current session, if * it can't be found, report an error. */ - if ((s = cmd_current_session(ctx, 0)) == NULL) { - ctx->error(ctx, "can't establish current session"); + if ((s = cmd_current_session(cmdq, 0)) == NULL) { + cmdq_error(cmdq, "can't establish current session"); return (-2); } @@ -1075,25 +1046,25 @@ lookup_session: no_session: if (ambiguous) - ctx->error(ctx, "multiple sessions: %s", arg); + cmdq_error(cmdq, "multiple sessions: %s", arg); else - ctx->error(ctx, "session not found: %s", arg); + cmdq_error(cmdq, "session not found: %s", arg); free(sessptr); return (-2); invalid_index: if (ambiguous) goto not_found; - ctx->error(ctx, "invalid index: %s", arg); + cmdq_error(cmdq, "invalid index: %s", arg); free(sessptr); return (-2); not_found: if (ambiguous) - ctx->error(ctx, "multiple windows: %s", arg); + cmdq_error(cmdq, "multiple windows: %s", arg); else - ctx->error(ctx, "window not found: %s", arg); + cmdq_error(cmdq, "window not found: %s", arg); free(sessptr); return (-2); } @@ -1130,7 +1101,7 @@ cmd_find_index_offset(const char *winptr, struct session *s, int *ambiguous) * such as mysession:mywindow.0. */ struct winlink * -cmd_find_pane(struct cmd_ctx *ctx, +cmd_find_pane(struct cmd_q *cmdq, const char *arg, struct session **sp, struct window_pane **wpp) { struct session *s; @@ -1140,8 +1111,8 @@ cmd_find_pane(struct cmd_ctx *ctx, u_int idx; /* Get the current session. */ - if ((s = cmd_current_session(ctx, 0)) == NULL) { - ctx->error(ctx, "can't establish current session"); + if ((s = cmd_current_session(cmdq, 0)) == NULL) { + cmdq_error(cmdq, "can't establish current session"); return (NULL); } if (sp != NULL) @@ -1155,7 +1126,7 @@ cmd_find_pane(struct cmd_ctx *ctx, /* Lookup as pane id. */ if ((*wpp = cmd_lookup_paneid(arg)) != NULL) { - s = cmd_window_session(ctx, (*wpp)->window, &wl); + s = cmd_window_session(cmdq, (*wpp)->window, &wl); if (sp != NULL) *sp = s; return (wl); @@ -1170,7 +1141,7 @@ cmd_find_pane(struct cmd_ctx *ctx, winptr[period - arg] = '\0'; if (*winptr == '\0') wl = s->curw; - else if ((wl = cmd_find_window(ctx, winptr, sp)) == NULL) + else if ((wl = cmd_find_window(cmdq, winptr, sp)) == NULL) goto error; /* Find the pane section and look it up. */ @@ -1194,7 +1165,7 @@ cmd_find_pane(struct cmd_ctx *ctx, lookup_string: /* Try pane string description. */ if ((*wpp = window_find_string(wl->window, paneptr)) == NULL) { - ctx->error(ctx, "can't find pane: %s", paneptr); + cmdq_error(cmdq, "can't find pane: %s", paneptr); goto error; } @@ -1219,7 +1190,7 @@ lookup_window: return (s->curw); /* Try as a window and use the active pane. */ - if ((wl = cmd_find_window(ctx, arg, sp)) != NULL) + if ((wl = cmd_find_window(cmdq, arg, sp)) != NULL) *wpp = wl->window->active; return (wl); @@ -1297,8 +1268,9 @@ cmd_template_replace(const char *template, const char *s, int idx) * directory. */ const char * -cmd_get_default_path(struct cmd_ctx *ctx, const char *cwd) +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; @@ -1308,7 +1280,7 @@ cmd_get_default_path(struct cmd_ctx *ctx, const char *cwd) size_t skip; static char path[MAXPATHLEN]; - if ((s = cmd_current_session(ctx, 0)) == NULL) + if ((s = cmd_current_session(cmdq, 0)) == NULL) return (NULL); if (cwd == NULL) @@ -1338,9 +1310,9 @@ cmd_get_default_path(struct cmd_ctx *ctx, const char *cwd) return (cwd); } else { /* Empty or relative path. */ - if (ctx->cmdclient != NULL && ctx->cmdclient->cwd != NULL) - root = ctx->cmdclient->cwd; - else if (ctx->curclient != NULL && s->curw != NULL) + if (c != NULL && c->session == NULL && c->cwd != NULL) + root = c->cwd; + else if (s->curw != NULL) root = get_proc_cwd(s->curw->window->active->fd); else return (s->cwd); diff --git a/control.c b/control.c index a248e91f..fc2d6e43 100644 --- a/control.c +++ b/control.c @@ -25,46 +25,6 @@ #include "tmux.h" -void printflike2 control_msg_error(struct cmd_ctx *, const char *, ...); -void printflike2 control_msg_print(struct cmd_ctx *, const char *, ...); -void printflike2 control_msg_info(struct cmd_ctx *, const char *, ...); - -/* Command error callback. */ -void printflike2 -control_msg_error(struct cmd_ctx *ctx, const char *fmt, ...) -{ - struct client *c = ctx->curclient; - va_list ap; - - va_start(ap, fmt); - evbuffer_add_vprintf(c->stdout_data, fmt, ap); - va_end(ap); - - evbuffer_add(c->stdout_data, "\n", 1); - server_push_stdout(c); -} - -/* Command print callback. */ -void printflike2 -control_msg_print(struct cmd_ctx *ctx, const char *fmt, ...) -{ - struct client *c = ctx->curclient; - va_list ap; - - va_start(ap, fmt); - evbuffer_add_vprintf(c->stdout_data, fmt, ap); - va_end(ap); - - evbuffer_add(c->stdout_data, "\n", 1); - server_push_stdout(c); -} - -/* Command info callback. */ -void printflike2 -control_msg_info(unused struct cmd_ctx *ctx, unused const char *fmt, ...) -{ -} - /* Write a line. */ void printflike2 control_write(struct client *c, const char *fmt, ...) @@ -93,7 +53,6 @@ void control_callback(struct client *c, int closed, unused void *data) { char *line, *cause; - struct cmd_ctx *ctx; struct cmd_list *cmdlist; if (closed) @@ -108,20 +67,14 @@ control_callback(struct client *c, int closed, unused void *data) break; } - ctx = cmd_get_ctx(NULL, c); - ctx->error = control_msg_error; - ctx->print = control_msg_print; - ctx->info = control_msg_info; - - if (cmd_string_parse(line, &cmdlist, &cause) != 0) { + if (cmd_string_parse(line, &cmdlist, NULL, 0, &cause) != 0) { control_write(c, "%%error in line \"%s\": %s", line, cause); free(cause); } else { - cmd_list_exec(cmdlist, ctx); + cmdq_run(c->cmdq, cmdlist); cmd_list_free(cmdlist); } - cmd_free_ctx(ctx); free(line); } diff --git a/format.c b/format.c index 4c93c766..af2c128b 100644 --- a/format.c +++ b/format.c @@ -397,10 +397,8 @@ format_window_pane(struct format_tree *ft, struct window_pane *wp) struct grid *gd = wp->base.grid; struct grid_line *gl; unsigned long long size; - u_int i; - u_int idx; - const char *cwd; - const char *cmd; + u_int i, idx; + const char *cwd, *cmd; size = 0; for (i = 0; i < gd->hsize; i++) { diff --git a/key-bindings.c b/key-bindings.c index 0f944c4c..4e889b7e 100644 --- a/key-bindings.c +++ b/key-bindings.c @@ -182,11 +182,11 @@ key_bindings_init(void) RB_INIT(&key_bindings); for (i = 0; i < nitems(table); i++) { - cmdlist = xmalloc(sizeof *cmdlist); - TAILQ_INIT(&cmdlist->list); + cmdlist = xcalloc(1, sizeof *cmdlist); cmdlist->references = 1; + TAILQ_INIT(&cmdlist->list); - cmd = xmalloc(sizeof *cmd); + cmd = xcalloc(1, sizeof *cmd); cmd->entry = table[i].entry; if (cmd->entry->key_binding != NULL) cmd->entry->key_binding(cmd, table[i].key); @@ -199,88 +199,21 @@ key_bindings_init(void) } } -void printflike2 -key_bindings_error(struct cmd_ctx *ctx, const char *fmt, ...) -{ - va_list ap; - char *msg; - - if (ctx->curclient->session == NULL) - return; - - va_start(ap, fmt); - xvasprintf(&msg, fmt, ap); - va_end(ap); - - *msg = toupper((u_char) *msg); - status_message_set(ctx->curclient, "%s", msg); - free(msg); -} - -void printflike2 -key_bindings_print(struct cmd_ctx *ctx, const char *fmt, ...) -{ - struct winlink *wl; - va_list ap; - - if (ctx->curclient->session == NULL) - return; - - wl = ctx->curclient->session->curw; - if (wl->window->active->mode != &window_copy_mode) { - window_pane_reset_mode(wl->window->active); - window_pane_set_mode(wl->window->active, &window_copy_mode); - window_copy_init_for_output(wl->window->active); - } - - va_start(ap, fmt); - window_copy_vadd(wl->window->active, fmt, ap); - va_end(ap); -} - -void printflike2 -key_bindings_info(struct cmd_ctx *ctx, const char *fmt, ...) -{ - va_list ap; - char *msg; - - if (ctx->curclient->session == NULL) - return; - - if (options_get_number(&global_options, "quiet")) - return; - - va_start(ap, fmt); - xvasprintf(&msg, fmt, ap); - va_end(ap); - - *msg = toupper((u_char) *msg); - status_message_set(ctx->curclient, "%s", msg); - free(msg); -} - void key_bindings_dispatch(struct key_binding *bd, struct client *c) { - struct cmd_ctx *ctx; struct cmd *cmd; int readonly; - ctx = cmd_get_ctx(NULL, c); - ctx->error = key_bindings_error; - ctx->print = key_bindings_print; - ctx->info = key_bindings_info; - readonly = 1; TAILQ_FOREACH(cmd, &bd->cmdlist->list, qentry) { if (!(cmd->entry->flags & CMD_READONLY)) readonly = 0; } - if (!readonly && c->flags & CLIENT_READONLY) { - key_bindings_info(ctx, "client is read-only"); + if (!readonly && (c->flags & CLIENT_READONLY)) { + cmdq_info(c->cmdq, "client is read-only"); return; } - cmd_list_exec(bd->cmdlist, ctx); - cmd_free_ctx(ctx); + cmdq_run(c->cmdq, bd->cmdlist); } diff --git a/server-client.c b/server-client.c index ef4936fc..6f29000b 100644 --- a/server-client.c +++ b/server-client.c @@ -45,10 +45,6 @@ void server_client_msg_identify( struct client *, struct msg_identify_data *, int); void server_client_msg_shell(struct client *); -void printflike2 server_client_msg_error(struct cmd_ctx *, const char *, ...); -void printflike2 server_client_msg_print(struct cmd_ctx *, const char *, ...); -void printflike2 server_client_msg_info(struct cmd_ctx *, const char *, ...); - /* Create a new client. */ void server_client_create(int fd) @@ -67,6 +63,9 @@ server_client_create(int fd) fatal("gettimeofday failed"); memcpy(&c->activity_time, &c->creation_time, sizeof c->activity_time); + c->cmdq = cmdq_new(c); + c->cmdq->client_exit = 1; + c->stdin_data = evbuffer_new (); c->stdout_data = evbuffer_new (); c->stderr_data = evbuffer_new (); @@ -181,6 +180,10 @@ server_client_lost(struct client *c) free(c->prompt_buffer); free(c->cwd); + c->cmdq->dead = 1; + cmdq_free(c->cmdq); + c->cmdq = NULL; + environ_free(&c->environ); close(c->ibuf.fd); @@ -901,71 +904,18 @@ server_client_msg_dispatch(struct client *c) } } -/* Callback to send error message to client. */ -void printflike2 -server_client_msg_error(struct cmd_ctx *ctx, const char *fmt, ...) -{ - va_list ap; - - va_start(ap, fmt); - evbuffer_add_vprintf(ctx->cmdclient->stderr_data, fmt, ap); - va_end(ap); - - evbuffer_add(ctx->cmdclient->stderr_data, "\n", 1); - server_push_stderr(ctx->cmdclient); - ctx->cmdclient->retcode = 1; -} - -/* Callback to send print message to client. */ -void printflike2 -server_client_msg_print(struct cmd_ctx *ctx, const char *fmt, ...) -{ - va_list ap; - - va_start(ap, fmt); - evbuffer_add_vprintf(ctx->cmdclient->stdout_data, fmt, ap); - va_end(ap); - - evbuffer_add(ctx->cmdclient->stdout_data, "\n", 1); - server_push_stdout(ctx->cmdclient); -} - -/* Callback to send print message to client, if not quiet. */ -void printflike2 -server_client_msg_info(struct cmd_ctx *ctx, const char *fmt, ...) -{ - va_list ap; - - if (options_get_number(&global_options, "quiet")) - return; - - va_start(ap, fmt); - evbuffer_add_vprintf(ctx->cmdclient->stdout_data, fmt, ap); - va_end(ap); - - evbuffer_add(ctx->cmdclient->stdout_data, "\n", 1); - server_push_stdout(ctx->cmdclient); -} - /* Handle command message. */ void server_client_msg_command(struct client *c, struct msg_command_data *data) { - struct cmd_ctx *ctx; struct cmd_list *cmdlist = NULL; int argc; char **argv, *cause; - ctx = cmd_get_ctx(c, NULL); - ctx->msgdata = data; - ctx->error = server_client_msg_error; - ctx->print = server_client_msg_print; - ctx->info = server_client_msg_info; - argc = data->argc; data->argv[(sizeof data->argv) - 1] = '\0'; if (cmd_unpack_argv(data->argv, sizeof data->argv, argc, &argv) != 0) { - server_client_msg_error(ctx, "command too long"); + cmdq_error(c->cmdq, "command too long"); goto error; } @@ -975,31 +925,20 @@ server_client_msg_command(struct client *c, struct msg_command_data *data) *argv = xstrdup("new-session"); } - if ((cmdlist = cmd_list_parse(argc, argv, &cause)) == NULL) { - server_client_msg_error(ctx, "%s", cause); + if ((cmdlist = cmd_list_parse(argc, argv, NULL, 0, &cause)) == NULL) { + cmdq_error(c->cmdq, "%s", cause); cmd_free_argv(argc, argv); goto error; } cmd_free_argv(argc, argv); - switch (cmd_list_exec(cmdlist, ctx)) - { - case CMD_RETURN_ERROR: - case CMD_RETURN_NORMAL: - c->flags |= CLIENT_EXIT; - break; - case CMD_RETURN_ATTACH: - case CMD_RETURN_YIELD: - break; - } + cmdq_run(c->cmdq, cmdlist); cmd_list_free(cmdlist); - cmd_free_ctx(ctx); return; error: if (cmdlist != NULL) cmd_list_free(cmdlist); - cmd_free_ctx(ctx); c->flags |= CLIENT_EXIT; } diff --git a/server-fn.c b/server-fn.c index 6d66a9f0..b9217ef2 100644 --- a/server-fn.c +++ b/server-fn.c @@ -194,7 +194,7 @@ server_status_window(struct window *w) /* * This is slightly different. We want to redraw the status line of any - * clients containing this window rather than any where it is the + * clients containing this window rather than anywhere it is the * current window. */ @@ -563,7 +563,7 @@ int server_set_stdin_callback(struct client *c, void (*cb)(struct client *, int, void *), void *cb_data, char **cause) { - if (c == NULL) { + if (c == NULL || c->session != NULL) { *cause = xstrdup("no client with stdin"); return (-1); } diff --git a/server.c b/server.c index 994f3968..a07fa1fd 100644 --- a/server.c +++ b/server.c @@ -106,8 +106,9 @@ server_create_socket(void) int server_start(int lockfd, char *lockfile) { - int pair[2]; - struct timeval tv; + int pair[2]; + struct timeval tv; + char *cause; /* The first client is special and gets a socketpair; create it. */ if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, pair) != 0) @@ -162,23 +163,28 @@ server_start(int lockfd, char *lockfile) free(lockfile); close(lockfd); - if (access(SYSTEM_CFG, R_OK) == 0) - load_cfg(SYSTEM_CFG, NULL, &cfg_causes); - else if (errno != ENOENT) { - cfg_add_cause( - &cfg_causes, "%s: %s", SYSTEM_CFG, strerror(errno)); + cfg_cmd_q = cmdq_new(NULL); + cfg_cmd_q->emptyfn = cfg_default_done; + cfg_finished = 0; + cfg_references = 1; + ARRAY_INIT(&cfg_causes); + + if (access(SYSTEM_CFG, R_OK) == 0) { + if (load_cfg(SYSTEM_CFG, cfg_cmd_q, &cause) == -1) { + xasprintf(&cause, "%s: %s", SYSTEM_CFG, cause); + ARRAY_ADD(&cfg_causes, cause); + } + } else if (errno != ENOENT) { + xasprintf(&cause, "%s: %s", SYSTEM_CFG, strerror(errno)); + ARRAY_ADD(&cfg_causes, cause); } - if (cfg_file != NULL) - load_cfg(cfg_file, NULL, &cfg_causes); - - /* - * If there is a session already, put the current window and pane into - * more mode. - */ - if (!RB_EMPTY(&sessions) && !ARRAY_EMPTY(&cfg_causes)) - show_cfg_causes(RB_MIN(sessions, &sessions)); - - cfg_finished = 1; + if (cfg_file != NULL) { + if (load_cfg(cfg_file, cfg_cmd_q, &cause) == -1) { + xasprintf(&cause, "%s: %s", cfg_file, cause); + ARRAY_ADD(&cfg_causes, cause); + } + } + cmdq_continue(cfg_cmd_q); server_add_accept(0); diff --git a/tmux.c b/tmux.c index 2428a404..7bce10ec 100644 --- a/tmux.c +++ b/tmux.c @@ -330,8 +330,6 @@ main(int argc, char **argv) options_init(&global_w_options, NULL); options_table_populate_tree(window_options_table, &global_w_options); - ARRAY_INIT(&cfg_causes); - /* Enable UTF-8 if the first client is on UTF-8 terminal. */ if (flags & IDENTIFY_UTF8) { options_set_number(&global_s_options, "status-utf8", 1); diff --git a/tmux.h b/tmux.h index b71df280..2674a178 100644 --- a/tmux.h +++ b/tmux.h @@ -432,6 +432,9 @@ struct tty_term_code_entry { const char *name; }; +/* List of error causes. */ +ARRAY_DECL(causelist, char *); + /* Message codes. */ enum msgtype { MSG_COMMAND, @@ -777,6 +780,9 @@ struct job { int fd; struct bufferevent *event; + struct bufferevent *out; + int outdone; + void (*callbackfn)(struct job *); void (*freefn)(void *); void *data; @@ -1350,6 +1356,7 @@ struct client { int wlmouse; + struct cmd_q *cmdq; int references; }; ARRAY_DECL(clients, struct client *); @@ -1363,41 +1370,14 @@ struct args { char **argv; }; -/* Key/command line command. */ -struct cmd_ctx { - /* - * curclient is the client where this command was executed if inside - * tmux. This is NULL if the command came from the command-line. - * - * cmdclient is the client which sent the MSG_COMMAND to the server, if - * any. This is NULL unless the command came from the command-line. - * - * cmdclient and curclient may both be NULL if the command is in the - * configuration file. - */ - struct client *curclient; - struct client *cmdclient; - - int references; - - struct msg_command_data *msgdata; - - /* gcc2 doesn't understand attributes on function pointers... */ -#if defined(__GNUC__) && __GNUC__ >= 3 - void printflike2 (*print)(struct cmd_ctx *, const char *, ...); - void printflike2 (*info)(struct cmd_ctx *, const char *, ...); - void printflike2 (*error)(struct cmd_ctx *, const char *, ...); -#else - void (*print)(struct cmd_ctx *, const char *, ...); - void (*info)(struct cmd_ctx *, const char *, ...); - void (*error)(struct cmd_ctx *, const char *, ...); -#endif -}; - +/* Command and list of commands. */ struct cmd { const struct cmd_entry *entry; struct args *args; + char *file; + u_int line; + TAILQ_ENTRY(cmd) qentry; }; struct cmd_list { @@ -1405,13 +1385,40 @@ struct cmd_list { TAILQ_HEAD(, cmd) list; }; +/* Command return values. */ enum cmd_retval { CMD_RETURN_ERROR = -1, CMD_RETURN_NORMAL = 0, - CMD_RETURN_YIELD, - CMD_RETURN_ATTACH + CMD_RETURN_WAIT, + CMD_RETURN_STOP }; +/* Command queue entry. */ +struct cmd_q_item { + struct cmd_list *cmdlist; + TAILQ_ENTRY(cmd_q_item) qentry; +}; +TAILQ_HEAD(cmd_q_items, cmd_q_item); + +/* Command queue. */ +struct cmd_q { + int references; + int dead; + + struct client *client; + int client_exit; + + struct cmd_q_items queue; + struct cmd_q_item *item; + struct cmd *cmd; + + void (*emptyfn)(struct cmd_q *); + void *data; + + struct msg_command_data *msgdata; +}; + +/* Command definition. */ struct cmd_entry { const char *name; const char *alias; @@ -1430,7 +1437,7 @@ struct cmd_entry { void (*key_binding)(struct cmd *, int); int (*check)(struct args *); - enum cmd_retval (*exec)(struct cmd *, struct cmd_ctx *); + enum cmd_retval (*exec)(struct cmd *, struct cmd_q *); }; /* Key binding. */ @@ -1479,9 +1486,6 @@ struct format_entry { }; RB_HEAD(format_tree, format_entry); -/* List of configuration causes. */ -ARRAY_DECL(causelist, char *); - /* Common command usages. */ #define CMD_TARGET_PANE_USAGE "[-t target-pane]" #define CMD_TARGET_WINDOW_USAGE "[-t target-window]" @@ -1517,12 +1521,13 @@ void setblocking(int, int); __dead void shell_exec(const char *, const char *); /* cfg.c */ -extern int cfg_finished; -extern int cfg_references; +extern struct cmd_q *cfg_cmd_q; +extern int cfg_finished; +extern int cfg_references; extern struct causelist cfg_causes; -void printflike2 cfg_add_cause(struct causelist *, const char *, ...); -enum cmd_retval load_cfg(const char *, struct cmd_ctx *, struct causelist *); -void show_cfg_causes(struct session *); +int load_cfg(const char *, struct cmd_q *, char **); +void cfg_default_done(struct cmd_q *); +void cfg_show_causes(struct session *); /* format.c */ int format_cmp(struct format_entry *, struct format_entry *); @@ -1725,27 +1730,24 @@ long long args_strtonum( struct args *, u_char, long long, long long, char **); /* cmd.c */ -struct cmd_ctx *cmd_get_ctx(struct client *, struct client *); -void cmd_free_ctx(struct cmd_ctx *); -void cmd_ref_ctx(struct cmd_ctx *); int cmd_pack_argv(int, char **, char *, size_t); int cmd_unpack_argv(char *, size_t, int, char ***); char **cmd_copy_argv(int, char *const *); void cmd_free_argv(int, char **); -struct cmd *cmd_parse(int, char **, char **); +struct cmd *cmd_parse(int, char **, const char *, u_int, char **); size_t cmd_print(struct cmd *, char *, size_t); -struct session *cmd_current_session(struct cmd_ctx *, int); -struct client *cmd_current_client(struct cmd_ctx *); -struct client *cmd_find_client(struct cmd_ctx *, const char *, int); -struct session *cmd_find_session(struct cmd_ctx *, const char *, int); -struct winlink *cmd_find_window( - struct cmd_ctx *, const char *, struct session **); -int cmd_find_index( - struct cmd_ctx *, const char *, struct session **); -struct winlink *cmd_find_pane(struct cmd_ctx *, - const char *, struct session **, struct window_pane **); +struct session *cmd_current_session(struct cmd_q *, int); +struct client *cmd_current_client(struct cmd_q *); +struct client *cmd_find_client(struct cmd_q *, const char *, int); +struct session *cmd_find_session(struct cmd_q *, const char *, int); +struct winlink *cmd_find_window(struct cmd_q *, const char *, + struct session **); +int cmd_find_index(struct cmd_q *, const char *, + struct session **); +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_ctx *, const char *); +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; @@ -1835,13 +1837,24 @@ extern const struct cmd_entry cmd_unlink_window_entry; extern const struct cmd_entry cmd_up_pane_entry; /* cmd-list.c */ -struct cmd_list *cmd_list_parse(int, char **, char **); -enum cmd_retval cmd_list_exec(struct cmd_list *, struct cmd_ctx *); +struct cmd_list *cmd_list_parse(int, char **, const char *, u_int, char **); void cmd_list_free(struct cmd_list *); size_t cmd_list_print(struct cmd_list *, char *, size_t); +/* cmd-queue.c */ +struct cmd_q *cmdq_new(struct client *); +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 *, ...); +void cmdq_run(struct cmd_q *, struct cmd_list *); +void cmdq_append(struct cmd_q *, struct cmd_list *); +int cmdq_continue(struct cmd_q *); +void cmdq_flush(struct cmd_q *); + /* cmd-string.c */ -int cmd_string_parse(const char *, struct cmd_list **, char **); +int cmd_string_parse(const char *, struct cmd_list **, const char *, + u_int, char **); /* client.c */ int client_main(int, char **, int); @@ -1856,9 +1869,6 @@ void key_bindings_remove(int); void key_bindings_clean(void); void key_bindings_init(void); void key_bindings_dispatch(struct key_binding *, struct client *); -void printflike2 key_bindings_error(struct cmd_ctx *, const char *, ...); -void printflike2 key_bindings_print(struct cmd_ctx *, const char *, ...); -void printflike2 key_bindings_info(struct cmd_ctx *, const char *, ...); /* key-string.c */ int key_string_lookup_string(const char *); diff --git a/window-choose.c b/window-choose.c index 4443e1a5..2671c781 100644 --- a/window-choose.c +++ b/window-choose.c @@ -200,9 +200,8 @@ window_choose_data_free(struct window_choose_data *wcd) void window_choose_data_run(struct window_choose_data *cdata) { - struct cmd_ctx *ctx; - struct cmd_list *cmdlist; - char *cause; + struct cmd_list *cmdlist; + char *cause; /* * The command template will have already been replaced. But if it's @@ -211,7 +210,7 @@ window_choose_data_run(struct window_choose_data *cdata) if (cdata->command == NULL) return; - if (cmd_string_parse(cdata->command, &cmdlist, &cause) != 0) { + if (cmd_string_parse(cdata->command, &cmdlist, NULL, 0, &cause) != 0) { if (cause != NULL) { *cause = toupper((u_char) *cause); status_message_set(cdata->start_client, "%s", cause); @@ -220,14 +219,8 @@ window_choose_data_run(struct window_choose_data *cdata) return; } - ctx = cmd_get_ctx(NULL, cdata->start_client); - ctx->error = key_bindings_error; - ctx->print = key_bindings_print; - ctx->info = key_bindings_info; - - cmd_list_exec(cmdlist, ctx); + cmdq_run(cdata->start_client->cmdq, cmdlist); cmd_list_free(cmdlist); - cmd_free_ctx(ctx); } void