1 /* $OpenBSD: cmd-queue.c,v 1.110 2022/05/30 13:00:18 nicm Exp $ */ 2 3 /* 4 * Copyright (c) 2013 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 <pwd.h> 23 #include <stdlib.h> 24 #include <string.h> 25 #include <time.h> 26 #include <unistd.h> 27 28 #include "tmux.h" 29 30 /* Command queue flags. */ 31 #define CMDQ_FIRED 0x1 32 #define CMDQ_WAITING 0x2 33 34 /* Command queue item type. */ 35 enum cmdq_type { 36 CMDQ_COMMAND, 37 CMDQ_CALLBACK, 38 }; 39 40 /* Command queue item. */ 41 struct cmdq_item { 42 char *name; 43 struct cmdq_list *queue; 44 struct cmdq_item *next; 45 46 struct client *client; 47 struct client *target_client; 48 49 enum cmdq_type type; 50 u_int group; 51 52 u_int number; 53 time_t time; 54 55 int flags; 56 57 struct cmdq_state *state; 58 struct cmd_find_state source; 59 struct cmd_find_state target; 60 61 struct cmd_list *cmdlist; 62 struct cmd *cmd; 63 64 cmdq_cb cb; 65 void *data; 66 67 TAILQ_ENTRY(cmdq_item) entry; 68 }; 69 TAILQ_HEAD(cmdq_item_list, cmdq_item); 70 71 /* 72 * Command queue state. This is the context for commands on the command queue. 73 * It holds information about how the commands were fired (the key and flags), 74 * any additional formats for the commands, and the current default target. 75 * Multiple commands can share the same state and a command may update the 76 * default target. 77 */ 78 struct cmdq_state { 79 int references; 80 int flags; 81 82 struct format_tree *formats; 83 84 struct key_event event; 85 struct cmd_find_state current; 86 }; 87 88 /* Command queue. */ 89 struct cmdq_list { 90 struct cmdq_item *item; 91 struct cmdq_item_list list; 92 }; 93 94 /* Get command queue name. */ 95 static const char * 96 cmdq_name(struct client *c) 97 { 98 static char s[256]; 99 100 if (c == NULL) 101 return ("<global>"); 102 if (c->name != NULL) 103 xsnprintf(s, sizeof s, "<%s>", c->name); 104 else 105 xsnprintf(s, sizeof s, "<%p>", c); 106 return (s); 107 } 108 109 /* Get command queue from client. */ 110 static struct cmdq_list * 111 cmdq_get(struct client *c) 112 { 113 static struct cmdq_list *global_queue; 114 115 if (c == NULL) { 116 if (global_queue == NULL) 117 global_queue = cmdq_new(); 118 return (global_queue); 119 } 120 return (c->queue); 121 } 122 123 /* Create a queue. */ 124 struct cmdq_list * 125 cmdq_new(void) 126 { 127 struct cmdq_list *queue; 128 129 queue = xcalloc(1, sizeof *queue); 130 TAILQ_INIT (&queue->list); 131 return (queue); 132 } 133 134 /* Free a queue. */ 135 void 136 cmdq_free(struct cmdq_list *queue) 137 { 138 if (!TAILQ_EMPTY(&queue->list)) 139 fatalx("queue not empty"); 140 free(queue); 141 } 142 143 /* Get item name. */ 144 const char * 145 cmdq_get_name(struct cmdq_item *item) 146 { 147 return (item->name); 148 } 149 150 /* Get item client. */ 151 struct client * 152 cmdq_get_client(struct cmdq_item *item) 153 { 154 return (item->client); 155 } 156 157 /* Get item target client. */ 158 struct client * 159 cmdq_get_target_client(struct cmdq_item *item) 160 { 161 return (item->target_client); 162 } 163 164 /* Get item state. */ 165 struct cmdq_state * 166 cmdq_get_state(struct cmdq_item *item) 167 { 168 return (item->state); 169 } 170 171 /* Get item target. */ 172 struct cmd_find_state * 173 cmdq_get_target(struct cmdq_item *item) 174 { 175 return (&item->target); 176 } 177 178 /* Get item source. */ 179 struct cmd_find_state * 180 cmdq_get_source(struct cmdq_item *item) 181 { 182 return (&item->source); 183 } 184 185 /* Get state event. */ 186 struct key_event * 187 cmdq_get_event(struct cmdq_item *item) 188 { 189 return (&item->state->event); 190 } 191 192 /* Get state current target. */ 193 struct cmd_find_state * 194 cmdq_get_current(struct cmdq_item *item) 195 { 196 return (&item->state->current); 197 } 198 199 /* Get state flags. */ 200 int 201 cmdq_get_flags(struct cmdq_item *item) 202 { 203 return (item->state->flags); 204 } 205 206 /* Create a new state. */ 207 struct cmdq_state * 208 cmdq_new_state(struct cmd_find_state *current, struct key_event *event, 209 int flags) 210 { 211 struct cmdq_state *state; 212 213 state = xcalloc(1, sizeof *state); 214 state->references = 1; 215 state->flags = flags; 216 217 if (event != NULL) 218 memcpy(&state->event, event, sizeof state->event); 219 else 220 state->event.key = KEYC_NONE; 221 if (current != NULL && cmd_find_valid_state(current)) 222 cmd_find_copy_state(&state->current, current); 223 else 224 cmd_find_clear_state(&state->current, 0); 225 226 return (state); 227 } 228 229 /* Add a reference to a state. */ 230 struct cmdq_state * 231 cmdq_link_state(struct cmdq_state *state) 232 { 233 state->references++; 234 return (state); 235 } 236 237 /* Make a copy of a state. */ 238 struct cmdq_state * 239 cmdq_copy_state(struct cmdq_state *state) 240 { 241 return (cmdq_new_state(&state->current, &state->event, state->flags)); 242 } 243 244 /* Free a state. */ 245 void 246 cmdq_free_state(struct cmdq_state *state) 247 { 248 if (--state->references != 0) 249 return; 250 251 if (state->formats != NULL) 252 format_free(state->formats); 253 free(state); 254 } 255 256 /* Add a format to command queue. */ 257 void 258 cmdq_add_format(struct cmdq_state *state, const char *key, const char *fmt, ...) 259 { 260 va_list ap; 261 char *value; 262 263 va_start(ap, fmt); 264 xvasprintf(&value, fmt, ap); 265 va_end(ap); 266 267 if (state->formats == NULL) 268 state->formats = format_create(NULL, NULL, FORMAT_NONE, 0); 269 format_add(state->formats, key, "%s", value); 270 271 free(value); 272 } 273 274 /* Add formats to command queue. */ 275 void 276 cmdq_add_formats(struct cmdq_state *state, struct format_tree *ft) 277 { 278 if (state->formats == NULL) 279 state->formats = format_create(NULL, NULL, FORMAT_NONE, 0); 280 format_merge(state->formats, ft); 281 } 282 283 /* Merge formats from item. */ 284 void 285 cmdq_merge_formats(struct cmdq_item *item, struct format_tree *ft) 286 { 287 const struct cmd_entry *entry; 288 289 if (item->cmd != NULL) { 290 entry = cmd_get_entry(item->cmd); 291 format_add(ft, "command", "%s", entry->name); 292 } 293 if (item->state->formats != NULL) 294 format_merge(ft, item->state->formats); 295 } 296 297 /* Append an item. */ 298 struct cmdq_item * 299 cmdq_append(struct client *c, struct cmdq_item *item) 300 { 301 struct cmdq_list *queue = cmdq_get(c); 302 struct cmdq_item *next; 303 304 do { 305 next = item->next; 306 item->next = NULL; 307 308 if (c != NULL) 309 c->references++; 310 item->client = c; 311 312 item->queue = queue; 313 TAILQ_INSERT_TAIL(&queue->list, item, entry); 314 log_debug("%s %s: %s", __func__, cmdq_name(c), item->name); 315 316 item = next; 317 } while (item != NULL); 318 return (TAILQ_LAST(&queue->list, cmdq_item_list)); 319 } 320 321 /* Insert an item. */ 322 struct cmdq_item * 323 cmdq_insert_after(struct cmdq_item *after, struct cmdq_item *item) 324 { 325 struct client *c = after->client; 326 struct cmdq_list *queue = after->queue; 327 struct cmdq_item *next; 328 329 do { 330 next = item->next; 331 item->next = after->next; 332 after->next = item; 333 334 if (c != NULL) 335 c->references++; 336 item->client = c; 337 338 item->queue = queue; 339 TAILQ_INSERT_AFTER(&queue->list, after, item, entry); 340 log_debug("%s %s: %s after %s", __func__, cmdq_name(c), 341 item->name, after->name); 342 343 after = item; 344 item = next; 345 } while (item != NULL); 346 return (after); 347 } 348 349 /* Insert a hook. */ 350 void 351 cmdq_insert_hook(struct session *s, struct cmdq_item *item, 352 struct cmd_find_state *current, const char *fmt, ...) 353 { 354 struct cmdq_state *state = item->state; 355 struct cmd *cmd = item->cmd; 356 struct args *args = cmd_get_args(cmd); 357 struct args_entry *ae; 358 struct args_value *av; 359 struct options *oo; 360 va_list ap; 361 char *name, tmp[32], flag, *arguments; 362 u_int i; 363 const char *value; 364 struct cmdq_item *new_item; 365 struct cmdq_state *new_state; 366 struct options_entry *o; 367 struct options_array_item *a; 368 struct cmd_list *cmdlist; 369 370 if (item->state->flags & CMDQ_STATE_NOHOOKS) 371 return; 372 if (s == NULL) 373 oo = global_s_options; 374 else 375 oo = s->options; 376 377 va_start(ap, fmt); 378 xvasprintf(&name, fmt, ap); 379 va_end(ap); 380 381 o = options_get(oo, name); 382 if (o == NULL) { 383 free(name); 384 return; 385 } 386 log_debug("running hook %s (parent %p)", name, item); 387 388 /* 389 * The hooks get a new state because they should not update the current 390 * target or formats for any subsequent commands. 391 */ 392 new_state = cmdq_new_state(current, &state->event, CMDQ_STATE_NOHOOKS); 393 cmdq_add_format(new_state, "hook", "%s", name); 394 395 arguments = args_print(args); 396 cmdq_add_format(new_state, "hook_arguments", "%s", arguments); 397 free(arguments); 398 399 for (i = 0; i < args_count(args); i++) { 400 xsnprintf(tmp, sizeof tmp, "hook_argument_%d", i); 401 cmdq_add_format(new_state, tmp, "%s", args_string(args, i)); 402 } 403 flag = args_first(args, &ae); 404 while (flag != 0) { 405 value = args_get(args, flag); 406 if (value == NULL) { 407 xsnprintf(tmp, sizeof tmp, "hook_flag_%c", flag); 408 cmdq_add_format(new_state, tmp, "1"); 409 } else { 410 xsnprintf(tmp, sizeof tmp, "hook_flag_%c", flag); 411 cmdq_add_format(new_state, tmp, "%s", value); 412 } 413 414 i = 0; 415 av = args_first_value(args, flag); 416 while (av != NULL) { 417 xsnprintf(tmp, sizeof tmp, "hook_flag_%c_%d", flag, i); 418 cmdq_add_format(new_state, tmp, "%s", av->string); 419 i++; 420 av = args_next_value(av); 421 } 422 423 flag = args_next(&ae); 424 } 425 426 a = options_array_first(o); 427 while (a != NULL) { 428 cmdlist = options_array_item_value(a)->cmdlist; 429 if (cmdlist != NULL) { 430 new_item = cmdq_get_command(cmdlist, new_state); 431 if (item != NULL) 432 item = cmdq_insert_after(item, new_item); 433 else 434 item = cmdq_append(NULL, new_item); 435 } 436 a = options_array_next(a); 437 } 438 439 cmdq_free_state(new_state); 440 free(name); 441 } 442 443 /* Continue processing command queue. */ 444 void 445 cmdq_continue(struct cmdq_item *item) 446 { 447 item->flags &= ~CMDQ_WAITING; 448 } 449 450 /* Remove an item. */ 451 static void 452 cmdq_remove(struct cmdq_item *item) 453 { 454 if (item->client != NULL) 455 server_client_unref(item->client); 456 if (item->cmdlist != NULL) 457 cmd_list_free(item->cmdlist); 458 cmdq_free_state(item->state); 459 460 TAILQ_REMOVE(&item->queue->list, item, entry); 461 462 free(item->name); 463 free(item); 464 } 465 466 /* Remove all subsequent items that match this item's group. */ 467 static void 468 cmdq_remove_group(struct cmdq_item *item) 469 { 470 struct cmdq_item *this, *next; 471 472 if (item->group == 0) 473 return; 474 this = TAILQ_NEXT(item, entry); 475 while (this != NULL) { 476 next = TAILQ_NEXT(this, entry); 477 if (this->group == item->group) 478 cmdq_remove(this); 479 this = next; 480 } 481 } 482 483 /* Empty command callback. */ 484 static enum cmd_retval 485 cmdq_empty_command(__unused struct cmdq_item *item, __unused void *data) 486 { 487 return (CMD_RETURN_NORMAL); 488 } 489 490 /* Get a command for the command queue. */ 491 struct cmdq_item * 492 cmdq_get_command(struct cmd_list *cmdlist, struct cmdq_state *state) 493 { 494 struct cmdq_item *item, *first = NULL, *last = NULL; 495 struct cmd *cmd; 496 const struct cmd_entry *entry; 497 int created = 0; 498 499 if ((cmd = cmd_list_first(cmdlist)) == NULL) 500 return (cmdq_get_callback(cmdq_empty_command, NULL)); 501 502 if (state == NULL) { 503 state = cmdq_new_state(NULL, NULL, 0); 504 created = 1; 505 } 506 507 while (cmd != NULL) { 508 entry = cmd_get_entry(cmd); 509 510 item = xcalloc(1, sizeof *item); 511 xasprintf(&item->name, "[%s/%p]", entry->name, item); 512 item->type = CMDQ_COMMAND; 513 514 item->group = cmd_get_group(cmd); 515 item->state = cmdq_link_state(state); 516 517 item->cmdlist = cmdlist; 518 item->cmd = cmd; 519 520 cmdlist->references++; 521 log_debug("%s: %s group %u", __func__, item->name, item->group); 522 523 if (first == NULL) 524 first = item; 525 if (last != NULL) 526 last->next = item; 527 last = item; 528 529 cmd = cmd_list_next(cmd); 530 } 531 532 if (created) 533 cmdq_free_state(state); 534 return (first); 535 } 536 537 /* Fill in flag for a command. */ 538 static enum cmd_retval 539 cmdq_find_flag(struct cmdq_item *item, struct cmd_find_state *fs, 540 const struct cmd_entry_flag *flag) 541 { 542 const char *value; 543 544 if (flag->flag == 0) { 545 cmd_find_from_client(fs, item->target_client, 0); 546 return (CMD_RETURN_NORMAL); 547 } 548 549 value = args_get(cmd_get_args(item->cmd), flag->flag); 550 if (cmd_find_target(fs, item, value, flag->type, flag->flags) != 0) { 551 cmd_find_clear_state(fs, 0); 552 return (CMD_RETURN_ERROR); 553 } 554 return (CMD_RETURN_NORMAL); 555 } 556 557 /* Add message with command. */ 558 static void 559 cmdq_add_message(struct cmdq_item *item) 560 { 561 struct client *c = item->client; 562 struct cmdq_state *state = item->state; 563 const char *key; 564 char *tmp; 565 uid_t uid; 566 struct passwd *pw; 567 char *user = NULL; 568 569 tmp = cmd_print(item->cmd); 570 if (c != NULL) { 571 uid = proc_get_peer_uid(c->peer); 572 if (uid != (uid_t)-1 && uid != getuid()) { 573 if ((pw = getpwuid(uid)) != NULL) 574 xasprintf(&user, "[%s]", pw->pw_name); 575 else 576 user = xstrdup("[unknown]"); 577 } else 578 user = xstrdup(""); 579 if (c->session != NULL && state->event.key != KEYC_NONE) { 580 key = key_string_lookup_key(state->event.key, 0); 581 server_add_message("%s%s key %s: %s", c->name, user, 582 key, tmp); 583 } else { 584 server_add_message("%s%s command: %s", c->name, user, 585 tmp); 586 } 587 free(user); 588 } else 589 server_add_message("command: %s", tmp); 590 free(tmp); 591 } 592 593 /* Fire command on command queue. */ 594 static enum cmd_retval 595 cmdq_fire_command(struct cmdq_item *item) 596 { 597 const char *name = cmdq_name(item->client); 598 struct cmdq_state *state = item->state; 599 struct cmd *cmd = item->cmd; 600 struct args *args = cmd_get_args(cmd); 601 const struct cmd_entry *entry = cmd_get_entry(cmd); 602 struct client *tc, *saved = item->client; 603 enum cmd_retval retval; 604 struct cmd_find_state *fsp, fs; 605 int flags, quiet = 0; 606 char *tmp; 607 608 if (cfg_finished) 609 cmdq_add_message(item); 610 if (log_get_level() > 1) { 611 tmp = cmd_print(cmd); 612 log_debug("%s %s: (%u) %s", __func__, name, item->group, tmp); 613 free(tmp); 614 } 615 616 flags = !!(state->flags & CMDQ_STATE_CONTROL); 617 cmdq_guard(item, "begin", flags); 618 619 if (item->client == NULL) 620 item->client = cmd_find_client(item, NULL, 1); 621 622 if (entry->flags & CMD_CLIENT_CANFAIL) 623 quiet = 1; 624 if (entry->flags & CMD_CLIENT_CFLAG) { 625 tc = cmd_find_client(item, args_get(args, 'c'), quiet); 626 if (tc == NULL && !quiet) { 627 retval = CMD_RETURN_ERROR; 628 goto out; 629 } 630 } else if (entry->flags & CMD_CLIENT_TFLAG) { 631 tc = cmd_find_client(item, args_get(args, 't'), quiet); 632 if (tc == NULL && !quiet) { 633 retval = CMD_RETURN_ERROR; 634 goto out; 635 } 636 } else 637 tc = cmd_find_client(item, NULL, 1); 638 item->target_client = tc; 639 640 retval = cmdq_find_flag(item, &item->source, &entry->source); 641 if (retval == CMD_RETURN_ERROR) 642 goto out; 643 retval = cmdq_find_flag(item, &item->target, &entry->target); 644 if (retval == CMD_RETURN_ERROR) 645 goto out; 646 647 retval = entry->exec(cmd, item); 648 if (retval == CMD_RETURN_ERROR) 649 goto out; 650 651 if (entry->flags & CMD_AFTERHOOK) { 652 if (cmd_find_valid_state(&item->target)) 653 fsp = &item->target; 654 else if (cmd_find_valid_state(&item->state->current)) 655 fsp = &item->state->current; 656 else if (cmd_find_from_client(&fs, item->client, 0) == 0) 657 fsp = &fs; 658 else 659 goto out; 660 cmdq_insert_hook(fsp->s, item, fsp, "after-%s", entry->name); 661 } 662 663 out: 664 item->client = saved; 665 if (retval == CMD_RETURN_ERROR) 666 cmdq_guard(item, "error", flags); 667 else 668 cmdq_guard(item, "end", flags); 669 return (retval); 670 } 671 672 /* Get a callback for the command queue. */ 673 struct cmdq_item * 674 cmdq_get_callback1(const char *name, cmdq_cb cb, void *data) 675 { 676 struct cmdq_item *item; 677 678 item = xcalloc(1, sizeof *item); 679 xasprintf(&item->name, "[%s/%p]", name, item); 680 item->type = CMDQ_CALLBACK; 681 682 item->group = 0; 683 item->state = cmdq_new_state(NULL, NULL, 0); 684 685 item->cb = cb; 686 item->data = data; 687 688 return (item); 689 } 690 691 /* Generic error callback. */ 692 static enum cmd_retval 693 cmdq_error_callback(struct cmdq_item *item, void *data) 694 { 695 char *error = data; 696 697 cmdq_error(item, "%s", error); 698 free(error); 699 700 return (CMD_RETURN_NORMAL); 701 } 702 703 /* Get an error callback for the command queue. */ 704 struct cmdq_item * 705 cmdq_get_error(const char *error) 706 { 707 return (cmdq_get_callback(cmdq_error_callback, xstrdup(error))); 708 } 709 710 /* Fire callback on callback queue. */ 711 static enum cmd_retval 712 cmdq_fire_callback(struct cmdq_item *item) 713 { 714 return (item->cb(item, item->data)); 715 } 716 717 /* Process next item on command queue. */ 718 u_int 719 cmdq_next(struct client *c) 720 { 721 struct cmdq_list *queue = cmdq_get(c); 722 const char *name = cmdq_name(c); 723 struct cmdq_item *item; 724 enum cmd_retval retval; 725 u_int items = 0; 726 static u_int number; 727 728 if (TAILQ_EMPTY(&queue->list)) { 729 log_debug("%s %s: empty", __func__, name); 730 return (0); 731 } 732 if (TAILQ_FIRST(&queue->list)->flags & CMDQ_WAITING) { 733 log_debug("%s %s: waiting", __func__, name); 734 return (0); 735 } 736 737 log_debug("%s %s: enter", __func__, name); 738 for (;;) { 739 item = queue->item = TAILQ_FIRST(&queue->list); 740 if (item == NULL) 741 break; 742 log_debug("%s %s: %s (%d), flags %x", __func__, name, 743 item->name, item->type, item->flags); 744 745 /* 746 * Any item with the waiting flag set waits until an external 747 * event clears the flag (for example, a job - look at 748 * run-shell). 749 */ 750 if (item->flags & CMDQ_WAITING) 751 goto waiting; 752 753 /* 754 * Items are only fired once, once the fired flag is set, a 755 * waiting flag can only be cleared by an external event. 756 */ 757 if (~item->flags & CMDQ_FIRED) { 758 item->time = time(NULL); 759 item->number = ++number; 760 761 switch (item->type) { 762 case CMDQ_COMMAND: 763 retval = cmdq_fire_command(item); 764 765 /* 766 * If a command returns an error, remove any 767 * subsequent commands in the same group. 768 */ 769 if (retval == CMD_RETURN_ERROR) 770 cmdq_remove_group(item); 771 break; 772 case CMDQ_CALLBACK: 773 retval = cmdq_fire_callback(item); 774 break; 775 default: 776 retval = CMD_RETURN_ERROR; 777 break; 778 } 779 item->flags |= CMDQ_FIRED; 780 781 if (retval == CMD_RETURN_WAIT) { 782 item->flags |= CMDQ_WAITING; 783 goto waiting; 784 } 785 items++; 786 } 787 cmdq_remove(item); 788 } 789 queue->item = NULL; 790 791 log_debug("%s %s: exit (empty)", __func__, name); 792 return (items); 793 794 waiting: 795 log_debug("%s %s: exit (wait)", __func__, name); 796 return (items); 797 } 798 799 /* Get running item if any. */ 800 struct cmdq_item * 801 cmdq_running(struct client *c) 802 { 803 struct cmdq_list *queue = cmdq_get(c); 804 805 if (queue->item == NULL) 806 return (NULL); 807 if (queue->item->flags & CMDQ_WAITING) 808 return (NULL); 809 return (queue->item); 810 } 811 812 /* Print a guard line. */ 813 void 814 cmdq_guard(struct cmdq_item *item, const char *guard, int flags) 815 { 816 struct client *c = item->client; 817 long t = item->time; 818 u_int number = item->number; 819 820 if (c != NULL && (c->flags & CLIENT_CONTROL)) 821 control_write(c, "%%%s %ld %u %d", guard, t, number, flags); 822 } 823 824 /* Show message from command. */ 825 void 826 cmdq_print(struct cmdq_item *item, const char *fmt, ...) 827 { 828 struct client *c = item->client; 829 struct window_pane *wp; 830 struct window_mode_entry *wme; 831 va_list ap; 832 char *tmp, *msg; 833 834 va_start(ap, fmt); 835 xvasprintf(&msg, fmt, ap); 836 va_end(ap); 837 838 log_debug("%s: %s", __func__, msg); 839 840 if (c == NULL) 841 /* nothing */; 842 else if (c->session == NULL || (c->flags & CLIENT_CONTROL)) { 843 if (~c->flags & CLIENT_UTF8) { 844 tmp = msg; 845 msg = utf8_sanitize(tmp); 846 free(tmp); 847 } 848 if (c->flags & CLIENT_CONTROL) 849 control_write(c, "%s", msg); 850 else 851 file_print(c, "%s\n", msg); 852 } else { 853 wp = server_client_get_pane(c); 854 wme = TAILQ_FIRST(&wp->modes); 855 if (wme == NULL || wme->mode != &window_view_mode) { 856 window_pane_set_mode(wp, NULL, &window_view_mode, NULL, 857 NULL); 858 } 859 window_copy_add(wp, 0, "%s", msg); 860 } 861 862 free(msg); 863 } 864 865 /* Show error from command. */ 866 void 867 cmdq_error(struct cmdq_item *item, const char *fmt, ...) 868 { 869 struct client *c = item->client; 870 struct cmd *cmd = item->cmd; 871 va_list ap; 872 char *msg, *tmp; 873 const char *file; 874 u_int line; 875 876 va_start(ap, fmt); 877 xvasprintf(&msg, fmt, ap); 878 va_end(ap); 879 880 log_debug("%s: %s", __func__, msg); 881 882 if (c == NULL) { 883 cmd_get_source(cmd, &file, &line); 884 cfg_add_cause("%s:%u: %s", file, line, msg); 885 } else if (c->session == NULL || (c->flags & CLIENT_CONTROL)) { 886 server_add_message("%s message: %s", c->name, msg); 887 if (~c->flags & CLIENT_UTF8) { 888 tmp = msg; 889 msg = utf8_sanitize(tmp); 890 free(tmp); 891 } 892 if (c->flags & CLIENT_CONTROL) 893 control_write(c, "%s", msg); 894 else 895 file_error(c, "%s\n", msg); 896 c->retval = 1; 897 } else { 898 *msg = toupper((u_char) *msg); 899 status_message_set(c, -1, 1, 0, "%s", msg); 900 } 901 902 free(msg); 903 } 904