1 /*
2 * Copyright (c) 1989, 1993, 1995
3 * The Regents of the University of California. All rights reserved.
4 *
5 * %sccs.include.redist.c%
6 */
7
8 #ifndef lint
9 static char sccsid[] = "@(#)config.c 8.8 (Berkeley) 01/31/95";
10 #endif /* not lint */
11
12 #include <sys/types.h>
13 #include <sys/queue.h>
14
15 #include <ctype.h>
16 #include <err.h>
17 #include <errno.h>
18 #include <stdio.h>
19 #include <stdlib.h>
20 #include <string.h>
21
22 #include "config.h"
23 #include "pathnames.h"
24
25 struct _head head;
26
27 /*
28 * config --
29 *
30 * Read the configuration file and build a doubly linked
31 * list that looks like:
32 *
33 * tag1 <-> record <-> record <-> record
34 * |
35 * tag2 <-> record <-> record <-> record
36 */
37 void
config(fname)38 config(fname)
39 char *fname;
40 {
41 TAG *tp;
42 ENTRY *ep;
43 FILE *cfp;
44 size_t len;
45 int lcnt;
46 char *p, *t;
47
48 if (fname == NULL)
49 fname = _PATH_MANCONF;
50 if ((cfp = fopen(fname, "r")) == NULL)
51 err(1, "%s", fname);
52 TAILQ_INIT(&head);
53 for (lcnt = 1; (p = fgetln(cfp, &len)) != NULL; ++lcnt) {
54 if (len == 1) /* Skip empty lines. */
55 continue;
56 if (p[len - 1] != '\n') { /* Skip corrupted lines. */
57 warnx("%s: line %d corrupted", fname, lcnt);
58 continue;
59 }
60 p[len - 1] = '\0'; /* Terminate the line. */
61
62 /* Skip leading space. */
63 for (; *p != '\0' && isspace(*p); ++p);
64 /* Skip empty/comment lines. */
65 if (*p == '\0' || *p == '#')
66 continue;
67 /* Find first token. */
68 for (t = p; *t && !isspace(*t); ++t);
69 if (*t == '\0') /* Need more than one token.*/
70 continue;
71 *t = '\0';
72
73 for (tp = head.tqh_first; /* Find any matching tag. */
74 tp != NULL && strcmp(p, tp->s); tp = tp->q.tqe_next);
75
76 if (tp == NULL) /* Create a new tag. */
77 tp = addlist(p);
78
79 /*
80 * Attach new records. The keyword _build takes the rest of
81 * the line as a single entity, everything else is white
82 * space separated. The reason we're not just using strtok(3)
83 * for all of the parsing is so we don't get caught if a line
84 * has only a single token on it.
85 */
86 if (!strcmp(p, "_build")) {
87 while (*++t && isspace(*t));
88 if ((ep = malloc(sizeof(ENTRY))) == NULL ||
89 (ep->s = strdup(t)) == NULL)
90 err(1, NULL);
91 TAILQ_INSERT_TAIL(&tp->list, ep, q);
92 } else for (++t; (p = strtok(t, " \t\n")) != NULL; t = NULL) {
93 if ((ep = malloc(sizeof(ENTRY))) == NULL ||
94 (ep->s = strdup(p)) == NULL)
95 err(1, NULL);
96 TAILQ_INSERT_TAIL(&tp->list, ep, q);
97 }
98 }
99
100 fclose(cfp);
101 }
102
103 /*
104 * addlist --
105 * Add a tag to the list.
106 */
107 TAG *
addlist(name)108 addlist(name)
109 char *name;
110 {
111 TAG *tp;
112
113 if ((tp = calloc(1, sizeof(TAG))) == NULL ||
114 (tp->s = strdup(name)) == NULL)
115 err(1, NULL);
116 TAILQ_INIT(&tp->list);
117 TAILQ_INSERT_TAIL(&head, tp, q);
118 return (tp);
119 }
120
121 /*
122 * getlist --
123 * Return the linked list of entries for a tag if it exists.
124 */
125 TAG *
getlist(name)126 getlist(name)
127 char *name;
128 {
129 TAG *tp;
130
131 for (tp = head.tqh_first; tp != NULL; tp = tp->q.tqe_next)
132 if (!strcmp(name, tp->s))
133 return (tp);
134 return (NULL);
135 }
136
137 void
debug(l)138 debug(l)
139 char *l;
140 {
141 TAG *tp;
142 ENTRY *ep;
143
144 (void)printf("%s ===============\n", l);
145 for (tp = head.tqh_first; tp != NULL; tp = tp->q.tqe_next) {
146 printf("%s\n", tp->s);
147 for (ep = tp->list.tqh_first; ep != NULL; ep = ep->q.tqe_next)
148 printf("\t%s\n", ep->s);
149 }
150 }
151