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