/src/tmux/events-payload.c
Line | Count | Source |
1 | | /* $OpenBSD: events-payload.c,v 1.1 2026/07/10 13:38:45 nicm Exp $ */ |
2 | | |
3 | | /* |
4 | | * Copyright (c) 2026 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 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 <stdarg.h> |
23 | | #include <stdlib.h> |
24 | | #include <string.h> |
25 | | #include <time.h> |
26 | | |
27 | | #include "tmux.h" |
28 | | |
29 | | /* Event payload item. */ |
30 | | struct event_payload_item { |
31 | | char *name; |
32 | | enum event_payload_type type; |
33 | | |
34 | | union { |
35 | | char *string; |
36 | | time_t time; |
37 | | int number; |
38 | | u_int unsigned_number; |
39 | | struct client *client; |
40 | | struct session *session; |
41 | | struct window *window; |
42 | | struct window_pane *pane; |
43 | | struct { |
44 | | void *ptr; |
45 | | event_payload_free_cb free_cb; |
46 | | event_payload_print_cb print_cb; |
47 | | } pointer; |
48 | | }; |
49 | | |
50 | | RB_ENTRY(event_payload_item) entry; |
51 | | }; |
52 | | |
53 | | RB_HEAD(event_payload_tree, event_payload_item); |
54 | | |
55 | | struct event_payload { |
56 | | struct event_payload_tree items; |
57 | | struct cmd_find_state target; |
58 | | }; |
59 | | |
60 | | static int |
61 | | event_payload_cmp(struct event_payload_item *epi1, |
62 | | struct event_payload_item *epi2) |
63 | 55.8k | { |
64 | 55.8k | return (strcmp(epi1->name, epi2->name)); |
65 | 55.8k | } |
66 | 552k | RB_GENERATE_STATIC(event_payload_tree, event_payload_item, entry, events-payload.c:event_payload_tree_RB_MINMAX Line | Count | Source | 66 | | RB_GENERATE_STATIC(event_payload_tree, event_payload_item, entry, |
events-payload.c:event_payload_tree_RB_REMOVE Line | Count | Source | 66 | | RB_GENERATE_STATIC(event_payload_tree, event_payload_item, entry, |
events-payload.c:event_payload_tree_RB_REMOVE_COLOR Line | Count | Source | 66 | | RB_GENERATE_STATIC(event_payload_tree, event_payload_item, entry, |
events-payload.c:event_payload_tree_RB_INSERT Line | Count | Source | 66 | | RB_GENERATE_STATIC(event_payload_tree, event_payload_item, entry, |
Unexecuted instantiation: events-payload.c:event_payload_tree_RB_FIND |
67 | 552k | event_payload_cmp); |
68 | 552k | |
69 | 552k | /* Find an item. */ |
70 | 552k | static struct event_payload_item * |
71 | 552k | event_payload_find(struct event_payload *ep, const char *name) |
72 | 552k | { |
73 | 0 | struct event_payload_item find = { .name = (char *)name }; |
74 | |
|
75 | 0 | return (RB_FIND(event_payload_tree, &ep->items, &find)); |
76 | 0 | } |
77 | | |
78 | | /* Free the target in a payload. */ |
79 | | static void |
80 | | event_payload_free_target(struct event_payload *ep) |
81 | 57.3k | { |
82 | 57.3k | struct cmd_find_state *target = &ep->target; |
83 | | |
84 | 57.3k | if (target->s != NULL) |
85 | 0 | session_remove_ref(target->s, __func__); |
86 | 57.3k | if (target->w != NULL) |
87 | 0 | window_remove_ref(target->w, __func__); |
88 | 57.3k | if (target->wp != NULL) |
89 | 0 | window_pane_remove_ref(target->wp, __func__); |
90 | | |
91 | 57.3k | cmd_find_clear_state(target, 0); |
92 | 57.3k | } |
93 | | |
94 | | /* Free the value in an item. */ |
95 | | static void |
96 | | event_payload_free_value(struct event_payload_item *epi) |
97 | 79.8k | { |
98 | 79.8k | switch (epi->type) { |
99 | 36.7k | case EVENT_PAYLOAD_STRING: |
100 | 36.7k | free(epi->string); |
101 | 36.7k | break; |
102 | 0 | case EVENT_PAYLOAD_CLIENT: |
103 | 0 | server_client_unref(epi->client); |
104 | 0 | break; |
105 | 0 | case EVENT_PAYLOAD_SESSION: |
106 | 0 | session_remove_ref(epi->session, __func__); |
107 | 0 | break; |
108 | 27.7k | case EVENT_PAYLOAD_WINDOW: |
109 | 27.7k | window_remove_ref(epi->window, __func__); |
110 | 27.7k | break; |
111 | 15.1k | case EVENT_PAYLOAD_PANE: |
112 | 15.1k | window_pane_remove_ref(epi->pane, __func__); |
113 | 15.1k | break; |
114 | 0 | case EVENT_PAYLOAD_POINTER: |
115 | 0 | if (epi->pointer.free_cb != NULL) |
116 | 0 | epi->pointer.free_cb(epi->pointer.ptr); |
117 | 0 | break; |
118 | 0 | case EVENT_PAYLOAD_INT: |
119 | 66 | case EVENT_PAYLOAD_UINT: |
120 | 132 | case EVENT_PAYLOAD_TIME: |
121 | 132 | break; |
122 | 79.8k | } |
123 | 79.8k | } |
124 | | |
125 | | /* Set an item. */ |
126 | | static void |
127 | | event_payload_set_item(struct event_payload *ep, const char *name, |
128 | | struct event_payload_item *new) |
129 | 79.8k | { |
130 | 79.8k | struct event_payload_item *old; |
131 | | |
132 | 79.8k | new->name = xstrdup(name); |
133 | 79.8k | old = RB_INSERT(event_payload_tree, &ep->items, new); |
134 | 79.8k | if (old != NULL) { |
135 | 0 | RB_REMOVE(event_payload_tree, &ep->items, old); |
136 | 0 | event_payload_free_value(old); |
137 | 0 | free(old->name); |
138 | 0 | free(old); |
139 | 0 | RB_INSERT(event_payload_tree, &ep->items, new); |
140 | 0 | } |
141 | 79.8k | } |
142 | | |
143 | | /* Create an event payload. */ |
144 | | struct event_payload * |
145 | | event_payload_create(void) |
146 | 29.5k | { |
147 | 29.5k | struct event_payload *ep; |
148 | | |
149 | 29.5k | ep = xcalloc(1, sizeof *ep); |
150 | 29.5k | RB_INIT(&ep->items); |
151 | 29.5k | cmd_find_clear_state(&ep->target, 0); |
152 | 29.5k | return (ep); |
153 | 29.5k | } |
154 | | |
155 | | /* Free an event payload. */ |
156 | | void |
157 | | event_payload_free(struct event_payload *ep) |
158 | 29.5k | { |
159 | 29.5k | struct event_payload_item *epi, *epi1; |
160 | | |
161 | 29.5k | if (ep != NULL) { |
162 | 79.8k | RB_FOREACH_SAFE(epi, event_payload_tree, &ep->items, epi1) { |
163 | 79.8k | RB_REMOVE(event_payload_tree, &ep->items, epi); |
164 | 79.8k | event_payload_free_value(epi); |
165 | 79.8k | free(epi->name); |
166 | 79.8k | free(epi); |
167 | 79.8k | } |
168 | 29.5k | event_payload_free_target(ep); |
169 | 29.5k | free(ep); |
170 | 29.5k | } |
171 | 29.5k | } |
172 | | |
173 | | /* Set the target. */ |
174 | | void |
175 | | event_payload_set_target(struct event_payload *ep, struct cmd_find_state *fs) |
176 | 27.7k | { |
177 | 27.7k | struct cmd_find_state *target = &ep->target; |
178 | | |
179 | 27.7k | event_payload_free_target(ep); |
180 | | |
181 | 27.7k | if (fs->s != NULL) { |
182 | 0 | session_add_ref(fs->s, __func__); |
183 | 0 | target->s = fs->s; |
184 | 0 | } |
185 | 27.7k | if (fs->wl != NULL) { |
186 | 0 | target->idx = fs->wl->idx; |
187 | 0 | if (target->s == NULL) { |
188 | 0 | session_add_ref(fs->wl->session, __func__); |
189 | 0 | target->s = fs->wl->session; |
190 | 0 | } |
191 | 0 | } else |
192 | 27.7k | target->idx = -1; |
193 | 27.7k | if (fs->w != NULL) { |
194 | 0 | window_add_ref(fs->w, __func__); |
195 | 0 | target->w = fs->w; |
196 | 27.7k | } else if (fs->wl != NULL) { |
197 | 0 | window_add_ref(fs->wl->window, __func__); |
198 | 0 | target->w = fs->wl->window; |
199 | 0 | } |
200 | 27.7k | if (fs->wp != NULL) { |
201 | 0 | window_pane_add_ref(fs->wp, __func__); |
202 | 0 | target->wp = fs->wp; |
203 | 0 | } |
204 | 27.7k | } |
205 | | |
206 | | /* Get the target. */ |
207 | | int |
208 | | event_payload_get_target(struct event_payload *ep, struct cmd_find_state *fs) |
209 | 0 | { |
210 | 0 | struct cmd_find_state *t = &ep->target; |
211 | 0 | struct winlink *wl = NULL; |
212 | 0 | int flags = fs->flags; |
213 | |
|
214 | 0 | if (t->idx != -1 && |
215 | 0 | t->s != NULL && |
216 | 0 | t->w != NULL && |
217 | 0 | session_alive(t->s)) { |
218 | 0 | wl = winlink_find_by_index(&t->s->windows, t->idx); |
219 | 0 | if (wl != NULL && wl->window != t->w) |
220 | 0 | wl = NULL; |
221 | 0 | } |
222 | |
|
223 | 0 | cmd_find_clear_state(fs, flags); |
224 | 0 | fs->s = t->s; |
225 | 0 | fs->w = t->w; |
226 | 0 | fs->wp = t->wp; |
227 | 0 | fs->wl = wl; |
228 | 0 | fs->idx = (wl != NULL ? wl->idx : -1); |
229 | 0 | if (cmd_find_valid_state(fs)) |
230 | 0 | return (1); |
231 | | |
232 | 0 | if (wl != NULL && |
233 | 0 | t->wp != NULL && |
234 | 0 | window_has_pane(wl->window, t->wp)) { |
235 | 0 | cmd_find_from_winlink_pane(fs, wl, t->wp, flags); |
236 | 0 | if (cmd_find_valid_state(fs)) |
237 | 0 | return (1); |
238 | 0 | } |
239 | | |
240 | 0 | if (t->wp != NULL && |
241 | 0 | cmd_find_from_pane(fs, t->wp, flags) == 0 && |
242 | 0 | cmd_find_valid_state(fs)) |
243 | 0 | return (1); |
244 | | |
245 | 0 | if (wl != NULL) { |
246 | 0 | cmd_find_from_winlink(fs, wl, flags); |
247 | 0 | if (cmd_find_valid_state(fs)) |
248 | 0 | return (1); |
249 | 0 | } |
250 | | |
251 | 0 | if (t->s != NULL && |
252 | 0 | t->w != NULL && |
253 | 0 | session_alive(t->s) && |
254 | 0 | cmd_find_from_session_window(fs, t->s, t->w, flags) == 0 && |
255 | 0 | cmd_find_valid_state(fs)) |
256 | 0 | return (1); |
257 | | |
258 | 0 | if (t->s != NULL && session_alive(t->s)) { |
259 | 0 | cmd_find_from_session(fs, t->s, flags); |
260 | 0 | if (cmd_find_valid_state(fs)) |
261 | 0 | return (1); |
262 | 0 | } |
263 | | |
264 | 0 | if (cmd_find_from_nothing(fs, flags) == 0) |
265 | 0 | return (1); |
266 | | |
267 | 0 | cmd_find_clear_state(fs, flags); |
268 | 0 | return (0); |
269 | 0 | } |
270 | | |
271 | | /* Set a string item. */ |
272 | | void |
273 | | event_payload_set_string(struct event_payload *ep, const char *name, |
274 | | const char *fmt, ...) |
275 | 36.7k | { |
276 | 36.7k | struct event_payload_item *epi; |
277 | 36.7k | va_list ap; |
278 | | |
279 | 36.7k | va_start(ap, fmt); |
280 | | |
281 | 36.7k | epi = xcalloc(1, sizeof *epi); |
282 | 36.7k | epi->type = EVENT_PAYLOAD_STRING; |
283 | 36.7k | xvasprintf(&epi->string, fmt, ap); |
284 | 36.7k | event_payload_set_item(ep, name, epi); |
285 | | |
286 | 36.7k | va_end(ap); |
287 | 36.7k | } |
288 | | |
289 | | /* Set a time item. */ |
290 | | void |
291 | | event_payload_set_time(struct event_payload *ep, const char *name, |
292 | | time_t value) |
293 | 66 | { |
294 | 66 | struct event_payload_item *epi; |
295 | | |
296 | 66 | epi = xcalloc(1, sizeof *epi); |
297 | 66 | epi->type = EVENT_PAYLOAD_TIME; |
298 | 66 | epi->time = value; |
299 | 66 | event_payload_set_item(ep, name, epi); |
300 | 66 | } |
301 | | |
302 | | /* Set a number item. */ |
303 | | void |
304 | | event_payload_set_int(struct event_payload *ep, const char *name, int value) |
305 | 0 | { |
306 | 0 | struct event_payload_item *epi; |
307 | |
|
308 | 0 | epi = xcalloc(1, sizeof *epi); |
309 | 0 | epi->type = EVENT_PAYLOAD_INT; |
310 | 0 | epi->number = value; |
311 | 0 | event_payload_set_item(ep, name, epi); |
312 | 0 | } |
313 | | |
314 | | /* Set an unsigned number item. */ |
315 | | void |
316 | | event_payload_set_uint(struct event_payload *ep, const char *name, u_int value) |
317 | 66 | { |
318 | 66 | struct event_payload_item *epi; |
319 | | |
320 | 66 | epi = xcalloc(1, sizeof *epi); |
321 | 66 | epi->type = EVENT_PAYLOAD_UINT; |
322 | 66 | epi->unsigned_number = value; |
323 | 66 | event_payload_set_item(ep, name, epi); |
324 | 66 | } |
325 | | |
326 | | /* Set a client item. */ |
327 | | void |
328 | | event_payload_set_client(struct event_payload *ep, const char *name, |
329 | | struct client *c) |
330 | 0 | { |
331 | 0 | struct event_payload_item *epi; |
332 | |
|
333 | 0 | c->references++; |
334 | |
|
335 | 0 | epi = xcalloc(1, sizeof *epi); |
336 | 0 | epi->type = EVENT_PAYLOAD_CLIENT; |
337 | 0 | epi->client = c; |
338 | 0 | event_payload_set_item(ep, name, epi); |
339 | 0 | } |
340 | | |
341 | | /* Set a session item. */ |
342 | | void |
343 | | event_payload_set_session(struct event_payload *ep, const char *name, |
344 | | struct session *s) |
345 | 0 | { |
346 | 0 | struct event_payload_item *epi; |
347 | |
|
348 | 0 | session_add_ref(s, __func__); |
349 | |
|
350 | 0 | epi = xcalloc(1, sizeof *epi); |
351 | 0 | epi->type = EVENT_PAYLOAD_SESSION; |
352 | 0 | epi->session = s; |
353 | 0 | event_payload_set_item(ep, name, epi); |
354 | 0 | } |
355 | | |
356 | | /* Set a window item. */ |
357 | | void |
358 | | event_payload_set_window(struct event_payload *ep, const char *name, |
359 | | struct window *w) |
360 | 27.7k | { |
361 | 27.7k | struct event_payload_item *epi; |
362 | | |
363 | 27.7k | window_add_ref(w, __func__); |
364 | | |
365 | 27.7k | epi = xcalloc(1, sizeof *epi); |
366 | 27.7k | epi->type = EVENT_PAYLOAD_WINDOW; |
367 | 27.7k | epi->window = w; |
368 | 27.7k | event_payload_set_item(ep, name, epi); |
369 | 27.7k | } |
370 | | |
371 | | /* Set a pane item. */ |
372 | | void |
373 | | event_payload_set_pane(struct event_payload *ep, const char *name, |
374 | | struct window_pane *wp) |
375 | 15.1k | { |
376 | 15.1k | struct event_payload_item *epi; |
377 | | |
378 | 15.1k | window_pane_add_ref(wp, __func__); |
379 | | |
380 | 15.1k | epi = xcalloc(1, sizeof *epi); |
381 | 15.1k | epi->type = EVENT_PAYLOAD_PANE; |
382 | 15.1k | epi->pane = wp; |
383 | 15.1k | event_payload_set_item(ep, name, epi); |
384 | 15.1k | } |
385 | | |
386 | | /* Set a pointer item. */ |
387 | | void |
388 | | event_payload_set_pointer(struct event_payload *ep, const char *name, |
389 | | void *ptr, event_payload_free_cb free_cb, event_payload_print_cb print_cb) |
390 | 0 | { |
391 | 0 | struct event_payload_item *epi; |
392 | |
|
393 | 0 | epi = xcalloc(1, sizeof *epi); |
394 | 0 | epi->type = EVENT_PAYLOAD_POINTER; |
395 | 0 | epi->pointer.ptr = ptr; |
396 | 0 | epi->pointer.free_cb = free_cb; |
397 | 0 | epi->pointer.print_cb = print_cb; |
398 | 0 | event_payload_set_item(ep, name, epi); |
399 | 0 | } |
400 | | |
401 | | /* Get a string item. */ |
402 | | const char * |
403 | | event_payload_get_string(struct event_payload *ep, const char *name) |
404 | 0 | { |
405 | 0 | struct event_payload_item *epi; |
406 | |
|
407 | 0 | epi = event_payload_find(ep, name); |
408 | 0 | if (epi == NULL || epi->type != EVENT_PAYLOAD_STRING) |
409 | 0 | return (NULL); |
410 | 0 | return (epi->string); |
411 | 0 | } |
412 | | |
413 | | /* Print a payload item. */ |
414 | | static void |
415 | | event_payload_add_item(struct event_payload_item *epi, struct evbuffer *evb) |
416 | 0 | { |
417 | 0 | switch (epi->type) { |
418 | 0 | case EVENT_PAYLOAD_STRING: |
419 | 0 | evbuffer_add_printf(evb, "%s", epi->string); |
420 | 0 | break; |
421 | 0 | case EVENT_PAYLOAD_TIME: |
422 | 0 | evbuffer_add_printf(evb, "%lld", (long long)epi->time); |
423 | 0 | break; |
424 | 0 | case EVENT_PAYLOAD_INT: |
425 | 0 | evbuffer_add_printf(evb, "%d", epi->number); |
426 | 0 | break; |
427 | 0 | case EVENT_PAYLOAD_UINT: |
428 | 0 | evbuffer_add_printf(evb, "%u", epi->unsigned_number); |
429 | 0 | break; |
430 | 0 | case EVENT_PAYLOAD_CLIENT: |
431 | 0 | evbuffer_add_printf(evb, "%s", epi->client->name); |
432 | 0 | break; |
433 | 0 | case EVENT_PAYLOAD_SESSION: |
434 | 0 | evbuffer_add_printf(evb, "$%u", epi->session->id); |
435 | 0 | break; |
436 | 0 | case EVENT_PAYLOAD_WINDOW: |
437 | 0 | evbuffer_add_printf(evb, "@%u", epi->window->id); |
438 | 0 | break; |
439 | 0 | case EVENT_PAYLOAD_PANE: |
440 | 0 | evbuffer_add_printf(evb, "%%%u", epi->pane->id); |
441 | 0 | break; |
442 | 0 | case EVENT_PAYLOAD_POINTER: |
443 | 0 | if (epi->pointer.print_cb != NULL) |
444 | 0 | epi->pointer.print_cb(epi->pointer.ptr, evb); |
445 | 0 | else |
446 | 0 | evbuffer_add_printf(evb, "%p", epi->pointer.ptr); |
447 | 0 | break; |
448 | 0 | } |
449 | 0 | } |
450 | | |
451 | | /* Print a payload item. */ |
452 | | char * |
453 | | event_payload_item_print(struct event_payload_item *epi) |
454 | 0 | { |
455 | 0 | struct evbuffer *evb; |
456 | 0 | char *value = NULL; |
457 | 0 | size_t size; |
458 | |
|
459 | 0 | evb = evbuffer_new(); |
460 | 0 | if (evb == NULL) |
461 | 0 | fatalx("out of memory"); |
462 | 0 | event_payload_add_item(epi, evb); |
463 | 0 | if ((size = EVBUFFER_LENGTH(evb)) != 0) |
464 | 0 | value = xmemdup(EVBUFFER_DATA(evb), size); |
465 | 0 | else |
466 | 0 | value = xstrdup(""); |
467 | 0 | evbuffer_free(evb); |
468 | 0 | return (value); |
469 | 0 | } |
470 | | |
471 | | /* Print an item value. */ |
472 | | char * |
473 | | event_payload_print(struct event_payload *ep, const char *name) |
474 | 0 | { |
475 | 0 | struct event_payload_item *epi; |
476 | |
|
477 | 0 | epi = event_payload_find(ep, name); |
478 | 0 | if (epi == NULL) |
479 | 0 | return (NULL); |
480 | 0 | return (event_payload_item_print(epi)); |
481 | 0 | } |
482 | | |
483 | | /* Add payload items as formats. */ |
484 | | void |
485 | | event_payload_add_formats(struct event_payload *ep, struct format_tree *ft, |
486 | | const char *prefix) |
487 | 0 | { |
488 | 0 | struct event_payload_item *epi; |
489 | 0 | char *name, *value; |
490 | 0 | const char *key; |
491 | |
|
492 | 0 | if (prefix == NULL) |
493 | 0 | prefix = ""; |
494 | |
|
495 | 0 | RB_FOREACH(epi, event_payload_tree, &ep->items) { |
496 | 0 | key = epi->name; |
497 | 0 | if (*key == '_') |
498 | 0 | continue; |
499 | | |
500 | 0 | value = event_payload_item_print(epi); |
501 | 0 | xasprintf(&name, "%s%s", prefix, key); |
502 | 0 | format_add(ft, name, "%s", value); |
503 | 0 | free(name); |
504 | 0 | free(value); |
505 | |
|
506 | 0 | if (epi->type == EVENT_PAYLOAD_SESSION) { |
507 | 0 | xasprintf(&name, "%s%s_name", prefix, key); |
508 | 0 | format_add(ft, name, "%s", epi->session->name); |
509 | 0 | free(name); |
510 | 0 | } else if (epi->type == EVENT_PAYLOAD_WINDOW) { |
511 | 0 | xasprintf(&name, "%s%s_name", prefix, key); |
512 | 0 | format_add(ft, name, "%s", epi->window->name); |
513 | 0 | free(name); |
514 | 0 | } |
515 | 0 | } |
516 | 0 | } |
517 | | |
518 | | /* Get the first payload item. */ |
519 | | struct event_payload_item * |
520 | | event_payload_first(struct event_payload *ep) |
521 | 0 | { |
522 | 0 | return (RB_MIN(event_payload_tree, &ep->items)); |
523 | 0 | } |
524 | | |
525 | | /* Get the next payload item. */ |
526 | | struct event_payload_item * |
527 | | event_payload_next(struct event_payload_item *epi) |
528 | 0 | { |
529 | 0 | return (RB_NEXT(event_payload_tree, , epi)); |
530 | 0 | } |
531 | | |
532 | | /* Get a payload item name. */ |
533 | | const char * |
534 | | event_payload_item_name(struct event_payload_item *epi) |
535 | 0 | { |
536 | 0 | return (epi->name); |
537 | 0 | } |
538 | | |
539 | | /* Get a payload item type. */ |
540 | | enum event_payload_type |
541 | | event_payload_item_type(struct event_payload_item *epi) |
542 | 0 | { |
543 | 0 | return (epi->type); |
544 | 0 | } |
545 | | |
546 | | /* Log a payload. */ |
547 | | void |
548 | | event_payload_log(struct event_payload *ep, const char *fmt, ...) |
549 | 0 | { |
550 | 0 | struct event_payload_item *epi; |
551 | 0 | struct evbuffer *evb; |
552 | 0 | va_list ap; |
553 | 0 | char *prefix; |
554 | |
|
555 | 0 | va_start(ap, fmt); |
556 | 0 | xvasprintf(&prefix, fmt, ap); |
557 | 0 | va_end(ap); |
558 | |
|
559 | 0 | evb = evbuffer_new(); |
560 | 0 | if (evb == NULL) |
561 | 0 | fatalx("out of memory"); |
562 | 0 | if (ep != NULL) { |
563 | 0 | RB_FOREACH(epi, event_payload_tree, &ep->items) { |
564 | 0 | if (EVBUFFER_LENGTH(evb) != 0) |
565 | 0 | evbuffer_add_printf(evb, ", "); |
566 | 0 | evbuffer_add_printf(evb, "%s=", epi->name); |
567 | 0 | event_payload_add_item(epi, evb); |
568 | 0 | } |
569 | 0 | } |
570 | 0 | log_debug("%s%.*s", prefix, (int)EVBUFFER_LENGTH(evb), |
571 | 0 | (char *)EVBUFFER_DATA(evb)); |
572 | 0 | evbuffer_free(evb); |
573 | 0 | free(prefix); |
574 | 0 | } |
575 | | |
576 | | /* Get a time item. */ |
577 | | time_t |
578 | | event_payload_get_time(struct event_payload *ep, const char *name) |
579 | 0 | { |
580 | 0 | struct event_payload_item *epi; |
581 | |
|
582 | 0 | epi = event_payload_find(ep, name); |
583 | 0 | if (epi == NULL || epi->type != EVENT_PAYLOAD_TIME) |
584 | 0 | return (0); |
585 | 0 | return (epi->time); |
586 | 0 | } |
587 | | |
588 | | /* Get a number item. */ |
589 | | int |
590 | | event_payload_get_int(struct event_payload *ep, const char *name, int *value) |
591 | 0 | { |
592 | 0 | struct event_payload_item *epi; |
593 | |
|
594 | 0 | epi = event_payload_find(ep, name); |
595 | 0 | if (epi == NULL || epi->type != EVENT_PAYLOAD_INT) |
596 | 0 | return (-1); |
597 | 0 | *value = epi->number; |
598 | 0 | return (0); |
599 | 0 | } |
600 | | |
601 | | /* Get an unsigned number item. */ |
602 | | int |
603 | | event_payload_get_uint(struct event_payload *ep, const char *name, u_int *value) |
604 | 0 | { |
605 | 0 | struct event_payload_item *epi; |
606 | |
|
607 | 0 | epi = event_payload_find(ep, name); |
608 | 0 | if (epi == NULL || epi->type != EVENT_PAYLOAD_UINT) |
609 | 0 | return (-1); |
610 | 0 | *value = epi->unsigned_number; |
611 | 0 | return (0); |
612 | 0 | } |
613 | | |
614 | | /* Get a client item. */ |
615 | | struct client * |
616 | | event_payload_get_client(struct event_payload *ep, const char *name) |
617 | 0 | { |
618 | 0 | struct event_payload_item *epi; |
619 | |
|
620 | 0 | epi = event_payload_find(ep, name); |
621 | 0 | if (epi == NULL || epi->type != EVENT_PAYLOAD_CLIENT) |
622 | 0 | return (NULL); |
623 | 0 | return (epi->client); |
624 | 0 | } |
625 | | |
626 | | /* Get a session item. */ |
627 | | struct session * |
628 | | event_payload_get_session(struct event_payload *ep, const char *name) |
629 | 0 | { |
630 | 0 | struct event_payload_item *epi; |
631 | |
|
632 | 0 | epi = event_payload_find(ep, name); |
633 | 0 | if (epi == NULL || epi->type != EVENT_PAYLOAD_SESSION) |
634 | 0 | return (NULL); |
635 | 0 | return (epi->session); |
636 | 0 | } |
637 | | |
638 | | /* Get a window item. */ |
639 | | struct window * |
640 | | event_payload_get_window(struct event_payload *ep, const char *name) |
641 | 0 | { |
642 | 0 | struct event_payload_item *epi; |
643 | |
|
644 | 0 | epi = event_payload_find(ep, name); |
645 | 0 | if (epi == NULL || epi->type != EVENT_PAYLOAD_WINDOW) |
646 | 0 | return (NULL); |
647 | 0 | return (epi->window); |
648 | 0 | } |
649 | | |
650 | | /* Get a pane item. */ |
651 | | struct window_pane * |
652 | | event_payload_get_pane(struct event_payload *ep, const char *name) |
653 | 0 | { |
654 | 0 | struct event_payload_item *epi; |
655 | |
|
656 | 0 | epi = event_payload_find(ep, name); |
657 | 0 | if (epi == NULL || epi->type != EVENT_PAYLOAD_PANE) |
658 | 0 | return (NULL); |
659 | 0 | return (epi->pane); |
660 | 0 | } |
661 | | |
662 | | /* Get a pointer item. */ |
663 | | void * |
664 | | event_payload_get_pointer(struct event_payload *ep, const char *name) |
665 | 0 | { |
666 | 0 | struct event_payload_item *epi; |
667 | |
|
668 | 0 | epi = event_payload_find(ep, name); |
669 | 0 | if (epi == NULL || epi->type != EVENT_PAYLOAD_POINTER) |
670 | 0 | return (NULL); |
671 | 0 | return (epi->pointer.ptr); |
672 | 0 | } |