home *** CD-ROM | disk | FTP | other *** search
/ PC-Online 1996 May / PCOnline_05_1996.bin / linux / source / n / bind / bind-4.001 / bind-4~ / bind-4.9.3-BETA9 / contrib / named-lint / named-lint.y < prev    next >
Text File  |  1993-12-05  |  14KB  |  667 lines

  1. %{
  2. #include <stdio.h>
  3. #include <string.h>
  4.  
  5. #ifndef YYDEBUG
  6. #define YYDEBUG 1
  7. #endif
  8.  
  9. #define True 1
  10. #define False 0
  11. int    restofline=False;    /* eat till the \n */
  12. int    justtokens=0;        /* >0 - want tokens not NUM NAMES... */
  13.                 /* <0 - want tokens and keywords */
  14.                 /* =0 - no tokens */
  15. int lldebug=0;            /* !=0 lexical debugging */
  16. int dup_ip=0;            /* check for duplicate ip addresses */
  17. FILE *nfd;
  18. FILE *cfd;
  19.  
  20. char *origin;
  21.  
  22. #define MAXNAME 256
  23. char host[MAXNAME];
  24.  
  25. int numrr;            /* number of RRs for this host */
  26. int numcname;            /* number of CNAME RRs for this host */
  27.  
  28. char *pgm;            /* name this program is invoked by */
  29. char *inname;            /* name of the input file */
  30.  
  31. extern FILE *yyin;        /* defined in scanner */
  32. extern char *yytext;        /* defined in scanner */
  33. extern int yyleng;        /* defined in scanner */
  34.  
  35. struct inaddr {
  36.   unsigned char b1, b2, b3, b4;
  37. };
  38. %}
  39.  
  40. %union {
  41.   int i;
  42.   char *c;
  43.   struct inaddr ia;
  44. }
  45. %token INCLUDE ORIGIN
  46. %token NUM NAME TOKEN RESTOFLINE
  47. %token IN
  48. %token A CNAME GID HINFO MB MG MINFO MR MX NS NULLRR
  49. %token PTR RP SOA TXT UID UINFO UNSPEC WKS AFSDB
  50. %token CAMPUS LOCATION MADDR PNAME OADDR
  51. %token OPHONE EXTENSION ORGANIZATION OWNER PERSON ROOM
  52.  
  53. %expect 1
  54.  
  55. %%
  56. input:    /* empty */
  57.     | input line comment '\n'
  58.     ;
  59.  
  60. line:    /* empty */
  61.     | nstmt        { numrr++;
  62.               if (numcname != 0 && numrr > numcname)
  63.                 yyerror("host has CNAME and other RRs"); 
  64.             }
  65.     | bstmt
  66.     | error
  67.     ;
  68.  
  69. comment: /* empty */
  70.     | cmnt
  71.     ;
  72.  
  73. cmnt:    ';' restofline
  74.     ;
  75.  
  76. restofline: {restofline = True;} RESTOFLINE {restofline = False;}
  77.  
  78. dname:    NAME        { $<c>$=$<c>1;}
  79.     | '@'        { $<c>$="@";}
  80.     | '.'        { $<c>$=".";}
  81.     ;
  82.  
  83. bstmt:    INCLUDE token
  84.             {/* copy new filename */} 
  85.         dname
  86.             { /* copy new origin */
  87.               /* indicate recursive parse */
  88.             }
  89.     | INCLUDE token
  90.             {/* copy new filename */} 
  91.  
  92.     | ORIGIN dname
  93.     ;
  94.  
  95. nstmt:    dname {(void)strcpy(host, $<c>1);  numrr = numcname = 0; }
  96.          stmt    {(void)fprintf(nfd, "%s\n", host);}
  97.     | stmt
  98.     ;
  99.  
  100. stmt:    NUM IN rr
  101.     | NUM rr
  102.     | IN rr
  103.     | rr
  104.     ;
  105.     
  106. services:  /* empty */
  107.     | services NAME
  108.         {/* make sure the name is a service */}
  109.     ;
  110.  
  111. mline:    /* empty */
  112.     | '\n'
  113.     | cmnt '\n'
  114.     ;
  115.  
  116. rr:      A addr cmnt
  117.         { 
  118.           if (dup_ip && iskeycmnt("noaddr", $<c>3))
  119.             (void)dup_check(host, origin, $<ia>2);
  120.         }
  121.     |  A addr
  122.         { if (dup_ip) (void)dup_check(host, origin, $<ia>2); }
  123.     | CNAME NAME
  124.         { 
  125.           numcname++;
  126.           if (nstrcmp(host, $<c>2) == 0)
  127.               yyerror("host name and alias/CNAME are the same");
  128.         }
  129.     | GID NUM
  130.     | HINFO token token
  131.     | MB NAME
  132.     | MG NAME
  133.     | MINFO NAME
  134.     | MR NAME
  135.     | MX NUM NAME
  136.     | NS NAME
  137.     | NULLRR
  138.     | PTR NAME
  139.     | RP NAME NAME
  140.     | AFSDB NUM NAME
  141.     | SOA NAME NAME '(' mline
  142.           NUM mline NUM mline NUM mline NUM mline NUM mline ')'
  143.     | TXT qtxtrr
  144.     | UID NUM
  145.     | UINFO '?'
  146.     | WKS addr NAME {/* check for proper protocol */} services
  147.     ;
  148.  
  149. qtxtrr:    '"' txtrr '"'
  150.     | txtrr
  151.     ;
  152.       
  153. txtrr:    LOCATION baddr
  154.     | MADDR token
  155.     | PNAME restofline
  156.     | OADDR baddr
  157.     | OPHONE PHONENUM
  158.     | ORGANIZATION whom
  159.     | OWNER restofline
  160.     | PERSON whom
  161.     | NAME restofline
  162.         { /* unknown TXT RR */ }
  163.     ;
  164.  
  165. whom:    NAME
  166.         {register char *p;
  167.          if ((p=strchr($<c>1, '.')) == NULL
  168.              || nstrcmp(p,".who.rutgers.edu") != 0)
  169.            yyerror("name doesn't end in .who.rutgers.edu");
  170.             }
  171.     ;
  172.  
  173. PHONENUM: phone EXTENSION NUM {if (yyleng!=4) yyerror("illegal extension");}
  174.     | phone
  175.     ;
  176.  
  177. phone:    NUM {if (yyleng!=3) yyerror("illegal area code");}
  178.         '-' NUM {if (yyleng!=3) yyerror("illegal exchange");}
  179.         '-' NUM {if (yyleng!=4) yyerror("illegal phone number");}
  180.     ;
  181.  
  182. addr:    NUM '.' NUM '.' NUM '.' NUM
  183.                 { 
  184.           int i,e=0;
  185.           if ((i=atoi($<c>1)) > 255) { e++; goto addr_r;}
  186.           $<ia>$.b1 = i;
  187.           if ((i=atoi($<c>3)) > 255) { e++; goto addr_r;}
  188.           $<ia>$.b2 = i;
  189.           if ((i=atoi($<c>5)) > 255) { e++; goto addr_r;}
  190.           $<ia>$.b3 = i;
  191.           if ((i=atoi($<c>7)) > 255) { e++; goto addr_r;}
  192.           $<ia>$.b4 = i;
  193.         addr_r:
  194.           if (e != 0)
  195.                     yyerror("illegal internet addr");
  196.         }
  197.     ;
  198.  
  199. baddr:    keytoks ROOM keytoks CAMPUS keytoks
  200.     ;
  201.  
  202. token:    {justtokens=1;} TOKEN {justtokens=0;}
  203.     ;
  204.  
  205. keytoks: {justtokens=-1;} toklst {justtokens=0;}
  206.     ;
  207.  
  208. toklst:    TOKEN
  209.     | toklst TOKEN
  210.     ;
  211. %%
  212. main(argc, argv)
  213.   int argc;
  214.   char *argv[];
  215. {
  216.   extern char *optarg;
  217.   extern int optind;
  218.   int c, aerr, e;
  219.  
  220.   /* command to check for duplicate host names */
  221.   static char ndup_cmd [] = "perl -e 'while (<>) {tr/A-Z/a-z/; $hosts{$_}++;'\
  222.                  -e 'if ($hosts{$_} > 1) { ' \
  223.                  -e 'print \"Duplicate host name $_\"; $v++; }' \
  224.                  -e '} exit($v);' ";
  225.  
  226.   pgm = *argv;
  227.   aerr = 0;
  228.   while ((c=getopt(argc, argv, "o:iLYh?")) != -1)
  229.     switch (c) {
  230.       case 'L':    lldebug++; break;
  231.       case 'Y':
  232. #ifdef YYDEBUG
  233.               yydebug++;
  234. #else !YYDEBUG
  235.         fprintf(stderr, "%s: not compiled with YYDEBUG, -Y ignored\n",
  236.             pgm);
  237. #endif !YYDEBUG
  238.         break;
  239.       case 'i': dup_ip++; break;
  240.       case 'o': origin = optarg; break;
  241.       case 'h':
  242.       case '?': aerr++;
  243.     }
  244.   if (aerr || ((optind+1) < argc)) {
  245.     fprintf(stderr, "usage: %s [-L] [-Y] [-o origin] [-i] [file-name]\n", pgm);
  246.     fprintf(stderr, "where:\tfile-name or stdinn is the input file\n");
  247.     fprintf(stderr, "\t-i = duplicate IP address checking\n");
  248.     fprintf(stderr, "\t-o = initialize the origin (ala $ORIGIN)\n");
  249.     fprintf(stderr, "\t-L = Lex debugging\n");
  250.     fprintf(stderr, "\t-Y = Yacc debugging\n");
  251.     exit(-1);
  252.   } else {
  253.     if (optind >= argc) {
  254.       inname = "<stdin>";
  255.     } else {
  256.       inname = argv[optind++];
  257.       yyin = fopen(inname, "r");
  258.       if (yyin == NULL) {
  259.     fprintf("%s: Can't open file named: '%s'\n", pgm, inname);
  260.     perror(pgm);
  261.     exit(-1);
  262.       }
  263.     }
  264.   }
  265.  
  266.   if ((nfd = popen(ndup_cmd, "w")) == NULL) {
  267.     (void)fprintf(stderr, "%s: can't execute dup name checker\n", pgm);
  268.     perror(pgm);
  269.     exit(2);
  270.   }
  271.  
  272.   if (dup_ip) {
  273. #if 0
  274.     static char dup_cmd[] = "sort -n +0 -1 +1 -2 +2 -3 +3 -4 \\\n\
  275.       | awk ' $1==l1 && $2==l2 && $3==l3 && $4==l4 { \\\n\
  276.       printf(\"duplicate IP address %d.%d.%d.%d, for: %s and %s\\n\",\\\n\
  277.                 l1, l2, l3, l4, l5, $5) } \\\n\
  278.       { l1=$1 ; l2=$2 ; l3=$3 ; l4=$4 ; l5=$5 } ' \\\n\
  279.     | tee /tmp/named-dup$$ \n\
  280.     if [ -s /tmp/named-dup$$ ]; then \n\
  281.       stat=1 \n\
  282.     else \n\
  283.       stat=0 \n\
  284.         fi \n\
  285.     rm -f /tmp/named-dup$$ \n\
  286.      exit $stat\n";
  287. #endif
  288.     static char dup_cmd[] = "/usr/local/bin/perl ./uniq-addr";
  289.     if ((cfd = popen(dup_cmd, "w")) == NULL) {
  290.       (void)fprintf(stderr, "%s: can't execute dup checker\n", pgm);
  291.       perror(pgm);
  292.       exit(2);
  293.     }      
  294. #if 0
  295.     if ((cfd = fopen("/tmp/named-dup.raw","w")) == NULL) {
  296.       (void)fprintf(stderr, "%s: can't open dup checker file: /tmp/named-dup.raw \n", pgm);
  297.       perror(pgm);
  298.       exit(2);
  299.     }      
  300. #endif
  301.   }
  302.   (void)yyparse();
  303.  
  304.   if ((e = pclose(nfd)) == -1)
  305.     yynerrs++;
  306.   else
  307.     yynerrs += (e >> 8);
  308.   
  309.  
  310.   if (dup_ip) {
  311. #if 1
  312.     if ((e=pclose(cfd)) == -1)
  313. #else
  314.     if ((e=fclose(cfd)) == -1)
  315. #endif
  316.       yynerrs++;
  317.     else
  318.       yynerrs += (e >> 8);    /* get the exit code not the whole status */
  319.   }
  320.   if (yynerrs != 0 )
  321.     (void)printf("%s: %d errors\n",pgm, yynerrs);
  322.   exit(yynerrs);
  323. }
  324.  
  325. /* write out the record needed by the dup_ip code */
  326. dup_check(host, origin, ia)
  327.   char host[], origin[];
  328.   struct inaddr ia;
  329. {            
  330.   (void)fprintf(cfd, "%3d %3d %3d %3d %s%",
  331.         ia.b1, ia.b2, ia.b3, ia.b4,
  332.         host);
  333.   if (origin!= NULL)
  334.     (void)fprintf(cfd, ".%s\n", origin);
  335.   else
  336.     (void)fputc('\n', cfd);
  337. }
  338.  
  339. /* compute the print size of a string 
  340.  * if the string is printed starting at column off figure tab expansion and
  341.  * count the size of the string
  342.  */
  343. int prtsize(str, off)
  344.   char str[];
  345.   int off;
  346. {
  347.   register char *s;
  348.   register int c;
  349.  
  350.   for (s=str, c=off; *s!=NULL; c++, s++)
  351.     if (*s == '\t')
  352.       c = (((c/8)+1)*8) - 1;
  353.   return (c);
  354. }
  355.  
  356. extern int yylineno;
  357. extern char linebuf[];
  358.  
  359. yyerror(s)
  360.   char s[];
  361. {
  362.   register char c;
  363.   register int i;
  364.  
  365.   (void)fprintf(stderr, "%s: %s on line %d, last recognized host name %s\n", 
  366.         pgm, s, yylineno, host);
  367.   i = prtsize(linebuf, strlen(pgm)+3); /* compute bogon pointer offset */
  368.   /* reset the lexcial flags to the initial state */
  369.   justtokens=0;
  370.   restofline++;
  371.   (void)yylex();        /* read the rest of the line */
  372.   restofline=0;
  373.   (void)fprintf(stderr, "%s: '%s'\n", pgm, linebuf);
  374.   for (; i>0; i--)        /* pad out bogon pointer */
  375.     (void)fputc(' ', stderr);
  376.   (void)fprintf(stderr, "^\n");
  377. }
  378.  
  379. #include <ctype.h>
  380.  
  381. /* check if the first word of a comment is the keyword */
  382. iskeycmnt(key,cmnt)
  383.   char key[], cmnt[];
  384. {
  385.   register char *c=cmnt+1;
  386.   char *s,t;
  387.   int r;
  388.  
  389.   while (*c == ' ' || *c == '\t') c++;
  390.   s=c;
  391.   while (isalpha(*c)) c++;
  392.   t=*c; *c=NULL;
  393.   r=nstrcmp(key, s);
  394.   *c=t;
  395.   return (r==0);
  396. }
  397.  
  398.  
  399. /* my lex replacement code */
  400.  
  401. #define iseol(c) ((c)=='\n')
  402.  
  403. FILE *yyin = {stdin};
  404. #define input() fgetc(yyin)
  405. #define unputc(c) ungetc(c, yyin)
  406.  
  407. yyinput() {return (input());}
  408. yyunputc(c) char c; {return (unputc(c));}
  409.  
  410. #define MAXTOKEN 500
  411. char linebuf[MAXTOKEN*10];    /* input line buffer */
  412. char *eline;            /* end of input line */
  413. char *yytext;            /* start of last 'token' */
  414. int eollast = True;        /* say a \n last */
  415. int yylineno=1;            /* line number */
  416. int yyleng;            /* length of the last token (NUM only) */
  417.  
  418. yylex()
  419. {
  420.   char *c;
  421.  
  422.   if (lldebug)
  423.     fprintf(stderr,"Entering yylex, justtokens=%d\n", justtokens);
  424.  
  425.   if (eollast && !restofline) {
  426.     yytext = linebuf;
  427.     eollast = False;
  428.   } else
  429.     yytext = eline;
  430.   c = yytext;
  431.  
  432.   for(;;) {
  433.     if (restofline) {
  434.       if (!eollast) {
  435.     while (! iseol(*c))
  436.       *++c=input();
  437.     unputc(*c);
  438.     *c = NULL;
  439.     eline = c;
  440.       }
  441.       return (RESTOFLINE);
  442.     }
  443.     *c=input();
  444.     if (*c == EOF)
  445.       return (0);
  446.     if (iseol(*c)) {
  447.       *c = NULL;
  448.       eollast++;
  449.       yylineno++; 
  450.       return ('\n');
  451.     }
  452.     if (isspace(*c)) {
  453.       do *++c=input(); while (isspace(*c) && (! iseol(*c))) ;
  454.       unputc(*c);
  455.       *c = NULL;
  456.       yytext = c;
  457.       continue;            /* just ignore the spaces */
  458.     }
  459.  
  460.     if (*c == '"')
  461.       goto special;
  462.  
  463.     if (justtokens) {
  464.       do *++c=input(); while (! isspace(*c) && ! iseol(*c) && *c != '"') ;
  465.       unputc(*c);
  466.       *c = NULL;
  467.       eline = c;
  468.       yylval.c = yytext;
  469.       if (justtokens>0)
  470.     return (TOKEN);
  471.       /* else, check for a keyword */
  472.       return (lookkey(yytext));
  473.     }
  474.  
  475.     if (isdigit(*c)) {
  476.       for (yyleng=0; isdigit(*c) ; yyleng++) 
  477.     *++c = input();
  478.       unputc(*c);
  479.       *c = NULL;
  480.       eline = c;
  481.       yylval.c = yytext;
  482.       return (NUM);
  483.     }
  484.     if (*c == '*') {
  485.       *++c = input();
  486.       if (*c == '.') {        /* an funny name? */
  487.     *++c = input();
  488.     if (! isalpha(*c)) {
  489.       unputc(*c--);
  490.       unputc(*c--);        /* put the '.' back also */
  491.     }
  492.       } else {
  493.     unputc(*c--);
  494.       }
  495.     }
  496.     if (isalpha(*c)) {
  497.       do *++c = input(); while (isalnum(*c) || *c=='.' || *c=='-') ;
  498.       if (*c == ':') {        /* maybe a TXT keyword? */
  499.     int r;
  500.     *++c = NULL;
  501.     if ((r=lookkey(yytext)) != TOKEN) {
  502.       eline = c;        /* yes */
  503.       return (r);
  504.     }
  505.     c--;            /* no, unput ':', test for other keywords */
  506.       }
  507.       unputc(*c);
  508.       *c = NULL;
  509.       eline = c;
  510.       yylval.c = yytext;
  511.       return (lookup(yytext));
  512.     }
  513.     if (*c == '$') {
  514.       do *++c = input(); while (isalnum(*c)) ;
  515.       unputc(*c);
  516.       *c = NULL;
  517.       eline = c;
  518.       if (nstrcmp(yytext, "$include") == 0)
  519.     return (INCLUDE);
  520.       if (nstrcmp(yytext, "$origin") == 0)
  521.     return (ORIGIN);
  522.       return (TOKEN);
  523.     }
  524.   special:
  525.     eline = c;
  526.     *++eline = NULL;
  527.     return (*c);
  528.   }
  529. }
  530.  
  531. #define lc(c) (isupper(c)?tolower(c):(c))
  532.  
  533. /* case insensitive string compare (ala. strcmp(3)) */
  534. nstrcmp(str1, str2)
  535.   char str1[], str2[];
  536. {
  537.   register char *s, *t;
  538.   for (s=str1, t=str2; *s!=NULL && *t!=NULL && lc(*s)==lc(*t); s++, t++) ;
  539.   if (*s==NULL)
  540.     if (*t==NULL) {
  541.       return (0);
  542.     } else {
  543.       return (-1);
  544.     }
  545.   return (1);
  546. }
  547.  
  548. /* symbol tables */
  549.  
  550. #define SYM struct sym
  551. SYM {
  552.   char *key;
  553.   int token;
  554. };
  555.  
  556. SYM dict[] = {
  557.   {"a", A},
  558.   {"cname", CNAME},
  559.   {"gid", GID},
  560.   {"hinfo", HINFO},
  561.   {"in", IN},
  562.   {"mb", MB},
  563.   {"mg", MG},
  564.   {"mr", MR},
  565.   {"mx", MX},
  566.   {"ns", NS},
  567.   {"null", NULLRR},
  568.   {"ptr", PTR},
  569.   {"rp", RP},
  570.   {"soa", SOA},
  571.   {"txt", TXT},
  572.   {"afsdb", AFSDB},
  573.   {"uid", UID},
  574.   {"uinfo", UINFO},
  575.   {"unspec", UNSPEC},
  576.   {"wks", WKS}
  577. };
  578. #define DICTSIZE (sizeof(dict)/sizeof(SYM))
  579.  
  580. SYM tdict[] = {
  581.   {"campus:", CAMPUS},
  582.   {"location:", LOCATION},
  583.   {"mailaddr:", MADDR},
  584.   {"name:", PNAME},
  585.   {"officeaddr:", OADDR},
  586.   {"extension:", EXTENSION},
  587.   {"officephone:", OPHONE},
  588.   {"organization:", ORGANIZATION},
  589.   {"owner:", OWNER},
  590.   {"person:", PERSON},
  591.   {"room:", ROOM},
  592. };
  593. #define TDICTSIZE (sizeof(tdict)/sizeof(SYM))
  594.  
  595.  
  596. int dict_compare(sym1, sym2)
  597.   SYM *sym1, *sym2;
  598. {
  599.   return strcmp(sym1->key, sym2->key);
  600. }
  601.  
  602. #ifdef NOPE
  603. char *bsearch(key, base, nel, keysize, compar)
  604.   char *key, *base;
  605.   unsigned nel;
  606.   int keysize;
  607.   int (*compar)();
  608. {
  609.   register char *b;
  610.   register i=nel;
  611.   for (b=base, i=0; i<=nel; i++, b+=keysize)
  612.     if ((*compar)(key, b) == 0)
  613.       return (b);
  614. }
  615. #endif NOPE
  616.  
  617. lookkey(t)
  618.   char t[];
  619. {
  620.   SYM *d, e;
  621.   char name[MAXNAME];
  622.   register char *f, *n;
  623.  
  624.   /* lowercase input */
  625.   for (f=t, n=name; *f!=NULL; f++, n++)
  626.     *n = (isupper(*f))?tolower(*f):*f;
  627.   *n=NULL;
  628.     
  629.   e.key = name;
  630.  
  631.   d = (SYM *)bsearch((char *)(&e), (char *)tdict, TDICTSIZE,
  632.              sizeof(SYM), dict_compare);
  633.   if (d != (SYM *)NULL)
  634.     return (d->token);
  635.   return (TOKEN);
  636. }
  637.  
  638. lookup(t)
  639.   char t[];
  640. {
  641.   SYM *d, e;
  642.   char name[MAXNAME];
  643.   register char *f, *n;
  644.  
  645.   /* lowercase input */
  646.   for (f=t, n=name; *f!=NULL; f++, n++)
  647.     *n = (isupper(*f))?tolower(*f):*f;
  648.   *n=NULL;
  649.     
  650.   e.key = name;
  651.                /* key          base   nel */
  652.   d = (SYM *)bsearch((char *)(&e), (char *)dict, DICTSIZE,
  653.              /* sizeof(*key)     commpar */
  654.              sizeof(SYM), dict_compare);
  655.   if (d != (SYM *)NULL)
  656.     return(d->token);
  657.  
  658.   d = (SYM *)bsearch((char *)(&e), (char *)tdict, TDICTSIZE,
  659.              sizeof(SYM), dict_compare);
  660.   if (d != (SYM *)NULL)
  661.     return(d->token);
  662.   return(NAME);
  663. }
  664.  
  665. stophere()
  666. {return;}
  667.