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