mkoptions.c revision 133248
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 133248 2004-08-07 04:19:37Z 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 *)malloc(sizeof(*op)); 73 memset(op, 0, sizeof(*op)); 74 op->op_name = ns(cp->cpu_name); 75 SLIST_INSERT_HEAD(&opt, op, op_next); 76 } 77 78 if (maxusers == 0) { 79 /* printf("maxusers not specified; will auto-size\n"); */ 80 } else if (maxusers < users.u_min) { 81 printf("minimum of %d maxusers assumed\n", users.u_min); 82 maxusers = users.u_min; 83 } else if (maxusers > users.u_max) 84 printf("warning: maxusers > %d (%d)\n", users.u_max, maxusers); 85 86 /* Fake MAXUSERS as an option. */ 87 op = (struct opt *)malloc(sizeof(*op)); 88 memset(op, 0, sizeof(*op)); 89 op->op_name = ns("MAXUSERS"); 90 snprintf(buf, sizeof(buf), "%d", maxusers); 91 op->op_value = ns(buf); 92 SLIST_INSERT_HEAD(&opt, op, op_next); 93 94 read_options(); 95 SLIST_FOREACH(ol, &otab, o_next) 96 do_option(ol->o_name); 97 SLIST_FOREACH(op, &opt, op_next) { 98 if (!op->op_ownfile && strncmp(op->op_name, "DEV_", 4)) { 99 printf("%s: unknown option \"%s\"\n", 100 PREFIX, op->op_name); 101 exit(1); 102 } 103 } 104} 105 106/* 107 * Generate an <options>.h file 108 */ 109 110static void 111do_option(char *name) 112{ 113 char *file, *inw; 114 const char *basefile; 115 struct opt_list *ol; 116 struct opt *op; 117 struct opt_head op_head; 118 FILE *inf, *outf; 119 char *value; 120 char *oldvalue; 121 int seen; 122 int tidy; 123 124 file = tooption(name); 125 126 /* 127 * Check to see if the option was specified.. 128 */ 129 value = NULL; 130 SLIST_FOREACH(op, &opt, op_next) { 131 if (eq(name, op->op_name)) { 132 oldvalue = value; 133 value = op->op_value; 134 if (value == NULL) 135 value = ns("1"); 136 if (oldvalue != NULL && !eq(value, oldvalue)) 137 printf( 138 "%s: option \"%s\" redefined from %s to %s\n", 139 PREFIX, op->op_name, oldvalue, 140 value); 141 op->op_ownfile++; 142 } 143 } 144 145 remember(file); 146 inf = fopen(file, "r"); 147 if (inf == 0) { 148 outf = fopen(file, "w"); 149 if (outf == 0) 150 err(1, "%s", file); 151 152 /* was the option in the config file? */ 153 if (value) { 154 fprintf(outf, "#define %s %s\n", name, value); 155 } /* else empty file */ 156 157 (void) fclose(outf); 158 return; 159 } 160 basefile = ""; 161 SLIST_FOREACH(ol, &otab, o_next) 162 if (eq(name, ol->o_name)) { 163 basefile = ol->o_file; 164 break; 165 } 166 oldvalue = NULL; 167 SLIST_INIT(&op_head); 168 seen = 0; 169 tidy = 0; 170 for (;;) { 171 char *cp; 172 char *invalue; 173 174 /* get the #define */ 175 if ((inw = get_word(inf)) == 0 || inw == (char *)EOF) 176 break; 177 /* get the option name */ 178 if ((inw = get_word(inf)) == 0 || inw == (char *)EOF) 179 break; 180 inw = ns(inw); 181 /* get the option value */ 182 if ((cp = get_word(inf)) == 0 || cp == (char *)EOF) 183 break; 184 /* option value */ 185 invalue = ns(cp); /* malloced */ 186 if (eq(inw, name)) { 187 oldvalue = invalue; 188 invalue = value; 189 seen++; 190 } 191 SLIST_FOREACH(ol, &otab, o_next) 192 if (eq(inw, ol->o_name)) 193 break; 194 if (!eq(inw, name) && !ol) { 195 printf("WARNING: unknown option `%s' removed from %s\n", 196 inw, file); 197 tidy++; 198 } else if (ol != NULL && !eq(basefile, ol->o_file)) { 199 printf("WARNING: option `%s' moved from %s to %s\n", 200 inw, basefile, ol->o_file); 201 tidy++; 202 } else { 203 op = (struct opt *) malloc(sizeof *op); 204 bzero(op, sizeof(*op)); 205 op->op_name = inw; 206 op->op_value = invalue; 207 SLIST_INSERT_HEAD(&op_head, op, op_next); 208 } 209 210 /* EOL? */ 211 cp = get_word(inf); 212 if (cp == (char *)EOF) 213 break; 214 } 215 (void) fclose(inf); 216 if (!tidy && ((value == NULL && oldvalue == NULL) || 217 (value && oldvalue && eq(value, oldvalue)))) { 218 while (!SLIST_EMPTY(&op_head)) { 219 op = SLIST_FIRST(&op_head); 220 SLIST_REMOVE_HEAD(&op_head, op_next); 221 free(op->op_name); 222 free(op->op_value); 223 free(op); 224 } 225 return; 226 } 227 228 if (value && !seen) { 229 /* New option appears */ 230 op = (struct opt *) malloc(sizeof *op); 231 bzero(op, sizeof(*op)); 232 op->op_name = ns(name); 233 op->op_value = value ? ns(value) : NULL; 234 SLIST_INSERT_HEAD(&op_head, op, op_next); 235 } 236 237 outf = fopen(file, "w"); 238 if (outf == 0) 239 err(1, "%s", file); 240 while (!SLIST_EMPTY(&op_head)) { 241 op = SLIST_FIRST(&op_head); 242 /* was the option in the config file? */ 243 if (op->op_value) { 244 fprintf(outf, "#define %s %s\n", 245 op->op_name, op->op_value); 246 } 247 SLIST_REMOVE_HEAD(&op_head, op_next); 248 free(op->op_name); 249 free(op->op_value); 250 free(op); 251 } 252 (void) fclose(outf); 253} 254 255/* 256 * Find the filename to store the option spec into. 257 */ 258static char * 259tooption(char *name) 260{ 261 static char hbuf[MAXPATHLEN]; 262 char nbuf[MAXPATHLEN]; 263 struct opt_list *po; 264 265 /* "cannot happen"? the otab list should be complete.. */ 266 (void) strlcpy(nbuf, "options.h", sizeof(nbuf)); 267 268 SLIST_FOREACH(po, &otab, o_next) { 269 if (eq(po->o_name, name)) { 270 strlcpy(nbuf, po->o_file, sizeof(nbuf)); 271 break; 272 } 273 } 274 275 (void) strlcpy(hbuf, path(nbuf), sizeof(hbuf)); 276 return (hbuf); 277} 278 279/* 280 * read the options and options.<machine> files 281 */ 282static void 283read_options(void) 284{ 285 FILE *fp; 286 char fname[MAXPATHLEN]; 287 char *wd, *this, *val; 288 struct opt_list *po; 289 int first = 1; 290 char genopt[MAXPATHLEN]; 291 292 SLIST_INIT(&otab); 293 if (ident == NULL) { 294 printf("no ident line specified\n"); 295 exit(1); 296 } 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 *) malloc(sizeof *po); 347 bzero(po, sizeof(*po)); 348 po->o_name = this; 349 po->o_file = val; 350 SLIST_INSERT_HEAD(&otab, po, o_next); 351 352 goto next; 353} 354 355static char * 356lower(char *str) 357{ 358 char *cp = str; 359 360 while (*str) { 361 if (isupper(*str)) 362 *str = tolower(*str); 363 str++; 364 } 365 return (cp); 366} 367