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