VirtualBox

source: kBuild/vendor/gnumake/2005-05-16/misc.c

Last change on this file was 280, checked in by bird, 20 years ago

Current make snaphot, 2005-05-16.

  • Property svn:eol-style set to native
File size: 18.4 KB
Line 
1/* Miscellaneous generic support functions for GNU Make.
2Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1997,
32002 Free Software Foundation, Inc.
4This file is part of GNU Make.
5
6GNU Make is free software; you can redistribute it and/or modify
7it under the terms of the GNU General Public License as published by
8the Free Software Foundation; either version 2, or (at your option)
9any later version.
10
11GNU Make is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with GNU Make; see the file COPYING. If not, write to
18the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19Boston, MA 02111-1307, USA. */
20
21#include "make.h"
22#include "dep.h"
23#include "debug.h"
24
25/* Variadic functions. We go through contortions to allow proper function
26 prototypes for both ANSI and pre-ANSI C compilers, and also for those
27 which support stdarg.h vs. varargs.h, and finally those which have
28 vfprintf(), etc. and those who have _doprnt... or nothing.
29
30 This fancy stuff all came from GNU fileutils, except for the VA_PRINTF and
31 VA_END macros used here since we have multiple print functions. */
32
33#if USE_VARIADIC
34# if HAVE_STDARG_H
35# include <stdarg.h>
36# define VA_START(args, lastarg) va_start(args, lastarg)
37# else
38# include <varargs.h>
39# define VA_START(args, lastarg) va_start(args)
40# endif
41# if HAVE_VPRINTF
42# define VA_PRINTF(fp, lastarg, args) vfprintf((fp), (lastarg), (args))
43# else
44# define VA_PRINTF(fp, lastarg, args) _doprnt((lastarg), (args), (fp))
45# endif
46# define VA_END(args) va_end(args)
47#else
48/* We can't use any variadic interface! */
49# define va_alist a1, a2, a3, a4, a5, a6, a7, a8
50# define va_dcl char *a1, *a2, *a3, *a4, *a5, *a6, *a7, *a8;
51# define VA_START(args, lastarg)
52# define VA_PRINTF(fp, lastarg, args) fprintf((fp), (lastarg), va_alist)
53# define VA_END(args)
54#endif
55
56
57/* Compare strings *S1 and *S2.
58 Return negative if the first is less, positive if it is greater,
59 zero if they are equal. */
60
61int
62alpha_compare (const void *v1, const void *v2)
63{
64 const char *s1 = *((char **)v1);
65 const char *s2 = *((char **)v2);
66
67 if (*s1 != *s2)
68 return *s1 - *s2;
69 return strcmp (s1, s2);
70}
71
72
73/* Discard each backslash-newline combination from LINE.
74 Backslash-backslash-newline combinations become backslash-newlines.
75 This is done by copying the text at LINE into itself. */
76
77void
78collapse_continuations (char *line)
79{
80 register char *in, *out, *p;
81 register int backslash;
82 register unsigned int bs_write;
83
84 in = strchr (line, '\n');
85 if (in == 0)
86 return;
87
88 out = in;
89 while (out > line && out[-1] == '\\')
90 --out;
91
92 while (*in != '\0')
93 {
94 /* BS_WRITE gets the number of quoted backslashes at
95 the end just before IN, and BACKSLASH gets nonzero
96 if the next character is quoted. */
97 backslash = 0;
98 bs_write = 0;
99 for (p = in - 1; p >= line && *p == '\\'; --p)
100 {
101 if (backslash)
102 ++bs_write;
103 backslash = !backslash;
104
105 /* It should be impossible to go back this far without exiting,
106 but if we do, we can't get the right answer. */
107 if (in == out - 1)
108 abort ();
109 }
110
111 /* Output the appropriate number of backslashes. */
112 while (bs_write-- > 0)
113 *out++ = '\\';
114
115 /* Skip the newline. */
116 ++in;
117
118 /* If the newline is quoted, discard following whitespace
119 and any preceding whitespace; leave just one space. */
120 if (backslash)
121 {
122 in = next_token (in);
123 while (out > line && isblank ((unsigned char)out[-1]))
124 --out;
125 *out++ = ' ';
126 }
127 else
128 /* If the newline isn't quoted, put it in the output. */
129 *out++ = '\n';
130
131 /* Now copy the following line to the output.
132 Stop when we find backslashes followed by a newline. */
133 while (*in != '\0')
134 if (*in == '\\')
135 {
136 p = in + 1;
137 while (*p == '\\')
138 ++p;
139 if (*p == '\n')
140 {
141 in = p;
142 break;
143 }
144 while (in < p)
145 *out++ = *in++;
146 }
147 else
148 *out++ = *in++;
149 }
150
151 *out = '\0';
152}
153
154
155/* Remove comments from LINE.
156 This is done by copying the text at LINE onto itself. */
157
158void
159remove_comments (char *line)
160{
161 char *comment;
162
163 comment = find_char_unquote (line, '#', 0, 0);
164
165 if (comment != 0)
166 /* Cut off the line at the #. */
167 *comment = '\0';
168}
169
170
171/* Print N spaces (used in debug for target-depth). */
172
173void
174print_spaces (unsigned int n)
175{
176 while (n-- > 0)
177 putchar (' ');
178}
179
180
181
182/* Return a newly-allocated string whose contents
183 concatenate those of s1, s2, s3. */
184
185char *
186concat (const char *s1, const char *s2, const char *s3)
187{
188 unsigned int len1, len2, len3;
189 char *result;
190
191 len1 = *s1 != '\0' ? strlen (s1) : 0;
192 len2 = *s2 != '\0' ? strlen (s2) : 0;
193 len3 = *s3 != '\0' ? strlen (s3) : 0;
194
195 result = (char *) xmalloc (len1 + len2 + len3 + 1);
196
197 if (*s1 != '\0')
198 bcopy (s1, result, len1);
199 if (*s2 != '\0')
200 bcopy (s2, result + len1, len2);
201 if (*s3 != '\0')
202 bcopy (s3, result + len1 + len2, len3);
203 *(result + len1 + len2 + len3) = '\0';
204
205 return result;
206}
207
208
209/* Print a message on stdout. */
210
211void
212#if HAVE_ANSI_COMPILER && USE_VARIADIC && HAVE_STDARG_H
213message (int prefix, const char *fmt, ...)
214#else
215message (prefix, fmt, va_alist)
216 int prefix;
217 const char *fmt;
218 va_dcl
219#endif
220{
221#if USE_VARIADIC
222 va_list args;
223#endif
224
225 log_working_directory (1);
226
227 if (fmt != 0)
228 {
229 if (prefix)
230 {
231 if (makelevel == 0)
232 printf ("%s: ", program);
233 else
234 printf ("%s[%u]: ", program, makelevel);
235 }
236 VA_START (args, fmt);
237 VA_PRINTF (stdout, fmt, args);
238 VA_END (args);
239 putchar ('\n');
240 }
241
242 fflush (stdout);
243}
244
245/* Print an error message. */
246
247void
248#if HAVE_ANSI_COMPILER && USE_VARIADIC && HAVE_STDARG_H
249error (const struct floc *flocp, const char *fmt, ...)
250#else
251error (flocp, fmt, va_alist)
252 const struct floc *flocp;
253 const char *fmt;
254 va_dcl
255#endif
256{
257#if USE_VARIADIC
258 va_list args;
259#endif
260
261 log_working_directory (1);
262
263 if (flocp && flocp->filenm)
264 fprintf (stderr, "%s:%lu: ", flocp->filenm, flocp->lineno);
265 else if (makelevel == 0)
266 fprintf (stderr, "%s: ", program);
267 else
268 fprintf (stderr, "%s[%u]: ", program, makelevel);
269
270 VA_START(args, fmt);
271 VA_PRINTF (stderr, fmt, args);
272 VA_END (args);
273
274 putc ('\n', stderr);
275 fflush (stderr);
276}
277
278/* Print an error message and exit. */
279
280void
281#if HAVE_ANSI_COMPILER && USE_VARIADIC && HAVE_STDARG_H
282fatal (const struct floc *flocp, const char *fmt, ...)
283#else
284fatal (flocp, fmt, va_alist)
285 const struct floc *flocp;
286 const char *fmt;
287 va_dcl
288#endif
289{
290#if USE_VARIADIC
291 va_list args;
292#endif
293
294 log_working_directory (1);
295
296 if (flocp && flocp->filenm)
297 fprintf (stderr, "%s:%lu: *** ", flocp->filenm, flocp->lineno);
298 else if (makelevel == 0)
299 fprintf (stderr, "%s: *** ", program);
300 else
301 fprintf (stderr, "%s[%u]: *** ", program, makelevel);
302
303 VA_START(args, fmt);
304 VA_PRINTF (stderr, fmt, args);
305 VA_END (args);
306
307 fputs (_(". Stop.\n"), stderr);
308
309 die (2);
310}
311
312#ifndef HAVE_STRERROR
313
314#undef strerror
315
316char *
317strerror (int errnum)
318{
319 extern int errno, sys_nerr;
320#ifndef __DECC
321 extern char *sys_errlist[];
322#endif
323 static char buf[] = "Unknown error 12345678901234567890";
324
325 if (errno < sys_nerr)
326 return sys_errlist[errnum];
327
328 sprintf (buf, _("Unknown error %d"), errnum);
329 return buf;
330}
331#endif
332
333/* Print an error message from errno. */
334
335void
336perror_with_name (const char *str, const char *name)
337{
338 error (NILF, _("%s%s: %s"), str, name, strerror (errno));
339}
340
341/* Print an error message from errno and exit. */
342
343void
344pfatal_with_name (const char *name)
345{
346 fatal (NILF, _("%s: %s"), name, strerror (errno));
347
348 /* NOTREACHED */
349}
350
351
352/* Like malloc but get fatal error if memory is exhausted. */
353/* Don't bother if we're using dmalloc; it provides these for us. */
354
355#ifndef HAVE_DMALLOC_H
356
357#undef xmalloc
358#undef xrealloc
359#undef xstrdup
360
361char *
362xmalloc (unsigned int size)
363{
364 /* Make sure we don't allocate 0, for pre-ANSI libraries. */
365 char *result = (char *) malloc (size ? size : 1);
366 if (result == 0)
367 fatal (NILF, _("virtual memory exhausted"));
368 return result;
369}
370
371
372char *
373xrealloc (char *ptr, unsigned int size)
374{
375 char *result;
376
377 /* Some older implementations of realloc() don't conform to ANSI. */
378 if (! size)
379 size = 1;
380 result = ptr ? realloc (ptr, size) : malloc (size);
381 if (result == 0)
382 fatal (NILF, _("virtual memory exhausted"));
383 return result;
384}
385
386
387char *
388xstrdup (const char *ptr)
389{
390 char *result;
391
392#ifdef HAVE_STRDUP
393 result = strdup (ptr);
394#else
395 result = (char *) malloc (strlen (ptr) + 1);
396#endif
397
398 if (result == 0)
399 fatal (NILF, _("virtual memory exhausted"));
400
401#ifdef HAVE_STRDUP
402 return result;
403#else
404 return strcpy(result, ptr);
405#endif
406}
407
408#endif /* HAVE_DMALLOC_H */
409
410char *
411savestring (const char *str, unsigned int length)
412{
413 register char *out = (char *) xmalloc (length + 1);
414 if (length > 0)
415 bcopy (str, out, length);
416 out[length] = '\0';
417 return out;
418}
419
420
421
422/* Limited INDEX:
423 Search through the string STRING, which ends at LIMIT, for the character C.
424 Returns a pointer to the first occurrence, or nil if none is found.
425 Like INDEX except that the string searched ends where specified
426 instead of at the first null. */
427
428char *
429lindex (const char *s, const char *limit, int c)
430{
431 while (s < limit)
432 if (*s++ == c)
433 return (char *)(s - 1);
434
435 return 0;
436}
437
438
439/* Return the address of the first whitespace or null in the string S. */
440
441char *
442end_of_token (const char *s)
443{
444 while (*s != '\0' && !isblank ((unsigned char)*s))
445 ++s;
446 return (char *)s;
447}
448
449#ifdef WINDOWS32
450/*
451 * Same as end_of_token, but take into account a stop character
452 */
453char *
454end_of_token_w32 (char *s, char stopchar)
455{
456 register char *p = s;
457 register int backslash = 0;
458
459 while (*p != '\0' && *p != stopchar
460 && (backslash || !isblank ((unsigned char)*p)))
461 {
462 if (*p++ == '\\')
463 {
464 backslash = !backslash;
465 while (*p == '\\')
466 {
467 backslash = !backslash;
468 ++p;
469 }
470 }
471 else
472 backslash = 0;
473 }
474
475 return p;
476}
477#endif
478
479/* Return the address of the first nonwhitespace or null in the string S. */
480
481char *
482next_token (const char *s)
483{
484 while (isblank ((unsigned char)*s))
485 ++s;
486 return (char *)s;
487}
488
489/* Find the next token in PTR; return the address of it, and store the
490 length of the token into *LENGTHPTR if LENGTHPTR is not nil. */
491
492char *
493find_next_token (char **ptr, unsigned int *lengthptr)
494{
495 char *p = next_token (*ptr);
496 char *end;
497
498 if (*p == '\0')
499 return 0;
500
501 *ptr = end = end_of_token (p);
502 if (lengthptr != 0)
503 *lengthptr = end - p;
504 return p;
505}
506
507
508/* Copy a chain of `struct dep', making a new chain
509 with the same contents as the old one. */
510
511struct dep *
512copy_dep_chain (struct dep *d)
513{
514 register struct dep *c;
515 struct dep *firstnew = 0;
516 struct dep *lastnew = 0;
517
518 while (d != 0)
519 {
520 c = (struct dep *) xmalloc (sizeof (struct dep));
521 bcopy ((char *) d, (char *) c, sizeof (struct dep));
522 if (c->name != 0)
523 c->name = xstrdup (c->name);
524 c->next = 0;
525 if (firstnew == 0)
526 firstnew = lastnew = c;
527 else
528 lastnew = lastnew->next = c;
529
530 d = d->next;
531 }
532
533 return firstnew;
534}
535
536
537/* Free a chain of `struct nameseq'. Each nameseq->name is freed
538 as well. Can be used on `struct dep' chains.*/
539
540void
541free_ns_chain (struct nameseq *n)
542{
543 register struct nameseq *tmp;
544
545 while (n != 0)
546 {
547 if (n->name != 0)
548 free (n->name);
549
550 tmp = n;
551
552 n = n->next;
553
554 free (tmp);
555 }
556
557}
558
559#ifdef iAPX286
560/* The losing compiler on this machine can't handle this macro. */
561
562char *
563dep_name (struct dep *dep)
564{
565 return dep->name == 0 ? dep->file->name : dep->name;
566}
567#endif
568
569
570#ifdef GETLOADAVG_PRIVILEGED
571
572#ifdef POSIX
573
574/* Hopefully if a system says it's POSIX.1 and has the setuid and setgid
575 functions, they work as POSIX.1 says. Some systems (Alpha OSF/1 1.2,
576 for example) which claim to be POSIX.1 also have the BSD setreuid and
577 setregid functions, but they don't work as in BSD and only the POSIX.1
578 way works. */
579
580#undef HAVE_SETREUID
581#undef HAVE_SETREGID
582
583#else /* Not POSIX. */
584
585/* Some POSIX.1 systems have the seteuid and setegid functions. In a
586 POSIX-like system, they are the best thing to use. However, some
587 non-POSIX systems have them too but they do not work in the POSIX style
588 and we must use setreuid and setregid instead. */
589
590#undef HAVE_SETEUID
591#undef HAVE_SETEGID
592
593#endif /* POSIX. */
594
595#ifndef HAVE_UNISTD_H
596extern int getuid (), getgid (), geteuid (), getegid ();
597extern int setuid (), setgid ();
598#ifdef HAVE_SETEUID
599extern int seteuid ();
600#else
601#ifdef HAVE_SETREUID
602extern int setreuid ();
603#endif /* Have setreuid. */
604#endif /* Have seteuid. */
605#ifdef HAVE_SETEGID
606extern int setegid ();
607#else
608#ifdef HAVE_SETREGID
609extern int setregid ();
610#endif /* Have setregid. */
611#endif /* Have setegid. */
612#endif /* No <unistd.h>. */
613
614/* Keep track of the user and group IDs for user- and make- access. */
615static int user_uid = -1, user_gid = -1, make_uid = -1, make_gid = -1;
616#define access_inited (user_uid != -1)
617static enum { make, user } current_access;
618
619
620/* Under -d, write a message describing the current IDs. */
621
622static void
623log_access (char *flavor)
624{
625 if (! ISDB (DB_JOBS))
626 return;
627
628 /* All the other debugging messages go to stdout,
629 but we write this one to stderr because it might be
630 run in a child fork whose stdout is piped. */
631
632 fprintf (stderr, _("%s: user %lu (real %lu), group %lu (real %lu)\n"),
633 flavor, (unsigned long) geteuid (), (unsigned long) getuid (),
634 (unsigned long) getegid (), (unsigned long) getgid ());
635 fflush (stderr);
636}
637
638
639static void
640init_access (void)
641{
642#ifndef VMS
643 user_uid = getuid ();
644 user_gid = getgid ();
645
646 make_uid = geteuid ();
647 make_gid = getegid ();
648
649 /* Do these ever fail? */
650 if (user_uid == -1 || user_gid == -1 || make_uid == -1 || make_gid == -1)
651 pfatal_with_name ("get{e}[gu]id");
652
653 log_access (_("Initialized access"));
654
655 current_access = make;
656#endif
657}
658
659#endif /* GETLOADAVG_PRIVILEGED */
660
661/* Give the process appropriate permissions for access to
662 user data (i.e., to stat files, or to spawn a child process). */
663void
664user_access (void)
665{
666#ifdef GETLOADAVG_PRIVILEGED
667
668 if (!access_inited)
669 init_access ();
670
671 if (current_access == user)
672 return;
673
674 /* We are in "make access" mode. This means that the effective user and
675 group IDs are those of make (if it was installed setuid or setgid).
676 We now want to set the effective user and group IDs to the real IDs,
677 which are the IDs of the process that exec'd make. */
678
679#ifdef HAVE_SETEUID
680
681 /* Modern systems have the seteuid/setegid calls which set only the
682 effective IDs, which is ideal. */
683
684 if (seteuid (user_uid) < 0)
685 pfatal_with_name ("user_access: seteuid");
686
687#else /* Not HAVE_SETEUID. */
688
689#ifndef HAVE_SETREUID
690
691 /* System V has only the setuid/setgid calls to set user/group IDs.
692 There is an effective ID, which can be set by setuid/setgid.
693 It can be set (unless you are root) only to either what it already is
694 (returned by geteuid/getegid, now in make_uid/make_gid),
695 the real ID (return by getuid/getgid, now in user_uid/user_gid),
696 or the saved set ID (what the effective ID was before this set-ID
697 executable (make) was exec'd). */
698
699 if (setuid (user_uid) < 0)
700 pfatal_with_name ("user_access: setuid");
701
702#else /* HAVE_SETREUID. */
703
704 /* In 4BSD, the setreuid/setregid calls set both the real and effective IDs.
705 They may be set to themselves or each other. So you have two alternatives
706 at any one time. If you use setuid/setgid, the effective will be set to
707 the real, leaving only one alternative. Using setreuid/setregid, however,
708 you can toggle between your two alternatives by swapping the values in a
709 single setreuid or setregid call. */
710
711 if (setreuid (make_uid, user_uid) < 0)
712 pfatal_with_name ("user_access: setreuid");
713
714#endif /* Not HAVE_SETREUID. */
715#endif /* HAVE_SETEUID. */
716
717#ifdef HAVE_SETEGID
718 if (setegid (user_gid) < 0)
719 pfatal_with_name ("user_access: setegid");
720#else
721#ifndef HAVE_SETREGID
722 if (setgid (user_gid) < 0)
723 pfatal_with_name ("user_access: setgid");
724#else
725 if (setregid (make_gid, user_gid) < 0)
726 pfatal_with_name ("user_access: setregid");
727#endif
728#endif
729
730 current_access = user;
731
732 log_access (_("User access"));
733
734#endif /* GETLOADAVG_PRIVILEGED */
735}
736
737/* Give the process appropriate permissions for access to
738 make data (i.e., the load average). */
739void
740make_access (void)
741{
742#ifdef GETLOADAVG_PRIVILEGED
743
744 if (!access_inited)
745 init_access ();
746
747 if (current_access == make)
748 return;
749
750 /* See comments in user_access, above. */
751
752#ifdef HAVE_SETEUID
753 if (seteuid (make_uid) < 0)
754 pfatal_with_name ("make_access: seteuid");
755#else
756#ifndef HAVE_SETREUID
757 if (setuid (make_uid) < 0)
758 pfatal_with_name ("make_access: setuid");
759#else
760 if (setreuid (user_uid, make_uid) < 0)
761 pfatal_with_name ("make_access: setreuid");
762#endif
763#endif
764
765#ifdef HAVE_SETEGID
766 if (setegid (make_gid) < 0)
767 pfatal_with_name ("make_access: setegid");
768#else
769#ifndef HAVE_SETREGID
770 if (setgid (make_gid) < 0)
771 pfatal_with_name ("make_access: setgid");
772#else
773 if (setregid (user_gid, make_gid) < 0)
774 pfatal_with_name ("make_access: setregid");
775#endif
776#endif
777
778 current_access = make;
779
780 log_access (_("Make access"));
781
782#endif /* GETLOADAVG_PRIVILEGED */
783}
784
785/* Give the process appropriate permissions for a child process.
786 This is like user_access, but you can't get back to make_access. */
787void
788child_access (void)
789{
790#ifdef GETLOADAVG_PRIVILEGED
791
792 if (!access_inited)
793 abort ();
794
795 /* Set both the real and effective UID and GID to the user's.
796 They cannot be changed back to make's. */
797
798#ifndef HAVE_SETREUID
799 if (setuid (user_uid) < 0)
800 pfatal_with_name ("child_access: setuid");
801#else
802 if (setreuid (user_uid, user_uid) < 0)
803 pfatal_with_name ("child_access: setreuid");
804#endif
805
806#ifndef HAVE_SETREGID
807 if (setgid (user_gid) < 0)
808 pfatal_with_name ("child_access: setgid");
809#else
810 if (setregid (user_gid, user_gid) < 0)
811 pfatal_with_name ("child_access: setregid");
812#endif
813
814 log_access (_("Child access"));
815
816#endif /* GETLOADAVG_PRIVILEGED */
817}
818
819
820#ifdef NEED_GET_PATH_MAX
821unsigned int
822get_path_max (void)
823{
824 static unsigned int value;
825
826 if (value == 0)
827 {
828 long int x = pathconf ("/", _PC_PATH_MAX);
829 if (x > 0)
830 value = x;
831 else
832 return MAXPATHLEN;
833 }
834
835 return value;
836}
837#endif
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette