Line data Source code
1 : /* Close standard input, rewinding seekable stdin if necessary.
2 :
3 : Copyright (C) 2007 Free Software Foundation, Inc.
4 :
5 : This program is free software: you can redistribute it and/or modify
6 : it under the terms of the GNU General Public License as published by
7 : the Free Software Foundation; either version 3 of the License, or
8 : (at your option) any later version.
9 :
10 : This program is distributed in the hope that it will be useful,
11 : but WITHOUT ANY WARRANTY; without even the implied warranty of
12 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 : GNU General Public License for more details.
14 :
15 : You should have received a copy of the GNU General Public License
16 : along with this program. If not, see <http://www.gnu.org/licenses/>. */
17 :
18 : #include <config.h>
19 :
20 : #include "closein.h"
21 :
22 : #include <errno.h>
23 : #include <stdbool.h>
24 : #include <stdio.h>
25 : #include <unistd.h>
26 :
27 : #include "gettext.h"
28 : #define _(msgid) gettext (msgid)
29 :
30 : #include "close-stream.h"
31 : #include "closeout.h"
32 : #include "error.h"
33 : #include "exitfail.h"
34 : #include "freadahead.h"
35 : #include "quotearg.h"
36 :
37 : static const char *file_name;
38 :
39 : /* Set the file name to be reported in the event an error is detected
40 : on stdin by close_stdin. See also close_stdout_set_file_name, if
41 : an error is detected when closing stdout. */
42 : void
43 0 : close_stdin_set_file_name (const char *file)
44 : {
45 0 : file_name = file;
46 0 : }
47 :
48 : /* Close standard input, rewinding any unused input if stdin is
49 : seekable. On error, issue a diagnostic and _exit with status
50 : 'exit_failure'. Then call close_stdout.
51 :
52 : Most programs can get by with close_stdout. close_stdin is only
53 : needed when a program wants to guarantee that partially read input
54 : from seekable stdin is not consumed, for any subsequent clients.
55 : For example, POSIX requires that these two commands behave alike:
56 :
57 : (sed -ne 1q; cat) < file
58 : tail -n 1 file
59 :
60 : Since close_stdin is commonly registered via 'atexit', POSIX
61 : and the C standard both say that it should not call 'exit',
62 : because the behavior is undefined if 'exit' is called more than
63 : once. So it calls '_exit' instead of 'exit'. If close_stdin
64 : is registered via atexit before other functions are registered,
65 : the other functions can act before this _exit is invoked.
66 :
67 : Applications that use close_stdout should flush any streams other
68 : than stdin, stdout, and stderr before exiting, since the call to
69 : _exit will bypass other buffer flushing. Applications should be
70 : flushing and closing other streams anyway, to check for I/O errors.
71 : Also, applications should not use tmpfile, since _exit can bypass
72 : the removal of these files.
73 :
74 : It's important to detect such failures and exit nonzero because many
75 : tools (most notably `make' and other build-management systems) depend
76 : on being able to detect failure in other tools via their exit status. */
77 :
78 : void
79 666 : close_stdin (void)
80 : {
81 666 : bool fail = false;
82 :
83 : /* There is no need to flush stdin if we can determine quickly that stdin's
84 : input buffer is empty; in this case we know that if stdin is seekable,
85 : fseeko (stdin, 0, SEEK_CUR) == lseek (0, 0, SEEK_CUR). */
86 666 : if (freadahead (stdin) > 0)
87 : {
88 : /* Only attempt flush if stdin is seekable, as fflush is entitled to
89 : fail on non-seekable streams. */
90 12 : if (fseeko (stdin, 0, SEEK_CUR) == 0 && fflush (stdin) != 0)
91 0 : fail = true;
92 : }
93 666 : if (close_stream (stdin) != 0)
94 0 : fail = true;
95 666 : if (fail)
96 : {
97 : /* Report failure, but defer exit until after closing stdout,
98 : since the failure report should still be flushed. */
99 0 : char const *close_error = _("error closing file");
100 0 : if (file_name)
101 0 : error (0, errno, "%s: %s", quotearg_colon (file_name),
102 : close_error);
103 : else
104 0 : error (0, errno, "%s", close_error);
105 : }
106 :
107 666 : close_stdout ();
108 :
109 666 : if (fail)
110 0 : _exit (exit_failure);
111 666 : }
|