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-03-24 09:54:10 +00:00
parent 66edb3392b
commit 20636d956d
84 changed files with 1240 additions and 1187 deletions

View File

@ -60,12 +60,10 @@ SRCS= arguments.c \
cmd-select-pane.c \ cmd-select-pane.c \
cmd-select-window.c \ cmd-select-window.c \
cmd-send-keys.c \ cmd-send-keys.c \
cmd-send-prefix.c \
cmd-server-info.c \ cmd-server-info.c \
cmd-set-buffer.c \ cmd-set-buffer.c \
cmd-set-environment.c \ cmd-set-environment.c \
cmd-set-option.c \ cmd-set-option.c \
cmd-show-buffer.c \
cmd-show-environment.c \ cmd-show-environment.c \
cmd-show-messages.c \ cmd-show-messages.c \
cmd-show-options.c \ cmd-show-options.c \
@ -80,6 +78,7 @@ SRCS= arguments.c \
cmd-unbind-key.c \ cmd-unbind-key.c \
cmd-unlink-window.c \ cmd-unlink-window.c \
cmd.c \ cmd.c \
cmd-queue.c \
colour.c \ colour.c \
control.c \ control.c \
control-notify.c \ control-notify.c \

130
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",
"t:", 2, 3, "bt:", 2, 3,
CMD_TARGET_PANE_USAGE " shell-command command [command]", "[-b] " CMD_TARGET_PANE_USAGE " 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;
@ -61,7 +64,7 @@ cmd_if_shell_exec(struct cmd *self, struct cmd_ctx *ctx)
struct window_pane *wp; struct window_pane *wp;
struct format_tree *ft; struct format_tree *ft;
wl = cmd_find_pane(ctx, args_get(args, 't'), &s, &wp); wl = cmd_find_pane(cmdq, args_get(args, 't'), &s, &wp);
if (wl == NULL) if (wl == NULL)
return (CMD_RETURN_ERROR); return (CMD_RETURN_ERROR);
@ -78,51 +81,83 @@ cmd_if_shell_exec(struct cmd *self, struct cmd_ctx *ctx)
cdata->cmd_else = xstrdup(args->argv[2]); 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);
free(shellcmd); free(shellcmd);
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;
if (cmd == NULL) else
return;
} else
cmd = cdata->cmd_if; cmd = cdata->cmd_if;
if (cmd_string_parse(cmd, &cmdlist, &cause) != 0) { if (cmd == NULL)
return;
if (cmd_string_parse(cmd, &cmdlist, NULL, 0, &cause) != 0) {
if (cause != NULL) { 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

@ -30,9 +30,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",
@ -69,13 +69,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;
@ -87,23 +87,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);
} }
@ -115,14 +115,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);
} }
@ -133,7 +133,7 @@ join_pane(struct cmd *self, struct cmd_ctx *ctx, int not_same_window)
} }
lc = layout_split_pane(dst_wp, type, size, args_has(args, 'b')); 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,62 +53,52 @@ 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 window *w; struct session *s, *groupwith;
struct environ env; struct window *w;
struct termios tio, *tiop; struct environ env;
struct passwd *pw; struct termios tio, *tiop;
const char *newname, *target, *update, *cwd, *errstr; struct passwd *pw;
char *cmd, *cause; const char *newname, *target, *update, *cwd, *errstr;
int detached, idx; char *cmd, *cause;
u_int sx, sy; int detached, idx;
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,32 +136,25 @@ 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( if (errstr != NULL) {
args_get(args, 'x'), 1, USHRT_MAX, &errstr); cmdq_error(cmdq, "width %s", errstr);
if (errstr != NULL) { return (CMD_RETURN_ERROR);
ctx->error(ctx, "width %s", errstr);
return (CMD_RETURN_ERROR);
}
} }
if (args_has(args, 'y')) { }
sy = strtonum( if (detached && args_has(args, 'y')) {
args_get(args, 'y'), 1, USHRT_MAX, &errstr); sy = strtonum(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"))
@ -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; session_update_activity(s);
notify_attached_session_changed(ctx->cmdclient); server_redraw_client(c);
session_update_activity(s);
server_redraw_client(ctx->cmdclient);
} else {
old_s = ctx->curclient->session;
if (old_s != NULL)
ctx->curclient->last_session = old_s;
ctx->curclient->session = s;
notify_attached_session_changed(ctx->curclient);
session_update_activity(s);
server_redraw_client(ctx->curclient);
}
} }
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

@ -28,7 +28,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);
@ -44,7 +44,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;
@ -55,7 +55,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'))
@ -63,7 +63,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);
} }
@ -74,7 +74,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

@ -32,7 +32,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 *);
@ -47,7 +47,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;
@ -55,9 +55,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;
@ -82,14 +82,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 @@
/* $OpenBSD$ */
/*
* 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,7 +71,7 @@ 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;
@ -81,7 +81,7 @@ cmd_run_shell_exec(struct cmd *self, struct cmd_ctx *ctx)
struct window_pane *wp; struct window_pane *wp;
struct format_tree *ft; struct format_tree *ft;
wl = cmd_find_pane(ctx, args_get(args, 't'), &s, &wp); wl = cmd_find_pane(cmdq, args_get(args, 't'), &s, &wp);
if (wl == NULL) if (wl == NULL)
return (CMD_RETURN_ERROR); return (CMD_RETURN_ERROR);
@ -94,35 +94,37 @@ cmd_run_shell_exec(struct cmd *self, struct cmd_ctx *ctx)
cdata = xmalloc(sizeof *cdata); cdata = xmalloc(sizeof *cdata);
cdata->cmd = shellcmd; cdata->cmd = shellcmd;
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++;
} }
@ -140,8 +142,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)
@ -152,7 +152,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);
@ -163,11 +163,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

@ -22,6 +22,7 @@
#include <errno.h> #include <errno.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <vis.h>
#include "tmux.h" #include "tmux.h"
@ -29,7 +30,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",
@ -41,83 +42,132 @@ const struct cmd_entry cmd_save_buffer_entry = {
cmd_save_buffer_exec cmd_save_buffer_exec
}; };
const struct cmd_entry cmd_show_buffer_entry = {
"show-buffer", "showb",
"b:", 0, 0,
CMD_BUFFER_USAGE,
0,
NULL,
NULL,
cmd_save_buffer_exec
};
enum cmd_retval 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;
struct session *s; struct session *s;
struct paste_buffer *pb; struct paste_buffer *pb;
const char *path, *newpath, *wd; const char *path, *newpath, *wd;
char *cause; char *cause, *start, *end;
size_t size, used;
int buffer; int buffer;
mode_t mask; mode_t mask;
FILE *f; FILE *f;
char *msg;
size_t msglen;
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);
} }
} }
path = args->argv[0]; if (self->entry == &cmd_show_buffer_entry)
path = "-";
else
path = args->argv[0];
if (strcmp(path, "-") == 0) { if (strcmp(path, "-") == 0) {
c = ctx->curclient; c = cmdq->client;
if (c == NULL || !(c->flags & CLIENT_CONTROL))
c = ctx->cmdclient;
if (c == NULL) { if (c == NULL) {
ctx->error(ctx, "can't write to stdout"); cmdq_error(cmdq, "can't write to stdout");
return (CMD_RETURN_ERROR); return (CMD_RETURN_ERROR);
} }
evbuffer_add(c->stdout_data, pb->data, pb->size); if (c->session == NULL || (c->flags & CLIENT_CONTROL))
server_push_stdout(c); goto do_stdout;
} else { goto do_print;
c = ctx->cmdclient;
if (c != NULL)
wd = c->cwd;
else if ((s = cmd_current_session(ctx, 0)) != NULL) {
wd = options_get_string(&s->options, "default-path");
if (*wd == '\0')
wd = s->cwd;
} else
wd = NULL;
if (wd != NULL && *wd != '\0') {
newpath = get_full_path(wd, path);
if (newpath != NULL)
path = newpath;
}
mask = umask(S_IRWXG | S_IRWXO);
if (args_has(self->args, 'a'))
f = fopen(path, "ab");
else
f = fopen(path, "wb");
umask(mask);
if (f == NULL) {
ctx->error(ctx, "%s: %s", path, strerror(errno));
return (CMD_RETURN_ERROR);
}
if (fwrite(pb->data, 1, pb->size, f) != pb->size) {
ctx->error(ctx, "%s: fwrite error", path);
fclose(f);
return (CMD_RETURN_ERROR);
}
fclose(f);
} }
c = cmdq->client;
if (c != NULL)
wd = c->cwd;
else if ((s = cmd_current_session(cmdq, 0)) != NULL) {
wd = options_get_string(&s->options, "default-path");
if (*wd == '\0')
wd = s->cwd;
} else
wd = NULL;
if (wd != NULL && *wd != '\0') {
newpath = get_full_path(wd, path);
if (newpath != NULL)
path = newpath;
}
mask = umask(S_IRWXG | S_IRWXO);
if (args_has(self->args, 'a'))
f = fopen(path, "ab");
else
f = fopen(path, "wb");
umask(mask);
if (f == NULL) {
cmdq_error(cmdq, "%s: %s", path, strerror(errno));
return (CMD_RETURN_ERROR);
}
if (fwrite(pb->data, 1, pb->size, f) != pb->size) {
cmdq_error(cmdq, "%s: fwrite error", path);
fclose(f);
return (CMD_RETURN_ERROR);
}
fclose(f);
return (CMD_RETURN_NORMAL);
do_stdout:
evbuffer_add(c->stdout_data, pb->data, pb->size);
server_push_stdout(c);
return (CMD_RETURN_NORMAL);
do_print:
if (pb->size > (INT_MAX / 4) - 1) {
cmdq_error(cmdq, "buffer too big");
return (CMD_RETURN_ERROR);
}
msg = NULL;
msglen = 0;
used = 0;
while (used != pb->size) {
start = pb->data + used;
end = memchr(start, '\n', pb->size - used);
if (end != NULL)
size = end - start;
else
size = pb->size - used;
msglen = size * 4 + 1;
msg = xrealloc(msg, 1, msglen);
strvisx(msg, start, size, VIS_OCTAL|VIS_TAB);
cmdq_print(cmdq, "%s", msg);
used += size + (end != NULL);
}
free(msg);
return (CMD_RETURN_NORMAL); return (CMD_RETURN_NORMAL);
} }

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",
@ -39,8 +39,18 @@ const struct cmd_entry cmd_send_keys_entry = {
cmd_send_keys_exec cmd_send_keys_exec
}; };
const struct cmd_entry cmd_send_prefix_entry = {
"send-prefix", NULL,
"2t:", 0, 0,
"[-2] " CMD_TARGET_PANE_USAGE,
0,
NULL,
NULL,
cmd_send_keys_exec
};
enum cmd_retval 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;
@ -49,9 +59,18 @@ 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 (args_has(args, '2'))
key = options_get_number(&s->options, "prefix2");
else
key = options_get_number(&s->options, "prefix");
window_pane_key(wp, s, key);
return (CMD_RETURN_NORMAL);
}
if (args_has(args, 'R')) { if (args_has(args, 'R')) {
ictx = &wp->ictx; ictx = &wp->ictx;

View File

@ -31,7 +31,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",
@ -44,7 +44,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;
@ -66,47 +66,47 @@ 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, "pid %ld, started %s", (long) getpid(), tim); cmdq_print(cmdq, "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,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;
u_int i; char *cause;
char *cause;
retval = load_cfg(args->argv[0], ctx, &cfg_causes); cmdq1 = cmdq_new(NULL);
cmdq1->emptyfn = cmd_source_file_done;
cmdq1->data = cmdq;
/* switch (load_cfg(args->argv[0], cmdq1, &cause)) {
* If the context for the cmdclient came from tmux's configuration case -1:
* file, then return the status of this command now, regardless of the if (cfg_references == 0) {
* error condition. Any errors from parsing a configuration file at cmdq_free(cmdq1);
* startup will be handled for us by the server. cmdq_error(cmdq, "%s", cause);
*/ free(cause);
if (cfg_references > 0 || return (CMD_RETURN_ERROR);
(ctx->curclient == NULL && ctx->cmdclient == NULL)) }
return (retval); ARRAY_ADD(&cfg_causes, cause);
/* FALLTHROUGH */
case 0:
if (cfg_references == 0)
cmd_source_file_show(cmdq);
cmdq_free(cmdq1);
return (CMD_RETURN_NORMAL);
}
cmdq->references++;
cfg_references++;
cmdq_continue(cmdq1);
return (CMD_RETURN_WAIT);
}
void
cmd_source_file_show(struct cmd_q *cmdq)
{
u_int i;
char *cause;
/*
* We were called from the command-line in which case print the errors
* gathered here directly.
*/
for (i = 0; i < ARRAY_LENGTH(&cfg_causes); i++) { 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

@ -29,7 +29,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",
@ -51,7 +51,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;
@ -70,7 +70,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;
@ -83,7 +83,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'))
@ -152,14 +152,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);
@ -171,7 +171,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

@ -127,48 +127,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)
{ {
@ -242,7 +206,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;
@ -292,9 +256,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:
@ -343,31 +312,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;
} }
@ -458,21 +429,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++) {
@ -517,7 +488,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;
@ -525,9 +496,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);
@ -542,7 +513,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);
@ -744,14 +715,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) {
@ -776,7 +747,7 @@ cmd_window_session(struct cmd_ctx *ctx, struct window *w, struct winlink **wlp)
/* Find the target session or report an error and return NULL. */ /* 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;
@ -788,13 +759,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);
@ -805,7 +776,7 @@ cmd_find_session(struct cmd_ctx *ctx, const char *arg, int prefer_unattached)
/* An empty session name is the current session. */ /* 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. */
@ -818,9 +789,9 @@ cmd_find_session(struct cmd_ctx *ctx, const char *arg, int prefer_unattached)
/* If no session found, report an error. */ /* If 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);
@ -829,7 +800,7 @@ cmd_find_session(struct cmd_ctx *ctx, const char *arg, int prefer_unattached)
/* Find the target session and window or report an error and return NULL. */ /* 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;
@ -842,8 +813,8 @@ cmd_find_window(struct cmd_ctx *ctx, const char *arg, struct session **sp)
* Find the current session. There must always be a current session, if * 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);
} }
@ -856,7 +827,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);
@ -937,17 +908,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);
} }
@ -979,7 +950,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;
@ -991,8 +962,8 @@ cmd_find_index(struct cmd_ctx *ctx, const char *arg, struct session **sp)
* Find the current session. There must always be a current session, if * 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);
} }
@ -1075,25 +1046,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);
} }
@ -1130,7 +1101,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;
@ -1140,8 +1111,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)
@ -1155,7 +1126,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);
@ -1170,7 +1141,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. */
@ -1194,7 +1165,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;
} }
@ -1219,7 +1190,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);
@ -1297,8 +1268,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;
@ -1308,7 +1280,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)
@ -1338,9 +1310,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 = get_proc_cwd(s->curw->window->active->fd); root = get_proc_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

@ -45,10 +45,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)
@ -67,6 +63,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 ();
@ -181,6 +180,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);
@ -901,71 +904,18 @@ server_client_msg_dispatch(struct client *c)
} }
} }
/* Callback to send error message to client. */
void printflike2
server_client_msg_error(struct cmd_ctx *ctx, const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
evbuffer_add_vprintf(ctx->cmdclient->stderr_data, fmt, ap);
va_end(ap);
evbuffer_add(ctx->cmdclient->stderr_data, "\n", 1);
server_push_stderr(ctx->cmdclient);
ctx->cmdclient->retcode = 1;
}
/* Callback to send print message to client. */
void printflike2
server_client_msg_print(struct cmd_ctx *ctx, const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
evbuffer_add_vprintf(ctx->cmdclient->stdout_data, fmt, ap);
va_end(ap);
evbuffer_add(ctx->cmdclient->stdout_data, "\n", 1);
server_push_stdout(ctx->cmdclient);
}
/* Callback to send print message to client, if not quiet. */
void printflike2
server_client_msg_info(struct cmd_ctx *ctx, const char *fmt, ...)
{
va_list ap;
if (options_get_number(&global_options, "quiet"))
return;
va_start(ap, fmt);
evbuffer_add_vprintf(ctx->cmdclient->stdout_data, fmt, ap);
va_end(ap);
evbuffer_add(ctx->cmdclient->stdout_data, "\n", 1);
server_push_stdout(ctx->cmdclient);
}
/* Handle command message. */ /* 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;
} }
@ -975,31 +925,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

@ -106,8 +106,9 @@ server_create_socket(void)
int int
server_start(int lockfd, char *lockfile) 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)
@ -162,23 +163,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);
}
} else if (errno != ENOENT) {
xasprintf(&cause, "%s: %s", SYSTEM_CFG, strerror(errno));
ARRAY_ADD(&cfg_causes, cause);
} }
if (cfg_file != NULL) if (cfg_file != NULL) {
load_cfg(cfg_file, NULL, &cfg_causes); if (load_cfg(cfg_file, cfg_cmd_q, &cause) == -1) {
xasprintf(&cause, "%s: %s", cfg_file, cause);
/* ARRAY_ADD(&cfg_causes, cause);
* If there is a session already, put the current window and pane into }
* more mode. }
*/ cmdq_continue(cfg_cmd_q);
if (!RB_EMPTY(&sessions) && !ARRAY_EMPTY(&cfg_causes))
show_cfg_causes(RB_MIN(sessions, &sessions));
cfg_finished = 1;
server_add_accept(0); server_add_accept(0);

2
tmux.c
View File

@ -330,8 +330,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);

136
tmux.h
View File

@ -432,6 +432,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,
@ -777,6 +780,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;
@ -1350,6 +1356,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 *);
@ -1363,41 +1370,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 {
@ -1405,13 +1385,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;
@ -1430,7 +1437,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. */
@ -1479,9 +1486,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]"
@ -1517,12 +1521,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 int cfg_finished; extern struct cmd_q *cfg_cmd_q;
extern int cfg_references; extern int cfg_finished;
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 *);
@ -1725,27 +1730,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;
@ -1835,13 +1837,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);
@ -1856,9 +1869,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,9 +200,8 @@ 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;
/* /*
* The command template will have already been replaced. But if it's * The command template will have already been replaced. But if it's
@ -211,7 +210,7 @@ window_choose_data_run(struct window_choose_data *cdata)
if (cdata->command == NULL) 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