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