mkoptions.c revision 207265
112772Speter/*
212772Speter * Copyright (c) 1995  Peter Wemm
312772Speter * Copyright (c) 1980, 1993
412772Speter *	The Regents of the University of California.  All rights reserved.
512772Speter *
612772Speter * Redistribution and use in source and binary forms, with or without
712772Speter * modification, are permitted provided that the following conditions
812772Speter * are met:
912772Speter * 1. Redistributions of source code must retain the above copyright
1012772Speter *    notice, this list of conditions and the following disclaimer.
1112772Speter * 2. Redistributions in binary form must reproduce the above copyright
1212772Speter *    notice, this list of conditions and the following disclaimer in the
1312772Speter *    documentation and/or other materials provided with the distribution.
1412772Speter * 4. Neither the name of the University nor the names of its contributors
1512772Speter *    may be used to endorse or promote products derived from this software
1612772Speter *    without specific prior written permission.
1712772Speter *
1812772Speter * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
1912772Speter * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2012772Speter * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2112772Speter * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
2212772Speter * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2312772Speter * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2412772Speter * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2512772Speter * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2612772Speter * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2712772Speter * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2812772Speter * SUCH DAMAGE.
2912772Speter */
3012772Speter
3112772Speter#ifndef lint
3229451Scharnier#if 0
3312772Speterstatic char sccsid[] = "@(#)mkheaders.c	8.1 (Berkeley) 6/6/93";
3429451Scharnier#endif
3529451Scharnierstatic const char rcsid[] =
3650479Speter  "$FreeBSD: head/usr.sbin/config/mkoptions.c 207265 2010-04-27 06:14:30Z imp $";
3712772Speter#endif /* not lint */
3812772Speter
3912772Speter/*
4012772Speter * Make all the .h files for the optional entries
4112772Speter */
4212772Speter
4329451Scharnier#include <ctype.h>
4429451Scharnier#include <err.h>
4512772Speter#include <stdio.h>
4620458Sjoerg#include <string.h>
4769004Simp#include <sys/param.h>
4812772Speter#include "config.h"
4916073Sphk#include "y.tab.h"
5012772Speter
5137578Sbdestatic	struct users {
5237578Sbde	int	u_default;
5337578Sbde	int	u_min;
5437578Sbde	int	u_max;
55125935Sdes} users = { 8, 2, 512 };
5637578Sbde
5761640Speterstatic char *lower(char *);
5861640Speterstatic void read_options(void);
5961640Speterstatic void do_option(char *);
6061640Speterstatic char *tooption(char *);
6120458Sjoerg
6229451Scharniervoid
6361640Speteroptions(void)
6412772Speter{
6537578Sbde	char buf[40];
6637578Sbde	struct cputype *cp;
6712772Speter	struct opt_list *ol;
6837578Sbde	struct opt *op;
6912772Speter
7037578Sbde	/* Fake the cpu types as options. */
71110895Sru	SLIST_FOREACH(cp, &cputype, cpu_next) {
72159362Sdelphij		op = (struct opt *)calloc(1, sizeof(*op));
73205880Sru		if (op == NULL)
74205880Sru			err(EXIT_FAILURE, "calloc");
7520458Sjoerg		op->op_name = ns(cp->cpu_name);
76110895Sru		SLIST_INSERT_HEAD(&opt, op, op_next);
7712772Speter	}
7812772Speter
7937578Sbde	if (maxusers == 0) {
8087546Sdillon		/* printf("maxusers not specified; will auto-size\n"); */
8172000Speter	} else if (maxusers < users.u_min) {
8272000Speter		printf("minimum of %d maxusers assumed\n", users.u_min);
8372000Speter		maxusers = users.u_min;
8472000Speter	} else if (maxusers > users.u_max)
8572000Speter		printf("warning: maxusers > %d (%d)\n", users.u_max, maxusers);
8637578Sbde
8737578Sbde	/* Fake MAXUSERS as an option. */
88159362Sdelphij	op = (struct opt *)calloc(1, sizeof(*op));
89205880Sru	if (op == NULL)
90205880Sru		err(EXIT_FAILURE, "calloc");
9172684Speter	op->op_name = ns("MAXUSERS");
9246021Speter	snprintf(buf, sizeof(buf), "%d", maxusers);
9337578Sbde	op->op_value = ns(buf);
94110895Sru	SLIST_INSERT_HEAD(&opt, op, op_next);
9537578Sbde
9612772Speter	read_options();
97206664Simp	SLIST_FOREACH(op, &opt, op_next) {
98206664Simp		SLIST_FOREACH(ol, &otab, o_next) {
99206664Simp			if (eq(op->op_name, ol->o_name) &&
100206664Simp			    (ol->o_flags & OL_ALIAS)) {
101206664Simp				printf("Mapping option %s to %s.\n",
102206664Simp				    op->op_name, ol->o_file);
103206664Simp				op->op_name = ol->o_file;
104206664Simp				break;
105206664Simp			}
106206664Simp		}
107206664Simp	}
108110895Sru	SLIST_FOREACH(ol, &otab, o_next)
10912772Speter		do_option(ol->o_name);
110110895Sru	SLIST_FOREACH(op, &opt, op_next) {
11171251Speter		if (!op->op_ownfile && strncmp(op->op_name, "DEV_", 4)) {
11272841Speter			printf("%s: unknown option \"%s\"\n",
11372841Speter			       PREFIX, op->op_name);
11461523Speter			exit(1);
11561523Speter		}
11661523Speter	}
11712772Speter}
11812772Speter
11912772Speter/*
12012772Speter * Generate an <options>.h file
12112772Speter */
12212772Speter
12345744Speterstatic void
12461640Speterdo_option(char *name)
12512772Speter{
12672684Speter	char *file, *inw;
12772684Speter	const char *basefile;
12848401Speter	struct opt_list *ol;
129110895Sru	struct opt *op;
130110895Sru	struct opt_head op_head;
13112772Speter	FILE *inf, *outf;
13212772Speter	char *value;
13312772Speter	char *oldvalue;
13412772Speter	int seen;
13548401Speter	int tidy;
13612772Speter
13712772Speter	file = tooption(name);
13812772Speter	/*
13912772Speter	 * Check to see if the option was specified..
14012772Speter	 */
14112772Speter	value = NULL;
142110895Sru	SLIST_FOREACH(op, &opt, op_next) {
14312772Speter		if (eq(name, op->op_name)) {
14437577Sbde			oldvalue = value;
14512772Speter			value = op->op_value;
14637577Sbde			if (value == NULL)
14712772Speter				value = ns("1");
14837577Sbde			if (oldvalue != NULL && !eq(value, oldvalue))
14937577Sbde				printf(
15072841Speter			    "%s: option \"%s\" redefined from %s to %s\n",
15172841Speter				   PREFIX, op->op_name, oldvalue,
15237577Sbde				   value);
15312772Speter			op->op_ownfile++;
15412772Speter		}
15512772Speter	}
15612772Speter
15771866Speter	remember(file);
15812772Speter	inf = fopen(file, "r");
15912772Speter	if (inf == 0) {
16012772Speter		outf = fopen(file, "w");
16129451Scharnier		if (outf == 0)
16229451Scharnier			err(1, "%s", file);
16312772Speter
16412772Speter		/* was the option in the config file? */
16512772Speter		if (value) {
16612772Speter			fprintf(outf, "#define %s %s\n", name, value);
16712772Speter		} /* else empty file */
16812772Speter
169207263Simp		(void)fclose(outf);
17012772Speter		return;
17112772Speter	}
17255659Sbde	basefile = "";
173110895Sru	SLIST_FOREACH(ol, &otab, o_next)
17455659Sbde		if (eq(name, ol->o_name)) {
17555659Sbde			basefile = ol->o_file;
17655659Sbde			break;
17755659Sbde		}
17812772Speter	oldvalue = NULL;
179110895Sru	SLIST_INIT(&op_head);
18012772Speter	seen = 0;
18148401Speter	tidy = 0;
18212772Speter	for (;;) {
18312772Speter		char *cp;
18412772Speter		char *invalue;
18512772Speter
18612772Speter		/* get the #define */
18712772Speter		if ((inw = get_word(inf)) == 0 || inw == (char *)EOF)
18812772Speter			break;
18912772Speter		/* get the option name */
19012772Speter		if ((inw = get_word(inf)) == 0 || inw == (char *)EOF)
19112772Speter			break;
19212772Speter		inw = ns(inw);
19348401Speter		/* get the option value */
19448401Speter		if ((cp = get_word(inf)) == 0 || cp == (char *)EOF)
19512772Speter			break;
19612772Speter		/* option value */
19712772Speter		invalue = ns(cp); /* malloced */
19812772Speter		if (eq(inw, name)) {
19912772Speter			oldvalue = invalue;
20012772Speter			invalue = value;
20112772Speter			seen++;
20212772Speter		}
203110895Sru		SLIST_FOREACH(ol, &otab, o_next)
20448401Speter			if (eq(inw, ol->o_name))
20548401Speter				break;
20655603Sbde		if (!eq(inw, name) && !ol) {
20748401Speter			printf("WARNING: unknown option `%s' removed from %s\n",
20848401Speter				inw, file);
20948401Speter			tidy++;
21055659Sbde		} else if (ol != NULL && !eq(basefile, ol->o_file)) {
21155659Sbde			printf("WARNING: option `%s' moved from %s to %s\n",
21255659Sbde				inw, basefile, ol->o_file);
21355659Sbde			tidy++;
21448401Speter		} else {
215159362Sdelphij			op = (struct opt *) calloc(1, sizeof *op);
216205880Sru			if (op == NULL)
217205880Sru				err(EXIT_FAILURE, "calloc");
21848401Speter			op->op_name = inw;
21948401Speter			op->op_value = invalue;
220110895Sru			SLIST_INSERT_HEAD(&op_head, op, op_next);
22148401Speter		}
22212772Speter
22312772Speter		/* EOL? */
22412772Speter		cp = get_word(inf);
22512772Speter		if (cp == (char *)EOF)
22612772Speter			break;
22712772Speter	}
228207263Simp	(void)fclose(inf);
22948401Speter	if (!tidy && ((value == NULL && oldvalue == NULL) ||
23048401Speter	    (value && oldvalue && eq(value, oldvalue)))) {
231110895Sru		while (!SLIST_EMPTY(&op_head)) {
232110895Sru			op = SLIST_FIRST(&op_head);
233110895Sru			SLIST_REMOVE_HEAD(&op_head, op_next);
23412772Speter			free(op->op_name);
23512772Speter			free(op->op_value);
23612772Speter			free(op);
23712772Speter		}
23812772Speter		return;
23912772Speter	}
24012772Speter
24112772Speter	if (value && !seen) {
24212772Speter		/* New option appears */
243159362Sdelphij		op = (struct opt *) calloc(1, sizeof *op);
244205880Sru		if (op == NULL)
245205880Sru			err(EXIT_FAILURE, "calloc");
24612772Speter		op->op_name = ns(name);
24712772Speter		op->op_value = value ? ns(value) : NULL;
248110895Sru		SLIST_INSERT_HEAD(&op_head, op, op_next);
24912772Speter	}
25012772Speter
25112772Speter	outf = fopen(file, "w");
25229451Scharnier	if (outf == 0)
25329451Scharnier		err(1, "%s", file);
254110895Sru	while (!SLIST_EMPTY(&op_head)) {
255110895Sru		op = SLIST_FIRST(&op_head);
25612772Speter		/* was the option in the config file? */
25712772Speter		if (op->op_value) {
25812772Speter			fprintf(outf, "#define %s %s\n",
25912772Speter				op->op_name, op->op_value);
26012772Speter		}
261110895Sru		SLIST_REMOVE_HEAD(&op_head, op_next);
26212772Speter		free(op->op_name);
26312772Speter		free(op->op_value);
26412772Speter		free(op);
26512772Speter	}
266207263Simp	(void)fclose(outf);
26712772Speter}
26812772Speter
26912772Speter/*
27012772Speter * Find the filename to store the option spec into.
27112772Speter */
27245744Speterstatic char *
27361640Spetertooption(char *name)
27412772Speter{
27569004Simp	static char hbuf[MAXPATHLEN];
27669004Simp	char nbuf[MAXPATHLEN];
27712772Speter	struct opt_list *po;
27812772Speter
27912772Speter	/* "cannot happen"?  the otab list should be complete.. */
280207263Simp	(void)strlcpy(nbuf, "options.h", sizeof(nbuf));
28112772Speter
282110895Sru	SLIST_FOREACH(po, &otab, o_next) {
28312772Speter		if (eq(po->o_name, name)) {
28469004Simp			strlcpy(nbuf, po->o_file, sizeof(nbuf));
28512772Speter			break;
28612772Speter		}
28712772Speter	}
28812772Speter
289207263Simp	(void)strlcpy(hbuf, path(nbuf), sizeof(hbuf));
29012772Speter	return (hbuf);
29112772Speter}
29212772Speter
293207263Simp
29445744Speterstatic void
295207265Simpcheck_duplicate(const char *fname, const char *this)
29612772Speter{
297207263Simp	struct opt_list *po;
298207263Simp
299207265Simp	SLIST_FOREACH(po, &otab, o_next) {
300207265Simp		if (eq(po->o_name, this)) {
301207265Simp			printf("%s: Duplicate option %s.\n",
302207265Simp			       fname, this);
303207265Simp			exit(1);
304207265Simp		}
305207265Simp	}
306207265Simp}
307207265Simp
308207265Simpstatic void
309207265Simpinsert_option(const char *fname, char *this, char *val)
310207265Simp{
311207265Simp	struct opt_list *po;
312207265Simp
313207265Simp	check_duplicate(fname, this);
314207263Simp	po = (struct opt_list *) calloc(1, sizeof *po);
315207263Simp	if (po == NULL)
316207263Simp		err(EXIT_FAILURE, "calloc");
317207263Simp	po->o_name = this;
318207263Simp	po->o_file = val;
319207265Simp	po->o_flags = 0;
320207263Simp	SLIST_INSERT_HEAD(&otab, po, o_next);
321207263Simp}
322207263Simp
323207263Simpstatic void
324207265Simpupdate_option(const char *this, char *val, int flags)
325207263Simp{
326207263Simp	struct opt_list *po;
327207263Simp
328207263Simp	SLIST_FOREACH(po, &otab, o_next) {
329207263Simp		if (eq(po->o_name, this)) {
330207265Simp			free(po->o_file);
331207265Simp			po->o_file = val;
332207265Simp			po->o_flags = flags;
333207265Simp			return;
334207263Simp		}
335207263Simp	}
336207265Simp	printf("Compat option %s not listed in options file.\n", this);
337207265Simp	exit(1);
338207263Simp}
339207263Simp
340207263Simpstatic int
341207263Simpread_option_file(const char *fname, int flags)
342207263Simp{
34312772Speter	FILE *fp;
34412772Speter	char *wd, *this, *val;
34569004Simp	char genopt[MAXPATHLEN];
34612772Speter
34712772Speter	fp = fopen(fname, "r");
348207263Simp	if (fp == 0)
349207263Simp		return (0);
350207263Simp	while ((wd = get_word(fp)) != (char *)EOF) {
351207263Simp		if (wd == 0)
352207263Simp			continue;
353207263Simp		if (wd[0] == '#') {
354207263Simp			while (((wd = get_word(fp)) != (char *)EOF) && wd)
355207263Simp				continue;
356207263Simp			continue;
35712772Speter		}
358207263Simp		this = ns(wd);
359206664Simp		val = get_word(fp);
360207263Simp		if (val == (char *)EOF)
361207263Simp			return (1);
362206664Simp		if (val == 0) {
363207263Simp			if (flags) {
364207263Simp				printf("%s: compat file requires two words "
365207263Simp				    "per line at %s\n", fname, this);
366207263Simp				exit(1);
367207263Simp			}
368207263Simp			char *s = ns(this);
369207263Simp			(void)snprintf(genopt, sizeof(genopt), "opt_%s.h",
370207263Simp			    lower(s));
371207263Simp			val = genopt;
372207263Simp			free(s);
373206664Simp		}
374207263Simp		val = ns(val);
375207265Simp		if (flags == 0)
376207265Simp			insert_option(fname, this, val);
377207265Simp		else
378207265Simp			update_option(this, val, flags);
37912772Speter	}
380207263Simp	(void)fclose(fp);
381207263Simp	return (1);
382207263Simp}
38312772Speter
384207263Simp/*
385207263Simp * read the options and options.<machine> files
386207263Simp */
387207263Simpstatic void
388207263Simpread_options(void)
389207263Simp{
390207263Simp	char fname[MAXPATHLEN];
391207263Simp
392207263Simp	SLIST_INIT(&otab);
393207263Simp	read_option_file("../../conf/options", 0);
394207263Simp	(void)snprintf(fname, sizeof fname, "../../conf/options.%s",
395207263Simp	    machinename);
396207263Simp	if (!read_option_file(fname, 0)) {
397207263Simp		(void)snprintf(fname, sizeof fname, "options.%s", machinename);
398207263Simp		read_option_file(fname, 0);
39912772Speter	}
400207263Simp	read_option_file("../../conf/options-compat", OL_ALIAS);
40112772Speter}
40212772Speter
40320458Sjoergstatic char *
40461640Speterlower(char *str)
40512772Speter{
40661640Speter	char *cp = str;
40712772Speter
40812772Speter	while (*str) {
40912772Speter		if (isupper(*str))
41012772Speter			*str = tolower(*str);
41112772Speter		str++;
41212772Speter	}
41312772Speter	return (cp);
41412772Speter}
415