VirtualBox

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

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

kmk: new function - eval-opt-var

  • Property svn:eol-style set to native
File size: 33.6 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 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 2, or (at your option) any later version.
10
11GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY
12WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
13A PARTICULAR PURPOSE. See the GNU General Public License for more details.
14
15You should have received a copy of the GNU General Public License along with
16GNU Make; see the file COPYING. If not, write to the Free Software
17Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */
18
19#include "make.h"
20#include "dep.h"
21#include "debug.h"
22#ifdef CONFIG_WITH_VALUE_LENGTH
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#ifdef CONFIG_WITH_MAKE_STATS
401 make_stats_allocations++;
402 if (make_expensive_statistics)
403 {
404 unsigned int actual_size = SIZE_OF_HEAP_BLOCK (result);
405 make_stats_allocated += actual_size;
406 make_stats_allocated_sum += actual_size;
407 }
408#endif
409 return result;
410}
411
412
413void *
414xrealloc (void *ptr, unsigned int size)
415{
416 void *result;
417#ifdef CONFIG_WITH_MAKE_STATS
418 if (make_expensive_statistics && ptr != NULL)
419 {
420 unsigned int actual_size = SIZE_OF_HEAP_BLOCK (ptr);
421 make_stats_allocated -= actual_size;
422 make_stats_allocated_sum -= actual_size;
423 }
424#endif
425
426 /* Some older implementations of realloc() don't conform to ANSI. */
427 if (! size)
428 size = 1;
429 result = ptr ? realloc (ptr, size) : malloc (size);
430 if (result == 0)
431 fatal (NILF, _("virtual memory exhausted"));
432#ifdef CONFIG_WITH_MAKE_STATS
433 if (!ptr)
434 make_stats_allocations++;
435 if (make_expensive_statistics)
436 {
437 unsigned int actual_size = SIZE_OF_HEAP_BLOCK (result);
438 make_stats_allocated += actual_size;
439 make_stats_allocated_sum += actual_size;
440 }
441#endif
442 return result;
443}
444
445
446char *
447xstrdup (const char *ptr)
448{
449 char *result;
450
451#ifdef HAVE_STRDUP
452 result = strdup (ptr);
453#else
454 result = malloc (strlen (ptr) + 1);
455#endif
456
457 if (result == 0)
458 fatal (NILF, _("virtual memory exhausted"));
459
460#ifdef CONFIG_WITH_MAKE_STATS
461 make_stats_allocations++;
462 if (make_expensive_statistics)
463 {
464 unsigned int actual_size = SIZE_OF_HEAP_BLOCK (result);
465 make_stats_allocated += actual_size;
466 make_stats_allocated_sum += actual_size;
467 }
468#endif
469#ifdef HAVE_STRDUP
470 return result;
471#else
472 return strcpy (result, ptr);
473#endif
474}
475
476#endif /* HAVE_DMALLOC_H */
477
478char *
479savestring (const char *str, unsigned int length)
480{
481 char *out = xmalloc (length + 1);
482 if (length > 0)
483 memcpy (out, str, length);
484 out[length] = '\0';
485 return out;
486}
487
488
489
490#ifndef CONFIG_WITH_OPTIMIZATION_HACKS /* This is really a reimplemntation of
491 memchr, only slower. It's been replaced by a macro in the header file. */
492
493/* Limited INDEX:
494 Search through the string STRING, which ends at LIMIT, for the character C.
495 Returns a pointer to the first occurrence, or nil if none is found.
496 Like INDEX except that the string searched ends where specified
497 instead of at the first null. */
498
499char *
500lindex (const char *s, const char *limit, int c)
501{
502 while (s < limit)
503 if (*s++ == c)
504 return (char *)(s - 1);
505
506 return 0;
507}
508#endif /* CONFIG_WITH_OPTIMIZATION_HACKS */
509
510
511/* Return the address of the first whitespace or null in the string S. */
512
513char *
514end_of_token (const char *s)
515{
516#ifdef KMK
517 for (;;)
518 {
519 unsigned char ch0, ch1, ch2, ch3;
520
521 ch0 = *s;
522 if (MY_PREDICT_FALSE(MY_IS_BLANK_OR_EOS(ch0)))
523 return (char *)s;
524 ch1 = s[1];
525 if (MY_PREDICT_FALSE(MY_IS_BLANK_OR_EOS(ch1)))
526 return (char *)s + 1;
527 ch2 = s[2];
528 if (MY_PREDICT_FALSE(MY_IS_BLANK_OR_EOS(ch2)))
529 return (char *)s + 2;
530 ch3 = s[3];
531 if (MY_PREDICT_FALSE(MY_IS_BLANK_OR_EOS(ch3)))
532 return (char *)s + 3;
533
534 s += 4;
535 }
536
537#else
538 while (*s != '\0' && !isblank ((unsigned char)*s))
539 ++s;
540 return (char *)s;
541#endif
542}
543
544#ifdef WINDOWS32
545/*
546 * Same as end_of_token, but take into account a stop character
547 */
548char *
549end_of_token_w32 (const char *s, char stopchar)
550{
551 const char *p = s;
552 int backslash = 0;
553
554 while (*p != '\0' && *p != stopchar
555 && (backslash || !isblank ((unsigned char)*p)))
556 {
557 if (*p++ == '\\')
558 {
559 backslash = !backslash;
560 while (*p == '\\')
561 {
562 backslash = !backslash;
563 ++p;
564 }
565 }
566 else
567 backslash = 0;
568 }
569
570 return (char *)p;
571}
572#endif
573
574/* Return the address of the first nonwhitespace or null in the string S. */
575
576char *
577next_token (const char *s)
578{
579#ifdef KMK
580 for (;;)
581 {
582 unsigned char ch0, ch1, ch2, ch3;
583
584 ch0 = *s;
585 if (MY_PREDICT_FALSE(!MY_IS_BLANK(ch0)))
586 return (char *)s;
587 ch1 = s[1];
588 if (MY_PREDICT_TRUE(!MY_IS_BLANK(ch1)))
589 return (char *)s + 1;
590 ch2 = s[2];
591 if (MY_PREDICT_FALSE(!MY_IS_BLANK(ch2)))
592 return (char *)s + 2;
593 ch3 = s[3];
594 if (MY_PREDICT_TRUE(!MY_IS_BLANK(ch3)))
595 return (char *)s + 3;
596
597 s += 4;
598 }
599
600#else /* !KMK */
601 while (isblank ((unsigned char)*s))
602 ++s;
603 return (char *)s;
604#endif /* !KMK */
605}
606
607/* Find the next token in PTR; return the address of it, and store the length
608 of the token into *LENGTHPTR if LENGTHPTR is not nil. Set *PTR to the end
609 of the token, so this function can be called repeatedly in a loop. */
610
611char *
612find_next_token (const char **ptr, unsigned int *lengthptr)
613{
614#ifdef KMK
615 const char *p = *ptr;
616 const char *e;
617
618 /* skip blanks */
619# if 0 /* a moderate version */
620 for (;; p++)
621 {
622 unsigned char ch = *p;
623 if (!MY_IS_BLANK(ch))
624 {
625 if (!ch)
626 return NULL;
627 break;
628 }
629 }
630
631# else /* (too) big unroll */
632 for (;; p += 4)
633 {
634 unsigned char ch0, ch1, ch2, ch3;
635
636 ch0 = *p;
637 if (MY_PREDICT_FALSE(!MY_IS_BLANK(ch0)))
638 {
639 if (!ch0)
640 return NULL;
641 break;
642 }
643 ch1 = p[1];
644 if (MY_PREDICT_TRUE(!MY_IS_BLANK(ch1)))
645 {
646 if (!ch1)
647 return NULL;
648 p += 1;
649 break;
650 }
651 ch2 = p[2];
652 if (MY_PREDICT_FALSE(!MY_IS_BLANK(ch2)))
653 {
654 if (!ch2)
655 return NULL;
656 p += 2;
657 break;
658 }
659 ch3 = p[3];
660 if (MY_PREDICT_TRUE(!MY_IS_BLANK(ch3)))
661 {
662 if (!ch3)
663 return NULL;
664 p += 3;
665 break;
666 }
667 }
668# endif
669
670 /* skip ahead until EOS or blanks. */
671# if 0 /* a moderate version */
672 for (e = p + 1; ; e++)
673 {
674 unsigned char ch = *e;
675 if (MY_PREDICT_FALSE(MY_IS_BLANK_OR_EOS(ch)))
676 break;
677 }
678# else /* (too) big unroll */
679 for (e = p + 1; ; e += 4)
680 {
681 unsigned char ch0, ch1, ch2, ch3;
682
683 ch0 = *e;
684 if (MY_PREDICT_FALSE(MY_IS_BLANK_OR_EOS(ch0)))
685 break;
686 ch1 = e[1];
687 if (MY_PREDICT_FALSE(MY_IS_BLANK_OR_EOS(ch1)))
688 {
689 e += 1;
690 break;
691 }
692 ch2 = e[2];
693 if (MY_PREDICT_FALSE(MY_IS_BLANK_OR_EOS(ch2)))
694 {
695 e += 2;
696 break;
697 }
698 ch3 = e[3];
699 if (MY_PREDICT_FALSE(MY_IS_BLANK_OR_EOS(ch3)))
700 {
701 e += 3;
702 break;
703 }
704 }
705# endif
706 *ptr = e;
707
708 if (lengthptr != 0)
709 *lengthptr = e - p;
710
711 return (char *)p;
712
713#else
714 const char *p = next_token (*ptr);
715
716 if (*p == '\0')
717 return 0;
718
719 *ptr = end_of_token (p);
720 if (lengthptr != 0)
721 *lengthptr = *ptr - p;
722
723 return (char *)p;
724#endif
725}
726
727
728
729/* Allocate a new `struct dep' with all fields initialized to 0. */
730
731struct dep *
732alloc_dep ()
733{
734#ifndef CONFIG_WITH_ALLOC_CACHES
735 struct dep *d = xmalloc (sizeof (struct dep));
736 memset (d, '\0', sizeof (struct dep));
737 return d;
738#else
739 return (struct dep *) alloccache_calloc (&dep_cache);
740#endif
741}
742
743
744/* Free `struct dep' along with `name' and `stem'. */
745
746void
747free_dep (struct dep *d)
748{
749#ifndef CONFIG_WITH_ALLOC_CACHES
750 free (d);
751#else
752 alloccache_free (&dep_cache, d);
753#endif
754}
755
756/* Copy a chain of `struct dep', making a new chain
757 with the same contents as the old one. */
758
759struct dep *
760copy_dep_chain (const struct dep *d)
761{
762 struct dep *firstnew = 0;
763 struct dep *lastnew = 0;
764
765 while (d != 0)
766 {
767#ifndef CONFIG_WITH_ALLOC_CACHES
768 struct dep *c = xmalloc (sizeof (struct dep));
769#else
770 struct dep *c = (struct dep *) alloccache_alloc (&dep_cache);
771#endif
772 memcpy (c, d, sizeof (struct dep));
773
774 c->next = 0;
775 if (firstnew == 0)
776 firstnew = lastnew = c;
777 else
778 lastnew = lastnew->next = c;
779
780 d = d->next;
781 }
782
783 return firstnew;
784}
785
786/* Free a chain of 'struct dep'. */
787
788void
789free_dep_chain (struct dep *d)
790{
791 while (d != 0)
792 {
793 struct dep *df = d;
794 d = d->next;
795#ifndef CONFIG_WITH_ALLOC_CACHES
796 free_dep (df);
797#else
798 alloccache_free (&dep_cache, df);
799#endif
800 }
801}
802
803/* Free a chain of struct nameseq.
804 For struct dep chains use free_dep_chain. */
805
806void
807free_ns_chain (struct nameseq *ns)
808{
809 while (ns != 0)
810 {
811 struct nameseq *t = ns;
812 ns = ns->next;
813#ifndef CONFIG_WITH_ALLOC_CACHES
814 free (t);
815#else
816 alloccache_free (&nameseq_cache, t);
817#endif
818 }
819}
820
821
822
823#if !HAVE_STRCASECMP && !HAVE_STRICMP && !HAVE_STRCMPI
824
825/* If we don't have strcasecmp() (from POSIX), or anything that can substitute
826 for it, define our own version. */
827
828int
829strcasecmp (const char *s1, const char *s2)
830{
831 while (1)
832 {
833 int c1 = (int) *(s1++);
834 int c2 = (int) *(s2++);
835
836 if (isalpha (c1))
837 c1 = tolower (c1);
838 if (isalpha (c2))
839 c2 = tolower (c2);
840
841 if (c1 != '\0' && c1 == c2)
842 continue;
843
844 return (c1 - c2);
845 }
846}
847#endif
848
849
850#ifdef GETLOADAVG_PRIVILEGED
851
852#ifdef POSIX
853
854/* Hopefully if a system says it's POSIX.1 and has the setuid and setgid
855 functions, they work as POSIX.1 says. Some systems (Alpha OSF/1 1.2,
856 for example) which claim to be POSIX.1 also have the BSD setreuid and
857 setregid functions, but they don't work as in BSD and only the POSIX.1
858 way works. */
859
860#undef HAVE_SETREUID
861#undef HAVE_SETREGID
862
863#else /* Not POSIX. */
864
865/* Some POSIX.1 systems have the seteuid and setegid functions. In a
866 POSIX-like system, they are the best thing to use. However, some
867 non-POSIX systems have them too but they do not work in the POSIX style
868 and we must use setreuid and setregid instead. */
869
870#undef HAVE_SETEUID
871#undef HAVE_SETEGID
872
873#endif /* POSIX. */
874
875#ifndef HAVE_UNISTD_H
876extern int getuid (), getgid (), geteuid (), getegid ();
877extern int setuid (), setgid ();
878#ifdef HAVE_SETEUID
879extern int seteuid ();
880#else
881#ifdef HAVE_SETREUID
882extern int setreuid ();
883#endif /* Have setreuid. */
884#endif /* Have seteuid. */
885#ifdef HAVE_SETEGID
886extern int setegid ();
887#else
888#ifdef HAVE_SETREGID
889extern int setregid ();
890#endif /* Have setregid. */
891#endif /* Have setegid. */
892#endif /* No <unistd.h>. */
893
894/* Keep track of the user and group IDs for user- and make- access. */
895static int user_uid = -1, user_gid = -1, make_uid = -1, make_gid = -1;
896#define access_inited (user_uid != -1)
897static enum { make, user } current_access;
898
899
900/* Under -d, write a message describing the current IDs. */
901
902static void
903log_access (const char *flavor)
904{
905 if (! ISDB (DB_JOBS))
906 return;
907
908 /* All the other debugging messages go to stdout,
909 but we write this one to stderr because it might be
910 run in a child fork whose stdout is piped. */
911
912 fprintf (stderr, _("%s: user %lu (real %lu), group %lu (real %lu)\n"),
913 flavor, (unsigned long) geteuid (), (unsigned long) getuid (),
914 (unsigned long) getegid (), (unsigned long) getgid ());
915 fflush (stderr);
916}
917
918
919static void
920init_access (void)
921{
922#ifndef VMS
923 user_uid = getuid ();
924 user_gid = getgid ();
925
926 make_uid = geteuid ();
927 make_gid = getegid ();
928
929 /* Do these ever fail? */
930 if (user_uid == -1 || user_gid == -1 || make_uid == -1 || make_gid == -1)
931 pfatal_with_name ("get{e}[gu]id");
932
933 log_access (_("Initialized access"));
934
935 current_access = make;
936#endif
937}
938
939#endif /* GETLOADAVG_PRIVILEGED */
940
941/* Give the process appropriate permissions for access to
942 user data (i.e., to stat files, or to spawn a child process). */
943void
944user_access (void)
945{
946#ifdef GETLOADAVG_PRIVILEGED
947
948 if (!access_inited)
949 init_access ();
950
951 if (current_access == user)
952 return;
953
954 /* We are in "make access" mode. This means that the effective user and
955 group IDs are those of make (if it was installed setuid or setgid).
956 We now want to set the effective user and group IDs to the real IDs,
957 which are the IDs of the process that exec'd make. */
958
959#ifdef HAVE_SETEUID
960
961 /* Modern systems have the seteuid/setegid calls which set only the
962 effective IDs, which is ideal. */
963
964 if (seteuid (user_uid) < 0)
965 pfatal_with_name ("user_access: seteuid");
966
967#else /* Not HAVE_SETEUID. */
968
969#ifndef HAVE_SETREUID
970
971 /* System V has only the setuid/setgid calls to set user/group IDs.
972 There is an effective ID, which can be set by setuid/setgid.
973 It can be set (unless you are root) only to either what it already is
974 (returned by geteuid/getegid, now in make_uid/make_gid),
975 the real ID (return by getuid/getgid, now in user_uid/user_gid),
976 or the saved set ID (what the effective ID was before this set-ID
977 executable (make) was exec'd). */
978
979 if (setuid (user_uid) < 0)
980 pfatal_with_name ("user_access: setuid");
981
982#else /* HAVE_SETREUID. */
983
984 /* In 4BSD, the setreuid/setregid calls set both the real and effective IDs.
985 They may be set to themselves or each other. So you have two alternatives
986 at any one time. If you use setuid/setgid, the effective will be set to
987 the real, leaving only one alternative. Using setreuid/setregid, however,
988 you can toggle between your two alternatives by swapping the values in a
989 single setreuid or setregid call. */
990
991 if (setreuid (make_uid, user_uid) < 0)
992 pfatal_with_name ("user_access: setreuid");
993
994#endif /* Not HAVE_SETREUID. */
995#endif /* HAVE_SETEUID. */
996
997#ifdef HAVE_SETEGID
998 if (setegid (user_gid) < 0)
999 pfatal_with_name ("user_access: setegid");
1000#else
1001#ifndef HAVE_SETREGID
1002 if (setgid (user_gid) < 0)
1003 pfatal_with_name ("user_access: setgid");
1004#else
1005 if (setregid (make_gid, user_gid) < 0)
1006 pfatal_with_name ("user_access: setregid");
1007#endif
1008#endif
1009
1010 current_access = user;
1011
1012 log_access (_("User access"));
1013
1014#endif /* GETLOADAVG_PRIVILEGED */
1015}
1016
1017/* Give the process appropriate permissions for access to
1018 make data (i.e., the load average). */
1019void
1020make_access (void)
1021{
1022#ifdef GETLOADAVG_PRIVILEGED
1023
1024 if (!access_inited)
1025 init_access ();
1026
1027 if (current_access == make)
1028 return;
1029
1030 /* See comments in user_access, above. */
1031
1032#ifdef HAVE_SETEUID
1033 if (seteuid (make_uid) < 0)
1034 pfatal_with_name ("make_access: seteuid");
1035#else
1036#ifndef HAVE_SETREUID
1037 if (setuid (make_uid) < 0)
1038 pfatal_with_name ("make_access: setuid");
1039#else
1040 if (setreuid (user_uid, make_uid) < 0)
1041 pfatal_with_name ("make_access: setreuid");
1042#endif
1043#endif
1044
1045#ifdef HAVE_SETEGID
1046 if (setegid (make_gid) < 0)
1047 pfatal_with_name ("make_access: setegid");
1048#else
1049#ifndef HAVE_SETREGID
1050 if (setgid (make_gid) < 0)
1051 pfatal_with_name ("make_access: setgid");
1052#else
1053 if (setregid (user_gid, make_gid) < 0)
1054 pfatal_with_name ("make_access: setregid");
1055#endif
1056#endif
1057
1058 current_access = make;
1059
1060 log_access (_("Make access"));
1061
1062#endif /* GETLOADAVG_PRIVILEGED */
1063}
1064
1065/* Give the process appropriate permissions for a child process.
1066 This is like user_access, but you can't get back to make_access. */
1067void
1068child_access (void)
1069{
1070#ifdef GETLOADAVG_PRIVILEGED
1071
1072 if (!access_inited)
1073 abort ();
1074
1075 /* Set both the real and effective UID and GID to the user's.
1076 They cannot be changed back to make's. */
1077
1078#ifndef HAVE_SETREUID
1079 if (setuid (user_uid) < 0)
1080 pfatal_with_name ("child_access: setuid");
1081#else
1082 if (setreuid (user_uid, user_uid) < 0)
1083 pfatal_with_name ("child_access: setreuid");
1084#endif
1085
1086#ifndef HAVE_SETREGID
1087 if (setgid (user_gid) < 0)
1088 pfatal_with_name ("child_access: setgid");
1089#else
1090 if (setregid (user_gid, user_gid) < 0)
1091 pfatal_with_name ("child_access: setregid");
1092#endif
1093
1094 log_access (_("Child access"));
1095
1096#endif /* GETLOADAVG_PRIVILEGED */
1097}
1098
1099
1100#ifdef NEED_GET_PATH_MAX
1101unsigned int
1102get_path_max (void)
1103{
1104 static unsigned int value;
1105
1106 if (value == 0)
1107 {
1108 long int x = pathconf ("/", _PC_PATH_MAX);
1109 if (x > 0)
1110 value = x;
1111 else
1112 return MAXPATHLEN;
1113 }
1114
1115 return value;
1116}
1117#endif
1118
1119
1120
1121/* This code is stolen from gnulib.
1122 If/when we abandon the requirement to work with K&R compilers, we can
1123 remove this (and perhaps other parts of GNU make!) and migrate to using
1124 gnulib directly.
1125
1126 This is called only through atexit(), which means die() has already been
1127 invoked. So, call exit() here directly. Apparently that works...?
1128*/
1129
1130/* Close standard output, exiting with status 'exit_failure' on failure.
1131 If a program writes *anything* to stdout, that program should close
1132 stdout and make sure that it succeeds before exiting. Otherwise,
1133 suppose that you go to the extreme of checking the return status
1134 of every function that does an explicit write to stdout. The last
1135 printf can succeed in writing to the internal stream buffer, and yet
1136 the fclose(stdout) could still fail (due e.g., to a disk full error)
1137 when it tries to write out that buffered data. Thus, you would be
1138 left with an incomplete output file and the offending program would
1139 exit successfully. Even calling fflush is not always sufficient,
1140 since some file systems (NFS and CODA) buffer written/flushed data
1141 until an actual close call.
1142
1143 Besides, it's wasteful to check the return value from every call
1144 that writes to stdout -- just let the internal stream state record
1145 the failure. That's what the ferror test is checking below.
1146
1147 It's important to detect such failures and exit nonzero because many
1148 tools (most notably `make' and other build-management systems) depend
1149 on being able to detect failure in other tools via their exit status. */
1150
1151void
1152close_stdout (void)
1153{
1154 int prev_fail = ferror (stdout);
1155 int fclose_fail = fclose (stdout);
1156
1157 if (prev_fail || fclose_fail)
1158 {
1159 if (fclose_fail)
1160 error (NILF, _("write error: %s"), strerror (errno));
1161 else
1162 error (NILF, _("write error"));
1163 exit (EXIT_FAILURE);
1164 }
1165}
1166
1167#if defined(CONFIG_WITH_MAKE_STATS) && !defined(ELECTRIC_HEAP)
1168#undef free
1169void xfree(void *ptr)
1170{
1171 if (ptr)
1172 {
1173 make_stats_allocations--;
1174 if (make_expensive_statistics)
1175 make_stats_allocated -= SIZE_OF_HEAP_BLOCK (ptr);
1176 free (ptr);
1177 }
1178}
1179#endif
1180
1181
1182#ifdef CONFIG_WITH_ALLOC_CACHES
1183
1184/* Default allocator. */
1185static void *
1186alloccache_default_grow_alloc(void *ignore, unsigned int size)
1187{
1188 return xmalloc (size);
1189}
1190
1191/* Worker for growing the cache. */
1192struct alloccache_free_ent *
1193alloccache_alloc_grow (struct alloccache *cache)
1194{
1195 void *item;
1196 unsigned int items = (64*1024 - 32) / cache->size;
1197 cache->free_start = cache->grow_alloc (cache->grow_arg, items * cache->size);
1198 cache->free_end = cache->free_start + items * cache->size;
1199 cache->total_count+= items;
1200
1201#ifndef NDEBUG /* skip the first item so the heap can detect free(). */
1202 cache->total_count--;
1203 cache->free_start += cache->size;
1204#endif
1205
1206 item = cache->free_start;
1207 cache->free_start += cache->size;
1208 /* caller counts */
1209 return (struct alloccache_free_ent *)item;
1210}
1211
1212/* List of alloc caches, for printing. */
1213static struct alloccache *alloccache_head = NULL;
1214
1215/* Initializes an alloc cache */
1216void
1217alloccache_init (struct alloccache *cache, unsigned int size, const char *name,
1218 void *(*grow_alloc)(void *grow_arg, unsigned int size), void *grow_arg)
1219{
1220 unsigned act_size;
1221
1222 /* ensure OK alignment and min sizeof (struct alloccache_free_ent). */
1223 if (size <= sizeof (struct alloccache_free_ent))
1224 act_size = sizeof (struct alloccache_free_ent);
1225 else if (size <= 32)
1226 {
1227 act_size = 4;
1228 while (act_size < size)
1229 act_size <<= 1;
1230 }
1231 else
1232 act_size = (size + 31U) & ~(size_t)31;
1233
1234 /* align the structure. */
1235 cache->free_start = NULL;
1236 cache->free_end = NULL;
1237 cache->free_head = NULL;
1238 cache->size = act_size;
1239 cache->total_count = 0;
1240 cache->alloc_count = 0;
1241 cache->free_count = 0;
1242 cache->name = name;
1243 cache->grow_arg = grow_arg;
1244 cache->grow_alloc = grow_alloc ? grow_alloc : alloccache_default_grow_alloc;
1245
1246 /* link it. */
1247 cache->next = alloccache_head;
1248 alloccache_head = cache;
1249}
1250
1251/* Terminate an alloc cache, free all the memory it contains. */
1252void
1253alloccache_term (struct alloccache *cache,
1254 void (*term_free)(void *term_arg, void *ptr, unsigned int size), void *term_arg)
1255{
1256 /*cache->size = 0;*/
1257 (void)cache;
1258 (void)term_free;
1259 (void)term_arg;
1260 /* FIXME: Implement memory segment tracking and cleanup. */
1261}
1262
1263/* Joins to caches, unlinking the 2nd one. */
1264void
1265alloccache_join (struct alloccache *cache, struct alloccache *eat)
1266{
1267 assert (cache->size == eat->size);
1268
1269#if 0 /* probably a waste of time */ /* FIXME: Optimize joining, avoid all list walking. */
1270 /* add the free list... */
1271 if (eat->free_head)
1272 {
1273 unsigned int eat_in_use = eat->alloc_count - eat->free_count;
1274 unsigned int dst_in_use = cache->alloc_count - cache->free_count;
1275 if (!cache->free_head)
1276 cache->free_head = eat->free_head;
1277 else if (eat->total_count - eat_in_use < cache->total_count - dst_ins_use)
1278 {
1279 struct alloccache_free_ent *last = eat->free_head;
1280 while (last->next)
1281 last = last->next;
1282 last->next = cache->free_head;
1283 cache->free_head = eat->free_head;
1284 }
1285 else
1286 {
1287 struct alloccache_free_ent *last = cache->free_head;
1288 while (last->next)
1289 last = last->next;
1290 last->next = eat->free_head;
1291 }
1292 }
1293
1294 /* ... and the free space. */
1295 while (eat->free_start != eat->free_end)
1296 {
1297 struct alloccache_free_ent *f = (struct alloccache_free_ent *)eat->free_start;
1298 eat->free_start += eat->size;
1299 f->next = cache->free_head;
1300 cache->free_head = f;
1301 }
1302
1303 /* and statistics */
1304 cache->alloc_count += eat->alloc_count;
1305 cache->free_count += eat->free_count;
1306#else
1307 /* and statistics */
1308 cache->alloc_count += eat->alloc_count;
1309 cache->free_count += eat->free_count;
1310#endif
1311 cache->total_count += eat->total_count;
1312
1313 /* unlink and disable the eat cache */
1314 if (alloccache_head == eat)
1315 alloccache_head = eat->next;
1316 else
1317 {
1318 struct alloccache *cur = alloccache_head;
1319 while (cur->next != eat)
1320 cur = cur->next;
1321 assert (cur && cur->next == eat);
1322 cur->next = eat->next;
1323 }
1324
1325 eat->size = 0;
1326 eat->free_end = eat->free_start = NULL;
1327 eat->free_head = NULL;
1328}
1329
1330/* Print one alloc cache. */
1331void
1332alloccache_print (struct alloccache *cache)
1333{
1334 printf (_("\n# Alloc Cache: %s\n"
1335 "# Items: size = %-3u total = %-6u"),
1336 cache->name, cache->size, cache->total_count);
1337 MAKE_STATS(printf (_(" in-use = %-6lu"),
1338 cache->alloc_count - cache->free_count););
1339 MAKE_STATS(printf (_("\n# alloc calls = %-7lu free calls = %-7lu"),
1340 cache->alloc_count, cache->free_count););
1341 printf ("\n");
1342}
1343
1344/* Print all alloc caches. */
1345void
1346alloccache_print_all (void)
1347{
1348 struct alloccache *cur;
1349 puts ("");
1350 for (cur = alloccache_head; cur; cur = cur->next)
1351 alloccache_print (cur);
1352}
1353
1354#endif /* CONFIG_WITH_ALLOC_CACHES */
1355
1356#ifdef CONFIG_WITH_PRINT_STATS_SWITCH
1357/* Print heap statistics if supported by the platform. */
1358void print_heap_stats (void)
1359{
1360 /* Darwin / Mac OS X */
1361# ifdef __APPLE__
1362 malloc_statistics_t s;
1363
1364 malloc_zone_statistics (NULL, &s);
1365 printf (_("\n# CRT Heap: %zu bytes in use, in %u block, avg %zu bytes/block\n"),
1366 s.size_in_use, s.blocks_in_use, s.size_in_use / s.blocks_in_use);
1367 printf (_("# %zu bytes max in use (high water mark)\n"),
1368 s.max_size_in_use);
1369 printf (_("# %zu bytes reserved, %zu bytes free (estimate)\n"),
1370 s.size_allocated, s.size_allocated - s.size_in_use);
1371# endif /* __APPLE__ */
1372
1373 /* Darwin Libc sources indicates that something like this may be
1374 found in GLIBC, however, it's not in any current one... */
1375# if 0 /* ??? */
1376 struct mstats m;
1377
1378 m = mstats();
1379 printf (_("\n# CRT Heap: %zu blocks / %zu bytes in use, %zu blocks / %zu bytes free\n"),
1380 m.chunks_used, m.bytes_used, m.chunks_free, m.bytes_free);
1381 printf (_("# %zu bytes reserved\n"),
1382 m.bytes_total);
1383# endif /* ??? */
1384
1385 /* XVID2/XPG mallinfo (displayed per GLIBC documentation). */
1386# if 0 && defined(__GLIBC__) /* XXX: finish on linux, check older glibc versions. */
1387 struct mallinfo m;
1388
1389 m = mallinfo();
1390 printf (_("\n# CRT Heap: %d bytes in use, %d bytes free\n"),
1391 m.uordblks, s.fordblks);
1392
1393 printf (_("# # free chunks=%d, # fastbin blocks=%d\n"),
1394 m.ordblks, m.smblks);
1395 printf (_("# # mapped regions=%d, space in mapped regions=%d\n"),
1396 m.hblks, m.hblkhd);
1397 printf (_("# non-mapped space allocated from system=%d\n"),
1398 m.arena);
1399 printf (_("# maximum total allocated space=%d\n"),
1400 m.usmblks);
1401 printf (_("# top-most releasable space=%d\n"),
1402 m.keepcost);
1403# endif /* __GLIBC__ */
1404
1405 /* XXX: windows */
1406}
1407#endif /* CONFIG_WITH_PRINT_STATS_SWITCH */
1408
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