main.c revision 71866
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 * 3. All advertising materials mentioning features or use of this software 141553Srgrimes * must display the following acknowledgement: 151553Srgrimes * This product includes software developed by the University of 161553Srgrimes * California, Berkeley and its contributors. 171553Srgrimes * 4. Neither the name of the University nor the names of its contributors 181553Srgrimes * may be used to endorse or promote products derived from this software 191553Srgrimes * without specific prior written permission. 201553Srgrimes * 211553Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 221553Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 231553Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 241553Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 251553Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 261553Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 271553Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 281553Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 291553Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 301553Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 311553Srgrimes * SUCH DAMAGE. 321553Srgrimes */ 331553Srgrimes 341553Srgrimes#ifndef lint 3529451Scharnierstatic const char copyright[] = 361553Srgrimes"@(#) Copyright (c) 1980, 1993\n\ 371553Srgrimes The Regents of the University of California. All rights reserved.\n"; 381553Srgrimes#endif /* not lint */ 391553Srgrimes 401553Srgrimes#ifndef lint 4129451Scharnier#if 0 421553Srgrimesstatic char sccsid[] = "@(#)main.c 8.1 (Berkeley) 6/6/93"; 4329451Scharnier#endif 4429451Scharnierstatic const char rcsid[] = 4550479Speter "$FreeBSD: head/usr.sbin/config/main.c 71866 2001-01-31 08:42:35Z peter $"; 461553Srgrimes#endif /* not lint */ 471553Srgrimes 481553Srgrimes#include <sys/types.h> 491553Srgrimes#include <sys/stat.h> 501553Srgrimes#include <sys/file.h> 5113400Speter#include <sys/mman.h> 5252653Smarcel#include <sys/param.h> 531553Srgrimes#include <ctype.h> 5413400Speter#include <err.h> 5529451Scharnier#include <stdio.h> 5613400Speter#include <sysexits.h> 5729451Scharnier#include <unistd.h> 5871784Speter#include <dirent.h> 5916073Sphk#include "y.tab.h" 601553Srgrimes#include "config.h" 611553Srgrimes 626631Sjkh#ifndef TRUE 636631Sjkh#define TRUE (1) 646631Sjkh#endif 656631Sjkh 666631Sjkh#ifndef FALSE 676631Sjkh#define FALSE (0) 686631Sjkh#endif 696631Sjkh 7052653Smarcel#define CDIR "../../compile/" 7152653Smarcel 7245744Speterchar * PREFIX; 7352653Smarcelchar destdir[MAXPATHLEN]; 7452653Smarcelchar srcdir[MAXPATHLEN]; 7552653Smarcel 7645744Speterint debugging; 7745744Speterint profiling; 781553Srgrimes 7961640Speterstatic void configfile(void); 8061640Speterstatic void get_srcdir(void); 8161640Speterstatic void usage(void); 8271866Speterstatic void cleanheaders(char *); 8329451Scharnier 8471866Speterstruct hdr_list { 8571866Speter char *h_name; 8671866Speter struct hdr_list *h_next; 8771866Speter} *htab; 8871866Speter 891553Srgrimes/* 901553Srgrimes * Config builds a set of files for building a UNIX 911553Srgrimes * system given a description of the desired system. 921553Srgrimes */ 9329451Scharnierint 9461640Spetermain(int argc, char **argv) 951553Srgrimes{ 961553Srgrimes 971553Srgrimes struct stat buf; 9852653Smarcel int ch, len; 991553Srgrimes char *p; 1001553Srgrimes 10171363Speter while ((ch = getopt(argc, argv, "d:gp")) != -1) 1021553Srgrimes switch (ch) { 10352653Smarcel case 'd': 10452653Smarcel if (*destdir == '\0') 10569004Simp strlcpy(destdir, optarg, sizeof(destdir)); 10652653Smarcel else 10752653Smarcel errx(2, "directory already set"); 10852653Smarcel break; 1091553Srgrimes case 'g': 11045579Sgrog debugging++; 1111553Srgrimes break; 1121553Srgrimes case 'p': 1131553Srgrimes profiling++; 1141553Srgrimes break; 1151553Srgrimes case '?': 1161553Srgrimes default: 11729451Scharnier usage(); 1181553Srgrimes } 1191553Srgrimes argc -= optind; 1201553Srgrimes argv += optind; 1211553Srgrimes 12229451Scharnier if (argc != 1) 12329451Scharnier usage(); 1241553Srgrimes 12529451Scharnier if (freopen(PREFIX = *argv, "r", stdin) == NULL) 12629451Scharnier err(2, "%s", PREFIX); 1276631Sjkh 12852653Smarcel if (*destdir != '\0') { 12952653Smarcel len = strlen(destdir); 13052653Smarcel while (len > 1 && destdir[len - 1] == '/') 13152653Smarcel destdir[--len] = '\0'; 13252653Smarcel get_srcdir(); 13352653Smarcel } else { 13469004Simp strlcpy(destdir, CDIR, sizeof(destdir)); 13569004Simp strlcat(destdir, PREFIX, sizeof(destdir)); 13652653Smarcel } 13752653Smarcel 1382483Sjkh p = path((char *)NULL); 1392483Sjkh if (stat(p, &buf)) { 14029451Scharnier if (mkdir(p, 0777)) 14129451Scharnier err(2, "%s", p); 1421553Srgrimes } 14371363Speter else if ((buf.st_mode & S_IFMT) != S_IFDIR) 14429451Scharnier errx(2, "%s isn't a directory", p); 1451553Srgrimes 1461553Srgrimes dtab = NULL; 1471553Srgrimes if (yyparse()) 1481553Srgrimes exit(3); 1491553Srgrimes switch (machine) { 1501553Srgrimes 1511553Srgrimes case MACHINE_I386: 15235609Skato case MACHINE_PC98: 15336813Sdfr case MACHINE_ALPHA: 15466457Sdfr case MACHINE_IA64: 15571374Sbenno case MACHINE_POWERPC: 15636813Sdfr break; 15736813Sdfr 1581553Srgrimes default: 15945775Speter printf("Specify machine type, e.g. ``machine i386''\n"); 1601553Srgrimes exit(1); 1611553Srgrimes } 1621553Srgrimes /* 1631553Srgrimes * make symbolic links in compilation directory 1641553Srgrimes * for "sys" (to make genassym.c work along with #include <sys/xxx>) 1651553Srgrimes * and similarly for "machine". 1661553Srgrimes */ 1671553Srgrimes { 16869004Simp char xxx[MAXPATHLEN]; 16952653Smarcel if (*srcdir == '\0') 17052653Smarcel (void)snprintf(xxx, sizeof(xxx), "../../%s/include", 17152653Smarcel machinename); 17252653Smarcel else 17352653Smarcel (void)snprintf(xxx, sizeof(xxx), "%s/%s/include", 17452653Smarcel srcdir, machinename); 1751553Srgrimes (void) symlink(xxx, path("machine")); 1761553Srgrimes } 17712772Speter options(); /* make options .h files */ 1781553Srgrimes makefile(); /* build Makefile */ 1791553Srgrimes headers(); /* make a lot of .h files */ 18016239Sjkh configfile(); /* put config file into kernel*/ 18171866Speter cleanheaders(p); 1828248Sjkh printf("Kernel build directory is %s\n", p); 1831553Srgrimes exit(0); 1841553Srgrimes} 1851553Srgrimes 18652653Smarcel/* 18752653Smarcel * get_srcdir 18852653Smarcel * determine the root of the kernel source tree 18952653Smarcel * and save that in srcdir. 19052653Smarcel */ 19129451Scharnierstatic void 19261640Speterget_srcdir(void) 19352653Smarcel{ 19452653Smarcel 19570673Speter if (realpath("../..", srcdir) == NULL) 19670673Speter errx(2, "Unable to find root of source tree"); 19752653Smarcel} 19852653Smarcel 19952653Smarcelstatic void 20061640Speterusage(void) 20129451Scharnier{ 20271363Speter fprintf(stderr, "usage: config [-gp] [-d destdir] sysname\n"); 20329451Scharnier exit(1); 20429451Scharnier} 20529451Scharnier 2061553Srgrimes/* 2071553Srgrimes * get_word 2081553Srgrimes * returns EOF on end of file 2091553Srgrimes * NULL on end of line 2101553Srgrimes * pointer to the word otherwise 2111553Srgrimes */ 2121553Srgrimeschar * 21361640Speterget_word(FILE *fp) 2141553Srgrimes{ 2151553Srgrimes static char line[80]; 21661640Speter int ch; 21761640Speter char *cp; 2184571Sgibbs int escaped_nl = 0; 2191553Srgrimes 2204571Sgibbsbegin: 2211553Srgrimes while ((ch = getc(fp)) != EOF) 2221553Srgrimes if (ch != ' ' && ch != '\t') 2231553Srgrimes break; 2241553Srgrimes if (ch == EOF) 2251553Srgrimes return ((char *)EOF); 2264571Sgibbs if (ch == '\\'){ 2274571Sgibbs escaped_nl = 1; 2284571Sgibbs goto begin; 2294571Sgibbs } 23045775Speter if (ch == '\n') { 2314571Sgibbs if (escaped_nl){ 2324571Sgibbs escaped_nl = 0; 2334571Sgibbs goto begin; 2344571Sgibbs } 2354571Sgibbs else 2364571Sgibbs return (NULL); 23745775Speter } 2381553Srgrimes cp = line; 2391553Srgrimes *cp++ = ch; 2401553Srgrimes while ((ch = getc(fp)) != EOF) { 2411553Srgrimes if (isspace(ch)) 2421553Srgrimes break; 2431553Srgrimes *cp++ = ch; 2441553Srgrimes } 2451553Srgrimes *cp = 0; 2461553Srgrimes if (ch == EOF) 2471553Srgrimes return ((char *)EOF); 2481553Srgrimes (void) ungetc(ch, fp); 2491553Srgrimes return (line); 2501553Srgrimes} 2511553Srgrimes 2521553Srgrimes/* 2531553Srgrimes * get_quoted_word 2541553Srgrimes * like get_word but will accept something in double or single quotes 2551553Srgrimes * (to allow embedded spaces). 2561553Srgrimes */ 2571553Srgrimeschar * 25861640Speterget_quoted_word(FILE *fp) 2591553Srgrimes{ 2601553Srgrimes static char line[256]; 26161640Speter int ch; 26261640Speter char *cp; 2634571Sgibbs int escaped_nl = 0; 2641553Srgrimes 2654571Sgibbsbegin: 2661553Srgrimes while ((ch = getc(fp)) != EOF) 2671553Srgrimes if (ch != ' ' && ch != '\t') 2681553Srgrimes break; 2691553Srgrimes if (ch == EOF) 2701553Srgrimes return ((char *)EOF); 2714571Sgibbs if (ch == '\\'){ 2724571Sgibbs escaped_nl = 1; 2734571Sgibbs goto begin; 2744571Sgibbs } 27545775Speter if (ch == '\n') { 2764571Sgibbs if (escaped_nl){ 2774571Sgibbs escaped_nl = 0; 2784571Sgibbs goto begin; 2794571Sgibbs } 2804571Sgibbs else 2814571Sgibbs return (NULL); 28245775Speter } 2831553Srgrimes cp = line; 2841553Srgrimes if (ch == '"' || ch == '\'') { 28561640Speter int quote = ch; 2861553Srgrimes 2871553Srgrimes while ((ch = getc(fp)) != EOF) { 2881553Srgrimes if (ch == quote) 2891553Srgrimes break; 2901553Srgrimes if (ch == '\n') { 2911553Srgrimes *cp = 0; 2921553Srgrimes printf("config: missing quote reading `%s'\n", 2931553Srgrimes line); 2941553Srgrimes exit(2); 2951553Srgrimes } 2961553Srgrimes *cp++ = ch; 2971553Srgrimes } 2981553Srgrimes } else { 2991553Srgrimes *cp++ = ch; 3001553Srgrimes while ((ch = getc(fp)) != EOF) { 3011553Srgrimes if (isspace(ch)) 3021553Srgrimes break; 3031553Srgrimes *cp++ = ch; 3041553Srgrimes } 3051553Srgrimes if (ch != EOF) 3061553Srgrimes (void) ungetc(ch, fp); 3071553Srgrimes } 3081553Srgrimes *cp = 0; 3091553Srgrimes if (ch == EOF) 3101553Srgrimes return ((char *)EOF); 3111553Srgrimes return (line); 3121553Srgrimes} 3131553Srgrimes 3141553Srgrimes/* 3151553Srgrimes * prepend the path to a filename 3161553Srgrimes */ 3171553Srgrimeschar * 31861640Speterpath(char *file) 3191553Srgrimes{ 32069004Simp char *cp = NULL; 3211553Srgrimes 32269004Simp if (file) 32369004Simp asprintf(&cp, "%s/%s", destdir, file); 32469004Simp else 32569004Simp cp = strdup(destdir); 3261553Srgrimes return (cp); 3271553Srgrimes} 32813400Speter 32945744Speterstatic void 33061640Speterconfigfile(void) 33116239Sjkh{ 33216239Sjkh FILE *fi, *fo; 33316239Sjkh char *p; 33416239Sjkh int i; 33516239Sjkh 33652098Speter fi = fopen(PREFIX, "r"); 33752098Speter if (!fi) 33829451Scharnier err(2, "%s", PREFIX); 33952098Speter fo = fopen(p=path("config.c.new"), "w"); 34052098Speter if (!fo) 34129451Scharnier err(2, "%s", p); 34252098Speter fprintf(fo, "#include \"opt_config.h\"\n"); 34352098Speter fprintf(fo, "#ifdef INCLUDE_CONFIG_FILE \n"); 34452098Speter fprintf(fo, "static const char config[] = \"\\\n"); 34552098Speter fprintf(fo, "START CONFIG FILE %s\\n\\\n___", PREFIX); 34616239Sjkh while (EOF != (i=getc(fi))) { 34752098Speter if (i == '\n') { 34852098Speter fprintf(fo, "\\n\\\n___"); 34952098Speter } else if (i == '\"') { 35052098Speter fprintf(fo, "\\\""); 35152098Speter } else if (i == '\\') { 35252098Speter fprintf(fo, "\\\\"); 35316239Sjkh } else { 35452098Speter putc(i, fo); 35516239Sjkh } 35616239Sjkh } 35752098Speter fprintf(fo, "\\n\\\nEND CONFIG FILE %s\\n\\\n", PREFIX); 35852098Speter fprintf(fo, "\";\n"); 35952098Speter fprintf(fo, "\n#endif /* INCLUDE_CONFIG_FILE */\n"); 36016239Sjkh fclose(fi); 36116239Sjkh fclose(fo); 36220940Speter moveifchanged(path("config.c.new"), path("config.c")); 36316239Sjkh} 36416239Sjkh 36513400Speter/* 36613400Speter * moveifchanged -- 36713400Speter * compare two files; rename if changed. 36813400Speter */ 36913400Spetervoid 37013400Spetermoveifchanged(const char *from_name, const char *to_name) 37113400Speter{ 37213400Speter char *p, *q; 37313400Speter int changed; 37413400Speter size_t tsize; 37513400Speter struct stat from_sb, to_sb; 37613400Speter int from_fd, to_fd; 37713400Speter 37813400Speter changed = 0; 37913400Speter 38013400Speter if ((from_fd = open(from_name, O_RDONLY)) < 0) 38113400Speter err(EX_OSERR, "moveifchanged open(%s)", from_name); 38213400Speter 38313400Speter if ((to_fd = open(to_name, O_RDONLY)) < 0) 38413400Speter changed++; 38513400Speter 38613400Speter if (!changed && fstat(from_fd, &from_sb) < 0) 38713400Speter err(EX_OSERR, "moveifchanged fstat(%s)", from_name); 38813400Speter 38913400Speter if (!changed && fstat(to_fd, &to_sb) < 0) 39013400Speter err(EX_OSERR, "moveifchanged fstat(%s)", to_name); 39113400Speter 39213400Speter if (!changed && from_sb.st_size != to_sb.st_size) 39313400Speter changed++; 39413400Speter 39513400Speter tsize = (size_t)from_sb.st_size; 39613400Speter 39713400Speter if (!changed) { 39821786Salex p = mmap(NULL, tsize, PROT_READ, MAP_SHARED, from_fd, (off_t)0); 39936813Sdfr#ifndef MAP_FAILED 40036813Sdfr#define MAP_FAILED ((caddr_t) -1) 40136813Sdfr#endif 40221786Salex if (p == MAP_FAILED) 40313400Speter err(EX_OSERR, "mmap %s", from_name); 40421786Salex q = mmap(NULL, tsize, PROT_READ, MAP_SHARED, to_fd, (off_t)0); 40521786Salex if (q == MAP_FAILED) 40613400Speter err(EX_OSERR, "mmap %s", to_name); 40713400Speter 40813400Speter changed = memcmp(p, q, tsize); 40913400Speter munmap(p, tsize); 41013400Speter munmap(q, tsize); 41113400Speter } 41213400Speter if (changed) { 41313400Speter if (rename(from_name, to_name) < 0) 41413400Speter err(EX_OSERR, "rename(%s, %s)", from_name, to_name); 41513400Speter } else { 41613400Speter if (unlink(from_name) < 0) 41731216Sjdp err(EX_OSERR, "unlink(%s)", from_name); 41813400Speter } 41913400Speter} 42071784Speter 42171784Speterstatic void 42271866Spetercleanheaders(char *p) 42371784Speter{ 42471784Speter DIR *dirp; 42571784Speter struct dirent *dp; 42671784Speter struct file_list *fl; 42771866Speter struct hdr_list *hl; 42871784Speter int i; 42971784Speter 43071866Speter remember("y.tab.h"); 43171866Speter remember("setdefs.h"); 43271866Speter for (fl = ftab; fl != NULL; fl = fl->f_next) 43371866Speter remember(fl->f_fn); 43471784Speter 43571784Speter /* 43671784Speter * Scan the build directory and clean out stuff that looks like 43771784Speter * it might have been a leftover NFOO header, etc. 43871784Speter */ 43971784Speter dirp = opendir(p); 44071784Speter while ((dp = readdir(dirp)) != NULL) { 44171784Speter i = dp->d_namlen - 2; 44271784Speter /* Skip non-headers */ 44371784Speter if (dp->d_name[i] != '.' || dp->d_name[i + 1] != 'h') 44471784Speter continue; 44571784Speter /* Skip special stuff, eg: bus_if.h, but check opt_*.h */ 44671784Speter if (index(dp->d_name, '_') && 44771784Speter strncmp(dp->d_name, "opt_", 4) != 0) 44871784Speter continue; 44971784Speter /* Check if it is a target file */ 45071866Speter for (hl = htab; hl != NULL; hl = hl->h_next) { 45171866Speter if (strcmp(dp->d_name, hl->h_name) == 0) { 45271784Speter break; 45371784Speter } 45471784Speter } 45571866Speter if (hl) 45671784Speter continue; 45771784Speter printf("Removing stale header: %s\n", dp->d_name); 45871784Speter unlink(path(dp->d_name)); 45971784Speter } 46071784Speter (void)closedir(dirp); 46171866Speter} 46271784Speter 46371866Spetervoid 46471866Speterremember(char *file) 46571866Speter{ 46671866Speter char *s; 46771866Speter struct hdr_list *hl; 46871866Speter 46971866Speter if ((s = strrchr(file, '/')) != NULL) 47071866Speter s++; 47171866Speter else 47271866Speter s = file; 47371866Speter s = ns(s); 47471866Speter 47571866Speter if (index(s, '_') && strncmp(s, "opt_", 4) != 0) { 47671866Speter free(s); 47771866Speter return; 47871866Speter } 47971866Speter for (hl = htab; hl != NULL; hl = hl->h_next) { 48071866Speter if (strcmp(s, hl->h_name) == 0) { 48171866Speter free(s); 48271866Speter return; 48371866Speter } 48471866Speter } 48571866Speter hl = malloc(sizeof(*hl)); 48671866Speter bzero(hl, sizeof(*hl)); 48771866Speter hl->h_name = s; 48871866Speter hl->h_next = htab; 48971866Speter htab = hl; 49071784Speter} 491