1/*	$NetBSD: main.c,v 1.101 2024/01/18 04:41:37 thorpej Exp $	*/
2
3/*
4 * Copyright (c) 1992, 1993
5 *	The Regents of the University of California.  All rights reserved.
6 *
7 * This software was developed by the Computer Systems Engineering group
8 * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
9 * contributed to Berkeley.
10 *
11 * All advertising materials mentioning features or use of this software
12 * must display the following acknowledgement:
13 *	This product includes software developed by the University of
14 *	California, Lawrence Berkeley Laboratories.
15 *
16 * Redistribution and use in source and binary forms, with or without
17 * modification, are permitted provided that the following conditions
18 * are met:
19 * 1. Redistributions of source code must retain the above copyright
20 *    notice, this list of conditions and the following disclaimer.
21 * 2. Redistributions in binary form must reproduce the above copyright
22 *    notice, this list of conditions and the following disclaimer in the
23 *    documentation and/or other materials provided with the distribution.
24 * 3. Neither the name of the University nor the names of its contributors
25 *    may be used to endorse or promote products derived from this software
26 *    without specific prior written permission.
27 *
28 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
29 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
30 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
31 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
32 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
33 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
34 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
35 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
36 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
37 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
38 * SUCH DAMAGE.
39 *
40 *	from: @(#)main.c	8.1 (Berkeley) 6/6/93
41 */
42
43#if HAVE_NBTOOL_CONFIG_H
44#include "nbtool_config.h"
45#endif
46
47#include <sys/cdefs.h>
48__RCSID("$NetBSD: main.c,v 1.101 2024/01/18 04:41:37 thorpej Exp $");
49
50#ifndef MAKE_BOOTSTRAP
51#include <sys/cdefs.h>
52#define	COPYRIGHT(x)	__COPYRIGHT(x)
53#else
54#define	COPYRIGHT(x)	static const char copyright[] = x
55#endif
56
57#ifndef lint
58COPYRIGHT("@(#) Copyright (c) 1992, 1993\
59 The Regents of the University of California.  All rights reserved.");
60#endif /* not lint */
61
62#include <sys/types.h>
63#include <sys/stat.h>
64#include <sys/param.h>
65#include <sys/mman.h>
66#if !HAVE_NBTOOL_CONFIG_H
67#include <sys/sysctl.h>
68#endif
69#include <paths.h>
70#include <ctype.h>
71#include <err.h>
72#include <errno.h>
73#include <fcntl.h>
74#include <limits.h>
75#include <stdio.h>
76#include <stdlib.h>
77#include <string.h>
78#include <unistd.h>
79#include <vis.h>
80#include <util.h>
81
82#include "defs.h"
83#include "sem.h"
84
85#ifndef LINE_MAX
86#define LINE_MAX 1024
87#endif
88
89struct devbasetq allbases;
90struct devatq alldevas;
91struct conftq allcf;
92struct devitq alldevi, allpseudo;
93struct devmtq alldevms;
94struct pspectq allpspecs;
95
96struct devi **packed;
97size_t npacked;
98
99struct locators locators;
100
101int lkmmode;
102const char *conffile;		/* source file, e.g., "GENERIC.sparc" */
103const char *machine;		/* machine type, e.g., "sparc" or "sun3" */
104const char *machinearch;	/* machine arch, e.g., "sparc" or "m68k" */
105struct	nvlist *machinesubarches;
106				/* machine subarches, e.g., "sun68k" or "hpc" */
107const char *ioconfname;		/* ioconf name, mutually exclusive to machine */
108const char *srcdir;		/* path to source directory (rel. to build) */
109const char *builddir;		/* path to build directory */
110const char *defbuilddir;	/* default build directory */
111const char *ident;		/* kernel "ident"ification string */
112int	errors;			/* counts calls to error() */
113int	minmaxusers;		/* minimum "maxusers" parameter */
114int	defmaxusers;		/* default "maxusers" parameter */
115int	maxmaxusers;		/* default "maxusers" parameter */
116int	maxusers;		/* configuration's "maxusers" parameter */
117int	maxpartitions;		/* configuration's "maxpartitions" parameter */
118int	version;		/* version of the configuration file */
119struct	nvlist *options;	/* options */
120struct	nvlist *fsoptions;	/* filesystems */
121struct	nvlist *mkoptions;	/* makeoptions */
122struct	nvlist *appmkoptions;	/* appending mkoptions */
123struct	nvlist *condmkoptions;	/* conditional makeoption table */
124struct	hashtab *devbasetab;	/* devbase lookup */
125struct	hashtab *devroottab;	/* attach at root lookup */
126struct	hashtab *devatab;	/* devbase attachment lookup */
127struct	hashtab *deaddevitab;	/* removed instances lookup */
128struct	hashtab *selecttab;	/* selects things that are "optional foo" */
129struct	hashtab *needcnttab;	/* retains names marked "needs-count" */
130struct	hashtab *opttab;	/* table of configured options */
131struct	hashtab *fsopttab;	/* table of configured file systems */
132struct	dlhash *defopttab;	/* options that have been "defopt"'d */
133struct	dlhash *defflagtab;	/* options that have been "defflag"'d */
134struct	dlhash *defparamtab;	/* options that have been "defparam"'d */
135struct	dlhash *defoptlint;	/* lint values for options */
136struct	nvhash *deffstab;	/* defined file systems */
137struct	dlhash *optfiletab;	/* "defopt"'d option .h files */
138struct	hashtab *attrtab;	/* attributes (locators, etc.) */
139struct	hashtab *attrdeptab;	/* attribute dependencies */
140struct	hashtab *bdevmtab;	/* block devm lookup */
141struct	hashtab *cdevmtab;	/* character devm lookup */
142
143int	ndevi;				/* number of devi's (before packing) */
144int	npspecs;			/* number of parent specs */
145devmajor_t maxbdevm;			/* max number of block major */
146devmajor_t maxcdevm;			/* max number of character major */
147int	do_devsw;			/* 0 if pre-devsw config */
148int	oktopackage;			/* 0 before setmachine() */
149int	devilevel;			/* used for devi->i_level */
150
151struct filelist		allfiles;	/* list of all kernel source files */
152struct filelist		allcfiles;	/* list of all .c files */
153struct filelist		allsfiles;	/* list of all .S files */
154struct filelist		allofiles;	/* list of all .o files */
155
156struct prefixlist	prefixes,	/* prefix stack */
157			allprefixes;	/* all prefixes used (after popped) */
158struct prefixlist	buildprefixes,	/* build prefix stack */
159			allbuildprefixes;/* all build prefixes used (after popped) */
160
161int	vflag;				/* verbose output */
162int	Pflag;				/* pack locators */
163int	Lflag;				/* lint config generation */
164int	Mflag;				/* modular build */
165int	Sflag;				/* suffix rules & subdirectory */
166int	handling_cmdlineopts;		/* currently processing -D/-U options */
167
168int	yyparse(void);
169
170#if !defined(MAKE_BOOTSTRAP) && defined(YYDEBUG)
171extern int yydebug;
172#endif
173int	dflag;
174
175static struct dlhash *obsopttab;
176static struct hashtab *mkopttab;
177static struct nvlist **nextopt;
178static struct nvlist **nextmkopt;
179static struct nvlist **nextappmkopt;
180static struct nvlist **nextcndmkopt;
181static struct nvlist **nextfsopt;
182static struct nvlist *cmdlinedefs, *cmdlineundefs;
183
184static	void	usage(void) __dead;
185static	void	dependopts(void);
186static	void	dependopts_one(const char *);
187static	void	do_depends(struct nvlist *);
188static	void	do_depend(struct nvlist *);
189static	void	stop(void);
190static	int	do_option(struct hashtab *, struct nvlist **,
191		    struct nvlist ***, const char *, const char *,
192		    const char *, struct hashtab *);
193static	int	undo_option(struct hashtab *, struct nvlist **,
194		    struct nvlist ***, const char *, const char *, int);
195static	int	crosscheck(void);
196static	int	badstar(void);
197static	int	mkallsubdirs(void);
198static	int	mksymlinks(void);
199static	int	mkident(void);
200static	int	devbase_has_dead_instances(const char *, void *, void *);
201static	int	devbase_has_any_instance(struct devbase *, int, int, int);
202static	int	check_dead_devi(const char *, void *, void *);
203static	void	add_makeopt(const char *);
204static	void	remove_makeopt(const char *);
205static	void	handle_cmdline_makeoptions(void);
206static	void	kill_orphans(void);
207static	void	do_kill_orphans(struct devbase *, struct attr *,
208    struct devbase *, int);
209static	int	kill_orphans_cb(const char *, void *, void *);
210static	int	cfcrosscheck(struct config *, const char *, struct nvlist *);
211static void	defopt(struct dlhash *ht, const char *fname,
212	     struct defoptlist *opts, struct nvlist *deps, int obs);
213static struct nvlist *find_declared_fs_option(const char *name);
214
215#define LOGCONFIG_LARGE "INCLUDE_CONFIG_FILE"
216#define LOGCONFIG_SMALL "INCLUDE_JUST_CONFIG"
217
218static	void	logconfig_start(void);
219static	void	logconfig_end(void);
220static	FILE	*cfg;
221static	time_t	cfgtime;
222
223static	int	is_elf(const char *);
224static	int	extract_config(const char *, const char *, int);
225
226int badfilename(const char *fname);
227
228const char *progname;
229extern const char *yyfile;
230
231int
232main(int argc, char **argv)
233{
234	char *p, cname[PATH_MAX];
235	const char *last_component;
236	int pflag, xflag, ch, removeit;
237
238	setprogname(argv[0]);
239
240	pflag = 0;
241	xflag = 0;
242	while ((ch = getopt(argc, argv, "D:LMPSU:dgpvb:s:x")) != -1) {
243		switch (ch) {
244
245		case 'd':
246#if !defined(MAKE_BOOTSTRAP) && defined(YYDEBUG)
247			yydebug = 1;
248#endif
249			dflag++;
250			break;
251
252		case 'M':
253			Mflag = 1;
254			break;
255
256		case 'L':
257			Lflag = 1;
258			break;
259
260		case 'P':
261			Pflag = 1;
262			break;
263
264		case 'g':
265			/*
266			 * In addition to DEBUG, you probably wanted to
267			 * set "options KGDB" and maybe others.  We could
268			 * do that for you, but you really should just
269			 * put them in the config file.
270			 */
271			warnx("-g is obsolete (use -D DEBUG=\"-g\")");
272			usage();
273			/*NOTREACHED*/
274
275		case 'p':
276			/*
277			 * Essentially the same as makeoptions PROF="-pg",
278			 * but also changes the path from ../../compile/FOO
279			 * to ../../compile/FOO.PROF; i.e., compile a
280			 * profiling kernel based on a typical "regular"
281			 * kernel.
282			 *
283			 * Note that if you always want profiling, you
284			 * can (and should) use a "makeoptions" line.
285			 */
286			pflag = 1;
287			break;
288
289		case 'v':
290			vflag = 1;
291			break;
292
293		case 'b':
294			builddir = optarg;
295			break;
296
297		case 's':
298			srcdir = optarg;
299			break;
300
301		case 'S':
302			Sflag = 1;
303			break;
304
305		case 'x':
306			xflag = 1;
307			break;
308
309		case 'D':
310			add_makeopt(optarg);
311			break;
312
313		case 'U':
314			remove_makeopt(optarg);
315			break;
316
317		case '?':
318		default:
319			usage();
320		}
321	}
322
323	if (xflag && optind != 2) {
324		errx(EXIT_FAILURE, "-x must be used alone");
325	}
326
327	argc -= optind;
328	argv += optind;
329	if (argc > 1) {
330		usage();
331	}
332
333	if (Lflag && (builddir != NULL || Pflag || pflag))
334		errx(EXIT_FAILURE, "-L can only be used with -s and -v");
335
336	if (xflag) {
337		if (argc == 0) {
338#if !HAVE_NBTOOL_CONFIG_H
339			char path_unix[MAXPATHLEN];
340			size_t len = sizeof(path_unix) - 1;
341			path_unix[0] = '/';
342
343			conffile = sysctlbyname("machdep.booted_kernel",
344			    &path_unix[1], &len, NULL, 0) == -1 ? _PATH_UNIX :
345			    path_unix;
346#else
347			errx(EXIT_FAILURE, "no kernel supplied");
348#endif
349		} else
350			conffile = argv[0];
351		if (!is_elf(conffile))
352			errx(EXIT_FAILURE, "%s: not a binary kernel",
353			    conffile);
354		if (!extract_config(conffile, "stdout", STDOUT_FILENO))
355			errx(EXIT_FAILURE, "%s does not contain embedded "
356			    "configuration data", conffile);
357		exit(0);
358	}
359
360	conffile = (argc == 1) ? argv[0] : "CONFIG";
361	if (firstfile(conffile)) {
362		err(EXIT_FAILURE, "Cannot read `%s'", conffile);
363		exit(2);
364	}
365
366	/*
367	 * Init variables.
368	 */
369	minmaxusers = 1;
370	maxmaxusers = 10000;
371	initintern();
372	ident = NULL;
373	devbasetab = ht_new();
374	devroottab = ht_new();
375	devatab = ht_new();
376	devitab = ht_new();
377	deaddevitab = ht_new();
378	selecttab = ht_new();
379	needcnttab = ht_new();
380	opttab = ht_new();
381	mkopttab = ht_new();
382	fsopttab = ht_new();
383	deffstab = nvhash_create();
384	defopttab = dlhash_create();
385	defparamtab = dlhash_create();
386	defoptlint = dlhash_create();
387	defflagtab = dlhash_create();
388	optfiletab = dlhash_create();
389	obsopttab = dlhash_create();
390	bdevmtab = ht_new();
391	maxbdevm = 0;
392	cdevmtab = ht_new();
393	maxcdevm = 0;
394	nextopt = &options;
395	nextmkopt = &mkoptions;
396	nextappmkopt = &appmkoptions;
397	nextcndmkopt = &condmkoptions;
398	nextfsopt = &fsoptions;
399	initfiles();
400	initsem();
401
402	/*
403	 * Handle profiling (must do this before we try to create any
404	 * files).
405	 */
406	last_component = strrchr(conffile, '/');
407	last_component = (last_component) ? last_component + 1 : conffile;
408	if (pflag) {
409		p = emalloc(strlen(last_component) + 17);
410		(void)sprintf(p, "../compile/%s.PROF", last_component);
411		(void)addmkoption(intern("PROF"), "-pg");
412		(void)addoption(intern("GPROF"), NULL);
413	} else {
414		p = emalloc(strlen(last_component) + 13);
415		(void)sprintf(p, "../compile/%s", last_component);
416	}
417	defbuilddir = (argc == 0) ? "." : p;
418
419	if (Lflag) {
420		char resolvedname[MAXPATHLEN];
421
422		if (realpath(conffile, resolvedname) == NULL)
423			err(EXIT_FAILURE, "realpath(%s)", conffile);
424
425		if (yyparse())
426			stop();
427
428		printf("include \"%s\"\n", resolvedname);
429
430		emit_params();
431		emit_options();
432		emit_instances();
433
434		exit(EXIT_SUCCESS);
435	}
436
437	removeit = 0;
438	if (is_elf(conffile)) {
439		const char *tmpdir;
440		int cfd;
441
442		if (builddir == NULL)
443			errx(EXIT_FAILURE, "Build directory must be specified "
444			    "with binary kernels");
445
446		/* Open temporary configuration file */
447		tmpdir = getenv("TMPDIR");
448		if (tmpdir == NULL)
449			tmpdir = _PATH_TMP;
450		snprintf(cname, sizeof(cname), "%s/config.tmp.XXXXXX", tmpdir);
451		cfd = mkstemp(cname);
452		if (cfd == -1)
453			err(EXIT_FAILURE, "Cannot create `%s'", cname);
454
455		printf("Using configuration data embedded in kernel...\n");
456		if (!extract_config(conffile, cname, cfd)) {
457			unlink(cname);
458			errx(EXIT_FAILURE, "%s does not contain embedded "
459			    "configuration data", conffile);
460		}
461
462		removeit = 1;
463		close(cfd);
464		firstfile(cname);
465	}
466
467	 /*
468	  * Log config file.  We don't know until yyparse() if we're
469	  * going to need config_file.h (i.e. if we're doing ioconf-only
470	  * or not).  Just start creating the file, and when we know
471	  * later, we'll just keep or discard our work here.
472	  */
473	logconfig_start();
474
475	/*
476	 * Parse config file (including machine definitions).
477	 */
478	if (yyparse())
479		stop();
480
481	if (ioconfname && cfg)
482		fclose(cfg);
483	else
484		logconfig_end();
485
486	if (removeit)
487		unlink(cname);
488
489	/*
490	 * Handle command line overrides
491	 */
492	yyfile = "handle_cmdline_makeoptions";
493	handle_cmdline_makeoptions();
494
495	/*
496	 * Detect and properly ignore orphaned devices
497	 */
498	yyfile = "kill_orphans";
499	kill_orphans();
500
501	/*
502	 * Select devices and pseudo devices and their attributes
503	 */
504	yyfile = "fixdevis";
505	if (fixdevis())
506		stop();
507
508	/*
509	 * Copy maxusers to param.
510	 */
511	yyfile = "fixmaxusers";
512	fixmaxusers();
513
514	/*
515	 * Copy makeoptions to params
516	 */
517	yyfile = "fixmkoption";
518	fixmkoption();
519
520	/*
521	 * If working on an ioconf-only config, process here and exit
522	 */
523	if (ioconfname) {
524		yyfile = "pack";
525		pack();
526		yyfile = "mkioconf";
527		mkioconf();
528		yyfile = "emitlocs";
529		emitlocs();
530		yyfile = "emitioconfh";
531		emitioconfh();
532		return 0;
533	}
534
535	yyfile = "dependattrs";
536	dependattrs();
537
538	/*
539	 * Deal with option dependencies.
540	 */
541	yyfile = "dependopts";
542	dependopts();
543
544	/*
545	 * Fix (as in `set firmly in place') files.
546	 */
547	yyfile = "fixfiles";
548	if (fixfiles())
549		stop();
550
551	/*
552	 * Fix device-majors.
553	 */
554	yyfile = "fixdevsw";
555	if (fixdevsw())
556		stop();
557
558	/*
559	 * Perform cross-checking.
560	 */
561	if (maxusers == 0) {
562		if (defmaxusers) {
563			(void)printf("maxusers not specified; %d assumed\n",
564			    defmaxusers);
565			maxusers = defmaxusers;
566		} else {
567			warnx("need \"maxusers\" line");
568			errors++;
569		}
570	}
571	if (crosscheck() || errors)
572		stop();
573
574	/*
575	 * Squeeze things down and finish cross-checks (STAR checks must
576	 * run after packing).
577	 */
578	yyfile = "pack";
579	pack();
580	yyfile = "badstar";
581	if (badstar())
582		stop();
583
584	yyfile = NULL;
585	/*
586	 * Ready to go.  Build all the various files.
587	 */
588	if ((Sflag && mkallsubdirs()) || mksymlinks() || mkmakefile() || mkheaders() || mkswap() ||
589	    mkioconf() || (do_devsw ? mkdevsw() : 0) || mkident() || errors)
590		stop();
591	(void)printf("Build directory is %s\n", builddir);
592	(void)printf("Don't forget to run \"make depend\"\n");
593
594	return 0;
595}
596
597static void
598usage(void)
599{
600	(void)fprintf(stderr, "Usage: %s [-Ppv] [-b builddir] [-D var=value] "
601	    "[-s srcdir] [-U var] "
602	    "[config-file]\n\t%s -x [kernel-file]\n"
603	    "\t%s -L [-v] [-s srcdir] [config-file]\n",
604	    getprogname(), getprogname(), getprogname());
605	exit(1);
606}
607
608/*
609 * Set any options that are implied by other options.
610 */
611static void
612dependopts(void)
613{
614	struct nvlist *nv;
615
616	for (nv = options; nv != NULL; nv = nv->nv_next) {
617		dependopts_one(nv->nv_name);
618	}
619
620	for (nv = fsoptions; nv != NULL; nv = nv->nv_next) {
621		dependopts_one(nv->nv_name);
622	}
623}
624
625static void
626dependopts_one(const char *name)
627{
628	struct defoptlist *dl;
629	struct nvlist *fs;
630
631	dl = find_declared_option_option(name);
632	if (dl != NULL) {
633		do_depends(dl->dl_depends);
634	}
635	fs = find_declared_fs_option(name);
636	if (fs != NULL) {
637		do_depends(fs->nv_ptr);
638	}
639
640	CFGDBG(3, "depend `%s' searched", name);
641}
642
643static void
644do_depends(struct nvlist *nv)
645{
646	struct nvlist *opt;
647
648	for (opt = nv; opt != NULL; opt = opt->nv_next) {
649		do_depend(opt);
650	}
651}
652
653static void
654do_depend(struct nvlist *nv)
655{
656	struct attr *a;
657
658	if (nv != NULL && (nv->nv_flags & NV_DEPENDED) == 0) {
659		nv->nv_flags |= NV_DEPENDED;
660		/*
661		 * If the dependency is an attribute, then just add
662		 * it to the selecttab.
663		 */
664		CFGDBG(3, "depend attr `%s'", nv->nv_name);
665		if ((a = ht_lookup(attrtab, nv->nv_name)) != NULL) {
666			if (a->a_iattr)
667				panic("do_depend(%s): dep `%s' is an iattr",
668				    nv->nv_name, a->a_name);
669			expandattr(a, selectattr);
670		} else {
671			if (ht_lookup(opttab, nv->nv_name) == NULL)
672				addoption(nv->nv_name, NULL);
673			dependopts_one(nv->nv_name);
674		}
675	}
676}
677
678static int
679recreate(const char *p, const char *q)
680{
681	int ret;
682
683	if ((ret = unlink(q)) == -1 && errno != ENOENT)
684		warn("unlink(%s)", q);
685	if ((ret = symlink(p, q)) == -1)
686		warn("symlink(%s -> %s)", q, p);
687	return ret;
688}
689
690static void
691mksubdir(char *buf)
692{
693	char *p;
694	struct stat st;
695
696	p = strrchr(buf, '/');
697	if (p != NULL && *p == '/') {
698		*p = '\0';
699		mksubdir(buf);
700		*p = '/';
701	}
702	if (stat(buf, &st) == 0) {
703		if (!S_ISDIR(st.st_mode))
704			errx(EXIT_FAILURE, "not directory %s", buf);
705	} else
706		if (mkdir(buf, 0777) == -1)
707			errx(EXIT_FAILURE, "cannot create %s", buf);
708}
709
710static int
711mksubdirs(struct filelist *fl)
712{
713	struct files *fi;
714	const char *prologue, *prefix, *sep;
715	char buf[MAXPATHLEN];
716
717	TAILQ_FOREACH(fi, fl, fi_next) {
718		if ((fi->fi_flags & FI_SEL) == 0)
719			continue;
720		prefix = sep = "";
721		if (fi->fi_buildprefix != NULL) {
722			prefix = fi->fi_buildprefix;
723			sep = "/";
724		} else {
725			if (fi->fi_prefix != NULL) {
726				prefix = fi->fi_prefix;
727				sep = "/";
728			}
729		}
730		snprintf(buf, sizeof(buf), "%s%s%s", prefix, sep, fi->fi_dir);
731		if (buf[0] == '\0')
732			continue;
733		mksubdir(buf);
734		if (fi->fi_prefix != NULL && fi->fi_buildprefix != NULL) {
735			char org[MAXPATHLEN];
736
737			if (fi->fi_prefix[0] == '/') {
738				prologue = "";
739				sep = "";
740			} else {
741				prologue = srcdir;
742				sep = "/";
743			}
744			snprintf(buf, sizeof(buf), "%s%s%s",
745			    fi->fi_buildprefix, "/", fi->fi_path);
746			snprintf(org, sizeof(org), "%s%s%s%s%s",
747			    prologue, sep, fi->fi_prefix, "/", fi->fi_path);
748			recreate(org, buf);
749			fi->fi_prefix = fi->fi_buildprefix;
750			fi->fi_buildprefix = NULL;
751		}
752	}
753
754	return 0;
755}
756
757static int
758mkallsubdirs(void)
759{
760
761	mksubdirs(&allfiles);
762	mksubdirs(&allofiles);
763	return 0;
764}
765
766/*
767 * Make a symlink for "machine" so that "#include <machine/foo.h>" works,
768 * and for the machine's CPU architecture, so that works as well.
769 */
770static int
771mksymlinks(void)
772{
773	int ret;
774	char *p, buf[MAXPATHLEN];
775	const char *q;
776	struct nvlist *nv;
777
778	p = buf;
779
780	snprintf(buf, sizeof(buf), "%s/arch/%s/include", srcdir, machine);
781	ret = recreate(p, "machine");
782	ret = recreate(p, machine);
783
784	if (machinearch != NULL) {
785		snprintf(buf, sizeof(buf), "%s/arch/%s/include", srcdir, machinearch);
786		q = machinearch;
787	} else {
788		snprintf(buf, sizeof(buf), "machine");
789		q = machine;
790	}
791
792	ret = recreate(p, q);
793
794	for (nv = machinesubarches; nv != NULL; nv = nv->nv_next) {
795		q = nv->nv_name;
796		snprintf(buf, sizeof(buf), "%s/arch/%s/include", srcdir, q);
797		ret = recreate(p, q);
798	}
799
800	return (ret);
801}
802
803static __dead void
804stop(void)
805{
806	(void)fprintf(stderr, "*** Stop.\n");
807	exit(1);
808}
809
810static void
811check_dependencies(const char *thing, struct nvlist *deps)
812{
813	struct nvlist *dep;
814	struct attr *a;
815
816	for (dep = deps; dep != NULL; dep = dep->nv_next) {
817		/*
818		 * If the dependency is an attribute, it must not
819		 * be an interface attribute.  Otherwise, it must
820		 * be a previously declared option.
821		 */
822		if ((a = ht_lookup(attrtab, dep->nv_name)) != NULL) {
823			if (a->a_iattr)
824				cfgerror("option `%s' dependency `%s' "
825				    "is an interface attribute",
826				    thing, a->a_name);
827		} else if (OPT_OBSOLETE(dep->nv_name)) {
828			cfgerror("option `%s' dependency `%s' "
829			    "is obsolete", thing, dep->nv_name);
830		} else if (!find_declared_option(dep->nv_name)) {
831			cfgerror("option `%s' dependency `%s' "
832			    "is an unknown option",
833			    thing, dep->nv_name);
834		}
835	}
836}
837
838static void
839add_fs_dependencies(struct nvlist *nv, struct nvlist *deps)
840{
841	/* Use nv_ptr to link any other options that are implied. */
842	nv->nv_ptr = deps;
843	check_dependencies(nv->nv_name, deps);
844}
845
846static void
847add_opt_dependencies(struct defoptlist *dl, struct nvlist *deps)
848{
849	dl->dl_depends = deps;
850	check_dependencies(dl->dl_name, deps);
851}
852
853/*
854 * Define one or more file systems.
855 */
856void
857deffilesystem(struct nvlist *fses, struct nvlist *deps)
858{
859	struct nvlist *nv;
860	struct where *w;
861
862	/*
863	 * Mark these options as ones to skip when creating the Makefile.
864	 */
865	for (nv = fses; nv != NULL; nv = nv->nv_next) {
866		if ((w = DEFINED_OPTION(nv->nv_name)) != NULL) {
867			cfgerror("file system or option `%s' already defined"
868			    " at %s:%hu", nv->nv_name, w->w_srcfile,
869			    w->w_srcline);
870			return;
871		}
872
873		/*
874		 * Also mark it as a valid file system, which may be
875		 * used in "file-system" directives in the config
876		 * file.
877		 */
878		if (nvhash_insert(deffstab, nv->nv_name, nv))
879			panic("file system `%s' already in table?!",
880			    nv->nv_name);
881
882		add_fs_dependencies(nv, deps);
883
884		/*
885		 * Implicit attribute definition for filesystem.
886		 */
887		const char *n;
888		n = strtolower(nv->nv_name);
889		refattr(n);
890	}
891}
892
893/*
894 * Sanity check a file name.
895 */
896int
897badfilename(const char *fname)
898{
899	const char *n;
900
901	/*
902	 * We're putting multiple options into one file.  Sanity
903	 * check the file name.
904	 */
905	if (strchr(fname, '/') != NULL) {
906		cfgerror("option file name contains a `/'");
907		return 1;
908	}
909	if ((n = strrchr(fname, '.')) == NULL || strcmp(n, ".h") != 0) {
910		cfgerror("option file name does not end in `.h'");
911		return 1;
912	}
913	return 0;
914}
915
916
917/*
918 * Search for a defined option (defopt, filesystem, etc), and if found,
919 * return the option's struct nvlist.
920 *
921 * This used to be one function (find_declared_option) before options
922 * and filesystems became different types.
923 */
924struct defoptlist *
925find_declared_option_option(const char *name)
926{
927	struct defoptlist *option;
928
929	if ((option = dlhash_lookup(defopttab, name)) != NULL ||
930	    (option = dlhash_lookup(defparamtab, name)) != NULL ||
931	    (option = dlhash_lookup(defflagtab, name)) != NULL) {
932		return (option);
933	}
934
935	return (NULL);
936}
937
938static struct nvlist *
939find_declared_fs_option(const char *name)
940{
941	struct nvlist *fs;
942
943	if ((fs = nvhash_lookup(deffstab, name)) != NULL) {
944		return fs;
945	}
946
947	return (NULL);
948}
949
950/*
951 * Like find_declared_option but doesn't return what it finds, so it
952 * can search both the various kinds of options and also filesystems.
953 */
954struct where *
955find_declared_option(const char *name)
956{
957	struct defoptlist *option = NULL;
958	struct nvlist *fs;
959
960	if ((option = dlhash_lookup(defopttab, name)) != NULL ||
961	    (option = dlhash_lookup(defparamtab, name)) != NULL ||
962	    (option = dlhash_lookup(defflagtab, name)) != NULL) {
963		return &option->dl_where;
964	}
965	if ((fs = nvhash_lookup(deffstab, name)) != NULL) {
966		return &fs->nv_where;
967	}
968
969	return NULL;
970}
971
972/*
973 * Define one or more standard options.  If an option file name is specified,
974 * place all options in one file with the specified name.  Otherwise, create
975 * an option file for each option.
976 * record the option information in the specified table.
977 */
978void
979defopt(struct dlhash *ht, const char *fname, struct defoptlist *opts,
980       struct nvlist *deps, int obs)
981{
982	struct defoptlist *dl, *nextdl, *olddl;
983	const char *name;
984	struct where *w;
985	char buf[500];
986
987	if (fname != NULL && badfilename(fname)) {
988		return;
989	}
990
991	/*
992	 * Mark these options as ones to skip when creating the Makefile.
993	 */
994	for (dl = opts; dl != NULL; dl = nextdl) {
995		nextdl = dl->dl_next;
996
997		if (dl->dl_lintvalue != NULL) {
998			/*
999			 * If an entry already exists, then we are about to
1000			 * complain, so no worry.
1001			 */
1002			(void) dlhash_insert(defoptlint, dl->dl_name,
1003			    dl);
1004		}
1005
1006		/* An option name can be declared at most once. */
1007		if ((w = DEFINED_OPTION(dl->dl_name)) != NULL) {
1008			cfgerror("file system or option `%s' already defined"
1009			    " at %s:%hu", dl->dl_name, w->w_srcfile,
1010			    w->w_srcline);
1011			return;
1012		}
1013
1014		if (dlhash_insert(ht, dl->dl_name, dl)) {
1015			cfgerror("file system or option `%s' already defined"
1016			    " at %s:%hu", dl->dl_name, dl->dl_where.w_srcfile,
1017			    dl->dl_where.w_srcline);
1018			return;
1019		}
1020
1021		if (fname == NULL) {
1022			/*
1023			 * Each option will be going into its own file.
1024			 * Convert the option name to lower case.  This
1025			 * lower case name will be used as the option
1026			 * file name.
1027			 */
1028			(void) snprintf(buf, sizeof(buf), "opt_%s.h",
1029			    strtolower(dl->dl_name));
1030			name = intern(buf);
1031		} else {
1032			name = fname;
1033		}
1034
1035		add_opt_dependencies(dl, deps);
1036
1037		/*
1038		 * Remove this option from the parameter list before adding
1039		 * it to the list associated with this option file.
1040		 */
1041		dl->dl_next = NULL;
1042
1043		/*
1044		 * Flag as obsolete, if requested.
1045		 */
1046		if (obs) {
1047			dl->dl_obsolete = 1;
1048			(void)dlhash_insert(obsopttab, dl->dl_name, dl);
1049		}
1050
1051		/*
1052		 * Add this option file if we haven't seen it yet.
1053		 * Otherwise, append to the list of options already
1054		 * associated with this file.
1055		 */
1056		if ((olddl = dlhash_lookup(optfiletab, name)) == NULL) {
1057			(void)dlhash_insert(optfiletab, name, dl);
1058		} else {
1059			while (olddl->dl_next != NULL)
1060				olddl = olddl->dl_next;
1061			olddl->dl_next = dl;
1062		}
1063	}
1064}
1065
1066/*
1067 * Specify that a defined option should have a Makefile variable created.
1068 */
1069static void
1070mkoptvar(struct dlhash *ht, struct defoptlist *opts)
1071{
1072	struct defoptlist *dl, *defined_dl;
1073
1074	for (dl = opts; dl != NULL; dl = dl->dl_next) {
1075		defined_dl = dlhash_lookup(ht, dl->dl_name);
1076		if (defined_dl == NULL) {
1077			cfgerror("option `%s' not defined"
1078			    " at %s:%hu", dl->dl_name, dl->dl_where.w_srcfile,
1079			    dl->dl_where.w_srcline);
1080			continue;
1081		}
1082		defined_dl->dl_mkvar = 1;
1083	}
1084	defoptlist_destroy(dl);
1085}
1086
1087/*
1088 * Define one or more standard options.  If an option file name is specified,
1089 * place all options in one file with the specified name.  Otherwise, create
1090 * an option file for each option.
1091 */
1092void
1093defoption(const char *fname, struct defoptlist *opts, struct nvlist *deps)
1094{
1095
1096	cfgwarn("The use of `defopt' is deprecated");
1097	defopt(defopttab, fname, opts, deps, 0);
1098}
1099
1100
1101/*
1102 * Define an option for which a value is required.
1103 */
1104void
1105defparam(const char *fname, struct defoptlist *opts, struct nvlist *deps, int obs)
1106{
1107
1108	defopt(defparamtab, fname, opts, deps, obs);
1109}
1110
1111/*
1112 * Define an option which must not have a value, and which
1113 * emits a "needs-flag" style output.
1114 */
1115void
1116defflag(const char *fname, struct defoptlist *opts, struct nvlist *deps, int obs)
1117{
1118
1119	defopt(defflagtab, fname, opts, deps, obs);
1120}
1121
1122/*
1123 * Specify that a defined flag option should have a Makefile variable
1124 * created.
1125 */
1126void
1127mkflagvar(struct defoptlist *opts)
1128{
1129
1130	mkoptvar(defflagtab, opts);
1131}
1132
1133/*
1134 * Add an option from "options FOO".  Note that this selects things that
1135 * are "optional foo".
1136 */
1137void
1138addoption(const char *name, const char *value)
1139{
1140	const char *n;
1141	int is_fs, is_param, is_flag, is_undecl, is_obs;
1142
1143	/*
1144	 * Figure out how this option was declared (if at all.)
1145	 * XXX should use "params" and "flags" in config.
1146	 * XXX crying out for a type field in a unified hashtab.
1147	 */
1148	is_fs = OPT_FSOPT(name);
1149	is_param = OPT_DEFPARAM(name);
1150	is_flag =  OPT_DEFFLAG(name);
1151	is_obs = OPT_OBSOLETE(name);
1152	is_undecl = !DEFINED_OPTION(name);
1153
1154	/* Warn and pretend the user had not selected the option  */
1155	if (is_obs) {
1156		cfgwarn("obsolete option `%s' will be ignored", name);
1157		return;
1158	}
1159
1160	/* Make sure this is not a defined file system. */
1161	if (is_fs) {
1162		cfgerror("`%s' is a defined file system", name);
1163		return;
1164	}
1165	/* A defparam must have a value */
1166	if (is_param && value == NULL) {
1167		cfgerror("option `%s' must have a value", name);
1168		return;
1169	}
1170	/* A defflag must not have a value */
1171	if (is_flag && value != NULL) {
1172		cfgerror("option `%s' must not have a value", name);
1173		return;
1174	}
1175
1176	if (is_undecl && vflag) {
1177		cfgwarn("undeclared option `%s' added to IDENT", name);
1178	}
1179
1180	if (do_option(opttab, &options, &nextopt, name, value, "options",
1181	    selecttab))
1182		return;
1183
1184	/* make lowercase, then add to select table */
1185	n = strtolower(name);
1186	(void)ht_insert(selecttab, n, (void *)__UNCONST(n));
1187	CFGDBG(3, "option selected `%s'", n);
1188}
1189
1190void
1191deloption(const char *name, int nowarn)
1192{
1193
1194	CFGDBG(4, "deselecting opt `%s'", name);
1195	if (undo_option(opttab, &options, &nextopt, name, "options", nowarn))
1196		return;
1197	if (undo_option(selecttab, NULL, NULL, strtolower(name), "options", nowarn))
1198		return;
1199}
1200
1201/*
1202 * Add a file system option.  This routine simply inserts the name into
1203 * a list of valid file systems, which is used to validate the root
1204 * file system type.  The name is then treated like a standard option.
1205 */
1206void
1207addfsoption(const char *name)
1208{
1209	const char *n;
1210
1211	/* Make sure this is a defined file system. */
1212	if (!OPT_FSOPT(name)) {
1213		cfgerror("`%s' is not a defined file system", name);
1214		return;
1215	}
1216
1217	/*
1218	 * Convert to lower case.  This will be used in the select
1219	 * table, to verify root file systems.
1220	 */
1221	n = strtolower(name);
1222
1223	if (do_option(fsopttab, &fsoptions, &nextfsopt, name, n, "file-system",
1224	    selecttab))
1225		return;
1226
1227	/* Add to select table. */
1228	(void)ht_insert(selecttab, n, __UNCONST(n));
1229	CFGDBG(3, "fs selected `%s'", name);
1230
1231	/*
1232	 * Select attribute if one exists.
1233	 */
1234	struct attr *a;
1235	if ((a = ht_lookup(attrtab, n)) != NULL)
1236		selectattr(a);
1237}
1238
1239void
1240delfsoption(const char *name, int nowarn)
1241{
1242	const char *n;
1243
1244	CFGDBG(4, "deselecting fs `%s'", name);
1245	n = strtolower(name);
1246	if (undo_option(fsopttab, &fsoptions, &nextfsopt, name, "file-system", nowarn))
1247		return;
1248	if (undo_option(selecttab, NULL, NULL, n, "file-system", nowarn))
1249		return;
1250}
1251
1252/*
1253 * Add a "make" option.
1254 */
1255void
1256addmkoption(const char *name, const char *value)
1257{
1258
1259	(void)do_option(mkopttab, &mkoptions, &nextmkopt, name, value,
1260		        "makeoptions", NULL);
1261}
1262
1263void
1264delmkoption(const char *name, int nowarn)
1265{
1266
1267	CFGDBG(4, "deselecting mkopt `%s'", name);
1268	(void)undo_option(mkopttab, &mkoptions, &nextmkopt, name,
1269	    "makeoptions", nowarn);
1270}
1271
1272/*
1273 * Add an appending "make" option.
1274 */
1275void
1276appendmkoption(const char *name, const char *value)
1277{
1278	struct nvlist *nv;
1279
1280	nv = newnv(name, value, NULL, 0, NULL);
1281	*nextappmkopt = nv;
1282	nextappmkopt = &nv->nv_next;
1283}
1284
1285/*
1286 * Add a conditional appending "make" option.
1287 */
1288void
1289appendcondmkoption(struct condexpr *cond, const char *name, const char *value)
1290{
1291	struct nvlist *nv;
1292
1293	nv = newnv(name, value, cond, 0, NULL);
1294	*nextcndmkopt = nv;
1295	nextcndmkopt = &nv->nv_next;
1296}
1297
1298/*
1299 * Copy maxusers to param "MAXUSERS".
1300 */
1301void
1302fixmaxusers(void)
1303{
1304	char str[32];
1305
1306	snprintf(str, sizeof(str), "%d", maxusers);
1307	addoption(intern("MAXUSERS"), intern(str));
1308}
1309
1310/*
1311 * Copy makeoptions to params with "makeoptions_" prefix.
1312 */
1313void
1314fixmkoption(void)
1315{
1316	struct nvlist *nv;
1317	char buf[100];
1318	const char *name;
1319
1320	for (nv = mkoptions; nv != NULL; nv = nv->nv_next) {
1321		snprintf(buf, sizeof(buf), "makeoptions_%s", nv->nv_name);
1322		name = intern(buf);
1323		if (!DEFINED_OPTION(name) || !OPT_DEFPARAM(name))
1324			continue;
1325		addoption(name, intern(nv->nv_str));
1326	}
1327}
1328
1329/*
1330 * Add a name=value pair to an option list.  The value may be NULL.
1331 */
1332static int
1333do_option(struct hashtab *ht, struct nvlist **npp, struct nvlist ***next,
1334	  const char *name, const char *value, const char *type,
1335	  struct hashtab *stab)
1336{
1337	struct nvlist *nv, *onv;
1338
1339	/* assume it will work */
1340	nv = newnv(name, value, NULL, 0, NULL);
1341	if (ht_insert(ht, name, nv) != 0) {
1342
1343		/* oops, already got that option - remove it first */
1344		if ((onv = ht_lookup(ht, name)) == NULL)
1345			panic("do_option 1");
1346		if (onv->nv_str != NULL && !OPT_FSOPT(name))
1347			cfgwarn("already have %s `%s=%s'", type, name,
1348			    onv->nv_str);
1349		else
1350			cfgwarn("already have %s `%s'", type, name);
1351
1352		if (undo_option(ht, npp, next, name, type, 0))
1353			panic("do_option 2");
1354		if (stab != NULL &&
1355		    undo_option(stab, NULL, NULL, strtolower(name), type, 0))
1356			panic("do_option 3");
1357
1358		/* now try adding it again */
1359		if (ht_insert(ht, name, nv) != 0)
1360			panic("do_option 4");
1361
1362		CFGDBG(2, "opt `%s' replaced", name);
1363	}
1364	**next = nv;
1365	*next = &nv->nv_next;
1366
1367	return (0);
1368}
1369
1370/*
1371 * Remove a name from a hash table,
1372 * and optionally, a name=value pair from an option list.
1373 */
1374static int
1375undo_option(struct hashtab *ht, struct nvlist **npp,
1376    struct nvlist ***next, const char *name, const char *type, int nowarn)
1377{
1378	struct nvlist *nv;
1379
1380	if (ht_remove(ht, name)) {
1381		/*
1382		 * -U command line option removals are always silent
1383		 */
1384		if (!handling_cmdlineopts && !nowarn)
1385			cfgwarn("%s `%s' is not defined", type, name);
1386		return (1);
1387	}
1388	if (npp == NULL) {
1389		CFGDBG(2, "opt `%s' deselected", name);
1390		return (0);
1391	}
1392
1393	for ( ; *npp != NULL; npp = &(*npp)->nv_next) {
1394		if ((*npp)->nv_name != name)
1395			continue;
1396		if (next != NULL && *next == &(*npp)->nv_next)
1397			*next = npp;
1398		nv = (*npp)->nv_next;
1399		CFGDBG(2, "opt `%s' deselected", (*npp)->nv_name);
1400		nvfree(*npp);
1401		*npp = nv;
1402		return (0);
1403	}
1404	panic("%s `%s' is not defined in nvlist", type, name);
1405	return (1);
1406}
1407
1408/*
1409 * Return true if there is at least one instance of the given unit
1410 * on the given device attachment (or any units, if unit == WILD).
1411 */
1412int
1413deva_has_instances(struct deva *deva, int unit)
1414{
1415	struct devi *i;
1416
1417	/*
1418	 * EHAMMERTOOBIG: we shouldn't check i_pseudoroot here.
1419	 * What we want by this check is them to appear non-present
1420	 * except for purposes of other devices being able to attach
1421	 * to them.
1422	 */
1423	for (i = deva->d_ihead; i != NULL; i = i->i_asame)
1424		if (i->i_active == DEVI_ACTIVE && i->i_pseudoroot == 0 &&
1425		    (unit == WILD || unit == i->i_unit || i->i_unit == STAR))
1426			return (1);
1427	return (0);
1428}
1429
1430/*
1431 * Return true if there is at least one instance of the given unit
1432 * on the given base (or any units, if unit == WILD).
1433 */
1434int
1435devbase_has_instances(struct devbase *dev, int unit)
1436{
1437	struct deva *da;
1438
1439	/*
1440	 * Pseudo-devices are a little special.  We consider them
1441	 * to have instances only if they are both:
1442	 *
1443	 *	1. Included in this kernel configuration.
1444	 *
1445	 *	2. Be declared "defpseudodev".
1446	 */
1447	if (dev->d_ispseudo) {
1448		return ((ht_lookup(devitab, dev->d_name) != NULL)
1449			&& (dev->d_ispseudo > 1));
1450	}
1451
1452	for (da = dev->d_ahead; da != NULL; da = da->d_bsame)
1453		if (deva_has_instances(da, unit))
1454			return (1);
1455	return (0);
1456}
1457
1458static int
1459cfcrosscheck(struct config *cf, const char *what, struct nvlist *nv)
1460{
1461	struct devbase *dev;
1462	struct devi *pd;
1463	int errs, devunit;
1464
1465	if (maxpartitions <= 0)
1466		panic("cfcrosscheck");
1467
1468	for (errs = 0; nv != NULL; nv = nv->nv_next) {
1469		if (nv->nv_name == NULL)
1470			continue;
1471		dev = ht_lookup(devbasetab, nv->nv_name);
1472		if (dev == NULL)
1473			panic("cfcrosscheck(%s)", nv->nv_name);
1474		if (has_attr(dev->d_attrs, s_ifnet))
1475			devunit = nv->nv_ifunit;	/* XXX XXX XXX */
1476		else
1477			devunit = (int)(minor(nv->nv_num) / maxpartitions);
1478		if (devbase_has_instances(dev, devunit))
1479			continue;
1480		if (devbase_has_instances(dev, STAR) &&
1481		    devunit >= dev->d_umax)
1482			continue;
1483		TAILQ_FOREACH(pd, &allpseudo, i_next) {
1484			if (pd->i_base == dev && devunit < dev->d_umax &&
1485			    devunit >= 0)
1486				goto loop;
1487		}
1488		(void)fprintf(stderr,
1489		    "%s:%hu: %s says %s on %s, but there's no %s\n",
1490		    conffile, cf->cf_where.w_srcline,
1491		    cf->cf_name, what, nv->nv_str, nv->nv_str);
1492		errs++;
1493 loop:
1494		;
1495	}
1496	return (errs);
1497}
1498
1499/*
1500 * Cross-check the configuration: make sure that each target device
1501 * or attribute (`at foo[0*?]') names at least one real device.  Also
1502 * see that the root and dump devices for all configurations are there.
1503 */
1504int
1505crosscheck(void)
1506{
1507	struct config *cf;
1508	int errs;
1509
1510	errs = 0;
1511	if (TAILQ_EMPTY(&allcf)) {
1512		warnx("%s has no configurations!", conffile);
1513		errs++;
1514	}
1515	TAILQ_FOREACH(cf, &allcf, cf_next) {
1516		if (cf->cf_root != NULL) {	/* i.e., not root on ? */
1517			errs += cfcrosscheck(cf, "root", cf->cf_root);
1518			errs += cfcrosscheck(cf, "dumps", cf->cf_dump);
1519		}
1520	}
1521	return (errs);
1522}
1523
1524/*
1525 * Check to see if there is a *'d unit with a needs-count file.
1526 */
1527int
1528badstar(void)
1529{
1530	struct devbase *d;
1531	struct deva *da;
1532	struct devi *i;
1533	int errs, n;
1534
1535	errs = 0;
1536	TAILQ_FOREACH(d, &allbases, d_next) {
1537		for (da = d->d_ahead; da != NULL; da = da->d_bsame)
1538			for (i = da->d_ihead; i != NULL; i = i->i_asame) {
1539				if (i->i_unit == STAR)
1540					goto aybabtu;
1541			}
1542		continue;
1543 aybabtu:
1544		if (ht_lookup(needcnttab, d->d_name)) {
1545			warnx("%s's cannot be *'d until its driver is fixed",
1546			    d->d_name);
1547			errs++;
1548			continue;
1549		}
1550		for (n = 0; i != NULL; i = i->i_alias)
1551			if (!i->i_collapsed)
1552				n++;
1553		if (n < 1)
1554			panic("badstar() n<1");
1555	}
1556	return (errs);
1557}
1558
1559/*
1560 * Verify/create builddir if necessary, change to it, and verify srcdir.
1561 * This will be called when we see the first include.
1562 */
1563void
1564setupdirs(void)
1565{
1566	struct stat st;
1567
1568	/* srcdir must be specified if builddir is not specified or if
1569	 * no configuration filename was specified. */
1570	if ((builddir || strcmp(defbuilddir, ".") == 0) && !srcdir) {
1571		cfgerror("source directory must be specified");
1572		exit(1);
1573	}
1574
1575	if (Lflag) {
1576		if (srcdir == NULL)
1577			srcdir = "../../..";
1578		return;
1579	}
1580
1581	if (srcdir == NULL)
1582		srcdir = "../../../..";
1583	if (builddir == NULL)
1584		builddir = defbuilddir;
1585
1586	if (stat(builddir, &st) == -1) {
1587		if (mkdir(builddir, 0777) == -1)
1588			errx(EXIT_FAILURE, "cannot create %s", builddir);
1589	} else if (!S_ISDIR(st.st_mode))
1590		errx(EXIT_FAILURE, "%s is not a directory", builddir);
1591	if (chdir(builddir) == -1)
1592		err(EXIT_FAILURE, "cannot change to %s", builddir);
1593	if (stat(srcdir, &st) == -1)
1594		err(EXIT_FAILURE, "cannot stat %s", srcdir);
1595	if (!S_ISDIR(st.st_mode))
1596		errx(EXIT_FAILURE, "%s is not a directory", srcdir);
1597}
1598
1599/*
1600 * Write identifier from "ident" directive into file, for
1601 * newvers.sh to pick it up.
1602 */
1603int
1604mkident(void)
1605{
1606	FILE *fp;
1607	int error = 0;
1608
1609	(void)unlink("ident");
1610
1611	if (ident == NULL)
1612		return (0);
1613
1614	if ((fp = fopen("ident", "w")) == NULL) {
1615		warn("cannot write ident");
1616		return (1);
1617	}
1618	if (vflag)
1619		(void)printf("using ident '%s'\n", ident);
1620	fprintf(fp, "%s\n", ident);
1621	fflush(fp);
1622	if (ferror(fp))
1623		error = 1;
1624	(void)fclose(fp);
1625
1626	return error;
1627}
1628
1629void
1630logconfig_start(void)
1631{
1632	extern FILE *yyin;
1633	char line[1024];
1634	const char *tmpdir;
1635	struct stat st;
1636	int fd;
1637
1638	if (yyin == NULL || fstat(fileno(yyin), &st) == -1)
1639		return;
1640	cfgtime = st.st_mtime;
1641
1642	tmpdir = getenv("TMPDIR");
1643	if (tmpdir == NULL)
1644		tmpdir = _PATH_TMP;
1645	(void)snprintf(line, sizeof(line), "%s/config.tmp.XXXXXX", tmpdir);
1646	if ((fd = mkstemp(line)) == -1 ||
1647	    (cfg = fdopen(fd, "r+")) == NULL) {
1648		if (fd != -1) {
1649			(void)unlink(line);
1650			(void)close(fd);
1651		}
1652		cfg = NULL;
1653		return;
1654	}
1655	(void)unlink(line);
1656
1657	(void)fprintf(cfg, "#include <sys/cdefs.h>\n\n");
1658	(void)fprintf(cfg, "#include \"opt_config.h\"\n");
1659	(void)fprintf(cfg, "\n");
1660	(void)fprintf(cfg, "/*\n");
1661	(void)fprintf(cfg, " * Add either (or both) of\n");
1662	(void)fprintf(cfg, " *\n");
1663	(void)fprintf(cfg, " *\toptions %s\n", LOGCONFIG_LARGE);
1664	(void)fprintf(cfg, " *\toptions %s\n", LOGCONFIG_SMALL);
1665	(void)fprintf(cfg, " *\n");
1666	(void)fprintf(cfg,
1667	    " * to your kernel config file to embed it in the resulting\n");
1668	(void)fprintf(cfg,
1669	    " * kernel.  The latter option does not include files that are\n");
1670	(void)fprintf(cfg,
1671	    " * included (recursively) by your config file.  The embedded\n");
1672	(void)fprintf(cfg,
1673	    " * data be extracted by using the command:\n");
1674	(void)fprintf(cfg, " *\n");
1675	(void)fprintf(cfg,
1676	    " *\tstrings netbsd | sed -n 's/^_CFG_//p' | unvis\n");
1677	(void)fprintf(cfg, " */\n");
1678	(void)fprintf(cfg, "\n");
1679	(void)fprintf(cfg, "#ifdef CONFIG_FILE\n");
1680	(void)fprintf(cfg, "#if defined(%s) || defined(%s)\n\n",
1681	    LOGCONFIG_LARGE, LOGCONFIG_SMALL);
1682	(void)fprintf(cfg, "static const char config[] __used =\n\n");
1683
1684	(void)fprintf(cfg, "#ifdef %s\n\n", LOGCONFIG_LARGE);
1685	(void)fprintf(cfg, "\"_CFG_### START CONFIG FILE \\\"%s\\\"\\n\"\n\n",
1686	    conffile);
1687	(void)fprintf(cfg, "#endif /* %s */\n\n", LOGCONFIG_LARGE);
1688
1689	logconfig_include(yyin, NULL);
1690
1691	(void)fprintf(cfg, "#ifdef %s\n\n", LOGCONFIG_LARGE);
1692	(void)fprintf(cfg, "\"_CFG_### END CONFIG FILE \\\"%s\\\"\\n\"\n",
1693	    conffile);
1694
1695	rewind(yyin);
1696}
1697
1698void
1699logconfig_include(FILE *cf, const char *filename)
1700{
1701	char line[1024], in[2048], *out;
1702	struct stat st;
1703	int missingeol;
1704
1705	if (!cfg)
1706		return;
1707
1708	missingeol = 0;
1709	if (fstat(fileno(cf), &st) == -1)
1710		return;
1711	if (cfgtime < st.st_mtime)
1712		cfgtime = st.st_mtime;
1713
1714	if (filename)
1715		(void)fprintf(cfg,
1716		    "\"_CFG_### (included from \\\"%s\\\")\\n\"\n",
1717		    filename);
1718	while (fgets(line, sizeof(line), cf) != NULL) {
1719		missingeol = 1;
1720		(void)fprintf(cfg, "\"_CFG_");
1721		if (filename)
1722			(void)fprintf(cfg, "###> ");
1723		strvis(in, line, VIS_TAB);
1724		for (out = in; *out; out++)
1725			switch (*out) {
1726			case '\n':
1727				(void)fprintf(cfg, "\\n\"\n");
1728				missingeol = 0;
1729				break;
1730			case '"': case '\\':
1731				(void)fputc('\\', cfg);
1732				/* FALLTHROUGH */
1733			default:
1734				(void)fputc(*out, cfg);
1735				break;
1736			}
1737	}
1738	if (missingeol) {
1739		(void)fprintf(cfg, "\\n\"\n");
1740		warnx("%s: newline missing at EOF",
1741		    filename != NULL ? filename : conffile);
1742	}
1743	if (filename)
1744		(void)fprintf(cfg, "\"_CFG_### (end include \\\"%s\\\")\\n\"\n",
1745		    filename);
1746
1747	rewind(cf);
1748}
1749
1750void
1751logconfig_end(void)
1752{
1753	char line[1024];
1754	FILE *fp;
1755	struct stat st;
1756
1757	if (!cfg)
1758		return;
1759
1760	(void)fprintf(cfg, "#endif /* %s */\n", LOGCONFIG_LARGE);
1761	(void)fprintf(cfg, ";\n");
1762	(void)fprintf(cfg, "#endif /* %s || %s */\n",
1763	    LOGCONFIG_LARGE, LOGCONFIG_SMALL);
1764	(void)fprintf(cfg, "#endif /* CONFIG_FILE */\n");
1765	fflush(cfg);
1766	if (ferror(cfg))
1767		err(EXIT_FAILURE, "write to temporary file for config.h failed");
1768	rewind(cfg);
1769
1770	if (stat("config_file.h", &st) != -1) {
1771		if (cfgtime < st.st_mtime) {
1772			fclose(cfg);
1773			return;
1774		}
1775	}
1776
1777	fp = fopen("config_file.h", "w");
1778	if (!fp)
1779		err(EXIT_FAILURE, "cannot open \"config.h\"");
1780
1781	while (fgets(line, sizeof(line), cfg) != NULL)
1782		fputs(line, fp);
1783	fflush(fp);
1784	if (ferror(fp))
1785		err(EXIT_FAILURE, "write to \"config.h\" failed");
1786	fclose(fp);
1787	fclose(cfg);
1788}
1789
1790const char *
1791strtolower(const char *name)
1792{
1793	const char *n;
1794	char *p, low[500];
1795	char c;
1796
1797	for (n = name, p = low; (c = *n) != '\0'; n++)
1798		*p++ = (char)(isupper((u_char)c) ? tolower((u_char)c) : c);
1799	*p = '\0';
1800	return (intern(low));
1801}
1802
1803static int
1804is_elf(const char *file)
1805{
1806	int kernel;
1807	char hdr[4];
1808
1809	kernel = open(file, O_RDONLY);
1810	if (kernel == -1)
1811		err(EXIT_FAILURE, "cannot open %s", file);
1812	if (read(kernel, hdr, 4) != 4)
1813		err(EXIT_FAILURE, "Cannot read from %s", file);
1814	(void)close(kernel);
1815
1816	return memcmp("\177ELF", hdr, 4) == 0 ? 1 : 0;
1817}
1818
1819static int
1820extract_config(const char *kname, const char *cname, int cfd)
1821{
1822	char *ptr;
1823	void *base;
1824	int found, kfd;
1825	struct stat st;
1826	off_t i;
1827
1828	found = 0;
1829
1830	/* mmap(2) binary kernel */
1831	kfd = open(conffile, O_RDONLY);
1832	if (kfd == -1)
1833		err(EXIT_FAILURE, "cannot open %s", kname);
1834	if (fstat(kfd, &st) == -1)
1835		err(EXIT_FAILURE, "cannot stat %s", kname);
1836	base = mmap(0, (size_t)st.st_size, PROT_READ, MAP_FILE | MAP_SHARED,
1837	    kfd, 0);
1838	if (base == MAP_FAILED)
1839		err(EXIT_FAILURE, "cannot mmap %s", kname);
1840	ptr = base;
1841
1842	/* Scan mmap(2)'ed region, extracting kernel configuration */
1843	for (i = 0; i < st.st_size; i++) {
1844		if ((*ptr == '_') && (st.st_size - i > 5) && memcmp(ptr,
1845		    "_CFG_", 5) == 0) {
1846			/* Line found */
1847			char *oldptr, line[LINE_MAX + 1], uline[LINE_MAX + 1];
1848			int j;
1849
1850			found = 1;
1851
1852			oldptr = (ptr += 5);
1853			while (*ptr != '\n' && *ptr != '\0')
1854				ptr++;
1855			if (ptr - oldptr > LINE_MAX)
1856				errx(EXIT_FAILURE, "line too long");
1857			i += ptr - oldptr + 5;
1858			(void)memcpy(line, oldptr, (size_t)(ptr - oldptr));
1859			line[ptr - oldptr] = '\0';
1860			j = strunvis(uline, line);
1861			if (j == -1)
1862				errx(EXIT_FAILURE, "unvis: invalid "
1863				    "encoded sequence");
1864			uline[j] = '\n';
1865			if (write(cfd, uline, (size_t)j + 1) == -1)
1866				err(EXIT_FAILURE, "cannot write to %s", cname);
1867		} else
1868			ptr++;
1869	}
1870
1871	(void)close(kfd);
1872	(void)munmap(base, (size_t)st.st_size);
1873
1874	return found;
1875}
1876
1877struct dhdi_params {
1878	struct devbase *d;
1879	int unit;
1880	int level;
1881};
1882
1883static int
1884devbase_has_dead_instances(const char *key, void *value, void *aux)
1885{
1886	struct devi *i;
1887	struct dhdi_params *dhdi = aux;
1888
1889	for (i = value; i != NULL; i = i->i_alias)
1890		if (i->i_base == dhdi->d &&
1891		    (dhdi->unit == WILD || dhdi->unit == i->i_unit ||
1892		     i->i_unit == STAR) &&
1893		    i->i_level >= dhdi->level)
1894			return 1;
1895	return 0;
1896}
1897
1898/*
1899 * This is almost the same as devbase_has_instances, except it
1900 * may have special considerations regarding ignored instances.
1901 */
1902
1903static int
1904devbase_has_any_instance(struct devbase *dev, int unit, int state, int level)
1905{
1906	struct deva *da;
1907	struct devi *i;
1908
1909	if (dev->d_ispseudo) {
1910		if (dev->d_ihead != NULL)
1911			return 1;
1912		else if (state != DEVI_IGNORED)
1913			return 0;
1914		if ((i = ht_lookup(deaddevitab, dev->d_name)) == NULL)
1915			return 0;
1916		return (i->i_level >= level);
1917	}
1918
1919	for (da = dev->d_ahead; da != NULL; da = da->d_bsame)
1920		for (i = da->d_ihead; i != NULL; i = i->i_asame)
1921			if ((i->i_active == DEVI_ACTIVE ||
1922			     i->i_active == state) &&
1923			    (unit == WILD || unit == i->i_unit ||
1924			     i->i_unit == STAR))
1925				return 1;
1926
1927	if (state == DEVI_IGNORED) {
1928		struct dhdi_params dhdi = { dev, unit, level };
1929		/* also check dead devices */
1930		return ht_enumerate(deaddevitab, devbase_has_dead_instances,
1931		    &dhdi);
1932	}
1933
1934	return 0;
1935}
1936
1937/*
1938 * check_dead_devi(), used with ht_enumerate, checks if any of the removed
1939 * device instances would have been a valid instance considering the devbase,
1940 * the parent device and the interface attribute.
1941 *
1942 * In other words, for a non-active device, it checks if children would be
1943 * actual orphans or the result of a negative statement in the config file.
1944 */
1945
1946struct cdd_params {
1947	struct devbase *d;
1948	struct attr *at;
1949	struct devbase *parent;
1950};
1951
1952static int
1953check_dead_devi(const char *key, void *value, void *aux)
1954{
1955	struct cdd_params *cdd = aux;
1956	struct devi *i = value;
1957	struct pspec *p;
1958
1959	if (i->i_base != cdd->d)
1960		return 0;
1961
1962	for (; i != NULL; i = i->i_alias) {
1963		p = i->i_pspec;
1964		if ((p == NULL && cdd->at == NULL) ||
1965		    (p != NULL && p->p_iattr == cdd->at &&
1966		     (p->p_atdev == NULL || p->p_atdev == cdd->parent))) {
1967			if (p != NULL &&
1968			    !devbase_has_any_instance(cdd->parent, p->p_atunit,
1969			    DEVI_IGNORED, i->i_level))
1970				return 0;
1971			else
1972				return 1;
1973		}
1974	}
1975	return 0;
1976}
1977
1978static struct devbase root;
1979
1980static int
1981addlevelparent(struct devbase *d, struct devbase *parent)
1982{
1983	struct devbase *p;
1984
1985	if (d == parent) {
1986		if (d->d_level > 1)
1987			return 0;
1988		return 1;
1989	}
1990
1991	if (d->d_levelparent) {
1992		if (d->d_level > 1)
1993			return 0;
1994		return 1;
1995	}
1996
1997	for (p = parent; p != NULL; p = p->d_levelparent)
1998		if (d == p && d->d_level > 1)
1999			return 0;
2000	d->d_levelparent = p ? p : &root;
2001	d->d_level++;
2002	return 1;
2003}
2004
2005static void
2006do_kill_orphans(struct devbase *d, struct attr *at, struct devbase *parent,
2007    int state)
2008{
2009	struct nvlist *nv1;
2010	struct attrlist *al;
2011	struct attr *a;
2012	struct devi *i, *j = NULL;
2013	struct pspec *p;
2014	int active = 0;
2015
2016	if (!addlevelparent(d, parent))
2017		return;
2018
2019	/*
2020	 * A pseudo-device will always attach at root, and if it has an
2021	 * instance (it cannot have more than one), it is enough to consider
2022	 * it active, as there is no real attachment.
2023	 *
2024	 * A pseudo device can never be marked DEVI_IGNORED.
2025	 */
2026	if (d->d_ispseudo) {
2027		if (d->d_ihead != NULL)
2028			d->d_ihead->i_active = active = DEVI_ACTIVE;
2029		else {
2030			if (ht_lookup(deaddevitab, d->d_name) != NULL)
2031				active = DEVI_IGNORED;
2032			else
2033				return;
2034		}
2035	} else {
2036		int seen = 0;
2037		int changed = 0;
2038
2039		for (i = d->d_ihead; i != NULL; i = i->i_bsame) {
2040			for (j = i; j != NULL; j = j->i_alias) {
2041				p = j->i_pspec;
2042				if ((p == NULL && at == NULL) ||
2043				    (p != NULL && p->p_iattr == at &&
2044				    (p->p_atdev == NULL ||
2045				    p->p_atdev == parent))) {
2046					if (p != NULL &&
2047					    !devbase_has_any_instance(parent,
2048					      p->p_atunit, state, j->i_level))
2049						continue;
2050					/*
2051					 * There are Fry-like devices which can
2052					 * be their own grand-parent (or even
2053					 * parent, like uhub).  We don't want
2054					 * to loop, so if we've already reached
2055					 * an instance for one reason or
2056					 * another, stop there.
2057					 */
2058					if (j->i_active == DEVI_ACTIVE ||
2059					    j->i_active == state) {
2060						/*
2061						 * Device has already been
2062						 * seen.  However it might
2063						 * have siblings who still
2064						 * have to be activated or
2065						 * orphaned.
2066						 */
2067						seen = 1;
2068						continue;
2069					}
2070					changed |= j->i_active != state;
2071					j->i_active = active = state;
2072					if (p != NULL) {
2073						if (state == DEVI_ACTIVE ||
2074						    --p->p_ref == 0)
2075							p->p_active = state;
2076					}
2077					if (state == DEVI_IGNORED) {
2078						CFGDBG(5,
2079						    "`%s' at '%s' ignored",
2080						    d->d_name, parent ?
2081						    parent->d_name : "(root)");
2082					}
2083				}
2084			}
2085		}
2086		/*
2087		 * If we've been there but have made no change, stop.
2088		 */
2089		if (seen && active != DEVI_ACTIVE)
2090			goto out;
2091		if (active != DEVI_ACTIVE) {
2092			struct cdd_params cdd = { d, at, parent };
2093			/* Look for a matching dead devi */
2094			if (ht_enumerate(deaddevitab, check_dead_devi, &cdd) &&
2095			    d != parent) {
2096				/*
2097				 * That device had its instances removed.
2098				 * Continue the loop marking descendants
2099				 * with DEVI_IGNORED instead of DEVI_ACTIVE.
2100				 *
2101				 * There is one special case for devices that
2102				 * are their own parent:  if that instance is
2103				 * removed (e.g., no uhub* at uhub?), we don't
2104				 * have to continue looping.
2105				 */
2106				active = DEVI_IGNORED;
2107				CFGDBG(5, "`%s' at '%s' ignored", d->d_name,
2108				    parent ? parent->d_name : "(root)");
2109
2110			} else if (!changed)
2111				goto out;
2112		}
2113	}
2114
2115	for (al = d->d_attrs; al != NULL; al = al->al_next) {
2116		a = al->al_this;
2117		for (nv1 = a->a_devs; nv1 != NULL; nv1 = nv1->nv_next) {
2118			do_kill_orphans(nv1->nv_ptr, a, d, active);
2119		}
2120	}
2121out:
2122	d->d_levelparent = NULL;
2123	d->d_level--;
2124}
2125
2126static int
2127/*ARGSUSED*/
2128kill_orphans_cb(const char *key, void *value, void *aux)
2129{
2130	do_kill_orphans((struct devbase *)value, NULL, NULL, DEVI_ACTIVE);
2131	return 0;
2132}
2133
2134static void
2135kill_orphans(void)
2136{
2137	ht_enumerate(devroottab, kill_orphans_cb, NULL);
2138}
2139
2140static void
2141add_makeopt(const char *opt)
2142{
2143	struct nvlist *p;
2144	char *buf = estrdup(opt);
2145	char *eq = strchr(buf, '=');
2146
2147	if (!eq)
2148		errx(EXIT_FAILURE, "-D %s is not in var=value format", opt);
2149
2150	*eq = 0;
2151	p = newnv(estrdup(buf), estrdup(eq+1), NULL, 0, NULL);
2152	free(buf);
2153	p->nv_next = cmdlinedefs;
2154	cmdlinedefs = p;
2155}
2156
2157static void
2158remove_makeopt(const char *opt)
2159{
2160	struct nvlist *p;
2161
2162	p = newnv(estrdup(opt), NULL, NULL, 0, NULL);
2163	p->nv_next = cmdlineundefs;
2164	cmdlineundefs = p;
2165}
2166
2167static void
2168handle_cmdline_makeoptions(void)
2169{
2170	struct nvlist *p, *n;
2171
2172	handling_cmdlineopts = 1;
2173	for (p = cmdlineundefs; p; p = n) {
2174		n = p->nv_next;
2175		delmkoption(intern(p->nv_name), 0);
2176		free(__UNCONST(p->nv_name));
2177		nvfree(p);
2178	}
2179	for (p = cmdlinedefs; p; p = n) {
2180		const char *name = intern(p->nv_name);
2181
2182		n = p->nv_next;
2183		delmkoption(name, 0);
2184		addmkoption(name, intern(p->nv_str));
2185		free(__UNCONST(p->nv_name));
2186		free(__UNCONST(p->nv_str));
2187
2188		nvfree(p);
2189	}
2190	handling_cmdlineopts = 0;
2191}
2192