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