summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authornicm <nicm@openbsd.org>2016-10-16 17:55:14 +0000
committernicm <nicm@openbsd.org>2016-10-16 17:55:14 +0000
commit765b9a582c208af75c7304abae7e7e4c757934cb (patch)
treec6ba4d8161097c3d648fe4a1d213628591795591
parentUse the err(3) family of functions more consistently. (diff)
downloadwireguard-openbsd-765b9a582c208af75c7304abae7e7e4c757934cb.tar.xz
wireguard-openbsd-765b9a582c208af75c7304abae7e7e4c757934cb.zip
Rewrite command queue handling. Each client still has a command queue,
but there is also now a global command queue. Instead of command queues being dispatched on demand from wherever the command happens to be added, they are now all dispatched from the top level server loop. Command queues may now also include callbacks as well as commands, and items may be inserted after the current command as well as at the end. This all makes command queues significantly more predictable and easier to use, and avoids the complex multiple nested command queues used by source-file, if-shell and friends. A mass rename of struct cmdq to a better name (cmdq_item probably) is coming.
-rw-r--r--usr.bin/tmux/cfg.c72
-rw-r--r--usr.bin/tmux/cmd-attach-session.c4
-rw-r--r--usr.bin/tmux/cmd-command-prompt.c32
-rw-r--r--usr.bin/tmux/cmd-confirm-before.c29
-rw-r--r--usr.bin/tmux/cmd-copy-mode.c6
-rw-r--r--usr.bin/tmux/cmd-display-panes.c52
-rw-r--r--usr.bin/tmux/cmd-find.c4
-rw-r--r--usr.bin/tmux/cmd-if-shell.c114
-rw-r--r--usr.bin/tmux/cmd-load-buffer.c47
-rw-r--r--usr.bin/tmux/cmd-new-session.c8
-rw-r--r--usr.bin/tmux/cmd-new-window.c6
-rw-r--r--usr.bin/tmux/cmd-queue.c491
-rw-r--r--usr.bin/tmux/cmd-resize-pane.c6
-rw-r--r--usr.bin/tmux/cmd-run-shell.c30
-rw-r--r--usr.bin/tmux/cmd-send-keys.c4
-rw-r--r--usr.bin/tmux/cmd-source-file.c56
-rw-r--r--usr.bin/tmux/cmd-split-window.c6
-rw-r--r--usr.bin/tmux/cmd-wait-for.c71
-rw-r--r--usr.bin/tmux/cmd.c53
-rw-r--r--usr.bin/tmux/control.c31
-rw-r--r--usr.bin/tmux/format.c11
-rw-r--r--usr.bin/tmux/hooks.c66
-rw-r--r--usr.bin/tmux/key-bindings.c24
-rw-r--r--usr.bin/tmux/notify.c14
-rw-r--r--usr.bin/tmux/server-client.c46
-rw-r--r--usr.bin/tmux/server.c12
-rw-r--r--usr.bin/tmux/tmux.18
-rw-r--r--usr.bin/tmux/tmux.h270
-rw-r--r--usr.bin/tmux/window-choose.c6
29 files changed, 847 insertions, 732 deletions
diff --git a/usr.bin/tmux/cfg.c b/usr.bin/tmux/cfg.c
index 86dd159ea67..8aa71d7c539 100644
--- a/usr.bin/tmux/cfg.c
+++ b/usr.bin/tmux/cfg.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: cfg.c,v 1.48 2016/10/14 18:41:53 nicm Exp $ */
+/* $OpenBSD: cfg.c,v 1.49 2016/10/16 17:55:14 nicm Exp $ */
/*
* Copyright (c) 2008 Nicholas Marriott <nicholas.marriott@gmail.com>
@@ -29,14 +29,25 @@
#include "tmux.h"
char *cfg_file;
-static struct cmd_q *cfg_cmd_q;
int cfg_finished;
-int cfg_references;
static char **cfg_causes;
static u_int cfg_ncauses;
struct client *cfg_client;
-static void cfg_default_done(struct cmd_q *);
+static enum cmd_retval
+cfg_done(__unused struct cmd_q *cmdq, __unused void *data)
+{
+ if (cfg_finished)
+ return (CMD_RETURN_NORMAL);
+ cfg_finished = 1;
+
+ if (!RB_EMPTY(&sessions))
+ cfg_show_causes(RB_MIN(sessions, &sessions));
+
+ if (cfg_client != NULL)
+ server_client_unref(cfg_client);
+ return (CMD_RETURN_NORMAL);
+}
void
set_cfg_file(const char *path)
@@ -51,30 +62,24 @@ start_cfg(void)
const char *home;
int quiet = 0;
- cfg_cmd_q = cmdq_new(NULL);
- cfg_cmd_q->emptyfn = cfg_default_done;
-
- cfg_finished = 0;
- cfg_references = 1;
-
cfg_client = TAILQ_FIRST(&clients);
if (cfg_client != NULL)
cfg_client->references++;
- load_cfg(TMUX_CONF, cfg_cmd_q, 1);
+ load_cfg(TMUX_CONF, cfg_client, NULL, 1);
if (cfg_file == NULL && (home = find_home()) != NULL) {
xasprintf(&cfg_file, "%s/.tmux.conf", home);
quiet = 1;
}
if (cfg_file != NULL)
- load_cfg(cfg_file, cfg_cmd_q, quiet);
+ load_cfg(cfg_file, cfg_client, NULL, quiet);
- cmdq_continue(cfg_cmd_q);
+ cmdq_append(cfg_client, cmdq_get_callback(cfg_done, NULL));
}
int
-load_cfg(const char *path, struct cmd_q *cmdq, int quiet)
+load_cfg(const char *path, struct client *c, struct cmd_q *cmdq, int quiet)
{
FILE *f;
char delim[3] = { '\\', '\\', '\0' };
@@ -82,6 +87,7 @@ load_cfg(const char *path, struct cmd_q *cmdq, int quiet)
size_t line = 0;
char *buf, *cause1, *p;
struct cmd_list *cmdlist;
+ struct cmd_q *new_cmdq;
log_debug("loading %s", path);
if ((f = fopen(path, "rb")) == NULL) {
@@ -117,8 +123,13 @@ load_cfg(const char *path, struct cmd_q *cmdq, int quiet)
if (cmdlist == NULL)
continue;
- cmdq_append(cmdq, cmdlist, NULL);
+ new_cmdq = cmdq_get_command(cmdlist, NULL, NULL, 0);
+ if (cmdq != NULL)
+ cmdq_insert_after(cmdq, new_cmdq);
+ else
+ cmdq_append(c, new_cmdq);
cmd_list_free(cmdlist);
+
found++;
}
fclose(f);
@@ -126,37 +137,6 @@ load_cfg(const char *path, struct cmd_q *cmdq, int quiet)
return (found);
}
-static void
-cfg_default_done(__unused struct cmd_q *cmdq)
-{
- log_debug("%s: %u references%s", __func__, cfg_references,
- cfg_finished ? " (finished)" : "");
-
- if (cfg_finished || --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;
-
- if (cfg_client != NULL) {
- /*
- * The client command queue starts with client_exit set to 1 so
- * only continue if not empty (that is, we have been delayed
- * during configuration parsing for long enough that the
- * MSG_COMMAND has arrived), else the client will exit before
- * the MSG_COMMAND which might tell it not to.
- */
- if (!TAILQ_EMPTY(&cfg_client->cmdq->queue))
- cmdq_continue(cfg_client->cmdq);
- server_client_unref(cfg_client);
- cfg_client = NULL;
- }
-}
-
void
cfg_add_cause(const char *fmt, ...)
{
diff --git a/usr.bin/tmux/cmd-attach-session.c b/usr.bin/tmux/cmd-attach-session.c
index 6d05b26e80b..bdf52980312 100644
--- a/usr.bin/tmux/cmd-attach-session.c
+++ b/usr.bin/tmux/cmd-attach-session.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: cmd-attach-session.c,v 1.62 2016/10/10 21:51:39 nicm Exp $ */
+/* $OpenBSD: cmd-attach-session.c,v 1.63 2016/10/16 17:55:14 nicm Exp $ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
@@ -145,7 +145,7 @@ cmd_attach_session(struct cmd_q *cmdq, int dflag, int rflag, const char *cflag,
if (~c->flags & CLIENT_CONTROL)
proc_send(c->peer, MSG_READY, -1, NULL, 0);
hooks_run(c->session->hooks, c, NULL, "client-attached");
- cmdq->client_exit = 0;
+ c->flags |= CLIENT_ATTACHED;
}
recalculate_sizes();
alerts_check_session(s);
diff --git a/usr.bin/tmux/cmd-command-prompt.c b/usr.bin/tmux/cmd-command-prompt.c
index e5ed4d9bc85..c0e66782bea 100644
--- a/usr.bin/tmux/cmd-command-prompt.c
+++ b/usr.bin/tmux/cmd-command-prompt.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: cmd-command-prompt.c,v 1.36 2016/10/12 13:03:27 nicm Exp $ */
+/* $OpenBSD: cmd-command-prompt.c,v 1.37 2016/10/16 17:55:14 nicm Exp $ */
/*
* Copyright (c) 2008 Nicholas Marriott <nicholas.marriott@gmail.com>
@@ -121,12 +121,24 @@ cmd_command_prompt_exec(struct cmd *self, struct cmd_q *cmdq)
return (CMD_RETURN_NORMAL);
}
+static enum cmd_retval
+cmd_command_prompt_error(struct cmd_q *cmdq, void *data)
+{
+ char *error = data;
+
+ cmdq_error(cmdq, "%s", error);
+ free(error);
+
+ return (CMD_RETURN_NORMAL);
+}
+
static int
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_q *new_cmdq;
char *cause, *new_template, *prompt, *ptr;
char *input = NULL;
@@ -153,17 +165,19 @@ cmd_command_prompt_callback(void *data, const char *s)
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);
- free(cause);
- }
- return (0);
+ new_cmdq = cmdq_get_callback(cmd_command_prompt_error,
+ cause);
+ } else
+ new_cmdq = NULL;
+ } else {
+ new_cmdq = cmdq_get_command(cmdlist, NULL, NULL, 0);
+ cmd_list_free(cmdlist);
}
- cmdq_run(c->cmdq, cmdlist, NULL);
- cmd_list_free(cmdlist);
+ if (new_cmdq != NULL)
+ cmdq_append(c, new_cmdq);
- if (c->prompt_callbackfn != (void *) &cmd_command_prompt_callback)
+ if (c->prompt_callbackfn != (void *)&cmd_command_prompt_callback)
return (1);
return (0);
}
diff --git a/usr.bin/tmux/cmd-confirm-before.c b/usr.bin/tmux/cmd-confirm-before.c
index e215b574e96..5810a89a21f 100644
--- a/usr.bin/tmux/cmd-confirm-before.c
+++ b/usr.bin/tmux/cmd-confirm-before.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: cmd-confirm-before.c,v 1.29 2016/10/10 21:51:39 nicm Exp $ */
+/* $OpenBSD: cmd-confirm-before.c,v 1.30 2016/10/16 17:55:14 nicm Exp $ */
/*
* Copyright (c) 2009 Tiago Cunha <me@tiagocunha.org>
@@ -83,12 +83,24 @@ cmd_confirm_before_exec(struct cmd *self, struct cmd_q *cmdq)
return (CMD_RETURN_NORMAL);
}
+static enum cmd_retval
+cmd_confirm_before_error(struct cmd_q *cmdq, void *data)
+{
+ char *error = data;
+
+ cmdq_error(cmdq, "%s", error);
+ free(error);
+
+ return (CMD_RETURN_NORMAL);
+}
+
static int
cmd_confirm_before_callback(void *data, const char *s)
{
struct cmd_confirm_before_data *cdata = data;
struct client *c = cdata->client;
struct cmd_list *cmdlist;
+ struct cmd_q *new_cmdq;
char *cause;
if (c->flags & CLIENT_DEAD)
@@ -101,14 +113,17 @@ cmd_confirm_before_callback(void *data, const char *s)
if (cmd_string_parse(cdata->cmd, &cmdlist, NULL, 0, &cause) != 0) {
if (cause != NULL) {
- cmdq_error(c->cmdq, "%s", cause);
- free(cause);
- }
- return (0);
+ new_cmdq = cmdq_get_callback(cmd_confirm_before_error,
+ cause);
+ } else
+ new_cmdq = NULL;
+ } else {
+ new_cmdq = cmdq_get_command(cmdlist, NULL, NULL, 0);
+ cmd_list_free(cmdlist);
}
- cmdq_run(c->cmdq, cmdlist, NULL);
- cmd_list_free(cmdlist);
+ if (new_cmdq != NULL)
+ cmdq_append(c, new_cmdq);
return (0);
}
diff --git a/usr.bin/tmux/cmd-copy-mode.c b/usr.bin/tmux/cmd-copy-mode.c
index dcbebcfec2c..6eb470f286d 100644
--- a/usr.bin/tmux/cmd-copy-mode.c
+++ b/usr.bin/tmux/cmd-copy-mode.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: cmd-copy-mode.c,v 1.29 2016/10/14 22:14:22 nicm Exp $ */
+/* $OpenBSD: cmd-copy-mode.c,v 1.30 2016/10/16 17:55:14 nicm Exp $ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
@@ -61,7 +61,7 @@ cmd_copy_mode_exec(struct cmd *self, struct cmd_q *cmdq)
struct window_pane *wp = cmdq->state.tflag.wp;
if (args_has(args, 'M')) {
- if ((wp = cmd_mouse_pane(&cmdq->item->mouse, &s, NULL)) == NULL)
+ if ((wp = cmd_mouse_pane(&cmdq->mouse, &s, NULL)) == NULL)
return (CMD_RETURN_NORMAL);
if (c == NULL || c->session != s)
return (CMD_RETURN_NORMAL);
@@ -80,7 +80,7 @@ cmd_copy_mode_exec(struct cmd *self, struct cmd_q *cmdq)
if (args_has(args, 'M')) {
if (wp->mode != NULL && wp->mode != &window_copy_mode)
return (CMD_RETURN_NORMAL);
- window_copy_start_drag(c, &cmdq->item->mouse);
+ window_copy_start_drag(c, &cmdq->mouse);
}
if (wp->mode == &window_copy_mode && args_has(self->args, 'u'))
window_copy_pageup(wp, 0);
diff --git a/usr.bin/tmux/cmd-display-panes.c b/usr.bin/tmux/cmd-display-panes.c
index 722562213d2..385222161ce 100644
--- a/usr.bin/tmux/cmd-display-panes.c
+++ b/usr.bin/tmux/cmd-display-panes.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: cmd-display-panes.c,v 1.14 2016/10/14 22:14:22 nicm Exp $ */
+/* $OpenBSD: cmd-display-panes.c,v 1.15 2016/10/16 17:55:14 nicm Exp $ */
/*
* Copyright (c) 2009 Nicholas Marriott <nicholas.marriott@gmail.com>
@@ -65,32 +65,48 @@ cmd_display_panes_exec(struct cmd *self, struct cmd_q *cmdq)
return (CMD_RETURN_NORMAL);
}
+static enum cmd_retval
+cmd_display_panes_error(struct cmd_q *cmdq, void *data)
+{
+ char *error = data;
+
+ cmdq_error(cmdq, "%s", error);
+ free(error);
+
+ return (CMD_RETURN_NORMAL);
+}
+
static void
cmd_display_panes_callback(struct client *c, struct window_pane *wp)
{
struct cmd_list *cmdlist;
+ struct cmd_q *new_cmdq;
char *template, *cmd, *expanded, *cause;
template = c->identify_callback_data;
- if (wp != NULL) {
- xasprintf(&expanded, "%%%u", wp->id);
- cmd = cmd_template_replace(template, expanded, 1);
-
- if (cmd_string_parse(cmd, &cmdlist, NULL, 0, &cause) != 0) {
- if (cause != NULL) {
- *cause = toupper((u_char) *cause);
- status_message_set(c, "%s", cause);
- free(cause);
- }
- } else {
- cmdq_run(c->cmdq, cmdlist, NULL);
- cmd_list_free(cmdlist);
- }
-
- free(cmd);
- free(expanded);
+ if (wp == NULL)
+ goto out;
+ xasprintf(&expanded, "%%%u", wp->id);
+ cmd = cmd_template_replace(template, expanded, 1);
+
+ if (cmd_string_parse(cmd, &cmdlist, NULL, 0, &cause) != 0) {
+ if (cause != NULL) {
+ new_cmdq = cmdq_get_callback(cmd_display_panes_error,
+ cause);
+ } else
+ new_cmdq = NULL;
+ } else {
+ new_cmdq = cmdq_get_command(cmdlist, NULL, NULL, 0);
+ cmd_list_free(cmdlist);
}
+ if (new_cmdq != NULL)
+ cmdq_append(c, new_cmdq);
+
+ free(cmd);
+ free(expanded);
+
+out:
free(c->identify_callback_data);
c->identify_callback_data = NULL;
c->identify_callback = NULL;
diff --git a/usr.bin/tmux/cmd-find.c b/usr.bin/tmux/cmd-find.c
index 72d0ee401bd..a31193f9529 100644
--- a/usr.bin/tmux/cmd-find.c
+++ b/usr.bin/tmux/cmd-find.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: cmd-find.c,v 1.35 2016/10/15 00:09:30 nicm Exp $ */
+/* $OpenBSD: cmd-find.c,v 1.36 2016/10/16 17:55:14 nicm Exp $ */
/*
* Copyright (c) 2015 Nicholas Marriott <nicholas.marriott@gmail.com>
@@ -1006,7 +1006,7 @@ cmd_find_target(struct cmd_find_state *fs, struct cmd_find_state *current,
/* Mouse target is a plain = or {mouse}. */
if (strcmp(target, "=") == 0 || strcmp(target, "{mouse}") == 0) {
- m = &cmdq->item->mouse;
+ m = &cmdq->mouse;
switch (type) {
case CMD_FIND_PANE:
fs->wp = cmd_mouse_pane(m, &fs->s, &fs->wl);
diff --git a/usr.bin/tmux/cmd-if-shell.c b/usr.bin/tmux/cmd-if-shell.c
index b29f045a1ed..1a148f5c504 100644
--- a/usr.bin/tmux/cmd-if-shell.c
+++ b/usr.bin/tmux/cmd-if-shell.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: cmd-if-shell.c,v 1.46 2016/10/13 22:48:51 nicm Exp $ */
+/* $OpenBSD: cmd-if-shell.c,v 1.47 2016/10/16 17:55:14 nicm Exp $ */
/*
* Copyright (c) 2009 Tiago Cunha <me@tiagocunha.org>
@@ -31,9 +31,9 @@
static enum cmd_retval cmd_if_shell_exec(struct cmd *, struct cmd_q *);
-static void cmd_if_shell_callback(struct job *);
-static void cmd_if_shell_done(struct cmd_q *);
-static void cmd_if_shell_free(void *);
+static enum cmd_retval cmd_if_shell_error(struct cmd_q *, void *);
+static void cmd_if_shell_callback(struct job *);
+static void cmd_if_shell_free(void *);
const struct cmd_entry cmd_if_shell_entry = {
.name = "if-shell",
@@ -56,11 +56,9 @@ struct cmd_if_shell_data {
char *cmd_if;
char *cmd_else;
+ struct client *client;
struct cmd_q *cmdq;
struct mouse_event mouse;
-
- int bflag;
- int references;
};
static enum cmd_retval
@@ -70,6 +68,7 @@ cmd_if_shell_exec(struct cmd *self, struct cmd_q *cmdq)
struct cmd_if_shell_data *cdata;
char *shellcmd, *cmd, *cause;
struct cmd_list *cmdlist;
+ struct cmd_q *new_cmdq;
struct session *s = cmdq->state.tflag.s;
struct winlink *wl = cmdq->state.tflag.wl;
struct window_pane *wp = cmdq->state.tflag.wp;
@@ -104,7 +103,8 @@ cmd_if_shell_exec(struct cmd *self, struct cmd_q *cmdq)
}
return (CMD_RETURN_ERROR);
}
- cmdq_run(cmdq, cmdlist, &cmdq->item->mouse);
+ new_cmdq = cmdq_get_command(cmdlist, NULL, &cmdq->mouse, 0);
+ cmdq_insert_after(cmdq, new_cmdq);
cmd_list_free(cmdlist);
return (CMD_RETURN_NORMAL);
}
@@ -121,92 +121,80 @@ cmd_if_shell_exec(struct cmd *self, struct cmd_q *cmdq)
else
cdata->cmd_else = NULL;
- cdata->bflag = args_has(args, 'b');
+ cdata->client = cmdq->client;
+ cdata->client->references++;
- cdata->cmdq = cmdq;
- memcpy(&cdata->mouse, &cmdq->item->mouse, sizeof cdata->mouse);
- cmdq->references++;
+ if (!args_has(args, 'b'))
+ cdata->cmdq = cmdq;
+ else
+ cdata->cmdq = NULL;
+ memcpy(&cdata->mouse, &cmdq->mouse, sizeof cdata->mouse);
- cdata->references = 1;
job_run(shellcmd, s, cwd, cmd_if_shell_callback, cmd_if_shell_free,
cdata);
free(shellcmd);
- if (cdata->bflag)
+ if (args_has(args, 'b'))
return (CMD_RETURN_NORMAL);
return (CMD_RETURN_WAIT);
}
+static enum cmd_retval
+cmd_if_shell_error(struct cmd_q *cmdq, void *data)
+{
+ char *error = data;
+
+ cmdq_error(cmdq, "%s", error);
+ free(error);
+
+ return (CMD_RETURN_NORMAL);
+}
+
static void
cmd_if_shell_callback(struct job *job)
{
struct cmd_if_shell_data *cdata = job->data;
- struct cmd_q *cmdq = cdata->cmdq, *cmdq1;
+ struct client *c = cdata->client;
struct cmd_list *cmdlist;
- char *cause, *cmd;
-
- if (cmdq->flags & CMD_Q_DEAD)
- return;
+ struct cmd_q *new_cmdq;
+ char *cause, *cmd, *file = cdata->file;
+ u_int line = cdata->line;
if (!WIFEXITED(job->status) || WEXITSTATUS(job->status) != 0)
cmd = cdata->cmd_else;
else
cmd = cdata->cmd_if;
if (cmd == NULL)
- return;
-
- if (cmd_string_parse(cmd, &cmdlist, cdata->file, cdata->line,
- &cause) != 0) {
- if (cause != NULL) {
- cmdq_error(cmdq, "%s", cause);
- free(cause);
- }
- return;
+ goto out;
+
+ if (cmd_string_parse(cmd, &cmdlist, file, line, &cause) != 0) {
+ if (cause != NULL)
+ new_cmdq = cmdq_get_callback(cmd_if_shell_error, cause);
+ else
+ new_cmdq = NULL;
+ } else {
+ new_cmdq = cmdq_get_command(cmdlist, NULL, &cdata->mouse, 0);
+ cmd_list_free(cmdlist);
}
- cmdq1 = cmdq_new(cmdq->client);
- cmdq1->emptyfn = cmd_if_shell_done;
- cmdq1->data = cdata;
-
- cdata->references++;
- cmdq_run(cmdq1, cmdlist, &cdata->mouse);
- cmd_list_free(cmdlist);
-}
-
-static void
-cmd_if_shell_done(struct cmd_q *cmdq1)
-{
- struct cmd_if_shell_data *cdata = cmdq1->data;
- struct cmd_q *cmdq = cdata->cmdq;
-
- if (cmdq1->client_exit >= 0)
- cmdq->client_exit = cmdq1->client_exit;
- cmdq_free(cmdq1);
-
- if (--cdata->references != 0)
- return;
-
- if (!cmdq_free(cmdq) && !cdata->bflag)
- cmdq_continue(cmdq);
-
- free(cdata->cmd_else);
- free(cdata->cmd_if);
+ if (new_cmdq != NULL) {
+ if (cdata->cmdq == NULL)
+ cmdq_append(c, new_cmdq);
+ else
+ cmdq_insert_after(cdata->cmdq, new_cmdq);
+ }
- free(cdata->file);
- free(cdata);
+out:
+ if (cdata->cmdq != NULL)
+ cdata->cmdq->flags &= ~CMD_Q_WAITING;
}
static void
cmd_if_shell_free(void *data)
{
struct cmd_if_shell_data *cdata = data;
- struct cmd_q *cmdq = cdata->cmdq;
-
- if (--cdata->references != 0)
- return;
- if (!cmdq_free(cmdq) && !cdata->bflag)
- cmdq_continue(cmdq);
+ server_client_unref(cdata->client);
free(cdata->cmd_else);
free(cdata->cmd_if);
diff --git a/usr.bin/tmux/cmd-load-buffer.c b/usr.bin/tmux/cmd-load-buffer.c
index fb0f8a187c6..cac5835dd2b 100644
--- a/usr.bin/tmux/cmd-load-buffer.c
+++ b/usr.bin/tmux/cmd-load-buffer.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: cmd-load-buffer.c,v 1.44 2016/10/14 22:14:22 nicm Exp $ */
+/* $OpenBSD: cmd-load-buffer.c,v 1.45 2016/10/16 17:55:14 nicm Exp $ */
/*
* Copyright (c) 2009 Tiago Cunha <me@tiagocunha.org>
@@ -46,17 +46,24 @@ const struct cmd_entry cmd_load_buffer_entry = {
.exec = cmd_load_buffer_exec
};
+struct cmd_load_buffer_data {
+ struct cmd_q *cmdq;
+ char *bufname;
+};
+
static enum cmd_retval
cmd_load_buffer_exec(struct cmd *self, struct cmd_q *cmdq)
{
- struct args *args = self->args;
- struct client *c = cmdq->client;
- struct session *s;
- FILE *f;
- const char *path, *bufname, *cwd;
- char *pdata, *new_pdata, *cause, *file, resolved[PATH_MAX];
- size_t psize;
- int ch, error;
+ struct args *args = self->args;
+ struct cmd_load_buffer_data *cdata;
+ struct client *c = cmdq->client;
+ struct session *s;
+ FILE *f;
+ const char *path, *bufname, *cwd;
+ char *pdata, *new_pdata, *cause, *file;
+ char resolved[PATH_MAX];
+ size_t psize;
+ int ch, error;
bufname = NULL;
if (args_has(args, 'b'))
@@ -64,8 +71,12 @@ cmd_load_buffer_exec(struct cmd *self, struct cmd_q *cmdq)
path = args->argv[0];
if (strcmp(path, "-") == 0) {
+ cdata = xcalloc(1, sizeof *cdata);
+ cdata->cmdq = cmdq;
+ cdata->bufname = xstrdup(bufname);
+
error = server_set_stdin_callback(c, cmd_load_buffer_callback,
- (void *)bufname, &cause);
+ cdata, &cause);
if (error != 0) {
cmdq_error(cmdq, "%s: %s", path, cause);
free(cause);
@@ -136,9 +147,9 @@ error:
static void
cmd_load_buffer_callback(struct client *c, int closed, void *data)
{
- const char *bufname = data;
- char *pdata, *cause, *saved;
- size_t psize;
+ struct cmd_load_buffer_data *cdata = data;
+ char *pdata, *cause, *saved;
+ size_t psize;
if (!closed)
return;
@@ -146,7 +157,7 @@ cmd_load_buffer_callback(struct client *c, int closed, void *data)
server_client_unref(c);
if (c->flags & CLIENT_DEAD)
- return;
+ goto out;
psize = EVBUFFER_LENGTH(c->stdin_data);
if (psize == 0 || (pdata = malloc(psize + 1)) == NULL)
@@ -156,7 +167,7 @@ cmd_load_buffer_callback(struct client *c, int closed, void *data)
pdata[psize] = '\0';
evbuffer_drain(c->stdin_data, psize);
- if (paste_set(pdata, psize, bufname, &cause) != 0) {
+ if (paste_set(pdata, psize, cdata->bufname, &cause) != 0) {
/* No context so can't use server_client_msg_error. */
if (~c->flags & CLIENT_UTF8) {
saved = cause;
@@ -168,7 +179,9 @@ cmd_load_buffer_callback(struct client *c, int closed, void *data)
free(pdata);
free(cause);
}
-
out:
- cmdq_continue(c->cmdq);
+ cdata->cmdq->flags &= ~CMD_Q_WAITING;
+
+ free(cdata->bufname);
+ free(cdata);
}
diff --git a/usr.bin/tmux/cmd-new-session.c b/usr.bin/tmux/cmd-new-session.c
index 3a6608b0c2b..30c89cdec3c 100644
--- a/usr.bin/tmux/cmd-new-session.c
+++ b/usr.bin/tmux/cmd-new-session.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: cmd-new-session.c,v 1.90 2016/10/13 22:48:51 nicm Exp $ */
+/* $OpenBSD: cmd-new-session.c,v 1.91 2016/10/16 17:55:14 nicm Exp $ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
@@ -312,14 +312,14 @@ cmd_new_session_exec(struct cmd *self, struct cmd_q *cmdq)
}
if (!detached)
- cmdq->client_exit = 0;
+ c->flags |= CLIENT_ATTACHED;
if (to_free != NULL)
free((void *)to_free);
cmd_find_from_session(&fs, s);
- if (hooks_wait(s->hooks, cmdq, &fs, "after-new-session") == 0)
- return (CMD_RETURN_WAIT);
+ hooks_insert(s->hooks, cmdq, &fs, "after-new-session");
+
return (CMD_RETURN_NORMAL);
error:
diff --git a/usr.bin/tmux/cmd-new-window.c b/usr.bin/tmux/cmd-new-window.c
index 73f62d01743..5ee6f9c13fe 100644
--- a/usr.bin/tmux/cmd-new-window.c
+++ b/usr.bin/tmux/cmd-new-window.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: cmd-new-window.c,v 1.62 2016/10/13 22:48:51 nicm Exp $ */
+/* $OpenBSD: cmd-new-window.c,v 1.63 2016/10/16 17:55:14 nicm Exp $ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
@@ -157,8 +157,8 @@ cmd_new_window_exec(struct cmd *self, struct cmd_q *cmdq)
free((void *)to_free);
cmd_find_from_winlink(&fs, s, wl);
- if (hooks_wait(s->hooks, cmdq, &fs, "after-new-window") == 0)
- return (CMD_RETURN_WAIT);
+ hooks_insert(s->hooks, cmdq, &fs, "after-new-window");
+
return (CMD_RETURN_NORMAL);
error:
diff --git a/usr.bin/tmux/cmd-queue.c b/usr.bin/tmux/cmd-queue.c
index 7fc277e84b4..23211d53ef7 100644
--- a/usr.bin/tmux/cmd-queue.c
+++ b/usr.bin/tmux/cmd-queue.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: cmd-queue.c,v 1.42 2016/10/15 00:01:01 nicm Exp $ */
+/* $OpenBSD: cmd-queue.c,v 1.43 2016/10/16 17:55:14 nicm Exp $ */
/*
* Copyright (c) 2013 Nicholas Marriott <nicholas.marriott@gmail.com>
@@ -25,47 +25,316 @@
#include "tmux.h"
-static enum cmd_retval cmdq_continue_one(struct cmd_q *);
-static void cmdq_flush(struct cmd_q *);
+/* Global command queue. */
+static struct cmd_q_list global_queue = TAILQ_HEAD_INITIALIZER(global_queue);
-/* Create new command queue. */
+/* Get command queue name. */
+static const char *
+cmdq_name(struct client *c)
+{
+ static char s[32];
+
+ if (c == NULL)
+ return ("<global>");
+ xsnprintf(s, sizeof s, "<%p>", c);
+ return (s);
+}
+
+/* Get command queue from client. */
+static struct cmd_q_list *
+cmdq_get(struct client *c)
+{
+ if (c == NULL)
+ return (&global_queue);
+ return (&c->queue);
+}
+
+/* Append an item. */
+void
+cmdq_append(struct client *c, struct cmd_q *cmdq)
+{
+ struct cmd_q_list *queue = cmdq_get(c);
+ struct cmd_q *next;
+
+ do {
+ next = cmdq->next;
+ cmdq->next = NULL;
+
+ if (c != NULL)
+ c->references++;
+ cmdq->client = c;
+
+ cmdq->queue = queue;
+ TAILQ_INSERT_TAIL(queue, cmdq, entry);
+
+ cmdq = next;
+ } while (cmdq != NULL);
+}
+
+/* Insert an item. */
+void
+cmdq_insert_after(struct cmd_q *after, struct cmd_q *cmdq)
+{
+ struct client *c = after->client;
+ struct cmd_q_list *queue = after->queue;
+ struct cmd_q *next;
+
+ do {
+ next = cmdq->next;
+ cmdq->next = NULL;
+
+ if (c != NULL)
+ c->references++;
+ cmdq->client = c;
+
+ cmdq->queue = queue;
+ if (after->next != NULL)
+ TAILQ_INSERT_AFTER(queue, after->next, cmdq, entry);
+ else
+ TAILQ_INSERT_AFTER(queue, after, cmdq, entry);
+ after->next = cmdq;
+
+ cmdq = next;
+ } while (cmdq != NULL);
+}
+
+/* Remove an item. */
+static void
+cmdq_remove(struct cmd_q *cmdq)
+{
+ free((void *)cmdq->hook);
+
+ if (cmdq->client != NULL)
+ server_client_unref(cmdq->client);
+
+ if (cmdq->type == CMD_Q_COMMAND)
+ cmd_list_free(cmdq->cmdlist);
+
+ TAILQ_REMOVE(cmdq->queue, cmdq, entry);
+ free(cmdq);
+}
+
+/* Set command group. */
+static u_int
+cmdq_next_group(void)
+{
+ static u_int group;
+
+ return (++group);
+}
+
+/* Remove all subsequent items that match this item's group. */
+static void
+cmdq_remove_group(struct cmd_q *cmdq)
+{
+ struct cmd_q *this, *next;
+
+ this = TAILQ_NEXT(cmdq, entry);
+ while (this != NULL) {
+ next = TAILQ_NEXT(this, entry);
+ if (this->group == cmdq->group)
+ cmdq_remove(this);
+ this = next;
+ }
+}
+
+/* Get a command for the command queue. */
struct cmd_q *
-cmdq_new(struct client *c)
+cmdq_get_command(struct cmd_list *cmdlist, struct cmd_find_state *current,
+ struct mouse_event *m, int flags)
{
- struct cmd_q *cmdq;
+ struct cmd_q *cmdq, *first = NULL, *last = NULL;
+ struct cmd *cmd;
+ u_int group = cmdq_next_group();
+
+ TAILQ_FOREACH(cmd, &cmdlist->list, qentry) {
+ cmdq = xcalloc(1, sizeof *cmdq);
+ cmdq->type = CMD_Q_COMMAND;
+ cmdq->group = group;
+ cmdq->flags = flags;
+
+ cmdq->cmdlist = cmdlist;
+ cmdq->cmd = cmd;
+
+ if (current != NULL)
+ cmd_find_copy_state(&cmdq->current, current);
+ if (m != NULL)
+ memcpy(&cmdq->mouse, m, sizeof cmdq->mouse);
+ cmdlist->references++;
+
+ if (first == NULL)
+ first = cmdq;
+ if (last != NULL)
+ last->next = cmdq;
+ last = cmdq;
+ }
+ return (first);
+}
- cmdq = xcalloc(1, sizeof *cmdq);
- cmdq->references = 1;
- cmdq->flags = 0;
+/* Fire command on command queue. */
+static enum cmd_retval
+cmdq_fire_command(struct cmd_q *cmdq)
+{
+ struct client *c = cmdq->client;
+ struct cmd *cmd = cmdq->cmd;
+ enum cmd_retval retval;
+ const char *name;
+ struct cmd_find_state *fsp, fs;
+ int flags;
+
+ flags = !!(cmd->flags & CMD_CONTROL);
+ cmdq_guard(cmdq, "begin", flags);
+
+ if (cmd_prepare_state(cmd, cmdq) != 0) {
+ retval = CMD_RETURN_ERROR;
+ goto out;
+ }
+ if (cmdq->client == NULL)
+ cmdq->client = cmd_find_client(cmdq, NULL, CMD_FIND_QUIET);
+ retval = cmd->entry->exec(cmd, cmdq);
+ if (retval == CMD_RETURN_ERROR)
+ goto out;
+
+ if (cmd->entry->flags & CMD_AFTERHOOK) {
+ name = cmd->entry->name;
+ if (cmd_find_valid_state(&cmdq->state.tflag))
+ fsp = &cmdq->state.tflag;
+ else {
+ if (cmd_find_current(&fs, cmdq, CMD_FIND_QUIET) != 0)
+ goto out;
+ fsp = &fs;
+ }
+ hooks_insert(fsp->s->hooks, cmdq, fsp, "after-%s", name);
+ }
+
+out:
cmdq->client = c;
- cmdq->client_exit = -1;
+ if (retval == CMD_RETURN_ERROR)
+ cmdq_guard(cmdq, "error", flags);
+ else
+ cmdq_guard(cmdq, "end", flags);
+ return (retval);
+}
- TAILQ_INIT(&cmdq->queue);
- cmdq->item = NULL;
- cmdq->cmd = NULL;
+/* Get a callback for the command queue. */
+struct cmd_q *
+cmdq_get_callback(cmd_q_cb cb, void *data)
+{
+ struct cmd_q *cmdq;
+
+ cmdq = xcalloc(1, sizeof *cmdq);
+ cmdq->type = CMD_Q_CALLBACK;
+ cmdq->group = 0;
+ cmdq->flags = 0;
- cmd_find_clear_state(&cmdq->current, NULL, 0);
- cmdq->parent = NULL;
+ cmdq->cb = cb;
+ cmdq->data = data;
return (cmdq);
}
-/* Free command queue */
-int
-cmdq_free(struct cmd_q *cmdq)
+/* Fire callback on callback queue. */
+static enum cmd_retval
+cmdq_fire_callback(struct cmd_q *cmdq)
{
- log_debug("cmdq %p free: %u references", cmdq, cmdq->references);
+ return (cmdq->cb(cmdq, cmdq->data));
+}
+
+/* Process next item on command queue. */
+u_int
+cmdq_next(struct client *c)
+{
+ struct cmd_q_list *queue = cmdq_get(c);
+ const char *name = cmdq_name(c);
+ struct cmd_q *cmdq;
+ enum cmd_retval retval;
+ u_int items = 0;
+ static u_int number;
- if (--cmdq->references != 0) {
- if (cmdq->flags & CMD_Q_DEAD)
- return (1);
+ if (TAILQ_EMPTY(queue)) {
+ log_debug("%s %s: empty", __func__, name);
+ return (0);
+ }
+ if (TAILQ_FIRST(queue)->flags & CMD_Q_WAITING) {
+ log_debug("%s %s: waiting", __func__, name);
return (0);
}
- cmdq_flush(cmdq);
- free(cmdq);
- return (1);
+ log_debug("%s %s: enter", __func__, name);
+ for (;;) {
+ cmdq = TAILQ_FIRST(queue);
+ if (cmdq == NULL)
+ break;
+ log_debug("%s %s: type %d, flags %x", __func__, name,
+ cmdq->type, cmdq->flags);
+
+ /*
+ * Any item with the waiting flag set waits until an external
+ * event clears the flag (for example, a job - look at
+ * run-shell).
+ */
+ if (cmdq->flags & CMD_Q_WAITING)
+ goto waiting;
+
+ /*
+ * Items are only fired once, once the fired flag is set, a
+ * waiting flag can only be cleared by an external event.
+ */
+ if (~cmdq->flags & CMD_Q_FIRED) {
+ cmdq->time = time(NULL);
+ cmdq->number = ++number;
+
+ switch (cmdq->type)
+ {
+ case CMD_Q_COMMAND:
+ retval = cmdq_fire_command(cmdq);
+
+ /*
+ * If a command returns an error, remove any
+ * subsequent commands in the same group.
+ */
+ if (retval == CMD_RETURN_ERROR)
+ cmdq_remove_group(cmdq);
+ break;
+ case CMD_Q_CALLBACK:
+ retval = cmdq_fire_callback(cmdq);
+ break;
+ default:
+ retval = CMD_RETURN_ERROR;
+ break;
+ }
+ cmdq->flags |= CMD_Q_FIRED;
+
+ if (retval == CMD_RETURN_WAIT) {
+ cmdq->flags |= CMD_Q_WAITING;
+ goto waiting;
+ }
+ items++;
+ }
+ cmdq_remove(cmdq);
+ }
+
+ log_debug("%s %s: exit (empty)", __func__, name);
+ return (items);
+
+waiting:
+ log_debug("%s %s: exit (wait)", __func__, name);
+ return (items);
+}
+
+/* Print a guard line. */
+void
+cmdq_guard(struct cmd_q *cmdq, const char *guard, int flags)
+{
+ struct client *c = cmdq->client;
+
+ if (c == NULL || !(c->flags & CLIENT_CONTROL))
+ return;
+
+ evbuffer_add_printf(c->stdout_data, "%%%s %ld %u %d\n", guard,
+ (long)cmdq->time, cmdq->number, flags);
+ server_client_push_stdout(c);
}
/* Show message from command. */
@@ -140,175 +409,3 @@ cmdq_error(struct cmd_q *cmdq, const char *fmt, ...)
free(msg);
}
-
-/* Print a guard line. */
-void
-cmdq_guard(struct cmd_q *cmdq, const char *guard, int flags)
-{
- struct client *c = cmdq->client;
-
- if (c == NULL || !(c->flags & CLIENT_CONTROL))
- return;
-
- evbuffer_add_printf(c->stdout_data, "%%%s %ld %u %d\n", guard,
- (long) cmdq->time, cmdq->number, flags);
- server_client_push_stdout(c);
-}
-
-/* Add command list to queue and begin processing if needed. */
-void
-cmdq_run(struct cmd_q *cmdq, struct cmd_list *cmdlist, struct mouse_event *m)
-{
- cmdq_append(cmdq, cmdlist, m);
-
- 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 mouse_event *m)
-{
- struct cmd_q_item *item;
-
- item = xcalloc(1, sizeof *item);
- item->cmdlist = cmdlist;
- TAILQ_INSERT_TAIL(&cmdq->queue, item, qentry);
- cmdlist->references++;
-
- if (m != NULL)
- memcpy(&item->mouse, m, sizeof item->mouse);
- else
- item->mouse.valid = 0;
-}
-
-/* Process one command. */
-static enum cmd_retval
-cmdq_continue_one(struct cmd_q *cmdq)
-{
- struct cmd_list *cmdlist = cmdq->item->cmdlist;
- struct cmd *cmd = cmdq->cmd;
- enum cmd_retval retval;
- char *tmp;
- int flags = !!(cmd->flags & CMD_CONTROL);
- const char *name;
- struct cmd_find_state *fsp, fs;
-
- cmdlist->references++;
-
- tmp = cmd_print(cmd);
- log_debug("cmdq %p: %s", cmdq, tmp);
- free(tmp);
-
- cmdq->time = time(NULL);
- cmdq->number++;
-
- cmdq_guard(cmdq, "begin", flags);
-
- if (cmd_prepare_state(cmd, cmdq, cmdq->parent) != 0)
- goto error;
-
- retval = cmd->entry->exec(cmd, cmdq);
- if (retval == CMD_RETURN_ERROR)
- goto error;
-
- if (~cmd->entry->flags & CMD_AFTERHOOK)
- goto end;
-
- if (cmd_find_valid_state(&cmdq->state.tflag))
- fsp = &cmdq->state.tflag;
- else {
- if (cmd_find_current(&fs, cmdq, CMD_FIND_QUIET) != 0)
- goto end;
- fsp = &fs;
- }
- name = cmd->entry->name;
- if (hooks_wait(fsp->s->hooks, cmdq, fsp, "after-%s", name) == 0)
- retval = CMD_RETURN_WAIT;
-
-end:
- cmdq_guard(cmdq, "end", flags);
- cmd_list_free(cmdlist);
- return (retval);
-
-error:
- cmdq_guard(cmdq, "error", flags);
- cmd_list_free(cmdlist);
- return (CMD_RETURN_ERROR);
-}
-
-/* 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 empty;
-
- log_debug("continuing cmdq %p: flags %#x (%p)", cmdq, cmdq->flags, c);
- cmdq->references++;
-
- 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 {
- while (cmdq->cmd != NULL) {
- retval = cmdq_continue_one(cmdq);
- 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);
- }
- next = TAILQ_NEXT(cmdq->item, 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:
- log_debug("cmdq %p empty", cmdq);
- if (cmdq->client_exit > 0)
- cmdq->client->flags |= CLIENT_EXIT;
- if (cmdq->emptyfn != NULL)
- cmdq->emptyfn(cmdq);
- empty = 1;
-
-out:
- cmdq_free(cmdq);
- return (empty);
-}
-
-/* Flush command queue. */
-static 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/usr.bin/tmux/cmd-resize-pane.c b/usr.bin/tmux/cmd-resize-pane.c
index 342337eef0d..e6295c74a35 100644
--- a/usr.bin/tmux/cmd-resize-pane.c
+++ b/usr.bin/tmux/cmd-resize-pane.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: cmd-resize-pane.c,v 1.26 2016/10/14 22:14:22 nicm Exp $ */
+/* $OpenBSD: cmd-resize-pane.c,v 1.27 2016/10/16 17:55:14 nicm Exp $ */
/*
* Copyright (c) 2009 Nicholas Marriott <nicholas.marriott@gmail.com>
@@ -60,12 +60,12 @@ cmd_resize_pane_exec(struct cmd *self, struct cmd_q *cmdq)
int x, y;
if (args_has(args, 'M')) {
- if (cmd_mouse_window(&cmdq->item->mouse, &s) == NULL)
+ if (cmd_mouse_window(&cmdq->mouse, &s) == NULL)
return (CMD_RETURN_NORMAL);
if (c == NULL || c->session != s)
return (CMD_RETURN_NORMAL);
c->tty.mouse_drag_update = cmd_resize_pane_mouse_update;
- cmd_resize_pane_mouse_update(c, &cmdq->item->mouse);
+ cmd_resize_pane_mouse_update(c, &cmdq->mouse);
return (CMD_RETURN_NORMAL);
}
diff --git a/usr.bin/tmux/cmd-run-shell.c b/usr.bin/tmux/cmd-run-shell.c
index e1f4795b506..2afe8e13589 100644
--- a/usr.bin/tmux/cmd-run-shell.c
+++ b/usr.bin/tmux/cmd-run-shell.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: cmd-run-shell.c,v 1.39 2016/10/15 23:06:39 nicm Exp $ */
+/* $OpenBSD: cmd-run-shell.c,v 1.40 2016/10/16 17:55:14 nicm Exp $ */
/*
* Copyright (c) 2009 Tiago Cunha <me@tiagocunha.org>
@@ -51,7 +51,6 @@ const struct cmd_entry cmd_run_shell_entry = {
struct cmd_run_shell_data {
char *cmd;
struct cmd_q *cmdq;
- int bflag;
int wp_id;
};
@@ -92,6 +91,7 @@ cmd_run_shell_exec(struct cmd *self, struct cmd_q *cmdq)
cwd = s->cwd;
else
cwd = NULL;
+
ft = format_create(cmdq, 0);
format_defaults(ft, cmdq->state.c, s, wl, wp);
shellcmd = format_expand(ft, args->argv[0]);
@@ -99,20 +99,24 @@ cmd_run_shell_exec(struct cmd *self, struct cmd_q *cmdq)
cdata = xcalloc(1, sizeof *cdata);
cdata->cmd = shellcmd;
- cdata->bflag = args_has(args, 'b');
if (args_has(args, 't') && wp != NULL)
cdata->wp_id = wp->id;
else
cdata->wp_id = -1;
- cdata->cmdq = cmdq;
- cmdq->references++;
+ if (args_has(args, 't') && wp != NULL)
+ cdata->wp_id = wp->id;
+ else
+ cdata->wp_id = -1;
+
+ if (!args_has(args, 'b'))
+ cdata->cmdq = cmdq;
job_run(shellcmd, s, cwd, cmd_run_shell_callback, cmd_run_shell_free,
cdata);
- if (cdata->bflag)
+ if (args_has(args, 'b'))
return (CMD_RETURN_NORMAL);
return (CMD_RETURN_WAIT);
}
@@ -121,16 +125,11 @@ static void
cmd_run_shell_callback(struct job *job)
{
struct cmd_run_shell_data *cdata = job->data;
- struct cmd_q *cmdq = cdata->cmdq;
- char *cmd, *msg, *line;
+ char *cmd = cdata->cmd, *msg, *line;
size_t size;
int retcode;
u_int lines;
- if (cmdq->flags & CMD_Q_DEAD)
- return;
- cmd = cdata->cmd;
-
lines = 0;
do {
if ((line = evbuffer_readline(job->event->input)) != NULL) {
@@ -163,16 +162,15 @@ cmd_run_shell_callback(struct job *job)
if (msg != NULL)
cmd_run_shell_print(job, msg);
free(msg);
+
+ if (cdata->cmdq != NULL)
+ cdata->cmdq->flags &= ~CMD_Q_WAITING;
}
static void
cmd_run_shell_free(void *data)
{
struct cmd_run_shell_data *cdata = data;
- struct cmd_q *cmdq = cdata->cmdq;
-
- if (!cmdq_free(cmdq) && !cdata->bflag)
- cmdq_continue(cmdq);
free(cdata->cmd);
free(cdata);
diff --git a/usr.bin/tmux/cmd-send-keys.c b/usr.bin/tmux/cmd-send-keys.c
index b8a213c4fbf..001f8b5afbd 100644
--- a/usr.bin/tmux/cmd-send-keys.c
+++ b/usr.bin/tmux/cmd-send-keys.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: cmd-send-keys.c,v 1.31 2016/10/14 22:14:22 nicm Exp $ */
+/* $OpenBSD: cmd-send-keys.c,v 1.32 2016/10/16 17:55:14 nicm Exp $ */
/*
* Copyright (c) 2008 Nicholas Marriott <nicholas.marriott@gmail.com>
@@ -62,7 +62,7 @@ cmd_send_keys_exec(struct cmd *self, struct cmd_q *cmdq)
struct client *c = cmdq->state.c;
struct window_pane *wp = cmdq->state.tflag.wp;
struct session *s = cmdq->state.tflag.s;
- struct mouse_event *m = &cmdq->item->mouse;
+ struct mouse_event *m = &cmdq->mouse;
const u_char *keystr;
int i, literal;
key_code key;
diff --git a/usr.bin/tmux/cmd-source-file.c b/usr.bin/tmux/cmd-source-file.c
index 5f00d8273b9..e48befd4028 100644
--- a/usr.bin/tmux/cmd-source-file.c
+++ b/usr.bin/tmux/cmd-source-file.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: cmd-source-file.c,v 1.28 2016/10/14 18:41:53 nicm Exp $ */
+/* $OpenBSD: cmd-source-file.c,v 1.29 2016/10/16 17:55:14 nicm Exp $ */
/*
* Copyright (c) 2008 Tiago Cunha <me@tiagocunha.org>
@@ -28,7 +28,7 @@
static enum cmd_retval cmd_source_file_exec(struct cmd *, struct cmd_q *);
-static void cmd_source_file_done(struct cmd_q *);
+static enum cmd_retval cmd_source_file_done(struct cmd_q *, void *);
const struct cmd_entry cmd_source_file_entry = {
.name = "source-file",
@@ -45,53 +45,31 @@ static enum cmd_retval
cmd_source_file_exec(struct cmd *self, struct cmd_q *cmdq)
{
struct args *args = self->args;
- struct cmd_q *cmdq1;
+ struct client *c = cmdq->client;
int quiet;
-
- cmdq1 = cmdq_new(cmdq->client);
- cmdq1->emptyfn = cmd_source_file_done;
- cmdq1->data = cmdq;
+ struct cmd_q *new_cmdq;
quiet = args_has(args, 'q');
- switch (load_cfg(args->argv[0], cmdq1, quiet)) {
+ switch (load_cfg(args->argv[0], c, cmdq, quiet)) {
case -1:
- cmdq_free(cmdq1);
- if (cfg_references == 0) {
+ if (cfg_finished)
cfg_print_causes(cmdq);
- return (CMD_RETURN_ERROR);
- }
- return (CMD_RETURN_NORMAL);
+ return (CMD_RETURN_ERROR);
case 0:
- cmdq_free(cmdq1);
- if (cfg_references == 0)
+ if (cfg_finished)
cfg_print_causes(cmdq);
return (CMD_RETURN_NORMAL);
}
-
- log_debug("%s: cmdq %p, parent %p", __func__, cmdq1, cmdq);
-
- cmdq->references++;
- cfg_references++;
-
- cmdq_continue(cmdq1);
- return (CMD_RETURN_WAIT);
+ if (cfg_finished) {
+ new_cmdq = cmdq_get_callback(cmd_source_file_done, NULL);
+ cmdq_insert_after(cmdq, new_cmdq);
+ }
+ return (CMD_RETURN_NORMAL);
}
-static void
-cmd_source_file_done(struct cmd_q *cmdq1)
+static enum cmd_retval
+cmd_source_file_done(struct cmd_q *cmdq, __unused void *data)
{
- struct cmd_q *cmdq = cmdq1->data;
-
- log_debug("%s: cmdq %p, parent %p", __func__, cmdq1, cmdq);
-
- if (cmdq1->client_exit >= 0)
- cmdq->client_exit = cmdq1->client_exit;
- cmdq_free(cmdq1);
-
- cfg_references--;
- if (cmdq_free(cmdq))
- return;
- if (cfg_references == 0)
- cfg_print_causes(cmdq);
- cmdq_continue(cmdq);
+ cfg_print_causes(cmdq);
+ return (CMD_RETURN_NORMAL);
}
diff --git a/usr.bin/tmux/cmd-split-window.c b/usr.bin/tmux/cmd-split-window.c
index f42e6428ead..db453271150 100644
--- a/usr.bin/tmux/cmd-split-window.c
+++ b/usr.bin/tmux/cmd-split-window.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: cmd-split-window.c,v 1.73 2016/10/13 22:48:51 nicm Exp $ */
+/* $OpenBSD: cmd-split-window.c,v 1.74 2016/10/16 17:55:14 nicm Exp $ */
/*
* Copyright (c) 2009 Nicholas Marriott <nicholas.marriott@gmail.com>
@@ -188,8 +188,8 @@ cmd_split_window_exec(struct cmd *self, struct cmd_q *cmdq)
fs.w = w;
fs.wp = new_wp;
cmd_find_log_state(__func__, &fs);
- if (hooks_wait(s->hooks, cmdq, &fs, "after-split-window") == 0)
- return (CMD_RETURN_WAIT);
+ hooks_insert(s->hooks, cmdq, &fs, "after-split-window");
+
return (CMD_RETURN_NORMAL);
error:
diff --git a/usr.bin/tmux/cmd-wait-for.c b/usr.bin/tmux/cmd-wait-for.c
index 5c7694267fe..f9b4f8694c0 100644
--- a/usr.bin/tmux/cmd-wait-for.c
+++ b/usr.bin/tmux/cmd-wait-for.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: cmd-wait-for.c,v 1.14 2016/10/10 21:51:39 nicm Exp $ */
+/* $OpenBSD: cmd-wait-for.c,v 1.15 2016/10/16 17:55:14 nicm Exp $ */
/*
* Copyright (c) 2013 Nicholas Marriott <nicholas.marriott@gmail.com>
@@ -41,13 +41,18 @@ const struct cmd_entry cmd_wait_for_entry = {
.exec = cmd_wait_for_exec
};
+struct wait_item {
+ struct cmd_q *cmdq;
+ TAILQ_ENTRY(wait_item) entry;
+};
+
struct wait_channel {
const char *name;
int locked;
int woken;
- TAILQ_HEAD(, cmd_q) waiters;
- TAILQ_HEAD(, cmd_q) lockers;
+ TAILQ_HEAD(, wait_item) waiters;
+ TAILQ_HEAD(, wait_item) lockers;
RB_ENTRY(wait_channel) entry;
};
@@ -135,7 +140,7 @@ static enum cmd_retval
cmd_wait_for_signal(__unused struct cmd_q *cmdq, const char *name,
struct wait_channel *wc)
{
- struct cmd_q *wq, *wq1;
+ struct wait_item *wi, *wi1;
if (wc == NULL)
wc = cmd_wait_for_add(name);
@@ -147,10 +152,11 @@ cmd_wait_for_signal(__unused struct cmd_q *cmdq, const char *name,
}
log_debug("signal wait channel %s, with waiters", wc->name);
- TAILQ_FOREACH_SAFE(wq, &wc->waiters, waitentry, wq1) {
- TAILQ_REMOVE(&wc->waiters, wq, waitentry);
- if (!cmdq_free(wq))
- cmdq_continue(wq);
+ TAILQ_FOREACH_SAFE(wi, &wc->waiters, entry, wi1) {
+ wi->cmdq->flags &= ~CMD_Q_WAITING;
+
+ TAILQ_REMOVE(&wc->waiters, wi, entry);
+ free(wi);
}
cmd_wait_for_remove(wc);
@@ -158,10 +164,10 @@ cmd_wait_for_signal(__unused struct cmd_q *cmdq, const char *name,
}
static enum cmd_retval
-cmd_wait_for_wait(struct cmd_q *cmdq, const char *name,
- struct wait_channel *wc)
+cmd_wait_for_wait(struct cmd_q *cmdq, const char *name, struct wait_channel *wc)
{
- struct client *c = cmdq->client;
+ struct client *c = cmdq->client;
+ struct wait_item *wi;
if (c == NULL || c->session != NULL) {
cmdq_error(cmdq, "not able to wait");
@@ -178,16 +184,18 @@ cmd_wait_for_wait(struct cmd_q *cmdq, const char *name,
}
log_debug("wait channel %s not woken (%p)", wc->name, c);
- TAILQ_INSERT_TAIL(&wc->waiters, cmdq, waitentry);
- cmdq->references++;
+ wi = xcalloc(1, sizeof *wi);
+ wi->cmdq = cmdq;
+ TAILQ_INSERT_TAIL(&wc->waiters, wi, entry);
return (CMD_RETURN_WAIT);
}
static enum cmd_retval
-cmd_wait_for_lock(struct cmd_q *cmdq, const char *name,
- struct wait_channel *wc)
+cmd_wait_for_lock(struct cmd_q *cmdq, const char *name, struct wait_channel *wc)
{
+ struct wait_item *wi;
+
if (cmdq->client == NULL || cmdq->client->session != NULL) {
cmdq_error(cmdq, "not able to lock");
return (CMD_RETURN_ERROR);
@@ -197,8 +205,9 @@ cmd_wait_for_lock(struct cmd_q *cmdq, const char *name,
wc = cmd_wait_for_add(name);
if (wc->locked) {
- TAILQ_INSERT_TAIL(&wc->lockers, cmdq, waitentry);
- cmdq->references++;
+ wi = xcalloc(1, sizeof *wi);
+ wi->cmdq = cmdq;
+ TAILQ_INSERT_TAIL(&wc->lockers, wi, entry);
return (CMD_RETURN_WAIT);
}
wc->locked = 1;
@@ -210,17 +219,17 @@ static enum cmd_retval
cmd_wait_for_unlock(struct cmd_q *cmdq, const char *name,
struct wait_channel *wc)
{
- struct cmd_q *wq;
+ struct wait_item *wi;
if (wc == NULL || !wc->locked) {
cmdq_error(cmdq, "channel %s not locked", name);
return (CMD_RETURN_ERROR);
}
- if ((wq = TAILQ_FIRST(&wc->lockers)) != NULL) {
- TAILQ_REMOVE(&wc->lockers, wq, waitentry);
- if (!cmdq_free(wq))
- cmdq_continue(wq);
+ if ((wi = TAILQ_FIRST(&wc->lockers)) != NULL) {
+ wi->cmdq->flags &= ~CMD_Q_WAITING;
+ TAILQ_REMOVE(&wc->lockers, wi, entry);
+ free(wi);
} else {
wc->locked = 0;
cmd_wait_for_remove(wc);
@@ -233,19 +242,19 @@ void
cmd_wait_for_flush(void)
{
struct wait_channel *wc, *wc1;
- struct cmd_q *wq, *wq1;
+ struct wait_item *wi, *wi1;
RB_FOREACH_SAFE(wc, wait_channels, &wait_channels, wc1) {
- TAILQ_FOREACH_SAFE(wq, &wc->waiters, waitentry, wq1) {
- TAILQ_REMOVE(&wc->waiters, wq, waitentry);
- if (!cmdq_free(wq))
- cmdq_continue(wq);
+ TAILQ_FOREACH_SAFE(wi, &wc->waiters, entry, wi1) {
+ wi->cmdq->flags &= ~CMD_Q_WAITING;
+ TAILQ_REMOVE(&wc->waiters, wi, entry);
+ free(wi);
}
wc->woken = 1;
- TAILQ_FOREACH_SAFE(wq, &wc->lockers, waitentry, wq1) {
- TAILQ_REMOVE(&wc->lockers, wq, waitentry);
- if (!cmdq_free(wq))
- cmdq_continue(wq);
+ TAILQ_FOREACH_SAFE(wi, &wc->lockers, entry, wi1) {
+ wi->cmdq->flags &= ~CMD_Q_WAITING;
+ TAILQ_REMOVE(&wc->lockers, wi, entry);
+ free(wi);
}
wc->locked = 0;
cmd_wait_for_remove(wc);
diff --git a/usr.bin/tmux/cmd.c b/usr.bin/tmux/cmd.c
index fb51e13e711..18ab02b5d6e 100644
--- a/usr.bin/tmux/cmd.c
+++ b/usr.bin/tmux/cmd.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: cmd.c,v 1.124 2016/10/13 10:01:49 nicm Exp $ */
+/* $OpenBSD: cmd.c,v 1.125 2016/10/16 17:55:14 nicm Exp $ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
@@ -390,12 +390,11 @@ usage:
static int
cmd_prepare_state_flag(char c, const char *target, enum cmd_entry_flag flag,
- struct cmd_q *cmdq, struct cmd_q *parent)
+ struct cmd_q *cmdq)
{
int targetflags, error;
struct cmd_find_state *fs = NULL;
- struct cmd_find_state *current = NULL;
- struct cmd_find_state tmp;
+ struct cmd_find_state current;
if (flag == CMD_NONE ||
flag == CMD_CLIENT ||
@@ -449,21 +448,12 @@ cmd_prepare_state_flag(char c, const char *target, enum cmd_entry_flag flag,
default:
fatalx("unknown %cflag %d", c, flag);
}
-
log_debug("%s: flag %c %d %#x", __func__, c, flag, targetflags);
- if (parent != NULL) {
- if (c == 't')
- current = &parent->state.tflag;
- else if (c == 's')
- current = &parent->state.sflag;
- }
- if (current == NULL || !cmd_find_valid_state(current)) {
- error = cmd_find_current(&tmp, cmdq, targetflags);
- if (error != 0 && ~targetflags & CMD_FIND_QUIET)
- return (-1);
- current = &tmp;
- }
- if (!cmd_find_empty_state(current) && !cmd_find_valid_state(current))
+
+ error = cmd_find_current(&current, cmdq, targetflags);
+ if (error != 0 && ~targetflags & CMD_FIND_QUIET)
+ return (-1);
+ if (!cmd_find_empty_state(&current) && !cmd_find_valid_state(&current))
fatalx("invalid current state");
switch (flag) {
@@ -475,13 +465,13 @@ cmd_prepare_state_flag(char c, const char *target, enum cmd_entry_flag flag,
case CMD_SESSION_CANFAIL:
case CMD_SESSION_PREFERUNATTACHED:
case CMD_SESSION_WITHPANE:
- error = cmd_find_target(fs, current, cmdq, target,
+ error = cmd_find_target(fs, &current, cmdq, target,
CMD_FIND_SESSION, targetflags);
if (error != 0 && ~targetflags & CMD_FIND_QUIET)
return (-1);
break;
case CMD_MOVEW_R:
- error = cmd_find_target(fs, current, cmdq, target,
+ error = cmd_find_target(fs, &current, cmdq, target,
CMD_FIND_SESSION, CMD_FIND_QUIET);
if (error == 0)
break;
@@ -490,7 +480,7 @@ cmd_prepare_state_flag(char c, const char *target, enum cmd_entry_flag flag,
case CMD_WINDOW_CANFAIL:
case CMD_WINDOW_MARKED:
case CMD_WINDOW_INDEX:
- error = cmd_find_target(fs, current, cmdq, target,
+ error = cmd_find_target(fs, &current, cmdq, target,
CMD_FIND_WINDOW, targetflags);
if (error != 0 && ~targetflags & CMD_FIND_QUIET)
return (-1);
@@ -498,7 +488,7 @@ cmd_prepare_state_flag(char c, const char *target, enum cmd_entry_flag flag,
case CMD_PANE:
case CMD_PANE_CANFAIL:
case CMD_PANE_MARKED:
- error = cmd_find_target(fs, current, cmdq, target,
+ error = cmd_find_target(fs, &current, cmdq, target,
CMD_FIND_PANE, targetflags);
if (error != 0 && ~targetflags & CMD_FIND_QUIET)
return (-1);
@@ -510,14 +500,14 @@ cmd_prepare_state_flag(char c, const char *target, enum cmd_entry_flag flag,
}
int
-cmd_prepare_state(struct cmd *cmd, struct cmd_q *cmdq, struct cmd_q *parent)
+cmd_prepare_state(struct cmd *cmd, struct cmd_q *cmdq)
{
- const struct cmd_entry *entry = cmd->entry;
- struct cmd_state *state = &cmdq->state;
- char *tmp;
- enum cmd_entry_flag flag;
- const char *s;
- int error;
+ const struct cmd_entry *entry = cmd->entry;
+ struct cmd_state *state = &cmdq->state;
+ char *tmp;
+ enum cmd_entry_flag flag;
+ const char *s;
+ int error;
tmp = cmd_print(cmd);
log_debug("preparing state for %s (client %p)", tmp, cmdq->client);
@@ -546,18 +536,19 @@ cmd_prepare_state(struct cmd *cmd, struct cmd_q *cmdq, struct cmd_q *parent)
state->c = cmd_find_client(cmdq, s, 1);
break;
}
+ log_debug("using client %p", state->c);
s = args_get(cmd->args, 't');
log_debug("preparing -t state: target %s", s == NULL ? "none" : s);
- error = cmd_prepare_state_flag('t', s, entry->tflag, cmdq, parent);
+ error = cmd_prepare_state_flag('t', s, entry->tflag, cmdq);
if (error != 0)
return (error);
s = args_get(cmd->args, 's');
log_debug("preparing -s state: target %s", s == NULL ? "none" : s);
- error = cmd_prepare_state_flag('s', s, entry->sflag, cmdq, parent);
+ error = cmd_prepare_state_flag('s', s, entry->sflag, cmdq);
if (error != 0)
return (error);
diff --git a/usr.bin/tmux/control.c b/usr.bin/tmux/control.c
index 65bba931376..53979b0f09f 100644
--- a/usr.bin/tmux/control.c
+++ b/usr.bin/tmux/control.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: control.c,v 1.17 2016/01/19 15:59:12 nicm Exp $ */
+/* $OpenBSD: control.c,v 1.18 2016/10/16 17:55:14 nicm Exp $ */
/*
* Copyright (c) 2012 Nicholas Marriott <nicholas.marriott@gmail.com>
@@ -49,6 +49,21 @@ control_write_buffer(struct client *c, struct evbuffer *buffer)
server_client_push_stdout(c);
}
+/* Control error callback. */
+static enum cmd_retval
+control_error(struct cmd_q *cmdq, void *data)
+{
+ struct client *c = cmdq->client;
+ char *error = data;
+
+ cmdq_guard(cmdq, "begin", 1);
+ control_write(c, "parse error: %s", error);
+ cmdq_guard(cmdq, "error", 1);
+
+ free(error);
+ return (CMD_RETURN_NORMAL);
+}
+
/* Control input callback. Read lines and fire commands. */
void
control_callback(struct client *c, int closed, __unused void *data)
@@ -56,6 +71,7 @@ control_callback(struct client *c, int closed, __unused void *data)
char *line, *cause;
struct cmd_list *cmdlist;
struct cmd *cmd;
+ struct cmd_q *cmdq;
if (closed)
c->flags |= CLIENT_EXIT;
@@ -70,18 +86,13 @@ control_callback(struct client *c, int closed, __unused void *data)
}
if (cmd_string_parse(line, &cmdlist, NULL, 0, &cause) != 0) {
- c->cmdq->time = time(NULL);
- c->cmdq->number++;
-
- cmdq_guard(c->cmdq, "begin", 1);
- control_write(c, "parse error: %s", cause);
- cmdq_guard(c->cmdq, "error", 1);
-
- free(cause);
+ cmdq = cmdq_get_callback(control_error, cause);
+ cmdq_append(c, cmdq);
} else {
TAILQ_FOREACH(cmd, &cmdlist->list, qentry)
cmd->flags |= CMD_CONTROL;
- cmdq_run(c->cmdq, cmdlist, NULL);
+ cmdq = cmdq_get_command(cmdlist, NULL, NULL, 0);
+ cmdq_append(c, cmdq);
cmd_list_free(cmdlist);
}
diff --git a/usr.bin/tmux/format.c b/usr.bin/tmux/format.c
index 05d61c0e5f6..7953e4618a9 100644
--- a/usr.bin/tmux/format.c
+++ b/usr.bin/tmux/format.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: format.c,v 1.109 2016/10/11 13:45:47 nicm Exp $ */
+/* $OpenBSD: format.c,v 1.110 2016/10/16 17:55:14 nicm Exp $ */
/*
* Copyright (c) 2011 Nicholas Marriott <nicholas.marriott@gmail.com>
@@ -473,7 +473,6 @@ struct format_tree *
format_create(struct cmd_q *cmdq, int flags)
{
struct format_tree *ft;
- struct cmd *cmd;
if (!event_initialized(&format_job_event)) {
evtimer_set(&format_job_event, format_job_timer, NULL);
@@ -491,11 +490,9 @@ format_create(struct cmd_q *cmdq, int flags)
format_add_tv(ft, "start_time", &start_time);
if (cmdq != NULL && cmdq->cmd != NULL)
- format_add(ft, "command_name", "%s", cmdq->cmd->entry->name);
- if (cmdq != NULL && cmdq->parent != NULL) {
- cmd = cmdq->parent->cmd;
- format_add(ft, "command_hooked", "%s", cmd->entry->name);
- }
+ format_add(ft, "command", "%s", cmdq->cmd->entry->name);
+ if (cmdq != NULL && cmdq->hook != NULL)
+ format_add(ft, "hook", "%s", cmdq->hook);
return (ft);
}
diff --git a/usr.bin/tmux/hooks.c b/usr.bin/tmux/hooks.c
index 5b51a0065c9..5547753df21 100644
--- a/usr.bin/tmux/hooks.c
+++ b/usr.bin/tmux/hooks.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: hooks.c,v 1.6 2016/10/13 22:48:51 nicm Exp $ */
+/* $OpenBSD: hooks.c,v 1.7 2016/10/16 17:55:14 nicm Exp $ */
/*
* Copyright (c) 2012 Thomas Adam <thomas@xteddy.org>
@@ -33,7 +33,6 @@ RB_GENERATE_STATIC(hooks_tree, hook, entry, hooks_cmp);
static struct hook *hooks_find1(struct hooks *, const char *);
static void hooks_free1(struct hooks *, struct hook *);
-static void hooks_emptyfn(struct cmd_q *);
static int
hooks_cmp(struct hook *hook1, struct hook *hook2)
@@ -140,28 +139,14 @@ hooks_find(struct hooks *hooks, const char *name)
return (hook);
}
-static void
-hooks_emptyfn(struct cmd_q *hooks_cmdq)
-{
- struct cmd_q *cmdq = hooks_cmdq->data;
-
- if (cmdq != NULL) {
- if (hooks_cmdq->client_exit >= 0)
- cmdq->client_exit = hooks_cmdq->client_exit;
- if (!cmdq_free(cmdq))
- cmdq_continue(cmdq);
- }
- cmdq_free(hooks_cmdq);
-}
-
-int
+void
hooks_run(struct hooks *hooks, struct client *c, struct cmd_find_state *fs,
const char *fmt, ...)
{
struct hook *hook;
- struct cmd_q *hooks_cmdq;
va_list ap;
char *name;
+ struct cmd_q *new_cmdq, *loop;
va_start(ap, fmt);
xvasprintf(&name, fmt, ap);
@@ -170,34 +155,30 @@ hooks_run(struct hooks *hooks, struct client *c, struct cmd_find_state *fs,
hook = hooks_find(hooks, name);
if (hook == NULL) {
free(name);
- return (-1);
+ return;
}
log_debug("running hook %s", name);
- free(name);
- hooks_cmdq = cmdq_new(c);
- hooks_cmdq->flags |= CMD_Q_NOHOOKS;
+ new_cmdq = cmdq_get_command(hook->cmdlist, fs, NULL, CMD_Q_NOHOOKS);
- if (fs != NULL)
- cmd_find_copy_state(&hooks_cmdq->current, fs);
- hooks_cmdq->parent = NULL;
+ for (loop = new_cmdq; loop != NULL; loop = loop->next)
+ loop->hook = xstrdup(name);
+ free(name);
- cmdq_run(hooks_cmdq, hook->cmdlist, NULL);
- cmdq_free(hooks_cmdq);
- return (0);
+ cmdq_append(c, new_cmdq);
}
-int
-hooks_wait(struct hooks *hooks, struct cmd_q *cmdq, struct cmd_find_state *fs,
+void
+hooks_insert(struct hooks *hooks, struct cmd_q *cmdq, struct cmd_find_state *fs,
const char *fmt, ...)
{
struct hook *hook;
- struct cmd_q *hooks_cmdq;
va_list ap;
char *name;
+ struct cmd_q *new_cmdq, *loop;
if (cmdq->flags & CMD_Q_NOHOOKS)
- return (-1);
+ return;
va_start(ap, fmt);
xvasprintf(&name, fmt, ap);
@@ -206,23 +187,18 @@ hooks_wait(struct hooks *hooks, struct cmd_q *cmdq, struct cmd_find_state *fs,
hook = hooks_find(hooks, name);
if (hook == NULL) {
free(name);
- return (-1);
+ return;
}
log_debug("running hook %s (parent %p)", name, cmdq);
- free(name);
-
- hooks_cmdq = cmdq_new(cmdq->client);
- hooks_cmdq->flags |= CMD_Q_NOHOOKS;
- if (fs != NULL)
- cmd_find_copy_state(&hooks_cmdq->current, fs);
- hooks_cmdq->parent = cmdq;
+ new_cmdq = cmdq_get_command(hook->cmdlist, fs, NULL, CMD_Q_NOHOOKS);
- hooks_cmdq->emptyfn = hooks_emptyfn;
- hooks_cmdq->data = cmdq;
+ for (loop = new_cmdq; loop != NULL; loop = loop->next)
+ loop->hook = xstrdup(name);
+ free(name);
if (cmdq != NULL)
- cmdq->references++;
- cmdq_run(hooks_cmdq, hook->cmdlist, NULL);
- return (0);
+ cmdq_insert_after(cmdq, new_cmdq);
+ else
+ cmdq_append(NULL, new_cmdq);
}
diff --git a/usr.bin/tmux/key-bindings.c b/usr.bin/tmux/key-bindings.c
index 7ef7a5b8a54..0b675a7d4cd 100644
--- a/usr.bin/tmux/key-bindings.c
+++ b/usr.bin/tmux/key-bindings.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: key-bindings.c,v 1.60 2016/10/12 13:03:27 nicm Exp $ */
+/* $OpenBSD: key-bindings.c,v 1.61 2016/10/16 17:55:14 nicm Exp $ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
@@ -377,18 +377,22 @@ key_bindings_init(void)
struct cmd_list *cmdlist;
char *cause;
int error;
- struct cmd_q *cmdq;
- cmdq = cmdq_new(NULL);
for (i = 0; i < nitems(defaults); i++) {
error = cmd_string_parse(defaults[i], &cmdlist,
"<default-keys>", i, &cause);
if (error != 0)
fatalx("bad default key");
- cmdq_run(cmdq, cmdlist, NULL);
+ cmdq_append(NULL, cmdq_get_command(cmdlist, NULL, NULL, 0));
cmd_list_free(cmdlist);
}
- cmdq_free(cmdq);
+}
+
+static enum cmd_retval
+key_bindings_read_only(struct cmd_q *cmdq, __unused void *data)
+{
+ cmdq_error(cmdq, "client is read-only");
+ return (CMD_RETURN_ERROR);
}
void
@@ -403,10 +407,8 @@ key_bindings_dispatch(struct key_binding *bd, struct client *c,
if (!(cmd->entry->flags & CMD_READONLY))
readonly = 0;
}
- if (!readonly && (c->flags & CLIENT_READONLY)) {
- cmdq_error(c->cmdq, "client is read-only");
- return;
- }
-
- cmdq_run(c->cmdq, bd->cmdlist, m);
+ if (!readonly && (c->flags & CLIENT_READONLY))
+ cmdq_append(c, cmdq_get_callback(key_bindings_read_only, NULL));
+ else
+ cmdq_append(c, cmdq_get_command(bd->cmdlist, NULL, m, 0));
}
diff --git a/usr.bin/tmux/notify.c b/usr.bin/tmux/notify.c
index 2395e777ca4..502f6e549ba 100644
--- a/usr.bin/tmux/notify.c
+++ b/usr.bin/tmux/notify.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: notify.c,v 1.12 2016/10/15 00:12:58 nicm Exp $ */
+/* $OpenBSD: notify.c,v 1.13 2016/10/16 17:55:14 nicm Exp $ */
/*
* Copyright (c) 2012 George Nachman <tmux@georgester.com>
@@ -66,7 +66,7 @@ notify_hook(struct notify_entry *ne)
const char *name;
struct cmd_find_state fs;
struct hook *hook;
- struct cmd_q *hooks_cmdq;
+ struct cmd_q *new_cmdq, *loop;
name = notify_hooks[ne->type];
if (name == NULL)
@@ -87,14 +87,12 @@ notify_hook(struct notify_entry *ne)
return;
log_debug("notify hook %s", name);
- hooks_cmdq = cmdq_new(NULL);
- hooks_cmdq->flags |= CMD_Q_NOHOOKS;
+ new_cmdq = cmdq_get_command(hook->cmdlist, &fs, NULL, CMD_Q_NOHOOKS);
- cmd_find_copy_state(&hooks_cmdq->current, &fs);
- hooks_cmdq->parent = NULL;
+ for (loop = new_cmdq; loop != NULL; loop = loop->next)
+ loop->hook = xstrdup(name);
- cmdq_run(hooks_cmdq, hook->cmdlist, NULL);
- cmdq_free(hooks_cmdq);
+ cmdq_append(NULL, new_cmdq);
}
static void
diff --git a/usr.bin/tmux/server-client.c b/usr.bin/tmux/server-client.c
index 149fba0e2d3..243e8233ea4 100644
--- a/usr.bin/tmux/server-client.c
+++ b/usr.bin/tmux/server-client.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: server-client.c,v 1.193 2016/10/12 13:03:27 nicm Exp $ */
+/* $OpenBSD: server-client.c,v 1.194 2016/10/16 17:55:14 nicm Exp $ */
/*
* Copyright (c) 2009 Nicholas Marriott <nicholas.marriott@gmail.com>
@@ -126,8 +126,7 @@ server_client_create(int fd)
c->fd = -1;
c->cwd = NULL;
- c->cmdq = cmdq_new(c);
- c->cmdq->client_exit = 1;
+ TAILQ_INIT(&c->queue);
c->stdin_data = evbuffer_new();
c->stdout_data = evbuffer_new();
@@ -244,10 +243,6 @@ server_client_lost(struct client *c)
free(c->prompt_string);
free(c->prompt_buffer);
- c->cmdq->flags |= CMD_Q_DEAD;
- cmdq_free(c->cmdq);
- c->cmdq = NULL;
-
environ_free(c->environ);
proc_remove_peer(c->peer);
@@ -281,6 +276,9 @@ server_client_free(__unused int fd, __unused short events, void *arg)
log_debug("free client %p (%d references)", c, c->references);
+ if (!TAILQ_EMPTY(&c->queue))
+ fatalx("queue not empty");
+
if (c->references == 0)
free(c);
}
@@ -1254,6 +1252,29 @@ server_client_dispatch(struct imsg *imsg, void *arg)
}
}
+/* Callback when command is done. */
+static enum cmd_retval
+server_client_command_done(struct cmd_q *cmdq, __unused void *data)
+{
+ struct client *c = cmdq->client;
+
+ if (~c->flags & CLIENT_ATTACHED)
+ c->flags |= CLIENT_EXIT;
+ return (CMD_RETURN_NORMAL);
+}
+
+/* Show an error message. */
+static enum cmd_retval
+server_client_command_error(struct cmd_q *cmdq, void *data)
+{
+ char *error = data;
+
+ cmdq_error(cmdq, "%s", error);
+ free(error);
+
+ return (CMD_RETURN_NORMAL);
+}
+
/* Handle command message. */
static void
server_client_dispatch_command(struct client *c, struct imsg *imsg)
@@ -1276,7 +1297,7 @@ server_client_dispatch_command(struct client *c, struct imsg *imsg)
argc = data.argc;
if (cmd_unpack_argv(buf, len, argc, &argv) != 0) {
- cmdq_error(c->cmdq, "command too long");
+ cause = xstrdup("command too long");
goto error;
}
@@ -1287,20 +1308,19 @@ server_client_dispatch_command(struct client *c, struct imsg *imsg)
}
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);
- if (c != cfg_client || cfg_finished)
- cmdq_run(c->cmdq, cmdlist, NULL);
- else
- cmdq_append(c->cmdq, cmdlist, NULL);
+ cmdq_append(c, cmdq_get_command(cmdlist, NULL, NULL, 0));
+ cmdq_append(c, cmdq_get_callback(server_client_command_done, NULL));
cmd_list_free(cmdlist);
return;
error:
+ cmdq_append(c, cmdq_get_callback(server_client_command_error, cause));
+
if (cmdlist != NULL)
cmd_list_free(cmdlist);
diff --git a/usr.bin/tmux/server.c b/usr.bin/tmux/server.c
index d7d8f1edb6a..e5787d48f00 100644
--- a/usr.bin/tmux/server.c
+++ b/usr.bin/tmux/server.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: server.c,v 1.161 2016/10/15 00:01:01 nicm Exp $ */
+/* $OpenBSD: server.c,v 1.162 2016/10/16 17:55:14 nicm Exp $ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
@@ -190,10 +190,18 @@ static int
server_loop(void)
{
struct client *c;
+ u_int items;
- server_client_loop();
notify_drain();
+ do {
+ items = cmdq_next(NULL);
+ TAILQ_FOREACH(c, &clients, entry)
+ items += cmdq_next(c);
+ } while (items != 0);
+
+ server_client_loop();
+
if (!options_get_number(global_options, "exit-unattached")) {
if (!RB_EMPTY(&sessions))
return (0);
diff --git a/usr.bin/tmux/tmux.1 b/usr.bin/tmux/tmux.1
index afb55467299..a10040f3793 100644
--- a/usr.bin/tmux/tmux.1
+++ b/usr.bin/tmux/tmux.1
@@ -1,4 +1,4 @@
-.\" $OpenBSD: tmux.1,v 1.508 2016/10/15 12:34:02 jmc Exp $
+.\" $OpenBSD: tmux.1,v 1.509 2016/10/16 17:55:14 nicm Exp $
.\"
.\" Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
.\"
@@ -14,7 +14,7 @@
.\" IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
.\" OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.\"
-.Dd $Mdocdate: October 15 2016 $
+.Dd $Mdocdate: October 16 2016 $
.Dt TMUX 1
.Os
.Sh NAME
@@ -3456,8 +3456,7 @@ The following variables are available, where appropriate:
.It Li "client_tty" Ta "" Ta "Pseudo terminal of client"
.It Li "client_utf8" Ta "" Ta "1 if client supports utf8"
.It Li "client_width" Ta "" Ta "Width of client"
-.It Li "command_hooked" Ta "" Ta "Name of command hooked, if any"
-.It Li "command_name" Ta "" Ta "Name of command in use, if any"
+.It Li "command" Ta "" Ta "Name of command in use, if any"
.It Li "command_list_name" Ta "" Ta "Command name if listing commands"
.It Li "command_list_alias" Ta "" Ta "Command alias if listing commands"
.It Li "command_list_usage" Ta "" Ta "Command usage if listing commands"
@@ -3467,6 +3466,7 @@ The following variables are available, where appropriate:
.It Li "history_bytes" Ta "" Ta "Number of bytes in window history"
.It Li "history_limit" Ta "" Ta "Maximum window history lines"
.It Li "history_size" Ta "" Ta "Size of history in bytes"
+.It Li "hook" Ta "" Ta "Name of running hook, if any"
.It Li "host" Ta "#H" Ta "Hostname of local host"
.It Li "host_short" Ta "#h" Ta "Hostname of local host (no domain name)"
.It Li "insert_flag" Ta "" Ta "Pane insert flag"
diff --git a/usr.bin/tmux/tmux.h b/usr.bin/tmux/tmux.h
index c9c3a849d00..ad36ba4f150 100644
--- a/usr.bin/tmux/tmux.h
+++ b/usr.bin/tmux/tmux.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: tmux.h,v 1.666 2016/10/15 09:27:52 nicm Exp $ */
+/* $OpenBSD: tmux.h,v 1.667 2016/10/16 17:55:14 nicm Exp $ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
@@ -40,6 +40,8 @@ extern char **environ;
struct args;
struct client;
+struct cmd_q;
+struct cmd_q_list;
struct environ;
struct input_ctx;
struct mode_key_cmdstr;
@@ -631,7 +633,6 @@ struct grid {
struct hook {
const char *name;
- struct cmd_q *cmdq;
struct cmd_list *cmdlist;
RB_ENTRY(hook) entry;
@@ -1160,101 +1161,6 @@ struct message_entry {
TAILQ_ENTRY(message_entry) entry;
};
-/* Client connection. */
-struct client {
- struct tmuxpeer *peer;
-
- pid_t pid;
- int fd;
- struct event event;
- int retval;
-
- struct timeval creation_time;
- struct timeval activity_time;
-
- struct environ *environ;
-
- char *title;
- const char *cwd;
-
- char *term;
- char *ttyname;
- struct tty tty;
-
- void (*stdin_callback)(struct client *, int, void *);
- void *stdin_callback_data;
- struct evbuffer *stdin_data;
- int stdin_closed;
- struct evbuffer *stdout_data;
- struct evbuffer *stderr_data;
-
- struct event repeat_timer;
-
- struct event click_timer;
- u_int click_button;
-
- struct event status_timer;
- struct screen status;
-
-#define CLIENT_TERMINAL 0x1
-#define CLIENT_LOGIN 0x2
-#define CLIENT_EXIT 0x4
-#define CLIENT_REDRAW 0x8
-#define CLIENT_STATUS 0x10
-#define CLIENT_REPEAT 0x20
-#define CLIENT_SUSPENDED 0x40
-/* 0x80 unused */
-#define CLIENT_IDENTIFY 0x100
-#define CLIENT_DEAD 0x200
-#define CLIENT_BORDERS 0x400
-#define CLIENT_READONLY 0x800
-#define CLIENT_REDRAWWINDOW 0x1000
-#define CLIENT_CONTROL 0x2000
-#define CLIENT_CONTROLCONTROL 0x4000
-#define CLIENT_FOCUSED 0x8000
-#define CLIENT_UTF8 0x10000
-#define CLIENT_256COLOURS 0x20000
-#define CLIENT_IDENTIFIED 0x40000
-#define CLIENT_STATUSFORCE 0x80000
-#define CLIENT_DOUBLECLICK 0x100000
-#define CLIENT_TRIPLECLICK 0x200000
- int flags;
- struct key_table *keytable;
-
- struct event identify_timer;
- void (*identify_callback)(struct client *, struct window_pane *);
- void *identify_callback_data;
-
- char *message_string;
- struct event message_timer;
- u_int message_next;
- TAILQ_HEAD(, message_entry) message_log;
-
- char *prompt_string;
- struct utf8_data *prompt_buffer;
- size_t prompt_index;
- int (*prompt_callbackfn)(void *, const char *);
- void (*prompt_freefn)(void *);
- void *prompt_data;
- u_int prompt_hindex;
- enum { PROMPT_ENTRY, PROMPT_COMMAND } prompt_mode;
-
-#define PROMPT_SINGLE 0x1
-#define PROMPT_NUMERIC 0x2
- int prompt_flags;
-
- struct session *session;
- struct session *last_session;
-
- int wlmouse;
-
- struct cmd_q *cmdq;
- int references;
-
- TAILQ_ENTRY(client) entry;
-};
-TAILQ_HEAD(clients, client);
-
/* Parsed arguments structures. */
struct args_entry;
RB_HEAD(args_tree, args_entry);
@@ -1324,42 +1230,46 @@ enum cmd_retval {
CMD_RETURN_STOP
};
-/* Command queue entry. */
-struct cmd_q_item {
- struct cmd_list *cmdlist;
-
- struct mouse_event mouse;
-
- TAILQ_ENTRY(cmd_q_item) qentry;
+/* Command queue item type. */
+enum cmd_q_type {
+ CMD_Q_COMMAND,
+ CMD_Q_CALLBACK,
};
-TAILQ_HEAD(cmd_q_items, cmd_q_item);
-/* Command queue. */
+/* Command queue item. */
+typedef enum cmd_retval (*cmd_q_cb) (struct cmd_q *, void *);
struct cmd_q {
- int references;
- int flags;
-#define CMD_Q_DEAD 0x1
-#define CMD_Q_NOHOOKS 0x2
+ struct cmd_q_list *queue;
+ struct cmd_q *next;
struct client *client;
- int client_exit;
- struct cmd_q_items queue;
- struct cmd_q_item *item;
+ enum cmd_q_type type;
+ u_int group;
+
+ u_int number;
+ time_t time;
+
+ const char *hook;
+ int flags;
+#define CMD_Q_FIRED 0x1
+#define CMD_Q_WAITING 0x2
+#define CMD_Q_NOHOOKS 0x4
+
+ struct cmd_list *cmdlist;
struct cmd *cmd;
- struct cmd_q *parent;
+
+ cmd_q_cb cb;
+ void *data;
struct cmd_find_state current;
struct cmd_state state;
- time_t time;
- u_int number;
-
- void (*emptyfn)(struct cmd_q *);
- void *data;
+ struct mouse_event mouse;
- TAILQ_ENTRY(cmd_q) waitentry;
+ TAILQ_ENTRY(cmd_q) entry;
};
+TAILQ_HEAD(cmd_q_list, cmd_q);
/* Command -c, -t or -s flags. */
enum cmd_entry_flag {
@@ -1409,6 +1319,101 @@ struct cmd_entry {
enum cmd_retval (*exec)(struct cmd *, struct cmd_q *);
};
+/* Client connection. */
+struct client {
+ struct tmuxpeer *peer;
+ struct cmd_q_list queue;
+
+ pid_t pid;
+ int fd;
+ struct event event;
+ int retval;
+
+ struct timeval creation_time;
+ struct timeval activity_time;
+
+ struct environ *environ;
+
+ char *title;
+ const char *cwd;
+
+ char *term;
+ char *ttyname;
+ struct tty tty;
+
+ void (*stdin_callback)(struct client *, int, void *);
+ void *stdin_callback_data;
+ struct evbuffer *stdin_data;
+ int stdin_closed;
+ struct evbuffer *stdout_data;
+ struct evbuffer *stderr_data;
+
+ struct event repeat_timer;
+
+ struct event click_timer;
+ u_int click_button;
+
+ struct event status_timer;
+ struct screen status;
+
+#define CLIENT_TERMINAL 0x1
+#define CLIENT_LOGIN 0x2
+#define CLIENT_EXIT 0x4
+#define CLIENT_REDRAW 0x8
+#define CLIENT_STATUS 0x10
+#define CLIENT_REPEAT 0x20
+#define CLIENT_SUSPENDED 0x40
+#define CLIENT_ATTACHED 0x80
+#define CLIENT_IDENTIFY 0x100
+#define CLIENT_DEAD 0x200
+#define CLIENT_BORDERS 0x400
+#define CLIENT_READONLY 0x800
+#define CLIENT_REDRAWWINDOW 0x1000
+#define CLIENT_CONTROL 0x2000
+#define CLIENT_CONTROLCONTROL 0x4000
+#define CLIENT_FOCUSED 0x8000
+#define CLIENT_UTF8 0x10000
+#define CLIENT_256COLOURS 0x20000
+#define CLIENT_IDENTIFIED 0x40000
+#define CLIENT_STATUSFORCE 0x80000
+#define CLIENT_DOUBLECLICK 0x100000
+#define CLIENT_TRIPLECLICK 0x200000
+ int flags;
+ struct key_table *keytable;
+
+ struct event identify_timer;
+ void (*identify_callback)(struct client *, struct window_pane *);
+ void *identify_callback_data;
+
+ char *message_string;
+ struct event message_timer;
+ u_int message_next;
+ TAILQ_HEAD(, message_entry) message_log;
+
+ char *prompt_string;
+ struct utf8_data *prompt_buffer;
+ size_t prompt_index;
+ int (*prompt_callbackfn)(void *, const char *);
+ void (*prompt_freefn)(void *);
+ void *prompt_data;
+ u_int prompt_hindex;
+ enum { PROMPT_ENTRY, PROMPT_COMMAND } prompt_mode;
+
+#define PROMPT_SINGLE 0x1
+#define PROMPT_NUMERIC 0x2
+ int prompt_flags;
+
+ struct session *session;
+ struct session *last_session;
+
+ int wlmouse;
+
+ int references;
+
+ TAILQ_ENTRY(client) entry;
+};
+TAILQ_HEAD(clients, client);
+
/* Key binding and key table. */
struct key_binding {
key_code key;
@@ -1504,10 +1509,9 @@ void proc_kill_peer(struct tmuxpeer *);
/* cfg.c */
extern int cfg_finished;
-extern int cfg_references;
extern struct client *cfg_client;
void start_cfg(void);
-int load_cfg(const char *, struct cmd_q *, int);
+int load_cfg(const char *, struct client *, struct cmd_q *, int);
void set_cfg_file(const char *);
void printflike(1, 2) cfg_add_cause(const char *, ...);
void cfg_print_causes(struct cmd_q *);
@@ -1557,9 +1561,9 @@ void hooks_add(struct hooks *, const char *, struct cmd_list *);
void hooks_copy(struct hooks *, struct hooks *);
void hooks_remove(struct hooks *, const char *);
struct hook *hooks_find(struct hooks *, const char *);
-int printflike(4, 5) hooks_run(struct hooks *, struct client *,
+void printflike(4, 5) hooks_run(struct hooks *, struct client *,
struct cmd_find_state *, const char *, ...);
-int printflike(4, 5) hooks_wait(struct hooks *, struct cmd_q *,
+void printflike(4, 5) hooks_insert(struct hooks *, struct cmd_q *,
struct cmd_find_state *, const char *, ...);
/* mode-key.c */
@@ -1755,8 +1759,7 @@ char **cmd_copy_argv(int, char **);
void cmd_free_argv(int, char **);
char *cmd_stringify_argv(int, char **);
struct cmd *cmd_parse(int, char **, const char *, u_int, char **);
-int cmd_prepare_state(struct cmd *, struct cmd_q *,
- struct cmd_q *);
+int cmd_prepare_state(struct cmd *, struct cmd_q *);
char *cmd_print(struct cmd *);
int cmd_mouse_at(struct window_pane *, struct mouse_event *,
u_int *, u_int *, int);
@@ -1776,16 +1779,15 @@ void cmd_list_free(struct cmd_list *);
char *cmd_list_print(struct cmd_list *);
/* cmd-queue.c */
-struct cmd_q *cmdq_new(struct client *);
-int cmdq_free(struct cmd_q *);
+struct cmd_q *cmdq_get_command(struct cmd_list *, struct cmd_find_state *,
+ struct mouse_event *, int);
+struct cmd_q *cmdq_get_callback(cmd_q_cb, void *);
+void cmdq_insert_after(struct cmd_q *, struct cmd_q *);
+void cmdq_append(struct client *, struct cmd_q *);
+u_int cmdq_next(struct client *);
+void cmdq_guard(struct cmd_q *, const char *, int);
void printflike(2, 3) cmdq_print(struct cmd_q *, const char *, ...);
void printflike(2, 3) cmdq_error(struct cmd_q *, const char *, ...);
-void cmdq_guard(struct cmd_q *, const char *, int);
-void cmdq_run(struct cmd_q *, struct cmd_list *,
- struct mouse_event *);
-void cmdq_append(struct cmd_q *, struct cmd_list *,
- struct mouse_event *);
-int cmdq_continue(struct cmd_q *);
/* cmd-string.c */
int cmd_string_parse(const char *, struct cmd_list **, const char *,
diff --git a/usr.bin/tmux/window-choose.c b/usr.bin/tmux/window-choose.c
index 6cb17b5fd0f..236fbeb5cdf 100644
--- a/usr.bin/tmux/window-choose.c
+++ b/usr.bin/tmux/window-choose.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: window-choose.c,v 1.80 2016/10/13 20:27:27 nicm Exp $ */
+/* $OpenBSD: window-choose.c,v 1.81 2016/10/16 17:55:14 nicm Exp $ */
/*
* Copyright (c) 2009 Nicholas Marriott <nicholas.marriott@gmail.com>
@@ -246,6 +246,7 @@ window_choose_data_run(struct window_choose_data *cdata)
{
struct cmd_list *cmdlist;
char *cause;
+ struct cmd_q *cmdq;
/*
* The command template will have already been replaced. But if it's
@@ -263,7 +264,8 @@ window_choose_data_run(struct window_choose_data *cdata)
return;
}
- cmdq_run(cdata->start_client->cmdq, cmdlist, NULL);
+ cmdq = cmdq_get_command(cmdlist, NULL, NULL, 0);
+ cmdq_append(cdata->start_client, cmdq);
cmd_list_free(cmdlist);
}