xref: /netbsd-src/usr.bin/config/main.c (revision d48f14661dda8638fee055ba15d35bdfb29b9fa8)
1 /*	$NetBSD: main.c,v 1.13 2006/05/25 22:28:38 cube 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 #ifndef MAKE_BOOTSTRAP
48 #include <sys/cdefs.h>
49 #define	COPYRIGHT(x)	__COPYRIGHT(x)
50 #else
51 #define	COPYRIGHT(x)	static const char copyright[] = x
52 #endif
53 
54 #ifndef lint
55 COPYRIGHT("@(#) Copyright (c) 1992, 1993\n\
56 	The Regents of the University of California.  All rights reserved.\n");
57 #endif /* not lint */
58 
59 #include <sys/types.h>
60 #include <sys/stat.h>
61 #include <sys/param.h>
62 #include <sys/mman.h>
63 #include <paths.h>
64 #include <ctype.h>
65 #include <errno.h>
66 #include <fcntl.h>
67 #include <stdio.h>
68 #include <stdlib.h>
69 #include <string.h>
70 #include <unistd.h>
71 #include "defs.h"
72 #include "sem.h"
73 #include <vis.h>
74 
75 #ifndef LINE_MAX
76 #define LINE_MAX 1024
77 #endif
78 
79 int	vflag;				/* verbose output */
80 int	Pflag;				/* pack locators */
81 
82 int	yyparse(void);
83 
84 #ifndef MAKE_BOOTSTRAP
85 extern int yydebug;
86 #endif
87 
88 static struct hashtab *obsopttab;
89 static struct hashtab *mkopttab;
90 static struct nvlist **nextopt;
91 static struct nvlist **nextmkopt;
92 static struct nvlist **nextappmkopt;
93 static struct nvlist **nextfsopt;
94 
95 static	void	usage(void);
96 static	void	dependopts(void);
97 static	void	do_depend(struct nvlist *);
98 static	void	stop(void);
99 static	int	do_option(struct hashtab *, struct nvlist ***,
100 		    const char *, const char *, const char *);
101 static	int	undo_option(struct hashtab *, struct nvlist **,
102 		    struct nvlist ***, const char *, const char *);
103 static	int	crosscheck(void);
104 static	int	badstar(void);
105 	int	main(int, char **);
106 static	int	mksymlinks(void);
107 static	int	mkident(void);
108 static	int	devbase_has_dead_instances(const char *, void *, void *);
109 static	int	devbase_has_any_instance(struct devbase *, int, int, int);
110 static	int	check_dead_devi(const char *, void *, void *);
111 static	void	kill_orphans(void);
112 static	void	do_kill_orphans(struct devbase *, struct attr *,
113     struct devbase *, int);
114 static	int	kill_orphans_cb(const char *, void *, void *);
115 static	int	cfcrosscheck(struct config *, const char *, struct nvlist *);
116 static	const char *strtolower(const char *);
117 void	defopt(struct hashtab *ht, const char *fname,
118 	     struct nvlist *opts, struct nvlist *deps, int obs);
119 
120 #define LOGCONFIG_LARGE "INCLUDE_CONFIG_FILE"
121 #define LOGCONFIG_SMALL "INCLUDE_JUST_CONFIG"
122 
123 static	void	logconfig_start(void);
124 static	void	logconfig_end(void);
125 static	FILE	*cfg;
126 static	time_t	cfgtime;
127 
128 static	int	is_elf(const char *);
129 static	int	extract_config(const char *, const char *, int);
130 
131 int badfilename(const char *fname);
132 
133 const char *progname;
134 
135 int
136 main(int argc, char **argv)
137 {
138 	char *p, cname[20];
139 	const char *last_component;
140 	int pflag, xflag, ch, removeit;
141 
142 	setprogname(argv[0]);
143 
144 	pflag = 0;
145 	xflag = 0;
146 	while ((ch = getopt(argc, argv, "DPgpvb:s:x")) != -1) {
147 		switch (ch) {
148 
149 #ifndef MAKE_BOOTSTRAP
150 		case 'D':
151 			yydebug = 1;
152 			break;
153 #endif
154 
155 		case 'P':
156 			Pflag = 1;
157 			break;
158 
159 		case 'g':
160 			/*
161 			 * In addition to DEBUG, you probably wanted to
162 			 * set "options KGDB" and maybe others.  We could
163 			 * do that for you, but you really should just
164 			 * put them in the config file.
165 			 */
166 			(void)fprintf(stderr,
167 		    "config: -g is obsolete (use makeoptions DEBUG=\"-g\")\n");
168 			usage();
169 
170 		case 'p':
171 			/*
172 			 * Essentially the same as makeoptions PROF="-pg",
173 			 * but also changes the path from ../../compile/FOO
174 			 * to ../../compile/FOO.PROF; i.e., compile a
175 			 * profiling kernel based on a typical "regular"
176 			 * kernel.
177 			 *
178 			 * Note that if you always want profiling, you
179 			 * can (and should) use a "makeoptions" line.
180 			 */
181 			pflag = 1;
182 			break;
183 
184 		case 'v':
185 			vflag = 1;
186 			break;
187 
188 		case 'b':
189 			builddir = optarg;
190 			break;
191 
192 		case 's':
193 			srcdir = optarg;
194 			break;
195 
196 		case 'x':
197 			xflag = 1;
198 			break;
199 
200 		case '?':
201 		default:
202 			usage();
203 		}
204 	}
205 
206 	argc -= optind;
207 	argv += optind;
208 	if (argc > 1) {
209 		usage();
210 	}
211 
212 	if (xflag && (builddir != NULL || srcdir != NULL || Pflag || pflag ||
213 	    vflag)) {
214 		(void)fprintf(stderr, "config: -x must be used alone\n");
215 		exit(1);
216 	}
217 
218 	if (xflag) {
219 #ifdef __NetBSD__
220 		conffile = (argc == 1) ? argv[0] : _PATH_UNIX;
221 #else
222 		if (argc == 0) {
223 			(void)fprintf(stderr, "config: no kernel supplied\n");
224 			exit(1);
225 		}
226 #endif
227 		if (!is_elf(conffile)) {
228 			(void)fprintf(stderr,
229 			    "config: %s: not a binary kernel\n",
230 			    conffile);
231 			exit(1);
232 		}
233 		if (!extract_config(conffile, "stdout", STDOUT_FILENO)) {
234 			(void)fprintf(stderr,
235 			    "config: %s does not contain embedded "
236 			    "configuration data\n", conffile);
237 			exit(2);
238 		}
239 		exit(0);
240 	}
241 
242 	conffile = (argc == 1) ? argv[0] : "CONFIG";
243 	if (firstfile(conffile)) {
244 		(void)fprintf(stderr, "config: cannot read %s: %s\n",
245 		    conffile, strerror(errno));
246 		exit(2);
247 	}
248 
249 	/*
250 	 * Init variables.
251 	 */
252 	minmaxusers = 1;
253 	maxmaxusers = 10000;
254 	initintern();
255 	initfiles();
256 	initsem();
257 	ident = NULL;
258 	devbasetab = ht_new();
259 	devroottab = ht_new();
260 	devatab = ht_new();
261 	devitab = ht_new();
262 	deaddevitab = ht_new();
263 	selecttab = ht_new();
264 	needcnttab = ht_new();
265 	opttab = ht_new();
266 	mkopttab = ht_new();
267 	condmkopttab = ht_new();
268 	fsopttab = ht_new();
269 	deffstab = ht_new();
270 	defopttab = ht_new();
271 	defparamtab = ht_new();
272 	defflagtab = ht_new();
273 	optfiletab = ht_new();
274 	obsopttab = ht_new();
275 	bdevmtab = ht_new();
276 	maxbdevm = 0;
277 	cdevmtab = ht_new();
278 	maxcdevm = 0;
279 	nextopt = &options;
280 	nextmkopt = &mkoptions;
281 	nextappmkopt = &appmkoptions;
282 	nextfsopt = &fsoptions;
283 
284 	/*
285 	 * Handle profiling (must do this before we try to create any
286 	 * files).
287 	 */
288 	last_component = strrchr(conffile, '/');
289 	last_component = (last_component) ? last_component + 1 : conffile;
290 	if (pflag) {
291 		p = emalloc(strlen(last_component) + 17);
292 		(void)sprintf(p, "../compile/%s.PROF", last_component);
293 		(void)addmkoption(intern("PROF"), "-pg");
294 		(void)addoption(intern("GPROF"), NULL);
295 	} else {
296 		p = emalloc(strlen(last_component) + 13);
297 		(void)sprintf(p, "../compile/%s", last_component);
298 	}
299 	defbuilddir = (argc == 0) ? "." : p;
300 
301 	removeit = 0;
302 	if (is_elf(conffile)) {
303 		const char *tmpdir;
304 		int cfd;
305 
306 		if (builddir == NULL) {
307 			(void)fprintf(stderr,
308 			    "config: build directory must be specified with "
309 			    "binary kernels\n");
310 			exit(1);
311 		}
312 
313 		/* Open temporary configuration file */
314 		tmpdir = getenv("TMPDIR");
315 		if (tmpdir == NULL)
316 			tmpdir = "/tmp";
317 		snprintf(cname, sizeof(cname), "%s/config.tmp.XXXXXX", tmpdir);
318 		cfd = mkstemp(cname);
319 		if (cfd == -1) {
320 			fprintf(stderr, "config: cannot create %s: %s", cname,
321 			    strerror(errno));
322 			exit(2);
323 		}
324 
325 		printf("Using configuration data embedded in kernel...\n");
326 		if (!extract_config(conffile, cname, cfd)) {
327 			(void)fprintf(stderr,
328 			    "config: %s does not contain embedded "
329 			    "configuration data\n", conffile);
330 			exit(2);
331 		}
332 
333 		removeit = 1;
334 		close(cfd);
335 		firstfile(cname);
336 	}
337 
338 	/*
339 	 * Parse config file (including machine definitions).
340 	 */
341 	logconfig_start();
342 	if (yyparse())
343 		stop();
344 	logconfig_end();
345 
346 	if (removeit)
347 		unlink(cname);
348 
349 	/*
350 	 * Detect and properly ignore orphaned devices
351 	 */
352 	kill_orphans();
353 
354 	/*
355 	 * Select devices and pseudo devices and their attributes
356 	 */
357 	if (fixdevis())
358 		stop();
359 
360 	/*
361 	 * Deal with option dependencies.
362 	 */
363 	dependopts();
364 
365 	/*
366 	 * Fix (as in `set firmly in place') files.
367 	 */
368 	if (fixfiles())
369 		stop();
370 
371 	/*
372 	 * Fix objects and libraries.
373 	 */
374 	if (fixobjects())
375 		stop();
376 
377 	/*
378 	 * Fix device-majors.
379 	 */
380 	if (fixdevsw())
381 		stop();
382 
383 	/*
384 	 * Perform cross-checking.
385 	 */
386 	if (maxusers == 0) {
387 		if (defmaxusers) {
388 			(void)printf("maxusers not specified; %d assumed\n",
389 			    defmaxusers);
390 			maxusers = defmaxusers;
391 		} else {
392 			(void)fprintf(stderr,
393 			    "config: need \"maxusers\" line\n");
394 			errors++;
395 		}
396 	}
397 	if (fsoptions == NULL) {
398 		(void)fprintf(stderr,
399 		    "config: need at least one \"file-system\" line\n");
400 		errors++;
401 	}
402 	if (crosscheck() || errors)
403 		stop();
404 
405 	/*
406 	 * Squeeze things down and finish cross-checks (STAR checks must
407 	 * run after packing).
408 	 */
409 	pack();
410 	if (badstar())
411 		stop();
412 
413 	/*
414 	 * Ready to go.  Build all the various files.
415 	 */
416 	if (mksymlinks() || mkmakefile() || mkheaders() || mkswap() ||
417 	    mkioconf() || (do_devsw ? mkdevsw() : 0) || mkident())
418 		stop();
419 	(void)printf("Build directory is %s\n", builddir);
420 	(void)printf("Don't forget to run \"make depend\"\n");
421 	exit(0);
422 }
423 
424 static void
425 usage(void)
426 {
427 	(void)fputs("usage: config [-Ppv] [-s srcdir] [-b builddir] "
428 		"[sysname]\n", stderr);
429 	(void)fputs("       config -x [kernel-file]\n", stderr);
430 	exit(1);
431 }
432 
433 /*
434  * Set any options that are implied by other options.
435  */
436 static void
437 dependopts(void)
438 {
439 	struct nvlist *nv, *opt;
440 
441 	for (nv = options; nv != NULL; nv = nv->nv_next) {
442 		if ((opt = find_declared_option(nv->nv_name)) != NULL) {
443 			for (opt = opt->nv_ptr; opt != NULL;
444 			    opt = opt->nv_next) {
445 				do_depend(opt);
446 			}
447 		}
448 	}
449 }
450 
451 static void
452 do_depend(struct nvlist *nv)
453 {
454 	struct nvlist *nextnv;
455 	struct attr *a;
456 
457 	if (nv != NULL && (nv->nv_flags & NV_DEPENDED) == 0) {
458 		nv->nv_flags |= NV_DEPENDED;
459 		/*
460 		 * If the dependency is an attribute, then just add
461 		 * it to the selecttab.
462 		 */
463 		if ((a = ht_lookup(attrtab, nv->nv_name)) != NULL) {
464 			if (a->a_iattr)
465 				panic("do_depend(%s): dep `%s' is an iattr",
466 				    nv->nv_name, a->a_name);
467 			expandattr(a, selectattr);
468 		} else {
469 			if (ht_lookup(opttab, nv->nv_name) == NULL)
470 				addoption(nv->nv_name, NULL);
471 			if ((nextnv =
472 			     find_declared_option(nv->nv_name)) != NULL)
473 				do_depend(nextnv->nv_ptr);
474 		}
475 	}
476 }
477 
478 /*
479  * Make a symlink for "machine" so that "#include <machine/foo.h>" works,
480  * and for the machine's CPU architecture, so that works as well.
481  */
482 static int
483 mksymlinks(void)
484 {
485 	int ret;
486 	char *p, buf[MAXPATHLEN];
487 	const char *q;
488 	struct nvlist *nv;
489 
490 	snprintf(buf, sizeof(buf), "arch/%s/include", machine);
491 	p = sourcepath(buf);
492 	ret = unlink("machine");
493 	if (ret && errno != ENOENT)
494 		(void)fprintf(stderr, "config: unlink(machine): %s\n",
495 		    strerror(errno));
496 	ret = symlink(p, "machine");
497 	if (ret)
498 		(void)fprintf(stderr, "config: symlink(machine -> %s): %s\n",
499 		    p, strerror(errno));
500 	free(p);
501 
502 	if (machinearch != NULL) {
503 		snprintf(buf, sizeof(buf), "arch/%s/include", machinearch);
504 		p = sourcepath(buf);
505 		q = machinearch;
506 	} else {
507 		p = estrdup("machine");
508 		q = machine;
509 	}
510 	ret = unlink(q);
511 	if (ret && errno != ENOENT)
512 		(void)fprintf(stderr, "config: unlink(%s): %s\n",
513 		    q, strerror(errno));
514 	ret = symlink(p, q);
515 	if (ret)
516 		(void)fprintf(stderr, "config: symlink(%s -> %s): %s\n",
517 		    q, p, strerror(errno));
518 	free(p);
519 
520 	for (nv = machinesubarches; nv != NULL; nv = nv->nv_next) {
521 		q = nv->nv_name;
522 		snprintf(buf, sizeof(buf), "arch/%s/include", q);
523 		p = sourcepath(buf);
524 		ret = unlink(q);
525 		if (ret && errno != ENOENT)
526 			(void)fprintf(stderr, "config: unlink(%s): %s\n",
527 			    q, strerror(errno));
528 		ret = symlink(p, q);
529 		if (ret)
530 			(void)fprintf(stderr, "config: symlink(%s -> %s): %s\n",
531 		    	q, p, strerror(errno));
532 		free(p);
533 	}
534 
535 	return (ret);
536 }
537 
538 static __dead void
539 stop(void)
540 {
541 	(void)fprintf(stderr, "*** Stop.\n");
542 	exit(1);
543 }
544 
545 /*
546  * Define one or more file systems.  If file system options file name is
547  * specified, a preprocessor #define for that file system will be placed
548  * in that file.  In this case, only one file system may be specified.
549  * Otherwise, no preprocessor #defines will be generated.
550  */
551 void
552 deffilesystem(const char *fname, struct nvlist *fses)
553 {
554 	struct nvlist *nv;
555 
556 	/*
557 	 * Mark these options as ones to skip when creating the Makefile.
558 	 */
559 	for (nv = fses; nv != NULL; nv = nv->nv_next) {
560 		if (ht_insert(defopttab, nv->nv_name, nv)) {
561 			error("file system or option `%s' already defined",
562 			    nv->nv_name);
563 			return;
564 		}
565 
566 		/*
567 		 * Also mark it as a valid file system, which may be
568 		 * used in "file-system" directives in the config
569 		 * file.
570 		 */
571 		if (ht_insert(deffstab, nv->nv_name, nv))
572 			panic("file system `%s' already in table?!",
573 			    nv->nv_name);
574 
575 		if (fname != NULL) {
576 			/*
577 			 * Only one file system allowed in this case.
578 			 */
579 			if (nv->nv_next != NULL) {
580 				error("only one file system per option "
581 				    "file may be specified");
582 				return;
583 			}
584 
585 			if (ht_insert(optfiletab, fname, nv)) {
586 				error("option file `%s' already exists",
587 				    fname);
588 				return;
589 			}
590 		}
591 	}
592 }
593 
594 /*
595  * Sanity check a file name.
596  */
597 int
598 badfilename(const char *fname)
599 {
600 	const char *n;
601 
602 	/*
603 	 * We're putting multiple options into one file.  Sanity
604 	 * check the file name.
605 	 */
606 	if (strchr(fname, '/') != NULL) {
607 		error("option file name contains a `/'");
608 		return 1;
609 	}
610 	if ((n = strrchr(fname, '.')) == NULL || strcmp(n, ".h") != 0) {
611 		error("option file name does not end in `.h'");
612 		return 1;
613 	}
614 	return 0;
615 }
616 
617 
618 /*
619  * Search for a defined option (defopt, filesystem, etc), and if found,
620  * return the option's struct nvlist.
621  */
622 struct nvlist *
623 find_declared_option(const char *name)
624 {
625 	struct nvlist *option = NULL;
626 
627 	if ((option = ht_lookup(defopttab, name)) != NULL ||
628 	    (option = ht_lookup(defparamtab, name)) != NULL ||
629 	    (option = ht_lookup(defflagtab, name)) != NULL ||
630 	    (option = ht_lookup(fsopttab, name)) != NULL) {
631 		return (option);
632 	}
633 
634 	return (NULL);
635 }
636 
637 
638 /*
639  * Define one or more standard options.  If an option file name is specified,
640  * place all options in one file with the specified name.  Otherwise, create
641  * an option file for each option.
642  * record the option information in the specified table.
643  */
644 void
645 defopt(struct hashtab *ht, const char *fname, struct nvlist *opts,
646        struct nvlist *deps, int obs)
647 {
648 	struct nvlist *nv, *nextnv, *oldnv, *dep;
649 	struct attr *a;
650 	const char *name;
651 	char buf[500];
652 
653 	if (fname != NULL && badfilename(fname)) {
654 		return;
655 	}
656 
657 	/*
658 	 * Mark these options as ones to skip when creating the Makefile.
659 	 */
660 	for (nv = opts; nv != NULL; nv = nextnv) {
661 		nextnv = nv->nv_next;
662 
663 		/* An option name can be declared at most once. */
664 		if (DEFINED_OPTION(nv->nv_name)) {
665 			error("file system or option `%s' already defined",
666 			    nv->nv_name);
667 			return;
668 		}
669 
670 		if (ht_insert(ht, nv->nv_name, nv)) {
671 			error("file system or option `%s' already defined",
672 			    nv->nv_name);
673 			return;
674 		}
675 
676 		if (fname == NULL) {
677 			/*
678 			 * Each option will be going into its own file.
679 			 * Convert the option name to lower case.  This
680 			 * lower case name will be used as the option
681 			 * file name.
682 			 */
683 			(void) snprintf(buf, sizeof(buf), "opt_%s.h",
684 			    strtolower(nv->nv_name));
685 			name = intern(buf);
686 		} else {
687 			name = fname;
688 		}
689 
690 		/* Use nv_ptr to link any other options that are implied. */
691 		nv->nv_ptr = deps;
692 		for (dep = deps; dep != NULL; dep = dep->nv_next) {
693 			/*
694 			 * If the dependency is an attribute, it must not
695 			 * be an interface attribute.  Otherwise, it must
696 			 * be a previously declared option.
697 			 */
698 			if ((a = ht_lookup(attrtab, dep->nv_name)) != NULL) {
699 				if (a->a_iattr)
700 					error("option `%s' dependency `%s' "
701 					    "is an interface attribute",
702 					    nv->nv_name, a->a_name);
703 			} else if (OPT_OBSOLETE(dep->nv_name)) {
704 				error("option `%s' dependency `%s' "
705 				    "is obsolete", nv->nv_name, dep->nv_name);
706 			} else if (find_declared_option(dep->nv_name) == NULL) {
707 				error("option `%s' dependency `%s' "
708 				    "is an unknown option",
709 				    nv->nv_name, dep->nv_name);
710 			}
711 		}
712 
713 		/*
714 		 * Remove this option from the parameter list before adding
715 		 * it to the list associated with this option file.
716 		 */
717 		nv->nv_next = NULL;
718 
719 		/*
720 		 * Flag as obsolete, if requested.
721 		 */
722 		if (obs) {
723 			nv->nv_flags |= NV_OBSOLETE;
724 			(void)ht_insert(obsopttab, nv->nv_name, nv);
725 		}
726 
727 		/*
728 		 * Add this option file if we haven't seen it yet.
729 		 * Otherwise, append to the list of options already
730 		 * associated with this file.
731 		 */
732 		if ((oldnv = ht_lookup(optfiletab, name)) == NULL) {
733 			(void)ht_insert(optfiletab, name, nv);
734 		} else {
735 			while (oldnv->nv_next != NULL)
736 				oldnv = oldnv->nv_next;
737 			oldnv->nv_next = nv;
738 		}
739 	}
740 }
741 
742 /*
743  * Define one or more standard options.  If an option file name is specified,
744  * place all options in one file with the specified name.  Otherwise, create
745  * an option file for each option.
746  */
747 void
748 defoption(const char *fname, struct nvlist *opts, struct nvlist *deps)
749 {
750 
751 	warn("The use of `defopt' is deprecated");
752 	defopt(defopttab, fname, opts, deps, 0);
753 }
754 
755 
756 /*
757  * Define an option for which a value is required.
758  */
759 void
760 defparam(const char *fname, struct nvlist *opts, struct nvlist *deps, int obs)
761 {
762 
763 	defopt(defparamtab, fname, opts, deps, obs);
764 }
765 
766 /*
767  * Define an option which must not have a value, and which
768  * emits a "needs-flag" style output.
769  */
770 void
771 defflag(const char *fname, struct nvlist *opts, struct nvlist *deps, int obs)
772 {
773 
774 	defopt(defflagtab, fname, opts, deps, obs);
775 }
776 
777 
778 /*
779  * Add an option from "options FOO".  Note that this selects things that
780  * are "optional foo".
781  */
782 void
783 addoption(const char *name, const char *value)
784 {
785 	const char *n;
786 	int is_fs, is_param, is_flag, is_opt, is_undecl, is_obs;
787 
788 	/*
789 	 * Figure out how this option was declared (if at all.)
790 	 * XXX should use "params" and "flags" in config.
791 	 * XXX crying out for a type field in a unified hashtab.
792 	 */
793 	is_fs = OPT_FSOPT(name);
794 	is_param = OPT_DEFPARAM(name);
795 	is_opt = OPT_DEFOPT(name);
796 	is_flag =  OPT_DEFFLAG(name);
797 	is_obs = OPT_OBSOLETE(name);
798 	is_undecl = !DEFINED_OPTION(name);
799 
800 	/* Warn and pretend the user had not selected the option  */
801 	if (is_obs) {
802 		warn("obsolete option `%s' will be ignored", name);
803 		return;
804 	}
805 
806 	/* Make sure this is not a defined file system. */
807 	if (is_fs) {
808 		error("`%s' is a defined file system", name);
809 		return;
810 	}
811 	/* A defparam must have a value */
812 	if (is_param && value == NULL) {
813 		error("option `%s' must have a value", name);
814 		return;
815 	}
816 	/* A defflag must not have a value */
817 	if (is_flag && value != NULL) {
818 		error("option `%s' must not have a value", name);
819 		return;
820 	}
821 
822 	if (is_undecl && vflag) {
823 		warn("undeclared option `%s' added to IDENT", name);
824 	}
825 
826 	if (do_option(opttab, &nextopt, name, value, "options"))
827 		return;
828 
829 	/* make lowercase, then add to select table */
830 	n = strtolower(name);
831 	(void)ht_insert(selecttab, n, (void *)n);
832 }
833 
834 void
835 deloption(const char *name)
836 {
837 
838 	if (undo_option(opttab, &options, &nextopt, name, "options"))
839 		return;
840 	if (undo_option(selecttab, NULL, NULL, strtolower(name), "options"))
841 		return;
842 }
843 
844 /*
845  * Add a file system option.  This routine simply inserts the name into
846  * a list of valid file systems, which is used to validate the root
847  * file system type.  The name is then treated like a standard option.
848  */
849 void
850 addfsoption(const char *name)
851 {
852 	const char *n;
853 
854 	/* Make sure this is a defined file system. */
855 	if (!OPT_FSOPT(name)) {
856 		error("`%s' is not a defined file system", name);
857 		return;
858 	}
859 
860 	/*
861 	 * Convert to lower case.  This will be used in the select
862 	 * table, to verify root file systems, and when the initial
863 	 * VFS list is created.
864 	 */
865 	n = strtolower(name);
866 
867 	if (do_option(fsopttab, &nextfsopt, name, n, "file-system"))
868 		return;
869 
870 	/*
871 	 * Add a lower-case version to the table for root file system
872 	 * verification.
873 	 */
874 	if (ht_insert(fsopttab, n, (void *)n))
875 		panic("addfsoption: already in table");
876 
877 	/* Add to select table. */
878 	(void)ht_insert(selecttab, n, (void *)n);
879 }
880 
881 void
882 delfsoption(const char *name)
883 {
884 	const char *n;
885 
886 	n = strtolower(name);
887 	if (undo_option(fsopttab, &fsoptions, &nextfsopt, name, "file-system"))
888 		return;
889 	if (undo_option(fsopttab, NULL, NULL, n, "file-system"))
890 		return;
891 	if (undo_option(selecttab, NULL, NULL, n, "file-system"))
892 		return;
893 }
894 
895 /*
896  * Add a "make" option.
897  */
898 void
899 addmkoption(const char *name, const char *value)
900 {
901 
902 	(void)do_option(mkopttab, &nextmkopt, name, value, "makeoptions");
903 }
904 
905 void
906 delmkoption(const char *name)
907 {
908 
909 	(void)undo_option(mkopttab, &mkoptions, &nextmkopt, name,
910 	    "makeoptions");
911 }
912 
913 /*
914  * Add an appending "make" option.
915  */
916 void
917 appendmkoption(const char *name, const char *value)
918 {
919 	struct nvlist *nv;
920 
921 	nv = newnv(name, value, NULL, 0, NULL);
922 	*nextappmkopt = nv;
923 	nextappmkopt = &nv->nv_next;
924 }
925 
926 /*
927  * Add a conditional appending "make" option.
928  */
929 void
930 appendcondmkoption(const char *selname, const char *name, const char *value)
931 {
932 	struct nvlist *nv, *lnv;
933 	const char *n;
934 
935 	n = strtolower(selname);
936 	nv = newnv(name, value, NULL, 0, NULL);
937 	if (ht_insert(condmkopttab, n, nv) == 0)
938 		return;
939 
940 	if ((lnv = ht_lookup(condmkopttab, n)) == NULL)
941 		panic("appendcondmkoption");
942 	for (; lnv->nv_next != NULL; lnv = lnv->nv_next)
943 		/* search for the last list element */;
944 	lnv->nv_next = nv;
945 }
946 
947 /*
948  * Add a name=value pair to an option list.  The value may be NULL.
949  */
950 static int
951 do_option(struct hashtab *ht, struct nvlist ***nppp, const char *name,
952 	  const char *value, const char *type)
953 {
954 	struct nvlist *nv;
955 
956 	/*
957 	 * If a defopt'ed or defflag'ed option was enabled but without
958 	 * an explicit value (always the case for defflag), supply a
959 	 * default value of 1, as for non-defopt options (where cc
960 	 * treats -DBAR as -DBAR=1.)
961 	 */
962 	if ((OPT_DEFOPT(name) || OPT_DEFFLAG(name)) && value == NULL)
963 		value = "1";
964 
965 	/* assume it will work */
966 	nv = newnv(name, value, NULL, 0, NULL);
967 	if (ht_insert(ht, name, nv) == 0) {
968 		**nppp = nv;
969 		*nppp = &nv->nv_next;
970 		return (0);
971 	}
972 
973 	/* oops, already got that option */
974 	nvfree(nv);
975 	if ((nv = ht_lookup(ht, name)) == NULL)
976 		panic("do_option");
977 	if (nv->nv_str != NULL && !OPT_FSOPT(name))
978 		error("already have %s `%s=%s'", type, name, nv->nv_str);
979 	else
980 		error("already have %s `%s'", type, name);
981 	return (1);
982 }
983 
984 /*
985  * Remove a name from a hash table,
986  * and optionally, a name=value pair from an option list.
987  */
988 static int
989 undo_option(struct hashtab *ht, struct nvlist **npp,
990     struct nvlist ***next, const char *name, const char *type)
991 {
992 	struct nvlist *nv;
993 
994 	if (ht_remove(ht, name)) {
995 		error("%s `%s' is not defined", type, name);
996 		return (1);
997 	}
998 	if (npp == NULL)
999 		return (0);
1000 
1001 	for ( ; *npp != NULL; npp = &(*npp)->nv_next) {
1002 		if ((*npp)->nv_name != name)
1003 			continue;
1004 		if (next != NULL && *next == &(*npp)->nv_next)
1005 			*next = npp;
1006 		nv = (*npp)->nv_next;
1007 		nvfree(*npp);
1008 		*npp = nv;
1009 		return (0);
1010 	}
1011 	panic("%s `%s' is not defined in nvlist", type, name);
1012 	return (1);
1013 }
1014 
1015 /*
1016  * Return true if there is at least one instance of the given unit
1017  * on the given device attachment (or any units, if unit == WILD).
1018  */
1019 int
1020 deva_has_instances(struct deva *deva, int unit)
1021 {
1022 	struct devi *i;
1023 
1024 	for (i = deva->d_ihead; i != NULL; i = i->i_asame)
1025 		if (i->i_active == DEVI_ACTIVE &&
1026 		    (unit == WILD || unit == i->i_unit || i->i_unit == STAR))
1027 			return (1);
1028 	return (0);
1029 }
1030 
1031 /*
1032  * Return true if there is at least one instance of the given unit
1033  * on the given base (or any units, if unit == WILD).
1034  */
1035 int
1036 devbase_has_instances(struct devbase *dev, int unit)
1037 {
1038 	struct deva *da;
1039 
1040 	/*
1041 	 * Pseudo-devices are a little special.  We consider them
1042 	 * to have instances only if they are both:
1043 	 *
1044 	 *	1. Included in this kernel configuration.
1045 	 *
1046 	 *	2. Have one or more interface attributes.
1047 	 */
1048 	if (dev->d_ispseudo) {
1049 		struct nvlist *nv;
1050 		struct attr *a;
1051 
1052 		if (ht_lookup(devitab, dev->d_name) == NULL)
1053 			return (0);
1054 
1055 		for (nv = dev->d_attrs; nv != NULL; nv = nv->nv_next) {
1056 			a = nv->nv_ptr;
1057 			if (a->a_iattr)
1058 				return (1);
1059 		}
1060 		return (0);
1061 	}
1062 
1063 	for (da = dev->d_ahead; da != NULL; da = da->d_bsame)
1064 		if (deva_has_instances(da, unit))
1065 			return (1);
1066 	return (0);
1067 }
1068 
1069 static int
1070 cfcrosscheck(struct config *cf, const char *what, struct nvlist *nv)
1071 {
1072 	struct devbase *dev;
1073 	struct devi *pd;
1074 	int errs, devunit;
1075 
1076 	if (maxpartitions <= 0)
1077 		panic("cfcrosscheck");
1078 
1079 	for (errs = 0; nv != NULL; nv = nv->nv_next) {
1080 		if (nv->nv_name == NULL)
1081 			continue;
1082 		dev = ht_lookup(devbasetab, nv->nv_name);
1083 		if (dev == NULL)
1084 			panic("cfcrosscheck(%s)", nv->nv_name);
1085 		if (has_attr(dev->d_attrs, s_ifnet))
1086 			devunit = nv->nv_ifunit;	/* XXX XXX XXX */
1087 		else
1088 			devunit = minor(nv->nv_int) / maxpartitions;
1089 		if (devbase_has_instances(dev, devunit))
1090 			continue;
1091 		if (devbase_has_instances(dev, STAR) &&
1092 		    devunit >= dev->d_umax)
1093 			continue;
1094 		TAILQ_FOREACH(pd, &allpseudo, i_next) {
1095 			if (pd->i_base == dev && devunit < dev->d_umax &&
1096 			    devunit >= 0)
1097 				goto loop;
1098 		}
1099 		(void)fprintf(stderr,
1100 		    "%s:%d: %s says %s on %s, but there's no %s\n",
1101 		    conffile, cf->cf_lineno,
1102 		    cf->cf_name, what, nv->nv_str, nv->nv_str);
1103 		errs++;
1104  loop:
1105 		;
1106 	}
1107 	return (errs);
1108 }
1109 
1110 /*
1111  * Cross-check the configuration: make sure that each target device
1112  * or attribute (`at foo[0*?]') names at least one real device.  Also
1113  * see that the root and dump devices for all configurations are there.
1114  */
1115 int
1116 crosscheck(void)
1117 {
1118 	struct config *cf;
1119 	int errs;
1120 
1121 	errs = 0;
1122 	if (TAILQ_EMPTY(&allcf)) {
1123 		(void)fprintf(stderr, "%s has no configurations!\n",
1124 		    conffile);
1125 		errs++;
1126 	}
1127 	TAILQ_FOREACH(cf, &allcf, cf_next) {
1128 		if (cf->cf_root != NULL) {	/* i.e., not root on ? */
1129 			errs += cfcrosscheck(cf, "root", cf->cf_root);
1130 			errs += cfcrosscheck(cf, "dumps", cf->cf_dump);
1131 		}
1132 	}
1133 	return (errs);
1134 }
1135 
1136 /*
1137  * Check to see if there is a *'d unit with a needs-count file.
1138  */
1139 int
1140 badstar(void)
1141 {
1142 	struct devbase *d;
1143 	struct deva *da;
1144 	struct devi *i;
1145 	int errs, n;
1146 
1147 	errs = 0;
1148 	TAILQ_FOREACH(d, &allbases, d_next) {
1149 		for (da = d->d_ahead; da != NULL; da = da->d_bsame)
1150 			for (i = da->d_ihead; i != NULL; i = i->i_asame) {
1151 				if (i->i_unit == STAR)
1152 					goto aybabtu;
1153 			}
1154 		continue;
1155  aybabtu:
1156 		if (ht_lookup(needcnttab, d->d_name)) {
1157 			(void)fprintf(stderr,
1158 		    "config: %s's cannot be *'d until its driver is fixed\n",
1159 			    d->d_name);
1160 			errs++;
1161 			continue;
1162 		}
1163 		for (n = 0; i != NULL; i = i->i_alias)
1164 			if (!i->i_collapsed)
1165 				n++;
1166 		if (n < 1)
1167 			panic("badstar() n<1");
1168 	}
1169 	return (errs);
1170 }
1171 
1172 /*
1173  * Verify/create builddir if necessary, change to it, and verify srcdir.
1174  * This will be called when we see the first include.
1175  */
1176 void
1177 setupdirs(void)
1178 {
1179 	struct stat st;
1180 
1181 	/* srcdir must be specified if builddir is not specified or if
1182 	 * no configuration filename was specified. */
1183 	if ((builddir || strcmp(defbuilddir, ".") == 0) && !srcdir) {
1184 		error("source directory must be specified");
1185 		exit(1);
1186 	}
1187 
1188 	if (srcdir == NULL)
1189 		srcdir = "../../../..";
1190 	if (builddir == NULL)
1191 		builddir = defbuilddir;
1192 
1193 	if (stat(builddir, &st) != 0) {
1194 		if (mkdir(builddir, 0777)) {
1195 			(void)fprintf(stderr, "config: cannot create %s: %s\n",
1196 			    builddir, strerror(errno));
1197 			exit(2);
1198 		}
1199 	} else if (!S_ISDIR(st.st_mode)) {
1200 		(void)fprintf(stderr, "config: %s is not a directory\n",
1201 			      builddir);
1202 		exit(2);
1203 	}
1204 	if (chdir(builddir) != 0) {
1205 		(void)fprintf(stderr, "config: cannot change to %s\n",
1206 			      builddir);
1207 		exit(2);
1208 	}
1209 	if (stat(srcdir, &st) != 0 || !S_ISDIR(st.st_mode)) {
1210 		(void)fprintf(stderr, "config: %s is not a directory\n",
1211 			      srcdir);
1212 		exit(2);
1213 	}
1214 }
1215 
1216 /*
1217  * Write identifier from "ident" directive into file, for
1218  * newvers.sh to pick it up.
1219  */
1220 int
1221 mkident(void)
1222 {
1223 	FILE *fp;
1224 	int error = 0;
1225 
1226 	(void)unlink("ident");
1227 
1228 	if (ident == NULL)
1229 		return (0);
1230 
1231 	if ((fp = fopen("ident", "w")) == NULL) {
1232 		(void)fprintf(stderr, "config: cannot write ident: %s\n",
1233 		    strerror(errno));
1234 		return (1);
1235 	}
1236 	if (vflag)
1237 		(void)printf("using ident '%s'\n", ident);
1238 	if (fprintf(fp, "%s\n", ident) < 0)
1239 		error = 1;
1240 	(void)fclose(fp);
1241 
1242 	return error;
1243 }
1244 
1245 void
1246 logconfig_start(void)
1247 {
1248 	extern FILE *yyin;
1249 	char line[1024];
1250 	const char *tmpdir;
1251 	struct stat st;
1252 	int fd;
1253 
1254 	if (yyin == NULL || fstat(fileno(yyin), &st) == -1)
1255 		return;
1256 	cfgtime = st.st_mtime;
1257 
1258 	tmpdir = getenv("TMPDIR");
1259 	if (tmpdir == NULL)
1260 		tmpdir = "/tmp";
1261 	snprintf(line, sizeof(line), "%s/config.tmp.XXXXXX", tmpdir);
1262 	if ((fd = mkstemp(line)) == -1 ||
1263 	    (cfg = fdopen(fd, "r+")) == NULL) {
1264 		if (fd != -1) {
1265 			unlink(line);
1266 			close(fd);
1267 		}
1268 		cfg = NULL;
1269 		return;
1270 	}
1271 	unlink(line);
1272 
1273 	(void)fprintf(cfg, "#include \"opt_config.h\"\n");
1274 	(void)fprintf(cfg, "\n");
1275 	(void)fprintf(cfg, "/*\n");
1276 	(void)fprintf(cfg, " * Add either (or both) of\n");
1277 	(void)fprintf(cfg, " *\n");
1278 	(void)fprintf(cfg, " *\toptions %s\n", LOGCONFIG_LARGE);
1279 	(void)fprintf(cfg, " *\toptions %s\n", LOGCONFIG_SMALL);
1280 	(void)fprintf(cfg, " *\n");
1281 	(void)fprintf(cfg,
1282 	    " * to your kernel config file to embed it in the resulting\n");
1283 	(void)fprintf(cfg,
1284 	    " * kernel.  The latter option does not include files that are\n");
1285 	(void)fprintf(cfg,
1286 	    " * included (recursively) by your config file.  The embedded\n");
1287 	(void)fprintf(cfg,
1288 	    " * data be extracted by using the command:\n");
1289 	(void)fprintf(cfg, " *\n");
1290 	(void)fprintf(cfg,
1291 	    " *\tstrings netbsd | sed -n 's/^_CFG_//p' | unvis\n");
1292 	(void)fprintf(cfg, " */\n");
1293 	(void)fprintf(cfg, "\n");
1294 	(void)fprintf(cfg, "#ifdef CONFIG_FILE\n");
1295 	(void)fprintf(cfg, "#if defined(%s) || defined(%s)\n\n",
1296 	    LOGCONFIG_LARGE, LOGCONFIG_SMALL);
1297 	(void)fprintf(cfg,
1298 	    "static const char config[]\n#ifdef __vax__\n"
1299 	    "\t__attribute__((__unused__))\n#else\n"
1300 	    "\t__attribute__((__used__))\n#endif\n\t=\n\n");
1301 
1302 	(void)fprintf(cfg, "#ifdef %s\n\n", LOGCONFIG_LARGE);
1303 	(void)fprintf(cfg, "\"_CFG_### START CONFIG FILE \\\"%s\\\"\\n\"\n\n",
1304 	    conffile);
1305 	(void)fprintf(cfg, "#endif /* %s */\n\n", LOGCONFIG_LARGE);
1306 
1307 	logconfig_include(yyin, NULL);
1308 
1309 	(void)fprintf(cfg, "#ifdef %s\n\n", LOGCONFIG_LARGE);
1310 	(void)fprintf(cfg, "\"_CFG_### END CONFIG FILE \\\"%s\\\"\\n\"\n",
1311 	    conffile);
1312 
1313 	rewind(yyin);
1314 }
1315 
1316 void
1317 logconfig_include(FILE *cf, const char *filename)
1318 {
1319 	char line[1024], in[2048], *out;
1320 	struct stat st;
1321 	int missingeol;
1322 
1323 	if (!cfg)
1324 		return;
1325 
1326 	missingeol = 0;
1327 	if (fstat(fileno(cf), &st) == -1)
1328 		return;
1329 	if (cfgtime < st.st_mtime)
1330 		cfgtime = st.st_mtime;
1331 
1332 	if (filename)
1333 		(void)fprintf(cfg,
1334 		    "\"_CFG_### (included from \\\"%s\\\")\\n\"\n",
1335 		    filename);
1336 	while (fgets(line, sizeof(line), cf) != NULL) {
1337 		missingeol = 1;
1338 		(void)fprintf(cfg, "\"_CFG_");
1339 		if (filename)
1340 			(void)fprintf(cfg, "###> ");
1341 		strvis(in, line, VIS_TAB);
1342 		for (out = in; *out; out++)
1343 			switch (*out) {
1344 			case '\n':
1345 				(void)fprintf(cfg, "\\n\"\n");
1346 				missingeol = 0;
1347 				break;
1348 			case '"': case '\\':
1349 				(void)fputc('\\', cfg);
1350 				/* FALLTHROUGH */
1351 			default:
1352 				(void)fputc(*out, cfg);
1353 				break;
1354 			}
1355 	}
1356 	if (missingeol) {
1357 		(void)fprintf(cfg, "\\n\"\n");
1358 		(void)fprintf(stderr,
1359 		    "config: %s: newline missing at EOF\n",
1360 		    filename != NULL ? filename : conffile);
1361 	}
1362 	if (filename)
1363 		(void)fprintf(cfg, "\"_CFG_### (end include \\\"%s\\\")\\n\"\n",
1364 		    filename);
1365 
1366 	rewind(cf);
1367 }
1368 
1369 void
1370 logconfig_end(void)
1371 {
1372 	char line[1024];
1373 	FILE *fp;
1374 	struct stat st;
1375 
1376 	if (!cfg)
1377 		return;
1378 
1379 	(void)fprintf(cfg, "#endif /* %s */\n", LOGCONFIG_LARGE);
1380 	(void)fprintf(cfg, ";\n");
1381 	(void)fprintf(cfg, "#endif /* %s || %s */\n",
1382 	    LOGCONFIG_LARGE, LOGCONFIG_SMALL);
1383 	(void)fprintf(cfg, "#endif /* CONFIG_FILE */\n");
1384 	rewind(cfg);
1385 
1386 	if (stat("config_file.h", &st) != -1) {
1387 		if (cfgtime < st.st_mtime) {
1388 			fclose(cfg);
1389 			return;
1390 		}
1391 	}
1392 
1393 	fp = fopen("config_file.h", "w");
1394 	if(!fp) {
1395 		(void)fprintf(stderr,
1396 		    "config: cannot write to \"config_file.h\"\n");
1397 		exit(1);
1398 	}
1399 
1400 	while (fgets(line, sizeof(line), cfg) != NULL)
1401 		fputs(line, fp);
1402 	fclose(fp);
1403 	fclose(cfg);
1404 }
1405 
1406 static const char *
1407 strtolower(const char *name)
1408 {
1409 	const char *n;
1410 	char *p, low[500];
1411 	unsigned char c;
1412 
1413 	for (n = name, p = low; (c = *n) != '\0'; n++)
1414 		*p++ = isupper(c) ? tolower(c) : c;
1415 	*p = 0;
1416 	return (intern(low));
1417 }
1418 
1419 static int
1420 is_elf(const char *file)
1421 {
1422 	int kernel;
1423 	char hdr[4];
1424 
1425 	kernel = open(file, O_RDONLY);
1426 	if (kernel == -1) {
1427 		fprintf(stderr, "config: cannot open %s: %s\n", file,
1428 		    strerror(errno));
1429 		exit(2);
1430 	}
1431 	if (read(kernel, hdr, 4) == -1) {
1432 		fprintf(stderr, "config: cannot read from %s: %s\n", file,
1433 		    strerror(errno));
1434 		exit(2);
1435 	}
1436 	close(kernel);
1437 
1438 	return memcmp("\177ELF", hdr, 4) == 0 ? 1 : 0;
1439 }
1440 
1441 static int
1442 extract_config(const char *kname, const char *cname, int cfd)
1443 {
1444 	char *ptr;
1445 	int found, kfd, i;
1446 	struct stat st;
1447 
1448 	found = 0;
1449 
1450 	/* mmap(2) binary kernel */
1451 	kfd = open(conffile, O_RDONLY);
1452 	if (kfd == -1) {
1453 		fprintf(stderr, "config: cannot open %s: %s\n", kname,
1454 		    strerror(errno));
1455 		exit(2);
1456 	}
1457 	if ((fstat(kfd, &st) == -1)) {
1458 		fprintf(stderr, "config: cannot stat %s: %s\n", kname,
1459 		    strerror(errno));
1460 		exit(2);
1461 	}
1462 	ptr = (char *)mmap(0, st.st_size, PROT_READ, MAP_FILE | MAP_SHARED,
1463 	    kfd, 0);
1464 	if (ptr == MAP_FAILED) {
1465 		fprintf(stderr, "config: cannot mmap %s: %s\n", kname,
1466 		    strerror(errno));
1467 		exit(2);
1468 	}
1469 
1470 	/* Scan mmap(2)'ed region, extracting kernel configuration */
1471 	for (i = 0; i < st.st_size; i++) {
1472 		if ((*ptr == '_') && (st.st_size - i > 5) && memcmp(ptr,
1473 		    "_CFG_", 5) == 0) {
1474 			/* Line found */
1475 			char *oldptr, line[LINE_MAX + 1], uline[LINE_MAX + 1];
1476 			int j;
1477 
1478 			found = 1;
1479 
1480 			oldptr = (ptr += 5);
1481 			while (*ptr != '\n' && *ptr != '\0') ptr++;
1482 			if (ptr - oldptr > LINE_MAX) {
1483 				fprintf(stderr, "config: line too long\n");
1484 				exit(2);
1485 			}
1486 			i += ptr - oldptr + 5;
1487 			memcpy(line, oldptr, (ptr - oldptr));
1488 			line[ptr - oldptr] = '\0';
1489 			j = strunvis(uline, line);
1490 			if (j == -1) {
1491 				fprintf(stderr, "config: unvis: invalid "
1492 				    "encoded sequence\n");
1493 				exit(2);
1494 			}
1495 			uline[j] = '\n';
1496 			if (write(cfd, uline, j + 1) == -1) {
1497 				fprintf(stderr, "config: cannot write to %s: "
1498 				    "%s\n", cname, strerror(errno));
1499 				exit(2);
1500 			}
1501 		} else ptr++;
1502 	}
1503 
1504 	close(kfd);
1505 
1506 	return found;
1507 }
1508 
1509 struct dhdi_params {
1510 	struct devbase *d;
1511 	int unit;
1512 	int level;
1513 };
1514 
1515 static int
1516 devbase_has_dead_instances(const char *key, void *value, void *aux)
1517 {
1518 	struct devi *i;
1519 	struct dhdi_params *dhdi = aux;
1520 
1521 	for (i = value; i != NULL; i = i->i_alias)
1522 		if (i->i_base == dhdi->d &&
1523 		    (dhdi->unit == WILD || dhdi->unit == i->i_unit ||
1524 		     i->i_unit == STAR) &&
1525 		    i->i_level >= dhdi->level)
1526 			return 1;
1527 	return 0;
1528 }
1529 
1530 /*
1531  * This is almost the same as devbase_has_instances, except it
1532  * may have special considerations regarding ignored instances.
1533  */
1534 
1535 static int
1536 devbase_has_any_instance(struct devbase *dev, int unit, int state, int level)
1537 {
1538 	struct deva *da;
1539 	struct devi *i;
1540 
1541 	if (dev->d_ispseudo) {
1542 		if (dev->d_ihead != NULL)
1543 			return 1;
1544 		else if (state != DEVI_IGNORED)
1545 			return 0;
1546 		if ((i = ht_lookup(deaddevitab, dev->d_name)) == NULL)
1547 			return 0;
1548 		return (i->i_level >= level);
1549 	}
1550 
1551 	for (da = dev->d_ahead; da != NULL; da = da->d_bsame)
1552 		for (i = da->d_ihead; i != NULL; i = i->i_asame)
1553 			if ((i->i_active == DEVI_ACTIVE ||
1554 			     i->i_active == state) &&
1555 			    (unit == WILD || unit == i->i_unit ||
1556 			     i->i_unit == STAR))
1557 				return 1;
1558 
1559 	if (state == DEVI_IGNORED) {
1560 		struct dhdi_params dhdi = { dev, unit, level };
1561 		/* also check dead devices */
1562 		return ht_enumerate(deaddevitab, devbase_has_dead_instances,
1563 		    &dhdi);
1564 	}
1565 
1566 	return 0;
1567 }
1568 
1569 /*
1570  * check_dead_devi(), used with ht_enumerate, checks if any of the removed
1571  * device instances would have been a valid instance considering the devbase,
1572  * the parent device and the interface attribute.
1573  *
1574  * In other words, for a non-active device, it checks if children would be
1575  * actual orphans or the result of a negative statement in the config file.
1576  */
1577 
1578 struct cdd_params {
1579 	struct devbase *d;
1580 	struct attr *at;
1581 	struct devbase *parent;
1582 };
1583 
1584 static int
1585 check_dead_devi(const char *key, void *value, void *aux)
1586 {
1587 	struct cdd_params *cdd = aux;
1588 	struct devi *i = value;
1589 	struct pspec *p;
1590 
1591 	if (i->i_base != cdd->d)
1592 		return 0;
1593 
1594 	for (; i != NULL; i = i->i_alias) {
1595 		p = i->i_pspec;
1596 		if ((p == NULL && cdd->at == NULL) ||
1597 		    (p != NULL && p->p_iattr == cdd->at &&
1598 		     (p->p_atdev == NULL || p->p_atdev == cdd->parent))) {
1599 			if (p != NULL &&
1600 			    !devbase_has_any_instance(cdd->parent, p->p_atunit,
1601 			    DEVI_IGNORED, i->i_level))
1602 				return 0;
1603 			else
1604 				return 1;
1605 		}
1606 	}
1607 	return 0;
1608 }
1609 
1610 static void
1611 do_kill_orphans(struct devbase *d, struct attr *at, struct devbase *parent,
1612     int state)
1613 {
1614 	struct nvlist *nv, *nv1;
1615 	struct attr *a;
1616 	struct devi *i, *j = NULL;
1617 	struct pspec *p;
1618 	int active = 0;
1619 
1620 	/*
1621 	 * A pseudo-device will always attach at root, and if it has an
1622 	 * instance (it cannot have more than one), it is enough to consider
1623 	 * it active, as there is no real attachment.
1624 	 *
1625 	 * A pseudo device can never be marked DEVI_IGNORED.
1626 	 */
1627 	if (d->d_ispseudo) {
1628 		if (d->d_ihead != NULL)
1629 			d->d_ihead->i_active = active = DEVI_ACTIVE;
1630 		else {
1631 			if (ht_lookup(deaddevitab, d->d_name) != NULL)
1632 				active = DEVI_IGNORED;
1633 			else
1634 				return;
1635 		}
1636 	} else {
1637 		int seen = 0;
1638 
1639 		for (i = d->d_ihead; i != NULL; i = i->i_bsame) {
1640 			for (j = i; j != NULL; j = j->i_alias) {
1641 				p = j->i_pspec;
1642 				if ((p == NULL && at == NULL) ||
1643 				    (p != NULL && p->p_iattr == at &&
1644 				    (p->p_atdev == NULL ||
1645 				    p->p_atdev == parent))) {
1646 					if (p != NULL &&
1647 					    !devbase_has_any_instance(parent,
1648 					      p->p_atunit, state, j->i_level))
1649 						continue;
1650 					/*
1651 					 * There are Fry-like devices which can
1652 					 * be their own grand-parent (or even
1653 					 * parent, like uhub).  We don't want
1654 					 * to loop, so if we've already reached
1655 					 * an instance for one reason or
1656 					 * another, stop there.
1657 					 */
1658 					if (j->i_active == DEVI_ACTIVE ||
1659 					    j->i_active == state) {
1660 						/*
1661 						 * Device has already been
1662 						 * seen.  However it might
1663 						 * have siblings who still
1664 						 * have to be activated or
1665 						 * orphaned.
1666 						 */
1667 						seen = 1;
1668 						continue;
1669 					}
1670 					j->i_active = active = state;
1671 					if (p != NULL)
1672 						p->p_active = state;
1673 				}
1674 			}
1675 		}
1676 		/*
1677 		 * If we've been there but have made no change, stop.
1678 		 */
1679 		if (seen && !active)
1680 			return;
1681 		if (!active) {
1682 			struct cdd_params cdd = { d, at, parent };
1683 			/* Look for a matching dead devi */
1684 			if (ht_enumerate(deaddevitab, check_dead_devi, &cdd) &&
1685 			    d != parent)
1686 				/*
1687 				 * That device had its instances removed.
1688 				 * Continue the loop marking descendants
1689 				 * with DEVI_IGNORED instead of DEVI_ACTIVE.
1690 				 *
1691 				 * There is one special case for devices that
1692 				 * are their own parent:  if that instance is
1693 				 * removed (e.g., no uhub* at uhub?), we don't
1694 				 * have to continue looping.
1695 				 */
1696 				active = DEVI_IGNORED;
1697 			else
1698 				return;
1699 		}
1700 	}
1701 
1702 	for (nv = d->d_attrs; nv != NULL; nv = nv->nv_next) {
1703 		a = nv->nv_ptr;
1704 		for (nv1 = a->a_devs; nv1 != NULL; nv1 = nv1->nv_next)
1705 			do_kill_orphans(nv1->nv_ptr, a, d, active);
1706 	}
1707 }
1708 
1709 static int
1710 kill_orphans_cb(const char *key, void *value, void *aux)
1711 {
1712 	do_kill_orphans((struct devbase *)value, NULL, NULL, DEVI_ACTIVE);
1713 	return 0;
1714 }
1715 
1716 static void
1717 kill_orphans()
1718 {
1719 	ht_enumerate(devroottab, kill_orphans_cb, NULL);
1720 }
1721