VirtualBox

source: kBuild/vendor/gnumake/2003-11-23/misc.c

Last change on this file was 54, checked in by (none), 21 years ago

This commit was manufactured by cvs2svn to create branch 'GNU'.

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