1 /* $OpenBSD: server-client.c,v 1.142 2015/06/05 18:06:30 nicm Exp $ */ 2 3 /* 4 * Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net> 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 22 #include <errno.h> 23 #include <event.h> 24 #include <fcntl.h> 25 #include <paths.h> 26 #include <stdlib.h> 27 #include <string.h> 28 #include <time.h> 29 #include <unistd.h> 30 31 #include "tmux.h" 32 33 void server_client_key_table(struct client *, const char *); 34 void server_client_free(int, short, void *); 35 void server_client_check_focus(struct window_pane *); 36 void server_client_check_resize(struct window_pane *); 37 int server_client_check_mouse(struct client *); 38 void server_client_repeat_timer(int, short, void *); 39 void server_client_check_exit(struct client *); 40 void server_client_check_redraw(struct client *); 41 void server_client_set_title(struct client *); 42 void server_client_reset_state(struct client *); 43 int server_client_assume_paste(struct session *); 44 45 int server_client_msg_dispatch(struct client *); 46 void server_client_msg_command(struct client *, struct imsg *); 47 void server_client_msg_identify(struct client *, struct imsg *); 48 void server_client_msg_shell(struct client *); 49 50 /* Check if this client is inside this server. */ 51 int 52 server_client_check_nested(struct client *c) 53 { 54 struct environ_entry *envent; 55 struct window_pane *wp; 56 57 if (c->tty.path == NULL) 58 return (0); 59 60 envent = environ_find(&c->environ, "TMUX"); 61 if (envent == NULL || *envent->value == '\0') 62 return (0); 63 64 RB_FOREACH(wp, window_pane_tree, &all_window_panes) { 65 if (strcmp(wp->tty, c->tty.path) == 0) 66 return (1); 67 } 68 return (0); 69 } 70 71 /* Set client key table. */ 72 void 73 server_client_key_table(struct client *c, const char *name) 74 { 75 key_bindings_unref_table(c->keytable); 76 c->keytable = key_bindings_get_table(name, 1); 77 c->keytable->references++; 78 } 79 80 /* Create a new client. */ 81 void 82 server_client_create(int fd) 83 { 84 struct client *c; 85 86 setblocking(fd, 0); 87 88 c = xcalloc(1, sizeof *c); 89 c->references = 1; 90 imsg_init(&c->ibuf, fd); 91 server_update_event(c); 92 93 if (gettimeofday(&c->creation_time, NULL) != 0) 94 fatal("gettimeofday failed"); 95 memcpy(&c->activity_time, &c->creation_time, sizeof c->activity_time); 96 97 environ_init(&c->environ); 98 99 c->cmdq = cmdq_new(c); 100 c->cmdq->client_exit = 1; 101 102 c->stdin_data = evbuffer_new(); 103 c->stdout_data = evbuffer_new(); 104 c->stderr_data = evbuffer_new(); 105 106 c->tty.fd = -1; 107 c->title = NULL; 108 109 c->session = NULL; 110 c->last_session = NULL; 111 c->tty.sx = 80; 112 c->tty.sy = 24; 113 114 screen_init(&c->status, c->tty.sx, 1, 0); 115 RB_INIT(&c->status_new); 116 RB_INIT(&c->status_old); 117 118 c->message_string = NULL; 119 TAILQ_INIT(&c->message_log); 120 121 c->prompt_string = NULL; 122 c->prompt_buffer = NULL; 123 c->prompt_index = 0; 124 125 c->flags |= CLIENT_FOCUSED; 126 127 c->keytable = key_bindings_get_table("root", 1); 128 c->keytable->references++; 129 130 evtimer_set(&c->repeat_timer, server_client_repeat_timer, c); 131 132 TAILQ_INSERT_TAIL(&clients, c, entry); 133 log_debug("new client %d", fd); 134 } 135 136 /* Open client terminal if needed. */ 137 int 138 server_client_open(struct client *c, char **cause) 139 { 140 if (c->flags & CLIENT_CONTROL) 141 return (0); 142 143 if (strcmp(c->ttyname, "/dev/tty") == 0) { 144 *cause = xstrdup("can't use /dev/tty"); 145 return (-1); 146 } 147 148 if (!(c->flags & CLIENT_TERMINAL)) { 149 *cause = xstrdup("not a terminal"); 150 return (-1); 151 } 152 153 if (tty_open(&c->tty, cause) != 0) 154 return (-1); 155 156 return (0); 157 } 158 159 /* Lost a client. */ 160 void 161 server_client_lost(struct client *c) 162 { 163 struct message_entry *msg, *msg1; 164 165 c->flags |= CLIENT_DEAD; 166 167 status_prompt_clear(c); 168 status_message_clear(c); 169 170 if (c->stdin_callback != NULL) 171 c->stdin_callback(c, 1, c->stdin_callback_data); 172 173 TAILQ_REMOVE(&clients, c, entry); 174 log_debug("lost client %d", c->ibuf.fd); 175 176 /* 177 * If CLIENT_TERMINAL hasn't been set, then tty_init hasn't been called 178 * and tty_free might close an unrelated fd. 179 */ 180 if (c->flags & CLIENT_TERMINAL) 181 tty_free(&c->tty); 182 free(c->ttyname); 183 free(c->term); 184 185 evbuffer_free(c->stdin_data); 186 evbuffer_free(c->stdout_data); 187 if (c->stderr_data != c->stdout_data) 188 evbuffer_free(c->stderr_data); 189 190 screen_free(&c->status); 191 192 free(c->title); 193 close(c->cwd); 194 195 evtimer_del(&c->repeat_timer); 196 197 key_bindings_unref_table(c->keytable); 198 199 if (event_initialized(&c->identify_timer)) 200 evtimer_del(&c->identify_timer); 201 202 free(c->message_string); 203 if (event_initialized(&c->message_timer)) 204 evtimer_del(&c->message_timer); 205 TAILQ_FOREACH_SAFE(msg, &c->message_log, entry, msg1) { 206 free(msg->msg); 207 TAILQ_REMOVE(&c->message_log, msg, entry); 208 free(msg); 209 } 210 211 free(c->prompt_string); 212 free(c->prompt_buffer); 213 214 c->cmdq->dead = 1; 215 cmdq_free(c->cmdq); 216 c->cmdq = NULL; 217 218 environ_free(&c->environ); 219 220 close(c->ibuf.fd); 221 imsg_clear(&c->ibuf); 222 if (event_initialized(&c->event)) 223 event_del(&c->event); 224 225 server_client_unref(c); 226 227 server_add_accept(0); /* may be more file descriptors now */ 228 229 recalculate_sizes(); 230 server_check_unattached(); 231 server_update_socket(); 232 } 233 234 /* Remove reference from a client. */ 235 void 236 server_client_unref(struct client *c) 237 { 238 log_debug("unref client %d (%d references)", c->ibuf.fd, c->references); 239 240 c->references--; 241 if (c->references == 0) 242 event_once(-1, EV_TIMEOUT, server_client_free, c, NULL); 243 } 244 245 /* Free dead client. */ 246 void 247 server_client_free(unused int fd, unused short events, void *arg) 248 { 249 struct client *c = arg; 250 251 log_debug("free client %d (%d references)", c->ibuf.fd, c->references); 252 253 if (c->references == 0) 254 free(c); 255 } 256 257 /* Process a single client event. */ 258 void 259 server_client_callback(int fd, short events, void *data) 260 { 261 struct client *c = data; 262 263 if (c->flags & CLIENT_DEAD) 264 return; 265 266 if (fd == c->ibuf.fd) { 267 if (events & EV_WRITE && msgbuf_write(&c->ibuf.w) <= 0 && 268 errno != EAGAIN) 269 goto client_lost; 270 271 if (c->flags & CLIENT_BAD) { 272 if (c->ibuf.w.queued == 0) 273 goto client_lost; 274 return; 275 } 276 277 if (events & EV_READ && server_client_msg_dispatch(c) != 0) 278 goto client_lost; 279 } 280 281 server_push_stdout(c); 282 server_push_stderr(c); 283 284 server_update_event(c); 285 return; 286 287 client_lost: 288 server_client_lost(c); 289 } 290 291 /* Handle client status timer. */ 292 void 293 server_client_status_timer(void) 294 { 295 struct client *c; 296 struct session *s; 297 struct timeval tv; 298 int interval; 299 time_t difference; 300 301 if (gettimeofday(&tv, NULL) != 0) 302 fatal("gettimeofday failed"); 303 304 TAILQ_FOREACH(c, &clients, entry) { 305 if (c->session == NULL) 306 continue; 307 if (c->message_string != NULL || c->prompt_string != NULL) { 308 /* 309 * Don't need timed redraw for messages/prompts so bail 310 * now. The status timer isn't reset when they are 311 * redrawn anyway. 312 */ 313 continue; 314 } 315 s = c->session; 316 317 if (!options_get_number(&s->options, "status")) 318 continue; 319 interval = options_get_number(&s->options, "status-interval"); 320 321 difference = tv.tv_sec - c->status_timer.tv_sec; 322 if (interval != 0 && difference >= interval) 323 c->flags |= CLIENT_STATUS; 324 } 325 } 326 327 /* Check for mouse keys. */ 328 int 329 server_client_check_mouse(struct client *c) 330 { 331 struct session *s = c->session; 332 struct mouse_event *m = &c->tty.mouse; 333 struct window *w; 334 struct window_pane *wp; 335 enum { NOTYPE, DOWN, UP, DRAG, WHEEL } type = NOTYPE; 336 enum { NOWHERE, PANE, STATUS, BORDER } where = NOWHERE; 337 u_int x, y, b; 338 int key; 339 340 log_debug("mouse %02x at %u,%u (last %u,%u) (%d)", m->b, m->x, m->y, 341 m->lx, m->ly, c->tty.mouse_drag_flag); 342 343 /* What type of event is this? */ 344 if (MOUSE_DRAG(m->b)) { 345 type = DRAG; 346 if (c->tty.mouse_drag_flag) { 347 x = m->x, y = m->y, b = m->b; 348 log_debug("drag update at %u,%u", x, y); 349 } else { 350 x = m->lx, y = m->ly, b = m->lb; 351 log_debug("drag start at %u,%u", x, y); 352 } 353 } else if (MOUSE_WHEEL(m->b)) { 354 type = WHEEL; 355 x = m->x, y = m->y, b = m->b; 356 log_debug("wheel at %u,%u", x, y); 357 } else if (MOUSE_BUTTONS(m->b) == 3) { 358 type = UP; 359 x = m->x, y = m->y, b = m->lb; 360 log_debug("up at %u,%u", x, y); 361 } else { 362 type = DOWN; 363 x = m->x, y = m->y, b = m->b; 364 log_debug("down at %u,%u", x, y); 365 } 366 if (type == NOTYPE) 367 return (KEYC_NONE); 368 369 /* Always save the session. */ 370 m->s = s->id; 371 372 /* Is this on the status line? */ 373 m->statusat = status_at_line(c); 374 if (m->statusat != -1 && y == (u_int)m->statusat) { 375 w = status_get_window_at(c, x); 376 if (w == NULL) 377 return (KEYC_NONE); 378 m->w = w->id; 379 where = STATUS; 380 } else 381 m->w = -1; 382 383 /* Not on status line. Adjust position and check for border or pane. */ 384 if (where == NOWHERE) { 385 if (m->statusat == 0 && y > 0) 386 y--; 387 else if (m->statusat > 0 && y >= (u_int)m->statusat) 388 y = m->statusat - 1; 389 390 TAILQ_FOREACH(wp, &s->curw->window->panes, entry) { 391 if ((wp->xoff + wp->sx == x && 392 wp->yoff <= 1 + y && 393 wp->yoff + wp->sy >= y) || 394 (wp->yoff + wp->sy == y && 395 wp->xoff <= 1 + x && 396 wp->xoff + wp->sx >= x)) 397 break; 398 } 399 if (wp != NULL) 400 where = BORDER; 401 else { 402 wp = window_get_active_at(s->curw->window, x, y); 403 if (wp != NULL) 404 where = PANE; 405 } 406 if (where == NOWHERE) 407 return (KEYC_NONE); 408 m->wp = wp->id; 409 m->w = wp->window->id; 410 } else 411 m->wp = -1; 412 413 /* Stop dragging if needed. */ 414 if (type != DRAG && c->tty.mouse_drag_flag) { 415 if (c->tty.mouse_drag_release != NULL) 416 c->tty.mouse_drag_release(c, m); 417 418 c->tty.mouse_drag_update = NULL; 419 c->tty.mouse_drag_release = NULL; 420 421 c->tty.mouse_drag_flag = 0; 422 return (KEYC_MOUSE); /* not a key, but still may want to pass */ 423 } 424 425 /* Convert to a key binding. */ 426 key = KEYC_NONE; 427 switch (type) { 428 case NOTYPE: 429 break; 430 case DRAG: 431 if (c->tty.mouse_drag_update != NULL) 432 c->tty.mouse_drag_update(c, m); 433 else { 434 switch (MOUSE_BUTTONS(b)) { 435 case 0: 436 if (where == PANE) 437 key = KEYC_MOUSEDRAG1_PANE; 438 if (where == STATUS) 439 key = KEYC_MOUSEDRAG1_STATUS; 440 if (where == BORDER) 441 key = KEYC_MOUSEDRAG1_BORDER; 442 break; 443 case 1: 444 if (where == PANE) 445 key = KEYC_MOUSEDRAG2_PANE; 446 if (where == STATUS) 447 key = KEYC_MOUSEDRAG2_STATUS; 448 if (where == BORDER) 449 key = KEYC_MOUSEDRAG2_BORDER; 450 break; 451 case 2: 452 if (where == PANE) 453 key = KEYC_MOUSEDRAG3_PANE; 454 if (where == STATUS) 455 key = KEYC_MOUSEDRAG3_STATUS; 456 if (where == BORDER) 457 key = KEYC_MOUSEDRAG3_BORDER; 458 break; 459 } 460 } 461 462 c->tty.mouse_drag_flag = 1; 463 break; 464 case WHEEL: 465 if (MOUSE_BUTTONS(b) == MOUSE_WHEEL_UP) { 466 if (where == PANE) 467 key = KEYC_WHEELUP_PANE; 468 if (where == STATUS) 469 key = KEYC_WHEELUP_STATUS; 470 if (where == BORDER) 471 key = KEYC_WHEELUP_BORDER; 472 } else { 473 if (where == PANE) 474 key = KEYC_WHEELDOWN_PANE; 475 if (where == STATUS) 476 key = KEYC_WHEELDOWN_STATUS; 477 if (where == BORDER) 478 key = KEYC_WHEELDOWN_BORDER; 479 } 480 break; 481 case UP: 482 switch (MOUSE_BUTTONS(b)) { 483 case 0: 484 if (where == PANE) 485 key = KEYC_MOUSEUP1_PANE; 486 if (where == STATUS) 487 key = KEYC_MOUSEUP1_STATUS; 488 if (where == BORDER) 489 key = KEYC_MOUSEUP1_BORDER; 490 break; 491 case 1: 492 if (where == PANE) 493 key = KEYC_MOUSEUP2_PANE; 494 if (where == STATUS) 495 key = KEYC_MOUSEUP2_STATUS; 496 if (where == BORDER) 497 key = KEYC_MOUSEUP2_BORDER; 498 break; 499 case 2: 500 if (where == PANE) 501 key = KEYC_MOUSEUP3_PANE; 502 if (where == STATUS) 503 key = KEYC_MOUSEUP3_STATUS; 504 if (where == BORDER) 505 key = KEYC_MOUSEUP3_BORDER; 506 break; 507 } 508 break; 509 case DOWN: 510 switch (MOUSE_BUTTONS(b)) { 511 case 0: 512 if (where == PANE) 513 key = KEYC_MOUSEDOWN1_PANE; 514 if (where == STATUS) 515 key = KEYC_MOUSEDOWN1_STATUS; 516 if (where == BORDER) 517 key = KEYC_MOUSEDOWN1_BORDER; 518 break; 519 case 1: 520 if (where == PANE) 521 key = KEYC_MOUSEDOWN2_PANE; 522 if (where == STATUS) 523 key = KEYC_MOUSEDOWN2_STATUS; 524 if (where == BORDER) 525 key = KEYC_MOUSEDOWN2_BORDER; 526 break; 527 case 2: 528 if (where == PANE) 529 key = KEYC_MOUSEDOWN3_PANE; 530 if (where == STATUS) 531 key = KEYC_MOUSEDOWN3_STATUS; 532 if (where == BORDER) 533 key = KEYC_MOUSEDOWN3_BORDER; 534 break; 535 } 536 break; 537 } 538 if (key == KEYC_NONE) 539 return (KEYC_NONE); 540 541 /* Apply modifiers if any. */ 542 if (b & MOUSE_MASK_META) 543 key |= KEYC_ESCAPE; 544 if (b & MOUSE_MASK_CTRL) 545 key |= KEYC_CTRL; 546 if (b & MOUSE_MASK_SHIFT) 547 key |= KEYC_SHIFT; 548 549 return (key); 550 } 551 552 /* Is this fast enough to probably be a paste? */ 553 int 554 server_client_assume_paste(struct session *s) 555 { 556 struct timeval tv; 557 int t; 558 559 if ((t = options_get_number(&s->options, "assume-paste-time")) == 0) 560 return (0); 561 562 timersub(&s->activity_time, &s->last_activity_time, &tv); 563 if (tv.tv_sec == 0 && tv.tv_usec < t * 1000) 564 return (1); 565 return (0); 566 } 567 568 /* Handle data key input from client. */ 569 void 570 server_client_handle_key(struct client *c, int key) 571 { 572 struct mouse_event *m = &c->tty.mouse; 573 struct session *s = c->session; 574 struct window *w; 575 struct window_pane *wp; 576 struct timeval tv; 577 struct key_table *table = c->keytable; 578 struct key_binding bd_find, *bd; 579 int xtimeout; 580 581 /* Check the client is good to accept input. */ 582 if (s == NULL || (c->flags & (CLIENT_DEAD|CLIENT_SUSPENDED)) != 0) 583 return; 584 w = s->curw->window; 585 wp = w->active; 586 587 /* No session, do nothing. */ 588 if (c->session == NULL) 589 return; 590 s = c->session; 591 w = c->session->curw->window; 592 wp = w->active; 593 594 /* Update the activity timer. */ 595 if (gettimeofday(&c->activity_time, NULL) != 0) 596 fatal("gettimeofday failed"); 597 memcpy(&s->last_activity_time, &s->activity_time, 598 sizeof s->last_activity_time); 599 memcpy(&s->activity_time, &c->activity_time, sizeof s->activity_time); 600 601 /* Number keys jump to pane in identify mode. */ 602 if (c->flags & CLIENT_IDENTIFY && key >= '0' && key <= '9') { 603 if (c->flags & CLIENT_READONLY) 604 return; 605 window_unzoom(w); 606 wp = window_pane_at_index(w, key - '0'); 607 if (wp != NULL && window_pane_visible(wp)) 608 window_set_active_pane(w, wp); 609 server_clear_identify(c); 610 return; 611 } 612 613 /* Handle status line. */ 614 if (!(c->flags & CLIENT_READONLY)) { 615 status_message_clear(c); 616 server_clear_identify(c); 617 } 618 if (c->prompt_string != NULL) { 619 if (!(c->flags & CLIENT_READONLY)) 620 status_prompt_key(c, key); 621 return; 622 } 623 624 /* Check for mouse keys. */ 625 if (key == KEYC_MOUSE) { 626 if (c->flags & CLIENT_READONLY) 627 return; 628 key = server_client_check_mouse(c); 629 if (key == KEYC_NONE) 630 return; 631 632 m->valid = 1; 633 m->key = key; 634 635 if (!options_get_number(&s->options, "mouse")) { 636 window_pane_key(wp, c, s, key, m); 637 return; 638 } 639 } else 640 m->valid = 0; 641 642 /* Treat everything as a regular key when pasting is detected. */ 643 if (server_client_assume_paste(s)) { 644 if (!(c->flags & CLIENT_READONLY)) 645 window_pane_key(wp, c, s, key, m); 646 return; 647 } 648 649 retry: 650 /* Try to see if there is a key binding in the current table. */ 651 bd_find.key = key; 652 bd = RB_FIND(key_bindings, &table->key_bindings, &bd_find); 653 if (bd != NULL) { 654 /* 655 * Key was matched in this table. If currently repeating but a 656 * non-repeating binding was found, stop repeating and try 657 * again in the root table. 658 */ 659 if ((c->flags & CLIENT_REPEAT) && !bd->can_repeat) { 660 server_client_key_table(c, "root"); 661 c->flags &= ~CLIENT_REPEAT; 662 server_status_client(c); 663 goto retry; 664 } 665 666 /* 667 * Take a reference to this table to make sure the key binding 668 * doesn't disappear. 669 */ 670 table->references++; 671 672 /* 673 * If this is a repeating key, start the timer. Otherwise reset 674 * the client back to the root table. 675 */ 676 xtimeout = options_get_number(&s->options, "repeat-time"); 677 if (xtimeout != 0 && bd->can_repeat) { 678 c->flags |= CLIENT_REPEAT; 679 680 tv.tv_sec = xtimeout / 1000; 681 tv.tv_usec = (xtimeout % 1000) * 1000L; 682 evtimer_del(&c->repeat_timer); 683 evtimer_add(&c->repeat_timer, &tv); 684 } else { 685 c->flags &= ~CLIENT_REPEAT; 686 server_client_key_table(c, "root"); 687 } 688 server_status_client(c); 689 690 /* Dispatch the key binding. */ 691 key_bindings_dispatch(bd, c, m); 692 key_bindings_unref_table(table); 693 return; 694 } 695 696 /* 697 * No match in this table. If repeating, switch the client back to the 698 * root table and try again. 699 */ 700 if (c->flags & CLIENT_REPEAT) { 701 server_client_key_table(c, "root"); 702 c->flags &= ~CLIENT_REPEAT; 703 server_status_client(c); 704 goto retry; 705 } 706 707 /* If no match and we're not in the root table, that's it. */ 708 if (strcmp(c->keytable->name, "root") != 0) { 709 server_client_key_table(c, "root"); 710 server_status_client(c); 711 return; 712 } 713 714 /* 715 * No match, but in the root table. Prefix switches to the prefix table 716 * and everything else is passed through. 717 */ 718 if (key == options_get_number(&s->options, "prefix") || 719 key == options_get_number(&s->options, "prefix2")) { 720 server_client_key_table(c, "prefix"); 721 server_status_client(c); 722 } else if (!(c->flags & CLIENT_READONLY)) 723 window_pane_key(wp, c, s, key, m); 724 } 725 726 /* Client functions that need to happen every loop. */ 727 void 728 server_client_loop(void) 729 { 730 struct client *c; 731 struct window *w; 732 struct window_pane *wp; 733 734 TAILQ_FOREACH(c, &clients, entry) { 735 server_client_check_exit(c); 736 if (c->session != NULL) { 737 server_client_check_redraw(c); 738 server_client_reset_state(c); 739 } 740 } 741 742 /* 743 * Any windows will have been redrawn as part of clients, so clear 744 * their flags now. Also check pane focus and resize. 745 */ 746 RB_FOREACH(w, windows, &windows) { 747 w->flags &= ~WINDOW_REDRAW; 748 TAILQ_FOREACH(wp, &w->panes, entry) { 749 if (wp->fd != -1) { 750 server_client_check_focus(wp); 751 server_client_check_resize(wp); 752 } 753 wp->flags &= ~PANE_REDRAW; 754 } 755 } 756 } 757 758 /* Check if pane should be resized. */ 759 void 760 server_client_check_resize(struct window_pane *wp) 761 { 762 struct winsize ws; 763 764 if (!(wp->flags & PANE_RESIZE)) 765 return; 766 767 memset(&ws, 0, sizeof ws); 768 ws.ws_col = wp->sx; 769 ws.ws_row = wp->sy; 770 771 if (ioctl(wp->fd, TIOCSWINSZ, &ws) == -1) 772 fatal("ioctl failed"); 773 774 wp->flags &= ~PANE_RESIZE; 775 } 776 777 /* Check whether pane should be focused. */ 778 void 779 server_client_check_focus(struct window_pane *wp) 780 { 781 struct client *c; 782 int push; 783 784 /* Are focus events off? */ 785 if (!options_get_number(&global_options, "focus-events")) 786 return; 787 788 /* Do we need to push the focus state? */ 789 push = wp->flags & PANE_FOCUSPUSH; 790 wp->flags &= ~PANE_FOCUSPUSH; 791 792 /* If we don't care about focus, forget it. */ 793 if (!(wp->base.mode & MODE_FOCUSON)) 794 return; 795 796 /* If we're not the active pane in our window, we're not focused. */ 797 if (wp->window->active != wp) 798 goto not_focused; 799 800 /* If we're in a mode, we're not focused. */ 801 if (wp->screen != &wp->base) 802 goto not_focused; 803 804 /* 805 * If our window is the current window in any focused clients with an 806 * attached session, we're focused. 807 */ 808 TAILQ_FOREACH(c, &clients, entry) { 809 if (c->session == NULL || !(c->flags & CLIENT_FOCUSED)) 810 continue; 811 if (c->session->flags & SESSION_UNATTACHED) 812 continue; 813 814 if (c->session->curw->window == wp->window) 815 goto focused; 816 } 817 818 not_focused: 819 if (push || (wp->flags & PANE_FOCUSED)) 820 bufferevent_write(wp->event, "\033[O", 3); 821 wp->flags &= ~PANE_FOCUSED; 822 return; 823 824 focused: 825 if (push || !(wp->flags & PANE_FOCUSED)) 826 bufferevent_write(wp->event, "\033[I", 3); 827 wp->flags |= PANE_FOCUSED; 828 } 829 830 /* 831 * Update cursor position and mode settings. The scroll region and attributes 832 * are cleared when idle (waiting for an event) as this is the most likely time 833 * a user may interrupt tmux, for example with ~^Z in ssh(1). This is a 834 * compromise between excessive resets and likelihood of an interrupt. 835 * 836 * tty_region/tty_reset/tty_update_mode already take care of not resetting 837 * things that are already in their default state. 838 */ 839 void 840 server_client_reset_state(struct client *c) 841 { 842 struct window *w = c->session->curw->window; 843 struct window_pane *wp = w->active; 844 struct screen *s = wp->screen; 845 struct options *oo = &c->session->options; 846 int status, mode, o; 847 848 if (c->flags & CLIENT_SUSPENDED) 849 return; 850 851 if (c->flags & CLIENT_CONTROL) 852 return; 853 854 tty_region(&c->tty, 0, c->tty.sy - 1); 855 856 status = options_get_number(oo, "status"); 857 if (!window_pane_visible(wp) || wp->yoff + s->cy >= c->tty.sy - status) 858 tty_cursor(&c->tty, 0, 0); 859 else { 860 o = status && options_get_number(oo, "status-position") == 0; 861 tty_cursor(&c->tty, wp->xoff + s->cx, o + wp->yoff + s->cy); 862 } 863 864 /* 865 * Set mouse mode if requested. To support dragging, always use button 866 * mode. 867 */ 868 mode = s->mode; 869 if (options_get_number(oo, "mouse")) 870 mode = (mode & ~ALL_MOUSE_MODES) | MODE_MOUSE_BUTTON; 871 872 /* 873 * Set UTF-8 mouse input if required. If the terminal is UTF-8, the 874 * user has set mouse-utf8 and any mouse mode is in effect, turn on 875 * UTF-8 mouse input. If the receiving terminal hasn't requested it 876 * (that is, it isn't in s->mode), then it'll be converted in 877 * input_mouse. 878 */ 879 if ((c->tty.flags & TTY_UTF8) && 880 (mode & ALL_MOUSE_MODES) && options_get_number(oo, "mouse-utf8")) 881 mode |= MODE_MOUSE_UTF8; 882 else 883 mode &= ~MODE_MOUSE_UTF8; 884 885 /* Set the terminal mode and reset attributes. */ 886 tty_update_mode(&c->tty, mode, s); 887 tty_reset(&c->tty); 888 } 889 890 /* Repeat time callback. */ 891 void 892 server_client_repeat_timer(unused int fd, unused short events, void *data) 893 { 894 struct client *c = data; 895 896 if (c->flags & CLIENT_REPEAT) { 897 server_client_key_table(c, "root"); 898 c->flags &= ~CLIENT_REPEAT; 899 server_status_client(c); 900 } 901 } 902 903 /* Check if client should be exited. */ 904 void 905 server_client_check_exit(struct client *c) 906 { 907 if (!(c->flags & CLIENT_EXIT)) 908 return; 909 910 if (EVBUFFER_LENGTH(c->stdin_data) != 0) 911 return; 912 if (EVBUFFER_LENGTH(c->stdout_data) != 0) 913 return; 914 if (EVBUFFER_LENGTH(c->stderr_data) != 0) 915 return; 916 917 server_write_client(c, MSG_EXIT, &c->retval, sizeof c->retval); 918 c->flags &= ~CLIENT_EXIT; 919 } 920 921 /* Check for client redraws. */ 922 void 923 server_client_check_redraw(struct client *c) 924 { 925 struct session *s = c->session; 926 struct tty *tty = &c->tty; 927 struct window_pane *wp; 928 int flags, redraw; 929 930 if (c->flags & (CLIENT_CONTROL|CLIENT_SUSPENDED)) 931 return; 932 933 if (c->flags & (CLIENT_REDRAW|CLIENT_STATUS)) { 934 if (options_get_number(&s->options, "set-titles")) 935 server_client_set_title(c); 936 937 if (c->message_string != NULL) 938 redraw = status_message_redraw(c); 939 else if (c->prompt_string != NULL) 940 redraw = status_prompt_redraw(c); 941 else 942 redraw = status_redraw(c); 943 if (!redraw) 944 c->flags &= ~CLIENT_STATUS; 945 } 946 947 flags = tty->flags & (TTY_FREEZE|TTY_NOCURSOR); 948 tty->flags = (tty->flags & ~TTY_FREEZE) | TTY_NOCURSOR; 949 950 if (c->flags & CLIENT_REDRAW) { 951 tty_update_mode(tty, tty->mode, NULL); 952 screen_redraw_screen(c, 1, 1, 1); 953 c->flags &= ~(CLIENT_STATUS|CLIENT_BORDERS); 954 } else if (c->flags & CLIENT_REDRAWWINDOW) { 955 tty_update_mode(tty, tty->mode, NULL); 956 TAILQ_FOREACH(wp, &c->session->curw->window->panes, entry) 957 screen_redraw_pane(c, wp); 958 c->flags &= ~CLIENT_REDRAWWINDOW; 959 } else { 960 TAILQ_FOREACH(wp, &c->session->curw->window->panes, entry) { 961 if (wp->flags & PANE_REDRAW) { 962 tty_update_mode(tty, tty->mode, NULL); 963 screen_redraw_pane(c, wp); 964 } 965 } 966 } 967 968 if (c->flags & CLIENT_BORDERS) { 969 tty_update_mode(tty, tty->mode, NULL); 970 screen_redraw_screen(c, 0, 0, 1); 971 } 972 973 if (c->flags & CLIENT_STATUS) { 974 tty_update_mode(tty, tty->mode, NULL); 975 screen_redraw_screen(c, 0, 1, 0); 976 } 977 978 tty->flags = (tty->flags & ~(TTY_FREEZE|TTY_NOCURSOR)) | flags; 979 tty_update_mode(tty, tty->mode, NULL); 980 981 c->flags &= ~(CLIENT_REDRAW|CLIENT_STATUS|CLIENT_BORDERS); 982 } 983 984 /* Set client title. */ 985 void 986 server_client_set_title(struct client *c) 987 { 988 struct session *s = c->session; 989 const char *template; 990 char *title; 991 struct format_tree *ft; 992 993 template = options_get_string(&s->options, "set-titles-string"); 994 995 ft = format_create(); 996 format_defaults(ft, c, NULL, NULL, NULL); 997 998 title = format_expand_time(ft, template, time(NULL)); 999 if (c->title == NULL || strcmp(title, c->title) != 0) { 1000 free(c->title); 1001 c->title = xstrdup(title); 1002 tty_set_title(&c->tty, c->title); 1003 } 1004 free(title); 1005 1006 format_free(ft); 1007 } 1008 1009 /* Dispatch message from client. */ 1010 int 1011 server_client_msg_dispatch(struct client *c) 1012 { 1013 struct imsg imsg; 1014 struct msg_stdin_data stdindata; 1015 const char *data; 1016 ssize_t n, datalen; 1017 1018 if ((n = imsg_read(&c->ibuf)) == -1 || n == 0) 1019 return (-1); 1020 1021 for (;;) { 1022 if ((n = imsg_get(&c->ibuf, &imsg)) == -1) 1023 return (-1); 1024 if (n == 0) 1025 return (0); 1026 1027 data = imsg.data; 1028 datalen = imsg.hdr.len - IMSG_HEADER_SIZE; 1029 1030 if (imsg.hdr.peerid != PROTOCOL_VERSION) { 1031 server_write_client(c, MSG_VERSION, NULL, 0); 1032 c->flags |= CLIENT_BAD; 1033 if (imsg.fd != -1) 1034 close(imsg.fd); 1035 imsg_free(&imsg); 1036 continue; 1037 } 1038 1039 log_debug("got %u from client %d", imsg.hdr.type, c->ibuf.fd); 1040 switch (imsg.hdr.type) { 1041 case MSG_IDENTIFY_FLAGS: 1042 case MSG_IDENTIFY_TERM: 1043 case MSG_IDENTIFY_TTYNAME: 1044 case MSG_IDENTIFY_CWD: 1045 case MSG_IDENTIFY_STDIN: 1046 case MSG_IDENTIFY_ENVIRON: 1047 case MSG_IDENTIFY_DONE: 1048 server_client_msg_identify(c, &imsg); 1049 break; 1050 case MSG_COMMAND: 1051 server_client_msg_command(c, &imsg); 1052 break; 1053 case MSG_STDIN: 1054 if (datalen != sizeof stdindata) 1055 fatalx("bad MSG_STDIN size"); 1056 memcpy(&stdindata, data, sizeof stdindata); 1057 1058 if (c->stdin_callback == NULL) 1059 break; 1060 if (stdindata.size <= 0) 1061 c->stdin_closed = 1; 1062 else { 1063 evbuffer_add(c->stdin_data, stdindata.data, 1064 stdindata.size); 1065 } 1066 c->stdin_callback(c, c->stdin_closed, 1067 c->stdin_callback_data); 1068 break; 1069 case MSG_RESIZE: 1070 if (datalen != 0) 1071 fatalx("bad MSG_RESIZE size"); 1072 1073 if (c->flags & CLIENT_CONTROL) 1074 break; 1075 if (tty_resize(&c->tty)) { 1076 recalculate_sizes(); 1077 server_redraw_client(c); 1078 } 1079 break; 1080 case MSG_EXITING: 1081 if (datalen != 0) 1082 fatalx("bad MSG_EXITING size"); 1083 1084 c->session = NULL; 1085 tty_close(&c->tty); 1086 server_write_client(c, MSG_EXITED, NULL, 0); 1087 break; 1088 case MSG_WAKEUP: 1089 case MSG_UNLOCK: 1090 if (datalen != 0) 1091 fatalx("bad MSG_WAKEUP size"); 1092 1093 if (!(c->flags & CLIENT_SUSPENDED)) 1094 break; 1095 c->flags &= ~CLIENT_SUSPENDED; 1096 1097 if (c->tty.fd == -1) /* exited in the meantime */ 1098 break; 1099 1100 if (gettimeofday(&c->activity_time, NULL) != 0) 1101 fatal("gettimeofday"); 1102 if (c->session != NULL) 1103 session_update_activity(c->session); 1104 1105 tty_start_tty(&c->tty); 1106 server_redraw_client(c); 1107 recalculate_sizes(); 1108 break; 1109 case MSG_SHELL: 1110 if (datalen != 0) 1111 fatalx("bad MSG_SHELL size"); 1112 1113 server_client_msg_shell(c); 1114 break; 1115 } 1116 1117 imsg_free(&imsg); 1118 } 1119 } 1120 1121 /* Handle command message. */ 1122 void 1123 server_client_msg_command(struct client *c, struct imsg *imsg) 1124 { 1125 struct msg_command_data data; 1126 char *buf; 1127 size_t len; 1128 struct cmd_list *cmdlist = NULL; 1129 int argc; 1130 char **argv, *cause; 1131 1132 if (imsg->hdr.len - IMSG_HEADER_SIZE < sizeof data) 1133 fatalx("bad MSG_COMMAND size"); 1134 memcpy(&data, imsg->data, sizeof data); 1135 1136 buf = (char *)imsg->data + sizeof data; 1137 len = imsg->hdr.len - IMSG_HEADER_SIZE - sizeof data; 1138 if (len > 0 && buf[len - 1] != '\0') 1139 fatalx("bad MSG_COMMAND string"); 1140 1141 argc = data.argc; 1142 if (cmd_unpack_argv(buf, len, argc, &argv) != 0) { 1143 cmdq_error(c->cmdq, "command too long"); 1144 goto error; 1145 } 1146 1147 if (argc == 0) { 1148 argc = 1; 1149 argv = xcalloc(1, sizeof *argv); 1150 *argv = xstrdup("new-session"); 1151 } 1152 1153 if ((cmdlist = cmd_list_parse(argc, argv, NULL, 0, &cause)) == NULL) { 1154 cmdq_error(c->cmdq, "%s", cause); 1155 cmd_free_argv(argc, argv); 1156 goto error; 1157 } 1158 cmd_free_argv(argc, argv); 1159 1160 if (c != cfg_client || cfg_finished) 1161 cmdq_run(c->cmdq, cmdlist, NULL); 1162 else 1163 cmdq_append(c->cmdq, cmdlist, NULL); 1164 cmd_list_free(cmdlist); 1165 return; 1166 1167 error: 1168 if (cmdlist != NULL) 1169 cmd_list_free(cmdlist); 1170 1171 c->flags |= CLIENT_EXIT; 1172 } 1173 1174 /* Handle identify message. */ 1175 void 1176 server_client_msg_identify(struct client *c, struct imsg *imsg) 1177 { 1178 const char *data; 1179 size_t datalen; 1180 int flags; 1181 1182 if (c->flags & CLIENT_IDENTIFIED) 1183 fatalx("out-of-order identify message"); 1184 1185 data = imsg->data; 1186 datalen = imsg->hdr.len - IMSG_HEADER_SIZE; 1187 1188 switch (imsg->hdr.type) { 1189 case MSG_IDENTIFY_FLAGS: 1190 if (datalen != sizeof flags) 1191 fatalx("bad MSG_IDENTIFY_FLAGS size"); 1192 memcpy(&flags, data, sizeof flags); 1193 c->flags |= flags; 1194 break; 1195 case MSG_IDENTIFY_TERM: 1196 if (datalen == 0 || data[datalen - 1] != '\0') 1197 fatalx("bad MSG_IDENTIFY_TERM string"); 1198 c->term = xstrdup(data); 1199 break; 1200 case MSG_IDENTIFY_TTYNAME: 1201 if (datalen == 0 || data[datalen - 1] != '\0') 1202 fatalx("bad MSG_IDENTIFY_TTYNAME string"); 1203 c->ttyname = xstrdup(data); 1204 break; 1205 case MSG_IDENTIFY_CWD: 1206 if (datalen != 0) 1207 fatalx("bad MSG_IDENTIFY_CWD size"); 1208 c->cwd = imsg->fd; 1209 break; 1210 case MSG_IDENTIFY_STDIN: 1211 if (datalen != 0) 1212 fatalx("bad MSG_IDENTIFY_STDIN size"); 1213 c->fd = imsg->fd; 1214 break; 1215 case MSG_IDENTIFY_ENVIRON: 1216 if (datalen == 0 || data[datalen - 1] != '\0') 1217 fatalx("bad MSG_IDENTIFY_ENVIRON string"); 1218 if (strchr(data, '=') != NULL) 1219 environ_put(&c->environ, data); 1220 break; 1221 default: 1222 break; 1223 } 1224 1225 if (imsg->hdr.type != MSG_IDENTIFY_DONE) 1226 return; 1227 c->flags |= CLIENT_IDENTIFIED; 1228 1229 if (c->flags & CLIENT_CONTROL) { 1230 c->stdin_callback = control_callback; 1231 1232 evbuffer_free(c->stderr_data); 1233 c->stderr_data = c->stdout_data; 1234 1235 if (c->flags & CLIENT_CONTROLCONTROL) 1236 evbuffer_add_printf(c->stdout_data, "\033P1000p"); 1237 server_write_client(c, MSG_STDIN, NULL, 0); 1238 1239 c->tty.fd = -1; 1240 c->tty.log_fd = -1; 1241 1242 close(c->fd); 1243 c->fd = -1; 1244 1245 return; 1246 } 1247 1248 if (c->fd == -1) 1249 return; 1250 if (!isatty(c->fd)) { 1251 close(c->fd); 1252 c->fd = -1; 1253 return; 1254 } 1255 tty_init(&c->tty, c, c->fd, c->term); 1256 if (c->flags & CLIENT_UTF8) 1257 c->tty.flags |= TTY_UTF8; 1258 if (c->flags & CLIENT_256COLOURS) 1259 c->tty.term_flags |= TERM_256COLOURS; 1260 1261 tty_resize(&c->tty); 1262 1263 if (!(c->flags & CLIENT_CONTROL)) 1264 c->flags |= CLIENT_TERMINAL; 1265 } 1266 1267 /* Handle shell message. */ 1268 void 1269 server_client_msg_shell(struct client *c) 1270 { 1271 const char *shell; 1272 1273 shell = options_get_string(&global_s_options, "default-shell"); 1274 if (*shell == '\0' || areshell(shell)) 1275 shell = _PATH_BSHELL; 1276 server_write_client(c, MSG_SHELL, shell, strlen(shell) + 1); 1277 1278 c->flags |= CLIENT_BAD; /* it will die after exec */ 1279 } 1280