source: trunk/src/gmake/misc.c@ 520

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

Cleaning up the modifications. Changes are now either configurable or marked, and dead stuff has been removed (dll shell).

  • Property svn:eol-style set to native
File size: 20.9 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__ /* bird: 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#if 0 /* This is really a reimplemntation of memchr, only slower.
409 It's been replaced by a macro in the header file. */
410/* Limited INDEX:
411 Search through the string STRING, which ends at LIMIT, for the character C.
412 Returns a pointer to the first occurrence, or nil if none is found.
413 Like INDEX except that the string searched ends where specified
414 instead of at the first null. */
415
416char *
417lindex (const char *s, const char *limit, int c)
418{
419 while (s < limit)
420 if (*s++ == c)
421 return (char *)(s - 1);
422
423 return 0;
424}
425#endif
426
427
428/* Return the address of the first whitespace or null in the string S. */
429
430char *
431end_of_token (const char *s)
432{
433 while (*s != '\0' && !isblank ((unsigned char)*s))
434 ++s;
435 return (char *)s;
436}
437
438#ifdef WINDOWS32
439/*
440 * Same as end_of_token, but take into account a stop character
441 */
442char *
443end_of_token_w32 (char *s, char stopchar)
444{
445 register char *p = s;
446 register int backslash = 0;
447
448 while (*p != '\0' && *p != stopchar
449 && (backslash || !isblank ((unsigned char)*p)))
450 {
451 if (*p++ == '\\')
452 {
453 backslash = !backslash;
454 while (*p == '\\')
455 {
456 backslash = !backslash;
457 ++p;
458 }
459 }
460 else
461 backslash = 0;
462 }
463
464 return p;
465}
466#endif
467
468/* Return the address of the first nonwhitespace or null in the string S. */
469
470char *
471next_token (const char *s)
472{
473 while (isblank ((unsigned char)*s))
474 ++s;
475 return (char *)s;
476}
477
478/* Find the next token in PTR; return the address of it, and store the
479 length of the token into *LENGTHPTR if LENGTHPTR is not nil. */
480
481char *
482find_next_token (char **ptr, unsigned int *lengthptr)
483{
484 char *p = next_token (*ptr);
485 char *end;
486
487 if (*p == '\0')
488 return 0;
489
490 *ptr = end = end_of_token (p);
491 if (lengthptr != 0)
492 *lengthptr = end - p;
493 return p;
494}
495
496
497
498/* Allocate a new `struct dep' with all fields initialized to 0. */
499
500struct dep *
501alloc_dep ()
502{
503 struct dep *d = (struct dep *) xmalloc (sizeof (struct dep));
504 bzero ((char *) d, sizeof (struct dep));
505 return d;
506}
507
508
509/* Free `struct dep' along with `name' and `stem'. */
510
511void
512free_dep (struct dep *d)
513{
514 if (d->name != 0)
515 free (d->name);
516
517 if (d->stem != 0)
518 free (d->stem);
519
520 free ((char *)d);
521}
522
523/* Copy a chain of `struct dep', making a new chain
524 with the same contents as the old one. */
525
526struct dep *
527copy_dep_chain (const struct dep *d)
528{
529 register struct dep *c;
530 struct dep *firstnew = 0;
531 struct dep *lastnew = 0;
532
533 while (d != 0)
534 {
535 c = (struct dep *) xmalloc (sizeof (struct dep));
536 bcopy ((char *) d, (char *) c, sizeof (struct dep));
537
538 if (c->name != 0)
539 c->name = xstrdup (c->name);
540 if (c->stem != 0)
541 c->stem = xstrdup (c->stem);
542
543 c->next = 0;
544 if (firstnew == 0)
545 firstnew = lastnew = c;
546 else
547 lastnew = lastnew->next = c;
548
549 d = d->next;
550 }
551
552 return firstnew;
553}
554
555/* Free a chain of 'struct dep'. */
556
557void
558free_dep_chain (struct dep *d)
559{
560 while (d != 0)
561 {
562 struct dep *df = d;
563 d = d->next;
564 free_dep (df);
565 }
566}
567
568
569/* Free a chain of `struct nameseq'. Each nameseq->name is freed
570 as well. For `struct dep' chains use free_dep_chain. */
571
572void
573free_ns_chain (struct nameseq *n)
574{
575 register struct nameseq *tmp;
576
577 while (n != 0)
578 {
579 if (n->name != 0)
580 free (n->name);
581
582 tmp = n;
583
584 n = n->next;
585
586 free (tmp);
587 }
588
589}
590
591#ifdef iAPX286
592/* The losing compiler on this machine can't handle this macro. */
593
594char *
595dep_name (struct dep *dep)
596{
597 return dep->name == 0 ? dep->file->name : dep->name;
598}
599#endif
600
601
602#ifdef GETLOADAVG_PRIVILEGED
603
604#ifdef POSIX
605
606/* Hopefully if a system says it's POSIX.1 and has the setuid and setgid
607 functions, they work as POSIX.1 says. Some systems (Alpha OSF/1 1.2,
608 for example) which claim to be POSIX.1 also have the BSD setreuid and
609 setregid functions, but they don't work as in BSD and only the POSIX.1
610 way works. */
611
612#undef HAVE_SETREUID
613#undef HAVE_SETREGID
614
615#else /* Not POSIX. */
616
617/* Some POSIX.1 systems have the seteuid and setegid functions. In a
618 POSIX-like system, they are the best thing to use. However, some
619 non-POSIX systems have them too but they do not work in the POSIX style
620 and we must use setreuid and setregid instead. */
621
622#undef HAVE_SETEUID
623#undef HAVE_SETEGID
624
625#endif /* POSIX. */
626
627#ifndef HAVE_UNISTD_H
628extern int getuid (), getgid (), geteuid (), getegid ();
629extern int setuid (), setgid ();
630#ifdef HAVE_SETEUID
631extern int seteuid ();
632#else
633#ifdef HAVE_SETREUID
634extern int setreuid ();
635#endif /* Have setreuid. */
636#endif /* Have seteuid. */
637#ifdef HAVE_SETEGID
638extern int setegid ();
639#else
640#ifdef HAVE_SETREGID
641extern int setregid ();
642#endif /* Have setregid. */
643#endif /* Have setegid. */
644#endif /* No <unistd.h>. */
645
646/* Keep track of the user and group IDs for user- and make- access. */
647static int user_uid = -1, user_gid = -1, make_uid = -1, make_gid = -1;
648#define access_inited (user_uid != -1)
649static enum { make, user } current_access;
650
651
652/* Under -d, write a message describing the current IDs. */
653
654static void
655log_access (const char *flavor)
656{
657 if (! ISDB (DB_JOBS))
658 return;
659
660 /* All the other debugging messages go to stdout,
661 but we write this one to stderr because it might be
662 run in a child fork whose stdout is piped. */
663
664 fprintf (stderr, _("%s: user %lu (real %lu), group %lu (real %lu)\n"),
665 flavor, (unsigned long) geteuid (), (unsigned long) getuid (),
666 (unsigned long) getegid (), (unsigned long) getgid ());
667 fflush (stderr);
668}
669
670
671static void
672init_access (void)
673{
674#ifndef VMS
675 user_uid = getuid ();
676 user_gid = getgid ();
677
678 make_uid = geteuid ();
679 make_gid = getegid ();
680
681 /* Do these ever fail? */
682 if (user_uid == -1 || user_gid == -1 || make_uid == -1 || make_gid == -1)
683 pfatal_with_name ("get{e}[gu]id");
684
685 log_access (_("Initialized access"));
686
687 current_access = make;
688#endif
689}
690
691#endif /* GETLOADAVG_PRIVILEGED */
692
693/* Give the process appropriate permissions for access to
694 user data (i.e., to stat files, or to spawn a child process). */
695void
696user_access (void)
697{
698#ifdef GETLOADAVG_PRIVILEGED
699
700 if (!access_inited)
701 init_access ();
702
703 if (current_access == user)
704 return;
705
706 /* We are in "make access" mode. This means that the effective user and
707 group IDs are those of make (if it was installed setuid or setgid).
708 We now want to set the effective user and group IDs to the real IDs,
709 which are the IDs of the process that exec'd make. */
710
711#ifdef HAVE_SETEUID
712
713 /* Modern systems have the seteuid/setegid calls which set only the
714 effective IDs, which is ideal. */
715
716 if (seteuid (user_uid) < 0)
717 pfatal_with_name ("user_access: seteuid");
718
719#else /* Not HAVE_SETEUID. */
720
721#ifndef HAVE_SETREUID
722
723 /* System V has only the setuid/setgid calls to set user/group IDs.
724 There is an effective ID, which can be set by setuid/setgid.
725 It can be set (unless you are root) only to either what it already is
726 (returned by geteuid/getegid, now in make_uid/make_gid),
727 the real ID (return by getuid/getgid, now in user_uid/user_gid),
728 or the saved set ID (what the effective ID was before this set-ID
729 executable (make) was exec'd). */
730
731 if (setuid (user_uid) < 0)
732 pfatal_with_name ("user_access: setuid");
733
734#else /* HAVE_SETREUID. */
735
736 /* In 4BSD, the setreuid/setregid calls set both the real and effective IDs.
737 They may be set to themselves or each other. So you have two alternatives
738 at any one time. If you use setuid/setgid, the effective will be set to
739 the real, leaving only one alternative. Using setreuid/setregid, however,
740 you can toggle between your two alternatives by swapping the values in a
741 single setreuid or setregid call. */
742
743 if (setreuid (make_uid, user_uid) < 0)
744 pfatal_with_name ("user_access: setreuid");
745
746#endif /* Not HAVE_SETREUID. */
747#endif /* HAVE_SETEUID. */
748
749#ifdef HAVE_SETEGID
750 if (setegid (user_gid) < 0)
751 pfatal_with_name ("user_access: setegid");
752#else
753#ifndef HAVE_SETREGID
754 if (setgid (user_gid) < 0)
755 pfatal_with_name ("user_access: setgid");
756#else
757 if (setregid (make_gid, user_gid) < 0)
758 pfatal_with_name ("user_access: setregid");
759#endif
760#endif
761
762 current_access = user;
763
764 log_access (_("User access"));
765
766#endif /* GETLOADAVG_PRIVILEGED */
767}
768
769/* Give the process appropriate permissions for access to
770 make data (i.e., the load average). */
771void
772make_access (void)
773{
774#ifdef GETLOADAVG_PRIVILEGED
775
776 if (!access_inited)
777 init_access ();
778
779 if (current_access == make)
780 return;
781
782 /* See comments in user_access, above. */
783
784#ifdef HAVE_SETEUID
785 if (seteuid (make_uid) < 0)
786 pfatal_with_name ("make_access: seteuid");
787#else
788#ifndef HAVE_SETREUID
789 if (setuid (make_uid) < 0)
790 pfatal_with_name ("make_access: setuid");
791#else
792 if (setreuid (user_uid, make_uid) < 0)
793 pfatal_with_name ("make_access: setreuid");
794#endif
795#endif
796
797#ifdef HAVE_SETEGID
798 if (setegid (make_gid) < 0)
799 pfatal_with_name ("make_access: setegid");
800#else
801#ifndef HAVE_SETREGID
802 if (setgid (make_gid) < 0)
803 pfatal_with_name ("make_access: setgid");
804#else
805 if (setregid (user_gid, make_gid) < 0)
806 pfatal_with_name ("make_access: setregid");
807#endif
808#endif
809
810 current_access = make;
811
812 log_access (_("Make access"));
813
814#endif /* GETLOADAVG_PRIVILEGED */
815}
816
817/* Give the process appropriate permissions for a child process.
818 This is like user_access, but you can't get back to make_access. */
819void
820child_access (void)
821{
822#ifdef GETLOADAVG_PRIVILEGED
823
824 if (!access_inited)
825 abort ();
826
827 /* Set both the real and effective UID and GID to the user's.
828 They cannot be changed back to make's. */
829
830#ifndef HAVE_SETREUID
831 if (setuid (user_uid) < 0)
832 pfatal_with_name ("child_access: setuid");
833#else
834 if (setreuid (user_uid, user_uid) < 0)
835 pfatal_with_name ("child_access: setreuid");
836#endif
837
838#ifndef HAVE_SETREGID
839 if (setgid (user_gid) < 0)
840 pfatal_with_name ("child_access: setgid");
841#else
842 if (setregid (user_gid, user_gid) < 0)
843 pfatal_with_name ("child_access: setregid");
844#endif
845
846 log_access (_("Child access"));
847
848#endif /* GETLOADAVG_PRIVILEGED */
849}
850
851
852#ifdef NEED_GET_PATH_MAX
853unsigned int
854get_path_max (void)
855{
856 static unsigned int value;
857
858 if (value == 0)
859 {
860 long int x = pathconf ("/", _PC_PATH_MAX);
861 if (x > 0)
862 value = x;
863 else
864 return MAXPATHLEN;
865 }
866
867 return value;
868}
869#endif
870
871
872
873/* This code is stolen from gnulib.
874 If/when we abandon the requirement to work with K&R compilers, we can
875 remove this (and perhaps other parts of GNU make!) and migrate to using
876 gnulib directly.
877
878 This is called only through atexit(), which means die() has already been
879 invoked. So, call exit() here directly. Apparently that works...?
880*/
881
882/* Close standard output, exiting with status 'exit_failure' on failure.
883 If a program writes *anything* to stdout, that program should close
884 stdout and make sure that it succeeds before exiting. Otherwise,
885 suppose that you go to the extreme of checking the return status
886 of every function that does an explicit write to stdout. The last
887 printf can succeed in writing to the internal stream buffer, and yet
888 the fclose(stdout) could still fail (due e.g., to a disk full error)
889 when it tries to write out that buffered data. Thus, you would be
890 left with an incomplete output file and the offending program would
891 exit successfully. Even calling fflush is not always sufficient,
892 since some file systems (NFS and CODA) buffer written/flushed data
893 until an actual close call.
894
895 Besides, it's wasteful to check the return value from every call
896 that writes to stdout -- just let the internal stream state record
897 the failure. That's what the ferror test is checking below.
898
899 It's important to detect such failures and exit nonzero because many
900 tools (most notably `make' and other build-management systems) depend
901 on being able to detect failure in other tools via their exit status. */
902
903void
904close_stdout (void)
905{
906 int prev_fail = ferror (stdout);
907 int fclose_fail = fclose (stdout);
908
909 if (prev_fail || fclose_fail)
910 {
911 if (fclose_fail)
912 error (NILF, _("write error: %s"), strerror (errno));
913 else
914 error (NILF, _("write error"));
915 exit (EXIT_FAILURE);
916 }
917}
Note: See TracBrowser for help on using the repository browser.