4 * Copyright (c) 2008 Nicholas Marriott <nicholas.marriott@gmail.com>
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.
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.
19 #include <sys/types.h>
29 * Prompt for command in client.
32 static enum args_parse_type
cmd_command_prompt_args_parse(struct args
*,
34 static enum cmd_retval
cmd_command_prompt_exec(struct cmd
*,
37 static int cmd_command_prompt_callback(struct client
*, void *,
39 static void cmd_command_prompt_free(void *);
41 const struct cmd_entry cmd_command_prompt_entry
= {
42 .name
= "command-prompt",
45 .args
= { "1bFkiI:Np:t:T:", 0, 1, cmd_command_prompt_args_parse
},
46 .usage
= "[-1bFkiN] [-I inputs] [-p prompts] " CMD_TARGET_CLIENT_USAGE
47 " [-T type] [template]",
49 .flags
= CMD_CLIENT_TFLAG
,
50 .exec
= cmd_command_prompt_exec
53 struct cmd_command_prompt_prompt
{
58 struct cmd_command_prompt_cdata
{
59 struct cmdq_item
*item
;
60 struct args_command_state
*state
;
63 enum prompt_type prompt_type
;
65 struct cmd_command_prompt_prompt
*prompts
;
73 static enum args_parse_type
74 cmd_command_prompt_args_parse(__unused
struct args
*args
, __unused u_int idx
,
75 __unused
char **cause
)
77 return (ARGS_PARSE_COMMANDS_OR_STRING
);
80 static enum cmd_retval
81 cmd_command_prompt_exec(struct cmd
*self
, struct cmdq_item
*item
)
83 struct args
*args
= cmd_get_args(self
);
84 struct client
*tc
= cmdq_get_target_client(item
);
85 struct cmd_find_state
*target
= cmdq_get_target(item
);
86 const char *type
, *s
, *input
;
87 struct cmd_command_prompt_cdata
*cdata
;
88 char *tmp
, *prompts
, *prompt
, *next_prompt
;
89 char *inputs
= NULL
, *next_input
;
90 u_int count
= args_count(args
);
91 int wait
= !args_has(args
, 'b'), space
= 1;
93 if (tc
->prompt_string
!= NULL
)
94 return (CMD_RETURN_NORMAL
);
95 if (args_has(args
, 'i'))
98 cdata
= xcalloc(1, sizeof *cdata
);
101 cdata
->state
= args_make_commands_prepare(self
, item
, 0, "%1", wait
,
102 args_has(args
, 'F'));
104 if ((s
= args_get(args
, 'p')) == NULL
) {
106 tmp
= args_make_commands_get_command(cdata
->state
);
107 xasprintf(&prompts
, "(%s)", tmp
);
110 prompts
= xstrdup(":");
113 next_prompt
= prompts
;
115 next_prompt
= prompts
= xstrdup(s
);
116 if ((s
= args_get(args
, 'I')) != NULL
)
117 next_input
= inputs
= xstrdup(s
);
120 while ((prompt
= strsep(&next_prompt
, ",")) != NULL
) {
121 cdata
->prompts
= xreallocarray(cdata
->prompts
, cdata
->count
+ 1,
122 sizeof *cdata
->prompts
);
124 tmp
= xstrdup(prompt
);
126 xasprintf(&tmp
, "%s ", prompt
);
127 cdata
->prompts
[cdata
->count
].prompt
= tmp
;
129 if (next_input
!= NULL
) {
130 input
= strsep(&next_input
, ",");
135 cdata
->prompts
[cdata
->count
].input
= xstrdup(input
);
142 if ((type
= args_get(args
, 'T')) != NULL
) {
143 cdata
->prompt_type
= status_prompt_type(type
);
144 if (cdata
->prompt_type
== PROMPT_TYPE_INVALID
) {
145 cmdq_error(item
, "unknown type: %s", type
);
146 return (CMD_RETURN_ERROR
);
149 cdata
->prompt_type
= PROMPT_TYPE_COMMAND
;
151 if (args_has(args
, '1'))
152 cdata
->flags
|= PROMPT_SINGLE
;
153 else if (args_has(args
, 'N'))
154 cdata
->flags
|= PROMPT_NUMERIC
;
155 else if (args_has(args
, 'i'))
156 cdata
->flags
|= PROMPT_INCREMENTAL
;
157 else if (args_has(args
, 'k'))
158 cdata
->flags
|= PROMPT_KEY
;
159 status_prompt_set(tc
, target
, cdata
->prompts
[0].prompt
,
160 cdata
->prompts
[0].input
, cmd_command_prompt_callback
,
161 cmd_command_prompt_free
, cdata
, cdata
->flags
, cdata
->prompt_type
);
164 return (CMD_RETURN_NORMAL
);
165 return (CMD_RETURN_WAIT
);
169 cmd_command_prompt_callback(struct client
*c
, void *data
, const char *s
,
172 struct cmd_command_prompt_cdata
*cdata
= data
;
174 struct cmdq_item
*item
= cdata
->item
, *new_item
;
175 struct cmd_list
*cmdlist
;
176 struct cmd_command_prompt_prompt
*prompt
;
183 if (cdata
->flags
& PROMPT_INCREMENTAL
)
186 cmd_append_argv(&cdata
->argc
, &cdata
->argv
, s
);
187 if (++cdata
->current
!= cdata
->count
) {
188 prompt
= &cdata
->prompts
[cdata
->current
];
189 status_prompt_update(c
, prompt
->prompt
, prompt
->input
);
195 argv
= cmd_copy_argv(cdata
->argc
, cdata
->argv
);
196 cmd_append_argv(&argc
, &argv
, s
);
199 cdata
->argv
= cmd_copy_argv(argc
, argv
);
202 cmdlist
= args_make_commands(cdata
->state
, argc
, argv
, &error
);
203 if (cmdlist
== NULL
) {
204 cmdq_append(c
, cmdq_get_error(error
));
206 } else if (item
== NULL
) {
207 new_item
= cmdq_get_command(cmdlist
, NULL
);
208 cmdq_append(c
, new_item
);
210 new_item
= cmdq_get_command(cmdlist
, cmdq_get_state(item
));
211 cmdq_insert_after(item
, new_item
);
213 cmd_free_argv(argc
, argv
);
215 if (c
->prompt_inputcb
!= cmd_command_prompt_callback
)
225 cmd_command_prompt_free(void *data
)
227 struct cmd_command_prompt_cdata
*cdata
= data
;
230 for (i
= 0; i
< cdata
->count
; i
++) {
231 free(cdata
->prompts
[i
].prompt
);
232 free(cdata
->prompts
[i
].input
);
234 free(cdata
->prompts
);
235 cmd_free_argv(cdata
->argc
, cdata
->argv
);
236 args_make_commands_free(cdata
->state
);