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