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$"; 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 *); 93207260Simpstatic void checkversion(void); 9429451Scharnier 9571866Speterstruct hdr_list { 9671866Speter char *h_name; 9771866Speter struct hdr_list *h_next; 9871866Speter} *htab; 9971866Speter 1001553Srgrimes/* 1011553Srgrimes * Config builds a set of files for building a UNIX 1021553Srgrimes * system given a description of the desired system. 1031553Srgrimes */ 10429451Scharnierint 10561640Spetermain(int argc, char **argv) 1061553Srgrimes{ 1071553Srgrimes 1081553Srgrimes struct stat buf; 10952653Smarcel int ch, len; 1101553Srgrimes char *p; 111169507Swkoszek char *kernfile; 112264326Sasomers struct includepath* ipath; 113209969Snwhitehorn int printmachine; 1141553Srgrimes 115209969Snwhitehorn printmachine = 0; 116169507Swkoszek kernfile = NULL; 117264326Sasomers SLIST_INIT(&includepath); 118264326Sasomers while ((ch = getopt(argc, argv, "CI:d:gmpVx:")) != -1) 1191553Srgrimes switch (ch) { 120169507Swkoszek case 'C': 121169507Swkoszek filebased = 1; 122169507Swkoszek break; 123264326Sasomers case 'I': 124264326Sasomers ipath = (struct includepath *) \ 125264326Sasomers calloc(1, sizeof (struct includepath)); 126264326Sasomers if (ipath == NULL) 127264326Sasomers err(EXIT_FAILURE, "calloc"); 128264326Sasomers ipath->path = optarg; 129264326Sasomers SLIST_INSERT_HEAD(&includepath, ipath, path_next); 130264326Sasomers break; 131209969Snwhitehorn case 'm': 132209969Snwhitehorn printmachine = 1; 133209969Snwhitehorn break; 13452653Smarcel case 'd': 13552653Smarcel if (*destdir == '\0') 13669004Simp strlcpy(destdir, optarg, sizeof(destdir)); 13752653Smarcel else 138205880Sru errx(EXIT_FAILURE, "directory already set"); 13952653Smarcel break; 1401553Srgrimes case 'g': 14145579Sgrog debugging++; 1421553Srgrimes break; 1431553Srgrimes case 'p': 1441553Srgrimes profiling++; 1451553Srgrimes break; 146169507Swkoszek case 'V': 147169507Swkoszek printf("%d\n", CONFIGVERS); 148169507Swkoszek exit(0); 149169507Swkoszek case 'x': 150169507Swkoszek kernfile = optarg; 151169507Swkoszek break; 1521553Srgrimes case '?': 1531553Srgrimes default: 15429451Scharnier usage(); 1551553Srgrimes } 1561553Srgrimes argc -= optind; 1571553Srgrimes argv += optind; 1581553Srgrimes 159169507Swkoszek if (kernfile != NULL) { 160169507Swkoszek kernconfdump(kernfile); 161169507Swkoszek exit(EXIT_SUCCESS); 162169507Swkoszek } 163169507Swkoszek 16429451Scharnier if (argc != 1) 16529451Scharnier usage(); 1661553Srgrimes 167151744Sjhb PREFIX = *argv; 168178085Simp if (stat(PREFIX, &buf) != 0 || !S_ISREG(buf.st_mode)) 169178085Simp err(2, "%s", PREFIX); 170169647Simp if (freopen("DEFAULTS", "r", stdin) != NULL) { 171169647Simp found_defaults = 1; 172169647Simp yyfile = "DEFAULTS"; 173169647Simp } else { 174169647Simp if (freopen(PREFIX, "r", stdin) == NULL) 175169647Simp err(2, "%s", PREFIX); 176169647Simp yyfile = PREFIX; 177169647Simp } 17852653Smarcel if (*destdir != '\0') { 17952653Smarcel len = strlen(destdir); 18052653Smarcel while (len > 1 && destdir[len - 1] == '/') 18152653Smarcel destdir[--len] = '\0'; 18252653Smarcel get_srcdir(); 18352653Smarcel } else { 18469004Simp strlcpy(destdir, CDIR, sizeof(destdir)); 18569004Simp strlcat(destdir, PREFIX, sizeof(destdir)); 18652653Smarcel } 18752653Smarcel 188169507Swkoszek SLIST_INIT(&cputype); 189169507Swkoszek SLIST_INIT(&mkopt); 190169507Swkoszek SLIST_INIT(&opt); 191169507Swkoszek SLIST_INIT(&rmopts); 192169507Swkoszek STAILQ_INIT(&cfgfiles); 193110895Sru STAILQ_INIT(&dtab); 194129073Scognet STAILQ_INIT(&fntab); 195129073Scognet STAILQ_INIT(&ftab); 196163638Simp STAILQ_INIT(&hints); 1971553Srgrimes if (yyparse()) 1981553Srgrimes exit(3); 199153888Sru 200153888Sru /* 201153888Sru * Ensure that required elements (machine, cpu, ident) are present. 202153888Sru */ 20372000Speter if (machinename == NULL) { 20445775Speter printf("Specify machine type, e.g. ``machine i386''\n"); 2051553Srgrimes exit(1); 2061553Srgrimes } 207153888Sru if (ident == NULL) { 208153888Sru printf("no ident line specified\n"); 209153888Sru exit(1); 210153888Sru } 211153888Sru if (SLIST_EMPTY(&cputype)) { 212153888Sru printf("cpu type must be specified\n"); 213153888Sru exit(1); 214153888Sru } 215207260Simp checkversion(); 216153888Sru 217209969Snwhitehorn if (printmachine) { 218209969Snwhitehorn printf("%s\t%s\n",machinename,machinearch); 219209969Snwhitehorn exit(0); 220209969Snwhitehorn } 221209969Snwhitehorn 222209969Snwhitehorn /* Make compile directory */ 223209969Snwhitehorn p = path((char *)NULL); 224209969Snwhitehorn if (stat(p, &buf)) { 225209969Snwhitehorn if (mkdir(p, 0777)) 226209969Snwhitehorn err(2, "%s", p); 227209969Snwhitehorn } else if (!S_ISDIR(buf.st_mode)) 228209969Snwhitehorn errx(EXIT_FAILURE, "%s isn't a directory", p); 229209969Snwhitehorn 230169507Swkoszek configfile(); /* put config file into kernel*/ 23112772Speter options(); /* make options .h files */ 2321553Srgrimes makefile(); /* build Makefile */ 233153888Sru makeenv(); /* build env.c */ 234153888Sru makehints(); /* build hints.c */ 2351553Srgrimes headers(); /* make a lot of .h files */ 23671866Speter cleanheaders(p); 2378248Sjkh printf("Kernel build directory is %s\n", p); 238154338Sflz printf("Don't forget to do ``make cleandepend && make depend''\n"); 2391553Srgrimes exit(0); 2401553Srgrimes} 2411553Srgrimes 24252653Smarcel/* 24352653Smarcel * get_srcdir 24452653Smarcel * determine the root of the kernel source tree 24552653Smarcel * and save that in srcdir. 24652653Smarcel */ 24729451Scharnierstatic void 24861640Speterget_srcdir(void) 24952653Smarcel{ 250175163Semaste struct stat lg, phy; 251175163Semaste char *p, *pwd; 252175163Semaste int i; 25352653Smarcel 25470673Speter if (realpath("../..", srcdir) == NULL) 255205880Sru err(EXIT_FAILURE, "Unable to find root of source tree"); 256175163Semaste if ((pwd = getenv("PWD")) != NULL && *pwd == '/' && 257175163Semaste (pwd = strdup(pwd)) != NULL) { 258175163Semaste /* Remove the last two path components. */ 259175163Semaste for (i = 0; i < 2; i++) { 260175163Semaste if ((p = strrchr(pwd, '/')) == NULL) { 261175163Semaste free(pwd); 262175163Semaste return; 263175163Semaste } 264175163Semaste *p = '\0'; 265175163Semaste } 266175163Semaste if (stat(pwd, &lg) != -1 && stat(srcdir, &phy) != -1 && 267175163Semaste lg.st_dev == phy.st_dev && lg.st_ino == phy.st_ino) 268175163Semaste strlcpy(srcdir, pwd, MAXPATHLEN); 269175163Semaste free(pwd); 270175163Semaste } 27152653Smarcel} 27252653Smarcel 27352653Smarcelstatic void 27461640Speterusage(void) 27529451Scharnier{ 276144352Simp 277209969Snwhitehorn fprintf(stderr, "usage: config [-CgmpV] [-d destdir] sysname\n"); 278169507Swkoszek fprintf(stderr, " config -x kernel\n"); 279169507Swkoszek exit(EX_USAGE); 28029451Scharnier} 28129451Scharnier 2821553Srgrimes/* 2831553Srgrimes * get_word 2841553Srgrimes * returns EOF on end of file 2851553Srgrimes * NULL on end of line 2861553Srgrimes * pointer to the word otherwise 2871553Srgrimes */ 2881553Srgrimeschar * 28961640Speterget_word(FILE *fp) 2901553Srgrimes{ 2911553Srgrimes static char line[80]; 29261640Speter int ch; 29361640Speter char *cp; 2944571Sgibbs int escaped_nl = 0; 2951553Srgrimes 2964571Sgibbsbegin: 2971553Srgrimes while ((ch = getc(fp)) != EOF) 2981553Srgrimes if (ch != ' ' && ch != '\t') 2991553Srgrimes break; 3001553Srgrimes if (ch == EOF) 3011553Srgrimes return ((char *)EOF); 3024571Sgibbs if (ch == '\\'){ 3034571Sgibbs escaped_nl = 1; 3044571Sgibbs goto begin; 3054571Sgibbs } 30645775Speter if (ch == '\n') { 3074571Sgibbs if (escaped_nl){ 3084571Sgibbs escaped_nl = 0; 3094571Sgibbs goto begin; 3104571Sgibbs } 3114571Sgibbs else 3124571Sgibbs return (NULL); 31345775Speter } 3141553Srgrimes cp = line; 3151553Srgrimes *cp++ = ch; 3161553Srgrimes while ((ch = getc(fp)) != EOF) { 3171553Srgrimes if (isspace(ch)) 3181553Srgrimes break; 3191553Srgrimes *cp++ = ch; 3201553Srgrimes } 3211553Srgrimes *cp = 0; 3221553Srgrimes if (ch == EOF) 3231553Srgrimes return ((char *)EOF); 3241553Srgrimes (void) ungetc(ch, fp); 3251553Srgrimes return (line); 3261553Srgrimes} 3271553Srgrimes 3281553Srgrimes/* 3291553Srgrimes * get_quoted_word 3301553Srgrimes * like get_word but will accept something in double or single quotes 3311553Srgrimes * (to allow embedded spaces). 3321553Srgrimes */ 3331553Srgrimeschar * 33461640Speterget_quoted_word(FILE *fp) 3351553Srgrimes{ 3361553Srgrimes static char line[256]; 33761640Speter int ch; 33861640Speter char *cp; 3394571Sgibbs int escaped_nl = 0; 3401553Srgrimes 3414571Sgibbsbegin: 3421553Srgrimes while ((ch = getc(fp)) != EOF) 3431553Srgrimes if (ch != ' ' && ch != '\t') 3441553Srgrimes break; 3451553Srgrimes if (ch == EOF) 3461553Srgrimes return ((char *)EOF); 3474571Sgibbs if (ch == '\\'){ 3484571Sgibbs escaped_nl = 1; 3494571Sgibbs goto begin; 3504571Sgibbs } 35145775Speter if (ch == '\n') { 3524571Sgibbs if (escaped_nl){ 3534571Sgibbs escaped_nl = 0; 3544571Sgibbs goto begin; 3554571Sgibbs } 3564571Sgibbs else 3574571Sgibbs return (NULL); 35845775Speter } 3591553Srgrimes cp = line; 3601553Srgrimes if (ch == '"' || ch == '\'') { 36161640Speter int quote = ch; 3621553Srgrimes 363250066Sjkim escaped_nl = 0; 3641553Srgrimes while ((ch = getc(fp)) != EOF) { 365250066Sjkim if (ch == quote && !escaped_nl) 3661553Srgrimes break; 367250066Sjkim if (ch == '\n' && !escaped_nl) { 3681553Srgrimes *cp = 0; 3691553Srgrimes printf("config: missing quote reading `%s'\n", 3701553Srgrimes line); 3711553Srgrimes exit(2); 3721553Srgrimes } 373250066Sjkim if (ch == '\\' && !escaped_nl) { 374250066Sjkim escaped_nl = 1; 375250066Sjkim continue; 376250066Sjkim } 377250066Sjkim if (ch != quote && escaped_nl) 378250066Sjkim *cp++ = '\\'; 3791553Srgrimes *cp++ = ch; 380250066Sjkim escaped_nl = 0; 3811553Srgrimes } 3821553Srgrimes } else { 3831553Srgrimes *cp++ = ch; 3841553Srgrimes while ((ch = getc(fp)) != EOF) { 3851553Srgrimes if (isspace(ch)) 3861553Srgrimes break; 3871553Srgrimes *cp++ = ch; 3881553Srgrimes } 3891553Srgrimes if (ch != EOF) 3901553Srgrimes (void) ungetc(ch, fp); 3911553Srgrimes } 3921553Srgrimes *cp = 0; 3931553Srgrimes if (ch == EOF) 3941553Srgrimes return ((char *)EOF); 3951553Srgrimes return (line); 3961553Srgrimes} 3971553Srgrimes 3981553Srgrimes/* 3991553Srgrimes * prepend the path to a filename 4001553Srgrimes */ 4011553Srgrimeschar * 40272684Speterpath(const char *file) 4031553Srgrimes{ 40469004Simp char *cp = NULL; 4051553Srgrimes 40669004Simp if (file) 40769004Simp asprintf(&cp, "%s/%s", destdir, file); 40869004Simp else 40969004Simp cp = strdup(destdir); 4101553Srgrimes return (cp); 4111553Srgrimes} 41213400Speter 413169507Swkoszek/* 414169507Swkoszek * Generate configuration file based on actual settings. With this mode, user 415169507Swkoszek * will be able to obtain and build conifguration file with one command. 416169507Swkoszek */ 41745744Speterstatic void 418169507Swkoszekconfigfile_dynamic(struct sbuf *sb) 419169507Swkoszek{ 420169507Swkoszek struct cputype *cput; 421169507Swkoszek struct device *d; 422169507Swkoszek struct opt *ol; 423169507Swkoszek char *lend; 424169512Swkoszek unsigned int i; 425169507Swkoszek 426169507Swkoszek asprintf(&lend, "\\n\\\n"); 427169507Swkoszek assert(lend != NULL); 428169507Swkoszek sbuf_printf(sb, "options\t%s%s", OPT_AUTOGEN, lend); 429169507Swkoszek sbuf_printf(sb, "ident\t%s%s", ident, lend); 430169507Swkoszek sbuf_printf(sb, "machine\t%s%s", machinename, lend); 431169507Swkoszek SLIST_FOREACH(cput, &cputype, cpu_next) 432169507Swkoszek sbuf_printf(sb, "cpu\t%s%s", cput->cpu_name, lend); 433169507Swkoszek SLIST_FOREACH(ol, &mkopt, op_next) 434169507Swkoszek sbuf_printf(sb, "makeoptions\t%s=%s%s", ol->op_name, 435169507Swkoszek ol->op_value, lend); 436169507Swkoszek SLIST_FOREACH(ol, &opt, op_next) { 437169507Swkoszek if (strncmp(ol->op_name, "DEV_", 4) == 0) 438169507Swkoszek continue; 439169507Swkoszek sbuf_printf(sb, "options\t%s", ol->op_name); 440169507Swkoszek if (ol->op_value != NULL) { 441169512Swkoszek sbuf_putc(sb, '='); 442169512Swkoszek for (i = 0; i < strlen(ol->op_value); i++) { 443169512Swkoszek if (ol->op_value[i] == '"') 444169512Swkoszek sbuf_printf(sb, "\\%c", 445169512Swkoszek ol->op_value[i]); 446169512Swkoszek else 447169512Swkoszek sbuf_printf(sb, "%c", 448169512Swkoszek ol->op_value[i]); 449169512Swkoszek } 450169512Swkoszek sbuf_printf(sb, "%s", lend); 451169507Swkoszek } else { 452169507Swkoszek sbuf_printf(sb, "%s", lend); 453169507Swkoszek } 454169507Swkoszek } 455169507Swkoszek /* 456169507Swkoszek * Mark this file as containing everything we need. 457169507Swkoszek */ 458169507Swkoszek STAILQ_FOREACH(d, &dtab, d_next) 459169507Swkoszek sbuf_printf(sb, "device\t%s%s", d->d_name, lend); 460169507Swkoszek free(lend); 461169507Swkoszek} 462169507Swkoszek 463169507Swkoszek/* 464169507Swkoszek * Generate file from the configuration files. 465169507Swkoszek */ 466169507Swkoszekstatic void 467169507Swkoszekconfigfile_filebased(struct sbuf *sb) 468169507Swkoszek{ 469169507Swkoszek FILE *cff; 470169507Swkoszek struct cfgfile *cf; 471169507Swkoszek int i; 472169507Swkoszek 473188280Swkoszek /* 474188280Swkoszek * Try to read all configuration files. Since those will be present as 475188280Swkoszek * C string in the macro, we have to slash their ends then the line 476188280Swkoszek * wraps. 477188280Swkoszek */ 478169507Swkoszek STAILQ_FOREACH(cf, &cfgfiles, cfg_next) { 479169507Swkoszek cff = fopen(cf->cfg_path, "r"); 480169507Swkoszek if (cff == NULL) { 481169507Swkoszek warn("Couldn't open file %s", cf->cfg_path); 482169507Swkoszek continue; 483169507Swkoszek } 484169507Swkoszek while ((i = getc(cff)) != EOF) { 485169507Swkoszek if (i == '\n') 486169507Swkoszek sbuf_printf(sb, "\\n\\\n"); 487169507Swkoszek else if (i == '"' || i == '\'') 488169507Swkoszek sbuf_printf(sb, "\\%c", i); 489169507Swkoszek else 490169507Swkoszek sbuf_putc(sb, i); 491169507Swkoszek } 492169507Swkoszek fclose(cff); 493169507Swkoszek } 494169507Swkoszek} 495169507Swkoszek 496169507Swkoszekstatic void 49761640Speterconfigfile(void) 49816239Sjkh{ 499169507Swkoszek FILE *fo; 500169507Swkoszek struct sbuf *sb; 50116239Sjkh char *p; 502169507Swkoszek 503169507Swkoszek /* Add main configuration file to the list of files to be included */ 504169507Swkoszek cfgfile_add(PREFIX); 505169507Swkoszek p = path("config.c.new"); 506169507Swkoszek fo = fopen(p, "w"); 50752098Speter if (!fo) 50829451Scharnier err(2, "%s", p); 509169507Swkoszek sb = sbuf_new(NULL, NULL, 2048, SBUF_AUTOEXTEND); 510169507Swkoszek assert(sb != NULL); 511169507Swkoszek sbuf_clear(sb); 512169507Swkoszek if (filebased) { 513169507Swkoszek /* Is needed, can be used for backward compatibility. */ 514169507Swkoszek configfile_filebased(sb); 515169507Swkoszek } else { 516169507Swkoszek configfile_dynamic(sb); 51716239Sjkh } 518169507Swkoszek sbuf_finish(sb); 519169507Swkoszek /* 520205880Sru * We print first part of the template, replace our tag with 521169507Swkoszek * configuration files content and later continue writing our 522169507Swkoszek * template. 523169507Swkoszek */ 524169507Swkoszek p = strstr(kernconfstr, KERNCONFTAG); 525169507Swkoszek if (p == NULL) 526169507Swkoszek errx(EXIT_FAILURE, "Something went terribly wrong!"); 527169507Swkoszek *p = '\0'; 528169507Swkoszek fprintf(fo, "%s", kernconfstr); 529169507Swkoszek fprintf(fo, "%s", sbuf_data(sb)); 530169507Swkoszek p += strlen(KERNCONFTAG); 531169507Swkoszek fprintf(fo, "%s", p); 532169507Swkoszek sbuf_delete(sb); 53316239Sjkh fclose(fo); 53420940Speter moveifchanged(path("config.c.new"), path("config.c")); 535169507Swkoszek cfgfile_removeall(); 53616239Sjkh} 53716239Sjkh 53813400Speter/* 53913400Speter * moveifchanged -- 54013400Speter * compare two files; rename if changed. 54113400Speter */ 54213400Spetervoid 54313400Spetermoveifchanged(const char *from_name, const char *to_name) 54413400Speter{ 54513400Speter char *p, *q; 54613400Speter int changed; 54713400Speter size_t tsize; 54813400Speter struct stat from_sb, to_sb; 54913400Speter int from_fd, to_fd; 55013400Speter 55113400Speter changed = 0; 55213400Speter 55313400Speter if ((from_fd = open(from_name, O_RDONLY)) < 0) 55413400Speter err(EX_OSERR, "moveifchanged open(%s)", from_name); 55513400Speter 55613400Speter if ((to_fd = open(to_name, O_RDONLY)) < 0) 55713400Speter changed++; 55813400Speter 55913400Speter if (!changed && fstat(from_fd, &from_sb) < 0) 56013400Speter err(EX_OSERR, "moveifchanged fstat(%s)", from_name); 56113400Speter 56213400Speter if (!changed && fstat(to_fd, &to_sb) < 0) 56313400Speter err(EX_OSERR, "moveifchanged fstat(%s)", to_name); 56413400Speter 56513400Speter if (!changed && from_sb.st_size != to_sb.st_size) 56613400Speter changed++; 56713400Speter 56813400Speter tsize = (size_t)from_sb.st_size; 56913400Speter 57013400Speter if (!changed) { 57121786Salex p = mmap(NULL, tsize, PROT_READ, MAP_SHARED, from_fd, (off_t)0); 57221786Salex if (p == MAP_FAILED) 57313400Speter err(EX_OSERR, "mmap %s", from_name); 57421786Salex q = mmap(NULL, tsize, PROT_READ, MAP_SHARED, to_fd, (off_t)0); 57521786Salex if (q == MAP_FAILED) 57613400Speter err(EX_OSERR, "mmap %s", to_name); 57713400Speter 57813400Speter changed = memcmp(p, q, tsize); 57913400Speter munmap(p, tsize); 58013400Speter munmap(q, tsize); 58113400Speter } 58213400Speter if (changed) { 58313400Speter if (rename(from_name, to_name) < 0) 58413400Speter err(EX_OSERR, "rename(%s, %s)", from_name, to_name); 58513400Speter } else { 58613400Speter if (unlink(from_name) < 0) 58731216Sjdp err(EX_OSERR, "unlink(%s)", from_name); 58813400Speter } 58913400Speter} 59071784Speter 59171784Speterstatic void 59271866Spetercleanheaders(char *p) 59371784Speter{ 59471784Speter DIR *dirp; 59571784Speter struct dirent *dp; 59671784Speter struct file_list *fl; 59771866Speter struct hdr_list *hl; 598223744Sed size_t len; 59971784Speter 60071866Speter remember("y.tab.h"); 60171866Speter remember("setdefs.h"); 602110895Sru STAILQ_FOREACH(fl, &ftab, f_next) 60371866Speter remember(fl->f_fn); 60471784Speter 60571784Speter /* 60671784Speter * Scan the build directory and clean out stuff that looks like 60771784Speter * it might have been a leftover NFOO header, etc. 60871784Speter */ 609116257Stmm if ((dirp = opendir(p)) == NULL) 610116257Stmm err(EX_OSERR, "opendir %s", p); 61171784Speter while ((dp = readdir(dirp)) != NULL) { 612223744Sed len = strlen(dp->d_name); 61371784Speter /* Skip non-headers */ 614223744Sed if (len < 2 || dp->d_name[len - 2] != '.' || 615223744Sed dp->d_name[len - 1] != 'h') 61671784Speter continue; 61771784Speter /* Skip special stuff, eg: bus_if.h, but check opt_*.h */ 618223744Sed if (strchr(dp->d_name, '_') && 61971784Speter strncmp(dp->d_name, "opt_", 4) != 0) 62071784Speter continue; 62171784Speter /* Check if it is a target file */ 62271866Speter for (hl = htab; hl != NULL; hl = hl->h_next) { 623152963Sru if (eq(dp->d_name, hl->h_name)) { 62471784Speter break; 62571784Speter } 62671784Speter } 62771866Speter if (hl) 62871784Speter continue; 62971784Speter printf("Removing stale header: %s\n", dp->d_name); 630116257Stmm if (unlink(path(dp->d_name)) == -1) 631116257Stmm warn("unlink %s", dp->d_name); 63271784Speter } 63371784Speter (void)closedir(dirp); 63471866Speter} 63571784Speter 63671866Spetervoid 63772684Speterremember(const char *file) 63871866Speter{ 63971866Speter char *s; 64071866Speter struct hdr_list *hl; 64171866Speter 64271866Speter if ((s = strrchr(file, '/')) != NULL) 64372684Speter s = ns(s + 1); 64471866Speter else 64572684Speter s = ns(file); 64671866Speter 64771866Speter if (index(s, '_') && strncmp(s, "opt_", 4) != 0) { 64871866Speter free(s); 64971866Speter return; 65071866Speter } 65171866Speter for (hl = htab; hl != NULL; hl = hl->h_next) { 652152963Sru if (eq(s, hl->h_name)) { 65371866Speter free(s); 65471866Speter return; 65571866Speter } 65671866Speter } 657159362Sdelphij hl = calloc(1, sizeof(*hl)); 658205880Sru if (hl == NULL) 659205880Sru err(EXIT_FAILURE, "calloc"); 66071866Speter hl->h_name = s; 66171866Speter hl->h_next = htab; 66271866Speter htab = hl; 66371784Speter} 664169507Swkoszek 665169507Swkoszek/* 666169507Swkoszek * This one is quick hack. Will be probably moved to elf(3) interface. 667169507Swkoszek * It takes kernel configuration file name, passes it as an argument to 668169507Swkoszek * elfdump -a, which output is parsed by some UNIX tools... 669169507Swkoszek */ 670169507Swkoszekstatic void 671169507Swkoszekkernconfdump(const char *file) 672169507Swkoszek{ 673169507Swkoszek struct stat st; 674169507Swkoszek FILE *fp, *pp; 675169507Swkoszek int error, len, osz, r; 676207461Simp unsigned int i, off, size, t1, t2, align; 677169507Swkoszek char *cmd, *o; 678169507Swkoszek 679169507Swkoszek r = open(file, O_RDONLY); 680169507Swkoszek if (r == -1) 681205880Sru err(EXIT_FAILURE, "Couldn't open file '%s'", file); 682169507Swkoszek error = fstat(r, &st); 683169507Swkoszek if (error == -1) 684205880Sru err(EXIT_FAILURE, "fstat() failed"); 685169507Swkoszek if (S_ISDIR(st.st_mode)) 686169507Swkoszek errx(EXIT_FAILURE, "'%s' is a directory", file); 687169507Swkoszek fp = fdopen(r, "r"); 688169507Swkoszek if (fp == NULL) 689205880Sru err(EXIT_FAILURE, "fdopen() failed"); 690169507Swkoszek osz = 1024; 691169507Swkoszek o = calloc(1, osz); 692169507Swkoszek if (o == NULL) 693205880Sru err(EXIT_FAILURE, "Couldn't allocate memory"); 694169507Swkoszek /* ELF note section header. */ 695207461Simp asprintf(&cmd, "/usr/bin/elfdump -c %s | grep -A 8 kern_conf" 696207461Simp "| tail -5 | cut -d ' ' -f 2 | paste - - - - -", file); 697169507Swkoszek if (cmd == NULL) 698169507Swkoszek errx(EXIT_FAILURE, "asprintf() failed"); 699169507Swkoszek pp = popen(cmd, "r"); 700169507Swkoszek if (pp == NULL) 701169507Swkoszek errx(EXIT_FAILURE, "popen() failed"); 702169507Swkoszek free(cmd); 703169507Swkoszek len = fread(o, osz, 1, pp); 704169507Swkoszek pclose(pp); 705207461Simp r = sscanf(o, "%d%d%d%d%d", &off, &size, &t1, &t2, &align); 706169507Swkoszek free(o); 707207461Simp if (r != 5) 708169507Swkoszek errx(EXIT_FAILURE, "File %s doesn't contain configuration " 709169507Swkoszek "file. Either unsupported, or not compiled with " 710169507Swkoszek "INCLUDE_CONFIG_FILE", file); 711169507Swkoszek r = fseek(fp, off, SEEK_CUR); 712169507Swkoszek if (r != 0) 713205880Sru err(EXIT_FAILURE, "fseek() failed"); 714207461Simp for (i = 0; i < size; i++) { 715188214Swkoszek r = fgetc(fp); 716188214Swkoszek if (r == EOF) 717188214Swkoszek break; 718188214Swkoszek /* 719188214Swkoszek * If '\0' is present in the middle of the configuration 720188214Swkoszek * string, this means something very weird is happening. 721207461Simp * Make such case very visible. However, some architectures 722207461Simp * pad the length of the section with NULs to a multiple of 723207461Simp * sh_addralign, allow a NUL in that part of the section. 724188214Swkoszek */ 725207461Simp if (r == '\0' && (size - i) < align) 726207461Simp break; 727188214Swkoszek assert(r != '\0' && ("Char present in the configuration " 728188214Swkoszek "string mustn't be equal to 0")); 729169507Swkoszek fputc(r, stdout); 730188214Swkoszek } 731169507Swkoszek fclose(fp); 732169507Swkoszek} 733207260Simp 734207260Simpstatic void 735207260Simpbadversion(int versreq) 736207260Simp{ 737207260Simp fprintf(stderr, "ERROR: version of config(8) does not match kernel!\n"); 738207260Simp fprintf(stderr, "config version = %d, ", CONFIGVERS); 739207260Simp fprintf(stderr, "version required = %d\n\n", versreq); 740207260Simp fprintf(stderr, "Make sure that /usr/src/usr.sbin/config is in sync\n"); 741207260Simp fprintf(stderr, "with your /usr/src/sys and install a new config binary\n"); 742207260Simp fprintf(stderr, "before trying this again.\n\n"); 743207260Simp fprintf(stderr, "If running the new config fails check your config\n"); 744207260Simp fprintf(stderr, "file against the GENERIC or LINT config files for\n"); 745207260Simp fprintf(stderr, "changes in config syntax, or option/device naming\n"); 746207260Simp fprintf(stderr, "conventions\n\n"); 747207260Simp exit(1); 748207260Simp} 749207260Simp 750207260Simpstatic void 751207260Simpcheckversion(void) 752207260Simp{ 753207260Simp FILE *ifp; 754207260Simp char line[BUFSIZ]; 755207260Simp int versreq; 756207260Simp 757207260Simp ifp = open_makefile_template(); 758207260Simp while (fgets(line, BUFSIZ, ifp) != 0) { 759207260Simp if (*line != '%') 760207260Simp continue; 761207260Simp if (strncmp(line, "%VERSREQ=", 9) != 0) 762207260Simp continue; 763207260Simp versreq = atoi(line + 9); 764207260Simp if (MAJOR_VERS(versreq) == MAJOR_VERS(CONFIGVERS) && 765207260Simp versreq <= CONFIGVERS) 766207260Simp continue; 767207260Simp badversion(versreq); 768207260Simp } 769207260Simp fclose(ifp); 770207260Simp} 771