1/* 2 * Copyright (c) 1980, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 4. Neither the name of the University nor the names of its contributors 14 * may be used to endorse or promote products derived from this software 15 * without specific prior written permission. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 */ 29 30#ifndef lint 31static const char copyright[] = 32"@(#) Copyright (c) 1980, 1993\n\ 33 The Regents of the University of California. All rights reserved.\n"; 34#endif /* not lint */ 35 36#ifndef lint 37#if 0 38static char sccsid[] = "@(#)main.c 8.1 (Berkeley) 6/6/93"; 39#endif 40static const char rcsid[] =
| 1/* 2 * Copyright (c) 1980, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 4. Neither the name of the University nor the names of its contributors 14 * may be used to endorse or promote products derived from this software 15 * without specific prior written permission. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 */ 29 30#ifndef lint 31static const char copyright[] = 32"@(#) Copyright (c) 1980, 1993\n\ 33 The Regents of the University of California. All rights reserved.\n"; 34#endif /* not lint */ 35 36#ifndef lint 37#if 0 38static char sccsid[] = "@(#)main.c 8.1 (Berkeley) 6/6/93"; 39#endif 40static const char rcsid[] =
|
41 "$FreeBSD: head/usr.sbin/config/main.c 169507 2007-05-12 19:38:18Z wkoszek $";
| 41 "$FreeBSD: head/usr.sbin/config/main.c 169512 2007-05-12 22:37:52Z wkoszek $";
|
42#endif /* not lint */ 43 44#include <sys/types.h> 45#include <sys/stat.h> 46#include <sys/sbuf.h> 47#include <sys/file.h> 48#include <sys/mman.h> 49#include <sys/param.h> 50 51#include <assert.h> 52#include <ctype.h> 53#include <err.h> 54#include <stdio.h>
| 42#endif /* not lint */ 43 44#include <sys/types.h> 45#include <sys/stat.h> 46#include <sys/sbuf.h> 47#include <sys/file.h> 48#include <sys/mman.h> 49#include <sys/param.h> 50 51#include <assert.h> 52#include <ctype.h> 53#include <err.h> 54#include <stdio.h>
|
| 55#include <string.h>
|
55#include <sysexits.h> 56#include <unistd.h> 57#include <dirent.h> 58#include "y.tab.h" 59#include "config.h" 60#include "configvers.h" 61 62#ifndef TRUE 63#define TRUE (1) 64#endif 65 66#ifndef FALSE 67#define FALSE (0) 68#endif 69 70#define CDIR "../compile/" 71 72char * PREFIX; 73char destdir[MAXPATHLEN]; 74char srcdir[MAXPATHLEN]; 75 76int debugging; 77int profiling; 78int found_defaults; 79int incignore; 80 81/* 82 * Preserve old behaviour in INCLUDE_CONFIG_FILE handling (files are included 83 * literally). 84 */ 85int filebased = 0; 86 87static void configfile(void); 88static void get_srcdir(void); 89static void usage(void); 90static void cleanheaders(char *); 91static void kernconfdump(const char *); 92 93struct hdr_list { 94 char *h_name; 95 struct hdr_list *h_next; 96} *htab; 97 98/* 99 * Config builds a set of files for building a UNIX 100 * system given a description of the desired system. 101 */ 102int 103main(int argc, char **argv) 104{ 105 106 struct stat buf; 107 int ch, len; 108 char *p; 109 char xxx[MAXPATHLEN]; 110 char *kernfile; 111 112 kernfile = NULL; 113 while ((ch = getopt(argc, argv, "Cd:gpVx:")) != -1) 114 switch (ch) { 115 case 'C': 116 filebased = 1; 117 break; 118 case 'd': 119 if (*destdir == '\0') 120 strlcpy(destdir, optarg, sizeof(destdir)); 121 else 122 errx(2, "directory already set"); 123 break; 124 case 'g': 125 debugging++; 126 break; 127 case 'p': 128 profiling++; 129 break; 130 case 'V': 131 printf("%d\n", CONFIGVERS); 132 exit(0); 133 case 'x': 134 kernfile = optarg; 135 break; 136 case '?': 137 default: 138 usage(); 139 } 140 argc -= optind; 141 argv += optind; 142 143 if (kernfile != NULL) { 144 kernconfdump(kernfile); 145 exit(EXIT_SUCCESS); 146 } 147 148 if (argc != 1) 149 usage(); 150 151 PREFIX = *argv; 152 /* 153 * We mark lack of DEFAULTS here. Once we hit EOF in PREFIX, yywrap() 154 * will try to bring DEFAULTS to the playground, if this exists. 155 */ 156 found_defaults = 0; 157 if (freopen(PREFIX, "r", stdin) == NULL) 158 err(2, "%s", PREFIX); 159 yyfile = PREFIX; 160 if (*destdir != '\0') { 161 len = strlen(destdir); 162 while (len > 1 && destdir[len - 1] == '/') 163 destdir[--len] = '\0'; 164 get_srcdir(); 165 } else { 166 strlcpy(destdir, CDIR, sizeof(destdir)); 167 strlcat(destdir, PREFIX, sizeof(destdir)); 168 } 169 170 p = path((char *)NULL); 171 if (stat(p, &buf)) { 172 if (mkdir(p, 0777)) 173 err(2, "%s", p); 174 } else if (!S_ISDIR(buf.st_mode)) 175 errx(2, "%s isn't a directory", p); 176 177 SLIST_INIT(&cputype); 178 SLIST_INIT(&mkopt); 179 SLIST_INIT(&opt); 180 SLIST_INIT(&rmopts); 181 STAILQ_INIT(&cfgfiles); 182 STAILQ_INIT(&dtab); 183 STAILQ_INIT(&fntab); 184 STAILQ_INIT(&ftab); 185 STAILQ_INIT(&hints); 186 STAILQ_INIT(&rmdtab); 187 if (yyparse()) 188 exit(3); 189 190 /* 191 * Ensure that required elements (machine, cpu, ident) are present. 192 */ 193 if (machinename == NULL) { 194 printf("Specify machine type, e.g. ``machine i386''\n"); 195 exit(1); 196 } 197 if (ident == NULL) { 198 printf("no ident line specified\n"); 199 exit(1); 200 } 201 if (SLIST_EMPTY(&cputype)) { 202 printf("cpu type must be specified\n"); 203 exit(1); 204 } 205 206 /* 207 * make symbolic links in compilation directory 208 * for "sys" (to make genassym.c work along with #include <sys/xxx>) 209 * and similarly for "machine". 210 */ 211 if (*srcdir == '\0') 212 (void)snprintf(xxx, sizeof(xxx), "../../include"); 213 else 214 (void)snprintf(xxx, sizeof(xxx), "%s/%s/include", 215 srcdir, machinename); 216 (void) unlink(path("machine")); 217 (void) symlink(xxx, path("machine")); 218 if (strcmp(machinename, machinearch) != 0) { 219 /* 220 * make symbolic links in compilation directory for 221 * machinearch, if it is different than machinename. 222 */ 223 if (*srcdir == '\0') 224 (void)snprintf(xxx, sizeof(xxx), "../../../%s/include", 225 machinearch); 226 else 227 (void)snprintf(xxx, sizeof(xxx), "%s/%s/include", 228 srcdir, machinearch); 229 (void) unlink(path(machinearch)); 230 (void) symlink(xxx, path(machinearch)); 231 } 232 configfile(); /* put config file into kernel*/ 233 options(); /* make options .h files */ 234 makefile(); /* build Makefile */ 235 makeenv(); /* build env.c */ 236 makehints(); /* build hints.c */ 237 headers(); /* make a lot of .h files */ 238 cleanheaders(p); 239 printf("Kernel build directory is %s\n", p); 240 printf("Don't forget to do ``make cleandepend && make depend''\n"); 241 exit(0); 242} 243 244/* 245 * get_srcdir 246 * determine the root of the kernel source tree 247 * and save that in srcdir. 248 */ 249static void 250get_srcdir(void) 251{ 252 253 if (realpath("../..", srcdir) == NULL) 254 errx(2, "Unable to find root of source tree"); 255} 256 257static void 258usage(void) 259{ 260 261 fprintf(stderr, "usage: config [-CgpV] [-d destdir] sysname\n"); 262 fprintf(stderr, " config -x kernel\n"); 263 exit(EX_USAGE); 264} 265 266/* 267 * get_word 268 * returns EOF on end of file 269 * NULL on end of line 270 * pointer to the word otherwise 271 */ 272char * 273get_word(FILE *fp) 274{ 275 static char line[80]; 276 int ch; 277 char *cp; 278 int escaped_nl = 0; 279 280begin: 281 while ((ch = getc(fp)) != EOF) 282 if (ch != ' ' && ch != '\t') 283 break; 284 if (ch == EOF) 285 return ((char *)EOF); 286 if (ch == '\\'){ 287 escaped_nl = 1; 288 goto begin; 289 } 290 if (ch == '\n') { 291 if (escaped_nl){ 292 escaped_nl = 0; 293 goto begin; 294 } 295 else 296 return (NULL); 297 } 298 cp = line; 299 *cp++ = ch; 300 while ((ch = getc(fp)) != EOF) { 301 if (isspace(ch)) 302 break; 303 *cp++ = ch; 304 } 305 *cp = 0; 306 if (ch == EOF) 307 return ((char *)EOF); 308 (void) ungetc(ch, fp); 309 return (line); 310} 311 312/* 313 * get_quoted_word 314 * like get_word but will accept something in double or single quotes 315 * (to allow embedded spaces). 316 */ 317char * 318get_quoted_word(FILE *fp) 319{ 320 static char line[256]; 321 int ch; 322 char *cp; 323 int escaped_nl = 0; 324 325begin: 326 while ((ch = getc(fp)) != EOF) 327 if (ch != ' ' && ch != '\t') 328 break; 329 if (ch == EOF) 330 return ((char *)EOF); 331 if (ch == '\\'){ 332 escaped_nl = 1; 333 goto begin; 334 } 335 if (ch == '\n') { 336 if (escaped_nl){ 337 escaped_nl = 0; 338 goto begin; 339 } 340 else 341 return (NULL); 342 } 343 cp = line; 344 if (ch == '"' || ch == '\'') { 345 int quote = ch; 346 347 while ((ch = getc(fp)) != EOF) { 348 if (ch == quote) 349 break; 350 if (ch == '\n') { 351 *cp = 0; 352 printf("config: missing quote reading `%s'\n", 353 line); 354 exit(2); 355 } 356 *cp++ = ch; 357 } 358 } else { 359 *cp++ = ch; 360 while ((ch = getc(fp)) != EOF) { 361 if (isspace(ch)) 362 break; 363 *cp++ = ch; 364 } 365 if (ch != EOF) 366 (void) ungetc(ch, fp); 367 } 368 *cp = 0; 369 if (ch == EOF) 370 return ((char *)EOF); 371 return (line); 372} 373 374/* 375 * prepend the path to a filename 376 */ 377char * 378path(const char *file) 379{ 380 char *cp = NULL; 381 382 if (file) 383 asprintf(&cp, "%s/%s", destdir, file); 384 else 385 cp = strdup(destdir); 386 return (cp); 387} 388 389/* 390 * Generate configuration file based on actual settings. With this mode, user 391 * will be able to obtain and build conifguration file with one command. 392 */ 393static void 394configfile_dynamic(struct sbuf *sb) 395{ 396 struct cputype *cput; 397 struct device *d; 398 struct opt *ol; 399 char *lend;
| 56#include <sysexits.h> 57#include <unistd.h> 58#include <dirent.h> 59#include "y.tab.h" 60#include "config.h" 61#include "configvers.h" 62 63#ifndef TRUE 64#define TRUE (1) 65#endif 66 67#ifndef FALSE 68#define FALSE (0) 69#endif 70 71#define CDIR "../compile/" 72 73char * PREFIX; 74char destdir[MAXPATHLEN]; 75char srcdir[MAXPATHLEN]; 76 77int debugging; 78int profiling; 79int found_defaults; 80int incignore; 81 82/* 83 * Preserve old behaviour in INCLUDE_CONFIG_FILE handling (files are included 84 * literally). 85 */ 86int filebased = 0; 87 88static void configfile(void); 89static void get_srcdir(void); 90static void usage(void); 91static void cleanheaders(char *); 92static void kernconfdump(const char *); 93 94struct hdr_list { 95 char *h_name; 96 struct hdr_list *h_next; 97} *htab; 98 99/* 100 * Config builds a set of files for building a UNIX 101 * system given a description of the desired system. 102 */ 103int 104main(int argc, char **argv) 105{ 106 107 struct stat buf; 108 int ch, len; 109 char *p; 110 char xxx[MAXPATHLEN]; 111 char *kernfile; 112 113 kernfile = NULL; 114 while ((ch = getopt(argc, argv, "Cd:gpVx:")) != -1) 115 switch (ch) { 116 case 'C': 117 filebased = 1; 118 break; 119 case 'd': 120 if (*destdir == '\0') 121 strlcpy(destdir, optarg, sizeof(destdir)); 122 else 123 errx(2, "directory already set"); 124 break; 125 case 'g': 126 debugging++; 127 break; 128 case 'p': 129 profiling++; 130 break; 131 case 'V': 132 printf("%d\n", CONFIGVERS); 133 exit(0); 134 case 'x': 135 kernfile = optarg; 136 break; 137 case '?': 138 default: 139 usage(); 140 } 141 argc -= optind; 142 argv += optind; 143 144 if (kernfile != NULL) { 145 kernconfdump(kernfile); 146 exit(EXIT_SUCCESS); 147 } 148 149 if (argc != 1) 150 usage(); 151 152 PREFIX = *argv; 153 /* 154 * We mark lack of DEFAULTS here. Once we hit EOF in PREFIX, yywrap() 155 * will try to bring DEFAULTS to the playground, if this exists. 156 */ 157 found_defaults = 0; 158 if (freopen(PREFIX, "r", stdin) == NULL) 159 err(2, "%s", PREFIX); 160 yyfile = PREFIX; 161 if (*destdir != '\0') { 162 len = strlen(destdir); 163 while (len > 1 && destdir[len - 1] == '/') 164 destdir[--len] = '\0'; 165 get_srcdir(); 166 } else { 167 strlcpy(destdir, CDIR, sizeof(destdir)); 168 strlcat(destdir, PREFIX, sizeof(destdir)); 169 } 170 171 p = path((char *)NULL); 172 if (stat(p, &buf)) { 173 if (mkdir(p, 0777)) 174 err(2, "%s", p); 175 } else if (!S_ISDIR(buf.st_mode)) 176 errx(2, "%s isn't a directory", p); 177 178 SLIST_INIT(&cputype); 179 SLIST_INIT(&mkopt); 180 SLIST_INIT(&opt); 181 SLIST_INIT(&rmopts); 182 STAILQ_INIT(&cfgfiles); 183 STAILQ_INIT(&dtab); 184 STAILQ_INIT(&fntab); 185 STAILQ_INIT(&ftab); 186 STAILQ_INIT(&hints); 187 STAILQ_INIT(&rmdtab); 188 if (yyparse()) 189 exit(3); 190 191 /* 192 * Ensure that required elements (machine, cpu, ident) are present. 193 */ 194 if (machinename == NULL) { 195 printf("Specify machine type, e.g. ``machine i386''\n"); 196 exit(1); 197 } 198 if (ident == NULL) { 199 printf("no ident line specified\n"); 200 exit(1); 201 } 202 if (SLIST_EMPTY(&cputype)) { 203 printf("cpu type must be specified\n"); 204 exit(1); 205 } 206 207 /* 208 * make symbolic links in compilation directory 209 * for "sys" (to make genassym.c work along with #include <sys/xxx>) 210 * and similarly for "machine". 211 */ 212 if (*srcdir == '\0') 213 (void)snprintf(xxx, sizeof(xxx), "../../include"); 214 else 215 (void)snprintf(xxx, sizeof(xxx), "%s/%s/include", 216 srcdir, machinename); 217 (void) unlink(path("machine")); 218 (void) symlink(xxx, path("machine")); 219 if (strcmp(machinename, machinearch) != 0) { 220 /* 221 * make symbolic links in compilation directory for 222 * machinearch, if it is different than machinename. 223 */ 224 if (*srcdir == '\0') 225 (void)snprintf(xxx, sizeof(xxx), "../../../%s/include", 226 machinearch); 227 else 228 (void)snprintf(xxx, sizeof(xxx), "%s/%s/include", 229 srcdir, machinearch); 230 (void) unlink(path(machinearch)); 231 (void) symlink(xxx, path(machinearch)); 232 } 233 configfile(); /* put config file into kernel*/ 234 options(); /* make options .h files */ 235 makefile(); /* build Makefile */ 236 makeenv(); /* build env.c */ 237 makehints(); /* build hints.c */ 238 headers(); /* make a lot of .h files */ 239 cleanheaders(p); 240 printf("Kernel build directory is %s\n", p); 241 printf("Don't forget to do ``make cleandepend && make depend''\n"); 242 exit(0); 243} 244 245/* 246 * get_srcdir 247 * determine the root of the kernel source tree 248 * and save that in srcdir. 249 */ 250static void 251get_srcdir(void) 252{ 253 254 if (realpath("../..", srcdir) == NULL) 255 errx(2, "Unable to find root of source tree"); 256} 257 258static void 259usage(void) 260{ 261 262 fprintf(stderr, "usage: config [-CgpV] [-d destdir] sysname\n"); 263 fprintf(stderr, " config -x kernel\n"); 264 exit(EX_USAGE); 265} 266 267/* 268 * get_word 269 * returns EOF on end of file 270 * NULL on end of line 271 * pointer to the word otherwise 272 */ 273char * 274get_word(FILE *fp) 275{ 276 static char line[80]; 277 int ch; 278 char *cp; 279 int escaped_nl = 0; 280 281begin: 282 while ((ch = getc(fp)) != EOF) 283 if (ch != ' ' && ch != '\t') 284 break; 285 if (ch == EOF) 286 return ((char *)EOF); 287 if (ch == '\\'){ 288 escaped_nl = 1; 289 goto begin; 290 } 291 if (ch == '\n') { 292 if (escaped_nl){ 293 escaped_nl = 0; 294 goto begin; 295 } 296 else 297 return (NULL); 298 } 299 cp = line; 300 *cp++ = ch; 301 while ((ch = getc(fp)) != EOF) { 302 if (isspace(ch)) 303 break; 304 *cp++ = ch; 305 } 306 *cp = 0; 307 if (ch == EOF) 308 return ((char *)EOF); 309 (void) ungetc(ch, fp); 310 return (line); 311} 312 313/* 314 * get_quoted_word 315 * like get_word but will accept something in double or single quotes 316 * (to allow embedded spaces). 317 */ 318char * 319get_quoted_word(FILE *fp) 320{ 321 static char line[256]; 322 int ch; 323 char *cp; 324 int escaped_nl = 0; 325 326begin: 327 while ((ch = getc(fp)) != EOF) 328 if (ch != ' ' && ch != '\t') 329 break; 330 if (ch == EOF) 331 return ((char *)EOF); 332 if (ch == '\\'){ 333 escaped_nl = 1; 334 goto begin; 335 } 336 if (ch == '\n') { 337 if (escaped_nl){ 338 escaped_nl = 0; 339 goto begin; 340 } 341 else 342 return (NULL); 343 } 344 cp = line; 345 if (ch == '"' || ch == '\'') { 346 int quote = ch; 347 348 while ((ch = getc(fp)) != EOF) { 349 if (ch == quote) 350 break; 351 if (ch == '\n') { 352 *cp = 0; 353 printf("config: missing quote reading `%s'\n", 354 line); 355 exit(2); 356 } 357 *cp++ = ch; 358 } 359 } else { 360 *cp++ = ch; 361 while ((ch = getc(fp)) != EOF) { 362 if (isspace(ch)) 363 break; 364 *cp++ = ch; 365 } 366 if (ch != EOF) 367 (void) ungetc(ch, fp); 368 } 369 *cp = 0; 370 if (ch == EOF) 371 return ((char *)EOF); 372 return (line); 373} 374 375/* 376 * prepend the path to a filename 377 */ 378char * 379path(const char *file) 380{ 381 char *cp = NULL; 382 383 if (file) 384 asprintf(&cp, "%s/%s", destdir, file); 385 else 386 cp = strdup(destdir); 387 return (cp); 388} 389 390/* 391 * Generate configuration file based on actual settings. With this mode, user 392 * will be able to obtain and build conifguration file with one command. 393 */ 394static void 395configfile_dynamic(struct sbuf *sb) 396{ 397 struct cputype *cput; 398 struct device *d; 399 struct opt *ol; 400 char *lend;
|
| 401 unsigned int i;
|
400 401 asprintf(&lend, "\\n\\\n"); 402 assert(lend != NULL); 403 sbuf_printf(sb, "options\t%s%s", OPT_AUTOGEN, lend); 404 sbuf_printf(sb, "ident\t%s%s", ident, lend); 405 sbuf_printf(sb, "machine\t%s%s", machinename, lend); 406 SLIST_FOREACH(cput, &cputype, cpu_next) 407 sbuf_printf(sb, "cpu\t%s%s", cput->cpu_name, lend); 408 SLIST_FOREACH(ol, &mkopt, op_next) 409 sbuf_printf(sb, "makeoptions\t%s=%s%s", ol->op_name, 410 ol->op_value, lend); 411 SLIST_FOREACH(ol, &opt, op_next) { 412 if (strncmp(ol->op_name, "DEV_", 4) == 0) 413 continue; 414 sbuf_printf(sb, "options\t%s", ol->op_name); 415 if (ol->op_value != NULL) {
| 402 403 asprintf(&lend, "\\n\\\n"); 404 assert(lend != NULL); 405 sbuf_printf(sb, "options\t%s%s", OPT_AUTOGEN, lend); 406 sbuf_printf(sb, "ident\t%s%s", ident, lend); 407 sbuf_printf(sb, "machine\t%s%s", machinename, lend); 408 SLIST_FOREACH(cput, &cputype, cpu_next) 409 sbuf_printf(sb, "cpu\t%s%s", cput->cpu_name, lend); 410 SLIST_FOREACH(ol, &mkopt, op_next) 411 sbuf_printf(sb, "makeoptions\t%s=%s%s", ol->op_name, 412 ol->op_value, lend); 413 SLIST_FOREACH(ol, &opt, op_next) { 414 if (strncmp(ol->op_name, "DEV_", 4) == 0) 415 continue; 416 sbuf_printf(sb, "options\t%s", ol->op_name); 417 if (ol->op_value != NULL) {
|
416 sbuf_printf(sb, "=%s%s", ol->op_value, lend);
| 418 sbuf_putc(sb, '='); 419 for (i = 0; i < strlen(ol->op_value); i++) { 420 if (ol->op_value[i] == '"') 421 sbuf_printf(sb, "\\%c", 422 ol->op_value[i]); 423 else 424 sbuf_printf(sb, "%c", 425 ol->op_value[i]); 426 } 427 sbuf_printf(sb, "%s", lend);
|
417 } else { 418 sbuf_printf(sb, "%s", lend); 419 } 420 } 421 /* 422 * Mark this file as containing everything we need. 423 */ 424 STAILQ_FOREACH(d, &dtab, d_next) 425 sbuf_printf(sb, "device\t%s%s", d->d_name, lend); 426 free(lend); 427} 428 429/* 430 * Generate file from the configuration files. 431 */ 432static void 433configfile_filebased(struct sbuf *sb) 434{ 435 FILE *cff; 436 struct cfgfile *cf; 437 int i; 438 439 STAILQ_FOREACH(cf, &cfgfiles, cfg_next) { 440 cff = fopen(cf->cfg_path, "r"); 441 if (cff == NULL) { 442 warn("Couldn't open file %s", cf->cfg_path); 443 continue; 444 } 445 while ((i = getc(cff)) != EOF) { 446 if (i == '\n') 447 sbuf_printf(sb, "\\n\\\n"); 448 else if (i == '"' || i == '\'') 449 sbuf_printf(sb, "\\%c", i); 450 else 451 sbuf_putc(sb, i); 452 } 453 fclose(cff); 454 } 455} 456 457static void 458configfile(void) 459{ 460 FILE *fo; 461 struct sbuf *sb; 462 char *p; 463 464 /* Add main configuration file to the list of files to be included */ 465 cfgfile_add(PREFIX); 466 p = path("config.c.new"); 467 fo = fopen(p, "w"); 468 if (!fo) 469 err(2, "%s", p); 470 sb = sbuf_new(NULL, NULL, 2048, SBUF_AUTOEXTEND); 471 assert(sb != NULL); 472 sbuf_clear(sb); 473 /* 474 * Try to read all configuration files. Since those will be present as 475 * C string in the macro, we have to slash their ends then the line 476 * wraps. 477 */ 478 if (filebased) { 479 /* Is needed, can be used for backward compatibility. */ 480 configfile_filebased(sb); 481 } else { 482 configfile_dynamic(sb); 483 } 484 sbuf_finish(sb); 485 /* 486 * We print first part of the tamplate, replace our tag with 487 * configuration files content and later continue writing our 488 * template. 489 */ 490 p = strstr(kernconfstr, KERNCONFTAG); 491 if (p == NULL) 492 errx(EXIT_FAILURE, "Something went terribly wrong!"); 493 *p = '\0'; 494 fprintf(fo, "%s", kernconfstr); 495 fprintf(fo, "%s", sbuf_data(sb)); 496 p += strlen(KERNCONFTAG); 497 fprintf(fo, "%s", p); 498 sbuf_delete(sb); 499 fclose(fo); 500 moveifchanged(path("config.c.new"), path("config.c")); 501 cfgfile_removeall(); 502} 503 504/* 505 * moveifchanged -- 506 * compare two files; rename if changed. 507 */ 508void 509moveifchanged(const char *from_name, const char *to_name) 510{ 511 char *p, *q; 512 int changed; 513 size_t tsize; 514 struct stat from_sb, to_sb; 515 int from_fd, to_fd; 516 517 changed = 0; 518 519 if ((from_fd = open(from_name, O_RDONLY)) < 0) 520 err(EX_OSERR, "moveifchanged open(%s)", from_name); 521 522 if ((to_fd = open(to_name, O_RDONLY)) < 0) 523 changed++; 524 525 if (!changed && fstat(from_fd, &from_sb) < 0) 526 err(EX_OSERR, "moveifchanged fstat(%s)", from_name); 527 528 if (!changed && fstat(to_fd, &to_sb) < 0) 529 err(EX_OSERR, "moveifchanged fstat(%s)", to_name); 530 531 if (!changed && from_sb.st_size != to_sb.st_size) 532 changed++; 533 534 tsize = (size_t)from_sb.st_size; 535 536 if (!changed) { 537 p = mmap(NULL, tsize, PROT_READ, MAP_SHARED, from_fd, (off_t)0); 538#ifndef MAP_FAILED 539#define MAP_FAILED ((caddr_t) -1) 540#endif 541 if (p == MAP_FAILED) 542 err(EX_OSERR, "mmap %s", from_name); 543 q = mmap(NULL, tsize, PROT_READ, MAP_SHARED, to_fd, (off_t)0); 544 if (q == MAP_FAILED) 545 err(EX_OSERR, "mmap %s", to_name); 546 547 changed = memcmp(p, q, tsize); 548 munmap(p, tsize); 549 munmap(q, tsize); 550 } 551 if (changed) { 552 if (rename(from_name, to_name) < 0) 553 err(EX_OSERR, "rename(%s, %s)", from_name, to_name); 554 } else { 555 if (unlink(from_name) < 0) 556 err(EX_OSERR, "unlink(%s)", from_name); 557 } 558} 559 560static void 561cleanheaders(char *p) 562{ 563 DIR *dirp; 564 struct dirent *dp; 565 struct file_list *fl; 566 struct hdr_list *hl; 567 int i; 568 569 remember("y.tab.h"); 570 remember("setdefs.h"); 571 STAILQ_FOREACH(fl, &ftab, f_next) 572 remember(fl->f_fn); 573 574 /* 575 * Scan the build directory and clean out stuff that looks like 576 * it might have been a leftover NFOO header, etc. 577 */ 578 if ((dirp = opendir(p)) == NULL) 579 err(EX_OSERR, "opendir %s", p); 580 while ((dp = readdir(dirp)) != NULL) { 581 i = dp->d_namlen - 2; 582 /* Skip non-headers */ 583 if (dp->d_name[i] != '.' || dp->d_name[i + 1] != 'h') 584 continue; 585 /* Skip special stuff, eg: bus_if.h, but check opt_*.h */ 586 if (index(dp->d_name, '_') && 587 strncmp(dp->d_name, "opt_", 4) != 0) 588 continue; 589 /* Check if it is a target file */ 590 for (hl = htab; hl != NULL; hl = hl->h_next) { 591 if (eq(dp->d_name, hl->h_name)) { 592 break; 593 } 594 } 595 if (hl) 596 continue; 597 printf("Removing stale header: %s\n", dp->d_name); 598 if (unlink(path(dp->d_name)) == -1) 599 warn("unlink %s", dp->d_name); 600 } 601 (void)closedir(dirp); 602} 603 604void 605remember(const char *file) 606{ 607 char *s; 608 struct hdr_list *hl; 609 610 if ((s = strrchr(file, '/')) != NULL) 611 s = ns(s + 1); 612 else 613 s = ns(file); 614 615 if (index(s, '_') && strncmp(s, "opt_", 4) != 0) { 616 free(s); 617 return; 618 } 619 for (hl = htab; hl != NULL; hl = hl->h_next) { 620 if (eq(s, hl->h_name)) { 621 free(s); 622 return; 623 } 624 } 625 hl = calloc(1, sizeof(*hl)); 626 hl->h_name = s; 627 hl->h_next = htab; 628 htab = hl; 629} 630 631/* 632 * This one is quick hack. Will be probably moved to elf(3) interface. 633 * It takes kernel configuration file name, passes it as an argument to 634 * elfdump -a, which output is parsed by some UNIX tools... 635 */ 636static void 637kernconfdump(const char *file) 638{ 639 struct stat st; 640 FILE *fp, *pp; 641 int error, len, osz, r; 642 unsigned int off, size; 643 char *cmd, *o; 644 645 r = open(file, O_RDONLY); 646 if (r == -1) 647 errx(EXIT_FAILURE, "Couldn't open file '%s'", file); 648 error = fstat(r, &st); 649 if (error == -1) 650 errx(EXIT_FAILURE, "fstat() failed"); 651 if (S_ISDIR(st.st_mode)) 652 errx(EXIT_FAILURE, "'%s' is a directory", file); 653 fp = fdopen(r, "r"); 654 if (fp == NULL) 655 errx(EXIT_FAILURE, "fdopen() failed"); 656 osz = 1024; 657 o = calloc(1, osz); 658 if (o == NULL) 659 errx(EXIT_FAILURE, "Couldn't allocate memory"); 660 /* ELF note section header. */ 661 asprintf(&cmd, "/usr/bin/elfdump -c %s | grep -A 5 kern_conf" 662 "| tail -2 | cut -d ' ' -f 2 | paste - - -", file); 663 if (cmd == NULL) 664 errx(EXIT_FAILURE, "asprintf() failed"); 665 pp = popen(cmd, "r"); 666 if (pp == NULL) 667 errx(EXIT_FAILURE, "popen() failed"); 668 free(cmd); 669 len = fread(o, osz, 1, pp); 670 pclose(pp); 671 r = sscanf(o, "%d\t%d", &off, &size); 672 free(o); 673 if (r != 2) 674 errx(EXIT_FAILURE, "File %s doesn't contain configuration " 675 "file. Either unsupported, or not compiled with " 676 "INCLUDE_CONFIG_FILE", file); 677 r = fseek(fp, off, SEEK_CUR); 678 if (r != 0) 679 errx(EXIT_FAILURE, "fseek() failed"); 680 while ((r = fgetc(fp)) != EOF && size-- > 0) 681 fputc(r, stdout); 682 fclose(fp); 683}
| 428 } else { 429 sbuf_printf(sb, "%s", lend); 430 } 431 } 432 /* 433 * Mark this file as containing everything we need. 434 */ 435 STAILQ_FOREACH(d, &dtab, d_next) 436 sbuf_printf(sb, "device\t%s%s", d->d_name, lend); 437 free(lend); 438} 439 440/* 441 * Generate file from the configuration files. 442 */ 443static void 444configfile_filebased(struct sbuf *sb) 445{ 446 FILE *cff; 447 struct cfgfile *cf; 448 int i; 449 450 STAILQ_FOREACH(cf, &cfgfiles, cfg_next) { 451 cff = fopen(cf->cfg_path, "r"); 452 if (cff == NULL) { 453 warn("Couldn't open file %s", cf->cfg_path); 454 continue; 455 } 456 while ((i = getc(cff)) != EOF) { 457 if (i == '\n') 458 sbuf_printf(sb, "\\n\\\n"); 459 else if (i == '"' || i == '\'') 460 sbuf_printf(sb, "\\%c", i); 461 else 462 sbuf_putc(sb, i); 463 } 464 fclose(cff); 465 } 466} 467 468static void 469configfile(void) 470{ 471 FILE *fo; 472 struct sbuf *sb; 473 char *p; 474 475 /* Add main configuration file to the list of files to be included */ 476 cfgfile_add(PREFIX); 477 p = path("config.c.new"); 478 fo = fopen(p, "w"); 479 if (!fo) 480 err(2, "%s", p); 481 sb = sbuf_new(NULL, NULL, 2048, SBUF_AUTOEXTEND); 482 assert(sb != NULL); 483 sbuf_clear(sb); 484 /* 485 * Try to read all configuration files. Since those will be present as 486 * C string in the macro, we have to slash their ends then the line 487 * wraps. 488 */ 489 if (filebased) { 490 /* Is needed, can be used for backward compatibility. */ 491 configfile_filebased(sb); 492 } else { 493 configfile_dynamic(sb); 494 } 495 sbuf_finish(sb); 496 /* 497 * We print first part of the tamplate, replace our tag with 498 * configuration files content and later continue writing our 499 * template. 500 */ 501 p = strstr(kernconfstr, KERNCONFTAG); 502 if (p == NULL) 503 errx(EXIT_FAILURE, "Something went terribly wrong!"); 504 *p = '\0'; 505 fprintf(fo, "%s", kernconfstr); 506 fprintf(fo, "%s", sbuf_data(sb)); 507 p += strlen(KERNCONFTAG); 508 fprintf(fo, "%s", p); 509 sbuf_delete(sb); 510 fclose(fo); 511 moveifchanged(path("config.c.new"), path("config.c")); 512 cfgfile_removeall(); 513} 514 515/* 516 * moveifchanged -- 517 * compare two files; rename if changed. 518 */ 519void 520moveifchanged(const char *from_name, const char *to_name) 521{ 522 char *p, *q; 523 int changed; 524 size_t tsize; 525 struct stat from_sb, to_sb; 526 int from_fd, to_fd; 527 528 changed = 0; 529 530 if ((from_fd = open(from_name, O_RDONLY)) < 0) 531 err(EX_OSERR, "moveifchanged open(%s)", from_name); 532 533 if ((to_fd = open(to_name, O_RDONLY)) < 0) 534 changed++; 535 536 if (!changed && fstat(from_fd, &from_sb) < 0) 537 err(EX_OSERR, "moveifchanged fstat(%s)", from_name); 538 539 if (!changed && fstat(to_fd, &to_sb) < 0) 540 err(EX_OSERR, "moveifchanged fstat(%s)", to_name); 541 542 if (!changed && from_sb.st_size != to_sb.st_size) 543 changed++; 544 545 tsize = (size_t)from_sb.st_size; 546 547 if (!changed) { 548 p = mmap(NULL, tsize, PROT_READ, MAP_SHARED, from_fd, (off_t)0); 549#ifndef MAP_FAILED 550#define MAP_FAILED ((caddr_t) -1) 551#endif 552 if (p == MAP_FAILED) 553 err(EX_OSERR, "mmap %s", from_name); 554 q = mmap(NULL, tsize, PROT_READ, MAP_SHARED, to_fd, (off_t)0); 555 if (q == MAP_FAILED) 556 err(EX_OSERR, "mmap %s", to_name); 557 558 changed = memcmp(p, q, tsize); 559 munmap(p, tsize); 560 munmap(q, tsize); 561 } 562 if (changed) { 563 if (rename(from_name, to_name) < 0) 564 err(EX_OSERR, "rename(%s, %s)", from_name, to_name); 565 } else { 566 if (unlink(from_name) < 0) 567 err(EX_OSERR, "unlink(%s)", from_name); 568 } 569} 570 571static void 572cleanheaders(char *p) 573{ 574 DIR *dirp; 575 struct dirent *dp; 576 struct file_list *fl; 577 struct hdr_list *hl; 578 int i; 579 580 remember("y.tab.h"); 581 remember("setdefs.h"); 582 STAILQ_FOREACH(fl, &ftab, f_next) 583 remember(fl->f_fn); 584 585 /* 586 * Scan the build directory and clean out stuff that looks like 587 * it might have been a leftover NFOO header, etc. 588 */ 589 if ((dirp = opendir(p)) == NULL) 590 err(EX_OSERR, "opendir %s", p); 591 while ((dp = readdir(dirp)) != NULL) { 592 i = dp->d_namlen - 2; 593 /* Skip non-headers */ 594 if (dp->d_name[i] != '.' || dp->d_name[i + 1] != 'h') 595 continue; 596 /* Skip special stuff, eg: bus_if.h, but check opt_*.h */ 597 if (index(dp->d_name, '_') && 598 strncmp(dp->d_name, "opt_", 4) != 0) 599 continue; 600 /* Check if it is a target file */ 601 for (hl = htab; hl != NULL; hl = hl->h_next) { 602 if (eq(dp->d_name, hl->h_name)) { 603 break; 604 } 605 } 606 if (hl) 607 continue; 608 printf("Removing stale header: %s\n", dp->d_name); 609 if (unlink(path(dp->d_name)) == -1) 610 warn("unlink %s", dp->d_name); 611 } 612 (void)closedir(dirp); 613} 614 615void 616remember(const char *file) 617{ 618 char *s; 619 struct hdr_list *hl; 620 621 if ((s = strrchr(file, '/')) != NULL) 622 s = ns(s + 1); 623 else 624 s = ns(file); 625 626 if (index(s, '_') && strncmp(s, "opt_", 4) != 0) { 627 free(s); 628 return; 629 } 630 for (hl = htab; hl != NULL; hl = hl->h_next) { 631 if (eq(s, hl->h_name)) { 632 free(s); 633 return; 634 } 635 } 636 hl = calloc(1, sizeof(*hl)); 637 hl->h_name = s; 638 hl->h_next = htab; 639 htab = hl; 640} 641 642/* 643 * This one is quick hack. Will be probably moved to elf(3) interface. 644 * It takes kernel configuration file name, passes it as an argument to 645 * elfdump -a, which output is parsed by some UNIX tools... 646 */ 647static void 648kernconfdump(const char *file) 649{ 650 struct stat st; 651 FILE *fp, *pp; 652 int error, len, osz, r; 653 unsigned int off, size; 654 char *cmd, *o; 655 656 r = open(file, O_RDONLY); 657 if (r == -1) 658 errx(EXIT_FAILURE, "Couldn't open file '%s'", file); 659 error = fstat(r, &st); 660 if (error == -1) 661 errx(EXIT_FAILURE, "fstat() failed"); 662 if (S_ISDIR(st.st_mode)) 663 errx(EXIT_FAILURE, "'%s' is a directory", file); 664 fp = fdopen(r, "r"); 665 if (fp == NULL) 666 errx(EXIT_FAILURE, "fdopen() failed"); 667 osz = 1024; 668 o = calloc(1, osz); 669 if (o == NULL) 670 errx(EXIT_FAILURE, "Couldn't allocate memory"); 671 /* ELF note section header. */ 672 asprintf(&cmd, "/usr/bin/elfdump -c %s | grep -A 5 kern_conf" 673 "| tail -2 | cut -d ' ' -f 2 | paste - - -", file); 674 if (cmd == NULL) 675 errx(EXIT_FAILURE, "asprintf() failed"); 676 pp = popen(cmd, "r"); 677 if (pp == NULL) 678 errx(EXIT_FAILURE, "popen() failed"); 679 free(cmd); 680 len = fread(o, osz, 1, pp); 681 pclose(pp); 682 r = sscanf(o, "%d\t%d", &off, &size); 683 free(o); 684 if (r != 2) 685 errx(EXIT_FAILURE, "File %s doesn't contain configuration " 686 "file. Either unsupported, or not compiled with " 687 "INCLUDE_CONFIG_FILE", file); 688 r = fseek(fp, off, SEEK_CUR); 689 if (r != 0) 690 errx(EXIT_FAILURE, "fseek() failed"); 691 while ((r = fgetc(fp)) != EOF && size-- > 0) 692 fputc(r, stdout); 693 fclose(fp); 694}
|