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