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