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