GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.bin/tmux/notify.c Lines: 0 99 0.0 %
Date: 2017-11-13 Branches: 0 58 0.0 %

Line Branch Exec Source
1
/* $OpenBSD: notify.c,v 1.25 2017/08/30 10:33:57 nicm Exp $ */
2
3
/*
4
 * Copyright (c) 2012 George Nachman <tmux@georgester.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/queue.h>
21
22
#include <stdlib.h>
23
#include <string.h>
24
25
#include "tmux.h"
26
27
struct notify_entry {
28
	const char		*name;
29
30
	struct client		*client;
31
	struct session		*session;
32
	struct window		*window;
33
	int			 pane;
34
35
	struct cmd_find_state	 fs;
36
};
37
38
static void
39
notify_hook(struct cmdq_item *item, struct notify_entry *ne)
40
{
41
	struct cmd_find_state	 fs;
42
	struct hook		*hook;
43
	struct cmdq_item	*new_item;
44
	struct session		*s = ne->session;
45
	struct window		*w = ne->window;
46
47
	cmd_find_clear_state(&fs, 0);
48
	if (cmd_find_empty_state(&ne->fs) || !cmd_find_valid_state(&ne->fs))
49
		cmd_find_from_nothing(&fs, 0);
50
	else
51
		cmd_find_copy_state(&fs, &ne->fs);
52
53
	hook = hooks_find(hooks_get(fs.s), ne->name);
54
	if (hook == NULL)
55
		return;
56
	log_debug("notify hook %s", ne->name);
57
58
	new_item = cmdq_get_command(hook->cmdlist, &fs, NULL, CMDQ_NOHOOKS);
59
	cmdq_format(new_item, "hook", "%s", ne->name);
60
61
	if (s != NULL) {
62
		cmdq_format(new_item, "hook_session", "$%u", s->id);
63
		cmdq_format(new_item, "hook_session_name", "%s", s->name);
64
	}
65
	if (w != NULL) {
66
		cmdq_format(new_item, "hook_window", "@%u", w->id);
67
		cmdq_format(new_item, "hook_window_name", "%s", w->name);
68
	}
69
	if (ne->pane != -1)
70
		cmdq_format(new_item, "hook_pane", "%%%d", ne->pane);
71
72
	cmdq_insert_after(item, new_item);
73
}
74
75
static enum cmd_retval
76
notify_callback(struct cmdq_item *item, void *data)
77
{
78
	struct notify_entry	*ne = data;
79
80
	log_debug("%s: %s", __func__, ne->name);
81
82
	if (strcmp(ne->name, "pane-mode-changed") == 0)
83
		control_notify_pane_mode_changed(ne->pane);
84
	if (strcmp(ne->name, "window-layout-changed") == 0)
85
		control_notify_window_layout_changed(ne->window);
86
	if (strcmp(ne->name, "window-pane-changed") == 0)
87
		control_notify_window_pane_changed(ne->window);
88
	if (strcmp(ne->name, "window-unlinked") == 0)
89
		control_notify_window_unlinked(ne->session, ne->window);
90
	if (strcmp(ne->name, "window-linked") == 0)
91
		control_notify_window_linked(ne->session, ne->window);
92
	if (strcmp(ne->name, "window-renamed") == 0)
93
		control_notify_window_renamed(ne->window);
94
	if (strcmp(ne->name, "client-session-changed") == 0)
95
		control_notify_client_session_changed(ne->client);
96
	if (strcmp(ne->name, "session-renamed") == 0)
97
		control_notify_session_renamed(ne->session);
98
	if (strcmp(ne->name, "session-created") == 0)
99
		control_notify_session_created(ne->session);
100
	if (strcmp(ne->name, "session-closed") == 0)
101
		control_notify_session_closed(ne->session);
102
	if (strcmp(ne->name, "session-window-changed") == 0)
103
		control_notify_session_window_changed(ne->session);
104
105
	notify_hook(item, ne);
106
107
	if (ne->client != NULL)
108
		server_client_unref(ne->client);
109
	if (ne->session != NULL)
110
		session_remove_ref(ne->session, __func__);
111
	if (ne->window != NULL)
112
		window_remove_ref(ne->window, __func__);
113
114
	if (ne->fs.s != NULL)
115
		session_remove_ref(ne->fs.s, __func__);
116
117
	free((void *)ne->name);
118
	free(ne);
119
120
	return (CMD_RETURN_NORMAL);
121
}
122
123
static void
124
notify_add(const char *name, struct cmd_find_state *fs, struct client *c,
125
    struct session *s, struct window *w, struct window_pane *wp)
126
{
127
	struct notify_entry	*ne;
128
	struct cmdq_item	*new_item;
129
130
	ne = xcalloc(1, sizeof *ne);
131
	ne->name = xstrdup(name);
132
133
	ne->client = c;
134
	ne->session = s;
135
	ne->window = w;
136
137
	if (wp != NULL)
138
		ne->pane = wp->id;
139
	else
140
		ne->pane = -1;
141
142
	if (c != NULL)
143
		c->references++;
144
	if (s != NULL)
145
		session_add_ref(s, __func__);
146
	if (w != NULL)
147
		window_add_ref(w, __func__);
148
149
	cmd_find_copy_state(&ne->fs, fs);
150
	if (ne->fs.s != NULL) /* cmd_find_valid_state needs session */
151
		session_add_ref(ne->fs.s, __func__);
152
153
	new_item = cmdq_get_callback(notify_callback, ne);
154
	cmdq_append(NULL, new_item);
155
}
156
157
void
158
notify_input(struct window_pane *wp, struct evbuffer *input)
159
{
160
	struct client	*c;
161
162
	TAILQ_FOREACH(c, &clients, entry) {
163
		if (c->flags & CLIENT_CONTROL)
164
			control_notify_input(c, wp, input);
165
	}
166
}
167
168
void
169
notify_client(const char *name, struct client *c)
170
{
171
	struct cmd_find_state	fs;
172
173
	cmd_find_from_client(&fs, c, 0);
174
	notify_add(name, &fs, c, NULL, NULL, NULL);
175
}
176
177
void
178
notify_session(const char *name, struct session *s)
179
{
180
	struct cmd_find_state	fs;
181
182
	if (session_alive(s))
183
		cmd_find_from_session(&fs, s, 0);
184
	else
185
		cmd_find_from_nothing(&fs, 0);
186
	notify_add(name, &fs, NULL, s, NULL, NULL);
187
}
188
189
void
190
notify_winlink(const char *name, struct winlink *wl)
191
{
192
	struct cmd_find_state	fs;
193
194
	cmd_find_from_winlink(&fs, wl, 0);
195
	notify_add(name, &fs, NULL, wl->session, wl->window, NULL);
196
}
197
198
void
199
notify_session_window(const char *name, struct session *s, struct window *w)
200
{
201
	struct cmd_find_state	fs;
202
203
	cmd_find_from_session_window(&fs, s, w, 0);
204
	notify_add(name, &fs, NULL, s, w, NULL);
205
}
206
207
void
208
notify_window(const char *name, struct window *w)
209
{
210
	struct cmd_find_state	fs;
211
212
	cmd_find_from_window(&fs, w, 0);
213
	notify_add(name, &fs, NULL, NULL, w, NULL);
214
}
215
216
void
217
notify_pane(const char *name, struct window_pane *wp)
218
{
219
	struct cmd_find_state	fs;
220
221
	cmd_find_from_pane(&fs, wp, 0);
222
	notify_add(name, &fs, NULL, NULL, NULL, wp);
223
}