home *** CD-ROM | disk | FTP | other *** search
/ ftp.ee.lbl.gov / 2014.05.ftp.ee.lbl.gov.tar / ftp.ee.lbl.gov / hf-1.2.tar.gz / hf-1.2.tar / hf-1.2 / hf.l < prev    next >
Text File  |  2009-12-09  |  20KB  |  1,035 lines

  1. N              [0-9]
  2. O              ({N}{1,3})
  3.  
  4. C              [0-9A-Fa-f]
  5. H              ({C}{1,4})
  6.  
  7.     #include <sys/types.h>
  8.     #include <sys/socket.h>
  9.     #include <sys/time.h>
  10.     #include <sys/stat.h>
  11.  
  12.     #include <netinet/in.h>
  13.  
  14.     #include <arpa/inet.h>
  15.     #include <arpa/nameser.h>
  16.  
  17.     #include <ctype.h>
  18.     #include <errno.h>
  19.     #ifdef HAVE_MEMORY_H
  20.     #include <memory.h>
  21.     #endif
  22.     #include <netdb.h>
  23.     #include <resolv.h>
  24.     #include <setjmp.h>
  25.     #include <signal.h>
  26.     #include <stdio.h>
  27.     #include <string.h>
  28.     #include <unistd.h>
  29.  
  30.     #include "gnuc.h"
  31.     #ifdef HAVE_OS_PROTO_H
  32.     #include "os-proto.h"
  33.     #endif
  34.  
  35.     #include "nb_dns.h"
  36.     #include "setsignal.h"
  37.     #include "version.h"
  38.  
  39.     #undef yywrap
  40.     #ifdef FLEX_SCANNER
  41.     #define YY_NO_UNPUT
  42.     #endif
  43.     int yywrap(void);
  44.     int yylex(void);
  45.     void convert(const char *, int);
  46.  
  47.     #ifdef HAVE_ASYNC_DNS
  48.     #define ECHO \
  49.     if (!lookup_pass) { (void) fwrite( yytext, yyleng, 1, yyout ); }
  50.     int lookup_pass;        /* true if lookup only */
  51.     #endif
  52.     int linemode;        /* convert at most one entry per line */
  53.     int triedone;
  54.  
  55. %%
  56.  
  57.  
  58. ::{O}(\.{O}){3}        convert(yytext, 1);
  59. {O}(\.{O}){3}        convert(yytext, 0);
  60.  
  61. {H}(:{H}){7}        convert(yytext, 1);
  62. {H}:(:{H}){1,6}        convert(yytext, 1);
  63. ({H}:){2}(:{H}){1,5}    convert(yytext, 1);
  64. ({H}:){3}(:{H}){1,4}    convert(yytext, 1);
  65. ({H}:){4}(:{H}){1,3}    convert(yytext, 1);
  66. ({H}:){5}(:{H}){1,2}    convert(yytext, 1);
  67. ({H}:){6}:{H}        convert(yytext, 1);
  68.  
  69. ({O}\.){1,3}        ECHO;        /* anti-backtrack */
  70. {O}((\.{O}){1,2})    ECHO;        /* anti-backtrack */
  71.  
  72. {N}+            ECHO;
  73. [^0-9\n]+        ECHO;
  74. [^0-9\n]+\n        {
  75.             ECHO;
  76.             triedone = 0;
  77.             }
  78.  
  79. \n            {
  80.             ECHO;
  81.             triedone = 0;
  82.             }
  83.  
  84. %%
  85.  
  86. /*
  87.  * Copyright (c) 1989, 1990, 1991, 1992, 1993, 1994, 1996, 1998, 1999, 2000, 2001, 2002, 2004, 2005, 2009
  88.  *    The Regents of the University of California.  All rights reserved.
  89.  *
  90.  * Redistribution and use in source and binary forms, with or without
  91.  * modification, are permitted provided that: (1) source code distributions
  92.  * retain the above copyright notice and this paragraph in its entirety, (2)
  93.  * distributions including binary code include the above copyright notice and
  94.  * this paragraph in its entirety in the documentation or other materials
  95.  * provided with the distribution, and (3) all advertising materials mentioning
  96.  * features or use of this software display the following acknowledgement:
  97.  * ``This product includes software developed by the University of California,
  98.  * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
  99.  * the University nor the names of its contributors may be used to endorse
  100.  * or promote products derived from this software without specific prior
  101.  * written permission.
  102.  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
  103.  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
  104.  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  105.  */
  106.  
  107. #ifndef lint
  108. static const char copyright[] =
  109.     "@(#) Copyright (c) 1989, 1990, 1991, 1992, 1993, 1994, 1996, 1998, 1999, 2000, 2001, 2002, 2004, 2005, 2009\n\
  110. The Regents of the University of California.  All rights reserved.\n";
  111. static const char rcsid[] =
  112.     "@(#) $Id: hf.l 175 2009-12-09 18:59:04Z leres $ (LBL)";
  113. #endif
  114.  
  115.  
  116. #define HSIZE 8192        /* must be a power of two */
  117.  
  118. struct htable {
  119.     char addr[NS_IN6ADDRSZ];
  120.     int af;            /* address family */
  121.     int alen;
  122.     int state;
  123.     char *name;        /* overloaded variable */
  124.     struct htable *next;
  125. } htable[HSIZE];
  126.  
  127. #define STATE_FREE    0    /* not in use */
  128. #define STATE_RAW    1    /* couldn't translate */
  129. #define STATE_SENTPTR    2
  130. #define STATE_HAVEPTR    3
  131. #define STATE_SENTA    4
  132. #define STATE_HAVEA    5
  133.  
  134. int strip = 1;            /* strip local domain when possible */
  135. int lcase = 1;            /* force lowercase */
  136. int shortdomain;        /* strip entire domain */
  137. const char defaultefmt[] = "%h";
  138. const char *efmt = defaultefmt;    /* expansion format */
  139. #ifdef HAVE_ASYNC_DNS
  140. int asyncdns;            /* 2 pass async dns hack */
  141. int numasync;            /* number of outstanding async requests */
  142. int asyncfd;
  143. #endif
  144. int networknumber;        /* convert to network numbers */
  145. int check;            /* check PTR's against A records */
  146. #ifdef DEBUG
  147. int debug = 0;
  148. #endif
  149.  
  150. int tmo;            /* seconds to wait for a answer from the dns */
  151. int doingdns;            /* true if we're waiting for the nameserver */
  152. jmp_buf alrmenv;        /* longjmp() buffer */
  153.  
  154. char *prog;
  155.  
  156. char domain[64];        /* current domain name (including '.') */
  157. int domainlen;            /* length of domain name */
  158.  
  159. char azero[NS_IN6ADDRSZ];
  160.  
  161. #ifdef HAVE_ASYNC_DNS
  162. struct nb_dns_info *nd;
  163. #endif
  164.  
  165. int targc;
  166. char **targv;
  167.  
  168. extern char *optarg;
  169. extern int optind, opterr;
  170.  
  171. /* ANSI C defines this */
  172. #ifndef __STDC__
  173. extern char *malloc();
  174. #endif
  175.  
  176. /* Forwards */
  177. char *a2h(const char *, int, int);
  178. char *addr2host(const char *, int, int);
  179. #ifdef HAVE_ASYNC_DNS
  180. void asyncreap(int);
  181. #endif
  182. struct htable *cacheaddr(const char *, int, int, int, const char *);
  183. #ifdef DEBUG
  184. void dump(void);
  185. #endif
  186. const char *format(const char *, const char *, const char *);
  187. int getdomain(void);
  188. struct htable *hash(const char *, int, int);
  189. #ifdef HAVE_ASYNC_DNS
  190. int ispipe(FILE *);
  191. #endif
  192. struct htable *lookupaddr(const char *, int, int);
  193. int main(int, char **);
  194. void massagename(char *);
  195. RETSIGTYPE timeout(int);
  196. void usage(void) __attribute__((noreturn));
  197.  
  198. int
  199. main(argc, argv)
  200.     int argc;
  201.     char **argv;
  202. {
  203.     char *cp;
  204.     int op;
  205. #ifdef HAVE_ASYNC_DNS
  206.     char errstr[NB_DNS_ERRSIZE];
  207. #endif
  208.  
  209.     if (argv[0] == NULL)
  210.         prog = "hf";
  211.     else if ((cp = strrchr(argv[0], '/')) != NULL)
  212.         prog = cp + 1;
  213.     else
  214.         prog = argv[0];
  215.  
  216.     opterr = 0;
  217.     while ((op = getopt(argc, argv, "1abcdf:ilnNt:")) != EOF)
  218.         switch (op) {
  219.  
  220.         case '1':
  221.             ++linemode;
  222.             break;
  223.  
  224.         case 'a':
  225. #ifdef HAVE_ASYNC_DNS
  226.             ++asyncdns;
  227. #else
  228.             fprintf(stderr,
  229.                 "%s: warning: -a not supported; ignored\n", prog);
  230. #endif
  231.             break;
  232.  
  233.         case 'b':
  234.             efmt = "%h(%i)";
  235.             break;
  236.  
  237.         case 'c':
  238.             ++check;
  239.             break;
  240.  
  241. #ifdef DEBUG
  242.         case 'd':
  243.             ++debug;
  244.             break;
  245. #endif
  246.  
  247.         case 'f':
  248.             if (*optarg == '\0')
  249.                 efmt = defaultefmt;
  250.             else
  251.                 efmt = optarg;
  252.             break;
  253.  
  254.         case 'i':
  255.             lcase = 0;
  256.             break;
  257.  
  258.         case 'l':
  259.             strip = 0;
  260.             break;
  261.  
  262.         case 'n':
  263. #ifdef notdef
  264.             ++networknumber;
  265. #else
  266.             fprintf(stderr, "%s: -n not currently impemented\n",
  267.                 prog);
  268.             exit(1);
  269. #endif
  270.             break;
  271.  
  272.         case 'N':
  273.             ++shortdomain;
  274.             break;
  275.  
  276.         case 't':
  277.             tmo = atoi(optarg);
  278.             if (tmo <= 0)
  279.                 usage();
  280.             break;
  281.  
  282.         default:
  283.             usage();
  284.         }
  285.  
  286. #ifdef HAVE_ASYNC_DNS
  287.     if (asyncdns) {
  288.         nd = nb_dns_init(errstr);
  289.         if (nd == NULL) {
  290.             fprintf(stderr, "%s: nb_dns_init: %s\n", prog, errstr);
  291.             exit(1);
  292.         }
  293.         asyncfd = nb_dns_fd(nd);
  294.         /* If no explicit timeout, use resolver retransmit */
  295.         if (tmo == 0)
  296.             tmo = _res.retrans;
  297.     }
  298. #endif
  299.  
  300.     /* Figure out our domain, if necessary */
  301.     if (!strip || shortdomain || !getdomain())
  302.         domain[0] = '\0';
  303.  
  304.     /* Up number of retries, we really want answers */
  305.     _res.retry = 20;
  306.  
  307.     /* Don't search, we'll use only FQDNs */
  308.     _res.options &= ~RES_DNSRCH;
  309.  
  310.     /* Setup alarm catcher if -t */
  311. #ifdef HAVE_ASYNC_DNS
  312.     if (!asyncdns)
  313. #endif
  314.         if (tmo > 0)
  315.             (void)setsignal(SIGALRM, timeout);
  316.  
  317.     /* Let yywrap() figure out if there are any arguments to open */
  318.     targc = argc - optind;
  319.     targv = &argv[optind];
  320.     yyin = NULL;
  321.     (void)yywrap();
  322.  
  323.     /* Process file opened by yywrap() or stdin if no arguments */
  324.     if (yyin) {
  325. #ifdef HAVE_ASYNC_DNS
  326.         /* XXX depends on the type of stdin */
  327.         /* XXX can we do a test rewind? */
  328. #ifdef notdef
  329.         if (asyncdns && yyin == stdin)
  330.             fprintf(stderr,
  331.                 "%s: warning: can't use -a on stdin\n", prog);
  332. #endif
  333. #endif
  334.         yylex();
  335.     }
  336.  
  337. #ifdef DEBUG
  338.     if (debug) {
  339.         fflush(stdout);
  340.         dump();
  341.     }
  342. #endif
  343.     exit(0);
  344. }
  345.  
  346. int
  347. yywrap()
  348. {
  349.     char *file;
  350.     static int didany = 0;
  351.  
  352.     /* Close file, if necessary */
  353.     if (yyin) {
  354. #ifdef HAVE_ASYNC_DNS
  355.         if (asyncdns) {
  356.             if (lookup_pass) {
  357.                 if (fseek(yyin, 0L, SEEK_SET) < 0) {
  358.                     fprintf(stderr,
  359.                         "%s: fseek/rewind: %s\n",
  360.                         prog, strerror(errno));
  361.                     exit(1);
  362.                 }
  363.                 yyrestart(yyin);
  364.                 lookup_pass = 0;
  365.                 asyncreap(1);
  366.                 return (0);
  367.             }
  368.             numasync = 0;
  369.         }
  370. #endif
  371.         if (yyin != stdin)
  372.             (void)fclose(yyin);
  373.         yyin = NULL;
  374.     }
  375.  
  376.     /* Spin through arguments until we run out or successfully open one */
  377.     while (targc > 0) {
  378.         file = targv[0];
  379.         --targc;
  380.         ++targv;
  381.         ++didany;
  382.         if ((yyin = fopen(file, "r")) != NULL) {
  383. #ifdef HAVE_ASYNC_DNS
  384.             if (asyncdns)
  385.                 lookup_pass = 1;
  386. #endif
  387.             return (0);
  388.         }
  389.         perror(file);
  390.     }
  391.     if (!didany) {
  392.         ++didany;
  393.         yyin = stdin;
  394. #ifdef HAVE_ASYNC_DNS
  395.         if (asyncdns) {
  396.             if (ispipe(yyin)) {
  397.                 fprintf(stderr,
  398.                     "%s: warning: can't use -a on a pipe\n",
  399.                     prog);
  400.                 asyncdns = 0;
  401.             } else
  402.                 lookup_pass = 1;
  403.         }
  404. #endif
  405.         return (0);
  406.     }
  407.     return (1);
  408. }
  409.  
  410. const char *
  411. format(const char *fmt, const char *hnstr, const char *ipstr)
  412. {
  413.     char *cp;
  414.     const char *cp2, *item;
  415.     size_t len, ilen, llen, dlen, nlen, hlen, itemlen;
  416.     static char buf[1024];
  417.  
  418.     /* ip address length */
  419.     ilen = strlen(ipstr);
  420.  
  421.     /* Normally we are passed the long hostname */
  422.     if (hnstr != NULL) {
  423.         /* Long hostname length */
  424.         llen = strlen(hnstr);
  425.  
  426.         /* Local domain truncated hostname length */
  427.         dlen = llen;
  428.         if (*domain != '\0') {
  429.             cp2 = hnstr + (llen - domainlen);
  430.             if (cp2 > hnstr && strcasecmp(cp2, domain) == 0)
  431.                 dlen = cp2 - hnstr;
  432.         }
  433.  
  434.         /* Local domain truncated hostname length */
  435.         cp = strchr(hnstr, '.');
  436.         if (cp == NULL)
  437.             nlen = llen;
  438.         else
  439.             nlen = cp - hnstr;
  440.  
  441.         /* Default hostname length */
  442.         if (shortdomain)
  443.             hlen = nlen;
  444.         else
  445.             hlen = dlen;
  446.     } else {
  447.         /* We only have the ip address string */
  448.         hnstr = ipstr;
  449.         llen = strlen(hnstr);
  450.         dlen = llen;
  451.         nlen = llen;
  452.         hlen = llen;
  453.     }
  454.  
  455.     cp = buf;
  456.     /* Leave room for EOS */
  457.     len = sizeof(buf) - 1;
  458.     cp2 = fmt;
  459.     while (*cp2 != '\0' && len > 0) {
  460.         if (*cp2 != '%') {
  461.             *cp++ = *cp2++;
  462.             --len;
  463.             continue;
  464.         }
  465.         ++cp2;
  466.         switch (*cp2) {
  467.  
  468.         case 'h':
  469.             /* Default hostname */
  470.             item = hnstr;
  471.             itemlen = hlen;
  472.             break;
  473.  
  474.         case 'D':
  475.             /* Local domain truncated hostname */
  476.             item = hnstr;
  477.             itemlen = dlen;
  478.             break;
  479.  
  480.         case 'N':
  481.             /* Domain truncated hostname */
  482.             item = hnstr;
  483.             itemlen = nlen;
  484.             break;
  485.  
  486.         case 'i':
  487.             /* ip address */
  488.             item = ipstr;
  489.             itemlen = ilen;
  490.             break;
  491.  
  492.         case 'l':
  493.             /* Long hostname */
  494.             item = hnstr;
  495.             itemlen = llen;
  496.             break;
  497.  
  498.         default:
  499.             /* Random character */
  500.             *cp++ = *cp2++;
  501.             --len;
  502.             continue;
  503.         }
  504.         if (itemlen > len)
  505.             itemlen = len;
  506.         strncpy(cp, item, itemlen);
  507.         cp += itemlen;
  508.         len -= itemlen;
  509.         ++cp2;
  510.     }
  511.     *cp = '\0';
  512.  
  513.     return (buf);
  514. }
  515.  
  516. int
  517. getdomain()
  518. {
  519.     char *cp;
  520.     struct hostent *hp;
  521.     char host[128];
  522.  
  523.     if (gethostname(host, sizeof(host) - 1) < 0)
  524.         return (0);
  525.     if ((cp = strchr(host, '.')) == NULL) {
  526.         /* Not already canonical */
  527.         if (tmo > 0)
  528.             alarm(tmo);
  529.         doingdns = 1;
  530.         if (setjmp(alrmenv))
  531.             return (0);
  532.         hp = gethostbyname(host);
  533.         doingdns = 0;
  534.         if (hp == NULL)
  535.             return (0);
  536.         if ((cp = strchr(hp->h_name, '.')) == NULL)
  537.             return (0);
  538.     }
  539.     (void)strncpy(domain, cp, sizeof(domain));
  540.     domain[sizeof(domain) - 1] = '\0';
  541.     if (lcase)
  542.         for (cp = domain; *cp; ++cp)
  543.             if (isupper((int)*cp))
  544.                 *cp = tolower(*cp);
  545.     domainlen = strlen(domain);
  546.     return (1);
  547. }
  548.  
  549. RETSIGTYPE
  550. timeout(int signo)
  551. {
  552.  
  553.     if (doingdns) {
  554.         doingdns = 0;
  555.         longjmp(alrmenv, 1);
  556.     }
  557.     return RETSIGVAL;
  558. }
  559.  
  560. /* Convert address to hostname via the dns */
  561. char *
  562. a2h(const char *ap, int alen, int af)
  563. {
  564.     char **pp;
  565.     size_t len;
  566.     static struct hostent *hp;
  567.     static char *host = NULL;
  568.     static size_t hostlen = 0;
  569.  
  570.     /* Look up the PTR */
  571.     if (tmo > 0)
  572.         alarm(tmo);
  573.     doingdns = 1;
  574.     if (setjmp(alrmenv))
  575.         return (NULL);
  576.     hp = gethostbyaddr(ap, alen, af);
  577.     doingdns = 0;
  578.     if (hp == NULL)
  579.         return (NULL);
  580.  
  581.     len = strlen(hp->h_name) + 1;
  582.     if (hostlen < len) {
  583.         if (len < 132)
  584.             len = 132;
  585.         if (host == NULL)
  586.             host = malloc(len);
  587.         else
  588.             host = realloc(host, len);
  589.         if (host == NULL) {
  590.             hostlen = 0;
  591.             return (NULL);
  592.         }
  593.         hostlen = len;
  594.     }
  595.     (void)strcpy(host, hp->h_name);
  596.  
  597.     /* Done if we aren't checking */
  598.     if (!check)
  599.         return (host);
  600.  
  601. #ifndef HAVE_GETHOSTBYNAME2
  602.     if (af != AF_INET)
  603.         return (NULL);
  604. #endif
  605.  
  606.     /* Check PTR against the A record */
  607.     if (tmo > 0)
  608.         alarm(tmo);
  609.     doingdns = 1;
  610.     if (setjmp(alrmenv))
  611.         return (NULL);
  612. #ifdef HAVE_GETHOSTBYNAME2
  613.     hp = gethostbyname2(host, af);
  614. #else
  615.     hp = gethostbyname(host);
  616. #endif
  617.     doingdns = 0;
  618.     if (hp == NULL)
  619.         return (NULL);
  620.     if (af != hp->h_addrtype)
  621.         return (NULL);
  622.  
  623.     /* Spin through ip addresses looking for a match */
  624.     for (pp = hp->h_addr_list; *pp != NULL; ++pp)
  625.         if (memcmp(ap, *pp, alen) == 0)
  626.             return (host);
  627.  
  628.     return (NULL);
  629. }
  630.  
  631. /* Convert address to hostname via the cache and/or dns */
  632. char *
  633. addr2host(const char *ap, int alen, int af)
  634. {
  635.     int state;
  636.     char *host;
  637.     struct htable *p;
  638.  
  639.     /* First look in hash table */
  640.     p = lookupaddr(ap, alen, af);
  641.     if (p != NULL)
  642.         return (p->name);
  643.  
  644.     /* Lookup this host */
  645.     host = a2h(ap, alen, af);
  646.     state = STATE_RAW;
  647.     if (host != NULL) {
  648.         if (check)
  649.             state = STATE_HAVEA;
  650.         else
  651.             state = STATE_HAVEPTR;
  652.         massagename(host);
  653.     }
  654.  
  655.     p = cacheaddr(ap, state, alen, af, host);
  656.     if (p != NULL)
  657.         return (p->name);
  658.  
  659.     return (host);
  660. }
  661.  
  662. /* Look hash table entry for address */
  663. struct htable *
  664. lookupaddr(const char *ap, int alen, int af)
  665. {
  666.     struct htable *p;
  667.  
  668.     for (p = hash(ap, alen, af); p != NULL; p = p->next)
  669.         if (p->af == af && memcmp(p->addr, ap, alen) == 0)
  670.             return (p);
  671.     return (NULL);
  672. }
  673.  
  674. void
  675. massagename(char *name)
  676. {
  677.     char *cp;
  678.  
  679.     if (lcase)
  680.         for (cp = name; *cp; ++cp)
  681.             if (isupper((int)*cp))
  682.                 *cp = tolower(*cp);
  683. }
  684.  
  685. struct htable *
  686. cacheaddr(const char *ap, int state, int alen, int af, const char *host)
  687. {
  688.     struct htable *p, *p2;
  689.  
  690.     /* Don't cache zero */
  691.     if (memcmp(ap, azero, alen) == 0)
  692.         return (NULL);
  693.  
  694.     /* Look for existing slot in hash table */
  695.     for (p = hash(ap, alen, af); p != NULL; p = p->next)
  696.         if (p->state != STATE_FREE &&
  697.             p->af == af &&
  698.             memcmp(p->addr, ap, alen) == 0)
  699.             break;
  700.  
  701.     /* Allocate a new slot */
  702.     if (p == NULL) {
  703.         p = hash(ap, alen, af);
  704.         if (p->state != STATE_FREE) {
  705.             /* Handle the collision */
  706.             p2 = (struct htable *)malloc(sizeof(struct htable));
  707.             /* Lose, lose */
  708.             if (p2 == NULL)
  709.                 return (NULL);
  710.             memset((char *)p2, 0, sizeof(struct htable));
  711.             p2->next = p->next;
  712.             p->next = p2;
  713.             p = p2;
  714.         }
  715.     }
  716.  
  717.     /* Install new host */
  718.     memmove(p->addr, ap, alen);
  719.     p->alen = alen;
  720.     p->af = af;
  721.     if (host != NULL)
  722.         p->name = strdup(host);
  723.     if (state != 0)
  724.         p->state = state;
  725.     if (p->state == STATE_FREE)
  726.         abort();
  727.  
  728.     /* Return answer entry */
  729.     return (p);
  730. }
  731.  
  732. #ifdef DEBUG
  733. void
  734. dump()
  735. {
  736.     char *cp;
  737.     int i, j, n, d;
  738.     struct htable *p, *p2;
  739.     char buf[132];
  740.  
  741.     d = n = 0;
  742.     for (p = htable, i = 0; i < HSIZE; ++p, ++i)
  743.         if (p->name) {
  744.             ++n;
  745.             j = 0;
  746.             for (p2 = p; p2; p2 = p2->next) {
  747.                 if ((cp = p2->name) == NULL)
  748.                     cp = "<nil>";
  749.                 else if (cp == (char *)1)
  750.                     cp = "<raw>";
  751.                 (void)fprintf(stderr, "%4d:%d ", i, j);
  752.                 if (inet_ntop(p2->af, p2->addr,
  753.                     buf, sizeof(buf)) == NULL)
  754.                     (void)fprintf(stderr, "?");
  755.                 else
  756.                     (void)fprintf(stderr, "%s", buf);
  757.                 switch (p2->state) {
  758.  
  759.                 case STATE_HAVEA:
  760.                     (void)fprintf(stderr, " HAVEA");
  761.                     break;
  762.  
  763.                 case STATE_HAVEPTR:
  764.                     (void)fprintf(stderr, " HAVEPTR");
  765.                     break;
  766.  
  767.                 case STATE_SENTPTR:
  768.                     (void)fprintf(stderr, " SENTPTR");
  769.                     break;
  770.  
  771.                 case STATE_RAW:
  772.                     (void)fprintf(stderr, " RAW");
  773.                     break;
  774.  
  775.                 default:
  776.                     (void)fprintf(stderr, " #%d",
  777.                         p2->state);
  778.                     break;
  779.                 }
  780.                 (void)fprintf(stderr, " \"%s\"\n", cp);
  781.                 ++d;
  782.                 ++j;
  783.             }
  784.         }
  785.     d -= n;
  786.     (void)fprintf(stderr, "%d entries (%d dynamically linked)\n", n, d);
  787. }
  788. #endif
  789.  
  790. #ifdef HAVE_ASYNC_DNS
  791. void
  792. asyncreap(int ateof)
  793. {
  794.     char *host;
  795.     int n;
  796.     char **pp;
  797.     struct htable *p;
  798.     struct nb_dns_result *nr;
  799.     struct hostent *hp;
  800.     fd_set fds;
  801.     struct timeval to;
  802.     char errstr[NB_DNS_ERRSIZE];
  803.     struct nb_dns_result xxxnr;
  804.  
  805.     nr = &xxxnr;
  806.     memset(nr, 0, sizeof(*nr));
  807.     while (numasync > 0) {
  808.         FD_ZERO(&fds);
  809.         FD_SET(asyncfd, &fds);
  810.         /* If we're not at EOF, just poll */
  811.         if (!ateof) {
  812.             to.tv_sec = 0;
  813.             to.tv_usec = 0;
  814.         } else {
  815.             to.tv_sec = tmo;
  816.             to.tv_usec = 0;
  817.         }
  818.         n = select(asyncfd + 1, &fds, NULL, NULL, &to);
  819.         if (n < 0) {
  820.             fprintf(stderr, "%s: select: %s\n",
  821.                 prog, strerror(errno));
  822.             exit(1);
  823.         }
  824.  
  825.         /* Done if timed out */
  826.         if (n == 0)
  827.             break;
  828.  
  829.         n = nb_dns_activity(nd, nr, errstr);
  830.         if (n < 0) {
  831.             fprintf(stderr, "%s: nb_dns_activity: %s\n",
  832.                 prog, errstr);
  833.             exit(1);
  834.         }
  835.  
  836.         /* Bail if reply doesn't match any current queries */
  837.         if (n == 0)
  838.             continue;
  839.  
  840.         /* Decrement outstanding request counter */
  841.         --numasync;
  842.  
  843.         /* Bail if not a good answer */
  844.         if (nr->host_errno != NETDB_SUCCESS)
  845.             continue;
  846.  
  847.         /* Bail if no hostname (probably shouldn't happen) */
  848.         hp = nr->hostent;
  849.         host = hp->h_name;
  850.         if (host == NULL)
  851.             continue;
  852.  
  853.         /* Recover hash table pointer */
  854.         p = (struct htable *)nr->cookie;
  855.  
  856.         switch (p->state) {
  857.  
  858.         case STATE_SENTPTR:
  859.             /* Are we done? */
  860.             if (!check) {
  861.                 p->state = STATE_HAVEPTR;
  862.                 break;
  863.             }
  864.  
  865.             /* Now look up the A record */
  866.             if (nb_dns_host_request2(nd, host, p->af,
  867.                 (void *)p, errstr) < 0) {
  868.                 fprintf(stderr, "%s: nb_dns_host_request: %s\n",
  869.                     prog, errstr);
  870.                 p->state = STATE_RAW;
  871.                 free(p->name);
  872.                 p->name = NULL;
  873.                 break;
  874.             }
  875.  
  876.             /* Cache the fact that we're looking */
  877.             ++numasync;
  878.             p->state = STATE_SENTA;
  879.             break;
  880.  
  881.         case STATE_SENTA:
  882.             /* Check A against our address */
  883.             if (p->af != hp->h_addrtype) {
  884.                 p->state = STATE_RAW;
  885.                 free(p->name);
  886.                 p->name = NULL;
  887.                 break;
  888.             }
  889.  
  890.             /* Spin through ip addresses looking for a match */
  891.             for (pp = hp->h_addr_list; *pp != NULL; ++pp)
  892.                 if (memcmp(p->addr, *pp, p->alen) == 0)
  893.                     break;
  894.  
  895.             if (pp == NULL) {
  896.                 p->state = STATE_RAW;
  897.                 free(p->name);
  898.                 p->name = NULL;
  899.                 break;
  900.             }
  901.             p->state = STATE_HAVEA;
  902.             break;
  903.  
  904.         default:
  905.             abort();
  906.         }
  907.         massagename(host);
  908.         if (p->name != NULL)
  909.             abort();
  910.         if (host != NULL)
  911.             p->name = strdup(host);
  912.     }
  913. }
  914. #endif
  915.  
  916. void
  917. convert(const char *ipstr, int isv6)
  918. {
  919.     const char *hnstr;
  920.     int alen;
  921.     int af;
  922. #ifdef HAVE_ASYNC_DNS
  923.     struct htable *p;
  924.     char errstr[NB_DNS_ERRSIZE];
  925.     static int num = 0;
  926. #endif
  927.     char addr[NS_IN6ADDRSZ];
  928.  
  929.     if (isv6) {
  930. #ifdef AF_INET6
  931.         af = AF_INET6;
  932.         alen = NS_IN6ADDRSZ;
  933. #else
  934. #ifdef HAVE_ASYNC_DNS
  935.         if (!asyncdns || !lookup_pass)
  936. #endif
  937.             fputs(ipstr, stdout);
  938.         return;
  939. #endif
  940.     } else {
  941.         af = AF_INET;
  942.         alen = NS_INADDRSZ;
  943.     }
  944.  
  945. #ifdef HAVE_ASYNC_DNS
  946.     if (asyncdns && lookup_pass) {
  947.         if (inet_pton(af, ipstr, addr) != 1)
  948.             return;
  949.  
  950.         /* Done if already in hash table */
  951.         if (lookupaddr(addr, alen, af) != NULL)
  952.             return;
  953.  
  954.         p = cacheaddr(addr, STATE_SENTPTR, alen, af, NULL);
  955.         if (p == NULL)
  956.             return;
  957.  
  958.         if (nb_dns_addr_request2(nd, addr, af,
  959.             (void *)p, errstr) >= 0) {
  960.             /* Cache the fact that we're looking */
  961.             ++numasync;
  962.             ++num;
  963.         } else
  964.             fprintf(stderr, "%s: nb_dns_host_request: %s\n",
  965.                 prog, errstr);
  966.         /* reap replies after we send a number of queries */
  967.         if (num > 10) {
  968.             asyncreap(0);
  969.             num = 0;
  970.         }
  971.         return;
  972.     }
  973. #endif
  974.  
  975.     /* Only attempt to translate one address per line */
  976.     if (linemode && triedone) {
  977.         fputs(ipstr, stdout);
  978.         return;
  979.     }
  980.     ++triedone;
  981.  
  982.     if (inet_pton(af, ipstr, addr) == 1)
  983.         hnstr = addr2host(addr, alen, af);
  984.     else
  985.         hnstr = NULL;
  986.     fputs(format(efmt, hnstr, ipstr), stdout);
  987. }
  988.  
  989. struct htable *
  990. hash(const char *ap, int alen, int af)
  991. {
  992.     u_int32_t h;
  993.  
  994.     switch (alen) {
  995.  
  996.     case NS_INADDRSZ:
  997.         memmove(&h, ap, sizeof(h));
  998.         break;
  999.  
  1000.     case NS_IN6ADDRSZ:
  1001.         memmove(&h, ap + NS_IN6ADDRSZ - sizeof(h), sizeof(h));
  1002.         break;
  1003.  
  1004.     default:
  1005.         abort();
  1006.     }
  1007.     return (&htable[h & (HSIZE - 1)]);
  1008. }
  1009.  
  1010. #ifdef HAVE_ASYNC_DNS
  1011. int
  1012. ispipe(FILE *f)
  1013. {
  1014.     struct stat sbuf;
  1015.  
  1016.     if (fstat(fileno(f), &sbuf) < 0) {
  1017.         fprintf(stderr, "%s: fstat: %s\n", prog, strerror(errno));
  1018.         exit(1);
  1019.     }
  1020.     if ((sbuf.st_mode & S_IFMT) != S_IFREG)
  1021.         return (1);
  1022.     return (0);
  1023. }
  1024. #endif
  1025.  
  1026. void
  1027. usage()
  1028. {
  1029.  
  1030.     (void)fprintf(stderr, "Version %s\n", version);
  1031.     (void)fprintf(stderr, "usage: %s [-1abcdilN] [-t secs] [-f format]"
  1032.         " [file ...]\n", prog);
  1033.     exit(1);
  1034. }
  1035.