2 * Copyright (c) 1980, 1993
3 * The Regents of the University of California. All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 4. Neither the name of the University nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 static const char copyright[] =
32 "@(#) Copyright (c) 1980, 1993\n\
33 The Regents of the University of California. All rights reserved.\n";
38 static char sccsid[] = "@(#)main.c 8.1 (Berkeley) 6/6/93";
40 static const char rcsid[] =
44 #include <sys/types.h>
48 #include <sys/param.h>
57 #include "configvers.h"
67 #define CDIR "../compile/"
70 char destdir[MAXPATHLEN];
71 char srcdir[MAXPATHLEN];
77 static void configfile(void);
78 static void get_srcdir(void);
79 static void usage(void);
80 static void cleanheaders(char *);
84 struct hdr_list *h_next;
88 * Config builds a set of files for building a UNIX
89 * system given a description of the desired system.
92 main(int argc, char **argv)
100 while ((ch = getopt(argc, argv, "d:gpV")) != -1)
103 printf("%d\n", CONFIGVERS);
106 if (*destdir == '\0')
107 strlcpy(destdir, optarg, sizeof(destdir));
109 errx(2, "directory already set");
128 if (freopen("DEFAULTS", "r", stdin) != NULL) {
132 if (freopen(PREFIX, "r", stdin) == NULL)
133 err(2, "%s", PREFIX);
137 if (*destdir != '\0') {
138 len = strlen(destdir);
139 while (len > 1 && destdir[len - 1] == '/')
140 destdir[--len] = '\0';
143 strlcpy(destdir, CDIR, sizeof(destdir));
144 strlcat(destdir, PREFIX, sizeof(destdir));
147 p = path((char *)NULL);
152 else if ((buf.st_mode & S_IFMT) != S_IFDIR)
153 errx(2, "%s isn't a directory", p);
157 SLIST_INIT(&cputype);
161 if (machinename == NULL) {
162 printf("Specify machine type, e.g. ``machine i386''\n");
166 * make symbolic links in compilation directory
167 * for "sys" (to make genassym.c work along with #include <sys/xxx>)
168 * and similarly for "machine".
171 (void)snprintf(xxx, sizeof(xxx), "../../include");
173 (void)snprintf(xxx, sizeof(xxx), "%s/%s/include",
174 srcdir, machinename);
175 (void) unlink(path("machine"));
176 (void) symlink(xxx, path("machine"));
177 if (strcmp(machinename, machinearch) != 0) {
179 * make symbolic links in compilation directory for
180 * machinearch, if it is different than machinename.
183 (void)snprintf(xxx, sizeof(xxx), "../../../%s/include",
186 (void)snprintf(xxx, sizeof(xxx), "%s/%s/include",
187 srcdir, machinearch);
188 (void) unlink(path(machinearch));
189 (void) symlink(xxx, path(machinearch));
191 options(); /* make options .h files */
192 makefile(); /* build Makefile */
193 headers(); /* make a lot of .h files */
194 configfile(); /* put config file into kernel*/
196 printf("Kernel build directory is %s\n", p);
197 printf("Don't forget to do ``make cleandepend; make depend''\n");
203 * determine the root of the kernel source tree
204 * and save that in srcdir.
213 if (realpath("../..", srcdir) == NULL)
214 errx(2, "Unable to find root of source tree");
215 if ((pwd = getenv("PWD")) != NULL && *pwd == '/' &&
216 (pwd = strdup(pwd)) != NULL) {
217 /* Remove the last two path components. */
218 for (i = 0; i < 2; i++) {
219 if ((p = strrchr(pwd, '/')) == NULL) {
225 if (stat(pwd, &lg) != -1 && stat(srcdir, &phy) != -1 &&
226 lg.st_dev == phy.st_dev && lg.st_ino == phy.st_ino)
227 strlcpy(srcdir, pwd, MAXPATHLEN);
236 fprintf(stderr, "usage: config [-Vgp] [-d destdir] sysname\n");
242 * returns EOF on end of file
243 * NULL on end of line
244 * pointer to the word otherwise
249 static char line[80];
255 while ((ch = getc(fp)) != EOF)
256 if (ch != ' ' && ch != '\t')
259 return ((char *)EOF);
274 while ((ch = getc(fp)) != EOF) {
281 return ((char *)EOF);
282 (void) ungetc(ch, fp);
288 * like get_word but will accept something in double or single quotes
289 * (to allow embedded spaces).
292 get_quoted_word(FILE *fp)
294 static char line[256];
300 while ((ch = getc(fp)) != EOF)
301 if (ch != ' ' && ch != '\t')
304 return ((char *)EOF);
318 if (ch == '"' || ch == '\'') {
321 while ((ch = getc(fp)) != EOF) {
326 printf("config: missing quote reading `%s'\n",
334 while ((ch = getc(fp)) != EOF) {
340 (void) ungetc(ch, fp);
344 return ((char *)EOF);
349 * prepend the path to a filename
352 path(const char *file)
357 asprintf(&cp, "%s/%s", destdir, file);
359 cp = strdup(destdir);
370 fi = fopen(PREFIX, "r");
372 err(2, "%s", PREFIX);
373 fo = fopen(p=path("config.c.new"), "w");
376 fprintf(fo, "#include \"opt_config.h\"\n");
377 fprintf(fo, "#ifdef INCLUDE_CONFIG_FILE \n");
378 fprintf(fo, "const char config[] = \"\\\n");
379 fprintf(fo, "START CONFIG FILE %s\\n\\\n___", PREFIX);
380 while (EOF != (i=getc(fi))) {
382 fprintf(fo, "\\n\\\n___");
383 } else if (i == '\"') {
385 } else if (i == '\\') {
391 fprintf(fo, "\\n\\\nEND CONFIG FILE %s\\n\\\n", PREFIX);
392 fprintf(fo, "\";\n");
393 fprintf(fo, "\n#endif /* INCLUDE_CONFIG_FILE */\n");
396 moveifchanged(path("config.c.new"), path("config.c"));
401 * compare two files; rename if changed.
404 moveifchanged(const char *from_name, const char *to_name)
409 struct stat from_sb, to_sb;
414 if ((from_fd = open(from_name, O_RDONLY)) < 0)
415 err(EX_OSERR, "moveifchanged open(%s)", from_name);
417 if ((to_fd = open(to_name, O_RDONLY)) < 0)
420 if (!changed && fstat(from_fd, &from_sb) < 0)
421 err(EX_OSERR, "moveifchanged fstat(%s)", from_name);
423 if (!changed && fstat(to_fd, &to_sb) < 0)
424 err(EX_OSERR, "moveifchanged fstat(%s)", to_name);
426 if (!changed && from_sb.st_size != to_sb.st_size)
429 tsize = (size_t)from_sb.st_size;
432 p = mmap(NULL, tsize, PROT_READ, MAP_SHARED, from_fd, (off_t)0);
434 #define MAP_FAILED ((caddr_t) -1)
437 err(EX_OSERR, "mmap %s", from_name);
438 q = mmap(NULL, tsize, PROT_READ, MAP_SHARED, to_fd, (off_t)0);
440 err(EX_OSERR, "mmap %s", to_name);
442 changed = memcmp(p, q, tsize);
447 if (rename(from_name, to_name) < 0)
448 err(EX_OSERR, "rename(%s, %s)", from_name, to_name);
450 if (unlink(from_name) < 0)
451 err(EX_OSERR, "unlink(%s)", from_name);
456 cleanheaders(char *p)
460 struct file_list *fl;
465 remember("setdefs.h");
466 STAILQ_FOREACH(fl, &ftab, f_next)
470 * Scan the build directory and clean out stuff that looks like
471 * it might have been a leftover NFOO header, etc.
473 if ((dirp = opendir(p)) == NULL)
474 err(EX_OSERR, "opendir %s", p);
475 while ((dp = readdir(dirp)) != NULL) {
476 i = dp->d_namlen - 2;
477 /* Skip non-headers */
478 if (dp->d_name[i] != '.' || dp->d_name[i + 1] != 'h')
480 /* Skip special stuff, eg: bus_if.h, but check opt_*.h */
481 if (index(dp->d_name, '_') &&
482 strncmp(dp->d_name, "opt_", 4) != 0)
484 /* Check if it is a target file */
485 for (hl = htab; hl != NULL; hl = hl->h_next) {
486 if (strcmp(dp->d_name, hl->h_name) == 0) {
492 printf("Removing stale header: %s\n", dp->d_name);
493 if (unlink(path(dp->d_name)) == -1)
494 warn("unlink %s", dp->d_name);
496 (void)closedir(dirp);
500 remember(const char *file)
505 if ((s = strrchr(file, '/')) != NULL)
510 if (index(s, '_') && strncmp(s, "opt_", 4) != 0) {
514 for (hl = htab; hl != NULL; hl = hl->h_next) {
515 if (strcmp(s, hl->h_name) == 0) {
520 hl = malloc(sizeof(*hl));
521 bzero(hl, sizeof(*hl));