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