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 static void server_client_free(int, short, void *); 34 static void server_client_check_focus(struct window_pane *); 35 static void server_client_check_resize(struct window_pane *); 36 static key_code server_client_check_mouse(struct client *); 37 static void server_client_repeat_timer(int, short, void *); 38 static void server_client_click_timer(int, short, void *); 39 static void server_client_check_exit(struct client *); 40 static void server_client_check_redraw(struct client *); 41 static void server_client_set_title(struct client *); 42 static void server_client_reset_state(struct client *); 43 static int server_client_assume_paste(struct session *); 44 static void server_client_clear_identify(struct client *, 45 struct window_pane *); 46 47 static void server_client_dispatch(struct imsg *, void *); 48 static void server_client_dispatch_command(struct client *, struct imsg *); 49 static void server_client_dispatch_identify(struct client *, struct imsg *); 50 static void server_client_dispatch_shell(struct client *); 51 52 /* Number of attached clients. */ 53 u_int 54 server_client_how_many(void) 55 { 56 struct client *c; 57 u_int n; 58 59 n = 0; 60 TAILQ_FOREACH(c, &clients, entry) { 61 if (c->session != NULL && (~c->flags & CLIENT_DETACHING)) 62 n++; 63 } 64 return (n); 65 } 66 67 /* Identify mode callback. */ 68 static void 69 server_client_callback_identify(__unused int fd, __unused short events, 70 void *data) 71 { 72 server_client_clear_identify(data, NULL); 73 } 74 75 /* Set identify mode on client. */ 76 void 77 server_client_set_identify(struct client *c, u_int delay) 78 { 79 struct timeval tv; 80 81 tv.tv_sec = delay / 1000; 82 tv.tv_usec = (delay % 1000) * 1000L; 83 84 if (event_initialized(&c->identify_timer)) 85 evtimer_del(&c->identify_timer); 86 evtimer_set(&c->identify_timer, server_client_callback_identify, c); 87 if (delay != 0) 88 evtimer_add(&c->identify_timer, &tv); 89 90 c->flags |= CLIENT_IDENTIFY; 91 c->tty.flags |= (TTY_FREEZE|TTY_NOCURSOR); 92 server_redraw_client(c); 93 } 94 95 /* Clear identify mode on client. */ 96 static void 97 server_client_clear_identify(struct client *c, struct window_pane *wp) 98 { 99 if (~c->flags & CLIENT_IDENTIFY) 100 return; 101 c->flags &= ~CLIENT_IDENTIFY; 102 103 if (c->identify_callback != NULL) 104 c->identify_callback(c, wp); 105 106 c->tty.flags &= ~(TTY_FREEZE|TTY_NOCURSOR); 107 server_redraw_client(c); 108 } 109 110 /* Check if this client is inside this server. */ 111 int 112 server_client_check_nested(struct client *c) 113 { 114 struct environ_entry *envent; 115 struct window_pane *wp; 116 117 envent = environ_find(c->environ, "TMUX"); 118 if (envent == NULL || *envent->value == '\0') 119 return (0); 120 121 RB_FOREACH(wp, window_pane_tree, &all_window_panes) { 122 if (strcmp(wp->tty, c->ttyname) == 0) 123 return (1); 124 } 125 return (0); 126 } 127 128 /* Set client key table. */ 129 void 130 server_client_set_key_table(struct client *c, const char *name) 131 { 132 if (name == NULL) 133 name = server_client_get_key_table(c); 134 135 key_bindings_unref_table(c->keytable); 136 c->keytable = key_bindings_get_table(name, 1); 137 c->keytable->references++; 138 } 139 140 /* Get default key table. */ 141 const char * 142 server_client_get_key_table(struct client *c) 143 { 144 struct session *s = c->session; 145 const char *name; 146 147 if (s == NULL) 148 return ("root"); 149 150 name = options_get_string(s->options, "key-table"); 151 if (*name == '\0') 152 return ("root"); 153 return (name); 154 } 155 156 /* Is this table the default key table? */ 157 static int 158 server_client_is_default_key_table(struct client *c, struct key_table *table) 159 { 160 return (strcmp(table->name, server_client_get_key_table(c)) == 0); 161 } 162 163 /* Create a new client. */ 164 struct client * 165 server_client_create(int fd) 166 { 167 struct client *c; 168 169 setblocking(fd, 0); 170 171 c = xcalloc(1, sizeof *c); 172 c->references = 1; 173 c->peer = proc_add_peer(server_proc, fd, server_client_dispatch, c); 174 175 if (gettimeofday(&c->creation_time, NULL) != 0) 176 fatal("gettimeofday failed"); 177 memcpy(&c->activity_time, &c->creation_time, sizeof c->activity_time); 178 179 c->environ = environ_create(); 180 181 c->fd = -1; 182 c->cwd = NULL; 183 184 TAILQ_INIT(&c->queue); 185 186 c->stdin_data = evbuffer_new(); 187 c->stdout_data = evbuffer_new(); 188 c->stderr_data = evbuffer_new(); 189 190 c->tty.fd = -1; 191 c->title = NULL; 192 193 c->session = NULL; 194 c->last_session = NULL; 195 c->tty.sx = 80; 196 c->tty.sy = 24; 197 198 screen_init(&c->status.status, c->tty.sx, 1, 0); 199 200 c->message_string = NULL; 201 TAILQ_INIT(&c->message_log); 202 203 c->prompt_string = NULL; 204 c->prompt_buffer = NULL; 205 c->prompt_index = 0; 206 207 c->flags |= CLIENT_FOCUSED; 208 209 c->keytable = key_bindings_get_table("root", 1); 210 c->keytable->references++; 211 212 evtimer_set(&c->repeat_timer, server_client_repeat_timer, c); 213 evtimer_set(&c->click_timer, server_client_click_timer, c); 214 215 TAILQ_INSERT_TAIL(&clients, c, entry); 216 log_debug("new client %p", c); 217 return (c); 218 } 219 220 /* Open client terminal if needed. */ 221 int 222 server_client_open(struct client *c, char **cause) 223 { 224 if (c->flags & CLIENT_CONTROL) 225 return (0); 226 227 if (strcmp(c->ttyname, "/dev/tty") == 0) { 228 *cause = xstrdup("can't use /dev/tty"); 229 return (-1); 230 } 231 232 if (!(c->flags & CLIENT_TERMINAL)) { 233 *cause = xstrdup("not a terminal"); 234 return (-1); 235 } 236 237 if (tty_open(&c->tty, cause) != 0) 238 return (-1); 239 240 return (0); 241 } 242 243 /* Lost a client. */ 244 void 245 server_client_lost(struct client *c) 246 { 247 struct message_entry *msg, *msg1; 248 249 c->flags |= CLIENT_DEAD; 250 251 server_client_clear_identify(c, NULL); 252 status_prompt_clear(c); 253 status_message_clear(c); 254 255 if (c->stdin_callback != NULL) 256 c->stdin_callback(c, 1, c->stdin_callback_data); 257 258 TAILQ_REMOVE(&clients, c, entry); 259 log_debug("lost client %p", c); 260 261 /* 262 * If CLIENT_TERMINAL hasn't been set, then tty_init hasn't been called 263 * and tty_free might close an unrelated fd. 264 */ 265 if (c->flags & CLIENT_TERMINAL) 266 tty_free(&c->tty); 267 free(c->ttyname); 268 free(c->term); 269 270 evbuffer_free(c->stdin_data); 271 evbuffer_free(c->stdout_data); 272 if (c->stderr_data != c->stdout_data) 273 evbuffer_free(c->stderr_data); 274 275 if (event_initialized(&c->status.timer)) 276 evtimer_del(&c->status.timer); 277 screen_free(&c->status.status); 278 if (c->status.old_status != NULL) { 279 screen_free(c->status.old_status); 280 free(c->status.old_status); 281 } 282 283 free(c->title); 284 free(__UNCONST(c->cwd)); 285 286 evtimer_del(&c->repeat_timer); 287 evtimer_del(&c->click_timer); 288 289 key_bindings_unref_table(c->keytable); 290 291 if (event_initialized(&c->identify_timer)) 292 evtimer_del(&c->identify_timer); 293 294 free(c->message_string); 295 if (event_initialized(&c->message_timer)) 296 evtimer_del(&c->message_timer); 297 TAILQ_FOREACH_SAFE(msg, &c->message_log, entry, msg1) { 298 free(msg->msg); 299 TAILQ_REMOVE(&c->message_log, msg, entry); 300 free(msg); 301 } 302 303 free(c->prompt_string); 304 free(c->prompt_buffer); 305 306 format_lost_client(c); 307 environ_free(c->environ); 308 309 proc_remove_peer(c->peer); 310 c->peer = NULL; 311 312 server_client_unref(c); 313 314 server_add_accept(0); /* may be more file descriptors now */ 315 316 recalculate_sizes(); 317 server_check_unattached(); 318 server_update_socket(); 319 } 320 321 /* Remove reference from a client. */ 322 void 323 server_client_unref(struct client *c) 324 { 325 log_debug("unref client %p (%d references)", c, c->references); 326 327 c->references--; 328 if (c->references == 0) 329 event_once(-1, EV_TIMEOUT, server_client_free, c, NULL); 330 } 331 332 /* Free dead client. */ 333 static void 334 server_client_free(__unused int fd, __unused short events, void *arg) 335 { 336 struct client *c = arg; 337 338 log_debug("free client %p (%d references)", c, c->references); 339 340 if (!TAILQ_EMPTY(&c->queue)) 341 fatalx("queue not empty"); 342 343 if (c->references == 0) { 344 free(__UNCONST(c->name)); 345 free(c); 346 } 347 } 348 349 /* Suspend a client. */ 350 void 351 server_client_suspend(struct client *c) 352 { 353 struct session *s = c->session; 354 355 if (s == NULL || (c->flags & CLIENT_DETACHING)) 356 return; 357 358 tty_stop_tty(&c->tty); 359 c->flags |= CLIENT_SUSPENDED; 360 proc_send(c->peer, MSG_SUSPEND, -1, NULL, 0); 361 } 362 363 /* Detach a client. */ 364 void 365 server_client_detach(struct client *c, enum msgtype msgtype) 366 { 367 struct session *s = c->session; 368 369 if (s == NULL || (c->flags & CLIENT_DETACHING)) 370 return; 371 372 c->flags |= CLIENT_DETACHING; 373 notify_client("client-detached", c); 374 proc_send(c->peer, msgtype, -1, s->name, strlen(s->name) + 1); 375 } 376 377 /* Execute command to replace a client. */ 378 void 379 server_client_exec(struct client *c, const char *cmd) 380 { 381 struct session *s = c->session; 382 char *msg; 383 const char *shell; 384 size_t cmdsize, shellsize; 385 386 if (*cmd == '\0') 387 return; 388 cmdsize = strlen(cmd) + 1; 389 390 if (s != NULL) 391 shell = options_get_string(s->options, "default-shell"); 392 else 393 shell = options_get_string(global_s_options, "default-shell"); 394 shellsize = strlen(shell) + 1; 395 396 msg = xmalloc(cmdsize + shellsize); 397 memcpy(msg, cmd, cmdsize); 398 memcpy(msg + cmdsize, shell, shellsize); 399 400 proc_send(c->peer, MSG_EXEC, -1, msg, cmdsize + shellsize); 401 free(msg); 402 } 403 404 /* Check for mouse keys. */ 405 static key_code 406 server_client_check_mouse(struct client *c) 407 { 408 struct session *s = c->session; 409 struct mouse_event *m = &c->tty.mouse; 410 struct window *w; 411 struct window_pane *wp; 412 u_int x, y, b; 413 int flag; 414 key_code key; 415 struct timeval tv; 416 enum { NOTYPE, MOVE, DOWN, UP, DRAG, WHEEL, DOUBLE, TRIPLE } type; 417 enum { NOWHERE, PANE, STATUS, BORDER } where; 418 419 type = NOTYPE; 420 where = NOWHERE; 421 422 log_debug("mouse %02x at %u,%u (last %u,%u) (%d)", m->b, m->x, m->y, 423 m->lx, m->ly, c->tty.mouse_drag_flag); 424 425 /* What type of event is this? */ 426 if ((m->sgr_type != ' ' && 427 MOUSE_DRAG(m->sgr_b) && 428 MOUSE_BUTTONS(m->sgr_b) == 3) || 429 (m->sgr_type == ' ' && 430 MOUSE_DRAG(m->b) && 431 MOUSE_BUTTONS(m->b) == 3 && 432 MOUSE_BUTTONS(m->lb) == 3)) { 433 type = MOVE; 434 x = m->x, y = m->y, b = 0; 435 log_debug("move at %u,%u", x, y); 436 } else if (MOUSE_DRAG(m->b)) { 437 type = DRAG; 438 if (c->tty.mouse_drag_flag) { 439 x = m->x, y = m->y, b = m->b; 440 log_debug("drag update at %u,%u", x, y); 441 } else { 442 x = m->lx, y = m->ly, b = m->lb; 443 log_debug("drag start at %u,%u", x, y); 444 } 445 } else if (MOUSE_WHEEL(m->b)) { 446 type = WHEEL; 447 x = m->x, y = m->y, b = m->b; 448 log_debug("wheel at %u,%u", x, y); 449 } else if (MOUSE_RELEASE(m->b)) { 450 type = UP; 451 x = m->x, y = m->y, b = m->lb; 452 log_debug("up at %u,%u", x, y); 453 } else { 454 if (c->flags & CLIENT_DOUBLECLICK) { 455 evtimer_del(&c->click_timer); 456 c->flags &= ~CLIENT_DOUBLECLICK; 457 if (m->b == c->click_button) { 458 type = DOUBLE; 459 x = m->x, y = m->y, b = m->b; 460 log_debug("double-click at %u,%u", x, y); 461 flag = CLIENT_TRIPLECLICK; 462 goto add_timer; 463 } 464 } else if (c->flags & CLIENT_TRIPLECLICK) { 465 evtimer_del(&c->click_timer); 466 c->flags &= ~CLIENT_TRIPLECLICK; 467 if (m->b == c->click_button) { 468 type = TRIPLE; 469 x = m->x, y = m->y, b = m->b; 470 log_debug("triple-click at %u,%u", x, y); 471 goto have_event; 472 } 473 } 474 475 type = DOWN; 476 x = m->x, y = m->y, b = m->b; 477 log_debug("down at %u,%u", x, y); 478 flag = CLIENT_DOUBLECLICK; 479 480 add_timer: 481 if (KEYC_CLICK_TIMEOUT != 0) { 482 c->flags |= flag; 483 c->click_button = m->b; 484 485 tv.tv_sec = KEYC_CLICK_TIMEOUT / 1000; 486 tv.tv_usec = (KEYC_CLICK_TIMEOUT % 1000) * 1000L; 487 evtimer_del(&c->click_timer); 488 evtimer_add(&c->click_timer, &tv); 489 } 490 } 491 492 have_event: 493 if (type == NOTYPE) 494 return (KEYC_UNKNOWN); 495 496 /* Always save the session. */ 497 m->s = s->id; 498 499 /* Is this on the status line? */ 500 m->statusat = status_at_line(c); 501 if (m->statusat != -1 && y == (u_int)m->statusat) { 502 w = status_get_window_at(c, x); 503 if (w == NULL) 504 return (KEYC_UNKNOWN); 505 m->w = w->id; 506 where = STATUS; 507 } else 508 m->w = -1; 509 510 /* Not on status line. Adjust position and check for border or pane. */ 511 if (where == NOWHERE) { 512 if (m->statusat == 0 && y > 0) 513 y--; 514 else if (m->statusat > 0 && y >= (u_int)m->statusat) 515 y = m->statusat - 1; 516 517 TAILQ_FOREACH(wp, &s->curw->window->panes, entry) { 518 if ((wp->xoff + wp->sx == x && 519 wp->yoff <= 1 + y && 520 wp->yoff + wp->sy >= y) || 521 (wp->yoff + wp->sy == y && 522 wp->xoff <= 1 + x && 523 wp->xoff + wp->sx >= x)) 524 break; 525 } 526 if (wp != NULL) 527 where = BORDER; 528 else { 529 wp = window_get_active_at(s->curw->window, x, y); 530 if (wp != NULL) { 531 where = PANE; 532 log_debug("mouse at %u,%u is on pane %%%u", 533 x, y, wp->id); 534 } 535 } 536 if (where == NOWHERE) 537 return (KEYC_UNKNOWN); 538 m->wp = wp->id; 539 m->w = wp->window->id; 540 } else 541 m->wp = -1; 542 543 /* Stop dragging if needed. */ 544 if (type != DRAG && type != WHEEL && c->tty.mouse_drag_flag) { 545 if (c->tty.mouse_drag_release != NULL) 546 c->tty.mouse_drag_release(c, m); 547 548 c->tty.mouse_drag_update = NULL; 549 c->tty.mouse_drag_release = NULL; 550 551 /* 552 * End a mouse drag by passing a MouseDragEnd key corresponding 553 * to the button that started the drag. 554 */ 555 switch (c->tty.mouse_drag_flag) { 556 case 1: 557 if (where == PANE) 558 key = KEYC_MOUSEDRAGEND1_PANE; 559 if (where == STATUS) 560 key = KEYC_MOUSEDRAGEND1_STATUS; 561 if (where == BORDER) 562 key = KEYC_MOUSEDRAGEND1_BORDER; 563 break; 564 case 2: 565 if (where == PANE) 566 key = KEYC_MOUSEDRAGEND2_PANE; 567 if (where == STATUS) 568 key = KEYC_MOUSEDRAGEND2_STATUS; 569 if (where == BORDER) 570 key = KEYC_MOUSEDRAGEND2_BORDER; 571 break; 572 case 3: 573 if (where == PANE) 574 key = KEYC_MOUSEDRAGEND3_PANE; 575 if (where == STATUS) 576 key = KEYC_MOUSEDRAGEND3_STATUS; 577 if (where == BORDER) 578 key = KEYC_MOUSEDRAGEND3_BORDER; 579 break; 580 default: 581 key = KEYC_MOUSE; 582 break; 583 } 584 c->tty.mouse_drag_flag = 0; 585 586 return (key); 587 } 588 589 /* Convert to a key binding. */ 590 key = KEYC_UNKNOWN; 591 switch (type) { 592 case NOTYPE: 593 break; 594 case MOVE: 595 if (where == PANE) 596 key = KEYC_MOUSEMOVE_PANE; 597 if (where == STATUS) 598 key = KEYC_MOUSEMOVE_STATUS; 599 if (where == BORDER) 600 key = KEYC_MOUSEMOVE_BORDER; 601 break; 602 case DRAG: 603 if (c->tty.mouse_drag_update != NULL) 604 key = KEYC_DRAGGING; 605 else { 606 switch (MOUSE_BUTTONS(b)) { 607 case 0: 608 if (where == PANE) 609 key = KEYC_MOUSEDRAG1_PANE; 610 if (where == STATUS) 611 key = KEYC_MOUSEDRAG1_STATUS; 612 if (where == BORDER) 613 key = KEYC_MOUSEDRAG1_BORDER; 614 break; 615 case 1: 616 if (where == PANE) 617 key = KEYC_MOUSEDRAG2_PANE; 618 if (where == STATUS) 619 key = KEYC_MOUSEDRAG2_STATUS; 620 if (where == BORDER) 621 key = KEYC_MOUSEDRAG2_BORDER; 622 break; 623 case 2: 624 if (where == PANE) 625 key = KEYC_MOUSEDRAG3_PANE; 626 if (where == STATUS) 627 key = KEYC_MOUSEDRAG3_STATUS; 628 if (where == BORDER) 629 key = KEYC_MOUSEDRAG3_BORDER; 630 break; 631 } 632 } 633 634 /* 635 * Begin a drag by setting the flag to a non-zero value that 636 * corresponds to the mouse button in use. 637 */ 638 c->tty.mouse_drag_flag = MOUSE_BUTTONS(b) + 1; 639 break; 640 case WHEEL: 641 if (MOUSE_BUTTONS(b) == MOUSE_WHEEL_UP) { 642 if (where == PANE) 643 key = KEYC_WHEELUP_PANE; 644 if (where == STATUS) 645 key = KEYC_WHEELUP_STATUS; 646 if (where == BORDER) 647 key = KEYC_WHEELUP_BORDER; 648 } else { 649 if (where == PANE) 650 key = KEYC_WHEELDOWN_PANE; 651 if (where == STATUS) 652 key = KEYC_WHEELDOWN_STATUS; 653 if (where == BORDER) 654 key = KEYC_WHEELDOWN_BORDER; 655 } 656 break; 657 case UP: 658 switch (MOUSE_BUTTONS(b)) { 659 case 0: 660 if (where == PANE) 661 key = KEYC_MOUSEUP1_PANE; 662 if (where == STATUS) 663 key = KEYC_MOUSEUP1_STATUS; 664 if (where == BORDER) 665 key = KEYC_MOUSEUP1_BORDER; 666 break; 667 case 1: 668 if (where == PANE) 669 key = KEYC_MOUSEUP2_PANE; 670 if (where == STATUS) 671 key = KEYC_MOUSEUP2_STATUS; 672 if (where == BORDER) 673 key = KEYC_MOUSEUP2_BORDER; 674 break; 675 case 2: 676 if (where == PANE) 677 key = KEYC_MOUSEUP3_PANE; 678 if (where == STATUS) 679 key = KEYC_MOUSEUP3_STATUS; 680 if (where == BORDER) 681 key = KEYC_MOUSEUP3_BORDER; 682 break; 683 } 684 break; 685 case DOWN: 686 switch (MOUSE_BUTTONS(b)) { 687 case 0: 688 if (where == PANE) 689 key = KEYC_MOUSEDOWN1_PANE; 690 if (where == STATUS) 691 key = KEYC_MOUSEDOWN1_STATUS; 692 if (where == BORDER) 693 key = KEYC_MOUSEDOWN1_BORDER; 694 break; 695 case 1: 696 if (where == PANE) 697 key = KEYC_MOUSEDOWN2_PANE; 698 if (where == STATUS) 699 key = KEYC_MOUSEDOWN2_STATUS; 700 if (where == BORDER) 701 key = KEYC_MOUSEDOWN2_BORDER; 702 break; 703 case 2: 704 if (where == PANE) 705 key = KEYC_MOUSEDOWN3_PANE; 706 if (where == STATUS) 707 key = KEYC_MOUSEDOWN3_STATUS; 708 if (where == BORDER) 709 key = KEYC_MOUSEDOWN3_BORDER; 710 break; 711 } 712 break; 713 case DOUBLE: 714 switch (MOUSE_BUTTONS(b)) { 715 case 0: 716 if (where == PANE) 717 key = KEYC_DOUBLECLICK1_PANE; 718 if (where == STATUS) 719 key = KEYC_DOUBLECLICK1_STATUS; 720 if (where == BORDER) 721 key = KEYC_DOUBLECLICK1_BORDER; 722 break; 723 case 1: 724 if (where == PANE) 725 key = KEYC_DOUBLECLICK2_PANE; 726 if (where == STATUS) 727 key = KEYC_DOUBLECLICK2_STATUS; 728 if (where == BORDER) 729 key = KEYC_DOUBLECLICK2_BORDER; 730 break; 731 case 2: 732 if (where == PANE) 733 key = KEYC_DOUBLECLICK3_PANE; 734 if (where == STATUS) 735 key = KEYC_DOUBLECLICK3_STATUS; 736 if (where == BORDER) 737 key = KEYC_DOUBLECLICK3_BORDER; 738 break; 739 } 740 break; 741 case TRIPLE: 742 switch (MOUSE_BUTTONS(b)) { 743 case 0: 744 if (where == PANE) 745 key = KEYC_TRIPLECLICK1_PANE; 746 if (where == STATUS) 747 key = KEYC_TRIPLECLICK1_STATUS; 748 if (where == BORDER) 749 key = KEYC_TRIPLECLICK1_BORDER; 750 break; 751 case 1: 752 if (where == PANE) 753 key = KEYC_TRIPLECLICK2_PANE; 754 if (where == STATUS) 755 key = KEYC_TRIPLECLICK2_STATUS; 756 if (where == BORDER) 757 key = KEYC_TRIPLECLICK2_BORDER; 758 break; 759 case 2: 760 if (where == PANE) 761 key = KEYC_TRIPLECLICK3_PANE; 762 if (where == STATUS) 763 key = KEYC_TRIPLECLICK3_STATUS; 764 if (where == BORDER) 765 key = KEYC_TRIPLECLICK3_BORDER; 766 break; 767 } 768 break; 769 } 770 if (key == KEYC_UNKNOWN) 771 return (KEYC_UNKNOWN); 772 773 /* Apply modifiers if any. */ 774 if (b & MOUSE_MASK_META) 775 key |= KEYC_ESCAPE; 776 if (b & MOUSE_MASK_CTRL) 777 key |= KEYC_CTRL; 778 if (b & MOUSE_MASK_SHIFT) 779 key |= KEYC_SHIFT; 780 781 return (key); 782 } 783 784 /* Is this fast enough to probably be a paste? */ 785 static int 786 server_client_assume_paste(struct session *s) 787 { 788 struct timeval tv; 789 int t; 790 791 if ((t = options_get_number(s->options, "assume-paste-time")) == 0) 792 return (0); 793 794 timersub(&s->activity_time, &s->last_activity_time, &tv); 795 if (tv.tv_sec == 0 && tv.tv_usec < t * 1000) { 796 log_debug("session %s pasting (flag %d)", s->name, 797 !!(s->flags & SESSION_PASTING)); 798 if (s->flags & SESSION_PASTING) 799 return (1); 800 s->flags |= SESSION_PASTING; 801 return (0); 802 } 803 log_debug("session %s not pasting", s->name); 804 s->flags &= ~SESSION_PASTING; 805 return (0); 806 } 807 808 /* Handle data key input from client. */ 809 void 810 server_client_handle_key(struct client *c, key_code key) 811 { 812 struct mouse_event *m = &c->tty.mouse; 813 struct session *s = c->session; 814 struct window *w; 815 struct window_pane *wp; 816 struct timeval tv; 817 struct key_table *table, *first; 818 struct key_binding *bd; 819 int xtimeout, flags; 820 struct cmd_find_state fs; 821 key_code key0; 822 823 /* Check the client is good to accept input. */ 824 if (s == NULL || (c->flags & (CLIENT_DEAD|CLIENT_SUSPENDED)) != 0) 825 return; 826 w = s->curw->window; 827 828 /* Update the activity timer. */ 829 if (gettimeofday(&c->activity_time, NULL) != 0) 830 fatal("gettimeofday failed"); 831 session_update_activity(s, &c->activity_time); 832 833 /* Number keys jump to pane in identify mode. */ 834 if (c->flags & CLIENT_IDENTIFY && key >= '0' && key <= '9') { 835 if (c->flags & CLIENT_READONLY) 836 return; 837 window_unzoom(w); 838 wp = window_pane_at_index(w, key - '0'); 839 if (wp != NULL && !window_pane_visible(wp)) 840 wp = NULL; 841 server_client_clear_identify(c, wp); 842 return; 843 } 844 845 /* Handle status line. */ 846 if (!(c->flags & CLIENT_READONLY)) { 847 status_message_clear(c); 848 server_client_clear_identify(c, NULL); 849 } 850 if (c->prompt_string != NULL) { 851 if (c->flags & CLIENT_READONLY) 852 return; 853 if (status_prompt_key(c, key) == 0) 854 return; 855 } 856 857 /* Check for mouse keys. */ 858 m->valid = 0; 859 if (key == KEYC_MOUSE) { 860 if (c->flags & CLIENT_READONLY) 861 return; 862 key = server_client_check_mouse(c); 863 if (key == KEYC_UNKNOWN) 864 return; 865 866 m->valid = 1; 867 m->key = key; 868 869 /* 870 * Mouse drag is in progress, so fire the callback (now that 871 * the mouse event is valid). 872 */ 873 if (key == KEYC_DRAGGING) { 874 c->tty.mouse_drag_update(c, m); 875 return; 876 } 877 } else 878 m->valid = 0; 879 880 /* Find affected pane. */ 881 if (!KEYC_IS_MOUSE(key) || cmd_find_from_mouse(&fs, m, 0) != 0) 882 cmd_find_from_session(&fs, s, 0); 883 wp = fs.wp; 884 885 /* Forward mouse keys if disabled. */ 886 if (KEYC_IS_MOUSE(key) && !options_get_number(s->options, "mouse")) 887 goto forward_key; 888 889 /* Treat everything as a regular key when pasting is detected. */ 890 if (!KEYC_IS_MOUSE(key) && server_client_assume_paste(s)) 891 goto forward_key; 892 893 /* 894 * Work out the current key table. If the pane is in a mode, use 895 * the mode table instead of the default key table. 896 */ 897 if (server_client_is_default_key_table(c, c->keytable) && 898 wp != NULL && 899 wp->mode != NULL && 900 wp->mode->key_table != NULL) 901 table = key_bindings_get_table(wp->mode->key_table(wp), 1); 902 else 903 table = c->keytable; 904 first = table; 905 906 table_changed: 907 /* 908 * The prefix always takes precedence and forces a switch to the prefix 909 * table, unless we are already there. 910 */ 911 key0 = (key & ~KEYC_XTERM); 912 if ((key0 == (key_code)options_get_number(s->options, "prefix") || 913 key0 == (key_code)options_get_number(s->options, "prefix2")) && 914 strcmp(table->name, "prefix") != 0) { 915 server_client_set_key_table(c, "prefix"); 916 server_status_client(c); 917 return; 918 } 919 flags = c->flags; 920 921 /* Log key table. */ 922 if (wp == NULL) 923 log_debug("key table %s (no pane)", table->name); 924 else 925 log_debug("key table %s (pane %%%u)", table->name, wp->id); 926 if (c->flags & CLIENT_REPEAT) 927 log_debug("currently repeating"); 928 929 try_again: 930 /* Try to see if there is a key binding in the current table. */ 931 bd = key_bindings_get(table, key0); 932 if (bd != NULL) { 933 /* 934 * Key was matched in this table. If currently repeating but a 935 * non-repeating binding was found, stop repeating and try 936 * again in the root table. 937 */ 938 if ((c->flags & CLIENT_REPEAT) && 939 (~bd->flags & KEY_BINDING_REPEAT)) { 940 server_client_set_key_table(c, NULL); 941 c->flags &= ~CLIENT_REPEAT; 942 server_status_client(c); 943 table = c->keytable; 944 goto table_changed; 945 } 946 log_debug("found in key table %s", table->name); 947 948 /* 949 * Take a reference to this table to make sure the key binding 950 * doesn't disappear. 951 */ 952 table->references++; 953 954 /* 955 * If this is a repeating key, start the timer. Otherwise reset 956 * the client back to the root table. 957 */ 958 xtimeout = options_get_number(s->options, "repeat-time"); 959 if (xtimeout != 0 && (bd->flags & KEY_BINDING_REPEAT)) { 960 c->flags |= CLIENT_REPEAT; 961 962 tv.tv_sec = xtimeout / 1000; 963 tv.tv_usec = (xtimeout % 1000) * 1000L; 964 evtimer_del(&c->repeat_timer); 965 evtimer_add(&c->repeat_timer, &tv); 966 } else { 967 c->flags &= ~CLIENT_REPEAT; 968 server_client_set_key_table(c, NULL); 969 } 970 server_status_client(c); 971 972 /* Execute the key binding. */ 973 key_bindings_dispatch(bd, NULL, c, m, &fs); 974 key_bindings_unref_table(table); 975 return; 976 } 977 978 /* 979 * No match, try the ANY key. 980 */ 981 if (key0 != KEYC_ANY) { 982 key0 = KEYC_ANY; 983 goto try_again; 984 } 985 986 /* 987 * No match in this table. If not in the root table or if repeating, 988 * switch the client back to the root table and try again. 989 */ 990 log_debug("not found in key table %s", table->name); 991 if (!server_client_is_default_key_table(c, table) || 992 (c->flags & CLIENT_REPEAT)) { 993 server_client_set_key_table(c, NULL); 994 c->flags &= ~CLIENT_REPEAT; 995 server_status_client(c); 996 table = c->keytable; 997 goto table_changed; 998 } 999 1000 /* 1001 * No match in the root table either. If this wasn't the first table 1002 * tried, don't pass the key to the pane. 1003 */ 1004 if (first != table && (~flags & CLIENT_REPEAT)) { 1005 server_client_set_key_table(c, NULL); 1006 server_status_client(c); 1007 return; 1008 } 1009 1010 forward_key: 1011 if (c->flags & CLIENT_READONLY) 1012 return; 1013 if (wp != NULL) 1014 window_pane_key(wp, c, s, key, m); 1015 } 1016 1017 /* Client functions that need to happen every loop. */ 1018 void 1019 server_client_loop(void) 1020 { 1021 struct client *c; 1022 struct window *w; 1023 struct window_pane *wp; 1024 int focus; 1025 1026 TAILQ_FOREACH(c, &clients, entry) { 1027 server_client_check_exit(c); 1028 if (c->session != NULL) { 1029 server_client_check_redraw(c); 1030 server_client_reset_state(c); 1031 } 1032 } 1033 1034 /* 1035 * Any windows will have been redrawn as part of clients, so clear 1036 * their flags now. Also check pane focus and resize. 1037 */ 1038 focus = options_get_number(global_options, "focus-events"); 1039 RB_FOREACH(w, windows, &windows) { 1040 TAILQ_FOREACH(wp, &w->panes, entry) { 1041 if (wp->fd != -1) { 1042 if (focus) 1043 server_client_check_focus(wp); 1044 server_client_check_resize(wp); 1045 } 1046 wp->flags &= ~PANE_REDRAW; 1047 } 1048 check_window_name(w); 1049 } 1050 } 1051 1052 /* Check if we need to force a resize. */ 1053 static int 1054 server_client_resize_force(struct window_pane *wp) 1055 { 1056 struct timeval tv = { .tv_usec = 100000 }; 1057 struct winsize ws; 1058 1059 /* 1060 * If we are resizing to the same size as when we entered the loop 1061 * (that is, to the same size the application currently thinks it is), 1062 * tmux may have gone through several resizes internally and thrown 1063 * away parts of the screen. So we need the application to actually 1064 * redraw even though its final size has not changed. 1065 */ 1066 1067 if (wp->flags & PANE_RESIZEFORCE) { 1068 wp->flags &= ~PANE_RESIZEFORCE; 1069 return (0); 1070 } 1071 1072 if (wp->sx != wp->osx || 1073 wp->sy != wp->osy || 1074 wp->sx <= 1 || 1075 wp->sy <= 1) 1076 return (0); 1077 1078 memset(&ws, 0, sizeof ws); 1079 ws.ws_col = wp->sx; 1080 ws.ws_row = wp->sy - 1; 1081 if (wp->fd != -1 && ioctl(wp->fd, TIOCSWINSZ, &ws) == -1) 1082 #ifdef __sun 1083 if (errno != EINVAL && errno != ENXIO) 1084 #endif 1085 fatal("ioctl failed"); 1086 log_debug("%s: %%%u forcing resize", __func__, wp->id); 1087 1088 evtimer_add(&wp->resize_timer, &tv); 1089 wp->flags |= PANE_RESIZEFORCE; 1090 return (1); 1091 } 1092 1093 /* Resize timer event. */ 1094 static void 1095 server_client_resize_event(__unused int fd, __unused short events, void *data) 1096 { 1097 struct window_pane *wp = data; 1098 struct winsize ws; 1099 1100 evtimer_del(&wp->resize_timer); 1101 1102 if (!(wp->flags & PANE_RESIZE)) 1103 return; 1104 if (server_client_resize_force(wp)) 1105 return; 1106 1107 memset(&ws, 0, sizeof ws); 1108 ws.ws_col = wp->sx; 1109 ws.ws_row = wp->sy; 1110 if (wp->fd != -1 && ioctl(wp->fd, TIOCSWINSZ, &ws) == -1) 1111 #ifdef __sun 1112 /* 1113 * Some versions of Solaris apparently can return an error when 1114 * resizing; don't know why this happens, can't reproduce on 1115 * other platforms and ignoring it doesn't seem to cause any 1116 * issues. 1117 */ 1118 if (errno != EINVAL && errno != ENXIO) 1119 #endif 1120 fatal("ioctl failed"); 1121 log_debug("%s: %%%u resize to %u,%u", __func__, wp->id, wp->sx, wp->sy); 1122 1123 wp->flags &= ~PANE_RESIZE; 1124 1125 wp->osx = wp->sx; 1126 wp->osy = wp->sy; 1127 } 1128 1129 /* Check if pane should be resized. */ 1130 static void 1131 server_client_check_resize(struct window_pane *wp) 1132 { 1133 struct timeval tv = { .tv_usec = 250000 }; 1134 1135 if (!(wp->flags & PANE_RESIZE)) 1136 return; 1137 log_debug("%s: %%%u resize to %u,%u", __func__, wp->id, wp->sx, wp->sy); 1138 1139 if (!event_initialized(&wp->resize_timer)) 1140 evtimer_set(&wp->resize_timer, server_client_resize_event, wp); 1141 1142 /* 1143 * The first resize should happen immediately, so if the timer is not 1144 * running, do it now. 1145 */ 1146 if (!evtimer_pending(&wp->resize_timer, NULL)) 1147 server_client_resize_event(-1, 0, wp); 1148 1149 /* 1150 * If the pane is in the alternate screen, let the timer expire and 1151 * resize to give the application a chance to redraw. If not, keep 1152 * pushing the timer back. 1153 */ 1154 if (wp->saved_grid != NULL && evtimer_pending(&wp->resize_timer, NULL)) 1155 return; 1156 evtimer_del(&wp->resize_timer); 1157 evtimer_add(&wp->resize_timer, &tv); 1158 } 1159 1160 /* Check whether pane should be focused. */ 1161 static void 1162 server_client_check_focus(struct window_pane *wp) 1163 { 1164 struct client *c; 1165 int push; 1166 1167 /* Do we need to push the focus state? */ 1168 push = wp->flags & PANE_FOCUSPUSH; 1169 wp->flags &= ~PANE_FOCUSPUSH; 1170 1171 /* If we're not the active pane in our window, we're not focused. */ 1172 if (wp->window->active != wp) 1173 goto not_focused; 1174 1175 /* If we're in a mode, we're not focused. */ 1176 if (wp->screen != &wp->base) 1177 goto not_focused; 1178 1179 /* 1180 * If our window is the current window in any focused clients with an 1181 * attached session, we're focused. 1182 */ 1183 TAILQ_FOREACH(c, &clients, entry) { 1184 if (c->session == NULL || !(c->flags & CLIENT_FOCUSED)) 1185 continue; 1186 if (c->session->flags & SESSION_UNATTACHED) 1187 continue; 1188 1189 if (c->session->curw->window == wp->window) 1190 goto focused; 1191 } 1192 1193 not_focused: 1194 if (push || (wp->flags & PANE_FOCUSED)) { 1195 if (wp->base.mode & MODE_FOCUSON) 1196 bufferevent_write(wp->event, "\033[O", 3); 1197 notify_pane("pane-focus-out", wp); 1198 } 1199 wp->flags &= ~PANE_FOCUSED; 1200 return; 1201 1202 focused: 1203 if (push || !(wp->flags & PANE_FOCUSED)) { 1204 if (wp->base.mode & MODE_FOCUSON) 1205 bufferevent_write(wp->event, "\033[I", 3); 1206 notify_pane("pane-focus-in", wp); 1207 } 1208 wp->flags |= PANE_FOCUSED; 1209 } 1210 1211 /* 1212 * Update cursor position and mode settings. The scroll region and attributes 1213 * are cleared when idle (waiting for an event) as this is the most likely time 1214 * a user may interrupt tmux, for example with ~^Z in ssh(1). This is a 1215 * compromise between excessive resets and likelihood of an interrupt. 1216 * 1217 * tty_region/tty_reset/tty_update_mode already take care of not resetting 1218 * things that are already in their default state. 1219 */ 1220 static void 1221 server_client_reset_state(struct client *c) 1222 { 1223 struct window *w = c->session->curw->window; 1224 struct window_pane *wp = w->active, *loop; 1225 struct screen *s = wp->screen; 1226 struct options *oo = c->session->options; 1227 int lines, mode; 1228 1229 if (c->flags & (CLIENT_CONTROL|CLIENT_SUSPENDED)) 1230 return; 1231 1232 tty_region_off(&c->tty); 1233 tty_margin_off(&c->tty); 1234 1235 if (status_at_line(c) != 0) 1236 lines = 0; 1237 else 1238 lines = status_line_size(c->session); 1239 if (!window_pane_visible(wp) || wp->yoff + s->cy >= c->tty.sy - lines) 1240 tty_cursor(&c->tty, 0, 0); 1241 else 1242 tty_cursor(&c->tty, wp->xoff + s->cx, lines + wp->yoff + s->cy); 1243 1244 /* 1245 * Set mouse mode if requested. To support dragging, always use button 1246 * mode. 1247 */ 1248 mode = s->mode; 1249 if (options_get_number(oo, "mouse")) { 1250 mode &= ~ALL_MOUSE_MODES; 1251 TAILQ_FOREACH(loop, &w->panes, entry) { 1252 if (loop->screen->mode & MODE_MOUSE_ALL) 1253 mode |= MODE_MOUSE_ALL; 1254 } 1255 if (~mode & MODE_MOUSE_ALL) 1256 mode |= MODE_MOUSE_BUTTON; 1257 } 1258 1259 /* Clear bracketed paste mode if at the prompt. */ 1260 if (c->prompt_string != NULL) 1261 mode &= ~MODE_BRACKETPASTE; 1262 1263 /* Set the terminal mode and reset attributes. */ 1264 tty_update_mode(&c->tty, mode, s); 1265 tty_reset(&c->tty); 1266 } 1267 1268 /* Repeat time callback. */ 1269 static void 1270 server_client_repeat_timer(__unused int fd, __unused short events, void *data) 1271 { 1272 struct client *c = data; 1273 1274 if (c->flags & CLIENT_REPEAT) { 1275 server_client_set_key_table(c, NULL); 1276 c->flags &= ~CLIENT_REPEAT; 1277 server_status_client(c); 1278 } 1279 } 1280 1281 /* Double-click callback. */ 1282 static void 1283 server_client_click_timer(__unused int fd, __unused short events, void *data) 1284 { 1285 struct client *c = data; 1286 1287 c->flags &= ~(CLIENT_DOUBLECLICK|CLIENT_TRIPLECLICK); 1288 } 1289 1290 /* Check if client should be exited. */ 1291 static void 1292 server_client_check_exit(struct client *c) 1293 { 1294 if (!(c->flags & CLIENT_EXIT)) 1295 return; 1296 1297 if (EVBUFFER_LENGTH(c->stdin_data) != 0) 1298 return; 1299 if (EVBUFFER_LENGTH(c->stdout_data) != 0) 1300 return; 1301 if (EVBUFFER_LENGTH(c->stderr_data) != 0) 1302 return; 1303 1304 if (c->flags & CLIENT_ATTACHED) 1305 notify_client("client-detached", c); 1306 proc_send(c->peer, MSG_EXIT, -1, &c->retval, sizeof c->retval); 1307 c->flags &= ~CLIENT_EXIT; 1308 } 1309 1310 /* Redraw timer callback. */ 1311 static void 1312 server_client_redraw_timer(__unused int fd, __unused short events, 1313 __unused void* data) 1314 { 1315 log_debug("redraw timer fired"); 1316 } 1317 1318 /* Check for client redraws. */ 1319 static void 1320 server_client_check_redraw(struct client *c) 1321 { 1322 struct session *s = c->session; 1323 struct tty *tty = &c->tty; 1324 struct window_pane *wp; 1325 int needed, flags, masked; 1326 struct timeval tv = { .tv_usec = 1000 }; 1327 static struct event ev; 1328 size_t left; 1329 1330 if (c->flags & (CLIENT_CONTROL|CLIENT_SUSPENDED)) 1331 return; 1332 1333 /* 1334 * If there is outstanding data, defer the redraw until it has been 1335 * consumed. We can just add a timer to get out of the event loop and 1336 * end up back here. 1337 */ 1338 needed = 0; 1339 if (c->flags & CLIENT_REDRAW) 1340 needed = 1; 1341 else { 1342 TAILQ_FOREACH(wp, &c->session->curw->window->panes, entry) { 1343 if (wp->flags & PANE_REDRAW) { 1344 needed = 1; 1345 break; 1346 } 1347 } 1348 } 1349 if (needed && (left = EVBUFFER_LENGTH(tty->out)) != 0) { 1350 log_debug("%s: redraw deferred (%zu left)", c->name, left); 1351 if (!evtimer_initialized(&ev)) 1352 evtimer_set(&ev, server_client_redraw_timer, NULL); 1353 if (!evtimer_pending(&ev, NULL)) { 1354 log_debug("redraw timer started"); 1355 evtimer_add(&ev, &tv); 1356 } 1357 1358 /* 1359 * We may have got here for a single pane redraw, but force a 1360 * full redraw next time in case other panes have been updated. 1361 */ 1362 c->flags |= CLIENT_REDRAW; 1363 return; 1364 } else if (needed) 1365 log_debug("%s: redraw needed", c->name); 1366 1367 if (c->flags & (CLIENT_REDRAW|CLIENT_STATUS)) { 1368 if (options_get_number(s->options, "set-titles")) 1369 server_client_set_title(c); 1370 screen_redraw_update(c); /* will adjust flags */ 1371 } 1372 1373 flags = tty->flags & (TTY_BLOCK|TTY_FREEZE|TTY_NOCURSOR); 1374 tty->flags = (tty->flags & ~(TTY_BLOCK|TTY_FREEZE)) | TTY_NOCURSOR; 1375 1376 if (c->flags & CLIENT_REDRAW) { 1377 tty_update_mode(tty, tty->mode, NULL); 1378 screen_redraw_screen(c, 1, 1, 1); 1379 c->flags &= ~(CLIENT_STATUS|CLIENT_BORDERS); 1380 } else { 1381 TAILQ_FOREACH(wp, &c->session->curw->window->panes, entry) { 1382 if (wp->flags & PANE_REDRAW) { 1383 tty_update_mode(tty, tty->mode, NULL); 1384 screen_redraw_pane(c, wp); 1385 } 1386 } 1387 } 1388 1389 masked = c->flags & (CLIENT_BORDERS|CLIENT_STATUS); 1390 if (masked != 0) 1391 tty_update_mode(tty, tty->mode, NULL); 1392 if (masked == CLIENT_BORDERS) 1393 screen_redraw_screen(c, 0, 0, 1); 1394 else if (masked == CLIENT_STATUS) 1395 screen_redraw_screen(c, 0, 1, 0); 1396 else if (masked != 0) 1397 screen_redraw_screen(c, 0, 1, 1); 1398 1399 tty->flags = (tty->flags & ~(TTY_FREEZE|TTY_NOCURSOR)) | flags; 1400 tty_update_mode(tty, tty->mode, NULL); 1401 1402 c->flags &= ~(CLIENT_REDRAW|CLIENT_BORDERS|CLIENT_STATUS| 1403 CLIENT_STATUSFORCE); 1404 1405 if (needed) { 1406 /* 1407 * We would have deferred the redraw unless the output buffer 1408 * was empty, so we can record how many bytes the redraw 1409 * generated. 1410 */ 1411 c->redraw = EVBUFFER_LENGTH(tty->out); 1412 log_debug("%s: redraw added %zu bytes", c->name, c->redraw); 1413 } 1414 } 1415 1416 /* Set client title. */ 1417 static void 1418 server_client_set_title(struct client *c) 1419 { 1420 struct session *s = c->session; 1421 const char *template; 1422 char *title; 1423 struct format_tree *ft; 1424 1425 template = options_get_string(s->options, "set-titles-string"); 1426 1427 ft = format_create(c, NULL, FORMAT_NONE, 0); 1428 format_defaults(ft, c, NULL, NULL, NULL); 1429 1430 title = format_expand_time(ft, template, time(NULL)); 1431 if (c->title == NULL || strcmp(title, c->title) != 0) { 1432 free(c->title); 1433 c->title = xstrdup(title); 1434 tty_set_title(&c->tty, c->title); 1435 } 1436 free(title); 1437 1438 format_free(ft); 1439 } 1440 1441 /* Dispatch message from client. */ 1442 static void 1443 server_client_dispatch(struct imsg *imsg, void *arg) 1444 { 1445 struct client *c = arg; 1446 struct msg_stdin_data stdindata; 1447 const char *data; 1448 ssize_t datalen; 1449 struct session *s; 1450 1451 if (c->flags & CLIENT_DEAD) 1452 return; 1453 1454 if (imsg == NULL) { 1455 server_client_lost(c); 1456 return; 1457 } 1458 1459 data = imsg->data; 1460 datalen = imsg->hdr.len - IMSG_HEADER_SIZE; 1461 1462 switch (imsg->hdr.type) { 1463 case MSG_IDENTIFY_FLAGS: 1464 case MSG_IDENTIFY_TERM: 1465 case MSG_IDENTIFY_TTYNAME: 1466 case MSG_IDENTIFY_CWD: 1467 case MSG_IDENTIFY_STDIN: 1468 case MSG_IDENTIFY_ENVIRON: 1469 case MSG_IDENTIFY_CLIENTPID: 1470 case MSG_IDENTIFY_DONE: 1471 server_client_dispatch_identify(c, imsg); 1472 break; 1473 case MSG_COMMAND: 1474 server_client_dispatch_command(c, imsg); 1475 break; 1476 case MSG_STDIN: 1477 if (datalen != sizeof stdindata) 1478 fatalx("bad MSG_STDIN size"); 1479 memcpy(&stdindata, data, sizeof stdindata); 1480 1481 if (c->stdin_callback == NULL) 1482 break; 1483 if (stdindata.size <= 0) 1484 c->stdin_closed = 1; 1485 else { 1486 evbuffer_add(c->stdin_data, stdindata.data, 1487 stdindata.size); 1488 } 1489 c->stdin_callback(c, c->stdin_closed, 1490 c->stdin_callback_data); 1491 break; 1492 case MSG_RESIZE: 1493 if (datalen != 0) 1494 fatalx("bad MSG_RESIZE size"); 1495 1496 if (c->flags & CLIENT_CONTROL) 1497 break; 1498 tty_resize(&c->tty); 1499 recalculate_sizes(); 1500 server_redraw_client(c); 1501 if (c->session != NULL) 1502 notify_client("client-resized", c); 1503 break; 1504 case MSG_EXITING: 1505 if (datalen != 0) 1506 fatalx("bad MSG_EXITING size"); 1507 1508 c->session = NULL; 1509 tty_close(&c->tty); 1510 proc_send(c->peer, MSG_EXITED, -1, NULL, 0); 1511 break; 1512 case MSG_WAKEUP: 1513 case MSG_UNLOCK: 1514 if (datalen != 0) 1515 fatalx("bad MSG_WAKEUP size"); 1516 1517 if (!(c->flags & CLIENT_SUSPENDED)) 1518 break; 1519 c->flags &= ~CLIENT_SUSPENDED; 1520 1521 if (c->tty.fd == -1) /* exited in the meantime */ 1522 break; 1523 s = c->session; 1524 1525 if (gettimeofday(&c->activity_time, NULL) != 0) 1526 fatal("gettimeofday failed"); 1527 1528 tty_start_tty(&c->tty); 1529 server_redraw_client(c); 1530 recalculate_sizes(); 1531 1532 if (s != NULL) 1533 session_update_activity(s, &c->activity_time); 1534 break; 1535 case MSG_SHELL: 1536 if (datalen != 0) 1537 fatalx("bad MSG_SHELL size"); 1538 1539 server_client_dispatch_shell(c); 1540 break; 1541 } 1542 } 1543 1544 /* Callback when command is done. */ 1545 static enum cmd_retval 1546 server_client_command_done(struct cmdq_item *item, __unused void *data) 1547 { 1548 struct client *c = item->client; 1549 1550 if (~c->flags & CLIENT_ATTACHED) 1551 c->flags |= CLIENT_EXIT; 1552 return (CMD_RETURN_NORMAL); 1553 } 1554 1555 /* Show an error message. */ 1556 static enum cmd_retval 1557 server_client_command_error(struct cmdq_item *item, void *data) 1558 { 1559 char *error = data; 1560 1561 cmdq_error(item, "%s", error); 1562 free(error); 1563 1564 return (CMD_RETURN_NORMAL); 1565 } 1566 1567 /* Handle command message. */ 1568 static void 1569 server_client_dispatch_command(struct client *c, struct imsg *imsg) 1570 { 1571 struct msg_command_data data; 1572 char *buf; 1573 size_t len; 1574 struct cmd_list *cmdlist = NULL; 1575 int argc; 1576 char **argv, *cause; 1577 1578 if (c->flags & CLIENT_EXIT) 1579 return; 1580 1581 if (imsg->hdr.len - IMSG_HEADER_SIZE < sizeof data) 1582 fatalx("bad MSG_COMMAND size"); 1583 memcpy(&data, imsg->data, sizeof data); 1584 1585 buf = (char *)imsg->data + sizeof data; 1586 len = imsg->hdr.len - IMSG_HEADER_SIZE - sizeof data; 1587 if (len > 0 && buf[len - 1] != '\0') 1588 fatalx("bad MSG_COMMAND string"); 1589 1590 argc = data.argc; 1591 if (cmd_unpack_argv(buf, len, argc, &argv) != 0) { 1592 cause = xstrdup("command too long"); 1593 goto error; 1594 } 1595 1596 if (argc == 0) { 1597 argc = 1; 1598 argv = xcalloc(1, sizeof *argv); 1599 *argv = xstrdup("new-session"); 1600 } 1601 1602 if ((cmdlist = cmd_list_parse(argc, argv, NULL, 0, &cause)) == NULL) { 1603 cmd_free_argv(argc, argv); 1604 goto error; 1605 } 1606 cmd_free_argv(argc, argv); 1607 1608 cmdq_append(c, cmdq_get_command(cmdlist, NULL, NULL, 0)); 1609 cmdq_append(c, cmdq_get_callback(server_client_command_done, NULL)); 1610 cmd_list_free(cmdlist); 1611 return; 1612 1613 error: 1614 cmdq_append(c, cmdq_get_callback(server_client_command_error, cause)); 1615 1616 if (cmdlist != NULL) 1617 cmd_list_free(cmdlist); 1618 1619 c->flags |= CLIENT_EXIT; 1620 } 1621 1622 /* Handle identify message. */ 1623 static void 1624 server_client_dispatch_identify(struct client *c, struct imsg *imsg) 1625 { 1626 const char *data, *home; 1627 size_t datalen; 1628 int flags; 1629 char *name; 1630 1631 if (c->flags & CLIENT_IDENTIFIED) 1632 fatalx("out-of-order identify message"); 1633 1634 data = imsg->data; 1635 datalen = imsg->hdr.len - IMSG_HEADER_SIZE; 1636 1637 switch (imsg->hdr.type) { 1638 case MSG_IDENTIFY_FLAGS: 1639 if (datalen != sizeof flags) 1640 fatalx("bad MSG_IDENTIFY_FLAGS size"); 1641 memcpy(&flags, data, sizeof flags); 1642 c->flags |= flags; 1643 log_debug("client %p IDENTIFY_FLAGS %#x", c, flags); 1644 break; 1645 case MSG_IDENTIFY_TERM: 1646 if (datalen == 0 || data[datalen - 1] != '\0') 1647 fatalx("bad MSG_IDENTIFY_TERM string"); 1648 c->term = xstrdup(data); 1649 log_debug("client %p IDENTIFY_TERM %s", c, data); 1650 break; 1651 case MSG_IDENTIFY_TTYNAME: 1652 if (datalen == 0 || data[datalen - 1] != '\0') 1653 fatalx("bad MSG_IDENTIFY_TTYNAME string"); 1654 c->ttyname = xstrdup(data); 1655 log_debug("client %p IDENTIFY_TTYNAME %s", c, data); 1656 break; 1657 case MSG_IDENTIFY_CWD: 1658 if (datalen == 0 || data[datalen - 1] != '\0') 1659 fatalx("bad MSG_IDENTIFY_CWD string"); 1660 if (access(data, X_OK) == 0) 1661 c->cwd = xstrdup(data); 1662 else if ((home = find_home()) != NULL) 1663 c->cwd = xstrdup(home); 1664 else 1665 c->cwd = xstrdup("/"); 1666 log_debug("client %p IDENTIFY_CWD %s", c, data); 1667 break; 1668 case MSG_IDENTIFY_STDIN: 1669 if (datalen != 0) 1670 fatalx("bad MSG_IDENTIFY_STDIN size"); 1671 c->fd = imsg->fd; 1672 log_debug("client %p IDENTIFY_STDIN %d", c, imsg->fd); 1673 break; 1674 case MSG_IDENTIFY_ENVIRON: 1675 if (datalen == 0 || data[datalen - 1] != '\0') 1676 fatalx("bad MSG_IDENTIFY_ENVIRON string"); 1677 if (strchr(data, '=') != NULL) 1678 environ_put(c->environ, data); 1679 log_debug("client %p IDENTIFY_ENVIRON %s", c, data); 1680 break; 1681 case MSG_IDENTIFY_CLIENTPID: 1682 if (datalen != sizeof c->pid) 1683 fatalx("bad MSG_IDENTIFY_CLIENTPID size"); 1684 memcpy(&c->pid, data, sizeof c->pid); 1685 log_debug("client %p IDENTIFY_CLIENTPID %ld", c, (long)c->pid); 1686 break; 1687 default: 1688 break; 1689 } 1690 1691 if (imsg->hdr.type != MSG_IDENTIFY_DONE) 1692 return; 1693 c->flags |= CLIENT_IDENTIFIED; 1694 1695 if (*c->ttyname != '\0') 1696 name = xstrdup(c->ttyname); 1697 else 1698 xasprintf(&name, "client-%ld", (long)c->pid); 1699 c->name = name; 1700 log_debug("client %p name is %s", c, c->name); 1701 1702 #ifdef __CYGWIN__ 1703 c->fd = open(c->ttyname, O_RDWR|O_NOCTTY); 1704 #endif 1705 1706 if (c->flags & CLIENT_CONTROL) { 1707 c->stdin_callback = control_callback; 1708 1709 evbuffer_free(c->stderr_data); 1710 c->stderr_data = c->stdout_data; 1711 1712 if (c->flags & CLIENT_CONTROLCONTROL) 1713 evbuffer_add_printf(c->stdout_data, "\033P1000p"); 1714 proc_send(c->peer, MSG_STDIN, -1, NULL, 0); 1715 1716 c->tty.fd = -1; 1717 1718 close(c->fd); 1719 c->fd = -1; 1720 1721 return; 1722 } 1723 1724 if (c->fd == -1) 1725 return; 1726 if (tty_init(&c->tty, c, c->fd, c->term) != 0) { 1727 close(c->fd); 1728 c->fd = -1; 1729 return; 1730 } 1731 if (c->flags & CLIENT_UTF8) 1732 c->tty.flags |= TTY_UTF8; 1733 if (c->flags & CLIENT_256COLOURS) 1734 c->tty.term_flags |= TERM_256COLOURS; 1735 1736 tty_resize(&c->tty); 1737 1738 if (!(c->flags & CLIENT_CONTROL)) 1739 c->flags |= CLIENT_TERMINAL; 1740 } 1741 1742 /* Handle shell message. */ 1743 static void 1744 server_client_dispatch_shell(struct client *c) 1745 { 1746 const char *shell; 1747 1748 shell = options_get_string(global_s_options, "default-shell"); 1749 if (*shell == '\0' || areshell(shell)) 1750 shell = _PATH_BSHELL; 1751 proc_send(c->peer, MSG_SHELL, -1, shell, strlen(shell) + 1); 1752 1753 proc_kill_peer(c->peer); 1754 } 1755 1756 /* Event callback to push more stdout data if any left. */ 1757 static void 1758 server_client_stdout_cb(__unused int fd, __unused short events, void *arg) 1759 { 1760 struct client *c = arg; 1761 1762 if (~c->flags & CLIENT_DEAD) 1763 server_client_push_stdout(c); 1764 server_client_unref(c); 1765 } 1766 1767 /* Push stdout to client if possible. */ 1768 void 1769 server_client_push_stdout(struct client *c) 1770 { 1771 struct msg_stdout_data data; 1772 size_t sent, left; 1773 1774 left = EVBUFFER_LENGTH(c->stdout_data); 1775 while (left != 0) { 1776 sent = left; 1777 if (sent > sizeof data.data) 1778 sent = sizeof data.data; 1779 memcpy(data.data, EVBUFFER_DATA(c->stdout_data), sent); 1780 data.size = sent; 1781 1782 if (proc_send(c->peer, MSG_STDOUT, -1, &data, sizeof data) != 0) 1783 break; 1784 evbuffer_drain(c->stdout_data, sent); 1785 1786 left = EVBUFFER_LENGTH(c->stdout_data); 1787 log_debug("%s: client %p, sent %zu, left %zu", __func__, c, 1788 sent, left); 1789 } 1790 if (left != 0) { 1791 c->references++; 1792 event_once(-1, EV_TIMEOUT, server_client_stdout_cb, c, NULL); 1793 log_debug("%s: client %p, queued", __func__, c); 1794 } 1795 } 1796 1797 /* Event callback to push more stderr data if any left. */ 1798 static void 1799 server_client_stderr_cb(__unused int fd, __unused short events, void *arg) 1800 { 1801 struct client *c = arg; 1802 1803 if (~c->flags & CLIENT_DEAD) 1804 server_client_push_stderr(c); 1805 server_client_unref(c); 1806 } 1807 1808 /* Push stderr to client if possible. */ 1809 void 1810 server_client_push_stderr(struct client *c) 1811 { 1812 struct msg_stderr_data data; 1813 size_t sent, left; 1814 1815 if (c->stderr_data == c->stdout_data) { 1816 server_client_push_stdout(c); 1817 return; 1818 } 1819 1820 left = EVBUFFER_LENGTH(c->stderr_data); 1821 while (left != 0) { 1822 sent = left; 1823 if (sent > sizeof data.data) 1824 sent = sizeof data.data; 1825 memcpy(data.data, EVBUFFER_DATA(c->stderr_data), sent); 1826 data.size = sent; 1827 1828 if (proc_send(c->peer, MSG_STDERR, -1, &data, sizeof data) != 0) 1829 break; 1830 evbuffer_drain(c->stderr_data, sent); 1831 1832 left = EVBUFFER_LENGTH(c->stderr_data); 1833 log_debug("%s: client %p, sent %zu, left %zu", __func__, c, 1834 sent, left); 1835 } 1836 if (left != 0) { 1837 c->references++; 1838 event_once(-1, EV_TIMEOUT, server_client_stderr_cb, c, NULL); 1839 log_debug("%s: client %p, queued", __func__, c); 1840 } 1841 } 1842 1843 /* Add to client message log. */ 1844 void 1845 server_client_add_message(struct client *c, const char *fmt, ...) 1846 { 1847 struct message_entry *msg, *msg1; 1848 char *s; 1849 va_list ap; 1850 u_int limit; 1851 1852 va_start(ap, fmt); 1853 xvasprintf(&s, fmt, ap); 1854 va_end(ap); 1855 1856 log_debug("message %s (client %p)", s, c); 1857 1858 msg = xcalloc(1, sizeof *msg); 1859 msg->msg_time = time(NULL); 1860 msg->msg_num = c->message_next++; 1861 msg->msg = s; 1862 TAILQ_INSERT_TAIL(&c->message_log, msg, entry); 1863 1864 limit = options_get_number(global_options, "message-limit"); 1865 TAILQ_FOREACH_SAFE(msg, &c->message_log, entry, msg1) { 1866 if (msg->msg_num + limit >= c->message_next) 1867 break; 1868 free(msg->msg); 1869 TAILQ_REMOVE(&c->message_log, msg, entry); 1870 free(msg); 1871 } 1872 } 1873 1874 /* Get client working directory. */ 1875 const char * 1876 server_client_get_cwd(struct client *c, struct session *s) 1877 { 1878 const char *home; 1879 1880 if (c != NULL && c->session == NULL && c->cwd != NULL) 1881 return (c->cwd); 1882 if (s != NULL && s->cwd != NULL) 1883 return (s->cwd); 1884 if (c != NULL && (s = c->session) != NULL && s->cwd != NULL) 1885 return (s->cwd); 1886 if ((home = find_home()) != NULL) 1887 return (home); 1888 return ("/"); 1889 } 1890 1891 /* Resolve an absolute path or relative to client working directory. */ 1892 char * 1893 server_client_get_path(struct client *c, const char *file) 1894 { 1895 char *path, resolved[PATH_MAX]; 1896 1897 if (*file == '/') 1898 path = xstrdup(file); 1899 else 1900 xasprintf(&path, "%s/%s", server_client_get_cwd(c, NULL), file); 1901 if (realpath(path, resolved) == NULL) 1902 return (path); 1903 free(path); 1904 return (xstrdup(resolved)); 1905 } 1906