110d63b7Richard Lowe/*
210d63b7Richard Lowe * CDDL HEADER START
310d63b7Richard Lowe *
410d63b7Richard Lowe * The contents of this file are subject to the terms of the
510d63b7Richard Lowe * Common Development and Distribution License (the "License").
610d63b7Richard Lowe * You may not use this file except in compliance with the License.
710d63b7Richard Lowe *
810d63b7Richard Lowe * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
910d63b7Richard Lowe * or http://www.opensolaris.org/os/licensing.
1010d63b7Richard Lowe * See the License for the specific language governing permissions
1110d63b7Richard Lowe * and limitations under the License.
1210d63b7Richard Lowe *
1310d63b7Richard Lowe * When distributing Covered Code, include this CDDL HEADER in each
1410d63b7Richard Lowe * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1510d63b7Richard Lowe * If applicable, add the following below this CDDL HEADER, with the
1610d63b7Richard Lowe * fields enclosed by brackets "[]" replaced with your own identifying
1710d63b7Richard Lowe * information: Portions Copyright [yyyy] [name of copyright owner]
1810d63b7Richard Lowe *
1910d63b7Richard Lowe * CDDL HEADER END
2010d63b7Richard Lowe */
2110d63b7Richard Lowe/*
2210d63b7Richard Lowe * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
2310d63b7Richard Lowe * Use is subject to license terms.
2436cd012Robert Mustacchi *
2536cd012Robert Mustacchi * Copyright 2019, Joyent, Inc.
268e0c824Andrew Stormont * Copyright 2019 RackTop Systems.
27ae389aaAndy Fiddaman * Copyright 2019 OmniOS Community Edition (OmniOSce) Association.
2810d63b7Richard Lowe */
2910d63b7Richard Lowe
3010d63b7Richard Lowe/*
3110d63b7Richard Lowe *	main.cc
3210d63b7Richard Lowe *
3310d63b7Richard Lowe *	make program main routine plus some helper routines
3410d63b7Richard Lowe */
35ae389aaAndy Fiddaman
3610d63b7Richard Lowe/*
3710d63b7Richard Lowe * Included files
3810d63b7Richard Lowe */
3910d63b7Richard Lowe#include <bsd/bsd.h>		/* bsd_signal() */
4010d63b7Richard Lowe
4110d63b7Richard Lowe
4210d63b7Richard Lowe#include <locale.h>		/* setlocale() */
4310d63b7Richard Lowe#include <libgen.h>
4410d63b7Richard Lowe#include <mk/defs.h>
4510d63b7Richard Lowe#include <mksh/macro.h>		/* getvar() */
4610d63b7Richard Lowe#include <mksh/misc.h>		/* getmem(), setup_char_semantics() */
4710d63b7Richard Lowe
4810d63b7Richard Lowe#include <pwd.h>		/* getpwnam() */
4910d63b7Richard Lowe#include <setjmp.h>
5010d63b7Richard Lowe#include <signal.h>
5110d63b7Richard Lowe#include <stdlib.h>
5210d63b7Richard Lowe#include <sys/errno.h>		/* ENOENT */
5310d63b7Richard Lowe#include <sys/stat.h>		/* fstat() */
5410d63b7Richard Lowe#include <fcntl.h>		/* open() */
5510d63b7Richard Lowe
5610d63b7Richard Lowe#	include <sys/systeminfo.h>	/* sysinfo() */
5710d63b7Richard Lowe
5810d63b7Richard Lowe#include <sys/types.h>		/* stat() */
5910d63b7Richard Lowe#include <sys/wait.h>		/* wait() */
6010d63b7Richard Lowe#include <unistd.h>		/* execv(), unlink(), access() */
6110d63b7Richard Lowe#include <vroot/report.h>	/* report_dependency(), get_report_file() */
6210d63b7Richard Lowe
6310d63b7Richard Lowe// From read2.cc
6410d63b7Richard Loweextern	Name		normalize_name(register wchar_t *name_string, register int length);
6510d63b7Richard Lowe
6610d63b7Richard Loweextern void job_adjust_fini();
6710d63b7Richard Lowe
6810d63b7Richard Lowe
6910d63b7Richard Lowe/*
7010d63b7Richard Lowe * Defined macros
7110d63b7Richard Lowe */
7210d63b7Richard Lowe#define	LD_SUPPORT_ENV_VAR	"SGS_SUPPORT_32"
7310d63b7Richard Lowe#define	LD_SUPPORT_ENV_VAR_32	"SGS_SUPPORT_32"
7410d63b7Richard Lowe#define	LD_SUPPORT_ENV_VAR_64	"SGS_SUPPORT_64"
7510d63b7Richard Lowe#define	LD_SUPPORT_MAKE_LIB	"libmakestate.so.1"
76356ba08Toomas Soome#ifdef __x86
7710d63b7Richard Lowe#define	LD_SUPPORT_MAKE_ARCH	"i386"
7810d63b7Richard Lowe#elif __sparc
7910d63b7Richard Lowe#define	LD_SUPPORT_MAKE_ARCH	"sparc"
8010d63b7Richard Lowe#else
8110d63b7Richard Lowe#error "Unsupported architecture"
8210d63b7Richard Lowe#endif
8310d63b7Richard Lowe
8410d63b7Richard Lowe/*
8510d63b7Richard Lowe * typedefs & structs
8610d63b7Richard Lowe */
8710d63b7Richard Lowe
8810d63b7Richard Lowe/*
8910d63b7Richard Lowe * Static variables
9010d63b7Richard Lowe */
9110d63b7Richard Lowestatic	char		*argv_zero_string;
9210d63b7Richard Lowestatic	Boolean		build_failed_ever_seen;
9310d63b7Richard Lowestatic	Boolean		continue_after_error_ever_seen;	/* `-k' */
9410d63b7Richard Lowestatic	Boolean		dmake_group_specified;		/* `-g' */
9510d63b7Richard Lowestatic	Boolean		dmake_max_jobs_specified;	/* `-j' */
9610d63b7Richard Lowestatic	Boolean		dmake_mode_specified;		/* `-m' */
9710d63b7Richard Lowestatic	Boolean		dmake_add_mode_specified;	/* `-x' */
9810d63b7Richard Lowestatic	Boolean		dmake_output_mode_specified;	/* `-x DMAKE_OUTPUT_MODE=' */
9910d63b7Richard Lowestatic	Boolean		dmake_compat_mode_specified;	/* `-x SUN_MAKE_COMPAT_MODE=' */
10010d63b7Richard Lowestatic	Boolean		dmake_odir_specified;		/* `-o' */
10110d63b7Richard Lowestatic	Boolean		dmake_rcfile_specified;		/* `-c' */
10210d63b7Richard Lowestatic	Boolean		env_wins;			/* `-e' */
10310d63b7Richard Lowestatic	Boolean		ignore_default_mk;		/* `-r' */
10410d63b7Richard Lowestatic	Boolean		list_all_targets;		/* `-T' */
10510d63b7Richard Lowestatic	int		mf_argc;
10610d63b7Richard Lowestatic	char		**mf_argv;
10710d63b7Richard Lowestatic	Dependency_rec  not_auto_depen_struct;
108ae389aaAndy Fiddamanstatic	Dependency	not_auto_depen = &not_auto_depen_struct;
10910d63b7Richard Lowestatic	Boolean		pmake_cap_r_specified;		/* `-R' */
11010d63b7Richard Lowestatic	Boolean		pmake_machinesfile_specified;	/* `-M' */
11110d63b7Richard Lowestatic	Boolean		stop_after_error_ever_seen;	/* `-S' */
11210d63b7Richard Lowestatic	Boolean		trace_status;			/* `-p' */
11310d63b7Richard Lowe
11410d63b7Richard Lowe#ifdef DMAKE_STATISTICS
11510d63b7Richard Lowestatic	Boolean		getname_stat = false;
11610d63b7Richard Lowe#endif
11710d63b7Richard Lowe
11810d63b7Richard Lowe	static	time_t		start_time;
11910d63b7Richard Lowe	static	int		g_argc;
12010d63b7Richard Lowe	static	char		**g_argv;
12110d63b7Richard Lowe
12210d63b7Richard Lowe/*
12310d63b7Richard Lowe * File table of contents
12410d63b7Richard Lowe */
12510d63b7Richard Lowe	extern "C" void		cleanup_after_exit(void);
12610d63b7Richard Lowe
12710d63b7Richard Loweextern "C" {
12810d63b7Richard Lowe	extern	void		dmake_exit_callback(void);
12910d63b7Richard Lowe	extern	void		dmake_message_callback(char *);
13010d63b7Richard Lowe}
13110d63b7Richard Lowe
13210d63b7Richard Loweextern	Name		normalize_name(register wchar_t *name_string, register int length);
13310d63b7Richard Lowe
13410d63b7Richard Loweextern	int		main(int, char * []);
13510d63b7Richard Lowe
13610d63b7Richard Lowestatic	void		append_makeflags_string(Name, String);
13710d63b7Richard Lowestatic	void		doalarm(int);
13810d63b7Richard Lowestatic	void		enter_argv_values(int , char **, ASCII_Dyn_Array *);
13910d63b7Richard Lowestatic	void		make_targets(int, char **, Boolean);
14010d63b7Richard Lowestatic	int		parse_command_option(char);
14110d63b7Richard Lowestatic	void		read_command_options(int, char **);
14210d63b7Richard Lowestatic	void		read_environment(Boolean);
14310d63b7Richard Lowestatic	void		read_files_and_state(int, char **);
14410d63b7Richard Lowestatic	Boolean		read_makefile(Name, Boolean, Boolean, Boolean);
14510d63b7Richard Lowestatic	void		report_recursion(Name);
14610d63b7Richard Lowestatic	void		set_sgs_support(void);
14710d63b7Richard Lowestatic	void		setup_for_projectdir(void);
14810d63b7Richard Lowestatic	void		setup_makeflags_argv(void);
14910d63b7Richard Lowestatic	void		report_dir_enter_leave(Boolean entering);
15010d63b7Richard Lowe
15110d63b7Richard Loweextern void expand_value(Name, register String , Boolean);
15210d63b7Richard Lowe
15310d63b7Richard Lowestatic const char	verstring[] = "illumos make";
15410d63b7Richard Lowe
15510d63b7Richard Lowejmp_buf jmpbuffer;
15610d63b7Richard Lowe
15710d63b7Richard Lowe/*
15810d63b7Richard Lowe *	main(argc, argv)
15910d63b7Richard Lowe *
16010d63b7Richard Lowe *	Parameters:
16110d63b7Richard Lowe *		argc			You know what this is
16210d63b7Richard Lowe *		argv			You know what this is
16310d63b7Richard Lowe *
16410d63b7Richard Lowe *	Static variables used:
16510d63b7Richard Lowe *		list_all_targets	make -T seen
16610d63b7Richard Lowe *		trace_status		make -p seen
16710d63b7Richard Lowe *
16810d63b7Richard Lowe *	Global variables used:
16910d63b7Richard Lowe *		debug_level		Should we trace make actions?
17010d63b7Richard Lowe *		keep_state		Set if .KEEP_STATE seen
17110d63b7Richard Lowe *		makeflags		The Name "MAKEFLAGS", used to get macro
17210d63b7Richard Lowe *		remote_command_name	Name of remote invocation cmd ("on")
17310d63b7Richard Lowe *		running_list		List of parallel running processes
17410d63b7Richard Lowe *		stdout_stderr_same	true if stdout and stderr are the same
17510d63b7Richard Lowe *		auto_dependencies	The Name "SUNPRO_DEPENDENCIES"
17610d63b7Richard Lowe *		temp_file_directory	Set to the dir where we create tmp file
17710d63b7Richard Lowe *		trace_reader		Set to reflect tracing status
17810d63b7Richard Lowe *		working_on_targets	Set when building user targets
17910d63b7Richard Lowe */
18010d63b7Richard Loweint
18110d63b7Richard Lowemain(int argc, char *argv[])
18210d63b7Richard Lowe{
18310d63b7Richard Lowe	/*
18410d63b7Richard Lowe	 * cp is a -> to the value of the MAKEFLAGS env var,
18510d63b7Richard Lowe	 * which has to be regular chars.
18610d63b7Richard Lowe	 */
18710d63b7Richard Lowe	register char		*cp;
188ae389aaAndy Fiddaman	char			make_state_dir[MAXPATHLEN];
18910d63b7Richard Lowe	Boolean			parallel_flag = false;
19036cd012Robert Mustacchi	Boolean			argv_zero_relative = false;
19110d63b7Richard Lowe	char			*prognameptr;
192ae389aaAndy Fiddaman	char			*slash_ptr;
19310d63b7Richard Lowe	mode_t			um;
19410d63b7Richard Lowe	int			i;
19510d63b7Richard Lowe	struct itimerval	value;
19610d63b7Richard Lowe	char			def_dmakerc_path[MAXPATHLEN];
19710d63b7Richard Lowe	Name			dmake_name, dmake_name2;
19810d63b7Richard Lowe	Name			dmake_value, dmake_value2;
19910d63b7Richard Lowe	Property		prop, prop2;
20010d63b7Richard Lowe	struct stat		statbuf;
20110d63b7Richard Lowe	int			statval;
20210d63b7Richard Lowe
20310d63b7Richard Lowe	struct stat		out_stat, err_stat;
20410d63b7Richard Lowe	hostid = gethostid();
20510d63b7Richard Lowe	bsd_signals();
20610d63b7Richard Lowe
20710d63b7Richard Lowe	(void) setlocale(LC_ALL, "");
20810d63b7Richard Lowe
20910d63b7Richard Lowe
21010d63b7Richard Lowe#ifdef DMAKE_STATISTICS
21110d63b7Richard Lowe	if (getenv("DMAKE_STATISTICS")) {
21210d63b7Richard Lowe		getname_stat = true;
21310d63b7Richard Lowe	}
21410d63b7Richard Lowe#endif
21510d63b7Richard Lowe
21610d63b7Richard Lowe#ifndef TEXT_DOMAIN
217ae389aaAndy Fiddaman#define	TEXT_DOMAIN	"SYS_TEST"
21810d63b7Richard Lowe#endif
21910d63b7Richard Lowe	textdomain(TEXT_DOMAIN);
22010d63b7Richard Lowe
22110d63b7Richard Lowe	g_argc = argc;
22210d63b7Richard Lowe	g_argv = (char **) malloc((g_argc + 1) * sizeof(char *));
22310d63b7Richard Lowe	for (i = 0; i < argc; i++) {
22410d63b7Richard Lowe		g_argv[i] = argv[i];
22510d63b7Richard Lowe	}
22610d63b7Richard Lowe	g_argv[i] = NULL;
22710d63b7Richard Lowe
22810d63b7Richard Lowe	/*
22910d63b7Richard Lowe	 * Set argv_zero_string to some form of argv[0] for
23010d63b7Richard Lowe	 * recursive MAKE builds.
23110d63b7Richard Lowe	 */
23210d63b7Richard Lowe
23310d63b7Richard Lowe	if (*argv[0] == (int) slash_char) {
23410d63b7Richard Lowe		/* argv[0] starts with a slash */
23510d63b7Richard Lowe		argv_zero_string = strdup(argv[0]);
23610d63b7Richard Lowe	} else if (strchr(argv[0], (int) slash_char) == NULL) {
23710d63b7Richard Lowe		/* argv[0] contains no slashes */
23810d63b7Richard Lowe		argv_zero_string = strdup(argv[0]);
23910d63b7Richard Lowe	} else {
24010d63b7Richard Lowe		/*
24110d63b7Richard Lowe		 * argv[0] contains at least one slash,
24210d63b7Richard Lowe		 * but doesn't start with a slash
24310d63b7Richard Lowe		 */
24410d63b7Richard Lowe		char	*tmp_current_path;
24510d63b7Richard Lowe		char	*tmp_string;
24610d63b7Richard Lowe
24710d63b7Richard Lowe		tmp_current_path = get_current_path();
24810d63b7Richard Lowe		tmp_string = getmem(strlen(tmp_current_path) + 1 +
24910d63b7Richard Lowe		                    strlen(argv[0]) + 1);
25010d63b7Richard Lowe		(void) sprintf(tmp_string,
25110d63b7Richard Lowe		               "%s/%s",
25210d63b7Richard Lowe		               tmp_current_path,
25310d63b7Richard Lowe		               argv[0]);
25410d63b7Richard Lowe		argv_zero_string = strdup(tmp_string);
25510d63b7Richard Lowe		retmem_mb(tmp_string);
25636cd012Robert Mustacchi		argv_zero_relative = true;
25710d63b7Richard Lowe	}
25810d63b7Richard Lowe
259ae389aaAndy Fiddaman	/*
260ae389aaAndy Fiddaman	 * The following flags are reset if we don't have the
261ae389aaAndy Fiddaman	 * (.nse_depinfo or .make.state) files locked and only set
26210d63b7Richard Lowe	 * AFTER the file has been locked. This ensures that if the user
26310d63b7Richard Lowe	 * interrupts the program while file_lock() is waiting to lock
264ae389aaAndy Fiddaman	 * the file, the interrupt handler doesn't remove a lock
26510d63b7Richard Lowe	 * that doesn't belong to us.
26610d63b7Richard Lowe	 */
26710d63b7Richard Lowe	make_state_lockfile = NULL;
26810d63b7Richard Lowe	make_state_locked = false;
26910d63b7Richard Lowe
27010d63b7Richard Lowe
27110d63b7Richard Lowe	/*
272ae389aaAndy Fiddaman	 * look for last slash char in the path to look at the binary
27310d63b7Richard Lowe	 * name. This is to resolve the hard link and invoke make
27410d63b7Richard Lowe	 * in svr4 mode.
27510d63b7Richard Lowe	 */
27610d63b7Richard Lowe
277ae389aaAndy Fiddaman	/* Sun OS make standard */
278ae389aaAndy Fiddaman	svr4 = false;
27910d63b7Richard Lowe	posix = false;
28010d63b7Richard Lowe	if(!strcmp(argv_zero_string, "/usr/xpg4/bin/make")) {
28110d63b7Richard Lowe		svr4 = false;
28210d63b7Richard Lowe		posix = true;
28310d63b7Richard Lowe	} else {
28410d63b7Richard Lowe		prognameptr = strrchr(argv[0], '/');
28510d63b7Richard Lowe		if(prognameptr) {
28610d63b7Richard Lowe			prognameptr++;
28710d63b7Richard Lowe		} else {
28810d63b7Richard Lowe			prognameptr = argv[0];
28910d63b7Richard Lowe		}
29010d63b7Richard Lowe		if(!strcmp(prognameptr, "svr4.make")) {
29110d63b7Richard Lowe			svr4 = true;
29210d63b7Richard Lowe			posix = false;
29310d63b7Richard Lowe		}
29410d63b7Richard Lowe	}
29510d63b7Richard Lowe	if (getenv(USE_SVR4_MAKE) || getenv("USE_SVID")){
29610d63b7Richard Lowe	   svr4 = true;
29710d63b7Richard Lowe	   posix = false;
29810d63b7Richard Lowe	}
29910d63b7Richard Lowe
30010d63b7Richard Lowe	/*
30110d63b7Richard Lowe	 * Find the dmake_compat_mode: posix, sun, svr4, or gnu_style, .
30210d63b7Richard Lowe	 */
30310d63b7Richard Lowe	char * dmake_compat_mode_var = getenv("SUN_MAKE_COMPAT_MODE");
30410d63b7Richard Lowe	if (dmake_compat_mode_var != NULL) {
30510d63b7Richard Lowe		if (0 == strcasecmp(dmake_compat_mode_var, "GNU")) {
30610d63b7Richard Lowe			gnu_style = true;
30710d63b7Richard Lowe		}
30810d63b7Richard Lowe		//svr4 = false;
30910d63b7Richard Lowe		//posix = false;
31010d63b7Richard Lowe	}
31110d63b7Richard Lowe
31210d63b7Richard Lowe	/*
31310d63b7Richard Lowe	 * Temporary directory set up.
31410d63b7Richard Lowe	 */
31510d63b7Richard Lowe	char * tmpdir_var = getenv("TMPDIR");
31610d63b7Richard Lowe	if (tmpdir_var != NULL && *tmpdir_var == '/' && strlen(tmpdir_var) < MAXPATHLEN) {
31710d63b7Richard Lowe		strcpy(mbs_buffer, tmpdir_var);
31810d63b7Richard Lowe		for (tmpdir_var = mbs_buffer+strlen(mbs_buffer);
31910d63b7Richard Lowe			*(--tmpdir_var) == '/' && tmpdir_var > mbs_buffer;
32010d63b7Richard Lowe			*tmpdir_var = '\0');
32110d63b7Richard Lowe		if (strlen(mbs_buffer) + 32 < MAXPATHLEN) { /* 32 = strlen("/dmake.stdout.%d.%d.XXXXXX") */
32210d63b7Richard Lowe			sprintf(mbs_buffer2, "%s/dmake.tst.%d.XXXXXX",
32310d63b7Richard Lowe				mbs_buffer, getpid());
32410d63b7Richard Lowe			int fd = mkstemp(mbs_buffer2);
32510d63b7Richard Lowe			if (fd >= 0) {
32610d63b7Richard Lowe				close(fd);
32710d63b7Richard Lowe				unlink(mbs_buffer2);
32810d63b7Richard Lowe				tmpdir = strdup(mbs_buffer);
32910d63b7Richard Lowe			}
33010d63b7Richard Lowe		}
33110d63b7Richard Lowe	}
33210d63b7Richard Lowe
33310d63b7Richard Lowe	/* find out if stdout and stderr point to the same place */
33410d63b7Richard Lowe	if (fstat(1, &out_stat) < 0) {
33510d63b7Richard Lowe		fatal(gettext("fstat of standard out failed: %s"), errmsg(errno));
33610d63b7Richard Lowe	}
33710d63b7Richard Lowe	if (fstat(2, &err_stat) < 0) {
33810d63b7Richard Lowe		fatal(gettext("fstat of standard error failed: %s"), errmsg(errno));
33910d63b7Richard Lowe	}
34010d63b7Richard Lowe	if ((out_stat.st_dev == err_stat.st_dev) &&
34110d63b7Richard Lowe	    (out_stat.st_ino == err_stat.st_ino)) {
34210d63b7Richard Lowe		stdout_stderr_same = true;
34310d63b7Richard Lowe	} else {
34410d63b7Richard Lowe		stdout_stderr_same = false;
34510d63b7Richard Lowe	}
34610d63b7Richard Lowe	/* Make the vroot package scan the path using shell semantics */
34710d63b7Richard Lowe	set_path_style(0);
34810d63b7Richard Lowe
34910d63b7Richard Lowe	setup_char_semantics();
35010d63b7Richard Lowe
35110d63b7Richard Lowe	/*
35210d63b7Richard Lowe	 * If running with .KEEP_STATE, curdir will be set with
35310d63b7Richard Lowe	 * the connected directory.
35410d63b7Richard Lowe	 */
35510d63b7Richard Lowe	(void) atexit(cleanup_after_exit);
35610d63b7Richard Lowe
35710d63b7Richard Lowe	load_cached_names();
35810d63b7Richard Lowe
35910d63b7Richard Lowe/*
36010d63b7Richard Lowe *	Set command line flags
36110d63b7Richard Lowe */
36210d63b7Richard Lowe	setup_makeflags_argv();
36310d63b7Richard Lowe	read_command_options(mf_argc, mf_argv);
36410d63b7Richard Lowe	read_command_options(argc, argv);
36510d63b7Richard Lowe	if (debug_level > 0) {
36610d63b7Richard Lowe		cp = getenv(makeflags->string_mb);
36710d63b7Richard Lowe		(void) printf(gettext("MAKEFLAGS value: %s\n"), cp == NULL ? "" : cp);
36810d63b7Richard Lowe	}
36910d63b7Richard Lowe
37036cd012Robert Mustacchi	/*
37136cd012Robert Mustacchi	 * Reset argv_zero_string if it was built from a relative path and the
37236cd012Robert Mustacchi	 * -C option was specified.
37336cd012Robert Mustacchi	 */
37436cd012Robert Mustacchi	if (argv_zero_relative && rebuild_arg0) {
37536cd012Robert Mustacchi		char	*tmp_current_path;
37636cd012Robert Mustacchi		char	*tmp_string;
37736cd012Robert Mustacchi
37836cd012Robert Mustacchi		free(argv_zero_string);
37936cd012Robert Mustacchi		tmp_current_path = get_current_path();
38036cd012Robert Mustacchi		tmp_string = getmem(strlen(tmp_current_path) + 1 +
38136cd012Robert Mustacchi		                    strlen(argv[0]) + 1);
38236cd012Robert Mustacchi		(void) sprintf(tmp_string,
38336cd012Robert Mustacchi		               "%s/%s",
38436cd012Robert Mustacchi		               tmp_current_path,
38536cd012Robert Mustacchi		               argv[0]);
38636cd012Robert Mustacchi		argv_zero_string = strdup(tmp_string);
38736cd012Robert Mustacchi		retmem_mb(tmp_string);
38836cd012Robert Mustacchi	}
38936cd012Robert Mustacchi
39036cd012Robert Mustacchi	setup_for_projectdir();
39136cd012Robert Mustacchi
39210d63b7Richard Lowe	setup_interrupt(handle_interrupt);
39310d63b7Richard Lowe
39410d63b7Richard Lowe	read_files_and_state(argc, argv);
39510d63b7Richard Lowe
39610d63b7Richard Lowe	/*
39710d63b7Richard Lowe	 * Find the dmake_output_mode: TXT1, TXT2 or HTML1.
39810d63b7Richard Lowe	 */
39910d63b7Richard Lowe	MBSTOWCS(wcs_buffer, "DMAKE_OUTPUT_MODE");
40010d63b7Richard Lowe	dmake_name2 = GETNAME(wcs_buffer, FIND_LENGTH);
40110d63b7Richard Lowe	prop2 = get_prop(dmake_name2->prop, macro_prop);
40210d63b7Richard Lowe	if (prop2 == NULL) {
40310d63b7Richard Lowe		/* DMAKE_OUTPUT_MODE not defined, default to TXT1 mode */
40410d63b7Richard Lowe		output_mode = txt1_mode;
40510d63b7Richard Lowe	} else {
40610d63b7Richard Lowe		dmake_value2 = prop2->body.macro.value;
40710d63b7Richard Lowe		if ((dmake_value2 == NULL) ||
40810d63b7Richard Lowe		    (IS_EQUAL(dmake_value2->string_mb, "TXT1"))) {
40910d63b7Richard Lowe			output_mode = txt1_mode;
41010d63b7Richard Lowe		} else if (IS_EQUAL(dmake_value2->string_mb, "TXT2")) {
41110d63b7Richard Lowe			output_mode = txt2_mode;
41210d63b7Richard Lowe		} else if (IS_EQUAL(dmake_value2->string_mb, "HTML1")) {
41310d63b7Richard Lowe			output_mode = html1_mode;
41410d63b7Richard Lowe		} else {
41510d63b7Richard Lowe			warning(gettext("Unsupported value `%s' for DMAKE_OUTPUT_MODE after -x flag (ignored)"),
41610d63b7Richard Lowe			      dmake_value2->string_mb);
41710d63b7Richard Lowe		}
41810d63b7Richard Lowe	}
41910d63b7Richard Lowe	/*
42010d63b7Richard Lowe	 * Find the dmake_mode: parallel, or serial.
42110d63b7Richard Lowe	 */
42210d63b7Richard Lowe    if ((!pmake_cap_r_specified) &&
42310d63b7Richard Lowe        (!pmake_machinesfile_specified)) {
42410d63b7Richard Lowe	char *s, *b;
42510d63b7Richard Lowe
42610d63b7Richard Lowe	if ((s = strdup(argv[0])) == NULL)
42710d63b7Richard Lowe		fatal(gettext("Out of memory"));
42810d63b7Richard Lowe
42910d63b7Richard Lowe	b = basename(s);
43010d63b7Richard Lowe
43110d63b7Richard Lowe	MBSTOWCS(wcs_buffer, "DMAKE_MODE");
43210d63b7Richard Lowe	dmake_name2 = GETNAME(wcs_buffer, FIND_LENGTH);
43310d63b7Richard Lowe	prop2 = get_prop(dmake_name2->prop, macro_prop);
43410d63b7Richard Lowe	// If we're invoked as 'make' run serially, regardless of DMAKE_MODE
43510d63b7Richard Lowe	// If we're invoked as 'make' but passed -j, run parallel
43610d63b7Richard Lowe	// If we're invoked as 'dmake', without DMAKE_MODE, default parallel
43710d63b7Richard Lowe	// If we're invoked as 'dmake' and DMAKE_MODE is set, honour it.
43810d63b7Richard Lowe	if ((strcmp(b, "make") == 0) &&
43910d63b7Richard Lowe	    !dmake_max_jobs_specified) {
44010d63b7Richard Lowe		dmake_mode_type = serial_mode;
44110d63b7Richard Lowe		no_parallel = true;
44210d63b7Richard Lowe	} else if (prop2 == NULL) {
44310d63b7Richard Lowe		/* DMAKE_MODE not defined, default based on our name */
44410d63b7Richard Lowe		if (strcmp(b, "dmake") == 0) {
44510d63b7Richard Lowe			dmake_mode_type = parallel_mode;
44610d63b7Richard Lowe			no_parallel = false;
44710d63b7Richard Lowe		}
44810d63b7Richard Lowe	} else {
44910d63b7Richard Lowe		dmake_value2 = prop2->body.macro.value;
45010d63b7Richard Lowe		if (IS_EQUAL(dmake_value2->string_mb, "parallel")) {
45110d63b7Richard Lowe			dmake_mode_type = parallel_mode;
45210d63b7Richard Lowe			no_parallel = false;
45310d63b7Richard Lowe		} else if (IS_EQUAL(dmake_value2->string_mb, "serial")) {
45410d63b7Richard Lowe			dmake_mode_type = serial_mode;
45510d63b7Richard Lowe			no_parallel = true;
45610d63b7Richard Lowe		} else {
45710d63b7Richard Lowe			fatal(gettext("Unknown dmake mode argument `%s' after -m flag"), dmake_value2->string_mb);
45810d63b7Richard Lowe		}
45910d63b7Richard Lowe	}
46010d63b7Richard Lowe	free(s);
46110d63b7Richard Lowe    }
46210d63b7Richard Lowe
46310d63b7Richard Lowe	parallel_flag = true;
46410d63b7Richard Lowe	putenv(strdup("DMAKE_CHILD=TRUE"));
46510d63b7Richard Lowe
46610d63b7Richard Lowe//
46710d63b7Richard Lowe// If dmake is running with -t option, set dmake_mode_type to serial.
46810d63b7Richard Lowe// This is done because doname() calls touch_command() that runs serially.
469ae389aaAndy Fiddaman// If we do not do that, maketool will have problems.
47010d63b7Richard Lowe//
47110d63b7Richard Lowe	if(touch) {
47210d63b7Richard Lowe		dmake_mode_type = serial_mode;
47310d63b7Richard Lowe		no_parallel = true;
47410d63b7Richard Lowe	}
47510d63b7Richard Lowe
47610d63b7Richard Lowe	/*
47710d63b7Richard Lowe	 * Check whether stdout and stderr are physically same.
47810d63b7Richard Lowe	 * This is in order to decide whether we need to redirect
47910d63b7Richard Lowe	 * stderr separately from stdout.
48010d63b7Richard Lowe	 * This check is performed only if __DMAKE_SEPARATE_STDERR
48110d63b7Richard Lowe	 * is not set. This variable may be used in order to preserve
48210d63b7Richard Lowe	 * the 'old' behaviour.
48310d63b7Richard Lowe	 */
48410d63b7Richard Lowe	out_err_same = true;
48510d63b7Richard Lowe	char * dmake_sep_var = getenv("__DMAKE_SEPARATE_STDERR");
48610d63b7Richard Lowe	if (dmake_sep_var == NULL || (0 != strcasecmp(dmake_sep_var, "NO"))) {
48710d63b7Richard Lowe		struct stat stdout_stat;
48810d63b7Richard Lowe		struct stat stderr_stat;
48910d63b7Richard Lowe		if( (fstat(1, &stdout_stat) == 0)
49010d63b7Richard Lowe		 && (fstat(2, &stderr_stat) == 0) )
49110d63b7Richard Lowe		{
49210d63b7Richard Lowe			if( (stdout_stat.st_dev != stderr_stat.st_dev)
49310d63b7Richard Lowe			 || (stdout_stat.st_ino != stderr_stat.st_ino) )
49410d63b7Richard Lowe			{
49510d63b7Richard Lowe				out_err_same = false;
49610d63b7Richard Lowe			}
49710d63b7Richard Lowe		}
49810d63b7Richard Lowe	}
49910d63b7Richard Lowe
500ae389aaAndy Fiddaman
50110d63b7Richard Lowe/*
50210d63b7Richard Lowe *	Enable interrupt handler for alarms
50310d63b7Richard Lowe */
50410d63b7Richard Lowe        (void) bsd_signal(SIGALRM, (SIG_PF)doalarm);
50510d63b7Richard Lowe
50610d63b7Richard Lowe/*
50710d63b7Richard Lowe *	Check if make should report
50810d63b7Richard Lowe */
50910d63b7Richard Lowe	if (getenv(sunpro_dependencies->string_mb) != NULL) {
51010d63b7Richard Lowe		FILE	*report_file;
51110d63b7Richard Lowe
51210d63b7Richard Lowe		report_dependency("");
51310d63b7Richard Lowe		report_file = get_report_file();
51410d63b7Richard Lowe		if ((report_file != NULL) && (report_file != (FILE*)-1)) {
51510d63b7Richard Lowe			(void) fprintf(report_file, "\n");
51610d63b7Richard Lowe		}
51710d63b7Richard Lowe	}
51810d63b7Richard Lowe
51910d63b7Richard Lowe/*
52010d63b7Richard Lowe *	Make sure SUNPRO_DEPENDENCIES is exported (or not) properly.
52110d63b7Richard Lowe */
52210d63b7Richard Lowe	if (keep_state) {
52310d63b7Richard Lowe		maybe_append_prop(sunpro_dependencies, macro_prop)->
52410d63b7Richard Lowe		  body.macro.exported = true;
52510d63b7Richard Lowe	} else {
52610d63b7Richard Lowe		maybe_append_prop(sunpro_dependencies, macro_prop)->
52710d63b7Richard Lowe		  body.macro.exported = false;
52810d63b7Richard Lowe	}
52910d63b7Richard Lowe
53010d63b7Richard Lowe	working_on_targets = true;
53110d63b7Richard Lowe	if (trace_status) {
53210d63b7Richard Lowe		dump_make_state();
53310d63b7Richard Lowe		fclose(stdout);
53410d63b7Richard Lowe		fclose(stderr);
53510d63b7Richard Lowe		exit_status = 0;
53610d63b7Richard Lowe		exit(0);
53710d63b7Richard Lowe	}
53810d63b7Richard Lowe	if (list_all_targets) {
53910d63b7Richard Lowe		dump_target_list();
54010d63b7Richard Lowe		fclose(stdout);
54110d63b7Richard Lowe		fclose(stderr);
54210d63b7Richard Lowe		exit_status = 0;
54310d63b7Richard Lowe		exit(0);
54410d63b7Richard Lowe	}
54510d63b7Richard Lowe	trace_reader = false;
54610d63b7Richard Lowe
547ae389aaAndy Fiddaman	/*
548ae389aaAndy Fiddaman	 * Set temp_file_directory to the directory the .make.state
549ae389aaAndy Fiddaman	 * file is written to.
550ae389aaAndy Fiddaman	 */
551ae389aaAndy Fiddaman	if ((slash_ptr = strrchr(make_state->string_mb, (int) slash_char)) == NULL) {
552ae389aaAndy Fiddaman		temp_file_directory = strdup(get_current_path());
553ae389aaAndy Fiddaman	} else {
554ae389aaAndy Fiddaman		*slash_ptr = (int) nul_char;
555ae389aaAndy Fiddaman		(void) strcpy(make_state_dir, make_state->string_mb);
556ae389aaAndy Fiddaman		*slash_ptr = (int) slash_char;
55710d63b7Richard Lowe		   /* when there is only one slash and it's the first
55810d63b7Richard Lowe		   ** character, make_state_dir should point to '/'.
55910d63b7Richard Lowe		   */
56010d63b7Richard Lowe		if(make_state_dir[0] == '\0') {
56110d63b7Richard Lowe		   make_state_dir[0] = '/';
56210d63b7Richard Lowe		   make_state_dir[1] = '\0';
56310d63b7Richard Lowe		}
564ae389aaAndy Fiddaman		if (make_state_dir[0] == (int) slash_char) {
565ae389aaAndy Fiddaman			temp_file_directory = strdup(make_state_dir);
566ae389aaAndy Fiddaman		} else {
567ae389aaAndy Fiddaman			char	tmp_current_path2[MAXPATHLEN];
568ae389aaAndy Fiddaman
569ae389aaAndy Fiddaman			(void) sprintf(tmp_current_path2,
570ae389aaAndy Fiddaman			               "%s/%s",
571ae389aaAndy Fiddaman			               get_current_path(),
572ae389aaAndy Fiddaman			               make_state_dir);
573ae389aaAndy Fiddaman			temp_file_directory = strdup(tmp_current_path2);
574ae389aaAndy Fiddaman		}
575ae389aaAndy Fiddaman	}
57610d63b7Richard Lowe
57710d63b7Richard Lowe
57810d63b7Richard Lowe	report_dir_enter_leave(true);
57910d63b7Richard Lowe
58010d63b7Richard Lowe	make_targets(argc, argv, parallel_flag);
58110d63b7Richard Lowe
58210d63b7Richard Lowe	report_dir_enter_leave(false);
58310d63b7Richard Lowe
58410d63b7Richard Lowe	if (build_failed_ever_seen) {
58510d63b7Richard Lowe		if (posix) {
58610d63b7Richard Lowe			exit_status = 1;
58710d63b7Richard Lowe		}
58810d63b7Richard Lowe		exit(1);
58910d63b7Richard Lowe	}
59010d63b7Richard Lowe	exit_status = 0;
59110d63b7Richard Lowe	exit(0);
59210d63b7Richard Lowe	/* NOTREACHED */
59310d63b7Richard Lowe}
59410d63b7Richard Lowe
59510d63b7Richard Lowe/*
59610d63b7Richard Lowe *	cleanup_after_exit()
59710d63b7Richard Lowe *
59810d63b7Richard Lowe *	Called from exit(), performs cleanup actions.
59910d63b7Richard Lowe *
60010d63b7Richard Lowe *	Parameters:
60110d63b7Richard Lowe *		status		The argument exit() was called with
60210d63b7Richard Lowe *		arg		Address of an argument vector to
60310d63b7Richard Lowe *				cleanup_after_exit()
60410d63b7Richard Lowe *
60510d63b7Richard Lowe *	Global variables used:
60610d63b7Richard Lowe *		command_changed	Set if we think .make.state should be rewritten
60710d63b7Richard Lowe *		current_line	Is set we set commands_changed
60810d63b7Richard Lowe *		do_not_exec_rule
60910d63b7Richard Lowe *				True if -n flag on
61010d63b7Richard Lowe *		done		The Name ".DONE", rule we run
61110d63b7Richard Lowe *		keep_state	Set if .KEEP_STATE seen
61210d63b7Richard Lowe *		parallel	True if building in parallel
61310d63b7Richard Lowe *		quest		If -q is on we do not run .DONE
61410d63b7Richard Lowe *		report_dependencies
61510d63b7Richard Lowe *				True if -P flag on
61610d63b7Richard Lowe *		running_list	List of parallel running processes
61710d63b7Richard Lowe *		temp_file_name	The temp file is removed, if any
61810d63b7Richard Lowe */
61910d63b7Richard Loweextern "C" void
62010d63b7Richard Lowecleanup_after_exit(void)
62110d63b7Richard Lowe{
62210d63b7Richard Lowe	Running		rp;
62310d63b7Richard Lowe
62410d63b7Richard Loweextern long	getname_bytes_count;
62510d63b7Richard Loweextern long	getname_names_count;
62610d63b7Richard Loweextern long	getname_struct_count;
62710d63b7Richard Loweextern long	freename_bytes_count;
62810d63b7Richard Loweextern long	freename_names_count;
62910d63b7Richard Loweextern long	freename_struct_count;
63010d63b7Richard Loweextern long	other_alloc;
63110d63b7Richard Lowe
63210d63b7Richard Loweextern long	env_alloc_num;
63310d63b7Richard Loweextern long	env_alloc_bytes;
63410d63b7Richard Lowe
63510d63b7Richard Lowe
63610d63b7Richard Lowe#ifdef DMAKE_STATISTICS
63710d63b7Richard Loweif(getname_stat) {
63810d63b7Richard Lowe	printf(">>> Getname statistics:\n");
63910d63b7Richard Lowe	printf("  Allocated:\n");
64010d63b7Richard Lowe	printf("        Names: %ld\n", getname_names_count);
64110d63b7Richard Lowe	printf("      Strings: %ld Kb (%ld bytes)\n", getname_bytes_count/1000, getname_bytes_count);
64210d63b7Richard Lowe	printf("      Structs: %ld Kb (%ld bytes)\n", getname_struct_count/1000, getname_struct_count);
64310d63b7Richard Lowe	printf("  Total bytes: %ld Kb (%ld bytes)\n", getname_struct_count/1000 + getname_bytes_count/1000, getname_struct_count + getname_bytes_count);
64410d63b7Richard Lowe
64510d63b7Richard Lowe	printf("\n  Unallocated: %ld\n", freename_names_count);
64610d63b7Richard Lowe	printf("        Names: %ld\n", freename_names_count);
64710d63b7Richard Lowe	printf("      Strings: %ld Kb (%ld bytes)\n", freename_bytes_count/1000, freename_bytes_count);
64810d63b7Richard Lowe	printf("      Structs: %ld Kb (%ld bytes)\n", freename_struct_count/1000, freename_struct_count);
64910d63b7Richard Lowe	printf("  Total bytes: %ld Kb (%ld bytes)\n", freename_struct_count/1000 + freename_bytes_count/1000, freename_struct_count + freename_bytes_count);
65010d63b7Richard Lowe
65110d63b7Richard Lowe	printf("\n  Total used: %ld Kb (%ld bytes)\n", (getname_struct_count/1000 + getname_bytes_count/1000) - (freename_struct_count/1000 + freename_bytes_count/1000), (getname_struct_count + getname_bytes_count) - (freename_struct_count + freename_bytes_count));
65210d63b7Richard Lowe
65310d63b7Richard Lowe	printf("\n>>> Other:\n");
65410d63b7Richard Lowe	printf(
65510d63b7Richard Lowe		"       Env (%ld): %ld Kb (%ld bytes)\n",
65610d63b7Richard Lowe		env_alloc_num,
65710d63b7Richard Lowe		env_alloc_bytes/1000,
65810d63b7Richard Lowe		env_alloc_bytes
65910d63b7Richard Lowe	);
66010d63b7Richard Lowe
66110d63b7Richard Lowe}
66210d63b7Richard Lowe#endif
66310d63b7Richard Lowe
66410d63b7Richard Lowe	parallel = false;
66510d63b7Richard Lowe	/* If we used the SVR4_MAKE, don't build .DONE or .FAILED */
66610d63b7Richard Lowe	if (!getenv(USE_SVR4_MAKE)){
66710d63b7Richard Lowe	    /* Build the target .DONE or .FAILED if we caught an error */
66810d63b7Richard Lowe	    if (!quest && !list_all_targets) {
66910d63b7Richard Lowe		Name		failed_name;
67010d63b7Richard Lowe
67110d63b7Richard Lowe		MBSTOWCS(wcs_buffer, ".FAILED");
67210d63b7Richard Lowe		failed_name = GETNAME(wcs_buffer, FIND_LENGTH);
67310d63b7Richard Lowe		if ((exit_status != 0) && (failed_name->prop != NULL)) {
67410d63b7Richard Lowe			/*
67510d63b7Richard Lowe			 * [tolik] switch DMake to serial mode
67610d63b7Richard Lowe			 */
67710d63b7Richard Lowe			dmake_mode_type = serial_mode;
67810d63b7Richard Lowe			no_parallel = true;
67910d63b7Richard Lowe			(void) doname(failed_name, false, true);
68010d63b7Richard Lowe		} else {
68110d63b7Richard Lowe		    if (!trace_status) {
68210d63b7Richard Lowe			/*
68310d63b7Richard Lowe			 * Switch DMake to serial mode
68410d63b7Richard Lowe			 */
68510d63b7Richard Lowe			dmake_mode_type = serial_mode;
68610d63b7Richard Lowe			no_parallel = true;
68710d63b7Richard Lowe			(void) doname(done, false, true);
68810d63b7Richard Lowe		    }
68910d63b7Richard Lowe		}
69010d63b7Richard Lowe	    }
69110d63b7Richard Lowe	}
69210d63b7Richard Lowe	/*
69310d63b7Richard Lowe	 * Remove the temp file utilities report dependencies thru if it
69410d63b7Richard Lowe	 * is still around
69510d63b7Richard Lowe	 */
69610d63b7Richard Lowe	if (temp_file_name != NULL) {
69710d63b7Richard Lowe		(void) unlink(temp_file_name->string_mb);
69810d63b7Richard Lowe	}
69910d63b7Richard Lowe	/*
70010d63b7Richard Lowe	 * Do not save the current command in .make.state if make
70110d63b7Richard Lowe	 * was interrupted.
70210d63b7Richard Lowe	 */
70310d63b7Richard Lowe	if (current_line != NULL) {
70410d63b7Richard Lowe		command_changed = true;
70510d63b7Richard Lowe		current_line->body.line.command_used = NULL;
70610d63b7Richard Lowe	}
70710d63b7Richard Lowe	/*
70810d63b7Richard Lowe	 * For each parallel build process running, remove the temp files
70910d63b7Richard Lowe	 * and zap the command line so it won't be put in .make.state
71010d63b7Richard Lowe	 */
71110d63b7Richard Lowe	for (rp = running_list; rp != NULL; rp = rp->next) {
71210d63b7Richard Lowe		if (rp->temp_file != NULL) {
71310d63b7Richard Lowe			(void) unlink(rp->temp_file->string_mb);
71410d63b7Richard Lowe		}
71510d63b7Richard Lowe		if (rp->stdout_file != NULL) {
71610d63b7Richard Lowe			(void) unlink(rp->stdout_file);
71710d63b7Richard Lowe			retmem_mb(rp->stdout_file);
71810d63b7Richard Lowe			rp->stdout_file = NULL;
71910d63b7Richard Lowe		}
72010d63b7Richard Lowe		if (rp->stderr_file != NULL) {
72110d63b7Richard Lowe			(void) unlink(rp->stderr_file);
72210d63b7Richard Lowe			retmem_mb(rp->stderr_file);
72310d63b7Richard Lowe			rp->stderr_file = NULL;
72410d63b7Richard Lowe		}
72510d63b7Richard Lowe		command_changed = true;
72610d63b7Richard Lowe/*
72710d63b7Richard Lowe		line = get_prop(rp->target->prop, line_prop);
72810d63b7Richard Lowe		if (line != NULL) {
72910d63b7Richard Lowe			line->body.line.command_used = NULL;
73010d63b7Richard Lowe		}
73110d63b7Richard Lowe */
73210d63b7Richard Lowe	}
73310d63b7Richard Lowe	/* Remove the statefile lock file if the file has been locked */
73410d63b7Richard Lowe	if ((make_state_lockfile != NULL) && (make_state_locked)) {
73510d63b7Richard Lowe		(void) unlink(make_state_lockfile);
73610d63b7Richard Lowe		make_state_lockfile = NULL;
73710d63b7Richard Lowe		make_state_locked = false;
73810d63b7Richard Lowe	}
73910d63b7Richard Lowe	/* Write .make.state */
74010d63b7Richard Lowe	write_state_file(1, (Boolean) 1);
74110d63b7Richard Lowe
74210d63b7Richard Lowe	job_adjust_fini();
74310d63b7Richard Lowe}
74410d63b7Richard Lowe
74510d63b7Richard Lowe/*
74610d63b7Richard Lowe *	handle_interrupt()
74710d63b7Richard Lowe *
74810d63b7Richard Lowe *	This is where C-C traps are caught.
74910d63b7Richard Lowe *
75010d63b7Richard Lowe *	Parameters:
75110d63b7Richard Lowe *
75210d63b7Richard Lowe *	Global variables used (except DMake 1.0):
75310d63b7Richard Lowe *		current_target		Sometimes the current target is removed
75410d63b7Richard Lowe *		do_not_exec_rule	But not if -n is on
75510d63b7Richard Lowe *		quest			or -q
75610d63b7Richard Lowe *		running_list		List of parallel running processes
75710d63b7Richard Lowe *		touch			Current target is not removed if -t on
75810d63b7Richard Lowe */
75910d63b7Richard Lowevoid
76010d63b7Richard Lowehandle_interrupt(int)
76110d63b7Richard Lowe{
76210d63b7Richard Lowe	Property		member;
76310d63b7Richard Lowe	Running			rp;
76410d63b7Richard Lowe
76510d63b7Richard Lowe	(void) fflush(stdout);
76610d63b7Richard Lowe	if (childPid > 0) {
76710d63b7Richard Lowe		kill(childPid, SIGTERM);
76810d63b7Richard Lowe		childPid = -1;
76910d63b7Richard Lowe	}
77010d63b7Richard Lowe	for (rp = running_list; rp != NULL; rp = rp->next) {
77110d63b7Richard Lowe		if (rp->state != build_running) {
77210d63b7Richard Lowe			continue;
77310d63b7Richard Lowe		}
77410d63b7Richard Lowe		if (rp->pid > 0) {
77510d63b7Richard Lowe			kill(rp->pid, SIGTERM);
77610d63b7Richard Lowe			rp->pid = -1;
77710d63b7Richard Lowe		}
77810d63b7Richard Lowe	}
77910d63b7Richard Lowe	if (getpid() == getpgrp()) {
78010d63b7Richard Lowe		bsd_signal(SIGTERM, SIG_IGN);
78110d63b7Richard Lowe		kill (-getpid(), SIGTERM);
78210d63b7Richard Lowe	}
78310d63b7Richard Lowe	/* Clean up all parallel children already finished */
78410d63b7Richard Lowe        finish_children(false);
78510d63b7Richard Lowe
78610d63b7Richard Lowe	/* Make sure the processes running under us terminate first */
78710d63b7Richard Lowe
78810d63b7Richard Lowe	while (wait((int *) NULL) != -1);
78910d63b7Richard Lowe	/* Delete the current targets unless they are precious */
79010d63b7Richard Lowe	if ((current_target != NULL) &&
79110d63b7Richard Lowe	    current_target->is_member &&
79210d63b7Richard Lowe	    ((member = get_prop(current_target->prop, member_prop)) != NULL)) {
79310d63b7Richard Lowe		current_target = member->body.member.library;
79410d63b7Richard Lowe	}
79510d63b7Richard Lowe	if (!do_not_exec_rule &&
79610d63b7Richard Lowe	    !touch &&
79710d63b7Richard Lowe	    !quest &&
79810d63b7Richard Lowe	    (current_target != NULL) &&
79910d63b7Richard Lowe	    !(current_target->stat.is_precious || all_precious)) {
80010d63b7Richard Lowe
80110d63b7Richard Lowe/* BID_1030811 */
80210d63b7Richard Lowe/* azv 16 Oct 95 */
803ae389aaAndy Fiddaman		current_target->stat.time = file_no_time;
80410d63b7Richard Lowe
80510d63b7Richard Lowe		if (exists(current_target) != file_doesnt_exist) {
80610d63b7Richard Lowe			(void) fprintf(stderr,
80710d63b7Richard Lowe				       "\n*** %s ",
80810d63b7Richard Lowe				       current_target->string_mb);
80910d63b7Richard Lowe			if (current_target->stat.is_dir) {
81010d63b7Richard Lowe				(void) fprintf(stderr,
81110d63b7Richard Lowe					       gettext("not removed.\n"),
81210d63b7Richard Lowe					       current_target->string_mb);
81310d63b7Richard Lowe			} else if (unlink(current_target->string_mb) == 0) {
81410d63b7Richard Lowe				(void) fprintf(stderr,
81510d63b7Richard Lowe					       gettext("removed.\n"),
81610d63b7Richard Lowe					       current_target->string_mb);
81710d63b7Richard Lowe			} else {
81810d63b7Richard Lowe				(void) fprintf(stderr,
81910d63b7Richard Lowe					       gettext("could not be removed: %s.\n"),
82010d63b7Richard Lowe					       current_target->string_mb,
82110d63b7Richard Lowe					       errmsg(errno));
82210d63b7Richard Lowe			}
82310d63b7Richard Lowe		}
82410d63b7Richard Lowe	}
82510d63b7Richard Lowe	for (rp = running_list; rp != NULL; rp = rp->next) {
82610d63b7Richard Lowe		if (rp->state != build_running) {
82710d63b7Richard Lowe			continue;
82810d63b7Richard Lowe		}
82910d63b7Richard Lowe		if (rp->target->is_member &&
83010d63b7Richard Lowe		    (