xref: /openbsd/usr.bin/tmux/control.c (revision 7c8808e4)
1 /* $OpenBSD: control.c,v 1.49 2022/08/24 07:22:30 nicm Exp $ */
2 
3 /*
4  * Copyright (c) 2012 Nicholas Marriott <nicholas.marriott@gmail.com>
5  * Copyright (c) 2012 George Nachman <tmux@georgester.com>
6  *
7  * Permission to use, copy, modify, and distribute this software for any
8  * purpose with or without fee is hereby granted, provided that the above
9  * copyright notice and this permission notice appear in all copies.
10  *
11  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15  * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
16  * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
17  * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18  */
19 
20 #include <sys/types.h>
21 
22 #include <event.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <time.h>
26 #include <unistd.h>
27 
28 #include "tmux.h"
29 
30 /*
31  * Block of data to output. Each client has one "all" queue of blocks and
32  * another queue for each pane (in struct client_offset). %output blocks are
33  * added to both queues and other output lines (notifications) added only to
34  * the client queue.
35  *
36  * When a client becomes writeable, data from blocks on the pane queue are sent
37  * up to the maximum size (CLIENT_BUFFER_HIGH). If a block is entirely written,
38  * it is removed from both pane and client queues and if this means non-%output
39  * blocks are now at the head of the client queue, they are written.
40  *
41  * This means a %output block holds up any subsequent non-%output blocks until
42  * it is written which enforces ordering even if the client cannot accept the
43  * entire block in one go.
44  */
45 struct control_block {
46 	size_t				 size;
47 	char				*line;
48 	uint64_t			 t;
49 
50 	TAILQ_ENTRY(control_block)	 entry;
51 	TAILQ_ENTRY(control_block)	 all_entry;
52 };
53 
54 /* Control client pane. */
55 struct control_pane {
56 	u_int				 pane;
57 
58 	/*
59 	 * Offsets into the pane data. The first (offset) is the data we have
60 	 * written; the second (queued) the data we have queued (pointed to by
61 	 * a block).
62 	 */
63 	struct window_pane_offset	 offset;
64 	struct window_pane_offset	 queued;
65 
66 	int				 flags;
67 #define CONTROL_PANE_OFF 0x1
68 #define CONTROL_PANE_PAUSED 0x2
69 
70 	int				 pending_flag;
71 	TAILQ_ENTRY(control_pane)	 pending_entry;
72 
73 	TAILQ_HEAD(, control_block)	 blocks;
74 
75 	RB_ENTRY(control_pane)		 entry;
76 };
77 RB_HEAD(control_panes, control_pane);
78 
79 /* Subscription pane. */
80 struct control_sub_pane {
81 	u_int				 pane;
82 	u_int				 idx;
83 	char				*last;
84 
85 	RB_ENTRY(control_sub_pane)	 entry;
86 };
87 RB_HEAD(control_sub_panes, control_sub_pane);
88 
89 /* Subscription window. */
90 struct control_sub_window {
91 	u_int				 window;
92 	u_int				 idx;
93 	char				*last;
94 
95 	RB_ENTRY(control_sub_window)	 entry;
96 };
97 RB_HEAD(control_sub_windows, control_sub_window);
98 
99 /* Control client subscription. */
100 struct control_sub {
101 	char				*name;
102 	char				*format;
103 
104 	enum control_sub_type		 type;
105 	u_int				 id;
106 
107 	char				*last;
108 	struct control_sub_panes	 panes;
109 	struct control_sub_windows	 windows;
110 
111 	RB_ENTRY(control_sub)		 entry;
112 };
113 RB_HEAD(control_subs, control_sub);
114 
115 /* Control client state. */
116 struct control_state {
117 	struct control_panes		 panes;
118 
119 	TAILQ_HEAD(, control_pane)	 pending_list;
120 	u_int				 pending_count;
121 
122 	TAILQ_HEAD(, control_block)	 all_blocks;
123 
124 	struct bufferevent		*read_event;
125 	struct bufferevent		*write_event;
126 
127 	struct control_subs		 subs;
128 	struct event			 subs_timer;
129 };
130 
131 /* Low and high watermarks. */
132 #define CONTROL_BUFFER_LOW 512
133 #define CONTROL_BUFFER_HIGH 8192
134 
135 /* Minimum to write to each client. */
136 #define CONTROL_WRITE_MINIMUM 32
137 
138 /* Maximum age for clients that are not using pause mode. */
139 #define CONTROL_MAXIMUM_AGE 300000
140 
141 /* Flags to ignore client. */
142 #define CONTROL_IGNORE_FLAGS \
143 	(CLIENT_CONTROL_NOOUTPUT| \
144 	 CLIENT_UNATTACHEDFLAGS)
145 
146 /* Compare client panes. */
147 static int
control_pane_cmp(struct control_pane * cp1,struct control_pane * cp2)148 control_pane_cmp(struct control_pane *cp1, struct control_pane *cp2)
149 {
150 	if (cp1->pane < cp2->pane)
151 		return (-1);
152 	if (cp1->pane > cp2->pane)
153 		return (1);
154 	return (0);
155 }
156 RB_GENERATE_STATIC(control_panes, control_pane, entry, control_pane_cmp);
157 
158 /* Compare client subs. */
159 static int
control_sub_cmp(struct control_sub * csub1,struct control_sub * csub2)160 control_sub_cmp(struct control_sub *csub1, struct control_sub *csub2)
161 {
162 	return (strcmp(csub1->name, csub2->name));
163 }
164 RB_GENERATE_STATIC(control_subs, control_sub, entry, control_sub_cmp);
165 
166 /* Compare client subscription panes. */
167 static int
control_sub_pane_cmp(struct control_sub_pane * csp1,struct control_sub_pane * csp2)168 control_sub_pane_cmp(struct control_sub_pane *csp1,
169     struct control_sub_pane *csp2)
170 {
171 	if (csp1->pane < csp2->pane)
172 		return (-1);
173 	if (csp1->pane > csp2->pane)
174 		return (1);
175 	if (csp1->idx < csp2->idx)
176 		return (-1);
177 	if (csp1->idx > csp2->idx)
178 		return (1);
179 	return (0);
180 }
181 RB_GENERATE_STATIC(control_sub_panes, control_sub_pane, entry,
182     control_sub_pane_cmp);
183 
184 /* Compare client subscription windows. */
185 static int
control_sub_window_cmp(struct control_sub_window * csw1,struct control_sub_window * csw2)186 control_sub_window_cmp(struct control_sub_window *csw1,
187     struct control_sub_window *csw2)
188 {
189 	if (csw1->window < csw2->window)
190 		return (-1);
191 	if (csw1->window > csw2->window)
192 		return (1);
193 	if (csw1->idx < csw2->idx)
194 		return (-1);
195 	if (csw1->idx > csw2->idx)
196 		return (1);
197 	return (0);
198 }
199 RB_GENERATE_STATIC(control_sub_windows, control_sub_window, entry,
200     control_sub_window_cmp);
201 
202 /* Free a subscription. */
203 static void
control_free_sub(struct control_state * cs,struct control_sub * csub)204 control_free_sub(struct control_state *cs, struct control_sub *csub)
205 {
206 	struct control_sub_pane		*csp, *csp1;
207 	struct control_sub_window	*csw, *csw1;
208 
209 	RB_FOREACH_SAFE(csp, control_sub_panes, &csub->panes, csp1) {
210 		RB_REMOVE(control_sub_panes, &csub->panes, csp);
211 		free(csp);
212 	}
213 	RB_FOREACH_SAFE(csw, control_sub_windows, &csub->windows, csw1) {
214 		RB_REMOVE(control_sub_windows, &csub->windows, csw);
215 		free(csw);
216 	}
217 	free(csub->last);
218 
219 	RB_REMOVE(control_subs, &cs->subs, csub);
220 	free(csub->name);
221 	free(csub->format);
222 	free(csub);
223 }
224 
225 /* Free a block. */
226 static void
control_free_block(struct control_state * cs,struct control_block * cb)227 control_free_block(struct control_state *cs, struct control_block *cb)
228 {
229 	free(cb->line);
230 	TAILQ_REMOVE(&cs->all_blocks, cb, all_entry);
231 	free(cb);
232 }
233 
234 /* Get pane offsets for this client. */
235 static struct control_pane *
control_get_pane(struct client * c,struct window_pane * wp)236 control_get_pane(struct client *c, struct window_pane *wp)
237 {
238 	struct control_state	*cs = c->control_state;
239 	struct control_pane	 cp = { .pane = wp->id };
240 
241 	return (RB_FIND(control_panes, &cs->panes, &cp));
242 }
243 
244 /* Add pane offsets for this client. */
245 static struct control_pane *
control_add_pane(struct client * c,struct window_pane * wp)246 control_add_pane(struct client *c, struct window_pane *wp)
247 {
248 	struct control_state	*cs = c->control_state;
249 	struct control_pane	*cp;
250 
251 	cp = control_get_pane(c, wp);
252 	if (cp != NULL)
253 		return (cp);
254 
255 	cp = xcalloc(1, sizeof *cp);
256 	cp->pane = wp->id;
257 	RB_INSERT(control_panes, &cs->panes, cp);
258 
259 	memcpy(&cp->offset, &wp->offset, sizeof cp->offset);
260 	memcpy(&cp->queued, &wp->offset, sizeof cp->queued);
261 	TAILQ_INIT(&cp->blocks);
262 
263 	return (cp);
264 }
265 
266 /* Discard output for a pane. */
267 static void
control_discard_pane(struct client * c,struct control_pane * cp)268 control_discard_pane(struct client *c, struct control_pane *cp)
269 {
270 	struct control_state	*cs = c->control_state;
271 	struct control_block	*cb, *cb1;
272 
273 	TAILQ_FOREACH_SAFE(cb, &cp->blocks, entry, cb1) {
274 		TAILQ_REMOVE(&cp->blocks, cb, entry);
275 		control_free_block(cs, cb);
276 	}
277 }
278 
279 /* Get actual pane for this client. */
280 static struct window_pane *
control_window_pane(struct client * c,u_int pane)281 control_window_pane(struct client *c, u_int pane)
282 {
283 	struct window_pane	*wp;
284 
285 	if (c->session == NULL)
286 		return (NULL);
287 	if ((wp = window_pane_find_by_id(pane)) == NULL)
288 		return (NULL);
289 	if (winlink_find_by_window(&c->session->windows, wp->window) == NULL)
290 		return (NULL);
291 	return (wp);
292 }
293 
294 /* Reset control offsets. */
295 void
control_reset_offsets(struct client * c)296 control_reset_offsets(struct client *c)
297 {
298 	struct control_state	*cs = c->control_state;
299 	struct control_pane	*cp, *cp1;
300 
301 	RB_FOREACH_SAFE(cp, control_panes, &cs->panes, cp1) {
302 		RB_REMOVE(control_panes, &cs->panes, cp);
303 		free(cp);
304 	}
305 
306 	TAILQ_INIT(&cs->pending_list);
307 	cs->pending_count = 0;
308 }
309 
310 /* Get offsets for client. */
311 struct window_pane_offset *
control_pane_offset(struct client * c,struct window_pane * wp,int * off)312 control_pane_offset(struct client *c, struct window_pane *wp, int *off)
313 {
314 	struct control_state	*cs = c->control_state;
315 	struct control_pane	*cp;
316 
317 	if (c->flags & CLIENT_CONTROL_NOOUTPUT) {
318 		*off = 0;
319 		return (NULL);
320 	}
321 
322 	cp = control_get_pane(c, wp);
323 	if (cp == NULL || (cp->flags & CONTROL_PANE_PAUSED)) {
324 		*off = 0;
325 		return (NULL);
326 	}
327 	if (cp->flags & CONTROL_PANE_OFF) {
328 		*off = 1;
329 		return (NULL);
330 	}
331 	*off = (EVBUFFER_LENGTH(cs->write_event->output) >= CONTROL_BUFFER_LOW);
332 	return (&cp->offset);
333 }
334 
335 /* Set pane as on. */
336 void
control_set_pane_on(struct client * c,struct window_pane * wp)337 control_set_pane_on(struct client *c, struct window_pane *wp)
338 {
339 	struct control_pane	*cp;
340 
341 	cp = control_get_pane(c, wp);
342 	if (cp != NULL && (cp->flags & CONTROL_PANE_OFF)) {
343 		cp->flags &= ~CONTROL_PANE_OFF;
344 		memcpy(&cp->offset, &wp->offset, sizeof cp->offset);
345 		memcpy(&cp->queued, &wp->offset, sizeof cp->queued);
346 	}
347 }
348 
349 /* Set pane as off. */
350 void
control_set_pane_off(struct client * c,struct window_pane * wp)351 control_set_pane_off(struct client *c, struct window_pane *wp)
352 {
353 	struct control_pane	*cp;
354 
355 	cp = control_add_pane(c, wp);
356 	cp->flags |= CONTROL_PANE_OFF;
357 }
358 
359 /* Continue a paused pane. */
360 void
control_continue_pane(struct client * c,struct window_pane * wp)361 control_continue_pane(struct client *c, struct window_pane *wp)
362 {
363 	struct control_pane	*cp;
364 
365 	cp = control_get_pane(c, wp);
366 	if (cp != NULL && (cp->flags & CONTROL_PANE_PAUSED)) {
367 		cp->flags &= ~CONTROL_PANE_PAUSED;
368 		memcpy(&cp->offset, &wp->offset, sizeof cp->offset);
369 		memcpy(&cp->queued, &wp->offset, sizeof cp->queued);
370 		control_write(c, "%%continue %%%u", wp->id);
371 	}
372 }
373 
374 /* Pause a pane. */
375 void
control_pause_pane(struct client * c,struct window_pane * wp)376 control_pause_pane(struct client *c, struct window_pane *wp)
377 {
378 	struct control_pane	*cp;
379 
380 	cp = control_add_pane(c, wp);
381 	if (~cp->flags & CONTROL_PANE_PAUSED) {
382 		cp->flags |= CONTROL_PANE_PAUSED;
383 		control_discard_pane(c, cp);
384 		control_write(c, "%%pause %%%u", wp->id);
385 	}
386 }
387 
388 /* Write a line. */
389 static void printflike(2, 0)
control_vwrite(struct client * c,const char * fmt,va_list ap)390 control_vwrite(struct client *c, const char *fmt, va_list ap)
391 {
392 	struct control_state	*cs = c->control_state;
393 	char			*s;
394 
395 	xvasprintf(&s, fmt, ap);
396 	log_debug("%s: %s: writing line: %s", __func__, c->name, s);
397 
398 	bufferevent_write(cs->write_event, s, strlen(s));
399 	bufferevent_write(cs->write_event, "\n", 1);
400 
401 	bufferevent_enable(cs->write_event, EV_WRITE);
402 	free(s);
403 }
404 
405 /* Write a line. */
406 void
control_write(struct client * c,const char * fmt,...)407 control_write(struct client *c, const char *fmt, ...)
408 {
409 	struct control_state	*cs = c->control_state;
410 	struct control_block	*cb;
411 	va_list			 ap;
412 
413 	va_start(ap, fmt);
414 
415 	if (TAILQ_EMPTY(&cs->all_blocks)) {
416 		control_vwrite(c, fmt, ap);
417 		va_end(ap);
418 		return;
419 	}
420 
421 	cb = xcalloc(1, sizeof *cb);
422 	xvasprintf(&cb->line, fmt, ap);
423 	TAILQ_INSERT_TAIL(&cs->all_blocks, cb, all_entry);
424 	cb->t = get_timer();
425 
426 	log_debug("%s: %s: storing line: %s", __func__, c->name, cb->line);
427 	bufferevent_enable(cs->write_event, EV_WRITE);
428 
429 	va_end(ap);
430 }
431 
432 /* Check age for this pane. */
433 static int
control_check_age(struct client * c,struct window_pane * wp,struct control_pane * cp)434 control_check_age(struct client *c, struct window_pane *wp,
435     struct control_pane *cp)
436 {
437 	struct control_block	*cb;
438 	uint64_t		 t, age;
439 
440 	cb = TAILQ_FIRST(&cp->blocks);
441 	if (cb == NULL)
442 		return (0);
443 	t = get_timer();
444 	if (cb->t >= t)
445 		return (0);
446 
447 	age = t - cb->t;
448 	log_debug("%s: %s: %%%u is %llu behind", __func__, c->name, wp->id,
449 	    (unsigned long long)age);
450 
451 	if (c->flags & CLIENT_CONTROL_PAUSEAFTER) {
452 		if (age < c->pause_age)
453 			return (0);
454 		cp->flags |= CONTROL_PANE_PAUSED;
455 		control_discard_pane(c, cp);
456 		control_write(c, "%%pause %%%u", wp->id);
457 	} else {
458 		if (age < CONTROL_MAXIMUM_AGE)
459 			return (0);
460 		c->exit_message = xstrdup("too far behind");
461 		c->flags |= CLIENT_EXIT;
462 		control_discard(c);
463 	}
464 	return (1);
465 }
466 
467 /* Write output from a pane. */
468 void
control_write_output(struct client * c,struct window_pane * wp)469 control_write_output(struct client *c, struct window_pane *wp)
470 {
471 	struct control_state	*cs = c->control_state;
472 	struct control_pane	*cp;
473 	struct control_block	*cb;
474 	size_t			 new_size;
475 
476 	if (winlink_find_by_window(&c->session->windows, wp->window) == NULL)
477 		return;
478 
479 	if (c->flags & CONTROL_IGNORE_FLAGS) {
480 		cp = control_get_pane(c, wp);
481 		if (cp != NULL)
482 			goto ignore;
483 		return;
484 	}
485 	cp = control_add_pane(c, wp);
486 	if (cp->flags & (CONTROL_PANE_OFF|CONTROL_PANE_PAUSED))
487 		goto ignore;
488 	if (control_check_age(c, wp, cp))
489 		return;
490 
491 	window_pane_get_new_data(wp, &cp->queued, &new_size);
492 	if (new_size == 0)
493 		return;
494 	window_pane_update_used_data(wp, &cp->queued, new_size);
495 
496 	cb = xcalloc(1, sizeof *cb);
497 	cb->size = new_size;
498 	TAILQ_INSERT_TAIL(&cs->all_blocks, cb, all_entry);
499 	cb->t = get_timer();
500 
501 	TAILQ_INSERT_TAIL(&cp->blocks, cb, entry);
502 	log_debug("%s: %s: new output block of %zu for %%%u", __func__, c->name,
503 	    cb->size, wp->id);
504 
505 	if (!cp->pending_flag) {
506 		log_debug("%s: %s: %%%u now pending", __func__, c->name,
507 		    wp->id);
508 		TAILQ_INSERT_TAIL(&cs->pending_list, cp, pending_entry);
509 		cp->pending_flag = 1;
510 		cs->pending_count++;
511 	}
512 	bufferevent_enable(cs->write_event, EV_WRITE);
513 	return;
514 
515 ignore:
516 	log_debug("%s: %s: ignoring pane %%%u", __func__, c->name, wp->id);
517 	window_pane_update_used_data(wp, &cp->offset, SIZE_MAX);
518 	window_pane_update_used_data(wp, &cp->queued, SIZE_MAX);
519 }
520 
521 /* Control client error callback. */
522 static enum cmd_retval
control_error(struct cmdq_item * item,void * data)523 control_error(struct cmdq_item *item, void *data)
524 {
525 	struct client	*c = cmdq_get_client(item);
526 	char		*error = data;
527 
528 	cmdq_guard(item, "begin", 1);
529 	control_write(c, "parse error: %s", error);
530 	cmdq_guard(item, "error", 1);
531 
532 	free(error);
533 	return (CMD_RETURN_NORMAL);
534 }
535 
536 /* Control client error callback. */
537 static void
control_error_callback(__unused struct bufferevent * bufev,__unused short what,void * data)538 control_error_callback(__unused struct bufferevent *bufev,
539     __unused short what, void *data)
540 {
541 	struct client	*c = data;
542 
543 	c->flags |= CLIENT_EXIT;
544 }
545 
546 /* Control client input callback. Read lines and fire commands. */
547 static void
control_read_callback(__unused struct bufferevent * bufev,void * data)548 control_read_callback(__unused struct bufferevent *bufev, void *data)
549 {
550 	struct client		*c = data;
551 	struct control_state	*cs = c->control_state;
552 	struct evbuffer		*buffer = cs->read_event->input;
553 	char			*line, *error;
554 	struct cmdq_state	*state;
555 	enum cmd_parse_status	 status;
556 
557 	for (;;) {
558 		line = evbuffer_readln(buffer, NULL, EVBUFFER_EOL_LF);
559 		if (line == NULL)
560 			break;
561 		log_debug("%s: %s: %s", __func__, c->name, line);
562 		if (*line == '\0') { /* empty line detach */
563 			free(line);
564 			c->flags |= CLIENT_EXIT;
565 			break;
566 		}
567 
568 		state = cmdq_new_state(NULL, NULL, CMDQ_STATE_CONTROL);
569 		status = cmd_parse_and_append(line, NULL, c, state, &error);
570 		if (status == CMD_PARSE_ERROR)
571 			cmdq_append(c, cmdq_get_callback(control_error, error));
572 		cmdq_free_state(state);
573 
574 		free(line);
575 	}
576 }
577 
578 /* Does this control client have outstanding data to write? */
579 int
control_all_done(struct client * c)580 control_all_done(struct client *c)
581 {
582 	struct control_state	*cs = c->control_state;
583 
584 	if (!TAILQ_EMPTY(&cs->all_blocks))
585 		return (0);
586 	return (EVBUFFER_LENGTH(cs->write_event->output) == 0);
587 }
588 
589 /* Flush all blocks until output. */
590 static void
control_flush_all_blocks(struct client * c)591 control_flush_all_blocks(struct client *c)
592 {
593 	struct control_state	*cs = c->control_state;
594 	struct control_block	*cb, *cb1;
595 
596 	TAILQ_FOREACH_SAFE(cb, &cs->all_blocks, all_entry, cb1) {
597 		if (cb->size != 0)
598 			break;
599 		log_debug("%s: %s: flushing line: %s", __func__, c->name,
600 		    cb->line);
601 
602 		bufferevent_write(cs->write_event, cb->line, strlen(cb->line));
603 		bufferevent_write(cs->write_event, "\n", 1);
604 		control_free_block(cs, cb);
605 	}
606 }
607 
608 /* Append data to buffer. */
609 static struct evbuffer *
control_append_data(struct client * c,struct control_pane * cp,uint64_t age,struct evbuffer * message,struct window_pane * wp,size_t size)610 control_append_data(struct client *c, struct control_pane *cp, uint64_t age,
611     struct evbuffer *message, struct window_pane *wp, size_t size)
612 {
613 	u_char	*new_data;
614 	size_t	 new_size;
615 	u_int	 i;
616 
617 	if (message == NULL) {
618 		message = evbuffer_new();
619 		if (message == NULL)
620 			fatalx("out of memory");
621 		if (c->flags & CLIENT_CONTROL_PAUSEAFTER) {
622 			evbuffer_add_printf(message,
623 			    "%%extended-output %%%u %llu : ", wp->id,
624 			    (unsigned long long)age);
625 		} else
626 			evbuffer_add_printf(message, "%%output %%%u ", wp->id);
627 	}
628 
629 	new_data = window_pane_get_new_data(wp, &cp->offset, &new_size);
630 	if (new_size < size)
631 		fatalx("not enough data: %zu < %zu", new_size, size);
632 	for (i = 0; i < size; i++) {
633 		if (new_data[i] < ' ' || new_data[i] == '\\')
634 			evbuffer_add_printf(message, "\\%03o", new_data[i]);
635 		else
636 			evbuffer_add_printf(message, "%c", new_data[i]);
637 	}
638 	window_pane_update_used_data(wp, &cp->offset, size);
639 	return (message);
640 }
641 
642 /* Write buffer. */
643 static void
control_write_data(struct client * c,struct evbuffer * message)644 control_write_data(struct client *c, struct evbuffer *message)
645 {
646 	struct control_state	*cs = c->control_state;
647 
648 	log_debug("%s: %s: %.*s", __func__, c->name,
649 	    (int)EVBUFFER_LENGTH(message), EVBUFFER_DATA(message));
650 
651 	evbuffer_add(message, "\n", 1);
652 	bufferevent_write_buffer(cs->write_event, message);
653 	evbuffer_free(message);
654 }
655 
656 /* Write output to client. */
657 static int
control_write_pending(struct client * c,struct control_pane * cp,size_t limit)658 control_write_pending(struct client *c, struct control_pane *cp, size_t limit)
659 {
660 	struct control_state	*cs = c->control_state;
661 	struct window_pane	*wp = NULL;
662 	struct evbuffer		*message = NULL;
663 	size_t			 used = 0, size;
664 	struct control_block	*cb, *cb1;
665 	uint64_t		 age, t = get_timer();
666 
667 	wp = control_window_pane(c, cp->pane);
668 	if (wp == NULL || wp->fd == -1) {
669 		TAILQ_FOREACH_SAFE(cb, &cp->blocks, entry, cb1) {
670 			TAILQ_REMOVE(&cp->blocks, cb, entry);
671 			control_free_block(cs, cb);
672 		}
673 		control_flush_all_blocks(c);
674 		return (0);
675 	}
676 
677 	while (used != limit && !TAILQ_EMPTY(&cp->blocks)) {
678 		if (control_check_age(c, wp, cp)) {
679 			if (message != NULL)
680 				evbuffer_free(message);
681 			message = NULL;
682 			break;
683 		}
684 
685 		cb = TAILQ_FIRST(&cp->blocks);
686 		if (cb->t < t)
687 			age = t - cb->t;
688 		else
689 			age = 0;
690 		log_debug("%s: %s: output block %zu (age %llu) for %%%u "
691 		    "(used %zu/%zu)", __func__, c->name, cb->size,
692 		    (unsigned long long)age, cp->pane, used, limit);
693 
694 		size = cb->size;
695 		if (size > limit - used)
696 			size = limit - used;
697 		used += size;
698 
699 		message = control_append_data(c, cp, age, message, wp, size);
700 
701 		cb->size -= size;
702 		if (cb->size == 0) {
703 			TAILQ_REMOVE(&cp->blocks, cb, entry);
704 			control_free_block(cs, cb);
705 
706 			cb = TAILQ_FIRST(&cs->all_blocks);
707 			if (cb != NULL && cb->size == 0) {
708 				if (wp != NULL && message != NULL) {
709 					control_write_data(c, message);
710 					message = NULL;
711 				}
712 				control_flush_all_blocks(c);
713 			}
714 		}
715 	}
716 	if (message != NULL)
717 		control_write_data(c, message);
718 	return (!TAILQ_EMPTY(&cp->blocks));
719 }
720 
721 /* Control client write callback. */
722 static void
control_write_callback(__unused struct bufferevent * bufev,void * data)723 control_write_callback(__unused struct bufferevent *bufev, void *data)
724 {
725 	struct client		*c = data;
726 	struct control_state	*cs = c->control_state;
727 	struct control_pane	*cp, *cp1;
728 	struct evbuffer		*evb = cs->write_event->output;
729 	size_t			 space, limit;
730 
731 	control_flush_all_blocks(c);
732 
733 	while (EVBUFFER_LENGTH(evb) < CONTROL_BUFFER_HIGH) {
734 		if (cs->pending_count == 0)
735 			break;
736 		space = CONTROL_BUFFER_HIGH - EVBUFFER_LENGTH(evb);
737 		log_debug("%s: %s: %zu bytes available, %u panes", __func__,
738 		    c->name, space, cs->pending_count);
739 
740 		limit = (space / cs->pending_count / 3); /* 3 bytes for \xxx */
741 		if (limit < CONTROL_WRITE_MINIMUM)
742 			limit = CONTROL_WRITE_MINIMUM;
743 
744 		TAILQ_FOREACH_SAFE(cp, &cs->pending_list, pending_entry, cp1) {
745 			if (EVBUFFER_LENGTH(evb) >= CONTROL_BUFFER_HIGH)
746 				break;
747 			if (control_write_pending(c, cp, limit))
748 				continue;
749 			TAILQ_REMOVE(&cs->pending_list, cp, pending_entry);
750 			cp->pending_flag = 0;
751 			cs->pending_count--;
752 		}
753 	}
754 	if (EVBUFFER_LENGTH(evb) == 0)
755 		bufferevent_disable(cs->write_event, EV_WRITE);
756 }
757 
758 /* Initialize for control mode. */
759 void
control_start(struct client * c)760 control_start(struct client *c)
761 {
762 	struct control_state	*cs;
763 
764 	if (c->flags & CLIENT_CONTROLCONTROL) {
765 		close(c->out_fd);
766 		c->out_fd = -1;
767 	} else
768 		setblocking(c->out_fd, 0);
769 	setblocking(c->fd, 0);
770 
771 	cs = c->control_state = xcalloc(1, sizeof *cs);
772 	RB_INIT(&cs->panes);
773 	TAILQ_INIT(&cs->pending_list);
774 	TAILQ_INIT(&cs->all_blocks);
775 	RB_INIT(&cs->subs);
776 
777 	cs->read_event = bufferevent_new(c->fd, control_read_callback,
778 	    control_write_callback, control_error_callback, c);
779 	if (cs->read_event == NULL)
780 		fatalx("out of memory");
781 
782 	if (c->flags & CLIENT_CONTROLCONTROL)
783 		cs->write_event = cs->read_event;
784 	else {
785 		cs->write_event = bufferevent_new(c->out_fd, NULL,
786 		    control_write_callback, control_error_callback, c);
787 		if (cs->write_event == NULL)
788 			fatalx("out of memory");
789 	}
790 	bufferevent_setwatermark(cs->write_event, EV_WRITE, CONTROL_BUFFER_LOW,
791 	    0);
792 
793 	if (c->flags & CLIENT_CONTROLCONTROL) {
794 		bufferevent_write(cs->write_event, "\033P1000p", 7);
795 		bufferevent_enable(cs->write_event, EV_WRITE);
796 	}
797 }
798 
799 /* Control client ready. */
800 void
control_ready(struct client * c)801 control_ready(struct client *c)
802 {
803 	bufferevent_enable(c->control_state->read_event, EV_READ);
804 }
805 
806 /* Discard all output for a client. */
807 void
control_discard(struct client * c)808 control_discard(struct client *c)
809 {
810 	struct control_state	*cs = c->control_state;
811 	struct control_pane	*cp;
812 
813 	RB_FOREACH(cp, control_panes, &cs->panes)
814 		control_discard_pane(c, cp);
815 	bufferevent_disable(cs->read_event, EV_READ);
816 }
817 
818 /* Stop control mode. */
819 void
control_stop(struct client * c)820 control_stop(struct client *c)
821 {
822 	struct control_state	*cs = c->control_state;
823 	struct control_block	*cb, *cb1;
824 	struct control_sub	*csub, *csub1;
825 
826 	if (~c->flags & CLIENT_CONTROLCONTROL)
827 		bufferevent_free(cs->write_event);
828 	bufferevent_free(cs->read_event);
829 
830 	RB_FOREACH_SAFE(csub, control_subs, &cs->subs, csub1)
831 		control_free_sub(cs, csub);
832 	if (evtimer_initialized(&cs->subs_timer))
833 		evtimer_del(&cs->subs_timer);
834 
835 	TAILQ_FOREACH_SAFE(cb, &cs->all_blocks, all_entry, cb1)
836 		control_free_block(cs, cb);
837 	control_reset_offsets(c);
838 
839 	free(cs);
840 }
841 
842 /* Check session subscription. */
843 static void
control_check_subs_session(struct client * c,struct control_sub * csub)844 control_check_subs_session(struct client *c, struct control_sub *csub)
845 {
846 	struct session		*s = c->session;
847 	struct format_tree	*ft;
848 	char			*value;
849 
850 	ft = format_create_defaults(NULL, c, s, NULL, NULL);
851 	value = format_expand(ft, csub->format);
852 	format_free(ft);
853 
854 	if (csub->last != NULL && strcmp(value, csub->last) == 0) {
855 		free(value);
856 		return;
857 	}
858 	control_write(c,
859 	    "%%subscription-changed %s $%u - - - : %s",
860 	    csub->name, s->id, value);
861 	free(csub->last);
862 	csub->last = value;
863 }
864 
865 /* Check pane subscription. */
866 static void
control_check_subs_pane(struct client * c,struct control_sub * csub)867 control_check_subs_pane(struct client *c, struct control_sub *csub)
868 {
869 	struct session		*s = c->session;
870 	struct window_pane	*wp;
871 	struct window		*w;
872 	struct winlink		*wl;
873 	struct format_tree	*ft;
874 	char			*value;
875 	struct control_sub_pane	*csp, find;
876 
877 	wp = window_pane_find_by_id(csub->id);
878 	if (wp == NULL || wp->fd == -1)
879 		return;
880 	w = wp->window;
881 
882 	TAILQ_FOREACH(wl, &w->winlinks, wentry) {
883 		if (wl->session != s)
884 			continue;
885 
886 		ft = format_create_defaults(NULL, c, s, wl, wp);
887 		value = format_expand(ft, csub->format);
888 		format_free(ft);
889 
890 		find.pane = wp->id;
891 		find.idx = wl->idx;
892 
893 		csp = RB_FIND(control_sub_panes, &csub->panes, &find);
894 		if (csp == NULL) {
895 			csp = xcalloc(1, sizeof *csp);
896 			csp->pane = wp->id;
897 			csp->idx = wl->idx;
898 			RB_INSERT(control_sub_panes, &csub->panes, csp);
899 		}
900 
901 		if (csp->last != NULL && strcmp(value, csp->last) == 0) {
902 			free(value);
903 			continue;
904 		}
905 		control_write(c,
906 		    "%%subscription-changed %s $%u @%u %u %%%u : %s",
907 		    csub->name, s->id, w->id, wl->idx, wp->id, value);
908 		free(csp->last);
909 		csp->last = value;
910 	}
911 }
912 
913 /* Check all panes subscription. */
914 static void
control_check_subs_all_panes(struct client * c,struct control_sub * csub)915 control_check_subs_all_panes(struct client *c, struct control_sub *csub)
916 {
917 	struct session		*s = c->session;
918 	struct window_pane	*wp;
919 	struct window		*w;
920 	struct winlink		*wl;
921 	struct format_tree	*ft;
922 	char			*value;
923 	struct control_sub_pane	*csp, find;
924 
925 	RB_FOREACH(wl, winlinks, &s->windows) {
926 		w = wl->window;
927 		TAILQ_FOREACH(wp, &w->panes, entry) {
928 			ft = format_create_defaults(NULL, c, s, wl, wp);
929 			value = format_expand(ft, csub->format);
930 			format_free(ft);
931 
932 			find.pane = wp->id;
933 			find.idx = wl->idx;
934 
935 			csp = RB_FIND(control_sub_panes, &csub->panes, &find);
936 			if (csp == NULL) {
937 				csp = xcalloc(1, sizeof *csp);
938 				csp->pane = wp->id;
939 				csp->idx = wl->idx;
940 				RB_INSERT(control_sub_panes, &csub->panes, csp);
941 			}
942 
943 			if (csp->last != NULL &&
944 			    strcmp(value, csp->last) == 0) {
945 				free(value);
946 				continue;
947 			}
948 			control_write(c,
949 			    "%%subscription-changed %s $%u @%u %u %%%u : %s",
950 			    csub->name, s->id, w->id, wl->idx, wp->id, value);
951 			free(csp->last);
952 			csp->last = value;
953 		}
954 	}
955 }
956 
957 /* Check window subscription. */
958 static void
control_check_subs_window(struct client * c,struct control_sub * csub)959 control_check_subs_window(struct client *c, struct control_sub *csub)
960 {
961 	struct session			*s = c->session;
962 	struct window			*w;
963 	struct winlink			*wl;
964 	struct format_tree		*ft;
965 	char				*value;
966 	struct control_sub_window	*csw, find;
967 
968 	w = window_find_by_id(csub->id);
969 	if (w == NULL)
970 		return;
971 
972 	TAILQ_FOREACH(wl, &w->winlinks, wentry) {
973 		if (wl->session != s)
974 			continue;
975 
976 		ft = format_create_defaults(NULL, c, s, wl, NULL);
977 		value = format_expand(ft, csub->format);
978 		format_free(ft);
979 
980 		find.window = w->id;
981 		find.idx = wl->idx;
982 
983 		csw = RB_FIND(control_sub_windows, &csub->windows, &find);
984 		if (csw == NULL) {
985 			csw = xcalloc(1, sizeof *csw);
986 			csw->window = w->id;
987 			csw->idx = wl->idx;
988 			RB_INSERT(control_sub_windows, &csub->windows, csw);
989 		}
990 
991 		if (csw->last != NULL && strcmp(value, csw->last) == 0) {
992 			free(value);
993 			continue;
994 		}
995 		control_write(c,
996 		    "%%subscription-changed %s $%u @%u %u - : %s",
997 		    csub->name, s->id, w->id, wl->idx, value);
998 		free(csw->last);
999 		csw->last = value;
1000 	}
1001 }
1002 
1003 /* Check all windows subscription. */
1004 static void
control_check_subs_all_windows(struct client * c,struct control_sub * csub)1005 control_check_subs_all_windows(struct client *c, struct control_sub *csub)
1006 {
1007 	struct session			*s = c->session;
1008 	struct window			*w;
1009 	struct winlink			*wl;
1010 	struct format_tree		*ft;
1011 	char				*value;
1012 	struct control_sub_window	*csw, find;
1013 
1014 	RB_FOREACH(wl, winlinks, &s->windows) {
1015 		w = wl->window;
1016 
1017 		ft = format_create_defaults(NULL, c, s, wl, NULL);
1018 		value = format_expand(ft, csub->format);
1019 		format_free(ft);
1020 
1021 		find.window = w->id;
1022 		find.idx = wl->idx;
1023 
1024 		csw = RB_FIND(control_sub_windows, &csub->windows, &find);
1025 		if (csw == NULL) {
1026 			csw = xcalloc(1, sizeof *csw);
1027 			csw->window = w->id;
1028 			csw->idx = wl->idx;
1029 			RB_INSERT(control_sub_windows, &csub->windows, csw);
1030 		}
1031 
1032 		if (csw->last != NULL && strcmp(value, csw->last) == 0) {
1033 			free(value);
1034 			continue;
1035 		}
1036 		control_write(c,
1037 		    "%%subscription-changed %s $%u @%u %u - : %s",
1038 		    csub->name, s->id, w->id, wl->idx, value);
1039 		free(csw->last);
1040 		csw->last = value;
1041 	}
1042 }
1043 
1044 /* Check subscriptions timer. */
1045 static void
control_check_subs_timer(__unused int fd,__unused short events,void * data)1046 control_check_subs_timer(__unused int fd, __unused short events, void *data)
1047 {
1048 	struct client		*c = data;
1049 	struct control_state	*cs = c->control_state;
1050 	struct control_sub	*csub, *csub1;
1051 	struct timeval		 tv = { .tv_sec = 1 };
1052 
1053 	log_debug("%s: timer fired", __func__);
1054 	evtimer_add(&cs->subs_timer, &tv);
1055 
1056 	RB_FOREACH_SAFE(csub, control_subs, &cs->subs, csub1) {
1057 		switch (csub->type) {
1058 		case CONTROL_SUB_SESSION:
1059 			control_check_subs_session(c, csub);
1060 			break;
1061 		case CONTROL_SUB_PANE:
1062 			control_check_subs_pane(c, csub);
1063 			break;
1064 		case CONTROL_SUB_ALL_PANES:
1065 			control_check_subs_all_panes(c, csub);
1066 			break;
1067 		case CONTROL_SUB_WINDOW:
1068 			control_check_subs_window(c, csub);
1069 			break;
1070 		case CONTROL_SUB_ALL_WINDOWS:
1071 			control_check_subs_all_windows(c, csub);
1072 			break;
1073 		}
1074 	}
1075 }
1076 
1077 /* Add a subscription. */
1078 void
control_add_sub(struct client * c,const char * name,enum control_sub_type type,int id,const char * format)1079 control_add_sub(struct client *c, const char *name, enum control_sub_type type,
1080     int id, const char *format)
1081 {
1082 	struct control_state	*cs = c->control_state;
1083 	struct control_sub	*csub, find;
1084 	struct timeval		 tv = { .tv_sec = 1 };
1085 
1086 	find.name = (char *)name;
1087 	if ((csub = RB_FIND(control_subs, &cs->subs, &find)) != NULL)
1088 		control_free_sub(cs, csub);
1089 
1090 	csub = xcalloc(1, sizeof *csub);
1091 	csub->name = xstrdup(name);
1092 	csub->type = type;
1093 	csub->id = id;
1094 	csub->format = xstrdup(format);
1095 	RB_INSERT(control_subs, &cs->subs, csub);
1096 
1097 	RB_INIT(&csub->panes);
1098 	RB_INIT(&csub->windows);
1099 
1100 	if (!evtimer_initialized(&cs->subs_timer))
1101 		evtimer_set(&cs->subs_timer, control_check_subs_timer, c);
1102 	if (!evtimer_pending(&cs->subs_timer, NULL))
1103 		evtimer_add(&cs->subs_timer, &tv);
1104 }
1105 
1106 /* Remove a subscription. */
1107 void
control_remove_sub(struct client * c,const char * name)1108 control_remove_sub(struct client *c, const char *name)
1109 {
1110 	struct control_state	*cs = c->control_state;
1111 	struct control_sub	*csub, find;
1112 
1113 	find.name = (char *)name;
1114 	if ((csub = RB_FIND(control_subs, &cs->subs, &find)) != NULL)
1115 		control_free_sub(cs, csub);
1116 	if (RB_EMPTY(&cs->subs))
1117 		evtimer_del(&cs->subs_timer);
1118 }
1119