1 /* $OpenBSD: server-client.c,v 1.186 2016/04/30 18:59:02 nicm Exp $ */ 2 3 /* 4 * Copyright (c) 2009 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 #include <sys/ioctl.h> 21 #include <sys/uio.h> 22 23 #include <errno.h> 24 #include <event.h> 25 #include <fcntl.h> 26 #include <imsg.h> 27 #include <paths.h> 28 #include <stdlib.h> 29 #include <string.h> 30 #include <time.h> 31 #include <unistd.h> 32 33 #include "tmux.h" 34 35 void server_client_free(int, short, void *); 36 void server_client_check_focus(struct window_pane *); 37 void server_client_check_resize(struct window_pane *); 38 key_code server_client_check_mouse(struct client *); 39 void server_client_repeat_timer(int, short, void *); 40 void server_client_check_exit(struct client *); 41 void server_client_check_redraw(struct client *); 42 void server_client_set_title(struct client *); 43 void server_client_reset_state(struct client *); 44 int server_client_assume_paste(struct session *); 45 46 void server_client_dispatch(struct imsg *, void *); 47 void server_client_dispatch_command(struct client *, struct imsg *); 48 void server_client_dispatch_identify(struct client *, struct imsg *); 49 void server_client_dispatch_shell(struct client *); 50 51 /* Check if this client is inside this server. */ 52 int 53 server_client_check_nested(struct client *c) 54 { 55 struct environ_entry *envent; 56 struct window_pane *wp; 57 58 if (c->tty.path == NULL) 59 return (0); 60 61 envent = environ_find(c->environ, "TMUX"); 62 if (envent == NULL || *envent->value == '\0') 63 return (0); 64 65 RB_FOREACH(wp, window_pane_tree, &all_window_panes) { 66 if (strcmp(wp->tty, c->tty.path) == 0) 67 return (1); 68 } 69 return (0); 70 } 71 72 /* Set client key table. */ 73 void 74 server_client_set_key_table(struct client *c, const char *name) 75 { 76 if (name == NULL) 77 name = server_client_get_key_table(c); 78 79 key_bindings_unref_table(c->keytable); 80 c->keytable = key_bindings_get_table(name, 1); 81 c->keytable->references++; 82 } 83 84 /* Get default key table. */ 85 const char * 86 server_client_get_key_table(struct client *c) 87 { 88 struct session *s = c->session; 89 const char *name; 90 91 if (s == NULL) 92 return ("root"); 93 94 name = options_get_string(s->options, "key-table"); 95 if (*name == '\0') 96 return ("root"); 97 return (name); 98 } 99 100 /* Create a new client. */ 101 void 102 server_client_create(int fd) 103 { 104 struct client *c; 105 106 setblocking(fd, 0); 107 108 c = xcalloc(1, sizeof *c); 109 c->references = 1; 110 c->peer = proc_add_peer(server_proc, fd, server_client_dispatch, c); 111 112 if (gettimeofday(&c->creation_time, NULL) != 0) 113 fatal("gettimeofday failed"); 114 memcpy(&c->activity_time, &c->creation_time, sizeof c->activity_time); 115 116 c->environ = environ_create(); 117 118 c->fd = -1; 119 c->cwd = NULL; 120 121 c->cmdq = cmdq_new(c); 122 c->cmdq->client_exit = 1; 123 124 c->stdin_data = evbuffer_new(); 125 c->stdout_data = evbuffer_new(); 126 c->stderr_data = evbuffer_new(); 127 128 c->tty.fd = -1; 129 c->title = NULL; 130 131 c->session = NULL; 132 c->last_session = NULL; 133 c->tty.sx = 80; 134 c->tty.sy = 24; 135 136 screen_init(&c->status, c->tty.sx, 1, 0); 137 138 c->message_string = NULL; 139 TAILQ_INIT(&c->message_log); 140 141 c->prompt_string = NULL; 142 c->prompt_buffer = NULL; 143 c->prompt_index = 0; 144 145 c->flags |= CLIENT_FOCUSED; 146 147 c->keytable = key_bindings_get_table("root", 1); 148 c->keytable->references++; 149 150 evtimer_set(&c->repeat_timer, server_client_repeat_timer, c); 151 152 TAILQ_INSERT_TAIL(&clients, c, entry); 153 log_debug("new client %p", c); 154 } 155 156 /* Open client terminal if needed. */ 157 int 158 server_client_open(struct client *c, char **cause) 159 { 160 if (c->flags & CLIENT_CONTROL) 161 return (0); 162 163 if (strcmp(c->ttyname, "/dev/tty") == 0) { 164 *cause = xstrdup("can't use /dev/tty"); 165 return (-1); 166 } 167 168 if (!(c->flags & CLIENT_TERMINAL)) { 169 *cause = xstrdup("not a terminal"); 170 return (-1); 171 } 172 173 if (tty_open(&c->tty, cause) != 0) 174 return (-1); 175 176 return (0); 177 } 178 179 /* Lost a client. */ 180 void 181 server_client_lost(struct client *c) 182 { 183 struct message_entry *msg, *msg1; 184 185 c->flags |= CLIENT_DEAD; 186 187 status_prompt_clear(c); 188 status_message_clear(c); 189 190 if (c->stdin_callback != NULL) 191 c->stdin_callback(c, 1, c->stdin_callback_data); 192 193 TAILQ_REMOVE(&clients, c, entry); 194 log_debug("lost client %p", c); 195 196 /* 197 * If CLIENT_TERMINAL hasn't been set, then tty_init hasn't been called 198 * and tty_free might close an unrelated fd. 199 */ 200 if (c->flags & CLIENT_TERMINAL) 201 tty_free(&c->tty); 202 free(c->ttyname); 203 free(c->term); 204 205 evbuffer_free(c->stdin_data); 206 evbuffer_free(c->stdout_data); 207 if (c->stderr_data != c->stdout_data) 208 evbuffer_free(c->stderr_data); 209 210 if (event_initialized(&c->status_timer)) 211 evtimer_del(&c->status_timer); 212 screen_free(&c->status); 213 214 free(c->title); 215 free((void *)c->cwd); 216 217 evtimer_del(&c->repeat_timer); 218 219 key_bindings_unref_table(c->keytable); 220 221 if (event_initialized(&c->identify_timer)) 222 evtimer_del(&c->identify_timer); 223 224 free(c->message_string); 225 if (event_initialized(&c->message_timer)) 226 evtimer_del(&c->message_timer); 227 TAILQ_FOREACH_SAFE(msg, &c->message_log, entry, msg1) { 228 free(msg->msg); 229 TAILQ_REMOVE(&c->message_log, msg, entry); 230 free(msg); 231 } 232 233 free(c->prompt_string); 234 free(c->prompt_buffer); 235 236 c->cmdq->flags |= CMD_Q_DEAD; 237 cmdq_free(c->cmdq); 238 c->cmdq = NULL; 239 240 environ_free(c->environ); 241 242 proc_remove_peer(c->peer); 243 c->peer = NULL; 244 245 server_client_unref(c); 246 247 server_add_accept(0); /* may be more file descriptors now */ 248 249 recalculate_sizes(); 250 server_check_unattached(); 251 server_update_socket(); 252 } 253 254 /* Remove reference from a client. */ 255 void 256 server_client_unref(struct client *c) 257 { 258 log_debug("unref client %p (%d references)", c, c->references); 259 260 c->references--; 261 if (c->references == 0) 262 event_once(-1, EV_TIMEOUT, server_client_free, c, NULL); 263 } 264 265 /* Free dead client. */ 266 void 267 server_client_free(__unused int fd, __unused short events, void *arg) 268 { 269 struct client *c = arg; 270 271 log_debug("free client %p (%d references)", c, c->references); 272 273 if (c->references == 0) 274 free(c); 275 } 276 277 /* Detach a client. */ 278 void 279 server_client_detach(struct client *c, enum msgtype msgtype) 280 { 281 struct session *s = c->session; 282 283 if (s == NULL) 284 return; 285 286 hooks_run(c->session->hooks, c, NULL, "client-detached"); 287 proc_send_s(c->peer, msgtype, s->name); 288 } 289 290 /* Check for mouse keys. */ 291 key_code 292 server_client_check_mouse(struct client *c) 293 { 294 struct session *s = c->session; 295 struct mouse_event *m = &c->tty.mouse; 296 struct window *w; 297 struct window_pane *wp; 298 enum { NOTYPE, DOWN, UP, DRAG, WHEEL } type = NOTYPE; 299 enum { NOWHERE, PANE, STATUS, BORDER } where = NOWHERE; 300 u_int x, y, b; 301 key_code key; 302 303 log_debug("mouse %02x at %u,%u (last %u,%u) (%d)", m->b, m->x, m->y, 304 m->lx, m->ly, c->tty.mouse_drag_flag); 305 306 /* What type of event is this? */ 307 if (MOUSE_DRAG(m->b)) { 308 type = DRAG; 309 if (c->tty.mouse_drag_flag) { 310 x = m->x, y = m->y, b = m->b; 311 log_debug("drag update at %u,%u", x, y); 312 } else { 313 x = m->lx, y = m->ly, b = m->lb; 314 log_debug("drag start at %u,%u", x, y); 315 } 316 } else if (MOUSE_WHEEL(m->b)) { 317 type = WHEEL; 318 x = m->x, y = m->y, b = m->b; 319 log_debug("wheel at %u,%u", x, y); 320 } else if (MOUSE_BUTTONS(m->b) == 3) { 321 type = UP; 322 x = m->x, y = m->y, b = m->lb; 323 log_debug("up at %u,%u", x, y); 324 } else { 325 type = DOWN; 326 x = m->x, y = m->y, b = m->b; 327 log_debug("down at %u,%u", x, y); 328 } 329 if (type == NOTYPE) 330 return (KEYC_UNKNOWN); 331 332 /* Always save the session. */ 333 m->s = s->id; 334 335 /* Is this on the status line? */ 336 m->statusat = status_at_line(c); 337 if (m->statusat != -1 && y == (u_int)m->statusat) { 338 w = status_get_window_at(c, x); 339 if (w == NULL) 340 return (KEYC_UNKNOWN); 341 m->w = w->id; 342 where = STATUS; 343 } else 344 m->w = -1; 345 346 /* Not on status line. Adjust position and check for border or pane. */ 347 if (where == NOWHERE) { 348 if (m->statusat == 0 && y > 0) 349 y--; 350 else if (m->statusat > 0 && y >= (u_int)m->statusat) 351 y = m->statusat - 1; 352 353 TAILQ_FOREACH(wp, &s->curw->window->panes, entry) { 354 if ((wp->xoff + wp->sx == x && 355 wp->yoff <= 1 + y && 356 wp->yoff + wp->sy >= y) || 357 (wp->yoff + wp->sy == y && 358 wp->xoff <= 1 + x && 359 wp->xoff + wp->sx >= x)) 360 break; 361 } 362 if (wp != NULL) 363 where = BORDER; 364 else { 365 wp = window_get_active_at(s->curw->window, x, y); 366 if (wp != NULL) { 367 where = PANE; 368 log_debug("mouse at %u,%u is on pane %%%u", 369 x, y, wp->id); 370 } 371 } 372 if (where == NOWHERE) 373 return (KEYC_UNKNOWN); 374 m->wp = wp->id; 375 m->w = wp->window->id; 376 } else 377 m->wp = -1; 378 379 /* Stop dragging if needed. */ 380 if (type != DRAG && c->tty.mouse_drag_flag) { 381 if (c->tty.mouse_drag_release != NULL) 382 c->tty.mouse_drag_release(c, m); 383 384 c->tty.mouse_drag_update = NULL; 385 c->tty.mouse_drag_release = NULL; 386 387 /* 388 * End a mouse drag by passing a MouseDragEnd key corresponding 389 * to the button that started the drag. 390 */ 391 switch (c->tty.mouse_drag_flag) { 392 case 1: 393 if (where == PANE) 394 key = KEYC_MOUSEDRAGEND1_PANE; 395 if (where == STATUS) 396 key = KEYC_MOUSEDRAGEND1_STATUS; 397 if (where == BORDER) 398 key = KEYC_MOUSEDRAGEND1_BORDER; 399 break; 400 case 2: 401 if (where == PANE) 402 key = KEYC_MOUSEDRAGEND2_PANE; 403 if (where == STATUS) 404 key = KEYC_MOUSEDRAGEND2_STATUS; 405 if (where == BORDER) 406 key = KEYC_MOUSEDRAGEND2_BORDER; 407 break; 408 case 3: 409 if (where == PANE) 410 key = KEYC_MOUSEDRAGEND3_PANE; 411 if (where == STATUS) 412 key = KEYC_MOUSEDRAGEND3_STATUS; 413 if (where == BORDER) 414 key = KEYC_MOUSEDRAGEND3_BORDER; 415 break; 416 default: 417 key = KEYC_MOUSE; 418 break; 419 } 420 c->tty.mouse_drag_flag = 0; 421 422 return (key); 423 } 424 425 /* Convert to a key binding. */ 426 key = KEYC_UNKNOWN; 427 switch (type) { 428 case NOTYPE: 429 break; 430 case DRAG: 431 if (c->tty.mouse_drag_update != NULL) 432 c->tty.mouse_drag_update(c, m); 433 else { 434 switch (MOUSE_BUTTONS(b)) { 435 case 0: 436 if (where == PANE) 437 key = KEYC_MOUSEDRAG1_PANE; 438 if (where == STATUS) 439 key = KEYC_MOUSEDRAG1_STATUS; 440 if (where == BORDER) 441 key = KEYC_MOUSEDRAG1_BORDER; 442 break; 443 case 1: 444 if (where == PANE) 445 key = KEYC_MOUSEDRAG2_PANE; 446 if (where == STATUS) 447 key = KEYC_MOUSEDRAG2_STATUS; 448 if (where == BORDER) 449 key = KEYC_MOUSEDRAG2_BORDER; 450 break; 451 case 2: 452 if (where == PANE) 453 key = KEYC_MOUSEDRAG3_PANE; 454 if (where == STATUS) 455 key = KEYC_MOUSEDRAG3_STATUS; 456 if (where == BORDER) 457 key = KEYC_MOUSEDRAG3_BORDER; 458 break; 459 } 460 } 461 462 /* 463 * Begin a drag by setting the flag to a non-zero value that 464 * corresponds to the mouse button in use. 465 */ 466 c->tty.mouse_drag_flag = MOUSE_BUTTONS(b) + 1; 467 break; 468 case WHEEL: 469 if (MOUSE_BUTTONS(b) == MOUSE_WHEEL_UP) { 470 if (where == PANE) 471 key = KEYC_WHEELUP_PANE; 472 if (where == STATUS) 473 key = KEYC_WHEELUP_STATUS; 474 if (where == BORDER) 475 key = KEYC_WHEELUP_BORDER; 476 } else { 477 if (where == PANE) 478 key = KEYC_WHEELDOWN_PANE; 479 if (where == STATUS) 480 key = KEYC_WHEELDOWN_STATUS; 481 if (where == BORDER) 482 key = KEYC_WHEELDOWN_BORDER; 483 } 484 break; 485 case UP: 486 switch (MOUSE_BUTTONS(b)) { 487 case 0: 488 if (where == PANE) 489 key = KEYC_MOUSEUP1_PANE; 490 if (where == STATUS) 491 key = KEYC_MOUSEUP1_STATUS; 492 if (where == BORDER) 493 key = KEYC_MOUSEUP1_BORDER; 494 break; 495 case 1: 496 if (where == PANE) 497 key = KEYC_MOUSEUP2_PANE; 498 if (where == STATUS) 499 key = KEYC_MOUSEUP2_STATUS; 500 if (where == BORDER) 501 key = KEYC_MOUSEUP2_BORDER; 502 break; 503 case 2: 504 if (where == PANE) 505 key = KEYC_MOUSEUP3_PANE; 506 if (where == STATUS) 507 key = KEYC_MOUSEUP3_STATUS; 508 if (where == BORDER) 509 key = KEYC_MOUSEUP3_BORDER; 510 break; 511 } 512 break; 513 case DOWN: 514 switch (MOUSE_BUTTONS(b)) { 515 case 0: 516 if (where == PANE) 517 key = KEYC_MOUSEDOWN1_PANE; 518 if (where == STATUS) 519 key = KEYC_MOUSEDOWN1_STATUS; 520 if (where == BORDER) 521 key = KEYC_MOUSEDOWN1_BORDER; 522 break; 523 case 1: 524 if (where == PANE) 525 key = KEYC_MOUSEDOWN2_PANE; 526 if (where == STATUS) 527 key = KEYC_MOUSEDOWN2_STATUS; 528 if (where == BORDER) 529 key = KEYC_MOUSEDOWN2_BORDER; 530 break; 531 case 2: 532 if (where == PANE) 533 key = KEYC_MOUSEDOWN3_PANE; 534 if (where == STATUS) 535 key = KEYC_MOUSEDOWN3_STATUS; 536 if (where == BORDER) 537 key = KEYC_MOUSEDOWN3_BORDER; 538 break; 539 } 540 break; 541 } 542 if (key == KEYC_UNKNOWN) 543 return (KEYC_UNKNOWN); 544 545 /* Apply modifiers if any. */ 546 if (b & MOUSE_MASK_META) 547 key |= KEYC_ESCAPE; 548 if (b & MOUSE_MASK_CTRL) 549 key |= KEYC_CTRL; 550 if (b & MOUSE_MASK_SHIFT) 551 key |= KEYC_SHIFT; 552 553 return (key); 554 } 555 556 /* Is this fast enough to probably be a paste? */ 557 int 558 server_client_assume_paste(struct session *s) 559 { 560 struct timeval tv; 561 int t; 562 563 if ((t = options_get_number(s->options, "assume-paste-time")) == 0) 564 return (0); 565 566 timersub(&s->activity_time, &s->last_activity_time, &tv); 567 if (tv.tv_sec == 0 && tv.tv_usec < t * 1000) { 568 log_debug("session %s pasting (flag %d)", s->name, 569 !!(s->flags & SESSION_PASTING)); 570 if (s->flags & SESSION_PASTING) 571 return (1); 572 s->flags |= SESSION_PASTING; 573 return (0); 574 } 575 log_debug("session %s not pasting", s->name); 576 s->flags &= ~SESSION_PASTING; 577 return (0); 578 } 579 580 /* Handle data key input from client. */ 581 void 582 server_client_handle_key(struct client *c, key_code key) 583 { 584 struct mouse_event *m = &c->tty.mouse; 585 struct session *s = c->session; 586 struct window *w; 587 struct window_pane *wp; 588 struct timeval tv; 589 struct key_table *table; 590 struct key_binding bd_find, *bd; 591 int xtimeout; 592 593 /* Check the client is good to accept input. */ 594 if (s == NULL || (c->flags & (CLIENT_DEAD|CLIENT_SUSPENDED)) != 0) 595 return; 596 w = s->curw->window; 597 598 /* Update the activity timer. */ 599 if (gettimeofday(&c->activity_time, NULL) != 0) 600 fatal("gettimeofday failed"); 601 session_update_activity(s, &c->activity_time); 602 603 /* Number keys jump to pane in identify mode. */ 604 if (c->flags & CLIENT_IDENTIFY && key >= '0' && key <= '9') { 605 if (c->flags & CLIENT_READONLY) 606 return; 607 window_unzoom(w); 608 wp = window_pane_at_index(w, key - '0'); 609 if (wp != NULL && window_pane_visible(wp)) 610 window_set_active_pane(w, wp); 611 server_clear_identify(c); 612 return; 613 } 614 615 /* Handle status line. */ 616 if (!(c->flags & CLIENT_READONLY)) { 617 status_message_clear(c); 618 server_clear_identify(c); 619 } 620 if (c->prompt_string != NULL) { 621 if (!(c->flags & CLIENT_READONLY)) 622 status_prompt_key(c, key); 623 return; 624 } 625 626 /* Check for mouse keys. */ 627 if (key == KEYC_MOUSE) { 628 if (c->flags & CLIENT_READONLY) 629 return; 630 key = server_client_check_mouse(c); 631 if (key == KEYC_UNKNOWN) 632 return; 633 634 m->valid = 1; 635 m->key = key; 636 637 if (!options_get_number(s->options, "mouse")) 638 goto forward; 639 } else 640 m->valid = 0; 641 642 /* Treat everything as a regular key when pasting is detected. */ 643 if (!KEYC_IS_MOUSE(key) && server_client_assume_paste(s)) 644 goto forward; 645 646 retry: 647 /* Try to see if there is a key binding in the current table. */ 648 bd_find.key = key; 649 bd = RB_FIND(key_bindings, &c->keytable->key_bindings, &bd_find); 650 if (bd != NULL) { 651 /* 652 * Key was matched in this table. If currently repeating but a 653 * non-repeating binding was found, stop repeating and try 654 * again in the root table. 655 */ 656 if ((c->flags & CLIENT_REPEAT) && !bd->can_repeat) { 657 server_client_set_key_table(c, NULL); 658 c->flags &= ~CLIENT_REPEAT; 659 server_status_client(c); 660 goto retry; 661 } 662 663 /* 664 * Take a reference to this table to make sure the key binding 665 * doesn't disappear. 666 */ 667 table = c->keytable; 668 table->references++; 669 670 /* 671 * If this is a repeating key, start the timer. Otherwise reset 672 * the client back to the root table. 673 */ 674 xtimeout = options_get_number(s->options, "repeat-time"); 675 if (xtimeout != 0 && bd->can_repeat) { 676 c->flags |= CLIENT_REPEAT; 677 678 tv.tv_sec = xtimeout / 1000; 679 tv.tv_usec = (xtimeout % 1000) * 1000L; 680 evtimer_del(&c->repeat_timer); 681 evtimer_add(&c->repeat_timer, &tv); 682 } else { 683 c->flags &= ~CLIENT_REPEAT; 684 server_client_set_key_table(c, NULL); 685 } 686 server_status_client(c); 687 688 /* Dispatch the key binding. */ 689 key_bindings_dispatch(bd, c, m); 690 key_bindings_unref_table(table); 691 return; 692 } 693 694 /* 695 * No match in this table. If repeating, switch the client back to the 696 * root table and try again. 697 */ 698 if (c->flags & CLIENT_REPEAT) { 699 server_client_set_key_table(c, NULL); 700 c->flags &= ~CLIENT_REPEAT; 701 server_status_client(c); 702 goto retry; 703 } 704 705 /* If no match and we're not in the root table, that's it. */ 706 if (strcmp(c->keytable->name, server_client_get_key_table(c)) != 0) { 707 server_client_set_key_table(c, NULL); 708 server_status_client(c); 709 return; 710 } 711 712 /* 713 * No match, but in the root table. Prefix switches to the prefix table 714 * and everything else is passed through. 715 */ 716 if (key == (key_code)options_get_number(s->options, "prefix") || 717 key == (key_code)options_get_number(s->options, "prefix2")) { 718 server_client_set_key_table(c, "prefix"); 719 server_status_client(c); 720 return; 721 } 722 723 forward: 724 if (c->flags & CLIENT_READONLY) 725 return; 726 if (KEYC_IS_MOUSE(key)) 727 wp = cmd_mouse_pane(m, NULL, NULL); 728 else 729 wp = w->active; 730 if (wp != NULL) 731 window_pane_key(wp, c, s, key, m); 732 } 733 734 /* Client functions that need to happen every loop. */ 735 void 736 server_client_loop(void) 737 { 738 struct client *c; 739 struct window *w; 740 struct window_pane *wp; 741 742 TAILQ_FOREACH(c, &clients, entry) { 743 server_client_check_exit(c); 744 if (c->session != NULL) { 745 server_client_check_redraw(c); 746 server_client_reset_state(c); 747 } 748 } 749 750 /* 751 * Any windows will have been redrawn as part of clients, so clear 752 * their flags now. Also check pane focus and resize. 753 */ 754 RB_FOREACH(w, windows, &windows) { 755 w->flags &= ~WINDOW_REDRAW; 756 TAILQ_FOREACH(wp, &w->panes, entry) { 757 if (wp->fd != -1) { 758 server_client_check_focus(wp); 759 server_client_check_resize(wp); 760 } 761 wp->flags &= ~PANE_REDRAW; 762 } 763 check_window_name(w); 764 } 765 } 766 767 /* Check if pane should be resized. */ 768 void 769 server_client_check_resize(struct window_pane *wp) 770 { 771 struct winsize ws; 772 773 if (!(wp->flags & PANE_RESIZE)) 774 return; 775 776 memset(&ws, 0, sizeof ws); 777 ws.ws_col = wp->sx; 778 ws.ws_row = wp->sy; 779 780 if (ioctl(wp->fd, TIOCSWINSZ, &ws) == -1) 781 fatal("ioctl failed"); 782 783 wp->flags &= ~PANE_RESIZE; 784 } 785 786 /* Check whether pane should be focused. */ 787 void 788 server_client_check_focus(struct window_pane *wp) 789 { 790 struct client *c; 791 int push; 792 793 /* Are focus events off? */ 794 if (!options_get_number(global_options, "focus-events")) 795 return; 796 797 /* Do we need to push the focus state? */ 798 push = wp->flags & PANE_FOCUSPUSH; 799 wp->flags &= ~PANE_FOCUSPUSH; 800 801 /* If we don't care about focus, forget it. */ 802 if (!(wp->base.mode & MODE_FOCUSON)) 803 return; 804 805 /* If we're not the active pane in our window, we're not focused. */ 806 if (wp->window->active != wp) 807 goto not_focused; 808 809 /* If we're in a mode, we're not focused. */ 810 if (wp->screen != &wp->base) 811 goto not_focused; 812 813 /* 814 * If our window is the current window in any focused clients with an 815 * attached session, we're focused. 816 */ 817 TAILQ_FOREACH(c, &clients, entry) { 818 if (c->session == NULL || !(c->flags & CLIENT_FOCUSED)) 819 continue; 820 if (c->session->flags & SESSION_UNATTACHED) 821 continue; 822 823 if (c->session->curw->window == wp->window) 824 goto focused; 825 } 826 827 not_focused: 828 if (push || (wp->flags & PANE_FOCUSED)) 829 bufferevent_write(wp->event, "\033[O", 3); 830 wp->flags &= ~PANE_FOCUSED; 831 return; 832 833 focused: 834 if (push || !(wp->flags & PANE_FOCUSED)) 835 bufferevent_write(wp->event, "\033[I", 3); 836 wp->flags |= PANE_FOCUSED; 837 } 838 839 /* 840 * Update cursor position and mode settings. The scroll region and attributes 841 * are cleared when idle (waiting for an event) as this is the most likely time 842 * a user may interrupt tmux, for example with ~^Z in ssh(1). This is a 843 * compromise between excessive resets and likelihood of an interrupt. 844 * 845 * tty_region/tty_reset/tty_update_mode already take care of not resetting 846 * things that are already in their default state. 847 */ 848 void 849 server_client_reset_state(struct client *c) 850 { 851 struct window *w = c->session->curw->window; 852 struct window_pane *wp = w->active; 853 struct screen *s = wp->screen; 854 struct options *oo = c->session->options; 855 int status, mode, o; 856 857 if (c->flags & (CLIENT_CONTROL|CLIENT_SUSPENDED)) 858 return; 859 860 tty_region(&c->tty, 0, c->tty.sy - 1); 861 862 status = options_get_number(oo, "status"); 863 if (!window_pane_visible(wp) || wp->yoff + s->cy >= c->tty.sy - status) 864 tty_cursor(&c->tty, 0, 0); 865 else { 866 o = status && options_get_number(oo, "status-position") == 0; 867 tty_cursor(&c->tty, wp->xoff + s->cx, o + wp->yoff + s->cy); 868 } 869 870 /* 871 * Set mouse mode if requested. To support dragging, always use button 872 * mode. 873 */ 874 mode = s->mode; 875 if (options_get_number(oo, "mouse")) 876 mode = (mode & ~ALL_MOUSE_MODES) | MODE_MOUSE_BUTTON; 877 878 /* Set the terminal mode and reset attributes. */ 879 tty_update_mode(&c->tty, mode, s); 880 tty_reset(&c->tty); 881 } 882 883 /* Repeat time callback. */ 884 void 885 server_client_repeat_timer(__unused int fd, __unused short events, void *data) 886 { 887 struct client *c = data; 888 889 if (c->flags & CLIENT_REPEAT) { 890 server_client_set_key_table(c, NULL); 891 c->flags &= ~CLIENT_REPEAT; 892 server_status_client(c); 893 } 894 } 895 896 /* Check if client should be exited. */ 897 void 898 server_client_check_exit(struct client *c) 899 { 900 if (!(c->flags & CLIENT_EXIT)) 901 return; 902 903 if (EVBUFFER_LENGTH(c->stdin_data) != 0) 904 return; 905 if (EVBUFFER_LENGTH(c->stdout_data) != 0) 906 return; 907 if (EVBUFFER_LENGTH(c->stderr_data) != 0) 908 return; 909 910 proc_send(c->peer, MSG_EXIT, -1, &c->retval, sizeof c->retval); 911 c->flags &= ~CLIENT_EXIT; 912 } 913 914 /* Check for client redraws. */ 915 void 916 server_client_check_redraw(struct client *c) 917 { 918 struct session *s = c->session; 919 struct tty *tty = &c->tty; 920 struct window_pane *wp; 921 int flags, masked, redraw; 922 923 if (c->flags & (CLIENT_CONTROL|CLIENT_SUSPENDED)) 924 return; 925 926 if (c->flags & (CLIENT_REDRAW|CLIENT_STATUS)) { 927 if (options_get_number(s->options, "set-titles")) 928 server_client_set_title(c); 929 930 if (c->message_string != NULL) 931 redraw = status_message_redraw(c); 932 else if (c->prompt_string != NULL) 933 redraw = status_prompt_redraw(c); 934 else 935 redraw = status_redraw(c); 936 if (!redraw) 937 c->flags &= ~CLIENT_STATUS; 938 } 939 940 flags = tty->flags & (TTY_FREEZE|TTY_NOCURSOR); 941 tty->flags = (tty->flags & ~TTY_FREEZE) | TTY_NOCURSOR; 942 943 if (c->flags & CLIENT_REDRAW) { 944 tty_update_mode(tty, tty->mode, NULL); 945 screen_redraw_screen(c, 1, 1, 1); 946 c->flags &= ~(CLIENT_STATUS|CLIENT_BORDERS); 947 } else if (c->flags & CLIENT_REDRAWWINDOW) { 948 tty_update_mode(tty, tty->mode, NULL); 949 TAILQ_FOREACH(wp, &c->session->curw->window->panes, entry) 950 screen_redraw_pane(c, wp); 951 c->flags &= ~CLIENT_REDRAWWINDOW; 952 } else { 953 TAILQ_FOREACH(wp, &c->session->curw->window->panes, entry) { 954 if (wp->flags & PANE_REDRAW) { 955 tty_update_mode(tty, tty->mode, NULL); 956 screen_redraw_pane(c, wp); 957 } 958 } 959 } 960 961 masked = c->flags & (CLIENT_BORDERS|CLIENT_STATUS); 962 if (masked != 0) 963 tty_update_mode(tty, tty->mode, NULL); 964 if (masked == CLIENT_BORDERS) 965 screen_redraw_screen(c, 0, 0, 1); 966 else if (masked == CLIENT_STATUS) 967 screen_redraw_screen(c, 0, 1, 0); 968 else if (masked != 0) 969 screen_redraw_screen(c, 0, 1, 1); 970 971 tty->flags = (tty->flags & ~(TTY_FREEZE|TTY_NOCURSOR)) | flags; 972 tty_update_mode(tty, tty->mode, NULL); 973 974 c->flags &= ~(CLIENT_REDRAW|CLIENT_BORDERS|CLIENT_STATUS| 975 CLIENT_STATUSFORCE); 976 } 977 978 /* Set client title. */ 979 void 980 server_client_set_title(struct client *c) 981 { 982 struct session *s = c->session; 983 const char *template; 984 char *title; 985 struct format_tree *ft; 986 987 template = options_get_string(s->options, "set-titles-string"); 988 989 ft = format_create(NULL, 0); 990 format_defaults(ft, c, NULL, NULL, NULL); 991 992 title = format_expand_time(ft, template, time(NULL)); 993 if (c->title == NULL || strcmp(title, c->title) != 0) { 994 free(c->title); 995 c->title = xstrdup(title); 996 tty_set_title(&c->tty, c->title); 997 } 998 free(title); 999 1000 format_free(ft); 1001 } 1002 1003 /* Dispatch message from client. */ 1004 void 1005 server_client_dispatch(struct imsg *imsg, void *arg) 1006 { 1007 struct client *c = arg; 1008 struct msg_stdin_data stdindata; 1009 const char *data; 1010 ssize_t datalen; 1011 struct session *s; 1012 1013 if (c->flags & CLIENT_DEAD) 1014 return; 1015 1016 if (imsg == NULL) { 1017 server_client_lost(c); 1018 return; 1019 } 1020 1021 data = imsg->data; 1022 datalen = imsg->hdr.len - IMSG_HEADER_SIZE; 1023 1024 switch (imsg->hdr.type) { 1025 case MSG_IDENTIFY_FLAGS: 1026 case MSG_IDENTIFY_TERM: 1027 case MSG_IDENTIFY_TTYNAME: 1028 case MSG_IDENTIFY_CWD: 1029 case MSG_IDENTIFY_STDIN: 1030 case MSG_IDENTIFY_ENVIRON: 1031 case MSG_IDENTIFY_CLIENTPID: 1032 case MSG_IDENTIFY_DONE: 1033 server_client_dispatch_identify(c, imsg); 1034 break; 1035 case MSG_COMMAND: 1036 server_client_dispatch_command(c, imsg); 1037 break; 1038 case MSG_STDIN: 1039 if (datalen != sizeof stdindata) 1040 fatalx("bad MSG_STDIN size"); 1041 memcpy(&stdindata, data, sizeof stdindata); 1042 1043 if (c->stdin_callback == NULL) 1044 break; 1045 if (stdindata.size <= 0) 1046 c->stdin_closed = 1; 1047 else { 1048 evbuffer_add(c->stdin_data, stdindata.data, 1049 stdindata.size); 1050 } 1051 c->stdin_callback(c, c->stdin_closed, 1052 c->stdin_callback_data); 1053 break; 1054 case MSG_RESIZE: 1055 if (datalen != 0) 1056 fatalx("bad MSG_RESIZE size"); 1057 1058 if (c->flags & CLIENT_CONTROL) 1059 break; 1060 if (tty_resize(&c->tty)) { 1061 recalculate_sizes(); 1062 server_redraw_client(c); 1063 } 1064 if (c->session != NULL) 1065 hooks_run(c->session->hooks, c, NULL, "client-resized"); 1066 break; 1067 case MSG_EXITING: 1068 if (datalen != 0) 1069 fatalx("bad MSG_EXITING size"); 1070 1071 c->session = NULL; 1072 tty_close(&c->tty); 1073 proc_send(c->peer, MSG_EXITED, -1, NULL, 0); 1074 break; 1075 case MSG_WAKEUP: 1076 case MSG_UNLOCK: 1077 if (datalen != 0) 1078 fatalx("bad MSG_WAKEUP size"); 1079 1080 if (!(c->flags & CLIENT_SUSPENDED)) 1081 break; 1082 c->flags &= ~CLIENT_SUSPENDED; 1083 1084 if (c->tty.fd == -1) /* exited in the meantime */ 1085 break; 1086 s = c->session; 1087 1088 if (gettimeofday(&c->activity_time, NULL) != 0) 1089 fatal("gettimeofday failed"); 1090 1091 tty_start_tty(&c->tty); 1092 server_redraw_client(c); 1093 recalculate_sizes(); 1094 1095 if (s != NULL) 1096 session_update_activity(s, &c->activity_time); 1097 break; 1098 case MSG_SHELL: 1099 if (datalen != 0) 1100 fatalx("bad MSG_SHELL size"); 1101 1102 server_client_dispatch_shell(c); 1103 break; 1104 } 1105 } 1106 1107 /* Handle command message. */ 1108 void 1109 server_client_dispatch_command(struct client *c, struct imsg *imsg) 1110 { 1111 struct msg_command_data data; 1112 char *buf; 1113 size_t len; 1114 struct cmd_list *cmdlist = NULL; 1115 int argc; 1116 char **argv, *cause; 1117 1118 if (imsg->hdr.len - IMSG_HEADER_SIZE < sizeof data) 1119 fatalx("bad MSG_COMMAND size"); 1120 memcpy(&data, imsg->data, sizeof data); 1121 1122 buf = (char *)imsg->data + sizeof data; 1123 len = imsg->hdr.len - IMSG_HEADER_SIZE - sizeof data; 1124 if (len > 0 && buf[len - 1] != '\0') 1125 fatalx("bad MSG_COMMAND string"); 1126 1127 argc = data.argc; 1128 if (cmd_unpack_argv(buf, len, argc, &argv) != 0) { 1129 cmdq_error(c->cmdq, "command too long"); 1130 goto error; 1131 } 1132 1133 if (argc == 0) { 1134 argc = 1; 1135 argv = xcalloc(1, sizeof *argv); 1136 *argv = xstrdup("new-session"); 1137 } 1138 1139 if ((cmdlist = cmd_list_parse(argc, argv, NULL, 0, &cause)) == NULL) { 1140 cmdq_error(c->cmdq, "%s", cause); 1141 cmd_free_argv(argc, argv); 1142 goto error; 1143 } 1144 cmd_free_argv(argc, argv); 1145 1146 if (c != cfg_client || cfg_finished) 1147 cmdq_run(c->cmdq, cmdlist, NULL); 1148 else 1149 cmdq_append(c->cmdq, cmdlist, NULL); 1150 cmd_list_free(cmdlist); 1151 return; 1152 1153 error: 1154 if (cmdlist != NULL) 1155 cmd_list_free(cmdlist); 1156 1157 c->flags |= CLIENT_EXIT; 1158 } 1159 1160 /* Handle identify message. */ 1161 void 1162 server_client_dispatch_identify(struct client *c, struct imsg *imsg) 1163 { 1164 const char *data, *home; 1165 size_t datalen; 1166 int flags; 1167 1168 if (c->flags & CLIENT_IDENTIFIED) 1169 fatalx("out-of-order identify message"); 1170 1171 data = imsg->data; 1172 datalen = imsg->hdr.len - IMSG_HEADER_SIZE; 1173 1174 switch (imsg->hdr.type) { 1175 case MSG_IDENTIFY_FLAGS: 1176 if (datalen != sizeof flags) 1177 fatalx("bad MSG_IDENTIFY_FLAGS size"); 1178 memcpy(&flags, data, sizeof flags); 1179 c->flags |= flags; 1180 log_debug("client %p IDENTIFY_FLAGS %#x", c, flags); 1181 break; 1182 case MSG_IDENTIFY_TERM: 1183 if (datalen == 0 || data[datalen - 1] != '\0') 1184 fatalx("bad MSG_IDENTIFY_TERM string"); 1185 c->term = xstrdup(data); 1186 log_debug("client %p IDENTIFY_TERM %s", c, data); 1187 break; 1188 case MSG_IDENTIFY_TTYNAME: 1189 if (datalen == 0 || data[datalen - 1] != '\0') 1190 fatalx("bad MSG_IDENTIFY_TTYNAME string"); 1191 c->ttyname = xstrdup(data); 1192 log_debug("client %p IDENTIFY_TTYNAME %s", c, data); 1193 break; 1194 case MSG_IDENTIFY_CWD: 1195 if (datalen == 0 || data[datalen - 1] != '\0') 1196 fatalx("bad MSG_IDENTIFY_CWD string"); 1197 if (access(data, X_OK) == 0) 1198 c->cwd = xstrdup(data); 1199 else if ((home = find_home()) != NULL) 1200 c->cwd = xstrdup(home); 1201 else 1202 c->cwd = xstrdup("/"); 1203 log_debug("client %p IDENTIFY_CWD %s", c, data); 1204 break; 1205 case MSG_IDENTIFY_STDIN: 1206 if (datalen != 0) 1207 fatalx("bad MSG_IDENTIFY_STDIN size"); 1208 c->fd = imsg->fd; 1209 log_debug("client %p IDENTIFY_STDIN %d", c, imsg->fd); 1210 break; 1211 case MSG_IDENTIFY_ENVIRON: 1212 if (datalen == 0 || data[datalen - 1] != '\0') 1213 fatalx("bad MSG_IDENTIFY_ENVIRON string"); 1214 if (strchr(data, '=') != NULL) 1215 environ_put(c->environ, data); 1216 log_debug("client %p IDENTIFY_ENVIRON %s", c, data); 1217 break; 1218 case MSG_IDENTIFY_CLIENTPID: 1219 if (datalen != sizeof c->pid) 1220 fatalx("bad MSG_IDENTIFY_CLIENTPID size"); 1221 memcpy(&c->pid, data, sizeof c->pid); 1222 log_debug("client %p IDENTIFY_CLIENTPID %ld", c, (long)c->pid); 1223 break; 1224 default: 1225 break; 1226 } 1227 1228 if (imsg->hdr.type != MSG_IDENTIFY_DONE) 1229 return; 1230 c->flags |= CLIENT_IDENTIFIED; 1231 1232 if (c->flags & CLIENT_CONTROL) { 1233 c->stdin_callback = control_callback; 1234 1235 evbuffer_free(c->stderr_data); 1236 c->stderr_data = c->stdout_data; 1237 1238 if (c->flags & CLIENT_CONTROLCONTROL) 1239 evbuffer_add_printf(c->stdout_data, "\033P1000p"); 1240 proc_send(c->peer, MSG_STDIN, -1, NULL, 0); 1241 1242 c->tty.fd = -1; 1243 1244 close(c->fd); 1245 c->fd = -1; 1246 1247 return; 1248 } 1249 1250 if (c->fd == -1) 1251 return; 1252 if (tty_init(&c->tty, c, c->fd, c->term) != 0) { 1253 close(c->fd); 1254 c->fd = -1; 1255 return; 1256 } 1257 if (c->flags & CLIENT_UTF8) 1258 c->tty.flags |= TTY_UTF8; 1259 if (c->flags & CLIENT_256COLOURS) 1260 c->tty.term_flags |= TERM_256COLOURS; 1261 1262 tty_resize(&c->tty); 1263 1264 if (!(c->flags & CLIENT_CONTROL)) 1265 c->flags |= CLIENT_TERMINAL; 1266 } 1267 1268 /* Handle shell message. */ 1269 void 1270 server_client_dispatch_shell(struct client *c) 1271 { 1272 const char *shell; 1273 1274 shell = options_get_string(global_s_options, "default-shell"); 1275 if (*shell == '\0' || areshell(shell)) 1276 shell = _PATH_BSHELL; 1277 proc_send_s(c->peer, MSG_SHELL, shell); 1278 1279 proc_kill_peer(c->peer); 1280 } 1281 1282 /* Event callback to push more stdout data if any left. */ 1283 static void 1284 server_client_stdout_cb(__unused int fd, __unused short events, void *arg) 1285 { 1286 struct client *c = arg; 1287 1288 if (~c->flags & CLIENT_DEAD) 1289 server_client_push_stdout(c); 1290 server_client_unref(c); 1291 } 1292 1293 /* Push stdout to client if possible. */ 1294 void 1295 server_client_push_stdout(struct client *c) 1296 { 1297 struct msg_stdout_data data; 1298 size_t sent, left; 1299 1300 left = EVBUFFER_LENGTH(c->stdout_data); 1301 while (left != 0) { 1302 sent = left; 1303 if (sent > sizeof data.data) 1304 sent = sizeof data.data; 1305 memcpy(data.data, EVBUFFER_DATA(c->stdout_data), sent); 1306 data.size = sent; 1307 1308 if (proc_send(c->peer, MSG_STDOUT, -1, &data, sizeof data) != 0) 1309 break; 1310 evbuffer_drain(c->stdout_data, sent); 1311 1312 left = EVBUFFER_LENGTH(c->stdout_data); 1313 log_debug("%s: client %p, sent %zu, left %zu", __func__, c, 1314 sent, left); 1315 } 1316 if (left != 0) { 1317 c->references++; 1318 event_once(-1, EV_TIMEOUT, server_client_stdout_cb, c, NULL); 1319 log_debug("%s: client %p, queued", __func__, c); 1320 } 1321 } 1322 1323 /* Event callback to push more stderr data if any left. */ 1324 static void 1325 server_client_stderr_cb(__unused int fd, __unused short events, void *arg) 1326 { 1327 struct client *c = arg; 1328 1329 if (~c->flags & CLIENT_DEAD) 1330 server_client_push_stderr(c); 1331 server_client_unref(c); 1332 } 1333 1334 /* Push stderr to client if possible. */ 1335 void 1336 server_client_push_stderr(struct client *c) 1337 { 1338 struct msg_stderr_data data; 1339 size_t sent, left; 1340 1341 if (c->stderr_data == c->stdout_data) { 1342 server_client_push_stdout(c); 1343 return; 1344 } 1345 1346 left = EVBUFFER_LENGTH(c->stderr_data); 1347 while (left != 0) { 1348 sent = left; 1349 if (sent > sizeof data.data) 1350 sent = sizeof data.data; 1351 memcpy(data.data, EVBUFFER_DATA(c->stderr_data), sent); 1352 data.size = sent; 1353 1354 if (proc_send(c->peer, MSG_STDERR, -1, &data, sizeof data) != 0) 1355 break; 1356 evbuffer_drain(c->stderr_data, sent); 1357 1358 left = EVBUFFER_LENGTH(c->stderr_data); 1359 log_debug("%s: client %p, sent %zu, left %zu", __func__, c, 1360 sent, left); 1361 } 1362 if (left != 0) { 1363 c->references++; 1364 event_once(-1, EV_TIMEOUT, server_client_stderr_cb, c, NULL); 1365 log_debug("%s: client %p, queued", __func__, c); 1366 } 1367 } 1368