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