]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/bmake/main.c
Merge libc++ trunk r300890, and update build glue.
[FreeBSD/FreeBSD.git] / contrib / bmake / main.c
1 /*      $NetBSD: main.c,v 1.264 2017/04/20 03:57:27 sjg Exp $   */
2
3 /*
4  * Copyright (c) 1988, 1989, 1990, 1993
5  *      The Regents of the University of California.  All rights reserved.
6  *
7  * This code is derived from software contributed to Berkeley by
8  * Adam de Boor.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  * 3. Neither the name of the University nor the names of its contributors
19  *    may be used to endorse or promote products derived from this software
20  *    without specific prior written permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32  * SUCH DAMAGE.
33  */
34
35 /*
36  * Copyright (c) 1989 by Berkeley Softworks
37  * All rights reserved.
38  *
39  * This code is derived from software contributed to Berkeley by
40  * Adam de Boor.
41  *
42  * Redistribution and use in source and binary forms, with or without
43  * modification, are permitted provided that the following conditions
44  * are met:
45  * 1. Redistributions of source code must retain the above copyright
46  *    notice, this list of conditions and the following disclaimer.
47  * 2. Redistributions in binary form must reproduce the above copyright
48  *    notice, this list of conditions and the following disclaimer in the
49  *    documentation and/or other materials provided with the distribution.
50  * 3. All advertising materials mentioning features or use of this software
51  *    must display the following acknowledgement:
52  *      This product includes software developed by the University of
53  *      California, Berkeley and its contributors.
54  * 4. Neither the name of the University nor the names of its contributors
55  *    may be used to endorse or promote products derived from this software
56  *    without specific prior written permission.
57  *
58  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
59  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
60  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
61  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
62  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
63  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
64  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
65  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
66  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
67  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
68  * SUCH DAMAGE.
69  */
70
71 #ifndef MAKE_NATIVE
72 static char rcsid[] = "$NetBSD: main.c,v 1.264 2017/04/20 03:57:27 sjg Exp $";
73 #else
74 #include <sys/cdefs.h>
75 #ifndef lint
76 __COPYRIGHT("@(#) Copyright (c) 1988, 1989, 1990, 1993\
77  The Regents of the University of California.  All rights reserved.");
78 #endif /* not lint */
79
80 #ifndef lint
81 #if 0
82 static char sccsid[] = "@(#)main.c      8.3 (Berkeley) 3/19/94";
83 #else
84 __RCSID("$NetBSD: main.c,v 1.264 2017/04/20 03:57:27 sjg Exp $");
85 #endif
86 #endif /* not lint */
87 #endif
88
89 /*-
90  * main.c --
91  *      The main file for this entire program. Exit routines etc
92  *      reside here.
93  *
94  * Utility functions defined in this file:
95  *      Main_ParseArgLine       Takes a line of arguments, breaks them and
96  *                              treats them as if they were given when first
97  *                              invoked. Used by the parse module to implement
98  *                              the .MFLAGS target.
99  *
100  *      Error                   Print a tagged error message. The global
101  *                              MAKE variable must have been defined. This
102  *                              takes a format string and optional arguments
103  *                              for it.
104  *
105  *      Fatal                   Print an error message and exit. Also takes
106  *                              a format string and arguments for it.
107  *
108  *      Punt                    Aborts all jobs and exits with a message. Also
109  *                              takes a format string and arguments for it.
110  *
111  *      Finish                  Finish things up by printing the number of
112  *                              errors which occurred, as passed to it, and
113  *                              exiting.
114  */
115
116 #include <sys/types.h>
117 #include <sys/time.h>
118 #include <sys/param.h>
119 #include <sys/resource.h>
120 #include <sys/stat.h>
121 #if defined(MAKE_NATIVE) && defined(HAVE_SYSCTL)
122 #include <sys/sysctl.h>
123 #endif
124 #include <sys/utsname.h>
125 #include "wait.h"
126
127 #include <errno.h>
128 #include <signal.h>
129 #include <stdarg.h>
130 #include <stdio.h>
131 #include <stdlib.h>
132 #include <time.h>
133 #include <ctype.h>
134
135 #include "make.h"
136 #include "hash.h"
137 #include "dir.h"
138 #include "job.h"
139 #include "pathnames.h"
140 #include "trace.h"
141
142 #ifdef USE_IOVEC
143 #include <sys/uio.h>
144 #endif
145
146 #ifndef DEFMAXLOCAL
147 #define DEFMAXLOCAL DEFMAXJOBS
148 #endif  /* DEFMAXLOCAL */
149
150 #ifndef __arraycount
151 # define __arraycount(__x)      (sizeof(__x) / sizeof(__x[0]))
152 #endif
153
154 Lst                     create;         /* Targets to be made */
155 time_t                  now;            /* Time at start of make */
156 GNode                   *DEFAULT;       /* .DEFAULT node */
157 Boolean                 allPrecious;    /* .PRECIOUS given on line by itself */
158 Boolean                 deleteOnError;  /* .DELETE_ON_ERROR: set */
159
160 static Boolean          noBuiltins;     /* -r flag */
161 static Lst              makefiles;      /* ordered list of makefiles to read */
162 static Boolean          printVars;      /* print value of one or more vars */
163 static Lst              variables;      /* list of variables to print */
164 int                     maxJobs;        /* -j argument */
165 static int              maxJobTokens;   /* -j argument */
166 Boolean                 compatMake;     /* -B argument */
167 int                     debug;          /* -d argument */
168 Boolean                 debugVflag;     /* -dV */
169 Boolean                 noExecute;      /* -n flag */
170 Boolean                 noRecursiveExecute;     /* -N flag */
171 Boolean                 keepgoing;      /* -k flag */
172 Boolean                 queryFlag;      /* -q flag */
173 Boolean                 touchFlag;      /* -t flag */
174 Boolean                 enterFlag;      /* -w flag */
175 Boolean                 enterFlagObj;   /* -w and objdir != srcdir */
176 Boolean                 ignoreErrors;   /* -i flag */
177 Boolean                 beSilent;       /* -s flag */
178 Boolean                 oldVars;        /* variable substitution style */
179 Boolean                 checkEnvFirst;  /* -e flag */
180 Boolean                 parseWarnFatal; /* -W flag */
181 Boolean                 jobServer;      /* -J flag */
182 static int jp_0 = -1, jp_1 = -1;        /* ends of parent job pipe */
183 Boolean                 varNoExportEnv; /* -X flag */
184 Boolean                 doing_depend;   /* Set while reading .depend */
185 static Boolean          jobsRunning;    /* TRUE if the jobs might be running */
186 static const char *     tracefile;
187 static void             MainParseArgs(int, char **);
188 static int              ReadMakefile(const void *, const void *);
189 static void             usage(void) MAKE_ATTR_DEAD;
190 static void             purge_cached_realpaths(void);
191
192 static Boolean          ignorePWD;      /* if we use -C, PWD is meaningless */
193 static char objdir[MAXPATHLEN + 1];     /* where we chdir'ed to */
194 char curdir[MAXPATHLEN + 1];            /* Startup directory */
195 char *progname;                         /* the program name */
196 char *makeDependfile;
197 pid_t myPid;
198 int makelevel;
199
200 Boolean forceJobs = FALSE;
201
202 /*
203  * On some systems MACHINE is defined as something other than
204  * what we want.
205  */
206 #ifdef FORCE_MACHINE
207 # undef MACHINE
208 # define MACHINE FORCE_MACHINE
209 #endif
210
211 extern Lst parseIncPath;
212
213 /*
214  * For compatibility with the POSIX version of MAKEFLAGS that includes
215  * all the options with out -, convert flags to -f -l -a -g -s.
216  */
217 static char *
218 explode(const char *flags)
219 {
220     size_t len;
221     char *nf, *st;
222     const char *f;
223
224     if (flags == NULL)
225         return NULL;
226
227     for (f = flags; *f; f++)
228         if (!isalpha((unsigned char)*f))
229             break;
230
231     if (*f)
232         return bmake_strdup(flags);
233
234     len = strlen(flags);
235     st = nf = bmake_malloc(len * 3 + 1);
236     while (*flags) {
237         *nf++ = '-';
238         *nf++ = *flags++;
239         *nf++ = ' ';
240     }
241     *nf = '\0';
242     return st;
243 }
244             
245 static void
246 parse_debug_options(const char *argvalue)
247 {
248         const char *modules;
249         const char *mode;
250         char *fname;
251         int len;
252
253         for (modules = argvalue; *modules; ++modules) {
254                 switch (*modules) {
255                 case 'A':
256                         debug = ~0;
257                         break;
258                 case 'a':
259                         debug |= DEBUG_ARCH;
260                         break;
261                 case 'C':
262                         debug |= DEBUG_CWD;
263                         break;
264                 case 'c':
265                         debug |= DEBUG_COND;
266                         break;
267                 case 'd':
268                         debug |= DEBUG_DIR;
269                         break;
270                 case 'e':
271                         debug |= DEBUG_ERROR;
272                         break;
273                 case 'f':
274                         debug |= DEBUG_FOR;
275                         break;
276                 case 'g':
277                         if (modules[1] == '1') {
278                                 debug |= DEBUG_GRAPH1;
279                                 ++modules;
280                         }
281                         else if (modules[1] == '2') {
282                                 debug |= DEBUG_GRAPH2;
283                                 ++modules;
284                         }
285                         else if (modules[1] == '3') {
286                                 debug |= DEBUG_GRAPH3;
287                                 ++modules;
288                         }
289                         break;
290                 case 'j':
291                         debug |= DEBUG_JOB;
292                         break;
293                 case 'l':
294                         debug |= DEBUG_LOUD;
295                         break;
296                 case 'M':
297                         debug |= DEBUG_META;
298                         break;
299                 case 'm':
300                         debug |= DEBUG_MAKE;
301                         break;
302                 case 'n':
303                         debug |= DEBUG_SCRIPT;
304                         break;
305                 case 'p':
306                         debug |= DEBUG_PARSE;
307                         break;
308                 case 's':
309                         debug |= DEBUG_SUFF;
310                         break;
311                 case 't':
312                         debug |= DEBUG_TARG;
313                         break;
314                 case 'V':
315                         debugVflag = TRUE;
316                         break;
317                 case 'v':
318                         debug |= DEBUG_VAR;
319                         break;
320                 case 'x':
321                         debug |= DEBUG_SHELL;
322                         break;
323                 case 'F':
324                         if (debug_file != stdout && debug_file != stderr)
325                                 fclose(debug_file);
326                         if (*++modules == '+') {
327                                 modules++;
328                                 mode = "a";
329                         } else
330                                 mode = "w";
331                         if (strcmp(modules, "stdout") == 0) {
332                                 debug_file = stdout;
333                                 goto debug_setbuf;
334                         }
335                         if (strcmp(modules, "stderr") == 0) {
336                                 debug_file = stderr;
337                                 goto debug_setbuf;
338                         }
339                         len = strlen(modules);
340                         fname = bmake_malloc(len + 20);
341                         memcpy(fname, modules, len + 1);
342                         /* Let the filename be modified by the pid */
343                         if (strcmp(fname + len - 3, ".%d") == 0)
344                                 snprintf(fname + len - 2, 20, "%d", getpid());
345                         debug_file = fopen(fname, mode);
346                         if (!debug_file) {
347                                 fprintf(stderr, "Cannot open debug file %s\n",
348                                     fname);
349                                 usage();
350                         }
351                         free(fname);
352                         goto debug_setbuf;
353                 default:
354                         (void)fprintf(stderr,
355                             "%s: illegal argument to d option -- %c\n",
356                             progname, *modules);
357                         usage();
358                 }
359         }
360 debug_setbuf:
361         /*
362          * Make the debug_file unbuffered, and make
363          * stdout line buffered (unless debugfile == stdout).
364          */
365         setvbuf(debug_file, NULL, _IONBF, 0);
366         if (debug_file != stdout) {
367                 setvbuf(stdout, NULL, _IOLBF, 0);
368         }
369 }
370
371 /*
372  * does path contain any relative components
373  */
374 static int
375 is_relpath(const char *path)
376 {
377         const char *cp;
378
379         if (path[0] != '/')
380                 return TRUE;
381         cp = path;
382         do {
383                 cp = strstr(cp, "/.");
384                 if (!cp)
385                         break;
386                 cp += 2;
387                 if (cp[0] == '/' || cp[0] == '\0')
388                         return TRUE;
389                 else if (cp[0] == '.') {
390                         if (cp[1] == '/' || cp[1] == '\0')
391                                 return TRUE;
392                 }
393         } while (cp);
394         return FALSE;
395 }
396
397 /*-
398  * MainParseArgs --
399  *      Parse a given argument vector. Called from main() and from
400  *      Main_ParseArgLine() when the .MAKEFLAGS target is used.
401  *
402  *      XXX: Deal with command line overriding .MAKEFLAGS in makefile
403  *
404  * Results:
405  *      None
406  *
407  * Side Effects:
408  *      Various global and local flags will be set depending on the flags
409  *      given
410  */
411 static void
412 MainParseArgs(int argc, char **argv)
413 {
414         char *p;
415         int c = '?';
416         int arginc;
417         char *argvalue;
418         const char *getopt_def;
419         struct stat sa, sb;
420         char *optscan;
421         Boolean inOption, dashDash = FALSE;
422         char found_path[MAXPATHLEN + 1];        /* for searching for sys.mk */
423
424 #define OPTFLAGS "BC:D:I:J:NST:V:WXd:ef:ij:km:nqrstw"
425 /* Can't actually use getopt(3) because rescanning is not portable */
426
427         getopt_def = OPTFLAGS;
428 rearg:  
429         inOption = FALSE;
430         optscan = NULL;
431         while(argc > 1) {
432                 char *getopt_spec;
433                 if(!inOption)
434                         optscan = argv[1];
435                 c = *optscan++;
436                 arginc = 0;
437                 if(inOption) {
438                         if(c == '\0') {
439                                 ++argv;
440                                 --argc;
441                                 inOption = FALSE;
442                                 continue;
443                         }
444                 } else {
445                         if (c != '-' || dashDash)
446                                 break;
447                         inOption = TRUE;
448                         c = *optscan++;
449                 }
450                 /* '-' found at some earlier point */
451                 getopt_spec = strchr(getopt_def, c);
452                 if(c != '\0' && getopt_spec != NULL && getopt_spec[1] == ':') {
453                         /* -<something> found, and <something> should have an arg */
454                         inOption = FALSE;
455                         arginc = 1;
456                         argvalue = optscan;
457                         if(*argvalue == '\0') {
458                                 if (argc < 3)
459                                         goto noarg;
460                                 argvalue = argv[2];
461                                 arginc = 2;
462                         }
463                 } else {
464                         argvalue = NULL; 
465                 }
466                 switch(c) {
467                 case '\0':
468                         arginc = 1;
469                         inOption = FALSE;
470                         break;
471                 case 'B':
472                         compatMake = TRUE;
473                         Var_Append(MAKEFLAGS, "-B", VAR_GLOBAL);
474                         Var_Set(MAKE_MODE, "compat", VAR_GLOBAL, 0);
475                         break;
476                 case 'C':
477                         if (chdir(argvalue) == -1) {
478                                 (void)fprintf(stderr,
479                                               "%s: chdir %s: %s\n",
480                                               progname, argvalue,
481                                               strerror(errno));
482                                 exit(1);
483                         }
484                         if (getcwd(curdir, MAXPATHLEN) == NULL) {
485                                 (void)fprintf(stderr, "%s: %s.\n", progname, strerror(errno));
486                                 exit(2);
487                         }
488                         if (!is_relpath(argvalue) &&
489                             stat(argvalue, &sa) != -1 &&
490                             stat(curdir, &sb) != -1 &&
491                             sa.st_ino == sb.st_ino &&
492                             sa.st_dev == sb.st_dev)
493                                 strncpy(curdir, argvalue, MAXPATHLEN);
494                         ignorePWD = TRUE;
495                         break;
496                 case 'D':
497                         if (argvalue == NULL || argvalue[0] == 0) goto noarg;
498                         Var_Set(argvalue, "1", VAR_GLOBAL, 0);
499                         Var_Append(MAKEFLAGS, "-D", VAR_GLOBAL);
500                         Var_Append(MAKEFLAGS, argvalue, VAR_GLOBAL);
501                         break;
502                 case 'I':
503                         if (argvalue == NULL) goto noarg;
504                         Parse_AddIncludeDir(argvalue);
505                         Var_Append(MAKEFLAGS, "-I", VAR_GLOBAL);
506                         Var_Append(MAKEFLAGS, argvalue, VAR_GLOBAL);
507                         break;
508                 case 'J':
509                         if (argvalue == NULL) goto noarg;
510                         if (sscanf(argvalue, "%d,%d", &jp_0, &jp_1) != 2) {
511                             (void)fprintf(stderr,
512                                 "%s: internal error -- J option malformed (%s)\n",
513                                 progname, argvalue);
514                                 usage();
515                         }
516                         if ((fcntl(jp_0, F_GETFD, 0) < 0) ||
517                             (fcntl(jp_1, F_GETFD, 0) < 0)) {
518 #if 0
519                             (void)fprintf(stderr,
520                                 "%s: ###### warning -- J descriptors were closed!\n",
521                                 progname);
522                             exit(2);
523 #endif
524                             jp_0 = -1;
525                             jp_1 = -1;
526                             compatMake = TRUE;
527                         } else {
528                             Var_Append(MAKEFLAGS, "-J", VAR_GLOBAL);
529                             Var_Append(MAKEFLAGS, argvalue, VAR_GLOBAL);
530                             jobServer = TRUE;
531                         }
532                         break;
533                 case 'N':
534                         noExecute = TRUE;
535                         noRecursiveExecute = TRUE;
536                         Var_Append(MAKEFLAGS, "-N", VAR_GLOBAL);
537                         break;
538                 case 'S':
539                         keepgoing = FALSE;
540                         Var_Append(MAKEFLAGS, "-S", VAR_GLOBAL);
541                         break;
542                 case 'T':
543                         if (argvalue == NULL) goto noarg;
544                         tracefile = bmake_strdup(argvalue);
545                         Var_Append(MAKEFLAGS, "-T", VAR_GLOBAL);
546                         Var_Append(MAKEFLAGS, argvalue, VAR_GLOBAL);
547                         break;
548                 case 'V':
549                         if (argvalue == NULL) goto noarg;
550                         printVars = TRUE;
551                         (void)Lst_AtEnd(variables, argvalue);
552                         Var_Append(MAKEFLAGS, "-V", VAR_GLOBAL);
553                         Var_Append(MAKEFLAGS, argvalue, VAR_GLOBAL);
554                         break;
555                 case 'W':
556                         parseWarnFatal = TRUE;
557                         break;
558                 case 'X':
559                         varNoExportEnv = TRUE;
560                         Var_Append(MAKEFLAGS, "-X", VAR_GLOBAL);
561                         break;
562                 case 'd':
563                         if (argvalue == NULL) goto noarg;
564                         /* If '-d-opts' don't pass to children */
565                         if (argvalue[0] == '-')
566                             argvalue++;
567                         else {
568                             Var_Append(MAKEFLAGS, "-d", VAR_GLOBAL);
569                             Var_Append(MAKEFLAGS, argvalue, VAR_GLOBAL);
570                         }
571                         parse_debug_options(argvalue);
572                         break;
573                 case 'e':
574                         checkEnvFirst = TRUE;
575                         Var_Append(MAKEFLAGS, "-e", VAR_GLOBAL);
576                         break;
577                 case 'f':
578                         if (argvalue == NULL) goto noarg;
579                         (void)Lst_AtEnd(makefiles, argvalue);
580                         break;
581                 case 'i':
582                         ignoreErrors = TRUE;
583                         Var_Append(MAKEFLAGS, "-i", VAR_GLOBAL);
584                         break;
585                 case 'j':
586                         if (argvalue == NULL) goto noarg;
587                         forceJobs = TRUE;
588                         maxJobs = strtol(argvalue, &p, 0);
589                         if (*p != '\0' || maxJobs < 1) {
590                                 (void)fprintf(stderr, "%s: illegal argument to -j -- must be positive integer!\n",
591                                     progname);
592                                 exit(1);
593                         }
594                         Var_Append(MAKEFLAGS, "-j", VAR_GLOBAL);
595                         Var_Append(MAKEFLAGS, argvalue, VAR_GLOBAL);
596                         Var_Set(".MAKE.JOBS", argvalue, VAR_GLOBAL, 0);
597                         maxJobTokens = maxJobs;
598                         break;
599                 case 'k':
600                         keepgoing = TRUE;
601                         Var_Append(MAKEFLAGS, "-k", VAR_GLOBAL);
602                         break;
603                 case 'm':
604                         if (argvalue == NULL) goto noarg;
605                         /* look for magic parent directory search string */
606                         if (strncmp(".../", argvalue, 4) == 0) {
607                                 if (!Dir_FindHereOrAbove(curdir, argvalue+4,
608                                     found_path, sizeof(found_path)))
609                                         break;          /* nothing doing */
610                                 (void)Dir_AddDir(sysIncPath, found_path);
611                         } else {
612                                 (void)Dir_AddDir(sysIncPath, argvalue);
613                         }
614                         Var_Append(MAKEFLAGS, "-m", VAR_GLOBAL);
615                         Var_Append(MAKEFLAGS, argvalue, VAR_GLOBAL);
616                         break;
617                 case 'n':
618                         noExecute = TRUE;
619                         Var_Append(MAKEFLAGS, "-n", VAR_GLOBAL);
620                         break;
621                 case 'q':
622                         queryFlag = TRUE;
623                         /* Kind of nonsensical, wot? */
624                         Var_Append(MAKEFLAGS, "-q", VAR_GLOBAL);
625                         break;
626                 case 'r':
627                         noBuiltins = TRUE;
628                         Var_Append(MAKEFLAGS, "-r", VAR_GLOBAL);
629                         break;
630                 case 's':
631                         beSilent = TRUE;
632                         Var_Append(MAKEFLAGS, "-s", VAR_GLOBAL);
633                         break;
634                 case 't':
635                         touchFlag = TRUE;
636                         Var_Append(MAKEFLAGS, "-t", VAR_GLOBAL);
637                         break;
638                 case 'w':
639                         enterFlag = TRUE;
640                         Var_Append(MAKEFLAGS, "-w", VAR_GLOBAL);
641                         break;
642                 case '-':
643                         dashDash = TRUE;
644                         break;
645                 default:
646                 case '?':
647 #ifndef MAKE_NATIVE
648                         fprintf(stderr, "getopt(%s) -> %d (%c)\n",
649                                 OPTFLAGS, c, c);
650 #endif
651                         usage();
652                 }
653                 argv += arginc;
654                 argc -= arginc;
655         }
656
657         oldVars = TRUE;
658
659         /*
660          * See if the rest of the arguments are variable assignments and
661          * perform them if so. Else take them to be targets and stuff them
662          * on the end of the "create" list.
663          */
664         for (; argc > 1; ++argv, --argc)
665                 if (Parse_IsVar(argv[1])) {
666                         Parse_DoVar(argv[1], VAR_CMD);
667                 } else {
668                         if (!*argv[1])
669                                 Punt("illegal (null) argument.");
670                         if (*argv[1] == '-' && !dashDash)
671                                 goto rearg;
672                         (void)Lst_AtEnd(create, bmake_strdup(argv[1]));
673                 }
674
675         return;
676 noarg:
677         (void)fprintf(stderr, "%s: option requires an argument -- %c\n",
678             progname, c);
679         usage();
680 }
681
682 /*-
683  * Main_ParseArgLine --
684  *      Used by the parse module when a .MFLAGS or .MAKEFLAGS target
685  *      is encountered and by main() when reading the .MAKEFLAGS envariable.
686  *      Takes a line of arguments and breaks it into its
687  *      component words and passes those words and the number of them to the
688  *      MainParseArgs function.
689  *      The line should have all its leading whitespace removed.
690  *
691  * Input:
692  *      line            Line to fracture
693  *
694  * Results:
695  *      None
696  *
697  * Side Effects:
698  *      Only those that come from the various arguments.
699  */
700 void
701 Main_ParseArgLine(const char *line)
702 {
703         char **argv;                    /* Manufactured argument vector */
704         int argc;                       /* Number of arguments in argv */
705         char *args;                     /* Space used by the args */
706         char *buf, *p1;
707         char *argv0 = Var_Value(".MAKE", VAR_GLOBAL, &p1);
708         size_t len;
709
710         if (line == NULL)
711                 return;
712         for (; *line == ' '; ++line)
713                 continue;
714         if (!*line)
715                 return;
716
717 #ifndef POSIX
718         {
719                 /*
720                  * $MAKE may simply be naming the make(1) binary
721                  */
722                 char *cp;
723
724                 if (!(cp = strrchr(line, '/')))
725                         cp = line;
726                 if ((cp = strstr(cp, "make")) &&
727                     strcmp(cp, "make") == 0)
728                         return;
729         }
730 #endif
731         buf = bmake_malloc(len = strlen(line) + strlen(argv0) + 2);
732         (void)snprintf(buf, len, "%s %s", argv0, line);
733         free(p1);
734
735         argv = brk_string(buf, &argc, TRUE, &args);
736         if (argv == NULL) {
737                 Error("Unterminated quoted string [%s]", buf);
738                 free(buf);
739                 return;
740         }
741         free(buf);
742         MainParseArgs(argc, argv);
743
744         free(args);
745         free(argv);
746 }
747
748 Boolean
749 Main_SetObjdir(const char *fmt, ...)
750 {
751         struct stat sb;
752         char *path;
753         char buf[MAXPATHLEN + 1];
754         Boolean rc = FALSE;
755         va_list ap;
756
757         va_start(ap, fmt);
758         vsnprintf(path = buf, MAXPATHLEN, fmt, ap);
759         va_end(ap);
760
761         if (path[0] != '/') {
762                 char buf2[MAXPATHLEN + 1];
763                 
764                 snprintf(buf2, MAXPATHLEN, "%s/%s", curdir, path);
765                 path = buf2;
766         }
767
768         /* look for the directory and try to chdir there */
769         if (stat(path, &sb) == 0 && S_ISDIR(sb.st_mode)) {
770                 if (chdir(path)) {
771                         (void)fprintf(stderr, "make warning: %s: %s.\n",
772                                       path, strerror(errno));
773                 } else {
774                         strncpy(objdir, path, MAXPATHLEN);
775                         Var_Set(".OBJDIR", objdir, VAR_GLOBAL, 0);
776                         setenv("PWD", objdir, 1);
777                         Dir_InitDot();
778                         purge_cached_realpaths();
779                         rc = TRUE;
780                         if (enterFlag && strcmp(objdir, curdir) != 0)
781                                 enterFlagObj = TRUE;
782                 }
783         }
784
785         return rc;
786 }
787
788 static Boolean
789 Main_SetVarObjdir(const char *var, const char *suffix)
790 {
791         char *p, *path, *xpath;
792
793         if ((path = Var_Value(var, VAR_CMD, &p)) == NULL)
794                 return FALSE;
795
796         /* expand variable substitutions */
797         if (strchr(path, '$') != 0)
798                 xpath = Var_Subst(NULL, path, VAR_GLOBAL, VARF_WANTRES);
799         else
800                 xpath = path;
801
802         (void)Main_SetObjdir("%s%s", xpath, suffix);
803
804         if (xpath != path)
805                 free(xpath);
806         free(p);
807         return TRUE;
808 }
809
810 /*-
811  * ReadAllMakefiles --
812  *      wrapper around ReadMakefile() to read all.
813  *
814  * Results:
815  *      TRUE if ok, FALSE on error
816  */
817 static int
818 ReadAllMakefiles(const void *p, const void *q)
819 {
820         return (ReadMakefile(p, q) == 0);
821 }
822
823 int
824 str2Lst_Append(Lst lp, char *str, const char *sep)
825 {
826     char *cp;
827     int n;
828
829     if (!sep)
830         sep = " \t";
831
832     for (n = 0, cp = strtok(str, sep); cp; cp = strtok(NULL, sep)) {
833         (void)Lst_AtEnd(lp, cp);
834         n++;
835     }
836     return (n);
837 }
838
839 #ifdef SIGINFO
840 /*ARGSUSED*/
841 static void
842 siginfo(int signo MAKE_ATTR_UNUSED)
843 {
844         char dir[MAXPATHLEN];
845         char str[2 * MAXPATHLEN];
846         int len;
847         if (getcwd(dir, sizeof(dir)) == NULL)
848                 return;
849         len = snprintf(str, sizeof(str), "%s: Working in: %s\n", progname, dir);
850         if (len > 0)
851                 (void)write(STDERR_FILENO, str, (size_t)len);
852 }
853 #endif
854
855 /*
856  * Allow makefiles some control over the mode we run in.
857  */
858 void
859 MakeMode(const char *mode)
860 {
861     char *mp = NULL;
862
863     if (!mode)
864         mode = mp = Var_Subst(NULL, "${" MAKE_MODE ":tl}",
865                               VAR_GLOBAL, VARF_WANTRES);
866
867     if (mode && *mode) {
868         if (strstr(mode, "compat")) {
869             compatMake = TRUE;
870             forceJobs = FALSE;
871         }
872 #if USE_META
873         if (strstr(mode, "meta"))
874             meta_mode_init(mode);
875 #endif
876     }
877
878     free(mp);
879 }
880
881 /*-
882  * main --
883  *      The main function, for obvious reasons. Initializes variables
884  *      and a few modules, then parses the arguments give it in the
885  *      environment and on the command line. Reads the system makefile
886  *      followed by either Makefile, makefile or the file given by the
887  *      -f argument. Sets the .MAKEFLAGS PMake variable based on all the
888  *      flags it has received by then uses either the Make or the Compat
889  *      module to create the initial list of targets.
890  *
891  * Results:
892  *      If -q was given, exits -1 if anything was out-of-date. Else it exits
893  *      0.
894  *
895  * Side Effects:
896  *      The program exits when done. Targets are created. etc. etc. etc.
897  */
898 int
899 main(int argc, char **argv)
900 {
901         Lst targs;      /* target nodes to create -- passed to Make_Init */
902         Boolean outOfDate = FALSE;      /* FALSE if all targets up to date */
903         struct stat sb, sa;
904         char *p1, *path;
905         char mdpath[MAXPATHLEN];
906 #ifdef FORCE_MACHINE
907         const char *machine = FORCE_MACHINE;
908 #else
909         const char *machine = getenv("MACHINE");
910 #endif
911         const char *machine_arch = getenv("MACHINE_ARCH");
912         char *syspath = getenv("MAKESYSPATH");
913         Lst sysMkPath;                  /* Path of sys.mk */
914         char *cp = NULL, *start;
915                                         /* avoid faults on read-only strings */
916         static char defsyspath[] = _PATH_DEFSYSPATH;
917         char found_path[MAXPATHLEN + 1];        /* for searching for sys.mk */
918         struct timeval rightnow;                /* to initialize random seed */
919         struct utsname utsname;
920
921         /* default to writing debug to stderr */
922         debug_file = stderr;
923
924 #ifdef SIGINFO
925         (void)bmake_signal(SIGINFO, siginfo);
926 #endif
927         /*
928          * Set the seed to produce a different random sequence
929          * on each program execution.
930          */
931         gettimeofday(&rightnow, NULL);
932         srandom(rightnow.tv_sec + rightnow.tv_usec);
933         
934         if ((progname = strrchr(argv[0], '/')) != NULL)
935                 progname++;
936         else
937                 progname = argv[0];
938 #if defined(MAKE_NATIVE) || (defined(HAVE_SETRLIMIT) && defined(RLIMIT_NOFILE))
939         /*
940          * get rid of resource limit on file descriptors
941          */
942         {
943                 struct rlimit rl;
944                 if (getrlimit(RLIMIT_NOFILE, &rl) != -1 &&
945                     rl.rlim_cur != rl.rlim_max) {
946                         rl.rlim_cur = rl.rlim_max;
947                         (void)setrlimit(RLIMIT_NOFILE, &rl);
948                 }
949         }
950 #endif
951
952         if (uname(&utsname) == -1) {
953             (void)fprintf(stderr, "%s: uname failed (%s).\n", progname,
954                 strerror(errno));
955             exit(2);
956         }
957
958         /*
959          * Get the name of this type of MACHINE from utsname
960          * so we can share an executable for similar machines.
961          * (i.e. m68k: amiga hp300, mac68k, sun3, ...)
962          *
963          * Note that both MACHINE and MACHINE_ARCH are decided at
964          * run-time.
965          */
966         if (!machine) {
967 #ifdef MAKE_NATIVE
968             machine = utsname.machine;
969 #else
970 #ifdef MAKE_MACHINE
971             machine = MAKE_MACHINE;
972 #else
973             machine = "unknown";
974 #endif
975 #endif
976         }
977
978         if (!machine_arch) {
979 #if defined(MAKE_NATIVE) && defined(HAVE_SYSCTL) && defined(CTL_HW) && defined(HW_MACHINE_ARCH)
980             static char machine_arch_buf[sizeof(utsname.machine)];
981             int mib[2] = { CTL_HW, HW_MACHINE_ARCH };
982             size_t len = sizeof(machine_arch_buf);
983                 
984             if (sysctl(mib, __arraycount(mib), machine_arch_buf,
985                     &len, NULL, 0) < 0) {
986                 (void)fprintf(stderr, "%s: sysctl failed (%s).\n", progname,
987                     strerror(errno));
988                 exit(2);
989             }
990
991             machine_arch = machine_arch_buf;
992 #else
993 #ifndef MACHINE_ARCH
994 #ifdef MAKE_MACHINE_ARCH
995             machine_arch = MAKE_MACHINE_ARCH;
996 #else
997             machine_arch = "unknown";
998 #endif
999 #else
1000             machine_arch = MACHINE_ARCH;
1001 #endif
1002 #endif
1003         }
1004
1005         myPid = getpid();               /* remember this for vFork() */
1006
1007         /*
1008          * Just in case MAKEOBJDIR wants us to do something tricky.
1009          */
1010         Var_Init();             /* Initialize the lists of variables for
1011                                  * parsing arguments */
1012         Var_Set(".MAKE.OS", utsname.sysname, VAR_GLOBAL, 0);
1013         Var_Set("MACHINE", machine, VAR_GLOBAL, 0);
1014         Var_Set("MACHINE_ARCH", machine_arch, VAR_GLOBAL, 0);
1015 #ifdef MAKE_VERSION
1016         Var_Set("MAKE_VERSION", MAKE_VERSION, VAR_GLOBAL, 0);
1017 #endif
1018         Var_Set(".newline", "\n", VAR_GLOBAL, 0); /* handy for :@ loops */
1019         /*
1020          * This is the traditional preference for makefiles.
1021          */
1022 #ifndef MAKEFILE_PREFERENCE_LIST
1023 # define MAKEFILE_PREFERENCE_LIST "makefile Makefile"
1024 #endif
1025         Var_Set(MAKEFILE_PREFERENCE, MAKEFILE_PREFERENCE_LIST,
1026                 VAR_GLOBAL, 0);
1027         Var_Set(MAKE_DEPENDFILE, ".depend", VAR_GLOBAL, 0);
1028
1029         create = Lst_Init(FALSE);
1030         makefiles = Lst_Init(FALSE);
1031         printVars = FALSE;
1032         debugVflag = FALSE;
1033         variables = Lst_Init(FALSE);
1034         beSilent = FALSE;               /* Print commands as executed */
1035         ignoreErrors = FALSE;           /* Pay attention to non-zero returns */
1036         noExecute = FALSE;              /* Execute all commands */
1037         noRecursiveExecute = FALSE;     /* Execute all .MAKE targets */
1038         keepgoing = FALSE;              /* Stop on error */
1039         allPrecious = FALSE;            /* Remove targets when interrupted */
1040         deleteOnError = FALSE;          /* Historical default behavior */
1041         queryFlag = FALSE;              /* This is not just a check-run */
1042         noBuiltins = FALSE;             /* Read the built-in rules */
1043         touchFlag = FALSE;              /* Actually update targets */
1044         debug = 0;                      /* No debug verbosity, please. */
1045         jobsRunning = FALSE;
1046
1047         maxJobs = DEFMAXLOCAL;          /* Set default local max concurrency */
1048         maxJobTokens = maxJobs;
1049         compatMake = FALSE;             /* No compat mode */
1050         ignorePWD = FALSE;
1051
1052         /*
1053          * Initialize the parsing, directory and variable modules to prepare
1054          * for the reading of inclusion paths and variable settings on the
1055          * command line
1056          */
1057
1058         /*
1059          * Initialize various variables.
1060          *      MAKE also gets this name, for compatibility
1061          *      .MAKEFLAGS gets set to the empty string just in case.
1062          *      MFLAGS also gets initialized empty, for compatibility.
1063          */
1064         Parse_Init();
1065         if (argv[0][0] == '/' || strchr(argv[0], '/') == NULL) {
1066             /*
1067              * Leave alone if it is an absolute path, or if it does
1068              * not contain a '/' in which case we need to find it in
1069              * the path, like execvp(3) and the shells do.
1070              */
1071             p1 = argv[0];
1072         } else {
1073             /*
1074              * A relative path, canonicalize it.
1075              */
1076             p1 = cached_realpath(argv[0], mdpath);
1077             if (!p1 || *p1 != '/' || stat(p1, &sb) < 0) {
1078                 p1 = argv[0];           /* realpath failed */
1079             }
1080         }
1081         Var_Set("MAKE", p1, VAR_GLOBAL, 0);
1082         Var_Set(".MAKE", p1, VAR_GLOBAL, 0);
1083         Var_Set(MAKEFLAGS, "", VAR_GLOBAL, 0);
1084         Var_Set(MAKEOVERRIDES, "", VAR_GLOBAL, 0);
1085         Var_Set("MFLAGS", "", VAR_GLOBAL, 0);
1086         Var_Set(".ALLTARGETS", "", VAR_GLOBAL, 0);
1087         /* some makefiles need to know this */
1088         Var_Set(MAKE_LEVEL ".ENV", MAKE_LEVEL_ENV, VAR_CMD, 0);
1089
1090         /*
1091          * Set some other useful macros
1092          */
1093         {
1094             char tmp[64], *ep;
1095
1096             makelevel = ((ep = getenv(MAKE_LEVEL_ENV)) && *ep) ? atoi(ep) : 0;
1097             if (makelevel < 0)
1098                 makelevel = 0;
1099             snprintf(tmp, sizeof(tmp), "%d", makelevel);
1100             Var_Set(MAKE_LEVEL, tmp, VAR_GLOBAL, 0);
1101             snprintf(tmp, sizeof(tmp), "%u", myPid);
1102             Var_Set(".MAKE.PID", tmp, VAR_GLOBAL, 0);
1103             snprintf(tmp, sizeof(tmp), "%u", getppid());
1104             Var_Set(".MAKE.PPID", tmp, VAR_GLOBAL, 0);
1105         }
1106         if (makelevel > 0) {
1107                 char pn[1024];
1108                 snprintf(pn, sizeof(pn), "%s[%d]", progname, makelevel);
1109                 progname = bmake_strdup(pn);
1110         }
1111
1112 #ifdef USE_META
1113         meta_init();
1114 #endif
1115         Dir_Init(NULL);         /* Dir_* safe to call from MainParseArgs */
1116
1117         /*
1118          * First snag any flags out of the MAKE environment variable.
1119          * (Note this is *not* MAKEFLAGS since /bin/make uses that and it's
1120          * in a different format).
1121          */
1122 #ifdef POSIX
1123         p1 = explode(getenv("MAKEFLAGS"));
1124         Main_ParseArgLine(p1);
1125         free(p1);
1126 #else
1127         Main_ParseArgLine(getenv("MAKE"));
1128 #endif
1129
1130         /*
1131          * Find where we are (now).
1132          * We take care of PWD for the automounter below...
1133          */
1134         if (getcwd(curdir, MAXPATHLEN) == NULL) {
1135                 (void)fprintf(stderr, "%s: getcwd: %s.\n",
1136                     progname, strerror(errno));
1137                 exit(2);
1138         }
1139
1140         MainParseArgs(argc, argv);
1141
1142         if (enterFlag)
1143                 printf("%s: Entering directory `%s'\n", progname, curdir);
1144
1145         /*
1146          * Verify that cwd is sane.
1147          */
1148         if (stat(curdir, &sa) == -1) {
1149             (void)fprintf(stderr, "%s: %s: %s.\n",
1150                  progname, curdir, strerror(errno));
1151             exit(2);
1152         }
1153
1154         /*
1155          * All this code is so that we know where we are when we start up
1156          * on a different machine with pmake.
1157          * Overriding getcwd() with $PWD totally breaks MAKEOBJDIRPREFIX
1158          * since the value of curdir can vary depending on how we got
1159          * here.  Ie sitting at a shell prompt (shell that provides $PWD)
1160          * or via subdir.mk in which case its likely a shell which does
1161          * not provide it.
1162          * So, to stop it breaking this case only, we ignore PWD if
1163          * MAKEOBJDIRPREFIX is set or MAKEOBJDIR contains a transform.
1164          */
1165 #ifndef NO_PWD_OVERRIDE
1166         if (!ignorePWD) {
1167                 char *pwd, *ptmp1 = NULL, *ptmp2 = NULL;
1168
1169                 if ((pwd = getenv("PWD")) != NULL &&
1170                     Var_Value("MAKEOBJDIRPREFIX", VAR_CMD, &ptmp1) == NULL) {
1171                         const char *makeobjdir = Var_Value("MAKEOBJDIR",
1172                             VAR_CMD, &ptmp2);
1173
1174                         if (makeobjdir == NULL || !strchr(makeobjdir, '$')) {
1175                                 if (stat(pwd, &sb) == 0 &&
1176                                     sa.st_ino == sb.st_ino &&
1177                                     sa.st_dev == sb.st_dev)
1178                                         (void)strncpy(curdir, pwd, MAXPATHLEN);
1179                         }
1180                 }
1181                 free(ptmp1);
1182                 free(ptmp2);
1183         }
1184 #endif
1185         Var_Set(".CURDIR", curdir, VAR_GLOBAL, 0);
1186
1187         /*
1188          * Find the .OBJDIR.  If MAKEOBJDIRPREFIX, or failing that,
1189          * MAKEOBJDIR is set in the environment, try only that value
1190          * and fall back to .CURDIR if it does not exist.
1191          *
1192          * Otherwise, try _PATH_OBJDIR.MACHINE-MACHINE_ARCH, _PATH_OBJDIR.MACHINE,
1193          * and * finally _PATH_OBJDIRPREFIX`pwd`, in that order.  If none
1194          * of these paths exist, just use .CURDIR.
1195          */
1196         Dir_Init(curdir);
1197         (void)Main_SetObjdir("%s", curdir);
1198
1199         if (!Main_SetVarObjdir("MAKEOBJDIRPREFIX", curdir) &&
1200             !Main_SetVarObjdir("MAKEOBJDIR", "") &&
1201             !Main_SetObjdir("%s.%s-%s", _PATH_OBJDIR, machine, machine_arch) &&
1202             !Main_SetObjdir("%s.%s", _PATH_OBJDIR, machine) &&
1203             !Main_SetObjdir("%s", _PATH_OBJDIR))
1204                 (void)Main_SetObjdir("%s%s", _PATH_OBJDIRPREFIX, curdir);
1205
1206         /*
1207          * Initialize archive, target and suffix modules in preparation for
1208          * parsing the makefile(s)
1209          */
1210         Arch_Init();
1211         Targ_Init();
1212         Suff_Init();
1213         Trace_Init(tracefile);
1214
1215         DEFAULT = NULL;
1216         (void)time(&now);
1217
1218         Trace_Log(MAKESTART, NULL);
1219         
1220         /*
1221          * Set up the .TARGETS variable to contain the list of targets to be
1222          * created. If none specified, make the variable empty -- the parser
1223          * will fill the thing in with the default or .MAIN target.
1224          */
1225         if (!Lst_IsEmpty(create)) {
1226                 LstNode ln;
1227
1228                 for (ln = Lst_First(create); ln != NULL;
1229                     ln = Lst_Succ(ln)) {
1230                         char *name = (char *)Lst_Datum(ln);
1231
1232                         Var_Append(".TARGETS", name, VAR_GLOBAL);
1233                 }
1234         } else
1235                 Var_Set(".TARGETS", "", VAR_GLOBAL, 0);
1236
1237
1238         /*
1239          * If no user-supplied system path was given (through the -m option)
1240          * add the directories from the DEFSYSPATH (more than one may be given
1241          * as dir1:...:dirn) to the system include path.
1242          */
1243         if (syspath == NULL || *syspath == '\0')
1244                 syspath = defsyspath;
1245         else
1246                 syspath = bmake_strdup(syspath);
1247
1248         for (start = syspath; *start != '\0'; start = cp) {
1249                 for (cp = start; *cp != '\0' && *cp != ':'; cp++)
1250                         continue;
1251                 if (*cp == ':') {
1252                         *cp++ = '\0';
1253                 }
1254                 /* look for magic parent directory search string */
1255                 if (strncmp(".../", start, 4) != 0) {
1256                         (void)Dir_AddDir(defIncPath, start);
1257                 } else {
1258                         if (Dir_FindHereOrAbove(curdir, start+4, 
1259                             found_path, sizeof(found_path))) {
1260                                 (void)Dir_AddDir(defIncPath, found_path);
1261                         }
1262                 }
1263         }
1264         if (syspath != defsyspath)
1265                 free(syspath);
1266
1267         /*
1268          * Read in the built-in rules first, followed by the specified
1269          * makefile, if it was (makefile != NULL), or the default
1270          * makefile and Makefile, in that order, if it wasn't.
1271          */
1272         if (!noBuiltins) {
1273                 LstNode ln;
1274
1275                 sysMkPath = Lst_Init(FALSE);
1276                 Dir_Expand(_PATH_DEFSYSMK,
1277                            Lst_IsEmpty(sysIncPath) ? defIncPath : sysIncPath,
1278                            sysMkPath);
1279                 if (Lst_IsEmpty(sysMkPath))
1280                         Fatal("%s: no system rules (%s).", progname,
1281                             _PATH_DEFSYSMK);
1282                 ln = Lst_Find(sysMkPath, NULL, ReadMakefile);
1283                 if (ln == NULL)
1284                         Fatal("%s: cannot open %s.", progname,
1285                             (char *)Lst_Datum(ln));
1286         }
1287
1288         if (!Lst_IsEmpty(makefiles)) {
1289                 LstNode ln;
1290
1291                 ln = Lst_Find(makefiles, NULL, ReadAllMakefiles);
1292                 if (ln != NULL)
1293                         Fatal("%s: cannot open %s.", progname, 
1294                             (char *)Lst_Datum(ln));
1295         } else {
1296             p1 = Var_Subst(NULL, "${" MAKEFILE_PREFERENCE "}",
1297                 VAR_CMD, VARF_WANTRES);
1298             if (p1) {
1299                 (void)str2Lst_Append(makefiles, p1, NULL);
1300                 (void)Lst_Find(makefiles, NULL, ReadMakefile);
1301                 free(p1);
1302             }
1303         }
1304
1305         /* In particular suppress .depend for '-r -V .OBJDIR -f /dev/null' */
1306         if (!noBuiltins || !printVars) {
1307             makeDependfile = Var_Subst(NULL, "${.MAKE.DEPENDFILE:T}",
1308                 VAR_CMD, VARF_WANTRES);
1309             doing_depend = TRUE;
1310             (void)ReadMakefile(makeDependfile, NULL);
1311             doing_depend = FALSE;
1312         }
1313
1314         if (enterFlagObj)
1315                 printf("%s: Entering directory `%s'\n", progname, objdir);
1316         
1317         MakeMode(NULL);
1318
1319         Var_Append("MFLAGS", Var_Value(MAKEFLAGS, VAR_GLOBAL, &p1), VAR_GLOBAL);
1320         free(p1);
1321
1322         if (!forceJobs && !compatMake &&
1323             Var_Exists(".MAKE.JOBS", VAR_GLOBAL)) {
1324             char *value;
1325             int n;
1326
1327             value = Var_Subst(NULL, "${.MAKE.JOBS}", VAR_GLOBAL, VARF_WANTRES);
1328             n = strtol(value, NULL, 0);
1329             if (n < 1) {
1330                 (void)fprintf(stderr, "%s: illegal value for .MAKE.JOBS -- must be positive integer!\n",
1331                     progname);
1332                 exit(1);
1333             }
1334             if (n != maxJobs) {
1335                 Var_Append(MAKEFLAGS, "-j", VAR_GLOBAL);
1336                 Var_Append(MAKEFLAGS, value, VAR_GLOBAL);
1337             }
1338             maxJobs = n;
1339             maxJobTokens = maxJobs;
1340             forceJobs = TRUE;
1341             free(value);
1342         }
1343
1344         /*
1345          * Be compatible if user did not specify -j and did not explicitly
1346          * turned compatibility on
1347          */
1348         if (!compatMake && !forceJobs) {
1349             compatMake = TRUE;
1350         }
1351
1352         if (!compatMake)
1353             Job_ServerStart(maxJobTokens, jp_0, jp_1);
1354         if (DEBUG(JOB))
1355             fprintf(debug_file, "job_pipe %d %d, maxjobs %d, tokens %d, compat %d\n",
1356                 jp_0, jp_1, maxJobs, maxJobTokens, compatMake);
1357
1358         if (!printVars)
1359             Main_ExportMAKEFLAGS(TRUE); /* initial export */
1360         
1361         /*
1362          * For compatibility, look at the directories in the VPATH variable
1363          * and add them to the search path, if the variable is defined. The
1364          * variable's value is in the same format as the PATH envariable, i.e.
1365          * <directory>:<directory>:<directory>...
1366          */
1367         if (Var_Exists("VPATH", VAR_CMD)) {
1368                 char *vpath, savec;
1369                 /*
1370                  * GCC stores string constants in read-only memory, but
1371                  * Var_Subst will want to write this thing, so store it
1372                  * in an array
1373                  */
1374                 static char VPATH[] = "${VPATH}";
1375
1376                 vpath = Var_Subst(NULL, VPATH, VAR_CMD, VARF_WANTRES);
1377                 path = vpath;
1378                 do {
1379                         /* skip to end of directory */
1380                         for (cp = path; *cp != ':' && *cp != '\0'; cp++)
1381                                 continue;
1382                         /* Save terminator character so know when to stop */
1383                         savec = *cp;
1384                         *cp = '\0';
1385                         /* Add directory to search path */
1386                         (void)Dir_AddDir(dirSearchPath, path);
1387                         *cp = savec;
1388                         path = cp + 1;
1389                 } while (savec == ':');
1390                 free(vpath);
1391         }
1392
1393         /*
1394          * Now that all search paths have been read for suffixes et al, it's
1395          * time to add the default search path to their lists...
1396          */
1397         Suff_DoPaths();
1398
1399         /*
1400          * Propagate attributes through :: dependency lists.
1401          */
1402         Targ_Propagate();
1403
1404         /* print the initial graph, if the user requested it */
1405         if (DEBUG(GRAPH1))
1406                 Targ_PrintGraph(1);
1407
1408         /* print the values of any variables requested by the user */
1409         if (printVars) {
1410                 LstNode ln;
1411                 Boolean expandVars;
1412
1413                 if (debugVflag)
1414                         expandVars = FALSE;
1415                 else
1416                         expandVars = getBoolean(".MAKE.EXPAND_VARIABLES", FALSE);
1417                 for (ln = Lst_First(variables); ln != NULL;
1418                     ln = Lst_Succ(ln)) {
1419                         char *var = (char *)Lst_Datum(ln);
1420                         char *value;
1421                         
1422                         if (strchr(var, '$')) {
1423                             value = p1 = Var_Subst(NULL, var, VAR_GLOBAL,
1424                                                    VARF_WANTRES);
1425                         } else if (expandVars) {
1426                                 char tmp[128];
1427                                                                 
1428                                 if (snprintf(tmp, sizeof(tmp), "${%s}", var) >= (int)(sizeof(tmp)))
1429                                         Fatal("%s: variable name too big: %s",
1430                                               progname, var);
1431                                 value = p1 = Var_Subst(NULL, tmp, VAR_GLOBAL,
1432                                                        VARF_WANTRES);
1433                         } else {
1434                                 value = Var_Value(var, VAR_GLOBAL, &p1);
1435                         }
1436                         printf("%s\n", value ? value : "");
1437                         free(p1);
1438                 }
1439         } else {
1440                 /*
1441                  * Have now read the entire graph and need to make a list of
1442                  * targets to create. If none was given on the command line,
1443                  * we consult the parsing module to find the main target(s)
1444                  * to create.
1445                  */
1446                 if (Lst_IsEmpty(create))
1447                         targs = Parse_MainName();
1448                 else
1449                         targs = Targ_FindList(create, TARG_CREATE);
1450
1451                 if (!compatMake) {
1452                         /*
1453                          * Initialize job module before traversing the graph
1454                          * now that any .BEGIN and .END targets have been read.
1455                          * This is done only if the -q flag wasn't given
1456                          * (to prevent the .BEGIN from being executed should
1457                          * it exist).
1458                          */
1459                         if (!queryFlag) {
1460                                 Job_Init();
1461                                 jobsRunning = TRUE;
1462                         }
1463
1464                         /* Traverse the graph, checking on all the targets */
1465                         outOfDate = Make_Run(targs);
1466                 } else {
1467                         /*
1468                          * Compat_Init will take care of creating all the
1469                          * targets as well as initializing the module.
1470                          */
1471                         Compat_Run(targs);
1472                 }
1473         }
1474
1475 #ifdef CLEANUP
1476         Lst_Destroy(targs, NULL);
1477         Lst_Destroy(variables, NULL);
1478         Lst_Destroy(makefiles, NULL);
1479         Lst_Destroy(create, (FreeProc *)free);
1480 #endif
1481
1482         /* print the graph now it's been processed if the user requested it */
1483         if (DEBUG(GRAPH2))
1484                 Targ_PrintGraph(2);
1485
1486         Trace_Log(MAKEEND, 0);
1487
1488         if (enterFlagObj)
1489                 printf("%s: Leaving directory `%s'\n", progname, objdir);
1490         if (enterFlag)
1491                 printf("%s: Leaving directory `%s'\n", progname, curdir);
1492
1493 #ifdef USE_META
1494         meta_finish();
1495 #endif
1496         Suff_End();
1497         Targ_End();
1498         Arch_End();
1499         Var_End();
1500         Parse_End();
1501         Dir_End();
1502         Job_End();
1503         Trace_End();
1504
1505         return outOfDate ? 1 : 0;
1506 }
1507
1508 /*-
1509  * ReadMakefile  --
1510  *      Open and parse the given makefile.
1511  *
1512  * Results:
1513  *      0 if ok. -1 if couldn't open file.
1514  *
1515  * Side Effects:
1516  *      lots
1517  */
1518 static int
1519 ReadMakefile(const void *p, const void *q MAKE_ATTR_UNUSED)
1520 {
1521         const char *fname = p;          /* makefile to read */
1522         int fd;
1523         size_t len = MAXPATHLEN;
1524         char *name, *path = bmake_malloc(len);
1525
1526         if (!strcmp(fname, "-")) {
1527                 Parse_File(NULL /*stdin*/, -1);
1528                 Var_Set("MAKEFILE", "", VAR_INTERNAL, 0);
1529         } else {
1530                 /* if we've chdir'd, rebuild the path name */
1531                 if (strcmp(curdir, objdir) && *fname != '/') {
1532                         size_t plen = strlen(curdir) + strlen(fname) + 2;
1533                         if (len < plen)
1534                                 path = bmake_realloc(path, len = 2 * plen);
1535                         
1536                         (void)snprintf(path, len, "%s/%s", curdir, fname);
1537                         fd = open(path, O_RDONLY);
1538                         if (fd != -1) {
1539                                 fname = path;
1540                                 goto found;
1541                         }
1542                         
1543                         /* If curdir failed, try objdir (ala .depend) */
1544                         plen = strlen(objdir) + strlen(fname) + 2;
1545                         if (len < plen)
1546                                 path = bmake_realloc(path, len = 2 * plen);
1547                         (void)snprintf(path, len, "%s/%s", objdir, fname);
1548                         fd = open(path, O_RDONLY);
1549                         if (fd != -1) {
1550                                 fname = path;
1551                                 goto found;
1552                         }
1553                 } else {
1554                         fd = open(fname, O_RDONLY);
1555                         if (fd != -1)
1556                                 goto found;
1557                 }
1558                 /* look in -I and system include directories. */
1559                 name = Dir_FindFile(fname, parseIncPath);
1560                 if (!name)
1561                         name = Dir_FindFile(fname,
1562                                 Lst_IsEmpty(sysIncPath) ? defIncPath : sysIncPath);
1563                 if (!name || (fd = open(name, O_RDONLY)) == -1) {
1564                         free(name);
1565                         free(path);
1566                         return(-1);
1567                 }
1568                 fname = name;
1569                 /*
1570                  * set the MAKEFILE variable desired by System V fans -- the
1571                  * placement of the setting here means it gets set to the last
1572                  * makefile specified, as it is set by SysV make.
1573                  */
1574 found:
1575                 if (!doing_depend)
1576                         Var_Set("MAKEFILE", fname, VAR_INTERNAL, 0);
1577                 Parse_File(fname, fd);
1578         }
1579         free(path);
1580         return(0);
1581 }
1582
1583
1584
1585 /*-
1586  * Cmd_Exec --
1587  *      Execute the command in cmd, and return the output of that command
1588  *      in a string.
1589  *
1590  * Results:
1591  *      A string containing the output of the command, or the empty string
1592  *      If errnum is not NULL, it contains the reason for the command failure
1593  *
1594  * Side Effects:
1595  *      The string must be freed by the caller.
1596  */
1597 char *
1598 Cmd_Exec(const char *cmd, const char **errnum)
1599 {
1600     const char  *args[4];       /* Args for invoking the shell */
1601     int         fds[2];         /* Pipe streams */
1602     int         cpid;           /* Child PID */
1603     int         pid;            /* PID from wait() */
1604     char        *res;           /* result */
1605     WAIT_T      status;         /* command exit status */
1606     Buffer      buf;            /* buffer to store the result */
1607     char        *cp;
1608     int         cc;             /* bytes read, or -1 */
1609     int         savederr;       /* saved errno */
1610
1611
1612     *errnum = NULL;
1613
1614     if (!shellName)
1615         Shell_Init();
1616     /*
1617      * Set up arguments for shell
1618      */
1619     args[0] = shellName;
1620     args[1] = "-c";
1621     args[2] = cmd;
1622     args[3] = NULL;
1623
1624     /*
1625      * Open a pipe for fetching its output
1626      */
1627     if (pipe(fds) == -1) {
1628         *errnum = "Couldn't create pipe for \"%s\"";
1629         goto bad;
1630     }
1631
1632     /*
1633      * Fork
1634      */
1635     switch (cpid = vFork()) {
1636     case 0:
1637         /*
1638          * Close input side of pipe
1639          */
1640         (void)close(fds[0]);
1641
1642         /*
1643          * Duplicate the output stream to the shell's output, then
1644          * shut the extra thing down. Note we don't fetch the error
1645          * stream...why not? Why?
1646          */
1647         (void)dup2(fds[1], 1);
1648         (void)close(fds[1]);
1649
1650         Var_ExportVars();
1651
1652         (void)execv(shellPath, UNCONST(args));
1653         _exit(1);
1654         /*NOTREACHED*/
1655
1656     case -1:
1657         *errnum = "Couldn't exec \"%s\"";
1658         goto bad;
1659
1660     default:
1661         /*
1662          * No need for the writing half
1663          */
1664         (void)close(fds[1]);
1665
1666         savederr = 0;
1667         Buf_Init(&buf, 0);
1668
1669         do {
1670             char   result[BUFSIZ];
1671             cc = read(fds[0], result, sizeof(result));
1672             if (cc > 0)
1673                 Buf_AddBytes(&buf, cc, result);
1674         }
1675         while (cc > 0 || (cc == -1 && errno == EINTR));
1676         if (cc == -1)
1677             savederr = errno;
1678
1679         /*
1680          * Close the input side of the pipe.
1681          */
1682         (void)close(fds[0]);
1683
1684         /*
1685          * Wait for the process to exit.
1686          */
1687         while(((pid = waitpid(cpid, &status, 0)) != cpid) && (pid >= 0)) {
1688             JobReapChild(pid, status, FALSE);
1689             continue;
1690         }
1691         cc = Buf_Size(&buf);
1692         res = Buf_Destroy(&buf, FALSE);
1693
1694         if (savederr != 0)
1695             *errnum = "Couldn't read shell's output for \"%s\"";
1696
1697         if (WIFSIGNALED(status))
1698             *errnum = "\"%s\" exited on a signal";
1699         else if (WEXITSTATUS(status) != 0)
1700             *errnum = "\"%s\" returned non-zero status";
1701
1702         /*
1703          * Null-terminate the result, convert newlines to spaces and
1704          * install it in the variable.
1705          */
1706         res[cc] = '\0';
1707         cp = &res[cc];
1708
1709         if (cc > 0 && *--cp == '\n') {
1710             /*
1711              * A final newline is just stripped
1712              */
1713             *cp-- = '\0';
1714         }
1715         while (cp >= res) {
1716             if (*cp == '\n') {
1717                 *cp = ' ';
1718             }
1719             cp--;
1720         }
1721         break;
1722     }
1723     return res;
1724 bad:
1725     res = bmake_malloc(1);
1726     *res = '\0';
1727     return res;
1728 }
1729
1730 /*-
1731  * Error --
1732  *      Print an error message given its format.
1733  *
1734  * Results:
1735  *      None.
1736  *
1737  * Side Effects:
1738  *      The message is printed.
1739  */
1740 /* VARARGS */
1741 void
1742 Error(const char *fmt, ...)
1743 {
1744         va_list ap;
1745         FILE *err_file;
1746
1747         err_file = debug_file;
1748         if (err_file == stdout)
1749                 err_file = stderr;
1750         (void)fflush(stdout);
1751         for (;;) {
1752                 va_start(ap, fmt);
1753                 fprintf(err_file, "%s: ", progname);
1754                 (void)vfprintf(err_file, fmt, ap);
1755                 va_end(ap);
1756                 (void)fprintf(err_file, "\n");
1757                 (void)fflush(err_file);
1758                 if (err_file == stderr)
1759                         break;
1760                 err_file = stderr;
1761         }
1762 }
1763
1764 /*-
1765  * Fatal --
1766  *      Produce a Fatal error message. If jobs are running, waits for them
1767  *      to finish.
1768  *
1769  * Results:
1770  *      None
1771  *
1772  * Side Effects:
1773  *      The program exits
1774  */
1775 /* VARARGS */
1776 void
1777 Fatal(const char *fmt, ...)
1778 {
1779         va_list ap;
1780
1781         va_start(ap, fmt);
1782         if (jobsRunning)
1783                 Job_Wait();
1784
1785         (void)fflush(stdout);
1786         (void)vfprintf(stderr, fmt, ap);
1787         va_end(ap);
1788         (void)fprintf(stderr, "\n");
1789         (void)fflush(stderr);
1790
1791         PrintOnError(NULL, NULL);
1792
1793         if (DEBUG(GRAPH2) || DEBUG(GRAPH3))
1794                 Targ_PrintGraph(2);
1795         Trace_Log(MAKEERROR, 0);
1796         exit(2);                /* Not 1 so -q can distinguish error */
1797 }
1798
1799 /*
1800  * Punt --
1801  *      Major exception once jobs are being created. Kills all jobs, prints
1802  *      a message and exits.
1803  *
1804  * Results:
1805  *      None
1806  *
1807  * Side Effects:
1808  *      All children are killed indiscriminately and the program Lib_Exits
1809  */
1810 /* VARARGS */
1811 void
1812 Punt(const char *fmt, ...)
1813 {
1814         va_list ap;
1815
1816         va_start(ap, fmt);
1817         (void)fflush(stdout);
1818         (void)fprintf(stderr, "%s: ", progname);
1819         (void)vfprintf(stderr, fmt, ap);
1820         va_end(ap);
1821         (void)fprintf(stderr, "\n");
1822         (void)fflush(stderr);
1823
1824         PrintOnError(NULL, NULL);
1825
1826         DieHorribly();
1827 }
1828
1829 /*-
1830  * DieHorribly --
1831  *      Exit without giving a message.
1832  *
1833  * Results:
1834  *      None
1835  *
1836  * Side Effects:
1837  *      A big one...
1838  */
1839 void
1840 DieHorribly(void)
1841 {
1842         if (jobsRunning)
1843                 Job_AbortAll();
1844         if (DEBUG(GRAPH2))
1845                 Targ_PrintGraph(2);
1846         Trace_Log(MAKEERROR, 0);
1847         exit(2);                /* Not 1, so -q can distinguish error */
1848 }
1849
1850 /*
1851  * Finish --
1852  *      Called when aborting due to errors in child shell to signal
1853  *      abnormal exit.
1854  *
1855  * Results:
1856  *      None
1857  *
1858  * Side Effects:
1859  *      The program exits
1860  */
1861 void
1862 Finish(int errors)
1863                         /* number of errors encountered in Make_Make */
1864 {
1865         Fatal("%d error%s", errors, errors == 1 ? "" : "s");
1866 }
1867
1868 /*
1869  * eunlink --
1870  *      Remove a file carefully, avoiding directories.
1871  */
1872 int
1873 eunlink(const char *file)
1874 {
1875         struct stat st;
1876
1877         if (lstat(file, &st) == -1)
1878                 return -1;
1879
1880         if (S_ISDIR(st.st_mode)) {
1881                 errno = EISDIR;
1882                 return -1;
1883         }
1884         return unlink(file);
1885 }
1886
1887 /*
1888  * execError --
1889  *      Print why exec failed, avoiding stdio.
1890  */
1891 void
1892 execError(const char *af, const char *av)
1893 {
1894 #ifdef USE_IOVEC
1895         int i = 0;
1896         struct iovec iov[8];
1897 #define IOADD(s) \
1898         (void)(iov[i].iov_base = UNCONST(s), \
1899             iov[i].iov_len = strlen(iov[i].iov_base), \
1900             i++)
1901 #else
1902 #define IOADD(s) (void)write(2, s, strlen(s))
1903 #endif
1904
1905         IOADD(progname);
1906         IOADD(": ");
1907         IOADD(af);
1908         IOADD("(");
1909         IOADD(av);
1910         IOADD(") failed (");
1911         IOADD(strerror(errno));
1912         IOADD(")\n");
1913
1914 #ifdef USE_IOVEC
1915         while (writev(2, iov, 8) == -1 && errno == EAGAIN)
1916             continue;
1917 #endif
1918 }
1919
1920 /*
1921  * usage --
1922  *      exit with usage message
1923  */
1924 static void
1925 usage(void)
1926 {
1927         char *p;
1928         if ((p = strchr(progname, '[')) != NULL)
1929             *p = '\0';
1930
1931         (void)fprintf(stderr,
1932 "usage: %s [-BeikNnqrstWwX] \n\
1933             [-C directory] [-D variable] [-d flags] [-f makefile]\n\
1934             [-I directory] [-J private] [-j max_jobs] [-m directory] [-T file]\n\
1935             [-V variable] [variable=value] [target ...]\n", progname);
1936         exit(2);
1937 }
1938
1939 /*
1940  * realpath(3) can get expensive, cache results...
1941  */
1942 static GNode *cached_realpaths = NULL;
1943
1944 static GNode *
1945 get_cached_realpaths(void)
1946 {
1947
1948     if (!cached_realpaths) {
1949         cached_realpaths = Targ_NewGN("Realpath");
1950 #ifndef DEBUG_REALPATH_CACHE
1951         cached_realpaths->flags = INTERNAL;
1952 #endif
1953     }
1954
1955     return cached_realpaths;
1956 }
1957
1958 /* purge any relative paths */
1959 static void
1960 purge_cached_realpaths(void)
1961 {
1962     GNode *cache = get_cached_realpaths();
1963     Hash_Entry *he, *nhe;
1964     Hash_Search hs;
1965
1966     he = Hash_EnumFirst(&cache->context, &hs);
1967     while (he) {
1968         nhe = Hash_EnumNext(&hs);
1969         if (he->name[0] != '/') {
1970             if (DEBUG(DIR))
1971                 fprintf(stderr, "cached_realpath: purging %s\n", he->name);
1972             Hash_DeleteEntry(&cache->context, he);
1973         }
1974         he = nhe;
1975     }
1976 }
1977
1978 char *
1979 cached_realpath(const char *pathname, char *resolved)
1980 {
1981     GNode *cache;
1982     char *rp, *cp;
1983
1984     if (!pathname || !pathname[0])
1985         return NULL;
1986
1987     cache = get_cached_realpaths();
1988
1989     if ((rp = Var_Value(pathname, cache, &cp)) != NULL) {
1990         /* a hit */
1991         strlcpy(resolved, rp, MAXPATHLEN);
1992     } else if ((rp = realpath(pathname, resolved)) != NULL) {
1993         Var_Set(pathname, rp, cache, 0);
1994     }
1995     free(cp);
1996     return rp ? resolved : NULL;
1997 }
1998
1999 int
2000 PrintAddr(void *a, void *b)
2001 {
2002     printf("%lx ", (unsigned long) a);
2003     return b ? 0 : 0;
2004 }
2005
2006
2007 static int
2008 addErrorCMD(void *cmdp, void *gnp MAKE_ATTR_UNUSED)
2009 {
2010     if (cmdp == NULL)
2011         return 1;                       /* stop */
2012     Var_Append(".ERROR_CMD", cmdp, VAR_GLOBAL);
2013     return 0;
2014 }
2015
2016 void
2017 PrintOnError(GNode *gn, const char *s)
2018 {
2019     static GNode *en = NULL;
2020     char tmp[64];
2021     char *cp;
2022
2023     if (s)
2024         printf("%s", s);
2025         
2026     printf("\n%s: stopped in %s\n", progname, curdir);
2027
2028     if (en)
2029         return;                         /* we've been here! */
2030     if (gn) {
2031         /*
2032          * We can print this even if there is no .ERROR target.
2033          */
2034         Var_Set(".ERROR_TARGET", gn->name, VAR_GLOBAL, 0);
2035         Var_Delete(".ERROR_CMD", VAR_GLOBAL);
2036         Lst_ForEach(gn->commands, addErrorCMD, gn);
2037     }
2038     strncpy(tmp, "${MAKE_PRINT_VAR_ON_ERROR:@v@$v='${$v}'\n@}",
2039             sizeof(tmp) - 1);
2040     cp = Var_Subst(NULL, tmp, VAR_GLOBAL, VARF_WANTRES);
2041     if (cp) {
2042         if (*cp)
2043             printf("%s", cp);
2044         free(cp);
2045     }
2046     fflush(stdout);
2047
2048     /*
2049      * Finally, see if there is a .ERROR target, and run it if so.
2050      */
2051     en = Targ_FindNode(".ERROR", TARG_NOCREATE);
2052     if (en) {
2053         en->type |= OP_SPECIAL;
2054         Compat_Make(en, en);
2055     }
2056 }
2057
2058 void
2059 Main_ExportMAKEFLAGS(Boolean first)
2060 {
2061     static int once = 1;
2062     char tmp[64];
2063     char *s;
2064
2065     if (once != first)
2066         return;
2067     once = 0;
2068     
2069     strncpy(tmp, "${.MAKEFLAGS} ${.MAKEOVERRIDES:O:u:@v@$v=${$v:Q}@}",
2070             sizeof(tmp));
2071     s = Var_Subst(NULL, tmp, VAR_CMD, VARF_WANTRES);
2072     if (s && *s) {
2073 #ifdef POSIX
2074         setenv("MAKEFLAGS", s, 1);
2075 #else
2076         setenv("MAKE", s, 1);
2077 #endif
2078     }
2079 }
2080
2081 char *
2082 getTmpdir(void)
2083 {
2084     static char *tmpdir = NULL;
2085
2086     if (!tmpdir) {
2087         struct stat st;
2088
2089         /*
2090          * Honor $TMPDIR but only if it is valid.
2091          * Ensure it ends with /.
2092          */
2093         tmpdir = Var_Subst(NULL, "${TMPDIR:tA:U" _PATH_TMP "}/", VAR_GLOBAL,
2094                            VARF_WANTRES);
2095         if (stat(tmpdir, &st) < 0 || !S_ISDIR(st.st_mode)) {
2096             free(tmpdir);
2097             tmpdir = bmake_strdup(_PATH_TMP);
2098         }
2099     }
2100     return tmpdir;
2101 }
2102
2103 /*
2104  * Create and open a temp file using "pattern".
2105  * If "fnamep" is provided set it to a copy of the filename created.
2106  * Otherwise unlink the file once open.
2107  */
2108 int
2109 mkTempFile(const char *pattern, char **fnamep)
2110 {
2111     static char *tmpdir = NULL;
2112     char tfile[MAXPATHLEN];
2113     int fd;
2114     
2115     if (!pattern)
2116         pattern = TMPPAT;
2117     if (!tmpdir)
2118         tmpdir = getTmpdir();
2119     if (pattern[0] == '/') {
2120         snprintf(tfile, sizeof(tfile), "%s", pattern);
2121     } else {
2122         snprintf(tfile, sizeof(tfile), "%s%s", tmpdir, pattern);
2123     }
2124     if ((fd = mkstemp(tfile)) < 0)
2125         Punt("Could not create temporary file %s: %s", tfile, strerror(errno));
2126     if (fnamep) {
2127         *fnamep = bmake_strdup(tfile);
2128     } else {
2129         unlink(tfile);                  /* we just want the descriptor */
2130     }
2131     return fd;
2132 }
2133
2134 /*
2135  * Convert a string representation of a boolean.
2136  * Anything that looks like "No", "False", "Off", "0" etc,
2137  * is FALSE, otherwise TRUE.
2138  */
2139 Boolean
2140 s2Boolean(const char *s, Boolean bf)
2141 {
2142     if (s) {
2143         switch(*s) {
2144         case '\0':                      /* not set - the default wins */
2145             break;
2146         case '0':
2147         case 'F':
2148         case 'f':
2149         case 'N':
2150         case 'n':
2151             bf = FALSE;
2152             break;
2153         case 'O':
2154         case 'o':
2155             switch (s[1]) {
2156             case 'F':
2157             case 'f':
2158                 bf = FALSE;
2159                 break;
2160             default:
2161                 bf = TRUE;
2162                 break;
2163             }
2164             break;
2165         default:
2166             bf = TRUE;
2167             break;
2168         }
2169     }
2170     return (bf);
2171 }
2172
2173 /*
2174  * Return a Boolean based on setting of a knob.
2175  *
2176  * If the knob is not set, the supplied default is the return value.
2177  * If set, anything that looks or smells like "No", "False", "Off", "0" etc,
2178  * is FALSE, otherwise TRUE.
2179  */
2180 Boolean
2181 getBoolean(const char *name, Boolean bf)
2182 {
2183     char tmp[64];
2184     char *cp;
2185
2186     if (snprintf(tmp, sizeof(tmp), "${%s:U:tl}", name) < (int)(sizeof(tmp))) {
2187         cp = Var_Subst(NULL, tmp, VAR_GLOBAL, VARF_WANTRES);
2188
2189         if (cp) {
2190             bf = s2Boolean(cp, bf);
2191             free(cp);
2192         }
2193     }
2194     return (bf);
2195 }