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