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