1 /* $OpenBSD: options.c,v 1.52 2019/06/23 10:00:29 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(o); 300 } 301 302 const char * 303 options_name(struct options_entry *o) 304 { 305 return (o->name); 306 } 307 308 const struct options_table_entry * 309 options_table_entry(struct options_entry *o) 310 { 311 return (o->tableentry); 312 } 313 314 static struct options_array_item * 315 options_array_item(struct options_entry *o, u_int idx) 316 { 317 struct options_array_item a; 318 319 a.index = idx; 320 return (RB_FIND(options_array, &o->value.array, &a)); 321 } 322 323 static void 324 options_array_free(struct options_entry *o, struct options_array_item *a) 325 { 326 options_value_free(o, &a->value); 327 RB_REMOVE(options_array, &o->value.array, a); 328 free(a); 329 } 330 331 void 332 options_array_clear(struct options_entry *o) 333 { 334 struct options_array_item *a, *a1; 335 336 if (!OPTIONS_IS_ARRAY(o)) 337 return; 338 339 RB_FOREACH_SAFE(a, options_array, &o->value.array, a1) 340 options_array_free(o, a); 341 } 342 343 union options_value * 344 options_array_get(struct options_entry *o, u_int idx) 345 { 346 struct options_array_item *a; 347 348 if (!OPTIONS_IS_ARRAY(o)) 349 return (NULL); 350 a = options_array_item(o, idx); 351 if (a == NULL) 352 return (NULL); 353 return (&a->value); 354 } 355 356 int 357 options_array_set(struct options_entry *o, u_int idx, const char *value, 358 int append, char **cause) 359 { 360 struct options_array_item *a; 361 char *new; 362 struct cmd_parse_result *pr; 363 364 if (!OPTIONS_IS_ARRAY(o)) { 365 if (cause != NULL) 366 *cause = xstrdup("not an array"); 367 return (-1); 368 } 369 370 if (OPTIONS_IS_COMMAND(o) && value != NULL) { 371 pr = cmd_parse_from_string(value, NULL); 372 switch (pr->status) { 373 case CMD_PARSE_EMPTY: 374 if (cause != NULL) 375 *cause = xstrdup("empty command"); 376 return (-1); 377 case CMD_PARSE_ERROR: 378 if (cause != NULL) 379 *cause = pr->error; 380 else 381 free(pr->error); 382 return (-1); 383 case CMD_PARSE_SUCCESS: 384 break; 385 } 386 } 387 388 a = options_array_item(o, idx); 389 if (value == NULL) { 390 if (a != NULL) 391 options_array_free(o, a); 392 return (0); 393 } 394 395 if (OPTIONS_IS_STRING(o)) { 396 if (a != NULL && append) 397 xasprintf(&new, "%s%s", a->value.string, value); 398 else 399 new = xstrdup(value); 400 } 401 402 if (a == NULL) { 403 a = xcalloc(1, sizeof *a); 404 a->index = idx; 405 RB_INSERT(options_array, &o->value.array, a); 406 } else 407 options_value_free(o, &a->value); 408 409 if (OPTIONS_IS_STRING(o)) 410 a->value.string = new; 411 else if (OPTIONS_IS_COMMAND(o)) 412 a->value.cmdlist = pr->cmdlist; 413 return (0); 414 } 415 416 int 417 options_array_assign(struct options_entry *o, const char *s, char **cause) 418 { 419 const char *separator; 420 char *copy, *next, *string; 421 u_int i; 422 423 separator = o->tableentry->separator; 424 if (separator == NULL) 425 separator = " ,"; 426 if (*separator == '\0') { 427 if (*s == '\0') 428 return (0); 429 for (i = 0; i < UINT_MAX; i++) { 430 if (options_array_item(o, i) == NULL) 431 break; 432 } 433 return (options_array_set(o, i, s, 0, cause)); 434 } 435 436 if (*s == '\0') 437 return (0); 438 copy = string = xstrdup(s); 439 while ((next = strsep(&string, separator)) != NULL) { 440 if (*next == '\0') 441 continue; 442 for (i = 0; i < UINT_MAX; i++) { 443 if (options_array_item(o, i) == NULL) 444 break; 445 } 446 if (i == UINT_MAX) 447 break; 448 if (options_array_set(o, i, next, 0, cause) != 0) { 449 free(copy); 450 return (-1); 451 } 452 } 453 free(copy); 454 return (0); 455 } 456 457 struct options_array_item * 458 options_array_first(struct options_entry *o) 459 { 460 if (!OPTIONS_IS_ARRAY(o)) 461 return (NULL); 462 return (RB_MIN(options_array, &o->value.array)); 463 } 464 465 struct options_array_item * 466 options_array_next(struct options_array_item *a) 467 { 468 return (RB_NEXT(options_array, &o->value.array, a)); 469 } 470 471 u_int 472 options_array_item_index(struct options_array_item *a) 473 { 474 return (a->index); 475 } 476 477 union options_value * 478 options_array_item_value(struct options_array_item *a) 479 { 480 return (&a->value); 481 } 482 483 int 484 options_isarray(struct options_entry *o) 485 { 486 return (OPTIONS_IS_ARRAY(o)); 487 } 488 489 int 490 options_isstring(struct options_entry *o) 491 { 492 return (OPTIONS_IS_STRING(o)); 493 } 494 495 char * 496 options_tostring(struct options_entry *o, int idx, int numeric) 497 { 498 struct options_array_item *a; 499 500 if (OPTIONS_IS_ARRAY(o)) { 501 if (idx == -1) 502 return (xstrdup("")); 503 a = options_array_item(o, idx); 504 if (a == NULL) 505 return (xstrdup("")); 506 return (options_value_tostring(o, &a->value, numeric)); 507 } 508 return (options_value_tostring(o, &o->value, numeric)); 509 } 510 511 char * 512 options_parse(const char *name, int *idx) 513 { 514 char *copy, *cp, *end; 515 516 if (*name == '\0') 517 return (NULL); 518 copy = xstrdup(name); 519 if ((cp = strchr(copy, '[')) == NULL) { 520 *idx = -1; 521 return (copy); 522 } 523 end = strchr(cp + 1, ']'); 524 if (end == NULL || end[1] != '\0' || !isdigit((u_char)end[-1])) { 525 free(copy); 526 return (NULL); 527 } 528 if (sscanf(cp, "[%d]", idx) != 1 || *idx < 0) { 529 free(copy); 530 return (NULL); 531 } 532 *cp = '\0'; 533 return (copy); 534 } 535 536 struct options_entry * 537 options_parse_get(struct options *oo, const char *s, int *idx, int only) 538 { 539 struct options_entry *o; 540 char *name; 541 542 name = options_parse(s, idx); 543 if (name == NULL) 544 return (NULL); 545 if (only) 546 o = options_get_only(oo, name); 547 else 548 o = options_get(oo, name); 549 free(name); 550 return (o); 551 } 552 553 char * 554 options_match(const char *s, int *idx, int *ambiguous) 555 { 556 const struct options_table_entry *oe, *found; 557 char *name; 558 size_t namelen; 559 560 name = options_parse(s, idx); 561 if (name == NULL) 562 return (NULL); 563 namelen = strlen(name); 564 565 if (*name == '@') { 566 *ambiguous = 0; 567 return (name); 568 } 569 570 found = NULL; 571 for (oe = options_table; oe->name != NULL; oe++) { 572 if (strcmp(oe->name, name) == 0) { 573 found = oe; 574 break; 575 } 576 if (strncmp(oe->name, name, namelen) == 0) { 577 if (found != NULL) { 578 *ambiguous = 1; 579 free(name); 580 return (NULL); 581 } 582 found = oe; 583 } 584 } 585 free(name); 586 if (found == NULL) { 587 *ambiguous = 0; 588 return (NULL); 589 } 590 return (xstrdup(found->name)); 591 } 592 593 struct options_entry * 594 options_match_get(struct options *oo, const char *s, int *idx, int only, 595 int* ambiguous) 596 { 597 char *name; 598 struct options_entry *o; 599 600 name = options_match(s, idx, ambiguous); 601 if (name == NULL) 602 return (NULL); 603 *ambiguous = 0; 604 if (only) 605 o = options_get_only(oo, name); 606 else 607 o = options_get(oo, name); 608 free(name); 609 return (o); 610 } 611 612 const char * 613 options_get_string(struct options *oo, const char *name) 614 { 615 struct options_entry *o; 616 617 o = options_get(oo, name); 618 if (o == NULL) 619 fatalx("missing option %s", name); 620 if (!OPTIONS_IS_STRING(o)) 621 fatalx("option %s is not a string", name); 622 return (o->value.string); 623 } 624 625 long long 626 options_get_number(struct options *oo, const char *name) 627 { 628 struct options_entry *o; 629 630 o = options_get(oo, name); 631 if (o == NULL) 632 fatalx("missing option %s", name); 633 if (!OPTIONS_IS_NUMBER(o)) 634 fatalx("option %s is not a number", name); 635 return (o->value.number); 636 } 637 638 struct style * 639 options_get_style(struct options *oo, const char *name) 640 { 641 struct options_entry *o; 642 643 o = options_get(oo, name); 644 if (o == NULL) 645 fatalx("missing option %s", name); 646 if (!OPTIONS_IS_STYLE(o)) 647 fatalx("option %s is not a style", name); 648 return (&o->value.style); 649 } 650 651 struct options_entry * 652 options_set_string(struct options *oo, const char *name, int append, 653 const char *fmt, ...) 654 { 655 struct options_entry *o; 656 va_list ap; 657 char *s, *value; 658 659 va_start(ap, fmt); 660 xvasprintf(&s, fmt, ap); 661 va_end(ap); 662 663 o = options_get_only(oo, name); 664 if (o != NULL && append && OPTIONS_IS_STRING(o)) { 665 xasprintf(&value, "%s%s", o->value.string, s); 666 free(s); 667 } else 668 value = s; 669 if (o == NULL && *name == '@') 670 o = options_add(oo, name); 671 else if (o == NULL) { 672 o = options_default(oo, options_parent_table_entry(oo, name)); 673 if (o == NULL) 674 return (NULL); 675 } 676 677 if (!OPTIONS_IS_STRING(o)) 678 fatalx("option %s is not a string", name); 679 free(o->value.string); 680 o->value.string = value; 681 return (o); 682 } 683 684 struct options_entry * 685 options_set_number(struct options *oo, const char *name, long long value) 686 { 687 struct options_entry *o; 688 689 if (*name == '@') 690 fatalx("user option %s must be a string", name); 691 692 o = options_get_only(oo, name); 693 if (o == NULL) { 694 o = options_default(oo, options_parent_table_entry(oo, name)); 695 if (o == NULL) 696 return (NULL); 697 } 698 699 if (!OPTIONS_IS_NUMBER(o)) 700 fatalx("option %s is not a number", name); 701 o->value.number = value; 702 return (o); 703 } 704 705 struct options_entry * 706 options_set_style(struct options *oo, const char *name, int append, 707 const char *value) 708 { 709 struct options_entry *o; 710 struct style sy; 711 712 if (*name == '@') 713 fatalx("user option %s must be a string", name); 714 715 o = options_get_only(oo, name); 716 if (o != NULL && append && OPTIONS_IS_STYLE(o)) 717 style_copy(&sy, &o->value.style); 718 else 719 style_set(&sy, &grid_default_cell); 720 if (style_parse(&sy, &grid_default_cell, value) == -1) 721 return (NULL); 722 if (o == NULL) { 723 o = options_default(oo, options_parent_table_entry(oo, name)); 724 if (o == NULL) 725 return (NULL); 726 } 727 728 if (!OPTIONS_IS_STYLE(o)) 729 fatalx("option %s is not a style", name); 730 style_copy(&o->value.style, &sy); 731 return (o); 732 } 733 734 int 735 options_scope_from_name(struct args *args, int window, 736 const char *name, struct cmd_find_state *fs, struct options **oo, 737 char **cause) 738 { 739 struct session *s = fs->s; 740 struct winlink *wl = fs->wl; 741 struct window_pane *wp = fs->wp; 742 const char *target = args_get(args, 't'); 743 const struct options_table_entry *oe; 744 int scope = OPTIONS_TABLE_NONE; 745 746 if (*name == '@') 747 return (options_scope_from_flags(args, window, fs, oo, cause)); 748 749 for (oe = options_table; oe->name != NULL; oe++) { 750 if (strcmp(oe->name, name) == 0) 751 break; 752 } 753 if (oe->name == NULL) { 754 xasprintf(cause, "unknown option: %s", name); 755 return (OPTIONS_TABLE_NONE); 756 } 757 switch (oe->scope) { 758 case OPTIONS_TABLE_SERVER: 759 *oo = global_options; 760 scope = OPTIONS_TABLE_SERVER; 761 break; 762 case OPTIONS_TABLE_SESSION: 763 if (args_has(args, 'g')) { 764 *oo = global_s_options; 765 scope = OPTIONS_TABLE_SESSION; 766 } else if (s == NULL && target != NULL) 767 xasprintf(cause, "no such session: %s", target); 768 else if (s == NULL) 769 xasprintf(cause, "no current session"); 770 else { 771 *oo = s->options; 772 scope = OPTIONS_TABLE_SESSION; 773 } 774 break; 775 case OPTIONS_TABLE_WINDOW|OPTIONS_TABLE_PANE: 776 if (args_has(args, 'p')) { 777 if (wp == NULL && target != NULL) 778 xasprintf(cause, "no such pane: %s", target); 779 else if (wp == NULL) 780 xasprintf(cause, "no current pane"); 781 else { 782 *oo = wp->options; 783 scope = OPTIONS_TABLE_PANE; 784 } 785 break; 786 } 787 /* FALLTHROUGH */ 788 case OPTIONS_TABLE_WINDOW: 789 if (args_has(args, 'g')) { 790 *oo = global_w_options; 791 scope = OPTIONS_TABLE_WINDOW; 792 } else if (wl == NULL && target != NULL) 793 xasprintf(cause, "no such window: %s", target); 794 else if (wl == NULL) 795 xasprintf(cause, "no current window"); 796 else { 797 *oo = wl->window->options; 798 scope = OPTIONS_TABLE_WINDOW; 799 } 800 break; 801 } 802 return (scope); 803 } 804 805 int 806 options_scope_from_flags(struct args *args, int window, 807 struct cmd_find_state *fs, struct options **oo, char **cause) 808 { 809 struct session *s = fs->s; 810 struct winlink *wl = fs->wl; 811 struct window_pane *wp = fs->wp; 812 const char *target = args_get(args, 't'); 813 814 if (args_has(args, 's')) { 815 *oo = global_options; 816 return (OPTIONS_TABLE_SERVER); 817 } 818 819 if (args_has(args, 'p')) { 820 if (wp == NULL) { 821 if (target != NULL) 822 xasprintf(cause, "no such pane: %s", target); 823 else 824 xasprintf(cause, "no current pane"); 825 return (OPTIONS_TABLE_NONE); 826 } 827 *oo = wp->options; 828 return (OPTIONS_TABLE_PANE); 829 } else if (window || args_has(args, 'w')) { 830 if (args_has(args, 'g')) { 831 *oo = global_w_options; 832 return (OPTIONS_TABLE_WINDOW); 833 } 834 if (wl == NULL) { 835 if (target != NULL) 836 xasprintf(cause, "no such window: %s", target); 837 else 838 xasprintf(cause, "no current window"); 839 return (OPTIONS_TABLE_NONE); 840 } 841 *oo = wl->window->options; 842 return (OPTIONS_TABLE_WINDOW); 843 } else { 844 if (args_has(args, 'g')) { 845 *oo = global_s_options; 846 return (OPTIONS_TABLE_SESSION); 847 } 848 if (s == NULL) { 849 if (target != NULL) 850 xasprintf(cause, "no such session: %s", target); 851 else 852 xasprintf(cause, "no current session"); 853 return (OPTIONS_TABLE_NONE); 854 } 855 *oo = s->options; 856 return (OPTIONS_TABLE_SESSION); 857 } 858 } 859