1141104Sharti/*-
21590Srgrimes * Copyright (c) 1988, 1989, 1990, 1993
31590Srgrimes *	The Regents of the University of California.  All rights reserved.
41590Srgrimes * Copyright (c) 1989 by Berkeley Softworks
51590Srgrimes * All rights reserved.
61590Srgrimes *
71590Srgrimes * This code is derived from software contributed to Berkeley by
81590Srgrimes * Adam de Boor.
91590Srgrimes *
101590Srgrimes * Redistribution and use in source and binary forms, with or without
111590Srgrimes * modification, are permitted provided that the following conditions
121590Srgrimes * are met:
131590Srgrimes * 1. Redistributions of source code must retain the above copyright
141590Srgrimes *    notice, this list of conditions and the following disclaimer.
151590Srgrimes * 2. Redistributions in binary form must reproduce the above copyright
161590Srgrimes *    notice, this list of conditions and the following disclaimer in the
171590Srgrimes *    documentation and/or other materials provided with the distribution.
181590Srgrimes * 3. All advertising materials mentioning features or use of this software
191590Srgrimes *    must display the following acknowledgement:
201590Srgrimes *	This product includes software developed by the University of
211590Srgrimes *	California, Berkeley and its contributors.
221590Srgrimes * 4. Neither the name of the University nor the names of its contributors
231590Srgrimes *    may be used to endorse or promote products derived from this software
241590Srgrimes *    without specific prior written permission.
251590Srgrimes *
261590Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
271590Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
281590Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
291590Srgrimes * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
301590Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
311590Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
321590Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
331590Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
341590Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
351590Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
361590Srgrimes * SUCH DAMAGE.
3762833Swsanchez *
3862833Swsanchez * @(#)main.c      8.3 (Berkeley) 3/19/94
391590Srgrimes */
401590Srgrimes
411590Srgrimes#ifndef lint
4294595Sobrien#if 0
4394589Sobrienstatic char copyright[] =
4494589Sobrien"@(#) Copyright (c) 1988, 1989, 1990, 1993\n\
4594589Sobrien	The Regents of the University of California.  All rights reserved.\n";
4694595Sobrien#endif
471590Srgrimes#endif /* not lint */
4894589Sobrien#include <sys/cdefs.h>
4994587Sobrien__FBSDID("$FreeBSD$");
501590Srgrimes
51144475Sharti/*
52144475Sharti * main.c
531590Srgrimes *	The main file for this entire program. Exit routines etc
541590Srgrimes *	reside here.
551590Srgrimes *
561590Srgrimes * Utility functions defined in this file:
57144475Sharti *	Main_ParseArgLine
58144475Sharti *			Takes a line of arguments, breaks them and
59144475Sharti *			treats them as if they were given when first
60144475Sharti *			invoked. Used by the parse module to implement
61144475Sharti *			the .MFLAGS target.
621590Srgrimes */
631590Srgrimes
641590Srgrimes#include <sys/param.h>
651590Srgrimes#include <sys/stat.h>
66127880Sdes#include <sys/time.h>
67144020Sharti#include <sys/queue.h>
68127899Sru#include <sys/resource.h>
69153115Sru#include <sys/utsname.h>
7018730Ssteve#include <sys/wait.h>
7127644Scharnier#include <err.h>
721590Srgrimes#include <errno.h>
73127880Sdes#include <stdlib.h>
74141104Sharti#include <string.h>
7563955Simp#include <unistd.h>
76127880Sdes
77141104Sharti#include "arch.h"
78141133Sharti#include "buf.h"
79141104Sharti#include "config.h"
801590Srgrimes#include "dir.h"
81141104Sharti#include "globals.h"
82167330Sfjoe#include "GNode.h"
831590Srgrimes#include "job.h"
84141104Sharti#include "make.h"
85141104Sharti#include "parse.h"
861590Srgrimes#include "pathnames.h"
87146572Sharti#include "shell.h"
88141104Sharti#include "str.h"
89141104Sharti#include "suff.h"
90141104Sharti#include "targ.h"
91141104Sharti#include "util.h"
92141104Sharti#include "var.h"
931590Srgrimes
94146146Shartiextern char **environ;	/* XXX what header declares this variable? */
95146146Sharti
96160442Sobrien#define	WANT_ENV_MKLVL	1
97138071Sjmallett#define	MKLVL_MAXVAL	500
98138071Sjmallett#define	MKLVL_ENVVAR	"__MKLVL__"
99104395Sjmallett
100138916Sharti/* ordered list of makefiles to read */
101138916Shartistatic Lst makefiles = Lst_Initializer(makefiles);
102138916Sharti
103167330Sfjoe/* ordered list of source makefiles */
104167330Sfjoestatic Lst source_makefiles = Lst_Initializer(source_makefiles);
105167330Sfjoe
106138916Sharti/* list of variables to print */
107138916Shartistatic Lst variables = Lst_Initializer(variables);
108138916Sharti
109146146Shartistatic Boolean	expandVars;	/* fully expand printed variables */
110146146Shartistatic Boolean	noBuiltins;	/* -r flag */
111160442Sobrienstatic Boolean	forceJobs;	/* -j argument given */
112146146Shartistatic char	*curdir;	/* startup directory */
113146146Shartistatic char	*objdir;	/* where we chdir'ed to */
114167330Sfjoestatic char	**save_argv;	/* saved argv */
115167330Sfjoestatic char	*save_makeflags;/* saved MAKEFLAGS */
116146146Sharti
117146146Sharti/* (-E) vars to override from env */
118146146ShartiLst envFirstVars = Lst_Initializer(envFirstVars);
119146146Sharti
120146146Sharti/* Targets to be made */
121146146ShartiLst create = Lst_Initializer(create);
122146146Sharti
123146146ShartiBoolean		allPrecious;	/* .PRECIOUS given on line by itself */
124167330SfjoeBoolean		is_posix;	/* .POSIX target seen */
125177101SobrienBoolean		mfAutoDeps;	/* .MAKEFILEDEPS target seen */
126190821SfjoeBoolean		remakingMakefiles; /* True if remaking makefiles is in progress */
127146146ShartiBoolean		beSilent;	/* -s flag */
128146146ShartiBoolean		beVerbose;	/* -v flag */
129187132SobrienBoolean		beQuiet;	/* -Q flag */
130144475ShartiBoolean		compatMake;	/* -B argument */
131149844Shartiint		debug;		/* -d flag */
132146146ShartiBoolean		ignoreErrors;	/* -i flag */
133146146Shartiint		jobLimit;	/* -j argument */
134186279Sfjoeint		makeErrors;	/* Number of targets not remade due to errors */
135146146ShartiBoolean		jobsRunning;	/* TRUE if the jobs might be running */
136146146ShartiBoolean		keepgoing;	/* -k flag */
137144475ShartiBoolean		noExecute;	/* -n flag */
138181021SedBoolean		printGraphOnly;	/* -p flag */
139144475ShartiBoolean		queryFlag;	/* -q flag */
140144475ShartiBoolean		touchFlag;	/* -t flag */
141144475ShartiBoolean		usePipes;	/* !-P flag */
142146146Shartiuint32_t	warn_cmd;	/* command line warning flags */
143146146Shartiuint32_t	warn_flags;	/* actual warning flags */
144146146Shartiuint32_t	warn_nocmd;	/* command line no-warning flags */
145138916Sharti
146146146Shartitime_t		now;		/* Time at start of make */
147146146Shartistruct GNode	*DEFAULT;	/* .DEFAULT node */
148138916Sharti
149144475Sharti/**
150146143Sharti * Exit with usage message.
151146143Sharti */
152146143Shartistatic void
153146143Shartiusage(void)
154146143Sharti{
155146143Sharti	fprintf(stderr,
156181021Sed	    "usage: make [-BPSXeiknpqrstv] [-C directory] [-D variable]\n"
157146143Sharti	    "\t[-d flags] [-E variable] [-f makefile] [-I directory]\n"
158146143Sharti	    "\t[-j max_jobs] [-m directory] [-V variable]\n"
159146143Sharti	    "\t[variable=value] [target ...]\n");
160146143Sharti	exit(2);
161146143Sharti}
162146143Sharti
163146143Sharti/**
164144475Sharti * MFLAGS_append
165144475Sharti *	Append a flag with an optional argument to MAKEFLAGS and MFLAGS
166133085Sharti */
167133085Shartistatic void
168141252ShartiMFLAGS_append(const char *flag, char *arg)
169133085Sharti{
170140870Sharti	char *str;
171138232Sharti
172146146Sharti	Var_Append(".MAKEFLAGS", flag, VAR_GLOBAL);
173140870Sharti	if (arg != NULL) {
174140870Sharti		str = MAKEFLAGS_quote(arg);
175146146Sharti		Var_Append(".MAKEFLAGS", str, VAR_GLOBAL);
176140870Sharti		free(str);
177140870Sharti	}
178133085Sharti
179133085Sharti	Var_Append("MFLAGS", flag, VAR_GLOBAL);
180140870Sharti	if (arg != NULL) {
181140870Sharti		str = MAKEFLAGS_quote(arg);
182140870Sharti		Var_Append("MFLAGS", str, VAR_GLOBAL);
183140870Sharti		free(str);
184140870Sharti	}
185133085Sharti}
186133085Sharti
187144475Sharti/**
188145679Sharti * Main_ParseWarn
189145679Sharti *
190145679Sharti *	Handle argument to warning option.
191145679Sharti */
192145679Shartiint
193145679ShartiMain_ParseWarn(const char *arg, int iscmd)
194145679Sharti{
195145679Sharti	int i, neg;
196145679Sharti
197145679Sharti	static const struct {
198145679Sharti		const char	*option;
199145679Sharti		uint32_t	flag;
200145679Sharti	} options[] = {
201145679Sharti		{ "dirsyntax",	WARN_DIRSYNTAX },
202145679Sharti		{ NULL,		0 }
203145679Sharti	};
204145679Sharti
205145679Sharti	neg = 0;
206145679Sharti	if (arg[0] == 'n' && arg[1] == 'o') {
207145679Sharti		neg = 1;
208145679Sharti		arg += 2;
209145679Sharti	}
210145679Sharti
211145679Sharti	for (i = 0; options[i].option != NULL; i++)
212145679Sharti		if (strcmp(arg, options[i].option) == 0)
213145679Sharti			break;
214145679Sharti
215145679Sharti	if (options[i].option == NULL)
216145679Sharti		/* unknown option */
217145679Sharti		return (-1);
218145679Sharti
219145679Sharti	if (iscmd) {
220145679Sharti		if (!neg) {
221145679Sharti			warn_cmd |= options[i].flag;
222145679Sharti			warn_nocmd &= ~options[i].flag;
223145679Sharti			warn_flags |= options[i].flag;
224145679Sharti		} else {
225145679Sharti			warn_nocmd |= options[i].flag;
226145679Sharti			warn_cmd &= ~options[i].flag;
227145679Sharti			warn_flags &= ~options[i].flag;
228145679Sharti		}
229145679Sharti	} else {
230145679Sharti		if (!neg) {
231145679Sharti			warn_flags |= (options[i].flag & ~warn_nocmd);
232145679Sharti		} else {
233145679Sharti			warn_flags &= ~(options[i].flag | warn_cmd);
234145679Sharti		}
235145679Sharti	}
236145679Sharti	return (0);
237145679Sharti}
238145679Sharti
239145679Sharti/**
240146143Sharti * Open and parse the given makefile.
241146143Sharti *
242146143Sharti * Results:
243146143Sharti *	TRUE if ok. FALSE if couldn't open file.
244146143Sharti */
245146143Shartistatic Boolean
246146143ShartiReadMakefile(const char p[])
247146143Sharti{
248152982Sdavidxu	char *fname, *fnamesave;	/* makefile to read */
249146143Sharti	FILE *stream;
250146143Sharti	char *name, path[MAXPATHLEN];
251146143Sharti	char *MAKEFILE;
252146143Sharti	int setMAKEFILE;
253146143Sharti
254146143Sharti	/* XXX - remove this once constification is done */
255152982Sdavidxu	fnamesave = fname = estrdup(p);
256146143Sharti
257146143Sharti	if (!strcmp(fname, "-")) {
258146143Sharti		Parse_File("(stdin)", stdin);
259146145Sharti		Var_SetGlobal("MAKEFILE", "");
260146143Sharti	} else {
261146143Sharti		setMAKEFILE = strcmp(fname, ".depend");
262146143Sharti
263146143Sharti		/* if we've chdir'd, rebuild the path name */
264146143Sharti		if (curdir != objdir && *fname != '/') {
265146143Sharti			snprintf(path, MAXPATHLEN, "%s/%s", curdir, fname);
266146143Sharti			/*
267146143Sharti			 * XXX The realpath stuff breaks relative includes
268146143Sharti			 * XXX in some cases.   The problem likely is in
269146143Sharti			 * XXX parse.c where it does special things in
270146143Sharti			 * XXX ParseDoInclude if the file is relateive
271146143Sharti			 * XXX or absolute and not a system file.  There
272146143Sharti			 * XXX it assumes that if the current file that's
273146143Sharti			 * XXX being included is absolute, that any files
274146143Sharti			 * XXX that it includes shouldn't do the -I path
275146143Sharti			 * XXX stuff, which is inconsistant with historical
276146143Sharti			 * XXX behavior.  However, I can't pentrate the mists
277146143Sharti			 * XXX further, so I'm putting this workaround in
278146143Sharti			 * XXX here until such time as the underlying bug
279146143Sharti			 * XXX can be fixed.
280146143Sharti			 */
281146143Sharti#if THIS_BREAKS_THINGS
282146143Sharti			if (realpath(path, path) != NULL &&
283146143Sharti			    (stream = fopen(path, "r")) != NULL) {
284146143Sharti				MAKEFILE = fname;
285146143Sharti				fname = path;
286146143Sharti				goto found;
287146143Sharti			}
288146143Sharti		} else if (realpath(fname, path) != NULL) {
289146143Sharti			MAKEFILE = fname;
290146143Sharti			fname = path;
291146143Sharti			if ((stream = fopen(fname, "r")) != NULL)
292146143Sharti				goto found;
293146143Sharti		}
294146143Sharti#else
295146143Sharti			if ((stream = fopen(path, "r")) != NULL) {
296146143Sharti				MAKEFILE = fname;
297146143Sharti				fname = path;
298146143Sharti				goto found;
299146143Sharti			}
300146143Sharti		} else {
301146143Sharti			MAKEFILE = fname;
302146143Sharti			if ((stream = fopen(fname, "r")) != NULL)
303146143Sharti				goto found;
304146143Sharti		}
305146143Sharti#endif
306146143Sharti		/* look in -I and system include directories. */
307146143Sharti		name = Path_FindFile(fname, &parseIncPath);
308146143Sharti		if (!name)
309146143Sharti			name = Path_FindFile(fname, &sysIncPath);
310152969Sfjoe		if (!name || !(stream = fopen(name, "r"))) {
311152982Sdavidxu			free(fnamesave);
312146143Sharti			return (FALSE);
313152969Sfjoe		}
314146143Sharti		MAKEFILE = fname = name;
315146143Sharti		/*
316146143Sharti		 * set the MAKEFILE variable desired by System V fans -- the
317146143Sharti		 * placement of the setting here means it gets set to the last
318146143Sharti		 * makefile specified, as it is set by SysV make.
319146143Sharti		 */
320146143Shartifound:
321146143Sharti		if (setMAKEFILE)
322146145Sharti			Var_SetGlobal("MAKEFILE", MAKEFILE);
323146143Sharti		Parse_File(fname, stream);
324146143Sharti	}
325152982Sdavidxu	free(fnamesave);
326146143Sharti	return (TRUE);
327146143Sharti}
328146143Sharti
329146143Sharti/**
330167330Sfjoe * Open and parse the given makefile.
331167330Sfjoe * If open is successful add it to the list of makefiles.
332167330Sfjoe *
333167330Sfjoe * Results:
334167330Sfjoe *	TRUE if ok. FALSE if couldn't open file.
335167330Sfjoe */
336167330Sfjoestatic Boolean
337167330SfjoeTryReadMakefile(const char p[])
338167330Sfjoe{
339167330Sfjoe	char *data;
340167330Sfjoe	LstNode *last = Lst_Last(&source_makefiles);
341167330Sfjoe
342167330Sfjoe	if (!ReadMakefile(p))
343167330Sfjoe		return (FALSE);
344167330Sfjoe
345167330Sfjoe	data = estrdup(p);
346167330Sfjoe	if (last == NULL) {
347167330Sfjoe		LstNode *first = Lst_First(&source_makefiles);
348167330Sfjoe		Lst_Insert(&source_makefiles, first, data);
349167330Sfjoe	} else
350167330Sfjoe		Lst_Append(&source_makefiles, last, estrdup(p));
351167330Sfjoe	return (TRUE);
352167330Sfjoe}
353167330Sfjoe
354167330Sfjoe/**
355144475Sharti * MainParseArgs
3561590Srgrimes *	Parse a given argument vector. Called from main() and from
3571590Srgrimes *	Main_ParseArgLine() when the .MAKEFLAGS target is used.
3581590Srgrimes *
3591590Srgrimes *	XXX: Deal with command line overriding .MAKEFLAGS in makefile
3601590Srgrimes *
3611590Srgrimes * Side Effects:
3621590Srgrimes *	Various global and local flags will be set depending on the flags
3631590Srgrimes *	given
3641590Srgrimes */
3651590Srgrimesstatic void
366104696SjmallettMainParseArgs(int argc, char **argv)
3671590Srgrimes{
3685814Sjkh	int c;
369146038Sharti	Boolean	found_dd = FALSE;
370201526Sobrien	char found_dir[MAXPATHLEN + 1];	/* for searching for sys.mk */
3711590Srgrimes
372144896Shartirearg:
3731590Srgrimes	optind = 1;	/* since we're called more than once */
374144896Sharti	optreset = 1;
375187995Simp#define OPTFLAGS "ABC:D:d:E:ef:I:ij:km:nPpQqrSstV:vXx:"
376146038Sharti	for (;;) {
377146038Sharti		if ((optind < argc) && strcmp(argv[optind], "--") == 0) {
378146038Sharti			found_dd = TRUE;
379146038Sharti		}
380146038Sharti		if ((c = getopt(argc, argv, OPTFLAGS)) == -1) {
381146038Sharti			break;
382146038Sharti		}
3831590Srgrimes		switch(c) {
384144387Sharti
385144387Sharti		case 'A':
386144387Sharti			arch_fatal = FALSE;
387144387Sharti			MFLAGS_append("-A", NULL);
388144387Sharti			break;
389187995Simp		case 'B':
390187995Simp			compatMake = TRUE;
391187995Simp			MFLAGS_append("-B", NULL);
392187995Simp			unsetenv("MAKE_JOBS_FIFO");
393187995Simp			break;
394102393Sjmallett		case 'C':
395107964Sseanc			if (chdir(optarg) == -1)
396107964Sseanc				err(1, "chdir %s", optarg);
397201526Sobrien			if (getcwd(curdir, MAXPATHLEN) == NULL)
398201526Sobrien				err(2, NULL);
399102393Sjmallett			break;
4001590Srgrimes		case 'D':
401146145Sharti			Var_SetGlobal(optarg, "1");
402133085Sharti			MFLAGS_append("-D", optarg);
4031590Srgrimes			break;
4041590Srgrimes		case 'd': {
4051590Srgrimes			char *modules = optarg;
4061590Srgrimes
4071590Srgrimes			for (; *modules; ++modules)
4081590Srgrimes				switch (*modules) {
4091590Srgrimes				case 'A':
4101590Srgrimes					debug = ~0;
4111590Srgrimes					break;
4121590Srgrimes				case 'a':
4131590Srgrimes					debug |= DEBUG_ARCH;
4141590Srgrimes					break;
4151590Srgrimes				case 'c':
4161590Srgrimes					debug |= DEBUG_COND;
4171590Srgrimes					break;
4181590Srgrimes				case 'd':
4191590Srgrimes					debug |= DEBUG_DIR;
4201590Srgrimes					break;
4211590Srgrimes				case 'f':
4221590Srgrimes					debug |= DEBUG_FOR;
4231590Srgrimes					break;
4241590Srgrimes				case 'g':
4251590Srgrimes					if (modules[1] == '1') {
4261590Srgrimes						debug |= DEBUG_GRAPH1;
4271590Srgrimes						++modules;
4281590Srgrimes					}
4291590Srgrimes					else if (modules[1] == '2') {
4301590Srgrimes						debug |= DEBUG_GRAPH2;
4311590Srgrimes						++modules;
4321590Srgrimes					}
4331590Srgrimes					break;
4341590Srgrimes				case 'j':
4351590Srgrimes					debug |= DEBUG_JOB;
4361590Srgrimes					break;
43760569Swill				case 'l':
43860569Swill					debug |= DEBUG_LOUD;
43960569Swill					break;
4401590Srgrimes				case 'm':
4411590Srgrimes					debug |= DEBUG_MAKE;
4421590Srgrimes					break;
4431590Srgrimes				case 's':
4441590Srgrimes					debug |= DEBUG_SUFF;
4451590Srgrimes					break;
4461590Srgrimes				case 't':
4471590Srgrimes					debug |= DEBUG_TARG;
4481590Srgrimes					break;
4491590Srgrimes				case 'v':
4501590Srgrimes					debug |= DEBUG_VAR;
4511590Srgrimes					break;
4521590Srgrimes				default:
453144475Sharti					warnx("illegal argument to d option "
454144475Sharti					    "-- %c", *modules);
4551590Srgrimes					usage();
4561590Srgrimes				}
457133085Sharti			MFLAGS_append("-d", optarg);
4581590Srgrimes			break;
4591590Srgrimes		}
46049332Shoek		case 'E':
461138920Sru			Lst_AtEnd(&envFirstVars, estrdup(optarg));
462133085Sharti			MFLAGS_append("-E", optarg);
46349332Shoek			break;
4641590Srgrimes		case 'e':
4651590Srgrimes			checkEnvFirst = TRUE;
466133085Sharti			MFLAGS_append("-e", NULL);
4671590Srgrimes			break;
4681590Srgrimes		case 'f':
469138920Sru			Lst_AtEnd(&makefiles, estrdup(optarg));
4701590Srgrimes			break;
471187995Simp		case 'I':
472187995Simp			Parse_AddIncludeDir(optarg);
473187995Simp			MFLAGS_append("-I", optarg);
474187995Simp			break;
4751590Srgrimes		case 'i':
4761590Srgrimes			ignoreErrors = TRUE;
477133085Sharti			MFLAGS_append("-i", NULL);
4781590Srgrimes			break;
47949331Shoek		case 'j': {
48049331Shoek			char *endptr;
48149331Shoek
48218730Ssteve			forceJobs = TRUE;
483146140Sharti			jobLimit = strtol(optarg, &endptr, 10);
484146140Sharti			if (jobLimit <= 0 || *endptr != '\0') {
48549938Shoek				warnx("illegal number, -j argument -- %s",
48649938Shoek				    optarg);
48749938Shoek				usage();
48849331Shoek			}
489133085Sharti			MFLAGS_append("-j", optarg);
4901590Srgrimes			break;
49149331Shoek		}
4921590Srgrimes		case 'k':
4931590Srgrimes			keepgoing = TRUE;
494133085Sharti			MFLAGS_append("-k", NULL);
4951590Srgrimes			break;
49618730Ssteve		case 'm':
497201526Sobrien			/* look for magic parent directory search string */
498201526Sobrien			if (strncmp(".../", optarg, 4) == 0) {
499201526Sobrien				if (!Dir_FindHereOrAbove(curdir, optarg + 4,
500201526Sobrien				    found_dir, sizeof(found_dir)))
501201526Sobrien					break;		/* nothing doing */
502201526Sobrien				Path_AddDir(&sysIncPath, found_dir);
503201526Sobrien			} else {
504201526Sobrien				Path_AddDir(&sysIncPath, optarg);
505201526Sobrien			}
506133085Sharti			MFLAGS_append("-m", optarg);
50718730Ssteve			break;
5081590Srgrimes		case 'n':
5091590Srgrimes			noExecute = TRUE;
510133085Sharti			MFLAGS_append("-n", NULL);
5111590Srgrimes			break;
512187995Simp		case 'P':
513187995Simp			usePipes = FALSE;
514187995Simp			MFLAGS_append("-P", NULL);
515187995Simp			break;
516181021Sed		case 'p':
517181021Sed			printGraphOnly = TRUE;
518181021Sed			debug |= DEBUG_GRAPH1;
519181021Sed			break;
520186713Sobrien		case 'Q':
521186713Sobrien			beQuiet = TRUE;
522187132Sobrien			beVerbose = FALSE;
523186713Sobrien			MFLAGS_append("-Q", NULL);
524186713Sobrien			break;
5251590Srgrimes		case 'q':
5261590Srgrimes			queryFlag = TRUE;
5271590Srgrimes			/* Kind of nonsensical, wot? */
528133085Sharti			MFLAGS_append("-q", NULL);
5291590Srgrimes			break;
5301590Srgrimes		case 'r':
5311590Srgrimes			noBuiltins = TRUE;
532133085Sharti			MFLAGS_append("-r", NULL);
5331590Srgrimes			break;
534187995Simp		case 'S':
535187995Simp			keepgoing = FALSE;
536187995Simp			MFLAGS_append("-S", NULL);
537187995Simp			break;
5381590Srgrimes		case 's':
5391590Srgrimes			beSilent = TRUE;
540133085Sharti			MFLAGS_append("-s", NULL);
5411590Srgrimes			break;
5421590Srgrimes		case 't':
5431590Srgrimes			touchFlag = TRUE;
544133085Sharti			MFLAGS_append("-t", NULL);
5451590Srgrimes			break;
546187995Simp		case 'V':
547187995Simp			Lst_AtEnd(&variables, estrdup(optarg));
548187995Simp			MFLAGS_append("-V", optarg);
549187995Simp			break;
55041151Sdg		case 'v':
55141151Sdg			beVerbose = TRUE;
552186713Sobrien			beQuiet = FALSE;
553133085Sharti			MFLAGS_append("-v", NULL);
55441151Sdg			break;
555187995Simp		case 'X':
556187995Simp			expandVars = FALSE;
557187995Simp			break;
558145627Sharti		case 'x':
559145679Sharti			if (Main_ParseWarn(optarg, 1) != -1)
560145627Sharti				MFLAGS_append("-x", optarg);
561145627Sharti			break;
562167330Sfjoe
5631590Srgrimes		default:
5641590Srgrimes		case '?':
5651590Srgrimes			usage();
5661590Srgrimes		}
5671590Srgrimes	}
568144896Sharti	argv += optind;
569144896Sharti	argc -= optind;
5701590Srgrimes
5711590Srgrimes	oldVars = TRUE;
5721590Srgrimes
5731590Srgrimes	/*
574144896Sharti	 * Parse the rest of the arguments.
575144896Sharti	 *	o Check for variable assignments and perform them if so.
576144896Sharti	 *	o Check for more flags and restart getopt if so.
577160442Sobrien	 *	o Anything else is taken to be a target and added
578144896Sharti	 *	  to the end of the "create" list.
5791590Srgrimes	 */
580144896Sharti	for (; *argv != NULL; ++argv, --argc) {
581133562Sharti		if (Parse_IsVar(*argv)) {
582140870Sharti			char *ptr = MAKEFLAGS_quote(*argv);
583167330Sfjoe			char *v = estrdup(*argv);
584133562Sharti
585146146Sharti			Var_Append(".MAKEFLAGS", ptr, VAR_GLOBAL);
586167330Sfjoe			Parse_DoVar(v, VAR_CMD);
587133562Sharti			free(ptr);
588167330Sfjoe			free(v);
589133562Sharti
590144896Sharti		} else if ((*argv)[0] == '-') {
591144896Sharti			if ((*argv)[1] == '\0') {
592144896Sharti				/*
593144896Sharti				 * (*argv) is a single dash, so we
594144896Sharti				 * just ignore it.
595144896Sharti				 */
596146038Sharti			} else if (found_dd) {
597146038Sharti				/*
598146038Sharti				 * Double dash has been found, ignore
599146038Sharti				 * any more options.  But what do we do
600146038Sharti				 * with it?  For now treat it like a target.
601146038Sharti				 */
602146038Sharti				Lst_AtEnd(&create, estrdup(*argv));
603144896Sharti			} else {
604144896Sharti				/*
605146038Sharti				 * (*argv) is a -flag, so backup argv and
606146038Sharti				 * argc.  getopt() expects options to start
607146038Sharti				 * in the 2nd position.
608144896Sharti				 */
609144896Sharti				argc++;
610144896Sharti				argv--;
6111590Srgrimes				goto rearg;
6121590Srgrimes			}
613144896Sharti
614144896Sharti		} else if ((*argv)[0] == '\0') {
615144896Sharti			Punt("illegal (null) argument.");
616144896Sharti
617144896Sharti		} else {
618138916Sharti			Lst_AtEnd(&create, estrdup(*argv));
6191590Srgrimes		}
620144896Sharti	}
6211590Srgrimes}
6221590Srgrimes
623144475Sharti/**
624144475Sharti * Main_ParseArgLine
625160442Sobrien *	Used by the parse module when a .MFLAGS or .MAKEFLAGS target
6261590Srgrimes *	is encountered and by main() when reading the .MAKEFLAGS envariable.
6271590Srgrimes *	Takes a line of arguments and breaks it into its
628160442Sobrien *	component words and passes those words and the number of them to the
6291590Srgrimes *	MainParseArgs function.
6301590Srgrimes *	The line should have all its leading whitespace removed.
6311590Srgrimes *
6321590Srgrimes * Side Effects:
6331590Srgrimes *	Only those that come from the various arguments.
6341590Srgrimes */
6351590Srgrimesvoid
636140870ShartiMain_ParseArgLine(char *line, int mflags)
6371590Srgrimes{
638146345Sharti	ArgArray	aa;
6391590Srgrimes
6401590Srgrimes	if (line == NULL)
6411590Srgrimes		return;
6421590Srgrimes	for (; *line == ' '; ++line)
6431590Srgrimes		continue;
6441590Srgrimes	if (!*line)
6451590Srgrimes		return;
6461590Srgrimes
647140870Sharti	if (mflags)
648146345Sharti		MAKEFLAGS_break(&aa, line);
649140870Sharti	else
650146345Sharti		brk_string(&aa, line, TRUE);
651140870Sharti
652146345Sharti	MainParseArgs(aa.argc, aa.argv);
653146345Sharti	ArgArray_Done(&aa);
6541590Srgrimes}
6551590Srgrimes
656146146Shartistatic char *
657141252Shartichdir_verify_path(const char *path, char *obpath)
65818339Sswallace{
65918339Sswallace	struct stat sb;
66018339Sswallace
66118339Sswallace	if (stat(path, &sb) == 0 && S_ISDIR(sb.st_mode)) {
66275973Sru		if (chdir(path) == -1 || getcwd(obpath, MAXPATHLEN) == NULL) {
66327644Scharnier			warn("warning: %s", path);
664141252Sharti			return (NULL);
66518339Sswallace		}
666138232Sharti		return (obpath);
66718339Sswallace	}
66818339Sswallace
669141252Sharti	return (NULL);
67018339Sswallace}
67118339Sswallace
672146144Sharti/**
673146144Sharti * In lieu of a good way to prevent every possible looping in make(1), stop
674146144Sharti * there from being more than MKLVL_MAXVAL processes forked by make(1), to
675146144Sharti * prevent a forkbomb from happening, in a dumb and mechanical way.
676146144Sharti *
677146144Sharti * Side Effects:
678146144Sharti *	Creates or modifies enviornment variable MKLVL_ENVVAR via setenv().
679138071Sjmallett */
680138071Sjmallettstatic void
681138071Sjmallettcheck_make_level(void)
682138071Sjmallett{
683138071Sjmallett#ifdef WANT_ENV_MKLVL
684138071Sjmallett	char	*value = getenv(MKLVL_ENVVAR);
685138071Sjmallett	int	level = (value == NULL) ? 0 : atoi(value);
686138071Sjmallett
687138071Sjmallett	if (level < 0) {
688213493Simp		errx(2, "Invalid value for recursion level (%d).", level);
689138071Sjmallett	} else if (level > MKLVL_MAXVAL) {
690213493Simp		errx(2, "Max recursion level (%d) exceeded.", MKLVL_MAXVAL);
691138071Sjmallett	} else {
692138071Sjmallett		char new_value[32];
693138071Sjmallett		sprintf(new_value, "%d", level + 1);
694138071Sjmallett		setenv(MKLVL_ENVVAR, new_value, 1);
695138071Sjmallett	}
696138071Sjmallett#endif /* WANT_ENV_MKLVL */
697138071Sjmallett}
698138071Sjmallett
699144475Sharti/**
700167330Sfjoe * Main_AddSourceMakefile
701167330Sfjoe *	Add a file to the list of source makefiles
702167330Sfjoe */
703167330Sfjoevoid
704167330SfjoeMain_AddSourceMakefile(const char *name)
705167330Sfjoe{
706167330Sfjoe
707167330Sfjoe	Lst_AtEnd(&source_makefiles, estrdup(name));
708167330Sfjoe}
709167330Sfjoe
710167330Sfjoe/**
711167330Sfjoe * Remake_Makefiles
712167330Sfjoe *	Remake all the makefiles
713167330Sfjoe */
714167330Sfjoestatic void
715167330SfjoeRemake_Makefiles(void)
716167330Sfjoe{
717198199Sfjoe	Lst cleanup;
718167330Sfjoe	LstNode *ln;
719167330Sfjoe	int error_cnt = 0;
720167330Sfjoe	int remade_cnt = 0;
721167330Sfjoe
722167330Sfjoe	Compat_InstallSignalHandlers();
723170179Sfjoe	if (curdir != objdir) {
724170179Sfjoe		if (chdir(curdir) < 0)
725170179Sfjoe			Fatal("Failed to change directory to %s.", curdir);
726170179Sfjoe	}
727167330Sfjoe
728198199Sfjoe	Lst_Init(&cleanup);
729167330Sfjoe	LST_FOREACH(ln, &source_makefiles) {
730167330Sfjoe		LstNode *ln2;
731167330Sfjoe		struct GNode *gn;
732167330Sfjoe		const char *name = Lst_Datum(ln);
733167330Sfjoe		Boolean saveTouchFlag = touchFlag;
734167330Sfjoe		Boolean saveQueryFlag = queryFlag;
735167330Sfjoe		Boolean saveNoExecute = noExecute;
736168892Sfjoe		int mtime;
737167330Sfjoe
738167330Sfjoe		/*
739167330Sfjoe		 * Create node
740167330Sfjoe		 */
741167330Sfjoe		gn = Targ_FindNode(name, TARG_CREATE);
742167330Sfjoe		DEBUGF(MAKE, ("Checking %s...", gn->name));
743167330Sfjoe		Suff_FindDeps(gn);
744167330Sfjoe
745167330Sfjoe		/*
746167330Sfjoe		 * -t, -q and -n has no effect unless the makefile is
747167330Sfjoe		 * specified as one of the targets explicitly in the
748167330Sfjoe		 * command line
749167330Sfjoe		 */
750167330Sfjoe		LST_FOREACH(ln2, &create) {
751167330Sfjoe			if (!strcmp(gn->name, Lst_Datum(ln2))) {
752167330Sfjoe				/* found as a target */
753167330Sfjoe				break;
754167330Sfjoe			}
755167330Sfjoe		}
756167330Sfjoe		if (ln2 == NULL) {
757167330Sfjoe			touchFlag = FALSE;
758167330Sfjoe			queryFlag = FALSE;
759167330Sfjoe			noExecute = FALSE;
760167330Sfjoe		}
761167330Sfjoe
762167330Sfjoe		/*
763167330Sfjoe		 * Check and remake the makefile
764167330Sfjoe		 */
765168892Sfjoe		mtime = Dir_MTime(gn);
766190821Sfjoe		remakingMakefiles = TRUE;
767167330Sfjoe		Compat_Make(gn, gn);
768190821Sfjoe		remakingMakefiles = FALSE;
769167330Sfjoe
770167330Sfjoe		/*
771167330Sfjoe		 * Restore -t, -q and -n behaviour
772167330Sfjoe		 */
773167330Sfjoe		touchFlag = saveTouchFlag;
774167330Sfjoe		queryFlag = saveQueryFlag;
775167330Sfjoe		noExecute = saveNoExecute;
776167330Sfjoe
777167330Sfjoe		/*
778167330Sfjoe		 * Compat_Make will leave the 'made' field of gn
779167330Sfjoe		 * in one of the following states:
780167330Sfjoe		 *	UPTODATE  gn was already up-to-date
781167330Sfjoe		 *	MADE	  gn was recreated successfully
782167330Sfjoe		 *	ERROR	  An error occurred while gn was being created
783167330Sfjoe		 *	ABORTED	  gn was not remade because one of its inferiors
784167330Sfjoe		 *		  could not be made due to errors.
785167330Sfjoe		 */
786168892Sfjoe		if (gn->made == MADE) {
787168892Sfjoe			if (mtime != Dir_MTime(gn)) {
788168892Sfjoe				DEBUGF(MAKE,
789168892Sfjoe				    ("%s updated (%d -> %d).\n",
790168892Sfjoe				     gn->name, mtime, gn->mtime));
791168892Sfjoe				remade_cnt++;
792168892Sfjoe			} else {
793168892Sfjoe				DEBUGF(MAKE,
794168892Sfjoe				    ("%s not updated: skipping restart.\n",
795168892Sfjoe				     gn->name));
796168892Sfjoe			}
797168892Sfjoe		} else if (gn->made == ERROR)
798167330Sfjoe			error_cnt++;
799167330Sfjoe		else if (gn->made == ABORTED) {
800167330Sfjoe			printf("`%s' not remade because of errors.\n",
801167330Sfjoe			    gn->name);
802167330Sfjoe			error_cnt++;
803173919Sfjoe		} else if (gn->made == UPTODATE) {
804198199Sfjoe			Lst_EnQueue(&cleanup, gn);
805167330Sfjoe		}
806167330Sfjoe	}
807167330Sfjoe
808167330Sfjoe	if (error_cnt > 0)
809167330Sfjoe		Fatal("Failed to remake Makefiles.");
810167330Sfjoe	if (remade_cnt > 0) {
811167330Sfjoe		DEBUGF(MAKE, ("Restarting `%s'.\n", save_argv[0]));
812167330Sfjoe
813167330Sfjoe		/*
814167330Sfjoe		 * Some of makefiles were remade -- restart from clean state
815167330Sfjoe		 */
816167330Sfjoe		if (save_makeflags != NULL)
817167330Sfjoe			setenv("MAKEFLAGS", save_makeflags, 1);
818167330Sfjoe		else
819167330Sfjoe			unsetenv("MAKEFLAGS");
820167330Sfjoe		if (execvp(save_argv[0], save_argv) < 0) {
821167330Sfjoe			Fatal("Can't restart `%s': %s.",
822167330Sfjoe			    save_argv[0], strerror(errno));
823167330Sfjoe		}
824167330Sfjoe	}
825170179Sfjoe
826198199Sfjoe	while (!Lst_IsEmpty(&cleanup)) {
827198199Sfjoe		GNode *gn = Lst_DeQueue(&cleanup);
828198199Sfjoe
829198199Sfjoe		gn->unmade = 0;
830198199Sfjoe		gn->make = FALSE;
831198199Sfjoe		gn->made = UNMADE;
832198199Sfjoe		gn->childMade = FALSE;
833198199Sfjoe		gn->mtime = gn->cmtime = 0;
834198199Sfjoe		gn->cmtime_gn = NULL;
835198199Sfjoe
836198199Sfjoe		LST_FOREACH(ln, &gn->children) {
837198199Sfjoe			GNode *cgn = Lst_Datum(ln);
838198199Sfjoe
839198199Sfjoe			gn->unmade++;
840198199Sfjoe			Lst_EnQueue(&cleanup, cgn);
841198199Sfjoe		}
842198199Sfjoe	}
843198199Sfjoe
844170179Sfjoe	if (curdir != objdir) {
845170179Sfjoe		if (chdir(objdir) < 0)
846170179Sfjoe			Fatal("Failed to change directory to %s.", objdir);
847170179Sfjoe	}
848167330Sfjoe}
849167330Sfjoe
850167330Sfjoe/**
851144475Sharti * main
8521590Srgrimes *	The main function, for obvious reasons. Initializes variables
8531590Srgrimes *	and a few modules, then parses the arguments give it in the
8541590Srgrimes *	environment and on the command line. Reads the system makefile
8551590Srgrimes *	followed by either Makefile, makefile or the file given by the
8561590Srgrimes *	-f argument. Sets the .MAKEFLAGS PMake variable based on all the
8571590Srgrimes *	flags it has received by then uses either the Make or the Compat
8581590Srgrimes *	module to create the initial list of targets.
8591590Srgrimes *
8601590Srgrimes * Results:
8611590Srgrimes *	If -q was given, exits -1 if anything was out-of-date. Else it exits
8621590Srgrimes *	0.
8631590Srgrimes *
8641590Srgrimes * Side Effects:
8651590Srgrimes *	The program exits when done. Targets are created. etc. etc. etc.
8661590Srgrimes */
8671590Srgrimesint
868104696Sjmallettmain(int argc, char **argv)
8691590Srgrimes{
870160442Sobrien	const char *machine;
871146144Sharti	const char *machine_arch;
872146144Sharti	const char *machine_cpu;
873160442Sobrien	Boolean outOfDate = TRUE;	/* FALSE if all targets up to date */
874146581Sharti	const char *p;
875146157Sharti	const char *pathp;
876146157Sharti	const char *path;
87773262Simp	char mdpath[MAXPATHLEN];
87873262Simp	char obpath[MAXPATHLEN];
87973262Simp	char cdpath[MAXPATHLEN];
880201526Sobrien	char found_dir[MAXPATHLEN + 1];	/* for searching for sys.mk */
88118730Ssteve	char *cp = NULL, *start;
882141252Sharti
883167330Sfjoe	save_argv = argv;
884167330Sfjoe	save_makeflags = getenv("MAKEFLAGS");
885167330Sfjoe	if (save_makeflags != NULL)
886167330Sfjoe		save_makeflags = estrdup(save_makeflags);
887167330Sfjoe
888146146Sharti	/*
889146146Sharti	 * Initialize file global variables.
890146146Sharti	 */
891146146Sharti	expandVars = TRUE;
892146146Sharti	noBuiltins = FALSE;		/* Read the built-in rules */
893160442Sobrien	forceJobs = FALSE;		/* No -j flag */
894146146Sharti	curdir = cdpath;
895146146Sharti
896146146Sharti	/*
897146146Sharti	 * Initialize program global variables.
898146146Sharti	 */
899146146Sharti	beSilent = FALSE;		/* Print commands as executed */
900146146Sharti	ignoreErrors = FALSE;		/* Pay attention to non-zero returns */
901146146Sharti	noExecute = FALSE;		/* Execute all commands */
902181021Sed	printGraphOnly = FALSE;		/* Don't stop after printing graph */
903146146Sharti	keepgoing = FALSE;		/* Stop on error */
904146146Sharti	allPrecious = FALSE;		/* Remove targets when interrupted */
905146146Sharti	queryFlag = FALSE;		/* This is not just a check-run */
906146146Sharti	touchFlag = FALSE;		/* Actually update targets */
907146146Sharti	usePipes = TRUE;		/* Catch child output in pipes */
908146146Sharti	debug = 0;			/* No debug verbosity, please. */
909146146Sharti	jobsRunning = FALSE;
910146146Sharti
911146146Sharti	jobLimit = DEFMAXJOBS;
912146146Sharti	compatMake = FALSE;		/* No compat mode */
913146146Sharti
914138071Sjmallett	check_make_level();
915104395Sjmallett
91618730Ssteve#ifdef RLIMIT_NOFILE
9171590Srgrimes	/*
91818730Ssteve	 * get rid of resource limit on file descriptors
91918730Ssteve	 */
92018730Ssteve	{
92118730Ssteve		struct rlimit rl;
922146144Sharti		if (getrlimit(RLIMIT_NOFILE, &rl) == -1) {
923146144Sharti			err(2, "getrlimit");
92418730Ssteve		}
925146144Sharti		rl.rlim_cur = rl.rlim_max;
926146144Sharti		if (setrlimit(RLIMIT_NOFILE, &rl) == -1) {
927146144Sharti			err(2, "setrlimit");
928146144Sharti		}
92918730Ssteve	}
93018730Ssteve#endif
9311590Srgrimes
9325814Sjkh	/*
9335814Sjkh	 * Get the name of this type of MACHINE from utsname
9345814Sjkh	 * so we can share an executable for similar machines.
9355814Sjkh	 * (i.e. m68k: amiga hp300, mac68k, sun3, ...)
9365814Sjkh	 *
937153115Sru	 * Note that both MACHINE and MACHINE_ARCH are decided at
938153115Sru	 * run-time.
9395814Sjkh	 */
940213494Simp	if ((machine = getenv("MACHINE")) == NULL) {
941144475Sharti		static struct utsname utsname;
94218730Ssteve
943144475Sharti		if (uname(&utsname) == -1)
944144475Sharti			err(2, "uname");
945144475Sharti		machine = utsname.machine;
9465814Sjkh	}
9471590Srgrimes
948146144Sharti	if ((machine_arch = getenv("MACHINE_ARCH")) == NULL) {
949146144Sharti#ifdef MACHINE_ARCH
950146144Sharti		machine_arch = MACHINE_ARCH;
951146144Sharti#else
95244362Simp		machine_arch = "unknown";
95344362Simp#endif
95444362Simp	}
95544362Simp
9561590Srgrimes	/*
95772679Skris	 * Set machine_cpu to the minumum supported CPU revision based
95872679Skris	 * on the target architecture, if not already set.
95972679Skris	 */
960146144Sharti	if ((machine_cpu = getenv("MACHINE_CPU")) == NULL) {
96172679Skris		if (!strcmp(machine_arch, "i386"))
96272679Skris			machine_cpu = "i386";
96372679Skris		else
96472679Skris			machine_cpu = "unknown";
96572679Skris	}
9661590Srgrimes
9671590Srgrimes	/*
9681590Srgrimes	 * Initialize the parsing, directory and variable modules to prepare
9691590Srgrimes	 * for the reading of inclusion paths and variable settings on the
9701590Srgrimes	 * command line
9711590Srgrimes	 */
972146144Sharti	Proc_Init();
973146144Sharti
9741590Srgrimes	Dir_Init();		/* Initialize directory structures so -I flags
9751590Srgrimes				 * can be processed correctly */
976145971Sharti	Var_Init(environ);	/* As well as the lists of variables for
9771590Srgrimes				 * parsing arguments */
978146560Sharti
9791590Srgrimes	/*
980146560Sharti	 * Initialize the Shell so that we have a shell for != assignments
981146560Sharti	 * on the command line.
982146560Sharti	 */
983146560Sharti	Shell_Init();
984146560Sharti
985146560Sharti	/*
9861590Srgrimes	 * Initialize various variables.
9871590Srgrimes	 *	MAKE also gets this name, for compatibility
9881590Srgrimes	 *	.MAKEFLAGS gets set to the empty string just in case.
9891590Srgrimes	 *	MFLAGS also gets initialized empty, for compatibility.
9901590Srgrimes	 */
991146145Sharti	Var_SetGlobal("MAKE", argv[0]);
992146146Sharti	Var_SetGlobal(".MAKEFLAGS", "");
993146145Sharti	Var_SetGlobal("MFLAGS", "");
994146145Sharti	Var_SetGlobal("MACHINE", machine);
995146145Sharti	Var_SetGlobal("MACHINE_ARCH", machine_arch);
996146145Sharti	Var_SetGlobal("MACHINE_CPU", machine_cpu);
99797121Sru#ifdef MAKE_VERSION
998146145Sharti	Var_SetGlobal("MAKE_VERSION", MAKE_VERSION);
99997121Sru#endif
1000186559Sobrien	Var_SetGlobal(".newline", "\n");	/* handy for :@ loops */
1001186559Sobrien	{
1002186559Sobrien		char tmp[64];
10031590Srgrimes
1004186559Sobrien		snprintf(tmp, sizeof(tmp), "%u", getpid());
1005186559Sobrien		Var_SetGlobal(".MAKE.PID", tmp);
1006186559Sobrien		snprintf(tmp, sizeof(tmp), "%u", getppid());
1007186559Sobrien		Var_SetGlobal(".MAKE.PPID", tmp);
1008186559Sobrien	}
1009186559Sobrien	Job_SetPrefix();
1010186559Sobrien
10111590Srgrimes	/*
1012201526Sobrien	 * Find where we are...
1013201526Sobrien	 */
1014201526Sobrien	if (getcwd(curdir, MAXPATHLEN) == NULL)
1015201526Sobrien		err(2, NULL);
1016201526Sobrien
1017201526Sobrien	/*
1018144896Sharti	 * First snag things out of the MAKEFLAGS environment
1019144896Sharti	 * variable.  Then parse the command line arguments.
10201590Srgrimes	 */
1021140870Sharti	Main_ParseArgLine(getenv("MAKEFLAGS"), 1);
10228874Srgrimes
10231590Srgrimes	MainParseArgs(argc, argv);
10241590Srgrimes
10251590Srgrimes	/*
1026201526Sobrien	 * Verify that cwd is sane (after -C may have changed it).
1027120053Sru	 */
1028141252Sharti	{
1029141252Sharti	struct stat sa;
1030141252Sharti
1031120053Sru	if (stat(curdir, &sa) == -1)
1032120053Sru	    err(2, "%s", curdir);
1033141252Sharti	}
1034120053Sru
1035120053Sru	/*
1036120053Sru	 * The object directory location is determined using the
1037120053Sru	 * following order of preference:
1038120053Sru	 *
1039120053Sru	 *	1. MAKEOBJDIRPREFIX`cwd`
1040120053Sru	 *	2. MAKEOBJDIR
1041143412Sharti	 *	3. PATH_OBJDIR.${MACHINE}
1042143412Sharti	 *	4. PATH_OBJDIR
1043143412Sharti	 *	5. PATH_OBJDIRPREFIX`cwd`
1044120053Sru	 *
1045120053Sru	 * If one of the first two fails, use the current directory.
1046120053Sru	 * If the remaining three all fail, use the current directory.
1047120053Sru	 *
1048120053Sru	 * Once things are initted,
1049120053Sru	 * have to add the original directory to the search path,
1050120053Sru	 * and modify the paths for the Makefiles apropriately.  The
1051120053Sru	 * current directory is also placed as a variable for make scripts.
1052120053Sru	 */
1053120053Sru	if (!(pathp = getenv("MAKEOBJDIRPREFIX"))) {
1054120053Sru		if (!(path = getenv("MAKEOBJDIR"))) {
1055143412Sharti			path = PATH_OBJDIR;
1056143412Sharti			pathp = PATH_OBJDIRPREFIX;
1057146145Sharti			snprintf(mdpath, MAXPATHLEN, "%s.%s", path, machine);
1058120053Sru			if (!(objdir = chdir_verify_path(mdpath, obpath)))
1059120053Sru				if (!(objdir=chdir_verify_path(path, obpath))) {
1060138232Sharti					snprintf(mdpath, MAXPATHLEN,
1061120053Sru							"%s%s", pathp, curdir);
1062120053Sru					if (!(objdir=chdir_verify_path(mdpath,
1063120053Sru								       obpath)))
1064120053Sru						objdir = curdir;
1065120053Sru				}
1066120053Sru		}
1067120053Sru		else if (!(objdir = chdir_verify_path(path, obpath)))
1068120053Sru			objdir = curdir;
1069120053Sru	}
1070120053Sru	else {
1071138232Sharti		snprintf(mdpath, MAXPATHLEN, "%s%s", pathp, curdir);
1072120053Sru		if (!(objdir = chdir_verify_path(mdpath, obpath)))
1073120053Sru			objdir = curdir;
1074120053Sru	}
1075120053Sru	Dir_InitDot();		/* Initialize the "." directory */
1076120053Sru	if (objdir != curdir)
1077144020Sharti		Path_AddDir(&dirSearchPath, curdir);
1078146145Sharti	Var_SetGlobal(".ST_EXPORTVAR", "YES");
1079146145Sharti	Var_SetGlobal(".CURDIR", curdir);
1080146145Sharti	Var_SetGlobal(".OBJDIR", objdir);
1081120053Sru
1082137606Sphk	if (getenv("MAKE_JOBS_FIFO") != NULL)
1083137606Sphk		forceJobs = TRUE;
1084120053Sru	/*
108528228Sfsmp	 * Be compatible if user did not specify -j and did not explicitly
108628228Sfsmp	 * turned compatibility on
108728228Sfsmp	 */
108828228Sfsmp	if (!compatMake && !forceJobs)
108928228Sfsmp		compatMake = TRUE;
109028228Sfsmp
109128228Sfsmp	/*
1092144387Sharti	 * Initialize target and suffix modules in preparation for
10931590Srgrimes	 * parsing the makefile(s)
10941590Srgrimes	 */
10951590Srgrimes	Targ_Init();
10961590Srgrimes	Suff_Init();
10971590Srgrimes
109869527Swill	DEFAULT = NULL;
1099138232Sharti	time(&now);
11001590Srgrimes
11011590Srgrimes	/*
11021590Srgrimes	 * Set up the .TARGETS variable to contain the list of targets to be
11031590Srgrimes	 * created. If none specified, make the variable empty -- the parser
11041590Srgrimes	 * will fill the thing in with the default or .MAIN target.
11051590Srgrimes	 */
1106146145Sharti	if (Lst_IsEmpty(&create)) {
1107146145Sharti		Var_SetGlobal(".TARGETS", "");
1108146145Sharti	} else {
1109138512Sharti		LstNode *ln;
11101590Srgrimes
1111138916Sharti		for (ln = Lst_First(&create); ln != NULL; ln = Lst_Succ(ln)) {
1112138264Sharti			char *name = Lst_Datum(ln);
11131590Srgrimes
11141590Srgrimes			Var_Append(".TARGETS", name, VAR_GLOBAL);
11151590Srgrimes		}
1116146145Sharti	}
11171590Srgrimes
111818730Ssteve
11191590Srgrimes	/*
112018730Ssteve	 * If no user-supplied system path was given (through the -m option)
112118730Ssteve	 * add the directories from the DEFSYSPATH (more than one may be given
112218730Ssteve	 * as dir1:...:dirn) to the system include path.
11231590Srgrimes	 */
1124144020Sharti	if (TAILQ_EMPTY(&sysIncPath)) {
1125201526Sobrien		char defsyspath[] = PATH_DEFSYSPATH;
1126201526Sobrien		char *syspath = getenv("MAKESYSPATH");
1127146144Sharti
1128201526Sobrien		/*
1129201526Sobrien		 * If no user-supplied system path was given (thru -m option)
1130201526Sobrien		 * add the directories from the DEFSYSPATH (more than one may
1131201526Sobrien		 * be given as dir1:...:dirn) to the system include path.
1132201526Sobrien		 */
1133201526Sobrien		if (syspath == NULL || *syspath == '\0')
1134201526Sobrien			syspath = defsyspath;
1135201526Sobrien		else
1136201526Sobrien			syspath = estrdup(syspath);
1137201526Sobrien
113818730Ssteve		for (start = syspath; *start != '\0'; start = cp) {
113918730Ssteve			for (cp = start; *cp != '\0' && *cp != ':'; cp++)
114018730Ssteve				continue;
1141201526Sobrien			if (*cp == ':') {
1142201526Sobrien				*cp++ = '\0';
1143201526Sobrien			}
1144201526Sobrien			/* look for magic parent directory search string */
1145201526Sobrien			if (strncmp(".../", start, 4) == 0) {
1146201526Sobrien				if (Dir_FindHereOrAbove(curdir, start + 4,
1147201526Sobrien				    found_dir, sizeof(found_dir))) {
1148201526Sobrien					Path_AddDir(&sysIncPath, found_dir);
1149201526Sobrien				}
115018730Ssteve			} else {
1151144020Sharti				Path_AddDir(&sysIncPath, start);
115218730Ssteve			}
115318730Ssteve		}
1154201526Sobrien		if (syspath != defsyspath)
1155201526Sobrien			free(syspath);
115618730Ssteve	}
11571590Srgrimes
115818730Ssteve	/*
115918730Ssteve	 * Read in the built-in rules first, followed by the specified
116018730Ssteve	 * makefile, if it was (makefile != (char *) NULL), or the default
116118730Ssteve	 * Makefile and makefile, in that order, if it wasn't.
116218730Ssteve	 */
116318730Ssteve	if (!noBuiltins) {
1164138916Sharti		/* Path of sys.mk */
1165138916Sharti		Lst sysMkPath = Lst_Initializer(sysMkPath);
1166138512Sharti		LstNode *ln;
1167146064Sharti		char	defsysmk[] = PATH_DEFSYSMK;
116818730Ssteve
1169146064Sharti		Path_Expand(defsysmk, &sysIncPath, &sysMkPath);
1170138916Sharti		if (Lst_IsEmpty(&sysMkPath))
1171143412Sharti			Fatal("make: no system rules (%s).", PATH_DEFSYSMK);
1172143808Sharti		LST_FOREACH(ln, &sysMkPath) {
1173143808Sharti			if (!ReadMakefile(Lst_Datum(ln)))
1174143808Sharti				break;
1175143808Sharti		}
117669527Swill		if (ln != NULL)
117718730Ssteve			Fatal("make: cannot open %s.", (char *)Lst_Datum(ln));
1178138916Sharti		Lst_Destroy(&sysMkPath, free);
117918730Ssteve	}
118018730Ssteve
1181138916Sharti	if (!Lst_IsEmpty(&makefiles)) {
1182138512Sharti		LstNode *ln;
11831590Srgrimes
1184143808Sharti		LST_FOREACH(ln, &makefiles) {
1185167330Sfjoe			if (!TryReadMakefile(Lst_Datum(ln)))
1186143808Sharti				break;
1187143808Sharti		}
118869527Swill		if (ln != NULL)
11891590Srgrimes			Fatal("make: cannot open %s.", (char *)Lst_Datum(ln));
1190167330Sfjoe	} else if (!TryReadMakefile("BSDmakefile"))
1191167330Sfjoe	    if (!TryReadMakefile("makefile"))
1192167330Sfjoe		TryReadMakefile("Makefile");
11931590Srgrimes
1194143808Sharti	ReadMakefile(".depend");
11951590Srgrimes
1196176842Syar	/* Install all the flags into the MAKEFLAGS envariable. */
1197146580Sharti	if (((p = Var_Value(".MAKEFLAGS", VAR_GLOBAL)) != NULL) && *p)
11981590Srgrimes		setenv("MAKEFLAGS", p, 1);
1199176839Syar	else
1200176839Syar		setenv("MAKEFLAGS", "", 1);
12011590Srgrimes
12021590Srgrimes	/*
12031590Srgrimes	 * For compatibility, look at the directories in the VPATH variable
12041590Srgrimes	 * and add them to the search path, if the variable is defined. The
12051590Srgrimes	 * variable's value is in the same format as the PATH envariable, i.e.
12061590Srgrimes	 * <directory>:<directory>:<directory>...
12071590Srgrimes	 */
12081590Srgrimes	if (Var_Exists("VPATH", VAR_CMD)) {
12091590Srgrimes		/*
12101590Srgrimes		 * GCC stores string constants in read-only memory, but
12111590Srgrimes		 * Var_Subst will want to write this thing, so store it
12121590Srgrimes		 * in an array
12131590Srgrimes		 */
12141590Srgrimes		static char VPATH[] = "${VPATH}";
1215142457Sharti		Buffer	*buf;
1216142457Sharti		char	*vpath;
1217142457Sharti		char	*ptr;
1218142457Sharti		char	savec;
12191590Srgrimes
1220146027Sharti		buf = Var_Subst(VPATH, VAR_CMD, FALSE);
1221142457Sharti
1222143959Sharti		vpath = Buf_Data(buf);
12231590Srgrimes		do {
12241590Srgrimes			/* skip to end of directory */
1225142457Sharti			for (ptr = vpath; *ptr != ':' && *ptr != '\0'; ptr++)
1226141969Sharti				;
1227141969Sharti
12281590Srgrimes			/* Save terminator character so know when to stop */
1229141969Sharti			savec = *ptr;
1230141969Sharti			*ptr = '\0';
1231141969Sharti
12321590Srgrimes			/* Add directory to search path */
1233144020Sharti			Path_AddDir(&dirSearchPath, vpath);
1234141969Sharti
1235142457Sharti			vpath = ptr + 1;
1236141969Sharti		} while (savec != '\0');
1237142457Sharti
1238142457Sharti		Buf_Destroy(buf, TRUE);
12391590Srgrimes	}
12401590Srgrimes
12411590Srgrimes	/*
12421590Srgrimes	 * Now that all search paths have been read for suffixes et al, it's
12431590Srgrimes	 * time to add the default search path to their lists...
12441590Srgrimes	 */
12451590Srgrimes	Suff_DoPaths();
12461590Srgrimes
12471590Srgrimes	/* print the initial graph, if the user requested it */
12481590Srgrimes	if (DEBUG(GRAPH1))
12491590Srgrimes		Targ_PrintGraph(1);
12501590Srgrimes
125117193Sbde	/* print the values of any variables requested by the user */
1252181021Sed	if (Lst_IsEmpty(&variables) && !printGraphOnly) {
12531590Srgrimes		/*
1254141974Sharti		 * Since the user has not requested that any variables
1255142008Sharti		 * be printed, we can build targets.
1256141974Sharti		 *
1257142008Sharti		 * Have read the entire graph and need to make a list of targets
1258141974Sharti		 * to create. If none was given on the command line, we consult
1259141974Sharti		 * the parsing module to find the main target(s) to create.
12601590Srgrimes		 */
1261138916Sharti		Lst targs = Lst_Initializer(targs);
1262138916Sharti
1263177101Sobrien		if (!is_posix && mfAutoDeps) {
1264167330Sfjoe			/*
1265167330Sfjoe			 * Check if any of the makefiles are out-of-date.
1266167330Sfjoe			 */
1267167330Sfjoe			Remake_Makefiles();
1268167330Sfjoe		}
1269167330Sfjoe
1270138916Sharti		if (Lst_IsEmpty(&create))
1271138916Sharti			Parse_MainName(&targs);
1272101460Sru		else
1273138916Sharti			Targ_FindList(&targs, &create, TARG_CREATE);
1274101460Sru
1275141974Sharti		if (compatMake) {
1276101460Sru			/*
1277141974Sharti			 * Compat_Init will take care of creating
1278141974Sharti			 * all the targets as well as initializing
1279141974Sharti			 * the module.
1280101460Sru			 */
1281141974Sharti			Compat_Run(&targs);
1282141974Sharti			outOfDate = 0;
1283141974Sharti		} else {
1284141974Sharti			/*
1285141974Sharti			 * Initialize job module before traversing
1286141974Sharti			 * the graph, now that any .BEGIN and .END
1287141974Sharti			 * targets have been read.  This is done
1288141974Sharti			 * only if the -q flag wasn't given (to
1289141974Sharti			 * prevent the .BEGIN from being executed
1290141974Sharti			 * should it exist).
1291141974Sharti			 */
1292101460Sru			if (!queryFlag) {
1293146140Sharti				Job_Init(jobLimit);
1294101460Sru				jobsRunning = TRUE;
1295101460Sru			}
1296101460Sru
1297101460Sru			/* Traverse the graph, checking on all the targets */
1298138916Sharti			outOfDate = Make_Run(&targs);
12991590Srgrimes		}
1300138916Sharti		Lst_Destroy(&targs, NOFREE);
1301141974Sharti
1302141974Sharti	} else {
1303146141Sharti		Var_Print(&variables, expandVars);
130417193Sbde	}
13058874Srgrimes
1306138920Sru	Lst_Destroy(&variables, free);
1307138920Sru	Lst_Destroy(&makefiles, free);
1308167330Sfjoe	Lst_Destroy(&source_makefiles, free);
1309138916Sharti	Lst_Destroy(&create, free);
13105814Sjkh
13111590Srgrimes	/* print the graph now it's been processed if the user requested it */
13121590Srgrimes	if (DEBUG(GRAPH2))
13131590Srgrimes		Targ_PrintGraph(2);
13141590Srgrimes
1315186279Sfjoe	if (queryFlag)
1316186279Sfjoe		return (outOfDate);
1317186279Sfjoe
1318186279Sfjoe	if (makeErrors != 0)
1319186279Sfjoe		Finish(makeErrors);
1320186279Sfjoe
1321186279Sfjoe	return (0);
13221590Srgrimes}
1323