GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.bin/tmux/alerts.c Lines: 0 120 0.0 %
Date: 2016-12-06 Branches: 0 122 0.0 %

Line Branch Exec Source
1
/* $OpenBSD: alerts.c,v 1.11 2016/05/11 20:56:58 nicm Exp $ */
2
3
/*
4
 * Copyright (c) 2015 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
21
#include <event.h>
22
23
#include "tmux.h"
24
25
int	alerts_fired;
26
27
void	alerts_timer(int, short, void *);
28
int	alerts_enabled(struct window *, int);
29
void	alerts_callback(int, short, void *);
30
void	alerts_reset(struct window *);
31
32
void	alerts_run_hook(struct session *, struct winlink *, int);
33
int	alerts_check_all(struct session *, struct winlink *);
34
int	alerts_check_bell(struct session *, struct winlink *);
35
int	alerts_check_activity(struct session *, struct winlink *);
36
int	alerts_check_silence(struct session *, struct winlink *);
37
void	alerts_ring_bell(struct session *);
38
39
void
40
alerts_timer(__unused int fd, __unused short events, void *arg)
41
{
42
	struct window	*w = arg;
43
44
	log_debug("@%u alerts timer expired", w->id);
45
	alerts_reset(w);
46
	alerts_queue(w, WINDOW_SILENCE);
47
}
48
49
void
50
alerts_callback(__unused int fd, __unused short events, __unused void *arg)
51
{
52
	struct window	*w;
53
	struct session	*s;
54
	struct winlink	*wl;
55
	int		 flags, alerts;
56
57
	RB_FOREACH(w, windows, &windows) {
58
		RB_FOREACH(s, sessions, &sessions) {
59
			RB_FOREACH(wl, winlinks, &s->windows) {
60
				if (wl->window != w)
61
					continue;
62
				flags = w->flags;
63
64
				alerts = alerts_check_all(s, wl);
65
66
				log_debug("%s:%d @%u alerts check, alerts %#x, "
67
				    "flags %#x", s->name, wl->idx, w->id,
68
				    alerts, flags);
69
			}
70
		}
71
	}
72
	alerts_fired = 0;
73
}
74
75
void
76
alerts_run_hook(struct session *s, struct winlink *wl, int flags)
77
{
78
	struct cmd_find_state	 fs;
79
80
	if (cmd_find_from_winlink(&fs, s, wl) != 0)
81
		return;
82
83
	if (flags & WINDOW_BELL)
84
		hooks_run(s->hooks, NULL, &fs, "alert-bell");
85
	if (flags & WINDOW_SILENCE)
86
		hooks_run(s->hooks, NULL, &fs, "alert-silence");
87
	if (flags & WINDOW_ACTIVITY)
88
		hooks_run(s->hooks, NULL, &fs, "alert-activity");
89
}
90
91
int
92
alerts_check_all(struct session *s, struct winlink *wl)
93
{
94
	int	alerts;
95
96
	alerts  = alerts_check_bell(s, wl);
97
	alerts |= alerts_check_activity(s, wl);
98
	alerts |= alerts_check_silence(s, wl);
99
	if (alerts != 0) {
100
		alerts_run_hook(s, wl, alerts);
101
		server_status_session(s);
102
	}
103
104
	return (alerts);
105
}
106
107
void
108
alerts_check_session(struct session *s)
109
{
110
	struct winlink	*wl;
111
112
	RB_FOREACH(wl, winlinks, &s->windows)
113
		alerts_check_all(s, wl);
114
}
115
116
int
117
alerts_enabled(struct window *w, int flags)
118
{
119
	if (flags & WINDOW_BELL)
120
		return (1);
121
	if (flags & WINDOW_ACTIVITY) {
122
		if (options_get_number(w->options, "monitor-activity"))
123
			return (1);
124
	}
125
	if (flags & WINDOW_SILENCE) {
126
		if (options_get_number(w->options, "monitor-silence") != 0)
127
			return (1);
128
	}
129
	return (0);
130
}
131
132
void
133
alerts_reset_all(void)
134
{
135
	struct window	*w;
136
137
	RB_FOREACH(w, windows, &windows)
138
		alerts_reset(w);
139
}
140
141
void
142
alerts_reset(struct window *w)
143
{
144
	struct timeval	tv;
145
146
	w->flags &= ~WINDOW_SILENCE;
147
	event_del(&w->alerts_timer);
148
149
	timerclear(&tv);
150
	tv.tv_sec = options_get_number(w->options, "monitor-silence");
151
152
	log_debug("@%u alerts timer reset %u", w->id, (u_int)tv.tv_sec);
153
	if (tv.tv_sec != 0)
154
		event_add(&w->alerts_timer, &tv);
155
}
156
157
void
158
alerts_queue(struct window *w, int flags)
159
{
160
	if (w->flags & WINDOW_ACTIVITY)
161
		alerts_reset(w);
162
163
	if (!event_initialized(&w->alerts_timer))
164
		evtimer_set(&w->alerts_timer, alerts_timer, w);
165
166
	if ((w->flags & flags) != flags) {
167
		w->flags |= flags;
168
		log_debug("@%u alerts flags added %#x", w->id, flags);
169
	}
170
171
	if (!alerts_fired && alerts_enabled(w, flags)) {
172
		log_debug("alerts check queued (by @%u)", w->id);
173
		event_once(-1, EV_TIMEOUT, alerts_callback, NULL, NULL);
174
		alerts_fired = 1;
175
	}
176
}
177
178
int
179
alerts_check_bell(struct session *s, struct winlink *wl)
180
{
181
	struct client	*c;
182
	struct window	*w = wl->window;
183
	int		 action, visual;
184
185
	if (!(w->flags & WINDOW_BELL))
186
		return (0);
187
	if (s->curw != wl) {
188
		wl->flags |= WINLINK_BELL;
189
		w->flags &= ~WINDOW_BELL;
190
	}
191
	if (s->curw->window == w)
192
		w->flags &= ~WINDOW_BELL;
193
194
	action = options_get_number(s->options, "bell-action");
195
	if (action == BELL_NONE)
196
		return (0);
197
198
	visual = options_get_number(s->options, "visual-bell");
199
	TAILQ_FOREACH(c, &clients, entry) {
200
		if (c->session != s || c->flags & CLIENT_CONTROL)
201
			continue;
202
		if (!visual) {
203
			if ((action == BELL_CURRENT &&
204
			    c->session->curw->window == w) ||
205
			    (action == BELL_OTHER &&
206
			    c->session->curw->window != w) ||
207
			    action == BELL_ANY)
208
				tty_putcode(&c->tty, TTYC_BEL);
209
			continue;
210
		}
211
		if (action == BELL_CURRENT && c->session->curw->window == w)
212
			status_message_set(c, "Bell in current window");
213
		else if (action == BELL_ANY || (action == BELL_OTHER &&
214
		    c->session->curw->window != w))
215
			status_message_set(c, "Bell in window %d", wl->idx);
216
	}
217
218
	return (WINDOW_BELL);
219
}
220
221
int
222
alerts_check_activity(struct session *s, struct winlink *wl)
223
{
224
	struct client	*c;
225
	struct window	*w = wl->window;
226
227
	if (s->curw->window == w)
228
		w->flags &= ~WINDOW_ACTIVITY;
229
230
	if (!(w->flags & WINDOW_ACTIVITY) || wl->flags & WINLINK_ACTIVITY)
231
		return (0);
232
	if (s->curw == wl)
233
		return (0);
234
235
	if (!options_get_number(w->options, "monitor-activity"))
236
		return (0);
237
238
	if (options_get_number(s->options, "bell-on-alert"))
239
		alerts_ring_bell(s);
240
	wl->flags |= WINLINK_ACTIVITY;
241
242
	if (options_get_number(s->options, "visual-activity")) {
243
		TAILQ_FOREACH(c, &clients, entry) {
244
			if (c->session != s)
245
				continue;
246
			status_message_set(c, "Activity in window %d", wl->idx);
247
		}
248
	}
249
250
	return (WINDOW_ACTIVITY);
251
}
252
253
int
254
alerts_check_silence(struct session *s, struct winlink *wl)
255
{
256
	struct client	*c;
257
	struct window	*w = wl->window;
258
259
	if (s->curw->window == w)
260
		w->flags &= ~WINDOW_SILENCE;
261
262
	if (!(w->flags & WINDOW_SILENCE) || wl->flags & WINLINK_SILENCE)
263
		return (0);
264
	if (s->curw == wl)
265
		return (0);
266
267
	if (options_get_number(w->options, "monitor-silence") == 0)
268
		return (0);
269
270
	if (options_get_number(s->options, "bell-on-alert"))
271
		alerts_ring_bell(s);
272
	wl->flags |= WINLINK_SILENCE;
273
274
	if (options_get_number(s->options, "visual-silence")) {
275
		TAILQ_FOREACH(c, &clients, entry) {
276
			if (c->session != s)
277
				continue;
278
			status_message_set(c, "Silence in window %d", wl->idx);
279
		}
280
	}
281
282
	return (WINDOW_SILENCE);
283
}
284
285
void
286
alerts_ring_bell(struct session *s)
287
{
288
	struct client	*c;
289
290
	TAILQ_FOREACH(c, &clients, entry) {
291
		if (c->session == s && !(c->flags & CLIENT_CONTROL))
292
			tty_putcode(&c->tty, TTYC_BEL);
293
	}
294
}