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