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: releng/10.3/usr.sbin/config/main.c 276280 2014-12-27 03:19:04Z ian $"; 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); 94235789Sbaptextern int yyparse(void); 9529451Scharnier 9671866Speterstruct hdr_list { 9771866Speter char *h_name; 9871866Speter struct hdr_list *h_next; 9971866Speter} *htab; 10071866Speter 1011553Srgrimes/* 1021553Srgrimes * Config builds a set of files for building a UNIX 1031553Srgrimes * system given a description of the desired system. 1041553Srgrimes */ 10529451Scharnierint 10661640Spetermain(int argc, char **argv) 1071553Srgrimes{ 1081553Srgrimes 1091553Srgrimes struct stat buf; 11052653Smarcel int ch, len; 1111553Srgrimes char *p; 112169507Swkoszek char *kernfile; 113264325Sasomers struct includepath* ipath; 114209969Snwhitehorn int printmachine; 1151553Srgrimes 116209969Snwhitehorn printmachine = 0; 117169507Swkoszek kernfile = NULL; 118264325Sasomers SLIST_INIT(&includepath); 119264325Sasomers while ((ch = getopt(argc, argv, "CI:d:gmpVx:")) != -1) 1201553Srgrimes switch (ch) { 121169507Swkoszek case 'C': 122169507Swkoszek filebased = 1; 123169507Swkoszek break; 124264325Sasomers case 'I': 125264325Sasomers ipath = (struct includepath *) \ 126264325Sasomers calloc(1, sizeof (struct includepath)); 127264325Sasomers if (ipath == NULL) 128264325Sasomers err(EXIT_FAILURE, "calloc"); 129264325Sasomers ipath->path = optarg; 130264325Sasomers SLIST_INSERT_HEAD(&includepath, ipath, path_next); 131264325Sasomers break; 132209969Snwhitehorn case 'm': 133209969Snwhitehorn printmachine = 1; 134209969Snwhitehorn break; 13552653Smarcel case 'd': 13652653Smarcel if (*destdir == '\0') 13769004Simp strlcpy(destdir, optarg, sizeof(destdir)); 13852653Smarcel else 139205880Sru errx(EXIT_FAILURE, "directory already set"); 14052653Smarcel break; 1411553Srgrimes case 'g': 14245579Sgrog debugging++; 1431553Srgrimes break; 1441553Srgrimes case 'p': 1451553Srgrimes profiling++; 1461553Srgrimes break; 147169507Swkoszek case 'V': 148169507Swkoszek printf("%d\n", CONFIGVERS); 149169507Swkoszek exit(0); 150169507Swkoszek case 'x': 151169507Swkoszek kernfile = optarg; 152169507Swkoszek break; 1531553Srgrimes case '?': 1541553Srgrimes default: 15529451Scharnier usage(); 1561553Srgrimes } 1571553Srgrimes argc -= optind; 1581553Srgrimes argv += optind; 1591553Srgrimes 160169507Swkoszek if (kernfile != NULL) { 161169507Swkoszek kernconfdump(kernfile); 162169507Swkoszek exit(EXIT_SUCCESS); 163169507Swkoszek } 164169507Swkoszek 16529451Scharnier if (argc != 1) 16629451Scharnier usage(); 1671553Srgrimes 168151744Sjhb PREFIX = *argv; 169178085Simp if (stat(PREFIX, &buf) != 0 || !S_ISREG(buf.st_mode)) 170178085Simp err(2, "%s", PREFIX); 171169647Simp if (freopen("DEFAULTS", "r", stdin) != NULL) { 172169647Simp found_defaults = 1; 173169647Simp yyfile = "DEFAULTS"; 174169647Simp } else { 175169647Simp if (freopen(PREFIX, "r", stdin) == NULL) 176169647Simp err(2, "%s", PREFIX); 177169647Simp yyfile = PREFIX; 178169647Simp } 17952653Smarcel if (*destdir != '\0') { 18052653Smarcel len = strlen(destdir); 18152653Smarcel while (len > 1 && destdir[len - 1] == '/') 18252653Smarcel destdir[--len] = '\0'; 18352653Smarcel get_srcdir(); 18452653Smarcel } else { 18569004Simp strlcpy(destdir, CDIR, sizeof(destdir)); 18669004Simp strlcat(destdir, PREFIX, sizeof(destdir)); 18752653Smarcel } 18852653Smarcel 189169507Swkoszek SLIST_INIT(&cputype); 190169507Swkoszek SLIST_INIT(&mkopt); 191169507Swkoszek SLIST_INIT(&opt); 192169507Swkoszek SLIST_INIT(&rmopts); 193169507Swkoszek STAILQ_INIT(&cfgfiles); 194110895Sru STAILQ_INIT(&dtab); 195129073Scognet STAILQ_INIT(&fntab); 196129073Scognet STAILQ_INIT(&ftab); 197163638Simp STAILQ_INIT(&hints); 1981553Srgrimes if (yyparse()) 1991553Srgrimes exit(3); 200153888Sru 201153888Sru /* 202153888Sru * Ensure that required elements (machine, cpu, ident) are present. 203153888Sru */ 20472000Speter if (machinename == NULL) { 20545775Speter printf("Specify machine type, e.g. ``machine i386''\n"); 2061553Srgrimes exit(1); 2071553Srgrimes } 208153888Sru if (ident == NULL) { 209153888Sru printf("no ident line specified\n"); 210153888Sru exit(1); 211153888Sru } 212153888Sru if (SLIST_EMPTY(&cputype)) { 213153888Sru printf("cpu type must be specified\n"); 214153888Sru exit(1); 215153888Sru } 216207260Simp checkversion(); 217153888Sru 218209969Snwhitehorn if (printmachine) { 219209969Snwhitehorn printf("%s\t%s\n",machinename,machinearch); 220209969Snwhitehorn exit(0); 221209969Snwhitehorn } 222209969Snwhitehorn 223209969Snwhitehorn /* Make compile directory */ 224209969Snwhitehorn p = path((char *)NULL); 225209969Snwhitehorn if (stat(p, &buf)) { 226209969Snwhitehorn if (mkdir(p, 0777)) 227209969Snwhitehorn err(2, "%s", p); 228209969Snwhitehorn } else if (!S_ISDIR(buf.st_mode)) 229209969Snwhitehorn errx(EXIT_FAILURE, "%s isn't a directory", p); 230209969Snwhitehorn 231169507Swkoszek configfile(); /* put config file into kernel*/ 23212772Speter options(); /* make options .h files */ 2331553Srgrimes makefile(); /* build Makefile */ 234153888Sru makeenv(); /* build env.c */ 235153888Sru makehints(); /* build hints.c */ 2361553Srgrimes headers(); /* make a lot of .h files */ 23771866Speter cleanheaders(p); 2388248Sjkh printf("Kernel build directory is %s\n", p); 239154338Sflz printf("Don't forget to do ``make cleandepend && make depend''\n"); 2401553Srgrimes exit(0); 2411553Srgrimes} 2421553Srgrimes 24352653Smarcel/* 24452653Smarcel * get_srcdir 24552653Smarcel * determine the root of the kernel source tree 24652653Smarcel * and save that in srcdir. 24752653Smarcel */ 24829451Scharnierstatic void 24961640Speterget_srcdir(void) 25052653Smarcel{ 251175163Semaste struct stat lg, phy; 252175163Semaste char *p, *pwd; 253175163Semaste int i; 25452653Smarcel 25570673Speter if (realpath("../..", srcdir) == NULL) 256205880Sru err(EXIT_FAILURE, "Unable to find root of source tree"); 257175163Semaste if ((pwd = getenv("PWD")) != NULL && *pwd == '/' && 258175163Semaste (pwd = strdup(pwd)) != NULL) { 259175163Semaste /* Remove the last two path components. */ 260175163Semaste for (i = 0; i < 2; i++) { 261175163Semaste if ((p = strrchr(pwd, '/')) == NULL) { 262175163Semaste free(pwd); 263175163Semaste return; 264175163Semaste } 265175163Semaste *p = '\0'; 266175163Semaste } 267175163Semaste if (stat(pwd, &lg) != -1 && stat(srcdir, &phy) != -1 && 268175163Semaste lg.st_dev == phy.st_dev && lg.st_ino == phy.st_ino) 269175163Semaste strlcpy(srcdir, pwd, MAXPATHLEN); 270175163Semaste free(pwd); 271175163Semaste } 27252653Smarcel} 27352653Smarcel 27452653Smarcelstatic void 27561640Speterusage(void) 27629451Scharnier{ 277144352Simp 278209969Snwhitehorn fprintf(stderr, "usage: config [-CgmpV] [-d destdir] sysname\n"); 279169507Swkoszek fprintf(stderr, " config -x kernel\n"); 280169507Swkoszek exit(EX_USAGE); 28129451Scharnier} 28229451Scharnier 2831553Srgrimes/* 2841553Srgrimes * get_word 2851553Srgrimes * returns EOF on end of file 2861553Srgrimes * NULL on end of line 2871553Srgrimes * pointer to the word otherwise 2881553Srgrimes */ 2891553Srgrimeschar * 29061640Speterget_word(FILE *fp) 2911553Srgrimes{ 2921553Srgrimes static char line[80]; 29361640Speter int ch; 29461640Speter char *cp; 2954571Sgibbs int escaped_nl = 0; 2961553Srgrimes 2974571Sgibbsbegin: 2981553Srgrimes while ((ch = getc(fp)) != EOF) 2991553Srgrimes if (ch != ' ' && ch != '\t') 3001553Srgrimes break; 3011553Srgrimes if (ch == EOF) 3021553Srgrimes return ((char *)EOF); 3034571Sgibbs if (ch == '\\'){ 3044571Sgibbs escaped_nl = 1; 3054571Sgibbs goto begin; 3064571Sgibbs } 30745775Speter if (ch == '\n') { 3084571Sgibbs if (escaped_nl){ 3094571Sgibbs escaped_nl = 0; 3104571Sgibbs goto begin; 3114571Sgibbs } 3124571Sgibbs else 3134571Sgibbs return (NULL); 31445775Speter } 3151553Srgrimes cp = line; 3161553Srgrimes *cp++ = ch; 317276280Sian /* Negation operator is a word by itself. */ 318276280Sian if (ch == '!') { 319276280Sian *cp = 0; 320276280Sian return (line); 321276280Sian } 3221553Srgrimes while ((ch = getc(fp)) != EOF) { 3231553Srgrimes if (isspace(ch)) 3241553Srgrimes break; 3251553Srgrimes *cp++ = ch; 3261553Srgrimes } 3271553Srgrimes *cp = 0; 3281553Srgrimes if (ch == EOF) 3291553Srgrimes return ((char *)EOF); 3301553Srgrimes (void) ungetc(ch, fp); 3311553Srgrimes return (line); 3321553Srgrimes} 3331553Srgrimes 3341553Srgrimes/* 3351553Srgrimes * get_quoted_word 3361553Srgrimes * like get_word but will accept something in double or single quotes 3371553Srgrimes * (to allow embedded spaces). 3381553Srgrimes */ 3391553Srgrimeschar * 34061640Speterget_quoted_word(FILE *fp) 3411553Srgrimes{ 3421553Srgrimes static char line[256]; 34361640Speter int ch; 34461640Speter char *cp; 3454571Sgibbs int escaped_nl = 0; 3461553Srgrimes 3474571Sgibbsbegin: 3481553Srgrimes while ((ch = getc(fp)) != EOF) 3491553Srgrimes if (ch != ' ' && ch != '\t') 3501553Srgrimes break; 3511553Srgrimes if (ch == EOF) 3521553Srgrimes return ((char *)EOF); 3534571Sgibbs if (ch == '\\'){ 3544571Sgibbs escaped_nl = 1; 3554571Sgibbs goto begin; 3564571Sgibbs } 35745775Speter if (ch == '\n') { 3584571Sgibbs if (escaped_nl){ 3594571Sgibbs escaped_nl = 0; 3604571Sgibbs goto begin; 3614571Sgibbs } 3624571Sgibbs else 3634571Sgibbs return (NULL); 36445775Speter } 3651553Srgrimes cp = line; 3661553Srgrimes if (ch == '"' || ch == '\'') { 36761640Speter int quote = ch; 3681553Srgrimes 369248777Sjkim escaped_nl = 0; 3701553Srgrimes while ((ch = getc(fp)) != EOF) { 371248777Sjkim if (ch == quote && !escaped_nl) 3721553Srgrimes break; 373248777Sjkim if (ch == '\n' && !escaped_nl) { 3741553Srgrimes *cp = 0; 3751553Srgrimes printf("config: missing quote reading `%s'\n", 3761553Srgrimes line); 3771553Srgrimes exit(2); 3781553Srgrimes } 379248777Sjkim if (ch == '\\' && !escaped_nl) { 380248777Sjkim escaped_nl = 1; 381248777Sjkim continue; 382248777Sjkim } 383248777Sjkim if (ch != quote && escaped_nl) 384248777Sjkim *cp++ = '\\'; 3851553Srgrimes *cp++ = ch; 386248777Sjkim escaped_nl = 0; 3871553Srgrimes } 3881553Srgrimes } else { 3891553Srgrimes *cp++ = ch; 3901553Srgrimes while ((ch = getc(fp)) != EOF) { 3911553Srgrimes if (isspace(ch)) 3921553Srgrimes break; 3931553Srgrimes *cp++ = ch; 3941553Srgrimes } 3951553Srgrimes if (ch != EOF) 3961553Srgrimes (void) ungetc(ch, fp); 3971553Srgrimes } 3981553Srgrimes *cp = 0; 3991553Srgrimes if (ch == EOF) 4001553Srgrimes return ((char *)EOF); 4011553Srgrimes return (line); 4021553Srgrimes} 4031553Srgrimes 4041553Srgrimes/* 4051553Srgrimes * prepend the path to a filename 4061553Srgrimes */ 4071553Srgrimeschar * 40872684Speterpath(const char *file) 4091553Srgrimes{ 41069004Simp char *cp = NULL; 4111553Srgrimes 41269004Simp if (file) 41369004Simp asprintf(&cp, "%s/%s", destdir, file); 41469004Simp else 41569004Simp cp = strdup(destdir); 4161553Srgrimes return (cp); 4171553Srgrimes} 41813400Speter 419169507Swkoszek/* 420169507Swkoszek * Generate configuration file based on actual settings. With this mode, user 421169507Swkoszek * will be able to obtain and build conifguration file with one command. 422169507Swkoszek */ 42345744Speterstatic void 424169507Swkoszekconfigfile_dynamic(struct sbuf *sb) 425169507Swkoszek{ 426169507Swkoszek struct cputype *cput; 427169507Swkoszek struct device *d; 428169507Swkoszek struct opt *ol; 429169507Swkoszek char *lend; 430169512Swkoszek unsigned int i; 431169507Swkoszek 432169507Swkoszek asprintf(&lend, "\\n\\\n"); 433169507Swkoszek assert(lend != NULL); 434169507Swkoszek sbuf_printf(sb, "options\t%s%s", OPT_AUTOGEN, lend); 435169507Swkoszek sbuf_printf(sb, "ident\t%s%s", ident, lend); 436169507Swkoszek sbuf_printf(sb, "machine\t%s%s", machinename, lend); 437169507Swkoszek SLIST_FOREACH(cput, &cputype, cpu_next) 438169507Swkoszek sbuf_printf(sb, "cpu\t%s%s", cput->cpu_name, lend); 439169507Swkoszek SLIST_FOREACH(ol, &mkopt, op_next) 440169507Swkoszek sbuf_printf(sb, "makeoptions\t%s=%s%s", ol->op_name, 441169507Swkoszek ol->op_value, lend); 442169507Swkoszek SLIST_FOREACH(ol, &opt, op_next) { 443169507Swkoszek if (strncmp(ol->op_name, "DEV_", 4) == 0) 444169507Swkoszek continue; 445169507Swkoszek sbuf_printf(sb, "options\t%s", ol->op_name); 446169507Swkoszek if (ol->op_value != NULL) { 447169512Swkoszek sbuf_putc(sb, '='); 448169512Swkoszek for (i = 0; i < strlen(ol->op_value); i++) { 449169512Swkoszek if (ol->op_value[i] == '"') 450169512Swkoszek sbuf_printf(sb, "\\%c", 451169512Swkoszek ol->op_value[i]); 452169512Swkoszek else 453169512Swkoszek sbuf_printf(sb, "%c", 454169512Swkoszek ol->op_value[i]); 455169512Swkoszek } 456169512Swkoszek sbuf_printf(sb, "%s", lend); 457169507Swkoszek } else { 458169507Swkoszek sbuf_printf(sb, "%s", lend); 459169507Swkoszek } 460169507Swkoszek } 461169507Swkoszek /* 462169507Swkoszek * Mark this file as containing everything we need. 463169507Swkoszek */ 464169507Swkoszek STAILQ_FOREACH(d, &dtab, d_next) 465169507Swkoszek sbuf_printf(sb, "device\t%s%s", d->d_name, lend); 466169507Swkoszek free(lend); 467169507Swkoszek} 468169507Swkoszek 469169507Swkoszek/* 470169507Swkoszek * Generate file from the configuration files. 471169507Swkoszek */ 472169507Swkoszekstatic void 473169507Swkoszekconfigfile_filebased(struct sbuf *sb) 474169507Swkoszek{ 475169507Swkoszek FILE *cff; 476169507Swkoszek struct cfgfile *cf; 477169507Swkoszek int i; 478169507Swkoszek 479188280Swkoszek /* 480188280Swkoszek * Try to read all configuration files. Since those will be present as 481188280Swkoszek * C string in the macro, we have to slash their ends then the line 482188280Swkoszek * wraps. 483188280Swkoszek */ 484169507Swkoszek STAILQ_FOREACH(cf, &cfgfiles, cfg_next) { 485169507Swkoszek cff = fopen(cf->cfg_path, "r"); 486169507Swkoszek if (cff == NULL) { 487169507Swkoszek warn("Couldn't open file %s", cf->cfg_path); 488169507Swkoszek continue; 489169507Swkoszek } 490169507Swkoszek while ((i = getc(cff)) != EOF) { 491169507Swkoszek if (i == '\n') 492169507Swkoszek sbuf_printf(sb, "\\n\\\n"); 493169507Swkoszek else if (i == '"' || i == '\'') 494169507Swkoszek sbuf_printf(sb, "\\%c", i); 495169507Swkoszek else 496169507Swkoszek sbuf_putc(sb, i); 497169507Swkoszek } 498169507Swkoszek fclose(cff); 499169507Swkoszek } 500169507Swkoszek} 501169507Swkoszek 502169507Swkoszekstatic void 50361640Speterconfigfile(void) 50416239Sjkh{ 505169507Swkoszek FILE *fo; 506169507Swkoszek struct sbuf *sb; 50716239Sjkh char *p; 508169507Swkoszek 509169507Swkoszek /* Add main configuration file to the list of files to be included */ 510169507Swkoszek cfgfile_add(PREFIX); 511169507Swkoszek p = path("config.c.new"); 512169507Swkoszek fo = fopen(p, "w"); 51352098Speter if (!fo) 51429451Scharnier err(2, "%s", p); 515169507Swkoszek sb = sbuf_new(NULL, NULL, 2048, SBUF_AUTOEXTEND); 516169507Swkoszek assert(sb != NULL); 517169507Swkoszek sbuf_clear(sb); 518169507Swkoszek if (filebased) { 519169507Swkoszek /* Is needed, can be used for backward compatibility. */ 520169507Swkoszek configfile_filebased(sb); 521169507Swkoszek } else { 522169507Swkoszek configfile_dynamic(sb); 52316239Sjkh } 524169507Swkoszek sbuf_finish(sb); 525169507Swkoszek /* 526205880Sru * We print first part of the template, replace our tag with 527169507Swkoszek * configuration files content and later continue writing our 528169507Swkoszek * template. 529169507Swkoszek */ 530169507Swkoszek p = strstr(kernconfstr, KERNCONFTAG); 531169507Swkoszek if (p == NULL) 532169507Swkoszek errx(EXIT_FAILURE, "Something went terribly wrong!"); 533169507Swkoszek *p = '\0'; 534169507Swkoszek fprintf(fo, "%s", kernconfstr); 535169507Swkoszek fprintf(fo, "%s", sbuf_data(sb)); 536169507Swkoszek p += strlen(KERNCONFTAG); 537169507Swkoszek fprintf(fo, "%s", p); 538169507Swkoszek sbuf_delete(sb); 53916239Sjkh fclose(fo); 54020940Speter moveifchanged(path("config.c.new"), path("config.c")); 541169507Swkoszek cfgfile_removeall(); 54216239Sjkh} 54316239Sjkh 54413400Speter/* 54513400Speter * moveifchanged -- 54613400Speter * compare two files; rename if changed. 54713400Speter */ 54813400Spetervoid 54913400Spetermoveifchanged(const char *from_name, const char *to_name) 55013400Speter{ 55113400Speter char *p, *q; 55213400Speter int changed; 55313400Speter size_t tsize; 55413400Speter struct stat from_sb, to_sb; 55513400Speter int from_fd, to_fd; 55613400Speter 55713400Speter changed = 0; 55813400Speter 55913400Speter if ((from_fd = open(from_name, O_RDONLY)) < 0) 56013400Speter err(EX_OSERR, "moveifchanged open(%s)", from_name); 56113400Speter 56213400Speter if ((to_fd = open(to_name, O_RDONLY)) < 0) 56313400Speter changed++; 56413400Speter 56513400Speter if (!changed && fstat(from_fd, &from_sb) < 0) 56613400Speter err(EX_OSERR, "moveifchanged fstat(%s)", from_name); 56713400Speter 56813400Speter if (!changed && fstat(to_fd, &to_sb) < 0) 56913400Speter err(EX_OSERR, "moveifchanged fstat(%s)", to_name); 57013400Speter 57113400Speter if (!changed && from_sb.st_size != to_sb.st_size) 57213400Speter changed++; 57313400Speter 57413400Speter tsize = (size_t)from_sb.st_size; 57513400Speter 57613400Speter if (!changed) { 57721786Salex p = mmap(NULL, tsize, PROT_READ, MAP_SHARED, from_fd, (off_t)0); 57821786Salex if (p == MAP_FAILED) 57913400Speter err(EX_OSERR, "mmap %s", from_name); 58021786Salex q = mmap(NULL, tsize, PROT_READ, MAP_SHARED, to_fd, (off_t)0); 58121786Salex if (q == MAP_FAILED) 58213400Speter err(EX_OSERR, "mmap %s", to_name); 58313400Speter 58413400Speter changed = memcmp(p, q, tsize); 58513400Speter munmap(p, tsize); 58613400Speter munmap(q, tsize); 58713400Speter } 58813400Speter if (changed) { 58913400Speter if (rename(from_name, to_name) < 0) 59013400Speter err(EX_OSERR, "rename(%s, %s)", from_name, to_name); 59113400Speter } else { 59213400Speter if (unlink(from_name) < 0) 59331216Sjdp err(EX_OSERR, "unlink(%s)", from_name); 59413400Speter } 59513400Speter} 59671784Speter 59771784Speterstatic void 59871866Spetercleanheaders(char *p) 59971784Speter{ 60071784Speter DIR *dirp; 60171784Speter struct dirent *dp; 60271784Speter struct file_list *fl; 60371866Speter struct hdr_list *hl; 604223744Sed size_t len; 60571784Speter 60671866Speter remember("y.tab.h"); 60771866Speter remember("setdefs.h"); 608110895Sru STAILQ_FOREACH(fl, &ftab, f_next) 60971866Speter remember(fl->f_fn); 61071784Speter 61171784Speter /* 61271784Speter * Scan the build directory and clean out stuff that looks like 61371784Speter * it might have been a leftover NFOO header, etc. 61471784Speter */ 615116257Stmm if ((dirp = opendir(p)) == NULL) 616116257Stmm err(EX_OSERR, "opendir %s", p); 61771784Speter while ((dp = readdir(dirp)) != NULL) { 618223744Sed len = strlen(dp->d_name); 61971784Speter /* Skip non-headers */ 620223744Sed if (len < 2 || dp->d_name[len - 2] != '.' || 621223744Sed dp->d_name[len - 1] != 'h') 62271784Speter continue; 62371784Speter /* Skip special stuff, eg: bus_if.h, but check opt_*.h */ 624223744Sed if (strchr(dp->d_name, '_') && 62571784Speter strncmp(dp->d_name, "opt_", 4) != 0) 62671784Speter continue; 62771784Speter /* Check if it is a target file */ 62871866Speter for (hl = htab; hl != NULL; hl = hl->h_next) { 629152963Sru if (eq(dp->d_name, hl->h_name)) { 63071784Speter break; 63171784Speter } 63271784Speter } 63371866Speter if (hl) 63471784Speter continue; 63571784Speter printf("Removing stale header: %s\n", dp->d_name); 636116257Stmm if (unlink(path(dp->d_name)) == -1) 637116257Stmm warn("unlink %s", dp->d_name); 63871784Speter } 63971784Speter (void)closedir(dirp); 64071866Speter} 64171784Speter 64271866Spetervoid 64372684Speterremember(const char *file) 64471866Speter{ 64571866Speter char *s; 64671866Speter struct hdr_list *hl; 64771866Speter 64871866Speter if ((s = strrchr(file, '/')) != NULL) 64972684Speter s = ns(s + 1); 65071866Speter else 65172684Speter s = ns(file); 65271866Speter 653229403Sed if (strchr(s, '_') && strncmp(s, "opt_", 4) != 0) { 65471866Speter free(s); 65571866Speter return; 65671866Speter } 65771866Speter for (hl = htab; hl != NULL; hl = hl->h_next) { 658152963Sru if (eq(s, hl->h_name)) { 65971866Speter free(s); 66071866Speter return; 66171866Speter } 66271866Speter } 663159362Sdelphij hl = calloc(1, sizeof(*hl)); 664205880Sru if (hl == NULL) 665205880Sru err(EXIT_FAILURE, "calloc"); 66671866Speter hl->h_name = s; 66771866Speter hl->h_next = htab; 66871866Speter htab = hl; 66971784Speter} 670169507Swkoszek 671169507Swkoszek/* 672169507Swkoszek * This one is quick hack. Will be probably moved to elf(3) interface. 673169507Swkoszek * It takes kernel configuration file name, passes it as an argument to 674169507Swkoszek * elfdump -a, which output is parsed by some UNIX tools... 675169507Swkoszek */ 676169507Swkoszekstatic void 677169507Swkoszekkernconfdump(const char *file) 678169507Swkoszek{ 679169507Swkoszek struct stat st; 680169507Swkoszek FILE *fp, *pp; 681169507Swkoszek int error, len, osz, r; 682207461Simp unsigned int i, off, size, t1, t2, align; 683169507Swkoszek char *cmd, *o; 684169507Swkoszek 685169507Swkoszek r = open(file, O_RDONLY); 686169507Swkoszek if (r == -1) 687205880Sru err(EXIT_FAILURE, "Couldn't open file '%s'", file); 688169507Swkoszek error = fstat(r, &st); 689169507Swkoszek if (error == -1) 690205880Sru err(EXIT_FAILURE, "fstat() failed"); 691169507Swkoszek if (S_ISDIR(st.st_mode)) 692169507Swkoszek errx(EXIT_FAILURE, "'%s' is a directory", file); 693169507Swkoszek fp = fdopen(r, "r"); 694169507Swkoszek if (fp == NULL) 695205880Sru err(EXIT_FAILURE, "fdopen() failed"); 696169507Swkoszek osz = 1024; 697169507Swkoszek o = calloc(1, osz); 698169507Swkoszek if (o == NULL) 699205880Sru err(EXIT_FAILURE, "Couldn't allocate memory"); 700169507Swkoszek /* ELF note section header. */ 701207461Simp asprintf(&cmd, "/usr/bin/elfdump -c %s | grep -A 8 kern_conf" 702207461Simp "| tail -5 | cut -d ' ' -f 2 | paste - - - - -", file); 703169507Swkoszek if (cmd == NULL) 704169507Swkoszek errx(EXIT_FAILURE, "asprintf() failed"); 705169507Swkoszek pp = popen(cmd, "r"); 706169507Swkoszek if (pp == NULL) 707169507Swkoszek errx(EXIT_FAILURE, "popen() failed"); 708169507Swkoszek free(cmd); 709169507Swkoszek len = fread(o, osz, 1, pp); 710169507Swkoszek pclose(pp); 711207461Simp r = sscanf(o, "%d%d%d%d%d", &off, &size, &t1, &t2, &align); 712169507Swkoszek free(o); 713207461Simp if (r != 5) 714169507Swkoszek errx(EXIT_FAILURE, "File %s doesn't contain configuration " 715169507Swkoszek "file. Either unsupported, or not compiled with " 716169507Swkoszek "INCLUDE_CONFIG_FILE", file); 717169507Swkoszek r = fseek(fp, off, SEEK_CUR); 718169507Swkoszek if (r != 0) 719205880Sru err(EXIT_FAILURE, "fseek() failed"); 720207461Simp for (i = 0; i < size; i++) { 721188214Swkoszek r = fgetc(fp); 722188214Swkoszek if (r == EOF) 723188214Swkoszek break; 724250133Swkoszek if (r == '\0') { 725250133Swkoszek assert(i == size - 1 && 726250133Swkoszek ("\\0 found in the middle of a file")); 727207461Simp break; 728250133Swkoszek } 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