• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* Miscellaneous generic support functions for GNU Make.
2 Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997,
3 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software
4 Foundation, Inc.
5 This file is part of GNU Make.
6 
7 GNU Make is free software; you can redistribute it and/or modify it under the
8 terms of the GNU General Public License as published by the Free Software
9 Foundation; either version 2, or (at your option) any later version.
10 
11 GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY
12 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
13 A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
14 
15 You should have received a copy of the GNU General Public License along with
16 GNU Make; see the file COPYING.  If not, write to the Free Software
17 Foundation, 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 
23 /* Variadic functions.  We go through contortions to allow proper function
24    prototypes for both ANSI and pre-ANSI C compilers, and also for those
25    which support stdarg.h vs. varargs.h, and finally those which have
26    vfprintf(), etc. and those who have _doprnt... or nothing.
27 
28    This fancy stuff all came from GNU fileutils, except for the VA_PRINTF and
29    VA_END macros used here since we have multiple print functions.  */
30 
31 #if USE_VARIADIC
32 # if HAVE_STDARG_H
33 #  include <stdarg.h>
34 #  define VA_START(args, lastarg) va_start(args, lastarg)
35 # else
36 #  include <varargs.h>
37 #  define VA_START(args, lastarg) va_start(args)
38 # endif
39 # if HAVE_VPRINTF
40 #  define VA_PRINTF(fp, lastarg, args) vfprintf((fp), (lastarg), (args))
41 # else
42 #  define VA_PRINTF(fp, lastarg, args) _doprnt((lastarg), (args), (fp))
43 # endif
44 # define VA_END(args) va_end(args)
45 #else
46 /* We can't use any variadic interface! */
47 # define va_alist a1, a2, a3, a4, a5, a6, a7, a8
48 # define va_dcl char *a1, *a2, *a3, *a4, *a5, *a6, *a7, *a8;
49 # define VA_START(args, lastarg)
50 # define VA_PRINTF(fp, lastarg, args) fprintf((fp), (lastarg), va_alist)
51 # define VA_END(args)
52 #endif
53 
54 
55 /* Compare strings *S1 and *S2.
56    Return negative if the first is less, positive if it is greater,
57    zero if they are equal.  */
58 
59 int
alpha_compare(const void * v1,const void * v2)60 alpha_compare (const void *v1, const void *v2)
61 {
62   const char *s1 = *((char **)v1);
63   const char *s2 = *((char **)v2);
64 
65   if (*s1 != *s2)
66     return *s1 - *s2;
67   return strcmp (s1, s2);
68 }
69 
70 /* Discard each backslash-newline combination from LINE.
71    Backslash-backslash-newline combinations become backslash-newlines.
72    This is done by copying the text at LINE into itself.  */
73 
74 void
collapse_continuations(char * line)75 collapse_continuations (char *line)
76 {
77   register char *in, *out, *p;
78   register int backslash;
79   register unsigned int bs_write;
80 
81   in = strchr (line, '\n');
82   if (in == 0)
83     return;
84 
85   out = in;
86   while (out > line && out[-1] == '\\')
87     --out;
88 
89   while (*in != '\0')
90     {
91       /* BS_WRITE gets the number of quoted backslashes at
92 	 the end just before IN, and BACKSLASH gets nonzero
93 	 if the next character is quoted.  */
94       backslash = 0;
95       bs_write = 0;
96       for (p = in - 1; p >= line && *p == '\\'; --p)
97 	{
98 	  if (backslash)
99 	    ++bs_write;
100 	  backslash = !backslash;
101 
102 	  /* It should be impossible to go back this far without exiting,
103 	     but if we do, we can't get the right answer.  */
104 	  if (in == out - 1)
105 	    abort ();
106 	}
107 
108       /* Output the appropriate number of backslashes.  */
109       while (bs_write-- > 0)
110 	*out++ = '\\';
111 
112       /* Skip the newline.  */
113       ++in;
114 
115       /* If the newline is quoted, discard following whitespace
116 	 and any preceding whitespace; leave just one space.  */
117       if (backslash)
118 	{
119 	  in = next_token (in);
120 	  while (out > line && isblank ((unsigned char)out[-1]))
121 	    --out;
122 	  *out++ = ' ';
123 	}
124       else
125 	/* If the newline isn't quoted, put it in the output.  */
126 	*out++ = '\n';
127 
128       /* Now copy the following line to the output.
129 	 Stop when we find backslashes followed by a newline.  */
130       while (*in != '\0')
131 	if (*in == '\\')
132 	  {
133 	    p = in + 1;
134 	    while (*p == '\\')
135 	      ++p;
136 	    if (*p == '\n')
137 	      {
138 		in = p;
139 		break;
140 	      }
141 	    while (in < p)
142 	      *out++ = *in++;
143 	  }
144 	else
145 	  *out++ = *in++;
146     }
147 
148   *out = '\0';
149 }
150 
151 /* Print N spaces (used in debug for target-depth).  */
152 
153 void
print_spaces(unsigned int n)154 print_spaces (unsigned int n)
155 {
156   while (n-- > 0)
157     putchar (' ');
158 }
159 
160 
161 /* Return a newly-allocated string whose contents
162    concatenate those of s1, s2, s3.  */
163 
164 char *
concat(const char * s1,const char * s2,const char * s3)165 concat (const char *s1, const char *s2, const char *s3)
166 {
167   unsigned int len1, len2, len3;
168   char *result;
169 
170   len1 = *s1 != '\0' ? strlen (s1) : 0;
171   len2 = *s2 != '\0' ? strlen (s2) : 0;
172   len3 = *s3 != '\0' ? strlen (s3) : 0;
173 
174   result = (char *) xmalloc (len1 + len2 + len3 + 1);
175 
176   if (*s1 != '\0')
177     bcopy (s1, result, len1);
178   if (*s2 != '\0')
179     bcopy (s2, result + len1, len2);
180   if (*s3 != '\0')
181     bcopy (s3, result + len1 + len2, len3);
182   *(result + len1 + len2 + len3) = '\0';
183 
184   return result;
185 }
186 
187 /* Print a message on stdout.  */
188 
189 void
190 #if HAVE_ANSI_COMPILER && USE_VARIADIC && HAVE_STDARG_H
message(int prefix,const char * fmt,...)191 message (int prefix, const char *fmt, ...)
192 #else
193 message (prefix, fmt, va_alist)
194      int prefix;
195      const char *fmt;
196      va_dcl
197 #endif
198 {
199 #if USE_VARIADIC
200   va_list args;
201 #endif
202 
203   log_working_directory (1);
204 
205   if (fmt != 0)
206     {
207       if (prefix)
208 	{
209 	  if (makelevel == 0)
210 	    printf ("%s: ", program);
211 	  else
212 	    printf ("%s[%u]: ", program, makelevel);
213 	}
214       VA_START (args, fmt);
215       VA_PRINTF (stdout, fmt, args);
216       VA_END (args);
217       putchar ('\n');
218     }
219 
220   fflush (stdout);
221 }
222 
223 /* Print an error message.  */
224 
225 void
226 #if HAVE_ANSI_COMPILER && USE_VARIADIC && HAVE_STDARG_H
error(const struct floc * flocp,const char * fmt,...)227 error (const struct floc *flocp, const char *fmt, ...)
228 #else
229 error (flocp, fmt, va_alist)
230      const struct floc *flocp;
231      const char *fmt;
232      va_dcl
233 #endif
234 {
235 #if USE_VARIADIC
236   va_list args;
237 #endif
238 
239   log_working_directory (1);
240 
241   if (flocp && flocp->filenm)
242     fprintf (stderr, "%s:%lu: ", flocp->filenm, flocp->lineno);
243   else if (makelevel == 0)
244     fprintf (stderr, "%s: ", program);
245   else
246     fprintf (stderr, "%s[%u]: ", program, makelevel);
247 
248   VA_START(args, fmt);
249   VA_PRINTF (stderr, fmt, args);
250   VA_END (args);
251 
252   putc ('\n', stderr);
253   fflush (stderr);
254 }
255 
256 /* Print an error message and exit.  */
257 
258 void
259 #if HAVE_ANSI_COMPILER && USE_VARIADIC && HAVE_STDARG_H
fatal(const struct floc * flocp,const char * fmt,...)260 fatal (const struct floc *flocp, const char *fmt, ...)
261 #else
262 fatal (flocp, fmt, va_alist)
263      const struct floc *flocp;
264      const char *fmt;
265      va_dcl
266 #endif
267 {
268 #if USE_VARIADIC
269   va_list args;
270 #endif
271 
272   log_working_directory (1);
273 
274   if (flocp && flocp->filenm)
275     fprintf (stderr, "%s:%lu: *** ", flocp->filenm, flocp->lineno);
276   else if (makelevel == 0)
277     fprintf (stderr, "%s: *** ", program);
278   else
279     fprintf (stderr, "%s[%u]: *** ", program, makelevel);
280 
281   VA_START(args, fmt);
282   VA_PRINTF (stderr, fmt, args);
283   VA_END (args);
284 
285   fputs (_(".  Stop.\n"), stderr);
286 
287   die (2);
288 }
289 
290 #ifndef HAVE_STRERROR
291 
292 #undef	strerror
293 
294 char *
strerror(int errnum)295 strerror (int errnum)
296 {
297   extern int errno, sys_nerr;
298 #ifndef __DECC
299   extern char *sys_errlist[];
300 #endif
301   static char buf[] = "Unknown error 12345678901234567890";
302 
303   if (errno < sys_nerr)
304     return sys_errlist[errnum];
305 
306   sprintf (buf, _("Unknown error %d"), errnum);
307   return buf;
308 }
309 #endif
310 
311 /* Print an error message from errno.  */
312 
313 void
perror_with_name(const char * str,const char * name)314 perror_with_name (const char *str, const char *name)
315 {
316   error (NILF, _("%s%s: %s"), str, name, strerror (errno));
317 }
318 
319 /* Print an error message from errno and exit.  */
320 
321 void
pfatal_with_name(const char * name)322 pfatal_with_name (const char *name)
323 {
324   fatal (NILF, _("%s: %s"), name, strerror (errno));
325 
326   /* NOTREACHED */
327 }
328 
329 /* Like malloc but get fatal error if memory is exhausted.  */
330 /* Don't bother if we're using dmalloc; it provides these for us.  */
331 
332 #ifndef HAVE_DMALLOC_H
333 
334 #undef xmalloc
335 #undef xrealloc
336 #undef xstrdup
337 
338 char *
xmalloc(unsigned int size)339 xmalloc (unsigned int size)
340 {
341   /* Make sure we don't allocate 0, for pre-ANSI libraries.  */
342   char *result = (char *) malloc (size ? size : 1);
343   if (result == 0)
344     fatal (NILF, _("virtual memory exhausted"));
345   return result;
346 }
347 
348 
349 char *
xrealloc(char * ptr,unsigned int size)350 xrealloc (char *ptr, unsigned int size)
351 {
352   char *result;
353 
354   /* Some older implementations of realloc() don't conform to ANSI.  */
355   if (! size)
356     size = 1;
357   result = ptr ? realloc (ptr, size) : malloc (size);
358   if (result == 0)
359     fatal (NILF, _("virtual memory exhausted"));
360   return result;
361 }
362 
363 
364 char *
xstrdup(const char * ptr)365 xstrdup (const char *ptr)
366 {
367   char *result;
368 
369 #ifdef HAVE_STRDUP
370   result = strdup (ptr);
371 #else
372   result = (char *) malloc (strlen (ptr) + 1);
373 #endif
374 
375   if (result == 0)
376     fatal (NILF, _("virtual memory exhausted"));
377 
378 #ifdef HAVE_STRDUP
379   return result;
380 #else
381   return strcpy(result, ptr);
382 #endif
383 }
384 
385 #endif  /* HAVE_DMALLOC_H */
386 
387 char *
savestring(const char * str,unsigned int length)388 savestring (const char *str, unsigned int length)
389 {
390   register char *out = (char *) xmalloc (length + 1);
391   if (length > 0)
392     bcopy (str, out, length);
393   out[length] = '\0';
394   return out;
395 }
396 
397 
398 /* Limited INDEX:
399    Search through the string STRING, which ends at LIMIT, for the character C.
400    Returns a pointer to the first occurrence, or nil if none is found.
401    Like INDEX except that the string searched ends where specified
402    instead of at the first null.  */
403 
404 char *
lindex(const char * s,const char * limit,int c)405 lindex (const char *s, const char *limit, int c)
406 {
407   while (s < limit)
408     if (*s++ == c)
409       return (char *)(s - 1);
410 
411   return 0;
412 }
413 
414 /* Return the address of the first whitespace or null in the string S.  */
415 
416 char *
end_of_token(const char * s)417 end_of_token (const char *s)
418 {
419   while (*s != '\0' && !isblank ((unsigned char)*s))
420     ++s;
421   return (char *)s;
422 }
423 
424 #ifdef WINDOWS32
425 /*
426  * Same as end_of_token, but take into account a stop character
427  */
428 char *
end_of_token_w32(char * s,char stopchar)429 end_of_token_w32 (char *s, char stopchar)
430 {
431   register char *p = s;
432   register int backslash = 0;
433 
434   while (*p != '\0' && *p != stopchar
435 	 && (backslash || !isblank ((unsigned char)*p)))
436     {
437       if (*p++ == '\\')
438         {
439           backslash = !backslash;
440           while (*p == '\\')
441             {
442               backslash = !backslash;
443               ++p;
444             }
445         }
446       else
447         backslash = 0;
448     }
449 
450   return p;
451 }
452 #endif
453 
454 /* Return the address of the first nonwhitespace or null in the string S.  */
455 
456 char *
next_token(const char * s)457 next_token (const char *s)
458 {
459   while (isblank ((unsigned char)*s))
460     ++s;
461   return (char *)s;
462 }
463 
464 /* Find the next token in PTR; return the address of it, and store the
465    length of the token into *LENGTHPTR if LENGTHPTR is not nil.  */
466 
467 char *
find_next_token(char ** ptr,unsigned int * lengthptr)468 find_next_token (char **ptr, unsigned int *lengthptr)
469 {
470   char *p = next_token (*ptr);
471   char *end;
472 
473   if (*p == '\0')
474     return 0;
475 
476   *ptr = end = end_of_token (p);
477   if (lengthptr != 0)
478     *lengthptr = end - p;
479   return p;
480 }
481 
482 
483 /* Allocate a new `struct dep' with all fields initialized to 0.   */
484 
485 struct dep *
alloc_dep()486 alloc_dep ()
487 {
488   struct dep *d = (struct dep *) xmalloc (sizeof (struct dep));
489   bzero ((char *) d, sizeof (struct dep));
490   return d;
491 }
492 
493 
494 /* Free `struct dep' along with `name' and `stem'.   */
495 
496 void
free_dep(struct dep * d)497 free_dep (struct dep *d)
498 {
499   if (d->name != 0)
500     free (d->name);
501 
502   if (d->stem != 0)
503     free (d->stem);
504 
505   free ((char *)d);
506 }
507 
508 /* Copy a chain of `struct dep', making a new chain
509    with the same contents as the old one.  */
510 
511 struct dep *
copy_dep_chain(const struct dep * d)512 copy_dep_chain (const struct dep *d)
513 {
514   register struct dep *c;
515   struct dep *firstnew = 0;
516   struct dep *lastnew = 0;
517 
518   while (d != 0)
519     {
520       c = (struct dep *) xmalloc (sizeof (struct dep));
521       bcopy ((char *) d, (char *) c, sizeof (struct dep));
522 
523       if (c->name != 0)
524 	c->name = xstrdup (c->name);
525       if (c->stem != 0)
526 	c->stem = xstrdup (c->stem);
527 
528       c->next = 0;
529       if (firstnew == 0)
530 	firstnew = lastnew = c;
531       else
532 	lastnew = lastnew->next = c;
533 
534       d = d->next;
535     }
536 
537   return firstnew;
538 }
539 
540 /* Free a chain of 'struct dep'.  */
541 
542 void
free_dep_chain(struct dep * d)543 free_dep_chain (struct dep *d)
544 {
545   while (d != 0)
546     {
547       struct dep *df = d;
548       d = d->next;
549       free_dep (df);
550     }
551 }
552 
553 /* Free a chain of `struct nameseq'. Each nameseq->name is freed
554    as well.  For `struct dep' chains use free_dep_chain.  */
555 
556 void
free_ns_chain(struct nameseq * n)557 free_ns_chain (struct nameseq *n)
558 {
559   register struct nameseq *tmp;
560 
561   while (n != 0)
562   {
563     if (n->name != 0)
564       free (n->name);
565 
566     tmp = n;
567 
568     n = n->next;
569 
570     free (tmp);
571   }
572 
573 }
574 #ifdef	iAPX286
575 /* The losing compiler on this machine can't handle this macro.  */
576 
577 char *
dep_name(struct dep * dep)578 dep_name (struct dep *dep)
579 {
580   return dep->name == 0 ? dep->file->name : dep->name;
581 }
582 #endif
583 
584 #ifdef	GETLOADAVG_PRIVILEGED
585 
586 #ifdef POSIX
587 
588 /* Hopefully if a system says it's POSIX.1 and has the setuid and setgid
589    functions, they work as POSIX.1 says.  Some systems (Alpha OSF/1 1.2,
590    for example) which claim to be POSIX.1 also have the BSD setreuid and
591    setregid functions, but they don't work as in BSD and only the POSIX.1
592    way works.  */
593 
594 #undef HAVE_SETREUID
595 #undef HAVE_SETREGID
596 
597 #else	/* Not POSIX.  */
598 
599 /* Some POSIX.1 systems have the seteuid and setegid functions.  In a
600    POSIX-like system, they are the best thing to use.  However, some
601    non-POSIX systems have them too but they do not work in the POSIX style
602    and we must use setreuid and setregid instead.  */
603 
604 #undef HAVE_SETEUID
605 #undef HAVE_SETEGID
606 
607 #endif	/* POSIX.  */
608 
609 #ifndef	HAVE_UNISTD_H
610 extern int getuid (), getgid (), geteuid (), getegid ();
611 extern int setuid (), setgid ();
612 #ifdef HAVE_SETEUID
613 extern int seteuid ();
614 #else
615 #ifdef	HAVE_SETREUID
616 extern int setreuid ();
617 #endif	/* Have setreuid.  */
618 #endif	/* Have seteuid.  */
619 #ifdef HAVE_SETEGID
620 extern int setegid ();
621 #else
622 #ifdef	HAVE_SETREGID
623 extern int setregid ();
624 #endif	/* Have setregid.  */
625 #endif	/* Have setegid.  */
626 #endif	/* No <unistd.h>.  */
627 
628 /* Keep track of the user and group IDs for user- and make- access.  */
629 static int user_uid = -1, user_gid = -1, make_uid = -1, make_gid = -1;
630 #define	access_inited	(user_uid != -1)
631 static enum { make, user } current_access;
632 
633 
634 /* Under -d, write a message describing the current IDs.  */
635 
636 static void
log_access(const char * flavor)637 log_access (const char *flavor)
638 {
639   if (! ISDB (DB_JOBS))
640     return;
641 
642   /* All the other debugging messages go to stdout,
643      but we write this one to stderr because it might be
644      run in a child fork whose stdout is piped.  */
645 
646   fprintf (stderr, _("%s: user %lu (real %lu), group %lu (real %lu)\n"),
647 	   flavor, (unsigned long) geteuid (), (unsigned long) getuid (),
648            (unsigned long) getegid (), (unsigned long) getgid ());
649   fflush (stderr);
650 }
651 
652 
653 static void
init_access(void)654 init_access (void)
655 {
656 #ifndef VMS
657   user_uid = getuid ();
658   user_gid = getgid ();
659 
660   make_uid = geteuid ();
661   make_gid = getegid ();
662 
663   /* Do these ever fail?  */
664   if (user_uid == -1 || user_gid == -1 || make_uid == -1 || make_gid == -1)
665     pfatal_with_name ("get{e}[gu]id");
666 
667   log_access (_("Initialized access"));
668 
669   current_access = make;
670 #endif
671 }
672 
673 #endif	/* GETLOADAVG_PRIVILEGED */
674 
675 /* Give the process appropriate permissions for access to
676    user data (i.e., to stat files, or to spawn a child process).  */
677 void
user_access(void)678 user_access (void)
679 {
680 #ifdef	GETLOADAVG_PRIVILEGED
681 
682   if (!access_inited)
683     init_access ();
684 
685   if (current_access == user)
686     return;
687 
688   /* We are in "make access" mode.  This means that the effective user and
689      group IDs are those of make (if it was installed setuid or setgid).
690      We now want to set the effective user and group IDs to the real IDs,
691      which are the IDs of the process that exec'd make.  */
692 
693 #ifdef	HAVE_SETEUID
694 
695   /* Modern systems have the seteuid/setegid calls which set only the
696      effective IDs, which is ideal.  */
697 
698   if (seteuid (user_uid) < 0)
699     pfatal_with_name ("user_access: seteuid");
700 
701 #else	/* Not HAVE_SETEUID.  */
702 
703 #ifndef	HAVE_SETREUID
704 
705   /* System V has only the setuid/setgid calls to set user/group IDs.
706      There is an effective ID, which can be set by setuid/setgid.
707      It can be set (unless you are root) only to either what it already is
708      (returned by geteuid/getegid, now in make_uid/make_gid),
709      the real ID (return by getuid/getgid, now in user_uid/user_gid),
710      or the saved set ID (what the effective ID was before this set-ID
711      executable (make) was exec'd).  */
712 
713   if (setuid (user_uid) < 0)
714     pfatal_with_name ("user_access: setuid");
715 
716 #else	/* HAVE_SETREUID.  */
717 
718   /* In 4BSD, the setreuid/setregid calls set both the real and effective IDs.
719      They may be set to themselves or each other.  So you have two alternatives
720      at any one time.  If you use setuid/setgid, the effective will be set to
721      the real, leaving only one alternative.  Using setreuid/setregid, however,
722      you can toggle between your two alternatives by swapping the values in a
723      single setreuid or setregid call.  */
724 
725   if (setreuid (make_uid, user_uid) < 0)
726     pfatal_with_name ("user_access: setreuid");
727 
728 #endif	/* Not HAVE_SETREUID.  */
729 #endif	/* HAVE_SETEUID.  */
730 
731 #ifdef	HAVE_SETEGID
732   if (setegid (user_gid) < 0)
733     pfatal_with_name ("user_access: setegid");
734 #else
735 #ifndef	HAVE_SETREGID
736   if (setgid (user_gid) < 0)
737     pfatal_with_name ("user_access: setgid");
738 #else
739   if (setregid (make_gid, user_gid) < 0)
740     pfatal_with_name ("user_access: setregid");
741 #endif
742 #endif
743 
744   current_access = user;
745 
746   log_access (_("User access"));
747 
748 #endif	/* GETLOADAVG_PRIVILEGED */
749 }
750 
751 /* Give the process appropriate permissions for access to
752    make data (i.e., the load average).  */
753 void
make_access(void)754 make_access (void)
755 {
756 #ifdef	GETLOADAVG_PRIVILEGED
757 
758   if (!access_inited)
759     init_access ();
760 
761   if (current_access == make)
762     return;
763 
764   /* See comments in user_access, above.  */
765 
766 #ifdef	HAVE_SETEUID
767   if (seteuid (make_uid) < 0)
768     pfatal_with_name ("make_access: seteuid");
769 #else
770 #ifndef	HAVE_SETREUID
771   if (setuid (make_uid) < 0)
772     pfatal_with_name ("make_access: setuid");
773 #else
774   if (setreuid (user_uid, make_uid) < 0)
775     pfatal_with_name ("make_access: setreuid");
776 #endif
777 #endif
778 
779 #ifdef	HAVE_SETEGID
780   if (setegid (make_gid) < 0)
781     pfatal_with_name ("make_access: setegid");
782 #else
783 #ifndef	HAVE_SETREGID
784   if (setgid (make_gid) < 0)
785     pfatal_with_name ("make_access: setgid");
786 #else
787   if (setregid (user_gid, make_gid) < 0)
788     pfatal_with_name ("make_access: setregid");
789 #endif
790 #endif
791 
792   current_access = make;
793 
794   log_access (_("Make access"));
795 
796 #endif	/* GETLOADAVG_PRIVILEGED */
797 }
798 
799 /* Give the process appropriate permissions for a child process.
800    This is like user_access, but you can't get back to make_access.  */
801 void
child_access(void)802 child_access (void)
803 {
804 #ifdef	GETLOADAVG_PRIVILEGED
805 
806   if (!access_inited)
807     abort ();
808 
809   /* Set both the real and effective UID and GID to the user's.
810      They cannot be changed back to make's.  */
811 
812 #ifndef	HAVE_SETREUID
813   if (setuid (user_uid) < 0)
814     pfatal_with_name ("child_access: setuid");
815 #else
816   if (setreuid (user_uid, user_uid) < 0)
817     pfatal_with_name ("child_access: setreuid");
818 #endif
819 
820 #ifndef	HAVE_SETREGID
821   if (setgid (user_gid) < 0)
822     pfatal_with_name ("child_access: setgid");
823 #else
824   if (setregid (user_gid, user_gid) < 0)
825     pfatal_with_name ("child_access: setregid");
826 #endif
827 
828   log_access (_("Child access"));
829 
830 #endif	/* GETLOADAVG_PRIVILEGED */
831 }
832 
833 #ifdef NEED_GET_PATH_MAX
834 unsigned int
get_path_max(void)835 get_path_max (void)
836 {
837   static unsigned int value;
838 
839   if (value == 0)
840     {
841       long int x = pathconf ("/", _PC_PATH_MAX);
842       if (x > 0)
843 	value = x;
844       else
845 	return MAXPATHLEN;
846     }
847 
848   return value;
849 }
850 #endif
851 
852 
853 /* This code is stolen from gnulib.
854    If/when we abandon the requirement to work with K&R compilers, we can
855    remove this (and perhaps other parts of GNU make!) and migrate to using
856    gnulib directly.
857 
858    This is called only through atexit(), which means die() has already been
859    invoked.  So, call exit() here directly.  Apparently that works...?
860 */
861 
862 /* Close standard output, exiting with status 'exit_failure' on failure.
863    If a program writes *anything* to stdout, that program should close
864    stdout and make sure that it succeeds before exiting.  Otherwise,
865    suppose that you go to the extreme of checking the return status
866    of every function that does an explicit write to stdout.  The last
867    printf can succeed in writing to the internal stream buffer, and yet
868    the fclose(stdout) could still fail (due e.g., to a disk full error)
869    when it tries to write out that buffered data.  Thus, you would be
870    left with an incomplete output file and the offending program would
871    exit successfully.  Even calling fflush is not always sufficient,
872    since some file systems (NFS and CODA) buffer written/flushed data
873    until an actual close call.
874 
875    Besides, it's wasteful to check the return value from every call
876    that writes to stdout -- just let the internal stream state record
877    the failure.  That's what the ferror test is checking below.
878 
879    It's important to detect such failures and exit nonzero because many
880    tools (most notably `make' and other build-management systems) depend
881    on being able to detect failure in other tools via their exit status.  */
882 
883 void
close_stdout(void)884 close_stdout (void)
885 {
886   int prev_fail = ferror (stdout);
887   int fclose_fail = fclose (stdout);
888 
889   if (prev_fail || fclose_fail)
890     {
891       if (fclose_fail)
892         error (NILF, _("write error: %s"), strerror (errno));
893       else
894         error (NILF, _("write error"));
895       exit (EXIT_FAILURE);
896     }
897 }
898