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