=================================================================== RCS file: /cvsrepo/anoncvs/cvs/src/usr.bin/tmux/cmd-if-shell.c,v retrieving revision 1.60 retrieving revision 1.61 diff -u -r1.60 -r1.61 --- src/usr.bin/tmux/cmd-if-shell.c 2018/08/27 11:03:34 1.60 +++ src/usr.bin/tmux/cmd-if-shell.c 2019/05/23 11:13:30 1.61 @@ -1,4 +1,4 @@ -/* $OpenBSD: cmd-if-shell.c,v 1.60 2018/08/27 11:03:34 nicm Exp $ */ +/* $OpenBSD: cmd-if-shell.c,v 1.61 2019/05/23 11:13:30 nicm Exp $ */ /* * Copyright (c) 2009 Tiago Cunha @@ -49,8 +49,7 @@ }; struct cmd_if_shell_data { - char *file; - u_int line; + struct cmd_parse_input input; char *cmd_if; char *cmd_else; @@ -64,51 +63,62 @@ cmd_if_shell_exec(struct cmd *self, struct cmdq_item *item) { struct args *args = self->args; - struct cmdq_shared *shared = item->shared; + struct mouse_event *m = &item->shared->mouse; struct cmd_if_shell_data *cdata; - char *shellcmd, *cmd, *cause; - struct cmd_list *cmdlist; + char *shellcmd, *cmd; struct cmdq_item *new_item; struct client *c = cmd_find_client(item, NULL, 1); struct session *s = item->target.s; struct winlink *wl = item->target.wl; struct window_pane *wp = item->target.wp; + struct cmd_parse_input pi; + struct cmd_parse_result *pr; shellcmd = format_single(item, args->argv[0], c, s, wl, wp); if (args_has(args, 'F')) { - cmd = NULL; if (*shellcmd != '0' && *shellcmd != '\0') cmd = args->argv[1]; else if (args->argc == 3) cmd = args->argv[2]; + else + cmd = NULL; free(shellcmd); if (cmd == NULL) return (CMD_RETURN_NORMAL); - cmdlist = cmd_string_parse(cmd, NULL, 0, &cause); - if (cmdlist == NULL) { - if (cause != NULL) { - cmdq_error(item, "%s", cause); - free(cause); - } + + memset(&pi, 0, sizeof pi); + if (self->file != NULL) + pi.file = self->file; + pi.line = self->line; + pi.item = item; + pi.c = c; + cmd_find_copy_state(&pi.fs, &item->target); + + pr = cmd_parse_from_string(cmd, &pi); + switch (pr->status) { + case CMD_PARSE_EMPTY: + break; + case CMD_PARSE_ERROR: + cmdq_error(item, "%s", pr->error); + free(pr->error); return (CMD_RETURN_ERROR); + case CMD_PARSE_SUCCESS: + new_item = cmdq_get_command(pr->cmdlist, NULL, m, 0); + cmdq_insert_after(item, new_item); + cmd_list_free(pr->cmdlist); + break; } - new_item = cmdq_get_command(cmdlist, NULL, &shared->mouse, 0); - cmdq_insert_after(item, new_item); - cmd_list_free(cmdlist); return (CMD_RETURN_NORMAL); } cdata = xcalloc(1, sizeof *cdata); - if (self->file != NULL) { - cdata->file = xstrdup(self->file); - cdata->line = self->line; - } cdata->cmd_if = xstrdup(args->argv[1]); if (args->argc == 3) cdata->cmd_else = xstrdup(args->argv[2]); else cdata->cmd_else = NULL; + memcpy(&cdata->mouse, m, sizeof cdata->mouse); cdata->client = item->client; if (cdata->client != NULL) @@ -118,8 +128,17 @@ cdata->item = item; else cdata->item = NULL; - memcpy(&cdata->mouse, &shared->mouse, sizeof cdata->mouse); + memset(&cdata->input, 0, sizeof cdata->input); + if (self->file != NULL) + cdata->input.file = xstrdup(self->file); + cdata->input.line = self->line; + cdata->input.item = cdata->item; + cdata->input.c = c; + if (cdata->input.c != NULL) + cdata->input.c->references++; + cmd_find_copy_state(&cdata->input.fs, &item->target); + if (job_run(shellcmd, s, server_client_get_cwd(item->client, s), NULL, cmd_if_shell_callback, cmd_if_shell_free, cdata, 0) == NULL) { cmdq_error(item, "failed to run command: %s", shellcmd); @@ -139,11 +158,11 @@ { struct cmd_if_shell_data *cdata = job_get_data(job); struct client *c = cdata->client; - struct cmd_list *cmdlist; + struct mouse_event *m = &cdata->mouse; struct cmdq_item *new_item; - char *cause, *cmd, *file = cdata->file; - u_int line = cdata->line; + char *cmd; int status; + struct cmd_parse_result *pr; status = job_get_status(job); if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) @@ -153,17 +172,20 @@ if (cmd == NULL) goto out; - cmdlist = cmd_string_parse(cmd, file, line, &cause); - if (cmdlist == NULL) { - if (cause != NULL && cdata->item != NULL) - cmdq_error(cdata->item, "%s", cause); - free(cause); + pr = cmd_parse_from_string(cmd, &cdata->input); + switch (pr->status) { + case CMD_PARSE_EMPTY: new_item = NULL; - } else { - new_item = cmdq_get_command(cmdlist, NULL, &cdata->mouse, 0); - cmd_list_free(cmdlist); + break; + case CMD_PARSE_ERROR: + new_item = cmdq_get_error(pr->error); + free(pr->error); + break; + case CMD_PARSE_SUCCESS: + new_item = cmdq_get_command(pr->cmdlist, NULL, m, 0); + cmd_list_free(pr->cmdlist); + break; } - if (new_item != NULL) { if (cdata->item == NULL) cmdq_append(c, new_item); @@ -187,6 +209,9 @@ free(cdata->cmd_else); free(cdata->cmd_if); - free(cdata->file); + if (cdata->input.c != NULL) + server_client_unref(cdata->input.c); + free((void *)cdata->input.file); + free(cdata); }