mkoptions.c revision 205880
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 205880 2010-03-30 13:46:40Z ru $";
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();
97110895Sru	SLIST_FOREACH(ol, &otab, o_next)
9812772Speter		do_option(ol->o_name);
99110895Sru	SLIST_FOREACH(op, &opt, op_next) {
10071251Speter		if (!op->op_ownfile && strncmp(op->op_name, "DEV_", 4)) {
10172841Speter			printf("%s: unknown option \"%s\"\n",
10272841Speter			       PREFIX, op->op_name);
10361523Speter			exit(1);
10461523Speter		}
10561523Speter	}
10612772Speter}
10712772Speter
10812772Speter/*
10912772Speter * Generate an <options>.h file
11012772Speter */
11112772Speter
11245744Speterstatic void
11361640Speterdo_option(char *name)
11412772Speter{
11572684Speter	char *file, *inw;
11672684Speter	const char *basefile;
11748401Speter	struct opt_list *ol;
118110895Sru	struct opt *op;
119110895Sru	struct opt_head op_head;
12012772Speter	FILE *inf, *outf;
12112772Speter	char *value;
12212772Speter	char *oldvalue;
12312772Speter	int seen;
12448401Speter	int tidy;
12512772Speter
12612772Speter	file = tooption(name);
12712772Speter
12812772Speter	/*
12912772Speter	 * Check to see if the option was specified..
13012772Speter	 */
13112772Speter	value = NULL;
132110895Sru	SLIST_FOREACH(op, &opt, op_next) {
13312772Speter		if (eq(name, op->op_name)) {
13437577Sbde			oldvalue = value;
13512772Speter			value = op->op_value;
13637577Sbde			if (value == NULL)
13712772Speter				value = ns("1");
13837577Sbde			if (oldvalue != NULL && !eq(value, oldvalue))
13937577Sbde				printf(
14072841Speter			    "%s: option \"%s\" redefined from %s to %s\n",
14172841Speter				   PREFIX, op->op_name, oldvalue,
14237577Sbde				   value);
14312772Speter			op->op_ownfile++;
14412772Speter		}
14512772Speter	}
14612772Speter
14771866Speter	remember(file);
14812772Speter	inf = fopen(file, "r");
14912772Speter	if (inf == 0) {
15012772Speter		outf = fopen(file, "w");
15129451Scharnier		if (outf == 0)
15229451Scharnier			err(1, "%s", file);
15312772Speter
15412772Speter		/* was the option in the config file? */
15512772Speter		if (value) {
15612772Speter			fprintf(outf, "#define %s %s\n", name, value);
15712772Speter		} /* else empty file */
15812772Speter
15912772Speter		(void) fclose(outf);
16012772Speter		return;
16112772Speter	}
16255659Sbde	basefile = "";
163110895Sru	SLIST_FOREACH(ol, &otab, o_next)
16455659Sbde		if (eq(name, ol->o_name)) {
16555659Sbde			basefile = ol->o_file;
16655659Sbde			break;
16755659Sbde		}
16812772Speter	oldvalue = NULL;
169110895Sru	SLIST_INIT(&op_head);
17012772Speter	seen = 0;
17148401Speter	tidy = 0;
17212772Speter	for (;;) {
17312772Speter		char *cp;
17412772Speter		char *invalue;
17512772Speter
17612772Speter		/* get the #define */
17712772Speter		if ((inw = get_word(inf)) == 0 || inw == (char *)EOF)
17812772Speter			break;
17912772Speter		/* get the option name */
18012772Speter		if ((inw = get_word(inf)) == 0 || inw == (char *)EOF)
18112772Speter			break;
18212772Speter		inw = ns(inw);
18348401Speter		/* get the option value */
18448401Speter		if ((cp = get_word(inf)) == 0 || cp == (char *)EOF)
18512772Speter			break;
18612772Speter		/* option value */
18712772Speter		invalue = ns(cp); /* malloced */
18812772Speter		if (eq(inw, name)) {
18912772Speter			oldvalue = invalue;
19012772Speter			invalue = value;
19112772Speter			seen++;
19212772Speter		}
193110895Sru		SLIST_FOREACH(ol, &otab, o_next)
19448401Speter			if (eq(inw, ol->o_name))
19548401Speter				break;
19655603Sbde		if (!eq(inw, name) && !ol) {
19748401Speter			printf("WARNING: unknown option `%s' removed from %s\n",
19848401Speter				inw, file);
19948401Speter			tidy++;
20055659Sbde		} else if (ol != NULL && !eq(basefile, ol->o_file)) {
20155659Sbde			printf("WARNING: option `%s' moved from %s to %s\n",
20255659Sbde				inw, basefile, ol->o_file);
20355659Sbde			tidy++;
20448401Speter		} else {
205159362Sdelphij			op = (struct opt *) calloc(1, sizeof *op);
206205880Sru			if (op == NULL)
207205880Sru				err(EXIT_FAILURE, "calloc");
20848401Speter			op->op_name = inw;
20948401Speter			op->op_value = invalue;
210110895Sru			SLIST_INSERT_HEAD(&op_head, op, op_next);
21148401Speter		}
21212772Speter
21312772Speter		/* EOL? */
21412772Speter		cp = get_word(inf);
21512772Speter		if (cp == (char *)EOF)
21612772Speter			break;
21712772Speter	}
21812772Speter	(void) fclose(inf);
21948401Speter	if (!tidy && ((value == NULL && oldvalue == NULL) ||
22048401Speter	    (value && oldvalue && eq(value, oldvalue)))) {
221110895Sru		while (!SLIST_EMPTY(&op_head)) {
222110895Sru			op = SLIST_FIRST(&op_head);
223110895Sru			SLIST_REMOVE_HEAD(&op_head, op_next);
22412772Speter			free(op->op_name);
22512772Speter			free(op->op_value);
22612772Speter			free(op);
22712772Speter		}
22812772Speter		return;
22912772Speter	}
23012772Speter
23112772Speter	if (value && !seen) {
23212772Speter		/* New option appears */
233159362Sdelphij		op = (struct opt *) calloc(1, sizeof *op);
234205880Sru		if (op == NULL)
235205880Sru			err(EXIT_FAILURE, "calloc");
23612772Speter		op->op_name = ns(name);
23712772Speter		op->op_value = value ? ns(value) : NULL;
238110895Sru		SLIST_INSERT_HEAD(&op_head, op, op_next);
23912772Speter	}
24012772Speter
24112772Speter	outf = fopen(file, "w");
24229451Scharnier	if (outf == 0)
24329451Scharnier		err(1, "%s", file);
244110895Sru	while (!SLIST_EMPTY(&op_head)) {
245110895Sru		op = SLIST_FIRST(&op_head);
24612772Speter		/* was the option in the config file? */
24712772Speter		if (op->op_value) {
24812772Speter			fprintf(outf, "#define %s %s\n",
24912772Speter				op->op_name, op->op_value);
25012772Speter		}
251110895Sru		SLIST_REMOVE_HEAD(&op_head, op_next);
25212772Speter		free(op->op_name);
25312772Speter		free(op->op_value);
25412772Speter		free(op);
25512772Speter	}
25612772Speter	(void) fclose(outf);
25712772Speter}
25812772Speter
25912772Speter/*
26012772Speter * Find the filename to store the option spec into.
26112772Speter */
26245744Speterstatic char *
26361640Spetertooption(char *name)
26412772Speter{
26569004Simp	static char hbuf[MAXPATHLEN];
26669004Simp	char nbuf[MAXPATHLEN];
26712772Speter	struct opt_list *po;
26812772Speter
26912772Speter	/* "cannot happen"?  the otab list should be complete.. */
27069004Simp	(void) strlcpy(nbuf, "options.h", sizeof(nbuf));
27112772Speter
272110895Sru	SLIST_FOREACH(po, &otab, o_next) {
27312772Speter		if (eq(po->o_name, name)) {
27469004Simp			strlcpy(nbuf, po->o_file, sizeof(nbuf));
27512772Speter			break;
27612772Speter		}
27712772Speter	}
27812772Speter
27969004Simp	(void) strlcpy(hbuf, path(nbuf), sizeof(hbuf));
28012772Speter	return (hbuf);
28112772Speter}
28212772Speter
28312772Speter/*
28412772Speter * read the options and options.<machine> files
28512772Speter */
28645744Speterstatic void
28761640Speterread_options(void)
28812772Speter{
28912772Speter	FILE *fp;
29069004Simp	char fname[MAXPATHLEN];
29112772Speter	char *wd, *this, *val;
29212772Speter	struct opt_list *po;
29312772Speter	int first = 1;
29469004Simp	char genopt[MAXPATHLEN];
29512772Speter
296110895Sru	SLIST_INIT(&otab);
29769004Simp	(void) snprintf(fname, sizeof(fname), "../../conf/options");
29812772Speteropenit:
29912772Speter	fp = fopen(fname, "r");
30012772Speter	if (fp == 0) {
30112772Speter		return;
30212772Speter	}
30312772Speternext:
30412772Speter	wd = get_word(fp);
30512772Speter	if (wd == (char *)EOF) {
30612772Speter		(void) fclose(fp);
30712772Speter		if (first == 1) {
30855614Speter			first++;
30955614Speter			(void) snprintf(fname, sizeof fname, "../../conf/options.%s", machinename);
31055614Speter			fp = fopen(fname, "r");
31155614Speter			if (fp != 0)
31255614Speter				goto next;
31320457Sjoerg			(void) snprintf(fname, sizeof fname, "options.%s", machinename);
31412772Speter			goto openit;
31512772Speter		}
31612772Speter		return;
31712772Speter	}
31812772Speter	if (wd == 0)
31912772Speter		goto next;
32052098Speter	if (wd[0] == '#')
32112772Speter	{
32252098Speter		while (((wd = get_word(fp)) != (char *)EOF) && wd)
32312772Speter		;
32412772Speter		goto next;
32512772Speter	}
32612772Speter	this = ns(wd);
32712772Speter	val = get_word(fp);
32812772Speter	if (val == (char *)EOF)
32912772Speter		return;
33012772Speter	if (val == 0) {
33112772Speter		char *s = ns(this);
33269004Simp		(void) snprintf(genopt, sizeof(genopt), "opt_%s.h", lower(s));
33312772Speter		val = genopt;
33412772Speter		free(s);
33512772Speter	}
33612772Speter	val = ns(val);
33712772Speter
338110895Sru	SLIST_FOREACH(po, &otab, o_next) {
33912772Speter		if (eq(po->o_name, this)) {
34012772Speter			printf("%s: Duplicate option %s.\n",
34112772Speter			       fname, this);
34212772Speter			exit(1);
34312772Speter		}
34412772Speter	}
34512772Speter
346159362Sdelphij	po = (struct opt_list *) calloc(1, sizeof *po);
347205880Sru	if (po == NULL)
348205880Sru		err(EXIT_FAILURE, "calloc");
34912772Speter	po->o_name = this;
35012772Speter	po->o_file = val;
351110895Sru	SLIST_INSERT_HEAD(&otab, po, o_next);
35212772Speter
35312772Speter	goto next;
35412772Speter}
35512772Speter
35620458Sjoergstatic char *
35761640Speterlower(char *str)
35812772Speter{
35961640Speter	char *cp = str;
36012772Speter
36112772Speter	while (*str) {
36212772Speter		if (isupper(*str))
36312772Speter			*str = tolower(*str);
36412772Speter		str++;
36512772Speter	}
36612772Speter	return (cp);
36712772Speter}
368