xref: /openbsd-src/usr.bin/tmux/options.c (revision 824adb5411e4389b29bae28eba5c2c2bbd147f34)
1 /* $OpenBSD: options.c,v 1.64 2021/08/21 17:25:32 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_ERROR:
447 			if (cause != NULL)
448 				*cause = pr->error;
449 			else
450 				free(pr->error);
451 			return (-1);
452 		case CMD_PARSE_SUCCESS:
453 			break;
454 		}
455 
456 		a = options_array_item(o, idx);
457 		if (a == NULL)
458 			a = options_array_new(o, idx);
459 		else
460 			options_value_free(o, &a->value);
461 		a->value.cmdlist = pr->cmdlist;
462 		return (0);
463 	}
464 
465 	if (OPTIONS_IS_STRING(o)) {
466 		a = options_array_item(o, idx);
467 		if (a != NULL && append)
468 			xasprintf(&new, "%s%s", a->value.string, value);
469 		else
470 			new = xstrdup(value);
471 		if (a == NULL)
472 			a = options_array_new(o, idx);
473 		else
474 			options_value_free(o, &a->value);
475 		a->value.string = new;
476 		return (0);
477 	}
478 
479 	if (o->tableentry->type == OPTIONS_TABLE_COLOUR) {
480 		if ((number = colour_fromstring(value)) == -1) {
481 			xasprintf(cause, "bad colour: %s", value);
482 			return (-1);
483 		}
484 		a = options_array_item(o, idx);
485 		if (a == NULL)
486 			a = options_array_new(o, idx);
487 		else
488 			options_value_free(o, &a->value);
489 		a->value.number = number;
490 		return (0);
491 	}
492 
493 	if (cause != NULL)
494 		*cause = xstrdup("wrong array type");
495 	return (-1);
496 }
497 
498 int
499 options_array_assign(struct options_entry *o, const char *s, char **cause)
500 {
501 	const char	*separator;
502 	char		*copy, *next, *string;
503 	u_int		 i;
504 
505 	separator = o->tableentry->separator;
506 	if (separator == NULL)
507 		separator = " ,";
508 	if (*separator == '\0') {
509 		if (*s == '\0')
510 			return (0);
511 		for (i = 0; i < UINT_MAX; i++) {
512 			if (options_array_item(o, i) == NULL)
513 				break;
514 		}
515 		return (options_array_set(o, i, s, 0, cause));
516 	}
517 
518 	if (*s == '\0')
519 		return (0);
520 	copy = string = xstrdup(s);
521 	while ((next = strsep(&string, separator)) != NULL) {
522 		if (*next == '\0')
523 			continue;
524 		for (i = 0; i < UINT_MAX; i++) {
525 			if (options_array_item(o, i) == NULL)
526 				break;
527 		}
528 		if (i == UINT_MAX)
529 			break;
530 		if (options_array_set(o, i, next, 0, cause) != 0) {
531 			free(copy);
532 			return (-1);
533 		}
534 	}
535 	free(copy);
536 	return (0);
537 }
538 
539 struct options_array_item *
540 options_array_first(struct options_entry *o)
541 {
542 	if (!OPTIONS_IS_ARRAY(o))
543 		return (NULL);
544 	return (RB_MIN(options_array, &o->value.array));
545 }
546 
547 struct options_array_item *
548 options_array_next(struct options_array_item *a)
549 {
550 	return (RB_NEXT(options_array, &o->value.array, a));
551 }
552 
553 u_int
554 options_array_item_index(struct options_array_item *a)
555 {
556 	return (a->index);
557 }
558 
559 union options_value *
560 options_array_item_value(struct options_array_item *a)
561 {
562 	return (&a->value);
563 }
564 
565 int
566 options_is_array(struct options_entry *o)
567 {
568 	return (OPTIONS_IS_ARRAY(o));
569 }
570 
571 int
572 options_is_string(struct options_entry *o)
573 {
574 	return (OPTIONS_IS_STRING(o));
575 }
576 
577 char *
578 options_to_string(struct options_entry *o, int idx, int numeric)
579 {
580 	struct options_array_item	*a;
581 
582 	if (OPTIONS_IS_ARRAY(o)) {
583 		if (idx == -1)
584 			return (xstrdup(""));
585 		a = options_array_item(o, idx);
586 		if (a == NULL)
587 			return (xstrdup(""));
588 		return (options_value_to_string(o, &a->value, numeric));
589 	}
590 	return (options_value_to_string(o, &o->value, numeric));
591 }
592 
593 char *
594 options_parse(const char *name, int *idx)
595 {
596 	char	*copy, *cp, *end;
597 
598 	if (*name == '\0')
599 		return (NULL);
600 	copy = xstrdup(name);
601 	if ((cp = strchr(copy, '[')) == NULL) {
602 		*idx = -1;
603 		return (copy);
604 	}
605 	end = strchr(cp + 1, ']');
606 	if (end == NULL || end[1] != '\0' || !isdigit((u_char)end[-1])) {
607 		free(copy);
608 		return (NULL);
609 	}
610 	if (sscanf(cp, "[%d]", idx) != 1 || *idx < 0) {
611 		free(copy);
612 		return (NULL);
613 	}
614 	*cp = '\0';
615 	return (copy);
616 }
617 
618 struct options_entry *
619 options_parse_get(struct options *oo, const char *s, int *idx, int only)
620 {
621 	struct options_entry	*o;
622 	char			*name;
623 
624 	name = options_parse(s, idx);
625 	if (name == NULL)
626 		return (NULL);
627 	if (only)
628 		o = options_get_only(oo, name);
629 	else
630 		o = options_get(oo, name);
631 	free(name);
632 	return (o);
633 }
634 
635 char *
636 options_match(const char *s, int *idx, int *ambiguous)
637 {
638 	const struct options_table_entry	*oe, *found;
639 	char					*parsed;
640 	const char				*name;
641 	size_t					 namelen;
642 
643 	parsed = options_parse(s, idx);
644 	if (parsed == NULL)
645 		return (NULL);
646 	if (*parsed == '@') {
647 		*ambiguous = 0;
648 		return (parsed);
649 	}
650 
651 	name = options_map_name(parsed);
652 	namelen = strlen(name);
653 
654 	found = NULL;
655 	for (oe = options_table; oe->name != NULL; oe++) {
656 		if (strcmp(oe->name, name) == 0) {
657 			found = oe;
658 			break;
659 		}
660 		if (strncmp(oe->name, name, namelen) == 0) {
661 			if (found != NULL) {
662 				*ambiguous = 1;
663 				free(parsed);
664 				return (NULL);
665 			}
666 			found = oe;
667 		}
668 	}
669 	free(parsed);
670 	if (found == NULL) {
671 		*ambiguous = 0;
672 		return (NULL);
673 	}
674 	return (xstrdup(found->name));
675 }
676 
677 struct options_entry *
678 options_match_get(struct options *oo, const char *s, int *idx, int only,
679     int *ambiguous)
680 {
681 	char			*name;
682 	struct options_entry	*o;
683 
684 	name = options_match(s, idx, ambiguous);
685 	if (name == NULL)
686 		return (NULL);
687 	*ambiguous = 0;
688 	if (only)
689 		o = options_get_only(oo, name);
690 	else
691 		o = options_get(oo, name);
692 	free(name);
693 	return (o);
694 }
695 
696 const char *
697 options_get_string(struct options *oo, const char *name)
698 {
699 	struct options_entry	*o;
700 
701 	o = options_get(oo, name);
702 	if (o == NULL)
703 		fatalx("missing option %s", name);
704 	if (!OPTIONS_IS_STRING(o))
705 		fatalx("option %s is not a string", name);
706 	return (o->value.string);
707 }
708 
709 long long
710 options_get_number(struct options *oo, const char *name)
711 {
712 	struct options_entry	*o;
713 
714 	o = options_get(oo, name);
715 	if (o == NULL)
716 		fatalx("missing option %s", name);
717 	if (!OPTIONS_IS_NUMBER(o))
718 		fatalx("option %s is not a number", name);
719 	return (o->value.number);
720 }
721 
722 struct options_entry *
723 options_set_string(struct options *oo, const char *name, int append,
724     const char *fmt, ...)
725 {
726 	struct options_entry	*o;
727 	va_list			 ap;
728 	const char		*separator = "";
729 	char			*s, *value;
730 
731 	va_start(ap, fmt);
732 	xvasprintf(&s, fmt, ap);
733 	va_end(ap);
734 
735 	o = options_get_only(oo, name);
736 	if (o != NULL && append && OPTIONS_IS_STRING(o)) {
737 		if (*name != '@') {
738 			separator = o->tableentry->separator;
739 			if (separator == NULL)
740 				separator = "";
741 		}
742 		xasprintf(&value, "%s%s%s", o->value.string, separator, s);
743 		free(s);
744 	} else
745 		value = s;
746 	if (o == NULL && *name == '@')
747 		o = options_add(oo, name);
748 	else if (o == NULL) {
749 		o = options_default(oo, options_parent_table_entry(oo, name));
750 		if (o == NULL)
751 			return (NULL);
752 	}
753 
754 	if (!OPTIONS_IS_STRING(o))
755 		fatalx("option %s is not a string", name);
756 	free(o->value.string);
757 	o->value.string = value;
758 	o->cached = 0;
759 	return (o);
760 }
761 
762 struct options_entry *
763 options_set_number(struct options *oo, const char *name, long long value)
764 {
765 	struct options_entry	*o;
766 
767 	if (*name == '@')
768 		fatalx("user option %s must be a string", name);
769 
770 	o = options_get_only(oo, name);
771 	if (o == NULL) {
772 		o = options_default(oo, options_parent_table_entry(oo, name));
773 		if (o == NULL)
774 			return (NULL);
775 	}
776 
777 	if (!OPTIONS_IS_NUMBER(o))
778 		fatalx("option %s is not a number", name);
779 	o->value.number = value;
780 	return (o);
781 }
782 
783 int
784 options_scope_from_name(struct args *args, int window,
785     const char *name, struct cmd_find_state *fs, struct options **oo,
786     char **cause)
787 {
788 	struct session				*s = fs->s;
789 	struct winlink				*wl = fs->wl;
790 	struct window_pane			*wp = fs->wp;
791 	const char				*target = args_get(args, 't');
792 	const struct options_table_entry	*oe;
793 	int					 scope = OPTIONS_TABLE_NONE;
794 
795 	if (*name == '@')
796 		return (options_scope_from_flags(args, window, fs, oo, cause));
797 
798 	for (oe = options_table; oe->name != NULL; oe++) {
799 		if (strcmp(oe->name, name) == 0)
800 			break;
801 	}
802 	if (oe->name == NULL) {
803 		xasprintf(cause, "unknown option: %s", name);
804 		return (OPTIONS_TABLE_NONE);
805 	}
806 	switch (oe->scope) {
807 	case OPTIONS_TABLE_SERVER:
808 		*oo = global_options;
809 		scope = OPTIONS_TABLE_SERVER;
810 		break;
811 	case OPTIONS_TABLE_SESSION:
812 		if (args_has(args, 'g')) {
813 			*oo = global_s_options;
814 			scope = OPTIONS_TABLE_SESSION;
815 		} else if (s == NULL && target != NULL)
816 			xasprintf(cause, "no such session: %s", target);
817 		else if (s == NULL)
818 			xasprintf(cause, "no current session");
819 		else {
820 			*oo = s->options;
821 			scope = OPTIONS_TABLE_SESSION;
822 		}
823 		break;
824 	case OPTIONS_TABLE_WINDOW|OPTIONS_TABLE_PANE:
825 		if (args_has(args, 'p')) {
826 			if (wp == NULL && target != NULL)
827 				xasprintf(cause, "no such pane: %s", target);
828 			else if (wp == NULL)
829 				xasprintf(cause, "no current pane");
830 			else {
831 				*oo = wp->options;
832 				scope = OPTIONS_TABLE_PANE;
833 			}
834 			break;
835 		}
836 		/* FALLTHROUGH */
837 	case OPTIONS_TABLE_WINDOW:
838 		if (args_has(args, 'g')) {
839 			*oo = global_w_options;
840 			scope = OPTIONS_TABLE_WINDOW;
841 		} else if (wl == NULL && target != NULL)
842 			xasprintf(cause, "no such window: %s", target);
843 		else if (wl == NULL)
844 			xasprintf(cause, "no current window");
845 		else {
846 			*oo = wl->window->options;
847 			scope = OPTIONS_TABLE_WINDOW;
848 		}
849 		break;
850 	}
851 	return (scope);
852 }
853 
854 int
855 options_scope_from_flags(struct args *args, int window,
856     struct cmd_find_state *fs, struct options **oo, char **cause)
857 {
858 	struct session		*s = fs->s;
859 	struct winlink		*wl = fs->wl;
860 	struct window_pane	*wp = fs->wp;
861 	const char		*target = args_get(args, 't');
862 
863 	if (args_has(args, 's')) {
864 		*oo = global_options;
865 		return (OPTIONS_TABLE_SERVER);
866 	}
867 
868 	if (args_has(args, 'p')) {
869 		if (wp == NULL) {
870 			if (target != NULL)
871 				xasprintf(cause, "no such pane: %s", target);
872 			else
873 				xasprintf(cause, "no current pane");
874 			return (OPTIONS_TABLE_NONE);
875 		}
876 		*oo = wp->options;
877 		return (OPTIONS_TABLE_PANE);
878 	} else if (window || args_has(args, 'w')) {
879 		if (args_has(args, 'g')) {
880 			*oo = global_w_options;
881 			return (OPTIONS_TABLE_WINDOW);
882 		}
883 		if (wl == NULL) {
884 			if (target != NULL)
885 				xasprintf(cause, "no such window: %s", target);
886 			else
887 				xasprintf(cause, "no current window");
888 			return (OPTIONS_TABLE_NONE);
889 		}
890 		*oo = wl->window->options;
891 		return (OPTIONS_TABLE_WINDOW);
892 	} else {
893 		if (args_has(args, 'g')) {
894 			*oo = global_s_options;
895 			return (OPTIONS_TABLE_SESSION);
896 		}
897 		if (s == NULL) {
898 			if (target != NULL)
899 				xasprintf(cause, "no such session: %s", target);
900 			else
901 				xasprintf(cause, "no current session");
902 			return (OPTIONS_TABLE_NONE);
903 		}
904 		*oo = s->options;
905 		return (OPTIONS_TABLE_SESSION);
906 	}
907 }
908 
909 struct style *
910 options_string_to_style(struct options *oo, const char *name,
911     struct format_tree *ft)
912 {
913 	struct options_entry	*o;
914 	const char		*s;
915 	char			*expanded;
916 
917 	o = options_get(oo, name);
918 	if (o == NULL || !OPTIONS_IS_STRING(o))
919 		return (NULL);
920 
921 	if (o->cached)
922 		return (&o->style);
923 	s = o->value.string;
924 	log_debug("%s: %s is '%s'", __func__, name, s);
925 
926 	style_set(&o->style, &grid_default_cell);
927 	o->cached = (strstr(s, "#{") == NULL);
928 
929 	if (ft != NULL && !o->cached) {
930 		expanded = format_expand(ft, s);
931 		if (style_parse(&o->style, &grid_default_cell, expanded) != 0) {
932 			free(expanded);
933 			return (NULL);
934 		}
935 		free(expanded);
936 	} else {
937 		if (style_parse(&o->style, &grid_default_cell, s) != 0)
938 			return (NULL);
939 	}
940 	return (&o->style);
941 }
942 
943 static int
944 options_from_string_check(const struct options_table_entry *oe,
945     const char *value, char **cause)
946 {
947 	struct style	sy;
948 
949 	if (oe == NULL)
950 		return (0);
951 	if (strcmp(oe->name, "default-shell") == 0 && !checkshell(value)) {
952 		xasprintf(cause, "not a suitable shell: %s", value);
953 		return (-1);
954 	}
955 	if (oe->pattern != NULL && fnmatch(oe->pattern, value, 0) != 0) {
956 		xasprintf(cause, "value is invalid: %s", value);
957 		return (-1);
958 	}
959 	if ((oe->flags & OPTIONS_TABLE_IS_STYLE) &&
960 	    strstr(value, "#{") == NULL &&
961 	    style_parse(&sy, &grid_default_cell, value) != 0) {
962 		xasprintf(cause, "invalid style: %s", value);
963 		return (-1);
964 	}
965 	return (0);
966 }
967 
968 static int
969 options_from_string_flag(struct options *oo, const char *name,
970     const char *value, char **cause)
971 {
972 	int	flag;
973 
974 	if (value == NULL || *value == '\0')
975 		flag = !options_get_number(oo, name);
976 	else if (strcmp(value, "1") == 0 ||
977 	    strcasecmp(value, "on") == 0 ||
978 	    strcasecmp(value, "yes") == 0)
979 		flag = 1;
980 	else if (strcmp(value, "0") == 0 ||
981 	    strcasecmp(value, "off") == 0 ||
982 	    strcasecmp(value, "no") == 0)
983 		flag = 0;
984 	else {
985 		xasprintf(cause, "bad value: %s", value);
986 		return (-1);
987 	}
988 	options_set_number(oo, name, flag);
989 	return (0);
990 }
991 
992 static int
993 options_from_string_choice(const struct options_table_entry *oe,
994     struct options *oo, const char *name, const char *value, char **cause)
995 {
996 	const char	**cp;
997 	int		  n, choice = -1;
998 
999 	if (value == NULL) {
1000 		choice = options_get_number(oo, name);
1001 		if (choice < 2)
1002 			choice = !choice;
1003 	} else {
1004 		n = 0;
1005 		for (cp = oe->choices; *cp != NULL; cp++) {
1006 			if (strcmp(*cp, value) == 0)
1007 				choice = n;
1008 			n++;
1009 		}
1010 		if (choice == -1) {
1011 			xasprintf(cause, "unknown value: %s", value);
1012 			return (-1);
1013 		}
1014 	}
1015 	options_set_number(oo, name, choice);
1016 	return (0);
1017 }
1018 
1019 int
1020 options_from_string(struct options *oo, const struct options_table_entry *oe,
1021     const char *name, const char *value, int append, char **cause)
1022 {
1023 	enum options_table_type	 type;
1024 	long long		 number;
1025 	const char		*errstr, *new;
1026 	char			*old;
1027 	key_code		 key;
1028 
1029 	if (oe != NULL) {
1030 		if (value == NULL &&
1031 		    oe->type != OPTIONS_TABLE_FLAG &&
1032 		    oe->type != OPTIONS_TABLE_CHOICE) {
1033 			xasprintf(cause, "empty value");
1034 			return (-1);
1035 		}
1036 		type = oe->type;
1037 	} else {
1038 		if (*name != '@') {
1039 			xasprintf(cause, "bad option name");
1040 			return (-1);
1041 		}
1042 		type = OPTIONS_TABLE_STRING;
1043 	}
1044 
1045 	switch (type) {
1046 	case OPTIONS_TABLE_STRING:
1047 		old = xstrdup(options_get_string(oo, name));
1048 		options_set_string(oo, name, append, "%s", value);
1049 
1050 		new = options_get_string(oo, name);
1051 		if (options_from_string_check(oe, new, cause) != 0) {
1052 			options_set_string(oo, name, 0, "%s", old);
1053 			free(old);
1054 			return (-1);
1055 		}
1056 		free(old);
1057 		return (0);
1058 	case OPTIONS_TABLE_NUMBER:
1059 		number = strtonum(value, oe->minimum, oe->maximum, &errstr);
1060 		if (errstr != NULL) {
1061 			xasprintf(cause, "value is %s: %s", errstr, value);
1062 			return (-1);
1063 		}
1064 		options_set_number(oo, name, number);
1065 		return (0);
1066 	case OPTIONS_TABLE_KEY:
1067 		key = key_string_lookup_string(value);
1068 		if (key == KEYC_UNKNOWN) {
1069 			xasprintf(cause, "bad key: %s", value);
1070 			return (-1);
1071 		}
1072 		options_set_number(oo, name, key);
1073 		return (0);
1074 	case OPTIONS_TABLE_COLOUR:
1075 		if ((number = colour_fromstring(value)) == -1) {
1076 			xasprintf(cause, "bad colour: %s", value);
1077 			return (-1);
1078 		}
1079 		options_set_number(oo, name, number);
1080 		return (0);
1081 	case OPTIONS_TABLE_FLAG:
1082 		return (options_from_string_flag(oo, name, value, cause));
1083 	case OPTIONS_TABLE_CHOICE:
1084 		return (options_from_string_choice(oe, oo, name, value, cause));
1085 	case OPTIONS_TABLE_COMMAND:
1086 		break;
1087 	}
1088 	return (-1);
1089 }
1090 
1091 void
1092 options_push_changes(const char *name)
1093 {
1094 	struct client		*loop;
1095 	struct session		*s;
1096 	struct window		*w;
1097 	struct window_pane	*wp;
1098 
1099 	if (strcmp(name, "automatic-rename") == 0) {
1100 		RB_FOREACH(w, windows, &windows) {
1101 			if (w->active == NULL)
1102 				continue;
1103 			if (options_get_number(w->options, "automatic-rename"))
1104 				w->active->flags |= PANE_CHANGED;
1105 		}
1106 	}
1107 	if (strcmp(name, "key-table") == 0) {
1108 		TAILQ_FOREACH(loop, &clients, entry)
1109 			server_client_set_key_table(loop, NULL);
1110 	}
1111 	if (strcmp(name, "user-keys") == 0) {
1112 		TAILQ_FOREACH(loop, &clients, entry) {
1113 			if (loop->tty.flags & TTY_OPENED)
1114 				tty_keys_build(&loop->tty);
1115 		}
1116 	}
1117 	if (strcmp(name, "status") == 0 ||
1118 	    strcmp(name, "status-interval") == 0)
1119 		status_timer_start_all();
1120 	if (strcmp(name, "monitor-silence") == 0)
1121 		alerts_reset_all();
1122 	if (strcmp(name, "window-style") == 0 ||
1123 	    strcmp(name, "window-active-style") == 0) {
1124 		RB_FOREACH(wp, window_pane_tree, &all_window_panes)
1125 			wp->flags |= PANE_STYLECHANGED;
1126 	}
1127 	if (strcmp(name, "pane-colours") == 0) {
1128 		RB_FOREACH(wp, window_pane_tree, &all_window_panes)
1129 			colour_palette_from_option(&wp->palette, wp->options);
1130 	}
1131 	if (strcmp(name, "pane-border-status") == 0) {
1132 		RB_FOREACH(w, windows, &windows)
1133 			layout_fix_panes(w, NULL);
1134 	}
1135 	RB_FOREACH(s, sessions, &sessions)
1136 		status_update_cache(s);
1137 
1138 	recalculate_sizes();
1139 	TAILQ_FOREACH(loop, &clients, entry) {
1140 		if (loop->session != NULL)
1141 			server_redraw_client(loop);
1142 	}
1143 }
1144 
1145 int
1146 options_remove_or_default(struct options_entry *o, int idx, char **cause)
1147 {
1148 	struct options	*oo = o->owner;
1149 
1150 	if (idx == -1) {
1151 		if (o->tableentry != NULL &&
1152 		    (oo == global_options ||
1153 		    oo == global_s_options ||
1154 		    oo == global_w_options))
1155 			options_default(oo, o->tableentry);
1156 		else
1157 			options_remove(o);
1158 	} else if (options_array_set(o, idx, NULL, 0, cause) != 0)
1159 		return (-1);
1160 	return (0);
1161 }
1162