+#ifdef HAVE_LIBADNS
+
+/* --- @before_select@ --- *
+ *
+ * Arguments: @sel_state *s@ = the @sel@ multiplexor (unused)
+ * @sel_args *a@ = input to @select@, to be updated
+ * @void *p@ = a context pointer (unused)
+ *
+ * Returns: ---
+ *
+ * Use: An I/O multiplexor hook, called just before waiting for I/O
+ * events.
+ *
+ * Currently its main purpose is to wire ADNS into the event
+ * loop.
+ */
+
+static void before_select(sel_state *s, sel_args *a, void *p)
+{
+ struct timeval now;
+ adns_query q;
+ adns_answer *n;
+ admin_resop *r;
+ int any = 0;
+
+ /* --- Check for name-resolution progress --- *
+ *
+ * If there is any, then clobber the timeout: one of the resolver
+ * callbacks might have renewed its interest in a file descriptor, but too
+ * late to affect this @select@ call.
+ *
+ * I think, strictly, this is an mLib bug, but it's cheap enough to hack
+ * around here. Fixing it will wait for mLib 3.
+ */
+
+ for (;;) {
+ q = 0;
+ if (adns_check(ads, &q, &n, &p)) break;
+ r = p;
+ any = 1;
+ if (n->status != adns_s_ok) {
+ T( trace(T_ADMIN, "admin: resop %s failed: %s",
+ BGTAG(r), adns_strerror(n->status)); )
+ a_bgfail(&r->bg, "resolve-error", "%s", r->addr, A_END);
+ r->func(r, ARES_FAIL);
+ } else {
+ T( trace(T_ADMIN, "admin: resop %s ok", BGTAG(r)); )
+ assert(n->type == adns_r_addr);
+ assert(n->nrrs > 0);
+ assert(n->rrs.addr[0].len <= sizeof(r->sa));
+ memcpy(&r->sa, &n->rrs.addr[0].addr, n->rrs.addr[0].len);
+ setport(&r->sa, r->port);
+ r->func(r, ARES_OK);
+ }
+ free(n);
+ sel_rmtimer(&r->t);
+ xfree(r->addr);
+ a_bgrelease(&r->bg);
+ }
+
+ if (any) { a->tvp = &a->tv; a->tv.tv_sec = 0; a->tv.tv_usec = 0; }
+
+ gettimeofday(&now, 0);
+ adns_beforeselect(ads, &a->maxfd,
+ &a->fd[SEL_READ], &a->fd[SEL_WRITE], &a->fd[SEL_EXC],
+ &a->tvp, &a->tv, &now);
+}
+
+/* --- @after_select@ --- *
+ *
+ * Arguments: @sel_state *s@ = the @sel@ multiplexor (unused)
+ * @sel_args *a@ = input to @select@, to be updated
+ * @void *p@ = a context pointer (unused)
+ *
+ * Returns: ---
+ *
+ * Use: An I/O multiplexor hook, called just after waiting for I/O
+ * events.
+ *
+ * Currently its main purpose is to wire ADNS into the event
+ * loop.
+ */
+
+static void after_select(sel_state *s, sel_args *a, void *p)
+{
+ struct timeval now;
+
+ gettimeofday(&now, 0);
+ adns_afterselect(ads, a->maxfd,
+ &a->fd[SEL_READ], &a->fd[SEL_WRITE], &a->fd[SEL_EXC],
+ &now);
+}
+
+#else
+