X-Git-Url: https://git.distorted.org.uk/~mdw/adns/blobdiff_plain/226c5eef1caec08ee33276de158e263c0593c0d0..57d68ed152f47a68cd91fa25a67b11161f11d82a:/client/adh-query.c diff --git a/client/adh-query.c b/client/adh-query.c index 5c023a6..f2dd5c1 100644 --- a/client/adh-query.c +++ b/client/adh-query.c @@ -29,33 +29,43 @@ #include "adnshost.h" adns_state ads; +struct outstanding_list outstanding; -struct query_node { - struct query_node *next, *back; - struct perqueryflags_remember pqfr; - char *id; - adns_query qu; +static unsigned long idcounter; + +#define STATUSTYPEMAX(v) { adns_s_max_##v, #v } +static const struct statustypemax { + adns_status smax; + const char *abbrev; +} statustypemaxes[]= { + { adns_s_ok, "ok" }, + STATUSTYPEMAX(localfail), + STATUSTYPEMAX(remotefail), + STATUSTYPEMAX(tempfail), + STATUSTYPEMAX(misconfig), + STATUSTYPEMAX(misquery), + STATUSTYPEMAX(permfail), }; -static struct { struct query_node *head, *tail; } outstanding; +void ensure_adns_init(void) { + int r; + + if (ads) return; -static unsigned long idcounter; + if (signal(SIGPIPE,SIG_IGN) == SIG_ERR) sysfail("ignore SIGPIPE",errno); + r= adns_init(&ads, + adns_if_noautosys|adns_if_nosigpipe | + (ov_env ? 0 : adns_if_noenv) | + ov_verbose, + 0); + if (r) sysfail("adns_init",r); +} -void domain_do(const char *domain) { +void query_do(const char *domain) { struct query_node *qun; char idbuf[20]; int r; - if (!ads) { - if (signal(SIGPIPE,SIG_IGN) == SIG_ERR) sysfail("ignore SIGPIPE",errno); - r= adns_init(&ads, - adns_if_noautosys|adns_if_nosigpipe | - (ov_env ? 0 : adns_if_noenv) | - ov_verbose, - 0); - if (r) sysfail("adns_init",r); - } - qun= malloc(sizeof(*qun)); qun->pqfr= ov_pqfr; if (ov_id) { @@ -82,5 +92,115 @@ void domain_do(const char *domain) { LIST_LINK_TAIL(outstanding,qun); } -void of_asynch_id(const struct optioninfo *oi, const char *arg) { abort(); } +static void print_withspace(const char *str) { + if (printf("%s ", str) == EOF) outerr(); +} + +static void print_ttl(struct query_node *qun, adns_answer *answer) { + unsigned long ttl; + time_t now; + + switch (qun->pqfr.ttl) { + case tm_none: + return; + case tm_rel: + if (time(&now) == (time_t)-1) sysfail("get current time",errno); + ttl= answer->expires < now ? 0 : answer->expires - now; + break; + case tm_abs: + ttl= answer->expires; + break; + default: + abort(); + } + if (printf("%lu ",ttl) == EOF) outerr(); +} + +static void print_owner_ttl(struct query_node *qun, adns_answer *answer) { + if (qun->pqfr.show_owner) print_withspace(answer->owner); + print_ttl(qun,answer); +} + +static void print_status(adns_status st, struct query_node *qun, adns_answer *answer) { + int stnmin, stnmax, stn; + const char *statusabbrev, *statusstring; + + stnmin= 0; + stnmax= sizeof(statustypemaxes)/sizeof(statustypemaxes[0]); + while (stnmin < stnmax) { + stn= (stnmin+stnmax)>>1; + if (st > statustypemaxes[stn].smax) stnmin= stn+1; else stnmax= stn; + } + stn= stnmin; + assert(statustypemaxes[stn].smax >= st); + + if (rcode < stn) rcode= stn; + + statusabbrev= adns_errabbrev(st); + statusstring= adns_strerror(st); + assert(!strchr(statusstring,'"')); + + if (printf("%s %d %s ", statustypemaxes[stn].abbrev, st, statusabbrev) + == EOF) outerr(); + print_owner_ttl(qun,answer); + if (qun->pqfr.show_cname) + print_withspace(answer->cname ? answer->cname : "$"); + if (printf("\"%s\"\n", statusstring) == EOF) outerr(); +} + +void query_done(struct query_node *qun, adns_answer *answer) { + adns_status st, ist; + int rrn, nrrs; + const char *rrp, *realowner, *typename; + char *datastr; + + if (ov_pipe) setnonblock(1,0); + + st= answer->status; + nrrs= answer->nrrs; + if (ov_asynch) { + if (printf("%s %d", qun->id, nrrs) == EOF) outerr(); + print_status(st,qun,answer); + } else { + if (st) { + if (fputs("; failed",stdout) == EOF) outerr(); + print_status(st,qun,answer); + } else if (answer->cname) { + print_owner_ttl(qun,answer); + if (printf("CNAME %s\n",answer->cname) == EOF) outerr(); + } + } + if (qun->pqfr.show_owner) { + realowner= answer->cname ? answer->cname : answer->owner;; + assert(realowner); + } else { + realowner= 0; + } + if (nrrs) { + for (rrn=0, rrp = answer->rrs.untyped; + rrn < nrrs; + rrn++, rrp += answer->rrsz) { + if (realowner) print_withspace(realowner); + print_ttl(qun,answer); + ist= adns_rr_info(answer->type, &typename, 0, 0, rrp, &datastr); + if (ist == adns_s_nomemory) sysfail("adns_rr_info failed",ENOMEM); + assert(!ist); + if (qun->pqfr.show_type) print_withspace(typename); + if (printf("%s\n",datastr) == EOF) outerr(); + free(datastr); + } + } + if (fflush(stdout)) outerr(); + LIST_UNLINK(outstanding,qun); + free(answer); + free(qun->id); + free(qun); +} + +void of_asynch_id(const struct optioninfo *oi, const char *arg) { + free(ov_id); + ov_id= xstrsave(arg); +} + void of_cancel_id(const struct optioninfo *oi, const char *arg) { abort(); } +