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 2005 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 /* 27 * misc.cc 28 * 29 * This file contains various unclassified routines. Some main groups: 30 * getname 31 * Memory allocation 32 * String handling 33 * Property handling 34 * Error message handling 35 * Make internal state dumping 36 * main routine support 37 */ 38 39 /* 40 * Included files 41 */ 42 #include <errno.h> 43 #include <mk/defs.h> 44 #include <mksh/macro.h> /* SETVAR() */ 45 #include <mksh/misc.h> /* enable_interrupt() */ 46 #include <stdarg.h> /* va_list, va_start(), va_end() */ 47 #include <vroot/report.h> /* SUNPRO_DEPENDENCIES */ 48 49 #if defined(HP_UX) || defined(linux) 50 #include <unistd.h> 51 #endif 52 53 #ifdef TEAMWARE_MAKE_CMN 54 #define MAXJOBS_ADJUST_RFE4694000 55 56 #ifdef MAXJOBS_ADJUST_RFE4694000 57 extern void job_adjust_fini(); 58 #endif /* MAXJOBS_ADJUST_RFE4694000 */ 59 #endif /* TEAMWARE_MAKE_CMN */ 60 61 #if defined(linux) 62 #include <time.h> /* localtime() */ 63 #endif 64 65 /* 66 * Defined macros 67 */ 68 69 /* 70 * typedefs & structs 71 */ 72 73 /* 74 * Static variables 75 */ 76 77 /* 78 * File table of contents 79 */ 80 static void print_rule(register Name target); 81 static void print_target_n_deps(register Name target); 82 83 /***************************************** 84 * 85 * getname 86 */ 87 88 /***************************************** 89 * 90 * Memory allocation 91 */ 92 93 /* 94 * free_chain() 95 * 96 * frees a chain of Name_vector's 97 * 98 * Parameters: 99 * ptr Pointer to the first element in the chain 100 * to be freed. 101 * 102 * Global variables used: 103 */ 104 void 105 free_chain(Name_vector ptr) 106 { 107 if (ptr != NULL) { 108 if (ptr->next != NULL) { 109 free_chain(ptr->next); 110 } 111 free((char *) ptr); 112 } 113 } 114 115 /***************************************** 116 * 117 * String manipulation 118 */ 119 120 /***************************************** 121 * 122 * Nameblock property handling 123 */ 124 125 /***************************************** 126 * 127 * Error message handling 128 */ 129 130 /* 131 * fatal(format, args...) 132 * 133 * Print a message and die 134 * 135 * Parameters: 136 * format printf type format string 137 * args Arguments to match the format 138 * 139 * Global variables used: 140 * fatal_in_progress Indicates if this is a recursive call 141 * parallel_process_cnt Do we need to wait for anything? 142 * report_pwd Should we report the current path? 143 */ 144 /*VARARGS*/ 145 void 146 fatal(char * message, ...) 147 { 148 va_list args; 149 150 va_start(args, message); 151 (void) fflush(stdout); 152 #ifdef DISTRIBUTED 153 (void) fprintf(stderr, catgets(catd, 1, 262, "dmake: Fatal error: ")); 154 #else 155 (void) fprintf(stderr, catgets(catd, 1, 263, "make: Fatal error: ")); 156 #endif 157 (void) vfprintf(stderr, message, args); 158 (void) fprintf(stderr, "\n"); 159 va_end(args); 160 if (report_pwd) { 161 (void) fprintf(stderr, 162 catgets(catd, 1, 156, "Current working directory %s\n"), 163 get_current_path()); 164 } 165 (void) fflush(stderr); 166 if (fatal_in_progress) { 167 #if defined(SUN5_0) || defined(HP_UX) || defined(linux) 168 exit_status = 1; 169 #endif 170 exit(1); 171 } 172 fatal_in_progress = true; 173 #ifdef TEAMWARE_MAKE_CMN 174 /* Let all parallel children finish */ 175 if ((dmake_mode_type == parallel_mode) && 176 (parallel_process_cnt > 0)) { 177 (void) fprintf(stderr, 178 catgets(catd, 1, 157, "Waiting for %d %s to finish\n"), 179 parallel_process_cnt, 180 parallel_process_cnt == 1 ? 181 catgets(catd, 1, 158, "job") : catgets(catd, 1, 159, "jobs")); 182 (void) fflush(stderr); 183 } 184 185 while (parallel_process_cnt > 0) { 186 #ifdef DISTRIBUTED 187 if (dmake_mode_type == distributed_mode) { 188 (void) await_dist(false); 189 } else { 190 await_parallel(true); 191 } 192 #else 193 await_parallel(true); 194 #endif 195 finish_children(false); 196 } 197 #endif 198 199 #if defined (TEAMWARE_MAKE_CMN) && defined (MAXJOBS_ADJUST_RFE4694000) 200 job_adjust_fini(); 201 #endif 202 203 #if defined(SUN5_0) || defined(HP_UX) || defined(linux) 204 exit_status = 1; 205 #endif 206 exit(1); 207 } 208 209 /* 210 * warning(format, args...) 211 * 212 * Print a message and continue. 213 * 214 * Parameters: 215 * format printf type format string 216 * args Arguments to match the format 217 * 218 * Global variables used: 219 * report_pwd Should we report the current path? 220 */ 221 /*VARARGS*/ 222 void 223 warning(char * message, ...) 224 { 225 va_list args; 226 227 va_start(args, message); 228 (void) fflush(stdout); 229 #ifdef DISTRIBUTED 230 (void) fprintf(stderr, catgets(catd, 1, 264, "dmake: Warning: ")); 231 #else 232 (void) fprintf(stderr, catgets(catd, 1, 265, "make: Warning: ")); 233 #endif 234 (void) vfprintf(stderr, message, args); 235 (void) fprintf(stderr, "\n"); 236 va_end(args); 237 if (report_pwd) { 238 (void) fprintf(stderr, 239 catgets(catd, 1, 161, "Current working directory %s\n"), 240 get_current_path()); 241 } 242 (void) fflush(stderr); 243 } 244 245 /* 246 * time_to_string(time) 247 * 248 * Take a numeric time value and produce 249 * a proper string representation. 250 * 251 * Return value: 252 * The string representation of the time 253 * 254 * Parameters: 255 * time The time we need to translate 256 * 257 * Global variables used: 258 */ 259 char * 260 time_to_string(const timestruc_t &time) 261 { 262 struct tm *tm; 263 char buf[128]; 264 265 if (time == file_doesnt_exist) { 266 return catgets(catd, 1, 163, "File does not exist"); 267 } 268 if (time == file_max_time) { 269 return catgets(catd, 1, 164, "Younger than any file"); 270 } 271 tm = localtime(&time.tv_sec); 272 strftime(buf, sizeof (buf), NOCATGETS("%c %Z"), tm); 273 buf[127] = (int) nul_char; 274 return strdup(buf); 275 } 276 277 /* 278 * get_current_path() 279 * 280 * Stuff current_path with the current path if it isnt there already. 281 * 282 * Parameters: 283 * 284 * Global variables used: 285 */ 286 char * 287 get_current_path(void) 288 { 289 char pwd[(MAXPATHLEN * MB_LEN_MAX)]; 290 static char *current_path; 291 292 if (current_path == NULL) { 293 #if defined(SUN5_0) || defined(HP_UX) || defined(linux) 294 getcwd(pwd, sizeof(pwd)); 295 #else 296 (void) getwd(pwd); 297 #endif 298 if (pwd[0] == (int) nul_char) { 299 pwd[0] = (int) slash_char; 300 pwd[1] = (int) nul_char; 301 #ifdef DISTRIBUTED 302 current_path = strdup(pwd); 303 } else if (IS_EQUALN(pwd, NOCATGETS("/tmp_mnt"), 8)) { 304 current_path = strdup(pwd + 8); 305 } else { 306 current_path = strdup(pwd); 307 } 308 #else 309 } 310 current_path = strdup(pwd); 311 #endif 312 } 313 return current_path; 314 } 315 316 /***************************************** 317 * 318 * Make internal state dumping 319 * 320 * This is a set of routines for dumping the internal make state 321 * Used for the -p option 322 */ 323 324 /* 325 * dump_make_state() 326 * 327 * Dump make's internal state to stdout 328 * 329 * Parameters: 330 * 331 * Global variables used: 332 * svr4 Was ".SVR4" seen in makefile? 333 * svr4_name The Name ".SVR4", printed 334 * posix Was ".POSIX" seen in makefile? 335 * posix_name The Name ".POSIX", printed 336 * default_rule Points to the .DEFAULT rule 337 * default_rule_name The Name ".DEFAULT", printed 338 * default_target_to_build The first target to print 339 * dot_keep_state The Name ".KEEP_STATE", printed 340 * dot_keep_state_file The Name ".KEEP_STATE_FILE", printed 341 * hashtab The make hash table for Name blocks 342 * ignore_errors Was ".IGNORE" seen in makefile? 343 * ignore_name The Name ".IGNORE", printed 344 * keep_state Was ".KEEP_STATE" seen in makefile? 345 * percent_list The list of % rules 346 * precious The Name ".PRECIOUS", printed 347 * sccs_get_name The Name ".SCCS_GET", printed 348 * sccs_get_posix_name The Name ".SCCS_GET_POSIX", printed 349 * get_name The Name ".GET", printed 350 * get_posix_name The Name ".GET_POSIX", printed 351 * sccs_get_rule Points to the ".SCCS_GET" rule 352 * silent Was ".SILENT" seen in makefile? 353 * silent_name The Name ".SILENT", printed 354 * suffixes The suffix list from ".SUFFIXES" 355 * suffixes_name The Name ".SUFFIX", printed 356 */ 357 void 358 dump_make_state(void) 359 { 360 Name_set::iterator p, e; 361 register Property prop; 362 register Dependency dep; 363 register Cmd_line rule; 364 Percent percent, percent_depe; 365 366 /* Default target */ 367 if (default_target_to_build != NULL) { 368 print_rule(default_target_to_build); 369 } 370 (void) printf("\n"); 371 372 /* .POSIX */ 373 if (posix) { 374 (void) printf("%s:\n", posix_name->string_mb); 375 } 376 377 /* .DEFAULT */ 378 if (default_rule != NULL) { 379 (void) printf("%s:\n", default_rule_name->string_mb); 380 for (rule = default_rule; rule != NULL; rule = rule->next) { 381 (void) printf("\t%s\n", rule->command_line->string_mb); 382 } 383 } 384 385 /* .IGNORE */ 386 if (ignore_errors) { 387 (void) printf("%s:\n", ignore_name->string_mb); 388 } 389 390 /* .KEEP_STATE: */ 391 if (keep_state) { 392 (void) printf("%s:\n\n", dot_keep_state->string_mb); 393 } 394 395 /* .PRECIOUS */ 396 (void) printf("%s:", precious->string_mb); 397 for (p = hashtab.begin(), e = hashtab.end(); p != e; p++) { 398 if ((p->stat.is_precious) || (all_precious)) { 399 (void) printf(" %s", p->string_mb); 400 } 401 } 402 (void) printf("\n"); 403 404 /* .SCCS_GET */ 405 if (sccs_get_rule != NULL) { 406 (void) printf("%s:\n", sccs_get_name->string_mb); 407 for (rule = sccs_get_rule; rule != NULL; rule = rule->next) { 408 (void) printf("\t%s\n", rule->command_line->string_mb); 409 } 410 } 411 412 /* .SILENT */ 413 if (silent) { 414 (void) printf("%s:\n", silent_name->string_mb); 415 } 416 417 /* .SUFFIXES: */ 418 (void) printf("%s:", suffixes_name->string_mb); 419 for (dep = suffixes; dep != NULL; dep = dep->next) { 420 (void) printf(" %s", dep->name->string_mb); 421 build_suffix_list(dep->name); 422 } 423 (void) printf("\n\n"); 424 425 /* % rules */ 426 for (percent = percent_list; 427 percent != NULL; 428 percent = percent->next) { 429 (void) printf("%s:", 430 percent->name->string_mb); 431 432 for (percent_depe = percent->dependencies; 433 percent_depe != NULL; 434 percent_depe = percent_depe->next) { 435 (void) printf(" %s", percent_depe->name->string_mb); 436 } 437 438 (void) printf("\n"); 439 440 for (rule = percent->command_template; 441 rule != NULL; 442 rule = rule->next) { 443 (void) printf("\t%s\n", rule->command_line->string_mb); 444 } 445 } 446 447 /* Suffix rules */ 448 for (p = hashtab.begin(), e = hashtab.end(); p != e; p++) { 449 Wstring wcb(p); 450 if (wcb.get_string()[0] == (int) period_char) { 451 print_rule(p); 452 } 453 } 454 455 /* Macro assignments */ 456 for (p = hashtab.begin(), e = hashtab.end(); p != e; p++) { 457 if (((prop = get_prop(p->prop, macro_prop)) != NULL) && 458 (prop->body.macro.value != NULL)) { 459 (void) printf("%s", p->string_mb); 460 print_value(prop->body.macro.value, 461 (Daemon) prop->body.macro.daemon); 462 } 463 } 464 (void) printf("\n"); 465 466 /* Conditional macro assignments */ 467 for (p = hashtab.begin(), e = hashtab.end(); p != e; p++) { 468 for (prop = get_prop(p->prop, conditional_prop); 469 prop != NULL; 470 prop = get_prop(prop->next, conditional_prop)) { 471 (void) printf("%s := %s", 472 p->string_mb, 473 prop->body.conditional.name-> 474 string_mb); 475 if (prop->body.conditional.append) { 476 printf(" +"); 477 } 478 else { 479 printf(" "); 480 } 481 print_value(prop->body.conditional.value, 482 no_daemon); 483 } 484 } 485 (void) printf("\n"); 486 487 /* All other dependencies */ 488 for (p = hashtab.begin(), e = hashtab.end(); p != e; p++) { 489 if (p->colons != no_colon) { 490 print_rule(p); 491 } 492 } 493 (void) printf("\n"); 494 } 495 496 /* 497 * print_rule(target) 498 * 499 * Print the rule for one target 500 * 501 * Parameters: 502 * target Target we print rule for 503 * 504 * Global variables used: 505 */ 506 static void 507 print_rule(register Name target) 508 { 509 register Cmd_line rule; 510 register Property line; 511 register Dependency dependency; 512 513 if (target->dependency_printed || 514 ((line = get_prop(target->prop, line_prop)) == NULL) || 515 ((line->body.line.command_template == NULL) && 516 (line->body.line.dependencies == NULL))) { 517 return; 518 } 519 target->dependency_printed = true; 520 521 (void) printf("%s:", target->string_mb); 522 523 for (dependency = line->body.line.dependencies; 524 dependency != NULL; 525 dependency = dependency->next) { 526 (void) printf(" %s", dependency->name->string_mb); 527 } 528 529 (void) printf("\n"); 530 531 for (rule = line->body.line.command_template; 532 rule != NULL; 533 rule = rule->next) { 534 (void) printf("\t%s\n", rule->command_line->string_mb); 535 } 536 } 537 538 void 539 dump_target_list(void) 540 { 541 Name_set::iterator p, e; 542 Wstring str; 543 544 for (p = hashtab.begin(), e = hashtab.end(); p != e; p++) { 545 str.init(p); 546 wchar_t * wcb = str.get_string(); 547 if ((p->colons != no_colon) && 548 ((wcb[0] != (int) period_char) || 549 ((wcb[0] == (int) period_char) && 550 (wschr(wcb, (int) slash_char))))) { 551 print_target_n_deps(p); 552 } 553 } 554 } 555 556 static void 557 print_target_n_deps(register Name target) 558 { 559 register Cmd_line rule; 560 register Property line; 561 register Dependency dependency; 562 563 if (target->dependency_printed) { 564 return; 565 } 566 target->dependency_printed = true; 567 568 (void) printf("%s\n", target->string_mb); 569 570 if ((line = get_prop(target->prop, line_prop)) == NULL) { 571 return; 572 } 573 for (dependency = line->body.line.dependencies; 574 dependency != NULL; 575 dependency = dependency->next) { 576 if (!dependency->automatic) { 577 print_target_n_deps(dependency->name); 578 } 579 } 580 } 581 582 /***************************************** 583 * 584 * main() support 585 */ 586 587 /* 588 * load_cached_names() 589 * 590 * Load the vector of cached names 591 * 592 * Parameters: 593 * 594 * Global variables used: 595 * Many many pointers to Name blocks. 596 */ 597 void 598 load_cached_names(void) 599 { 600 char *cp; 601 Name dollar; 602 603 /* Load the cached_names struct */ 604 MBSTOWCS(wcs_buffer, NOCATGETS(".BUILT_LAST_MAKE_RUN")); 605 built_last_make_run = GETNAME(wcs_buffer, FIND_LENGTH); 606 MBSTOWCS(wcs_buffer, NOCATGETS("@")); 607 c_at = GETNAME(wcs_buffer, FIND_LENGTH); 608 MBSTOWCS(wcs_buffer, NOCATGETS(" *conditionals* ")); 609 conditionals = GETNAME(wcs_buffer, FIND_LENGTH); 610 /* 611 * A version of make was released with NSE 1.0 that used 612 * VERSION-1.1 but this version is identical to VERSION-1.0. 613 * The version mismatch code makes a special case for this 614 * situation. If the version number is changed from 1.0 615 * it should go to 1.2. 616 */ 617 MBSTOWCS(wcs_buffer, NOCATGETS("VERSION-1.0")); 618 current_make_version = GETNAME(wcs_buffer, FIND_LENGTH); 619 MBSTOWCS(wcs_buffer, NOCATGETS(".SVR4")); 620 svr4_name = GETNAME(wcs_buffer, FIND_LENGTH); 621 MBSTOWCS(wcs_buffer, NOCATGETS(".POSIX")); 622 posix_name = GETNAME(wcs_buffer, FIND_LENGTH); 623 MBSTOWCS(wcs_buffer, NOCATGETS(".DEFAULT")); 624 default_rule_name = GETNAME(wcs_buffer, FIND_LENGTH); 625 #ifdef NSE 626 MBSTOWCS(wcs_buffer, NOCATGETS(".DERIVED_SRC")); 627 derived_src= GETNAME(wcs_buffer, FIND_LENGTH); 628 #endif 629 MBSTOWCS(wcs_buffer, NOCATGETS("$")); 630 dollar = GETNAME(wcs_buffer, FIND_LENGTH); 631 MBSTOWCS(wcs_buffer, NOCATGETS(".DONE")); 632 done = GETNAME(wcs_buffer, FIND_LENGTH); 633 MBSTOWCS(wcs_buffer, NOCATGETS(".")); 634 dot = GETNAME(wcs_buffer, FIND_LENGTH); 635 MBSTOWCS(wcs_buffer, NOCATGETS(".KEEP_STATE")); 636 dot_keep_state = GETNAME(wcs_buffer, FIND_LENGTH); 637 MBSTOWCS(wcs_buffer, NOCATGETS(".KEEP_STATE_FILE")); 638 dot_keep_state_file = GETNAME(wcs_buffer, FIND_LENGTH); 639 MBSTOWCS(wcs_buffer, NOCATGETS("")); 640 empty_name = GETNAME(wcs_buffer, FIND_LENGTH); 641 MBSTOWCS(wcs_buffer, NOCATGETS(" FORCE")); 642 force = GETNAME(wcs_buffer, FIND_LENGTH); 643 MBSTOWCS(wcs_buffer, NOCATGETS("HOST_ARCH")); 644 host_arch = GETNAME(wcs_buffer, FIND_LENGTH); 645 MBSTOWCS(wcs_buffer, NOCATGETS("HOST_MACH")); 646 host_mach = GETNAME(wcs_buffer, FIND_LENGTH); 647 MBSTOWCS(wcs_buffer, NOCATGETS(".IGNORE")); 648 ignore_name = GETNAME(wcs_buffer, FIND_LENGTH); 649 MBSTOWCS(wcs_buffer, NOCATGETS(".INIT")); 650 init = GETNAME(wcs_buffer, FIND_LENGTH); 651 MBSTOWCS(wcs_buffer, NOCATGETS(".LOCAL")); 652 localhost_name = GETNAME(wcs_buffer, FIND_LENGTH); 653 MBSTOWCS(wcs_buffer, NOCATGETS(".make.state")); 654 make_state = GETNAME(wcs_buffer, FIND_LENGTH); 655 MBSTOWCS(wcs_buffer, NOCATGETS("MAKEFLAGS")); 656 makeflags = GETNAME(wcs_buffer, FIND_LENGTH); 657 MBSTOWCS(wcs_buffer, NOCATGETS(".MAKE_VERSION")); 658 make_version = GETNAME(wcs_buffer, FIND_LENGTH); 659 MBSTOWCS(wcs_buffer, NOCATGETS(".NO_PARALLEL")); 660 no_parallel_name = GETNAME(wcs_buffer, FIND_LENGTH); 661 MBSTOWCS(wcs_buffer, NOCATGETS(".NOT_AUTO")); 662 not_auto = GETNAME(wcs_buffer, FIND_LENGTH); 663 MBSTOWCS(wcs_buffer, NOCATGETS(".PARALLEL")); 664 parallel_name = GETNAME(wcs_buffer, FIND_LENGTH); 665 MBSTOWCS(wcs_buffer, NOCATGETS("PATH")); 666 path_name = GETNAME(wcs_buffer, FIND_LENGTH); 667 MBSTOWCS(wcs_buffer, NOCATGETS("+")); 668 plus = GETNAME(wcs_buffer, FIND_LENGTH); 669 MBSTOWCS(wcs_buffer, NOCATGETS(".PRECIOUS")); 670 precious = GETNAME(wcs_buffer, FIND_LENGTH); 671 MBSTOWCS(wcs_buffer, NOCATGETS("?")); 672 query = GETNAME(wcs_buffer, FIND_LENGTH); 673 MBSTOWCS(wcs_buffer, NOCATGETS("^")); 674 hat = GETNAME(wcs_buffer, FIND_LENGTH); 675 MBSTOWCS(wcs_buffer, NOCATGETS(".RECURSIVE")); 676 recursive_name = GETNAME(wcs_buffer, FIND_LENGTH); 677 MBSTOWCS(wcs_buffer, NOCATGETS(".SCCS_GET")); 678 sccs_get_name = GETNAME(wcs_buffer, FIND_LENGTH); 679 MBSTOWCS(wcs_buffer, NOCATGETS(".SCCS_GET_POSIX")); 680 sccs_get_posix_name = GETNAME(wcs_buffer, FIND_LENGTH); 681 MBSTOWCS(wcs_buffer, NOCATGETS(".GET")); 682 get_name = GETNAME(wcs_buffer, FIND_LENGTH); 683 MBSTOWCS(wcs_buffer, NOCATGETS(".GET_POSIX")); 684 get_posix_name = GETNAME(wcs_buffer, FIND_LENGTH); 685 MBSTOWCS(wcs_buffer, NOCATGETS("SHELL")); 686 shell_name = GETNAME(wcs_buffer, FIND_LENGTH); 687 MBSTOWCS(wcs_buffer, NOCATGETS(".SILENT")); 688 silent_name = GETNAME(wcs_buffer, FIND_LENGTH); 689 MBSTOWCS(wcs_buffer, NOCATGETS(".SUFFIXES")); 690 suffixes_name = GETNAME(wcs_buffer, FIND_LENGTH); 691 MBSTOWCS(wcs_buffer, SUNPRO_DEPENDENCIES); 692 sunpro_dependencies = GETNAME(wcs_buffer, FIND_LENGTH); 693 MBSTOWCS(wcs_buffer, NOCATGETS("TARGET_ARCH")); 694 target_arch = GETNAME(wcs_buffer, FIND_LENGTH); 695 MBSTOWCS(wcs_buffer, NOCATGETS("TARGET_MACH")); 696 target_mach = GETNAME(wcs_buffer, FIND_LENGTH); 697 MBSTOWCS(wcs_buffer, NOCATGETS("VIRTUAL_ROOT")); 698 virtual_root = GETNAME(wcs_buffer, FIND_LENGTH); 699 MBSTOWCS(wcs_buffer, NOCATGETS("VPATH")); 700 vpath_name = GETNAME(wcs_buffer, FIND_LENGTH); 701 MBSTOWCS(wcs_buffer, NOCATGETS(".WAIT")); 702 wait_name = GETNAME(wcs_buffer, FIND_LENGTH); 703 704 wait_name->state = build_ok; 705 706 /* Mark special targets so that the reader treats them properly */ 707 svr4_name->special_reader = svr4_special; 708 posix_name->special_reader = posix_special; 709 built_last_make_run->special_reader = built_last_make_run_special; 710 default_rule_name->special_reader = default_special; 711 #ifdef NSE 712 derived_src->special_reader= derived_src_special; 713 #endif 714 dot_keep_state->special_reader = keep_state_special; 715 dot_keep_state_file->special_reader = keep_state_file_special; 716 ignore_name->special_reader = ignore_special; 717 make_version->special_reader = make_version_special; 718 no_parallel_name->special_reader = no_parallel_special; 719 parallel_name->special_reader = parallel_special; 720 localhost_name->special_reader = localhost_special; 721 precious->special_reader = precious_special; 722 sccs_get_name->special_reader = sccs_get_special; 723 sccs_get_posix_name->special_reader = sccs_get_posix_special; 724 get_name->special_reader = get_special; 725 get_posix_name->special_reader = get_posix_special; 726 silent_name->special_reader = silent_special; 727 suffixes_name->special_reader = suffixes_special; 728 729 /* The value of $$ is $ */ 730 (void) SETVAR(dollar, dollar, false); 731 dollar->dollar = false; 732 733 /* Set the value of $(SHELL) */ 734 #ifdef HP_UX 735 MBSTOWCS(wcs_buffer, NOCATGETS("/bin/posix/sh")); 736 #else 737 #if defined(SUN5_0) 738 if (posix) { 739 MBSTOWCS(wcs_buffer, NOCATGETS("/usr/xpg4/bin/sh")); 740 } else { 741 MBSTOWCS(wcs_buffer, NOCATGETS("/bin/sh")); 742 } 743 #else /* ^SUN5_0 */ 744 MBSTOWCS(wcs_buffer, NOCATGETS("/bin/sh")); 745 #endif /* ^SUN5_0 */ 746 #endif 747 (void) SETVAR(shell_name, GETNAME(wcs_buffer, FIND_LENGTH), false); 748 749 /* 750 * Use " FORCE" to simulate a FRC dependency for :: type 751 * targets with no dependencies. 752 */ 753 (void) append_prop(force, line_prop); 754 force->stat.time = file_max_time; 755 756 /* Make sure VPATH is defined before current dir is read */ 757 if ((cp = getenv(vpath_name->string_mb)) != NULL) { 758 MBSTOWCS(wcs_buffer, cp); 759 (void) SETVAR(vpath_name, 760 GETNAME(wcs_buffer, FIND_LENGTH), 761 false); 762 } 763 764 /* Check if there is NO PATH variable. If not we construct one. */ 765 if (getenv(path_name->string_mb) == NULL) { 766 vroot_path = NULL; 767 add_dir_to_path(NOCATGETS("."), &vroot_path, -1); 768 add_dir_to_path(NOCATGETS("/bin"), &vroot_path, -1); 769 add_dir_to_path(NOCATGETS("/usr/bin"), &vroot_path, -1); 770 } 771 } 772 773 /* 774 * iterate on list of conditional macros in np, and place them in 775 * a String_rec starting with, and separated by the '$' character. 776 */ 777 void 778 cond_macros_into_string(Name np, String_rec *buffer) 779 { 780 Macro_list macro_list; 781 782 /* 783 * Put the version number at the start of the string 784 */ 785 MBSTOWCS(wcs_buffer, DEPINFO_FMT_VERSION); 786 append_string(wcs_buffer, buffer, FIND_LENGTH); 787 /* 788 * Add the rest of the conditional macros to the buffer 789 */ 790 if (np->depends_on_conditional){ 791 for (macro_list = np->conditional_macro_list; 792 macro_list != NULL; macro_list = macro_list->next){ 793 append_string(macro_list->macro_name, buffer, 794 FIND_LENGTH); 795 append_char((int) equal_char, buffer); 796 append_string(macro_list->value, buffer, FIND_LENGTH); 797 append_char((int) dollar_char, buffer); 798 } 799 } 800 } 801 /* 802 * Copyright (c) 1987-1992 Sun Microsystems, Inc. All Rights Reserved. 803 * Sun considers its source code as an unpublished, proprietary 804 * trade secret, and it is available only under strict license 805 * provisions. This copyright notice is placed here only to protect 806 * Sun in the event the source is deemed a published work. Dissassembly, 807 * decompilation, or other means of reducing the object code to human 808 * readable form is prohibited by the license agreement under which 809 * this code is provided to the user or company in possession of this 810 * copy. 811 * RESTRICTED RIGHTS LEGEND: Use, duplication, or disclosure by the 812 * Government is subject to restrictions as set forth in subparagraph 813 * (c)(1)(ii) of the Rights in Technical Data and Computer Software 814 * clause at DFARS 52.227-7013 and in similar clauses in the FAR and 815 * NASA FAR Supplement. 816 * 817 * 1.3 91/09/30 818 */ 819 820 821 /* Some includes are commented because of the includes at the beginning */ 822 /* #include <signal.h> */ 823 #include <sys/types.h> 824 #include <sys/stat.h> 825 #include <sys/param.h> 826 /* #include <string.h> */ 827 #include <unistd.h> 828 #include <stdlib.h> 829 /* #include <stdio.h> */ 830 /* #include <avo/find_dir.h> */ 831 /* #ifndef TEAMWARE_MAKE_CMN 832 #include <avo/find_dir.h> 833 #endif */ 834 835 /* Routines to find the base directory name from which the various components 836 * -executables, *crt* libraries etc will be accessed 837 */ 838 839 /* This routine checks to see if a given filename is an executable or not. 840 Logically similar to the csh statement : if ( -x $i && ! -d $i ) 841 */ 842 843 static int 844 check_if_exec(char *file) 845 { 846 struct stat stb; 847 if (stat(file, &stb) < 0) { 848 return ( -1); 849 } 850 if (S_ISDIR(stb.st_mode)) { 851 return (-1); 852 } 853 if (!(stb.st_mode & S_IEXEC)) { 854 return ( -1); 855 } 856 return (0); 857 } 858 859 /* resolve - check for specified file in specified directory 860 * sets up dir, following symlinks. 861 * returns zero for success, or 862 * -1 for error (with errno set properly) 863 */ 864 static int 865 resolve (char *indir, /* search directory */ 866 char *cmd, /* search for name */ 867 char *dir, /* directory buffer */ 868 char **run) /* resultion name ptr ptr */ 869 { 870 char *p; 871 int rv = -1; 872 int sll; 873 char symlink[MAXPATHLEN + 1]; 874 875 do { 876 errno = ENAMETOOLONG; 877 if ((strlen (indir) + strlen (cmd) + 2) > (size_t) MAXPATHLEN) 878 break; 879 880 sprintf(dir, "%s/%s", indir, cmd); 881 if (check_if_exec(dir) != 0) /* check if dir is an executable */ 882 { 883 break; /* Not an executable program */ 884 } 885 886 /* follow symbolic links */ 887 while ((sll = readlink (dir, symlink, MAXPATHLEN)) >= 0) { 888 symlink[sll] = 0; 889 if (*symlink == '/') 890 strcpy (dir, symlink); 891 else 892 sprintf (strrchr (dir, '/'), "/%s", symlink); 893 } 894 if (errno != EINVAL) 895 break; 896 897 p = strrchr (dir, '/'); 898 *p++ = 0; 899 if (run) /* user wants resolution name */ 900 *run = p; 901 rv = 0; /* complete, with success! */ 902 903 } while (0); 904 905 return rv; 906 } 907 908 /* 909 *find_run_directory - find executable file in PATH 910 * 911 * PARAMETERS: 912 * cmd filename as typed by user (argv[0]) 913 * cwd buffer from which is read the working directory 914 * if first character is '/' or into which is 915 * copied working directory name otherwise 916 * dir buffer into which is copied program's directory 917 * pgm where to return pointer to tail of cmd (may be NULL 918 * if not wanted) 919 * run where to return pointer to tail of final resolved 920 * name ( dir/run is the program) (may be NULL 921 * if not wanted) 922 * path user's path from environment 923 * 924 * Note: run and pgm will agree except when symbolic links have 925 * renamed files 926 * 927 * RETURNS: 928 * returns zero for success, 929 * -1 for error (with errno set properly). 930 * 931 * EXAMPLE: 932 * find_run_directory (argv[0], ".", &charray1, (char **) 0, (char **) 0, 933 * getenv(NOGETTEXT("PATH"))); 934 */ 935 extern int 936 find_run_directory (char *cmd, 937 char *cwd, 938 char *dir, 939 char **pgm, 940 char **run, 941 char *path) 942 { 943 int rv = 0; 944 char *f, *s; 945 int i; 946 char tmp_path[MAXPATHLEN]; 947 948 if (!cmd || !*cmd || !cwd || !dir) { 949 errno = EINVAL; /* stupid arguments! */ 950 return -1; 951 } 952 953 if (*cwd != '/') 954 if (!(getcwd (cwd, MAXPATHLEN))) 955 return -1; /* can not get working directory */ 956 957 f = strrchr (cmd, '/'); 958 if (pgm) /* user wants program name */ 959 *pgm = f ? f + 1 : cmd; 960 961 /* get program directory */ 962 rv = -1; 963 if (*cmd == '/') /* absname given */ 964 rv = resolve ("", cmd + 1, dir, run); 965 else if (f) /* relname given */ 966 rv = resolve (cwd, cmd, dir, run); 967 else { /* from searchpath */ 968 if (!path || !*path) { /* if missing or null path */ 969 tmp_path[0] = '.'; /* assume sanity */ 970 tmp_path[1] = '\0'; 971 } else { 972 strcpy(tmp_path, path); 973 } 974 f = tmp_path; 975 rv = -1; 976 errno = ENOENT; /* errno gets this if path empty */ 977 while (*f && (rv < 0)) { 978 s = f; 979 while (*f && (*f != ':')) 980 ++f; 981 if (*f) 982 *f++ = 0; 983 if (*s == '/') 984 rv = resolve (s, cmd, dir, run); 985 else { 986 char abuf[MAXPATHLEN]; 987 988 sprintf (abuf, "%s/%s", cwd, s); 989 rv = resolve (abuf, cmd, dir, run); 990 } 991 } 992 } 993 994 /* Remove any trailing /. */ 995 i = strlen(dir); 996 if ( dir[i-2] == '/' && dir[i-1] == '.') { 997 dir[i-2] = '\0'; 998 } 999 1000 return rv; 1001 } 1002