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