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 = ¬_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