VirtualBox

source: kBuild/vendor/gnumake/2008-10-28/misc.c

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

Load gnumake-2008-10-28-CVS into vendor/gnumake/current.

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