main.c revision 29451
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[] =
4529451Scharnier	"$Id$";
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>
521553Srgrimes#include <ctype.h>
5313400Speter#include <err.h>
5429451Scharnier#include <stdio.h>
5513400Speter#include <sysexits.h>
5629451Scharnier#include <unistd.h>
5716073Sphk#include "y.tab.h"
581553Srgrimes#include "config.h"
591553Srgrimes
606631Sjkh#ifndef TRUE
616631Sjkh#define TRUE	(1)
626631Sjkh#endif
636631Sjkh
646631Sjkh#ifndef FALSE
656631Sjkh#define FALSE	(0)
666631Sjkh#endif
676631Sjkh
681553Srgrimesstatic char *PREFIX;
696631Sjkhstatic int no_config_clobber = FALSE;
7012772Speterint old_config_present;
711553Srgrimes
7229451Scharnierstatic void usage __P((void));
7329451Scharniervoid configfile __P((void));
7429451Scharnier
751553Srgrimes/*
761553Srgrimes * Config builds a set of files for building a UNIX
771553Srgrimes * system given a description of the desired system.
781553Srgrimes */
7929451Scharnierint
801553Srgrimesmain(argc, argv)
811553Srgrimes	int argc;
821553Srgrimes	char **argv;
831553Srgrimes{
841553Srgrimes
851553Srgrimes	struct stat buf;
861553Srgrimes	int ch;
871553Srgrimes	char *p;
881553Srgrimes
8924428Simp	while ((ch = getopt(argc, argv, "gpn")) != -1)
901553Srgrimes		switch (ch) {
911553Srgrimes		case 'g':
921553Srgrimes			debugging++;
931553Srgrimes			break;
941553Srgrimes		case 'p':
951553Srgrimes			profiling++;
961553Srgrimes			break;
976631Sjkh		case 'n':
986631Sjkh			no_config_clobber = TRUE;
996631Sjkh			break;
1001553Srgrimes		case '?':
1011553Srgrimes		default:
10229451Scharnier			usage();
1031553Srgrimes		}
1041553Srgrimes	argc -= optind;
1051553Srgrimes	argv += optind;
1061553Srgrimes
10729451Scharnier	if (argc != 1)
10829451Scharnier		usage();
1091553Srgrimes
11029451Scharnier	if (freopen(PREFIX = *argv, "r", stdin) == NULL)
11129451Scharnier		err(2, "%s", PREFIX);
1126631Sjkh	if (getenv("NO_CONFIG_CLOBBER"))
1136631Sjkh		no_config_clobber = TRUE;
1146631Sjkh
1152483Sjkh	p = path((char *)NULL);
1162483Sjkh	if (stat(p, &buf)) {
11729451Scharnier		if (mkdir(p, 0777))
11829451Scharnier			err(2, "%s", p);
1191553Srgrimes	}
1201553Srgrimes	else if ((buf.st_mode & S_IFMT) != S_IFDIR) {
12129451Scharnier		errx(2, "%s isn't a directory", p);
1221553Srgrimes	}
12312508Swollman#ifndef NO_CLOBBER_EVER
1246631Sjkh	else if (!no_config_clobber) {
1252483Sjkh		char tmp[strlen(p) + 8];
1261553Srgrimes
1272483Sjkh		fprintf(stderr, "Removing old directory %s:  ", p);
1282483Sjkh		fflush(stderr);
1292483Sjkh		sprintf(tmp, "rm -rf %s", p);
1302483Sjkh		if (system(tmp)) {
1312483Sjkh			fprintf(stderr, "Failed!\n");
13229451Scharnier			err(2, "%s", tmp);
1332483Sjkh		}
1342483Sjkh		fprintf(stderr, "Done.\n");
13529451Scharnier		if (mkdir(p, 0777))
13629451Scharnier			err(2, "%s", p);
1372483Sjkh	}
13812508Swollman#endif
13912772Speter	else
14012772Speter		old_config_present++;
14112772Speter
1421566Srgrimes	loadaddress = -1;
1431553Srgrimes	dtab = NULL;
1441553Srgrimes	confp = &conf_list;
1451553Srgrimes	compp = &comp_list;
1461553Srgrimes	if (yyparse())
1471553Srgrimes		exit(3);
1481553Srgrimes	switch (machine) {
1491553Srgrimes
1501553Srgrimes	case MACHINE_VAX:
1511553Srgrimes		vax_ioconf();		/* Print ioconf.c */
1521553Srgrimes		ubglue();		/* Create ubglue.s */
1531553Srgrimes		break;
1541553Srgrimes
1551553Srgrimes	case MACHINE_TAHOE:
1561553Srgrimes		tahoe_ioconf();
1571553Srgrimes		vbglue();
1581553Srgrimes		break;
1591553Srgrimes
1601553Srgrimes	case MACHINE_HP300:
1611553Srgrimes	case MACHINE_LUNA68K:
1621553Srgrimes		hp300_ioconf();
1631553Srgrimes		hpglue();
1641553Srgrimes		break;
1651553Srgrimes
1661553Srgrimes	case MACHINE_I386:
1671553Srgrimes		i386_ioconf();		/* Print ioconf.c */
1681553Srgrimes		vector();		/* Create vector.s */
1691553Srgrimes		break;
1701553Srgrimes
1711553Srgrimes	case MACHINE_MIPS:
1721553Srgrimes	case MACHINE_PMAX:
1731553Srgrimes		pmax_ioconf();
1741553Srgrimes		break;
1751553Srgrimes
1761553Srgrimes	case MACHINE_NEWS3400:
1771553Srgrimes		news_ioconf();
1781553Srgrimes		break;
1791553Srgrimes
1801553Srgrimes	default:
1811553Srgrimes		printf("Specify machine type, e.g. ``machine vax''\n");
1821553Srgrimes		exit(1);
1831553Srgrimes	}
1841553Srgrimes	/*
1851553Srgrimes	 * make symbolic links in compilation directory
1861553Srgrimes	 * for "sys" (to make genassym.c work along with #include <sys/xxx>)
1871553Srgrimes	 * and similarly for "machine".
1881553Srgrimes	 */
1891553Srgrimes	{
1901553Srgrimes	char xxx[80];
1911553Srgrimes
1921553Srgrimes	(void) sprintf(xxx, "../../%s/include", machinename);
1931553Srgrimes	(void) symlink(xxx, path("machine"));
1941553Srgrimes	}
19512772Speter	options();			/* make options .h files */
1961553Srgrimes	makefile();			/* build Makefile */
1971553Srgrimes	headers();			/* make a lot of .h files */
1981553Srgrimes	swapconf();			/* swap config files */
19916239Sjkh	configfile();			/* put config file into kernel*/
2008248Sjkh	printf("Kernel build directory is %s\n", p);
2011553Srgrimes	exit(0);
2021553Srgrimes}
2031553Srgrimes
20429451Scharnierstatic void
20529451Scharnierusage()
20629451Scharnier{
20729451Scharnier		fprintf(stderr, "usage: config [-gpn] sysname\n");
20829451Scharnier		exit(1);
20929451Scharnier}
21029451Scharnier
2111553Srgrimes/*
2121553Srgrimes * get_word
2131553Srgrimes *	returns EOF on end of file
2141553Srgrimes *	NULL on end of line
2151553Srgrimes *	pointer to the word otherwise
2161553Srgrimes */
2171553Srgrimeschar *
2181553Srgrimesget_word(fp)
2191553Srgrimes	register FILE *fp;
2201553Srgrimes{
2211553Srgrimes	static char line[80];
2221553Srgrimes	register int ch;
2231553Srgrimes	register char *cp;
2244571Sgibbs	int escaped_nl = 0;
2251553Srgrimes
2264571Sgibbsbegin:
2271553Srgrimes	while ((ch = getc(fp)) != EOF)
2281553Srgrimes		if (ch != ' ' && ch != '\t')
2291553Srgrimes			break;
2301553Srgrimes	if (ch == EOF)
2311553Srgrimes		return ((char *)EOF);
2324571Sgibbs	if (ch == '\\'){
2334571Sgibbs		escaped_nl = 1;
2344571Sgibbs		goto begin;
2354571Sgibbs	}
2361553Srgrimes	if (ch == '\n')
2374571Sgibbs		if (escaped_nl){
2384571Sgibbs			escaped_nl = 0;
2394571Sgibbs			goto begin;
2404571Sgibbs		}
2414571Sgibbs		else
2424571Sgibbs			return (NULL);
2431553Srgrimes	cp = line;
2441553Srgrimes	*cp++ = ch;
2451553Srgrimes	while ((ch = getc(fp)) != EOF) {
2461553Srgrimes		if (isspace(ch))
2471553Srgrimes			break;
2481553Srgrimes		*cp++ = ch;
2491553Srgrimes	}
2501553Srgrimes	*cp = 0;
2511553Srgrimes	if (ch == EOF)
2521553Srgrimes		return ((char *)EOF);
2531553Srgrimes	(void) ungetc(ch, fp);
2541553Srgrimes	return (line);
2551553Srgrimes}
2561553Srgrimes
2571553Srgrimes/*
2581553Srgrimes * get_quoted_word
2591553Srgrimes *	like get_word but will accept something in double or single quotes
2601553Srgrimes *	(to allow embedded spaces).
2611553Srgrimes */
2621553Srgrimeschar *
2631553Srgrimesget_quoted_word(fp)
2641553Srgrimes	register FILE *fp;
2651553Srgrimes{
2661553Srgrimes	static char line[256];
2671553Srgrimes	register int ch;
2681553Srgrimes	register char *cp;
2694571Sgibbs	int escaped_nl = 0;
2701553Srgrimes
2714571Sgibbsbegin:
2721553Srgrimes	while ((ch = getc(fp)) != EOF)
2731553Srgrimes		if (ch != ' ' && ch != '\t')
2741553Srgrimes			break;
2751553Srgrimes	if (ch == EOF)
2761553Srgrimes		return ((char *)EOF);
2774571Sgibbs	if (ch == '\\'){
2784571Sgibbs		escaped_nl = 1;
2794571Sgibbs		goto begin;
2804571Sgibbs	}
2811553Srgrimes	if (ch == '\n')
2824571Sgibbs		if (escaped_nl){
2834571Sgibbs			escaped_nl = 0;
2844571Sgibbs			goto begin;
2854571Sgibbs		}
2864571Sgibbs		else
2874571Sgibbs			return (NULL);
2881553Srgrimes	cp = line;
2891553Srgrimes	if (ch == '"' || ch == '\'') {
2901553Srgrimes		register int quote = ch;
2911553Srgrimes
2921553Srgrimes		while ((ch = getc(fp)) != EOF) {
2931553Srgrimes			if (ch == quote)
2941553Srgrimes				break;
2951553Srgrimes			if (ch == '\n') {
2961553Srgrimes				*cp = 0;
2971553Srgrimes				printf("config: missing quote reading `%s'\n",
2981553Srgrimes					line);
2991553Srgrimes				exit(2);
3001553Srgrimes			}
3011553Srgrimes			*cp++ = ch;
3021553Srgrimes		}
3031553Srgrimes	} else {
3041553Srgrimes		*cp++ = ch;
3051553Srgrimes		while ((ch = getc(fp)) != EOF) {
3061553Srgrimes			if (isspace(ch))
3071553Srgrimes				break;
3081553Srgrimes			*cp++ = ch;
3091553Srgrimes		}
3101553Srgrimes		if (ch != EOF)
3111553Srgrimes			(void) ungetc(ch, fp);
3121553Srgrimes	}
3131553Srgrimes	*cp = 0;
3141553Srgrimes	if (ch == EOF)
3151553Srgrimes		return ((char *)EOF);
3161553Srgrimes	return (line);
3171553Srgrimes}
3181553Srgrimes
3191553Srgrimes/*
3201553Srgrimes * prepend the path to a filename
3211553Srgrimes */
3221553Srgrimeschar *
3231553Srgrimespath(file)
3241553Srgrimes	char *file;
3251553Srgrimes{
3261553Srgrimes	register char *cp;
3271553Srgrimes
3281553Srgrimes#define	CDIR	"../../compile/"
3291553Srgrimes	cp = malloc((unsigned int)(sizeof(CDIR) + strlen(PREFIX) +
3301553Srgrimes	    (file ? strlen(file) : 0) + 2));
3311553Srgrimes	(void) strcpy(cp, CDIR);
3321553Srgrimes	(void) strcat(cp, PREFIX);
3331553Srgrimes	if (file) {
3341553Srgrimes		(void) strcat(cp, "/");
3351553Srgrimes		(void) strcat(cp, file);
3361553Srgrimes	}
3371553Srgrimes	return (cp);
3381553Srgrimes}
33913400Speter
34029451Scharniervoid
34116239Sjkhconfigfile()
34216239Sjkh{
34316239Sjkh	FILE *fi, *fo;
34416239Sjkh	char *p;
34516239Sjkh	int i;
34616239Sjkh
34716239Sjkh	fi = fopen(PREFIX,"r");
34829451Scharnier	if(!fi)
34929451Scharnier		err(2, "%s", PREFIX);
35020940Speter	fo = fopen(p=path("config.c.new"),"w");
35129451Scharnier	if(!fo)
35229451Scharnier		err(2, "%s", p);
35320940Speter	fprintf(fo,"#include \"opt_config.h\"\n");
35416239Sjkh	fprintf(fo,"#ifdef INCLUDE_CONFIG_FILE \n");
35516239Sjkh	fprintf(fo,"static char *config = \"\n");
35616239Sjkh	fprintf(fo,"START CONFIG FILE %s\n___",PREFIX);
35716239Sjkh	while (EOF != (i=getc(fi))) {
35816239Sjkh		if(i == '\n') {
35916239Sjkh			fprintf(fo,"\n___");
36016239Sjkh		} else if(i == '\"') {
36116239Sjkh			fprintf(fo,"\\\"");
36216239Sjkh		} else if(i == '\\') {
36316239Sjkh			fprintf(fo,"\\\\");
36416239Sjkh		} else {
36516239Sjkh			putc(i,fo);
36616239Sjkh		}
36716239Sjkh	}
36816239Sjkh	fprintf(fo,"\nEND CONFIG FILE %s\n",PREFIX);
36916239Sjkh	fprintf(fo,"\";\n");
37020940Speter	fprintf(fo,"\n#endif /* INCLUDE_CONFIG_FILE */\n");
37116239Sjkh	fclose(fi);
37216239Sjkh	fclose(fo);
37320940Speter	moveifchanged(path("config.c.new"), path("config.c"));
37416239Sjkh}
37516239Sjkh
37613400Speter/*
37713400Speter * moveifchanged --
37813400Speter *	compare two files; rename if changed.
37913400Speter */
38013400Spetervoid
38113400Spetermoveifchanged(const char *from_name, const char *to_name)
38213400Speter{
38313400Speter	char *p, *q;
38413400Speter	int changed;
38513400Speter	size_t tsize;
38613400Speter	struct stat from_sb, to_sb;
38713400Speter	int from_fd, to_fd;
38813400Speter
38913400Speter	changed = 0;
39013400Speter
39113400Speter	if ((from_fd = open(from_name, O_RDONLY)) < 0)
39213400Speter		err(EX_OSERR, "moveifchanged open(%s)", from_name);
39313400Speter
39413400Speter	if ((to_fd = open(to_name, O_RDONLY)) < 0)
39513400Speter		changed++;
39613400Speter
39713400Speter	if (!changed && fstat(from_fd, &from_sb) < 0)
39813400Speter		err(EX_OSERR, "moveifchanged fstat(%s)", from_name);
39913400Speter
40013400Speter	if (!changed && fstat(to_fd, &to_sb) < 0)
40113400Speter		err(EX_OSERR, "moveifchanged fstat(%s)", to_name);
40213400Speter
40313400Speter	if (!changed && from_sb.st_size != to_sb.st_size)
40413400Speter		changed++;
40513400Speter
40613400Speter	tsize = (size_t)from_sb.st_size;
40713400Speter
40813400Speter	if (!changed) {
40921786Salex		p = mmap(NULL, tsize, PROT_READ, MAP_SHARED, from_fd, (off_t)0);
41021786Salex		if (p == MAP_FAILED)
41113400Speter			err(EX_OSERR, "mmap %s", from_name);
41221786Salex		q = mmap(NULL, tsize, PROT_READ, MAP_SHARED, to_fd, (off_t)0);
41321786Salex		if (q == MAP_FAILED)
41413400Speter			err(EX_OSERR, "mmap %s", to_name);
41513400Speter
41613400Speter		changed = memcmp(p, q, tsize);
41713400Speter		munmap(p, tsize);
41813400Speter		munmap(q, tsize);
41913400Speter	}
42013400Speter	if (changed) {
42113400Speter		if (rename(from_name, to_name) < 0)
42213400Speter			err(EX_OSERR, "rename(%s, %s)", from_name, to_name);
42313400Speter	} else {
42413400Speter		if (unlink(from_name) < 0)
42513400Speter			err(EX_OSERR, "unlink(%s, %s)", from_name);
42613400Speter	}
42713400Speter
42813400Speter#ifdef DIAG
42913400Speter	if (changed)
43013400Speter		printf("CHANGED! rename (%s, %s)\n", from_name, to_name);
43113400Speter	else
43213400Speter		printf("SAME! unlink (%s)\n", from_name);
43313400Speter#endif
43413400Speter
43513400Speter	return;
43613400Speter}
437