#ifndef SUDO_EVENT_H
#define SUDO_EVENT_H
#include <time.h>
#include <signal.h>
#include <sudo_queue.h>
struct timeval;
#define SUDO_EV_TIMEOUT 0x01
#define SUDO_EV_READ 0x02
#define SUDO_EV_WRITE 0x04
#define SUDO_EV_PERSIST 0x08
#define SUDO_EV_SIGNAL 0x10
#define SUDO_EV_SIGINFO 0x20
#define SUDO_EV_MASK (SUDO_EV_READ|SUDO_EV_WRITE|SUDO_EV_PERSIST|SUDO_EV_SIGNAL|SUDO_EV_SIGINFO)
#define SUDO_EVQ_INSERTED 0x01U
#define SUDO_EVQ_ACTIVE 0x02U
#define SUDO_EVQ_TIMEOUTS 0x04U
#define SUDO_EVLOOP_ONCE 0x01U
#define SUDO_EVLOOP_NONBLOCK 0x02U
#define SUDO_EVBASE_LOOPONCE SUDO_EVLOOP_ONCE
#define SUDO_EVBASE_LOOPEXIT 0x02U
#define SUDO_EVBASE_LOOPBREAK 0x04U
#define SUDO_EVBASE_LOOPCONT 0x08U
#define SUDO_EVBASE_GOT_EXIT 0x10U
#define SUDO_EVBASE_GOT_BREAK 0x20U
#define SUDO_EVBASE_GOT_MASK 0xf0U
typedef void (*sudo_ev_callback_t)(int fd, int what, void *closure);
struct sudo_ev_siginfo_container {
void *closure;
siginfo_t *siginfo;
char si_buf[];
};
struct sudo_event {
TAILQ_ENTRY(sudo_event) entries;
TAILQ_ENTRY(sudo_event) active_entries;
TAILQ_ENTRY(sudo_event) timeouts_entries;
struct sudo_event_base *base;
int fd;
short events;
short revents;
unsigned short flags;
short pfd_idx;
sudo_ev_callback_t callback;
struct timespec timeout;
void *closure;
};
TAILQ_HEAD(sudo_event_list, sudo_event);
struct sudo_event_base {
struct sudo_event_list events;
struct sudo_event_list active;
struct sudo_event_list timeouts;
struct sudo_event signal_event;
struct sudo_event_list signals[NSIG];
struct sigaction *orig_handlers[NSIG];
siginfo_t *siginfo[NSIG];
sig_atomic_t signal_pending[NSIG];
sig_atomic_t signal_caught;
int num_handlers;
int signal_pipe[2];
#if defined(HAVE_POLL) || defined(HAVE_PPOLL)
struct pollfd *pfds;
int pfd_max;
int pfd_high;
int pfd_free;
#else
void *readfds_in;
void *writefds_in;
void *readfds_out;
void *writefds_out;
int maxfd;
int highfd;
#endif
unsigned int flags;
};
sudo_dso_public struct sudo_event_base *sudo_ev_base_alloc_v1(void);
#define sudo_ev_base_alloc() sudo_ev_base_alloc_v1()
sudo_dso_public void sudo_ev_base_free_v1(struct sudo_event_base *base);
#define sudo_ev_base_free(_a) sudo_ev_base_free_v1((_a))
sudo_dso_public void sudo_ev_base_setdef_v1(struct sudo_event_base *base);
#define sudo_ev_base_setdef(_a) sudo_ev_base_setdef_v1((_a))
sudo_dso_public struct sudo_event *sudo_ev_alloc_v1(int fd, short events, sudo_ev_callback_t callback, void *closure);
sudo_dso_public struct sudo_event *sudo_ev_alloc_v2(int fd, int events, sudo_ev_callback_t callback, void *closure);
#define sudo_ev_alloc(_a, _b, _c, _d) sudo_ev_alloc_v2((_a), (_b), (_c), (_d))
sudo_dso_public void sudo_ev_free_v1(struct sudo_event *ev);
#define sudo_ev_free(_a) sudo_ev_free_v1((_a))
sudo_dso_public int sudo_ev_set_v1(struct sudo_event *ev, int fd, short events, sudo_ev_callback_t callback, void *closure);
sudo_dso_public int sudo_ev_set_v2(struct sudo_event *ev, int fd, int events, sudo_ev_callback_t callback, void *closure);
#define sudo_ev_set(_a, _b, _c, _d, _e) sudo_ev_set_v2((_a), (_b), (_c), (_d), (_e))
sudo_dso_public int sudo_ev_add_v1(struct sudo_event_base *head, struct sudo_event *ev, const struct timeval *timo, bool tohead);
sudo_dso_public int sudo_ev_add_v2(struct sudo_event_base *head, struct sudo_event *ev, const struct timespec *timo, bool tohead);
#define sudo_ev_add(_a, _b, _c, _d) sudo_ev_add_v2((_a), (_b), (_c), (_d))
sudo_dso_public int sudo_ev_del_v1(struct sudo_event_base *head, struct sudo_event *ev);
#define sudo_ev_del(_a, _b) sudo_ev_del_v1((_a), (_b))
sudo_dso_public int sudo_ev_dispatch_v1(struct sudo_event_base *head);
#define sudo_ev_dispatch(_a) sudo_ev_dispatch_v1((_a))
sudo_dso_public int sudo_ev_loop_v1(struct sudo_event_base *head, unsigned int flags);
#define sudo_ev_loop(_a, _b) sudo_ev_loop_v1((_a), (_b))
sudo_dso_public int sudo_ev_pending_v1(struct sudo_event *ev, short events, struct timespec *ts);
sudo_dso_public int sudo_ev_pending_v2(struct sudo_event *ev, int events, struct timespec *ts);
#define sudo_ev_pending(_a, _b, _c) sudo_ev_pending_v2((_a), (_b), (_c))
sudo_dso_public int sudo_ev_get_timeleft_v1(struct sudo_event *ev, struct timeval *tv);
sudo_dso_public int sudo_ev_get_timeleft_v2(struct sudo_event *ev, struct timespec *tv);
#define sudo_ev_get_timeleft(_a, _b) sudo_ev_get_timeleft_v2((_a), (_b))
sudo_dso_public void sudo_ev_loopexit_v1(struct sudo_event_base *base);
#define sudo_ev_loopexit(_a) sudo_ev_loopexit_v1((_a))
sudo_dso_public void sudo_ev_loopbreak_v1(struct sudo_event_base *base);
#define sudo_ev_loopbreak(_a) sudo_ev_loopbreak_v1((_a))
sudo_dso_public void sudo_ev_loopcontinue_v1(struct sudo_event_base *base);
#define sudo_ev_loopcontinue(_a) sudo_ev_loopcontinue_v1((_a))
sudo_dso_public bool sudo_ev_got_exit_v1(struct sudo_event_base *base);
#define sudo_ev_got_exit(_a) sudo_ev_got_exit_v1((_a))
sudo_dso_public bool sudo_ev_got_break_v1(struct sudo_event_base *base);
#define sudo_ev_got_break(_a) sudo_ev_got_break_v1((_a))
#define sudo_ev_get_fd(_ev) ((_ev) ? (_ev)->fd : -1)
#define sudo_ev_get_timeout(_ev) \
(ISSET((_ev)->flags, SUDO_EVQ_TIMEOUTS) ? &(_ev)->timeout : NULL)
#define sudo_ev_get_base(_ev) ((_ev) ? (_ev)->base : NULL)
#define sudo_ev_set_base(_ev, _b) ((_ev)->base = (_b))
#define sudo_ev_self_cbarg() ((void *)-1)
void sudo_ev_activate(struct sudo_event_base *base, struct sudo_event *ev);
int sudo_ev_base_alloc_impl(struct sudo_event_base *base);
void sudo_ev_base_free_impl(struct sudo_event_base *base);
int sudo_ev_add_impl(struct sudo_event_base *base, struct sudo_event *ev);
int sudo_ev_del_impl(struct sudo_event_base *base, struct sudo_event *ev);
int sudo_ev_scan_impl(struct sudo_event_base *base, unsigned int flags);
#endif