1 /* $OpenBSD: config.c,v 1.6 2004/09/15 22:20:03 deraadt Exp $ */
2 /* $NetBSD: config.c,v 1.7 1995/09/28 06:05:21 tls Exp $ */
3
4 /*
5 * Copyright (c) 1989, 1993, 1995
6 * The Regents of the University of California. All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. Neither the name of the University nor the names of its contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 */
32
33 #ifndef lint
34 #if 0
35 static char sccsid[] = "@(#)config.c 8.8 (Berkeley) 1/31/95";
36 #else
37 static char rcsid[] = "$OpenBSD: config.c,v 1.6 2004/09/15 22:20:03 deraadt Exp $";
38 #endif
39 #endif /* not lint */
40
41 #include <sys/types.h>
42 #include <sys/queue.h>
43
44 #include <ctype.h>
45 #include <err.h>
46 #include <errno.h>
47 #include <stdio.h>
48 #include <stdlib.h>
49 #include <string.h>
50
51 #include "config.h"
52 #include "pathnames.h"
53
54 struct _head head;
55
56 /*
57 * config --
58 *
59 * Read the configuration file and build a doubly linked
60 * list that looks like:
61 *
62 * tag1 <-> record <-> record <-> record
63 * |
64 * tag2 <-> record <-> record <-> record
65 */
66 void
config(char * fname)67 config(char *fname)
68 {
69 TAG *tp;
70 ENTRY *ep;
71 FILE *cfp;
72 size_t len;
73 int lcnt;
74 char *p, *t;
75
76 if (fname == NULL)
77 fname = _PATH_MANCONF;
78 if ((cfp = fopen(fname, "r")) == NULL)
79 err(1, "%s", fname);
80 TAILQ_INIT(&head);
81 for (lcnt = 1; (p = fgetln(cfp, &len)) != NULL; ++lcnt) {
82 if (len == 1) /* Skip empty lines. */
83 continue;
84 if (p[len - 1] != '\n') { /* Skip corrupted lines. */
85 warnx("%s: line %d corrupted", fname, lcnt);
86 continue;
87 }
88 p[len - 1] = '\0'; /* Terminate the line. */
89
90 /* Skip leading space. */
91 while (*p != '\0' && isspace(*p))
92 p++;
93 /* Skip empty/comment lines. */
94 if (*p == '\0' || *p == '#')
95 continue;
96 /* Find first token. */
97 for (t = p; *t && !isspace(*t); ++t)
98 continue;
99 if (*t == '\0') /* Need more than one token.*/
100 continue;
101 *t = '\0';
102
103 for (tp = head.tqh_first; /* Find any matching tag. */
104 tp != NULL && strcmp(p, tp->s); tp = tp->q.tqe_next);
105
106 if (tp == NULL) /* Create a new tag. */
107 tp = addlist(p);
108
109 /*
110 * Attach new records. The keyword _build takes the rest of
111 * the line as a single entity, everything else is white
112 * space separated. The reason we're not just using strtok(3)
113 * for all of the parsing is so we don't get caught if a line
114 * has only a single token on it.
115 */
116 if (!strcmp(p, "_build")) {
117 while (*++t && isspace(*t));
118 if ((ep = malloc(sizeof(ENTRY))) == NULL ||
119 (ep->s = strdup(t)) == NULL)
120 err(1, NULL);
121 TAILQ_INSERT_TAIL(&tp->list, ep, q);
122 } else for (++t; (p = strtok(t, " \t\n")) != NULL; t = NULL) {
123 if ((ep = malloc(sizeof(ENTRY))) == NULL ||
124 (ep->s = strdup(p)) == NULL)
125 err(1, NULL);
126 TAILQ_INSERT_TAIL(&tp->list, ep, q);
127 }
128 }
129
130 fclose(cfp);
131 }
132
133 /*
134 * addlist --
135 * Add a tag to the list.
136 */
137 TAG *
addlist(char * name)138 addlist(char *name)
139 {
140 TAG *tp;
141
142 if ((tp = calloc(1, sizeof(TAG))) == NULL ||
143 (tp->s = strdup(name)) == NULL)
144 err(1, NULL);
145 TAILQ_INIT(&tp->list);
146 TAILQ_INSERT_TAIL(&head, tp, q);
147 return (tp);
148 }
149
150 /*
151 * getlist --
152 * Return the linked list of entries for a tag if it exists.
153 */
154 TAG *
getlist(char * name)155 getlist(char *name)
156 {
157 TAG *tp;
158
159 for (tp = head.tqh_first; tp != NULL; tp = tp->q.tqe_next)
160 if (!strcmp(name, tp->s))
161 return (tp);
162 return (NULL);
163 }
164