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(wchar_t *name_string, 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(wchar_t *name_string, 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, 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 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(int argc, char **argv) 914 { 915 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 int i; 921 int j; 922 int k; 923 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(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 char ch; 1782 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 int i; 1789 int j; 1790 Name keep_state_name; 1791 int length; 1792 Name Makefile; 1793 Property macro; 1794 struct stat make_state_stat; 1795 Name makefile_name; 1796 int makefile_next = 0; 1797 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 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 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 * Note: cw depends on short flags with no arguments appearing 1911 * first in MAKEFLAGS. If this behavior changes, cw will need to 1912 * be updated. 1913 */ 1914 INIT_STRING_FROM_STACK(makeflags_string, buffer); 1915 INIT_STRING_FROM_STACK(makeflags_string_posix, buffer_posix); 1916 append_char((int) hyphen_char, &makeflags_string); 1917 append_char((int) hyphen_char, &makeflags_string_posix); 1918 1919 switch (read_trace_level) { 1920 case 2: 1921 append_char('D', &makeflags_string); 1922 append_char('D', &makeflags_string_posix); 1923 /* FALLTHROUGH */ 1924 case 1: 1925 append_char('D', &makeflags_string); 1926 append_char('D', &makeflags_string_posix); 1927 } 1928 switch (debug_level) { 1929 case 2: 1930 append_char('d', &makeflags_string); 1931 append_char('d', &makeflags_string_posix); 1932 /* FALLTHROUGH */ 1933 case 1: 1934 append_char('d', &makeflags_string); 1935 append_char('d', &makeflags_string_posix); 1936 } 1937 if (env_wins) { 1938 append_char('e', &makeflags_string); 1939 append_char('e', &makeflags_string_posix); 1940 } 1941 if (ignore_errors_all) { 1942 append_char('i', &makeflags_string); 1943 append_char('i', &makeflags_string_posix); 1944 } 1945 if (continue_after_error) { 1946 if (stop_after_error_ever_seen) { 1947 append_char('S', &makeflags_string_posix); 1948 append_char((int) space_char, &makeflags_string_posix); 1949 append_char((int) hyphen_char, &makeflags_string_posix); 1950 } 1951 append_char('k', &makeflags_string); 1952 append_char('k', &makeflags_string_posix); 1953 } else { 1954 if (stop_after_error_ever_seen 1955 && continue_after_error_ever_seen) { 1956 append_char('k', &makeflags_string_posix); 1957 append_char((int) space_char, &makeflags_string_posix); 1958 append_char((int) hyphen_char, &makeflags_string_posix); 1959 append_char('S', &makeflags_string_posix); 1960 } 1961 } 1962 if (do_not_exec_rule) { 1963 append_char('n', &makeflags_string); 1964 append_char('n', &makeflags_string_posix); 1965 } 1966 switch (report_dependencies_level) { 1967 case 4: 1968 append_char('P', &makeflags_string); 1969 append_char('P', &makeflags_string_posix); 1970 /* FALLTHROUGH */ 1971 case 3: 1972 append_char('P', &makeflags_string); 1973 append_char('P', &makeflags_string_posix); 1974 /* FALLTHROUGH */ 1975 case 2: 1976 append_char('P', &makeflags_string); 1977 append_char('P', &makeflags_string_posix); 1978 /* FALLTHROUGH */ 1979 case 1: 1980 append_char('P', &makeflags_string); 1981 append_char('P', &makeflags_string_posix); 1982 } 1983 if (trace_status) { 1984 append_char('p', &makeflags_string); 1985 append_char('p', &makeflags_string_posix); 1986 } 1987 if (quest) { 1988 append_char('q', &makeflags_string); 1989 append_char('q', &makeflags_string_posix); 1990 } 1991 if (silent_all) { 1992 append_char('s', &makeflags_string); 1993 append_char('s', &makeflags_string_posix); 1994 } 1995 if (touch) { 1996 append_char('t', &makeflags_string); 1997 append_char('t', &makeflags_string_posix); 1998 } 1999 if (build_unconditional) { 2000 append_char('u', &makeflags_string); 2001 append_char('u', &makeflags_string_posix); 2002 } 2003 if (report_cwd) { 2004 append_char('w', &makeflags_string); 2005 append_char('w', &makeflags_string_posix); 2006 } 2007 /* -c dmake_rcfile */ 2008 if (dmake_rcfile_specified) { 2009 MBSTOWCS(wcs_buffer, "DMAKE_RCFILE"); 2010 dmake_rcfile = GETNAME(wcs_buffer, FIND_LENGTH); 2011 append_makeflags_string(dmake_rcfile, &makeflags_string); 2012 append_makeflags_string(dmake_rcfile, &makeflags_string_posix); 2013 } 2014 /* -g dmake_group */ 2015 if (dmake_group_specified) { 2016 MBSTOWCS(wcs_buffer, "DMAKE_GROUP"); 2017 dmake_group = GETNAME(wcs_buffer, FIND_LENGTH); 2018 append_makeflags_string(dmake_group, &makeflags_string); 2019 append_makeflags_string(dmake_group, &makeflags_string_posix); 2020 } 2021 /* -j dmake_max_jobs */ 2022 if (dmake_max_jobs_specified) { 2023 MBSTOWCS(wcs_buffer, "DMAKE_MAX_JOBS"); 2024 dmake_max_jobs = GETNAME(wcs_buffer, FIND_LENGTH); 2025 append_makeflags_string(dmake_max_jobs, &makeflags_string); 2026 append_makeflags_string(dmake_max_jobs, &makeflags_string_posix); 2027 } 2028 /* -m dmake_mode */ 2029 if (dmake_mode_specified) { 2030 MBSTOWCS(wcs_buffer, "DMAKE_MODE"); 2031 dmake_mode = GETNAME(wcs_buffer, FIND_LENGTH); 2032 append_makeflags_string(dmake_mode, &makeflags_string); 2033 append_makeflags_string(dmake_mode, &makeflags_string_posix); 2034 } 2035 /* -x dmake_compat_mode */ 2036 // if (dmake_compat_mode_specified) { 2037 // MBSTOWCS(wcs_buffer, "SUN_MAKE_COMPAT_MODE"); 2038 // dmake_compat_mode = GETNAME(wcs_buffer, FIND_LENGTH); 2039 // append_makeflags_string(dmake_compat_mode, &makeflags_string); 2040 // append_makeflags_string(dmake_compat_mode, &makeflags_string_posix); 2041 // } 2042 /* -x dmake_output_mode */ 2043 if (dmake_output_mode_specified) { 2044 MBSTOWCS(wcs_buffer, "DMAKE_OUTPUT_MODE"); 2045 dmake_output_mode = GETNAME(wcs_buffer, FIND_LENGTH); 2046 append_makeflags_string(dmake_output_mode, &makeflags_string); 2047 append_makeflags_string(dmake_output_mode, &makeflags_string_posix); 2048 } 2049 /* -o dmake_odir */ 2050 if (dmake_odir_specified) { 2051 MBSTOWCS(wcs_buffer, "DMAKE_ODIR"); 2052 dmake_odir = GETNAME(wcs_buffer, FIND_LENGTH); 2053 append_makeflags_string(dmake_odir, &makeflags_string); 2054 append_makeflags_string(dmake_odir, &makeflags_string_posix); 2055 } 2056 /* -M pmake_machinesfile */ 2057 if (pmake_machinesfile_specified) { 2058 MBSTOWCS(wcs_buffer, "PMAKE_MACHINESFILE"); 2059 pmake_machinesfile = GETNAME(wcs_buffer, FIND_LENGTH); 2060 append_makeflags_string(pmake_machinesfile, &makeflags_string); 2061 append_makeflags_string(pmake_machinesfile, &makeflags_string_posix); 2062 } 2063 /* -R */ 2064 if (pmake_cap_r_specified) { 2065 append_char((int) space_char, &makeflags_string); 2066 append_char((int) hyphen_char, &makeflags_string); 2067 append_char('R', &makeflags_string); 2068 append_char((int) space_char, &makeflags_string_posix); 2069 append_char((int) hyphen_char, &makeflags_string_posix); 2070 append_char('R', &makeflags_string_posix); 2071 } 2072 2073 /* 2074 * Make sure MAKEFLAGS is exported 2075 */ 2076 maybe_append_prop(makeflags, macro_prop)-> 2077 body.macro.exported = true; 2078 2079 if (makeflags_string.buffer.start[1] != (int) nul_char) { 2080 if (makeflags_string.buffer.start[1] != (int) space_char) { 2081 MBSTOWCS(wcs_buffer, "MFLAGS"); 2082 (void) SETVAR(GETNAME(wcs_buffer, FIND_LENGTH), 2083 GETNAME(makeflags_string.buffer.start, 2084 FIND_LENGTH), 2085 false); 2086 } else { 2087 MBSTOWCS(wcs_buffer, "MFLAGS"); 2088 (void) SETVAR(GETNAME(wcs_buffer, FIND_LENGTH), 2089 GETNAME(makeflags_string.buffer.start + 2, 2090 FIND_LENGTH), 2091 false); 2092 } 2093 } 2094 2095 /* 2096 * Add command line macro to POSIX makeflags_string 2097 */ 2098 if (makeflags_and_macro.start) { 2099 tmp_char = (char) space_char; 2100 cp = makeflags_and_macro.start; 2101 do { 2102 append_char(tmp_char, &makeflags_string_posix); 2103 } while ( tmp_char = *cp++ ); 2104 retmem_mb(makeflags_and_macro.start); 2105 } 2106 2107 /* 2108 * Now set the value of MAKEFLAGS macro in accordance 2109 * with current mode. 2110 */ 2111 macro = maybe_append_prop(makeflags, macro_prop); 2112 temp = (Boolean) macro->body.macro.read_only; 2113 macro->body.macro.read_only = false; 2114 if(posix || gnu_style) { 2115 makeflags_string_current = &makeflags_string_posix; 2116 } else { 2117 makeflags_string_current = &makeflags_string; 2118 } 2119 if (makeflags_string_current->buffer.start[1] == (int) nul_char) { 2120 makeflags_value_saved = 2121 GETNAME( makeflags_string_current->buffer.start + 1 2122 , FIND_LENGTH 2123 ); 2124 } else { 2125 if (makeflags_string_current->buffer.start[1] != (int) space_char) { 2126 makeflags_value_saved = 2127 GETNAME( makeflags_string_current->buffer.start 2128 , FIND_LENGTH 2129 ); 2130 } else { 2131 makeflags_value_saved = 2132 GETNAME( makeflags_string_current->buffer.start + 2 2133 , FIND_LENGTH 2134 ); 2135 } 2136 } 2137 (void) SETVAR( makeflags 2138 , makeflags_value_saved 2139 , false 2140 ); 2141 macro->body.macro.read_only = temp; 2142 2143 /* 2144 * Read command line "-f" arguments and ignore -c, g, j, K, M, m, O and o args. 2145 */ 2146 save_do_not_exec_rule = do_not_exec_rule; 2147 do_not_exec_rule = false; 2148 if (read_trace_level > 0) { 2149 trace_reader = true; 2150 } 2151 2152 for (i = 1; i < argc; i++) { 2153 if (argv[i] && 2154 (argv[i][0] == (int) hyphen_char) && 2155 (argv[i][1] == 'f') && 2156 (argv[i][2] == (int) nul_char)) { 2157 argv[i] = NULL; /* Remove -f */ 2158 if (i >= argc - 1) { 2159 fatal(gettext("No filename argument after -f flag")); 2160 } 2161 MBSTOWCS(wcs_buffer, argv[++i]); 2162 primary_makefile = GETNAME(wcs_buffer, FIND_LENGTH); 2163 (void) read_makefile(primary_makefile, true, true, true); 2164 argv[i] = NULL; /* Remove filename */ 2165 makefile_read = true; 2166 } else if (argv[i] && 2167 (argv[i][0] == (int) hyphen_char) && 2168 (argv[i][1] == 'c' || 2169 argv[i][1] == 'g' || 2170 argv[i][1] == 'j' || 2171 argv[i][1] == 'K' || 2172 argv[i][1] == 'M' || 2173 argv[i][1] == 'm' || 2174 argv[i][1] == 'O' || 2175 argv[i][1] == 'o') && 2176 (argv[i][2] == (int) nul_char)) { 2177 argv[i] = NULL; 2178 argv[++i] = NULL; 2179 } 2180 } 2181 2182 /* 2183 * If no command line "-f" args then look for "makefile", and then for 2184 * "Makefile" if "makefile" isn't found. 2185 */ 2186 if (!makefile_read) { 2187 (void) read_dir(dot, 2188 (wchar_t *) NULL, 2189 (Property) NULL, 2190 (wchar_t *) NULL); 2191 if (!posix) { 2192 if (makefile_name->stat.is_file) { 2193 if (Makefile->stat.is_file) { 2194 warning(gettext("Both `makefile' and `Makefile' exist")); 2195 } 2196 primary_makefile = makefile_name; 2197 makefile_read = read_makefile(makefile_name, 2198 false, 2199 false, 2200 true); 2201 } 2202 if (!makefile_read && 2203 Makefile->stat.is_file) { 2204 primary_makefile = Makefile; 2205 makefile_read = read_makefile(Makefile, 2206 false, 2207 false, 2208 true); 2209 } 2210 } else { 2211 2212 enum sccs_stat save_m_has_sccs = NO_SCCS; 2213 enum sccs_stat save_M_has_sccs = NO_SCCS; 2214 2215 if (makefile_name->stat.is_file) { 2216 if (Makefile->stat.is_file) { 2217 warning(gettext("Both `makefile' and `Makefile' exist")); 2218 } 2219 } 2220 if (makefile_name->stat.is_file) { 2221 if (makefile_name->stat.has_sccs == NO_SCCS) { 2222 primary_makefile = makefile_name; 2223 makefile_read = read_makefile(makefile_name, 2224 false, 2225 false, 2226 true); 2227 } else { 2228 save_m_has_sccs = makefile_name->stat.has_sccs; 2229 makefile_name->stat.has_sccs = NO_SCCS; 2230 primary_makefile = makefile_name; 2231 makefile_read = read_makefile(makefile_name, 2232 false, 2233 false, 2234 true); 2235 } 2236 } 2237 if (!makefile_read && 2238 Makefile->stat.is_file) { 2239 if (Makefile->stat.has_sccs == NO_SCCS) { 2240 primary_makefile = Makefile; 2241 makefile_read = read_makefile(Makefile, 2242 false, 2243 false, 2244 true); 2245 } else { 2246 save_M_has_sccs = Makefile->stat.has_sccs; 2247 Makefile->stat.has_sccs = NO_SCCS; 2248 primary_makefile = Makefile; 2249 makefile_read = read_makefile(Makefile, 2250 false, 2251 false, 2252 true); 2253 } 2254 } 2255 if (!makefile_read && 2256 makefile_name->stat.is_file) { 2257 makefile_name->stat.has_sccs = save_m_has_sccs; 2258 primary_makefile = makefile_name; 2259 makefile_read = read_makefile(makefile_name, 2260 false, 2261 false, 2262 true); 2263 } 2264 if (!makefile_read && 2265 Makefile->stat.is_file) { 2266 Makefile->stat.has_sccs = save_M_has_sccs; 2267 primary_makefile = Makefile; 2268 makefile_read = read_makefile(Makefile, 2269 false, 2270 false, 2271 true); 2272 } 2273 } 2274 } 2275 do_not_exec_rule = save_do_not_exec_rule; 2276 allrules_read = makefile_read; 2277 trace_reader = false; 2278 2279 /* 2280 * Now get current value of MAKEFLAGS and compare it with 2281 * the saved value we set before reading makefile. 2282 * If they are different then MAKEFLAGS is subsequently set by 2283 * makefile, just leave it there. Otherwise, if make mode 2284 * is changed by using .POSIX target in makefile we need 2285 * to correct MAKEFLAGS value. 2286 */ 2287 Name mf_val = getvar(makeflags); 2288 if( (posix != is_xpg4) 2289 && (!strcmp(mf_val->string_mb, makeflags_value_saved->string_mb))) 2290 { 2291 if (makeflags_string_posix.buffer.start[1] == (int) nul_char) { 2292 (void) SETVAR(makeflags, 2293 GETNAME(makeflags_string_posix.buffer.start + 1, 2294 FIND_LENGTH), 2295 false); 2296 } else { 2297 if (makeflags_string_posix.buffer.start[1] != (int) space_char) { 2298 (void) SETVAR(makeflags, 2299 GETNAME(makeflags_string_posix.buffer.start, 2300 FIND_LENGTH), 2301 false); 2302 } else { 2303 (void) SETVAR(makeflags, 2304 GETNAME(makeflags_string_posix.buffer.start + 2, 2305 FIND_LENGTH), 2306 false); 2307 } 2308 } 2309 } 2310 2311 if (makeflags_string.free_after_use) { 2312 retmem(makeflags_string.buffer.start); 2313 } 2314 if (makeflags_string_posix.free_after_use) { 2315 retmem(makeflags_string_posix.buffer.start); 2316 } 2317 makeflags_string.buffer.start = NULL; 2318 makeflags_string_posix.buffer.start = NULL; 2319 2320 if (posix) { 2321 /* 2322 * If the user did not redefine the ARFLAGS macro in the 2323 * default makefile (make.rules), then we'd like to 2324 * change the macro value of ARFLAGS to be in accordance 2325 * with "POSIX" requirements. 2326 */ 2327 MBSTOWCS(wcs_buffer, "ARFLAGS"); 2328 name = GETNAME(wcs_buffer, wcslen(wcs_buffer)); 2329 macro = get_prop(name->prop, macro_prop); 2330 if ((macro != NULL) && /* Maybe (macro == NULL) || ? */ 2331 (IS_EQUAL(macro->body.macro.value->string_mb, 2332 "rv"))) { 2333 MBSTOWCS(wcs_buffer, "-rv"); 2334 value = GETNAME(wcs_buffer, wcslen(wcs_buffer)); 2335 (void) SETVAR(name, 2336 value, 2337 false); 2338 } 2339 } 2340 2341 if (!posix && !svr4) { 2342 set_sgs_support(); 2343 } 2344 2345 2346 /* 2347 * Make sure KEEP_STATE is in the environment if KEEP_STATE is on. 2348 */ 2349 macro = get_prop(keep_state_name->prop, macro_prop); 2350 if ((macro != NULL) && 2351 macro->body.macro.exported) { 2352 keep_state = true; 2353 } 2354 if (keep_state) { 2355 if (macro == NULL) { 2356 macro = maybe_append_prop(keep_state_name, 2357 macro_prop); 2358 } 2359 macro->body.macro.exported = true; 2360 (void) SETVAR(keep_state_name, 2361 empty_name, 2362 false); 2363 2364 /* 2365 * Read state file 2366 */ 2367 2368 /* Before we read state, let's make sure we have 2369 ** right state file. 2370 */ 2371 /* just in case macro references are used in make_state file 2372 ** name, we better expand them at this stage using expand_value. 2373 */ 2374 INIT_STRING_FROM_STACK(dest, destbuffer); 2375 expand_value(make_state, &dest, false); 2376 2377 make_state = GETNAME(dest.buffer.start, FIND_LENGTH); 2378 2379 if(!stat(make_state->string_mb, &make_state_stat)) { 2380 if(!(make_state_stat.st_mode & S_IFREG) ) { 2381 /* copy the make_state structure to the other 2382 ** and then let make_state point to the new 2383 ** one. 2384 */ 2385 memcpy(&state_filename, make_state,sizeof(state_filename)); 2386 state_filename.string_mb = state_file_str_mb; 2387 /* Just a kludge to avoid two slashes back to back */ 2388 if((make_state->hash.length == 1)&& 2389 (make_state->string_mb[0] == '/')) { 2390 make_state->hash.length = 0; 2391 make_state->string_mb[0] = '\0'; 2392 } 2393 sprintf(state_file_str_mb,"%s%s", 2394 make_state->string_mb,"/.make.state"); 2395 make_state = &state_filename; 2396 /* adjust the length to reflect the appended string */ 2397 make_state->hash.length += 12; 2398 } 2399 } else { /* the file doesn't exist or no permission */ 2400 char tmp_path[MAXPATHLEN]; 2401 char *slashp; 2402 2403 if (slashp = strrchr(make_state->string_mb, '/')) { 2404 strncpy(tmp_path, make_state->string_mb, 2405 (slashp - make_state->string_mb)); 2406 tmp_path[slashp - make_state->string_mb]=0; 2407 if(strlen(tmp_path)) { 2408 if(stat(tmp_path, &make_state_stat)) { 2409 warning(gettext("directory %s for .KEEP_STATE_FILE does not exist"),tmp_path); 2410 } 2411 if (access(tmp_path, F_OK) != 0) { 2412 warning(gettext("can't access dir %s"),tmp_path); 2413 } 2414 } 2415 } 2416 } 2417 if (report_dependencies_level != 1) { 2418 Makefile_type makefile_type_temp = makefile_type; 2419 makefile_type = reading_statefile; 2420 if (read_trace_level > 1) { 2421 trace_reader = true; 2422 } 2423 (void) read_simple_file(make_state, 2424 false, 2425 false, 2426 false, 2427 false, 2428 false, 2429 true); 2430 trace_reader = false; 2431 makefile_type = makefile_type_temp; 2432 } 2433 } 2434 } 2435 2436 /* 2437 * Scan the argv for options and "=" type args and make them readonly. 2438 */ 2439 static void 2440 enter_argv_values(int argc, char *argv[], ASCII_Dyn_Array *makeflags_and_macro) 2441 { 2442 char *cp; 2443 int i; 2444 int length; 2445 Name name; 2446 int opt_separator = argc; 2447 char tmp_char; 2448 wchar_t *tmp_wcs_buffer; 2449 Name value; 2450 Boolean append = false; 2451 Property macro; 2452 struct stat statbuf; 2453 2454 2455 /* Read argv options and "=" type args and make them readonly. */ 2456 makefile_type = reading_nothing; 2457 for (i = 1; i < argc; ++i) { 2458 append = false; 2459 if (argv[i] == NULL) { 2460 continue; 2461 } else if (((argv[i][0] == '-') && (argv[i][1] == '-')) || 2462 ((argv[i][0] == (int) ' ') && 2463 (argv[i][1] == (int) '-') && 2464 (argv[i][2] == (int) ' ') && 2465 (argv[i][3] == (int) '-'))) { 2466 argv[i] = NULL; 2467 opt_separator = i; 2468 continue; 2469 } else if ((i < opt_separator) && (argv[i][0] == (int) hyphen_char)) { 2470 switch (parse_command_option(argv[i][1])) { 2471 case 1: /* -f seen */ 2472 ++i; 2473 continue; 2474 case 2: /* -c seen */ 2475 if (argv[i+1] == NULL) { 2476 fatal(gettext("No dmake rcfile argument after -c flag")); 2477 } 2478 MBSTOWCS(wcs_buffer, "DMAKE_RCFILE"); 2479 name = GETNAME(wcs_buffer, FIND_LENGTH); 2480 break; 2481 case 4: /* -g seen */ 2482 if (argv[i+1] == NULL) { 2483 fatal(gettext("No dmake group argument after -g flag")); 2484 } 2485 MBSTOWCS(wcs_buffer, "DMAKE_GROUP"); 2486 name = GETNAME(wcs_buffer, FIND_LENGTH); 2487 break; 2488 case 8: /* -j seen */ 2489 if (argv[i+1] == NULL) { 2490 fatal(gettext("No dmake max jobs argument after -j flag")); 2491 } 2492 MBSTOWCS(wcs_buffer, "DMAKE_MAX_JOBS"); 2493 name = GETNAME(wcs_buffer, FIND_LENGTH); 2494 break; 2495 case 16: /* -M seen */ 2496 if (argv[i+1] == NULL) { 2497 fatal(gettext("No pmake machinesfile argument after -M flag")); 2498 } 2499 MBSTOWCS(wcs_buffer, "PMAKE_MACHINESFILE"); 2500 name = GETNAME(wcs_buffer, FIND_LENGTH); 2501 break; 2502 case 32: /* -m seen */ 2503 if (argv[i+1] == NULL) { 2504 fatal(gettext("No dmake mode argument after -m flag")); 2505 } 2506 MBSTOWCS(wcs_buffer, "DMAKE_MODE"); 2507 name = GETNAME(wcs_buffer, FIND_LENGTH); 2508 break; 2509 case 256: /* -K seen */ 2510 if (argv[i+1] == NULL) { 2511 fatal(gettext("No makestate filename argument after -K flag")); 2512 } 2513 MBSTOWCS(wcs_buffer, argv[i+1]); 2514 make_state = GETNAME(wcs_buffer, FIND_LENGTH); 2515 keep_state = true; 2516 argv[i] = NULL; 2517 argv[i+1] = NULL; 2518 continue; 2519 case 512: /* -o seen */ 2520 if (argv[i+1] == NULL) { 2521 fatal(gettext("No dmake output dir argument after -o flag")); 2522 } 2523 MBSTOWCS(wcs_buffer, "DMAKE_ODIR"); 2524 name = GETNAME(wcs_buffer, FIND_LENGTH); 2525 break; 2526 case 1024: /* -x seen */ 2527 if (argv[i+1] == NULL) { 2528 fatal(gettext("No argument after -x flag")); 2529 } 2530 length = strlen( "SUN_MAKE_COMPAT_MODE="); 2531 if (strncmp(argv[i+1], "SUN_MAKE_COMPAT_MODE=", length) == 0) { 2532 argv[i+1] = &argv[i+1][length]; 2533 MBSTOWCS(wcs_buffer, "SUN_MAKE_COMPAT_MODE"); 2534 name = GETNAME(wcs_buffer, FIND_LENGTH); 2535 dmake_compat_mode_specified = dmake_add_mode_specified; 2536 break; 2537 } 2538 length = strlen( "DMAKE_OUTPUT_MODE="); 2539 if (strncmp(argv[i+1], "DMAKE_OUTPUT_MODE=", length) == 0) { 2540 argv[i+1] = &argv[i+1][length]; 2541 MBSTOWCS(wcs_buffer, "DMAKE_OUTPUT_MODE"); 2542 name = GETNAME(wcs_buffer, FIND_LENGTH); 2543 dmake_output_mode_specified = dmake_add_mode_specified; 2544 } else { 2545 warning(gettext("Unknown argument `%s' after -x flag (ignored)"), 2546 argv[i+1]); 2547 argv[i] = argv[i + 1] = NULL; 2548 continue; 2549 } 2550 break; 2551 case 2048: /* -C seen */ 2552 /* 2553 * The chdir() will have been performed 2554 * in read_command_options(). 2555 * Just set DMAKE_CDIR here. 2556 */ 2557 if (argv[i + 1] == NULL) { 2558 fatal(gettext( 2559 "No argument after -C flag")); 2560 } 2561 MBSTOWCS(wcs_buffer, "DMAKE_CDIR"); 2562 name = GETNAME(wcs_buffer, FIND_LENGTH); 2563 break; 2564 default: /* Shouldn't reach here */ 2565 argv[i] = NULL; 2566 continue; 2567 } 2568 argv[i] = NULL; 2569 if (i == (argc - 1)) { 2570 break; 2571 } 2572 if ((length = strlen(argv[i+1])) >= MAXPATHLEN) { 2573 tmp_wcs_buffer = ALLOC_WC(length + 1); 2574 (void) mbstowcs(tmp_wcs_buffer, argv[i+1], length + 1); 2575 value = GETNAME(tmp_wcs_buffer, FIND_LENGTH); 2576 retmem(tmp_wcs_buffer); 2577 } else { 2578 MBSTOWCS(wcs_buffer, argv[i+1]); 2579 value = GETNAME(wcs_buffer, FIND_LENGTH); 2580 } 2581 argv[i+1] = NULL; 2582 } else if ((cp = strchr(argv[i], (int) equal_char)) != NULL) { 2583 /* 2584 * Combine all macro in dynamic array 2585 */ 2586 if(*(cp-1) == (int) plus_char) 2587 { 2588 if(isspace(*(cp-2))) { 2589 append = true; 2590 cp--; 2591 } 2592 } 2593 if(!append) 2594 append_or_replace_macro_in_dyn_array(makeflags_and_macro, argv[i]); 2595 2596 while (isspace(*(cp-1))) { 2597 cp--; 2598 } 2599 tmp_char = *cp; 2600 *cp = (int) nul_char; 2601 MBSTOWCS(wcs_buffer, argv[i]); 2602 *cp = tmp_char; 2603 name = GETNAME(wcs_buffer, wcslen(wcs_buffer)); 2604 while (*cp != (int) equal_char) { 2605 cp++; 2606 } 2607 cp++; 2608 while (isspace(*cp) && (*cp != (int) nul_char)) { 2609 cp++; 2610 } 2611 if ((length = strlen(cp)) >= MAXPATHLEN) { 2612 tmp_wcs_buffer = ALLOC_WC(length + 1); 2613 (void) mbstowcs(tmp_wcs_buffer, cp, length + 1); 2614 value = GETNAME(tmp_wcs_buffer, FIND_LENGTH); 2615 retmem(tmp_wcs_buffer); 2616 } else { 2617 MBSTOWCS(wcs_buffer, cp); 2618 value = GETNAME(wcs_buffer, FIND_LENGTH); 2619 } 2620 argv[i] = NULL; 2621 } else { 2622 /* Illegal MAKEFLAGS argument */ 2623 continue; 2624 } 2625 if(append) { 2626 setvar_append(name, value); 2627 append = false; 2628 } else { 2629 macro = maybe_append_prop(name, macro_prop); 2630 macro->body.macro.exported = true; 2631 SETVAR(name, value, false)->body.macro.read_only = true; 2632 } 2633 } 2634 } 2635 2636 /* 2637 * Append the DMake option and value to the MAKEFLAGS string. 2638 */ 2639 static void 2640 append_makeflags_string(Name name, String makeflags_string) 2641 { 2642 const char *option; 2643 2644 if (strcmp(name->string_mb, "DMAKE_GROUP") == 0) { 2645 option = " -g "; 2646 } else if (strcmp(name->string_mb, "DMAKE_MAX_JOBS") == 0) { 2647 option = " -j "; 2648 } else if (strcmp(name->string_mb, "DMAKE_MODE") == 0) { 2649 option = " -m "; 2650 } else if (strcmp(name->string_mb, "DMAKE_ODIR") == 0) { 2651 option = " -o "; 2652 } else if (strcmp(name->string_mb, "DMAKE_RCFILE") == 0) { 2653 option = " -c "; 2654 } else if (strcmp(name->string_mb, "PMAKE_MACHINESFILE") == 0) { 2655 option = " -M "; 2656 } else if (strcmp(name->string_mb, "DMAKE_OUTPUT_MODE") == 0) { 2657 option = " -x DMAKE_OUTPUT_MODE="; 2658 } else if (strcmp(name->string_mb, "SUN_MAKE_COMPAT_MODE") == 0) { 2659 option = " -x SUN_MAKE_COMPAT_MODE="; 2660 } else { 2661 fatal(gettext("Internal error: name not recognized in append_makeflags_string()")); 2662 } 2663 Property prop = maybe_append_prop(name, macro_prop); 2664 if( prop == 0 || prop->body.macro.value == 0 || 2665 prop->body.macro.value->string_mb == 0 ) { 2666 return; 2667 } 2668 char mbs_value[MAXPATHLEN + 100]; 2669 strcpy(mbs_value, option); 2670 strcat(mbs_value, prop->body.macro.value->string_mb); 2671 MBSTOWCS(wcs_buffer, mbs_value); 2672 append_string(wcs_buffer, makeflags_string, FIND_LENGTH); 2673 } 2674 2675 /* 2676 * read_environment(read_only) 2677 * 2678 * This routine reads the process environment when make starts and enters 2679 * it as make macros. The environment variable SHELL is ignored. 2680 * 2681 * Parameters: 2682 * read_only Should we make env vars read only? 2683 * 2684 * Global variables used: 2685 * report_pwd Set if this make was started by other make 2686 */ 2687 static void 2688 read_environment(Boolean read_only) 2689 { 2690 char **environment; 2691 int length; 2692 wchar_t *tmp_wcs_buffer; 2693 Boolean alloced_tmp_wcs_buffer = false; 2694 wchar_t *name; 2695 wchar_t *value; 2696 Name macro; 2697 Property val; 2698 Boolean read_only_saved; 2699 2700 reading_environment = true; 2701 environment = environ; 2702 for (; *environment; environment++) { 2703 read_only_saved = read_only; 2704 if ((length = strlen(*environment)) >= MAXPATHLEN) { 2705 tmp_wcs_buffer = ALLOC_WC(length + 1); 2706 alloced_tmp_wcs_buffer = true; 2707 (void) mbstowcs(tmp_wcs_buffer, *environment, length + 1); 2708 name = tmp_wcs_buffer; 2709 } else { 2710 MBSTOWCS(wcs_buffer, *environment); 2711 name = wcs_buffer; 2712 } 2713 value = (wchar_t *) wcschr(name, (int) equal_char); 2714 2715 /* 2716 * Looks like there's a bug in the system, but sometimes 2717 * you can get blank lines in *environment. 2718 */ 2719 if (!value) { 2720 continue; 2721 } 2722 MBSTOWCS(wcs_buffer2, "SHELL="); 2723 if (IS_WEQUALN(name, wcs_buffer2, wcslen(wcs_buffer2))) { 2724 continue; 2725 } 2726 MBSTOWCS(wcs_buffer2, "MAKEFLAGS="); 2727 if (IS_WEQUALN(name, wcs_buffer2, wcslen(wcs_buffer2))) { 2728 report_pwd = true; 2729 /* 2730 * In POSIX mode we do not want MAKEFLAGS to be readonly. 2731 * If the MAKEFLAGS macro is subsequently set by the makefile, 2732 * it replaces the MAKEFLAGS variable currently found in the 2733 * environment. 2734 * See Assertion 50 in section 6.2.5.3 of standard P1003.3.2/D8. 2735 */ 2736 if(posix) { 2737 read_only_saved = false; 2738 } 2739 } 2740 2741 /* 2742 * We ignore SUNPRO_DEPENDENCIES. This environment variable is 2743 * set by make and read by cpp which then writes info to 2744 * .make.dependency.xxx. When make is invoked by another make 2745 * (recursive make), we don't want to read this because then 2746 * the child make will end up writing to the parent 2747 * directory's .make.state and clobbering them. 2748 */ 2749 MBSTOWCS(wcs_buffer2, "SUNPRO_DEPENDENCIES"); 2750 if (IS_WEQUALN(name, wcs_buffer2, wcslen(wcs_buffer2))) { 2751 continue; 2752 } 2753 2754 macro = GETNAME(name, value - name); 2755 maybe_append_prop(macro, macro_prop)->body.macro.exported = 2756 true; 2757 if ((value == NULL) || ((value + 1)[0] == (int) nul_char)) { 2758 val = setvar_daemon(macro, 2759 (Name) NULL, 2760 false, no_daemon, false, debug_level); 2761 } else { 2762 val = setvar_daemon(macro, 2763 GETNAME(value + 1, FIND_LENGTH), 2764 false, no_daemon, false, debug_level); 2765 } 2766 val->body.macro.read_only = read_only_saved; 2767 if (alloced_tmp_wcs_buffer) { 2768 retmem(tmp_wcs_buffer); 2769 alloced_tmp_wcs_buffer = false; 2770 } 2771 } 2772 reading_environment = false; 2773 } 2774 2775 /* 2776 * read_makefile(makefile, complain, must_exist, report_file) 2777 * 2778 * Read one makefile and check the result 2779 * 2780 * Return value: 2781 * false is the read failed 2782 * 2783 * Parameters: 2784 * makefile The file to read 2785 * complain Passed thru to read_simple_file() 2786 * must_exist Passed thru to read_simple_file() 2787 * report_file Passed thru to read_simple_file() 2788 * 2789 * Global variables used: 2790 * makefile_type Set to indicate we are reading main file 2791 * recursion_level Initialized 2792 */ 2793 static Boolean 2794 read_makefile(Name makefile, Boolean complain, Boolean must_exist, Boolean report_file) 2795 { 2796 Boolean b; 2797 2798 makefile_type = reading_makefile; 2799 recursion_level = 0; 2800 reading_dependencies = true; 2801 b = read_simple_file(makefile, true, true, complain, 2802 must_exist, report_file, false); 2803 reading_dependencies = false; 2804 return b; 2805 } 2806 2807 /* 2808 * make_targets(argc, argv, parallel_flag) 2809 * 2810 * Call doname on the specified targets 2811 * 2812 * Parameters: 2813 * argc You know what this is 2814 * argv You know what this is 2815 * parallel_flag True if building in parallel 2816 * 2817 * Global variables used: 2818 * build_failed_seen Used to generated message after failed -k 2819 * commands_done Used to generate message "Up to date" 2820 * default_target_to_build First proper target in makefile 2821 * init The Name ".INIT", use to run command 2822 * parallel Global parallel building flag 2823 * quest make -q, suppresses messages 2824 * recursion_level Initialized, used for tracing 2825 * report_dependencies make -P, regroves whole process 2826 */ 2827 static void 2828 make_targets(int argc, char **argv, Boolean parallel_flag) 2829 { 2830 int i; 2831 char *cp; 2832 Doname result; 2833 Boolean target_to_make_found = false; 2834 2835 (void) doname(init, true, true); 2836 recursion_level = 1; 2837 parallel = parallel_flag; 2838 /* 2839 * make remaining args 2840 */ 2841 /* 2842 if ((report_dependencies_level == 0) && parallel) { 2843 */ 2844 if (parallel) { 2845 /* 2846 * If building targets in parallel, start all of the 2847 * remaining args to build in parallel. 2848 */ 2849 for (i = 1; i < argc; i++) { 2850 if ((cp = argv[i]) != NULL) { 2851 commands_done = false; 2852 if ((cp[0] == (int) period_char) && 2853 (cp[1] == (int) slash_char)) { 2854 cp += 2; 2855 } 2856 if((cp[0] == (int) ' ') && 2857 (cp[1] == (int) '-') && 2858 (cp[2] == (int) ' ') && 2859 (cp[3] == (int) '-')) { 2860 argv[i] = NULL; 2861 continue; 2862 } 2863 MBSTOWCS(wcs_buffer, cp); 2864 //default_target_to_build = GETNAME(wcs_buffer, 2865 // FIND_LENGTH); 2866 default_target_to_build = normalize_name(wcs_buffer, 2867 wcslen(wcs_buffer)); 2868 if (default_target_to_build == wait_name) { 2869 if (parallel_process_cnt > 0) { 2870 finish_running(); 2871 } 2872 continue; 2873 } 2874 top_level_target = get_wstring(default_target_to_build->string_mb); 2875 /* 2876 * If we can't execute the current target in 2877 * parallel, hold off the target processing 2878 * to preserve the order of the targets as they appeared 2879 * in command line. 2880 */ 2881 if (!parallel_ok(default_target_to_build, false) 2882 && parallel_process_cnt > 0) { 2883 finish_running(); 2884 } 2885 result = doname_check(default_target_to_build, 2886 true, 2887 false, 2888 false); 2889 gather_recursive_deps(); 2890 if (/* !commands_done && */ 2891 (result == build_ok) && 2892 !quest && 2893 (report_dependencies_level == 0) /* && 2894 (exists(default_target_to_build) > file_doesnt_exist) */) { 2895 if (posix) { 2896 if (!commands_done) { 2897 (void) printf(gettext("`%s' is updated.\n"), 2898 default_target_to_build->string_mb); 2899 } else { 2900 if (no_action_was_taken) { 2901 (void) printf(gettext("`%s': no action was taken.\n"), 2902 default_target_to_build->string_mb); 2903 } 2904 } 2905 } else { 2906 default_target_to_build->stat.time = file_no_time; 2907 if (!commands_done && 2908 (exists(default_target_to_build) > file_doesnt_exist)) { 2909 (void) printf(gettext("`%s' is up to date.\n"), 2910 default_target_to_build->string_mb); 2911 } 2912 } 2913 } 2914 } 2915 } 2916 /* Now wait for all of the targets to finish running */ 2917 finish_running(); 2918 // setjmp(jmpbuffer); 2919 2920 } 2921 for (i = 1; i < argc; i++) { 2922 if ((cp = argv[i]) != NULL) { 2923 target_to_make_found = true; 2924 if ((cp[0] == (int) period_char) && 2925 (cp[1] == (int) slash_char)) { 2926 cp += 2; 2927 } 2928 if((cp[0] == (int) ' ') && 2929 (cp[1] == (int) '-') && 2930 (cp[2] == (int) ' ') && 2931 (cp[3] == (int) '-')) { 2932 argv[i] = NULL; 2933 continue; 2934 } 2935 MBSTOWCS(wcs_buffer, cp); 2936 default_target_to_build = normalize_name(wcs_buffer, wcslen(wcs_buffer)); 2937 top_level_target = get_wstring(default_target_to_build->string_mb); 2938 report_recursion(default_target_to_build); 2939 commands_done = false; 2940 if (parallel) { 2941 result = (Doname) default_target_to_build->state; 2942 } else { 2943 result = doname_check(default_target_to_build, 2944 true, 2945 false, 2946 false); 2947 } 2948 gather_recursive_deps(); 2949 if (build_failed_seen) { 2950 build_failed_ever_seen = true; 2951 warning(gettext("Target `%s' not remade because of errors"), 2952 default_target_to_build->string_mb); 2953 } 2954 build_failed_seen = false; 2955 if (report_dependencies_level > 0) { 2956 print_dependencies(default_target_to_build, 2957 get_prop(default_target_to_build->prop, 2958 line_prop)); 2959 } 2960 default_target_to_build->stat.time = 2961 file_no_time; 2962 if (default_target_to_build->colon_splits > 0) { 2963 default_target_to_build->state = 2964 build_dont_know; 2965 } 2966 if (!parallel && 2967 /* !commands_done && */ 2968 (result == build_ok) && 2969 !quest && 2970 (report_dependencies_level == 0) /* && 2971 (exists(default_target_to_build) > file_doesnt_exist) */) { 2972 if (posix) { 2973 if (!commands_done) { 2974 (void) printf(gettext("`%s' is updated.\n"), 2975 default_target_to_build->string_mb); 2976 } else { 2977 if (no_action_was_taken) { 2978 (void) printf(gettext("`%s': no action was taken.\n"), 2979 default_target_to_build->string_mb); 2980 } 2981 } 2982 } else { 2983 if (!commands_done && 2984 (exists(default_target_to_build) > file_doesnt_exist)) { 2985 (void) printf(gettext("`%s' is up to date.\n"), 2986 default_target_to_build->string_mb); 2987 } 2988 } 2989 } 2990 } 2991 } 2992 2993 /* 2994 * If no file arguments have been encountered, 2995 * make the first name encountered that doesnt start with a dot 2996 */ 2997 if (!target_to_make_found) { 2998 if (default_target_to_build == NULL) { 2999 fatal(gettext("No arguments to build")); 3000 } 3001 commands_done = false; 3002 top_level_target = get_wstring(default_target_to_build->string_mb); 3003 report_recursion(default_target_to_build); 3004 3005 3006 if (getenv("SPRO_EXPAND_ERRORS")){ 3007 (void) printf("::(%s)\n", 3008 default_target_to_build->string_mb); 3009 } 3010 3011 3012 result = doname_parallel(default_target_to_build, true, false); 3013 gather_recursive_deps(); 3014 if (build_failed_seen) { 3015 build_failed_ever_seen = true; 3016 warning(gettext("Target `%s' not remade because of errors"), 3017 default_target_to_build->string_mb); 3018 } 3019 build_failed_seen = false; 3020 if (report_dependencies_level > 0) { 3021 print_dependencies(default_target_to_build, 3022 get_prop(default_target_to_build-> 3023 prop, 3024 line_prop)); 3025 } 3026 default_target_to_build->stat.time = file_no_time; 3027 if (default_target_to_build->colon_splits > 0) { 3028 default_target_to_build->state = build_dont_know; 3029 } 3030 if (/* !commands_done && */ 3031 (result == build_ok) && 3032 !quest && 3033 (report_dependencies_level == 0) /* && 3034 (exists(default_target_to_build) > file_doesnt_exist) */) { 3035 if (posix) { 3036 if (!commands_done) { 3037 (void) printf(gettext("`%s' is updated.\n"), 3038 default_target_to_build->string_mb); 3039 } else { 3040 if (no_action_was_taken) { 3041 (void) printf(gettext("`%s': no action was taken.\n"), 3042 default_target_to_build->string_mb); 3043 } 3044 } 3045 } else { 3046 if (!commands_done && 3047 (exists(default_target_to_build) > file_doesnt_exist)) { 3048 (void) printf(gettext("`%s' is up to date.\n"), 3049 default_target_to_build->string_mb); 3050 } 3051 } 3052 } 3053 } 3054 } 3055 3056 /* 3057 * report_recursion(target) 3058 * 3059 * If this is a recursive make and the parent make has KEEP_STATE on 3060 * this routine reports the dependency to the parent make 3061 * 3062 * Parameters: 3063 * target Target to report 3064 * 3065 * Global variables used: 3066 * makefiles_used List of makefiles read 3067 * recursive_name The Name ".RECURSIVE", printed 3068 * report_dependency dwight 3069 */ 3070 static void 3071 report_recursion(Name target) 3072 { 3073 FILE *report_file = get_report_file(); 3074 3075 if ((report_file == NULL) || (report_file == (FILE*)-1)) { 3076 return; 3077 } 3078 if (primary_makefile == NULL) { 3079 /* 3080 * This can happen when there is no makefile and 3081 * only implicit rules are being used. 3082 */ 3083 return; 3084 } 3085 (void) fprintf(report_file, 3086 "%s: %s ", 3087 get_target_being_reported_for(), 3088 recursive_name->string_mb); 3089 report_dependency(get_current_path()); 3090 report_dependency(target->string_mb); 3091 report_dependency(primary_makefile->string_mb); 3092 (void) fprintf(report_file, "\n"); 3093 } 3094 3095 /* Next function "append_or_replace_macro_in_dyn_array" must be in "misc.cc". */ 3096 /* NIKMOL */ 3097 extern void 3098 append_or_replace_macro_in_dyn_array(ASCII_Dyn_Array *Ar, char *macro) 3099 { 3100 char *cp0; /* work pointer in macro */ 3101 char *cp1; /* work pointer in array */ 3102 char *cp2; /* work pointer in array */ 3103 char *cp3; /* work pointer in array */ 3104 char *name; /* macro name */ 3105 char *value; /* macro value */ 3106 int len_array; 3107 int len_macro; 3108 3109 char * esc_value = NULL; 3110 int esc_len; 3111 3112 if (!(len_macro = strlen(macro))) return; 3113 name = macro; 3114 while (isspace(*(name))) { 3115 name++; 3116 } 3117 if (!(value = strchr(name, (int) equal_char))) { 3118 /* no '=' in macro */ 3119 goto ERROR_MACRO; 3120 } 3121 cp0 = value; 3122 value++; 3123 while (isspace(*(value))) { 3124 value++; 3125 } 3126 while (isspace(*(cp0-1))) { 3127 cp0--; 3128 } 3129 if (cp0 <= name) goto ERROR_MACRO; /* no name */ 3130 if (!(Ar->size)) goto ALLOC_ARRAY; 3131 cp1 = Ar->start; 3132 3133 LOOK_FOR_NAME: 3134 if (!(cp1 = strchr(cp1, name[0]))) goto APPEND_MACRO; 3135 if (!(cp2 = strchr(cp1, (int) equal_char))) goto APPEND_MACRO; 3136 if (strncmp(cp1, name, (size_t)(cp0-name))) { 3137 /* another name */ 3138 cp1++; 3139 goto LOOK_FOR_NAME; 3140 } 3141 if (cp1 != Ar->start) { 3142 if (!isspace(*(cp1-1))) { 3143 /* another name */ 3144 cp1++; 3145 goto LOOK_FOR_NAME; 3146 } 3147 } 3148 for (cp3 = cp1 + (cp0-name); cp3 < cp2; cp3++) { 3149 if (isspace(*cp3)) continue; 3150 /* else: another name */ 3151 cp1++; 3152 goto LOOK_FOR_NAME; 3153 } 3154 /* Look for the next macro name in array */ 3155 cp3 = cp2+1; 3156 if (*cp3 != (int) doublequote_char) { 3157 /* internal error */ 3158 goto ERROR_MACRO; 3159 } 3160 if (!(cp3 = strchr(cp3+1, (int) doublequote_char))) { 3161 /* internal error */ 3162 goto ERROR_MACRO; 3163 } 3164 cp3++; 3165 while (isspace(*cp3)) { 3166 cp3++; 3167 } 3168 3169 cp2 = cp1; /* remove old macro */ 3170 if ((*cp3) && (cp3 < Ar->start + Ar->size)) { 3171 for (; cp3 < Ar->start + Ar->size; cp3++) { 3172 *cp2++ = *cp3; 3173 } 3174 } 3175 for (; cp2 < Ar->start + Ar->size; cp2++) { 3176 *cp2 = 0; 3177 } 3178 if (*cp1) { 3179 /* check next name */ 3180 goto LOOK_FOR_NAME; 3181 } 3182 goto APPEND_MACRO; 3183 3184 ALLOC_ARRAY: 3185 if (Ar->size) { 3186 cp1 = Ar->start; 3187 } else { 3188 cp1 = 0; 3189 } 3190 Ar->size += 128; 3191 Ar->start = getmem(Ar->size); 3192 for (len_array=0; len_array < Ar->size; len_array++) { 3193 Ar->start[len_array] = 0; 3194 } 3195 if (cp1) { 3196 strcpy(Ar->start, cp1); 3197 retmem((wchar_t *) cp1); 3198 } 3199 3200 APPEND_MACRO: 3201 len_array = strlen(Ar->start); 3202 esc_value = (char*)malloc(strlen(value)*2 + 1); 3203 quote_str(value, esc_value); 3204 esc_len = strlen(esc_value) - strlen(value); 3205 if (len_array + len_macro + esc_len + 5 >= Ar->size) goto ALLOC_ARRAY; 3206 strcat(Ar->start, " "); 3207 strncat(Ar->start, name, cp0-name); 3208 strcat(Ar->start, "="); 3209 strncat(Ar->start, esc_value, strlen(esc_value)); 3210 free(esc_value); 3211 return; 3212 ERROR_MACRO: 3213 /* Macro without '=' or with invalid left/right part */ 3214 return; 3215 } 3216 3217 static void 3218 report_dir_enter_leave(Boolean entering) 3219 { 3220 char rcwd[MAXPATHLEN]; 3221 static char * mlev = NULL; 3222 char * make_level_str = NULL; 3223 int make_level_val = 0; 3224 3225 make_level_str = getenv("MAKELEVEL"); 3226 if(make_level_str) { 3227 make_level_val = atoi(make_level_str); 3228 } 3229 if(mlev == NULL) { 3230 mlev = (char*) malloc(MAXPATHLEN); 3231 } 3232 if(entering) { 3233 sprintf(mlev, "MAKELEVEL=%d", make_level_val + 1); 3234 } else { 3235 make_level_val--; 3236 sprintf(mlev, "MAKELEVEL=%d", make_level_val); 3237 } 3238 putenv(mlev); 3239 3240 if(report_cwd) { 3241 if(make_level_val <= 0) { 3242 if(entering) { 3243 sprintf(rcwd, 3244 gettext("%s: Entering directory `%s'\n"), 3245 getprogname(), 3246 get_current_path()); 3247 } else { 3248 sprintf(rcwd, 3249 gettext("%s: Leaving directory `%s'\n"), 3250 getprogname(), 3251 get_current_path()); 3252 } 3253 } else { 3254 if(entering) { 3255 sprintf(rcwd, 3256 gettext("%s[%d]: Entering directory `%s'\n"), 3257 getprogname(), 3258 make_level_val, get_current_path()); 3259 } else { 3260 sprintf(rcwd, 3261 gettext("%s[%d]: Leaving directory `%s'\n"), 3262 getprogname(), 3263 make_level_val, get_current_path()); 3264 } 3265 } 3266 printf("%s", rcwd); 3267 } 3268 } 3269