142257Sbostic /*
2*68212Spendry * Copyright (c) 1989, 1993, 1995
363516Sbostic * The Regents of the University of California. All rights reserved.
442257Sbostic *
542741Sbostic * %sccs.include.redist.c%
642257Sbostic */
742257Sbostic
842257Sbostic #ifndef lint
9*68212Spendry static char sccsid[] = "@(#)config.c 8.8 (Berkeley) 01/31/95";
1042257Sbostic #endif /* not lint */
1142257Sbostic
1265276Sbostic #include <sys/types.h>
1365276Sbostic #include <sys/queue.h>
1465276Sbostic
1565276Sbostic #include <ctype.h>
1665276Sbostic #include <err.h>
1765276Sbostic #include <errno.h>
1842257Sbostic #include <stdio.h>
1965276Sbostic #include <stdlib.h>
2042257Sbostic #include <string.h>
2165276Sbostic
2265276Sbostic #include "config.h"
2342257Sbostic #include "pathnames.h"
2442257Sbostic
2565279Sbostic struct _head head;
2642402Sbostic
2742257Sbostic /*
2865276Sbostic * config --
2965276Sbostic *
3065276Sbostic * Read the configuration file and build a doubly linked
3165276Sbostic * list that looks like:
3265276Sbostic *
3365276Sbostic * tag1 <-> record <-> record <-> record
3465276Sbostic * |
3565276Sbostic * tag2 <-> record <-> record <-> record
3642257Sbostic */
3765276Sbostic void
config(fname)3865278Sbostic config(fname)
3965278Sbostic char *fname;
4042257Sbostic {
4165279Sbostic TAG *tp;
4265279Sbostic ENTRY *ep;
4365276Sbostic FILE *cfp;
4442402Sbostic size_t len;
4565276Sbostic int lcnt;
4665276Sbostic char *p, *t;
4742257Sbostic
4865278Sbostic if (fname == NULL)
4965278Sbostic fname = _PATH_MANCONF;
5065278Sbostic if ((cfp = fopen(fname, "r")) == NULL)
5165278Sbostic err(1, "%s", fname);
5265279Sbostic TAILQ_INIT(&head);
5365361Sbostic for (lcnt = 1; (p = fgetln(cfp, &len)) != NULL; ++lcnt) {
5465280Sbostic if (len == 1) /* Skip empty lines. */
5542402Sbostic continue;
5665276Sbostic if (p[len - 1] != '\n') { /* Skip corrupted lines. */
5765278Sbostic warnx("%s: line %d corrupted", fname, lcnt);
5842402Sbostic continue;
5942402Sbostic }
6065276Sbostic p[len - 1] = '\0'; /* Terminate the line. */
6142402Sbostic
6265276Sbostic /* Skip leading space. */
6365276Sbostic for (; *p != '\0' && isspace(*p); ++p);
6465276Sbostic /* Skip empty/comment lines. */
6565276Sbostic if (*p == '\0' || *p == '#')
6665276Sbostic continue;
6765276Sbostic /* Find first token. */
6865276Sbostic for (t = p; *t && !isspace(*t); ++t);
6965276Sbostic if (*t == '\0') /* Need more than one token.*/
7065276Sbostic continue;
7165276Sbostic *t = '\0';
7242402Sbostic
7365279Sbostic for (tp = head.tqh_first; /* Find any matching tag. */
7465279Sbostic tp != NULL && strcmp(p, tp->s); tp = tp->q.tqe_next);
7542402Sbostic
7665279Sbostic if (tp == NULL) /* Create a new tag. */
7765279Sbostic tp = addlist(p);
7865276Sbostic
7965276Sbostic /*
8065276Sbostic * Attach new records. The keyword _build takes the rest of
8165276Sbostic * the line as a single entity, everything else is white
8265276Sbostic * space separated. The reason we're not just using strtok(3)
8365276Sbostic * for all of the parsing is so we don't get caught if a line
8465276Sbostic * has only a single token on it.
8565276Sbostic */
8665276Sbostic if (!strcmp(p, "_build")) {
8765276Sbostic while (*++t && isspace(*t));
8865276Sbostic if ((ep = malloc(sizeof(ENTRY))) == NULL ||
8965276Sbostic (ep->s = strdup(t)) == NULL)
9065276Sbostic err(1, NULL);
9165279Sbostic TAILQ_INSERT_TAIL(&tp->list, ep, q);
9265277Sbostic } else for (++t; (p = strtok(t, " \t\n")) != NULL; t = NULL) {
9365276Sbostic if ((ep = malloc(sizeof(ENTRY))) == NULL ||
9465276Sbostic (ep->s = strdup(p)) == NULL)
9565276Sbostic err(1, NULL);
9665279Sbostic TAILQ_INSERT_TAIL(&tp->list, ep, q);
9765276Sbostic }
9842402Sbostic }
99*68212Spendry
100*68212Spendry fclose(cfp);
10142402Sbostic }
10242402Sbostic
10365276Sbostic /*
10465276Sbostic * addlist --
10565276Sbostic * Add a tag to the list.
10665276Sbostic */
10765279Sbostic TAG *
addlist(name)10865276Sbostic addlist(name)
10965276Sbostic char *name;
11042402Sbostic {
11165279Sbostic TAG *tp;
11242402Sbostic
11365279Sbostic if ((tp = calloc(1, sizeof(TAG))) == NULL ||
11465279Sbostic (tp->s = strdup(name)) == NULL)
11565276Sbostic err(1, NULL);
11665279Sbostic TAILQ_INIT(&tp->list);
11765279Sbostic TAILQ_INSERT_TAIL(&head, tp, q);
11865279Sbostic return (tp);
11942257Sbostic }
12042257Sbostic
12165276Sbostic /*
12265276Sbostic * getlist --
12365279Sbostic * Return the linked list of entries for a tag if it exists.
12465276Sbostic */
12565279Sbostic TAG *
getlist(name)12665276Sbostic getlist(name)
12765276Sbostic char *name;
12842402Sbostic {
12965279Sbostic TAG *tp;
13042402Sbostic
13165279Sbostic for (tp = head.tqh_first; tp != NULL; tp = tp->q.tqe_next)
13265279Sbostic if (!strcmp(name, tp->s))
13365279Sbostic return (tp);
13465276Sbostic return (NULL);
13542402Sbostic }
13642402Sbostic
13765276Sbostic void
debug(l)13865276Sbostic debug(l)
13965276Sbostic char *l;
14042402Sbostic {
14165279Sbostic TAG *tp;
14265279Sbostic ENTRY *ep;
14342402Sbostic
14465276Sbostic (void)printf("%s ===============\n", l);
14565279Sbostic for (tp = head.tqh_first; tp != NULL; tp = tp->q.tqe_next) {
14665279Sbostic printf("%s\n", tp->s);
14765279Sbostic for (ep = tp->list.tqh_first; ep != NULL; ep = ep->q.tqe_next)
14865276Sbostic printf("\t%s\n", ep->s);
14942402Sbostic }
15042402Sbostic }
151