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