VirtualBox

source: kBuild/vendor/gnumake/current/misc.c@ 501

Last change on this file since 501 was 501, checked in by bird, 18 years ago

Load make-3.81/ into vendor/gnumake/current.

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