cmd-confirm-before.c revision 1.22
1/* $OpenBSD: cmd-confirm-before.c,v 1.22 2014/10/20 23:27:14 nicm Exp $ */
2
3/*
4 * Copyright (c) 2009 Tiago Cunha <me@tiagocunha.org>
5 *
6 * Permission to use, copy, modify, and distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
15 * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
16 * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18
19#include <sys/types.h>
20
21#include <ctype.h>
22#include <stdlib.h>
23#include <string.h>
24
25#include "tmux.h"
26
27/*
28 * Asks for confirmation before executing a command.
29 */
30
31enum cmd_retval	 cmd_confirm_before_exec(struct cmd *, struct cmd_q *);
32
33int		 cmd_confirm_before_callback(void *, const char *);
34void		 cmd_confirm_before_free(void *);
35
36const struct cmd_entry cmd_confirm_before_entry = {
37	"confirm-before", "confirm",
38	"p:t:", 1, 1,
39	"[-p prompt] " CMD_TARGET_CLIENT_USAGE " command",
40	0,
41	cmd_confirm_before_exec
42};
43
44struct cmd_confirm_before_data {
45	char		*cmd;
46	struct client	*client;
47};
48
49enum cmd_retval
50cmd_confirm_before_exec(struct cmd *self, struct cmd_q *cmdq)
51{
52	struct args			*args = self->args;
53	struct cmd_confirm_before_data	*cdata;
54	struct client			*c;
55	char				*cmd, *copy, *new_prompt, *ptr;
56	const char			*prompt;
57
58	if ((c = cmd_find_client(cmdq, args_get(args, 't'), 0)) == NULL)
59		return (CMD_RETURN_ERROR);
60
61	if ((prompt = args_get(args, 'p')) != NULL)
62		xasprintf(&new_prompt, "%s ", prompt);
63	else {
64		ptr = copy = xstrdup(args->argv[0]);
65		cmd = strsep(&ptr, " \t");
66		xasprintf(&new_prompt, "Confirm '%s'? (y/n) ", cmd);
67		free(copy);
68	}
69
70	cdata = xmalloc(sizeof *cdata);
71	cdata->cmd = xstrdup(args->argv[0]);
72
73	cdata->client = c;
74	cdata->client->references++;
75
76	status_prompt_set(c, new_prompt, NULL,
77	    cmd_confirm_before_callback, cmd_confirm_before_free, cdata,
78	    PROMPT_SINGLE);
79
80	free(new_prompt);
81	return (CMD_RETURN_NORMAL);
82}
83
84int
85cmd_confirm_before_callback(void *data, const char *s)
86{
87	struct cmd_confirm_before_data	*cdata = data;
88	struct client			*c = cdata->client;
89	struct cmd_list			*cmdlist;
90	char				*cause;
91
92	if (c->flags & CLIENT_DEAD)
93		return (0);
94
95	if (s == NULL || *s == '\0')
96		return (0);
97	if (tolower((u_char) s[0]) != 'y' || s[1] != '\0')
98		return (0);
99
100	if (cmd_string_parse(cdata->cmd, &cmdlist, NULL, 0, &cause) != 0) {
101		if (cause != NULL) {
102			cmdq_error(c->cmdq, "%s", cause);
103			free(cause);
104		}
105		return (0);
106	}
107
108	cmdq_run(c->cmdq, cmdlist);
109	cmd_list_free(cmdlist);
110
111	return (0);
112}
113
114void
115cmd_confirm_before_free(void *data)
116{
117	struct cmd_confirm_before_data	*cdata = data;
118	struct client			*c = cdata->client;
119
120	c->references--;
121
122	free(cdata->cmd);
123	free(cdata);
124}
125