xref: /netbsd-src/external/bsd/tmux/dist/cmd-confirm-before.c (revision f8cf1a9151c7af1cb0bd8b09c13c66bca599c027)
15494e770Schristos /* $OpenBSD$ */
2698d5317Sjmmv 
3698d5317Sjmmv /*
4698d5317Sjmmv  * Copyright (c) 2009 Tiago Cunha <me@tiagocunha.org>
5698d5317Sjmmv  *
6698d5317Sjmmv  * Permission to use, copy, modify, and distribute this software for any
7698d5317Sjmmv  * purpose with or without fee is hereby granted, provided that the above
8698d5317Sjmmv  * copyright notice and this permission notice appear in all copies.
9698d5317Sjmmv  *
10698d5317Sjmmv  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11698d5317Sjmmv  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12698d5317Sjmmv  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13698d5317Sjmmv  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14698d5317Sjmmv  * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
15698d5317Sjmmv  * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
16698d5317Sjmmv  * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17698d5317Sjmmv  */
18698d5317Sjmmv 
195494e770Schristos #include <sys/types.h>
205494e770Schristos 
21698d5317Sjmmv #include <ctype.h>
22928fc495Schristos #include <stdlib.h>
23698d5317Sjmmv #include <string.h>
24698d5317Sjmmv 
25698d5317Sjmmv #include "tmux.h"
26698d5317Sjmmv 
27698d5317Sjmmv /*
28698d5317Sjmmv  * Asks for confirmation before executing a command.
29698d5317Sjmmv  */
30698d5317Sjmmv 
316db26757Swiz static enum args_parse_type	cmd_confirm_before_args_parse(struct args *,
326db26757Swiz 				    u_int, char **);
334e179ddaSchristos static enum cmd_retval		cmd_confirm_before_exec(struct cmd *,
344e179ddaSchristos 				    struct cmdq_item *);
35698d5317Sjmmv 
36c9ad075bSchristos static int	cmd_confirm_before_callback(struct client *, void *,
37c9ad075bSchristos 		    const char *, int);
384e179ddaSchristos static void	cmd_confirm_before_free(void *);
39698d5317Sjmmv 
40698d5317Sjmmv const struct cmd_entry cmd_confirm_before_entry = {
41ed4e6cd4Schristos 	.name = "confirm-before",
42ed4e6cd4Schristos 	.alias = "confirm",
43ed4e6cd4Schristos 
44c23f9150Swiz 	.args = { "bc:p:t:y", 1, 1, cmd_confirm_before_args_parse },
45c23f9150Swiz 	.usage = "[-by] [-c confirm_key] [-p prompt] " CMD_TARGET_CLIENT_USAGE
46c23f9150Swiz 		 " command",
47ed4e6cd4Schristos 
489fb66d81Schristos 	.flags = CMD_CLIENT_TFLAG,
49ed4e6cd4Schristos 	.exec = cmd_confirm_before_exec
50698d5317Sjmmv };
51698d5317Sjmmv 
52698d5317Sjmmv struct cmd_confirm_before_data {
536db26757Swiz 	struct cmdq_item	*item;
546db26757Swiz 	struct cmd_list		*cmdlist;
55c23f9150Swiz 	u_char			 confirm_key;
56c23f9150Swiz 	int			 default_yes;
57698d5317Sjmmv };
58698d5317Sjmmv 
596db26757Swiz static enum args_parse_type
606db26757Swiz cmd_confirm_before_args_parse(__unused struct args *args, __unused u_int idx,
616db26757Swiz     __unused char **cause)
626db26757Swiz {
636db26757Swiz 	return (ARGS_PARSE_COMMANDS_OR_STRING);
646db26757Swiz }
656db26757Swiz 
664e179ddaSchristos static enum cmd_retval
674e179ddaSchristos cmd_confirm_before_exec(struct cmd *self, struct cmdq_item *item)
68698d5317Sjmmv {
699fb66d81Schristos 	struct args			*args = cmd_get_args(self);
70698d5317Sjmmv 	struct cmd_confirm_before_data	*cdata;
719fb66d81Schristos 	struct client			*tc = cmdq_get_target_client(item);
729fb66d81Schristos 	struct cmd_find_state		*target = cmdq_get_target(item);
736db26757Swiz 	char				*new_prompt;
74c23f9150Swiz 	const char			*confirm_key, *prompt, *cmd;
756db26757Swiz 	int				 wait = !args_has(args, 'b');
766db26757Swiz 
776db26757Swiz 	cdata = xcalloc(1, sizeof *cdata);
786db26757Swiz 	cdata->cmdlist = args_make_commands_now(self, item, 0, 1);
79*f8cf1a91Swiz 	if (cdata->cmdlist == NULL) {
80*f8cf1a91Swiz 		free(cdata);
816db26757Swiz 		return (CMD_RETURN_ERROR);
82*f8cf1a91Swiz 	}
836db26757Swiz 
846db26757Swiz 	if (wait)
856db26757Swiz 		cdata->item = item;
86698d5317Sjmmv 
87c23f9150Swiz 	cdata->default_yes = args_has(args, 'y');
88c23f9150Swiz 	if ((confirm_key = args_get(args, 'c')) != NULL) {
89c23f9150Swiz 		if (confirm_key[1] == '\0' &&
90c23f9150Swiz 		    confirm_key[0] > 31 &&
91c23f9150Swiz 		    confirm_key[0] < 127)
92c23f9150Swiz 			cdata->confirm_key = confirm_key[0];
93c23f9150Swiz 		else {
94c23f9150Swiz 			cmdq_error(item, "invalid confirm key");
95*f8cf1a91Swiz 			free(cdata);
96c23f9150Swiz 			return (CMD_RETURN_ERROR);
97c23f9150Swiz 		}
98c23f9150Swiz 	}
99c23f9150Swiz 	else
100c23f9150Swiz 		cdata->confirm_key = 'y';
101c23f9150Swiz 
102d530c4d0Sjmmv 	if ((prompt = args_get(args, 'p')) != NULL)
103d530c4d0Sjmmv 		xasprintf(&new_prompt, "%s ", prompt);
104d530c4d0Sjmmv 	else {
1056db26757Swiz 		cmd = cmd_get_entry(cmd_list_first(cdata->cmdlist))->name;
106*f8cf1a91Swiz 		xasprintf(&new_prompt, "Confirm '%s'? (%c/n) ", cmd,
107*f8cf1a91Swiz 		    cdata->confirm_key);
108d530c4d0Sjmmv 	}
109698d5317Sjmmv 
1109fb66d81Schristos 	status_prompt_set(tc, target, new_prompt, NULL,
111698d5317Sjmmv 	    cmd_confirm_before_callback, cmd_confirm_before_free, cdata,
1126db26757Swiz 	    PROMPT_SINGLE, PROMPT_TYPE_COMMAND);
113928fc495Schristos 	free(new_prompt);
1146db26757Swiz 
1156db26757Swiz 	if (!wait)
116928fc495Schristos 		return (CMD_RETURN_NORMAL);
1176db26757Swiz 	return (CMD_RETURN_WAIT);
118698d5317Sjmmv }
119698d5317Sjmmv 
1204e179ddaSchristos static int
121c9ad075bSchristos cmd_confirm_before_callback(struct client *c, void *data, const char *s,
122c9ad075bSchristos     __unused int done)
123698d5317Sjmmv {
124698d5317Sjmmv 	struct cmd_confirm_before_data	*cdata = data;
1256db26757Swiz 	struct cmdq_item		*item = cdata->item, *new_item;
1266db26757Swiz 	int				 retcode = 1;
127698d5317Sjmmv 
128928fc495Schristos 	if (c->flags & CLIENT_DEAD)
1296db26757Swiz 		goto out;
130928fc495Schristos 
131c23f9150Swiz 	if (s == NULL)
1326db26757Swiz 		goto out;
133c23f9150Swiz 	if (s[0] != cdata->confirm_key && (s[0] != '\0' || !cdata->default_yes))
1346db26757Swiz 		goto out;
1356db26757Swiz 	retcode = 0;
136698d5317Sjmmv 
1376db26757Swiz 	if (item == NULL) {
1386db26757Swiz 		new_item = cmdq_get_command(cdata->cmdlist, NULL);
1396db26757Swiz 		cmdq_append(c, new_item);
1406db26757Swiz 	} else {
1416db26757Swiz 		new_item = cmdq_get_command(cdata->cmdlist,
1426db26757Swiz 		    cmdq_get_state(item));
1436db26757Swiz 		cmdq_insert_after(item, new_item);
1446483eba0Schristos 	}
145698d5317Sjmmv 
1466db26757Swiz out:
1476db26757Swiz 	if (item != NULL) {
1486db26757Swiz 		if (cmdq_get_client(item) != NULL &&
1496db26757Swiz 		    cmdq_get_client(item)->session == NULL)
1506db26757Swiz 			cmdq_get_client(item)->retval = retcode;
1516db26757Swiz 		cmdq_continue(item);
1526db26757Swiz 	}
153698d5317Sjmmv 	return (0);
154698d5317Sjmmv }
155698d5317Sjmmv 
1564e179ddaSchristos static void
157698d5317Sjmmv cmd_confirm_before_free(void *data)
158698d5317Sjmmv {
159698d5317Sjmmv 	struct cmd_confirm_before_data	*cdata = data;
160928fc495Schristos 
1616db26757Swiz 	cmd_list_free(cdata->cmdlist);
162928fc495Schristos 	free(cdata);
163698d5317Sjmmv }
164