VirtualBox

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

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

kmk: Implemented new switch --print-time. Fixes #65.

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