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