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