xref: /illumos-gate/usr/src/cmd/make/bin/parallel.cc (revision 10d63b7d)
1*10d63b7dSRichard Lowe /*
2*10d63b7dSRichard Lowe  * CDDL HEADER START
3*10d63b7dSRichard Lowe  *
4*10d63b7dSRichard Lowe  * The contents of this file are subject to the terms of the
5*10d63b7dSRichard Lowe  * Common Development and Distribution License (the "License").
6*10d63b7dSRichard Lowe  * You may not use this file except in compliance with the License.
7*10d63b7dSRichard Lowe  *
8*10d63b7dSRichard Lowe  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*10d63b7dSRichard Lowe  * or http://www.opensolaris.org/os/licensing.
10*10d63b7dSRichard Lowe  * See the License for the specific language governing permissions
11*10d63b7dSRichard Lowe  * and limitations under the License.
12*10d63b7dSRichard Lowe  *
13*10d63b7dSRichard Lowe  * When distributing Covered Code, include this CDDL HEADER in each
14*10d63b7dSRichard Lowe  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*10d63b7dSRichard Lowe  * If applicable, add the following below this CDDL HEADER, with the
16*10d63b7dSRichard Lowe  * fields enclosed by brackets "[]" replaced with your own identifying
17*10d63b7dSRichard Lowe  * information: Portions Copyright [yyyy] [name of copyright owner]
18*10d63b7dSRichard Lowe  *
19*10d63b7dSRichard Lowe  * CDDL HEADER END
20*10d63b7dSRichard Lowe  */
21*10d63b7dSRichard Lowe /*
22*10d63b7dSRichard Lowe  * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
23*10d63b7dSRichard Lowe  * Use is subject to license terms.
24*10d63b7dSRichard Lowe  */
25*10d63b7dSRichard Lowe 
26*10d63b7dSRichard Lowe 
27*10d63b7dSRichard Lowe /*
28*10d63b7dSRichard Lowe  *	parallel.cc
29*10d63b7dSRichard Lowe  *
30*10d63b7dSRichard Lowe  *	Deal with the parallel processing
31*10d63b7dSRichard Lowe  */
32*10d63b7dSRichard Lowe 
33*10d63b7dSRichard Lowe /*
34*10d63b7dSRichard Lowe  * Included files
35*10d63b7dSRichard Lowe  */
36*10d63b7dSRichard Lowe #include <errno.h>		/* errno */
37*10d63b7dSRichard Lowe #include <fcntl.h>
38*10d63b7dSRichard Lowe #include <mk/defs.h>
39*10d63b7dSRichard Lowe #include <mksh/dosys.h>		/* redirect_io() */
40*10d63b7dSRichard Lowe #include <mksh/macro.h>		/* expand_value() */
41*10d63b7dSRichard Lowe #include <mksh/misc.h>		/* getmem() */
42*10d63b7dSRichard Lowe #include <sys/signal.h>
43*10d63b7dSRichard Lowe #include <sys/stat.h>
44*10d63b7dSRichard Lowe #include <sys/types.h>
45*10d63b7dSRichard Lowe #include <sys/utsname.h>
46*10d63b7dSRichard Lowe #include <sys/wait.h>
47*10d63b7dSRichard Lowe #include <unistd.h>
48*10d63b7dSRichard Lowe #include <netdb.h>
49*10d63b7dSRichard Lowe #include <libintl.h>
50*10d63b7dSRichard Lowe 
51*10d63b7dSRichard Lowe 
52*10d63b7dSRichard Lowe 
53*10d63b7dSRichard Lowe /*
54*10d63b7dSRichard Lowe  * Defined macros
55*10d63b7dSRichard Lowe  */
56*10d63b7dSRichard Lowe #define MAXRULES		100
57*10d63b7dSRichard Lowe 
58*10d63b7dSRichard Lowe /*
59*10d63b7dSRichard Lowe  * This const should be in avo_dms/include/AvoDmakeCommand.h
60*10d63b7dSRichard Lowe  */
61*10d63b7dSRichard Lowe const int local_host_mask = 0x20;
62*10d63b7dSRichard Lowe 
63*10d63b7dSRichard Lowe 
64*10d63b7dSRichard Lowe /*
65*10d63b7dSRichard Lowe  * typedefs & structs
66*10d63b7dSRichard Lowe  */
67*10d63b7dSRichard Lowe 
68*10d63b7dSRichard Lowe 
69*10d63b7dSRichard Lowe /*
70*10d63b7dSRichard Lowe  * Static variables
71*10d63b7dSRichard Lowe  */
72*10d63b7dSRichard Lowe static	Boolean		just_did_subtree = false;
73*10d63b7dSRichard Lowe static	char		local_host[MAXNAMELEN] = "";
74*10d63b7dSRichard Lowe static	char		user_name[MAXNAMELEN] = "";
75*10d63b7dSRichard Lowe static	int		pmake_max_jobs = 0;
76*10d63b7dSRichard Lowe static	pid_t		process_running = -1;
77*10d63b7dSRichard Lowe static	Running		*running_tail = &running_list;
78*10d63b7dSRichard Lowe static	Name		subtree_conflict;
79*10d63b7dSRichard Lowe static	Name		subtree_conflict2;
80*10d63b7dSRichard Lowe 
81*10d63b7dSRichard Lowe 
82*10d63b7dSRichard Lowe /*
83*10d63b7dSRichard Lowe  * File table of contents
84*10d63b7dSRichard Lowe  */
85*10d63b7dSRichard Lowe static	void		delete_running_struct(Running rp);
86*10d63b7dSRichard Lowe static	Boolean		dependency_conflict(Name target);
87*10d63b7dSRichard Lowe static	Doname		distribute_process(char **commands, Property line);
88*10d63b7dSRichard Lowe static	void		doname_subtree(Name target, Boolean do_get, Boolean implicit);
89*10d63b7dSRichard Lowe static	void		dump_out_file(char *filename, Boolean err);
90*10d63b7dSRichard Lowe static	void		finish_doname(Running rp);
91*10d63b7dSRichard Lowe static	void		maybe_reread_make_state(void);
92*10d63b7dSRichard Lowe static	void		process_next(void);
93*10d63b7dSRichard Lowe static	void		reset_conditionals(int cnt, Name *targets, Property *locals);
94*10d63b7dSRichard Lowe static	pid_t           run_rule_commands(char *host, char **commands);
95*10d63b7dSRichard Lowe static	Property	*set_conditionals(int cnt, Name *targets);
96*10d63b7dSRichard Lowe static	void		store_conditionals(Running rp);
97*10d63b7dSRichard Lowe 
98*10d63b7dSRichard Lowe 
99*10d63b7dSRichard Lowe /*
100*10d63b7dSRichard Lowe  *	execute_parallel(line, waitflg)
101*10d63b7dSRichard Lowe  *
102*10d63b7dSRichard Lowe  *	DMake 2.x:
103*10d63b7dSRichard Lowe  *	parallel mode: spawns a parallel process to execute the command group.
104*10d63b7dSRichard Lowe  *
105*10d63b7dSRichard Lowe  *	Return value:
106*10d63b7dSRichard Lowe  *				The result of the execution
107*10d63b7dSRichard Lowe  *
108*10d63b7dSRichard Lowe  *	Parameters:
109*10d63b7dSRichard Lowe  *		line		The command group to execute
110*10d63b7dSRichard Lowe  */
111*10d63b7dSRichard Lowe Doname
112*10d63b7dSRichard Lowe execute_parallel(Property line, Boolean waitflg, Boolean local)
113*10d63b7dSRichard Lowe {
114*10d63b7dSRichard Lowe 	int			argcnt;
115*10d63b7dSRichard Lowe 	int			cmd_options = 0;
116*10d63b7dSRichard Lowe 	char			*commands[MAXRULES + 5];
117*10d63b7dSRichard Lowe 	char			*cp;
118*10d63b7dSRichard Lowe 	Name			dmake_name;
119*10d63b7dSRichard Lowe 	Name			dmake_value;
120*10d63b7dSRichard Lowe 	int			ignore;
121*10d63b7dSRichard Lowe 	Name			make_machines_name;
122*10d63b7dSRichard Lowe 	char			**p;
123*10d63b7dSRichard Lowe 	Property		prop;
124*10d63b7dSRichard Lowe 	Doname			result = build_ok;
125*10d63b7dSRichard Lowe 	Cmd_line		rule;
126*10d63b7dSRichard Lowe 	Boolean			silent_flag;
127*10d63b7dSRichard Lowe 	Name			target = line->body.line.target;
128*10d63b7dSRichard Lowe 	Boolean			wrote_state_file = false;
129*10d63b7dSRichard Lowe 
130*10d63b7dSRichard Lowe 	if ((pmake_max_jobs == 0) &&
131*10d63b7dSRichard Lowe 	    (dmake_mode_type == parallel_mode)) {
132*10d63b7dSRichard Lowe 		if (local_host[0] == '\0') {
133*10d63b7dSRichard Lowe 			(void) gethostname(local_host, MAXNAMELEN);
134*10d63b7dSRichard Lowe 		}
135*10d63b7dSRichard Lowe 		MBSTOWCS(wcs_buffer, "DMAKE_MAX_JOBS");
136*10d63b7dSRichard Lowe 		dmake_name = GETNAME(wcs_buffer, FIND_LENGTH);
137*10d63b7dSRichard Lowe 		if (((prop = get_prop(dmake_name->prop, macro_prop)) != NULL) &&
138*10d63b7dSRichard Lowe 		    ((dmake_value = prop->body.macro.value) != NULL)) {
139*10d63b7dSRichard Lowe 			pmake_max_jobs = atoi(dmake_value->string_mb);
140*10d63b7dSRichard Lowe 			if (pmake_max_jobs <= 0) {
141*10d63b7dSRichard Lowe 				warning(gettext("DMAKE_MAX_JOBS cannot be less than or equal to zero."));
142*10d63b7dSRichard Lowe 				warning(gettext("setting DMAKE_MAX_JOBS to %d."), PMAKE_DEF_MAX_JOBS);
143*10d63b7dSRichard Lowe 				pmake_max_jobs = PMAKE_DEF_MAX_JOBS;
144*10d63b7dSRichard Lowe 			}
145*10d63b7dSRichard Lowe 		} else {
146*10d63b7dSRichard Lowe 			/*
147*10d63b7dSRichard Lowe 			 * For backwards compatibility w/ PMake 1.x, when
148*10d63b7dSRichard Lowe 			 * DMake 2.x is being run in parallel mode, DMake
149*10d63b7dSRichard Lowe 			 * should parse the PMake startup file
150*10d63b7dSRichard Lowe 			 * $(HOME)/.make.machines to get the pmake_max_jobs.
151*10d63b7dSRichard Lowe 			 */
152*10d63b7dSRichard Lowe 			MBSTOWCS(wcs_buffer, "PMAKE_MACHINESFILE");
153*10d63b7dSRichard Lowe 			dmake_name = GETNAME(wcs_buffer, FIND_LENGTH);
154*10d63b7dSRichard Lowe 			if (((prop = get_prop(dmake_name->prop, macro_prop)) != NULL) &&
155*10d63b7dSRichard Lowe 			    ((dmake_value = prop->body.macro.value) != NULL)) {
156*10d63b7dSRichard Lowe 				make_machines_name = dmake_value;
157*10d63b7dSRichard Lowe 			} else {
158*10d63b7dSRichard Lowe 				make_machines_name = NULL;
159*10d63b7dSRichard Lowe 			}
160*10d63b7dSRichard Lowe 			if ((pmake_max_jobs = read_make_machines(make_machines_name)) <= 0) {
161*10d63b7dSRichard Lowe 				pmake_max_jobs = PMAKE_DEF_MAX_JOBS;
162*10d63b7dSRichard Lowe 			}
163*10d63b7dSRichard Lowe 		}
164*10d63b7dSRichard Lowe 	}
165*10d63b7dSRichard Lowe 
166*10d63b7dSRichard Lowe 	if ((dmake_mode_type == serial_mode) ||
167*10d63b7dSRichard Lowe 	    ((dmake_mode_type == parallel_mode) && (waitflg))) {
168*10d63b7dSRichard Lowe 		return (execute_serial(line));
169*10d63b7dSRichard Lowe 	}
170*10d63b7dSRichard Lowe 
171*10d63b7dSRichard Lowe 	{
172*10d63b7dSRichard Lowe 		p = commands;
173*10d63b7dSRichard Lowe 	}
174*10d63b7dSRichard Lowe 
175*10d63b7dSRichard Lowe 	argcnt = 0;
176*10d63b7dSRichard Lowe 	for (rule = line->body.line.command_used;
177*10d63b7dSRichard Lowe 	     rule != NULL;
178*10d63b7dSRichard Lowe 	     rule = rule->next) {
179*10d63b7dSRichard Lowe 		if (posix && (touch || quest) && !rule->always_exec) {
180*10d63b7dSRichard Lowe 			continue;
181*10d63b7dSRichard Lowe 		}
182*10d63b7dSRichard Lowe 		if (vpath_defined) {
183*10d63b7dSRichard Lowe 			rule->command_line =
184*10d63b7dSRichard Lowe 			  vpath_translation(rule->command_line);
185*10d63b7dSRichard Lowe 		}
186*10d63b7dSRichard Lowe 
187*10d63b7dSRichard Lowe 		silent_flag = false;
188*10d63b7dSRichard Lowe 		ignore = 0;
189*10d63b7dSRichard Lowe 
190*10d63b7dSRichard Lowe 		if (rule->command_line->hash.length > 0) {
191*10d63b7dSRichard Lowe 			if (++argcnt == MAXRULES) {
192*10d63b7dSRichard Lowe 				return build_serial;
193*10d63b7dSRichard Lowe 			}
194*10d63b7dSRichard Lowe 			{
195*10d63b7dSRichard Lowe 				if (rule->silent && !silent) {
196*10d63b7dSRichard Lowe 					silent_flag = true;
197*10d63b7dSRichard Lowe 				}
198*10d63b7dSRichard Lowe 				if (rule->ignore_error) {
199*10d63b7dSRichard Lowe 					ignore++;
200*10d63b7dSRichard Lowe 				}
201*10d63b7dSRichard Lowe 				/* XXX - need to add support for + prefix */
202*10d63b7dSRichard Lowe 				if (silent_flag || ignore) {
203*10d63b7dSRichard Lowe 					*p = getmem((silent_flag ? 1 : 0) +
204*10d63b7dSRichard Lowe 						    ignore +
205*10d63b7dSRichard Lowe 						    (strlen(rule->
206*10d63b7dSRichard Lowe 						           command_line->
207*10d63b7dSRichard Lowe 						           string_mb)) +
208*10d63b7dSRichard Lowe 						    1);
209*10d63b7dSRichard Lowe 					cp = *p++;
210*10d63b7dSRichard Lowe 					if (silent_flag) {
211*10d63b7dSRichard Lowe 						*cp++ = (int) at_char;
212*10d63b7dSRichard Lowe 					}
213*10d63b7dSRichard Lowe 					if (ignore) {
214*10d63b7dSRichard Lowe 						*cp++ = (int) hyphen_char;
215*10d63b7dSRichard Lowe 					}
216*10d63b7dSRichard Lowe 					(void) strcpy(cp, rule->command_line->string_mb);
217*10d63b7dSRichard Lowe 				} else {
218*10d63b7dSRichard Lowe 					*p++ = rule->command_line->string_mb;
219*10d63b7dSRichard Lowe 				}
220*10d63b7dSRichard Lowe 			}
221*10d63b7dSRichard Lowe 		}
222*10d63b7dSRichard Lowe 	}
223*10d63b7dSRichard Lowe 	if ((argcnt == 0) ||
224*10d63b7dSRichard Lowe 	    (report_dependencies_level > 0)) {
225*10d63b7dSRichard Lowe 		return build_ok;
226*10d63b7dSRichard Lowe 	}
227*10d63b7dSRichard Lowe 	{
228*10d63b7dSRichard Lowe 		*p = NULL;
229*10d63b7dSRichard Lowe 
230*10d63b7dSRichard Lowe 		Doname res = distribute_process(commands, line);
231*10d63b7dSRichard Lowe 		if (res == build_running) {
232*10d63b7dSRichard Lowe 			parallel_process_cnt++;
233*10d63b7dSRichard Lowe 		}
234*10d63b7dSRichard Lowe 
235*10d63b7dSRichard Lowe 		/*
236*10d63b7dSRichard Lowe 		 * Return only those memory that were specially allocated
237*10d63b7dSRichard Lowe 		 * for part of commands.
238*10d63b7dSRichard Lowe 		 */
239*10d63b7dSRichard Lowe 		for (int i = 0; commands[i] != NULL; i++) {
240*10d63b7dSRichard Lowe 			if ((commands[i][0] == (int) at_char) ||
241*10d63b7dSRichard Lowe 			    (commands[i][0] == (int) hyphen_char)) {
242*10d63b7dSRichard Lowe 				retmem_mb(commands[i]);
243*10d63b7dSRichard Lowe 			}
244*10d63b7dSRichard Lowe 		}
245*10d63b7dSRichard Lowe 		return res;
246*10d63b7dSRichard Lowe 	}
247*10d63b7dSRichard Lowe }
248*10d63b7dSRichard Lowe 
249*10d63b7dSRichard Lowe 
250*10d63b7dSRichard Lowe 
251*10d63b7dSRichard Lowe #include <unistd.h>	/* sysconf(_SC_NPROCESSORS_ONLN) */
252*10d63b7dSRichard Lowe #include <sys/ipc.h>		/* ftok() */
253*10d63b7dSRichard Lowe #include <sys/shm.h>		/* shmget(), shmat(), shmdt(), shmctl() */
254*10d63b7dSRichard Lowe #include <semaphore.h>		/* sem_init(), sem_trywait(), sem_post(), sem_destroy() */
255*10d63b7dSRichard Lowe #include <sys/loadavg.h>	/* getloadavg() */
256*10d63b7dSRichard Lowe 
257*10d63b7dSRichard Lowe /*
258*10d63b7dSRichard Lowe  *	adjust_pmake_max_jobs (int pmake_max_jobs)
259*10d63b7dSRichard Lowe  *
260*10d63b7dSRichard Lowe  *	Parameters:
261*10d63b7dSRichard Lowe  * 		pmake_max_jobs	- max jobs limit set by user
262*10d63b7dSRichard Lowe  *
263*10d63b7dSRichard Lowe  *	External functions used:
264*10d63b7dSRichard Lowe  *		sysconf()
265*10d63b7dSRichard Lowe  * 		getloadavg()
266*10d63b7dSRichard Lowe  */
267*10d63b7dSRichard Lowe static int
268*10d63b7dSRichard Lowe adjust_pmake_max_jobs (int pmake_max_jobs)
269*10d63b7dSRichard Lowe {
270*10d63b7dSRichard Lowe 	static int	ncpu = 0;
271*10d63b7dSRichard Lowe 	double		loadavg[3];
272*10d63b7dSRichard Lowe 	int		adjustment;
273*10d63b7dSRichard Lowe 	int		adjusted_max_jobs;
274*10d63b7dSRichard Lowe 
275*10d63b7dSRichard Lowe 	if (ncpu <= 0) {
276*10d63b7dSRichard Lowe 		if ((ncpu = sysconf(_SC_NPROCESSORS_ONLN)) <= 0) {
277*10d63b7dSRichard Lowe 			ncpu = 1;
278*10d63b7dSRichard Lowe 		}
279*10d63b7dSRichard Lowe 	}
280*10d63b7dSRichard Lowe 	if (getloadavg(loadavg, 3) != 3) return(pmake_max_jobs);
281*10d63b7dSRichard Lowe 	adjustment = ((int)loadavg[LOADAVG_1MIN]);
282*10d63b7dSRichard Lowe 	if (adjustment < 2) return(pmake_max_jobs);
283*10d63b7dSRichard Lowe 	if (ncpu > 1) {
284*10d63b7dSRichard Lowe 		adjustment = adjustment / ncpu;
285*10d63b7dSRichard Lowe 	}
286*10d63b7dSRichard Lowe 	adjusted_max_jobs = pmake_max_jobs - adjustment;
287*10d63b7dSRichard Lowe 	if (adjusted_max_jobs < 1) adjusted_max_jobs = 1;
288*10d63b7dSRichard Lowe 	return(adjusted_max_jobs);
289*10d63b7dSRichard Lowe }
290*10d63b7dSRichard Lowe 
291*10d63b7dSRichard Lowe /*
292*10d63b7dSRichard Lowe  *  M2 adjust mode data and functions
293*10d63b7dSRichard Lowe  *
294*10d63b7dSRichard Lowe  *  m2_init()		- initializes M2 shared semaphore
295*10d63b7dSRichard Lowe  *  m2_acquire_job()	- decrements M2 semaphore counter
296*10d63b7dSRichard Lowe  *  m2_release_job()	- increments M2 semaphore counter
297*10d63b7dSRichard Lowe  *  m2_fini()		- destroys M2 semaphore and shared memory*
298*10d63b7dSRichard Lowe  *
299*10d63b7dSRichard Lowe  *  Environment variables:
300*10d63b7dSRichard Lowe  *	__DMAKE_M2_FILE__
301*10d63b7dSRichard Lowe  *
302*10d63b7dSRichard Lowe  *  External functions:
303*10d63b7dSRichard Lowe  *	ftok(), shmget(), shmat(), shmdt(), shmctl()
304*10d63b7dSRichard Lowe  *	sem_init(), sem_trywait(), sem_post(), sem_destroy()
305*10d63b7dSRichard Lowe  *	creat(), close(), unlink()
306*10d63b7dSRichard Lowe  *	getenv(), putenv()
307*10d63b7dSRichard Lowe  *
308*10d63b7dSRichard Lowe  *  Static variables:
309*10d63b7dSRichard Lowe  *	m2_file		- tmp file name to create ipc key for shared memory
310*10d63b7dSRichard Lowe  *	m2_shm_id	- shared memory id
311*10d63b7dSRichard Lowe  *	m2_shm_sem	- shared memory semaphore
312*10d63b7dSRichard Lowe  */
313*10d63b7dSRichard Lowe 
314*10d63b7dSRichard Lowe static char	m2_file[MAXPATHLEN];
315*10d63b7dSRichard Lowe static int	m2_shm_id = -1;
316*10d63b7dSRichard Lowe static sem_t*	m2_shm_sem = 0;
317*10d63b7dSRichard Lowe 
318*10d63b7dSRichard Lowe static int
319*10d63b7dSRichard Lowe m2_init() {
320*10d63b7dSRichard Lowe 	char	*var;
321*10d63b7dSRichard Lowe 	key_t	key;
322*10d63b7dSRichard Lowe 
323*10d63b7dSRichard Lowe 	if ((var = getenv("__DMAKE_M2_FILE__")) == 0) {
324*10d63b7dSRichard Lowe 		/* compose tmp file name */
325*10d63b7dSRichard Lowe 		sprintf(m2_file, "%s/dmake.m2.%d.XXXXXX", tmpdir, getpid());
326*10d63b7dSRichard Lowe 
327*10d63b7dSRichard Lowe 		/* create tmp file */
328*10d63b7dSRichard Lowe 		int fd = mkstemp(m2_file);
329*10d63b7dSRichard Lowe 		if (fd < 0) {
330*10d63b7dSRichard Lowe 			return -1;
331*10d63b7dSRichard Lowe 		} else {
332*10d63b7dSRichard Lowe 			close(fd);
333*10d63b7dSRichard Lowe 		}
334*10d63b7dSRichard Lowe 	} else {
335*10d63b7dSRichard Lowe 		/* using existing semaphore */
336*10d63b7dSRichard Lowe 		strcpy(m2_file, var);
337*10d63b7dSRichard Lowe 	}
338*10d63b7dSRichard Lowe 
339*10d63b7dSRichard Lowe 	/* combine IPC key */
340*10d63b7dSRichard Lowe 	if ((key = ftok(m2_file, 38)) == (key_t) -1) {
341*10d63b7dSRichard Lowe 		return -1;
342*10d63b7dSRichard Lowe 	}
343*10d63b7dSRichard Lowe 
344*10d63b7dSRichard Lowe 	/* create shared memory */
345*10d63b7dSRichard Lowe 	if ((m2_shm_id = shmget(key, sizeof(*m2_shm_sem), 0666 | (var ? 0 : IPC_CREAT|IPC_EXCL))) == -1) {
346*10d63b7dSRichard Lowe 		return -1;
347*10d63b7dSRichard Lowe 	}
348*10d63b7dSRichard Lowe 
349*10d63b7dSRichard Lowe 	/* attach shared memory */
350*10d63b7dSRichard Lowe 	if ((m2_shm_sem = (sem_t*) shmat(m2_shm_id, 0, 0666)) == (sem_t*)-1) {
351*10d63b7dSRichard Lowe 		return -1;
352*10d63b7dSRichard Lowe 	}
353*10d63b7dSRichard Lowe 
354*10d63b7dSRichard Lowe 	/* root process */
355*10d63b7dSRichard Lowe 	if (var == 0) {
356*10d63b7dSRichard Lowe 		/* initialize semaphore */
357*10d63b7dSRichard Lowe 		if (sem_init(m2_shm_sem, 1, pmake_max_jobs)) {
358*10d63b7dSRichard Lowe 			return -1;
359*10d63b7dSRichard Lowe 		}
360*10d63b7dSRichard Lowe 
361*10d63b7dSRichard Lowe 		/* alloc memory for env variable */
362*10d63b7dSRichard Lowe 		if ((var = (char*) malloc(MAXPATHLEN)) == 0) {
363*10d63b7dSRichard Lowe 			return -1;
364*10d63b7dSRichard Lowe 		}
365*10d63b7dSRichard Lowe 
366*10d63b7dSRichard Lowe 		/* put key to env */
367*10d63b7dSRichard Lowe 		sprintf(var, "__DMAKE_M2_FILE__=%s", m2_file);
368*10d63b7dSRichard Lowe 		if (putenv(var)) {
369*10d63b7dSRichard Lowe 			return -1;
370*10d63b7dSRichard Lowe 		}
371*10d63b7dSRichard Lowe 	}
372*10d63b7dSRichard Lowe 	return 0;
373*10d63b7dSRichard Lowe }
374*10d63b7dSRichard Lowe 
375*10d63b7dSRichard Lowe static void
376*10d63b7dSRichard Lowe m2_fini() {
377*10d63b7dSRichard Lowe 	if (m2_shm_id >= 0) {
378*10d63b7dSRichard Lowe 		struct shmid_ds stat;
379*10d63b7dSRichard Lowe 
380*10d63b7dSRichard Lowe 		/* determine the number of attached processes */
381*10d63b7dSRichard Lowe 		if (shmctl(m2_shm_id, IPC_STAT, &stat) == 0) {
382*10d63b7dSRichard Lowe 			if (stat.shm_nattch <= 1) {
383*10d63b7dSRichard Lowe 				/* destroy semaphore */
384*10d63b7dSRichard Lowe 				if (m2_shm_sem != 0) {
385*10d63b7dSRichard Lowe 					(void) sem_destroy(m2_shm_sem);
386*10d63b7dSRichard Lowe 				}
387*10d63b7dSRichard Lowe 
388*10d63b7dSRichard Lowe 				/* destroy shared memory */
389*10d63b7dSRichard Lowe 				(void) shmctl(m2_shm_id, IPC_RMID, &stat);
390*10d63b7dSRichard Lowe 
391*10d63b7dSRichard Lowe 				/* remove tmp file created for the key */
392*10d63b7dSRichard Lowe 				(void) unlink(m2_file);
393*10d63b7dSRichard Lowe 			} else {
394*10d63b7dSRichard Lowe 				/* detach shared memory */
395*10d63b7dSRichard Lowe 				if (m2_shm_sem != 0) {
396*10d63b7dSRichard Lowe 					(void) shmdt((char*) m2_shm_sem);
397*10d63b7dSRichard Lowe 				}
398*10d63b7dSRichard Lowe 			}
399*10d63b7dSRichard Lowe 		}
400*10d63b7dSRichard Lowe 
401*10d63b7dSRichard Lowe 		m2_shm_id = -1;
402*10d63b7dSRichard Lowe 		m2_shm_sem = 0;
403*10d63b7dSRichard Lowe 	}
404*10d63b7dSRichard Lowe }
405*10d63b7dSRichard Lowe 
406*10d63b7dSRichard Lowe static int
407*10d63b7dSRichard Lowe m2_acquire_job() {
408*10d63b7dSRichard Lowe 	if ((m2_shm_id >= 0) && (m2_shm_sem != 0)) {
409*10d63b7dSRichard Lowe 		if (sem_trywait(m2_shm_sem) == 0) {
410*10d63b7dSRichard Lowe 			return 1;
411*10d63b7dSRichard Lowe 		}
412*10d63b7dSRichard Lowe 		if (errno == EAGAIN) {
413*10d63b7dSRichard Lowe 			return 0;
414*10d63b7dSRichard Lowe 		}
415*10d63b7dSRichard Lowe 	}
416*10d63b7dSRichard Lowe 	return -1;
417*10d63b7dSRichard Lowe }
418*10d63b7dSRichard Lowe 
419*10d63b7dSRichard Lowe static int
420*10d63b7dSRichard Lowe m2_release_job() {
421*10d63b7dSRichard Lowe 	if ((m2_shm_id >= 0) && (m2_shm_sem != 0)) {
422*10d63b7dSRichard Lowe 		if (sem_post(m2_shm_sem) == 0) {
423*10d63b7dSRichard Lowe 			return 0;
424*10d63b7dSRichard Lowe 		}
425*10d63b7dSRichard Lowe 	}
426*10d63b7dSRichard Lowe 	return -1;
427*10d63b7dSRichard Lowe }
428*10d63b7dSRichard Lowe 
429*10d63b7dSRichard Lowe /*
430*10d63b7dSRichard Lowe  *  job adjust mode
431*10d63b7dSRichard Lowe  *
432*10d63b7dSRichard Lowe  *  Possible values:
433*10d63b7dSRichard Lowe  *    ADJUST_M1		- adjustment by system load (default)
434*10d63b7dSRichard Lowe  *    ADJUST_M2		- fixed limit of jobs for the group of nested dmakes
435*10d63b7dSRichard Lowe  *    ADJUST_NONE	- no adjustment - fixed limit of jobs for the current dmake
436*10d63b7dSRichard Lowe  */
437*10d63b7dSRichard Lowe static enum {
438*10d63b7dSRichard Lowe 	ADJUST_UNKNOWN,
439*10d63b7dSRichard Lowe 	ADJUST_M1,
440*10d63b7dSRichard Lowe 	ADJUST_M2,
441*10d63b7dSRichard Lowe 	ADJUST_NONE
442*10d63b7dSRichard Lowe } job_adjust_mode = ADJUST_UNKNOWN;
443*10d63b7dSRichard Lowe 
444*10d63b7dSRichard Lowe /*
445*10d63b7dSRichard Lowe  *  void job_adjust_fini()
446*10d63b7dSRichard Lowe  *
447*10d63b7dSRichard Lowe  *  Description:
448*10d63b7dSRichard Lowe  *	Cleans up job adjust data.
449*10d63b7dSRichard Lowe  *
450*10d63b7dSRichard Lowe  *  Static variables:
451*10d63b7dSRichard Lowe  *	job_adjust_mode	Current job adjust mode
452*10d63b7dSRichard Lowe  */
453*10d63b7dSRichard Lowe void
454*10d63b7dSRichard Lowe job_adjust_fini() {
455*10d63b7dSRichard Lowe 	if (job_adjust_mode == ADJUST_M2) {
456*10d63b7dSRichard Lowe 		m2_fini();
457*10d63b7dSRichard Lowe 	}
458*10d63b7dSRichard Lowe }
459*10d63b7dSRichard Lowe 
460*10d63b7dSRichard Lowe /*
461*10d63b7dSRichard Lowe  *  void job_adjust_error()
462*10d63b7dSRichard Lowe  *
463*10d63b7dSRichard Lowe  *  Description:
464*10d63b7dSRichard Lowe  *	Prints warning message, cleans up job adjust data, and disables job adjustment
465*10d63b7dSRichard Lowe  *
466*10d63b7dSRichard Lowe  *  Environment:
467*10d63b7dSRichard Lowe  *	DMAKE_ADJUST_MAX_JOBS
468*10d63b7dSRichard Lowe  *
469*10d63b7dSRichard Lowe  *  External functions:
470*10d63b7dSRichard Lowe  *	putenv()
471*10d63b7dSRichard Lowe  *
472*10d63b7dSRichard Lowe  *  Static variables:
473*10d63b7dSRichard Lowe  *	job_adjust_mode	Current job adjust mode
474*10d63b7dSRichard Lowe  */
475*10d63b7dSRichard Lowe static void
476*10d63b7dSRichard Lowe job_adjust_error() {
477*10d63b7dSRichard Lowe 	if (job_adjust_mode != ADJUST_NONE) {
478*10d63b7dSRichard Lowe 		/* cleanup internals */
479*10d63b7dSRichard Lowe 		job_adjust_fini();
480*10d63b7dSRichard Lowe 
481*10d63b7dSRichard Lowe 		/* warning message for the user */
482*10d63b7dSRichard Lowe 		warning(gettext("Encountered max jobs auto adjustment error - disabling auto adjustment."));
483*10d63b7dSRichard Lowe 
484*10d63b7dSRichard Lowe 		/* switch off job adjustment for the children */
485*10d63b7dSRichard Lowe 		putenv(strdup("DMAKE_ADJUST_MAX_JOBS=NO"));
486*10d63b7dSRichard Lowe 
487*10d63b7dSRichard Lowe 		/* and for this dmake */
488*10d63b7dSRichard Lowe 		job_adjust_mode = ADJUST_NONE;
489*10d63b7dSRichard Lowe 	}
490*10d63b7dSRichard Lowe }
491*10d63b7dSRichard Lowe 
492*10d63b7dSRichard Lowe /*
493*10d63b7dSRichard Lowe  *  void job_adjust_init()
494*10d63b7dSRichard Lowe  *
495*10d63b7dSRichard Lowe  *  Description:
496*10d63b7dSRichard Lowe  *	Parses DMAKE_ADJUST_MAX_JOBS env variable
497*10d63b7dSRichard Lowe  *	and performs appropriate initializations.
498*10d63b7dSRichard Lowe  *
499*10d63b7dSRichard Lowe  *  Environment:
500*10d63b7dSRichard Lowe  *	DMAKE_ADJUST_MAX_JOBS
501*10d63b7dSRichard Lowe  *	  DMAKE_ADJUST_MAX_JOBS == "NO"	- no adjustment
502*10d63b7dSRichard Lowe  *	  DMAKE_ADJUST_MAX_JOBS == "M2"	- M2 adjust mode
503*10d63b7dSRichard Lowe  *	  other				- M1 adjust mode
504*10d63b7dSRichard Lowe  *
505*10d63b7dSRichard Lowe  *  External functions:
506*10d63b7dSRichard Lowe  *	getenv()
507*10d63b7dSRichard Lowe  *
508*10d63b7dSRichard Lowe  *  Static variables:
509*10d63b7dSRichard Lowe  *	job_adjust_mode	Current job adjust mode
510*10d63b7dSRichard Lowe  */
511*10d63b7dSRichard Lowe static void
512*10d63b7dSRichard Lowe job_adjust_init() {
513*10d63b7dSRichard Lowe 	if (job_adjust_mode == ADJUST_UNKNOWN) {
514*10d63b7dSRichard Lowe 		/* default mode */
515*10d63b7dSRichard Lowe 		job_adjust_mode = ADJUST_M1;
516*10d63b7dSRichard Lowe 
517*10d63b7dSRichard Lowe 		/* determine adjust mode */
518*10d63b7dSRichard Lowe 		if (char *var = getenv("DMAKE_ADJUST_MAX_JOBS")) {
519*10d63b7dSRichard Lowe 			if (strcasecmp(var, "NO") == 0) {
520*10d63b7dSRichard Lowe 				job_adjust_mode = ADJUST_NONE;
521*10d63b7dSRichard Lowe 			} else if (strcasecmp(var, "M2") == 0) {
522*10d63b7dSRichard Lowe 				job_adjust_mode = ADJUST_M2;
523*10d63b7dSRichard Lowe 			}
524*10d63b7dSRichard Lowe 		}
525*10d63b7dSRichard Lowe 
526*10d63b7dSRichard Lowe 		/* M2 specific initialization */
527*10d63b7dSRichard Lowe 		if (job_adjust_mode == ADJUST_M2) {
528*10d63b7dSRichard Lowe 			if (m2_init()) {
529*10d63b7dSRichard Lowe 				job_adjust_error();
530*10d63b7dSRichard Lowe 			}
531*10d63b7dSRichard Lowe 		}
532*10d63b7dSRichard Lowe 	}
533*10d63b7dSRichard Lowe }
534*10d63b7dSRichard Lowe 
535*10d63b7dSRichard Lowe 
536*10d63b7dSRichard Lowe /*
537*10d63b7dSRichard Lowe  *	distribute_process(char **commands, Property line)
538*10d63b7dSRichard Lowe  *
539*10d63b7dSRichard Lowe  *	Parameters:
540*10d63b7dSRichard Lowe  *		commands	argv vector of commands to execute
541*10d63b7dSRichard Lowe  *
542*10d63b7dSRichard Lowe  *	Return value:
543*10d63b7dSRichard Lowe  *				The result of the execution
544*10d63b7dSRichard Lowe  *
545*10d63b7dSRichard Lowe  *	Static variables used:
546*10d63b7dSRichard Lowe  *		process_running	Set to the pid of the process set running
547*10d63b7dSRichard Lowe  *		job_adjust_mode	Current job adjust mode
548*10d63b7dSRichard Lowe  */
549*10d63b7dSRichard Lowe static Doname
550*10d63b7dSRichard Lowe distribute_process(char **commands, Property line)
551*10d63b7dSRichard Lowe {
552*10d63b7dSRichard Lowe 	static unsigned	file_number = 0;
553*10d63b7dSRichard Lowe 	wchar_t		string[MAXPATHLEN];
554*10d63b7dSRichard Lowe 	char		mbstring[MAXPATHLEN];
555*10d63b7dSRichard Lowe 	int		filed;
556*10d63b7dSRichard Lowe 	int		res;
557*10d63b7dSRichard Lowe 	int		tmp_index;
558*10d63b7dSRichard Lowe 	char		*tmp_index_str_ptr;
559*10d63b7dSRichard Lowe 
560*10d63b7dSRichard Lowe 	/* initialize adjust mode, if not initialized */
561*10d63b7dSRichard Lowe 	if (job_adjust_mode == ADJUST_UNKNOWN) {
562*10d63b7dSRichard Lowe 		job_adjust_init();
563*10d63b7dSRichard Lowe 	}
564*10d63b7dSRichard Lowe 
565*10d63b7dSRichard Lowe 	/* actions depend on adjust mode */
566*10d63b7dSRichard Lowe 	switch (job_adjust_mode) {
567*10d63b7dSRichard Lowe 	case ADJUST_M1:
568*10d63b7dSRichard Lowe 		while (parallel_process_cnt >= adjust_pmake_max_jobs (pmake_max_jobs)) {
569*10d63b7dSRichard Lowe 			await_parallel(false);
570*10d63b7dSRichard Lowe 			finish_children(true);
571*10d63b7dSRichard Lowe 		}
572*10d63b7dSRichard Lowe 		break;
573*10d63b7dSRichard Lowe 	case ADJUST_M2:
574*10d63b7dSRichard Lowe 		if ((res = m2_acquire_job()) == 0) {
575*10d63b7dSRichard Lowe 			if (parallel_process_cnt > 0) {
576*10d63b7dSRichard Lowe 				await_parallel(false);
577*10d63b7dSRichard Lowe 				finish_children(true);
578*10d63b7dSRichard Lowe 
579*10d63b7dSRichard Lowe 				if ((res = m2_acquire_job()) == 0) {
580*10d63b7dSRichard Lowe 					return build_serial;
581*10d63b7dSRichard Lowe 				}
582*10d63b7dSRichard Lowe 			} else {
583*10d63b7dSRichard Lowe 				return build_serial;
584*10d63b7dSRichard Lowe 			}
585*10d63b7dSRichard Lowe 		}
586*10d63b7dSRichard Lowe 		if (res < 0) {
587*10d63b7dSRichard Lowe 			/* job adjustment error */
588*10d63b7dSRichard Lowe 			job_adjust_error();
589*10d63b7dSRichard Lowe 
590*10d63b7dSRichard Lowe 			/* no adjustment */
591*10d63b7dSRichard Lowe 			while (parallel_process_cnt >= pmake_max_jobs) {
592*10d63b7dSRichard Lowe 				await_parallel(false);
593*10d63b7dSRichard Lowe 				finish_children(true);
594*10d63b7dSRichard Lowe 			}
595*10d63b7dSRichard Lowe 		}
596*10d63b7dSRichard Lowe 		break;
597*10d63b7dSRichard Lowe 	default:
598*10d63b7dSRichard Lowe 		while (parallel_process_cnt >= pmake_max_jobs) {
599*10d63b7dSRichard Lowe 			await_parallel(false);
600*10d63b7dSRichard Lowe 			finish_children(true);
601*10d63b7dSRichard Lowe 		}
602*10d63b7dSRichard Lowe 	}
603*10d63b7dSRichard Lowe 
604*10d63b7dSRichard Lowe 	setvar_envvar();
605*10d63b7dSRichard Lowe 	/*
606*10d63b7dSRichard Lowe 	 * Tell the user what DMake is doing.
607*10d63b7dSRichard Lowe 	 */
608*10d63b7dSRichard Lowe 	if (!silent && output_mode != txt2_mode) {
609*10d63b7dSRichard Lowe 		/*
610*10d63b7dSRichard Lowe 		 * Print local_host --> x job(s).
611*10d63b7dSRichard Lowe 		 */
612*10d63b7dSRichard Lowe 		(void) fprintf(stdout,
613*10d63b7dSRichard Lowe 		               gettext("%s --> %d %s\n"),
614*10d63b7dSRichard Lowe 		               local_host,
615*10d63b7dSRichard Lowe 		               parallel_process_cnt + 1,
616*10d63b7dSRichard Lowe 		               (parallel_process_cnt == 0) ? gettext("job") : gettext("jobs"));
617*10d63b7dSRichard Lowe 
618*10d63b7dSRichard Lowe 		/* Print command line(s). */
619*10d63b7dSRichard Lowe 		tmp_index = 0;
620*10d63b7dSRichard Lowe 		while (commands[tmp_index] != NULL) {
621*10d63b7dSRichard Lowe 		    /* No @ char. */
622*10d63b7dSRichard Lowe 		    /* XXX - need to add [2] when + prefix is added */
623*10d63b7dSRichard Lowe 		    if ((commands[tmp_index][0] != (int) at_char) &&
624*10d63b7dSRichard Lowe 		        (commands[tmp_index][1] != (int) at_char)) {
625*10d63b7dSRichard Lowe 			tmp_index_str_ptr = commands[tmp_index];
626*10d63b7dSRichard Lowe 			if (*tmp_index_str_ptr == (int) hyphen_char) {
627*10d63b7dSRichard Lowe 				tmp_index_str_ptr++;
628*10d63b7dSRichard Lowe 			}
629*10d63b7dSRichard Lowe                         (void) fprintf(stdout, "%s\n", tmp_index_str_ptr);
630*10d63b7dSRichard Lowe 		    }
631*10d63b7dSRichard Lowe 		    tmp_index++;
632*10d63b7dSRichard Lowe 		}
633*10d63b7dSRichard Lowe 		(void) fflush(stdout);
634*10d63b7dSRichard Lowe 	}
635*10d63b7dSRichard Lowe 
636*10d63b7dSRichard Lowe 	(void) sprintf(mbstring,
637*10d63b7dSRichard Lowe 		        "%s/dmake.stdout.%d.%d.XXXXXX",
638*10d63b7dSRichard Lowe 			tmpdir,
639*10d63b7dSRichard Lowe 		        getpid(),
640*10d63b7dSRichard Lowe 	                file_number++);
641*10d63b7dSRichard Lowe 
642*10d63b7dSRichard Lowe 	mktemp(mbstring);
643*10d63b7dSRichard Lowe 
644*10d63b7dSRichard Lowe 	stdout_file = strdup(mbstring);
645*10d63b7dSRichard Lowe 	stderr_file = NULL;
646*10d63b7dSRichard Lowe 
647*10d63b7dSRichard Lowe 	if (!out_err_same) {
648*10d63b7dSRichard Lowe 		(void) sprintf(mbstring,
649*10d63b7dSRichard Lowe 			        "%s/dmake.stderr.%d.%d.XXXXXX",
650*10d63b7dSRichard Lowe 				tmpdir,
651*10d63b7dSRichard Lowe 			        getpid(),
652*10d63b7dSRichard Lowe 		                file_number++);
653*10d63b7dSRichard Lowe 
654*10d63b7dSRichard Lowe 		mktemp(mbstring);
655*10d63b7dSRichard Lowe 
656*10d63b7dSRichard Lowe 		stderr_file = strdup(mbstring);
657*10d63b7dSRichard Lowe 	}
658*10d63b7dSRichard Lowe 
659*10d63b7dSRichard Lowe 	process_running = run_rule_commands(local_host, commands);
660*10d63b7dSRichard Lowe 
661*10d63b7dSRichard Lowe 	return build_running;
662*10d63b7dSRichard Lowe }
663*10d63b7dSRichard Lowe 
664*10d63b7dSRichard Lowe /*
665*10d63b7dSRichard Lowe  *	doname_parallel(target, do_get, implicit)
666*10d63b7dSRichard Lowe  *
667*10d63b7dSRichard Lowe  *	Processes the given target and finishes up any parallel
668*10d63b7dSRichard Lowe  *	processes left running.
669*10d63b7dSRichard Lowe  *
670*10d63b7dSRichard Lowe  *	Return value:
671*10d63b7dSRichard Lowe  *				Result of target build
672*10d63b7dSRichard Lowe  *
673*10d63b7dSRichard Lowe  *	Parameters:
674*10d63b7dSRichard Lowe  *		target		Target to build
675*10d63b7dSRichard Lowe  *		do_get		True if sccs get to be done
676*10d63b7dSRichard Lowe  *		implicit	True if this is an implicit target
677*10d63b7dSRichard Lowe  */
678*10d63b7dSRichard Lowe Doname
679*10d63b7dSRichard Lowe doname_parallel(Name target, Boolean do_get, Boolean implicit)
680*10d63b7dSRichard Lowe {
681*10d63b7dSRichard Lowe 	Doname		result;
682*10d63b7dSRichard Lowe 
683*10d63b7dSRichard Lowe 	result = doname_check(target, do_get, implicit, false);
684*10d63b7dSRichard Lowe 	if (result == build_ok || result == build_failed) {
685*10d63b7dSRichard Lowe 		return result;
686*10d63b7dSRichard Lowe 	}
687*10d63b7dSRichard Lowe 	finish_running();
688*10d63b7dSRichard Lowe 	return (Doname) target->state;
689*10d63b7dSRichard Lowe }
690*10d63b7dSRichard Lowe 
691*10d63b7dSRichard Lowe /*
692*10d63b7dSRichard Lowe  *	doname_subtree(target, do_get, implicit)
693*10d63b7dSRichard Lowe  *
694*10d63b7dSRichard Lowe  *	Completely computes an object and its dependents for a
695*10d63b7dSRichard Lowe  *	serial subtree build.
696*10d63b7dSRichard Lowe  *
697*10d63b7dSRichard Lowe  *	Parameters:
698*10d63b7dSRichard Lowe  *		target		Target to build
699*10d63b7dSRichard Lowe  *		do_get		True if sccs get to be done
700*10d63b7dSRichard Lowe  *		implicit	True if this is an implicit target
701*10d63b7dSRichard Lowe  *
702*10d63b7dSRichard Lowe  *	Static variables used:
703*10d63b7dSRichard Lowe  *		running_tail	Tail of the list of running processes
704*10d63b7dSRichard Lowe  *
705*10d63b7dSRichard Lowe  *	Global variables used:
706*10d63b7dSRichard Lowe  *		running_list	The list of running processes
707*10d63b7dSRichard Lowe  */
708*10d63b7dSRichard Lowe static void
709*10d63b7dSRichard Lowe doname_subtree(Name target, Boolean do_get, Boolean implicit)
710*10d63b7dSRichard Lowe {
711*10d63b7dSRichard Lowe 	Running		save_running_list;
712*10d63b7dSRichard Lowe 	Running		*save_running_tail;
713*10d63b7dSRichard Lowe 
714*10d63b7dSRichard Lowe 	save_running_list = running_list;
715*10d63b7dSRichard Lowe 	save_running_tail = running_tail;
716*10d63b7dSRichard Lowe 	running_list = NULL;
717*10d63b7dSRichard Lowe 	running_tail = &running_list;
718*10d63b7dSRichard Lowe 	target->state = build_subtree;
719*10d63b7dSRichard Lowe 	target->checking_subtree = true;
720*10d63b7dSRichard Lowe 	while(doname_check(target, do_get, implicit, false) == build_running) {
721*10d63b7dSRichard Lowe 		target->checking_subtree = false;
722*10d63b7dSRichard Lowe 		finish_running();
723*10d63b7dSRichard Lowe 		target->state = build_subtree;
724*10d63b7dSRichard Lowe 	}
725*10d63b7dSRichard Lowe 	target->checking_subtree = false;
726*10d63b7dSRichard Lowe 	running_list = save_running_list;
727*10d63b7dSRichard Lowe 	running_tail = save_running_tail;
728*10d63b7dSRichard Lowe }
729*10d63b7dSRichard Lowe 
730*10d63b7dSRichard Lowe /*
731*10d63b7dSRichard Lowe  *	finish_running()
732*10d63b7dSRichard Lowe  *
733*10d63b7dSRichard Lowe  *	Keeps processing until the running_list is emptied out.
734*10d63b7dSRichard Lowe  *
735*10d63b7dSRichard Lowe  *	Parameters:
736*10d63b7dSRichard Lowe  *
737*10d63b7dSRichard Lowe  *	Global variables used:
738*10d63b7dSRichard Lowe  *		running_list	The list of running processes
739*10d63b7dSRichard Lowe  */
740*10d63b7dSRichard Lowe void
741*10d63b7dSRichard Lowe finish_running(void)
742*10d63b7dSRichard Lowe {
743*10d63b7dSRichard Lowe 	while (running_list != NULL) {
744*10d63b7dSRichard Lowe 		{
745*10d63b7dSRichard Lowe 			await_parallel(false);
746*10d63b7dSRichard Lowe 			finish_children(true);
747*10d63b7dSRichard Lowe 		}
748*10d63b7dSRichard Lowe 		if (running_list != NULL) {
749*10d63b7dSRichard Lowe 			process_next();
750*10d63b7dSRichard Lowe 		}
751*10d63b7dSRichard Lowe 	}
752*10d63b7dSRichard Lowe }
753*10d63b7dSRichard Lowe 
754*10d63b7dSRichard Lowe /*
755*10d63b7dSRichard Lowe  *	process_next()
756*10d63b7dSRichard Lowe  *
757*10d63b7dSRichard Lowe  *	Searches the running list for any targets which can start processing.
758*10d63b7dSRichard Lowe  *	This can be a pending target, a serial target, or a subtree target.
759*10d63b7dSRichard Lowe  *
760*10d63b7dSRichard Lowe  *	Parameters:
761*10d63b7dSRichard Lowe  *
762*10d63b7dSRichard Lowe  *	Static variables used:
763*10d63b7dSRichard Lowe  *		running_tail		The end of the list of running procs
764*10d63b7dSRichard Lowe  *		subtree_conflict	A target which conflicts with a subtree
765*10d63b7dSRichard Lowe  *		subtree_conflict2	The other target which conflicts
766*10d63b7dSRichard Lowe  *
767*10d63b7dSRichard Lowe  *	Global variables used:
768*10d63b7dSRichard Lowe  *		commands_done		True if commands executed
769*10d63b7dSRichard Lowe  *		debug_level		Controls debug output
770*10d63b7dSRichard Lowe  *		parallel_process_cnt	Number of parallel process running
771*10d63b7dSRichard Lowe  *		recursion_level		Indentation for debug output
772*10d63b7dSRichard Lowe  *		running_list		List of running processes
773*10d63b7dSRichard Lowe  */
774*10d63b7dSRichard Lowe static void
775*10d63b7dSRichard Lowe process_next(void)
776*10d63b7dSRichard Lowe {
777*10d63b7dSRichard Lowe 	Running		rp;
778*10d63b7dSRichard Lowe 	Running		*rp_prev;
779*10d63b7dSRichard Lowe 	Property	line;
780*10d63b7dSRichard Lowe 	Chain		target_group;
781*10d63b7dSRichard Lowe 	Dependency	dep;
782*10d63b7dSRichard Lowe 	Boolean		quiescent = true;
783*10d63b7dSRichard Lowe 	Running		*subtree_target;
784*10d63b7dSRichard Lowe 	Boolean		saved_commands_done;
785*10d63b7dSRichard Lowe 	Property	*conditionals;
786*10d63b7dSRichard Lowe 
787*10d63b7dSRichard Lowe 	subtree_target = NULL;
788*10d63b7dSRichard Lowe 	subtree_conflict = NULL;
789*10d63b7dSRichard Lowe 	subtree_conflict2 = NULL;
790*10d63b7dSRichard Lowe 	/*
791*10d63b7dSRichard Lowe 	 * If nothing currently running, build a serial target, if any.
792*10d63b7dSRichard Lowe 	 */
793*10d63b7dSRichard Lowe start_loop_1:
794*10d63b7dSRichard Lowe 	for (rp_prev = &running_list, rp = running_list;
795*10d63b7dSRichard Lowe 	     rp != NULL && parallel_process_cnt == 0;
796*10d63b7dSRichard Lowe 	     rp = rp->next) {
797*10d63b7dSRichard Lowe 		if (rp->state == build_serial) {
798*10d63b7dSRichard Lowe 			*rp_prev = rp->next;
799*10d63b7dSRichard Lowe 			if (rp->next == NULL) {
800*10d63b7dSRichard Lowe 				running_tail = rp_prev;
801*10d63b7dSRichard Lowe 			}
802*10d63b7dSRichard Lowe 			recursion_level = rp->recursion_level;
803*10d63b7dSRichard Lowe 			rp->target->state = build_pending;
804*10d63b7dSRichard Lowe 			(void) doname_check(rp->target,
805*10d63b7dSRichard Lowe 					    rp->do_get,
806*10d63b7dSRichard Lowe 					    rp->implicit,
807*10d63b7dSRichard Lowe 					    false);
808*10d63b7dSRichard Lowe 			quiescent = false;
809*10d63b7dSRichard Lowe 			delete_running_struct(rp);
810*10d63b7dSRichard Lowe 			goto start_loop_1;
811*10d63b7dSRichard Lowe 		} else {
812*10d63b7dSRichard Lowe 			rp_prev = &rp->next;
813*10d63b7dSRichard Lowe 		}
814*10d63b7dSRichard Lowe 	}
815*10d63b7dSRichard Lowe 	/*
816*10d63b7dSRichard Lowe 	 * Find a target to build.  The target must be pending, have all
817*10d63b7dSRichard Lowe 	 * its dependencies built, and not be in a target group with a target
818*10d63b7dSRichard Lowe 	 * currently building.
819*10d63b7dSRichard Lowe 	 */
820*10d63b7dSRichard Lowe start_loop_2:
821*10d63b7dSRichard Lowe 	for (rp_prev = &running_list, rp = running_list;
822*10d63b7dSRichard Lowe 	     rp != NULL;
823*10d63b7dSRichard Lowe 	     rp = rp->next) {
824*10d63b7dSRichard Lowe 		if (!(rp->state == build_pending ||
825*10d63b7dSRichard Lowe 		      rp->state == build_subtree)) {
826*10d63b7dSRichard Lowe 			quiescent = false;
827*10d63b7dSRichard Lowe 			rp_prev = &rp->next;
828*10d63b7dSRichard Lowe 		} else if (rp->state == build_pending) {
829*10d63b7dSRichard Lowe 			line = get_prop(rp->target->prop, line_prop);
830*10d63b7dSRichard Lowe 			for (dep = line->body.line.dependencies;
831*10d63b7dSRichard Lowe 			     dep != NULL;
832*10d63b7dSRichard Lowe 			     dep = dep->next) {
833*10d63b7dSRichard Lowe 				if (dep->name->state == build_running ||
834*10d63b7dSRichard Lowe 				    dep->name->state == build_pending ||
835*10d63b7dSRichard Lowe 				    dep->name->state == build_serial) {
836*10d63b7dSRichard Lowe 					break;
837*10d63b7dSRichard Lowe 				}
838*10d63b7dSRichard Lowe 			}
839*10d63b7dSRichard Lowe 			if (dep == NULL) {
840*10d63b7dSRichard Lowe 				for (target_group = line->body.line.target_group;
841*10d63b7dSRichard Lowe 				     target_group != NULL;
842*10d63b7dSRichard Lowe 				     target_group = target_group->next) {
843*10d63b7dSRichard Lowe 					if (is_running(target_group->name)) {
844*10d63b7dSRichard Lowe 						break;
845*10d63b7dSRichard Lowe 					}
846*10d63b7dSRichard Lowe 				}
847*10d63b7dSRichard Lowe 				if (target_group == NULL) {
848*10d63b7dSRichard Lowe 					*rp_prev = rp->next;
849*10d63b7dSRichard Lowe 					if (rp->next == NULL) {
850*10d63b7dSRichard Lowe 						running_tail = rp_prev;
851*10d63b7dSRichard Lowe 					}
852*10d63b7dSRichard Lowe 					recursion_level = rp->recursion_level;
853*10d63b7dSRichard Lowe 					rp->target->state = rp->redo ?
854*10d63b7dSRichard Lowe 					  build_dont_know : build_pending;
855*10d63b7dSRichard Lowe 					saved_commands_done = commands_done;
856*10d63b7dSRichard Lowe 					conditionals =
857*10d63b7dSRichard Lowe 						set_conditionals
858*10d63b7dSRichard Lowe 						    (rp->conditional_cnt,
859*10d63b7dSRichard Lowe 						     rp->conditional_targets);
860*10d63b7dSRichard Lowe 					rp->target->dont_activate_cond_values = true;
861*10d63b7dSRichard Lowe 					if ((doname_check(rp->target,
862*10d63b7dSRichard Lowe 							  rp->do_get,
863*10d63b7dSRichard Lowe 							  rp->implicit,
864*10d63b7dSRichard Lowe 							  rp->target->has_target_prop ? true : false) !=
865*10d63b7dSRichard Lowe 					     build_running) &&
866*10d63b7dSRichard Lowe 					    !commands_done) {
867*10d63b7dSRichard Lowe 						commands_done =
868*10d63b7dSRichard Lowe 						  saved_commands_done;
869*10d63b7dSRichard Lowe 					}
870*10d63b7dSRichard Lowe 					rp->target->dont_activate_cond_values = false;
871*10d63b7dSRichard Lowe 					reset_conditionals
872*10d63b7dSRichard Lowe 						(rp->conditional_cnt,
873*10d63b7dSRichard Lowe 						 rp->conditional_targets,
874*10d63b7dSRichard Lowe 						 conditionals);
875*10d63b7dSRichard Lowe 					quiescent = false;
876*10d63b7dSRichard Lowe 					delete_running_struct(rp);
877*10d63b7dSRichard Lowe 					goto start_loop_2;
878*10d63b7dSRichard Lowe 				} else {
879*10d63b7dSRichard Lowe 					rp_prev = &rp->next;
880*10d63b7dSRichard Lowe 				}
881*10d63b7dSRichard Lowe 			} else {
882*10d63b7dSRichard Lowe 				rp_prev = &rp->next;
883*10d63b7dSRichard Lowe 			}
884*10d63b7dSRichard Lowe 		} else {
885*10d63b7dSRichard Lowe 			rp_prev = &rp->next;
886*10d63b7dSRichard Lowe 		}
887*10d63b7dSRichard Lowe 	}
888*10d63b7dSRichard Lowe 	/*
889*10d63b7dSRichard Lowe 	 * If nothing has been found to build and there exists a subtree
890*10d63b7dSRichard Lowe 	 * target with no dependency conflicts, build it.
891*10d63b7dSRichard Lowe 	 */
892*10d63b7dSRichard Lowe 	if (quiescent) {
893*10d63b7dSRichard Lowe start_loop_3:
894*10d63b7dSRichard Lowe 		for (rp_prev = &running_list, rp = running_list;
895*10d63b7dSRichard Lowe 		     rp != NULL;
896*10d63b7dSRichard Lowe 		     rp = rp->next) {
897*10d63b7dSRichard Lowe 			if (rp->state == build_subtree) {
898*10d63b7dSRichard Lowe 				if (!dependency_conflict(rp->target)) {
899*10d63b7dSRichard Lowe 					*rp_prev = rp->next;
900*10d63b7dSRichard Lowe 					if (rp->next == NULL) {
901*10d63b7dSRichard Lowe 						running_tail = rp_prev;
902*10d63b7dSRichard Lowe 					}
903*10d63b7dSRichard Lowe 					recursion_level = rp->recursion_level;
904*10d63b7dSRichard Lowe 					doname_subtree(rp->target,
905*10d63b7dSRichard Lowe 						       rp->do_get,
906*10d63b7dSRichard Lowe 						       rp->implicit);
907*10d63b7dSRichard Lowe 					quiescent = false;
908*10d63b7dSRichard Lowe 					delete_running_struct(rp);
909*10d63b7dSRichard Lowe 					goto start_loop_3;
910*10d63b7dSRichard Lowe 				} else {
911*10d63b7dSRichard Lowe 					subtree_target = rp_prev;
912*10d63b7dSRichard Lowe 					rp_prev = &rp->next;
913*10d63b7dSRichard Lowe 				}
914*10d63b7dSRichard Lowe 			} else {
915*10d63b7dSRichard Lowe 				rp_prev = &rp->next;
916*10d63b7dSRichard Lowe 			}
917*10d63b7dSRichard Lowe 		}
918*10d63b7dSRichard Lowe 	}
919*10d63b7dSRichard Lowe 	/*
920*10d63b7dSRichard Lowe 	 * If still nothing found to build, we either have a deadlock
921*10d63b7dSRichard Lowe 	 * or a subtree with a dependency conflict with something waiting
922*10d63b7dSRichard Lowe 	 * to build.
923*10d63b7dSRichard Lowe 	 */
924*10d63b7dSRichard Lowe 	if (quiescent) {
925*10d63b7dSRichard Lowe 		if (subtree_target == NULL) {
926*10d63b7dSRichard Lowe 			fatal(gettext("Internal error: deadlock detected in process_next"));
927*10d63b7dSRichard Lowe 		} else {
928*10d63b7dSRichard Lowe 			rp = *subtree_target;
929*10d63b7dSRichard Lowe 			if (debug_level > 0) {
930*10d63b7dSRichard Lowe 				warning(gettext("Conditional macro conflict encountered for %s between %s and %s"),
931*10d63b7dSRichard Lowe 					subtree_conflict2->string_mb,
932*10d63b7dSRichard Lowe 					rp->target->string_mb,
933*10d63b7dSRichard Lowe 					subtree_conflict->string_mb);
934*10d63b7dSRichard Lowe 			}
935*10d63b7dSRichard Lowe 			*subtree_target = (*subtree_target)->next;
936*10d63b7dSRichard Lowe 			if (rp->next == NULL) {
937*10d63b7dSRichard Lowe 				running_tail = subtree_target;
938*10d63b7dSRichard Lowe 			}
939*10d63b7dSRichard Lowe 			recursion_level = rp->recursion_level;
940*10d63b7dSRichard Lowe 			doname_subtree(rp->target, rp->do_get, rp->implicit);
941*10d63b7dSRichard Lowe 			delete_running_struct(rp);
942*10d63b7dSRichard Lowe 		}
943*10d63b7dSRichard Lowe 	}
944*10d63b7dSRichard Lowe }
945*10d63b7dSRichard Lowe 
946*10d63b7dSRichard Lowe /*
947*10d63b7dSRichard Lowe  *	set_conditionals(cnt, targets)
948*10d63b7dSRichard Lowe  *
949*10d63b7dSRichard Lowe  *	Sets the conditional macros for the targets given in the array of
950*10d63b7dSRichard Lowe  *	targets.  The old macro values are returned in an array of
951*10d63b7dSRichard Lowe  *	Properties for later resetting.
952*10d63b7dSRichard Lowe  *
953*10d63b7dSRichard Lowe  *	Return value:
954*10d63b7dSRichard Lowe  *					Array of conditional macro settings
955*10d63b7dSRichard Lowe  *
956*10d63b7dSRichard Lowe  *	Parameters:
957*10d63b7dSRichard Lowe  *		cnt			Number of targets
958*10d63b7dSRichard Lowe  *		targets			Array of targets
959*10d63b7dSRichard Lowe  */
960*10d63b7dSRichard Lowe static Property *
961*10d63b7dSRichard Lowe set_conditionals(int cnt, Name *targets)
962*10d63b7dSRichard Lowe {
963*10d63b7dSRichard Lowe 	Property	*locals, *lp;
964*10d63b7dSRichard Lowe 	Name		*tp;
965*10d63b7dSRichard Lowe 
966*10d63b7dSRichard Lowe 	locals = (Property *) getmem(cnt * sizeof(Property));
967*10d63b7dSRichard Lowe 	for (lp = locals, tp = targets;
968*10d63b7dSRichard Lowe 	     cnt > 0;
969*10d63b7dSRichard Lowe 	     cnt--, lp++, tp++) {
970*10d63b7dSRichard Lowe 		*lp = (Property) getmem((*tp)->conditional_cnt *
971*10d63b7dSRichard Lowe 					sizeof(struct _Property));
972*10d63b7dSRichard Lowe 		set_locals(*tp, *lp);
973*10d63b7dSRichard Lowe 	}
974*10d63b7dSRichard Lowe 	return locals;
975*10d63b7dSRichard Lowe }
976*10d63b7dSRichard Lowe 
977*10d63b7dSRichard Lowe /*
978*10d63b7dSRichard Lowe  *	reset_conditionals(cnt, targets, locals)
979*10d63b7dSRichard Lowe  *
980*10d63b7dSRichard Lowe  *	Resets the conditional macros as saved in the given array of
981*10d63b7dSRichard Lowe  *	Properties.  The resets are done in reverse order.  Afterwards the
982*10d63b7dSRichard Lowe  *	data structures are freed.
983*10d63b7dSRichard Lowe  *
984*10d63b7dSRichard Lowe  *	Parameters:
985*10d63b7dSRichard Lowe  *		cnt			Number of targets
986*10d63b7dSRichard Lowe  *		targets			Array of targets
987*10d63b7dSRichard Lowe  *		locals			Array of dependency macro settings
988*10d63b7dSRichard Lowe  */
989*10d63b7dSRichard Lowe static void
990*10d63b7dSRichard Lowe reset_conditionals(int cnt, Name *targets, Property *locals)
991*10d63b7dSRichard Lowe {
992*10d63b7dSRichard Lowe 	Name		*tp;
993*10d63b7dSRichard Lowe 	Property	*lp;
994*10d63b7dSRichard Lowe 
995*10d63b7dSRichard Lowe 	for (tp = targets + (cnt - 1), lp = locals + (cnt - 1);
996*10d63b7dSRichard Lowe 	     cnt > 0;
997*10d63b7dSRichard Lowe 	     cnt--, tp--, lp--) {
998*10d63b7dSRichard Lowe 		reset_locals(*tp,
999*10d63b7dSRichard Lowe 			     *lp,
1000*10d63b7dSRichard Lowe 			     get_prop((*tp)->prop, conditional_prop),
1001*10d63b7dSRichard Lowe 			     0);
1002*10d63b7dSRichard Lowe 		retmem_mb((caddr_t) *lp);
1003*10d63b7dSRichard Lowe 	}
1004*10d63b7dSRichard Lowe 	retmem_mb((caddr_t) locals);
1005*10d63b7dSRichard Lowe }
1006*10d63b7dSRichard Lowe 
1007*10d63b7dSRichard Lowe /*
1008*10d63b7dSRichard Lowe  *	dependency_conflict(target)
1009*10d63b7dSRichard Lowe  *
1010*10d63b7dSRichard Lowe  *	Returns true if there is an intersection between
1011*10d63b7dSRichard Lowe  *	the subtree of the target and any dependents of the pending targets.
1012*10d63b7dSRichard Lowe  *
1013*10d63b7dSRichard Lowe  *	Return value:
1014*10d63b7dSRichard Lowe  *					True if conflict found
1015*10d63b7dSRichard Lowe  *
1016*10d63b7dSRichard Lowe  *	Parameters:
1017*10d63b7dSRichard Lowe  *		target			Subtree target to check
1018*10d63b7dSRichard Lowe  *
1019*10d63b7dSRichard Lowe  *	Static variables used:
1020*10d63b7dSRichard Lowe  *		subtree_conflict	Target conflict found
1021*10d63b7dSRichard Lowe  *		subtree_conflict2	Second conflict found
1022*10d63b7dSRichard Lowe  *
1023*10d63b7dSRichard Lowe  *	Global variables used:
1024*10d63b7dSRichard Lowe  *		running_list		List of running processes
1025*10d63b7dSRichard Lowe  *		wait_name		.WAIT, not a real dependency
1026*10d63b7dSRichard Lowe  */
1027*10d63b7dSRichard Lowe static Boolean
1028*10d63b7dSRichard Lowe dependency_conflict(Name target)
1029*10d63b7dSRichard Lowe {
1030*10d63b7dSRichard Lowe 	Property	line;
1031*10d63b7dSRichard Lowe 	Property	pending_line;
1032*10d63b7dSRichard Lowe 	Dependency	dp;
1033*10d63b7dSRichard Lowe 	Dependency	pending_dp;
1034*10d63b7dSRichard Lowe 	Running		rp;
1035*10d63b7dSRichard Lowe 
1036*10d63b7dSRichard Lowe 	/* Return if we are already checking this target */
1037*10d63b7dSRichard Lowe 	if (target->checking_subtree) {
1038*10d63b7dSRichard Lowe 		return false;
1039*10d63b7dSRichard Lowe 	}
1040*10d63b7dSRichard Lowe 	target->checking_subtree = true;
1041*10d63b7dSRichard Lowe 	line = get_prop(target->prop, line_prop);
1042*10d63b7dSRichard Lowe 	if (line == NULL) {
1043*10d63b7dSRichard Lowe 		target->checking_subtree = false;
1044*10d63b7dSRichard Lowe 		return false;
1045*10d63b7dSRichard Lowe 	}
1046*10d63b7dSRichard Lowe 	/* Check each dependency of the target for conflicts */
1047*10d63b7dSRichard Lowe 	for (dp = line->body.line.dependencies; dp != NULL; dp = dp->next) {
1048*10d63b7dSRichard Lowe 		/* Ignore .WAIT dependency */
1049*10d63b7dSRichard Lowe 		if (dp->name == wait_name) {
1050*10d63b7dSRichard Lowe 			continue;
1051*10d63b7dSRichard Lowe 		}
1052*10d63b7dSRichard Lowe 		/*
1053*10d63b7dSRichard Lowe 		 * For each pending target, look for a dependency which
1054*10d63b7dSRichard Lowe 		 * is the same as a dependency of the subtree target.  Since
1055*10d63b7dSRichard Lowe 		 * we can't build the subtree until all pending targets have
1056*10d63b7dSRichard Lowe 		 * finished which depend on the same dependency, this is
1057*10d63b7dSRichard Lowe 		 * a conflict.
1058*10d63b7dSRichard Lowe 		 */
1059*10d63b7dSRichard Lowe 		for (rp = running_list; rp != NULL; rp = rp->next) {
1060*10d63b7dSRichard Lowe 			if (rp->state == build_pending) {
1061*10d63b7dSRichard Lowe 				pending_line = get_prop(rp->target->prop,
1062*10d63b7dSRichard Lowe 							line_prop);
1063*10d63b7dSRichard Lowe 				if (pending_line == NULL) {
1064*10d63b7dSRichard Lowe 					continue;
1065*10d63b7dSRichard Lowe 				}
1066*10d63b7dSRichard Lowe 				for(pending_dp = pending_line->
1067*10d63b7dSRichard Lowe 				    			body.line.dependencies;
1068*10d63b7dSRichard Lowe 				    pending_dp != NULL;
1069*10d63b7dSRichard Lowe 				    pending_dp = pending_dp->next) {
1070*10d63b7dSRichard Lowe 					if (dp->name == pending_dp->name) {
1071*10d63b7dSRichard Lowe 						target->checking_subtree
1072*10d63b7dSRichard Lowe 						  		= false;
1073*10d63b7dSRichard Lowe 						subtree_conflict = rp->target;
1074*10d63b7dSRichard Lowe 						subtree_conflict2 = dp->name;
1075*10d63b7dSRichard Lowe 						return true;
1076*10d63b7dSRichard Lowe 					}
1077*10d63b7dSRichard Lowe 				}
1078*10d63b7dSRichard Lowe 			}
1079*10d63b7dSRichard Lowe 		}
1080*10d63b7dSRichard Lowe 		if (dependency_conflict(dp->name)) {
1081*10d63b7dSRichard Lowe 			target->checking_subtree = false;
1082*10d63b7dSRichard Lowe 			return true;
1083*10d63b7dSRichard Lowe 		}
1084*10d63b7dSRichard Lowe 	}
1085*10d63b7dSRichard Lowe 	target->checking_subtree = false;
1086*10d63b7dSRichard Lowe 	return false;
1087*10d63b7dSRichard Lowe }
1088*10d63b7dSRichard Lowe 
1089*10d63b7dSRichard Lowe /*
1090*10d63b7dSRichard Lowe  *	await_parallel(waitflg)
1091*10d63b7dSRichard Lowe  *
1092*10d63b7dSRichard Lowe  *	Waits for parallel children to exit and finishes their processing.
1093*10d63b7dSRichard Lowe  *	If waitflg is false, the function returns after update_delay.
1094*10d63b7dSRichard Lowe  *
1095*10d63b7dSRichard Lowe  *	Parameters:
1096*10d63b7dSRichard Lowe  *		waitflg		dwight
1097*10d63b7dSRichard Lowe  */
1098*10d63b7dSRichard Lowe void
1099*10d63b7dSRichard Lowe await_parallel(Boolean waitflg)
1100*10d63b7dSRichard Lowe {
1101*10d63b7dSRichard Lowe 	Boolean		nohang;
1102*10d63b7dSRichard Lowe 	pid_t		pid;
1103*10d63b7dSRichard Lowe 	int		status;
1104*10d63b7dSRichard Lowe 	Running		rp;
1105*10d63b7dSRichard Lowe 	int		waiterr;
1106*10d63b7dSRichard Lowe 
1107*10d63b7dSRichard Lowe 	nohang = false;
1108*10d63b7dSRichard Lowe 	for ( ; ; ) {
1109*10d63b7dSRichard Lowe 		if (!nohang) {
1110*10d63b7dSRichard Lowe 			(void) alarm((int) update_delay);
1111*10d63b7dSRichard Lowe 		}
1112*10d63b7dSRichard Lowe 		pid = waitpid((pid_t)-1,
1113*10d63b7dSRichard Lowe 			      &status,
1114*10d63b7dSRichard Lowe 			      nohang ? WNOHANG : 0);
1115*10d63b7dSRichard Lowe 		waiterr = errno;
1116*10d63b7dSRichard Lowe 		if (!nohang) {
1117*10d63b7dSRichard Lowe 			(void) alarm(0);
1118*10d63b7dSRichard Lowe 		}
1119*10d63b7dSRichard Lowe 		if (pid <= 0) {
1120*10d63b7dSRichard Lowe 			if (waiterr == EINTR) {
1121*10d63b7dSRichard Lowe 				if (waitflg) {
1122*10d63b7dSRichard Lowe 					continue;
1123*10d63b7dSRichard Lowe 				} else {
1124*10d63b7dSRichard Lowe 					return;
1125*10d63b7dSRichard Lowe 				}
1126*10d63b7dSRichard Lowe 			} else {
1127*10d63b7dSRichard Lowe 				return;
1128*10d63b7dSRichard Lowe 			}
1129*10d63b7dSRichard Lowe 		}
1130*10d63b7dSRichard Lowe 		for (rp = running_list;
1131*10d63b7dSRichard Lowe 		     (rp != NULL) && (rp->pid != pid);
1132*10d63b7dSRichard Lowe 		     rp = rp->next) {
1133*10d63b7dSRichard Lowe 			;
1134*10d63b7dSRichard Lowe 		}
1135*10d63b7dSRichard Lowe 		if (rp == NULL) {
1136*10d63b7dSRichard Lowe 			fatal(gettext("Internal error: returned child pid not in running_list"));
1137*10d63b7dSRichard Lowe 		} else {
1138*10d63b7dSRichard Lowe 			rp->state = (WIFEXITED(status) && WEXITSTATUS(status) == 0) ? build_ok : build_failed;
1139*10d63b7dSRichard Lowe 		}
1140*10d63b7dSRichard Lowe 		nohang = true;
1141*10d63b7dSRichard Lowe 		parallel_process_cnt--;
1142*10d63b7dSRichard Lowe 
1143*10d63b7dSRichard Lowe 		if (job_adjust_mode == ADJUST_M2) {
1144*10d63b7dSRichard Lowe 			if (m2_release_job()) {
1145*10d63b7dSRichard Lowe 				job_adjust_error();
1146*10d63b7dSRichard Lowe 			}
1147*10d63b7dSRichard Lowe 		}
1148*10d63b7dSRichard Lowe 	}
1149*10d63b7dSRichard Lowe }
1150*10d63b7dSRichard Lowe 
1151*10d63b7dSRichard Lowe /*
1152*10d63b7dSRichard Lowe  *	finish_children(docheck)
1153*10d63b7dSRichard Lowe  *
1154*10d63b7dSRichard Lowe  *	Finishes the processing for all targets which were running
1155*10d63b7dSRichard Lowe  *	and have now completed.
1156*10d63b7dSRichard Lowe  *
1157*10d63b7dSRichard Lowe  *	Parameters:
1158*10d63b7dSRichard Lowe  *		docheck		Completely check the finished target
1159*10d63b7dSRichard Lowe  *
1160*10d63b7dSRichard Lowe  *	Static variables used:
1161*10d63b7dSRichard Lowe  *		running_tail	The tail of the running list
1162*10d63b7dSRichard Lowe  *
1163*10d63b7dSRichard Lowe  *	Global variables used:
1164*10d63b7dSRichard Lowe  *		continue_after_error  -k flag
1165*10d63b7dSRichard Lowe  *		fatal_in_progress  True if we are finishing up after fatal err
1166*10d63b7dSRichard Lowe  *		running_list	List of running processes
1167*10d63b7dSRichard Lowe  */
1168*10d63b7dSRichard Lowe void
1169*10d63b7dSRichard Lowe finish_children(Boolean docheck)
1170*10d63b7dSRichard Lowe {
1171*10d63b7dSRichard Lowe 	int		cmds_length;
1172*10d63b7dSRichard Lowe 	Property	line;
1173*10d63b7dSRichard Lowe 	Property	line2;
1174*10d63b7dSRichard Lowe 	struct stat	out_buf;
1175*10d63b7dSRichard Lowe 	Running		rp;
1176*10d63b7dSRichard Lowe 	Running		*rp_prev;
1177*10d63b7dSRichard Lowe 	Cmd_line	rule;
1178*10d63b7dSRichard Lowe 	Boolean		silent_flag;
1179*10d63b7dSRichard Lowe 
1180*10d63b7dSRichard Lowe 	for (rp_prev = &running_list, rp = running_list;
1181*10d63b7dSRichard Lowe 	     rp != NULL;
1182*10d63b7dSRichard Lowe 	     rp = rp->next) {
1183*10d63b7dSRichard Lowe bypass_for_loop_inc_4:
1184*10d63b7dSRichard Lowe 		/*
1185*10d63b7dSRichard Lowe 		 * If the state is ok or failed, then this target has
1186*10d63b7dSRichard Lowe 		 * finished building.
1187*10d63b7dSRichard Lowe 		 * In parallel_mode, output the accumulated stdout/stderr.
1188*10d63b7dSRichard Lowe 		 * Read the auto dependency stuff, handle a failed build,
1189*10d63b7dSRichard Lowe 		 * update the target, then finish the doname process for
1190*10d63b7dSRichard Lowe 		 * that target.
1191*10d63b7dSRichard Lowe 		 */
1192*10d63b7dSRichard Lowe 		if (rp->state == build_ok || rp->state == build_failed) {
1193*10d63b7dSRichard Lowe 			*rp_prev = rp->next;
1194*10d63b7dSRichard Lowe 			if (rp->next == NULL) {
1195*10d63b7dSRichard Lowe 				running_tail = rp_prev;
1196*10d63b7dSRichard Lowe 			}
1197*10d63b7dSRichard Lowe 			if ((line2 = rp->command) == NULL) {
1198*10d63b7dSRichard Lowe 				line2 = get_prop(rp->target->prop, line_prop);
1199*10d63b7dSRichard Lowe 			}
1200*10d63b7dSRichard Lowe 
1201*10d63b7dSRichard Lowe 
1202*10d63b7dSRichard Lowe 			/*
1203*10d63b7dSRichard Lowe 			 * Check if there were any job output
1204*10d63b7dSRichard Lowe 			 * from the parallel build.
1205*10d63b7dSRichard Lowe 			 */
1206*10d63b7dSRichard Lowe 			if (rp->stdout_file != NULL) {
1207*10d63b7dSRichard Lowe 				if (stat(rp->stdout_file, &out_buf) < 0) {
1208*10d63b7dSRichard Lowe 					fatal(gettext("stat of %s failed: %s"),
1209*10d63b7dSRichard Lowe 					    rp->stdout_file,
1210*10d63b7dSRichard Lowe 					    errmsg(errno));
1211*10d63b7dSRichard Lowe 				}
1212*10d63b7dSRichard Lowe 
1213*10d63b7dSRichard Lowe 				if ((line2 != NULL) &&
1214*10d63b7dSRichard Lowe 				    (out_buf.st_size > 0)) {
1215*10d63b7dSRichard Lowe 					cmds_length = 0;
1216*10d63b7dSRichard Lowe 					for (rule = line2->body.line.command_used,
1217*10d63b7dSRichard Lowe 						 silent_flag = silent;
1218*10d63b7dSRichard Lowe 					     rule != NULL;
1219*10d63b7dSRichard Lowe 					     rule = rule->next) {
1220*10d63b7dSRichard Lowe 						cmds_length += rule->command_line->hash.length + 1;
1221*10d63b7dSRichard Lowe 						silent_flag = BOOLEAN(silent_flag || rule->silent);
1222*10d63b7dSRichard Lowe 					}
1223*10d63b7dSRichard Lowe 					if (out_buf.st_size != cmds_length || silent_flag ||
1224*10d63b7dSRichard Lowe 					    output_mode == txt2_mode) {
1225*10d63b7dSRichard Lowe 						dump_out_file(rp->stdout_file, false);
1226*10d63b7dSRichard Lowe 					}
1227*10d63b7dSRichard Lowe 				}
1228*10d63b7dSRichard Lowe 				(void) unlink(rp->stdout_file);
1229*10d63b7dSRichard Lowe 				retmem_mb(rp->stdout_file);
1230*10d63b7dSRichard Lowe 				rp->stdout_file = NULL;
1231*10d63b7dSRichard Lowe 			}
1232*10d63b7dSRichard Lowe 
1233*10d63b7dSRichard Lowe 			if (!out_err_same && (rp->stderr_file != NULL)) {
1234*10d63b7dSRichard Lowe 				if (stat(rp->stderr_file, &out_buf) < 0) {
1235*10d63b7dSRichard Lowe 					fatal(gettext("stat of %s failed: %s"),
1236*10d63b7dSRichard Lowe 					    rp->stderr_file,
1237*10d63b7dSRichard Lowe 					    errmsg(errno));
1238*10d63b7dSRichard Lowe 				}
1239*10d63b7dSRichard Lowe 				if ((line2 != NULL) &&
1240*10d63b7dSRichard Lowe 				    (out_buf.st_size > 0)) {
1241*10d63b7dSRichard Lowe 					dump_out_file(rp->stderr_file, true);
1242*10d63b7dSRichard Lowe 				}
1243*10d63b7dSRichard Lowe 				(void) unlink(rp->stderr_file);
1244*10d63b7dSRichard Lowe 				retmem_mb(rp->stderr_file);
1245*10d63b7dSRichard Lowe 				rp->stderr_file = NULL;
1246*10d63b7dSRichard Lowe 			}
1247*10d63b7dSRichard Lowe 
1248*10d63b7dSRichard Lowe 			check_state(rp->temp_file);
1249*10d63b7dSRichard Lowe 			if (rp->temp_file != NULL) {
1250*10d63b7dSRichard Lowe 				free_name(rp->temp_file);
1251*10d63b7dSRichard Lowe 			}
1252*10d63b7dSRichard Lowe 			rp->temp_file = NULL;
1253*10d63b7dSRichard Lowe 			if (rp->state == build_failed) {
1254*10d63b7dSRichard Lowe 				line = get_prop(rp->target->prop, line_prop);
1255*10d63b7dSRichard Lowe 				if (line != NULL) {
1256*10d63b7dSRichard Lowe 					line->body.line.command_used = NULL;
1257*10d63b7dSRichard Lowe 				}
1258*10d63b7dSRichard Lowe 				if (continue_after_error ||
1259*10d63b7dSRichard Lowe 				    fatal_in_progress ||
1260*10d63b7dSRichard Lowe 				    !docheck) {
1261*10d63b7dSRichard Lowe 					warning(gettext("Command failed for target `%s'"),
1262*10d63b7dSRichard Lowe 						rp->command ? line2->body.line.target->string_mb : rp->target->string_mb);
1263*10d63b7dSRichard Lowe 					build_failed_seen = true;
1264*10d63b7dSRichard Lowe 				} else {
1265*10d63b7dSRichard Lowe 					/*
1266*10d63b7dSRichard Lowe 					 * XXX??? - DMake needs to exit(),
1267*10d63b7dSRichard Lowe 					 * but shouldn't call fatal().
1268*10d63b7dSRichard Lowe 					 */
1269*10d63b7dSRichard Lowe #ifdef PRINT_EXIT_STATUS
1270*10d63b7dSRichard Lowe 					warning("I'm in finish_children. rp->state == build_failed.");
1271*10d63b7dSRichard Lowe #endif
1272*10d63b7dSRichard Lowe 
1273*10d63b7dSRichard Lowe 					fatal(gettext("Command failed for target `%s'"),
1274*10d63b7dSRichard Lowe 						rp->command ? line2->body.line.target->string_mb : rp->target->string_mb);
1275*10d63b7dSRichard Lowe 				}
1276*10d63b7dSRichard Lowe 			}
1277*10d63b7dSRichard Lowe 			if (!docheck) {
1278*10d63b7dSRichard Lowe 				delete_running_struct(rp);
1279*10d63b7dSRichard Lowe 				rp = *rp_prev;
1280*10d63b7dSRichard Lowe 				if (rp == NULL) {
1281*10d63b7dSRichard Lowe 					break;
1282*10d63b7dSRichard Lowe 				} else {
1283*10d63b7dSRichard Lowe 					goto bypass_for_loop_inc_4;
1284*10d63b7dSRichard Lowe 				}
1285*10d63b7dSRichard Lowe 			}
1286*10d63b7dSRichard Lowe 			update_target(get_prop(rp->target->prop, line_prop),
1287*10d63b7dSRichard Lowe 				      rp->state);
1288*10d63b7dSRichard Lowe 			finish_doname(rp);
1289*10d63b7dSRichard Lowe 			delete_running_struct(rp);
1290*10d63b7dSRichard Lowe 			rp = *rp_prev;
1291*10d63b7dSRichard Lowe 			if (rp == NULL) {
1292*10d63b7dSRichard Lowe 				break;
1293*10d63b7dSRichard Lowe 			} else {
1294*10d63b7dSRichard Lowe 				goto bypass_for_loop_inc_4;
1295*10d63b7dSRichard Lowe 			}
1296*10d63b7dSRichard Lowe 		} else {
1297*10d63b7dSRichard Lowe 			rp_prev = &rp->next;
1298*10d63b7dSRichard Lowe 		}
1299*10d63b7dSRichard Lowe 	}
1300*10d63b7dSRichard Lowe }
1301*10d63b7dSRichard Lowe 
1302*10d63b7dSRichard Lowe /*
1303*10d63b7dSRichard Lowe  *	dump_out_file(filename, err)
1304*10d63b7dSRichard Lowe  *
1305*10d63b7dSRichard Lowe  *	Write the contents of the file to stdout, then unlink the file.
1306*10d63b7dSRichard Lowe  *
1307*10d63b7dSRichard Lowe  *	Parameters:
1308*10d63b7dSRichard Lowe  *		filename	Name of temp file containing output
1309*10d63b7dSRichard Lowe  *
1310*10d63b7dSRichard Lowe  *	Global variables used:
1311*10d63b7dSRichard Lowe  */
1312*10d63b7dSRichard Lowe static void
1313*10d63b7dSRichard Lowe dump_out_file(char *filename, Boolean err)
1314*10d63b7dSRichard Lowe {
1315*10d63b7dSRichard Lowe 	int		chars_read;
1316*10d63b7dSRichard Lowe 	char		copybuf[BUFSIZ];
1317*10d63b7dSRichard Lowe 	int		fd;
1318*10d63b7dSRichard Lowe 	int		out_fd = (err ? 2 : 1);
1319*10d63b7dSRichard Lowe 
1320*10d63b7dSRichard Lowe 	if ((fd = open(filename, O_RDONLY)) < 0) {
1321*10d63b7dSRichard Lowe 		fatal(gettext("open failed for output file %s: %s"),
1322*10d63b7dSRichard Lowe 		      filename,
1323*10d63b7dSRichard Lowe 		      errmsg(errno));
1324*10d63b7dSRichard Lowe 	}
1325*10d63b7dSRichard Lowe 	if (!silent && output_mode != txt2_mode) {
1326*10d63b7dSRichard Lowe 		(void) fprintf(err ? stderr : stdout,
1327*10d63b7dSRichard Lowe 		               err ?
1328*10d63b7dSRichard Lowe 				gettext("%s --> Job errors\n") :
1329*10d63b7dSRichard Lowe 				gettext("%s --> Job output\n"),
1330*10d63b7dSRichard Lowe 		               local_host);
1331*10d63b7dSRichard Lowe 		(void) fflush(err ? stderr : stdout);
1332*10d63b7dSRichard Lowe 	}
1333*10d63b7dSRichard Lowe 	for (chars_read = read(fd, copybuf, BUFSIZ);
1334*10d63b7dSRichard Lowe 	     chars_read > 0;
1335*10d63b7dSRichard Lowe 	     chars_read = read(fd, copybuf, BUFSIZ)) {
1336*10d63b7dSRichard Lowe 		/*
1337*10d63b7dSRichard Lowe 		 * Read buffers from the source file until end or error.
1338*10d63b7dSRichard Lowe 		 */
1339*10d63b7dSRichard Lowe 		if (write(out_fd, copybuf, chars_read) < 0) {
1340*10d63b7dSRichard Lowe 			fatal(gettext("write failed for output file %s: %s"),
1341*10d63b7dSRichard Lowe 			      filename,
1342*10d63b7dSRichard Lowe 			      errmsg(errno));
1343*10d63b7dSRichard Lowe 		}
1344*10d63b7dSRichard Lowe 	}
1345*10d63b7dSRichard Lowe 	(void) close(fd);
1346*10d63b7dSRichard Lowe 	(void) unlink(filename);
1347*10d63b7dSRichard Lowe }
1348*10d63b7dSRichard Lowe 
1349*10d63b7dSRichard Lowe /*
1350*10d63b7dSRichard Lowe  *	finish_doname(rp)
1351*10d63b7dSRichard Lowe  *
1352*10d63b7dSRichard Lowe  *	Completes the processing for a target which was left running.
1353*10d63b7dSRichard Lowe  *
1354*10d63b7dSRichard Lowe  *	Parameters:
1355*10d63b7dSRichard Lowe  *		rp		Running list entry for target
1356*10d63b7dSRichard Lowe  *
1357*10d63b7dSRichard Lowe  *	Global variables used:
1358*10d63b7dSRichard Lowe  *		debug_level	Debug flag
1359*10d63b7dSRichard Lowe  *		recursion_level	Indentation for debug output
1360*10d63b7dSRichard Lowe  */
1361*10d63b7dSRichard Lowe static void
1362*10d63b7dSRichard Lowe finish_doname(Running rp)
1363*10d63b7dSRichard Lowe {
1364*10d63b7dSRichard Lowe 	int		auto_count = rp->auto_count;
1365*10d63b7dSRichard Lowe 	Name		*automatics = rp->automatics;
1366*10d63b7dSRichard Lowe 	Doname		result = rp->state;
1367*10d63b7dSRichard Lowe 	Name		target = rp->target;
1368*10d63b7dSRichard Lowe 	Name		true_target = rp->true_target;
1369*10d63b7dSRichard Lowe 	Property	*conditionals;
1370*10d63b7dSRichard Lowe 
1371*10d63b7dSRichard Lowe 	recursion_level = rp->recursion_level;
1372*10d63b7dSRichard Lowe 	if (result == build_ok) {
1373*10d63b7dSRichard Lowe 		if (true_target == NULL) {
1374*10d63b7dSRichard Lowe 			(void) printf("Target = %s\n", target->string_mb);
1375*10d63b7dSRichard Lowe 			(void) printf(" State = %d\n", result);
1376*10d63b7dSRichard Lowe 			fatal("Internal error: NULL true_target in finish_doname");
1377*10d63b7dSRichard Lowe 		}
1378*10d63b7dSRichard Lowe 		/* If all went OK, set a nice timestamp */
1379*10d63b7dSRichard Lowe 		if (true_target->stat.time == file_doesnt_exist) {
1380*10d63b7dSRichard Lowe 			true_target->stat.time = file_max_time;
1381*10d63b7dSRichard Lowe 		}
1382*10d63b7dSRichard Lowe 	}
1383*10d63b7dSRichard Lowe 	target->state = result;
1384*10d63b7dSRichard Lowe 	if (target->is_member) {
1385*10d63b7dSRichard Lowe 		Property member;
1386*10d63b7dSRichard Lowe 
1387*10d63b7dSRichard Lowe 		/* Propagate the timestamp from the member file to the member */
1388*10d63b7dSRichard Lowe 		if ((target->stat.time != file_max_time) &&
1389*10d63b7dSRichard Lowe 		    ((member = get_prop(target->prop, member_prop)) != NULL) &&
1390*10d63b7dSRichard Lowe 		    (exists(member->body.member.member) > file_doesnt_exist)) {
1391*10d63b7dSRichard Lowe 			target->stat.time =
1392*10d63b7dSRichard Lowe /*
1393*10d63b7dSRichard Lowe 			  exists(member->body.member.member);
1394*10d63b7dSRichard Lowe  */
1395*10d63b7dSRichard Lowe 			  member->body.member.member->stat.time;
1396*10d63b7dSRichard Lowe 		}
1397*10d63b7dSRichard Lowe 	}
1398*10d63b7dSRichard Lowe 	/*
1399*10d63b7dSRichard Lowe 	 * Check if we found any new auto dependencies when we
1400*10d63b7dSRichard Lowe 	 * built the target.
1401*10d63b7dSRichard Lowe 	 */
1402*10d63b7dSRichard Lowe 	if ((result == build_ok) && check_auto_dependencies(target,
1403*10d63b7dSRichard Lowe 							    auto_count,
1404*10d63b7dSRichard Lowe 							    automatics)) {
1405*10d63b7dSRichard Lowe 		if (debug_level > 0) {
1406*10d63b7dSRichard Lowe 			(void) printf(gettext("%*sTarget `%s' acquired new dependencies from build, checking all dependencies\n"),
1407*10d63b7dSRichard Lowe 				      recursion_level,
1408*10d63b7dSRichard Lowe 				      "",
1409*10d63b7dSRichard Lowe 				      true_target->string_mb);
1410*10d63b7dSRichard Lowe 		}
1411*10d63b7dSRichard Lowe 		target->rechecking_target = true;
1412*10d63b7dSRichard Lowe 		target->state = build_running;
1413*10d63b7dSRichard Lowe 
1414*10d63b7dSRichard Lowe 		/* [tolik, Tue Mar 25 1997]
1415*10d63b7dSRichard Lowe 		 * Fix for bug 4038824:
1416*10d63b7dSRichard Lowe 		 *       command line options set by conditional macros get dropped
1417*10d63b7dSRichard Lowe 		 * rp->conditional_cnt and rp->conditional_targets must be copied
1418*10d63b7dSRichard Lowe 		 * to new 'rp' during add_pending(). Set_conditionals() stores
1419*10d63b7dSRichard Lowe 		 * rp->conditional_targets to the global variable 'conditional_targets'
1420*10d63b7dSRichard Lowe 		 * Add_pending() will use this variable to set up 'rp'.
1421*10d63b7dSRichard Lowe 		 */
1422*10d63b7dSRichard Lowe 		conditionals = set_conditionals(rp->conditional_cnt, rp->conditional_targets);
1423*10d63b7dSRichard Lowe 		add_pending(target,
1424*10d63b7dSRichard Lowe 			    recursion_level,
1425*10d63b7dSRichard Lowe 			    rp->do_get,
1426*10d63b7dSRichard Lowe 			    rp->implicit,
1427*10d63b7dSRichard Lowe 			    true);
1428*10d63b7dSRichard Lowe 		reset_conditionals(rp->conditional_cnt, rp->conditional_targets, conditionals);
1429*10d63b7dSRichard Lowe 	}
1430*10d63b7dSRichard Lowe }
1431*10d63b7dSRichard Lowe 
1432*10d63b7dSRichard Lowe /*
1433*10d63b7dSRichard Lowe  *	new_running_struct()
1434*10d63b7dSRichard Lowe  *
1435*10d63b7dSRichard Lowe  *	Constructor for Running struct. Creates a structure and initializes
1436*10d63b7dSRichard Lowe  *      its fields.
1437*10d63b7dSRichard Lowe  *
1438*10d63b7dSRichard Lowe  */
1439*10d63b7dSRichard Lowe static Running new_running_struct()
1440*10d63b7dSRichard Lowe {
1441*10d63b7dSRichard Lowe 	Running		rp;
1442*10d63b7dSRichard Lowe 
1443*10d63b7dSRichard Lowe 	rp = ALLOC(Running);
1444*10d63b7dSRichard Lowe 	rp->target = NULL;
1445*10d63b7dSRichard Lowe 	rp->true_target = NULL;
1446*10d63b7dSRichard Lowe 	rp->command = NULL;
1447*10d63b7dSRichard Lowe 	rp->sprodep_value = NULL;
1448*10d63b7dSRichard Lowe 	rp->sprodep_env = NULL;
1449*10d63b7dSRichard Lowe 	rp->auto_count = 0;
1450*10d63b7dSRichard Lowe 	rp->automatics = NULL;
1451*10d63b7dSRichard Lowe 	rp->pid = -1;
1452*10d63b7dSRichard Lowe 	rp->job_msg_id = -1;
1453*10d63b7dSRichard Lowe 	rp->stdout_file = NULL;
1454*10d63b7dSRichard Lowe 	rp->stderr_file = NULL;
1455*10d63b7dSRichard Lowe 	rp->temp_file = NULL;
1456*10d63b7dSRichard Lowe 	rp->next = NULL;
1457*10d63b7dSRichard Lowe 	return rp;
1458*10d63b7dSRichard Lowe }
1459*10d63b7dSRichard Lowe 
1460*10d63b7dSRichard Lowe /*
1461*10d63b7dSRichard Lowe  *	add_running(target, true_target, command, recursion_level, auto_count,
1462*10d63b7dSRichard Lowe  *					automatics, do_get, implicit)
1463*10d63b7dSRichard Lowe  *
1464*10d63b7dSRichard Lowe  *	Adds a record on the running list for this target, which
1465*10d63b7dSRichard Lowe  *	was just spawned and is running.
1466*10d63b7dSRichard Lowe  *
1467*10d63b7dSRichard Lowe  *	Parameters:
1468*10d63b7dSRichard Lowe  *		target		Target being built
1469*10d63b7dSRichard Lowe  *		true_target	True target for target
1470*10d63b7dSRichard Lowe  *		command		Running command.
1471*10d63b7dSRichard Lowe  *		recursion_level	Debug indentation level
1472*10d63b7dSRichard Lowe  *		auto_count	Count of automatic dependencies
1473*10d63b7dSRichard Lowe  *		automatics	List of automatic dependencies
1474*10d63b7dSRichard Lowe  *		do_get		Sccs get flag
1475*10d63b7dSRichard Lowe  *		implicit	Implicit flag
1476*10d63b7dSRichard Lowe  *
1477*10d63b7dSRichard Lowe  *	Static variables used:
1478*10d63b7dSRichard Lowe  *		running_tail	Tail of running list
1479*10d63b7dSRichard Lowe  *		process_running	PID of process
1480*10d63b7dSRichard Lowe  *
1481*10d63b7dSRichard Lowe  *	Global variables used:
1482*10d63b7dSRichard Lowe  *		current_line	Current line for target
1483*10d63b7dSRichard Lowe  *		current_target	Current target being built
1484*10d63b7dSRichard Lowe  *		stderr_file	Temporary file for stdout
1485*10d63b7dSRichard Lowe  *		stdout_file	Temporary file for stdout
1486*10d63b7dSRichard Lowe  *		temp_file_name	Temporary file for auto dependencies
1487*10d63b7dSRichard Lowe  */
1488*10d63b7dSRichard Lowe void
1489*10d63b7dSRichard Lowe add_running(Name target, Name true_target, Property command, int recursion_level, int auto_count, Name *automatics, Boolean do_get, Boolean implicit)
1490*10d63b7dSRichard Lowe {
1491*10d63b7dSRichard Lowe 	Running		rp;
1492*10d63b7dSRichard Lowe 	Name		*p;
1493*10d63b7dSRichard Lowe 
1494*10d63b7dSRichard Lowe 	rp = new_running_struct();
1495*10d63b7dSRichard Lowe 	rp->state = build_running;
1496*10d63b7dSRichard Lowe 	rp->target = target;
1497*10d63b7dSRichard Lowe 	rp->true_target = true_target;
1498*10d63b7dSRichard Lowe 	rp->command = command;
1499*10d63b7dSRichard Lowe 	rp->recursion_level = recursion_level;
1500*10d63b7dSRichard Lowe 	rp->do_get = do_get;
1501*10d63b7dSRichard Lowe 	rp->implicit = implicit;
1502*10d63b7dSRichard Lowe 	rp->auto_count = auto_count;
1503*10d63b7dSRichard Lowe 	if (auto_count > 0) {
1504*10d63b7dSRichard Lowe 		rp->automatics = (Name *) getmem(auto_count * sizeof (Name));
1505*10d63b7dSRichard Lowe 		for (p = rp->automatics; auto_count > 0; auto_count--) {
1506*10d63b7dSRichard Lowe 			*p++ = *automatics++;
1507*10d63b7dSRichard Lowe 		}
1508*10d63b7dSRichard Lowe 	} else {
1509*10d63b7dSRichard Lowe 		rp->automatics = NULL;
1510*10d63b7dSRichard Lowe 	}
1511*10d63b7dSRichard Lowe 	{
1512*10d63b7dSRichard Lowe 		rp->pid = process_running;
1513*10d63b7dSRichard Lowe 		process_running = -1;
1514*10d63b7dSRichard Lowe 		childPid = -1;
1515*10d63b7dSRichard Lowe 	}
1516*10d63b7dSRichard Lowe 	rp->job_msg_id = job_msg_id;
1517*10d63b7dSRichard Lowe 	rp->stdout_file = stdout_file;
1518*10d63b7dSRichard Lowe 	rp->stderr_file = stderr_file;
1519*10d63b7dSRichard Lowe 	rp->temp_file = temp_file_name;
1520*10d63b7dSRichard Lowe 	rp->redo = false;
1521*10d63b7dSRichard Lowe 	rp->next = NULL;
1522*10d63b7dSRichard Lowe 	store_conditionals(rp);
1523*10d63b7dSRichard Lowe 	stdout_file = NULL;
1524*10d63b7dSRichard Lowe 	stderr_file = NULL;
1525*10d63b7dSRichard Lowe 	temp_file_name = NULL;
1526*10d63b7dSRichard Lowe 	current_target = NULL;
1527*10d63b7dSRichard Lowe 	current_line = NULL;
1528*10d63b7dSRichard Lowe 	*running_tail = rp;
1529*10d63b7dSRichard Lowe 	running_tail = &rp->next;
1530*10d63b7dSRichard Lowe }
1531*10d63b7dSRichard Lowe 
1532*10d63b7dSRichard Lowe /*
1533*10d63b7dSRichard Lowe  *	add_pending(target, recursion_level, do_get, implicit, redo)
1534*10d63b7dSRichard Lowe  *
1535*10d63b7dSRichard Lowe  *	Adds a record on the running list for a pending target
1536*10d63b7dSRichard Lowe  *	(waiting for its dependents to finish running).
1537*10d63b7dSRichard Lowe  *
1538*10d63b7dSRichard Lowe  *	Parameters:
1539*10d63b7dSRichard Lowe  *		target		Target being built
1540*10d63b7dSRichard Lowe  *		recursion_level	Debug indentation level
1541*10d63b7dSRichard Lowe  *		do_get		Sccs get flag
1542*10d63b7dSRichard Lowe  *		implicit	Implicit flag
1543*10d63b7dSRichard Lowe  *		redo		True if this target is being redone
1544*10d63b7dSRichard Lowe  *
1545*10d63b7dSRichard Lowe  *	Static variables used:
1546*10d63b7dSRichard Lowe  *		running_tail	Tail of running list
1547*10d63b7dSRichard Lowe  */
1548*10d63b7dSRichard Lowe void
1549*10d63b7dSRichard Lowe add_pending(Name target, int recursion_level, Boolean do_get, Boolean implicit, Boolean redo)
1550*10d63b7dSRichard Lowe {
1551*10d63b7dSRichard Lowe 	Running		rp;
1552*10d63b7dSRichard Lowe 	rp = new_running_struct();
1553*10d63b7dSRichard Lowe 	rp->state = build_pending;
1554*10d63b7dSRichard Lowe 	rp->target = target;
1555*10d63b7dSRichard Lowe 	rp->recursion_level = recursion_level;
1556*10d63b7dSRichard Lowe 	rp->do_get = do_get;
1557*10d63b7dSRichard Lowe 	rp->implicit = implicit;
1558*10d63b7dSRichard Lowe 	rp->redo = redo;
1559*10d63b7dSRichard Lowe 	store_conditionals(rp);
1560*10d63b7dSRichard Lowe 	*running_tail = rp;
1561*10d63b7dSRichard Lowe 	running_tail = &rp->next;
1562*10d63b7dSRichard Lowe }
1563*10d63b7dSRichard Lowe 
1564*10d63b7dSRichard Lowe /*
1565*10d63b7dSRichard Lowe  *	add_serial(target, recursion_level, do_get, implicit)
1566*10d63b7dSRichard Lowe  *
1567*10d63b7dSRichard Lowe  *	Adds a record on the running list for a target which must be
1568*10d63b7dSRichard Lowe  *	executed in serial after others have finished.
1569*10d63b7dSRichard Lowe  *
1570*10d63b7dSRichard Lowe  *	Parameters:
1571*10d63b7dSRichard Lowe  *		target		Target being built
1572*10d63b7dSRichard Lowe  *		recursion_level	Debug indentation level
1573*10d63b7dSRichard Lowe  *		do_get		Sccs get flag
1574*10d63b7dSRichard Lowe  *		implicit	Implicit flag
1575*10d63b7dSRichard Lowe  *
1576*10d63b7dSRichard Lowe  *	Static variables used:
1577*10d63b7dSRichard Lowe  *		running_tail	Tail of running list
1578*10d63b7dSRichard Lowe  */
1579*10d63b7dSRichard Lowe void
1580*10d63b7dSRichard Lowe add_serial(Name target, int recursion_level, Boolean do_get, Boolean implicit)
1581*10d63b7dSRichard Lowe {
1582*10d63b7dSRichard Lowe 	Running		rp;
1583*10d63b7dSRichard Lowe 
1584*10d63b7dSRichard Lowe 	rp = new_running_struct();
1585*10d63b7dSRichard Lowe 	rp->target = target;
1586*10d63b7dSRichard Lowe 	rp->recursion_level = recursion_level;
1587*10d63b7dSRichard Lowe 	rp->do_get = do_get;
1588*10d63b7dSRichard Lowe 	rp->implicit = implicit;
1589*10d63b7dSRichard Lowe 	rp->state = build_serial;
1590*10d63b7dSRichard Lowe 	rp->redo = false;
1591*10d63b7dSRichard Lowe 	store_conditionals(rp);
1592*10d63b7dSRichard Lowe 	*running_tail = rp;
1593*10d63b7dSRichard Lowe 	running_tail = &rp->next;
1594*10d63b7dSRichard Lowe }
1595*10d63b7dSRichard Lowe 
1596*10d63b7dSRichard Lowe /*
1597*10d63b7dSRichard Lowe  *	add_subtree(target, recursion_level, do_get, implicit)
1598*10d63b7dSRichard Lowe  *
1599*10d63b7dSRichard Lowe  *	Adds a record on the running list for a target which must be
1600*10d63b7dSRichard Lowe  *	executed in isolation after others have finished.
1601*10d63b7dSRichard Lowe  *
1602*10d63b7dSRichard Lowe  *	Parameters:
1603*10d63b7dSRichard Lowe  *		target		Target being built
1604*10d63b7dSRichard Lowe  *		recursion_level	Debug indentation level
1605*10d63b7dSRichard Lowe  *		do_get		Sccs get flag
1606*10d63b7dSRichard Lowe  *		implicit	Implicit flag
1607*10d63b7dSRichard Lowe  *
1608*10d63b7dSRichard Lowe  *	Static variables used:
1609*10d63b7dSRichard Lowe  *		running_tail	Tail of running list
1610*10d63b7dSRichard Lowe  */
1611*10d63b7dSRichard Lowe void
1612*10d63b7dSRichard Lowe add_subtree(Name target, int recursion_level, Boolean do_get, Boolean implicit)
1613*10d63b7dSRichard Lowe {
1614*10d63b7dSRichard Lowe 	Running		rp;
1615*10d63b7dSRichard Lowe 
1616*10d63b7dSRichard Lowe 	rp = new_running_struct();
1617*10d63b7dSRichard Lowe 	rp->target = target;
1618*10d63b7dSRichard Lowe 	rp->recursion_level = recursion_level;
1619*10d63b7dSRichard Lowe 	rp->do_get = do_get;
1620*10d63b7dSRichard Lowe 	rp->implicit = implicit;
1621*10d63b7dSRichard Lowe 	rp->state = build_subtree;
1622*10d63b7dSRichard Lowe 	rp->redo = false;
1623*10d63b7dSRichard Lowe 	store_conditionals(rp);
1624*10d63b7dSRichard Lowe 	*running_tail = rp;
1625*10d63b7dSRichard Lowe 	running_tail = &rp->next;
1626*10d63b7dSRichard Lowe }
1627*10d63b7dSRichard Lowe 
1628*10d63b7dSRichard Lowe /*
1629*10d63b7dSRichard Lowe  *	store_conditionals(rp)
1630*10d63b7dSRichard Lowe  *
1631*10d63b7dSRichard Lowe  *	Creates an array of the currently active targets with conditional
1632*10d63b7dSRichard Lowe  *	macros (found in the chain conditional_targets) and puts that
1633*10d63b7dSRichard Lowe  *	array in the Running struct.
1634*10d63b7dSRichard Lowe  *
1635*10d63b7dSRichard Lowe  *	Parameters:
1636*10d63b7dSRichard Lowe  *		rp		Running struct for storing chain
1637*10d63b7dSRichard Lowe  *
1638*10d63b7dSRichard Lowe  *	Global variables used:
1639*10d63b7dSRichard Lowe  *		conditional_targets  Chain of current dynamic conditionals
1640*10d63b7dSRichard Lowe  */
1641*10d63b7dSRichard Lowe static void
1642*10d63b7dSRichard Lowe store_conditionals(Running rp)
1643*10d63b7dSRichard Lowe {
1644*10d63b7dSRichard Lowe 	int		cnt;
1645*10d63b7dSRichard Lowe 	Chain		cond_name;
1646*10d63b7dSRichard Lowe 
1647*10d63b7dSRichard Lowe 	if (conditional_targets == NULL) {
1648*10d63b7dSRichard Lowe 		rp->conditional_cnt = 0;
1649*10d63b7dSRichard Lowe 		rp->conditional_targets = NULL;
1650*10d63b7dSRichard Lowe 		return;
1651*10d63b7dSRichard Lowe 	}
1652*10d63b7dSRichard Lowe 	cnt = 0;
1653*10d63b7dSRichard Lowe 	for (cond_name = conditional_targets;
1654*10d63b7dSRichard Lowe 	     cond_name != NULL;
1655*10d63b7dSRichard Lowe 	     cond_name = cond_name->next) {
1656*10d63b7dSRichard Lowe 		cnt++;
1657*10d63b7dSRichard Lowe 	}
1658*10d63b7dSRichard Lowe 	rp->conditional_cnt = cnt;
1659*10d63b7dSRichard Lowe 	rp->conditional_targets = (Name *) getmem(cnt * sizeof(Name));
1660*10d63b7dSRichard Lowe 	for (cond_name = conditional_targets;
1661*10d63b7dSRichard Lowe 	     cond_name != NULL;
1662*10d63b7dSRichard Lowe 	     cond_name = cond_name->next) {
1663*10d63b7dSRichard Lowe 		rp->conditional_targets[--cnt] = cond_name->name;
1664*10d63b7dSRichard Lowe 	}
1665*10d63b7dSRichard Lowe }
1666*10d63b7dSRichard Lowe 
1667*10d63b7dSRichard Lowe /*
1668*10d63b7dSRichard Lowe  *	parallel_ok(target, line_prop_must_exists)
1669*10d63b7dSRichard Lowe  *
1670*10d63b7dSRichard Lowe  *	Returns true if the target can be run in parallel
1671*10d63b7dSRichard Lowe  *
1672*10d63b7dSRichard Lowe  *	Return value:
1673*10d63b7dSRichard Lowe  *				True if can run in parallel
1674*10d63b7dSRichard Lowe  *
1675*10d63b7dSRichard Lowe  *	Parameters:
1676*10d63b7dSRichard Lowe  *		target		Target being tested
1677*10d63b7dSRichard Lowe  *
1678*10d63b7dSRichard Lowe  *	Global variables used:
1679*10d63b7dSRichard Lowe  *		all_parallel	True if all targets default to parallel
1680*10d63b7dSRichard Lowe  *		only_parallel	True if no targets default to parallel
1681*10d63b7dSRichard Lowe  */
1682*10d63b7dSRichard Lowe Boolean
1683*10d63b7dSRichard Lowe parallel_ok(Name target, Boolean line_prop_must_exists)
1684*10d63b7dSRichard Lowe {
1685*10d63b7dSRichard Lowe 	Boolean		assign;
1686*10d63b7dSRichard Lowe 	Boolean		make_refd;
1687*10d63b7dSRichard Lowe 	Property	line;
1688*10d63b7dSRichard Lowe 	Cmd_line	rule;
1689*10d63b7dSRichard Lowe 
1690*10d63b7dSRichard Lowe 	assign = make_refd = false;
1691*10d63b7dSRichard Lowe 	if (((line = get_prop(target->prop, line_prop)) == NULL) &&
1692*10d63b7dSRichard Lowe 	    line_prop_must_exists) {
1693*10d63b7dSRichard Lowe 		return false;
1694*10d63b7dSRichard Lowe 	}
1695*10d63b7dSRichard Lowe 	if (line != NULL) {
1696*10d63b7dSRichard Lowe 		for (rule = line->body.line.command_used;
1697*10d63b7dSRichard Lowe 		     rule != NULL;
1698*10d63b7dSRichard Lowe 		     rule = rule->next) {
1699*10d63b7dSRichard Lowe 			if (rule->assign) {
1700*10d63b7dSRichard Lowe 				assign = true;
1701*10d63b7dSRichard Lowe 			} else if (rule->make_refd) {
1702*10d63b7dSRichard Lowe 				make_refd = true;
1703*10d63b7dSRichard Lowe 			}
1704*10d63b7dSRichard Lowe 		}
1705*10d63b7dSRichard Lowe 	}
1706*10d63b7dSRichard Lowe 	if (assign) {
1707*10d63b7dSRichard Lowe 		return false;
1708*10d63b7dSRichard Lowe 	} else if (target->parallel) {
1709*10d63b7dSRichard Lowe 		return true;
1710*10d63b7dSRichard Lowe 	} else if (target->no_parallel) {
1711*10d63b7dSRichard Lowe 		return false;
1712*10d63b7dSRichard Lowe 	} else if (all_parallel) {
1713*10d63b7dSRichard Lowe 		return true;
1714*10d63b7dSRichard Lowe 	} else if (only_parallel) {
1715*10d63b7dSRichard Lowe 		return false;
1716*10d63b7dSRichard Lowe 	} else if (make_refd) {
1717*10d63b7dSRichard Lowe 		return false;
1718*10d63b7dSRichard Lowe 	} else {
1719*10d63b7dSRichard Lowe 		return true;
1720*10d63b7dSRichard Lowe 	}
1721*10d63b7dSRichard Lowe }
1722*10d63b7dSRichard Lowe 
1723*10d63b7dSRichard Lowe /*
1724*10d63b7dSRichard Lowe  *	is_running(target)
1725*10d63b7dSRichard Lowe  *
1726*10d63b7dSRichard Lowe  *	Returns true if the target is running.
1727*10d63b7dSRichard Lowe  *
1728*10d63b7dSRichard Lowe  *	Return value:
1729*10d63b7dSRichard Lowe  *				True if target is running
1730*10d63b7dSRichard Lowe  *
1731*10d63b7dSRichard Lowe  *	Parameters:
1732*10d63b7dSRichard Lowe  *		target		Target to check
1733*10d63b7dSRichard Lowe  *
1734*10d63b7dSRichard Lowe  *	Global variables used:
1735*10d63b7dSRichard Lowe  *		running_list	List of running processes
1736*10d63b7dSRichard Lowe  */
1737*10d63b7dSRichard Lowe Boolean
1738*10d63b7dSRichard Lowe is_running(Name target)
1739*10d63b7dSRichard Lowe {
1740*10d63b7dSRichard Lowe 	Running		rp;
1741*10d63b7dSRichard Lowe 
1742*10d63b7dSRichard Lowe 	if (target->state != build_running) {
1743*10d63b7dSRichard Lowe 		return false;
1744*10d63b7dSRichard Lowe 	}
1745*10d63b7dSRichard Lowe 	for (rp = running_list;
1746*10d63b7dSRichard Lowe 	     rp != NULL && target != rp->target;
1747*10d63b7dSRichard Lowe 	     rp = rp->next);
1748*10d63b7dSRichard Lowe 	if (rp == NULL) {
1749*10d63b7dSRichard Lowe 		return false;
1750*10d63b7dSRichard Lowe 	} else {
1751*10d63b7dSRichard Lowe 		return (rp->state == build_running) ? true : false;
1752*10d63b7dSRichard Lowe 	}
1753*10d63b7dSRichard Lowe }
1754*10d63b7dSRichard Lowe 
1755*10d63b7dSRichard Lowe /*
1756*10d63b7dSRichard Lowe  * This function replaces the makesh binary.
1757*10d63b7dSRichard Lowe  */
1758*10d63b7dSRichard Lowe 
1759*10d63b7dSRichard Lowe 
1760*10d63b7dSRichard Lowe static pid_t
1761*10d63b7dSRichard Lowe run_rule_commands(char *host, char **commands)
1762*10d63b7dSRichard Lowe {
1763*10d63b7dSRichard Lowe 	Boolean		always_exec;
1764*10d63b7dSRichard Lowe 	Name		command;
1765*10d63b7dSRichard Lowe 	Boolean		ignore;
1766*10d63b7dSRichard Lowe 	int		length;
1767*10d63b7dSRichard Lowe 	Doname		result;
1768*10d63b7dSRichard Lowe 	Boolean		silent_flag;
1769*10d63b7dSRichard Lowe 	wchar_t		*tmp_wcs_buffer;
1770*10d63b7dSRichard Lowe 
1771*10d63b7dSRichard Lowe 	childPid = fork();
1772*10d63b7dSRichard Lowe 	switch (childPid) {
1773*10d63b7dSRichard Lowe 	case -1:	/* Error */
1774*10d63b7dSRichard Lowe 		fatal(gettext("Could not fork child process for dmake job: %s"),
1775*10d63b7dSRichard Lowe 		      errmsg(errno));
1776*10d63b7dSRichard Lowe 		break;
1777*10d63b7dSRichard Lowe 	case 0:		/* Child */
1778*10d63b7dSRichard Lowe 		/* To control the processed targets list is not the child's business */
1779*10d63b7dSRichard Lowe 		running_list = NULL;
1780*10d63b7dSRichard Lowe 		if(out_err_same) {
1781*10d63b7dSRichard Lowe 			redirect_io(stdout_file, (char*)NULL);
1782*10d63b7dSRichard Lowe 		} else {
1783*10d63b7dSRichard Lowe 			redirect_io(stdout_file, stderr_file);
1784*10d63b7dSRichard Lowe 		}
1785*10d63b7dSRichard Lowe 		for (commands = commands;
1786*10d63b7dSRichard Lowe 		     (*commands != (char *)NULL);
1787*10d63b7dSRichard Lowe 		     commands++) {
1788*10d63b7dSRichard Lowe 			silent_flag = silent;
1789*10d63b7dSRichard Lowe 			ignore = false;
1790*10d63b7dSRichard Lowe 			always_exec = false;
1791*10d63b7dSRichard Lowe 			while ((**commands == (int) at_char) ||
1792*10d63b7dSRichard Lowe 			       (**commands == (int) hyphen_char) ||
1793*10d63b7dSRichard Lowe 			       (**commands == (int) plus_char)) {
1794*10d63b7dSRichard Lowe 				if (**commands == (int) at_char) {
1795*10d63b7dSRichard Lowe 					silent_flag = true;
1796*10d63b7dSRichard Lowe 				}
1797*10d63b7dSRichard Lowe 				if (**commands == (int) hyphen_char) {
1798*10d63b7dSRichard Lowe 					ignore = true;
1799*10d63b7dSRichard Lowe 				}
1800*10d63b7dSRichard Lowe 				if (**commands == (int) plus_char) {
1801*10d63b7dSRichard Lowe 					always_exec = true;
1802*10d63b7dSRichard Lowe 				}
1803*10d63b7dSRichard Lowe 				(*commands)++;
1804*10d63b7dSRichard Lowe 			}
1805*10d63b7dSRichard Lowe 			if ((length = strlen(*commands)) >= MAXPATHLEN) {
1806*10d63b7dSRichard Lowe 				tmp_wcs_buffer = ALLOC_WC(length + 1);
1807*10d63b7dSRichard Lowe 				(void) mbstowcs(tmp_wcs_buffer, *commands, length + 1);
1808*10d63b7dSRichard Lowe 				command = GETNAME(tmp_wcs_buffer, FIND_LENGTH);
1809*10d63b7dSRichard Lowe 				retmem(tmp_wcs_buffer);
1810*10d63b7dSRichard Lowe 			} else {
1811*10d63b7dSRichard Lowe 				MBSTOWCS(wcs_buffer, *commands);
1812*10d63b7dSRichard Lowe 				command = GETNAME(wcs_buffer, FIND_LENGTH);
1813*10d63b7dSRichard Lowe 			}
1814*10d63b7dSRichard Lowe 			if ((command->hash.length > 0) &&
1815*10d63b7dSRichard Lowe 			    !silent_flag) {
1816*10d63b7dSRichard Lowe 				(void) printf("%s\n", command->string_mb);
1817*10d63b7dSRichard Lowe 			}
1818*10d63b7dSRichard Lowe 			result = dosys(command,
1819*10d63b7dSRichard Lowe 			               ignore,
1820*10d63b7dSRichard Lowe 			               false,
1821*10d63b7dSRichard Lowe 			               false, /* bugs #4085164 & #4990057 */
1822*10d63b7dSRichard Lowe 			               /* BOOLEAN(silent_flag && ignore), */
1823*10d63b7dSRichard Lowe 			               always_exec,
1824*10d63b7dSRichard Lowe 			               (Name) NULL);
1825*10d63b7dSRichard Lowe 			if (result == build_failed) {
1826*10d63b7dSRichard Lowe 				if (silent_flag) {
1827*10d63b7dSRichard Lowe 					(void) printf(gettext("The following command caused the error:\n%s\n"), command->string_mb);
1828*10d63b7dSRichard Lowe 				}
1829*10d63b7dSRichard Lowe 				if (!ignore) {
1830*10d63b7dSRichard Lowe 					_exit(1);
1831*10d63b7dSRichard Lowe 				}
1832*10d63b7dSRichard Lowe 			}
1833*10d63b7dSRichard Lowe 		}
1834*10d63b7dSRichard Lowe 		_exit(0);
1835*10d63b7dSRichard Lowe 		break;
1836*10d63b7dSRichard Lowe 	default:
1837*10d63b7dSRichard Lowe 		break;
1838*10d63b7dSRichard Lowe 	}
1839*10d63b7dSRichard Lowe 	return childPid;
1840*10d63b7dSRichard Lowe }
1841*10d63b7dSRichard Lowe 
1842*10d63b7dSRichard Lowe static void
1843*10d63b7dSRichard Lowe maybe_reread_make_state(void)
1844*10d63b7dSRichard Lowe {
1845*10d63b7dSRichard Lowe 	/* Copying dosys()... */
1846*10d63b7dSRichard Lowe 	if (report_dependencies_level == 0) {
1847*10d63b7dSRichard Lowe 		make_state->stat.time = file_no_time;
1848*10d63b7dSRichard Lowe 		(void) exists(make_state);
1849*10d63b7dSRichard Lowe 		if (make_state_before == make_state->stat.time) {
1850*10d63b7dSRichard Lowe 			return;
1851*10d63b7dSRichard Lowe 		}
1852*10d63b7dSRichard Lowe 		makefile_type = reading_statefile;
1853*10d63b7dSRichard Lowe 		if (read_trace_level > 1) {
1854*10d63b7dSRichard Lowe 			trace_reader = true;
1855*10d63b7dSRichard Lowe 		}
1856*10d63b7dSRichard Lowe 		temp_file_number++;
1857*10d63b7dSRichard Lowe 		(void) read_simple_file(make_state,
1858*10d63b7dSRichard Lowe 					false,
1859*10d63b7dSRichard Lowe 					false,
1860*10d63b7dSRichard Lowe 					false,
1861*10d63b7dSRichard Lowe 					false,
1862*10d63b7dSRichard Lowe 					false,
1863*10d63b7dSRichard Lowe 					true);
1864*10d63b7dSRichard Lowe 		trace_reader = false;
1865*10d63b7dSRichard Lowe 	}
1866*10d63b7dSRichard Lowe }
1867*10d63b7dSRichard Lowe 
1868*10d63b7dSRichard Lowe 
1869*10d63b7dSRichard Lowe static void
1870*10d63b7dSRichard Lowe delete_running_struct(Running rp)
1871*10d63b7dSRichard Lowe {
1872*10d63b7dSRichard Lowe 	if ((rp->conditional_cnt > 0) &&
1873*10d63b7dSRichard Lowe 	    (rp->conditional_targets != NULL)) {
1874*10d63b7dSRichard Lowe 		retmem_mb((char *) rp->conditional_targets);
1875*10d63b7dSRichard Lowe 	}
1876*10d63b7dSRichard Lowe /**/
1877*10d63b7dSRichard Lowe 	if ((rp->auto_count > 0) &&
1878*10d63b7dSRichard Lowe 	    (rp->automatics != NULL)) {
1879*10d63b7dSRichard Lowe 		retmem_mb((char *) rp->automatics);
1880*10d63b7dSRichard Lowe 	}
1881*10d63b7dSRichard Lowe /**/
1882*10d63b7dSRichard Lowe 	if(rp->sprodep_value) {
1883*10d63b7dSRichard Lowe 		free_name(rp->sprodep_value);
1884*10d63b7dSRichard Lowe 	}
1885*10d63b7dSRichard Lowe 	if(rp->sprodep_env) {
1886*10d63b7dSRichard Lowe 		retmem_mb(rp->sprodep_env);
1887*10d63b7dSRichard Lowe 	}
1888*10d63b7dSRichard Lowe 	retmem_mb((char *) rp);
1889*10d63b7dSRichard Lowe 
1890*10d63b7dSRichard Lowe }
1891*10d63b7dSRichard Lowe 
1892*10d63b7dSRichard Lowe 
1893