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