1 /* $NetBSD: main.c,v 1.89 2015/09/04 06:01:40 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.89 2015/09/04 06:01:40 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 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 *); 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) 1086 { 1087 1088 CFGDBG(4, "deselecting opt `%s'", name); 1089 if (undo_option(opttab, &options, &nextopt, name, "options")) 1090 return; 1091 if (undo_option(selecttab, NULL, NULL, strtolower(name), "options")) 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) 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")) 1141 return; 1142 if (undo_option(selecttab, NULL, NULL, n, "file-system")) 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) 1159 { 1160 1161 CFGDBG(4, "deselecting mkopt `%s'", name); 1162 (void)undo_option(mkopttab, &mkoptions, &nextmkopt, name, 1163 "makeoptions"); 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)) 1247 panic("do_option 2"); 1248 if (stab != NULL && 1249 undo_option(stab, NULL, NULL, strtolower(name), type)) 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) 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) 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)); 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); 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