chiark / gitweb /
Build system: Add test case output and common.make to `make [dist]clean'.
[adns.git] / client / adnsresfilter.c
index bba1b1c65c6e1680985d4bcc193f0b47f5706896..770af173169abc589897371ef9ff1de441f848b7 100644 (file)
@@ -3,16 +3,16 @@
  * - filter which does resolving, not part of the library
  */
 /*
  * - filter which does resolving, not part of the library
  */
 /*
- *  This file is
- *    Copyright (C) 1999-2000 Ian Jackson <ian@davenant.greenend.org.uk>
- *
- *  It is part of adns, which is
- *    Copyright (C) 1997-2000 Ian Jackson <ian@davenant.greenend.org.uk>
- *    Copyright (C) 1999 Tony Finch <dot@dotat.at>
+ *  This file is part of adns, which is
+ *    Copyright (C) 1997-2000,2003,2006,2014  Ian Jackson
+ *    Copyright (C) 2014  Mark Wooding
+ *    Copyright (C) 1999-2000,2003,2006  Tony Finch
+ *    Copyright (C) 1991 Massachusetts Institute of Technology
+ *  (See the file INSTALL for full details.)
  *  
  *  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
  *  
  *  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)
+ *  the Free Software Foundation; either version 3, or (at your option)
  *  any later version.
  *  
  *  This program is distributed in the hope that it will be useful,
  *  any later version.
  *  
  *  This program is distributed in the hope that it will be useful,
@@ -21,8 +21,7 @@
  *  GNU General Public License for more details.
  *  
  *  You should have received a copy of the GNU General Public License
  *  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. 
+ *  along with this program; if not, write to the Free Software Foundation.
  */
 
 #include <stdio.h>
  */
 
 #include <stdio.h>
 #include "adns.h"
 #include "dlist.h"
 #include "tvarith.h"
 #include "adns.h"
 #include "dlist.h"
 #include "tvarith.h"
+#include "client.h"
+
+#ifdef ADNS_REGRESS_TEST
+# include "hredirect.h"
+#endif
 
 struct outqueuenode {
   struct outqueuenode *next, *back;
 
 struct outqueuenode {
   struct outqueuenode *next, *back;
-  void *buffer;
-  char *textp;
+  char *buffer, *textp;
   int textlen;
   struct timeval printbefore;
   struct treething *addr;
   int textlen;
   struct timeval printbefore;
   struct treething *addr;
@@ -54,6 +57,8 @@ struct outqueuenode {
 static int bracket, forever, address;
 static unsigned long timeout= 1000;
 static adns_rrtype rrt= adns_r_ptr;
 static int bracket, forever, address;
 static unsigned long timeout= 1000;
 static adns_rrtype rrt= adns_r_ptr;
+static adns_initflags initflags= 0;
+static const char *config_text;
 
 static int outblocked, inputeof;
 static struct { struct outqueuenode *head, *tail; } outqueue;
 
 static int outblocked, inputeof;
 static struct { struct outqueuenode *head, *tail; } outqueue;
@@ -86,8 +91,7 @@ static int nonblock(int fd, int isnonblock) {
   return 0;
 }
 
   return 0;
 }
 
-static void quit(int exitstatus) NONRETURNING;
-static void quit(int exitstatus) {
+void quitnow(int exitstatus) {
   nonblock(0,0);
   nonblock(1,0);
   exit(exitstatus);
   nonblock(0,0);
   nonblock(1,0);
   exit(exitstatus);
@@ -96,7 +100,7 @@ static void quit(int 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));
 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);
+  quitnow(2);
 }
 
 static void *xmalloc(size_t sz) {
 }
 
 static void *xmalloc(size_t sz) {
@@ -110,28 +114,31 @@ static void outputerr(void) { sysfail("write to stdout"); }
 
 static void usage(void) {
   if (printf("usage: adnsresfilter [<options ...>]\n"
 
 static void usage(void) {
   if (printf("usage: adnsresfilter [<options ...>]\n"
-            "       adnsresfilter  -h|--help\n"
+            "       adnsresfilter  -h|--help | --version\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"
             "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"
+            "         --config <text>  (use this instead of resolv.conf)\n"
+            "         --debug          (turn on adns resolver debugging)\n"
             "Timeout is the maximum amount to delay any particular bit of output for.\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")
+            "Lookups will go on in the background.  Default timeout = 1000 (ms).\n")
       == EOF) outputerr();
       == EOF) outputerr();
+  if (fflush(stdout)) sysfail("flush stdout");
 }
 
 static void usageerr(const char *why) NONRETURNING;
 static void usageerr(const char *why) {
   fprintf(stderr,"adnsresfilter: bad usage: %s\n",why);
   usage();
 }
 
 static void usageerr(const char *why) NONRETURNING;
 static void usageerr(const char *why) {
   fprintf(stderr,"adnsresfilter: bad usage: %s\n",why);
   usage();
-  quit(1);
+  quitnow(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));
 }
 
 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);
+  quitnow(2);
 }
 
 static void settimeout(const char *arg) {
 }
 
 static void settimeout(const char *arg) {
@@ -147,48 +154,55 @@ static void parseargs(const char *const *argv) {
   while ((arg= *++argv)) {
     if (arg[0] != '-') usageerr("no non-option arguments are allowed");
     if (arg[1] == '-') {
   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;
+      if (!strcmp(arg,"--timeout")) {
+       if (!(arg= *++argv)) usageerr("--timeout needs a value");
+       settimeout(arg);
+       forever= 0;
       } else if (!strcmp(arg,"--wait")) {
        forever= 1;
       } else if (!strcmp(arg,"--wait")) {
        forever= 1;
+      } else if (!strcmp(arg,"--brackets")) {
+       bracket= 1;
       } else if (!strcmp(arg,"--address")) {
        address= 1;
       } else if (!strcmp(arg,"--address")) {
        address= 1;
+      } else if (!strcmp(arg,"--unchecked")) {
+       rrt= adns_r_ptr_raw;
+      } else if (!strcmp(arg,"--config")) {
+       if (!(arg= *++argv)) usageerr("--config needs a value");
+       config_text= arg;
+      } else if (!strcmp(arg,"--debug")) {
+       initflags |= adns_if_debug;
       } else if (!strcmp(arg,"--help")) {
       } 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;
+       usage(); quitnow(0);
+      } else if (!strcmp(arg,"--version")) {
+       VERSION_PRINT_QUIT("adnsresfilter"); quitnow(0);
       } else {
        usageerr("unknown long option");
       }
     } else {
       while ((c= *++arg)) {
        switch (c) {
       } else {
        usageerr("unknown long option");
       }
     } else {
       while ((c= *++arg)) {
        switch (c) {
-       case 'b':
-         bracket= 1;
-         break;
-       case 'u':
-         rrt= adns_r_ptr_raw;
+       case 't':
+         if (*++arg) settimeout(arg);
+         else if ((arg= *++argv)) settimeout(arg);
+         else usageerr("-t needs a value");
+         forever= 0;
+         arg= "\0";
          break;
        case 'w':
          forever= 1;
          break;
          break;
        case 'w':
          forever= 1;
          break;
+       case 'b':
+         bracket= 1;
+         break;
        case 'a':
          address= 1;
          break;
        case 'a':
          address= 1;
          break;
+       case 'u':
+         rrt= adns_r_ptr_raw;
+         break;
        case 'h':
          usage();
        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;
+         quitnow(0);
        default:
          usageerr("unknown short option");
        }
        default:
          usageerr("unknown short option");
        }
@@ -201,7 +215,8 @@ static void queueoutchar(int c) {
   struct outqueuenode *entry;
   
   entry= outqueue.tail;
   struct outqueuenode *entry;
   
   entry= outqueue.tail;
-  if (!entry || entry->addr || entry->textlen >= peroutqueuenode) {
+  if (!entry || entry->addr ||
+      entry->textlen >= peroutqueuenode - (entry->textp - entry->buffer)) {
     peroutqueuenode= !peroutqueuenode || !entry || entry->addr ? 128 : 
       peroutqueuenode >= 1024 ? 4096 : peroutqueuenode<<2;
     entry= xmalloc(sizeof(*entry));
     peroutqueuenode= !peroutqueuenode || !entry || entry->addr ? 128 : 
       peroutqueuenode >= 1024 ? 4096 : peroutqueuenode<<2;
     entry= xmalloc(sizeof(*entry));
@@ -380,7 +395,12 @@ static void startup(void) {
   if (nonblock(1,1)) sysfail("set stdout to nonblocking mode");
   memset(&sa,0,sizeof(sa));
   sa.sin_family= AF_INET;
   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);
+  if (config_text) {
+    r= adns_init_strcfg(&ads,initflags,stderr,config_text);
+  } else {
+    r= adns_init(&ads,initflags,0);
+  }
+  if (r) adnsfail("init",r);
   cbyte= -1;
   inbyte= -1;
   inbuf= 0;
   cbyte= -1;
   inbyte= -1;
   inbuf= 0;
@@ -449,7 +469,6 @@ int main(int argc, const char *const *argv) {
   }
   if (nonblock(0,0)) sysfail("un-nonblock stdin");
   if (nonblock(1,0)) sysfail("un-nonblock stdout");
   }
   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");
+  adns_finish(ads);
   exit(0);
 }
   exit(0);
 }