mkoptions.c revision 66457
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 66457 2000-09-29 13:36:47Z dfr $"; 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 "config.h" 52#include "y.tab.h" 53 54static struct users { 55 int u_default; 56 int u_min; 57 int u_max; 58} users[] = { 59 { 8, 2, 512 }, /* MACHINE_I386 */ 60 { 8, 2, 512 }, /* MACHINE_PC98 */ 61 { 8, 2, 512 }, /* MACHINE_ALPHA */ 62 { 8, 2, 512 }, /* MACHINE_IA64 */ 63}; 64#define NUSERS (sizeof (users) / sizeof (users[0])) 65 66static char *lower(char *); 67static void read_options(void); 68static void do_option(char *); 69static char *tooption(char *); 70 71void 72options(void) 73{ 74 char buf[40]; 75 struct cputype *cp; 76 struct opt_list *ol; 77 struct opt *op; 78 struct users *up; 79 80 /* Fake the cpu types as options. */ 81 for (cp = cputype; cp != NULL; cp = cp->cpu_next) { 82 op = (struct opt *)malloc(sizeof(*op)); 83 memset(op, 0, sizeof(*op)); 84 op->op_name = ns(cp->cpu_name); 85 op->op_next = opt; 86 opt = op; 87 } 88 89 /* Initialize `maxusers'. */ 90 if ((unsigned)machine > NUSERS) { 91 printf("maxusers config info isn't present, using i386\n"); 92 up = &users[MACHINE_I386 - 1]; 93 } else 94 up = &users[machine - 1]; 95 if (maxusers == 0) { 96 printf("maxusers not specified; %d assumed\n", up->u_default); 97 maxusers = up->u_default; 98 } else if (maxusers < up->u_min) { 99 printf("minimum of %d maxusers assumed\n", up->u_min); 100 maxusers = up->u_min; 101 } else if (maxusers > up->u_max) 102 printf("warning: maxusers > %d (%d)\n", up->u_max, maxusers); 103 104 /* Fake MAXUSERS as an option. */ 105 op = (struct opt *)malloc(sizeof(*op)); 106 memset(op, 0, sizeof(*op)); 107 op->op_name = "MAXUSERS"; 108 snprintf(buf, sizeof(buf), "%d", maxusers); 109 op->op_value = ns(buf); 110 op->op_next = opt; 111 opt = op; 112 113 read_options(); 114 for (ol = otab; ol != 0; ol = ol->o_next) 115 do_option(ol->o_name); 116 for (op = opt; op; op = op->op_next) { 117 if (!op->op_ownfile) { 118 printf("%s:%d: unknown option \"%s\"\n", 119 PREFIX, op->op_line, op->op_name); 120 exit(1); 121 } 122 } 123} 124 125/* 126 * Generate an <options>.h file 127 */ 128 129static void 130do_option(char *name) 131{ 132 char *basefile, *file, *inw; 133 struct opt_list *ol; 134 struct opt *op, *op_head, *topp; 135 FILE *inf, *outf; 136 char *value; 137 char *oldvalue; 138 int seen; 139 int tidy; 140 141 file = tooption(name); 142 143 /* 144 * Check to see if the option was specified.. 145 */ 146 value = NULL; 147 for (op = opt; op; op = op->op_next) { 148 if (eq(name, op->op_name)) { 149 oldvalue = value; 150 value = op->op_value; 151 if (value == NULL) 152 value = ns("1"); 153 if (oldvalue != NULL && !eq(value, oldvalue)) 154 printf( 155 "%s:%d: option \"%s\" redefined from %s to %s\n", 156 PREFIX, op->op_line, op->op_name, oldvalue, 157 value); 158 op->op_ownfile++; 159 } 160 } 161 162 inf = fopen(file, "r"); 163 if (inf == 0) { 164 outf = fopen(file, "w"); 165 if (outf == 0) 166 err(1, "%s", file); 167 168 /* was the option in the config file? */ 169 if (value) { 170 fprintf(outf, "#define %s %s\n", name, value); 171 } /* else empty file */ 172 173 (void) fclose(outf); 174 return; 175 } 176 basefile = ""; 177 for (ol = otab; ol != 0; ol = ol->o_next) 178 if (eq(name, ol->o_name)) { 179 basefile = ol->o_file; 180 break; 181 } 182 oldvalue = NULL; 183 op_head = NULL; 184 seen = 0; 185 tidy = 0; 186 for (;;) { 187 char *cp; 188 char *invalue; 189 190 /* get the #define */ 191 if ((inw = get_word(inf)) == 0 || inw == (char *)EOF) 192 break; 193 /* get the option name */ 194 if ((inw = get_word(inf)) == 0 || inw == (char *)EOF) 195 break; 196 inw = ns(inw); 197 /* get the option value */ 198 if ((cp = get_word(inf)) == 0 || cp == (char *)EOF) 199 break; 200 /* option value */ 201 invalue = ns(cp); /* malloced */ 202 if (eq(inw, name)) { 203 oldvalue = invalue; 204 invalue = value; 205 seen++; 206 } 207 for (ol = otab; ol != 0; ol = ol->o_next) 208 if (eq(inw, ol->o_name)) 209 break; 210 if (!eq(inw, name) && !ol) { 211 printf("WARNING: unknown option `%s' removed from %s\n", 212 inw, file); 213 tidy++; 214 } else if (ol != NULL && !eq(basefile, ol->o_file)) { 215 printf("WARNING: option `%s' moved from %s to %s\n", 216 inw, basefile, ol->o_file); 217 tidy++; 218 } else { 219 op = (struct opt *) malloc(sizeof *op); 220 bzero(op, sizeof(*op)); 221 op->op_name = inw; 222 op->op_value = invalue; 223 op->op_next = op_head; 224 op_head = op; 225 } 226 227 /* EOL? */ 228 cp = get_word(inf); 229 if (cp == (char *)EOF) 230 break; 231 } 232 (void) fclose(inf); 233 if (!tidy && ((value == NULL && oldvalue == NULL) || 234 (value && oldvalue && eq(value, oldvalue)))) { 235 for (op = op_head; op != NULL; op = topp) { 236 topp = op->op_next; 237 free(op->op_name); 238 free(op->op_value); 239 free(op); 240 } 241 return; 242 } 243 244 if (value && !seen) { 245 /* New option appears */ 246 op = (struct opt *) malloc(sizeof *op); 247 bzero(op, sizeof(*op)); 248 op->op_name = ns(name); 249 op->op_value = value ? ns(value) : NULL; 250 op->op_next = op_head; 251 op_head = op; 252 } 253 254 outf = fopen(file, "w"); 255 if (outf == 0) 256 err(1, "%s", file); 257 for (op = op_head; op != NULL; op = topp) { 258 /* was the option in the config file? */ 259 if (op->op_value) { 260 fprintf(outf, "#define %s %s\n", 261 op->op_name, op->op_value); 262 } 263 topp = op->op_next; 264 free(op->op_name); 265 free(op->op_value); 266 free(op); 267 } 268 (void) fclose(outf); 269} 270 271/* 272 * Find the filename to store the option spec into. 273 */ 274static char * 275tooption(char *name) 276{ 277 static char hbuf[80]; 278 char nbuf[80]; 279 struct opt_list *po; 280 281 /* "cannot happen"? the otab list should be complete.. */ 282 (void) strcpy(nbuf, "options.h"); 283 284 for (po = otab ; po != 0; po = po->o_next) { 285 if (eq(po->o_name, name)) { 286 strcpy(nbuf, po->o_file); 287 break; 288 } 289 } 290 291 (void) strcpy(hbuf, path(nbuf)); 292 return (hbuf); 293} 294 295/* 296 * read the options and options.<machine> files 297 */ 298static void 299read_options(void) 300{ 301 FILE *fp; 302 char fname[80]; 303 char *wd, *this, *val; 304 struct opt_list *po; 305 int first = 1; 306 char genopt[80]; 307 308 otab = 0; 309 if (ident == NULL) { 310 printf("no ident line specified\n"); 311 exit(1); 312 } 313 (void) snprintf(fname, sizeof fname, "../../conf/options"); 314openit: 315 fp = fopen(fname, "r"); 316 if (fp == 0) { 317 return; 318 } 319next: 320 wd = get_word(fp); 321 if (wd == (char *)EOF) { 322 (void) fclose(fp); 323 if (first == 1) { 324 first++; 325 (void) snprintf(fname, sizeof fname, "../../conf/options.%s", machinename); 326 fp = fopen(fname, "r"); 327 if (fp != 0) 328 goto next; 329 (void) snprintf(fname, sizeof fname, "options.%s", machinename); 330 goto openit; 331 } 332 if (first == 2) { 333 first++; 334 (void) snprintf(fname, sizeof fname, "options.%s", raisestr(ident)); 335 fp = fopen(fname, "r"); 336 if (fp != 0) 337 goto next; 338 } 339 return; 340 } 341 if (wd == 0) 342 goto next; 343 if (wd[0] == '#') 344 { 345 while (((wd = get_word(fp)) != (char *)EOF) && wd) 346 ; 347 goto next; 348 } 349 this = ns(wd); 350 val = get_word(fp); 351 if (val == (char *)EOF) 352 return; 353 if (val == 0) { 354 char *s = ns(this); 355 (void) snprintf(genopt, sizeof genopt, "opt_%s.h", lower(s)); 356 val = genopt; 357 free(s); 358 } 359 val = ns(val); 360 361 for (po = otab ; po != 0; po = po->o_next) { 362 if (eq(po->o_name, this)) { 363 printf("%s: Duplicate option %s.\n", 364 fname, this); 365 exit(1); 366 } 367 } 368 369 po = (struct opt_list *) malloc(sizeof *po); 370 bzero(po, sizeof(*po)); 371 po->o_name = this; 372 po->o_file = val; 373 po->o_next = otab; 374 otab = po; 375 376 goto next; 377} 378 379static char * 380lower(char *str) 381{ 382 char *cp = str; 383 384 while (*str) { 385 if (isupper(*str)) 386 *str = tolower(*str); 387 str++; 388 } 389 return (cp); 390} 391