+ WL head;
+ sig_atomic_t volatile gotsig;
+} ANSIG;
+
+static ANSIG *signals;
+static int signalmax;
+
+static int sigpipe [2];
+static sig_atomic_t volatile gotsig;
+static struct ev_io sigev;
+
+static void
+signals_init (ANSIG *base, int count)
+{
+ while (count--)
+ {
+ base->head = 0;
+ base->gotsig = 0;
+
+ ++base;
+ }
+}
+
+static void
+sighandler (int signum)
+{
+#if WIN32
+ signal (signum, sighandler);
+#endif
+
+ signals [signum - 1].gotsig = 1;
+
+ if (!gotsig)
+ {
+ int old_errno = errno;
+ gotsig = 1;
+#ifdef WIN32
+ send (sigpipe [1], &signum, 1, MSG_DONTWAIT);
+#else
+ write (sigpipe [1], &signum, 1);
+#endif
+ errno = old_errno;
+ }
+}
+
+void
+ev_feed_signal_event (EV_P_ int signum)
+{
+ WL w;
+
+#if EV_MULTIPLICITY
+ assert (("feeding signal events is only supported in the default loop", loop == default_loop));
+#endif
+
+ --signum;
+
+ if (signum < 0 || signum >= signalmax)
+ return;
+
+ signals [signum].gotsig = 0;
+
+ for (w = signals [signum].head; w; w = w->next)
+ ev_feed_event (EV_A_ (W)w, EV_SIGNAL);
+}
+
+static void
+sigcb (EV_P_ struct ev_io *iow, int revents)
+{
+ int signum;
+
+#ifdef WIN32
+ recv (sigpipe [0], &revents, 1, MSG_DONTWAIT);
+#else
+ read (sigpipe [0], &revents, 1);
+#endif
+ gotsig = 0;
+
+ for (signum = signalmax; signum--; )
+ if (signals [signum].gotsig)
+ ev_feed_signal_event (EV_A_ signum + 1);
+}
+
+static void
+siginit (EV_P)
+{
+#ifndef WIN32
+ fcntl (sigpipe [0], F_SETFD, FD_CLOEXEC);
+ fcntl (sigpipe [1], F_SETFD, FD_CLOEXEC);
+
+ /* rather than sort out wether we really need nb, set it */
+ fcntl (sigpipe [0], F_SETFL, O_NONBLOCK);
+ fcntl (sigpipe [1], F_SETFL, O_NONBLOCK);
+#endif
+
+ ev_io_set (&sigev, sigpipe [0], EV_READ);
+ ev_io_start (EV_A_ &sigev);
+ ev_unref (EV_A); /* child watcher should not keep loop alive */
+}
+
+/*****************************************************************************/
+
+static struct ev_child *childs [PID_HASHSIZE];
+
+#ifndef WIN32
+
+static struct ev_signal childev;
+
+#ifndef WCONTINUED
+# define WCONTINUED 0
+#endif
+
+static void
+child_reap (EV_P_ struct ev_signal *sw, int chain, int pid, int status)
+{
+ struct ev_child *w;
+
+ for (w = (struct ev_child *)childs [chain & (PID_HASHSIZE - 1)]; w; w = (struct ev_child *)((WL)w)->next)
+ if (w->pid == pid || !w->pid)
+ {
+ ev_priority (w) = ev_priority (sw); /* need to do it *now* */
+ w->rpid = pid;
+ w->rstatus = status;
+ ev_feed_event (EV_A_ (W)w, EV_CHILD);
+ }
+}
+
+static void
+childcb (EV_P_ struct ev_signal *sw, int revents)
+{
+ int pid, status;
+
+ if (0 < (pid = waitpid (-1, &status, WNOHANG | WUNTRACED | WCONTINUED)))
+ {
+ /* make sure we are called again until all childs have been reaped */
+ ev_feed_event (EV_A_ (W)sw, EV_SIGNAL);
+
+ child_reap (EV_A_ sw, pid, pid, status);
+ child_reap (EV_A_ sw, 0, pid, status); /* this might trigger a watcher twice, but event catches that */
+ }
+}
+
+#endif
+
+/*****************************************************************************/
+
+#if EV_USE_KQUEUE
+# include "ev_kqueue.c"
+#endif
+#if EV_USE_EPOLL
+# include "ev_epoll.c"
+#endif
+#if EV_USE_POLL
+# include "ev_poll.c"
+#endif
+#if EV_USE_SELECT
+# include "ev_select.c"
+#endif
+
+int
+ev_version_major (void)
+{
+ return EV_VERSION_MAJOR;
+}
+
+int
+ev_version_minor (void)
+{
+ return EV_VERSION_MINOR;
+}
+
+/* return true if we are running with elevated privileges and should ignore env variables */
+static int
+enable_secure (void)
+{
+#ifdef WIN32
+ return 0;
+#else
+ return getuid () != geteuid ()
+ || getgid () != getegid ();
+#endif
+}