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