mkoptions.c revision 69004
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 * 3. All advertising materials mentioning features or use of this software
1512772Speter *    must display the following acknowledgement:
1612772Speter *	This product includes software developed by the University of
1712772Speter *	California, Berkeley and its contributors.
1812772Speter * 4. Neither the name of the University nor the names of its contributors
1912772Speter *    may be used to endorse or promote products derived from this software
2012772Speter *    without specific prior written permission.
2112772Speter *
2212772Speter * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
2312772Speter * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2412772Speter * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2512772Speter * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
2612772Speter * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2712772Speter * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2812772Speter * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2912772Speter * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
3012772Speter * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3112772Speter * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3212772Speter * SUCH DAMAGE.
3312772Speter */
3412772Speter
3512772Speter#ifndef lint
3629451Scharnier#if 0
3712772Speterstatic char sccsid[] = "@(#)mkheaders.c	8.1 (Berkeley) 6/6/93";
3829451Scharnier#endif
3929451Scharnierstatic const char rcsid[] =
4050479Speter  "$FreeBSD: head/usr.sbin/config/mkoptions.c 69004 2000-11-21 19:58:55Z imp $";
4112772Speter#endif /* not lint */
4212772Speter
4312772Speter/*
4412772Speter * Make all the .h files for the optional entries
4512772Speter */
4612772Speter
4729451Scharnier#include <ctype.h>
4829451Scharnier#include <err.h>
4912772Speter#include <stdio.h>
5020458Sjoerg#include <string.h>
5169004Simp#include <sys/param.h>
5212772Speter#include "config.h"
5316073Sphk#include "y.tab.h"
5412772Speter
5537578Sbdestatic	struct users {
5637578Sbde	int	u_default;
5737578Sbde	int	u_min;
5837578Sbde	int	u_max;
5937578Sbde} users[] = {
6037578Sbde	{ 8, 2, 512 },			/* MACHINE_I386 */
6137578Sbde	{ 8, 2, 512 },			/* MACHINE_PC98 */
6237578Sbde	{ 8, 2, 512 },			/* MACHINE_ALPHA */
6366457Sdfr	{ 8, 2, 512 },			/* MACHINE_IA64 */
6437578Sbde};
6537578Sbde#define	NUSERS	(sizeof (users) / sizeof (users[0]))
6637578Sbde
6761640Speterstatic char *lower(char *);
6861640Speterstatic void read_options(void);
6961640Speterstatic void do_option(char *);
7061640Speterstatic char *tooption(char *);
7120458Sjoerg
7229451Scharniervoid
7361640Speteroptions(void)
7412772Speter{
7537578Sbde	char buf[40];
7637578Sbde	struct cputype *cp;
7712772Speter	struct opt_list *ol;
7837578Sbde	struct opt *op;
7937578Sbde	struct users *up;
8012772Speter
8137578Sbde	/* Fake the cpu types as options. */
8237578Sbde	for (cp = cputype; cp != NULL; cp = cp->cpu_next) {
8337578Sbde		op = (struct opt *)malloc(sizeof(*op));
8412772Speter		memset(op, 0, sizeof(*op));
8520458Sjoerg		op->op_name = ns(cp->cpu_name);
8612772Speter		op->op_next = opt;
8712772Speter		opt = op;
8812772Speter	}
8912772Speter
9037578Sbde	/* Initialize `maxusers'. */
9137578Sbde	if ((unsigned)machine > NUSERS) {
9245775Speter		printf("maxusers config info isn't present, using i386\n");
9345744Speter		up = &users[MACHINE_I386 - 1];
9437578Sbde	} else
9537578Sbde		up = &users[machine - 1];
9637578Sbde	if (maxusers == 0) {
9737578Sbde		printf("maxusers not specified; %d assumed\n", up->u_default);
9837578Sbde		maxusers = up->u_default;
9937578Sbde	} else if (maxusers < up->u_min) {
10037578Sbde		printf("minimum of %d maxusers assumed\n", up->u_min);
10137578Sbde		maxusers = up->u_min;
10237578Sbde	} else if (maxusers > up->u_max)
10337578Sbde		printf("warning: maxusers > %d (%d)\n", up->u_max, maxusers);
10437578Sbde
10537578Sbde	/* Fake MAXUSERS as an option. */
10637578Sbde	op = (struct opt *)malloc(sizeof(*op));
10737578Sbde	memset(op, 0, sizeof(*op));
10837578Sbde	op->op_name = "MAXUSERS";
10946021Speter	snprintf(buf, sizeof(buf), "%d", maxusers);
11037578Sbde	op->op_value = ns(buf);
11137578Sbde	op->op_next = opt;
11237578Sbde	opt = op;
11337578Sbde
11412772Speter	read_options();
11512772Speter	for (ol = otab; ol != 0; ol = ol->o_next)
11612772Speter		do_option(ol->o_name);
11761523Speter	for (op = opt; op; op = op->op_next) {
11861523Speter		if (!op->op_ownfile) {
11961523Speter			printf("%s:%d: unknown option \"%s\"\n",
12061523Speter			       PREFIX, op->op_line, op->op_name);
12161523Speter			exit(1);
12261523Speter		}
12361523Speter	}
12412772Speter}
12512772Speter
12612772Speter/*
12712772Speter * Generate an <options>.h file
12812772Speter */
12912772Speter
13045744Speterstatic void
13161640Speterdo_option(char *name)
13212772Speter{
13355659Sbde	char *basefile, *file, *inw;
13448401Speter	struct opt_list *ol;
13512772Speter	struct opt *op, *op_head, *topp;
13612772Speter	FILE *inf, *outf;
13712772Speter	char *value;
13812772Speter	char *oldvalue;
13912772Speter	int seen;
14048401Speter	int tidy;
14112772Speter
14212772Speter	file = tooption(name);
14312772Speter
14412772Speter	/*
14512772Speter	 * Check to see if the option was specified..
14612772Speter	 */
14712772Speter	value = NULL;
14812772Speter	for (op = opt; op; op = op->op_next) {
14912772Speter		if (eq(name, op->op_name)) {
15037577Sbde			oldvalue = value;
15112772Speter			value = op->op_value;
15237577Sbde			if (value == NULL)
15312772Speter				value = ns("1");
15437577Sbde			if (oldvalue != NULL && !eq(value, oldvalue))
15537577Sbde				printf(
15637577Sbde			    "%s:%d: option \"%s\" redefined from %s to %s\n",
15737577Sbde				   PREFIX, op->op_line, op->op_name, oldvalue,
15837577Sbde				   value);
15912772Speter			op->op_ownfile++;
16012772Speter		}
16112772Speter	}
16212772Speter
16312772Speter	inf = fopen(file, "r");
16412772Speter	if (inf == 0) {
16512772Speter		outf = fopen(file, "w");
16629451Scharnier		if (outf == 0)
16729451Scharnier			err(1, "%s", file);
16812772Speter
16912772Speter		/* was the option in the config file? */
17012772Speter		if (value) {
17112772Speter			fprintf(outf, "#define %s %s\n", name, value);
17212772Speter		} /* else empty file */
17312772Speter
17412772Speter		(void) fclose(outf);
17512772Speter		return;
17612772Speter	}
17755659Sbde	basefile = "";
17855659Sbde	for (ol = otab; ol != 0; ol = ol->o_next)
17955659Sbde		if (eq(name, ol->o_name)) {
18055659Sbde			basefile = ol->o_file;
18155659Sbde			break;
18255659Sbde		}
18312772Speter	oldvalue = NULL;
18412772Speter	op_head = NULL;
18512772Speter	seen = 0;
18648401Speter	tidy = 0;
18712772Speter	for (;;) {
18812772Speter		char *cp;
18912772Speter		char *invalue;
19012772Speter
19112772Speter		/* get the #define */
19212772Speter		if ((inw = get_word(inf)) == 0 || inw == (char *)EOF)
19312772Speter			break;
19412772Speter		/* get the option name */
19512772Speter		if ((inw = get_word(inf)) == 0 || inw == (char *)EOF)
19612772Speter			break;
19712772Speter		inw = ns(inw);
19848401Speter		/* get the option value */
19948401Speter		if ((cp = get_word(inf)) == 0 || cp == (char *)EOF)
20012772Speter			break;
20112772Speter		/* option value */
20212772Speter		invalue = ns(cp); /* malloced */
20312772Speter		if (eq(inw, name)) {
20412772Speter			oldvalue = invalue;
20512772Speter			invalue = value;
20612772Speter			seen++;
20712772Speter		}
20848401Speter		for (ol = otab; ol != 0; ol = ol->o_next)
20948401Speter			if (eq(inw, ol->o_name))
21048401Speter				break;
21155603Sbde		if (!eq(inw, name) && !ol) {
21248401Speter			printf("WARNING: unknown option `%s' removed from %s\n",
21348401Speter				inw, file);
21448401Speter			tidy++;
21555659Sbde		} else if (ol != NULL && !eq(basefile, ol->o_file)) {
21655659Sbde			printf("WARNING: option `%s' moved from %s to %s\n",
21755659Sbde				inw, basefile, ol->o_file);
21855659Sbde			tidy++;
21948401Speter		} else {
22048401Speter			op = (struct opt *) malloc(sizeof *op);
22148401Speter			bzero(op, sizeof(*op));
22248401Speter			op->op_name = inw;
22348401Speter			op->op_value = invalue;
22448401Speter			op->op_next = op_head;
22548401Speter			op_head = op;
22648401Speter		}
22712772Speter
22812772Speter		/* EOL? */
22912772Speter		cp = get_word(inf);
23012772Speter		if (cp == (char *)EOF)
23112772Speter			break;
23212772Speter	}
23312772Speter	(void) fclose(inf);
23448401Speter	if (!tidy && ((value == NULL && oldvalue == NULL) ||
23548401Speter	    (value && oldvalue && eq(value, oldvalue)))) {
23612772Speter		for (op = op_head; op != NULL; op = topp) {
23712772Speter			topp = op->op_next;
23812772Speter			free(op->op_name);
23912772Speter			free(op->op_value);
24012772Speter			free(op);
24112772Speter		}
24212772Speter		return;
24312772Speter	}
24412772Speter
24512772Speter	if (value && !seen) {
24612772Speter		/* New option appears */
24712772Speter		op = (struct opt *) malloc(sizeof *op);
24812772Speter		bzero(op, sizeof(*op));
24912772Speter		op->op_name = ns(name);
25012772Speter		op->op_value = value ? ns(value) : NULL;
25112772Speter		op->op_next = op_head;
25212772Speter		op_head = op;
25312772Speter	}
25412772Speter
25512772Speter	outf = fopen(file, "w");
25629451Scharnier	if (outf == 0)
25729451Scharnier		err(1, "%s", file);
25812772Speter	for (op = op_head; op != NULL; op = topp) {
25912772Speter		/* was the option in the config file? */
26012772Speter		if (op->op_value) {
26112772Speter			fprintf(outf, "#define %s %s\n",
26212772Speter				op->op_name, op->op_value);
26312772Speter		}
26412772Speter		topp = op->op_next;
26512772Speter		free(op->op_name);
26612772Speter		free(op->op_value);
26712772Speter		free(op);
26812772Speter	}
26912772Speter	(void) fclose(outf);
27012772Speter}
27112772Speter
27212772Speter/*
27312772Speter * Find the filename to store the option spec into.
27412772Speter */
27545744Speterstatic char *
27661640Spetertooption(char *name)
27712772Speter{
27869004Simp	static char hbuf[MAXPATHLEN];
27969004Simp	char nbuf[MAXPATHLEN];
28012772Speter	struct opt_list *po;
28112772Speter
28212772Speter	/* "cannot happen"?  the otab list should be complete.. */
28369004Simp	(void) strlcpy(nbuf, "options.h", sizeof(nbuf));
28412772Speter
28512772Speter	for (po = otab ; po != 0; po = po->o_next) {
28612772Speter		if (eq(po->o_name, name)) {
28769004Simp			strlcpy(nbuf, po->o_file, sizeof(nbuf));
28812772Speter			break;
28912772Speter		}
29012772Speter	}
29112772Speter
29269004Simp	(void) strlcpy(hbuf, path(nbuf), sizeof(hbuf));
29312772Speter	return (hbuf);
29412772Speter}
29512772Speter
29612772Speter/*
29712772Speter * read the options and options.<machine> files
29812772Speter */
29945744Speterstatic void
30061640Speterread_options(void)
30112772Speter{
30212772Speter	FILE *fp;
30369004Simp	char fname[MAXPATHLEN];
30412772Speter	char *wd, *this, *val;
30512772Speter	struct opt_list *po;
30612772Speter	int first = 1;
30769004Simp	char genopt[MAXPATHLEN];
30812772Speter
30912772Speter	otab = 0;
31055614Speter	if (ident == NULL) {
31155614Speter		printf("no ident line specified\n");
31255614Speter		exit(1);
31355614Speter	}
31469004Simp	(void) snprintf(fname, sizeof(fname), "../../conf/options");
31512772Speteropenit:
31612772Speter	fp = fopen(fname, "r");
31712772Speter	if (fp == 0) {
31812772Speter		return;
31912772Speter	}
32012772Speternext:
32112772Speter	wd = get_word(fp);
32212772Speter	if (wd == (char *)EOF) {
32312772Speter		(void) fclose(fp);
32412772Speter		if (first == 1) {
32555614Speter			first++;
32655614Speter			(void) snprintf(fname, sizeof fname, "../../conf/options.%s", machinename);
32755614Speter			fp = fopen(fname, "r");
32855614Speter			if (fp != 0)
32955614Speter				goto next;
33020457Sjoerg			(void) snprintf(fname, sizeof fname, "options.%s", machinename);
33112772Speter			goto openit;
33212772Speter		}
33312772Speter		if (first == 2) {
33455614Speter			first++;
33545744Speter			(void) snprintf(fname, sizeof fname, "options.%s", raisestr(ident));
33612772Speter			fp = fopen(fname, "r");
33712772Speter			if (fp != 0)
33812772Speter				goto next;
33912772Speter		}
34012772Speter		return;
34112772Speter	}
34212772Speter	if (wd == 0)
34312772Speter		goto next;
34452098Speter	if (wd[0] == '#')
34512772Speter	{
34652098Speter		while (((wd = get_word(fp)) != (char *)EOF) && wd)
34712772Speter		;
34812772Speter		goto next;
34912772Speter	}
35012772Speter	this = ns(wd);
35112772Speter	val = get_word(fp);
35212772Speter	if (val == (char *)EOF)
35312772Speter		return;
35412772Speter	if (val == 0) {
35512772Speter		char *s = ns(this);
35669004Simp		(void) snprintf(genopt, sizeof(genopt), "opt_%s.h", lower(s));
35712772Speter		val = genopt;
35812772Speter		free(s);
35912772Speter	}
36012772Speter	val = ns(val);
36112772Speter
36212772Speter	for (po = otab ; po != 0; po = po->o_next) {
36312772Speter		if (eq(po->o_name, this)) {
36412772Speter			printf("%s: Duplicate option %s.\n",
36512772Speter			       fname, this);
36612772Speter			exit(1);
36712772Speter		}
36812772Speter	}
36912772Speter
37012772Speter	po = (struct opt_list *) malloc(sizeof *po);
37112772Speter	bzero(po, sizeof(*po));
37212772Speter	po->o_name = this;
37312772Speter	po->o_file = val;
37412772Speter	po->o_next = otab;
37512772Speter	otab = po;
37612772Speter
37712772Speter	goto next;
37812772Speter}
37912772Speter
38020458Sjoergstatic char *
38161640Speterlower(char *str)
38212772Speter{
38361640Speter	char *cp = str;
38412772Speter
38512772Speter	while (*str) {
38612772Speter		if (isupper(*str))
38712772Speter			*str = tolower(*str);
38812772Speter		str++;
38912772Speter	}
39012772Speter	return (cp);
39112772Speter}
392