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 #include "tmate.h"
33
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 key_code 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 void server_client_dispatch(struct imsg *, void *);
46 void server_client_dispatch_command(struct client *, struct imsg *);
47 void server_client_dispatch_identify(struct client *, struct imsg *);
48 void server_client_dispatch_shell(struct client *);
49
50 /* Check if this client is inside this server. */
51 int
server_client_check_nested(struct client * c)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
server_client_set_key_table(struct client * c,const char * name)73 server_client_set_key_table(struct client *c, const char *name)
74 {
75 if (name == NULL)
76 name = server_client_get_key_table(c);
77
78 key_bindings_unref_table(c->keytable);
79 c->keytable = key_bindings_get_table(name, 1);
80 c->keytable->references++;
81 }
82
83 /* Get default key table. */
84 const char *
server_client_get_key_table(struct client * c)85 server_client_get_key_table(struct client *c)
86 {
87 struct session *s = c->session;
88 const char *name;
89
90 if (s == NULL)
91 return ("root");
92
93 name = options_get_string(s->options, "key-table");
94 if (*name == '\0')
95 return ("root");
96 return (name);
97 }
98
99 /* Create a new client. */
100 void
server_client_create(int fd)101 server_client_create(int fd)
102 {
103 struct client *c;
104
105 setblocking(fd, 0);
106
107 c = xcalloc(1, sizeof *c);
108 c->references = 1;
109 c->peer = proc_add_peer(server_proc, fd, server_client_dispatch, c);
110
111 if (gettimeofday(&c->creation_time, NULL) != 0)
112 fatal("gettimeofday failed");
113 memcpy(&c->activity_time, &c->creation_time, sizeof c->activity_time);
114
115 c->environ = environ_create();
116
117 c->fd = -1;
118 c->cwd = NULL;
119
120 c->cmdq = cmdq_new(c);
121 c->cmdq->client_exit = 1;
122
123 c->stdin_data = evbuffer_new();
124 c->stdout_data = evbuffer_new();
125 c->stderr_data = evbuffer_new();
126
127 c->tty.fd = -1;
128 c->title = NULL;
129
130 c->session = NULL;
131 c->last_session = NULL;
132 c->tty.sx = 80;
133 c->tty.sy = 24;
134
135 screen_init(&c->status, c->tty.sx, 1, 0);
136
137 c->message_string = NULL;
138 TAILQ_INIT(&c->message_log);
139
140 c->prompt_string = NULL;
141 c->prompt_buffer = NULL;
142 c->prompt_index = 0;
143
144 c->flags |= CLIENT_FOCUSED;
145
146 c->keytable = key_bindings_get_table("root", 1);
147 c->keytable->references++;
148
149 evtimer_set(&c->repeat_timer, server_client_repeat_timer, c);
150
151 TAILQ_INSERT_TAIL(&clients, c, entry);
152 log_debug("new client %p", c);
153 }
154
155 /* Open client terminal if needed. */
156 int
server_client_open(struct client * c,char ** cause)157 server_client_open(struct client *c, char **cause)
158 {
159 if (c->flags & CLIENT_CONTROL)
160 return (0);
161
162 if (strcmp(c->ttyname, "/dev/tty") == 0) {
163 *cause = xstrdup("can't use /dev/tty");
164 return (-1);
165 }
166
167 if (!(c->flags & CLIENT_TERMINAL)) {
168 *cause = xstrdup("not a terminal");
169 return (-1);
170 }
171
172 if (tty_open(&c->tty, cause) != 0)
173 return (-1);
174
175 return (0);
176 }
177
178 /* Lost a client. */
179 void
server_client_lost(struct client * c)180 server_client_lost(struct client *c)
181 {
182 struct message_entry *msg, *msg1;
183
184 c->flags |= CLIENT_DEAD;
185
186 status_prompt_clear(c);
187 status_message_clear(c);
188
189 if (c->stdin_callback != NULL)
190 c->stdin_callback(c, 1, c->stdin_callback_data);
191
192 TAILQ_REMOVE(&clients, c, entry);
193 log_debug("lost client %p", c);
194
195 /*
196 * If CLIENT_TERMINAL hasn't been set, then tty_init hasn't been called
197 * and tty_free might close an unrelated fd.
198 */
199 if (c->flags & CLIENT_TERMINAL)
200 tty_free(&c->tty);
201 free(c->ttyname);
202 free(c->term);
203
204 evbuffer_free(c->stdin_data);
205 evbuffer_free(c->stdout_data);
206 if (c->stderr_data != c->stdout_data)
207 evbuffer_free(c->stderr_data);
208
209 if (event_initialized(&c->status_timer))
210 evtimer_del(&c->status_timer);
211 screen_free(&c->status);
212
213 free(c->title);
214 free((void *)c->cwd);
215
216 evtimer_del(&c->repeat_timer);
217
218 key_bindings_unref_table(c->keytable);
219
220 if (event_initialized(&c->identify_timer))
221 evtimer_del(&c->identify_timer);
222
223 free(c->message_string);
224 if (event_initialized(&c->message_timer))
225 evtimer_del(&c->message_timer);
226 TAILQ_FOREACH_SAFE(msg, &c->message_log, entry, msg1) {
227 free(msg->msg);
228 TAILQ_REMOVE(&c->message_log, msg, entry);
229 free(msg);
230 }
231
232 free(c->prompt_string);
233 free(c->prompt_buffer);
234
235 c->cmdq->flags |= CMD_Q_DEAD;
236 cmdq_free(c->cmdq);
237 c->cmdq = NULL;
238
239 environ_free(c->environ);
240
241 proc_remove_peer(c->peer);
242 c->peer = NULL;
243
244 server_client_unref(c);
245
246 server_add_accept(0); /* may be more file descriptors now */
247
248 recalculate_sizes();
249 server_check_unattached();
250 server_update_socket();
251 }
252
253 /* Remove reference from a client. */
254 void
server_client_unref(struct client * c)255 server_client_unref(struct client *c)
256 {
257 log_debug("unref client %p (%d references)", c, c->references);
258
259 c->references--;
260 if (c->references == 0)
261 event_once(-1, EV_TIMEOUT, server_client_free, c, NULL);
262 }
263
264 /* Free dead client. */
265 void
server_client_free(__unused int fd,__unused short events,void * arg)266 server_client_free(__unused int fd, __unused short events, void *arg)
267 {
268 struct client *c = arg;
269
270 log_debug("free client %p (%d references)", c, c->references);
271
272 if (c->references == 0)
273 free(c);
274 }
275
276 /* Detach a client. */
277 void
server_client_detach(struct client * c,enum msgtype msgtype)278 server_client_detach(struct client *c, enum msgtype msgtype)
279 {
280 struct session *s = c->session;
281
282 if (s == NULL)
283 return;
284
285 hooks_run(c->session->hooks, c, NULL, "client-detached");
286 proc_send_s(c->peer, msgtype, s->name);
287 }
288
289 /* Check for mouse keys. */
290 key_code
server_client_check_mouse(struct client * c)291 server_client_check_mouse(struct client *c)
292 {
293 struct session *s = c->session;
294 struct mouse_event *m = &c->tty.mouse;
295 struct window *w;
296 struct window_pane *wp;
297 enum { NOTYPE, DOWN, UP, DRAG, WHEEL } type = NOTYPE;
298 enum { NOWHERE, PANE, STATUS, BORDER } where = NOWHERE;
299 u_int x, y, b;
300 key_code key;
301
302 log_debug("mouse %02x at %u,%u (last %u,%u) (%d)", m->b, m->x, m->y,
303 m->lx, m->ly, c->tty.mouse_drag_flag);
304
305 /* What type of event is this? */
306 if (MOUSE_DRAG(m->b)) {
307 type = DRAG;
308 if (c->tty.mouse_drag_flag) {
309 x = m->x, y = m->y, b = m->b;
310 log_debug("drag update at %u,%u", x, y);
311 } else {
312 x = m->lx, y = m->ly, b = m->lb;
313 log_debug("drag start at %u,%u", x, y);
314 }
315 } else if (MOUSE_WHEEL(m->b)) {
316 type = WHEEL;
317 x = m->x, y = m->y, b = m->b;
318 log_debug("wheel at %u,%u", x, y);
319 } else if (MOUSE_BUTTONS(m->b) == 3) {
320 type = UP;
321 x = m->x, y = m->y, b = m->lb;
322 log_debug("up at %u,%u", x, y);
323 } else {
324 type = DOWN;
325 x = m->x, y = m->y, b = m->b;
326 log_debug("down at %u,%u", x, y);
327 }
328 if (type == NOTYPE)
329 return (KEYC_UNKNOWN);
330
331 /* Always save the session. */
332 m->s = s->id;
333
334 /* Is this on the status line? */
335 m->statusat = status_at_line(c);
336 if (m->statusat != -1 && y == (u_int)m->statusat) {
337 w = status_get_window_at(c, x);
338 if (w == NULL)
339 return (KEYC_UNKNOWN);
340 m->w = w->id;
341 where = STATUS;
342 } else
343 m->w = -1;
344
345 /* Not on status line. Adjust position and check for border or pane. */
346 if (where == NOWHERE) {
347 if (m->statusat == 0 && y > 0)
348 y--;
349 else if (m->statusat > 0 && y >= (u_int)m->statusat)
350 y = m->statusat - 1;
351
352 TAILQ_FOREACH(wp, &s->curw->window->panes, entry) {
353 if ((wp->xoff + wp->sx == x &&
354 wp->yoff <= 1 + y &&
355 wp->yoff + wp->sy >= y) ||
356 (wp->yoff + wp->sy == y &&
357 wp->xoff <= 1 + x &&
358 wp->xoff + wp->sx >= x))
359 break;
360 }
361 if (wp != NULL)
362 where = BORDER;
363 else {
364 wp = window_get_active_at(s->curw->window, x, y);
365 if (wp != NULL) {
366 where = PANE;
367 log_debug("mouse at %u,%u is on pane %%%u",
368 x, y, wp->id);
369 }
370 }
371 if (where == NOWHERE)
372 return (KEYC_UNKNOWN);
373 m->wp = wp->id;
374 m->w = wp->window->id;
375 } else
376 m->wp = -1;
377
378 /* Stop dragging if needed. */
379 if (type != DRAG && c->tty.mouse_drag_flag) {
380 if (c->tty.mouse_drag_release != NULL)
381 c->tty.mouse_drag_release(c, m);
382
383 c->tty.mouse_drag_update = NULL;
384 c->tty.mouse_drag_release = NULL;
385
386 /*
387 * End a mouse drag by passing a MouseDragEnd key corresponding
388 * to the button that started the drag.
389 */
390 switch (c->tty.mouse_drag_flag) {
391 case 1:
392 if (where == PANE)
393 key = KEYC_MOUSEDRAGEND1_PANE;
394 if (where == STATUS)
395 key = KEYC_MOUSEDRAGEND1_STATUS;
396 if (where == BORDER)
397 key = KEYC_MOUSEDRAGEND1_BORDER;
398 break;
399 case 2:
400 if (where == PANE)
401 key = KEYC_MOUSEDRAGEND2_PANE;
402 if (where == STATUS)
403 key = KEYC_MOUSEDRAGEND2_STATUS;
404 if (where == BORDER)
405 key = KEYC_MOUSEDRAGEND2_BORDER;
406 break;
407 case 3:
408 if (where == PANE)
409 key = KEYC_MOUSEDRAGEND3_PANE;
410 if (where == STATUS)
411 key = KEYC_MOUSEDRAGEND3_STATUS;
412 if (where == BORDER)
413 key = KEYC_MOUSEDRAGEND3_BORDER;
414 break;
415 default:
416 key = KEYC_MOUSE;
417 break;
418 }
419 c->tty.mouse_drag_flag = 0;
420
421 return (key);
422 }
423
424 /* Convert to a key binding. */
425 key = KEYC_UNKNOWN;
426 switch (type) {
427 case NOTYPE:
428 break;
429 case DRAG:
430 if (c->tty.mouse_drag_update != NULL)
431 c->tty.mouse_drag_update(c, m);
432 else {
433 switch (MOUSE_BUTTONS(b)) {
434 case 0:
435 if (where == PANE)
436 key = KEYC_MOUSEDRAG1_PANE;
437 if (where == STATUS)
438 key = KEYC_MOUSEDRAG1_STATUS;
439 if (where == BORDER)
440 key = KEYC_MOUSEDRAG1_BORDER;
441 break;
442 case 1:
443 if (where == PANE)
444 key = KEYC_MOUSEDRAG2_PANE;
445 if (where == STATUS)
446 key = KEYC_MOUSEDRAG2_STATUS;
447 if (where == BORDER)
448 key = KEYC_MOUSEDRAG2_BORDER;
449 break;
450 case 2:
451 if (where == PANE)
452 key = KEYC_MOUSEDRAG3_PANE;
453 if (where == STATUS)
454 key = KEYC_MOUSEDRAG3_STATUS;
455 if (where == BORDER)
456 key = KEYC_MOUSEDRAG3_BORDER;
457 break;
458 }
459 }
460
461 /*
462 * Begin a drag by setting the flag to a non-zero value that
463 * corresponds to the mouse button in use.
464 */
465 c->tty.mouse_drag_flag = MOUSE_BUTTONS(b) + 1;
466 break;
467 case WHEEL:
468 if (MOUSE_BUTTONS(b) == MOUSE_WHEEL_UP) {
469 if (where == PANE)
470 key = KEYC_WHEELUP_PANE;
471 if (where == STATUS)
472 key = KEYC_WHEELUP_STATUS;
473 if (where == BORDER)
474 key = KEYC_WHEELUP_BORDER;
475 } else {
476 if (where == PANE)
477 key = KEYC_WHEELDOWN_PANE;
478 if (where == STATUS)
479 key = KEYC_WHEELDOWN_STATUS;
480 if (where == BORDER)
481 key = KEYC_WHEELDOWN_BORDER;
482 }
483 break;
484 case UP:
485 switch (MOUSE_BUTTONS(b)) {
486 case 0:
487 if (where == PANE)
488 key = KEYC_MOUSEUP1_PANE;
489 if (where == STATUS)
490 key = KEYC_MOUSEUP1_STATUS;
491 if (where == BORDER)
492 key = KEYC_MOUSEUP1_BORDER;
493 break;
494 case 1:
495 if (where == PANE)
496 key = KEYC_MOUSEUP2_PANE;
497 if (where == STATUS)
498 key = KEYC_MOUSEUP2_STATUS;
499 if (where == BORDER)
500 key = KEYC_MOUSEUP2_BORDER;
501 break;
502 case 2:
503 if (where == PANE)
504 key = KEYC_MOUSEUP3_PANE;
505 if (where == STATUS)
506 key = KEYC_MOUSEUP3_STATUS;
507 if (where == BORDER)
508 key = KEYC_MOUSEUP3_BORDER;
509 break;
510 }
511 break;
512 case DOWN:
513 switch (MOUSE_BUTTONS(b)) {
514 case 0:
515 if (where == PANE)
516 key = KEYC_MOUSEDOWN1_PANE;
517 if (where == STATUS)
518 key = KEYC_MOUSEDOWN1_STATUS;
519 if (where == BORDER)
520 key = KEYC_MOUSEDOWN1_BORDER;
521 break;
522 case 1:
523 if (where == PANE)
524 key = KEYC_MOUSEDOWN2_PANE;
525 if (where == STATUS)
526 key = KEYC_MOUSEDOWN2_STATUS;
527 if (where == BORDER)
528 key = KEYC_MOUSEDOWN2_BORDER;
529 break;
530 case 2:
531 if (where == PANE)
532 key = KEYC_MOUSEDOWN3_PANE;
533 if (where == STATUS)
534 key = KEYC_MOUSEDOWN3_STATUS;
535 if (where == BORDER)
536 key = KEYC_MOUSEDOWN3_BORDER;
537 break;
538 }
539 break;
540 }
541 if (key == KEYC_UNKNOWN)
542 return (KEYC_UNKNOWN);
543
544 /* Apply modifiers if any. */
545 if (b & MOUSE_MASK_META)
546 key |= KEYC_ESCAPE;
547 if (b & MOUSE_MASK_CTRL)
548 key |= KEYC_CTRL;
549 if (b & MOUSE_MASK_SHIFT)
550 key |= KEYC_SHIFT;
551
552 return (key);
553 }
554
555 /* Is this fast enough to probably be a paste? */
556 int
server_client_assume_paste(struct session * s)557 server_client_assume_paste(struct session *s)
558 {
559 struct timeval tv;
560 int t;
561
562 if ((t = options_get_number(s->options, "assume-paste-time")) == 0)
563 return (0);
564
565 timersub(&s->activity_time, &s->last_activity_time, &tv);
566 if (tv.tv_sec == 0 && tv.tv_usec < t * 1000) {
567 log_debug("session %s pasting (flag %d)", s->name,
568 !!(s->flags & SESSION_PASTING));
569 if (s->flags & SESSION_PASTING)
570 return (1);
571 s->flags |= SESSION_PASTING;
572 return (0);
573 }
574 log_debug("session %s not pasting", s->name);
575 s->flags &= ~SESSION_PASTING;
576 return (0);
577 }
578
579 /* Handle data key input from client. */
580 void
server_client_handle_key(struct client * c,key_code key)581 server_client_handle_key(struct client *c, key_code key)
582 {
583 struct mouse_event *m = &c->tty.mouse;
584 struct session *s = c->session;
585 struct window *w;
586 struct window_pane *wp;
587 struct timeval tv;
588 struct key_table *table;
589 struct key_binding bd_find, *bd;
590 int xtimeout;
591
592 /* Check the client is good to accept input. */
593 if (s == NULL || (c->flags & (CLIENT_DEAD|CLIENT_SUSPENDED)) != 0)
594 return;
595 w = s->curw->window;
596
597 /* Update the activity timer. */
598 if (gettimeofday(&c->activity_time, NULL) != 0)
599 fatal("gettimeofday failed");
600 session_update_activity(s, &c->activity_time);
601
602 /* Number keys jump to pane in identify mode. */
603 if (c->flags & CLIENT_IDENTIFY && key >= '0' && key <= '9') {
604 if (c->flags & CLIENT_READONLY)
605 return;
606 window_unzoom(w);
607 wp = window_pane_at_index(w, key - '0');
608 if (wp != NULL && window_pane_visible(wp))
609 window_set_active_pane(w, wp);
610 server_clear_identify(c);
611 return;
612 }
613
614 /* Handle status line. */
615 if (!(c->flags & CLIENT_READONLY)) {
616 #ifdef TMATE
617 if (!(c->flags & CLIENT_FORCE_STATUS))
618 #endif
619 status_message_clear(c);
620 server_clear_identify(c);
621 }
622 if (c->prompt_string != NULL) {
623 if (!(c->flags & CLIENT_READONLY))
624 status_prompt_key(c, key);
625 return;
626 }
627
628 /* Check for mouse keys. */
629 if (key == KEYC_MOUSE) {
630 if (c->flags & CLIENT_READONLY)
631 return;
632 key = server_client_check_mouse(c);
633 if (key == KEYC_UNKNOWN)
634 return;
635
636 m->valid = 1;
637 m->key = key;
638
639 if (!options_get_number(s->options, "mouse"))
640 goto forward;
641 } else
642 m->valid = 0;
643
644 /* Treat everything as a regular key when pasting is detected. */
645 if (!KEYC_IS_MOUSE(key) && server_client_assume_paste(s))
646 goto forward;
647
648 retry:
649 /* Try to see if there is a key binding in the current table. */
650 bd_find.key = key;
651 bd = RB_FIND(key_bindings, &c->keytable->key_bindings, &bd_find);
652 if (bd != NULL) {
653 /*
654 * Key was matched in this table. If currently repeating but a
655 * non-repeating binding was found, stop repeating and try
656 * again in the root table.
657 */
658 if ((c->flags & CLIENT_REPEAT) && !bd->can_repeat) {
659 server_client_set_key_table(c, NULL);
660 c->flags &= ~CLIENT_REPEAT;
661 server_status_client(c);
662 goto retry;
663 }
664
665 /*
666 * Take a reference to this table to make sure the key binding
667 * doesn't disappear.
668 */
669 table = c->keytable;
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_set_key_table(c, NULL);
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_set_key_table(c, NULL);
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, server_client_get_key_table(c)) != 0) {
709 server_client_set_key_table(c, NULL);
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 == (key_code)options_get_number(s->options, "prefix") ||
719 key == (key_code)options_get_number(s->options, "prefix2")) {
720 server_client_set_key_table(c, "prefix");
721 server_status_client(c);
722 return;
723 }
724
725 forward:
726 if (c->flags & CLIENT_READONLY)
727 return;
728 if (KEYC_IS_MOUSE(key))
729 wp = cmd_mouse_pane(m, NULL, NULL);
730 else
731 wp = w->active;
732 if (wp != NULL)
733 window_pane_key(wp, c, s, key, m);
734 }
735
736 /* Client functions that need to happen every loop. */
737 void
server_client_loop(void)738 server_client_loop(void)
739 {
740 struct client *c;
741 struct window *w;
742 struct window_pane *wp;
743 #ifdef TMATE
744 int tmate_should_sync_layout = 0;
745 #endif
746
747 TAILQ_FOREACH(c, &clients, entry) {
748 server_client_check_exit(c);
749 if (c->session != NULL) {
750 server_client_check_redraw(c);
751 server_client_reset_state(c);
752 }
753 }
754
755 /*
756 * Any windows will have been redrawn as part of clients, so clear
757 * their flags now. Also check pane focus and resize.
758 */
759 RB_FOREACH(w, windows, &windows) {
760 #ifdef TMATE
761 if (w->flags & WINDOW_REDRAW)
762 tmate_should_sync_layout = 1;
763 if (w->tmate_last_sync_active_pane != w->active)
764 tmate_should_sync_layout = 1;
765 #endif
766
767 w->flags &= ~WINDOW_REDRAW;
768 TAILQ_FOREACH(wp, &w->panes, entry) {
769 if (wp->fd != -1) {
770 server_client_check_focus(wp);
771 server_client_check_resize(wp);
772 }
773 wp->flags &= ~PANE_REDRAW;
774 }
775 check_window_name(w);
776 }
777
778 #ifdef TMATE
779 if (tmate_should_sync_layout)
780 tmate_sync_layout();
781 #endif
782 }
783
784 /* Check if pane should be resized. */
785 void
server_client_check_resize(struct window_pane * wp)786 server_client_check_resize(struct window_pane *wp)
787 {
788 struct winsize ws;
789
790 if (!(wp->flags & PANE_RESIZE))
791 return;
792
793 memset(&ws, 0, sizeof ws);
794 ws.ws_col = wp->sx;
795 ws.ws_row = wp->sy;
796
797 if (ioctl(wp->fd, TIOCSWINSZ, &ws) == -1) {
798 #ifdef __sun
799 /*
800 * Some versions of Solaris apparently can return an error when
801 * resizing; don't know why this happens, can't reproduce on
802 * other platforms and ignoring it doesn't seem to cause any
803 * issues.
804 */
805 if (errno != EINVAL && errno != ENXIO)
806 #endif
807 fatal("ioctl failed");
808 }
809
810 wp->flags &= ~PANE_RESIZE;
811 }
812
813 /* Check whether pane should be focused. */
814 void
server_client_check_focus(struct window_pane * wp)815 server_client_check_focus(struct window_pane *wp)
816 {
817 struct client *c;
818 int push;
819
820 /* Are focus events off? */
821 if (!options_get_number(global_options, "focus-events"))
822 return;
823
824 /* Do we need to push the focus state? */
825 push = wp->flags & PANE_FOCUSPUSH;
826 wp->flags &= ~PANE_FOCUSPUSH;
827
828 /* If we don't care about focus, forget it. */
829 if (!(wp->base.mode & MODE_FOCUSON))
830 return;
831
832 /* If we're not the active pane in our window, we're not focused. */
833 if (wp->window->active != wp)
834 goto not_focused;
835
836 /* If we're in a mode, we're not focused. */
837 if (wp->screen != &wp->base)
838 goto not_focused;
839
840 /*
841 * If our window is the current window in any focused clients with an
842 * attached session, we're focused.
843 */
844 TAILQ_FOREACH(c, &clients, entry) {
845 if (c->session == NULL || !(c->flags & CLIENT_FOCUSED))
846 continue;
847 if (c->session->flags & SESSION_UNATTACHED)
848 continue;
849
850 if (c->session->curw->window == wp->window)
851 goto focused;
852 }
853
854 not_focused:
855 if (push || (wp->flags & PANE_FOCUSED))
856 bufferevent_write(wp->event, "\033[O", 3);
857 wp->flags &= ~PANE_FOCUSED;
858 return;
859
860 focused:
861 if (push || !(wp->flags & PANE_FOCUSED))
862 bufferevent_write(wp->event, "\033[I", 3);
863 wp->flags |= PANE_FOCUSED;
864 }
865
866 /*
867 * Update cursor position and mode settings. The scroll region and attributes
868 * are cleared when idle (waiting for an event) as this is the most likely time
869 * a user may interrupt tmux, for example with ~^Z in ssh(1). This is a
870 * compromise between excessive resets and likelihood of an interrupt.
871 *
872 * tty_region/tty_reset/tty_update_mode already take care of not resetting
873 * things that are already in their default state.
874 */
875 void
server_client_reset_state(struct client * c)876 server_client_reset_state(struct client *c)
877 {
878 struct window *w = c->session->curw->window;
879 struct window_pane *wp = w->active;
880 struct screen *s = wp->screen;
881 struct options *oo = c->session->options;
882 int status, mode, o;
883
884 if (c->flags & CLIENT_SUSPENDED)
885 return;
886
887 if (c->flags & CLIENT_CONTROL)
888 return;
889
890 tty_region(&c->tty, 0, c->tty.sy - 1);
891
892 status = options_get_number(oo, "status");
893 #ifdef TMATE
894 if (c->flags & CLIENT_FORCE_STATUS)
895 status = 1;
896 #endif
897 if (!window_pane_visible(wp) || wp->yoff + s->cy >= c->tty.sy - status)
898 tty_cursor(&c->tty, 0, 0);
899 else {
900 o = status && options_get_number(oo, "status-position") == 0;
901 tty_cursor(&c->tty, wp->xoff + s->cx, o + wp->yoff + s->cy);
902 }
903
904 /*
905 * Set mouse mode if requested. To support dragging, always use button
906 * mode.
907 */
908 mode = s->mode;
909 if (options_get_number(oo, "mouse"))
910 mode = (mode & ~ALL_MOUSE_MODES) | MODE_MOUSE_BUTTON;
911
912 /* Set the terminal mode and reset attributes. */
913 tty_update_mode(&c->tty, mode, s);
914 tty_reset(&c->tty);
915 }
916
917 /* Repeat time callback. */
918 void
server_client_repeat_timer(__unused int fd,__unused short events,void * data)919 server_client_repeat_timer(__unused int fd, __unused short events, void *data)
920 {
921 struct client *c = data;
922
923 if (c->flags & CLIENT_REPEAT) {
924 server_client_set_key_table(c, NULL);
925 c->flags &= ~CLIENT_REPEAT;
926 server_status_client(c);
927 }
928 }
929
930 /* Check if client should be exited. */
931 void
server_client_check_exit(struct client * c)932 server_client_check_exit(struct client *c)
933 {
934 if (!(c->flags & CLIENT_EXIT))
935 return;
936
937 if (EVBUFFER_LENGTH(c->stdin_data) != 0)
938 return;
939 if (EVBUFFER_LENGTH(c->stdout_data) != 0)
940 return;
941 if (EVBUFFER_LENGTH(c->stderr_data) != 0)
942 return;
943
944 proc_send(c->peer, MSG_EXIT, -1, &c->retval, sizeof c->retval);
945 c->flags &= ~CLIENT_EXIT;
946 }
947
948 /* Check for client redraws. */
949 void
server_client_check_redraw(struct client * c)950 server_client_check_redraw(struct client *c)
951 {
952 struct session *s = c->session;
953 struct tty *tty = &c->tty;
954 struct window_pane *wp;
955 int flags, redraw;
956
957 if (c->flags & (CLIENT_CONTROL|CLIENT_SUSPENDED))
958 return;
959
960 if (c->flags & (CLIENT_REDRAW|CLIENT_STATUS)) {
961 if (options_get_number(s->options, "set-titles"))
962 server_client_set_title(c);
963
964 if (c->message_string != NULL)
965 redraw = status_message_redraw(c);
966 else if (c->prompt_string != NULL)
967 redraw = status_prompt_redraw(c);
968 else
969 redraw = status_redraw(c);
970 if (!redraw)
971 c->flags &= ~CLIENT_STATUS;
972 }
973
974 flags = tty->flags & (TTY_FREEZE|TTY_NOCURSOR);
975 tty->flags = (tty->flags & ~TTY_FREEZE) | TTY_NOCURSOR;
976
977 if (c->flags & CLIENT_REDRAW) {
978 tty_update_mode(tty, tty->mode, NULL);
979 screen_redraw_screen(c, 1, 1, 1);
980 c->flags &= ~(CLIENT_STATUS|CLIENT_BORDERS);
981 } else if (c->flags & CLIENT_REDRAWWINDOW) {
982 tty_update_mode(tty, tty->mode, NULL);
983 TAILQ_FOREACH(wp, &c->session->curw->window->panes, entry)
984 screen_redraw_pane(c, wp);
985 c->flags &= ~CLIENT_REDRAWWINDOW;
986 } else {
987 TAILQ_FOREACH(wp, &c->session->curw->window->panes, entry) {
988 if (wp->flags & PANE_REDRAW) {
989 tty_update_mode(tty, tty->mode, NULL);
990 screen_redraw_pane(c, wp);
991 }
992 }
993 }
994
995 if (c->flags & CLIENT_BORDERS) {
996 tty_update_mode(tty, tty->mode, NULL);
997 screen_redraw_screen(c, 0, 0, 1);
998 }
999
1000 if (c->flags & CLIENT_STATUS) {
1001 tty_update_mode(tty, tty->mode, NULL);
1002 screen_redraw_screen(c, 0, 1, 0);
1003 }
1004
1005 tty->flags = (tty->flags & ~(TTY_FREEZE|TTY_NOCURSOR)) | flags;
1006 tty_update_mode(tty, tty->mode, NULL);
1007
1008 c->flags &= ~(CLIENT_REDRAW|CLIENT_BORDERS|CLIENT_STATUS|
1009 CLIENT_STATUSFORCE);
1010 }
1011
1012 /* Set client title. */
1013 void
server_client_set_title(struct client * c)1014 server_client_set_title(struct client *c)
1015 {
1016 struct session *s = c->session;
1017 const char *template;
1018 char *title;
1019 struct format_tree *ft;
1020
1021 template = options_get_string(s->options, "set-titles-string");
1022
1023 ft = format_create(NULL, 0);
1024 format_defaults(ft, c, NULL, NULL, NULL);
1025
1026 title = format_expand_time(ft, template, time(NULL));
1027 if (c->title == NULL || strcmp(title, c->title) != 0) {
1028 free(c->title);
1029 c->title = xstrdup(title);
1030 tty_set_title(&c->tty, c->title);
1031 }
1032 free(title);
1033
1034 format_free(ft);
1035 }
1036
1037 /* Dispatch message from client. */
1038 void
server_client_dispatch(struct imsg * imsg,void * arg)1039 server_client_dispatch(struct imsg *imsg, void *arg)
1040 {
1041 struct client *c = arg;
1042 struct msg_stdin_data stdindata;
1043 const char *data;
1044 ssize_t datalen;
1045 struct session *s;
1046
1047 if (c->flags & CLIENT_DEAD)
1048 return;
1049
1050 if (imsg == NULL) {
1051 server_client_lost(c);
1052 return;
1053 }
1054
1055 data = imsg->data;
1056 datalen = imsg->hdr.len - IMSG_HEADER_SIZE;
1057
1058 switch (imsg->hdr.type) {
1059 case MSG_IDENTIFY_FLAGS:
1060 case MSG_IDENTIFY_TERM:
1061 case MSG_IDENTIFY_TTYNAME:
1062 case MSG_IDENTIFY_CWD:
1063 case MSG_IDENTIFY_STDIN:
1064 case MSG_IDENTIFY_ENVIRON:
1065 case MSG_IDENTIFY_CLIENTPID:
1066 case MSG_IDENTIFY_DONE:
1067 server_client_dispatch_identify(c, imsg);
1068 break;
1069 case MSG_COMMAND:
1070 server_client_dispatch_command(c, imsg);
1071 break;
1072 case MSG_STDIN:
1073 if (datalen != sizeof stdindata)
1074 fatalx("bad MSG_STDIN size");
1075 memcpy(&stdindata, data, sizeof stdindata);
1076
1077 if (c->stdin_callback == NULL)
1078 break;
1079 if (stdindata.size <= 0)
1080 c->stdin_closed = 1;
1081 else {
1082 evbuffer_add(c->stdin_data, stdindata.data,
1083 stdindata.size);
1084 }
1085 c->stdin_callback(c, c->stdin_closed,
1086 c->stdin_callback_data);
1087 break;
1088 case MSG_RESIZE:
1089 if (datalen != 0)
1090 fatalx("bad MSG_RESIZE size");
1091
1092 if (c->flags & CLIENT_CONTROL)
1093 break;
1094 if (tty_resize(&c->tty)) {
1095 recalculate_sizes();
1096 server_redraw_client(c);
1097 }
1098 if (c->session != NULL)
1099 hooks_run(c->session->hooks, c, NULL, "client-resized");
1100 break;
1101 case MSG_EXITING:
1102 if (datalen != 0)
1103 fatalx("bad MSG_EXITING size");
1104
1105 c->session = NULL;
1106 tty_close(&c->tty);
1107 proc_send(c->peer, MSG_EXITED, -1, NULL, 0);
1108 break;
1109 case MSG_WAKEUP:
1110 case MSG_UNLOCK:
1111 if (datalen != 0)
1112 fatalx("bad MSG_WAKEUP size");
1113
1114 if (!(c->flags & CLIENT_SUSPENDED))
1115 break;
1116 c->flags &= ~CLIENT_SUSPENDED;
1117
1118 if (c->tty.fd == -1) /* exited in the meantime */
1119 break;
1120 s = c->session;
1121
1122 if (gettimeofday(&c->activity_time, NULL) != 0)
1123 fatal("gettimeofday failed");
1124 if (s != NULL)
1125 session_update_activity(s, &c->activity_time);
1126
1127 tty_start_tty(&c->tty);
1128 server_redraw_client(c);
1129 recalculate_sizes();
1130 break;
1131 case MSG_SHELL:
1132 if (datalen != 0)
1133 fatalx("bad MSG_SHELL size");
1134
1135 server_client_dispatch_shell(c);
1136 break;
1137 }
1138 }
1139
1140 /* Handle command message. */
1141 void
server_client_dispatch_command(struct client * c,struct imsg * imsg)1142 server_client_dispatch_command(struct client *c, struct imsg *imsg)
1143 {
1144 struct msg_command_data data;
1145 char *buf;
1146 size_t len;
1147 struct cmd_list *cmdlist = NULL;
1148 int argc;
1149 char **argv, *cause;
1150
1151 if (imsg->hdr.len - IMSG_HEADER_SIZE < sizeof data)
1152 fatalx("bad MSG_COMMAND size");
1153 memcpy(&data, imsg->data, sizeof data);
1154
1155 buf = (char *)imsg->data + sizeof data;
1156 len = imsg->hdr.len - IMSG_HEADER_SIZE - sizeof data;
1157 if (len > 0 && buf[len - 1] != '\0')
1158 fatalx("bad MSG_COMMAND string");
1159
1160 argc = data.argc;
1161 if (cmd_unpack_argv(buf, len, argc, &argv) != 0) {
1162 cmdq_error(c->cmdq, "command too long");
1163 goto error;
1164 }
1165
1166 if (argc == 0) {
1167 argc = 1;
1168 argv = xcalloc(1, sizeof *argv);
1169 *argv = xstrdup("new-session");
1170 }
1171
1172 if ((cmdlist = cmd_list_parse(argc, argv, NULL, 0, &cause)) == NULL) {
1173 cmdq_error(c->cmdq, "%s", cause);
1174 cmd_free_argv(argc, argv);
1175 goto error;
1176 }
1177 cmd_free_argv(argc, argv);
1178
1179 if (c != cfg_client || cfg_finished)
1180 cmdq_run(c->cmdq, cmdlist, NULL);
1181 else
1182 cmdq_append(c->cmdq, cmdlist, NULL);
1183 cmd_list_free(cmdlist);
1184 return;
1185
1186 error:
1187 if (cmdlist != NULL)
1188 cmd_list_free(cmdlist);
1189
1190 c->flags |= CLIENT_EXIT;
1191 }
1192
1193 /* Handle identify message. */
1194 void
server_client_dispatch_identify(struct client * c,struct imsg * imsg)1195 server_client_dispatch_identify(struct client *c, struct imsg *imsg)
1196 {
1197 const char *data, *home;
1198 size_t datalen;
1199 int flags;
1200
1201 if (c->flags & CLIENT_IDENTIFIED)
1202 fatalx("out-of-order identify message");
1203
1204 data = imsg->data;
1205 datalen = imsg->hdr.len - IMSG_HEADER_SIZE;
1206
1207 switch (imsg->hdr.type) {
1208 case MSG_IDENTIFY_FLAGS:
1209 if (datalen != sizeof flags)
1210 fatalx("bad MSG_IDENTIFY_FLAGS size");
1211 memcpy(&flags, data, sizeof flags);
1212 c->flags |= flags;
1213 log_debug("client %p IDENTIFY_FLAGS %#x", c, flags);
1214 break;
1215 case MSG_IDENTIFY_TERM:
1216 if (datalen == 0 || data[datalen - 1] != '\0')
1217 fatalx("bad MSG_IDENTIFY_TERM string");
1218 c->term = xstrdup(data);
1219 log_debug("client %p IDENTIFY_TERM %s", c, data);
1220 break;
1221 case MSG_IDENTIFY_TTYNAME:
1222 if (datalen == 0 || data[datalen - 1] != '\0')
1223 fatalx("bad MSG_IDENTIFY_TTYNAME string");
1224 c->ttyname = xstrdup(data);
1225 log_debug("client %p IDENTIFY_TTYNAME %s", c, data);
1226 break;
1227 case MSG_IDENTIFY_CWD:
1228 if (datalen == 0 || data[datalen - 1] != '\0')
1229 fatalx("bad MSG_IDENTIFY_CWD string");
1230 if (access(data, X_OK) == 0)
1231 c->cwd = xstrdup(data);
1232 else if ((home = find_home()) != NULL)
1233 c->cwd = xstrdup(home);
1234 else
1235 c->cwd = xstrdup("/");
1236 log_debug("client %p IDENTIFY_CWD %s", c, data);
1237 break;
1238 case MSG_IDENTIFY_STDIN:
1239 if (datalen != 0)
1240 fatalx("bad MSG_IDENTIFY_STDIN size");
1241 c->fd = imsg->fd;
1242 log_debug("client %p IDENTIFY_STDIN %d", c, imsg->fd);
1243 break;
1244 case MSG_IDENTIFY_ENVIRON:
1245 if (datalen == 0 || data[datalen - 1] != '\0')
1246 fatalx("bad MSG_IDENTIFY_ENVIRON string");
1247 if (strchr(data, '=') != NULL)
1248 environ_put(c->environ, data);
1249 log_debug("client %p IDENTIFY_ENVIRON %s", c, data);
1250 break;
1251 case MSG_IDENTIFY_CLIENTPID:
1252 if (datalen != sizeof c->pid)
1253 fatalx("bad MSG_IDENTIFY_CLIENTPID size");
1254 memcpy(&c->pid, data, sizeof c->pid);
1255 log_debug("client %p IDENTIFY_CLIENTPID %ld", c, (long)c->pid);
1256 break;
1257 default:
1258 break;
1259 }
1260
1261 if (imsg->hdr.type != MSG_IDENTIFY_DONE)
1262 return;
1263 c->flags |= CLIENT_IDENTIFIED;
1264
1265 #ifdef __CYGWIN__
1266 c->fd = open(c->ttyname, O_RDWR|O_NOCTTY);
1267 #endif
1268
1269 if (c->flags & CLIENT_CONTROL) {
1270 c->stdin_callback = control_callback;
1271
1272 evbuffer_free(c->stderr_data);
1273 c->stderr_data = c->stdout_data;
1274
1275 if (c->flags & CLIENT_CONTROLCONTROL)
1276 evbuffer_add_printf(c->stdout_data, "\033P1000p");
1277 proc_send(c->peer, MSG_STDIN, -1, NULL, 0);
1278
1279 c->tty.fd = -1;
1280
1281 close(c->fd);
1282 c->fd = -1;
1283
1284 return;
1285 }
1286
1287 if (c->fd == -1)
1288 return;
1289 if (tty_init(&c->tty, c, c->fd, c->term) != 0) {
1290 close(c->fd);
1291 c->fd = -1;
1292 return;
1293 }
1294 if (c->flags & CLIENT_UTF8)
1295 c->tty.flags |= TTY_UTF8;
1296 if (c->flags & CLIENT_256COLOURS)
1297 c->tty.term_flags |= TERM_256COLOURS;
1298
1299 tty_resize(&c->tty);
1300
1301 if (!(c->flags & CLIENT_CONTROL))
1302 c->flags |= CLIENT_TERMINAL;
1303 }
1304
1305 /* Handle shell message. */
1306 void
server_client_dispatch_shell(struct client * c)1307 server_client_dispatch_shell(struct client *c)
1308 {
1309 const char *shell;
1310
1311 shell = options_get_string(global_s_options, "default-shell");
1312 if (*shell == '\0' || areshell(shell))
1313 shell = _PATH_BSHELL;
1314 proc_send_s(c->peer, MSG_SHELL, shell);
1315
1316 proc_kill_peer(c->peer);
1317 }
1318
1319 /* Event callback to push more stdout data if any left. */
1320 static void
server_client_stdout_cb(__unused int fd,__unused short events,void * arg)1321 server_client_stdout_cb(__unused int fd, __unused short events, void *arg)
1322 {
1323 struct client *c = arg;
1324
1325 if (~c->flags & CLIENT_DEAD)
1326 server_client_push_stdout(c);
1327 server_client_unref(c);
1328 }
1329
1330 /* Push stdout to client if possible. */
1331 void
server_client_push_stdout(struct client * c)1332 server_client_push_stdout(struct client *c)
1333 {
1334 struct msg_stdout_data data;
1335 size_t sent, left;
1336
1337 left = EVBUFFER_LENGTH(c->stdout_data);
1338 while (left != 0) {
1339 sent = left;
1340 if (sent > sizeof data.data)
1341 sent = sizeof data.data;
1342 memcpy(data.data, EVBUFFER_DATA(c->stdout_data), sent);
1343 data.size = sent;
1344
1345 if (proc_send(c->peer, MSG_STDOUT, -1, &data, sizeof data) != 0)
1346 break;
1347 evbuffer_drain(c->stdout_data, sent);
1348
1349 left = EVBUFFER_LENGTH(c->stdout_data);
1350 log_debug("%s: client %p, sent %zu, left %zu", __func__, c,
1351 sent, left);
1352 }
1353 if (left != 0) {
1354 c->references++;
1355 event_once(-1, EV_TIMEOUT, server_client_stdout_cb, c, NULL);
1356 log_debug("%s: client %p, queued", __func__, c);
1357 }
1358 }
1359
1360 /* Event callback to push more stderr data if any left. */
1361 static void
server_client_stderr_cb(__unused int fd,__unused short events,void * arg)1362 server_client_stderr_cb(__unused int fd, __unused short events, void *arg)
1363 {
1364 struct client *c = arg;
1365
1366 if (~c->flags & CLIENT_DEAD)
1367 server_client_push_stderr(c);
1368 server_client_unref(c);
1369 }
1370
1371 /* Push stderr to client if possible. */
1372 void
server_client_push_stderr(struct client * c)1373 server_client_push_stderr(struct client *c)
1374 {
1375 struct msg_stderr_data data;
1376 size_t sent, left;
1377
1378 if (c->stderr_data == c->stdout_data) {
1379 server_client_push_stdout(c);
1380 return;
1381 }
1382
1383 left = EVBUFFER_LENGTH(c->stderr_data);
1384 while (left != 0) {
1385 sent = left;
1386 if (sent > sizeof data.data)
1387 sent = sizeof data.data;
1388 memcpy(data.data, EVBUFFER_DATA(c->stderr_data), sent);
1389 data.size = sent;
1390
1391 if (proc_send(c->peer, MSG_STDERR, -1, &data, sizeof data) != 0)
1392 break;
1393 evbuffer_drain(c->stderr_data, sent);
1394
1395 left = EVBUFFER_LENGTH(c->stderr_data);
1396 log_debug("%s: client %p, sent %zu, left %zu", __func__, c,
1397 sent, left);
1398 }
1399 if (left != 0) {
1400 c->references++;
1401 event_once(-1, EV_TIMEOUT, server_client_stderr_cb, c, NULL);
1402 log_debug("%s: client %p, queued", __func__, c);
1403 }
1404 }
1405