mkoptions.c revision 207263
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 207263 2010-04-27 05:38:26Z imp $"; 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 SLIST_FOREACH(op, &opt, op_next) { 98 SLIST_FOREACH(ol, &otab, o_next) { 99 if (eq(op->op_name, ol->o_name) && 100 (ol->o_flags & OL_ALIAS)) { 101 printf("Mapping option %s to %s.\n", 102 op->op_name, ol->o_file); 103 op->op_name = ol->o_file; 104 break; 105 } 106 } 107 } 108 SLIST_FOREACH(ol, &otab, o_next) 109 do_option(ol->o_name); 110 SLIST_FOREACH(op, &opt, op_next) { 111 if (!op->op_ownfile && strncmp(op->op_name, "DEV_", 4)) { 112 printf("%s: unknown option \"%s\"\n", 113 PREFIX, op->op_name); 114 exit(1); 115 } 116 } 117} 118 119/* 120 * Generate an <options>.h file 121 */ 122 123static void 124do_option(char *name) 125{ 126 char *file, *inw; 127 const char *basefile; 128 struct opt_list *ol; 129 struct opt *op; 130 struct opt_head op_head; 131 FILE *inf, *outf; 132 char *value; 133 char *oldvalue; 134 int seen; 135 int tidy; 136 137 file = tooption(name); 138 /* 139 * Check to see if the option was specified.. 140 */ 141 value = NULL; 142 SLIST_FOREACH(op, &opt, op_next) { 143 if (eq(name, op->op_name)) { 144 oldvalue = value; 145 value = op->op_value; 146 if (value == NULL) 147 value = ns("1"); 148 if (oldvalue != NULL && !eq(value, oldvalue)) 149 printf( 150 "%s: option \"%s\" redefined from %s to %s\n", 151 PREFIX, op->op_name, oldvalue, 152 value); 153 op->op_ownfile++; 154 } 155 } 156 157 remember(file); 158 inf = fopen(file, "r"); 159 if (inf == 0) { 160 outf = fopen(file, "w"); 161 if (outf == 0) 162 err(1, "%s", file); 163 164 /* was the option in the config file? */ 165 if (value) { 166 fprintf(outf, "#define %s %s\n", name, value); 167 } /* else empty file */ 168 169 (void)fclose(outf); 170 return; 171 } 172 basefile = ""; 173 SLIST_FOREACH(ol, &otab, o_next) 174 if (eq(name, ol->o_name)) { 175 basefile = ol->o_file; 176 break; 177 } 178 oldvalue = NULL; 179 SLIST_INIT(&op_head); 180 seen = 0; 181 tidy = 0; 182 for (;;) { 183 char *cp; 184 char *invalue; 185 186 /* get the #define */ 187 if ((inw = get_word(inf)) == 0 || inw == (char *)EOF) 188 break; 189 /* get the option name */ 190 if ((inw = get_word(inf)) == 0 || inw == (char *)EOF) 191 break; 192 inw = ns(inw); 193 /* get the option value */ 194 if ((cp = get_word(inf)) == 0 || cp == (char *)EOF) 195 break; 196 /* option value */ 197 invalue = ns(cp); /* malloced */ 198 if (eq(inw, name)) { 199 oldvalue = invalue; 200 invalue = value; 201 seen++; 202 } 203 SLIST_FOREACH(ol, &otab, o_next) 204 if (eq(inw, ol->o_name)) 205 break; 206 if (!eq(inw, name) && !ol) { 207 printf("WARNING: unknown option `%s' removed from %s\n", 208 inw, file); 209 tidy++; 210 } else if (ol != NULL && !eq(basefile, ol->o_file)) { 211 printf("WARNING: option `%s' moved from %s to %s\n", 212 inw, basefile, ol->o_file); 213 tidy++; 214 } else { 215 op = (struct opt *) calloc(1, sizeof *op); 216 if (op == NULL) 217 err(EXIT_FAILURE, "calloc"); 218 op->op_name = inw; 219 op->op_value = invalue; 220 SLIST_INSERT_HEAD(&op_head, op, op_next); 221 } 222 223 /* EOL? */ 224 cp = get_word(inf); 225 if (cp == (char *)EOF) 226 break; 227 } 228 (void)fclose(inf); 229 if (!tidy && ((value == NULL && oldvalue == NULL) || 230 (value && oldvalue && eq(value, oldvalue)))) { 231 while (!SLIST_EMPTY(&op_head)) { 232 op = SLIST_FIRST(&op_head); 233 SLIST_REMOVE_HEAD(&op_head, op_next); 234 free(op->op_name); 235 free(op->op_value); 236 free(op); 237 } 238 return; 239 } 240 241 if (value && !seen) { 242 /* New option appears */ 243 op = (struct opt *) calloc(1, sizeof *op); 244 if (op == NULL) 245 err(EXIT_FAILURE, "calloc"); 246 op->op_name = ns(name); 247 op->op_value = value ? ns(value) : NULL; 248 SLIST_INSERT_HEAD(&op_head, op, op_next); 249 } 250 251 outf = fopen(file, "w"); 252 if (outf == 0) 253 err(1, "%s", file); 254 while (!SLIST_EMPTY(&op_head)) { 255 op = SLIST_FIRST(&op_head); 256 /* was the option in the config file? */ 257 if (op->op_value) { 258 fprintf(outf, "#define %s %s\n", 259 op->op_name, op->op_value); 260 } 261 SLIST_REMOVE_HEAD(&op_head, op_next); 262 free(op->op_name); 263 free(op->op_value); 264 free(op); 265 } 266 (void)fclose(outf); 267} 268 269/* 270 * Find the filename to store the option spec into. 271 */ 272static char * 273tooption(char *name) 274{ 275 static char hbuf[MAXPATHLEN]; 276 char nbuf[MAXPATHLEN]; 277 struct opt_list *po; 278 279 /* "cannot happen"? the otab list should be complete.. */ 280 (void)strlcpy(nbuf, "options.h", sizeof(nbuf)); 281 282 SLIST_FOREACH(po, &otab, o_next) { 283 if (eq(po->o_name, name)) { 284 strlcpy(nbuf, po->o_file, sizeof(nbuf)); 285 break; 286 } 287 } 288 289 (void)strlcpy(hbuf, path(nbuf), sizeof(hbuf)); 290 return (hbuf); 291} 292 293 294static void 295insert_option(char *this, char *val, int flags) 296{ 297 struct opt_list *po; 298 299 po = (struct opt_list *) calloc(1, sizeof *po); 300 if (po == NULL) 301 err(EXIT_FAILURE, "calloc"); 302 po->o_name = this; 303 po->o_file = val; 304 po->o_flags = flags; 305 SLIST_INSERT_HEAD(&otab, po, o_next); 306} 307 308 309static void 310check_duplicate(const char *fname, const char *this) 311{ 312 struct opt_list *po; 313 314 SLIST_FOREACH(po, &otab, o_next) { 315 if (eq(po->o_name, this)) { 316 printf("%s: Duplicate option %s.\n", 317 fname, this); 318 exit(1); 319 } 320 } 321} 322 323static int 324read_option_file(const char *fname, int flags) 325{ 326 FILE *fp; 327 char *wd, *this, *val; 328 char genopt[MAXPATHLEN]; 329 330 fp = fopen(fname, "r"); 331 if (fp == 0) 332 return (0); 333 while ((wd = get_word(fp)) != (char *)EOF) { 334 if (wd == 0) 335 continue; 336 if (wd[0] == '#') { 337 while (((wd = get_word(fp)) != (char *)EOF) && wd) 338 continue; 339 continue; 340 } 341 this = ns(wd); 342 val = get_word(fp); 343 if (val == (char *)EOF) 344 return (1); 345 if (val == 0) { 346 if (flags) { 347 printf("%s: compat file requires two words " 348 "per line at %s\n", fname, this); 349 exit(1); 350 } 351 char *s = ns(this); 352 (void)snprintf(genopt, sizeof(genopt), "opt_%s.h", 353 lower(s)); 354 val = genopt; 355 free(s); 356 } 357 val = ns(val); 358 check_duplicate(fname, this); 359 insert_option(this, val, flags); 360 } 361 (void)fclose(fp); 362 return (1); 363} 364 365/* 366 * read the options and options.<machine> files 367 */ 368static void 369read_options(void) 370{ 371 char fname[MAXPATHLEN]; 372 373 SLIST_INIT(&otab); 374 read_option_file("../../conf/options", 0); 375 (void)snprintf(fname, sizeof fname, "../../conf/options.%s", 376 machinename); 377 if (!read_option_file(fname, 0)) { 378 (void)snprintf(fname, sizeof fname, "options.%s", machinename); 379 read_option_file(fname, 0); 380 } 381 read_option_file("../../conf/options-compat", OL_ALIAS); 382} 383 384static char * 385lower(char *str) 386{ 387 char *cp = str; 388 389 while (*str) { 390 if (isupper(*str)) 391 *str = tolower(*str); 392 str++; 393 } 394 return (cp); 395} 396