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