home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / bsd_srcs / usr.sbin / named / db_load.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-04-24  |  20.4 KB  |  969 lines

  1. /*
  2.  * Copyright (c) 1986, 1988, 1990 Regents of the University of California.
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms, with or without
  6.  * modification, are permitted provided that the following conditions
  7.  * are met:
  8.  * 1. Redistributions of source code must retain the above copyright
  9.  *    notice, this list of conditions and the following disclaimer.
  10.  * 2. Redistributions in binary form must reproduce the above copyright
  11.  *    notice, this list of conditions and the following disclaimer in the
  12.  *    documentation and/or other materials provided with the distribution.
  13.  * 3. All advertising materials mentioning features or use of this software
  14.  *    must display the following acknowledgement:
  15.  *    This product includes software developed by the University of
  16.  *    California, Berkeley and its contributors.
  17.  * 4. Neither the name of the University nor the names of its contributors
  18.  *    may be used to endorse or promote products derived from this software
  19.  *    without specific prior written permission.
  20.  *
  21.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  22.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  23.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  24.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  25.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  26.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  27.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  28.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  29.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  30.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  31.  * SUCH DAMAGE.
  32.  */
  33.  
  34. #ifndef lint
  35. static char sccsid[] = "@(#)db_load.c    4.38 (Berkeley) 3/2/91";
  36. #endif /* not lint */
  37.  
  38. /*
  39.  * Load data base from ascii backupfile.  Format similar to RFC 883.
  40.  */
  41.  
  42. #include <sys/param.h>
  43. #include <sys/time.h>
  44. #include <sys/stat.h>
  45. #include <netinet/in.h>
  46. #include <stdio.h>
  47. #include <syslog.h>
  48. #include <ctype.h>
  49. #include <netdb.h>
  50. #include <arpa/nameser.h>
  51. #include "ns.h"
  52. #include "db.h"
  53.  
  54. extern char *index();
  55. extern int max_cache_ttl;
  56.  
  57. /*
  58.  * Map class and type names to number
  59.  */
  60. struct map {
  61.     char    token[8];
  62.     int    val;
  63. };
  64.  
  65. struct map m_class[] = {
  66.     "in",        C_IN,
  67. #ifdef notdef
  68.     "any",        C_ANY,        /* any is a QCLASS, not CLASS */
  69. #endif
  70.     "chaos",    C_CHAOS,
  71.     "hs",        C_HS,
  72. };
  73. #define NCLASS (sizeof(m_class)/sizeof(struct map))
  74.  
  75. struct map m_type[] = {
  76.     "a",        T_A,
  77.     "ns",        T_NS,
  78.     "cname",    T_CNAME,
  79.     "soa",        T_SOA,
  80.     "mb",        T_MB,
  81.     "mg",        T_MG,
  82.     "mr",        T_MR,
  83.     "null",        T_NULL,
  84.     "wks",        T_WKS,
  85.     "ptr",        T_PTR,
  86.     "hinfo",    T_HINFO,
  87.     "minfo",    T_MINFO,
  88.     "mx",        T_MX,
  89.     "uinfo",    T_UINFO,
  90.     "txt",        T_TXT,
  91.     "uid",        T_UID,
  92.     "gid",        T_GID,
  93. #ifdef notdef
  94.     "any",        T_ANY,        /* any is a QTYPE, not TYPE */
  95. #endif
  96. #ifdef ALLOW_T_UNSPEC
  97.         "unspec",       T_UNSPEC,
  98. #endif ALLOW_T_UNSPEC
  99. };
  100. #define NTYPE (sizeof(m_type)/sizeof(struct map))
  101.  
  102. /*
  103.  * Parser token values
  104.  */
  105. #define CURRENT    1
  106. #define DOT    2
  107. #define AT    3
  108. #define DNAME    4
  109. #define INCLUDE    5
  110. #define ORIGIN    6
  111. #define ERROR    7
  112.  
  113. int    lineno;        /* current line number */
  114.  
  115. /*
  116.  * Load the database from 'filename'. Origin is appended to all domain
  117.  * names in the file.
  118.  */
  119. db_load(filename, in_origin, zp, doinginclude)
  120.     char *filename, *in_origin;
  121.     struct zoneinfo *zp;
  122. {
  123.     register u_char *cp;
  124.     register struct map *mp;
  125.     char domain[MAXDNAME];
  126.     char origin[MAXDNAME];
  127.     char tmporigin[MAXDNAME];
  128.     u_char buf[MAXDATA];
  129.     u_char data[MAXDATA];
  130.     u_char *cp1;
  131.     char *op;
  132.     int c;
  133.     int class, type, ttl, dbflags, dataflags;
  134.         int read_soa = 0;    /* number of soa's read */
  135.     struct databuf *dp;
  136.     FILE *fp;
  137.     int slineno, i, errs = 0, didinclude = 0;
  138.     register u_long n;
  139.     struct stat sb;
  140.  
  141. #ifdef DEBUG
  142.     if (debug)
  143.         fprintf(ddt,"db_load(%s, %s, %d, %d)\n",
  144.             filename, in_origin, zp - zones, doinginclude);
  145. #endif
  146.  
  147.     (void) strcpy(origin, in_origin);
  148.     if ((fp = fopen(filename, "r")) == NULL) {
  149.         syslog(LOG_ERR, "%s: %m", filename);
  150. #ifdef DEBUG
  151.         if (debug)
  152.             fprintf(ddt,"db_load: error opening file %s\n", filename);
  153. #endif
  154.         return (-1);
  155.     }
  156.     if (zp->z_type == Z_CACHE) {
  157.         dbflags = DB_NODATA | DB_NOHINTS;
  158.         dataflags = DB_F_HINT;
  159.     } else {
  160.         dbflags = DB_NODATA;
  161.         dataflags = 0;
  162.     }
  163.     gettime(&tt);
  164.     if (fstat(fileno(fp), &sb) < 0) {
  165.         syslog(LOG_ERR, "%s: %m", filename);
  166.         sb.st_mtime = (int)tt.tv_sec;
  167.     }
  168.     slineno = lineno;
  169.     lineno = 1;
  170.     domain[0] = '\0';
  171.     class = C_IN;
  172.     zp->z_state &= ~(Z_INCLUDE|Z_DB_BAD);
  173.     while ((c = gettoken(fp)) != EOF) {
  174.         switch (c) {
  175.         case INCLUDE:
  176.             if (!getword(buf, sizeof(buf), fp)) /* file name */
  177.                 break;
  178.             if (!getword(tmporigin, sizeof(tmporigin), fp))
  179.                 strcpy(tmporigin, origin);
  180.             else {
  181.                 makename(tmporigin, origin);
  182.                 endline(fp);
  183.             }
  184.             didinclude = 1;
  185.             errs += db_load(buf, tmporigin, zp, 1);
  186.             continue;
  187.  
  188.         case ORIGIN:
  189.             (void) strcpy((char *)buf, origin);
  190.             if (!getword(origin, sizeof(origin), fp))
  191.                 break;
  192. #ifdef DEBUG
  193.             if (debug > 3)
  194.                 fprintf(ddt,"db_load: origin %s, buf %s\n",
  195.                     origin, buf);
  196. #endif
  197.             makename(origin, buf);
  198. #ifdef DEBUG
  199.             if (debug > 3)
  200.                 fprintf(ddt,"db_load: origin now %s\n", origin);
  201. #endif
  202.             continue;
  203.  
  204.         case DNAME:
  205.             if (!getword(domain, sizeof(domain), fp))
  206.                 break;
  207.             n = strlen(domain) - 1;
  208.             if (domain[n] == '.')
  209.                 domain[n] = '\0';
  210.             else if (*origin) {
  211.                 (void) strcat(domain, ".");
  212.                 (void) strcat(domain, origin);
  213.             }
  214.             goto gotdomain;
  215.  
  216.         case AT:
  217.             (void) strcpy(domain, origin);
  218.             goto gotdomain;
  219.  
  220.         case DOT:
  221.             domain[0] = '\0';
  222.             /* fall thru ... */
  223.         case CURRENT:
  224.         gotdomain:
  225.             if (!getword(buf, sizeof(buf), fp)) {
  226.                 if (c == CURRENT)
  227.                     continue;
  228.                 break;
  229.             }
  230.             cp = buf;
  231.             ttl = 0;
  232.             if (isdigit(*cp)) {
  233.                 n = 0;
  234.                 do
  235.                     n = n * 10 + (*cp++ - '0');
  236.                 while (isdigit(*cp));
  237.                 if (zp->z_type == Z_CACHE) {
  238.                     /* this allows the cache entry to age */
  239.                     /* while sitting on disk (powered off) */
  240.                     if (n > max_cache_ttl)
  241.                     n = max_cache_ttl;
  242.                     n += sb.st_mtime;
  243.                 }
  244.                 ttl = n;
  245.                 if (!getword(buf, sizeof(buf), fp))
  246.                     break;
  247.             }
  248.             for (mp = m_class; mp < m_class+NCLASS; mp++)
  249.                 if (!strcasecmp((char *)buf, mp->token)) {
  250.                     class = mp->val;
  251.                     (void) getword(buf, sizeof(buf), fp);
  252.                     break;
  253.                 }
  254.             for (mp = m_type; mp < m_type+NTYPE; mp++)
  255.                 if (!strcasecmp((char *)buf, mp->token)) {
  256.                     type = mp->val;
  257.                     goto fndtype;
  258.                 }
  259. #ifdef DEBUG
  260.             if (debug)
  261.                 fprintf(ddt,"Line %d: Unknown type: %s.\n",
  262.                     lineno, buf);
  263. #endif
  264.             errs++;
  265.              syslog(LOG_ERR, "Line %d: Unknown type: %s.\n",
  266.                 lineno, buf);
  267.             break;
  268.         fndtype:
  269. #ifdef ALLOW_T_UNSPEC
  270.             /* Don't do anything here for T_UNSPEC...
  271.              * read input separately later
  272.              */
  273.                         if (type != T_UNSPEC) {
  274. #endif ALLOW_T_UNSPEC
  275.                 if (!getword(buf, sizeof(buf), fp))
  276.                 break;
  277. #ifdef DEBUG
  278.                 if (debug >= 3)
  279.                     fprintf(ddt,
  280.                     "d='%s', c=%d, t=%d, ttl=%d, data='%s'\n",
  281.                     domain, class, type, ttl, buf);
  282. #endif
  283. #ifdef ALLOW_T_UNSPEC
  284.                         }
  285. #endif ALLOW_T_UNSPEC
  286.             /*
  287.              * Convert the ascii data 'buf' to the proper format
  288.              * based on the type and pack into 'data'.
  289.              */
  290.             switch (type) {
  291.             case T_A:
  292.                 n = ntohl((u_long)inet_addr((char *)buf));
  293.                 cp = data;
  294.                 PUTLONG(n, cp);
  295.                 n = sizeof(u_long);
  296.                 break;
  297.  
  298.             case T_HINFO:
  299.                 n = strlen((char *)buf);
  300.                 if (n > 255) {
  301.                     syslog(LOG_WARNING,
  302.                     "%s: line %d: CPU type too long",
  303.                     filename, lineno);
  304.                     n = 255;
  305.                 }
  306.                 data[0] = n;
  307.                 bcopy(buf, (char *)data + 1, (int)n);
  308.                 n++;
  309.                 if (!getword(buf, sizeof(buf), fp))
  310.                     break;
  311.                 i = strlen((char *)buf);
  312.                 if (i > 255) {
  313.                     syslog(LOG_WARNING,
  314.                     "%s: line %d: OS type too long",
  315.                     filename, lineno);
  316.                     i = 255;
  317.                 }
  318.                 data[n] = i;
  319.                 bcopy(buf, data + n + 1, i);
  320.                 n += i + 1;
  321.                 endline(fp);
  322.                 break;
  323.  
  324.             case T_SOA:
  325.             case T_MINFO:
  326.                 (void) strcpy((char *)data, (char *)buf);
  327.                 makename(data, origin);
  328.                 cp = data + strlen((char *)data) + 1;
  329.                 if (!getword(cp,
  330.                     sizeof(data) - (cp - data),fp)) {
  331.                     n = cp - data;
  332.                     break;
  333.                 }
  334.                 makename(cp, origin);
  335.                 cp += strlen((char *)cp) + 1;
  336.                 if (type == T_MINFO) {
  337.                     n = cp - data;
  338.                     break;
  339.                 }
  340.                 if (getnonblank(fp) != '(')
  341.                     goto err;
  342.                 zp->z_serial = getnum(fp);
  343.                 n = (u_long) zp->z_serial;
  344.                 PUTLONG(n, cp);
  345.                 zp->z_refresh = getnum(fp);
  346.                 n = (u_long) zp->z_refresh;
  347.                 PUTLONG(n, cp);
  348.                 if (zp->z_type == Z_SECONDARY)
  349.                     zp->z_time = sb.st_mtime + zp->z_refresh;
  350.                 zp->z_retry = getnum(fp);
  351.                 n = (u_long) zp->z_retry;
  352.                 PUTLONG(n, cp);
  353.                 zp->z_expire = getnum(fp);
  354.                 n = (u_long) zp->z_expire;
  355.                 PUTLONG (n, cp);
  356.                 zp->z_minimum = getnum(fp);
  357.                 n = (u_long) zp->z_minimum;
  358.                 PUTLONG (n, cp);
  359.                 n = cp - data;
  360.                 if (getnonblank(fp) != ')')
  361.                     goto err;
  362.                                 read_soa++;
  363.                 endline(fp);
  364.                 break;
  365.  
  366.             case T_UID:
  367.             case T_GID:
  368.                 n = 0;
  369.                 cp = buf;
  370.                 while (isdigit(*cp))
  371.                     n = n * 10 + (*cp++ - '0');
  372.                 if (cp == buf)
  373.                     goto err;
  374.                 cp = data;
  375.                 PUTLONG(n, cp);
  376.                 n = sizeof(long);
  377.                 break;
  378.  
  379.             case T_WKS:
  380.                 /* Address */
  381.                 n = ntohl((u_long)inet_addr((char *)buf));
  382.                 cp = data;
  383.                 PUTLONG(n, cp);
  384.                 *cp = getprotocol(fp, filename);
  385.                 /* Protocol */
  386.                 n = sizeof(u_long) + sizeof(char);
  387.                 /* Services */
  388.                 n = getservices((int)n, data, fp, filename);
  389.                 break;
  390.  
  391.             case T_NS:
  392.             case T_CNAME:
  393.             case T_MB:
  394.             case T_MG:
  395.             case T_MR:
  396.             case T_PTR:
  397.                 (void) strcpy((char *)data, (char *)buf);
  398.                 makename(data, origin);
  399.                 n = strlen((char *)data) + 1;
  400.                 break;
  401.  
  402.             case T_UINFO:
  403.                 cp = (u_char *)index((char *)buf, '&');
  404.                 bzero(data, sizeof(data));
  405.                 if ( cp != NULL) {
  406.                     (void) strncpy((char *)data,
  407.                         (char *)buf, cp - buf);
  408.                     op = index(domain, '.');
  409.                     if ( op != NULL)
  410.                         (void) strncat((char *)data,
  411.                         domain,op-domain);
  412.                     else
  413.                         (void) strcat((char *)data,
  414.                             domain);
  415.                     (void) strcat((char *)data,
  416.                         (char *)++cp);
  417.                 } else
  418.                     (void) strcpy((char *)data,
  419.                         (char *)buf);
  420.                 n = strlen((char *)data) + 1;
  421.                 break;
  422.             case T_MX:
  423.                 n = 0;
  424.                 cp = buf;
  425.                 while (isdigit(*cp))
  426.                     n = n * 10 + (*cp++ - '0');
  427.                 /* catch bad values */
  428.                 if ((cp == buf) || (n > 65535))
  429.                     goto err;
  430.  
  431.                 cp = data;
  432.                 PUTSHORT((u_short)n, cp);
  433.  
  434.                 if (!getword(buf, sizeof(buf), fp))
  435.                         break;
  436.                 (void) strcpy((char *)cp, (char *)buf);
  437.                 makename(cp, origin);
  438.                 /* get pointer to place in data */
  439.                 cp += strlen((char *)cp) +1;
  440.  
  441.                 /* now save length */
  442.                 n = (cp - data);
  443.                 break;
  444.  
  445.             case T_TXT:
  446.                 i = strlen((char *)buf);
  447.                 cp = data;
  448.                 cp1 = buf;
  449.                 /*
  450.                  * there is expansion here so make sure we
  451.                  * don't overflow data
  452.                  */
  453.                 if (i > sizeof(data) * 255 / 256) {
  454.                     syslog(LOG_WARNING,
  455.                     "%s: line %d: TXT record truncated",
  456.                     filename, lineno);
  457.                     i = sizeof(data) * 255 / 256;
  458.                 }
  459.                 while (i > 255) {
  460.                     *cp++ = 255;
  461.                     bcopy(cp1, cp, 255);
  462.                     cp += 255;
  463.                     cp1 += 255;
  464.                     i -= 255;
  465.                 }
  466.                 *cp++ = i;
  467.                 bcopy(cp1, cp, i);
  468.                 cp += i;
  469.                 n = cp - data;
  470.                 endline(fp);
  471.                 break;
  472. #ifdef ALLOW_T_UNSPEC
  473.                         case T_UNSPEC:
  474.                                 {
  475.                                     int rcode;
  476.                                     fgets(buf, sizeof(buf), fp);
  477. #ifdef DEBUG
  478.                     if (debug)
  479.                                         fprintf(ddt, "loading T_UNSPEC\n");
  480. #endif DEBUG
  481.                                     if (rcode = atob(buf,
  482.                     strlen((char *)buf), data,
  483.                     sizeof(data), &n)) {
  484.                                         if (rcode == CONV_OVERFLOW) {
  485. #ifdef DEBUG
  486.                                             if (debug)
  487.                                                fprintf(ddt,
  488.                                   "Load T_UNSPEC: input buffer overflow\n");
  489. #endif DEBUG
  490.                         errs++;
  491.                                             syslog(LOG_ERR,
  492.                          "Load T_UNSPEC: input buffer overflow");
  493.                                          } else {
  494. #ifdef DEBUG
  495.                                             if (debug)
  496.                                                 fprintf(ddt,
  497.                            "Load T_UNSPEC: Data in bad atob format\n");
  498. #endif DEBUG
  499.                         errs++;
  500.                                             syslog(LOG_ERR,
  501.                            "Load T_UNSPEC: Data in bad atob format");
  502.                                          }
  503.                                     }
  504.                                 }
  505.                                 break;
  506. #endif ALLOW_T_UNSPEC
  507.  
  508.             default:
  509.                 goto err;
  510.             }
  511.             dp = savedata(class, type, (u_long)ttl, data, (int)n);
  512.             dp->d_zone = zp - zones;
  513.             dp->d_flags = dataflags;
  514.             if ((c = db_update(domain, dp, dp, dbflags,
  515.                (zp->z_type == Z_CACHE)? fcachetab : hashtab)) < 0) {
  516. #ifdef DEBUG
  517.                 if (debug && (c != DATAEXISTS))
  518.                     fprintf(ddt,"update failed\n");
  519. #endif
  520.             }
  521.             continue;
  522.  
  523.         case ERROR:
  524.             break;
  525.         }
  526.     err:
  527.         errs++;
  528.         syslog(LOG_ERR, "%s: line %d: database format error (%s)",
  529.             filename, lineno, buf);
  530. #ifdef DEBUG
  531.         if (debug)
  532.             fprintf(ddt,"%s: line %d: database format error ('%s', %d)\n",
  533.                 filename, lineno, buf, n);
  534. #endif
  535.         while ((c = getc(fp)) != EOF && c != '\n')
  536.             ;
  537.         if (c == '\n')
  538.             lineno++;
  539.     }
  540.     (void) fclose(fp);
  541.     lineno = slineno;
  542.     if (doinginclude == 0) {
  543.         if (didinclude) {
  544.             zp->z_state |= Z_INCLUDE;
  545.             zp->z_ftime = 0;
  546.         } else
  547.             zp->z_ftime = sb.st_mtime;
  548.         zp->z_lastupdate = sb.st_mtime;
  549.         if (zp->z_type != Z_CACHE && read_soa != 1) {
  550.             errs++;
  551.             if (read_soa == 0)
  552.                 syslog(LOG_ERR, "%s: no SOA record", filename);
  553.             else
  554.                 syslog(LOG_ERR, "%s: multiple SOA records",
  555.                     filename);
  556.         }
  557.     }
  558.     if (errs)
  559.         zp->z_state |= Z_DB_BAD;
  560.     return (errs);
  561. }
  562.  
  563. int gettoken(fp)
  564.     register FILE *fp;
  565. {
  566.     register int c;
  567.     char op[32];
  568.  
  569.     for (;;) {
  570.         c = getc(fp);
  571.     top:
  572.         switch (c) {
  573.         case EOF:
  574.             return (EOF);
  575.  
  576.         case '$':
  577.             if (getword(op, sizeof(op), fp)) {
  578.                 if (!strcasecmp("include", op))
  579.                     return (INCLUDE);
  580.                 if (!strcasecmp("origin", op))
  581.                     return (ORIGIN);
  582.             }
  583. #ifdef DEBUG
  584.             if (debug)
  585.                 fprintf(ddt,"Line %d: Unknown $ option: $%s\n", 
  586.                     lineno, op);
  587. #endif
  588.             syslog(LOG_ERR,"Line %d: Unknown $ option: $%s\n", 
  589.                 lineno, op);
  590.             return (ERROR);
  591.  
  592.         case ';':
  593.             while ((c = getc(fp)) != EOF && c != '\n')
  594.                 ;
  595.             goto top;
  596.  
  597.         case ' ':
  598.         case '\t':
  599.             return (CURRENT);
  600.  
  601.         case '.':
  602.             return (DOT);
  603.  
  604.         case '@':
  605.             return (AT);
  606.  
  607.         case '\n':
  608.             lineno++;
  609.             continue;
  610.  
  611.         default:
  612.             (void) ungetc(c, fp);
  613.             return (DNAME);
  614.         }
  615.     }
  616. }
  617.  
  618. /*
  619.  * Get next word, skipping blanks & comments.
  620.  */
  621. getword(buf, size, fp)
  622.     char *buf;
  623.     int size;
  624.     FILE *fp;
  625. {
  626.     register char *cp;
  627.     register int c;
  628.  
  629.     for (cp = buf; (c = getc(fp)) != EOF; ) {
  630.         if (c == ';') {
  631.             while ((c = getc(fp)) != EOF && c != '\n')
  632.                 ;
  633.             c = '\n';
  634.         }
  635.         if (c == '\n') {
  636.             if (cp != buf)
  637.                 ungetc(c, fp);
  638.             else
  639.                 lineno++;
  640.             break;
  641.         }
  642.         if (isspace(c)) {
  643.             while (isspace(c = getc(fp)) && c != '\n')
  644.                 ;
  645.             ungetc(c, fp);
  646.             if (cp != buf)        /* Trailing whitespace */
  647.                 break;
  648.             continue;        /* Leading whitespace */
  649.         }
  650.         if (c == '"') {
  651.             while ((c = getc(fp)) != EOF && c != '"' && c != '\n') {
  652.                 if (c == '\\') {
  653.                     if ((c = getc(fp)) == EOF)
  654.                         c = '\\';
  655.                     if (c == '\n')
  656.                         lineno++;
  657.                 }
  658.                 if (cp >= buf+size-1)
  659.                     break;
  660.                 *cp++ = c;
  661.             }
  662.             if (c == '\n') {
  663.                 lineno++;
  664.                 break;
  665.             }
  666.             continue;
  667.         }
  668.         if (c == '\\') {
  669.             if ((c = getc(fp)) == EOF)
  670.                 c = '\\';
  671.             if (c == '\n')
  672.                 lineno++;
  673.         }
  674.         if (cp >= buf+size-1)
  675.             break;
  676.         *cp++ = c;
  677.     }
  678.     *cp = '\0';
  679.     return (cp != buf);
  680. }
  681.  
  682. getnum(fp)
  683.     FILE *fp;
  684. {
  685.     register int c, n;
  686.     int seendigit = 0;
  687.     int seendecimal = 0;
  688.  
  689.     for (n = 0; (c = getc(fp)) != EOF; ) {
  690.         if (isspace(c)) {
  691.             if (c == '\n')
  692.                 lineno++;
  693.             if (seendigit)
  694.                 break;
  695.             continue;
  696.         }
  697.         if (c == ';') {
  698.             while ((c = getc(fp)) != EOF && c != '\n')
  699.                 ;
  700.             if (c == '\n')
  701.                 lineno++;
  702.             if (seendigit)
  703.                 break;
  704.             continue;
  705.         }
  706.         if (!isdigit(c)) {
  707.             if (c == ')' && seendigit) {
  708.                 (void) ungetc(c, fp);
  709.                 break;
  710.             }
  711.             if (seendecimal || c != '.') {
  712.                 syslog(LOG_ERR, "line %d: expected a number",
  713.                 lineno);
  714. #ifdef DEBUG
  715.                 if (debug)
  716.                     fprintf(ddt,"line %d: expected a number",
  717.                         lineno);
  718. #endif
  719.                 exit(1);    /* XXX why exit */
  720.             } else {
  721.                 if (!seendigit)
  722.                     n = 1;
  723.                 n = n * 1000 ;
  724.                 seendigit = 1;
  725.                 seendecimal = 1;
  726.             }
  727.             continue;
  728.         }
  729.         n = n * 10 + (c - '0');
  730.         seendigit = 1;
  731.     }
  732.     return (n);
  733. }
  734.  
  735. getnonblank(fp)
  736.     FILE *fp;
  737. {
  738.     register int c;
  739.  
  740.     while ( (c = getc(fp)) != EOF ) {
  741.         if (isspace(c)) {
  742.             if (c == '\n')
  743.                 lineno++;
  744.             continue;
  745.         }
  746.         if (c == ';') {
  747.             while ((c = getc(fp)) != EOF && c != '\n')
  748.                 ;
  749.             if (c == '\n')
  750.                 lineno++;
  751.             continue;
  752.         }
  753.         return(c);
  754.     }
  755.     syslog(LOG_ERR, "line %d: unexpected EOF", lineno);
  756. #ifdef DEBUG
  757.     if (debug)
  758.         fprintf(ddt, "line %d: unexpected EOF", lineno);
  759. #endif
  760.     return (EOF);
  761. }
  762.  
  763. /*
  764.  * Take name and fix it according to following rules:
  765.  * "." means root.
  766.  * "@" means current origin.
  767.  * "name." means no changes.
  768.  * "name" means append origin.
  769.  */
  770. makename(name, origin)
  771.     char *name, *origin;
  772. {
  773.     int n;
  774.  
  775.     if (origin[0] == '.')
  776.         origin++;
  777.     n = strlen(name);
  778.     if (n == 1) {
  779.         if (name[0] == '.') {
  780.             name[0] = '\0';
  781.             return;
  782.         }
  783.         if (name[0] == '@') {
  784.             (void) strcpy(name, origin);
  785.             return;
  786.         }
  787.     }
  788.     if (n > 0) {
  789.         if (name[n - 1] == '.')
  790.             name[n - 1] = '\0';
  791.         else if (origin[0] != '\0') {
  792.             name[n] = '.';
  793.             (void) strcpy(name + n + 1, origin);
  794.         }
  795.     }
  796. }
  797.  
  798. endline(fp)
  799.     register FILE *fp;
  800. {
  801.      register int c;
  802.      while (c = getc(fp))
  803.     if (c == '\n') {
  804.         (void) ungetc(c,fp);
  805.         break;
  806.     } else if (c == EOF)
  807.         break;
  808. }
  809.  
  810. #define MAXPORT 256
  811. #define MAXLEN 24
  812.  
  813. getprotocol(fp, src)
  814.     FILE *fp;
  815.     char *src;
  816. {
  817.     int  k;
  818.     char b[MAXLEN];
  819.  
  820.     (void) getword(b, sizeof(b), fp);
  821.         
  822.     k = protocolnumber(b);
  823.     if(k == -1)
  824.         syslog(LOG_ERR, "%s: line %d: unknown protocol: %s.",
  825.             src, lineno, b);
  826.     return(k);
  827. }
  828.  
  829. int
  830. getservices(n, data, fp, src)
  831.     int n;
  832.     char *data, *src;
  833.     FILE *fp;
  834. {
  835.     int j, ch;
  836.     int k;
  837.     int maxl;
  838.     int bracket;
  839.     char b[MAXLEN];
  840.     char bm[MAXPORT/8];
  841.  
  842.     for (j = 0; j < MAXPORT/8; j++)
  843.         bm[j] = 0;
  844.     maxl = 0;
  845.     bracket = 0;
  846.     while (getword(b, sizeof(b), fp) || bracket) {
  847.         if (feof(fp) || ferror(fp))
  848.             break;
  849.         if (strlen(b) == 0)
  850.             continue;
  851.         if ( b[0] == '(') {
  852.             bracket++;
  853.              continue;
  854.         }
  855.         if ( b[0] == ')') {
  856.             bracket = 0;
  857.             while ((ch = getc(fp)) != EOF && ch != '\n')
  858.                 ;
  859.             if (ch == '\n')
  860.                 lineno++;
  861.             break;
  862.         }
  863.         k = servicenumber(b);
  864.         if (k == -1) {
  865.             syslog(LOG_WARNING, "%s: line %d: Unknown service '%s'",
  866.                 src, lineno, b);
  867.             continue;
  868.         }
  869.         if ((k < MAXPORT) && (k)) {
  870.             bm[k/8] |= (0x80>>(k%8));
  871.             if (k > maxl)
  872.                 maxl=k;
  873.         }
  874.         else {
  875.             syslog(LOG_WARNING,
  876.                 "%s: line %d: port no. (%d) too big\n",
  877.                 src, lineno, k);
  878. #ifdef DEBUG
  879.             if (debug)
  880.                 fprintf(ddt,
  881.                     "%s: line %d: port no. (%d) too big\n",
  882.                     src, lineno, k);
  883. #endif
  884.         }
  885.     }
  886.     if (bracket)
  887.         syslog(LOG_WARNING, "%s: line %d: missing close paren\n",
  888.             src, lineno);
  889.     maxl = maxl/8+1;
  890.     bcopy(bm, data+n, maxl);
  891.     return(maxl+n);
  892. }
  893.  
  894. get_sort_list(fp)
  895.     FILE *fp;
  896. {
  897.     extern struct netinfo **enettab;
  898.     register struct netinfo *ntp, **end = enettab;
  899.     extern struct netinfo *findnetinfo();
  900.     struct in_addr addr;
  901.     char buf[BUFSIZ];
  902.  
  903. #ifdef DEBUG
  904.     if (debug)
  905.         fprintf(ddt,"sortlist ");
  906. #endif
  907.     while (getword(buf, sizeof(buf), fp)) {
  908.         if (strlen(buf) == 0)
  909.             break;
  910. #ifdef DEBUG
  911.         if (debug)
  912.             fprintf(ddt," %s",buf);
  913. #endif
  914.         addr.s_addr = inet_addr(buf);
  915.         if (addr.s_addr == (unsigned)-1) {
  916.             /* resolve name to address - XXX */
  917.             continue;    
  918.         }
  919.         /* Check for duplicates, then add to linked list */
  920.         if (findnetinfo(addr))
  921.             continue;
  922.         ntp = (struct netinfo *)malloc(sizeof(struct netinfo));
  923.         ntp->my_addr = addr;
  924.         ntp->next = NULL;
  925.         ntp->mask = net_mask(ntp->my_addr);
  926.         ntp->net = ntp->my_addr.s_addr & ntp->mask;
  927.         if (ntp->net != addr.s_addr) {
  928.             struct in_addr tmpaddr;
  929.  
  930.             tmpaddr.s_addr = ntp->net;
  931.             syslog(LOG_WARNING, "sortlist: addr %s != %s", buf,
  932.                 inet_ntoa(tmpaddr));
  933. #ifdef DEBUG
  934.             if (debug)
  935.                 fprintf(ddt, "\nsortlist: addr %s != %s\n", buf,
  936.                     inet_ntoa(tmpaddr));
  937. #endif
  938.         }
  939.  
  940.         *end = ntp;
  941.         end = &ntp->next;
  942.     }
  943.     
  944. #ifdef DEBUG
  945.     if (debug) 
  946.         fprintf(ddt,"\n");
  947.     if (debug > 2)
  948.         printnetinfo(*enettab);
  949.     if (debug > 4) {
  950.         extern struct netinfo *nettab;
  951.  
  952.         fprintf(ddt, "\nFull sort list:\n");
  953.         printnetinfo(nettab);
  954.     }
  955. #endif
  956. }
  957.  
  958. free_sort_list()
  959. {
  960.     extern struct netinfo **enettab;
  961.     register struct netinfo *ntp, *next;
  962.  
  963.     for (ntp = *enettab; ntp != NULL; ntp = next) {
  964.         next = ntp->next;
  965.         free((char *)ntp);
  966.     }
  967.     *enettab = NULL;
  968. }
  969.