Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sudo-project
GitHub Repository: sudo-project/sudo
Path: blob/main/include/sudo_event.h
1532 views
1
/*
2
* SPDX-License-Identifier: ISC
3
*
4
* Copyright (c) 2013-2015, 2017 Todd C. Miller <[email protected]>
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 IN AN
15
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17
*/
18
19
#ifndef SUDO_EVENT_H
20
#define SUDO_EVENT_H
21
22
#include <time.h> /* for struct timespec */
23
#include <signal.h> /* for sigatomic_t and NSIG */
24
#include <sudo_queue.h>
25
26
struct timeval; /* for deprecated APIs */
27
28
/* Event types (keep in sync with sudo_plugin.h) */
29
#define SUDO_EV_TIMEOUT 0x01 /* fire after timeout */
30
#define SUDO_EV_READ 0x02 /* fire when readable */
31
#define SUDO_EV_WRITE 0x04 /* fire when writable */
32
#define SUDO_EV_PERSIST 0x08 /* persist until deleted */
33
#define SUDO_EV_SIGNAL 0x10 /* fire on signal receipt */
34
#define SUDO_EV_SIGINFO 0x20 /* fire on signal receipt (siginfo) */
35
36
/* User-settable events for sudo_ev_init() (SUDO_EV_TIMEOUT not valid here) */
37
#define SUDO_EV_MASK (SUDO_EV_READ|SUDO_EV_WRITE|SUDO_EV_PERSIST|SUDO_EV_SIGNAL|SUDO_EV_SIGINFO)
38
39
/* Event flags (internal) */
40
#define SUDO_EVQ_INSERTED 0x01U /* event is on the event queue */
41
#define SUDO_EVQ_ACTIVE 0x02U /* event is on the active queue */
42
#define SUDO_EVQ_TIMEOUTS 0x04U /* event is on the timeouts queue */
43
44
/* Event loop flags */
45
#define SUDO_EVLOOP_ONCE 0x01U /* Only run once through the loop */
46
#define SUDO_EVLOOP_NONBLOCK 0x02U /* Do not block in event loop */
47
48
/* Event base flags (internal) */
49
#define SUDO_EVBASE_LOOPONCE SUDO_EVLOOP_ONCE
50
#define SUDO_EVBASE_LOOPEXIT 0x02U
51
#define SUDO_EVBASE_LOOPBREAK 0x04U
52
#define SUDO_EVBASE_LOOPCONT 0x08U
53
#define SUDO_EVBASE_GOT_EXIT 0x10U
54
#define SUDO_EVBASE_GOT_BREAK 0x20U
55
#define SUDO_EVBASE_GOT_MASK 0xf0U
56
57
/* Must match sudo_plugin_ev_callback_t in sudo_plugin.h */
58
typedef void (*sudo_ev_callback_t)(int fd, int what, void *closure);
59
60
/*
61
* Container for SUDO_EV_SIGINFO events that gets passed as the closure
62
* pointer. This allows us to pass a siginfo_t without changing everything.
63
*/
64
struct sudo_ev_siginfo_container {
65
void *closure;
66
siginfo_t *siginfo;
67
char si_buf[];
68
};
69
70
/* Member of struct sudo_event_base. */
71
struct sudo_event {
72
TAILQ_ENTRY(sudo_event) entries;
73
TAILQ_ENTRY(sudo_event) active_entries;
74
TAILQ_ENTRY(sudo_event) timeouts_entries;
75
struct sudo_event_base *base; /* base this event belongs to */
76
int fd; /* fd/signal we are interested in */
77
short events; /* SUDO_EV_* flags (in) */
78
short revents; /* SUDO_EV_* flags (out) */
79
unsigned short flags; /* internal event flags */
80
short pfd_idx; /* index into pfds array (XXX) */
81
sudo_ev_callback_t callback;/* user-provided callback */
82
struct timespec timeout; /* for SUDO_EV_TIMEOUT */
83
void *closure; /* user-provided data pointer */
84
};
85
TAILQ_HEAD(sudo_event_list, sudo_event);
86
87
struct sudo_event_base {
88
struct sudo_event_list events; /* tail queue of all events */
89
struct sudo_event_list active; /* tail queue of active events */
90
struct sudo_event_list timeouts; /* tail queue of timeout events */
91
struct sudo_event signal_event; /* storage for signal pipe event */
92
struct sudo_event_list signals[NSIG]; /* array of signal event tail queues */
93
struct sigaction *orig_handlers[NSIG]; /* original signal handlers */
94
siginfo_t *siginfo[NSIG]; /* detailed signal info */
95
sig_atomic_t signal_pending[NSIG]; /* pending signals */
96
sig_atomic_t signal_caught; /* at least one signal caught */
97
int num_handlers; /* number of installed handlers */
98
int signal_pipe[2]; /* so we can wake up on signal */
99
#if defined(HAVE_POLL) || defined(HAVE_PPOLL)
100
struct pollfd *pfds; /* array of struct pollfd */
101
int pfd_max; /* size of the pfds array */
102
int pfd_high; /* highest slot used */
103
int pfd_free; /* idx of next free entry or pfd_max if full */
104
#else
105
void *readfds_in; /* read I/O descriptor set (in) */
106
void *writefds_in; /* write I/O descriptor set (in) */
107
void *readfds_out; /* read I/O descriptor set (out) */
108
void *writefds_out; /* write I/O descriptor set (out) */
109
int maxfd; /* max fd we can store in readfds/writefds */
110
int highfd; /* highest fd to pass as 1st arg to select */
111
#endif /* HAVE_POLL */
112
unsigned int flags; /* SUDO_EVBASE_* */
113
};
114
115
/* Allocate a new event base. */
116
sudo_dso_public struct sudo_event_base *sudo_ev_base_alloc_v1(void);
117
#define sudo_ev_base_alloc() sudo_ev_base_alloc_v1()
118
119
/* Free an event base. */
120
sudo_dso_public void sudo_ev_base_free_v1(struct sudo_event_base *base);
121
#define sudo_ev_base_free(_a) sudo_ev_base_free_v1((_a))
122
123
/* Set the default event base. */
124
sudo_dso_public void sudo_ev_base_setdef_v1(struct sudo_event_base *base);
125
#define sudo_ev_base_setdef(_a) sudo_ev_base_setdef_v1((_a))
126
127
/* Allocate a new event. */
128
sudo_dso_public struct sudo_event *sudo_ev_alloc_v1(int fd, short events, sudo_ev_callback_t callback, void *closure);
129
sudo_dso_public struct sudo_event *sudo_ev_alloc_v2(int fd, int events, sudo_ev_callback_t callback, void *closure);
130
#define sudo_ev_alloc(_a, _b, _c, _d) sudo_ev_alloc_v2((_a), (_b), (_c), (_d))
131
132
/* Free an event. */
133
sudo_dso_public void sudo_ev_free_v1(struct sudo_event *ev);
134
#define sudo_ev_free(_a) sudo_ev_free_v1((_a))
135
136
/* Set an event struct that was pre-allocated. */
137
sudo_dso_public int sudo_ev_set_v1(struct sudo_event *ev, int fd, short events, sudo_ev_callback_t callback, void *closure);
138
sudo_dso_public int sudo_ev_set_v2(struct sudo_event *ev, int fd, int events, sudo_ev_callback_t callback, void *closure);
139
#define sudo_ev_set(_a, _b, _c, _d, _e) sudo_ev_set_v2((_a), (_b), (_c), (_d), (_e))
140
141
/* Add an event, returns 0 on success, -1 on error */
142
sudo_dso_public int sudo_ev_add_v1(struct sudo_event_base *head, struct sudo_event *ev, const struct timeval *timo, bool tohead);
143
sudo_dso_public int sudo_ev_add_v2(struct sudo_event_base *head, struct sudo_event *ev, const struct timespec *timo, bool tohead);
144
#define sudo_ev_add(_a, _b, _c, _d) sudo_ev_add_v2((_a), (_b), (_c), (_d))
145
146
/* Delete an event, returns 0 on success, -1 on error */
147
sudo_dso_public int sudo_ev_del_v1(struct sudo_event_base *head, struct sudo_event *ev);
148
#define sudo_ev_del(_a, _b) sudo_ev_del_v1((_a), (_b))
149
150
/* Dispatch events, returns SUDO_CB_SUCCESS, SUDO_CB_BREAK or SUDO_CB_ERROR */
151
sudo_dso_public int sudo_ev_dispatch_v1(struct sudo_event_base *head);
152
#define sudo_ev_dispatch(_a) sudo_ev_dispatch_v1((_a))
153
154
/* Main event loop, returns SUDO_CB_SUCCESS, SUDO_CB_BREAK or SUDO_CB_ERROR */
155
sudo_dso_public int sudo_ev_loop_v1(struct sudo_event_base *head, unsigned int flags);
156
#define sudo_ev_loop(_a, _b) sudo_ev_loop_v1((_a), (_b))
157
158
/* Return pending event types, fills in ts if non-NULL and there is a timeout */
159
sudo_dso_public int sudo_ev_pending_v1(struct sudo_event *ev, short events, struct timespec *ts);
160
sudo_dso_public int sudo_ev_pending_v2(struct sudo_event *ev, int events, struct timespec *ts);
161
#define sudo_ev_pending(_a, _b, _c) sudo_ev_pending_v2((_a), (_b), (_c))
162
163
/* Return the remaining timeout associated with an event (deprecated). */
164
sudo_dso_public int sudo_ev_get_timeleft_v1(struct sudo_event *ev, struct timeval *tv);
165
sudo_dso_public int sudo_ev_get_timeleft_v2(struct sudo_event *ev, struct timespec *tv);
166
#define sudo_ev_get_timeleft(_a, _b) sudo_ev_get_timeleft_v2((_a), (_b))
167
168
/* Cause the event loop to exit after one run through. */
169
sudo_dso_public void sudo_ev_loopexit_v1(struct sudo_event_base *base);
170
#define sudo_ev_loopexit(_a) sudo_ev_loopexit_v1((_a))
171
172
/* Break out of the event loop right now. */
173
sudo_dso_public void sudo_ev_loopbreak_v1(struct sudo_event_base *base);
174
#define sudo_ev_loopbreak(_a) sudo_ev_loopbreak_v1((_a))
175
176
/* Rescan for events and restart the event loop. */
177
sudo_dso_public void sudo_ev_loopcontinue_v1(struct sudo_event_base *base);
178
#define sudo_ev_loopcontinue(_a) sudo_ev_loopcontinue_v1((_a))
179
180
/* Returns true if event loop stopped due to sudo_ev_loopexit(). */
181
sudo_dso_public bool sudo_ev_got_exit_v1(struct sudo_event_base *base);
182
#define sudo_ev_got_exit(_a) sudo_ev_got_exit_v1((_a))
183
184
/* Returns true if event loop stopped due to sudo_ev_loopbreak(). */
185
sudo_dso_public bool sudo_ev_got_break_v1(struct sudo_event_base *base);
186
#define sudo_ev_got_break(_a) sudo_ev_got_break_v1((_a))
187
188
/* Return the fd associated with an event. */
189
#define sudo_ev_get_fd(_ev) ((_ev) ? (_ev)->fd : -1)
190
191
/* Return the (absolute) timeout associated with an event or NULL. */
192
#define sudo_ev_get_timeout(_ev) \
193
(ISSET((_ev)->flags, SUDO_EVQ_TIMEOUTS) ? &(_ev)->timeout : NULL)
194
195
/* Return the base an event is associated with or NULL. */
196
#define sudo_ev_get_base(_ev) ((_ev) ? (_ev)->base : NULL)
197
198
/* Set the base an event is associated with. */
199
#define sudo_ev_set_base(_ev, _b) ((_ev)->base = (_b))
200
201
/* Magic pointer value to use self pointer as callback arg. */
202
#define sudo_ev_self_cbarg() ((void *)-1)
203
204
/* Add an event to the base's active queue and mark it active (internal). */
205
void sudo_ev_activate(struct sudo_event_base *base, struct sudo_event *ev);
206
207
/*
208
* Backend implementation.
209
*/
210
int sudo_ev_base_alloc_impl(struct sudo_event_base *base);
211
void sudo_ev_base_free_impl(struct sudo_event_base *base);
212
int sudo_ev_add_impl(struct sudo_event_base *base, struct sudo_event *ev);
213
int sudo_ev_del_impl(struct sudo_event_base *base, struct sudo_event *ev);
214
int sudo_ev_scan_impl(struct sudo_event_base *base, unsigned int flags);
215
216
#endif /* SUDO_EVENT_H */
217
218