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