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