1 /* $OpenBSD: options.c,v 1.55 2019/12/03 10:47:22 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 <stdarg.h> 23 #include <stdlib.h> 24 #include <string.h> 25 26 #include "tmux.h" 27 28 /* 29 * Option handling; each option has a name, type and value and is stored in 30 * a red-black tree. 31 */ 32 33 struct options_array_item { 34 u_int index; 35 union options_value value; 36 RB_ENTRY(options_array_item) entry; 37 }; 38 static int 39 options_array_cmp(struct options_array_item *a1, struct options_array_item *a2) 40 { 41 if (a1->index < a2->index) 42 return (-1); 43 if (a1->index > a2->index) 44 return (1); 45 return (0); 46 } 47 RB_GENERATE_STATIC(options_array, options_array_item, entry, options_array_cmp); 48 49 struct options_entry { 50 struct options *owner; 51 52 const char *name; 53 const struct options_table_entry *tableentry; 54 union options_value value; 55 56 RB_ENTRY(options_entry) entry; 57 }; 58 59 struct options { 60 RB_HEAD(options_tree, options_entry) tree; 61 struct options *parent; 62 }; 63 64 static struct options_entry *options_add(struct options *, const char *); 65 66 #define OPTIONS_IS_STRING(o) \ 67 ((o)->tableentry == NULL || \ 68 (o)->tableentry->type == OPTIONS_TABLE_STRING) 69 #define OPTIONS_IS_NUMBER(o) \ 70 ((o)->tableentry != NULL && \ 71 ((o)->tableentry->type == OPTIONS_TABLE_NUMBER || \ 72 (o)->tableentry->type == OPTIONS_TABLE_KEY || \ 73 (o)->tableentry->type == OPTIONS_TABLE_COLOUR || \ 74 (o)->tableentry->type == OPTIONS_TABLE_FLAG || \ 75 (o)->tableentry->type == OPTIONS_TABLE_CHOICE)) 76 #define OPTIONS_IS_STYLE(o) \ 77 ((o)->tableentry != NULL && \ 78 (o)->tableentry->type == OPTIONS_TABLE_STYLE) 79 #define OPTIONS_IS_COMMAND(o) \ 80 ((o)->tableentry != NULL && \ 81 (o)->tableentry->type == OPTIONS_TABLE_COMMAND) 82 83 #define OPTIONS_IS_ARRAY(o) \ 84 ((o)->tableentry != NULL && \ 85 ((o)->tableentry->flags & OPTIONS_TABLE_IS_ARRAY)) 86 87 static int options_cmp(struct options_entry *, struct options_entry *); 88 RB_GENERATE_STATIC(options_tree, options_entry, entry, options_cmp); 89 90 static int 91 options_cmp(struct options_entry *lhs, struct options_entry *rhs) 92 { 93 return (strcmp(lhs->name, rhs->name)); 94 } 95 96 static const struct options_table_entry * 97 options_parent_table_entry(struct options *oo, const char *s) 98 { 99 struct options_entry *o; 100 101 if (oo->parent == NULL) 102 fatalx("no parent options for %s", s); 103 o = options_get(oo->parent, s); 104 if (o == NULL) 105 fatalx("%s not in parent options", s); 106 return (o->tableentry); 107 } 108 109 static void 110 options_value_free(struct options_entry *o, union options_value *ov) 111 { 112 if (OPTIONS_IS_STRING(o)) 113 free(ov->string); 114 if (OPTIONS_IS_COMMAND(o) && ov->cmdlist != NULL) 115 cmd_list_free(ov->cmdlist); 116 } 117 118 static char * 119 options_value_tostring(struct options_entry *o, union options_value *ov, 120 int numeric) 121 { 122 char *s; 123 124 if (OPTIONS_IS_COMMAND(o)) 125 return (cmd_list_print(ov->cmdlist, 0)); 126 if (OPTIONS_IS_STYLE(o)) 127 return (xstrdup(style_tostring(&ov->style))); 128 if (OPTIONS_IS_NUMBER(o)) { 129 switch (o->tableentry->type) { 130 case OPTIONS_TABLE_NUMBER: 131 xasprintf(&s, "%lld", ov->number); 132 break; 133 case OPTIONS_TABLE_KEY: 134 s = xstrdup(key_string_lookup_key(ov->number)); 135 break; 136 case OPTIONS_TABLE_COLOUR: 137 s = xstrdup(colour_tostring(ov->number)); 138 break; 139 case OPTIONS_TABLE_FLAG: 140 if (numeric) 141 xasprintf(&s, "%lld", ov->number); 142 else 143 s = xstrdup(ov->number ? "on" : "off"); 144 break; 145 case OPTIONS_TABLE_CHOICE: 146 s = xstrdup(o->tableentry->choices[ov->number]); 147 break; 148 case OPTIONS_TABLE_STRING: 149 case OPTIONS_TABLE_STYLE: 150 case OPTIONS_TABLE_COMMAND: 151 fatalx("not a number option type"); 152 } 153 return (s); 154 } 155 if (OPTIONS_IS_STRING(o)) 156 return (xstrdup(ov->string)); 157 return (xstrdup("")); 158 } 159 160 struct options * 161 options_create(struct options *parent) 162 { 163 struct options *oo; 164 165 oo = xcalloc(1, sizeof *oo); 166 RB_INIT(&oo->tree); 167 oo->parent = parent; 168 return (oo); 169 } 170 171 void 172 options_free(struct options *oo) 173 { 174 struct options_entry *o, *tmp; 175 176 RB_FOREACH_SAFE(o, options_tree, &oo->tree, tmp) 177 options_remove(o); 178 free(oo); 179 } 180 181 void 182 options_set_parent(struct options *oo, struct options *parent) 183 { 184 oo->parent = parent; 185 } 186 187 struct options_entry * 188 options_first(struct options *oo) 189 { 190 return (RB_MIN(options_tree, &oo->tree)); 191 } 192 193 struct options_entry * 194 options_next(struct options_entry *o) 195 { 196 return (RB_NEXT(options_tree, &oo->tree, o)); 197 } 198 199 struct options_entry * 200 options_get_only(struct options *oo, const char *name) 201 { 202 struct options_entry o; 203 204 o.name = name; 205 return (RB_FIND(options_tree, &oo->tree, &o)); 206 } 207 208 struct options_entry * 209 options_get(struct options *oo, const char *name) 210 { 211 struct options_entry *o; 212 213 o = options_get_only(oo, name); 214 while (o == NULL) { 215 oo = oo->parent; 216 if (oo == NULL) 217 break; 218 o = options_get_only(oo, name); 219 } 220 return (o); 221 } 222 223 struct options_entry * 224 options_empty(struct options *oo, const struct options_table_entry *oe) 225 { 226 struct options_entry *o; 227 228 o = options_add(oo, oe->name); 229 o->tableentry = oe; 230 231 if (oe->flags & OPTIONS_TABLE_IS_ARRAY) 232 RB_INIT(&o->value.array); 233 234 return (o); 235 } 236 237 struct options_entry * 238 options_default(struct options *oo, const struct options_table_entry *oe) 239 { 240 struct options_entry *o; 241 union options_value *ov; 242 u_int i; 243 244 o = options_empty(oo, oe); 245 ov = &o->value; 246 247 if (oe->flags & OPTIONS_TABLE_IS_ARRAY) { 248 if (oe->default_arr == NULL) { 249 options_array_assign(o, oe->default_str, NULL); 250 return (o); 251 } 252 for (i = 0; oe->default_arr[i] != NULL; i++) 253 options_array_set(o, i, oe->default_arr[i], 0, NULL); 254 return (o); 255 } 256 257 switch (oe->type) { 258 case OPTIONS_TABLE_STRING: 259 ov->string = xstrdup(oe->default_str); 260 break; 261 case OPTIONS_TABLE_STYLE: 262 style_set(&ov->style, &grid_default_cell); 263 style_parse(&ov->style, &grid_default_cell, oe->default_str); 264 break; 265 default: 266 ov->number = oe->default_num; 267 break; 268 } 269 return (o); 270 } 271 272 static struct options_entry * 273 options_add(struct options *oo, const char *name) 274 { 275 struct options_entry *o; 276 277 o = options_get_only(oo, name); 278 if (o != NULL) 279 options_remove(o); 280 281 o = xcalloc(1, sizeof *o); 282 o->owner = oo; 283 o->name = xstrdup(name); 284 285 RB_INSERT(options_tree, &oo->tree, o); 286 return (o); 287 } 288 289 void 290 options_remove(struct options_entry *o) 291 { 292 struct options *oo = o->owner; 293 294 if (OPTIONS_IS_ARRAY(o)) 295 options_array_clear(o); 296 else 297 options_value_free(o, &o->value); 298 RB_REMOVE(options_tree, &oo->tree, o); 299 free((void *)o->name); 300 free(o); 301 } 302 303 const char * 304 options_name(struct options_entry *o) 305 { 306 return (o->name); 307 } 308 309 const struct options_table_entry * 310 options_table_entry(struct options_entry *o) 311 { 312 return (o->tableentry); 313 } 314 315 static struct options_array_item * 316 options_array_item(struct options_entry *o, u_int idx) 317 { 318 struct options_array_item a; 319 320 a.index = idx; 321 return (RB_FIND(options_array, &o->value.array, &a)); 322 } 323 324 static struct options_array_item * 325 options_array_new(struct options_entry *o, u_int idx) 326 { 327 struct options_array_item *a; 328 329 a = xcalloc(1, sizeof *a); 330 a->index = idx; 331 RB_INSERT(options_array, &o->value.array, a); 332 return (a); 333 } 334 335 static void 336 options_array_free(struct options_entry *o, struct options_array_item *a) 337 { 338 options_value_free(o, &a->value); 339 RB_REMOVE(options_array, &o->value.array, a); 340 free(a); 341 } 342 343 void 344 options_array_clear(struct options_entry *o) 345 { 346 struct options_array_item *a, *a1; 347 348 if (!OPTIONS_IS_ARRAY(o)) 349 return; 350 351 RB_FOREACH_SAFE(a, options_array, &o->value.array, a1) 352 options_array_free(o, a); 353 } 354 355 union options_value * 356 options_array_get(struct options_entry *o, u_int idx) 357 { 358 struct options_array_item *a; 359 360 if (!OPTIONS_IS_ARRAY(o)) 361 return (NULL); 362 a = options_array_item(o, idx); 363 if (a == NULL) 364 return (NULL); 365 return (&a->value); 366 } 367 368 int 369 options_array_set(struct options_entry *o, u_int idx, const char *value, 370 int append, char **cause) 371 { 372 struct options_array_item *a; 373 char *new; 374 struct cmd_parse_result *pr; 375 376 if (!OPTIONS_IS_ARRAY(o)) { 377 if (cause != NULL) 378 *cause = xstrdup("not an array"); 379 return (-1); 380 } 381 382 if (value == NULL) { 383 a = options_array_item(o, idx); 384 if (a != NULL) 385 options_array_free(o, a); 386 return (0); 387 } 388 389 if (OPTIONS_IS_COMMAND(o)) { 390 pr = cmd_parse_from_string(value, NULL); 391 switch (pr->status) { 392 case CMD_PARSE_EMPTY: 393 if (cause != NULL) 394 *cause = xstrdup("empty command"); 395 return (-1); 396 case CMD_PARSE_ERROR: 397 if (cause != NULL) 398 *cause = pr->error; 399 else 400 free(pr->error); 401 return (-1); 402 case CMD_PARSE_SUCCESS: 403 break; 404 } 405 406 a = options_array_item(o, idx); 407 if (a == NULL) 408 a = options_array_new(o, idx); 409 else 410 options_value_free(o, &a->value); 411 a->value.cmdlist = pr->cmdlist; 412 return (0); 413 } 414 415 if (OPTIONS_IS_STRING(o)) { 416 a = options_array_item(o, idx); 417 if (a != NULL && append) 418 xasprintf(&new, "%s%s", a->value.string, value); 419 else 420 new = xstrdup(value); 421 if (a == NULL) 422 a = options_array_new(o, idx); 423 else 424 options_value_free(o, &a->value); 425 a->value.string = new; 426 return (0); 427 } 428 429 if (cause != NULL) 430 *cause = xstrdup("wrong array type"); 431 return (-1); 432 } 433 434 int 435 options_array_assign(struct options_entry *o, const char *s, char **cause) 436 { 437 const char *separator; 438 char *copy, *next, *string; 439 u_int i; 440 441 separator = o->tableentry->separator; 442 if (separator == NULL) 443 separator = " ,"; 444 if (*separator == '\0') { 445 if (*s == '\0') 446 return (0); 447 for (i = 0; i < UINT_MAX; i++) { 448 if (options_array_item(o, i) == NULL) 449 break; 450 } 451 return (options_array_set(o, i, s, 0, cause)); 452 } 453 454 if (*s == '\0') 455 return (0); 456 copy = string = xstrdup(s); 457 while ((next = strsep(&string, separator)) != NULL) { 458 if (*next == '\0') 459 continue; 460 for (i = 0; i < UINT_MAX; i++) { 461 if (options_array_item(o, i) == NULL) 462 break; 463 } 464 if (i == UINT_MAX) 465 break; 466 if (options_array_set(o, i, next, 0, cause) != 0) { 467 free(copy); 468 return (-1); 469 } 470 } 471 free(copy); 472 return (0); 473 } 474 475 struct options_array_item * 476 options_array_first(struct options_entry *o) 477 { 478 if (!OPTIONS_IS_ARRAY(o)) 479 return (NULL); 480 return (RB_MIN(options_array, &o->value.array)); 481 } 482 483 struct options_array_item * 484 options_array_next(struct options_array_item *a) 485 { 486 return (RB_NEXT(options_array, &o->value.array, a)); 487 } 488 489 u_int 490 options_array_item_index(struct options_array_item *a) 491 { 492 return (a->index); 493 } 494 495 union options_value * 496 options_array_item_value(struct options_array_item *a) 497 { 498 return (&a->value); 499 } 500 501 int 502 options_isarray(struct options_entry *o) 503 { 504 return (OPTIONS_IS_ARRAY(o)); 505 } 506 507 int 508 options_isstring(struct options_entry *o) 509 { 510 return (OPTIONS_IS_STRING(o)); 511 } 512 513 char * 514 options_tostring(struct options_entry *o, int idx, int numeric) 515 { 516 struct options_array_item *a; 517 518 if (OPTIONS_IS_ARRAY(o)) { 519 if (idx == -1) 520 return (xstrdup("")); 521 a = options_array_item(o, idx); 522 if (a == NULL) 523 return (xstrdup("")); 524 return (options_value_tostring(o, &a->value, numeric)); 525 } 526 return (options_value_tostring(o, &o->value, numeric)); 527 } 528 529 char * 530 options_parse(const char *name, int *idx) 531 { 532 char *copy, *cp, *end; 533 534 if (*name == '\0') 535 return (NULL); 536 copy = xstrdup(name); 537 if ((cp = strchr(copy, '[')) == NULL) { 538 *idx = -1; 539 return (copy); 540 } 541 end = strchr(cp + 1, ']'); 542 if (end == NULL || end[1] != '\0' || !isdigit((u_char)end[-1])) { 543 free(copy); 544 return (NULL); 545 } 546 if (sscanf(cp, "[%d]", idx) != 1 || *idx < 0) { 547 free(copy); 548 return (NULL); 549 } 550 *cp = '\0'; 551 return (copy); 552 } 553 554 struct options_entry * 555 options_parse_get(struct options *oo, const char *s, int *idx, int only) 556 { 557 struct options_entry *o; 558 char *name; 559 560 name = options_parse(s, idx); 561 if (name == NULL) 562 return (NULL); 563 if (only) 564 o = options_get_only(oo, name); 565 else 566 o = options_get(oo, name); 567 free(name); 568 return (o); 569 } 570 571 char * 572 options_match(const char *s, int *idx, int *ambiguous) 573 { 574 const struct options_table_entry *oe, *found; 575 char *name; 576 size_t namelen; 577 578 name = options_parse(s, idx); 579 if (name == NULL) 580 return (NULL); 581 namelen = strlen(name); 582 583 if (*name == '@') { 584 *ambiguous = 0; 585 return (name); 586 } 587 588 found = NULL; 589 for (oe = options_table; oe->name != NULL; oe++) { 590 if (strcmp(oe->name, name) == 0) { 591 found = oe; 592 break; 593 } 594 if (strncmp(oe->name, name, namelen) == 0) { 595 if (found != NULL) { 596 *ambiguous = 1; 597 free(name); 598 return (NULL); 599 } 600 found = oe; 601 } 602 } 603 free(name); 604 if (found == NULL) { 605 *ambiguous = 0; 606 return (NULL); 607 } 608 return (xstrdup(found->name)); 609 } 610 611 struct options_entry * 612 options_match_get(struct options *oo, const char *s, int *idx, int only, 613 int *ambiguous) 614 { 615 char *name; 616 struct options_entry *o; 617 618 name = options_match(s, idx, ambiguous); 619 if (name == NULL) 620 return (NULL); 621 *ambiguous = 0; 622 if (only) 623 o = options_get_only(oo, name); 624 else 625 o = options_get(oo, name); 626 free(name); 627 return (o); 628 } 629 630 const char * 631 options_get_string(struct options *oo, const char *name) 632 { 633 struct options_entry *o; 634 635 o = options_get(oo, name); 636 if (o == NULL) 637 fatalx("missing option %s", name); 638 if (!OPTIONS_IS_STRING(o)) 639 fatalx("option %s is not a string", name); 640 return (o->value.string); 641 } 642 643 long long 644 options_get_number(struct options *oo, const char *name) 645 { 646 struct options_entry *o; 647 648 o = options_get(oo, name); 649 if (o == NULL) 650 fatalx("missing option %s", name); 651 if (!OPTIONS_IS_NUMBER(o)) 652 fatalx("option %s is not a number", name); 653 return (o->value.number); 654 } 655 656 struct style * 657 options_get_style(struct options *oo, const char *name) 658 { 659 struct options_entry *o; 660 661 o = options_get(oo, name); 662 if (o == NULL) 663 fatalx("missing option %s", name); 664 if (!OPTIONS_IS_STYLE(o)) 665 fatalx("option %s is not a style", name); 666 return (&o->value.style); 667 } 668 669 struct options_entry * 670 options_set_string(struct options *oo, const char *name, int append, 671 const char *fmt, ...) 672 { 673 struct options_entry *o; 674 va_list ap; 675 char *s, *value; 676 677 va_start(ap, fmt); 678 xvasprintf(&s, fmt, ap); 679 va_end(ap); 680 681 o = options_get_only(oo, name); 682 if (o != NULL && append && OPTIONS_IS_STRING(o)) { 683 xasprintf(&value, "%s%s", o->value.string, s); 684 free(s); 685 } else 686 value = s; 687 if (o == NULL && *name == '@') 688 o = options_add(oo, name); 689 else if (o == NULL) { 690 o = options_default(oo, options_parent_table_entry(oo, name)); 691 if (o == NULL) 692 return (NULL); 693 } 694 695 if (!OPTIONS_IS_STRING(o)) 696 fatalx("option %s is not a string", name); 697 free(o->value.string); 698 o->value.string = value; 699 return (o); 700 } 701 702 struct options_entry * 703 options_set_number(struct options *oo, const char *name, long long value) 704 { 705 struct options_entry *o; 706 707 if (*name == '@') 708 fatalx("user option %s must be a string", name); 709 710 o = options_get_only(oo, name); 711 if (o == NULL) { 712 o = options_default(oo, options_parent_table_entry(oo, name)); 713 if (o == NULL) 714 return (NULL); 715 } 716 717 if (!OPTIONS_IS_NUMBER(o)) 718 fatalx("option %s is not a number", name); 719 o->value.number = value; 720 return (o); 721 } 722 723 struct options_entry * 724 options_set_style(struct options *oo, const char *name, int append, 725 const char *value) 726 { 727 struct options_entry *o; 728 struct style sy; 729 730 if (*name == '@') 731 fatalx("user option %s must be a string", name); 732 733 o = options_get_only(oo, name); 734 if (o != NULL && append && OPTIONS_IS_STYLE(o)) 735 style_copy(&sy, &o->value.style); 736 else 737 style_set(&sy, &grid_default_cell); 738 if (style_parse(&sy, &grid_default_cell, value) == -1) 739 return (NULL); 740 if (o == NULL) { 741 o = options_default(oo, options_parent_table_entry(oo, name)); 742 if (o == NULL) 743 return (NULL); 744 } 745 746 if (!OPTIONS_IS_STYLE(o)) 747 fatalx("option %s is not a style", name); 748 style_copy(&o->value.style, &sy); 749 return (o); 750 } 751 752 int 753 options_scope_from_name(struct args *args, int window, 754 const char *name, struct cmd_find_state *fs, struct options **oo, 755 char **cause) 756 { 757 struct session *s = fs->s; 758 struct winlink *wl = fs->wl; 759 struct window_pane *wp = fs->wp; 760 const char *target = args_get(args, 't'); 761 const struct options_table_entry *oe; 762 int scope = OPTIONS_TABLE_NONE; 763 764 if (*name == '@') 765 return (options_scope_from_flags(args, window, fs, oo, cause)); 766 767 for (oe = options_table; oe->name != NULL; oe++) { 768 if (strcmp(oe->name, name) == 0) 769 break; 770 } 771 if (oe->name == NULL) { 772 xasprintf(cause, "unknown option: %s", name); 773 return (OPTIONS_TABLE_NONE); 774 } 775 switch (oe->scope) { 776 case OPTIONS_TABLE_SERVER: 777 *oo = global_options; 778 scope = OPTIONS_TABLE_SERVER; 779 break; 780 case OPTIONS_TABLE_SESSION: 781 if (args_has(args, 'g')) { 782 *oo = global_s_options; 783 scope = OPTIONS_TABLE_SESSION; 784 } else if (s == NULL && target != NULL) 785 xasprintf(cause, "no such session: %s", target); 786 else if (s == NULL) 787 xasprintf(cause, "no current session"); 788 else { 789 *oo = s->options; 790 scope = OPTIONS_TABLE_SESSION; 791 } 792 break; 793 case OPTIONS_TABLE_WINDOW|OPTIONS_TABLE_PANE: 794 if (args_has(args, 'p')) { 795 if (wp == NULL && target != NULL) 796 xasprintf(cause, "no such pane: %s", target); 797 else if (wp == NULL) 798 xasprintf(cause, "no current pane"); 799 else { 800 *oo = wp->options; 801 scope = OPTIONS_TABLE_PANE; 802 } 803 break; 804 } 805 /* FALLTHROUGH */ 806 case OPTIONS_TABLE_WINDOW: 807 if (args_has(args, 'g')) { 808 *oo = global_w_options; 809 scope = OPTIONS_TABLE_WINDOW; 810 } else if (wl == NULL && target != NULL) 811 xasprintf(cause, "no such window: %s", target); 812 else if (wl == NULL) 813 xasprintf(cause, "no current window"); 814 else { 815 *oo = wl->window->options; 816 scope = OPTIONS_TABLE_WINDOW; 817 } 818 break; 819 } 820 return (scope); 821 } 822 823 int 824 options_scope_from_flags(struct args *args, int window, 825 struct cmd_find_state *fs, struct options **oo, char **cause) 826 { 827 struct session *s = fs->s; 828 struct winlink *wl = fs->wl; 829 struct window_pane *wp = fs->wp; 830 const char *target = args_get(args, 't'); 831 832 if (args_has(args, 's')) { 833 *oo = global_options; 834 return (OPTIONS_TABLE_SERVER); 835 } 836 837 if (args_has(args, 'p')) { 838 if (wp == NULL) { 839 if (target != NULL) 840 xasprintf(cause, "no such pane: %s", target); 841 else 842 xasprintf(cause, "no current pane"); 843 return (OPTIONS_TABLE_NONE); 844 } 845 *oo = wp->options; 846 return (OPTIONS_TABLE_PANE); 847 } else if (window || args_has(args, 'w')) { 848 if (args_has(args, 'g')) { 849 *oo = global_w_options; 850 return (OPTIONS_TABLE_WINDOW); 851 } 852 if (wl == NULL) { 853 if (target != NULL) 854 xasprintf(cause, "no such window: %s", target); 855 else 856 xasprintf(cause, "no current window"); 857 return (OPTIONS_TABLE_NONE); 858 } 859 *oo = wl->window->options; 860 return (OPTIONS_TABLE_WINDOW); 861 } else { 862 if (args_has(args, 'g')) { 863 *oo = global_s_options; 864 return (OPTIONS_TABLE_SESSION); 865 } 866 if (s == NULL) { 867 if (target != NULL) 868 xasprintf(cause, "no such session: %s", target); 869 else 870 xasprintf(cause, "no current session"); 871 return (OPTIONS_TABLE_NONE); 872 } 873 *oo = s->options; 874 return (OPTIONS_TABLE_SESSION); 875 } 876 } 877