1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21 /*
22 * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 */
25
26 /*
27 * main.cc
28 *
29 * make program main routine plus some helper routines
30 */
31
32 /*
33 * Included files
34 */
35 #if defined(TEAMWARE_MAKE_CMN)
36 # include <avo/intl.h>
37 #endif
38
39 #include <bsd/bsd.h> /* bsd_signal() */
40
41
42 #include <locale.h> /* setlocale() */
43 #include <libgen.h>
44 #include <mk/defs.h>
45 #include <mksdmsi18n/mksdmsi18n.h> /* libmksdmsi18n_init() */
46 #include <mksh/macro.h> /* getvar() */
47 #include <mksh/misc.h> /* getmem(), setup_char_semantics() */
48
49 #if defined(TEAMWARE_MAKE_CMN)
50 #endif
51
52 #include <pwd.h> /* getpwnam() */
53 #include <setjmp.h>
54 #include <signal.h>
55 #include <stdlib.h>
56 #include <sys/errno.h> /* ENOENT */
57 #include <sys/stat.h> /* fstat() */
58 #include <fcntl.h> /* open() */
59
60 # include <sys/systeminfo.h> /* sysinfo() */
61
62 #include <sys/types.h> /* stat() */
63 #include <sys/wait.h> /* wait() */
64 #include <unistd.h> /* execv(), unlink(), access() */
65 #include <vroot/report.h> /* report_dependency(), get_report_file() */
66
67 // From read2.cc
68 extern Name normalize_name(register wchar_t *name_string, register int length);
69
70 // From parallel.cc
71 #define MAXJOBS_ADJUST_RFE4694000
72
73 #ifdef MAXJOBS_ADJUST_RFE4694000
74 extern void job_adjust_fini();
75 #endif /* MAXJOBS_ADJUST_RFE4694000 */
76
77
78 /*
79 * Defined macros
80 */
81 #define MAKE_PREFIX NOCATGETS("/usr")
82 #define LD_SUPPORT_ENV_VAR NOCATGETS("SGS_SUPPORT_32")
83 #define LD_SUPPORT_ENV_VAR_32 NOCATGETS("SGS_SUPPORT_32")
84 #define LD_SUPPORT_ENV_VAR_64 NOCATGETS("SGS_SUPPORT_64")
85 #define LD_SUPPORT_MAKE_LIB NOCATGETS("libmakestate.so.1")
86 #define LD_SUPPORT_MAKE_LIB_DIR NOCATGETS("/lib")
87 #define LD_SUPPORT_MAKE_LIB_DIR_64 NOCATGETS("/64")
88
89 /*
90 * typedefs & structs
91 */
92
93 /*
94 * Static variables
95 */
96 static char *argv_zero_string;
97 static Boolean build_failed_ever_seen;
98 static Boolean continue_after_error_ever_seen; /* `-k' */
99 static Boolean dmake_group_specified; /* `-g' */
100 static Boolean dmake_max_jobs_specified; /* `-j' */
101 static Boolean dmake_mode_specified; /* `-m' */
102 static Boolean dmake_add_mode_specified; /* `-x' */
103 static Boolean dmake_output_mode_specified; /* `-x DMAKE_OUTPUT_MODE=' */
104 static Boolean dmake_compat_mode_specified; /* `-x SUN_MAKE_COMPAT_MODE=' */
105 static Boolean dmake_odir_specified; /* `-o' */
106 static Boolean dmake_rcfile_specified; /* `-c' */
107 static Boolean env_wins; /* `-e' */
108 static Boolean ignore_default_mk; /* `-r' */
109 static Boolean list_all_targets; /* `-T' */
110 static int mf_argc;
111 static char **mf_argv;
112 static Dependency_rec not_auto_depen_struct;
113 static Dependency not_auto_depen = ¬_auto_depen_struct;
114 static Boolean pmake_cap_r_specified; /* `-R' */
115 static Boolean pmake_machinesfile_specified; /* `-M' */
116 static Boolean stop_after_error_ever_seen; /* `-S' */
117 static Boolean trace_status; /* `-p' */
118
119 #ifdef DMAKE_STATISTICS
120 static Boolean getname_stat = false;
121 #endif
122
123 static time_t start_time;
124 static int g_argc;
125 static char **g_argv;
126
127 /*
128 * File table of contents
129 */
130 extern "C" void cleanup_after_exit(void);
131
132 extern "C" {
133 extern void dmake_exit_callback(void);
134 extern void dmake_message_callback(char *);
135 }
136
137 extern Name normalize_name(register wchar_t *name_string, register int length);
138
139 extern int main(int, char * []);
140
141 static void append_makeflags_string(Name, String);
142 static void doalarm(int);
143 static void enter_argv_values(int , char **, ASCII_Dyn_Array *);
144 static void make_targets(int, char **, Boolean);
145 static int parse_command_option(char);
146 static void read_command_options(int, char **);
147 static void read_environment(Boolean);
148 static void read_files_and_state(int, char **);
149 static Boolean read_makefile(Name, Boolean, Boolean, Boolean);
150 static void report_recursion(Name);
151 static void set_sgs_support(void);
152 static void setup_for_projectdir(void);
153 static void setup_makeflags_argv(void);
154 static void report_dir_enter_leave(Boolean entering);
155
156 extern void expand_value(Name, register String , Boolean);
157
158 static const char verstring[] = "illumos make";
159
160 jmp_buf jmpbuffer;
161 extern nl_catd catd;
162
163 /*
164 * main(argc, argv)
165 *
166 * Parameters:
167 * argc You know what this is
168 * argv You know what this is
169 *
170 * Static variables used:
171 * list_all_targets make -T seen
172 * trace_status make -p seen
173 *
174 * Global variables used:
175 * debug_level Should we trace make actions?
176 * keep_state Set if .KEEP_STATE seen
177 * makeflags The Name "MAKEFLAGS", used to get macro
178 * remote_command_name Name of remote invocation cmd ("on")
179 * running_list List of parallel running processes
180 * stdout_stderr_same true if stdout and stderr are the same
181 * auto_dependencies The Name "SUNPRO_DEPENDENCIES"
182 * temp_file_directory Set to the dir where we create tmp file
183 * trace_reader Set to reflect tracing status
184 * working_on_targets Set when building user targets
185 */
186 int
187 main(int argc, char *argv[])
188 {
189 /*
190 * cp is a -> to the value of the MAKEFLAGS env var,
191 * which has to be regular chars.
192 */
193 register char *cp;
194 char make_state_dir[MAXPATHLEN];
195 Boolean parallel_flag = false;
196 char *prognameptr;
197 char *slash_ptr;
198 mode_t um;
199 int i;
200 struct itimerval value;
201 char def_dmakerc_path[MAXPATHLEN];
202 Name dmake_name, dmake_name2;
203 Name dmake_value, dmake_value2;
204 Property prop, prop2;
205 struct stat statbuf;
206 int statval;
207
208 struct stat out_stat, err_stat;
209 hostid = gethostid();
210 bsd_signals();
211
212 (void) setlocale(LC_ALL, "");
213
214
215 #ifdef DMAKE_STATISTICS
216 if (getenv(NOCATGETS("DMAKE_STATISTICS"))) {
217 getname_stat = true;
218 }
219 #endif
220
221 catd = catopen(AVO_DOMAIN_DMAKE, NL_CAT_LOCALE);
222
223 // ---> fprintf(stderr, catgets(catd, 15, 666, "--- SUN make ---\n"));
224
225
226 /*
227 * I put libmksdmsi18n_init() under #ifdef because it requires avo_i18n_init()
228 * from avo_util library.
229 */
230 libmksdmsi18n_init();
231
232
233 textdomain(NOCATGETS("SUNW_SPRO_MAKE"));
234
235 g_argc = argc;
236 g_argv = (char **) malloc((g_argc + 1) * sizeof(char *));
237 for (i = 0; i < argc; i++) {
238 g_argv[i] = argv[i];
239 }
240 g_argv[i] = NULL;
241
242 /*
243 * Set argv_zero_string to some form of argv[0] for
244 * recursive MAKE builds.
245 */
246
247 if (*argv[0] == (int) slash_char) {
248 /* argv[0] starts with a slash */
249 argv_zero_string = strdup(argv[0]);
250 } else if (strchr(argv[0], (int) slash_char) == NULL) {
251 /* argv[0] contains no slashes */
252 argv_zero_string = strdup(argv[0]);
253 } else {
254 /*
255 * argv[0] contains at least one slash,
256 * but doesn't start with a slash
257 */
258 char *tmp_current_path;
259 char *tmp_string;
260
261 tmp_current_path = get_current_path();
262 tmp_string = getmem(strlen(tmp_current_path) + 1 +
263 strlen(argv[0]) + 1);
264 (void) sprintf(tmp_string,
265 "%s/%s",
266 tmp_current_path,
267 argv[0]);
268 argv_zero_string = strdup(tmp_string);
269 retmem_mb(tmp_string);
270 }
271
272 /*
273 * The following flags are reset if we don't have the
274 * (.nse_depinfo or .make.state) files locked and only set
275 * AFTER the file has been locked. This ensures that if the user
276 * interrupts the program while file_lock() is waiting to lock
277 * the file, the interrupt handler doesn't remove a lock
278 * that doesn't belong to us.
279 */
280 make_state_lockfile = NULL;
281 make_state_locked = false;
282
283
284 /*
285 * look for last slash char in the path to look at the binary
286 * name. This is to resolve the hard link and invoke make
287 * in svr4 mode.
288 */
289
290 /* Sun OS make standart */
291 svr4 = false;
292 posix = false;
293 if(!strcmp(argv_zero_string, NOCATGETS("/usr/xpg4/bin/make"))) {
294 svr4 = false;
295 posix = true;
296 } else {
297 prognameptr = strrchr(argv[0], '/');
298 if(prognameptr) {
299 prognameptr++;
300 } else {
301 prognameptr = argv[0];
302 }
303 if(!strcmp(prognameptr, NOCATGETS("svr4.make"))) {
304 svr4 = true;
305 posix = false;
306 }
307 }
308 if (getenv(USE_SVR4_MAKE) || getenv(NOCATGETS("USE_SVID"))){
309 svr4 = true;
310 posix = false;
311 }
312
313 /*
314 * Find the dmake_compat_mode: posix, sun, svr4, or gnu_style, .
315 */
316 char * dmake_compat_mode_var = getenv(NOCATGETS("SUN_MAKE_COMPAT_MODE"));
317 if (dmake_compat_mode_var != NULL) {
318 if (0 == strcasecmp(dmake_compat_mode_var, NOCATGETS("GNU"))) {
319 gnu_style = true;
320 }
321 //svr4 = false;
322 //posix = false;
323 }
324
325 /*
326 * Temporary directory set up.
327 */
328 char * tmpdir_var = getenv(NOCATGETS("TMPDIR"));
329 if (tmpdir_var != NULL && *tmpdir_var == '/' && strlen(tmpdir_var) < MAXPATHLEN) {
330 strcpy(mbs_buffer, tmpdir_var);
331 for (tmpdir_var = mbs_buffer+strlen(mbs_buffer);
332 *(--tmpdir_var) == '/' && tmpdir_var > mbs_buffer;
333 *tmpdir_var = '\0');
334 if (strlen(mbs_buffer) + 32 < MAXPATHLEN) { /* 32 = strlen("/dmake.stdout.%d.%d.XXXXXX") */
335 sprintf(mbs_buffer2, NOCATGETS("%s/dmake.tst.%d.XXXXXX"),
336 mbs_buffer, getpid());
337 int fd = mkstemp(mbs_buffer2);
338 if (fd >= 0) {
339 close(fd);
340 unlink(mbs_buffer2);
341 tmpdir = strdup(mbs_buffer);
342 }
343 }
344 }
345
346 /* find out if stdout and stderr point to the same place */
347 if (fstat(1, &out_stat) < 0) {
348 fatal(catgets(catd, 1, 165, "fstat of standard out failed: %s"), errmsg(errno));
349 }
350 if (fstat(2, &err_stat) < 0) {
351 fatal(catgets(catd, 1, 166, "fstat of standard error failed: %s"), errmsg(errno));
352 }
353 if ((out_stat.st_dev == err_stat.st_dev) &&
354 (out_stat.st_ino == err_stat.st_ino)) {
355 stdout_stderr_same = true;
356 } else {
357 stdout_stderr_same = false;
358 }
359 /* Make the vroot package scan the path using shell semantics */
360 set_path_style(0);
361
362 setup_char_semantics();
363
364 setup_for_projectdir();
365
366 /*
367 * If running with .KEEP_STATE, curdir will be set with
368 * the connected directory.
369 */
370 (void) atexit(cleanup_after_exit);
371
372 load_cached_names();
373
374 /*
375 * Set command line flags
376 */
377 setup_makeflags_argv();
378 read_command_options(mf_argc, mf_argv);
379 read_command_options(argc, argv);
380 if (debug_level > 0) {
381 cp = getenv(makeflags->string_mb);
382 (void) printf(catgets(catd, 1, 167, "MAKEFLAGS value: %s\n"), cp == NULL ? "" : cp);
383 }
384
385 setup_interrupt(handle_interrupt);
386
387 read_files_and_state(argc, argv);
388
389 /*
390 * Find the dmake_output_mode: TXT1, TXT2 or HTML1.
391 */
392 MBSTOWCS(wcs_buffer, NOCATGETS("DMAKE_OUTPUT_MODE"));
393 dmake_name2 = GETNAME(wcs_buffer, FIND_LENGTH);
394 prop2 = get_prop(dmake_name2->prop, macro_prop);
395 if (prop2 == NULL) {
396 /* DMAKE_OUTPUT_MODE not defined, default to TXT1 mode */
397 output_mode = txt1_mode;
398 } else {
399 dmake_value2 = prop2->body.macro.value;
400 if ((dmake_value2 == NULL) ||
401 (IS_EQUAL(dmake_value2->string_mb, NOCATGETS("TXT1")))) {
402 output_mode = txt1_mode;
403 } else if (IS_EQUAL(dmake_value2->string_mb, NOCATGETS("TXT2"))) {
404 output_mode = txt2_mode;
405 } else if (IS_EQUAL(dmake_value2->string_mb, NOCATGETS("HTML1"))) {
406 output_mode = html1_mode;
407 } else {
408 warning(catgets(catd, 1, 352, "Unsupported value `%s' for DMAKE_OUTPUT_MODE after -x flag (ignored)"),
409 dmake_value2->string_mb);
410 }
411 }
412 /*
413 * Find the dmake_mode: parallel, or serial.
414 */
415 if ((!pmake_cap_r_specified) &&
416 (!pmake_machinesfile_specified)) {
417 char *s = strdup(argv[0]);
418
419 MBSTOWCS(wcs_buffer, NOCATGETS("DMAKE_MODE"));
420 dmake_name2 = GETNAME(wcs_buffer, FIND_LENGTH);
421 prop2 = get_prop(dmake_name2->prop, macro_prop);
422 // If we're invoked as 'make' run serially, regardless of DMAKE_MODE
423 // If we're invoked as 'make' but passed -j, run parallel
424 // If we're invoked as 'dmake', without DMAKE_MODE, default parallel
425 // If we're invoked as 'dmake' and DMAKE_MODE is set, honour it.
426 if ((strcmp(basename(s), NOCATGETS("make")) == 0) &&
427 !dmake_max_jobs_specified) {
428 dmake_mode_type = serial_mode;
429 no_parallel = true;
430 } else if (prop2 == NULL) {
431 /* DMAKE_MODE not defined, default based on our name */
432 char *s = strdup(argv[0]);
433
434 if (strcmp(basename(s), NOCATGETS("dmake")) == 0) {
435 dmake_mode_type = parallel_mode;
436 no_parallel = false;
437 }
438 } else {
439 dmake_value2 = prop2->body.macro.value;
440 if (IS_EQUAL(dmake_value2->string_mb, NOCATGETS("parallel"))) {
441 dmake_mode_type = parallel_mode;
442 no_parallel = false;
443 } else if (IS_EQUAL(dmake_value2->string_mb, NOCATGETS("serial"))) {
444 dmake_mode_type = serial_mode;
445 no_parallel = true;
446 } else {
447 fatal(catgets(catd, 1, 307, "Unknown dmake mode argument `%s' after -m flag"), dmake_value2->string_mb);
448 }
449 }
450 free(s);
451 }
452
453 parallel_flag = true;
454 putenv(strdup(NOCATGETS("DMAKE_CHILD=TRUE")));
455
456 //
457 // If dmake is running with -t option, set dmake_mode_type to serial.
458 // This is done because doname() calls touch_command() that runs serially.
459 // If we do not do that, maketool will have problems.
460 //
461 if(touch) {
462 dmake_mode_type = serial_mode;
463 no_parallel = true;
464 }
465
466 /*
467 * Check whether stdout and stderr are physically same.
468 * This is in order to decide whether we need to redirect
469 * stderr separately from stdout.
470 * This check is performed only if __DMAKE_SEPARATE_STDERR
471 * is not set. This variable may be used in order to preserve
472 * the 'old' behaviour.
473 */
474 out_err_same = true;
475 char * dmake_sep_var = getenv(NOCATGETS("__DMAKE_SEPARATE_STDERR"));
476 if (dmake_sep_var == NULL || (0 != strcasecmp(dmake_sep_var, NOCATGETS("NO")))) {
477 struct stat stdout_stat;
478 struct stat stderr_stat;
479 if( (fstat(1, &stdout_stat) == 0)
480 && (fstat(2, &stderr_stat) == 0) )
481 {
482 if( (stdout_stat.st_dev != stderr_stat.st_dev)
483 || (stdout_stat.st_ino != stderr_stat.st_ino) )
484 {
485 out_err_same = false;
486 }
487 }
488 }
489
490
491 /*
492 * Enable interrupt handler for alarms
493 */
494 (void) bsd_signal(SIGALRM, (SIG_PF)doalarm);
495
496 /*
497 * Check if make should report
498 */
499 if (getenv(sunpro_dependencies->string_mb) != NULL) {
500 FILE *report_file;
501
502 report_dependency("");
503 report_file = get_report_file();
504 if ((report_file != NULL) && (report_file != (FILE*)-1)) {
505 (void) fprintf(report_file, "\n");
506 }
507 }
508
509 /*
510 * Make sure SUNPRO_DEPENDENCIES is exported (or not) properly.
511 */
512 if (keep_state) {
513 maybe_append_prop(sunpro_dependencies, macro_prop)->
514 body.macro.exported = true;
515 } else {
516 maybe_append_prop(sunpro_dependencies, macro_prop)->
517 body.macro.exported = false;
518 }
519
520 working_on_targets = true;
521 if (trace_status) {
522 dump_make_state();
523 fclose(stdout);
524 fclose(stderr);
525 exit_status = 0;
526 exit(0);
527 }
528 if (list_all_targets) {
529 dump_target_list();
530 fclose(stdout);
531 fclose(stderr);
532 exit_status = 0;
533 exit(0);
534 }
535 trace_reader = false;
536
537 /*
538 * Set temp_file_directory to the directory the .make.state
539 * file is written to.
540 */
541 if ((slash_ptr = strrchr(make_state->string_mb, (int) slash_char)) == NULL) {
542 temp_file_directory = strdup(get_current_path());
543 } else {
544 *slash_ptr = (int) nul_char;
545 (void) strcpy(make_state_dir, make_state->string_mb);
546 *slash_ptr = (int) slash_char;
547 /* when there is only one slash and it's the first
548 ** character, make_state_dir should point to '/'.
549 */
550 if(make_state_dir[0] == '\0') {
551 make_state_dir[0] = '/';
552 make_state_dir[1] = '\0';
553 }
554 if (make_state_dir[0] == (int) slash_char) {
555 temp_file_directory = strdup(make_state_dir);
556 } else {
557 char tmp_current_path2[MAXPATHLEN];
558
559 (void) sprintf(tmp_current_path2,
560 "%s/%s",
561 get_current_path(),
562 make_state_dir);
563 temp_file_directory = strdup(tmp_current_path2);
564 }
565 }
566
567
568 report_dir_enter_leave(true);
569
570 make_targets(argc, argv, parallel_flag);
571
572 report_dir_enter_leave(false);
573
574 if (build_failed_ever_seen) {
575 if (posix) {
576 exit_status = 1;
577 }
578 exit(1);
579 }
580 exit_status = 0;
581 exit(0);
582 /* NOTREACHED */
583 }
584
585 /*
586 * cleanup_after_exit()
587 *
588 * Called from exit(), performs cleanup actions.
589 *
590 * Parameters:
591 * status The argument exit() was called with
592 * arg Address of an argument vector to
593 * cleanup_after_exit()
594 *
595 * Global variables used:
596 * command_changed Set if we think .make.state should be rewritten
597 * current_line Is set we set commands_changed
598 * do_not_exec_rule
599 * True if -n flag on
600 * done The Name ".DONE", rule we run
601 * keep_state Set if .KEEP_STATE seen
602 * parallel True if building in parallel
603 * quest If -q is on we do not run .DONE
604 * report_dependencies
605 * True if -P flag on
606 * running_list List of parallel running processes
607 * temp_file_name The temp file is removed, if any
608 * catd the message catalog file
609 */
610 extern "C" void
611 cleanup_after_exit(void)
612 {
613 Running rp;
614
615 extern long getname_bytes_count;
616 extern long getname_names_count;
617 extern long getname_struct_count;
618 extern long freename_bytes_count;
619 extern long freename_names_count;
620 extern long freename_struct_count;
621 extern long other_alloc;
622
623 extern long env_alloc_num;
624 extern long env_alloc_bytes;
625
626
627 #ifdef DMAKE_STATISTICS
628 if(getname_stat) {
629 printf(NOCATGETS(">>> Getname statistics:\n"));
630 printf(NOCATGETS(" Allocated:\n"));
631 printf(NOCATGETS(" Names: %ld\n"), getname_names_count);
632 printf(NOCATGETS(" Strings: %ld Kb (%ld bytes)\n"), getname_bytes_count/1000, getname_bytes_count);
633 printf(NOCATGETS(" Structs: %ld Kb (%ld bytes)\n"), getname_struct_count/1000, getname_struct_count);
634 printf(NOCATGETS(" Total bytes: %ld Kb (%ld bytes)\n"), getname_struct_count/1000 + getname_bytes_count/1000, getname_struct_count + getname_bytes_count);
635
636 printf(NOCATGETS("\n Unallocated: %ld\n"), freename_names_count);
637 printf(NOCATGETS(" Names: %ld\n"), freename_names_count);
638 printf(NOCATGETS(" Strings: %ld Kb (%ld bytes)\n"), freename_bytes_count/1000, freename_bytes_count);
639 printf(NOCATGETS(" Structs: %ld Kb (%ld bytes)\n"), freename_struct_count/1000, freename_struct_count);
640 printf(NOCATGETS(" Total bytes: %ld Kb (%ld bytes)\n"), freename_struct_count/1000 + freename_bytes_count/1000, freename_struct_count + freename_bytes_count);
641
642 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));
643
644 printf(NOCATGETS("\n>>> Other:\n"));
645 printf(
646 NOCATGETS(" Env (%ld): %ld Kb (%ld bytes)\n"),
647 env_alloc_num,
648 env_alloc_bytes/1000,
649 env_alloc_bytes
650 );
651
652 }
653 #endif
654
655 parallel = false;
656 /* If we used the SVR4_MAKE, don't build .DONE or .FAILED */
657 if (!getenv(USE_SVR4_MAKE)){
658 /* Build the target .DONE or .FAILED if we caught an error */
659 if (!quest && !list_all_targets) {
660 Name failed_name;
661
662 MBSTOWCS(wcs_buffer, NOCATGETS(".FAILED"));
663 failed_name = GETNAME(wcs_buffer, FIND_LENGTH);
664 if ((exit_status != 0) && (failed_name->prop != NULL)) {
665 /*
666 * [tolik] switch DMake to serial mode
667 */
668 dmake_mode_type = serial_mode;
669 no_parallel = true;
670 (void) doname(failed_name, false, true);
671 } else {
672 if (!trace_status) {
673 /*
674 * Switch DMake to serial mode
675 */
676 dmake_mode_type = serial_mode;
677 no_parallel = true;
678 (void) doname(done, false, true);
679 }
680 }
681 }
682 }
683 /*
684 * Remove the temp file utilities report dependencies thru if it
685 * is still around
686 */
687 if (temp_file_name != NULL) {
688 (void) unlink(temp_file_name->string_mb);
689 }
690 /*
691 * Do not save the current command in .make.state if make
692 * was interrupted.
693 */
694 if (current_line != NULL) {
695 command_changed = true;
696 current_line->body.line.command_used = NULL;
697 }
698 /*
699 * For each parallel build process running, remove the temp files
700 * and zap the command line so it won't be put in .make.state
701 */
702 for (rp = running_list; rp != NULL; rp = rp->next) {
703 if (rp->temp_file != NULL) {
704 (void) unlink(rp->temp_file->string_mb);
705 }
706 if (rp->stdout_file != NULL) {
707 (void) unlink(rp->stdout_file);
708 retmem_mb(rp->stdout_file);
709 rp->stdout_file = NULL;
710 }
711 if (rp->stderr_file != NULL) {
712 (void) unlink(rp->stderr_file);
713 retmem_mb(rp->stderr_file);
714 rp->stderr_file = NULL;
715 }
716 command_changed = true;
717 /*
718 line = get_prop(rp->target->prop, line_prop);
719 if (line != NULL) {
720 line->body.line.command_used = NULL;
721 }
722 */
723 }
724 /* Remove the statefile lock file if the file has been locked */
725 if ((make_state_lockfile != NULL) && (make_state_locked)) {
726 (void) unlink(make_state_lockfile);
727 make_state_lockfile = NULL;
728 make_state_locked = false;
729 }
730 /* Write .make.state */
731 write_state_file(1, (Boolean) 1);
732
733 #if defined (TEAMWARE_MAKE_CMN) && defined (MAXJOBS_ADJUST_RFE4694000)
734 job_adjust_fini();
735 #endif
736
737 #ifdef TEAMWARE_MAKE_CMN
738 catclose(catd);
739 #endif
740 }
741
742 /*
743 * handle_interrupt()
744 *
745 * This is where C-C traps are caught.
746 *
747 * Parameters:
748 *
749 * Global variables used (except DMake 1.0):
750 * current_target Sometimes the current target is removed
751 * do_not_exec_rule But not if -n is on
752 * quest or -q
753 * running_list List of parallel running processes
754 * touch Current target is not removed if -t on
755 */
756 void
757 handle_interrupt(int)
758 {
759 Property member;
760 Running rp;
761
762 (void) fflush(stdout);
763 if (childPid > 0) {
764 kill(childPid, SIGTERM);
765 childPid = -1;
766 }
767 for (rp = running_list; rp != NULL; rp = rp->next) {
768 if (rp->state != build_running) {
769 continue;
770 }
771 if (rp->pid > 0) {
772 kill(rp->pid, SIGTERM);
773 rp->pid = -1;
774 }
775 }
776 if (getpid() == getpgrp()) {
777 bsd_signal(SIGTERM, SIG_IGN);
778 kill (-getpid(), SIGTERM);
779 }
780 /* Clean up all parallel children already finished */
781 finish_children(false);
782
783 /* Make sure the processes running under us terminate first */
784
785 while (wait((int *) NULL) != -1);
786 /* Delete the current targets unless they are precious */
787 if ((current_target != NULL) &&
788 current_target->is_member &&
789 ((member = get_prop(current_target->prop, member_prop)) != NULL)) {
790 current_target = member->body.member.library;
791 }
792 if (!do_not_exec_rule &&
793 !touch &&
794 !quest &&
795 (current_target != NULL) &&
796 !(current_target->stat.is_precious || all_precious)) {
797
798 /* BID_1030811 */
799 /* azv 16 Oct 95 */
800 current_target->stat.time = file_no_time;
801
802 if (exists(current_target) != file_doesnt_exist) {
803 (void) fprintf(stderr,
804 "\n*** %s ",
805 current_target->string_mb);
806 if (current_target->stat.is_dir) {
807 (void) fprintf(stderr,
808 catgets(catd, 1, 168, "not removed.\n"),
809 current_target->string_mb);
810 } else if (unlink(current_target->string_mb) == 0) {
811 (void) fprintf(stderr,
812 catgets(catd, 1, 169, "removed.\n"),
813 current_target->string_mb);
814 } else {
815 (void) fprintf(stderr,
816 catgets(catd, 1, 170, "could not be removed: %s.\n"),
817 current_target->string_mb,
818 errmsg(errno));
819 }
820 }
821 }
822 for (rp = running_list; rp != NULL; rp = rp->next) {
823 if (rp->state != build_running) {
824 continue;
825 }
826 if (rp->target->is_member &&
827 ((member = get_prop(rp->target->prop, member_prop)) !=
828 NULL)) {
829 rp->target = member->body.member.library;
830 }
831 if (!do_not_exec_rule &&
832 !touch &&
833 !quest &&
834 !(rp->target->stat.is_precious || all_precious)) {
835
836 rp->target->stat.time = file_no_time;
837 if (exists(rp->target) != file_doesnt_exist) {
838 (void) fprintf(stderr,
839 "\n*** %s ",
840 rp->target->string_mb);
841 if (rp->target->stat.is_dir) {
842 (void) fprintf(stderr,
843 catgets(catd, 1, 171, "not removed.\n"),
844 rp->target->string_mb);
845 } else if (unlink(rp->target->string_mb) == 0) {
846 (void) fprintf(stderr,
847 catgets(catd, 1, 172, "removed.\n"),
848 rp->target->string_mb);
849 } else {
850 (void) fprintf(stderr,
851 catgets(catd, 1, 173, "could not be removed: %s.\n"),
852 rp->target->string_mb,
853 errmsg(errno));
854 }
855 }
856 }
857 }
858
859
860 /* Have we locked .make.state or .nse_depinfo? */
861 if ((make_state_lockfile != NULL) && (make_state_locked)) {
862 unlink(make_state_lockfile);
863 make_state_lockfile = NULL;
864 make_state_locked = false;
865 }
866 /*
867 * Re-read .make.state file (it might be changed by recursive make)
868 */
869 check_state(NULL);
870
871 report_dir_enter_leave(false);
872
873 exit_status = 2;
874 exit(2);
875 }
876
877 /*
878 * doalarm(sig, ...)
879 *
880 * Handle the alarm interrupt but do nothing. Side effect is to
881 * cause return from wait3.
882 *
883 * Parameters:
884 * sig
885 *
886 * Global variables used:
887 */
888 /*ARGSUSED*/
889 static void
890 doalarm(int)
891 {
892 return;
893 }
894
895
896 /*
897 * read_command_options(argc, argv)
898 *
899 * Scan the cmd line options and process the ones that start with "-"
900 *
901 * Return value:
902 * -M argument, if any
903 *
904 * Parameters:
905 * argc You know what this is
906 * argv You know what this is
907 *
908 * Global variables used:
909 */
910 static void
911 read_command_options(register int argc, register char **argv)
912 {
913 register int ch;
914 int current_optind = 1;
915 int last_optind_with_double_hyphen = 0;
916 int last_optind;
917 int last_current_optind;
918 register int i;
919 register int j;
920 register int k;
921 register int makefile_next = 0; /*
922 * flag to note options:
923 * -c, f, g, j, m, o
924 */
925 const char *tptr;
926 const char *CMD_OPTS;
927
928 extern char *optarg;
929 extern int optind, opterr, optopt;
930
931 #define SUNPRO_CMD_OPTS "-~Bbc:Ddef:g:ij:K:kM:m:NnO:o:PpqRrSsTtuVvwx:"
932
933 # define SVR4_CMD_OPTS "-c:ef:g:ij:km:nO:o:pqrsTtVv"
934
935 /*
936 * Added V in SVR4_CMD_OPTS also, which is going to be a hidden
937 * option, just to make sure that the getopt doesn't fail when some
938 * users leave their USE_SVR4_MAKE set and try to use the makefiles
939 * that are designed to issue commands like $(MAKE) -V. Anyway it
940 * sets the same flag but ensures that getopt doesn't fail.
941 */
942
943 opterr = 0;
944 optind = 1;
945 while (1) {
946 last_optind=optind; /* Save optind and current_optind values */
947 last_current_optind=current_optind; /* in case we have to repeat this round. */
948 if (svr4) {
949 CMD_OPTS=SVR4_CMD_OPTS;
950 ch = getopt(argc, argv, SVR4_CMD_OPTS);
951 } else {
952 CMD_OPTS=SUNPRO_CMD_OPTS;
953 ch = getopt(argc, argv, SUNPRO_CMD_OPTS);
954 }
955 if (ch == EOF) {
956 if(optind < argc) {
957 /*
958 * Fixing bug 4102537:
959 * Strange behaviour of command make using -- option.
960 * Not all argv have been processed
961 * Skip non-flag argv and continue processing.
962 */
963 optind++;
964 current_optind++;
965 continue;
966 } else {
967 break;
968 }
969
970 }
971 if (ch == '?') {
972 if (optopt == '-') {
973 /* Bug 5060758: getopt() changed behavior (s10_60),
974 * and now we have to deal with cases when options
975 * with double hyphen appear here, from -$(MAKEFLAGS)
976 */
977 i = current_optind;
978 if (argv[i][0] == '-') {
979 if (argv[i][1] == '-') {
980 if (argv[i][2] != '\0') {
981 /* Check if this option is allowed */
982 tptr = strchr(CMD_OPTS, argv[i][2]);
983 if (tptr) {
984 if (last_optind_with_double_hyphen != current_optind) {
985 /* This is first time we are trying to fix "--"
986 * problem with this option. If we come here second
987 * time, we will go to fatal error.
988 */
989 last_optind_with_double_hyphen = current_optind;
990
991 /* Eliminate first hyphen character */
992 for (j=0; argv[i][j] != '\0'; j++) {
993 argv[i][j] = argv[i][j+1];
994 }
995
996 /* Repeat the processing of this argument */
997 optind=last_optind;
998 current_optind=last_current_optind;
999 continue;
1000 }
1001 }
1002 }
1003 }
1004 }
1005 }
1006 }
1007
1008 if (ch == '?') {
1009 if (svr4) {
1010 fprintf(stderr,
1011 catgets(catd, 1, 267, "Usage : dmake [ -f makefile ][ -c dmake_rcfile ][ -g dmake_group ]\n"));
1012 fprintf(stderr,
1013 catgets(catd, 1, 268, " [ -j dmake_max_jobs ][ -m dmake_mode ][ -o dmake_odir ]...\n"));
1014 fprintf(stderr,
1015 catgets(catd, 1, 269, " [ -e ][ -i ][ -k ][ -n ][ -p ][ -q ][ -r ][ -s ][ -t ][ -v ]\n"));
1016 tptr = strchr(SVR4_CMD_OPTS, optopt);
1017 } else {
1018 fprintf(stderr,
1019 catgets(catd, 1, 272, "Usage : dmake [ -f makefile ][ -c dmake_rcfile ][ -g dmake_group ]\n"));
1020 fprintf(stderr,
1021 catgets(catd, 1, 273, " [ -j dmake_max_jobs ][ -K statefile ][ -m dmake_mode ][ -x MODE_NAME=VALUE ][ -o dmake_odir ]...\n"));
1022 fprintf(stderr,
1023 catgets(catd, 1, 274, " [ -d ][ -dd ][ -D ][ -DD ][ -e ][ -i ][ -k ][ -n ][ -p ][ -P ][ -u ][ -w ]\n"));
1024 fprintf(stderr,
1025 catgets(catd, 1, 275, " [ -q ][ -r ][ -s ][ -S ][ -t ][ -v ][ -V ][ target... ][ macro=value... ][ \"macro +=value\"... ]\n"));
1026 tptr = strchr(SUNPRO_CMD_OPTS, optopt);
1027 }
1028 if (!tptr) {
1029 fatal(catgets(catd, 1, 279, "Unknown option `-%c'"), optopt);
1030 } else {
1031 fatal(catgets(catd, 1, 280, "Missing argument after `-%c'"), optopt);
1032 }
1033 }
1034
1035
1036
1037 makefile_next |= parse_command_option(ch);
1038 /*
1039 * If we're done processing all of the options of
1040 * ONE argument string...
1041 */
1042 if (current_optind < optind) {
1043 i = current_optind;
1044 k = 0;
1045 /* If there's an argument for an option... */
1046 if ((optind - current_optind) > 1) {
1047 k = i + 1;
1048 }
1049 switch (makefile_next) {
1050 case 0:
1051 argv[i] = NULL;
1052 /* This shouldn't happen */
1053 if (k) {
1054 argv[k] = NULL;
1055 }
1056 break;
1057 case 1: /* -f seen */
1058 argv[i] = (char *)NOCATGETS("-f");
1059 break;
1060 case 2: /* -c seen */
1061 argv[i] = (char *)NOCATGETS("-c");
1062 break;
1063 case 4: /* -g seen */
1064 argv[i] = (char *)NOCATGETS("-g");
1065 break;
1066 case 8: /* -j seen */
1067 argv[i] = (char *)NOCATGETS("-j");
1068 break;
1069 case 16: /* -M seen */
1070 argv[i] = (char *)NOCATGETS("-M");
1071 break;
1072 case 32: /* -m seen */
1073 argv[i] = (char *)NOCATGETS("-m");
1074 break;
1075 case 128: /* -O seen */
1076 argv[i] = (char *)NOCATGETS("-O");
1077 break;
1078 case 256: /* -K seen */
1079 argv[i] = (char *)NOCATGETS("-K");
1080 break;
1081 case 512: /* -o seen */
1082 argv[i] = (char *)NOCATGETS("-o");
1083 break;
1084 case 1024: /* -x seen */
1085 argv[i] = (char *)NOCATGETS("-x");
1086 break;
1087 default: /* > 1 of -c, f, g, j, K, M, m, O, o, x seen */
1088 fatal(catgets(catd, 1, 286, "Illegal command line. More than one option requiring\nan argument given in the same argument group"));
1089 }
1090
1091 makefile_next = 0;
1092 current_optind = optind;
1093 }
1094 }
1095 }
1096
1097 static void
1098 quote_str(char *str, char *qstr)
1099 {
1100 char *to;
1101 char *from;
1102
1103 to = qstr;
1104 for (from = str; *from; from++) {
1105 switch (*from) {
1106 case ';': /* End of command */
1107 case '(': /* Start group */
1108 case ')': /* End group */
1109 case '{': /* Start group */
1110 case '}': /* End group */
1111 case '[': /* Reg expr - any of a set of chars */
1112 case ']': /* End of set of chars */
1113 case '|': /* Pipe or logical-or */
1114 case '^': /* Old-fashioned pipe */
1115 case '&': /* Background or logical-and */
1116 case '<': /* Redirect stdin */
1117 case '>': /* Redirect stdout */
1118 case '*': /* Reg expr - any sequence of chars */
1119 case '?': /* Reg expr - any single char */
1120 case '$': /* Variable substitution */
1121 case '\'': /* Singe quote - turn off all magic */
1122 case '"': /* Double quote - span whitespace */
1123 case '`': /* Backquote - run a command */
1124 case '#': /* Comment */
1125 case ' ': /* Space (for MACRO=value1 value2 */
1126 case '\\': /* Escape char - turn off magic of next char */
1127 *to++ = '\\';
1128 break;
1129
1130 default:
1131 break;
1132 }
1133 *to++ = *from;
1134 }
1135 *to = '\0';
1136 }
1137
1138 static void
1139 unquote_str(char *str, char *qstr)
1140 {
1141 char *to;
1142 char *from;
1143
1144 to = qstr;
1145 for (from = str; *from; from++) {
1146 if (*from == '\\') {
1147 from++;
1148 }
1149 *to++ = *from;
1150 }
1151 *to = '\0';
1152 }
1153
1154 /*
1155 * Convert the MAKEFLAGS string value into a vector of char *, similar
1156 * to argv.
1157 */
1158 static void
1159 setup_makeflags_argv()
1160 {
1161 char *cp;
1162 char *cp1;
1163 char *cp2;
1164 char *cp3;
1165 char *cp_orig;
1166 Boolean add_hyphen;
1167 int i;
1168 char tmp_char;
1169
1170 mf_argc = 1;
1171 cp = getenv(makeflags->string_mb);
1172 cp_orig = cp;
1173
1174 if (cp) {
1175 /*
1176 * If new MAKEFLAGS format, no need to add hyphen.
1177 * If old MAKEFLAGS format, add hyphen before flags.
1178 */
1179
1180 if ((strchr(cp, (int) hyphen_char) != NULL) ||
1181 (strchr(cp, (int) equal_char) != NULL)) {
1182
1183 /* New MAKEFLAGS format */
1184
1185 add_hyphen = false;
1186 #ifdef ADDFIX5060758
1187 /* Check if MAKEFLAGS value begins with multiple
1188 * hyphen characters, and remove all duplicates.
1189 * Usually it happens when the next command is
1190 * used: $(MAKE) -$(MAKEFLAGS)
1191 * This is a workaround for BugID 5060758.
1192 */
1193 while (*cp) {
1194 if (*cp != (int) hyphen_char) {
1195 break;
1196 }
1197 cp++;
1198 if (*cp == (int) hyphen_char) {
1199 /* There are two hyphens. Skip one */
1200 cp_orig = cp;
1201 cp++;
1202 }
1203 if (!(*cp)) {
1204 /* There are hyphens only. Skip all */
1205 cp_orig = cp;
1206 break;
1207 }
1208 }
1209 #endif
1210 } else {
1211
1212 /* Old MAKEFLAGS format */
1213
1214 add_hyphen = true;
1215 }
1216 }
1217
1218 /* Find the number of arguments in MAKEFLAGS */
1219 while (cp && *cp) {
1220 /* Skip white spaces */
1221 while (cp && *cp && isspace(*cp)) {
1222 cp++;
1223 }
1224 if (cp && *cp) {
1225 /* Increment arg count */
1226 mf_argc++;
1227 /* Go to next white space */
1228 while (cp && *cp && !isspace(*cp)) {
1229 if(*cp == (int) backslash_char) {
1230 cp++;
1231 }
1232 cp++;
1233 }
1234 }
1235 }
1236 /* Allocate memory for the new MAKEFLAGS argv */
1237 mf_argv = (char **) malloc((mf_argc + 1) * sizeof(char *));
1238 mf_argv[0] = (char *)NOCATGETS("MAKEFLAGS");
1239 /*
1240 * Convert the MAKEFLAGS string value into a vector of char *,
1241 * similar to argv.
1242 */
1243 cp = cp_orig;
1244 for (i = 1; i < mf_argc; i++) {
1245 /* Skip white spaces */
1246 while (cp && *cp && isspace(*cp)) {
1247 cp++;
1248 }
1249 if (cp && *cp) {
1250 cp_orig = cp;
1251 /* Go to next white space */
1252 while (cp && *cp && !isspace(*cp)) {
1253 if(*cp == (int) backslash_char) {
1254 cp++;
1255 }
1256 cp++;
1257 }
1258 tmp_char = *cp;
1259 *cp = (int) nul_char;
1260 if (add_hyphen) {
1261 mf_argv[i] = getmem(2 + strlen(cp_orig));
1262 mf_argv[i][0] = '\0';
1263 (void) strcat(mf_argv[i], "-");
1264 // (void) strcat(mf_argv[i], cp_orig);
1265 unquote_str(cp_orig, mf_argv[i]+1);
1266 } else {
1267 mf_argv[i] = getmem(2 + strlen(cp_orig));
1268 //mf_argv[i] = strdup(cp_orig);
1269 unquote_str(cp_orig, mf_argv[i]);
1270 }
1271 *cp = tmp_char;
1272 }
1273 }
1274 mf_argv[i] = NULL;
1275 }
1276
1277 /*
1278 * parse_command_option(ch)
1279 *
1280 * Parse make command line options.
1281 *
1282 * Return value:
1283 * Indicates if any -f -c or -M were seen
1284 *
1285 * Parameters:
1286 * ch The character to parse
1287 *
1288 * Static variables used:
1289 * dmake_group_specified Set for make -g
1290 * dmake_max_jobs_specified Set for make -j
1291 * dmake_mode_specified Set for make -m
1292 * dmake_add_mode_specified Set for make -x
1293 * dmake_compat_mode_specified Set for make -x SUN_MAKE_COMPAT_MODE=
1294 * dmake_output_mode_specified Set for make -x DMAKE_OUTPUT_MODE=
1295 * dmake_odir_specified Set for make -o
1296 * dmake_rcfile_specified Set for make -c
1297 * env_wins Set for make -e
1298 * ignore_default_mk Set for make -r
1299 * trace_status Set for make -p
1300 *
1301 * Global variables used:
1302 * .make.state path & name set for make -K
1303 * continue_after_error Set for make -k
1304 * debug_level Set for make -d
1305 * do_not_exec_rule Set for make -n
1306 * filter_stderr Set for make -X
1307 * ignore_errors_all Set for make -i
1308 * no_parallel Set for make -R
1309 * quest Set for make -q
1310 * read_trace_level Set for make -D
1311 * report_dependencies Set for make -P
1312 * send_mtool_msgs Set for make -K
1313 * silent_all Set for make -s
1314 * touch Set for make -t
1315 */
1316 static int
1317 parse_command_option(register char ch)
1318 {
1319 static int invert_next = 0;
1320 int invert_this = invert_next;
1321
1322 invert_next = 0;
1323 switch (ch) {
1324 case '-': /* Ignore "--" */
1325 return 0;
1326 case '~': /* Invert next option */
1327 invert_next = 1;
1328 return 0;
1329 case 'B': /* Obsolete */
1330 return 0;
1331 case 'b': /* Obsolete */
1332 return 0;
1333 case 'c': /* Read alternative dmakerc file */
1334 if (invert_this) {
1335 dmake_rcfile_specified = false;
1336 } else {
1337 dmake_rcfile_specified = true;
1338 }
1339 return 2;
1340 case 'D': /* Show lines read */
1341 if (invert_this) {
1342 read_trace_level--;
1343 } else {
1344 read_trace_level++;
1345 }
1346 return 0;
1347 case 'd': /* Debug flag */
1348 if (invert_this) {
1349 debug_level--;
1350 } else {
1351 debug_level++;
1352 }
1353 return 0;
1354 case 'e': /* Environment override flag */
1355 if (invert_this) {
1356 env_wins = false;
1357 } else {
1358 env_wins = true;
1359 }
1360 return 0;
1361 case 'f': /* Read alternative makefile(s) */
1362 return 1;
1363 case 'g': /* Use alternative DMake group */
1364 if (invert_this) {
1365 dmake_group_specified = false;
1366 } else {
1367 dmake_group_specified = true;
1368 }
1369 return 4;
1370 case 'i': /* Ignore errors */
1371 if (invert_this) {
1372 ignore_errors_all = false;
1373 } else {
1374 ignore_errors_all = true;
1375 }
1376 return 0;
1377 case 'j': /* Use alternative DMake max jobs */
1378 if (invert_this) {
1379 dmake_max_jobs_specified = false;
1380 } else {
1381 dmake_mode_type = parallel_mode;
1382 no_parallel = false;
1383 dmake_max_jobs_specified = true;
1384 }
1385 return 8;
1386 case 'K': /* Read alternative .make.state */
1387 return 256;
1388 case 'k': /* Keep making even after errors */
1389 if (invert_this) {
1390 continue_after_error = false;
1391 } else {
1392 continue_after_error = true;
1393 continue_after_error_ever_seen = true;
1394 }
1395 return 0;
1396 case 'M': /* Read alternative make.machines file */
1397 if (invert_this) {
1398 pmake_machinesfile_specified = false;
1399 } else {
1400 pmake_machinesfile_specified = true;
1401 dmake_mode_type = parallel_mode;
1402 no_parallel = false;
1403 }
1404 return 16;
1405 case 'm': /* Use alternative DMake build mode */
1406 if (invert_this) {
1407 dmake_mode_specified = false;
1408 } else {
1409 dmake_mode_specified = true;
1410 }
1411 return 32;
1412 case 'x': /* Use alternative DMake mode */
1413 if (invert_this) {
1414 dmake_add_mode_specified = false;
1415 } else {
1416 dmake_add_mode_specified = true;
1417 }
1418 return 1024;
1419 case 'N': /* Reverse -n */
1420 if (invert_this) {
1421 do_not_exec_rule = true;
1422 } else {
1423 do_not_exec_rule = false;
1424 }
1425 return 0;
1426 case 'n': /* Print, not exec commands */
1427 if (invert_this) {
1428 do_not_exec_rule = false;
1429 } else {
1430 do_not_exec_rule = true;
1431 }
1432 return 0;
1433 case 'O': /* Send job start & result msgs */
1434 if (invert_this) {
1435 send_mtool_msgs = false;
1436 } else {
1437 }
1438 return 128;
1439 case 'o': /* Use alternative dmake output dir */
1440 if (invert_this) {
1441 dmake_odir_specified = false;
1442 } else {
1443 dmake_odir_specified = true;
1444 }
1445 return 512;
1446 case 'P': /* Print for selected targets */
1447 if (invert_this) {
1448 report_dependencies_level--;
1449 } else {
1450 report_dependencies_level++;
1451 }
1452 return 0;
1453 case 'p': /* Print description */
1454 if (invert_this) {
1455 trace_status = false;
1456 do_not_exec_rule = false;
1457 } else {
1458 trace_status = true;
1459 do_not_exec_rule = true;
1460 }
1461 return 0;
1462 case 'q': /* Question flag */
1463 if (invert_this) {
1464 quest = false;
1465 } else {
1466 quest = true;
1467 }
1468 return 0;
1469 case 'R': /* Don't run in parallel */
1470 if (invert_this) {
1471 pmake_cap_r_specified = false;
1472 no_parallel = false;
1473 } else {
1474 pmake_cap_r_specified = true;
1475 dmake_mode_type = serial_mode;
1476 no_parallel = true;
1477 }
1478 return 0;
1479 case 'r': /* Turn off internal rules */
1480 if (invert_this) {
1481 ignore_default_mk = false;
1482 } else {
1483 ignore_default_mk = true;
1484 }
1485 return 0;
1486 case 'S': /* Reverse -k */
1487 if (invert_this) {
1488 continue_after_error = true;
1489 } else {
1490 continue_after_error = false;
1491 stop_after_error_ever_seen = true;
1492 }
1493 return 0;
1494 case 's': /* Silent flag */
1495 if (invert_this) {
1496 silent_all = false;
1497 } else {
1498 silent_all = true;
1499 }
1500 return 0;
1501 case 'T': /* Print target list */
1502 if (invert_this) {
1503 list_all_targets = false;
1504 do_not_exec_rule = false;
1505 } else {
1506 list_all_targets = true;
1507 do_not_exec_rule = true;
1508 }
1509 return 0;
1510 case 't': /* Touch flag */
1511 if (invert_this) {
1512 touch = false;
1513 } else {
1514 touch = true;
1515 }
1516 return 0;
1517 case 'u': /* Unconditional flag */
1518 if (invert_this) {
1519 build_unconditional = false;
1520 } else {
1521 build_unconditional = true;
1522 }
1523 return 0;
1524 case 'V': /* SVR4 mode */
1525 svr4 = true;
1526 return 0;
1527 case 'v': /* Version flag */
1528 if (invert_this) {
1529 } else {
1530 fprintf(stdout, NOCATGETS("dmake: %s\n"), verstring);
1531 exit_status = 0;
1532 exit(0);
1533 }
1534 return 0;
1535 case 'w': /* Unconditional flag */
1536 if (invert_this) {
1537 report_cwd = false;
1538 } else {
1539 report_cwd = true;
1540 }
1541 return 0;
1542 #if 0
1543 case 'X': /* Filter stdout */
1544 if (invert_this) {
1545 filter_stderr = false;
1546 } else {
1547 filter_stderr = true;
1548 }
1549 return 0;
1550 #endif
1551 default:
1552 break;
1553 }
1554 return 0;
1555 }
1556
1557 /*
1558 * setup_for_projectdir()
1559 *
1560 * Read the PROJECTDIR variable, if defined, and set the sccs path
1561 *
1562 * Parameters:
1563 *
1564 * Global variables used:
1565 * sccs_dir_path Set to point to SCCS dir to use
1566 */
1567 static void
1568 setup_for_projectdir(void)
1569 {
1570 static char path[MAXPATHLEN];
1571 char cwdpath[MAXPATHLEN];
1572 uid_t uid;
1573 int done=0;
1574
1575 /* Check if we should use PROJECTDIR when reading the SCCS dir. */
1576 sccs_dir_path = getenv(NOCATGETS("PROJECTDIR"));
1577 if ((sccs_dir_path != NULL) &&
1578 (sccs_dir_path[0] != (int) slash_char)) {
1579 struct passwd *pwent;
1580
1581 {
1582 uid = getuid();
1583 pwent = getpwuid(uid);
1584 if (pwent == NULL) {
1585 fatal(catgets(catd, 1, 188, "Bogus USERID "));
1586 }
1587 if ((pwent = getpwnam(sccs_dir_path)) == NULL) {
1588 /*empty block : it'll go & check cwd */
1589 }
1590 else {
1591 (void) sprintf(path, NOCATGETS("%s/src"), pwent->pw_dir);
1592 if (access(path, F_OK) == 0) {
1593 sccs_dir_path = path;
1594 done = 1;
1595 } else {
1596 (void) sprintf(path, NOCATGETS("%s/source"), pwent->pw_dir);
1597 if (access(path, F_OK) == 0) {
1598 sccs_dir_path = path;
1599 done = 1;
1600 }
1601 }
1602 }
1603 if (!done) {
1604 if (getcwd(cwdpath, MAXPATHLEN - 1 )) {
1605
1606 (void) sprintf(path, NOCATGETS("%s/%s"), cwdpath,sccs_dir_path);
1607 if (access(path, F_OK) == 0) {
1608 sccs_dir_path = path;
1609 done = 1;
1610 } else {
1611 fatal(catgets(catd, 1, 189, "Bogus PROJECTDIR '%s'"), sccs_dir_path);
1612 }
1613 }
1614 }
1615 }
1616 }
1617 }
1618
1619 /*
1620 * set_sgs_support()
1621 *
1622 * Add the libmakestate.so.1 lib to the env var SGS_SUPPORT
1623 * if it's not already in there.
1624 * The SGS_SUPPORT env var and libmakestate.so.1 is used by
1625 * the linker ld to report .make.state info back to make.
1626 *
1627 * In the new world we always will set the 32-bit and 64-bit versions of this
1628 * variable explicitly so that we can take into account the correct isa and our
1629 * prefix. So say that the prefix was /opt/local. Then we would want to search
1630 * /opt/local/lib/libmakestate.so.1:libmakestate.so.1. We still want to search
1631 * the original location just as a safety measure.
1632 */
1633 static void
1634 set_sgs_support()
1635 {
1636 int len;
1637 char *newpath, *newpath64;
1638 char *oldpath, *oldpath64;
1639 static char *prev_path, *prev_path64;
1640
1641 oldpath = getenv(LD_SUPPORT_ENV_VAR_32);
1642 if (oldpath == NULL) {
1643 len = snprintf(NULL, 0, "%s=%s/%s/%s:%s",
1644 LD_SUPPORT_ENV_VAR_32,
1645 MAKE_PREFIX,
1646 LD_SUPPORT_MAKE_LIB_DIR,
1647 LD_SUPPORT_MAKE_LIB, LD_SUPPORT_MAKE_LIB) + 1;
1648 newpath = (char *) malloc(len);
1649 sprintf(newpath, "%s=%s/%s/%s:%s",
1650 LD_SUPPORT_ENV_VAR_32,
1651 MAKE_PREFIX,
1652 LD_SUPPORT_MAKE_LIB_DIR,
1653 LD_SUPPORT_MAKE_LIB, LD_SUPPORT_MAKE_LIB);
1654 } else {
1655 len = snprintf(NULL, 0, "%s=%s:%s/%s/%s:%s",
1656 LD_SUPPORT_ENV_VAR_32, oldpath, MAKE_PREFIX,
1657 LD_SUPPORT_MAKE_LIB_DIR, LD_SUPPORT_MAKE_LIB,
1658 LD_SUPPORT_MAKE_LIB) + 1;
1659 newpath = (char *) malloc(len);
1660 sprintf(newpath, "%s=%s:%s/%s/%s:%s",
1661 LD_SUPPORT_ENV_VAR_32, oldpath, MAKE_PREFIX,
1662 LD_SUPPORT_MAKE_LIB_DIR, LD_SUPPORT_MAKE_LIB,
1663 LD_SUPPORT_MAKE_LIB);
1664 }
1665
1666 oldpath64 = getenv(LD_SUPPORT_ENV_VAR_64);
1667 if (oldpath64 == NULL) {
1668 len = snprintf(NULL, 0, "%s=%s/%s/%s/%s:%s",
1669 LD_SUPPORT_ENV_VAR_64, MAKE_PREFIX, LD_SUPPORT_MAKE_LIB_DIR,
1670 LD_SUPPORT_MAKE_LIB_DIR_64, LD_SUPPORT_MAKE_LIB,
1671 LD_SUPPORT_MAKE_LIB) + 1;
1672 newpath64 = (char *) malloc(len);
1673 sprintf(newpath64, "%s=%s/%s/%s/%s:%s",
1674 LD_SUPPORT_ENV_VAR_64, MAKE_PREFIX, LD_SUPPORT_MAKE_LIB_DIR,
1675 LD_SUPPORT_MAKE_LIB_DIR_64, LD_SUPPORT_MAKE_LIB,
1676 LD_SUPPORT_MAKE_LIB);
1677 } else {
1678 len = snprintf(NULL, 0, "%s=%s:%s/%s/%s/%s:%s",
1679 LD_SUPPORT_ENV_VAR_64, oldpath64, MAKE_PREFIX,
1680 LD_SUPPORT_MAKE_LIB_DIR, LD_SUPPORT_MAKE_LIB_DIR_64,
1681 LD_SUPPORT_MAKE_LIB, LD_SUPPORT_MAKE_LIB) + 1;
1682 newpath64 = (char *) malloc(len);
1683 sprintf(newpath64, "%s=%s:%s/%s/%s/%s:%s",
1684 LD_SUPPORT_ENV_VAR_64, oldpath64, MAKE_PREFIX,
1685 LD_SUPPORT_MAKE_LIB_DIR, LD_SUPPORT_MAKE_LIB_DIR_64,
1686 LD_SUPPORT_MAKE_LIB, LD_SUPPORT_MAKE_LIB);
1687 }
1688
1689 putenv(newpath);
1690 if (prev_path) {
1691 free(prev_path);
1692 }
1693 prev_path = newpath;
1694
1695 putenv(newpath64);
1696 if (prev_path64) {
1697 free(prev_path64);
1698 }
1699 prev_path64 = newpath64;
1700 }
1701
1702 /*
1703 * read_files_and_state(argc, argv)
1704 *
1705 * Read the makefiles we care about and the environment
1706 * Also read the = style command line options
1707 *
1708 * Parameters:
1709 * argc You know what this is
1710 * argv You know what this is
1711 *
1712 * Static variables used:
1713 * env_wins make -e, determines if env vars are RO
1714 * ignore_default_mk make -r, determines if make.rules is read
1715 * not_auto_depen dwight
1716 *
1717 * Global variables used:
1718 * default_target_to_build Set to first proper target from file
1719 * do_not_exec_rule Set to false when makfile is made
1720 * dot The Name ".", used to read current dir
1721 * empty_name The Name "", use as macro value
1722 * keep_state Set if KEEP_STATE is in environment
1723 * make_state The Name ".make.state", used to read file
1724 * makefile_type Set to type of file being read
1725 * makeflags The Name "MAKEFLAGS", used to set macro value
1726 * not_auto dwight
1727 * read_trace_level Checked to se if the reader should trace
1728 * report_dependencies If -P is on we do not read .make.state
1729 * trace_reader Set if reader should trace
1730 * virtual_root The Name "VIRTUAL_ROOT", used to check value
1731 */
1732 static void
1733 read_files_and_state(int argc, char **argv)
1734 {
1735 wchar_t buffer[1000];
1736 wchar_t buffer_posix[1000];
1737 register char ch;
1738 register char *cp;
1739 Property def_make_macro = NULL;
1740 Name def_make_name;
1741 Name default_makefile;
1742 String_rec dest;
1743 wchar_t destbuffer[STRING_BUFFER_LENGTH];
1744 register int i;
1745 register int j;
1746 Name keep_state_name;
1747 int length;
1748 Name Makefile;
1749 register Property macro;
1750 struct stat make_state_stat;
1751 Name makefile_name;
1752 register int makefile_next = 0;
1753 register Boolean makefile_read = false;
1754 String_rec makeflags_string;
1755 String_rec makeflags_string_posix;
1756 String_rec * makeflags_string_current;
1757 Name makeflags_value_saved;
1758 register Name name;
1759 Name new_make_value;
1760 Boolean save_do_not_exec_rule;
1761 Name sdotMakefile;
1762 Name sdotmakefile_name;
1763 static wchar_t state_file_str;
1764 static char state_file_str_mb[MAXPATHLEN];
1765 static struct _Name state_filename;
1766 Boolean temp;
1767 char tmp_char;
1768 wchar_t *tmp_wcs_buffer;
1769 register Name value;
1770 ASCII_Dyn_Array makeflags_and_macro;
1771 Boolean is_xpg4;
1772
1773 /*
1774 * Remember current mode. It may be changed after reading makefile
1775 * and we will have to correct MAKEFLAGS variable.
1776 */
1777 is_xpg4 = posix;
1778
1779 MBSTOWCS(wcs_buffer, NOCATGETS("KEEP_STATE"));
1780 keep_state_name = GETNAME(wcs_buffer, FIND_LENGTH);
1781 MBSTOWCS(wcs_buffer, NOCATGETS("Makefile"));
1782 Makefile = GETNAME(wcs_buffer, FIND_LENGTH);
1783 MBSTOWCS(wcs_buffer, NOCATGETS("makefile"));
1784 makefile_name = GETNAME(wcs_buffer, FIND_LENGTH);
1785 MBSTOWCS(wcs_buffer, NOCATGETS("s.makefile"));
1786 sdotmakefile_name = GETNAME(wcs_buffer, FIND_LENGTH);
1787 MBSTOWCS(wcs_buffer, NOCATGETS("s.Makefile"));
1788 sdotMakefile = GETNAME(wcs_buffer, FIND_LENGTH);
1789
1790 /*
1791 * initialize global dependency entry for .NOT_AUTO
1792 */
1793 not_auto_depen->next = NULL;
1794 not_auto_depen->name = not_auto;
1795 not_auto_depen->automatic = not_auto_depen->stale = false;
1796
1797 /*
1798 * Read internal definitions and rules.
1799 */
1800 if (read_trace_level > 1) {
1801 trace_reader = true;
1802 }
1803 if (!ignore_default_mk) {
1804 if (svr4) {
1805 MBSTOWCS(wcs_buffer, NOCATGETS("svr4.make.rules"));
1806 default_makefile = GETNAME(wcs_buffer, FIND_LENGTH);
1807 } else {
1808 MBSTOWCS(wcs_buffer, NOCATGETS("make.rules"));
1809 default_makefile = GETNAME(wcs_buffer, FIND_LENGTH);
1810 }
1811 default_makefile->stat.is_file = true;
1812
1813 (void) read_makefile(default_makefile,
1814 true,
1815 false,
1816 true);
1817 }
1818
1819 /*
1820 * If the user did not redefine the MAKE macro in the
1821 * default makefile (make.rules), then we'd like to
1822 * change the macro value of MAKE to be some form
1823 * of argv[0] for recursive MAKE builds.
1824 */
1825 MBSTOWCS(wcs_buffer, NOCATGETS("MAKE"));
1826 def_make_name = GETNAME(wcs_buffer, wslen(wcs_buffer));
1827 def_make_macro = get_prop(def_make_name->prop, macro_prop);
1828 if ((def_make_macro != NULL) &&
1829 (IS_EQUAL(def_make_macro->body.macro.value->string_mb,
1830 NOCATGETS("make")))) {
1831 MBSTOWCS(wcs_buffer, argv_zero_string);
1832 new_make_value = GETNAME(wcs_buffer, wslen(wcs_buffer));
1833 (void) SETVAR(def_make_name,
1834 new_make_value,
1835 false);
1836 }
1837
1838 default_target_to_build = NULL;
1839 trace_reader = false;
1840
1841 /*
1842 * Read environment args. Let file args which follow override unless
1843 * -e option seen. If -e option is not mentioned.
1844 */
1845 read_environment(env_wins);
1846 if (getvar(virtual_root)->hash.length == 0) {
1847 maybe_append_prop(virtual_root, macro_prop)
1848 ->body.macro.exported = true;
1849 MBSTOWCS(wcs_buffer, "/");
1850 (void) SETVAR(virtual_root,
1851 GETNAME(wcs_buffer, FIND_LENGTH),
1852 false);
1853 }
1854
1855 /*
1856 * We now scan mf_argv and argv to see if we need to set
1857 * any of the DMake-added options/variables in MAKEFLAGS.
1858 */
1859
1860 makeflags_and_macro.start = 0;
1861 makeflags_and_macro.size = 0;
1862 enter_argv_values(mf_argc, mf_argv, &makeflags_and_macro);
1863 enter_argv_values(argc, argv, &makeflags_and_macro);
1864
1865 /*
1866 * Set MFLAGS and MAKEFLAGS
1867 *
1868 * Before reading makefile we do not know exactly which mode
1869 * (posix or not) is used. So prepare two MAKEFLAGS strings
1870 * for both posix and solaris modes because they are different.
1871 */
1872 INIT_STRING_FROM_STACK(makeflags_string, buffer);
1873 INIT_STRING_FROM_STACK(makeflags_string_posix, buffer_posix);
1874 append_char((int) hyphen_char, &makeflags_string);
1875 append_char((int) hyphen_char, &makeflags_string_posix);
1876
1877 switch (read_trace_level) {
1878 case 2:
1879 append_char('D', &makeflags_string);
1880 append_char('D', &makeflags_string_posix);
1881 case 1:
1882 append_char('D', &makeflags_string);
1883 append_char('D', &makeflags_string_posix);
1884 }
1885 switch (debug_level) {
1886 case 2:
1887 append_char('d', &makeflags_string);
1888 append_char('d', &makeflags_string_posix);
1889 case 1:
1890 append_char('d', &makeflags_string);
1891 append_char('d', &makeflags_string_posix);
1892 }
1893 if (env_wins) {
1894 append_char('e', &makeflags_string);
1895 append_char('e', &makeflags_string_posix);
1896 }
1897 if (ignore_errors_all) {
1898 append_char('i', &makeflags_string);
1899 append_char('i', &makeflags_string_posix);
1900 }
1901 if (continue_after_error) {
1902 if (stop_after_error_ever_seen) {
1903 append_char('S', &makeflags_string_posix);
1904 append_char((int) space_char, &makeflags_string_posix);
1905 append_char((int) hyphen_char, &makeflags_string_posix);
1906 }
1907 append_char('k', &makeflags_string);
1908 append_char('k', &makeflags_string_posix);
1909 } else {
1910 if (stop_after_error_ever_seen
1911 && continue_after_error_ever_seen) {
1912 append_char('k', &makeflags_string_posix);
1913 append_char((int) space_char, &makeflags_string_posix);
1914 append_char((int) hyphen_char, &makeflags_string_posix);
1915 append_char('S', &makeflags_string_posix);
1916 }
1917 }
1918 if (do_not_exec_rule) {
1919 append_char('n', &makeflags_string);
1920 append_char('n', &makeflags_string_posix);
1921 }
1922 switch (report_dependencies_level) {
1923 case 4:
1924 append_char('P', &makeflags_string);
1925 append_char('P', &makeflags_string_posix);
1926 case 3:
1927 append_char('P', &makeflags_string);
1928 append_char('P', &makeflags_string_posix);
1929 case 2:
1930 append_char('P', &makeflags_string);
1931 append_char('P', &makeflags_string_posix);
1932 case 1:
1933 append_char('P', &makeflags_string);
1934 append_char('P', &makeflags_string_posix);
1935 }
1936 if (trace_status) {
1937 append_char('p', &makeflags_string);
1938 append_char('p', &makeflags_string_posix);
1939 }
1940 if (quest) {
1941 append_char('q', &makeflags_string);
1942 append_char('q', &makeflags_string_posix);
1943 }
1944 if (silent_all) {
1945 append_char('s', &makeflags_string);
1946 append_char('s', &makeflags_string_posix);
1947 }
1948 if (touch) {
1949 append_char('t', &makeflags_string);
1950 append_char('t', &makeflags_string_posix);
1951 }
1952 if (build_unconditional) {
1953 append_char('u', &makeflags_string);
1954 append_char('u', &makeflags_string_posix);
1955 }
1956 if (report_cwd) {
1957 append_char('w', &makeflags_string);
1958 append_char('w', &makeflags_string_posix);
1959 }
1960 /* -c dmake_rcfile */
1961 if (dmake_rcfile_specified) {
1962 MBSTOWCS(wcs_buffer, NOCATGETS("DMAKE_RCFILE"));
1963 dmake_rcfile = GETNAME(wcs_buffer, FIND_LENGTH);
1964 append_makeflags_string(dmake_rcfile, &makeflags_string);
1965 append_makeflags_string(dmake_rcfile, &makeflags_string_posix);
1966 }
1967 /* -g dmake_group */
1968 if (dmake_group_specified) {
1969 MBSTOWCS(wcs_buffer, NOCATGETS("DMAKE_GROUP"));
1970 dmake_group = GETNAME(wcs_buffer, FIND_LENGTH);
1971 append_makeflags_string(dmake_group, &makeflags_string);
1972 append_makeflags_string(dmake_group, &makeflags_string_posix);
1973 }
1974 /* -j dmake_max_jobs */
1975 if (dmake_max_jobs_specified) {
1976 MBSTOWCS(wcs_buffer, NOCATGETS("DMAKE_MAX_JOBS"));
1977 dmake_max_jobs = GETNAME(wcs_buffer, FIND_LENGTH);
1978 append_makeflags_string(dmake_max_jobs, &makeflags_string);
1979 append_makeflags_string(dmake_max_jobs, &makeflags_string_posix);
1980 }
1981 /* -m dmake_mode */
1982 if (dmake_mode_specified) {
1983 MBSTOWCS(wcs_buffer, NOCATGETS("DMAKE_MODE"));
1984 dmake_mode = GETNAME(wcs_buffer, FIND_LENGTH);
1985 append_makeflags_string(dmake_mode, &makeflags_string);
1986 append_makeflags_string(dmake_mode, &makeflags_string_posix);
1987 }
1988 /* -x dmake_compat_mode */
1989 // if (dmake_compat_mode_specified) {
1990 // MBSTOWCS(wcs_buffer, NOCATGETS("SUN_MAKE_COMPAT_MODE"));
1991 // dmake_compat_mode = GETNAME(wcs_buffer, FIND_LENGTH);
1992 // append_makeflags_string(dmake_compat_mode, &makeflags_string);
1993 // append_makeflags_string(dmake_compat_mode, &makeflags_string_posix);
1994 // }
1995 /* -x dmake_output_mode */
1996 if (dmake_output_mode_specified) {
1997 MBSTOWCS(wcs_buffer, NOCATGETS("DMAKE_OUTPUT_MODE"));
1998 dmake_output_mode = GETNAME(wcs_buffer, FIND_LENGTH);
1999 append_makeflags_string(dmake_output_mode, &makeflags_string);
2000 append_makeflags_string(dmake_output_mode, &makeflags_string_posix);
2001 }
2002 /* -o dmake_odir */
2003 if (dmake_odir_specified) {
2004 MBSTOWCS(wcs_buffer, NOCATGETS("DMAKE_ODIR"));
2005 dmake_odir = GETNAME(wcs_buffer, FIND_LENGTH);
2006 append_makeflags_string(dmake_odir, &makeflags_string);
2007 append_makeflags_string(dmake_odir, &makeflags_string_posix);
2008 }
2009 /* -M pmake_machinesfile */
2010 if (pmake_machinesfile_specified) {
2011 MBSTOWCS(wcs_buffer, NOCATGETS("PMAKE_MACHINESFILE"));
2012 pmake_machinesfile = GETNAME(wcs_buffer, FIND_LENGTH);
2013 append_makeflags_string(pmake_machinesfile, &makeflags_string);
2014 append_makeflags_string(pmake_machinesfile, &makeflags_string_posix);
2015 }
2016 /* -R */
2017 if (pmake_cap_r_specified) {
2018 append_char((int) space_char, &makeflags_string);
2019 append_char((int) hyphen_char, &makeflags_string);
2020 append_char('R', &makeflags_string);
2021 append_char((int) space_char, &makeflags_string_posix);
2022 append_char((int) hyphen_char, &makeflags_string_posix);
2023 append_char('R', &makeflags_string_posix);
2024 }
2025
2026 /*
2027 * Make sure MAKEFLAGS is exported
2028 */
2029 maybe_append_prop(makeflags, macro_prop)->
2030 body.macro.exported = true;
2031
2032 if (makeflags_string.buffer.start[1] != (int) nul_char) {
2033 if (makeflags_string.buffer.start[1] != (int) space_char) {
2034 MBSTOWCS(wcs_buffer, NOCATGETS("MFLAGS"));
2035 (void) SETVAR(GETNAME(wcs_buffer, FIND_LENGTH),
2036 GETNAME(makeflags_string.buffer.start,
2037 FIND_LENGTH),
2038 false);
2039 } else {
2040 MBSTOWCS(wcs_buffer, NOCATGETS("MFLAGS"));
2041 (void) SETVAR(GETNAME(wcs_buffer, FIND_LENGTH),
2042 GETNAME(makeflags_string.buffer.start + 2,
2043 FIND_LENGTH),
2044 false);
2045 }
2046 }
2047
2048 /*
2049 * Add command line macro to POSIX makeflags_string
2050 */
2051 if (makeflags_and_macro.start) {
2052 tmp_char = (char) space_char;
2053 cp = makeflags_and_macro.start;
2054 do {
2055 append_char(tmp_char, &makeflags_string_posix);
2056 } while ( tmp_char = *cp++ );
2057 retmem_mb(makeflags_and_macro.start);
2058 }
2059
2060 /*
2061 * Now set the value of MAKEFLAGS macro in accordance
2062 * with current mode.
2063 */
2064 macro = maybe_append_prop(makeflags, macro_prop);
2065 temp = (Boolean) macro->body.macro.read_only;
2066 macro->body.macro.read_only = false;
2067 if(posix || gnu_style) {
2068 makeflags_string_current = &makeflags_string_posix;
2069 } else {
2070 makeflags_string_current = &makeflags_string;
2071 }
2072 if (makeflags_string_current->buffer.start[1] == (int) nul_char) {
2073 makeflags_value_saved =
2074 GETNAME( makeflags_string_current->buffer.start + 1
2075 , FIND_LENGTH
2076 );
2077 } else {
2078 if (makeflags_string_current->buffer.start[1] != (int) space_char) {
2079 makeflags_value_saved =
2080 GETNAME( makeflags_string_current->buffer.start
2081 , FIND_LENGTH
2082 );
2083 } else {
2084 makeflags_value_saved =
2085 GETNAME( makeflags_string_current->buffer.start + 2
2086 , FIND_LENGTH
2087 );
2088 }
2089 }
2090 (void) SETVAR( makeflags
2091 , makeflags_value_saved
2092 , false
2093 );
2094 macro->body.macro.read_only = temp;
2095
2096 /*
2097 * Read command line "-f" arguments and ignore -c, g, j, K, M, m, O and o args.
2098 */
2099 save_do_not_exec_rule = do_not_exec_rule;
2100 do_not_exec_rule = false;
2101 if (read_trace_level > 0) {
2102 trace_reader = true;
2103 }
2104
2105 for (i = 1; i < argc; i++) {
2106 if (argv[i] &&
2107 (argv[i][0] == (int) hyphen_char) &&
2108 (argv[i][1] == 'f') &&
2109 (argv[i][2] == (int) nul_char)) {
2110 argv[i] = NULL; /* Remove -f */
2111 if (i >= argc - 1) {
2112 fatal(catgets(catd, 1, 190, "No filename argument after -f flag"));
2113 }
2114 MBSTOWCS(wcs_buffer, argv[++i]);
2115 primary_makefile = GETNAME(wcs_buffer, FIND_LENGTH);
2116 (void) read_makefile(primary_makefile, true, true, true);
2117 argv[i] = NULL; /* Remove filename */
2118 makefile_read = true;
2119 } else if (argv[i] &&
2120 (argv[i][0] == (int) hyphen_char) &&
2121 (argv[i][1] == 'c' ||
2122 argv[i][1] == 'g' ||
2123 argv[i][1] == 'j' ||
2124 argv[i][1] == 'K' ||
2125 argv[i][1] == 'M' ||
2126 argv[i][1] == 'm' ||
2127 argv[i][1] == 'O' ||
2128 argv[i][1] == 'o') &&
2129 (argv[i][2] == (int) nul_char)) {
2130 argv[i] = NULL;
2131 argv[++i] = NULL;
2132 }
2133 }
2134
2135 /*
2136 * If no command line "-f" args then look for "makefile", and then for
2137 * "Makefile" if "makefile" isn't found.
2138 */
2139 if (!makefile_read) {
2140 (void) read_dir(dot,
2141 (wchar_t *) NULL,
2142 (Property) NULL,
2143 (wchar_t *) NULL);
2144 if (!posix) {
2145 if (makefile_name->stat.is_file) {
2146 if (Makefile->stat.is_file) {
2147 warning(catgets(catd, 1, 310, "Both `makefile' and `Makefile' exist"));
2148 }
2149 primary_makefile = makefile_name;
2150 makefile_read = read_makefile(makefile_name,
2151 false,
2152 false,
2153 true);
2154 }
2155 if (!makefile_read &&
2156 Makefile->stat.is_file) {
2157 primary_makefile = Makefile;
2158 makefile_read = read_makefile(Makefile,
2159 false,
2160 false,
2161 true);
2162 }
2163 } else {
2164
2165 enum sccs_stat save_m_has_sccs = NO_SCCS;
2166 enum sccs_stat save_M_has_sccs = NO_SCCS;
2167
2168 if (makefile_name->stat.is_file) {
2169 if (Makefile->stat.is_file) {
2170 warning(catgets(catd, 1, 191, "Both `makefile' and `Makefile' exist"));
2171 }
2172 }
2173 if (makefile_name->stat.is_file) {
2174 if (makefile_name->stat.has_sccs == NO_SCCS) {
2175 primary_makefile = makefile_name;
2176 makefile_read = read_makefile(makefile_name,
2177 false,
2178 false,
2179 true);
2180 } else {
2181 save_m_has_sccs = makefile_name->stat.has_sccs;
2182 makefile_name->stat.has_sccs = NO_SCCS;
2183 primary_makefile = makefile_name;
2184 makefile_read = read_makefile(makefile_name,
2185 false,
2186 false,
2187 true);
2188 }
2189 }
2190 if (!makefile_read &&
2191 Makefile->stat.is_file) {
2192 if (Makefile->stat.has_sccs == NO_SCCS) {
2193 primary_makefile = Makefile;
2194 makefile_read = read_makefile(Makefile,
2195 false,
2196 false,
2197 true);
2198 } else {
2199 save_M_has_sccs = Makefile->stat.has_sccs;
2200 Makefile->stat.has_sccs = NO_SCCS;
2201 primary_makefile = Makefile;
2202 makefile_read = read_makefile(Makefile,
2203 false,
2204 false,
2205 true);
2206 }
2207 }
2208 if (!makefile_read &&
2209 makefile_name->stat.is_file) {
2210 makefile_name->stat.has_sccs = save_m_has_sccs;
2211 primary_makefile = makefile_name;
2212 makefile_read = read_makefile(makefile_name,
2213 false,
2214 false,
2215 true);
2216 }
2217 if (!makefile_read &&
2218 Makefile->stat.is_file) {
2219 Makefile->stat.has_sccs = save_M_has_sccs;
2220 primary_makefile = Makefile;
2221 makefile_read = read_makefile(Makefile,
2222 false,
2223 false,
2224 true);
2225 }
2226 }
2227 }
2228 do_not_exec_rule = save_do_not_exec_rule;
2229 allrules_read = makefile_read;
2230 trace_reader = false;
2231
2232 /*
2233 * Now get current value of MAKEFLAGS and compare it with
2234 * the saved value we set before reading makefile.
2235 * If they are different then MAKEFLAGS is subsequently set by
2236 * makefile, just leave it there. Otherwise, if make mode
2237 * is changed by using .POSIX target in makefile we need
2238 * to correct MAKEFLAGS value.
2239 */
2240 Name mf_val = getvar(makeflags);
2241 if( (posix != is_xpg4)
2242 && (!strcmp(mf_val->string_mb, makeflags_value_saved->string_mb)))
2243 {
2244 if (makeflags_string_posix.buffer.start[1] == (int) nul_char) {
2245 (void) SETVAR(makeflags,
2246 GETNAME(makeflags_string_posix.buffer.start + 1,
2247 FIND_LENGTH),
2248 false);
2249 } else {
2250 if (makeflags_string_posix.buffer.start[1] != (int) space_char) {
2251 (void) SETVAR(makeflags,
2252 GETNAME(makeflags_string_posix.buffer.start,
2253 FIND_LENGTH),
2254 false);
2255 } else {
2256 (void) SETVAR(makeflags,
2257 GETNAME(makeflags_string_posix.buffer.start + 2,
2258 FIND_LENGTH),
2259 false);
2260 }
2261 }
2262 }
2263
2264 if (makeflags_string.free_after_use) {
2265 retmem(makeflags_string.buffer.start);
2266 }
2267 if (makeflags_string_posix.free_after_use) {
2268 retmem(makeflags_string_posix.buffer.start);
2269 }
2270 makeflags_string.buffer.start = NULL;
2271 makeflags_string_posix.buffer.start = NULL;
2272
2273 if (posix) {
2274 /*
2275 * If the user did not redefine the ARFLAGS macro in the
2276 * default makefile (make.rules), then we'd like to
2277 * change the macro value of ARFLAGS to be in accordance
2278 * with "POSIX" requirements.
2279 */
2280 MBSTOWCS(wcs_buffer, NOCATGETS("ARFLAGS"));
2281 name = GETNAME(wcs_buffer, wslen(wcs_buffer));
2282 macro = get_prop(name->prop, macro_prop);
2283 if ((macro != NULL) && /* Maybe (macro == NULL) || ? */
2284 (IS_EQUAL(macro->body.macro.value->string_mb,
2285 NOCATGETS("rv")))) {
2286 MBSTOWCS(wcs_buffer, NOCATGETS("-rv"));
2287 value = GETNAME(wcs_buffer, wslen(wcs_buffer));
2288 (void) SETVAR(name,
2289 value,
2290 false);
2291 }
2292 }
2293
2294 if (!posix && !svr4) {
2295 set_sgs_support();
2296 }
2297
2298
2299 /*
2300 * Make sure KEEP_STATE is in the environment if KEEP_STATE is on.
2301 */
2302 macro = get_prop(keep_state_name->prop, macro_prop);
2303 if ((macro != NULL) &&
2304 macro->body.macro.exported) {
2305 keep_state = true;
2306 }
2307 if (keep_state) {
2308 if (macro == NULL) {
2309 macro = maybe_append_prop(keep_state_name,
2310 macro_prop);
2311 }
2312 macro->body.macro.exported = true;
2313 (void) SETVAR(keep_state_name,
2314 empty_name,
2315 false);
2316
2317 /*
2318 * Read state file
2319 */
2320
2321 /* Before we read state, let's make sure we have
2322 ** right state file.
2323 */
2324 /* just in case macro references are used in make_state file
2325 ** name, we better expand them at this stage using expand_value.
2326 */
2327 INIT_STRING_FROM_STACK(dest, destbuffer);
2328 expand_value(make_state, &dest, false);
2329
2330 make_state = GETNAME(dest.buffer.start, FIND_LENGTH);
2331
2332 if(!stat(make_state->string_mb, &make_state_stat)) {
2333 if(!(make_state_stat.st_mode & S_IFREG) ) {
2334 /* copy the make_state structure to the other
2335 ** and then let make_state point to the new
2336 ** one.
2337 */
2338 memcpy(&state_filename, make_state,sizeof(state_filename));
2339 state_filename.string_mb = state_file_str_mb;
2340 /* Just a kludge to avoid two slashes back to back */
2341 if((make_state->hash.length == 1)&&
2342 (make_state->string_mb[0] == '/')) {
2343 make_state->hash.length = 0;
2344 make_state->string_mb[0] = '\0';
2345 }
2346 sprintf(state_file_str_mb,NOCATGETS("%s%s"),
2347 make_state->string_mb,NOCATGETS("/.make.state"));
2348 make_state = &state_filename;
2349 /* adjust the length to reflect the appended string */
2350 make_state->hash.length += 12;
2351 }
2352 } else { /* the file doesn't exist or no permission */
2353 char tmp_path[MAXPATHLEN];
2354 char *slashp;
2355
2356 if (slashp = strrchr(make_state->string_mb, '/')) {
2357 strncpy(tmp_path, make_state->string_mb,
2358 (slashp - make_state->string_mb));
2359 tmp_path[slashp - make_state->string_mb]=0;
2360 if(strlen(tmp_path)) {
2361 if(stat(tmp_path, &make_state_stat)) {
2362 warning(catgets(catd, 1, 192, "directory %s for .KEEP_STATE_FILE does not exist"),tmp_path);
2363 }
2364 if (access(tmp_path, F_OK) != 0) {
2365 warning(catgets(catd, 1, 193, "can't access dir %s"),tmp_path);
2366 }
2367 }
2368 }
2369 }
2370 if (report_dependencies_level != 1) {
2371 Makefile_type makefile_type_temp = makefile_type;
2372 makefile_type = reading_statefile;
2373 if (read_trace_level > 1) {
2374 trace_reader = true;
2375 }
2376 (void) read_simple_file(make_state,
2377 false,
2378 false,
2379 false,
2380 false,
2381 false,
2382 true);
2383 trace_reader = false;
2384 makefile_type = makefile_type_temp;
2385 }
2386 }
2387 }
2388
2389 /*
2390 * Scan the argv for options and "=" type args and make them readonly.
2391 */
2392 static void
2393 enter_argv_values(int argc, char *argv[], ASCII_Dyn_Array *makeflags_and_macro)
2394 {
2395 register char *cp;
2396 register int i;
2397 int length;
2398 register Name name;
2399 int opt_separator = argc;
2400 char tmp_char;
2401 wchar_t *tmp_wcs_buffer;
2402 register Name value;
2403 Boolean append = false;
2404 Property macro;
2405 struct stat statbuf;
2406
2407
2408 /* Read argv options and "=" type args and make them readonly. */
2409 makefile_type = reading_nothing;
2410 for (i = 1; i < argc; ++i) {
2411 append = false;
2412 if (argv[i] == NULL) {
2413 continue;
2414 } else if (((argv[i][0] == '-') && (argv[i][1] == '-')) ||
2415 ((argv[i][0] == (int) ' ') &&
2416 (argv[i][1] == (int) '-') &&
2417 (argv[i][2] == (int) ' ') &&
2418 (argv[i][3] == (int) '-'))) {
2419 argv[i] = NULL;
2420 opt_separator = i;
2421 continue;
2422 } else if ((i < opt_separator) && (argv[i][0] == (int) hyphen_char)) {
2423 switch (parse_command_option(argv[i][1])) {
2424 case 1: /* -f seen */
2425 ++i;
2426 continue;
2427 case 2: /* -c seen */
2428 if (argv[i+1] == NULL) {
2429 fatal(catgets(catd, 1, 194, "No dmake rcfile argument after -c flag"));
2430 }
2431 MBSTOWCS(wcs_buffer, NOCATGETS("DMAKE_RCFILE"));
2432 name = GETNAME(wcs_buffer, FIND_LENGTH);
2433 break;
2434 case 4: /* -g seen */
2435 if (argv[i+1] == NULL) {
2436 fatal(catgets(catd, 1, 195, "No dmake group argument after -g flag"));
2437 }
2438 MBSTOWCS(wcs_buffer, NOCATGETS("DMAKE_GROUP"));
2439 name = GETNAME(wcs_buffer, FIND_LENGTH);
2440 break;
2441 case 8: /* -j seen */
2442 if (argv[i+1] == NULL) {
2443 fatal(catgets(catd, 1, 196, "No dmake max jobs argument after -j flag"));
2444 }
2445 MBSTOWCS(wcs_buffer, NOCATGETS("DMAKE_MAX_JOBS"));
2446 name = GETNAME(wcs_buffer, FIND_LENGTH);
2447 break;
2448 case 16: /* -M seen */
2449 if (argv[i+1] == NULL) {
2450 fatal(catgets(catd, 1, 323, "No pmake machinesfile argument after -M flag"));
2451 }
2452 MBSTOWCS(wcs_buffer, NOCATGETS("PMAKE_MACHINESFILE"));
2453 name = GETNAME(wcs_buffer, FIND_LENGTH);
2454 break;
2455 case 32: /* -m seen */
2456 if (argv[i+1] == NULL) {
2457 fatal(catgets(catd, 1, 197, "No dmake mode argument after -m flag"));
2458 }
2459 MBSTOWCS(wcs_buffer, NOCATGETS("DMAKE_MODE"));
2460 name = GETNAME(wcs_buffer, FIND_LENGTH);
2461 break;
2462 case 128: /* -O seen */
2463 if (argv[i+1] == NULL) {
2464 fatal(catgets(catd, 1, 287, "No file descriptor argument after -O flag"));
2465 }
2466 mtool_msgs_fd = atoi(argv[i+1]);
2467 /* find out if mtool_msgs_fd is a valid file descriptor */
2468 if (fstat(mtool_msgs_fd, &statbuf) < 0) {
2469 fatal(catgets(catd, 1, 355, "Invalid file descriptor %d after -O flag"), mtool_msgs_fd);
2470 }
2471 argv[i] = NULL;
2472 argv[i+1] = NULL;
2473 continue;
2474 case 256: /* -K seen */
2475 if (argv[i+1] == NULL) {
2476 fatal(catgets(catd, 1, 288, "No makestate filename argument after -K flag"));
2477 }
2478 MBSTOWCS(wcs_buffer, argv[i+1]);
2479 make_state = GETNAME(wcs_buffer, FIND_LENGTH);
2480 keep_state = true;
2481 argv[i] = NULL;
2482 argv[i+1] = NULL;
2483 continue;
2484 case 512: /* -o seen */
2485 if (argv[i+1] == NULL) {
2486 fatal(catgets(catd, 1, 312, "No dmake output dir argument after -o flag"));
2487 }
2488 MBSTOWCS(wcs_buffer, NOCATGETS("DMAKE_ODIR"));
2489 name = GETNAME(wcs_buffer, FIND_LENGTH);
2490 break;
2491 case 1024: /* -x seen */
2492 if (argv[i+1] == NULL) {
2493 fatal(catgets(catd, 1, 351, "No argument after -x flag"));
2494 }
2495 length = strlen( NOCATGETS("SUN_MAKE_COMPAT_MODE="));
2496 if (strncmp(argv[i+1], NOCATGETS("SUN_MAKE_COMPAT_MODE="), length) == 0) {
2497 argv[i+1] = &argv[i+1][length];
2498 MBSTOWCS(wcs_buffer, NOCATGETS("SUN_MAKE_COMPAT_MODE"));
2499 name = GETNAME(wcs_buffer, FIND_LENGTH);
2500 dmake_compat_mode_specified = dmake_add_mode_specified;
2501 break;
2502 }
2503 length = strlen( NOCATGETS("DMAKE_OUTPUT_MODE="));
2504 if (strncmp(argv[i+1], NOCATGETS("DMAKE_OUTPUT_MODE="), length) == 0) {
2505 argv[i+1] = &argv[i+1][length];
2506 MBSTOWCS(wcs_buffer, NOCATGETS("DMAKE_OUTPUT_MODE"));
2507 name = GETNAME(wcs_buffer, FIND_LENGTH);
2508 dmake_output_mode_specified = dmake_add_mode_specified;
2509 } else {
2510 warning(catgets(catd, 1, 354, "Unknown argument `%s' after -x flag (ignored)"),
2511 argv[i+1]);
2512 argv[i] = argv[i + 1] = NULL;
2513 continue;
2514 }
2515 break;
2516 default: /* Shouldn't reach here */
2517 argv[i] = NULL;
2518 continue;
2519 }
2520 argv[i] = NULL;
2521 if (i == (argc - 1)) {
2522 break;
2523 }
2524 if ((length = strlen(argv[i+1])) >= MAXPATHLEN) {
2525 tmp_wcs_buffer = ALLOC_WC(length + 1);
2526 (void) mbstowcs(tmp_wcs_buffer, argv[i+1], length + 1);
2527 value = GETNAME(tmp_wcs_buffer, FIND_LENGTH);
2528 retmem(tmp_wcs_buffer);
2529 } else {
2530 MBSTOWCS(wcs_buffer, argv[i+1]);
2531 value = GETNAME(wcs_buffer, FIND_LENGTH);
2532 }
2533 argv[i+1] = NULL;
2534 } else if ((cp = strchr(argv[i], (int) equal_char)) != NULL) {
2535 /*
2536 * Combine all macro in dynamic array
2537 */
2538 if(*(cp-1) == (int) plus_char)
2539 {
2540 if(isspace(*(cp-2))) {
2541 append = true;
2542 cp--;
2543 }
2544 }
2545 if(!append)
2546 append_or_replace_macro_in_dyn_array(makeflags_and_macro, argv[i]);
2547
2548 while (isspace(*(cp-1))) {
2549 cp--;
2550 }
2551 tmp_char = *cp;
2552 *cp = (int) nul_char;
2553 MBSTOWCS(wcs_buffer, argv[i]);
2554 *cp = tmp_char;
2555 name = GETNAME(wcs_buffer, wslen(wcs_buffer));
2556 while (*cp != (int) equal_char) {
2557 cp++;
2558 }
2559 cp++;
2560 while (isspace(*cp) && (*cp != (int) nul_char)) {
2561 cp++;
2562 }
2563 if ((length = strlen(cp)) >= MAXPATHLEN) {
2564 tmp_wcs_buffer = ALLOC_WC(length + 1);
2565 (void) mbstowcs(tmp_wcs_buffer, cp, length + 1);
2566 value = GETNAME(tmp_wcs_buffer, FIND_LENGTH);
2567 retmem(tmp_wcs_buffer);
2568 } else {
2569 MBSTOWCS(wcs_buffer, cp);
2570 value = GETNAME(wcs_buffer, FIND_LENGTH);
2571 }
2572 argv[i] = NULL;
2573 } else {
2574 /* Illegal MAKEFLAGS argument */
2575 continue;
2576 }
2577 if(append) {
2578 setvar_append(name, value);
2579 append = false;
2580 } else {
2581 macro = maybe_append_prop(name, macro_prop);
2582 macro->body.macro.exported = true;
2583 SETVAR(name, value, false)->body.macro.read_only = true;
2584 }
2585 }
2586 }
2587
2588 /*
2589 * Append the DMake option and value to the MAKEFLAGS string.
2590 */
2591 static void
2592 append_makeflags_string(Name name, register String makeflags_string)
2593 {
2594 const char *option;
2595
2596 if (strcmp(name->string_mb, NOCATGETS("DMAKE_GROUP")) == 0) {
2597 option = NOCATGETS(" -g ");
2598 } else if (strcmp(name->string_mb, NOCATGETS("DMAKE_MAX_JOBS")) == 0) {
2599 option = NOCATGETS(" -j ");
2600 } else if (strcmp(name->string_mb, NOCATGETS("DMAKE_MODE")) == 0) {
2601 option = NOCATGETS(" -m ");
2602 } else if (strcmp(name->string_mb, NOCATGETS("DMAKE_ODIR")) == 0) {
2603 option = NOCATGETS(" -o ");
2604 } else if (strcmp(name->string_mb, NOCATGETS("DMAKE_RCFILE")) == 0) {
2605 option = NOCATGETS(" -c ");
2606 } else if (strcmp(name->string_mb, NOCATGETS("PMAKE_MACHINESFILE")) == 0) {
2607 option = NOCATGETS(" -M ");
2608 } else if (strcmp(name->string_mb, NOCATGETS("DMAKE_OUTPUT_MODE")) == 0) {
2609 option = NOCATGETS(" -x DMAKE_OUTPUT_MODE=");
2610 } else if (strcmp(name->string_mb, NOCATGETS("SUN_MAKE_COMPAT_MODE")) == 0) {
2611 option = NOCATGETS(" -x SUN_MAKE_COMPAT_MODE=");
2612 } else {
2613 fatal(catgets(catd, 1, 289, "Internal error: name not recognized in append_makeflags_string()"));
2614 }
2615 Property prop = maybe_append_prop(name, macro_prop);
2616 if( prop == 0 || prop->body.macro.value == 0 ||
2617 prop->body.macro.value->string_mb == 0 ) {
2618 return;
2619 }
2620 char mbs_value[MAXPATHLEN + 100];
2621 strcpy(mbs_value, option);
2622 strcat(mbs_value, prop->body.macro.value->string_mb);
2623 MBSTOWCS(wcs_buffer, mbs_value);
2624 append_string(wcs_buffer, makeflags_string, FIND_LENGTH);
2625 }
2626
2627 /*
2628 * read_environment(read_only)
2629 *
2630 * This routine reads the process environment when make starts and enters
2631 * it as make macros. The environment variable SHELL is ignored.
2632 *
2633 * Parameters:
2634 * read_only Should we make env vars read only?
2635 *
2636 * Global variables used:
2637 * report_pwd Set if this make was started by other make
2638 */
2639 static void
2640 read_environment(Boolean read_only)
2641 {
2642 register char **environment;
2643 int length;
2644 wchar_t *tmp_wcs_buffer;
2645 Boolean alloced_tmp_wcs_buffer = false;
2646 register wchar_t *name;
2647 register wchar_t *value;
2648 register Name macro;
2649 Property val;
2650 Boolean read_only_saved;
2651
2652 reading_environment = true;
2653 environment = environ;
2654 for (; *environment; environment++) {
2655 read_only_saved = read_only;
2656 if ((length = strlen(*environment)) >= MAXPATHLEN) {
2657 tmp_wcs_buffer = ALLOC_WC(length + 1);
2658 alloced_tmp_wcs_buffer = true;
2659 (void) mbstowcs(tmp_wcs_buffer, *environment, length + 1);
2660 name = tmp_wcs_buffer;
2661 } else {
2662 MBSTOWCS(wcs_buffer, *environment);
2663 name = wcs_buffer;
2664 }
2665 value = (wchar_t *) wschr(name, (int) equal_char);
2666
2667 /*
2668 * Looks like there's a bug in the system, but sometimes
2669 * you can get blank lines in *environment.
2670 */
2671 if (!value) {
2672 continue;
2673 }
2674 MBSTOWCS(wcs_buffer2, NOCATGETS("SHELL="));
2675 if (IS_WEQUALN(name, wcs_buffer2, wslen(wcs_buffer2))) {
2676 continue;
2677 }
2678 MBSTOWCS(wcs_buffer2, NOCATGETS("MAKEFLAGS="));
2679 if (IS_WEQUALN(name, wcs_buffer2, wslen(wcs_buffer2))) {
2680 report_pwd = true;
2681 /*
2682 * In POSIX mode we do not want MAKEFLAGS to be readonly.
2683 * If the MAKEFLAGS macro is subsequently set by the makefile,
2684 * it replaces the MAKEFLAGS variable currently found in the
2685 * environment.
2686 * See Assertion 50 in section 6.2.5.3 of standard P1003.3.2/D8.
2687 */
2688 if(posix) {
2689 read_only_saved = false;
2690 }
2691 }
2692
2693 /*
2694 * We ignore SUNPRO_DEPENDENCIES. This environment variable is
2695 * set by make and read by cpp which then writes info to
2696 * .make.dependency.xxx. When make is invoked by another make
2697 * (recursive make), we don't want to read this because then
2698 * the child make will end up writing to the parent
2699 * directory's .make.state and clobbering them.
2700 */
2701 MBSTOWCS(wcs_buffer2, NOCATGETS("SUNPRO_DEPENDENCIES"));
2702 if (IS_WEQUALN(name, wcs_buffer2, wslen(wcs_buffer2))) {
2703 continue;
2704 }
2705
2706 macro = GETNAME(name, value - name);
2707 maybe_append_prop(macro, macro_prop)->body.macro.exported =
2708 true;
2709 if ((value == NULL) || ((value + 1)[0] == (int) nul_char)) {
2710 val = setvar_daemon(macro,
2711 (Name) NULL,
2712 false, no_daemon, false, debug_level);
2713 } else {
2714 val = setvar_daemon(macro,
2715 GETNAME(value + 1, FIND_LENGTH),
2716 false, no_daemon, false, debug_level);
2717 }
2718 val->body.macro.read_only = read_only_saved;
2719 if (alloced_tmp_wcs_buffer) {
2720 retmem(tmp_wcs_buffer);
2721 alloced_tmp_wcs_buffer = false;
2722 }
2723 }
2724 reading_environment = false;
2725 }
2726
2727 /*
2728 * read_makefile(makefile, complain, must_exist, report_file)
2729 *
2730 * Read one makefile and check the result
2731 *
2732 * Return value:
2733 * false is the read failed
2734 *
2735 * Parameters:
2736 * makefile The file to read
2737 * complain Passed thru to read_simple_file()
2738 * must_exist Passed thru to read_simple_file()
2739 * report_file Passed thru to read_simple_file()
2740 *
2741 * Global variables used:
2742 * makefile_type Set to indicate we are reading main file
2743 * recursion_level Initialized
2744 */
2745 static Boolean
2746 read_makefile(register Name makefile, Boolean complain, Boolean must_exist, Boolean report_file)
2747 {
2748 Boolean b;
2749
2750 makefile_type = reading_makefile;
2751 recursion_level = 0;
2752 reading_dependencies = true;
2753 b = read_simple_file(makefile, true, true, complain,
2754 must_exist, report_file, false);
2755 reading_dependencies = false;
2756 return b;
2757 }
2758
2759 /*
2760 * make_targets(argc, argv, parallel_flag)
2761 *
2762 * Call doname on the specified targets
2763 *
2764 * Parameters:
2765 * argc You know what this is
2766 * argv You know what this is
2767 * parallel_flag True if building in parallel
2768 *
2769 * Global variables used:
2770 * build_failed_seen Used to generated message after failed -k
2771 * commands_done Used to generate message "Up to date"
2772 * default_target_to_build First proper target in makefile
2773 * init The Name ".INIT", use to run command
2774 * parallel Global parallel building flag
2775 * quest make -q, suppresses messages
2776 * recursion_level Initialized, used for tracing
2777 * report_dependencies make -P, regroves whole process
2778 */
2779 static void
2780 make_targets(int argc, char **argv, Boolean parallel_flag)
2781 {
2782 int i;
2783 char *cp;
2784 Doname result;
2785 register Boolean target_to_make_found = false;
2786
2787 (void) doname(init, true, true);
2788 recursion_level = 1;
2789 parallel = parallel_flag;
2790 /*
2791 * make remaining args
2792 */
2793 /*
2794 if ((report_dependencies_level == 0) && parallel) {
2795 */
2796 if (parallel) {
2797 /*
2798 * If building targets in parallel, start all of the
2799 * remaining args to build in parallel.
2800 */
2801 for (i = 1; i < argc; i++) {
2802 if ((cp = argv[i]) != NULL) {
2803 commands_done = false;
2804 if ((cp[0] == (int) period_char) &&
2805 (cp[1] == (int) slash_char)) {
2806 cp += 2;
2807 }
2808 if((cp[0] == (int) ' ') &&
2809 (cp[1] == (int) '-') &&
2810 (cp[2] == (int) ' ') &&
2811 (cp[3] == (int) '-')) {
2812 argv[i] = NULL;
2813 continue;
2814 }
2815 MBSTOWCS(wcs_buffer, cp);
2816 //default_target_to_build = GETNAME(wcs_buffer,
2817 // FIND_LENGTH);
2818 default_target_to_build = normalize_name(wcs_buffer,
2819 wslen(wcs_buffer));
2820 if (default_target_to_build == wait_name) {
2821 if (parallel_process_cnt > 0) {
2822 finish_running();
2823 }
2824 continue;
2825 }
2826 top_level_target = get_wstring(default_target_to_build->string_mb);
2827 /*
2828 * If we can't execute the current target in
2829 * parallel, hold off the target processing
2830 * to preserve the order of the targets as they appeared
2831 * in command line.
2832 */
2833 if (!parallel_ok(default_target_to_build, false)
2834 && parallel_process_cnt > 0) {
2835 finish_running();
2836 }
2837 result = doname_check(default_target_to_build,
2838 true,
2839 false,
2840 false);
2841 gather_recursive_deps();
2842 if (/* !commands_done && */
2843 (result == build_ok) &&
2844 !quest &&
2845 (report_dependencies_level == 0) /* &&
2846 (exists(default_target_to_build) > file_doesnt_exist) */) {
2847 if (posix) {
2848 if (!commands_done) {
2849 (void) printf(catgets(catd, 1, 293, "`%s' is updated.\n"),
2850 default_target_to_build->string_mb);
2851 } else {
2852 if (no_action_was_taken) {
2853 (void) printf(catgets(catd, 1, 294, "`%s': no action was taken.\n"),
2854 default_target_to_build->string_mb);
2855 }
2856 }
2857 } else {
2858 default_target_to_build->stat.time = file_no_time;
2859 if (!commands_done &&
2860 (exists(default_target_to_build) > file_doesnt_exist)) {
2861 (void) printf(catgets(catd, 1, 295, "`%s' is up to date.\n"),
2862 default_target_to_build->string_mb);
2863 }
2864 }
2865 }
2866 }
2867 }
2868 /* Now wait for all of the targets to finish running */
2869 finish_running();
2870 // setjmp(jmpbuffer);
2871
2872 }
2873 for (i = 1; i < argc; i++) {
2874 if ((cp = argv[i]) != NULL) {
2875 target_to_make_found = true;
2876 if ((cp[0] == (int) period_char) &&
2877 (cp[1] == (int) slash_char)) {
2878 cp += 2;
2879 }
2880 if((cp[0] == (int) ' ') &&
2881 (cp[1] == (int) '-') &&
2882 (cp[2] == (int) ' ') &&
2883 (cp[3] == (int) '-')) {
2884 argv[i] = NULL;
2885 continue;
2886 }
2887 MBSTOWCS(wcs_buffer, cp);
2888 default_target_to_build = normalize_name(wcs_buffer, wslen(wcs_buffer));
2889 top_level_target = get_wstring(default_target_to_build->string_mb);
2890 report_recursion(default_target_to_build);
2891 commands_done = false;
2892 if (parallel) {
2893 result = (Doname) default_target_to_build->state;
2894 } else {
2895 result = doname_check(default_target_to_build,
2896 true,
2897 false,
2898 false);
2899 }
2900 gather_recursive_deps();
2901 if (build_failed_seen) {
2902 build_failed_ever_seen = true;
2903 warning(catgets(catd, 1, 200, "Target `%s' not remade because of errors"),
2904 default_target_to_build->string_mb);
2905 }
2906 build_failed_seen = false;
2907 if (report_dependencies_level > 0) {
2908 print_dependencies(default_target_to_build,
2909 get_prop(default_target_to_build->prop,
2910 line_prop));
2911 }
2912 default_target_to_build->stat.time =
2913 file_no_time;
2914 if (default_target_to_build->colon_splits > 0) {
2915 default_target_to_build->state =
2916 build_dont_know;
2917 }
2918 if (!parallel &&
2919 /* !commands_done && */
2920 (result == build_ok) &&
2921 !quest &&
2922 (report_dependencies_level == 0) /* &&
2923 (exists(default_target_to_build) > file_doesnt_exist) */) {
2924 if (posix) {
2925 if (!commands_done) {
2926 (void) printf(catgets(catd, 1, 296, "`%s' is updated.\n"),
2927 default_target_to_build->string_mb);
2928 } else {
2929 if (no_action_was_taken) {
2930 (void) printf(catgets(catd, 1, 297, "`%s': no action was taken.\n"),
2931 default_target_to_build->string_mb);
2932 }
2933 }
2934 } else {
2935 if (!commands_done &&
2936 (exists(default_target_to_build) > file_doesnt_exist)) {
2937 (void) printf(catgets(catd, 1, 298, "`%s' is up to date.\n"),
2938 default_target_to_build->string_mb);
2939 }
2940 }
2941 }
2942 }
2943 }
2944
2945 /*
2946 * If no file arguments have been encountered,
2947 * make the first name encountered that doesnt start with a dot
2948 */
2949 if (!target_to_make_found) {
2950 if (default_target_to_build == NULL) {
2951 fatal(catgets(catd, 1, 202, "No arguments to build"));
2952 }
2953 commands_done = false;
2954 top_level_target = get_wstring(default_target_to_build->string_mb);
2955 report_recursion(default_target_to_build);
2956
2957
2958 if (getenv(NOCATGETS("SPRO_EXPAND_ERRORS"))){
2959 (void) printf(NOCATGETS("::(%s)\n"),
2960 default_target_to_build->string_mb);
2961 }
2962
2963
2964 result = doname_parallel(default_target_to_build, true, false);
2965 gather_recursive_deps();
2966 if (build_failed_seen) {
2967 build_failed_ever_seen = true;
2968 warning(catgets(catd, 1, 203, "Target `%s' not remade because of errors"),
2969 default_target_to_build->string_mb);
2970 }
2971 build_failed_seen = false;
2972 if (report_dependencies_level > 0) {
2973 print_dependencies(default_target_to_build,
2974 get_prop(default_target_to_build->
2975 prop,
2976 line_prop));
2977 }
2978 default_target_to_build->stat.time = file_no_time;
2979 if (default_target_to_build->colon_splits > 0) {
2980 default_target_to_build->state = build_dont_know;
2981 }
2982 if (/* !commands_done && */
2983 (result == build_ok) &&
2984 !quest &&
2985 (report_dependencies_level == 0) /* &&
2986 (exists(default_target_to_build) > file_doesnt_exist) */) {
2987 if (posix) {
2988 if (!commands_done) {
2989 (void) printf(catgets(catd, 1, 299, "`%s' is updated.\n"),
2990 default_target_to_build->string_mb);
2991 } else {
2992 if (no_action_was_taken) {
2993 (void) printf(catgets(catd, 1, 300, "`%s': no action was taken.\n"),
2994 default_target_to_build->string_mb);
2995 }
2996 }
2997 } else {
2998 if (!commands_done &&
2999 (exists(default_target_to_build) > file_doesnt_exist)) {
3000 (void) printf(catgets(catd, 1, 301, "`%s' is up to date.\n"),
3001 default_target_to_build->string_mb);
3002 }
3003 }
3004 }
3005 }
3006 }
3007
3008 /*
3009 * report_recursion(target)
3010 *
3011 * If this is a recursive make and the parent make has KEEP_STATE on
3012 * this routine reports the dependency to the parent make
3013 *
3014 * Parameters:
3015 * target Target to report
3016 *
3017 * Global variables used:
3018 * makefiles_used List of makefiles read
3019 * recursive_name The Name ".RECURSIVE", printed
3020 * report_dependency dwight
3021 */
3022 static void
3023 report_recursion(register Name target)
3024 {
3025 register FILE *report_file = get_report_file();
3026
3027 if ((report_file == NULL) || (report_file == (FILE*)-1)) {
3028 return;
3029 }
3030 if (primary_makefile == NULL) {
3031 /*
3032 * This can happen when there is no makefile and
3033 * only implicit rules are being used.
3034 */
3035 return;
3036 }
3037 (void) fprintf(report_file,
3038 "%s: %s ",
3039 get_target_being_reported_for(),
3040 recursive_name->string_mb);
3041 report_dependency(get_current_path());
3042 report_dependency(target->string_mb);
3043 report_dependency(primary_makefile->string_mb);
3044 (void) fprintf(report_file, "\n");
3045 }
3046
3047 /* Next function "append_or_replace_macro_in_dyn_array" must be in "misc.cc". */
3048 /* NIKMOL */
3049 extern void
3050 append_or_replace_macro_in_dyn_array(ASCII_Dyn_Array *Ar, char *macro)
3051 {
3052 register char *cp0; /* work pointer in macro */
3053 register char *cp1; /* work pointer in array */
3054 register char *cp2; /* work pointer in array */
3055 register char *cp3; /* work pointer in array */
3056 register char *name; /* macro name */
3057 register char *value; /* macro value */
3058 register int len_array;
3059 register int len_macro;
3060
3061 char * esc_value = NULL;
3062 int esc_len;
3063
3064 if (!(len_macro = strlen(macro))) return;
3065 name = macro;
3066 while (isspace(*(name))) {
3067 name++;
3068 }
3069 if (!(value = strchr(name, (int) equal_char))) {
3070 /* no '=' in macro */
3071 goto ERROR_MACRO;
3072 }
3073 cp0 = value;
3074 value++;
3075 while (isspace(*(value))) {
3076 value++;
3077 }
3078 while (isspace(*(cp0-1))) {
3079 cp0--;
3080 }
3081 if (cp0 <= name) goto ERROR_MACRO; /* no name */
3082 if (!(Ar->size)) goto ALLOC_ARRAY;
3083 cp1 = Ar->start;
3084
3085 LOOK_FOR_NAME:
3086 if (!(cp1 = strchr(cp1, name[0]))) goto APPEND_MACRO;
3087 if (!(cp2 = strchr(cp1, (int) equal_char))) goto APPEND_MACRO;
3088 if (strncmp(cp1, name, (size_t)(cp0-name))) {
3089 /* another name */
3090 cp1++;
3091 goto LOOK_FOR_NAME;
3092 }
3093 if (cp1 != Ar->start) {
3094 if (!isspace(*(cp1-1))) {
3095 /* another name */
3096 cp1++;
3097 goto LOOK_FOR_NAME;
3098 }
3099 }
3100 for (cp3 = cp1 + (cp0-name); cp3 < cp2; cp3++) {
3101 if (isspace(*cp3)) continue;
3102 /* else: another name */
3103 cp1++;
3104 goto LOOK_FOR_NAME;
3105 }
3106 /* Look for the next macro name in array */
3107 cp3 = cp2+1;
3108 if (*cp3 != (int) doublequote_char) {
3109 /* internal error */
3110 goto ERROR_MACRO;
3111 }
3112 if (!(cp3 = strchr(cp3+1, (int) doublequote_char))) {
3113 /* internal error */
3114 goto ERROR_MACRO;
3115 }
3116 cp3++;
3117 while (isspace(*cp3)) {
3118 cp3++;
3119 }
3120
3121 cp2 = cp1; /* remove old macro */
3122 if ((*cp3) && (cp3 < Ar->start + Ar->size)) {
3123 for (; cp3 < Ar->start + Ar->size; cp3++) {
3124 *cp2++ = *cp3;
3125 }
3126 }
3127 for (; cp2 < Ar->start + Ar->size; cp2++) {
3128 *cp2 = 0;
3129 }
3130 if (*cp1) {
3131 /* check next name */
3132 goto LOOK_FOR_NAME;
3133 }
3134 goto APPEND_MACRO;
3135
3136 ALLOC_ARRAY:
3137 if (Ar->size) {
3138 cp1 = Ar->start;
3139 } else {
3140 cp1 = 0;
3141 }
3142 Ar->size += 128;
3143 Ar->start = getmem(Ar->size);
3144 for (len_array=0; len_array < Ar->size; len_array++) {
3145 Ar->start[len_array] = 0;
3146 }
3147 if (cp1) {
3148 strcpy(Ar->start, cp1);
3149 retmem((wchar_t *) cp1);
3150 }
3151
3152 APPEND_MACRO:
3153 len_array = strlen(Ar->start);
3154 esc_value = (char*)malloc(strlen(value)*2 + 1);
3155 quote_str(value, esc_value);
3156 esc_len = strlen(esc_value) - strlen(value);
3157 if (len_array + len_macro + esc_len + 5 >= Ar->size) goto ALLOC_ARRAY;
3158 strcat(Ar->start, " ");
3159 strncat(Ar->start, name, cp0-name);
3160 strcat(Ar->start, "=");
3161 strncat(Ar->start, esc_value, strlen(esc_value));
3162 free(esc_value);
3163 return;
3164 ERROR_MACRO:
3165 /* Macro without '=' or with invalid left/right part */
3166 return;
3167 }
3168
3169 #ifdef TEAMWARE_MAKE_CMN
3170 /*
3171 * This function, if registered w/ avo_cli_get_license(), will be called
3172 * if the application is about to exit because:
3173 * 1) there has been certain unrecoverable error(s) that cause the
3174 * application to exit immediately.
3175 * 2) the user has lost a license while the application is running.
3176 */
3177 extern "C" void
3178 dmake_exit_callback(void)
3179 {
3180 fatal(catgets(catd, 1, 306, "can not get a license, exiting..."));
3181 exit(1);
3182 }
3183
3184 /*
3185 * This function, if registered w/ avo_cli_get_license(), will be called
3186 * if the application can not get a license.
3187 */
3188 extern "C" void
3189 dmake_message_callback(char *err_msg)
3190 {
3191 static Boolean first = true;
3192
3193 if (!first) {
3194 return;
3195 }
3196 first = false;
3197 if ((!list_all_targets) &&
3198 (report_dependencies_level == 0) &&
3199 (dmake_mode_type != serial_mode)) {
3200 warning(catgets(catd, 1, 313, "can not get a TeamWare license, defaulting to serial mode..."));
3201 }
3202 }
3203 #endif
3204
3205
3206 static void
3207 report_dir_enter_leave(Boolean entering)
3208 {
3209 char rcwd[MAXPATHLEN];
3210 static char * mlev = NULL;
3211 char * make_level_str = NULL;
3212 int make_level_val = 0;
3213
3214 make_level_str = getenv(NOCATGETS("MAKELEVEL"));
3215 if(make_level_str) {
3216 make_level_val = atoi(make_level_str);
3217 }
3218 if(mlev == NULL) {
3219 mlev = (char*) malloc(MAXPATHLEN);
3220 }
3221 if(entering) {
3222 sprintf(mlev, NOCATGETS("MAKELEVEL=%d"), make_level_val + 1);
3223 } else {
3224 make_level_val--;
3225 sprintf(mlev, NOCATGETS("MAKELEVEL=%d"), make_level_val);
3226 }
3227 putenv(mlev);
3228
3229 if(report_cwd) {
3230 if(make_level_val <= 0) {
3231 if(entering) {
3232 sprintf( rcwd
3233 , catgets(catd, 1, 329, "dmake: Entering directory `%s'\n")
3234 , get_current_path());
3235 } else {
3236 sprintf( rcwd
3237 , catgets(catd, 1, 331, "dmake: Leaving directory `%s'\n")
3238 , get_current_path());
3239 }
3240 } else {
3241 if(entering) {
3242 sprintf( rcwd
3243 , catgets(catd, 1, 333, "dmake[%d]: Entering directory `%s'\n")
3244 , make_level_val, get_current_path());
3245 } else {
3246 sprintf( rcwd
3247 , catgets(catd, 1, 335, "dmake[%d]: Leaving directory `%s'\n")
3248 , make_level_val, get_current_path());
3249 }
3250 }
3251 printf(NOCATGETS("%s"), rcwd);
3252 }
3253 }