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