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"	*/
114MAKE_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
125CmdOpts opts;
126time_t now;			/* Time at start of make */
127GNode *defaultNode;		/* .DEFAULT node */
128Boolean allPrecious;		/* .PRECIOUS given on line by itself */
129Boolean deleteOnError;		/* .DELETE_ON_ERROR: set */
130
131static int maxJobTokens;	/* -j argument */
132Boolean enterFlagObj;		/* -w and objdir != srcdir */
133
134static int jp_0 = -1, jp_1 = -1; /* ends of parent job pipe */
135Boolean doing_depend;		/* Set while reading .depend */
136static Boolean jobsRunning;	/* TRUE if the jobs might be running */
137static const char *tracefile;
138static int ReadMakefile(const char *);
139static void purge_relative_cached_realpaths(void);
140
141static Boolean ignorePWD;	/* if we use -C, PWD is meaningless */
142static char objdir[MAXPATHLEN + 1]; /* where we chdir'ed to */
143char curdir[MAXPATHLEN + 1];	/* Startup directory */
144const char *progname;
145char *makeDependfile;
146pid_t myPid;
147int makelevel;
148
149Boolean forceJobs = FALSE;
150static int main_errors = 0;
151static 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 */
157static char *
158explode(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 */
189MAKE_ATTR_DEAD static void
190usage(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
203static void
204MainParseArgDebugFile(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
245static void
246MainParseArgDebug(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
339debug_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 ".."? */
353static Boolean
354IsRelativePath(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
371static void
372MainParseArgChdir(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
394static void
395MainParseArgJobsInternal(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
421static void
422MainParseArgJobs(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
440static void
441MainParseArgSysInc(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
457static Boolean
458MainParseArg(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 */
588static void
589MainParseArgs(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
600rearg:
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;
673noarg:
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 */
685void
686Main_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
731Boolean
732Main_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
771static Boolean
772SetVarObjdir(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 */
802int
803str2Lst_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*/
819static void
820siginfo(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. */
834static void
835MakeMode(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
856static void
857PrintVar(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 */
889Boolean
890GetBooleanVar(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
904static void
905doPrintVars(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
923static Boolean
924runTargets(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 */
972static void
973InitVarTargets(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
988static void
989InitRandom(void)
990{
991	struct timeval tv;
992
993	gettimeofday(&tv, NULL);
994	srandom((unsigned int)(tv.tv_sec + tv.tv_usec));
995}
996
997static const char *
998InitVarMachine(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
1018static const char *
1019InitVarMachineArch(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 */
1071static void
1072HandlePWD(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
1096ignore_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 */
1110static void
1111InitObjdir(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 */
1128static void
1129UnlimitFiles(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
1141static void
1142CmdOpts_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 */
1175static void
1176InitVarMake(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 */
1197static void
1198InitDefSysIncPath(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
1235static void
1236ReadBuiltinRules(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
1261static void
1262InitMaxJobs(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 */
1299static void
1300InitVpath(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
1325static void
1326ReadAllMakefiles(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
1337static void
1338ReadFirstDefaultMakefile(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 */
1365static void
1366main_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	if (makelevel > 0) {
1477		char pn[1024];
1478		snprintf(pn, sizeof pn, "%s[%d]", progname, makelevel);
1479		progname = bmake_strdup(pn);
1480	}
1481
1482#ifdef USE_META
1483	meta_init();
1484#endif
1485	Dir_Init();
1486
1487	/*
1488	 * First snag any flags out of the MAKE environment variable.
1489	 * (Note this is *not* MAKEFLAGS since /bin/make uses that and it's
1490	 * in a different format).
1491	 */
1492#ifdef POSIX
1493	{
1494		char *p1 = explode(getenv("MAKEFLAGS"));
1495		Main_ParseArgLine(p1);
1496		free(p1);
1497	}
1498#else
1499	Main_ParseArgLine(getenv("MAKE"));
1500#endif
1501
1502	/*
1503	 * Find where we are (now).
1504	 * We take care of PWD for the automounter below...
1505	 */
1506	if (getcwd(curdir, MAXPATHLEN) == NULL) {
1507		(void)fprintf(stderr, "%s: getcwd: %s.\n",
1508		    progname, strerror(errno));
1509		exit(2);
1510	}
1511
1512	MainParseArgs(argc, argv);
1513
1514	if (opts.enterFlag)
1515		printf("%s: Entering directory `%s'\n", progname, curdir);
1516
1517	/*
1518	 * Verify that cwd is sane.
1519	 */
1520	if (stat(curdir, &sa) == -1) {
1521		(void)fprintf(stderr, "%s: %s: %s.\n",
1522		    progname, curdir, strerror(errno));
1523		exit(2);
1524	}
1525
1526#ifndef NO_PWD_OVERRIDE
1527	HandlePWD(&sa);
1528#endif
1529	Global_Set(".CURDIR", curdir);
1530
1531	InitObjdir(machine, machine_arch);
1532
1533	/*
1534	 * Initialize archive, target and suffix modules in preparation for
1535	 * parsing the makefile(s)
1536	 */
1537	Arch_Init();
1538	Suff_Init();
1539	Trace_Init(tracefile);
1540
1541	defaultNode = NULL;
1542	(void)time(&now);
1543
1544	Trace_Log(MAKESTART, NULL);
1545
1546	InitVarTargets();
1547
1548	InitDefSysIncPath(syspath);
1549}
1550
1551/*
1552 * Read the system makefile followed by either makefile, Makefile or the
1553 * files given by the -f option. Exit on parse errors.
1554 */
1555static void
1556main_ReadFiles(void)
1557{
1558
1559	if (!opts.noBuiltins)
1560		ReadBuiltinRules();
1561
1562	if (!Lst_IsEmpty(&opts.makefiles))
1563		ReadAllMakefiles(&opts.makefiles);
1564	else
1565		ReadFirstDefaultMakefile();
1566}
1567
1568/* Compute the dependency graph. */
1569static void
1570main_PrepareMaking(void)
1571{
1572	/* In particular suppress .depend for '-r -V .OBJDIR -f /dev/null' */
1573	if (!opts.noBuiltins || opts.printVars == PVM_NONE) {
1574		(void)Var_Subst("${.MAKE.DEPENDFILE}",
1575		    SCOPE_CMDLINE, VARE_WANTRES, &makeDependfile);
1576		if (makeDependfile[0] != '\0') {
1577			/* TODO: handle errors */
1578			doing_depend = TRUE;
1579			(void)ReadMakefile(makeDependfile);
1580			doing_depend = FALSE;
1581		}
1582	}
1583
1584	if (enterFlagObj)
1585		printf("%s: Entering directory `%s'\n", progname, objdir);
1586
1587	MakeMode();
1588
1589	{
1590		FStr makeflags = Var_Value(SCOPE_GLOBAL, MAKEFLAGS);
1591		Global_Append("MFLAGS", makeflags.str);
1592		FStr_Done(&makeflags);
1593	}
1594
1595	InitMaxJobs();
1596
1597	/*
1598	 * Be compatible if the user did not specify -j and did not explicitly
1599	 * turn compatibility on.
1600	 */
1601	if (!opts.compatMake && !forceJobs)
1602		opts.compatMake = TRUE;
1603
1604	if (!opts.compatMake)
1605		Job_ServerStart(maxJobTokens, jp_0, jp_1);
1606	DEBUG5(JOB, "job_pipe %d %d, maxjobs %d, tokens %d, compat %d\n",
1607	    jp_0, jp_1, opts.maxJobs, maxJobTokens, opts.compatMake ? 1 : 0);
1608
1609	if (opts.printVars == PVM_NONE)
1610		Main_ExportMAKEFLAGS(TRUE);	/* initial export */
1611
1612	InitVpath();
1613
1614	/*
1615	 * Now that all search paths have been read for suffixes et al, it's
1616	 * time to add the default search path to their lists...
1617	 */
1618	Suff_DoPaths();
1619
1620	/*
1621	 * Propagate attributes through :: dependency lists.
1622	 */
1623	Targ_Propagate();
1624
1625	/* print the initial graph, if the user requested it */
1626	if (DEBUG(GRAPH1))
1627		Targ_PrintGraph(1);
1628}
1629
1630/*
1631 * Make the targets.
1632 * If the -v or -V options are given, print variables instead.
1633 * Return whether any of the targets is out-of-date.
1634 */
1635static Boolean
1636main_Run(void)
1637{
1638	if (opts.printVars != PVM_NONE) {
1639		/* print the values of any variables requested by the user */
1640		doPrintVars();
1641		return FALSE;
1642	} else {
1643		return runTargets();
1644	}
1645}
1646
1647/* Clean up after making the targets. */
1648static void
1649main_CleanUp(void)
1650{
1651#ifdef CLEANUP
1652	Lst_DoneCall(&opts.variables, free);
1653	/*
1654	 * Don't free the actual strings from opts.makefiles, they may be
1655	 * used in GNodes.
1656	 */
1657	Lst_Done(&opts.makefiles);
1658	Lst_DoneCall(&opts.create, free);
1659#endif
1660
1661	/* print the graph now it's been processed if the user requested it */
1662	if (DEBUG(GRAPH2))
1663		Targ_PrintGraph(2);
1664
1665	Trace_Log(MAKEEND, NULL);
1666
1667	if (enterFlagObj)
1668		printf("%s: Leaving directory `%s'\n", progname, objdir);
1669	if (opts.enterFlag)
1670		printf("%s: Leaving directory `%s'\n", progname, curdir);
1671
1672#ifdef USE_META
1673	meta_finish();
1674#endif
1675	Suff_End();
1676	Targ_End();
1677	Arch_End();
1678	Var_End();
1679	Parse_End();
1680	Dir_End();
1681	Job_End();
1682	Trace_End();
1683}
1684
1685/* Determine the exit code. */
1686static int
1687main_Exit(Boolean outOfDate)
1688{
1689	if (opts.strict && (main_errors > 0 || Parse_GetFatals() > 0))
1690		return 2;	/* Not 1 so -q can distinguish error */
1691	return outOfDate ? 1 : 0;
1692}
1693
1694int
1695main(int argc, char **argv)
1696{
1697	Boolean outOfDate;
1698
1699	main_Init(argc, argv);
1700	main_ReadFiles();
1701	main_PrepareMaking();
1702	outOfDate = main_Run();
1703	main_CleanUp();
1704	return main_Exit(outOfDate);
1705}
1706
1707/*
1708 * Open and parse the given makefile, with all its side effects.
1709 *
1710 * Results:
1711 *	0 if ok. -1 if couldn't open file.
1712 */
1713static int
1714ReadMakefile(const char *fname)
1715{
1716	int fd;
1717	char *name, *path = NULL;
1718
1719	if (strcmp(fname, "-") == 0) {
1720		Parse_File(NULL /*stdin*/, -1);
1721		Var_Set(SCOPE_INTERNAL, "MAKEFILE", "");
1722	} else {
1723		/* if we've chdir'd, rebuild the path name */
1724		if (strcmp(curdir, objdir) != 0 && *fname != '/') {
1725			path = str_concat3(curdir, "/", fname);
1726			fd = open(path, O_RDONLY);
1727			if (fd != -1) {
1728				fname = path;
1729				goto found;
1730			}
1731			free(path);
1732
1733			/* If curdir failed, try objdir (ala .depend) */
1734			path = str_concat3(objdir, "/", fname);
1735			fd = open(path, O_RDONLY);
1736			if (fd != -1) {
1737				fname = path;
1738				goto found;
1739			}
1740		} else {
1741			fd = open(fname, O_RDONLY);
1742			if (fd != -1)
1743				goto found;
1744		}
1745		/* look in -I and system include directories. */
1746		name = Dir_FindFile(fname, parseIncPath);
1747		if (name == NULL) {
1748			SearchPath *sysInc = Lst_IsEmpty(&sysIncPath->dirs)
1749					     ? defSysIncPath : sysIncPath;
1750			name = Dir_FindFile(fname, sysInc);
1751		}
1752		if (name == NULL || (fd = open(name, O_RDONLY)) == -1) {
1753			free(name);
1754			free(path);
1755			return -1;
1756		}
1757		fname = name;
1758		/*
1759		 * set the MAKEFILE variable desired by System V fans -- the
1760		 * placement of the setting here means it gets set to the last
1761		 * makefile specified, as it is set by SysV make.
1762		 */
1763found:
1764		if (!doing_depend)
1765			Var_Set(SCOPE_INTERNAL, "MAKEFILE", fname);
1766		Parse_File(fname, fd);
1767	}
1768	free(path);
1769	return 0;
1770}
1771
1772/*
1773 * Cmd_Exec --
1774 *	Execute the command in cmd, and return the output of that command
1775 *	in a string.  In the output, newlines are replaced with spaces.
1776 *
1777 * Results:
1778 *	A string containing the output of the command, or the empty string.
1779 *	*errfmt returns a format string describing the command failure,
1780 *	if any, using a single %s conversion specification.
1781 *
1782 * Side Effects:
1783 *	The string must be freed by the caller.
1784 */
1785char *
1786Cmd_Exec(const char *cmd, const char **errfmt)
1787{
1788	const char *args[4];	/* Args for invoking the shell */
1789	int pipefds[2];
1790	int cpid;		/* Child PID */
1791	int pid;		/* PID from wait() */
1792	int status;		/* command exit status */
1793	Buffer buf;		/* buffer to store the result */
1794	ssize_t bytes_read;
1795	char *res;		/* result */
1796	size_t res_len;
1797	char *cp;
1798	int savederr;		/* saved errno */
1799
1800	*errfmt = NULL;
1801
1802	if (shellName == NULL)
1803		Shell_Init();
1804	/*
1805	 * Set up arguments for shell
1806	 */
1807	args[0] = shellName;
1808	args[1] = "-c";
1809	args[2] = cmd;
1810	args[3] = NULL;
1811
1812	/*
1813	 * Open a pipe for fetching its output
1814	 */
1815	if (pipe(pipefds) == -1) {
1816		*errfmt = "Couldn't create pipe for \"%s\"";
1817		goto bad;
1818	}
1819
1820	Var_ReexportVars();
1821
1822	/*
1823	 * Fork
1824	 */
1825	switch (cpid = vfork()) {
1826	case 0:
1827		(void)close(pipefds[0]); /* Close input side of pipe */
1828
1829		/*
1830		 * Duplicate the output stream to the shell's output, then
1831		 * shut the extra thing down. Note we don't fetch the error
1832		 * stream...why not? Why?
1833		 */
1834		(void)dup2(pipefds[1], 1);
1835		(void)close(pipefds[1]);
1836
1837		(void)execv(shellPath, UNCONST(args));
1838		_exit(1);
1839		/*NOTREACHED*/
1840
1841	case -1:
1842		*errfmt = "Couldn't exec \"%s\"";
1843		goto bad;
1844
1845	default:
1846		(void)close(pipefds[1]); /* No need for the writing half */
1847
1848		savederr = 0;
1849		Buf_Init(&buf);
1850
1851		do {
1852			char result[BUFSIZ];
1853			bytes_read = read(pipefds[0], result, sizeof result);
1854			if (bytes_read > 0)
1855				Buf_AddBytes(&buf, result, (size_t)bytes_read);
1856		} while (bytes_read > 0 ||
1857			 (bytes_read == -1 && errno == EINTR));
1858		if (bytes_read == -1)
1859			savederr = errno;
1860
1861		(void)close(pipefds[0]); /* Close the input side of the pipe. */
1862
1863		/* Wait for the process to exit. */
1864		while ((pid = waitpid(cpid, &status, 0)) != cpid && pid >= 0)
1865			JobReapChild(pid, status, FALSE);
1866
1867		res_len = buf.len;
1868		res = Buf_DoneData(&buf);
1869
1870		if (savederr != 0)
1871			*errfmt = "Couldn't read shell's output for \"%s\"";
1872
1873		if (WIFSIGNALED(status))
1874			*errfmt = "\"%s\" exited on a signal";
1875		else if (WEXITSTATUS(status) != 0)
1876			*errfmt = "\"%s\" returned non-zero status";
1877
1878		/* Convert newlines to spaces.  A final newline is just stripped */
1879		if (res_len > 0 && res[res_len - 1] == '\n')
1880			res[res_len - 1] = '\0';
1881		for (cp = res; *cp != '\0'; cp++)
1882			if (*cp == '\n')
1883				*cp = ' ';
1884		break;
1885	}
1886	return res;
1887bad:
1888	return bmake_strdup("");
1889}
1890
1891/*
1892 * Print a printf-style error message.
1893 *
1894 * In default mode, this error message has no consequences, in particular it
1895 * does not affect the exit status.  Only in lint mode (-dL) it does.
1896 */
1897void
1898Error(const char *fmt, ...)
1899{
1900	va_list ap;
1901	FILE *err_file;
1902
1903	err_file = opts.debug_file;
1904	if (err_file == stdout)
1905		err_file = stderr;
1906	(void)fflush(stdout);
1907	for (;;) {
1908		va_start(ap, fmt);
1909		fprintf(err_file, "%s: ", progname);
1910		(void)vfprintf(err_file, fmt, ap);
1911		va_end(ap);
1912		(void)fprintf(err_file, "\n");
1913		(void)fflush(err_file);
1914		if (err_file == stderr)
1915			break;
1916		err_file = stderr;
1917	}
1918	main_errors++;
1919}
1920
1921/*
1922 * Wait for any running jobs to finish, then produce an error message,
1923 * finally exit immediately.
1924 *
1925 * Exiting immediately differs from Parse_Error, which exits only after the
1926 * current top-level makefile has been parsed completely.
1927 */
1928void
1929Fatal(const char *fmt, ...)
1930{
1931	va_list ap;
1932
1933	if (jobsRunning)
1934		Job_Wait();
1935
1936	(void)fflush(stdout);
1937	va_start(ap, fmt);
1938	(void)vfprintf(stderr, fmt, ap);
1939	va_end(ap);
1940	(void)fprintf(stderr, "\n");
1941	(void)fflush(stderr);
1942
1943	PrintOnError(NULL, NULL);
1944
1945	if (DEBUG(GRAPH2) || DEBUG(GRAPH3))
1946		Targ_PrintGraph(2);
1947	Trace_Log(MAKEERROR, NULL);
1948	exit(2);		/* Not 1 so -q can distinguish error */
1949}
1950
1951/*
1952 * Major exception once jobs are being created.
1953 * Kills all jobs, prints a message and exits.
1954 */
1955void
1956Punt(const char *fmt, ...)
1957{
1958	va_list ap;
1959
1960	va_start(ap, fmt);
1961	(void)fflush(stdout);
1962	(void)fprintf(stderr, "%s: ", progname);
1963	(void)vfprintf(stderr, fmt, ap);
1964	va_end(ap);
1965	(void)fprintf(stderr, "\n");
1966	(void)fflush(stderr);
1967
1968	PrintOnError(NULL, NULL);
1969
1970	DieHorribly();
1971}
1972
1973/* Exit without giving a message. */
1974void
1975DieHorribly(void)
1976{
1977	if (jobsRunning)
1978		Job_AbortAll();
1979	if (DEBUG(GRAPH2))
1980		Targ_PrintGraph(2);
1981	Trace_Log(MAKEERROR, NULL);
1982	exit(2);		/* Not 1 so -q can distinguish error */
1983}
1984
1985/*
1986 * Called when aborting due to errors in child shell to signal abnormal exit.
1987 * The program exits.
1988 * Errors is the number of errors encountered in Make_Make.
1989 */
1990void
1991Finish(int errs)
1992{
1993	if (shouldDieQuietly(NULL, -1))
1994		exit(2);
1995	Fatal("%d error%s", errs, errs == 1 ? "" : "s");
1996}
1997
1998/*
1999 * eunlink --
2000 *	Remove a file carefully, avoiding directories.
2001 */
2002int
2003eunlink(const char *file)
2004{
2005	struct stat st;
2006
2007	if (lstat(file, &st) == -1)
2008		return -1;
2009
2010	if (S_ISDIR(st.st_mode)) {
2011		errno = EISDIR;
2012		return -1;
2013	}
2014	return unlink(file);
2015}
2016
2017static void
2018write_all(int fd, const void *data, size_t n)
2019{
2020	const char *mem = data;
2021
2022	while (n > 0) {
2023		ssize_t written = write(fd, mem, n);
2024		if (written == -1 && errno == EAGAIN)
2025			continue;
2026		if (written == -1)
2027			break;
2028		mem += written;
2029		n -= (size_t)written;
2030	}
2031}
2032
2033/*
2034 * execDie --
2035 *	Print why exec failed, avoiding stdio.
2036 */
2037void MAKE_ATTR_DEAD
2038execDie(const char *af, const char *av)
2039{
2040	Buffer buf;
2041
2042	Buf_Init(&buf);
2043	Buf_AddStr(&buf, progname);
2044	Buf_AddStr(&buf, ": ");
2045	Buf_AddStr(&buf, af);
2046	Buf_AddStr(&buf, "(");
2047	Buf_AddStr(&buf, av);
2048	Buf_AddStr(&buf, ") failed (");
2049	Buf_AddStr(&buf, strerror(errno));
2050	Buf_AddStr(&buf, ")\n");
2051
2052	write_all(STDERR_FILENO, buf.data, buf.len);
2053
2054	Buf_Done(&buf);
2055	_exit(1);
2056}
2057
2058/* purge any relative paths */
2059static void
2060purge_relative_cached_realpaths(void)
2061{
2062	HashEntry *he, *nhe;
2063	HashIter hi;
2064
2065	HashIter_Init(&hi, &cached_realpaths);
2066	he = HashIter_Next(&hi);
2067	while (he != NULL) {
2068		nhe = HashIter_Next(&hi);
2069		if (he->key[0] != '/') {
2070			DEBUG1(DIR, "cached_realpath: purging %s\n", he->key);
2071			HashTable_DeleteEntry(&cached_realpaths, he);
2072			/* XXX: What about the allocated he->value? Either
2073			 * free them or document why they cannot be freed. */
2074		}
2075		he = nhe;
2076	}
2077}
2078
2079char *
2080cached_realpath(const char *pathname, char *resolved)
2081{
2082	const char *rp;
2083
2084	if (pathname == NULL || pathname[0] == '\0')
2085		return NULL;
2086
2087	rp = HashTable_FindValue(&cached_realpaths, pathname);
2088	if (rp != NULL) {
2089		/* a hit */
2090		strncpy(resolved, rp, MAXPATHLEN);
2091		resolved[MAXPATHLEN - 1] = '\0';
2092		return resolved;
2093	}
2094
2095	rp = realpath(pathname, resolved);
2096	if (rp != NULL) {
2097		HashTable_Set(&cached_realpaths, pathname, bmake_strdup(rp));
2098		DEBUG2(DIR, "cached_realpath: %s -> %s\n", pathname, rp);
2099		return resolved;
2100	}
2101
2102	/* should we negative-cache? */
2103	return NULL;
2104}
2105
2106/*
2107 * Return true if we should die without noise.
2108 * For example our failing child was a sub-make or failure happened elsewhere.
2109 */
2110Boolean
2111shouldDieQuietly(GNode *gn, int bf)
2112{
2113	static int quietly = -1;
2114
2115	if (quietly < 0) {
2116		if (DEBUG(JOB) || !GetBooleanVar(".MAKE.DIE_QUIETLY", TRUE))
2117			quietly = 0;
2118		else if (bf >= 0)
2119			quietly = bf;
2120		else
2121			quietly = (gn != NULL && (gn->type & OP_MAKE)) ? 1 : 0;
2122	}
2123	return quietly != 0;
2124}
2125
2126static void
2127SetErrorVars(GNode *gn)
2128{
2129	StringListNode *ln;
2130
2131	/*
2132	 * We can print this even if there is no .ERROR target.
2133	 */
2134	Global_Set(".ERROR_TARGET", gn->name);
2135	Global_Delete(".ERROR_CMD");
2136
2137	for (ln = gn->commands.first; ln != NULL; ln = ln->next) {
2138		const char *cmd = ln->datum;
2139
2140		if (cmd == NULL)
2141			break;
2142		Global_Append(".ERROR_CMD", cmd);
2143	}
2144}
2145
2146/*
2147 * Print some helpful information in case of an error.
2148 * The caller should exit soon after calling this function.
2149 */
2150void
2151PrintOnError(GNode *gn, const char *msg)
2152{
2153	static GNode *errorNode = NULL;
2154
2155	if (DEBUG(HASH)) {
2156		Targ_Stats();
2157		Var_Stats();
2158	}
2159
2160	if (errorNode != NULL)
2161		return;		/* we've been here! */
2162
2163	if (msg != NULL)
2164		printf("%s", msg);
2165	printf("\n%s: stopped in %s\n", progname, curdir);
2166
2167	/* we generally want to keep quiet if a sub-make died */
2168	if (shouldDieQuietly(gn, -1))
2169		return;
2170
2171	if (gn != NULL)
2172		SetErrorVars(gn);
2173
2174	{
2175		char *errorVarsValues;
2176		(void)Var_Subst("${MAKE_PRINT_VAR_ON_ERROR:@v@$v='${$v}'\n@}",
2177				SCOPE_GLOBAL, VARE_WANTRES, &errorVarsValues);
2178		/* TODO: handle errors */
2179		printf("%s", errorVarsValues);
2180		free(errorVarsValues);
2181	}
2182
2183	fflush(stdout);
2184
2185	/*
2186	 * Finally, see if there is a .ERROR target, and run it if so.
2187	 */
2188	errorNode = Targ_FindNode(".ERROR");
2189	if (errorNode != NULL) {
2190		errorNode->type |= OP_SPECIAL;
2191		Compat_Make(errorNode, errorNode);
2192	}
2193}
2194
2195void
2196Main_ExportMAKEFLAGS(Boolean first)
2197{
2198	static Boolean once = TRUE;
2199	const char *expr;
2200	char *s;
2201
2202	if (once != first)
2203		return;
2204	once = FALSE;
2205
2206	expr = "${.MAKEFLAGS} ${.MAKEOVERRIDES:O:u:@v@$v=${$v:Q}@}";
2207	(void)Var_Subst(expr, SCOPE_CMDLINE, VARE_WANTRES, &s);
2208	/* TODO: handle errors */
2209	if (s[0] != '\0') {
2210#ifdef POSIX
2211		setenv("MAKEFLAGS", s, 1);
2212#else
2213		setenv("MAKE", s, 1);
2214#endif
2215	}
2216}
2217
2218char *
2219getTmpdir(void)
2220{
2221	static char *tmpdir = NULL;
2222	struct stat st;
2223
2224	if (tmpdir != NULL)
2225		return tmpdir;
2226
2227	/* Honor $TMPDIR but only if it is valid. Ensure it ends with '/'. */
2228	(void)Var_Subst("${TMPDIR:tA:U" _PATH_TMP "}/",
2229	    SCOPE_GLOBAL, VARE_WANTRES, &tmpdir);
2230	/* TODO: handle errors */
2231
2232	if (stat(tmpdir, &st) < 0 || !S_ISDIR(st.st_mode)) {
2233		free(tmpdir);
2234		tmpdir = bmake_strdup(_PATH_TMP);
2235	}
2236	return tmpdir;
2237}
2238
2239/*
2240 * Create and open a temp file using "pattern".
2241 * If out_fname is provided, set it to a copy of the filename created.
2242 * Otherwise unlink the file once open.
2243 */
2244int
2245mkTempFile(const char *pattern, char *tfile, size_t tfile_sz)
2246{
2247	static char *tmpdir = NULL;
2248	char tbuf[MAXPATHLEN];
2249	int fd;
2250
2251	if (pattern == NULL)
2252		pattern = TMPPAT;
2253	if (tmpdir == NULL)
2254		tmpdir = getTmpdir();
2255	if (tfile == NULL) {
2256	    tfile = tbuf;
2257	    tfile_sz = sizeof tbuf;
2258	}
2259	if (pattern[0] == '/') {
2260		snprintf(tfile, tfile_sz, "%s", pattern);
2261	} else {
2262		snprintf(tfile, tfile_sz, "%s%s", tmpdir, pattern);
2263	}
2264	if ((fd = mkstemp(tfile)) < 0)
2265		Punt("Could not create temporary file %s: %s", tfile,
2266		    strerror(errno));
2267	if (tfile == tbuf) {
2268		unlink(tfile);	/* we just want the descriptor */
2269	}
2270	return fd;
2271}
2272
2273/*
2274 * Convert a string representation of a boolean into a boolean value.
2275 * Anything that looks like "No", "False", "Off", "0" etc. is FALSE,
2276 * the empty string is the fallback, everything else is TRUE.
2277 */
2278Boolean
2279ParseBoolean(const char *s, Boolean fallback)
2280{
2281	char ch = ch_tolower(s[0]);
2282	if (ch == '\0')
2283		return fallback;
2284	if (ch == '0' || ch == 'f' || ch == 'n')
2285		return FALSE;
2286	if (ch == 'o')
2287		return ch_tolower(s[1]) != 'f';
2288	return TRUE;
2289}
2290