1*a8fa202aSchristos /* $NetBSD: closeout.c,v 1.1.1.1 2016/01/10 21:36:18 christos Exp $ */
2*a8fa202aSchristos
3*a8fa202aSchristos /* closeout.c - close standard output
4*a8fa202aSchristos Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
5*a8fa202aSchristos
6*a8fa202aSchristos This program is free software; you can redistribute it and/or modify
7*a8fa202aSchristos it under the terms of the GNU General Public License as published by
8*a8fa202aSchristos the Free Software Foundation; either version 2, or (at your option)
9*a8fa202aSchristos any later version.
10*a8fa202aSchristos
11*a8fa202aSchristos This program is distributed in the hope that it will be useful,
12*a8fa202aSchristos but WITHOUT ANY WARRANTY; without even the implied warranty of
13*a8fa202aSchristos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14*a8fa202aSchristos GNU General Public License for more details.
15*a8fa202aSchristos
16*a8fa202aSchristos You should have received a copy of the GNU General Public License
17*a8fa202aSchristos along with this program; if not, write to the Free Software Foundation,
18*a8fa202aSchristos Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
19*a8fa202aSchristos
20*a8fa202aSchristos #if HAVE_CONFIG_H
21*a8fa202aSchristos # include <config.h>
22*a8fa202aSchristos #endif
23*a8fa202aSchristos
24*a8fa202aSchristos #if ENABLE_NLS
25*a8fa202aSchristos # include <libintl.h>
26*a8fa202aSchristos # define _(Text) gettext (Text)
27*a8fa202aSchristos #else
28*a8fa202aSchristos # define _(Text) Text
29*a8fa202aSchristos #endif
30*a8fa202aSchristos
31*a8fa202aSchristos #if HAVE_STDLIB_H
32*a8fa202aSchristos # include <stdlib.h>
33*a8fa202aSchristos #endif
34*a8fa202aSchristos #ifndef EXIT_FAILURE
35*a8fa202aSchristos # define EXIT_FAILURE 1
36*a8fa202aSchristos #endif
37*a8fa202aSchristos
38*a8fa202aSchristos #include <stdio.h>
39*a8fa202aSchristos
40*a8fa202aSchristos #include <errno.h>
41*a8fa202aSchristos #ifndef errno
42*a8fa202aSchristos extern int errno;
43*a8fa202aSchristos #endif
44*a8fa202aSchristos
45*a8fa202aSchristos #include "closeout.h"
46*a8fa202aSchristos #include "error.h"
47*a8fa202aSchristos #include "quotearg.h"
48*a8fa202aSchristos #if 0
49*a8fa202aSchristos #include "__fpending.h"
50*a8fa202aSchristos #endif
51*a8fa202aSchristos
52*a8fa202aSchristos static int default_exit_status = EXIT_FAILURE;
53*a8fa202aSchristos static const char *file_name;
54*a8fa202aSchristos
55*a8fa202aSchristos /* Set the value to be used for the exit status when close_stdout is called.
56*a8fa202aSchristos This is useful when it is not convenient to call close_stdout_status,
57*a8fa202aSchristos e.g., when close_stdout is called via atexit. */
58*a8fa202aSchristos void
close_stdout_set_status(int status)59*a8fa202aSchristos close_stdout_set_status (int status)
60*a8fa202aSchristos {
61*a8fa202aSchristos default_exit_status = status;
62*a8fa202aSchristos }
63*a8fa202aSchristos
64*a8fa202aSchristos /* Set the file name to be reported in the event an error is detected
65*a8fa202aSchristos by close_stdout_status. */
66*a8fa202aSchristos void
close_stdout_set_file_name(const char * file)67*a8fa202aSchristos close_stdout_set_file_name (const char *file)
68*a8fa202aSchristos {
69*a8fa202aSchristos file_name = file;
70*a8fa202aSchristos }
71*a8fa202aSchristos
72*a8fa202aSchristos /* Close standard output, exiting with status STATUS on failure.
73*a8fa202aSchristos If a program writes *anything* to stdout, that program should `fflush'
74*a8fa202aSchristos stdout and make sure that it succeeds before exiting. Otherwise,
75*a8fa202aSchristos suppose that you go to the extreme of checking the return status
76*a8fa202aSchristos of every function that does an explicit write to stdout. The last
77*a8fa202aSchristos printf can succeed in writing to the internal stream buffer, and yet
78*a8fa202aSchristos the fclose(stdout) could still fail (due e.g., to a disk full error)
79*a8fa202aSchristos when it tries to write out that buffered data. Thus, you would be
80*a8fa202aSchristos left with an incomplete output file and the offending program would
81*a8fa202aSchristos exit successfully.
82*a8fa202aSchristos
83*a8fa202aSchristos FIXME: note the fflush suggested above is implicit in the fclose
84*a8fa202aSchristos we actually do below. Consider doing only the fflush and/or using
85*a8fa202aSchristos setvbuf to inhibit buffering.
86*a8fa202aSchristos
87*a8fa202aSchristos Besides, it's wasteful to check the return value from every call
88*a8fa202aSchristos that writes to stdout -- just let the internal stream state record
89*a8fa202aSchristos the failure. That's what the ferror test is checking below.
90*a8fa202aSchristos
91*a8fa202aSchristos It's important to detect such failures and exit nonzero because many
92*a8fa202aSchristos tools (most notably `make' and other build-management systems) depend
93*a8fa202aSchristos on being able to detect failure in other tools via their exit status. */
94*a8fa202aSchristos
95*a8fa202aSchristos void
close_stdout_status(int status)96*a8fa202aSchristos close_stdout_status (int status)
97*a8fa202aSchristos {
98*a8fa202aSchristos int e = ferror (stdout) ? 0 : -1;
99*a8fa202aSchristos
100*a8fa202aSchristos #if 0
101*a8fa202aSchristos if (__fpending (stdout) == 0)
102*a8fa202aSchristos return;
103*a8fa202aSchristos #endif
104*a8fa202aSchristos
105*a8fa202aSchristos if (fclose (stdout) != 0)
106*a8fa202aSchristos e = errno;
107*a8fa202aSchristos
108*a8fa202aSchristos if (0 < e)
109*a8fa202aSchristos {
110*a8fa202aSchristos char const *write_error = _("write error");
111*a8fa202aSchristos if (file_name)
112*a8fa202aSchristos error (status, e, "%s: %s", quotearg_colon (file_name), write_error);
113*a8fa202aSchristos else
114*a8fa202aSchristos error (status, e, "%s", write_error);
115*a8fa202aSchristos }
116*a8fa202aSchristos }
117*a8fa202aSchristos
118*a8fa202aSchristos /* Close standard output, exiting with status EXIT_FAILURE on failure. */
119*a8fa202aSchristos void
close_stdout(void)120*a8fa202aSchristos close_stdout (void)
121*a8fa202aSchristos {
122*a8fa202aSchristos close_stdout_status (default_exit_status);
123*a8fa202aSchristos }
124