1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146
|
/*
* Copyright (c) 2013 Todd C. Miller <Todd.Miller@courtesan.com>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef _SUDO_EVENT_H
#define _SUDO_EVENT_H
#include "queue.h"
/* Event types */
#define SUDO_EV_TIMEOUT 0x01 /* fire after timeout */
#define SUDO_EV_READ 0x02 /* fire when readable */
#define SUDO_EV_WRITE 0x04 /* fire when writable */
#define SUDO_EV_PERSIST 0x08 /* persist until deleted */
/* Event flags (internal) */
#define SUDO_EVQ_INSERTED 0x01 /* event is on the event queue */
#define SUDO_EVQ_ACTIVE 0x02 /* event is on the active queue */
#define SUDO_EVQ_TIMEOUTS 0x04 /* event is on the timeouts queue */
/* Event loop flags */
#define SUDO_EVLOOP_ONCE 0x01 /* Only run once through the loop */
#define SUDO_EVLOOP_NONBLOCK 0x02 /* Do not block in event loop */
/* Event base flags (internal) */
#define SUDO_EVBASE_LOOPEXIT 0x01
#define SUDO_EVBASE_LOOPBREAK 0x02
#define SUDO_EVBASE_LOOPCONT 0x04
#define SUDO_EVBASE_GOT_EXIT 0x10
#define SUDO_EVBASE_GOT_BREAK 0x20
#define SUDO_EVBASE_GOT_MASK 0xf0
typedef void (*sudo_ev_callback_t)(int fd, int what, void *closure);
/* Member of struct sudo_event_base. */
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; /* base this event belongs to */
int fd; /* fd we are interested in */
short events; /* SUDO_EV_* flags (in) */
short revents; /* SUDO_EV_* flags (out) */
short flags; /* internal event flags */
short pfd_idx; /* index into pfds array (XXX) */
sudo_ev_callback_t callback;/* user-provided callback */
struct timeval timeout; /* for SUDO_EV_TIMEOUT */
void *closure; /* user-provided data pointer */
};
TAILQ_HEAD(sudo_event_list, sudo_event);
struct sudo_event_base {
struct sudo_event_list events; /* tail queue of all events */
struct sudo_event_list active; /* tail queue of active events */
struct sudo_event_list timeouts; /* tail queue of timeout events */
#ifdef HAVE_POLL
struct pollfd *pfds; /* array of struct pollfd */
int pfd_max; /* size of the pfds array */
int pfd_high; /* highest slot used */
int pfd_free; /* idx of next free entry or pfd_max if full */
#else
fd_set *readfds_in; /* read I/O descriptor set (in) */
fd_set *writefds_in; /* write I/O descriptor set (in) */
fd_set *readfds_out; /* read I/O descriptor set (out) */
fd_set *writefds_out; /* write I/O descriptor set (out) */
int maxfd; /* max fd we can store in readfds/writefds */
int highfd; /* highest fd to pass as 1st arg to select */
#endif /* HAVE_POLL */
unsigned int flags; /* SUDO_EVBASE_* */
};
/* Allocate a new event base. */
struct sudo_event_base *sudo_ev_base_alloc(void);
/* Free an event base. */
void sudo_ev_base_free(struct sudo_event_base *base);
/* Allocate a new event. */
struct sudo_event *sudo_ev_alloc(int fd, short events, sudo_ev_callback_t callback, void *closure);
/* Free an event. */
void sudo_ev_free(struct sudo_event *ev);
/* Add an event, returns 0 on success, -1 on error */
int sudo_ev_add(struct sudo_event_base *head, struct sudo_event *ev, struct timeval *timo, bool tohead);
/* Delete an event, returns 0 on success, -1 on error */
int sudo_ev_del(struct sudo_event_base *head, struct sudo_event *ev);
/* Main event loop, returns SUDO_CB_SUCCESS, SUDO_CB_BREAK or SUDO_CB_ERROR */
int sudo_ev_loop(struct sudo_event_base *head, int flags);
/* Return the remaining timeout associated with an event. */
int sudo_ev_get_timeleft(struct sudo_event *ev, struct timeval *tv);
/* Cause the event loop to exit after one run through. */
void sudo_ev_loopexit(struct sudo_event_base *base);
/* Break out of the event loop right now. */
void sudo_ev_loopbreak(struct sudo_event_base *base);
/* Rescan for events and restart the event loop. */
void sudo_ev_loopcontinue(struct sudo_event_base *base);
/* Returns true if event loop stopped due to sudo_ev_loopexit(). */
bool sudo_ev_got_exit(struct sudo_event_base *base);
/* Returns true if event loop stopped due to sudo_ev_loopbreak(). */
bool sudo_ev_got_break(struct sudo_event_base *base);
/* Return the fd associated with an event. */
#define sudo_ev_get_fd(_ev) ((_ev) ? (_ev)->fd : -1)
/* Return the (absolute) timeout associated with an event or NULL. */
#define sudo_ev_get_timeout(_ev) \
(ISSET((_ev)->flags, SUDO_EVQ_TIMEOUTS) ? &(_ev)->timeout : NULL)
/* Return the base an event is associated with or NULL. */
#define sudo_ev_get_base(_ev) ((_ev) ? (_ev)->base : NULL)
/* Magic pointer value to use self pointer as callback arg. */
#define sudo_ev_self_cbarg() ((void *)-1)
/*
* Backend implementation.
*/
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, int flags);
#endif /* _SUDO_EVENT_H */
|