main.c revision 49938
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.
371590Srgrimes */
381590Srgrimes
391590Srgrimes#ifndef lint
4027644Scharnierstatic const char copyright[] =
411590Srgrimes"@(#) Copyright (c) 1988, 1989, 1990, 1993\n\
421590Srgrimes	The Regents of the University of California.  All rights reserved.\n";
431590Srgrimes#endif /* not lint */
441590Srgrimes
451590Srgrimes#ifndef lint
4627644Scharnier#if 0
471590Srgrimesstatic char sccsid[] = "@(#)main.c	8.3 (Berkeley) 3/19/94";
4849938Shoek#else
4949938Shoekstatic const char rcsid[] =
5049938Shoek	"$Id: main.c,v 1.32 1999/07/31 20:53:01 hoek Exp $";
5127644Scharnier#endif
521590Srgrimes#endif /* not lint */
531590Srgrimes
541590Srgrimes/*-
551590Srgrimes * main.c --
561590Srgrimes *	The main file for this entire program. Exit routines etc
571590Srgrimes *	reside here.
581590Srgrimes *
591590Srgrimes * Utility functions defined in this file:
601590Srgrimes *	Main_ParseArgLine	Takes a line of arguments, breaks them and
611590Srgrimes *				treats them as if they were given when first
621590Srgrimes *				invoked. Used by the parse module to implement
631590Srgrimes *				the .MFLAGS target.
641590Srgrimes *
651590Srgrimes *	Error			Print a tagged error message. The global
661590Srgrimes *				MAKE variable must have been defined. This
671590Srgrimes *				takes a format string and two optional
681590Srgrimes *				arguments for it.
691590Srgrimes *
701590Srgrimes *	Fatal			Print an error message and exit. Also takes
711590Srgrimes *				a format string and two arguments.
721590Srgrimes *
731590Srgrimes *	Punt			Aborts all jobs and exits with a message. Also
741590Srgrimes *				takes a format string and two arguments.
751590Srgrimes *
761590Srgrimes *	Finish			Finish things up by printing the number of
771590Srgrimes *				errors which occured, as passed to it, and
781590Srgrimes *				exiting.
791590Srgrimes */
801590Srgrimes
811590Srgrimes#include <sys/types.h>
821590Srgrimes#include <sys/time.h>
831590Srgrimes#include <sys/param.h>
841590Srgrimes#include <sys/resource.h>
851590Srgrimes#include <sys/signal.h>
861590Srgrimes#include <sys/stat.h>
8739006Skato#if defined(__i386__)
8839006Skato#include <sys/sysctl.h>
8939006Skato#endif
9018730Ssteve#ifndef MACHINE
915814Sjkh#include <sys/utsname.h>
9218730Ssteve#endif
9318730Ssteve#include <sys/wait.h>
9427644Scharnier#include <err.h>
9529957Simp#include <stdlib.h>
961590Srgrimes#include <errno.h>
971590Srgrimes#include <fcntl.h>
981590Srgrimes#include <stdio.h>
9949331Shoek#include <sysexits.h>
10049938Shoek#ifdef __STDC__
1011590Srgrimes#include <stdarg.h>
1021590Srgrimes#else
1031590Srgrimes#include <varargs.h>
1041590Srgrimes#endif
1051590Srgrimes#include "make.h"
1061590Srgrimes#include "hash.h"
1071590Srgrimes#include "dir.h"
1081590Srgrimes#include "job.h"
1091590Srgrimes#include "pathnames.h"
1101590Srgrimes
1111590Srgrimes#ifndef	DEFMAXLOCAL
1121590Srgrimes#define	DEFMAXLOCAL DEFMAXJOBS
11318730Ssteve#endif	/* DEFMAXLOCAL */
1141590Srgrimes
1151590Srgrimes#define	MAKEFLAGS	".MAKEFLAGS"
1161590Srgrimes
1171590SrgrimesLst			create;		/* Targets to be made */
1181590Srgrimestime_t			now;		/* Time at start of make */
1191590SrgrimesGNode			*DEFAULT;	/* .DEFAULT node */
1201590SrgrimesBoolean			allPrecious;	/* .PRECIOUS given on line by itself */
1211590Srgrimes
1221590Srgrimesstatic Boolean		noBuiltins;	/* -r flag */
1231590Srgrimesstatic Lst		makefiles;	/* ordered list of makefiles to read */
12417193Sbdestatic Boolean		printVars;	/* print value of one or more vars */
12517193Sbdestatic Lst		variables;	/* list of variables to print */
12618730Ssteveint			maxJobs;	/* -j argument */
12728228Sfsmpstatic Boolean          forceJobs;      /* -j argument given */
1281590Srgrimesstatic int		maxLocal;	/* -L argument */
1291590SrgrimesBoolean			compatMake;	/* -B argument */
1301590SrgrimesBoolean			debug;		/* -d flag */
1311590SrgrimesBoolean			noExecute;	/* -n flag */
1321590SrgrimesBoolean			keepgoing;	/* -k flag */
1331590SrgrimesBoolean			queryFlag;	/* -q flag */
1341590SrgrimesBoolean			touchFlag;	/* -t flag */
1351590SrgrimesBoolean			usePipes;	/* !-P flag */
1361590SrgrimesBoolean			ignoreErrors;	/* -i flag */
1371590SrgrimesBoolean			beSilent;	/* -s flag */
13841151SdgBoolean			beVerbose;	/* -v flag */
1391590SrgrimesBoolean			oldVars;	/* variable substitution style */
1401590SrgrimesBoolean			checkEnvFirst;	/* -e flag */
14149332ShoekLst			envFirstVars;	/* (-E) vars to override from env */
1421590Srgrimesstatic Boolean		jobsRunning;	/* TRUE if the jobs might be running */
1431590Srgrimes
14418730Sstevestatic void		MainParseArgs __P((int, char **));
14518730Sstevechar *			chdir_verify_path __P((char *, char *));
14618730Sstevestatic int		ReadMakefile __P((ClientData, ClientData));
14718730Sstevestatic void		usage __P((void));
1481590Srgrimes
1491590Srgrimesstatic char *curdir;			/* startup directory */
1501590Srgrimesstatic char *objdir;			/* where we chdir'ed to */
1511590Srgrimes
1521590Srgrimes/*-
1531590Srgrimes * MainParseArgs --
1541590Srgrimes *	Parse a given argument vector. Called from main() and from
1551590Srgrimes *	Main_ParseArgLine() when the .MAKEFLAGS target is used.
1561590Srgrimes *
1571590Srgrimes *	XXX: Deal with command line overriding .MAKEFLAGS in makefile
1581590Srgrimes *
1591590Srgrimes * Results:
1601590Srgrimes *	None
1611590Srgrimes *
1621590Srgrimes * Side Effects:
1631590Srgrimes *	Various global and local flags will be set depending on the flags
1641590Srgrimes *	given
1651590Srgrimes */
1661590Srgrimesstatic void
1671590SrgrimesMainParseArgs(argc, argv)
1681590Srgrimes	int argc;
1691590Srgrimes	char **argv;
1701590Srgrimes{
1711590Srgrimes	extern int optind;
1721590Srgrimes	extern char *optarg;
17336942Speter	char *p;
1745814Sjkh	int c;
1751590Srgrimes
1761590Srgrimes	optind = 1;	/* since we're called more than once */
17718730Ssteve#ifdef REMOTE
17849332Shoek# define OPTFLAGS "BD:E:I:L:PSV:d:ef:ij:km:nqrstv"
1791590Srgrimes#else
18049332Shoek# define OPTFLAGS "BD:E:I:PSV:d:ef:ij:km:nqrstv"
1811590Srgrimes#endif
18224360Simprearg:	while((c = getopt(argc, argv, OPTFLAGS)) != -1) {
1831590Srgrimes		switch(c) {
1841590Srgrimes		case 'D':
1851590Srgrimes			Var_Set(optarg, "1", VAR_GLOBAL);
1861590Srgrimes			Var_Append(MAKEFLAGS, "-D", VAR_GLOBAL);
1871590Srgrimes			Var_Append(MAKEFLAGS, optarg, VAR_GLOBAL);
1881590Srgrimes			break;
1891590Srgrimes		case 'I':
1901590Srgrimes			Parse_AddIncludeDir(optarg);
1911590Srgrimes			Var_Append(MAKEFLAGS, "-I", VAR_GLOBAL);
1921590Srgrimes			Var_Append(MAKEFLAGS, optarg, VAR_GLOBAL);
1931590Srgrimes			break;
19417193Sbde		case 'V':
19517193Sbde			printVars = TRUE;
19637872Simp			p = malloc(strlen(optarg) + 1 + 3);
19736942Speter			if (!p)
19836942Speter				Punt("make: cannot allocate memory.");
19937872Simp                        /* This sprintf is safe, because of the malloc above */
20037872Simp			(void)sprintf(p, "${%s}", optarg);
20136942Speter			(void)Lst_AtEnd(variables, (ClientData)p);
20217193Sbde			Var_Append(MAKEFLAGS, "-V", VAR_GLOBAL);
20317193Sbde			Var_Append(MAKEFLAGS, optarg, VAR_GLOBAL);
20417193Sbde			break;
2051590Srgrimes		case 'B':
2061590Srgrimes			compatMake = TRUE;
20728746Sfsmp			Var_Append(MAKEFLAGS, "-B", VAR_GLOBAL);
2081590Srgrimes			break;
20918730Ssteve#ifdef REMOTE
21049331Shoek		case 'L': {
21149331Shoek			char *endptr;
21249331Shoek
21349331Shoek			maxLocal = strtol(optarg, &endptr, 10);
21449331Shoek			if (maxLocal < 0 || *endptr != '\0') {
21549938Shoek				warnx("illegal number, -L argument -- %s",
21649938Shoek				    optarg);
21749938Shoek				usage();
21849331Shoek			}
2191590Srgrimes			Var_Append(MAKEFLAGS, "-L", VAR_GLOBAL);
2201590Srgrimes			Var_Append(MAKEFLAGS, optarg, VAR_GLOBAL);
2211590Srgrimes			break;
22249331Shoek		}
22318730Ssteve#endif
2241590Srgrimes		case 'P':
2251590Srgrimes			usePipes = FALSE;
2261590Srgrimes			Var_Append(MAKEFLAGS, "-P", VAR_GLOBAL);
2271590Srgrimes			break;
2281590Srgrimes		case 'S':
2291590Srgrimes			keepgoing = FALSE;
2301590Srgrimes			Var_Append(MAKEFLAGS, "-S", VAR_GLOBAL);
2311590Srgrimes			break;
2321590Srgrimes		case 'd': {
2331590Srgrimes			char *modules = optarg;
2341590Srgrimes
2351590Srgrimes			for (; *modules; ++modules)
2361590Srgrimes				switch (*modules) {
2371590Srgrimes				case 'A':
2381590Srgrimes					debug = ~0;
2391590Srgrimes					break;
2401590Srgrimes				case 'a':
2411590Srgrimes					debug |= DEBUG_ARCH;
2421590Srgrimes					break;
2431590Srgrimes				case 'c':
2441590Srgrimes					debug |= DEBUG_COND;
2451590Srgrimes					break;
2461590Srgrimes				case 'd':
2471590Srgrimes					debug |= DEBUG_DIR;
2481590Srgrimes					break;
2491590Srgrimes				case 'f':
2501590Srgrimes					debug |= DEBUG_FOR;
2511590Srgrimes					break;
2521590Srgrimes				case 'g':
2531590Srgrimes					if (modules[1] == '1') {
2541590Srgrimes						debug |= DEBUG_GRAPH1;
2551590Srgrimes						++modules;
2561590Srgrimes					}
2571590Srgrimes					else if (modules[1] == '2') {
2581590Srgrimes						debug |= DEBUG_GRAPH2;
2591590Srgrimes						++modules;
2601590Srgrimes					}
2611590Srgrimes					break;
2621590Srgrimes				case 'j':
2631590Srgrimes					debug |= DEBUG_JOB;
2641590Srgrimes					break;
2651590Srgrimes				case 'm':
2661590Srgrimes					debug |= DEBUG_MAKE;
2671590Srgrimes					break;
2681590Srgrimes				case 's':
2691590Srgrimes					debug |= DEBUG_SUFF;
2701590Srgrimes					break;
2711590Srgrimes				case 't':
2721590Srgrimes					debug |= DEBUG_TARG;
2731590Srgrimes					break;
2741590Srgrimes				case 'v':
2751590Srgrimes					debug |= DEBUG_VAR;
2761590Srgrimes					break;
2771590Srgrimes				default:
27827644Scharnier					warnx("illegal argument to d option -- %c", *modules);
2791590Srgrimes					usage();
2801590Srgrimes				}
2811590Srgrimes			Var_Append(MAKEFLAGS, "-d", VAR_GLOBAL);
2821590Srgrimes			Var_Append(MAKEFLAGS, optarg, VAR_GLOBAL);
2831590Srgrimes			break;
2841590Srgrimes		}
28549332Shoek		case 'E':
28649332Shoek			p = malloc(strlen(optarg) + 1);
28749332Shoek			if (!p)
28849332Shoek				Punt("make: cannot allocate memory.");
28949332Shoek			(void)strcpy(p, optarg);
29049332Shoek			(void)Lst_AtEnd(envFirstVars, (ClientData)p);
29149332Shoek			Var_Append(MAKEFLAGS, "-E", VAR_GLOBAL);
29249332Shoek			Var_Append(MAKEFLAGS, optarg, VAR_GLOBAL);
29349332Shoek			break;
2941590Srgrimes		case 'e':
2951590Srgrimes			checkEnvFirst = TRUE;
2961590Srgrimes			Var_Append(MAKEFLAGS, "-e", VAR_GLOBAL);
2971590Srgrimes			break;
2981590Srgrimes		case 'f':
2991590Srgrimes			(void)Lst_AtEnd(makefiles, (ClientData)optarg);
3001590Srgrimes			break;
3011590Srgrimes		case 'i':
3021590Srgrimes			ignoreErrors = TRUE;
3031590Srgrimes			Var_Append(MAKEFLAGS, "-i", VAR_GLOBAL);
3041590Srgrimes			break;
30549331Shoek		case 'j': {
30649331Shoek			char *endptr;
30749331Shoek
30818730Ssteve			forceJobs = TRUE;
30949331Shoek			maxJobs = strtol(optarg, &endptr, 10);
31049331Shoek			if (maxJobs <= 0 || *endptr != '\0') {
31149938Shoek				warnx("illegal number, -j argument -- %s",
31249938Shoek				    optarg);
31349938Shoek				usage();
31449331Shoek			}
31518730Ssteve#ifndef REMOTE
31618730Ssteve			maxLocal = maxJobs;
31718730Ssteve#endif
3181590Srgrimes			Var_Append(MAKEFLAGS, "-j", VAR_GLOBAL);
3191590Srgrimes			Var_Append(MAKEFLAGS, optarg, VAR_GLOBAL);
3201590Srgrimes			break;
32149331Shoek		}
3221590Srgrimes		case 'k':
3231590Srgrimes			keepgoing = TRUE;
3241590Srgrimes			Var_Append(MAKEFLAGS, "-k", VAR_GLOBAL);
3251590Srgrimes			break;
32618730Ssteve		case 'm':
32718730Ssteve			Dir_AddDir(sysIncPath, optarg);
32818730Ssteve			Var_Append(MAKEFLAGS, "-m", VAR_GLOBAL);
32918730Ssteve			Var_Append(MAKEFLAGS, optarg, VAR_GLOBAL);
33018730Ssteve			break;
3311590Srgrimes		case 'n':
3321590Srgrimes			noExecute = TRUE;
3331590Srgrimes			Var_Append(MAKEFLAGS, "-n", VAR_GLOBAL);
3341590Srgrimes			break;
3351590Srgrimes		case 'q':
3361590Srgrimes			queryFlag = TRUE;
3371590Srgrimes			/* Kind of nonsensical, wot? */
3381590Srgrimes			Var_Append(MAKEFLAGS, "-q", VAR_GLOBAL);
3391590Srgrimes			break;
3401590Srgrimes		case 'r':
3411590Srgrimes			noBuiltins = TRUE;
3421590Srgrimes			Var_Append(MAKEFLAGS, "-r", VAR_GLOBAL);
3431590Srgrimes			break;
3441590Srgrimes		case 's':
3451590Srgrimes			beSilent = TRUE;
3461590Srgrimes			Var_Append(MAKEFLAGS, "-s", VAR_GLOBAL);
3471590Srgrimes			break;
3481590Srgrimes		case 't':
3491590Srgrimes			touchFlag = TRUE;
3501590Srgrimes			Var_Append(MAKEFLAGS, "-t", VAR_GLOBAL);
3511590Srgrimes			break;
35241151Sdg		case 'v':
35341151Sdg			beVerbose = TRUE;
35441151Sdg			Var_Append(MAKEFLAGS, "-v", VAR_GLOBAL);
35541151Sdg			break;
3561590Srgrimes		default:
3571590Srgrimes		case '?':
3581590Srgrimes			usage();
3591590Srgrimes		}
3601590Srgrimes	}
3611590Srgrimes
3621590Srgrimes	oldVars = TRUE;
3631590Srgrimes
3641590Srgrimes	/*
3651590Srgrimes	 * See if the rest of the arguments are variable assignments and
3661590Srgrimes	 * perform them if so. Else take them to be targets and stuff them
3671590Srgrimes	 * on the end of the "create" list.
3681590Srgrimes	 */
3691590Srgrimes	for (argv += optind, argc -= optind; *argv; ++argv, --argc)
3701590Srgrimes		if (Parse_IsVar(*argv))
3711590Srgrimes			Parse_DoVar(*argv, VAR_CMD);
3721590Srgrimes		else {
3731590Srgrimes			if (!**argv)
3741590Srgrimes				Punt("illegal (null) argument.");
3751590Srgrimes			if (**argv == '-') {
3761590Srgrimes				if ((*argv)[1])
3771590Srgrimes					optind = 0;     /* -flag... */
3781590Srgrimes				else
3791590Srgrimes					optind = 1;     /* - */
3801590Srgrimes				goto rearg;
3811590Srgrimes			}
38218730Ssteve			(void)Lst_AtEnd(create, (ClientData)estrdup(*argv));
3831590Srgrimes		}
3841590Srgrimes}
3851590Srgrimes
3861590Srgrimes/*-
3871590Srgrimes * Main_ParseArgLine --
3881590Srgrimes *  	Used by the parse module when a .MFLAGS or .MAKEFLAGS target
3891590Srgrimes *	is encountered and by main() when reading the .MAKEFLAGS envariable.
3901590Srgrimes *	Takes a line of arguments and breaks it into its
3911590Srgrimes * 	component words and passes those words and the number of them to the
3921590Srgrimes *	MainParseArgs function.
3931590Srgrimes *	The line should have all its leading whitespace removed.
3941590Srgrimes *
3951590Srgrimes * Results:
3961590Srgrimes *	None
3971590Srgrimes *
3981590Srgrimes * Side Effects:
3991590Srgrimes *	Only those that come from the various arguments.
4001590Srgrimes */
4011590Srgrimesvoid
4021590SrgrimesMain_ParseArgLine(line)
4031590Srgrimes	char *line;			/* Line to fracture */
4041590Srgrimes{
4051590Srgrimes	char **argv;			/* Manufactured argument vector */
4061590Srgrimes	int argc;			/* Number of arguments in argv */
4071590Srgrimes
4081590Srgrimes	if (line == NULL)
4091590Srgrimes		return;
4101590Srgrimes	for (; *line == ' '; ++line)
4111590Srgrimes		continue;
4121590Srgrimes	if (!*line)
4131590Srgrimes		return;
4141590Srgrimes
4155814Sjkh	argv = brk_string(line, &argc, TRUE);
4161590Srgrimes	MainParseArgs(argc, argv);
4171590Srgrimes}
4181590Srgrimes
41918339Sswallacechar *
42018339Sswallacechdir_verify_path(path, obpath)
42118339Sswallace	char *path;
42218339Sswallace	char *obpath;
42318339Sswallace{
42418339Sswallace	struct stat sb;
42518339Sswallace
42618339Sswallace	if (stat(path, &sb) == 0 && S_ISDIR(sb.st_mode)) {
42718339Sswallace		if (chdir(path)) {
42827644Scharnier			warn("warning: %s", path);
42918339Sswallace			return 0;
43018339Sswallace		}
43118339Sswallace		else {
43218339Sswallace			if (path[0] != '/') {
43318339Sswallace				(void) snprintf(obpath, MAXPATHLEN, "%s/%s",
43418339Sswallace						curdir, path);
43518339Sswallace				return obpath;
43618339Sswallace			}
43718339Sswallace			else
43818339Sswallace				return path;
43918339Sswallace		}
44018339Sswallace	}
44118339Sswallace
44218339Sswallace	return 0;
44318339Sswallace}
44418339Sswallace
44518339Sswallace
4461590Srgrimes/*-
4471590Srgrimes * main --
4481590Srgrimes *	The main function, for obvious reasons. Initializes variables
4491590Srgrimes *	and a few modules, then parses the arguments give it in the
4501590Srgrimes *	environment and on the command line. Reads the system makefile
4511590Srgrimes *	followed by either Makefile, makefile or the file given by the
4521590Srgrimes *	-f argument. Sets the .MAKEFLAGS PMake variable based on all the
4531590Srgrimes *	flags it has received by then uses either the Make or the Compat
4541590Srgrimes *	module to create the initial list of targets.
4551590Srgrimes *
4561590Srgrimes * Results:
4571590Srgrimes *	If -q was given, exits -1 if anything was out-of-date. Else it exits
4581590Srgrimes *	0.
4591590Srgrimes *
4601590Srgrimes * Side Effects:
4611590Srgrimes *	The program exits when done. Targets are created. etc. etc. etc.
4621590Srgrimes */
4631590Srgrimesint
4641590Srgrimesmain(argc, argv)
4651590Srgrimes	int argc;
4661590Srgrimes	char **argv;
4671590Srgrimes{
4681590Srgrimes	Lst targs;	/* target nodes to create -- passed to Make_Init */
4691590Srgrimes	Boolean outOfDate = TRUE; 	/* FALSE if all targets up to date */
47040500Sobrien	struct stat sa;
47140500Sobrien	char *p, *p1, *path, *pathp;
47240500Sobrien#ifdef WANT_ENV_PWD
47340500Sobrien	struct stat sb;
47440500Sobrien	char *pwd;
47540500Sobrien#endif
4761590Srgrimes	char mdpath[MAXPATHLEN + 1];
4771590Srgrimes	char obpath[MAXPATHLEN + 1];
4781590Srgrimes	char cdpath[MAXPATHLEN + 1];
4795814Sjkh    	char *machine = getenv("MACHINE");
48044362Simp	char *machine_arch = getenv("MACHINE_ARCH");
48118730Ssteve	Lst sysMkPath;			/* Path of sys.mk */
48218730Ssteve	char *cp = NULL, *start;
48318730Ssteve					/* avoid faults on read-only strings */
48418730Ssteve	static char syspath[] = _PATH_DEFSYSPATH;
4851590Srgrimes
48618730Ssteve#ifdef RLIMIT_NOFILE
4871590Srgrimes	/*
48818730Ssteve	 * get rid of resource limit on file descriptors
48918730Ssteve	 */
49018730Ssteve	{
49118730Ssteve		struct rlimit rl;
49218730Ssteve		if (getrlimit(RLIMIT_NOFILE, &rl) != -1 &&
49318730Ssteve		    rl.rlim_cur != rl.rlim_max) {
49418730Ssteve			rl.rlim_cur = rl.rlim_max;
49518730Ssteve			(void) setrlimit(RLIMIT_NOFILE, &rl);
49618730Ssteve		}
49718730Ssteve	}
49818730Ssteve#endif
49918730Ssteve	/*
5001590Srgrimes	 * Find where we are and take care of PWD for the automounter...
5011590Srgrimes	 * All this code is so that we know where we are when we start up
5021590Srgrimes	 * on a different machine with pmake.
5031590Srgrimes	 */
5041590Srgrimes	curdir = cdpath;
50527644Scharnier	if (getcwd(curdir, MAXPATHLEN) == NULL)
50627644Scharnier		err(2, NULL);
5071590Srgrimes
50827644Scharnier	if (stat(curdir, &sa) == -1)
50927644Scharnier	    err(2, "%s", curdir);
5101590Srgrimes
51140500Sobrien#ifdef WANT_ENV_PWD
51216885Sjkh	if ((pwd = getenv("PWD")) != NULL) {
51316885Sjkh	    if (stat(pwd, &sb) == 0 && sa.st_ino == sb.st_ino &&
51416885Sjkh		sa.st_dev == sb.st_dev)
51516885Sjkh		(void) strcpy(curdir, pwd);
51616885Sjkh	}
51740500Sobrien#endif
51816885Sjkh
51939006Skato#if defined(__i386__)
5205814Sjkh	/*
52139006Skato	 * PC-98 kernel sets the `i386' string to the utsname.machine and
52239006Skato	 * it cannot be distinguished from IBM-PC by uname(3).  Therefore,
52339006Skato	 * we check machine.ispc98 and adjust the machine variable before
52439006Skato	 * using usname(3) below.
52539006Skato	 */
52639006Skato	if (!machine) {
52739006Skato		int	ispc98;
52839006Skato		size_t	len;
52939006Skato
53039006Skato		len = sizeof(ispc98);
53139006Skato		if (!sysctlbyname("machdep.ispc98", &ispc98, &len, NULL, 0)) {
53239006Skato			if (ispc98)
53339006Skato				machine = "pc98";
53439006Skato		}
53539006Skato	}
53639006Skato#endif
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
55018339Sswallace	    if (uname(&utsname) == -1) {
5515814Sjkh		    perror("make: uname");
5525814Sjkh		    exit(2);
5535814Sjkh	    }
5545814Sjkh	    machine = utsname.machine;
55518339Sswallace#else
55618339Sswallace	    machine = MACHINE;
55718339Sswallace#endif
5585814Sjkh	}
5591590Srgrimes
56044362Simp	if (!machine_arch) {
56144362Simp#ifndef MACHINE_ARCH
56244362Simp		machine_arch = "unknown";
56344362Simp#else
56444362Simp		machine_arch = MACHINE_ARCH;
56544362Simp#endif
56644362Simp	}
56744362Simp
5681590Srgrimes	/*
56918759Ssteve	 * The object directory location is determined using the
57018759Ssteve	 * following order of preference:
57118759Ssteve	 *
57218759Ssteve	 *	1. MAKEOBJDIRPREFIX`cwd`
57318759Ssteve	 *	2. MAKEOBJDIR
57418759Ssteve	 *	3. _PATH_OBJDIR.${MACHINE}
57518759Ssteve	 *	4. _PATH_OBJDIR
57649938Shoek	 *	5. _PATH_OBJDIRPREFIX`cwd`
57718759Ssteve	 *
57849938Shoek	 * If one of the first two fails, use the current directory.
57949938Shoek	 * If the remaining three all fail, use the current directory.
58018339Sswallace	 *
58118339Sswallace	 * Once things are initted,
58218339Sswallace	 * have to add the original directory to the search path,
5831590Srgrimes	 * and modify the paths for the Makefiles apropriately.  The
5841590Srgrimes	 * current directory is also placed as a variable for make scripts.
5851590Srgrimes	 */
58618339Sswallace	if (!(pathp = getenv("MAKEOBJDIRPREFIX"))) {
58718339Sswallace		if (!(path = getenv("MAKEOBJDIR"))) {
58818339Sswallace			path = _PATH_OBJDIR;
58918339Sswallace			pathp = _PATH_OBJDIRPREFIX;
59018339Sswallace			(void) snprintf(mdpath, MAXPATHLEN, "%s.%s",
59118339Sswallace					path, machine);
59218339Sswallace			if (!(objdir = chdir_verify_path(mdpath, obpath)))
59318339Sswallace				if (!(objdir=chdir_verify_path(path, obpath))) {
59418339Sswallace					(void) snprintf(mdpath, MAXPATHLEN,
59518339Sswallace							"%s%s", pathp, curdir);
59618339Sswallace					if (!(objdir=chdir_verify_path(mdpath,
59718339Sswallace								       obpath)))
59818339Sswallace						objdir = curdir;
59918339Sswallace				}
60018339Sswallace		}
60118339Sswallace		else if (!(objdir = chdir_verify_path(path, obpath)))
6021590Srgrimes			objdir = curdir;
6031590Srgrimes	}
60418339Sswallace	else {
60518339Sswallace		(void) snprintf(mdpath, MAXPATHLEN, "%s%s", pathp, curdir);
60618339Sswallace		if (!(objdir = chdir_verify_path(mdpath, obpath)))
60718339Sswallace			objdir = curdir;
60818339Sswallace	}
6091590Srgrimes
61040500Sobrien#ifdef WANT_ENV_PWD
6111590Srgrimes	setenv("PWD", objdir, 1);
61240500Sobrien#endif
6131590Srgrimes
6141590Srgrimes	create = Lst_Init(FALSE);
6151590Srgrimes	makefiles = Lst_Init(FALSE);
61649332Shoek	envFirstVars = Lst_Init(FALSE);
61717193Sbde	printVars = FALSE;
61817193Sbde	variables = Lst_Init(FALSE);
6191590Srgrimes	beSilent = FALSE;		/* Print commands as executed */
6201590Srgrimes	ignoreErrors = FALSE;		/* Pay attention to non-zero returns */
6211590Srgrimes	noExecute = FALSE;		/* Execute all commands */
6221590Srgrimes	keepgoing = FALSE;		/* Stop on error */
6231590Srgrimes	allPrecious = FALSE;		/* Remove targets when interrupted */
6241590Srgrimes	queryFlag = FALSE;		/* This is not just a check-run */
6251590Srgrimes	noBuiltins = FALSE;		/* Read the built-in rules */
6261590Srgrimes	touchFlag = FALSE;		/* Actually update targets */
6271590Srgrimes	usePipes = TRUE;		/* Catch child output in pipes */
6281590Srgrimes	debug = 0;			/* No debug verbosity, please. */
6291590Srgrimes	jobsRunning = FALSE;
6301590Srgrimes
63118730Ssteve	maxLocal = DEFMAXLOCAL;		/* Set default local max concurrency */
63218730Ssteve#ifdef REMOTE
6331590Srgrimes	maxJobs = DEFMAXJOBS;		/* Set default max concurrency */
6341590Srgrimes#else
63518730Ssteve	maxJobs = maxLocal;
6361590Srgrimes#endif
63728228Sfsmp	forceJobs = FALSE;              /* No -j flag */
63818730Ssteve	compatMake = FALSE;		/* No compat mode */
6391590Srgrimes
6408874Srgrimes
6411590Srgrimes	/*
6421590Srgrimes	 * Initialize the parsing, directory and variable modules to prepare
6431590Srgrimes	 * for the reading of inclusion paths and variable settings on the
6441590Srgrimes	 * command line
6451590Srgrimes	 */
6461590Srgrimes	Dir_Init();		/* Initialize directory structures so -I flags
6471590Srgrimes				 * can be processed correctly */
6481590Srgrimes	Parse_Init();		/* Need to initialize the paths of #include
6491590Srgrimes				 * directories */
6501590Srgrimes	Var_Init();		/* As well as the lists of variables for
6511590Srgrimes				 * parsing arguments */
6525814Sjkh        str_init();
6531590Srgrimes	if (objdir != curdir)
6541590Srgrimes		Dir_AddDir(dirSearchPath, curdir);
6551590Srgrimes	Var_Set(".CURDIR", curdir, VAR_GLOBAL);
6561590Srgrimes	Var_Set(".OBJDIR", objdir, VAR_GLOBAL);
6571590Srgrimes
6581590Srgrimes	/*
6591590Srgrimes	 * Initialize various variables.
6601590Srgrimes	 *	MAKE also gets this name, for compatibility
6611590Srgrimes	 *	.MAKEFLAGS gets set to the empty string just in case.
6621590Srgrimes	 *	MFLAGS also gets initialized empty, for compatibility.
6631590Srgrimes	 */
6641590Srgrimes	Var_Set("MAKE", argv[0], VAR_GLOBAL);
6651590Srgrimes	Var_Set(MAKEFLAGS, "", VAR_GLOBAL);
6661590Srgrimes	Var_Set("MFLAGS", "", VAR_GLOBAL);
6675814Sjkh	Var_Set("MACHINE", machine, VAR_GLOBAL);
66844362Simp	Var_Set("MACHINE_ARCH", machine_arch, VAR_GLOBAL);
6691590Srgrimes
6701590Srgrimes	/*
6711590Srgrimes	 * First snag any flags out of the MAKE environment variable.
6721590Srgrimes	 * (Note this is *not* MAKEFLAGS since /bin/make uses that and it's
6731590Srgrimes	 * in a different format).
6741590Srgrimes	 */
6751590Srgrimes#ifdef POSIX
6761590Srgrimes	Main_ParseArgLine(getenv("MAKEFLAGS"));
6771590Srgrimes#else
6781590Srgrimes	Main_ParseArgLine(getenv("MAKE"));
6791590Srgrimes#endif
6808874Srgrimes
6811590Srgrimes	MainParseArgs(argc, argv);
6821590Srgrimes
6831590Srgrimes	/*
68428228Sfsmp	 * Be compatible if user did not specify -j and did not explicitly
68528228Sfsmp	 * turned compatibility on
68628228Sfsmp	 */
68728228Sfsmp	if (!compatMake && !forceJobs)
68828228Sfsmp		compatMake = TRUE;
68928228Sfsmp
69028228Sfsmp	/*
6911590Srgrimes	 * Initialize archive, target and suffix modules in preparation for
6921590Srgrimes	 * parsing the makefile(s)
6931590Srgrimes	 */
6941590Srgrimes	Arch_Init();
6951590Srgrimes	Targ_Init();
6961590Srgrimes	Suff_Init();
6971590Srgrimes
6981590Srgrimes	DEFAULT = NILGNODE;
6991590Srgrimes	(void)time(&now);
7001590Srgrimes
7011590Srgrimes	/*
7021590Srgrimes	 * Set up the .TARGETS variable to contain the list of targets to be
7031590Srgrimes	 * created. If none specified, make the variable empty -- the parser
7041590Srgrimes	 * will fill the thing in with the default or .MAIN target.
7051590Srgrimes	 */
7061590Srgrimes	if (!Lst_IsEmpty(create)) {
7071590Srgrimes		LstNode ln;
7081590Srgrimes
7091590Srgrimes		for (ln = Lst_First(create); ln != NILLNODE;
7101590Srgrimes		    ln = Lst_Succ(ln)) {
7111590Srgrimes			char *name = (char *)Lst_Datum(ln);
7121590Srgrimes
7131590Srgrimes			Var_Append(".TARGETS", name, VAR_GLOBAL);
7141590Srgrimes		}
7151590Srgrimes	} else
7161590Srgrimes		Var_Set(".TARGETS", "", VAR_GLOBAL);
7171590Srgrimes
71818730Ssteve
7191590Srgrimes	/*
72018730Ssteve	 * If no user-supplied system path was given (through the -m option)
72118730Ssteve	 * add the directories from the DEFSYSPATH (more than one may be given
72218730Ssteve	 * as dir1:...:dirn) to the system include path.
7231590Srgrimes	 */
72418730Ssteve	if (Lst_IsEmpty(sysIncPath)) {
72518730Ssteve		for (start = syspath; *start != '\0'; start = cp) {
72618730Ssteve			for (cp = start; *cp != '\0' && *cp != ':'; cp++)
72718730Ssteve				continue;
72818730Ssteve			if (*cp == '\0') {
72918730Ssteve				Dir_AddDir(sysIncPath, start);
73018730Ssteve			} else {
73118730Ssteve				*cp++ = '\0';
73218730Ssteve				Dir_AddDir(sysIncPath, start);
73318730Ssteve			}
73418730Ssteve		}
73518730Ssteve	}
7361590Srgrimes
73718730Ssteve	/*
73818730Ssteve	 * Read in the built-in rules first, followed by the specified
73918730Ssteve	 * makefile, if it was (makefile != (char *) NULL), or the default
74018730Ssteve	 * Makefile and makefile, in that order, if it wasn't.
74118730Ssteve	 */
74218730Ssteve	if (!noBuiltins) {
74318730Ssteve		LstNode ln;
74418730Ssteve
74518730Ssteve		sysMkPath = Lst_Init (FALSE);
74618730Ssteve		Dir_Expand (_PATH_DEFSYSMK, sysIncPath, sysMkPath);
74718730Ssteve		if (Lst_IsEmpty(sysMkPath))
74818730Ssteve			Fatal("make: no system rules (%s).", _PATH_DEFSYSMK);
74918730Ssteve		ln = Lst_Find(sysMkPath, (ClientData)NULL, ReadMakefile);
75018730Ssteve		if (ln != NILLNODE)
75118730Ssteve			Fatal("make: cannot open %s.", (char *)Lst_Datum(ln));
75218730Ssteve	}
75318730Ssteve
7541590Srgrimes	if (!Lst_IsEmpty(makefiles)) {
7551590Srgrimes		LstNode ln;
7561590Srgrimes
7571590Srgrimes		ln = Lst_Find(makefiles, (ClientData)NULL, ReadMakefile);
7581590Srgrimes		if (ln != NILLNODE)
7591590Srgrimes			Fatal("make: cannot open %s.", (char *)Lst_Datum(ln));
76018730Ssteve	} else if (!ReadMakefile("makefile", NULL))
76118730Ssteve		(void)ReadMakefile("Makefile", NULL);
7621590Srgrimes
76318730Ssteve	(void)ReadMakefile(".depend", NULL);
7641590Srgrimes
7655814Sjkh	Var_Append("MFLAGS", Var_Value(MAKEFLAGS, VAR_GLOBAL, &p1), VAR_GLOBAL);
76649938Shoek	efree(p1);
7671590Srgrimes
7681590Srgrimes	/* Install all the flags into the MAKE envariable. */
7695814Sjkh	if (((p = Var_Value(MAKEFLAGS, VAR_GLOBAL, &p1)) != NULL) && *p)
7701590Srgrimes#ifdef POSIX
7711590Srgrimes		setenv("MAKEFLAGS", p, 1);
7721590Srgrimes#else
7731590Srgrimes		setenv("MAKE", p, 1);
7741590Srgrimes#endif
77549938Shoek	efree(p1);
7761590Srgrimes
7771590Srgrimes	/*
7781590Srgrimes	 * For compatibility, look at the directories in the VPATH variable
7791590Srgrimes	 * and add them to the search path, if the variable is defined. The
7801590Srgrimes	 * variable's value is in the same format as the PATH envariable, i.e.
7811590Srgrimes	 * <directory>:<directory>:<directory>...
7821590Srgrimes	 */
7831590Srgrimes	if (Var_Exists("VPATH", VAR_CMD)) {
7841590Srgrimes		char *vpath, *path, *cp, savec;
7851590Srgrimes		/*
7861590Srgrimes		 * GCC stores string constants in read-only memory, but
7871590Srgrimes		 * Var_Subst will want to write this thing, so store it
7881590Srgrimes		 * in an array
7891590Srgrimes		 */
7901590Srgrimes		static char VPATH[] = "${VPATH}";
7911590Srgrimes
7921590Srgrimes		vpath = Var_Subst(NULL, VPATH, VAR_CMD, FALSE);
7931590Srgrimes		path = vpath;
7941590Srgrimes		do {
7951590Srgrimes			/* skip to end of directory */
7961590Srgrimes			for (cp = path; *cp != ':' && *cp != '\0'; cp++)
7971590Srgrimes				continue;
7981590Srgrimes			/* Save terminator character so know when to stop */
7991590Srgrimes			savec = *cp;
8001590Srgrimes			*cp = '\0';
8011590Srgrimes			/* Add directory to search path */
8021590Srgrimes			Dir_AddDir(dirSearchPath, path);
8031590Srgrimes			*cp = savec;
8041590Srgrimes			path = cp + 1;
8051590Srgrimes		} while (savec == ':');
8061590Srgrimes		(void)free((Address)vpath);
8071590Srgrimes	}
8081590Srgrimes
8091590Srgrimes	/*
8101590Srgrimes	 * Now that all search paths have been read for suffixes et al, it's
8111590Srgrimes	 * time to add the default search path to their lists...
8121590Srgrimes	 */
8131590Srgrimes	Suff_DoPaths();
8141590Srgrimes
8151590Srgrimes	/* print the initial graph, if the user requested it */
8161590Srgrimes	if (DEBUG(GRAPH1))
8171590Srgrimes		Targ_PrintGraph(1);
8181590Srgrimes
81917193Sbde	/* print the values of any variables requested by the user */
82017193Sbde	if (printVars) {
82117193Sbde		LstNode ln;
82217193Sbde
82317193Sbde		for (ln = Lst_First(variables); ln != NILLNODE;
82417193Sbde		    ln = Lst_Succ(ln)) {
82536942Speter			char *value = Var_Subst(NULL, (char *)Lst_Datum(ln),
82636942Speter					  VAR_GLOBAL, FALSE);
82717193Sbde
82817193Sbde			printf("%s\n", value ? value : "");
82917193Sbde		}
83017193Sbde	}
83117193Sbde
8321590Srgrimes	/*
8331590Srgrimes	 * Have now read the entire graph and need to make a list of targets
8341590Srgrimes	 * to create. If none was given on the command line, we consult the
8351590Srgrimes	 * parsing module to find the main target(s) to create.
8361590Srgrimes	 */
8371590Srgrimes	if (Lst_IsEmpty(create))
8381590Srgrimes		targs = Parse_MainName();
8391590Srgrimes	else
8401590Srgrimes		targs = Targ_FindList(create, TARG_CREATE);
8411590Srgrimes
84217193Sbde	if (!compatMake && !printVars) {
8431590Srgrimes		/*
8441590Srgrimes		 * Initialize job module before traversing the graph, now that
8451590Srgrimes		 * any .BEGIN and .END targets have been read.  This is done
8461590Srgrimes		 * only if the -q flag wasn't given (to prevent the .BEGIN from
8471590Srgrimes		 * being executed should it exist).
8481590Srgrimes		 */
8491590Srgrimes		if (!queryFlag) {
8501590Srgrimes			if (maxLocal == -1)
8511590Srgrimes				maxLocal = maxJobs;
8521590Srgrimes			Job_Init(maxJobs, maxLocal);
8531590Srgrimes			jobsRunning = TRUE;
8541590Srgrimes		}
8551590Srgrimes
8561590Srgrimes		/* Traverse the graph, checking on all the targets */
8571590Srgrimes		outOfDate = Make_Run(targs);
85817193Sbde	} else if (!printVars) {
8591590Srgrimes		/*
8601590Srgrimes		 * Compat_Init will take care of creating all the targets as
8611590Srgrimes		 * well as initializing the module.
8621590Srgrimes		 */
8631590Srgrimes		Compat_Run(targs);
86417193Sbde	}
8658874Srgrimes
8665814Sjkh	Lst_Destroy(targs, NOFREE);
86717193Sbde	Lst_Destroy(variables, NOFREE);
8685814Sjkh	Lst_Destroy(makefiles, NOFREE);
8695814Sjkh	Lst_Destroy(create, (void (*) __P((ClientData))) free);
8705814Sjkh
8711590Srgrimes	/* print the graph now it's been processed if the user requested it */
8721590Srgrimes	if (DEBUG(GRAPH2))
8731590Srgrimes		Targ_PrintGraph(2);
8741590Srgrimes
8755814Sjkh	Suff_End();
8765814Sjkh        Targ_End();
8775814Sjkh	Arch_End();
8785814Sjkh	str_end();
8795814Sjkh	Var_End();
8805814Sjkh	Parse_End();
8815814Sjkh	Dir_End();
8825814Sjkh
8831590Srgrimes	if (queryFlag && outOfDate)
8841590Srgrimes		return(1);
8851590Srgrimes	else
8861590Srgrimes		return(0);
8871590Srgrimes}
8881590Srgrimes
8891590Srgrimes/*-
8901590Srgrimes * ReadMakefile  --
8911590Srgrimes *	Open and parse the given makefile.
8921590Srgrimes *
8931590Srgrimes * Results:
8941590Srgrimes *	TRUE if ok. FALSE if couldn't open file.
8951590Srgrimes *
8961590Srgrimes * Side Effects:
8971590Srgrimes *	lots
8981590Srgrimes */
8991590Srgrimesstatic Boolean
90018730SsteveReadMakefile(p, q)
90118730Ssteve	ClientData p, q;
9021590Srgrimes{
90318730Ssteve	char *fname = p;		/* makefile to read */
90418730Ssteve	extern Lst parseIncPath;
9051590Srgrimes	FILE *stream;
9061590Srgrimes	char *name, path[MAXPATHLEN + 1];
9071590Srgrimes
9081590Srgrimes	if (!strcmp(fname, "-")) {
9091590Srgrimes		Parse_File("(stdin)", stdin);
9101590Srgrimes		Var_Set("MAKEFILE", "", VAR_GLOBAL);
9111590Srgrimes	} else {
9121590Srgrimes		/* if we've chdir'd, rebuild the path name */
9131590Srgrimes		if (curdir != objdir && *fname != '/') {
9141590Srgrimes			(void)sprintf(path, "%s/%s", curdir, fname);
9151590Srgrimes			if ((stream = fopen(path, "r")) != NULL) {
9161590Srgrimes				fname = path;
9171590Srgrimes				goto found;
9181590Srgrimes			}
91928828Sjkh		} else if ((stream = fopen(fname, "r")) != NULL)
92028828Sjkh			goto found;
9211590Srgrimes		/* look in -I and system include directories. */
9221590Srgrimes		name = Dir_FindFile(fname, parseIncPath);
9231590Srgrimes		if (!name)
9241590Srgrimes			name = Dir_FindFile(fname, sysIncPath);
9251590Srgrimes		if (!name || !(stream = fopen(name, "r")))
9261590Srgrimes			return(FALSE);
9271590Srgrimes		fname = name;
9281590Srgrimes		/*
9291590Srgrimes		 * set the MAKEFILE variable desired by System V fans -- the
9301590Srgrimes		 * placement of the setting here means it gets set to the last
9311590Srgrimes		 * makefile specified, as it is set by SysV make.
9321590Srgrimes		 */
9331590Srgrimesfound:		Var_Set("MAKEFILE", fname, VAR_GLOBAL);
9341590Srgrimes		Parse_File(fname, stream);
9351590Srgrimes		(void)fclose(stream);
9361590Srgrimes	}
9371590Srgrimes	return(TRUE);
9381590Srgrimes}
9391590Srgrimes
9401590Srgrimes/*-
94118730Ssteve * Cmd_Exec --
94218730Ssteve *	Execute the command in cmd, and return the output of that command
94318730Ssteve *	in a string.
94418730Ssteve *
94518730Ssteve * Results:
94618730Ssteve *	A string containing the output of the command, or the empty string
94718730Ssteve *	If err is not NULL, it contains the reason for the command failure
94818730Ssteve *
94918730Ssteve * Side Effects:
95018730Ssteve *	The string must be freed by the caller.
95118730Ssteve */
95218730Sstevechar *
95318730SsteveCmd_Exec(cmd, err)
95418730Ssteve    char *cmd;
95518730Ssteve    char **err;
95618730Ssteve{
95718730Ssteve    char	*args[4];   	/* Args for invoking the shell */
95818730Ssteve    int 	fds[2];	    	/* Pipe streams */
95918730Ssteve    int 	cpid;	    	/* Child PID */
96018730Ssteve    int 	pid;	    	/* PID from wait() */
96118730Ssteve    char	*res;		/* result */
96218730Ssteve    int		status;		/* command exit status */
96318730Ssteve    Buffer	buf;		/* buffer to store the result */
96418730Ssteve    char	*cp;
96518730Ssteve    int		cc;
96618730Ssteve
96718730Ssteve
96818730Ssteve    *err = NULL;
96918730Ssteve
97018730Ssteve    /*
97118730Ssteve     * Set up arguments for shell
97218730Ssteve     */
97318730Ssteve    args[0] = "sh";
97418730Ssteve    args[1] = "-c";
97518730Ssteve    args[2] = cmd;
97618730Ssteve    args[3] = NULL;
97718730Ssteve
97818730Ssteve    /*
97918730Ssteve     * Open a pipe for fetching its output
98018730Ssteve     */
98118730Ssteve    if (pipe(fds) == -1) {
98218730Ssteve	*err = "Couldn't create pipe for \"%s\"";
98318730Ssteve	goto bad;
98418730Ssteve    }
98518730Ssteve
98618730Ssteve    /*
98718730Ssteve     * Fork
98818730Ssteve     */
98918730Ssteve    switch (cpid = vfork()) {
99018730Ssteve    case 0:
99118730Ssteve	/*
99218730Ssteve	 * Close input side of pipe
99318730Ssteve	 */
99418730Ssteve	(void) close(fds[0]);
99518730Ssteve
99618730Ssteve	/*
99718730Ssteve	 * Duplicate the output stream to the shell's output, then
99818730Ssteve	 * shut the extra thing down. Note we don't fetch the error
99918730Ssteve	 * stream...why not? Why?
100018730Ssteve	 */
100118730Ssteve	(void) dup2(fds[1], 1);
100218730Ssteve	(void) close(fds[1]);
100318730Ssteve
100418730Ssteve	(void) execv("/bin/sh", args);
100518730Ssteve	_exit(1);
100618730Ssteve	/*NOTREACHED*/
100718730Ssteve
100818730Ssteve    case -1:
100918730Ssteve	*err = "Couldn't exec \"%s\"";
101018730Ssteve	goto bad;
101118730Ssteve
101218730Ssteve    default:
101318730Ssteve	/*
101418730Ssteve	 * No need for the writing half
101518730Ssteve	 */
101618730Ssteve	(void) close(fds[1]);
101718730Ssteve
101818730Ssteve	buf = Buf_Init (MAKE_BSIZE);
101918730Ssteve
102018730Ssteve	do {
102118730Ssteve	    char   result[BUFSIZ];
102218730Ssteve	    cc = read(fds[0], result, sizeof(result));
102318730Ssteve	    if (cc > 0)
102418730Ssteve		Buf_AddBytes(buf, cc, (Byte *) result);
102518730Ssteve	}
102618730Ssteve	while (cc > 0 || (cc == -1 && errno == EINTR));
102718730Ssteve
102818730Ssteve	/*
102918730Ssteve	 * Close the input side of the pipe.
103018730Ssteve	 */
103118730Ssteve	(void) close(fds[0]);
103218730Ssteve
103318730Ssteve	/*
103418730Ssteve	 * Wait for the process to exit.
103518730Ssteve	 */
103618730Ssteve	while(((pid = wait(&status)) != cpid) && (pid >= 0))
103718730Ssteve	    continue;
103818730Ssteve
103918877Ssteve	if (cc == -1)
104018877Ssteve	    *err = "Error reading shell's output for \"%s\"";
104118864Ssteve
104218730Ssteve	res = (char *)Buf_GetAll (buf, &cc);
104318730Ssteve	Buf_Destroy (buf, FALSE);
104418730Ssteve
104518730Ssteve	if (status)
104618730Ssteve	    *err = "\"%s\" returned non-zero status";
104718730Ssteve
104818730Ssteve	/*
104918730Ssteve	 * Null-terminate the result, convert newlines to spaces and
105018730Ssteve	 * install it in the variable.
105118730Ssteve	 */
105218730Ssteve	res[cc] = '\0';
105318730Ssteve	cp = &res[cc] - 1;
105418730Ssteve
105518730Ssteve	if (*cp == '\n') {
105618730Ssteve	    /*
105718730Ssteve	     * A final newline is just stripped
105818730Ssteve	     */
105918730Ssteve	    *cp-- = '\0';
106018730Ssteve	}
106118730Ssteve	while (cp >= res) {
106218730Ssteve	    if (*cp == '\n') {
106318730Ssteve		*cp = ' ';
106418730Ssteve	    }
106518730Ssteve	    cp--;
106618730Ssteve	}
106718730Ssteve	break;
106818730Ssteve    }
106918730Ssteve    return res;
107018730Sstevebad:
107118730Ssteve    res = emalloc(1);
107218730Ssteve    *res = '\0';
107318730Ssteve    return res;
107418730Ssteve}
107518730Ssteve
107618730Ssteve/*-
10771590Srgrimes * Error --
10781590Srgrimes *	Print an error message given its format.
10791590Srgrimes *
10801590Srgrimes * Results:
10811590Srgrimes *	None.
10821590Srgrimes *
10831590Srgrimes * Side Effects:
10841590Srgrimes *	The message is printed.
10851590Srgrimes */
10861590Srgrimes/* VARARGS */
10871590Srgrimesvoid
108849938Shoek#ifdef __STDC__
10895814SjkhError(char *fmt, ...)
10901590Srgrimes#else
10911590SrgrimesError(va_alist)
10921590Srgrimes	va_dcl
10931590Srgrimes#endif
10941590Srgrimes{
10951590Srgrimes	va_list ap;
109649938Shoek#ifdef __STDC__
10971590Srgrimes	va_start(ap, fmt);
10981590Srgrimes#else
10991590Srgrimes	char *fmt;
11001590Srgrimes
11011590Srgrimes	va_start(ap);
11021590Srgrimes	fmt = va_arg(ap, char *);
11031590Srgrimes#endif
11041590Srgrimes	(void)vfprintf(stderr, fmt, ap);
11051590Srgrimes	va_end(ap);
11061590Srgrimes	(void)fprintf(stderr, "\n");
11071590Srgrimes	(void)fflush(stderr);
11081590Srgrimes}
11091590Srgrimes
11101590Srgrimes/*-
11111590Srgrimes * Fatal --
11121590Srgrimes *	Produce a Fatal error message. If jobs are running, waits for them
11131590Srgrimes *	to finish.
11141590Srgrimes *
11151590Srgrimes * Results:
11161590Srgrimes *	None
11171590Srgrimes *
11181590Srgrimes * Side Effects:
11191590Srgrimes *	The program exits
11201590Srgrimes */
11211590Srgrimes/* VARARGS */
11221590Srgrimesvoid
112349938Shoek#ifdef __STDC__
11245814SjkhFatal(char *fmt, ...)
11251590Srgrimes#else
11261590SrgrimesFatal(va_alist)
11271590Srgrimes	va_dcl
11281590Srgrimes#endif
11291590Srgrimes{
11301590Srgrimes	va_list ap;
113149938Shoek#ifdef __STDC__
11321590Srgrimes	va_start(ap, fmt);
11331590Srgrimes#else
11341590Srgrimes	char *fmt;
11351590Srgrimes
11361590Srgrimes	va_start(ap);
11371590Srgrimes	fmt = va_arg(ap, char *);
11381590Srgrimes#endif
11391590Srgrimes	if (jobsRunning)
11401590Srgrimes		Job_Wait();
11411590Srgrimes
11421590Srgrimes	(void)vfprintf(stderr, fmt, ap);
11431590Srgrimes	va_end(ap);
11441590Srgrimes	(void)fprintf(stderr, "\n");
11451590Srgrimes	(void)fflush(stderr);
11461590Srgrimes
11471590Srgrimes	if (DEBUG(GRAPH2))
11481590Srgrimes		Targ_PrintGraph(2);
11491590Srgrimes	exit(2);		/* Not 1 so -q can distinguish error */
11501590Srgrimes}
11511590Srgrimes
11521590Srgrimes/*
11531590Srgrimes * Punt --
11541590Srgrimes *	Major exception once jobs are being created. Kills all jobs, prints
11551590Srgrimes *	a message and exits.
11561590Srgrimes *
11571590Srgrimes * Results:
11588874Srgrimes *	None
11591590Srgrimes *
11601590Srgrimes * Side Effects:
11611590Srgrimes *	All children are killed indiscriminately and the program Lib_Exits
11621590Srgrimes */
11631590Srgrimes/* VARARGS */
11641590Srgrimesvoid
116549938Shoek#ifdef __STDC__
11665814SjkhPunt(char *fmt, ...)
11671590Srgrimes#else
11681590SrgrimesPunt(va_alist)
11691590Srgrimes	va_dcl
11701590Srgrimes#endif
11711590Srgrimes{
11721590Srgrimes	va_list ap;
11731590Srgrimes#if __STDC__
11741590Srgrimes	va_start(ap, fmt);
11751590Srgrimes#else
11761590Srgrimes	char *fmt;
11771590Srgrimes
11781590Srgrimes	va_start(ap);
11791590Srgrimes	fmt = va_arg(ap, char *);
11801590Srgrimes#endif
11811590Srgrimes
11821590Srgrimes	(void)fprintf(stderr, "make: ");
11831590Srgrimes	(void)vfprintf(stderr, fmt, ap);
11841590Srgrimes	va_end(ap);
11851590Srgrimes	(void)fprintf(stderr, "\n");
11861590Srgrimes	(void)fflush(stderr);
11871590Srgrimes
11881590Srgrimes	DieHorribly();
11891590Srgrimes}
11901590Srgrimes
11911590Srgrimes/*-
11921590Srgrimes * DieHorribly --
11931590Srgrimes *	Exit without giving a message.
11941590Srgrimes *
11951590Srgrimes * Results:
11961590Srgrimes *	None
11971590Srgrimes *
11981590Srgrimes * Side Effects:
11991590Srgrimes *	A big one...
12001590Srgrimes */
12011590Srgrimesvoid
12021590SrgrimesDieHorribly()
12031590Srgrimes{
12041590Srgrimes	if (jobsRunning)
12051590Srgrimes		Job_AbortAll();
12061590Srgrimes	if (DEBUG(GRAPH2))
12071590Srgrimes		Targ_PrintGraph(2);
12081590Srgrimes	exit(2);		/* Not 1, so -q can distinguish error */
12091590Srgrimes}
12101590Srgrimes
12111590Srgrimes/*
12121590Srgrimes * Finish --
12131590Srgrimes *	Called when aborting due to errors in child shell to signal
12148874Srgrimes *	abnormal exit.
12151590Srgrimes *
12161590Srgrimes * Results:
12178874Srgrimes *	None
12181590Srgrimes *
12191590Srgrimes * Side Effects:
12201590Srgrimes *	The program exits
12211590Srgrimes */
12221590Srgrimesvoid
12231590SrgrimesFinish(errors)
12241590Srgrimes	int errors;	/* number of errors encountered in Make_Make */
12251590Srgrimes{
12261590Srgrimes	Fatal("%d error%s", errors, errors == 1 ? "" : "s");
12271590Srgrimes}
12281590Srgrimes
12291590Srgrimes/*
12301590Srgrimes * emalloc --
12311590Srgrimes *	malloc, but die on error.
12321590Srgrimes */
123318730Sstevevoid *
12341590Srgrimesemalloc(len)
12355814Sjkh	size_t len;
12361590Srgrimes{
123718730Ssteve	void *p;
123818730Ssteve
123918730Ssteve	if ((p = malloc(len)) == NULL)
124018730Ssteve		enomem();
124118730Ssteve	return(p);
124218730Ssteve}
124318730Ssteve
124418730Ssteve/*
124518730Ssteve * estrdup --
124618730Ssteve *	strdup, but die on error.
124718730Ssteve */
124818730Sstevechar *
124918730Ssteveestrdup(str)
125018730Ssteve	const char *str;
125118730Ssteve{
12521590Srgrimes	char *p;
12531590Srgrimes
125418730Ssteve	if ((p = strdup(str)) == NULL)
12551590Srgrimes		enomem();
12561590Srgrimes	return(p);
12571590Srgrimes}
12581590Srgrimes
12591590Srgrimes/*
126018730Ssteve * erealloc --
126118730Ssteve *	realloc, but die on error.
126218730Ssteve */
126318730Sstevevoid *
126418730Ssteveerealloc(ptr, size)
126518730Ssteve	void *ptr;
126618730Ssteve	size_t size;
126718730Ssteve{
126818730Ssteve	if ((ptr = realloc(ptr, size)) == NULL)
126918730Ssteve		enomem();
127018730Ssteve	return(ptr);
127118730Ssteve}
127218730Ssteve
127318730Ssteve/*
12741590Srgrimes * enomem --
12751590Srgrimes *	die when out of memory.
12761590Srgrimes */
12771590Srgrimesvoid
12781590Srgrimesenomem()
12791590Srgrimes{
128027644Scharnier	err(2, NULL);
12811590Srgrimes}
12821590Srgrimes
12831590Srgrimes/*
128418730Ssteve * enunlink --
128518730Ssteve *	Remove a file carefully, avoiding directories.
128618730Ssteve */
128718730Ssteveint
128818730Ssteveeunlink(file)
128918730Ssteve	const char *file;
129018730Ssteve{
129118730Ssteve	struct stat st;
129218730Ssteve
129318730Ssteve	if (lstat(file, &st) == -1)
129418730Ssteve		return -1;
129518730Ssteve
129618730Ssteve	if (S_ISDIR(st.st_mode)) {
129718730Ssteve		errno = EISDIR;
129818730Ssteve		return -1;
129918730Ssteve	}
130018730Ssteve	return unlink(file);
130118730Ssteve}
130218730Ssteve
130318730Ssteve/*
13041590Srgrimes * usage --
13051590Srgrimes *	exit with usage message
13061590Srgrimes */
13071590Srgrimesstatic void
13081590Srgrimesusage()
13091590Srgrimes{
131027644Scharnier	(void)fprintf(stderr, "%s\n%s\n%s\n",
131149332Shoek"usage: make [-Beiknqrstv] [-D variable] [-d flags] [-E variable] [-f makefile]",
131227644Scharnier"            [-I directory] [-j max_jobs] [-m directory] [-V variable]",
131327644Scharnier"            [variable=value] [target ...]");
13141590Srgrimes	exit(2);
13151590Srgrimes}
13165814Sjkh
13175814Sjkh
13185814Sjkhint
13195814SjkhPrintAddr(a, b)
13205814Sjkh    ClientData a;
13215814Sjkh    ClientData b;
13225814Sjkh{
13235814Sjkh    printf("%lx ", (unsigned long) a);
13245814Sjkh    return b ? 0 : 0;
13255814Sjkh}
1326