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