home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 35 Internet / 35-Internet.zip / analg211.zip / init2.c < prev    next >
C/C++ Source or Header  |  1997-03-14  |  30KB  |  1,090 lines

  1. /*** analog 2.1 ***/
  2. /* Please read Readme.html, or http://www.statslab.cam.ac.uk/~sret1/analog/  */
  3.  
  4. /*** init2.c; some initialisation functions not using many global variables */
  5. /* See also init.c */
  6.  
  7. #include "analhea2.h"
  8.  
  9. /*** The function that parses the domains file ***/
  10.  
  11. void domainscan(void)
  12. {
  13.   extern char *domainsfile;
  14.   extern struct domain **ohead;
  15.   extern struct alias *subdomshead;
  16.   extern char *commandname;
  17.   extern flag oq, warnq, anywarns;
  18.  
  19.   FILE *df;
  20.   struct domain *p, *lastp;
  21.   struct alias *subdomp;
  22.   char tempstr[MAXSTRINGLENGTH], tempstr2[MAXSTRINGLENGTH];
  23.   char inputline[MAXLINELENGTH];
  24.   int rc;    /* return code */
  25.   int domcode;   /* the code of a particular domain;
  26.             see the long comment just below */
  27.   flag ispipe;
  28.  
  29.   df = fopenlog(domainsfile, "domains file", &ispipe);
  30.   if (df == NULL) {
  31.     if (warnq) {
  32.       fprintf(stderr,"  will not construct domain report.\n");
  33.       anywarns = ON;
  34.     }
  35.     oq = OFF;
  36.     return;
  37.   }
  38.  
  39.   /* We put the domains in the following order. aa = 0, ab = 2, ...,
  40.      ba = 52, ... Domains with more than two letters go in the spaces;
  41.      co = 134, com = 135, cp = 136. We assume that there are no two long
  42.      domain names with the same two initial letters. Finally zz = 1350,
  43.      zzspam = 1351, Unknown = 1352, Numerical = 1353. Each domain contains
  44.      a 'nexti' element to show which is the next domain that occurs in the
  45.      domains file. */
  46.  
  47.   else {   /* there is a domains file */
  48.     p = ohead[DOMHASHSIZE - 2];
  49.     p -> id = xmalloc(5);      /* enough for "*UNK\0" */
  50.     strcpy(p -> id, "*UNK");
  51.     p -> name = xmalloc(8);
  52.     strcpy(p -> name, "unknown");
  53.     p -> reqs = 0;
  54.     p -> pages = 0;
  55.     p -> bytes = 0;
  56.     p -> next = (struct domain *)xmalloc(sizeof(struct domain));
  57.     p -> next -> name = NULL;
  58.     p = ohead[DOMHASHSIZE - 1];
  59.     p -> id = xmalloc(5);
  60.     strcpy(p -> id, "*NUM");
  61.     p -> name = xmalloc(31);
  62.     strcpy(p -> name, "unresolved numerical addresses");
  63.     p -> reqs = 0;
  64.     p -> pages = 0;
  65.     p -> bytes = 0.0;
  66.     p -> next = (struct domain *)xmalloc(sizeof(struct domain));
  67.     p -> next -> name = NULL;
  68.     lastp = p;
  69.     p = p -> next;
  70.  
  71.     while (fgets(inputline, MAXLINELENGTH, df) != NULL) {
  72.       rc = sscanf_domains(inputline, tempstr, tempstr2);
  73.       if (rc == 2) {
  74.     if ((!isdigit(tempstr[0])) && strchr(tempstr, '.') == NULL) {
  75.                                                     /* new domain */
  76.       domcode = (tempstr[0] - 'a') * 52 + (tempstr[1] - 'a') * 2 +
  77.         (tempstr[2] != '\0');
  78.       if ((domcode < 0 || domcode > DOMHASHSIZE - 3) && warnq) {
  79.         fprintf(stderr, "%s: Warning: Ignoring corrupt line in domains file looking like\n", commandname);
  80.         fprintf(stderr,"  %s", inputline);
  81.         anywarns = ON;
  82.       }
  83.       p = ohead[domcode];
  84.       p -> id = xmalloc((size_t)((int)strlen(tempstr) + 1));
  85.       strcpy(p -> id, tempstr);
  86.       p -> name = xmalloc((size_t)((int)strlen(tempstr2) + 1));
  87.       strcpy(p -> name, tempstr2);
  88.       p -> reqs = 0;
  89.       p -> pages = 0;
  90.       p -> bytes = 0.0;
  91.       p -> next = (struct domain *)xmalloc(sizeof(struct domain));
  92.       p -> next -> name = NULL;
  93.       lastp -> nexti = domcode;
  94.                             /* domlastp is the last domain we looked at */
  95.       lastp = p;
  96.       p = p -> next;
  97.     }
  98.     else if (warnq) {   /* old specification subdomain */
  99.       fprintf(stderr, "%s: Warning: Ignoring corrupt line in domains file looking like\n", commandname);
  100.       fprintf(stderr,"  %s", inputline);
  101.       anywarns = ON;
  102.     }
  103.       }
  104.       else if (rc == 1 && warnq) {
  105.     fprintf(stderr, "%s: Warning: Ignoring corrupt line in domains file looking like\n", commandname);
  106.     fprintf(stderr, "  %s", inputline);
  107.     anywarns = ON;
  108.       }
  109.     }
  110.  
  111.     lastp -> nexti = -1;   /* marker; last domain has no subsequent one */
  112.     
  113.     fcloselog(df, domainsfile, "domains file", ispipe);
  114.  
  115.     /* Now do the subdomains which we read in at configuration time */
  116.  
  117.     for (subdomp = subdomshead; subdomp -> from[0] != '\0';
  118.      subdomp = subdomp -> next)
  119.       if (subdomp -> from[0] != '?')
  120.     subdomadd(subdomp -> from, subdomp -> to);
  121.  
  122.   }     /* end else can read domains file */
  123. }
  124.  
  125. /*** Now the function that parses the DNS cache ***/
  126. /* Test dnsq before calling this */
  127.  
  128. #ifndef NODNS
  129. void dnscachescan(void)
  130. {
  131.   extern char *dnsfile;
  132.   extern time_t dnsstaletime;
  133.   extern char *commandname;
  134.   extern flag warnq, anywarns;
  135.  
  136.   FILE *cf;
  137.   time_t timec;
  138.   char number[MAXSTRINGLENGTH], alias[MAXSTRINGLENGTH];
  139.   char inputline[MAXLINELENGTH];
  140.   flag ispipe;
  141.  
  142.   cf = fopenlog(dnsfile, "DNS cache file", &ispipe);
  143.   if (cf != NULL) {
  144.     while (fgets(inputline, MAXLINELENGTH, cf) != NULL) {
  145.       if (sscanf(inputline, "%ld %s%s", &timec, number, alias) != 3) {
  146.     if (warnq) {  /* NB: Poss. problem if strings too long */
  147.       fprintf(stderr, "%s: Warning: Ignoring corrupt line in DNS cache file looking like\n", 
  148.           commandname);
  149.       fprintf(stderr,"  %s", inputline);
  150.       anywarns = ON;
  151.     }
  152.       }
  153.       else if (timec > dnsstaletime)
  154.     dnshashadd(number, (alias[0] == '*')?NULL:alias, timec);
  155.     }
  156.     fcloselog(cf, dnsfile, "DNS cache file", ispipe);
  157.   }
  158. }
  159. #endif
  160.  
  161. /*** Functions used in parsing the configuration file ***/
  162. /* First some warning messages */
  163.  
  164. void configwarning(char *comname, char *inputline)
  165. {
  166.   extern char *commandname;
  167.   extern flag warnq, anywarns;
  168.  
  169.   if (warnq) {
  170.     fprintf(stderr, "%s: Warning: Not enough arguments to %s command: ignoring line\n", commandname, comname);
  171.     fprintf(stderr, "  %s", inputline);
  172.     if (inputline[MAX(strlen(inputline) - 1, 0)] != '\n')
  173.       fprintf(stderr, "\n");
  174.     anywarns = ON;
  175.   }
  176. }
  177.  
  178. void configwarning2(char *inputline)
  179. {
  180.   extern char *commandname;
  181.   extern flag warnq, anywarns;
  182.  
  183.   if (warnq) {
  184.     fprintf(stderr, "%s: Warning: Discarding illegal configuration command\n",
  185.         commandname);
  186.     fprintf(stderr, "  %s", inputline);
  187.     if (inputline[MAX(strlen(inputline) - 1, 0)] != '\n')
  188.       fprintf(stderr, "\n");
  189.     anywarns = ON;
  190.   }
  191. }
  192.  
  193. void configwarning3(char *comname, char *inputline)
  194. {
  195.   extern char *commandname;
  196.   extern flag warnq, anywarns;
  197.  
  198.   if (warnq) {
  199.     fprintf(stderr, "%s: Warning: Too many arguments to %s command: ignoring end of line\n", commandname, comname);
  200.     fprintf(stderr, "  %s", inputline);
  201.     if (inputline[MAX(strlen(inputline) - 1, 0)] != '\n')
  202.       fprintf(stderr, "\n");
  203.     anywarns = ON;
  204.   }
  205. }
  206.  
  207. /* Next some sub-functions to initialise configuration things */
  208.  
  209. void addonelogfile(struct loglist **p, char name[MAXSTRINGLENGTH],
  210.            char prefix[MAXSTRINGLENGTH])
  211. {
  212.   strncpy((*p) -> name, name, MAXSTRINGLENGTH - 1);
  213.   (*p) -> name[MAXSTRINGLENGTH - 1] = '\0';
  214.   strncpy((*p) -> prefix, prefix, MAXSTRINGLENGTH - 1);
  215.   (*p) -> prefix[MAXSTRINGLENGTH - 1] = '\0';
  216.   (*p) -> next = (struct loglist *)xmalloc(sizeof(struct loglist));
  217.   *p = (*p) -> next;
  218.   (*p) -> name[0] = '\0';
  219. }
  220.  
  221. #ifndef NODIRENT
  222. #ifndef VMSDIRENT
  223. void addwildlogs(struct loglist **p, char name[MAXSTRINGLENGTH],
  224.          char prefix[MAXSTRINGLENGTH])
  225. {
  226.   extern char *commandname;
  227.   extern flag warnq, anywarns;
  228.  
  229.   DIR *dirp;
  230.   struct dirent *filep;
  231.   struct stat *buf;
  232.   char dirname[MAXSTRINGLENGTH];
  233.   int dirnamelen;
  234.   char filename[MAXSTRINGLENGTH];
  235.   char *tempc, *temp1, *temp2;
  236.   flag matched = FALSE;
  237.  
  238.   strcpy(dirname, name);
  239.   for (tempc = dirname + strlen(dirname) - 1; tempc >= dirname &&
  240.        *tempc != DIRSEP; tempc--)
  241.     ;   /* run back to last DIRSEP if any */
  242.   if (tempc < dirname) {
  243.     strcpy(filename, dirname);
  244. #ifdef MAC
  245.     dirname[0] = '\0';
  246. #else
  247.     sprintf(dirname, ".%c", DIRSEP);
  248. #endif
  249.   }
  250.   else {
  251.     strcpy(filename, tempc + 1);
  252.     *(tempc + 1) = '\0';
  253.   }
  254.   if ((dirp = opendir(dirname)) == NULL) {
  255.     (*p) -> name[0] = '\0';
  256.     if (warnq) {
  257.       fprintf(stderr,
  258.          "%s: Warning: can't open directory %s:\n  ignoring logfiles %s\n",
  259.           commandname, dirname, name);
  260.       if (strchr(dirname, '*') != NULL || strchr(dirname, '?') != NULL)
  261.     fprintf(stderr, "  (wildcards not allowed in directory name)\n");
  262.       anywarns = ON;
  263.     }
  264.   }
  265.   else {
  266.     dirnamelen = strlen(dirname);
  267.     buf = (struct stat *)xmalloc(sizeof(struct stat));
  268.     while ((filep = readdir(dirp)) != NULL) {
  269.       strncpy(dirname + dirnamelen, filep -> d_name,
  270.           (size_t)(MAXSTRINGLENGTH - dirnamelen - 1));
  271.       stat(dirname, buf);    /* dirname now contains the complete filename */
  272.       if (S_ISREG(buf -> st_mode) &&  /* is ordinary file */
  273.       wildmatch(filep -> d_name, filename, &temp1, &temp2)) {
  274.     addonelogfile(p, dirname, prefix);
  275.     matched = TRUE;
  276.       }
  277.     }
  278.     closedir(dirp);
  279.     if (!matched)
  280.       addonelogfile(p, name, prefix);   /* so as to get proper error message */
  281.   }
  282. }
  283. #else  /* VMSDIRENT */
  284. /* The next function is due to Dave Jones */
  285. void addwildlogs(struct loglist **p, char name[MAXSTRINGLENGTH],
  286.          char prefix[MAXSTRINGLENGTH])
  287. {
  288.     static char fspec[VMS_FSPEC_MAX], related[VMS_FSPEC_MAX];
  289.     static char result[VMS_FSPEC_MAX];
  290.     static $DESCRIPTOR(fspec_dx,fspec);
  291.     static $DESCRIPTOR(related_dx,"");
  292.     static $DESCRIPTOR(default_dx,".log");
  293.     static $DESCRIPTOR(result_dx,result);
  294.     char *space, *ques;
  295.     long int context;
  296.     int status, stsval, length, LIB$FIND_FILE(), LIB$FIND_FILE_END();
  297.     flag matched;
  298.  
  299.     length = strlen ( name );
  300.     if ( length >= VMS_FSPEC_MAX ) length = VMS_FSPEC_MAX - 1;
  301.     strncpy ( fspec, name, length ); fspec[length] = '\0';
  302.     while ( ques = strchr(fspec,'?') ) *ques = '%';
  303.     fspec_dx.dsc$w_length = length;
  304.     for ( matched = FALSE, context = 0; 
  305.     1&(status=LIB$FIND_FILE ( &fspec_dx, &result_dx, &context,
  306.         &default_dx, &related_dx, &stsval, (long *) 0 )); 
  307.         matched = TRUE) {
  308.     space = strchr ( result, ' ' );
  309.     if ( !space ) space = &result[VMS_FSPEC_MAX-1];
  310.     *space = '\0';
  311.     addonelogfile ( p, result, prefix );
  312.     /* Save last result to use as defaul for next lookup */
  313.     strcpy ( related, result );
  314.     related_dx.dsc$w_length = strlen(result);
  315.     related_dx.dsc$a_pointer = related;
  316.     }
  317.     if ( context ) LIB$FIND_FILE_END ( &context );
  318.     if (!matched)
  319.       addonelogfile(p, name, prefix);   /* so as to get proper error message */
  320. }
  321. #endif
  322. #endif  /* NODIRENT */
  323.  
  324. void addlogfile(struct loglist **p, char name[MAXSTRINGLENGTH],
  325.         char prefix[MAXSTRINGLENGTH], flag wildexpand)
  326. {         /* wildexpand only used if NODIRENT off */
  327.   char *tempstr;
  328.   struct stringlist *tempstrlist, *tempslp;
  329.  
  330.   /* NB Do all strtok's before calling subsiduary functions that use it too */
  331.   tempstrlist = (struct stringlist *)xmalloc(sizeof(struct stringlist));
  332.   tempstrlist -> name[0] = '\0';
  333.   tempslp = tempstrlist;
  334.  
  335.   tempstr = strtok(name, ","); /* break at commas */
  336.   addonestrlist(&tempslp, tempstr);
  337.   while ((tempstr = strtok((char *)NULL, ",")) != NULL)
  338.     addonestrlist(&tempslp, tempstr);
  339.  
  340.   /* now check for wildcards and add to logfile list */
  341.   for ( ; tempstrlist -> name[0] != '\0'; tempstrlist = tempstrlist -> next) {
  342. #ifndef NODIRENT
  343. #ifndef VMSDIRENT
  344.     if (wildexpand && (strchr(tempstrlist -> name, '*') != NULL ||
  345.                strchr(tempstrlist -> name, '?') != NULL))
  346. #else /* VMSDIRENT; wildcards only supported for VMS file syntax, not Unix */
  347.     if (wildexpand && (strchr(tempstrlist -> name, '/' ) == NULL))
  348. #endif
  349.       addwildlogs(p, tempstrlist -> name, prefix);
  350.     else
  351. #endif
  352.       addonelogfile(p, tempstrlist -> name, prefix);
  353.   }
  354. }
  355.  
  356. void includeone(char *name, struct include **p, struct include *head, int in,
  357.         char *comname, char *inputline)
  358. {                          /* put something in an include list */
  359.   extern char *commandname;
  360.   extern flag warnq, anywarns;
  361.  
  362.   struct include *tempp, *oldp;
  363.   int tempflag;
  364.   char tempstr[MAXSTRINGLENGTH];
  365.  
  366.   if (in == UNSET) {   /* *ALLOW */
  367.     tempflag = OFF;
  368.     for (tempp = head; tempp -> in != UNSET; tempp = tempp -> next) {
  369.       if (STREQ(tempp -> name, name) && tempp -> in == FALSE) {
  370.     if (tempp == head)
  371.       tempp -> name[0] = '\0';
  372.     else
  373.       oldp -> next = tempp -> next;
  374.     tempflag = ON;
  375.       }
  376.       oldp = tempp;
  377.     }
  378.     if (!tempflag && warnq) {
  379.       fprintf(stderr, "%s: Warning: %s command before corresponding EXCLUDE at\n", commandname, comname);
  380.       fprintf(stderr, "  %s", inputline);
  381.       if (inputline[MAX(strlen(inputline) - 1, 0)] != '\n')
  382.     fprintf(stderr, "\n");
  383.       anywarns = ON;
  384.     }
  385.   }
  386.   else {
  387.     strcpy(tempstr, name);
  388.     if (STREQ(strtolower(tempstr), "pages"))
  389.       strcpy((*p) -> name, "pages");
  390.     else {
  391.       strncpy((*p) -> name, name, MAXSTRINGLENGTH - 1);
  392.       (*p) -> name[MAXSTRINGLENGTH - 1] = '\0';
  393.     }
  394.     (*p) -> in = in;
  395.     (*p) -> next = (struct include *)xmalloc(sizeof(struct include));
  396.     *p = (*p) -> next;
  397.     (*p) -> in = UNSET;
  398.   }
  399. }
  400.  
  401. void include(char *name, struct include **p, struct include *head, int in,
  402.          char *comname, char *inputline, int rc, flag *maskq)
  403. {                          /* put something(s) in/out of an include list */
  404.   char *tempstr;
  405.  
  406.   if (rc < 2)
  407.     configwarning(comname, inputline);
  408.   else {
  409.     if (rc > 2)
  410.       configwarning3(comname, inputline);
  411.     *maskq = ON;
  412.     tempstr = strtok(name, ",");
  413.     includeone(tempstr, p, head, in, comname, inputline);
  414.     while ((tempstr = strtok((char *)NULL, ",")) != NULL)
  415.       includeone(tempstr, p, head, in, comname, inputline);
  416.   }
  417. }
  418.  
  419. void configalias(char *from, char *to, struct alias **p, char *comname,
  420.          char *inputline, int rc)
  421. {
  422.   if (rc < 3)
  423.     configwarning(comname, inputline);
  424.   else if (from[0] == '\0' || to[0] == '\0')
  425.     configwarning2(inputline);
  426.   else {
  427.     if (rc > 3)
  428.       configwarning3(comname, inputline);
  429.     strcpy((*p) -> from, from);
  430.     strcpy((*p) -> to, to);
  431.     (*p) -> next = (struct alias *)xmalloc(sizeof(struct alias));
  432.     *p = (*p) -> next;
  433.     (*p) -> from[0] = '\0';
  434.   }
  435. }
  436.  
  437. void fromtodate(char *tstr, struct timestruct *t, flag from,
  438.         char *comname, char *inputline, int rc)
  439. {  /* NB should we put more syntax checking in this function? */
  440.   extern struct timestruct starttimec;
  441.   extern int monthlength[];
  442.  
  443.   if (rc < 2)
  444.     configwarning(comname, inputline);
  445.   else if (STREQ(strtoupper(tstr), "OFF")) {
  446.     if (from)
  447.       t -> code = -INFINITY;
  448.     else
  449.       t -> code = INFINITY;
  450.   }
  451.   else if ((int)strlen(tstr) < 6)
  452.     configwarning2(inputline);
  453.   else {
  454.     if (rc > 2)
  455.       configwarning3(comname, inputline);
  456.     if (*tstr == '-') {
  457.       t -> year = starttimec.year;
  458.       t -> year -= 10 * (*(++tstr) - '0');
  459.       t -> year -= (*(++tstr) - '0');
  460.     }
  461.     else {
  462.       t -> year = 10 * (*tstr - '0');
  463.       t -> year += (*(++tstr) - '0');
  464.       if (t -> year > 70)   /* (say) */
  465.     t -> year += 1900;
  466.       else
  467.     t -> year += 2000;
  468.     }
  469.     tstr++;
  470.     if (*tstr == '-') {
  471.       t -> monthno = starttimec.monthno;
  472.       t -> monthno -= 10 * (*(++tstr) - '0');
  473.       t -> monthno -= (*(++tstr) - '0');
  474.       while (t -> monthno < 0) {
  475.     t -> monthno += 12;
  476.     t -> year--;
  477.       }
  478.     }
  479.     else if (*tstr == '+') {
  480.       t -> monthno = starttimec.monthno;
  481.       t -> monthno += 10 * (*(++tstr) - '0');
  482.       t -> monthno += (*(++tstr) - '0');
  483.       while (t -> monthno > 11) {
  484.     t -> monthno -= 12;
  485.     t -> year++;
  486.       }
  487.     }
  488.     else {
  489.       t -> monthno = 10 * (*tstr - '0');
  490.       t -> monthno += (*(++tstr) - '0');
  491.       t -> monthno--;  /* prog. months are 1 out from standard */
  492.     }
  493.     tstr++;
  494.     if (*tstr == '-') {
  495.       t -> date = starttimec.date;
  496.       t -> date -= atoi(++tstr);
  497.       while (t -> date <= 0) {
  498.     t -> monthno--;
  499.     if (t -> monthno < 0) {
  500.       t -> monthno += 12;
  501.       t -> year--;
  502.     }
  503.     t -> date += monthlength[t -> monthno] +
  504.       ISLEAPFEB(t -> monthno, t -> year);
  505.       }
  506.     }
  507.     else if (*tstr == '+') {
  508.       t -> date = starttimec.date;
  509.       t -> date += atoi(++tstr);
  510.       while (t -> date > monthlength[t -> monthno] +
  511.          ISLEAPFEB(t -> monthno, t -> year)) {
  512.     t -> date -= monthlength[t -> monthno] +
  513.       ISLEAPFEB(t -> monthno, t -> year);
  514.     t -> monthno++;
  515.     if (t -> monthno > 11) {
  516.       t -> monthno -= 12;
  517.       t -> year++;
  518.     }
  519.       }
  520.     }
  521.     else {
  522.       t -> date = 10 * (*tstr - '0');
  523.       t -> date += (*(++tstr) - '0');
  524.     }
  525.     if (from) {
  526.       t -> hr = 0;
  527.       t -> min = 0;
  528.     }
  529.     else {
  530.       t -> hr = 23;
  531.       t -> min = 59;
  532.     }
  533.     t -> code = timecode(t -> date, t -> monthno, t -> year, t -> hr,
  534.              t -> min);
  535.   }
  536. }
  537.  
  538. void configstr(char *name, char *target, char *comname, char *inputline,
  539.            int rc)  /* NB: name must have size at least MSL */
  540. {
  541.   if (rc < 2)
  542.     configwarning(comname, inputline);
  543.   else {
  544.     if (rc > 2)
  545.       configwarning3(comname, inputline);
  546.     strncpy(target, name, MAXSTRINGLENGTH - 1);
  547.   }
  548. }
  549.  
  550. /* a couple of functions for configstrlist() below */
  551.  
  552. void addonestrlist(struct stringlist **p, char *name)
  553. {
  554.   strncpy((*p) -> name, name, MAXSTRINGLENGTH - 1);
  555.   (*p) -> name[MAXSTRINGLENGTH - 1] = '\0';
  556.   (*p) -> next = (struct stringlist *)xmalloc(sizeof(struct stringlist));
  557.   *p = (*p) -> next;
  558.   (*p) -> name[0] = '\0';
  559. }
  560.  
  561. #ifndef NODIRENT
  562. #ifndef VMSDIRENT
  563. void addwildstrlist(struct stringlist **p, char *name)
  564. {    /* exactly the same as addwildlogs() above */
  565.   extern char *commandname;
  566.   extern flag warnq, anywarns;
  567.  
  568.   DIR *dirp;
  569.   struct dirent *filep;
  570.   struct stat *buf;
  571.   char dirname[MAXSTRINGLENGTH];
  572.   int dirnamelen;
  573.   char filename[MAXSTRINGLENGTH];
  574.   char *tempc, *temp1, *temp2;
  575.   flag matched = FALSE;
  576.  
  577.   strcpy(dirname, name);
  578.   for (tempc = dirname + strlen(dirname) - 1; tempc >= dirname &&
  579.        *tempc != DIRSEP; tempc--)
  580.     ;      /* run back to last DIRSEP if any */
  581.   if (tempc < dirname) {
  582.     strcpy(filename, dirname);
  583. #ifdef MAC
  584.     dirname[0] = '\0';
  585. #else
  586.     sprintf(dirname, ".%c", DIRSEP);
  587. #endif
  588.   }
  589.   else {
  590.     strcpy(filename, tempc + 1);
  591.     *(tempc + 1) = '\0';
  592.   }
  593.   if ((dirp = opendir(dirname)) == NULL) {
  594.     (*p) -> name[0] = '\0';
  595.     if (warnq) {
  596.       fprintf(stderr,
  597.          "%s: Warning: can't open directory %s:\n  ignoring files %s\n",
  598.           commandname, dirname, name);
  599.       if (strchr(dirname, '*') != NULL || strchr(dirname, '?') != NULL)
  600.     fprintf(stderr, "  (wildcards not allowed in directory name)\n");
  601.       anywarns = ON;
  602.     }
  603.   }
  604.   else {
  605.     dirnamelen = strlen(dirname);
  606.     buf = (struct stat *)xmalloc(sizeof(struct stat));
  607.     while ((filep = readdir(dirp)) != NULL) {
  608.       strncpy(dirname + dirnamelen, filep -> d_name,
  609.           (size_t)(MAXSTRINGLENGTH - dirnamelen - 1));
  610.       stat(dirname, buf);
  611.       if (S_ISREG(buf -> st_mode) &&  /* is ordinary file */
  612.       wildmatch(filep -> d_name, filename, &temp1, &temp2)) {
  613.     addonestrlist(p, dirname);
  614.     matched = TRUE;
  615.       }
  616.     }
  617.     closedir(dirp);
  618.     if (!matched)
  619.       addonestrlist(p, name);
  620.   }
  621. }
  622. #else /* VMSDIRENT */
  623. /* The next function is due to Dave Jones */
  624. void addwildstrlist(struct stringlist **p, char *name)
  625. {
  626.     static char fspec[VMS_FSPEC_MAX], related[VMS_FSPEC_MAX];
  627.     static char result[VMS_FSPEC_MAX];
  628.     static $DESCRIPTOR(fspec_dx,fspec);
  629.     static $DESCRIPTOR(related_dx,"");
  630.     static $DESCRIPTOR(default_dx,".log");
  631.     static $DESCRIPTOR(result_dx,result);
  632.     char *space, *ques;
  633.     long int context;
  634.     int status, stsval, length, LIB$FIND_FILE(), LIB$FIND_FILE_END();
  635.     flag matched;
  636.  
  637.     length = strlen ( name );
  638.     if ( length >= VMS_FSPEC_MAX ) length = VMS_FSPEC_MAX - 1;
  639.     strncpy ( fspec, name, length ); fspec[length] = '\0';
  640.     while ( ques = strchr(fspec,'?') ) *ques = '%';
  641.     fspec_dx.dsc$w_length = length;
  642.     for ( matched = FALSE, context = 0; 
  643.     1&(status=LIB$FIND_FILE ( &fspec_dx, &result_dx, &context,
  644.         &default_dx, &related_dx, &stsval, (long *) 0 )); 
  645.         matched = TRUE) {
  646.     space = strchr ( result, ' ' );
  647.     if ( !space ) space = &result[VMS_FSPEC_MAX-1];
  648.     *space = '\0';
  649.     addonestrlist ( p, result );
  650.     /* Save last result to use as default for next lookup */
  651.     strcpy ( related, result );
  652.     related_dx.dsc$w_length = strlen(result);
  653.     related_dx.dsc$a_pointer = related;
  654.     }
  655.     if ( context ) LIB$FIND_FILE_END ( &context );
  656.     if (!matched)
  657.       addonestrlist(p, name );   /* so as to get proper error message */
  658. }
  659. #endif
  660. #endif /* #define NODIRENT */
  661.  
  662. void configstrlist(char *name, struct stringlist **p, char *comname,
  663.            char *inputline, int rc, flag wildexpand)
  664. {   /* one or more of a list of strings (with filename matching as in */
  665.     /* addlogfile()). NB in configstr() applies */
  666.   char *tempstr;
  667.   struct stringlist *tempstrlist, *tempslp;
  668.  
  669.   if (rc < 2)
  670.     configwarning(comname, inputline);
  671.   else {
  672.     if (rc > 2)
  673.       configwarning3(comname, inputline);
  674.     tempstrlist = (struct stringlist *)xmalloc(sizeof(struct stringlist));
  675.     tempstrlist -> name[0] = '\0';
  676.     tempslp = tempstrlist;
  677.     tempstr = strtok(name, ",");
  678.     addonestrlist(&tempslp, tempstr);
  679.     while ((tempstr = strtok((char *)NULL, ",")) != NULL)
  680.       addonestrlist(&tempslp, tempstr);
  681.  
  682.     for ( ; tempstrlist -> name[0] != '\0';
  683.      tempstrlist = tempstrlist -> next) {
  684. #ifndef NODIRENT
  685. #ifndef VMSDIRENT
  686.       if (wildexpand && (strchr(tempstrlist -> name, '*') != NULL ||
  687.              strchr(tempstrlist -> name, '?') != NULL))
  688. #else /* VMSDIRENT */
  689.       if (wildexpand && (strchr(tempstrlist -> name, '/' ) == NULL))
  690. #endif
  691.     addwildstrlist(p, tempstrlist -> name);
  692.       else
  693. #endif
  694.     addonestrlist(p, tempstrlist -> name);
  695.     }
  696.   }
  697. }
  698.  
  699. void configcols(char *cols, char *target, char *comname, char *inputline,
  700.         int rc)
  701. {                           /* as configstr, but extra length check */
  702.   if (rc < 2)
  703.     configwarning(comname, inputline);
  704.   else {
  705.     if (rc > 2 || (int)strlen(cols) > 6)
  706.       configwarning3(comname, inputline);
  707.     strncpy(target, cols, 6);
  708.   }
  709. }
  710.  
  711. void configchar(char *str, char *target, char *comname, char *inputline,
  712.         int rc)
  713. {                           /* read in a single character */
  714.   if (rc < 2)
  715.     configwarning(comname, inputline);
  716.   else {
  717.     if (rc > 2 || str[1] != '\0')
  718.       configwarning3(comname, inputline);
  719.     *target = str[0];
  720.   }
  721. }
  722.  
  723. void configint(char *number, int *target, char *comname, char *inputline,
  724.            int rc)
  725. {
  726.   if (rc < 2)
  727.     configwarning(comname, inputline);
  728.   else {
  729.     if (rc > 2)
  730.       configwarning3(comname, inputline);
  731.     *target = atoi(number);
  732.   }
  733. }
  734.  
  735. void configsizet(char *number, size_t *target, char *comname, char *inputline,
  736.          int rc)  /* same as configint() except the target is size_t */
  737. {
  738.   if (rc < 2)
  739.     configwarning(comname, inputline);
  740.   else {
  741.     if (rc > 2)
  742.       configwarning3(comname, inputline);
  743.     *target = MAX(atoi(number), 1);  /* we only use this for hash sizes, so
  744.                     we want them to be at least 1 */
  745.   }
  746. }
  747.  
  748. void configsortby(char *method, int *target, char *comname, char *inputline,
  749.           int rc)
  750. {
  751.   if (rc < 2)
  752.     configwarning(comname, inputline);
  753.   else {
  754.     if (rc > 2)
  755.       configwarning3(comname, inputline);
  756.     strtoupper(method);
  757.     if (STREQ(method, "REQUESTS"))
  758.       *target = BYREQUESTS;
  759.     else if (STREQ(method, "BYTES"))
  760.       *target = BYBYTES;
  761.     else if (STREQ(method, "PAGES"))
  762.       *target = BYPAGES;
  763.     else if (STREQ(method, "ALPHABETICAL"))
  764.       *target = ALPHABETICAL;
  765.     else if (STREQ(method, "RANDOM"))
  766.       *target = RANDOMLY;
  767.     else
  768.       configwarning2(inputline);
  769.   }
  770. }
  771.  
  772. void onoff(char *method, flag *target, char *comname, char *inputline, int rc)
  773. {
  774.   if (rc < 2)
  775.     configwarning(comname, inputline);
  776.   else {
  777.     if (rc > 2)
  778.       configwarning3(comname, inputline);
  779.     strtoupper(method);
  780.     if (STREQ(method, "ON"))
  781.       *target = ON;
  782.     else if (STREQ(method, "OFF"))
  783.       *target = OFF;
  784.     else
  785.       configwarning2(inputline);
  786.   }
  787. }
  788.  
  789. /*** Now some subfunctions for commandline() ***/
  790.  
  791. void clflag(flag *f, char *arg)   /* simple on/off switches */
  792. {
  793.   extern char *commandname;
  794.   extern flag warnq, anywarns;
  795.  
  796.   if (arg[0] == '-')
  797.     *f = OFF;
  798.   else
  799.     *f = ON;
  800.   if (arg[2] != '\0' && warnq) {
  801.     fprintf(stderr, "%s: Warning: ignoring extra text after %c%c option\n",
  802.         commandname, arg[0], arg[1]);
  803.     anywarns = ON;
  804.   }
  805. }
  806.  
  807. void cldaterep(flag *f, char *graph, char *arg)
  808. {
  809.   extern char *commandname;
  810.   extern flag warnq, anywarns;
  811.  
  812.   if (arg[0] == '-') {
  813.     *f = OFF;
  814.     if (arg[2] != '\0' && warnq) {
  815.       fprintf(stderr, "%s: Warning: ignoring extra text after -%c option\n",
  816.           commandname, arg[1]);
  817.       anywarns = ON;
  818.     }
  819.   }
  820.   else {
  821.     *f = ON;
  822.     if (arg[2] != '\0') {
  823.       if (arg[2] != 'b' && arg[2] != 'r' && arg[2] != 'B' && arg[2] != 'R'
  824.       && arg[2] != 'p' && arg[2] != 'P') {
  825.     if (warnq) {
  826.       fprintf(stderr, "%s: Warning: unknown graph method %c at %s\n",
  827.           commandname, arg[2], arg);
  828.       anywarns = ON;
  829.     }
  830.       }
  831.       else {
  832.     *graph = arg[2];
  833.     if (arg[3] != '\0') {
  834.       fprintf(stderr,
  835.           "%s: Warning: ignoring extra text after +%c%c option\n",
  836.           commandname, arg[1], arg[2]);
  837.       anywarns = ON;
  838.     }
  839.       }
  840.     }
  841.   }
  842. }
  843.  
  844. void clgenrep(flag *f, int *sortby, char *minreqstr, char *minpagestr,
  845.           char *minbytestr, char *arg)    /* generic reports */
  846. {
  847.   extern char *commandname;
  848.   extern flag warnq, anywarns;
  849.  
  850.   if (arg[0] == '-') {
  851.     *f = OFF;
  852.     if (arg[2] != '\0' && warnq) {
  853.       fprintf(stderr, "%s: Warning: ignoring extra text after -%c option\n",
  854.           commandname, arg[1]);
  855.       anywarns = ON;
  856.     }
  857.   }
  858.   else {
  859.     *f = ON;
  860.     switch (arg[2]) {
  861.     case '\0':
  862.       break;
  863.     case 'a':
  864.     case 'A':
  865.       *sortby = ALPHABETICAL;
  866.       if (arg[3] != '\0')
  867.     strcpy(minreqstr, arg + 3);
  868.       break;
  869.     case 'b':
  870.     case 'B':
  871.       *sortby = BYBYTES;
  872.       if (arg[3] != '\0')
  873.     strcpy(minbytestr, arg + 3);
  874.       break;
  875.     case 'p':
  876.     case 'P':
  877.       *sortby = BYPAGES;
  878.       if (arg[3] != '\0')
  879.     strcpy(minpagestr, arg + 3);
  880.       break;
  881.     case 'r':
  882.     case 'R':
  883.       *sortby = BYREQUESTS;
  884.       if (arg[3] != '\0')
  885.     strcpy(minreqstr, arg + 3);
  886.       break;
  887.     case 'x':
  888.     case 'X':
  889.       *sortby = RANDOMLY;
  890.       if (arg[3] != '\0')
  891.     strcpy(minreqstr, arg + 3);
  892.       break;
  893.     default:
  894.       if (warnq) {
  895.     fprintf(stderr, "%s: Warning: unknown sort method %c at %s\n",
  896.         commandname, arg[2], arg);
  897.     anywarns = ON;
  898.       }
  899.     }
  900.   }
  901. }
  902.  
  903. flag clfile(char *filename, char *arg)   /* read in a filename */
  904. {
  905.   extern char *commandname;
  906.   extern flag warnq, anywarns;
  907.  
  908.   if (arg[0] == '-') {
  909.     strcpy(filename, "none");
  910.     if (arg[2] != '\0' && warnq) {
  911.       fprintf(stderr, "%s: Warning: ignoring extra text after -%c option\n",
  912.           commandname, arg[1]);
  913.       anywarns = ON;
  914.     }
  915.   }
  916.   else if (arg[2] == '\0') {
  917.     if (warnq) {
  918.       fprintf(stderr, "%s: Warning: no filename supplied after +%c option\n",
  919.           commandname, arg[1]);
  920.       fprintf(stderr, "  (or space left before filename)\n");
  921.       anywarns = ON;
  922.     }
  923.     return(ERR);
  924.   }
  925.   else
  926.     strncpy(filename, arg + 2, MAXSTRINGLENGTH - 1);
  927.   return(OK);
  928. }
  929.  
  930. /*** Functions for conversion to lower case of alias list and include list ***/
  931.  
  932. void alias_to_lower(struct alias *head)
  933. {
  934.   struct alias *p;
  935.  
  936.   for (p = head; p -> from[0] != '\0'; p = p -> next) {
  937.     strtolower(p -> from);
  938.     strtolower(p -> to);
  939.   }
  940. }
  941.  
  942. void include_to_lower(struct include *head)
  943. {
  944.   struct include *p;
  945.  
  946.   for (p = head; p -> in != UNSET; p = p -> next)
  947.     strtolower(p -> name);
  948. }
  949.  
  950. /*** And finally some functions in connection with printvbles() ***/
  951.  
  952. void pvfiletest(char *name)
  953. {
  954.   extern flag stdin_used;
  955.  
  956.   FILE *filep;
  957.  
  958.   if ((filep = fopen(name, "r")) == NULL && !STREQ(name, "stdin") &&
  959.       !STREQ(name, "-"))
  960.     printf("\n    Warning: cannot open that file");
  961.   else
  962.     fclose(filep);  /* NB So condl 3 lines back must be in that order */
  963.   if (STREQ(name, "stdin") || STREQ(name, "-")) {
  964.     if (stdin_used)
  965.       printf("\n    Warning: attempt to use stdin twice will fail");
  966.     stdin_used = TRUE;
  967.   }
  968.   printf("\n");
  969. }
  970.  
  971. void pvfilelist(struct stringlist *head, char filetype[MAXSTRINGLENGTH])
  972. {
  973.   struct stringlist *p;
  974.  
  975.   printf("%s to analyse:\n", filetype);
  976.   if (head -> name[0] == '\0')
  977.     printf("  none\n");
  978.   for (p = head; p -> name[0] != '\0'; p = p -> next) {  /* for each file */
  979.     printf("  %s", p -> name);
  980.     pvfiletest(p -> name);
  981.   }
  982. }
  983.  
  984. void pvcols(char *cols)
  985. {
  986.   char *c;
  987.  
  988.   printf("  Columns:");
  989.   if (*cols == '\0')
  990.     printf("  none");
  991.   else for (c = cols; *c != '\0'; c++) {
  992.     switch(*c) {
  993.     case 'b':
  994.       printf("  %%bytes");
  995.       break;
  996.     case 'B':
  997.       printf("  #bytes");
  998.       break;
  999.     case 'p':
  1000.       printf("  %%pages");
  1001.       break;
  1002.     case 'P':
  1003.       printf("  #pages");
  1004.       break;
  1005.     case 'r':
  1006.       printf("  %%requests");
  1007.       break;
  1008.     case 'R':
  1009.       printf("  #requests");
  1010.       break;
  1011.     }
  1012.   }
  1013.   printf("\n");
  1014. }
  1015.  
  1016. void pvtime(char name[15], flag q, char graph, int unit, char cols[], int rows)
  1017. {
  1018.   extern char sepchar;
  1019.  
  1020.   int i;
  1021.  
  1022.   printf("%s", name);
  1023.   for (i = 19 - (int)strlen(name); i > 0; i--)
  1024.     printf(" ");
  1025.   printf("%s\n", q?"ON":"OFF");
  1026.   if (q) {
  1027.     printf("  Drawing bar chart by ");
  1028.     if (graph == 'b' || graph == 'B')
  1029.       printf("bytes\n");
  1030.     else if (graph == 'p' || graph == 'P')
  1031.       printf("pages\n");
  1032.     else
  1033.       printf("requests\n");
  1034.     if (unit != 0) {
  1035.       printf("  Each character in the graph will represent");
  1036.       int3printf(stdout, unit, sepchar, 0);
  1037.       if (graph == 'b' || graph == 'B')
  1038.     printf("bytes\n");
  1039.       else if (graph == 'p' || graph == 'P')
  1040.     printf("pages\n");
  1041.       else
  1042.     printf("requests\n");
  1043.     }
  1044.     if (rows > 0)
  1045.       printf("  Maximum number of rows in report will be %d\n", rows);
  1046.     pvcols(cols);
  1047.   }
  1048. }
  1049.  
  1050. void pvgen(char name[17], flag q, int sortby, char *minreqstr,
  1051.        char *minpagestr, char *minbytestr, char cols[], char singular[20],
  1052.        char plural[21], char gender)
  1053. {
  1054.   int i;
  1055.  
  1056.   printf("%s", name);
  1057.   for (i = 19 - (int)strlen(name); i > 0; i--)
  1058.     printf(" ");
  1059.   printf("%s\n", q?"ON":"OFF");
  1060.   if (q) {
  1061.     printf("  ");
  1062.     whatincluded(stdout, sortby, minreqstr, minpagestr, minbytestr, singular,
  1063.          plural, OFF, gender);
  1064.     pvcols(cols);
  1065.   }
  1066. }
  1067.  
  1068. void pvinout(char name[14], struct include *head)
  1069. {
  1070.   struct include *p;
  1071.  
  1072.   if (head -> in != UNSET) {
  1073.     printf("Including (+) and excluding (-) the following %s:\n", name);
  1074.     printf("  All %s, then\n", (head -> in == TRUE)?"excluded":"included");
  1075.     for (p = head; p -> in != UNSET; p = p -> next)
  1076.       printf("  %c %s\n", (p -> in)?'+':'-', p -> name);
  1077.   }
  1078. }
  1079.  
  1080. void pvalias(char name[8], struct alias *head)
  1081. {
  1082.   struct alias *p;
  1083.  
  1084.   if (head -> from[0] != '\0') {
  1085.     printf("%s aliases:\n", name);
  1086.     for (p = head; p -> from[0] != '\0'; p = p -> next)
  1087.       printf("  %s -> %s\n", p -> from, p -> to);
  1088.   }
  1089. }
  1090.