Replace eloop with libevent in dhcpcd-curses.
authorRoy Marples <roy@marples.name>
Mon, 11 May 2015 21:09:31 +0000 (21:09 +0000)
committerRoy Marples <roy@marples.name>
Mon, 11 May 2015 21:09:31 +0000 (21:09 +0000)
configure
src/dhcpcd-curses/Makefile
src/dhcpcd-curses/common.h [deleted file]
src/dhcpcd-curses/dhcpcd-curses.c
src/dhcpcd-curses/dhcpcd-curses.h
src/dhcpcd-curses/eloop.c [deleted file]
src/dhcpcd-curses/eloop.h [deleted file]
src/dhcpcd-curses/event-object.c [new file with mode: 0644]
src/dhcpcd-curses/event-object.h [new file with mode: 0644]

index a97afc5170b797528ce671d7e9c7e9413b6e8025..c1cd3fc481904c4ccf8796761cc6979c2ea7453b 100755 (executable)
--- a/configure
+++ b/configure
@@ -439,8 +439,30 @@ if [ "$WITH_ICONS" = yes ]; then
        echo "MKICONS=  icons" >>$CONFIG_MK
 fi
 
-LIB_CURSES=
+if [ "$WITH_EVENT" = yes -o -z "$WITH_EVENT" ]; then
+       printf "Looking for libevent ... "
+       cat <<EOF >_event.c
+#include <event.h>
+int main(void) {
+       event_base_new();
+       return 0;
+}
+EOF
+       LIB_EVENT=
+       if $XCC _event.c -levent -o _event.c 2>&3; then
+               LIB_EVENT=-levent
+       fi
+       rm -f _event.c _event
+fi
+if [ -n "$LIB_EVENT" ]; then
+       echo "$LIB_EVENT"
+       echo "LIB_EVENT=        $LIB_EVENT" >>$CONFIG_MK
+else
+       echo "not found"
+fi
+
 if [ "$WITH_CURSES" = yes -o -z "$WITH_CURSES" ]; then
+       LIB_CURSES=
        printf "Looking for libcurses ... "
        cat <<EOF >_curses.c
 #include <curses.h>
@@ -454,7 +476,7 @@ EOF
        fi
        rm -f _curses.c _curses
 fi
-if [ -n "$LIB_CURSES" ]; then
+if [ -n "$LIB_CURSES" -a -n "$LIB_EVENT" ]; then
        echo "$LIB_CURSES"
        echo "LIB_CURSES=       $LIB_CURSES" >>$CONFIG_MK
        UI="dhcpcd-curses${UI:+ }$UI"
index 8e117e3c0ce6180912f715baa82c8da243164918..fffff6e86ddcd58ef761ee1176fbca5bdc8e1c4a 100644 (file)
@@ -1,5 +1,5 @@
 PROG=          dhcpcd-curses
-SRCS=          dhcpcd-curses.c eloop.c
+SRCS=          dhcpcd-curses.c event-object.c
 
 TOPDIR=                ../..
 include ${TOPDIR}/iconfig.mk
@@ -7,7 +7,7 @@ include ${TOPDIR}/iconfig.mk
 MAN8=          dhcpcd-curses.8
 
 CPPFLAGS+=     -I${TOPDIR} ${CURSES_CPPFLAGS}
-LDADD+=                ${LIB_DHCPCD} ${LIB_CURSES} ${LIB_INTL}
+LDADD+=                ${LIB_DHCPCD} ${LIB_CURSES} ${LIB_INTL} ${LIB_EVENT}
 
 .PHONY: dhcpcd-curses
 
diff --git a/src/dhcpcd-curses/common.h b/src/dhcpcd-curses/common.h
deleted file mode 100644 (file)
index ea46b6d..0000000
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
- * dhcpcd - DHCP client daemon
- * Copyright (c) 2006-2015 Roy Marples <roy@marples.name>
- * All rights reserved
-
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#ifndef COMMON_H
-#define COMMON_H
-
-#include <sys/time.h>
-
-#include "config.h"
-
-#define USEC_PER_SEC           1000000L
-#define USEC_PER_NSEC          1000L
-#define NSEC_PER_SEC           1000000000L
-#define MSEC_PER_SEC           1000L
-#define MSEC_PER_NSEC          1000000L
-
-#ifndef TIMEVAL_TO_TIMESPEC
-#define        TIMEVAL_TO_TIMESPEC(tv, ts) do {                                \
-       (ts)->tv_sec = (tv)->tv_sec;                                    \
-       (ts)->tv_nsec = (tv)->tv_usec * USEC_PER_NSEC;                  \
-} while (0 /* CONSTCOND */)
-#endif
-
-/* Some systems don't define timespec macros */
-#ifndef timespecclear
-#define timespecclear(tsp)      (tsp)->tv_sec = (time_t)((tsp)->tv_nsec = 0L)
-#define timespecisset(tsp)      ((tsp)->tv_sec || (tsp)->tv_nsec)
-#define timespeccmp(tsp, usp, cmp)                                      \
-        (((tsp)->tv_sec == (usp)->tv_sec) ?                             \
-            ((tsp)->tv_nsec cmp (usp)->tv_nsec) :                       \
-            ((tsp)->tv_sec cmp (usp)->tv_sec))
-#define timespecadd(tsp, usp, vsp)                                      \
-        do {                                                            \
-                (vsp)->tv_sec = (tsp)->tv_sec + (usp)->tv_sec;          \
-                (vsp)->tv_nsec = (tsp)->tv_nsec + (usp)->tv_nsec;       \
-                if ((vsp)->tv_nsec >= 1000000000L) {                    \
-                        (vsp)->tv_sec++;                                \
-                        (vsp)->tv_nsec -= 1000000000L;                  \
-                }                                                       \
-        } while (/* CONSTCOND */ 0)
-#define timespecsub(tsp, usp, vsp)                                      \
-        do {                                                            \
-                (vsp)->tv_sec = (tsp)->tv_sec - (usp)->tv_sec;          \
-                (vsp)->tv_nsec = (tsp)->tv_nsec - (usp)->tv_nsec;       \
-                if ((vsp)->tv_nsec < 0) {                               \
-                        (vsp)->tv_sec--;                                \
-                        (vsp)->tv_nsec += 1000000000L;                  \
-                }                                                       \
-        } while (/* CONSTCOND */ 0)
-#endif
-
-#define timespecnorm(tv) do {                                               \
-       while ((tv)->tv_nsec >=  NSEC_PER_SEC) {                             \
-               (tv)->tv_sec++;                                              \
-               (tv)->tv_nsec -= NSEC_PER_SEC;                               \
-       }                                                                    \
-} while (0 /* CONSTCOND */);
-
-#if __GNUC__ > 2 || defined(__INTEL_COMPILER)
-# ifndef __dead
-#  define __dead __attribute__((__noreturn__))
-# endif
-# ifndef __packed
-#  define __packed   __attribute__((__packed__))
-# endif
-# ifndef __unused
-#  define __unused   __attribute__((__unused__))
-# endif
-#else
-# ifndef __dead
-#  define __dead
-# endif
-# ifndef __packed
-#  define __packed
-# endif
-# ifndef __unused
-#  define __unused
-# endif
-#endif
-
-#endif
index 3584b9b57b49ba9c91188e53e73281bf37bccb86..737dc2749d7f6eb907cc597ad4d553ce01d5d209 100644 (file)
@@ -27,6 +27,7 @@
 
 #include <sys/ioctl.h>
 
+#include <assert.h>
 #include <curses.h>
 #include <err.h>
 #include <errno.h>
 #include <unistd.h>
 
 #include "dhcpcd-curses.h"
+#include "event-object.h"
 
 #ifdef HAVE_NC_FREE_AND_EXIT
        void _nc_free_and_exit(void);
 #endif
 
-const int handle_sigs[] = {
-       SIGHUP,
-       SIGINT,
-       SIGPIPE,
-       SIGTERM,
-       SIGWINCH,
-       0
-};
-
-/* Handling signals needs *some* context */
-static struct ctx *_ctx;
-
-static void try_open(void *);
+static void try_open_cb(evutil_socket_t, short, void *);
 
 static void
 set_status(struct ctx *ctx, const char *status)
@@ -138,23 +128,14 @@ notify(struct ctx *ctx, const char *fmt, ...)
 static void
 update_online(struct ctx *ctx, bool show_if)
 {
-       bool online, carrier;
        char *msg, *msgs, *nmsg;
        size_t msgs_len, mlen;
        DHCPCD_IF *ifs, *i;
 
-       online = carrier = false;
        msgs = NULL;
        msgs_len = 0;
        ifs = dhcpcd_interfaces(ctx->con);
        for (i = ifs; i; i = i->next) {
-               if (i->type == DHT_LINK) {
-                       if (i->up)
-                               carrier = true;
-               } else {
-                       if (i->up)
-                               online = true;
-               }
                msg = dhcpcd_if_message(i, NULL);
                if (msg) {
                        if (show_if) {
@@ -191,15 +172,21 @@ update_online(struct ctx *ctx, bool show_if)
 }
 
 static void
-dispatch(void *arg)
+dispatch_cb(evutil_socket_t fd, __unused short what, void *arg)
 {
        struct ctx *ctx = arg;
 
-       if (dhcpcd_get_fd(ctx->con) == -1) {
-               warning(ctx, _("dhcpcd connection lost"));
-               eloop_event_delete(ctx->eloop, -1, NULL, ctx->con, 0);
-               eloop_timeout_add_msec(ctx->eloop, DHCPCD_RETRYOPEN,
-                   try_open, ctx);
+       if (fd == -1 || dhcpcd_get_fd(ctx->con) == -1) {
+               struct timeval tv = { 0, DHCPCD_RETRYOPEN * MSECS_PER_NSEC };
+               struct event *ev;
+
+               if (fd != -1)
+                       warning(ctx, _("dhcpcd connection lost"));
+               event_object_find_delete(ctx->evobjects, ctx);
+               ev = evtimer_new(ctx->evbase, try_open_cb, ctx);
+               if (ev == NULL ||
+                   event_object_add(ctx->evobjects, ev, &tv, ctx) == NULL)
+                       warning(ctx, "dispatch: event: %s", strerror(errno));
                return;
        }
 
@@ -207,13 +194,18 @@ dispatch(void *arg)
 }
 
 static void
-try_open(void *arg)
+try_open_cb(__unused evutil_socket_t fd, __unused short what, void *arg)
 {
        struct ctx *ctx = arg;
        static int last_error;
+       EVENT_OBJECT *eo;
+       struct event *ev;
 
+       eo = event_object_find(ctx->evobjects, ctx);
        ctx->fd = dhcpcd_open(ctx->con, true);
        if (ctx->fd == -1) {
+               struct timeval tv = { 0, DHCPCD_RETRYOPEN * MSECS_PER_NSEC };
+
                if (errno == EACCES || errno == EPERM) {
                        ctx->fd = dhcpcd_open(ctx->con, false);
                        if (ctx->fd != -1)
@@ -223,16 +215,22 @@ try_open(void *arg)
                        last_error = errno;
                        set_status(ctx, strerror(errno));
                }
-               eloop_timeout_add_msec(ctx->eloop, DHCPCD_RETRYOPEN,
-                   try_open, ctx);
+               event_del(eo->event);
+               event_add(eo->event, &tv);
                return;
        }
 
 unprived:
+       event_object_delete(ctx->evobjects, eo);
+
        /* Start listening to WPA events */
        dhcpcd_wpa_start(ctx->con);
 
-       eloop_event_add(ctx->eloop, ctx->fd, dispatch, ctx, NULL, NULL);
+       ev = event_new(ctx->evbase, ctx->fd, EV_READ | EV_PERSIST,
+           dispatch_cb, ctx);
+       if (ev == NULL ||
+           event_object_add(ctx->evobjects, ev, NULL, ctx) == NULL)
+               warning(ctx, "event_new: %s", strerror(errno));
 }
 
 static void
@@ -245,13 +243,10 @@ status_cb(DHCPCD_CONNECTION *con,
        set_status(ctx, status_msg);
 
        if (status == DHC_DOWN) {
-               eloop_event_delete(ctx->eloop, ctx->fd, NULL, NULL, 0);
                ctx->fd = -1;
                ctx->online = ctx->carrier = false;
-               eloop_timeout_delete(ctx->eloop, NULL, ctx);
                set_summary(ctx, NULL);
-               eloop_timeout_add_msec(ctx->eloop, DHCPCD_RETRYOPEN,
-                   try_open, ctx);
+               dispatch_cb(-1, 0, ctx);
        } else {
                bool refresh;
 
@@ -299,7 +294,7 @@ if_cb(DHCPCD_IF *i, void *arg)
 }
 
 static void
-wpa_dispatch(void *arg)
+wpa_dispatch_cb(__unused evutil_socket_t fd, __unused short what, void *arg)
 {
        DHCPCD_WPA *wpa = arg;
 
@@ -311,6 +306,7 @@ static void
 wpa_scan_cb(DHCPCD_WPA *wpa, void *arg)
 {
        struct ctx *ctx = arg;
+       EVENT_OBJECT *eo;
        DHCPCD_IF *i;
        WI_SCAN *wi;
        DHCPCD_WI_SCAN *scans, *s1, *s2;
@@ -321,8 +317,15 @@ wpa_scan_cb(DHCPCD_WPA *wpa, void *arg)
                debug(ctx, "%s (%p)", _("no fd for WPA"), wpa);
                return;
        }
-       eloop_event_add(ctx->eloop,
-           dhcpcd_wpa_get_fd(wpa), wpa_dispatch, wpa, NULL, NULL);
+       if ((eo = event_object_find(ctx->evobjects, wpa)) == NULL) {
+               struct event *ev;
+
+               ev = event_new(ctx->evbase, fd, EV_READ | EV_PERSIST,
+                   wpa_dispatch_cb, wpa);
+               if (ev == NULL ||
+                   event_object_add(ctx->evobjects, ev, NULL, wpa) == NULL)
+                       warning(ctx, "event_new: %s", strerror(errno));
+       }
 
        i = dhcpcd_wpa_if(wpa);
        if (i == NULL) {
@@ -408,7 +411,7 @@ wpa_status_cb(DHCPCD_WPA *wpa,
        i = dhcpcd_wpa_if(wpa);
        debug(ctx, _("%s: WPA status %s"), i->ifname, status_msg);
        if (status == DHC_DOWN) {
-               eloop_event_delete(ctx->eloop, -1, NULL, wpa, 0);
+               event_object_find_delete(ctx->evobjects, wpa);
                TAILQ_FOREACH_SAFE(w, &ctx->wi_scans, next, wn) {
                        if (w->interface == i) {
                                TAILQ_REMOVE(&ctx->wi_scans, w, next);
@@ -420,7 +423,7 @@ wpa_status_cb(DHCPCD_WPA *wpa,
 }
 
 static void
-bg_scan(void *arg)
+bg_scan_cb(__unused evutil_socket_t fd, __unused short what, void *arg)
 {
        struct ctx *ctx = arg;
        WI_SCAN *w;
@@ -435,51 +438,50 @@ bg_scan(void *arg)
                                dhcpcd_wpa_scan(wpa);
                }
        }
+}
 
-       eloop_timeout_add_msec(ctx->eloop, DHCPCD_WPA_SCAN_SHORT,
-           bg_scan, ctx);
+static void
+sigint_cb(__unused evutil_socket_t fd, __unused short what, void *arg)
+{
+       struct ctx *ctx = arg;
+
+       debug(ctx, _("caught SIGINT, exiting"));
+       event_base_loopbreak(ctx->evbase);
 }
 
 static void
-signal_handler(int sig)
+sigterm_cb(__unused evutil_socket_t fd, __unused short what, void *arg)
+{
+       struct ctx *ctx = arg;
+
+       debug(ctx, _("caught SIGTERM, exiting"));
+       event_base_loopbreak(ctx->evbase);
+}
+
+static void
+sigwinch_cb(__unused evutil_socket_t fd, __unused short what,
+    __unused void *arg)
 {
        struct winsize ws;
 
-       switch(sig) {
-       case SIGWINCH:
-               if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &ws) == 0)
-                       resizeterm(ws.ws_row, ws.ws_col);
-               break;
-       case SIGINT:
-               debug(_ctx, _("SIGINT caught, exiting"));
-               eloop_exit(_ctx->eloop, EXIT_FAILURE);
-               break;
-       case SIGTERM:
-               debug(_ctx, _("SIGTERM caught, exiting"));
-               eloop_exit(_ctx->eloop, EXIT_FAILURE);
-               break;
-       case SIGHUP:
-               debug(_ctx, _("SIGHUP caught, ignoring"));
-               break;
-       case SIGPIPE:
-               debug(_ctx, _("SIGPIPE caught, ignoring"));
-               break;
-       }
+       if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &ws) == 0)
+               resizeterm(ws.ws_row, ws.ws_col);
 }
 
 static int
-setup_signals()
+setup_signals(struct ctx *ctx)
 {
-       struct sigaction sa;
-       int i;
-
-       memset(&sa, 0, sizeof(sa));
-       sa.sa_handler = signal_handler;
+       struct event *ev;
 
-       for (i = 0; handle_sigs[i]; i++) {
-               if (sigaction(handle_sigs[i], &sa, NULL) == -1)
-                       return -1;
-       }
+       ev = evsignal_new(ctx->evbase, SIGINT, sigint_cb, ctx);
+       if (ev == NULL || event_add(ev, NULL) == -1)
+               return -1;
+       ev = evsignal_new(ctx->evbase, SIGTERM, sigterm_cb, ctx);
+       if (ev == NULL || event_add(ev, NULL) == -1)
+               return -1;
+       ev = evsignal_new(ctx->evbase, SIGWINCH, sigwinch_cb, ctx);
+       if (ev == NULL || event_add(ev, NULL) == -1)
+               return -1;
        return 0;
 }
 
@@ -522,21 +524,25 @@ main(void)
 {
        struct ctx ctx;
        WI_SCAN *wi;
+       struct timeval tv0 = { 0, 0 };
+       struct timeval tv_short = { 0, DHCPCD_WPA_SCAN_SHORT };
+       struct event *ev;
 
        memset(&ctx, 0, sizeof(ctx));
        ctx.fd = -1;
+       if ((ctx.evobjects = event_object_new()) == NULL)
+               err(EXIT_FAILURE, "event_object_new");
        TAILQ_INIT(&ctx.wi_scans);
-       _ctx = &ctx;
 
-       if (setup_signals() == -1)
+       if ((ctx.evbase = event_base_new()) == NULL)
+               err(EXIT_FAILURE, "event_base_new");
+
+       if (setup_signals(&ctx) == -1)
                err(EXIT_FAILURE, "setup_signals");
 
        if ((ctx.con = dhcpcd_new()) == NULL)
                err(EXIT_FAILURE, "dhcpcd_new");
 
-       if ((ctx.eloop = eloop_init()) == NULL)
-               err(EXIT_FAILURE, "malloc");
-
        if ((ctx.stdscr = initscr()) == NULL)
                err(EXIT_FAILURE, "initscr");
 
@@ -554,10 +560,15 @@ main(void)
        dhcpcd_wpa_set_scan_callback(ctx.con, wpa_scan_cb, &ctx);
        dhcpcd_wpa_set_status_callback(ctx.con, wpa_status_cb, &ctx);
 
-       eloop_timeout_add_sec(ctx.eloop, 0, try_open, &ctx);
-       eloop_timeout_add_msec(ctx.eloop, DHCPCD_WPA_SCAN_SHORT,
-           bg_scan, &ctx);
-       eloop_start(ctx.eloop);
+       if ((ev = event_new(ctx.evbase, 0, 0, try_open_cb, &ctx)) == NULL)
+               err(EXIT_FAILURE, "event_new");
+       if (event_object_add(ctx.evobjects, ev, &tv0, &ctx) == NULL)
+               err(EXIT_FAILURE, "event_object_add");
+       if ((ev = event_new(ctx.evbase, EV_PERSIST, 0, bg_scan_cb, &ctx)) == NULL)
+               err(EXIT_FAILURE, "event_new");
+       if (event_add(ev, &tv_short) == -1)
+               err(EXIT_FAILURE, "event_add");
+       event_base_dispatch(ctx.evbase);
 
        /* Un-resgister the callbacks to avoid spam on close */
        dhcpcd_set_status_callback(ctx.con, NULL, NULL);
@@ -575,7 +586,8 @@ main(void)
        }
 
        /* Free everything else */
-       eloop_free(ctx.eloop);
+       event_base_free(ctx.evbase);
+       event_object_free(ctx.evobjects);
        endwin();
 
 #ifdef HAVE_NC_FREE_AND_EXIT
index c94d09c76699fbcd1db17d872987d192d6fb0416..1915da4dc72428e04268b364e22850507ba84c7c 100644 (file)
@@ -28,6 +28,8 @@
 #ifndef DHCPCD_CURSES_H
 #define DHCPCD_CURSES_H
 
+#include <event.h>
+
 #ifdef HAS_GETTEXT
 #include <libintl.h>
 #define _ gettext
@@ -39,8 +41,8 @@
 
 #include "config.h"
 #include "dhcpcd.h"
-#include "eloop.h"
 #include "queue.h"
+#include "event-object.h"
 
 #ifndef __printflike
 #ifdef __GNUC__
@@ -50,6 +52,8 @@
 #endif
 #endif
 
+#define MSECS_PER_NSEC 1000
+
 typedef struct wi_scan {
        TAILQ_ENTRY(wi_scan) next;
        DHCPCD_IF *interface;
@@ -58,7 +62,8 @@ typedef struct wi_scan {
 typedef TAILQ_HEAD(wi_scan_head, wi_scan) WI_SCANS;
 
 struct ctx {
-       ELOOP_CTX *eloop;
+       struct event_base *evbase;
+       EVENT_OBJECTS *evobjects;
        DHCPCD_CONNECTION *con;
        int fd;
        bool online;
diff --git a/src/dhcpcd-curses/eloop.c b/src/dhcpcd-curses/eloop.c
deleted file mode 100644 (file)
index f70f04e..0000000
+++ /dev/null
@@ -1,459 +0,0 @@
-/*
- * dhcpcd - DHCP client daemon
- * Copyright (c) 2006-2015 Roy Marples <roy@marples.name>
- * All rights reserved
-
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include <sys/time.h>
-
-#include <errno.h>
-#include <limits.h>
-#include <poll.h>
-#include <signal.h>
-#include <stdlib.h>
-#include <syslog.h>
-
-#include <stdio.h>
-
-#define IN_ELOOP
-
-#include "config.h"
-#include "common.h"
-#include "eloop.h"
-
-/* Handy function to get the time.
- * We only care about time advancements, not the actual time itself
- * Which is why we use CLOCK_MONOTONIC, but it is not available on all
- * platforms.
- */
-#define NO_MONOTONIC "host does not support a monotonic clock - timing can skew"
-static int
-get_monotonic(struct timespec *ts)
-{
-
-#if defined(_POSIX_MONOTONIC_CLOCK) && defined(CLOCK_MONOTONIC)
-       return clock_gettime(CLOCK_MONOTONIC, ts);
-               return 0;
-#elif defined(__APPLE__)
-       /* We can use mach kernel functions here.
-        * This is crap though - why can't they implement clock_gettime?*/
-       static struct mach_timebase_info info = { 0, 0 };
-       static double factor = 0.0;
-       uint64_t nano;
-       long rem;
-
-       if (!posix_clock_set) {
-               if (mach_timebase_info(&info) == KERN_SUCCESS) {
-                       factor = (double)info.numer / (double)info.denom;
-                       clock_monotonic = posix_clock_set = 1;
-               }
-       }
-       if (clock_monotonic) {
-               nano = mach_absolute_time();
-               if ((info.denom != 1 || info.numer != 1) && factor != 0.0)
-                       nano *= factor;
-               ts->tv_sec = nano / NSEC_PER_SEC;
-               ts->tv_nsec = nano % NSEC_PER_SEC;
-               if (ts->tv_nsec < 0) {
-                       ts->tv_sec--;
-                       ts->tv_nsec += NSEC_PER_SEC;
-               }
-               return 0;
-       }
-#endif
-
-#if 0
-       /* Something above failed, so fall back to gettimeofday */
-       if (!posix_clock_set) {
-               syslog(LOG_WARNING, NO_MONOTONIC);
-               posix_clock_set = 1;
-       }
-#endif
-       {
-               struct timeval tv;
-               if (gettimeofday(&tv, NULL) == 0) {
-                       TIMEVAL_TO_TIMESPEC(&tv, ts);
-                       return 0;
-               }
-       }
-
-       return -1;
-}
-
-static void
-eloop_event_setup_fds(ELOOP_CTX *ctx)
-{
-       struct eloop_event *e;
-       size_t i;
-
-       i = 0;
-       TAILQ_FOREACH(e, &ctx->events, next) {
-               ctx->fds[i].fd = e->fd;
-               ctx->fds[i].events = 0;
-               if (e->read_cb)
-                       ctx->fds[i].events |= POLLIN;
-               if (e->write_cb)
-                       ctx->fds[i].events |= POLLOUT;
-               ctx->fds[i].revents = 0;
-               e->pollfd = &ctx->fds[i];
-               i++;
-       }
-}
-
-int
-eloop_event_add(ELOOP_CTX *ctx, int fd,
-    void (*read_cb)(void *), void *read_cb_arg,
-    void (*write_cb)(void *), void *write_cb_arg)
-{
-       struct eloop_event *e;
-       struct pollfd *nfds;
-
-       /* We should only have one callback monitoring the fd */
-       TAILQ_FOREACH(e, &ctx->events, next) {
-               if (e->fd == fd) {
-                       if (read_cb) {
-                               e->read_cb = read_cb;
-                               e->read_cb_arg = read_cb_arg;
-                       }
-                       if (write_cb) {
-                               e->write_cb = write_cb;
-                               e->write_cb_arg = write_cb_arg;
-                       }
-                       eloop_event_setup_fds(ctx);
-                       return 0;
-               }
-       }
-
-       /* Allocate a new event if no free ones already allocated */
-       if ((e = TAILQ_FIRST(&ctx->free_events))) {
-               TAILQ_REMOVE(&ctx->free_events, e, next);
-       } else {
-               e = malloc(sizeof(*e));
-               if (e == NULL) {
-                       syslog(LOG_ERR, "%s: %m", __func__);
-                       return -1;
-               }
-       }
-
-       /* Ensure we can actually listen to it */
-       ctx->events_len++;
-       if (ctx->events_len > ctx->fds_len) {
-               ctx->fds_len += 5;
-               nfds = malloc(sizeof(*ctx->fds) * (ctx->fds_len + 5));
-               if (nfds == NULL) {
-                       syslog(LOG_ERR, "%s: %m", __func__);
-                       ctx->events_len--;
-                       TAILQ_INSERT_TAIL(&ctx->free_events, e, next);
-                       return -1;
-               }
-               ctx->fds_len += 5;
-               free(ctx->fds);
-               ctx->fds = nfds;
-       }
-
-       /* Now populate the structure and add it to the list */
-       e->fd = fd;
-       e->read_cb = read_cb;
-       e->read_cb_arg = read_cb_arg;
-       e->write_cb = write_cb;
-       e->write_cb_arg = write_cb_arg;
-       /* The order of events should not matter.
-        * However, some PPP servers love to close the link right after
-        * sending their final message. So to ensure dhcpcd processes this
-        * message (which is likely to be that the DHCP addresses are wrong)
-        * we insert new events at the queue head as the link fd will be
-        * the first event added. */
-       TAILQ_INSERT_HEAD(&ctx->events, e, next);
-       eloop_event_setup_fds(ctx);
-       return 0;
-}
-
-void
-eloop_event_delete(ELOOP_CTX *ctx, int fd, void (*callback)(void *), void *arg,
-    int write_only)
-{
-       struct eloop_event *e;
-
-       TAILQ_FOREACH(e, &ctx->events, next) {
-               if (e->fd == fd ||
-                   e->read_cb == callback || (arg && e->read_cb_arg == arg))
-               {
-                       if (write_only) {
-                               e->write_cb = NULL;
-                               e->write_cb_arg = NULL;
-                       } else {
-                               TAILQ_REMOVE(&ctx->events, e, next);
-                               TAILQ_INSERT_TAIL(&ctx->free_events, e, next);
-                               ctx->events_len--;
-                       }
-                       eloop_event_setup_fds(ctx);
-                       break;
-               }
-       }
-}
-
-int
-eloop_q_timeout_add_tv(ELOOP_CTX *ctx, int queue,
-    const struct timespec *when, void (*callback)(void *), void *arg)
-{
-       struct timespec now;
-       struct timespec w;
-       struct eloop_timeout *t, *tt = NULL;
-
-       get_monotonic(&now);
-       timespecadd(&now, when, &w);
-       /* Check for time_t overflow. */
-       if (timespeccmp(&w, &now, <)) {
-               errno = ERANGE;
-               return -1;
-       }
-
-       /* Remove existing timeout if present */
-       TAILQ_FOREACH(t, &ctx->timeouts, next) {
-               if (t->callback == callback && t->arg == arg) {
-                       TAILQ_REMOVE(&ctx->timeouts, t, next);
-                       break;
-               }
-       }
-
-       if (t == NULL) {
-               /* No existing, so allocate or grab one from the free pool */
-               if ((t = TAILQ_FIRST(&ctx->free_timeouts))) {
-                       TAILQ_REMOVE(&ctx->free_timeouts, t, next);
-               } else {
-                       t = malloc(sizeof(*t));
-                       if (t == NULL) {
-                               syslog(LOG_ERR, "%s: %m", __func__);
-                               return -1;
-                       }
-               }
-       }
-
-       t->when = *when;
-       t->callback = callback;
-       t->arg = arg;
-       t->queue = queue;
-
-       /* The timeout list should be in chronological order,
-        * soonest first. */
-       TAILQ_FOREACH(tt, &ctx->timeouts, next) {
-               if (timespeccmp(&t->when, &tt->when, <)) {
-                       TAILQ_INSERT_BEFORE(tt, t, next);
-                       return 0;
-               }
-       }
-       TAILQ_INSERT_TAIL(&ctx->timeouts, t, next);
-       return 0;
-}
-
-int
-eloop_q_timeout_add_sec(ELOOP_CTX *ctx, int queue, time_t when,
-    void (*callback)(void *), void *arg)
-{
-       struct timespec tv;
-
-       tv.tv_sec = when;
-       tv.tv_nsec = 0;
-       return eloop_q_timeout_add_tv(ctx, queue, &tv, callback, arg);
-}
-
-int
-eloop_q_timeout_add_msec(ELOOP_CTX *ctx, int queue, suseconds_t when,
-    void (*callback)(void *), void *arg)
-{
-       struct timespec tv;
-
-       tv.tv_sec = 0;
-       tv.tv_nsec = when * MSEC_PER_NSEC;
-       timespecnorm(&tv);
-       return eloop_q_timeout_add_tv(ctx, queue, &tv, callback, arg);
-}
-
-int
-eloop_timeout_add_now(ELOOP_CTX *ctx,
-    void (*callback)(void *), void *arg)
-{
-
-       if (ctx->timeout0 != NULL) {
-               syslog(LOG_WARNING, "%s: timeout0 already set", __func__);
-               return eloop_q_timeout_add_sec(ctx, 0, 0, callback, arg);
-       }
-
-       ctx->timeout0 = callback;
-       ctx->timeout0_arg = arg;
-       return 0;
-}
-
-void
-eloop_q_timeout_delete(ELOOP_CTX *ctx, int queue,
-    void (*callback)(void *), void *arg)
-{
-       struct eloop_timeout *t, *tt;
-
-       TAILQ_FOREACH_SAFE(t, &ctx->timeouts, next, tt) {
-               if ((queue == 0 || t->queue == queue) &&
-                   t->arg == arg &&
-                   (!callback || t->callback == callback))
-               {
-                       TAILQ_REMOVE(&ctx->timeouts, t, next);
-                       TAILQ_INSERT_TAIL(&ctx->free_timeouts, t, next);
-               }
-       }
-}
-
-void
-eloop_exit(ELOOP_CTX *ctx, int code)
-{
-
-       ctx->exitcode = code;
-       ctx->exitnow = 1;
-}
-
-ELOOP_CTX *
-eloop_init(void)
-{
-       ELOOP_CTX *ctx;
-
-       ctx = calloc(1, sizeof(*ctx));
-       if (ctx) {
-               TAILQ_INIT(&ctx->events);
-               TAILQ_INIT(&ctx->free_events);
-               TAILQ_INIT(&ctx->timeouts);
-               TAILQ_INIT(&ctx->free_timeouts);
-               ctx->exitcode = EXIT_FAILURE;
-       }
-       return ctx;
-}
-
-
-void eloop_free(ELOOP_CTX *ctx)
-{
-       struct eloop_event *e;
-       struct eloop_timeout *t;
-
-       if (ctx == NULL)
-               return;
-
-       while ((e = TAILQ_FIRST(&ctx->events))) {
-               TAILQ_REMOVE(&ctx->events, e, next);
-               free(e);
-       }
-       while ((e = TAILQ_FIRST(&ctx->free_events))) {
-               TAILQ_REMOVE(&ctx->free_events, e, next);
-               free(e);
-       }
-       while ((t = TAILQ_FIRST(&ctx->timeouts))) {
-               TAILQ_REMOVE(&ctx->timeouts, t, next);
-               free(t);
-       }
-       while ((t = TAILQ_FIRST(&ctx->free_timeouts))) {
-               TAILQ_REMOVE(&ctx->free_timeouts, t, next);
-               free(t);
-       }
-       free(ctx->fds);
-       free(ctx);
-}
-
-int
-eloop_start(ELOOP_CTX *ctx)
-{
-       int n;
-       struct eloop_event *e;
-       struct eloop_timeout *t;
-       struct timespec now, ts, tv, *tsp;
-       void (*t0)(void *);
-       int timeout;
-
-       for (;;) {
-               if (ctx->exitnow)
-                       break;
-
-               /* Run all timeouts first */
-               if (ctx->timeout0) {
-                       t0 = ctx->timeout0;
-                       ctx->timeout0 = NULL;
-                       t0(ctx->timeout0_arg);
-                       continue;
-               }
-               if ((t = TAILQ_FIRST(&ctx->timeouts))) {
-                       get_monotonic(&now);
-                       if (timespeccmp(&now, &t->when, >)) {
-                               TAILQ_REMOVE(&ctx->timeouts, t, next);
-                               t->callback(t->arg);
-                               TAILQ_INSERT_TAIL(&ctx->free_timeouts, t, next);
-                               continue;
-                       }
-                       timespecsub(&t->when, &now, &tv);
-                       tsp = &ts;
-               } else
-                       /* No timeouts, so wait forever */
-                       tsp = NULL;
-
-               if (tsp == NULL && ctx->events_len == 0) {
-                       syslog(LOG_ERR, "nothing to do");
-                       break;
-               }
-
-               if (tsp == NULL)
-                       timeout = -1;
-               else if (tsp->tv_sec > INT_MAX / 1000 ||
-                   (tsp->tv_sec == INT_MAX / 1000 &&
-                   (tsp->tv_nsec + 999999) / 1000000 > INT_MAX % 1000000))
-                       timeout = INT_MAX;
-               else
-                       timeout = (int)(tsp->tv_sec * 1000 +
-                           (tsp->tv_nsec + 999999) / 1000000);
-               n = poll(ctx->fds, ctx->events_len, timeout);
-               if (n == -1) {
-                       if (errno == EINTR)
-                               continue;
-                       syslog(LOG_ERR, "poll: %m");
-                       break;
-               }
-
-               /* Process any triggered events. */
-               if (n > 0) {
-                       TAILQ_FOREACH(e, &ctx->events, next) {
-                               if (e->pollfd->revents & POLLOUT &&
-                                       e->write_cb)
-                               {
-                                       e->write_cb(e->write_cb_arg);
-                                       /* We need to break here as the
-                                        * callback could destroy the next
-                                        * fd to process. */
-                                       break;
-                               }
-                               if (e->pollfd->revents) {
-                                       e->read_cb(e->read_cb_arg);
-                                       /* We need to break here as the
-                                        * callback could destroy the next
-                                        * fd to process. */
-                                       break;
-                               }
-                       }
-               }
-       }
-
-       return ctx->exitcode;
-}
diff --git a/src/dhcpcd-curses/eloop.h b/src/dhcpcd-curses/eloop.h
deleted file mode 100644 (file)
index dc1dd5c..0000000
+++ /dev/null
@@ -1,109 +0,0 @@
-/*
- * dhcpcd - DHCP client daemon
- * Copyright (c) 2006-2015 Roy Marples <roy@marples.name>
- * All rights reserved
-
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#ifndef ELOOP_H
-#define ELOOP_H
-
-#include <time.h>
-
-#ifndef ELOOP_QUEUE
-  #define ELOOP_QUEUE 1
-#endif
-
-/* EXIT_FAILURE is a non zero value and EXIT_SUCCESS is zero.
- * To add a CONTINUE definition, simply do the opposite of EXIT_FAILURE. */
-#define ELOOP_CONTINUE -EXIT_FAILURE
-
-#ifdef IN_ELOOP
-#include "queue.h"
-
-struct eloop_event {
-       TAILQ_ENTRY(eloop_event) next;
-       int fd;
-       void (*read_cb)(void *);
-       void *read_cb_arg;
-       void (*write_cb)(void *);
-       void *write_cb_arg;
-       struct pollfd *pollfd;
-};
-
-struct eloop_timeout {
-       TAILQ_ENTRY(eloop_timeout) next;
-       struct timespec when;
-       void (*callback)(void *);
-       void *arg;
-       int queue;
-};
-
-typedef struct eloop_ctx {
-       nfds_t events_len;
-       TAILQ_HEAD (event_head, eloop_event) events;
-       struct event_head free_events;
-
-       TAILQ_HEAD (timeout_head, eloop_timeout) timeouts;
-       struct timeout_head free_timeouts;
-
-       void (*timeout0)(void *);
-       void *timeout0_arg;
-
-       struct pollfd *fds;
-       nfds_t fds_len;
-
-       int exitnow;
-       int exitcode;
-} ELOOP_CTX;
-#else
-typedef void *ELOOP_CTX;
-#endif
-
-#define eloop_timeout_add_tv(a, b, c, d) \
-    eloop_q_timeout_add_tv(a, ELOOP_QUEUE, b, c, d)
-#define eloop_timeout_add_sec(a, b, c, d) \
-    eloop_q_timeout_add_sec(a, ELOOP_QUEUE, b, c, d)
-#define eloop_timeout_add_msec(a, b, c, d) \
-    eloop_q_timeout_add_msec(a, ELOOP_QUEUE, b, c, d)
-#define eloop_timeout_delete(a, b, c) \
-    eloop_q_timeout_delete(a, ELOOP_QUEUE, b, c)
-
-int eloop_event_add(ELOOP_CTX *, int,
-    void (*)(void *), void *,
-    void (*)(void *), void *);
-void eloop_event_delete(ELOOP_CTX *, int, void (*)(void *), void *, int);
-int eloop_q_timeout_add_sec(ELOOP_CTX *, int queue,
-    time_t, void (*)(void *), void *);
-int eloop_q_timeout_add_msec(ELOOP_CTX *, int queue,
-    suseconds_t, void (*)(void *), void *);
-int eloop_q_timeout_add_tv(ELOOP_CTX *, int queue,
-    const struct timespec *, void (*)(void *), void *);
-int eloop_timeout_add_now(ELOOP_CTX *, void (*)(void *), void *);
-void eloop_q_timeout_delete(ELOOP_CTX *, int, void (*)(void *), void *);
-ELOOP_CTX * eloop_init(void);
-void eloop_free(ELOOP_CTX *);
-void eloop_exit(ELOOP_CTX *, int);
-int eloop_start(ELOOP_CTX *);
-
-#endif
diff --git a/src/dhcpcd-curses/event-object.c b/src/dhcpcd-curses/event-object.c
new file mode 100644 (file)
index 0000000..f8b73ba
--- /dev/null
@@ -0,0 +1,112 @@
+/*
+ * dhcpcd - DHCP client daemon
+ * Copyright (c) 2006-2015 Roy Marples <roy@marples.name>
+ * All rights reserved
+
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <assert.h>
+#include <errno.h>
+#include <stdlib.h>
+
+#include "event-object.h"
+
+/* Track event objects by parameter */
+EVENT_OBJECT *
+event_object_find(EVENT_OBJECTS *events, void *object)
+{
+       EVENT_OBJECT *eo;
+
+       assert(events);
+       assert(object);
+       TAILQ_FOREACH(eo, events, next) {
+               if (eo->object == object)
+                       return eo;
+       }
+       errno = ESRCH;
+       return NULL;
+}
+
+EVENT_OBJECT *
+event_object_add(EVENT_OBJECTS *events, struct event *event,
+    struct timeval *tv, void *object)
+{
+       EVENT_OBJECT *eo;
+
+       assert(events);
+       assert(event);
+       assert(object);
+       eo = malloc(sizeof(*eo));
+       if (eo == NULL || event_add(event, tv) == -1)
+               return NULL;
+       eo->event = event;
+       eo->object = object;
+       TAILQ_INSERT_TAIL(events, eo, next);
+       return eo;
+}
+
+void
+event_object_delete(EVENT_OBJECTS *events, EVENT_OBJECT *eo)
+{
+
+       assert(events);
+       assert(eo);
+       TAILQ_REMOVE(events, eo, next);
+       event_del(eo->event);
+       event_free(eo->event);
+       free(eo);
+}
+
+void
+event_object_find_delete(EVENT_OBJECTS *events, void *object)
+{
+       EVENT_OBJECT *eo;
+
+       if ((eo = event_object_find(events, object)) != NULL)
+               event_object_delete(events, eo);
+}
+
+EVENT_OBJECTS *
+event_object_new(void)
+{
+       EVENT_OBJECTS *events;
+
+       if ((events = malloc(sizeof(*events))) == NULL)
+               return NULL;
+
+       TAILQ_INIT(events);
+       return events;
+}
+
+void
+event_object_free(EVENT_OBJECTS *events)
+{
+       EVENT_OBJECT *eo;
+
+       if (events) {
+               while ((eo = TAILQ_FIRST(events)) != NULL) {
+                       event_object_delete(events, eo);
+               }
+               free(events);
+       }
+}
diff --git a/src/dhcpcd-curses/event-object.h b/src/dhcpcd-curses/event-object.h
new file mode 100644 (file)
index 0000000..720c929
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * dhcpcd - DHCP client daemon
+ * Copyright (c) 2006-2015 Roy Marples <roy@marples.name>
+ * All rights reserved
+
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef EVENT_OBJECT_H
+#define EVENT_OBJECT_H
+
+#include <event.h>
+#include "queue.h"
+
+typedef struct event_object {
+       TAILQ_ENTRY(event_object) next;
+       struct event *event;
+       void *object;
+} EVENT_OBJECT;
+typedef TAILQ_HEAD(event_object_head, event_object) EVENT_OBJECTS;
+
+EVENT_OBJECT *event_object_find(EVENT_OBJECTS *, void *);
+EVENT_OBJECT *event_object_add(EVENT_OBJECTS *, struct event *,
+    struct timeval *, void *);
+void event_object_delete(EVENT_OBJECTS *, EVENT_OBJECT *);
+void event_object_find_delete(EVENT_OBJECTS *, void *);
+EVENT_OBJECTS *event_object_new(void);
+void event_object_free(EVENT_OBJECTS *);
+
+#endif