1 /* $OpenBSD: server-client.c,v 1.250 2018/05/24 09:42:49 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 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((void *)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((void *)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_find, *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; 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; 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 /* 907 * The prefix always takes precedence and forces a switch to the prefix 908 * table, unless we are already there. 909 */ 910 retry: 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 to see if there is a key binding in the current table. */ 930 bd_find.key = key0; 931 bd = RB_FIND(key_bindings, &table->key_bindings, &bd_find); 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 retry; 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 in this table. If not in the root table or if repeating, 980 * switch the client back to the root table and try again. 981 */ 982 log_debug("not found in key table %s", table->name); 983 if (!server_client_is_default_key_table(c, table) || 984 (c->flags & CLIENT_REPEAT)) { 985 server_client_set_key_table(c, NULL); 986 c->flags &= ~CLIENT_REPEAT; 987 server_status_client(c); 988 table = c->keytable; 989 goto retry; 990 } 991 992 /* 993 * No match in the root table either. If this wasn't the first table 994 * tried, don't pass the key to the pane. 995 */ 996 if (first != table && (~flags & CLIENT_REPEAT)) { 997 server_client_set_key_table(c, NULL); 998 server_status_client(c); 999 return; 1000 } 1001 1002 forward: 1003 if (c->flags & CLIENT_READONLY) 1004 return; 1005 if (wp != NULL) 1006 window_pane_key(wp, c, s, key, m); 1007 } 1008 1009 /* Client functions that need to happen every loop. */ 1010 void 1011 server_client_loop(void) 1012 { 1013 struct client *c; 1014 struct window *w; 1015 struct window_pane *wp; 1016 int focus; 1017 1018 TAILQ_FOREACH(c, &clients, entry) { 1019 server_client_check_exit(c); 1020 if (c->session != NULL) { 1021 server_client_check_redraw(c); 1022 server_client_reset_state(c); 1023 } 1024 } 1025 1026 /* 1027 * Any windows will have been redrawn as part of clients, so clear 1028 * their flags now. Also check pane focus and resize. 1029 */ 1030 focus = options_get_number(global_options, "focus-events"); 1031 RB_FOREACH(w, windows, &windows) { 1032 TAILQ_FOREACH(wp, &w->panes, entry) { 1033 if (wp->fd != -1) { 1034 if (focus) 1035 server_client_check_focus(wp); 1036 server_client_check_resize(wp); 1037 } 1038 wp->flags &= ~PANE_REDRAW; 1039 } 1040 check_window_name(w); 1041 } 1042 } 1043 1044 /* Check if we need to force a resize. */ 1045 static int 1046 server_client_resize_force(struct window_pane *wp) 1047 { 1048 struct timeval tv = { .tv_usec = 100000 }; 1049 struct winsize ws; 1050 1051 /* 1052 * If we are resizing to the same size as when we entered the loop 1053 * (that is, to the same size the application currently thinks it is), 1054 * tmux may have gone through several resizes internally and thrown 1055 * away parts of the screen. So we need the application to actually 1056 * redraw even though its final size has not changed. 1057 */ 1058 1059 if (wp->flags & PANE_RESIZEFORCE) { 1060 wp->flags &= ~PANE_RESIZEFORCE; 1061 return (0); 1062 } 1063 1064 if (wp->sx != wp->osx || 1065 wp->sy != wp->osy || 1066 wp->sx <= 1 || 1067 wp->sy <= 1) 1068 return (0); 1069 1070 memset(&ws, 0, sizeof ws); 1071 ws.ws_col = wp->sx; 1072 ws.ws_row = wp->sy - 1; 1073 if (wp->fd != -1 && ioctl(wp->fd, TIOCSWINSZ, &ws) == -1) 1074 fatal("ioctl failed"); 1075 log_debug("%s: %%%u forcing resize", __func__, wp->id); 1076 1077 evtimer_add(&wp->resize_timer, &tv); 1078 wp->flags |= PANE_RESIZEFORCE; 1079 return (1); 1080 } 1081 1082 /* Resize timer event. */ 1083 static void 1084 server_client_resize_event(__unused int fd, __unused short events, void *data) 1085 { 1086 struct window_pane *wp = data; 1087 struct winsize ws; 1088 1089 evtimer_del(&wp->resize_timer); 1090 1091 if (!(wp->flags & PANE_RESIZE)) 1092 return; 1093 if (server_client_resize_force(wp)) 1094 return; 1095 1096 memset(&ws, 0, sizeof ws); 1097 ws.ws_col = wp->sx; 1098 ws.ws_row = wp->sy; 1099 if (wp->fd != -1 && ioctl(wp->fd, TIOCSWINSZ, &ws) == -1) 1100 fatal("ioctl failed"); 1101 log_debug("%s: %%%u resize to %u,%u", __func__, wp->id, wp->sx, wp->sy); 1102 1103 wp->flags &= ~PANE_RESIZE; 1104 1105 wp->osx = wp->sx; 1106 wp->osy = wp->sy; 1107 } 1108 1109 /* Check if pane should be resized. */ 1110 static void 1111 server_client_check_resize(struct window_pane *wp) 1112 { 1113 struct timeval tv = { .tv_usec = 250000 }; 1114 1115 if (!(wp->flags & PANE_RESIZE)) 1116 return; 1117 log_debug("%s: %%%u resize to %u,%u", __func__, wp->id, wp->sx, wp->sy); 1118 1119 if (!event_initialized(&wp->resize_timer)) 1120 evtimer_set(&wp->resize_timer, server_client_resize_event, wp); 1121 1122 /* 1123 * The first resize should happen immediately, so if the timer is not 1124 * running, do it now. 1125 */ 1126 if (!evtimer_pending(&wp->resize_timer, NULL)) 1127 server_client_resize_event(-1, 0, wp); 1128 1129 /* 1130 * If the pane is in the alternate screen, let the timer expire and 1131 * resize to give the application a chance to redraw. If not, keep 1132 * pushing the timer back. 1133 */ 1134 if (wp->saved_grid != NULL && evtimer_pending(&wp->resize_timer, NULL)) 1135 return; 1136 evtimer_del(&wp->resize_timer); 1137 evtimer_add(&wp->resize_timer, &tv); 1138 } 1139 1140 /* Check whether pane should be focused. */ 1141 static void 1142 server_client_check_focus(struct window_pane *wp) 1143 { 1144 struct client *c; 1145 int push; 1146 1147 /* Do we need to push the focus state? */ 1148 push = wp->flags & PANE_FOCUSPUSH; 1149 wp->flags &= ~PANE_FOCUSPUSH; 1150 1151 /* If we don't care about focus, forget it. */ 1152 if (!(wp->base.mode & MODE_FOCUSON)) 1153 return; 1154 1155 /* If we're not the active pane in our window, we're not focused. */ 1156 if (wp->window->active != wp) 1157 goto not_focused; 1158 1159 /* If we're in a mode, we're not focused. */ 1160 if (wp->screen != &wp->base) 1161 goto not_focused; 1162 1163 /* 1164 * If our window is the current window in any focused clients with an 1165 * attached session, we're focused. 1166 */ 1167 TAILQ_FOREACH(c, &clients, entry) { 1168 if (c->session == NULL || !(c->flags & CLIENT_FOCUSED)) 1169 continue; 1170 if (c->session->flags & SESSION_UNATTACHED) 1171 continue; 1172 1173 if (c->session->curw->window == wp->window) 1174 goto focused; 1175 } 1176 1177 not_focused: 1178 if (push || (wp->flags & PANE_FOCUSED)) 1179 bufferevent_write(wp->event, "\033[O", 3); 1180 wp->flags &= ~PANE_FOCUSED; 1181 return; 1182 1183 focused: 1184 if (push || !(wp->flags & PANE_FOCUSED)) 1185 bufferevent_write(wp->event, "\033[I", 3); 1186 wp->flags |= PANE_FOCUSED; 1187 } 1188 1189 /* 1190 * Update cursor position and mode settings. The scroll region and attributes 1191 * are cleared when idle (waiting for an event) as this is the most likely time 1192 * a user may interrupt tmux, for example with ~^Z in ssh(1). This is a 1193 * compromise between excessive resets and likelihood of an interrupt. 1194 * 1195 * tty_region/tty_reset/tty_update_mode already take care of not resetting 1196 * things that are already in their default state. 1197 */ 1198 static void 1199 server_client_reset_state(struct client *c) 1200 { 1201 struct window *w = c->session->curw->window; 1202 struct window_pane *wp = w->active, *loop; 1203 struct screen *s = wp->screen; 1204 struct options *oo = c->session->options; 1205 int lines, mode; 1206 1207 if (c->flags & (CLIENT_CONTROL|CLIENT_SUSPENDED)) 1208 return; 1209 1210 tty_region_off(&c->tty); 1211 tty_margin_off(&c->tty); 1212 1213 if (status_at_line(c) != 0) 1214 lines = 0; 1215 else 1216 lines = status_line_size(c->session); 1217 if (!window_pane_visible(wp) || wp->yoff + s->cy >= c->tty.sy - lines) 1218 tty_cursor(&c->tty, 0, 0); 1219 else 1220 tty_cursor(&c->tty, wp->xoff + s->cx, lines + wp->yoff + s->cy); 1221 1222 /* 1223 * Set mouse mode if requested. To support dragging, always use button 1224 * mode. 1225 */ 1226 mode = s->mode; 1227 if (options_get_number(oo, "mouse")) { 1228 mode &= ~ALL_MOUSE_MODES; 1229 TAILQ_FOREACH(loop, &w->panes, entry) { 1230 if (loop->screen->mode & MODE_MOUSE_ALL) 1231 mode |= MODE_MOUSE_ALL; 1232 } 1233 if (~mode & MODE_MOUSE_ALL) 1234 mode |= MODE_MOUSE_BUTTON; 1235 } 1236 1237 /* Clear bracketed paste mode if at the prompt. */ 1238 if (c->prompt_string != NULL) 1239 mode &= ~MODE_BRACKETPASTE; 1240 1241 /* Set the terminal mode and reset attributes. */ 1242 tty_update_mode(&c->tty, mode, s); 1243 tty_reset(&c->tty); 1244 } 1245 1246 /* Repeat time callback. */ 1247 static void 1248 server_client_repeat_timer(__unused int fd, __unused short events, void *data) 1249 { 1250 struct client *c = data; 1251 1252 if (c->flags & CLIENT_REPEAT) { 1253 server_client_set_key_table(c, NULL); 1254 c->flags &= ~CLIENT_REPEAT; 1255 server_status_client(c); 1256 } 1257 } 1258 1259 /* Double-click callback. */ 1260 static void 1261 server_client_click_timer(__unused int fd, __unused short events, void *data) 1262 { 1263 struct client *c = data; 1264 1265 c->flags &= ~(CLIENT_DOUBLECLICK|CLIENT_TRIPLECLICK); 1266 } 1267 1268 /* Check if client should be exited. */ 1269 static void 1270 server_client_check_exit(struct client *c) 1271 { 1272 if (!(c->flags & CLIENT_EXIT)) 1273 return; 1274 1275 if (EVBUFFER_LENGTH(c->stdin_data) != 0) 1276 return; 1277 if (EVBUFFER_LENGTH(c->stdout_data) != 0) 1278 return; 1279 if (EVBUFFER_LENGTH(c->stderr_data) != 0) 1280 return; 1281 1282 if (c->flags & CLIENT_ATTACHED) 1283 notify_client("client-detached", c); 1284 proc_send(c->peer, MSG_EXIT, -1, &c->retval, sizeof c->retval); 1285 c->flags &= ~CLIENT_EXIT; 1286 } 1287 1288 /* Redraw timer callback. */ 1289 static void 1290 server_client_redraw_timer(__unused int fd, __unused short events, 1291 __unused void* data) 1292 { 1293 log_debug("redraw timer fired"); 1294 } 1295 1296 /* Check for client redraws. */ 1297 static void 1298 server_client_check_redraw(struct client *c) 1299 { 1300 struct session *s = c->session; 1301 struct tty *tty = &c->tty; 1302 struct window_pane *wp; 1303 int needed, flags, masked; 1304 struct timeval tv = { .tv_usec = 1000 }; 1305 static struct event ev; 1306 size_t left; 1307 1308 if (c->flags & (CLIENT_CONTROL|CLIENT_SUSPENDED)) 1309 return; 1310 1311 /* 1312 * If there is outstanding data, defer the redraw until it has been 1313 * consumed. We can just add a timer to get out of the event loop and 1314 * end up back here. 1315 */ 1316 needed = 0; 1317 if (c->flags & CLIENT_REDRAW) 1318 needed = 1; 1319 else { 1320 TAILQ_FOREACH(wp, &c->session->curw->window->panes, entry) { 1321 if (wp->flags & PANE_REDRAW) { 1322 needed = 1; 1323 break; 1324 } 1325 } 1326 } 1327 if (needed && (left = EVBUFFER_LENGTH(tty->out)) != 0) { 1328 log_debug("%s: redraw deferred (%zu left)", c->name, left); 1329 if (!evtimer_initialized(&ev)) 1330 evtimer_set(&ev, server_client_redraw_timer, NULL); 1331 if (!evtimer_pending(&ev, NULL)) { 1332 log_debug("redraw timer started"); 1333 evtimer_add(&ev, &tv); 1334 } 1335 1336 /* 1337 * We may have got here for a single pane redraw, but force a 1338 * full redraw next time in case other panes have been updated. 1339 */ 1340 c->flags |= CLIENT_REDRAW; 1341 return; 1342 } else if (needed) 1343 log_debug("%s: redraw needed", c->name); 1344 1345 if (c->flags & (CLIENT_REDRAW|CLIENT_STATUS)) { 1346 if (options_get_number(s->options, "set-titles")) 1347 server_client_set_title(c); 1348 screen_redraw_update(c); /* will adjust flags */ 1349 } 1350 1351 flags = tty->flags & (TTY_BLOCK|TTY_FREEZE|TTY_NOCURSOR); 1352 tty->flags = (tty->flags & ~(TTY_BLOCK|TTY_FREEZE)) | TTY_NOCURSOR; 1353 1354 if (c->flags & CLIENT_REDRAW) { 1355 tty_update_mode(tty, tty->mode, NULL); 1356 screen_redraw_screen(c, 1, 1, 1); 1357 c->flags &= ~(CLIENT_STATUS|CLIENT_BORDERS); 1358 } else { 1359 TAILQ_FOREACH(wp, &c->session->curw->window->panes, entry) { 1360 if (wp->flags & PANE_REDRAW) { 1361 tty_update_mode(tty, tty->mode, NULL); 1362 screen_redraw_pane(c, wp); 1363 } 1364 } 1365 } 1366 1367 masked = c->flags & (CLIENT_BORDERS|CLIENT_STATUS); 1368 if (masked != 0) 1369 tty_update_mode(tty, tty->mode, NULL); 1370 if (masked == CLIENT_BORDERS) 1371 screen_redraw_screen(c, 0, 0, 1); 1372 else if (masked == CLIENT_STATUS) 1373 screen_redraw_screen(c, 0, 1, 0); 1374 else if (masked != 0) 1375 screen_redraw_screen(c, 0, 1, 1); 1376 1377 tty->flags = (tty->flags & ~(TTY_FREEZE|TTY_NOCURSOR)) | flags; 1378 tty_update_mode(tty, tty->mode, NULL); 1379 1380 c->flags &= ~(CLIENT_REDRAW|CLIENT_BORDERS|CLIENT_STATUS| 1381 CLIENT_STATUSFORCE); 1382 1383 if (needed) { 1384 /* 1385 * We would have deferred the redraw unless the output buffer 1386 * was empty, so we can record how many bytes the redraw 1387 * generated. 1388 */ 1389 c->redraw = EVBUFFER_LENGTH(tty->out); 1390 log_debug("%s: redraw added %zu bytes", c->name, c->redraw); 1391 } 1392 } 1393 1394 /* Set client title. */ 1395 static void 1396 server_client_set_title(struct client *c) 1397 { 1398 struct session *s = c->session; 1399 const char *template; 1400 char *title; 1401 struct format_tree *ft; 1402 1403 template = options_get_string(s->options, "set-titles-string"); 1404 1405 ft = format_create(c, NULL, FORMAT_NONE, 0); 1406 format_defaults(ft, c, NULL, NULL, NULL); 1407 1408 title = format_expand_time(ft, template, time(NULL)); 1409 if (c->title == NULL || strcmp(title, c->title) != 0) { 1410 free(c->title); 1411 c->title = xstrdup(title); 1412 tty_set_title(&c->tty, c->title); 1413 } 1414 free(title); 1415 1416 format_free(ft); 1417 } 1418 1419 /* Dispatch message from client. */ 1420 static void 1421 server_client_dispatch(struct imsg *imsg, void *arg) 1422 { 1423 struct client *c = arg; 1424 struct msg_stdin_data stdindata; 1425 const char *data; 1426 ssize_t datalen; 1427 struct session *s; 1428 1429 if (c->flags & CLIENT_DEAD) 1430 return; 1431 1432 if (imsg == NULL) { 1433 server_client_lost(c); 1434 return; 1435 } 1436 1437 data = imsg->data; 1438 datalen = imsg->hdr.len - IMSG_HEADER_SIZE; 1439 1440 switch (imsg->hdr.type) { 1441 case MSG_IDENTIFY_FLAGS: 1442 case MSG_IDENTIFY_TERM: 1443 case MSG_IDENTIFY_TTYNAME: 1444 case MSG_IDENTIFY_CWD: 1445 case MSG_IDENTIFY_STDIN: 1446 case MSG_IDENTIFY_ENVIRON: 1447 case MSG_IDENTIFY_CLIENTPID: 1448 case MSG_IDENTIFY_DONE: 1449 server_client_dispatch_identify(c, imsg); 1450 break; 1451 case MSG_COMMAND: 1452 server_client_dispatch_command(c, imsg); 1453 break; 1454 case MSG_STDIN: 1455 if (datalen != sizeof stdindata) 1456 fatalx("bad MSG_STDIN size"); 1457 memcpy(&stdindata, data, sizeof stdindata); 1458 1459 if (c->stdin_callback == NULL) 1460 break; 1461 if (stdindata.size <= 0) 1462 c->stdin_closed = 1; 1463 else { 1464 evbuffer_add(c->stdin_data, stdindata.data, 1465 stdindata.size); 1466 } 1467 c->stdin_callback(c, c->stdin_closed, 1468 c->stdin_callback_data); 1469 break; 1470 case MSG_RESIZE: 1471 if (datalen != 0) 1472 fatalx("bad MSG_RESIZE size"); 1473 1474 if (c->flags & CLIENT_CONTROL) 1475 break; 1476 tty_resize(&c->tty); 1477 recalculate_sizes(); 1478 server_redraw_client(c); 1479 if (c->session != NULL) 1480 notify_client("client-resized", c); 1481 break; 1482 case MSG_EXITING: 1483 if (datalen != 0) 1484 fatalx("bad MSG_EXITING size"); 1485 1486 c->session = NULL; 1487 tty_close(&c->tty); 1488 proc_send(c->peer, MSG_EXITED, -1, NULL, 0); 1489 break; 1490 case MSG_WAKEUP: 1491 case MSG_UNLOCK: 1492 if (datalen != 0) 1493 fatalx("bad MSG_WAKEUP size"); 1494 1495 if (!(c->flags & CLIENT_SUSPENDED)) 1496 break; 1497 c->flags &= ~CLIENT_SUSPENDED; 1498 1499 if (c->tty.fd == -1) /* exited in the meantime */ 1500 break; 1501 s = c->session; 1502 1503 if (gettimeofday(&c->activity_time, NULL) != 0) 1504 fatal("gettimeofday failed"); 1505 1506 tty_start_tty(&c->tty); 1507 server_redraw_client(c); 1508 recalculate_sizes(); 1509 1510 if (s != NULL) 1511 session_update_activity(s, &c->activity_time); 1512 break; 1513 case MSG_SHELL: 1514 if (datalen != 0) 1515 fatalx("bad MSG_SHELL size"); 1516 1517 server_client_dispatch_shell(c); 1518 break; 1519 } 1520 } 1521 1522 /* Callback when command is done. */ 1523 static enum cmd_retval 1524 server_client_command_done(struct cmdq_item *item, __unused void *data) 1525 { 1526 struct client *c = item->client; 1527 1528 if (~c->flags & CLIENT_ATTACHED) 1529 c->flags |= CLIENT_EXIT; 1530 return (CMD_RETURN_NORMAL); 1531 } 1532 1533 /* Show an error message. */ 1534 static enum cmd_retval 1535 server_client_command_error(struct cmdq_item *item, void *data) 1536 { 1537 char *error = data; 1538 1539 cmdq_error(item, "%s", error); 1540 free(error); 1541 1542 return (CMD_RETURN_NORMAL); 1543 } 1544 1545 /* Handle command message. */ 1546 static void 1547 server_client_dispatch_command(struct client *c, struct imsg *imsg) 1548 { 1549 struct msg_command_data data; 1550 char *buf; 1551 size_t len; 1552 struct cmd_list *cmdlist = NULL; 1553 int argc; 1554 char **argv, *cause; 1555 1556 if (c->flags & CLIENT_EXIT) 1557 return; 1558 1559 if (imsg->hdr.len - IMSG_HEADER_SIZE < sizeof data) 1560 fatalx("bad MSG_COMMAND size"); 1561 memcpy(&data, imsg->data, sizeof data); 1562 1563 buf = (char *)imsg->data + sizeof data; 1564 len = imsg->hdr.len - IMSG_HEADER_SIZE - sizeof data; 1565 if (len > 0 && buf[len - 1] != '\0') 1566 fatalx("bad MSG_COMMAND string"); 1567 1568 argc = data.argc; 1569 if (cmd_unpack_argv(buf, len, argc, &argv) != 0) { 1570 cause = xstrdup("command too long"); 1571 goto error; 1572 } 1573 1574 if (argc == 0) { 1575 argc = 1; 1576 argv = xcalloc(1, sizeof *argv); 1577 *argv = xstrdup("new-session"); 1578 } 1579 1580 if ((cmdlist = cmd_list_parse(argc, argv, NULL, 0, &cause)) == NULL) { 1581 cmd_free_argv(argc, argv); 1582 goto error; 1583 } 1584 cmd_free_argv(argc, argv); 1585 1586 cmdq_append(c, cmdq_get_command(cmdlist, NULL, NULL, 0)); 1587 cmdq_append(c, cmdq_get_callback(server_client_command_done, NULL)); 1588 cmd_list_free(cmdlist); 1589 return; 1590 1591 error: 1592 cmdq_append(c, cmdq_get_callback(server_client_command_error, cause)); 1593 1594 if (cmdlist != NULL) 1595 cmd_list_free(cmdlist); 1596 1597 c->flags |= CLIENT_EXIT; 1598 } 1599 1600 /* Handle identify message. */ 1601 static void 1602 server_client_dispatch_identify(struct client *c, struct imsg *imsg) 1603 { 1604 const char *data, *home; 1605 size_t datalen; 1606 int flags; 1607 char *name; 1608 1609 if (c->flags & CLIENT_IDENTIFIED) 1610 fatalx("out-of-order identify message"); 1611 1612 data = imsg->data; 1613 datalen = imsg->hdr.len - IMSG_HEADER_SIZE; 1614 1615 switch (imsg->hdr.type) { 1616 case MSG_IDENTIFY_FLAGS: 1617 if (datalen != sizeof flags) 1618 fatalx("bad MSG_IDENTIFY_FLAGS size"); 1619 memcpy(&flags, data, sizeof flags); 1620 c->flags |= flags; 1621 log_debug("client %p IDENTIFY_FLAGS %#x", c, flags); 1622 break; 1623 case MSG_IDENTIFY_TERM: 1624 if (datalen == 0 || data[datalen - 1] != '\0') 1625 fatalx("bad MSG_IDENTIFY_TERM string"); 1626 c->term = xstrdup(data); 1627 log_debug("client %p IDENTIFY_TERM %s", c, data); 1628 break; 1629 case MSG_IDENTIFY_TTYNAME: 1630 if (datalen == 0 || data[datalen - 1] != '\0') 1631 fatalx("bad MSG_IDENTIFY_TTYNAME string"); 1632 c->ttyname = xstrdup(data); 1633 log_debug("client %p IDENTIFY_TTYNAME %s", c, data); 1634 break; 1635 case MSG_IDENTIFY_CWD: 1636 if (datalen == 0 || data[datalen - 1] != '\0') 1637 fatalx("bad MSG_IDENTIFY_CWD string"); 1638 if (access(data, X_OK) == 0) 1639 c->cwd = xstrdup(data); 1640 else if ((home = find_home()) != NULL) 1641 c->cwd = xstrdup(home); 1642 else 1643 c->cwd = xstrdup("/"); 1644 log_debug("client %p IDENTIFY_CWD %s", c, data); 1645 break; 1646 case MSG_IDENTIFY_STDIN: 1647 if (datalen != 0) 1648 fatalx("bad MSG_IDENTIFY_STDIN size"); 1649 c->fd = imsg->fd; 1650 log_debug("client %p IDENTIFY_STDIN %d", c, imsg->fd); 1651 break; 1652 case MSG_IDENTIFY_ENVIRON: 1653 if (datalen == 0 || data[datalen - 1] != '\0') 1654 fatalx("bad MSG_IDENTIFY_ENVIRON string"); 1655 if (strchr(data, '=') != NULL) 1656 environ_put(c->environ, data); 1657 log_debug("client %p IDENTIFY_ENVIRON %s", c, data); 1658 break; 1659 case MSG_IDENTIFY_CLIENTPID: 1660 if (datalen != sizeof c->pid) 1661 fatalx("bad MSG_IDENTIFY_CLIENTPID size"); 1662 memcpy(&c->pid, data, sizeof c->pid); 1663 log_debug("client %p IDENTIFY_CLIENTPID %ld", c, (long)c->pid); 1664 break; 1665 default: 1666 break; 1667 } 1668 1669 if (imsg->hdr.type != MSG_IDENTIFY_DONE) 1670 return; 1671 c->flags |= CLIENT_IDENTIFIED; 1672 1673 if (*c->ttyname != '\0') 1674 name = xstrdup(c->ttyname); 1675 else 1676 xasprintf(&name, "client-%ld", (long)c->pid); 1677 c->name = name; 1678 log_debug("client %p name is %s", c, c->name); 1679 1680 if (c->flags & CLIENT_CONTROL) { 1681 c->stdin_callback = control_callback; 1682 1683 evbuffer_free(c->stderr_data); 1684 c->stderr_data = c->stdout_data; 1685 1686 if (c->flags & CLIENT_CONTROLCONTROL) 1687 evbuffer_add_printf(c->stdout_data, "\033P1000p"); 1688 proc_send(c->peer, MSG_STDIN, -1, NULL, 0); 1689 1690 c->tty.fd = -1; 1691 1692 close(c->fd); 1693 c->fd = -1; 1694 1695 return; 1696 } 1697 1698 if (c->fd == -1) 1699 return; 1700 if (tty_init(&c->tty, c, c->fd, c->term) != 0) { 1701 close(c->fd); 1702 c->fd = -1; 1703 return; 1704 } 1705 if (c->flags & CLIENT_UTF8) 1706 c->tty.flags |= TTY_UTF8; 1707 if (c->flags & CLIENT_256COLOURS) 1708 c->tty.term_flags |= TERM_256COLOURS; 1709 1710 tty_resize(&c->tty); 1711 1712 if (!(c->flags & CLIENT_CONTROL)) 1713 c->flags |= CLIENT_TERMINAL; 1714 } 1715 1716 /* Handle shell message. */ 1717 static void 1718 server_client_dispatch_shell(struct client *c) 1719 { 1720 const char *shell; 1721 1722 shell = options_get_string(global_s_options, "default-shell"); 1723 if (*shell == '\0' || areshell(shell)) 1724 shell = _PATH_BSHELL; 1725 proc_send(c->peer, MSG_SHELL, -1, shell, strlen(shell) + 1); 1726 1727 proc_kill_peer(c->peer); 1728 } 1729 1730 /* Event callback to push more stdout data if any left. */ 1731 static void 1732 server_client_stdout_cb(__unused int fd, __unused short events, void *arg) 1733 { 1734 struct client *c = arg; 1735 1736 if (~c->flags & CLIENT_DEAD) 1737 server_client_push_stdout(c); 1738 server_client_unref(c); 1739 } 1740 1741 /* Push stdout to client if possible. */ 1742 void 1743 server_client_push_stdout(struct client *c) 1744 { 1745 struct msg_stdout_data data; 1746 size_t sent, left; 1747 1748 left = EVBUFFER_LENGTH(c->stdout_data); 1749 while (left != 0) { 1750 sent = left; 1751 if (sent > sizeof data.data) 1752 sent = sizeof data.data; 1753 memcpy(data.data, EVBUFFER_DATA(c->stdout_data), sent); 1754 data.size = sent; 1755 1756 if (proc_send(c->peer, MSG_STDOUT, -1, &data, sizeof data) != 0) 1757 break; 1758 evbuffer_drain(c->stdout_data, sent); 1759 1760 left = EVBUFFER_LENGTH(c->stdout_data); 1761 log_debug("%s: client %p, sent %zu, left %zu", __func__, c, 1762 sent, left); 1763 } 1764 if (left != 0) { 1765 c->references++; 1766 event_once(-1, EV_TIMEOUT, server_client_stdout_cb, c, NULL); 1767 log_debug("%s: client %p, queued", __func__, c); 1768 } 1769 } 1770 1771 /* Event callback to push more stderr data if any left. */ 1772 static void 1773 server_client_stderr_cb(__unused int fd, __unused short events, void *arg) 1774 { 1775 struct client *c = arg; 1776 1777 if (~c->flags & CLIENT_DEAD) 1778 server_client_push_stderr(c); 1779 server_client_unref(c); 1780 } 1781 1782 /* Push stderr to client if possible. */ 1783 void 1784 server_client_push_stderr(struct client *c) 1785 { 1786 struct msg_stderr_data data; 1787 size_t sent, left; 1788 1789 if (c->stderr_data == c->stdout_data) { 1790 server_client_push_stdout(c); 1791 return; 1792 } 1793 1794 left = EVBUFFER_LENGTH(c->stderr_data); 1795 while (left != 0) { 1796 sent = left; 1797 if (sent > sizeof data.data) 1798 sent = sizeof data.data; 1799 memcpy(data.data, EVBUFFER_DATA(c->stderr_data), sent); 1800 data.size = sent; 1801 1802 if (proc_send(c->peer, MSG_STDERR, -1, &data, sizeof data) != 0) 1803 break; 1804 evbuffer_drain(c->stderr_data, sent); 1805 1806 left = EVBUFFER_LENGTH(c->stderr_data); 1807 log_debug("%s: client %p, sent %zu, left %zu", __func__, c, 1808 sent, left); 1809 } 1810 if (left != 0) { 1811 c->references++; 1812 event_once(-1, EV_TIMEOUT, server_client_stderr_cb, c, NULL); 1813 log_debug("%s: client %p, queued", __func__, c); 1814 } 1815 } 1816 1817 /* Add to client message log. */ 1818 void 1819 server_client_add_message(struct client *c, const char *fmt, ...) 1820 { 1821 struct message_entry *msg, *msg1; 1822 char *s; 1823 va_list ap; 1824 u_int limit; 1825 1826 va_start(ap, fmt); 1827 xvasprintf(&s, fmt, ap); 1828 va_end(ap); 1829 1830 log_debug("message %s (client %p)", s, c); 1831 1832 msg = xcalloc(1, sizeof *msg); 1833 msg->msg_time = time(NULL); 1834 msg->msg_num = c->message_next++; 1835 msg->msg = s; 1836 TAILQ_INSERT_TAIL(&c->message_log, msg, entry); 1837 1838 limit = options_get_number(global_options, "message-limit"); 1839 TAILQ_FOREACH_SAFE(msg, &c->message_log, entry, msg1) { 1840 if (msg->msg_num + limit >= c->message_next) 1841 break; 1842 free(msg->msg); 1843 TAILQ_REMOVE(&c->message_log, msg, entry); 1844 free(msg); 1845 } 1846 } 1847 1848 /* Get client working directory. */ 1849 const char * 1850 server_client_get_cwd(struct client *c, struct session *s) 1851 { 1852 const char *home; 1853 1854 if (c != NULL && c->session == NULL && c->cwd != NULL) 1855 return (c->cwd); 1856 if (s != NULL && s->cwd != NULL) 1857 return (s->cwd); 1858 if (c != NULL && (s = c->session) != NULL && s->cwd != NULL) 1859 return (s->cwd); 1860 if ((home = find_home()) != NULL) 1861 return (home); 1862 return ("/"); 1863 } 1864 1865 /* Resolve an absolute path or relative to client working directory. */ 1866 char * 1867 server_client_get_path(struct client *c, const char *file) 1868 { 1869 char *path, resolved[PATH_MAX]; 1870 1871 if (*file == '/') 1872 path = xstrdup(file); 1873 else 1874 xasprintf(&path, "%s/%s", server_client_get_cwd(c, NULL), file); 1875 if (realpath(path, resolved) == NULL) 1876 return (path); 1877 free(path); 1878 return (xstrdup(resolved)); 1879 } 1880