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