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