]> CyberLeo.Net >> Repos - FreeBSD/releng/8.2.git/blob - usr.sbin/config/mkoptions.c
MFC r213265:
[FreeBSD/releng/8.2.git] / usr.sbin / config / mkoptions.c
1 /*
2  * Copyright (c) 1995  Peter Wemm
3  * Copyright (c) 1980, 1993
4  *      The Regents of the University of California.  All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  * 4. Neither the name of the University nor the names of its contributors
15  *    may be used to endorse or promote products derived from this software
16  *    without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
19  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
22  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28  * SUCH DAMAGE.
29  */
30
31 #ifndef lint
32 #if 0
33 static char sccsid[] = "@(#)mkheaders.c 8.1 (Berkeley) 6/6/93";
34 #endif
35 static const char rcsid[] =
36   "$FreeBSD$";
37 #endif /* not lint */
38
39 /*
40  * Make all the .h files for the optional entries
41  */
42
43 #include <ctype.h>
44 #include <err.h>
45 #include <stdio.h>
46 #include <string.h>
47 #include <sys/param.h>
48 #include "config.h"
49 #include "y.tab.h"
50
51 static  struct users {
52         int     u_default;
53         int     u_min;
54         int     u_max;
55 } users = { 8, 2, 512 };
56
57 static char *lower(char *);
58 static void read_options(void);
59 static void do_option(char *);
60 static char *tooption(char *);
61
62 void
63 options(void)
64 {
65         char buf[40];
66         struct cputype *cp;
67         struct opt_list *ol;
68         struct opt *op;
69
70         /* Fake the cpu types as options. */
71         SLIST_FOREACH(cp, &cputype, cpu_next) {
72                 op = (struct opt *)calloc(1, sizeof(*op));
73                 if (op == NULL)
74                         err(EXIT_FAILURE, "calloc");
75                 op->op_name = ns(cp->cpu_name);
76                 SLIST_INSERT_HEAD(&opt, op, op_next);
77         }       
78
79         if (maxusers == 0) {
80                 /* printf("maxusers not specified; will auto-size\n"); */
81         } else if (maxusers < users.u_min) {
82                 printf("minimum of %d maxusers assumed\n", users.u_min);
83                 maxusers = users.u_min;
84         } else if (maxusers > users.u_max)
85                 printf("warning: maxusers > %d (%d)\n", users.u_max, maxusers);
86
87         /* Fake MAXUSERS as an option. */
88         op = (struct opt *)calloc(1, sizeof(*op));
89         if (op == NULL)
90                 err(EXIT_FAILURE, "calloc");
91         op->op_name = ns("MAXUSERS");
92         snprintf(buf, sizeof(buf), "%d", maxusers);
93         op->op_value = ns(buf);
94         SLIST_INSERT_HEAD(&opt, op, op_next);
95
96         read_options();
97
98         /* Fake the value of MACHINE_ARCH as an option if necessary */
99         SLIST_FOREACH(ol, &otab, o_next) {
100                 if (strcasecmp(ol->o_name, machinearch) != 0)
101                         continue;
102
103                 op = (struct opt *)calloc(1, sizeof(*op));
104                 if (op == NULL)
105                         err(EXIT_FAILURE, "calloc");
106                 op->op_name = ns(ol->o_name);
107                 SLIST_INSERT_HEAD(&opt, op, op_next);
108                 break;
109         }
110
111         SLIST_FOREACH(op, &opt, op_next) {
112                 SLIST_FOREACH(ol, &otab, o_next) {
113                         if (eq(op->op_name, ol->o_name) &&
114                             (ol->o_flags & OL_ALIAS)) {
115                                 printf("Mapping option %s to %s.\n",
116                                     op->op_name, ol->o_file);
117                                 op->op_name = ol->o_file;
118                                 break;
119                         }
120                 }
121         }
122         SLIST_FOREACH(ol, &otab, o_next)
123                 do_option(ol->o_name);
124         SLIST_FOREACH(op, &opt, op_next) {
125                 if (!op->op_ownfile && strncmp(op->op_name, "DEV_", 4)) {
126                         printf("%s: unknown option \"%s\"\n",
127                                PREFIX, op->op_name);
128                         exit(1);
129                 }
130         }
131 }
132
133 /*
134  * Generate an <options>.h file
135  */
136
137 static void
138 do_option(char *name)
139 {
140         char *file, *inw;
141         const char *basefile;
142         struct opt_list *ol;
143         struct opt *op;
144         struct opt_head op_head;
145         FILE *inf, *outf;
146         char *value;
147         char *oldvalue;
148         int seen;
149         int tidy;
150
151         file = tooption(name);
152         /*
153          * Check to see if the option was specified..
154          */
155         value = NULL;
156         SLIST_FOREACH(op, &opt, op_next) {
157                 if (eq(name, op->op_name)) {
158                         oldvalue = value;
159                         value = op->op_value;
160                         if (value == NULL)
161                                 value = ns("1");
162                         if (oldvalue != NULL && !eq(value, oldvalue))
163                                 printf(
164                             "%s: option \"%s\" redefined from %s to %s\n",
165                                    PREFIX, op->op_name, oldvalue,
166                                    value);
167                         op->op_ownfile++;
168                 }
169         }
170
171         remember(file);
172         inf = fopen(file, "r");
173         if (inf == 0) {
174                 outf = fopen(file, "w");
175                 if (outf == 0)
176                         err(1, "%s", file);
177
178                 /* was the option in the config file? */
179                 if (value) {
180                         fprintf(outf, "#define %s %s\n", name, value);
181                 } /* else empty file */
182
183                 (void)fclose(outf);
184                 return;
185         }
186         basefile = "";
187         SLIST_FOREACH(ol, &otab, o_next)
188                 if (eq(name, ol->o_name)) {
189                         basefile = ol->o_file;
190                         break;
191                 }
192         oldvalue = NULL;
193         SLIST_INIT(&op_head);
194         seen = 0;
195         tidy = 0;
196         for (;;) {
197                 char *cp;
198                 char *invalue;
199
200                 /* get the #define */
201                 if ((inw = get_word(inf)) == 0 || inw == (char *)EOF)
202                         break;
203                 /* get the option name */
204                 if ((inw = get_word(inf)) == 0 || inw == (char *)EOF)
205                         break;
206                 inw = ns(inw);
207                 /* get the option value */
208                 if ((cp = get_word(inf)) == 0 || cp == (char *)EOF)
209                         break;
210                 /* option value */
211                 invalue = ns(cp); /* malloced */
212                 if (eq(inw, name)) {
213                         oldvalue = invalue;
214                         invalue = value;
215                         seen++;
216                 }
217                 SLIST_FOREACH(ol, &otab, o_next)
218                         if (eq(inw, ol->o_name))
219                                 break;
220                 if (!eq(inw, name) && !ol) {
221                         printf("WARNING: unknown option `%s' removed from %s\n",
222                                 inw, file);
223                         tidy++;
224                 } else if (ol != NULL && !eq(basefile, ol->o_file)) {
225                         printf("WARNING: option `%s' moved from %s to %s\n",
226                                 inw, basefile, ol->o_file);
227                         tidy++;
228                 } else {
229                         op = (struct opt *) calloc(1, sizeof *op);
230                         if (op == NULL)
231                                 err(EXIT_FAILURE, "calloc");
232                         op->op_name = inw;
233                         op->op_value = invalue;
234                         SLIST_INSERT_HEAD(&op_head, op, op_next);
235                 }
236
237                 /* EOL? */
238                 cp = get_word(inf);
239                 if (cp == (char *)EOF)
240                         break;
241         }
242         (void)fclose(inf);
243         if (!tidy && ((value == NULL && oldvalue == NULL) ||
244             (value && oldvalue && eq(value, oldvalue)))) {      
245                 while (!SLIST_EMPTY(&op_head)) {
246                         op = SLIST_FIRST(&op_head);
247                         SLIST_REMOVE_HEAD(&op_head, op_next);
248                         free(op->op_name);
249                         free(op->op_value);
250                         free(op);
251                 }
252                 return;
253         }
254
255         if (value && !seen) {
256                 /* New option appears */
257                 op = (struct opt *) calloc(1, sizeof *op);
258                 if (op == NULL)
259                         err(EXIT_FAILURE, "calloc");
260                 op->op_name = ns(name);
261                 op->op_value = value ? ns(value) : NULL;
262                 SLIST_INSERT_HEAD(&op_head, op, op_next);
263         }
264
265         outf = fopen(file, "w");
266         if (outf == 0)
267                 err(1, "%s", file);
268         while (!SLIST_EMPTY(&op_head)) {
269                 op = SLIST_FIRST(&op_head);
270                 /* was the option in the config file? */
271                 if (op->op_value) {
272                         fprintf(outf, "#define %s %s\n",
273                                 op->op_name, op->op_value);
274                 }
275                 SLIST_REMOVE_HEAD(&op_head, op_next);
276                 free(op->op_name);
277                 free(op->op_value);
278                 free(op);
279         }
280         (void)fclose(outf);
281 }
282
283 /*
284  * Find the filename to store the option spec into.
285  */
286 static char *
287 tooption(char *name)
288 {
289         static char hbuf[MAXPATHLEN];
290         char nbuf[MAXPATHLEN];
291         struct opt_list *po;
292
293         /* "cannot happen"?  the otab list should be complete.. */
294         (void)strlcpy(nbuf, "options.h", sizeof(nbuf));
295
296         SLIST_FOREACH(po, &otab, o_next) {
297                 if (eq(po->o_name, name)) {
298                         strlcpy(nbuf, po->o_file, sizeof(nbuf));
299                         break;
300                 }
301         }
302
303         (void)strlcpy(hbuf, path(nbuf), sizeof(hbuf));
304         return (hbuf);
305 }
306
307         
308 static void
309 check_duplicate(const char *fname, const char *this)
310 {
311         struct opt_list *po;
312
313         SLIST_FOREACH(po, &otab, o_next) {
314                 if (eq(po->o_name, this)) {
315                         printf("%s: Duplicate option %s.\n",
316                                fname, this);
317                         exit(1);
318                 }
319         }
320 }
321
322 static void
323 insert_option(const char *fname, char *this, char *val)
324 {
325         struct opt_list *po;
326
327         check_duplicate(fname, this);
328         po = (struct opt_list *) calloc(1, sizeof *po);
329         if (po == NULL)
330                 err(EXIT_FAILURE, "calloc");
331         po->o_name = this;
332         po->o_file = val;
333         po->o_flags = 0;
334         SLIST_INSERT_HEAD(&otab, po, o_next);
335 }
336
337 static void
338 update_option(const char *this, char *val, int flags)
339 {
340         struct opt_list *po;
341
342         SLIST_FOREACH(po, &otab, o_next) {
343                 if (eq(po->o_name, this)) {
344                         free(po->o_file);
345                         po->o_file = val;
346                         po->o_flags = flags;
347                         return;
348                 }
349         }
350         printf("Compat option %s not listed in options file.\n", this);
351         exit(1);
352 }
353
354 static int
355 read_option_file(const char *fname, int flags)
356 {
357         FILE *fp;
358         char *wd, *this, *val;
359         char genopt[MAXPATHLEN];
360
361         fp = fopen(fname, "r");
362         if (fp == 0)
363                 return (0);
364         while ((wd = get_word(fp)) != (char *)EOF) {
365                 if (wd == 0)
366                         continue;
367                 if (wd[0] == '#') {
368                         while (((wd = get_word(fp)) != (char *)EOF) && wd)
369                                 continue;
370                         continue;
371                 }
372                 this = ns(wd);
373                 val = get_word(fp);
374                 if (val == (char *)EOF)
375                         return (1);
376                 if (val == 0) {
377                         if (flags) {
378                                 printf("%s: compat file requires two words "
379                                     "per line at %s\n", fname, this);
380                                 exit(1);
381                         }
382                         char *s = ns(this);
383                         (void)snprintf(genopt, sizeof(genopt), "opt_%s.h",
384                             lower(s));
385                         val = genopt;
386                         free(s);
387                 }
388                 val = ns(val);
389                 if (flags == 0)
390                         insert_option(fname, this, val);
391                 else
392                         update_option(this, val, flags);
393         }
394         (void)fclose(fp);
395         return (1);
396 }
397
398 /*
399  * read the options and options.<machine> files
400  */
401 static void
402 read_options(void)
403 {
404         char fname[MAXPATHLEN];
405
406         SLIST_INIT(&otab);
407         read_option_file("../../conf/options", 0);
408         (void)snprintf(fname, sizeof fname, "../../conf/options.%s",
409             machinename);
410         if (!read_option_file(fname, 0)) {
411                 (void)snprintf(fname, sizeof fname, "options.%s", machinename);
412                 read_option_file(fname, 0);
413         }
414         read_option_file("../../conf/options-compat", OL_ALIAS);
415 }
416
417 static char *
418 lower(char *str)
419 {
420         char *cp = str;
421
422         while (*str) {
423                 if (isupper(*str))
424                         *str = tolower(*str);
425                 str++;
426         }
427         return (cp);
428 }