xref: /openbsd-src/usr.bin/tmux/server-client.c (revision aa5e9e10509ffd51558f081f01cd78bfa3c4f2a5)
1 /* $OpenBSD: server-client.c,v 1.101 2013/04/21 21:32:00 nicm Exp $ */
2 
3 /*
4  * Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
5  *
6  * Permission to use, copy, modify, and distribute this software for any
7  * purpose with or without fee is hereby granted, provided that the above
8  * copyright notice and this permission notice appear in all copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14  * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
15  * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
16  * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17  */
18 
19 #include <sys/types.h>
20 #include <sys/ioctl.h>
21 
22 #include <event.h>
23 #include <fcntl.h>
24 #include <paths.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <time.h>
28 #include <unistd.h>
29 
30 #include "tmux.h"
31 
32 void	server_client_check_focus(struct window_pane *);
33 void	server_client_check_resize(struct window_pane *);
34 void	server_client_check_mouse(struct client *, struct window_pane *);
35 void	server_client_repeat_timer(int, short, void *);
36 void	server_client_check_exit(struct client *);
37 void	server_client_check_redraw(struct client *);
38 void	server_client_set_title(struct client *);
39 void	server_client_reset_state(struct client *);
40 int	server_client_assume_paste(struct session *);
41 
42 int	server_client_msg_dispatch(struct client *);
43 void	server_client_msg_command(struct client *, struct msg_command_data *);
44 void	server_client_msg_identify(
45 	    struct client *, struct msg_identify_data *, int);
46 void	server_client_msg_shell(struct client *);
47 
48 /* Create a new client. */
49 void
50 server_client_create(int fd)
51 {
52 	struct client	*c;
53 	u_int		 i;
54 
55 	setblocking(fd, 0);
56 
57 	c = xcalloc(1, sizeof *c);
58 	c->references = 0;
59 	imsg_init(&c->ibuf, fd);
60 	server_update_event(c);
61 
62 	if (gettimeofday(&c->creation_time, NULL) != 0)
63 		fatal("gettimeofday failed");
64 	memcpy(&c->activity_time, &c->creation_time, sizeof c->activity_time);
65 
66 	c->cmdq = cmdq_new(c);
67 	c->cmdq->client_exit = 1;
68 
69 	c->stdin_data = evbuffer_new ();
70 	c->stdout_data = evbuffer_new ();
71 	c->stderr_data = evbuffer_new ();
72 
73 	c->tty.fd = -1;
74 	c->title = NULL;
75 
76 	c->session = NULL;
77 	c->last_session = NULL;
78 	c->tty.sx = 80;
79 	c->tty.sy = 24;
80 
81 	screen_init(&c->status, c->tty.sx, 1, 0);
82 	RB_INIT(&c->status_new);
83 	RB_INIT(&c->status_old);
84 
85 	c->message_string = NULL;
86 	ARRAY_INIT(&c->message_log);
87 
88 	c->prompt_string = NULL;
89 	c->prompt_buffer = NULL;
90 	c->prompt_index = 0;
91 
92 	c->tty.mouse.xb = c->tty.mouse.button = 3;
93 	c->tty.mouse.x = c->tty.mouse.y = -1;
94 	c->tty.mouse.lx = c->tty.mouse.ly = -1;
95 	c->tty.mouse.sx = c->tty.mouse.sy = -1;
96 	c->tty.mouse.event = MOUSE_EVENT_UP;
97 	c->tty.mouse.flags = 0;
98 
99 	c->flags |= CLIENT_FOCUSED;
100 
101 	evtimer_set(&c->repeat_timer, server_client_repeat_timer, c);
102 
103 	for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
104 		if (ARRAY_ITEM(&clients, i) == NULL) {
105 			ARRAY_SET(&clients, i, c);
106 			return;
107 		}
108 	}
109 	ARRAY_ADD(&clients, c);
110 	log_debug("new client %d", fd);
111 }
112 
113 /* Open client terminal if needed. */
114 int
115 server_client_open(struct client *c, struct session *s, char **cause)
116 {
117 	struct options	*oo = s != NULL ? &s->options : &global_s_options;
118 	char		*overrides;
119 
120 	if (c->flags & CLIENT_CONTROL)
121 		return (0);
122 
123 	if (!(c->flags & CLIENT_TERMINAL)) {
124 		*cause = xstrdup ("not a terminal");
125 		return (-1);
126 	}
127 
128 	overrides = options_get_string(oo, "terminal-overrides");
129 	if (tty_open(&c->tty, overrides, cause) != 0)
130 		return (-1);
131 
132 	return (0);
133 }
134 
135 /* Lost a client. */
136 void
137 server_client_lost(struct client *c)
138 {
139 	struct message_entry	*msg;
140 	u_int			 i;
141 
142 	for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
143 		if (ARRAY_ITEM(&clients, i) == c)
144 			ARRAY_SET(&clients, i, NULL);
145 	}
146 	log_debug("lost client %d", c->ibuf.fd);
147 
148 	/*
149 	 * If CLIENT_TERMINAL hasn't been set, then tty_init hasn't been called
150 	 * and tty_free might close an unrelated fd.
151 	 */
152 	if (c->flags & CLIENT_TERMINAL)
153 		tty_free(&c->tty);
154 
155 	evbuffer_free (c->stdin_data);
156 	evbuffer_free (c->stdout_data);
157 	if (c->stderr_data != c->stdout_data)
158 		evbuffer_free (c->stderr_data);
159 
160 	status_free_jobs(&c->status_new);
161 	status_free_jobs(&c->status_old);
162 	screen_free(&c->status);
163 
164 	free(c->title);
165 
166 	evtimer_del(&c->repeat_timer);
167 
168 	if (event_initialized(&c->identify_timer))
169 		evtimer_del(&c->identify_timer);
170 
171 	free(c->message_string);
172 	if (event_initialized (&c->message_timer))
173 		evtimer_del(&c->message_timer);
174 	for (i = 0; i < ARRAY_LENGTH(&c->message_log); i++) {
175 		msg = &ARRAY_ITEM(&c->message_log, i);
176 		free(msg->msg);
177 	}
178 	ARRAY_FREE(&c->message_log);
179 
180 	free(c->prompt_string);
181 	free(c->prompt_buffer);
182 	free(c->cwd);
183 
184 	c->cmdq->dead = 1;
185 	cmdq_free(c->cmdq);
186 	c->cmdq = NULL;
187 
188 	environ_free(&c->environ);
189 
190 	close(c->ibuf.fd);
191 	imsg_clear(&c->ibuf);
192 	if (event_initialized(&c->event))
193 		event_del(&c->event);
194 
195 	for (i = 0; i < ARRAY_LENGTH(&dead_clients); i++) {
196 		if (ARRAY_ITEM(&dead_clients, i) == NULL) {
197 			ARRAY_SET(&dead_clients, i, c);
198 			break;
199 		}
200 	}
201 	if (i == ARRAY_LENGTH(&dead_clients))
202 		ARRAY_ADD(&dead_clients, c);
203 	c->flags |= CLIENT_DEAD;
204 
205 	server_add_accept(0); /* may be more file descriptors now */
206 
207 	recalculate_sizes();
208 	server_check_unattached();
209 	server_update_socket();
210 }
211 
212 /* Process a single client event. */
213 void
214 server_client_callback(int fd, short events, void *data)
215 {
216 	struct client	*c = data;
217 
218 	if (c->flags & CLIENT_DEAD)
219 		return;
220 
221 	if (fd == c->ibuf.fd) {
222 		if (events & EV_WRITE && msgbuf_write(&c->ibuf.w) < 0)
223 			goto client_lost;
224 
225 		if (c->flags & CLIENT_BAD) {
226 			if (c->ibuf.w.queued == 0)
227 				goto client_lost;
228 			return;
229 		}
230 
231 		if (events & EV_READ && server_client_msg_dispatch(c) != 0)
232 			goto client_lost;
233 	}
234 
235 	server_push_stdout(c);
236 	server_push_stderr(c);
237 
238 	server_update_event(c);
239 	return;
240 
241 client_lost:
242 	server_client_lost(c);
243 }
244 
245 /* Handle client status timer. */
246 void
247 server_client_status_timer(void)
248 {
249 	struct client	*c;
250 	struct session	*s;
251 	struct timeval	 tv;
252 	u_int		 i;
253 	int		 interval;
254 	time_t		 difference;
255 
256 	if (gettimeofday(&tv, NULL) != 0)
257 		fatal("gettimeofday failed");
258 
259 	for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
260 		c = ARRAY_ITEM(&clients, i);
261 		if (c == NULL || c->session == NULL)
262 			continue;
263 		if (c->message_string != NULL || c->prompt_string != NULL) {
264 			/*
265 			 * Don't need timed redraw for messages/prompts so bail
266 			 * now. The status timer isn't reset when they are
267 			 * redrawn anyway.
268 			 */
269 			continue;
270 		}
271 		s = c->session;
272 
273 		if (!options_get_number(&s->options, "status"))
274 			continue;
275 		interval = options_get_number(&s->options, "status-interval");
276 
277 		difference = tv.tv_sec - c->status_timer.tv_sec;
278 		if (difference >= interval) {
279 			status_update_jobs(c);
280 			c->flags |= CLIENT_STATUS;
281 		}
282 	}
283 }
284 
285 /* Check for mouse keys. */
286 void
287 server_client_check_mouse(struct client *c, struct window_pane *wp)
288 {
289 	struct session		*s = c->session;
290 	struct options		*oo = &s->options;
291 	struct mouse_event	*m = &c->tty.mouse;
292 	int			 statusat;
293 
294 	statusat = status_at_line(c);
295 
296 	/* Is this a window selection click on the status line? */
297 	if (statusat != -1 && m->y == (u_int)statusat &&
298 	    options_get_number(oo, "mouse-select-window")) {
299 		if (m->event & MOUSE_EVENT_CLICK) {
300 			status_set_window_at(c, m->x);
301 		} else if (m->event == MOUSE_EVENT_WHEEL) {
302 			if (m->wheel == MOUSE_WHEEL_UP)
303 				session_previous(c->session, 0);
304 			else if (m->wheel == MOUSE_WHEEL_DOWN)
305 				session_next(c->session, 0);
306 			server_redraw_session(s);
307 		}
308 		recalculate_sizes();
309 		return;
310 	}
311 
312 	/*
313 	 * Not on status line - adjust mouse position if status line is at the
314 	 * top and limit if at the bottom. From here on a struct mouse
315 	 * represents the offset onto the window itself.
316 	 */
317 	if (statusat == 0 && m->y > 0)
318 		m->y--;
319 	else if (statusat > 0 && m->y >= (u_int)statusat)
320 		m->y = statusat - 1;
321 
322 	/* Is this a pane selection? Allow down only in copy mode. */
323 	if (options_get_number(oo, "mouse-select-pane") &&
324 	    (m->event == MOUSE_EVENT_DOWN || wp->mode != &window_copy_mode)) {
325 		window_set_active_at(wp->window, m->x, m->y);
326 		server_redraw_window_borders(wp->window);
327 		wp = wp->window->active; /* may have changed */
328 	}
329 
330 	/* Check if trying to resize pane. */
331 	if (options_get_number(oo, "mouse-resize-pane"))
332 		layout_resize_pane_mouse(c);
333 
334 	/* Update last and pass through to client. */
335 	window_pane_mouse(wp, c->session, m);
336 }
337 
338 /* Is this fast enough to probably be a paste? */
339 int
340 server_client_assume_paste(struct session *s)
341 {
342 	struct timeval	tv;
343 	int		t;
344 
345 	if ((t = options_get_number(&s->options, "assume-paste-time")) == 0)
346 		return (0);
347 
348 	timersub(&s->activity_time, &s->last_activity_time, &tv);
349 	if (tv.tv_sec == 0 && tv.tv_usec < t * 1000)
350 		return (1);
351 	return (0);
352 }
353 
354 /* Handle data key input from client. */
355 void
356 server_client_handle_key(struct client *c, int key)
357 {
358 	struct session		*s;
359 	struct window		*w;
360 	struct window_pane	*wp;
361 	struct timeval		 tv;
362 	struct key_binding	*bd;
363 	int		      	 xtimeout, isprefix, ispaste;
364 
365 	/* Check the client is good to accept input. */
366 	if ((c->flags & (CLIENT_DEAD|CLIENT_SUSPENDED)) != 0)
367 		return;
368 
369 	if (c->session == NULL)
370 		return;
371 	s = c->session;
372 
373 	/* Update the activity timer. */
374 	if (gettimeofday(&c->activity_time, NULL) != 0)
375 		fatal("gettimeofday failed");
376 
377 	memcpy(&s->last_activity_time, &s->activity_time,
378 	    sizeof s->last_activity_time);
379 	memcpy(&s->activity_time, &c->activity_time, sizeof s->activity_time);
380 
381 	w = c->session->curw->window;
382 	wp = w->active;
383 
384 	/* Special case: number keys jump to pane in identify mode. */
385 	if (c->flags & CLIENT_IDENTIFY && key >= '0' && key <= '9') {
386 		if (c->flags & CLIENT_READONLY)
387 			return;
388 		window_unzoom(w);
389 		wp = window_pane_at_index(w, key - '0');
390 		if (wp != NULL && window_pane_visible(wp))
391 			window_set_active_pane(w, wp);
392 		server_clear_identify(c);
393 		return;
394 	}
395 
396 	/* Handle status line. */
397 	if (!(c->flags & CLIENT_READONLY)) {
398 		status_message_clear(c);
399 		server_clear_identify(c);
400 	}
401 	if (c->prompt_string != NULL) {
402 		if (!(c->flags & CLIENT_READONLY))
403 			status_prompt_key(c, key);
404 		return;
405 	}
406 
407 	/* Check for mouse keys. */
408 	if (key == KEYC_MOUSE) {
409 		if (c->flags & CLIENT_READONLY)
410 			return;
411 		server_client_check_mouse(c, wp);
412 		return;
413 	}
414 
415 	/* Is this a prefix key? */
416 	if (key == options_get_number(&s->options, "prefix"))
417 		isprefix = 1;
418 	else if (key == options_get_number(&s->options, "prefix2"))
419 		isprefix = 1;
420 	else
421 		isprefix = 0;
422 
423 	/* Treat prefix as a regular key when pasting is detected. */
424 	ispaste = server_client_assume_paste(s);
425 	if (ispaste)
426 		isprefix = 0;
427 
428 	/* No previous prefix key. */
429 	if (!(c->flags & CLIENT_PREFIX)) {
430 		if (isprefix) {
431 			c->flags |= CLIENT_PREFIX;
432 			server_status_client(c);
433 			return;
434 		}
435 
436 		/* Try as a non-prefix key binding. */
437 		if (ispaste || (bd = key_bindings_lookup(key)) == NULL) {
438 			if (!(c->flags & CLIENT_READONLY))
439 				window_pane_key(wp, s, key);
440 		} else
441 			key_bindings_dispatch(bd, c);
442 		return;
443 	}
444 
445 	/* Prefix key already pressed. Reset prefix and lookup key. */
446 	c->flags &= ~CLIENT_PREFIX;
447 	server_status_client(c);
448 	if ((bd = key_bindings_lookup(key | KEYC_PREFIX)) == NULL) {
449 		/* If repeating, treat this as a key, else ignore. */
450 		if (c->flags & CLIENT_REPEAT) {
451 			c->flags &= ~CLIENT_REPEAT;
452 			if (isprefix)
453 				c->flags |= CLIENT_PREFIX;
454 			else if (!(c->flags & CLIENT_READONLY))
455 				window_pane_key(wp, s, key);
456 		}
457 		return;
458 	}
459 
460 	/* If already repeating, but this key can't repeat, skip it. */
461 	if (c->flags & CLIENT_REPEAT && !bd->can_repeat) {
462 		c->flags &= ~CLIENT_REPEAT;
463 		if (isprefix)
464 			c->flags |= CLIENT_PREFIX;
465 		else if (!(c->flags & CLIENT_READONLY))
466 			window_pane_key(wp, s, key);
467 		return;
468 	}
469 
470 	/* If this key can repeat, reset the repeat flags and timer. */
471 	xtimeout = options_get_number(&s->options, "repeat-time");
472 	if (xtimeout != 0 && bd->can_repeat) {
473 		c->flags |= CLIENT_PREFIX|CLIENT_REPEAT;
474 
475 		tv.tv_sec = xtimeout / 1000;
476 		tv.tv_usec = (xtimeout % 1000) * 1000L;
477 		evtimer_del(&c->repeat_timer);
478 		evtimer_add(&c->repeat_timer, &tv);
479 	}
480 
481 	/* Dispatch the command. */
482 	key_bindings_dispatch(bd, c);
483 }
484 
485 /* Client functions that need to happen every loop. */
486 void
487 server_client_loop(void)
488 {
489 	struct client		*c;
490 	struct window		*w;
491 	struct window_pane	*wp;
492 	u_int		 	 i;
493 
494 	for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
495 		c = ARRAY_ITEM(&clients, i);
496 		if (c == NULL)
497 			continue;
498 
499 		server_client_check_exit(c);
500 		if (c->session != NULL) {
501 			server_client_check_redraw(c);
502 			server_client_reset_state(c);
503 		}
504 	}
505 
506 	/*
507 	 * Any windows will have been redrawn as part of clients, so clear
508 	 * their flags now. Also check pane focus and resize.
509 	 */
510 	for (i = 0; i < ARRAY_LENGTH(&windows); i++) {
511 		w = ARRAY_ITEM(&windows, i);
512 		if (w == NULL)
513 			continue;
514 
515 		w->flags &= ~WINDOW_REDRAW;
516 		TAILQ_FOREACH(wp, &w->panes, entry) {
517 			if (wp->fd != -1) {
518 				server_client_check_focus(wp);
519 				server_client_check_resize(wp);
520 			}
521 			wp->flags &= ~PANE_REDRAW;
522 		}
523 	}
524 }
525 
526 /* Check if pane should be resized. */
527 void
528 server_client_check_resize(struct window_pane *wp)
529 {
530 	struct winsize	ws;
531 
532 	if (!(wp->flags & PANE_RESIZE))
533 		return;
534 
535 	memset(&ws, 0, sizeof ws);
536 	ws.ws_col = wp->sx;
537 	ws.ws_row = wp->sy;
538 
539 	if (ioctl(wp->fd, TIOCSWINSZ, &ws) == -1)
540 		fatal("ioctl failed");
541 
542 	wp->flags &= ~PANE_RESIZE;
543 }
544 
545 /* Check whether pane should be focused. */
546 void
547 server_client_check_focus(struct window_pane *wp)
548 {
549 	u_int		 i;
550 	struct client	*c;
551 
552 	/* If we don't care about focus, forget it. */
553 	if (!(wp->base.mode & MODE_FOCUSON))
554 		return;
555 
556 	/* If we're not the active pane in our window, we're not focused. */
557 	if (wp->window->active != wp)
558 		goto not_focused;
559 
560 	/* If we're in a mode, we're not focused. */
561 	if (wp->screen != &wp->base)
562 		goto not_focused;
563 
564 	/*
565 	 * If our window is the current window in any focused clients with an
566 	 * attached session, we're focused.
567 	 */
568 	for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
569 		c = ARRAY_ITEM(&clients, i);
570 		if (c == NULL || c->session == NULL)
571 			continue;
572 
573 		if (!(c->flags & CLIENT_FOCUSED))
574 			continue;
575 		if (c->session->flags & SESSION_UNATTACHED)
576 			continue;
577 
578 		if (c->session->curw->window == wp->window)
579 			goto focused;
580 	}
581 
582 not_focused:
583 	if (wp->flags & PANE_FOCUSED)
584 		bufferevent_write(wp->event, "\033[O", 3);
585 	wp->flags &= ~PANE_FOCUSED;
586 	return;
587 
588 focused:
589 	if (!(wp->flags & PANE_FOCUSED))
590 		bufferevent_write(wp->event, "\033[I", 3);
591 	wp->flags |= PANE_FOCUSED;
592 }
593 
594 /*
595  * Update cursor position and mode settings. The scroll region and attributes
596  * are cleared when idle (waiting for an event) as this is the most likely time
597  * a user may interrupt tmux, for example with ~^Z in ssh(1). This is a
598  * compromise between excessive resets and likelihood of an interrupt.
599  *
600  * tty_region/tty_reset/tty_update_mode already take care of not resetting
601  * things that are already in their default state.
602  */
603 void
604 server_client_reset_state(struct client *c)
605 {
606 	struct window		*w = c->session->curw->window;
607 	struct window_pane	*wp = w->active;
608 	struct screen		*s = wp->screen;
609 	struct options		*oo = &c->session->options;
610 	struct options		*wo = &w->options;
611 	int			 status, mode, o;
612 
613 	if (c->flags & CLIENT_SUSPENDED)
614 		return;
615 
616 	if (c->flags & CLIENT_CONTROL)
617 		return;
618 
619 	tty_region(&c->tty, 0, c->tty.sy - 1);
620 
621 	status = options_get_number(oo, "status");
622 	if (!window_pane_visible(wp) || wp->yoff + s->cy >= c->tty.sy - status)
623 		tty_cursor(&c->tty, 0, 0);
624 	else {
625 		o = status && options_get_number (oo, "status-position") == 0;
626 		tty_cursor(&c->tty, wp->xoff + s->cx, o + wp->yoff + s->cy);
627 	}
628 
629 	/*
630 	 * Resizing panes with the mouse requires at least button mode to give
631 	 * a smooth appearance.
632 	 */
633 	mode = s->mode;
634 	if ((c->tty.mouse.flags & MOUSE_RESIZE_PANE) &&
635 	    !(mode & (MODE_MOUSE_BUTTON|MODE_MOUSE_ANY)))
636 		mode |= MODE_MOUSE_BUTTON;
637 
638 	/*
639 	 * Any mode will do for mouse-select-pane, but set standard mode if
640 	 * none.
641 	 */
642 	if ((mode & ALL_MOUSE_MODES) == 0) {
643 		if (TAILQ_NEXT(TAILQ_FIRST(&w->panes), entry) != NULL &&
644 		    options_get_number(oo, "mouse-select-pane"))
645 			mode |= MODE_MOUSE_STANDARD;
646 		else if (options_get_number(oo, "mouse-resize-pane"))
647 			mode |= MODE_MOUSE_STANDARD;
648 		else if (options_get_number(oo, "mouse-select-window"))
649 			mode |= MODE_MOUSE_STANDARD;
650 		else if (options_get_number(wo, "mode-mouse"))
651 			mode |= MODE_MOUSE_STANDARD;
652 	}
653 
654 	/*
655 	 * Set UTF-8 mouse input if required. If the terminal is UTF-8, the
656 	 * user has set mouse-utf8 and any mouse mode is in effect, turn on
657 	 * UTF-8 mouse input. If the receiving terminal hasn't requested it
658 	 * (that is, it isn't in s->mode), then it'll be converted in
659 	 * input_mouse.
660 	 */
661 	if ((c->tty.flags & TTY_UTF8) &&
662 	    (mode & ALL_MOUSE_MODES) && options_get_number(oo, "mouse-utf8"))
663 		mode |= MODE_MOUSE_UTF8;
664 	else
665 		mode &= ~MODE_MOUSE_UTF8;
666 
667 	/* Set the terminal mode and reset attributes. */
668 	tty_update_mode(&c->tty, mode, s);
669 	tty_reset(&c->tty);
670 }
671 
672 /* Repeat time callback. */
673 void
674 server_client_repeat_timer(unused int fd, unused short events, void *data)
675 {
676 	struct client	*c = data;
677 
678 	if (c->flags & CLIENT_REPEAT) {
679 		if (c->flags & CLIENT_PREFIX)
680 			server_status_client(c);
681 		c->flags &= ~(CLIENT_PREFIX|CLIENT_REPEAT);
682 	}
683 }
684 
685 /* Check if client should be exited. */
686 void
687 server_client_check_exit(struct client *c)
688 {
689 	struct msg_exit_data	exitdata;
690 
691 	if (!(c->flags & CLIENT_EXIT))
692 		return;
693 
694 	if (EVBUFFER_LENGTH(c->stdin_data) != 0)
695 		return;
696 	if (EVBUFFER_LENGTH(c->stdout_data) != 0)
697 		return;
698 	if (EVBUFFER_LENGTH(c->stderr_data) != 0)
699 		return;
700 
701 	exitdata.retcode = c->retcode;
702 	server_write_client(c, MSG_EXIT, &exitdata, sizeof exitdata);
703 
704 	c->flags &= ~CLIENT_EXIT;
705 }
706 
707 /* Check for client redraws. */
708 void
709 server_client_check_redraw(struct client *c)
710 {
711 	struct session		*s = c->session;
712 	struct window_pane	*wp;
713 	int		 	 flags, redraw;
714 
715 	if (c->flags & (CLIENT_CONTROL|CLIENT_SUSPENDED))
716 		return;
717 
718 	flags = c->tty.flags & TTY_FREEZE;
719 	c->tty.flags &= ~TTY_FREEZE;
720 
721 	if (c->flags & (CLIENT_REDRAW|CLIENT_STATUS)) {
722 		if (options_get_number(&s->options, "set-titles"))
723 			server_client_set_title(c);
724 
725 		if (c->message_string != NULL)
726 			redraw = status_message_redraw(c);
727 		else if (c->prompt_string != NULL)
728 			redraw = status_prompt_redraw(c);
729 		else
730 			redraw = status_redraw(c);
731 		if (!redraw)
732 			c->flags &= ~CLIENT_STATUS;
733 	}
734 
735 	if (c->flags & CLIENT_REDRAW) {
736 		screen_redraw_screen(c, 0, 0);
737 		c->flags &= ~(CLIENT_STATUS|CLIENT_BORDERS);
738 	} else if (c->flags & CLIENT_REDRAWWINDOW) {
739 		TAILQ_FOREACH(wp, &c->session->curw->window->panes, entry)
740 			screen_redraw_pane(c, wp);
741 		c->flags &= ~CLIENT_REDRAWWINDOW;
742 	} else {
743 		TAILQ_FOREACH(wp, &c->session->curw->window->panes, entry) {
744 			if (wp->flags & PANE_REDRAW)
745 				screen_redraw_pane(c, wp);
746 		}
747 	}
748 
749 	if (c->flags & CLIENT_BORDERS)
750 		screen_redraw_screen(c, 0, 1);
751 
752 	if (c->flags & CLIENT_STATUS)
753 		screen_redraw_screen(c, 1, 0);
754 
755 	c->tty.flags |= flags;
756 
757 	c->flags &= ~(CLIENT_REDRAW|CLIENT_STATUS|CLIENT_BORDERS);
758 }
759 
760 /* Set client title. */
761 void
762 server_client_set_title(struct client *c)
763 {
764 	struct session	*s = c->session;
765 	const char	*template;
766 	char		*title;
767 
768 	template = options_get_string(&s->options, "set-titles-string");
769 
770 	title = status_replace(c, NULL, NULL, NULL, template, time(NULL), 1);
771 	if (c->title == NULL || strcmp(title, c->title) != 0) {
772 		free(c->title);
773 		c->title = xstrdup(title);
774 		tty_set_title(&c->tty, c->title);
775 	}
776 	free(title);
777 }
778 
779 /* Dispatch message from client. */
780 int
781 server_client_msg_dispatch(struct client *c)
782 {
783 	struct imsg		 imsg;
784 	struct msg_command_data	 commanddata;
785 	struct msg_identify_data identifydata;
786 	struct msg_environ_data	 environdata;
787 	struct msg_stdin_data	 stdindata;
788 	ssize_t			 n, datalen;
789 
790 	if ((n = imsg_read(&c->ibuf)) == -1 || n == 0)
791 		return (-1);
792 
793 	for (;;) {
794 		if ((n = imsg_get(&c->ibuf, &imsg)) == -1)
795 			return (-1);
796 		if (n == 0)
797 			return (0);
798 		datalen = imsg.hdr.len - IMSG_HEADER_SIZE;
799 
800 		if (imsg.hdr.peerid != PROTOCOL_VERSION) {
801 			server_write_client(c, MSG_VERSION, NULL, 0);
802 			c->flags |= CLIENT_BAD;
803 			imsg_free(&imsg);
804 			continue;
805 		}
806 
807 		log_debug("got %d from client %d", imsg.hdr.type, c->ibuf.fd);
808 		switch (imsg.hdr.type) {
809 		case MSG_COMMAND:
810 			if (datalen != sizeof commanddata)
811 				fatalx("bad MSG_COMMAND size");
812 			memcpy(&commanddata, imsg.data, sizeof commanddata);
813 
814 			server_client_msg_command(c, &commanddata);
815 			break;
816 		case MSG_IDENTIFY:
817 			if (datalen != sizeof identifydata)
818 				fatalx("bad MSG_IDENTIFY size");
819 			if (imsg.fd == -1)
820 				fatalx("MSG_IDENTIFY missing fd");
821 			memcpy(&identifydata, imsg.data, sizeof identifydata);
822 
823 			server_client_msg_identify(c, &identifydata, imsg.fd);
824 			break;
825 		case MSG_STDIN:
826 			if (datalen != sizeof stdindata)
827 				fatalx("bad MSG_STDIN size");
828 			memcpy(&stdindata, imsg.data, sizeof stdindata);
829 
830 			if (c->stdin_callback == NULL)
831 				break;
832 			if (stdindata.size <= 0)
833 				c->stdin_closed = 1;
834 			else {
835 				evbuffer_add(c->stdin_data, stdindata.data,
836 				    stdindata.size);
837 			}
838 			c->stdin_callback(c, c->stdin_closed,
839 			    c->stdin_callback_data);
840 			break;
841 		case MSG_RESIZE:
842 			if (datalen != 0)
843 				fatalx("bad MSG_RESIZE size");
844 
845 			if (c->flags & CLIENT_CONTROL)
846 				break;
847 			if (tty_resize(&c->tty)) {
848 				recalculate_sizes();
849 				server_redraw_client(c);
850 			}
851 			break;
852 		case MSG_EXITING:
853 			if (datalen != 0)
854 				fatalx("bad MSG_EXITING size");
855 
856 			c->session = NULL;
857 			tty_close(&c->tty);
858 			server_write_client(c, MSG_EXITED, NULL, 0);
859 			break;
860 		case MSG_WAKEUP:
861 		case MSG_UNLOCK:
862 			if (datalen != 0)
863 				fatalx("bad MSG_WAKEUP size");
864 
865 			if (!(c->flags & CLIENT_SUSPENDED))
866 				break;
867 			c->flags &= ~CLIENT_SUSPENDED;
868 
869 			if (gettimeofday(&c->activity_time, NULL) != 0)
870 				fatal("gettimeofday");
871 			if (c->session != NULL)
872 				session_update_activity(c->session);
873 
874 			tty_start_tty(&c->tty);
875 			server_redraw_client(c);
876 			recalculate_sizes();
877 			break;
878 		case MSG_ENVIRON:
879 			if (datalen != sizeof environdata)
880 				fatalx("bad MSG_ENVIRON size");
881 			memcpy(&environdata, imsg.data, sizeof environdata);
882 
883 			environdata.var[(sizeof environdata.var) - 1] = '\0';
884 			if (strchr(environdata.var, '=') != NULL)
885 				environ_put(&c->environ, environdata.var);
886 			break;
887 		case MSG_SHELL:
888 			if (datalen != 0)
889 				fatalx("bad MSG_SHELL size");
890 
891 			server_client_msg_shell(c);
892 			break;
893 		default:
894 			fatalx("unexpected message");
895 		}
896 
897 		imsg_free(&imsg);
898 	}
899 }
900 
901 /* Handle command message. */
902 void
903 server_client_msg_command(struct client *c, struct msg_command_data *data)
904 {
905 	struct cmd_list	*cmdlist = NULL;
906 	int		 argc;
907 	char	       **argv, *cause;
908 
909 	argc = data->argc;
910 	data->argv[(sizeof data->argv) - 1] = '\0';
911 	if (cmd_unpack_argv(data->argv, sizeof data->argv, argc, &argv) != 0) {
912 		cmdq_error(c->cmdq, "command too long");
913 		goto error;
914 	}
915 
916 	if (argc == 0) {
917 		argc = 1;
918 		argv = xcalloc(1, sizeof *argv);
919 		*argv = xstrdup("new-session");
920 	}
921 
922 	if ((cmdlist = cmd_list_parse(argc, argv, NULL, 0, &cause)) == NULL) {
923 		cmdq_error(c->cmdq, "%s", cause);
924 		cmd_free_argv(argc, argv);
925 		goto error;
926 	}
927 	cmd_free_argv(argc, argv);
928 
929 	cmdq_run(c->cmdq, cmdlist);
930 	cmd_list_free(cmdlist);
931 	return;
932 
933 error:
934 	if (cmdlist != NULL)
935 		cmd_list_free(cmdlist);
936 
937 	c->flags |= CLIENT_EXIT;
938 }
939 
940 /* Handle identify message. */
941 void
942 server_client_msg_identify(
943     struct client *c, struct msg_identify_data *data, int fd)
944 {
945 	c->cwd = NULL;
946 	data->cwd[(sizeof data->cwd) - 1] = '\0';
947 	if (*data->cwd != '\0')
948 		c->cwd = xstrdup(data->cwd);
949 
950 	if (data->flags & IDENTIFY_CONTROL) {
951 		c->stdin_callback = control_callback;
952 		evbuffer_free(c->stderr_data);
953 		c->stderr_data = c->stdout_data;
954 		c->flags |= CLIENT_CONTROL;
955 		if (data->flags & IDENTIFY_TERMIOS)
956 			evbuffer_add_printf(c->stdout_data, "\033P1000p");
957 		server_write_client(c, MSG_STDIN, NULL, 0);
958 
959 		c->tty.fd = -1;
960 		c->tty.log_fd = -1;
961 
962 		close(fd);
963 		return;
964 	}
965 
966 	if (!isatty(fd)) {
967 		close(fd);
968 		return;
969 	}
970 	data->term[(sizeof data->term) - 1] = '\0';
971 	tty_init(&c->tty, c, fd, data->term);
972 	if (data->flags & IDENTIFY_UTF8)
973 		c->tty.flags |= TTY_UTF8;
974 	if (data->flags & IDENTIFY_256COLOURS)
975 		c->tty.term_flags |= TERM_256COLOURS;
976 
977 	tty_resize(&c->tty);
978 
979 	if (!(data->flags & IDENTIFY_CONTROL))
980 		c->flags |= CLIENT_TERMINAL;
981 }
982 
983 /* Handle shell message. */
984 void
985 server_client_msg_shell(struct client *c)
986 {
987 	struct msg_shell_data	 data;
988 	const char		*shell;
989 
990 	shell = options_get_string(&global_s_options, "default-shell");
991 
992 	if (*shell == '\0' || areshell(shell))
993 		shell = _PATH_BSHELL;
994 	if (strlcpy(data.shell, shell, sizeof data.shell) >= sizeof data.shell)
995 		strlcpy(data.shell, _PATH_BSHELL, sizeof data.shell);
996 
997 	server_write_client(c, MSG_SHELL, &data, sizeof data);
998 	c->flags |= CLIENT_BAD;	/* it will die after exec */
999 }
1000