mirror of
https://github.com/sudo-project/sudo.git
synced 2025-08-22 01:49:11 +00:00
Simple event subsystem that uses poll() or select(). Basically a
simplied subset of libevent2. Currently only fd events are supported (since that's all we need). The poll() backend is used by default, except on Mac OS X where poll() is broken for devices (including /dev/tty and ptys).
This commit is contained in:
parent
ff18c65862
commit
79acd5db49
7
INSTALL
7
INSTALL
@ -150,6 +150,13 @@ Compilation options:
|
||||
option may be needed on some Linux systems where PIE binaries
|
||||
are not fully supported.
|
||||
|
||||
--disable-poll
|
||||
Use select() instead of poll() in the event loop. By default,
|
||||
sudo will use poll() on systems that support it. Some systems
|
||||
have a broken poll() implementation and need to use select instead.
|
||||
On Mac OS X, select() is always used since its poll() doesn't
|
||||
support devices.
|
||||
|
||||
--disable-rpath
|
||||
By default, configure will use -Rpath in addition to -Lpath
|
||||
when passing library paths to the loader. This option will
|
||||
|
4
MANIFEST
4
MANIFEST
@ -12,6 +12,9 @@ common/aix.c
|
||||
common/alloc.c
|
||||
common/atobool.c
|
||||
common/atoid.c
|
||||
common/event.c
|
||||
common/event_poll.c
|
||||
common/event_select.c
|
||||
common/fatal.c
|
||||
common/fileops.c
|
||||
common/fmt_string.c
|
||||
@ -147,6 +150,7 @@ include/missing.h
|
||||
include/secure_path.h
|
||||
include/sudo_conf.h
|
||||
include/sudo_debug.h
|
||||
include/sudo_event.h
|
||||
include/sudo_plugin.h
|
||||
indent.pro
|
||||
install-sh
|
||||
|
@ -66,9 +66,10 @@ DEFS = @OSDEFS@ -D_PATH_SUDO_CONF=\"$(sysconfdir)/sudo.conf\"
|
||||
|
||||
SHELL = @SHELL@
|
||||
|
||||
LTOBJS = alloc.lo atobool.lo atoid.lo fatal.lo fileops.lo fmt_string.lo \
|
||||
gidlist.lo lbuf.lo list.lo secure_path.lo setgroups.lo sudo_conf.lo \
|
||||
sudo_debug.lo sudo_printf.lo term.lo ttysize.lo @COMMON_OBJS@
|
||||
LTOBJS = alloc.lo atobool.lo atoid.lo event.lo fatal.lo fileops.lo \
|
||||
fmt_string.lo gidlist.lo lbuf.lo list.lo secure_path.lo \
|
||||
setgroups.lo sudo_conf.lo sudo_debug.lo sudo_printf.lo term.lo \
|
||||
ttysize.lo @COMMON_OBJS@
|
||||
|
||||
PARSELN_TEST_OBJS = parseln_test.lo
|
||||
|
||||
@ -171,6 +172,21 @@ conf_test.lo: $(srcdir)/regress/sudo_conf/conf_test.c $(top_builddir)/config.h \
|
||||
$(top_srcdir)/compat/stdbool.h $(incdir)/missing.h \
|
||||
$(incdir)/sudo_conf.h $(incdir)/list.h
|
||||
$(LIBTOOL) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(DEFS) $(srcdir)/regress/sudo_conf/conf_test.c
|
||||
event.lo: $(srcdir)/event.c $(top_builddir)/config.h \
|
||||
$(top_srcdir)/compat/stdbool.h $(incdir)/missing.h $(incdir)/alloc.h \
|
||||
$(incdir)/fatal.h $(incdir)/list.h $(incdir)/sudo_debug.h \
|
||||
$(incdir)/sudo_event.h
|
||||
$(LIBTOOL) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(DEFS) $(srcdir)/event.c
|
||||
event_poll.lo: $(srcdir)/event_poll.c $(top_builddir)/config.h \
|
||||
$(top_srcdir)/compat/stdbool.h $(incdir)/missing.h \
|
||||
$(incdir)/alloc.h $(incdir)/fatal.h $(incdir)/list.h \
|
||||
$(incdir)/sudo_debug.h $(incdir)/sudo_event.h
|
||||
$(LIBTOOL) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(DEFS) $(srcdir)/event_poll.c
|
||||
event_select.lo: $(srcdir)/event_select.c $(top_builddir)/config.h \
|
||||
$(top_srcdir)/compat/stdbool.h $(incdir)/missing.h \
|
||||
$(incdir)/alloc.h $(incdir)/fatal.h $(incdir)/list.h \
|
||||
$(incdir)/sudo_debug.h $(incdir)/sudo_event.h
|
||||
$(LIBTOOL) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(DEFS) $(srcdir)/event_select.c
|
||||
fatal.lo: $(srcdir)/fatal.c $(top_builddir)/config.h \
|
||||
$(top_srcdir)/compat/stdbool.h $(incdir)/missing.h $(incdir)/alloc.h \
|
||||
$(incdir)/fatal.h $(incdir)/sudo_plugin.h $(incdir)/gettext.h
|
||||
|
224
common/event.c
Normal file
224
common/event.c
Normal file
@ -0,0 +1,224 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <stdio.h>
|
||||
#ifdef STDC_HEADERS
|
||||
# include <stdlib.h>
|
||||
# include <stddef.h>
|
||||
#else
|
||||
# ifdef HAVE_STDLIB_H
|
||||
# include <stdlib.h>
|
||||
# endif
|
||||
#endif /* STDC_HEADERS */
|
||||
#ifdef HAVE_STDBOOL_H
|
||||
# include <stdbool.h>
|
||||
#else
|
||||
# include "compat/stdbool.h"
|
||||
#endif /* HAVE_STDBOOL_H */
|
||||
#ifdef HAVE_STRING_H
|
||||
# include <string.h>
|
||||
#endif /* HAVE_STRING_H */
|
||||
#ifdef HAVE_STRINGS_H
|
||||
# include <strings.h>
|
||||
#endif /* HAVE_STRINGS_H */
|
||||
#ifdef HAVE_UNISTD_H
|
||||
# include <unistd.h>
|
||||
#endif /* HAVE_UNISTD_H */
|
||||
#include <errno.h>
|
||||
|
||||
#include "missing.h"
|
||||
#include "alloc.h"
|
||||
#include "fatal.h"
|
||||
#include "list.h"
|
||||
#include "sudo_debug.h"
|
||||
#include "sudo_event.h"
|
||||
|
||||
/* XXX - use non-exiting allocators? */
|
||||
|
||||
struct sudo_event_base *
|
||||
sudo_ev_base_alloc(void)
|
||||
{
|
||||
struct sudo_event_base *base;
|
||||
debug_decl(sudo_ev_base_alloc, SUDO_DEBUG_EVENT)
|
||||
|
||||
base = ecalloc(1, sizeof(*base));
|
||||
if (sudo_ev_base_alloc_impl(base) != 0) {
|
||||
efree(base);
|
||||
base = NULL;
|
||||
}
|
||||
|
||||
debug_return_ptr(base);
|
||||
}
|
||||
|
||||
void
|
||||
sudo_ev_base_free(struct sudo_event_base *base)
|
||||
{
|
||||
debug_decl(sudo_ev_base_free, SUDO_DEBUG_EVENT)
|
||||
sudo_ev_base_free_impl(base);
|
||||
efree(base);
|
||||
debug_return;
|
||||
}
|
||||
|
||||
struct sudo_event *
|
||||
sudo_ev_alloc(int fd, short events, sudo_ev_callback_t callback, void *closure)
|
||||
{
|
||||
struct sudo_event *ev;
|
||||
debug_decl(sudo_ev_alloc, SUDO_DEBUG_EVENT)
|
||||
|
||||
ev = ecalloc(1, sizeof(*ev));
|
||||
ev->fd = fd;
|
||||
ev->events = events;
|
||||
ev->pfd_idx = -1;
|
||||
ev->callback = callback;
|
||||
ev->closure = closure;
|
||||
|
||||
debug_return_ptr(ev);
|
||||
}
|
||||
|
||||
void
|
||||
sudo_ev_free(struct sudo_event *ev)
|
||||
{
|
||||
debug_decl(sudo_ev_free, SUDO_DEBUG_EVENT)
|
||||
free(ev);
|
||||
debug_return;
|
||||
}
|
||||
|
||||
int
|
||||
sudo_ev_add(struct sudo_event_base *base, struct sudo_event *ev, bool tohead)
|
||||
{
|
||||
debug_decl(sudo_ev_add, SUDO_DEBUG_EVENT)
|
||||
|
||||
/* Don't add an event twice; revisit if we want to support timeouts. */
|
||||
if (ev->base == NULL) {
|
||||
if (sudo_ev_add_impl(base, ev) != 0)
|
||||
debug_return_int(-1);
|
||||
ev->base = base;
|
||||
if (tohead) {
|
||||
tq_insert_head(base, ev);
|
||||
} else {
|
||||
tq_insert_tail(base, ev);
|
||||
}
|
||||
}
|
||||
/* Clear pending delete so adding from callback works properly. */
|
||||
CLR(ev->events, SUDO_EV_DELETE);
|
||||
debug_return_int(0);
|
||||
}
|
||||
|
||||
int
|
||||
sudo_ev_del(struct sudo_event_base *base, struct sudo_event *ev)
|
||||
{
|
||||
debug_decl(sudo_ev_del, SUDO_DEBUG_EVENT)
|
||||
|
||||
/* Make sure event is really in the queue. */
|
||||
if (ev->base == NULL) {
|
||||
sudo_debug_printf(SUDO_DEBUG_INFO, "%s: event %p not in queue",
|
||||
__func__, ev);
|
||||
debug_return_int(0);
|
||||
}
|
||||
|
||||
/* Check for event base mismatch, if one is specified. */
|
||||
if (base == NULL) {
|
||||
base = ev->base;
|
||||
} else if (base != ev->base) {
|
||||
sudo_debug_printf(SUDO_DEBUG_ERROR, "%s: mismatch base %p, ev->base %p",
|
||||
__func__, base, ev->base);
|
||||
debug_return_int(-1);
|
||||
}
|
||||
|
||||
sudo_debug_printf(SUDO_DEBUG_INFO, "%s: removing event %p from base %p",
|
||||
__func__, ev, base);
|
||||
|
||||
/* Call backend. */
|
||||
if (sudo_ev_del_impl(base, ev) != 0)
|
||||
debug_return_int(-1);
|
||||
|
||||
/* Unlink from list. */
|
||||
tq_remove(base, ev);
|
||||
|
||||
/* If we removed the pending event, replace it with the next one. */
|
||||
if (base->pending == ev)
|
||||
base->pending = ev->next;
|
||||
|
||||
/* Mark event unused. */
|
||||
ev->pfd_idx = -1;
|
||||
ev->base = NULL;
|
||||
ev->prev = NULL;
|
||||
ev->next = NULL;
|
||||
|
||||
debug_return_int(0);
|
||||
}
|
||||
|
||||
int
|
||||
sudo_ev_loop(struct sudo_event_base *base, int flags)
|
||||
{
|
||||
int rc;
|
||||
debug_decl(sudo_ev_loop, SUDO_DEBUG_EVENT)
|
||||
|
||||
/*
|
||||
* If sudo_ev_loopexit() was called when events were not running
|
||||
* the next invocation of sudo_ev_loop() only runs once.
|
||||
* All other base flags are ignored unless we are running events.
|
||||
*/
|
||||
if (ISSET(base->flags, SUDO_EVBASE_LOOPEXIT))
|
||||
flags |= SUDO_EVLOOP_ONCE;
|
||||
base->flags = 0;
|
||||
|
||||
/* Most work is done by the backend. */
|
||||
rc = sudo_ev_loop_impl(base, flags);
|
||||
base->flags &= SUDO_EVBASE_GOT_MASK;
|
||||
debug_return_int(rc);
|
||||
}
|
||||
|
||||
void
|
||||
sudo_ev_loopexit(struct sudo_event_base *base)
|
||||
{
|
||||
debug_decl(sudo_ev_loopexit, SUDO_DEBUG_EVENT)
|
||||
base->flags |= SUDO_EVBASE_LOOPEXIT;
|
||||
debug_return;
|
||||
}
|
||||
|
||||
void
|
||||
sudo_ev_loopbreak(struct sudo_event_base *base)
|
||||
{
|
||||
debug_decl(sudo_ev_loopbreak, SUDO_DEBUG_EVENT)
|
||||
base->flags |= SUDO_EVBASE_LOOPBREAK;
|
||||
debug_return;
|
||||
}
|
||||
|
||||
void
|
||||
sudo_ev_loopcontinue(struct sudo_event_base *base)
|
||||
{
|
||||
debug_decl(sudo_ev_loopcontinue, SUDO_DEBUG_EVENT)
|
||||
base->flags |= SUDO_EVBASE_LOOPCONT;
|
||||
debug_return;
|
||||
}
|
||||
|
||||
bool
|
||||
sudo_ev_got_exit(struct sudo_event_base *base)
|
||||
{
|
||||
debug_decl(sudo_ev_got_exit, SUDO_DEBUG_EVENT)
|
||||
debug_return_bool(ISSET(base->flags, SUDO_EVBASE_GOT_EXIT));
|
||||
}
|
||||
|
||||
bool
|
||||
sudo_ev_got_break(struct sudo_event_base *base)
|
||||
{
|
||||
debug_decl(sudo_ev_got_break, SUDO_DEBUG_EVENT)
|
||||
debug_return_bool(ISSET(base->flags, SUDO_EVBASE_GOT_BREAK));
|
||||
}
|
197
common/event_poll.c
Normal file
197
common/event_poll.c
Normal file
@ -0,0 +1,197 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <stdio.h>
|
||||
#ifdef STDC_HEADERS
|
||||
# include <stdlib.h>
|
||||
# include <stddef.h>
|
||||
#else
|
||||
# ifdef HAVE_STDLIB_H
|
||||
# include <stdlib.h>
|
||||
# endif
|
||||
#endif /* STDC_HEADERS */
|
||||
#ifdef HAVE_STDBOOL_H
|
||||
# include <stdbool.h>
|
||||
#else
|
||||
# include "compat/stdbool.h"
|
||||
#endif /* HAVE_STDBOOL_H */
|
||||
#ifdef HAVE_STRING_H
|
||||
# include <string.h>
|
||||
#endif /* HAVE_STRING_H */
|
||||
#ifdef HAVE_STRINGS_H
|
||||
# include <strings.h>
|
||||
#endif /* HAVE_STRINGS_H */
|
||||
#ifdef HAVE_UNISTD_H
|
||||
# include <unistd.h>
|
||||
#endif /* HAVE_UNISTD_H */
|
||||
#include <errno.h>
|
||||
#include <poll.h>
|
||||
|
||||
#include "missing.h"
|
||||
#include "alloc.h"
|
||||
#include "fatal.h"
|
||||
#include "list.h"
|
||||
#include "sudo_debug.h"
|
||||
#include "sudo_event.h"
|
||||
|
||||
/* XXX - use non-exiting allocators? */
|
||||
|
||||
int
|
||||
sudo_ev_base_alloc_impl(struct sudo_event_base *base)
|
||||
{
|
||||
int i;
|
||||
debug_decl(sudo_ev_base_alloc_impl, SUDO_DEBUG_EVENT)
|
||||
|
||||
base->pfd_high = -1;
|
||||
base->pfd_max = 32;
|
||||
base->pfds = erealloc3(NULL, base->pfd_max, sizeof(struct pollfd));
|
||||
for (i = 0; i < base->pfd_max; i++) {
|
||||
base->pfds[i].fd = -1;
|
||||
}
|
||||
|
||||
debug_return_int(0);
|
||||
}
|
||||
|
||||
void
|
||||
sudo_ev_base_free_impl(struct sudo_event_base *base)
|
||||
{
|
||||
debug_decl(sudo_ev_base_free_impl, SUDO_DEBUG_EVENT)
|
||||
efree(base->pfds);
|
||||
debug_return;
|
||||
}
|
||||
|
||||
int
|
||||
sudo_ev_add_impl(struct sudo_event_base *base, struct sudo_event *ev)
|
||||
{
|
||||
debug_decl(sudo_ev_add_impl, SUDO_DEBUG_EVENT)
|
||||
struct pollfd *pfd;
|
||||
|
||||
/* If out of space in pfds array, realloc. */
|
||||
if (base->pfd_free == base->pfd_max) {
|
||||
int i;
|
||||
base->pfd_max <<= 1;
|
||||
base->pfds =
|
||||
erealloc3(base->pfds, base->pfd_max, sizeof(struct pollfd));
|
||||
for (i = base->pfd_free; i < base->pfd_max; i++) {
|
||||
base->pfds[i].fd = -1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Fill in pfd entry. */
|
||||
ev->pfd_idx = base->pfd_free;
|
||||
pfd = &base->pfds[ev->pfd_idx];
|
||||
pfd->fd = ev->fd;
|
||||
pfd->events = 0;
|
||||
if (ISSET(ev->events, SUDO_EV_READ))
|
||||
pfd->events |= POLLIN;
|
||||
if (ISSET(ev->events, SUDO_EV_WRITE))
|
||||
pfd->events |= POLLOUT;
|
||||
|
||||
/* Update pfd_high and pfd_free. */
|
||||
if (ev->pfd_idx > base->pfd_high)
|
||||
base->pfd_high = ev->pfd_idx;
|
||||
for (;;) {
|
||||
if (++base->pfd_free == base->pfd_max)
|
||||
break;
|
||||
if (base->pfds[base->pfd_free].fd == -1)
|
||||
break;
|
||||
}
|
||||
|
||||
debug_return_int(0);
|
||||
}
|
||||
|
||||
int
|
||||
sudo_ev_del_impl(struct sudo_event_base *base, struct sudo_event *ev)
|
||||
{
|
||||
debug_decl(sudo_ev_del_impl, SUDO_DEBUG_EVENT)
|
||||
|
||||
/* Mark pfd entry unused, add to free list and adjust high slot. */
|
||||
base->pfds[ev->pfd_idx].fd = -1;
|
||||
if (ev->pfd_idx < base->pfd_free)
|
||||
base->pfd_free = ev->pfd_idx;
|
||||
while (base->pfd_high >= 0 && base->pfds[base->pfd_high].fd == -1)
|
||||
base->pfd_high--;
|
||||
|
||||
debug_return_int(0);
|
||||
}
|
||||
|
||||
int
|
||||
sudo_ev_loop_impl(struct sudo_event_base *base, int flags)
|
||||
{
|
||||
const int timeout = (flags & SUDO_EVLOOP_NONBLOCK) ? 0 : -1;
|
||||
struct sudo_event *ev;
|
||||
int nready;
|
||||
debug_decl(sudo_ev_loop_impl, SUDO_DEBUG_EVENT)
|
||||
|
||||
rescan:
|
||||
while (base->pfd_high != -1) {
|
||||
nready = poll(base->pfds, base->pfd_high + 1, timeout);
|
||||
sudo_debug_printf(SUDO_DEBUG_INFO, "%s: %d fds ready",
|
||||
__func__, nready);
|
||||
switch (nready) {
|
||||
case -1:
|
||||
if (errno == EINTR || errno == ENOMEM)
|
||||
continue;
|
||||
debug_return_int(-1);
|
||||
case 0:
|
||||
/* timeout or no events */
|
||||
break;
|
||||
default:
|
||||
/* Service each event that fired. */
|
||||
for (ev = tq_first(base); ev != NULL; ev = base->pending) {
|
||||
base->pending = list_next(ev);
|
||||
if (base->pfds[ev->pfd_idx].revents) {
|
||||
int what = 0;
|
||||
if (base->pfds[ev->pfd_idx].revents & (POLLIN|POLLHUP|POLLNVAL|POLLERR))
|
||||
what |= (ev->events & SUDO_EV_READ);
|
||||
if (base->pfds[ev->pfd_idx].revents & (POLLOUT|POLLHUP|POLLNVAL|POLLERR))
|
||||
what |= (ev->events & SUDO_EV_WRITE);
|
||||
if (!ISSET(ev->events, SUDO_EV_PERSIST))
|
||||
SET(ev->events, SUDO_EV_DELETE);
|
||||
ev->callback(ev->fd, what, ev->closure);
|
||||
if (ISSET(ev->events, SUDO_EV_DELETE))
|
||||
sudo_ev_del(base, ev);
|
||||
if (ISSET(base->flags, SUDO_EVBASE_LOOPBREAK)) {
|
||||
/* stop processing events immediately */
|
||||
base->flags |= SUDO_EVBASE_GOT_BREAK;
|
||||
base->pending = NULL;
|
||||
goto done;
|
||||
}
|
||||
if (ISSET(base->flags, SUDO_EVBASE_LOOPCONT)) {
|
||||
/* rescan events and start polling again */
|
||||
CLR(base->flags, SUDO_EVBASE_LOOPCONT);
|
||||
base->pending = NULL;
|
||||
goto rescan;
|
||||
}
|
||||
}
|
||||
}
|
||||
base->pending = NULL;
|
||||
if (ISSET(base->flags, SUDO_EVBASE_LOOPEXIT)) {
|
||||
/* exit loop after once through */
|
||||
base->flags |= SUDO_EVBASE_GOT_EXIT;
|
||||
goto done;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (flags & (SUDO_EVLOOP_ONCE | SUDO_EVLOOP_NONBLOCK))
|
||||
break;
|
||||
}
|
||||
done:
|
||||
debug_return_int(0);
|
||||
}
|
207
common/event_select.c
Normal file
207
common/event_select.c
Normal file
@ -0,0 +1,207 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#ifdef HAVE_SYS_SYSMACROS_H
|
||||
# include <sys/sysmacros.h>
|
||||
#endif
|
||||
#ifdef HAVE_SYS_SELECT_H
|
||||
# include <sys/select.h>
|
||||
#endif /* HAVE_SYS_SELECT_H */
|
||||
#include <stdio.h>
|
||||
#ifdef STDC_HEADERS
|
||||
# include <stdlib.h>
|
||||
# include <stddef.h>
|
||||
#else
|
||||
# ifdef HAVE_STDLIB_H
|
||||
# include <stdlib.h>
|
||||
# endif
|
||||
#endif /* STDC_HEADERS */
|
||||
#ifdef HAVE_STDBOOL_H
|
||||
# include <stdbool.h>
|
||||
#else
|
||||
# include "compat/stdbool.h"
|
||||
#endif /* HAVE_STDBOOL_H */
|
||||
#ifdef HAVE_STRING_H
|
||||
# include <string.h>
|
||||
#endif /* HAVE_STRING_H */
|
||||
#ifdef HAVE_STRINGS_H
|
||||
# include <strings.h>
|
||||
#endif /* HAVE_STRINGS_H */
|
||||
#ifdef HAVE_UNISTD_H
|
||||
# include <unistd.h>
|
||||
#endif /* HAVE_UNISTD_H */
|
||||
#include <errno.h>
|
||||
|
||||
#include "missing.h"
|
||||
#include "alloc.h"
|
||||
#include "fatal.h"
|
||||
#include "list.h"
|
||||
#include "sudo_debug.h"
|
||||
#include "sudo_event.h"
|
||||
|
||||
/* XXX - use non-exiting allocators? */
|
||||
|
||||
int
|
||||
sudo_ev_base_alloc_impl(struct sudo_event_base *base)
|
||||
{
|
||||
debug_decl(sudo_ev_base_alloc_impl, SUDO_DEBUG_EVENT)
|
||||
|
||||
base->maxfd = NFDBITS - 1;
|
||||
base->nevents = 0;
|
||||
base->readfds = ecalloc(1, sizeof(fd_mask));
|
||||
base->writefds = ecalloc(1, sizeof(fd_mask));
|
||||
|
||||
debug_return_int(0);
|
||||
}
|
||||
|
||||
void
|
||||
sudo_ev_base_free_impl(struct sudo_event_base *base)
|
||||
{
|
||||
debug_decl(sudo_ev_base_free_impl, SUDO_DEBUG_EVENT)
|
||||
efree(base->readfds);
|
||||
efree(base->writefds);
|
||||
debug_return;
|
||||
}
|
||||
|
||||
int
|
||||
sudo_ev_add_impl(struct sudo_event_base *base, struct sudo_event *ev)
|
||||
{
|
||||
debug_decl(sudo_ev_add_impl, SUDO_DEBUG_EVENT)
|
||||
|
||||
/* If out of space in fd sets, realloc. */
|
||||
if (ev->fd > base->maxfd) {
|
||||
const int n = howmany(ev->fd + 1, NFDBITS);
|
||||
efree(base->readfds);
|
||||
efree(base->writefds);
|
||||
base->readfds = ecalloc(n, sizeof(fd_mask));
|
||||
base->writefds = ecalloc(n, sizeof(fd_mask));
|
||||
base->maxfd = (n * NFDBITS) - 1;
|
||||
}
|
||||
base->nevents++;
|
||||
|
||||
debug_return_int(0);
|
||||
}
|
||||
|
||||
int
|
||||
sudo_ev_del_impl(struct sudo_event_base *base, struct sudo_event *ev)
|
||||
{
|
||||
debug_decl(sudo_ev_del_impl, SUDO_DEBUG_EVENT)
|
||||
|
||||
/* Remove from readfds and writefds and adjust event count. */
|
||||
FD_CLR(ev->fd, base->readfds);
|
||||
FD_CLR(ev->fd, base->writefds);
|
||||
base->nevents--;
|
||||
|
||||
debug_return_int(0);
|
||||
}
|
||||
|
||||
int
|
||||
sudo_ev_loop_impl(struct sudo_event_base *base, int flags)
|
||||
{
|
||||
struct timeval tv, *timeout;
|
||||
struct sudo_event *ev;
|
||||
int nready;
|
||||
debug_decl(sudo_ev_loop, SUDO_DEBUG_EVENT)
|
||||
|
||||
if (ISSET(flags, SUDO_EVLOOP_NONBLOCK)) {
|
||||
tv.tv_sec = 0;
|
||||
tv.tv_usec = 0;
|
||||
timeout = &tv;
|
||||
} else {
|
||||
timeout = NULL;
|
||||
}
|
||||
|
||||
rescan:
|
||||
while (base->nevents != 0) {
|
||||
int highfd = 0;
|
||||
/* For select we need to redo readfds and writefds each time. */
|
||||
memset(base->readfds, 0, howmany(base->maxfd + 1, NFDBITS) * sizeof(fd_mask));
|
||||
memset(base->writefds, 0, howmany(base->maxfd + 1, NFDBITS) * sizeof(fd_mask));
|
||||
tq_foreach_fwd(base, ev) {
|
||||
if (ISSET(ev->events, SUDO_EV_READ)) {
|
||||
sudo_debug_printf(SUDO_DEBUG_DEBUG, "%s: added fd %d to readfs",
|
||||
__func__, ev->fd);
|
||||
FD_SET(ev->fd, base->readfds);
|
||||
if (ev->fd > highfd)
|
||||
highfd = ev->fd;
|
||||
}
|
||||
if (ISSET(ev->events, SUDO_EV_WRITE)) {
|
||||
sudo_debug_printf(SUDO_DEBUG_DEBUG, "%s: added fd %d to writefds",
|
||||
__func__, ev->fd);
|
||||
FD_SET(ev->fd, base->writefds);
|
||||
if (ev->fd > highfd)
|
||||
highfd = ev->fd;
|
||||
}
|
||||
}
|
||||
sudo_debug_printf(SUDO_DEBUG_DEBUG, "%s: select high fd %d",
|
||||
__func__, highfd);
|
||||
nready = select(highfd + 1, base->readfds, base->writefds, NULL, timeout);
|
||||
sudo_debug_printf(SUDO_DEBUG_INFO, "%s: %d fds ready",
|
||||
__func__, nready);
|
||||
switch (nready) {
|
||||
case -1:
|
||||
if (errno == EINTR || errno == ENOMEM)
|
||||
continue;
|
||||
debug_return_int(-1);
|
||||
case 0:
|
||||
/* timeout or no events */
|
||||
break;
|
||||
default:
|
||||
/* Service each event that fired. */
|
||||
for (ev = tq_first(base); ev != NULL; ev = base->pending) {
|
||||
int what = 0;
|
||||
base->pending = list_next(ev);
|
||||
if (FD_ISSET(ev->fd, base->readfds))
|
||||
what |= (ev->events & SUDO_EV_READ);
|
||||
if (FD_ISSET(ev->fd, base->writefds))
|
||||
what |= (ev->events & SUDO_EV_WRITE);
|
||||
if (what != 0) {
|
||||
if (!ISSET(ev->events, SUDO_EV_PERSIST))
|
||||
SET(ev->events, SUDO_EV_DELETE);
|
||||
ev->callback(ev->fd, what, ev->closure);
|
||||
if (ISSET(ev->events, SUDO_EV_DELETE))
|
||||
sudo_ev_del(base, ev);
|
||||
if (ISSET(base->flags, SUDO_EVBASE_LOOPBREAK)) {
|
||||
/* stop processing events immediately */
|
||||
base->flags |= SUDO_EVBASE_GOT_BREAK;
|
||||
base->pending = NULL;
|
||||
goto done;
|
||||
}
|
||||
if (ISSET(base->flags, SUDO_EVBASE_LOOPCONT)) {
|
||||
/* rescan events and start polling again */
|
||||
CLR(base->flags, SUDO_EVBASE_LOOPCONT);
|
||||
base->pending = NULL;
|
||||
goto rescan;
|
||||
}
|
||||
}
|
||||
}
|
||||
base->pending = NULL;
|
||||
if (ISSET(base->flags, SUDO_EVBASE_LOOPEXIT)) {
|
||||
/* exit loop after once through */
|
||||
base->flags |= SUDO_EVBASE_GOT_EXIT;
|
||||
goto done;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (flags & (SUDO_EVLOOP_ONCE | SUDO_EVLOOP_NONBLOCK))
|
||||
break;
|
||||
}
|
||||
done:
|
||||
debug_return_int(0);
|
||||
}
|
@ -112,7 +112,7 @@ list_append(void *vl1, void *vl2)
|
||||
|
||||
/*
|
||||
* Append the list of entries to the head node and convert
|
||||
* e from a semi-circle queue to normal doubly-linked list.
|
||||
* from a semi-circle queue to normal doubly-linked list.
|
||||
*/
|
||||
void
|
||||
tq_append(void *vh, void *vl)
|
||||
@ -129,6 +129,42 @@ tq_append(void *vh, void *vl)
|
||||
h->last = tail;
|
||||
}
|
||||
|
||||
/*
|
||||
* Insert a single item at the head of the queue.
|
||||
*/
|
||||
void
|
||||
tq_insert_head(void *vh, void *vl)
|
||||
{
|
||||
struct list_head_proto *h = (struct list_head_proto *)vh;
|
||||
struct list_proto *l = (struct list_proto *)vl;
|
||||
|
||||
l->prev = NULL;
|
||||
l->next = h->first;
|
||||
if (tq_empty(h))
|
||||
h->last = l;
|
||||
else
|
||||
h->first->prev = l;
|
||||
h->first = l;
|
||||
}
|
||||
|
||||
/*
|
||||
* Insert a single item at the tail of the queue.
|
||||
*/
|
||||
void
|
||||
tq_insert_tail(void *vh, void *vl)
|
||||
{
|
||||
struct list_head_proto *h = (struct list_head_proto *)vh;
|
||||
struct list_proto *l = (struct list_proto *)vl;
|
||||
|
||||
l->prev = h->last;
|
||||
l->next = NULL;
|
||||
if (tq_empty(h))
|
||||
h->first = l;
|
||||
else
|
||||
h->last->next = l;
|
||||
h->last = l;
|
||||
}
|
||||
|
||||
/*
|
||||
* Remove element from the tail_queue
|
||||
*/
|
||||
@ -146,7 +182,7 @@ tq_remove(void *vh, void *vl)
|
||||
/* At least two elements in the list. */
|
||||
if (h->first == l) {
|
||||
h->first = l->next;
|
||||
h->first->prev = h->first;
|
||||
h->first->prev = h->first; /* XXX - do we rely on this behavior? */
|
||||
} else if (h->last == l) {
|
||||
h->last = l->prev;
|
||||
h->last->next = NULL;
|
||||
|
@ -103,6 +103,7 @@ const char *const sudo_debug_subsystems[] = {
|
||||
"plugin",
|
||||
"hooks",
|
||||
"sssd",
|
||||
"event",
|
||||
NULL
|
||||
};
|
||||
|
||||
|
@ -442,6 +442,9 @@
|
||||
/* Define to 1 if you have the <paths.h> header file. */
|
||||
#undef HAVE_PATHS_H
|
||||
|
||||
/* Define to 1 if you have the `poll' function. */
|
||||
#undef HAVE_POLL
|
||||
|
||||
/* Define to 1 if you have the `posix_openpt' function. */
|
||||
#undef HAVE_POSIX_OPENPT
|
||||
|
||||
|
36
configure
vendored
36
configure
vendored
@ -903,6 +903,7 @@ enable_warnings
|
||||
enable_werror
|
||||
enable_hardening
|
||||
enable_pie
|
||||
enable_poll
|
||||
enable_admin_flag
|
||||
enable_nls
|
||||
enable_rpath
|
||||
@ -1570,6 +1571,7 @@ Optional Features:
|
||||
--disable-hardening Do not use compiler/linker exploit mitigation
|
||||
options
|
||||
--enable-pie Build sudo as a position independent executable.
|
||||
--disable-poll Use select() instead of poll().
|
||||
--enable-admin-flag Whether to create a Ubuntu-style admin flag file
|
||||
--disable-nls Disable natural language support using gettext
|
||||
--disable-rpath Disable passing of -Rpath to the linker
|
||||
@ -5662,6 +5664,12 @@ if test "${enable_pie+set}" = set; then :
|
||||
fi
|
||||
|
||||
|
||||
# Check whether --enable-poll was given.
|
||||
if test "${enable_poll+set}" = set; then :
|
||||
enableval=$enable_poll;
|
||||
fi
|
||||
|
||||
|
||||
# Check whether --enable-admin-flag was given.
|
||||
if test "${enable_admin_flag+set}" = set; then :
|
||||
enableval=$enable_admin_flag; case "$enableval" in
|
||||
@ -14062,7 +14070,7 @@ _ACEOF
|
||||
fi
|
||||
done
|
||||
|
||||
COMMON_OBJS="$COMMON_OBJS aix.lo"
|
||||
COMMON_OBJS="${COMMON_OBJS} aix.lo"
|
||||
;;
|
||||
*-*-hiuxmpp*)
|
||||
: ${mansectsu='1m'}
|
||||
@ -14582,6 +14590,8 @@ done
|
||||
CHECKSHADOW="false"
|
||||
test -z "$with_pam" && AUTH_EXCL_DEF="PAM"
|
||||
: ${with_logincap='yes'}
|
||||
# Darwin has a broken poll()
|
||||
: ${enable_poll='no'}
|
||||
# Darwin 8 and above can interpose library symbols cleanly
|
||||
if test $OSMAJOR -ge 8; then
|
||||
$as_echo "#define HAVE___INTERPOSE 1" >>confdefs.h
|
||||
@ -20330,6 +20340,30 @@ done
|
||||
fi
|
||||
fi
|
||||
|
||||
if test X"$enable_poll" = X""; then
|
||||
for ac_func in poll
|
||||
do :
|
||||
ac_fn_c_check_func "$LINENO" "poll" "ac_cv_func_poll"
|
||||
if test "x$ac_cv_func_poll" = xyes; then :
|
||||
cat >>confdefs.h <<_ACEOF
|
||||
#define HAVE_POLL 1
|
||||
_ACEOF
|
||||
enable_poll=yes
|
||||
else
|
||||
enable_poll=no
|
||||
fi
|
||||
done
|
||||
|
||||
elif test X"$enable_poll" = X"yes"; then
|
||||
$as_echo "#define HAVE_POLL 1" >>confdefs.h
|
||||
|
||||
fi
|
||||
if test "$enable_poll" = "yes"; then
|
||||
COMMON_OBJS="${COMMON_OBJS} event_poll.lo"
|
||||
else
|
||||
COMMON_OBJS="${COMMON_OBJS} event_select.lo"
|
||||
fi
|
||||
|
||||
if test ${with_ldap-'no'} != "no"; then
|
||||
O_LDFLAGS="$LDFLAGS"
|
||||
if test "$with_ldap" != "yes"; then
|
||||
|
21
configure.in
21
configure.in
@ -1388,6 +1388,9 @@ AC_ARG_ENABLE(hardening,
|
||||
AC_ARG_ENABLE(pie,
|
||||
[AS_HELP_STRING([--enable-pie], [Build sudo as a position independent executable.])])
|
||||
|
||||
AC_ARG_ENABLE(poll,
|
||||
[AS_HELP_STRING([--disable-poll], [Use select() instead of poll().])])
|
||||
|
||||
AC_ARG_ENABLE(admin-flag,
|
||||
[AS_HELP_STRING([--enable-admin-flag], [Whether to create a Ubuntu-style admin flag file])],
|
||||
[ case "$enableval" in
|
||||
@ -1646,7 +1649,7 @@ case "$host" in
|
||||
|
||||
# AIX-specific functions
|
||||
AC_CHECK_FUNCS(getuserattr setauthdb setrlimit64)
|
||||
COMMON_OBJS="$COMMON_OBJS aix.lo"
|
||||
COMMON_OBJS="${COMMON_OBJS} aix.lo"
|
||||
;;
|
||||
*-*-hiuxmpp*)
|
||||
: ${mansectsu='1m'}
|
||||
@ -1963,6 +1966,8 @@ case "$host" in
|
||||
CHECKSHADOW="false"
|
||||
test -z "$with_pam" && AUTH_EXCL_DEF="PAM"
|
||||
: ${with_logincap='yes'}
|
||||
# Darwin has a broken poll()
|
||||
: ${enable_poll='no'}
|
||||
# Darwin 8 and above can interpose library symbols cleanly
|
||||
if test $OSMAJOR -ge 8; then
|
||||
AC_DEFINE(HAVE___INTERPOSE)
|
||||
@ -3217,6 +3222,20 @@ if test ${with_passwd-'no'} != "no"; then
|
||||
fi
|
||||
fi
|
||||
|
||||
dnl
|
||||
dnl Choose event subsystem backend: poll or select
|
||||
dnl
|
||||
if test X"$enable_poll" = X""; then
|
||||
AC_CHECK_FUNCS(poll, [enable_poll=yes], [enable_poll=no])
|
||||
elif test X"$enable_poll" = X"yes"; then
|
||||
AC_DEFINE(HAVE_POLL)
|
||||
fi
|
||||
if test "$enable_poll" = "yes"; then
|
||||
COMMON_OBJS="${COMMON_OBJS} event_poll.lo"
|
||||
else
|
||||
COMMON_OBJS="${COMMON_OBJS} event_select.lo"
|
||||
fi
|
||||
|
||||
dnl
|
||||
dnl extra lib and .o file for LDAP support
|
||||
dnl
|
||||
|
@ -69,6 +69,8 @@ struct n##_list { \
|
||||
*/
|
||||
void *tq_pop(void *);
|
||||
void tq_append(void *, void *);
|
||||
void tq_insert_head(void *, void *);
|
||||
void tq_insert_tail(void *, void *);
|
||||
void tq_remove(void *, void *);
|
||||
void list_append(void *, void *);
|
||||
void list2tq(void *, void *);
|
||||
|
@ -72,6 +72,7 @@
|
||||
#define SUDO_DEBUG_PLUGIN (24<<6) /* main plugin functions */
|
||||
#define SUDO_DEBUG_HOOKS (25<<6) /* hook functions */
|
||||
#define SUDO_DEBUG_SSSD (26<<6) /* sudoers SSSD */
|
||||
#define SUDO_DEBUG_EVENT (27<<6) /* event handling */
|
||||
#define SUDO_DEBUG_ALL 0xfff0 /* all subsystems */
|
||||
|
||||
/* Flag to include string version of errno in debug info. */
|
||||
|
122
include/sudo_event.h
Normal file
122
include/sudo_event.h
Normal file
@ -0,0 +1,122 @@
|
||||
/*
|
||||
* 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
|
||||
|
||||
/* Event types */
|
||||
#define SUDO_EV_READ 0x01 /* fire when readable */
|
||||
#define SUDO_EV_WRITE 0x02 /* fire when writable */
|
||||
#define SUDO_EV_PERSIST 0x04 /* persist until deleted */
|
||||
#define SUDO_EV_DELETE 0x08 /* deletion pending */
|
||||
|
||||
/* 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 {
|
||||
struct sudo_event *prev; /* must be first element in struct */
|
||||
struct sudo_event *next; /* must be second element in struct */
|
||||
struct sudo_event_base *base; /* base this event belongs to */
|
||||
int fd; /* fd we are interested in */
|
||||
short events; /* SUDO_EV_* flags */
|
||||
short pfd_idx; /* index into pfds array */
|
||||
sudo_ev_callback_t callback;/* user-provided callback */
|
||||
void *closure; /* user-provided data pointer */
|
||||
};
|
||||
|
||||
/* Tail queue of events. */
|
||||
struct sudo_event_base {
|
||||
struct sudo_event *first; /* must be first element in struct */
|
||||
struct sudo_event *last; /* must be second element in struct */
|
||||
struct sudo_event *pending; /* next event to be run in the event loop */
|
||||
#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; /* read I/O descriptor set */
|
||||
fd_set *writefds; /* write I/O descriptor set */
|
||||
int maxfd; /* max fd we can store in readfds/writefds */
|
||||
int nevents; /* number of events in the list */
|
||||
#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, 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);
|
||||
|
||||
/* 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 base an event is associated with or NULL. */
|
||||
#define sudo_ev_get_base(_ev) ((_ev) ? (_ev)->base : NULL)
|
||||
|
||||
/*
|
||||
* 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_loop_impl(struct sudo_event_base *base, int flags);
|
||||
|
||||
#endif /* _SUDO_EVENT_H */
|
2
mkdep.pl
2
mkdep.pl
@ -65,7 +65,7 @@ sub mkdep {
|
||||
|
||||
# Expand some configure bits
|
||||
$makefile =~ s:\@DEV\@::g;
|
||||
$makefile =~ s:\@COMMON_OBJS\@:aix.lo:;
|
||||
$makefile =~ s:\@COMMON_OBJS\@:aix.lo event_poll.lo event_select.lo:;
|
||||
$makefile =~ s:\@SUDO_OBJS\@:openbsd.o preload.o selinux.o sesh.o solaris.o sudo_noexec.lo:;
|
||||
$makefile =~ s:\@SUDOERS_OBJS\@:bsm_audit.lo linux_audit.lo ldap.lo sssd.lo:;
|
||||
# XXX - fill in AUTH_OBJS from contents of the auth dir instead
|
||||
|
@ -615,7 +615,8 @@ iolog.lo: $(srcdir)/iolog.c $(top_builddir)/config.h $(srcdir)/sudoers.h \
|
||||
$(incdir)/missing.h $(incdir)/fatal.h $(incdir)/alloc.h \
|
||||
$(incdir)/list.h $(incdir)/fileops.h $(srcdir)/defaults.h \
|
||||
$(devdir)/def_data.h $(srcdir)/logging.h $(srcdir)/sudo_nss.h \
|
||||
$(incdir)/sudo_plugin.h $(incdir)/sudo_debug.h $(incdir)/gettext.h
|
||||
$(incdir)/sudo_plugin.h $(incdir)/sudo_debug.h $(incdir)/gettext.h \
|
||||
$(srcdir)/iolog.h
|
||||
$(LIBTOOL) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(DEFS) $(srcdir)/iolog.c
|
||||
iolog_path.lo: $(srcdir)/iolog_path.c $(top_builddir)/config.h \
|
||||
$(srcdir)/sudoers.h $(top_srcdir)/compat/stdbool.h \
|
||||
@ -837,8 +838,9 @@ sudoreplay.o: $(srcdir)/sudoreplay.c $(top_builddir)/config.h \
|
||||
$(top_srcdir)/compat/timespec.h $(top_srcdir)/compat/stdbool.h \
|
||||
$(top_srcdir)/compat/getopt.h $(top_builddir)/pathnames.h \
|
||||
$(incdir)/missing.h $(incdir)/alloc.h $(incdir)/fatal.h \
|
||||
$(incdir)/gettext.h $(srcdir)/logging.h $(incdir)/sudo_plugin.h \
|
||||
$(incdir)/sudo_conf.h $(incdir)/list.h $(incdir)/sudo_debug.h
|
||||
$(incdir)/gettext.h $(srcdir)/logging.h $(srcdir)/iolog.h \
|
||||
$(incdir)/sudo_plugin.h $(incdir)/sudo_conf.h $(incdir)/list.h \
|
||||
$(incdir)/sudo_debug.h
|
||||
$(CC) -c $(CPPFLAGS) $(CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(DEFS) $(srcdir)/sudoreplay.c
|
||||
testsudoers.o: $(srcdir)/testsudoers.c $(top_builddir)/config.h \
|
||||
$(top_srcdir)/compat/fnmatch.h $(srcdir)/tsgetgrpw.h \
|
||||
|
@ -89,9 +89,9 @@ SHELL = @SHELL@
|
||||
|
||||
PROGS = @PROGS@
|
||||
|
||||
OBJS = conversation.o env_hooks.o exec.o exec_common.o exec_pty.o get_pty.o \
|
||||
hooks.o net_ifs.o load_plugins.o parse_args.o signal.o sudo.o \
|
||||
sudo_edit.o tgetpass.o ttyname.o utmp.o @SUDO_OBJS@
|
||||
OBJS = conversation.o env_hooks.o exec.o exec_common.o exec_pty.o \
|
||||
get_pty.o hooks.o net_ifs.o load_plugins.o parse_args.o signal.o \
|
||||
sudo.o sudo_edit.o tgetpass.o ttyname.o utmp.o @SUDO_OBJS@
|
||||
|
||||
SESH_OBJS = sesh.o locale_stub.o exec_common.o
|
||||
|
||||
|
@ -1177,7 +1177,7 @@ exec_monitor(struct command_details *details, int backchannel)
|
||||
warning(_("error reading from socketpair"));
|
||||
goto done;
|
||||
} else {
|
||||
/* /* short read or EOF, parent process died? */
|
||||
/* short read or EOF, parent process died? */
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user