make: unifdef for MAKETOOL and DISTRIBUTED (undefined)
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
--- EOF ---