main.c revision 133085
11590Srgrimes/*
21590Srgrimes * Copyright (c) 1988, 1989, 1990, 1993
31590Srgrimes *	The Regents of the University of California.  All rights reserved.
41590Srgrimes * Copyright (c) 1989 by Berkeley Softworks
51590Srgrimes * All rights reserved.
61590Srgrimes *
71590Srgrimes * This code is derived from software contributed to Berkeley by
81590Srgrimes * Adam de Boor.
91590Srgrimes *
101590Srgrimes * Redistribution and use in source and binary forms, with or without
111590Srgrimes * modification, are permitted provided that the following conditions
121590Srgrimes * are met:
131590Srgrimes * 1. Redistributions of source code must retain the above copyright
141590Srgrimes *    notice, this list of conditions and the following disclaimer.
151590Srgrimes * 2. Redistributions in binary form must reproduce the above copyright
161590Srgrimes *    notice, this list of conditions and the following disclaimer in the
171590Srgrimes *    documentation and/or other materials provided with the distribution.
181590Srgrimes * 3. All advertising materials mentioning features or use of this software
191590Srgrimes *    must display the following acknowledgement:
201590Srgrimes *	This product includes software developed by the University of
211590Srgrimes *	California, Berkeley and its contributors.
221590Srgrimes * 4. Neither the name of the University nor the names of its contributors
231590Srgrimes *    may be used to endorse or promote products derived from this software
241590Srgrimes *    without specific prior written permission.
251590Srgrimes *
261590Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
271590Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
281590Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
291590Srgrimes * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
301590Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
311590Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
321590Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
331590Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
341590Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
351590Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
361590Srgrimes * SUCH DAMAGE.
3762833Swsanchez *
3862833Swsanchez * @(#)main.c      8.3 (Berkeley) 3/19/94
391590Srgrimes */
401590Srgrimes
411590Srgrimes#ifndef lint
4294595Sobrien#if 0
4394589Sobrienstatic char copyright[] =
4494589Sobrien"@(#) Copyright (c) 1988, 1989, 1990, 1993\n\
4594589Sobrien	The Regents of the University of California.  All rights reserved.\n";
4694595Sobrien#endif
471590Srgrimes#endif /* not lint */
4894589Sobrien#include <sys/cdefs.h>
4994587Sobrien__FBSDID("$FreeBSD: head/usr.bin/make/main.c 133085 2004-08-03 18:56:31Z harti $");
501590Srgrimes
511590Srgrimes/*-
521590Srgrimes * main.c --
531590Srgrimes *	The main file for this entire program. Exit routines etc
541590Srgrimes *	reside here.
551590Srgrimes *
561590Srgrimes * Utility functions defined in this file:
571590Srgrimes *	Main_ParseArgLine	Takes a line of arguments, breaks them and
581590Srgrimes *				treats them as if they were given when first
591590Srgrimes *				invoked. Used by the parse module to implement
601590Srgrimes *				the .MFLAGS target.
611590Srgrimes */
621590Srgrimes
631590Srgrimes#include <sys/param.h>
641590Srgrimes#include <sys/signal.h>
651590Srgrimes#include <sys/stat.h>
6639006Skato#if defined(__i386__)
6739006Skato#include <sys/sysctl.h>
6839006Skato#endif
69127880Sdes#include <sys/time.h>
70127899Sru#include <sys/resource.h>
7118730Ssteve#ifndef MACHINE
725814Sjkh#include <sys/utsname.h>
7318730Ssteve#endif
7418730Ssteve#include <sys/wait.h>
75127880Sdes
7627644Scharnier#include <err.h>
771590Srgrimes#include <errno.h>
781590Srgrimes#include <fcntl.h>
79127880Sdes#include <signal.h>
80127880Sdes#include <stdarg.h>
811590Srgrimes#include <stdio.h>
82127880Sdes#include <stdlib.h>
8349331Shoek#include <sysexits.h>
8463955Simp#include <unistd.h>
85127880Sdes
861590Srgrimes#include "make.h"
871590Srgrimes#include "hash.h"
881590Srgrimes#include "dir.h"
891590Srgrimes#include "job.h"
901590Srgrimes#include "pathnames.h"
911590Srgrimes
92104395Sjmallett#define WANT_ENV_MKLVL	1
93104395Sjmallett
941590Srgrimes#ifndef	DEFMAXLOCAL
951590Srgrimes#define	DEFMAXLOCAL DEFMAXJOBS
9618730Ssteve#endif	/* DEFMAXLOCAL */
971590Srgrimes
981590Srgrimes#define	MAKEFLAGS	".MAKEFLAGS"
991590Srgrimes
1001590SrgrimesLst			create;		/* Targets to be made */
1011590Srgrimestime_t			now;		/* Time at start of make */
1021590SrgrimesGNode			*DEFAULT;	/* .DEFAULT node */
1031590SrgrimesBoolean			allPrecious;	/* .PRECIOUS given on line by itself */
1041590Srgrimes
1051590Srgrimesstatic Boolean		noBuiltins;	/* -r flag */
1061590Srgrimesstatic Lst		makefiles;	/* ordered list of makefiles to read */
10766365Speterstatic Boolean		expandVars;	/* fully expand printed variables */
10817193Sbdestatic Lst		variables;	/* list of variables to print */
10918730Ssteveint			maxJobs;	/* -j argument */
11028228Sfsmpstatic Boolean          forceJobs;      /* -j argument given */
1111590Srgrimesstatic int		maxLocal;	/* -L argument */
1121590SrgrimesBoolean			compatMake;	/* -B argument */
1131590SrgrimesBoolean			debug;		/* -d flag */
1141590SrgrimesBoolean			noExecute;	/* -n flag */
1151590SrgrimesBoolean			keepgoing;	/* -k flag */
1161590SrgrimesBoolean			queryFlag;	/* -q flag */
1171590SrgrimesBoolean			touchFlag;	/* -t flag */
1181590SrgrimesBoolean			usePipes;	/* !-P flag */
1191590SrgrimesBoolean			ignoreErrors;	/* -i flag */
1201590SrgrimesBoolean			beSilent;	/* -s flag */
12141151SdgBoolean			beVerbose;	/* -v flag */
1221590SrgrimesBoolean			oldVars;	/* variable substitution style */
1231590SrgrimesBoolean			checkEnvFirst;	/* -e flag */
12449332ShoekLst			envFirstVars;	/* (-E) vars to override from env */
125104818SjmallettBoolean			jobsRunning;	/* TRUE if the jobs might be running */
1261590Srgrimes
12792921Simpstatic void		MainParseArgs(int, char **);
12892921Simpchar *			chdir_verify_path(char *, char *);
12992921Simpstatic int		ReadMakefile(void *, void *);
13092921Simpstatic void		usage(void);
1311590Srgrimes
1321590Srgrimesstatic char *curdir;			/* startup directory */
1331590Srgrimesstatic char *objdir;			/* where we chdir'ed to */
1341590Srgrimes
135133085Sharti/*
136133085Sharti * Append a flag with an optional argument to MAKEFLAGS and MFLAGS
137133085Sharti */
138133085Shartistatic void
139133085ShartiMFLAGS_append(char *flag, char *arg)
140133085Sharti{
141133085Sharti	Var_Append(MAKEFLAGS, flag, VAR_GLOBAL);
142133085Sharti	if (arg != NULL)
143133085Sharti		Var_Append(MAKEFLAGS, arg, VAR_GLOBAL);
144133085Sharti
145133085Sharti	Var_Append("MFLAGS", flag, VAR_GLOBAL);
146133085Sharti	if (arg != NULL)
147133085Sharti		Var_Append("MFLAGS", arg, VAR_GLOBAL);
148133085Sharti}
149133085Sharti
1501590Srgrimes/*-
1511590Srgrimes * MainParseArgs --
1521590Srgrimes *	Parse a given argument vector. Called from main() and from
1531590Srgrimes *	Main_ParseArgLine() when the .MAKEFLAGS target is used.
1541590Srgrimes *
1551590Srgrimes *	XXX: Deal with command line overriding .MAKEFLAGS in makefile
1561590Srgrimes *
1571590Srgrimes * Results:
1581590Srgrimes *	None
1591590Srgrimes *
1601590Srgrimes * Side Effects:
1611590Srgrimes *	Various global and local flags will be set depending on the flags
1621590Srgrimes *	given
1631590Srgrimes */
1641590Srgrimesstatic void
165104696SjmallettMainParseArgs(int argc, char **argv)
1661590Srgrimes{
16736942Speter	char *p;
1685814Sjkh	int c;
1691590Srgrimes
1701590Srgrimes	optind = 1;	/* since we're called more than once */
17118730Ssteve#ifdef REMOTE
172102393Sjmallett# define OPTFLAGS "BC:D:E:I:L:PSV:Xd:ef:ij:km:nqrstv"
1731590Srgrimes#else
174102393Sjmallett# define OPTFLAGS "BC:D:E:I:PSV:Xd:ef:ij:km:nqrstv"
1751590Srgrimes#endif
17624360Simprearg:	while((c = getopt(argc, argv, OPTFLAGS)) != -1) {
1771590Srgrimes		switch(c) {
178102393Sjmallett		case 'C':
179107964Sseanc			if (chdir(optarg) == -1)
180107964Sseanc				err(1, "chdir %s", optarg);
181102393Sjmallett			break;
1821590Srgrimes		case 'D':
1831590Srgrimes			Var_Set(optarg, "1", VAR_GLOBAL);
184133085Sharti			MFLAGS_append("-D", optarg);
1851590Srgrimes			break;
1861590Srgrimes		case 'I':
1871590Srgrimes			Parse_AddIncludeDir(optarg);
188133085Sharti			MFLAGS_append("-I", optarg);
1891590Srgrimes			break;
19017193Sbde		case 'V':
19169531Swill			(void)Lst_AtEnd(variables, (void *)optarg);
192133085Sharti			MFLAGS_append("-V", optarg);
19317193Sbde			break;
19466365Speter		case 'X':
19566365Speter			expandVars = FALSE;
19666365Speter			break;
1971590Srgrimes		case 'B':
1981590Srgrimes			compatMake = TRUE;
199133085Sharti			MFLAGS_append("-B", NULL);
2001590Srgrimes			break;
20118730Ssteve#ifdef REMOTE
20249331Shoek		case 'L': {
20349331Shoek			char *endptr;
20449331Shoek
20549331Shoek			maxLocal = strtol(optarg, &endptr, 10);
20649331Shoek			if (maxLocal < 0 || *endptr != '\0') {
20749938Shoek				warnx("illegal number, -L argument -- %s",
20849938Shoek				    optarg);
20949938Shoek				usage();
21049331Shoek			}
211133085Sharti			MFLAGS_append("-L", optarg);
2121590Srgrimes			break;
21349331Shoek		}
21418730Ssteve#endif
2151590Srgrimes		case 'P':
2161590Srgrimes			usePipes = FALSE;
217133085Sharti			MFLAGS_append("-P", NULL);
2181590Srgrimes			break;
2191590Srgrimes		case 'S':
2201590Srgrimes			keepgoing = FALSE;
221133085Sharti			MFLAGS_append("-S", NULL);
2221590Srgrimes			break;
2231590Srgrimes		case 'd': {
2241590Srgrimes			char *modules = optarg;
2251590Srgrimes
2261590Srgrimes			for (; *modules; ++modules)
2271590Srgrimes				switch (*modules) {
2281590Srgrimes				case 'A':
2291590Srgrimes					debug = ~0;
2301590Srgrimes					break;
2311590Srgrimes				case 'a':
2321590Srgrimes					debug |= DEBUG_ARCH;
2331590Srgrimes					break;
2341590Srgrimes				case 'c':
2351590Srgrimes					debug |= DEBUG_COND;
2361590Srgrimes					break;
2371590Srgrimes				case 'd':
2381590Srgrimes					debug |= DEBUG_DIR;
2391590Srgrimes					break;
2401590Srgrimes				case 'f':
2411590Srgrimes					debug |= DEBUG_FOR;
2421590Srgrimes					break;
2431590Srgrimes				case 'g':
2441590Srgrimes					if (modules[1] == '1') {
2451590Srgrimes						debug |= DEBUG_GRAPH1;
2461590Srgrimes						++modules;
2471590Srgrimes					}
2481590Srgrimes					else if (modules[1] == '2') {
2491590Srgrimes						debug |= DEBUG_GRAPH2;
2501590Srgrimes						++modules;
2511590Srgrimes					}
2521590Srgrimes					break;
2531590Srgrimes				case 'j':
2541590Srgrimes					debug |= DEBUG_JOB;
2551590Srgrimes					break;
25660569Swill				case 'l':
25760569Swill					debug |= DEBUG_LOUD;
25860569Swill					break;
2591590Srgrimes				case 'm':
2601590Srgrimes					debug |= DEBUG_MAKE;
2611590Srgrimes					break;
2621590Srgrimes				case 's':
2631590Srgrimes					debug |= DEBUG_SUFF;
2641590Srgrimes					break;
2651590Srgrimes				case 't':
2661590Srgrimes					debug |= DEBUG_TARG;
2671590Srgrimes					break;
2681590Srgrimes				case 'v':
2691590Srgrimes					debug |= DEBUG_VAR;
2701590Srgrimes					break;
2711590Srgrimes				default:
27227644Scharnier					warnx("illegal argument to d option -- %c", *modules);
2731590Srgrimes					usage();
2741590Srgrimes				}
275133085Sharti			MFLAGS_append("-d", optarg);
2761590Srgrimes			break;
2771590Srgrimes		}
27849332Shoek		case 'E':
27994506Scharnier			p = emalloc(strlen(optarg) + 1);
28049332Shoek			(void)strcpy(p, optarg);
28169531Swill			(void)Lst_AtEnd(envFirstVars, (void *)p);
282133085Sharti			MFLAGS_append("-E", optarg);
28349332Shoek			break;
2841590Srgrimes		case 'e':
2851590Srgrimes			checkEnvFirst = TRUE;
286133085Sharti			MFLAGS_append("-e", NULL);
2871590Srgrimes			break;
2881590Srgrimes		case 'f':
28969531Swill			(void)Lst_AtEnd(makefiles, (void *)optarg);
2901590Srgrimes			break;
2911590Srgrimes		case 'i':
2921590Srgrimes			ignoreErrors = TRUE;
293133085Sharti			MFLAGS_append("-i", NULL);
2941590Srgrimes			break;
29549331Shoek		case 'j': {
29649331Shoek			char *endptr;
29749331Shoek
29818730Ssteve			forceJobs = TRUE;
29949331Shoek			maxJobs = strtol(optarg, &endptr, 10);
30049331Shoek			if (maxJobs <= 0 || *endptr != '\0') {
30149938Shoek				warnx("illegal number, -j argument -- %s",
30249938Shoek				    optarg);
30349938Shoek				usage();
30449331Shoek			}
30518730Ssteve#ifndef REMOTE
30618730Ssteve			maxLocal = maxJobs;
30718730Ssteve#endif
308133085Sharti			MFLAGS_append("-j", optarg);
3091590Srgrimes			break;
31049331Shoek		}
3111590Srgrimes		case 'k':
3121590Srgrimes			keepgoing = TRUE;
313133085Sharti			MFLAGS_append("-k", NULL);
3141590Srgrimes			break;
31518730Ssteve		case 'm':
31618730Ssteve			Dir_AddDir(sysIncPath, optarg);
317133085Sharti			MFLAGS_append("-m", optarg);
31818730Ssteve			break;
3191590Srgrimes		case 'n':
3201590Srgrimes			noExecute = TRUE;
321133085Sharti			MFLAGS_append("-n", NULL);
3221590Srgrimes			break;
3231590Srgrimes		case 'q':
3241590Srgrimes			queryFlag = TRUE;
3251590Srgrimes			/* Kind of nonsensical, wot? */
326133085Sharti			MFLAGS_append("-q", NULL);
3271590Srgrimes			break;
3281590Srgrimes		case 'r':
3291590Srgrimes			noBuiltins = TRUE;
330133085Sharti			MFLAGS_append("-r", NULL);
3311590Srgrimes			break;
3321590Srgrimes		case 's':
3331590Srgrimes			beSilent = TRUE;
334133085Sharti			MFLAGS_append("-s", NULL);
3351590Srgrimes			break;
3361590Srgrimes		case 't':
3371590Srgrimes			touchFlag = TRUE;
338133085Sharti			MFLAGS_append("-t", NULL);
3391590Srgrimes			break;
34041151Sdg		case 'v':
34141151Sdg			beVerbose = TRUE;
342133085Sharti			MFLAGS_append("-v", NULL);
34341151Sdg			break;
3441590Srgrimes		default:
3451590Srgrimes		case '?':
3461590Srgrimes			usage();
3471590Srgrimes		}
3481590Srgrimes	}
3491590Srgrimes
3501590Srgrimes	oldVars = TRUE;
3511590Srgrimes
3521590Srgrimes	/*
3531590Srgrimes	 * See if the rest of the arguments are variable assignments and
3541590Srgrimes	 * perform them if so. Else take them to be targets and stuff them
3551590Srgrimes	 * on the end of the "create" list.
3561590Srgrimes	 */
3571590Srgrimes	for (argv += optind, argc -= optind; *argv; ++argv, --argc)
3581590Srgrimes		if (Parse_IsVar(*argv))
3591590Srgrimes			Parse_DoVar(*argv, VAR_CMD);
3601590Srgrimes		else {
3611590Srgrimes			if (!**argv)
3621590Srgrimes				Punt("illegal (null) argument.");
3631590Srgrimes			if (**argv == '-') {
3641590Srgrimes				if ((*argv)[1])
3651590Srgrimes					optind = 0;     /* -flag... */
3661590Srgrimes				else
3671590Srgrimes					optind = 1;     /* - */
3681590Srgrimes				goto rearg;
3691590Srgrimes			}
37069531Swill			(void)Lst_AtEnd(create, (void *)estrdup(*argv));
3711590Srgrimes		}
3721590Srgrimes}
3731590Srgrimes
3741590Srgrimes/*-
3751590Srgrimes * Main_ParseArgLine --
3761590Srgrimes *  	Used by the parse module when a .MFLAGS or .MAKEFLAGS target
3771590Srgrimes *	is encountered and by main() when reading the .MAKEFLAGS envariable.
3781590Srgrimes *	Takes a line of arguments and breaks it into its
3791590Srgrimes * 	component words and passes those words and the number of them to the
3801590Srgrimes *	MainParseArgs function.
3811590Srgrimes *	The line should have all its leading whitespace removed.
3821590Srgrimes *
3831590Srgrimes * Results:
3841590Srgrimes *	None
3851590Srgrimes *
3861590Srgrimes * Side Effects:
3871590Srgrimes *	Only those that come from the various arguments.
3881590Srgrimes */
3891590Srgrimesvoid
390104696SjmallettMain_ParseArgLine(char *line)
3911590Srgrimes{
3921590Srgrimes	char **argv;			/* Manufactured argument vector */
3931590Srgrimes	int argc;			/* Number of arguments in argv */
3941590Srgrimes
3951590Srgrimes	if (line == NULL)
3961590Srgrimes		return;
3971590Srgrimes	for (; *line == ' '; ++line)
3981590Srgrimes		continue;
3991590Srgrimes	if (!*line)
4001590Srgrimes		return;
4011590Srgrimes
4025814Sjkh	argv = brk_string(line, &argc, TRUE);
4031590Srgrimes	MainParseArgs(argc, argv);
4041590Srgrimes}
4051590Srgrimes
40618339Sswallacechar *
407104696Sjmallettchdir_verify_path(char *path, char *obpath)
40818339Sswallace{
40918339Sswallace	struct stat sb;
41018339Sswallace
41118339Sswallace	if (stat(path, &sb) == 0 && S_ISDIR(sb.st_mode)) {
41275973Sru		if (chdir(path) == -1 || getcwd(obpath, MAXPATHLEN) == NULL) {
41327644Scharnier			warn("warning: %s", path);
41418339Sswallace			return 0;
41518339Sswallace		}
41675973Sru		return obpath;
41718339Sswallace	}
41818339Sswallace
41918339Sswallace	return 0;
42018339Sswallace}
42118339Sswallace
422133082Shartistatic void
423133082Sharticatch_child(int sig __unused)
424123513Sdes{
425123513Sdes}
42618339Sswallace
4271590Srgrimes/*-
4281590Srgrimes * main --
4291590Srgrimes *	The main function, for obvious reasons. Initializes variables
4301590Srgrimes *	and a few modules, then parses the arguments give it in the
4311590Srgrimes *	environment and on the command line. Reads the system makefile
4321590Srgrimes *	followed by either Makefile, makefile or the file given by the
4331590Srgrimes *	-f argument. Sets the .MAKEFLAGS PMake variable based on all the
4341590Srgrimes *	flags it has received by then uses either the Make or the Compat
4351590Srgrimes *	module to create the initial list of targets.
4361590Srgrimes *
4371590Srgrimes * Results:
4381590Srgrimes *	If -q was given, exits -1 if anything was out-of-date. Else it exits
4391590Srgrimes *	0.
4401590Srgrimes *
4411590Srgrimes * Side Effects:
4421590Srgrimes *	The program exits when done. Targets are created. etc. etc. etc.
4431590Srgrimes */
4441590Srgrimesint
445104696Sjmallettmain(int argc, char **argv)
4461590Srgrimes{
4471590Srgrimes	Lst targs;	/* target nodes to create -- passed to Make_Init */
4481590Srgrimes	Boolean outOfDate = TRUE; 	/* FALSE if all targets up to date */
44940500Sobrien	struct stat sa;
45040500Sobrien	char *p, *p1, *path, *pathp;
451104395Sjmallett#ifdef WANT_ENV_MKLVL
452104395Sjmallett#define	MKLVL_MAXVAL	500
453104395Sjmallett#define	MKLVL_ENVVAR	"__MKLVL__"
454104395Sjmallett	int iMkLvl = 0;
455104395Sjmallett	char *szMkLvl = getenv(MKLVL_ENVVAR);
456104395Sjmallett#endif	/* WANT_ENV_MKLVL */
45773262Simp	char mdpath[MAXPATHLEN];
45873262Simp	char obpath[MAXPATHLEN];
45973262Simp	char cdpath[MAXPATHLEN];
4605814Sjkh    	char *machine = getenv("MACHINE");
46144362Simp	char *machine_arch = getenv("MACHINE_ARCH");
46272679Skris	char *machine_cpu = getenv("MACHINE_CPU");
46318730Ssteve	Lst sysMkPath;			/* Path of sys.mk */
46418730Ssteve	char *cp = NULL, *start;
46518730Ssteve					/* avoid faults on read-only strings */
46618730Ssteve	static char syspath[] = _PATH_DEFSYSPATH;
4671590Srgrimes
468123513Sdes	{
469123513Sdes	/*
470123513Sdes	 * Catch SIGCHLD so that we get kicked out of select() when we
471123513Sdes	 * need to look at a child.  This is only known to matter for the
472123513Sdes	 * -j case (perhaps without -P).
473123513Sdes	 *
474123513Sdes	 * XXX this is intentionally misplaced.
475123513Sdes	 */
476123513Sdes	struct sigaction sa;
477123513Sdes
478123513Sdes	sigemptyset(&sa.sa_mask);
479123513Sdes	sa.sa_flags = SA_RESTART | SA_NOCLDSTOP;
480123513Sdes	sa.sa_handler = catch_child;
481123513Sdes	sigaction(SIGCHLD, &sa, NULL);
482123513Sdes	}
483123513Sdes
484104395Sjmallett#ifdef WANT_ENV_MKLVL
485104395Sjmallett	if ((iMkLvl = szMkLvl ? atoi(szMkLvl) : 0) < 0) {
486104395Sjmallett	  iMkLvl = 0;
487104395Sjmallett	}
488104395Sjmallett	if (iMkLvl++ > MKLVL_MAXVAL) {
489104395Sjmallett	  errc(2, EAGAIN,
490104395Sjmallett	       "Max recursion level (%d) exceeded.", MKLVL_MAXVAL);
491104395Sjmallett	}
492104395Sjmallett	bzero(szMkLvl = emalloc(32), 32);
493104395Sjmallett	sprintf(szMkLvl, "%d", iMkLvl);
494104395Sjmallett	setenv(MKLVL_ENVVAR, szMkLvl, 1);
495104395Sjmallett#endif /* WANT_ENV_MKLVL */
496104395Sjmallett
49764739Sgreen#if DEFSHELL == 2
49864739Sgreen	/*
49964739Sgreen	 * Turn off ENV to make ksh happier.
50064739Sgreen	 */
50164739Sgreen	unsetenv("ENV");
50264739Sgreen#endif
50364739Sgreen
50418730Ssteve#ifdef RLIMIT_NOFILE
5051590Srgrimes	/*
50618730Ssteve	 * get rid of resource limit on file descriptors
50718730Ssteve	 */
50818730Ssteve	{
50918730Ssteve		struct rlimit rl;
51018730Ssteve		if (getrlimit(RLIMIT_NOFILE, &rl) != -1 &&
51118730Ssteve		    rl.rlim_cur != rl.rlim_max) {
51218730Ssteve			rl.rlim_cur = rl.rlim_max;
51318730Ssteve			(void) setrlimit(RLIMIT_NOFILE, &rl);
51418730Ssteve		}
51518730Ssteve	}
51618730Ssteve#endif
5171590Srgrimes
5185814Sjkh	/*
51939006Skato	 * PC-98 kernel sets the `i386' string to the utsname.machine and
52039006Skato	 * it cannot be distinguished from IBM-PC by uname(3).  Therefore,
52139006Skato	 * we check machine.ispc98 and adjust the machine variable before
52239006Skato	 * using usname(3) below.
52353631Smarcel	 * NOTE: machdep.ispc98 was defined on 1998/8/31. At that time,
52453631Smarcel	 * __FreeBSD_version was defined as 300003. So, this check can
52553631Smarcel	 * safely be done with any kernel with version > 300003.
52639006Skato	 */
52739006Skato	if (!machine) {
52839006Skato		int	ispc98;
52939006Skato		size_t	len;
53039006Skato
53139006Skato		len = sizeof(ispc98);
53239006Skato		if (!sysctlbyname("machdep.ispc98", &ispc98, &len, NULL, 0)) {
53339006Skato			if (ispc98)
53439006Skato				machine = "pc98";
53539006Skato		}
53639006Skato	}
53739006Skato
53839006Skato	/*
5395814Sjkh	 * Get the name of this type of MACHINE from utsname
5405814Sjkh	 * so we can share an executable for similar machines.
5415814Sjkh	 * (i.e. m68k: amiga hp300, mac68k, sun3, ...)
5425814Sjkh	 *
5435814Sjkh	 * Note that while MACHINE is decided at run-time,
5445814Sjkh	 * MACHINE_ARCH is always known at compile time.
5455814Sjkh	 */
54618864Ssteve	if (!machine) {
54718339Sswallace#ifndef MACHINE
54818730Ssteve	    struct utsname utsname;
54918730Ssteve
55094506Scharnier	    if (uname(&utsname) == -1)
55194506Scharnier		    err(2, "uname");
5525814Sjkh	    machine = utsname.machine;
55318339Sswallace#else
55418339Sswallace	    machine = MACHINE;
55518339Sswallace#endif
5565814Sjkh	}
5571590Srgrimes
55844362Simp	if (!machine_arch) {
55944362Simp#ifndef MACHINE_ARCH
56044362Simp		machine_arch = "unknown";
56144362Simp#else
56244362Simp		machine_arch = MACHINE_ARCH;
56344362Simp#endif
56444362Simp	}
56544362Simp
5661590Srgrimes	/*
56772679Skris	 * Set machine_cpu to the minumum supported CPU revision based
56872679Skris	 * on the target architecture, if not already set.
56972679Skris	 */
57072679Skris	if (!machine_cpu) {
57172679Skris		if (!strcmp(machine_arch, "i386"))
57272679Skris			machine_cpu = "i386";
57372679Skris		else if (!strcmp(machine_arch, "alpha"))
57472679Skris			machine_cpu = "ev4";
57572679Skris		else
57672679Skris			machine_cpu = "unknown";
57772679Skris	}
5781590Srgrimes
5791590Srgrimes	create = Lst_Init(FALSE);
5801590Srgrimes	makefiles = Lst_Init(FALSE);
58149332Shoek	envFirstVars = Lst_Init(FALSE);
58266365Speter	expandVars = TRUE;
58317193Sbde	variables = Lst_Init(FALSE);
5841590Srgrimes	beSilent = FALSE;		/* Print commands as executed */
5851590Srgrimes	ignoreErrors = FALSE;		/* Pay attention to non-zero returns */
5861590Srgrimes	noExecute = FALSE;		/* Execute all commands */
5871590Srgrimes	keepgoing = FALSE;		/* Stop on error */
5881590Srgrimes	allPrecious = FALSE;		/* Remove targets when interrupted */
5891590Srgrimes	queryFlag = FALSE;		/* This is not just a check-run */
5901590Srgrimes	noBuiltins = FALSE;		/* Read the built-in rules */
5911590Srgrimes	touchFlag = FALSE;		/* Actually update targets */
5921590Srgrimes	usePipes = TRUE;		/* Catch child output in pipes */
5931590Srgrimes	debug = 0;			/* No debug verbosity, please. */
5941590Srgrimes	jobsRunning = FALSE;
5951590Srgrimes
59618730Ssteve	maxLocal = DEFMAXLOCAL;		/* Set default local max concurrency */
59718730Ssteve#ifdef REMOTE
5981590Srgrimes	maxJobs = DEFMAXJOBS;		/* Set default max concurrency */
5991590Srgrimes#else
60018730Ssteve	maxJobs = maxLocal;
6011590Srgrimes#endif
60228228Sfsmp	forceJobs = FALSE;              /* No -j flag */
60318730Ssteve	compatMake = FALSE;		/* No compat mode */
6041590Srgrimes
6058874Srgrimes
6061590Srgrimes	/*
6071590Srgrimes	 * Initialize the parsing, directory and variable modules to prepare
6081590Srgrimes	 * for the reading of inclusion paths and variable settings on the
6091590Srgrimes	 * command line
6101590Srgrimes	 */
6111590Srgrimes	Dir_Init();		/* Initialize directory structures so -I flags
6121590Srgrimes				 * can be processed correctly */
6131590Srgrimes	Parse_Init();		/* Need to initialize the paths of #include
6141590Srgrimes				 * directories */
6151590Srgrimes	Var_Init();		/* As well as the lists of variables for
6161590Srgrimes				 * parsing arguments */
6175814Sjkh        str_init();
6181590Srgrimes
6191590Srgrimes	/*
6201590Srgrimes	 * Initialize various variables.
6211590Srgrimes	 *	MAKE also gets this name, for compatibility
6221590Srgrimes	 *	.MAKEFLAGS gets set to the empty string just in case.
6231590Srgrimes	 *	MFLAGS also gets initialized empty, for compatibility.
6241590Srgrimes	 */
6251590Srgrimes	Var_Set("MAKE", argv[0], VAR_GLOBAL);
6261590Srgrimes	Var_Set(MAKEFLAGS, "", VAR_GLOBAL);
6271590Srgrimes	Var_Set("MFLAGS", "", VAR_GLOBAL);
6285814Sjkh	Var_Set("MACHINE", machine, VAR_GLOBAL);
62944362Simp	Var_Set("MACHINE_ARCH", machine_arch, VAR_GLOBAL);
63072679Skris	Var_Set("MACHINE_CPU", machine_cpu, VAR_GLOBAL);
63197121Sru#ifdef MAKE_VERSION
63297121Sru	Var_Set("MAKE_VERSION", MAKE_VERSION, VAR_GLOBAL);
63397121Sru#endif
6341590Srgrimes
6351590Srgrimes	/*
6361590Srgrimes	 * First snag any flags out of the MAKE environment variable.
6371590Srgrimes	 * (Note this is *not* MAKEFLAGS since /bin/make uses that and it's
6381590Srgrimes	 * in a different format).
6391590Srgrimes	 */
6401590Srgrimes#ifdef POSIX
6411590Srgrimes	Main_ParseArgLine(getenv("MAKEFLAGS"));
6421590Srgrimes#else
6431590Srgrimes	Main_ParseArgLine(getenv("MAKE"));
6441590Srgrimes#endif
6458874Srgrimes
6461590Srgrimes	MainParseArgs(argc, argv);
6471590Srgrimes
648133085Sharti#ifdef POSIX
649133085Sharti	Var_AddCmdLine(MAKEFLAGS);
650133085Sharti#endif
651133085Sharti
6521590Srgrimes	/*
653120053Sru	 * Find where we are...
654120053Sru	 * All this code is so that we know where we are when we start up
655120053Sru	 * on a different machine with pmake.
656120053Sru	 */
657120053Sru	curdir = cdpath;
658120053Sru	if (getcwd(curdir, MAXPATHLEN) == NULL)
659120053Sru		err(2, NULL);
660120053Sru
661120053Sru	if (stat(curdir, &sa) == -1)
662120053Sru	    err(2, "%s", curdir);
663120053Sru
664120053Sru	/*
665120053Sru	 * The object directory location is determined using the
666120053Sru	 * following order of preference:
667120053Sru	 *
668120053Sru	 *	1. MAKEOBJDIRPREFIX`cwd`
669120053Sru	 *	2. MAKEOBJDIR
670120053Sru	 *	3. _PATH_OBJDIR.${MACHINE}
671120053Sru	 *	4. _PATH_OBJDIR
672120053Sru	 *	5. _PATH_OBJDIRPREFIX`cwd`
673120053Sru	 *
674120053Sru	 * If one of the first two fails, use the current directory.
675120053Sru	 * If the remaining three all fail, use the current directory.
676120053Sru	 *
677120053Sru	 * Once things are initted,
678120053Sru	 * have to add the original directory to the search path,
679120053Sru	 * and modify the paths for the Makefiles apropriately.  The
680120053Sru	 * current directory is also placed as a variable for make scripts.
681120053Sru	 */
682120053Sru	if (!(pathp = getenv("MAKEOBJDIRPREFIX"))) {
683120053Sru		if (!(path = getenv("MAKEOBJDIR"))) {
684120053Sru			path = _PATH_OBJDIR;
685120053Sru			pathp = _PATH_OBJDIRPREFIX;
686120053Sru			(void) snprintf(mdpath, MAXPATHLEN, "%s.%s",
687120053Sru					path, machine);
688120053Sru			if (!(objdir = chdir_verify_path(mdpath, obpath)))
689120053Sru				if (!(objdir=chdir_verify_path(path, obpath))) {
690120053Sru					(void) snprintf(mdpath, MAXPATHLEN,
691120053Sru							"%s%s", pathp, curdir);
692120053Sru					if (!(objdir=chdir_verify_path(mdpath,
693120053Sru								       obpath)))
694120053Sru						objdir = curdir;
695120053Sru				}
696120053Sru		}
697120053Sru		else if (!(objdir = chdir_verify_path(path, obpath)))
698120053Sru			objdir = curdir;
699120053Sru	}
700120053Sru	else {
701120053Sru		(void) snprintf(mdpath, MAXPATHLEN, "%s%s", pathp, curdir);
702120053Sru		if (!(objdir = chdir_verify_path(mdpath, obpath)))
703120053Sru			objdir = curdir;
704120053Sru	}
705120053Sru	Dir_InitDot();		/* Initialize the "." directory */
706120053Sru	if (objdir != curdir)
707120053Sru		Dir_AddDir(dirSearchPath, curdir);
708120053Sru	Var_Set(".CURDIR", curdir, VAR_GLOBAL);
709120053Sru	Var_Set(".OBJDIR", objdir, VAR_GLOBAL);
710120053Sru
711120053Sru	/*
71228228Sfsmp	 * Be compatible if user did not specify -j and did not explicitly
71328228Sfsmp	 * turned compatibility on
71428228Sfsmp	 */
71528228Sfsmp	if (!compatMake && !forceJobs)
71628228Sfsmp		compatMake = TRUE;
71728228Sfsmp
71828228Sfsmp	/*
7191590Srgrimes	 * Initialize archive, target and suffix modules in preparation for
7201590Srgrimes	 * parsing the makefile(s)
7211590Srgrimes	 */
7221590Srgrimes	Arch_Init();
7231590Srgrimes	Targ_Init();
7241590Srgrimes	Suff_Init();
7251590Srgrimes
72669527Swill	DEFAULT = NULL;
7271590Srgrimes	(void)time(&now);
7281590Srgrimes
7291590Srgrimes	/*
7301590Srgrimes	 * Set up the .TARGETS variable to contain the list of targets to be
7311590Srgrimes	 * created. If none specified, make the variable empty -- the parser
7321590Srgrimes	 * will fill the thing in with the default or .MAIN target.
7331590Srgrimes	 */
7341590Srgrimes	if (!Lst_IsEmpty(create)) {
7351590Srgrimes		LstNode ln;
7361590Srgrimes
73769527Swill		for (ln = Lst_First(create); ln != NULL;
7381590Srgrimes		    ln = Lst_Succ(ln)) {
7391590Srgrimes			char *name = (char *)Lst_Datum(ln);
7401590Srgrimes
7411590Srgrimes			Var_Append(".TARGETS", name, VAR_GLOBAL);
7421590Srgrimes		}
7431590Srgrimes	} else
7441590Srgrimes		Var_Set(".TARGETS", "", VAR_GLOBAL);
7451590Srgrimes
74618730Ssteve
7471590Srgrimes	/*
74818730Ssteve	 * If no user-supplied system path was given (through the -m option)
74918730Ssteve	 * add the directories from the DEFSYSPATH (more than one may be given
75018730Ssteve	 * as dir1:...:dirn) to the system include path.
7511590Srgrimes	 */
75218730Ssteve	if (Lst_IsEmpty(sysIncPath)) {
75318730Ssteve		for (start = syspath; *start != '\0'; start = cp) {
75418730Ssteve			for (cp = start; *cp != '\0' && *cp != ':'; cp++)
75518730Ssteve				continue;
75618730Ssteve			if (*cp == '\0') {
75718730Ssteve				Dir_AddDir(sysIncPath, start);
75818730Ssteve			} else {
75918730Ssteve				*cp++ = '\0';
76018730Ssteve				Dir_AddDir(sysIncPath, start);
76118730Ssteve			}
76218730Ssteve		}
76318730Ssteve	}
7641590Srgrimes
76518730Ssteve	/*
76618730Ssteve	 * Read in the built-in rules first, followed by the specified
76718730Ssteve	 * makefile, if it was (makefile != (char *) NULL), or the default
76818730Ssteve	 * Makefile and makefile, in that order, if it wasn't.
76918730Ssteve	 */
77018730Ssteve	if (!noBuiltins) {
77118730Ssteve		LstNode ln;
77218730Ssteve
77318730Ssteve		sysMkPath = Lst_Init (FALSE);
77418730Ssteve		Dir_Expand (_PATH_DEFSYSMK, sysIncPath, sysMkPath);
77518730Ssteve		if (Lst_IsEmpty(sysMkPath))
77618730Ssteve			Fatal("make: no system rules (%s).", _PATH_DEFSYSMK);
77769531Swill		ln = Lst_Find(sysMkPath, (void *)NULL, ReadMakefile);
77869527Swill		if (ln != NULL)
77918730Ssteve			Fatal("make: cannot open %s.", (char *)Lst_Datum(ln));
78018730Ssteve	}
78118730Ssteve
7821590Srgrimes	if (!Lst_IsEmpty(makefiles)) {
7831590Srgrimes		LstNode ln;
7841590Srgrimes
78569531Swill		ln = Lst_Find(makefiles, (void *)NULL, ReadMakefile);
78669527Swill		if (ln != NULL)
7871590Srgrimes			Fatal("make: cannot open %s.", (char *)Lst_Datum(ln));
78894594Sobrien	} else if (!ReadMakefile("BSDmakefile", NULL))
78994594Sobrien	    if (!ReadMakefile("makefile", NULL))
79018730Ssteve		(void)ReadMakefile("Makefile", NULL);
7911590Srgrimes
79218730Ssteve	(void)ReadMakefile(".depend", NULL);
7931590Srgrimes
7941590Srgrimes	/* Install all the flags into the MAKE envariable. */
7955814Sjkh	if (((p = Var_Value(MAKEFLAGS, VAR_GLOBAL, &p1)) != NULL) && *p)
7961590Srgrimes#ifdef POSIX
7971590Srgrimes		setenv("MAKEFLAGS", p, 1);
7981590Srgrimes#else
7991590Srgrimes		setenv("MAKE", p, 1);
8001590Srgrimes#endif
801105826Sjmallett	free(p1);
8021590Srgrimes
8031590Srgrimes	/*
8041590Srgrimes	 * For compatibility, look at the directories in the VPATH variable
8051590Srgrimes	 * and add them to the search path, if the variable is defined. The
8061590Srgrimes	 * variable's value is in the same format as the PATH envariable, i.e.
8071590Srgrimes	 * <directory>:<directory>:<directory>...
8081590Srgrimes	 */
8091590Srgrimes	if (Var_Exists("VPATH", VAR_CMD)) {
810104692Sjmallett		char *vpath, savec;
8111590Srgrimes		/*
8121590Srgrimes		 * GCC stores string constants in read-only memory, but
8131590Srgrimes		 * Var_Subst will want to write this thing, so store it
8141590Srgrimes		 * in an array
8151590Srgrimes		 */
8161590Srgrimes		static char VPATH[] = "${VPATH}";
8171590Srgrimes
8181590Srgrimes		vpath = Var_Subst(NULL, VPATH, VAR_CMD, FALSE);
819104692Sjmallett		path = vpath;
8201590Srgrimes		do {
8211590Srgrimes			/* skip to end of directory */
822104692Sjmallett			for (cp = path; *cp != ':' && *cp != '\0'; cp++)
8231590Srgrimes				continue;
8241590Srgrimes			/* Save terminator character so know when to stop */
825104692Sjmallett			savec = *cp;
826104692Sjmallett			*cp = '\0';
8271590Srgrimes			/* Add directory to search path */
828104692Sjmallett			Dir_AddDir(dirSearchPath, path);
829104692Sjmallett			*cp = savec;
830104692Sjmallett			path = cp + 1;
8311590Srgrimes		} while (savec == ':');
83269531Swill		(void)free(vpath);
8331590Srgrimes	}
8341590Srgrimes
8351590Srgrimes	/*
8361590Srgrimes	 * Now that all search paths have been read for suffixes et al, it's
8371590Srgrimes	 * time to add the default search path to their lists...
8381590Srgrimes	 */
8391590Srgrimes	Suff_DoPaths();
8401590Srgrimes
8411590Srgrimes	/* print the initial graph, if the user requested it */
8421590Srgrimes	if (DEBUG(GRAPH1))
8431590Srgrimes		Targ_PrintGraph(1);
8441590Srgrimes
84517193Sbde	/* print the values of any variables requested by the user */
846101460Sru	if (!Lst_IsEmpty(variables)) {
84717193Sbde		LstNode ln;
84817193Sbde
84969527Swill		for (ln = Lst_First(variables); ln != NULL;
85017193Sbde		    ln = Lst_Succ(ln)) {
85166365Speter			char *value;
85266365Speter			if (expandVars) {
85394506Scharnier				p1 = emalloc(strlen((char *)Lst_Datum(ln)) + 1 + 3);
85466365Speter				/* This sprintf is safe, because of the malloc above */
85566365Speter				(void)sprintf(p1, "${%s}", (char *)Lst_Datum(ln));
85666365Speter				value = Var_Subst(NULL, p1, VAR_GLOBAL, FALSE);
85766365Speter			} else {
85866365Speter				value = Var_Value((char *)Lst_Datum(ln),
85966365Speter						  VAR_GLOBAL, &p1);
86066365Speter			}
86117193Sbde			printf("%s\n", value ? value : "");
86266365Speter			if (p1)
86366365Speter				free(p1);
86417193Sbde		}
865101460Sru	} else {
86617193Sbde
8671590Srgrimes		/*
868101460Sru		 * Have now read the entire graph and need to make a list of targets
869101460Sru		 * to create. If none was given on the command line, we consult the
870101460Sru		 * parsing module to find the main target(s) to create.
8711590Srgrimes		 */
872101460Sru		if (Lst_IsEmpty(create))
873101460Sru			targs = Parse_MainName();
874101460Sru		else
875101460Sru			targs = Targ_FindList(create, TARG_CREATE);
876101460Sru
877101460Sru		if (!compatMake) {
878101460Sru			/*
879101460Sru			 * Initialize job module before traversing the graph, now that
880101460Sru			 * any .BEGIN and .END targets have been read.  This is done
881101460Sru			 * only if the -q flag wasn't given (to prevent the .BEGIN from
882101460Sru			 * being executed should it exist).
883101460Sru			 */
884101460Sru			if (!queryFlag) {
885101460Sru				if (maxLocal == -1)
886101460Sru					maxLocal = maxJobs;
887101460Sru				Job_Init(maxJobs, maxLocal);
888101460Sru				jobsRunning = TRUE;
889101460Sru			}
890101460Sru
891101460Sru			/* Traverse the graph, checking on all the targets */
892101460Sru			outOfDate = Make_Run(targs);
893101460Sru		} else {
894101460Sru			/*
895101460Sru			 * Compat_Init will take care of creating all the targets as
896101460Sru			 * well as initializing the module.
897101460Sru			 */
898101460Sru			Compat_Run(targs);
899120718Sru			outOfDate = 0;
9001590Srgrimes		}
901101672Sru		Lst_Destroy(targs, NOFREE);
90217193Sbde	}
9038874Srgrimes
90417193Sbde	Lst_Destroy(variables, NOFREE);
9055814Sjkh	Lst_Destroy(makefiles, NOFREE);
90692921Simp	Lst_Destroy(create, (void (*)(void *)) free);
9075814Sjkh
9081590Srgrimes	/* print the graph now it's been processed if the user requested it */
9091590Srgrimes	if (DEBUG(GRAPH2))
9101590Srgrimes		Targ_PrintGraph(2);
9111590Srgrimes
9125814Sjkh	Suff_End();
9135814Sjkh        Targ_End();
9145814Sjkh	Arch_End();
9155814Sjkh	str_end();
9165814Sjkh	Var_End();
9175814Sjkh	Parse_End();
9185814Sjkh	Dir_End();
9195814Sjkh
9201590Srgrimes	if (queryFlag && outOfDate)
9211590Srgrimes		return(1);
9221590Srgrimes	else
9231590Srgrimes		return(0);
9241590Srgrimes}
9251590Srgrimes
9261590Srgrimes/*-
9271590Srgrimes * ReadMakefile  --
9281590Srgrimes *	Open and parse the given makefile.
9291590Srgrimes *
9301590Srgrimes * Results:
9311590Srgrimes *	TRUE if ok. FALSE if couldn't open file.
9321590Srgrimes *
9331590Srgrimes * Side Effects:
9341590Srgrimes *	lots
9351590Srgrimes */
9361590Srgrimesstatic Boolean
937104696SjmallettReadMakefile(void *p, void *q __unused)
9381590Srgrimes{
939104696Sjmallett	char *fname;			/* makefile to read */
9401590Srgrimes	FILE *stream;
94173262Simp	char *name, path[MAXPATHLEN];
94297163Sjmallett	char *MAKEFILE;
94394990Sru	int setMAKEFILE;
9441590Srgrimes
945104696Sjmallett	fname = p;
946104696Sjmallett
9471590Srgrimes	if (!strcmp(fname, "-")) {
9481590Srgrimes		Parse_File("(stdin)", stdin);
9491590Srgrimes		Var_Set("MAKEFILE", "", VAR_GLOBAL);
9501590Srgrimes	} else {
95194990Sru		setMAKEFILE = strcmp(fname, ".depend");
95294990Sru
9531590Srgrimes		/* if we've chdir'd, rebuild the path name */
9541590Srgrimes		if (curdir != objdir && *fname != '/') {
95569390Swill			(void)snprintf(path, MAXPATHLEN, "%s/%s", curdir, fname);
956100733Simp			/*
957100733Simp			 * XXX The realpath stuff breaks relative includes
958100733Simp			 * XXX in some cases.   The problem likely is in
959100733Simp			 * XXX parse.c where it does special things in
960100733Simp			 * XXX ParseDoInclude if the file is relateive
961100733Simp			 * XXX or absolute and not a system file.  There
962100733Simp			 * XXX it assumes that if the current file that's
963100733Simp			 * XXX being included is absolute, that any files
964100733Simp			 * XXX that it includes shouldn't do the -I path
965100733Simp			 * XXX stuff, which is inconsistant with historical
966100733Simp			 * XXX behavior.  However, I can't pentrate the mists
967100733Simp			 * XXX further, so I'm putting this workaround in
968100733Simp			 * XXX here until such time as the underlying bug
969100733Simp			 * XXX can be fixed.
970100733Simp			 */
971100733Simp#if THIS_BREAKS_THINGS
97297077Sjmallett			if (realpath(path, path) != NULL &&
97397077Sjmallett			    (stream = fopen(path, "r")) != NULL) {
97497163Sjmallett				MAKEFILE = fname;
9751590Srgrimes				fname = path;
9761590Srgrimes				goto found;
9771590Srgrimes			}
97897077Sjmallett		} else if (realpath(fname, path) != NULL) {
97997163Sjmallett			MAKEFILE = fname;
98097077Sjmallett			fname = path;
98197077Sjmallett			if ((stream = fopen(fname, "r")) != NULL)
98297077Sjmallett				goto found;
98397077Sjmallett		}
984100733Simp#else
985100733Simp			if ((stream = fopen(path, "r")) != NULL) {
986100733Simp				MAKEFILE = fname;
987100733Simp				fname = path;
988100733Simp				goto found;
989100733Simp			}
990100733Simp		} else {
991100733Simp			MAKEFILE = fname;
992100733Simp			if ((stream = fopen(fname, "r")) != NULL)
993100733Simp				goto found;
994100733Simp		}
995100733Simp#endif
9961590Srgrimes		/* look in -I and system include directories. */
9971590Srgrimes		name = Dir_FindFile(fname, parseIncPath);
9981590Srgrimes		if (!name)
9991590Srgrimes			name = Dir_FindFile(fname, sysIncPath);
10001590Srgrimes		if (!name || !(stream = fopen(name, "r")))
10011590Srgrimes			return(FALSE);
100297163Sjmallett		MAKEFILE = fname = name;
10031590Srgrimes		/*
10041590Srgrimes		 * set the MAKEFILE variable desired by System V fans -- the
10051590Srgrimes		 * placement of the setting here means it gets set to the last
10061590Srgrimes		 * makefile specified, as it is set by SysV make.
10071590Srgrimes		 */
100894990Srufound:
100994990Sru		if (setMAKEFILE)
101097163Sjmallett			Var_Set("MAKEFILE", MAKEFILE, VAR_GLOBAL);
10111590Srgrimes		Parse_File(fname, stream);
10121590Srgrimes		(void)fclose(stream);
10131590Srgrimes	}
10141590Srgrimes	return(TRUE);
10151590Srgrimes}
10161590Srgrimes
10171590Srgrimes/*-
101818730Ssteve * Cmd_Exec --
101918730Ssteve *	Execute the command in cmd, and return the output of that command
102018730Ssteve *	in a string.
102118730Ssteve *
102218730Ssteve * Results:
102318730Ssteve *	A string containing the output of the command, or the empty string
1024104121Sjmallett *	If error is not NULL, it contains the reason for the command failure
102518730Ssteve *
102618730Ssteve * Side Effects:
102718730Ssteve *	The string must be freed by the caller.
102818730Ssteve */
102918730Sstevechar *
1030104696SjmallettCmd_Exec(char *cmd, char **error)
103118730Ssteve{
103218730Ssteve    char	*args[4];   	/* Args for invoking the shell */
103318730Ssteve    int 	fds[2];	    	/* Pipe streams */
103418730Ssteve    int 	cpid;	    	/* Child PID */
103518730Ssteve    int 	pid;	    	/* PID from wait() */
103618730Ssteve    char	*res;		/* result */
103718730Ssteve    int		status;		/* command exit status */
103818730Ssteve    Buffer	buf;		/* buffer to store the result */
103918730Ssteve    char	*cp;
104018730Ssteve    int		cc;
104118730Ssteve
1042104121Sjmallett    *error = NULL;
104318730Ssteve
104418730Ssteve    /*
104518730Ssteve     * Set up arguments for shell
104618730Ssteve     */
104718730Ssteve    args[0] = "sh";
104818730Ssteve    args[1] = "-c";
104918730Ssteve    args[2] = cmd;
105018730Ssteve    args[3] = NULL;
105118730Ssteve
105218730Ssteve    /*
105318730Ssteve     * Open a pipe for fetching its output
105418730Ssteve     */
105518730Ssteve    if (pipe(fds) == -1) {
1056104121Sjmallett	*error = "Couldn't create pipe for \"%s\"";
105718730Ssteve	goto bad;
105818730Ssteve    }
105918730Ssteve
106018730Ssteve    /*
106118730Ssteve     * Fork
106218730Ssteve     */
106318730Ssteve    switch (cpid = vfork()) {
106418730Ssteve    case 0:
106518730Ssteve	/*
106618730Ssteve	 * Close input side of pipe
106718730Ssteve	 */
106818730Ssteve	(void) close(fds[0]);
106918730Ssteve
107018730Ssteve	/*
107118730Ssteve	 * Duplicate the output stream to the shell's output, then
107218730Ssteve	 * shut the extra thing down. Note we don't fetch the error
107318730Ssteve	 * stream...why not? Why?
107418730Ssteve	 */
107518730Ssteve	(void) dup2(fds[1], 1);
107618730Ssteve	(void) close(fds[1]);
107718730Ssteve
1078104123Sjmallett#if defined(DEFSHELL) && DEFSHELL == 0
1079104123Sjmallett	(void) execv("/bin/csh", args);
1080104123Sjmallett#elif DEFSHELL == 1
108197251Sru	(void) execv("/bin/sh", args);
108264739Sgreen#elif DEFSHELL == 2
108397251Sru	(void) execv("/bin/ksh", args);
108464739Sgreen#else
108564739Sgreen#error "DEFSHELL must be 1 or 2."
108664739Sgreen#endif
108718730Ssteve	_exit(1);
108818730Ssteve	/*NOTREACHED*/
108918730Ssteve
109018730Ssteve    case -1:
1091104121Sjmallett	*error = "Couldn't exec \"%s\"";
109218730Ssteve	goto bad;
109318730Ssteve
109418730Ssteve    default:
109518730Ssteve	/*
109618730Ssteve	 * No need for the writing half
109718730Ssteve	 */
109818730Ssteve	(void) close(fds[1]);
109918730Ssteve
110018730Ssteve	buf = Buf_Init (MAKE_BSIZE);
110118730Ssteve
110218730Ssteve	do {
110318730Ssteve	    char   result[BUFSIZ];
110418730Ssteve	    cc = read(fds[0], result, sizeof(result));
110518730Ssteve	    if (cc > 0)
110618730Ssteve		Buf_AddBytes(buf, cc, (Byte *) result);
110718730Ssteve	}
110818730Ssteve	while (cc > 0 || (cc == -1 && errno == EINTR));
110918730Ssteve
111018730Ssteve	/*
111118730Ssteve	 * Close the input side of the pipe.
111218730Ssteve	 */
111318730Ssteve	(void) close(fds[0]);
111418730Ssteve
111518730Ssteve	/*
111618730Ssteve	 * Wait for the process to exit.
111718730Ssteve	 */
111818730Ssteve	while(((pid = wait(&status)) != cpid) && (pid >= 0))
111918730Ssteve	    continue;
112018730Ssteve
112118877Ssteve	if (cc == -1)
1122104121Sjmallett	    *error = "Error reading shell's output for \"%s\"";
112318864Ssteve
112418730Ssteve	res = (char *)Buf_GetAll (buf, &cc);
112518730Ssteve	Buf_Destroy (buf, FALSE);
112618730Ssteve
112718730Ssteve	if (status)
1128104121Sjmallett	    *error = "\"%s\" returned non-zero status";
112918730Ssteve
113018730Ssteve	/*
113118730Ssteve	 * Null-terminate the result, convert newlines to spaces and
113218730Ssteve	 * install it in the variable.
113318730Ssteve	 */
113418730Ssteve	res[cc] = '\0';
113518730Ssteve	cp = &res[cc] - 1;
113618730Ssteve
113718730Ssteve	if (*cp == '\n') {
113818730Ssteve	    /*
113918730Ssteve	     * A final newline is just stripped
114018730Ssteve	     */
114118730Ssteve	    *cp-- = '\0';
114218730Ssteve	}
114318730Ssteve	while (cp >= res) {
114418730Ssteve	    if (*cp == '\n') {
114518730Ssteve		*cp = ' ';
114618730Ssteve	    }
114718730Ssteve	    cp--;
114818730Ssteve	}
114918730Ssteve	break;
115018730Ssteve    }
115118730Ssteve    return res;
115218730Sstevebad:
115318730Ssteve    res = emalloc(1);
115418730Ssteve    *res = '\0';
115518730Ssteve    return res;
115618730Ssteve}
115718730Ssteve
11581590Srgrimes/*
11591590Srgrimes * usage --
11601590Srgrimes *	exit with usage message
11611590Srgrimes */
11621590Srgrimesstatic void
1163104696Sjmallettusage(void)
11641590Srgrimes{
116527644Scharnier	(void)fprintf(stderr, "%s\n%s\n%s\n",
1166113512Sru"usage: make [-BPSXeiknqrstv] [-C directory] [-D variable] [-d flags]",
1167113512Sru"            [-E variable] [-f makefile] [-I directory] [-j max_jobs]",
1168113512Sru"            [-m directory] [-V variable] [variable=value] [target ...]");
11691590Srgrimes	exit(2);
11701590Srgrimes}
1171