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