Import new eloop from dhcpcd.
[dhcpcd-ui] / src / dhcpcd-curses / eloop.c
1 /*
2  * dhcpcd - DHCP client daemon
3  * Copyright (c) 2006-2016 Roy Marples <roy@marples.name>
4  * All rights reserved
5
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25  * SUCH DAMAGE.
26  */
27
28 #if (defined(__unix__) || defined(unix)) && !defined(USG)
29 #include <sys/param.h>
30 #endif
31 #include <sys/time.h>
32
33 #include <assert.h>
34 #include <errno.h>
35 #include <limits.h>
36 #include <signal.h>
37 #include <stdlib.h>
38 #include <string.h>
39 #include <unistd.h>
40
41 /* config.h should define HAVE_KQUEUE, HAVE_EPOLL, etc */
42 #ifdef HAVE_CONFIG_H
43 #include "config.h"
44 #endif
45
46 /* Attempt to autodetect kqueue or epoll.
47  * Failing that, fall back to pselect. */
48 #if !defined(HAVE_KQUEUE) && !defined(HAVE_EPOLL) && !defined(HAVE_PSELECT) && \
49     !defined(HAVE_POLLTS) && !defined(HAVE_PPOLL)
50 #if defined(BSD)
51 /* Assume BSD has a working sys/queue.h and kqueue(2) interface */
52 #define HAVE_SYS_QUEUE_H
53 #define HAVE_KQUEUE
54 #elif defined(__linux__)
55 /* Assume Linux has a working epoll(3) interface */
56 #define HAVE_EPOLL
57 #else
58 /* pselect(2) is a POSIX standard. */
59 #define HAVE_PSELECT
60 #endif
61 #endif
62
63 /* pollts and ppoll require poll.
64  * pselect is wrapped in a pollts/ppoll style interface
65  * and as such require poll as well. */
66 #if defined(HAVE_PSELECT) || defined(HAVE_POLLTS) || defined(HAVE_PPOLL)
67 #ifndef HAVE_POLL
68 #define HAVE_POLL
69 #endif
70 #if defined(HAVE_POLLTS)
71 #define POLLTS pollts
72 #elif defined(HAVE_PPOLL)
73 #define POLLTS ppoll
74 #else
75 #define POLLTS eloop_pollts
76 #define ELOOP_NEED_POLLTS
77 #endif
78 #endif
79
80 #include "eloop.h"
81
82 /* Our structures require TAILQ macros, which really every libc should
83  * ship as they are useful beyond belief.
84  * Sadly some libc's don't have sys/queue.h and some that do don't have
85  * the TAILQ_FOREACH macro. For those that don't, the application using
86  * this implementation will need to ship a working queue.h somewhere.
87  * If we don't have sys/queue.h found in config.h, then
88  * allow QUEUE_H to override loading queue.h in the current directory. */
89 #ifndef TAILQ_FOREACH
90 #ifdef HAVE_SYS_QUEUE_H
91 #include <sys/queue.h>
92 #elif defined(QUEUE_H)
93 #define __QUEUE_HEADER(x) #x
94 #define _QUEUE_HEADER(x) __QUEUE_HEADER(x)
95 #include _QUEUE_HEADER(QUEUE_H)
96 #else
97 #include "queue.h"
98 #endif
99 #endif
100
101 #ifndef UNUSED
102 #define UNUSED(a) (void)((a))
103 #endif
104 #ifndef __unused
105 #ifdef __GNUC__
106 #define __unused   __attribute__((__unused__))
107 #else
108 #define __unused
109 #endif
110 #endif
111
112 #ifndef MSEC_PER_SEC
113 #define MSEC_PER_SEC    1000L
114 #define NSEC_PER_MSEC   1000000L
115 #endif
116
117 #if defined(HAVE_KQUEUE)
118 #include <sys/event.h>
119 #include <fcntl.h>
120 #ifdef __NetBSD__
121 /* udata is void * except on NetBSD
122  * lengths are int except on NetBSD */
123 #define UPTR(x) ((intptr_t)(x))
124 #define LENC(x) (x)
125 #else
126 #define UPTR(x) (x)
127 #define LENC(x) ((int)(x))
128 #endif
129 #elif defined(HAVE_EPOLL)
130 #include <sys/epoll.h>
131 #elif defined(HAVE_POLL)
132 #if defined(HAVE_PSELECT)
133 #include <sys/select.h>
134 #endif
135 #include <poll.h>
136 #endif
137
138 struct eloop_event {
139         TAILQ_ENTRY(eloop_event) next;
140         int fd;
141         void (*read_cb)(void *);
142         void *read_cb_arg;
143         void (*write_cb)(void *);
144         void *write_cb_arg;
145 #ifdef HAVE_POLL
146         struct pollfd *pollfd;
147 #endif
148 };
149
150 struct eloop_timeout {
151         TAILQ_ENTRY(eloop_timeout) next;
152         struct timespec when;
153         void (*callback)(void *);
154         void *arg;
155         int queue;
156 };
157
158 struct eloop {
159         size_t events_len;
160         TAILQ_HEAD (event_head, eloop_event) events;
161         struct event_head free_events;
162
163         TAILQ_HEAD (timeout_head, eloop_timeout) timeouts;
164         struct timeout_head free_timeouts;
165
166         void (*timeout0)(void *);
167         void *timeout0_arg;
168         const int *signals;
169         size_t signals_len;
170         void (*signal_cb)(int, void *);
171         void *signal_cb_ctx;
172
173 #if defined(HAVE_KQUEUE) || defined(HAVE_EPOLL)
174         int poll_fd;
175 #elif defined(HAVE_POLL)
176         struct pollfd *fds;
177         size_t fds_len;
178 #endif
179
180         int exitnow;
181         int exitcode;
182 };
183
184 #ifdef HAVE_POLL
185 static void
186 eloop_event_setup_fds(struct eloop *eloop)
187 {
188         struct eloop_event *e;
189         size_t i;
190
191         i = 0;
192         TAILQ_FOREACH(e, &eloop->events, next) {
193                 eloop->fds[i].fd = e->fd;
194                 eloop->fds[i].events = 0;
195                 if (e->read_cb)
196                         eloop->fds[i].events |= POLLIN;
197                 if (e->write_cb)
198                         eloop->fds[i].events |= POLLOUT;
199                 eloop->fds[i].revents = 0;
200                 e->pollfd = &eloop->fds[i];
201                 i++;
202         }
203 }
204
205 #ifdef ELOOP_NEED_POLLTS
206 /* Wrapper around pselect, to imitate the NetBSD pollts call. */
207 static int
208 eloop_pollts(struct pollfd * fds, nfds_t nfds,
209     const struct timespec *ts, const sigset_t *sigmask)
210 {
211         fd_set read_fds;
212         nfds_t n;
213         int maxfd, r;
214
215         FD_ZERO(&read_fds);
216         maxfd = 0;
217         for (n = 0; n < nfds; n++) {
218                 if (fds[n].events & POLLIN) {
219                         FD_SET(fds[n].fd, &read_fds);
220                         if (fds[n].fd > maxfd)
221                                 maxfd = fds[n].fd;
222                 }
223         }
224
225         r = pselect(maxfd + 1, &read_fds, NULL, NULL, ts, sigmask);
226         if (r > 0) {
227                 for (n = 0; n < nfds; n++) {
228                         fds[n].revents =
229                             FD_ISSET(fds[n].fd, &read_fds) ? POLLIN : 0;
230                 }
231         }
232
233         return r;
234 }
235 #endif /* pollts */
236 #else /* !HAVE_POLL */
237 #define eloop_event_setup_fds(a) {}
238 #endif /* HAVE_POLL */
239
240 int
241 eloop_event_add(struct eloop *eloop, int fd,
242     void (*read_cb)(void *), void *read_cb_arg,
243     void (*write_cb)(void *), void *write_cb_arg)
244 {
245         struct eloop_event *e;
246 #if defined(HAVE_KQUEUE)
247         struct kevent ke[2];
248 #elif defined(HAVE_EPOLL)
249         struct epoll_event epe;
250 #elif defined(HAVE_POLL)
251         struct pollfd *nfds;
252 #endif
253
254         assert(eloop != NULL);
255         assert(read_cb != NULL || write_cb != NULL);
256         if (fd == -1) {
257                 errno = EINVAL;
258                 return -1;
259         }
260
261 #ifdef HAVE_EPOLL
262         memset(&epe, 0, sizeof(epe));
263         epe.data.fd = fd;
264         epe.events = EPOLLIN;
265         if (write_cb)
266                 epe.events |= EPOLLOUT;
267 #endif
268
269         /* We should only have one callback monitoring the fd */
270         TAILQ_FOREACH(e, &eloop->events, next) {
271                 if (e->fd == fd) {
272                         int error;
273
274 #if defined(HAVE_KQUEUE)
275                         EV_SET(&ke[0], (uintptr_t)fd, EVFILT_READ, EV_ADD,
276                             0, 0, UPTR(e));
277                         if (write_cb)
278                                 EV_SET(&ke[1], (uintptr_t)fd, EVFILT_WRITE,
279                                     EV_ADD, 0, 0, UPTR(e));
280                         else if (e->write_cb)
281                                 EV_SET(&ke[1], (uintptr_t)fd, EVFILT_WRITE,
282                                     EV_DELETE, 0, 0, UPTR(e));
283                         error = kevent(eloop->poll_fd, ke,
284                             e->write_cb || write_cb ? 2 : 1, NULL, 0, NULL);
285 #elif defined(HAVE_EPOLL)
286                         epe.data.ptr = e;
287                         error = epoll_ctl(eloop->poll_fd, EPOLL_CTL_MOD,
288                             fd, &epe);
289 #else
290                         error = 0;
291 #endif
292                         if (read_cb) {
293                                 e->read_cb = read_cb;
294                                 e->read_cb_arg = read_cb_arg;
295                         }
296                         if (write_cb) {
297                                 e->write_cb = write_cb;
298                                 e->write_cb_arg = write_cb_arg;
299                         }
300                         eloop_event_setup_fds(eloop);
301                         return error;
302                 }
303         }
304
305         /* Allocate a new event if no free ones already allocated */
306         if ((e = TAILQ_FIRST(&eloop->free_events))) {
307                 TAILQ_REMOVE(&eloop->free_events, e, next);
308         } else {
309                 e = malloc(sizeof(*e));
310                 if (e == NULL)
311                         goto err;
312         }
313
314         /* Ensure we can actually listen to it */
315         eloop->events_len++;
316 #ifdef HAVE_POLL
317         if (eloop->events_len > eloop->fds_len) {
318                 nfds = realloc(eloop->fds,
319                     sizeof(*eloop->fds) * (eloop->fds_len + 5));
320                 if (nfds == NULL)
321                         goto err;
322                 eloop->fds_len += 5;
323                 eloop->fds = nfds;
324         }
325 #endif
326
327         /* Now populate the structure and add it to the list */
328         e->fd = fd;
329         e->read_cb = read_cb;
330         e->read_cb_arg = read_cb_arg;
331         e->write_cb = write_cb;
332         e->write_cb_arg = write_cb_arg;
333
334 #if defined(HAVE_KQUEUE)
335         if (read_cb != NULL)
336                 EV_SET(&ke[0], (uintptr_t)fd, EVFILT_READ,
337                     EV_ADD, 0, 0, UPTR(e));
338         if (write_cb != NULL)
339                 EV_SET(&ke[1], (uintptr_t)fd, EVFILT_WRITE,
340                     EV_ADD, 0, 0, UPTR(e));
341         if (kevent(eloop->poll_fd, ke, write_cb ? 2 : 1, NULL, 0, NULL) == -1)
342                 goto err;
343 #elif defined(HAVE_EPOLL)
344         epe.data.ptr = e;
345         if (epoll_ctl(eloop->poll_fd, EPOLL_CTL_ADD, fd, &epe) == -1)
346                 goto err;
347 #endif
348
349         /* The order of events should not matter.
350          * However, some PPP servers love to close the link right after
351          * sending their final message. So to ensure dhcpcd processes this
352          * message (which is likely to be that the DHCP addresses are wrong)
353          * we insert new events at the queue head as the link fd will be
354          * the first event added. */
355         TAILQ_INSERT_HEAD(&eloop->events, e, next);
356         eloop_event_setup_fds(eloop);
357         return 0;
358
359 err:
360         if (e) {
361                 eloop->events_len--;
362                 TAILQ_INSERT_TAIL(&eloop->free_events, e, next);
363         }
364         return -1;
365 }
366
367 void
368 eloop_event_delete_write(struct eloop *eloop, int fd, int write_only)
369 {
370         struct eloop_event *e;
371 #if defined(HAVE_KQUEUE)
372         struct kevent ke[2];
373 #elif defined(HAVE_EPOLL)
374         struct epoll_event epe;
375 #endif
376
377         assert(eloop != NULL);
378
379         TAILQ_FOREACH(e, &eloop->events, next) {
380                 if (e->fd == fd) {
381                         if (write_only && e->read_cb != NULL) {
382                                 if (e->write_cb != NULL) {
383                                         e->write_cb = NULL;
384                                         e->write_cb_arg = NULL;
385 #if defined(HAVE_KQUEUE)
386                                         EV_SET(&ke[0], (uintptr_t)fd,
387                                             EVFILT_WRITE, EV_DELETE,
388                                             0, 0, UPTR(NULL));
389                                         kevent(eloop->poll_fd, ke, 1, NULL, 0,
390                                             NULL);
391 #elif defined(HAVE_EPOLL)
392                                         memset(&epe, 0, sizeof(epe));
393                                         epe.data.fd = e->fd;
394                                         epe.data.ptr = e;
395                                         epe.events = EPOLLIN;
396                                         epoll_ctl(eloop->poll_fd,
397                                             EPOLL_CTL_MOD, fd, &epe);
398 #endif
399                                 }
400                         } else {
401                                 TAILQ_REMOVE(&eloop->events, e, next);
402 #if defined(HAVE_KQUEUE)
403                                 EV_SET(&ke[0], (uintptr_t)fd, EVFILT_READ,
404                                     EV_DELETE, 0, 0, UPTR(NULL));
405                                 if (e->write_cb)
406                                         EV_SET(&ke[1], (uintptr_t)fd,
407                                             EVFILT_WRITE, EV_DELETE,
408                                             0, 0, UPTR(NULL));
409                                 kevent(eloop->poll_fd, ke, e->write_cb ? 2 : 1,
410                                     NULL, 0, NULL);
411 #elif defined(HAVE_EPOLL)
412                                 /* NULL event is safe because we
413                                  * rely on epoll_pwait which as added
414                                  * after the delete without event was fixed. */
415                                 epoll_ctl(eloop->poll_fd, EPOLL_CTL_DEL,
416                                     fd, NULL);
417 #endif
418                                 TAILQ_INSERT_TAIL(&eloop->free_events, e, next);
419                                 eloop->events_len--;
420                         }
421                         eloop_event_setup_fds(eloop);
422                         break;
423                 }
424         }
425 }
426
427 int
428 eloop_q_timeout_add_tv(struct eloop *eloop, int queue,
429     const struct timespec *when, void (*callback)(void *), void *arg)
430 {
431         struct timespec now, w;
432         struct eloop_timeout *t, *tt = NULL;
433
434         assert(eloop != NULL);
435         assert(when != NULL);
436         assert(callback != NULL);
437
438         clock_gettime(CLOCK_MONOTONIC, &now);
439         timespecadd(&now, when, &w);
440         /* Check for time_t overflow. */
441         if (timespeccmp(&w, &now, <)) {
442                 errno = ERANGE;
443                 return -1;
444         }
445
446         /* Remove existing timeout if present */
447         TAILQ_FOREACH(t, &eloop->timeouts, next) {
448                 if (t->callback == callback && t->arg == arg) {
449                         TAILQ_REMOVE(&eloop->timeouts, t, next);
450                         break;
451                 }
452         }
453
454         if (t == NULL) {
455                 /* No existing, so allocate or grab one from the free pool */
456                 if ((t = TAILQ_FIRST(&eloop->free_timeouts))) {
457                         TAILQ_REMOVE(&eloop->free_timeouts, t, next);
458                 } else {
459                         if ((t = malloc(sizeof(*t))) == NULL)
460                                 return -1;
461                 }
462         }
463
464         t->when = w;
465         t->callback = callback;
466         t->arg = arg;
467         t->queue = queue;
468
469         /* The timeout list should be in chronological order,
470          * soonest first. */
471         TAILQ_FOREACH(tt, &eloop->timeouts, next) {
472                 if (timespeccmp(&t->when, &tt->when, <)) {
473                         TAILQ_INSERT_BEFORE(tt, t, next);
474                         return 0;
475                 }
476         }
477         TAILQ_INSERT_TAIL(&eloop->timeouts, t, next);
478         return 0;
479 }
480
481 int
482 eloop_q_timeout_add_sec(struct eloop *eloop, int queue, time_t when,
483     void (*callback)(void *), void *arg)
484 {
485         struct timespec tv;
486
487         tv.tv_sec = when;
488         tv.tv_nsec = 0;
489         return eloop_q_timeout_add_tv(eloop, queue, &tv, callback, arg);
490 }
491
492 int
493 eloop_q_timeout_add_msec(struct eloop *eloop, int queue, long when,
494     void (*callback)(void *), void *arg)
495 {
496         struct timespec tv;
497
498         tv.tv_sec = when / MSEC_PER_SEC;
499         tv.tv_nsec = (when % MSEC_PER_SEC) * NSEC_PER_MSEC;
500         return eloop_q_timeout_add_tv(eloop, queue, &tv, callback, arg);
501 }
502
503 #if !defined(HAVE_KQUEUE)
504 static int
505 eloop_timeout_add_now(struct eloop *eloop,
506     void (*callback)(void *), void *arg)
507 {
508
509         assert(eloop->timeout0 == NULL);
510         eloop->timeout0 = callback;
511         eloop->timeout0_arg = arg;
512         return 0;
513 }
514 #endif
515
516 void
517 eloop_q_timeout_delete(struct eloop *eloop, int queue,
518     void (*callback)(void *), void *arg)
519 {
520         struct eloop_timeout *t, *tt;
521
522         assert(eloop != NULL);
523
524         TAILQ_FOREACH_SAFE(t, &eloop->timeouts, next, tt) {
525                 if ((queue == 0 || t->queue == queue) &&
526                     t->arg == arg &&
527                     (!callback || t->callback == callback))
528                 {
529                         TAILQ_REMOVE(&eloop->timeouts, t, next);
530                         TAILQ_INSERT_TAIL(&eloop->free_timeouts, t, next);
531                 }
532         }
533 }
534
535 void
536 eloop_exit(struct eloop *eloop, int code)
537 {
538
539         assert(eloop != NULL);
540
541         eloop->exitcode = code;
542         eloop->exitnow = 1;
543 }
544
545 #if defined(HAVE_KQUEUE) || defined(HAVE_EPOLL)
546 static int
547 eloop_open(struct eloop *eloop)
548 {
549
550 #if defined(HAVE_KQUEUE1)
551         return (eloop->poll_fd = kqueue1(O_CLOEXEC));
552 #elif defined(HAVE_KQUEUE)
553         int i;
554
555         if ((eloop->poll_fd = kqueue()) == -1)
556                 return -1;
557         if ((i = fcntl(eloop->poll_fd, F_GETFD, 0)) == -1 ||
558             fcntl(eloop->poll_fd, F_SETFD, i | FD_CLOEXEC) == -1)
559         {
560                 close(eloop->poll_fd);
561                 eloop->poll_fd = -1;
562                 return -1;
563         }
564
565         return eloop->poll_fd;
566 #elif defined (HAVE_EPOLL)
567         return (eloop->poll_fd = epoll_create1(EPOLL_CLOEXEC));
568 #endif
569 }
570 #endif
571
572 int
573 eloop_requeue(struct eloop *eloop)
574 {
575 #if defined(HAVE_POLL)
576
577         UNUSED(eloop);
578         return 0;
579 #else /* !HAVE_POLL */
580         struct eloop_event *e;
581         int error;
582 #if defined(HAVE_KQUEUE)
583         size_t i;
584         struct kevent *ke;
585 #elif defined(HAVE_EPOLL)
586         struct epoll_event epe;
587 #endif
588
589         assert(eloop != NULL);
590
591         if (eloop->poll_fd != -1)
592                 close(eloop->poll_fd);
593         if (eloop_open(eloop) == -1)
594                 return -1;
595 #if defined (HAVE_KQUEUE)
596         i = eloop->signals_len;
597         TAILQ_FOREACH(e, &eloop->events, next) {
598                 i++;
599                 if (e->write_cb)
600                         i++;
601         }
602
603         if ((ke = malloc(sizeof(*ke) * i)) == NULL)
604                 return -1;
605
606         for (i = 0; i < eloop->signals_len; i++)
607                 EV_SET(&ke[i], (uintptr_t)eloop->signals[i],
608                     EVFILT_SIGNAL, EV_ADD, 0, 0, UPTR(NULL));
609
610         TAILQ_FOREACH(e, &eloop->events, next) {
611                 EV_SET(&ke[i], (uintptr_t)e->fd, EVFILT_READ,
612                     EV_ADD, 0, 0, UPTR(e));
613                 i++;
614                 if (e->write_cb) {
615                         EV_SET(&ke[i], (uintptr_t)e->fd, EVFILT_WRITE,
616                             EV_ADD, 0, 0, UPTR(e));
617                         i++;
618                 }
619         }
620
621         error =  kevent(eloop->poll_fd, ke, LENC(i), NULL, 0, NULL);
622         free(ke);
623
624 #elif defined(HAVE_EPOLL)
625
626         error = 0;
627         TAILQ_FOREACH(e, &eloop->events, next) {
628                 memset(&epe, 0, sizeof(epe));
629                 epe.data.fd = e->fd;
630                 epe.events = EPOLLIN;
631                 if (e->write_cb)
632                         epe.events |= EPOLLOUT;
633                 epe.data.ptr = e;
634                 if (epoll_ctl(eloop->poll_fd, EPOLL_CTL_ADD, e->fd, &epe) == -1)
635                         error = -1;
636         }
637 #endif
638
639         return error;
640 #endif /* HAVE_POLL */
641 }
642
643 int
644 eloop_signal_set_cb(struct eloop *eloop,
645     const int *signals, size_t signals_len,
646     void (*signal_cb)(int, void *), void *signal_cb_ctx)
647 {
648
649         assert(eloop != NULL);
650
651         eloop->signals = signals;
652         eloop->signals_len = signals_len;
653         eloop->signal_cb = signal_cb;
654         eloop->signal_cb_ctx = signal_cb_ctx;
655         return eloop_requeue(eloop);
656 }
657
658 #ifndef HAVE_KQUEUE
659 struct eloop_siginfo {
660         int sig;
661         struct eloop *eloop;
662 };
663 static struct eloop_siginfo _eloop_siginfo;
664 static struct eloop *_eloop;
665
666 static void
667 eloop_signal1(void *arg)
668 {
669         struct eloop_siginfo *si = arg;
670
671         si->eloop->signal_cb(si->sig, si->eloop->signal_cb_ctx);
672 }
673
674 static void
675 eloop_signal3(int sig, __unused siginfo_t *siginfo, __unused void *arg)
676 {
677
678         /* So that we can operate safely under a signal we instruct
679          * eloop to pass a copy of the siginfo structure to handle_signal1
680          * as the very first thing to do. */
681         _eloop_siginfo.eloop = _eloop;
682         _eloop_siginfo.sig = sig;
683         eloop_timeout_add_now(_eloop_siginfo.eloop,
684             eloop_signal1, &_eloop_siginfo);
685 }
686 #endif
687
688 int
689 eloop_signal_mask(struct eloop *eloop, sigset_t *oldset)
690 {
691         sigset_t newset;
692 #ifndef HAVE_KQUEUE
693         size_t i;
694         struct sigaction sa;
695 #endif
696
697         assert(eloop != NULL);
698
699         sigfillset(&newset);
700         if (sigprocmask(SIG_SETMASK, &newset, oldset) == -1)
701                 return -1;
702
703 #ifdef HAVE_KQUEUE
704         UNUSED(eloop);
705 #else
706         memset(&sa, 0, sizeof(sa));
707         sa.sa_sigaction = eloop_signal3;
708         sa.sa_flags = SA_SIGINFO;
709         sigemptyset(&sa.sa_mask);
710
711         for (i = 0; i < eloop->signals_len; i++) {
712                 if (sigaction(eloop->signals[i], &sa, NULL) == -1)
713                         return -1;
714         }
715 #endif
716         return 0;
717 }
718
719 struct eloop *
720 eloop_new(void)
721 {
722         struct eloop *eloop;
723         struct timespec now;
724
725         /* Check we have a working monotonic clock. */
726         if (clock_gettime(CLOCK_MONOTONIC, &now) == -1)
727                 return NULL;
728
729         eloop = calloc(1, sizeof(*eloop));
730         if (eloop) {
731                 TAILQ_INIT(&eloop->events);
732                 TAILQ_INIT(&eloop->free_events);
733                 TAILQ_INIT(&eloop->timeouts);
734                 TAILQ_INIT(&eloop->free_timeouts);
735                 eloop->exitcode = EXIT_FAILURE;
736 #if defined(HAVE_KQUEUE) || defined(HAVE_EPOLL)
737                 eloop->poll_fd = -1;
738                 eloop_open(eloop);
739 #endif
740         }
741
742         return eloop;
743 }
744
745 void eloop_free(struct eloop *eloop)
746 {
747         struct eloop_event *e;
748         struct eloop_timeout *t;
749
750         if (eloop == NULL)
751                 return;
752
753         while ((e = TAILQ_FIRST(&eloop->events))) {
754                 TAILQ_REMOVE(&eloop->events, e, next);
755                 free(e);
756         }
757         while ((e = TAILQ_FIRST(&eloop->free_events))) {
758                 TAILQ_REMOVE(&eloop->free_events, e, next);
759                 free(e);
760         }
761         while ((t = TAILQ_FIRST(&eloop->timeouts))) {
762                 TAILQ_REMOVE(&eloop->timeouts, t, next);
763                 free(t);
764         }
765         while ((t = TAILQ_FIRST(&eloop->free_timeouts))) {
766                 TAILQ_REMOVE(&eloop->free_timeouts, t, next);
767                 free(t);
768         }
769 #if defined(HAVE_KQUEUE) || defined(HAVE_EPOLL)
770         close(eloop->poll_fd);
771 #elif defined(HAVE_POLL)
772         free(eloop->fds);
773 #endif
774         free(eloop);
775 }
776
777 int
778 eloop_start(struct eloop *eloop, sigset_t *signals)
779 {
780         int n;
781         struct eloop_event *e;
782         struct eloop_timeout *t;
783         struct timespec now, ts, *tsp;
784         void (*t0)(void *);
785 #if defined(HAVE_KQUEUE)
786         struct kevent ke;
787         UNUSED(signals);
788 #elif defined(HAVE_EPOLL)
789         struct epoll_event epe;
790 #endif
791 #ifndef HAVE_KQUEUE
792         int timeout;
793
794         _eloop = eloop;
795 #endif
796
797         assert(eloop != NULL);
798
799         for (;;) {
800                 if (eloop->exitnow)
801                         break;
802
803                 /* Run all timeouts first */
804                 if (eloop->timeout0) {
805                         t0 = eloop->timeout0;
806                         eloop->timeout0 = NULL;
807                         t0(eloop->timeout0_arg);
808                         continue;
809                 }
810                 if ((t = TAILQ_FIRST(&eloop->timeouts))) {
811                         clock_gettime(CLOCK_MONOTONIC, &now);
812                         if (timespeccmp(&now, &t->when, >)) {
813                                 TAILQ_REMOVE(&eloop->timeouts, t, next);
814                                 t->callback(t->arg);
815                                 TAILQ_INSERT_TAIL(&eloop->free_timeouts, t, next);
816                                 continue;
817                         }
818                         timespecsub(&t->when, &now, &ts);
819                         tsp = &ts;
820                 } else
821                         /* No timeouts, so wait forever */
822                         tsp = NULL;
823
824                 if (tsp == NULL && eloop->events_len == 0)
825                         break;
826
827 #ifndef HAVE_KQUEUE
828                 if (tsp == NULL)
829                         timeout = -1;
830                 else if (tsp->tv_sec > INT_MAX / 1000 ||
831                     (tsp->tv_sec == INT_MAX / 1000 &&
832                     (tsp->tv_nsec + 999999) / 1000000 > INT_MAX % 1000000))
833                         timeout = INT_MAX;
834                 else
835                         timeout = (int)(tsp->tv_sec * 1000 +
836                             (tsp->tv_nsec + 999999) / 1000000);
837 #endif
838
839 #if defined(HAVE_KQUEUE)
840                 n = kevent(eloop->poll_fd, NULL, 0, &ke, 1, tsp);
841 #elif defined(HAVE_EPOLL)
842                 if (signals)
843                         n = epoll_pwait(eloop->poll_fd, &epe, 1,
844                             timeout, signals);
845                 else
846                         n = epoll_wait(eloop->poll_fd, &epe, 1, timeout);
847 #elif defined(HAVE_POLL)
848                 if (signals)
849                         n = POLLTS(eloop->fds, (nfds_t)eloop->events_len,
850                             tsp, signals);
851                 else
852                         n = poll(eloop->fds, (nfds_t)eloop->events_len,
853                             timeout);
854 #endif
855                 if (n == -1) {
856                         if (errno == EINTR)
857                                 continue;
858                         return -errno;
859                 }
860
861                 /* Process any triggered events.
862                  * We go back to the start after calling each callback incase
863                  * the current event or next event is removed. */
864 #if defined(HAVE_KQUEUE)
865                 if (n) {
866                         if (ke.filter == EVFILT_SIGNAL) {
867                                 eloop->signal_cb((int)ke.ident,
868                                     eloop->signal_cb_ctx);
869                                 continue;
870                         }
871                         e = (struct eloop_event *)ke.udata;
872                         if (ke.filter == EVFILT_WRITE) {
873                                 e->write_cb(e->write_cb_arg);
874                                 continue;
875                         } else if (ke.filter == EVFILT_READ) {
876                                 e->read_cb(e->read_cb_arg);
877                                 continue;
878                         }
879                 }
880 #elif defined(HAVE_EPOLL)
881                 if (n) {
882                         e = (struct eloop_event *)epe.data.ptr;
883                         if (epe.events & EPOLLOUT && e->write_cb != NULL) {
884                                 e->write_cb(e->write_cb_arg);
885                                 continue;
886                         }
887                         if (epe.events &
888                             (EPOLLIN | EPOLLERR | EPOLLHUP) &&
889                             e->read_cb != NULL)
890                         {
891                                 e->read_cb(e->read_cb_arg);
892                                 continue;
893                         }
894                 }
895 #elif defined(HAVE_POLL)
896                 if (n > 0) {
897                         TAILQ_FOREACH(e, &eloop->events, next) {
898                                 if (e->pollfd->revents & POLLOUT &&
899                                     e->write_cb != NULL)
900                                 {
901                                         e->write_cb(e->write_cb_arg);
902                                         break;
903                                 }
904                                 if (e->pollfd->revents && e->read_cb != NULL) {
905                                         e->read_cb(e->read_cb_arg);
906                                         break;
907                                 }
908                         }
909                 }
910 #endif
911         }
912
913         return eloop->exitcode;
914 }