break out special local mail processing (e.g., mapping to the
[unix-history] / usr / src / usr.bin / man / config.c
index f98828c..fad6517 100644 (file)
 /*
 /*
- * Copyright (c) 1989 The Regents of the University of California.
- * All rights reserved.
+ * Copyright (c) 1989, 1993
+ *     The Regents of the University of California.  All rights reserved.
  *
  * %sccs.include.redist.c%
  */
 
 #ifndef lint
  *
  * %sccs.include.redist.c%
  */
 
 #ifndef lint
-static char sccsid[] = "@(#)config.c   5.8 (Berkeley) %G%";
+static char sccsid[] = "@(#)config.c   8.7 (Berkeley) %G%";
 #endif /* not lint */
 
 #endif /* not lint */
 
-#include <sys/param.h>
-#include <stdio.h>
+#include <sys/types.h>
+#include <sys/queue.h>
+
+#include <ctype.h>
+#include <err.h>
 #include <errno.h>
 #include <errno.h>
-#include <string.h>
+#include <stdio.h>
 #include <stdlib.h>
 #include <stdlib.h>
-#include <pwd.h>
-#include "pathnames.h"
-
-#define        MAXLINE         1024
+#include <string.h>
 
 
-extern char *progname;
-char *pathbuf, **arorder;
+#include "config.h"
+#include "pathnames.h"
 
 
-static FILE *cfp;
+struct _head head;
 
 /*
 
 /*
- * getpath --
- *     read in the configuration file, calling a function with the line
- *     from each matching section.
+ * config --
+ *
+ * Read the configuration file and build a doubly linked
+ * list that looks like:
+ *
+ *     tag1 <-> record <-> record <-> record
+ *     |
+ *     tag2 <-> record <-> record <-> record
  */
  */
-char *
-getpath(sects)
-       char **sects;
+void
+config(fname)
+       char *fname;
 {
 {
-       register char **av, *p;
+       TAG *tp;
+       ENTRY *ep;
+       FILE *cfp;
        size_t len;
        size_t len;
-       char line[MAXLINE];
-       static int openconfig();
-
-       openconfig();
-       while (fgets(line, sizeof(line), cfp)) {
-               if (!index(line, '\n')) {
-                       (void)fprintf(stderr, "%s: config line too long.\n",
-                           progname);
-                       exit(1);
-               }
-               p = strtok(line, " \t\n");
-               if (!p || *p == '#')
+       int lcnt;
+       char *p, *t;
+
+       if (fname == NULL)
+               fname = _PATH_MANCONF;
+       if ((cfp = fopen(fname, "r")) == NULL)
+               err(1, "%s", fname);
+       TAILQ_INIT(&head);
+       for (lcnt = 1; (p = fgetln(cfp, &len)) != NULL; ++lcnt) {
+               if (len == 1)                   /* Skip empty lines. */
                        continue;
                        continue;
-               for (av = sects; *av; ++av)
-                       if (!strcmp(p, *av))
-                               break;
-               if (!*av)
+               if (p[len - 1] != '\n') {       /* Skip corrupted lines. */
+                       warnx("%s: line %d corrupted", fname, lcnt);
                        continue;
                        continue;
-               while (p = strtok((char *)NULL, " \t\n")) {
-                       len = strlen(p);
-                       if (p[len - 1] == '/')
-                               for (av = arorder; *av; ++av)
-                                       cadd(p, len, *av);
-                       else
-                               cadd(p, len, (char *)NULL);
                }
                }
-       }
-       return(pathbuf);
-}
-
-cadd(add1, len1, add2)
-       char *add1, *add2;
-       register size_t len1;
-{
-       static size_t buflen, boff;
-       static char *bp, *endp;
-       register size_t len2;
-
-       len2 = add2 ? strlen(add2) : 0;
-       if (bp == NULL || bp + len1 + len2 + 2 >= endp) {
-               buflen += MAX(len1 + len2 + 2, 1024);
-               boff = bp ? bp - pathbuf : 0;
-               if ((pathbuf = realloc(pathbuf, buflen)) == NULL)
-                       enomem();
-               bp = pathbuf + boff;
-               endp = pathbuf + buflen;
-       }
-       bcopy(add1, bp, len1);
-       bp += len1;
-       if (len2) {
-               bcopy(add2, bp, len2);
-               bp += len2;
-       }
-       *bp++ = ':';
-       *bp = '\0';
-}
+               p[len - 1] = '\0';              /* Terminate the line. */
 
 
-static
-openconfig()
-{
-       if (cfp) {
-               rewind(cfp);
-               return;
-       }
-       if (!(cfp = fopen(_PATH_MANCONF, "r"))) {
-               (void)fprintf(stderr, "%s: no configuration file %s.\n",
-                   progname, _PATH_MANCONF);
-               exit(1);
-       }
-}
-
-char **
-getdb()
-{
-       register char *p;
-       int cnt, num;
-       char **ar, line[MAXLINE];
-
-       ar = NULL;
-       num = 0;
-       cnt = -1;
-       openconfig();
-       while (fgets(line, sizeof(line), cfp)) {
-               if (!index(line, '\n')) {
-                       (void)fprintf(stderr, "%s: config line too long.\n",
-                           progname);
-                       exit(1);
-               }
-               p = strtok(line, " \t\n");
-#define        WHATDB  "_whatdb"
-               if (!p || *p == '#' || strcmp(p, WHATDB))
+                                               /* Skip leading space. */
+               for (; *p != '\0' && isspace(*p); ++p);
+                                               /* Skip empty/comment lines. */
+               if (*p == '\0' || *p == '#')
+                       continue;
+                                               /* Find first token. */
+               for (t = p; *t && !isspace(*t); ++t);
+               if (*t == '\0')                 /* Need more than one token.*/
                        continue;
                        continue;
-               while (p = strtok((char *)NULL, " \t\n")) {
-                       if (cnt == num - 1 &&
-                           !(ar = realloc(ar, (num += 30) * sizeof(char **))))
-                               enomem();
-                       if (!(ar[++cnt] = strdup(p)))
-                               enomem();
+               *t = '\0';
+
+               for (tp = head.tqh_first;       /* Find any matching tag. */
+                   tp != NULL && strcmp(p, tp->s); tp = tp->q.tqe_next);
+
+               if (tp == NULL)         /* Create a new tag. */
+                       tp = addlist(p);
+
+               /*
+                * Attach new records.  The keyword _build takes the rest of
+                * the line as a single entity, everything else is white
+                * space separated.  The reason we're not just using strtok(3)
+                * for all of the parsing is so we don't get caught if a line
+                * has only a single token on it.
+                */
+               if (!strcmp(p, "_build")) {
+                       while (*++t && isspace(*t));
+                       if ((ep = malloc(sizeof(ENTRY))) == NULL ||
+                           (ep->s = strdup(t)) == NULL)
+                               err(1, NULL);
+                       TAILQ_INSERT_TAIL(&tp->list, ep, q);
+               } else for (++t; (p = strtok(t, " \t\n")) != NULL; t = NULL) {
+                       if ((ep = malloc(sizeof(ENTRY))) == NULL ||
+                           (ep->s = strdup(p)) == NULL)
+                               err(1, NULL);
+                       TAILQ_INSERT_TAIL(&tp->list, ep, q);
                }
        }
                }
        }
-       if (ar) {
-               if (cnt == num - 1 &&
-                   !(ar = realloc(ar, ++num * sizeof(char **))))
-                       enomem();
-               ar[++cnt] = NULL;
-       }
-       return(ar);
 }
 
 }
 
-char **
-getorder()
+/*
+ * addlist --
+ *     Add a tag to the list.
+ */
+TAG *
+addlist(name)
+       char *name;
 {
 {
-       register char *p;
-       int cnt, num;
-       char **ar, line[MAXLINE];
-
-       ar = NULL;
-       num = 0;
-       cnt = -1;
-       openconfig();
-       while (fgets(line, sizeof(line), cfp)) {
-               if (!index(line, '\n')) {
-                       (void)fprintf(stderr, "%s: config line too long.\n",
-                           progname);
-                       exit(1);
-               }
-               p = strtok(line, " \t\n");
-#define        SUBDIR  "_subdir"
-               if (!p || *p == '#' || strcmp(p, SUBDIR))
-                       continue;
-               while (p = strtok((char *)NULL, " \t\n")) {
-                       if (cnt == num - 1 &&
-                           !(ar = realloc(ar, (num += 30) * sizeof(char **))))
-                               enomem();
-                       if (!(ar[++cnt] = strdup(p)))
-                               enomem();
-               }
-       }
-       if (ar) {
-               if (cnt == num - 1 &&
-                   !(ar = realloc(ar, ++num * sizeof(char **))))
-                       enomem();
-               ar[++cnt] = NULL;
-       }
-       return(ar);
+       TAG *tp;
+
+       if ((tp = calloc(1, sizeof(TAG))) == NULL ||
+           (tp->s = strdup(name)) == NULL)
+               err(1, NULL);
+       TAILQ_INIT(&tp->list);
+       TAILQ_INSERT_TAIL(&head, tp, q);
+       return (tp);
 }
 
 }
 
-getsection(sect)
-       char *sect;
+/*
+ * getlist --
+ *     Return the linked list of entries for a tag if it exists.
+ */
+TAG *
+getlist(name)
+       char *name;
 {
 {
-       register char *p;
-       char line[MAXLINE];
-
-       openconfig();
-       while (fgets(line, sizeof(line), cfp)) {
-               if (!index(line, '\n')) {
-                       (void)fprintf(stderr, "%s: config line too long.\n",
-                           progname);
-                       exit(1);
-               }
-               p = strtok(line, " \t\n");
-               if (!p || *p == '#')
-                       continue;
-               if (!strcmp(p, sect))
-                       return(1);
-       }
-       return(0);
+       TAG *tp;
+
+       for (tp = head.tqh_first; tp != NULL; tp = tp->q.tqe_next)
+               if (!strcmp(name, tp->s))
+                       return (tp);
+       return (NULL);
 }
 
 }
 
-enomem()
+void
+debug(l)
+       char *l;
 {
 {
-       (void)fprintf(stderr, "%s: %s\n", progname, strerror(ENOMEM));
-       exit(1);
+       TAG *tp;
+       ENTRY *ep;
+
+       (void)printf("%s ===============\n", l);
+       for (tp = head.tqh_first; tp != NULL; tp = tp->q.tqe_next) {
+               printf("%s\n", tp->s);
+               for (ep = tp->list.tqh_first; ep != NULL; ep = ep->q.tqe_next)
+                       printf("\t%s\n", ep->s);
+       }
 }
 }