1*f82227c0Snicm /* $OpenBSD: cmd-confirm-before.c,v 1.56 2024/11/26 15:51:48 nicm Exp $ */ 2311827fbSnicm 3311827fbSnicm /* 4311827fbSnicm * Copyright (c) 2009 Tiago Cunha <me@tiagocunha.org> 5311827fbSnicm * 6311827fbSnicm * Permission to use, copy, modify, and distribute this software for any 7311827fbSnicm * purpose with or without fee is hereby granted, provided that the above 8311827fbSnicm * copyright notice and this permission notice appear in all copies. 9311827fbSnicm * 10311827fbSnicm * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11311827fbSnicm * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12311827fbSnicm * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13311827fbSnicm * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14311827fbSnicm * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER 15311827fbSnicm * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING 16311827fbSnicm * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17311827fbSnicm */ 18311827fbSnicm 1926529d6fSnicm #include <sys/types.h> 2026529d6fSnicm 21311827fbSnicm #include <ctype.h> 227d053cf9Snicm #include <stdlib.h> 23311827fbSnicm #include <string.h> 24311827fbSnicm 25311827fbSnicm #include "tmux.h" 26311827fbSnicm 27311827fbSnicm /* 28311827fbSnicm * Asks for confirmation before executing a command. 29311827fbSnicm */ 30311827fbSnicm 31e4c0b811Snicm static enum args_parse_type cmd_confirm_before_args_parse(struct args *, 32e4c0b811Snicm u_int, char **); 3368e0a7f2Snicm static enum cmd_retval cmd_confirm_before_exec(struct cmd *, 3468e0a7f2Snicm struct cmdq_item *); 35311827fbSnicm 363bf5ffecSnicm static int cmd_confirm_before_callback(struct client *, void *, 373bf5ffecSnicm const char *, int); 38dc1f0f5fSnicm static void cmd_confirm_before_free(void *); 39311827fbSnicm 40311827fbSnicm const struct cmd_entry cmd_confirm_before_entry = { 41c057646bSnicm .name = "confirm-before", 42c057646bSnicm .alias = "confirm", 43c057646bSnicm 4496e7c398Snicm .args = { "bc:p:t:y", 1, 1, cmd_confirm_before_args_parse }, 4596e7c398Snicm .usage = "[-by] [-c confirm_key] [-p prompt] " CMD_TARGET_CLIENT_USAGE 4696e7c398Snicm " command", 47c057646bSnicm 48035dc73dSnicm .flags = CMD_CLIENT_TFLAG, 49c057646bSnicm .exec = cmd_confirm_before_exec 50311827fbSnicm }; 51311827fbSnicm 52e468f8d3Snicm struct cmd_confirm_before_data { 539597ed2aSnicm struct cmdq_item *item; 542db6a388Snicm struct cmd_list *cmdlist; 5596e7c398Snicm u_char confirm_key; 5696e7c398Snicm int default_yes; 57e468f8d3Snicm }; 58e468f8d3Snicm 59e4c0b811Snicm static enum args_parse_type 60e4c0b811Snicm cmd_confirm_before_args_parse(__unused struct args *args, __unused u_int idx, 61e4c0b811Snicm __unused char **cause) 62e4c0b811Snicm { 63e4c0b811Snicm return (ARGS_PARSE_COMMANDS_OR_STRING); 64e4c0b811Snicm } 65e4c0b811Snicm 66dc1f0f5fSnicm static enum cmd_retval 6768e0a7f2Snicm cmd_confirm_before_exec(struct cmd *self, struct cmdq_item *item) 68311827fbSnicm { 6990d7ba38Snicm struct args *args = cmd_get_args(self); 70311827fbSnicm struct cmd_confirm_before_data *cdata; 71035dc73dSnicm struct client *tc = cmdq_get_target_client(item); 7294adf770Snicm struct cmd_find_state *target = cmdq_get_target(item); 732db6a388Snicm char *new_prompt; 7496e7c398Snicm const char *confirm_key, *prompt, *cmd; 759597ed2aSnicm int wait = !args_has(args, 'b'); 76311827fbSnicm 771693b10bSnicm cdata = xcalloc(1, sizeof *cdata); 78987f865fSnicm cdata->cmdlist = args_make_commands_now(self, item, 0, 1); 7910e0aa77Snicm if (cdata->cmdlist == NULL) { 8010e0aa77Snicm free(cdata); 812db6a388Snicm return (CMD_RETURN_ERROR); 8210e0aa77Snicm } 832db6a388Snicm 842db6a388Snicm if (wait) 852db6a388Snicm cdata->item = item; 861693b10bSnicm 8796e7c398Snicm cdata->default_yes = args_has(args, 'y'); 8896e7c398Snicm if ((confirm_key = args_get(args, 'c')) != NULL) { 8996e7c398Snicm if (confirm_key[1] == '\0' && 9096e7c398Snicm confirm_key[0] > 31 && 9196e7c398Snicm confirm_key[0] < 127) 9296e7c398Snicm cdata->confirm_key = confirm_key[0]; 9396e7c398Snicm else { 9496e7c398Snicm cmdq_error(item, "invalid confirm key"); 95095d8c2eSnicm free(cdata); 9696e7c398Snicm return (CMD_RETURN_ERROR); 9796e7c398Snicm } 9896e7c398Snicm } 9996e7c398Snicm else 10096e7c398Snicm cdata->confirm_key = 'y'; 10196e7c398Snicm 1023041f374Snicm if ((prompt = args_get(args, 'p')) != NULL) 1033041f374Snicm xasprintf(&new_prompt, "%s ", prompt); 1043041f374Snicm else { 1052db6a388Snicm cmd = cmd_get_entry(cmd_list_first(cdata->cmdlist))->name; 106095d8c2eSnicm xasprintf(&new_prompt, "Confirm '%s'? (%c/n) ", cmd, 107095d8c2eSnicm cdata->confirm_key); 1083041f374Snicm } 109311827fbSnicm 11094adf770Snicm status_prompt_set(tc, target, new_prompt, NULL, 11194adf770Snicm cmd_confirm_before_callback, cmd_confirm_before_free, cdata, 112bc5a8fc2Snicm PROMPT_SINGLE, PROMPT_TYPE_COMMAND); 1137d053cf9Snicm free(new_prompt); 114d530b597Snicm 1159597ed2aSnicm if (!wait) 116175d36ccSnicm return (CMD_RETURN_NORMAL); 1179597ed2aSnicm return (CMD_RETURN_WAIT); 118311827fbSnicm } 119311827fbSnicm 120dc1f0f5fSnicm static int 1213bf5ffecSnicm cmd_confirm_before_callback(struct client *c, void *data, const char *s, 1223bf5ffecSnicm __unused int done) 123311827fbSnicm { 124311827fbSnicm struct cmd_confirm_before_data *cdata = data; 1252db6a388Snicm struct cmdq_item *item = cdata->item, *new_item; 126d530b597Snicm int retcode = 1; 127311827fbSnicm 128175d36ccSnicm if (c->flags & CLIENT_DEAD) 129d530b597Snicm goto out; 130175d36ccSnicm 13196e7c398Snicm if (s == NULL) 1329597ed2aSnicm goto out; 133*f82227c0Snicm if (s[0] != cdata->confirm_key && (s[0] != '\r' || !cdata->default_yes)) 1349597ed2aSnicm goto out; 135d530b597Snicm retcode = 0; 136311827fbSnicm 1372db6a388Snicm if (item == NULL) { 1382db6a388Snicm new_item = cmdq_get_command(cdata->cmdlist, NULL); 1392db6a388Snicm cmdq_append(c, new_item); 1402db6a388Snicm } else { 1412db6a388Snicm new_item = cmdq_get_command(cdata->cmdlist, 1422db6a388Snicm cmdq_get_state(item)); 1432db6a388Snicm cmdq_insert_after(item, new_item); 144df6ab229Snicm } 145311827fbSnicm 1469597ed2aSnicm out: 147d530b597Snicm if (item != NULL) { 148d530b597Snicm if (cmdq_get_client(item) != NULL && 149d530b597Snicm cmdq_get_client(item)->session == NULL) 150d530b597Snicm cmdq_get_client(item)->retval = retcode; 1519597ed2aSnicm cmdq_continue(item); 152d530b597Snicm } 153e468f8d3Snicm return (0); 154e468f8d3Snicm } 155e468f8d3Snicm 156dc1f0f5fSnicm static void 157e468f8d3Snicm cmd_confirm_before_free(void *data) 158e468f8d3Snicm { 159e468f8d3Snicm struct cmd_confirm_before_data *cdata = data; 160e468f8d3Snicm 1612db6a388Snicm cmd_list_free(cdata->cmdlist); 1627d053cf9Snicm free(cdata); 163311827fbSnicm } 164