xref: /netbsd-src/usr.bin/make/main.c (revision d20841bb642898112fe68f0ad3f7b26dddf56f07)
1 /*	$NetBSD: main.c,v 1.98 2004/02/05 23:31:34 ross Exp $	*/
2 
3 /*
4  * Copyright (c) 1988, 1989, 1990, 1993
5  *	The Regents of the University of California.  All rights reserved.
6  *
7  * This code is derived from software contributed to Berkeley by
8  * Adam de Boor.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  * 3. Neither the name of the University nor the names of its contributors
19  *    may be used to endorse or promote products derived from this software
20  *    without specific prior written permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32  * SUCH DAMAGE.
33  */
34 
35 /*
36  * Copyright (c) 1989 by Berkeley Softworks
37  * All rights reserved.
38  *
39  * This code is derived from software contributed to Berkeley by
40  * Adam de Boor.
41  *
42  * Redistribution and use in source and binary forms, with or without
43  * modification, are permitted provided that the following conditions
44  * are met:
45  * 1. Redistributions of source code must retain the above copyright
46  *    notice, this list of conditions and the following disclaimer.
47  * 2. Redistributions in binary form must reproduce the above copyright
48  *    notice, this list of conditions and the following disclaimer in the
49  *    documentation and/or other materials provided with the distribution.
50  * 3. All advertising materials mentioning features or use of this software
51  *    must display the following acknowledgement:
52  *	This product includes software developed by the University of
53  *	California, Berkeley and its contributors.
54  * 4. Neither the name of the University nor the names of its contributors
55  *    may be used to endorse or promote products derived from this software
56  *    without specific prior written permission.
57  *
58  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
59  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
60  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
61  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
62  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
63  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
64  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
65  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
66  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
67  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
68  * SUCH DAMAGE.
69  */
70 
71 #ifdef MAKE_BOOTSTRAP
72 static char rcsid[] = "$NetBSD: main.c,v 1.98 2004/02/05 23:31:34 ross Exp $";
73 #else
74 #include <sys/cdefs.h>
75 #ifndef lint
76 __COPYRIGHT("@(#) Copyright (c) 1988, 1989, 1990, 1993\n\
77 	The Regents of the University of California.  All rights reserved.\n");
78 #endif /* not lint */
79 
80 #ifndef lint
81 #if 0
82 static char sccsid[] = "@(#)main.c	8.3 (Berkeley) 3/19/94";
83 #else
84 __RCSID("$NetBSD: main.c,v 1.98 2004/02/05 23:31:34 ross Exp $");
85 #endif
86 #endif /* not lint */
87 #endif
88 
89 /*-
90  * main.c --
91  *	The main file for this entire program. Exit routines etc
92  *	reside here.
93  *
94  * Utility functions defined in this file:
95  *	Main_ParseArgLine	Takes a line of arguments, breaks them and
96  *				treats them as if they were given when first
97  *				invoked. Used by the parse module to implement
98  *				the .MFLAGS target.
99  *
100  *	Error			Print a tagged error message. The global
101  *				MAKE variable must have been defined. This
102  *				takes a format string and two optional
103  *				arguments for it.
104  *
105  *	Fatal			Print an error message and exit. Also takes
106  *				a format string and two arguments.
107  *
108  *	Punt			Aborts all jobs and exits with a message. Also
109  *				takes a format string and two arguments.
110  *
111  *	Finish			Finish things up by printing the number of
112  *				errors which occurred, as passed to it, and
113  *				exiting.
114  */
115 
116 #include <sys/types.h>
117 #include <sys/time.h>
118 #include <sys/param.h>
119 #include <sys/resource.h>
120 #include <sys/signal.h>
121 #include <sys/stat.h>
122 #ifndef MAKE_BOOTSTRAP
123 #include <sys/utsname.h>
124 #endif
125 #include <sys/wait.h>
126 
127 #include <errno.h>
128 #include <fcntl.h>
129 #include <stdarg.h>
130 #include <stdio.h>
131 #include <stdlib.h>
132 #include <time.h>
133 
134 #include "make.h"
135 #include "hash.h"
136 #include "dir.h"
137 #include "job.h"
138 #include "pathnames.h"
139 #include "trace.h"
140 
141 #ifdef USE_IOVEC
142 #include <sys/uio.h>
143 #endif
144 
145 #ifndef	DEFMAXLOCAL
146 #define	DEFMAXLOCAL DEFMAXJOBS
147 #endif	/* DEFMAXLOCAL */
148 
149 Lst			create;		/* Targets to be made */
150 time_t			now;		/* Time at start of make */
151 GNode			*DEFAULT;	/* .DEFAULT node */
152 Boolean			allPrecious;	/* .PRECIOUS given on line by itself */
153 
154 static Boolean		noBuiltins;	/* -r flag */
155 static Lst		makefiles;	/* ordered list of makefiles to read */
156 static Boolean		printVars;	/* print value of one or more vars */
157 static Lst		variables;	/* list of variables to print */
158 int			maxJobs;	/* -j argument */
159 static int		maxLocal;	/* -L argument */
160 Boolean			compatMake;	/* -B argument */
161 Boolean			debug;		/* -d flag */
162 Boolean			noExecute;	/* -n flag */
163 Boolean			noRecursiveExecute;	/* -N flag */
164 Boolean			keepgoing;	/* -k flag */
165 Boolean			queryFlag;	/* -q flag */
166 Boolean			touchFlag;	/* -t flag */
167 Boolean			usePipes;	/* !-P flag */
168 Boolean			ignoreErrors;	/* -i flag */
169 Boolean			beSilent;	/* -s flag */
170 Boolean			oldVars;	/* variable substitution style */
171 Boolean			checkEnvFirst;	/* -e flag */
172 Boolean			parseWarnFatal;	/* -W flag */
173 Boolean			jobServer; 	/* -J flag */
174 Boolean			varNoExportEnv;	/* -X flag */
175 static Boolean		jobsRunning;	/* TRUE if the jobs might be running */
176 static const char *	tracefile;
177 static char *		Check_Cwd_av(int, char **, int);
178 static void		MainParseArgs(int, char **);
179 static int		ReadMakefile(ClientData, ClientData);
180 static void		usage(void);
181 
182 static char curdir[MAXPATHLEN + 1];	/* startup directory */
183 static char objdir[MAXPATHLEN + 1];	/* where we chdir'ed to */
184 char *progname;				/* the program name */
185 
186 Boolean forceJobs = FALSE;
187 
188 extern Lst parseIncPath;
189 
190 /*-
191  * MainParseArgs --
192  *	Parse a given argument vector. Called from main() and from
193  *	Main_ParseArgLine() when the .MAKEFLAGS target is used.
194  *
195  *	XXX: Deal with command line overriding .MAKEFLAGS in makefile
196  *
197  * Results:
198  *	None
199  *
200  * Side Effects:
201  *	Various global and local flags will be set depending on the flags
202  *	given
203  */
204 static void
205 MainParseArgs(int argc, char **argv)
206 {
207 	char *p;
208 	int c;
209 	int arginc;
210 	char *argvalue;
211 	const char *getopt_def;
212 	char *optscan;
213 	Boolean inOption;
214 	char found_path[MAXPATHLEN + 1];	/* for searching for sys.mk */
215 
216 #ifdef REMOTE
217 # define OPTFLAGS "BD:I:J:L:NPST:V:WXd:ef:ij:km:nqrst"
218 #else
219 # define OPTFLAGS "BD:I:J:NPST:V:WXd:ef:ij:km:nqrst"
220 #endif
221 #undef optarg
222 #define optarg argvalue
223 /* Can't actually use getopt(3) because rescanning is not portable */
224 
225 	getopt_def = OPTFLAGS;
226 rearg:
227 	inOption = FALSE;
228 	while(argc > 1) {
229 		char *getopt_spec;
230 		if(!inOption)
231 			optscan = argv[1];
232 		c = *optscan++;
233 		arginc = 0;
234 		if(inOption) {
235 			if(c == '\0') {
236 				++argv;
237 				--argc;
238 				inOption = FALSE;
239 				continue;
240 			}
241 		} else {
242 			if (c != '-')
243 				break;
244 			inOption = TRUE;
245 			c = *optscan++;
246 		}
247 		/* '-' found at some earlier point */
248 		getopt_spec = strchr(getopt_def, c);
249 		if(c != '\0' && getopt_spec != NULL && getopt_spec[1] == ':') {
250 			/* -<something> found, and <something> should have an arg */
251 			inOption = FALSE;
252 			arginc = 1;
253 			argvalue = optscan;
254 			if(*argvalue == '\0') {
255 				argvalue = argv[2];
256 				arginc = 2;
257 			}
258 		}
259 		switch(c) {
260 		case '\0':
261 			arginc = 1;
262 			inOption = FALSE;
263 			break;
264 		case 'B':
265 			compatMake = TRUE;
266 			Var_Append(MAKEFLAGS, "-B", VAR_GLOBAL);
267 			break;
268 		case 'D':
269 			Var_Set(optarg, "1", VAR_GLOBAL, 0);
270 			Var_Append(MAKEFLAGS, "-D", VAR_GLOBAL);
271 			Var_Append(MAKEFLAGS, optarg, VAR_GLOBAL);
272 			break;
273 		case 'I':
274 			Parse_AddIncludeDir(optarg);
275 			Var_Append(MAKEFLAGS, "-I", VAR_GLOBAL);
276 			Var_Append(MAKEFLAGS, optarg, VAR_GLOBAL);
277 			break;
278 		case 'J':
279 			if (sscanf(optarg, "%d,%d", &job_pipe[0], &job_pipe[1]) != 2) {
280 			    /* backslash to avoid trigraph ??) */
281 			    (void)fprintf(stderr,
282 				"%s: internal error -- J option malformed (%s?\?)\n",
283 				progname, optarg);
284 				usage();
285 			}
286 			if ((fcntl(job_pipe[0], F_GETFD, 0) < 0) ||
287 			    (fcntl(job_pipe[1], F_GETFD, 0) < 0)) {
288 #if 0
289 			    (void)fprintf(stderr,
290 				"%s: warning -- J descriptors were closed!\n",
291 				progname);
292 #endif
293 			    job_pipe[0] = -1;
294 			    job_pipe[1] = -1;
295 			    compatMake = TRUE;
296 			} else {
297 			    Var_Append(MAKEFLAGS, "-J", VAR_GLOBAL);
298 			    Var_Append(MAKEFLAGS, optarg, VAR_GLOBAL);
299 			    jobServer = TRUE;
300 			}
301 			break;
302 #ifdef REMOTE
303 		case 'L':
304 			maxLocal = strtol(optarg, &p, 0);
305 			if (*p != '\0' || maxLocal < 1) {
306 			    (void) fprintf(stderr, "%s: illegal argument to -L -- must be positive integer!\n",
307 				progname);
308 			    exit(1);
309 			}
310 			Var_Append(MAKEFLAGS, "-L", VAR_GLOBAL);
311 			Var_Append(MAKEFLAGS, optarg, VAR_GLOBAL);
312 			break;
313 #endif
314 		case 'N':
315 			noExecute = TRUE;
316 			noRecursiveExecute = TRUE;
317 			Var_Append(MAKEFLAGS, "-N", VAR_GLOBAL);
318 			break;
319 		case 'P':
320 			usePipes = FALSE;
321 			Var_Append(MAKEFLAGS, "-P", VAR_GLOBAL);
322 			break;
323 		case 'S':
324 			keepgoing = FALSE;
325 			Var_Append(MAKEFLAGS, "-S", VAR_GLOBAL);
326 			break;
327 		case 'T':
328 			tracefile = estrdup(optarg);
329 			Var_Append(MAKEFLAGS, "-T", VAR_GLOBAL);
330 			Var_Append(MAKEFLAGS, optarg, VAR_GLOBAL);
331 			break;
332 		case 'V':
333 			printVars = TRUE;
334 			(void)Lst_AtEnd(variables, (ClientData)optarg);
335 			Var_Append(MAKEFLAGS, "-V", VAR_GLOBAL);
336 			Var_Append(MAKEFLAGS, optarg, VAR_GLOBAL);
337 			break;
338 		case 'W':
339 			parseWarnFatal = TRUE;
340 			break;
341 		case 'X':
342 			varNoExportEnv = TRUE;
343 			Var_Append(MAKEFLAGS, "-X", VAR_GLOBAL);
344 			break;
345 		case 'd': {
346 			char *modules = optarg;
347 
348 			for (; *modules; ++modules)
349 				switch (*modules) {
350 				case 'A':
351 					debug = ~0;
352 					break;
353 				case 'a':
354 					debug |= DEBUG_ARCH;
355 					break;
356 				case 'c':
357 					debug |= DEBUG_COND;
358 					break;
359 				case 'd':
360 					debug |= DEBUG_DIR;
361 					break;
362 				case 'e':
363 					debug |= DEBUG_ERROR;
364 					break;
365 				case 'f':
366 					debug |= DEBUG_FOR;
367 					break;
368 				case 'g':
369 					if (modules[1] == '1') {
370 						debug |= DEBUG_GRAPH1;
371 						++modules;
372 					}
373 					else if (modules[1] == '2') {
374 						debug |= DEBUG_GRAPH2;
375 						++modules;
376 					}
377 					else if (modules[1] == '3') {
378 						debug |= DEBUG_GRAPH3;
379 						++modules;
380 					}
381 					break;
382 				case 'j':
383 					debug |= DEBUG_JOB;
384 					break;
385 				case 'm':
386 					debug |= DEBUG_MAKE;
387 					break;
388 				case 's':
389 					debug |= DEBUG_SUFF;
390 					break;
391 				case 't':
392 					debug |= DEBUG_TARG;
393 					break;
394 				case 'v':
395 					debug |= DEBUG_VAR;
396 					break;
397 				case 'x':
398 					debug |= DEBUG_SHELL;
399 					break;
400 				default:
401 					(void)fprintf(stderr,
402 				"%s: illegal argument to d option -- %c\n",
403 					    progname, *modules);
404 					usage();
405 				}
406 			Var_Append(MAKEFLAGS, "-d", VAR_GLOBAL);
407 			Var_Append(MAKEFLAGS, optarg, VAR_GLOBAL);
408 			break;
409 		}
410 		case 'e':
411 			checkEnvFirst = TRUE;
412 			Var_Append(MAKEFLAGS, "-e", VAR_GLOBAL);
413 			break;
414 		case 'f':
415 			(void)Lst_AtEnd(makefiles, (ClientData)optarg);
416 			break;
417 		case 'i':
418 			ignoreErrors = TRUE;
419 			Var_Append(MAKEFLAGS, "-i", VAR_GLOBAL);
420 			break;
421 		case 'j':
422 			forceJobs = TRUE;
423 			maxJobs = strtol(optarg, &p, 0);
424 			if (*p != '\0' || maxJobs < 1) {
425 				(void) fprintf(stderr, "%s: illegal argument to -j -- must be positive integer!\n",
426 				    progname);
427 				exit(1);
428 			}
429 #ifndef REMOTE
430 			maxLocal = maxJobs;
431 #endif
432 			Var_Append(MAKEFLAGS, "-j", VAR_GLOBAL);
433 			Var_Append(MAKEFLAGS, optarg, VAR_GLOBAL);
434 			break;
435 		case 'k':
436 			keepgoing = TRUE;
437 			Var_Append(MAKEFLAGS, "-k", VAR_GLOBAL);
438 			break;
439 		case 'm':
440 			/* look for magic parent directory search string */
441 			if (strncmp(".../", optarg, 4) == 0) {
442 				if (!Dir_FindHereOrAbove(curdir, optarg+4,
443 				    found_path, sizeof(found_path)))
444 					break;		/* nothing doing */
445 				(void) Dir_AddDir(sysIncPath, found_path);
446 
447 			} else {
448 				(void) Dir_AddDir(sysIncPath, optarg);
449 			}
450 			Var_Append(MAKEFLAGS, "-m", VAR_GLOBAL);
451 			Var_Append(MAKEFLAGS, optarg, VAR_GLOBAL);
452 			break;
453 		case 'n':
454 			noExecute = TRUE;
455 			Var_Append(MAKEFLAGS, "-n", VAR_GLOBAL);
456 			break;
457 		case 'q':
458 			queryFlag = TRUE;
459 			/* Kind of nonsensical, wot? */
460 			Var_Append(MAKEFLAGS, "-q", VAR_GLOBAL);
461 			break;
462 		case 'r':
463 			noBuiltins = TRUE;
464 			Var_Append(MAKEFLAGS, "-r", VAR_GLOBAL);
465 			break;
466 		case 's':
467 			beSilent = TRUE;
468 			Var_Append(MAKEFLAGS, "-s", VAR_GLOBAL);
469 			break;
470 		case 't':
471 			touchFlag = TRUE;
472 			Var_Append(MAKEFLAGS, "-t", VAR_GLOBAL);
473 			break;
474 		default:
475 		case '?':
476 			usage();
477 		}
478 		argv += arginc;
479 		argc -= arginc;
480 	}
481 
482 	oldVars = TRUE;
483 
484 	/*
485 	 * See if the rest of the arguments are variable assignments and
486 	 * perform them if so. Else take them to be targets and stuff them
487 	 * on the end of the "create" list.
488 	 */
489 	for (; argc > 1; ++argv, --argc)
490 		if (Parse_IsVar(argv[1])) {
491 			Parse_DoVar(argv[1], VAR_CMD);
492 		} else {
493 			if (!*argv[1])
494 				Punt("illegal (null) argument.");
495 			if (*argv[1] == '-')
496 				goto rearg;
497 			(void)Lst_AtEnd(create, (ClientData)estrdup(argv[1]));
498 		}
499 }
500 
501 /*-
502  * Main_ParseArgLine --
503  *  	Used by the parse module when a .MFLAGS or .MAKEFLAGS target
504  *	is encountered and by main() when reading the .MAKEFLAGS envariable.
505  *	Takes a line of arguments and breaks it into its
506  * 	component words and passes those words and the number of them to the
507  *	MainParseArgs function.
508  *	The line should have all its leading whitespace removed.
509  *
510  * Input:
511  *	line		Line to fracture
512  *
513  * Results:
514  *	None
515  *
516  * Side Effects:
517  *	Only those that come from the various arguments.
518  */
519 void
520 Main_ParseArgLine(char *line)
521 {
522 	char **argv;			/* Manufactured argument vector */
523 	int argc;			/* Number of arguments in argv */
524 	char *args;			/* Space used by the args */
525 	char *buf, *p1;
526 	char *argv0 = Var_Value(".MAKE", VAR_GLOBAL, &p1);
527 	size_t len;
528 
529 	if (line == NULL)
530 		return;
531 	for (; *line == ' '; ++line)
532 		continue;
533 	if (!*line)
534 		return;
535 
536 	buf = emalloc(len = strlen(line) + strlen(argv0) + 2);
537 	(void)snprintf(buf, len, "%s %s", argv0, line);
538 	if (p1)
539 		free(p1);
540 
541 	argv = brk_string(buf, &argc, TRUE, &args);
542 	free(buf);
543 	MainParseArgs(argc, argv);
544 
545 	free(args);
546 	free(argv);
547 }
548 
549 Boolean
550 Main_SetObjdir(const char *path)
551 {
552 	struct stat sb;
553 	char *p = NULL;
554 	char buf[MAXPATHLEN + 1];
555 	Boolean rc = FALSE;
556 
557 	/* expand variable substitutions */
558 	if (strchr(path, '$') != 0) {
559 		snprintf(buf, MAXPATHLEN, "%s", path);
560 		path = p = Var_Subst(NULL, buf, VAR_GLOBAL, 0);
561 	}
562 
563 	if (path[0] != '/') {
564 		snprintf(buf, MAXPATHLEN, "%s/%s", curdir, path);
565 		path = buf;
566 	}
567 
568 	/* look for the directory and try to chdir there */
569 	if (stat(path, &sb) == 0 && S_ISDIR(sb.st_mode)) {
570 		if (chdir(path)) {
571 			(void)fprintf(stderr, "make warning: %s: %s.\n",
572 				      path, strerror(errno));
573 		} else {
574 			strncpy(objdir, path, MAXPATHLEN);
575 			Var_Set(".OBJDIR", objdir, VAR_GLOBAL, 0);
576 			setenv("PWD", objdir, 1);
577 			Dir_InitDot();
578 			rc = TRUE;
579 		}
580 	}
581 
582 	if (p)
583 		free(p);
584 	return rc;
585 }
586 
587 
588 /*-
589  * main --
590  *	The main function, for obvious reasons. Initializes variables
591  *	and a few modules, then parses the arguments give it in the
592  *	environment and on the command line. Reads the system makefile
593  *	followed by either Makefile, makefile or the file given by the
594  *	-f argument. Sets the .MAKEFLAGS PMake variable based on all the
595  *	flags it has received by then uses either the Make or the Compat
596  *	module to create the initial list of targets.
597  *
598  * Results:
599  *	If -q was given, exits -1 if anything was out-of-date. Else it exits
600  *	0.
601  *
602  * Side Effects:
603  *	The program exits when done. Targets are created. etc. etc. etc.
604  */
605 int
606 main(int argc, char **argv)
607 {
608 	Lst targs;	/* target nodes to create -- passed to Make_Init */
609 	Boolean outOfDate = TRUE; 	/* FALSE if all targets up to date */
610 	struct stat sb, sa;
611 	char *p1, *path, *pwd;
612 	char mdpath[MAXPATHLEN];
613     	char *machine = getenv("MACHINE");
614 	const char *machine_arch = getenv("MACHINE_ARCH");
615 	char *syspath = getenv("MAKESYSPATH");
616 	Lst sysMkPath;			/* Path of sys.mk */
617 	char *cp = NULL, *start;
618 					/* avoid faults on read-only strings */
619 	static char defsyspath[] = _PATH_DEFSYSPATH;
620 	char found_path[MAXPATHLEN + 1];	/* for searching for sys.mk */
621 
622 	if ((progname = strrchr(argv[0], '/')) != NULL)
623 		progname++;
624 	else
625 		progname = argv[0];
626 #ifdef RLIMIT_NOFILE
627 	/*
628 	 * get rid of resource limit on file descriptors
629 	 */
630 	{
631 		struct rlimit rl;
632 		if (getrlimit(RLIMIT_NOFILE, &rl) != -1 &&
633 		    rl.rlim_cur != rl.rlim_max) {
634 			rl.rlim_cur = rl.rlim_max;
635 			(void) setrlimit(RLIMIT_NOFILE, &rl);
636 		}
637 	}
638 #endif
639 	/*
640 	 * Find where we are and take care of PWD for the automounter...
641 	 * All this code is so that we know where we are when we start up
642 	 * on a different machine with pmake.
643 	 */
644 	if (getcwd(curdir, MAXPATHLEN) == NULL) {
645 		(void)fprintf(stderr, "%s: %s.\n", progname, strerror(errno));
646 		exit(2);
647 	}
648 
649 	if (stat(curdir, &sa) == -1) {
650 	    (void)fprintf(stderr, "%s: %s: %s.\n",
651 		 progname, curdir, strerror(errno));
652 	    exit(2);
653 	}
654 
655 	/*
656 	 * Overriding getcwd() with $PWD totally breaks MAKEOBJDIRPREFIX
657 	 * since the value of curdir can very depending on how we got
658 	 * here.  Ie sitting at a shell prompt (shell that provides $PWD)
659 	 * or via subdir.mk in which case its likely a shell which does
660 	 * not provide it.
661 	 * So, to stop it breaking this case only, we ignore PWD if
662 	 * MAKEOBJDIRPREFIX is set or MAKEOBJDIR contains a transform.
663 	 */
664 	if ((pwd = getenv("PWD")) != NULL && getenv("MAKEOBJDIRPREFIX") == NULL) {
665 		const char *makeobjdir = getenv("MAKEOBJDIR");
666 
667 		if (makeobjdir == NULL || !strchr(makeobjdir, '$')) {
668 			if (stat(pwd, &sb) == 0 && sa.st_ino == sb.st_ino &&
669 			    sa.st_dev == sb.st_dev)
670 				(void) strncpy(curdir, pwd, MAXPATHLEN);
671 		}
672 	}
673 
674 	/*
675 	 * Get the name of this type of MACHINE from utsname
676 	 * so we can share an executable for similar machines.
677 	 * (i.e. m68k: amiga hp300, mac68k, sun3, ...)
678 	 *
679 	 * Note that both MACHINE and MACHINE_ARCH are decided at
680 	 * run-time.
681 	 */
682 	if (!machine) {
683 #ifndef MAKE_BOOTSTRAP
684 	    struct utsname utsname;
685 
686 	    if (uname(&utsname) == -1) {
687 		(void)fprintf(stderr, "%s: uname failed (%s).\n", progname,
688 		    strerror(errno));
689 		exit(2);
690 	    }
691 	    machine = utsname.machine;
692 #else
693 #ifdef MAKE_MACHINE
694 	    machine = MAKE_MACHINE;
695 #else
696 	    machine = "unknown";
697 #endif
698 #endif
699 	}
700 
701 	if (!machine_arch) {
702 #ifndef MACHINE_ARCH
703 #ifdef MAKE_MACHINE_ARCH
704             machine_arch = MAKE_MACHINE_ARCH;
705 #else
706 	    machine_arch = "unknown";
707 #endif
708 #else
709 	    machine_arch = MACHINE_ARCH;
710 #endif
711 	}
712 
713 	/*
714 	 * Just in case MAKEOBJDIR wants us to do something tricky.
715 	 */
716 	Var_Init();		/* Initialize the lists of variables for
717 				 * parsing arguments */
718 	Var_Set(".CURDIR", curdir, VAR_GLOBAL, 0);
719 	Var_Set("MACHINE", machine, VAR_GLOBAL, 0);
720 	Var_Set("MACHINE_ARCH", machine_arch, VAR_GLOBAL, 0);
721 #ifdef MAKE_VERSION
722 	Var_Set("MAKE_VERSION", MAKE_VERSION, VAR_GLOBAL, 0);
723 #endif
724 	Var_Set(".newline", "\n", VAR_GLOBAL, 0); /* handy for :@ loops */
725 
726 	/*
727 	 * Find the .OBJDIR.  If MAKEOBJDIRPREFIX, or failing that,
728 	 * MAKEOBJDIR is set in the environment, try only that value
729 	 * and fall back to .CURDIR if it does not exist.
730 	 *
731 	 * Otherwise, try _PATH_OBJDIR.MACHINE, _PATH_OBJDIR, and
732 	 * finally _PATH_OBJDIRPREFIX`pwd`, in that order.  If none
733 	 * of these paths exist, just use .CURDIR.
734 	 */
735 	Dir_Init(curdir);
736 	(void) Main_SetObjdir(curdir);
737 
738 	if ((path = getenv("MAKEOBJDIRPREFIX")) != NULL) {
739 		(void) snprintf(mdpath, MAXPATHLEN, "%s%s", path, curdir);
740 		(void) Main_SetObjdir(mdpath);
741 	} else if ((path = getenv("MAKEOBJDIR")) != NULL) {
742 		(void) Main_SetObjdir(path);
743 	} else {
744 		(void) snprintf(mdpath, MAXPATHLEN, "%s.%s", _PATH_OBJDIR, machine);
745 		if (!Main_SetObjdir(mdpath) && !Main_SetObjdir(_PATH_OBJDIR)) {
746 			(void) snprintf(mdpath, MAXPATHLEN, "%s%s",
747 					_PATH_OBJDIRPREFIX, curdir);
748 			(void) Main_SetObjdir(mdpath);
749 		}
750 	}
751 
752 	create = Lst_Init(FALSE);
753 	makefiles = Lst_Init(FALSE);
754 	printVars = FALSE;
755 	variables = Lst_Init(FALSE);
756 	beSilent = FALSE;		/* Print commands as executed */
757 	ignoreErrors = FALSE;		/* Pay attention to non-zero returns */
758 	noExecute = FALSE;		/* Execute all commands */
759 	noRecursiveExecute = FALSE;	/* Execute all .MAKE targets */
760 	keepgoing = FALSE;		/* Stop on error */
761 	allPrecious = FALSE;		/* Remove targets when interrupted */
762 	queryFlag = FALSE;		/* This is not just a check-run */
763 	noBuiltins = FALSE;		/* Read the built-in rules */
764 	touchFlag = FALSE;		/* Actually update targets */
765 	usePipes = TRUE;		/* Catch child output in pipes */
766 	debug = 0;			/* No debug verbosity, please. */
767 	jobsRunning = FALSE;
768 
769 	maxLocal = DEFMAXLOCAL;		/* Set default local max concurrency */
770 #ifdef REMOTE
771 	maxJobs = DEFMAXJOBS;		/* Set default max concurrency */
772 #else
773 	maxJobs = maxLocal;
774 #endif
775 	compatMake = FALSE;		/* No compat mode */
776 
777 
778 	/*
779 	 * Initialize the parsing, directory and variable modules to prepare
780 	 * for the reading of inclusion paths and variable settings on the
781 	 * command line
782 	 */
783 
784 	/*
785 	 * Initialize various variables.
786 	 *	MAKE also gets this name, for compatibility
787 	 *	.MAKEFLAGS gets set to the empty string just in case.
788 	 *	MFLAGS also gets initialized empty, for compatibility.
789 	 */
790 	Parse_Init();
791 	Var_Set("MAKE", argv[0], VAR_GLOBAL, 0);
792 	Var_Set(".MAKE", argv[0], VAR_GLOBAL, 0);
793 	Var_Set(MAKEFLAGS, "", VAR_GLOBAL, 0);
794 	Var_Set(MAKEOVERRIDES, "", VAR_GLOBAL, 0);
795 	Var_Set("MFLAGS", "", VAR_GLOBAL, 0);
796 	Var_Set(".ALLTARGETS", "", VAR_GLOBAL, 0);
797 
798 	/*
799 	 * First snag any flags out of the MAKE environment variable.
800 	 * (Note this is *not* MAKEFLAGS since /bin/make uses that and it's
801 	 * in a different format).
802 	 */
803 #ifdef POSIX
804 	Main_ParseArgLine(getenv("MAKEFLAGS"));
805 #else
806 	Main_ParseArgLine(getenv("MAKE"));
807 #endif
808 
809 	MainParseArgs(argc, argv);
810 
811 	/*
812 	 * Be compatible if user did not specify -j and did not explicitly
813 	 * turned compatibility on
814 	 */
815 	if (!compatMake && !forceJobs) {
816 		compatMake = TRUE;
817 	}
818 
819 	/*
820 	 * Initialize archive, target and suffix modules in preparation for
821 	 * parsing the makefile(s)
822 	 */
823 	Arch_Init();
824 	Targ_Init();
825 	Suff_Init();
826 	Trace_Init(tracefile);
827 
828 	DEFAULT = NILGNODE;
829 	(void)time(&now);
830 
831 	Trace_Log(MAKESTART, NULL);
832 
833 	/*
834 	 * Set up the .TARGETS variable to contain the list of targets to be
835 	 * created. If none specified, make the variable empty -- the parser
836 	 * will fill the thing in with the default or .MAIN target.
837 	 */
838 	if (!Lst_IsEmpty(create)) {
839 		LstNode ln;
840 
841 		for (ln = Lst_First(create); ln != NILLNODE;
842 		    ln = Lst_Succ(ln)) {
843 			char *name = (char *)Lst_Datum(ln);
844 
845 			Var_Append(".TARGETS", name, VAR_GLOBAL);
846 		}
847 	} else
848 		Var_Set(".TARGETS", "", VAR_GLOBAL, 0);
849 
850 
851 	/*
852 	 * If no user-supplied system path was given (through the -m option)
853 	 * add the directories from the DEFSYSPATH (more than one may be given
854 	 * as dir1:...:dirn) to the system include path.
855 	 */
856 	if (syspath == NULL || *syspath == '\0')
857 		syspath = defsyspath;
858 	else
859 		syspath = strdup(syspath);
860 
861 	for (start = syspath; *start != '\0'; start = cp) {
862 		for (cp = start; *cp != '\0' && *cp != ':'; cp++)
863 			continue;
864 		if (*cp == ':') {
865 			*cp++ = '\0';
866 		}
867 		/* look for magic parent directory search string */
868 		if (strncmp(".../", start, 4) != 0) {
869 			(void) Dir_AddDir(defIncPath, start);
870 		} else {
871 			if (Dir_FindHereOrAbove(curdir, start+4,
872 			    found_path, sizeof(found_path))) {
873 				(void) Dir_AddDir(defIncPath, found_path);
874 			}
875 		}
876 	}
877 	if (syspath != defsyspath)
878 		free(syspath);
879 
880 	/*
881 	 * Read in the built-in rules first, followed by the specified
882 	 * makefile, if it was (makefile != (char *) NULL), or the default
883 	 * Makefile and makefile, in that order, if it wasn't.
884 	 */
885 	if (!noBuiltins) {
886 		LstNode ln;
887 
888 		sysMkPath = Lst_Init (FALSE);
889 		Dir_Expand(_PATH_DEFSYSMK,
890 			   Lst_IsEmpty(sysIncPath) ? defIncPath : sysIncPath,
891 			   sysMkPath);
892 		if (Lst_IsEmpty(sysMkPath))
893 			Fatal("%s: no system rules (%s).", progname,
894 			    _PATH_DEFSYSMK);
895 		ln = Lst_Find(sysMkPath, (ClientData)NULL, ReadMakefile);
896 		if (ln != NILLNODE)
897 			Fatal("%s: cannot open %s.", progname,
898 			    (char *)Lst_Datum(ln));
899 	}
900 
901 	if (!Lst_IsEmpty(makefiles)) {
902 		LstNode ln;
903 
904 		ln = Lst_Find(makefiles, (ClientData)NULL, ReadMakefile);
905 		if (ln != NILLNODE)
906 			Fatal("%s: cannot open %s.", progname,
907 			    (char *)Lst_Datum(ln));
908 	} else if (!ReadMakefile(UNCONST("makefile"), NULL))
909 		(void)ReadMakefile(UNCONST("Makefile"), NULL);
910 
911 	(void)ReadMakefile(UNCONST(".depend"), NULL);
912 
913 	Var_Append("MFLAGS", Var_Value(MAKEFLAGS, VAR_GLOBAL, &p1), VAR_GLOBAL);
914 	if (p1)
915 	    free(p1);
916 
917 	if (!jobServer && !compatMake)
918 	    Job_ServerStart(maxJobs);
919 	if (DEBUG(JOB))
920 	    printf("job_pipe %d %d, maxjobs %d maxlocal %d compat %d\n", job_pipe[0], job_pipe[1], maxJobs,
921 	           maxLocal, compatMake);
922 
923 	Main_ExportMAKEFLAGS(TRUE);	/* initial export */
924 
925 	Check_Cwd_av(0, NULL, 0);	/* initialize it */
926 
927 
928 	/*
929 	 * For compatibility, look at the directories in the VPATH variable
930 	 * and add them to the search path, if the variable is defined. The
931 	 * variable's value is in the same format as the PATH envariable, i.e.
932 	 * <directory>:<directory>:<directory>...
933 	 */
934 	if (Var_Exists("VPATH", VAR_CMD)) {
935 		char *vpath, savec;
936 		/*
937 		 * GCC stores string constants in read-only memory, but
938 		 * Var_Subst will want to write this thing, so store it
939 		 * in an array
940 		 */
941 		static char VPATH[] = "${VPATH}";
942 
943 		vpath = Var_Subst(NULL, VPATH, VAR_CMD, FALSE);
944 		path = vpath;
945 		do {
946 			/* skip to end of directory */
947 			for (cp = path; *cp != ':' && *cp != '\0'; cp++)
948 				continue;
949 			/* Save terminator character so know when to stop */
950 			savec = *cp;
951 			*cp = '\0';
952 			/* Add directory to search path */
953 			(void) Dir_AddDir(dirSearchPath, path);
954 			*cp = savec;
955 			path = cp + 1;
956 		} while (savec == ':');
957 		(void)free((Address)vpath);
958 	}
959 
960 	/*
961 	 * Now that all search paths have been read for suffixes et al, it's
962 	 * time to add the default search path to their lists...
963 	 */
964 	Suff_DoPaths();
965 
966 	/*
967 	 * Propagate attributes through :: dependency lists.
968 	 */
969 	Targ_Propagate();
970 
971 	/* print the initial graph, if the user requested it */
972 	if (DEBUG(GRAPH1))
973 		Targ_PrintGraph(1);
974 
975 	/* print the values of any variables requested by the user */
976 	if (printVars) {
977 		LstNode ln;
978 
979 		for (ln = Lst_First(variables); ln != NILLNODE;
980 		    ln = Lst_Succ(ln)) {
981 			char *var = (char *)Lst_Datum(ln);
982 			char *value;
983 
984 			if (strchr(var, '$')) {
985 				value = p1 = Var_Subst(NULL, var, VAR_GLOBAL, 0);
986 			} else {
987 				value = Var_Value(var, VAR_GLOBAL, &p1);
988 			}
989 			printf("%s\n", value ? value : "");
990 			if (p1)
991 				free(p1);
992 		}
993 	}
994 
995 	/*
996 	 * Have now read the entire graph and need to make a list of targets
997 	 * to create. If none was given on the command line, we consult the
998 	 * parsing module to find the main target(s) to create.
999 	 */
1000 	if (Lst_IsEmpty(create))
1001 		targs = Parse_MainName();
1002 	else
1003 		targs = Targ_FindList(create, TARG_CREATE);
1004 
1005 	if (!compatMake && !printVars) {
1006 		/*
1007 		 * Initialize job module before traversing the graph, now that
1008 		 * any .BEGIN and .END targets have been read.  This is done
1009 		 * only if the -q flag wasn't given (to prevent the .BEGIN from
1010 		 * being executed should it exist).
1011 		 */
1012 		if (!queryFlag) {
1013 			if (maxLocal == -1)
1014 				maxLocal = maxJobs;
1015 			Job_Init(maxJobs, maxLocal);
1016 			jobsRunning = TRUE;
1017 		}
1018 
1019 		/* Traverse the graph, checking on all the targets */
1020 		outOfDate = Make_Run(targs);
1021 	} else if (!printVars) {
1022 		/*
1023 		 * Compat_Init will take care of creating all the targets as
1024 		 * well as initializing the module.
1025 		 */
1026 		Compat_Run(targs);
1027 	}
1028 
1029 #ifdef CLEANUP
1030 	Lst_Destroy(targs, NOFREE);
1031 	Lst_Destroy(variables, NOFREE);
1032 	Lst_Destroy(makefiles, NOFREE);
1033 	Lst_Destroy(create, (void (*)(ClientData))) free;
1034 #endif
1035 
1036 	/* print the graph now it's been processed if the user requested it */
1037 	if (DEBUG(GRAPH2))
1038 		Targ_PrintGraph(2);
1039 
1040 	Trace_Log(MAKEEND, 0);
1041 
1042 	Suff_End();
1043         Targ_End();
1044 	Arch_End();
1045 	Var_End();
1046 	Parse_End();
1047 	Dir_End();
1048 	Job_End();
1049 	Trace_End();
1050 
1051 	if (queryFlag && outOfDate)
1052 		return(1);
1053 	else
1054 		return(0);
1055 }
1056 
1057 /*-
1058  * ReadMakefile  --
1059  *	Open and parse the given makefile.
1060  *
1061  * Results:
1062  *	TRUE if ok. FALSE if couldn't open file.
1063  *
1064  * Side Effects:
1065  *	lots
1066  */
1067 static Boolean
1068 ReadMakefile(ClientData p, ClientData q)
1069 {
1070 	char *fname = p;		/* makefile to read */
1071 	FILE *stream;
1072 	size_t len = MAXPATHLEN;
1073 	char *name, *path = emalloc(len);
1074 	int setMAKEFILE;
1075 
1076 	if (!strcmp(fname, "-")) {
1077 		Parse_File("(stdin)", stdin);
1078 		Var_Set("MAKEFILE", "", VAR_GLOBAL, 0);
1079 	} else {
1080 		setMAKEFILE = strcmp(fname, ".depend");
1081 
1082 		/* if we've chdir'd, rebuild the path name */
1083 		if (strcmp(curdir, objdir) && *fname != '/') {
1084 			size_t plen = strlen(curdir) + strlen(fname) + 2;
1085 			if (len < plen)
1086 				path = erealloc(path, len = 2 * plen);
1087 
1088 			(void)snprintf(path, len, "%s/%s", curdir, fname);
1089 			if ((stream = fopen(path, "r")) != NULL) {
1090 				fname = path;
1091 				goto found;
1092 			}
1093 
1094 			/* If curdir failed, try objdir (ala .depend) */
1095 			plen = strlen(objdir) + strlen(fname) + 2;
1096 			if (len < plen)
1097 				path = erealloc(path, len = 2 * plen);
1098 			(void)snprintf(path, len, "%s/%s", objdir, fname);
1099 			if ((stream = fopen(path, "r")) != NULL) {
1100 				fname = path;
1101 				goto found;
1102 			}
1103 		} else if ((stream = fopen(fname, "r")) != NULL)
1104 			goto found;
1105 		/* look in -I and system include directories. */
1106 		name = Dir_FindFile(fname, parseIncPath);
1107 		if (!name)
1108 			name = Dir_FindFile(fname,
1109 				Lst_IsEmpty(sysIncPath) ? defIncPath : sysIncPath);
1110 		if (!name || !(stream = fopen(name, "r"))) {
1111 			free(path);
1112 			return(FALSE);
1113 		}
1114 		fname = name;
1115 		/*
1116 		 * set the MAKEFILE variable desired by System V fans -- the
1117 		 * placement of the setting here means it gets set to the last
1118 		 * makefile specified, as it is set by SysV make.
1119 		 */
1120 found:
1121 		if (setMAKEFILE)
1122 			Var_Set("MAKEFILE", fname, VAR_GLOBAL, 0);
1123 		Parse_File(fname, stream);
1124 		(void)fclose(stream);
1125 	}
1126 	free(path);
1127 	return(TRUE);
1128 }
1129 
1130 
1131 /*
1132  * If MAKEOBJDIRPREFIX is in use, make ends up not in .CURDIR
1133  * in situations that would not arrise with ./obj (links or not).
1134  * This tends to break things like:
1135  *
1136  * build:
1137  * 	${MAKE} includes
1138  *
1139  * This function spots when ${.MAKE:T} or ${.MAKE} is a command (as
1140  * opposed to an argument) in a command line and if so returns
1141  * ${.CURDIR} so caller can chdir() so that the assumptions made by
1142  * the Makefile hold true.
1143  *
1144  * If ${.MAKE} does not contain any '/', then ${.MAKE:T} is skipped.
1145  *
1146  * The chdir() only happens in the child process, and does nothing if
1147  * MAKEOBJDIRPREFIX and MAKEOBJDIR are not in the environment so it
1148  * should not break anything.  Also if NOCHECKMAKECHDIR is set we
1149  * do nothing - to ensure historic semantics can be retained.
1150  */
1151 static int  Check_Cwd_Off = 0;
1152 
1153 static char *
1154 Check_Cwd_av(int ac, char **av, int copy)
1155 {
1156     static char *make[4];
1157     static char *cur_dir = NULL;
1158     char **mp;
1159     char *cp;
1160     int is_cmd, next_cmd;
1161     int i;
1162     int n;
1163 
1164     if (Check_Cwd_Off)
1165 	return NULL;
1166 
1167     if (make[0] == NULL) {
1168 	if (Var_Exists("NOCHECKMAKECHDIR", VAR_GLOBAL)) {
1169 	    Check_Cwd_Off = 1;
1170 	    return NULL;
1171 	}
1172 
1173         make[1] = Var_Value(".MAKE", VAR_GLOBAL, &cp);
1174         if ((make[0] = strrchr(make[1], '/')) == NULL) {
1175             make[0] = make[1];
1176             make[1] = NULL;
1177         } else
1178             ++make[0];
1179         make[2] = NULL;
1180         cur_dir = Var_Value(".CURDIR", VAR_GLOBAL, &cp);
1181     }
1182     if (ac == 0 || av == NULL)
1183         return NULL;			/* initialization only */
1184 
1185     if (getenv("MAKEOBJDIR") == NULL &&
1186         getenv("MAKEOBJDIRPREFIX") == NULL)
1187         return NULL;
1188 
1189 
1190     next_cmd = 1;
1191     for (i = 0; i < ac; ++i) {
1192 	is_cmd = next_cmd;
1193 
1194 	n = strlen(av[i]);
1195 	cp = &(av[i])[n - 1];
1196 	if (strspn(av[i], "|&;") == n) {
1197 	    next_cmd = 1;
1198 	    continue;
1199 	} else if (*cp == ';' || *cp == '&' || *cp == '|' || *cp == ')') {
1200 	    next_cmd = 1;
1201 	    if (copy) {
1202 		do {
1203 		    *cp-- = '\0';
1204 		} while (*cp == ';' || *cp == '&' || *cp == '|' ||
1205 			 *cp == ')' || *cp == '}') ;
1206 	    } else {
1207 		/*
1208 		 * XXX this should not happen.
1209 		 */
1210 		fprintf(stderr, "WARNING: raw arg ends in shell meta '%s'\n",
1211 			av[i]);
1212 	    }
1213 	} else
1214 	    next_cmd = 0;
1215 
1216 	cp = av[i];
1217 	if (*cp == ';' || *cp == '&' || *cp == '|')
1218 	    is_cmd = 1;
1219 
1220 #ifdef check_cwd_debug
1221 	fprintf(stderr, "av[%d] == %s '%s'",
1222 		i, (is_cmd) ? "cmd" : "arg", av[i]);
1223 #endif
1224 	if (is_cmd != 0) {
1225 	    if (*cp == '(' || *cp == '{' ||
1226 		*cp == ';' || *cp == '&' || *cp == '|') {
1227 		do {
1228 		    ++cp;
1229 		} while (*cp == '(' || *cp == '{' ||
1230 			 *cp == ';' || *cp == '&' || *cp == '|');
1231 		if (*cp == '\0') {
1232 		    next_cmd = 1;
1233 		    continue;
1234 		}
1235 	    }
1236 	    if (strcmp(cp, "cd") == 0 || strcmp(cp, "chdir") == 0) {
1237 #ifdef check_cwd_debug
1238 		fprintf(stderr, " == cd, done.\n");
1239 #endif
1240 		return NULL;
1241 	    }
1242 	    for (mp = make; *mp != NULL; ++mp) {
1243 		n = strlen(*mp);
1244 		if (strcmp(cp, *mp) == 0) {
1245 #ifdef check_cwd_debug
1246 		    fprintf(stderr, " %s == '%s', chdir(%s)\n",
1247 			    cp, *mp, cur_dir);
1248 #endif
1249 		    return cur_dir;
1250 		}
1251 	    }
1252 	}
1253 #ifdef check_cwd_debug
1254 	fprintf(stderr, "\n");
1255 #endif
1256     }
1257     return NULL;
1258 }
1259 
1260 char *
1261 Check_Cwd_Cmd(const char *cmd)
1262 {
1263     char *cp, *bp;
1264     char **av;
1265     int ac;
1266 
1267     if (Check_Cwd_Off)
1268 	return NULL;
1269 
1270     if (cmd) {
1271 	av = brk_string(cmd, &ac, TRUE, &bp);
1272 #ifdef check_cwd_debug
1273 	fprintf(stderr, "splitting: '%s' -> %d words\n",
1274 		cmd, ac);
1275 #endif
1276     } else {
1277 	ac = 0;
1278 	av = NULL;
1279 	bp = NULL;
1280     }
1281     cp = Check_Cwd_av(ac, av, 1);
1282     if (bp) {
1283 	free(av);
1284 	free(bp);
1285     }
1286     return cp;
1287 }
1288 
1289 void
1290 Check_Cwd(const char **argv)
1291 {
1292     char *cp;
1293     int ac;
1294 
1295     if (Check_Cwd_Off)
1296 	return;
1297 
1298     for (ac = 0; argv[ac] != NULL; ++ac)
1299 	/* NOTHING */;
1300     if (ac == 3 && *argv[1] == '-') {
1301 	cp =  Check_Cwd_Cmd(argv[2]);
1302     } else {
1303 	cp = Check_Cwd_av(ac, UNCONST(argv), 0);
1304     }
1305     if (cp) {
1306 	chdir(cp);
1307     }
1308 }
1309 
1310 /*-
1311  * Cmd_Exec --
1312  *	Execute the command in cmd, and return the output of that command
1313  *	in a string.
1314  *
1315  * Results:
1316  *	A string containing the output of the command, or the empty string
1317  *	If err is not NULL, it contains the reason for the command failure
1318  *
1319  * Side Effects:
1320  *	The string must be freed by the caller.
1321  */
1322 char *
1323 Cmd_Exec(const char *cmd, const char **err)
1324 {
1325     const char	*args[4];   	/* Args for invoking the shell */
1326     int 	fds[2];	    	/* Pipe streams */
1327     int 	cpid;	    	/* Child PID */
1328     int 	pid;	    	/* PID from wait() */
1329     char	*res;		/* result */
1330     int		status;		/* command exit status */
1331     Buffer	buf;		/* buffer to store the result */
1332     char	*cp;
1333     int		cc;
1334 
1335 
1336     *err = NULL;
1337 
1338     if (!shellName)
1339 	Shell_Init();
1340     /*
1341      * Set up arguments for shell
1342      */
1343     args[0] = shellName;
1344     args[1] = "-c";
1345     args[2] = cmd;
1346     args[3] = NULL;
1347 
1348     /*
1349      * Open a pipe for fetching its output
1350      */
1351     if (pipe(fds) == -1) {
1352 	*err = "Couldn't create pipe for \"%s\"";
1353 	goto bad;
1354     }
1355 
1356     /*
1357      * Fork
1358      */
1359     switch (cpid = vfork()) {
1360     case 0:
1361 	/*
1362 	 * Close input side of pipe
1363 	 */
1364 	(void) close(fds[0]);
1365 
1366 	/*
1367 	 * Duplicate the output stream to the shell's output, then
1368 	 * shut the extra thing down. Note we don't fetch the error
1369 	 * stream...why not? Why?
1370 	 */
1371 	(void) dup2(fds[1], 1);
1372 	(void) close(fds[1]);
1373 
1374 	(void) execv(shellPath, UNCONST(args));
1375 	_exit(1);
1376 	/*NOTREACHED*/
1377 
1378     case -1:
1379 	*err = "Couldn't exec \"%s\"";
1380 	goto bad;
1381 
1382     default:
1383 	/*
1384 	 * No need for the writing half
1385 	 */
1386 	(void) close(fds[1]);
1387 
1388 	buf = Buf_Init (MAKE_BSIZE);
1389 
1390 	do {
1391 	    char   result[BUFSIZ];
1392 	    cc = read(fds[0], result, sizeof(result));
1393 	    if (cc > 0)
1394 		Buf_AddBytes(buf, cc, (Byte *) result);
1395 	}
1396 	while (cc > 0 || (cc == -1 && errno == EINTR));
1397 
1398 	/*
1399 	 * Close the input side of the pipe.
1400 	 */
1401 	(void) close(fds[0]);
1402 
1403 	/*
1404 	 * Wait for the process to exit.
1405 	 */
1406 	while(((pid = wait(&status)) != cpid) && (pid >= 0))
1407 	    continue;
1408 
1409 	res = (char *)Buf_GetAll (buf, &cc);
1410 	Buf_Destroy (buf, FALSE);
1411 
1412 	if (cc == 0)
1413 	    *err = "Couldn't read shell's output for \"%s\"";
1414 
1415 	if (status)
1416 	    *err = "\"%s\" returned non-zero status";
1417 
1418 	/*
1419 	 * Null-terminate the result, convert newlines to spaces and
1420 	 * install it in the variable.
1421 	 */
1422 	res[cc] = '\0';
1423 	cp = &res[cc];
1424 
1425 	if (cc > 0 && *--cp == '\n') {
1426 	    /*
1427 	     * A final newline is just stripped
1428 	     */
1429 	    *cp-- = '\0';
1430 	}
1431 	while (cp >= res) {
1432 	    if (*cp == '\n') {
1433 		*cp = ' ';
1434 	    }
1435 	    cp--;
1436 	}
1437 	break;
1438     }
1439     return res;
1440 bad:
1441     res = emalloc(1);
1442     *res = '\0';
1443     return res;
1444 }
1445 
1446 /*-
1447  * Error --
1448  *	Print an error message given its format.
1449  *
1450  * Results:
1451  *	None.
1452  *
1453  * Side Effects:
1454  *	The message is printed.
1455  */
1456 /* VARARGS */
1457 void
1458 Error(const char *fmt, ...)
1459 {
1460 	va_list ap;
1461 
1462 	va_start(ap, fmt);
1463 	fprintf(stderr, "%s: ", progname);
1464 	(void)vfprintf(stderr, fmt, ap);
1465 	va_end(ap);
1466 	(void)fprintf(stderr, "\n");
1467 	(void)fflush(stderr);
1468 }
1469 
1470 /*-
1471  * Fatal --
1472  *	Produce a Fatal error message. If jobs are running, waits for them
1473  *	to finish.
1474  *
1475  * Results:
1476  *	None
1477  *
1478  * Side Effects:
1479  *	The program exits
1480  */
1481 /* VARARGS */
1482 void
1483 Fatal(const char *fmt, ...)
1484 {
1485 	va_list ap;
1486 
1487 	va_start(ap, fmt);
1488 	if (jobsRunning)
1489 		Job_Wait();
1490 	Job_TokenFlush();
1491 
1492 	(void)vfprintf(stderr, fmt, ap);
1493 	va_end(ap);
1494 	(void)fprintf(stderr, "\n");
1495 	(void)fflush(stderr);
1496 
1497 	PrintOnError(NULL);
1498 
1499 	if (DEBUG(GRAPH2) || DEBUG(GRAPH3))
1500 		Targ_PrintGraph(2);
1501 	Trace_Log(MAKEERROR, 0);
1502 	exit(2);		/* Not 1 so -q can distinguish error */
1503 }
1504 
1505 /*
1506  * Punt --
1507  *	Major exception once jobs are being created. Kills all jobs, prints
1508  *	a message and exits.
1509  *
1510  * Results:
1511  *	None
1512  *
1513  * Side Effects:
1514  *	All children are killed indiscriminately and the program Lib_Exits
1515  */
1516 /* VARARGS */
1517 void
1518 Punt(const char *fmt, ...)
1519 {
1520 	va_list ap;
1521 
1522 	va_start(ap, fmt);
1523 	(void)fprintf(stderr, "%s: ", progname);
1524 	(void)vfprintf(stderr, fmt, ap);
1525 	va_end(ap);
1526 	(void)fprintf(stderr, "\n");
1527 	(void)fflush(stderr);
1528 
1529 	PrintOnError(NULL);
1530 
1531 	DieHorribly();
1532 }
1533 
1534 /*-
1535  * DieHorribly --
1536  *	Exit without giving a message.
1537  *
1538  * Results:
1539  *	None
1540  *
1541  * Side Effects:
1542  *	A big one...
1543  */
1544 void
1545 DieHorribly(void)
1546 {
1547 	if (jobsRunning)
1548 		Job_AbortAll();
1549 	if (DEBUG(GRAPH2))
1550 		Targ_PrintGraph(2);
1551 	Trace_Log(MAKEERROR, 0);
1552 	exit(2);		/* Not 1, so -q can distinguish error */
1553 }
1554 
1555 /*
1556  * Finish --
1557  *	Called when aborting due to errors in child shell to signal
1558  *	abnormal exit.
1559  *
1560  * Results:
1561  *	None
1562  *
1563  * Side Effects:
1564  *	The program exits
1565  */
1566 void
1567 Finish(int errors)
1568 	           	/* number of errors encountered in Make_Make */
1569 {
1570 	Fatal("%d error%s", errors, errors == 1 ? "" : "s");
1571 }
1572 
1573 /*
1574  * emalloc --
1575  *	malloc, but die on error.
1576  */
1577 void *
1578 emalloc(size_t len)
1579 {
1580 	void *p;
1581 
1582 	if ((p = malloc(len)) == NULL)
1583 		enomem();
1584 	return(p);
1585 }
1586 
1587 /*
1588  * estrdup --
1589  *	strdup, but die on error.
1590  */
1591 char *
1592 estrdup(const char *str)
1593 {
1594 	char *p;
1595 
1596 	if ((p = strdup(str)) == NULL)
1597 		enomem();
1598 	return(p);
1599 }
1600 
1601 /*
1602  * erealloc --
1603  *	realloc, but die on error.
1604  */
1605 void *
1606 erealloc(void *ptr, size_t size)
1607 {
1608 	if ((ptr = realloc(ptr, size)) == NULL)
1609 		enomem();
1610 	return(ptr);
1611 }
1612 
1613 /*
1614  * enomem --
1615  *	die when out of memory.
1616  */
1617 void
1618 enomem(void)
1619 {
1620 	(void)fprintf(stderr, "%s: %s.\n", progname, strerror(errno));
1621 	exit(2);
1622 }
1623 
1624 /*
1625  * enunlink --
1626  *	Remove a file carefully, avoiding directories.
1627  */
1628 int
1629 eunlink(const char *file)
1630 {
1631 	struct stat st;
1632 
1633 	if (lstat(file, &st) == -1)
1634 		return -1;
1635 
1636 	if (S_ISDIR(st.st_mode)) {
1637 		errno = EISDIR;
1638 		return -1;
1639 	}
1640 	return unlink(file);
1641 }
1642 
1643 /*
1644  * execError --
1645  *	Print why exec failed, avoiding stdio.
1646  */
1647 void
1648 execError(const char *af, const char *av)
1649 {
1650 #ifdef USE_IOVEC
1651 	int i = 0;
1652 	struct iovec iov[8];
1653 #define IOADD(s) \
1654 	(void)(iov[i].iov_base = UNCONST(s), \
1655 	    iov[i].iov_len = strlen(iov[i].iov_base), \
1656 	    i++)
1657 #else
1658 #define	IOADD (void)write(2, s, strlen(s))
1659 #endif
1660 
1661 	IOADD(progname);
1662 	IOADD(": ");
1663 	IOADD(af);
1664 	IOADD("(");
1665 	IOADD(av);
1666 	IOADD(") failed (");
1667 	IOADD(strerror(errno));
1668 	IOADD(")\n");
1669 
1670 #ifdef USE_IOVEC
1671 	(void)writev(2, iov, 8);
1672 #endif
1673 }
1674 
1675 /*
1676  * usage --
1677  *	exit with usage message
1678  */
1679 static void
1680 usage(void)
1681 {
1682 	(void)fprintf(stderr,
1683 "usage: %s [-Beiknqrst] [-D variable] [-d flags] [-f makefile]\n\
1684             [-I directory] [-j max_jobs] [-m directory] [-V variable]\n\
1685             [variable=value] [target ...]\n", progname);
1686 	exit(2);
1687 }
1688 
1689 
1690 int
1691 PrintAddr(ClientData a, ClientData b)
1692 {
1693     printf("%lx ", (unsigned long) a);
1694     return b ? 0 : 0;
1695 }
1696 
1697 
1698 
1699 void
1700 PrintOnError(const char *s)
1701 {
1702     char tmp[64];
1703 
1704     if (s)
1705 	    printf("%s", s);
1706 
1707     printf("\n%s: stopped in %s\n", progname, curdir);
1708     strncpy(tmp, "${MAKE_PRINT_VAR_ON_ERROR:@v@$v='${$v}'\n@}",
1709 	    sizeof(tmp) - 1);
1710     s = Var_Subst(NULL, tmp, VAR_GLOBAL, 0);
1711     if (s && *s)
1712 	printf("%s", s);
1713 }
1714 
1715 void
1716 Main_ExportMAKEFLAGS(Boolean first)
1717 {
1718     static int once = 1;
1719     char tmp[64];
1720     char *s;
1721 
1722     if (once != first)
1723 	return;
1724     once = 0;
1725 
1726     strncpy(tmp, "${.MAKEFLAGS} ${.MAKEOVERRIDES:O:u:@v@$v=${$v:Q}@}",
1727 	    sizeof(tmp));
1728     s = Var_Subst(NULL, tmp, VAR_CMD, 0);
1729     if (s && *s) {
1730 #ifdef POSIX
1731 	setenv("MAKEFLAGS", s, 1);
1732 #else
1733 	setenv("MAKE", s, 1);
1734 #endif
1735     }
1736 }
1737