main.c revision 73262
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
4262833Swsanchez#include <sys/cdefs.h>
4362835Sache__COPYRIGHT("@(#) Copyright (c) 1988, 1989, 1990, 1993  The Regents of the University of California.  All rights reserved.");
4462833Swsanchez__RCSID("$FreeBSD: head/usr.bin/make/main.c 73262 2001-03-01 06:03:17Z imp $");
451590Srgrimes#endif /* not lint */
461590Srgrimes
471590Srgrimes/*-
481590Srgrimes * main.c --
491590Srgrimes *	The main file for this entire program. Exit routines etc
501590Srgrimes *	reside here.
511590Srgrimes *
521590Srgrimes * Utility functions defined in this file:
531590Srgrimes *	Main_ParseArgLine	Takes a line of arguments, breaks them and
541590Srgrimes *				treats them as if they were given when first
551590Srgrimes *				invoked. Used by the parse module to implement
561590Srgrimes *				the .MFLAGS target.
571590Srgrimes *
581590Srgrimes *	Error			Print a tagged error message. The global
591590Srgrimes *				MAKE variable must have been defined. This
601590Srgrimes *				takes a format string and two optional
611590Srgrimes *				arguments for it.
621590Srgrimes *
631590Srgrimes *	Fatal			Print an error message and exit. Also takes
641590Srgrimes *				a format string and two arguments.
651590Srgrimes *
661590Srgrimes *	Punt			Aborts all jobs and exits with a message. Also
671590Srgrimes *				takes a format string and two arguments.
681590Srgrimes *
691590Srgrimes *	Finish			Finish things up by printing the number of
701590Srgrimes *				errors which occured, as passed to it, and
711590Srgrimes *				exiting.
721590Srgrimes */
731590Srgrimes
741590Srgrimes#include <sys/types.h>
751590Srgrimes#include <sys/time.h>
761590Srgrimes#include <sys/param.h>
771590Srgrimes#include <sys/resource.h>
781590Srgrimes#include <sys/signal.h>
791590Srgrimes#include <sys/stat.h>
8039006Skato#if defined(__i386__)
8139006Skato#include <sys/sysctl.h>
8239006Skato#endif
8318730Ssteve#ifndef MACHINE
845814Sjkh#include <sys/utsname.h>
8518730Ssteve#endif
8618730Ssteve#include <sys/wait.h>
8727644Scharnier#include <err.h>
8829957Simp#include <stdlib.h>
891590Srgrimes#include <errno.h>
901590Srgrimes#include <fcntl.h>
911590Srgrimes#include <stdio.h>
9249331Shoek#include <sysexits.h>
9349938Shoek#ifdef __STDC__
941590Srgrimes#include <stdarg.h>
951590Srgrimes#else
961590Srgrimes#include <varargs.h>
971590Srgrimes#endif
9863955Simp#include <unistd.h>
991590Srgrimes#include "make.h"
1001590Srgrimes#include "hash.h"
1011590Srgrimes#include "dir.h"
1021590Srgrimes#include "job.h"
1031590Srgrimes#include "pathnames.h"
1041590Srgrimes
1051590Srgrimes#ifndef	DEFMAXLOCAL
1061590Srgrimes#define	DEFMAXLOCAL DEFMAXJOBS
10718730Ssteve#endif	/* DEFMAXLOCAL */
1081590Srgrimes
1091590Srgrimes#define	MAKEFLAGS	".MAKEFLAGS"
1101590Srgrimes
1111590SrgrimesLst			create;		/* Targets to be made */
1121590Srgrimestime_t			now;		/* Time at start of make */
1131590SrgrimesGNode			*DEFAULT;	/* .DEFAULT node */
1141590SrgrimesBoolean			allPrecious;	/* .PRECIOUS given on line by itself */
1151590Srgrimes
1161590Srgrimesstatic Boolean		noBuiltins;	/* -r flag */
1171590Srgrimesstatic Lst		makefiles;	/* ordered list of makefiles to read */
11817193Sbdestatic Boolean		printVars;	/* print value of one or more vars */
11966365Speterstatic Boolean		expandVars;	/* fully expand printed variables */
12017193Sbdestatic Lst		variables;	/* list of variables to print */
12118730Ssteveint			maxJobs;	/* -j argument */
12228228Sfsmpstatic Boolean          forceJobs;      /* -j argument given */
1231590Srgrimesstatic int		maxLocal;	/* -L argument */
1241590SrgrimesBoolean			compatMake;	/* -B argument */
1251590SrgrimesBoolean			debug;		/* -d flag */
1261590SrgrimesBoolean			noExecute;	/* -n flag */
1271590SrgrimesBoolean			keepgoing;	/* -k flag */
1281590SrgrimesBoolean			queryFlag;	/* -q flag */
1291590SrgrimesBoolean			touchFlag;	/* -t flag */
1301590SrgrimesBoolean			usePipes;	/* !-P flag */
1311590SrgrimesBoolean			ignoreErrors;	/* -i flag */
1321590SrgrimesBoolean			beSilent;	/* -s flag */
13341151SdgBoolean			beVerbose;	/* -v flag */
1341590SrgrimesBoolean			oldVars;	/* variable substitution style */
1351590SrgrimesBoolean			checkEnvFirst;	/* -e flag */
13649332ShoekLst			envFirstVars;	/* (-E) vars to override from env */
1371590Srgrimesstatic Boolean		jobsRunning;	/* TRUE if the jobs might be running */
1381590Srgrimes
13918730Sstevestatic void		MainParseArgs __P((int, char **));
14018730Sstevechar *			chdir_verify_path __P((char *, char *));
14169531Swillstatic int		ReadMakefile __P((void *, void *));
14218730Sstevestatic void		usage __P((void));
1431590Srgrimes
1441590Srgrimesstatic char *curdir;			/* startup directory */
1451590Srgrimesstatic char *objdir;			/* where we chdir'ed to */
1461590Srgrimes
1471590Srgrimes/*-
1481590Srgrimes * MainParseArgs --
1491590Srgrimes *	Parse a given argument vector. Called from main() and from
1501590Srgrimes *	Main_ParseArgLine() when the .MAKEFLAGS target is used.
1511590Srgrimes *
1521590Srgrimes *	XXX: Deal with command line overriding .MAKEFLAGS in makefile
1531590Srgrimes *
1541590Srgrimes * Results:
1551590Srgrimes *	None
1561590Srgrimes *
1571590Srgrimes * Side Effects:
1581590Srgrimes *	Various global and local flags will be set depending on the flags
1591590Srgrimes *	given
1601590Srgrimes */
1611590Srgrimesstatic void
1621590SrgrimesMainParseArgs(argc, argv)
1631590Srgrimes	int argc;
1641590Srgrimes	char **argv;
1651590Srgrimes{
16636942Speter	char *p;
1675814Sjkh	int c;
1681590Srgrimes
1691590Srgrimes	optind = 1;	/* since we're called more than once */
17018730Ssteve#ifdef REMOTE
17166365Speter# define OPTFLAGS "BD:E:I:L:PSV:Xd:ef:ij:km:nqrstv"
1721590Srgrimes#else
17366365Speter# define OPTFLAGS "BD:E:I:PSV:Xd:ef:ij:km:nqrstv"
1741590Srgrimes#endif
17524360Simprearg:	while((c = getopt(argc, argv, OPTFLAGS)) != -1) {
1761590Srgrimes		switch(c) {
1771590Srgrimes		case 'D':
1781590Srgrimes			Var_Set(optarg, "1", VAR_GLOBAL);
1791590Srgrimes			Var_Append(MAKEFLAGS, "-D", VAR_GLOBAL);
1801590Srgrimes			Var_Append(MAKEFLAGS, optarg, VAR_GLOBAL);
1811590Srgrimes			break;
1821590Srgrimes		case 'I':
1831590Srgrimes			Parse_AddIncludeDir(optarg);
1841590Srgrimes			Var_Append(MAKEFLAGS, "-I", VAR_GLOBAL);
1851590Srgrimes			Var_Append(MAKEFLAGS, optarg, VAR_GLOBAL);
1861590Srgrimes			break;
18717193Sbde		case 'V':
18817193Sbde			printVars = TRUE;
18969531Swill			(void)Lst_AtEnd(variables, (void *)optarg);
19017193Sbde			Var_Append(MAKEFLAGS, "-V", VAR_GLOBAL);
19117193Sbde			Var_Append(MAKEFLAGS, optarg, VAR_GLOBAL);
19217193Sbde			break;
19366365Speter		case 'X':
19466365Speter			expandVars = FALSE;
19566365Speter			break;
1961590Srgrimes		case 'B':
1971590Srgrimes			compatMake = TRUE;
19828746Sfsmp			Var_Append(MAKEFLAGS, "-B", VAR_GLOBAL);
1991590Srgrimes			break;
20018730Ssteve#ifdef REMOTE
20149331Shoek		case 'L': {
20249331Shoek			char *endptr;
20349331Shoek
20449331Shoek			maxLocal = strtol(optarg, &endptr, 10);
20549331Shoek			if (maxLocal < 0 || *endptr != '\0') {
20649938Shoek				warnx("illegal number, -L argument -- %s",
20749938Shoek				    optarg);
20849938Shoek				usage();
20949331Shoek			}
2101590Srgrimes			Var_Append(MAKEFLAGS, "-L", VAR_GLOBAL);
2111590Srgrimes			Var_Append(MAKEFLAGS, optarg, VAR_GLOBAL);
2121590Srgrimes			break;
21349331Shoek		}
21418730Ssteve#endif
2151590Srgrimes		case 'P':
2161590Srgrimes			usePipes = FALSE;
2171590Srgrimes			Var_Append(MAKEFLAGS, "-P", VAR_GLOBAL);
2181590Srgrimes			break;
2191590Srgrimes		case 'S':
2201590Srgrimes			keepgoing = FALSE;
2211590Srgrimes			Var_Append(MAKEFLAGS, "-S", VAR_GLOBAL);
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				}
2751590Srgrimes			Var_Append(MAKEFLAGS, "-d", VAR_GLOBAL);
2761590Srgrimes			Var_Append(MAKEFLAGS, optarg, VAR_GLOBAL);
2771590Srgrimes			break;
2781590Srgrimes		}
27949332Shoek		case 'E':
28049332Shoek			p = malloc(strlen(optarg) + 1);
28149332Shoek			if (!p)
28249332Shoek				Punt("make: cannot allocate memory.");
28349332Shoek			(void)strcpy(p, optarg);
28469531Swill			(void)Lst_AtEnd(envFirstVars, (void *)p);
28549332Shoek			Var_Append(MAKEFLAGS, "-E", VAR_GLOBAL);
28649332Shoek			Var_Append(MAKEFLAGS, optarg, VAR_GLOBAL);
28749332Shoek			break;
2881590Srgrimes		case 'e':
2891590Srgrimes			checkEnvFirst = TRUE;
2901590Srgrimes			Var_Append(MAKEFLAGS, "-e", VAR_GLOBAL);
2911590Srgrimes			break;
2921590Srgrimes		case 'f':
29369531Swill			(void)Lst_AtEnd(makefiles, (void *)optarg);
2941590Srgrimes			break;
2951590Srgrimes		case 'i':
2961590Srgrimes			ignoreErrors = TRUE;
2971590Srgrimes			Var_Append(MAKEFLAGS, "-i", VAR_GLOBAL);
2981590Srgrimes			break;
29949331Shoek		case 'j': {
30049331Shoek			char *endptr;
30149331Shoek
30218730Ssteve			forceJobs = TRUE;
30349331Shoek			maxJobs = strtol(optarg, &endptr, 10);
30449331Shoek			if (maxJobs <= 0 || *endptr != '\0') {
30549938Shoek				warnx("illegal number, -j argument -- %s",
30649938Shoek				    optarg);
30749938Shoek				usage();
30849331Shoek			}
30918730Ssteve#ifndef REMOTE
31018730Ssteve			maxLocal = maxJobs;
31118730Ssteve#endif
3121590Srgrimes			Var_Append(MAKEFLAGS, "-j", VAR_GLOBAL);
3131590Srgrimes			Var_Append(MAKEFLAGS, optarg, VAR_GLOBAL);
3141590Srgrimes			break;
31549331Shoek		}
3161590Srgrimes		case 'k':
3171590Srgrimes			keepgoing = TRUE;
3181590Srgrimes			Var_Append(MAKEFLAGS, "-k", VAR_GLOBAL);
3191590Srgrimes			break;
32018730Ssteve		case 'm':
32118730Ssteve			Dir_AddDir(sysIncPath, optarg);
32218730Ssteve			Var_Append(MAKEFLAGS, "-m", VAR_GLOBAL);
32318730Ssteve			Var_Append(MAKEFLAGS, optarg, VAR_GLOBAL);
32418730Ssteve			break;
3251590Srgrimes		case 'n':
3261590Srgrimes			noExecute = TRUE;
3271590Srgrimes			Var_Append(MAKEFLAGS, "-n", VAR_GLOBAL);
3281590Srgrimes			break;
3291590Srgrimes		case 'q':
3301590Srgrimes			queryFlag = TRUE;
3311590Srgrimes			/* Kind of nonsensical, wot? */
3321590Srgrimes			Var_Append(MAKEFLAGS, "-q", VAR_GLOBAL);
3331590Srgrimes			break;
3341590Srgrimes		case 'r':
3351590Srgrimes			noBuiltins = TRUE;
3361590Srgrimes			Var_Append(MAKEFLAGS, "-r", VAR_GLOBAL);
3371590Srgrimes			break;
3381590Srgrimes		case 's':
3391590Srgrimes			beSilent = TRUE;
3401590Srgrimes			Var_Append(MAKEFLAGS, "-s", VAR_GLOBAL);
3411590Srgrimes			break;
3421590Srgrimes		case 't':
3431590Srgrimes			touchFlag = TRUE;
3441590Srgrimes			Var_Append(MAKEFLAGS, "-t", VAR_GLOBAL);
3451590Srgrimes			break;
34641151Sdg		case 'v':
34741151Sdg			beVerbose = TRUE;
34841151Sdg			Var_Append(MAKEFLAGS, "-v", VAR_GLOBAL);
34941151Sdg			break;
3501590Srgrimes		default:
3511590Srgrimes		case '?':
3521590Srgrimes			usage();
3531590Srgrimes		}
3541590Srgrimes	}
3551590Srgrimes
3561590Srgrimes	oldVars = TRUE;
3571590Srgrimes
3581590Srgrimes	/*
3591590Srgrimes	 * See if the rest of the arguments are variable assignments and
3601590Srgrimes	 * perform them if so. Else take them to be targets and stuff them
3611590Srgrimes	 * on the end of the "create" list.
3621590Srgrimes	 */
3631590Srgrimes	for (argv += optind, argc -= optind; *argv; ++argv, --argc)
3641590Srgrimes		if (Parse_IsVar(*argv))
3651590Srgrimes			Parse_DoVar(*argv, VAR_CMD);
3661590Srgrimes		else {
3671590Srgrimes			if (!**argv)
3681590Srgrimes				Punt("illegal (null) argument.");
3691590Srgrimes			if (**argv == '-') {
3701590Srgrimes				if ((*argv)[1])
3711590Srgrimes					optind = 0;     /* -flag... */
3721590Srgrimes				else
3731590Srgrimes					optind = 1;     /* - */
3741590Srgrimes				goto rearg;
3751590Srgrimes			}
37669531Swill			(void)Lst_AtEnd(create, (void *)estrdup(*argv));
3771590Srgrimes		}
3781590Srgrimes}
3791590Srgrimes
3801590Srgrimes/*-
3811590Srgrimes * Main_ParseArgLine --
3821590Srgrimes *  	Used by the parse module when a .MFLAGS or .MAKEFLAGS target
3831590Srgrimes *	is encountered and by main() when reading the .MAKEFLAGS envariable.
3841590Srgrimes *	Takes a line of arguments and breaks it into its
3851590Srgrimes * 	component words and passes those words and the number of them to the
3861590Srgrimes *	MainParseArgs function.
3871590Srgrimes *	The line should have all its leading whitespace removed.
3881590Srgrimes *
3891590Srgrimes * Results:
3901590Srgrimes *	None
3911590Srgrimes *
3921590Srgrimes * Side Effects:
3931590Srgrimes *	Only those that come from the various arguments.
3941590Srgrimes */
3951590Srgrimesvoid
3961590SrgrimesMain_ParseArgLine(line)
3971590Srgrimes	char *line;			/* Line to fracture */
3981590Srgrimes{
3991590Srgrimes	char **argv;			/* Manufactured argument vector */
4001590Srgrimes	int argc;			/* Number of arguments in argv */
4011590Srgrimes
4021590Srgrimes	if (line == NULL)
4031590Srgrimes		return;
4041590Srgrimes	for (; *line == ' '; ++line)
4051590Srgrimes		continue;
4061590Srgrimes	if (!*line)
4071590Srgrimes		return;
4081590Srgrimes
4095814Sjkh	argv = brk_string(line, &argc, TRUE);
4101590Srgrimes	MainParseArgs(argc, argv);
4111590Srgrimes}
4121590Srgrimes
41318339Sswallacechar *
41418339Sswallacechdir_verify_path(path, obpath)
41518339Sswallace	char *path;
41618339Sswallace	char *obpath;
41718339Sswallace{
41818339Sswallace	struct stat sb;
41918339Sswallace
42018339Sswallace	if (stat(path, &sb) == 0 && S_ISDIR(sb.st_mode)) {
42118339Sswallace		if (chdir(path)) {
42227644Scharnier			warn("warning: %s", path);
42318339Sswallace			return 0;
42418339Sswallace		}
42518339Sswallace		else {
42618339Sswallace			if (path[0] != '/') {
42718339Sswallace				(void) snprintf(obpath, MAXPATHLEN, "%s/%s",
42818339Sswallace						curdir, path);
42918339Sswallace				return obpath;
43018339Sswallace			}
43118339Sswallace			else
43218339Sswallace				return path;
43318339Sswallace		}
43418339Sswallace	}
43518339Sswallace
43618339Sswallace	return 0;
43718339Sswallace}
43818339Sswallace
43918339Sswallace
4401590Srgrimes/*-
4411590Srgrimes * main --
4421590Srgrimes *	The main function, for obvious reasons. Initializes variables
4431590Srgrimes *	and a few modules, then parses the arguments give it in the
4441590Srgrimes *	environment and on the command line. Reads the system makefile
4451590Srgrimes *	followed by either Makefile, makefile or the file given by the
4461590Srgrimes *	-f argument. Sets the .MAKEFLAGS PMake variable based on all the
4471590Srgrimes *	flags it has received by then uses either the Make or the Compat
4481590Srgrimes *	module to create the initial list of targets.
4491590Srgrimes *
4501590Srgrimes * Results:
4511590Srgrimes *	If -q was given, exits -1 if anything was out-of-date. Else it exits
4521590Srgrimes *	0.
4531590Srgrimes *
4541590Srgrimes * Side Effects:
4551590Srgrimes *	The program exits when done. Targets are created. etc. etc. etc.
4561590Srgrimes */
4571590Srgrimesint
4581590Srgrimesmain(argc, argv)
4591590Srgrimes	int argc;
4601590Srgrimes	char **argv;
4611590Srgrimes{
4621590Srgrimes	Lst targs;	/* target nodes to create -- passed to Make_Init */
4631590Srgrimes	Boolean outOfDate = TRUE; 	/* FALSE if all targets up to date */
46440500Sobrien	struct stat sa;
46540500Sobrien	char *p, *p1, *path, *pathp;
46640500Sobrien#ifdef WANT_ENV_PWD
46740500Sobrien	struct stat sb;
46840500Sobrien	char *pwd;
46940500Sobrien#endif
47073262Simp	char mdpath[MAXPATHLEN];
47173262Simp	char obpath[MAXPATHLEN];
47273262Simp	char cdpath[MAXPATHLEN];
4735814Sjkh    	char *machine = getenv("MACHINE");
47444362Simp	char *machine_arch = getenv("MACHINE_ARCH");
47572679Skris	char *machine_cpu = getenv("MACHINE_CPU");
47618730Ssteve	Lst sysMkPath;			/* Path of sys.mk */
47718730Ssteve	char *cp = NULL, *start;
47818730Ssteve					/* avoid faults on read-only strings */
47918730Ssteve	static char syspath[] = _PATH_DEFSYSPATH;
4801590Srgrimes
48164739Sgreen#if DEFSHELL == 2
48264739Sgreen	/*
48364739Sgreen	 * Turn off ENV to make ksh happier.
48464739Sgreen	 */
48564739Sgreen	unsetenv("ENV");
48664739Sgreen#endif
48764739Sgreen
48818730Ssteve#ifdef RLIMIT_NOFILE
4891590Srgrimes	/*
49018730Ssteve	 * get rid of resource limit on file descriptors
49118730Ssteve	 */
49218730Ssteve	{
49318730Ssteve		struct rlimit rl;
49418730Ssteve		if (getrlimit(RLIMIT_NOFILE, &rl) != -1 &&
49518730Ssteve		    rl.rlim_cur != rl.rlim_max) {
49618730Ssteve			rl.rlim_cur = rl.rlim_max;
49718730Ssteve			(void) setrlimit(RLIMIT_NOFILE, &rl);
49818730Ssteve		}
49918730Ssteve	}
50018730Ssteve#endif
50118730Ssteve	/*
5021590Srgrimes	 * Find where we are and take care of PWD for the automounter...
5031590Srgrimes	 * All this code is so that we know where we are when we start up
5041590Srgrimes	 * on a different machine with pmake.
5051590Srgrimes	 */
5061590Srgrimes	curdir = cdpath;
50727644Scharnier	if (getcwd(curdir, MAXPATHLEN) == NULL)
50827644Scharnier		err(2, NULL);
5091590Srgrimes
51027644Scharnier	if (stat(curdir, &sa) == -1)
51127644Scharnier	    err(2, "%s", curdir);
5121590Srgrimes
51340500Sobrien#ifdef WANT_ENV_PWD
51416885Sjkh	if ((pwd = getenv("PWD")) != NULL) {
51516885Sjkh	    if (stat(pwd, &sb) == 0 && sa.st_ino == sb.st_ino &&
51616885Sjkh		sa.st_dev == sb.st_dev)
51716885Sjkh		(void) strcpy(curdir, pwd);
51816885Sjkh	}
51940500Sobrien#endif
52016885Sjkh
52153631Smarcel#if defined(__i386__) && defined(__FreeBSD_version) && \
52253631Smarcel    __FreeBSD_version > 300003
5235814Sjkh	/*
52439006Skato	 * PC-98 kernel sets the `i386' string to the utsname.machine and
52539006Skato	 * it cannot be distinguished from IBM-PC by uname(3).  Therefore,
52639006Skato	 * we check machine.ispc98 and adjust the machine variable before
52739006Skato	 * using usname(3) below.
52853631Smarcel	 * NOTE: machdep.ispc98 was defined on 1998/8/31. At that time,
52953631Smarcel	 * __FreeBSD_version was defined as 300003. So, this check can
53053631Smarcel	 * safely be done with any kernel with version > 300003.
53139006Skato	 */
53239006Skato	if (!machine) {
53339006Skato		int	ispc98;
53439006Skato		size_t	len;
53539006Skato
53639006Skato		len = sizeof(ispc98);
53739006Skato		if (!sysctlbyname("machdep.ispc98", &ispc98, &len, NULL, 0)) {
53839006Skato			if (ispc98)
53939006Skato				machine = "pc98";
54039006Skato		}
54139006Skato	}
54239006Skato#endif
54339006Skato
54439006Skato	/*
5455814Sjkh	 * Get the name of this type of MACHINE from utsname
5465814Sjkh	 * so we can share an executable for similar machines.
5475814Sjkh	 * (i.e. m68k: amiga hp300, mac68k, sun3, ...)
5485814Sjkh	 *
5495814Sjkh	 * Note that while MACHINE is decided at run-time,
5505814Sjkh	 * MACHINE_ARCH is always known at compile time.
5515814Sjkh	 */
55218864Ssteve	if (!machine) {
55318339Sswallace#ifndef MACHINE
55418730Ssteve	    struct utsname utsname;
55518730Ssteve
55618339Sswallace	    if (uname(&utsname) == -1) {
5575814Sjkh		    perror("make: uname");
5585814Sjkh		    exit(2);
5595814Sjkh	    }
5605814Sjkh	    machine = utsname.machine;
56118339Sswallace#else
56218339Sswallace	    machine = MACHINE;
56318339Sswallace#endif
5645814Sjkh	}
5651590Srgrimes
56644362Simp	if (!machine_arch) {
56744362Simp#ifndef MACHINE_ARCH
56844362Simp		machine_arch = "unknown";
56944362Simp#else
57044362Simp		machine_arch = MACHINE_ARCH;
57144362Simp#endif
57244362Simp	}
57344362Simp
5741590Srgrimes	/*
57572679Skris	 * Set machine_cpu to the minumum supported CPU revision based
57672679Skris	 * on the target architecture, if not already set.
57772679Skris	 */
57872679Skris	if (!machine_cpu) {
57972679Skris		if (!strcmp(machine_arch, "i386"))
58072679Skris			machine_cpu = "i386";
58172679Skris		else if (!strcmp(machine_arch, "alpha"))
58272679Skris			machine_cpu = "ev4";
58372679Skris		else
58472679Skris			machine_cpu = "unknown";
58572679Skris	}
58672679Skris
58772679Skris	/*
58818759Ssteve	 * The object directory location is determined using the
58918759Ssteve	 * following order of preference:
59018759Ssteve	 *
59118759Ssteve	 *	1. MAKEOBJDIRPREFIX`cwd`
59218759Ssteve	 *	2. MAKEOBJDIR
59318759Ssteve	 *	3. _PATH_OBJDIR.${MACHINE}
59418759Ssteve	 *	4. _PATH_OBJDIR
59549938Shoek	 *	5. _PATH_OBJDIRPREFIX`cwd`
59618759Ssteve	 *
59749938Shoek	 * If one of the first two fails, use the current directory.
59849938Shoek	 * If the remaining three all fail, use the current directory.
59918339Sswallace	 *
60018339Sswallace	 * Once things are initted,
60118339Sswallace	 * have to add the original directory to the search path,
6021590Srgrimes	 * and modify the paths for the Makefiles apropriately.  The
6031590Srgrimes	 * current directory is also placed as a variable for make scripts.
6041590Srgrimes	 */
60518339Sswallace	if (!(pathp = getenv("MAKEOBJDIRPREFIX"))) {
60618339Sswallace		if (!(path = getenv("MAKEOBJDIR"))) {
60718339Sswallace			path = _PATH_OBJDIR;
60818339Sswallace			pathp = _PATH_OBJDIRPREFIX;
60918339Sswallace			(void) snprintf(mdpath, MAXPATHLEN, "%s.%s",
61018339Sswallace					path, machine);
61118339Sswallace			if (!(objdir = chdir_verify_path(mdpath, obpath)))
61218339Sswallace				if (!(objdir=chdir_verify_path(path, obpath))) {
61318339Sswallace					(void) snprintf(mdpath, MAXPATHLEN,
61418339Sswallace							"%s%s", pathp, curdir);
61518339Sswallace					if (!(objdir=chdir_verify_path(mdpath,
61618339Sswallace								       obpath)))
61718339Sswallace						objdir = curdir;
61818339Sswallace				}
61918339Sswallace		}
62018339Sswallace		else if (!(objdir = chdir_verify_path(path, obpath)))
6211590Srgrimes			objdir = curdir;
6221590Srgrimes	}
62318339Sswallace	else {
62418339Sswallace		(void) snprintf(mdpath, MAXPATHLEN, "%s%s", pathp, curdir);
62518339Sswallace		if (!(objdir = chdir_verify_path(mdpath, obpath)))
62618339Sswallace			objdir = curdir;
62718339Sswallace	}
6281590Srgrimes
62940500Sobrien#ifdef WANT_ENV_PWD
6301590Srgrimes	setenv("PWD", objdir, 1);
63140500Sobrien#endif
6321590Srgrimes
6331590Srgrimes	create = Lst_Init(FALSE);
6341590Srgrimes	makefiles = Lst_Init(FALSE);
63549332Shoek	envFirstVars = Lst_Init(FALSE);
63617193Sbde	printVars = FALSE;
63766365Speter	expandVars = TRUE;
63817193Sbde	variables = Lst_Init(FALSE);
6391590Srgrimes	beSilent = FALSE;		/* Print commands as executed */
6401590Srgrimes	ignoreErrors = FALSE;		/* Pay attention to non-zero returns */
6411590Srgrimes	noExecute = FALSE;		/* Execute all commands */
6421590Srgrimes	keepgoing = FALSE;		/* Stop on error */
6431590Srgrimes	allPrecious = FALSE;		/* Remove targets when interrupted */
6441590Srgrimes	queryFlag = FALSE;		/* This is not just a check-run */
6451590Srgrimes	noBuiltins = FALSE;		/* Read the built-in rules */
6461590Srgrimes	touchFlag = FALSE;		/* Actually update targets */
6471590Srgrimes	usePipes = TRUE;		/* Catch child output in pipes */
6481590Srgrimes	debug = 0;			/* No debug verbosity, please. */
6491590Srgrimes	jobsRunning = FALSE;
6501590Srgrimes
65118730Ssteve	maxLocal = DEFMAXLOCAL;		/* Set default local max concurrency */
65218730Ssteve#ifdef REMOTE
6531590Srgrimes	maxJobs = DEFMAXJOBS;		/* Set default max concurrency */
6541590Srgrimes#else
65518730Ssteve	maxJobs = maxLocal;
6561590Srgrimes#endif
65728228Sfsmp	forceJobs = FALSE;              /* No -j flag */
65818730Ssteve	compatMake = FALSE;		/* No compat mode */
6591590Srgrimes
6608874Srgrimes
6611590Srgrimes	/*
6621590Srgrimes	 * Initialize the parsing, directory and variable modules to prepare
6631590Srgrimes	 * for the reading of inclusion paths and variable settings on the
6641590Srgrimes	 * command line
6651590Srgrimes	 */
6661590Srgrimes	Dir_Init();		/* Initialize directory structures so -I flags
6671590Srgrimes				 * can be processed correctly */
6681590Srgrimes	Parse_Init();		/* Need to initialize the paths of #include
6691590Srgrimes				 * directories */
6701590Srgrimes	Var_Init();		/* As well as the lists of variables for
6711590Srgrimes				 * parsing arguments */
6725814Sjkh        str_init();
6731590Srgrimes	if (objdir != curdir)
6741590Srgrimes		Dir_AddDir(dirSearchPath, curdir);
6751590Srgrimes	Var_Set(".CURDIR", curdir, VAR_GLOBAL);
6761590Srgrimes	Var_Set(".OBJDIR", objdir, VAR_GLOBAL);
6771590Srgrimes
6781590Srgrimes	/*
6791590Srgrimes	 * Initialize various variables.
6801590Srgrimes	 *	MAKE also gets this name, for compatibility
6811590Srgrimes	 *	.MAKEFLAGS gets set to the empty string just in case.
6821590Srgrimes	 *	MFLAGS also gets initialized empty, for compatibility.
6831590Srgrimes	 */
6841590Srgrimes	Var_Set("MAKE", argv[0], VAR_GLOBAL);
6851590Srgrimes	Var_Set(MAKEFLAGS, "", VAR_GLOBAL);
6861590Srgrimes	Var_Set("MFLAGS", "", VAR_GLOBAL);
6875814Sjkh	Var_Set("MACHINE", machine, VAR_GLOBAL);
68844362Simp	Var_Set("MACHINE_ARCH", machine_arch, VAR_GLOBAL);
68972679Skris	Var_Set("MACHINE_CPU", machine_cpu, VAR_GLOBAL);
6901590Srgrimes
6911590Srgrimes	/*
6921590Srgrimes	 * First snag any flags out of the MAKE environment variable.
6931590Srgrimes	 * (Note this is *not* MAKEFLAGS since /bin/make uses that and it's
6941590Srgrimes	 * in a different format).
6951590Srgrimes	 */
6961590Srgrimes#ifdef POSIX
6971590Srgrimes	Main_ParseArgLine(getenv("MAKEFLAGS"));
6981590Srgrimes#else
6991590Srgrimes	Main_ParseArgLine(getenv("MAKE"));
7001590Srgrimes#endif
7018874Srgrimes
7021590Srgrimes	MainParseArgs(argc, argv);
7031590Srgrimes
7041590Srgrimes	/*
70528228Sfsmp	 * Be compatible if user did not specify -j and did not explicitly
70628228Sfsmp	 * turned compatibility on
70728228Sfsmp	 */
70828228Sfsmp	if (!compatMake && !forceJobs)
70928228Sfsmp		compatMake = TRUE;
71028228Sfsmp
71128228Sfsmp	/*
7121590Srgrimes	 * Initialize archive, target and suffix modules in preparation for
7131590Srgrimes	 * parsing the makefile(s)
7141590Srgrimes	 */
7151590Srgrimes	Arch_Init();
7161590Srgrimes	Targ_Init();
7171590Srgrimes	Suff_Init();
7181590Srgrimes
71969527Swill	DEFAULT = NULL;
7201590Srgrimes	(void)time(&now);
7211590Srgrimes
7221590Srgrimes	/*
7231590Srgrimes	 * Set up the .TARGETS variable to contain the list of targets to be
7241590Srgrimes	 * created. If none specified, make the variable empty -- the parser
7251590Srgrimes	 * will fill the thing in with the default or .MAIN target.
7261590Srgrimes	 */
7271590Srgrimes	if (!Lst_IsEmpty(create)) {
7281590Srgrimes		LstNode ln;
7291590Srgrimes
73069527Swill		for (ln = Lst_First(create); ln != NULL;
7311590Srgrimes		    ln = Lst_Succ(ln)) {
7321590Srgrimes			char *name = (char *)Lst_Datum(ln);
7331590Srgrimes
7341590Srgrimes			Var_Append(".TARGETS", name, VAR_GLOBAL);
7351590Srgrimes		}
7361590Srgrimes	} else
7371590Srgrimes		Var_Set(".TARGETS", "", VAR_GLOBAL);
7381590Srgrimes
73918730Ssteve
7401590Srgrimes	/*
74118730Ssteve	 * If no user-supplied system path was given (through the -m option)
74218730Ssteve	 * add the directories from the DEFSYSPATH (more than one may be given
74318730Ssteve	 * as dir1:...:dirn) to the system include path.
7441590Srgrimes	 */
74518730Ssteve	if (Lst_IsEmpty(sysIncPath)) {
74618730Ssteve		for (start = syspath; *start != '\0'; start = cp) {
74718730Ssteve			for (cp = start; *cp != '\0' && *cp != ':'; cp++)
74818730Ssteve				continue;
74918730Ssteve			if (*cp == '\0') {
75018730Ssteve				Dir_AddDir(sysIncPath, start);
75118730Ssteve			} else {
75218730Ssteve				*cp++ = '\0';
75318730Ssteve				Dir_AddDir(sysIncPath, start);
75418730Ssteve			}
75518730Ssteve		}
75618730Ssteve	}
7571590Srgrimes
75818730Ssteve	/*
75918730Ssteve	 * Read in the built-in rules first, followed by the specified
76018730Ssteve	 * makefile, if it was (makefile != (char *) NULL), or the default
76118730Ssteve	 * Makefile and makefile, in that order, if it wasn't.
76218730Ssteve	 */
76318730Ssteve	if (!noBuiltins) {
76418730Ssteve		LstNode ln;
76518730Ssteve
76618730Ssteve		sysMkPath = Lst_Init (FALSE);
76718730Ssteve		Dir_Expand (_PATH_DEFSYSMK, sysIncPath, sysMkPath);
76818730Ssteve		if (Lst_IsEmpty(sysMkPath))
76918730Ssteve			Fatal("make: no system rules (%s).", _PATH_DEFSYSMK);
77069531Swill		ln = Lst_Find(sysMkPath, (void *)NULL, ReadMakefile);
77169527Swill		if (ln != NULL)
77218730Ssteve			Fatal("make: cannot open %s.", (char *)Lst_Datum(ln));
77318730Ssteve	}
77418730Ssteve
7751590Srgrimes	if (!Lst_IsEmpty(makefiles)) {
7761590Srgrimes		LstNode ln;
7771590Srgrimes
77869531Swill		ln = Lst_Find(makefiles, (void *)NULL, ReadMakefile);
77969527Swill		if (ln != NULL)
7801590Srgrimes			Fatal("make: cannot open %s.", (char *)Lst_Datum(ln));
78118730Ssteve	} else if (!ReadMakefile("makefile", NULL))
78218730Ssteve		(void)ReadMakefile("Makefile", NULL);
7831590Srgrimes
78418730Ssteve	(void)ReadMakefile(".depend", NULL);
7851590Srgrimes
7865814Sjkh	Var_Append("MFLAGS", Var_Value(MAKEFLAGS, VAR_GLOBAL, &p1), VAR_GLOBAL);
78749938Shoek	efree(p1);
7881590Srgrimes
7891590Srgrimes	/* Install all the flags into the MAKE envariable. */
7905814Sjkh	if (((p = Var_Value(MAKEFLAGS, VAR_GLOBAL, &p1)) != NULL) && *p)
7911590Srgrimes#ifdef POSIX
7921590Srgrimes		setenv("MAKEFLAGS", p, 1);
7931590Srgrimes#else
7941590Srgrimes		setenv("MAKE", p, 1);
7951590Srgrimes#endif
79649938Shoek	efree(p1);
7971590Srgrimes
7981590Srgrimes	/*
7991590Srgrimes	 * For compatibility, look at the directories in the VPATH variable
8001590Srgrimes	 * and add them to the search path, if the variable is defined. The
8011590Srgrimes	 * variable's value is in the same format as the PATH envariable, i.e.
8021590Srgrimes	 * <directory>:<directory>:<directory>...
8031590Srgrimes	 */
8041590Srgrimes	if (Var_Exists("VPATH", VAR_CMD)) {
8051590Srgrimes		char *vpath, *path, *cp, savec;
8061590Srgrimes		/*
8071590Srgrimes		 * GCC stores string constants in read-only memory, but
8081590Srgrimes		 * Var_Subst will want to write this thing, so store it
8091590Srgrimes		 * in an array
8101590Srgrimes		 */
8111590Srgrimes		static char VPATH[] = "${VPATH}";
8121590Srgrimes
8131590Srgrimes		vpath = Var_Subst(NULL, VPATH, VAR_CMD, FALSE);
8141590Srgrimes		path = vpath;
8151590Srgrimes		do {
8161590Srgrimes			/* skip to end of directory */
8171590Srgrimes			for (cp = path; *cp != ':' && *cp != '\0'; cp++)
8181590Srgrimes				continue;
8191590Srgrimes			/* Save terminator character so know when to stop */
8201590Srgrimes			savec = *cp;
8211590Srgrimes			*cp = '\0';
8221590Srgrimes			/* Add directory to search path */
8231590Srgrimes			Dir_AddDir(dirSearchPath, path);
8241590Srgrimes			*cp = savec;
8251590Srgrimes			path = cp + 1;
8261590Srgrimes		} while (savec == ':');
82769531Swill		(void)free(vpath);
8281590Srgrimes	}
8291590Srgrimes
8301590Srgrimes	/*
8311590Srgrimes	 * Now that all search paths have been read for suffixes et al, it's
8321590Srgrimes	 * time to add the default search path to their lists...
8331590Srgrimes	 */
8341590Srgrimes	Suff_DoPaths();
8351590Srgrimes
8361590Srgrimes	/* print the initial graph, if the user requested it */
8371590Srgrimes	if (DEBUG(GRAPH1))
8381590Srgrimes		Targ_PrintGraph(1);
8391590Srgrimes
84017193Sbde	/* print the values of any variables requested by the user */
84117193Sbde	if (printVars) {
84217193Sbde		LstNode ln;
84317193Sbde
84469527Swill		for (ln = Lst_First(variables); ln != NULL;
84517193Sbde		    ln = Lst_Succ(ln)) {
84666365Speter			char *value;
84766365Speter			if (expandVars) {
84866365Speter				p1 = malloc(strlen((char *)Lst_Datum(ln)) + 1 + 3);
84966365Speter				if (!p1)
85066365Speter					Punt("make: cannot allocate memory.");
85166365Speter				/* This sprintf is safe, because of the malloc above */
85266365Speter				(void)sprintf(p1, "${%s}", (char *)Lst_Datum(ln));
85366365Speter				value = Var_Subst(NULL, p1, VAR_GLOBAL, FALSE);
85466365Speter			} else {
85566365Speter				value = Var_Value((char *)Lst_Datum(ln),
85666365Speter						  VAR_GLOBAL, &p1);
85766365Speter			}
85817193Sbde			printf("%s\n", value ? value : "");
85966365Speter			if (p1)
86066365Speter				free(p1);
86117193Sbde		}
86217193Sbde	}
86317193Sbde
8641590Srgrimes	/*
8651590Srgrimes	 * Have now read the entire graph and need to make a list of targets
8661590Srgrimes	 * to create. If none was given on the command line, we consult the
8671590Srgrimes	 * parsing module to find the main target(s) to create.
8681590Srgrimes	 */
8691590Srgrimes	if (Lst_IsEmpty(create))
8701590Srgrimes		targs = Parse_MainName();
8711590Srgrimes	else
8721590Srgrimes		targs = Targ_FindList(create, TARG_CREATE);
8731590Srgrimes
87417193Sbde	if (!compatMake && !printVars) {
8751590Srgrimes		/*
8761590Srgrimes		 * Initialize job module before traversing the graph, now that
8771590Srgrimes		 * any .BEGIN and .END targets have been read.  This is done
8781590Srgrimes		 * only if the -q flag wasn't given (to prevent the .BEGIN from
8791590Srgrimes		 * being executed should it exist).
8801590Srgrimes		 */
8811590Srgrimes		if (!queryFlag) {
8821590Srgrimes			if (maxLocal == -1)
8831590Srgrimes				maxLocal = maxJobs;
8841590Srgrimes			Job_Init(maxJobs, maxLocal);
8851590Srgrimes			jobsRunning = TRUE;
8861590Srgrimes		}
8871590Srgrimes
8881590Srgrimes		/* Traverse the graph, checking on all the targets */
8891590Srgrimes		outOfDate = Make_Run(targs);
89017193Sbde	} else if (!printVars) {
8911590Srgrimes		/*
8921590Srgrimes		 * Compat_Init will take care of creating all the targets as
8931590Srgrimes		 * well as initializing the module.
8941590Srgrimes		 */
8951590Srgrimes		Compat_Run(targs);
89617193Sbde	}
8978874Srgrimes
8985814Sjkh	Lst_Destroy(targs, NOFREE);
89917193Sbde	Lst_Destroy(variables, NOFREE);
9005814Sjkh	Lst_Destroy(makefiles, NOFREE);
90169531Swill	Lst_Destroy(create, (void (*) __P((void *))) free);
9025814Sjkh
9031590Srgrimes	/* print the graph now it's been processed if the user requested it */
9041590Srgrimes	if (DEBUG(GRAPH2))
9051590Srgrimes		Targ_PrintGraph(2);
9061590Srgrimes
9075814Sjkh	Suff_End();
9085814Sjkh        Targ_End();
9095814Sjkh	Arch_End();
9105814Sjkh	str_end();
9115814Sjkh	Var_End();
9125814Sjkh	Parse_End();
9135814Sjkh	Dir_End();
9145814Sjkh
9151590Srgrimes	if (queryFlag && outOfDate)
9161590Srgrimes		return(1);
9171590Srgrimes	else
9181590Srgrimes		return(0);
9191590Srgrimes}
9201590Srgrimes
9211590Srgrimes/*-
9221590Srgrimes * ReadMakefile  --
9231590Srgrimes *	Open and parse the given makefile.
9241590Srgrimes *
9251590Srgrimes * Results:
9261590Srgrimes *	TRUE if ok. FALSE if couldn't open file.
9271590Srgrimes *
9281590Srgrimes * Side Effects:
9291590Srgrimes *	lots
9301590Srgrimes */
9311590Srgrimesstatic Boolean
93218730SsteveReadMakefile(p, q)
93369531Swill	void *p;
93469531Swill	void *q;
9351590Srgrimes{
93618730Ssteve	char *fname = p;		/* makefile to read */
93718730Ssteve	extern Lst parseIncPath;
9381590Srgrimes	FILE *stream;
93973262Simp	char *name, path[MAXPATHLEN];
9401590Srgrimes
9411590Srgrimes	if (!strcmp(fname, "-")) {
9421590Srgrimes		Parse_File("(stdin)", stdin);
9431590Srgrimes		Var_Set("MAKEFILE", "", VAR_GLOBAL);
9441590Srgrimes	} else {
9451590Srgrimes		/* if we've chdir'd, rebuild the path name */
9461590Srgrimes		if (curdir != objdir && *fname != '/') {
94769390Swill			(void)snprintf(path, MAXPATHLEN, "%s/%s", curdir, fname);
9481590Srgrimes			if ((stream = fopen(path, "r")) != NULL) {
9491590Srgrimes				fname = path;
9501590Srgrimes				goto found;
9511590Srgrimes			}
95228828Sjkh		} else if ((stream = fopen(fname, "r")) != NULL)
95328828Sjkh			goto found;
9541590Srgrimes		/* look in -I and system include directories. */
9551590Srgrimes		name = Dir_FindFile(fname, parseIncPath);
9561590Srgrimes		if (!name)
9571590Srgrimes			name = Dir_FindFile(fname, sysIncPath);
9581590Srgrimes		if (!name || !(stream = fopen(name, "r")))
9591590Srgrimes			return(FALSE);
9601590Srgrimes		fname = name;
9611590Srgrimes		/*
9621590Srgrimes		 * set the MAKEFILE variable desired by System V fans -- the
9631590Srgrimes		 * placement of the setting here means it gets set to the last
9641590Srgrimes		 * makefile specified, as it is set by SysV make.
9651590Srgrimes		 */
9661590Srgrimesfound:		Var_Set("MAKEFILE", fname, VAR_GLOBAL);
9671590Srgrimes		Parse_File(fname, stream);
9681590Srgrimes		(void)fclose(stream);
9691590Srgrimes	}
9701590Srgrimes	return(TRUE);
9711590Srgrimes}
9721590Srgrimes
9731590Srgrimes/*-
97418730Ssteve * Cmd_Exec --
97518730Ssteve *	Execute the command in cmd, and return the output of that command
97618730Ssteve *	in a string.
97718730Ssteve *
97818730Ssteve * Results:
97918730Ssteve *	A string containing the output of the command, or the empty string
98018730Ssteve *	If err is not NULL, it contains the reason for the command failure
98118730Ssteve *
98218730Ssteve * Side Effects:
98318730Ssteve *	The string must be freed by the caller.
98418730Ssteve */
98518730Sstevechar *
98618730SsteveCmd_Exec(cmd, err)
98718730Ssteve    char *cmd;
98818730Ssteve    char **err;
98918730Ssteve{
99018730Ssteve    char	*args[4];   	/* Args for invoking the shell */
99118730Ssteve    int 	fds[2];	    	/* Pipe streams */
99218730Ssteve    int 	cpid;	    	/* Child PID */
99318730Ssteve    int 	pid;	    	/* PID from wait() */
99418730Ssteve    char	*res;		/* result */
99518730Ssteve    int		status;		/* command exit status */
99618730Ssteve    Buffer	buf;		/* buffer to store the result */
99718730Ssteve    char	*cp;
99818730Ssteve    int		cc;
99918730Ssteve
100018730Ssteve
100118730Ssteve    *err = NULL;
100218730Ssteve
100318730Ssteve    /*
100418730Ssteve     * Set up arguments for shell
100518730Ssteve     */
100618730Ssteve    args[0] = "sh";
100718730Ssteve    args[1] = "-c";
100818730Ssteve    args[2] = cmd;
100918730Ssteve    args[3] = NULL;
101018730Ssteve
101118730Ssteve    /*
101218730Ssteve     * Open a pipe for fetching its output
101318730Ssteve     */
101418730Ssteve    if (pipe(fds) == -1) {
101518730Ssteve	*err = "Couldn't create pipe for \"%s\"";
101618730Ssteve	goto bad;
101718730Ssteve    }
101818730Ssteve
101918730Ssteve    /*
102018730Ssteve     * Fork
102118730Ssteve     */
102218730Ssteve    switch (cpid = vfork()) {
102318730Ssteve    case 0:
102418730Ssteve	/*
102518730Ssteve	 * Close input side of pipe
102618730Ssteve	 */
102718730Ssteve	(void) close(fds[0]);
102818730Ssteve
102918730Ssteve	/*
103018730Ssteve	 * Duplicate the output stream to the shell's output, then
103118730Ssteve	 * shut the extra thing down. Note we don't fetch the error
103218730Ssteve	 * stream...why not? Why?
103318730Ssteve	 */
103418730Ssteve	(void) dup2(fds[1], 1);
103518730Ssteve	(void) close(fds[1]);
103618730Ssteve
103764739Sgreen#if DEFSHELL == 1
103818730Ssteve	(void) execv("/bin/sh", args);
103964739Sgreen#elif DEFSHELL == 2
104064739Sgreen	(void) execv("/bin/ksh", args);
104164739Sgreen#else
104264739Sgreen#error "DEFSHELL must be 1 or 2."
104364739Sgreen#endif
104418730Ssteve	_exit(1);
104518730Ssteve	/*NOTREACHED*/
104618730Ssteve
104718730Ssteve    case -1:
104818730Ssteve	*err = "Couldn't exec \"%s\"";
104918730Ssteve	goto bad;
105018730Ssteve
105118730Ssteve    default:
105218730Ssteve	/*
105318730Ssteve	 * No need for the writing half
105418730Ssteve	 */
105518730Ssteve	(void) close(fds[1]);
105618730Ssteve
105718730Ssteve	buf = Buf_Init (MAKE_BSIZE);
105818730Ssteve
105918730Ssteve	do {
106018730Ssteve	    char   result[BUFSIZ];
106118730Ssteve	    cc = read(fds[0], result, sizeof(result));
106218730Ssteve	    if (cc > 0)
106318730Ssteve		Buf_AddBytes(buf, cc, (Byte *) result);
106418730Ssteve	}
106518730Ssteve	while (cc > 0 || (cc == -1 && errno == EINTR));
106618730Ssteve
106718730Ssteve	/*
106818730Ssteve	 * Close the input side of the pipe.
106918730Ssteve	 */
107018730Ssteve	(void) close(fds[0]);
107118730Ssteve
107218730Ssteve	/*
107318730Ssteve	 * Wait for the process to exit.
107418730Ssteve	 */
107518730Ssteve	while(((pid = wait(&status)) != cpid) && (pid >= 0))
107618730Ssteve	    continue;
107718730Ssteve
107818877Ssteve	if (cc == -1)
107918877Ssteve	    *err = "Error reading shell's output for \"%s\"";
108018864Ssteve
108118730Ssteve	res = (char *)Buf_GetAll (buf, &cc);
108218730Ssteve	Buf_Destroy (buf, FALSE);
108318730Ssteve
108418730Ssteve	if (status)
108518730Ssteve	    *err = "\"%s\" returned non-zero status";
108618730Ssteve
108718730Ssteve	/*
108818730Ssteve	 * Null-terminate the result, convert newlines to spaces and
108918730Ssteve	 * install it in the variable.
109018730Ssteve	 */
109118730Ssteve	res[cc] = '\0';
109218730Ssteve	cp = &res[cc] - 1;
109318730Ssteve
109418730Ssteve	if (*cp == '\n') {
109518730Ssteve	    /*
109618730Ssteve	     * A final newline is just stripped
109718730Ssteve	     */
109818730Ssteve	    *cp-- = '\0';
109918730Ssteve	}
110018730Ssteve	while (cp >= res) {
110118730Ssteve	    if (*cp == '\n') {
110218730Ssteve		*cp = ' ';
110318730Ssteve	    }
110418730Ssteve	    cp--;
110518730Ssteve	}
110618730Ssteve	break;
110718730Ssteve    }
110818730Ssteve    return res;
110918730Sstevebad:
111018730Ssteve    res = emalloc(1);
111118730Ssteve    *res = '\0';
111218730Ssteve    return res;
111318730Ssteve}
111418730Ssteve
111518730Ssteve/*-
11161590Srgrimes * Error --
11171590Srgrimes *	Print an error message given its format.
11181590Srgrimes *
11191590Srgrimes * Results:
11201590Srgrimes *	None.
11211590Srgrimes *
11221590Srgrimes * Side Effects:
11231590Srgrimes *	The message is printed.
11241590Srgrimes */
11251590Srgrimes/* VARARGS */
11261590Srgrimesvoid
112749938Shoek#ifdef __STDC__
11285814SjkhError(char *fmt, ...)
11291590Srgrimes#else
11301590SrgrimesError(va_alist)
11311590Srgrimes	va_dcl
11321590Srgrimes#endif
11331590Srgrimes{
11341590Srgrimes	va_list ap;
113549938Shoek#ifdef __STDC__
11361590Srgrimes	va_start(ap, fmt);
11371590Srgrimes#else
11381590Srgrimes	char *fmt;
11391590Srgrimes
11401590Srgrimes	va_start(ap);
11411590Srgrimes	fmt = va_arg(ap, char *);
11421590Srgrimes#endif
11431590Srgrimes	(void)vfprintf(stderr, fmt, ap);
11441590Srgrimes	va_end(ap);
11451590Srgrimes	(void)fprintf(stderr, "\n");
11461590Srgrimes	(void)fflush(stderr);
11471590Srgrimes}
11481590Srgrimes
11491590Srgrimes/*-
11501590Srgrimes * Fatal --
11511590Srgrimes *	Produce a Fatal error message. If jobs are running, waits for them
11521590Srgrimes *	to finish.
11531590Srgrimes *
11541590Srgrimes * Results:
11551590Srgrimes *	None
11561590Srgrimes *
11571590Srgrimes * Side Effects:
11581590Srgrimes *	The program exits
11591590Srgrimes */
11601590Srgrimes/* VARARGS */
11611590Srgrimesvoid
116249938Shoek#ifdef __STDC__
11635814SjkhFatal(char *fmt, ...)
11641590Srgrimes#else
11651590SrgrimesFatal(va_alist)
11661590Srgrimes	va_dcl
11671590Srgrimes#endif
11681590Srgrimes{
11691590Srgrimes	va_list ap;
117049938Shoek#ifdef __STDC__
11711590Srgrimes	va_start(ap, fmt);
11721590Srgrimes#else
11731590Srgrimes	char *fmt;
11741590Srgrimes
11751590Srgrimes	va_start(ap);
11761590Srgrimes	fmt = va_arg(ap, char *);
11771590Srgrimes#endif
11781590Srgrimes	if (jobsRunning)
11791590Srgrimes		Job_Wait();
11801590Srgrimes
11811590Srgrimes	(void)vfprintf(stderr, fmt, ap);
11821590Srgrimes	va_end(ap);
11831590Srgrimes	(void)fprintf(stderr, "\n");
11841590Srgrimes	(void)fflush(stderr);
11851590Srgrimes
11861590Srgrimes	if (DEBUG(GRAPH2))
11871590Srgrimes		Targ_PrintGraph(2);
11881590Srgrimes	exit(2);		/* Not 1 so -q can distinguish error */
11891590Srgrimes}
11901590Srgrimes
11911590Srgrimes/*
11921590Srgrimes * Punt --
11931590Srgrimes *	Major exception once jobs are being created. Kills all jobs, prints
11941590Srgrimes *	a message and exits.
11951590Srgrimes *
11961590Srgrimes * Results:
11978874Srgrimes *	None
11981590Srgrimes *
11991590Srgrimes * Side Effects:
12001590Srgrimes *	All children are killed indiscriminately and the program Lib_Exits
12011590Srgrimes */
12021590Srgrimes/* VARARGS */
12031590Srgrimesvoid
120449938Shoek#ifdef __STDC__
12055814SjkhPunt(char *fmt, ...)
12061590Srgrimes#else
12071590SrgrimesPunt(va_alist)
12081590Srgrimes	va_dcl
12091590Srgrimes#endif
12101590Srgrimes{
12111590Srgrimes	va_list ap;
12121590Srgrimes#if __STDC__
12131590Srgrimes	va_start(ap, fmt);
12141590Srgrimes#else
12151590Srgrimes	char *fmt;
12161590Srgrimes
12171590Srgrimes	va_start(ap);
12181590Srgrimes	fmt = va_arg(ap, char *);
12191590Srgrimes#endif
12201590Srgrimes
12211590Srgrimes	(void)fprintf(stderr, "make: ");
12221590Srgrimes	(void)vfprintf(stderr, fmt, ap);
12231590Srgrimes	va_end(ap);
12241590Srgrimes	(void)fprintf(stderr, "\n");
12251590Srgrimes	(void)fflush(stderr);
12261590Srgrimes
12271590Srgrimes	DieHorribly();
12281590Srgrimes}
12291590Srgrimes
12301590Srgrimes/*-
12311590Srgrimes * DieHorribly --
12321590Srgrimes *	Exit without giving a message.
12331590Srgrimes *
12341590Srgrimes * Results:
12351590Srgrimes *	None
12361590Srgrimes *
12371590Srgrimes * Side Effects:
12381590Srgrimes *	A big one...
12391590Srgrimes */
12401590Srgrimesvoid
12411590SrgrimesDieHorribly()
12421590Srgrimes{
12431590Srgrimes	if (jobsRunning)
12441590Srgrimes		Job_AbortAll();
12451590Srgrimes	if (DEBUG(GRAPH2))
12461590Srgrimes		Targ_PrintGraph(2);
12471590Srgrimes	exit(2);		/* Not 1, so -q can distinguish error */
12481590Srgrimes}
12491590Srgrimes
12501590Srgrimes/*
12511590Srgrimes * Finish --
12521590Srgrimes *	Called when aborting due to errors in child shell to signal
12538874Srgrimes *	abnormal exit.
12541590Srgrimes *
12551590Srgrimes * Results:
12568874Srgrimes *	None
12571590Srgrimes *
12581590Srgrimes * Side Effects:
12591590Srgrimes *	The program exits
12601590Srgrimes */
12611590Srgrimesvoid
12621590SrgrimesFinish(errors)
12631590Srgrimes	int errors;	/* number of errors encountered in Make_Make */
12641590Srgrimes{
12651590Srgrimes	Fatal("%d error%s", errors, errors == 1 ? "" : "s");
12661590Srgrimes}
12671590Srgrimes
12681590Srgrimes/*
12691590Srgrimes * emalloc --
12701590Srgrimes *	malloc, but die on error.
12711590Srgrimes */
127218730Sstevevoid *
12731590Srgrimesemalloc(len)
12745814Sjkh	size_t len;
12751590Srgrimes{
127618730Ssteve	void *p;
127718730Ssteve
127818730Ssteve	if ((p = malloc(len)) == NULL)
127918730Ssteve		enomem();
128018730Ssteve	return(p);
128118730Ssteve}
128218730Ssteve
128318730Ssteve/*
128418730Ssteve * estrdup --
128518730Ssteve *	strdup, but die on error.
128618730Ssteve */
128718730Sstevechar *
128818730Ssteveestrdup(str)
128918730Ssteve	const char *str;
129018730Ssteve{
12911590Srgrimes	char *p;
12921590Srgrimes
129318730Ssteve	if ((p = strdup(str)) == NULL)
12941590Srgrimes		enomem();
12951590Srgrimes	return(p);
12961590Srgrimes}
12971590Srgrimes
12981590Srgrimes/*
129918730Ssteve * erealloc --
130018730Ssteve *	realloc, but die on error.
130118730Ssteve */
130218730Sstevevoid *
130318730Ssteveerealloc(ptr, size)
130418730Ssteve	void *ptr;
130518730Ssteve	size_t size;
130618730Ssteve{
130718730Ssteve	if ((ptr = realloc(ptr, size)) == NULL)
130818730Ssteve		enomem();
130918730Ssteve	return(ptr);
131018730Ssteve}
131118730Ssteve
131218730Ssteve/*
13131590Srgrimes * enomem --
13141590Srgrimes *	die when out of memory.
13151590Srgrimes */
13161590Srgrimesvoid
13171590Srgrimesenomem()
13181590Srgrimes{
131927644Scharnier	err(2, NULL);
13201590Srgrimes}
13211590Srgrimes
13221590Srgrimes/*
132318730Ssteve * enunlink --
132418730Ssteve *	Remove a file carefully, avoiding directories.
132518730Ssteve */
132618730Ssteveint
132718730Ssteveeunlink(file)
132818730Ssteve	const char *file;
132918730Ssteve{
133018730Ssteve	struct stat st;
133118730Ssteve
133218730Ssteve	if (lstat(file, &st) == -1)
133318730Ssteve		return -1;
133418730Ssteve
133518730Ssteve	if (S_ISDIR(st.st_mode)) {
133618730Ssteve		errno = EISDIR;
133718730Ssteve		return -1;
133818730Ssteve	}
133918730Ssteve	return unlink(file);
134018730Ssteve}
134118730Ssteve
134218730Ssteve/*
13431590Srgrimes * usage --
13441590Srgrimes *	exit with usage message
13451590Srgrimes */
13461590Srgrimesstatic void
13471590Srgrimesusage()
13481590Srgrimes{
134927644Scharnier	(void)fprintf(stderr, "%s\n%s\n%s\n",
135049332Shoek"usage: make [-Beiknqrstv] [-D variable] [-d flags] [-E variable] [-f makefile]",
135127644Scharnier"            [-I directory] [-j max_jobs] [-m directory] [-V variable]",
135227644Scharnier"            [variable=value] [target ...]");
13531590Srgrimes	exit(2);
13541590Srgrimes}
13555814Sjkh
13565814Sjkh
13575814Sjkhint
13585814SjkhPrintAddr(a, b)
135969531Swill    void * a;
136069531Swill    void * b;
13615814Sjkh{
13625814Sjkh    printf("%lx ", (unsigned long) a);
13635814Sjkh    return b ? 0 : 0;
13645814Sjkh}
1365