xref: /openbsd-src/usr.bin/tmux/arguments.c (revision 8550894424f8a4aa4aafb6cd57229dd6ed7cd9dd)
1 /* $OpenBSD: arguments.c,v 1.58 2023/01/08 23:34:46 nicm Exp $ */
2 
3 /*
4  * Copyright (c) 2010 Nicholas Marriott <nicholas.marriott@gmail.com>
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 #include <vis.h>
25 
26 #include "tmux.h"
27 
28 /*
29  * Manipulate command arguments.
30  */
31 
32 /* List of argument values. */
33 TAILQ_HEAD(args_values, args_value);
34 
35 /* Single arguments flag. */
36 struct args_entry {
37 	u_char			 flag;
38 	struct args_values	 values;
39 	u_int			 count;
40 
41 	int			 flags;
42 #define ARGS_ENTRY_OPTIONAL_VALUE 0x1
43 
44 	RB_ENTRY(args_entry)	 entry;
45 };
46 
47 /* Parsed argument flags and values. */
48 struct args {
49 	struct args_tree	 tree;
50 	u_int			 count;
51 	struct args_value	*values;
52 };
53 
54 /* Prepared command state. */
55 struct args_command_state {
56 	struct cmd_list		*cmdlist;
57 	char			*cmd;
58 	struct cmd_parse_input	 pi;
59 };
60 
61 static struct args_entry	*args_find(struct args *, u_char);
62 
63 static int	args_cmp(struct args_entry *, struct args_entry *);
64 RB_GENERATE_STATIC(args_tree, args_entry, entry, args_cmp);
65 
66 /* Arguments tree comparison function. */
67 static int
68 args_cmp(struct args_entry *a1, struct args_entry *a2)
69 {
70 	return (a1->flag - a2->flag);
71 }
72 
73 /* Find a flag in the arguments tree. */
74 static struct args_entry *
75 args_find(struct args *args, u_char flag)
76 {
77 	struct args_entry	entry;
78 
79 	entry.flag = flag;
80 	return (RB_FIND(args_tree, &args->tree, &entry));
81 }
82 
83 /* Copy value. */
84 static void
85 args_copy_value(struct args_value *to, struct args_value *from)
86 {
87 	to->type = from->type;
88 	switch (from->type) {
89 	case ARGS_NONE:
90 		break;
91 	case ARGS_COMMANDS:
92 		to->cmdlist = from->cmdlist;
93 		to->cmdlist->references++;
94 		break;
95 	case ARGS_STRING:
96 		to->string = xstrdup(from->string);
97 		break;
98 	}
99 }
100 
101 /* Get value as string. */
102 static const char *
103 args_value_as_string(struct args_value *value)
104 {
105 	switch (value->type) {
106 	case ARGS_NONE:
107 		return ("");
108 	case ARGS_COMMANDS:
109 		if (value->cached == NULL)
110 			value->cached = cmd_list_print(value->cmdlist, 0);
111 		return (value->cached);
112 	case ARGS_STRING:
113 		return (value->string);
114 	}
115 	fatalx("unexpected argument type");
116 }
117 
118 /* Create an empty arguments set. */
119 struct args *
120 args_create(void)
121 {
122 	struct args	 *args;
123 
124 	args = xcalloc(1, sizeof *args);
125 	RB_INIT(&args->tree);
126 	return (args);
127 }
128 
129 /* Parse a single flag. */
130 static int
131 args_parse_flag_argument(struct args_value *values, u_int count, char **cause,
132     struct args *args, u_int *i, const char *string, int flag,
133     int optional_argument)
134 {
135 	struct args_value	*argument, *new;
136 	const char		*s;
137 
138 	new = xcalloc(1, sizeof *new);
139 	if (*string != '\0') {
140 		new->type = ARGS_STRING;
141 		new->string = xstrdup(string);
142 		goto out;
143 	}
144 
145 	if (*i == count)
146 		argument = NULL;
147 	else {
148 		argument = &values[*i];
149 		if (argument->type != ARGS_STRING) {
150 			xasprintf(cause, "-%c argument must be a string", flag);
151 			return (-1);
152 		}
153 	}
154 	if (argument == NULL) {
155 		if (optional_argument) {
156 			log_debug("%s: -%c (optional)", __func__, flag);
157 			args_set(args, flag, NULL, ARGS_ENTRY_OPTIONAL_VALUE);
158 			return (0); /* either - or end */
159 		}
160 		xasprintf(cause, "-%c expects an argument", flag);
161 		return (-1);
162 	}
163 	args_copy_value(new, argument);
164 	(*i)++;
165 
166 out:
167 	s = args_value_as_string(new);
168 	log_debug("%s: -%c = %s", __func__, flag, s);
169 	args_set(args, flag, new, 0);
170 	return (0);
171 }
172 
173 /* Parse flags argument. */
174 static int
175 args_parse_flags(const struct args_parse *parse, struct args_value *values,
176     u_int count, char **cause, struct args *args, int *i)
177 {
178 	struct args_value	*value;
179 	u_char			 flag;
180 	const char		*found, *string;
181 	int			 optional_argument;
182 
183 	value = &values[*i];
184 	if (value->type != ARGS_STRING)
185 		return (1);
186 
187 	string = value->string;
188 	log_debug("%s: next %s", __func__, string);
189 	if (*string++ != '-' || *string == '\0')
190 		return (1);
191 	(*i)++;
192 	if (string[0] == '-' && string[1] == '\0')
193 		return (1);
194 
195 	for (;;) {
196 		flag = *string++;
197 		if (flag == '\0')
198 			return (0);
199 		if (flag == '?')
200 			return (-1);
201 		if (!isalnum(flag)) {
202 			xasprintf(cause, "invalid flag -%c", flag);
203 			return (-1);
204 		}
205 
206 		found = strchr(parse->template, flag);
207 		if (found == NULL) {
208 			xasprintf(cause, "unknown flag -%c", flag);
209 			return (-1);
210 		}
211 		if (found[1] != ':') {
212 			log_debug("%s: -%c", __func__, flag);
213 			args_set(args, flag, NULL, 0);
214 			continue;
215 		}
216 		optional_argument = (found[2] == ':');
217 		return (args_parse_flag_argument(values, count, cause, args, i,
218 		    string, flag, optional_argument));
219 	}
220 }
221 
222 /* Parse arguments into a new argument set. */
223 struct args *
224 args_parse(const struct args_parse *parse, struct args_value *values,
225     u_int count, char **cause)
226 {
227 	struct args		*args;
228 	u_int			 i;
229 	enum args_parse_type	 type;
230 	struct args_value	*value, *new;
231 	const char		*s;
232 	int			 stop;
233 
234 	if (count == 0)
235 		return (args_create());
236 
237 	args = args_create();
238 	for (i = 1; i < count; /* nothing */) {
239 		stop = args_parse_flags(parse, values, count, cause, args, &i);
240 		if (stop == -1) {
241 			args_free(args);
242 			return (NULL);
243 		}
244 		if (stop == 1)
245 			break;
246 	}
247 	log_debug("%s: flags end at %u of %u", __func__, i, count);
248 	if (i != count) {
249 		for (/* nothing */; i < count; i++) {
250 			value = &values[i];
251 
252 			s = args_value_as_string(value);
253 			log_debug("%s: %u = %s (type %d)", __func__, i, s,
254 			    value->type);
255 
256 			if (parse->cb != NULL) {
257 				type = parse->cb(args, args->count, cause);
258 				if (type == ARGS_PARSE_INVALID) {
259 					args_free(args);
260 					return (NULL);
261 				}
262 			} else
263 				type = ARGS_PARSE_STRING;
264 
265 			args->values = xrecallocarray(args->values,
266 			    args->count, args->count + 1, sizeof *args->values);
267 			new = &args->values[args->count++];
268 
269 			switch (type) {
270 			case ARGS_PARSE_INVALID:
271 				fatalx("unexpected argument type");
272 			case ARGS_PARSE_STRING:
273 				if (value->type != ARGS_STRING) {
274 					xasprintf(cause,
275 					    "argument %u must be \"string\"",
276 					    args->count);
277 					args_free(args);
278 					return (NULL);
279 				}
280 				args_copy_value(new, value);
281 				break;
282 			case ARGS_PARSE_COMMANDS_OR_STRING:
283 				args_copy_value(new, value);
284 				break;
285 			case ARGS_PARSE_COMMANDS:
286 				if (value->type != ARGS_COMMANDS) {
287 					xasprintf(cause,
288 					    "argument %u must be { commands }",
289 					    args->count);
290 					args_free(args);
291 					return (NULL);
292 				}
293 				args_copy_value(new, value);
294 				break;
295 			}
296 		}
297 	}
298 
299 	if (parse->lower != -1 && args->count < (u_int)parse->lower) {
300 		xasprintf(cause,
301 		    "too few arguments (need at least %u)",
302 		    parse->lower);
303 		args_free(args);
304 		return (NULL);
305 	}
306 	if (parse->upper != -1 && args->count > (u_int)parse->upper) {
307 		xasprintf(cause,
308 		    "too many arguments (need at most %u)",
309 		    parse->upper);
310 		args_free(args);
311 		return (NULL);
312 	}
313 	return (args);
314 }
315 
316 /* Copy and expand a value. */
317 static void
318 args_copy_copy_value(struct args_value *to, struct args_value *from, int argc,
319     char **argv)
320 {
321 	char	*s, *expanded;
322 	int	 i;
323 
324 	to->type = from->type;
325 	switch (from->type) {
326 	case ARGS_NONE:
327 		break;
328 	case ARGS_STRING:
329 		expanded = xstrdup(from->string);
330 		for (i = 0; i < argc; i++) {
331 			s = cmd_template_replace(expanded, argv[i], i + 1);
332 			free(expanded);
333 			expanded = s;
334 		}
335 		to->string = expanded;
336 		break;
337 	case ARGS_COMMANDS:
338 		to->cmdlist = cmd_list_copy(from->cmdlist, argc, argv);
339 		break;
340 	}
341 }
342 
343 /* Copy an arguments set. */
344 struct args *
345 args_copy(struct args *args, int argc, char **argv)
346 {
347 	struct args		*new_args;
348 	struct args_entry	*entry;
349 	struct args_value	*value, *new_value;
350 	u_int			 i;
351 
352 	cmd_log_argv(argc, argv, "%s", __func__);
353 
354 	new_args = args_create();
355 	RB_FOREACH(entry, args_tree, &args->tree) {
356 		if (TAILQ_EMPTY(&entry->values)) {
357 			for (i = 0; i < entry->count; i++)
358 				args_set(new_args, entry->flag, NULL, 0);
359 			continue;
360 		}
361 		TAILQ_FOREACH(value, &entry->values, entry) {
362 			new_value = xcalloc(1, sizeof *new_value);
363 			args_copy_copy_value(new_value, value, argc, argv);
364 			args_set(new_args, entry->flag, new_value, 0);
365 		}
366 	}
367 	if (args->count == 0)
368 		return (new_args);
369 	new_args->count = args->count;
370 	new_args->values = xcalloc(args->count, sizeof *new_args->values);
371 	for (i = 0; i < args->count; i++) {
372 		new_value = &new_args->values[i];
373 		args_copy_copy_value(new_value, &args->values[i], argc, argv);
374 	}
375 	return (new_args);
376 }
377 
378 /* Free a value. */
379 void
380 args_free_value(struct args_value *value)
381 {
382 	switch (value->type) {
383 	case ARGS_NONE:
384 		break;
385 	case ARGS_STRING:
386 		free(value->string);
387 		break;
388 	case ARGS_COMMANDS:
389 		cmd_list_free(value->cmdlist);
390 		break;
391 	}
392 	free(value->cached);
393 }
394 
395 /* Free values. */
396 void
397 args_free_values(struct args_value *values, u_int count)
398 {
399 	u_int	i;
400 
401 	for (i = 0; i < count; i++)
402 		args_free_value(&values[i]);
403 }
404 
405 /* Free an arguments set. */
406 void
407 args_free(struct args *args)
408 {
409 	struct args_entry	*entry;
410 	struct args_entry	*entry1;
411 	struct args_value	*value;
412 	struct args_value	*value1;
413 
414 	args_free_values(args->values, args->count);
415 	free(args->values);
416 
417 	RB_FOREACH_SAFE(entry, args_tree, &args->tree, entry1) {
418 		RB_REMOVE(args_tree, &args->tree, entry);
419 		TAILQ_FOREACH_SAFE(value, &entry->values, entry, value1) {
420 			TAILQ_REMOVE(&entry->values, value, entry);
421 			args_free_value(value);
422 			free(value);
423 		}
424 		free(entry);
425 	}
426 
427 	free(args);
428 }
429 
430 /* Convert arguments to vector. */
431 void
432 args_to_vector(struct args *args, int *argc, char ***argv)
433 {
434 	char	*s;
435 	u_int	 i;
436 
437 	*argc = 0;
438 	*argv = NULL;
439 
440 	for (i = 0; i < args->count; i++) {
441 		switch (args->values[i].type) {
442 		case ARGS_NONE:
443 			break;
444 		case ARGS_STRING:
445 			cmd_append_argv(argc, argv, args->values[i].string);
446 			break;
447 		case ARGS_COMMANDS:
448 			s = cmd_list_print(args->values[i].cmdlist, 0);
449 			cmd_append_argv(argc, argv, s);
450 			free(s);
451 			break;
452 		}
453 	}
454 }
455 
456 /* Convert arguments from vector. */
457 struct args_value *
458 args_from_vector(int argc, char **argv)
459 {
460 	struct args_value	*values;
461 	int			 i;
462 
463 	values = xcalloc(argc, sizeof *values);
464 	for (i = 0; i < argc; i++) {
465 		values[i].type = ARGS_STRING;
466 		values[i].string = xstrdup(argv[i]);
467 	}
468 	return (values);
469 }
470 
471 /* Add to string. */
472 static void printflike(3, 4)
473 args_print_add(char **buf, size_t *len, const char *fmt, ...)
474 {
475 	va_list	 ap;
476 	char	*s;
477 	size_t	 slen;
478 
479 	va_start(ap, fmt);
480 	slen = xvasprintf(&s, fmt, ap);
481 	va_end(ap);
482 
483 	*len += slen;
484 	*buf = xrealloc(*buf, *len);
485 
486 	strlcat(*buf, s, *len);
487 	free(s);
488 }
489 
490 /* Add value to string. */
491 static void
492 args_print_add_value(char **buf, size_t *len, struct args_value *value)
493 {
494 	char	*expanded = NULL;
495 
496 	if (**buf != '\0')
497 		args_print_add(buf, len, " ");
498 
499 	switch (value->type) {
500 	case ARGS_NONE:
501 		break;
502 	case ARGS_COMMANDS:
503 		expanded = cmd_list_print(value->cmdlist, 0);
504 		args_print_add(buf, len, "{ %s }", expanded);
505 		break;
506 	case ARGS_STRING:
507 		expanded = args_escape(value->string);
508 		args_print_add(buf, len, "%s", expanded);
509 		break;
510 	}
511 	free(expanded);
512 }
513 
514 /* Print a set of arguments. */
515 char *
516 args_print(struct args *args)
517 {
518 	size_t			 len;
519 	char			*buf;
520 	u_int			 i, j;
521 	struct args_entry	*entry;
522 	struct args_entry	*last = NULL;
523 	struct args_value	*value;
524 
525 	len = 1;
526 	buf = xcalloc(1, len);
527 
528 	/* Process the flags first. */
529 	RB_FOREACH(entry, args_tree, &args->tree) {
530 		if (entry->flags & ARGS_ENTRY_OPTIONAL_VALUE)
531 			continue;
532 		if (!TAILQ_EMPTY(&entry->values))
533 			continue;
534 
535 		if (*buf == '\0')
536 			args_print_add(&buf, &len, "-");
537 		for (j = 0; j < entry->count; j++)
538 			args_print_add(&buf, &len, "%c", entry->flag);
539 	}
540 
541 	/* Then the flags with arguments. */
542 	RB_FOREACH(entry, args_tree, &args->tree) {
543 		if (entry->flags & ARGS_ENTRY_OPTIONAL_VALUE) {
544 			if (*buf != '\0')
545 				args_print_add(&buf, &len, " -%c", entry->flag);
546 			else
547 				args_print_add(&buf, &len, "-%c", entry->flag);
548 			last = entry;
549 			continue;
550 		}
551 		if (TAILQ_EMPTY(&entry->values))
552 			continue;
553 		TAILQ_FOREACH(value, &entry->values, entry) {
554 			if (*buf != '\0')
555 				args_print_add(&buf, &len, " -%c", entry->flag);
556 			else
557 				args_print_add(&buf, &len, "-%c", entry->flag);
558 			args_print_add_value(&buf, &len, value);
559 		}
560 		last = entry;
561 	}
562 	if (last && (last->flags & ARGS_ENTRY_OPTIONAL_VALUE))
563 		args_print_add(&buf, &len, " --");
564 
565 	/* And finally the argument vector. */
566 	for (i = 0; i < args->count; i++)
567 		args_print_add_value(&buf, &len, &args->values[i]);
568 
569 	return (buf);
570 }
571 
572 /* Escape an argument. */
573 char *
574 args_escape(const char *s)
575 {
576 	static const char	 dquoted[] = " #';${}%";
577 	static const char	 squoted[] = " \"";
578 	char			*escaped, *result;
579 	int			 flags, quotes = 0;
580 
581 	if (*s == '\0') {
582 		xasprintf(&result, "''");
583 		return (result);
584 	}
585 	if (s[strcspn(s, dquoted)] != '\0')
586 		quotes = '"';
587 	else if (s[strcspn(s, squoted)] != '\0')
588 		quotes = '\'';
589 
590 	if (s[0] != ' ' &&
591 	    s[1] == '\0' &&
592 	    (quotes != 0 || s[0] == '~')) {
593 		xasprintf(&escaped, "\\%c", s[0]);
594 		return (escaped);
595 	}
596 
597 	flags = VIS_OCTAL|VIS_CSTYLE|VIS_TAB|VIS_NL;
598 	if (quotes == '"')
599 		flags |= VIS_DQ;
600 	utf8_stravis(&escaped, s, flags);
601 
602 	if (quotes == '\'')
603 		xasprintf(&result, "'%s'", escaped);
604 	else if (quotes == '"') {
605 		if (*escaped == '~')
606 			xasprintf(&result, "\"\\%s\"", escaped);
607 		else
608 			xasprintf(&result, "\"%s\"", escaped);
609 	} else {
610 		if (*escaped == '~')
611 			xasprintf(&result, "\\%s", escaped);
612 		else
613 			result = xstrdup(escaped);
614 	}
615 	free(escaped);
616 	return (result);
617 }
618 
619 /* Return if an argument is present. */
620 int
621 args_has(struct args *args, u_char flag)
622 {
623 	struct args_entry	*entry;
624 
625 	entry = args_find(args, flag);
626 	if (entry == NULL)
627 		return (0);
628 	return (entry->count);
629 }
630 
631 /* Set argument value in the arguments tree. */
632 void
633 args_set(struct args *args, u_char flag, struct args_value *value, int flags)
634 {
635 	struct args_entry	*entry;
636 
637 	entry = args_find(args, flag);
638 	if (entry == NULL) {
639 		entry = xcalloc(1, sizeof *entry);
640 		entry->flag = flag;
641 		entry->count = 1;
642 		entry->flags = flags;
643 		TAILQ_INIT(&entry->values);
644 		RB_INSERT(args_tree, &args->tree, entry);
645 	} else
646 		entry->count++;
647 	if (value != NULL && value->type != ARGS_NONE)
648 		TAILQ_INSERT_TAIL(&entry->values, value, entry);
649 }
650 
651 /* Get argument value. Will be NULL if it isn't present. */
652 const char *
653 args_get(struct args *args, u_char flag)
654 {
655 	struct args_entry	*entry;
656 
657 	if ((entry = args_find(args, flag)) == NULL)
658 		return (NULL);
659 	if (TAILQ_EMPTY(&entry->values))
660 		return (NULL);
661 	return (TAILQ_LAST(&entry->values, args_values)->string);
662 }
663 
664 /* Get first argument. */
665 u_char
666 args_first(struct args *args, struct args_entry **entry)
667 {
668 	*entry = RB_MIN(args_tree, &args->tree);
669 	if (*entry == NULL)
670 		return (0);
671 	return ((*entry)->flag);
672 }
673 
674 /* Get next argument. */
675 u_char
676 args_next(struct args_entry **entry)
677 {
678 	*entry = RB_NEXT(args_tree, &args->tree, *entry);
679 	if (*entry == NULL)
680 		return (0);
681 	return ((*entry)->flag);
682 }
683 
684 /* Get argument count. */
685 u_int
686 args_count(struct args *args)
687 {
688 	return (args->count);
689 }
690 
691 /* Get argument values. */
692 struct args_value *
693 args_values(struct args *args)
694 {
695 	return (args->values);
696 }
697 
698 /* Get argument value. */
699 struct args_value *
700 args_value(struct args *args, u_int idx)
701 {
702 	if (idx >= args->count)
703 		return (NULL);
704 	return (&args->values[idx]);
705 }
706 
707 /* Return argument as string. */
708 const char *
709 args_string(struct args *args, u_int idx)
710 {
711 	if (idx >= args->count)
712 		return (NULL);
713 	return (args_value_as_string(&args->values[idx]));
714 }
715 
716 /* Make a command now. */
717 struct cmd_list *
718 args_make_commands_now(struct cmd *self, struct cmdq_item *item, u_int idx,
719     int expand)
720 {
721 	struct args_command_state	*state;
722 	char				*error;
723 	struct cmd_list			*cmdlist;
724 
725 	state = args_make_commands_prepare(self, item, idx, NULL, 0, expand);
726 	cmdlist = args_make_commands(state, 0, NULL, &error);
727 	if (cmdlist == NULL) {
728 		cmdq_error(item, "%s", error);
729 		free(error);
730 	}
731 	else
732 		cmdlist->references++;
733 	args_make_commands_free(state);
734 	return (cmdlist);
735 }
736 
737 /* Save bits to make a command later. */
738 struct args_command_state *
739 args_make_commands_prepare(struct cmd *self, struct cmdq_item *item, u_int idx,
740     const char *default_command, int wait, int expand)
741 {
742 	struct args			*args = cmd_get_args(self);
743 	struct cmd_find_state		*target = cmdq_get_target(item);
744 	struct client			*tc = cmdq_get_target_client(item);
745 	struct args_value		*value;
746 	struct args_command_state	*state;
747 	const char			*cmd;
748 
749 	state = xcalloc(1, sizeof *state);
750 
751 	if (idx < args->count) {
752 		value = &args->values[idx];
753 		if (value->type == ARGS_COMMANDS) {
754 			state->cmdlist = value->cmdlist;
755 			state->cmdlist->references++;
756 			return (state);
757 		}
758 		cmd = value->string;
759 	} else {
760 		if (default_command == NULL)
761 			fatalx("argument out of range");
762 		cmd = default_command;
763 	}
764 
765 
766 	if (expand)
767 		state->cmd = format_single_from_target(item, cmd);
768 	else
769 		state->cmd = xstrdup(cmd);
770 	log_debug("%s: %s", __func__, state->cmd);
771 
772 	if (wait)
773 		state->pi.item = item;
774 	cmd_get_source(self, &state->pi.file, &state->pi.line);
775 	state->pi.c = tc;
776 	if (state->pi.c != NULL)
777 		state->pi.c->references++;
778 	cmd_find_copy_state(&state->pi.fs, target);
779 
780 	return (state);
781 }
782 
783 /* Return argument as command. */
784 struct cmd_list *
785 args_make_commands(struct args_command_state *state, int argc, char **argv,
786     char **error)
787 {
788 	struct cmd_parse_result	*pr;
789 	char			*cmd, *new_cmd;
790 	int			 i;
791 
792 	if (state->cmdlist != NULL) {
793 		if (argc == 0)
794 			return (state->cmdlist);
795 		return (cmd_list_copy(state->cmdlist, argc, argv));
796 	}
797 
798 	cmd = xstrdup(state->cmd);
799 	for (i = 0; i < argc; i++) {
800 		new_cmd = cmd_template_replace(cmd, argv[i], i + 1);
801 		log_debug("%s: %%%u %s: %s", __func__, i + 1, argv[i], new_cmd);
802 		free(cmd);
803 		cmd = new_cmd;
804 	}
805 	log_debug("%s: %s", __func__, cmd);
806 
807 	pr = cmd_parse_from_string(cmd, &state->pi);
808 	free(cmd);
809 	switch (pr->status) {
810 	case CMD_PARSE_ERROR:
811 		*error = pr->error;
812 		return (NULL);
813 	case CMD_PARSE_SUCCESS:
814 		return (pr->cmdlist);
815 	}
816 	fatalx("invalid parse return state");
817 }
818 
819 /* Free commands state. */
820 void
821 args_make_commands_free(struct args_command_state *state)
822 {
823 	if (state->cmdlist != NULL)
824 		cmd_list_free(state->cmdlist);
825 	if (state->pi.c != NULL)
826 		server_client_unref(state->pi.c);
827 	free(state->cmd);
828 	free(state);
829 }
830 
831 /* Get prepared command. */
832 char *
833 args_make_commands_get_command(struct args_command_state *state)
834 {
835 	struct cmd	*first;
836 	int		 n;
837 	char		*s;
838 
839 	if (state->cmdlist != NULL) {
840 		first = cmd_list_first(state->cmdlist);
841 		if (first == NULL)
842 			return (xstrdup(""));
843 		return (xstrdup(cmd_get_entry(first)->name));
844 	}
845 	n = strcspn(state->cmd, " ,");
846 	xasprintf(&s, "%.*s", n, state->cmd);
847 	return (s);
848 }
849 
850 /* Get first value in argument. */
851 struct args_value *
852 args_first_value(struct args *args, u_char flag)
853 {
854 	struct args_entry	*entry;
855 
856 	if ((entry = args_find(args, flag)) == NULL)
857 		return (NULL);
858 	return (TAILQ_FIRST(&entry->values));
859 }
860 
861 /* Get next value in argument. */
862 struct args_value *
863 args_next_value(struct args_value *value)
864 {
865 	return (TAILQ_NEXT(value, entry));
866 }
867 
868 /* Convert an argument value to a number. */
869 long long
870 args_strtonum(struct args *args, u_char flag, long long minval,
871     long long maxval, char **cause)
872 {
873 	const char		*errstr;
874 	long long		 ll;
875 	struct args_entry	*entry;
876 	struct args_value	*value;
877 
878 	if ((entry = args_find(args, flag)) == NULL) {
879 		*cause = xstrdup("missing");
880 		return (0);
881 	}
882 	value = TAILQ_LAST(&entry->values, args_values);
883 	if (value == NULL ||
884 	    value->type != ARGS_STRING ||
885 	    value->string == NULL) {
886 		*cause = xstrdup("missing");
887 		return (0);
888 	}
889 
890 	ll = strtonum(value->string, minval, maxval, &errstr);
891 	if (errstr != NULL) {
892 		*cause = xstrdup(errstr);
893 		return (0);
894 	}
895 
896 	*cause = NULL;
897 	return (ll);
898 }
899 
900 /* Convert an argument value to a number, and expand formats. */
901 long long
902 args_strtonum_and_expand(struct args *args, u_char flag, long long minval,
903     long long maxval, struct cmdq_item *item, char **cause)
904 {
905 	const char		*errstr;
906 	char			*formatted;
907 	long long		 ll;
908 	struct args_entry	*entry;
909 	struct args_value	*value;
910 
911 	if ((entry = args_find(args, flag)) == NULL) {
912 		*cause = xstrdup("missing");
913 		return (0);
914 	}
915 	value = TAILQ_LAST(&entry->values, args_values);
916 	if (value == NULL ||
917 	    value->type != ARGS_STRING ||
918 	    value->string == NULL) {
919 		*cause = xstrdup("missing");
920 		return (0);
921 	}
922 
923 	formatted = format_single_from_target(item, value->string);
924 	ll = strtonum(formatted, minval, maxval, &errstr);
925 	free(formatted);
926 	if (errstr != NULL) {
927 		*cause = xstrdup(errstr);
928 		return (0);
929 	}
930 
931 	*cause = NULL;
932 	return (ll);
933 }
934 
935 /* Convert an argument to a number which may be a percentage. */
936 long long
937 args_percentage(struct args *args, u_char flag, long long minval,
938     long long maxval, long long curval, char **cause)
939 {
940 	const char		*value;
941 	struct args_entry	*entry;
942 
943 	if ((entry = args_find(args, flag)) == NULL) {
944 		*cause = xstrdup("missing");
945 		return (0);
946 	}
947 	if (TAILQ_EMPTY(&entry->values)) {
948 		*cause = xstrdup("empty");
949 		return (0);
950 	}
951 	value = TAILQ_LAST(&entry->values, args_values)->string;
952 	return (args_string_percentage(value, minval, maxval, curval, cause));
953 }
954 
955 /* Convert a string to a number which may be a percentage. */
956 long long
957 args_string_percentage(const char *value, long long minval, long long maxval,
958     long long curval, char **cause)
959 {
960 	const char	*errstr;
961 	long long	 ll;
962 	size_t		 valuelen = strlen(value);
963 	char		*copy;
964 
965 	if (valuelen == 0) {
966 		*cause = xstrdup("empty");
967 		return (0);
968 	}
969 	if (value[valuelen - 1] == '%') {
970 		copy = xstrdup(value);
971 		copy[valuelen - 1] = '\0';
972 
973 		ll = strtonum(copy, 0, 100, &errstr);
974 		free(copy);
975 		if (errstr != NULL) {
976 			*cause = xstrdup(errstr);
977 			return (0);
978 		}
979 		ll = (curval * ll) / 100;
980 		if (ll < minval) {
981 			*cause = xstrdup("too small");
982 			return (0);
983 		}
984 		if (ll > maxval) {
985 			*cause = xstrdup("too large");
986 			return (0);
987 		}
988 	} else {
989 		ll = strtonum(value, minval, maxval, &errstr);
990 		if (errstr != NULL) {
991 			*cause = xstrdup(errstr);
992 			return (0);
993 		}
994 	}
995 
996 	*cause = NULL;
997 	return (ll);
998 }
999 
1000 /*
1001  * Convert an argument to a number which may be a percentage, and expand
1002  * formats.
1003  */
1004 long long
1005 args_percentage_and_expand(struct args *args, u_char flag, long long minval,
1006     long long maxval, long long curval, struct cmdq_item *item, char **cause)
1007 {
1008 	const char		*value;
1009 	struct args_entry	*entry;
1010 
1011 	if ((entry = args_find(args, flag)) == NULL) {
1012 		*cause = xstrdup("missing");
1013 		return (0);
1014 	}
1015 	if (TAILQ_EMPTY(&entry->values)) {
1016 		*cause = xstrdup("empty");
1017 		return (0);
1018 	}
1019 	value = TAILQ_LAST(&entry->values, args_values)->string;
1020 	return (args_string_percentage_and_expand(value, minval, maxval, curval,
1021 		    item, cause));
1022 }
1023 
1024 /*
1025  * Convert a string to a number which may be a percentage, and expand formats.
1026  */
1027 long long
1028 args_string_percentage_and_expand(const char *value, long long minval,
1029     long long maxval, long long curval, struct cmdq_item *item, char **cause)
1030 {
1031 	const char	*errstr;
1032 	long long	 ll;
1033 	size_t		 valuelen = strlen(value);
1034 	char		*copy, *f;
1035 
1036 	if (value[valuelen - 1] == '%') {
1037 		copy = xstrdup(value);
1038 		copy[valuelen - 1] = '\0';
1039 
1040 		f = format_single_from_target(item, copy);
1041 		ll = strtonum(f, 0, 100, &errstr);
1042 		free(f);
1043 		free(copy);
1044 		if (errstr != NULL) {
1045 			*cause = xstrdup(errstr);
1046 			return (0);
1047 		}
1048 		ll = (curval * ll) / 100;
1049 		if (ll < minval) {
1050 			*cause = xstrdup("too small");
1051 			return (0);
1052 		}
1053 		if (ll > maxval) {
1054 			*cause = xstrdup("too large");
1055 			return (0);
1056 		}
1057 	} else {
1058 		f = format_single_from_target(item, value);
1059 		ll = strtonum(f, minval, maxval, &errstr);
1060 		free(f);
1061 		if (errstr != NULL) {
1062 			*cause = xstrdup(errstr);
1063 			return (0);
1064 		}
1065 	}
1066 
1067 	*cause = NULL;
1068 	return (ll);
1069 }
1070