VirtualBox

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

Last change on this file since 2014 was 1993, checked in by bird, 16 years ago

Merged in current GNU Make code (CVS from 2008-10-28). Ref #55.

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