1 /*
2  * CDDL HEADER START
3  *
4  * This file and its contents are supplied under the terms of the
5  * Common Development and Distribution License ("CDDL"), version 1.0.
6  * You may use this file only in accordance with the terms of version
7  * 1.0 of the CDDL.
8  *
9  * A full copy of the text of the CDDL should have accompanied this
10  * source.  A copy of the CDDL is also available via the Internet at
11  * http://www.opensource.org/licenses/cddl1.txt
12  * See the License for the specific language governing permissions
13  * and limitations under the License.
14  *
15  * When distributing Covered Code, include this CDDL HEADER in each
16  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
17  * If applicable, add the following below this CDDL HEADER, with the
18  * fields enclosed by brackets "[]" replaced with your own identifying
19  * information: Portions Copyright [yyyy] [name of copyright owner]
20  *
21  * CDDL HEADER END
22  */
23 /*
24  * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
25  * Use is subject to license terms.
26  */
27 /*
28  * @(#)main.cc 1.158 06/12/12
29  */
30 
31 #pragma	ident	"@(#)main.cc	1.158	06/12/12"
32 
33 /*
34  * Copyright 2017-2021 J. Schilling
35  *
36  * @(#)main.cc	1.60 21/08/30 2017-2021 J. Schilling
37  */
38 #include <schily/mconfig.h>
39 #ifndef lint
40 static	UConst char sccsid[] =
41 	"@(#)main.cc	1.60 21/08/30 2017-2021 J. Schilling";
42 #endif
43 
44 /*
45  *	main.cc
46  *
47  *	make program main routine plus some helper routines
48  */
49 
50 /*
51  * Included files
52  */
53 #if defined(TEAMWARE_MAKE_CMN)
54 #       include <avo/intl.h>
55 #       include <avo/libcli.h>          /* libcli_init() */
56 #	include <avo/cli_license.h>	/* avo_cli_get_license() */
57 #	include <avo/find_dir.h>	/* avo_find_run_dir() */
58 #	include <avo/version_string.h>
59 #	include <avo/util.h>		/* avo_init() */
60 #ifdef USE_DMS_CCR
61 #	include <avo/usage_tracking.h>
62 #else
63 #	include <avo/cleanup.h>
64 #endif
65 #endif
66 
67 #if defined(TEAMWARE_MAKE_CMN)
68 /* This is for dmake only (not for Solaris make).
69  * Include code to check updates (dmake patches)
70  */
71 #ifdef _CHECK_UPDATE_H
72 #include <libAU.h>
73 #endif
74 #endif
75 
76 #include <bsd/bsd.h>		/* bsd_signal() */
77 
78 #ifdef DISTRIBUTED
79 #	include <dm/Avo_AcknowledgeMsg.h>
80 #	include <rw/xdrstrea.h>
81 #	include <dmrc/dmrc.h> /* dmakerc file processing */
82 #endif
83 
84 #if defined(SCHILY_BUILD) || defined(SCHILY_INCLUDES)
85 #include <schily/locale.h>	/* setlocale() */
86 #else
87 #include <locale.h>		/* setlocale() */
88 #endif
89 #include <mk/copyright.h>
90 #include <mk/defs.h>
91 #include <mksh/macro.h>		/* getvar() */
92 #include <mksh/misc.h>		/* getmem(), setup_char_semantics() */
93 
94 #if defined(TEAMWARE_MAKE_CMN)
95 #ifdef USE_DMS_CCR
96 #	include <pubdmsi18n/pubdmsi18n.h>	/* libpubdmsi18n_init() */
97 #endif
98 #endif
99 
100 #if defined(SCHILY_BUILD) || defined(SCHILY_INCLUDES)
101 #include <schily/pwd.h>		/* getpwnam() */
102 #include <schily/setjmp.h>
103 
104 #include <schily/wait.h>	/* wait() */
105 #else
106 #include <pwd.h>		/* getpwnam() */
107 #include <setjmp.h>
108 
109 #include <sys/wait.h>		/* wait() */
110 #define	WAIT_T	int
111 #endif
112 #include <vroot/report.h>	/* report_dependency(), get_report_file() */
113 
114 // From read2.cc
115 extern	Name		normalize_name(register wchar_t *name_string, register int length);
116 
117 // From parallel.cc
118 #if defined(TEAMWARE_MAKE_CMN) || defined(PMAKE)
119 #define MAXJOBS_ADJUST_RFE4694000
120 
121 #ifdef MAXJOBS_ADJUST_RFE4694000
122 extern void job_adjust_fini();
123 #endif /* MAXJOBS_ADJUST_RFE4694000 */
124 #endif /* TEAMWARE_MAKE_CMN */
125 
126 #include <ctype.h>
127 
128 #ifdef	HAVE_LIBGEN_H
129 #include <libgen.h>
130 #endif
131 #include <schily/schily.h>
132 
133 #ifdef	ultrix		/* No prototypes in SIG_DFL macro */
134 #undef	SUN5_0
135 #endif
136 
137 /*
138  * Defined macros
139  */
140 #define	LD_SUPPORT_ENV_VAR	NOCATGETS("SGS_SUPPORT")
141 #define	LD_SUPPORT_ENV_VAR_32	NOCATGETS("SGS_SUPPORT_32")
142 #define	LD_SUPPORT_ENV_VAR_64	NOCATGETS("SGS_SUPPORT_64")
143 #define	LD_SUPPORT_MAKE_LIB	NOCATGETS("libmakestate.so.1")
144 #ifdef	sun
145 #ifdef	__i386
146 #define	LD_SUPPORT_MAKE_ARCH	"i386/"
147 #endif
148 #ifdef	__sparc
149 #define	LD_SUPPORT_MAKE_ARCH	"sparc/"
150 #endif
151 #endif	/* sun */
152 
153 /*
154  * typedefs & structs
155  */
156 
157 /*
158  * Static variables
159  */
160 static	char		*argv_zero_string;
161 static	char		*argv_zero_base;
162 static	char		*dmake_compat_value;
163 static	Boolean		build_failed_ever_seen;
164 static	Boolean		continue_after_error_ever_seen;	/* `-k' */
165 static	Boolean		dmake_group_specified;		/* `-g' */
166 static	Boolean		dmake_max_jobs_specified;	/* `-j' */
167 static	Boolean		dmake_mode_specified;		/* `-m' */
168 static	Boolean		dmake_add_mode_specified;	/* `-x' */
169 static	Boolean		dmake_output_mode_specified;	/* `-x DMAKE_OUTPUT_MODE=' */
170 static	Boolean		dmake_compat_mode_specified;	/* `-x SUN_MAKE_COMPAT_MODE=' */
171 static	Boolean		dmake_odir_specified;		/* `-o' */
172 static	Boolean		dmake_rcfile_specified;		/* `-c' */
173 static	Boolean		env_wins;			/* `-e' */
174 static	Boolean		ignore_default_mk;		/* `-r' */
175 static	Boolean		list_all_targets;		/* `-T' */
176 static	int		mf_argc;
177 static	char		**mf_argv;
178 static	Dependency_rec  not_auto_depen_struct;
179 static	Dependency 	not_auto_depen = &not_auto_depen_struct;
180 static	Boolean		pmake_cap_r_specified;		/* `-R' */
181 static	Boolean		pmake_machinesfile_specified;	/* `-M' */
182 static	Boolean		stop_after_error_ever_seen;	/* `-S' */
183 static	Boolean		trace_status;			/* `-p' */
184 
185 #ifdef DMAKE_STATISTICS
186 static	Boolean		getname_stat = false;
187 #endif
188 
189 	static	int		g_argc;
190 	static	char		**g_argv;
191 #if defined(TEAMWARE_MAKE_CMN)
192 	static	time_t		start_time;
193 #ifdef USE_DMS_CCR
194 	static  Avo_usage_tracking *usageTracking = NULL;
195 #else
196 	static  Avo_cleanup	*cleanup = NULL;
197 #endif
198 #endif
199 
200 /*
201  * File table of contents
202  */
203 #ifdef	HAVE_ATEXIT
204 	extern "C" void		cleanup_after_exit(void);
205 #else
206 	extern	void		cleanup_after_exit(int, ...);
207 #endif
208 
209 #ifdef TEAMWARE_MAKE_CMN
210 extern "C" {
211 	extern	void		dmake_exit_callback(void);
212 	extern	void		dmake_message_callback(char *);
213 }
214 #endif
215 
216 extern	Name		normalize_name(register wchar_t *name_string, register int length);
217 
218 extern	int		main(int, char * []);
219 
220 static	void		scan_dmake_compat_mode(char *);
221 static	void		append_makeflags_string(Name, String);
222 static	void		doalarm(int);
223 static	void		enter_argv_values(int , char **, ASCII_Dyn_Array *);
224 static	void		make_targets(int, char **, Boolean);
225 static	int		parse_command_option(char);
226 static	void		read_command_options(int, char **);
227 static	void		read_environment(Boolean);
228 static	void		read_files_and_state(int, char **);
229 static	Boolean		read_makefile(Name, Boolean, Boolean, Boolean);
230 static	void		report_recursion(Name);
231 static	void		set_sgs_support(void);
232 static	void		setup_for_projectdir(void);
233 static	void		setup_makeflags_argv(void);
234 static	void		dir_enter_leave(Boolean entering);
235 static	void		report_dir_enter_leave(Boolean entering);
236 
237 
238 #ifdef DISTRIBUTED
239 	extern	int		dmake_ofd;
240 	extern	FILE*		dmake_ofp;
241 	extern	int		rxmPid;
242 	extern	XDR 		xdrs_out;
243 #endif
244 #ifdef TEAMWARE_MAKE_CMN
245 	extern	char		verstring[];
246 #else
247 #if defined(SCHILY_BUILD) || defined(SCHILY_INCLUDES)
248 	extern	char		verstring[];
249 #endif
250 #endif
251 
252 jmp_buf jmpbuffer;
253 
254 /*
255  *	main(argc, argv)
256  *
257  *	Parameters:
258  *		argc			You know what this is
259  *		argv			You know what this is
260  *
261  *	Static variables used:
262  *		list_all_targets	make -T seen
263  *		trace_status		make -p seen
264  *
265  *	Global variables used:
266  *		debug_level		Should we trace make actions?
267  *		keep_state		Set if .KEEP_STATE seen
268  *		makeflags		The Name "MAKEFLAGS", used to get macro
269  *		remote_command_name	Name of remote invocation cmd ("on")
270  *		running_list		List of parallel running processes
271  *		stdout_stderr_same	true if stdout and stderr are the same
272  *		auto_dependencies	The Name "SUNPRO_DEPENDENCIES"
273  *		temp_file_directory	Set to the dir where we create tmp file
274  *		trace_reader		Set to reflect tracing status
275  *		working_on_targets	Set when building user targets
276  */
277 int
main(int argc,char * argv[])278 main(int argc, char *argv[])
279 {
280 	/*
281 	 * cp is a -> to the value of the MAKEFLAGS env var,
282 	 * which has to be regular chars.
283 	 */
284 	register char		*cp;
285 	char 			make_state_dir[MAXPATHLEN];
286 	Boolean			parallel_flag = false;
287 	char			*prognameptr;
288 	char 			*slash_ptr;
289 	mode_t			um;
290 	int			i;
291 #if defined(TEAMWARE_MAKE_CMN) || defined(PMAKE)
292 	struct itimerval	value;
293 	char			def_dmakerc_path[MAXPATHLEN];
294 	Name			dmake_name, dmake_name2;
295 	Name			dmake_value, dmake_value2;
296 	Property		prop, prop2;
297 	struct stat		statbuf;
298 	int			statval;
299 #endif
300 
301 #ifndef PARALLEL
302 	struct stat		out_stat, err_stat;
303 #endif
304 	hostid = gethostid();
305 #ifdef TEAMWARE_MAKE_CMN
306 	avo_get_user(NULL, NULL); // Initialize user name
307 #endif
308 	bsd_signals();
309 
310 	(void) setlocale(LC_ALL, "");
311 
312 #ifdef DMAKE_STATISTICS
313 	if (getenv(NOCATGETS("DMAKE_STATISTICS"))) {
314 		getname_stat = true;
315 	}
316 #endif
317 
318 
319 	/*
320 	 * avo_init() sets the umask to 0.  Save it here and restore
321 	 * it after the avo_init() call.
322 	 */
323 #if defined(TEAMWARE_MAKE_CMN) || defined(MAKETOOL)
324 	um = umask(0);
325 	avo_init(argv[0]);
326 	umask(um);
327 
328 #ifdef USE_DMS_CCR
329 	usageTracking = new Avo_usage_tracking(NOCATGETS("dmake"), argc, argv);
330 #else
331 	cleanup = new Avo_cleanup(NOCATGETS("dmake"), argc, argv);
332 #endif
333 #endif
334 
335 #if defined(TEAMWARE_MAKE_CMN)
336 	libcli_init();
337 
338 #ifdef _CHECK_UPDATE_H
339 	/* This is for dmake only (not for Solaris make).
340 	 * Check (in background) if there is an update (dmake patch)
341 	 * and inform user
342 	 */
343 	{
344 		Avo_err		*err;
345 		char		*dir;
346 		err = avo_find_run_dir(&dir);
347 		if (AVO_OK == err) {
348 			AU_check_update_service(NOCATGETS("Dmake"), dir);
349 		}
350 	}
351 #endif /* _CHECK_UPDATE_H */
352 #endif
353 
354 // ---> fprintf(stderr, gettext("--- SUN make ---\n"));
355 
356 
357 #if defined(TEAMWARE_MAKE_CMN) || defined(MAKETOOL)
358 /*
359  * I put libmksdmsi18n_init() under #ifdef because it requires avo_i18n_init()
360  * from avo_util library.
361  */
362 	libmksdmsi18n_init();
363 #ifdef USE_DMS_CCR
364 	libpubdmsi18n_init();
365 #endif
366 #endif
367 
368 #if !defined(TEXT_DOMAIN)	/* Should be defined by CC -D */
369 #define TEXT_DOMAIN "SYS_TEST"	/* Use this only if it weren't */
370 #endif
371 	textdomain(TEXT_DOMAIN);
372 
373 	g_argc = argc;
374 	g_argv = (char **) malloc((g_argc + 1) * sizeof(char *));
375 	for (i = 0; i < argc; i++) {
376 		g_argv[i] = argv[i];
377 	}
378 	g_argv[i] = NULL;
379 
380 	/*
381 	 * Set argv_zero_string to some form of argv[0] for
382 	 * recursive MAKE builds.
383 	 */
384 
385 	if (*argv[0] == (int) slash_char) {
386 		/* argv[0] starts with a slash */
387 		argv_zero_string = strdup(argv[0]);
388 	} else if (strchr(argv[0], (int) slash_char) == NULL) {
389 		/* argv[0] contains no slashes */
390 		argv_zero_string = strdup(argv[0]);
391 	} else {
392 		/*
393 		 * argv[0] contains at least one slash,
394 		 * but doesn't start with a slash
395 		 * so it is relative to the current working directory.
396 		 * Build an absolute path name for argv[0] to the called make
397 		 * binary path before we may do a chdir() from a -C option.
398 		 */
399 		char	*tmp_current_path;
400 		char	*tmp_string;
401 
402 		tmp_current_path = get_current_path();
403 		tmp_string = getmem(strlen(tmp_current_path) + 1 +
404 		                    strlen(argv[0]) + 1);
405 		(void) sprintf(tmp_string,
406 		               "%s/%s",
407 		               tmp_current_path,
408 		               argv[0]);
409 		argv_zero_string = strdup(tmp_string);
410 		retmem_mb(tmp_string);
411 	}
412 	if ((argv_zero_base = strrchr(argv_zero_string, '/')) == NULL)
413 		argv_zero_base = argv_zero_string;
414 	else
415 		argv_zero_base++;
416 
417 	/*
418 	 * The following flags are reset if we don't have the
419 	 * (.nse_depinfo or .make.state) files locked and only set
420 	 * AFTER the file has been locked. This ensures that if the user
421 	 * interrupts the program while file_lock() is waiting to lock
422 	 * the file, the interrupt handler doesn't remove a lock
423 	 * that doesn't belong to us.
424 	 */
425 	make_state_lockfile = NULL;
426 	make_state_locked = false;
427 
428 #ifdef NSE
429 	nse_depinfo_lockfile[0] = '\0';
430 	nse_depinfo_locked = false;
431 #endif
432 
433 	/*
434 	 * look for last slash char in the path to look at the binary
435 	 * name. This is to resolve the hard link and invoke make
436 	 * in svr4 mode.
437 	 *
438 	 * WARNING: /usr/bin/make and /usr/xpg4/bin/make must be
439 	 *	hardlinked or we will not be able to distinct them.
440 	 */
441 
442 	/* Sun OS make standard */
443 	svr4 = false;
444 	posix = false;
445 	make_run_dir = find_run_dir();
446 	if(!strcmp(argv_zero_string, NOCATGETS("/usr/xpg4/bin/make"))) {
447 		svr4 = false;
448 		posix = true;
449 	} else if (make_run_dir && (cp = strstr(make_run_dir, "xpg4/bin")) &&
450 	    strcmp(cp, "xpg4/bin") == 0) {
451 		svr4 = false;
452 		posix = true;
453 	} else if ((cp = strstr(argv_zero_string, "xpg4/bin/make")) &&
454 	    strcmp(cp, "xpg4/bin/make") == 0) {
455 		svr4 = false;
456 		posix = true;
457 	} else {
458 		prognameptr = strrchr(argv[0], '/');
459 		if(prognameptr) {
460 			prognameptr++;
461 		} else {
462 			prognameptr = argv[0];
463 		}
464 		if(!strcmp(prognameptr, NOCATGETS("svr4.make"))) {
465 			svr4 = true;
466 			posix = false;
467 		}
468 	}
469 	if (getenv(USE_SVR4_MAKE) || getenv(NOCATGETS("USE_SVID"))){
470 	   svr4 = true;
471 	   posix = false;
472 	}
473 
474 	/*
475 	 * Find the dmake_compat_mode: posix, sun, svr4, or gnu_style.
476 	 */
477 	scan_dmake_compat_mode(getenv(NOCATGETS("SUN_MAKE_COMPAT_MODE")));
478 
479 	/*
480 	 * Temporary directory set up.
481 	 */
482 	char * tmpdir_var = getenv(NOCATGETS("TMPDIR"));
483 	if (tmpdir_var != NULL && *tmpdir_var == '/' && strlen(tmpdir_var) < MAXPATHLEN) {
484 		strcpy(mbs_buffer, tmpdir_var);
485 		for (tmpdir_var = mbs_buffer+strlen(mbs_buffer);
486 			*(--tmpdir_var) == '/' && tmpdir_var > mbs_buffer;
487 			*tmpdir_var = '\0');
488 		if (strlen(mbs_buffer) + 32 < MAXPATHLEN) { /* 32 = strlen("/dmake.stdout.%d.%d.XXXXXX") */
489 			sprintf(mbs_buffer2, NOCATGETS("%s/dmake.tst.%d.XXXXXX"),
490 				mbs_buffer, getpid());
491 			int fd = mkstemp(mbs_buffer2);
492 			if (fd >= 0) {
493 				close(fd);
494 				unlink(mbs_buffer2);
495 				tmpdir = strdup(mbs_buffer);
496 			}
497 		}
498 	}
499 
500 #ifndef PARALLEL
501 	/* find out if stdout and stderr point to the same place */
502 	if (fstat(1, &out_stat) < 0) {
503 		fatal(gettext("fstat of standard out failed: %s"), errmsg(errno));
504 	}
505 	if (fstat(2, &err_stat) < 0) {
506 		fatal(gettext("fstat of standard error failed: %s"), errmsg(errno));
507 	}
508 	if ((out_stat.st_dev == err_stat.st_dev) &&
509 	    (out_stat.st_ino == err_stat.st_ino)) {
510 		stdout_stderr_same = true;
511 	} else {
512 		stdout_stderr_same = false;
513 	}
514 #else
515 	stdout_stderr_same = false;
516 #endif
517 	/* Make the vroot package scan the path using shell semantics */
518 	set_path_style(0);
519 
520 	setup_char_semantics();
521 
522 	/*
523 	 * If running with .KEEP_STATE, curdir will be set with
524 	 * the connected directory.
525 	 */
526 #ifdef	HAVE_ATEXIT
527 	(void) atexit(cleanup_after_exit);
528 #else
529 	(void) on_exit(cleanup_after_exit, (char *) NULL);
530 #endif
531 
532 	load_cached_names();
533 
534 /*
535  *	Set command line flags
536  *
537  *	Warning: Do not keep pointers from get_current_path() calls while
538  *	parsing the options as they could become invalid from a -C option.
539  */
540 	setup_makeflags_argv();
541 	read_command_options(mf_argc, mf_argv);
542 	read_command_options(argc, argv);
543 	if (debug_level > 0) {
544 		cp = getenv(makeflags->string_mb);
545 		(void) printf(gettext("MAKEFLAGS value: %s\n"), cp == NULL ? "" : cp);
546 	}
547 	if (dmake_compat_value) {	/* -x SUN_MAKE_COMPAT_MODE=xxx */
548 		char	*p = strchr(dmake_compat_value, '='); /* != NULL */
549 
550 		scan_dmake_compat_mode(++p);
551 
552 		/*
553 		 * Calling setup_char_semantics() again is needed in case that
554 		 * svr4 did change it's value.
555 		 */
556 		for (i = 0; i < CHAR_SEMANTICS_ENTRIES; i++)
557 			char_semantics[i] = 0;
558 		setup_char_semantics();
559 	}
560 #if defined(TEAMWARE_MAKE_CMN) || defined(PMAKE)
561 	if (posix)
562 		job_adjust_posix();		/* DMAKE_ADJUST_MAX_JOBS=M2 */
563 #endif
564 
565 	/*
566 	 * If there have been -C options, they have been evaluated with the
567 	 * last call to read_command_options() and we thus may need to
568 	 * re-initialize CURDIR before we read the Makefiles in order to let
569 	 * them overwrite CURDIR if they like.
570 	 */
571 	if (current_path_reset)
572 		(void) get_current_path();
573 	/*
574 	 * Need to set this up after parsing options and after a
575 	 * possible -C option has been processed.
576 	 */
577 	setup_for_projectdir();
578 
579 	dir_enter_leave(true);			/* Must be before next call */
580 	setup_interrupt(handle_interrupt);
581 
582 	read_files_and_state(argc, argv);
583 
584 #if defined(TEAMWARE_MAKE_CMN) || defined(PMAKE)
585 	/*
586 	 * Find the dmake_output_mode: TXT1, TXT2 or HTML1.
587 	 */
588 	MBSTOWCS(wcs_buffer, NOCATGETS("DMAKE_OUTPUT_MODE"));
589 	dmake_name2 = GETNAME(wcs_buffer, FIND_LENGTH);
590 	prop2 = get_prop(dmake_name2->prop, macro_prop);
591 	if (prop2 == NULL) {
592 		/* DMAKE_OUTPUT_MODE not defined, default to TXT1 mode */
593 		output_mode = txt1_mode;
594 	} else {
595 		dmake_value2 = prop2->body.macro.value;
596 		if ((dmake_value2 == NULL) ||
597 		    (IS_EQUAL(dmake_value2->string_mb, NOCATGETS("TXT1")))) {
598 			output_mode = txt1_mode;
599 		} else if (IS_EQUAL(dmake_value2->string_mb, NOCATGETS("TXT2"))) {
600 			output_mode = txt2_mode;
601 		} else if (IS_EQUAL(dmake_value2->string_mb, NOCATGETS("HTML1"))) {
602 			output_mode = html1_mode;
603 		} else {
604 			warning(gettext("Unsupported value `%s' for DMAKE_OUTPUT_MODE after -x flag (ignored)"),
605 			      dmake_value2->string_mb);
606 		}
607 	}
608 	/*
609 	 * Find the dmake_mode: distributed, parallel, or serial.
610 	 */
611 #ifdef	DO_NOTPARALLEL
612     if (notparallel) {
613 	dmake_mode_type = serial_mode;
614 	no_parallel = true;
615     } else
616 #endif
617     if ((!pmake_cap_r_specified) &&
618         (!pmake_machinesfile_specified)) {
619 	MBSTOWCS(wcs_buffer, NOCATGETS("DMAKE_MODE"));
620 	dmake_name2 = GETNAME(wcs_buffer, FIND_LENGTH);
621 	prop2 = get_prop(dmake_name2->prop, macro_prop);
622 
623 	if ((IS_EQUAL(argv_zero_base, NOCATGETS("make")) ||
624 	    IS_EQUAL(argv_zero_base, NOCATGETS("svr4.make"))) &&
625 	    !dmake_max_jobs_specified) {
626 		/*
627 		 * "make" and "svr4.make" default to serial mode, except when
628 		 * -j was specified.
629 		 */
630 		dmake_mode_type = serial_mode;
631 		no_parallel = true;
632 	} else if (prop2 == NULL) {
633 #ifdef TEAMWARE_MAKE_CMN
634 		/* DMAKE_MODE not defined, default to distributed mode */
635 		dmake_mode_type = distributed_mode;
636 		no_parallel = false;
637 #else
638 		/*
639 		 * If we ever implement support for something like the TeamWare
640 		 * .dmakerc, we need to move the printout down after the check
641 		 * for the .dmakerc file.
642 		 */
643 		if (getenv(NOCATGETS("DMAKE_DEF_PRINTED")) == NULL) {
644 			putenv((char *)NOCATGETS("DMAKE_DEF_PRINTED=TRUE"));
645 			(void) fprintf(stdout, gettext("dmake: defaulting to parallel mode.\n"));
646 		}
647 		dmake_mode_type = parallel_mode;
648 		no_parallel = false;
649 #endif
650 	} else {
651 		dmake_value2 = prop2->body.macro.value;
652 		if ((dmake_value2 == NULL) ||
653 		    (IS_EQUAL(dmake_value2->string_mb, NOCATGETS("distributed")))) {
654 			dmake_mode_type = distributed_mode;
655 			no_parallel = false;
656 		} else if (IS_EQUAL(dmake_value2->string_mb, NOCATGETS("parallel"))) {
657 			dmake_mode_type = parallel_mode;
658 			no_parallel = false;
659 #ifdef SGE_SUPPORT
660 			grid = false;
661 		} else if (IS_EQUAL(dmake_value2->string_mb, NOCATGETS("grid"))) {
662 			dmake_mode_type = parallel_mode;
663 			no_parallel = false;
664 			grid = true;
665 #endif
666 		} else if (IS_EQUAL(dmake_value2->string_mb, NOCATGETS("serial"))) {
667 			dmake_mode_type = serial_mode;
668 			no_parallel = true;
669 		} else {
670 			fatal(gettext("Unknown dmake mode argument `%s' after -m flag"), dmake_value2->string_mb);
671 		}
672 	}
673 
674 	if ((!list_all_targets) &&
675 	    (report_dependencies_level == 0)) {
676 		/*
677 		 * Check to see if either DMAKE_RCFILE or DMAKE_MODE is defined.
678 		 * They could be defined in the env, in the makefile, or on the
679 		 * command line.
680 		 * If neither is defined, and $(HOME)/.dmakerc does not exists,
681 		 * then print a message, and default to parallel mode.
682 		 */
683 #ifdef DISTRIBUTED
684 		MBSTOWCS(wcs_buffer, NOCATGETS("DMAKE_RCFILE"));
685 		dmake_name = GETNAME(wcs_buffer, FIND_LENGTH);
686 		MBSTOWCS(wcs_buffer, NOCATGETS("DMAKE_MODE"));
687 		dmake_name2 = GETNAME(wcs_buffer, FIND_LENGTH);
688 		if ((((prop = get_prop(dmake_name->prop, macro_prop)) == NULL) ||
689 		     ((dmake_value = prop->body.macro.value) == NULL)) &&
690 		    (((prop2 = get_prop(dmake_name2->prop, macro_prop)) == NULL) ||
691 		     ((dmake_value2 = prop2->body.macro.value) == NULL))) {
692 			Boolean empty_dmakerc = true;
693 			char *homedir = getenv(NOCATGETS("HOME"));
694 			if ((homedir != NULL) && (strlen(homedir) < (sizeof(def_dmakerc_path) - 16))) {
695 				sprintf(def_dmakerc_path, NOCATGETS("%s/.dmakerc"), homedir);
696 				if ((((statval = stat(def_dmakerc_path, &statbuf)) != 0) && (errno == ENOENT)) ||
697 					((statval == 0) && (statbuf.st_size == 0))) {
698 				} else {
699 					Avo_dmakerc	*rcfile = new Avo_dmakerc();
700 					Avo_err		*err = rcfile->read(def_dmakerc_path, NULL, TRUE);
701 					if (err) {
702 						fatal(err->str);
703 					}
704 					empty_dmakerc = rcfile->was_empty();
705 					delete rcfile;
706 				}
707 			}
708 			if (empty_dmakerc) {
709 				if (getenv(NOCATGETS("DMAKE_DEF_PRINTED")) == NULL) {
710 					putenv((char *)NOCATGETS("DMAKE_DEF_PRINTED=TRUE"));
711 					(void) fprintf(stdout, gettext("dmake: defaulting to parallel mode.\n"));
712 					(void) fprintf(stdout, gettext("See the man page dmake(1) for more information on setting up the .dmakerc file.\n"));
713 				}
714 				dmake_mode_type = parallel_mode;
715 				no_parallel = false;
716 			}
717 		}
718 #else
719 		if(dmake_mode_type == distributed_mode) {
720 			(void) fprintf(stdout, NOCATGETS("dmake: Distributed mode not implemented.\n"));
721 			(void) fprintf(stdout, NOCATGETS("       Defaulting to parallel mode.\n"));
722 			dmake_mode_type = parallel_mode;
723 			no_parallel = false;
724 		}
725 #endif	/* DISTRIBUTED */
726 	}
727     }
728 #endif
729 
730 #ifdef TEAMWARE_MAKE_CMN
731 	parallel_flag = true;
732 	/* XXX - This is a major hack for DMake/Licensing. */
733 	if (getenv(NOCATGETS("DMAKE_CHILD")) == NULL) {
734 		if (!avo_cli_search_license(argv[0], dmake_exit_callback, TRUE, dmake_message_callback)) {
735 			/*
736 			 * If the user can not get a TeamWare license,
737 			 * default to serial mode.
738 			 */
739 			dmake_mode_type = serial_mode;
740 			no_parallel = true;
741 		} else {
742 			putenv((char *)NOCATGETS("DMAKE_CHILD=TRUE"));
743 		}
744 		start_time = time(NULL);
745 		/*
746 		 * XXX - Hack to disable SIGALRM's from licensing library's
747 		 *       setitimer().
748 		 */
749 		value.it_interval.tv_sec = 0;
750 		value.it_interval.tv_usec = 0;
751 		value.it_value.tv_sec = 0;
752 		value.it_value.tv_usec = 0;
753 		(void) setitimer(ITIMER_REAL, &value, NULL);
754 	}
755 
756 //
757 // If dmake is running with -t option, set dmake_mode_type to serial.
758 // This is done because doname() calls touch_command() that runs serially.
759 // If we do not do that, maketool will have problems.
760 //
761 	if(touch) {
762 		dmake_mode_type = serial_mode;
763 		no_parallel = true;
764 	}
765 #else
766 #ifdef	PMAKE
767 	if (IS_EQUAL(argv_zero_base, NOCATGETS("dmake")) ||
768 	    dmake_max_jobs_specified) {
769 		parallel_flag = true;
770 	} else
771 #endif
772 		parallel_flag = false;
773 #ifdef	PMAKE
774 	/*
775 	 * If dmake is running with -t option, set dmake_mode_type to serial.
776 	 * This is done because doname() calls touch_command() that runs
777 	 * serially.
778 	 * If we do not do that, maketool will have problems.
779 	 */
780 	if (touch) {
781 		dmake_mode_type = serial_mode;
782 		no_parallel = true;
783 	}
784 #endif
785 #endif
786 
787 #if (defined(TEAMWARE_MAKE_CMN) || defined(PMAKE)) && defined(REDIRECT_ERR)
788 	/*
789 	 * Check whether stdout and stderr are physically same.
790 	 * This is in order to decide whether we need to redirect
791 	 * stderr separately from stdout.
792 	 * This check is performed only if __DMAKE_SEPARATE_STDERR
793 	 * is not set. This variable may be used in order to preserve
794 	 * the 'old' behaviour.
795 	 */
796 	out_err_same = true;
797 	char * dmake_sep_var = getenv(NOCATGETS("__DMAKE_SEPARATE_STDERR"));
798 	if (dmake_sep_var == NULL || (0 != strcasecmp(dmake_sep_var, NOCATGETS("NO")))) {
799 		struct stat stdout_stat;
800 		struct stat stderr_stat;
801 		if( (fstat(1, &stdout_stat) == 0)
802 		 && (fstat(2, &stderr_stat) == 0) )
803 		{
804 			if( (stdout_stat.st_dev != stderr_stat.st_dev)
805 			 || (stdout_stat.st_ino != stderr_stat.st_ino) )
806 			{
807 				out_err_same = false;
808 			}
809 		}
810 	}
811 #endif
812 
813 #ifdef DISTRIBUTED
814 	/*
815 	 * At this point, DMake should startup an rxm with any and all
816 	 * DMake command line options. Rxm will, among other things,
817 	 * read the rc file.
818 	 */
819 	if ((!list_all_targets) &&
820 	    (report_dependencies_level == 0) &&
821 	    (dmake_mode_type == distributed_mode)) {
822 		startup_rxm();
823 	}
824 #endif
825 
826 /*
827  *	Enable interrupt handler for alarms
828  */
829         (void) bsd_signal(SIGALRM, (SIG_PF)doalarm);
830 
831 /*
832  *	Check if make should report
833  */
834 	if (getenv(sunpro_dependencies->string_mb) != NULL) {
835 		FILE	*report_file;
836 
837 		report_dependency("");
838 		report_file = get_report_file();
839 		if ((report_file != NULL) && (report_file != (FILE*)-1)) {
840 			(void) fprintf(report_file, "\n");
841 		}
842 	}
843 
844 /*
845  *	Make sure SUNPRO_DEPENDENCIES is exported (or not) properly
846  *      and NSE_DEP.
847  */
848 	if (keep_state) {
849 		maybe_append_prop(sunpro_dependencies, macro_prop)->
850 		  body.macro.exported = true;
851 #ifdef NSE
852 		(void) setenv(NOCATGETS("NSE_DEP"), get_current_path());
853 #endif
854 	} else {
855 		maybe_append_prop(sunpro_dependencies, macro_prop)->
856 		  body.macro.exported = false;
857 	}
858 
859 	working_on_targets = true;
860 	if (trace_status) {
861 		dump_make_state();
862 		fclose(stdout);
863 		fclose(stderr);
864 		exit_status = 0;
865 		exit(0);
866 	}
867 	if (list_all_targets) {
868 		dump_target_list();
869 		fclose(stdout);
870 		fclose(stderr);
871 		exit_status = 0;
872 		exit(0);
873 	}
874 	trace_reader = false;
875 
876  	/*
877  	 * Set temp_file_directory to the directory the .make.state
878  	 * file is written to.
879  	 */
880  	if ((slash_ptr = strrchr(make_state->string_mb, (int) slash_char)) == NULL) {
881  		temp_file_directory = strdup(get_current_path());
882  	} else {
883  		*slash_ptr = (int) nul_char;
884  		(void) strcpy(make_state_dir, make_state->string_mb);
885  		*slash_ptr = (int) slash_char;
886 		   /* when there is only one slash and it's the first
887 		   ** character, make_state_dir should point to '/'.
888 		   */
889 		if(make_state_dir[0] == '\0') {
890 		   make_state_dir[0] = '/';
891 		   make_state_dir[1] = '\0';
892 		}
893  		if (make_state_dir[0] == (int) slash_char) {
894  			temp_file_directory = strdup(make_state_dir);
895  		} else {
896  			char	tmp_current_path2[MAXPATHLEN];
897 
898  			(void) sprintf(tmp_current_path2,
899  			               "%s/%s",
900  			               get_current_path(),
901  			               make_state_dir);
902  			temp_file_directory = strdup(tmp_current_path2);
903  		}
904  	}
905 
906 #ifdef DISTRIBUTED
907 	building_serial = false;
908 #endif
909 
910 	report_dir_enter_leave(true);
911 
912 	make_targets(argc, argv, parallel_flag);
913 
914 	report_dir_enter_leave(false);
915 	dir_enter_leave(false);
916 
917 #ifdef NSE
918         exit(nse_exit_status());
919 #else
920 	if (build_failed_ever_seen) {
921 		if (posix) {
922 			exit_status = 1;
923 		}
924 		exit(1);
925 	}
926 	exit_status = 0;
927 	exit(0);
928 #endif
929 	/* NOTREACHED */
930 }
931 
932 /*
933  * scan_dmake_compat_mode()
934  *
935  *	Called from main(), handles SUN_MAKE_COMPAT_MODE.
936  *
937  *	Parameters:
938  *		dmake_compat_mode_var	The SUN_MAKE_COMPAT_MODE= environ
939  *					or the -x SUN_MAKE_COMPAT_MODE=
940  *					argument.
941  *
942  *	Global variables used:
943  *		sunpro_compat
944  *		gnu_style
945  *		svr4
946  *		posix
947  */
948 static void
scan_dmake_compat_mode(char * dmake_compat_mode_var)949 scan_dmake_compat_mode(char *dmake_compat_mode_var)
950 {
951 	if (dmake_compat_mode_var != NULL) {
952 		sunpro_compat = true;
953 		if (0 == strcasecmp(dmake_compat_mode_var, NOCATGETS("GNU"))) {
954 			sunpro_compat = false;
955 			gnu_style = true;
956 			svr4 = false;
957 			posix = false;
958 		} else if (0 == strcasecmp(dmake_compat_mode_var,
959 							NOCATGETS("POSIX"))) {
960 			sunpro_compat = false;
961 			gnu_style = false;
962 			svr4 = false;
963 			posix = true;
964 		} else if (0 == strcasecmp(dmake_compat_mode_var,
965 							NOCATGETS("SUN"))) {
966 			sunpro_compat = true;
967 			gnu_style = false;
968 			svr4 = false;
969 			posix = false;
970 		} else if (0 == strcasecmp(dmake_compat_mode_var,
971 							NOCATGETS("SVR4"))) {
972 			sunpro_compat = false;
973 			gnu_style = false;
974 			svr4 = true;
975 			posix = false;
976 		}
977 		//svr4 = false;
978 		//posix = false;
979 	}
980 }
981 
982 /*
983  *	cleanup_after_exit()
984  *
985  *	Called from exit(), performs cleanup actions.
986  *
987  *	Parameters:
988  *		status		The argument exit() was called with
989  *		arg		Address of an argument vector to
990  *				cleanup_after_exit()
991  *
992  *	Global variables used:
993  *		command_changed	Set if we think .make.state should be rewritten
994  *		current_line	Is set we set commands_changed
995  *		do_not_exec_rule
996  *				True if -n flag on
997  *		done		The Name ".DONE", rule we run
998  *		keep_state	Set if .KEEP_STATE seen
999  *		parallel	True if building in parallel
1000  *		quest		If -q is on we do not run .DONE
1001  *		report_dependencies
1002  *				True if -P flag on
1003  *		running_list	List of parallel running processes
1004  *		temp_file_name	The temp file is removed, if any
1005  *		usage_tracking  Should have been constructed in main()
1006  *			        should destroyed just before exiting
1007  */
1008 #ifdef	HAVE_ATEXIT
1009 extern "C" void
cleanup_after_exit(void)1010 cleanup_after_exit(void)
1011 #else
1012 void cleanup_after_exit(int status, ...)
1013 #endif
1014 {
1015 	Running		rp;
1016 #ifdef NSE
1017 	char		push_cmd[NSE_TFS_PUSH_LEN + 3 +
1018 			         (MAXPATHLEN * MB_LEN_MAX) + 12];
1019 	char		*active;
1020 #endif
1021 
1022 extern long	getname_bytes_count;
1023 extern long	getname_names_count;
1024 extern long	getname_struct_count;
1025 extern long	freename_bytes_count;
1026 extern long	freename_names_count;
1027 extern long	freename_struct_count;
1028 extern long	other_alloc;
1029 
1030 extern long	env_alloc_num;
1031 extern long	env_alloc_bytes;
1032 
1033 
1034 #ifdef DMAKE_STATISTICS
1035 if(getname_stat) {
1036 	printf(NOCATGETS(">>> Getname statistics:\n"));
1037 	printf(NOCATGETS("  Allocated:\n"));
1038 	printf(NOCATGETS("        Names: %ld\n"), getname_names_count);
1039 	printf(NOCATGETS("      Strings: %ld Kb (%ld bytes)\n"), getname_bytes_count/1000, getname_bytes_count);
1040 	printf(NOCATGETS("      Structs: %ld Kb (%ld bytes)\n"), getname_struct_count/1000, getname_struct_count);
1041 	printf(NOCATGETS("  Total bytes: %ld Kb (%ld bytes)\n"), getname_struct_count/1000 + getname_bytes_count/1000, getname_struct_count + getname_bytes_count);
1042 
1043 	printf(NOCATGETS("\n  Unallocated: %ld\n"), freename_names_count);
1044 	printf(NOCATGETS("        Names: %ld\n"), freename_names_count);
1045 	printf(NOCATGETS("      Strings: %ld Kb (%ld bytes)\n"), freename_bytes_count/1000, freename_bytes_count);
1046 	printf(NOCATGETS("      Structs: %ld Kb (%ld bytes)\n"), freename_struct_count/1000, freename_struct_count);
1047 	printf(NOCATGETS("  Total bytes: %ld Kb (%ld bytes)\n"), freename_struct_count/1000 + freename_bytes_count/1000, freename_struct_count + freename_bytes_count);
1048 
1049 	printf(NOCATGETS("\n  Total used: %ld Kb (%ld bytes)\n"), (getname_struct_count/1000 + getname_bytes_count/1000) - (freename_struct_count/1000 + freename_bytes_count/1000), (getname_struct_count + getname_bytes_count) - (freename_struct_count + freename_bytes_count));
1050 
1051 	printf(NOCATGETS("\n>>> Other:\n"));
1052 	printf(
1053 		NOCATGETS("       Env (%ld): %ld Kb (%ld bytes)\n"),
1054 		env_alloc_num,
1055 		env_alloc_bytes/1000,
1056 		env_alloc_bytes
1057 	);
1058 
1059 }
1060 #endif
1061 
1062 /*
1063 #ifdef DISTRIBUTED
1064     if (get_parent() == TRUE) {
1065 #endif
1066  */
1067 
1068 	parallel = false;
1069 #ifdef SUN5_0
1070 	/* If we used the SVR4_MAKE, don't build .DONE or .FAILED */
1071 	if (!getenv(USE_SVR4_MAKE)){
1072 #endif
1073 	    /* Build the target .DONE or .FAILED if we caught an error */
1074 	    if (!quest && !list_all_targets) {
1075 		Name		failed_name;
1076 
1077 		MBSTOWCS(wcs_buffer, NOCATGETS(".FAILED"));
1078 		failed_name = GETNAME(wcs_buffer, FIND_LENGTH);
1079 #ifdef	HAVE_ATEXIT
1080 		if ((exit_status != 0) && (failed_name->prop != NULL)) {
1081 #else
1082 		if ((status != 0) && (failed_name->prop != NULL)) {
1083 #endif
1084 #if defined(TEAMWARE_MAKE_CMN) || defined(PMAKE)
1085 			/*
1086 			 * [tolik] switch DMake to serial mode
1087 			 */
1088 			dmake_mode_type = serial_mode;
1089 			no_parallel = true;
1090 #endif
1091 			(void) doname(failed_name, false, true);
1092 		} else {
1093 		    if (!trace_status) {
1094 #if defined(TEAMWARE_MAKE_CMN) || defined(PMAKE)
1095 			/*
1096 			 * Switch DMake to serial mode
1097 			 */
1098 			dmake_mode_type = serial_mode;
1099 			no_parallel = true;
1100 #endif
1101 			(void) doname(done, false, true);
1102 		    }
1103 		}
1104 	    }
1105 #ifdef SUN5_0
1106 	}
1107 #endif
1108 	/*
1109 	 * Remove the temp file utilities report dependencies thru if it
1110 	 * is still around
1111 	 */
1112 	if (temp_file_name != NULL) {
1113 		(void) unlink(temp_file_name->string_mb);
1114 	}
1115 	/*
1116 	 * Do not save the current command in .make.state if make
1117 	 * was interrupted.
1118 	 */
1119 	if (current_line != NULL) {
1120 		command_changed = true;
1121 		current_line->body.line.command_used = NULL;
1122 	}
1123 	/*
1124 	 * For each parallel build process running, remove the temp files
1125 	 * and zap the command line so it won't be put in .make.state
1126 	 */
1127 	for (rp = running_list; rp != NULL; rp = rp->next) {
1128 		if (rp->temp_file != NULL) {
1129 			(void) unlink(rp->temp_file->string_mb);
1130 		}
1131 		if (rp->stdout_file != NULL) {
1132 			(void) unlink(rp->stdout_file);
1133 			retmem_mb(rp->stdout_file);
1134 			rp->stdout_file = NULL;
1135 		}
1136 		if (rp->stderr_file != NULL) {
1137 			(void) unlink(rp->stderr_file);
1138 			retmem_mb(rp->stderr_file);
1139 			rp->stderr_file = NULL;
1140 		}
1141 		command_changed = true;
1142 /*
1143 		line = get_prop(rp->target->prop, line_prop);
1144 		if (line != NULL) {
1145 			line->body.line.command_used = NULL;
1146 		}
1147  */
1148 	}
1149 	/* Remove the statefile lock file if the file has been locked */
1150 	if ((make_state_lockfile != NULL) && (make_state_locked)) {
1151 		(void) unlink(make_state_lockfile);
1152 		make_state_lockfile = NULL;
1153 		make_state_locked = false;
1154 	}
1155 	/* Write .make.state */
1156 	write_state_file(1, (Boolean) 1);
1157 
1158 #ifdef TEAMWARE_MAKE_CMN
1159 	// Deleting the usage tracking object sends the usage mail
1160 #ifdef USE_DMS_CCR
1161 	//usageTracking->setExitStatus(exit_status, NULL);
1162 	//delete usageTracking;
1163 #else
1164 	cleanup->set_exit_status(exit_status);
1165 	delete cleanup;
1166 #endif
1167 #endif
1168 
1169 #ifdef NSE
1170         /* If running inside an activated environment, push the */
1171 	/* .nse_depinfo file (if written) */
1172 	active = getenv(NSE_VARIANT_ENV);
1173 	if (keep_state &&
1174 	    (active != NULL) &&
1175 	    !IS_EQUAL(active, NSE_RT_SOURCE_NAME) &&
1176 	    !do_not_exec_rule &&
1177 	    (report_dependencies_level == 0)) {
1178 		(void) sprintf(push_cmd,
1179 			       "%s %s/%s",
1180 			       NSE_TFS_PUSH,
1181 			       get_current_path(),
1182 			       NSE_DEPINFO);
1183 		(void) system(push_cmd);
1184 	}
1185 #endif
1186 
1187 /*
1188 #ifdef DISTRIBUTED
1189     }
1190 #endif
1191  */
1192 
1193 #if (defined(TEAMWARE_MAKE_CMN) || defined(PMAKE)) && \
1194     defined (MAXJOBS_ADJUST_RFE4694000)
1195 	job_adjust_fini();
1196 #endif
1197 
1198 #ifdef DISTRIBUTED
1199 	if (rxmPid > 0) {
1200 		// Tell rxm to exit by sending it an Avo_AcknowledgeMsg
1201 		Avo_AcknowledgeMsg acknowledgeMsg;
1202 		RWCollectable *msg = (RWCollectable *)&acknowledgeMsg;
1203 
1204 		int xdrResult = xdr(&xdrs_out, msg);
1205 
1206 		if (xdrResult) {
1207 			fflush(dmake_ofp);
1208 		} else {
1209 /*
1210 			fatal(gettext("couldn't tell rxm to exit"));
1211  */
1212 			kill(rxmPid, SIGTERM);
1213 		}
1214 
1215 		waitpid(rxmPid, NULL, 0);
1216 		rxmPid = 0;
1217 	}
1218 #endif
1219 }
1220 
1221 /*
1222  *	handle_interrupt()
1223  *
1224  *	This is where C-C traps are caught.
1225  *
1226  *	Parameters:
1227  *
1228  *	Global variables used (except DMake 1.0):
1229  *		current_target		Sometimes the current target is removed
1230  *		do_not_exec_rule	But not if -n is on
1231  *		quest			or -q
1232  *		running_list		List of parallel running processes
1233  *		touch			Current target is not removed if -t on
1234  */
1235 void
1236 handle_interrupt(int)
1237 {
1238 	Property		member;
1239 	Running			rp;
1240 
1241 	(void) fflush(stdout);
1242 #ifdef DISTRIBUTED
1243 	if (rxmPid > 0) {
1244 		// Tell rxm to exit by sending it an Avo_AcknowledgeMsg
1245 		Avo_AcknowledgeMsg acknowledgeMsg;
1246 		RWCollectable *msg = (RWCollectable *)&acknowledgeMsg;
1247 
1248 		int xdrResult = xdr(&xdrs_out, msg);
1249 
1250 		if (xdrResult) {
1251 			fflush(dmake_ofp);
1252 		} else {
1253 			kill(rxmPid, SIGTERM);
1254 			rxmPid = 0;
1255 		}
1256 	}
1257 #endif
1258 	if (childPid > 0) {
1259 		kill(childPid, SIGTERM);
1260 		childPid = -1;
1261 	}
1262 	for (rp = running_list; rp != NULL; rp = rp->next) {
1263 		if (rp->state != build_running) {
1264 			continue;
1265 		}
1266 		if (rp->pid > 0) {
1267 			kill(rp->pid, SIGTERM);
1268 			rp->pid = -1;
1269 		}
1270 	}
1271 	if (getpid() == getpgrp()) {
1272 #ifdef	SUN5_0
1273 		bsd_signal(SIGTERM, SIG_IGN);
1274 #else
1275 		bsd_signal(SIGTERM, (void (*)(int)) SIG_IGN);
1276 #endif
1277 		kill (-getpid(), SIGTERM);
1278 	}
1279 #if defined(TEAMWARE_MAKE_CMN) || defined(PMAKE)
1280 	/* Clean up all parallel/distributed children already finished */
1281         finish_children(false);
1282 #endif
1283 
1284 	/* Make sure the processes running under us terminate first */
1285 
1286 	while (wait((WAIT_T *) NULL) != -1);
1287 	/* Delete the current targets unless they are precious or phony */
1288 	if ((current_target != NULL) &&
1289 	    current_target->is_member &&
1290 	    ((member = get_prop(current_target->prop, member_prop)) != NULL)) {
1291 		current_target = member->body.member.library;
1292 	}
1293 	if (!do_not_exec_rule &&
1294 	    !touch &&
1295 	    !quest &&
1296 	    (current_target != NULL) &&
1297 	    !(current_target->stat.is_precious || all_precious ||
1298 	    current_target->stat.is_phony)) {
1299 
1300 /* BID_1030811 */
1301 /* azv 16 Oct 95 */
1302 		current_target->stat.time = file_no_time;
1303 
1304 		if (exists(current_target) != file_doesnt_exist) {
1305 			(void) fprintf(stderr,
1306 				       "\n*** %s ",
1307 				       current_target->string_mb);
1308 			if (current_target->stat.is_dir) {
1309 				(void) fprintf(stderr,
1310 					       gettext("not removed.\n"));
1311 			} else if (unlink(current_target->string_mb) == 0) {
1312 				(void) fprintf(stderr,
1313 					       gettext("removed.\n"));
1314 			} else {
1315 				(void) fprintf(stderr,
1316 					       gettext("could not be removed: %s.\n"),
1317 					       errmsg(errno));
1318 			}
1319 		}
1320 	}
1321 	for (rp = running_list; rp != NULL; rp = rp->next) {
1322 		if (rp->state != build_running) {
1323 			continue;
1324 		}
1325 		if (rp->target->is_member &&
1326 		    ((member = get_prop(rp->target->prop, member_prop)) !=
1327 		     NULL)) {
1328 			rp->target = member->body.member.library;
1329 		}
1330 		if (!do_not_exec_rule &&
1331 		    !touch &&
1332 		    !quest &&
1333 		    !(rp->target->stat.is_precious || all_precious ||
1334 		    rp->target->stat.is_phony)) {
1335 
1336 			rp->target->stat.time = file_no_time;
1337 			if (exists(rp->target) != file_doesnt_exist) {
1338 				(void) fprintf(stderr,
1339 					       "\n*** %s ",
1340 					       rp->target->string_mb);
1341 				if (rp->target->stat.is_dir) {
1342 					(void) fprintf(stderr,
1343 						       gettext("not removed.\n"));
1344 				} else if (unlink(rp->target->string_mb) == 0) {
1345 					(void) fprintf(stderr,
1346 						       gettext("removed.\n"));
1347 				} else {
1348 					(void) fprintf(stderr,
1349 						       gettext("could not be removed: %s.\n"),
1350 						       errmsg(errno));
1351 				}
1352 			}
1353 		}
1354 	}
1355 
1356 #ifdef SGE_SUPPORT
1357 	/* Remove SGE script file */
1358 	if (grid) {
1359 		unlink(script_file);
1360 	}
1361 #endif
1362 
1363 	/* Have we locked .make.state or .nse_depinfo? */
1364 	if ((make_state_lockfile != NULL) && (make_state_locked)) {
1365 		unlink(make_state_lockfile);
1366 		make_state_lockfile = NULL;
1367 		make_state_locked = false;
1368 	}
1369 #ifdef NSE
1370 	if ((nse_depinfo_lockfile[0] != '\0') && (nse_depinfo_locked)) {
1371 		unlink(nse_depinfo_lockfile);
1372 		nse_depinfo_lockfile[0] = '\0';
1373 		nse_depinfo_locked = false;
1374 	}
1375 #endif
1376 	/*
1377 	 * Re-read .make.state file (it might be changed by recursive make)
1378 	 */
1379 	check_state(NULL);
1380 
1381 	report_dir_enter_leave(false);
1382 
1383 	exit_status = 2;
1384 	exit(2);
1385 }
1386 
1387 /*
1388  *	doalarm(sig, ...)
1389  *
1390  *	Handle the alarm interrupt but do nothing.  Side effect is to
1391  *	cause return from wait3.
1392  *
1393  *	Parameters:
1394  *		sig
1395  *
1396  *	Global variables used:
1397  */
1398 /*ARGSUSED*/
1399 static void
1400 doalarm(int)
1401 {
1402 	return;
1403 }
1404 
1405 
1406 /*
1407  *	read_command_options(argc, argv)
1408  *
1409  *	Scan the cmd line options and process the ones that start with "-"
1410  *
1411  *	Return value:
1412  *				-M argument, if any
1413  *
1414  *	Parameters:
1415  *		argc		You know what this is
1416  *		argv		You know what this is
1417  *
1418  *	Global variables used:
1419  */
1420 static void
1421 read_command_options(register int argc, register char **argv)
1422 {
1423 	register int		ch;
1424 	int			current_optind = 1;
1425 	int			last_optind_with_double_hyphen = 0;
1426 	int			last_optind;
1427 	int			last_current_optind;
1428 	register int		i;
1429 	register int		j;
1430 	register int		k;
1431 	register int		makefile_next = 0; /*
1432 						    * flag to note options:
1433 						    * -c, f, g, j, m, o
1434 						    */
1435 	const char		*tptr;
1436 	const char		*CMD_OPTS;
1437 
1438 	extern char		*optarg;
1439 	extern int		optind, opterr, optopt;
1440 
1441 #define SUNPRO_CMD_OPTS	"-~aBbC:c:Ddef:g:ij:K:kM:m:NnO:o:PpqRrSsTtuVvwx:"
1442 
1443 #if defined(TEAMWARE_MAKE_CMN) || defined(PMAKE)
1444 #	define SVR4_CMD_OPTS   "-C:c:ef:g:ij:km:nO:o:pqrsTtVv"
1445 #else
1446 #	define SVR4_CMD_OPTS   "-C:ef:iknpqrstV"
1447 #endif
1448 
1449 	/*
1450 	 * Added V in SVR4_CMD_OPTS also, which is going to be a hidden
1451 	 * option, just to make sure that the getopt doesn't fail when some
1452 	 * users leave their USE_SVR4_MAKE set and try to use the makefiles
1453 	 * that are designed to issue commands like $(MAKE) -V. Anyway it
1454 	 * sets the same flag but ensures that getopt doesn't fail.
1455 	 */
1456 
1457 	opterr = 0;
1458 	optind = 1;
1459 	while (1) {
1460 		last_optind=optind;			/* Save optind and current_optind values */
1461 		last_current_optind=current_optind;	/* in case we have to repeat this round. */
1462 		if (svr4) {
1463 			CMD_OPTS=SVR4_CMD_OPTS;
1464 			ch = getopt(argc, argv, SVR4_CMD_OPTS);
1465 		} else {
1466 			CMD_OPTS=SUNPRO_CMD_OPTS;
1467 			ch = getopt(argc, argv, SUNPRO_CMD_OPTS);
1468 		}
1469 		if (ch == EOF) {
1470 			if(optind < argc) {
1471 				/*
1472 				 * Fixing bug 4102537:
1473 				 *    Strange behaviour of command make using -- option.
1474 				 * Not all argv have been processed
1475 				 * Skip non-flag argv and continue processing.
1476 				 */
1477 				optind++;
1478 				current_optind++;
1479 				continue;
1480 			} else {
1481 				break;
1482 			}
1483 
1484 		}
1485 		if (ch == '?') {
1486 		 	if (optopt == '-') {
1487 				/* Bug 5060758: getopt() changed behavior (s10_60),
1488 				 * and now we have to deal with cases when options
1489 				 * with double hyphen appear here, from -$(MAKEFLAGS)
1490 				 */
1491 				i = current_optind;
1492 				if (argv[i][0] == '-') {
1493 				  if (argv[i][1] == '-') {
1494 				    if (argv[i][2] != '\0') {
1495 				      /* Check if this option is allowed */
1496 				      tptr = strchr(CMD_OPTS, argv[i][2]);
1497 				      if (tptr) {
1498 				        if (last_optind_with_double_hyphen != current_optind) {
1499 				          /* This is first time we are trying to fix "--"
1500 				           * problem with this option. If we come here second
1501 				           * time, we will go to fatal error.
1502 				           */
1503 				          last_optind_with_double_hyphen = current_optind;
1504 
1505 				          /* Eliminate first hyphen character */
1506 				          for (j=0; argv[i][j] != '\0'; j++) {
1507 				            argv[i][j] = argv[i][j+1];
1508 				          }
1509 
1510 				          /* Repeat the processing of this argument */
1511 				          optind=last_optind;
1512 				          current_optind=last_current_optind;
1513 				          continue;
1514 				        }
1515 				      }
1516 				    }
1517 				  }
1518 				}
1519 			}
1520 		}
1521 
1522 		if (ch == '?') {
1523 			if (svr4) {
1524 #if defined(TEAMWARE_MAKE_CMN) || defined(PMAKE)
1525 				fprintf(stderr,
1526 					gettext("Usage : dmake [ -f makefile ][ -c dmake_rcfile ][ -g dmake_group ][ -C directory ]\n"));
1527 				fprintf(stderr,
1528 					gettext("              [ -j dmake_max_jobs ][ -m dmake_mode ][ -o dmake_odir ]...\n"));
1529 				fprintf(stderr,
1530 					gettext("              [ -e ][ -i ][ -k ][ -n ][ -p ][ -q ][ -r ][ -s ][ -t ][ -v ]\n"));
1531 #else
1532 				fprintf(stderr,
1533 					gettext("Usage : make [ -f makefile ]... [ -e ][ -i ][ -k ][ -n ][ -p ][ -q ][ -r ]\n"));
1534 				fprintf(stderr,
1535 					gettext("             [ -s ][ -t ]\n"));
1536 #endif
1537 				tptr = strchr(SVR4_CMD_OPTS, optopt);
1538 			} else {
1539 #if defined(TEAMWARE_MAKE_CMN) || defined(PMAKE)
1540 				if (IS_EQUAL(argv_zero_base, NOCATGETS("dmake"))) {
1541 				fprintf(stderr,
1542 					gettext("Usage : dmake [ -f makefile ][ -c dmake_rcfile ][ -g dmake_group ][ -C directory ]\n"));
1543 				fprintf(stderr,
1544 					gettext("              [ -j dmake_max_jobs ][ -K statefile ][ -m dmake_mode ][ -x MODE_NAME=VALUE ][ -o dmake_odir ]...\n"));
1545 				fprintf(stderr,
1546 					gettext("              [ -a] [ -d ][ -dd ][ -D ][ -DD ]\n"));
1547 				fprintf(stderr,
1548 					gettext("              [ -e ][ -i ][ -k ][ -n ][ -p ][ -P ][ -u ][ -w ]\n"));
1549 				fprintf(stderr,
1550 					gettext("              [ -q ][ -r ][ -s ][ -S ][ -t ][ -v ][ -V ][ target... ][ macro=value... ][ \"macro +=value\"... ]\n"));
1551 				} else
1552 #endif
1553 				{
1554 				fprintf(stderr,
1555 					gettext("Usage : make [ -f makefile ][ -K statefile ]...\n"));
1556 				fprintf(stderr,
1557 					gettext("             [ -a ][ -d ][ -dd ][ -D ][ -DD ] [ -C directory]\n"));
1558 				fprintf(stderr,
1559 					gettext("             [ -e ][ -i ][ -k ][ -n ][ -p ][ -P ][ -q ][ -r ][ -s ][ -S ][ -t ]\n"));
1560 				fprintf(stderr,
1561 					gettext("             [ -u ][ -w ][ -V ][ target... ][ macro=value... ][ \"macro +=value\"... ]\n"));
1562 				}
1563 				tptr = strchr(SUNPRO_CMD_OPTS, optopt);
1564 			}
1565 			if (!tptr) {
1566 				fatal(gettext("Unknown option `-%c'"), optopt);
1567 			} else {
1568 				fatal(gettext("Missing argument after `-%c'"), optopt);
1569 			}
1570 		}
1571 
1572 		makefile_next |= parse_command_option(ch);
1573 		/*
1574 		 * If we're done processing all of the options of
1575 		 * ONE argument string...
1576 		 */
1577 		if (current_optind < optind) {
1578 			i = current_optind;
1579 			k = 0;
1580 			/* If there's an argument for an option... */
1581 			if ((optind - current_optind) > 1) {
1582 				k = i + 1;
1583 			}
1584 			switch (makefile_next) {
1585 			case 0:
1586 				argv[i] = NULL;
1587 				/* This shouldn't happen */
1588 				if (k) {
1589 					argv[k] = NULL;
1590 				}
1591 				break;
1592 			case 1:	/* -f seen */
1593 				argv[i] = (char *)NOCATGETS("-f");
1594 				break;
1595 			case 2:	/* -c seen */
1596 				argv[i] = (char *)NOCATGETS("-c");
1597 #ifndef TEAMWARE_MAKE_CMN
1598 				warning(gettext("Ignoring DistributedMake -c option"));
1599 #endif
1600 				break;
1601 			case 4:	/* -g seen */
1602 				argv[i] = (char *)NOCATGETS("-g");
1603 #ifndef TEAMWARE_MAKE_CMN
1604 				warning(gettext("Ignoring DistributedMake -g option"));
1605 #endif
1606 				break;
1607 			case 8:	/* -j seen */
1608 				if (sunpro_compat)	/* Disallow -j5 */
1609 					argv[i] = (char *)NOCATGETS("-j");
1610 #if !defined(TEAMWARE_MAKE_CMN) && !defined(PMAKE)
1611 				warning(gettext("Ignoring DistributedMake -j option"));
1612 #endif
1613 				break;
1614 			case 16: /* -M seen */
1615 				argv[i] = (char *)NOCATGETS("-M");
1616 #ifndef TEAMWARE_MAKE_CMN
1617 				warning(gettext("Ignoring ParallelMake -M option"));
1618 #endif
1619 				break;
1620 			case 32: /* -m seen */
1621 				argv[i] = (char *)NOCATGETS("-m");
1622 #if !defined(TEAMWARE_MAKE_CMN) && !defined(PMAKE)
1623 				warning(gettext("Ignoring DistributedMake -m option"));
1624 #endif
1625 				break;
1626 #ifndef PARALLEL
1627 			case 128: /* -O seen */
1628 				argv[i] = (char *)NOCATGETS("-O");
1629 				break;
1630 #endif
1631 			case 256: /* -K seen */
1632 				argv[i] = (char *)NOCATGETS("-K");
1633 			        break;
1634 			case 512:	/* -o seen */
1635 				argv[i] = (char *)NOCATGETS("-o");
1636 #ifndef TEAMWARE_MAKE_CMN
1637 				warning(gettext("Ignoring DistributedMake -o option"));
1638 #endif
1639 				break;
1640 			case 1024: /* -x seen */
1641 				argv[i] = (char *)NOCATGETS("-x");
1642 				if (argv[i+1] &&
1643 				    strstr(argv[i+1],
1644 					NOCATGETS("SUN_MAKE_COMPAT_MODE=")) ==
1645 								argv[i+1]) {
1646 					if (dmake_add_mode_specified)
1647 						dmake_compat_value = argv[i+1];
1648 					else
1649 						dmake_compat_value = NULL;
1650 				}
1651 #if !defined(TEAMWARE_MAKE_CMN) && !defined(PMAKE)
1652 				warning(gettext("Ignoring DistributedMake -x option"));
1653 #endif
1654 				break;
1655 			case 2048: {
1656 				char	*ap = argv[i+1];
1657 
1658 				if (argv[i][2])		/* e.g. -Cdir */
1659 					ap = &argv[i][2];
1660 				if (ap == NULL) {
1661 					fatal(gettext("No argument after -C flag"));
1662 				}
1663 				if (chdir(ap) != 0) {
1664 					fatal(gettext("Failed to change to directory %s: %s"),
1665 					    ap, strerror(errno));
1666 				}
1667 				current_path_reset = true;
1668 				}
1669 				break;
1670 			default: /* > 1 of -c, f, g, j, K, M, m, O, o, x seen */
1671 				fatal(gettext("Illegal command line. More than one option requiring\nan argument given in the same argument group"));
1672 			}
1673 
1674 			makefile_next = 0;
1675 			current_optind = optind;
1676 		}
1677 	}
1678 }
1679 
1680 static void
1681 quote_str(char *str, char *qstr)
1682 {
1683 	char		*to;
1684 	char		*from;
1685 
1686 	to = qstr;
1687 	for (from = str; *from; from++) {
1688 		switch (*from) {
1689 		case ';':	/* End of command */
1690 		case '(':	/* Start group */
1691 		case ')':	/* End group */
1692 		case '{':	/* Start group */
1693 		case '}':	/* End group */
1694 		case '[':	/* Reg expr - any of a set of chars */
1695 		case ']':	/* End of set of chars */
1696 		case '|':	/* Pipe or logical-or */
1697 		case '^':	/* Old-fashioned pipe */
1698 		case '&':	/* Background or logical-and */
1699 		case '<':	/* Redirect stdin */
1700 		case '>':	/* Redirect stdout */
1701 		case '*':	/* Reg expr - any sequence of chars */
1702 		case '?':	/* Reg expr - any single char */
1703 		case '$':	/* Variable substitution */
1704 		case '\'':	/* Singe quote - turn off all magic */
1705 		case '"':	/* Double quote - span whitespace */
1706 		case '`':	/* Backquote - run a command */
1707 		case '#':	/* Comment */
1708 		case ' ':	/* Space (for MACRO=value1 value2  */
1709 		case '\\':	/* Escape char - turn off magic of next char */
1710 			*to++ = '\\';
1711 			break;
1712 
1713 		default:
1714 			break;
1715 		}
1716 		*to++ = *from;
1717 	}
1718 	*to = '\0';
1719 }
1720 
1721 static void
1722 unquote_str(char *str, char *qstr)
1723 {
1724 	char		*to;
1725 	char		*from;
1726 
1727 	to = qstr;
1728 	for (from = str; *from; from++) {
1729 		if (*from == '\\' && from[1] != '\0') {
1730 			from++;
1731 		}
1732 		*to++ = *from;
1733 	}
1734 	*to = '\0';
1735 }
1736 
1737 /*
1738  * Convert the MAKEFLAGS string value into a vector of char *, similar
1739  * to argv.
1740  */
1741 static void
1742 setup_makeflags_argv()
1743 {
1744 	char		*cp;
1745 	char		*cp1;
1746 	char		*cp2;
1747 	char		*cp3;
1748 	char		*cp_orig;
1749 	Boolean		add_hyphen;
1750 	int		i;
1751 	char		tmp_char;
1752 
1753 	mf_argc = 1;
1754 	cp = getenv(makeflags->string_mb);
1755 	cp_orig = cp;
1756 
1757 	if (cp) {
1758 		/*
1759 		 * If new MAKEFLAGS format, no need to add hyphen.
1760 		 * If old MAKEFLAGS format, add hyphen before flags.
1761 		 */
1762 
1763 		if ((strchr(cp, (int) hyphen_char) != NULL) ||
1764 		    (strchr(cp, (int) equal_char) != NULL)) {
1765 
1766 			/* New MAKEFLAGS format */
1767 
1768 			add_hyphen = false;
1769 #ifdef ADDFIX5060758
1770 			/* Check if MAKEFLAGS value begins with multiple
1771 			 * hyphen characters, and remove all duplicates.
1772 			 * Usually it happens when the next command is
1773 			 * used: $(MAKE) -$(MAKEFLAGS)
1774 			 * This is a workaround for BugID 5060758.
1775 			 */
1776 			while (*cp) {
1777 				if (*cp != (int) hyphen_char) {
1778 					break;
1779 				}
1780 				cp++;
1781 				if (*cp == (int) hyphen_char) {
1782 					/* There are two hyphens. Skip one */
1783 					cp_orig = cp;
1784 					cp++;
1785 				}
1786 				if (!(*cp)) {
1787 					/* There are hyphens only. Skip all */
1788 					cp_orig = cp;
1789 					break;
1790 				}
1791 			}
1792 #endif
1793 		} else {
1794 
1795 			/* Old MAKEFLAGS format */
1796 
1797 			add_hyphen = true;
1798 		}
1799 	}
1800 
1801 	/* Find the number of arguments in MAKEFLAGS */
1802 	while (cp && *cp) {
1803 		/* Skip white spaces */
1804 		while (cp && *cp && isspace(*cp)) {
1805 			cp++;
1806 		}
1807 		if (cp && *cp) {
1808 			/* Increment arg count */
1809 			mf_argc++;
1810 			/* Go to next white space */
1811 			while (cp && *cp && !isspace(*cp)) {
1812 				if(*cp == (int) backslash_char) {
1813 					cp++;
1814 				}
1815 				cp++;
1816 			}
1817 		}
1818 	}
1819 	/* Allocate memory for the new MAKEFLAGS argv */
1820 	mf_argv = (char **) malloc((mf_argc + 1) * sizeof(char *));
1821 	mf_argv[0] = (char *)NOCATGETS("MAKEFLAGS");
1822 	/*
1823 	 * Convert the MAKEFLAGS string value into a vector of char *,
1824 	 * similar to argv.
1825 	 */
1826 	cp = cp_orig;
1827 	for (i = 1; i < mf_argc; i++) {
1828 		/* Skip white spaces */
1829 		while (cp && *cp && isspace(*cp)) {
1830 			cp++;
1831 		}
1832 		if (cp && *cp) {
1833 			cp_orig = cp;
1834 			/* Go to next white space */
1835 			while (cp && *cp && !isspace(*cp)) {
1836 				if(*cp == (int) backslash_char) {
1837 					cp++;
1838 				}
1839 				cp++;
1840 			}
1841 			tmp_char = *cp;
1842 			*cp = (int) nul_char;
1843 			if (add_hyphen) {
1844 				mf_argv[i] = getmem(2 + strlen(cp_orig));
1845 				mf_argv[i][0] = '\0';
1846 				(void) strcat(mf_argv[i], "-");
1847 				// (void) strcat(mf_argv[i], cp_orig);
1848 				unquote_str(cp_orig, mf_argv[i]+1);
1849 			} else {
1850 				mf_argv[i] = getmem(2 + strlen(cp_orig));
1851 				//mf_argv[i] = strdup(cp_orig);
1852 				unquote_str(cp_orig, mf_argv[i]);
1853 			}
1854 			*cp = tmp_char;
1855 		} else {
1856 			mf_argv[i] = NULL;
1857 		}
1858 	}
1859 	mf_argv[i] = NULL;
1860 
1861 	for (i = 1; i < mf_argc; i++) {
1862 		if (strncmp(mf_argv[i], NOCATGETS("-C"), 2) == 0) {
1863 			int	j = i;
1864 
1865 			/*
1866 			 * Ignore -C and argument.
1867 			 */
1868 			if (mf_argv[i][2]) {
1869 				j += 1;
1870 				mf_argc -= 1;
1871 			} else {
1872 				j += 2;
1873 				mf_argc -= 2;
1874 			}
1875 			for ( ; i <= mf_argc; i++, j++)
1876 				mf_argv[i] = mf_argv[j];
1877 		}
1878 	}
1879 }
1880 
1881 /*
1882  *	parse_command_option(ch)
1883  *
1884  *	Parse make command line options.
1885  *
1886  *	Return value:
1887  *				Indicates if any -f -c or -M were seen
1888  *
1889  *	Parameters:
1890  *		ch		The character to parse
1891  *
1892  *	Static variables used:
1893  *		dmake_group_specified	Set for make -g
1894  *		dmake_max_jobs_specified	Set for make -j
1895  *		dmake_mode_specified	Set for make -m
1896  *		dmake_add_mode_specified	Set for make -x
1897  *		dmake_compat_mode_specified	Set for make -x SUN_MAKE_COMPAT_MODE=
1898  *		dmake_output_mode_specified	Set for make -x DMAKE_OUTPUT_MODE=
1899  *		dmake_odir_specified	Set for make -o
1900  *		dmake_rcfile_specified	Set for make -c
1901  *		env_wins		Set for make -e
1902  *		ignore_default_mk	Set for make -r
1903  *		trace_status		Set for make -p
1904  *
1905  *	Global variables used:
1906  *		.make.state path & name set for make -K
1907  *		continue_after_error	Set for make -k
1908  *		debug_level		Set for make -d
1909  *		do_not_exec_rule	Set for make -n
1910  *		filter_stderr		Set for make -X
1911  *		ignore_errors_all	Set for make -i
1912  *		no_parallel		Set for make -R
1913  *		quest			Set for make -q
1914  *		read_trace_level	Set for make -D
1915  *		report_dependencies	Set for make -P
1916  *		send_mtool_msgs		Set for make -K
1917  *		silent_all		Set for make -s
1918  *		touch			Set for make -t
1919  */
1920 static int
1921 parse_command_option(register char ch)
1922 {
1923 	static int		invert_next = 0;
1924 	int			invert_this = invert_next;
1925 
1926 	invert_next = 0;
1927 	switch (ch) {
1928 	case '-':			 /* Ignore "--" */
1929 		return 0;
1930 	case '~':			 /* Invert next option */
1931 		invert_next = 1;
1932 		return 0;
1933 #ifdef	DO_ARCHCONF
1934 	case 'a':			 /* Do not set up uname, ... vars */
1935 		if (invert_this) {
1936 			no_archconf = false;
1937 		} else {
1938 			no_archconf = true;
1939 		}
1940 		return 0;
1941 #endif
1942 	case 'B':			 /* Obsolete */
1943 		return 0;
1944 	case 'b':			 /* Obsolete */
1945 		return 0;
1946 	case 'c':			 /* Read alternative dmakerc file */
1947 		if (invert_this) {
1948 			dmake_rcfile_specified = false;
1949 		} else {
1950 			dmake_rcfile_specified = true;
1951 		}
1952 		return 2;
1953 	case 'C':			/* Change directory */
1954 		return 2048;
1955 	case 'D':			 /* Show lines read */
1956 		if (invert_this) {
1957 			read_trace_level--;
1958 		} else {
1959 			read_trace_level++;
1960 		}
1961 		return 0;
1962 	case 'd':			 /* Debug flag */
1963 		if (invert_this) {
1964 			debug_level--;
1965 		} else {
1966 #if defined( HP_UX) || defined(linux)
1967 		      if (debug_level < 2)  /* Fixes a bug on HP-UX */
1968 #endif
1969 			debug_level++;
1970 		}
1971 		return 0;
1972 #ifdef NSE
1973 	case 'E':
1974 		if (invert_this) {
1975 			nse = false;
1976 		} else {
1977 			nse = true;
1978 		}
1979 		nse_init_source_suffixes();
1980 		return 0;
1981 #endif
1982 	case 'e':			 /* Environment override flag */
1983 		if (invert_this) {
1984 			env_wins = false;
1985 		} else {
1986 			env_wins = true;
1987 		}
1988 		return 0;
1989 	case 'f':			 /* Read alternative makefile(s) */
1990 		return 1;
1991 	case 'g':			 /* Use alternative DMake group */
1992 		if (invert_this) {
1993 			dmake_group_specified = false;
1994 		} else {
1995 			dmake_group_specified = true;
1996 		}
1997 		return 4;
1998 	case 'i':			 /* Ignore errors */
1999 		if (invert_this) {
2000 			ignore_errors_all = false;
2001 		} else {
2002 			ignore_errors_all = true;
2003 		}
2004 		return 0;
2005 	case 'j':			 /* Use alternative DMake max jobs */
2006 		if (invert_this) {
2007 			dmake_max_jobs_specified = false;
2008 		} else {
2009 			dmake_max_jobs_specified = true;
2010 		}
2011 		return 8;
2012 	case 'K':			 /* Read alternative .make.state */
2013 		return 256;
2014 	case 'k':			 /* Keep making even after errors */
2015 		if (invert_this) {
2016 			continue_after_error = false;
2017 		} else {
2018 			continue_after_error = true;
2019 			continue_after_error_ever_seen = true;
2020 		}
2021 		return 0;
2022 	case 'M':			 /* Read alternative make.machines file */
2023 		if (invert_this) {
2024 			pmake_machinesfile_specified = false;
2025 		} else {
2026 			pmake_machinesfile_specified = true;
2027 			dmake_mode_type = parallel_mode;
2028 			no_parallel = false;
2029 		}
2030 		return 16;
2031 	case 'm':			 /* Use alternative DMake build mode */
2032 		if (invert_this) {
2033 			dmake_mode_specified = false;
2034 		} else {
2035 			dmake_mode_specified = true;
2036 		}
2037 		return 32;
2038 	case 'x':			 /* Use alternative DMake mode */
2039 		if (invert_this) {
2040 			dmake_add_mode_specified = false;
2041 		} else {
2042 			dmake_add_mode_specified = true;
2043 		}
2044 		return 1024;
2045 	case 'N':			 /* Reverse -n */
2046 		if (invert_this) {
2047 			do_not_exec_rule = true;
2048 		} else {
2049 			do_not_exec_rule = false;
2050 		}
2051 		return 0;
2052 	case 'n':			 /* Print, not exec commands */
2053 		if (invert_this) {
2054 			do_not_exec_rule = false;
2055 		} else {
2056 			do_not_exec_rule = true;
2057 		}
2058 		return 0;
2059 #ifndef PARALLEL
2060 	case 'O':			 /* Send job start & result msgs */
2061 		if (invert_this) {
2062 			send_mtool_msgs = false;
2063 		} else {
2064 #ifdef DISTRIBUTED
2065 			send_mtool_msgs = true;
2066 #endif
2067 		}
2068 		return 128;
2069 #endif
2070 	case 'o':			 /* Use alternative dmake output dir */
2071 		if (invert_this) {
2072 			dmake_odir_specified = false;
2073 		} else {
2074 			dmake_odir_specified = true;
2075 		}
2076 		return 512;
2077 	case 'P':			 /* Print for selected targets */
2078 		if (invert_this) {
2079 			report_dependencies_level--;
2080 		} else {
2081 			report_dependencies_level++;
2082 		}
2083 		return 0;
2084 	case 'p':			 /* Print description */
2085 		if (invert_this) {
2086 			trace_status = false;
2087 			do_not_exec_rule = false;
2088 		} else {
2089 			trace_status = true;
2090 			do_not_exec_rule = true;
2091 		}
2092 		return 0;
2093 	case 'q':			 /* Question flag */
2094 		if (invert_this) {
2095 			quest = false;
2096 		} else {
2097 			quest = true;
2098 		}
2099 		return 0;
2100 	case 'R':			 /* Don't run in parallel */
2101 #if defined(TEAMWARE_MAKE_CMN) || defined(PMAKE)
2102 		if (invert_this) {
2103 			pmake_cap_r_specified = false;
2104 			no_parallel = false;
2105 		} else {
2106 			pmake_cap_r_specified = true;
2107 			dmake_mode_type = serial_mode;
2108 			no_parallel = true;
2109 		}
2110 #else
2111 		warning(gettext("Ignoring ParallelMake -R option"));
2112 #endif
2113 		return 0;
2114 	case 'r':			 /* Turn off internal rules */
2115 		if (invert_this) {
2116 			ignore_default_mk = false;
2117 		} else {
2118 			ignore_default_mk = true;
2119 		}
2120 		return 0;
2121 	case 'S':			 /* Reverse -k */
2122 		if (invert_this) {
2123 			continue_after_error = true;
2124 		} else {
2125 			continue_after_error = false;
2126 			stop_after_error_ever_seen = true;
2127 		}
2128 		return 0;
2129 	case 's':			 /* Silent flag */
2130 		if (invert_this) {
2131 			silent_all = false;
2132 		} else {
2133 			silent_all = true;
2134 		}
2135 		return 0;
2136 	case 'T':			 /* Print target list */
2137 		if (invert_this) {
2138 			list_all_targets = false;
2139 			do_not_exec_rule = false;
2140 		} else {
2141 			list_all_targets = true;
2142 			do_not_exec_rule = true;
2143 		}
2144 		return 0;
2145 	case 't':			 /* Touch flag */
2146 		if (invert_this) {
2147 			touch = false;
2148 		} else {
2149 			touch = true;
2150 		}
2151 		return 0;
2152 	case 'u':			 /* Unconditional flag */
2153 		if (invert_this) {
2154 			build_unconditional = false;
2155 		} else {
2156 			build_unconditional = true;
2157 		}
2158 		return 0;
2159 	case 'V':			/* SVR4 mode */
2160 		svr4 = true;
2161 		return 0;
2162 	case 'v':			/* Version flag */
2163 		if (invert_this) {
2164 		} else {
2165 #ifdef TEAMWARE_MAKE_CMN
2166 			fprintf(stdout, NOCATGETS("dmake: %s\n"), verstring);
2167 #ifdef SUN5_0
2168 			exit_status = 0;
2169 #endif
2170 			exit(0);
2171 #else
2172 #if defined(SCHILY_BUILD) || defined(SCHILY_INCLUDES)
2173 			fprintf(stdout, NOCATGETS("%s: %s\n"),
2174 				argv_zero_base, verstring);
2175 			fprintf(stdout, "\n");
2176 			fprintf(stdout, "Copyright (C) 1987-2006 Sun Microsystems\n");
2177 			fprintf(stdout, "Copyright (C) 1996-2021 Joerg Schilling\n");
2178 			exit_status = 0;
2179 			exit(0);
2180 #else
2181 			warning(gettext("Ignoring DistributedMake -v option"));
2182 #endif
2183 #endif
2184 		}
2185 		return 0;
2186 	case 'w':			 /* Report working directory flag */
2187 		if (invert_this) {
2188 			report_cwd = false;
2189 		} else {
2190 			report_cwd = true;
2191 		}
2192 		return 0;
2193 #if 0
2194 	case 'X':			/* Filter stdout */
2195 		if (invert_this) {
2196 			filter_stderr = false;
2197 		} else {
2198 			filter_stderr = true;
2199 		}
2200 		return 0;
2201 #endif
2202 	default:
2203 		break;
2204 	}
2205 	return 0;
2206 }
2207 
2208 /*
2209  *	setup_for_projectdir()
2210  *
2211  *	Read the PROJECTDIR variable, if defined, and set the sccs path
2212  *
2213  *	Parameters:
2214  *
2215  *	Global variables used:
2216  *		sccs_dir_path	Set to point to SCCS dir to use
2217  */
2218 static void
2219 setup_for_projectdir(void)
2220 {
2221 static char	path[MAXPATHLEN];
2222 char		cwdpath[MAXPATHLEN];
2223 uid_t uid;
2224 int   done=0;
2225 
2226 	/* Check if we should use PROJECTDIR when reading the SCCS dir. */
2227 	sccs_dir_path = getenv(NOCATGETS("PROJECTDIR"));
2228 	if ((sccs_dir_path != NULL) &&
2229 	    (sccs_dir_path[0] != (int) slash_char)) {
2230 		struct passwd *pwent;
2231 
2232 	     {
2233 		uid = getuid();
2234 		pwent = getpwuid(uid);
2235 		if (pwent == NULL) {
2236 		   fatal(gettext("Bogus USERID "));
2237 		}
2238 		if ((pwent = getpwnam(sccs_dir_path)) == NULL) {
2239 			/*empty block : it'll go & check cwd  */
2240 		}
2241 		else {
2242 		  (void) sprintf(path, NOCATGETS("%s/src"), pwent->pw_dir);
2243 		  if (access(path, F_OK) == 0) {
2244 			sccs_dir_path = path;
2245 			done = 1;
2246 		  } else {
2247 			(void) sprintf(path, NOCATGETS("%s/source"), pwent->pw_dir);
2248 			if (access(path, F_OK) == 0) {
2249 				sccs_dir_path = path;
2250 				done = 1;
2251 			}
2252 		     }
2253 		}
2254 		if (!done) {
2255 		    if (getcwd(cwdpath, MAXPATHLEN - 1 )) {
2256 
2257 		       (void) sprintf(path, NOCATGETS("%s/%s"), cwdpath,sccs_dir_path);
2258 		       if (access(path, F_OK) == 0) {
2259 		        	sccs_dir_path = path;
2260 				done = 1;
2261 		        } else {
2262 		  	       	fatal(gettext("Bogus PROJECTDIR '%s'"), sccs_dir_path);
2263 		        }
2264 		    }
2265 		}
2266 	   }
2267 	}
2268 }
2269 
2270 static char *
2271 append_to_env(const char *env, const char *value, const char *deflt)
2272 {
2273 	size_t	len;
2274 	char	*oldpath = getenv(env);
2275 	char	*newpath;
2276 
2277 	if (value == NULL)
2278 		value = deflt;
2279 
2280 	if (oldpath == NULL) {
2281 		len = strlen(env) + 1 +
2282 			strlen(value) + 1;
2283 		newpath = (char *) malloc(len);
2284 		if (newpath)
2285 			sprintf(newpath, "%s=", env);
2286 	} else {
2287 		len = strlen(env) + 1 + strlen(oldpath) + 1 +
2288 			strlen(value) + 1;
2289 		newpath = (char *) malloc(len);
2290 		if (newpath)
2291 			sprintf(newpath, "%s=%s", env, oldpath);
2292 	}
2293 	if (newpath == NULL)
2294 		return (newpath);
2295 
2296 #if defined(TEAMWARE_MAKE_CMN)
2297 
2298 	/* function maybe_append_str_to_env_var() is defined in avo_util library
2299 	 * Serial make should not use this library !!!
2300 	 */
2301 	maybe_append_str_to_env_var(newpath, value);
2302 #else
2303 	if (oldpath == NULL) {
2304 		strcat(newpath, value);
2305 	} else {
2306 		strcat(newpath, ":");
2307 		strcat(newpath, value);
2308 	}
2309 #endif
2310 
2311 	return (newpath);
2312 }
2313 
2314 static char *
2315 get_run_lib(const char *run_dir, const char *subdir)
2316 {
2317 	size_t		len;
2318 	char		*lib;
2319 	struct stat	stb;
2320 
2321 	if (run_dir == NULL)
2322 		return (NULL);
2323 
2324 	len = strlen(run_dir) + 1 + 5	/* Nul + strlen("/lib/") */
2325 		+ (subdir ? strlen(subdir) : 0)
2326 		+ strlen(LD_SUPPORT_MAKE_LIB);
2327 	lib = (char *) malloc(len);
2328 	if (lib) {
2329 		strcpy(lib, run_dir);
2330 		strcat(lib, "/lib/");
2331 		if (subdir)
2332 			strcat(lib, subdir);
2333 		strcat(lib, LD_SUPPORT_MAKE_LIB);
2334 		if (stat(lib, &stb) < 0) {
2335 			free(lib);
2336 			lib = NULL;
2337 		}
2338 	}
2339 #ifdef	LD_SUPPORT_MAKE_ARCH
2340 	if (lib == NULL) {		/* Try tools path */
2341 		len += 3 + strlen(LD_SUPPORT_MAKE_ARCH);
2342 
2343 		lib = (char *) malloc(len);
2344 		if (lib) {
2345 			/*
2346 			 * OpenSolaris ON tools path:
2347 			 * tools/..../bin/i386/make
2348 			 * tools/..../lib/i386/libmakestate.so.1
2349 			 * or
2350 			 * tools/..../lib/i386/64/libmakestate.so.1
2351 			 */
2352 			strcpy(lib, run_dir);
2353 			strcat(lib, "/../lib/");
2354 			strcat(lib, LD_SUPPORT_MAKE_ARCH);
2355 			if (subdir)
2356 				strcat(lib, subdir);
2357 			strcat(lib, LD_SUPPORT_MAKE_LIB);
2358 			if (stat(lib, &stb) < 0) {
2359 				free(lib);
2360 				lib = NULL;
2361 			}
2362 		}
2363 	}
2364 #endif
2365 	return (lib);
2366 }
2367 
2368 /*
2369  *	set_sgs_support()
2370  *
2371  *	Add the libmakestate.so.1 lib to the env var SGS_SUPPORT
2372  *	  if it's not already in there.
2373  *	The SGS_SUPPORT env var and libmakestate.so.1 is used by
2374  *	  the linker ld to report .make.state info back to make.
2375  *
2376  *	In case there is a slash in the path for libmakestate.so.1,
2377  *	we cannot use SGS_SUPPORT, but need SGS_SUPPORT_32 and SGS_SUPPORT_64.
2378  *
2379  *	If SGS_SUPPORT_32 or SGS_SUPPORT_64 is present, we manage these
2380  *	variables as well.
2381  */
2382 static void
2383 set_sgs_support()
2384 {
2385 	char		*newpath;
2386 	char		*lib;
2387 	static char	*prev_path;
2388 	static char	*prev_path_32;
2389 	static char	*prev_path_64;
2390 	char		*run_dir = strdup(make_run_dir);
2391 
2392 	if (run_dir && strstr(run_dir, "xpg4/bin"))
2393 		run_dir = dirname(run_dir);	/* Strip last dir component */
2394 	run_dir = dirname(run_dir);		/* Strip last dir component */
2395 
2396 	lib = get_run_lib(run_dir, NULL);
2397 	newpath = append_to_env(LD_SUPPORT_ENV_VAR, lib, LD_SUPPORT_MAKE_LIB);
2398 
2399 	/*
2400 	 * Newer Solaris linker versions may switch to 64 bit binaries.
2401 	 * A simple SGS_SUPPORT entry would not work in case it contains
2402 	 * a slash. So do not create a SGS_SUPPORT entry in this case but
2403 	 * rather directly create SGS_SUPPORT_32 and SGS_SUPPORT_64.
2404 	 */
2405 	if (newpath && strchr(newpath, (int) slash_char)) {
2406 		free(newpath);
2407 		if (lib)
2408 			free(lib);
2409 		goto need_specific;
2410 	}
2411 
2412 	if (newpath)
2413 		putenv(newpath);
2414 	if (prev_path) {
2415 		free(prev_path);
2416 	}
2417 	prev_path = newpath;
2418 	if (lib)
2419 		free(lib);
2420 
2421 	if (getenv(LD_SUPPORT_ENV_VAR_32) == NULL &&
2422 	    getenv(LD_SUPPORT_ENV_VAR_64) == NULL)
2423 		return;
2424 
2425 need_specific:
2426 
2427 	lib = get_run_lib(run_dir, NULL);
2428 	newpath = append_to_env(LD_SUPPORT_ENV_VAR_32, lib, LD_SUPPORT_MAKE_LIB);
2429 
2430 	if (newpath)
2431 		putenv(newpath);
2432 	if (prev_path_32) {
2433 		free(prev_path_32);
2434 	}
2435 	prev_path_32 = newpath;
2436 	if (lib)
2437 		free(lib);
2438 
2439 	lib = get_run_lib(run_dir, "64/");
2440 	newpath = append_to_env(LD_SUPPORT_ENV_VAR_64, lib, LD_SUPPORT_MAKE_LIB);
2441 
2442 	if (newpath)
2443 		putenv(newpath);
2444 	if (prev_path_64) {
2445 		free(prev_path_64);
2446 	}
2447 	prev_path_64 = newpath;
2448 	if (lib)
2449 		free(lib);
2450 }
2451 
2452 /*
2453  *	read_files_and_state(argc, argv)
2454  *
2455  *	Read the makefiles we care about and the environment
2456  *	Also read the = style command line options
2457  *
2458  *	Parameters:
2459  *		argc		You know what this is
2460  *		argv		You know what this is
2461  *
2462  *	Static variables used:
2463  *		env_wins	make -e, determines if env vars are RO
2464  *		ignore_default_mk make -r, determines if make.rules is read
2465  *		not_auto_depen	dwight
2466  *
2467  *	Global variables used:
2468  *		default_target_to_build	Set to first proper target from file
2469  *		do_not_exec_rule Set to false when makfile is made
2470  *		dot		The Name ".", used to read current dir
2471  *		empty_name	The Name "", use as macro value
2472  *		keep_state	Set if KEEP_STATE is in environment
2473  *		make_state	The Name ".make.state", used to read file
2474  *		makefile_type	Set to type of file being read
2475  *		makeflags	The Name "MAKEFLAGS", used to set macro value
2476  *		not_auto	dwight
2477  *		nse		Set if NSE_ENV is in the environment
2478  *		read_trace_level Checked to se if the reader should trace
2479  *		report_dependencies If -P is on we do not read .make.state
2480  *		trace_reader	Set if reader should trace
2481  *		virtual_root	The Name "VIRTUAL_ROOT", used to check value
2482  */
2483 static void
2484 read_files_and_state(int argc, char **argv)
2485 {
2486 	wchar_t			buffer[1000];
2487 	wchar_t			buffer_posix[1000];
2488 	register char		ch;
2489 	register char		*cp;
2490 	Property		def_make_macro = NULL;
2491 	Name			def_make_name;
2492 	Name			default_makefile;
2493 	String_rec		dest;
2494 	wchar_t			destbuffer[STRING_BUFFER_LENGTH];
2495 	register int		i;
2496 	register int		j;
2497 	Name			keep_state_name;
2498 	int			length;
2499 	Name			Makefile;
2500 	register Property	macro;
2501 	struct stat		make_state_stat;
2502 	Name			makefile_name;
2503         register int		makefile_next = 0;
2504 	register Boolean	makefile_read = false;
2505 	String_rec		makeflags_string;
2506 	String_rec		makeflags_string_posix;
2507 	String_rec *		makeflags_string_current;
2508 	Name			makeflags_value_saved;
2509 	register Name		name;
2510 	Name			new_make_value;
2511 	Boolean			save_do_not_exec_rule;
2512 	Name			sdotMakefile;
2513 	Name			sdotmakefile_name;
2514 	static wchar_t		state_file_str;
2515 	static char		state_file_str_mb[MAXPATHLEN];
2516 	static struct _Name	state_filename;
2517 	Boolean			temp;
2518 	char			tmp_char;
2519 	wchar_t			*tmp_wcs_buffer;
2520 	register Name		value;
2521 	ASCII_Dyn_Array		makeflags_and_macro;
2522 	Boolean			is_xpg4;
2523 
2524 /*
2525  *	Remember current mode. It may be changed after reading makefile
2526  *	and we will have to correct MAKEFLAGS variable.
2527  */
2528 	is_xpg4 = posix;
2529 
2530 	MBSTOWCS(wcs_buffer, NOCATGETS("KEEP_STATE"));
2531 	keep_state_name = GETNAME(wcs_buffer, FIND_LENGTH);
2532 	MBSTOWCS(wcs_buffer, NOCATGETS("Makefile"));
2533 	Makefile = GETNAME(wcs_buffer, FIND_LENGTH);
2534 	MBSTOWCS(wcs_buffer, NOCATGETS("makefile"));
2535 	makefile_name = GETNAME(wcs_buffer, FIND_LENGTH);
2536 	MBSTOWCS(wcs_buffer, NOCATGETS("s.makefile"));
2537 	sdotmakefile_name = GETNAME(wcs_buffer, FIND_LENGTH);
2538 	MBSTOWCS(wcs_buffer, NOCATGETS("s.Makefile"));
2539 	sdotMakefile = GETNAME(wcs_buffer, FIND_LENGTH);
2540 
2541 /*
2542  *	Set flag if NSE is active
2543  */
2544 #ifdef NSE
2545 	if (getenv(NOCATGETS("NSE_ENV")) != NULL) {
2546 		nse = true;
2547 	}
2548 #endif
2549 
2550 /*
2551  *	initialize global dependency entry for .NOT_AUTO
2552  */
2553 	not_auto_depen->next = NULL;
2554 	not_auto_depen->name = not_auto;
2555 	not_auto_depen->automatic = not_auto_depen->stale = false;
2556 
2557 /*
2558  *	Read internal definitions and rules.
2559  */
2560 	if (read_trace_level > 1) {
2561 		trace_reader = true;
2562 	}
2563 	if (!ignore_default_mk) {
2564 #if defined(SUN5_0) || defined(HP_UX) || defined(linux)
2565 		if (svr4) {
2566 			MBSTOWCS(wcs_buffer, NOCATGETS("svr4.make.rules"));
2567 			default_makefile = GETNAME(wcs_buffer, FIND_LENGTH);
2568 		} else {
2569 			MBSTOWCS(wcs_buffer, NOCATGETS("make.rules"));
2570 			default_makefile = GETNAME(wcs_buffer, FIND_LENGTH);
2571 		}
2572 #else
2573 		MBSTOWCS(wcs_buffer, NOCATGETS("default.mk"));
2574 		default_makefile = GETNAME(wcs_buffer, FIND_LENGTH);
2575 #endif
2576 		default_makefile->stat.is_file = true;
2577 
2578 		(void) read_makefile(default_makefile,
2579 				     true,
2580 				     false,
2581 				     true);
2582 	}
2583 
2584 	/*
2585 	 * If the user did not redefine the MAKE macro in the
2586 	 * default makefile (make.rules), then we'd like to
2587 	 * change the macro value of MAKE to be some form
2588 	 * of argv[0] for recursive MAKE builds.
2589 	 * Since POSIX claims for the option -r:
2590 	 *	Clear the suffix list and do not use the built-in rules.
2591 	 * $(MAKE) should not be affected by -r. We need to provide a
2592 	 * useful default in case $(MAKE) has not been defined at all.
2593 	 */
2594 	MBSTOWCS(wcs_buffer, NOCATGETS("MAKE"));
2595 	def_make_name = GETNAME(wcs_buffer, wcslen(wcs_buffer));
2596 	def_make_macro = get_prop(def_make_name->prop, macro_prop);
2597 	if ((def_make_macro == NULL) ||
2598 	    ((def_make_macro != NULL) &&
2599 	    (IS_EQUAL(def_make_macro->body.macro.value->string_mb,
2600 	              NOCATGETS("make"))))) {
2601 		MBSTOWCS(wcs_buffer, argv_zero_string);
2602 		new_make_value = GETNAME(wcs_buffer, wcslen(wcs_buffer));
2603 		(void) SETVAR(def_make_name,
2604 		              new_make_value,
2605 		              false);
2606 	}
2607 
2608 #ifdef	DO_MAKE_NAME
2609 	if (!sunpro_compat && !svr4) {
2610 		MBSTOWCS(wcs_buffer, NOCATGETS("sunpro"));
2611 		SETVAR(sunpro_make_name,
2612 			GETNAME(wcs_buffer, FIND_LENGTH),
2613 			false);
2614 	}
2615 #endif
2616 #ifdef	DO_ARCHCONF
2617 	if (!sunpro_compat && !svr4 && !no_archconf) {
2618 		setup_arch();
2619 	}
2620 #endif
2621 
2622 	default_target_to_build = NULL;
2623 	trace_reader = false;
2624 
2625 /*
2626  *	Read environment args. Let file args which follow override unless
2627  *	-e option seen. If -e option is not mentioned.
2628  */
2629 	read_environment(env_wins);
2630 	if (getvar(virtual_root)->hash.length == 0) {
2631 		maybe_append_prop(virtual_root, macro_prop)
2632 		  ->body.macro.exported = true;
2633 		MBSTOWCS(wcs_buffer, "/");
2634 		(void) SETVAR(virtual_root,
2635 			      GETNAME(wcs_buffer, FIND_LENGTH),
2636 			      false);
2637 	}
2638 
2639 /*
2640  * We now scan mf_argv and argv to see if we need to set
2641  * any of the DMake-added options/variables in MAKEFLAGS.
2642  */
2643 
2644 	makeflags_and_macro.start = 0;
2645 	makeflags_and_macro.size = 0;
2646 	enter_argv_values(mf_argc, mf_argv, &makeflags_and_macro);
2647 	enter_argv_values(argc, argv, &makeflags_and_macro);
2648 
2649 /*
2650  *	Set MFLAGS and MAKEFLAGS
2651  *
2652  *	Before reading makefile we do not know exactly which mode
2653  *	(posix or not) is used. So prepare two MAKEFLAGS strings
2654  *	for both posix and solaris modes because they are different.
2655  */
2656 	INIT_STRING_FROM_STACK(makeflags_string, buffer);
2657 	INIT_STRING_FROM_STACK(makeflags_string_posix, buffer_posix);
2658 	append_char((int) hyphen_char, &makeflags_string);
2659 	append_char((int) hyphen_char, &makeflags_string_posix);
2660 
2661 #ifdef	DO_ARCHCONF
2662 	if (no_archconf) {
2663 		append_char('a', &makeflags_string);
2664 		append_char('a', &makeflags_string_posix);
2665 	}
2666 #endif
2667 	switch (read_trace_level) {
2668 	case 2:
2669 		append_char('D', &makeflags_string);
2670 		append_char('D', &makeflags_string_posix);
2671 	case 1:
2672 		append_char('D', &makeflags_string);
2673 		append_char('D', &makeflags_string_posix);
2674 	}
2675 	switch (debug_level) {
2676 	case 2:
2677 		append_char('d', &makeflags_string);
2678 		append_char('d', &makeflags_string_posix);
2679 	case 1:
2680 		append_char('d', &makeflags_string);
2681 		append_char('d', &makeflags_string_posix);
2682 	}
2683 #ifdef NSE
2684 	if (nse) {
2685 		append_char('E', &makeflags_string);
2686 	}
2687 #endif
2688 	if (env_wins) {
2689 		append_char('e', &makeflags_string);
2690 		append_char('e', &makeflags_string_posix);
2691 	}
2692 	if (ignore_errors_all) {
2693 		append_char('i', &makeflags_string);
2694 		append_char('i', &makeflags_string_posix);
2695 	}
2696 	if (continue_after_error) {
2697 		if (stop_after_error_ever_seen) {
2698 			append_char('S', &makeflags_string_posix);
2699 			append_char((int) space_char, &makeflags_string_posix);
2700 			append_char((int) hyphen_char, &makeflags_string_posix);
2701 		}
2702 		append_char('k', &makeflags_string);
2703 		append_char('k', &makeflags_string_posix);
2704 	} else {
2705 		if (stop_after_error_ever_seen
2706 		    && continue_after_error_ever_seen) {
2707 			append_char('k', &makeflags_string_posix);
2708 			append_char((int) space_char, &makeflags_string_posix);
2709 			append_char((int) hyphen_char, &makeflags_string_posix);
2710 			append_char('S', &makeflags_string_posix);
2711 		}
2712 	}
2713 	if (do_not_exec_rule) {
2714 		append_char('n', &makeflags_string);
2715 		append_char('n', &makeflags_string_posix);
2716 	}
2717 	switch (report_dependencies_level) {
2718 	case 4:
2719 		append_char('P', &makeflags_string);
2720 		append_char('P', &makeflags_string_posix);
2721 	case 3:
2722 		append_char('P', &makeflags_string);
2723 		append_char('P', &makeflags_string_posix);
2724 	case 2:
2725 		append_char('P', &makeflags_string);
2726 		append_char('P', &makeflags_string_posix);
2727 	case 1:
2728 		append_char('P', &makeflags_string);
2729 		append_char('P', &makeflags_string_posix);
2730 	}
2731 	if (trace_status) {
2732 		append_char('p', &makeflags_string);
2733 		append_char('p', &makeflags_string_posix);
2734 	}
2735 	if (quest) {
2736 		append_char('q', &makeflags_string);
2737 		append_char('q', &makeflags_string_posix);
2738 	}
2739 	if (ignore_default_mk) {
2740 		append_char('r', &makeflags_string);
2741 		append_char('r', &makeflags_string_posix);
2742 	}
2743 	if (silent_all) {
2744 		append_char('s', &makeflags_string);
2745 		append_char('s', &makeflags_string_posix);
2746 	}
2747 	if (touch) {
2748 		append_char('t', &makeflags_string);
2749 		append_char('t', &makeflags_string_posix);
2750 	}
2751 	if (build_unconditional) {
2752 		append_char('u', &makeflags_string);
2753 		append_char('u', &makeflags_string_posix);
2754 	}
2755 	if (report_cwd) {
2756 		append_char('w', &makeflags_string);
2757 		append_char('w', &makeflags_string_posix);
2758 	}
2759 #ifndef PARALLEL
2760 	/* -c dmake_rcfile */
2761 	if (dmake_rcfile_specified) {
2762 		MBSTOWCS(wcs_buffer, NOCATGETS("DMAKE_RCFILE"));
2763 		dmake_rcfile = GETNAME(wcs_buffer, FIND_LENGTH);
2764 		append_makeflags_string(dmake_rcfile, &makeflags_string);
2765 		append_makeflags_string(dmake_rcfile, &makeflags_string_posix);
2766 	}
2767 	/* -g dmake_group */
2768 	if (dmake_group_specified) {
2769 		MBSTOWCS(wcs_buffer, NOCATGETS("DMAKE_GROUP"));
2770 		dmake_group = GETNAME(wcs_buffer, FIND_LENGTH);
2771 		append_makeflags_string(dmake_group, &makeflags_string);
2772 		append_makeflags_string(dmake_group, &makeflags_string_posix);
2773 	}
2774 	/* -j dmake_max_jobs */
2775 	if (dmake_max_jobs_specified) {
2776 		MBSTOWCS(wcs_buffer, NOCATGETS("DMAKE_MAX_JOBS"));
2777 		dmake_max_jobs = GETNAME(wcs_buffer, FIND_LENGTH);
2778 		append_makeflags_string(dmake_max_jobs, &makeflags_string);
2779 		append_makeflags_string(dmake_max_jobs, &makeflags_string_posix);
2780 	}
2781 	/* -m dmake_mode */
2782 	if (dmake_mode_specified) {
2783 		MBSTOWCS(wcs_buffer, NOCATGETS("DMAKE_MODE"));
2784 		dmake_mode = GETNAME(wcs_buffer, FIND_LENGTH);
2785 		append_makeflags_string(dmake_mode, &makeflags_string);
2786 		append_makeflags_string(dmake_mode, &makeflags_string_posix);
2787 	}
2788 	/* -x dmake_compat_mode */
2789 	if (dmake_compat_mode_specified) {
2790 		MBSTOWCS(wcs_buffer, NOCATGETS("SUN_MAKE_COMPAT_MODE"));
2791 		dmake_compat_mode = GETNAME(wcs_buffer, FIND_LENGTH);
2792 		append_makeflags_string(dmake_compat_mode, &makeflags_string);
2793 		append_makeflags_string(dmake_compat_mode, &makeflags_string_posix);
2794 	}
2795 	/* -x dmake_output_mode */
2796 	if (dmake_output_mode_specified) {
2797 		MBSTOWCS(wcs_buffer, NOCATGETS("DMAKE_OUTPUT_MODE"));
2798 		dmake_output_mode = GETNAME(wcs_buffer, FIND_LENGTH);
2799 		append_makeflags_string(dmake_output_mode, &makeflags_string);
2800 		append_makeflags_string(dmake_output_mode, &makeflags_string_posix);
2801 	}
2802 	/* -o dmake_odir */
2803 	if (dmake_odir_specified) {
2804 		MBSTOWCS(wcs_buffer, NOCATGETS("DMAKE_ODIR"));
2805 		dmake_odir = GETNAME(wcs_buffer, FIND_LENGTH);
2806 		append_makeflags_string(dmake_odir, &makeflags_string);
2807 		append_makeflags_string(dmake_odir, &makeflags_string_posix);
2808 	}
2809 	/* -M pmake_machinesfile */
2810 	if (pmake_machinesfile_specified) {
2811 		MBSTOWCS(wcs_buffer, NOCATGETS("PMAKE_MACHINESFILE"));
2812 		pmake_machinesfile = GETNAME(wcs_buffer, FIND_LENGTH);
2813 		append_makeflags_string(pmake_machinesfile, &makeflags_string);
2814 		append_makeflags_string(pmake_machinesfile, &makeflags_string_posix);
2815 	}
2816 	/* -R */
2817 	if (pmake_cap_r_specified) {
2818 		append_char((int) space_char, &makeflags_string);
2819 		append_char((int) hyphen_char, &makeflags_string);
2820 		append_char('R', &makeflags_string);
2821 		append_char((int) space_char, &makeflags_string_posix);
2822 		append_char((int) hyphen_char, &makeflags_string_posix);
2823 		append_char('R', &makeflags_string_posix);
2824 	}
2825 #endif
2826 
2827 /*
2828  *	Make sure MAKEFLAGS is exported
2829  */
2830 	maybe_append_prop(makeflags, macro_prop)->
2831 	  body.macro.exported = true;
2832 
2833 	if (makeflags_string.buffer.start[1] != (int) nul_char) {
2834 		if (makeflags_string.buffer.start[1] != (int) space_char) {
2835 			MBSTOWCS(wcs_buffer, NOCATGETS("MFLAGS"));
2836 			(void) SETVAR(GETNAME(wcs_buffer, FIND_LENGTH),
2837 				      GETNAME(makeflags_string.buffer.start,
2838 					      FIND_LENGTH),
2839 				      false);
2840 		} else {
2841 			MBSTOWCS(wcs_buffer, NOCATGETS("MFLAGS"));
2842 			(void) SETVAR(GETNAME(wcs_buffer, FIND_LENGTH),
2843 				      GETNAME(makeflags_string.buffer.start + 2,
2844 					      FIND_LENGTH),
2845 				      false);
2846 		}
2847 	}
2848 
2849 /*
2850  *	Add command line macro to POSIX makeflags_string
2851  */
2852 	if (makeflags_and_macro.start) {
2853 		tmp_char = (char) space_char;
2854 		cp = makeflags_and_macro.start;
2855 		do {
2856 			if (!sunpro_compat && !svr4)
2857 				append_char(tmp_char, &makeflags_string);
2858 			append_char(tmp_char, &makeflags_string_posix);
2859 		} while ((tmp_char = *cp++) != '\0');
2860 		retmem_mb(makeflags_and_macro.start);
2861 	}
2862 
2863 /*
2864  *	Now set the value of MAKEFLAGS macro in accordance
2865  *	with current mode.
2866  */
2867 	macro = maybe_append_prop(makeflags, macro_prop);
2868 	temp = (Boolean) macro->body.macro.read_only;
2869 	macro->body.macro.read_only = false;
2870 	if(posix || gnu_style) {
2871 		makeflags_string_current = &makeflags_string_posix;
2872 	} else {
2873 		makeflags_string_current = &makeflags_string;
2874 	}
2875 	if (makeflags_string_current->buffer.start[1] == (int) nul_char) {
2876 		makeflags_value_saved =
2877 			GETNAME( makeflags_string_current->buffer.start + 1
2878 			       , FIND_LENGTH
2879 			       );
2880 	} else {
2881 		if (makeflags_string_current->buffer.start[1] != (int) space_char) {
2882 			makeflags_value_saved =
2883 				GETNAME( makeflags_string_current->buffer.start
2884 				       , FIND_LENGTH
2885 				       );
2886 		} else {
2887 			makeflags_value_saved =
2888 				GETNAME( makeflags_string_current->buffer.start + 2
2889 				       , FIND_LENGTH
2890 				       );
2891 		}
2892 	}
2893 	(void) SETVAR( makeflags
2894 	             , makeflags_value_saved
2895 	             , false
2896 	             );
2897 	macro->body.macro.read_only = temp;
2898 
2899 /*
2900  *	Read command line "-f" arguments and ignore -c, g, j, K, M, m, O and o args.
2901  */
2902 	save_do_not_exec_rule = do_not_exec_rule;
2903 	do_not_exec_rule = false;
2904 	if (read_trace_level > 0) {
2905 		trace_reader = true;
2906 	}
2907 
2908 	for (i = 1; i < argc; i++) {
2909 		if (argv[i] &&
2910 		    (argv[i][0] == (int) hyphen_char) &&
2911 		    (argv[i][1] == 'f') &&
2912 		    (argv[i][2] == (int) nul_char)) {
2913 			argv[i] = NULL;		/* Remove -f */
2914 			if (i >= argc - 1) {
2915 				fatal(gettext("No filename argument after -f flag"));
2916 			}
2917 			MBSTOWCS(wcs_buffer, argv[++i]);
2918 			primary_makefile = GETNAME(wcs_buffer, FIND_LENGTH);
2919 			(void) read_makefile(primary_makefile, true, true, true);
2920 			argv[i] = NULL;		/* Remove filename */
2921 			makefile_read = true;
2922 		} else if (argv[i] &&
2923 			   (argv[i][0] == (int) hyphen_char) &&
2924 			   (argv[i][1] == 'C' ||
2925 			    argv[i][1] == 'c' ||
2926 			    argv[i][1] == 'g' ||
2927 			    argv[i][1] == 'j' ||
2928 			    argv[i][1] == 'K' ||
2929 			    argv[i][1] == 'M' ||
2930 			    argv[i][1] == 'm' ||
2931 			    argv[i][1] == 'O' ||
2932 			    argv[i][1] == 'o') &&
2933 			   (argv[i][2] == (int) nul_char)) {
2934 			argv[i] = NULL;
2935 			argv[++i] = NULL;
2936 		}
2937 	}
2938 
2939 /*
2940  *	If no command line "-f" args then look for "makefile", and then for
2941  *	"Makefile" if "makefile" isn't found.
2942  */
2943 	if (!makefile_read) {
2944 		(void) read_dir(dot,
2945 				(wchar_t *) NULL,
2946 				(Property) NULL,
2947 				(wchar_t *) NULL);
2948 	    if (!posix) {
2949 		if (makefile_name->stat.is_file) {
2950 			if (Makefile->stat.is_file) {
2951 				warning(gettext("Both `makefile' and `Makefile' exist"));
2952 			}
2953 			primary_makefile = makefile_name;
2954 			makefile_read = read_makefile(makefile_name,
2955 						      false,
2956 						      false,
2957 						      true);
2958 		}
2959 		if (!makefile_read &&
2960 		    Makefile->stat.is_file) {
2961 			primary_makefile = Makefile;
2962 			makefile_read = read_makefile(Makefile,
2963 						      false,
2964 						      false,
2965 						      true);
2966 		}
2967 	    } else {
2968 
2969 		enum sccs_stat save_m_has_sccs = NO_SCCS;
2970 		enum sccs_stat save_M_has_sccs = NO_SCCS;
2971 
2972 		if (makefile_name->stat.is_file) {
2973 			if (Makefile->stat.is_file) {
2974 				warning(gettext("Both `makefile' and `Makefile' exist"));
2975 			}
2976 		}
2977 		if (makefile_name->stat.is_file) {
2978 			if (makefile_name->stat.has_sccs == NO_SCCS) {
2979 			   primary_makefile = makefile_name;
2980 			   makefile_read = read_makefile(makefile_name,
2981 						      false,
2982 						      false,
2983 						      true);
2984 			} else {
2985 			  save_m_has_sccs = makefile_name->stat.has_sccs;
2986 			  makefile_name->stat.has_sccs = NO_SCCS;
2987 			  primary_makefile = makefile_name;
2988 			  makefile_read = read_makefile(makefile_name,
2989 						      false,
2990 						      false,
2991 						      true);
2992 			}
2993 		}
2994 		if (!makefile_read &&
2995 		    Makefile->stat.is_file) {
2996 			if (Makefile->stat.has_sccs == NO_SCCS) {
2997 			   primary_makefile = Makefile;
2998 			   makefile_read = read_makefile(Makefile,
2999 						      false,
3000 						      false,
3001 						      true);
3002 			} else {
3003 			  save_M_has_sccs = Makefile->stat.has_sccs;
3004 			  Makefile->stat.has_sccs = NO_SCCS;
3005 			  primary_makefile = Makefile;
3006 			  makefile_read = read_makefile(Makefile,
3007 						      false,
3008 						      false,
3009 						      true);
3010 			}
3011 		}
3012 		if (!makefile_read &&
3013 		        makefile_name->stat.is_file) {
3014 			   makefile_name->stat.has_sccs = save_m_has_sccs;
3015 			   primary_makefile = makefile_name;
3016 			   makefile_read = read_makefile(makefile_name,
3017 						      false,
3018 						      false,
3019 						      true);
3020 		}
3021 		if (!makefile_read &&
3022 		    Makefile->stat.is_file) {
3023 			   Makefile->stat.has_sccs = save_M_has_sccs;
3024 			   primary_makefile = Makefile;
3025 			   makefile_read = read_makefile(Makefile,
3026 						      false,
3027 						      false,
3028 						      true);
3029 		}
3030 	    }
3031 	}
3032 	do_not_exec_rule = save_do_not_exec_rule;
3033 	allrules_read = makefile_read;
3034 	trace_reader = false;
3035 
3036 /*
3037  *	Now get current value of MAKEFLAGS and compare it with
3038  *	the saved value we set before reading makefile.
3039  *	If they are different then MAKEFLAGS is subsequently set by
3040  *	makefile, just leave it there. Otherwise, if make mode
3041  *	is changed by using .POSIX target in makefile we need
3042  *	to correct MAKEFLAGS value.
3043  */
3044 	Name mf_val = getvar(makeflags);
3045 	if( (posix != is_xpg4)
3046 	 && (!strcmp(mf_val->string_mb, makeflags_value_saved->string_mb)))
3047 	{
3048 		if (makeflags_string_posix.buffer.start[1] == (int) nul_char) {
3049 			(void) SETVAR(makeflags,
3050 				      GETNAME(makeflags_string_posix.buffer.start + 1,
3051 					      FIND_LENGTH),
3052 				      false);
3053 		} else {
3054 			if (makeflags_string_posix.buffer.start[1] != (int) space_char) {
3055 				(void) SETVAR(makeflags,
3056 					      GETNAME(makeflags_string_posix.buffer.start,
3057 						      FIND_LENGTH),
3058 					      false);
3059 			} else {
3060 				(void) SETVAR(makeflags,
3061 					      GETNAME(makeflags_string_posix.buffer.start + 2,
3062 						      FIND_LENGTH),
3063 					      false);
3064 			}
3065 		}
3066 	}
3067 
3068 	if (makeflags_string.free_after_use) {
3069 		retmem(makeflags_string.buffer.start);
3070 	}
3071 	if (makeflags_string_posix.free_after_use) {
3072 		retmem(makeflags_string_posix.buffer.start);
3073 	}
3074 	makeflags_string.buffer.start = NULL;
3075 	makeflags_string_posix.buffer.start = NULL;
3076 
3077 	if (posix) {
3078 		/*
3079 		 * If the user did not redefine the ARFLAGS macro in the
3080 		 * default makefile (make.rules), then we'd like to
3081 		 * change the macro value of ARFLAGS to be in accordance
3082 		 * with "POSIX" requirements.
3083 		 */
3084 		MBSTOWCS(wcs_buffer, NOCATGETS("ARFLAGS"));
3085 		name = GETNAME(wcs_buffer, wcslen(wcs_buffer));
3086 		macro = get_prop(name->prop, macro_prop);
3087 		if ((macro != NULL) && /* Maybe (macro == NULL) || ? */
3088 		    (IS_EQUAL(macro->body.macro.value->string_mb,
3089 		              NOCATGETS("rv")))) {
3090 			MBSTOWCS(wcs_buffer, NOCATGETS("-rv"));
3091 			value = GETNAME(wcs_buffer, wcslen(wcs_buffer));
3092 			(void) SETVAR(name,
3093 			              value,
3094 			              false);
3095 		}
3096 	}
3097 
3098 	if (!posix && !svr4) {
3099 		set_sgs_support();
3100 	}
3101 
3102 
3103 /*
3104  *	Make sure KEEP_STATE is in the environment if KEEP_STATE is on.
3105  */
3106 	macro = get_prop(keep_state_name->prop, macro_prop);
3107 	if ((macro != NULL) &&
3108 	    macro->body.macro.exported) {
3109 		keep_state = true;
3110 	}
3111 	if (keep_state) {
3112 		if (macro == NULL) {
3113 			macro = maybe_append_prop(keep_state_name,
3114 						  macro_prop);
3115 		}
3116 		macro->body.macro.exported = true;
3117 		(void) SETVAR(keep_state_name,
3118 			      empty_name,
3119 			      false);
3120 
3121 		/*
3122 		 *	Read state file
3123 		 */
3124 
3125 		/* Before we read state, let's make sure we have
3126 		** right state file.
3127 		*/
3128 		/* just in case macro references are used in make_state file
3129 		** name, we better expand them at this stage using expand_value.
3130 		*/
3131 		INIT_STRING_FROM_STACK(dest, destbuffer);
3132 		expand_value(make_state, &dest, false);
3133 
3134 		make_state = GETNAME(dest.buffer.start, FIND_LENGTH);
3135 
3136 		if(!stat(make_state->string_mb, &make_state_stat)) {
3137 		   if(!(make_state_stat.st_mode & S_IFREG) ) {
3138 			/* copy the make_state structure to the other
3139 			** and then let make_state point to the new
3140 			** one.
3141 			*/
3142 		      memcpy(&state_filename, make_state,sizeof(state_filename));
3143 		      state_filename.string_mb = state_file_str_mb;
3144 		/* Just a kludge to avoid two slashes back to back */
3145 		      if((make_state->hash.length == 1)&&
3146 			        (make_state->string_mb[0] == '/')) {
3147 			 make_state->hash.length = 0;
3148 			 make_state->string_mb[0] = '\0';
3149 		      }
3150 	   	      sprintf(state_file_str_mb,NOCATGETS("%s%s"),
3151 		       make_state->string_mb,NOCATGETS("/.make.state"));
3152 		      make_state = &state_filename;
3153 			/* adjust the length to reflect the appended string */
3154 		      make_state->hash.length += 12;
3155 		   }
3156 		} else { /* the file doesn't exist or no permission */
3157 		   char tmp_path[MAXPATHLEN];
3158 		   char *slashp;
3159 
3160 		   if ((slashp = strrchr(make_state->string_mb, '/')) != 0) {
3161 		      strncpy(tmp_path, make_state->string_mb,
3162 				(slashp - make_state->string_mb));
3163 			tmp_path[slashp - make_state->string_mb]=0;
3164 		      if(strlen(tmp_path)) {
3165 		        if(stat(tmp_path, &make_state_stat)) {
3166 			  warning(gettext("directory %s for .KEEP_STATE_FILE does not exist"),tmp_path);
3167 		        }
3168 		        if (access(tmp_path, F_OK) != 0) {
3169 			  warning(gettext("can't access dir %s"),tmp_path);
3170 		        }
3171 		      }
3172 		   }
3173 		}
3174 		if (report_dependencies_level != 1) {
3175 			Makefile_type	makefile_type_temp = makefile_type;
3176 			makefile_type = reading_statefile;
3177 			if (read_trace_level > 1) {
3178 				trace_reader = true;
3179 			}
3180 			(void) read_simple_file(make_state,
3181 						false,
3182 						false,
3183 						false,
3184 						false,
3185 						false,
3186 						true);
3187 			trace_reader = false;
3188 			makefile_type = makefile_type_temp;
3189 		}
3190 	}
3191 }
3192 
3193 /*
3194  * Scan the argv for options and "=" type args and make them readonly.
3195  */
3196 static void
3197 enter_argv_values(int argc, char *argv[], ASCII_Dyn_Array *makeflags_and_macro)
3198 {
3199 	register char		*cp;
3200 	register int		i;
3201 	int			length;
3202 	register Name		name;
3203 	int			opt_separator = argc;
3204 	char			tmp_char;
3205 	wchar_t			*tmp_wcs_buffer;
3206 	register Name		value;
3207 	Boolean			append = false;
3208 	Boolean			gnuassign = false;
3209 	Property		macro;
3210 	struct stat		statbuf;
3211 
3212 
3213 	/* Read argv options and "=" type args and make them readonly. */
3214 	makefile_type = reading_nothing;
3215 	for (i = 1; i < argc; ++i) {
3216 		append = false;
3217 		if (argv[i] == NULL) {
3218 			continue;
3219 		} else if (((argv[i][0] == '-') && (argv[i][1] == '-')) ||
3220 			   ((argv[i][0] == (int) ' ') &&
3221 			    (argv[i][1] == (int) '-') &&
3222 			    (argv[i][2] == (int) ' ') &&
3223 			    (argv[i][3] == (int) '-'))) {
3224 			argv[i] = NULL;
3225 			opt_separator = i;
3226 			continue;
3227 		} else if ((i < opt_separator) && (argv[i][0] == (int) hyphen_char)) {
3228 			char	*ap = argv[i+1];
3229 
3230 			switch (parse_command_option(argv[i][1])) {
3231 			case 1:	/* -f seen */
3232 				++i;
3233 				continue;
3234 			case 2:	/* -c seen */
3235 				if (argv[i+1] == NULL) {
3236 					fatal(gettext("No dmake rcfile argument after -c flag"));
3237 				}
3238 				MBSTOWCS(wcs_buffer, NOCATGETS("DMAKE_RCFILE"));
3239 				name = GETNAME(wcs_buffer, FIND_LENGTH);
3240 				break;
3241 			case 4:	/* -g seen */
3242 				if (argv[i+1] == NULL) {
3243 					fatal(gettext("No dmake group argument after -g flag"));
3244 				}
3245 				MBSTOWCS(wcs_buffer, NOCATGETS("DMAKE_GROUP"));
3246 				name = GETNAME(wcs_buffer, FIND_LENGTH);
3247 				break;
3248 			case 8:	/* -j seen */
3249 				if (argv[i][2])		/* e.g. -j5 */
3250 					ap = &argv[i][2];
3251 				if (ap == NULL) {
3252 					fatal(gettext("No dmake max jobs argument after -j flag"));
3253 				}
3254 				MBSTOWCS(wcs_buffer, NOCATGETS("DMAKE_MAX_JOBS"));
3255 				name = GETNAME(wcs_buffer, FIND_LENGTH);
3256 				break;
3257 			case 16: /* -M seen */
3258 				if (argv[i+1] == NULL) {
3259 					fatal(gettext("No pmake machinesfile argument after -M flag"));
3260 				}
3261 				MBSTOWCS(wcs_buffer, NOCATGETS("PMAKE_MACHINESFILE"));
3262 				name = GETNAME(wcs_buffer, FIND_LENGTH);
3263 				break;
3264 			case 32: /* -m seen */
3265 				if (argv[i+1] == NULL) {
3266 					fatal(gettext("No dmake mode argument after -m flag"));
3267 				}
3268 				MBSTOWCS(wcs_buffer, NOCATGETS("DMAKE_MODE"));
3269 				name = GETNAME(wcs_buffer, FIND_LENGTH);
3270 				break;
3271 			case 128: /* -O seen */
3272 				if (argv[i+1] == NULL) {
3273 					fatal(gettext("No file descriptor argument after -O flag"));
3274 				}
3275 				mtool_msgs_fd = atoi(argv[i+1]);
3276 				/* find out if mtool_msgs_fd is a valid file descriptor */
3277 				if (fstat(mtool_msgs_fd, &statbuf) < 0) {
3278 					fatal(gettext("Invalid file descriptor %d after -O flag"), mtool_msgs_fd);
3279 				}
3280 				argv[i] = NULL;
3281 				argv[i+1] = NULL;
3282 				continue;
3283 			case 256: /* -K seen */
3284 				if (argv[i+1] == NULL) {
3285 					fatal(gettext("No makestate filename argument after -K flag"));
3286 				}
3287 				MBSTOWCS(wcs_buffer, argv[i+1]);
3288 				make_state = GETNAME(wcs_buffer, FIND_LENGTH);
3289 				keep_state = true;
3290 				argv[i] = NULL;
3291 				argv[i+1] = NULL;
3292 				continue;
3293 			case 512:	/* -o seen */
3294 				if (argv[i+1] == NULL) {
3295 					fatal(gettext("No dmake output dir argument after -o flag"));
3296 				}
3297 				MBSTOWCS(wcs_buffer, NOCATGETS("DMAKE_ODIR"));
3298 				name = GETNAME(wcs_buffer, FIND_LENGTH);
3299 				break;
3300 			case 1024: /* -x seen */
3301 				if (argv[i+1] == NULL) {
3302 					fatal(gettext("No argument after -x flag"));
3303 				}
3304 				length = strlen( NOCATGETS("SUN_MAKE_COMPAT_MODE="));
3305 				if (strncmp(argv[i+1], NOCATGETS("SUN_MAKE_COMPAT_MODE="), length) == 0) {
3306 					argv[i+1] = ap = &argv[i+1][length];
3307 					MBSTOWCS(wcs_buffer, NOCATGETS("SUN_MAKE_COMPAT_MODE"));
3308 					name = GETNAME(wcs_buffer, FIND_LENGTH);
3309 					dmake_compat_mode_specified = dmake_add_mode_specified;
3310 					break;
3311 				}
3312 				length = strlen( NOCATGETS("DMAKE_OUTPUT_MODE="));
3313 				if (strncmp(argv[i+1], NOCATGETS("DMAKE_OUTPUT_MODE="), length) == 0) {
3314 					argv[i+1] = ap = &argv[i+1][length];
3315 					MBSTOWCS(wcs_buffer, NOCATGETS("DMAKE_OUTPUT_MODE"));
3316 					name = GETNAME(wcs_buffer, FIND_LENGTH);
3317 					dmake_output_mode_specified = dmake_add_mode_specified;
3318 				} else {
3319 					warning(gettext("Unknown argument `%s' after -x flag (ignored)"),
3320 					      argv[i+1]);
3321 					argv[i] = argv[i + 1] = NULL;
3322 					continue;
3323 				}
3324 				break;
3325 			case 2048: /* -C seen */
3326 				if (argv[i][2])		/* e.g. -Cdir */
3327 					ap = &argv[i][2];
3328 				else
3329 					argv[i+1] = NULL;
3330 				argv[i] = NULL;
3331 				continue;
3332 			default: /* Shouldn't reach here */
3333 				argv[i] = NULL;
3334 				continue;
3335 			}
3336 			argv[i] = NULL;
3337 			if (argv[i+1] == ap)	/* If optarg is separate */
3338 				argv[i+1] = NULL;
3339 			else
3340 				i--;
3341 			if (i == (argc - 1)) {
3342 				break;
3343 			}
3344 			if ((length = strlen(ap)) >= MAXPATHLEN) {
3345 				tmp_wcs_buffer = ALLOC_WC(length + 1);
3346 				(void) mbstowcs(tmp_wcs_buffer, ap, length + 1);
3347 				value = GETNAME(tmp_wcs_buffer, FIND_LENGTH);
3348 				retmem(tmp_wcs_buffer);
3349 			} else {
3350 				MBSTOWCS(wcs_buffer, ap);
3351 				value = GETNAME(wcs_buffer, FIND_LENGTH);
3352 			}
3353 		} else if ((cp = strchr(argv[i], (int) equal_char)) != NULL) {
3354 			Boolean	expand = false;
3355 			Boolean	gnuassign = false;
3356 
3357 			if (*(cp-1) == (int) plus_char) {
3358 				if (isspace(*(cp-2))) {		/* += */
3359 					append = true;
3360 					cp--;
3361 				}
3362 			} else if (*(cp-1) == (int) colon_char) {
3363 				if (*(cp-2) == (int) plus_char &&
3364 				    isspace(*(cp-3))) {		/* +:= */
3365 					append = true;
3366 					expand = true;
3367 					cp -= 2;
3368 				} else if (*(cp-2) == (int) colon_char) {
3369 					if (*(cp-3) == (int) colon_char) {
3370 						/* :::= */
3371 						cp -= 3;
3372 						expand = true;
3373 #ifdef	GNU_ASSIGN_BY_DEFAULT
3374 					} else {
3375 #else
3376 					} else if (posix || gnu_style) {
3377 #endif
3378 						/* ::= */
3379 						cp -= 2;
3380 						expand = true;
3381 						gnuassign = true;
3382 					}
3383 				}
3384 			}
3385 
3386 			/*
3387 			 * Combine all macro in dynamic array
3388 			 */
3389 			if (!append)
3390 				append_or_replace_macro_in_dyn_array(makeflags_and_macro, argv[i]);
3391 
3392 			while (isspace(*(cp-1))) {
3393 				cp--;
3394 			}
3395 			tmp_char = *cp;
3396 			*cp = (int) nul_char;
3397 			MBSTOWCS(wcs_buffer, argv[i]);
3398 			*cp = tmp_char;
3399 			name = GETNAME(wcs_buffer, wcslen(wcs_buffer));
3400 			if (gnuassign &&
3401 			    name->stat.macro_type == unknown_macro_type)
3402 				name->stat.macro_type = gnu_assign;
3403 			while (*cp != (int) equal_char) {
3404 				cp++;
3405 			}
3406 			cp++;
3407 			while (isspace(*cp) && (*cp != (int) nul_char)) {
3408 				cp++;
3409 			}
3410 			if ((length = strlen(cp)) >= MAXPATHLEN) {
3411 				tmp_wcs_buffer = ALLOC_WC(length + 1);
3412 				(void) mbstowcs(tmp_wcs_buffer, cp, length + 1);
3413 				value = GETNAME(tmp_wcs_buffer, FIND_LENGTH);
3414 				retmem(tmp_wcs_buffer);
3415 			} else {
3416 				MBSTOWCS(wcs_buffer, cp);
3417 				value = GETNAME(wcs_buffer, FIND_LENGTH);
3418 			}
3419 			if (expand) {
3420 				String_rec	val;
3421 				wchar_t		buffer[STRING_BUFFER_LENGTH];
3422 
3423 				INIT_STRING_FROM_STACK(val, buffer);
3424 				expand_value(value, &val, false);
3425 				value = GETNAME(val.buffer.start, FIND_LENGTH);
3426 			}
3427 			argv[i] = NULL;
3428 		} else {
3429 			/* Illegal MAKEFLAGS argument */
3430 			continue;
3431 		}
3432 		if(append) {
3433 			setvar_append(name, value);
3434 			append = false;
3435 		} else {
3436 			macro = maybe_append_prop(name, macro_prop);
3437 			macro->body.macro.exported = true;
3438 			SETVAR(name, value, false)->body.macro.read_only = true;
3439 		}
3440 	}
3441 }
3442 
3443 /*
3444  * Append the DMake option and value to the MAKEFLAGS string.
3445  */
3446 static void
3447 append_makeflags_string(Name name, register String makeflags_string)
3448 {
3449 	char		*option;
3450 
3451 	if (strcmp(name->string_mb, NOCATGETS("DMAKE_GROUP")) == 0) {
3452 		option = (char *)NOCATGETS(" -g ");
3453 	} else if (strcmp(name->string_mb, NOCATGETS("DMAKE_MAX_JOBS")) == 0) {
3454 		option = (char *)NOCATGETS(" -j ");
3455 	} else if (strcmp(name->string_mb, NOCATGETS("DMAKE_MODE")) == 0) {
3456 		option = (char *)NOCATGETS(" -m ");
3457 	} else if (strcmp(name->string_mb, NOCATGETS("DMAKE_ODIR")) == 0) {
3458 		option = (char *)NOCATGETS(" -o ");
3459 	} else if (strcmp(name->string_mb, NOCATGETS("DMAKE_RCFILE")) == 0) {
3460 		option = (char *)NOCATGETS(" -c ");
3461 	} else if (strcmp(name->string_mb, NOCATGETS("PMAKE_MACHINESFILE")) == 0) {
3462 		option = (char *)NOCATGETS(" -M ");
3463 	} else if (strcmp(name->string_mb, NOCATGETS("DMAKE_OUTPUT_MODE")) == 0) {
3464 		option = (char *)NOCATGETS(" -x DMAKE_OUTPUT_MODE=");
3465 	} else if (strcmp(name->string_mb, NOCATGETS("SUN_MAKE_COMPAT_MODE")) == 0) {
3466 		option = (char *)NOCATGETS(" -x SUN_MAKE_COMPAT_MODE=");
3467 	} else {
3468 		fatal(gettext("Internal error: name not recognized in append_makeflags_string()"));
3469 	}
3470 	Property prop = maybe_append_prop(name, macro_prop);
3471 	if( prop == 0 || prop->body.macro.value == 0 ||
3472 	    prop->body.macro.value->string_mb == 0 ) {
3473 		return;
3474 	}
3475 	char mbs_value[MAXPATHLEN + 100];
3476 	strcpy(mbs_value, option);
3477 	strcat(mbs_value, prop->body.macro.value->string_mb);
3478 	MBSTOWCS(wcs_buffer, mbs_value);
3479 	append_string(wcs_buffer, makeflags_string, FIND_LENGTH);
3480 }
3481 
3482 /*
3483  *	read_environment(read_only)
3484  *
3485  *	This routine reads the process environment when make starts and enters
3486  *	it as make macros. The environment variable SHELL is ignored.
3487  *
3488  *	Parameters:
3489  *		read_only	Should we make env vars read only?
3490  *
3491  *	Global variables used:
3492  *		report_pwd	Set if this make was started by other make
3493  */
3494 static void
3495 read_environment(Boolean read_only)
3496 {
3497 	register char		**environment;
3498 	int			length;
3499 	wchar_t			*tmp_wcs_buffer;
3500 	Boolean			alloced_tmp_wcs_buffer = false;
3501 	register wchar_t	*name;
3502 	register wchar_t	*value;
3503 	register Name		macro;
3504 	Property		val;
3505 	Boolean			read_only_saved;
3506 
3507 	reading_environment = true;
3508 	environment = environ;
3509 	for (; *environment; environment++) {
3510 		read_only_saved = read_only;
3511 		if ((length = strlen(*environment)) >= MAXPATHLEN) {
3512 			tmp_wcs_buffer = ALLOC_WC(length + 1);
3513 			alloced_tmp_wcs_buffer = true;
3514 			(void) mbstowcs(tmp_wcs_buffer, *environment, length + 1);
3515 			name = tmp_wcs_buffer;
3516 		} else {
3517 			MBSTOWCS(wcs_buffer, *environment);
3518 			name = wcs_buffer;
3519 		}
3520 		value = (wchar_t *) wcschr(name, (int) equal_char);
3521 
3522 		/*
3523 		 * Looks like there's a bug in the system, but sometimes
3524 		 * you can get blank lines in *environment.
3525 		 */
3526 		if (!value) {
3527 			continue;
3528 		}
3529 		MBSTOWCS(wcs_buffer2, NOCATGETS("SHELL="));
3530 		if (IS_WEQUALN(name, wcs_buffer2, wcslen(wcs_buffer2))) {
3531 			continue;
3532 		}
3533 		MBSTOWCS(wcs_buffer2, NOCATGETS("MAKEFLAGS="));
3534 		if (IS_WEQUALN(name, wcs_buffer2, wcslen(wcs_buffer2))) {
3535 			report_pwd = true;
3536 			/*
3537 			 * In POSIX mode we do not want MAKEFLAGS to be readonly.
3538 			 * If the MAKEFLAGS macro is subsequently set by the makefile,
3539 			 * it replaces the MAKEFLAGS variable currently found in the
3540 			 * environment.
3541 			 * See Assertion 50 in section 6.2.5.3 of standard P1003.3.2/D8.
3542 			 */
3543 			if(posix) {
3544 				read_only_saved = false;
3545 			}
3546 		}
3547 
3548 		/*
3549 		 * We ignore SUNPRO_DEPENDENCIES and NSE_DEP. Those
3550 		 * environment variables are set by make and read by
3551 		 * cpp which then writes info to .make.dependency.xxx and
3552 		 * .nse_depinfo. When make is invoked by another make
3553 		 * (recursive make), we don't want to read this because
3554 		 * then the child make will end up writing to the parent
3555 		 * directory's .make.state and .nse_depinfo and clobbering
3556 		 * them.
3557 		 */
3558 		MBSTOWCS(wcs_buffer2, NOCATGETS("SUNPRO_DEPENDENCIES"));
3559 		if (IS_WEQUALN(name, wcs_buffer2, wcslen(wcs_buffer2))) {
3560 			continue;
3561 		}
3562 #ifdef NSE
3563 		MBSTOWCS(wcs_buffer2, NOCATGETS("NSE_DEP"));
3564 		if (IS_WEQUALN(name, wcs_buffer2, wcslen(wcs_buffer2))) {
3565 			continue;
3566 		}
3567 #endif
3568 
3569 		macro = GETNAME(name, value - name);
3570 		maybe_append_prop(macro, macro_prop)->body.macro.exported =
3571 		  true;
3572 		if ((value == NULL) || ((value + 1)[0] == (int) nul_char)) {
3573 			val = setvar_daemon(macro,
3574 					    (Name) NULL,
3575 					    false, no_daemon, false, debug_level);
3576 		} else {
3577 			val = setvar_daemon(macro,
3578 					    GETNAME(value + 1, FIND_LENGTH),
3579 					    false, no_daemon, false, debug_level);
3580 		}
3581 #ifdef NSE
3582                 /*
3583 	         * Must be after the call to setvar() as it sets
3584 	         * imported to false.
3585 	         */
3586 		maybe_append_prop(macro, macro_prop)->body.macro.imported = true;
3587 #endif
3588 		val->body.macro.read_only = read_only_saved;
3589 		if (alloced_tmp_wcs_buffer) {
3590 			retmem(tmp_wcs_buffer);
3591 			alloced_tmp_wcs_buffer = false;
3592 		}
3593 	}
3594 	reading_environment = false;
3595 }
3596 
3597 /*
3598  *	read_makefile(makefile, complain, must_exist, report_file)
3599  *
3600  *	Read one makefile and check the result
3601  *
3602  *	Return value:
3603  *				false is the read failed
3604  *
3605  *	Parameters:
3606  *		makefile	The file to read
3607  *		complain	Passed thru to read_simple_file()
3608  *		must_exist	Passed thru to read_simple_file()
3609  *		report_file	Passed thru to read_simple_file()
3610  *
3611  *	Global variables used:
3612  *		makefile_type	Set to indicate we are reading main file
3613  *		recursion_level	Initialized
3614  */
3615 static Boolean
3616 read_makefile(register Name makefile, Boolean complain, Boolean must_exist, Boolean report_file)
3617 {
3618 	Boolean			b;
3619 
3620 	makefile_type = reading_makefile;
3621 	recursion_level = 0;
3622 #ifdef NSE
3623 	wcscpy(current_makefile, makefile->string);
3624 #endif
3625 	reading_dependencies = true;
3626 	b = read_simple_file(makefile, true, true, complain,
3627 			     must_exist, report_file, false);
3628 	reading_dependencies = false;
3629 	return b;
3630 }
3631 
3632 /*
3633  *	make_targets(argc, argv, parallel_flag)
3634  *
3635  *	Call doname on the specified targets
3636  *
3637  *	Parameters:
3638  *		argc		You know what this is
3639  *		argv		You know what this is
3640  *		parallel_flag	True if building in parallel
3641  *
3642  *	Global variables used:
3643  *		build_failed_seen Used to generated message after failed -k
3644  *		commands_done	Used to generate message "Up to date"
3645  *		default_target_to_build	First proper target in makefile
3646  *		init		The Name ".INIT", use to run command
3647  *		parallel	Global parallel building flag
3648  *		quest		make -q, suppresses messages
3649  *		recursion_level	Initialized, used for tracing
3650  *		report_dependencies make -P, regroves whole process
3651  */
3652 static void
3653 make_targets(int argc, char **argv, Boolean parallel_flag)
3654 {
3655 	int			i;
3656 	char			*cp;
3657 	Doname			result;
3658 	register Boolean	target_to_make_found = false;
3659 
3660 	(void) doname(init, true, true);
3661 	recursion_level = 1;
3662 	parallel = parallel_flag;
3663 /*
3664  *	make remaining args
3665  */
3666 #if defined(TEAMWARE_MAKE_CMN) || defined(PMAKE)
3667 /*
3668 	if ((report_dependencies_level == 0) && parallel) {
3669  */
3670 	if (parallel) {
3671 		/*
3672 		 * If building targets in parallel, start all of the
3673 		 * remaining args to build in parallel.
3674 		 */
3675 		for (i = 1; i < argc; i++) {
3676 			if ((cp = argv[i]) != NULL) {
3677 				commands_done = false;
3678 				if ((cp[0] == (int) period_char) &&
3679 				    (cp[1] == (int) slash_char)) {
3680 					cp += 2;
3681 				}
3682 				 if((cp[0] == (int) ' ') &&
3683 				    (cp[1] == (int) '-') &&
3684 				    (cp[2] == (int) ' ') &&
3685 				    (cp[3] == (int) '-')) {
3686 			            argv[i] = NULL;
3687 					continue;
3688 				}
3689 				MBSTOWCS(wcs_buffer, cp);
3690 				//default_target_to_build = GETNAME(wcs_buffer,
3691 				//				  FIND_LENGTH);
3692 				default_target_to_build = normalize_name(wcs_buffer,
3693 								  wcslen(wcs_buffer));
3694 				if (default_target_to_build == wait_name) {
3695 					if (parallel_process_cnt > 0) {
3696 						finish_running();
3697 					}
3698 					continue;
3699 				}
3700 				top_level_target = get_wstring(default_target_to_build->string_mb);
3701 				/*
3702 				 * If we can't execute the current target in
3703 				 * parallel, hold off the target processing
3704 				 * to preserve the order of the targets as they appeared
3705 				 * in command line.
3706 				 */
3707 				if (!parallel_ok(default_target_to_build, false)
3708 						&& parallel_process_cnt > 0) {
3709 					finish_running();
3710 				}
3711 				result = doname_check(default_target_to_build,
3712 						      true,
3713 						      false,
3714 						      false);
3715 				gather_recursive_deps();
3716 				if (/* !commands_done && */
3717 				    (result == build_ok) &&
3718 				    !quest &&
3719 				    (report_dependencies_level == 0) /*  &&
3720 				    (exists(default_target_to_build) > file_doesnt_exist)  */) {
3721 					if (posix) {
3722 						if (!commands_done) {
3723 							(void) printf(gettext("`%s' is updated.\n"),
3724 						 		      default_target_to_build->string_mb);
3725 						} else {
3726 							if (no_action_was_taken) {
3727 								(void) printf(gettext("`%s': no action was taken.\n"),
3728 						 			      default_target_to_build->string_mb);
3729 							}
3730 						}
3731 					} else {
3732 						default_target_to_build->stat.time = file_no_time;
3733 						if (!commands_done &&
3734 						    !default_target_to_build->stat.is_phony &&
3735 						    (exists(default_target_to_build) > file_doesnt_exist)) {
3736 							(void) printf(gettext("`%s' is up to date.\n"),
3737 								      default_target_to_build->string_mb);
3738 						}
3739 					}
3740 				}
3741 			}
3742 		}
3743 		/* Now wait for all of the targets to finish running */
3744 		finish_running();
3745 		//		setjmp(jmpbuffer);
3746 
3747 	}
3748 #endif
3749 	for (i = 1; i < argc; i++) {
3750 		if ((cp = argv[i]) != NULL) {
3751 			target_to_make_found = true;
3752 			if ((cp[0] == (int) period_char) &&
3753 			    (cp[1] == (int) slash_char)) {
3754 				cp += 2;
3755 			}
3756 				 if((cp[0] == (int) ' ') &&
3757 				    (cp[1] == (int) '-') &&
3758 				    (cp[2] == (int) ' ') &&
3759 				    (cp[3] == (int) '-')) {
3760 			            argv[i] = NULL;
3761 					continue;
3762 				}
3763 			MBSTOWCS(wcs_buffer, cp);
3764 			default_target_to_build = normalize_name(wcs_buffer, wcslen(wcs_buffer));
3765 			top_level_target = get_wstring(default_target_to_build->string_mb);
3766 			report_recursion(default_target_to_build);
3767 			commands_done = false;
3768 			if (parallel) {
3769 				result = (Doname) default_target_to_build->state;
3770 			} else {
3771 				result = doname_check(default_target_to_build,
3772 						      true,
3773 						      false,
3774 						      false);
3775 			}
3776 			gather_recursive_deps();
3777 			if (build_failed_seen) {
3778 				build_failed_ever_seen = true;
3779 				warning(gettext("Target `%s' not remade because of errors"),
3780 					default_target_to_build->string_mb);
3781 			}
3782 			build_failed_seen = false;
3783 			if (report_dependencies_level > 0) {
3784 				print_dependencies(default_target_to_build,
3785 						   get_prop(default_target_to_build->prop,
3786 							    line_prop));
3787 			}
3788 			default_target_to_build->stat.time =
3789 			  file_no_time;
3790 			if (default_target_to_build->colon_splits > 0) {
3791 				default_target_to_build->state =
3792 				  build_dont_know;
3793 			}
3794 			if (!parallel &&
3795 			    /* !commands_done && */
3796 			    (result == build_ok) &&
3797 			    !quest &&
3798 			    (report_dependencies_level == 0) /*  &&
3799 			    (exists(default_target_to_build) > file_doesnt_exist)  */) {
3800 				if (posix) {
3801 					if (!commands_done) {
3802 						(void) printf(gettext("`%s' is updated.\n"),
3803 					 		      default_target_to_build->string_mb);
3804 					} else {
3805 						if (no_action_was_taken) {
3806 							(void) printf(gettext("`%s': no action was taken.\n"),
3807 					 			      default_target_to_build->string_mb);
3808 						}
3809 					}
3810 				} else {
3811 					if (!commands_done &&
3812 					    !default_target_to_build->stat.is_phony &&
3813 					    (exists(default_target_to_build) > file_doesnt_exist)) {
3814 						(void) printf(gettext("`%s' is up to date.\n"),
3815 							      default_target_to_build->string_mb);
3816 					}
3817 				}
3818 			}
3819 		}
3820 	}
3821 
3822 /*
3823  *	If no file arguments have been encountered,
3824  *	make the first name encountered that doesnt start with a dot
3825  */
3826 	if (!target_to_make_found) {
3827 		if (default_target_to_build == NULL) {
3828 			fatal(gettext("No arguments to build"));
3829 		}
3830 		commands_done = false;
3831 		top_level_target = get_wstring(default_target_to_build->string_mb);
3832 		report_recursion(default_target_to_build);
3833 
3834 
3835 		if (getenv(NOCATGETS("SPRO_EXPAND_ERRORS"))){
3836 			(void) printf(NOCATGETS("::(%s)\n"),
3837 				      default_target_to_build->string_mb);
3838 		}
3839 
3840 
3841 #if defined(TEAMWARE_MAKE_CMN) || defined(PMAKE)
3842 		result = doname_parallel(default_target_to_build, true, false);
3843 #else
3844 		result = doname_check(default_target_to_build, true,
3845 				      false, false);
3846 #endif
3847 		gather_recursive_deps();
3848 		if (build_failed_seen) {
3849 			build_failed_ever_seen = true;
3850 			warning(gettext("Target `%s' not remade because of errors"),
3851 				default_target_to_build->string_mb);
3852 		}
3853 		build_failed_seen = false;
3854 		if (report_dependencies_level > 0) {
3855 			print_dependencies(default_target_to_build,
3856 					   get_prop(default_target_to_build->
3857 						    prop,
3858 						    line_prop));
3859 		}
3860 		default_target_to_build->stat.time = file_no_time;
3861 		if (default_target_to_build->colon_splits > 0) {
3862 			default_target_to_build->state = build_dont_know;
3863 		}
3864 		if (/* !commands_done && */
3865 		    (result == build_ok) &&
3866 		    !quest &&
3867 		    (report_dependencies_level == 0) /*  &&
3868 		    (exists(default_target_to_build) > file_doesnt_exist)  */) {
3869 			if (posix) {
3870 				if (!commands_done) {
3871 					(void) printf(gettext("`%s' is updated.\n"),
3872 				 		      default_target_to_build->string_mb);
3873 				} else {
3874 					if (no_action_was_taken) {
3875 						(void) printf(gettext("`%s': no action was taken.\n"),
3876 							      default_target_to_build->string_mb);
3877 					}
3878 				}
3879 			} else {
3880 				if (!commands_done &&
3881 				    !default_target_to_build->stat.is_phony &&
3882 				    (exists(default_target_to_build) > file_doesnt_exist)) {
3883 					(void) printf(gettext("`%s' is up to date.\n"),
3884 						      default_target_to_build->string_mb);
3885 				}
3886 			}
3887 		}
3888 	}
3889 }
3890 
3891 /*
3892  *	report_recursion(target)
3893  *
3894  *	If this is a recursive make and the parent make has KEEP_STATE on
3895  *	this routine reports the dependency to the parent make
3896  *
3897  *	Parameters:
3898  *		target		Target to report
3899  *
3900  *	Global variables used:
3901  *		makefiles_used		List of makefiles read
3902  *		recursive_name		The Name ".RECURSIVE", printed
3903  *		report_dependency	dwight
3904  */
3905 static void
3906 report_recursion(register Name target)
3907 {
3908 	register FILE		*report_file = get_report_file();
3909 
3910 	if ((report_file == NULL) || (report_file == (FILE*)-1)) {
3911 		return;
3912 	}
3913 	if (primary_makefile == NULL) {
3914 		/*
3915 		 * This can happen when there is no makefile and
3916 		 * only implicit rules are being used.
3917 		 */
3918 #ifdef NSE
3919 		nse_no_makefile(target);
3920 #endif
3921 		return;
3922 	}
3923 	(void) fprintf(report_file,
3924 		       "%s: %s ",
3925 		       get_target_being_reported_for(),
3926 		       recursive_name->string_mb);
3927 	report_dependency(get_current_path());
3928 	report_dependency(target->string_mb);
3929 	report_dependency(primary_makefile->string_mb);
3930 	(void) fprintf(report_file, "\n");
3931 }
3932 
3933 /* Next function "append_or_replace_macro_in_dyn_array" must be in "misc.cc". */
3934 /* NIKMOL */
3935 extern void
3936 append_or_replace_macro_in_dyn_array(ASCII_Dyn_Array *Ar, char *macro)
3937 {
3938 	register char	*cp0;	/* work pointer in macro */
3939 	register char	*cp1;	/* work pointer in array */
3940 	register char	*cp2;	/* work pointer in array */
3941 	register char	*cp3;	/* work pointer in array */
3942 	register char	*name;	/* macro name */
3943 	register char	*value;	/* macro value */
3944 	register int 	len_array;
3945 	register int 	len_macro;
3946 		Boolean	isassign = false;
3947 		Boolean	isgnuassign = false;
3948 
3949 	char * esc_value = NULL;
3950 	int esc_len;
3951 
3952 	if (!(len_macro = strlen(macro))) return;
3953 	name = macro;
3954 	while (isspace(*(name))) {
3955 		name++;
3956 	}
3957 	if (!(value = strchr(name, (int) equal_char))) {
3958 		/* no '=' in macro */
3959 		goto ERROR_MACRO;
3960 	}
3961 	cp0 = value;
3962 	value++;
3963 	while (isspace(*(value))) {
3964 		value++;
3965 	}
3966 
3967 	if (cp0[-1] == ':' && cp0[-2] == ':') {
3968 		cp0 -= 2;
3969 		if (cp0[-1] == ':') {
3970 			cp0--;
3971 			isassign = true;
3972 #ifdef	GNU_ASSIGN_BY_DEFAULT
3973 		} else {
3974 			isgnuassign = true;
3975 		}
3976 #else
3977 		} else if (posix || gnu_style) {
3978 			isgnuassign = true;
3979 		} else {
3980 			cp0 += 2;
3981 		}
3982 #endif
3983 	}
3984 	while (isspace(*(cp0-1))) {
3985 		cp0--;
3986 	}
3987 	if (cp0 <= name) goto ERROR_MACRO; /* no name */
3988 	if (!(Ar->size)) goto ALLOC_ARRAY;
3989 	cp1 = Ar->start;
3990 
3991 LOOK_FOR_NAME:
3992 	if (!(cp1 = strchr(cp1, name[0]))) goto APPEND_MACRO;
3993 	if (!(cp2 = strchr(cp1, (int) equal_char))) goto APPEND_MACRO;
3994 	if (strncmp(cp1, name, (size_t)(cp0-name))) {
3995 		/* another name */
3996 		cp1++;
3997 		goto LOOK_FOR_NAME;
3998 	}
3999 	if (cp1 != Ar->start) {
4000 		if (!isspace(*(cp1-1))) {
4001 			/* another name */
4002 			cp1++;
4003 			goto LOOK_FOR_NAME;
4004 		}
4005 	}
4006 	for (cp3 = cp1 + (cp0-name); cp3 < cp2; cp3++) {
4007 		if (isspace(*cp3)) continue;
4008 		/* else: another name */
4009 		cp1++;
4010 		goto LOOK_FOR_NAME;
4011 	}
4012 	/* Look for the next macro name in array */
4013 	cp3 = cp2+1;
4014 	if (*cp3 != (int) doublequote_char) {
4015 		/* internal error */
4016 		goto ERROR_MACRO;
4017 	}
4018 	if (!(cp3 = strchr(cp3+1, (int) doublequote_char))) {
4019 		/* internal error */
4020 		goto ERROR_MACRO;
4021 	}
4022 	cp3++;
4023 	while (isspace(*cp3)) {
4024 		cp3++;
4025 	}
4026 
4027 	cp2 = cp1;  /* remove old macro */
4028 	if ((*cp3) && (cp3 < Ar->start + Ar->size)) {
4029 		for (; cp3 < Ar->start + Ar->size; cp3++) {
4030 			*cp2++ = *cp3;
4031 		}
4032 	}
4033 	for (; cp2 < Ar->start + Ar->size; cp2++) {
4034 		*cp2 = 0;
4035 	}
4036 	if (*cp1) {
4037 		/* check next name */
4038 		goto LOOK_FOR_NAME;
4039 	}
4040 	goto APPEND_MACRO;
4041 
4042 ALLOC_ARRAY:
4043 	if (Ar->size) {
4044 		cp1 = Ar->start;
4045 	} else {
4046 		cp1 = 0;
4047 	}
4048 	Ar->size += 128;
4049 	Ar->start = getmem(Ar->size);
4050 	for (len_array=0; len_array < Ar->size; len_array++) {
4051 		Ar->start[len_array] = 0;
4052 	}
4053 	if (cp1) {
4054 		strcpy(Ar->start, cp1);
4055 		retmem((wchar_t *) cp1);
4056 	}
4057 
4058 APPEND_MACRO:
4059 	len_array = strlen(Ar->start);
4060 	esc_value = (char*)malloc(strlen(value)*2 + 1);
4061 	quote_str(value, esc_value);
4062 	esc_len = strlen(esc_value) - strlen(value);
4063 	if (len_array + len_macro + esc_len + 5 >= Ar->size) goto  ALLOC_ARRAY;
4064 	strcat(Ar->start, " ");
4065 	strncat(Ar->start, name, cp0-name);
4066 	if (isassign)
4067 		strcat(Ar->start, ":::=");
4068 	else if (isgnuassign)
4069 		strcat(Ar->start, "::=");
4070 	else
4071 		strcat(Ar->start, "=");
4072 	strncat(Ar->start, esc_value, strlen(esc_value));
4073 	free(esc_value);
4074 	return;
4075 ERROR_MACRO:
4076 	/* Macro without '=' or with invalid left/right part */
4077 	return;
4078 }
4079 
4080 #ifdef TEAMWARE_MAKE_CMN
4081 /*
4082  * This function, if registered w/ avo_cli_get_license(), will be called
4083  * if the application is about to exit because:
4084  *   1) there has been certain unrecoverable error(s) that cause the
4085  *      application to exit immediately.
4086  *   2) the user has lost a license while the application is running.
4087  */
4088 extern "C" void
dmake_exit_callback(void)4089 dmake_exit_callback(void)
4090 {
4091 	fatal(gettext("can not get a license, exiting..."));
4092 	exit(1);
4093 }
4094 
4095 /*
4096  * This function, if registered w/ avo_cli_get_license(), will be called
4097  * if the application can not get a license.
4098  */
4099 extern "C" void
dmake_message_callback(char * err_msg)4100 dmake_message_callback(char *err_msg)
4101 {
4102 	static Boolean	first = true;
4103 
4104 	if (!first) {
4105 		return;
4106 	}
4107 	first = false;
4108 	if ((!list_all_targets) &&
4109 	    (report_dependencies_level == 0) &&
4110 	    (dmake_mode_type != serial_mode)) {
4111 		warning(gettext("can not get a TeamWare license, defaulting to serial mode..."));
4112 	}
4113 }
4114 #endif
4115 
4116 #ifdef DISTRIBUTED
4117 /*
4118  * Returns whether -c is set or not.
4119  */
4120 Boolean
get_dmake_rcfile_specified(void)4121 get_dmake_rcfile_specified(void)
4122 {
4123 	return(dmake_rcfile_specified);
4124 }
4125 
4126 /*
4127  * Returns whether -g is set or not.
4128  */
4129 Boolean
get_dmake_group_specified(void)4130 get_dmake_group_specified(void)
4131 {
4132 	return(dmake_group_specified);
4133 }
4134 
4135 /*
4136  * Returns whether -j is set or not.
4137  */
4138 Boolean
get_dmake_max_jobs_specified(void)4139 get_dmake_max_jobs_specified(void)
4140 {
4141 	return(dmake_max_jobs_specified);
4142 }
4143 
4144 /*
4145  * Returns whether -m is set or not.
4146  */
4147 Boolean
get_dmake_mode_specified(void)4148 get_dmake_mode_specified(void)
4149 {
4150 	return(dmake_mode_specified);
4151 }
4152 
4153 /*
4154  * Returns whether -o is set or not.
4155  */
4156 Boolean
get_dmake_odir_specified(void)4157 get_dmake_odir_specified(void)
4158 {
4159 	return(dmake_odir_specified);
4160 }
4161 
4162 #endif
4163 
4164 static void
dir_enter_leave(Boolean entering)4165 dir_enter_leave(Boolean entering)
4166 {
4167 static	char *	mlev = NULL;
4168 	char *	make_level_str = NULL;
4169 	int	make_level_val = 0;
4170 
4171 	make_level_str = getenv(NOCATGETS("MAKELEVEL"));
4172 	if (make_level_str) {
4173 		make_level_val = atoi(make_level_str);
4174 	}
4175 	if (mlev == NULL) {
4176 		mlev = (char*) malloc(MAXPATHLEN);
4177 	}
4178 	if (entering) {
4179 		sprintf(mlev, NOCATGETS("MAKELEVEL=%d"), make_level_val + 1);
4180 	} else {
4181 		make_level_val--;
4182 		sprintf(mlev, NOCATGETS("MAKELEVEL=%d"), make_level_val);
4183 	}
4184 	putenv(mlev);
4185 }
4186 
4187 static void
report_dir_enter_leave(Boolean entering)4188 report_dir_enter_leave(Boolean entering)
4189 {
4190 	char	rcwd[MAXPATHLEN];
4191 	char *	make_level_str = NULL;
4192 	int	make_level_val = 0;
4193 
4194 	make_level_str = getenv(NOCATGETS("MAKELEVEL"));
4195 	if (make_level_str) {
4196 		make_level_val = atoi(make_level_str);
4197 	}
4198 	/*
4199 	 * We previously did increment our environment, so we need to
4200 	 * correct this to get the correct value for this level.
4201 	 */
4202 	make_level_val--;
4203 
4204 	if (report_cwd) {
4205 		if (make_level_val <= 0) {
4206 			if (entering) {
4207 #ifdef TEAMWARE_MAKE_CMN
4208 				sprintf( rcwd
4209 				       , gettext("dmake: Entering directory `%s'\n")
4210 				       , get_current_path());
4211 #else
4212 				sprintf( rcwd
4213 				       , gettext("make: Entering directory `%s'\n")
4214 				       , get_current_path());
4215 #endif
4216 			} else {
4217 #ifdef TEAMWARE_MAKE_CMN
4218 				sprintf( rcwd
4219 				       , gettext("dmake: Leaving directory `%s'\n")
4220 				       , get_current_path());
4221 #else
4222 				sprintf( rcwd
4223 				       , gettext("make: Leaving directory `%s'\n")
4224 				       , get_current_path());
4225 #endif
4226 			}
4227 		} else {
4228 			if (entering) {
4229 #ifdef TEAMWARE_MAKE_CMN
4230 				sprintf( rcwd
4231 				       , gettext("dmake[%d]: Entering directory `%s'\n")
4232 				       , make_level_val, get_current_path());
4233 #else
4234 				sprintf( rcwd
4235 				       , gettext("make[%d]: Entering directory `%s'\n")
4236 				       , make_level_val, get_current_path());
4237 #endif
4238 			} else {
4239 #ifdef TEAMWARE_MAKE_CMN
4240 				sprintf( rcwd
4241 				       , gettext("dmake[%d]: Leaving directory `%s'\n")
4242 				       , make_level_val, get_current_path());
4243 #else
4244 				sprintf( rcwd
4245 				       , gettext("make[%d]: Leaving directory `%s'\n")
4246 				       , make_level_val, get_current_path());
4247 #endif
4248 			}
4249 		}
4250 		printf(NOCATGETS("%s"), rcwd);
4251 	}
4252 }
4253 
4254 char *
find_run_dir()4255 find_run_dir()
4256 {
4257 #ifdef	HAVE_GETEXECNAME
4258 	/*
4259 	 * This is the easy method but it works only on Solaris.
4260 	 * Try to use it as it helps us to avoid linking against libschily.
4261 	 */
4262 	const char	*exname = getexecname();
4263 	char		xpath[MAXPATHLEN];
4264 	int		amt;
4265 
4266 	/*
4267 	 * If getexecname() exists, it always returns a name for dynamically
4268 	 * linked processes.
4269 	 */
4270 	if (exname == NULL || *exname != '/') {
4271 		if ((amt = readlink("/proc/self/path/a.out",
4272 		    xpath, MAXPATHLEN-1)) < 0) {
4273 			return (NULL);
4274 		}
4275 		xpath[amt] = '\0';
4276 	} else {
4277 		strlcpy(xpath, exname, MAXPATHLEN);
4278 	}
4279 	return (strdup(dirname(xpath)));
4280 #else
4281 	char		*exname = getexecpath();
4282 	char		*ret;
4283 
4284 	if (exname == NULL) {
4285 		if (strchr(g_argv[0], (int) slash_char) == NULL) {
4286 			/*
4287 			 * Do pathname search only if we have been
4288 			 * called via PATH.
4289 			 */
4290 			exname = findinpath(g_argv[0], X_OK, TRUE, NULL);
4291 		} else {
4292 			/*
4293 			 * If arvg[0] starts with a slash, use it,
4294 			 * else use its concatenation with `pwd`.
4295 			 */
4296 			if (*g_argv[0] == slash_char)
4297 				exname = strdup(g_argv[0]);
4298 			else
4299 				exname = strdup(argv_zero_string);
4300 		}
4301 	}
4302 	if (exname == NULL)
4303 		return (NULL);
4304 	ret = strdup(dirname(exname));
4305 	free(exname);
4306 	return (ret);
4307 #endif
4308 }
4309