mkoptions.c revision 209969
1/* 2 * Copyright (c) 1995 Peter Wemm 3 * Copyright (c) 1980, 1993 4 * The Regents of the University of California. All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 4. Neither the name of the University nor the names of its contributors 15 * may be used to endorse or promote products derived from this software 16 * without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28 * SUCH DAMAGE. 29 */ 30 31#ifndef lint 32#if 0 33static char sccsid[] = "@(#)mkheaders.c 8.1 (Berkeley) 6/6/93"; 34#endif 35static const char rcsid[] = 36 "$FreeBSD: head/usr.sbin/config/mkoptions.c 209969 2010-07-13 04:08:08Z nwhitehorn $"; 37#endif /* not lint */ 38 39/* 40 * Make all the .h files for the optional entries 41 */ 42 43#include <ctype.h> 44#include <err.h> 45#include <stdio.h> 46#include <string.h> 47#include <sys/param.h> 48#include "config.h" 49#include "y.tab.h" 50 51static struct users { 52 int u_default; 53 int u_min; 54 int u_max; 55} users = { 8, 2, 512 }; 56 57static char *lower(char *); 58static void read_options(void); 59static void do_option(char *); 60static char *tooption(char *); 61 62void 63options(void) 64{ 65 char buf[40]; 66 struct cputype *cp; 67 struct opt_list *ol; 68 struct opt *op; 69 70 /* Fake the cpu types as options. */ 71 SLIST_FOREACH(cp, &cputype, cpu_next) { 72 op = (struct opt *)calloc(1, sizeof(*op)); 73 if (op == NULL) 74 err(EXIT_FAILURE, "calloc"); 75 op->op_name = ns(cp->cpu_name); 76 SLIST_INSERT_HEAD(&opt, op, op_next); 77 } 78 79 if (maxusers == 0) { 80 /* printf("maxusers not specified; will auto-size\n"); */ 81 } else if (maxusers < users.u_min) { 82 printf("minimum of %d maxusers assumed\n", users.u_min); 83 maxusers = users.u_min; 84 } else if (maxusers > users.u_max) 85 printf("warning: maxusers > %d (%d)\n", users.u_max, maxusers); 86 87 /* Fake MAXUSERS as an option. */ 88 op = (struct opt *)calloc(1, sizeof(*op)); 89 if (op == NULL) 90 err(EXIT_FAILURE, "calloc"); 91 op->op_name = ns("MAXUSERS"); 92 snprintf(buf, sizeof(buf), "%d", maxusers); 93 op->op_value = ns(buf); 94 SLIST_INSERT_HEAD(&opt, op, op_next); 95 96 read_options(); 97 98 /* Fake the value of MACHINE_ARCH as an option if necessary */ 99 SLIST_FOREACH(ol, &otab, o_next) { 100 if (strcasecmp(ol->o_name, machinearch) != 0) 101 continue; 102 103 op = (struct opt *)calloc(1, sizeof(*op)); 104 if (op == NULL) 105 err(EXIT_FAILURE, "calloc"); 106 op->op_name = ns(ol->o_name); 107 SLIST_INSERT_HEAD(&opt, op, op_next); 108 break; 109 } 110 111 SLIST_FOREACH(op, &opt, op_next) { 112 SLIST_FOREACH(ol, &otab, o_next) { 113 if (eq(op->op_name, ol->o_name) && 114 (ol->o_flags & OL_ALIAS)) { 115 printf("Mapping option %s to %s.\n", 116 op->op_name, ol->o_file); 117 op->op_name = ol->o_file; 118 break; 119 } 120 } 121 } 122 SLIST_FOREACH(ol, &otab, o_next) 123 do_option(ol->o_name); 124 SLIST_FOREACH(op, &opt, op_next) { 125 if (!op->op_ownfile && strncmp(op->op_name, "DEV_", 4)) { 126 printf("%s: unknown option \"%s\"\n", 127 PREFIX, op->op_name); 128 exit(1); 129 } 130 } 131} 132 133/* 134 * Generate an <options>.h file 135 */ 136 137static void 138do_option(char *name) 139{ 140 char *file, *inw; 141 const char *basefile; 142 struct opt_list *ol; 143 struct opt *op; 144 struct opt_head op_head; 145 FILE *inf, *outf; 146 char *value; 147 char *oldvalue; 148 int seen; 149 int tidy; 150 151 file = tooption(name); 152 /* 153 * Check to see if the option was specified.. 154 */ 155 value = NULL; 156 SLIST_FOREACH(op, &opt, op_next) { 157 if (eq(name, op->op_name)) { 158 oldvalue = value; 159 value = op->op_value; 160 if (value == NULL) 161 value = ns("1"); 162 if (oldvalue != NULL && !eq(value, oldvalue)) 163 printf( 164 "%s: option \"%s\" redefined from %s to %s\n", 165 PREFIX, op->op_name, oldvalue, 166 value); 167 op->op_ownfile++; 168 } 169 } 170 171 remember(file); 172 inf = fopen(file, "r"); 173 if (inf == 0) { 174 outf = fopen(file, "w"); 175 if (outf == 0) 176 err(1, "%s", file); 177 178 /* was the option in the config file? */ 179 if (value) { 180 fprintf(outf, "#define %s %s\n", name, value); 181 } /* else empty file */ 182 183 (void)fclose(outf); 184 return; 185 } 186 basefile = ""; 187 SLIST_FOREACH(ol, &otab, o_next) 188 if (eq(name, ol->o_name)) { 189 basefile = ol->o_file; 190 break; 191 } 192 oldvalue = NULL; 193 SLIST_INIT(&op_head); 194 seen = 0; 195 tidy = 0; 196 for (;;) { 197 char *cp; 198 char *invalue; 199 200 /* get the #define */ 201 if ((inw = get_word(inf)) == 0 || inw == (char *)EOF) 202 break; 203 /* get the option name */ 204 if ((inw = get_word(inf)) == 0 || inw == (char *)EOF) 205 break; 206 inw = ns(inw); 207 /* get the option value */ 208 if ((cp = get_word(inf)) == 0 || cp == (char *)EOF) 209 break; 210 /* option value */ 211 invalue = ns(cp); /* malloced */ 212 if (eq(inw, name)) { 213 oldvalue = invalue; 214 invalue = value; 215 seen++; 216 } 217 SLIST_FOREACH(ol, &otab, o_next) 218 if (eq(inw, ol->o_name)) 219 break; 220 if (!eq(inw, name) && !ol) { 221 printf("WARNING: unknown option `%s' removed from %s\n", 222 inw, file); 223 tidy++; 224 } else if (ol != NULL && !eq(basefile, ol->o_file)) { 225 printf("WARNING: option `%s' moved from %s to %s\n", 226 inw, basefile, ol->o_file); 227 tidy++; 228 } else { 229 op = (struct opt *) calloc(1, sizeof *op); 230 if (op == NULL) 231 err(EXIT_FAILURE, "calloc"); 232 op->op_name = inw; 233 op->op_value = invalue; 234 SLIST_INSERT_HEAD(&op_head, op, op_next); 235 } 236 237 /* EOL? */ 238 cp = get_word(inf); 239 if (cp == (char *)EOF) 240 break; 241 } 242 (void)fclose(inf); 243 if (!tidy && ((value == NULL && oldvalue == NULL) || 244 (value && oldvalue && eq(value, oldvalue)))) { 245 while (!SLIST_EMPTY(&op_head)) { 246 op = SLIST_FIRST(&op_head); 247 SLIST_REMOVE_HEAD(&op_head, op_next); 248 free(op->op_name); 249 free(op->op_value); 250 free(op); 251 } 252 return; 253 } 254 255 if (value && !seen) { 256 /* New option appears */ 257 op = (struct opt *) calloc(1, sizeof *op); 258 if (op == NULL) 259 err(EXIT_FAILURE, "calloc"); 260 op->op_name = ns(name); 261 op->op_value = value ? ns(value) : NULL; 262 SLIST_INSERT_HEAD(&op_head, op, op_next); 263 } 264 265 outf = fopen(file, "w"); 266 if (outf == 0) 267 err(1, "%s", file); 268 while (!SLIST_EMPTY(&op_head)) { 269 op = SLIST_FIRST(&op_head); 270 /* was the option in the config file? */ 271 if (op->op_value) { 272 fprintf(outf, "#define %s %s\n", 273 op->op_name, op->op_value); 274 } 275 SLIST_REMOVE_HEAD(&op_head, op_next); 276 free(op->op_name); 277 free(op->op_value); 278 free(op); 279 } 280 (void)fclose(outf); 281} 282 283/* 284 * Find the filename to store the option spec into. 285 */ 286static char * 287tooption(char *name) 288{ 289 static char hbuf[MAXPATHLEN]; 290 char nbuf[MAXPATHLEN]; 291 struct opt_list *po; 292 293 /* "cannot happen"? the otab list should be complete.. */ 294 (void)strlcpy(nbuf, "options.h", sizeof(nbuf)); 295 296 SLIST_FOREACH(po, &otab, o_next) { 297 if (eq(po->o_name, name)) { 298 strlcpy(nbuf, po->o_file, sizeof(nbuf)); 299 break; 300 } 301 } 302 303 (void)strlcpy(hbuf, path(nbuf), sizeof(hbuf)); 304 return (hbuf); 305} 306 307 308static void 309check_duplicate(const char *fname, const char *this) 310{ 311 struct opt_list *po; 312 313 SLIST_FOREACH(po, &otab, o_next) { 314 if (eq(po->o_name, this)) { 315 printf("%s: Duplicate option %s.\n", 316 fname, this); 317 exit(1); 318 } 319 } 320} 321 322static void 323insert_option(const char *fname, char *this, char *val) 324{ 325 struct opt_list *po; 326 327 check_duplicate(fname, this); 328 po = (struct opt_list *) calloc(1, sizeof *po); 329 if (po == NULL) 330 err(EXIT_FAILURE, "calloc"); 331 po->o_name = this; 332 po->o_file = val; 333 po->o_flags = 0; 334 SLIST_INSERT_HEAD(&otab, po, o_next); 335} 336 337static void 338update_option(const char *this, char *val, int flags) 339{ 340 struct opt_list *po; 341 342 SLIST_FOREACH(po, &otab, o_next) { 343 if (eq(po->o_name, this)) { 344 free(po->o_file); 345 po->o_file = val; 346 po->o_flags = flags; 347 return; 348 } 349 } 350 printf("Compat option %s not listed in options file.\n", this); 351 exit(1); 352} 353 354static int 355read_option_file(const char *fname, int flags) 356{ 357 FILE *fp; 358 char *wd, *this, *val; 359 char genopt[MAXPATHLEN]; 360 361 fp = fopen(fname, "r"); 362 if (fp == 0) 363 return (0); 364 while ((wd = get_word(fp)) != (char *)EOF) { 365 if (wd == 0) 366 continue; 367 if (wd[0] == '#') { 368 while (((wd = get_word(fp)) != (char *)EOF) && wd) 369 continue; 370 continue; 371 } 372 this = ns(wd); 373 val = get_word(fp); 374 if (val == (char *)EOF) 375 return (1); 376 if (val == 0) { 377 if (flags) { 378 printf("%s: compat file requires two words " 379 "per line at %s\n", fname, this); 380 exit(1); 381 } 382 char *s = ns(this); 383 (void)snprintf(genopt, sizeof(genopt), "opt_%s.h", 384 lower(s)); 385 val = genopt; 386 free(s); 387 } 388 val = ns(val); 389 if (flags == 0) 390 insert_option(fname, this, val); 391 else 392 update_option(this, val, flags); 393 } 394 (void)fclose(fp); 395 return (1); 396} 397 398/* 399 * read the options and options.<machine> files 400 */ 401static void 402read_options(void) 403{ 404 char fname[MAXPATHLEN]; 405 406 SLIST_INIT(&otab); 407 read_option_file("../../conf/options", 0); 408 (void)snprintf(fname, sizeof fname, "../../conf/options.%s", 409 machinename); 410 if (!read_option_file(fname, 0)) { 411 (void)snprintf(fname, sizeof fname, "options.%s", machinename); 412 read_option_file(fname, 0); 413 } 414 read_option_file("../../conf/options-compat", OL_ALIAS); 415} 416 417static char * 418lower(char *str) 419{ 420 char *cp = str; 421 422 while (*str) { 423 if (isupper(*str)) 424 *str = tolower(*str); 425 str++; 426 } 427 return (cp); 428} 429