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