1
0
mirror of https://github.com/tmate-io/tmate-ssh-server.git synced 2020-11-18 19:53:51 -08:00

Add a command queue to standardize and simplify commands that call other

commands and allow a command to block execution of subsequent commands. This
allows run-shell and if-shell to be synchronous which has been much requested.

Each client has a default command queue and commands are consumed one at a time
from it. A command may suspend execution from the queue by returning
CMD_RETURN_WAIT and then resume it by calling cmd_continue() - for example
run-shell does this from the callback that is fired after the job is freed.

When the command queue becomes empty, command clients are automatically exited
(unless attaching). A callback is also fired - this is used for nested commands
in, for example, if-shell which can block execution of the client's cmdq until
a new cmdq becomes empty.

Also merge all the old error/info/print functions together and lose the old
curclient/cmdclient distinction - a cmdq is bound to one client (or none if in
the configuration file), this is a command client if c->session is NULL
otherwise an attached client.
This commit is contained in:
Nicholas Marriott 2013-02-23 22:25:58 +00:00
parent 357da035b9
commit 3964309c67
86 changed files with 1218 additions and 1219 deletions

View File

@ -104,6 +104,7 @@ dist_tmux_SOURCES = \
cmd-new-window.c \ cmd-new-window.c \
cmd-paste-buffer.c \ cmd-paste-buffer.c \
cmd-pipe-pane.c \ cmd-pipe-pane.c \
cmd-queue.c \
cmd-refresh-client.c \ cmd-refresh-client.c \
cmd-rename-session.c \ cmd-rename-session.c \
cmd-rename-window.c \ cmd-rename-window.c \

128
cfg.c
View File

@ -27,80 +27,27 @@
#include "tmux.h" #include "tmux.h"
/* struct cmd_q *cfg_cmd_q;
* 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;
int cfg_finished; int cfg_finished;
int cfg_references; int cfg_references;
struct causelist cfg_causes; struct causelist cfg_causes;
void printflike2 int
cfg_print(unused struct cmd_ctx *ctx, unused const char *fmt, ...) load_cfg(const char *path, struct cmd_q *cmdq, char **cause)
{
}
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)
{ {
FILE *f; FILE *f;
u_int n; u_int n, found;
char *buf, *copy, *line, *cause; char *buf, *copy, *line, *cause1, *msg;
size_t len, oldlen; size_t len, oldlen;
struct cmd_list *cmdlist; struct cmd_list *cmdlist;
enum cmd_retval retval;
if ((f = fopen(path, "rb")) == NULL) { if ((f = fopen(path, "rb")) == NULL) {
cfg_add_cause(causes, "%s: %s", path, strerror(errno)); xasprintf(cause, "%s: %s", path, strerror(errno));
return (CMD_RETURN_ERROR); return (-1);
} }
cfg_references++; n = found = 0;
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;
line = NULL; line = NULL;
retval = CMD_RETURN_NORMAL;
while ((buf = fgetln(f, &len))) { while ((buf = fgetln(f, &len))) {
/* Trim \n. */ /* Trim \n. */
if (buf[len - 1] == '\n') if (buf[len - 1] == '\n')
@ -142,53 +89,47 @@ load_cfg(const char *path, struct cmd_ctx *ctx, struct causelist *causes)
continue; 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); free(copy);
if (cause == NULL) if (cause1 == NULL)
continue; continue;
cfg_add_cause(causes, "%s: %u: %s", path, n, cause); xasprintf(&msg, "%s:%u: %s", path, n, cause1);
free(cause); ARRAY_ADD(&cfg_causes, msg);
free(cause1);
continue; continue;
} }
free(copy); free(copy);
if (cmdlist == NULL) if (cmdlist == NULL)
continue; continue;
cmdq_append(cmdq, cmdlist);
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;
}
cmd_list_free(cmdlist); cmd_list_free(cmdlist);
if (cfg_cause != NULL) { found++;
cfg_add_cause(causes, "%s: %d: %s", path, n, cfg_cause);
free(cfg_cause);
} }
} if (line != NULL)
if (line != NULL) {
cfg_add_cause(causes,
"%s: %d: line continuation at end of file", path, n);
free(line); free(line);
}
fclose(f); fclose(f);
cmd_free_ctx(ctx); return (found);
cfg_references--;
return (retval);
} }
void 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; struct window_pane *wp;
char *cause; char *cause;
@ -196,7 +137,6 @@ show_cfg_causes(struct session *s)
if (s == NULL || ARRAY_EMPTY(&cfg_causes)) if (s == NULL || ARRAY_EMPTY(&cfg_causes))
return; return;
wp = s->curw->window->active; wp = s->curw->window->active;
window_pane_set_mode(wp, &window_copy_mode); window_pane_set_mode(wp, &window_copy_mode);

View File

@ -188,7 +188,8 @@ client_main(int argc, char **argv, int flags)
* later in server) but it is necessary to get the start server * later in server) but it is necessary to get the start server
* flag. * 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); fprintf(stderr, "%s\n", cause);
return (1); return (1);
} }

View File

@ -26,7 +26,7 @@
* Attach existing session to the current terminal. * 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 = { const struct cmd_entry cmd_attach_session_entry = {
"attach-session", "attach", "attach-session", "attach",
@ -39,7 +39,7 @@ const struct cmd_entry cmd_attach_session_entry = {
}; };
enum cmd_retval 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 args *args = self->args;
struct session *s; struct session *s;
@ -49,17 +49,17 @@ cmd_attach_session_exec(struct cmd *self, struct cmd_ctx *ctx)
u_int i; u_int i;
if (RB_EMPTY(&sessions)) { if (RB_EMPTY(&sessions)) {
ctx->error(ctx, "no sessions"); cmdq_error(cmdq, "no sessions");
return (CMD_RETURN_ERROR); 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); return (CMD_RETURN_ERROR);
if (ctx->cmdclient == NULL && ctx->curclient == NULL) if (cmdq->client == NULL)
return (CMD_RETURN_NORMAL); return (CMD_RETURN_NORMAL);
if (ctx->cmdclient == NULL) { if (cmdq->client->session != NULL) {
if (args_has(self->args, 'd')) { if (args_has(self->args, 'd')) {
/* /*
* Can't use server_write_session in case attaching to * 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); c = ARRAY_ITEM(&clients, i);
if (c == NULL || c->session != s) if (c == NULL || c->session != s)
continue; continue;
if (c == ctx->curclient) if (c == cmdq->client)
continue; continue;
server_write_client(c, MSG_DETACH, NULL, 0); server_write_client(c, MSG_DETACH, NULL, 0);
} }
} }
ctx->curclient->session = s; cmdq->client->session = s;
notify_attached_session_changed(ctx->curclient); notify_attached_session_changed(cmdq->client);
session_update_activity(s); session_update_activity(s);
server_redraw_client(ctx->curclient); server_redraw_client(cmdq->client);
s->curw->flags &= ~WINLINK_ALERTFLAGS; s->curw->flags &= ~WINLINK_ALERTFLAGS;
} else { } else {
if (server_client_open(ctx->cmdclient, s, &cause) != 0) { if (server_client_open(cmdq->client, s, &cause) != 0) {
ctx->error(ctx, "open terminal failed: %s", cause); cmdq_error(cmdq, "open terminal failed: %s", cause);
free(cause); free(cause);
return (CMD_RETURN_ERROR); return (CMD_RETURN_ERROR);
} }
if (args_has(self->args, 'r')) if (args_has(self->args, 'r'))
ctx->cmdclient->flags |= CLIENT_READONLY; cmdq->client->flags |= CLIENT_READONLY;
if (args_has(self->args, 'd')) if (args_has(self->args, 'd'))
server_write_session(s, MSG_DETACH, NULL, 0); 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"); 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; s->curw->flags &= ~WINLINK_ALERTFLAGS;
server_write_ready(cmdq->client);
cmdq->client_exit = 0;
} }
recalculate_sizes(); recalculate_sizes();
server_update_socket(); server_update_socket();
return (CMD_RETURN_ATTACH); return (CMD_RETURN_NORMAL);
} }

View File

@ -28,9 +28,9 @@
*/ */
enum cmd_retval cmd_bind_key_check(struct args *); 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 = { const struct cmd_entry cmd_bind_key_entry = {
"bind-key", "bind", "bind-key", "bind",
@ -56,7 +56,7 @@ cmd_bind_key_check(struct args *args)
} }
enum cmd_retval 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; struct args *args = self->args;
char *cause; 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]); key = key_string_lookup_string(args->argv[0]);
if (key == KEYC_NONE) { 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); return (CMD_RETURN_ERROR);
} }
if (args_has(args, 't')) 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) { if (cmdlist == NULL) {
ctx->error(ctx, "%s", cause); cmdq_error(cmdq, "%s", cause);
free(cause); free(cause);
return (CMD_RETURN_ERROR); return (CMD_RETURN_ERROR);
} }
@ -86,7 +87,7 @@ cmd_bind_key_exec(struct cmd *self, struct cmd_ctx *ctx)
} }
enum cmd_retval 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; struct args *args = self->args;
const char *tablename; 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'); tablename = args_get(args, 't');
if ((mtab = mode_key_findtable(tablename)) == NULL) { 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); return (CMD_RETURN_ERROR);
} }
cmd = mode_key_fromstring(mtab->cmdstr, args->argv[1]); cmd = mode_key_fromstring(mtab->cmdstr, args->argv[1]);
if (cmd == MODEKEY_NONE) { 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); return (CMD_RETURN_ERROR);
} }
if (cmd != MODEKEYCOPY_COPYPIPE) { if (cmd != MODEKEYCOPY_COPYPIPE) {
if (args->argc != 2) { if (args->argc != 2) {
ctx->error(ctx, "no argument allowed"); cmdq_error(cmdq, "no argument allowed");
return (CMD_RETURN_ERROR); return (CMD_RETURN_ERROR);
} }
arg = NULL; arg = NULL;
} else { } else {
if (args->argc != 3) { if (args->argc != 3) {
ctx->error(ctx, "no argument given"); cmdq_error(cmdq, "no argument given");
return (CMD_RETURN_ERROR); return (CMD_RETURN_ERROR);
} }
arg = args->argv[2]; arg = args->argv[2];

View File

@ -26,7 +26,7 @@
* Break pane off into a window. * 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 = { const struct cmd_entry cmd_break_pane_entry = {
"break-pane", "breakp", "break-pane", "breakp",
@ -39,7 +39,7 @@ const struct cmd_entry cmd_break_pane_entry = {
}; };
enum cmd_retval 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 args *args = self->args;
struct winlink *wl; struct winlink *wl;
@ -54,11 +54,11 @@ cmd_break_pane_exec(struct cmd *self, struct cmd_ctx *ctx)
const char *template; const char *template;
char *cp; 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); return (CMD_RETURN_ERROR);
if (window_count_panes(wl->window) == 1) { 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); return (CMD_RETURN_ERROR);
} }
@ -97,14 +97,14 @@ cmd_break_pane_exec(struct cmd *self, struct cmd_ctx *ctx)
template = BREAK_PANE_TEMPLATE; template = BREAK_PANE_TEMPLATE;
ft = format_create(); 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_client(ft, c);
format_session(ft, s); format_session(ft, s);
format_winlink(ft, s, wl); format_winlink(ft, s, wl);
format_window_pane(ft, wp); format_window_pane(ft, wp);
cp = format_expand(ft, template); cp = format_expand(ft, template);
ctx->print(ctx, "%s", cp); cmdq_print(cmdq, "%s", cp);
free(cp); free(cp);
format_free(ft); format_free(ft);

View File

@ -27,7 +27,7 @@
* Write the entire contents of a pane to a buffer or stdout. * 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 = { const struct cmd_entry cmd_capture_pane_entry = {
"capture-pane", "capturep", "capture-pane", "capturep",
@ -41,7 +41,7 @@ const struct cmd_entry cmd_capture_pane_entry = {
}; };
enum cmd_retval 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 args *args = self->args;
struct client *c; struct client *c;
@ -55,7 +55,7 @@ cmd_capture_pane_exec(struct cmd *self, struct cmd_ctx *ctx)
struct grid_cell *gc; struct grid_cell *gc;
const struct grid_line *gl; 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); return (CMD_RETURN_ERROR);
s = &wp->base; s = &wp->base;
gd = s->grid; gd = s->grid;
@ -113,11 +113,10 @@ cmd_capture_pane_exec(struct cmd *self, struct cmd_ctx *ctx)
} }
if (args_has(args, 'p')) { if (args_has(args, 'p')) {
c = ctx->curclient; c = cmdq->client;
if (c == NULL || !(c->flags & CLIENT_CONTROL)) if (c == NULL ||
c = ctx->cmdclient; (c->session != NULL && !(c->flags & CLIENT_CONTROL))) {
if (c == NULL) { cmdq_error(cmdq, "can't write to stdout");
ctx->error(ctx, "can't write to stdout");
return (CMD_RETURN_ERROR); return (CMD_RETURN_ERROR);
} }
evbuffer_add(c->stdout_data, buf, len); 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); buffer = args_strtonum(args, 'b', 0, INT_MAX, &cause);
if (cause != NULL) { if (cause != NULL) {
ctx->error(ctx, "buffer %s", cause); cmdq_error(cmdq, "buffer %s", cause);
free(buf); free(buf);
free(cause); free(cause);
return (CMD_RETURN_ERROR); return (CMD_RETURN_ERROR);
} }
if (paste_replace(&global_buffers, buffer, buf, len) != 0) { 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); free(buf);
return (CMD_RETURN_ERROR); return (CMD_RETURN_ERROR);
} }

View File

@ -27,7 +27,7 @@
* Enter choice mode to choose a buffer. * 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 = { const struct cmd_entry cmd_choose_buffer_entry = {
"choose-buffer", NULL, "choose-buffer", NULL,
@ -40,7 +40,7 @@ const struct cmd_entry cmd_choose_buffer_entry = {
}; };
enum cmd_retval 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 args *args = self->args;
struct client *c; struct client *c;
@ -51,15 +51,15 @@ cmd_choose_buffer_exec(struct cmd *self, struct cmd_ctx *ctx)
const char *template; const char *template;
u_int idx; u_int idx;
if ((c = cmd_current_client(ctx)) == NULL) { if ((c = cmd_current_client(cmdq)) == NULL) {
ctx->error(ctx, "no client available"); cmdq_error(cmdq, "no client available");
return (CMD_RETURN_ERROR); return (CMD_RETURN_ERROR);
} }
if ((template = args_get(args, 'F')) == NULL) if ((template = args_get(args, 'F')) == NULL)
template = CHOOSE_BUFFER_TEMPLATE; 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); return (CMD_RETURN_ERROR);
if (paste_get_top(&global_buffers) == NULL) if (paste_get_top(&global_buffers) == NULL)

View File

@ -27,7 +27,7 @@
* Enter choice mode to choose a client. * 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 *); void cmd_choose_client_callback(struct window_choose_data *);
@ -46,7 +46,7 @@ struct cmd_choose_client_data {
}; };
enum cmd_retval 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 args *args = self->args;
struct client *c; struct client *c;
@ -57,12 +57,12 @@ cmd_choose_client_exec(struct cmd *self, struct cmd_ctx *ctx)
char *action; char *action;
u_int i, idx, cur; u_int i, idx, cur;
if ((c = cmd_current_client(ctx)) == NULL) { if ((c = cmd_current_client(cmdq)) == NULL) {
ctx->error(ctx, "no client available"); cmdq_error(cmdq, "no client available");
return (CMD_RETURN_ERROR); 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); return (CMD_RETURN_ERROR);
if (window_pane_set_mode(wl->window->active, &window_choose_mode) != 0) 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); c1 = ARRAY_ITEM(&clients, i);
if (c1 == NULL || c1->session == NULL) if (c1 == NULL || c1->session == NULL)
continue; continue;
if (c1 == ctx->curclient) if (c1 == cmdq->client)
cur = idx; cur = idx;
idx++; idx++;

View File

@ -31,7 +31,7 @@
* Enter choose mode to choose a custom list. * 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 = { const struct cmd_entry cmd_choose_list_entry = {
"choose-list", NULL, "choose-list", NULL,
@ -44,7 +44,7 @@ const struct cmd_entry cmd_choose_list_entry = {
}; };
enum cmd_retval 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 args *args = self->args;
struct client *c; struct client *c;
@ -53,15 +53,15 @@ cmd_choose_list_exec(struct cmd *self, struct cmd_ctx *ctx)
char *template, *item, *copy, *list; char *template, *item, *copy, *list;
u_int idx; u_int idx;
if ((c = cmd_current_client(ctx)) == NULL) { if ((c = cmd_current_client(cmdq)) == NULL) {
ctx->error(ctx, "no client available"); cmdq_error(cmdq, "no client available");
return (CMD_RETURN_ERROR); return (CMD_RETURN_ERROR);
} }
if ((list1 = args_get(args, 'l')) == NULL) if ((list1 = args_get(args, 'l')) == NULL)
return (CMD_RETURN_ERROR); 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); return (CMD_RETURN_ERROR);
if (window_pane_set_mode(wl->window->active, &window_choose_mode) != 0) if (window_pane_set_mode(wl->window->active, &window_choose_mode) != 0)

View File

@ -32,7 +32,7 @@
* Enter choice mode to choose a session and/or window. * 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 = { const struct cmd_entry cmd_choose_tree_entry = {
"choose-tree", NULL, "choose-tree", NULL,
@ -66,7 +66,7 @@ const struct cmd_entry cmd_choose_window_entry = {
}; };
enum cmd_retval 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 args *args = self->args;
struct winlink *wl, *wm; 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_template = win_template = NULL;
ses_action = win_action = NULL; ses_action = win_action = NULL;
if ((c = cmd_current_client(ctx)) == NULL) { if ((c = cmd_current_client(cmdq)) == NULL) {
ctx->error(ctx, "no client available"); cmdq_error(cmdq, "no client available");
return (CMD_RETURN_ERROR); return (CMD_RETURN_ERROR);
} }
if ((s = c->session) == NULL) if ((s = c->session) == NULL)
return (CMD_RETURN_ERROR); 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); return (CMD_RETURN_ERROR);
if (window_pane_set_mode(wl->window->active, &window_choose_mode) != 0) if (window_pane_set_mode(wl->window->active, &window_choose_mode) != 0)

View File

@ -24,7 +24,7 @@
* Clear pane history. * 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 = { const struct cmd_entry cmd_clear_history_entry = {
"clear-history", "clearhist", "clear-history", "clearhist",
@ -37,13 +37,13 @@ const struct cmd_entry cmd_clear_history_entry = {
}; };
enum cmd_retval 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 args *args = self->args;
struct window_pane *wp; struct window_pane *wp;
struct grid *gd; 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); return (CMD_RETURN_ERROR);
gd = wp->base.grid; gd = wp->base.grid;

View File

@ -24,7 +24,7 @@
* Enter clock mode. * 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 = { const struct cmd_entry cmd_clock_mode_entry = {
"clock-mode", NULL, "clock-mode", NULL,
@ -37,12 +37,12 @@ const struct cmd_entry cmd_clock_mode_entry = {
}; };
enum cmd_retval 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 args *args = self->args;
struct window_pane *wp; 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); return (CMD_RETURN_ERROR);
window_pane_set_mode(wp, &window_clock_mode); window_pane_set_mode(wp, &window_clock_mode);

View File

@ -31,7 +31,7 @@
void cmd_command_prompt_key_binding(struct cmd *, int); void cmd_command_prompt_key_binding(struct cmd *, int);
int cmd_command_prompt_check(struct args *); 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 *); int cmd_command_prompt_callback(void *, const char *);
void cmd_command_prompt_free(void *); void cmd_command_prompt_free(void *);
@ -85,7 +85,7 @@ cmd_command_prompt_key_binding(struct cmd *self, int key)
} }
enum cmd_retval 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; struct args *args = self->args;
const char *inputs, *prompts; const char *inputs, *prompts;
@ -94,7 +94,7 @@ cmd_command_prompt_exec(struct cmd *self, struct cmd_ctx *ctx)
char *prompt, *ptr, *input = NULL; char *prompt, *ptr, *input = NULL;
size_t n; 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); return (CMD_RETURN_ERROR);
if (c->prompt_string != NULL) 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 cmd_command_prompt_cdata *cdata = data;
struct client *c = cdata->c; struct client *c = cdata->c;
struct cmd_list *cmdlist; struct cmd_list *cmdlist;
struct cmd_ctx *ctx;
char *cause, *new_template, *prompt, *ptr; char *cause, *new_template, *prompt, *ptr;
char *input = NULL; char *input = NULL;
@ -175,7 +174,7 @@ cmd_command_prompt_callback(void *data, const char *s)
return (1); 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) { if (cause != NULL) {
*cause = toupper((u_char) *cause); *cause = toupper((u_char) *cause);
status_message_set(c, "%s", cause); status_message_set(c, "%s", cause);
@ -184,14 +183,8 @@ cmd_command_prompt_callback(void *data, const char *s)
return (0); return (0);
} }
ctx = cmd_get_ctx(NULL, c); cmdq_run(c->cmdq, cmdlist);
ctx->error = key_bindings_error;
ctx->print = key_bindings_print;
ctx->info = key_bindings_info;
cmd_list_exec(cmdlist, ctx);
cmd_list_free(cmdlist); cmd_list_free(cmdlist);
cmd_free_ctx(ctx);
if (c->prompt_callbackfn != (void *) &cmd_command_prompt_callback) if (c->prompt_callbackfn != (void *) &cmd_command_prompt_callback)
return (1); return (1);

View File

@ -27,7 +27,7 @@
*/ */
void cmd_confirm_before_key_binding(struct cmd *, int); 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 *); int cmd_confirm_before_callback(void *, const char *);
void cmd_confirm_before_free(void *); void cmd_confirm_before_free(void *);
@ -43,8 +43,8 @@ const struct cmd_entry cmd_confirm_before_entry = {
}; };
struct cmd_confirm_before_data { struct cmd_confirm_before_data {
struct client *c;
char *cmd; char *cmd;
struct client *client;
}; };
void void
@ -66,7 +66,7 @@ cmd_confirm_before_key_binding(struct cmd *self, int key)
} }
enum cmd_retval 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 args *args = self->args;
struct cmd_confirm_before_data *cdata; 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; char *cmd, *copy, *new_prompt, *ptr;
const char *prompt; const char *prompt;
if (ctx->curclient == NULL) { if ((c = cmd_find_client(cmdq, args_get(args, 't'), 0)) == NULL)
ctx->error(ctx, "must be run interactively");
return (CMD_RETURN_ERROR);
}
if ((c = cmd_find_client(ctx, args_get(args, 't'), 0)) == NULL)
return (CMD_RETURN_ERROR); return (CMD_RETURN_ERROR);
if ((prompt = args_get(args, 'p')) != NULL) 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 = xmalloc(sizeof *cdata);
cdata->cmd = xstrdup(args->argv[0]); 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, cmd_confirm_before_callback, cmd_confirm_before_free, cdata,
PROMPT_SINGLE); PROMPT_SINGLE);
free(new_prompt); free(new_prompt);
return (CMD_RETURN_YIELD); return (CMD_RETURN_NORMAL);
} }
int int
cmd_confirm_before_callback(void *data, const char *s) cmd_confirm_before_callback(void *data, const char *s)
{ {
struct cmd_confirm_before_data *cdata = data; struct cmd_confirm_before_data *cdata = data;
struct client *c = cdata->c; struct client *c = cdata->client;
struct cmd_list *cmdlist; struct cmd_list *cmdlist;
struct cmd_ctx *ctx;
char *cause; char *cause;
if (c->flags & CLIENT_DEAD)
return (0);
if (s == NULL || *s == '\0') if (s == NULL || *s == '\0')
return (0); return (0);
if (tolower((u_char) s[0]) != 'y' || s[1] != '\0') if (tolower((u_char) s[0]) != 'y' || s[1] != '\0')
return (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) { if (cause != NULL) {
*cause = toupper((u_char) *cause); cmdq_error(c->cmdq, "%s", cause);
status_message_set(c, "%s", cause);
free(cause); free(cause);
} }
return (0); return (0);
} }
ctx = cmd_get_ctx(NULL, c); cmdq_run(c->cmdq, cmdlist);
ctx->error = key_bindings_error;
ctx->print = key_bindings_print;
ctx->info = key_bindings_info;
cmd_list_exec(cmdlist, ctx);
cmd_list_free(cmdlist); cmd_list_free(cmdlist);
cmd_free_ctx(ctx);
return (0); return (0);
} }
@ -141,6 +134,9 @@ void
cmd_confirm_before_free(void *data) cmd_confirm_before_free(void *data)
{ {
struct cmd_confirm_before_data *cdata = data; struct cmd_confirm_before_data *cdata = data;
struct client *c = cdata->client;
c->references--;
free(cdata->cmd); free(cdata->cmd);
free(cdata); free(cdata);

View File

@ -25,7 +25,7 @@
*/ */
void cmd_copy_mode_key_binding(struct cmd *, int); 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 = { const struct cmd_entry cmd_copy_mode_entry = {
"copy-mode", NULL, "copy-mode", NULL,
@ -46,12 +46,12 @@ cmd_copy_mode_key_binding(struct cmd *self, int key)
} }
enum cmd_retval 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 args *args = self->args;
struct window_pane *wp; 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); return (CMD_RETURN_ERROR);
if (window_pane_set_mode(wp, &window_copy_mode) != 0) if (window_pane_set_mode(wp, &window_copy_mode) != 0)

View File

@ -26,7 +26,7 @@
* Delete a paste buffer. * 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 = { const struct cmd_entry cmd_delete_buffer_entry = {
"delete-buffer", "deleteb", "delete-buffer", "deleteb",
@ -39,7 +39,7 @@ const struct cmd_entry cmd_delete_buffer_entry = {
}; };
enum cmd_retval 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; struct args *args = self->args;
char *cause; 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); buffer = args_strtonum(args, 'b', 0, INT_MAX, &cause);
if (cause != NULL) { if (cause != NULL) {
ctx->error(ctx, "buffer %s", cause); cmdq_error(cmdq, "buffer %s", cause);
free(cause); free(cause);
return (CMD_RETURN_ERROR); return (CMD_RETURN_ERROR);
} }
if (paste_free_index(&global_buffers, buffer) != 0) { 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); return (CMD_RETURN_ERROR);
} }

View File

@ -24,7 +24,7 @@
* Detach a client. * 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 = { const struct cmd_entry cmd_detach_client_entry = {
"detach-client", "detach", "detach-client", "detach",
@ -37,7 +37,7 @@ const struct cmd_entry cmd_detach_client_entry = {
}; };
enum cmd_retval 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 args *args = self->args;
struct client *c, *c2; struct client *c, *c2;
@ -51,7 +51,7 @@ cmd_detach_client_exec(struct cmd *self, struct cmd_ctx *ctx)
msgtype = MSG_DETACH; msgtype = MSG_DETACH;
if (args_has(args, 's')) { 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) if (s == NULL)
return (CMD_RETURN_ERROR); 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); server_write_client(c, msgtype, NULL, 0);
} }
} else { } else {
c = cmd_find_client(ctx, args_get(args, 't'), 0); c = cmd_find_client(cmdq, args_get(args, 't'), 0);
if (c == NULL) if (c == NULL)
return (CMD_RETURN_ERROR); 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); server_write_client(c, msgtype, NULL, 0);
} }
return (CMD_RETURN_NORMAL); return (CMD_RETURN_STOP);
} }

View File

@ -27,7 +27,7 @@
* Displays a message in the status line. * 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 = { const struct cmd_entry cmd_display_message_entry = {
"display-message", "display", "display-message", "display",
@ -41,7 +41,7 @@ const struct cmd_entry cmd_display_message_entry = {
}; };
enum cmd_retval 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 args *args = self->args;
struct client *c; struct client *c;
@ -56,17 +56,17 @@ cmd_display_message_exec(struct cmd *self, struct cmd_ctx *ctx)
size_t len; size_t len;
if (args_has(args, 't')) { 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) if (wl == NULL)
return (CMD_RETURN_ERROR); return (CMD_RETURN_ERROR);
} else { } else {
wl = cmd_find_pane(ctx, NULL, &s, &wp); wl = cmd_find_pane(cmdq, NULL, &s, &wp);
if (wl == NULL) if (wl == NULL)
return (CMD_RETURN_ERROR); return (CMD_RETURN_ERROR);
} }
if (args_has(args, 'F') && args->argc != 0) { 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); return (CMD_RETURN_ERROR);
} }
@ -77,7 +77,7 @@ cmd_display_message_exec(struct cmd *self, struct cmd_ctx *ctx)
template = DISPLAY_MESSAGE_TEMPLATE; template = DISPLAY_MESSAGE_TEMPLATE;
ft = format_create(); 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_client(ft, c);
format_session(ft, s); format_session(ft, s);
format_winlink(ft, s, wl); 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); msg = format_expand(ft, out);
if (args_has(self->args, 'p')) if (args_has(self->args, 'p'))
ctx->print(ctx, "%s", msg); cmdq_print(cmdq, "%s", msg);
else else
status_message_set(c, "%s", msg); status_message_set(c, "%s", msg);
free(msg); free(msg);
format_free(ft); format_free(ft);
return (CMD_RETURN_NORMAL); return (CMD_RETURN_NORMAL);
} }

View File

@ -24,7 +24,7 @@
* Display panes on a client. * 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 = { const struct cmd_entry cmd_display_panes_entry = {
"display-panes", "displayp", "display-panes", "displayp",
@ -37,12 +37,12 @@ const struct cmd_entry cmd_display_panes_entry = {
}; };
enum cmd_retval 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 args *args = self->args;
struct client *c; 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); return (CMD_RETURN_ERROR);
server_set_identify(c); server_set_identify(c);

View File

@ -28,7 +28,7 @@
* Find window containing text. * 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 *); 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 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 args *args = self->args;
struct client *c; struct client *c;
@ -139,13 +139,13 @@ cmd_find_window_exec(struct cmd *self, struct cmd_ctx *ctx)
const char *template; const char *template;
u_int i, match_flags; u_int i, match_flags;
if ((c = cmd_current_client(ctx)) == NULL) { if ((c = cmd_current_client(cmdq)) == NULL) {
ctx->error(ctx, "no client available"); cmdq_error(cmdq, "no client available");
return (CMD_RETURN_ERROR); return (CMD_RETURN_ERROR);
} }
s = c->session; 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); return (CMD_RETURN_ERROR);
if ((template = args_get(args, 'F')) == NULL) if ((template = args_get(args, 'F')) == NULL)
@ -162,7 +162,7 @@ cmd_find_window_exec(struct cmd *self, struct cmd_ctx *ctx)
free(searchstr); free(searchstr);
if (ARRAY_LENGTH(&find_list) == 0) { 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); ARRAY_FREE(&find_list);
return (CMD_RETURN_ERROR); return (CMD_RETURN_ERROR);
} }

View File

@ -24,7 +24,7 @@
* Cause client to report an error and exit with 1 if session doesn't exist. * 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 = { const struct cmd_entry cmd_has_session_entry = {
"has-session", "has", "has-session", "has",
@ -37,11 +37,11 @@ const struct cmd_entry cmd_has_session_entry = {
}; };
enum cmd_retval 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; 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_ERROR);
return (CMD_RETURN_NORMAL); return (CMD_RETURN_NORMAL);

View File

@ -29,15 +29,16 @@
* Executes a tmux command if a shell command returns true or false. * 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_callback(struct job *);
void cmd_if_shell_done(struct cmd_q *);
void cmd_if_shell_free(void *); void cmd_if_shell_free(void *);
const struct cmd_entry cmd_if_shell_entry = { const struct cmd_entry cmd_if_shell_entry = {
"if-shell", "if", "if-shell", "if",
"", 2, 3, "b", 2, 3,
"shell-command command [command]", "[-b] shell-command command [command]",
0, 0,
NULL, NULL,
NULL, NULL,
@ -47,11 +48,13 @@ const struct cmd_entry cmd_if_shell_entry = {
struct cmd_if_shell_data { struct cmd_if_shell_data {
char *cmd_if; char *cmd_if;
char *cmd_else; char *cmd_else;
struct cmd_ctx *ctx; struct cmd_q *cmdq;
int bflag;
int started;
}; };
enum cmd_retval 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 args *args = self->args;
struct cmd_if_shell_data *cdata; struct cmd_if_shell_data *cdata;
@ -63,50 +66,82 @@ cmd_if_shell_exec(struct cmd *self, struct cmd_ctx *ctx)
cdata->cmd_else = xstrdup(args->argv[2]); cdata->cmd_else = xstrdup(args->argv[2]);
else else
cdata->cmd_else = NULL; cdata->cmd_else = NULL;
cdata->bflag = args_has(args, 'b');
cdata->ctx = ctx; cdata->started = 0;
cmd_ref_ctx(ctx); cdata->cmdq = cmdq;
cmdq->references++;
job_run(shellcmd, cmd_if_shell_callback, cmd_if_shell_free, cdata); job_run(shellcmd, cmd_if_shell_callback, cmd_if_shell_free, cdata);
return (CMD_RETURN_YIELD); /* don't let client exit */ if (cdata->bflag)
return (CMD_RETURN_NORMAL);
return (CMD_RETURN_WAIT);
} }
void void
cmd_if_shell_callback(struct job *job) cmd_if_shell_callback(struct job *job)
{ {
struct cmd_if_shell_data *cdata = job->data; 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; struct cmd_list *cmdlist;
char *cause, *cmd; 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; cmd = cdata->cmd_else;
else
cmd = cdata->cmd_if;
if (cmd == NULL) if (cmd == NULL)
return; return;
} else
cmd = cdata->cmd_if; if (cmd_string_parse(cmd, &cmdlist, NULL, 0, &cause) != 0) {
if (cmd_string_parse(cmd, &cmdlist, &cause) != 0) {
if (cause != NULL) { if (cause != NULL) {
ctx->error(ctx, "%s", cause); cmdq_error(cmdq, "%s", cause);
free(cause); free(cause);
} }
return; 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); 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 void
cmd_if_shell_free(void *data) cmd_if_shell_free(void *data)
{ {
struct cmd_if_shell_data *cdata = data; struct cmd_if_shell_data *cdata = data;
struct cmd_ctx *ctx = cdata->ctx; struct cmd_q *cmdq = cdata->cmdq;
if (ctx->cmdclient != NULL) if (cdata->started)
ctx->cmdclient->flags |= CLIENT_EXIT; return;
cmd_free_ctx(ctx);
if (!cmdq_free(cmdq) && !cdata->bflag)
cmdq_continue(cmdq);
free(cdata->cmd_else); free(cdata->cmd_else);
free(cdata->cmd_if); free(cdata->cmd_if);

View File

@ -29,9 +29,9 @@
*/ */
void cmd_join_pane_key_binding(struct cmd *, int); 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 = { const struct cmd_entry cmd_join_pane_entry = {
"join-pane", "joinp", "join-pane", "joinp",
@ -68,13 +68,13 @@ cmd_join_pane_key_binding(struct cmd *self, int key)
} }
enum cmd_retval 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 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 args *args = self->args;
struct session *dst_s; struct session *dst_s;
@ -86,23 +86,23 @@ join_pane(struct cmd *self, struct cmd_ctx *ctx, int not_same_window)
enum layout_type type; enum layout_type type;
struct layout_cell *lc; 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) if (dst_wl == NULL)
return (CMD_RETURN_ERROR); return (CMD_RETURN_ERROR);
dst_w = dst_wl->window; dst_w = dst_wl->window;
dst_idx = dst_wl->idx; 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) if (src_wl == NULL)
return (CMD_RETURN_ERROR); return (CMD_RETURN_ERROR);
src_w = src_wl->window; src_w = src_wl->window;
if (not_same_window && src_w == dst_w) { 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); return (CMD_RETURN_ERROR);
} }
if (!not_same_window && src_wp == dst_wp) { 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); return (CMD_RETURN_ERROR);
} }
@ -114,14 +114,14 @@ join_pane(struct cmd *self, struct cmd_ctx *ctx, int not_same_window)
if (args_has(args, 'l')) { if (args_has(args, 'l')) {
size = args_strtonum(args, 'l', 0, INT_MAX, &cause); size = args_strtonum(args, 'l', 0, INT_MAX, &cause);
if (cause != NULL) { if (cause != NULL) {
ctx->error(ctx, "size %s", cause); cmdq_error(cmdq, "size %s", cause);
free(cause); free(cause);
return (CMD_RETURN_ERROR); return (CMD_RETURN_ERROR);
} }
} else if (args_has(args, 'p')) { } else if (args_has(args, 'p')) {
percentage = args_strtonum(args, 'p', 0, 100, &cause); percentage = args_strtonum(args, 'p', 0, 100, &cause);
if (cause != NULL) { if (cause != NULL) {
ctx->error(ctx, "percentage %s", cause); cmdq_error(cmdq, "percentage %s", cause);
free(cause); free(cause);
return (CMD_RETURN_ERROR); return (CMD_RETURN_ERROR);
} }
@ -132,7 +132,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')); lc = layout_split_pane(dst_wp, type, size, args_has(args, 'b'));
if (lc == NULL) { 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); return (CMD_RETURN_ERROR);
} }

View File

@ -26,7 +26,7 @@
* Kill pane. * 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 = { const struct cmd_entry cmd_kill_pane_entry = {
"kill-pane", "killp", "kill-pane", "killp",
@ -39,13 +39,13 @@ const struct cmd_entry cmd_kill_pane_entry = {
}; };
enum cmd_retval 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 args *args = self->args;
struct winlink *wl; struct winlink *wl;
struct window_pane *loopwp, *tmpwp, *wp; 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); return (CMD_RETURN_ERROR);
if (window_count_panes(wl->window) == 1) { if (window_count_panes(wl->window) == 1) {

View File

@ -27,7 +27,7 @@
* Kill the server and do nothing else. * 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 = { const struct cmd_entry cmd_kill_server_entry = {
"kill-server", NULL, "kill-server", NULL,
@ -40,7 +40,7 @@ const struct cmd_entry cmd_kill_server_entry = {
}; };
enum cmd_retval 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); kill(getpid(), SIGTERM);

View File

@ -27,7 +27,7 @@
* Note this deliberately has no alias to make it hard to hit by accident. * 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 = { const struct cmd_entry cmd_kill_session_entry = {
"kill-session", NULL, "kill-session", NULL,
@ -40,12 +40,12 @@ const struct cmd_entry cmd_kill_session_entry = {
}; };
enum cmd_retval 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 args *args = self->args;
struct session *s, *s2, *s3; 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); return (CMD_RETURN_ERROR);
if (args_has(args, 'a')) { if (args_has(args, 'a')) {

View File

@ -24,7 +24,7 @@
* Destroy window. * 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 = { const struct cmd_entry cmd_kill_window_entry = {
"kill-window", "killw", "kill-window", "killw",
@ -37,13 +37,13 @@ const struct cmd_entry cmd_kill_window_entry = {
}; };
enum cmd_retval 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 args *args = self->args;
struct winlink *wl, *wl2, *wl3; struct winlink *wl, *wl2, *wl3;
struct session *s; 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); return (CMD_RETURN_ERROR);
if (args_has(args, 'a')) { if (args_has(args, 'a')) {

View File

@ -26,7 +26,7 @@
* Link a window into another session. * 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 = { const struct cmd_entry cmd_link_window_entry = {
"link-window", "linkw", "link-window", "linkw",
@ -39,7 +39,7 @@ const struct cmd_entry cmd_link_window_entry = {
}; };
enum cmd_retval 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 args *args = self->args;
struct session *src, *dst; struct session *src, *dst;
@ -47,15 +47,15 @@ cmd_link_window_exec(struct cmd *self, struct cmd_ctx *ctx)
char *cause; char *cause;
int idx, kflag, dflag; 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); 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); return (CMD_RETURN_ERROR);
kflag = args_has(self->args, 'k'); kflag = args_has(self->args, 'k');
dflag = args_has(self->args, 'd'); dflag = args_has(self->args, 'd');
if (server_link_window(src, wl, dst, idx, kflag, !dflag, &cause) != 0) { 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); free(cause);
return (CMD_RETURN_ERROR); return (CMD_RETURN_ERROR);
} }

View File

@ -27,7 +27,7 @@
* List paste buffers. * 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 = { const struct cmd_entry cmd_list_buffers_entry = {
"list-buffers", "lsb", "list-buffers", "lsb",
@ -40,7 +40,7 @@ const struct cmd_entry cmd_list_buffers_entry = {
}; };
enum cmd_retval 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 args *args = self->args;
struct paste_buffer *pb; 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); format_paste_buffer(ft, pb);
line = format_expand(ft, template); line = format_expand(ft, template);
ctx->print(ctx, "%s", line); cmdq_print(cmdq, "%s", line);
free(line); free(line);
format_free(ft); format_free(ft);

View File

@ -28,7 +28,7 @@
* List all clients. * 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 = { const struct cmd_entry cmd_list_clients_entry = {
"list-clients", "lsc", "list-clients", "lsc",
@ -41,7 +41,7 @@ const struct cmd_entry cmd_list_clients_entry = {
}; };
enum cmd_retval 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 args *args = self->args;
struct client *c; struct client *c;
@ -52,7 +52,7 @@ cmd_list_clients_exec(struct cmd *self, struct cmd_ctx *ctx)
char *line; char *line;
if (args_has(args, 't')) { 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) if (s == NULL)
return (CMD_RETURN_ERROR); return (CMD_RETURN_ERROR);
} else } else
@ -75,7 +75,7 @@ cmd_list_clients_exec(struct cmd *self, struct cmd_ctx *ctx)
format_client(ft, c); format_client(ft, c);
line = format_expand(ft, template); line = format_expand(ft, template);
ctx->print(ctx, "%s", line); cmdq_print(cmdq, "%s", line);
free(line); free(line);
format_free(ft); format_free(ft);

View File

@ -24,7 +24,7 @@
* List all commands with usages. * 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 = { const struct cmd_entry cmd_list_commands_entry = {
"list-commands", "lscm", "list-commands", "lscm",
@ -37,16 +37,16 @@ const struct cmd_entry cmd_list_commands_entry = {
}; };
enum cmd_retval 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; const struct cmd_entry **entryp;
for (entryp = cmd_table; *entryp != NULL; entryp++) { for (entryp = cmd_table; *entryp != NULL; entryp++) {
if ((*entryp)->alias != NULL) { if ((*entryp)->alias != NULL) {
ctx->print(ctx, "%s (%s) %s", (*entryp)->name, cmdq_print(cmdq, "%s (%s) %s", (*entryp)->name,
(*entryp)->alias, (*entryp)->usage); (*entryp)->alias, (*entryp)->usage);
} else { } else {
ctx->print(ctx, "%s %s", (*entryp)->name, cmdq_print(cmdq, "%s %s", (*entryp)->name,
(*entryp)->usage); (*entryp)->usage);
} }
} }

View File

@ -26,8 +26,8 @@
* List key bindings. * List key bindings.
*/ */
enum cmd_retval cmd_list_keys_exec(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_ctx *); enum cmd_retval cmd_list_keys_table(struct cmd *, struct cmd_q *);
const struct cmd_entry cmd_list_keys_entry = { const struct cmd_entry cmd_list_keys_entry = {
"list-keys", "lsk", "list-keys", "lsk",
@ -40,7 +40,7 @@ const struct cmd_entry cmd_list_keys_entry = {
}; };
enum cmd_retval 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 args *args = self->args;
struct key_binding *bd; struct key_binding *bd;
@ -50,7 +50,7 @@ cmd_list_keys_exec(struct cmd *self, struct cmd_ctx *ctx)
int width, keywidth; int width, keywidth;
if (args_has(args, 't')) if (args_has(args, 't'))
return (cmd_list_keys_table(self, ctx)); return (cmd_list_keys_table(self, cmdq));
width = 0; width = 0;
@ -91,14 +91,14 @@ cmd_list_keys_exec(struct cmd *self, struct cmd_ctx *ctx)
continue; continue;
cmd_list_print(bd->cmdlist, tmp + used, (sizeof tmp) - used); 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); return (CMD_RETURN_NORMAL);
} }
enum cmd_retval 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; struct args *args = self->args;
const char *tablename; const char *tablename;
@ -109,7 +109,7 @@ cmd_list_keys_table(struct cmd *self, struct cmd_ctx *ctx)
tablename = args_get(args, 't'); tablename = args_get(args, 't');
if ((mtab = mode_key_findtable(tablename)) == NULL) { 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); return (CMD_RETURN_ERROR);
} }
@ -138,7 +138,7 @@ cmd_list_keys_table(struct cmd *self, struct cmd_ctx *ctx)
mode = "c"; mode = "c";
cmdstr = mode_key_tostring(mtab->cmdstr, mbind->cmd); cmdstr = mode_key_tostring(mtab->cmdstr, mbind->cmd);
if (cmdstr != NULL) { 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' ? " " : "", mode, any_mode && *mode == '\0' ? " " : "",
mtab->name, (int) width, key, cmdstr, mtab->name, (int) width, key, cmdstr,
mbind->arg != NULL ? " \"" : "", mbind->arg != NULL ? " \"" : "",

View File

@ -27,13 +27,13 @@
* List panes on given window. * 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( 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 *, 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 = { const struct cmd_entry cmd_list_panes_entry = {
"list-panes", "lsp", "list-panes", "lsp",
@ -46,51 +46,51 @@ const struct cmd_entry cmd_list_panes_entry = {
}; };
enum cmd_retval 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 args *args = self->args;
struct session *s; struct session *s;
struct winlink *wl; struct winlink *wl;
if (args_has(args, 'a')) if (args_has(args, 'a'))
cmd_list_panes_server(self, ctx); cmd_list_panes_server(self, cmdq);
else if (args_has(args, 's')) { 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) if (s == NULL)
return (CMD_RETURN_ERROR); return (CMD_RETURN_ERROR);
cmd_list_panes_session(self, s, ctx, 1); cmd_list_panes_session(self, s, cmdq, 1);
} else { } else {
wl = cmd_find_window(ctx, args_get(args, 't'), &s); wl = cmd_find_window(cmdq, args_get(args, 't'), &s);
if (wl == NULL) if (wl == NULL)
return (CMD_RETURN_ERROR); 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); return (CMD_RETURN_NORMAL);
} }
void 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; struct session *s;
RB_FOREACH(s, sessions, &sessions) RB_FOREACH(s, sessions, &sessions)
cmd_list_panes_session(self, s, ctx, 2); cmd_list_panes_session(self, s, cmdq, 2);
} }
void void
cmd_list_panes_session( 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; struct winlink *wl;
RB_FOREACH(wl, winlinks, &s->windows) 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 void
cmd_list_panes_window(struct cmd *self, 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 args *args = self->args;
struct window_pane *wp; struct window_pane *wp;
@ -135,7 +135,7 @@ cmd_list_panes_window(struct cmd *self,
format_window_pane(ft, wp); format_window_pane(ft, wp);
line = format_expand(ft, template); line = format_expand(ft, template);
ctx->print(ctx, "%s", line); cmdq_print(cmdq, "%s", line);
free(line); free(line);
format_free(ft); format_free(ft);

View File

@ -28,7 +28,7 @@
* List all sessions. * 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 = { const struct cmd_entry cmd_list_sessions_entry = {
"list-sessions", "ls", "list-sessions", "ls",
@ -41,7 +41,7 @@ const struct cmd_entry cmd_list_sessions_entry = {
}; };
enum cmd_retval 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 args *args = self->args;
struct session *s; struct session *s;
@ -60,7 +60,7 @@ cmd_list_sessions_exec(struct cmd *self, struct cmd_ctx *ctx)
format_session(ft, s); format_session(ft, s);
line = format_expand(ft, template); line = format_expand(ft, template);
ctx->print(ctx, "%s", line); cmdq_print(cmdq, "%s", line);
free(line); free(line);
format_free(ft); format_free(ft);

View File

@ -27,11 +27,11 @@
* List windows on given session. * 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( 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 = { const struct cmd_entry cmd_list_windows_entry = {
"list-windows", "lsw", "list-windows", "lsw",
@ -44,35 +44,35 @@ const struct cmd_entry cmd_list_windows_entry = {
}; };
enum cmd_retval 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 args *args = self->args;
struct session *s; struct session *s;
if (args_has(args, 'a')) if (args_has(args, 'a'))
cmd_list_windows_server(self, ctx); cmd_list_windows_server(self, cmdq);
else { else {
s = cmd_find_session(ctx, args_get(args, 't'), 0); s = cmd_find_session(cmdq, args_get(args, 't'), 0);
if (s == NULL) if (s == NULL)
return (CMD_RETURN_ERROR); return (CMD_RETURN_ERROR);
cmd_list_windows_session(self, s, ctx, 0); cmd_list_windows_session(self, s, cmdq, 0);
} }
return (CMD_RETURN_NORMAL); return (CMD_RETURN_NORMAL);
} }
void 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; struct session *s;
RB_FOREACH(s, sessions, &sessions) RB_FOREACH(s, sessions, &sessions)
cmd_list_windows_session(self, s, ctx, 1); cmd_list_windows_session(self, s, cmdq, 1);
} }
void void
cmd_list_windows_session( 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 args *args = self->args;
struct winlink *wl; struct winlink *wl;
@ -102,7 +102,7 @@ cmd_list_windows_session(
format_window_pane(ft, wl->window->active); format_window_pane(ft, wl->window->active);
line = format_expand(ft, template); line = format_expand(ft, template);
ctx->print(ctx, "%s", line); cmdq_print(cmdq, "%s", line);
free(line); free(line);
format_free(ft); format_free(ft);

View File

@ -24,7 +24,8 @@
#include "tmux.h" #include "tmux.h"
struct cmd_list * 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_list *cmdlist;
struct cmd *cmd; struct cmd *cmd;
@ -34,7 +35,7 @@ cmd_list_parse(int argc, char **argv, char **cause)
copy_argv = cmd_copy_argv(argc, argv); copy_argv = cmd_copy_argv(argc, argv);
cmdlist = xmalloc(sizeof *cmdlist); cmdlist = xcalloc(1, sizeof *cmdlist);
cmdlist->references = 1; cmdlist->references = 1;
TAILQ_INIT(&cmdlist->list); TAILQ_INIT(&cmdlist->list);
@ -55,7 +56,7 @@ cmd_list_parse(int argc, char **argv, char **cause)
if (arglen != 1) if (arglen != 1)
new_argc++; new_argc++;
cmd = cmd_parse(new_argc, new_argv, cause); cmd = cmd_parse(new_argc, new_argv, file, line, cause);
if (cmd == NULL) if (cmd == NULL)
goto bad; goto bad;
TAILQ_INSERT_TAIL(&cmdlist->list, cmd, qentry); TAILQ_INSERT_TAIL(&cmdlist->list, cmd, qentry);
@ -64,7 +65,8 @@ cmd_list_parse(int argc, char **argv, char **cause)
} }
if (lastsplit != argc) { 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) if (cmd == NULL)
goto bad; goto bad;
TAILQ_INSERT_TAIL(&cmdlist->list, cmd, qentry); TAILQ_INSERT_TAIL(&cmdlist->list, cmd, qentry);
@ -79,76 +81,21 @@ bad:
return (NULL); 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 void
cmd_list_free(struct cmd_list *cmdlist) cmd_list_free(struct cmd_list *cmdlist)
{ {
struct cmd *cmd; struct cmd *cmd, *cmd1;
if (--cmdlist->references != 0) if (--cmdlist->references != 0)
return; return;
while (!TAILQ_EMPTY(&cmdlist->list)) { TAILQ_FOREACH_SAFE(cmd, &cmdlist->list, qentry, cmd1) {
cmd = TAILQ_FIRST(&cmdlist->list);
TAILQ_REMOVE(&cmdlist->list, cmd, qentry); TAILQ_REMOVE(&cmdlist->list, cmd, qentry);
args_free(cmd->args); args_free(cmd->args);
free(cmd->file);
free(cmd); free(cmd);
} }
free(cmdlist); free(cmdlist);
} }

View File

@ -30,7 +30,7 @@
* Loads a paste buffer from a file. * 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 *); void cmd_load_buffer_callback(struct client *, int, void *);
const struct cmd_entry cmd_load_buffer_entry = { const struct cmd_entry cmd_load_buffer_entry = {
@ -44,10 +44,10 @@ const struct cmd_entry cmd_load_buffer_entry = {
}; };
enum cmd_retval 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 args *args = self->args;
struct client *c = ctx->cmdclient; struct client *c = cmdq->client;
struct session *s; struct session *s;
FILE *f; FILE *f;
const char *path, *newpath, *wd; const char *path, *newpath, *wd;
@ -61,7 +61,7 @@ cmd_load_buffer_exec(struct cmd *self, struct cmd_ctx *ctx)
else { else {
buffer = args_strtonum(args, 'b', 0, INT_MAX, &cause); buffer = args_strtonum(args, 'b', 0, INT_MAX, &cause);
if (cause != NULL) { if (cause != NULL) {
ctx->error(ctx, "buffer %s", cause); cmdq_error(cmdq, "buffer %s", cause);
free(cause); free(cause);
return (CMD_RETURN_ERROR); 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, error = server_set_stdin_callback (c, cmd_load_buffer_callback,
buffer_ptr, &cause); buffer_ptr, &cause);
if (error != 0) { if (error != 0) {
ctx->error(ctx, "%s: %s", path, cause); cmdq_error(cmdq, "%s: %s", path, cause);
free(cause); free(cause);
return (CMD_RETURN_ERROR); return (CMD_RETURN_ERROR);
} }
return (CMD_RETURN_YIELD); return (CMD_RETURN_WAIT);
} }
if (c != NULL) if (c != NULL)
wd = c->cwd; 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"); wd = options_get_string(&s->options, "default-path");
if (*wd == '\0') if (*wd == '\0')
wd = s->cwd; wd = s->cwd;
@ -96,7 +96,7 @@ cmd_load_buffer_exec(struct cmd *self, struct cmd_ctx *ctx)
path = newpath; path = newpath;
} }
if ((f = fopen(path, "rb")) == NULL) { 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); return (CMD_RETURN_ERROR);
} }
@ -105,14 +105,14 @@ cmd_load_buffer_exec(struct cmd *self, struct cmd_ctx *ctx)
while ((ch = getc(f)) != EOF) { while ((ch = getc(f)) != EOF) {
/* Do not let the server die due to memory exhaustion. */ /* Do not let the server die due to memory exhaustion. */
if ((new_pdata = realloc(pdata, psize + 2)) == NULL) { 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; goto error;
} }
pdata = new_pdata; pdata = new_pdata;
pdata[psize++] = ch; pdata[psize++] = ch;
} }
if (ferror(f)) { if (ferror(f)) {
ctx->error(ctx, "%s: read error", path); cmdq_error(cmdq, "%s: read error", path);
goto error; goto error;
} }
if (pdata != NULL) if (pdata != NULL)
@ -126,7 +126,7 @@ cmd_load_buffer_exec(struct cmd *self, struct cmd_ctx *ctx)
return (CMD_RETURN_NORMAL); return (CMD_RETURN_NORMAL);
} }
if (paste_replace(&global_buffers, buffer, pdata, psize) != 0) { 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); free(pdata);
return (CMD_RETURN_ERROR); return (CMD_RETURN_ERROR);
} }
@ -153,12 +153,13 @@ cmd_load_buffer_callback(struct client *c, int closed, void *data)
c->stdin_callback = NULL; c->stdin_callback = NULL;
c->references--; c->references--;
c->flags |= CLIENT_EXIT; if (c->flags & CLIENT_DEAD)
return;
psize = EVBUFFER_LENGTH(c->stdin_data); psize = EVBUFFER_LENGTH(c->stdin_data);
if (psize == 0 || (pdata = malloc(psize + 1)) == NULL) { if (psize == 0 || (pdata = malloc(psize + 1)) == NULL) {
free(data); free(data);
return; goto out;
} }
memcpy(pdata, EVBUFFER_DATA(c->stdin_data), psize); memcpy(pdata, EVBUFFER_DATA(c->stdin_data), psize);
pdata[psize] = '\0'; pdata[psize] = '\0';
@ -174,4 +175,7 @@ cmd_load_buffer_callback(struct client *c, int closed, void *data)
} }
free(data); free(data);
out:
cmdq_continue(c->cmdq);
} }

View File

@ -28,7 +28,7 @@
* Lock commands. * 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 = { const struct cmd_entry cmd_lock_server_entry = {
"lock-server", "lock", "lock-server", "lock",
@ -61,7 +61,7 @@ const struct cmd_entry cmd_lock_client_entry = {
}; };
enum cmd_retval 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 args *args = self->args;
struct client *c; 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) if (self->entry == &cmd_lock_server_entry)
server_lock(); server_lock();
else if (self->entry == &cmd_lock_session_entry) { 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); return (CMD_RETURN_ERROR);
server_lock_session(s); server_lock_session(s);
} else { } 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); return (CMD_RETURN_ERROR);
server_lock_client(c); server_lock_client(c);
} }

View File

@ -26,7 +26,7 @@
* Move a window. * 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 = { const struct cmd_entry cmd_move_window_entry = {
"move-window", "movew", "move-window", "movew",
@ -39,7 +39,7 @@ const struct cmd_entry cmd_move_window_entry = {
}; };
enum cmd_retval 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 args *args = self->args;
struct session *src, *dst, *s; struct session *src, *dst, *s;
@ -48,7 +48,7 @@ cmd_move_window_exec(struct cmd *self, struct cmd_ctx *ctx)
int idx, kflag, dflag; int idx, kflag, dflag;
if (args_has(args, 'r')) { 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); return (CMD_RETURN_ERROR);
session_renumber_windows(s); session_renumber_windows(s);
@ -57,15 +57,15 @@ cmd_move_window_exec(struct cmd *self, struct cmd_ctx *ctx)
return (CMD_RETURN_NORMAL); 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); 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); return (CMD_RETURN_ERROR);
kflag = args_has(self->args, 'k'); kflag = args_has(self->args, 'k');
dflag = args_has(self->args, 'd'); dflag = args_has(self->args, 'd');
if (server_link_window(src, wl, dst, idx, kflag, !dflag, &cause) != 0) { 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); free(cause);
return (CMD_RETURN_ERROR); return (CMD_RETURN_ERROR);
} }

View File

@ -31,7 +31,7 @@
*/ */
enum cmd_retval cmd_new_session_check(struct args *); 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 = { const struct cmd_entry cmd_new_session_entry = {
"new-session", "new", "new-session", "new",
@ -53,10 +53,11 @@ cmd_new_session_check(struct args *args)
} }
enum cmd_retval 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 args *args = self->args;
struct session *s, *old_s, *groupwith; struct client *c = cmdq->client;
struct session *s, *groupwith;
struct window *w; struct window *w;
struct environ env; struct environ env;
struct termios tio, *tiop; struct termios tio, *tiop;
@ -65,50 +66,39 @@ cmd_new_session_exec(struct cmd *self, struct cmd_ctx *ctx)
char *cmd, *cause; char *cmd, *cause;
int detached, idx; int detached, idx;
u_int sx, sy; u_int sx, sy;
int already_attached;
newname = args_get(args, 's'); newname = args_get(args, 's');
if (newname != NULL) { if (newname != NULL) {
if (!session_check_name(newname)) { 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); return (CMD_RETURN_ERROR);
} }
if (session_find(newname) != NULL) { if (session_find(newname) != NULL) {
ctx->error(ctx, "duplicate session: %s", newname); cmdq_error(cmdq, "duplicate session: %s", newname);
return (CMD_RETURN_ERROR); return (CMD_RETURN_ERROR);
} }
} }
target = args_get(args, 't'); target = args_get(args, 't');
if (target != NULL) { if (target != NULL) {
groupwith = cmd_find_session(ctx, target, 0); groupwith = cmd_find_session(cmdq, target, 0);
if (groupwith == NULL) if (groupwith == NULL)
return (CMD_RETURN_ERROR); return (CMD_RETURN_ERROR);
} else } else
groupwith = NULL; 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. */ /* Set -d if no client. */
detached = args_has(args, 'd'); detached = args_has(args, 'd');
if (ctx->cmdclient == NULL && ctx->curclient == NULL) if (c == NULL)
detached = 1; 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 * Save the termios settings, part of which is used for new windows in
* this session. * 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 * before opening the terminal as that calls tcsetattr() to prepare for
* tmux taking over. * tmux taking over.
*/ */
if (ctx->cmdclient != NULL && ctx->cmdclient->tty.fd != -1) { if (!detached && !already_attached && c->tty.fd != -1) {
if (tcgetattr(ctx->cmdclient->tty.fd, &tio) != 0) if (tcgetattr(c->tty.fd, &tio) != 0)
fatal("tcgetattr failed"); fatal("tcgetattr failed");
tiop = &tio; tiop = &tio;
} else } else
tiop = NULL; tiop = NULL;
/* Open the terminal if necessary. */ /* Open the terminal if necessary. */
if (!detached && ctx->cmdclient != NULL) { if (!detached && !already_attached) {
if (server_client_open(ctx->cmdclient, NULL, &cause) != 0) { if (server_client_open(c, NULL, &cause) != 0) {
ctx->error(ctx, "open terminal failed: %s", cause); cmdq_error(cmdq, "open terminal failed: %s", cause);
free(cause); free(cause);
return (CMD_RETURN_ERROR); return (CMD_RETURN_ERROR);
} }
} }
/* Get the new session working directory. */ /* Get the new session working directory. */
if (ctx->cmdclient != NULL && ctx->cmdclient->cwd != NULL) if (c != NULL && c->cwd != NULL)
cwd = ctx->cmdclient->cwd; cwd = c->cwd;
else { else {
pw = getpwuid(getuid()); pw = getpwuid(getuid());
if (pw->pw_dir != NULL && *pw->pw_dir != '\0') if (pw->pw_dir != NULL && *pw->pw_dir != '\0')
@ -146,34 +136,27 @@ cmd_new_session_exec(struct cmd *self, struct cmd_ctx *ctx)
} }
/* Find new session size. */ /* Find new session size. */
if (ctx->cmdclient != NULL) { if (c != NULL) {
sx = ctx->cmdclient->tty.sx; sx = c->tty.sx;
sy = ctx->cmdclient->tty.sy; sy = c->tty.sy;
} else if (ctx->curclient != NULL) {
sx = ctx->curclient->tty.sx;
sy = ctx->curclient->tty.sy;
} else { } else {
sx = 80; sx = 80;
sy = 24; sy = 24;
} }
if (detached) { if (detached && args_has(args, 'x')) {
if (args_has(args, 'x')) { sx = strtonum(args_get(args, 'x'), 1, USHRT_MAX, &errstr);
sx = strtonum(
args_get(args, 'x'), 1, USHRT_MAX, &errstr);
if (errstr != NULL) { if (errstr != NULL) {
ctx->error(ctx, "width %s", errstr); cmdq_error(cmdq, "width %s", errstr);
return (CMD_RETURN_ERROR); return (CMD_RETURN_ERROR);
} }
} }
if (args_has(args, 'y')) { if (detached && args_has(args, 'y')) {
sy = strtonum( sy = strtonum(args_get(args, 'y'), 1, USHRT_MAX, &errstr);
args_get(args, 'y'), 1, USHRT_MAX, &errstr);
if (errstr != NULL) { if (errstr != NULL) {
ctx->error(ctx, "height %s", errstr); cmdq_error(cmdq, "height %s", errstr);
return (CMD_RETURN_ERROR); return (CMD_RETURN_ERROR);
} }
} }
}
if (sy > 0 && options_get_number(&global_s_options, "status")) if (sy > 0 && options_get_number(&global_s_options, "status"))
sy--; sy--;
if (sx == 0) if (sx == 0)
@ -192,14 +175,14 @@ cmd_new_session_exec(struct cmd *self, struct cmd_ctx *ctx)
/* Construct the environment. */ /* Construct the environment. */
environ_init(&env); environ_init(&env);
update = options_get_string(&global_s_options, "update-environment"); update = options_get_string(&global_s_options, "update-environment");
if (ctx->cmdclient != NULL) if (c != NULL)
environ_update(update, &ctx->cmdclient->environ, &env); environ_update(update, &c->environ, &env);
/* Create the new session. */ /* Create the new session. */
idx = -1 - options_get_number(&global_s_options, "base-index"); idx = -1 - options_get_number(&global_s_options, "base-index");
s = session_create(newname, cmd, cwd, &env, tiop, idx, sx, sy, &cause); s = session_create(newname, cmd, cwd, &env, tiop, idx, sx, sy, &cause);
if (s == NULL) { if (s == NULL) {
ctx->error(ctx, "create session failed: %s", cause); cmdq_error(cmdq, "create session failed: %s", cause);
free(cause); free(cause);
return (CMD_RETURN_ERROR); 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. */ /* Set the initial window name if one given. */
if (cmd != NULL && args_has(args, 'n')) { if (cmd != NULL && args_has(args, 'n')) {
w = s->curw->window; w = s->curw->window;
window_set_name(w, args_get(args, 'n')); window_set_name(w, args_get(args, 'n'));
options_set_number(&w->options, "automatic-rename", 0); 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. * taking this session and needs to get MSG_READY and stay around.
*/ */
if (!detached) { if (!detached) {
if (ctx->cmdclient != NULL) { if (!already_attached)
server_write_ready(ctx->cmdclient); server_write_ready(c);
else if (c->session != NULL)
old_s = ctx->cmdclient->session; c->last_session = c->session;
if (old_s != NULL) c->session = s;
ctx->cmdclient->last_session = old_s; notify_attached_session_changed(c);
ctx->cmdclient->session = s;
notify_attached_session_changed(ctx->cmdclient);
session_update_activity(s); session_update_activity(s);
server_redraw_client(ctx->cmdclient); server_redraw_client(c);
} 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);
}
} }
recalculate_sizes(); recalculate_sizes();
server_update_socket(); 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. * session's current window into more mode and display them now.
*/ */
if (cfg_finished) 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);
} }

View File

@ -26,7 +26,7 @@
* Create a new window. * 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 = { const struct cmd_entry cmd_new_window_entry = {
"new-window", "neww", "new-window", "neww",
@ -40,7 +40,7 @@ const struct cmd_entry cmd_new_window_entry = {
}; };
enum cmd_retval 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 args *args = self->args;
struct session *s; struct session *s;
@ -54,7 +54,7 @@ cmd_new_window_exec(struct cmd *self, struct cmd_ctx *ctx)
char *cp; char *cp;
if (args_has(args, 'a')) { 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) if (wl == NULL)
return (CMD_RETURN_ERROR); return (CMD_RETURN_ERROR);
idx = wl->idx + 1; idx = wl->idx + 1;
@ -65,7 +65,7 @@ cmd_new_window_exec(struct cmd *self, struct cmd_ctx *ctx)
break; break;
} }
if (last == INT_MAX) { if (last == INT_MAX) {
ctx->error(ctx, "no free window indexes"); cmdq_error(cmdq, "no free window indexes");
return (CMD_RETURN_ERROR); return (CMD_RETURN_ERROR);
} }
@ -76,7 +76,7 @@ cmd_new_window_exec(struct cmd *self, struct cmd_ctx *ctx)
server_unlink_window(s, wl); server_unlink_window(s, wl);
} }
} else { } 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); return (CMD_RETURN_ERROR);
} }
detached = args_has(args, 'd'); 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"); cmd = options_get_string(&s->options, "default-command");
else else
cmd = args->argv[0]; 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) if (idx == -1)
idx = -1 - options_get_number(&s->options, "base-index"); idx = -1 - options_get_number(&s->options, "base-index");
wl = session_new(s, args_get(args, 'n'), cmd, cwd, idx, &cause); wl = session_new(s, args_get(args, 'n'), cmd, cwd, idx, &cause);
if (wl == NULL) { if (wl == NULL) {
ctx->error(ctx, "create window failed: %s", cause); cmdq_error(cmdq, "create window failed: %s", cause);
free(cause); free(cause);
return (CMD_RETURN_ERROR); return (CMD_RETURN_ERROR);
} }
@ -126,14 +126,14 @@ cmd_new_window_exec(struct cmd *self, struct cmd_ctx *ctx)
template = NEW_WINDOW_TEMPLATE; template = NEW_WINDOW_TEMPLATE;
ft = format_create(); 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_client(ft, c);
format_session(ft, s); format_session(ft, s);
format_winlink(ft, s, wl); format_winlink(ft, s, wl);
format_window_pane(ft, wl->window->active); format_window_pane(ft, wl->window->active);
cp = format_expand(ft, template); cp = format_expand(ft, template);
ctx->print(ctx, "%s", cp); cmdq_print(cmdq, "%s", cp);
free(cp); free(cp);
format_free(ft); format_free(ft);

View File

@ -27,7 +27,7 @@
* Paste paste buffer if present. * 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 *, void cmd_paste_buffer_filter(struct window_pane *,
const char *, size_t, const char *, int); const char *, size_t, const char *, int);
@ -43,7 +43,7 @@ const struct cmd_entry cmd_paste_buffer_entry = {
}; };
enum cmd_retval 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 args *args = self->args;
struct window_pane *wp; struct window_pane *wp;
@ -54,7 +54,7 @@ cmd_paste_buffer_exec(struct cmd *self, struct cmd_ctx *ctx)
int buffer; int buffer;
int pflag; 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); return (CMD_RETURN_ERROR);
if (!args_has(args, 'b')) if (!args_has(args, 'b'))
@ -62,7 +62,7 @@ cmd_paste_buffer_exec(struct cmd *self, struct cmd_ctx *ctx)
else { else {
buffer = args_strtonum(args, 'b', 0, INT_MAX, &cause); buffer = args_strtonum(args, 'b', 0, INT_MAX, &cause);
if (cause != NULL) { if (cause != NULL) {
ctx->error(ctx, "buffer %s", cause); cmdq_error(cmdq, "buffer %s", cause);
free(cause); free(cause);
return (CMD_RETURN_ERROR); return (CMD_RETURN_ERROR);
} }
@ -73,7 +73,7 @@ cmd_paste_buffer_exec(struct cmd *self, struct cmd_ctx *ctx)
else { else {
pb = paste_get_index(&global_buffers, buffer); pb = paste_get_index(&global_buffers, buffer);
if (pb == NULL) { if (pb == NULL) {
ctx->error(ctx, "no buffer %d", buffer); cmdq_error(cmdq, "no buffer %d", buffer);
return (CMD_RETURN_ERROR); return (CMD_RETURN_ERROR);
} }
} }

View File

@ -31,7 +31,7 @@
* Open pipe to redirect pane output. If already open, close first. * 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 *); void cmd_pipe_pane_error_callback(struct bufferevent *, short, void *);
@ -46,7 +46,7 @@ const struct cmd_entry cmd_pipe_pane_entry = {
}; };
enum cmd_retval 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 args *args = self->args;
struct client *c; struct client *c;
@ -54,9 +54,9 @@ cmd_pipe_pane_exec(struct cmd *self, struct cmd_ctx *ctx)
char *command; char *command;
int old_fd, pipe_fd[2], null_fd; 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); return (CMD_RETURN_ERROR);
c = cmd_find_client(ctx, NULL, 1); c = cmd_find_client(cmdq, NULL, 1);
/* Destroy the old pipe. */ /* Destroy the old pipe. */
old_fd = wp->pipe_fd; old_fd = wp->pipe_fd;
@ -81,14 +81,14 @@ cmd_pipe_pane_exec(struct cmd *self, struct cmd_ctx *ctx)
/* Open the new pipe. */ /* Open the new pipe. */
if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, pipe_fd) != 0) { 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); return (CMD_RETURN_ERROR);
} }
/* Fork the child. */ /* Fork the child. */
switch (fork()) { switch (fork()) {
case -1: case -1:
ctx->error(ctx, "fork error: %s", strerror(errno)); cmdq_error(cmdq, "fork error: %s", strerror(errno));
return (CMD_RETURN_ERROR); return (CMD_RETURN_ERROR);
case 0: case 0:
/* Child process. */ /* Child process. */

258
cmd-queue.c Normal file
View File

@ -0,0 +1,258 @@
/* $Id$ */
/*
* Copyright (c) 2013 Nicholas Marriott <nicm@users.sourceforge.net>
*
* 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 <sys/types.h>
#include <ctype.h>
#include <stdlib.h>
#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;
}

View File

@ -24,7 +24,7 @@
* Refresh client. * 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 = { const struct cmd_entry cmd_refresh_client_entry = {
"refresh-client", "refresh", "refresh-client", "refresh",
@ -37,32 +37,32 @@ const struct cmd_entry cmd_refresh_client_entry = {
}; };
enum cmd_retval 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 args *args = self->args;
struct client *c; struct client *c;
const char *size; const char *size;
u_int w, h; 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); return (CMD_RETURN_ERROR);
if (args_has(args, 'C')) { if (args_has(args, 'C')) {
if ((size = args_get(args, 'C')) == NULL) { if ((size = args_get(args, 'C')) == NULL) {
ctx->error(ctx, "missing size"); cmdq_error(cmdq, "missing size");
return (CMD_RETURN_ERROR); return (CMD_RETURN_ERROR);
} }
if (sscanf(size, "%u,%u", &w, &h) != 2) { if (sscanf(size, "%u,%u", &w, &h) != 2) {
ctx->error(ctx, "bad size argument"); cmdq_error(cmdq, "bad size argument");
return (CMD_RETURN_ERROR); return (CMD_RETURN_ERROR);
} }
if (w < PANE_MINIMUM || w > 5000 || if (w < PANE_MINIMUM || w > 5000 ||
h < PANE_MINIMUM || h > 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); return (CMD_RETURN_ERROR);
} }
if (!(c->flags & CLIENT_CONTROL)) { if (!(c->flags & CLIENT_CONTROL)) {
ctx->error(ctx, "not a control client"); cmdq_error(cmdq, "not a control client");
return (CMD_RETURN_ERROR); return (CMD_RETURN_ERROR);
} }
if (tty_set_size(&c->tty, w, h)) if (tty_set_size(&c->tty, w, h))

View File

@ -26,7 +26,7 @@
* Change session name. * 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 = { const struct cmd_entry cmd_rename_session_entry = {
"rename-session", "rename", "rename-session", "rename",
@ -39,7 +39,7 @@ const struct cmd_entry cmd_rename_session_entry = {
}; };
enum cmd_retval 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 args *args = self->args;
struct session *s; struct session *s;
@ -47,15 +47,15 @@ cmd_rename_session_exec(struct cmd *self, struct cmd_ctx *ctx)
newname = args->argv[0]; newname = args->argv[0];
if (!session_check_name(newname)) { 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); return (CMD_RETURN_ERROR);
} }
if (session_find(newname) != NULL) { if (session_find(newname) != NULL) {
ctx->error(ctx, "duplicate session: %s", newname); cmdq_error(cmdq, "duplicate session: %s", newname);
return (CMD_RETURN_ERROR); 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); return (CMD_RETURN_ERROR);
RB_REMOVE(sessions, &sessions, s); RB_REMOVE(sessions, &sessions, s);

View File

@ -26,7 +26,7 @@
* Rename a window. * 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 = { const struct cmd_entry cmd_rename_window_entry = {
"rename-window", "renamew", "rename-window", "renamew",
@ -39,13 +39,13 @@ const struct cmd_entry cmd_rename_window_entry = {
}; };
enum cmd_retval 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 args *args = self->args;
struct session *s; struct session *s;
struct winlink *wl; 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); return (CMD_RETURN_ERROR);
window_set_name(wl->window, args->argv[0]); window_set_name(wl->window, args->argv[0]);

View File

@ -27,7 +27,7 @@
*/ */
void cmd_resize_pane_key_binding(struct cmd *, int); 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 = { const struct cmd_entry cmd_resize_pane_entry = {
"resize-pane", "resizep", "resize-pane", "resizep",
@ -82,7 +82,7 @@ cmd_resize_pane_key_binding(struct cmd *self, int key)
} }
enum cmd_retval 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 args *args = self->args;
struct winlink *wl; struct winlink *wl;
@ -92,7 +92,7 @@ cmd_resize_pane_exec(struct cmd *self, struct cmd_ctx *ctx)
u_int adjust; u_int adjust;
int x, y; 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); return (CMD_RETURN_ERROR);
if (args->argc == 0) if (args->argc == 0)
@ -100,7 +100,7 @@ cmd_resize_pane_exec(struct cmd *self, struct cmd_ctx *ctx)
else { else {
adjust = strtonum(args->argv[0], 1, INT_MAX, &errstr); adjust = strtonum(args->argv[0], 1, INT_MAX, &errstr);
if (errstr != NULL) { if (errstr != NULL) {
ctx->error(ctx, "adjustment %s", errstr); cmdq_error(cmdq, "adjustment %s", errstr);
return (CMD_RETURN_ERROR); 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, x = args_strtonum(self->args, 'x', PANE_MINIMUM, INT_MAX,
&cause); &cause);
if (cause != NULL) { if (cause != NULL) {
ctx->error(ctx, "width %s", cause); cmdq_error(cmdq, "width %s", cause);
free(cause); free(cause);
return (CMD_RETURN_ERROR); 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, y = args_strtonum(self->args, 'y', PANE_MINIMUM, INT_MAX,
&cause); &cause);
if (cause != NULL) { if (cause != NULL) {
ctx->error(ctx, "height %s", cause); cmdq_error(cmdq, "height %s", cause);
free(cause); free(cause);
return (CMD_RETURN_ERROR); return (CMD_RETURN_ERROR);
} }

View File

@ -28,7 +28,7 @@
* Respawn a pane (restart the command). Kill existing if -k given. * 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 = { const struct cmd_entry cmd_respawn_pane_entry = {
"respawn-pane", "respawnp", "respawn-pane", "respawnp",
@ -41,7 +41,7 @@ const struct cmd_entry cmd_respawn_pane_entry = {
}; };
enum cmd_retval 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 args *args = self->args;
struct winlink *wl; struct winlink *wl;
@ -53,14 +53,14 @@ cmd_respawn_pane_exec(struct cmd *self, struct cmd_ctx *ctx)
char *cause; char *cause;
u_int idx; 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); return (CMD_RETURN_ERROR);
w = wl->window; w = wl->window;
if (!args_has(self->args, 'k') && wp->fd != -1) { if (!args_has(self->args, 'k') && wp->fd != -1) {
if (window_pane_index(wp, &idx) != 0) if (window_pane_index(wp, &idx) != 0)
fatalx("index not found"); 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); s->name, wl->idx, idx);
return (CMD_RETURN_ERROR); return (CMD_RETURN_ERROR);
} }
@ -79,7 +79,7 @@ cmd_respawn_pane_exec(struct cmd *self, struct cmd_ctx *ctx)
else else
cmd = NULL; cmd = NULL;
if (window_pane_spawn(wp, cmd, NULL, NULL, &env, s->tio, &cause) != 0) { 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); free(cause);
environ_free(&env); environ_free(&env);
return (CMD_RETURN_ERROR); return (CMD_RETURN_ERROR);

View File

@ -27,7 +27,7 @@
* Respawn a window (restart the command). Kill existing if -k given. * 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 = { const struct cmd_entry cmd_respawn_window_entry = {
"respawn-window", "respawnw", "respawn-window", "respawnw",
@ -40,7 +40,7 @@ const struct cmd_entry cmd_respawn_window_entry = {
}; };
enum cmd_retval 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 args *args = self->args;
struct winlink *wl; struct winlink *wl;
@ -51,7 +51,7 @@ cmd_respawn_window_exec(struct cmd *self, struct cmd_ctx *ctx)
const char *cmd; const char *cmd;
char *cause; 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); return (CMD_RETURN_ERROR);
w = wl->window; w = wl->window;
@ -59,7 +59,7 @@ cmd_respawn_window_exec(struct cmd *self, struct cmd_ctx *ctx)
TAILQ_FOREACH(wp, &w->panes, entry) { TAILQ_FOREACH(wp, &w->panes, entry) {
if (wp->fd == -1) if (wp->fd == -1)
continue; continue;
ctx->error(ctx, cmdq_error(cmdq,
"window still active: %s:%d", s->name, wl->idx); "window still active: %s:%d", s->name, wl->idx);
return (CMD_RETURN_ERROR); return (CMD_RETURN_ERROR);
} }
@ -81,7 +81,7 @@ cmd_respawn_window_exec(struct cmd *self, struct cmd_ctx *ctx)
else else
cmd = NULL; cmd = NULL;
if (window_pane_spawn(wp, cmd, NULL, NULL, &env, s->tio, &cause) != 0) { 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); free(cause);
environ_free(&env); environ_free(&env);
server_destroy_pane(wp); server_destroy_pane(wp);

View File

@ -25,7 +25,7 @@
*/ */
void cmd_rotate_window_key_binding(struct cmd *, int); 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 = { const struct cmd_entry cmd_rotate_window_entry = {
"rotate-window", "rotatew", "rotate-window", "rotatew",
@ -46,7 +46,7 @@ cmd_rotate_window_key_binding(struct cmd *self, int key)
} }
enum cmd_retval 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 args *args = self->args;
struct winlink *wl; struct winlink *wl;
@ -55,7 +55,7 @@ cmd_rotate_window_exec(struct cmd *self, struct cmd_ctx *ctx)
struct layout_cell *lc; struct layout_cell *lc;
u_int sx, sy, xoff, yoff; 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); return (CMD_RETURN_ERROR);
w = wl->window; w = wl->window;

View File

@ -29,7 +29,7 @@
* Runs a command without a window. * 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_callback(struct job *);
void cmd_run_shell_free(void *); 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 = { const struct cmd_entry cmd_run_shell_entry = {
"run-shell", "run", "run-shell", "run",
"t:", 1, 1, "bt:", 1, 1,
CMD_TARGET_PANE_USAGE " command", "[-b] " CMD_TARGET_PANE_USAGE " shell-command",
0, 0,
NULL, NULL,
NULL, NULL,
@ -47,7 +47,8 @@ const struct cmd_entry cmd_run_shell_entry = {
struct cmd_run_shell_data { struct cmd_run_shell_data {
char *cmd; char *cmd;
struct cmd_ctx *ctx; struct cmd_q *cmdq;
int bflag;
u_int wp_id; u_int wp_id;
}; };
@ -55,12 +56,11 @@ void
cmd_run_shell_print(struct job *job, const char *msg) cmd_run_shell_print(struct job *job, const char *msg)
{ {
struct cmd_run_shell_data *cdata = job->data; struct cmd_run_shell_data *cdata = job->data;
struct cmd_ctx *ctx = cdata->ctx;
struct window_pane *wp; struct window_pane *wp;
wp = window_pane_find_by_id(cdata->wp_id); wp = window_pane_find_by_id(cdata->wp_id);
if (wp == NULL) { if (wp == NULL) {
ctx->print(ctx, "%s", msg); cmdq_print(cdata->cmdq, "%s", msg);
return; return;
} }
@ -71,47 +71,49 @@ cmd_run_shell_print(struct job *job, const char *msg)
} }
enum cmd_retval 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 args *args = self->args;
struct cmd_run_shell_data *cdata; struct cmd_run_shell_data *cdata;
const char *shellcmd = args->argv[0]; const char *shellcmd = args->argv[0];
struct window_pane *wp; 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); return (CMD_RETURN_ERROR);
cdata = xmalloc(sizeof *cdata); cdata = xmalloc(sizeof *cdata);
cdata->cmd = xstrdup(args->argv[0]); cdata->cmd = xstrdup(args->argv[0]);
cdata->bflag = args_has(args, 'b');
cdata->wp_id = wp->id; cdata->wp_id = wp->id;
cdata->ctx = ctx; cdata->cmdq = cmdq;
cmd_ref_ctx(ctx); cmdq->references++;
job_run(shellcmd, cmd_run_shell_callback, cmd_run_shell_free, cdata); 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 void
cmd_run_shell_callback(struct job *job) cmd_run_shell_callback(struct job *job)
{ {
struct cmd_run_shell_data *cdata = job->data; struct cmd_run_shell_data *cdata = job->data;
struct cmd_ctx *ctx = cdata->ctx; struct cmd_q *cmdq = cdata->cmdq;
char *cmd, *msg, *line; char *cmd, *msg, *line;
size_t size; size_t size;
int retcode; int retcode;
u_int lines; u_int lines;
if (ctx->cmdclient != NULL && ctx->cmdclient->flags & CLIENT_DEAD) if (cmdq->dead)
return;
if (ctx->curclient != NULL && ctx->curclient->flags & CLIENT_DEAD)
return; return;
cmd = cdata->cmd;
lines = 0; lines = 0;
do { do {
if ((line = evbuffer_readline(job->event->input)) != NULL) { if ((line = evbuffer_readline(job->event->input)) != NULL) {
cmd_run_shell_print (job, line); cmd_run_shell_print(job, line);
free(line); free(line);
lines++; lines++;
} }
@ -129,8 +131,6 @@ cmd_run_shell_callback(struct job *job)
free(line); free(line);
} }
cmd = cdata->cmd;
msg = NULL; msg = NULL;
if (WIFEXITED(job->status)) { if (WIFEXITED(job->status)) {
if ((retcode = WEXITSTATUS(job->status)) != 0) if ((retcode = WEXITSTATUS(job->status)) != 0)
@ -141,7 +141,7 @@ cmd_run_shell_callback(struct job *job)
} }
if (msg != NULL) { if (msg != NULL) {
if (lines == 0) if (lines == 0)
ctx->info(ctx, "%s", msg); cmdq_info(cmdq, "%s", msg);
else else
cmd_run_shell_print(job, msg); cmd_run_shell_print(job, msg);
free(msg); free(msg);
@ -152,11 +152,10 @@ void
cmd_run_shell_free(void *data) cmd_run_shell_free(void *data)
{ {
struct cmd_run_shell_data *cdata = data; struct cmd_run_shell_data *cdata = data;
struct cmd_ctx *ctx = cdata->ctx; struct cmd_q *cmdq = cdata->cmdq;
if (ctx->cmdclient != NULL) if (!cmdq_free(cmdq) && !cdata->bflag)
ctx->cmdclient->flags |= CLIENT_EXIT; cmdq_continue(cmdq);
cmd_free_ctx(ctx);
free(cdata->cmd); free(cdata->cmd);
free(cdata); free(cdata);

View File

@ -29,7 +29,7 @@
* Saves a paste buffer to a file. * 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 = { const struct cmd_entry cmd_save_buffer_entry = {
"save-buffer", "saveb", "save-buffer", "saveb",
@ -52,7 +52,7 @@ const struct cmd_entry cmd_show_buffer_entry = {
}; };
enum cmd_retval 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 args *args = self->args;
struct client *c; struct client *c;
@ -69,20 +69,20 @@ cmd_save_buffer_exec(struct cmd *self, struct cmd_ctx *ctx)
if (!args_has(args, 'b')) { if (!args_has(args, 'b')) {
if ((pb = paste_get_top(&global_buffers)) == NULL) { if ((pb = paste_get_top(&global_buffers)) == NULL) {
ctx->error(ctx, "no buffers"); cmdq_error(cmdq, "no buffers");
return (CMD_RETURN_ERROR); return (CMD_RETURN_ERROR);
} }
} else { } else {
buffer = args_strtonum(args, 'b', 0, INT_MAX, &cause); buffer = args_strtonum(args, 'b', 0, INT_MAX, &cause);
if (cause != NULL) { if (cause != NULL) {
ctx->error(ctx, "buffer %s", cause); cmdq_error(cmdq, "buffer %s", cause);
free(cause); free(cause);
return (CMD_RETURN_ERROR); return (CMD_RETURN_ERROR);
} }
pb = paste_get_index(&global_buffers, buffer); pb = paste_get_index(&global_buffers, buffer);
if (pb == NULL) { if (pb == NULL) {
ctx->error(ctx, "no buffer %d", buffer); cmdq_error(cmdq, "no buffer %d", buffer);
return (CMD_RETURN_ERROR); return (CMD_RETURN_ERROR);
} }
} }
@ -92,22 +92,20 @@ cmd_save_buffer_exec(struct cmd *self, struct cmd_ctx *ctx)
else else
path = args->argv[0]; path = args->argv[0];
if (strcmp(path, "-") == 0) { if (strcmp(path, "-") == 0) {
c = ctx->cmdclient; c = cmdq->client;
if (c != NULL) if (c == NULL) {
goto do_stdout; cmdq_error(cmdq, "can't write to stdout");
c = ctx->curclient;
if (c->flags & CLIENT_CONTROL)
goto do_stdout;
if (c != NULL)
goto do_print;
ctx->error(ctx, "can't write to stdout");
return (CMD_RETURN_ERROR); return (CMD_RETURN_ERROR);
} }
if (c->session == NULL || (c->flags & CLIENT_CONTROL))
goto do_stdout;
goto do_print;
}
c = ctx->cmdclient; c = cmdq->client;
if (c != NULL) if (c != NULL)
wd = c->cwd; 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"); wd = options_get_string(&s->options, "default-path");
if (*wd == '\0') if (*wd == '\0')
wd = s->cwd; wd = s->cwd;
@ -126,11 +124,11 @@ cmd_save_buffer_exec(struct cmd *self, struct cmd_ctx *ctx)
f = fopen(path, "wb"); f = fopen(path, "wb");
umask(mask); umask(mask);
if (f == NULL) { if (f == NULL) {
ctx->error(ctx, "%s: %s", path, strerror(errno)); cmdq_error(cmdq, "%s: %s", path, strerror(errno));
return (CMD_RETURN_ERROR); return (CMD_RETURN_ERROR);
} }
if (fwrite(pb->data, 1, pb->size, f) != pb->size) { if (fwrite(pb->data, 1, pb->size, f) != pb->size) {
ctx->error(ctx, "%s: fwrite error", path); cmdq_error(cmdq, "%s: fwrite error", path);
fclose(f); fclose(f);
return (CMD_RETURN_ERROR); return (CMD_RETURN_ERROR);
} }
@ -145,7 +143,7 @@ do_stdout:
do_print: do_print:
if (pb->size > (INT_MAX / 4) - 1) { if (pb->size > (INT_MAX / 4) - 1) {
ctx->error(ctx, "buffer too big"); cmdq_error(cmdq, "buffer too big");
return (CMD_RETURN_ERROR); return (CMD_RETURN_ERROR);
} }
msg = NULL; msg = NULL;
@ -164,7 +162,7 @@ do_print:
msg = xrealloc(msg, 1, msglen); msg = xrealloc(msg, 1, msglen);
strvisx(msg, start, size, VIS_OCTAL|VIS_TAB); strvisx(msg, start, size, VIS_OCTAL|VIS_TAB);
ctx->print(ctx, "%s", msg); cmdq_print(cmdq, "%s", msg);
used += size + (end != NULL); used += size + (end != NULL);
} }

View File

@ -25,7 +25,7 @@
*/ */
void cmd_select_layout_key_binding(struct cmd *, int); 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 = { const struct cmd_entry cmd_select_layout_entry = {
"select-layout", "selectl", "select-layout", "selectl",
@ -83,14 +83,14 @@ cmd_select_layout_key_binding(struct cmd *self, int key)
} }
enum cmd_retval 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 args *args = self->args;
struct winlink *wl; struct winlink *wl;
const char *layoutname; const char *layoutname;
int next, previous, layout; 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); return (CMD_RETURN_ERROR);
next = self->entry == &cmd_next_layout_entry; next = self->entry == &cmd_next_layout_entry;
@ -106,7 +106,7 @@ cmd_select_layout_exec(struct cmd *self, struct cmd_ctx *ctx)
else else
layout = layout_set_previous(wl->window); layout = layout_set_previous(wl->window);
server_redraw_window(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); return (CMD_RETURN_NORMAL);
} }
@ -117,18 +117,18 @@ cmd_select_layout_exec(struct cmd *self, struct cmd_ctx *ctx)
if (layout != -1) { if (layout != -1) {
layout = layout_set_select(wl->window, layout); layout = layout_set_select(wl->window, layout);
server_redraw_window(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); return (CMD_RETURN_NORMAL);
} }
if (args->argc != 0) { if (args->argc != 0) {
layoutname = args->argv[0]; layoutname = args->argv[0];
if (layout_parse(wl->window, layoutname) == -1) { 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); return (CMD_RETURN_ERROR);
} }
server_redraw_window(wl->window); server_redraw_window(wl->window);
ctx->info(ctx, "arranging in: %s", layoutname); cmdq_info(cmdq, "arranging in: %s", layoutname);
} }
return (CMD_RETURN_NORMAL); return (CMD_RETURN_NORMAL);
} }

View File

@ -25,7 +25,7 @@
*/ */
void cmd_select_pane_key_binding(struct cmd *, int); 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 = { const struct cmd_entry cmd_select_pane_entry = {
"select-pane", "selectp", "select-pane", "selectp",
@ -64,19 +64,19 @@ cmd_select_pane_key_binding(struct cmd *self, int key)
} }
enum cmd_retval 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 args *args = self->args;
struct winlink *wl; struct winlink *wl;
struct window_pane *wp; struct window_pane *wp;
if (self->entry == &cmd_last_pane_entry || args_has(args, 'l')) { 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) if (wl == NULL)
return (CMD_RETURN_ERROR); return (CMD_RETURN_ERROR);
if (wl->window->last == NULL) { if (wl->window->last == NULL) {
ctx->error(ctx, "no last pane"); cmdq_error(cmdq, "no last pane");
return (CMD_RETURN_ERROR); return (CMD_RETURN_ERROR);
} }
@ -87,11 +87,11 @@ cmd_select_pane_exec(struct cmd *self, struct cmd_ctx *ctx)
return (CMD_RETURN_NORMAL); 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); return (CMD_RETURN_ERROR);
if (!window_pane_visible(wp)) { if (!window_pane_visible(wp)) {
ctx->error(ctx, "pane not visible"); cmdq_error(cmdq, "pane not visible");
return (CMD_RETURN_ERROR); 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')) else if (args_has(self->args, 'D'))
wp = window_pane_find_down(wp); wp = window_pane_find_down(wp);
if (wp == NULL) { if (wp == NULL) {
ctx->error(ctx, "pane not found"); cmdq_error(cmdq, "pane not found");
return (CMD_RETURN_ERROR); return (CMD_RETURN_ERROR);
} }

View File

@ -27,7 +27,7 @@
*/ */
void cmd_select_window_key_binding(struct cmd *, int); 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 = { const struct cmd_entry cmd_select_window_entry = {
"select-window", "selectw", "select-window", "selectw",
@ -84,7 +84,7 @@ cmd_select_window_key_binding(struct cmd *self, int key)
} }
enum cmd_retval 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 args *args = self->args;
struct winlink *wl; struct winlink *wl;
@ -102,31 +102,31 @@ cmd_select_window_exec(struct cmd *self, struct cmd_ctx *ctx)
last = 1; last = 1;
if (next || previous || last) { 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) if (s == NULL)
return (CMD_RETURN_ERROR); return (CMD_RETURN_ERROR);
activity = args_has(self->args, 'a'); activity = args_has(self->args, 'a');
if (next) { if (next) {
if (session_next(s, activity) != 0) { if (session_next(s, activity) != 0) {
ctx->error(ctx, "no next window"); cmdq_error(cmdq, "no next window");
return (CMD_RETURN_ERROR); return (CMD_RETURN_ERROR);
} }
} else if (previous) { } else if (previous) {
if (session_previous(s, activity) != 0) { if (session_previous(s, activity) != 0) {
ctx->error(ctx, "no previous window"); cmdq_error(cmdq, "no previous window");
return (CMD_RETURN_ERROR); return (CMD_RETURN_ERROR);
} }
} else { } else {
if (session_last(s) != 0) { if (session_last(s) != 0) {
ctx->error(ctx, "no last window"); cmdq_error(cmdq, "no last window");
return (CMD_RETURN_ERROR); return (CMD_RETURN_ERROR);
} }
} }
server_redraw_session(s); server_redraw_session(s);
} else { } else {
wl = cmd_find_window(ctx, args_get(args, 't'), &s); wl = cmd_find_window(cmdq, args_get(args, 't'), &s);
if (wl == NULL) if (wl == NULL)
return (CMD_RETURN_ERROR); 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 (args_has(self->args, 'T') && wl == s->curw) {
if (session_last(s) != 0) { if (session_last(s) != 0) {
ctx->error(ctx, "no last window"); cmdq_error(cmdq, "no last window");
return (-1); return (-1);
} }
server_redraw_session(s); server_redraw_session(s);

View File

@ -27,7 +27,7 @@
* Send keys to client. * 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 = { const struct cmd_entry cmd_send_keys_entry = {
"send-keys", "send", "send-keys", "send",
@ -50,7 +50,7 @@ const struct cmd_entry cmd_send_prefix_entry = {
}; };
enum cmd_retval 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 args *args = self->args;
struct window_pane *wp; struct window_pane *wp;
@ -59,7 +59,7 @@ cmd_send_keys_exec(struct cmd *self, struct cmd_ctx *ctx)
const char *str; const char *str;
int i, key; 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); return (CMD_RETURN_ERROR);
if (self->entry == &cmd_send_prefix_entry) { if (self->entry == &cmd_send_prefix_entry) {

View File

@ -30,7 +30,7 @@
* Show various information about server. * 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 = { const struct cmd_entry cmd_server_info_entry = {
"server-info", "info", "server-info", "info",
@ -43,7 +43,7 @@ const struct cmd_entry cmd_server_info_entry = {
}; };
enum cmd_retval 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 tty_term *term;
struct client *c; struct client *c;
@ -65,48 +65,48 @@ cmd_server_info_exec(unused struct cmd *self, struct cmd_ctx *ctx)
tim = ctime(&start_time); tim = ctime(&start_time);
*strchr(tim, '\n') = '\0'; *strchr(tim, '\n') = '\0';
ctx->print(ctx, cmdq_print(cmdq,
"tmux " VERSION ", pid %ld, started %s", (long) getpid(), tim); "tmux " VERSION ", pid %ld, started %s", (long) getpid(), tim);
ctx->print( cmdq_print(cmdq, "socket path %s, debug level %d", socket_path,
ctx, "socket path %s, debug level %d", socket_path, debug_level); debug_level);
if (uname(&un) >= 0) { 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); un.sysname, un.release, un.version, un.machine);
} }
if (cfg_file != NULL) if (cfg_file != NULL)
ctx->print(ctx, "configuration file is %s", cfg_file); cmdq_print(cmdq, "configuration file is %s", cfg_file);
else else
ctx->print(ctx, "configuration file not specified"); cmdq_print(cmdq, "configuration file not specified");
ctx->print(ctx, "protocol version is %d", PROTOCOL_VERSION); cmdq_print(cmdq, "protocol version is %d", PROTOCOL_VERSION);
ctx->print(ctx, "%s", ""); cmdq_print(cmdq, "%s", "");
ctx->print(ctx, "Clients:"); cmdq_print(cmdq, "Clients:");
for (i = 0; i < ARRAY_LENGTH(&clients); i++) { for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
c = ARRAY_ITEM(&clients, i); c = ARRAY_ITEM(&clients, i);
if (c == NULL || c->session == NULL) if (c == NULL || c->session == NULL)
continue; 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, "class=%u] [flags=0x%x/0x%x, references=%u]", i,
c->tty.path, c->ibuf.fd, c->tty.fd, c->session->name, c->tty.path, c->ibuf.fd, c->tty.fd, c->session->name,
c->tty.sx, c->tty.sy, c->tty.termname, c->tty.sx, c->tty.sy, c->tty.termname,
c->tty.tio.c_cc[VERASE], c->tty.class, c->tty.tio.c_cc[VERASE], c->tty.class,
c->flags, c->tty.flags, c->references); 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) { RB_FOREACH(s, sessions, &sessions) {
t = s->creation_time.tv_sec; t = s->creation_time.tv_sec;
tim = ctime(&t); tim = ctime(&t);
*strchr(tim, '\n') = '\0'; *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, "[flags=0x%x]", s->idx, s->name,
winlink_count(&s->windows), tim, s->sx, s->sy, s->flags); winlink_count(&s->windows), tim, s->sx, s->sy, s->flags);
RB_FOREACH(wl, winlinks, &s->windows) { RB_FOREACH(wl, winlinks, &s->windows) {
w = wl->window; 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, "references=%u, last layout=%d]", wl->idx, w->name,
w->sx, w->sy, w->flags, w->references, w->sx, w->sy, w->flags, w->references,
w->lastlayout); w->lastlayout);
@ -122,7 +122,7 @@ cmd_server_info_exec(unused struct cmd *self, struct cmd_ctx *ctx)
size += gl->cellsize * size += gl->cellsize *
sizeof *gl->celldata; sizeof *gl->celldata;
} }
ctx->print(ctx, cmdq_print(cmdq,
"%6u: %s %lu %d %u/%u, %zu bytes", j, "%6u: %s %lu %d %u/%u, %zu bytes", j,
wp->tty, (u_long) wp->pid, wp->fd, lines, wp->tty, (u_long) wp->pid, wp->fd, lines,
gd->hsize + gd->sy, size); 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) { 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); term->name, term->references, term->flags);
for (i = 0; i < NTTYCODE; i++) { for (i = 0; i < NTTYCODE; i++) {
ent = &tty_term_codes[i]; ent = &tty_term_codes[i];
code = &term->codes[ent->code]; code = &term->codes[ent->code];
switch (code->type) { switch (code->type) {
case TTYCODE_NONE: case TTYCODE_NONE:
ctx->print(ctx, "%2u: %s: [missing]", cmdq_print(cmdq, "%2u: %s: [missing]",
ent->code, ent->name); ent->code, ent->name);
break; break;
case TTYCODE_STRING: case TTYCODE_STRING:
strnvis(out, code->value.string, sizeof out, strnvis(out, code->value.string, sizeof out,
VIS_OCTAL|VIS_TAB|VIS_NL); 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); ent->code, ent->name, out);
break; break;
case TTYCODE_NUMBER: case TTYCODE_NUMBER:
ctx->print(ctx, "%2u: %s: (number) %d", cmdq_print(cmdq, "%2u: %s: (number) %d",
ent->code, ent->name, code->value.number); ent->code, ent->name, code->value.number);
break; break;
case TTYCODE_FLAG: case TTYCODE_FLAG:
ctx->print(ctx, "%2u: %s: (flag) %s", cmdq_print(cmdq, "%2u: %s: (flag) %s",
ent->code, ent->name, ent->code, ent->name,
code->value.flag ? "true" : "false"); code->value.flag ? "true" : "false");
break; break;
} }
} }
} }
ctx->print(ctx, "%s", ""); cmdq_print(cmdq, "%s", "");
ctx->print(ctx, "Jobs:"); cmdq_print(cmdq, "Jobs:");
LIST_FOREACH(job, &all_jobs, lentry) { 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); job->cmd, job->fd, job->pid, job->status);
} }

View File

@ -27,7 +27,7 @@
* Add or set a paste buffer. * 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 = { const struct cmd_entry cmd_set_buffer_entry = {
"set-buffer", "setb", "set-buffer", "setb",
@ -40,7 +40,7 @@ const struct cmd_entry cmd_set_buffer_entry = {
}; };
enum cmd_retval 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; struct args *args = self->args;
u_int limit; 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); buffer = args_strtonum(args, 'b', 0, INT_MAX, &cause);
if (cause != NULL) { if (cause != NULL) {
ctx->error(ctx, "buffer %s", cause); cmdq_error(cmdq, "buffer %s", cause);
free(cause); free(cause);
free(pdata); free(pdata);
return (CMD_RETURN_ERROR); return (CMD_RETURN_ERROR);
} }
if (paste_replace(&global_buffers, buffer, pdata, psize) != 0) { 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); free(pdata);
return (CMD_RETURN_ERROR); return (CMD_RETURN_ERROR);
} }

View File

@ -27,7 +27,7 @@
* Set an environment variable. * 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 = { const struct cmd_entry cmd_set_environment_entry = {
"set-environment", "setenv", "set-environment", "setenv",
@ -40,7 +40,7 @@ const struct cmd_entry cmd_set_environment_entry = {
}; };
enum cmd_retval 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 args *args = self->args;
struct session *s; struct session *s;
@ -49,11 +49,11 @@ cmd_set_environment_exec(struct cmd *self, struct cmd_ctx *ctx)
name = args->argv[0]; name = args->argv[0];
if (*name == '\0') { if (*name == '\0') {
ctx->error(ctx, "empty variable name"); cmdq_error(cmdq, "empty variable name");
return (CMD_RETURN_ERROR); return (CMD_RETURN_ERROR);
} }
if (strchr(name, '=') != NULL) { if (strchr(name, '=') != NULL) {
ctx->error(ctx, "variable name contains ="); cmdq_error(cmdq, "variable name contains =");
return (CMD_RETURN_ERROR); 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')) if (args_has(self->args, 'g'))
env = &global_environ; env = &global_environ;
else { 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); return (CMD_RETURN_ERROR);
env = &s->environ; env = &s->environ;
} }
if (args_has(self->args, 'u')) { if (args_has(self->args, 'u')) {
if (value != NULL) { 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); return (CMD_RETURN_ERROR);
} }
environ_unset(env, name); environ_unset(env, name);
} else if (args_has(self->args, 'r')) { } else if (args_has(self->args, 'r')) {
if (value != NULL) { 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); return (CMD_RETURN_ERROR);
} }
environ_set(env, name, NULL); environ_set(env, name, NULL);
} else { } else {
if (value == NULL) { if (value == NULL) {
ctx->error(ctx, "no value specified"); cmdq_error(cmdq, "no value specified");
return (CMD_RETURN_ERROR); return (CMD_RETURN_ERROR);
} }
environ_set(env, name, value); environ_set(env, name, value);

View File

@ -27,37 +27,37 @@
* Set an option. * Set an option.
*/ */
enum cmd_retval cmd_set_option_exec(struct cmd *, struct cmd_ctx *); enum cmd_retval cmd_set_option_exec(struct cmd *, struct cmd_q *);
enum cmd_retval cmd_set_option_user(struct cmd *, struct cmd_ctx *, enum cmd_retval cmd_set_option_user(struct cmd *, struct cmd_q *,
const char *, const char *); const char *, const char *);
int cmd_set_option_unset(struct cmd *, struct cmd_ctx *, int cmd_set_option_unset(struct cmd *, struct cmd_q *,
const struct options_table_entry *, struct options *, const struct options_table_entry *, struct options *,
const char *); const char *);
int cmd_set_option_set(struct cmd *, struct cmd_ctx *, int cmd_set_option_set(struct cmd *, struct cmd_q *,
const struct options_table_entry *, struct options *, const struct options_table_entry *, struct options *,
const char *); const char *);
struct options_entry *cmd_set_option_string(struct cmd *, struct cmd_ctx *, struct options_entry *cmd_set_option_string(struct cmd *, struct cmd_q *,
const struct options_table_entry *, struct options *, const struct options_table_entry *, struct options *,
const char *); const char *);
struct options_entry *cmd_set_option_number(struct cmd *, struct cmd_ctx *, struct options_entry *cmd_set_option_number(struct cmd *, struct cmd_q *,
const struct options_table_entry *, struct options *, const struct options_table_entry *, struct options *,
const char *); const char *);
struct options_entry *cmd_set_option_key(struct cmd *, struct cmd_ctx *, struct options_entry *cmd_set_option_key(struct cmd *, struct cmd_q *,
const struct options_table_entry *, struct options *, const struct options_table_entry *, struct options *,
const char *); const char *);
struct options_entry *cmd_set_option_colour(struct cmd *, struct cmd_ctx *, struct options_entry *cmd_set_option_colour(struct cmd *, struct cmd_q *,
const struct options_table_entry *, struct options *, const struct options_table_entry *, struct options *,
const char *); const char *);
struct options_entry *cmd_set_option_attributes(struct cmd *, struct cmd_ctx *, struct options_entry *cmd_set_option_attributes(struct cmd *, struct cmd_q *,
const struct options_table_entry *, struct options *, const struct options_table_entry *, struct options *,
const char *); const char *);
struct options_entry *cmd_set_option_flag(struct cmd *, struct cmd_ctx *, struct options_entry *cmd_set_option_flag(struct cmd *, struct cmd_q *,
const struct options_table_entry *, struct options *, const struct options_table_entry *, struct options *,
const char *); const char *);
struct options_entry *cmd_set_option_choice(struct cmd *, struct cmd_ctx *, struct options_entry *cmd_set_option_choice(struct cmd *, struct cmd_q *,
const struct options_table_entry *, struct options *, const struct options_table_entry *, struct options *,
const char *); const char *);
@ -82,7 +82,7 @@ const struct cmd_entry cmd_set_window_option_entry = {
}; };
enum cmd_retval enum cmd_retval
cmd_set_option_exec(struct cmd *self, struct cmd_ctx *ctx) cmd_set_option_exec(struct cmd *self, struct cmd_q *cmdq)
{ {
struct args *args = self->args; struct args *args = self->args;
const struct options_table_entry *table, *oe; const struct options_table_entry *table, *oe;
@ -97,7 +97,7 @@ cmd_set_option_exec(struct cmd *self, struct cmd_ctx *ctx)
/* Get the option name and value. */ /* Get the option name and value. */
optstr = args->argv[0]; optstr = args->argv[0];
if (*optstr == '\0') { if (*optstr == '\0') {
ctx->error(ctx, "invalid option"); cmdq_error(cmdq, "invalid option");
return (CMD_RETURN_ERROR); return (CMD_RETURN_ERROR);
} }
if (args->argc < 2) if (args->argc < 2)
@ -107,16 +107,16 @@ cmd_set_option_exec(struct cmd *self, struct cmd_ctx *ctx)
/* Is this a user option? */ /* Is this a user option? */
if (*optstr == '@') if (*optstr == '@')
return (cmd_set_option_user(self, ctx, optstr, valstr)); return (cmd_set_option_user(self, cmdq, optstr, valstr));
/* Find the option entry, try each table. */ /* Find the option entry, try each table. */
table = oe = NULL; table = oe = NULL;
if (options_table_find(optstr, &table, &oe) != 0) { if (options_table_find(optstr, &table, &oe) != 0) {
ctx->error(ctx, "ambiguous option: %s", optstr); cmdq_error(cmdq, "ambiguous option: %s", optstr);
return (CMD_RETURN_ERROR); return (CMD_RETURN_ERROR);
} }
if (oe == NULL) { if (oe == NULL) {
ctx->error(ctx, "unknown option: %s", optstr); cmdq_error(cmdq, "unknown option: %s", optstr);
return (CMD_RETURN_ERROR); return (CMD_RETURN_ERROR);
} }
@ -127,7 +127,7 @@ cmd_set_option_exec(struct cmd *self, struct cmd_ctx *ctx)
if (args_has(self->args, 'g')) if (args_has(self->args, 'g'))
oo = &global_w_options; oo = &global_w_options;
else { else {
wl = cmd_find_window(ctx, args_get(args, 't'), NULL); wl = cmd_find_window(cmdq, args_get(args, 't'), NULL);
if (wl == NULL) if (wl == NULL)
return (CMD_RETURN_ERROR); return (CMD_RETURN_ERROR);
oo = &wl->window->options; oo = &wl->window->options;
@ -136,22 +136,22 @@ cmd_set_option_exec(struct cmd *self, struct cmd_ctx *ctx)
if (args_has(self->args, 'g')) if (args_has(self->args, 'g'))
oo = &global_s_options; oo = &global_s_options;
else { else {
s = cmd_find_session(ctx, args_get(args, 't'), 0); s = cmd_find_session(cmdq, args_get(args, 't'), 0);
if (s == NULL) if (s == NULL)
return (CMD_RETURN_ERROR); return (CMD_RETURN_ERROR);
oo = &s->options; oo = &s->options;
} }
} else { } else {
ctx->error(ctx, "unknown table"); cmdq_error(cmdq, "unknown table");
return (CMD_RETURN_ERROR); return (CMD_RETURN_ERROR);
} }
/* Unset or set the option. */ /* Unset or set the option. */
if (args_has(args, 'u')) { if (args_has(args, 'u')) {
if (cmd_set_option_unset(self, ctx, oe, oo, valstr) != 0) if (cmd_set_option_unset(self, cmdq, oe, oo, valstr) != 0)
return (CMD_RETURN_ERROR); return (CMD_RETURN_ERROR);
} else { } else {
if (cmd_set_option_set(self, ctx, oe, oo, valstr) != 0) if (cmd_set_option_set(self, cmdq, oe, oo, valstr) != 0)
return (CMD_RETURN_ERROR); return (CMD_RETURN_ERROR);
} }
@ -180,7 +180,7 @@ cmd_set_option_exec(struct cmd *self, struct cmd_ctx *ctx)
/* Set user option. */ /* Set user option. */
enum cmd_retval enum cmd_retval
cmd_set_option_user(struct cmd *self, struct cmd_ctx *ctx, const char* optstr, cmd_set_option_user(struct cmd *self, struct cmd_q *cmdq, const char* optstr,
const char *valstr) const char *valstr)
{ {
struct args *args = self->args; struct args *args = self->args;
@ -195,7 +195,7 @@ cmd_set_option_user(struct cmd *self, struct cmd_ctx *ctx, const char* optstr,
if (args_has(self->args, 'g')) if (args_has(self->args, 'g'))
oo = &global_w_options; oo = &global_w_options;
else { else {
wl = cmd_find_window(ctx, args_get(args, 't'), NULL); wl = cmd_find_window(cmdq, args_get(args, 't'), NULL);
if (wl == NULL) if (wl == NULL)
return (CMD_RETURN_ERROR); return (CMD_RETURN_ERROR);
oo = &wl->window->options; oo = &wl->window->options;
@ -204,7 +204,7 @@ cmd_set_option_user(struct cmd *self, struct cmd_ctx *ctx, const char* optstr,
if (args_has(self->args, 'g')) if (args_has(self->args, 'g'))
oo = &global_s_options; oo = &global_s_options;
else { else {
s = cmd_find_session(ctx, args_get(args, 't'), 0); s = cmd_find_session(cmdq, args_get(args, 't'), 0);
if (s == NULL) if (s == NULL)
return (CMD_RETURN_ERROR); return (CMD_RETURN_ERROR);
oo = &s->options; oo = &s->options;
@ -213,23 +213,25 @@ cmd_set_option_user(struct cmd *self, struct cmd_ctx *ctx, const char* optstr,
if (args_has(args, 'u')) { if (args_has(args, 'u')) {
if (options_find1(oo, optstr) == NULL) { if (options_find1(oo, optstr) == NULL) {
ctx->error(ctx, "unknown option: %s", optstr); cmdq_error(cmdq, "unknown option: %s", optstr);
return (CMD_RETURN_ERROR); return (CMD_RETURN_ERROR);
} }
if (valstr != NULL) { if (valstr != NULL) {
ctx->error(ctx, "value passed to unset option: %s", cmdq_error(cmdq, "value passed to unset option: %s",
optstr); optstr);
return (CMD_RETURN_ERROR); return (CMD_RETURN_ERROR);
} }
options_remove(oo, optstr); options_remove(oo, optstr);
} else { } else {
if (valstr == NULL) { if (valstr == NULL) {
ctx->error(ctx, "empty value"); cmdq_error(cmdq, "empty value");
return (CMD_RETURN_ERROR); return (CMD_RETURN_ERROR);
} }
options_set_string(oo, optstr, "%s", valstr); options_set_string(oo, optstr, "%s", valstr);
if (!args_has(args, 'q')) if (!args_has(args, 'q')) {
ctx->info(ctx, "set option: %s -> %s", optstr, valstr); cmdq_info(cmdq, "set option: %s -> %s", optstr,
valstr);
}
} }
return (CMD_RETURN_NORMAL); return (CMD_RETURN_NORMAL);
} }
@ -237,29 +239,29 @@ cmd_set_option_user(struct cmd *self, struct cmd_ctx *ctx, const char* optstr,
/* Unset an option. */ /* Unset an option. */
int int
cmd_set_option_unset(struct cmd *self, struct cmd_ctx *ctx, cmd_set_option_unset(struct cmd *self, struct cmd_q *cmdq,
const struct options_table_entry *oe, struct options *oo, const char *value) const struct options_table_entry *oe, struct options *oo, const char *value)
{ {
struct args *args = self->args; struct args *args = self->args;
if (args_has(args, 'g')) { if (args_has(args, 'g')) {
ctx->error(ctx, "can't unset global option: %s", oe->name); cmdq_error(cmdq, "can't unset global option: %s", oe->name);
return (-1); return (-1);
} }
if (value != NULL) { if (value != NULL) {
ctx->error(ctx, "value passed to unset option: %s", oe->name); cmdq_error(cmdq, "value passed to unset option: %s", oe->name);
return (-1); return (-1);
} }
options_remove(oo, oe->name); options_remove(oo, oe->name);
if (!args_has(args, 'q')) if (!args_has(args, 'q'))
ctx->info(ctx, "unset option: %s", oe->name); cmdq_info(cmdq, "unset option: %s", oe->name);
return (0); return (0);
} }
/* Set an option. */ /* Set an option. */
int int
cmd_set_option_set(struct cmd *self, struct cmd_ctx *ctx, cmd_set_option_set(struct cmd *self, struct cmd_q *cmdq,
const struct options_table_entry *oe, struct options *oo, const char *value) const struct options_table_entry *oe, struct options *oo, const char *value)
{ {
struct args *args = self->args; struct args *args = self->args;
@ -267,32 +269,32 @@ cmd_set_option_set(struct cmd *self, struct cmd_ctx *ctx,
const char *s; const char *s;
if (oe->type != OPTIONS_TABLE_FLAG && value == NULL) { if (oe->type != OPTIONS_TABLE_FLAG && value == NULL) {
ctx->error(ctx, "empty value"); cmdq_error(cmdq, "empty value");
return (-1); return (-1);
} }
o = NULL; o = NULL;
switch (oe->type) { switch (oe->type) {
case OPTIONS_TABLE_STRING: case OPTIONS_TABLE_STRING:
o = cmd_set_option_string(self, ctx, oe, oo, value); o = cmd_set_option_string(self, cmdq, oe, oo, value);
break; break;
case OPTIONS_TABLE_NUMBER: case OPTIONS_TABLE_NUMBER:
o = cmd_set_option_number(self, ctx, oe, oo, value); o = cmd_set_option_number(self, cmdq, oe, oo, value);
break; break;
case OPTIONS_TABLE_KEY: case OPTIONS_TABLE_KEY:
o = cmd_set_option_key(self, ctx, oe, oo, value); o = cmd_set_option_key(self, cmdq, oe, oo, value);
break; break;
case OPTIONS_TABLE_COLOUR: case OPTIONS_TABLE_COLOUR:
o = cmd_set_option_colour(self, ctx, oe, oo, value); o = cmd_set_option_colour(self, cmdq, oe, oo, value);
break; break;
case OPTIONS_TABLE_ATTRIBUTES: case OPTIONS_TABLE_ATTRIBUTES:
o = cmd_set_option_attributes(self, ctx, oe, oo, value); o = cmd_set_option_attributes(self, cmdq, oe, oo, value);
break; break;
case OPTIONS_TABLE_FLAG: case OPTIONS_TABLE_FLAG:
o = cmd_set_option_flag(self, ctx, oe, oo, value); o = cmd_set_option_flag(self, cmdq, oe, oo, value);
break; break;
case OPTIONS_TABLE_CHOICE: case OPTIONS_TABLE_CHOICE:
o = cmd_set_option_choice(self, ctx, oe, oo, value); o = cmd_set_option_choice(self, cmdq, oe, oo, value);
break; break;
} }
if (o == NULL) if (o == NULL)
@ -300,13 +302,13 @@ cmd_set_option_set(struct cmd *self, struct cmd_ctx *ctx,
s = options_table_print_entry(oe, o, 0); s = options_table_print_entry(oe, o, 0);
if (!args_has(args, 'q')) if (!args_has(args, 'q'))
ctx->info(ctx, "set option: %s -> %s", oe->name, s); cmdq_info(cmdq, "set option: %s -> %s", oe->name, s);
return (0); return (0);
} }
/* Set a string option. */ /* Set a string option. */
struct options_entry * struct options_entry *
cmd_set_option_string(struct cmd *self, unused struct cmd_ctx *ctx, cmd_set_option_string(struct cmd *self, unused struct cmd_q *cmdq,
const struct options_table_entry *oe, struct options *oo, const char *value) const struct options_table_entry *oe, struct options *oo, const char *value)
{ {
struct args *args = self->args; struct args *args = self->args;
@ -327,7 +329,7 @@ cmd_set_option_string(struct cmd *self, unused struct cmd_ctx *ctx,
/* Set a number option. */ /* Set a number option. */
struct options_entry * struct options_entry *
cmd_set_option_number(unused struct cmd *self, struct cmd_ctx *ctx, cmd_set_option_number(unused struct cmd *self, struct cmd_q *cmdq,
const struct options_table_entry *oe, struct options *oo, const char *value) const struct options_table_entry *oe, struct options *oo, const char *value)
{ {
long long ll; long long ll;
@ -335,7 +337,7 @@ cmd_set_option_number(unused struct cmd *self, struct cmd_ctx *ctx,
ll = strtonum(value, oe->minimum, oe->maximum, &errstr); ll = strtonum(value, oe->minimum, oe->maximum, &errstr);
if (errstr != NULL) { if (errstr != NULL) {
ctx->error(ctx, "value is %s: %s", errstr, value); cmdq_error(cmdq, "value is %s: %s", errstr, value);
return (NULL); return (NULL);
} }
@ -344,13 +346,13 @@ cmd_set_option_number(unused struct cmd *self, struct cmd_ctx *ctx,
/* Set a key option. */ /* Set a key option. */
struct options_entry * struct options_entry *
cmd_set_option_key(unused struct cmd *self, struct cmd_ctx *ctx, cmd_set_option_key(unused struct cmd *self, struct cmd_q *cmdq,
const struct options_table_entry *oe, struct options *oo, const char *value) const struct options_table_entry *oe, struct options *oo, const char *value)
{ {
int key; int key;
if ((key = key_string_lookup_string(value)) == KEYC_NONE) { if ((key = key_string_lookup_string(value)) == KEYC_NONE) {
ctx->error(ctx, "bad key: %s", value); cmdq_error(cmdq, "bad key: %s", value);
return (NULL); return (NULL);
} }
@ -359,13 +361,13 @@ cmd_set_option_key(unused struct cmd *self, struct cmd_ctx *ctx,
/* Set a colour option. */ /* Set a colour option. */
struct options_entry * struct options_entry *
cmd_set_option_colour(unused struct cmd *self, struct cmd_ctx *ctx, cmd_set_option_colour(unused struct cmd *self, struct cmd_q *cmdq,
const struct options_table_entry *oe, struct options *oo, const char *value) const struct options_table_entry *oe, struct options *oo, const char *value)
{ {
int colour; int colour;
if ((colour = colour_fromstring(value)) == -1) { if ((colour = colour_fromstring(value)) == -1) {
ctx->error(ctx, "bad colour: %s", value); cmdq_error(cmdq, "bad colour: %s", value);
return (NULL); return (NULL);
} }
@ -374,13 +376,13 @@ cmd_set_option_colour(unused struct cmd *self, struct cmd_ctx *ctx,
/* Set an attributes option. */ /* Set an attributes option. */
struct options_entry * struct options_entry *
cmd_set_option_attributes(unused struct cmd *self, struct cmd_ctx *ctx, cmd_set_option_attributes(unused struct cmd *self, struct cmd_q *cmdq,
const struct options_table_entry *oe, struct options *oo, const char *value) const struct options_table_entry *oe, struct options *oo, const char *value)
{ {
int attr; int attr;
if ((attr = attributes_fromstring(value)) == -1) { if ((attr = attributes_fromstring(value)) == -1) {
ctx->error(ctx, "bad attributes: %s", value); cmdq_error(cmdq, "bad attributes: %s", value);
return (NULL); return (NULL);
} }
@ -389,7 +391,7 @@ cmd_set_option_attributes(unused struct cmd *self, struct cmd_ctx *ctx,
/* Set a flag option. */ /* Set a flag option. */
struct options_entry * struct options_entry *
cmd_set_option_flag(unused struct cmd *self, struct cmd_ctx *ctx, cmd_set_option_flag(unused struct cmd *self, struct cmd_q *cmdq,
const struct options_table_entry *oe, struct options *oo, const char *value) const struct options_table_entry *oe, struct options *oo, const char *value)
{ {
int flag; int flag;
@ -406,7 +408,7 @@ cmd_set_option_flag(unused struct cmd *self, struct cmd_ctx *ctx,
strcasecmp(value, "no") == 0) strcasecmp(value, "no") == 0)
flag = 0; flag = 0;
else { else {
ctx->error(ctx, "bad value: %s", value); cmdq_error(cmdq, "bad value: %s", value);
return (NULL); return (NULL);
} }
} }
@ -416,8 +418,9 @@ cmd_set_option_flag(unused struct cmd *self, struct cmd_ctx *ctx,
/* Set a choice option. */ /* Set a choice option. */
struct options_entry * struct options_entry *
cmd_set_option_choice(unused struct cmd *self, struct cmd_ctx *ctx, cmd_set_option_choice(unused struct cmd *self, struct cmd_q *cmdq,
const struct options_table_entry *oe, struct options *oo, const char *value) const struct options_table_entry *oe, struct options *oo,
const char *value)
{ {
const char **choicep; const char **choicep;
int n, choice = -1; int n, choice = -1;
@ -429,13 +432,13 @@ cmd_set_option_choice(unused struct cmd *self, struct cmd_ctx *ctx,
continue; continue;
if (choice != -1) { if (choice != -1) {
ctx->error(ctx, "ambiguous value: %s", value); cmdq_error(cmdq, "ambiguous value: %s", value);
return (NULL); return (NULL);
} }
choice = n - 1; choice = n - 1;
} }
if (choice == -1) { if (choice == -1) {
ctx->error(ctx, "unknown value: %s", value); cmdq_error(cmdq, "unknown value: %s", value);
return (NULL); return (NULL);
} }

View File

@ -27,7 +27,7 @@
* Show environment. * 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 = { const struct cmd_entry cmd_show_environment_entry = {
"show-environment", "showenv", "show-environment", "showenv",
@ -40,7 +40,7 @@ const struct cmd_entry cmd_show_environment_entry = {
}; };
enum cmd_retval 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 args *args = self->args;
struct session *s; struct session *s;
@ -50,7 +50,7 @@ cmd_show_environment_exec(struct cmd *self, struct cmd_ctx *ctx)
if (args_has(self->args, 'g')) if (args_has(self->args, 'g'))
env = &global_environ; env = &global_environ;
else { 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); return (CMD_RETURN_ERROR);
env = &s->environ; env = &s->environ;
} }
@ -58,21 +58,21 @@ cmd_show_environment_exec(struct cmd *self, struct cmd_ctx *ctx)
if (args->argc != 0) { if (args->argc != 0) {
envent = environ_find(env, args->argv[0]); envent = environ_find(env, args->argv[0]);
if (envent == NULL) { 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); return (CMD_RETURN_ERROR);
} }
if (envent->value != NULL) if (envent->value != NULL)
ctx->print(ctx, "%s=%s", envent->name, envent->value); cmdq_print(cmdq, "%s=%s", envent->name, envent->value);
else else
ctx->print(ctx, "-%s", envent->name); cmdq_print(cmdq, "-%s", envent->name);
return (CMD_RETURN_NORMAL); return (CMD_RETURN_NORMAL);
} }
RB_FOREACH(envent, environ, env) { RB_FOREACH(envent, environ, env) {
if (envent->value != NULL) if (envent->value != NULL)
ctx->print(ctx, "%s=%s", envent->name, envent->value); cmdq_print(cmdq, "%s=%s", envent->name, envent->value);
else else
ctx->print(ctx, "-%s", envent->name); cmdq_print(cmdq, "-%s", envent->name);
} }
return (CMD_RETURN_NORMAL); return (CMD_RETURN_NORMAL);

View File

@ -27,7 +27,7 @@
* Show client message log. * 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 = { const struct cmd_entry cmd_show_messages_entry = {
"show-messages", "showmsgs", "show-messages", "showmsgs",
@ -40,7 +40,7 @@ const struct cmd_entry cmd_show_messages_entry = {
}; };
enum cmd_retval 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 args *args = self->args;
struct client *c; struct client *c;
@ -48,7 +48,7 @@ cmd_show_messages_exec(struct cmd *self, struct cmd_ctx *ctx)
char *tim; char *tim;
u_int i; 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); return (CMD_RETURN_ERROR);
for (i = 0; i < ARRAY_LENGTH(&c->message_log); i++) { 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); tim = ctime(&msg->msg_time);
*strchr(tim, '\n') = '\0'; *strchr(tim, '\n') = '\0';
ctx->print(ctx, "%s %s", tim, msg->msg); cmdq_print(cmdq, "%s %s", tim, msg->msg);
} }
return (CMD_RETURN_NORMAL); return (CMD_RETURN_NORMAL);

View File

@ -27,11 +27,11 @@
* Show options. * 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 *); 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 options_table_entry *, struct options *);
const struct cmd_entry cmd_show_options_entry = { const struct cmd_entry cmd_show_options_entry = {
@ -55,7 +55,7 @@ const struct cmd_entry cmd_show_window_options_entry = {
}; };
enum cmd_retval 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 args *args = self->args;
struct session *s; struct session *s;
@ -72,7 +72,7 @@ cmd_show_options_exec(struct cmd *self, struct cmd_ctx *ctx)
if (args_has(self->args, 'g')) if (args_has(self->args, 'g'))
oo = &global_w_options; oo = &global_w_options;
else { else {
wl = cmd_find_window(ctx, args_get(args, 't'), NULL); wl = cmd_find_window(cmdq, args_get(args, 't'), NULL);
if (wl == NULL) if (wl == NULL)
return (CMD_RETURN_ERROR); return (CMD_RETURN_ERROR);
oo = &wl->window->options; 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')) if (args_has(self->args, 'g'))
oo = &global_s_options; oo = &global_s_options;
else { else {
s = cmd_find_session(ctx, args_get(args, 't'), 0); s = cmd_find_session(cmdq, args_get(args, 't'), 0);
if (s == NULL) if (s == NULL)
return (CMD_RETURN_ERROR); return (CMD_RETURN_ERROR);
oo = &s->options; oo = &s->options;
@ -90,13 +90,13 @@ cmd_show_options_exec(struct cmd *self, struct cmd_ctx *ctx)
} }
if (args->argc != 0) if (args->argc != 0)
return (cmd_show_options_one(self, ctx, oo)); return (cmd_show_options_one(self, cmdq, oo));
else else
return (cmd_show_options_all(self, ctx, table, oo)); return (cmd_show_options_all(self, cmdq, table, oo));
} }
enum cmd_retval 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 options *oo)
{ {
struct args *args = self->args; 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 (*args->argv[0] == '@') {
if ((o = options_find1(oo, args->argv[0])) == NULL) { 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); return (CMD_RETURN_ERROR);
} }
if (args_has(self->args, 'v')) if (args_has(self->args, 'v'))
ctx->print(ctx, "%s", o->str); cmdq_print(cmdq, "%s", o->str);
else else
ctx->print(ctx, "%s \"%s\"", o->name, o->str); cmdq_print(cmdq, "%s \"%s\"", o->name, o->str);
return (CMD_RETURN_NORMAL); return (CMD_RETURN_NORMAL);
} }
table = oe = NULL; table = oe = NULL;
if (options_table_find(args->argv[0], &table, &oe) != 0) { 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); return (CMD_RETURN_ERROR);
} }
if (oe == NULL) { 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); return (CMD_RETURN_ERROR);
} }
if ((o = options_find1(oo, oe->name)) == NULL) if ((o = options_find1(oo, oe->name)) == NULL)
return (CMD_RETURN_NORMAL); return (CMD_RETURN_NORMAL);
optval = options_table_print_entry(oe, o, args_has(self->args, 'v')); optval = options_table_print_entry(oe, o, args_has(self->args, 'v'));
if (args_has(self->args, 'v')) if (args_has(self->args, 'v'))
ctx->print(ctx, "%s", optval); cmdq_print(cmdq, "%s", optval);
else else
ctx->print(ctx, "%s %s", oe->name, optval); cmdq_print(cmdq, "%s %s", oe->name, optval);
return (CMD_RETURN_NORMAL); return (CMD_RETURN_NORMAL);
} }
enum cmd_retval 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 *table, struct options *oo)
{ {
const struct options_table_entry *oe; 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) { RB_FOREACH(o, options_tree, &oo->tree) {
if (*o->name == '@') { if (*o->name == '@') {
if (args_has(self->args, 'v')) if (args_has(self->args, 'v'))
ctx->print(ctx, "%s", o->str); cmdq_print(cmdq, "%s", o->str);
else 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, optval = options_table_print_entry(oe, o,
args_has(self->args, 'v')); args_has(self->args, 'v'));
if (args_has(self->args, 'v')) if (args_has(self->args, 'v'))
ctx->print(ctx, "%s", optval); cmdq_print(cmdq, "%s", optval);
else else
ctx->print(ctx, "%s %s", oe->name, optval); cmdq_print(cmdq, "%s %s", oe->name, optval);
} }
return (CMD_RETURN_NORMAL); return (CMD_RETURN_NORMAL);

View File

@ -26,7 +26,10 @@
* Sources a configuration file. * 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 = { const struct cmd_entry cmd_source_file_entry = {
"source-file", "source", "source-file", "source",
@ -39,35 +42,66 @@ const struct cmd_entry cmd_source_file_entry = {
}; };
enum cmd_retval 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; struct args *args = self->args;
int retval; struct cmd_q *cmdq1;
char *cause;
cmdq1 = cmdq_new(NULL);
cmdq1->emptyfn = cmd_source_file_done;
cmdq1->data = cmdq;
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; u_int i;
char *cause; char *cause;
retval = load_cfg(args->argv[0], ctx, &cfg_causes);
/*
* 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);
/*
* 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++) { for (i = 0; i < ARRAY_LENGTH(&cfg_causes); i++) {
cause = ARRAY_ITEM(&cfg_causes, i); cause = ARRAY_ITEM(&cfg_causes, i);
ctx->print(ctx, "%s", cause); cmdq_print(cmdq, "%s", cause);
free(cause); free(cause);
} }
ARRAY_FREE(&cfg_causes); 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);
} }

View File

@ -28,7 +28,7 @@
*/ */
void cmd_split_window_key_binding(struct cmd *, int); 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 = { const struct cmd_entry cmd_split_window_entry = {
"split-window", "splitw", "split-window", "splitw",
@ -50,7 +50,7 @@ cmd_split_window_key_binding(struct cmd *self, int key)
} }
enum cmd_retval 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 args *args = self->args;
struct session *s; struct session *s;
@ -69,7 +69,7 @@ cmd_split_window_exec(struct cmd *self, struct cmd_ctx *ctx)
struct format_tree *ft; struct format_tree *ft;
char *cp; 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); return (CMD_RETURN_ERROR);
w = wl->window; w = wl->window;
@ -82,7 +82,7 @@ cmd_split_window_exec(struct cmd *self, struct cmd_ctx *ctx)
cmd = options_get_string(&s->options, "default-command"); cmd = options_get_string(&s->options, "default-command");
else else
cmd = args->argv[0]; 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; type = LAYOUT_TOPBOTTOM;
if (args_has(args, 'h')) if (args_has(args, 'h'))
@ -151,14 +151,14 @@ cmd_split_window_exec(struct cmd *self, struct cmd_ctx *ctx)
template = SPLIT_WINDOW_TEMPLATE; template = SPLIT_WINDOW_TEMPLATE;
ft = format_create(); 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_client(ft, c);
format_session(ft, s); format_session(ft, s);
format_winlink(ft, s, wl); format_winlink(ft, s, wl);
format_window_pane(ft, new_wp); format_window_pane(ft, new_wp);
cp = format_expand(ft, template); cp = format_expand(ft, template);
ctx->print(ctx, "%s", cp); cmdq_print(cmdq, "%s", cp);
free(cp); free(cp);
format_free(ft); format_free(ft);
@ -170,7 +170,7 @@ error:
environ_free(&env); environ_free(&env);
if (new_wp != NULL) if (new_wp != NULL)
window_remove_pane(w, new_wp); window_remove_pane(w, new_wp);
ctx->error(ctx, "create pane failed: %s", cause); cmdq_error(cmdq, "create pane failed: %s", cause);
free(cause); free(cause);
return (CMD_RETURN_ERROR); return (CMD_RETURN_ERROR);
} }

View File

@ -24,7 +24,7 @@
* Start the server and do nothing else. * 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 = { const struct cmd_entry cmd_start_server_entry = {
"start-server", "start", "start-server", "start",
@ -37,7 +37,7 @@ const struct cmd_entry cmd_start_server_entry = {
}; };
enum cmd_retval 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); return (CMD_RETURN_NORMAL);
} }

View File

@ -59,7 +59,8 @@ cmd_string_ungetc(size_t *p)
* string, or NULL for empty command. * string, or NULL for empty command.
*/ */
int 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; size_t p;
int ch, i, argc, rval; int ch, i, argc, rval;
@ -131,7 +132,7 @@ cmd_string_parse(const char *s, struct cmd_list **cmdlist, char **cause)
if (argc == 0) if (argc == 0)
goto out; goto out;
*cmdlist = cmd_list_parse(argc, argv, cause); *cmdlist = cmd_list_parse(argc, argv, file, line, cause);
if (*cmdlist == NULL) if (*cmdlist == NULL)
goto out; goto out;

View File

@ -27,7 +27,7 @@
* Suspend client with SIGTSTP. * 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 = { const struct cmd_entry cmd_suspend_client_entry = {
"suspend-client", "suspendc", "suspend-client", "suspendc",
@ -40,12 +40,12 @@ const struct cmd_entry cmd_suspend_client_entry = {
}; };
enum cmd_retval 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 args *args = self->args;
struct client *c; 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); return (CMD_RETURN_ERROR);
tty_stop_tty(&c->tty); tty_stop_tty(&c->tty);

View File

@ -27,7 +27,7 @@
*/ */
void cmd_swap_pane_key_binding(struct cmd *, int); 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 = { const struct cmd_entry cmd_swap_pane_entry = {
"swap-pane", "swapp", "swap-pane", "swapp",
@ -50,7 +50,7 @@ cmd_swap_pane_key_binding(struct cmd *self, int key)
} }
enum cmd_retval 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 args *args = self->args;
struct winlink *src_wl, *dst_wl; 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; struct layout_cell *src_lc, *dst_lc;
u_int sx, sy, xoff, yoff; 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) if (dst_wl == NULL)
return (CMD_RETURN_ERROR); return (CMD_RETURN_ERROR);
dst_w = dst_wl->window; dst_w = dst_wl->window;
@ -77,7 +77,7 @@ cmd_swap_pane_exec(struct cmd *self, struct cmd_ctx *ctx)
} else } else
return (CMD_RETURN_NORMAL); return (CMD_RETURN_NORMAL);
} else { } 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) if (src_wl == NULL)
return (CMD_RETURN_ERROR); return (CMD_RETURN_ERROR);
src_w = src_wl->window; src_w = src_wl->window;

View File

@ -26,7 +26,7 @@
* Swap one window with another. * 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 = { const struct cmd_entry cmd_swap_window_entry = {
"swap-window", "swapw", "swap-window", "swapw",
@ -39,7 +39,7 @@ const struct cmd_entry cmd_swap_window_entry = {
}; };
enum cmd_retval 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; struct args *args = self->args;
const char *target_src, *target_dst; const char *target_src, *target_dst;
@ -49,17 +49,17 @@ cmd_swap_window_exec(struct cmd *self, struct cmd_ctx *ctx)
struct window *w; struct window *w;
target_src = args_get(args, 's'); 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); return (CMD_RETURN_ERROR);
target_dst = args_get(args, 't'); 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); return (CMD_RETURN_ERROR);
sg_src = session_group_find(src); sg_src = session_group_find(src);
sg_dst = session_group_find(dst); sg_dst = session_group_find(dst);
if (src != dst && if (src != dst &&
sg_src != NULL && sg_dst != NULL && sg_src == sg_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); return (CMD_RETURN_ERROR);
} }

View File

@ -28,7 +28,7 @@
*/ */
void cmd_switch_client_key_binding(struct cmd *, int); 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 = { const struct cmd_entry cmd_switch_client_entry = {
"switch-client", "switchc", "switch-client", "switchc",
@ -58,45 +58,45 @@ cmd_switch_client_key_binding(struct cmd *self, int key)
} }
enum cmd_retval 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 args *args = self->args;
struct client *c; struct client *c;
struct session *s; 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); return (CMD_RETURN_ERROR);
if (args_has(args, 'r')) { if (args_has(args, 'r')) {
if (c->flags & CLIENT_READONLY) { if (c->flags & CLIENT_READONLY) {
c->flags &= ~CLIENT_READONLY; c->flags &= ~CLIENT_READONLY;
ctx->info(ctx, "made client writable"); cmdq_info(cmdq, "made client writable");
} else { } else {
c->flags |= CLIENT_READONLY; c->flags |= CLIENT_READONLY;
ctx->info(ctx, "made client read-only"); cmdq_info(cmdq, "made client read-only");
} }
} }
s = NULL; s = NULL;
if (args_has(args, 'n')) { if (args_has(args, 'n')) {
if ((s = session_next_session(c->session)) == NULL) { 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); return (CMD_RETURN_ERROR);
} }
} else if (args_has(args, 'p')) { } else if (args_has(args, 'p')) {
if ((s = session_previous_session(c->session)) == NULL) { 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); return (CMD_RETURN_ERROR);
} }
} else if (args_has(args, 'l')) { } else if (args_has(args, 'l')) {
if (c->last_session != NULL && session_alive(c->last_session)) if (c->last_session != NULL && session_alive(c->last_session))
s = c->last_session; s = c->last_session;
if (s == NULL) { if (s == NULL) {
ctx->error(ctx, "can't find last session"); cmdq_error(cmdq, "can't find last session");
return (CMD_RETURN_ERROR); return (CMD_RETURN_ERROR);
} }
} else } else
s = cmd_find_session(ctx, args_get(args, 't'), 0); s = cmd_find_session(cmdq, args_get(args, 't'), 0);
if (s == NULL) if (s == NULL)
return (CMD_RETURN_ERROR); return (CMD_RETURN_ERROR);

View File

@ -27,8 +27,8 @@
*/ */
enum cmd_retval cmd_unbind_key_check(struct args *); 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_exec(struct cmd *, struct cmd_q *);
enum cmd_retval cmd_unbind_key_table(struct cmd *, struct cmd_ctx *, int); enum cmd_retval cmd_unbind_key_table(struct cmd *, struct cmd_q *, int);
const struct cmd_entry cmd_unbind_key_entry = { const struct cmd_entry cmd_unbind_key_entry = {
"unbind-key", "unbind", "unbind-key", "unbind",
@ -51,7 +51,7 @@ cmd_unbind_key_check(struct args *args)
} }
enum cmd_retval 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 args *args = self->args;
struct key_binding *bd; 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')) { if (!args_has(args, 'a')) {
key = key_string_lookup_string(args->argv[0]); key = key_string_lookup_string(args->argv[0]);
if (key == KEYC_NONE) { 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); return (CMD_RETURN_ERROR);
} }
} else } else
key = KEYC_NONE; key = KEYC_NONE;
if (args_has(args, 't')) 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) { if (key == KEYC_NONE) {
while (!RB_EMPTY(&key_bindings)) { while (!RB_EMPTY(&key_bindings)) {
@ -84,7 +84,7 @@ cmd_unbind_key_exec(struct cmd *self, unused struct cmd_ctx *ctx)
} }
enum cmd_retval 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; struct args *args = self->args;
const char *tablename; 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'); tablename = args_get(args, 't');
if ((mtab = mode_key_findtable(tablename)) == NULL) { 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); return (CMD_RETURN_ERROR);
} }

View File

@ -24,7 +24,7 @@
* Unlink a window, unless it would be destroyed by doing so (only one link). * 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 = { const struct cmd_entry cmd_unlink_window_entry = {
"unlink-window", "unlinkw", "unlink-window", "unlinkw",
@ -37,7 +37,7 @@ const struct cmd_entry cmd_unlink_window_entry = {
}; };
enum cmd_retval 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 args *args = self->args;
struct winlink *wl; struct winlink *wl;
@ -46,7 +46,7 @@ cmd_unlink_window_exec(struct cmd *self, struct cmd_ctx *ctx)
struct session_group *sg; struct session_group *sg;
u_int references; 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); return (CMD_RETURN_ERROR);
w = wl->window; w = wl->window;
@ -59,7 +59,7 @@ cmd_unlink_window_exec(struct cmd *self, struct cmd_ctx *ctx)
references = 1; references = 1;
if (!args_has(self->args, 'k') && w->references == references) { 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); return (CMD_RETURN_ERROR);
} }

156
cmd.c
View File

@ -126,48 +126,12 @@ int cmd_lookup_index(struct session *, const char *, int *);
struct window_pane *cmd_lookup_paneid(const char *); struct window_pane *cmd_lookup_paneid(const char *);
struct winlink *cmd_lookup_winlink_windowid(struct session *, const char *); struct winlink *cmd_lookup_winlink_windowid(struct session *, const char *);
struct window *cmd_lookup_windowid(const char *); struct window *cmd_lookup_windowid(const char *);
struct session *cmd_window_session(struct cmd_ctx *, struct session *cmd_window_session(struct cmd_q *, struct window *,
struct window *, struct winlink **); struct winlink **);
struct winlink *cmd_find_window_offset(const char *, struct session *, int *); struct winlink *cmd_find_window_offset(const char *, struct session *, int *);
int cmd_find_index_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 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 int
cmd_pack_argv(int argc, char **argv, char *buf, size_t len) cmd_pack_argv(int argc, char **argv, char *buf, size_t len)
{ {
@ -241,7 +205,7 @@ cmd_free_argv(int argc, char **argv)
} }
struct cmd * 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; const struct cmd_entry **entryp, *entry;
struct cmd *cmd; struct cmd *cmd;
@ -291,9 +255,14 @@ cmd_parse(int argc, char **argv, char **cause)
if (entry->check != NULL && entry->check(args) != 0) if (entry->check != NULL && entry->check(args) != 0)
goto usage; goto usage;
cmd = xmalloc(sizeof *cmd); cmd = xcalloc(1, sizeof *cmd);
cmd->entry = entry; cmd->entry = entry;
cmd->args = args; cmd->args = args;
if (file != NULL)
cmd->file = xstrdup(file);
cmd->line = line;
return (cmd); return (cmd);
ambiguous: ambiguous:
@ -342,31 +311,33 @@ cmd_print(struct cmd *cmd, char *buf, size_t len)
* session from all sessions. * session from all sessions.
*/ */
struct session * 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 msg_command_data *data = cmdq->msgdata;
struct client *c = ctx->cmdclient; struct client *c = cmdq->client;
struct session *s; struct session *s;
struct sessionslist ss; struct sessionslist ss;
struct winlink *wl; struct winlink *wl;
struct window_pane *wp; struct window_pane *wp;
const char *path;
int found; int found;
if (ctx->curclient != NULL && ctx->curclient->session != NULL) if (c != NULL && c->session != NULL)
return (ctx->curclient->session); return (c->session);
/* /*
* If the name of the calling client's pty is know, build a list of the * 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 * sessions that contain it and if any choose either the first or the
* newest. * newest.
*/ */
if (c != NULL && c->tty.path != NULL) { path = c == NULL ? NULL : c->tty.path;
if (path != NULL) {
ARRAY_INIT(&ss); ARRAY_INIT(&ss);
RB_FOREACH(s, sessions, &sessions) { RB_FOREACH(s, sessions, &sessions) {
found = 0; found = 0;
RB_FOREACH(wl, winlinks, &s->windows) { RB_FOREACH(wl, winlinks, &s->windows) {
TAILQ_FOREACH(wp, &wl->window->panes, entry) { TAILQ_FOREACH(wp, &wl->window->panes, entry) {
if (strcmp(wp->tty, c->tty.path) == 0) { if (strcmp(wp->tty, path) == 0) {
found = 1; found = 1;
break; break;
} }
@ -457,21 +428,21 @@ cmd_choose_session_list(struct sessionslist *ss)
* then of all clients. * then of all clients.
*/ */
struct client * struct client *
cmd_current_client(struct cmd_ctx *ctx) cmd_current_client(struct cmd_q *cmdq)
{ {
struct session *s; struct session *s;
struct client *c; struct client *c;
struct clients cc; struct clients cc;
u_int i; u_int i;
if (ctx->curclient != NULL) if (cmdq->client != NULL && cmdq->client->session != NULL)
return (ctx->curclient); return (cmdq->client);
/* /*
* No current client set. Find the current session and return the * No current client set. Find the current session and return the
* newest of its clients. * newest of its clients.
*/ */
s = cmd_current_session(ctx, 0); s = cmd_current_session(cmdq, 0);
if (s != NULL && !(s->flags & SESSION_UNATTACHED)) { if (s != NULL && !(s->flags & SESSION_UNATTACHED)) {
ARRAY_INIT(&cc); ARRAY_INIT(&cc);
for (i = 0; i < ARRAY_LENGTH(&clients); i++) { for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
@ -516,7 +487,7 @@ cmd_choose_client(struct clients *cc)
/* Find the target client or report an error and return NULL. */ /* Find the target client or report an error and return NULL. */
struct client * 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; struct client *c;
char *tmparg; char *tmparg;
@ -524,9 +495,9 @@ cmd_find_client(struct cmd_ctx *ctx, const char *arg, int quiet)
/* A NULL argument means the current client. */ /* A NULL argument means the current client. */
if (arg == NULL) { if (arg == NULL) {
c = cmd_current_client(ctx); c = cmd_current_client(cmdq);
if (c == NULL && !quiet) if (c == NULL && !quiet)
ctx->error(ctx, "no clients"); cmdq_error(cmdq, "no clients");
return (c); return (c);
} }
tmparg = xstrdup(arg); tmparg = xstrdup(arg);
@ -541,7 +512,7 @@ cmd_find_client(struct cmd_ctx *ctx, const char *arg, int quiet)
/* If no client found, report an error. */ /* If no client found, report an error. */
if (c == NULL && !quiet) if (c == NULL && !quiet)
ctx->error(ctx, "client not found: %s", tmparg); cmdq_error(cmdq, "client not found: %s", tmparg);
free(tmparg); free(tmparg);
return (c); return (c);
@ -743,14 +714,14 @@ cmd_lookup_windowid(const char *arg)
/* Find session and winlink for window. */ /* Find session and winlink for window. */
struct session * 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 session *s;
struct sessionslist ss; struct sessionslist ss;
struct winlink *wl; struct winlink *wl;
/* If this window is in the current session, return that winlink. */ /* 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) { if (s != NULL) {
wl = winlink_find_by_window(&s->windows, w); wl = winlink_find_by_window(&s->windows, w);
if (wl != NULL) { if (wl != NULL) {
@ -775,7 +746,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. */ /* Find the target session or report an error and return NULL. */
struct session * 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 session *s;
struct window_pane *wp; struct window_pane *wp;
@ -787,13 +758,13 @@ cmd_find_session(struct cmd_ctx *ctx, const char *arg, int prefer_unattached)
/* A NULL argument means the current session. */ /* A NULL argument means the current session. */
if (arg == NULL) if (arg == NULL)
return (cmd_current_session(ctx, prefer_unattached)); return (cmd_current_session(cmdq, prefer_unattached));
/* Lookup as pane id or window id. */ /* Lookup as pane id or window id. */
if ((wp = cmd_lookup_paneid(arg)) != NULL) 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) 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. */ /* Trim a single trailing colon if any. */
tmparg = xstrdup(arg); tmparg = xstrdup(arg);
@ -804,7 +775,7 @@ cmd_find_session(struct cmd_ctx *ctx, const char *arg, int prefer_unattached)
/* An empty session name is the current session. */ /* An empty session name is the current session. */
if (*tmparg == '\0') { if (*tmparg == '\0') {
free(tmparg); free(tmparg);
return (cmd_current_session(ctx, prefer_unattached)); return (cmd_current_session(cmdq, prefer_unattached));
} }
/* Find the session, if any. */ /* Find the session, if any. */
@ -817,9 +788,9 @@ cmd_find_session(struct cmd_ctx *ctx, const char *arg, int prefer_unattached)
/* If no session found, report an error. */ /* If no session found, report an error. */
if (s == NULL) { if (s == NULL) {
if (ambiguous) if (ambiguous)
ctx->error(ctx, "more than one session: %s", tmparg); cmdq_error(cmdq, "more than one session: %s", tmparg);
else else
ctx->error(ctx, "session not found: %s", tmparg); cmdq_error(cmdq, "session not found: %s", tmparg);
} }
free(tmparg); free(tmparg);
@ -828,7 +799,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. */ /* Find the target session and window or report an error and return NULL. */
struct winlink * 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 session *s;
struct winlink *wl; struct winlink *wl;
@ -841,8 +812,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 * Find the current session. There must always be a current session, if
* it can't be found, report an error. * it can't be found, report an error.
*/ */
if ((s = cmd_current_session(ctx, 0)) == NULL) { if ((s = cmd_current_session(cmdq, 0)) == NULL) {
ctx->error(ctx, "can't establish current session"); cmdq_error(cmdq, "can't establish current session");
return (NULL); return (NULL);
} }
@ -855,7 +826,7 @@ cmd_find_window(struct cmd_ctx *ctx, const char *arg, struct session **sp)
/* Lookup as pane id. */ /* Lookup as pane id. */
if ((wp = cmd_lookup_paneid(arg)) != NULL) { 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) if (sp != NULL)
*sp = s; *sp = s;
return (wl); return (wl);
@ -936,17 +907,17 @@ lookup_session:
no_session: no_session:
if (ambiguous) if (ambiguous)
ctx->error(ctx, "multiple sessions: %s", arg); cmdq_error(cmdq, "multiple sessions: %s", arg);
else else
ctx->error(ctx, "session not found: %s", arg); cmdq_error(cmdq, "session not found: %s", arg);
free(sessptr); free(sessptr);
return (NULL); return (NULL);
not_found: not_found:
if (ambiguous) if (ambiguous)
ctx->error(ctx, "multiple windows: %s", arg); cmdq_error(cmdq, "multiple windows: %s", arg);
else else
ctx->error(ctx, "window not found: %s", arg); cmdq_error(cmdq, "window not found: %s", arg);
free(sessptr); free(sessptr);
return (NULL); return (NULL);
} }
@ -978,7 +949,7 @@ cmd_find_window_offset(const char *winptr, struct session *s, int *ambiguous)
* example if it is going to be created). * example if it is going to be created).
*/ */
int 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 session *s;
struct winlink *wl; struct winlink *wl;
@ -990,8 +961,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 * Find the current session. There must always be a current session, if
* it can't be found, report an error. * it can't be found, report an error.
*/ */
if ((s = cmd_current_session(ctx, 0)) == NULL) { if ((s = cmd_current_session(cmdq, 0)) == NULL) {
ctx->error(ctx, "can't establish current session"); cmdq_error(cmdq, "can't establish current session");
return (-2); return (-2);
} }
@ -1074,25 +1045,25 @@ lookup_session:
no_session: no_session:
if (ambiguous) if (ambiguous)
ctx->error(ctx, "multiple sessions: %s", arg); cmdq_error(cmdq, "multiple sessions: %s", arg);
else else
ctx->error(ctx, "session not found: %s", arg); cmdq_error(cmdq, "session not found: %s", arg);
free(sessptr); free(sessptr);
return (-2); return (-2);
invalid_index: invalid_index:
if (ambiguous) if (ambiguous)
goto not_found; goto not_found;
ctx->error(ctx, "invalid index: %s", arg); cmdq_error(cmdq, "invalid index: %s", arg);
free(sessptr); free(sessptr);
return (-2); return (-2);
not_found: not_found:
if (ambiguous) if (ambiguous)
ctx->error(ctx, "multiple windows: %s", arg); cmdq_error(cmdq, "multiple windows: %s", arg);
else else
ctx->error(ctx, "window not found: %s", arg); cmdq_error(cmdq, "window not found: %s", arg);
free(sessptr); free(sessptr);
return (-2); return (-2);
} }
@ -1129,7 +1100,7 @@ cmd_find_index_offset(const char *winptr, struct session *s, int *ambiguous)
* such as mysession:mywindow.0. * such as mysession:mywindow.0.
*/ */
struct winlink * 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) const char *arg, struct session **sp, struct window_pane **wpp)
{ {
struct session *s; struct session *s;
@ -1139,8 +1110,8 @@ cmd_find_pane(struct cmd_ctx *ctx,
u_int idx; u_int idx;
/* Get the current session. */ /* Get the current session. */
if ((s = cmd_current_session(ctx, 0)) == NULL) { if ((s = cmd_current_session(cmdq, 0)) == NULL) {
ctx->error(ctx, "can't establish current session"); cmdq_error(cmdq, "can't establish current session");
return (NULL); return (NULL);
} }
if (sp != NULL) if (sp != NULL)
@ -1154,7 +1125,7 @@ cmd_find_pane(struct cmd_ctx *ctx,
/* Lookup as pane id. */ /* Lookup as pane id. */
if ((*wpp = cmd_lookup_paneid(arg)) != NULL) { 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) if (sp != NULL)
*sp = s; *sp = s;
return (wl); return (wl);
@ -1169,7 +1140,7 @@ cmd_find_pane(struct cmd_ctx *ctx,
winptr[period - arg] = '\0'; winptr[period - arg] = '\0';
if (*winptr == '\0') if (*winptr == '\0')
wl = s->curw; 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; goto error;
/* Find the pane section and look it up. */ /* Find the pane section and look it up. */
@ -1193,7 +1164,7 @@ cmd_find_pane(struct cmd_ctx *ctx,
lookup_string: lookup_string:
/* Try pane string description. */ /* Try pane string description. */
if ((*wpp = window_find_string(wl->window, paneptr)) == NULL) { 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; goto error;
} }
@ -1218,7 +1189,7 @@ lookup_window:
return (s->curw); return (s->curw);
/* Try as a window and use the active pane. */ /* 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; *wpp = wl->window->active;
return (wl); return (wl);
@ -1296,8 +1267,9 @@ cmd_template_replace(const char *template, const char *s, int idx)
* directory. * directory.
*/ */
const char * 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 session *s;
struct environ_entry *envent; struct environ_entry *envent;
const char *root; const char *root;
@ -1307,7 +1279,7 @@ cmd_get_default_path(struct cmd_ctx *ctx, const char *cwd)
size_t skip; size_t skip;
static char path[MAXPATHLEN]; static char path[MAXPATHLEN];
if ((s = cmd_current_session(ctx, 0)) == NULL) if ((s = cmd_current_session(cmdq, 0)) == NULL)
return (NULL); return (NULL);
if (cwd == NULL) if (cwd == NULL)
@ -1337,9 +1309,9 @@ cmd_get_default_path(struct cmd_ctx *ctx, const char *cwd)
return (cwd); return (cwd);
} else { } else {
/* Empty or relative path. */ /* Empty or relative path. */
if (ctx->cmdclient != NULL && ctx->cmdclient->cwd != NULL) if (c != NULL && c->session == NULL && c->cwd != NULL)
root = ctx->cmdclient->cwd; root = c->cwd;
else if (ctx->curclient != NULL && s->curw != NULL) else if (s->curw != NULL)
root = osdep_get_cwd(s->curw->window->active->fd); root = osdep_get_cwd(s->curw->window->active->fd);
else else
return (s->cwd); return (s->cwd);

View File

@ -25,46 +25,6 @@
#include "tmux.h" #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. */ /* Write a line. */
void printflike2 void printflike2
control_write(struct client *c, const char *fmt, ...) control_write(struct client *c, const char *fmt, ...)
@ -93,7 +53,6 @@ void
control_callback(struct client *c, int closed, unused void *data) control_callback(struct client *c, int closed, unused void *data)
{ {
char *line, *cause; char *line, *cause;
struct cmd_ctx *ctx;
struct cmd_list *cmdlist; struct cmd_list *cmdlist;
if (closed) if (closed)
@ -108,20 +67,14 @@ control_callback(struct client *c, int closed, unused void *data)
break; break;
} }
ctx = cmd_get_ctx(NULL, c); if (cmd_string_parse(line, &cmdlist, NULL, 0, &cause) != 0) {
ctx->error = control_msg_error;
ctx->print = control_msg_print;
ctx->info = control_msg_info;
if (cmd_string_parse(line, &cmdlist, &cause) != 0) {
control_write(c, "%%error in line \"%s\": %s", line, control_write(c, "%%error in line \"%s\": %s", line,
cause); cause);
free(cause); free(cause);
} else { } else {
cmd_list_exec(cmdlist, ctx); cmdq_run(c->cmdq, cmdlist);
cmd_list_free(cmdlist); cmd_list_free(cmdlist);
} }
cmd_free_ctx(ctx);
free(line); free(line);
} }

View File

@ -397,10 +397,8 @@ format_window_pane(struct format_tree *ft, struct window_pane *wp)
struct grid *gd = wp->base.grid; struct grid *gd = wp->base.grid;
struct grid_line *gl; struct grid_line *gl;
unsigned long long size; unsigned long long size;
u_int i; u_int i, idx;
u_int idx; const char *cwd, *cmd;
const char *cwd;
const char *cmd;
size = 0; size = 0;
for (i = 0; i < gd->hsize; i++) { for (i = 0; i < gd->hsize; i++) {

View File

@ -182,11 +182,11 @@ key_bindings_init(void)
RB_INIT(&key_bindings); RB_INIT(&key_bindings);
for (i = 0; i < nitems(table); i++) { for (i = 0; i < nitems(table); i++) {
cmdlist = xmalloc(sizeof *cmdlist); cmdlist = xcalloc(1, sizeof *cmdlist);
TAILQ_INIT(&cmdlist->list);
cmdlist->references = 1; cmdlist->references = 1;
TAILQ_INIT(&cmdlist->list);
cmd = xmalloc(sizeof *cmd); cmd = xcalloc(1, sizeof *cmd);
cmd->entry = table[i].entry; cmd->entry = table[i].entry;
if (cmd->entry->key_binding != NULL) if (cmd->entry->key_binding != NULL)
cmd->entry->key_binding(cmd, table[i].key); 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 void
key_bindings_dispatch(struct key_binding *bd, struct client *c) key_bindings_dispatch(struct key_binding *bd, struct client *c)
{ {
struct cmd_ctx *ctx;
struct cmd *cmd; struct cmd *cmd;
int readonly; 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; readonly = 1;
TAILQ_FOREACH(cmd, &bd->cmdlist->list, qentry) { TAILQ_FOREACH(cmd, &bd->cmdlist->list, qentry) {
if (!(cmd->entry->flags & CMD_READONLY)) if (!(cmd->entry->flags & CMD_READONLY))
readonly = 0; readonly = 0;
} }
if (!readonly && c->flags & CLIENT_READONLY) { if (!readonly && (c->flags & CLIENT_READONLY)) {
key_bindings_info(ctx, "client is read-only"); cmdq_info(c->cmdq, "client is read-only");
return; return;
} }
cmd_list_exec(bd->cmdlist, ctx); cmdq_run(c->cmdq, bd->cmdlist);
cmd_free_ctx(ctx);
} }

View File

@ -44,10 +44,6 @@ void server_client_msg_identify(
struct client *, struct msg_identify_data *, int); struct client *, struct msg_identify_data *, int);
void server_client_msg_shell(struct client *); 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. */ /* Create a new client. */
void void
server_client_create(int fd) server_client_create(int fd)
@ -66,6 +62,9 @@ server_client_create(int fd)
fatal("gettimeofday failed"); fatal("gettimeofday failed");
memcpy(&c->activity_time, &c->creation_time, sizeof c->activity_time); 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->stdin_data = evbuffer_new ();
c->stdout_data = evbuffer_new (); c->stdout_data = evbuffer_new ();
c->stderr_data = evbuffer_new (); c->stderr_data = evbuffer_new ();
@ -180,6 +179,10 @@ server_client_lost(struct client *c)
free(c->prompt_buffer); free(c->prompt_buffer);
free(c->cwd); free(c->cwd);
c->cmdq->dead = 1;
cmdq_free(c->cmdq);
c->cmdq = NULL;
environ_free(&c->environ); environ_free(&c->environ);
close(c->ibuf.fd); close(c->ibuf.fd);
@ -900,71 +903,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. */ /* Handle command message. */
void void
server_client_msg_command(struct client *c, struct msg_command_data *data) server_client_msg_command(struct client *c, struct msg_command_data *data)
{ {
struct cmd_ctx *ctx;
struct cmd_list *cmdlist = NULL; struct cmd_list *cmdlist = NULL;
int argc; int argc;
char **argv, *cause; 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; argc = data->argc;
data->argv[(sizeof data->argv) - 1] = '\0'; data->argv[(sizeof data->argv) - 1] = '\0';
if (cmd_unpack_argv(data->argv, sizeof data->argv, argc, &argv) != 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; goto error;
} }
@ -974,31 +924,20 @@ server_client_msg_command(struct client *c, struct msg_command_data *data)
*argv = xstrdup("new-session"); *argv = xstrdup("new-session");
} }
if ((cmdlist = cmd_list_parse(argc, argv, &cause)) == NULL) { if ((cmdlist = cmd_list_parse(argc, argv, NULL, 0, &cause)) == NULL) {
server_client_msg_error(ctx, "%s", cause); cmdq_error(c->cmdq, "%s", cause);
cmd_free_argv(argc, argv); cmd_free_argv(argc, argv);
goto error; goto error;
} }
cmd_free_argv(argc, argv); cmd_free_argv(argc, argv);
switch (cmd_list_exec(cmdlist, ctx)) cmdq_run(c->cmdq, cmdlist);
{
case CMD_RETURN_ERROR:
case CMD_RETURN_NORMAL:
c->flags |= CLIENT_EXIT;
break;
case CMD_RETURN_ATTACH:
case CMD_RETURN_YIELD:
break;
}
cmd_list_free(cmdlist); cmd_list_free(cmdlist);
cmd_free_ctx(ctx);
return; return;
error: error:
if (cmdlist != NULL) if (cmdlist != NULL)
cmd_list_free(cmdlist); cmd_list_free(cmdlist);
cmd_free_ctx(ctx);
c->flags |= CLIENT_EXIT; c->flags |= CLIENT_EXIT;
} }

View File

@ -194,7 +194,7 @@ server_status_window(struct window *w)
/* /*
* This is slightly different. We want to redraw the status line of any * 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. * current window.
*/ */
@ -563,7 +563,7 @@ int
server_set_stdin_callback(struct client *c, void (*cb)(struct client *, int, server_set_stdin_callback(struct client *c, void (*cb)(struct client *, int,
void *), void *cb_data, char **cause) void *), void *cb_data, char **cause)
{ {
if (c == NULL) { if (c == NULL || c->session != NULL) {
*cause = xstrdup("no client with stdin"); *cause = xstrdup("no client with stdin");
return (-1); return (-1);
} }

View File

@ -107,6 +107,7 @@ server_start(int lockfd, char *lockfile)
{ {
int pair[2]; int pair[2];
struct timeval tv; struct timeval tv;
char *cause;
/* The first client is special and gets a socketpair; create it. */ /* The first client is special and gets a socketpair; create it. */
if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, pair) != 0) if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, pair) != 0)
@ -163,23 +164,28 @@ server_start(int lockfd, char *lockfile)
free(lockfile); free(lockfile);
close(lockfd); close(lockfd);
if (access(SYSTEM_CFG, R_OK) == 0) cfg_cmd_q = cmdq_new(NULL);
load_cfg(SYSTEM_CFG, NULL, &cfg_causes); cfg_cmd_q->emptyfn = cfg_default_done;
else if (errno != ENOENT) { cfg_finished = 0;
cfg_add_cause( cfg_references = 1;
&cfg_causes, "%s: %s", SYSTEM_CFG, strerror(errno)); 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);
} }
if (cfg_file != NULL) } else if (errno != ENOENT) {
load_cfg(cfg_file, NULL, &cfg_causes); xasprintf(&cause, "%s: %s", SYSTEM_CFG, strerror(errno));
ARRAY_ADD(&cfg_causes, cause);
/* }
* If there is a session already, put the current window and pane into if (cfg_file != NULL) {
* more mode. if (load_cfg(cfg_file, cfg_cmd_q, &cause) == -1) {
*/ xasprintf(&cause, "%s: %s", cfg_file, cause);
if (!RB_EMPTY(&sessions) && !ARRAY_EMPTY(&cfg_causes)) ARRAY_ADD(&cfg_causes, cause);
show_cfg_causes(RB_MIN(sessions, &sessions)); }
}
cfg_finished = 1; cmdq_continue(cfg_cmd_q);
server_add_accept(0); server_add_accept(0);

16
tmux.1
View File

@ -3468,7 +3468,11 @@ Miscellaneous commands are as follows:
.Bl -tag -width Ds .Bl -tag -width Ds
.It Ic clock-mode Op Fl t Ar target-pane .It Ic clock-mode Op Fl t Ar target-pane
Display a large clock. Display a large clock.
.It Ic if-shell Ar shell-command command Op Ar command .It Xo Ic if-shell
.Op Fl b
.Ar shell-command command
.Op Ar command
.Xc
.D1 (alias: Ic if ) .D1 (alias: Ic if )
Execute the first Execute the first
.Ar command .Ar command
@ -3477,19 +3481,27 @@ if
returns success or the second returns success or the second
.Ar command .Ar command
otherwise. otherwise.
With
.Fl b ,
.Ar shell-command
is run in the background.
.It Ic lock-server .It Ic lock-server
.D1 (alias: Ic lock ) .D1 (alias: Ic lock )
Lock each client individually by running the command specified by the Lock each client individually by running the command specified by the
.Ic lock-command .Ic lock-command
option. option.
.It Xo Ic run-shell .It Xo Ic run-shell
.Fl b
.Op Fl t Ar target-pane .Op Fl t Ar target-pane
.Ar shell-command .Ar shell-command
.Xc .Xc
.D1 (alias: Ic run ) .D1 (alias: Ic run )
Execute Execute
.Ar shell-command .Ar shell-command
in the background without creating a window. without creating a window.
With
.Fl b ,
the command is run in the background.
After it finishes, any output to stdout is displayed in copy mode (in the pane After it finishes, any output to stdout is displayed in copy mode (in the pane
specified by specified by
.Fl t .Fl t

2
tmux.c
View File

@ -336,8 +336,6 @@ main(int argc, char **argv)
options_init(&global_w_options, NULL); options_init(&global_w_options, NULL);
options_table_populate_tree(window_options_table, &global_w_options); 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. */ /* Enable UTF-8 if the first client is on UTF-8 terminal. */
if (flags & IDENTIFY_UTF8) { if (flags & IDENTIFY_UTF8) {
options_set_number(&global_s_options, "status-utf8", 1); options_set_number(&global_s_options, "status-utf8", 1);

132
tmux.h
View File

@ -428,6 +428,9 @@ struct tty_term_code_entry {
const char *name; const char *name;
}; };
/* List of error causes. */
ARRAY_DECL(causelist, char *);
/* Message codes. */ /* Message codes. */
enum msgtype { enum msgtype {
MSG_COMMAND, MSG_COMMAND,
@ -773,6 +776,9 @@ struct job {
int fd; int fd;
struct bufferevent *event; struct bufferevent *event;
struct bufferevent *out;
int outdone;
void (*callbackfn)(struct job *); void (*callbackfn)(struct job *);
void (*freefn)(void *); void (*freefn)(void *);
void *data; void *data;
@ -1346,6 +1352,7 @@ struct client {
int wlmouse; int wlmouse;
struct cmd_q *cmdq;
int references; int references;
}; };
ARRAY_DECL(clients, struct client *); ARRAY_DECL(clients, struct client *);
@ -1359,41 +1366,14 @@ struct args {
char **argv; char **argv;
}; };
/* Key/command line command. */ /* Command and list of commands. */
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
};
struct cmd { struct cmd {
const struct cmd_entry *entry; const struct cmd_entry *entry;
struct args *args; struct args *args;
char *file;
u_int line;
TAILQ_ENTRY(cmd) qentry; TAILQ_ENTRY(cmd) qentry;
}; };
struct cmd_list { struct cmd_list {
@ -1401,13 +1381,40 @@ struct cmd_list {
TAILQ_HEAD(, cmd) list; TAILQ_HEAD(, cmd) list;
}; };
/* Command return values. */
enum cmd_retval { enum cmd_retval {
CMD_RETURN_ERROR = -1, CMD_RETURN_ERROR = -1,
CMD_RETURN_NORMAL = 0, CMD_RETURN_NORMAL = 0,
CMD_RETURN_YIELD, CMD_RETURN_WAIT,
CMD_RETURN_ATTACH 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 { struct cmd_entry {
const char *name; const char *name;
const char *alias; const char *alias;
@ -1426,7 +1433,7 @@ struct cmd_entry {
void (*key_binding)(struct cmd *, int); void (*key_binding)(struct cmd *, int);
int (*check)(struct args *); int (*check)(struct args *);
enum cmd_retval (*exec)(struct cmd *, struct cmd_ctx *); enum cmd_retval (*exec)(struct cmd *, struct cmd_q *);
}; };
/* Key binding. */ /* Key binding. */
@ -1475,9 +1482,6 @@ struct format_entry {
}; };
RB_HEAD(format_tree, format_entry); RB_HEAD(format_tree, format_entry);
/* List of configuration causes. */
ARRAY_DECL(causelist, char *);
/* Common command usages. */ /* Common command usages. */
#define CMD_TARGET_PANE_USAGE "[-t target-pane]" #define CMD_TARGET_PANE_USAGE "[-t target-pane]"
#define CMD_TARGET_WINDOW_USAGE "[-t target-window]" #define CMD_TARGET_WINDOW_USAGE "[-t target-window]"
@ -1513,12 +1517,13 @@ void setblocking(int, int);
__dead void shell_exec(const char *, const char *); __dead void shell_exec(const char *, const char *);
/* cfg.c */ /* cfg.c */
extern struct cmd_q *cfg_cmd_q;
extern int cfg_finished; extern int cfg_finished;
extern int cfg_references; extern int cfg_references;
extern struct causelist cfg_causes; extern struct causelist cfg_causes;
void printflike2 cfg_add_cause(struct causelist *, const char *, ...); int load_cfg(const char *, struct cmd_q *, char **);
enum cmd_retval load_cfg(const char *, struct cmd_ctx *, struct causelist *); void cfg_default_done(struct cmd_q *);
void show_cfg_causes(struct session *); void cfg_show_causes(struct session *);
/* format.c */ /* format.c */
int format_cmp(struct format_entry *, struct format_entry *); int format_cmp(struct format_entry *, struct format_entry *);
@ -1721,27 +1726,24 @@ long long args_strtonum(
struct args *, u_char, long long, long long, char **); struct args *, u_char, long long, long long, char **);
/* cmd.c */ /* 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_pack_argv(int, char **, char *, size_t);
int cmd_unpack_argv(char *, size_t, int, char ***); int cmd_unpack_argv(char *, size_t, int, char ***);
char **cmd_copy_argv(int, char *const *); char **cmd_copy_argv(int, char *const *);
void cmd_free_argv(int, char **); 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); size_t cmd_print(struct cmd *, char *, size_t);
struct session *cmd_current_session(struct cmd_ctx *, int); struct session *cmd_current_session(struct cmd_q *, int);
struct client *cmd_current_client(struct cmd_ctx *); struct client *cmd_current_client(struct cmd_q *);
struct client *cmd_find_client(struct cmd_ctx *, const char *, int); struct client *cmd_find_client(struct cmd_q *, const char *, int);
struct session *cmd_find_session(struct cmd_ctx *, const char *, int); struct session *cmd_find_session(struct cmd_q *, const char *, int);
struct winlink *cmd_find_window( struct winlink *cmd_find_window(struct cmd_q *, const char *,
struct cmd_ctx *, const char *, struct session **); struct session **);
int cmd_find_index( int cmd_find_index(struct cmd_q *, const char *,
struct cmd_ctx *, const char *, struct session **); struct session **);
struct winlink *cmd_find_pane(struct cmd_ctx *, struct winlink *cmd_find_pane(struct cmd_q *, const char *, struct session **,
const char *, struct session **, struct window_pane **); struct window_pane **);
char *cmd_template_replace(const char *, const char *, int); 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_table[];
extern const struct cmd_entry cmd_attach_session_entry; extern const struct cmd_entry cmd_attach_session_entry;
extern const struct cmd_entry cmd_bind_key_entry; extern const struct cmd_entry cmd_bind_key_entry;
@ -1831,13 +1833,24 @@ extern const struct cmd_entry cmd_unlink_window_entry;
extern const struct cmd_entry cmd_up_pane_entry; extern const struct cmd_entry cmd_up_pane_entry;
/* cmd-list.c */ /* cmd-list.c */
struct cmd_list *cmd_list_parse(int, char **, char **); struct cmd_list *cmd_list_parse(int, char **, const char *, u_int, char **);
enum cmd_retval cmd_list_exec(struct cmd_list *, struct cmd_ctx *);
void cmd_list_free(struct cmd_list *); void cmd_list_free(struct cmd_list *);
size_t cmd_list_print(struct cmd_list *, char *, size_t); 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 */ /* 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 */ /* client.c */
int client_main(int, char **, int); int client_main(int, char **, int);
@ -1852,9 +1865,6 @@ void key_bindings_remove(int);
void key_bindings_clean(void); void key_bindings_clean(void);
void key_bindings_init(void); void key_bindings_init(void);
void key_bindings_dispatch(struct key_binding *, struct client *); 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 */ /* key-string.c */
int key_string_lookup_string(const char *); int key_string_lookup_string(const char *);

View File

@ -200,7 +200,6 @@ window_choose_data_free(struct window_choose_data *wcd)
void void
window_choose_data_run(struct window_choose_data *cdata) window_choose_data_run(struct window_choose_data *cdata)
{ {
struct cmd_ctx *ctx;
struct cmd_list *cmdlist; struct cmd_list *cmdlist;
char *cause; char *cause;
@ -211,7 +210,7 @@ window_choose_data_run(struct window_choose_data *cdata)
if (cdata->command == NULL) if (cdata->command == NULL)
return; return;
if (cmd_string_parse(cdata->command, &cmdlist, &cause) != 0) { if (cmd_string_parse(cdata->command, &cmdlist, NULL, 0, &cause) != 0) {
if (cause != NULL) { if (cause != NULL) {
*cause = toupper((u_char) *cause); *cause = toupper((u_char) *cause);
status_message_set(cdata->start_client, "%s", cause); status_message_set(cdata->start_client, "%s", cause);
@ -220,14 +219,8 @@ window_choose_data_run(struct window_choose_data *cdata)
return; return;
} }
ctx = cmd_get_ctx(NULL, cdata->start_client); cmdq_run(cdata->start_client->cmdq, cmdlist);
ctx->error = key_bindings_error;
ctx->print = key_bindings_print;
ctx->info = key_bindings_info;
cmd_list_exec(cmdlist, ctx);
cmd_list_free(cmdlist); cmd_list_free(cmdlist);
cmd_free_ctx(ctx);
} }
void void