main.c revision 175163
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 175163 2008-01-08 21:10:13Z emaste $"; 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; 153169647Simp if (freopen("DEFAULTS", "r", stdin) != NULL) { 154169647Simp found_defaults = 1; 155169647Simp yyfile = "DEFAULTS"; 156169647Simp } else { 157169647Simp if (freopen(PREFIX, "r", stdin) == NULL) 158169647Simp err(2, "%s", PREFIX); 159169647Simp yyfile = PREFIX; 160169647Simp } 16152653Smarcel if (*destdir != '\0') { 16252653Smarcel len = strlen(destdir); 16352653Smarcel while (len > 1 && destdir[len - 1] == '/') 16452653Smarcel destdir[--len] = '\0'; 16552653Smarcel get_srcdir(); 16652653Smarcel } else { 16769004Simp strlcpy(destdir, CDIR, sizeof(destdir)); 16869004Simp strlcat(destdir, PREFIX, sizeof(destdir)); 16952653Smarcel } 17052653Smarcel 1712483Sjkh p = path((char *)NULL); 1722483Sjkh if (stat(p, &buf)) { 17329451Scharnier if (mkdir(p, 0777)) 17429451Scharnier err(2, "%s", p); 175152963Sru } else if (!S_ISDIR(buf.st_mode)) 17629451Scharnier errx(2, "%s isn't a directory", p); 1771553Srgrimes 178169507Swkoszek SLIST_INIT(&cputype); 179169507Swkoszek SLIST_INIT(&mkopt); 180169507Swkoszek SLIST_INIT(&opt); 181169507Swkoszek SLIST_INIT(&rmopts); 182169507Swkoszek STAILQ_INIT(&cfgfiles); 183110895Sru STAILQ_INIT(&dtab); 184129073Scognet STAILQ_INIT(&fntab); 185129073Scognet STAILQ_INIT(&ftab); 186163638Simp STAILQ_INIT(&hints); 1871553Srgrimes if (yyparse()) 1881553Srgrimes exit(3); 189153888Sru 190153888Sru /* 191153888Sru * Ensure that required elements (machine, cpu, ident) are present. 192153888Sru */ 19372000Speter if (machinename == NULL) { 19445775Speter printf("Specify machine type, e.g. ``machine i386''\n"); 1951553Srgrimes exit(1); 1961553Srgrimes } 197153888Sru if (ident == NULL) { 198153888Sru printf("no ident line specified\n"); 199153888Sru exit(1); 200153888Sru } 201153888Sru if (SLIST_EMPTY(&cputype)) { 202153888Sru printf("cpu type must be specified\n"); 203153888Sru exit(1); 204153888Sru } 205153888Sru 2061553Srgrimes /* 2071553Srgrimes * make symbolic links in compilation directory 2081553Srgrimes * for "sys" (to make genassym.c work along with #include <sys/xxx>) 2091553Srgrimes * and similarly for "machine". 2101553Srgrimes */ 21152653Smarcel if (*srcdir == '\0') 21279013Simp (void)snprintf(xxx, sizeof(xxx), "../../include"); 21352653Smarcel else 21452653Smarcel (void)snprintf(xxx, sizeof(xxx), "%s/%s/include", 21552653Smarcel srcdir, machinename); 21679694Speter (void) unlink(path("machine")); 2171553Srgrimes (void) symlink(xxx, path("machine")); 218144509Simp if (strcmp(machinename, machinearch) != 0) { 219144509Simp /* 220144509Simp * make symbolic links in compilation directory for 221144509Simp * machinearch, if it is different than machinename. 222144509Simp */ 223144509Simp if (*srcdir == '\0') 224144509Simp (void)snprintf(xxx, sizeof(xxx), "../../../%s/include", 225144509Simp machinearch); 226144509Simp else 227144509Simp (void)snprintf(xxx, sizeof(xxx), "%s/%s/include", 228144509Simp srcdir, machinearch); 229144509Simp (void) unlink(path(machinearch)); 230144509Simp (void) symlink(xxx, path(machinearch)); 231144509Simp } 232169507Swkoszek configfile(); /* put config file into kernel*/ 23312772Speter options(); /* make options .h files */ 2341553Srgrimes makefile(); /* build Makefile */ 235153888Sru makeenv(); /* build env.c */ 236153888Sru makehints(); /* build hints.c */ 2371553Srgrimes headers(); /* make a lot of .h files */ 23871866Speter cleanheaders(p); 2398248Sjkh printf("Kernel build directory is %s\n", p); 240154338Sflz printf("Don't forget to do ``make cleandepend && make depend''\n"); 2411553Srgrimes exit(0); 2421553Srgrimes} 2431553Srgrimes 24452653Smarcel/* 24552653Smarcel * get_srcdir 24652653Smarcel * determine the root of the kernel source tree 24752653Smarcel * and save that in srcdir. 24852653Smarcel */ 24929451Scharnierstatic void 25061640Speterget_srcdir(void) 25152653Smarcel{ 252175163Semaste struct stat lg, phy; 253175163Semaste char *p, *pwd; 254175163Semaste int i; 25552653Smarcel 25670673Speter if (realpath("../..", srcdir) == NULL) 25770673Speter errx(2, "Unable to find root of source tree"); 258175163Semaste if ((pwd = getenv("PWD")) != NULL && *pwd == '/' && 259175163Semaste (pwd = strdup(pwd)) != NULL) { 260175163Semaste /* Remove the last two path components. */ 261175163Semaste for (i = 0; i < 2; i++) { 262175163Semaste if ((p = strrchr(pwd, '/')) == NULL) { 263175163Semaste free(pwd); 264175163Semaste return; 265175163Semaste } 266175163Semaste *p = '\0'; 267175163Semaste } 268175163Semaste if (stat(pwd, &lg) != -1 && stat(srcdir, &phy) != -1 && 269175163Semaste lg.st_dev == phy.st_dev && lg.st_ino == phy.st_ino) 270175163Semaste strlcpy(srcdir, pwd, MAXPATHLEN); 271175163Semaste free(pwd); 272175163Semaste } 27352653Smarcel} 27452653Smarcel 27552653Smarcelstatic void 27661640Speterusage(void) 27729451Scharnier{ 278144352Simp 279169507Swkoszek fprintf(stderr, "usage: config [-CgpV] [-d destdir] sysname\n"); 280169507Swkoszek fprintf(stderr, " config -x kernel\n"); 281169507Swkoszek exit(EX_USAGE); 28229451Scharnier} 28329451Scharnier 2841553Srgrimes/* 2851553Srgrimes * get_word 2861553Srgrimes * returns EOF on end of file 2871553Srgrimes * NULL on end of line 2881553Srgrimes * pointer to the word otherwise 2891553Srgrimes */ 2901553Srgrimeschar * 29161640Speterget_word(FILE *fp) 2921553Srgrimes{ 2931553Srgrimes static char line[80]; 29461640Speter int ch; 29561640Speter char *cp; 2964571Sgibbs int escaped_nl = 0; 2971553Srgrimes 2984571Sgibbsbegin: 2991553Srgrimes while ((ch = getc(fp)) != EOF) 3001553Srgrimes if (ch != ' ' && ch != '\t') 3011553Srgrimes break; 3021553Srgrimes if (ch == EOF) 3031553Srgrimes return ((char *)EOF); 3044571Sgibbs if (ch == '\\'){ 3054571Sgibbs escaped_nl = 1; 3064571Sgibbs goto begin; 3074571Sgibbs } 30845775Speter if (ch == '\n') { 3094571Sgibbs if (escaped_nl){ 3104571Sgibbs escaped_nl = 0; 3114571Sgibbs goto begin; 3124571Sgibbs } 3134571Sgibbs else 3144571Sgibbs return (NULL); 31545775Speter } 3161553Srgrimes cp = line; 3171553Srgrimes *cp++ = ch; 3181553Srgrimes while ((ch = getc(fp)) != EOF) { 3191553Srgrimes if (isspace(ch)) 3201553Srgrimes break; 3211553Srgrimes *cp++ = ch; 3221553Srgrimes } 3231553Srgrimes *cp = 0; 3241553Srgrimes if (ch == EOF) 3251553Srgrimes return ((char *)EOF); 3261553Srgrimes (void) ungetc(ch, fp); 3271553Srgrimes return (line); 3281553Srgrimes} 3291553Srgrimes 3301553Srgrimes/* 3311553Srgrimes * get_quoted_word 3321553Srgrimes * like get_word but will accept something in double or single quotes 3331553Srgrimes * (to allow embedded spaces). 3341553Srgrimes */ 3351553Srgrimeschar * 33661640Speterget_quoted_word(FILE *fp) 3371553Srgrimes{ 3381553Srgrimes static char line[256]; 33961640Speter int ch; 34061640Speter char *cp; 3414571Sgibbs int escaped_nl = 0; 3421553Srgrimes 3434571Sgibbsbegin: 3441553Srgrimes while ((ch = getc(fp)) != EOF) 3451553Srgrimes if (ch != ' ' && ch != '\t') 3461553Srgrimes break; 3471553Srgrimes if (ch == EOF) 3481553Srgrimes return ((char *)EOF); 3494571Sgibbs if (ch == '\\'){ 3504571Sgibbs escaped_nl = 1; 3514571Sgibbs goto begin; 3524571Sgibbs } 35345775Speter if (ch == '\n') { 3544571Sgibbs if (escaped_nl){ 3554571Sgibbs escaped_nl = 0; 3564571Sgibbs goto begin; 3574571Sgibbs } 3584571Sgibbs else 3594571Sgibbs return (NULL); 36045775Speter } 3611553Srgrimes cp = line; 3621553Srgrimes if (ch == '"' || ch == '\'') { 36361640Speter int quote = ch; 3641553Srgrimes 3651553Srgrimes while ((ch = getc(fp)) != EOF) { 3661553Srgrimes if (ch == quote) 3671553Srgrimes break; 3681553Srgrimes if (ch == '\n') { 3691553Srgrimes *cp = 0; 3701553Srgrimes printf("config: missing quote reading `%s'\n", 3711553Srgrimes line); 3721553Srgrimes exit(2); 3731553Srgrimes } 3741553Srgrimes *cp++ = ch; 3751553Srgrimes } 3761553Srgrimes } else { 3771553Srgrimes *cp++ = ch; 3781553Srgrimes while ((ch = getc(fp)) != EOF) { 3791553Srgrimes if (isspace(ch)) 3801553Srgrimes break; 3811553Srgrimes *cp++ = ch; 3821553Srgrimes } 3831553Srgrimes if (ch != EOF) 3841553Srgrimes (void) ungetc(ch, fp); 3851553Srgrimes } 3861553Srgrimes *cp = 0; 3871553Srgrimes if (ch == EOF) 3881553Srgrimes return ((char *)EOF); 3891553Srgrimes return (line); 3901553Srgrimes} 3911553Srgrimes 3921553Srgrimes/* 3931553Srgrimes * prepend the path to a filename 3941553Srgrimes */ 3951553Srgrimeschar * 39672684Speterpath(const char *file) 3971553Srgrimes{ 39869004Simp char *cp = NULL; 3991553Srgrimes 40069004Simp if (file) 40169004Simp asprintf(&cp, "%s/%s", destdir, file); 40269004Simp else 40369004Simp cp = strdup(destdir); 4041553Srgrimes return (cp); 4051553Srgrimes} 40613400Speter 407169507Swkoszek/* 408169507Swkoszek * Generate configuration file based on actual settings. With this mode, user 409169507Swkoszek * will be able to obtain and build conifguration file with one command. 410169507Swkoszek */ 41145744Speterstatic void 412169507Swkoszekconfigfile_dynamic(struct sbuf *sb) 413169507Swkoszek{ 414169507Swkoszek struct cputype *cput; 415169507Swkoszek struct device *d; 416169507Swkoszek struct opt *ol; 417169507Swkoszek char *lend; 418169512Swkoszek unsigned int i; 419169507Swkoszek 420169507Swkoszek asprintf(&lend, "\\n\\\n"); 421169507Swkoszek assert(lend != NULL); 422169507Swkoszek sbuf_printf(sb, "options\t%s%s", OPT_AUTOGEN, lend); 423169507Swkoszek sbuf_printf(sb, "ident\t%s%s", ident, lend); 424169507Swkoszek sbuf_printf(sb, "machine\t%s%s", machinename, lend); 425169507Swkoszek SLIST_FOREACH(cput, &cputype, cpu_next) 426169507Swkoszek sbuf_printf(sb, "cpu\t%s%s", cput->cpu_name, lend); 427169507Swkoszek SLIST_FOREACH(ol, &mkopt, op_next) 428169507Swkoszek sbuf_printf(sb, "makeoptions\t%s=%s%s", ol->op_name, 429169507Swkoszek ol->op_value, lend); 430169507Swkoszek SLIST_FOREACH(ol, &opt, op_next) { 431169507Swkoszek if (strncmp(ol->op_name, "DEV_", 4) == 0) 432169507Swkoszek continue; 433169507Swkoszek sbuf_printf(sb, "options\t%s", ol->op_name); 434169507Swkoszek if (ol->op_value != NULL) { 435169512Swkoszek sbuf_putc(sb, '='); 436169512Swkoszek for (i = 0; i < strlen(ol->op_value); i++) { 437169512Swkoszek if (ol->op_value[i] == '"') 438169512Swkoszek sbuf_printf(sb, "\\%c", 439169512Swkoszek ol->op_value[i]); 440169512Swkoszek else 441169512Swkoszek sbuf_printf(sb, "%c", 442169512Swkoszek ol->op_value[i]); 443169512Swkoszek } 444169512Swkoszek sbuf_printf(sb, "%s", lend); 445169507Swkoszek } else { 446169507Swkoszek sbuf_printf(sb, "%s", lend); 447169507Swkoszek } 448169507Swkoszek } 449169507Swkoszek /* 450169507Swkoszek * Mark this file as containing everything we need. 451169507Swkoszek */ 452169507Swkoszek STAILQ_FOREACH(d, &dtab, d_next) 453169507Swkoszek sbuf_printf(sb, "device\t%s%s", d->d_name, lend); 454169507Swkoszek free(lend); 455169507Swkoszek} 456169507Swkoszek 457169507Swkoszek/* 458169507Swkoszek * Generate file from the configuration files. 459169507Swkoszek */ 460169507Swkoszekstatic void 461169507Swkoszekconfigfile_filebased(struct sbuf *sb) 462169507Swkoszek{ 463169507Swkoszek FILE *cff; 464169507Swkoszek struct cfgfile *cf; 465169507Swkoszek int i; 466169507Swkoszek 467169507Swkoszek STAILQ_FOREACH(cf, &cfgfiles, cfg_next) { 468169507Swkoszek cff = fopen(cf->cfg_path, "r"); 469169507Swkoszek if (cff == NULL) { 470169507Swkoszek warn("Couldn't open file %s", cf->cfg_path); 471169507Swkoszek continue; 472169507Swkoszek } 473169507Swkoszek while ((i = getc(cff)) != EOF) { 474169507Swkoszek if (i == '\n') 475169507Swkoszek sbuf_printf(sb, "\\n\\\n"); 476169507Swkoszek else if (i == '"' || i == '\'') 477169507Swkoszek sbuf_printf(sb, "\\%c", i); 478169507Swkoszek else 479169507Swkoszek sbuf_putc(sb, i); 480169507Swkoszek } 481169507Swkoszek fclose(cff); 482169507Swkoszek } 483169507Swkoszek} 484169507Swkoszek 485169507Swkoszekstatic void 48661640Speterconfigfile(void) 48716239Sjkh{ 488169507Swkoszek FILE *fo; 489169507Swkoszek struct sbuf *sb; 49016239Sjkh char *p; 491169507Swkoszek 492169507Swkoszek /* Add main configuration file to the list of files to be included */ 493169507Swkoszek cfgfile_add(PREFIX); 494169507Swkoszek p = path("config.c.new"); 495169507Swkoszek fo = fopen(p, "w"); 49652098Speter if (!fo) 49729451Scharnier err(2, "%s", p); 498169507Swkoszek sb = sbuf_new(NULL, NULL, 2048, SBUF_AUTOEXTEND); 499169507Swkoszek assert(sb != NULL); 500169507Swkoszek sbuf_clear(sb); 501169507Swkoszek /* 502169507Swkoszek * Try to read all configuration files. Since those will be present as 503169507Swkoszek * C string in the macro, we have to slash their ends then the line 504169507Swkoszek * wraps. 505169507Swkoszek */ 506169507Swkoszek if (filebased) { 507169507Swkoszek /* Is needed, can be used for backward compatibility. */ 508169507Swkoszek configfile_filebased(sb); 509169507Swkoszek } else { 510169507Swkoszek configfile_dynamic(sb); 51116239Sjkh } 512169507Swkoszek sbuf_finish(sb); 513169507Swkoszek /* 514169507Swkoszek * We print first part of the tamplate, replace our tag with 515169507Swkoszek * configuration files content and later continue writing our 516169507Swkoszek * template. 517169507Swkoszek */ 518169507Swkoszek p = strstr(kernconfstr, KERNCONFTAG); 519169507Swkoszek if (p == NULL) 520169507Swkoszek errx(EXIT_FAILURE, "Something went terribly wrong!"); 521169507Swkoszek *p = '\0'; 522169507Swkoszek fprintf(fo, "%s", kernconfstr); 523169507Swkoszek fprintf(fo, "%s", sbuf_data(sb)); 524169507Swkoszek p += strlen(KERNCONFTAG); 525169507Swkoszek fprintf(fo, "%s", p); 526169507Swkoszek sbuf_delete(sb); 52716239Sjkh fclose(fo); 52820940Speter moveifchanged(path("config.c.new"), path("config.c")); 529169507Swkoszek cfgfile_removeall(); 53016239Sjkh} 53116239Sjkh 53213400Speter/* 53313400Speter * moveifchanged -- 53413400Speter * compare two files; rename if changed. 53513400Speter */ 53613400Spetervoid 53713400Spetermoveifchanged(const char *from_name, const char *to_name) 53813400Speter{ 53913400Speter char *p, *q; 54013400Speter int changed; 54113400Speter size_t tsize; 54213400Speter struct stat from_sb, to_sb; 54313400Speter int from_fd, to_fd; 54413400Speter 54513400Speter changed = 0; 54613400Speter 54713400Speter if ((from_fd = open(from_name, O_RDONLY)) < 0) 54813400Speter err(EX_OSERR, "moveifchanged open(%s)", from_name); 54913400Speter 55013400Speter if ((to_fd = open(to_name, O_RDONLY)) < 0) 55113400Speter changed++; 55213400Speter 55313400Speter if (!changed && fstat(from_fd, &from_sb) < 0) 55413400Speter err(EX_OSERR, "moveifchanged fstat(%s)", from_name); 55513400Speter 55613400Speter if (!changed && fstat(to_fd, &to_sb) < 0) 55713400Speter err(EX_OSERR, "moveifchanged fstat(%s)", to_name); 55813400Speter 55913400Speter if (!changed && from_sb.st_size != to_sb.st_size) 56013400Speter changed++; 56113400Speter 56213400Speter tsize = (size_t)from_sb.st_size; 56313400Speter 56413400Speter if (!changed) { 56521786Salex p = mmap(NULL, tsize, PROT_READ, MAP_SHARED, from_fd, (off_t)0); 56636813Sdfr#ifndef MAP_FAILED 56736813Sdfr#define MAP_FAILED ((caddr_t) -1) 56836813Sdfr#endif 56921786Salex if (p == MAP_FAILED) 57013400Speter err(EX_OSERR, "mmap %s", from_name); 57121786Salex q = mmap(NULL, tsize, PROT_READ, MAP_SHARED, to_fd, (off_t)0); 57221786Salex if (q == MAP_FAILED) 57313400Speter err(EX_OSERR, "mmap %s", to_name); 57413400Speter 57513400Speter changed = memcmp(p, q, tsize); 57613400Speter munmap(p, tsize); 57713400Speter munmap(q, tsize); 57813400Speter } 57913400Speter if (changed) { 58013400Speter if (rename(from_name, to_name) < 0) 58113400Speter err(EX_OSERR, "rename(%s, %s)", from_name, to_name); 58213400Speter } else { 58313400Speter if (unlink(from_name) < 0) 58431216Sjdp err(EX_OSERR, "unlink(%s)", from_name); 58513400Speter } 58613400Speter} 58771784Speter 58871784Speterstatic void 58971866Spetercleanheaders(char *p) 59071784Speter{ 59171784Speter DIR *dirp; 59271784Speter struct dirent *dp; 59371784Speter struct file_list *fl; 59471866Speter struct hdr_list *hl; 59571784Speter int i; 59671784Speter 59771866Speter remember("y.tab.h"); 59871866Speter remember("setdefs.h"); 599110895Sru STAILQ_FOREACH(fl, &ftab, f_next) 60071866Speter remember(fl->f_fn); 60171784Speter 60271784Speter /* 60371784Speter * Scan the build directory and clean out stuff that looks like 60471784Speter * it might have been a leftover NFOO header, etc. 60571784Speter */ 606116257Stmm if ((dirp = opendir(p)) == NULL) 607116257Stmm err(EX_OSERR, "opendir %s", p); 60871784Speter while ((dp = readdir(dirp)) != NULL) { 60971784Speter i = dp->d_namlen - 2; 61071784Speter /* Skip non-headers */ 61171784Speter if (dp->d_name[i] != '.' || dp->d_name[i + 1] != 'h') 61271784Speter continue; 61371784Speter /* Skip special stuff, eg: bus_if.h, but check opt_*.h */ 61471784Speter if (index(dp->d_name, '_') && 61571784Speter strncmp(dp->d_name, "opt_", 4) != 0) 61671784Speter continue; 61771784Speter /* Check if it is a target file */ 61871866Speter for (hl = htab; hl != NULL; hl = hl->h_next) { 619152963Sru if (eq(dp->d_name, hl->h_name)) { 62071784Speter break; 62171784Speter } 62271784Speter } 62371866Speter if (hl) 62471784Speter continue; 62571784Speter printf("Removing stale header: %s\n", dp->d_name); 626116257Stmm if (unlink(path(dp->d_name)) == -1) 627116257Stmm warn("unlink %s", dp->d_name); 62871784Speter } 62971784Speter (void)closedir(dirp); 63071866Speter} 63171784Speter 63271866Spetervoid 63372684Speterremember(const char *file) 63471866Speter{ 63571866Speter char *s; 63671866Speter struct hdr_list *hl; 63771866Speter 63871866Speter if ((s = strrchr(file, '/')) != NULL) 63972684Speter s = ns(s + 1); 64071866Speter else 64172684Speter s = ns(file); 64271866Speter 64371866Speter if (index(s, '_') && strncmp(s, "opt_", 4) != 0) { 64471866Speter free(s); 64571866Speter return; 64671866Speter } 64771866Speter for (hl = htab; hl != NULL; hl = hl->h_next) { 648152963Sru if (eq(s, hl->h_name)) { 64971866Speter free(s); 65071866Speter return; 65171866Speter } 65271866Speter } 653159362Sdelphij hl = calloc(1, sizeof(*hl)); 65471866Speter hl->h_name = s; 65571866Speter hl->h_next = htab; 65671866Speter htab = hl; 65771784Speter} 658169507Swkoszek 659169507Swkoszek/* 660169507Swkoszek * This one is quick hack. Will be probably moved to elf(3) interface. 661169507Swkoszek * It takes kernel configuration file name, passes it as an argument to 662169507Swkoszek * elfdump -a, which output is parsed by some UNIX tools... 663169507Swkoszek */ 664169507Swkoszekstatic void 665169507Swkoszekkernconfdump(const char *file) 666169507Swkoszek{ 667169507Swkoszek struct stat st; 668169507Swkoszek FILE *fp, *pp; 669169507Swkoszek int error, len, osz, r; 670169507Swkoszek unsigned int off, size; 671169507Swkoszek char *cmd, *o; 672169507Swkoszek 673169507Swkoszek r = open(file, O_RDONLY); 674169507Swkoszek if (r == -1) 675169507Swkoszek errx(EXIT_FAILURE, "Couldn't open file '%s'", file); 676169507Swkoszek error = fstat(r, &st); 677169507Swkoszek if (error == -1) 678169507Swkoszek errx(EXIT_FAILURE, "fstat() failed"); 679169507Swkoszek if (S_ISDIR(st.st_mode)) 680169507Swkoszek errx(EXIT_FAILURE, "'%s' is a directory", file); 681169507Swkoszek fp = fdopen(r, "r"); 682169507Swkoszek if (fp == NULL) 683169507Swkoszek errx(EXIT_FAILURE, "fdopen() failed"); 684169507Swkoszek osz = 1024; 685169507Swkoszek o = calloc(1, osz); 686169507Swkoszek if (o == NULL) 687169507Swkoszek errx(EXIT_FAILURE, "Couldn't allocate memory"); 688169507Swkoszek /* ELF note section header. */ 689169507Swkoszek asprintf(&cmd, "/usr/bin/elfdump -c %s | grep -A 5 kern_conf" 690169507Swkoszek "| tail -2 | cut -d ' ' -f 2 | paste - - -", file); 691169507Swkoszek if (cmd == NULL) 692169507Swkoszek errx(EXIT_FAILURE, "asprintf() failed"); 693169507Swkoszek pp = popen(cmd, "r"); 694169507Swkoszek if (pp == NULL) 695169507Swkoszek errx(EXIT_FAILURE, "popen() failed"); 696169507Swkoszek free(cmd); 697169507Swkoszek len = fread(o, osz, 1, pp); 698169507Swkoszek pclose(pp); 699169507Swkoszek r = sscanf(o, "%d\t%d", &off, &size); 700169507Swkoszek free(o); 701169507Swkoszek if (r != 2) 702169507Swkoszek errx(EXIT_FAILURE, "File %s doesn't contain configuration " 703169507Swkoszek "file. Either unsupported, or not compiled with " 704169507Swkoszek "INCLUDE_CONFIG_FILE", file); 705169507Swkoszek r = fseek(fp, off, SEEK_CUR); 706169507Swkoszek if (r != 0) 707169507Swkoszek errx(EXIT_FAILURE, "fseek() failed"); 708169507Swkoszek while ((r = fgetc(fp)) != EOF && size-- > 0) 709169507Swkoszek fputc(r, stdout); 710169507Swkoszek fclose(fp); 711169507Swkoszek} 712