VirtualBox

source: kBuild/trunk/src/gmake/misc.c@ 503

Last change on this file since 503 was 503, checked in by bird, 19 years ago

Untested merge with GNU Make v3.81 (vendor/gnumake/2005-05-16 -> vendor/gnumake/current).

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

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette