+ Resolver *res= logfndata;
+ int l, newline;
+ char *str;
+
+ l= vasprintf(&str,fmt,al);
+ if (l<0) {
+ posixerr(res->interp,errno,"construct adns log callback string");
+ Tcl_BackgroundError(res->interp);
+ }
+
+ if (l==0) { free(str); return; }
+ if ((newline= l>0 && str[l-1]=='\n')) l--;
+
+ if (!res->errstring_accum) {
+ res->errstring_accum= Tcl_NewStringObj(str,l);
+ Tcl_IncrRefCount(res->errstring_accum);
+ } else {
+ Tcl_AppendToObj(res->errstring_accum,str,l);
+ }
+ free(str);
+
+ if (newline)
+ adnslogfn_flushmessage(res);
+}
+
+static Resolver *default_resolver(Tcl_Interp *ip) {
+ return Tcl_GetAssocData(ip,ASSOC_DEFAULTRES,0);
+}
+
+static void destroy_resolver(Tcl_Interp *ip, Resolver *res) {
+ void *query_v;
+ int logstring_len;
+ char *rstr;
+ adns_query aqu;
+
+ if (res == default_resolver(ip))
+ Tcl_DeleteAssocData(ip,ASSOC_DEFAULTRES);
+
+ if (res->errstring_accum) {
+ rstr= Tcl_GetStringFromObj(res->errstring_accum, &logstring_len);
+ assert(rstr);
+ if (logstring_len)
+ adnslogfn_flushmessage(res);
+ }
+
+ if (res->ads) {
+ /* although adns would throw these away for us, we need to
+ * destroy our own data too and only adns has a list of them */
+ for (;;) {
+ adns_forallqueries_begin(res->ads);
+ aqu= adns_forallqueries_next(res->ads, &query_v);
+ if (!aqu) break;
+ asynch_query_dispose(ip, query_v);
+ }
+ adns_finish(res->ads);
+ res->ads= 0;
+ }
+ asynch_cancelhandlers(res);
+ scriptinv_cancel(&res->errcallback);
+ Tcl_EventuallyFree(res, Tcl_Free);
+}
+
+static void destroy_resolver_idtabcb(Tcl_Interp *ip, void *resolver_v) {
+ destroy_resolver(ip,resolver_v);
+}
+static void destroy_resolver_defcb(ClientData resolver_v, Tcl_Interp *ip) {
+ destroy_resolver(ip,resolver_v);