VirtualBox

source: kBuild/trunk/src/kmk/misc.c@ 2074

Last change on this file since 2074 was 2062, checked in by bird, 16 years ago

kmk: Moved the alloccache code into a separate file because it seems gcc has ends up in some inlining / aliasing trouble in free_dep_chain (alloccache_free is suspected to be inlined) with gcc 4.3.2 on S/390.

  • Property svn:eol-style set to native
File size: 29.4 KB
Line 
1/* Miscellaneous generic support functions for GNU Make.
2Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997,
31998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007 Free Software
4Foundation, Inc.
5This file is part of GNU Make.
6
7GNU Make is free software; you can redistribute it and/or modify it under the
8terms of the GNU General Public License as published by the Free Software
9Foundation; either version 3 of the License, or (at your option) any later
10version.
11
12GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY
13WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
14A PARTICULAR PURPOSE. See the GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public License along with
17this program. If not, see <http://www.gnu.org/licenses/>. */
18
19#include "make.h"
20#include "dep.h"
21#include "debug.h"
22#if defined (CONFIG_WITH_VALUE_LENGTH) || defined (CONFIG_WITH_ALLOC_CACHES)
23# include <assert.h>
24#endif
25#ifdef CONFIG_WITH_PRINT_STATS_SWITCH
26# ifdef __APPLE__
27# include <malloc/malloc.h>
28# endif
29# if defined(__GLIBC__) || defined(HAVE_MALLINFO)
30# include <malloc.h>
31# endif
32#endif
33
34/* All bcopy calls in this file can be replaced by memcpy and save a tick or two. */
35#ifdef CONFIG_WITH_OPTIMIZATION_HACKS
36# undef bcopy
37# if defined(__GNUC__) && defined(CONFIG_WITH_OPTIMIZATION_HACKS)
38# define bcopy(src, dst, size) __builtin_memcpy ((dst), (src), (size))
39# else
40# define bcopy(src, dst, size) memcpy ((dst), (src), (size))
41# endif
42#endif
43
44/* Variadic functions. We go through contortions to allow proper function
45 prototypes for both ANSI and pre-ANSI C compilers, and also for those
46 which support stdarg.h vs. varargs.h, and finally those which have
47 vfprintf(), etc. and those who have _doprnt... or nothing.
48
49 This fancy stuff all came from GNU fileutils, except for the VA_PRINTF and
50 VA_END macros used here since we have multiple print functions. */
51
52#if USE_VARIADIC
53# if HAVE_STDARG_H
54# include <stdarg.h>
55# define VA_START(args, lastarg) va_start(args, lastarg)
56# else
57# include <varargs.h>
58# define VA_START(args, lastarg) va_start(args)
59# endif
60# if HAVE_VPRINTF
61# define VA_PRINTF(fp, lastarg, args) vfprintf((fp), (lastarg), (args))
62# else
63# define VA_PRINTF(fp, lastarg, args) _doprnt((lastarg), (args), (fp))
64# endif
65# define VA_END(args) va_end(args)
66#else
67/* We can't use any variadic interface! */
68# define va_alist a1, a2, a3, a4, a5, a6, a7, a8
69# define va_dcl char *a1, *a2, *a3, *a4, *a5, *a6, *a7, *a8;
70# define VA_START(args, lastarg)
71# define VA_PRINTF(fp, lastarg, args) fprintf((fp), (lastarg), va_alist)
72# define VA_END(args)
73#endif
74
75
76/* Compare strings *S1 and *S2.
77 Return negative if the first is less, positive if it is greater,
78 zero if they are equal. */
79
80int
81alpha_compare (const void *v1, const void *v2)
82{
83 const char *s1 = *((char **)v1);
84 const char *s2 = *((char **)v2);
85
86 if (*s1 != *s2)
87 return *s1 - *s2;
88 return strcmp (s1, s2);
89}
90
91
92/* Discard each backslash-newline combination from LINE.
93 Backslash-backslash-newline combinations become backslash-newlines.
94 This is done by copying the text at LINE into itself. */
95
96#ifndef CONFIG_WITH_VALUE_LENGTH
97void
98collapse_continuations (char *line)
99#else
100char *
101collapse_continuations (char *line, unsigned int linelen)
102#endif
103{
104 register char *in, *out, *p;
105 register int backslash;
106 register unsigned int bs_write;
107
108#ifndef CONFIG_WITH_VALUE_LENGTH
109 in = strchr (line, '\n');
110 if (in == 0)
111 return;
112#else
113 assert (strlen (line) == linelen);
114 in = memchr (line, '\n', linelen);
115 if (in == 0)
116 return line + linelen;
117 if (in == line || in[-1] != '\\')
118 {
119 do
120 {
121 unsigned int off_in = in - line;
122 if (off_in == linelen)
123 return in;
124 in = memchr (in + 1, '\n', linelen - off_in - 1);
125 if (in == 0)
126 return line + linelen;
127 }
128 while (in[-1] != '\\');
129 }
130#endif
131
132 out = in;
133 while (out > line && out[-1] == '\\')
134 --out;
135
136 while (*in != '\0')
137 {
138 /* BS_WRITE gets the number of quoted backslashes at
139 the end just before IN, and BACKSLASH gets nonzero
140 if the next character is quoted. */
141 backslash = 0;
142 bs_write = 0;
143 for (p = in - 1; p >= line && *p == '\\'; --p)
144 {
145 if (backslash)
146 ++bs_write;
147 backslash = !backslash;
148
149 /* It should be impossible to go back this far without exiting,
150 but if we do, we can't get the right answer. */
151 if (in == out - 1)
152 abort ();
153 }
154
155 /* Output the appropriate number of backslashes. */
156 while (bs_write-- > 0)
157 *out++ = '\\';
158
159 /* Skip the newline. */
160 ++in;
161
162 /* If the newline is quoted, discard following whitespace
163 and any preceding whitespace; leave just one space. */
164 if (backslash)
165 {
166 in = next_token (in);
167 while (out > line && isblank ((unsigned char)out[-1]))
168 --out;
169 *out++ = ' ';
170 }
171 else
172 /* If the newline isn't quoted, put it in the output. */
173 *out++ = '\n';
174
175 /* Now copy the following line to the output.
176 Stop when we find backslashes followed by a newline. */
177 while (*in != '\0')
178 if (*in == '\\')
179 {
180 p = in + 1;
181 while (*p == '\\')
182 ++p;
183 if (*p == '\n')
184 {
185 in = p;
186 break;
187 }
188 while (in < p)
189 *out++ = *in++;
190 }
191 else
192 *out++ = *in++;
193 }
194
195 *out = '\0';
196#ifdef CONFIG_WITH_VALUE_LENGTH
197 assert (strchr (line, '\0') == out);
198 return out;
199#endif
200}
201
202
203/* Print N spaces (used in debug for target-depth). */
204
205void
206print_spaces (unsigned int n)
207{
208 while (n-- > 0)
209 putchar (' ');
210}
211
212
213
214/* Return a string whose contents concatenate those of s1, s2, s3.
215 This string lives in static, re-used memory. */
216
217char *
218concat (const char *s1, const char *s2, const char *s3)
219{
220 unsigned int len1, len2, len3;
221 static unsigned int rlen = 0;
222 static char *result = NULL;
223
224 len1 = (s1 && *s1 != '\0') ? strlen (s1) : 0;
225 len2 = (s2 && *s2 != '\0') ? strlen (s2) : 0;
226 len3 = (s3 && *s3 != '\0') ? strlen (s3) : 0;
227
228 if (len1 + len2 + len3 + 1 > rlen)
229 result = xrealloc (result, (rlen = len1 + len2 + len3 + 10));
230
231 if (len1)
232 memcpy (result, s1, len1);
233 if (len2)
234 memcpy (result + len1, s2, len2);
235 if (len3)
236 memcpy (result + len1 + len2, s3, len3);
237
238 result[len1+len2+len3] = '\0';
239
240 return result;
241}
242
243
244/* Print a message on stdout. */
245
246void
247#if HAVE_ANSI_COMPILER && USE_VARIADIC && HAVE_STDARG_H
248message (int prefix, const char *fmt, ...)
249#else
250message (prefix, fmt, va_alist)
251 int prefix;
252 const char *fmt;
253 va_dcl
254#endif
255{
256#if USE_VARIADIC
257 va_list args;
258#endif
259
260 log_working_directory (1);
261
262 if (fmt != 0)
263 {
264 if (prefix)
265 {
266 if (makelevel == 0)
267 printf ("%s: ", program);
268 else
269 printf ("%s[%u]: ", program, makelevel);
270 }
271 VA_START (args, fmt);
272 VA_PRINTF (stdout, fmt, args);
273 VA_END (args);
274 putchar ('\n');
275 }
276
277 fflush (stdout);
278}
279
280/* Print an error message. */
281
282void
283#if HAVE_ANSI_COMPILER && USE_VARIADIC && HAVE_STDARG_H
284error (const struct floc *flocp, const char *fmt, ...)
285#else
286error (flocp, fmt, va_alist)
287 const struct floc *flocp;
288 const char *fmt;
289 va_dcl
290#endif
291{
292#if USE_VARIADIC
293 va_list args;
294#endif
295
296 log_working_directory (1);
297
298 if (flocp && flocp->filenm)
299 fprintf (stderr, "%s:%lu: ", flocp->filenm, flocp->lineno);
300 else if (makelevel == 0)
301 fprintf (stderr, "%s: ", program);
302 else
303 fprintf (stderr, "%s[%u]: ", program, makelevel);
304
305 VA_START(args, fmt);
306 VA_PRINTF (stderr, fmt, args);
307 VA_END (args);
308
309 putc ('\n', stderr);
310 fflush (stderr);
311}
312
313/* Print an error message and exit. */
314
315void
316#if HAVE_ANSI_COMPILER && USE_VARIADIC && HAVE_STDARG_H
317fatal (const struct floc *flocp, const char *fmt, ...)
318#else
319fatal (flocp, fmt, va_alist)
320 const struct floc *flocp;
321 const char *fmt;
322 va_dcl
323#endif
324{
325#if USE_VARIADIC
326 va_list args;
327#endif
328
329 log_working_directory (1);
330
331 if (flocp && flocp->filenm)
332 fprintf (stderr, "%s:%lu: *** ", flocp->filenm, flocp->lineno);
333 else if (makelevel == 0)
334 fprintf (stderr, "%s: *** ", program);
335 else
336 fprintf (stderr, "%s[%u]: *** ", program, makelevel);
337
338 VA_START(args, fmt);
339 VA_PRINTF (stderr, fmt, args);
340 VA_END (args);
341
342 fputs (_(". Stop.\n"), stderr);
343
344 die (2);
345}
346
347#ifndef HAVE_STRERROR
348
349#undef strerror
350
351char *
352strerror (int errnum)
353{
354 extern int errno, sys_nerr;
355#ifndef __DECC
356 extern char *sys_errlist[];
357#endif
358 static char buf[] = "Unknown error 12345678901234567890";
359
360 if (errno < sys_nerr)
361 return sys_errlist[errnum];
362
363 sprintf (buf, _("Unknown error %d"), errnum);
364 return buf;
365}
366#endif
367
368/* Print an error message from errno. */
369
370void
371perror_with_name (const char *str, const char *name)
372{
373 error (NILF, _("%s%s: %s"), str, name, strerror (errno));
374}
375
376/* Print an error message from errno and exit. */
377
378void
379pfatal_with_name (const char *name)
380{
381 fatal (NILF, _("%s: %s"), name, strerror (errno));
382
383 /* NOTREACHED */
384}
385
386
387/* Like malloc but get fatal error if memory is exhausted. */
388/* Don't bother if we're using dmalloc; it provides these for us. */
389
390#if !defined(HAVE_DMALLOC_H) && !defined(ELECTRIC_HEAP) /* bird */
391
392#undef xmalloc
393#undef xrealloc
394#undef xstrdup
395
396void *
397xmalloc (unsigned int size)
398{
399 /* Make sure we don't allocate 0, for pre-ANSI libraries. */
400 void *result = malloc (size ? size : 1);
401 if (result == 0)
402 fatal (NILF, _("virtual memory exhausted"));
403
404#ifdef CONFIG_WITH_MAKE_STATS
405 make_stats_allocations++;
406 if (make_expensive_statistics)
407 make_stats_allocated += SIZE_OF_HEAP_BLOCK (result);
408 else
409 make_stats_allocated += size;
410#endif
411 return result;
412}
413
414
415void *
416xrealloc (void *ptr, unsigned int size)
417{
418 void *result;
419#ifdef CONFIG_WITH_MAKE_STATS
420 if (make_expensive_statistics && ptr != NULL)
421 make_stats_allocated -= SIZE_OF_HEAP_BLOCK (ptr);
422 if (ptr)
423 make_stats_reallocations++;
424 else
425 make_stats_allocations++;
426#endif
427
428 /* Some older implementations of realloc() don't conform to ANSI. */
429 if (! size)
430 size = 1;
431 result = ptr ? realloc (ptr, size) : malloc (size);
432 if (result == 0)
433 fatal (NILF, _("virtual memory exhausted"));
434
435#ifdef CONFIG_WITH_MAKE_STATS
436 if (make_expensive_statistics)
437 make_stats_allocated += SIZE_OF_HEAP_BLOCK (result);
438 else
439 make_stats_allocated += size;
440#endif
441 return result;
442}
443
444
445char *
446xstrdup (const char *ptr)
447{
448 char *result;
449
450#ifdef HAVE_STRDUP
451 result = strdup (ptr);
452#else
453 result = malloc (strlen (ptr) + 1);
454#endif
455
456 if (result == 0)
457 fatal (NILF, _("virtual memory exhausted"));
458
459#ifdef CONFIG_WITH_MAKE_STATS
460 make_stats_allocations++;
461 if (make_expensive_statistics)
462 make_stats_allocated += SIZE_OF_HEAP_BLOCK (result);
463 else
464 make_stats_allocated += strlen (ptr) + 1;
465#endif
466#ifdef HAVE_STRDUP
467 return result;
468#else
469 return strcpy (result, ptr);
470#endif
471}
472
473#endif /* HAVE_DMALLOC_H */
474
475char *
476savestring (const char *str, unsigned int length)
477{
478 char *out = xmalloc (length + 1);
479 if (length > 0)
480 memcpy (out, str, length);
481 out[length] = '\0';
482 return out;
483}
484
485
486
487#ifndef CONFIG_WITH_OPTIMIZATION_HACKS /* This is really a reimplemntation of
488 memchr, only slower. It's been replaced by a macro in the header file. */
489
490/* Limited INDEX:
491 Search through the string STRING, which ends at LIMIT, for the character C.
492 Returns a pointer to the first occurrence, or nil if none is found.
493 Like INDEX except that the string searched ends where specified
494 instead of at the first null. */
495
496char *
497lindex (const char *s, const char *limit, int c)
498{
499 while (s < limit)
500 if (*s++ == c)
501 return (char *)(s - 1);
502
503 return 0;
504}
505#endif /* CONFIG_WITH_OPTIMIZATION_HACKS */
506
507
508/* Return the address of the first whitespace or null in the string S. */
509
510char *
511end_of_token (const char *s)
512{
513#ifdef KMK
514 for (;;)
515 {
516 unsigned char ch0, ch1, ch2, ch3;
517
518 ch0 = *s;
519 if (MY_PREDICT_FALSE(MY_IS_BLANK_OR_EOS(ch0)))
520 return (char *)s;
521 ch1 = s[1];
522 if (MY_PREDICT_FALSE(MY_IS_BLANK_OR_EOS(ch1)))
523 return (char *)s + 1;
524 ch2 = s[2];
525 if (MY_PREDICT_FALSE(MY_IS_BLANK_OR_EOS(ch2)))
526 return (char *)s + 2;
527 ch3 = s[3];
528 if (MY_PREDICT_FALSE(MY_IS_BLANK_OR_EOS(ch3)))
529 return (char *)s + 3;
530
531 s += 4;
532 }
533
534#else
535 while (*s != '\0' && !isblank ((unsigned char)*s))
536 ++s;
537 return (char *)s;
538#endif
539}
540
541#ifdef WINDOWS32
542/*
543 * Same as end_of_token, but take into account a stop character
544 */
545char *
546end_of_token_w32 (const char *s, char stopchar)
547{
548 const char *p = s;
549 int backslash = 0;
550
551 while (*p != '\0' && *p != stopchar
552 && (backslash || !isblank ((unsigned char)*p)))
553 {
554 if (*p++ == '\\')
555 {
556 backslash = !backslash;
557 while (*p == '\\')
558 {
559 backslash = !backslash;
560 ++p;
561 }
562 }
563 else
564 backslash = 0;
565 }
566
567 return (char *)p;
568}
569#endif
570
571/* Return the address of the first nonwhitespace or null in the string S. */
572
573char *
574next_token (const char *s)
575{
576#ifdef KMK
577 for (;;)
578 {
579 unsigned char ch0, ch1, ch2, ch3;
580
581 ch0 = *s;
582 if (MY_PREDICT_FALSE(!MY_IS_BLANK(ch0)))
583 return (char *)s;
584 ch1 = s[1];
585 if (MY_PREDICT_TRUE(!MY_IS_BLANK(ch1)))
586 return (char *)s + 1;
587 ch2 = s[2];
588 if (MY_PREDICT_FALSE(!MY_IS_BLANK(ch2)))
589 return (char *)s + 2;
590 ch3 = s[3];
591 if (MY_PREDICT_TRUE(!MY_IS_BLANK(ch3)))
592 return (char *)s + 3;
593
594 s += 4;
595 }
596
597#else /* !KMK */
598 while (isblank ((unsigned char)*s))
599 ++s;
600 return (char *)s;
601#endif /* !KMK */
602}
603
604/* Find the next token in PTR; return the address of it, and store the length
605 of the token into *LENGTHPTR if LENGTHPTR is not nil. Set *PTR to the end
606 of the token, so this function can be called repeatedly in a loop. */
607
608char *
609find_next_token (const char **ptr, unsigned int *lengthptr)
610{
611#ifdef KMK
612 const char *p = *ptr;
613 const char *e;
614
615 /* skip blanks */
616# if 0 /* a moderate version */
617 for (;; p++)
618 {
619 unsigned char ch = *p;
620 if (!MY_IS_BLANK(ch))
621 {
622 if (!ch)
623 return NULL;
624 break;
625 }
626 }
627
628# else /* (too) big unroll */
629 for (;; p += 4)
630 {
631 unsigned char ch0, ch1, ch2, ch3;
632
633 ch0 = *p;
634 if (MY_PREDICT_FALSE(!MY_IS_BLANK(ch0)))
635 {
636 if (!ch0)
637 return NULL;
638 break;
639 }
640 ch1 = p[1];
641 if (MY_PREDICT_TRUE(!MY_IS_BLANK(ch1)))
642 {
643 if (!ch1)
644 return NULL;
645 p += 1;
646 break;
647 }
648 ch2 = p[2];
649 if (MY_PREDICT_FALSE(!MY_IS_BLANK(ch2)))
650 {
651 if (!ch2)
652 return NULL;
653 p += 2;
654 break;
655 }
656 ch3 = p[3];
657 if (MY_PREDICT_TRUE(!MY_IS_BLANK(ch3)))
658 {
659 if (!ch3)
660 return NULL;
661 p += 3;
662 break;
663 }
664 }
665# endif
666
667 /* skip ahead until EOS or blanks. */
668# if 0 /* a moderate version */
669 for (e = p + 1; ; e++)
670 {
671 unsigned char ch = *e;
672 if (MY_PREDICT_FALSE(MY_IS_BLANK_OR_EOS(ch)))
673 break;
674 }
675# else /* (too) big unroll */
676 for (e = p + 1; ; e += 4)
677 {
678 unsigned char ch0, ch1, ch2, ch3;
679
680 ch0 = *e;
681 if (MY_PREDICT_FALSE(MY_IS_BLANK_OR_EOS(ch0)))
682 break;
683 ch1 = e[1];
684 if (MY_PREDICT_FALSE(MY_IS_BLANK_OR_EOS(ch1)))
685 {
686 e += 1;
687 break;
688 }
689 ch2 = e[2];
690 if (MY_PREDICT_FALSE(MY_IS_BLANK_OR_EOS(ch2)))
691 {
692 e += 2;
693 break;
694 }
695 ch3 = e[3];
696 if (MY_PREDICT_FALSE(MY_IS_BLANK_OR_EOS(ch3)))
697 {
698 e += 3;
699 break;
700 }
701 }
702# endif
703 *ptr = e;
704
705 if (lengthptr != 0)
706 *lengthptr = e - p;
707
708 return (char *)p;
709
710#else
711 const char *p = next_token (*ptr);
712
713 if (*p == '\0')
714 return 0;
715
716 *ptr = end_of_token (p);
717 if (lengthptr != 0)
718 *lengthptr = *ptr - p;
719
720 return (char *)p;
721#endif
722}
723
724
725
726/* Allocate a new `struct dep' with all fields initialized to 0. */
727
728struct dep *
729alloc_dep ()
730{
731#ifndef CONFIG_WITH_ALLOC_CACHES
732 struct dep *d = xmalloc (sizeof (struct dep));
733 memset (d, '\0', sizeof (struct dep));
734 return d;
735#else
736 return (struct dep *) alloccache_calloc (&dep_cache);
737#endif
738}
739
740
741/* Free `struct dep' along with `name' and `stem'. */
742
743void
744free_dep (struct dep *d)
745{
746#ifndef CONFIG_WITH_ALLOC_CACHES
747 free (d);
748#else
749 alloccache_free (&dep_cache, d);
750#endif
751}
752
753/* Copy a chain of `struct dep', making a new chain
754 with the same contents as the old one. */
755
756struct dep *
757copy_dep_chain (const struct dep *d)
758{
759 struct dep *firstnew = 0;
760 struct dep *lastnew = 0;
761
762 while (d != 0)
763 {
764#ifndef CONFIG_WITH_ALLOC_CACHES
765 struct dep *c = xmalloc (sizeof (struct dep));
766#else
767 struct dep *c = (struct dep *) alloccache_alloc (&dep_cache);
768#endif
769 memcpy (c, d, sizeof (struct dep));
770
771 c->next = 0;
772 if (firstnew == 0)
773 firstnew = lastnew = c;
774 else
775 lastnew = lastnew->next = c;
776
777 d = d->next;
778 }
779
780 return firstnew;
781}
782
783/* Free a chain of 'struct dep'. */
784
785void
786free_dep_chain (struct dep *d)
787{
788 while (d != 0)
789 {
790 struct dep *df = d;
791 d = d->next;
792#ifndef CONFIG_WITH_ALLOC_CACHES
793 free_dep (df);
794#else
795 alloccache_free (&dep_cache, df);
796#endif
797 }
798}
799
800/* Free a chain of struct nameseq.
801 For struct dep chains use free_dep_chain. */
802
803void
804free_ns_chain (struct nameseq *ns)
805{
806 while (ns != 0)
807 {
808 struct nameseq *t = ns;
809 ns = ns->next;
810#ifndef CONFIG_WITH_ALLOC_CACHES
811 free (t);
812#else
813 alloccache_free (&nameseq_cache, t);
814#endif
815 }
816}
817
818
819
820#if !HAVE_STRCASECMP && !HAVE_STRICMP && !HAVE_STRCMPI
821
822/* If we don't have strcasecmp() (from POSIX), or anything that can substitute
823 for it, define our own version. */
824
825int
826strcasecmp (const char *s1, const char *s2)
827{
828 while (1)
829 {
830 int c1 = (int) *(s1++);
831 int c2 = (int) *(s2++);
832
833 if (isalpha (c1))
834 c1 = tolower (c1);
835 if (isalpha (c2))
836 c2 = tolower (c2);
837
838 if (c1 != '\0' && c1 == c2)
839 continue;
840
841 return (c1 - c2);
842 }
843}
844#endif
845
846
847#ifdef GETLOADAVG_PRIVILEGED
848
849#ifdef POSIX
850
851/* Hopefully if a system says it's POSIX.1 and has the setuid and setgid
852 functions, they work as POSIX.1 says. Some systems (Alpha OSF/1 1.2,
853 for example) which claim to be POSIX.1 also have the BSD setreuid and
854 setregid functions, but they don't work as in BSD and only the POSIX.1
855 way works. */
856
857#undef HAVE_SETREUID
858#undef HAVE_SETREGID
859
860#else /* Not POSIX. */
861
862/* Some POSIX.1 systems have the seteuid and setegid functions. In a
863 POSIX-like system, they are the best thing to use. However, some
864 non-POSIX systems have them too but they do not work in the POSIX style
865 and we must use setreuid and setregid instead. */
866
867#undef HAVE_SETEUID
868#undef HAVE_SETEGID
869
870#endif /* POSIX. */
871
872#ifndef HAVE_UNISTD_H
873extern int getuid (), getgid (), geteuid (), getegid ();
874extern int setuid (), setgid ();
875#ifdef HAVE_SETEUID
876extern int seteuid ();
877#else
878#ifdef HAVE_SETREUID
879extern int setreuid ();
880#endif /* Have setreuid. */
881#endif /* Have seteuid. */
882#ifdef HAVE_SETEGID
883extern int setegid ();
884#else
885#ifdef HAVE_SETREGID
886extern int setregid ();
887#endif /* Have setregid. */
888#endif /* Have setegid. */
889#endif /* No <unistd.h>. */
890
891/* Keep track of the user and group IDs for user- and make- access. */
892static int user_uid = -1, user_gid = -1, make_uid = -1, make_gid = -1;
893#define access_inited (user_uid != -1)
894static enum { make, user } current_access;
895
896
897/* Under -d, write a message describing the current IDs. */
898
899static void
900log_access (const char *flavor)
901{
902 if (! ISDB (DB_JOBS))
903 return;
904
905 /* All the other debugging messages go to stdout,
906 but we write this one to stderr because it might be
907 run in a child fork whose stdout is piped. */
908
909 fprintf (stderr, _("%s: user %lu (real %lu), group %lu (real %lu)\n"),
910 flavor, (unsigned long) geteuid (), (unsigned long) getuid (),
911 (unsigned long) getegid (), (unsigned long) getgid ());
912 fflush (stderr);
913}
914
915
916static void
917init_access (void)
918{
919#ifndef VMS
920 user_uid = getuid ();
921 user_gid = getgid ();
922
923 make_uid = geteuid ();
924 make_gid = getegid ();
925
926 /* Do these ever fail? */
927 if (user_uid == -1 || user_gid == -1 || make_uid == -1 || make_gid == -1)
928 pfatal_with_name ("get{e}[gu]id");
929
930 log_access (_("Initialized access"));
931
932 current_access = make;
933#endif
934}
935
936#endif /* GETLOADAVG_PRIVILEGED */
937
938/* Give the process appropriate permissions for access to
939 user data (i.e., to stat files, or to spawn a child process). */
940void
941user_access (void)
942{
943#ifdef GETLOADAVG_PRIVILEGED
944
945 if (!access_inited)
946 init_access ();
947
948 if (current_access == user)
949 return;
950
951 /* We are in "make access" mode. This means that the effective user and
952 group IDs are those of make (if it was installed setuid or setgid).
953 We now want to set the effective user and group IDs to the real IDs,
954 which are the IDs of the process that exec'd make. */
955
956#ifdef HAVE_SETEUID
957
958 /* Modern systems have the seteuid/setegid calls which set only the
959 effective IDs, which is ideal. */
960
961 if (seteuid (user_uid) < 0)
962 pfatal_with_name ("user_access: seteuid");
963
964#else /* Not HAVE_SETEUID. */
965
966#ifndef HAVE_SETREUID
967
968 /* System V has only the setuid/setgid calls to set user/group IDs.
969 There is an effective ID, which can be set by setuid/setgid.
970 It can be set (unless you are root) only to either what it already is
971 (returned by geteuid/getegid, now in make_uid/make_gid),
972 the real ID (return by getuid/getgid, now in user_uid/user_gid),
973 or the saved set ID (what the effective ID was before this set-ID
974 executable (make) was exec'd). */
975
976 if (setuid (user_uid) < 0)
977 pfatal_with_name ("user_access: setuid");
978
979#else /* HAVE_SETREUID. */
980
981 /* In 4BSD, the setreuid/setregid calls set both the real and effective IDs.
982 They may be set to themselves or each other. So you have two alternatives
983 at any one time. If you use setuid/setgid, the effective will be set to
984 the real, leaving only one alternative. Using setreuid/setregid, however,
985 you can toggle between your two alternatives by swapping the values in a
986 single setreuid or setregid call. */
987
988 if (setreuid (make_uid, user_uid) < 0)
989 pfatal_with_name ("user_access: setreuid");
990
991#endif /* Not HAVE_SETREUID. */
992#endif /* HAVE_SETEUID. */
993
994#ifdef HAVE_SETEGID
995 if (setegid (user_gid) < 0)
996 pfatal_with_name ("user_access: setegid");
997#else
998#ifndef HAVE_SETREGID
999 if (setgid (user_gid) < 0)
1000 pfatal_with_name ("user_access: setgid");
1001#else
1002 if (setregid (make_gid, user_gid) < 0)
1003 pfatal_with_name ("user_access: setregid");
1004#endif
1005#endif
1006
1007 current_access = user;
1008
1009 log_access (_("User access"));
1010
1011#endif /* GETLOADAVG_PRIVILEGED */
1012}
1013
1014/* Give the process appropriate permissions for access to
1015 make data (i.e., the load average). */
1016void
1017make_access (void)
1018{
1019#ifdef GETLOADAVG_PRIVILEGED
1020
1021 if (!access_inited)
1022 init_access ();
1023
1024 if (current_access == make)
1025 return;
1026
1027 /* See comments in user_access, above. */
1028
1029#ifdef HAVE_SETEUID
1030 if (seteuid (make_uid) < 0)
1031 pfatal_with_name ("make_access: seteuid");
1032#else
1033#ifndef HAVE_SETREUID
1034 if (setuid (make_uid) < 0)
1035 pfatal_with_name ("make_access: setuid");
1036#else
1037 if (setreuid (user_uid, make_uid) < 0)
1038 pfatal_with_name ("make_access: setreuid");
1039#endif
1040#endif
1041
1042#ifdef HAVE_SETEGID
1043 if (setegid (make_gid) < 0)
1044 pfatal_with_name ("make_access: setegid");
1045#else
1046#ifndef HAVE_SETREGID
1047 if (setgid (make_gid) < 0)
1048 pfatal_with_name ("make_access: setgid");
1049#else
1050 if (setregid (user_gid, make_gid) < 0)
1051 pfatal_with_name ("make_access: setregid");
1052#endif
1053#endif
1054
1055 current_access = make;
1056
1057 log_access (_("Make access"));
1058
1059#endif /* GETLOADAVG_PRIVILEGED */
1060}
1061
1062/* Give the process appropriate permissions for a child process.
1063 This is like user_access, but you can't get back to make_access. */
1064void
1065child_access (void)
1066{
1067#ifdef GETLOADAVG_PRIVILEGED
1068
1069 if (!access_inited)
1070 abort ();
1071
1072 /* Set both the real and effective UID and GID to the user's.
1073 They cannot be changed back to make's. */
1074
1075#ifndef HAVE_SETREUID
1076 if (setuid (user_uid) < 0)
1077 pfatal_with_name ("child_access: setuid");
1078#else
1079 if (setreuid (user_uid, user_uid) < 0)
1080 pfatal_with_name ("child_access: setreuid");
1081#endif
1082
1083#ifndef HAVE_SETREGID
1084 if (setgid (user_gid) < 0)
1085 pfatal_with_name ("child_access: setgid");
1086#else
1087 if (setregid (user_gid, user_gid) < 0)
1088 pfatal_with_name ("child_access: setregid");
1089#endif
1090
1091 log_access (_("Child access"));
1092
1093#endif /* GETLOADAVG_PRIVILEGED */
1094}
1095
1096
1097#ifdef NEED_GET_PATH_MAX
1098unsigned int
1099get_path_max (void)
1100{
1101 static unsigned int value;
1102
1103 if (value == 0)
1104 {
1105 long int x = pathconf ("/", _PC_PATH_MAX);
1106 if (x > 0)
1107 value = x;
1108 else
1109 return MAXPATHLEN;
1110 }
1111
1112 return value;
1113}
1114#endif
1115
1116
1117
1118/* This code is stolen from gnulib.
1119 If/when we abandon the requirement to work with K&R compilers, we can
1120 remove this (and perhaps other parts of GNU make!) and migrate to using
1121 gnulib directly.
1122
1123 This is called only through atexit(), which means die() has already been
1124 invoked. So, call exit() here directly. Apparently that works...?
1125*/
1126
1127/* Close standard output, exiting with status 'exit_failure' on failure.
1128 If a program writes *anything* to stdout, that program should close
1129 stdout and make sure that it succeeds before exiting. Otherwise,
1130 suppose that you go to the extreme of checking the return status
1131 of every function that does an explicit write to stdout. The last
1132 printf can succeed in writing to the internal stream buffer, and yet
1133 the fclose(stdout) could still fail (due e.g., to a disk full error)
1134 when it tries to write out that buffered data. Thus, you would be
1135 left with an incomplete output file and the offending program would
1136 exit successfully. Even calling fflush is not always sufficient,
1137 since some file systems (NFS and CODA) buffer written/flushed data
1138 until an actual close call.
1139
1140 Besides, it's wasteful to check the return value from every call
1141 that writes to stdout -- just let the internal stream state record
1142 the failure. That's what the ferror test is checking below.
1143
1144 It's important to detect such failures and exit nonzero because many
1145 tools (most notably `make' and other build-management systems) depend
1146 on being able to detect failure in other tools via their exit status. */
1147
1148void
1149close_stdout (void)
1150{
1151 int prev_fail = ferror (stdout);
1152 int fclose_fail = fclose (stdout);
1153
1154 if (prev_fail || fclose_fail)
1155 {
1156 if (fclose_fail)
1157 error (NILF, _("write error: %s"), strerror (errno));
1158 else
1159 error (NILF, _("write error"));
1160 exit (EXIT_FAILURE);
1161 }
1162}
1163
1164#ifdef CONFIG_WITH_PRINT_STATS_SWITCH
1165/* Print heap statistics if supported by the platform. */
1166void print_heap_stats (void)
1167{
1168 /* Darwin / Mac OS X */
1169# ifdef __APPLE__
1170 malloc_statistics_t s;
1171
1172 malloc_zone_statistics (NULL, &s);
1173 printf (_("\n# CRT Heap: %zu bytes in use, in %u blocks, avg %zu bytes/block\n"),
1174 s.size_in_use, s.blocks_in_use, s.size_in_use / s.blocks_in_use);
1175 printf (_("# %zu bytes max in use (high water mark)\n"),
1176 s.max_size_in_use);
1177 printf (_("# %zu bytes reserved, %zu bytes free (estimate)\n"),
1178 s.size_allocated, s.size_allocated - s.size_in_use);
1179# endif /* __APPLE__ */
1180
1181 /* MSC / Windows */
1182# ifdef _MSC_VER
1183 unsigned int blocks_used = 0;
1184 unsigned int bytes_used = 0;
1185 unsigned int blocks_avail = 0;
1186 unsigned int bytes_avail = 0;
1187 _HEAPINFO hinfo;
1188
1189 memset (&hinfo, '\0', sizeof (hinfo));
1190 while (_heapwalk(&hinfo) == _HEAPOK)
1191 {
1192 if (hinfo._useflag == _USEDENTRY)
1193 {
1194 blocks_used++;
1195 bytes_used += hinfo._size;
1196 }
1197 else
1198 {
1199 blocks_avail++;
1200 bytes_avail += hinfo._size;
1201 }
1202 }
1203
1204 printf (_("\n# CRT Heap: %u bytes in use, in %u blocks, avg %u bytes/block\n"),
1205 bytes_used, blocks_used, bytes_used / blocks_used);
1206 printf (_("# %u bytes avail, in %u blocks, avg %u bytes/block\n"),
1207 bytes_avail, blocks_avail, bytes_avail / blocks_avail);
1208# endif /* _MSC_VER */
1209
1210 /* Darwin Libc sources indicates that something like this may be
1211 found in GLIBC, however, it's not in any current one... */
1212# if 0 /* ??? */
1213 struct mstats m;
1214
1215 m = mstats();
1216 printf (_("\n# CRT Heap: %zu blocks / %zu bytes in use, %zu blocks / %zu bytes free\n"),
1217 m.chunks_used, m.bytes_used, m.chunks_free, m.bytes_free);
1218 printf (_("# %zu bytes reserved\n"),
1219 m.bytes_total);
1220# endif /* ??? */
1221
1222 /* XVID2/XPG mallinfo (displayed per GLIBC documentation). */
1223# if defined(__GLIBC__) || defined(HAVE_MALLINFO)
1224 struct mallinfo m;
1225
1226 m = mallinfo();
1227 printf (_("\n# CRT Heap: %d bytes in use, %d bytes free\n"),
1228 m.uordblks, m.fordblks);
1229
1230 printf (_("# # free chunks=%d, # fastbin blocks=%d\n"),
1231 m.ordblks, m.smblks);
1232 printf (_("# # mapped regions=%d, space in mapped regions=%d\n"),
1233 m.hblks, m.hblkhd);
1234 printf (_("# non-mapped space allocated from system=%d\n"),
1235 m.arena);
1236 printf (_("# maximum total allocated space=%d\n"),
1237 m.usmblks);
1238 printf (_("# top-most releasable space=%d\n"),
1239 m.keepcost);
1240# endif /* __GLIBC__ || HAVE_MALLINFO */
1241
1242# ifdef CONFIG_WITH_MAKE_STATS
1243 printf(_("# %lu malloc calls, %lu realloc calls\n"),
1244 make_stats_allocations, make_stats_reallocations);
1245 printf(_("# %lu MBs alloc sum, not counting freed, add pinch of salt\n"), /* XXX: better wording */
1246 make_stats_allocated / (1024*1024));
1247# endif
1248
1249 /* XXX: windows */
1250}
1251#endif /* CONFIG_WITH_PRINT_STATS_SWITCH */
1252
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