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