From d1e6ce26722e3a0774d240e39bbc69b07e93c48b Mon Sep 17 00:00:00 2001 From: Nicholas Marriott Date: Fri, 22 Mar 2013 15:49:55 +0000 Subject: Add functions to allocate and free command contexts rather than doing it all on the stack. --- cmd-if-shell.c | 20 +++++++------------- 1 file changed, 7 insertions(+), 13 deletions(-) (limited to 'cmd-if-shell.c') diff --git a/cmd-if-shell.c b/cmd-if-shell.c index 4cb9de82..ab69e8b5 100644 --- a/cmd-if-shell.c +++ b/cmd-if-shell.c @@ -47,7 +47,7 @@ const struct cmd_entry cmd_if_shell_entry = { struct cmd_if_shell_data { char *cmd_if; char *cmd_else; - struct cmd_ctx ctx; + struct cmd_ctx *ctx; }; enum cmd_retval @@ -63,12 +63,9 @@ cmd_if_shell_exec(struct cmd *self, struct cmd_ctx *ctx) cdata->cmd_else = xstrdup(args->argv[2]); else cdata->cmd_else = NULL; - memcpy(&cdata->ctx, ctx, sizeof cdata->ctx); - if (ctx->cmdclient != NULL) - ctx->cmdclient->references++; - if (ctx->curclient != NULL) - ctx->curclient->references++; + cdata->ctx = ctx; + cmd_ref_ctx(ctx); job_run(shellcmd, cmd_if_shell_callback, cmd_if_shell_free, cdata); @@ -79,7 +76,7 @@ void cmd_if_shell_callback(struct job *job) { struct cmd_if_shell_data *cdata = job->data; - struct cmd_ctx *ctx = &cdata->ctx; + struct cmd_ctx *ctx = cdata->ctx; struct cmd_list *cmdlist; char *cause, *cmd; @@ -105,14 +102,11 @@ void cmd_if_shell_free(void *data) { struct cmd_if_shell_data *cdata = data; - struct cmd_ctx *ctx = &cdata->ctx; + struct cmd_ctx *ctx = cdata->ctx; - if (ctx->cmdclient != NULL) { - ctx->cmdclient->references--; + if (ctx->cmdclient != NULL) ctx->cmdclient->flags |= CLIENT_EXIT; - } - if (ctx->curclient != NULL) - ctx->curclient->references--; + cmd_free_ctx(ctx); free(cdata->cmd_else); free(cdata->cmd_if); -- cgit From 66edb3392b234ccd9a940039936edb34258c2102 Mon Sep 17 00:00:00 2001 From: Nicholas Marriott Date: Sun, 24 Mar 2013 09:33:35 +0000 Subject: Expand format variables in the run-shell and if-shell shell commands, from Thiago Padilha. --- cmd-if-shell.c | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) (limited to 'cmd-if-shell.c') diff --git a/cmd-if-shell.c b/cmd-if-shell.c index ab69e8b5..e0e2c230 100644 --- a/cmd-if-shell.c +++ b/cmd-if-shell.c @@ -36,8 +36,8 @@ void cmd_if_shell_free(void *); const struct cmd_entry cmd_if_shell_entry = { "if-shell", "if", - "", 2, 3, - "shell-command command [command]", + "t:", 2, 3, + CMD_TARGET_PANE_USAGE " shell-command command [command]", 0, NULL, NULL, @@ -55,7 +55,22 @@ cmd_if_shell_exec(struct cmd *self, struct cmd_ctx *ctx) { struct args *args = self->args; struct cmd_if_shell_data *cdata; - const char *shellcmd = args->argv[0]; + char *shellcmd; + struct session *s; + struct winlink *wl; + struct window_pane *wp; + struct format_tree *ft; + + wl = cmd_find_pane(ctx, args_get(args, 't'), &s, &wp); + if (wl == NULL) + return (CMD_RETURN_ERROR); + + ft = format_create(); + format_session(ft, s); + format_winlink(ft, s, wl); + format_window_pane(ft, wp); + shellcmd = format_expand(ft, args->argv[0]); + format_free(ft); cdata = xmalloc(sizeof *cdata); cdata->cmd_if = xstrdup(args->argv[1]); @@ -68,6 +83,7 @@ cmd_if_shell_exec(struct cmd *self, struct cmd_ctx *ctx) cmd_ref_ctx(ctx); job_run(shellcmd, cmd_if_shell_callback, cmd_if_shell_free, cdata); + free(shellcmd); return (CMD_RETURN_YIELD); /* don't let client exit */ } -- cgit From 20636d956dd36c1f14152569a4d44a50eea9083d Mon Sep 17 00:00:00 2001 From: Nicholas Marriott Date: Sun, 24 Mar 2013 09:54:10 +0000 Subject: 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. --- cmd-if-shell.c | 77 ++++++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 56 insertions(+), 21 deletions(-) (limited to 'cmd-if-shell.c') diff --git a/cmd-if-shell.c b/cmd-if-shell.c index e0e2c230..e2a45972 100644 --- a/cmd-if-shell.c +++ b/cmd-if-shell.c @@ -29,15 +29,16 @@ * Executes a tmux command if a shell command returns true or false. */ -enum cmd_retval cmd_if_shell_exec(struct cmd *, struct cmd_ctx *); +enum cmd_retval cmd_if_shell_exec(struct cmd *, struct cmd_q *); void cmd_if_shell_callback(struct job *); +void cmd_if_shell_done(struct cmd_q *); void cmd_if_shell_free(void *); const struct cmd_entry cmd_if_shell_entry = { "if-shell", "if", - "t:", 2, 3, - CMD_TARGET_PANE_USAGE " shell-command command [command]", + "bt:", 2, 3, + "[-b] " CMD_TARGET_PANE_USAGE " shell-command command [command]", 0, NULL, NULL, @@ -47,11 +48,13 @@ const struct cmd_entry cmd_if_shell_entry = { struct cmd_if_shell_data { char *cmd_if; char *cmd_else; - struct cmd_ctx *ctx; + struct cmd_q *cmdq; + int bflag; + int started; }; enum cmd_retval -cmd_if_shell_exec(struct cmd *self, struct cmd_ctx *ctx) +cmd_if_shell_exec(struct cmd *self, struct cmd_q *cmdq) { struct args *args = self->args; struct cmd_if_shell_data *cdata; @@ -61,7 +64,7 @@ cmd_if_shell_exec(struct cmd *self, struct cmd_ctx *ctx) struct window_pane *wp; struct format_tree *ft; - wl = cmd_find_pane(ctx, args_get(args, 't'), &s, &wp); + wl = cmd_find_pane(cmdq, args_get(args, 't'), &s, &wp); if (wl == NULL) return (CMD_RETURN_ERROR); @@ -78,51 +81,83 @@ cmd_if_shell_exec(struct cmd *self, struct cmd_ctx *ctx) cdata->cmd_else = xstrdup(args->argv[2]); else cdata->cmd_else = NULL; + cdata->bflag = args_has(args, 'b'); - cdata->ctx = ctx; - cmd_ref_ctx(ctx); + cdata->started = 0; + cdata->cmdq = cmdq; + cmdq->references++; job_run(shellcmd, cmd_if_shell_callback, cmd_if_shell_free, cdata); free(shellcmd); - return (CMD_RETURN_YIELD); /* don't let client exit */ + if (cdata->bflag) + return (CMD_RETURN_NORMAL); + return (CMD_RETURN_WAIT); } void cmd_if_shell_callback(struct job *job) { struct cmd_if_shell_data *cdata = job->data; - struct cmd_ctx *ctx = cdata->ctx; + struct cmd_q *cmdq = cdata->cmdq, *cmdq1; struct cmd_list *cmdlist; char *cause, *cmd; - if (!WIFEXITED(job->status) || WEXITSTATUS(job->status) != 0) { + if (cmdq->dead) + return; + + if (!WIFEXITED(job->status) || WEXITSTATUS(job->status) != 0) cmd = cdata->cmd_else; - if (cmd == NULL) - return; - } else + else cmd = cdata->cmd_if; - if (cmd_string_parse(cmd, &cmdlist, &cause) != 0) { + if (cmd == NULL) + return; + + if (cmd_string_parse(cmd, &cmdlist, NULL, 0, &cause) != 0) { if (cause != NULL) { - ctx->error(ctx, "%s", cause); + cmdq_error(cmdq, "%s", cause); free(cause); } return; } - cmd_list_exec(cmdlist, ctx); + cdata->started = 1; + + cmdq1 = cmdq_new(cmdq->client); + cmdq1->emptyfn = cmd_if_shell_done; + cmdq1->data = cdata; + + cmdq_run(cmdq1, cmdlist); cmd_list_free(cmdlist); } +void +cmd_if_shell_done(struct cmd_q *cmdq1) +{ + struct cmd_if_shell_data *cdata = cmdq1->data; + struct cmd_q *cmdq = cdata->cmdq; + + if (!cmdq_free(cmdq) && !cdata->bflag) + cmdq_continue(cmdq); + + cmdq_free(cmdq1); + + free(cdata->cmd_else); + free(cdata->cmd_if); + free(cdata); +} + void cmd_if_shell_free(void *data) { struct cmd_if_shell_data *cdata = data; - struct cmd_ctx *ctx = cdata->ctx; + struct cmd_q *cmdq = cdata->cmdq; + + if (cdata->started) + return; - if (ctx->cmdclient != NULL) - ctx->cmdclient->flags |= CLIENT_EXIT; - cmd_free_ctx(ctx); + if (!cmdq_free(cmdq) && !cdata->bflag) + cmdq_continue(cmdq); free(cdata->cmd_else); free(cdata->cmd_if); -- cgit From d28a39d01de47786a703e630a4f8930485cba7a1 Mon Sep 17 00:00:00 2001 From: Nicholas Marriott Date: Mon, 25 Mar 2013 11:43:01 +0000 Subject: Extend jobs to support writing and use that for copy-pipe instead of popen, from Chris Johnsen. --- cmd-if-shell.c | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) (limited to 'cmd-if-shell.c') diff --git a/cmd-if-shell.c b/cmd-if-shell.c index e2a45972..a3ca6555 100644 --- a/cmd-if-shell.c +++ b/cmd-if-shell.c @@ -59,19 +59,21 @@ cmd_if_shell_exec(struct cmd *self, struct cmd_q *cmdq) struct args *args = self->args; struct cmd_if_shell_data *cdata; char *shellcmd; - struct session *s; - struct winlink *wl; - struct window_pane *wp; + struct session *s = NULL; + struct winlink *wl = NULL; + struct window_pane *wp = NULL; struct format_tree *ft; - wl = cmd_find_pane(cmdq, args_get(args, 't'), &s, &wp); - if (wl == NULL) - return (CMD_RETURN_ERROR); + if (args_has(args, 't')) + wl = cmd_find_pane(cmdq, args_get(args, 't'), &s, &wp); ft = format_create(); - format_session(ft, s); - format_winlink(ft, s, wl); - format_window_pane(ft, wp); + if (s != NULL) + format_session(ft, s); + if (s != NULL && wl != NULL) + format_winlink(ft, s, wl); + if (wp != NULL) + format_window_pane(ft, wp); shellcmd = format_expand(ft, args->argv[0]); format_free(ft); @@ -87,7 +89,7 @@ cmd_if_shell_exec(struct cmd *self, struct cmd_q *cmdq) cdata->cmdq = cmdq; cmdq->references++; - job_run(shellcmd, cmd_if_shell_callback, cmd_if_shell_free, cdata); + job_run(shellcmd, s, cmd_if_shell_callback, cmd_if_shell_free, cdata); free(shellcmd); if (cdata->bflag) -- cgit