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