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