1*75eb07f2Suebayasi /* $NetBSD: main.c,v 1.67 2014/10/11 15:47:38 uebayasi Exp $ */ 25ecc953bSthorpej 35ecc953bSthorpej /* 45ecc953bSthorpej * Copyright (c) 1992, 1993 55ecc953bSthorpej * The Regents of the University of California. All rights reserved. 65ecc953bSthorpej * 75ecc953bSthorpej * This software was developed by the Computer Systems Engineering group 85ecc953bSthorpej * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and 95ecc953bSthorpej * contributed to Berkeley. 105ecc953bSthorpej * 115ecc953bSthorpej * All advertising materials mentioning features or use of this software 125ecc953bSthorpej * must display the following acknowledgement: 135ecc953bSthorpej * This product includes software developed by the University of 145ecc953bSthorpej * California, Lawrence Berkeley Laboratories. 155ecc953bSthorpej * 165ecc953bSthorpej * Redistribution and use in source and binary forms, with or without 175ecc953bSthorpej * modification, are permitted provided that the following conditions 185ecc953bSthorpej * are met: 195ecc953bSthorpej * 1. Redistributions of source code must retain the above copyright 205ecc953bSthorpej * notice, this list of conditions and the following disclaimer. 215ecc953bSthorpej * 2. Redistributions in binary form must reproduce the above copyright 225ecc953bSthorpej * notice, this list of conditions and the following disclaimer in the 235ecc953bSthorpej * documentation and/or other materials provided with the distribution. 245ecc953bSthorpej * 3. Neither the name of the University nor the names of its contributors 255ecc953bSthorpej * may be used to endorse or promote products derived from this software 265ecc953bSthorpej * without specific prior written permission. 275ecc953bSthorpej * 285ecc953bSthorpej * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 295ecc953bSthorpej * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 305ecc953bSthorpej * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 315ecc953bSthorpej * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 325ecc953bSthorpej * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 335ecc953bSthorpej * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 345ecc953bSthorpej * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 355ecc953bSthorpej * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 365ecc953bSthorpej * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 375ecc953bSthorpej * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 385ecc953bSthorpej * SUCH DAMAGE. 395ecc953bSthorpej * 405ecc953bSthorpej * from: @(#)main.c 8.1 (Berkeley) 6/6/93 415ecc953bSthorpej */ 425ecc953bSthorpej 435ecc953bSthorpej #if HAVE_NBTOOL_CONFIG_H 445ecc953bSthorpej #include "nbtool_config.h" 455ecc953bSthorpej #endif 465ecc953bSthorpej 475ecc953bSthorpej #ifndef MAKE_BOOTSTRAP 485ecc953bSthorpej #include <sys/cdefs.h> 495ecc953bSthorpej #define COPYRIGHT(x) __COPYRIGHT(x) 505ecc953bSthorpej #else 515ecc953bSthorpej #define COPYRIGHT(x) static const char copyright[] = x 525ecc953bSthorpej #endif 535ecc953bSthorpej 545ecc953bSthorpej #ifndef lint 5598e5374cSlukem COPYRIGHT("@(#) Copyright (c) 1992, 1993\ 5698e5374cSlukem The Regents of the University of California. All rights reserved."); 575ecc953bSthorpej #endif /* not lint */ 585ecc953bSthorpej 595ecc953bSthorpej #include <sys/types.h> 605ecc953bSthorpej #include <sys/stat.h> 615ecc953bSthorpej #include <sys/param.h> 625ecc953bSthorpej #include <sys/mman.h> 6399d2b097Schristos #if !HAVE_NBTOOL_CONFIG_H 649de19619Schristos #include <sys/sysctl.h> 659de19619Schristos #endif 665ecc953bSthorpej #include <paths.h> 675ecc953bSthorpej #include <ctype.h> 68342d3579Sdsl #include <err.h> 695ecc953bSthorpej #include <errno.h> 705ecc953bSthorpej #include <fcntl.h> 7136c1b19bSdholland #include <limits.h> 725ecc953bSthorpej #include <stdio.h> 735ecc953bSthorpej #include <stdlib.h> 745ecc953bSthorpej #include <string.h> 755ecc953bSthorpej #include <unistd.h> 76d0fb8901Schristos #include <vis.h> 77d0fb8901Schristos #include <util.h> 78d0fb8901Schristos 795ecc953bSthorpej #include "defs.h" 805ecc953bSthorpej #include "sem.h" 815ecc953bSthorpej 825ecc953bSthorpej #ifndef LINE_MAX 835ecc953bSthorpej #define LINE_MAX 1024 845ecc953bSthorpej #endif 855ecc953bSthorpej 865ecc953bSthorpej int vflag; /* verbose output */ 875ecc953bSthorpej int Pflag; /* pack locators */ 8859c94545Scube int Lflag; /* lint config generation */ 89d2737476Smartin int handling_cmdlineopts; /* currently processing -D/-U options */ 905ecc953bSthorpej 915ecc953bSthorpej int yyparse(void); 925ecc953bSthorpej 935ecc953bSthorpej #ifndef MAKE_BOOTSTRAP 945ecc953bSthorpej extern int yydebug; 955ecc953bSthorpej #endif 965a918911Suebayasi int dflag; 975ecc953bSthorpej 98d74eb995Sdholland static struct dlhash *obsopttab; 995ecc953bSthorpej static struct hashtab *mkopttab; 1005ecc953bSthorpej static struct nvlist **nextopt; 1015ecc953bSthorpej static struct nvlist **nextmkopt; 1025ecc953bSthorpej static struct nvlist **nextappmkopt; 103a16a6365Scube static struct nvlist **nextcndmkopt; 1045ecc953bSthorpej static struct nvlist **nextfsopt; 105d2737476Smartin static struct nvlist *cmdlinedefs, *cmdlineundefs; 1065ecc953bSthorpej 1078b0f9554Sperry static void usage(void) __dead; 1085ecc953bSthorpej static void dependopts(void); 109d74eb995Sdholland static void dependopts_one(const char *); 110d74eb995Sdholland static void do_depends(struct nvlist *); 1115ecc953bSthorpej static void do_depend(struct nvlist *); 1125ecc953bSthorpej static void stop(void); 1135ecc953bSthorpej static int do_option(struct hashtab *, struct nvlist ***, 1145ecc953bSthorpej const char *, const char *, const char *); 1155ecc953bSthorpej static int undo_option(struct hashtab *, struct nvlist **, 1165ecc953bSthorpej struct nvlist ***, const char *, const char *); 1175ecc953bSthorpej static int crosscheck(void); 1185ecc953bSthorpej static int badstar(void); 1195ecc953bSthorpej int main(int, char **); 1205ecc953bSthorpej static int mksymlinks(void); 1215ecc953bSthorpej static int mkident(void); 1227aa6070dScube static int devbase_has_dead_instances(const char *, void *, void *); 123a31ff6b4Scube static int devbase_has_any_instance(struct devbase *, int, int, int); 1247aa6070dScube static int check_dead_devi(const char *, void *, void *); 125d2737476Smartin static void add_makeopt(const char *); 126d2737476Smartin static void remove_makeopt(const char *); 127d2737476Smartin static void handle_cmdline_makeoptions(void); 128c130d400Scube static void kill_orphans(void); 1297aa6070dScube static void do_kill_orphans(struct devbase *, struct attr *, 1307aa6070dScube struct devbase *, int); 131c130d400Scube static int kill_orphans_cb(const char *, void *, void *); 1325ecc953bSthorpej static int cfcrosscheck(struct config *, const char *, struct nvlist *); 133d74eb995Sdholland static void defopt(struct dlhash *ht, const char *fname, 134d74eb995Sdholland struct defoptlist *opts, struct nvlist *deps, int obs); 135d74eb995Sdholland static struct defoptlist *find_declared_option_option(const char *name); 136d74eb995Sdholland static struct nvlist *find_declared_fs_option(const char *name); 1375ecc953bSthorpej 1385ecc953bSthorpej #define LOGCONFIG_LARGE "INCLUDE_CONFIG_FILE" 1395ecc953bSthorpej #define LOGCONFIG_SMALL "INCLUDE_JUST_CONFIG" 1405ecc953bSthorpej 1415ecc953bSthorpej static void logconfig_start(void); 1425ecc953bSthorpej static void logconfig_end(void); 1435ecc953bSthorpej static FILE *cfg; 1445ecc953bSthorpej static time_t cfgtime; 1455ecc953bSthorpej 1465ecc953bSthorpej static int is_elf(const char *); 1475ecc953bSthorpej static int extract_config(const char *, const char *, int); 1485ecc953bSthorpej 1495ecc953bSthorpej int badfilename(const char *fname); 1505ecc953bSthorpej 1515ecc953bSthorpej const char *progname; 15244e453f5Suebayasi extern const char *yyfile; 1535ecc953bSthorpej 1545ecc953bSthorpej int 1555ecc953bSthorpej main(int argc, char **argv) 1565ecc953bSthorpej { 15736c1b19bSdholland char *p, cname[PATH_MAX]; 1585ecc953bSthorpej const char *last_component; 1595ecc953bSthorpej int pflag, xflag, ch, removeit; 1605ecc953bSthorpej 1615ecc953bSthorpej setprogname(argv[0]); 1625ecc953bSthorpej 1635ecc953bSthorpej pflag = 0; 1645ecc953bSthorpej xflag = 0; 1655f8cf5aeSuebayasi while ((ch = getopt(argc, argv, "D:LMPU:dgpvb:s:x")) != -1) { 1665ecc953bSthorpej switch (ch) { 1675ecc953bSthorpej 168d2737476Smartin case 'd': 1695a918911Suebayasi #ifndef MAKE_BOOTSTRAP 1705ecc953bSthorpej yydebug = 1; 1715a918911Suebayasi #endif 172d3809db7Suebayasi dflag++; 1735ecc953bSthorpej break; 1745ecc953bSthorpej 1755f8cf5aeSuebayasi case 'M': 1765f8cf5aeSuebayasi usekobjs = 1; 1775f8cf5aeSuebayasi break; 1785f8cf5aeSuebayasi 17959c94545Scube case 'L': 18059c94545Scube Lflag = 1; 18159c94545Scube break; 18259c94545Scube 1835ecc953bSthorpej case 'P': 1845ecc953bSthorpej Pflag = 1; 1855ecc953bSthorpej break; 1865ecc953bSthorpej 1875ecc953bSthorpej case 'g': 1885ecc953bSthorpej /* 1895ecc953bSthorpej * In addition to DEBUG, you probably wanted to 1905ecc953bSthorpej * set "options KGDB" and maybe others. We could 1915ecc953bSthorpej * do that for you, but you really should just 1925ecc953bSthorpej * put them in the config file. 1935ecc953bSthorpej */ 194d2737476Smartin warnx("-g is obsolete (use -D DEBUG=\"-g\")"); 1955ecc953bSthorpej usage(); 196c7295a4cSchristos /*NOTREACHED*/ 1975ecc953bSthorpej 1985ecc953bSthorpej case 'p': 1995ecc953bSthorpej /* 2005ecc953bSthorpej * Essentially the same as makeoptions PROF="-pg", 2015ecc953bSthorpej * but also changes the path from ../../compile/FOO 2025ecc953bSthorpej * to ../../compile/FOO.PROF; i.e., compile a 2035ecc953bSthorpej * profiling kernel based on a typical "regular" 2045ecc953bSthorpej * kernel. 2055ecc953bSthorpej * 2065ecc953bSthorpej * Note that if you always want profiling, you 2075ecc953bSthorpej * can (and should) use a "makeoptions" line. 2085ecc953bSthorpej */ 2095ecc953bSthorpej pflag = 1; 2105ecc953bSthorpej break; 2115ecc953bSthorpej 2125ecc953bSthorpej case 'v': 2135ecc953bSthorpej vflag = 1; 2145ecc953bSthorpej break; 2155ecc953bSthorpej 2165ecc953bSthorpej case 'b': 2175ecc953bSthorpej builddir = optarg; 2185ecc953bSthorpej break; 2195ecc953bSthorpej 2205ecc953bSthorpej case 's': 2215ecc953bSthorpej srcdir = optarg; 2225ecc953bSthorpej break; 2235ecc953bSthorpej 2245ecc953bSthorpej case 'x': 2255ecc953bSthorpej xflag = 1; 2265ecc953bSthorpej break; 2275ecc953bSthorpej 228d2737476Smartin case 'D': 229d2737476Smartin add_makeopt(optarg); 230d2737476Smartin break; 231d2737476Smartin 232d2737476Smartin case 'U': 233d2737476Smartin remove_makeopt(optarg); 234d2737476Smartin break; 235d2737476Smartin 2365ecc953bSthorpej case '?': 2375ecc953bSthorpej default: 2385ecc953bSthorpej usage(); 2395ecc953bSthorpej } 2405ecc953bSthorpej } 2415ecc953bSthorpej 2427547791dSpooka if (xflag && optind != 2) { 243e239742fSpooka errx(EXIT_FAILURE, "-x must be used alone"); 244e239742fSpooka } 245e239742fSpooka 2465ecc953bSthorpej argc -= optind; 2475ecc953bSthorpej argv += optind; 2485ecc953bSthorpej if (argc > 1) { 2495ecc953bSthorpej usage(); 2505ecc953bSthorpej } 2515ecc953bSthorpej 252c7295a4cSchristos if (Lflag && (builddir != NULL || Pflag || pflag)) 253c7295a4cSchristos errx(EXIT_FAILURE, "-L can only be used with -s and -v"); 2545ecc953bSthorpej 2555ecc953bSthorpej if (xflag) { 2569de19619Schristos if (argc == 0) { 25799d2b097Schristos #if !HAVE_NBTOOL_CONFIG_H 2589de19619Schristos char path_unix[MAXPATHLEN]; 2599de19619Schristos size_t len = sizeof(path_unix) - 1; 2609de19619Schristos path_unix[0] = '/'; 2619de19619Schristos 2629de19619Schristos conffile = sysctlbyname("machdep.booted_kernel", 2639de19619Schristos &path_unix[1], &len, NULL, 0) == -1 ? _PATH_UNIX : 2649de19619Schristos path_unix; 2655ecc953bSthorpej #else 266c7295a4cSchristos errx(EXIT_FAILURE, "no kernel supplied"); 2675ecc953bSthorpej #endif 2689de19619Schristos } else 2699de19619Schristos conffile = argv[0]; 270c7295a4cSchristos if (!is_elf(conffile)) 271c7295a4cSchristos errx(EXIT_FAILURE, "%s: not a binary kernel", 2725ecc953bSthorpej conffile); 273c7295a4cSchristos if (!extract_config(conffile, "stdout", STDOUT_FILENO)) 274c7295a4cSchristos errx(EXIT_FAILURE, "%s does not contain embedded " 275c7295a4cSchristos "configuration data", conffile); 2765ecc953bSthorpej exit(0); 2775ecc953bSthorpej } 2785ecc953bSthorpej 2795ecc953bSthorpej conffile = (argc == 1) ? argv[0] : "CONFIG"; 2805ecc953bSthorpej if (firstfile(conffile)) { 281c7295a4cSchristos err(EXIT_FAILURE, "Cannot read `%s'", conffile); 2825ecc953bSthorpej exit(2); 2835ecc953bSthorpej } 2845ecc953bSthorpej 2855ecc953bSthorpej /* 2865ecc953bSthorpej * Init variables. 2875ecc953bSthorpej */ 2885ecc953bSthorpej minmaxusers = 1; 2895ecc953bSthorpej maxmaxusers = 10000; 2905ecc953bSthorpej initintern(); 2915ecc953bSthorpej ident = NULL; 2925ecc953bSthorpej devbasetab = ht_new(); 293c130d400Scube devroottab = ht_new(); 2945ecc953bSthorpej devatab = ht_new(); 2955ecc953bSthorpej devitab = ht_new(); 2967aa6070dScube deaddevitab = ht_new(); 2975ecc953bSthorpej selecttab = ht_new(); 2985ecc953bSthorpej needcnttab = ht_new(); 2995ecc953bSthorpej opttab = ht_new(); 3005ecc953bSthorpej mkopttab = ht_new(); 3015ecc953bSthorpej fsopttab = ht_new(); 30202245173Sdholland deffstab = nvhash_create(); 303d74eb995Sdholland defopttab = dlhash_create(); 304d74eb995Sdholland defparamtab = dlhash_create(); 305d74eb995Sdholland defoptlint = dlhash_create(); 306d74eb995Sdholland defflagtab = dlhash_create(); 307d74eb995Sdholland optfiletab = dlhash_create(); 308d74eb995Sdholland obsopttab = dlhash_create(); 3095ecc953bSthorpej bdevmtab = ht_new(); 3105ecc953bSthorpej maxbdevm = 0; 3115ecc953bSthorpej cdevmtab = ht_new(); 3125ecc953bSthorpej maxcdevm = 0; 3135ecc953bSthorpej nextopt = &options; 3145ecc953bSthorpej nextmkopt = &mkoptions; 3155ecc953bSthorpej nextappmkopt = &appmkoptions; 3161894a7d2Scube nextcndmkopt = &condmkoptions; 3175ecc953bSthorpej nextfsopt = &fsoptions; 318cd06fea3Suebayasi initfiles(); 319cd06fea3Suebayasi initsem(); 3205ecc953bSthorpej 3215ecc953bSthorpej /* 3225ecc953bSthorpej * Handle profiling (must do this before we try to create any 3235ecc953bSthorpej * files). 3245ecc953bSthorpej */ 3255ecc953bSthorpej last_component = strrchr(conffile, '/'); 3265ecc953bSthorpej last_component = (last_component) ? last_component + 1 : conffile; 3275ecc953bSthorpej if (pflag) { 3285ecc953bSthorpej p = emalloc(strlen(last_component) + 17); 3295ecc953bSthorpej (void)sprintf(p, "../compile/%s.PROF", last_component); 3305ecc953bSthorpej (void)addmkoption(intern("PROF"), "-pg"); 3315ecc953bSthorpej (void)addoption(intern("GPROF"), NULL); 3325ecc953bSthorpej } else { 3335ecc953bSthorpej p = emalloc(strlen(last_component) + 13); 3345ecc953bSthorpej (void)sprintf(p, "../compile/%s", last_component); 3355ecc953bSthorpej } 3365ecc953bSthorpej defbuilddir = (argc == 0) ? "." : p; 3375ecc953bSthorpej 33859c94545Scube if (Lflag) { 33959c94545Scube char resolvedname[MAXPATHLEN]; 34059c94545Scube 34159c94545Scube if (realpath(conffile, resolvedname) == NULL) 34259c94545Scube err(EXIT_FAILURE, "realpath(%s)", conffile); 34359c94545Scube 34459c94545Scube if (yyparse()) 34559c94545Scube stop(); 34659c94545Scube 347aa3d0249Scube printf("include \"%s\"\n", resolvedname); 34859c94545Scube 34959c94545Scube emit_params(); 35059c94545Scube emit_options(); 35159c94545Scube emit_instances(); 35259c94545Scube 35359c94545Scube exit(EXIT_SUCCESS); 35459c94545Scube } 35559c94545Scube 3565ecc953bSthorpej removeit = 0; 3575ecc953bSthorpej if (is_elf(conffile)) { 3585ecc953bSthorpej const char *tmpdir; 3595ecc953bSthorpej int cfd; 3605ecc953bSthorpej 361c7295a4cSchristos if (builddir == NULL) 362c7295a4cSchristos errx(EXIT_FAILURE, "Build directory must be specified " 363c7295a4cSchristos "with binary kernels"); 3645ecc953bSthorpej 3655ecc953bSthorpej /* Open temporary configuration file */ 3665ecc953bSthorpej tmpdir = getenv("TMPDIR"); 3675ecc953bSthorpej if (tmpdir == NULL) 36836c1b19bSdholland tmpdir = _PATH_TMP; 3695ecc953bSthorpej snprintf(cname, sizeof(cname), "%s/config.tmp.XXXXXX", tmpdir); 3705ecc953bSthorpej cfd = mkstemp(cname); 371c7295a4cSchristos if (cfd == -1) 372c7295a4cSchristos err(EXIT_FAILURE, "Cannot create `%s'", cname); 3735ecc953bSthorpej 3745ecc953bSthorpej printf("Using configuration data embedded in kernel...\n"); 37536c1b19bSdholland if (!extract_config(conffile, cname, cfd)) { 37636c1b19bSdholland unlink(cname); 377c7295a4cSchristos errx(EXIT_FAILURE, "%s does not contain embedded " 378c7295a4cSchristos "configuration data", conffile); 37936c1b19bSdholland } 3805ecc953bSthorpej 3815ecc953bSthorpej removeit = 1; 3825ecc953bSthorpej close(cfd); 3835ecc953bSthorpej firstfile(cname); 3845ecc953bSthorpej } 3855ecc953bSthorpej 3865ecc953bSthorpej /* 387e239742fSpooka * Log config file. We don't know until yyparse() if we're 388e239742fSpooka * going to need config_file.h (i.e. if we're doing ioconf-only 389e239742fSpooka * or not). Just start creating the file, and when we know 390e239742fSpooka * later, we'll just keep or discard our work here. 3915ecc953bSthorpej */ 3925ecc953bSthorpej logconfig_start(); 393e239742fSpooka 394e239742fSpooka /* 395e239742fSpooka * Parse config file (including machine definitions). 396e239742fSpooka */ 3975ecc953bSthorpej if (yyparse()) 3985ecc953bSthorpej stop(); 399e239742fSpooka 400e239742fSpooka if (ioconfname && cfg) 401e239742fSpooka fclose(cfg); 402e239742fSpooka else 4035ecc953bSthorpej logconfig_end(); 4045ecc953bSthorpej 4055ecc953bSthorpej if (removeit) 4065ecc953bSthorpej unlink(cname); 4075ecc953bSthorpej 4085ecc953bSthorpej /* 409d2737476Smartin * Handle command line overrides 410d2737476Smartin */ 41144e453f5Suebayasi yyfile = "handle_cmdline_makeoptions"; 412d2737476Smartin handle_cmdline_makeoptions(); 413d2737476Smartin 414d2737476Smartin /* 415c130d400Scube * Detect and properly ignore orphaned devices 416c130d400Scube */ 41744e453f5Suebayasi yyfile = "kill_orphans"; 418c130d400Scube kill_orphans(); 419c130d400Scube 420c130d400Scube /* 4215ecc953bSthorpej * Select devices and pseudo devices and their attributes 4225ecc953bSthorpej */ 42344e453f5Suebayasi yyfile = "fixdevis"; 4247aa6070dScube if (fixdevis()) 4257aa6070dScube stop(); 4265ecc953bSthorpej 4275ecc953bSthorpej /* 428e239742fSpooka * If working on an ioconf-only config, process here and exit 429e239742fSpooka */ 430e239742fSpooka if (ioconfname) { 43144e453f5Suebayasi yyfile = "pack"; 432e239742fSpooka pack(); 43344e453f5Suebayasi yyfile = "mkioconf"; 434e239742fSpooka mkioconf(); 43544e453f5Suebayasi yyfile = "emitlocs"; 436e239742fSpooka emitlocs(); 43744e453f5Suebayasi yyfile = "emitioconfh"; 438d0e5d937Spooka emitioconfh(); 439e239742fSpooka return 0; 440e239742fSpooka } 441e239742fSpooka 442e239742fSpooka /* 4435ecc953bSthorpej * Deal with option dependencies. 4445ecc953bSthorpej */ 44544e453f5Suebayasi yyfile = "dependopts"; 4465ecc953bSthorpej dependopts(); 4475ecc953bSthorpej 4485ecc953bSthorpej /* 4495ecc953bSthorpej * Fix (as in `set firmly in place') files. 4505ecc953bSthorpej */ 45144e453f5Suebayasi yyfile = "fixfiles"; 4525ecc953bSthorpej if (fixfiles()) 4535ecc953bSthorpej stop(); 4545ecc953bSthorpej 4555ecc953bSthorpej /* 4565ecc953bSthorpej * Fix objects and libraries. 4575ecc953bSthorpej */ 45844e453f5Suebayasi yyfile = "fixobjects"; 4595ecc953bSthorpej if (fixobjects()) 4605ecc953bSthorpej stop(); 4615ecc953bSthorpej 4625ecc953bSthorpej /* 4635ecc953bSthorpej * Fix device-majors. 4645ecc953bSthorpej */ 46544e453f5Suebayasi yyfile = "fixdevsw"; 4665ecc953bSthorpej if (fixdevsw()) 4675ecc953bSthorpej stop(); 4685ecc953bSthorpej 4695ecc953bSthorpej /* 4705ecc953bSthorpej * Perform cross-checking. 4715ecc953bSthorpej */ 4725ecc953bSthorpej if (maxusers == 0) { 4735ecc953bSthorpej if (defmaxusers) { 4745ecc953bSthorpej (void)printf("maxusers not specified; %d assumed\n", 4755ecc953bSthorpej defmaxusers); 4765ecc953bSthorpej maxusers = defmaxusers; 4775ecc953bSthorpej } else { 478c7295a4cSchristos warnx("need \"maxusers\" line"); 4795ecc953bSthorpej errors++; 4805ecc953bSthorpej } 4815ecc953bSthorpej } 4825ecc953bSthorpej if (crosscheck() || errors) 4835ecc953bSthorpej stop(); 4845ecc953bSthorpej 4855ecc953bSthorpej /* 4865ecc953bSthorpej * Squeeze things down and finish cross-checks (STAR checks must 4875ecc953bSthorpej * run after packing). 4885ecc953bSthorpej */ 48944e453f5Suebayasi yyfile = "pack"; 4905ecc953bSthorpej pack(); 49144e453f5Suebayasi yyfile = "badstar"; 4925ecc953bSthorpej if (badstar()) 4935ecc953bSthorpej stop(); 4945ecc953bSthorpej 49544e453f5Suebayasi yyfile = NULL; 4965ecc953bSthorpej /* 4975ecc953bSthorpej * Ready to go. Build all the various files. 4985ecc953bSthorpej */ 4995ecc953bSthorpej if (mksymlinks() || mkmakefile() || mkheaders() || mkswap() || 5000367057bScube mkioconf() || (do_devsw ? mkdevsw() : 0) || mkident() || errors) 5015ecc953bSthorpej stop(); 5025ecc953bSthorpej (void)printf("Build directory is %s\n", builddir); 5035ecc953bSthorpej (void)printf("Don't forget to run \"make depend\"\n"); 504c7295a4cSchristos return 0; 5055ecc953bSthorpej } 5065ecc953bSthorpej 5075ecc953bSthorpej static void 5085ecc953bSthorpej usage(void) 5095ecc953bSthorpej { 5108566a894Swiz (void)fprintf(stderr, "Usage: %s [-Ppv] [-b builddir] [-D var=value] " 5118566a894Swiz "[-s srcdir] [-U var] " 512c7295a4cSchristos "[config-file]\n\t%s -x [kernel-file]\n" 513c7295a4cSchristos "\t%s -L [-v] [-s srcdir] [config-file]\n", 514c7295a4cSchristos getprogname(), getprogname(), getprogname()); 5155ecc953bSthorpej exit(1); 5165ecc953bSthorpej } 5175ecc953bSthorpej 5185ecc953bSthorpej /* 5195ecc953bSthorpej * Set any options that are implied by other options. 5205ecc953bSthorpej */ 5215ecc953bSthorpej static void 5225ecc953bSthorpej dependopts(void) 5235ecc953bSthorpej { 524d74eb995Sdholland struct nvlist *nv; 5255ecc953bSthorpej 5265ecc953bSthorpej for (nv = options; nv != NULL; nv = nv->nv_next) { 527d74eb995Sdholland dependopts_one(nv->nv_name); 5285ecc953bSthorpej } 5294a82747aSmatt 5304a82747aSmatt for (nv = fsoptions; nv != NULL; nv = nv->nv_next) { 531d74eb995Sdholland dependopts_one(nv->nv_name); 532d74eb995Sdholland } 533d74eb995Sdholland } 534d74eb995Sdholland 535d74eb995Sdholland static void 536d74eb995Sdholland dependopts_one(const char *name) 537d74eb995Sdholland { 538d74eb995Sdholland struct defoptlist *dl; 539d74eb995Sdholland struct nvlist *fs; 540d74eb995Sdholland 541d74eb995Sdholland dl = find_declared_option_option(name); 542d74eb995Sdholland if (dl != NULL) { 543d74eb995Sdholland do_depends(dl->dl_depends); 544d74eb995Sdholland } 545d74eb995Sdholland fs = find_declared_fs_option(name); 546d74eb995Sdholland if (fs != NULL) { 547d74eb995Sdholland do_depends(fs->nv_ptr); 548d74eb995Sdholland } 549bd5b1cb6Suebayasi 550bd5b1cb6Suebayasi CFGDBG(3, "depend `%s' searched", name); 551d74eb995Sdholland } 552d74eb995Sdholland 553d74eb995Sdholland static void 554d74eb995Sdholland do_depends(struct nvlist *nv) 555d74eb995Sdholland { 556d74eb995Sdholland struct nvlist *opt; 557d74eb995Sdholland 558d74eb995Sdholland for (opt = nv; opt != NULL; opt = opt->nv_next) { 5594a82747aSmatt do_depend(opt); 5604a82747aSmatt } 5614a82747aSmatt } 5625ecc953bSthorpej 5635ecc953bSthorpej static void 5645ecc953bSthorpej do_depend(struct nvlist *nv) 5655ecc953bSthorpej { 5665ecc953bSthorpej struct attr *a; 5675ecc953bSthorpej 5685ecc953bSthorpej if (nv != NULL && (nv->nv_flags & NV_DEPENDED) == 0) { 5695ecc953bSthorpej nv->nv_flags |= NV_DEPENDED; 5705ecc953bSthorpej /* 5715ecc953bSthorpej * If the dependency is an attribute, then just add 5725ecc953bSthorpej * it to the selecttab. 5735ecc953bSthorpej */ 574bd5b1cb6Suebayasi CFGDBG(3, "depend attr `%s'", nv->nv_name); 5755ecc953bSthorpej if ((a = ht_lookup(attrtab, nv->nv_name)) != NULL) { 5765ecc953bSthorpej if (a->a_iattr) 5775ecc953bSthorpej panic("do_depend(%s): dep `%s' is an iattr", 5785ecc953bSthorpej nv->nv_name, a->a_name); 5795ecc953bSthorpej expandattr(a, selectattr); 5805ecc953bSthorpej } else { 5815ecc953bSthorpej if (ht_lookup(opttab, nv->nv_name) == NULL) 5825ecc953bSthorpej addoption(nv->nv_name, NULL); 583d74eb995Sdholland dependopts_one(nv->nv_name); 5845ecc953bSthorpej } 5855ecc953bSthorpej } 5865ecc953bSthorpej } 5875ecc953bSthorpej 588c7295a4cSchristos static int 589c7295a4cSchristos recreate(const char *p, const char *q) 590c7295a4cSchristos { 591c7295a4cSchristos int ret; 592c7295a4cSchristos 593c7295a4cSchristos if ((ret = unlink(q)) == -1 && errno != ENOENT) 594c7295a4cSchristos warn("unlink(%s)\n", q); 595c7295a4cSchristos if ((ret = symlink(p, q)) == -1) 596c7295a4cSchristos warn("symlink(%s -> %s)", q, p); 597c7295a4cSchristos return ret; 598c7295a4cSchristos } 599c7295a4cSchristos 6005ecc953bSthorpej /* 6015ecc953bSthorpej * Make a symlink for "machine" so that "#include <machine/foo.h>" works, 6025ecc953bSthorpej * and for the machine's CPU architecture, so that works as well. 6035ecc953bSthorpej */ 6045ecc953bSthorpej static int 6055ecc953bSthorpej mksymlinks(void) 6065ecc953bSthorpej { 6075ecc953bSthorpej int ret; 6085ecc953bSthorpej char *p, buf[MAXPATHLEN]; 6095ecc953bSthorpej const char *q; 6105ecc953bSthorpej struct nvlist *nv; 6115ecc953bSthorpej 6125ecc953bSthorpej snprintf(buf, sizeof(buf), "arch/%s/include", machine); 6135ecc953bSthorpej p = sourcepath(buf); 614c7295a4cSchristos ret = recreate(p, "machine"); 615cfbe3a4fSmatt ret = recreate(p, machine); 6165ecc953bSthorpej free(p); 6175ecc953bSthorpej 6185ecc953bSthorpej if (machinearch != NULL) { 6195ecc953bSthorpej snprintf(buf, sizeof(buf), "arch/%s/include", machinearch); 6205ecc953bSthorpej p = sourcepath(buf); 6215ecc953bSthorpej q = machinearch; 6225ecc953bSthorpej } else { 6235ecc953bSthorpej p = estrdup("machine"); 6245ecc953bSthorpej q = machine; 6255ecc953bSthorpej } 626c7295a4cSchristos 627c7295a4cSchristos ret = recreate(p, q); 6285ecc953bSthorpej free(p); 6295ecc953bSthorpej 6305ecc953bSthorpej for (nv = machinesubarches; nv != NULL; nv = nv->nv_next) { 6315ecc953bSthorpej q = nv->nv_name; 6325ecc953bSthorpej snprintf(buf, sizeof(buf), "arch/%s/include", q); 6335ecc953bSthorpej p = sourcepath(buf); 634c7295a4cSchristos ret = recreate(p, q); 6355ecc953bSthorpej free(p); 6365ecc953bSthorpej } 6375ecc953bSthorpej 6385ecc953bSthorpej return (ret); 6395ecc953bSthorpej } 6405ecc953bSthorpej 6415ecc953bSthorpej static __dead void 6425ecc953bSthorpej stop(void) 6435ecc953bSthorpej { 6445ecc953bSthorpej (void)fprintf(stderr, "*** Stop.\n"); 6455ecc953bSthorpej exit(1); 6465ecc953bSthorpej } 6475ecc953bSthorpej 6484a82747aSmatt static void 649d74eb995Sdholland check_dependencies(const char *thing, struct nvlist *deps) 6504a82747aSmatt { 6514a82747aSmatt struct nvlist *dep; 6524a82747aSmatt struct attr *a; 6534a82747aSmatt 6544a82747aSmatt for (dep = deps; dep != NULL; dep = dep->nv_next) { 6554a82747aSmatt /* 6564a82747aSmatt * If the dependency is an attribute, it must not 6574a82747aSmatt * be an interface attribute. Otherwise, it must 6584a82747aSmatt * be a previously declared option. 6594a82747aSmatt */ 6604a82747aSmatt if ((a = ht_lookup(attrtab, dep->nv_name)) != NULL) { 6614a82747aSmatt if (a->a_iattr) 662c7295a4cSchristos cfgerror("option `%s' dependency `%s' " 6634a82747aSmatt "is an interface attribute", 664d74eb995Sdholland thing, a->a_name); 6654a82747aSmatt } else if (OPT_OBSOLETE(dep->nv_name)) { 666c7295a4cSchristos cfgerror("option `%s' dependency `%s' " 667d74eb995Sdholland "is obsolete", thing, dep->nv_name); 668d74eb995Sdholland } else if (!is_declared_option(dep->nv_name)) { 669c7295a4cSchristos cfgerror("option `%s' dependency `%s' " 6704a82747aSmatt "is an unknown option", 671d74eb995Sdholland thing, dep->nv_name); 6724a82747aSmatt } 6734a82747aSmatt } 6744a82747aSmatt } 6754a82747aSmatt 676d74eb995Sdholland static void 677d74eb995Sdholland add_fs_dependencies(struct nvlist *nv, struct nvlist *deps) 678d74eb995Sdholland { 679d74eb995Sdholland /* Use nv_ptr to link any other options that are implied. */ 680d74eb995Sdholland nv->nv_ptr = deps; 681d74eb995Sdholland check_dependencies(nv->nv_name, deps); 682d74eb995Sdholland } 683d74eb995Sdholland 684d74eb995Sdholland static void 685d74eb995Sdholland add_opt_dependencies(struct defoptlist *dl, struct nvlist *deps) 686d74eb995Sdholland { 687d74eb995Sdholland dl->dl_depends = deps; 688d74eb995Sdholland check_dependencies(dl->dl_name, deps); 689d74eb995Sdholland } 690d74eb995Sdholland 6915ecc953bSthorpej /* 692e6e6744fSpooka * Define one or more file systems. 6935ecc953bSthorpej */ 6945ecc953bSthorpej void 695c9607065Spooka deffilesystem(struct nvlist *fses, struct nvlist *deps) 6965ecc953bSthorpej { 6975ecc953bSthorpej struct nvlist *nv; 6985ecc953bSthorpej 6995ecc953bSthorpej /* 7005ecc953bSthorpej * Mark these options as ones to skip when creating the Makefile. 7015ecc953bSthorpej */ 7025ecc953bSthorpej for (nv = fses; nv != NULL; nv = nv->nv_next) { 703c93963e6Scube if (DEFINED_OPTION(nv->nv_name)) { 704c7295a4cSchristos cfgerror("file system or option `%s' already defined", 7055ecc953bSthorpej nv->nv_name); 7065ecc953bSthorpej return; 7075ecc953bSthorpej } 7085ecc953bSthorpej 7095ecc953bSthorpej /* 7105ecc953bSthorpej * Also mark it as a valid file system, which may be 7115ecc953bSthorpej * used in "file-system" directives in the config 7125ecc953bSthorpej * file. 7135ecc953bSthorpej */ 71402245173Sdholland if (nvhash_insert(deffstab, nv->nv_name, nv)) 7155ecc953bSthorpej panic("file system `%s' already in table?!", 7165ecc953bSthorpej nv->nv_name); 7175ecc953bSthorpej 718d74eb995Sdholland add_fs_dependencies(nv, deps); 719a5a68b71Suebayasi 720a5a68b71Suebayasi /* 721a5a68b71Suebayasi * Implicit attribute definition for filesystem. 722a5a68b71Suebayasi */ 723a5a68b71Suebayasi const char *n; 724a5a68b71Suebayasi n = strtolower(nv->nv_name); 725a5a68b71Suebayasi refattr(n); 7265ecc953bSthorpej } 7275ecc953bSthorpej } 7285ecc953bSthorpej 7295ecc953bSthorpej /* 7305ecc953bSthorpej * Sanity check a file name. 7315ecc953bSthorpej */ 7325ecc953bSthorpej int 7335ecc953bSthorpej badfilename(const char *fname) 7345ecc953bSthorpej { 7355ecc953bSthorpej const char *n; 7365ecc953bSthorpej 7375ecc953bSthorpej /* 7385ecc953bSthorpej * We're putting multiple options into one file. Sanity 7395ecc953bSthorpej * check the file name. 7405ecc953bSthorpej */ 7415ecc953bSthorpej if (strchr(fname, '/') != NULL) { 742c7295a4cSchristos cfgerror("option file name contains a `/'"); 7435ecc953bSthorpej return 1; 7445ecc953bSthorpej } 7455ecc953bSthorpej if ((n = strrchr(fname, '.')) == NULL || strcmp(n, ".h") != 0) { 746c7295a4cSchristos cfgerror("option file name does not end in `.h'"); 7475ecc953bSthorpej return 1; 7485ecc953bSthorpej } 7495ecc953bSthorpej return 0; 7505ecc953bSthorpej } 7515ecc953bSthorpej 7525ecc953bSthorpej 7535ecc953bSthorpej /* 7545ecc953bSthorpej * Search for a defined option (defopt, filesystem, etc), and if found, 7555ecc953bSthorpej * return the option's struct nvlist. 756d74eb995Sdholland * 757d74eb995Sdholland * This used to be one function (find_declared_option) before options 758d74eb995Sdholland * and filesystems became different types. 7595ecc953bSthorpej */ 760d74eb995Sdholland static struct defoptlist * 761d74eb995Sdholland find_declared_option_option(const char *name) 7625ecc953bSthorpej { 763d74eb995Sdholland struct defoptlist *option; 7645ecc953bSthorpej 765d74eb995Sdholland if ((option = dlhash_lookup(defopttab, name)) != NULL || 766d74eb995Sdholland (option = dlhash_lookup(defparamtab, name)) != NULL || 767d74eb995Sdholland (option = dlhash_lookup(defflagtab, name)) != NULL) { 7685ecc953bSthorpej return (option); 7695ecc953bSthorpej } 7705ecc953bSthorpej 7715ecc953bSthorpej return (NULL); 7725ecc953bSthorpej } 7735ecc953bSthorpej 774d74eb995Sdholland static struct nvlist * 775d74eb995Sdholland find_declared_fs_option(const char *name) 776d74eb995Sdholland { 777d74eb995Sdholland struct nvlist *fs; 778d74eb995Sdholland 779d74eb995Sdholland if ((fs = nvhash_lookup(deffstab, name)) != NULL) { 780d74eb995Sdholland return fs; 781d74eb995Sdholland } 782d74eb995Sdholland 783d74eb995Sdholland return (NULL); 784d74eb995Sdholland } 785d74eb995Sdholland 786d74eb995Sdholland /* 787d74eb995Sdholland * Like find_declared_option but doesn't return what it finds, so it 788d74eb995Sdholland * can search both the various kinds of options and also filesystems. 789d74eb995Sdholland */ 790d74eb995Sdholland int 791d74eb995Sdholland is_declared_option(const char *name) 792d74eb995Sdholland { 793d74eb995Sdholland struct defoptlist *option = NULL; 794d74eb995Sdholland struct nvlist *fs; 795d74eb995Sdholland 796d74eb995Sdholland if ((option = dlhash_lookup(defopttab, name)) != NULL || 797d74eb995Sdholland (option = dlhash_lookup(defparamtab, name)) != NULL || 798d74eb995Sdholland (option = dlhash_lookup(defflagtab, name)) != NULL) { 799d74eb995Sdholland return 1; 800d74eb995Sdholland } 801d74eb995Sdholland if ((fs = nvhash_lookup(deffstab, name)) != NULL) { 802d74eb995Sdholland return 1; 803d74eb995Sdholland } 804d74eb995Sdholland 805d74eb995Sdholland return 0; 806d74eb995Sdholland } 8075ecc953bSthorpej 8085ecc953bSthorpej /* 8095ecc953bSthorpej * Define one or more standard options. If an option file name is specified, 8105ecc953bSthorpej * place all options in one file with the specified name. Otherwise, create 8115ecc953bSthorpej * an option file for each option. 8125ecc953bSthorpej * record the option information in the specified table. 8135ecc953bSthorpej */ 8145ecc953bSthorpej void 815d74eb995Sdholland defopt(struct dlhash *ht, const char *fname, struct defoptlist *opts, 816ac24e161Scube struct nvlist *deps, int obs) 8175ecc953bSthorpej { 818d74eb995Sdholland struct defoptlist *dl, *nextdl, *olddl; 8195ecc953bSthorpej const char *name; 8205ecc953bSthorpej char buf[500]; 8215ecc953bSthorpej 8225ecc953bSthorpej if (fname != NULL && badfilename(fname)) { 8235ecc953bSthorpej return; 8245ecc953bSthorpej } 8255ecc953bSthorpej 8265ecc953bSthorpej /* 8275ecc953bSthorpej * Mark these options as ones to skip when creating the Makefile. 8285ecc953bSthorpej */ 829d74eb995Sdholland for (dl = opts; dl != NULL; dl = nextdl) { 830d74eb995Sdholland nextdl = dl->dl_next; 8315ecc953bSthorpej 832d74eb995Sdholland if (dl->dl_lintvalue != NULL) { 83390426267Scube /* 83490426267Scube * If an entry already exists, then we are about to 83590426267Scube * complain, so no worry. 83690426267Scube */ 837d74eb995Sdholland (void) dlhash_insert(defoptlint, dl->dl_name, 838d74eb995Sdholland dl); 83990426267Scube } 84090426267Scube 8415ecc953bSthorpej /* An option name can be declared at most once. */ 842d74eb995Sdholland if (DEFINED_OPTION(dl->dl_name)) { 843c7295a4cSchristos cfgerror("file system or option `%s' already defined", 844d74eb995Sdholland dl->dl_name); 8455ecc953bSthorpej return; 8465ecc953bSthorpej } 8475ecc953bSthorpej 848d74eb995Sdholland if (dlhash_insert(ht, dl->dl_name, dl)) { 849c7295a4cSchristos cfgerror("file system or option `%s' already defined", 850d74eb995Sdholland dl->dl_name); 8515ecc953bSthorpej return; 8525ecc953bSthorpej } 8535ecc953bSthorpej 8545ecc953bSthorpej if (fname == NULL) { 8555ecc953bSthorpej /* 8565ecc953bSthorpej * Each option will be going into its own file. 8575ecc953bSthorpej * Convert the option name to lower case. This 8585ecc953bSthorpej * lower case name will be used as the option 8595ecc953bSthorpej * file name. 8605ecc953bSthorpej */ 8615ecc953bSthorpej (void) snprintf(buf, sizeof(buf), "opt_%s.h", 862d74eb995Sdholland strtolower(dl->dl_name)); 8635ecc953bSthorpej name = intern(buf); 8645ecc953bSthorpej } else { 8655ecc953bSthorpej name = fname; 8665ecc953bSthorpej } 8675ecc953bSthorpej 868d74eb995Sdholland add_opt_dependencies(dl, deps); 8695ecc953bSthorpej 8705ecc953bSthorpej /* 8715ecc953bSthorpej * Remove this option from the parameter list before adding 8725ecc953bSthorpej * it to the list associated with this option file. 8735ecc953bSthorpej */ 874d74eb995Sdholland dl->dl_next = NULL; 8755ecc953bSthorpej 8765ecc953bSthorpej /* 877ac24e161Scube * Flag as obsolete, if requested. 878ac24e161Scube */ 879ac24e161Scube if (obs) { 880d74eb995Sdholland dl->dl_obsolete = 1; 881d74eb995Sdholland (void)dlhash_insert(obsopttab, dl->dl_name, dl); 882ac24e161Scube } 883ac24e161Scube 884ac24e161Scube /* 8855ecc953bSthorpej * Add this option file if we haven't seen it yet. 8865ecc953bSthorpej * Otherwise, append to the list of options already 8875ecc953bSthorpej * associated with this file. 8885ecc953bSthorpej */ 889d74eb995Sdholland if ((olddl = dlhash_lookup(optfiletab, name)) == NULL) { 890d74eb995Sdholland (void)dlhash_insert(optfiletab, name, dl); 8915ecc953bSthorpej } else { 892d74eb995Sdholland while (olddl->dl_next != NULL) 893d74eb995Sdholland olddl = olddl->dl_next; 894d74eb995Sdholland olddl->dl_next = dl; 8955ecc953bSthorpej } 896bb52c144Suebayasi 897bb52c144Suebayasi /* 898bb52c144Suebayasi * Implicit attribute definition for option. 899bb52c144Suebayasi */ 900bb52c144Suebayasi const char *n; 901bb52c144Suebayasi n = strtolower(dl->dl_name); 902bb52c144Suebayasi refattr(n); 9035ecc953bSthorpej } 9045ecc953bSthorpej } 9055ecc953bSthorpej 9065ecc953bSthorpej /* 9075ecc953bSthorpej * Define one or more standard options. If an option file name is specified, 9085ecc953bSthorpej * place all options in one file with the specified name. Otherwise, create 9095ecc953bSthorpej * an option file for each option. 9105ecc953bSthorpej */ 9115ecc953bSthorpej void 912d74eb995Sdholland defoption(const char *fname, struct defoptlist *opts, struct nvlist *deps) 9135ecc953bSthorpej { 9145ecc953bSthorpej 915c7295a4cSchristos cfgwarn("The use of `defopt' is deprecated"); 916ac24e161Scube defopt(defopttab, fname, opts, deps, 0); 9175ecc953bSthorpej } 9185ecc953bSthorpej 9195ecc953bSthorpej 9205ecc953bSthorpej /* 9215ecc953bSthorpej * Define an option for which a value is required. 9225ecc953bSthorpej */ 9235ecc953bSthorpej void 924d74eb995Sdholland defparam(const char *fname, struct defoptlist *opts, struct nvlist *deps, int obs) 9255ecc953bSthorpej { 9265ecc953bSthorpej 927ac24e161Scube defopt(defparamtab, fname, opts, deps, obs); 9285ecc953bSthorpej } 9295ecc953bSthorpej 9305ecc953bSthorpej /* 93172303951Scube * Define an option which must not have a value, and which 9325ecc953bSthorpej * emits a "needs-flag" style output. 9335ecc953bSthorpej */ 9345ecc953bSthorpej void 935d74eb995Sdholland defflag(const char *fname, struct defoptlist *opts, struct nvlist *deps, int obs) 9365ecc953bSthorpej { 9375ecc953bSthorpej 938ac24e161Scube defopt(defflagtab, fname, opts, deps, obs); 9395ecc953bSthorpej } 9405ecc953bSthorpej 9415ecc953bSthorpej 9425ecc953bSthorpej /* 9435ecc953bSthorpej * Add an option from "options FOO". Note that this selects things that 9445ecc953bSthorpej * are "optional foo". 9455ecc953bSthorpej */ 9465ecc953bSthorpej void 9475ecc953bSthorpej addoption(const char *name, const char *value) 9485ecc953bSthorpej { 9495ecc953bSthorpej const char *n; 950c7295a4cSchristos int is_fs, is_param, is_flag, is_undecl, is_obs; 9515ecc953bSthorpej 9525ecc953bSthorpej /* 9535ecc953bSthorpej * Figure out how this option was declared (if at all.) 9545ecc953bSthorpej * XXX should use "params" and "flags" in config. 9555ecc953bSthorpej * XXX crying out for a type field in a unified hashtab. 9565ecc953bSthorpej */ 9575ecc953bSthorpej is_fs = OPT_FSOPT(name); 9585ecc953bSthorpej is_param = OPT_DEFPARAM(name); 9595ecc953bSthorpej is_flag = OPT_DEFFLAG(name); 960ac24e161Scube is_obs = OPT_OBSOLETE(name); 9615ecc953bSthorpej is_undecl = !DEFINED_OPTION(name); 9625ecc953bSthorpej 963ac24e161Scube /* Warn and pretend the user had not selected the option */ 964ac24e161Scube if (is_obs) { 965c7295a4cSchristos cfgwarn("obsolete option `%s' will be ignored", name); 966ac24e161Scube return; 967ac24e161Scube } 968ac24e161Scube 9695ecc953bSthorpej /* Make sure this is not a defined file system. */ 9705ecc953bSthorpej if (is_fs) { 971c7295a4cSchristos cfgerror("`%s' is a defined file system", name); 9725ecc953bSthorpej return; 9735ecc953bSthorpej } 9745ecc953bSthorpej /* A defparam must have a value */ 9755ecc953bSthorpej if (is_param && value == NULL) { 976c7295a4cSchristos cfgerror("option `%s' must have a value", name); 9775ecc953bSthorpej return; 9785ecc953bSthorpej } 9795ecc953bSthorpej /* A defflag must not have a value */ 9805ecc953bSthorpej if (is_flag && value != NULL) { 981c7295a4cSchristos cfgerror("option `%s' must not have a value", name); 9825ecc953bSthorpej return; 9835ecc953bSthorpej } 9845ecc953bSthorpej 9855ecc953bSthorpej if (is_undecl && vflag) { 986c7295a4cSchristos cfgwarn("undeclared option `%s' added to IDENT", name); 9875ecc953bSthorpej } 9885ecc953bSthorpej 9895ecc953bSthorpej if (do_option(opttab, &nextopt, name, value, "options")) 9905ecc953bSthorpej return; 9915ecc953bSthorpej 9925ecc953bSthorpej /* make lowercase, then add to select table */ 9935ecc953bSthorpej n = strtolower(name); 994c7295a4cSchristos (void)ht_insert(selecttab, n, (void *)__UNCONST(n)); 995b599bf99Suebayasi CFGDBG(3, "option selected `%s'", n); 996bd5b1cb6Suebayasi 997bd5b1cb6Suebayasi /* 998bd5b1cb6Suebayasi * Select attribute if one exists. 999bd5b1cb6Suebayasi */ 1000bd5b1cb6Suebayasi struct attr *a; 1001bd5b1cb6Suebayasi if ((a = ht_lookup(attrtab, n)) != NULL) 1002bd5b1cb6Suebayasi selectattr(a); 10035ecc953bSthorpej } 10045ecc953bSthorpej 10055ecc953bSthorpej void 10065ecc953bSthorpej deloption(const char *name) 10075ecc953bSthorpej { 10085ecc953bSthorpej 1009*75eb07f2Suebayasi CFGDBG(4, "deselecting opt `%s'", name); 10105ecc953bSthorpej if (undo_option(opttab, &options, &nextopt, name, "options")) 10115ecc953bSthorpej return; 10125ecc953bSthorpej if (undo_option(selecttab, NULL, NULL, strtolower(name), "options")) 10135ecc953bSthorpej return; 10145ecc953bSthorpej } 10155ecc953bSthorpej 10165ecc953bSthorpej /* 10175ecc953bSthorpej * Add a file system option. This routine simply inserts the name into 10185ecc953bSthorpej * a list of valid file systems, which is used to validate the root 10195ecc953bSthorpej * file system type. The name is then treated like a standard option. 10205ecc953bSthorpej */ 10215ecc953bSthorpej void 10225ecc953bSthorpej addfsoption(const char *name) 10235ecc953bSthorpej { 10245ecc953bSthorpej const char *n; 10255ecc953bSthorpej 10265ecc953bSthorpej /* Make sure this is a defined file system. */ 10275ecc953bSthorpej if (!OPT_FSOPT(name)) { 1028c7295a4cSchristos cfgerror("`%s' is not a defined file system", name); 10295ecc953bSthorpej return; 10305ecc953bSthorpej } 10315ecc953bSthorpej 10325ecc953bSthorpej /* 10335ecc953bSthorpej * Convert to lower case. This will be used in the select 1034baec5c01Scube * table, to verify root file systems. 10355ecc953bSthorpej */ 10365ecc953bSthorpej n = strtolower(name); 10375ecc953bSthorpej 10385ecc953bSthorpej if (do_option(fsopttab, &nextfsopt, name, n, "file-system")) 10395ecc953bSthorpej return; 10405ecc953bSthorpej 10415ecc953bSthorpej /* Add to select table. */ 1042c7295a4cSchristos (void)ht_insert(selecttab, n, __UNCONST(n)); 1043b599bf99Suebayasi CFGDBG(3, "fs selected `%s'", name); 1044e845f2ccSuebayasi 1045e845f2ccSuebayasi /* 1046e845f2ccSuebayasi * Select attribute if one exists. 1047e845f2ccSuebayasi */ 1048e845f2ccSuebayasi struct attr *a; 1049e845f2ccSuebayasi if ((a = ht_lookup(attrtab, n)) != NULL) 1050e845f2ccSuebayasi selectattr(a); 10515ecc953bSthorpej } 10525ecc953bSthorpej 10535ecc953bSthorpej void 10545ecc953bSthorpej delfsoption(const char *name) 10555ecc953bSthorpej { 10565ecc953bSthorpej const char *n; 10575ecc953bSthorpej 1058*75eb07f2Suebayasi CFGDBG(4, "deselecting fs `%s'", name); 10595ecc953bSthorpej n = strtolower(name); 10605ecc953bSthorpej if (undo_option(fsopttab, &fsoptions, &nextfsopt, name, "file-system")) 10615ecc953bSthorpej return; 10625ecc953bSthorpej if (undo_option(selecttab, NULL, NULL, n, "file-system")) 10635ecc953bSthorpej return; 10645ecc953bSthorpej } 10655ecc953bSthorpej 10665ecc953bSthorpej /* 10675ecc953bSthorpej * Add a "make" option. 10685ecc953bSthorpej */ 10695ecc953bSthorpej void 10705ecc953bSthorpej addmkoption(const char *name, const char *value) 10715ecc953bSthorpej { 10725ecc953bSthorpej 10735ecc953bSthorpej (void)do_option(mkopttab, &nextmkopt, name, value, "makeoptions"); 10745ecc953bSthorpej } 10755ecc953bSthorpej 10765ecc953bSthorpej void 10775ecc953bSthorpej delmkoption(const char *name) 10785ecc953bSthorpej { 10795ecc953bSthorpej 1080*75eb07f2Suebayasi CFGDBG(4, "deselecting mkopt `%s'", name); 10815ecc953bSthorpej (void)undo_option(mkopttab, &mkoptions, &nextmkopt, name, 10825ecc953bSthorpej "makeoptions"); 10835ecc953bSthorpej } 10845ecc953bSthorpej 10855ecc953bSthorpej /* 10865ecc953bSthorpej * Add an appending "make" option. 10875ecc953bSthorpej */ 10885ecc953bSthorpej void 10895ecc953bSthorpej appendmkoption(const char *name, const char *value) 10905ecc953bSthorpej { 10915ecc953bSthorpej struct nvlist *nv; 10925ecc953bSthorpej 10935ecc953bSthorpej nv = newnv(name, value, NULL, 0, NULL); 10945ecc953bSthorpej *nextappmkopt = nv; 10955ecc953bSthorpej nextappmkopt = &nv->nv_next; 10965ecc953bSthorpej } 10975ecc953bSthorpej 10985ecc953bSthorpej /* 10995ecc953bSthorpej * Add a conditional appending "make" option. 11005ecc953bSthorpej */ 11015ecc953bSthorpej void 11029483bda7Sdholland appendcondmkoption(struct condexpr *cond, const char *name, const char *value) 11035ecc953bSthorpej { 1104a16a6365Scube struct nvlist *nv; 11055ecc953bSthorpej 11069483bda7Sdholland nv = newnv(name, value, cond, 0, NULL); 1107a16a6365Scube *nextcndmkopt = nv; 1108a16a6365Scube nextcndmkopt = &nv->nv_next; 11095ecc953bSthorpej } 11105ecc953bSthorpej 11115ecc953bSthorpej /* 11125ecc953bSthorpej * Add a name=value pair to an option list. The value may be NULL. 11135ecc953bSthorpej */ 11145ecc953bSthorpej static int 11155ecc953bSthorpej do_option(struct hashtab *ht, struct nvlist ***nppp, const char *name, 11165ecc953bSthorpej const char *value, const char *type) 11175ecc953bSthorpej { 11185ecc953bSthorpej struct nvlist *nv; 11195ecc953bSthorpej 11205ecc953bSthorpej /* assume it will work */ 11215ecc953bSthorpej nv = newnv(name, value, NULL, 0, NULL); 11225ecc953bSthorpej if (ht_insert(ht, name, nv) == 0) { 11235ecc953bSthorpej **nppp = nv; 11245ecc953bSthorpej *nppp = &nv->nv_next; 11255ecc953bSthorpej return (0); 11265ecc953bSthorpej } 11275ecc953bSthorpej 11285ecc953bSthorpej /* oops, already got that option */ 11295ecc953bSthorpej nvfree(nv); 11305ecc953bSthorpej if ((nv = ht_lookup(ht, name)) == NULL) 11315ecc953bSthorpej panic("do_option"); 11325ecc953bSthorpej if (nv->nv_str != NULL && !OPT_FSOPT(name)) 1133c7295a4cSchristos cfgerror("already have %s `%s=%s'", type, name, nv->nv_str); 11345ecc953bSthorpej else 1135c7295a4cSchristos cfgerror("already have %s `%s'", type, name); 11365ecc953bSthorpej return (1); 11375ecc953bSthorpej } 11385ecc953bSthorpej 11395ecc953bSthorpej /* 11405ecc953bSthorpej * Remove a name from a hash table, 11415ecc953bSthorpej * and optionally, a name=value pair from an option list. 11425ecc953bSthorpej */ 11435ecc953bSthorpej static int 11445ecc953bSthorpej undo_option(struct hashtab *ht, struct nvlist **npp, 11455ecc953bSthorpej struct nvlist ***next, const char *name, const char *type) 11465ecc953bSthorpej { 11475ecc953bSthorpej struct nvlist *nv; 11485ecc953bSthorpej 11495ecc953bSthorpej if (ht_remove(ht, name)) { 1150d2737476Smartin /* 1151d2737476Smartin * -U command line option removals are always silent 1152d2737476Smartin */ 115334e6631aSbad if (!handling_cmdlineopts) 115434e6631aSbad cfgwarn("%s `%s' is not defined", type, name); 11555ecc953bSthorpej return (1); 11565ecc953bSthorpej } 1157*75eb07f2Suebayasi if (npp == NULL) { 1158*75eb07f2Suebayasi CFGDBG(2, "opt `%s' deselected", name); 11595ecc953bSthorpej return (0); 1160*75eb07f2Suebayasi } 11615ecc953bSthorpej 11625ecc953bSthorpej for ( ; *npp != NULL; npp = &(*npp)->nv_next) { 11635ecc953bSthorpej if ((*npp)->nv_name != name) 11645ecc953bSthorpej continue; 11655ecc953bSthorpej if (next != NULL && *next == &(*npp)->nv_next) 11665ecc953bSthorpej *next = npp; 11675ecc953bSthorpej nv = (*npp)->nv_next; 1168*75eb07f2Suebayasi CFGDBG(2, "opt `%s' deselected", (*npp)->nv_name); 11695ecc953bSthorpej nvfree(*npp); 11705ecc953bSthorpej *npp = nv; 11715ecc953bSthorpej return (0); 11725ecc953bSthorpej } 11735ecc953bSthorpej panic("%s `%s' is not defined in nvlist", type, name); 11745ecc953bSthorpej return (1); 11755ecc953bSthorpej } 11765ecc953bSthorpej 11775ecc953bSthorpej /* 11785ecc953bSthorpej * Return true if there is at least one instance of the given unit 11795ecc953bSthorpej * on the given device attachment (or any units, if unit == WILD). 11805ecc953bSthorpej */ 11815ecc953bSthorpej int 11825ecc953bSthorpej deva_has_instances(struct deva *deva, int unit) 11835ecc953bSthorpej { 11845ecc953bSthorpej struct devi *i; 11855ecc953bSthorpej 118690ac64deSpooka /* 118790ac64deSpooka * EHAMMERTOOBIG: we shouldn't check i_pseudoroot here. 118890ac64deSpooka * What we want by this check is them to appear non-present 118990ac64deSpooka * except for purposes of other devices being able to attach 119090ac64deSpooka * to them. 119190ac64deSpooka */ 11925ecc953bSthorpej for (i = deva->d_ihead; i != NULL; i = i->i_asame) 119390ac64deSpooka if (i->i_active == DEVI_ACTIVE && i->i_pseudoroot == 0 && 1194c130d400Scube (unit == WILD || unit == i->i_unit || i->i_unit == STAR)) 11955ecc953bSthorpej return (1); 11965ecc953bSthorpej return (0); 11975ecc953bSthorpej } 11985ecc953bSthorpej 11995ecc953bSthorpej /* 12005ecc953bSthorpej * Return true if there is at least one instance of the given unit 12015ecc953bSthorpej * on the given base (or any units, if unit == WILD). 12025ecc953bSthorpej */ 12035ecc953bSthorpej int 12045ecc953bSthorpej devbase_has_instances(struct devbase *dev, int unit) 12055ecc953bSthorpej { 12065ecc953bSthorpej struct deva *da; 12075ecc953bSthorpej 12085ecc953bSthorpej /* 12095ecc953bSthorpej * Pseudo-devices are a little special. We consider them 12105ecc953bSthorpej * to have instances only if they are both: 12115ecc953bSthorpej * 12125ecc953bSthorpej * 1. Included in this kernel configuration. 12135ecc953bSthorpej * 1214b66156c7Sdrochner * 2. Be declared "defpseudodev". 12155ecc953bSthorpej */ 12165ecc953bSthorpej if (dev->d_ispseudo) { 1217b66156c7Sdrochner return ((ht_lookup(devitab, dev->d_name) != NULL) 1218b66156c7Sdrochner && (dev->d_ispseudo > 1)); 12195ecc953bSthorpej } 12205ecc953bSthorpej 12215ecc953bSthorpej for (da = dev->d_ahead; da != NULL; da = da->d_bsame) 12225ecc953bSthorpej if (deva_has_instances(da, unit)) 12235ecc953bSthorpej return (1); 12245ecc953bSthorpej return (0); 12255ecc953bSthorpej } 12265ecc953bSthorpej 12275ecc953bSthorpej static int 12285ecc953bSthorpej cfcrosscheck(struct config *cf, const char *what, struct nvlist *nv) 12295ecc953bSthorpej { 12305ecc953bSthorpej struct devbase *dev; 12315ecc953bSthorpej struct devi *pd; 12325ecc953bSthorpej int errs, devunit; 12335ecc953bSthorpej 12345ecc953bSthorpej if (maxpartitions <= 0) 12355ecc953bSthorpej panic("cfcrosscheck"); 12365ecc953bSthorpej 12375ecc953bSthorpej for (errs = 0; nv != NULL; nv = nv->nv_next) { 12385ecc953bSthorpej if (nv->nv_name == NULL) 12395ecc953bSthorpej continue; 12405ecc953bSthorpej dev = ht_lookup(devbasetab, nv->nv_name); 12415ecc953bSthorpej if (dev == NULL) 12425ecc953bSthorpej panic("cfcrosscheck(%s)", nv->nv_name); 12435ecc953bSthorpej if (has_attr(dev->d_attrs, s_ifnet)) 12445ecc953bSthorpej devunit = nv->nv_ifunit; /* XXX XXX XXX */ 12455ecc953bSthorpej else 12460001b928Schristos devunit = (int)(minor(nv->nv_num) / maxpartitions); 12475ecc953bSthorpej if (devbase_has_instances(dev, devunit)) 12485ecc953bSthorpej continue; 12495ecc953bSthorpej if (devbase_has_instances(dev, STAR) && 12505ecc953bSthorpej devunit >= dev->d_umax) 12515ecc953bSthorpej continue; 12525ecc953bSthorpej TAILQ_FOREACH(pd, &allpseudo, i_next) { 12535ecc953bSthorpej if (pd->i_base == dev && devunit < dev->d_umax && 12545ecc953bSthorpej devunit >= 0) 12555ecc953bSthorpej goto loop; 12565ecc953bSthorpej } 12575ecc953bSthorpej (void)fprintf(stderr, 1258fb65a080Schristos "%s:%d: %s says %s on %s, but there's no %s\n", 12595ecc953bSthorpej conffile, cf->cf_lineno, 12605ecc953bSthorpej cf->cf_name, what, nv->nv_str, nv->nv_str); 12615ecc953bSthorpej errs++; 12625ecc953bSthorpej loop: 12635ecc953bSthorpej ; 12645ecc953bSthorpej } 12655ecc953bSthorpej return (errs); 12665ecc953bSthorpej } 12675ecc953bSthorpej 12685ecc953bSthorpej /* 12695ecc953bSthorpej * Cross-check the configuration: make sure that each target device 12705ecc953bSthorpej * or attribute (`at foo[0*?]') names at least one real device. Also 12715ecc953bSthorpej * see that the root and dump devices for all configurations are there. 12725ecc953bSthorpej */ 12735ecc953bSthorpej int 12745ecc953bSthorpej crosscheck(void) 12755ecc953bSthorpej { 12765ecc953bSthorpej struct config *cf; 12775ecc953bSthorpej int errs; 12785ecc953bSthorpej 12795ecc953bSthorpej errs = 0; 12805ecc953bSthorpej if (TAILQ_EMPTY(&allcf)) { 1281c7295a4cSchristos warnx("%s has no configurations!", conffile); 12825ecc953bSthorpej errs++; 12835ecc953bSthorpej } 12845ecc953bSthorpej TAILQ_FOREACH(cf, &allcf, cf_next) { 12855ecc953bSthorpej if (cf->cf_root != NULL) { /* i.e., not root on ? */ 12865ecc953bSthorpej errs += cfcrosscheck(cf, "root", cf->cf_root); 12875ecc953bSthorpej errs += cfcrosscheck(cf, "dumps", cf->cf_dump); 12885ecc953bSthorpej } 12895ecc953bSthorpej } 12905ecc953bSthorpej return (errs); 12915ecc953bSthorpej } 12925ecc953bSthorpej 12935ecc953bSthorpej /* 12945ecc953bSthorpej * Check to see if there is a *'d unit with a needs-count file. 12955ecc953bSthorpej */ 12965ecc953bSthorpej int 12975ecc953bSthorpej badstar(void) 12985ecc953bSthorpej { 12995ecc953bSthorpej struct devbase *d; 13005ecc953bSthorpej struct deva *da; 13015ecc953bSthorpej struct devi *i; 13025ecc953bSthorpej int errs, n; 13035ecc953bSthorpej 13045ecc953bSthorpej errs = 0; 13055ecc953bSthorpej TAILQ_FOREACH(d, &allbases, d_next) { 13065ecc953bSthorpej for (da = d->d_ahead; da != NULL; da = da->d_bsame) 13075ecc953bSthorpej for (i = da->d_ihead; i != NULL; i = i->i_asame) { 13085ecc953bSthorpej if (i->i_unit == STAR) 13095ecc953bSthorpej goto aybabtu; 13105ecc953bSthorpej } 13115ecc953bSthorpej continue; 13125ecc953bSthorpej aybabtu: 13135ecc953bSthorpej if (ht_lookup(needcnttab, d->d_name)) { 1314c7295a4cSchristos warnx("%s's cannot be *'d until its driver is fixed", 13155ecc953bSthorpej d->d_name); 13165ecc953bSthorpej errs++; 13175ecc953bSthorpej continue; 13185ecc953bSthorpej } 13195ecc953bSthorpej for (n = 0; i != NULL; i = i->i_alias) 13205ecc953bSthorpej if (!i->i_collapsed) 13215ecc953bSthorpej n++; 13225ecc953bSthorpej if (n < 1) 13235ecc953bSthorpej panic("badstar() n<1"); 13245ecc953bSthorpej } 13255ecc953bSthorpej return (errs); 13265ecc953bSthorpej } 13275ecc953bSthorpej 13285ecc953bSthorpej /* 13295ecc953bSthorpej * Verify/create builddir if necessary, change to it, and verify srcdir. 13305ecc953bSthorpej * This will be called when we see the first include. 13315ecc953bSthorpej */ 13325ecc953bSthorpej void 13335ecc953bSthorpej setupdirs(void) 13345ecc953bSthorpej { 13355ecc953bSthorpej struct stat st; 13365ecc953bSthorpej 13375ecc953bSthorpej /* srcdir must be specified if builddir is not specified or if 13385ecc953bSthorpej * no configuration filename was specified. */ 13395ecc953bSthorpej if ((builddir || strcmp(defbuilddir, ".") == 0) && !srcdir) { 1340c7295a4cSchristos cfgerror("source directory must be specified"); 13415ecc953bSthorpej exit(1); 13425ecc953bSthorpej } 13435ecc953bSthorpej 134459c94545Scube if (Lflag) { 134559c94545Scube if (srcdir == NULL) 134659c94545Scube srcdir = "../../.."; 134759c94545Scube return; 134859c94545Scube } 134959c94545Scube 13505ecc953bSthorpej if (srcdir == NULL) 13515ecc953bSthorpej srcdir = "../../../.."; 13525ecc953bSthorpej if (builddir == NULL) 13535ecc953bSthorpej builddir = defbuilddir; 13545ecc953bSthorpej 1355c7295a4cSchristos if (stat(builddir, &st) == -1) { 1356c7295a4cSchristos if (mkdir(builddir, 0777) == -1) 1357c7295a4cSchristos errx(EXIT_FAILURE, "cannot create %s", builddir); 1358c7295a4cSchristos } else if (!S_ISDIR(st.st_mode)) 1359c7295a4cSchristos errx(EXIT_FAILURE, "%s is not a directory", builddir); 1360c7295a4cSchristos if (chdir(builddir) == -1) 1361c7295a4cSchristos err(EXIT_FAILURE, "cannot change to %s", builddir); 1362c7295a4cSchristos if (stat(srcdir, &st) == -1) 1363c7295a4cSchristos err(EXIT_FAILURE, "cannot stat %s", srcdir); 1364c7295a4cSchristos if (!S_ISDIR(st.st_mode)) 1365c7295a4cSchristos errx(EXIT_FAILURE, "%s is not a directory", srcdir); 13665ecc953bSthorpej } 13675ecc953bSthorpej 13685ecc953bSthorpej /* 13695ecc953bSthorpej * Write identifier from "ident" directive into file, for 13705ecc953bSthorpej * newvers.sh to pick it up. 13715ecc953bSthorpej */ 13725ecc953bSthorpej int 13735ecc953bSthorpej mkident(void) 13745ecc953bSthorpej { 13755ecc953bSthorpej FILE *fp; 137611820066Scube int error = 0; 13775ecc953bSthorpej 13785ecc953bSthorpej (void)unlink("ident"); 13795ecc953bSthorpej 13805ecc953bSthorpej if (ident == NULL) 13815ecc953bSthorpej return (0); 13825ecc953bSthorpej 13835ecc953bSthorpej if ((fp = fopen("ident", "w")) == NULL) { 1384c7295a4cSchristos warn("cannot write ident"); 13855ecc953bSthorpej return (1); 13865ecc953bSthorpej } 13875ecc953bSthorpej if (vflag) 13885ecc953bSthorpej (void)printf("using ident '%s'\n", ident); 1389342d3579Sdsl fprintf(fp, "%s\n", ident); 1390342d3579Sdsl fflush(fp); 1391342d3579Sdsl if (ferror(fp)) 139211820066Scube error = 1; 13935ecc953bSthorpej (void)fclose(fp); 13945ecc953bSthorpej 139511820066Scube return error; 13965ecc953bSthorpej } 13975ecc953bSthorpej 13985ecc953bSthorpej void 13995ecc953bSthorpej logconfig_start(void) 14005ecc953bSthorpej { 14015ecc953bSthorpej extern FILE *yyin; 14025ecc953bSthorpej char line[1024]; 14035ecc953bSthorpej const char *tmpdir; 14045ecc953bSthorpej struct stat st; 14055ecc953bSthorpej int fd; 14065ecc953bSthorpej 14075ecc953bSthorpej if (yyin == NULL || fstat(fileno(yyin), &st) == -1) 14085ecc953bSthorpej return; 14095ecc953bSthorpej cfgtime = st.st_mtime; 14105ecc953bSthorpej 14115ecc953bSthorpej tmpdir = getenv("TMPDIR"); 14125ecc953bSthorpej if (tmpdir == NULL) 14133b398d5cSdholland tmpdir = _PATH_TMP; 1414c7295a4cSchristos (void)snprintf(line, sizeof(line), "%s/config.tmp.XXXXXX", tmpdir); 14155ecc953bSthorpej if ((fd = mkstemp(line)) == -1 || 14165ecc953bSthorpej (cfg = fdopen(fd, "r+")) == NULL) { 14175ecc953bSthorpej if (fd != -1) { 1418c7295a4cSchristos (void)unlink(line); 1419c7295a4cSchristos (void)close(fd); 14205ecc953bSthorpej } 14215ecc953bSthorpej cfg = NULL; 14225ecc953bSthorpej return; 14235ecc953bSthorpej } 1424c7295a4cSchristos (void)unlink(line); 14255ecc953bSthorpej 14264e4935bbSuwe (void)fprintf(cfg, "#include <sys/cdefs.h>\n\n"); 14275ecc953bSthorpej (void)fprintf(cfg, "#include \"opt_config.h\"\n"); 14285ecc953bSthorpej (void)fprintf(cfg, "\n"); 14295ecc953bSthorpej (void)fprintf(cfg, "/*\n"); 14305ecc953bSthorpej (void)fprintf(cfg, " * Add either (or both) of\n"); 14315ecc953bSthorpej (void)fprintf(cfg, " *\n"); 14325ecc953bSthorpej (void)fprintf(cfg, " *\toptions %s\n", LOGCONFIG_LARGE); 14335ecc953bSthorpej (void)fprintf(cfg, " *\toptions %s\n", LOGCONFIG_SMALL); 14345ecc953bSthorpej (void)fprintf(cfg, " *\n"); 14355ecc953bSthorpej (void)fprintf(cfg, 14365ecc953bSthorpej " * to your kernel config file to embed it in the resulting\n"); 14375ecc953bSthorpej (void)fprintf(cfg, 14385ecc953bSthorpej " * kernel. The latter option does not include files that are\n"); 14395ecc953bSthorpej (void)fprintf(cfg, 14405ecc953bSthorpej " * included (recursively) by your config file. The embedded\n"); 14415ecc953bSthorpej (void)fprintf(cfg, 14425ecc953bSthorpej " * data be extracted by using the command:\n"); 14435ecc953bSthorpej (void)fprintf(cfg, " *\n"); 14445ecc953bSthorpej (void)fprintf(cfg, 14455ecc953bSthorpej " *\tstrings netbsd | sed -n 's/^_CFG_//p' | unvis\n"); 14465ecc953bSthorpej (void)fprintf(cfg, " */\n"); 14475ecc953bSthorpej (void)fprintf(cfg, "\n"); 14485ecc953bSthorpej (void)fprintf(cfg, "#ifdef CONFIG_FILE\n"); 14495ecc953bSthorpej (void)fprintf(cfg, "#if defined(%s) || defined(%s)\n\n", 14505ecc953bSthorpej LOGCONFIG_LARGE, LOGCONFIG_SMALL); 14514e4935bbSuwe (void)fprintf(cfg, "static const char config[] __used =\n\n"); 14525ecc953bSthorpej 14535ecc953bSthorpej (void)fprintf(cfg, "#ifdef %s\n\n", LOGCONFIG_LARGE); 14545ecc953bSthorpej (void)fprintf(cfg, "\"_CFG_### START CONFIG FILE \\\"%s\\\"\\n\"\n\n", 14555ecc953bSthorpej conffile); 14565ecc953bSthorpej (void)fprintf(cfg, "#endif /* %s */\n\n", LOGCONFIG_LARGE); 14575ecc953bSthorpej 14585ecc953bSthorpej logconfig_include(yyin, NULL); 14595ecc953bSthorpej 14605ecc953bSthorpej (void)fprintf(cfg, "#ifdef %s\n\n", LOGCONFIG_LARGE); 14615ecc953bSthorpej (void)fprintf(cfg, "\"_CFG_### END CONFIG FILE \\\"%s\\\"\\n\"\n", 14625ecc953bSthorpej conffile); 14635ecc953bSthorpej 14645ecc953bSthorpej rewind(yyin); 14655ecc953bSthorpej } 14665ecc953bSthorpej 14675ecc953bSthorpej void 14685ecc953bSthorpej logconfig_include(FILE *cf, const char *filename) 14695ecc953bSthorpej { 14705ecc953bSthorpej char line[1024], in[2048], *out; 14715ecc953bSthorpej struct stat st; 14725ecc953bSthorpej int missingeol; 14735ecc953bSthorpej 14745ecc953bSthorpej if (!cfg) 14755ecc953bSthorpej return; 14765ecc953bSthorpej 14775ecc953bSthorpej missingeol = 0; 14785ecc953bSthorpej if (fstat(fileno(cf), &st) == -1) 14795ecc953bSthorpej return; 14805ecc953bSthorpej if (cfgtime < st.st_mtime) 14815ecc953bSthorpej cfgtime = st.st_mtime; 14825ecc953bSthorpej 14835ecc953bSthorpej if (filename) 14845ecc953bSthorpej (void)fprintf(cfg, 14855ecc953bSthorpej "\"_CFG_### (included from \\\"%s\\\")\\n\"\n", 14865ecc953bSthorpej filename); 14875ecc953bSthorpej while (fgets(line, sizeof(line), cf) != NULL) { 14885ecc953bSthorpej missingeol = 1; 14895ecc953bSthorpej (void)fprintf(cfg, "\"_CFG_"); 14905ecc953bSthorpej if (filename) 14915ecc953bSthorpej (void)fprintf(cfg, "###> "); 14925ecc953bSthorpej strvis(in, line, VIS_TAB); 14935ecc953bSthorpej for (out = in; *out; out++) 14945ecc953bSthorpej switch (*out) { 14955ecc953bSthorpej case '\n': 14965ecc953bSthorpej (void)fprintf(cfg, "\\n\"\n"); 14975ecc953bSthorpej missingeol = 0; 14985ecc953bSthorpej break; 14995ecc953bSthorpej case '"': case '\\': 15005ecc953bSthorpej (void)fputc('\\', cfg); 15015ecc953bSthorpej /* FALLTHROUGH */ 15025ecc953bSthorpej default: 15035ecc953bSthorpej (void)fputc(*out, cfg); 15045ecc953bSthorpej break; 15055ecc953bSthorpej } 15065ecc953bSthorpej } 15075ecc953bSthorpej if (missingeol) { 15085ecc953bSthorpej (void)fprintf(cfg, "\\n\"\n"); 1509c7295a4cSchristos warnx("%s: newline missing at EOF", 15105ecc953bSthorpej filename != NULL ? filename : conffile); 15115ecc953bSthorpej } 15125ecc953bSthorpej if (filename) 15135ecc953bSthorpej (void)fprintf(cfg, "\"_CFG_### (end include \\\"%s\\\")\\n\"\n", 15145ecc953bSthorpej filename); 15155ecc953bSthorpej 15165ecc953bSthorpej rewind(cf); 15175ecc953bSthorpej } 15185ecc953bSthorpej 15195ecc953bSthorpej void 15205ecc953bSthorpej logconfig_end(void) 15215ecc953bSthorpej { 15225ecc953bSthorpej char line[1024]; 15235ecc953bSthorpej FILE *fp; 15245ecc953bSthorpej struct stat st; 15255ecc953bSthorpej 15265ecc953bSthorpej if (!cfg) 15275ecc953bSthorpej return; 15285ecc953bSthorpej 15295ecc953bSthorpej (void)fprintf(cfg, "#endif /* %s */\n", LOGCONFIG_LARGE); 15305ecc953bSthorpej (void)fprintf(cfg, ";\n"); 15315ecc953bSthorpej (void)fprintf(cfg, "#endif /* %s || %s */\n", 15325ecc953bSthorpej LOGCONFIG_LARGE, LOGCONFIG_SMALL); 15335ecc953bSthorpej (void)fprintf(cfg, "#endif /* CONFIG_FILE */\n"); 1534342d3579Sdsl fflush(cfg); 1535342d3579Sdsl if (ferror(cfg)) 1536342d3579Sdsl err(EXIT_FAILURE, "write to temporary file for config.h failed"); 15375ecc953bSthorpej rewind(cfg); 15385ecc953bSthorpej 15395ecc953bSthorpej if (stat("config_file.h", &st) != -1) { 15405ecc953bSthorpej if (cfgtime < st.st_mtime) { 15415ecc953bSthorpej fclose(cfg); 15425ecc953bSthorpej return; 15435ecc953bSthorpej } 15445ecc953bSthorpej } 15455ecc953bSthorpej 15465ecc953bSthorpej fp = fopen("config_file.h", "w"); 1547342d3579Sdsl if (!fp) 1548342d3579Sdsl err(EXIT_FAILURE, "cannot open \"config.h\""); 15495ecc953bSthorpej 15505ecc953bSthorpej while (fgets(line, sizeof(line), cfg) != NULL) 15515ecc953bSthorpej fputs(line, fp); 1552342d3579Sdsl fflush(fp); 1553342d3579Sdsl if (ferror(fp)) 1554342d3579Sdsl err(EXIT_FAILURE, "write to \"config.h\" failed"); 15555ecc953bSthorpej fclose(fp); 15565ecc953bSthorpej fclose(cfg); 15575ecc953bSthorpej } 15585ecc953bSthorpej 1559a16a6365Scube const char * 15605ecc953bSthorpej strtolower(const char *name) 15615ecc953bSthorpej { 15625ecc953bSthorpej const char *n; 15635ecc953bSthorpej char *p, low[500]; 15645ecc953bSthorpej unsigned char c; 15655ecc953bSthorpej 15665ecc953bSthorpej for (n = name, p = low; (c = *n) != '\0'; n++) 15675ecc953bSthorpej *p++ = isupper(c) ? tolower(c) : c; 15685ecc953bSthorpej *p = 0; 15695ecc953bSthorpej return (intern(low)); 15705ecc953bSthorpej } 15715ecc953bSthorpej 15725ecc953bSthorpej static int 15735ecc953bSthorpej is_elf(const char *file) 15745ecc953bSthorpej { 15755ecc953bSthorpej int kernel; 15765ecc953bSthorpej char hdr[4]; 15775ecc953bSthorpej 15785ecc953bSthorpej kernel = open(file, O_RDONLY); 1579c7295a4cSchristos if (kernel == -1) 1580c7295a4cSchristos err(EXIT_FAILURE, "cannot open %s", file); 1581c7295a4cSchristos if (read(kernel, hdr, 4) != 4) 1582c7295a4cSchristos err(EXIT_FAILURE, "Cannot read from %s", file); 1583c7295a4cSchristos (void)close(kernel); 15845ecc953bSthorpej 15855ecc953bSthorpej return memcmp("\177ELF", hdr, 4) == 0 ? 1 : 0; 15865ecc953bSthorpej } 15875ecc953bSthorpej 15885ecc953bSthorpej static int 15895ecc953bSthorpej extract_config(const char *kname, const char *cname, int cfd) 15905ecc953bSthorpej { 15915ecc953bSthorpej char *ptr; 15925ecc953bSthorpej int found, kfd, i; 15935ecc953bSthorpej struct stat st; 15945ecc953bSthorpej 15955ecc953bSthorpej found = 0; 15965ecc953bSthorpej 15975ecc953bSthorpej /* mmap(2) binary kernel */ 15985ecc953bSthorpej kfd = open(conffile, O_RDONLY); 1599c7295a4cSchristos if (kfd == -1) 1600c7295a4cSchristos err(EXIT_FAILURE, "cannot open %s", kname); 1601c7295a4cSchristos if (fstat(kfd, &st) == -1) 1602c7295a4cSchristos err(EXIT_FAILURE, "cannot stat %s", kname); 1603c7295a4cSchristos ptr = mmap(0, st.st_size, PROT_READ, MAP_FILE | MAP_SHARED, 16045ecc953bSthorpej kfd, 0); 1605c7295a4cSchristos if (ptr == MAP_FAILED) 1606c7295a4cSchristos err(EXIT_FAILURE, "cannot mmap %s", kname); 16075ecc953bSthorpej 16085ecc953bSthorpej /* Scan mmap(2)'ed region, extracting kernel configuration */ 16095ecc953bSthorpej for (i = 0; i < st.st_size; i++) { 16105ecc953bSthorpej if ((*ptr == '_') && (st.st_size - i > 5) && memcmp(ptr, 16115ecc953bSthorpej "_CFG_", 5) == 0) { 16125ecc953bSthorpej /* Line found */ 16135ecc953bSthorpej char *oldptr, line[LINE_MAX + 1], uline[LINE_MAX + 1]; 16145ecc953bSthorpej int j; 16155ecc953bSthorpej 16165ecc953bSthorpej found = 1; 16175ecc953bSthorpej 16185ecc953bSthorpej oldptr = (ptr += 5); 1619c7295a4cSchristos while (*ptr != '\n' && *ptr != '\0') 1620c7295a4cSchristos ptr++; 1621c7295a4cSchristos if (ptr - oldptr > LINE_MAX) 1622c7295a4cSchristos errx(EXIT_FAILURE, "line too long"); 16235ecc953bSthorpej i += ptr - oldptr + 5; 1624c7295a4cSchristos (void)memcpy(line, oldptr, (size_t)(ptr - oldptr)); 16255ecc953bSthorpej line[ptr - oldptr] = '\0'; 16265ecc953bSthorpej j = strunvis(uline, line); 1627c7295a4cSchristos if (j == -1) 1628c7295a4cSchristos errx(EXIT_FAILURE, "unvis: invalid " 1629c7295a4cSchristos "encoded sequence"); 16305ecc953bSthorpej uline[j] = '\n'; 1631c7295a4cSchristos if (write(cfd, uline, (size_t)j + 1) == -1) 1632c7295a4cSchristos err(EXIT_FAILURE, "cannot write to %s", cname); 1633c7295a4cSchristos } else 1634c7295a4cSchristos ptr++; 16355ecc953bSthorpej } 16365ecc953bSthorpej 1637c7295a4cSchristos (void)close(kfd); 16385ecc953bSthorpej 16395ecc953bSthorpej return found; 16405ecc953bSthorpej } 1641c130d400Scube 16427aa6070dScube struct dhdi_params { 16437aa6070dScube struct devbase *d; 16447aa6070dScube int unit; 1645a31ff6b4Scube int level; 16467aa6070dScube }; 16477aa6070dScube 16487aa6070dScube static int 16497aa6070dScube devbase_has_dead_instances(const char *key, void *value, void *aux) 16507aa6070dScube { 1651a31ff6b4Scube struct devi *i; 16527aa6070dScube struct dhdi_params *dhdi = aux; 16537aa6070dScube 1654a31ff6b4Scube for (i = value; i != NULL; i = i->i_alias) 16557aa6070dScube if (i->i_base == dhdi->d && 16567aa6070dScube (dhdi->unit == WILD || dhdi->unit == i->i_unit || 1657a31ff6b4Scube i->i_unit == STAR) && 1658a31ff6b4Scube i->i_level >= dhdi->level) 16597aa6070dScube return 1; 16607aa6070dScube return 0; 16617aa6070dScube } 16627aa6070dScube 16637aa6070dScube /* 16647aa6070dScube * This is almost the same as devbase_has_instances, except it 16657aa6070dScube * may have special considerations regarding ignored instances. 16667aa6070dScube */ 16677aa6070dScube 16687aa6070dScube static int 1669a31ff6b4Scube devbase_has_any_instance(struct devbase *dev, int unit, int state, int level) 16707aa6070dScube { 16717aa6070dScube struct deva *da; 16727aa6070dScube struct devi *i; 16737aa6070dScube 16747aa6070dScube if (dev->d_ispseudo) { 16757aa6070dScube if (dev->d_ihead != NULL) 16767aa6070dScube return 1; 1677a31ff6b4Scube else if (state != DEVI_IGNORED) 16787aa6070dScube return 0; 1679a31ff6b4Scube if ((i = ht_lookup(deaddevitab, dev->d_name)) == NULL) 1680a31ff6b4Scube return 0; 1681a31ff6b4Scube return (i->i_level >= level); 16827aa6070dScube } 16837aa6070dScube 16847aa6070dScube for (da = dev->d_ahead; da != NULL; da = da->d_bsame) 16857aa6070dScube for (i = da->d_ihead; i != NULL; i = i->i_asame) 16867aa6070dScube if ((i->i_active == DEVI_ACTIVE || 16877aa6070dScube i->i_active == state) && 16887aa6070dScube (unit == WILD || unit == i->i_unit || 16897aa6070dScube i->i_unit == STAR)) 16907aa6070dScube return 1; 16917aa6070dScube 16927aa6070dScube if (state == DEVI_IGNORED) { 1693a31ff6b4Scube struct dhdi_params dhdi = { dev, unit, level }; 16947aa6070dScube /* also check dead devices */ 16957aa6070dScube return ht_enumerate(deaddevitab, devbase_has_dead_instances, 16967aa6070dScube &dhdi); 16977aa6070dScube } 16987aa6070dScube 16997aa6070dScube return 0; 17007aa6070dScube } 17017aa6070dScube 17027aa6070dScube /* 17037aa6070dScube * check_dead_devi(), used with ht_enumerate, checks if any of the removed 17047aa6070dScube * device instances would have been a valid instance considering the devbase, 17057aa6070dScube * the parent device and the interface attribute. 17067aa6070dScube * 17077aa6070dScube * In other words, for a non-active device, it checks if children would be 17087aa6070dScube * actual orphans or the result of a negative statement in the config file. 17097aa6070dScube */ 17107aa6070dScube 17117aa6070dScube struct cdd_params { 17127aa6070dScube struct devbase *d; 17137aa6070dScube struct attr *at; 17147aa6070dScube struct devbase *parent; 17157aa6070dScube }; 17167aa6070dScube 17177aa6070dScube static int 17187aa6070dScube check_dead_devi(const char *key, void *value, void *aux) 17197aa6070dScube { 17207aa6070dScube struct cdd_params *cdd = aux; 17217aa6070dScube struct devi *i = value; 1722a31ff6b4Scube struct pspec *p; 17237aa6070dScube 17247aa6070dScube if (i->i_base != cdd->d) 17257aa6070dScube return 0; 17267aa6070dScube 1727a31ff6b4Scube for (; i != NULL; i = i->i_alias) { 1728a31ff6b4Scube p = i->i_pspec; 17297aa6070dScube if ((p == NULL && cdd->at == NULL) || 17307aa6070dScube (p != NULL && p->p_iattr == cdd->at && 17317aa6070dScube (p->p_atdev == NULL || p->p_atdev == cdd->parent))) { 17327aa6070dScube if (p != NULL && 17337aa6070dScube !devbase_has_any_instance(cdd->parent, p->p_atunit, 1734a31ff6b4Scube DEVI_IGNORED, i->i_level)) 17357aa6070dScube return 0; 17367aa6070dScube else 17377aa6070dScube return 1; 17387aa6070dScube } 1739a31ff6b4Scube } 17407aa6070dScube return 0; 17417aa6070dScube } 17427aa6070dScube 1743c130d400Scube static void 17447aa6070dScube do_kill_orphans(struct devbase *d, struct attr *at, struct devbase *parent, 17457aa6070dScube int state) 1746c130d400Scube { 17474caf067bSdholland struct nvlist *nv1; 17484caf067bSdholland struct attrlist *al; 1749c130d400Scube struct attr *a; 1750c130d400Scube struct devi *i, *j = NULL; 1751c130d400Scube struct pspec *p; 17527aa6070dScube int active = 0; 1753c130d400Scube 1754c130d400Scube /* 1755c130d400Scube * A pseudo-device will always attach at root, and if it has an 1756c130d400Scube * instance (it cannot have more than one), it is enough to consider 1757c130d400Scube * it active, as there is no real attachment. 17587aa6070dScube * 17597aa6070dScube * A pseudo device can never be marked DEVI_IGNORED. 1760c130d400Scube */ 1761c130d400Scube if (d->d_ispseudo) { 17627aa6070dScube if (d->d_ihead != NULL) 17637aa6070dScube d->d_ihead->i_active = active = DEVI_ACTIVE; 17647aa6070dScube else { 17657aa6070dScube if (ht_lookup(deaddevitab, d->d_name) != NULL) 17667aa6070dScube active = DEVI_IGNORED; 17677aa6070dScube else 1768c130d400Scube return; 17697aa6070dScube } 1770c130d400Scube } else { 17712fb411a1Scube int seen = 0; 17722fb411a1Scube 1773c130d400Scube for (i = d->d_ihead; i != NULL; i = i->i_bsame) { 1774c130d400Scube for (j = i; j != NULL; j = j->i_alias) { 1775c130d400Scube p = j->i_pspec; 1776c130d400Scube if ((p == NULL && at == NULL) || 1777c130d400Scube (p != NULL && p->p_iattr == at && 1778c130d400Scube (p->p_atdev == NULL || 1779c130d400Scube p->p_atdev == parent))) { 1780c130d400Scube if (p != NULL && 17817aa6070dScube !devbase_has_any_instance(parent, 1782a31ff6b4Scube p->p_atunit, state, j->i_level)) 1783c130d400Scube continue; 1784c130d400Scube /* 1785c130d400Scube * There are Fry-like devices which can 1786c130d400Scube * be their own grand-parent (or even 1787c130d400Scube * parent, like uhub). We don't want 1788c130d400Scube * to loop, so if we've already reached 1789c130d400Scube * an instance for one reason or 1790c130d400Scube * another, stop there. 1791c130d400Scube */ 17927aa6070dScube if (j->i_active == DEVI_ACTIVE || 17932fb411a1Scube j->i_active == state) { 1794c130d400Scube /* 1795c130d400Scube * Device has already been 17962fb411a1Scube * seen. However it might 17972fb411a1Scube * have siblings who still 17982fb411a1Scube * have to be activated or 17992fb411a1Scube * orphaned. 1800c130d400Scube */ 18012fb411a1Scube seen = 1; 18022fb411a1Scube continue; 18032fb411a1Scube } 18047aa6070dScube j->i_active = active = state; 1805c130d400Scube if (p != NULL) 18067aa6070dScube p->p_active = state; 1807c130d400Scube } 1808c130d400Scube } 1809c130d400Scube } 1810b7505c15Scube /* 1811b7505c15Scube * If we've been there but have made no change, stop. 1812b7505c15Scube */ 1813b7505c15Scube if (seen && !active) 18142fb411a1Scube return; 18157aa6070dScube if (!active) { 18167aa6070dScube struct cdd_params cdd = { d, at, parent }; 18177aa6070dScube /* Look for a matching dead devi */ 181842256315Scube if (ht_enumerate(deaddevitab, check_dead_devi, &cdd) && 181942256315Scube d != parent) 18207aa6070dScube /* 18217aa6070dScube * That device had its instances removed. 18227aa6070dScube * Continue the loop marking descendants 18237aa6070dScube * with DEVI_IGNORED instead of DEVI_ACTIVE. 182442256315Scube * 182542256315Scube * There is one special case for devices that 182642256315Scube * are their own parent: if that instance is 182742256315Scube * removed (e.g., no uhub* at uhub?), we don't 182842256315Scube * have to continue looping. 18297aa6070dScube */ 18307aa6070dScube active = DEVI_IGNORED; 18317aa6070dScube else 1832c130d400Scube return; 1833c130d400Scube } 18347aa6070dScube } 1835c130d400Scube 18364caf067bSdholland for (al = d->d_attrs; al != NULL; al = al->al_next) { 18374caf067bSdholland a = al->al_this; 1838c130d400Scube for (nv1 = a->a_devs; nv1 != NULL; nv1 = nv1->nv_next) 18397aa6070dScube do_kill_orphans(nv1->nv_ptr, a, d, active); 1840c130d400Scube } 1841c130d400Scube } 1842c130d400Scube 1843c130d400Scube static int 1844c7295a4cSchristos /*ARGSUSED*/ 1845c130d400Scube kill_orphans_cb(const char *key, void *value, void *aux) 1846c130d400Scube { 18477aa6070dScube do_kill_orphans((struct devbase *)value, NULL, NULL, DEVI_ACTIVE); 1848c130d400Scube return 0; 1849c130d400Scube } 1850c130d400Scube 1851c130d400Scube static void 1852c7295a4cSchristos kill_orphans(void) 1853c130d400Scube { 1854c130d400Scube ht_enumerate(devroottab, kill_orphans_cb, NULL); 1855c130d400Scube } 1856d2737476Smartin 1857d2737476Smartin static void 1858d2737476Smartin add_makeopt(const char *opt) 1859d2737476Smartin { 1860d2737476Smartin struct nvlist *p; 1861d2737476Smartin char *buf = estrdup(opt); 1862d2737476Smartin char *eq = strchr(buf, '='); 1863d2737476Smartin 1864d2737476Smartin if (!eq) 1865d2737476Smartin errx(EXIT_FAILURE, "-D %s is not in var=value format", opt); 1866d2737476Smartin 1867d2737476Smartin *eq = 0; 1868d2737476Smartin p = newnv(estrdup(buf), estrdup(eq+1), NULL, 0, NULL); 1869d2737476Smartin free(buf); 1870d2737476Smartin p->nv_next = cmdlinedefs; 1871d2737476Smartin cmdlinedefs = p; 1872d2737476Smartin } 1873d2737476Smartin 1874d2737476Smartin static void 1875d2737476Smartin remove_makeopt(const char *opt) 1876d2737476Smartin { 1877d2737476Smartin struct nvlist *p; 1878d2737476Smartin 1879d2737476Smartin p = newnv(estrdup(opt), NULL, NULL, 0, NULL); 1880d2737476Smartin p->nv_next = cmdlineundefs; 1881d2737476Smartin cmdlineundefs = p; 1882d2737476Smartin } 1883d2737476Smartin 1884d2737476Smartin static void 1885d2737476Smartin handle_cmdline_makeoptions(void) 1886d2737476Smartin { 1887d2737476Smartin struct nvlist *p, *n; 1888d2737476Smartin 1889d2737476Smartin handling_cmdlineopts = 1; 1890d2737476Smartin for (p = cmdlineundefs; p; p = n) { 1891d2737476Smartin n = p->nv_next; 1892d2737476Smartin delmkoption(intern(p->nv_name)); 1893d2737476Smartin free(__UNCONST(p->nv_name)); 1894d2737476Smartin nvfree(p); 1895d2737476Smartin } 1896d2737476Smartin for (p = cmdlinedefs; p; p = n) { 1897d2737476Smartin const char *name = intern(p->nv_name); 1898d2737476Smartin 1899d2737476Smartin n = p->nv_next; 1900d2737476Smartin delmkoption(name); 1901d2737476Smartin addmkoption(name, intern(p->nv_str)); 1902d2737476Smartin free(__UNCONST(p->nv_name)); 1903d2737476Smartin free(__UNCONST(p->nv_str)); 1904d2737476Smartin 1905d2737476Smartin nvfree(p); 1906d2737476Smartin } 1907d2737476Smartin handling_cmdlineopts = 0; 1908d2737476Smartin } 1909