Index: adns/INSTALL
diff -u adns/INSTALL:1.3 adns/INSTALL:1.4
--- adns/INSTALL:1.3	Sun Oct 10 14:16:23 1999
+++ adns/INSTALL	Wed Nov 24 16:57:32 1999
@@ -18,6 +18,14 @@
 However, if you send me an appropriate patch I'd be willing to make it
 easy or automatic to disable the ELF shared library arrangements.
 
+The adnsresfilter utility uses `tsearch' from the C library (a la SVID
+and X/Open).  If your C library doesn't have tsearch you will find
+that configure arranges for adnsresfilter not to be built.  To rectify
+this, install a C library containing tsearch, such as the GNU C
+library.  It is best if tsearch uses an automatically-balancing tree
+algorithm, like the glibc version does.  Simple binary trees may
+perform badly.
+
 You will probably find that GNU Make is required.
 
 
@@ -44,3 +52,7 @@
 along with userv as the file COPYING; if not, email me at the address
 above or write to the Free Software Foundation, 59 Temple Place -
 Suite 330, Boston, MA 02111-1307, USA.
+
+# Local variables:
+# mode: text
+# End:
Index: adns/Makefile.in
diff -u adns/Makefile.in:1.16 adns/Makefile.in:1.17
--- adns/Makefile.in:1.16	Wed Oct 13 02:26:09 1999
+++ adns/Makefile.in	Wed Nov 24 17:17:04 1999
@@ -21,7 +21,7 @@
 #  along with this program; if not, write to the Free Software Foundation,
 #  Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 
 
-DISTVERSION=	0.5
+DISTVERSION=	0.6
 srcdir=		@srcdir@
 VPATH=		@srcdir@
 
Index: adns/changelog
diff -u adns/changelog:1.58 adns/changelog:1.78
--- adns/changelog:1.58	Wed Oct 13 02:24:43 1999
+++ adns/changelog	Wed Nov 24 17:13:07 1999
@@ -1,3 +1,34 @@
+adns (0.6) BETA; urgency=high
+
+  Core library bugfixes:
+  * Avoid infinite timeouts, causing lockup, when they should be zero !
+  * TCP handling revamped (avoids undefined behaviour due to reentrancy).
+  * Do not fail assertion if _qf_owner, _qf_search, domain ends in `.'.
+  * Many memory leaks fixed.
+
+  Cool new utility:
+  * adnsresfilter is like `cat' but converts addresses to names without
+    delaying the output.  Pipe `netstat -n', `tcpdump -ln', etc. into it.
+
+  Test and client program bug and portability fixes:
+  * Dynamic library building works properly.
+  * adnshost prints somewhat better messages about some wrong usages.
+  * Include <stdlib.h> and <sys/types.h> in adnshost.h.
+  * adnslogres: parsing and error checking improved (Tony Finch).
+  * Regression tests can cope with zero-length reads.
+  * Regression tests check for memory leaks.
+  * adnstest copes with empty query type list.
+  * adnstest uninitialised memory bug fixed.
+
+  General improvements
+  * Better control of adnshost output and error messages (new -F options).
+  * New adns_if_logpid option (functionality suggested by Tony Finch).
+  * New fanftest test program from Tony Finch (ignored by `make install').
+  * Reads /etc/resolv-adns.conf if it exists.
+  * Declare flags parameters as enums again, not ints.
+
+ -- Ian Jackson <ian@davenant.greenend.org.uk>  Wed, 24 Nov 1999 17:13:03 +0000
+
 adns (0.5) unstable; urgency=high
 
   New features:
Index: adns/configure
diff -u adns/configure:1.8 adns/configure:1.10
--- adns/configure:1.8	Wed Oct 13 02:16:30 1999
+++ adns/configure	Wed Nov 24 16:57:32 1999
@@ -1040,14 +1040,71 @@
 
 
 
+PROGS_IF_TSEARCH=adnsresfilter
+
+echo $ac_n "checking for tsearch""... $ac_c" 1>&6
+echo "configure:1047: checking for tsearch" >&5
+if eval "test \"`echo '$''{'ac_cv_func_tsearch'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  cat > conftest.$ac_ext <<EOF
+#line 1052 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char tsearch(); below.  */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error.  */
+/* We use char because int might match the return type of a gcc2
+    builtin and then its argument prototype would still apply.  */
+char tsearch();
+
+int main() {
+
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined (__stub_tsearch) || defined (__stub___tsearch)
+choke me
+#else
+tsearch();
+#endif
+
+; return 0; }
+EOF
+if { (eval echo configure:1075: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
+  rm -rf conftest*
+  eval "ac_cv_func_tsearch=yes"
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  eval "ac_cv_func_tsearch=no"
+fi
+rm -f conftest*
+fi
+
+if eval "test \"`echo '$ac_cv_func_'tsearch`\" = yes"; then
+  echo "$ac_t""yes" 1>&6
+  
+ PROGS_HAVE_TSEARCH=$PROGS_IF_TSEARCH
+
+else
+  echo "$ac_t""no" 1>&6
+
+ PROGS_HAVE_TSEARCH='';
+ echo "configure: warning: tsearch missing - not building client program(s) $PROGS_IF_TSEARCH" 1>&2
+
+fi
+
+
 echo $ac_n "checking for INADDR_LOOPBACK""... $ac_c" 1>&6
-echo "configure:1045: checking for INADDR_LOOPBACK" >&5
+echo "configure:1102: checking for INADDR_LOOPBACK" >&5
 if eval "test \"`echo '$''{'adns_cv_decl_inaddrloopback'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   
  cat > conftest.$ac_ext <<EOF
-#line 1051 "configure"
+#line 1108 "configure"
 #include "confdefs.h"
 
 #include <sys/socket.h>
@@ -1060,7 +1117,7 @@
  
 ; return 0; }
 EOF
-if { (eval echo configure:1064: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:1121: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
   rm -rf conftest*
   adns_cv_decl_inaddrloopback=yes
 else
@@ -1078,17 +1135,17 @@
  echo "$ac_t""not in standard headers, urgh..." 1>&6
  ac_safe=`echo "rpc/types.h" | sed 'y%./+-%__p_%'`
 echo $ac_n "checking for rpc/types.h""... $ac_c" 1>&6
-echo "configure:1082: checking for rpc/types.h" >&5
+echo "configure:1139: checking for rpc/types.h" >&5
 if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 1087 "configure"
+#line 1144 "configure"
 #include "confdefs.h"
 #include <rpc/types.h>
 EOF
 ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:1092: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:1149: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
 ac_err=`grep -v '^ *+' conftest.out`
 if test -z "$ac_err"; then
   rm -rf conftest*
@@ -1121,12 +1178,12 @@
 
 
  echo $ac_n "checking for inet_aton""... $ac_c" 1>&6
-echo "configure:1125: checking for inet_aton" >&5
+echo "configure:1182: checking for inet_aton" >&5
 if eval "test \"`echo '$''{'ac_cv_func_inet_aton'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 1130 "configure"
+#line 1187 "configure"
 #include "confdefs.h"
 /* System header to define __stub macros and hopefully few prototypes,
     which can conflict with char inet_aton(); below.  */
@@ -1149,7 +1206,7 @@
 
 ; return 0; }
 EOF
-if { (eval echo configure:1153: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
+if { (eval echo configure:1210: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
   rm -rf conftest*
   eval "ac_cv_func_inet_aton=yes"
 else
@@ -1168,7 +1225,7 @@
   echo "$ac_t""no" 1>&6
 
   echo $ac_n "checking for inet_aton in -lresolv""... $ac_c" 1>&6
-echo "configure:1172: checking for inet_aton in -lresolv" >&5
+echo "configure:1229: checking for inet_aton in -lresolv" >&5
 ac_lib_var=`echo resolv'_'inet_aton | sed 'y%./+-%__p_%'`
 if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
@@ -1176,7 +1233,7 @@
   ac_save_LIBS="$LIBS"
 LIBS="-lresolv  $LIBS"
 cat > conftest.$ac_ext <<EOF
-#line 1180 "configure"
+#line 1237 "configure"
 #include "confdefs.h"
 /* Override any gcc2 internal prototype to avoid an error.  */
 /* We use char because int might match the return type of a gcc2
@@ -1187,7 +1244,7 @@
 inet_aton()
 ; return 0; }
 EOF
-if { (eval echo configure:1191: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
+if { (eval echo configure:1248: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
   rm -rf conftest*
   eval "ac_cv_lib_$ac_lib_var=yes"
 else
@@ -1221,20 +1278,20 @@
 
  
  echo $ac_n "checking __attribute__((,,))""... $ac_c" 1>&6
-echo "configure:1225: checking __attribute__((,,))" >&5
+echo "configure:1282: checking __attribute__((,,))" >&5
  if eval "test \"`echo '$''{'adns_cv_c_attribute_supported'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   
   cat > conftest.$ac_ext <<EOF
-#line 1231 "configure"
+#line 1288 "configure"
 #include "confdefs.h"
 
 int main() {
 extern int testfunction(int x) __attribute__((,,))
 ; return 0; }
 EOF
-if { (eval echo configure:1238: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:1295: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
   rm -rf conftest*
   adns_cv_c_attribute_supported=yes
 else
@@ -1256,20 +1313,20 @@
 
    
  echo $ac_n "checking __attribute__((noreturn))""... $ac_c" 1>&6
-echo "configure:1260: checking __attribute__((noreturn))" >&5
+echo "configure:1317: checking __attribute__((noreturn))" >&5
  if eval "test \"`echo '$''{'adns_cv_c_attribute_noreturn'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   
   cat > conftest.$ac_ext <<EOF
-#line 1266 "configure"
+#line 1323 "configure"
 #include "confdefs.h"
 
 int main() {
 extern int testfunction(int x) __attribute__((noreturn))
 ; return 0; }
 EOF
-if { (eval echo configure:1273: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:1330: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
   rm -rf conftest*
   adns_cv_c_attribute_noreturn=yes
 else
@@ -1296,20 +1353,20 @@
 
    
  echo $ac_n "checking __attribute__((const))""... $ac_c" 1>&6
-echo "configure:1300: checking __attribute__((const))" >&5
+echo "configure:1357: checking __attribute__((const))" >&5
  if eval "test \"`echo '$''{'adns_cv_c_attribute_const'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   
   cat > conftest.$ac_ext <<EOF
-#line 1306 "configure"
+#line 1363 "configure"
 #include "confdefs.h"
 
 int main() {
 extern int testfunction(int x) __attribute__((const))
 ; return 0; }
 EOF
-if { (eval echo configure:1313: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:1370: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
   rm -rf conftest*
   adns_cv_c_attribute_const=yes
 else
@@ -1336,20 +1393,20 @@
 
    
  echo $ac_n "checking __attribute__((format...))""... $ac_c" 1>&6
-echo "configure:1340: checking __attribute__((format...))" >&5
+echo "configure:1397: checking __attribute__((format...))" >&5
  if eval "test \"`echo '$''{'adns_cv_attribute_format'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   
   cat > conftest.$ac_ext <<EOF
-#line 1346 "configure"
+#line 1403 "configure"
 #include "confdefs.h"
 
 int main() {
 extern int testfunction(char *y, ...) __attribute__((format(printf,1,2)))
 ; return 0; }
 EOF
-if { (eval echo configure:1353: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:1410: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
   rm -rf conftest*
   adns_cv_attribute_format=yes
 else
@@ -1398,15 +1455,15 @@
 
 
 
-SHLIBCC='$(CC) $(CFLAGS) -fpic'
-MKSHLIB_1='$(CC) $(LDFLAGS) -shared -Wxl,soname=$(SONAME) -o'
-MKSHLIB_2=''
-MKSHLIB_3='-lc'
-
 SHLIBFORLINK='libadns.so'
 SHLIBSONAME='$(SHLIBFORLINK).$(MAJOR)'
 SHLIBFILE='$(SHLIBSONAME).$(MINOR)'
 
+SHLIBCC='$(CC) $(CFLAGS) -fpic'
+MKSHLIB_1='$(CC) $(LDFLAGS) -shared -Wl,-soname=$(SHLIBSONAME) -o'
+MKSHLIB_2=''
+MKSHLIB_3='-lc'
+
 trap '' 1 2 15
 cat > confcache <<\EOF
 # This file is a shell script that caches the results of configure
@@ -1542,6 +1599,7 @@
 s%@CC@%$CC%g
 s%@CPP@%$CPP%g
 s%@RANLIB@%$RANLIB%g
+s%@PROGS_HAVE_TSEARCH@%$PROGS_HAVE_TSEARCH%g
 s%@WARNS@%$WARNS%g
 s%@SHLIBCC@%$SHLIBCC%g
 s%@MKSHLIB_1@%$MKSHLIB_1%g
Index: adns/configure.in
diff -u adns/configure.in:1.9 adns/configure.in:1.11
--- adns/configure.in:1.9	Wed Oct 13 02:16:30 1999
+++ adns/configure.in	Wed Nov 24 16:57:32 1999
@@ -31,6 +31,15 @@
 ADNS_C_GETFUNC(socket,socket)
 ADNS_C_GETFUNC(inet_ntoa,nsl)
 
+PROGS_IF_TSEARCH=adnsresfilter
+AC_SUBST(PROGS_HAVE_TSEARCH)
+AC_CHECK_FUNC(tsearch,[
+ PROGS_HAVE_TSEARCH=$PROGS_IF_TSEARCH
+],[
+ PROGS_HAVE_TSEARCH='';
+ AC_MSG_WARN([tsearch missing - not building client program(s) $PROGS_IF_TSEARCH])
+])
+
 AC_MSG_CHECKING(for INADDR_LOOPBACK)
 AC_CACHE_VAL(adns_cv_decl_inaddrloopback,[
  AC_TRY_COMPILE([
@@ -77,14 +86,14 @@
 AC_SUBST(SHLIBFILE)
 AC_SUBST(SHLIBSONAME)
 
-SHLIBCC='$(CC) $(CFLAGS) -fpic'
-MKSHLIB_1='$(CC) $(LDFLAGS) -shared -Wxl,soname=$(SONAME) -o'
-MKSHLIB_2=''
-MKSHLIB_3='-lc'
-
 SHLIBFORLINK='libadns.so'
 SHLIBSONAME='$(SHLIBFORLINK).$(MAJOR)'
 SHLIBFILE='$(SHLIBSONAME).$(MINOR)'
+
+SHLIBCC='$(CC) $(CFLAGS) -fpic'
+MKSHLIB_1='$(CC) $(LDFLAGS) -shared -Wl,-soname=$(SHLIBSONAME) -o'
+MKSHLIB_2=''
+MKSHLIB_3='-lc'
 
 AC_OUTPUT(
 	settings.make Makefile
Index: adns/client/.cvsignore
diff -u adns/client/.cvsignore:1.5 adns/client/.cvsignore:1.7
--- adns/client/.cvsignore:1.5	Sun Aug 15 18:23:14 1999
+++ adns/client/.cvsignore	Wed Nov  3 02:25:25 1999
@@ -5,3 +5,7 @@
 adnslogres_s
 adnshost
 adnshost_s
+adnsresfilter
+adnsresfilter_s
+fanftest
+fanftest_s
Index: adns/client/Makefile.in
diff -u adns/client/Makefile.in:1.14 adns/client/Makefile.in:1.20
--- adns/client/Makefile.in:1.14	Wed Oct 13 02:23:38 1999
+++ adns/client/Makefile.in	Wed Nov 24 16:57:32 1999
@@ -24,17 +24,26 @@
 srcdir=		@srcdir@
 VPATH=		@srcdir@
 
-PROGRAMS=	adnstest adnslogres adnshost
+PROGS_SYSDEP=		@PROGS_HAVE_TSEARCH@
+
+PROGRAMS=	adnstest adnslogres adnshost $(PROGS_SYSDEP)
+PROGRAMS_LOCAL=	fanftest
+PROGRAMS_ALL=	$(PROGRAMS) $(PROGRAMS_LOCAL)
+
 TARG_INSTALL=	$(PROGRAMS)
-TARG_LOCAL=	$(addsuffix _s, $(PROGRAMS))
+TARG_LOCAL=	$(addsuffix _s, $(PROGRAMS_ALL))
 TARGETS=	$(TARG_LOCAL) $(TARG_INSTALL)
 include		$(srcdir)/../settings.make
 
 DIRCFLAGS=	-I$(srcdir)/../src
 
+TARG_OBJS=	$(addsuffix .o, $(PROGRAMS_ALL))
 ADH_OBJS=	adh-main.o adh-opts.o adh-query.o
+ALL_OBJS=	$(ADH_OBJS) $(TARG_OBJS)
+
+ADNSDIR=	$(srcdir)/../src/
 
-STATIC_LIB=	$(srcdir)/../src/libadns.a
+STATIC_LIB=	$(ADNSDIR)/libadns.a
 DYNAMIC_DEP=	$(srcdir)/../dynamic/$(SHLIBFILE)
 DYNAMIC_LINK=	-L$(srcdir)/../dynamic -ladns
 
@@ -47,16 +56,19 @@
 uninstall:
 		for f in $(TARGETS); do rm -f $(bin_dir)/$$f; done
 
-$(ADH_OBJS):	adnshost.h
-
 adnshost:	$(ADH_OBJS) $(DYNAMIC_DEP)
 		$(CC) $(LDFLAGS) $(ADH_OBJS) $(DYNAMIC_LINK) -o $@ $(LDLIBS)
 
 adnshost_s:	$(ADH_OBJS) $(STATIC_LIB)
 		$(CC) $(LDFLAGS) $(ADH_OBJS) $(STATIC_LIB) -o $@ $(LDLIBS)
 
+$(ADH_OBJS):		adnshost.h
+$(ALL_OBJS):		$(ADNSDIR)/adns.h $(ADNSDIR)/config.h
+adnsresfilter.o:	$(ADNSDIR)/tvarith.h
+
 %:		%.o $(DYNAMIC_DEP)
 		$(CC) $(LDFLAGS) $< $(DYNAMIC_LINK) -o $@ $(LDLIBS)
 
 %_s:		%.o $(STATIC_LIB)
 		$(CC) $(LDFLAGS) $< $(STATIC_LIB) -o $@ $(LDLIBS)
+
Index: adns/client/adh-opts.c
diff -u adns/client/adh-opts.c:1.8 adns/client/adh-opts.c:1.10
--- adns/client/adh-opts.c:1.8	Wed Oct 13 01:57:36 1999
+++ adns/client/adh-opts.c	Fri Oct 15 18:55:45 1999
@@ -32,7 +32,7 @@
 int ov_verbose= 0;
 adns_rrtype ov_type= adns_r_none;
 int ov_search=0, ov_qc_query=0, ov_qc_anshost=0, ov_qc_cname=1;
-int ov_tcp=0, ov_cname=0;
+int ov_tcp=0, ov_cname=0, ov_format=fmt_default;
 char *ov_id= 0;
 struct perqueryflags_remember ov_pqfr = { 1,1,1, tm_none };
 
@@ -44,6 +44,14 @@
     "f", "pipe",           &ov_pipe, 1 },
   { ot_flag,             "Allow answers to be reordered",
     "a", "asynch",         &ov_asynch, 1 },
+  
+  { ot_desconly, "answer/error output format and destination (see below):" },
+  { ot_value,            "Answers to stdout, errors as messages to stderr (default)",
+    "Fs", "fmt-simple",    &ov_format, fmt_simple },
+  { ot_value,            "Answers and errors both to stdout in parseable format",
+    "Fi", "fmt-inline",    &ov_format, fmt_inline },
+  { ot_value,            "Fully-parseable output format (default for --asynch)",
+    "Fa", "fmt-asynch",    &ov_format, fmt_asynch },
   		         
   { ot_desconly, "global verbosity level:" },
   { ot_value,            "Do not print anything to stderr",
@@ -216,11 +224,12 @@
 	"or if the <owner> domain refers to a CNAME and --show-cname is on\n"
 	"   [<owner>] [<ttl>] CNAME <cname>\n"
 	"   [<cname>] [<ttl>] <type> <data>\n"
-	"When a query fails you get a line like this (broken here for readability):\n"
+	"When a query fails you get an error message to stderr (with --fmt-simple).\n"
+	"Specify --fmt-inline for lines like this (broken here for readability):\n"
 	"   ; failed <statustype> <statusnum> <statusabbrev> \\\n"
 	"       [<owner>] [<ttl>] [<cname>] \"<status string>\"\n"
-	"\n"
-	"If you use --asynch each answer (success or failure) is preceded by a line\n"
+	"If you use --fmt-asynch, which is the default for --asynch,\n"
+	"each answer (success or failure) is preceded by a line\n"
 	"   <id> <nrrs> <statustype> <statusnum> <statusabbrev> \\\n"
 	"       [<owner>] [<ttl>] [<cname>] \"<status string>\"\n"
 	"where <nrrs> is the number of RRs that follow and <cname> will be `$' or\n"
@@ -285,12 +294,14 @@
 				     const char *prefix,
 				     comparer_type *comparer) {
   const struct optioninfo *oip;
+  const char *opt;
 
+  opt= *optp;
   oip= find1(optp,perquery_options,comparer);
   if (oip) return oip;
   oip= find1(optp,global_options,comparer);
-  if (!oip) usageerr("unknown option %s%s",prefix,*optp);
-  if (ads) usageerr("global option %s%s specified after query domain(s)",prefix,*optp);
+  if (!oip) usageerr("unknown option %s%s",prefix,opt);
+  if (ads) usageerr("global option %s%s specified after query domain(s)",prefix,opt);
   return oip;
 }
 
Index: adns/client/adh-query.c
diff -u adns/client/adh-query.c:1.8 adns/client/adh-query.c:1.10
--- adns/client/adh-query.c:1.8	Wed Oct 13 01:57:36 1999
+++ adns/client/adh-query.c	Fri Oct 15 18:55:45 1999
@@ -45,6 +45,9 @@
 	       ov_verbose,
 	       0);
   if (r) sysfail("adns_init",r);
+
+  if (ov_format == fmt_default)
+    ov_format= ov_asynch ? fmt_asynch : fmt_simple;
 }
 
 static void prep_query(struct query_node **qun_r, int *quflags_r) {
@@ -67,7 +70,7 @@
   *quflags_r=
     (ov_search ? adns_qf_search : 0) |
     (ov_tcp ? adns_qf_usevc : 0) |
-    (ov_pqfr.show_owner ? adns_qf_owner : 0) |
+    ((ov_pqfr.show_owner || ov_format == fmt_simple) ? adns_qf_owner : 0) |
     (ov_qc_query ? adns_qf_quoteok_query : 0) |
     (ov_qc_anshost ? adns_qf_quoteok_anshost : 0) |
     (ov_qc_cname ? 0 : adns_qf_quoteok_cname) |
@@ -147,7 +150,7 @@
   print_ttl(qun,answer);
 }
 
-static void print_status(adns_status st, struct query_node *qun, adns_answer *answer) {
+static void check_status(adns_status st) {
   static const adns_status statuspoints[]= {
     adns_s_ok,
     adns_s_max_localfail, adns_s_max_remotefail, adns_s_max_tempfail,
@@ -155,16 +158,19 @@
   };
 
   const adns_status *spp;
-  const char *statustypeabbrev, *statusabbrev, *statusstring;
   int minrcode;
 
-  statustypeabbrev= adns_errtypeabbrev(st);
   for (minrcode=0, spp=statuspoints;
        spp < statuspoints + (sizeof(statuspoints)/sizeof(statuspoints[0]));
        spp++)
     if (st > *spp) minrcode++;
   if (rcode < minrcode) rcode= minrcode;
+}
 
+static void print_status(adns_status st, struct query_node *qun, adns_answer *answer) {
+  const char *statustypeabbrev, *statusabbrev, *statusstring;
+
+  statustypeabbrev= adns_errtypeabbrev(st);
   statusabbrev= adns_errabbrev(st);
   statusstring= adns_strerror(st);
   assert(!strchr(statusstring,'"'));
@@ -177,6 +183,32 @@
   if (printf("\"%s\"\n", statusstring) == EOF) outerr();
 }
 
+static void print_dnsfail(adns_status st, struct query_node *qun, adns_answer *answer) {
+  int r;
+  const char *typename, *statusstring;
+  adns_status ist;
+  
+  if (ov_format == fmt_inline) {
+    if (fputs("; failed ",stdout) == EOF) outerr();
+    print_status(st,qun,answer);
+    return;
+  }
+  assert(ov_format == fmt_simple);
+  if (st == adns_s_nxdomain) {
+    r= fprintf(stderr,"%s does not exist\n", answer->owner);
+  } else {
+    ist= adns_rr_info(answer->type, &typename, 0,0,0,0);
+    if (st == adns_s_nodata) {
+      r= fprintf(stderr,"%s has no %s record\n", answer->owner, typename);
+    } else {
+      statusstring= adns_strerror(st);
+      r= fprintf(stderr,"Error during DNS %s lookup for %s: %s\n",
+		 typename, answer->owner, statusstring);
+    }
+  }
+  if (r == EOF) sysfail("write error message to stderr",errno);
+}
+    
 void query_done(struct query_node *qun, adns_answer *answer) {
   adns_status st, ist;
   int rrn, nrrs;
@@ -185,20 +217,23 @@
 
   st= answer->status;
   nrrs= answer->nrrs;
-  if (ov_asynch) {
+  if (ov_format == fmt_asynch) {
+    check_status(st);
     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 (qun->pqfr.show_cname && answer->cname) {
+    if (qun->pqfr.show_cname && answer->cname) {
       print_owner_ttl(qun,answer);
-      if (printf("CNAME %s\n",answer->cname) == EOF) outerr();
+      if (qun->pqfr.show_type) print_withspace("CNAME");
+      if (printf("%s\n", answer->cname) == EOF) outerr();
+    }
+    if (st) {
+      check_status(st);
+      print_dnsfail(st,qun,answer);
     }
   }
   if (qun->pqfr.show_owner) {
-    realowner= answer->cname ? answer->cname : answer->owner;;
+    realowner= answer->cname ? answer->cname : answer->owner;
     assert(realowner);
   } else {
     realowner= 0;
Index: adns/client/adnshost.h
diff -u adns/client/adnshost.h:1.6 adns/client/adnshost.h:1.9
--- adns/client/adnshost.h:1.6	Wed Oct 13 01:57:36 1999
+++ adns/client/adnshost.h	Tue Nov  2 22:22:43 1999
@@ -28,6 +28,7 @@
 #ifndef ADNSHOST_H_INCLUDED
 #define ADNSHOST_H_INCLUDED
 
+#include <stdlib.h>
 #include <stdio.h>
 #include <string.h>
 #include <errno.h>
@@ -36,6 +37,7 @@
 #include <stdlib.h>
 #include <assert.h>
 
+#include <sys/types.h>
 #include <sys/socket.h>
 #include <netinet/in.h>
 #include <arpa/inet.h>
@@ -62,6 +64,7 @@
 };
 
 enum ttlmode { tm_none, tm_rel, tm_abs };
+enum outputformat { fmt_default, fmt_simple, fmt_inline, fmt_asynch };
 
 struct perqueryflags_remember {
   int show_owner, show_type, show_cname;
@@ -72,7 +75,7 @@
 extern int ov_verbose;
 extern adns_rrtype ov_type;
 extern int ov_search, ov_qc_query, ov_qc_anshost, ov_qc_cname;
-extern int ov_tcp, ov_cname;
+extern int ov_tcp, ov_cname, ov_format;
 extern char *ov_id;
 extern struct perqueryflags_remember ov_pqfr;
 
Index: adns/client/adnslogres.c
diff -u adns/client/adnslogres.c:1.5 adns/client/adnslogres.c:1.7
--- adns/client/adnslogres.c:1.5	Tue Oct 12 23:56:16 1999
+++ adns/client/adnslogres.c	Fri Oct 15 17:46:14 1999
@@ -30,7 +30,7 @@
  */
 
 static const char * const cvsid =
-	"$Id: adnslogres.c,v 1.5 1999/10/12 22:56:16 ian Exp $";
+	"$Id: adnslogres.c,v 1.7 1999/10/15 16:46:14 ian Exp $";
 
 #include <sys/types.h>
 #include <sys/time.h>
@@ -56,9 +56,12 @@
 
 static const char *progname;
 
-static void aargh(const char *msg) {
-  fprintf(stderr, "%s: %s: %s (%d)\n", progname, msg,
-	  strerror(errno) ? strerror(errno) : "Unknown error", errno);
+#define msg(fmt, args...) fprintf(stderr, "%s: " fmt "\n", progname, ##args)
+
+static void aargh(const char *cause) {
+  const char *why = strerror(errno);
+  if (!why) why = "Unknown error";
+  msg("%s: %s (%d)", cause, why, errno);
   exit(1);
 }
 
@@ -78,13 +81,15 @@
       *addr= *rest= NULL;
       return buf;
     }
-  for (i= 1; i < 5; i ++) {
-    ptrs[i]= strchr(ptrs[i-1], (i == 4) ? ' ' : '.');
-    if (!ptrs[i] || ptrs[i]-ptrs[i-1] > 3) {
-      ptrs[0]++;
+  for (i= 1; i < 5; i++) {
+    ptrs[i]= ptrs[i-1];
+    while (isdigit(*ptrs[i]++));
+    if ((i == 4 && !isspace(ptrs[i][-1])) ||
+	(i != 4 && ptrs[i][-1] != '.') ||
+	(ptrs[i]-ptrs[i-1] > 4)) {
+      ptrs[0]= ptrs[i]-1;
       goto retry;
-    } else
-      ptrs[i]++;
+    }
   }
   sprintf(buf, "%.*s.%.*s.%.*s.%.*s.in-addr.arpa.",
 	  ptrs[4]-ptrs[3]-1, ptrs[3],
@@ -96,12 +101,12 @@
   return buf;
 }
 
-static void printline(char *start, char *addr, char *rest, char *domain) {
+static void printline(FILE *outf, char *start, char *addr, char *rest, char *domain) {
   if (domain)
-    printf("%.*s%s%s", addr - start, start, domain, rest);
+    fprintf(outf, "%.*s%s%s", addr - start, start, domain, rest);
   else
-    fputs(start, stdout);
-  if (ferror(stdout)) aargh("write output");
+    fputs(start, outf);
+  if (ferror(outf)) aargh("write output");
 }
 
 typedef struct logline {
@@ -110,33 +115,33 @@
   adns_query query;
 } logline;
 
-static logline *readline(adns_state adns, int opts) {
+static logline *readline(FILE *inf, adns_state adns, int opts) {
   static char buf[MAXLINE];
   char *str;
   logline *line;
 
-  if (fgets(buf, MAXLINE, stdin)) {
+  if (fgets(buf, MAXLINE, inf)) {
     str= malloc(sizeof(*line) + strlen(buf) + 1);
     if (!str) aargh("malloc");
     line= (logline*)str;
     line->next= NULL;
     line->start= str+sizeof(logline);
     strcpy(line->start, buf);
-    str = ipaddr2domain(line->start, &line->addr, &line->rest);
+    str= ipaddr2domain(line->start, &line->addr, &line->rest);
     if (opts & OPT_DEBUG)
-	fprintf(stderr, "%s: adns_submit %s\n", progname, str);
+      msg("submitting %.*s -> %s", line->rest-line->addr, line->addr, str);
     if (adns_submit(adns, str, adns_r_ptr,
 		    adns_qf_quoteok_cname|adns_qf_cname_loose,
 		    NULL, &line->query))
       aargh("adns_submit");
     return line;
   }
-  if (!feof(stdin))
+  if (!feof(inf))
     aargh("fgets");
   return NULL;
 }
 	
-static void proclog(int opts) {
+static void proclog(FILE *inf, FILE *outf, int opts) {
   int eof, err, len;
   adns_state adns;
   adns_answer *answer;
@@ -144,9 +149,12 @@
 
   errno= adns_init(&adns, (opts & OPT_DEBUG) ? adns_if_debug : 0, 0);
   if (errno) aargh("adns_init");
-  head= tail= readline(adns, opts);
+  head= tail= readline(inf, adns, opts);
   len= 1; eof= 0;
   while (head) {
+    if (opts & OPT_DEBUG)
+      msg("%d in queue; checking %.*s", len,
+	  head->rest-head->addr, head->addr);
     if (eof || len > MAXPENDING)
       if (opts & OPT_POLL)
 	err= adns_wait_poll(adns, &head->query, &answer, NULL);
@@ -155,22 +163,22 @@
     else
       err= adns_check(adns, &head->query, &answer, NULL);
     if (err != EAGAIN) {
-	printline(head->start, head->addr, head->rest,
-		  answer->status == adns_s_ok ? *answer->rrs.str : NULL);
-	line= head; head= head->next;
-	free(line); free(answer);
-	len--;
+      printline(outf, head->start, head->addr, head->rest,
+		answer->status == adns_s_ok ? *answer->rrs.str : NULL);
+      line= head; head= head->next;
+      free(line); free(answer);
+      len--;
     }
     if (!eof) {
-      line= readline(adns, opts);
+      line= readline(inf, adns, opts);
       if (!line)
 	eof= 1;
       else {
 	if (!head)
-	  head = line;
+	  head= line;
 	else
-	  tail->next = line;
-	tail = line;
+	  tail->next= line;
+	tail= line;
 	len++;
       }
     }
@@ -178,30 +186,54 @@
   adns_finish(adns);
 }
 
+static void usage(void) {
+  fprintf(stderr, "usage: %s [-d] [-p] [logfile]\n", progname);
+  exit(1);
+}
+
 int main(int argc, char *argv[]) {
   int c, opts;
+  FILE *inf;
 
-  progname= *argv;
+  progname= strrchr(*argv, '/');
+  if (progname)
+    progname++;
+  else
+    progname= *argv;
   opts= 0;
 
-  while ((c= getopt(argc, argv, "dp")) != -1) {
+  while ((c= getopt(argc, argv, "dp")) != -1)
     switch (c) {
     case 'd':
-      opts |= OPT_DEBUG;
+      opts|= OPT_DEBUG;
       break;
     case 'p':
-      opts |= OPT_POLL;
+      opts|= OPT_POLL;
       break;
     default:
-      fprintf(stderr, "usage: %s [-d] < logfile\n", progname);
-      exit(1);
+      usage();
     }
-    argc-= optind;
-    argv+= optind;
-  }
+
+  argc-= optind;
+  argv+= optind;
+
+  inf= NULL;
+  if (argc == 0)
+    inf= stdin;
+  else if (argc == 1)
+    inf= fopen(*argv, "r");
+  else
+    usage();
+
+  if (!inf)
+    aargh("couldn't open input");
+
+  proclog(inf, stdout, opts);
 
-  proclog(opts);
+  if (fclose(inf))
+    aargh("fclose input");
+  if (fclose(stdout))
+    aargh("fclose output");
 
-  if (fclose(stdout)) aargh("finish writing output");
   return 0;
 }
Index: adns/client/adnsresfilter.c
diff -u /dev/null adns/client/adnsresfilter.c:1.6
--- /dev/null	Wed Nov 24 17:20:58 1999
+++ adns/client/adnsresfilter.c	Wed Nov 24 17:10:56 1999
@@ -0,0 +1,454 @@
+/*
+ * adnsresfilter.c
+ * - filter which does resolving, not part of the library
+ */
+/*
+ *  This file is
+ *    Copyright (C) 1999 Ian Jackson <ian@davenant.greenend.org.uk>
+ *
+ *  It is part of adns, which is
+ *    Copyright (C) 1997-1999 Ian Jackson <ian@davenant.greenend.org.uk>
+ *    Copyright (C) 1999 Tony Finch <dot@dotat.at>
+ *  
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2, or (at your option)
+ *  any later version.
+ *  
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *  
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software Foundation,
+ *  Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <search.h>
+#include <assert.h>
+#include <ctype.h>
+
+#include <sys/fcntl.h>
+
+#include "adns.h"
+#include "config.h"
+#include "dlist.h"
+#include "tvarith.h"
+
+struct outqueuenode {
+  struct outqueuenode *next, *back;
+  void *buffer;
+  char *textp;
+  int textlen;
+  struct timeval printbefore;
+  struct treething *addr;
+};
+
+static int bracket, forever, address;
+static unsigned long timeout=100;
+static adns_rrtype rrt= adns_r_ptr;
+
+static int outblocked, inputeof;
+static struct { struct outqueuenode *head, *tail; } outqueue;
+static int peroutqueuenode, outqueuelen;
+
+static struct sockaddr_in sa;
+static adns_state ads;
+
+static char addrtextbuf[14];
+static int cbyte, inbyte, inbuf;
+static unsigned char bytes[4];
+static struct timeval printbefore;
+
+struct treething {
+  unsigned char bytes[4];
+  adns_query qu;
+  adns_answer *ans;
+};
+
+static struct treething *newthing;
+static void *treeroot;
+
+static int nonblock(int fd, int isnonblock) {
+  int r;
+
+  r= fcntl(fd,F_GETFL); 
+  if (r==-1) return -1;
+  r= fcntl(fd,F_SETFL, isnonblock ? r|O_NONBLOCK : r&~O_NONBLOCK);
+  if (r==-1) return -1;
+  return 0;
+}
+
+static void quit(int exitstatus) NONRETURNING;
+static void quit(int exitstatus) {
+  nonblock(0,0);
+  nonblock(1,0);
+  exit(exitstatus);
+}
+
+static void sysfail(const char *what) NONRETURNING;
+static void sysfail(const char *what) {
+  fprintf(stderr,"adnsresfilter: system call failed: %s: %s\n",what,strerror(errno));
+  quit(2);
+}
+
+static void *xmalloc(size_t sz) {
+  void *r;
+  r= malloc(sz);  if (r) return r;
+  sysfail("malloc");
+}
+
+static void outputerr(void) NONRETURNING;
+static void outputerr(void) { sysfail("write to stdout"); }
+
+static void usage(void) {
+  if (printf("usage: adnsresfilter [<options ...>]\n"
+	     "       adnsresfilter  -h|--help\n"
+	     "options: -t<milliseconds>|--timeout <milliseconds>\n"
+	     "         -w|--wait        (always wait for queries to time out or fail)\n"
+	     "         -b|--brackets    (require [...] around IP addresses)\n"
+	     "         -a|--address     (always include [address] in output)\n"
+	     "         -u|--unchecked   (do not forward map for checking)\n"
+	     "Timeout is the maximum amount to delay any particular bit of output for.\n"
+	     "Lookups will go on in the background.  Default timeout = 100 (ms).\n")
+      == EOF) outputerr();
+}
+
+static void usageerr(const char *why) NONRETURNING;
+static void usageerr(const char *why) {
+  fprintf(stderr,"adnsresfilter: bad usage: %s\n",why);
+  usage();
+  quit(1);
+}
+
+static void adnsfail(const char *what, int e) NONRETURNING;
+static void adnsfail(const char *what, int e) {
+  fprintf(stderr,"adnsresfilter: adns call failed: %s: %s\n",what,strerror(e));
+  quit(2);
+}
+
+static void settimeout(const char *arg) {
+  char *ep;
+  timeout= strtoul(arg,&ep,0);
+  if (*ep) usageerr("invalid timeout");
+}
+
+static void parseargs(const char *const *argv) {
+  const char *arg;
+  int c;
+
+  while ((arg= *++argv)) {
+    if (arg[0] != '-') usageerr("no non-option arguments are allowed");
+    if (arg[1] == '-') {
+      if (!strcmp(arg,"--brackets")) {
+	bracket= 1;
+      } else if (!strcmp(arg,"--unchecked")) {
+	rrt= adns_r_ptr_raw;
+      } else if (!strcmp(arg,"--wait")) {
+	forever= 1;
+      } else if (!strcmp(arg,"--address")) {
+	address= 1;
+      } else if (!strcmp(arg,"--help")) {
+	usage(); quit(0);
+      } else if (!strcmp(arg,"--timeout")) {
+	if (!(arg= *++argv)) usageerr("--timeout needs a value");
+	settimeout(arg);
+	forever= 0;
+      } else {
+	usageerr("unknown long option");
+      }
+    } else {
+      while ((c= *++arg)) {
+	switch (c) {
+	case 'b':
+	  bracket= 1;
+	  break;
+	case 'u':
+	  rrt= adns_r_ptr_raw;
+	  break;
+	case 'w':
+	  forever= 1;
+	  break;
+	case 'a':
+	  address= 1;
+	  break;
+	case 'h':
+	  usage();
+	  quit(0);
+	case 't':
+	  if (*++arg) settimeout(arg);
+	  else if ((arg= *++argv)) settimeout(arg);
+	  else usageerr("-t needs a value");
+	  forever= 0;
+	  arg= "\0";
+	  break;
+	default:
+	  usageerr("unknown short option");
+	}
+      }
+    }
+  }
+}
+
+static void queueoutchar(int c) {
+  struct outqueuenode *entry;
+  
+  entry= outqueue.tail;
+  if (!entry || entry->addr || entry->textlen >= peroutqueuenode) {
+    peroutqueuenode= !peroutqueuenode || !entry || entry->addr ? 128 : 
+      peroutqueuenode >= 1024 ? 4096 : peroutqueuenode<<2;
+    entry= xmalloc(sizeof(*entry));
+    entry->buffer= xmalloc(peroutqueuenode);
+    entry->textp= entry->buffer;
+    entry->textlen= 0;
+    entry->addr= 0;
+    LIST_LINK_TAIL(outqueue,entry);
+    outqueuelen++;
+  }
+  entry->textp[entry->textlen++]= c;
+}
+
+static void queueoutstr(const char *str, int len) {
+  while (len-- > 0) queueoutchar(*str++);
+}
+
+static void writestdout(struct outqueuenode *entry) {
+  int r;
+
+  while (entry->textlen) {
+    r= write(1, entry->textp, entry->textlen);
+    if (r < 0) {
+      if (errno == EINTR) continue;
+      if (errno == EAGAIN) { outblocked= 1; break; }
+      sysfail("write stdout");
+    }
+    assert(r <= entry->textlen);
+    entry->textp += r;
+    entry->textlen -= r;
+  }
+  if (!entry->textlen) {
+    LIST_UNLINK(outqueue,entry);
+    free(entry->buffer);
+    free(entry);
+    outqueuelen--;
+  }
+}
+
+static void replacetextwithname(struct outqueuenode *entry) {
+  char *name, *newbuf;
+  int namelen, newlen;
+
+  name= entry->addr->ans->rrs.str[0];
+  namelen= strlen(name);
+  if (!address) {
+    free(entry->buffer);
+    entry->buffer= 0;
+    entry->textp= name;
+    entry->textlen= namelen;
+  } else {
+    newlen= entry->textlen + namelen + (bracket ? 0 : 2);
+    newbuf= xmalloc(newlen + 1);
+    sprintf(newbuf, bracket ? "%s%.*s" : "%s[%.*s]", name, entry->textlen, entry->textp);
+    free(entry->buffer);
+    entry->buffer= entry->textp= newbuf;
+    entry->textlen= newlen;
+  }
+}
+
+static void checkadnsqueries(void) {
+  adns_query qu;
+  adns_answer *ans;
+  void *context;
+  struct treething *foundthing;
+  int r;
+
+  for (;;) {
+    qu= 0; context= 0; ans= 0;
+    r= adns_check(ads,&qu,&ans,&context);
+    if (r == ESRCH || r == EAGAIN) break;
+    assert(!r);
+    foundthing= context;
+    foundthing->ans= ans;
+    foundthing->qu= 0;
+  }
+}
+
+static void restartbuf(void) {
+  if (inbuf>0) queueoutstr(addrtextbuf,inbuf);
+  inbuf= 0;
+}
+
+static int comparer(const void *a, const void *b) {
+  return memcmp(a,b,4);
+}
+
+static void procaddr(void) {
+  struct treething *foundthing;
+  void **searchfound;
+  struct outqueuenode *entry;
+  int r;
+  
+  if (!newthing) {
+    newthing= xmalloc(sizeof(struct treething));
+    newthing->qu= 0;
+    newthing->ans= 0;
+  }
+
+  memcpy(newthing->bytes,bytes,4);
+  searchfound= tsearch(newthing,&treeroot,comparer);
+  if (!searchfound) sysfail("tsearch");
+  foundthing= *searchfound;
+
+  if (foundthing == newthing) {
+    newthing= 0;
+    memcpy(&sa.sin_addr,bytes,4);
+    r= adns_submit_reverse(ads, (const struct sockaddr*)&sa,
+			   rrt,0,foundthing,&foundthing->qu);
+    if (r) adnsfail("submit",r);
+  }
+  entry= xmalloc(sizeof(*entry));
+  entry->buffer= xmalloc(inbuf);
+  entry->textp= entry->buffer;
+  memcpy(entry->textp,addrtextbuf,inbuf);
+  entry->textlen= inbuf;
+  entry->addr= foundthing;
+  entry->printbefore= printbefore;
+  LIST_LINK_TAIL(outqueue,entry);
+  outqueuelen++;
+  inbuf= 0;
+  cbyte= -1;
+}
+
+static void startaddr(void) {
+  bytes[cbyte=0]= 0;
+  inbyte= 0;
+}
+
+static void readstdin(void) {
+  char readbuf[512], *p;
+  int r, c, nbyte;
+
+  while ((r= read(0,readbuf,sizeof(readbuf))) <= 0) {
+    if (r == 0) { inputeof= 1; return; }
+    if (r == EAGAIN) return;
+    if (r != EINTR) sysfail("read stdin");
+  }
+  for (p=readbuf; r>0; r--,p++) {
+    c= *p;
+    if (cbyte==-1 && bracket && c=='[') {
+      addrtextbuf[inbuf++]= c;
+      startaddr();
+    } else if (cbyte==-1 && !bracket && !isalnum(c)) {
+      queueoutchar(c);
+      startaddr();
+    } else if (cbyte>=0 && inbyte<3 && c>='0' && c<='9' &&
+	       (nbyte= bytes[cbyte]*10 + (c-'0')) <= 255) {
+      bytes[cbyte]= nbyte;
+      addrtextbuf[inbuf++]= c;
+      inbyte++;
+    } else if (cbyte>=0 && cbyte<3 && inbyte>0 && c=='.') {
+      bytes[++cbyte]= 0;
+      addrtextbuf[inbuf++]= c;
+      inbyte= 0;
+    } else if (cbyte==3 && inbyte>0 && bracket && c==']') {
+      addrtextbuf[inbuf++]= c;
+      procaddr();
+    } else if (cbyte==3 && inbyte>0 && !bracket && !isalnum(c)) {
+      procaddr();
+      queueoutchar(c);
+      startaddr();
+    } else {
+      restartbuf();
+      queueoutchar(c);
+      cbyte= -1;
+      if (!bracket && !isalnum(c)) startaddr();
+    }
+  }
+  if (cbyte==3 && inbyte>0 && !bracket) procaddr();
+}
+
+static void startup(void) {
+  int r;
+
+  if (nonblock(0,1)) sysfail("set stdin to nonblocking mode");
+  if (nonblock(1,1)) sysfail("set stdout to nonblocking mode");
+  memset(&sa,0,sizeof(sa));
+  sa.sin_family= AF_INET;
+  r= adns_init(&ads,0,0);  if (r) adnsfail("init",r);
+  cbyte= -1;
+  inbyte= -1;
+  inbuf= 0;
+  if (!bracket) startaddr();
+}
+
+int main(int argc, const char *const *argv) {
+  int r, maxfd;
+  fd_set readfds, writefds, exceptfds;
+  struct outqueuenode *entry;
+  struct timeval *tv, tvbuf, now;
+
+  parseargs(argv);
+  startup();
+
+  while (!inputeof || outqueue.head) {
+    maxfd= 2;
+    tv= 0;
+    FD_ZERO(&readfds); FD_ZERO(&writefds); FD_ZERO(&exceptfds);
+    if ((entry= outqueue.head) && !outblocked) {
+      if (!entry->addr) {
+	writestdout(entry);
+	continue;
+      }
+      if (entry->addr->ans) {
+	if (entry->addr->ans->nrrs) 
+	  replacetextwithname(entry);
+	entry->addr= 0;
+	continue;
+      }
+      r= gettimeofday(&now,0);  if (r) sysfail("gettimeofday");
+      if (forever) {
+	tv= 0;
+      } else if (!timercmp(&now,&entry->printbefore,<)) {
+	entry->addr= 0;
+	continue;
+      } else {
+	tvbuf.tv_sec= entry->printbefore.tv_sec - now.tv_sec - 1;
+	tvbuf.tv_usec= entry->printbefore.tv_usec - now.tv_usec + 1000000;
+	tvbuf.tv_sec += tvbuf.tv_usec / 1000000;
+	tvbuf.tv_usec %= 1000000;
+	tv= &tvbuf;
+      }
+      adns_beforeselect(ads,&maxfd,&readfds,&writefds,&exceptfds,
+			&tv,&tvbuf,&now);
+    }
+    if (outblocked) FD_SET(1,&writefds);
+    if (!inputeof && outqueuelen<1024) FD_SET(0,&readfds);
+    
+    r= select(maxfd,&readfds,&writefds,&exceptfds,tv);
+    if (r < 0) { if (r == EINTR) continue; else sysfail("select"); }
+
+    r= gettimeofday(&now,0);  if (r) sysfail("gettimeofday");
+    adns_afterselect(ads,maxfd,&readfds,&writefds,&exceptfds,&now);
+    checkadnsqueries();
+
+    if (FD_ISSET(0,&readfds)) {
+      if (!forever) {
+	printbefore= now;
+	timevaladd(&printbefore,timeout);
+      }
+      readstdin();
+    } else if (FD_ISSET(1,&writefds)) {
+      outblocked= 0;
+    }
+  }
+  if (nonblock(0,0)) sysfail("un-nonblock stdin");
+  if (nonblock(1,0)) sysfail("un-nonblock stdout");
+  if (ferror(stdin) || fclose(stdin)) sysfail("read stdin");
+  if (fclose(stdout)) sysfail("close stdout");
+  exit(0);
+}
Index: adns/client/adnstest.c
diff -u adns/client/adnstest.c:1.38 adns/client/adnstest.c:1.39
--- adns/client/adnstest.c:1.38	Sun Oct 10 14:16:24 1999
+++ adns/client/adnstest.c	Tue Nov  2 23:40:14 1999
@@ -41,11 +41,30 @@
 # define OUTPUTSTREAM stdout
 #endif
 
+struct myctx {
+  adns_query qu;
+  int doneyet, found;
+  const char *fdom;
+};
+  
+static struct myctx *mcs;
+static adns_state ads;
+static adns_rrtype *types_a;
+
+static void quitnow(int rc) NONRETURNING;
+static void quitnow(int rc) {
+  free(mcs);
+  free(types_a);
+  if (ads) adns_finish(ads);
+  
+  exit(rc);
+}
+
 #ifndef HAVE_POLL
 #undef poll
 int poll(struct pollfd *ufds, int nfds, int timeout) {
   fputs("poll(2) not supported on this system\n",stderr);
-  exit(5);
+  quitnow(5);
 }
 #define adns_beforepoll(a,b,c,d,e) 0
 #define adns_afterpoll(a,b,c,d) 0
@@ -54,13 +73,13 @@
 static void failure_status(const char *what, adns_status st) NONRETURNING;
 static void failure_status(const char *what, adns_status st) {
   fprintf(stderr,"adns failure: %s: %s\n",what,adns_strerror(st));
-  exit(2);
+  quitnow(2);
 }
 
 static void failure_errno(const char *what, int errnoval) NONRETURNING;
 static void failure_errno(const char *what, int errnoval) {
   fprintf(stderr,"adns failure: %s: errno=%d\n",what,errnoval);
-  exit(2);
+  quitnow(2);
 }
 
 static void usageerr(const char *why) NONRETURNING;
@@ -80,7 +99,7 @@
 	  "              4 usage error\n"
 	  "              5 operation not supported on this system\n",
 	  why);
-  exit(4);
+  quitnow(4);
 }
 
 static const adns_rrtype defaulttypes[]= {
@@ -120,7 +139,7 @@
   if (*ep == ',' && strchr(ep,'/')) {
     ep++;
     while (*ep != '/') {
-      if (--ownflags_l <= 0) { fputs("too many flags\n",stderr); exit(3); }
+      if (--ownflags_l <= 0) { fputs("too many flags\n",stderr); quitnow(3); }
       *ownflags++= *ep++;
     }
   }
@@ -134,15 +153,8 @@
 }
 
 int main(int argc, char *const *argv) {
-  struct myctx {
-    adns_query qu;
-    int doneyet, found;
-    const char *fdom;
-  };
-  
-  adns_state ads;
   adns_query qu;
-  struct myctx *mcs, *mc, *mcw;
+  struct myctx *mc, *mcw;
   void *mcr;
   adns_answer *ans;
   const char *initstring, *rrtn, *fmtn;
@@ -153,7 +165,6 @@
   int r;
   const adns_rrtype *types;
   struct timeval now;
-  adns_rrtype *types_a;
   char ownflags[10];
   char *ep;
   const char *initflags, *owninitflags;
@@ -185,7 +196,7 @@
     for (cp= argv[1]+1, tc=1; (ch= *cp); cp++)
       if (ch==',') tc++;
     types_a= malloc(sizeof(*types_a)*(tc+1));
-    if (!types_a) { perror("malloc types"); exit(3); }
+    if (!types_a) { perror("malloc types"); quitnow(3); }
     for (cp= argv[1]+1, ti=0; ti<tc; ti++) {
       types_a[ti]= strtoul(cp,&cp,10);
       if ((ch= *cp)) {
@@ -193,10 +204,11 @@
 	cp++;
       }
     }
-    *cp++= adns_r_none;
+    types_a[ti]= adns_r_none;
     types= types_a;
     argv++;
   } else {
+    types_a= 0;
     types= defaulttypes;
   }
   
@@ -205,8 +217,8 @@
 
   for (qc=0; fdomlist[qc]; qc++);
   for (tc=0; types[tc] != adns_r_none; tc++);
-  mcs= malloc(sizeof(*mcs)*qc*tc);
-  if (!mcs) { perror("malloc mcs"); exit(3); }
+  mcs= malloc(tc ? sizeof(*mcs)*qc*tc : 1);
+  if (!mcs) { perror("malloc mcs"); quitnow(3); }
 
   if (initstring) {
     r= adns_init_strcfg(&ads,
@@ -293,7 +305,7 @@
     
     fdom_split(mc->fdom,&domain,&qflags,ownflags,sizeof(ownflags));
 
-    if (gettimeofday(&now,0)) { perror("gettimeofday"); exit(3); }
+    if (gettimeofday(&now,0)) { perror("gettimeofday"); quitnow(3); }
       
     ri= adns_rr_info(ans->type, &rrtn,&fmtn,&len, 0,0);
     fprintf(stdout, "%s flags %d type ",domain,qflags);
@@ -321,8 +333,5 @@
     mc->doneyet= 1;
   }
 
-  free(mcs);
-  adns_finish(ads);
-  
-  exit(0);
+  quitnow(0);
 }
Index: adns/client/fanftest.c
diff -u /dev/null adns/client/fanftest.c:1.2
--- /dev/null	Wed Nov 24 17:20:58 1999
+++ adns/client/fanftest.c	Fri Oct 15 17:46:57 1999
@@ -0,0 +1,85 @@
+/*
+ * fanftest.c
+ * - a small test program from Tony Finch
+ */
+/*
+ *  This file is
+ *   Copyright (C) 1999 Tony Finch <dot@dotat.at>
+ *   Copyright (C) 1999 Ian Jackson <ian@davenant.greenend.org.uk>
+ *
+ *  It is part of adns, which is
+ *    Copyright (C) 1997-1999 Ian Jackson <ian@davenant.greenend.org.uk>
+ *    Copyright (C) 1999 Tony Finch <dot@dotat.at>
+ *  
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2, or (at your option)
+ *  any later version.
+ *  
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *  
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software Foundation,
+ *  Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * This version was originally supplied by Tony Finch, but has been
+ * modified by Ian Jackson as it was incorporated into adns.
+ */
+
+static const char * const cvsid =
+	"$Id: fanftest.c,v 1.2 1999/10/15 16:46:57 ian Exp $";
+
+#include <sys/types.h>
+#include <sys/time.h>
+
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <errno.h>
+
+#include "adns.h"
+
+static const char *progname;
+
+static void aargh(const char *msg) {
+  fprintf(stderr, "%s: %s: %s (%d)\n", progname, msg,
+	  strerror(errno) ? strerror(errno) : "Unknown error", errno);
+  exit(1);
+}
+
+int main(int argc, char *argv[]) {
+  adns_state adns;
+  adns_query query;
+  adns_answer *answer;
+
+  progname= strrchr(*argv, '/');
+  if (progname)
+    progname++;
+  else
+    progname= *argv;
+
+  if (argc != 2) {
+    fprintf(stderr, "usage: %s <domain>\n", progname);
+    exit(1);
+  }
+
+  errno= adns_init(&adns, adns_if_debug, 0);
+  if (errno) aargh("adns_init");
+
+  errno= adns_submit(adns, argv[1], adns_r_ptr,
+		     adns_qf_quoteok_cname|adns_qf_cname_loose,
+		     NULL, &query);
+  if (errno) aargh("adns_submit");
+
+  errno= adns_wait(adns, &query, &answer, NULL);
+  if (errno) aargh("adns_init");
+
+  printf("%s\n", answer->status == adns_s_ok ? *answer->rrs.str : "dunno");
+
+  adns_finish(adns);
+
+  return 0;
+}
Index: adns/client/x.gdb
diff -u /dev/null adns/client/x.gdb:1.1
--- /dev/null	Wed Nov 24 17:20:58 1999
+++ adns/client/x.gdb	Sun Nov  7 19:02:20 1999
@@ -0,0 +1,2 @@
+file adnsresfilter_s
+set args <testinput -t2000
Index: adns/dynamic/Makefile.in
diff -u adns/dynamic/Makefile.in:1.8 adns/dynamic/Makefile.in:1.10
--- adns/dynamic/Makefile.in:1.8	Wed Oct 13 02:16:30 1999
+++ adns/dynamic/Makefile.in	Fri Oct 15 18:57:50 1999
@@ -32,9 +32,10 @@
 
 install:
 		$(INSTALL_PROGRAM) $(SHLIBFILE) $(lib_dir)/$(SHLIBFILE)
+		ln -sf $(SHLIBFILE) $(lib_dir)/$(SHLIBSONAME)
 
 uninstall:
-		rm -f $(lib_dir)/$(SHLIBFILE)
+		rm -f $(lib_dir)/$(SHLIBFILE) $(lib_dir)/$(SHLIBSONAME)
 
 $(SHLIBFORLINK):
 		ln -s $(SHLIBSONAME) $(SHLIBFORLINK)
Index: adns/regress/Makefile.in
diff -u adns/regress/Makefile.in:1.11 adns/regress/Makefile.in:1.12
--- adns/regress/Makefile.in:1.11	Sun Oct 10 14:16:24 1999
+++ adns/regress/Makefile.in	Tue Nov  2 23:40:14 1999
@@ -35,6 +35,7 @@
 	gettimeofday select poll		\
 	socket fcntl connect close		\
 	sendto recvfrom read write writev	\
+	malloc realloc free exit		\
 , -D$F=H$F)
 
 HARNLOBJS=	$(addsuffix _d.o, $(basename $(LIBOBJS)))
Index: adns/regress/case-1stservbroken.out
diff -u /dev/null adns/regress/case-1stservbroken.out:1.1
--- /dev/null	Wed Nov 24 17:20:58 1999
+++ adns/regress/case-1stservbroken.out	Sat Oct 16 20:04:06 1999
@@ -0,0 +1,39 @@
+adns debug: using nameserver 172.18.45.2
+adns debug: using nameserver 172.18.45.6
+trunc.test.iwj.relativity.greenend.org.uk flags 0 type 12 PTR(raw) submitted
+adns warning: datagram receive error: Connection refused
+adns debug: TCP connected (NS=172.18.45.2)
+adns warning: TCP connection failed: read: Broken pipe (NS=172.18.45.2)
+adns debug: TCP connected (NS=172.18.45.6)
+trunc.test.iwj.relativity.greenend.org.uk flags 0 type PTR(raw): OK; nrrs=30; cname=$; owner=$; ttl=60
+ long.domain.to.force.truncation.0.test.iwj.relativity.greenend.org.uk
+ long.domain.to.force.truncation.1.test.iwj.relativity.greenend.org.uk
+ long.domain.to.force.truncation.2.test.iwj.relativity.greenend.org.uk
+ long.domain.to.force.truncation.3.test.iwj.relativity.greenend.org.uk
+ long.domain.to.force.truncation.4.test.iwj.relativity.greenend.org.uk
+ long.domain.to.force.truncation.5.test.iwj.relativity.greenend.org.uk
+ long.domain.to.force.truncation.6.test.iwj.relativity.greenend.org.uk
+ long.domain.to.force.truncation.7.test.iwj.relativity.greenend.org.uk
+ long.domain.to.force.truncation.8.test.iwj.relativity.greenend.org.uk
+ long.domain.to.force.truncation.9.test.iwj.relativity.greenend.org.uk
+ long.domain.to.force.truncation.10.test.iwj.relativity.greenend.org.uk
+ long.domain.to.force.truncation.11.test.iwj.relativity.greenend.org.uk
+ long.domain.to.force.truncation.12.test.iwj.relativity.greenend.org.uk
+ long.domain.to.force.truncation.13.test.iwj.relativity.greenend.org.uk
+ long.domain.to.force.truncation.14.test.iwj.relativity.greenend.org.uk
+ long.domain.to.force.truncation.15.test.iwj.relativity.greenend.org.uk
+ long.domain.to.force.truncation.16.test.iwj.relativity.greenend.org.uk
+ long.domain.to.force.truncation.17.test.iwj.relativity.greenend.org.uk
+ long.domain.to.force.truncation.18.test.iwj.relativity.greenend.org.uk
+ long.domain.to.force.truncation.19.test.iwj.relativity.greenend.org.uk
+ long.domain.to.force.truncation.20.test.iwj.relativity.greenend.org.uk
+ long.domain.to.force.truncation.21.test.iwj.relativity.greenend.org.uk
+ long.domain.to.force.truncation.22.test.iwj.relativity.greenend.org.uk
+ long.domain.to.force.truncation.23.test.iwj.relativity.greenend.org.uk
+ long.domain.to.force.truncation.24.test.iwj.relativity.greenend.org.uk
+ long.domain.to.force.truncation.25.test.iwj.relativity.greenend.org.uk
+ long.domain.to.force.truncation.26.test.iwj.relativity.greenend.org.uk
+ long.domain.to.force.truncation.27.test.iwj.relativity.greenend.org.uk
+ long.domain.to.force.truncation.28.test.iwj.relativity.greenend.org.uk
+ long.domain.to.force.truncation.29.test.iwj.relativity.greenend.org.uk
+rc=0
Index: adns/regress/case-1stservbroken.sys
diff -u /dev/null adns/regress/case-1stservbroken.sys:1.2
--- /dev/null	Wed Nov 24 17:20:58 1999
+++ adns/regress/case-1stservbroken.sys	Sat Oct 16 20:43:26 1999
@@ -0,0 +1,180 @@
+1stservbroken
+:12 trunc.test.iwj.relativity.greenend.org.uk
+ start 940102940.701451
+ socket type=SOCK_DGRAM
+ socket=4
+ +0.000612
+ fcntl fd=4 cmd=F_GETFL
+ fcntl=~O_NONBLOCK&...
+ +0.000605
+ fcntl fd=4 cmd=F_SETFL O_NONBLOCK|...
+ fcntl=OK
+ +0.000573
+ sendto fd=4 addr=172.18.45.2:53
+     311f0100 00010000 00000000 05747275 6e630474 65737403 69776a0a 72656c61
+     74697669 74790867 7265656e 656e6403 6f726702 756b0000 0c0001.
+ sendto=59
+ +0.006374
+ select max=5 rfds=[4] wfds=[] efds=[] to=1.993626
+ select=1 rfds=[4] wfds=[] efds=[]
+ +0.001402
+ recvfrom fd=4 buflen=512 *addrlen=16
+ recvfrom=ECONNREFUSED
+ +0.000666
+ select max=5 rfds=[4] wfds=[] efds=[] to=1.991558
+ select=0 rfds=[] wfds=[] efds=[]
+ +2.-02914
+ sendto fd=4 addr=172.18.45.6:53
+     311f0100 00010000 00000000 05747275 6e630474 65737403 69776a0a 72656c61
+     74697669 74790867 7265656e 656e6403 6f726702 756b0000 0c0001.
+ sendto=59
+ +0.002262
+ select max=5 rfds=[4] wfds=[] efds=[] to=1.997738
+ select=1 rfds=[4] wfds=[] efds=[]
+ +0.000973
+ recvfrom fd=4 buflen=512 *addrlen=16
+ recvfrom=OK addr=172.18.45.6:53
+     311f8380 00010008 00000000 05747275 6e630474 65737403 69776a0a 72656c61
+     74697669 74790867 7265656e 656e6403 6f726702 756b0000 0c0001c0 0c000c00
+     01000000 3c004704 6c6f6e67 06646f6d 61696e02 746f0566 6f726365 0a747275
+     6e636174 696f6e01 30047465 73740369 776a0a72 656c6174 69766974 79086772
+     65656e65 6e64036f 72670275 6b00c00c 000c0001 0000003c 0024046c 6f6e6706
+     646f6d61 696e0274 6f05666f 7263650a 7472756e 63617469 6f6e0131 c069c00c
+     000c0001 0000003c 0024046c 6f6e6706 646f6d61 696e0274 6f05666f 7263650a
+     7472756e 63617469 6f6e0132 c069c00c 000c0001 0000003c 0024046c 6f6e6706
+     646f6d61 696e0274 6f05666f 7263650a 7472756e 63617469 6f6e0133 c069c00c
+     000c0001 0000003c 0024046c 6f6e6706 646f6d61 696e0274 6f05666f 7263650a
+     7472756e 63617469 6f6e0134 c069c00c 000c0001 0000003c 0024046c 6f6e6706
+     646f6d61 696e0274 6f05666f 7263650a 7472756e 63617469 6f6e0135 c069c00c
+     000c0001 0000003c 0024046c 6f6e6706 646f6d61 696e0274 6f05666f 7263650a
+     7472756e 63617469 6f6e0136 c069c00c 000c0001 0000003c 0024046c 6f6e6706
+     646f6d61 696e0274 6f05666f 7263650a 7472756e 63617469 6f6e0137 c069.
+ +0.004340
+ socket type=SOCK_STREAM
+ socket=5
+ +0.005126
+ fcntl fd=5 cmd=F_GETFL
+ fcntl=~O_NONBLOCK&...
+ +0.000742
+ fcntl fd=5 cmd=F_SETFL O_NONBLOCK|...
+ fcntl=OK
+ +0.000604
+ connect fd=5 addr=172.18.45.2:53
+ connect=EINPROGRESS
+ +0.000797
+ recvfrom fd=4 buflen=512 *addrlen=16
+ recvfrom=EAGAIN
+ +0.000829
+ select max=6 rfds=[4] wfds=[5] efds=[] to=13.987562
+ select=1 rfds=[] wfds=[5] efds=[]
+ +0.001172
+ read fd=5 buflen=1
+ read=OK
+     .
+ +0.001161
+ write fd=5
+     003b311f 01000001 00000000 00000574 72756e63 04746573 74036977 6a0a7265
+     6c617469 76697479 08677265 656e656e 64036f72 6702756b 00000c00 01.
+ write=61
+ +0.003598
+ select max=6 rfds=[4,5] wfds=[] efds=[5] to=29.981631
+ select=1 rfds=[5] wfds=[] efds=[]
+ +0.001370
+ read fd=5 buflen=2
+ read=EPIPE
+ +0.001699
+ close fd=5
+ close=OK
+ +0.000687
+ socket type=SOCK_STREAM
+ socket=5
+ +0.004866
+ fcntl fd=5 cmd=F_GETFL
+ fcntl=~O_NONBLOCK&...
+ +0.000611
+ fcntl fd=5 cmd=F_SETFL O_NONBLOCK|...
+ fcntl=OK
+ +0.000574
+ connect fd=5 addr=172.18.45.6:53
+ connect=EINPROGRESS
+ +0.001082
+ select max=6 rfds=[4] wfds=[5] efds=[] to=14.000000
+ select=1 rfds=[] wfds=[5] efds=[]
+ +0.001011
+ read fd=5 buflen=1
+ read=EAGAIN
+ +0.000595
+ write fd=5
+     003b311f 01000001 00000000 00000574 72756e63 04746573 74036977 6a0a7265
+     6c617469 76697479 08677265 656e656e 64036f72 6702756b 00000c00 01.
+ write=61
+ +0.005087
+ select max=6 rfds=[4,5] wfds=[] efds=[5] to=29.964049
+ select=1 rfds=[5] wfds=[] efds=[]
+ +0.001295
+ read fd=5 buflen=2
+ read=OK
+     0638.
+ +0.000649
+ read fd=5 buflen=1592
+ read=OK
+     311f8580 0001001e 00010001 05747275 6e630474 65737403 69776a0a 72656c61
+     74697669 74790867 7265656e 656e6403 6f726702 756b0000 0c0001c0 0c000c00
+     01000000 3c004704 6c6f6e67 06646f6d 61696e02 746f0566 6f726365 0a747275
+     6e636174 696f6e01 30047465 73740369 776a0a72 656c6174 69766974 79086772
+     65656e65 6e64036f 72670275 6b00c00c 000c0001 0000003c 0024046c 6f6e6706
+     646f6d61 696e0274 6f05666f 7263650a 7472756e 63617469 6f6e0131 c069c00c
+     000c0001 0000003c 0024046c 6f6e6706 646f6d61 696e0274 6f05666f 7263650a
+     7472756e 63617469 6f6e0132 c069c00c 000c0001 0000003c 0024046c 6f6e6706
+     646f6d61 696e0274 6f05666f 7263650a 7472756e 63617469 6f6e0133 c069c00c
+     000c0001 0000003c 0024046c 6f6e6706 646f6d61 696e0274 6f05666f 7263650a
+     7472756e 63617469 6f6e0134 c069c00c 000c0001 0000003c 0024046c 6f6e6706
+     646f6d61 696e0274 6f05666f 7263650a 7472756e 63617469 6f6e0135 c069c00c
+     000c0001 0000003c 0024046c 6f6e6706 646f6d61 696e0274 6f05666f 7263650a
+     7472756e 63617469 6f6e0136 c069c00c 000c0001 0000003c 0024046c 6f6e6706
+     646f6d61 696e0274 6f05666f 7263650a 7472756e 63617469 6f6e0137 c069c00c
+     000c0001 0000003c 0024046c 6f6e6706 646f6d61 696e0274 6f05666f 7263650a
+     7472756e 63617469 6f6e0138 c069c00c 000c0001 0000003c 0024046c 6f6e6706
+     646f6d61 696e0274 6f05666f 7263650a 7472756e 63617469 6f6e0139 c069c00c
+     000c0001 0000003c 0025046c 6f6e6706 646f6d61 696e0274 6f05666f 7263650a
+     7472756e 63617469 6f6e0231 30c069c0 0c000c00 01000000 3c002504 6c6f6e67
+     06646f6d 61696e02 746f0566 6f726365 0a747275 6e636174 696f6e02 3131c069
+     c00c000c 00010000 003c0025 046c6f6e 6706646f 6d61696e 02746f05 666f7263
+     650a7472 756e6361 74696f6e 023132c0 69c00c00 0c000100 00003c00 25046c6f
+     6e670664 6f6d6169 6e02746f 05666f72 63650a74 72756e63 6174696f 6e023133
+     c069c00c 000c0001 0000003c 0025046c 6f6e6706 646f6d61 696e0274 6f05666f
+     7263650a 7472756e 63617469 6f6e0231 34c069c0 0c000c00 01000000 3c002504
+     6c6f6e67 06646f6d 61696e02 746f0566 6f726365 0a747275 6e636174 696f6e02
+     3135c069 c00c000c 00010000 003c0025 046c6f6e 6706646f 6d61696e 02746f05
+     666f7263 650a7472 756e6361 74696f6e 023136c0 69c00c00 0c000100 00003c00
+     25046c6f 6e670664 6f6d6169 6e02746f 05666f72 63650a74 72756e63 6174696f
+     6e023137 c069c00c 000c0001 0000003c 0025046c 6f6e6706 646f6d61 696e0274
+     6f05666f 7263650a 7472756e 63617469 6f6e0231 38c069c0 0c000c00 01000000
+     3c002504 6c6f6e67 06646f6d 61696e02 746f0566 6f726365 0a747275 6e636174
+     696f6e02 3139c069 c00c000c 00010000 003c0025 046c6f6e 6706646f 6d61696e
+     02746f05 666f7263 650a7472 756e6361 74696f6e 023230c0 69c00c00 0c000100
+     00003c00 25046c6f 6e670664 6f6d6169 6e02746f 05666f72 63650a74 72756e63
+     6174696f 6e023231 c069c00c 000c0001 0000003c 0025046c 6f6e6706 646f6d61
+     696e0274 6f05666f 7263650a 7472756e 63617469 6f6e0232 32c069c0 0c000c00
+     01000000 3c002504 6c6f6e67 06646f6d 61696e02 746f0566 6f726365 0a747275
+     6e636174 696f6e02 3233c069 c00c000c 00010000 003c0025 046c6f6e 6706646f
+     6d61696e 02746f05 666f7263 650a7472 756e6361 74696f6e 023234c0 69c00c00
+     0c000100 00003c00 25046c6f 6e670664 6f6d6169 6e02746f 05666f72 63650a74
+     72756e63 6174696f 6e023235 c069c00c 000c0001 0000003c 0025046c 6f6e6706
+     646f6d61 696e0274 6f05666f 7263650a 7472756e 63617469 6f6e0232 36c069c0
+     0c000c00 01000000 3c002504 6c6f6e67 06646f6d 61696e02 746f0566 6f726365
+     0a747275 6e636174 696f6e02 3237c069 c00c000c 00010000 003c0025 046c6f6e
+     6706646f 6d61696e 02746f05 666f7263 650a7472 756e6361 74696f6e 023238c0
+     69c00c00 0c000100 00003c00 25046c6f 6e670664 6f6d6169 6e02746f 05666f72
+     63650a74 72756e63 6174696f 6e023239 c069c069 00020001 0000003c 0006036e
+     7330c072 036e7330 c0720001 00010001 51800004 ac122d06.
+ +0.009426
+ read fd=5 buflen=1594
+ read=EAGAIN
+ +0.033394
+ close fd=4
+ close=OK
+ +0.054384
+ close fd=5
+ close=OK
+ +0.000977
Index: adns/regress/case-1stservtotcp.out
diff -u /dev/null adns/regress/case-1stservtotcp.out:1.1
--- /dev/null	Wed Nov 24 17:20:58 1999
+++ adns/regress/case-1stservtotcp.out	Sat Oct 16 20:04:06 1999
@@ -0,0 +1,37 @@
+adns debug: using nameserver 10.0.0.1
+adns debug: using nameserver 172.18.45.6
+trunc.test.iwj.relativity.greenend.org.uk flags 0 type 12 PTR(raw) submitted
+adns warning: TCP connection failed: unable to make connection: timed out (NS=10.0.0.1)
+adns debug: TCP connected (NS=172.18.45.6)
+trunc.test.iwj.relativity.greenend.org.uk flags 0 type PTR(raw): OK; nrrs=30; cname=$; owner=$; ttl=59
+ long.domain.to.force.truncation.0.test.iwj.relativity.greenend.org.uk
+ long.domain.to.force.truncation.1.test.iwj.relativity.greenend.org.uk
+ long.domain.to.force.truncation.2.test.iwj.relativity.greenend.org.uk
+ long.domain.to.force.truncation.3.test.iwj.relativity.greenend.org.uk
+ long.domain.to.force.truncation.4.test.iwj.relativity.greenend.org.uk
+ long.domain.to.force.truncation.5.test.iwj.relativity.greenend.org.uk
+ long.domain.to.force.truncation.6.test.iwj.relativity.greenend.org.uk
+ long.domain.to.force.truncation.7.test.iwj.relativity.greenend.org.uk
+ long.domain.to.force.truncation.8.test.iwj.relativity.greenend.org.uk
+ long.domain.to.force.truncation.9.test.iwj.relativity.greenend.org.uk
+ long.domain.to.force.truncation.10.test.iwj.relativity.greenend.org.uk
+ long.domain.to.force.truncation.11.test.iwj.relativity.greenend.org.uk
+ long.domain.to.force.truncation.12.test.iwj.relativity.greenend.org.uk
+ long.domain.to.force.truncation.13.test.iwj.relativity.greenend.org.uk
+ long.domain.to.force.truncation.14.test.iwj.relativity.greenend.org.uk
+ long.domain.to.force.truncation.15.test.iwj.relativity.greenend.org.uk
+ long.domain.to.force.truncation.16.test.iwj.relativity.greenend.org.uk
+ long.domain.to.force.truncation.17.test.iwj.relativity.greenend.org.uk
+ long.domain.to.force.truncation.18.test.iwj.relativity.greenend.org.uk
+ long.domain.to.force.truncation.19.test.iwj.relativity.greenend.org.uk
+ long.domain.to.force.truncation.20.test.iwj.relativity.greenend.org.uk
+ long.domain.to.force.truncation.21.test.iwj.relativity.greenend.org.uk
+ long.domain.to.force.truncation.22.test.iwj.relativity.greenend.org.uk
+ long.domain.to.force.truncation.23.test.iwj.relativity.greenend.org.uk
+ long.domain.to.force.truncation.24.test.iwj.relativity.greenend.org.uk
+ long.domain.to.force.truncation.25.test.iwj.relativity.greenend.org.uk
+ long.domain.to.force.truncation.26.test.iwj.relativity.greenend.org.uk
+ long.domain.to.force.truncation.27.test.iwj.relativity.greenend.org.uk
+ long.domain.to.force.truncation.28.test.iwj.relativity.greenend.org.uk
+ long.domain.to.force.truncation.29.test.iwj.relativity.greenend.org.uk
+rc=0
Index: adns/regress/case-1stservtotcp.sys
diff -u /dev/null adns/regress/case-1stservtotcp.sys:1.1
--- /dev/null	Wed Nov 24 17:20:58 1999
+++ adns/regress/case-1stservtotcp.sys	Sat Oct 16 20:04:06 1999
@@ -0,0 +1,159 @@
+1stservto
+:12 trunc.test.iwj.relativity.greenend.org.uk
+ start 940100259.965940
+ socket type=SOCK_DGRAM
+ socket=4
+ +0.000698
+ fcntl fd=4 cmd=F_GETFL
+ fcntl=~O_NONBLOCK&...
+ +0.000611
+ fcntl fd=4 cmd=F_SETFL O_NONBLOCK|...
+ fcntl=OK
+ +0.000582
+ sendto fd=4 addr=10.0.0.1:53
+     311f0100 00010000 00000000 05747275 6e630474 65737403 69776a0a 72656c61
+     74697669 74790867 7265656e 656e6403 6f726702 756b0000 0c0001.
+ sendto=59
+ +0.006634
+ select max=5 rfds=[4] wfds=[] efds=[] to=1.993366
+ select=0 rfds=[] wfds=[] efds=[]
+ +2.-05507
+ sendto fd=4 addr=172.18.45.6:53
+     311f0100 00010000 00000000 05747275 6e630474 65737403 69776a0a 72656c61
+     74697669 74790867 7265656e 656e6403 6f726702 756b0000 0c0001.
+ sendto=59
+ +0.002310
+ select max=5 rfds=[4] wfds=[] efds=[] to=1.997690
+ select=1 rfds=[4] wfds=[] efds=[]
+ +0.000996
+ recvfrom fd=4 buflen=512 *addrlen=16
+ recvfrom=OK addr=172.18.45.6:53
+     311f8380 00010008 00000000 05747275 6e630474 65737403 69776a0a 72656c61
+     74697669 74790867 7265656e 656e6403 6f726702 756b0000 0c0001c0 0c000c00
+     01000000 3c004704 6c6f6e67 06646f6d 61696e02 746f0566 6f726365 0a747275
+     6e636174 696f6e01 30047465 73740369 776a0a72 656c6174 69766974 79086772
+     65656e65 6e64036f 72670275 6b00c00c 000c0001 0000003c 0024046c 6f6e6706
+     646f6d61 696e0274 6f05666f 7263650a 7472756e 63617469 6f6e0131 c069c00c
+     000c0001 0000003c 0024046c 6f6e6706 646f6d61 696e0274 6f05666f 7263650a
+     7472756e 63617469 6f6e0132 c069c00c 000c0001 0000003c 0024046c 6f6e6706
+     646f6d61 696e0274 6f05666f 7263650a 7472756e 63617469 6f6e0133 c069c00c
+     000c0001 0000003c 0024046c 6f6e6706 646f6d61 696e0274 6f05666f 7263650a
+     7472756e 63617469 6f6e0134 c069c00c 000c0001 0000003c 0024046c 6f6e6706
+     646f6d61 696e0274 6f05666f 7263650a 7472756e 63617469 6f6e0135 c069c00c
+     000c0001 0000003c 0024046c 6f6e6706 646f6d61 696e0274 6f05666f 7263650a
+     7472756e 63617469 6f6e0136 c069c00c 000c0001 0000003c 0024046c 6f6e6706
+     646f6d61 696e0274 6f05666f 7263650a 7472756e 63617469 6f6e0137 c069.
+ +0.004379
+ socket type=SOCK_STREAM
+ socket=5
+ +0.009970
+ fcntl fd=5 cmd=F_GETFL
+ fcntl=~O_NONBLOCK&...
+ +0.000612
+ fcntl fd=5 cmd=F_SETFL O_NONBLOCK|...
+ fcntl=OK
+ +0.000602
+ connect fd=5 addr=10.0.0.1:53
+ connect=EINPROGRESS
+ +0.000850
+ recvfrom fd=4 buflen=512 *addrlen=16
+ recvfrom=EAGAIN
+ +0.000646
+ select max=6 rfds=[4] wfds=[5] efds=[] to=13.982941
+ select=0 rfds=[] wfds=[] efds=[]
+ +14.-10600
+ close fd=5
+ close=OK
+ +0.000750
+ socket type=SOCK_STREAM
+ socket=5
+ +0.004957
+ fcntl fd=5 cmd=F_GETFL
+ fcntl=~O_NONBLOCK&...
+ +0.000593
+ fcntl fd=5 cmd=F_SETFL O_NONBLOCK|...
+ fcntl=OK
+ +0.000582
+ connect fd=5 addr=172.18.45.6:53
+ connect=EINPROGRESS
+ +0.001140
+ select max=6 rfds=[4] wfds=[5] efds=[] to=13.991978
+ select=1 rfds=[] wfds=[5] efds=[]
+ +0.001038
+ read fd=5 buflen=1
+ read=EAGAIN
+ +0.001203
+ write fd=5
+     003b311f 01000001 00000000 00000574 72756e63 04746573 74036977 6a0a7265
+     6c617469 76697479 08677265 656e656e 64036f72 6702756b 00000c00 01.
+ write=61
+ +0.007301
+ select max=6 rfds=[4,5] wfds=[] efds=[5] to=15.975977
+ select=1 rfds=[5] wfds=[] efds=[]
+ +0.001431
+ read fd=5 buflen=2
+ read=OK
+     0638.
+ +0.001841
+ read fd=5 buflen=1592
+ read=OK
+     311f8580 0001001e 00010001 05747275 6e630474 65737403 69776a0a 72656c61
+     74697669 74790867 7265656e 656e6403 6f726702 756b0000 0c0001c0 0c000c00
+     01000000 3c004704 6c6f6e67 06646f6d 61696e02 746f0566 6f726365 0a747275
+     6e636174 696f6e01 30047465 73740369 776a0a72 656c6174 69766974 79086772
+     65656e65 6e64036f 72670275 6b00c00c 000c0001 0000003c 0024046c 6f6e6706
+     646f6d61 696e0274 6f05666f 7263650a 7472756e 63617469 6f6e0131 c069c00c
+     000c0001 0000003c 0024046c 6f6e6706 646f6d61 696e0274 6f05666f 7263650a
+     7472756e 63617469 6f6e0132 c069c00c 000c0001 0000003c 0024046c 6f6e6706
+     646f6d61 696e0274 6f05666f 7263650a 7472756e 63617469 6f6e0133 c069c00c
+     000c0001 0000003c 0024046c 6f6e6706 646f6d61 696e0274 6f05666f 7263650a
+     7472756e 63617469 6f6e0134 c069c00c 000c0001 0000003c 0024046c 6f6e6706
+     646f6d61 696e0274 6f05666f 7263650a 7472756e 63617469 6f6e0135 c069c00c
+     000c0001 0000003c 0024046c 6f6e6706 646f6d61 696e0274 6f05666f 7263650a
+     7472756e 63617469 6f6e0136 c069c00c 000c0001 0000003c 0024046c 6f6e6706
+     646f6d61 696e0274 6f05666f 7263650a 7472756e 63617469 6f6e0137 c069c00c
+     000c0001 0000003c 0024046c 6f6e6706 646f6d61 696e0274 6f05666f 7263650a
+     7472756e 63617469 6f6e0138 c069c00c 000c0001 0000003c 0024046c 6f6e6706
+     646f6d61 696e0274 6f05666f 7263650a 7472756e 63617469 6f6e0139 c069c00c
+     000c0001 0000003c 0025046c 6f6e6706 646f6d61 696e0274 6f05666f 7263650a
+     7472756e 63617469 6f6e0231 30c069c0 0c000c00 01000000 3c002504 6c6f6e67
+     06646f6d 61696e02 746f0566 6f726365 0a747275 6e636174 696f6e02 3131c069
+     c00c000c 00010000 003c0025 046c6f6e 6706646f 6d61696e 02746f05 666f7263
+     650a7472 756e6361 74696f6e 023132c0 69c00c00 0c000100 00003c00 25046c6f
+     6e670664 6f6d6169 6e02746f 05666f72 63650a74 72756e63 6174696f 6e023133
+     c069c00c 000c0001 0000003c 0025046c 6f6e6706 646f6d61 696e0274 6f05666f
+     7263650a 7472756e 63617469 6f6e0231 34c069c0 0c000c00 01000000 3c002504
+     6c6f6e67 06646f6d 61696e02 746f0566 6f726365 0a747275 6e636174 696f6e02
+     3135c069 c00c000c 00010000 003c0025 046c6f6e 6706646f 6d61696e 02746f05
+     666f7263 650a7472 756e6361 74696f6e 023136c0 69c00c00 0c000100 00003c00
+     25046c6f 6e670664 6f6d6169 6e02746f 05666f72 63650a74 72756e63 6174696f
+     6e023137 c069c00c 000c0001 0000003c 0025046c 6f6e6706 646f6d61 696e0274
+     6f05666f 7263650a 7472756e 63617469 6f6e0231 38c069c0 0c000c00 01000000
+     3c002504 6c6f6e67 06646f6d 61696e02 746f0566 6f726365 0a747275 6e636174
+     696f6e02 3139c069 c00c000c 00010000 003c0025 046c6f6e 6706646f 6d61696e
+     02746f05 666f7263 650a7472 756e6361 74696f6e 023230c0 69c00c00 0c000100
+     00003c00 25046c6f 6e670664 6f6d6169 6e02746f 05666f72 63650a74 72756e63
+     6174696f 6e023231 c069c00c 000c0001 0000003c 0025046c 6f6e6706 646f6d61
+     696e0274 6f05666f 7263650a 7472756e 63617469 6f6e0232 32c069c0 0c000c00
+     01000000 3c002504 6c6f6e67 06646f6d 61696e02 746f0566 6f726365 0a747275
+     6e636174 696f6e02 3233c069 c00c000c 00010000 003c0025 046c6f6e 6706646f
+     6d61696e 02746f05 666f7263 650a7472 756e6361 74696f6e 023234c0 69c00c00
+     0c000100 00003c00 25046c6f 6e670664 6f6d6169 6e02746f 05666f72 63650a74
+     72756e63 6174696f 6e023235 c069c00c 000c0001 0000003c 0025046c 6f6e6706
+     646f6d61 696e0274 6f05666f 7263650a 7472756e 63617469 6f6e0232 36c069c0
+     0c000c00 01000000 3c002504 6c6f6e67 06646f6d 61696e02 746f0566 6f726365
+     0a747275 6e636174 696f6e02 3237c069 c00c000c 00010000 003c0025 046c6f6e
+     6706646f 6d61696e 02746f05 666f7263 650a7472 756e6361 74696f6e 023238c0
+     69c00c00 0c000100 00003c00 25046c6f 6e670664 6f6d6169 6e02746f 05666f72
+     63650a74 72756e63 6174696f 6e023239 c069c069 00020001 0000003c 0006036e
+     7330c072 036e7330 c0720001 00010001 51800004 ac122d06.
+ +1.-990207
+ read fd=5 buflen=1594
+ read=EAGAIN
+ +0.040526
+ close fd=4
+ close=OK
+ +0.065240
+ close fd=5
+ close=OK
+ +0.000982
Index: adns/regress/case-2ndservok.out
diff -u /dev/null adns/regress/case-2ndservok.out:1.1
--- /dev/null	Wed Nov 24 17:20:58 1999
+++ adns/regress/case-2ndservok.out	Sat Oct 16 20:04:06 1999
@@ -0,0 +1,6 @@
+adns debug: using nameserver 172.18.45.36
+adns debug: using nameserver 172.18.45.6
+davenant.relativity.greenend.org.uk flags 0 type 1 A(-) submitted
+davenant.relativity.greenend.org.uk flags 0 type A(-): OK; nrrs=1; cname=$; owner=$; ttl=86400
+ 172.18.45.6
+rc=0
Index: adns/regress/case-2ndservok.sys
diff -u /dev/null adns/regress/case-2ndservok.sys:1.1
--- /dev/null	Wed Nov 24 17:20:58 1999
+++ adns/regress/case-2ndservok.sys	Sat Oct 16 20:04:06 1999
@@ -0,0 +1,47 @@
+2ndserver
+:1 davenant.relativity.greenend.org.uk
+ start 940100095.012145
+ socket type=SOCK_DGRAM
+ socket=4
+ +0.000173
+ fcntl fd=4 cmd=F_GETFL
+ fcntl=~O_NONBLOCK&...
+ +0.000053
+ fcntl fd=4 cmd=F_SETFL O_NONBLOCK|...
+ fcntl=OK
+ +0.000042
+ sendto fd=4 addr=172.18.45.36:53
+     311f0100 00010000 00000000 08646176 656e616e 740a7265 6c617469 76697479
+     08677265 656e656e 64036f72 6702756b 00000100 01.
+ sendto=53
+ +0.001041
+ select max=5 rfds=[4] wfds=[] efds=[] to=1.998959
+ select=0 rfds=[] wfds=[] efds=[]
+ +2.-04931
+ select max=5 rfds=[4] wfds=[] efds=[] to=0.003890
+ select=0 rfds=[] wfds=[] efds=[]
+ +0.009910
+ sendto fd=4 addr=172.18.45.6:53
+     311f0100 00010000 00000000 08646176 656e616e 740a7265 6c617469 76697479
+     08677265 656e656e 64036f72 6702756b 00000100 01.
+ sendto=53
+ +0.000863
+ select max=5 rfds=[4] wfds=[] efds=[] to=1.999137
+ select=1 rfds=[4] wfds=[] efds=[]
+ +0.000126
+ recvfrom fd=4 buflen=512 *addrlen=16
+ recvfrom=OK addr=172.18.45.6:53
+     311f8580 00010001 00030003 08646176 656e616e 740a7265 6c617469 76697479
+     08677265 656e656e 64036f72 6702756b 00000100 01c00c00 01000100 01518000
+     04ac122d 060a7265 6c617469 76697479 08677265 656e656e 64036f72 6702756b
+     00000200 01000151 80000603 6e7330c0 45c04500 02000100 01518000 06036e73
+     31c045c0 45000200 01000151 80000603 6e7332c0 45c06b00 01000100 01518000
+     04ac122d 06c07d00 01000100 01518000 04ac122d 41c08f00 01000100 01518000
+     04ac122d 01.
+ +0.001026
+ recvfrom fd=4 buflen=512 *addrlen=16
+ recvfrom=EAGAIN
+ +0.000423
+ close fd=4
+ close=OK
+ +0.000435
Index: adns/regress/case-2ndservtcp.out
diff -u /dev/null adns/regress/case-2ndservtcp.out:1.1
--- /dev/null	Wed Nov 24 17:20:58 1999
+++ adns/regress/case-2ndservtcp.out	Sat Oct 16 20:04:06 1999
@@ -0,0 +1,37 @@
+adns debug: using nameserver 172.18.45.36
+adns debug: using nameserver 172.18.45.6
+trunc.test.iwj.relativity.greenend.org.uk flags 0 type 12 PTR(raw) submitted
+adns warning: TCP connection failed: connect/read: No route to host (NS=172.18.45.36)
+adns debug: TCP connected (NS=172.18.45.6)
+trunc.test.iwj.relativity.greenend.org.uk flags 0 type PTR(raw): OK; nrrs=30; cname=$; owner=$; ttl=60
+ long.domain.to.force.truncation.0.test.iwj.relativity.greenend.org.uk
+ long.domain.to.force.truncation.1.test.iwj.relativity.greenend.org.uk
+ long.domain.to.force.truncation.2.test.iwj.relativity.greenend.org.uk
+ long.domain.to.force.truncation.3.test.iwj.relativity.greenend.org.uk
+ long.domain.to.force.truncation.4.test.iwj.relativity.greenend.org.uk
+ long.domain.to.force.truncation.5.test.iwj.relativity.greenend.org.uk
+ long.domain.to.force.truncation.6.test.iwj.relativity.greenend.org.uk
+ long.domain.to.force.truncation.7.test.iwj.relativity.greenend.org.uk
+ long.domain.to.force.truncation.8.test.iwj.relativity.greenend.org.uk
+ long.domain.to.force.truncation.9.test.iwj.relativity.greenend.org.uk
+ long.domain.to.force.truncation.10.test.iwj.relativity.greenend.org.uk
+ long.domain.to.force.truncation.11.test.iwj.relativity.greenend.org.uk
+ long.domain.to.force.truncation.12.test.iwj.relativity.greenend.org.uk
+ long.domain.to.force.truncation.13.test.iwj.relativity.greenend.org.uk
+ long.domain.to.force.truncation.14.test.iwj.relativity.greenend.org.uk
+ long.domain.to.force.truncation.15.test.iwj.relativity.greenend.org.uk
+ long.domain.to.force.truncation.16.test.iwj.relativity.greenend.org.uk
+ long.domain.to.force.truncation.17.test.iwj.relativity.greenend.org.uk
+ long.domain.to.force.truncation.18.test.iwj.relativity.greenend.org.uk
+ long.domain.to.force.truncation.19.test.iwj.relativity.greenend.org.uk
+ long.domain.to.force.truncation.20.test.iwj.relativity.greenend.org.uk
+ long.domain.to.force.truncation.21.test.iwj.relativity.greenend.org.uk
+ long.domain.to.force.truncation.22.test.iwj.relativity.greenend.org.uk
+ long.domain.to.force.truncation.23.test.iwj.relativity.greenend.org.uk
+ long.domain.to.force.truncation.24.test.iwj.relativity.greenend.org.uk
+ long.domain.to.force.truncation.25.test.iwj.relativity.greenend.org.uk
+ long.domain.to.force.truncation.26.test.iwj.relativity.greenend.org.uk
+ long.domain.to.force.truncation.27.test.iwj.relativity.greenend.org.uk
+ long.domain.to.force.truncation.28.test.iwj.relativity.greenend.org.uk
+ long.domain.to.force.truncation.29.test.iwj.relativity.greenend.org.uk
+rc=0
Index: adns/regress/case-2ndservtcp.sys
diff -u /dev/null adns/regress/case-2ndservtcp.sys:1.1
--- /dev/null	Wed Nov 24 17:20:58 1999
+++ adns/regress/case-2ndservtcp.sys	Sat Oct 16 20:04:06 1999
@@ -0,0 +1,165 @@
+2ndserver
+:12 trunc.test.iwj.relativity.greenend.org.uk
+ start 940100083.268555
+ socket type=SOCK_DGRAM
+ socket=4
+ +0.000169
+ fcntl fd=4 cmd=F_GETFL
+ fcntl=~O_NONBLOCK&...
+ +0.000053
+ fcntl fd=4 cmd=F_SETFL O_NONBLOCK|...
+ fcntl=OK
+ +0.000040
+ sendto fd=4 addr=172.18.45.36:53
+     311f0100 00010000 00000000 05747275 6e630474 65737403 69776a0a 72656c61
+     74697669 74790867 7265656e 656e6403 6f726702 756b0000 0c0001.
+ sendto=59
+ +0.001167
+ select max=5 rfds=[4] wfds=[] efds=[] to=1.998833
+ select=0 rfds=[] wfds=[] efds=[]
+ +2.-01463
+ select max=5 rfds=[4] wfds=[] efds=[] to=0.000296
+ select=0 rfds=[] wfds=[] efds=[]
+ +0.009912
+ sendto fd=4 addr=172.18.45.6:53
+     311f0100 00010000 00000000 05747275 6e630474 65737403 69776a0a 72656c61
+     74697669 74790867 7265656e 656e6403 6f726702 756b0000 0c0001.
+ sendto=59
+ +0.001357
+ select max=5 rfds=[4] wfds=[] efds=[] to=1.998643
+ select=1 rfds=[4] wfds=[] efds=[]
+ +0.000126
+ recvfrom fd=4 buflen=512 *addrlen=16
+ recvfrom=OK addr=172.18.45.6:53
+     311f8380 00010008 00000000 05747275 6e630474 65737403 69776a0a 72656c61
+     74697669 74790867 7265656e 656e6403 6f726702 756b0000 0c0001c0 0c000c00
+     01000000 3c004704 6c6f6e67 06646f6d 61696e02 746f0566 6f726365 0a747275
+     6e636174 696f6e01 30047465 73740369 776a0a72 656c6174 69766974 79086772
+     65656e65 6e64036f 72670275 6b00c00c 000c0001 0000003c 0024046c 6f6e6706
+     646f6d61 696e0274 6f05666f 7263650a 7472756e 63617469 6f6e0131 c069c00c
+     000c0001 0000003c 0024046c 6f6e6706 646f6d61 696e0274 6f05666f 7263650a
+     7472756e 63617469 6f6e0132 c069c00c 000c0001 0000003c 0024046c 6f6e6706
+     646f6d61 696e0274 6f05666f 7263650a 7472756e 63617469 6f6e0133 c069c00c
+     000c0001 0000003c 0024046c 6f6e6706 646f6d61 696e0274 6f05666f 7263650a
+     7472756e 63617469 6f6e0134 c069c00c 000c0001 0000003c 0024046c 6f6e6706
+     646f6d61 696e0274 6f05666f 7263650a 7472756e 63617469 6f6e0135 c069c00c
+     000c0001 0000003c 0024046c 6f6e6706 646f6d61 696e0274 6f05666f 7263650a
+     7472756e 63617469 6f6e0136 c069c00c 000c0001 0000003c 0024046c 6f6e6706
+     646f6d61 696e0274 6f05666f 7263650a 7472756e 63617469 6f6e0137 c069.
+ +0.002022
+ socket type=SOCK_STREAM
+ socket=5
+ +0.000905
+ fcntl fd=5 cmd=F_GETFL
+ fcntl=~O_NONBLOCK&...
+ +0.000041
+ fcntl fd=5 cmd=F_SETFL O_NONBLOCK|...
+ fcntl=OK
+ +0.000038
+ connect fd=5 addr=172.18.45.36:53
+ connect=EINPROGRESS
+ +0.000162
+ recvfrom fd=4 buflen=512 *addrlen=16
+ recvfrom=EAGAIN
+ +0.000062
+ select max=6 rfds=[4] wfds=[5] efds=[] to=13.996770
+ select=1 rfds=[] wfds=[5] efds=[]
+ +1.-14443
+ read fd=5 buflen=1
+ read=EHOSTUNREACH
+ +0.000193
+ close fd=5
+ close=OK
+ +0.000146
+ socket type=SOCK_STREAM
+ socket=5
+ +0.000678
+ fcntl fd=5 cmd=F_GETFL
+ fcntl=~O_NONBLOCK&...
+ +0.000042
+ fcntl fd=5 cmd=F_SETFL O_NONBLOCK|...
+ fcntl=OK
+ +0.000039
+ connect fd=5 addr=172.18.45.6:53
+ connect=EINPROGRESS
+ +0.000455
+ select max=6 rfds=[4] wfds=[5] efds=[] to=14.000000
+ select=1 rfds=[] wfds=[5] efds=[]
+ +0.000135
+ read fd=5 buflen=1
+ read=EAGAIN
+ +0.000062
+ write fd=5
+     003b311f 01000001 00000000 00000574 72756e63 04746573 74036977 6a0a7265
+     6c617469 76697479 08677265 656e656e 64036f72 6702756b 00000c00 01.
+ write=61
+ +0.004082
+ select max=6 rfds=[4,5] wfds=[] efds=[5] to=29.005381
+ select=1 rfds=[5] wfds=[] efds=[]
+ +0.000149
+ read fd=5 buflen=2
+ read=OK
+     0638.
+ +0.000210
+ read fd=5 buflen=1592
+ read=OK
+     311f8580 0001001e 00010001 05747275 6e630474 65737403 69776a0a 72656c61
+     74697669 74790867 7265656e 656e6403 6f726702 756b0000 0c0001c0 0c000c00
+     01000000 3c004704 6c6f6e67 06646f6d 61696e02 746f0566 6f726365 0a747275
+     6e636174 696f6e01 30047465 73740369 776a0a72 656c6174 69766974 79086772
+     65656e65 6e64036f 72670275 6b00c00c 000c0001 0000003c 0024046c 6f6e6706
+     646f6d61 696e0274 6f05666f 7263650a 7472756e 63617469 6f6e0131 c069c00c
+     000c0001 0000003c 0024046c 6f6e6706 646f6d61 696e0274 6f05666f 7263650a
+     7472756e 63617469 6f6e0132 c069c00c 000c0001 0000003c 0024046c 6f6e6706
+     646f6d61 696e0274 6f05666f 7263650a 7472756e 63617469 6f6e0133 c069c00c
+     000c0001 0000003c 0024046c 6f6e6706 646f6d61 696e0274 6f05666f 7263650a
+     7472756e 63617469 6f6e0134 c069c00c 000c0001 0000003c 0024046c 6f6e6706
+     646f6d61 696e0274 6f05666f 7263650a 7472756e 63617469 6f6e0135 c069c00c
+     000c0001 0000003c 0024046c 6f6e6706 646f6d61 696e0274 6f05666f 7263650a
+     7472756e 63617469 6f6e0136 c069c00c 000c0001 0000003c 0024046c 6f6e6706
+     646f6d61 696e0274 6f05666f 7263650a 7472756e 63617469 6f6e0137 c069c00c
+     000c0001 0000003c 0024046c 6f6e6706 646f6d61 696e0274 6f05666f 7263650a
+     7472756e 63617469 6f6e0138 c069c00c 000c0001 0000003c 0024046c 6f6e6706
+     646f6d61 696e0274 6f05666f 7263650a 7472756e 63617469 6f6e0139 c069c00c
+     000c0001 0000003c 0025046c 6f6e6706 646f6d61 696e0274 6f05666f 7263650a
+     7472756e 63617469 6f6e0231 30c069c0 0c000c00 01000000 3c002504 6c6f6e67
+     06646f6d 61696e02 746f0566 6f726365 0a747275 6e636174 696f6e02 3131c069
+     c00c000c 00010000 003c0025 046c6f6e 6706646f 6d61696e 02746f05 666f7263
+     650a7472 756e6361 74696f6e 023132c0 69c00c00 0c000100 00003c00 25046c6f
+     6e670664 6f6d6169 6e02746f 05666f72 63650a74 72756e63 6174696f 6e023133
+     c069c00c 000c0001 0000003c 0025046c 6f6e6706 646f6d61 696e0274 6f05666f
+     7263650a 7472756e 63617469 6f6e0231 34c069c0 0c000c00 01000000 3c002504
+     6c6f6e67 06646f6d 61696e02 746f0566 6f726365 0a747275 6e636174 696f6e02
+     3135c069 c00c000c 00010000 003c0025 046c6f6e 6706646f 6d61696e 02746f05
+     666f7263 650a7472 756e6361 74696f6e 023136c0 69c00c00 0c000100 00003c00
+     25046c6f 6e670664 6f6d6169 6e02746f 05666f72 63650a74 72756e63 6174696f
+     6e023137 c069c00c 000c0001 0000003c 0025046c 6f6e6706 646f6d61 696e0274
+     6f05666f 7263650a 7472756e 63617469 6f6e0231 38c069c0 0c000c00 01000000
+     3c002504 6c6f6e67 06646f6d 61696e02 746f0566 6f726365 0a747275 6e636174
+     696f6e02 3139c069 c00c000c 00010000 003c0025 046c6f6e 6706646f 6d61696e
+     02746f05 666f7263 650a7472 756e6361 74696f6e 023230c0 69c00c00 0c000100
+     00003c00 25046c6f 6e670664 6f6d6169 6e02746f 05666f72 63650a74 72756e63
+     6174696f 6e023231 c069c00c 000c0001 0000003c 0025046c 6f6e6706 646f6d61
+     696e0274 6f05666f 7263650a 7472756e 63617469 6f6e0232 32c069c0 0c000c00
+     01000000 3c002504 6c6f6e67 06646f6d 61696e02 746f0566 6f726365 0a747275
+     6e636174 696f6e02 3233c069 c00c000c 00010000 003c0025 046c6f6e 6706646f
+     6d61696e 02746f05 666f7263 650a7472 756e6361 74696f6e 023234c0 69c00c00
+     0c000100 00003c00 25046c6f 6e670664 6f6d6169 6e02746f 05666f72 63650a74
+     72756e63 6174696f 6e023235 c069c00c 000c0001 0000003c 0025046c 6f6e6706
+     646f6d61 696e0274 6f05666f 7263650a 7472756e 63617469 6f6e0232 36c069c0
+     0c000c00 01000000 3c002504 6c6f6e67 06646f6d 61696e02 746f0566 6f726365
+     0a747275 6e636174 696f6e02 3237c069 c00c000c 00010000 003c0025 046c6f6e
+     6706646f 6d61696e 02746f05 666f7263 650a7472 756e6361 74696f6e 023238c0
+     69c00c00 0c000100 00003c00 25046c6f 6e670664 6f6d6169 6e02746f 05666f72
+     63650a74 72756e63 6174696f 6e023239 c069c069 00020001 0000003c 0006036e
+     7330c072 036e7330 c0720001 00010001 51800004 ac122d06.
+ +0.006071
+ read fd=5 buflen=1594
+ read=EAGAIN
+ +0.005347
+ close fd=4
+ close=OK
+ +0.004675
+ close fd=5
+ close=OK
+ +0.000433
Index: adns/regress/case-flags10.sys
diff -u adns/regress/case-flags10.sys:1.1 adns/regress/case-flags10.sys:1.2
--- adns/regress/case-flags10.sys:1.1	Thu Jun 17 01:54:01 1999
+++ adns/regress/case-flags10.sys	Tue Nov  2 23:40:14 1999
@@ -10,3 +10,6 @@
  fcntl fd=4 cmd=F_SETFL O_NONBLOCK|...
  fcntl=OK
  +0.000061
+ close fd=4
+ close=OK
+ +0.000001
Index: adns/regress/case-manyptrwrongrem.sys
diff -u adns/regress/case-manyptrwrongrem.sys:1.1 adns/regress/case-manyptrwrongrem.sys:1.2
--- adns/regress/case-manyptrwrongrem.sys:1.1	Thu Jul 29 23:21:51 1999
+++ adns/regress/case-manyptrwrongrem.sys	Sat Oct 16 20:04:06 1999
@@ -316,7 +316,7 @@
  recvfrom fd=4 buflen=512 *addrlen=16
  recvfrom=EAGAIN
  +0.000373
- select max=6 rfds=[4] wfds=[5] efds=[] to=29.539402
+ select max=6 rfds=[4] wfds=[5] efds=[] to=13.539402
  select=1 rfds=[] wfds=[5] efds=[]
  +0.008807
  read fd=5 buflen=1
@@ -332,7 +332,7 @@
      64647204 61727061 00000c00 01.
  write=45
  +0.000449
- select max=6 rfds=[4,5] wfds=[] efds=[5] to=29.998444
+ select max=6 rfds=[4,5] wfds=[] efds=[5] to=29.529039
  select=1 rfds=[5] wfds=[] efds=[]
  +1.-90216
  read fd=5 buflen=2
@@ -391,7 +391,7 @@
  read fd=5 buflen=973
  read=EAGAIN
  +0.000255
- select max=6 rfds=[4,5] wfds=[] efds=[5] to=29.078950
+ select max=6 rfds=[4,5] wfds=[] efds=[5] to=28.609545
  select=1 rfds=[5] wfds=[] efds=[]
  +1.-260444
  read fd=5 buflen=973
@@ -431,7 +431,7 @@
  read fd=5 buflen=2433
  read=EAGAIN
  +0.018754
- select max=6 rfds=[4,5] wfds=[] efds=[5] to=28.314815
+ select max=6 rfds=[4,5] wfds=[] efds=[5] to=28.145272
  select=1 rfds=[5] wfds=[] efds=[]
  +0.355726
  read fd=5 buflen=2433
@@ -486,7 +486,7 @@
  read fd=5 buflen=973
  read=EAGAIN
  +0.000242
- select max=6 rfds=[4,5] wfds=[] efds=[5] to=27.950237
+ select max=6 rfds=[4,5] wfds=[] efds=[5] to=27.780694
  select=1 rfds=[5] wfds=[] efds=[]
  +1.-129629
  read fd=5 buflen=973
Index: adns/regress/case-manyptrwrongrst.sys
diff -u adns/regress/case-manyptrwrongrst.sys:1.2 adns/regress/case-manyptrwrongrst.sys:1.3
--- adns/regress/case-manyptrwrongrst.sys:1.2	Fri Jul 30 00:10:49 1999
+++ adns/regress/case-manyptrwrongrst.sys	Sat Oct 16 20:04:07 1999
@@ -446,7 +446,7 @@
  recvfrom fd=4 buflen=512 *addrlen=16
  recvfrom=EAGAIN
  +0.000169
- select max=6 rfds=[4,5] wfds=[] efds=[5] to=29.282776
+ select max=6 rfds=[4,5] wfds=[] efds=[5] to=29.275214
  select=1 rfds=[4] wfds=[] efds=[]
  +1.-921124
  recvfrom fd=4 buflen=512 *addrlen=16
@@ -471,7 +471,7 @@
  recvfrom fd=4 buflen=512 *addrlen=16
  recvfrom=EAGAIN
  +0.000483
- select max=6 rfds=[4,5] wfds=[] efds=[5] to=29.200363
+ select max=6 rfds=[4,5] wfds=[] efds=[5] to=29.192801
  select=1 rfds=[5] wfds=[] efds=[]
  +0.817055
  read fd=5 buflen=2
@@ -563,7 +563,7 @@
  read fd=5 buflen=2417
  read=EAGAIN
  +0.019409
- select max=6 rfds=[4,5] wfds=[] efds=[5] to=59.059852
+ select max=6 rfds=[4,5] wfds=[] efds=[5] to=29.059852
  select=1 rfds=[5] wfds=[] efds=[]
  +0.028945
  read fd=5 buflen=2417
@@ -618,7 +618,7 @@
  read fd=5 buflen=957
  read=EAGAIN
  +0.000264
- select max=6 rfds=[4,5] wfds=[] efds=[5] to=59.021921
+ select max=6 rfds=[4,5] wfds=[] efds=[5] to=29.021921
  select=1 rfds=[5] wfds=[] efds=[]
  +0.063001
  read fd=5 buflen=957
Index: adns/regress/case-noinfto.out
diff -u /dev/null adns/regress/case-noinfto.out:1.1
--- /dev/null	Wed Nov 24 17:20:58 1999
+++ adns/regress/case-noinfto.out	Fri Oct 15 19:20:57 1999
@@ -0,0 +1,4 @@
+adns debug: using nameserver 172.18.45.36
+a.b.c.d flags 0 type 1 A(-) submitted
+a.b.c.d flags 0 type A(-): DNS query timed out; nrrs=0; cname=$; owner=$; ttl=604744
+rc=0
Index: adns/regress/case-noinfto.sys
diff -u /dev/null adns/regress/case-noinfto.sys:1.1
--- /dev/null	Wed Nov 24 17:20:58 1999
+++ adns/regress/case-noinfto.sys	Fri Oct 15 19:20:57 1999
@@ -0,0 +1,123 @@
+noserver -,p
+:1 a.b.c.d
+ start 940011574.766962
+ socket type=SOCK_DGRAM
+ socket=4
+ +0.000158
+ fcntl fd=4 cmd=F_GETFL
+ fcntl=~O_NONBLOCK&...
+ +0.000053
+ fcntl fd=4 cmd=F_SETFL O_NONBLOCK|...
+ fcntl=OK
+ +0.000039
+ sendto fd=4 addr=172.18.45.36:53
+     311f0100 00010000 00000000 01610162 01630164 00000100 01.
+ sendto=25
+ +0.001065
+ poll fds=[{fd=4, events=POLLIN, revents=0}] timeout=1999
+ poll=0 fds=[{fd=4, events=POLLIN, revents=0}]
+ +2.010188
+ sendto fd=4 addr=172.18.45.36:53
+     311f0100 00010000 00000000 01610162 01630164 00000100 01.
+ sendto=25
+ +0.000218
+ poll fds=[{fd=4, events=POLLIN, revents=0}] timeout=2000
+ poll=0 fds=[{fd=4, events=POLLIN, revents=0}]
+ +2.009786
+ sendto fd=4 addr=172.18.45.36:53
+     311f0100 00010000 00000000 01610162 01630164 00000100 01.
+ sendto=25
+ +0.000282
+ poll fds=[{fd=4, events=POLLIN, revents=0}] timeout=2000
+ poll=0 fds=[{fd=4, events=POLLIN, revents=0}]
+ +2.009708
+ sendto fd=4 addr=172.18.45.36:53
+     311f0100 00010000 00000000 01610162 01630164 00000100 01.
+ sendto=25
+ +0.000217
+ poll fds=[{fd=4, events=POLLIN, revents=0}] timeout=2000
+ poll=0 fds=[{fd=4, events=POLLIN, revents=0}]
+ +2.009800
+ sendto fd=4 addr=172.18.45.36:53
+     311f0100 00010000 00000000 01610162 01630164 00000100 01.
+ sendto=25
+ +0.000272
+ poll fds=[{fd=4, events=POLLIN, revents=0}] timeout=2000
+ poll=0 fds=[{fd=4, events=POLLIN, revents=0}]
+ +2.009786
+ sendto fd=4 addr=172.18.45.36:53
+     311f0100 00010000 00000000 01610162 01630164 00000100 01.
+ sendto=25
+ +0.000216
+ poll fds=[{fd=4, events=POLLIN, revents=0}] timeout=2000
+ poll=0 fds=[{fd=4, events=POLLIN, revents=0}]
+ +2.009723
+ sendto fd=4 addr=172.18.45.36:53
+     311f0100 00010000 00000000 01610162 01630164 00000100 01.
+ sendto=25
+ +0.000273
+ poll fds=[{fd=4, events=POLLIN, revents=0}] timeout=2000
+ poll=EINTR
+ +18.-37194
+ poll fds=[{fd=4, events=POLLIN, revents=0}] timeout=0
+ poll=0 fds=[{fd=4, events=POLLIN, revents=0}]
+ +10.-89436
+ sendto fd=4 addr=172.18.45.36:53
+     311f0100 00010000 00000000 01610162 01630164 00000100 01.
+ sendto=25
+ +0.000256
+ poll fds=[{fd=4, events=POLLIN, revents=0}] timeout=2000
+ poll=0 fds=[{fd=4, events=POLLIN, revents=0}]
+ +2.006138
+ sendto fd=4 addr=172.18.45.36:53
+     311f0100 00010000 00000000 01610162 01630164 00000100 01.
+ sendto=25
+ +0.000218
+ poll fds=[{fd=4, events=POLLIN, revents=0}] timeout=2000
+ poll=0 fds=[{fd=4, events=POLLIN, revents=0}]
+ +2.009731
+ sendto fd=4 addr=172.18.45.36:53
+     311f0100 00010000 00000000 01610162 01630164 00000100 01.
+ sendto=25
+ +0.000261
+ poll fds=[{fd=4, events=POLLIN, revents=0}] timeout=2000
+ poll=0 fds=[{fd=4, events=POLLIN, revents=0}]
+ +2.009735
+ sendto fd=4 addr=172.18.45.36:53
+     311f0100 00010000 00000000 01610162 01630164 00000100 01.
+ sendto=25
+ +0.000212
+ poll fds=[{fd=4, events=POLLIN, revents=0}] timeout=2000
+ poll=0 fds=[{fd=4, events=POLLIN, revents=0}]
+ +2.009790
+ sendto fd=4 addr=172.18.45.36:53
+     311f0100 00010000 00000000 01610162 01630164 00000100 01.
+ sendto=25
+ +0.000254
+ poll fds=[{fd=4, events=POLLIN, revents=0}] timeout=2000
+ poll=0 fds=[{fd=4, events=POLLIN, revents=0}]
+ +2.009747
+ sendto fd=4 addr=172.18.45.36:53
+     311f0100 00010000 00000000 01610162 01630164 00000100 01.
+ sendto=25
+ +0.000228
+ poll fds=[{fd=4, events=POLLIN, revents=0}] timeout=2000
+ poll=0 fds=[{fd=4, events=POLLIN, revents=0}]
+ +2.009771
+ sendto fd=4 addr=172.18.45.36:53
+     311f0100 00010000 00000000 01610162 01630164 00000100 01.
+ sendto=25
+ +0.000256
+ poll fds=[{fd=4, events=POLLIN, revents=0}] timeout=2000
+ poll=0 fds=[{fd=4, events=POLLIN, revents=0}]
+ +2.009755
+ sendto fd=4 addr=172.18.45.36:53
+     311f0100 00010000 00000000 01610162 01630164 00000100 01.
+ sendto=25
+ +0.000226
+ poll fds=[{fd=4, events=POLLIN, revents=0}] timeout=2000
+ poll=0 fds=[{fd=4, events=POLLIN, revents=0}]
+ +2.009768
+ close fd=4
+ close=OK
+ +0.000363
Index: adns/regress/case-norecurse.out
diff -u adns/regress/case-norecurse.out:1.5 adns/regress/case-norecurse.out:1.6
--- adns/regress/case-norecurse.out:1.5	Tue Oct 12 22:35:06 1999
+++ adns/regress/case-norecurse.out	Sat Oct 16 20:04:07 1999
@@ -6,7 +6,7 @@
 4.204.50.158.in-addr.arpa flags 0 type 12 PTR(raw) submitted
 4.204.50.158.in-addr.arpa flags 0 type 13adns debug: TCP connected (NS=172.18.45.6)
  HINFO(-) submitted
-4.204.50.158.in-addr.arpa flags 0 type 15adns warning: TCP connection lost: poll/select: exceptional condition detected (NS=172.18.45.6)
+4.204.50.158.in-addr.arpa flags 0 type 15adns warning: TCP connection failed: poll/select: exceptional condition detected (NS=172.18.45.6)
  MX(raw) submitted
 4.204.50.158.in-addr.arpa flags 0 type 16 TXT(-) submitted
 4.204.50.158.in-addr.arpa flags 0 type 17 RP(raw) submitted
@@ -15,7 +15,7 @@
 4.204.50.158.in-addr.arpa flags 0 type 65548 PTR(checked) submitted
 4.204.50.158.in-addr.arpa flags 0 type 65551adns debug: TCP connected (NS=172.18.45.6)
  MX(+addr) submitted
-4.204.50.158.in-addr.arpa flags 0 type 131078adns warning: TCP connection lost: poll/select: exceptional condition detected (NS=172.18.45.6)
+4.204.50.158.in-addr.arpa flags 0 type 131078adns warning: TCP connection failed: poll/select: exceptional condition detected (NS=172.18.45.6)
  SOA(822) submitted
 4.204.50.158.in-addr.arpa flags 0 type 131089adns debug: reply not found, id 3141, query owner ns2.afpdoc.com (NS=172.18.45.6)
 adns debug: reply not found, id 3142, query owner ns2.afp-notes.com (NS=172.18.45.6)
Index: adns/regress/case-norecurse2.sys
diff -u adns/regress/case-norecurse2.sys:1.4 adns/regress/case-norecurse2.sys:1.5
--- adns/regress/case-norecurse2.sys:1.4	Tue Oct 12 22:38:23 1999
+++ adns/regress/case-norecurse2.sys	Sat Oct 16 20:04:07 1999
@@ -523,7 +523,7 @@
  recvfrom fd=4 buflen=512 *addrlen=16
  recvfrom=EAGAIN
  +0.000201
- select max=6 rfds=[4] wfds=[5] efds=[] to=29.987312
+ select max=6 rfds=[4] wfds=[5] efds=[] to=13.987312
  select=1 rfds=[] wfds=[5] efds=[]
  +0.000364
  read fd=5 buflen=1
@@ -539,7 +539,7 @@
      64647204 61727061 00000c00 01.
  write=45
  +0.001275
- select max=6 rfds=[4,5] wfds=[] efds=[5] to=29.996906
+ select max=6 rfds=[4,5] wfds=[] efds=[5] to=29.983854
  select=1 rfds=[5] wfds=[] efds=[]
  +0.000150
  read fd=5 buflen=2
Index: adns/regress/case-tcpmultipart.sys
diff -u adns/regress/case-tcpmultipart.sys:1.1 adns/regress/case-tcpmultipart.sys:1.2
--- adns/regress/case-tcpmultipart.sys:1.1	Sun Sep 26 19:21:07 1999
+++ adns/regress/case-tcpmultipart.sys	Sat Oct 16 20:04:07 1999
@@ -22,7 +22,7 @@
  connect fd=5 addr=172.31.80.9:53
  connect=EINPROGRESS
  +0.000414
- select max=6 rfds=[4] wfds=[5] efds=[] to=29.998324
+ select max=6 rfds=[4] wfds=[5] efds=[] to=13.998324
  select=1 rfds=[] wfds=[5] efds=[]
  +1.-647444
  read fd=5 buflen=1
@@ -43,7 +43,7 @@
      2d616464 72046172 70610000 0c0001.
  write=47
  +0.000273
- select max=6 rfds=[4,5] wfds=[] efds=[5] to=29.998465
+ select max=6 rfds=[4,5] wfds=[] efds=[5] to=29.644233
  select=1 rfds=[5] wfds=[] efds=[]
  +0.538651
  read fd=5 buflen=2
@@ -66,7 +66,7 @@
  read fd=5 buflen=297
  read=EAGAIN
  +0.000476
- select max=6 rfds=[4,5] wfds=[] efds=[5] to=29.457802
+ select max=6 rfds=[4,5] wfds=[] efds=[5] to=29.105246
  select=1 rfds=[5] wfds=[] efds=[]
  +1.-401146
  read fd=5 buflen=297
@@ -109,7 +109,7 @@
  read fd=5 buflen=2572
  read=EAGAIN
  +0.000101
- select max=6 rfds=[4,5] wfds=[] efds=[5] to=28.855360
+ select max=6 rfds=[4,5] wfds=[] efds=[5] to=28.502804
  select=1 rfds=[5] wfds=[] efds=[]
  +0.336462
  read fd=5 buflen=2572
@@ -148,7 +148,7 @@
  read fd=5 buflen=1624
  read=EAGAIN
  +0.000124
- select max=6 rfds=[4,5] wfds=[] efds=[5] to=28.515459
+ select max=6 rfds=[4,5] wfds=[] efds=[5] to=28.162903
  select=1 rfds=[5] wfds=[] efds=[]
  +1.-683589
  read fd=5 buflen=1624
@@ -187,7 +187,7 @@
  read fd=5 buflen=676
  read=EAGAIN
  +0.000114
- select max=6 rfds=[4,5] wfds=[] efds=[5] to=28.195733
+ select max=6 rfds=[4,5] wfds=[] efds=[5] to=27.843177
  select=1 rfds=[5] wfds=[] efds=[]
  +0.376863
  read fd=5 buflen=676
@@ -230,7 +230,7 @@
  read fd=5 buflen=3248
  read=EAGAIN
  +0.000066
- select max=6 rfds=[4,5] wfds=[] efds=[5] to=27.807002
+ select max=6 rfds=[4,5] wfds=[] efds=[5] to=27.454446
  select=1 rfds=[5] wfds=[] efds=[]
  +0.316770
  read fd=5 buflen=3248
Index: adns/regress/harness.h.m4
diff -u adns/regress/harness.h.m4:1.7 adns/regress/harness.h.m4:1.8
--- adns/regress/harness.h.m4:1.7	Sun Oct 10 14:16:24 1999
+++ adns/regress/harness.h.m4	Tue Nov  2 23:40:14 1999
@@ -48,6 +48,11 @@
 int Hwritev(int fd, const struct iovec *vector, size_t count);
 int Hgettimeofday(struct timeval *tv, struct timezone *tz);
 
+void *Hmalloc(size_t sz);
+void Hfree(void *ptr);
+void *Hrealloc(void *op, size_t nsz);
+void Hexit(int rv);
+
 /* There is a Q function (Q for Question) for each such syscall;
  * it constructs a string representing the call, and calls Q_str
  * on it, or constructs it in vb and calls Q_vb;
@@ -58,6 +63,8 @@
 m4_include(`hsyscalls.i4')
 
 void Q_vb(void);
+
+extern void Tshutdown(void);
 
 /* General help functions */
 
Index: adns/regress/hcommon.c.m4
diff -u adns/regress/hcommon.c.m4:1.9 adns/regress/hcommon.c.m4:1.12
--- adns/regress/hcommon.c.m4:1.9	Tue Oct 12 22:29:02 1999
+++ adns/regress/hcommon.c.m4	Tue Nov  2 23:40:14 1999
@@ -28,6 +28,7 @@
 #include <fcntl.h>
 #include <string.h>
 #include <errno.h>
+#include <stdlib.h>
 
 #include <sys/socket.h>
 #include <netinet/in.h>
@@ -51,6 +52,9 @@
   { "ENOPROTOOPT",               ENOPROTOOPT                  },
   { "ENOSPC",                    ENOSPC                       },
   { "EWOULDBLOCK",               EWOULDBLOCK                  },
+  { "EHOSTUNREACH",              EHOSTUNREACH                 },
+  { "ECONNREFUSED",              ECONNREFUSED                 },
+  { "EPIPE",                     EPIPE                        },
   {  0,                          0                            }
 };
 
@@ -128,7 +132,7 @@
   const byte *bp;
   int i;
 
-  if (!len) { Tvba(" empty"); return; }
+  if (!len) { Tvba("\n     ."); return; }
   for (i=0, bp=buf; i<len; i++, bp++) {
     if (!(i&31)) Tvba("\n     ");
     else if (!(i&3)) Tvba(" ");
@@ -224,4 +228,81 @@
 
 void Toutputerr(void) {
   Tfailed("write error on test harness output");
+}
+
+struct malloced {
+  struct malloced *next, *back;
+  size_t sz;
+  unsigned long count;
+  struct { double d; long ul; void *p; void (*fp)(void); } data;
+};
+
+static unsigned long malloccount, mallocfailat;
+static struct { struct malloced *head, *tail; } mallocedlist;
+
+#define MALLOCHSZ ((char*)&mallocedlist.head->data - (char*)mallocedlist.head)
+
+void *Hmalloc(size_t sz) {
+  struct malloced *newnode;
+  const char *mfavar;
+  char *ep;
+
+  assert(sz);
+
+  newnode= malloc(MALLOCHSZ + sz);  if (!newnode) Tnomem();
+
+  LIST_LINK_TAIL(mallocedlist,newnode);
+  newnode->sz= sz;
+  newnode->count= ++malloccount;
+  if (!mallocfailat) {
+    mfavar= getenv("ADNS_REGRESS_MALLOCFAILAT");
+    if (mfavar) {
+      mallocfailat= strtoul(mfavar,&ep,10);
+      if (!mallocfailat || *ep) Tfailed("ADNS_REGRESS_MALLOCFAILAT bad value");
+    } else {
+      mallocfailat= ~0UL;
+    }
+  }
+  assert(newnode->count != mallocfailat);
+  memset(&newnode->data,0xc7,sz);
+  return &newnode->data;
+}
+
+void Hfree(void *ptr) {
+  struct malloced *oldnode;
+
+  if (!ptr) return;
+
+  oldnode= (void*)((char*)ptr - MALLOCHSZ);
+  LIST_UNLINK(mallocedlist,oldnode);
+  memset(&oldnode->data,0x38,oldnode->sz);
+  free(oldnode);
+}
+
+void *Hrealloc(void *op, size_t nsz) {
+  struct malloced *oldnode;
+  void *np;
+  size_t osz;
+
+  if (op) { oldnode= (void*)((char*)op - MALLOCHSZ); osz= oldnode->sz; } else { osz= 0; }
+  np= Hmalloc(nsz);
+  memcpy(np,op, osz>nsz ? nsz : osz);
+  Hfree(op);
+  return np;
+}
+
+void Hexit(int rv) {
+  struct malloced *loopnode;
+
+  Tshutdown();
+  adns__vbuf_free(&vb);
+  adns__vbuf_free(&vbw);
+  if (mallocedlist.head) {
+    fprintf(stderr,"adns test harness: memory leaked:");
+    for (loopnode=mallocedlist.head; loopnode; loopnode=loopnode->next)
+      fprintf(stderr," %lu(%lu)",loopnode->count,(unsigned long)loopnode->sz);
+    putc('\n',stderr);
+    if (ferror(stderr)) exit(-1);
+  }
+  exit(rv);
 }
Index: adns/regress/hplayback.c.m4
diff -u adns/regress/hplayback.c.m4:1.9 adns/regress/hplayback.c.m4:1.11
--- adns/regress/hplayback.c.m4:1.9	Tue Oct 12 22:28:29 1999
+++ adns/regress/hplayback.c.m4	Tue Nov  2 23:40:14 1999
@@ -40,10 +40,15 @@
 static FILE *Tinputfile, *Treportfile;
 static vbuf vb2;
 
+extern void Tshutdown(void) {
+  adns__vbuf_free(&vb2);
+}
+
 static void Tensurereportfile(void) {
   const char *fdstr;
   int fd;
 
+  if (Treportfile) return;
   Treportfile= stderr;
   fdstr= getenv("ADNS_TEST_REPORT_FD"); if (!fdstr) return;
   fd= atoi(fdstr);
@@ -271,7 +276,7 @@
 m4_define(`hm_syscall', `
  hm_create_proto_h
 int H$1(hm_args_massage($3,void)) {
- int r;
+ int r, amtread;
  m4_define(`hm_rv_fd',`char *ep;')
  m4_define(`hm_rv_any',`char *ep;')
  m4_define(`hm_rv_len',`')
@@ -295,10 +300,10 @@
 
  Tensurereportfile();
  fprintf(Treportfile,"syscallr %s",vb2.buf);
- vb2.avail= strlen(vb2.buf);
- if (vb.avail<=0 || vb2.buf[--vb2.avail]!=hm_squote\nhm_squote)
+ amtread= strlen(vb2.buf);
+ if (amtread<=0 || vb2.buf[--amtread]!=hm_squote\nhm_squote)
   Psyntax("badly formed line");
- vb2.buf[vb2.avail]= 0;
+ vb2.buf[amtread]= 0;
  if (memcmp(vb2.buf," $1=",hm_r_offset)) Psyntax("syscall reply mismatch");
 
  if (vb2.buf[hm_r_offset] == hm_squoteEhm_squote) {
@@ -346,7 +351,8 @@
  m4_define(`hm_arg_pollfds_io',`Parg("$'`1"); Ppollfds($'`1,$'`2);')
  m4_define(`hm_arg_addr_out',`Parg("$'`1"); Paddr($'`1,$'`2);')
  $3
- if (vb2.used != vb2.avail) Psyntax("junk at end of line");
+ assert(vb2.used <= amtread);
+ if (vb2.used != amtread) Psyntax("junk at end of line");
 
  hm_create_nothing
  m4_define(`hm_arg_bytes_out',`r= Pbytes($'`2,$'`4);')
Index: adns/regress/hrecord.c.m4
diff -u adns/regress/hrecord.c.m4:1.10 adns/regress/hrecord.c.m4:1.11
--- adns/regress/hrecord.c.m4:1.10	Sun Oct 10 14:16:24 1999
+++ adns/regress/hrecord.c.m4	Tue Nov  2 23:40:14 1999
@@ -35,6 +35,9 @@
 
 static FILE *Toutputfile;
 
+void Tshutdown(void) {
+}
+
 static void R_recordtime(void) {
   int r;
   struct timeval tv, tvrel;
Index: adns/regress/init-1stservbroken.text
diff -u /dev/null adns/regress/init-1stservbroken.text:1.1
--- /dev/null	Wed Nov 24 17:20:58 1999
+++ adns/regress/init-1stservbroken.text	Sat Oct 16 20:04:07 1999
@@ -0,0 +1,3 @@
+nameserver 172.18.45.2
+nameserver 172.18.45.6
+sortlist 127.0.0.1/32 172.18.45.0/28 172.18.45.0/24
Index: adns/regress/init-1stservto.text
diff -u /dev/null adns/regress/init-1stservto.text:1.1
--- /dev/null	Wed Nov 24 17:20:58 1999
+++ adns/regress/init-1stservto.text	Sat Oct 16 20:04:07 1999
@@ -0,0 +1,3 @@
+nameserver 10.0.0.1
+nameserver 172.18.45.6
+sortlist 127.0.0.1/32 172.18.45.0/28 172.18.45.0/24
Index: adns/regress/init-2ndserver.text
diff -u /dev/null adns/regress/init-2ndserver.text:1.1
--- /dev/null	Wed Nov 24 17:20:58 1999
+++ adns/regress/init-2ndserver.text	Sat Oct 16 20:04:07 1999
@@ -0,0 +1,3 @@
+nameserver 172.18.45.36
+nameserver 172.18.45.6
+sortlist 127.0.0.1/32 172.18.45.0/28 172.18.45.0/24
Index: adns/src/adns.h
diff -u adns/src/adns.h:1.70 adns/src/adns.h:1.73
--- adns/src/adns.h:1.70	Wed Oct 13 02:23:56 1999
+++ adns/src/adns.h	Sun Nov  7 19:15:36 1999
@@ -51,7 +51,7 @@
  *  Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  *
  *
- *  $Id: adns.h,v 1.70 1999/10/13 01:23:56 ian Exp $
+ *  $Id: adns.h,v 1.73 1999/11/07 19:15:36 ian Exp $
  */
 
 #ifndef ADNS_H_INCLUDED
@@ -78,6 +78,7 @@
   adns_if_noerrprint=   0x0002, /* never print output to stderr (_debug overrides) */
   adns_if_noserverwarn= 0x0004, /* do not warn to stderr about duff nameservers etc */
   adns_if_debug=        0x0008, /* enable all output to stderr plus debug msgs */
+  adns_if_logpid=       0x0080, /* include pid in diagnostic output */
   adns_if_noautosys=    0x0010, /* do not make syscalls at every opportunity */
   adns_if_eintr=        0x0020, /* allow _wait and _synchronous to return EINTR */
   adns_if_nosigpipe=    0x0040, /* applic has SIGPIPE set to SIG_IGN, do not protect */
@@ -336,20 +337,21 @@
  *  requested.
  */
 
-int adns_init(adns_state *newstate_r, int flags /*adns_initflags*/,
+int adns_init(adns_state *newstate_r, adns_initflags flags,
 	      FILE *diagfile /*0=>stderr*/);
 
-int adns_init_strcfg(adns_state *newstate_r, int flags /*adns_initflags*/,
+int adns_init_strcfg(adns_state *newstate_r, adns_initflags flags,
 		     FILE *diagfile /*0=>discard*/, const char *configtext);
 
 /* Configuration:
  *  adns_init reads /etc/resolv.conf, which is expected to be (broadly
- *  speaking) in the format expected by libresolv.  adns_init_strcfg
- *  is instead passed a string which is interpreted as if it were the
- *  contents of resolv.conf.  In general, configuration which is set
- *  later overrides any that is set earlier.
+ *  speaking) in the format expected by libresolv, and then
+ *  /etc/resolv-adns.conf if it exists.  adns_init_strcfg is instead
+ *  passed a string which is interpreted as if it were the contents of
+ *  resolv.conf or resolv-adns.conf.  In general, configuration which
+ *  is set later overrides any that is set earlier.
  *
- * Standard directives understood in resolv.conf:
+ * Standard directives understood in resolv[-adns].conf:
  * 
  *  nameserver <address>
  *   Must be followed by the IP address of a nameserver.  Several
@@ -382,7 +384,7 @@
  *   Each option consists of an option name, followed by optionally
  *   a colon and a value.  Options are listed below.
  *
- * Non-standard directives understood in resolv.conf:
+ * Non-standard directives understood in resolv[-adns].conf:
  *
  *  clearnameservers
  *   Clears the list of nameservers, so that further nameserver lines
@@ -391,7 +393,8 @@
  *  include <filename>
  *   The specified file will be read.
  *
- * Additionally, adns will ignore lines in resolv.conf which start with a #.
+ * Additionally, adns will ignore lines in resolv[-adns].conf which
+ * start with a #.
  *
  * Standard options understood:
  *
@@ -420,7 +423,7 @@
  * each case there is both a FOO and an ADNS_FOO; the latter is
  * interpreted later so that it can override the former.  Unless
  * otherwise stated, environment variables are interpreted after
- * resolv.conf is read, in the order they are listed here.
+ * resolv[-adns].conf are read, in the order they are listed here.
  *
  *  RES_CONF, ADNS_RES_CONF
  *   A filename, whose contets are in the format of resolv.conf.
@@ -443,7 +446,7 @@
 int adns_synchronous(adns_state ads,
 		     const char *owner,
 		     adns_rrtype type,
-		     int flags /*adns_queryflags*/,
+		     adns_queryflags flags,
 		     adns_answer **answer_r);
 
 /* NB: if you set adns_if_noautosys then _submit and _check do not
@@ -454,7 +457,7 @@
 int adns_submit(adns_state ads,
 		const char *owner,
 		adns_rrtype type,
-		int flags /*adns_queryflags*/,
+		adns_queryflags flags,
 		void *context,
 		adns_query *query_r);
 
@@ -493,7 +496,7 @@
 int adns_submit_reverse(adns_state ads,
 			const struct sockaddr *addr,
 			adns_rrtype type,
-			int flags /*adns_queryflags*/,
+			adns_queryflags flags,
 			void *context,
 			adns_query *query_r);
 /* type must be _r_ptr or _r_ptr_raw.  _qf_search is ignored.
Index: adns/src/check.c
diff -u adns/src/check.c:1.5 adns/src/check.c:1.6
--- adns/src/check.c:1.5	Tue Oct 12 20:51:08 1999
+++ adns/src/check.c	Sat Oct 16 20:11:02 1999
@@ -63,12 +63,16 @@
 
   assert(qu->udpnextserver < ads->nservers);
   assert(!(qu->udpsent & (~0UL << ads->nservers)));
-  assert(!(qu->tcpfailed & (~0UL << ads->nservers)));
-  assert(qu->udpretries <= UDPMAXRETRIES);
   assert(qu->search_pos <= ads->nsearchlist);
   if (qu->parent) DLIST_ASSERTON(qu, child, qu->parent->children, siblings.);
 }
 
+static void checkc_notcpbuf(adns_state ads) {
+  assert(!ads->tcpsend.used);
+  assert(!ads->tcprecv.used);
+  assert(!ads->tcprecv_skip);
+}
+
 static void checkc_global(adns_state ads) {
   int i;
   
@@ -82,10 +86,12 @@
   switch (ads->tcpstate) {
   case server_connecting:
     assert(ads->tcpsocket >= 0);
-  case server_disconnected: /* fall through */
-    assert(!ads->tcpsend.used);
-    assert(!ads->tcprecv.used);
-    assert(!ads->tcprecv_skip);
+    checkc_notcpbuf(ads);
+    break;
+  case server_disconnected:
+  case server_broken:
+    assert(ads->tcpsocket == -1);
+    checkc_notcpbuf(ads);
     break;
   case server_ok:
     assert(ads->tcpsocket >= 0);
@@ -98,34 +104,36 @@
   assert(ads->searchlist || !ads->nsearchlist);
 }
 
-static void checkc_queue_timew(adns_state ads) {
+static void checkc_queue_udpw(adns_state ads) {
   adns_query qu;
   
-  DLIST_CHECK(ads->timew, qu, , {
-    switch (qu->state) {
-    case query_tosend:
-      assert(qu->udpsent);
-      assert(!qu->tcpfailed);
-      break;
-    case query_tcpwait:
-      assert(ads->tcpstate != server_ok);
-      break;
-    case query_tcpsent:
-      break;
-    default:
-      assert(!"timew state");
-    }
+  DLIST_CHECK(ads->udpw, qu, , {
+    assert(qu->state==query_tosend);
+    assert(qu->retries <= UDPMAXRETRIES);
+    assert(qu->udpsent);
     assert(!qu->children.head && !qu->children.tail);
     checkc_query(ads,qu);
     checkc_query_alloc(ads,qu);
   });
 }
 
+static void checkc_queue_tcpw(adns_state ads) {
+  adns_query qu;
+  
+  DLIST_CHECK(ads->tcpw, qu, , {
+    assert(qu->state==query_tcpw);
+    assert(!qu->children.head && !qu->children.tail);
+    assert(qu->retries <= ads->nservers+1);
+    checkc_query(ads,qu);
+    checkc_query_alloc(ads,qu);
+  });
+}
+
 static void checkc_queue_childw(adns_state ads) {
   adns_query parent, child;
 
   DLIST_CHECK(ads->childw, parent, , {
-    assert(parent->state == query_child);
+    assert(parent->state == query_childw);
     assert(parent->children.head);
     DLIST_CHECK(parent->children, child, siblings., {
       assert(child->parent == parent);
@@ -165,18 +173,20 @@
   }
 
   checkc_global(ads);
-  checkc_queue_timew(ads);
+  checkc_queue_udpw(ads);
+  checkc_queue_tcpw(ads);
   checkc_queue_childw(ads);
   checkc_queue_output(ads);
 
   if (qu) {
     switch (qu->state) {
     case query_tosend:
-    case query_tcpwait:
-    case query_tcpsent:
-      DLIST_ASSERTON(qu, search, ads->timew, );
+      DLIST_ASSERTON(qu, search, ads->udpw, );
+      break;
+    case query_tcpw:
+      DLIST_ASSERTON(qu, search, ads->tcpw, );
       break;
-    case query_child:
+    case query_childw:
       DLIST_ASSERTON(qu, search, ads->childw, );
       break;
     case query_done:
Index: adns/src/event.c
diff -u adns/src/event.c:1.40 adns/src/event.c:1.44
--- adns/src/event.c:1.40	Wed Oct 13 00:00:08 1999
+++ adns/src/event.c	Sun Nov  7 16:06:48 1999
@@ -39,40 +39,29 @@
 #include <arpa/inet.h>
 
 #include "internal.h"
+#include "tvarith.h"
 
 /* TCP connection management. */
 
-void adns__tcp_closenext(adns_state ads) {
+static void tcp_close(adns_state ads) {
   int serv;
   
   serv= ads->tcpserver;
   close(ads->tcpsocket);
   ads->tcpsocket= -1;
-  ads->tcpstate= server_disconnected;
   ads->tcprecv.used= ads->tcprecv_skip= ads->tcpsend.used= 0;
-  ads->tcpserver= (serv+1)%ads->nservers;
 }
 
 void adns__tcp_broken(adns_state ads, const char *what, const char *why) {
   int serv;
-  adns_query qu, nqu;
   
   assert(ads->tcpstate == server_connecting || ads->tcpstate == server_ok);
   serv= ads->tcpserver;
-  adns__warn(ads,serv,0,"TCP connection lost: %s: %s",what,why);
-  adns__tcp_closenext(ads);
-  
-  for (qu= ads->timew.head; qu; qu= nqu) {
-    nqu= qu->next;
-    if (qu->state == query_tosend) continue;
-    assert(qu->state == query_tcpwait || qu->state == query_tcpsent);
-    qu->state= query_tcpwait;
-    qu->tcpfailed |= (1<<serv);
-    if (qu->tcpfailed == (1<<ads->nservers)-1) {
-      LIST_UNLINK(ads->timew,qu);
-      adns__query_fail(qu,adns_s_allservfail);
-    }
-  }
+  if (what) adns__warn(ads,serv,0,"TCP connection failed: %s: %s",what,why);
+
+  tcp_close(ads);
+  ads->tcpstate= server_broken;
+  ads->tcpserver= (serv+1)%ads->nservers;
 }
 
 static void tcp_connected(adns_state ads, struct timeval now) {
@@ -80,11 +69,10 @@
   
   adns__debug(ads,ads->tcpserver,0,"TCP connected");
   ads->tcpstate= server_ok;
-  for (qu= ads->timew.head; qu; qu= nqu) {
+  for (qu= ads->tcpw.head; qu && ads->tcpstate == server_ok; qu= nqu) {
     nqu= qu->next;
-    if (qu->state == query_tosend) continue;
-    assert (qu->state == query_tcpwait);
-    adns__query_tcp(qu,now);
+    assert(qu->state == query_tcpw);
+    adns__querysend_tcp(qu,now);
   }
 }
 
@@ -94,8 +82,17 @@
   struct protoent *proto;
 
   for (tries=0; tries<ads->nservers; tries++) {
-    if (ads->tcpstate == server_connecting || ads->tcpstate == server_ok) return;
-    assert(ads->tcpstate == server_disconnected);
+    switch (ads->tcpstate) {
+    case server_connecting:
+    case server_ok:
+    case server_broken:
+      return;
+    case server_disconnected:
+      break;
+    default:
+      abort();
+    }
+    
     assert(!ads->tcpsend.used);
     assert(!ads->tcprecv.used);
     assert(!ads->tcprecv_skip);
@@ -120,9 +117,14 @@
     r= connect(fd,(const struct sockaddr*)&addr,sizeof(addr));
     ads->tcpsocket= fd;
     ads->tcpstate= server_connecting;
-    if (r==0) { tcp_connected(ads,now); continue; }
-    if (errno == EWOULDBLOCK || errno == EINPROGRESS) return;
+    if (r==0) { tcp_connected(ads,now); return; }
+    if (errno == EWOULDBLOCK || errno == EINPROGRESS) {
+      ads->tcptimeout= now;
+      timevaladd(&ads->tcptimeout,TCPCONNMS);
+      return;
+    }
     adns__tcp_broken(ads,"connect",strerror(errno));
+    ads->tcpstate= server_disconnected;
   }
 }
 
@@ -158,6 +160,7 @@
 
 static void inter_maxtoabs(struct timeval **tv_io, struct timeval *tvbuf,
 			   struct timeval now, struct timeval maxtime) {
+  /* tv_io may be 0 */
   ldiv_t dr;
 
 /*fprintf(stderr,"inter_maxtoabs now=%ld.%06ld maxtime=%ld.%06ld\n",
@@ -172,29 +175,94 @@
   inter_maxto(tv_io,tvbuf,maxtime);
 }
 
-void adns__timeouts(adns_state ads, int act,
-		    struct timeval **tv_io, struct timeval *tvbuf,
-		    struct timeval now) {
+static void timeouts_queue(adns_state ads, int act,
+			   struct timeval **tv_io, struct timeval *tvbuf,
+			   struct timeval now, struct query_queue *queue) {
   adns_query qu, nqu;
-
-  for (qu= ads->timew.head; qu; qu= nqu) {
+  
+  for (qu= queue->head; qu; qu= nqu) {
     nqu= qu->next;
     if (!timercmp(&now,&qu->timeout,>)) {
-      if (!tv_io) continue;
       inter_maxtoabs(tv_io,tvbuf,now,qu->timeout);
     } else {
-      if (!act) continue;
-      LIST_UNLINK(ads->timew,qu);
+      if (!act) {
+	tvbuf->tv_sec= 0;
+	tvbuf->tv_usec= 0;
+	*tv_io= tvbuf;
+	return;
+      }
+      LIST_UNLINK(*queue,qu);
       if (qu->state != query_tosend) {
 	adns__query_fail(qu,adns_s_timeout);
       } else {
 	adns__query_send(qu,now);
       }
-      nqu= ads->timew.head;
+      nqu= queue->head;
     }
   }
-}  
+}
 
+static void tcp_events(adns_state ads, int act,
+		       struct timeval **tv_io, struct timeval *tvbuf,
+		       struct timeval now) {
+  adns_query qu, nqu;
+  
+  for (;;) {
+    switch (ads->tcpstate) {
+    case server_broken:
+      for (qu= ads->tcpw.head; qu; qu= nqu) {
+	nqu= qu->next;
+	assert(qu->state == query_tcpw);
+	if (qu->retries > ads->nservers) {
+	  LIST_UNLINK(ads->tcpw,qu);
+	  adns__query_fail(qu,adns_s_allservfail);
+	}
+      }
+      ads->tcpstate= server_disconnected;
+    case server_disconnected: /* fall through */
+      if (!ads->tcpw.head) return;
+      adns__tcp_tryconnect(ads,now);
+      break;
+    case server_ok:
+      if (ads->tcpw.head) return;
+      if (!ads->tcptimeout.tv_sec) {
+	assert(!ads->tcptimeout.tv_usec);
+	ads->tcptimeout= now;
+	timevaladd(&ads->tcptimeout,TCPIDLEMS);
+      }
+    case server_connecting: /* fall through */
+      if (!timercmp(&now,&ads->tcptimeout,>)) {
+	inter_maxtoabs(tv_io,tvbuf,now,ads->tcptimeout);
+	return;
+      } {
+	/* TCP timeout has happened */
+	switch (ads->tcpstate) {
+	case server_connecting: /* failed to connect */
+	  adns__tcp_broken(ads,"unable to make connection","timed out");
+	  break;
+	case server_ok: /* idle timeout */
+	  tcp_close(ads);
+	  ads->tcpstate= server_disconnected;
+	  return;
+	default:
+	  abort();
+	}
+      }
+      break;
+    default:
+      abort();
+    }
+  }
+}
+
+void adns__timeouts(adns_state ads, int act,
+		    struct timeval **tv_io, struct timeval *tvbuf,
+		    struct timeval now) {
+  timeouts_queue(ads,act,tv_io,tvbuf,now, &ads->udpw);
+  timeouts_queue(ads,act,tv_io,tvbuf,now, &ads->tcpw);
+  tcp_events(ads,act,tv_io,tvbuf,now);
+}
+
 void adns_firsttimeout(adns_state ads,
 		       struct timeval **tv_io, struct timeval *tvbuf,
 		       struct timeval now) {
@@ -509,14 +577,13 @@
 void adns_globalsystemfailure(adns_state ads) {
   adns__consistency(ads,0,cc_entex);
 
-  while (ads->timew.head) {
-    adns__query_fail(ads->timew.head, adns_s_systemfail);
-  }
+  while (ads->udpw.head) adns__query_fail(ads->udpw.head, adns_s_systemfail);
+  while (ads->tcpw.head) adns__query_fail(ads->tcpw.head, adns_s_systemfail);
   
   switch (ads->tcpstate) {
   case server_connecting:
   case server_ok:
-    adns__tcp_closenext(ads);
+    adns__tcp_broken(ads,0,0);
     break;
   case server_disconnected:
     break;
@@ -567,7 +634,7 @@
   if (!qu) {
     if (ads->output.head) {
       qu= ads->output.head;
-    } else if (ads->timew.head) {
+    } else if (ads->udpw.head || ads->tcpw.head) {
       return EAGAIN;
     } else {
       return ESRCH;
Index: adns/src/general.c
diff -u adns/src/general.c:1.23 adns/src/general.c:1.25
--- adns/src/general.c:1.23	Wed Oct 13 01:23:01 1999
+++ adns/src/general.c	Tue Nov  2 23:40:14 1999
@@ -27,6 +27,7 @@
  */
 
 #include <stdlib.h>
+#include <unistd.h>
 
 #include <sys/types.h>
 #include <sys/socket.h>
@@ -46,7 +47,11 @@
       (!(ads->iflags & adns_if_debug) && (!prevent || (ads->iflags & prevent))))
     return;
 
-  fprintf(ads->diagfile,"adns%s: ",pfx);
+  if (ads->iflags & adns_if_logpid) {
+    fprintf(ads->diagfile,"adns%s [%ld]: ",pfx,(long)getpid());
+  } else {
+    fprintf(ads->diagfile,"adns%s: ",pfx);
+  }
 
   vfprintf(ads->diagfile,fmt,al);
 
@@ -63,6 +68,7 @@
     if (qu->typei && qu->typei->fmtname)
       fprintf(ads->diagfile,"(%s)",qu->typei->fmtname);
     bef=", "; aft=")\n";
+    adns__vbuf_free(&vb);
   }
   
   if (serv>=0) {
Index: adns/src/internal.h
diff -u adns/src/internal.h:1.51 adns/src/internal.h:1.54
--- adns/src/internal.h:1.51	Tue Oct 12 20:51:08 1999
+++ adns/src/internal.h	Sun Nov  7 16:06:49 1999
@@ -11,20 +11,20 @@
  *  It is part of adns, which is
  *    Copyright (C) 1997-1999 Ian Jackson <ian@davenant.greenend.org.uk>
  *    Copyright (C) 1999 Tony Finch <dot@dotat.at>
- *  
+ *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
  *  the Free Software Foundation; either version 2, or (at your option)
  *  any later version.
- *  
+ *
  *  This program is distributed in the hope that it will be useful,
  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  *  GNU General Public License for more details.
- *  
+ *
  *  You should have received a copy of the GNU General Public License
  *  along with this program; if not, write to the Free Software Foundation,
- *  Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 
+ *  Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  */
 
 #ifndef ADNS_INTERNAL_H_INCLUDED
@@ -51,7 +51,9 @@
 #define MAXSORTLIST 15
 #define UDPMAXRETRIES 15
 #define UDPRETRYMS 2000
-#define TCPMS 30000
+#define TCPWAITMS 30000
+#define TCPCONNMS 14000
+#define TCPIDLEMS 30000
 #define MAXTTLBELIEVE (7*86400) /* any TTL > 7 days is capped */
 
 #define DNS_PORT 53
@@ -164,7 +166,7 @@
 
 struct adns__query {
   adns_state ads;
-  enum { query_tosend, query_tcpwait, query_tcpsent, query_child, query_done } state;
+  enum { query_tosend, query_tcpw, query_childw, query_done } state;
   adns_query back, next, parent;
   struct { adns_query head, tail; } children;
   struct { adns_query back, next; } siblings;
@@ -175,7 +177,7 @@
   const typeinfo *typei;
   byte *query_dgram;
   int query_dglen;
-  
+
   vbuf vb;
   /* General-purpose messing-about buffer.
    * Wherever a `big' interface is crossed, this may be corrupted/changed
@@ -192,7 +194,7 @@
    * owner is set during querying unless we're doing searchlist,
    * in which case it is set only when we find an answer.
    */
-  
+
   byte *cname_dgram;
   int cname_dglen, cname_begin;
   /* If non-0, has been allocated using . */
@@ -207,10 +209,10 @@
    * but not done yet).  If flags doesn't have adns_qf_search then
    * the vbuf is initialised but empty and everything else is zero.
    */
-  
-  int id, flags, udpretries;
+
+  int id, flags, retries;
   int udpnextserver;
-  unsigned long udpsent, tcpfailed; /* bitmap indexed by server */
+  unsigned long udpsent; /* bitmap indexed by server */
   struct timeval timeout;
   time_t expires; /* Earliest expiry time of any record we used. */
 
@@ -219,43 +221,41 @@
   /* Possible states:
    *
    *  state   Queue   child  id   nextudpserver  udpsent     tcpfailed
-   *				  
+   *
    *  tosend  NONE    null   >=0  0              zero        zero
-   *  tosend  timew   null   >=0  any            nonzero     zero
+   *  tosend  udpw    null   >=0  any            nonzero     zero
    *  tosend  NONE    null   >=0  any            nonzero     zero
-   *				  
-   *  tcpwait timew   null   >=0  irrelevant     any         any
-   *  tcpsent timew   null   >=0  irrelevant     any         any
-   *				  
+   *
+   *  tcpw    tcpw    null   >=0  irrelevant     any         any
+   *
    *  child   childw  set    >=0  irrelevant     irrelevant  irrelevant
    *  child   NONE    null   >=0  irrelevant     irrelevant  irrelevant
    *  done    output  null   -1   irrelevant     irrelevant  irrelevant
    *
    * Queries are only not on a queue when they are actually being processed.
+   * Queries in state tcpw/tcpw have been sent (or are in the to-send buffer)
+   * iff the tcp connection is in state server_ok.
    *
    *			      +------------------------+
-   *             START -----> |      udp/NONE          |
+   *             START -----> |      tosend/NONE       |
    *			      +------------------------+
    *                         /                       |\  \
    *        too big for UDP /             UDP timeout  \  \ send via UDP
-   *        do this ASAP!  /              more retries  \  \   do this ASAP!
-   *                     |_                  desired     \  _|
-   *		  +---------------+     	    	+-----------+
-   *              | tcpwait/timew | ____                | udp/timew |
-   *              +---------------+     \	    	+-----------+
-   *                    |  ^             |                 | |
-   *     TCP conn'd;    |  | TCP died    |                 | |
-   *     send via TCP   |  | more        |     UDP timeout | |
-   *     do this ASAP!  |  | servers     |      no more    | |
-   *                    v  | to try      |      retries    | |
-   *              +---------------+      |      desired    | |
-   *              | tcpsent/timew | ____ |                 | |
-   *    	  +---------------+     \|                 | |
-   *                  \   \ TCP died     | TCP             | |
-   *                   \   \ no more     | timeout         / |
-   *                    \   \ servers    |                /  |
-   *                     \   \ to try    |               /   |
-   *                  got \   \          v             |_    / got
+   *        send via TCP   /              more retries  \  \
+   *        when conn'd   /                  desired     \  \
+   *                     |     	       	       	       	  |  |
+   *                     v				  |  v
+   *              +-----------+         	    	+-------------+
+   *              | tcpw/tcpw | ________                | tosend/udpw |
+   *              +-----------+         \	    	+-------------+
+   *                 |    |              |     UDP timeout | |
+   *                 |    |              |      no more    | |
+   *                 |    |              |      retries    | |
+   *                  \   | TCP died     |      desired    | |
+   *                   \   \ no more     |                 | |
+   *                    \   \ servers    | TCP            /  |
+   *                     \   \ to try    | timeout       /   |
+   *                  got \   \          v             |_    | got
    *                 reply \   _| +------------------+      / reply
    *   	       	       	    \  	  | done/output FAIL |     /
    *                         \    +------------------+    /
@@ -266,23 +266,33 @@
    *        need child query/ies /                     \ no child query
    *                            /                       \
    *                          |_                         _|
-   *		    +--------------+		       +----------------+
-   *                | child/childw | ----------------> | done/output OK |
-   *                +--------------+  children done    +----------------+
+   *		   +---------------+		       +----------------+
+   *               | childw/childw | ----------------> | done/output OK |
+   *               +---------------+  children done    +----------------+
    */
 };
 
+struct query_queue { adns_query head, tail; };
+
 struct adns__state {
   adns_initflags iflags;
   FILE *diagfile;
   int configerrno;
-  struct { adns_query head, tail; } timew, childw, output;
+  struct query_queue udpw, tcpw, childw, output;
   adns_query forallnext;
   int nextid, udpsocket, tcpsocket;
   vbuf tcpsend, tcprecv;
   int nservers, nsortlist, nsearchlist, searchndots, tcpserver, tcprecv_skip;
-  enum adns__tcpstate { server_disconnected, server_connecting, server_ok } tcpstate;
+  enum adns__tcpstate {
+    server_disconnected, server_connecting,
+    server_ok, server_broken
+  } tcpstate;
   struct timeval tcptimeout;
+  /* This will have tv_sec==0 if it is not valid.
+   * It will always be valid if tcpstate _connecting.
+   * When _ok, it will be nonzero if we are idle
+   * (ie, tcpw queue is empty) and counting down.
+   */
   struct sigaction stdsigpipe;
   sigset_t stdsigmask;
   struct pollfd pollfds_buf[MAX_POLLFDS];
@@ -298,7 +308,6 @@
 /* From setup.c: */
 
 int adns__setnonblock(adns_state ads, int fd); /* => errno value */
-void adns__checkqueues(adns_state ads); /* expensive walk, for checking */
 
 /* From general.c: */
 
@@ -332,7 +341,7 @@
  * Returns either vb->buf, or a pointer to a string literal.  Do not modify
  * vb before using the return value.
  */
-  
+
 void adns__isort(void *array, int nobjs, int sz, void *tempbuf,
 		 int (*needswap)(void *context, const void *a, const void *b),
 		 void *context);
@@ -347,7 +356,8 @@
 /* If SIGPIPE protection is not disabled, will block all signals except
  * SIGPIPE, and set SIGPIPE's disposition to SIG_IGN.  (And then restore.)
  * Each call to _protect must be followed by a call to _unprotect before
- * any significant amount of code gets to run.
+ * any significant amount of code gets to run, since the old signal mask
+ * is stored in the adns structure.
  */
 
 /* From transmit.c: */
@@ -365,16 +375,10 @@
  * That domain must be correct and untruncated.
  */
 
-void adns__query_tcp(adns_query qu, struct timeval now);
-/* Query must be in state tcpwait/timew; it will be moved to a new state
- * if possible and no further processing can be done on it for now.
- * (Resulting state is one of tcpwait/timew (if server not connected),
- *  tcpsent/timew, child/childw or done/output.)
- *
- * adns__tcp_tryconnect should already have been called - _tcp
- * will only use an existing connection (if there is one), which it
- * may break.  If the conn list lost then the caller is responsible for any
- * reestablishment and retry.
+void adns__querysend_tcp(adns_query qu, struct timeval now);
+/* Query must be in state tcpw/tcpw; it will be sent if possible and
+ * no further processing can be done on it for now.  The connection
+ * might be broken, but no reconnect will be attempted.
  */
 
 void adns__query_send(adns_query qu, struct timeval now);
@@ -488,11 +492,19 @@
 
 void adns__query_done(adns_query qu);
 void adns__query_fail(adns_query qu, adns_status stat);
-   
+
 /* From reply.c: */
 
 void adns__procdgram(adns_state ads, const byte *dgram, int len,
 		     int serv, int viatcp, struct timeval now);
+/* This function is allowed to cause new datagrams to be constructed
+ * and sent, or even new queries to be started.  However,
+ * query-sending functions are not allowed to call any general event
+ * loop functions in case they accidentally call this.
+ *
+ * Ie, receiving functions may call sending functions.
+ * Sending functions may NOT call receiving functions.
+ */
 
 /* From types.c: */
 
@@ -628,7 +640,8 @@
 /* From event.c: */
 
 void adns__tcp_broken(adns_state ads, const char *what, const char *why);
-void adns__tcp_closenext(adns_state ads);
+/* what and why may be both 0, or both non-0. */
+
 void adns__tcp_tryconnect(adns_state ads, struct timeval now);
 
 void adns__autosys(adns_state ads, struct timeval now);
@@ -639,9 +652,7 @@
 
 void adns__must_gettimeofday(adns_state ads, const struct timeval **now_io,
 			     struct timeval *tv_buf);
-void adns__timeouts(adns_state ads, int act,
-		    struct timeval **tv_io, struct timeval *tvbuf,
-		    struct timeval now);
+
 int adns__pollfds(adns_state ads, struct pollfd pollfds_buf[MAX_POLLFDS]);
 void adns__fdevents(adns_state ads,
 		    const struct pollfd *pollfds, int npollfds,
@@ -653,21 +664,18 @@
 			 adns_answer **answer,
 			 void **context_r);
 
+void adns__timeouts(adns_state ads, int act,
+		    struct timeval **tv_io, struct timeval *tvbuf,
+		    struct timeval now);
+/* If act is !0, then this will also deal with the TCP connection
+ * if previous events broke it or require it to be connected.
+ */
+
 /* From check.c: */
 
 void adns__consistency(adns_state ads, adns_query qu, consistency_checks cc);
 
 /* Useful static inline functions: */
-
-static inline void timevaladd(struct timeval *tv_io, long ms) {
-  struct timeval tmp;
-  assert(ms>=0);
-  tmp= *tv_io;
-  tmp.tv_usec += (ms%1000)*1000000;
-  tmp.tv_sec += ms/1000;
-  if (tmp.tv_usec >= 1000000) { tmp.tv_sec++; tmp.tv_usec -= 1000; }
-  *tv_io= tmp;
-}
 
 static inline int ctype_whitespace(int c) { return c==' ' || c=='\n' || c=='\t'; }
 static inline int ctype_digit(int c) { return c>='0' && c<='9'; }
Index: adns/src/query.c
diff -u adns/src/query.c:1.48 adns/src/query.c:1.53
--- adns/src/query.c:1.48	Wed Oct 13 02:23:56 1999
+++ adns/src/query.c	Tue Nov  2 23:40:14 1999
@@ -68,9 +68,9 @@
 
   qu->id= 0;
   qu->flags= flags;
-  qu->udpretries= 0;
+  qu->retries= 0;
   qu->udpnextserver= 0;
-  qu->udpsent= qu->tcpfailed= 0;
+  qu->udpsent= 0;
   timerclear(&qu->timeout);
   qu->expires= now.tv_sec + MAXTTLBELIEVE;
 
@@ -91,7 +91,7 @@
 			 const typeinfo *typei, vbuf *qumsg_vb, int id,
 			 adns_queryflags flags, struct timeval now) {
   /* Fills in the query message in for a previously-allocated query,
-   * and submits it.  Cannot fail.
+   * and submits it.  Cannot fail.  Takes over the memory for qumsg_vb.
    */
 
   qu->vb= *qumsg_vb;
@@ -131,7 +131,7 @@
   int id;
   adns_status stat;
 
-  adns__vbuf_init(&vb);
+  vb= qu->vb;
   
   stat= adns__mkquery(ads,&vb,&id, owner,ol, typei,flags);
   if (stat) { adns__query_fail(qu,stat); return; }
@@ -195,7 +195,7 @@
 int adns_submit(adns_state ads,
 		const char *owner,
 		adns_rrtype type,
-		int flags,
+		adns_queryflags flags,
 		void *context,
 		adns_query *query_r) {
   int r, ol, ndots;
@@ -225,6 +225,7 @@
 				 
   if (ol>=1 && owner[ol-1]=='.' && (ol<2 || owner[ol-2]!='\\')) {
     flags &= ~adns_qf_search;
+    qu->flags= flags;
     ol--;
   }
 
@@ -261,7 +262,7 @@
 int adns_submit_reverse(adns_state ads,
 			const struct sockaddr *addr,
 			adns_rrtype type,
-			int flags,
+			adns_queryflags flags,
 			void *context,
 			adns_query *query_r) {
   const unsigned char *iaddr;
@@ -282,7 +283,7 @@
 int adns_synchronous(adns_state ads,
 		     const char *owner,
 		     adns_rrtype type,
-		     int flags,
+		     adns_queryflags flags,
 		     adns_answer **answer_r) {
   adns_query qu;
   int r;
@@ -389,6 +390,8 @@
   for (an= qu->allocations.head; an; an= ann) { ann= an->next; free(an); }
   LIST_INIT(qu->allocations);
   adns__vbuf_free(&qu->vb);
+  adns__vbuf_free(&qu->search_vb);
+  free(qu->query_dgram);
 }
 
 void adns_cancel(adns_query qu) {
@@ -398,10 +401,13 @@
   adns__consistency(ads,qu,cc_entex);
   if (qu->parent) LIST_UNLINK_PART(qu->parent->children,qu,siblings.);
   switch (qu->state) {
-  case query_tosend: case query_tcpwait: case query_tcpsent:
-    LIST_UNLINK(ads->timew,qu);
+  case query_tosend:
+    LIST_UNLINK(ads->udpw,qu);
+    break;
+  case query_tcpw:
+    LIST_UNLINK(ads->tcpw,qu);
     break;
-  case query_child:
+  case query_childw:
     LIST_UNLINK(ads->childw,qu);
     break;
   case query_done:
@@ -496,6 +502,7 @@
     LIST_UNLINK(qu->ads->childw,parent);
     qu->ctx.callback(parent,qu);
     free_query_allocs(qu);
+    free(qu->answer);
     free(qu);
   } else {
     makefinal_query(qu);
Index: adns/src/reply.c
diff -u adns/src/reply.c:1.33 adns/src/reply.c:1.34
--- adns/src/reply.c:1.33	Sun Oct 10 14:16:24 1999
+++ adns/src/reply.c	Sat Oct 16 20:11:02 1999
@@ -85,7 +85,7 @@
 	       qdcount);
     return;
   }
-  for (qu= ads->timew.head; qu; qu= nqu) {
+  for (qu= viatcp ? ads->tcpw.head : ads->udpw.head; qu; qu= nqu) {
     nqu= qu->next;
     if (qu->id != id) continue;
     if (dglen < qu->query_dglen) continue;
@@ -94,9 +94,9 @@
 	       qu->query_dglen-DNS_HDRSIZE))
       continue;
     if (viatcp) {
-      if (qu->state != query_tcpsent) continue;
+      assert(qu->state == query_tcpw);
     } else {
-      if (qu->state != query_tosend) continue;
+      assert(qu->state == query_tosend);
       if (!(qu->udpsent & (1<<serv))) continue;
     }
     break;
@@ -113,7 +113,8 @@
   anstart= qu->query_dglen;
   arstart= -1;
 
-  LIST_UNLINK(ads->timew,qu);
+  if (viatcp) LIST_UNLINK(ads->tcpw,qu);
+  else LIST_UNLINK(ads->udpw,qu);
   /* We're definitely going to do something with this query now */
   
   switch (rcode) {
@@ -318,7 +319,7 @@
 
   /* This may have generated some child queries ... */
   if (qu->children.head) {
-    qu->state= query_child;
+    qu->state= query_childw;
     LIST_LINK_TAIL(ads->childw,qu);
     return;
   }
@@ -349,7 +350,8 @@
     memcpy(newquery,qu->vb.buf,qu->vb.used);
   }
   
-  if (qu->state == query_tcpsent) qu->state= query_tosend;
+  if (qu->state == query_tcpw) qu->state= query_tosend;
+  qu->retries= 0;
   adns__reset_preserved(qu);
   adns__query_send(qu,now);
 }
Index: adns/src/setup.c
diff -u adns/src/setup.c:1.30 adns/src/setup.c:1.35
--- adns/src/setup.c:1.30	Wed Oct 13 02:23:56 1999
+++ adns/src/setup.c	Sun Nov  7 19:15:36 1999
@@ -39,7 +39,7 @@
 
 #include "internal.h"
 
-static void readconfig(adns_state ads, const char *filename);
+static void readconfig(adns_state ads, const char *filename, int warnmissing);
 
 static void addserver(adns_state ads, struct in_addr addr) {
   int i;
@@ -62,6 +62,11 @@
   ads->nservers++;
 }
 
+static void freesearchlist(adns_state ads) {
+  if (ads->nsearchlist) free(*ads->searchlist);
+  free(ads->searchlist);
+}
+
 static void saveerr(adns_state ads, int en) {
   if (!ads->configerrno) ads->configerrno= en;
 }
@@ -133,7 +138,7 @@
     *newchars++ = 0;
   }
 
-  free(ads->searchlist);
+  freesearchlist(ads);
   ads->nsearchlist= count;
   ads->searchlist= newptrs;
 }
@@ -259,7 +264,7 @@
     configparseerr(ads,fn,lno,"`include' directive with no filename");
     return;
   }
-  readconfig(ads,buf);
+  readconfig(ads,buf,1);
 }
 
 static const struct configcommandinfo {
@@ -394,13 +399,14 @@
   return value;
 }
 
-static void readconfig(adns_state ads, const char *filename) {
+static void readconfig(adns_state ads, const char *filename, int warnmissing) {
   getline_ctx gl_ctx;
   
   gl_ctx.file= fopen(filename,"r");
   if (!gl_ctx.file) {
     if (errno == ENOENT) {
-      adns__debug(ads,-1,0,"configuration file `%s' does not exist",filename);
+      if (warnmissing)
+	adns__debug(ads,-1,0,"configuration file `%s' does not exist",filename);
       return;
     }
     saveerr(ads,errno);
@@ -429,7 +435,7 @@
     return;
   }
   filename= instrum_getenv(ads,envvar);
-  if (filename) readconfig(ads,filename);
+  if (filename) readconfig(ads,filename,1);
 }
 
 static void readconfigenvtext(adns_state ads, const char *envvar) {
@@ -461,7 +467,8 @@
   ads->iflags= flags;
   ads->diagfile= diagfile;
   ads->configerrno= 0;
-  LIST_INIT(ads->timew);
+  LIST_INIT(ads->udpw);
+  LIST_INIT(ads->tcpw);
   LIST_INIT(ads->childw);
   LIST_INIT(ads->output);
   ads->forallnext= 0;
@@ -516,7 +523,7 @@
   free(ads);
 }
 
-int adns_init(adns_state *ads_r, int flags, FILE *diagfile) {
+int adns_init(adns_state *ads_r, adns_initflags flags, FILE *diagfile) {
   adns_state ads;
   const char *res_options, *adns_res_options;
   int r;
@@ -529,7 +536,8 @@
   ccf_options(ads,"RES_OPTIONS",-1,res_options);
   ccf_options(ads,"ADNS_RES_OPTIONS",-1,adns_res_options);
 
-  readconfig(ads,"/etc/resolv.conf");
+  readconfig(ads,"/etc/resolv.conf",1);
+  readconfig(ads,"/etc/resolv-adns.conf",0);
   readconfigenv(ads,"RES_CONF");
   readconfigenv(ads,"ADNS_RES_CONF");
 
@@ -556,7 +564,7 @@
   return 0;
 }
 
-int adns_init_strcfg(adns_state *ads_r, int flags,
+int adns_init_strcfg(adns_state *ads_r, adns_initflags flags,
 		     FILE *diagfile, const char *configtext) {
   adns_state ads;
   int r;
@@ -580,7 +588,8 @@
 void adns_finish(adns_state ads) {
   adns__consistency(ads,0,cc_entex);
   for (;;) {
-    if (ads->timew.head) adns_cancel(ads->timew.head);
+    if (ads->udpw.head) adns_cancel(ads->udpw.head);
+    else if (ads->tcpw.head) adns_cancel(ads->tcpw.head);
     else if (ads->childw.head) adns_cancel(ads->childw.head);
     else if (ads->output.head) adns_cancel(ads->output.head);
     else break;
@@ -589,13 +598,15 @@
   if (ads->tcpsocket >= 0) close(ads->tcpsocket);
   adns__vbuf_free(&ads->tcpsend);
   adns__vbuf_free(&ads->tcprecv);
+  freesearchlist(ads);
   free(ads);
 }
 
 void adns_forallqueries_begin(adns_state ads) {
   adns__consistency(ads,0,cc_entex);
   ads->forallnext=
-    ads->timew.head ? ads->timew.head :
+    ads->udpw.head ? ads->udpw.head :
+    ads->tcpw.head ? ads->tcpw.head :
     ads->childw.head ? ads->childw.head :
     ads->output.head;
 }
@@ -610,12 +621,15 @@
     if (!qu) return 0;
     if (qu->next) {
       nqu= qu->next;
-    } else if (qu == ads->timew.tail) {
-      if (ads->childw.head) {
-	nqu= ads->childw.head;
-      } else {
-	nqu= ads->output.head;
-      }
+    } else if (qu == ads->udpw.tail) {
+      nqu=
+	ads->tcpw.head ? ads->tcpw.head :
+	ads->childw.head ? ads->childw.head :
+	ads->output.head;
+    } else if (qu == ads->tcpw.tail) {
+      nqu=
+	ads->childw.head ? ads->childw.head :
+	ads->output.head;
     } else if (qu == ads->childw.tail) {
       nqu= ads->output.head;
     } else {
@@ -626,9 +640,4 @@
   ads->forallnext= nqu;
   if (context_r) *context_r= qu->ctx.ext;
   return qu;
-}
-
-void adns__checkqueues(adns_state ads) {
-  adns_forallqueries_begin(ads);
-  while (adns_forallqueries_next(ads,0));
 }
Index: adns/src/transmit.c
diff -u adns/src/transmit.c:1.14 adns/src/transmit.c:1.17
--- adns/src/transmit.c:1.14	Sun Oct 10 14:16:24 1999
+++ adns/src/transmit.c	Sun Nov  7 16:06:49 1999
@@ -32,6 +32,7 @@
 #include <sys/uio.h>
 
 #include "internal.h"
+#include "tvarith.h"
 
 #define MKQUERY_START(vb) (rqp= (vb)->buf+(vb)->used)
 #define MKQUERY_ADDB(b) *rqp++= (b)
@@ -81,7 +82,7 @@
   const char *p, *pe;
   adns_status st;
 
-  st= mkquery_header(ads,vb,id_r,strlen(owner)+2); if (st) return st;
+  st= mkquery_header(ads,vb,id_r,ol+2); if (st) return st;
   
   MKQUERY_START(vb);
 
@@ -157,7 +158,7 @@
   return adns_s_ok;
 }
 
-void adns__query_tcp(adns_query qu, struct timeval now) {
+void adns__querysend_tcp(adns_query qu, struct timeval now) {
   byte length[2];
   struct iovec iov[2];
   int wr, r;
@@ -165,15 +166,18 @@
 
   if (qu->ads->tcpstate != server_ok) return;
 
+  assert(qu->state == query_tcpw);
+
   length[0]= (qu->query_dglen&0x0ff00U) >>8;
   length[1]= (qu->query_dglen&0x0ff);
 
   ads= qu->ads;
   if (!adns__vbuf_ensure(&ads->tcpsend,ads->tcpsend.used+qu->query_dglen+2)) return;
 
-  timevaladd(&now,TCPMS);
-  qu->timeout= now;
-  qu->state= query_tcpsent;
+  qu->retries++;
+
+  /* Reset idle timeout. */
+  ads->tcptimeout.tv_sec= ads->tcptimeout.tv_usec= 0;
 
   if (ads->tcpsend.used) {
     wr= 0;
@@ -207,11 +211,11 @@
 }
 
 static void query_usetcp(adns_query qu, struct timeval now) {
-  timevaladd(&now,TCPMS);
+  qu->state= query_tcpw;
   qu->timeout= now;
-  qu->state= query_tcpwait;
-  LIST_LINK_TAIL(qu->ads->timew,qu);
-  adns__query_tcp(qu,now);
+  timevaladd(&qu->timeout,TCPWAITMS);
+  LIST_LINK_TAIL(qu->ads->tcpw,qu);
+  adns__querysend_tcp(qu,now);
   adns__tcp_tryconnect(qu->ads,now);
 }
 
@@ -226,7 +230,7 @@
     return;
   }
 
-  if (qu->udpretries >= UDPMAXRETRIES) {
+  if (qu->retries >= UDPMAXRETRIES) {
     adns__query_fail(qu,adns_s_timeout);
     return;
   }
@@ -241,13 +245,13 @@
   
   r= sendto(ads->udpsocket,qu->query_dgram,qu->query_dglen,0,
 	    (const struct sockaddr*)&servaddr,sizeof(servaddr));
-  if (r<0 && errno == EMSGSIZE) { query_usetcp(qu,now); return; }
+  if (r<0 && errno == EMSGSIZE) { qu->retries= 0; query_usetcp(qu,now); return; }
   if (r<0) adns__warn(ads,serv,0,"sendto failed: %s",strerror(errno));
   
-  timevaladd(&now,UDPRETRYMS);
   qu->timeout= now;
+  timevaladd(&qu->timeout,UDPRETRYMS);
   qu->udpsent |= (1<<serv);
   qu->udpnextserver= (serv+1)%ads->nservers;
-  qu->udpretries++;
-  LIST_LINK_TAIL(ads->timew,qu);
+  qu->retries++;
+  LIST_LINK_TAIL(ads->udpw,qu);
 }
Index: adns/src/tvarith.h
diff -u /dev/null adns/src/tvarith.h:1.2
--- /dev/null	Wed Nov 24 17:20:58 1999
+++ adns/src/tvarith.h	Sun Nov  7 19:02:20 1999
@@ -0,0 +1,41 @@
+/*
+ * tvarith.h
+ * - static inline functions for doing arithmetic on timevals
+ */
+/*
+ *  This file is
+ *    Copyright (C) 1997-1999 Ian Jackson <ian@davenant.greenend.org.uk>
+ *
+ *  It is part of adns, which is
+ *    Copyright (C) 1997-1999 Ian Jackson <ian@davenant.greenend.org.uk>
+ *    Copyright (C) 1999 Tony Finch <dot@dotat.at>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2, or (at your option)
+ *  any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software Foundation,
+ *  Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef ADNS_TVARITH_H_INCLUDED
+#define ADNS_TVARITH_H_INCLUDED
+
+static inline void timevaladd(struct timeval *tv_io, long ms) {
+  struct timeval tmp;
+  assert(ms>=0);
+  tmp= *tv_io;
+  tmp.tv_usec += (ms%1000)*1000;
+  tmp.tv_sec += ms/1000;
+  if (tmp.tv_usec >= 1000000) { tmp.tv_sec++; tmp.tv_usec -= 1000000; }
+  *tv_io= tmp;
+}
+
+#endif