main.c (163638) | main.c (169507) |
---|---|
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 --- 24 unchanged lines hidden (view full) --- 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 --- 24 unchanged lines hidden (view full) --- 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 163638 2006-10-24 00:31:59Z imp $"; | 41 "$FreeBSD: head/usr.sbin/config/main.c 169507 2007-05-12 19:38:18Z wkoszek $"; |
42#endif /* not lint */ 43 44#include <sys/types.h> 45#include <sys/stat.h> | 42#endif /* not lint */ 43 44#include <sys/types.h> 45#include <sys/stat.h> |
46#include <sys/sbuf.h> |
|
46#include <sys/file.h> 47#include <sys/mman.h> 48#include <sys/param.h> | 47#include <sys/file.h> 48#include <sys/mman.h> 49#include <sys/param.h> |
50 51#include <assert.h> |
|
49#include <ctype.h> 50#include <err.h> 51#include <stdio.h> 52#include <sysexits.h> 53#include <unistd.h> 54#include <dirent.h> 55#include "y.tab.h" 56#include "config.h" --- 11 unchanged lines hidden (view full) --- 68 69char * PREFIX; 70char destdir[MAXPATHLEN]; 71char srcdir[MAXPATHLEN]; 72 73int debugging; 74int profiling; 75int found_defaults; | 52#include <ctype.h> 53#include <err.h> 54#include <stdio.h> 55#include <sysexits.h> 56#include <unistd.h> 57#include <dirent.h> 58#include "y.tab.h" 59#include "config.h" --- 11 unchanged lines hidden (view full) --- 71 72char * PREFIX; 73char destdir[MAXPATHLEN]; 74char srcdir[MAXPATHLEN]; 75 76int debugging; 77int profiling; 78int found_defaults; |
79int incignore; |
|
76 | 80 |
81/* 82 * Preserve old behaviour in INCLUDE_CONFIG_FILE handling (files are included 83 * literally). 84 */ 85int filebased = 0; 86 |
|
77static void configfile(void); 78static void get_srcdir(void); 79static void usage(void); 80static void cleanheaders(char *); | 87static void configfile(void); 88static void get_srcdir(void); 89static void usage(void); 90static void cleanheaders(char *); |
91static void kernconfdump(const char *); |
|
81 82struct hdr_list { 83 char *h_name; 84 struct hdr_list *h_next; 85} *htab; 86 87/* 88 * Config builds a set of files for building a UNIX 89 * system given a description of the desired system. 90 */ 91int 92main(int argc, char **argv) 93{ 94 95 struct stat buf; 96 int ch, len; 97 char *p; 98 char xxx[MAXPATHLEN]; | 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]; |
99 FILE *fp; | 110 char *kernfile; |
100 | 111 |
101 while ((ch = getopt(argc, argv, "d:gpV")) != -1) | 112 kernfile = NULL; 113 while ((ch = getopt(argc, argv, "Cd:gpVx:")) != -1) |
102 switch (ch) { | 114 switch (ch) { |
103 case 'V': 104 printf("%d\n", CONFIGVERS); 105 exit(0); | 115 case 'C': 116 filebased = 1; 117 break; |
106 case 'd': 107 if (*destdir == '\0') 108 strlcpy(destdir, optarg, sizeof(destdir)); 109 else 110 errx(2, "directory already set"); 111 break; 112 case 'g': 113 debugging++; 114 break; 115 case 'p': 116 profiling++; 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; |
|
118 case '?': 119 default: 120 usage(); 121 } 122 argc -= optind; 123 argv += optind; 124 | 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 |
|
125 if (argc != 1) 126 usage(); 127 128 PREFIX = *argv; | 148 if (argc != 1) 149 usage(); 150 151 PREFIX = *argv; |
129 fp = fopen(PREFIX, "r"); 130 if (fp == NULL) | 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) |
131 err(2, "%s", PREFIX); | 158 err(2, "%s", PREFIX); |
132 fclose(fp); 133 if (freopen("DEFAULTS", "r", stdin) != NULL) { 134 found_defaults = 1; 135 yyfile = "DEFAULTS"; 136 } else { 137 if (freopen(PREFIX, "r", stdin) == NULL) 138 err(2, "%s", PREFIX); 139 yyfile = PREFIX; 140 } 141 | 159 yyfile = PREFIX; |
142 if (*destdir != '\0') { 143 len = strlen(destdir); 144 while (len > 1 && destdir[len - 1] == '/') 145 destdir[--len] = '\0'; 146 get_srcdir(); 147 } else { 148 strlcpy(destdir, CDIR, sizeof(destdir)); 149 strlcat(destdir, PREFIX, sizeof(destdir)); 150 } 151 152 p = path((char *)NULL); 153 if (stat(p, &buf)) { 154 if (mkdir(p, 0777)) 155 err(2, "%s", p); 156 } else if (!S_ISDIR(buf.st_mode)) 157 errx(2, "%s isn't a directory", p); 158 | 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); |
|
159 STAILQ_INIT(&dtab); 160 STAILQ_INIT(&fntab); | 182 STAILQ_INIT(&dtab); 183 STAILQ_INIT(&fntab); |
161 SLIST_INIT(&cputype); | |
162 STAILQ_INIT(&ftab); 163 STAILQ_INIT(&hints); | 184 STAILQ_INIT(&ftab); 185 STAILQ_INIT(&hints); |
186 STAILQ_INIT(&rmdtab); |
|
164 if (yyparse()) 165 exit(3); 166 167 /* 168 * Ensure that required elements (machine, cpu, ident) are present. 169 */ 170 if (machinename == NULL) { 171 printf("Specify machine type, e.g. ``machine i386''\n"); --- 29 unchanged lines hidden (view full) --- 201 (void)snprintf(xxx, sizeof(xxx), "../../../%s/include", 202 machinearch); 203 else 204 (void)snprintf(xxx, sizeof(xxx), "%s/%s/include", 205 srcdir, machinearch); 206 (void) unlink(path(machinearch)); 207 (void) symlink(xxx, path(machinearch)); 208 } | 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"); --- 29 unchanged lines hidden (view full) --- 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*/ |
|
209 options(); /* make options .h files */ 210 makefile(); /* build Makefile */ 211 makeenv(); /* build env.c */ 212 makehints(); /* build hints.c */ 213 headers(); /* make a lot of .h files */ | 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 */ |
214 configfile(); /* put config file into kernel*/ | |
215 cleanheaders(p); 216 printf("Kernel build directory is %s\n", p); 217 printf("Don't forget to do ``make cleandepend && make depend''\n"); 218 exit(0); 219} 220 221/* 222 * get_srcdir --- 7 unchanged lines hidden (view full) --- 230 if (realpath("../..", srcdir) == NULL) 231 errx(2, "Unable to find root of source tree"); 232} 233 234static void 235usage(void) 236{ 237 | 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 --- 7 unchanged lines hidden (view full) --- 253 if (realpath("../..", srcdir) == NULL) 254 errx(2, "Unable to find root of source tree"); 255} 256 257static void 258usage(void) 259{ 260 |
238 fprintf(stderr, "usage: config [-Vgp] [-d destdir] sysname\n"); 239 exit(1); | 261 fprintf(stderr, "usage: config [-CgpV] [-d destdir] sysname\n"); 262 fprintf(stderr, " config -x kernel\n"); 263 exit(EX_USAGE); |
240} 241 242/* 243 * get_word 244 * returns EOF on end of file 245 * NULL on end of line 246 * pointer to the word otherwise 247 */ --- 109 unchanged lines hidden (view full) --- 357 358 if (file) 359 asprintf(&cp, "%s/%s", destdir, file); 360 else 361 cp = strdup(destdir); 362 return (cp); 363} 364 | 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 */ --- 109 unchanged lines hidden (view full) --- 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 */ |
|
365static void | 393static void |
394configfile_dynamic(struct sbuf *sb) 395{ 396 struct cputype *cput; 397 struct device *d; 398 struct opt *ol; 399 char *lend; 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) { 416 sbuf_printf(sb, "=%s%s", ol->op_value, 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 |
|
366configfile(void) 367{ | 458configfile(void) 459{ |
368 FILE *fi, *fo; | 460 FILE *fo; 461 struct sbuf *sb; |
369 char *p; | 462 char *p; |
370 int i; 371 372 fi = fopen(PREFIX, "r"); 373 if (!fi) 374 err(2, "%s", PREFIX); 375 fo = fopen(p=path("config.c.new"), "w"); | 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"); |
376 if (!fo) 377 err(2, "%s", p); | 468 if (!fo) 469 err(2, "%s", p); |
378 fprintf(fo, "#include \"opt_config.h\"\n"); 379 fprintf(fo, "#ifdef INCLUDE_CONFIG_FILE \n"); 380 fprintf(fo, "const char config[] = \"\\\n"); 381 fprintf(fo, "START CONFIG FILE %s\\n\\\n___", PREFIX); 382 while (EOF != (i=getc(fi))) { 383 if (i == '\n') { 384 fprintf(fo, "\\n\\\n___"); 385 } else if (i == '\"') { 386 fprintf(fo, "\\\""); 387 } else if (i == '\\') { 388 fprintf(fo, "\\\\"); 389 } else { 390 putc(i, fo); 391 } | 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); |
392 } | 483 } |
393 fprintf(fo, "\\n\\\nEND CONFIG FILE %s\\n\\\n", PREFIX); 394 fprintf(fo, "\";\n"); 395 fprintf(fo, "\n#endif /* INCLUDE_CONFIG_FILE */\n"); 396 fclose(fi); | 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); |
397 fclose(fo); 398 moveifchanged(path("config.c.new"), path("config.c")); | 499 fclose(fo); 500 moveifchanged(path("config.c.new"), path("config.c")); |
501 cfgfile_removeall(); |
|
399} 400 401/* 402 * moveifchanged -- 403 * compare two files; rename if changed. 404 */ 405void 406moveifchanged(const char *from_name, const char *to_name) --- 112 unchanged lines hidden (view full) --- 519 return; 520 } 521 } 522 hl = calloc(1, sizeof(*hl)); 523 hl->h_name = s; 524 hl->h_next = htab; 525 htab = hl; 526} | 502} 503 504/* 505 * moveifchanged -- 506 * compare two files; rename if changed. 507 */ 508void 509moveifchanged(const char *from_name, const char *to_name) --- 112 unchanged lines hidden (view full) --- 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} |
|