]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - usr.sbin/config/main.c
Only try to setup moused(8) before setting up the X server if WITH_MICE is
[FreeBSD/FreeBSD.git] / usr.sbin / config / main.c
1 /*
2  * Copyright (c) 1980, 1993
3  *      The Regents of the University of California.  All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
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  * 3. All advertising materials mentioning features or use of this software
14  *    must display the following acknowledgement:
15  *      This product includes software developed by the University of
16  *      California, Berkeley and its contributors.
17  * 4. Neither the name of the University nor the names of its contributors
18  *    may be used to endorse or promote products derived from this software
19  *    without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31  * SUCH DAMAGE.
32  */
33
34 #ifndef lint
35 static const char copyright[] =
36 "@(#) Copyright (c) 1980, 1993\n\
37         The Regents of the University of California.  All rights reserved.\n";
38 #endif /* not lint */
39
40 #ifndef lint
41 #if 0
42 static char sccsid[] = "@(#)main.c      8.1 (Berkeley) 6/6/93";
43 #endif
44 static const char rcsid[] =
45   "$FreeBSD$";
46 #endif /* not lint */
47
48 #include <sys/types.h>
49 #include <sys/stat.h>
50 #include <sys/file.h>
51 #include <sys/mman.h>
52 #include <sys/param.h>
53 #include <ctype.h>
54 #include <err.h>
55 #include <stdio.h>
56 #include <sysexits.h>
57 #include <unistd.h>
58 #include <dirent.h>
59 #include "y.tab.h"
60 #include "config.h"
61
62 #ifndef TRUE
63 #define TRUE    (1)
64 #endif
65
66 #ifndef FALSE
67 #define FALSE   (0)
68 #endif
69
70 #define CDIR    "../compile/"
71
72 char *  PREFIX;
73 char    destdir[MAXPATHLEN];
74 char    srcdir[MAXPATHLEN];
75
76 int     debugging;
77 int     profiling;
78
79 static void configfile(void);
80 static void get_srcdir(void);
81 static void usage(void);
82 static void cleanheaders(char *);
83
84 struct hdr_list {
85         char *h_name;
86         struct hdr_list *h_next;
87 } *htab;
88
89 /*
90  * Config builds a set of files for building a UNIX
91  * system given a description of the desired system.
92  */
93 int
94 main(int argc, char **argv)
95 {
96
97         struct stat buf;
98         int ch, len;
99         char *p;
100         char xxx[MAXPATHLEN];
101
102         while ((ch = getopt(argc, argv, "d:gp")) != -1)
103                 switch (ch) {
104                 case 'd':
105                         if (*destdir == '\0')
106                                 strlcpy(destdir, optarg, sizeof(destdir));
107                         else
108                                 errx(2, "directory already set");
109                         break;
110                 case 'g':
111                         debugging++;
112                         break;
113                 case 'p':
114                         profiling++;
115                         break;
116                 case '?':
117                 default:
118                         usage();
119                 }
120         argc -= optind;
121         argv += optind;
122
123         if (argc != 1)
124                 usage();
125
126         if (freopen(PREFIX = *argv, "r", stdin) == NULL)
127                 err(2, "%s", PREFIX);
128
129         if (*destdir != '\0') {
130                 len = strlen(destdir);
131                 while (len > 1 && destdir[len - 1] == '/')
132                         destdir[--len] = '\0';
133                 get_srcdir();
134         } else {
135                 strlcpy(destdir, CDIR, sizeof(destdir));
136                 strlcat(destdir, PREFIX, sizeof(destdir));
137         }
138
139         p = path((char *)NULL);
140         if (stat(p, &buf)) {
141                 if (mkdir(p, 0777))
142                         err(2, "%s", p);
143         }
144         else if ((buf.st_mode & S_IFMT) != S_IFDIR)
145                 errx(2, "%s isn't a directory", p);
146
147         dtab = NULL;
148         yyfile = *argv;
149         if (yyparse())
150                 exit(3);
151         if (machinename == NULL) {
152                 printf("Specify machine type, e.g. ``machine i386''\n");
153                 exit(1);
154         }
155         /*
156          * make symbolic links in compilation directory
157          * for "sys" (to make genassym.c work along with #include <sys/xxx>)
158          * and similarly for "machine".
159          */
160         if (*srcdir == '\0')
161                 (void)snprintf(xxx, sizeof(xxx), "../../include");
162         else
163                 (void)snprintf(xxx, sizeof(xxx), "%s/%s/include",
164                     srcdir, machinename);
165         (void) unlink(path("machine"));
166         (void) symlink(xxx, path("machine"));
167         options();                      /* make options .h files */
168         makefile();                     /* build Makefile */
169         headers();                      /* make a lot of .h files */
170         configfile();                   /* put config file into kernel*/
171         cleanheaders(p);
172         printf("Kernel build directory is %s\n", p);
173         printf("Don't forget to do a ``make depend''\n");
174         exit(0);
175 }
176
177 /*
178  * get_srcdir
179  *      determine the root of the kernel source tree
180  *      and save that in srcdir.
181  */
182 static void
183 get_srcdir(void)
184 {
185
186         if (realpath("../..", srcdir) == NULL)
187                 errx(2, "Unable to find root of source tree");
188 }
189
190 static void
191 usage(void)
192 {
193                 fprintf(stderr, "usage: config [-gp] [-d destdir] sysname\n");
194                 exit(1);
195 }
196
197 /*
198  * get_word
199  *      returns EOF on end of file
200  *      NULL on end of line
201  *      pointer to the word otherwise
202  */
203 char *
204 get_word(FILE *fp)
205 {
206         static char line[80];
207         int ch;
208         char *cp;
209         int escaped_nl = 0;
210
211 begin:
212         while ((ch = getc(fp)) != EOF)
213                 if (ch != ' ' && ch != '\t')
214                         break;
215         if (ch == EOF)
216                 return ((char *)EOF);
217         if (ch == '\\'){
218                 escaped_nl = 1;
219                 goto begin;
220         }
221         if (ch == '\n') {
222                 if (escaped_nl){
223                         escaped_nl = 0;
224                         goto begin;
225                 }
226                 else
227                         return (NULL);
228         }
229         cp = line;
230         *cp++ = ch;
231         while ((ch = getc(fp)) != EOF) {
232                 if (isspace(ch))
233                         break;
234                 *cp++ = ch;
235         }
236         *cp = 0;
237         if (ch == EOF)
238                 return ((char *)EOF);
239         (void) ungetc(ch, fp);
240         return (line);
241 }
242
243 /*
244  * get_quoted_word
245  *      like get_word but will accept something in double or single quotes
246  *      (to allow embedded spaces).
247  */
248 char *
249 get_quoted_word(FILE *fp)
250 {
251         static char line[256];
252         int ch;
253         char *cp;
254         int escaped_nl = 0;
255
256 begin:
257         while ((ch = getc(fp)) != EOF)
258                 if (ch != ' ' && ch != '\t')
259                         break;
260         if (ch == EOF)
261                 return ((char *)EOF);
262         if (ch == '\\'){
263                 escaped_nl = 1;
264                 goto begin;
265         }
266         if (ch == '\n') {
267                 if (escaped_nl){
268                         escaped_nl = 0;
269                         goto begin;
270                 }
271                 else
272                         return (NULL);
273         }
274         cp = line;
275         if (ch == '"' || ch == '\'') {
276                 int quote = ch;
277
278                 while ((ch = getc(fp)) != EOF) {
279                         if (ch == quote)
280                                 break;
281                         if (ch == '\n') {
282                                 *cp = 0;
283                                 printf("config: missing quote reading `%s'\n",
284                                         line);
285                                 exit(2);
286                         }
287                         *cp++ = ch;
288                 }
289         } else {
290                 *cp++ = ch;
291                 while ((ch = getc(fp)) != EOF) {
292                         if (isspace(ch))
293                                 break;
294                         *cp++ = ch;
295                 }
296                 if (ch != EOF)
297                         (void) ungetc(ch, fp);
298         }
299         *cp = 0;
300         if (ch == EOF)
301                 return ((char *)EOF);
302         return (line);
303 }
304
305 /*
306  * prepend the path to a filename
307  */
308 char *
309 path(const char *file)
310 {
311         char *cp = NULL;
312
313         if (file)
314                 asprintf(&cp, "%s/%s", destdir, file);
315         else
316                 cp = strdup(destdir);
317         return (cp);
318 }
319
320 static void
321 configfile(void)
322 {
323         FILE *fi, *fo;
324         char *p;
325         int i;
326         
327         fi = fopen(PREFIX, "r");
328         if (!fi)
329                 err(2, "%s", PREFIX);
330         fo = fopen(p=path("config.c.new"), "w");
331         if (!fo)
332                 err(2, "%s", p);
333         fprintf(fo, "#include \"opt_config.h\"\n");
334         fprintf(fo, "#ifdef INCLUDE_CONFIG_FILE \n");
335         fprintf(fo, "static const char config[] = \"\\\n");
336         fprintf(fo, "START CONFIG FILE %s\\n\\\n___", PREFIX);
337         while (EOF != (i=getc(fi))) {
338                 if (i == '\n') {
339                         fprintf(fo, "\\n\\\n___");
340                 } else if (i == '\"') {
341                         fprintf(fo, "\\\"");
342                 } else if (i == '\\') {
343                         fprintf(fo, "\\\\");
344                 } else {
345                         putc(i, fo);
346                 }
347         }
348         fprintf(fo, "\\n\\\nEND CONFIG FILE %s\\n\\\n", PREFIX);
349         fprintf(fo, "\";\n");
350         fprintf(fo, "\n#endif /* INCLUDE_CONFIG_FILE */\n");
351         fclose(fi);
352         fclose(fo);
353         moveifchanged(path("config.c.new"), path("config.c"));
354 }
355
356 /*
357  * moveifchanged --
358  *      compare two files; rename if changed.
359  */
360 void
361 moveifchanged(const char *from_name, const char *to_name)
362 {
363         char *p, *q;
364         int changed;
365         size_t tsize;
366         struct stat from_sb, to_sb;
367         int from_fd, to_fd;
368
369         changed = 0;
370
371         if ((from_fd = open(from_name, O_RDONLY)) < 0)
372                 err(EX_OSERR, "moveifchanged open(%s)", from_name);
373
374         if ((to_fd = open(to_name, O_RDONLY)) < 0)
375                 changed++;
376
377         if (!changed && fstat(from_fd, &from_sb) < 0)
378                 err(EX_OSERR, "moveifchanged fstat(%s)", from_name);
379
380         if (!changed && fstat(to_fd, &to_sb) < 0)
381                 err(EX_OSERR, "moveifchanged fstat(%s)", to_name);
382
383         if (!changed && from_sb.st_size != to_sb.st_size)
384                 changed++;
385
386         tsize = (size_t)from_sb.st_size;
387
388         if (!changed) {
389                 p = mmap(NULL, tsize, PROT_READ, MAP_SHARED, from_fd, (off_t)0);
390 #ifndef MAP_FAILED
391 #define MAP_FAILED ((caddr_t) -1)
392 #endif
393                 if (p == MAP_FAILED)
394                         err(EX_OSERR, "mmap %s", from_name);
395                 q = mmap(NULL, tsize, PROT_READ, MAP_SHARED, to_fd, (off_t)0);
396                 if (q == MAP_FAILED)
397                         err(EX_OSERR, "mmap %s", to_name);
398
399                 changed = memcmp(p, q, tsize);
400                 munmap(p, tsize);
401                 munmap(q, tsize);
402         }
403         if (changed) {
404                 if (rename(from_name, to_name) < 0)
405                         err(EX_OSERR, "rename(%s, %s)", from_name, to_name);
406         } else {
407                 if (unlink(from_name) < 0)
408                         err(EX_OSERR, "unlink(%s)", from_name);
409         }
410 }
411
412 static void
413 cleanheaders(char *p)
414 {
415         DIR *dirp;
416         struct dirent *dp;
417         struct file_list *fl;
418         struct hdr_list *hl;
419         int i;
420
421         remember("y.tab.h");
422         remember("setdefs.h");
423         for (fl = ftab; fl != NULL; fl = fl->f_next)
424                 remember(fl->f_fn);
425
426         /*
427          * Scan the build directory and clean out stuff that looks like
428          * it might have been a leftover NFOO header, etc.
429          */
430         dirp = opendir(p);
431         while ((dp = readdir(dirp)) != NULL) {
432                 i = dp->d_namlen - 2;
433                 /* Skip non-headers */
434                 if (dp->d_name[i] != '.' || dp->d_name[i + 1] != 'h')
435                         continue;
436                 /* Skip special stuff, eg: bus_if.h, but check opt_*.h */
437                 if (index(dp->d_name, '_') &&
438                     strncmp(dp->d_name, "opt_", 4) != 0)
439                         continue;
440                 /* Check if it is a target file */
441                 for (hl = htab; hl != NULL; hl = hl->h_next) {
442                         if (strcmp(dp->d_name, hl->h_name) == 0) {
443                                 break;
444                         }
445                 }
446                 if (hl)
447                         continue;
448                 printf("Removing stale header: %s\n", dp->d_name);
449                 unlink(path(dp->d_name));
450         }
451         (void)closedir(dirp);
452 }
453
454 void
455 remember(const char *file)
456 {
457         char *s;
458         struct hdr_list *hl;
459
460         if ((s = strrchr(file, '/')) != NULL)
461                 s = ns(s + 1);
462         else
463                 s = ns(file);
464
465         if (index(s, '_') && strncmp(s, "opt_", 4) != 0) {
466                 free(s);
467                 return;
468         }
469         for (hl = htab; hl != NULL; hl = hl->h_next) {
470                 if (strcmp(s, hl->h_name) == 0) {
471                         free(s);
472                         return;
473                 }
474         }
475         hl = malloc(sizeof(*hl));
476         bzero(hl, sizeof(*hl));
477         hl->h_name = s;
478         hl->h_next = htab;
479         htab = hl;
480 }