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