mkoptions.c revision 125935
1336821Sdim/*
2336821Sdim * Copyright (c) 1995  Peter Wemm
3353358Sdim * Copyright (c) 1980, 1993
4353358Sdim *	The Regents of the University of California.  All rights reserved.
5353358Sdim *
6336821Sdim * Redistribution and use in source and binary forms, with or without
7336821Sdim * modification, are permitted provided that the following conditions
8336821Sdim * are met:
9336821Sdim * 1. Redistributions of source code must retain the above copyright
10336821Sdim *    notice, this list of conditions and the following disclaimer.
11336821Sdim * 2. Redistributions in binary form must reproduce the above copyright
12336821Sdim *    notice, this list of conditions and the following disclaimer in the
13336821Sdim *    documentation and/or other materials provided with the distribution.
14336821Sdim * 3. All advertising materials mentioning features or use of this software
15336821Sdim *    must display the following acknowledgement:
16353358Sdim *	This product includes software developed by the University of
17336821Sdim *	California, Berkeley and its contributors.
18336821Sdim * 4. Neither the name of the University nor the names of its contributors
19353358Sdim *    may be used to endorse or promote products derived from this software
20336821Sdim *    without specific prior written permission.
21353358Sdim *
22353358Sdim * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23336821Sdim * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24336821Sdim * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25336821Sdim * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26336821Sdim * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27353358Sdim * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28353358Sdim * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29353358Sdim * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30336821Sdim * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31336821Sdim * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32353358Sdim * SUCH DAMAGE.
33353358Sdim */
34353358Sdim
35336821Sdim#ifndef lint
36336821Sdim#if 0
37336821Sdimstatic char sccsid[] = "@(#)mkheaders.c	8.1 (Berkeley) 6/6/93";
38353358Sdim#endif
39336821Sdimstatic const char rcsid[] =
40336821Sdim  "$FreeBSD: head/usr.sbin/config/mkoptions.c 125935 2004-02-17 09:59:45Z des $";
41336821Sdim#endif /* not lint */
42353358Sdim
43353358Sdim/*
44336821Sdim * Make all the .h files for the optional entries
45336821Sdim */
46336821Sdim
47353358Sdim#include <ctype.h>
48336821Sdim#include <err.h>
49336821Sdim#include <stdio.h>
50336821Sdim#include <string.h>
51353358Sdim#include <sys/param.h>
52353358Sdim#include "config.h"
53336821Sdim#include "y.tab.h"
54336821Sdim
55336821Sdimstatic	struct users {
56336821Sdim	int	u_default;
57336821Sdim	int	u_min;
58336821Sdim	int	u_max;
59336821Sdim} users = { 8, 2, 512 };
60336821Sdim
61353358Sdimstatic char *lower(char *);
62336821Sdimstatic void read_options(void);
63336821Sdimstatic void do_option(char *);
64336821Sdimstatic char *tooption(char *);
65353358Sdim
66353358Sdimvoid
67336821Sdimoptions(void)
68353358Sdim{
69353358Sdim	char buf[40];
70353358Sdim	struct cputype *cp;
71353358Sdim	struct opt_list *ol;
72336821Sdim	struct opt *op;
73353358Sdim
74336821Sdim	/* Fake the cpu types as options. */
75353358Sdim	SLIST_FOREACH(cp, &cputype, cpu_next) {
76353358Sdim		op = (struct opt *)malloc(sizeof(*op));
77353358Sdim		memset(op, 0, sizeof(*op));
78336821Sdim		op->op_name = ns(cp->cpu_name);
79336821Sdim		SLIST_INSERT_HEAD(&opt, op, op_next);
80	}
81
82	if (maxusers == 0) {
83		/* printf("maxusers not specified; will auto-size\n"); */
84	} else if (maxusers < users.u_min) {
85		printf("minimum of %d maxusers assumed\n", users.u_min);
86		maxusers = users.u_min;
87	} else if (maxusers > users.u_max)
88		printf("warning: maxusers > %d (%d)\n", users.u_max, maxusers);
89
90	/* Fake MAXUSERS as an option. */
91	op = (struct opt *)malloc(sizeof(*op));
92	memset(op, 0, sizeof(*op));
93	op->op_name = ns("MAXUSERS");
94	snprintf(buf, sizeof(buf), "%d", maxusers);
95	op->op_value = ns(buf);
96	SLIST_INSERT_HEAD(&opt, op, op_next);
97
98	read_options();
99	SLIST_FOREACH(ol, &otab, o_next)
100		do_option(ol->o_name);
101	SLIST_FOREACH(op, &opt, op_next) {
102		if (!op->op_ownfile && strncmp(op->op_name, "DEV_", 4)) {
103			printf("%s: unknown option \"%s\"\n",
104			       PREFIX, op->op_name);
105			exit(1);
106		}
107	}
108}
109
110/*
111 * Generate an <options>.h file
112 */
113
114static void
115do_option(char *name)
116{
117	char *file, *inw;
118	const char *basefile;
119	struct opt_list *ol;
120	struct opt *op;
121	struct opt_head op_head;
122	FILE *inf, *outf;
123	char *value;
124	char *oldvalue;
125	int seen;
126	int tidy;
127
128	file = tooption(name);
129
130	/*
131	 * Check to see if the option was specified..
132	 */
133	value = NULL;
134	SLIST_FOREACH(op, &opt, op_next) {
135		if (eq(name, op->op_name)) {
136			oldvalue = value;
137			value = op->op_value;
138			if (value == NULL)
139				value = ns("1");
140			if (oldvalue != NULL && !eq(value, oldvalue))
141				printf(
142			    "%s: option \"%s\" redefined from %s to %s\n",
143				   PREFIX, op->op_name, oldvalue,
144				   value);
145			op->op_ownfile++;
146		}
147	}
148
149	remember(file);
150	inf = fopen(file, "r");
151	if (inf == 0) {
152		outf = fopen(file, "w");
153		if (outf == 0)
154			err(1, "%s", file);
155
156		/* was the option in the config file? */
157		if (value) {
158			fprintf(outf, "#define %s %s\n", name, value);
159		} /* else empty file */
160
161		(void) fclose(outf);
162		return;
163	}
164	basefile = "";
165	SLIST_FOREACH(ol, &otab, o_next)
166		if (eq(name, ol->o_name)) {
167			basefile = ol->o_file;
168			break;
169		}
170	oldvalue = NULL;
171	SLIST_INIT(&op_head);
172	seen = 0;
173	tidy = 0;
174	for (;;) {
175		char *cp;
176		char *invalue;
177
178		/* get the #define */
179		if ((inw = get_word(inf)) == 0 || inw == (char *)EOF)
180			break;
181		/* get the option name */
182		if ((inw = get_word(inf)) == 0 || inw == (char *)EOF)
183			break;
184		inw = ns(inw);
185		/* get the option value */
186		if ((cp = get_word(inf)) == 0 || cp == (char *)EOF)
187			break;
188		/* option value */
189		invalue = ns(cp); /* malloced */
190		if (eq(inw, name)) {
191			oldvalue = invalue;
192			invalue = value;
193			seen++;
194		}
195		SLIST_FOREACH(ol, &otab, o_next)
196			if (eq(inw, ol->o_name))
197				break;
198		if (!eq(inw, name) && !ol) {
199			printf("WARNING: unknown option `%s' removed from %s\n",
200				inw, file);
201			tidy++;
202		} else if (ol != NULL && !eq(basefile, ol->o_file)) {
203			printf("WARNING: option `%s' moved from %s to %s\n",
204				inw, basefile, ol->o_file);
205			tidy++;
206		} else {
207			op = (struct opt *) malloc(sizeof *op);
208			bzero(op, sizeof(*op));
209			op->op_name = inw;
210			op->op_value = invalue;
211			SLIST_INSERT_HEAD(&op_head, op, op_next);
212		}
213
214		/* EOL? */
215		cp = get_word(inf);
216		if (cp == (char *)EOF)
217			break;
218	}
219	(void) fclose(inf);
220	if (!tidy && ((value == NULL && oldvalue == NULL) ||
221	    (value && oldvalue && eq(value, oldvalue)))) {
222		while (!SLIST_EMPTY(&op_head)) {
223			op = SLIST_FIRST(&op_head);
224			SLIST_REMOVE_HEAD(&op_head, op_next);
225			free(op->op_name);
226			free(op->op_value);
227			free(op);
228		}
229		return;
230	}
231
232	if (value && !seen) {
233		/* New option appears */
234		op = (struct opt *) malloc(sizeof *op);
235		bzero(op, sizeof(*op));
236		op->op_name = ns(name);
237		op->op_value = value ? ns(value) : NULL;
238		SLIST_INSERT_HEAD(&op_head, op, op_next);
239	}
240
241	outf = fopen(file, "w");
242	if (outf == 0)
243		err(1, "%s", file);
244	while (!SLIST_EMPTY(&op_head)) {
245		op = SLIST_FIRST(&op_head);
246		/* was the option in the config file? */
247		if (op->op_value) {
248			fprintf(outf, "#define %s %s\n",
249				op->op_name, op->op_value);
250		}
251		SLIST_REMOVE_HEAD(&op_head, op_next);
252		free(op->op_name);
253		free(op->op_value);
254		free(op);
255	}
256	(void) fclose(outf);
257}
258
259/*
260 * Find the filename to store the option spec into.
261 */
262static char *
263tooption(char *name)
264{
265	static char hbuf[MAXPATHLEN];
266	char nbuf[MAXPATHLEN];
267	struct opt_list *po;
268
269	/* "cannot happen"?  the otab list should be complete.. */
270	(void) strlcpy(nbuf, "options.h", sizeof(nbuf));
271
272	SLIST_FOREACH(po, &otab, o_next) {
273		if (eq(po->o_name, name)) {
274			strlcpy(nbuf, po->o_file, sizeof(nbuf));
275			break;
276		}
277	}
278
279	(void) strlcpy(hbuf, path(nbuf), sizeof(hbuf));
280	return (hbuf);
281}
282
283/*
284 * read the options and options.<machine> files
285 */
286static void
287read_options(void)
288{
289	FILE *fp;
290	char fname[MAXPATHLEN];
291	char *wd, *this, *val;
292	struct opt_list *po;
293	int first = 1;
294	char genopt[MAXPATHLEN];
295
296	SLIST_INIT(&otab);
297	if (ident == NULL) {
298		printf("no ident line specified\n");
299		exit(1);
300	}
301	(void) snprintf(fname, sizeof(fname), "../../conf/options");
302openit:
303	fp = fopen(fname, "r");
304	if (fp == 0) {
305		return;
306	}
307next:
308	wd = get_word(fp);
309	if (wd == (char *)EOF) {
310		(void) fclose(fp);
311		if (first == 1) {
312			first++;
313			(void) snprintf(fname, sizeof fname, "../../conf/options.%s", machinename);
314			fp = fopen(fname, "r");
315			if (fp != 0)
316				goto next;
317			(void) snprintf(fname, sizeof fname, "options.%s", machinename);
318			goto openit;
319		}
320		return;
321	}
322	if (wd == 0)
323		goto next;
324	if (wd[0] == '#')
325	{
326		while (((wd = get_word(fp)) != (char *)EOF) && wd)
327		;
328		goto next;
329	}
330	this = ns(wd);
331	val = get_word(fp);
332	if (val == (char *)EOF)
333		return;
334	if (val == 0) {
335		char *s = ns(this);
336		(void) snprintf(genopt, sizeof(genopt), "opt_%s.h", lower(s));
337		val = genopt;
338		free(s);
339	}
340	val = ns(val);
341
342	SLIST_FOREACH(po, &otab, o_next) {
343		if (eq(po->o_name, this)) {
344			printf("%s: Duplicate option %s.\n",
345			       fname, this);
346			exit(1);
347		}
348	}
349
350	po = (struct opt_list *) malloc(sizeof *po);
351	bzero(po, sizeof(*po));
352	po->o_name = this;
353	po->o_file = val;
354	SLIST_INSERT_HEAD(&otab, po, o_next);
355
356	goto next;
357}
358
359static char *
360lower(char *str)
361{
362	char *cp = str;
363
364	while (*str) {
365		if (isupper(*str))
366			*str = tolower(*str);
367		str++;
368	}
369	return (cp);
370}
371