xref: /openbsd-src/usr.bin/tmux/options.c (revision 33a1e283d38a65aa7da3be95bd21dcccb6e464f8)
1 /* $OpenBSD: options.c,v 1.63 2021/08/11 20:49:55 nicm Exp $ */
2 
3 /*
4  * Copyright (c) 2008 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 <fnmatch.h>
23 #include <stdarg.h>
24 #include <stdlib.h>
25 #include <string.h>
26 
27 #include "tmux.h"
28 
29 /*
30  * Option handling; each option has a name, type and value and is stored in
31  * a red-black tree.
32  */
33 
34 struct options_array_item {
35 	u_int				 index;
36 	union options_value		 value;
37 	RB_ENTRY(options_array_item)	 entry;
38 };
39 static int
40 options_array_cmp(struct options_array_item *a1, struct options_array_item *a2)
41 {
42 	if (a1->index < a2->index)
43 		return (-1);
44 	if (a1->index > a2->index)
45 		return (1);
46 	return (0);
47 }
48 RB_GENERATE_STATIC(options_array, options_array_item, entry, options_array_cmp);
49 
50 struct options_entry {
51 	struct options				*owner;
52 
53 	const char				*name;
54 	const struct options_table_entry	*tableentry;
55 	union options_value			 value;
56 
57 	int					 cached;
58 	struct style				 style;
59 
60 	RB_ENTRY(options_entry)			 entry;
61 };
62 
63 struct options {
64 	RB_HEAD(options_tree, options_entry)	 tree;
65 	struct options				*parent;
66 };
67 
68 static struct options_entry	*options_add(struct options *, const char *);
69 static void			 options_remove(struct options_entry *);
70 
71 #define OPTIONS_IS_STRING(o)						\
72 	((o)->tableentry == NULL ||					\
73 	    (o)->tableentry->type == OPTIONS_TABLE_STRING)
74 #define OPTIONS_IS_NUMBER(o) \
75 	((o)->tableentry != NULL &&					\
76 	    ((o)->tableentry->type == OPTIONS_TABLE_NUMBER ||		\
77 	    (o)->tableentry->type == OPTIONS_TABLE_KEY ||		\
78 	    (o)->tableentry->type == OPTIONS_TABLE_COLOUR ||		\
79 	    (o)->tableentry->type == OPTIONS_TABLE_FLAG ||		\
80 	    (o)->tableentry->type == OPTIONS_TABLE_CHOICE))
81 #define OPTIONS_IS_COMMAND(o) \
82 	((o)->tableentry != NULL &&					\
83 	    (o)->tableentry->type == OPTIONS_TABLE_COMMAND)
84 
85 #define OPTIONS_IS_ARRAY(o)						\
86 	((o)->tableentry != NULL &&					\
87 	    ((o)->tableentry->flags & OPTIONS_TABLE_IS_ARRAY))
88 
89 static int	options_cmp(struct options_entry *, struct options_entry *);
90 RB_GENERATE_STATIC(options_tree, options_entry, entry, options_cmp);
91 
92 static int
93 options_cmp(struct options_entry *lhs, struct options_entry *rhs)
94 {
95 	return (strcmp(lhs->name, rhs->name));
96 }
97 
98 static const char *
99 options_map_name(const char *name)
100 {
101 	const struct options_name_map	*map;
102 
103 	for (map = options_other_names; map->from != NULL; map++) {
104 		if (strcmp(map->from, name) == 0)
105 			return (map->to);
106 	}
107 	return (name);
108 }
109 
110 static const struct options_table_entry *
111 options_parent_table_entry(struct options *oo, const char *s)
112 {
113 	struct options_entry	*o;
114 
115 	if (oo->parent == NULL)
116 		fatalx("no parent options for %s", s);
117 	o = options_get(oo->parent, s);
118 	if (o == NULL)
119 		fatalx("%s not in parent options", s);
120 	return (o->tableentry);
121 }
122 
123 static void
124 options_value_free(struct options_entry *o, union options_value *ov)
125 {
126 	if (OPTIONS_IS_STRING(o))
127 		free(ov->string);
128 	if (OPTIONS_IS_COMMAND(o) && ov->cmdlist != NULL)
129 		cmd_list_free(ov->cmdlist);
130 }
131 
132 static char *
133 options_value_to_string(struct options_entry *o, union options_value *ov,
134     int numeric)
135 {
136 	char	*s;
137 
138 	if (OPTIONS_IS_COMMAND(o))
139 		return (cmd_list_print(ov->cmdlist, 0));
140 	if (OPTIONS_IS_NUMBER(o)) {
141 		switch (o->tableentry->type) {
142 		case OPTIONS_TABLE_NUMBER:
143 			xasprintf(&s, "%lld", ov->number);
144 			break;
145 		case OPTIONS_TABLE_KEY:
146 			s = xstrdup(key_string_lookup_key(ov->number, 0));
147 			break;
148 		case OPTIONS_TABLE_COLOUR:
149 			s = xstrdup(colour_tostring(ov->number));
150 			break;
151 		case OPTIONS_TABLE_FLAG:
152 			if (numeric)
153 				xasprintf(&s, "%lld", ov->number);
154 			else
155 				s = xstrdup(ov->number ? "on" : "off");
156 			break;
157 		case OPTIONS_TABLE_CHOICE:
158 			s = xstrdup(o->tableentry->choices[ov->number]);
159 			break;
160 		default:
161 			fatalx("not a number option type");
162 		}
163 		return (s);
164 	}
165 	if (OPTIONS_IS_STRING(o))
166 		return (xstrdup(ov->string));
167 	return (xstrdup(""));
168 }
169 
170 struct options *
171 options_create(struct options *parent)
172 {
173 	struct options	*oo;
174 
175 	oo = xcalloc(1, sizeof *oo);
176 	RB_INIT(&oo->tree);
177 	oo->parent = parent;
178 	return (oo);
179 }
180 
181 void
182 options_free(struct options *oo)
183 {
184 	struct options_entry	*o, *tmp;
185 
186 	RB_FOREACH_SAFE(o, options_tree, &oo->tree, tmp)
187 		options_remove(o);
188 	free(oo);
189 }
190 
191 struct options *
192 options_get_parent(struct options *oo)
193 {
194 	return (oo->parent);
195 }
196 
197 void
198 options_set_parent(struct options *oo, struct options *parent)
199 {
200 	oo->parent = parent;
201 }
202 
203 struct options_entry *
204 options_first(struct options *oo)
205 {
206 	return (RB_MIN(options_tree, &oo->tree));
207 }
208 
209 struct options_entry *
210 options_next(struct options_entry *o)
211 {
212 	return (RB_NEXT(options_tree, &oo->tree, o));
213 }
214 
215 struct options_entry *
216 options_get_only(struct options *oo, const char *name)
217 {
218 	struct options_entry	o = { .name = name }, *found;
219 
220 	found = RB_FIND(options_tree, &oo->tree, &o);
221 	if (found == NULL) {
222 		o.name = options_map_name(name);
223 		return (RB_FIND(options_tree, &oo->tree, &o));
224 	}
225 	return (found);
226 }
227 
228 struct options_entry *
229 options_get(struct options *oo, const char *name)
230 {
231 	struct options_entry	*o;
232 
233 	o = options_get_only(oo, name);
234 	while (o == NULL) {
235 		oo = oo->parent;
236 		if (oo == NULL)
237 			break;
238 		o = options_get_only(oo, name);
239 	}
240 	return (o);
241 }
242 
243 struct options_entry *
244 options_empty(struct options *oo, const struct options_table_entry *oe)
245 {
246 	struct options_entry	*o;
247 
248 	o = options_add(oo, oe->name);
249 	o->tableentry = oe;
250 
251 	if (oe->flags & OPTIONS_TABLE_IS_ARRAY)
252 		RB_INIT(&o->value.array);
253 
254 	return (o);
255 }
256 
257 struct options_entry *
258 options_default(struct options *oo, const struct options_table_entry *oe)
259 {
260 	struct options_entry	*o;
261 	union options_value	*ov;
262 	u_int			 i;
263 
264 	o = options_empty(oo, oe);
265 	ov = &o->value;
266 
267 	if (oe->flags & OPTIONS_TABLE_IS_ARRAY) {
268 		if (oe->default_arr == NULL) {
269 			options_array_assign(o, oe->default_str, NULL);
270 			return (o);
271 		}
272 		for (i = 0; oe->default_arr[i] != NULL; i++)
273 			options_array_set(o, i, oe->default_arr[i], 0, NULL);
274 		return (o);
275 	}
276 
277 	switch (oe->type) {
278 	case OPTIONS_TABLE_STRING:
279 		ov->string = xstrdup(oe->default_str);
280 		break;
281 	default:
282 		ov->number = oe->default_num;
283 		break;
284 	}
285 	return (o);
286 }
287 
288 char *
289 options_default_to_string(const struct options_table_entry *oe)
290 {
291 	char	*s;
292 
293 	switch (oe->type) {
294 	case OPTIONS_TABLE_STRING:
295 	case OPTIONS_TABLE_COMMAND:
296 		s = xstrdup(oe->default_str);
297 		break;
298 	case OPTIONS_TABLE_NUMBER:
299 		xasprintf(&s, "%lld", oe->default_num);
300 		break;
301 	case OPTIONS_TABLE_KEY:
302 		s = xstrdup(key_string_lookup_key(oe->default_num, 0));
303 		break;
304 	case OPTIONS_TABLE_COLOUR:
305 		s = xstrdup(colour_tostring(oe->default_num));
306 		break;
307 	case OPTIONS_TABLE_FLAG:
308 		s = xstrdup(oe->default_num ? "on" : "off");
309 		break;
310 	case OPTIONS_TABLE_CHOICE:
311 		s = xstrdup(oe->choices[oe->default_num]);
312 		break;
313 	default:
314 		fatalx("unknown option type");
315 	}
316 	return (s);
317 }
318 
319 static struct options_entry *
320 options_add(struct options *oo, const char *name)
321 {
322 	struct options_entry	*o;
323 
324 	o = options_get_only(oo, name);
325 	if (o != NULL)
326 		options_remove(o);
327 
328 	o = xcalloc(1, sizeof *o);
329 	o->owner = oo;
330 	o->name = xstrdup(name);
331 
332 	RB_INSERT(options_tree, &oo->tree, o);
333 	return (o);
334 }
335 
336 static void
337 options_remove(struct options_entry *o)
338 {
339 	struct options	*oo = o->owner;
340 
341 	if (OPTIONS_IS_ARRAY(o))
342 		options_array_clear(o);
343 	else
344 		options_value_free(o, &o->value);
345 	RB_REMOVE(options_tree, &oo->tree, o);
346 	free((void *)o->name);
347 	free(o);
348 }
349 
350 const char *
351 options_name(struct options_entry *o)
352 {
353 	return (o->name);
354 }
355 
356 struct options *
357 options_owner(struct options_entry *o)
358 {
359 	return (o->owner);
360 }
361 
362 const struct options_table_entry *
363 options_table_entry(struct options_entry *o)
364 {
365 	return (o->tableentry);
366 }
367 
368 static struct options_array_item *
369 options_array_item(struct options_entry *o, u_int idx)
370 {
371 	struct options_array_item	a;
372 
373 	a.index = idx;
374 	return (RB_FIND(options_array, &o->value.array, &a));
375 }
376 
377 static struct options_array_item *
378 options_array_new(struct options_entry *o, u_int idx)
379 {
380 	struct options_array_item	*a;
381 
382 	a = xcalloc(1, sizeof *a);
383 	a->index = idx;
384 	RB_INSERT(options_array, &o->value.array, a);
385 	return (a);
386 }
387 
388 static void
389 options_array_free(struct options_entry *o, struct options_array_item *a)
390 {
391 	options_value_free(o, &a->value);
392 	RB_REMOVE(options_array, &o->value.array, a);
393 	free(a);
394 }
395 
396 void
397 options_array_clear(struct options_entry *o)
398 {
399 	struct options_array_item	*a, *a1;
400 
401 	if (!OPTIONS_IS_ARRAY(o))
402 		return;
403 
404 	RB_FOREACH_SAFE(a, options_array, &o->value.array, a1)
405 		options_array_free(o, a);
406 }
407 
408 union options_value *
409 options_array_get(struct options_entry *o, u_int idx)
410 {
411 	struct options_array_item	*a;
412 
413 	if (!OPTIONS_IS_ARRAY(o))
414 		return (NULL);
415 	a = options_array_item(o, idx);
416 	if (a == NULL)
417 		return (NULL);
418 	return (&a->value);
419 }
420 
421 int
422 options_array_set(struct options_entry *o, u_int idx, const char *value,
423     int append, char **cause)
424 {
425 	struct options_array_item	*a;
426 	char				*new;
427 	struct cmd_parse_result		*pr;
428 	long long		 	 number;
429 
430 	if (!OPTIONS_IS_ARRAY(o)) {
431 		if (cause != NULL)
432 			*cause = xstrdup("not an array");
433 		return (-1);
434 	}
435 
436 	if (value == NULL) {
437 		a = options_array_item(o, idx);
438 		if (a != NULL)
439 			options_array_free(o, a);
440 		return (0);
441 	}
442 
443 	if (OPTIONS_IS_COMMAND(o)) {
444 		pr = cmd_parse_from_string(value, NULL);
445 		switch (pr->status) {
446 		case CMD_PARSE_EMPTY:
447 			if (cause != NULL)
448 				*cause = xstrdup("empty command");
449 			return (-1);
450 		case CMD_PARSE_ERROR:
451 			if (cause != NULL)
452 				*cause = pr->error;
453 			else
454 				free(pr->error);
455 			return (-1);
456 		case CMD_PARSE_SUCCESS:
457 			break;
458 		}
459 
460 		a = options_array_item(o, idx);
461 		if (a == NULL)
462 			a = options_array_new(o, idx);
463 		else
464 			options_value_free(o, &a->value);
465 		a->value.cmdlist = pr->cmdlist;
466 		return (0);
467 	}
468 
469 	if (OPTIONS_IS_STRING(o)) {
470 		a = options_array_item(o, idx);
471 		if (a != NULL && append)
472 			xasprintf(&new, "%s%s", a->value.string, value);
473 		else
474 			new = xstrdup(value);
475 		if (a == NULL)
476 			a = options_array_new(o, idx);
477 		else
478 			options_value_free(o, &a->value);
479 		a->value.string = new;
480 		return (0);
481 	}
482 
483 	if (o->tableentry->type == OPTIONS_TABLE_COLOUR) {
484 		if ((number = colour_fromstring(value)) == -1) {
485 			xasprintf(cause, "bad colour: %s", value);
486 			return (-1);
487 		}
488 		a = options_array_item(o, idx);
489 		if (a == NULL)
490 			a = options_array_new(o, idx);
491 		else
492 			options_value_free(o, &a->value);
493 		a->value.number = number;
494 		return (0);
495 	}
496 
497 	if (cause != NULL)
498 		*cause = xstrdup("wrong array type");
499 	return (-1);
500 }
501 
502 int
503 options_array_assign(struct options_entry *o, const char *s, char **cause)
504 {
505 	const char	*separator;
506 	char		*copy, *next, *string;
507 	u_int		 i;
508 
509 	separator = o->tableentry->separator;
510 	if (separator == NULL)
511 		separator = " ,";
512 	if (*separator == '\0') {
513 		if (*s == '\0')
514 			return (0);
515 		for (i = 0; i < UINT_MAX; i++) {
516 			if (options_array_item(o, i) == NULL)
517 				break;
518 		}
519 		return (options_array_set(o, i, s, 0, cause));
520 	}
521 
522 	if (*s == '\0')
523 		return (0);
524 	copy = string = xstrdup(s);
525 	while ((next = strsep(&string, separator)) != NULL) {
526 		if (*next == '\0')
527 			continue;
528 		for (i = 0; i < UINT_MAX; i++) {
529 			if (options_array_item(o, i) == NULL)
530 				break;
531 		}
532 		if (i == UINT_MAX)
533 			break;
534 		if (options_array_set(o, i, next, 0, cause) != 0) {
535 			free(copy);
536 			return (-1);
537 		}
538 	}
539 	free(copy);
540 	return (0);
541 }
542 
543 struct options_array_item *
544 options_array_first(struct options_entry *o)
545 {
546 	if (!OPTIONS_IS_ARRAY(o))
547 		return (NULL);
548 	return (RB_MIN(options_array, &o->value.array));
549 }
550 
551 struct options_array_item *
552 options_array_next(struct options_array_item *a)
553 {
554 	return (RB_NEXT(options_array, &o->value.array, a));
555 }
556 
557 u_int
558 options_array_item_index(struct options_array_item *a)
559 {
560 	return (a->index);
561 }
562 
563 union options_value *
564 options_array_item_value(struct options_array_item *a)
565 {
566 	return (&a->value);
567 }
568 
569 int
570 options_is_array(struct options_entry *o)
571 {
572 	return (OPTIONS_IS_ARRAY(o));
573 }
574 
575 int
576 options_is_string(struct options_entry *o)
577 {
578 	return (OPTIONS_IS_STRING(o));
579 }
580 
581 char *
582 options_to_string(struct options_entry *o, int idx, int numeric)
583 {
584 	struct options_array_item	*a;
585 
586 	if (OPTIONS_IS_ARRAY(o)) {
587 		if (idx == -1)
588 			return (xstrdup(""));
589 		a = options_array_item(o, idx);
590 		if (a == NULL)
591 			return (xstrdup(""));
592 		return (options_value_to_string(o, &a->value, numeric));
593 	}
594 	return (options_value_to_string(o, &o->value, numeric));
595 }
596 
597 char *
598 options_parse(const char *name, int *idx)
599 {
600 	char	*copy, *cp, *end;
601 
602 	if (*name == '\0')
603 		return (NULL);
604 	copy = xstrdup(name);
605 	if ((cp = strchr(copy, '[')) == NULL) {
606 		*idx = -1;
607 		return (copy);
608 	}
609 	end = strchr(cp + 1, ']');
610 	if (end == NULL || end[1] != '\0' || !isdigit((u_char)end[-1])) {
611 		free(copy);
612 		return (NULL);
613 	}
614 	if (sscanf(cp, "[%d]", idx) != 1 || *idx < 0) {
615 		free(copy);
616 		return (NULL);
617 	}
618 	*cp = '\0';
619 	return (copy);
620 }
621 
622 struct options_entry *
623 options_parse_get(struct options *oo, const char *s, int *idx, int only)
624 {
625 	struct options_entry	*o;
626 	char			*name;
627 
628 	name = options_parse(s, idx);
629 	if (name == NULL)
630 		return (NULL);
631 	if (only)
632 		o = options_get_only(oo, name);
633 	else
634 		o = options_get(oo, name);
635 	free(name);
636 	return (o);
637 }
638 
639 char *
640 options_match(const char *s, int *idx, int *ambiguous)
641 {
642 	const struct options_table_entry	*oe, *found;
643 	char					*parsed;
644 	const char				*name;
645 	size_t					 namelen;
646 
647 	parsed = options_parse(s, idx);
648 	if (parsed == NULL)
649 		return (NULL);
650 	if (*parsed == '@') {
651 		*ambiguous = 0;
652 		return (parsed);
653 	}
654 
655 	name = options_map_name(parsed);
656 	namelen = strlen(name);
657 
658 	found = NULL;
659 	for (oe = options_table; oe->name != NULL; oe++) {
660 		if (strcmp(oe->name, name) == 0) {
661 			found = oe;
662 			break;
663 		}
664 		if (strncmp(oe->name, name, namelen) == 0) {
665 			if (found != NULL) {
666 				*ambiguous = 1;
667 				free(parsed);
668 				return (NULL);
669 			}
670 			found = oe;
671 		}
672 	}
673 	free(parsed);
674 	if (found == NULL) {
675 		*ambiguous = 0;
676 		return (NULL);
677 	}
678 	return (xstrdup(found->name));
679 }
680 
681 struct options_entry *
682 options_match_get(struct options *oo, const char *s, int *idx, int only,
683     int *ambiguous)
684 {
685 	char			*name;
686 	struct options_entry	*o;
687 
688 	name = options_match(s, idx, ambiguous);
689 	if (name == NULL)
690 		return (NULL);
691 	*ambiguous = 0;
692 	if (only)
693 		o = options_get_only(oo, name);
694 	else
695 		o = options_get(oo, name);
696 	free(name);
697 	return (o);
698 }
699 
700 const char *
701 options_get_string(struct options *oo, const char *name)
702 {
703 	struct options_entry	*o;
704 
705 	o = options_get(oo, name);
706 	if (o == NULL)
707 		fatalx("missing option %s", name);
708 	if (!OPTIONS_IS_STRING(o))
709 		fatalx("option %s is not a string", name);
710 	return (o->value.string);
711 }
712 
713 long long
714 options_get_number(struct options *oo, const char *name)
715 {
716 	struct options_entry	*o;
717 
718 	o = options_get(oo, name);
719 	if (o == NULL)
720 		fatalx("missing option %s", name);
721 	if (!OPTIONS_IS_NUMBER(o))
722 		fatalx("option %s is not a number", name);
723 	return (o->value.number);
724 }
725 
726 struct options_entry *
727 options_set_string(struct options *oo, const char *name, int append,
728     const char *fmt, ...)
729 {
730 	struct options_entry	*o;
731 	va_list			 ap;
732 	const char		*separator = "";
733 	char			*s, *value;
734 
735 	va_start(ap, fmt);
736 	xvasprintf(&s, fmt, ap);
737 	va_end(ap);
738 
739 	o = options_get_only(oo, name);
740 	if (o != NULL && append && OPTIONS_IS_STRING(o)) {
741 		if (*name != '@') {
742 			separator = o->tableentry->separator;
743 			if (separator == NULL)
744 				separator = "";
745 		}
746 		xasprintf(&value, "%s%s%s", o->value.string, separator, s);
747 		free(s);
748 	} else
749 		value = s;
750 	if (o == NULL && *name == '@')
751 		o = options_add(oo, name);
752 	else if (o == NULL) {
753 		o = options_default(oo, options_parent_table_entry(oo, name));
754 		if (o == NULL)
755 			return (NULL);
756 	}
757 
758 	if (!OPTIONS_IS_STRING(o))
759 		fatalx("option %s is not a string", name);
760 	free(o->value.string);
761 	o->value.string = value;
762 	o->cached = 0;
763 	return (o);
764 }
765 
766 struct options_entry *
767 options_set_number(struct options *oo, const char *name, long long value)
768 {
769 	struct options_entry	*o;
770 
771 	if (*name == '@')
772 		fatalx("user option %s must be a string", name);
773 
774 	o = options_get_only(oo, name);
775 	if (o == NULL) {
776 		o = options_default(oo, options_parent_table_entry(oo, name));
777 		if (o == NULL)
778 			return (NULL);
779 	}
780 
781 	if (!OPTIONS_IS_NUMBER(o))
782 		fatalx("option %s is not a number", name);
783 	o->value.number = value;
784 	return (o);
785 }
786 
787 int
788 options_scope_from_name(struct args *args, int window,
789     const char *name, struct cmd_find_state *fs, struct options **oo,
790     char **cause)
791 {
792 	struct session				*s = fs->s;
793 	struct winlink				*wl = fs->wl;
794 	struct window_pane			*wp = fs->wp;
795 	const char				*target = args_get(args, 't');
796 	const struct options_table_entry	*oe;
797 	int					 scope = OPTIONS_TABLE_NONE;
798 
799 	if (*name == '@')
800 		return (options_scope_from_flags(args, window, fs, oo, cause));
801 
802 	for (oe = options_table; oe->name != NULL; oe++) {
803 		if (strcmp(oe->name, name) == 0)
804 			break;
805 	}
806 	if (oe->name == NULL) {
807 		xasprintf(cause, "unknown option: %s", name);
808 		return (OPTIONS_TABLE_NONE);
809 	}
810 	switch (oe->scope) {
811 	case OPTIONS_TABLE_SERVER:
812 		*oo = global_options;
813 		scope = OPTIONS_TABLE_SERVER;
814 		break;
815 	case OPTIONS_TABLE_SESSION:
816 		if (args_has(args, 'g')) {
817 			*oo = global_s_options;
818 			scope = OPTIONS_TABLE_SESSION;
819 		} else if (s == NULL && target != NULL)
820 			xasprintf(cause, "no such session: %s", target);
821 		else if (s == NULL)
822 			xasprintf(cause, "no current session");
823 		else {
824 			*oo = s->options;
825 			scope = OPTIONS_TABLE_SESSION;
826 		}
827 		break;
828 	case OPTIONS_TABLE_WINDOW|OPTIONS_TABLE_PANE:
829 		if (args_has(args, 'p')) {
830 			if (wp == NULL && target != NULL)
831 				xasprintf(cause, "no such pane: %s", target);
832 			else if (wp == NULL)
833 				xasprintf(cause, "no current pane");
834 			else {
835 				*oo = wp->options;
836 				scope = OPTIONS_TABLE_PANE;
837 			}
838 			break;
839 		}
840 		/* FALLTHROUGH */
841 	case OPTIONS_TABLE_WINDOW:
842 		if (args_has(args, 'g')) {
843 			*oo = global_w_options;
844 			scope = OPTIONS_TABLE_WINDOW;
845 		} else if (wl == NULL && target != NULL)
846 			xasprintf(cause, "no such window: %s", target);
847 		else if (wl == NULL)
848 			xasprintf(cause, "no current window");
849 		else {
850 			*oo = wl->window->options;
851 			scope = OPTIONS_TABLE_WINDOW;
852 		}
853 		break;
854 	}
855 	return (scope);
856 }
857 
858 int
859 options_scope_from_flags(struct args *args, int window,
860     struct cmd_find_state *fs, struct options **oo, char **cause)
861 {
862 	struct session		*s = fs->s;
863 	struct winlink		*wl = fs->wl;
864 	struct window_pane	*wp = fs->wp;
865 	const char		*target = args_get(args, 't');
866 
867 	if (args_has(args, 's')) {
868 		*oo = global_options;
869 		return (OPTIONS_TABLE_SERVER);
870 	}
871 
872 	if (args_has(args, 'p')) {
873 		if (wp == NULL) {
874 			if (target != NULL)
875 				xasprintf(cause, "no such pane: %s", target);
876 			else
877 				xasprintf(cause, "no current pane");
878 			return (OPTIONS_TABLE_NONE);
879 		}
880 		*oo = wp->options;
881 		return (OPTIONS_TABLE_PANE);
882 	} else if (window || args_has(args, 'w')) {
883 		if (args_has(args, 'g')) {
884 			*oo = global_w_options;
885 			return (OPTIONS_TABLE_WINDOW);
886 		}
887 		if (wl == NULL) {
888 			if (target != NULL)
889 				xasprintf(cause, "no such window: %s", target);
890 			else
891 				xasprintf(cause, "no current window");
892 			return (OPTIONS_TABLE_NONE);
893 		}
894 		*oo = wl->window->options;
895 		return (OPTIONS_TABLE_WINDOW);
896 	} else {
897 		if (args_has(args, 'g')) {
898 			*oo = global_s_options;
899 			return (OPTIONS_TABLE_SESSION);
900 		}
901 		if (s == NULL) {
902 			if (target != NULL)
903 				xasprintf(cause, "no such session: %s", target);
904 			else
905 				xasprintf(cause, "no current session");
906 			return (OPTIONS_TABLE_NONE);
907 		}
908 		*oo = s->options;
909 		return (OPTIONS_TABLE_SESSION);
910 	}
911 }
912 
913 struct style *
914 options_string_to_style(struct options *oo, const char *name,
915     struct format_tree *ft)
916 {
917 	struct options_entry	*o;
918 	const char		*s;
919 	char			*expanded;
920 
921 	o = options_get(oo, name);
922 	if (o == NULL || !OPTIONS_IS_STRING(o))
923 		return (NULL);
924 
925 	if (o->cached)
926 		return (&o->style);
927 	s = o->value.string;
928 	log_debug("%s: %s is '%s'", __func__, name, s);
929 
930 	style_set(&o->style, &grid_default_cell);
931 	o->cached = (strstr(s, "#{") == NULL);
932 
933 	if (ft != NULL && !o->cached) {
934 		expanded = format_expand(ft, s);
935 		if (style_parse(&o->style, &grid_default_cell, expanded) != 0) {
936 			free(expanded);
937 			return (NULL);
938 		}
939 		free(expanded);
940 	} else {
941 		if (style_parse(&o->style, &grid_default_cell, s) != 0)
942 			return (NULL);
943 	}
944 	return (&o->style);
945 }
946 
947 static int
948 options_from_string_check(const struct options_table_entry *oe,
949     const char *value, char **cause)
950 {
951 	struct style	sy;
952 
953 	if (oe == NULL)
954 		return (0);
955 	if (strcmp(oe->name, "default-shell") == 0 && !checkshell(value)) {
956 		xasprintf(cause, "not a suitable shell: %s", value);
957 		return (-1);
958 	}
959 	if (oe->pattern != NULL && fnmatch(oe->pattern, value, 0) != 0) {
960 		xasprintf(cause, "value is invalid: %s", value);
961 		return (-1);
962 	}
963 	if ((oe->flags & OPTIONS_TABLE_IS_STYLE) &&
964 	    strstr(value, "#{") == NULL &&
965 	    style_parse(&sy, &grid_default_cell, value) != 0) {
966 		xasprintf(cause, "invalid style: %s", value);
967 		return (-1);
968 	}
969 	return (0);
970 }
971 
972 static int
973 options_from_string_flag(struct options *oo, const char *name,
974     const char *value, char **cause)
975 {
976 	int	flag;
977 
978 	if (value == NULL || *value == '\0')
979 		flag = !options_get_number(oo, name);
980 	else if (strcmp(value, "1") == 0 ||
981 	    strcasecmp(value, "on") == 0 ||
982 	    strcasecmp(value, "yes") == 0)
983 		flag = 1;
984 	else if (strcmp(value, "0") == 0 ||
985 	    strcasecmp(value, "off") == 0 ||
986 	    strcasecmp(value, "no") == 0)
987 		flag = 0;
988 	else {
989 		xasprintf(cause, "bad value: %s", value);
990 		return (-1);
991 	}
992 	options_set_number(oo, name, flag);
993 	return (0);
994 }
995 
996 static int
997 options_from_string_choice(const struct options_table_entry *oe,
998     struct options *oo, const char *name, const char *value, char **cause)
999 {
1000 	const char	**cp;
1001 	int		  n, choice = -1;
1002 
1003 	if (value == NULL) {
1004 		choice = options_get_number(oo, name);
1005 		if (choice < 2)
1006 			choice = !choice;
1007 	} else {
1008 		n = 0;
1009 		for (cp = oe->choices; *cp != NULL; cp++) {
1010 			if (strcmp(*cp, value) == 0)
1011 				choice = n;
1012 			n++;
1013 		}
1014 		if (choice == -1) {
1015 			xasprintf(cause, "unknown value: %s", value);
1016 			return (-1);
1017 		}
1018 	}
1019 	options_set_number(oo, name, choice);
1020 	return (0);
1021 }
1022 
1023 int
1024 options_from_string(struct options *oo, const struct options_table_entry *oe,
1025     const char *name, const char *value, int append, char **cause)
1026 {
1027 	enum options_table_type	 type;
1028 	long long		 number;
1029 	const char		*errstr, *new;
1030 	char			*old;
1031 	key_code		 key;
1032 
1033 	if (oe != NULL) {
1034 		if (value == NULL &&
1035 		    oe->type != OPTIONS_TABLE_FLAG &&
1036 		    oe->type != OPTIONS_TABLE_CHOICE) {
1037 			xasprintf(cause, "empty value");
1038 			return (-1);
1039 		}
1040 		type = oe->type;
1041 	} else {
1042 		if (*name != '@') {
1043 			xasprintf(cause, "bad option name");
1044 			return (-1);
1045 		}
1046 		type = OPTIONS_TABLE_STRING;
1047 	}
1048 
1049 	switch (type) {
1050 	case OPTIONS_TABLE_STRING:
1051 		old = xstrdup(options_get_string(oo, name));
1052 		options_set_string(oo, name, append, "%s", value);
1053 
1054 		new = options_get_string(oo, name);
1055 		if (options_from_string_check(oe, new, cause) != 0) {
1056 			options_set_string(oo, name, 0, "%s", old);
1057 			free(old);
1058 			return (-1);
1059 		}
1060 		free(old);
1061 		return (0);
1062 	case OPTIONS_TABLE_NUMBER:
1063 		number = strtonum(value, oe->minimum, oe->maximum, &errstr);
1064 		if (errstr != NULL) {
1065 			xasprintf(cause, "value is %s: %s", errstr, value);
1066 			return (-1);
1067 		}
1068 		options_set_number(oo, name, number);
1069 		return (0);
1070 	case OPTIONS_TABLE_KEY:
1071 		key = key_string_lookup_string(value);
1072 		if (key == KEYC_UNKNOWN) {
1073 			xasprintf(cause, "bad key: %s", value);
1074 			return (-1);
1075 		}
1076 		options_set_number(oo, name, key);
1077 		return (0);
1078 	case OPTIONS_TABLE_COLOUR:
1079 		if ((number = colour_fromstring(value)) == -1) {
1080 			xasprintf(cause, "bad colour: %s", value);
1081 			return (-1);
1082 		}
1083 		options_set_number(oo, name, number);
1084 		return (0);
1085 	case OPTIONS_TABLE_FLAG:
1086 		return (options_from_string_flag(oo, name, value, cause));
1087 	case OPTIONS_TABLE_CHOICE:
1088 		return (options_from_string_choice(oe, oo, name, value, cause));
1089 	case OPTIONS_TABLE_COMMAND:
1090 		break;
1091 	}
1092 	return (-1);
1093 }
1094 
1095 void
1096 options_push_changes(const char *name)
1097 {
1098 	struct client		*loop;
1099 	struct session		*s;
1100 	struct window		*w;
1101 	struct window_pane	*wp;
1102 
1103 	if (strcmp(name, "automatic-rename") == 0) {
1104 		RB_FOREACH(w, windows, &windows) {
1105 			if (w->active == NULL)
1106 				continue;
1107 			if (options_get_number(w->options, "automatic-rename"))
1108 				w->active->flags |= PANE_CHANGED;
1109 		}
1110 	}
1111 	if (strcmp(name, "key-table") == 0) {
1112 		TAILQ_FOREACH(loop, &clients, entry)
1113 			server_client_set_key_table(loop, NULL);
1114 	}
1115 	if (strcmp(name, "user-keys") == 0) {
1116 		TAILQ_FOREACH(loop, &clients, entry) {
1117 			if (loop->tty.flags & TTY_OPENED)
1118 				tty_keys_build(&loop->tty);
1119 		}
1120 	}
1121 	if (strcmp(name, "status") == 0 ||
1122 	    strcmp(name, "status-interval") == 0)
1123 		status_timer_start_all();
1124 	if (strcmp(name, "monitor-silence") == 0)
1125 		alerts_reset_all();
1126 	if (strcmp(name, "window-style") == 0 ||
1127 	    strcmp(name, "window-active-style") == 0) {
1128 		RB_FOREACH(wp, window_pane_tree, &all_window_panes)
1129 			wp->flags |= PANE_STYLECHANGED;
1130 	}
1131 	if (strcmp(name, "pane-colours") == 0) {
1132 		RB_FOREACH(wp, window_pane_tree, &all_window_panes)
1133 			colour_palette_from_option(&wp->palette, wp->options);
1134 	}
1135 	if (strcmp(name, "pane-border-status") == 0) {
1136 		RB_FOREACH(w, windows, &windows)
1137 			layout_fix_panes(w, NULL);
1138 	}
1139 	RB_FOREACH(s, sessions, &sessions)
1140 		status_update_cache(s);
1141 
1142 	recalculate_sizes();
1143 	TAILQ_FOREACH(loop, &clients, entry) {
1144 		if (loop->session != NULL)
1145 			server_redraw_client(loop);
1146 	}
1147 }
1148 
1149 int
1150 options_remove_or_default(struct options_entry *o, int idx, char **cause)
1151 {
1152 	struct options	*oo = o->owner;
1153 
1154 	if (idx == -1) {
1155 		if (o->tableentry != NULL &&
1156 		    (oo == global_options ||
1157 		    oo == global_s_options ||
1158 		    oo == global_w_options))
1159 			options_default(oo, o->tableentry);
1160 		else
1161 			options_remove(o);
1162 	} else if (options_array_set(o, idx, NULL, 0, cause) != 0)
1163 		return (-1);
1164 	return (0);
1165 }
1166