chiark / gitweb /
Bugfixes and stuff implemented.
authorian <ian>
Wed, 13 Oct 1999 00:27:54 +0000 (00:27 +0000)
committerian <ian>
Wed, 13 Oct 1999 00:27:54 +0000 (00:27 +0000)
client/adh-main.c
client/adh-opts.c
client/adh-query.c
client/adnshost.h

index 289f0d43c80770d09dbe520c463a8a00ee446ca0..b933bfa4f6537d8ce40bce69ae5f2d38eeae2131 100644 (file)
@@ -47,8 +47,8 @@ void outerr(void) {
   sysfail("write to stdout",errno);
 }
 
-static void domain_do_arg(const char *domain) {
-  if (ov_pipe) usageerr("-f/--pipe not consistent with domains on command line");
+static void domain_do(const char *domain) {
+  if (ov_pipe && !ads) usageerr("-f/--pipe not consistent with domains on command line");
   ensure_adns_init();
   query_do(domain);
 }
@@ -68,69 +68,154 @@ char *xstrsave(const char *str) {
   return p;
 }
 
-void of_type(const struct optioninfo *oi, const char *arg) { assert(!"implemented"); }
+void of_type(const struct optioninfo *oi, const char *arg) {
+  static const struct typename {
+    adns_rrtype type;
+    const char *desc;
+  } typenames[]= {
+    /* enhanced versions */
+    { adns_r_ns,     "ns"     },
+    { adns_r_soa,    "soa"    },
+    { adns_r_ptr,    "ptr"    },
+    { adns_r_mx,     "mx"     },
+    { adns_r_rp,     "rp"     },
+    { adns_r_addr,   "addr"   },
+    
+    /* types with only one version */
+    { adns_r_cname,  "cname"  },
+    { adns_r_hinfo,  "hinfo"  },
+    { adns_r_txt,    "txt"    },
+    
+    /* raw versions */
+    { adns_r_a,        "a"    },
+    { adns_r_ns_raw,   "ns-"  },
+    { adns_r_soa_raw,  "soa-" },
+    { adns_r_ptr_raw,  "ptr-" },
+    { adns_r_mx_raw,   "mx-"  },
+    { adns_r_rp_raw,   "rp-"  },
 
-int rcode;
+    { adns_r_none, 0 }
+  };
 
-void setnonblock(int fd, int nonblock) { }
+  const struct typename *tnp;
 
-static void read_query(void) { assert(!"implemented"); }
+  for (tnp=typenames;
+       tnp->type && strcmp(arg,tnp->desc);
+       tnp++);
+  if (!tnp->type) usageerr("unknown RR type %s",arg);
+  ov_type= tnp->type;
+}
 
-int main(int argc, const char *const *argv) {
-  const char *arg;
+int rcode;
+
+static void process_optarg(const char *arg,
+                          const char *const **argv_p,
+                          const char *value) {
   const struct optioninfo *oip;
-  struct timeval *tv, tvbuf;
-  adns_query qu;
-  void *qun_v;
-  adns_answer *answer;
-  int r, maxfd, invert;
-  fd_set readfds, writefds, exceptfds;
-  
-  while ((arg= *++argv)) {
-    if (arg[0] == '-' || arg[0] == '+') {
-      if (arg[0] == '-' && arg[1] == '-') {
-       if (!strncmp(arg,"--no-",5)) {
-         invert= 1;
-         oip= opt_findl(arg+5);
-       } else {
-         invert= 0;
-         oip= opt_findl(arg+2);
-       }
+  int invert;
+
+  if (arg[0] == '-' || arg[0] == '+') {
+    if (arg[0] == '-' && arg[1] == '-') {
+      if (!strncmp(arg,"--no-",5)) {
+       invert= 1;
+       oip= opt_findl(arg+5);
+      } else {
+       invert= 0;
+       oip= opt_findl(arg+2);
+      }
+      if (oip->type == ot_funcarg) {
+       arg= argv_p ? *++(*argv_p) : value;
+       if (!arg) usageerr("option --%s requires a value argument",oip->lopt);
+      } else {
+       if (value) usageerr("option --%s does not take a value",oip->lopt);
+       arg= 0;
+      }
+      opt_do(oip,arg,invert);
+    } else if (arg[0] == '-' && arg[1] == 0) {
+      arg= argv_p ? *++(*argv_p) : value;
+      if (!arg) usageerr("option `-' must be followed by a domain");
+      domain_do(arg);
+    } else { /* arg[1] != '-', != '\0' */
+      invert= (arg[0] == '+');
+      ++arg;
+      while (*arg) {
+       oip= opt_finds(&arg);
        if (oip->type == ot_funcarg) {
-         arg= *++argv;
-         if (!arg) usageerr("option --%s requires a value argument",oip->lopt);
-       } else {
-         arg= 0;
-       }
-       opt_do(oip,arg,invert);
-      } else if (arg[0] == '-' && arg[1] == 0) {
-       arg= *++argv;
-       if (!arg) usageerr("option `-' must be followed by a domain");
-       domain_do_arg(arg);
-      } else { /* arg[1] != '-', != '\0' */
-       invert= (arg[0] == '+');
-       ++arg;
-       while (*arg) {
-         oip= opt_finds(&arg);
-         if (oip->type == ot_funcarg) {
-           if (!*arg) {
-             arg= *++argv;
-             if (!arg) usageerr("option -%s requires a value argument",oip->sopt);
-           }
-           opt_do(oip,arg,invert);
-           arg= "";
+         if (!*arg) {
+           arg= argv_p ? *++(*argv_p) : value;
+           if (!arg) usageerr("option -%s requires a value argument",oip->sopt);
          } else {
-           opt_do(oip,0,invert);
+           if (value) usageerr("two values for option -%s given !",oip->sopt);
          }
+         opt_do(oip,arg,invert);
+         arg= "";
+       } else {
+         if (value) usageerr("option -%s does not take a value",oip->sopt);
+         opt_do(oip,0,invert);
        }
       }
-    } else { /* arg[0] != '-' */
-      domain_do_arg(arg);
     }
+  } else { /* arg[0] != '-' */
+    domain_do(arg);
   }
+}
+    
+static void read_stdin(void) {
+  static int used, avail;
+  static char *buf;
+
+  int anydone, r;
+  char *newline, *space;
+
+  anydone= 0;
+  while (!anydone || used) {
+    while (!(newline= memchr(buf,'\n',used))) {
+      if (used == avail) {
+       avail += 20; avail <<= 1;
+       buf= realloc(buf,avail);
+       if (!buf) sysfail("realloc stdin buffer",errno);
+      }
+      do {
+       r= read(0,buf+used,avail-used);
+      } while (r < 0 && errno == EINTR);
+      if (r == 0) {
+       if (used) {
+         /* fake up final newline */
+         buf[used++]= '\n';
+         r= 1;
+       } else {
+         ov_pipe= 0;
+         return;
+       }
+      }
+      if (r < 0) sysfail("read stdin",errno);
+      used += r;
+    }
+    *newline++= 0;
+    space= strchr(buf,' ');
+    if (space) *space++= 0;
+    process_optarg(buf,0,space);
+    used -= (newline-buf);
+    memmove(buf,newline,used);
+    anydone= 1;
+  }
+}
+
+int main(int argc, const char *const *argv) {
+  struct timeval *tv, tvbuf;
+  adns_query qu;
+  void *qun_v;
+  adns_answer *answer;
+  int r, maxfd;
+  fd_set readfds, writefds, exceptfds;
+  const char *arg;
+  
+  while ((arg= *++argv)) process_optarg(arg,&argv,0);
 
   if (!ov_pipe && !ads) usageerr("no domains given, and -f/--pipe not used; try --help");
 
+  ensure_adns_init();
+
   for (;;) {
     for (;;) {
       qu= ov_asynch ? 0 : outstanding.head ? outstanding.head->qu : 0;
@@ -156,7 +241,7 @@ int main(int argc, const char *const *argv) {
       sysfail("select",errno);
     }
     adns_afterselect(ads, maxfd, &readfds,&writefds,&exceptfds, 0);
-    if (ov_pipe && FD_ISSET(0,&readfds)) read_query();
+    if (ov_pipe && FD_ISSET(0,&readfds)) read_stdin();
   }
 x_quit:
   if (fclose(stdout)) outerr();
index e7704a1341ac8faf8c17d02227b4164acdee3477..92a3c0b31683732d6b1892c0fa68148f8e7a5165 100644 (file)
@@ -104,7 +104,7 @@ static const struct optioninfo perquery_options[]= {
   { ot_desconly, "asynchronous/pipe mode options:" },
   { ot_funcarg,          "Set <id>, default is decimal sequence starting 0",
     0, "asynch-id",        0,0, &of_asynch_id, "id" },
-  { ot_funcarg,          "Cancel the query with id <id>",
+  { ot_funcarg,          "Cancel the query with id <id> (no error if not found)",
     0, "cancel-id",        0,0, &of_cancel_id, "id" },
 
   { ot_end }
index 1edf1608879e8551ae8b174dcee184e673d0090b..1bc4e4c6c9a8fd4000889ab28eb98b8e5fd46121 100644 (file)
@@ -33,20 +33,6 @@ struct outstanding_list outstanding;
 
 static unsigned long idcounter;
 
-#define STATUSTYPEMAX(v) { adns_s_max_##v, #v }
-static const struct statustypemax {
-  adns_status smax;
-  const char *abbrev;
-} statustypemaxes[]= {
-  { adns_s_ok, "ok" },
-  STATUSTYPEMAX(localfail),
-  STATUSTYPEMAX(remotefail),
-  STATUSTYPEMAX(tempfail),
-  STATUSTYPEMAX(misconfig),
-  STATUSTYPEMAX(misquery),
-  STATUSTYPEMAX(permfail),
-};
-
 void ensure_adns_init(void) {
   int r;
   
@@ -92,6 +78,12 @@ void query_do(const char *domain) {
   LIST_LINK_TAIL(outstanding,qun);
 }
 
+static void dequeue_query(struct query_node *qun) {
+  LIST_UNLINK(outstanding,qun);
+  free(qun->id);
+  free(qun);
+}
+
 static void print_withspace(const char *str) {
   if (printf("%s ", str) == EOF) outerr();
 }
@@ -122,25 +114,28 @@ static void print_owner_ttl(struct query_node *qun, adns_answer *answer) {
 }
 
 static void print_status(adns_status st, struct query_node *qun, adns_answer *answer) {
-  int stnmin, stnmax, stn;
-  const char *statusabbrev, *statusstring;
-
-  stnmin= 0;
-  stnmax= sizeof(statustypemaxes)/sizeof(statustypemaxes[0]);
-  while (stnmin < stnmax) {
-    stn= (stnmin+stnmax)>>1;
-    if (st > statustypemaxes[stn].smax) stnmin= stn+1; else stnmax= stn;
-  }
-  stn= stnmin;
-  assert(statustypemaxes[stn].smax >= st);
-  
-  if (rcode < stn) rcode= stn;
+  static const adns_status statuspoints[]= {
+    adns_s_ok,
+    adns_s_max_localfail, adns_s_max_remotefail, adns_s_max_tempfail,
+    adns_s_max_misconfig, adns_s_max_misquery
+  };
+
+  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;
 
   statusabbrev= adns_errabbrev(st);
   statusstring= adns_strerror(st);
   assert(!strchr(statusstring,'"'));
 
-  if (printf("%s %d %s ", statustypemaxes[stn].abbrev, st, statusabbrev)
+  if (printf("%s %d %s ", statustypeabbrev, st, statusabbrev)
       == EOF) outerr();
   print_owner_ttl(qun,answer);
   if (qun->pqfr.show_cname)
@@ -154,8 +149,6 @@ void query_done(struct query_node *qun, adns_answer *answer) {
   const char *rrp, *realowner, *typename;
   char *datastr;
 
-  if (ov_pipe) setnonblock(1,0);
-
   st= answer->status;
   nrrs= answer->nrrs;
   if (ov_asynch) {
@@ -165,7 +158,7 @@ void query_done(struct query_node *qun, adns_answer *answer) {
     if (st) {
       if (fputs("; failed ",stdout) == EOF) outerr();
       print_status(st,qun,answer);
-    } else if (answer->cname) {
+    } else if (qun->pqfr.show_cname && answer->cname) {
       print_owner_ttl(qun,answer);
       if (printf("CNAME %s\n",answer->cname) == EOF) outerr();
     }
@@ -191,10 +184,8 @@ void query_done(struct query_node *qun, adns_answer *answer) {
     }
   }
   if (fflush(stdout)) outerr();
-  LIST_UNLINK(outstanding,qun);
   free(answer);
-  free(qun->id);
-  free(qun);
+  dequeue_query(qun);
 }
 
 void of_asynch_id(const struct optioninfo *oi, const char *arg) {
@@ -203,6 +194,12 @@ void of_asynch_id(const struct optioninfo *oi, const char *arg) {
 }
 
 void of_cancel_id(const struct optioninfo *oi, const char *arg) {
-  assert(!"implemented");
-}
+  struct query_node *qun;
 
+  for (qun= outstanding.head;
+       qun && !strcmp(qun->id,arg);
+       qun= qun->next);
+  if (!qun) return;
+  adns_cancel(qun->qu);
+  dequeue_query(qun);
+}
index 919a758adbf179b58d3ac2b69ca62878ae5b6242..3ab665d576e5e215f0450782d61cde1a1cf258f0 100644 (file)
@@ -102,7 +102,6 @@ void of_cancel_id(const struct optioninfo *oi, const char *arg);
 void sysfail(const char *what, int errnoval) NONRETURNING;
 void usageerr(const char *what, ...) NONRETURNPRINTFFORMAT(1,2);
 void outerr(void) NONRETURNING;
-void setnonblock(int fd, int nonblock);
 
 void *xmalloc(size_t sz);
 char *xstrsave(const char *str);