main.c revision 178085
11553Srgrimes/* 21553Srgrimes * Copyright (c) 1980, 1993 31553Srgrimes * The Regents of the University of California. All rights reserved. 41553Srgrimes * 51553Srgrimes * Redistribution and use in source and binary forms, with or without 61553Srgrimes * modification, are permitted provided that the following conditions 71553Srgrimes * are met: 81553Srgrimes * 1. Redistributions of source code must retain the above copyright 91553Srgrimes * notice, this list of conditions and the following disclaimer. 101553Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 111553Srgrimes * notice, this list of conditions and the following disclaimer in the 121553Srgrimes * documentation and/or other materials provided with the distribution. 131553Srgrimes * 4. Neither the name of the University nor the names of its contributors 141553Srgrimes * may be used to endorse or promote products derived from this software 151553Srgrimes * without specific prior written permission. 161553Srgrimes * 171553Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 181553Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 191553Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 201553Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 211553Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 221553Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 231553Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 241553Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 251553Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 261553Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 271553Srgrimes * SUCH DAMAGE. 281553Srgrimes */ 291553Srgrimes 301553Srgrimes#ifndef lint 3129451Scharnierstatic const char copyright[] = 321553Srgrimes"@(#) Copyright (c) 1980, 1993\n\ 331553Srgrimes The Regents of the University of California. All rights reserved.\n"; 341553Srgrimes#endif /* not lint */ 351553Srgrimes 361553Srgrimes#ifndef lint 3729451Scharnier#if 0 381553Srgrimesstatic char sccsid[] = "@(#)main.c 8.1 (Berkeley) 6/6/93"; 3929451Scharnier#endif 4029451Scharnierstatic const char rcsid[] = 4150479Speter "$FreeBSD: head/usr.sbin/config/main.c 178085 2008-04-10 22:57:54Z imp $"; 421553Srgrimes#endif /* not lint */ 431553Srgrimes 441553Srgrimes#include <sys/types.h> 451553Srgrimes#include <sys/stat.h> 46169507Swkoszek#include <sys/sbuf.h> 471553Srgrimes#include <sys/file.h> 4813400Speter#include <sys/mman.h> 4952653Smarcel#include <sys/param.h> 50169507Swkoszek 51169507Swkoszek#include <assert.h> 521553Srgrimes#include <ctype.h> 5313400Speter#include <err.h> 5429451Scharnier#include <stdio.h> 55169512Swkoszek#include <string.h> 5613400Speter#include <sysexits.h> 5729451Scharnier#include <unistd.h> 5871784Speter#include <dirent.h> 5916073Sphk#include "y.tab.h" 601553Srgrimes#include "config.h" 61148916Sobrien#include "configvers.h" 621553Srgrimes 636631Sjkh#ifndef TRUE 646631Sjkh#define TRUE (1) 656631Sjkh#endif 666631Sjkh 676631Sjkh#ifndef FALSE 686631Sjkh#define FALSE (0) 696631Sjkh#endif 706631Sjkh 7179013Simp#define CDIR "../compile/" 7252653Smarcel 7345744Speterchar * PREFIX; 7452653Smarcelchar destdir[MAXPATHLEN]; 7552653Smarcelchar srcdir[MAXPATHLEN]; 7652653Smarcel 7745744Speterint debugging; 7845744Speterint profiling; 79151744Sjhbint found_defaults; 80169507Swkoszekint incignore; 811553Srgrimes 82169507Swkoszek/* 83169507Swkoszek * Preserve old behaviour in INCLUDE_CONFIG_FILE handling (files are included 84169507Swkoszek * literally). 85169507Swkoszek */ 86169507Swkoszekint filebased = 0; 87169507Swkoszek 8861640Speterstatic void configfile(void); 8961640Speterstatic void get_srcdir(void); 9061640Speterstatic void usage(void); 9171866Speterstatic void cleanheaders(char *); 92169507Swkoszekstatic void kernconfdump(const char *); 9329451Scharnier 9471866Speterstruct hdr_list { 9571866Speter char *h_name; 9671866Speter struct hdr_list *h_next; 9771866Speter} *htab; 9871866Speter 991553Srgrimes/* 1001553Srgrimes * Config builds a set of files for building a UNIX 1011553Srgrimes * system given a description of the desired system. 1021553Srgrimes */ 10329451Scharnierint 10461640Spetermain(int argc, char **argv) 1051553Srgrimes{ 1061553Srgrimes 1071553Srgrimes struct stat buf; 10852653Smarcel int ch, len; 1091553Srgrimes char *p; 11079694Speter char xxx[MAXPATHLEN]; 111169507Swkoszek char *kernfile; 1121553Srgrimes 113169507Swkoszek kernfile = NULL; 114169507Swkoszek while ((ch = getopt(argc, argv, "Cd:gpVx:")) != -1) 1151553Srgrimes switch (ch) { 116169507Swkoszek case 'C': 117169507Swkoszek filebased = 1; 118169507Swkoszek break; 11952653Smarcel case 'd': 12052653Smarcel if (*destdir == '\0') 12169004Simp strlcpy(destdir, optarg, sizeof(destdir)); 12252653Smarcel else 12352653Smarcel errx(2, "directory already set"); 12452653Smarcel break; 1251553Srgrimes case 'g': 12645579Sgrog debugging++; 1271553Srgrimes break; 1281553Srgrimes case 'p': 1291553Srgrimes profiling++; 1301553Srgrimes break; 131169507Swkoszek case 'V': 132169507Swkoszek printf("%d\n", CONFIGVERS); 133169507Swkoszek exit(0); 134169507Swkoszek case 'x': 135169507Swkoszek kernfile = optarg; 136169507Swkoszek break; 1371553Srgrimes case '?': 1381553Srgrimes default: 13929451Scharnier usage(); 1401553Srgrimes } 1411553Srgrimes argc -= optind; 1421553Srgrimes argv += optind; 1431553Srgrimes 144169507Swkoszek if (kernfile != NULL) { 145169507Swkoszek kernconfdump(kernfile); 146169507Swkoszek exit(EXIT_SUCCESS); 147169507Swkoszek } 148169507Swkoszek 14929451Scharnier if (argc != 1) 15029451Scharnier usage(); 1511553Srgrimes 152151744Sjhb PREFIX = *argv; 153178085Simp if (stat(PREFIX, &buf) != 0 || !S_ISREG(buf.st_mode)) 154178085Simp err(2, "%s", PREFIX); 155169647Simp if (freopen("DEFAULTS", "r", stdin) != NULL) { 156169647Simp found_defaults = 1; 157169647Simp yyfile = "DEFAULTS"; 158169647Simp } else { 159169647Simp if (freopen(PREFIX, "r", stdin) == NULL) 160169647Simp err(2, "%s", PREFIX); 161169647Simp yyfile = PREFIX; 162169647Simp } 16352653Smarcel if (*destdir != '\0') { 16452653Smarcel len = strlen(destdir); 16552653Smarcel while (len > 1 && destdir[len - 1] == '/') 16652653Smarcel destdir[--len] = '\0'; 16752653Smarcel get_srcdir(); 16852653Smarcel } else { 16969004Simp strlcpy(destdir, CDIR, sizeof(destdir)); 17069004Simp strlcat(destdir, PREFIX, sizeof(destdir)); 17152653Smarcel } 17252653Smarcel 1732483Sjkh p = path((char *)NULL); 1742483Sjkh if (stat(p, &buf)) { 17529451Scharnier if (mkdir(p, 0777)) 17629451Scharnier err(2, "%s", p); 177152963Sru } else if (!S_ISDIR(buf.st_mode)) 17829451Scharnier errx(2, "%s isn't a directory", p); 1791553Srgrimes 180169507Swkoszek SLIST_INIT(&cputype); 181169507Swkoszek SLIST_INIT(&mkopt); 182169507Swkoszek SLIST_INIT(&opt); 183169507Swkoszek SLIST_INIT(&rmopts); 184169507Swkoszek STAILQ_INIT(&cfgfiles); 185110895Sru STAILQ_INIT(&dtab); 186129073Scognet STAILQ_INIT(&fntab); 187129073Scognet STAILQ_INIT(&ftab); 188163638Simp STAILQ_INIT(&hints); 1891553Srgrimes if (yyparse()) 1901553Srgrimes exit(3); 191153888Sru 192153888Sru /* 193153888Sru * Ensure that required elements (machine, cpu, ident) are present. 194153888Sru */ 19572000Speter if (machinename == NULL) { 19645775Speter printf("Specify machine type, e.g. ``machine i386''\n"); 1971553Srgrimes exit(1); 1981553Srgrimes } 199153888Sru if (ident == NULL) { 200153888Sru printf("no ident line specified\n"); 201153888Sru exit(1); 202153888Sru } 203153888Sru if (SLIST_EMPTY(&cputype)) { 204153888Sru printf("cpu type must be specified\n"); 205153888Sru exit(1); 206153888Sru } 207153888Sru 2081553Srgrimes /* 2091553Srgrimes * make symbolic links in compilation directory 2101553Srgrimes * for "sys" (to make genassym.c work along with #include <sys/xxx>) 2111553Srgrimes * and similarly for "machine". 2121553Srgrimes */ 21352653Smarcel if (*srcdir == '\0') 21479013Simp (void)snprintf(xxx, sizeof(xxx), "../../include"); 21552653Smarcel else 21652653Smarcel (void)snprintf(xxx, sizeof(xxx), "%s/%s/include", 21752653Smarcel srcdir, machinename); 21879694Speter (void) unlink(path("machine")); 2191553Srgrimes (void) symlink(xxx, path("machine")); 220144509Simp if (strcmp(machinename, machinearch) != 0) { 221144509Simp /* 222144509Simp * make symbolic links in compilation directory for 223144509Simp * machinearch, if it is different than machinename. 224144509Simp */ 225144509Simp if (*srcdir == '\0') 226144509Simp (void)snprintf(xxx, sizeof(xxx), "../../../%s/include", 227144509Simp machinearch); 228144509Simp else 229144509Simp (void)snprintf(xxx, sizeof(xxx), "%s/%s/include", 230144509Simp srcdir, machinearch); 231144509Simp (void) unlink(path(machinearch)); 232144509Simp (void) symlink(xxx, path(machinearch)); 233144509Simp } 234169507Swkoszek configfile(); /* put config file into kernel*/ 23512772Speter options(); /* make options .h files */ 2361553Srgrimes makefile(); /* build Makefile */ 237153888Sru makeenv(); /* build env.c */ 238153888Sru makehints(); /* build hints.c */ 2391553Srgrimes headers(); /* make a lot of .h files */ 24071866Speter cleanheaders(p); 2418248Sjkh printf("Kernel build directory is %s\n", p); 242154338Sflz printf("Don't forget to do ``make cleandepend && make depend''\n"); 2431553Srgrimes exit(0); 2441553Srgrimes} 2451553Srgrimes 24652653Smarcel/* 24752653Smarcel * get_srcdir 24852653Smarcel * determine the root of the kernel source tree 24952653Smarcel * and save that in srcdir. 25052653Smarcel */ 25129451Scharnierstatic void 25261640Speterget_srcdir(void) 25352653Smarcel{ 254175163Semaste struct stat lg, phy; 255175163Semaste char *p, *pwd; 256175163Semaste int i; 25752653Smarcel 25870673Speter if (realpath("../..", srcdir) == NULL) 25970673Speter errx(2, "Unable to find root of source tree"); 260175163Semaste if ((pwd = getenv("PWD")) != NULL && *pwd == '/' && 261175163Semaste (pwd = strdup(pwd)) != NULL) { 262175163Semaste /* Remove the last two path components. */ 263175163Semaste for (i = 0; i < 2; i++) { 264175163Semaste if ((p = strrchr(pwd, '/')) == NULL) { 265175163Semaste free(pwd); 266175163Semaste return; 267175163Semaste } 268175163Semaste *p = '\0'; 269175163Semaste } 270175163Semaste if (stat(pwd, &lg) != -1 && stat(srcdir, &phy) != -1 && 271175163Semaste lg.st_dev == phy.st_dev && lg.st_ino == phy.st_ino) 272175163Semaste strlcpy(srcdir, pwd, MAXPATHLEN); 273175163Semaste free(pwd); 274175163Semaste } 27552653Smarcel} 27652653Smarcel 27752653Smarcelstatic void 27861640Speterusage(void) 27929451Scharnier{ 280144352Simp 281169507Swkoszek fprintf(stderr, "usage: config [-CgpV] [-d destdir] sysname\n"); 282169507Swkoszek fprintf(stderr, " config -x kernel\n"); 283169507Swkoszek exit(EX_USAGE); 28429451Scharnier} 28529451Scharnier 2861553Srgrimes/* 2871553Srgrimes * get_word 2881553Srgrimes * returns EOF on end of file 2891553Srgrimes * NULL on end of line 2901553Srgrimes * pointer to the word otherwise 2911553Srgrimes */ 2921553Srgrimeschar * 29361640Speterget_word(FILE *fp) 2941553Srgrimes{ 2951553Srgrimes static char line[80]; 29661640Speter int ch; 29761640Speter char *cp; 2984571Sgibbs int escaped_nl = 0; 2991553Srgrimes 3004571Sgibbsbegin: 3011553Srgrimes while ((ch = getc(fp)) != EOF) 3021553Srgrimes if (ch != ' ' && ch != '\t') 3031553Srgrimes break; 3041553Srgrimes if (ch == EOF) 3051553Srgrimes return ((char *)EOF); 3064571Sgibbs if (ch == '\\'){ 3074571Sgibbs escaped_nl = 1; 3084571Sgibbs goto begin; 3094571Sgibbs } 31045775Speter if (ch == '\n') { 3114571Sgibbs if (escaped_nl){ 3124571Sgibbs escaped_nl = 0; 3134571Sgibbs goto begin; 3144571Sgibbs } 3154571Sgibbs else 3164571Sgibbs return (NULL); 31745775Speter } 3181553Srgrimes cp = line; 3191553Srgrimes *cp++ = ch; 3201553Srgrimes while ((ch = getc(fp)) != EOF) { 3211553Srgrimes if (isspace(ch)) 3221553Srgrimes break; 3231553Srgrimes *cp++ = ch; 3241553Srgrimes } 3251553Srgrimes *cp = 0; 3261553Srgrimes if (ch == EOF) 3271553Srgrimes return ((char *)EOF); 3281553Srgrimes (void) ungetc(ch, fp); 3291553Srgrimes return (line); 3301553Srgrimes} 3311553Srgrimes 3321553Srgrimes/* 3331553Srgrimes * get_quoted_word 3341553Srgrimes * like get_word but will accept something in double or single quotes 3351553Srgrimes * (to allow embedded spaces). 3361553Srgrimes */ 3371553Srgrimeschar * 33861640Speterget_quoted_word(FILE *fp) 3391553Srgrimes{ 3401553Srgrimes static char line[256]; 34161640Speter int ch; 34261640Speter char *cp; 3434571Sgibbs int escaped_nl = 0; 3441553Srgrimes 3454571Sgibbsbegin: 3461553Srgrimes while ((ch = getc(fp)) != EOF) 3471553Srgrimes if (ch != ' ' && ch != '\t') 3481553Srgrimes break; 3491553Srgrimes if (ch == EOF) 3501553Srgrimes return ((char *)EOF); 3514571Sgibbs if (ch == '\\'){ 3524571Sgibbs escaped_nl = 1; 3534571Sgibbs goto begin; 3544571Sgibbs } 35545775Speter if (ch == '\n') { 3564571Sgibbs if (escaped_nl){ 3574571Sgibbs escaped_nl = 0; 3584571Sgibbs goto begin; 3594571Sgibbs } 3604571Sgibbs else 3614571Sgibbs return (NULL); 36245775Speter } 3631553Srgrimes cp = line; 3641553Srgrimes if (ch == '"' || ch == '\'') { 36561640Speter int quote = ch; 3661553Srgrimes 3671553Srgrimes while ((ch = getc(fp)) != EOF) { 3681553Srgrimes if (ch == quote) 3691553Srgrimes break; 3701553Srgrimes if (ch == '\n') { 3711553Srgrimes *cp = 0; 3721553Srgrimes printf("config: missing quote reading `%s'\n", 3731553Srgrimes line); 3741553Srgrimes exit(2); 3751553Srgrimes } 3761553Srgrimes *cp++ = ch; 3771553Srgrimes } 3781553Srgrimes } else { 3791553Srgrimes *cp++ = ch; 3801553Srgrimes while ((ch = getc(fp)) != EOF) { 3811553Srgrimes if (isspace(ch)) 3821553Srgrimes break; 3831553Srgrimes *cp++ = ch; 3841553Srgrimes } 3851553Srgrimes if (ch != EOF) 3861553Srgrimes (void) ungetc(ch, fp); 3871553Srgrimes } 3881553Srgrimes *cp = 0; 3891553Srgrimes if (ch == EOF) 3901553Srgrimes return ((char *)EOF); 3911553Srgrimes return (line); 3921553Srgrimes} 3931553Srgrimes 3941553Srgrimes/* 3951553Srgrimes * prepend the path to a filename 3961553Srgrimes */ 3971553Srgrimeschar * 39872684Speterpath(const char *file) 3991553Srgrimes{ 40069004Simp char *cp = NULL; 4011553Srgrimes 40269004Simp if (file) 40369004Simp asprintf(&cp, "%s/%s", destdir, file); 40469004Simp else 40569004Simp cp = strdup(destdir); 4061553Srgrimes return (cp); 4071553Srgrimes} 40813400Speter 409169507Swkoszek/* 410169507Swkoszek * Generate configuration file based on actual settings. With this mode, user 411169507Swkoszek * will be able to obtain and build conifguration file with one command. 412169507Swkoszek */ 41345744Speterstatic void 414169507Swkoszekconfigfile_dynamic(struct sbuf *sb) 415169507Swkoszek{ 416169507Swkoszek struct cputype *cput; 417169507Swkoszek struct device *d; 418169507Swkoszek struct opt *ol; 419169507Swkoszek char *lend; 420169512Swkoszek unsigned int i; 421169507Swkoszek 422169507Swkoszek asprintf(&lend, "\\n\\\n"); 423169507Swkoszek assert(lend != NULL); 424169507Swkoszek sbuf_printf(sb, "options\t%s%s", OPT_AUTOGEN, lend); 425169507Swkoszek sbuf_printf(sb, "ident\t%s%s", ident, lend); 426169507Swkoszek sbuf_printf(sb, "machine\t%s%s", machinename, lend); 427169507Swkoszek SLIST_FOREACH(cput, &cputype, cpu_next) 428169507Swkoszek sbuf_printf(sb, "cpu\t%s%s", cput->cpu_name, lend); 429169507Swkoszek SLIST_FOREACH(ol, &mkopt, op_next) 430169507Swkoszek sbuf_printf(sb, "makeoptions\t%s=%s%s", ol->op_name, 431169507Swkoszek ol->op_value, lend); 432169507Swkoszek SLIST_FOREACH(ol, &opt, op_next) { 433169507Swkoszek if (strncmp(ol->op_name, "DEV_", 4) == 0) 434169507Swkoszek continue; 435169507Swkoszek sbuf_printf(sb, "options\t%s", ol->op_name); 436169507Swkoszek if (ol->op_value != NULL) { 437169512Swkoszek sbuf_putc(sb, '='); 438169512Swkoszek for (i = 0; i < strlen(ol->op_value); i++) { 439169512Swkoszek if (ol->op_value[i] == '"') 440169512Swkoszek sbuf_printf(sb, "\\%c", 441169512Swkoszek ol->op_value[i]); 442169512Swkoszek else 443169512Swkoszek sbuf_printf(sb, "%c", 444169512Swkoszek ol->op_value[i]); 445169512Swkoszek } 446169512Swkoszek sbuf_printf(sb, "%s", lend); 447169507Swkoszek } else { 448169507Swkoszek sbuf_printf(sb, "%s", lend); 449169507Swkoszek } 450169507Swkoszek } 451169507Swkoszek /* 452169507Swkoszek * Mark this file as containing everything we need. 453169507Swkoszek */ 454169507Swkoszek STAILQ_FOREACH(d, &dtab, d_next) 455169507Swkoszek sbuf_printf(sb, "device\t%s%s", d->d_name, lend); 456169507Swkoszek free(lend); 457169507Swkoszek} 458169507Swkoszek 459169507Swkoszek/* 460169507Swkoszek * Generate file from the configuration files. 461169507Swkoszek */ 462169507Swkoszekstatic void 463169507Swkoszekconfigfile_filebased(struct sbuf *sb) 464169507Swkoszek{ 465169507Swkoszek FILE *cff; 466169507Swkoszek struct cfgfile *cf; 467169507Swkoszek int i; 468169507Swkoszek 469169507Swkoszek STAILQ_FOREACH(cf, &cfgfiles, cfg_next) { 470169507Swkoszek cff = fopen(cf->cfg_path, "r"); 471169507Swkoszek if (cff == NULL) { 472169507Swkoszek warn("Couldn't open file %s", cf->cfg_path); 473169507Swkoszek continue; 474169507Swkoszek } 475169507Swkoszek while ((i = getc(cff)) != EOF) { 476169507Swkoszek if (i == '\n') 477169507Swkoszek sbuf_printf(sb, "\\n\\\n"); 478169507Swkoszek else if (i == '"' || i == '\'') 479169507Swkoszek sbuf_printf(sb, "\\%c", i); 480169507Swkoszek else 481169507Swkoszek sbuf_putc(sb, i); 482169507Swkoszek } 483169507Swkoszek fclose(cff); 484169507Swkoszek } 485169507Swkoszek} 486169507Swkoszek 487169507Swkoszekstatic void 48861640Speterconfigfile(void) 48916239Sjkh{ 490169507Swkoszek FILE *fo; 491169507Swkoszek struct sbuf *sb; 49216239Sjkh char *p; 493169507Swkoszek 494169507Swkoszek /* Add main configuration file to the list of files to be included */ 495169507Swkoszek cfgfile_add(PREFIX); 496169507Swkoszek p = path("config.c.new"); 497169507Swkoszek fo = fopen(p, "w"); 49852098Speter if (!fo) 49929451Scharnier err(2, "%s", p); 500169507Swkoszek sb = sbuf_new(NULL, NULL, 2048, SBUF_AUTOEXTEND); 501169507Swkoszek assert(sb != NULL); 502169507Swkoszek sbuf_clear(sb); 503169507Swkoszek /* 504169507Swkoszek * Try to read all configuration files. Since those will be present as 505169507Swkoszek * C string in the macro, we have to slash their ends then the line 506169507Swkoszek * wraps. 507169507Swkoszek */ 508169507Swkoszek if (filebased) { 509169507Swkoszek /* Is needed, can be used for backward compatibility. */ 510169507Swkoszek configfile_filebased(sb); 511169507Swkoszek } else { 512169507Swkoszek configfile_dynamic(sb); 51316239Sjkh } 514169507Swkoszek sbuf_finish(sb); 515169507Swkoszek /* 516169507Swkoszek * We print first part of the tamplate, replace our tag with 517169507Swkoszek * configuration files content and later continue writing our 518169507Swkoszek * template. 519169507Swkoszek */ 520169507Swkoszek p = strstr(kernconfstr, KERNCONFTAG); 521169507Swkoszek if (p == NULL) 522169507Swkoszek errx(EXIT_FAILURE, "Something went terribly wrong!"); 523169507Swkoszek *p = '\0'; 524169507Swkoszek fprintf(fo, "%s", kernconfstr); 525169507Swkoszek fprintf(fo, "%s", sbuf_data(sb)); 526169507Swkoszek p += strlen(KERNCONFTAG); 527169507Swkoszek fprintf(fo, "%s", p); 528169507Swkoszek sbuf_delete(sb); 52916239Sjkh fclose(fo); 53020940Speter moveifchanged(path("config.c.new"), path("config.c")); 531169507Swkoszek cfgfile_removeall(); 53216239Sjkh} 53316239Sjkh 53413400Speter/* 53513400Speter * moveifchanged -- 53613400Speter * compare two files; rename if changed. 53713400Speter */ 53813400Spetervoid 53913400Spetermoveifchanged(const char *from_name, const char *to_name) 54013400Speter{ 54113400Speter char *p, *q; 54213400Speter int changed; 54313400Speter size_t tsize; 54413400Speter struct stat from_sb, to_sb; 54513400Speter int from_fd, to_fd; 54613400Speter 54713400Speter changed = 0; 54813400Speter 54913400Speter if ((from_fd = open(from_name, O_RDONLY)) < 0) 55013400Speter err(EX_OSERR, "moveifchanged open(%s)", from_name); 55113400Speter 55213400Speter if ((to_fd = open(to_name, O_RDONLY)) < 0) 55313400Speter changed++; 55413400Speter 55513400Speter if (!changed && fstat(from_fd, &from_sb) < 0) 55613400Speter err(EX_OSERR, "moveifchanged fstat(%s)", from_name); 55713400Speter 55813400Speter if (!changed && fstat(to_fd, &to_sb) < 0) 55913400Speter err(EX_OSERR, "moveifchanged fstat(%s)", to_name); 56013400Speter 56113400Speter if (!changed && from_sb.st_size != to_sb.st_size) 56213400Speter changed++; 56313400Speter 56413400Speter tsize = (size_t)from_sb.st_size; 56513400Speter 56613400Speter if (!changed) { 56721786Salex p = mmap(NULL, tsize, PROT_READ, MAP_SHARED, from_fd, (off_t)0); 56836813Sdfr#ifndef MAP_FAILED 56936813Sdfr#define MAP_FAILED ((caddr_t) -1) 57036813Sdfr#endif 57121786Salex if (p == MAP_FAILED) 57213400Speter err(EX_OSERR, "mmap %s", from_name); 57321786Salex q = mmap(NULL, tsize, PROT_READ, MAP_SHARED, to_fd, (off_t)0); 57421786Salex if (q == MAP_FAILED) 57513400Speter err(EX_OSERR, "mmap %s", to_name); 57613400Speter 57713400Speter changed = memcmp(p, q, tsize); 57813400Speter munmap(p, tsize); 57913400Speter munmap(q, tsize); 58013400Speter } 58113400Speter if (changed) { 58213400Speter if (rename(from_name, to_name) < 0) 58313400Speter err(EX_OSERR, "rename(%s, %s)", from_name, to_name); 58413400Speter } else { 58513400Speter if (unlink(from_name) < 0) 58631216Sjdp err(EX_OSERR, "unlink(%s)", from_name); 58713400Speter } 58813400Speter} 58971784Speter 59071784Speterstatic void 59171866Spetercleanheaders(char *p) 59271784Speter{ 59371784Speter DIR *dirp; 59471784Speter struct dirent *dp; 59571784Speter struct file_list *fl; 59671866Speter struct hdr_list *hl; 59771784Speter int i; 59871784Speter 59971866Speter remember("y.tab.h"); 60071866Speter remember("setdefs.h"); 601110895Sru STAILQ_FOREACH(fl, &ftab, f_next) 60271866Speter remember(fl->f_fn); 60371784Speter 60471784Speter /* 60571784Speter * Scan the build directory and clean out stuff that looks like 60671784Speter * it might have been a leftover NFOO header, etc. 60771784Speter */ 608116257Stmm if ((dirp = opendir(p)) == NULL) 609116257Stmm err(EX_OSERR, "opendir %s", p); 61071784Speter while ((dp = readdir(dirp)) != NULL) { 61171784Speter i = dp->d_namlen - 2; 61271784Speter /* Skip non-headers */ 61371784Speter if (dp->d_name[i] != '.' || dp->d_name[i + 1] != 'h') 61471784Speter continue; 61571784Speter /* Skip special stuff, eg: bus_if.h, but check opt_*.h */ 61671784Speter if (index(dp->d_name, '_') && 61771784Speter strncmp(dp->d_name, "opt_", 4) != 0) 61871784Speter continue; 61971784Speter /* Check if it is a target file */ 62071866Speter for (hl = htab; hl != NULL; hl = hl->h_next) { 621152963Sru if (eq(dp->d_name, hl->h_name)) { 62271784Speter break; 62371784Speter } 62471784Speter } 62571866Speter if (hl) 62671784Speter continue; 62771784Speter printf("Removing stale header: %s\n", dp->d_name); 628116257Stmm if (unlink(path(dp->d_name)) == -1) 629116257Stmm warn("unlink %s", dp->d_name); 63071784Speter } 63171784Speter (void)closedir(dirp); 63271866Speter} 63371784Speter 63471866Spetervoid 63572684Speterremember(const char *file) 63671866Speter{ 63771866Speter char *s; 63871866Speter struct hdr_list *hl; 63971866Speter 64071866Speter if ((s = strrchr(file, '/')) != NULL) 64172684Speter s = ns(s + 1); 64271866Speter else 64372684Speter s = ns(file); 64471866Speter 64571866Speter if (index(s, '_') && strncmp(s, "opt_", 4) != 0) { 64671866Speter free(s); 64771866Speter return; 64871866Speter } 64971866Speter for (hl = htab; hl != NULL; hl = hl->h_next) { 650152963Sru if (eq(s, hl->h_name)) { 65171866Speter free(s); 65271866Speter return; 65371866Speter } 65471866Speter } 655159362Sdelphij hl = calloc(1, sizeof(*hl)); 65671866Speter hl->h_name = s; 65771866Speter hl->h_next = htab; 65871866Speter htab = hl; 65971784Speter} 660169507Swkoszek 661169507Swkoszek/* 662169507Swkoszek * This one is quick hack. Will be probably moved to elf(3) interface. 663169507Swkoszek * It takes kernel configuration file name, passes it as an argument to 664169507Swkoszek * elfdump -a, which output is parsed by some UNIX tools... 665169507Swkoszek */ 666169507Swkoszekstatic void 667169507Swkoszekkernconfdump(const char *file) 668169507Swkoszek{ 669169507Swkoszek struct stat st; 670169507Swkoszek FILE *fp, *pp; 671169507Swkoszek int error, len, osz, r; 672169507Swkoszek unsigned int off, size; 673169507Swkoszek char *cmd, *o; 674169507Swkoszek 675169507Swkoszek r = open(file, O_RDONLY); 676169507Swkoszek if (r == -1) 677169507Swkoszek errx(EXIT_FAILURE, "Couldn't open file '%s'", file); 678169507Swkoszek error = fstat(r, &st); 679169507Swkoszek if (error == -1) 680169507Swkoszek errx(EXIT_FAILURE, "fstat() failed"); 681169507Swkoszek if (S_ISDIR(st.st_mode)) 682169507Swkoszek errx(EXIT_FAILURE, "'%s' is a directory", file); 683169507Swkoszek fp = fdopen(r, "r"); 684169507Swkoszek if (fp == NULL) 685169507Swkoszek errx(EXIT_FAILURE, "fdopen() failed"); 686169507Swkoszek osz = 1024; 687169507Swkoszek o = calloc(1, osz); 688169507Swkoszek if (o == NULL) 689169507Swkoszek errx(EXIT_FAILURE, "Couldn't allocate memory"); 690169507Swkoszek /* ELF note section header. */ 691169507Swkoszek asprintf(&cmd, "/usr/bin/elfdump -c %s | grep -A 5 kern_conf" 692169507Swkoszek "| tail -2 | cut -d ' ' -f 2 | paste - - -", file); 693169507Swkoszek if (cmd == NULL) 694169507Swkoszek errx(EXIT_FAILURE, "asprintf() failed"); 695169507Swkoszek pp = popen(cmd, "r"); 696169507Swkoszek if (pp == NULL) 697169507Swkoszek errx(EXIT_FAILURE, "popen() failed"); 698169507Swkoszek free(cmd); 699169507Swkoszek len = fread(o, osz, 1, pp); 700169507Swkoszek pclose(pp); 701169507Swkoszek r = sscanf(o, "%d\t%d", &off, &size); 702169507Swkoszek free(o); 703169507Swkoszek if (r != 2) 704169507Swkoszek errx(EXIT_FAILURE, "File %s doesn't contain configuration " 705169507Swkoszek "file. Either unsupported, or not compiled with " 706169507Swkoszek "INCLUDE_CONFIG_FILE", file); 707169507Swkoszek r = fseek(fp, off, SEEK_CUR); 708169507Swkoszek if (r != 0) 709169507Swkoszek errx(EXIT_FAILURE, "fseek() failed"); 710169507Swkoszek while ((r = fgetc(fp)) != EOF && size-- > 0) 711169507Swkoszek fputc(r, stdout); 712169507Swkoszek fclose(fp); 713169507Swkoszek} 714