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