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