Mercurial > gnulib
annotate lib/closein.c @ 40216:02ed6264c100
strfmon_l: Fix -fsanitize=address finding.
* lib/strfmon_l.c: Include <errno.h>, <stdbool.h>, <stdlib.h>,
<string.h>.
(MAX_ARGS): Renamed from MAX_ARG_WORDS.
(directive_t, directives_t): New types.
(fmon_parse): New function.
(rpl_strfmon_l): Don't call va_arg more often than needed for the
format string. Consume 'long double' arguments in places where the
format string indicates so.
* modules/strfmon_l (Depends-on): Add 'stdbool'.
author | Bruno Haible <bruno@clisp.org> |
---|---|
date | Sat, 09 Mar 2019 23:30:40 +0100 |
parents | b06060465f09 |
children |
rev | line source |
---|---|
8674
72f80d715b09
Work around glibc's failure to reset seekable stdin on exit.
Eric Blake <ebb9@byu.net>
parents:
diff
changeset
|
1 /* Close standard input, rewinding seekable stdin if necessary. |
72f80d715b09
Work around glibc's failure to reset seekable stdin on exit.
Eric Blake <ebb9@byu.net>
parents:
diff
changeset
|
2 |
40057
b06060465f09
maint: Run 'make update-copyright'
Paul Eggert <eggert@cs.ucla.edu>
parents:
19484
diff
changeset
|
3 Copyright (C) 2007, 2009-2019 Free Software Foundation, Inc. |
8674
72f80d715b09
Work around glibc's failure to reset seekable stdin on exit.
Eric Blake <ebb9@byu.net>
parents:
diff
changeset
|
4 |
9309
bbbbbf4cd1c5
Change copyright notice from GPLv2+ to GPLv3+.
Bruno Haible <bruno@clisp.org>
parents:
9160
diff
changeset
|
5 This program is free software: you can redistribute it and/or modify |
8674
72f80d715b09
Work around glibc's failure to reset seekable stdin on exit.
Eric Blake <ebb9@byu.net>
parents:
diff
changeset
|
6 it under the terms of the GNU General Public License as published by |
9309
bbbbbf4cd1c5
Change copyright notice from GPLv2+ to GPLv3+.
Bruno Haible <bruno@clisp.org>
parents:
9160
diff
changeset
|
7 the Free Software Foundation; either version 3 of the License, or |
bbbbbf4cd1c5
Change copyright notice from GPLv2+ to GPLv3+.
Bruno Haible <bruno@clisp.org>
parents:
9160
diff
changeset
|
8 (at your option) any later version. |
8674
72f80d715b09
Work around glibc's failure to reset seekable stdin on exit.
Eric Blake <ebb9@byu.net>
parents:
diff
changeset
|
9 |
72f80d715b09
Work around glibc's failure to reset seekable stdin on exit.
Eric Blake <ebb9@byu.net>
parents:
diff
changeset
|
10 This program is distributed in the hope that it will be useful, |
72f80d715b09
Work around glibc's failure to reset seekable stdin on exit.
Eric Blake <ebb9@byu.net>
parents:
diff
changeset
|
11 but WITHOUT ANY WARRANTY; without even the implied warranty of |
72f80d715b09
Work around glibc's failure to reset seekable stdin on exit.
Eric Blake <ebb9@byu.net>
parents:
diff
changeset
|
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
72f80d715b09
Work around glibc's failure to reset seekable stdin on exit.
Eric Blake <ebb9@byu.net>
parents:
diff
changeset
|
13 GNU General Public License for more details. |
72f80d715b09
Work around glibc's failure to reset seekable stdin on exit.
Eric Blake <ebb9@byu.net>
parents:
diff
changeset
|
14 |
72f80d715b09
Work around glibc's failure to reset seekable stdin on exit.
Eric Blake <ebb9@byu.net>
parents:
diff
changeset
|
15 You should have received a copy of the GNU General Public License |
19190 | 16 along with this program. If not, see <https://www.gnu.org/licenses/>. */ |
8674
72f80d715b09
Work around glibc's failure to reset seekable stdin on exit.
Eric Blake <ebb9@byu.net>
parents:
diff
changeset
|
17 |
72f80d715b09
Work around glibc's failure to reset seekable stdin on exit.
Eric Blake <ebb9@byu.net>
parents:
diff
changeset
|
18 #include <config.h> |
72f80d715b09
Work around glibc's failure to reset seekable stdin on exit.
Eric Blake <ebb9@byu.net>
parents:
diff
changeset
|
19 |
72f80d715b09
Work around glibc's failure to reset seekable stdin on exit.
Eric Blake <ebb9@byu.net>
parents:
diff
changeset
|
20 #include "closein.h" |
72f80d715b09
Work around glibc's failure to reset seekable stdin on exit.
Eric Blake <ebb9@byu.net>
parents:
diff
changeset
|
21 |
72f80d715b09
Work around glibc's failure to reset seekable stdin on exit.
Eric Blake <ebb9@byu.net>
parents:
diff
changeset
|
22 #include <errno.h> |
72f80d715b09
Work around glibc's failure to reset seekable stdin on exit.
Eric Blake <ebb9@byu.net>
parents:
diff
changeset
|
23 #include <stdbool.h> |
72f80d715b09
Work around glibc's failure to reset seekable stdin on exit.
Eric Blake <ebb9@byu.net>
parents:
diff
changeset
|
24 #include <stdio.h> |
72f80d715b09
Work around glibc's failure to reset seekable stdin on exit.
Eric Blake <ebb9@byu.net>
parents:
diff
changeset
|
25 #include <unistd.h> |
72f80d715b09
Work around glibc's failure to reset seekable stdin on exit.
Eric Blake <ebb9@byu.net>
parents:
diff
changeset
|
26 |
72f80d715b09
Work around glibc's failure to reset seekable stdin on exit.
Eric Blake <ebb9@byu.net>
parents:
diff
changeset
|
27 #include "gettext.h" |
72f80d715b09
Work around glibc's failure to reset seekable stdin on exit.
Eric Blake <ebb9@byu.net>
parents:
diff
changeset
|
28 #define _(msgid) gettext (msgid) |
72f80d715b09
Work around glibc's failure to reset seekable stdin on exit.
Eric Blake <ebb9@byu.net>
parents:
diff
changeset
|
29 |
72f80d715b09
Work around glibc's failure to reset seekable stdin on exit.
Eric Blake <ebb9@byu.net>
parents:
diff
changeset
|
30 #include "close-stream.h" |
8730 | 31 #include "closeout.h" |
8674
72f80d715b09
Work around glibc's failure to reset seekable stdin on exit.
Eric Blake <ebb9@byu.net>
parents:
diff
changeset
|
32 #include "error.h" |
72f80d715b09
Work around glibc's failure to reset seekable stdin on exit.
Eric Blake <ebb9@byu.net>
parents:
diff
changeset
|
33 #include "exitfail.h" |
9160
3ba41f99309f
Optimization: no need to flush stdin if we can determine quickly that stdin's
Bruno Haible <bruno@clisp.org>
parents:
8730
diff
changeset
|
34 #include "freadahead.h" |
8674
72f80d715b09
Work around glibc's failure to reset seekable stdin on exit.
Eric Blake <ebb9@byu.net>
parents:
diff
changeset
|
35 #include "quotearg.h" |
72f80d715b09
Work around glibc's failure to reset seekable stdin on exit.
Eric Blake <ebb9@byu.net>
parents:
diff
changeset
|
36 |
72f80d715b09
Work around glibc's failure to reset seekable stdin on exit.
Eric Blake <ebb9@byu.net>
parents:
diff
changeset
|
37 static const char *file_name; |
72f80d715b09
Work around glibc's failure to reset seekable stdin on exit.
Eric Blake <ebb9@byu.net>
parents:
diff
changeset
|
38 |
72f80d715b09
Work around glibc's failure to reset seekable stdin on exit.
Eric Blake <ebb9@byu.net>
parents:
diff
changeset
|
39 /* Set the file name to be reported in the event an error is detected |
72f80d715b09
Work around glibc's failure to reset seekable stdin on exit.
Eric Blake <ebb9@byu.net>
parents:
diff
changeset
|
40 on stdin by close_stdin. See also close_stdout_set_file_name, if |
72f80d715b09
Work around glibc's failure to reset seekable stdin on exit.
Eric Blake <ebb9@byu.net>
parents:
diff
changeset
|
41 an error is detected when closing stdout. */ |
72f80d715b09
Work around glibc's failure to reset seekable stdin on exit.
Eric Blake <ebb9@byu.net>
parents:
diff
changeset
|
42 void |
72f80d715b09
Work around glibc's failure to reset seekable stdin on exit.
Eric Blake <ebb9@byu.net>
parents:
diff
changeset
|
43 close_stdin_set_file_name (const char *file) |
72f80d715b09
Work around glibc's failure to reset seekable stdin on exit.
Eric Blake <ebb9@byu.net>
parents:
diff
changeset
|
44 { |
72f80d715b09
Work around glibc's failure to reset seekable stdin on exit.
Eric Blake <ebb9@byu.net>
parents:
diff
changeset
|
45 file_name = file; |
72f80d715b09
Work around glibc's failure to reset seekable stdin on exit.
Eric Blake <ebb9@byu.net>
parents:
diff
changeset
|
46 } |
72f80d715b09
Work around glibc's failure to reset seekable stdin on exit.
Eric Blake <ebb9@byu.net>
parents:
diff
changeset
|
47 |
72f80d715b09
Work around glibc's failure to reset seekable stdin on exit.
Eric Blake <ebb9@byu.net>
parents:
diff
changeset
|
48 /* Close standard input, rewinding any unused input if stdin is |
72f80d715b09
Work around glibc's failure to reset seekable stdin on exit.
Eric Blake <ebb9@byu.net>
parents:
diff
changeset
|
49 seekable. On error, issue a diagnostic and _exit with status |
72f80d715b09
Work around glibc's failure to reset seekable stdin on exit.
Eric Blake <ebb9@byu.net>
parents:
diff
changeset
|
50 'exit_failure'. Then call close_stdout. |
72f80d715b09
Work around glibc's failure to reset seekable stdin on exit.
Eric Blake <ebb9@byu.net>
parents:
diff
changeset
|
51 |
72f80d715b09
Work around glibc's failure to reset seekable stdin on exit.
Eric Blake <ebb9@byu.net>
parents:
diff
changeset
|
52 Most programs can get by with close_stdout. close_stdin is only |
72f80d715b09
Work around glibc's failure to reset seekable stdin on exit.
Eric Blake <ebb9@byu.net>
parents:
diff
changeset
|
53 needed when a program wants to guarantee that partially read input |
72f80d715b09
Work around glibc's failure to reset seekable stdin on exit.
Eric Blake <ebb9@byu.net>
parents:
diff
changeset
|
54 from seekable stdin is not consumed, for any subsequent clients. |
72f80d715b09
Work around glibc's failure to reset seekable stdin on exit.
Eric Blake <ebb9@byu.net>
parents:
diff
changeset
|
55 For example, POSIX requires that these two commands behave alike: |
72f80d715b09
Work around glibc's failure to reset seekable stdin on exit.
Eric Blake <ebb9@byu.net>
parents:
diff
changeset
|
56 |
72f80d715b09
Work around glibc's failure to reset seekable stdin on exit.
Eric Blake <ebb9@byu.net>
parents:
diff
changeset
|
57 (sed -ne 1q; cat) < file |
15509 | 58 tail -n +2 file |
8674
72f80d715b09
Work around glibc's failure to reset seekable stdin on exit.
Eric Blake <ebb9@byu.net>
parents:
diff
changeset
|
59 |
72f80d715b09
Work around glibc's failure to reset seekable stdin on exit.
Eric Blake <ebb9@byu.net>
parents:
diff
changeset
|
60 Since close_stdin is commonly registered via 'atexit', POSIX |
72f80d715b09
Work around glibc's failure to reset seekable stdin on exit.
Eric Blake <ebb9@byu.net>
parents:
diff
changeset
|
61 and the C standard both say that it should not call 'exit', |
72f80d715b09
Work around glibc's failure to reset seekable stdin on exit.
Eric Blake <ebb9@byu.net>
parents:
diff
changeset
|
62 because the behavior is undefined if 'exit' is called more than |
72f80d715b09
Work around glibc's failure to reset seekable stdin on exit.
Eric Blake <ebb9@byu.net>
parents:
diff
changeset
|
63 once. So it calls '_exit' instead of 'exit'. If close_stdin |
72f80d715b09
Work around glibc's failure to reset seekable stdin on exit.
Eric Blake <ebb9@byu.net>
parents:
diff
changeset
|
64 is registered via atexit before other functions are registered, |
72f80d715b09
Work around glibc's failure to reset seekable stdin on exit.
Eric Blake <ebb9@byu.net>
parents:
diff
changeset
|
65 the other functions can act before this _exit is invoked. |
72f80d715b09
Work around glibc's failure to reset seekable stdin on exit.
Eric Blake <ebb9@byu.net>
parents:
diff
changeset
|
66 |
72f80d715b09
Work around glibc's failure to reset seekable stdin on exit.
Eric Blake <ebb9@byu.net>
parents:
diff
changeset
|
67 Applications that use close_stdout should flush any streams other |
72f80d715b09
Work around glibc's failure to reset seekable stdin on exit.
Eric Blake <ebb9@byu.net>
parents:
diff
changeset
|
68 than stdin, stdout, and stderr before exiting, since the call to |
72f80d715b09
Work around glibc's failure to reset seekable stdin on exit.
Eric Blake <ebb9@byu.net>
parents:
diff
changeset
|
69 _exit will bypass other buffer flushing. Applications should be |
72f80d715b09
Work around glibc's failure to reset seekable stdin on exit.
Eric Blake <ebb9@byu.net>
parents:
diff
changeset
|
70 flushing and closing other streams anyway, to check for I/O errors. |
72f80d715b09
Work around glibc's failure to reset seekable stdin on exit.
Eric Blake <ebb9@byu.net>
parents:
diff
changeset
|
71 Also, applications should not use tmpfile, since _exit can bypass |
72f80d715b09
Work around glibc's failure to reset seekable stdin on exit.
Eric Blake <ebb9@byu.net>
parents:
diff
changeset
|
72 the removal of these files. |
72f80d715b09
Work around glibc's failure to reset seekable stdin on exit.
Eric Blake <ebb9@byu.net>
parents:
diff
changeset
|
73 |
72f80d715b09
Work around glibc's failure to reset seekable stdin on exit.
Eric Blake <ebb9@byu.net>
parents:
diff
changeset
|
74 It's important to detect such failures and exit nonzero because many |
16235
18a38c9615f0
In commentary, do not use ` to quote.
Paul Eggert <eggert@cs.ucla.edu>
parents:
16201
diff
changeset
|
75 tools (most notably 'make' and other build-management systems) depend |
8674
72f80d715b09
Work around glibc's failure to reset seekable stdin on exit.
Eric Blake <ebb9@byu.net>
parents:
diff
changeset
|
76 on being able to detect failure in other tools via their exit status. */ |
72f80d715b09
Work around glibc's failure to reset seekable stdin on exit.
Eric Blake <ebb9@byu.net>
parents:
diff
changeset
|
77 |
72f80d715b09
Work around glibc's failure to reset seekable stdin on exit.
Eric Blake <ebb9@byu.net>
parents:
diff
changeset
|
78 void |
72f80d715b09
Work around glibc's failure to reset seekable stdin on exit.
Eric Blake <ebb9@byu.net>
parents:
diff
changeset
|
79 close_stdin (void) |
72f80d715b09
Work around glibc's failure to reset seekable stdin on exit.
Eric Blake <ebb9@byu.net>
parents:
diff
changeset
|
80 { |
72f80d715b09
Work around glibc's failure to reset seekable stdin on exit.
Eric Blake <ebb9@byu.net>
parents:
diff
changeset
|
81 bool fail = false; |
8730 | 82 |
9160
3ba41f99309f
Optimization: no need to flush stdin if we can determine quickly that stdin's
Bruno Haible <bruno@clisp.org>
parents:
8730
diff
changeset
|
83 /* There is no need to flush stdin if we can determine quickly that stdin's |
3ba41f99309f
Optimization: no need to flush stdin if we can determine quickly that stdin's
Bruno Haible <bruno@clisp.org>
parents:
8730
diff
changeset
|
84 input buffer is empty; in this case we know that if stdin is seekable, |
15509 | 85 (fseeko (stdin, 0, SEEK_CUR), ftello (stdin)) |
86 == lseek (0, 0, SEEK_CUR). */ | |
9160
3ba41f99309f
Optimization: no need to flush stdin if we can determine quickly that stdin's
Bruno Haible <bruno@clisp.org>
parents:
8730
diff
changeset
|
87 if (freadahead (stdin) > 0) |
3ba41f99309f
Optimization: no need to flush stdin if we can determine quickly that stdin's
Bruno Haible <bruno@clisp.org>
parents:
8730
diff
changeset
|
88 { |
3ba41f99309f
Optimization: no need to flush stdin if we can determine quickly that stdin's
Bruno Haible <bruno@clisp.org>
parents:
8730
diff
changeset
|
89 /* Only attempt flush if stdin is seekable, as fflush is entitled to |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
9309
diff
changeset
|
90 fail on non-seekable streams. */ |
9160
3ba41f99309f
Optimization: no need to flush stdin if we can determine quickly that stdin's
Bruno Haible <bruno@clisp.org>
parents:
8730
diff
changeset
|
91 if (fseeko (stdin, 0, SEEK_CUR) == 0 && fflush (stdin) != 0) |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
9309
diff
changeset
|
92 fail = true; |
9160
3ba41f99309f
Optimization: no need to flush stdin if we can determine quickly that stdin's
Bruno Haible <bruno@clisp.org>
parents:
8730
diff
changeset
|
93 } |
8730 | 94 if (close_stream (stdin) != 0) |
95 fail = true; | |
96 if (fail) | |
8674
72f80d715b09
Work around glibc's failure to reset seekable stdin on exit.
Eric Blake <ebb9@byu.net>
parents:
diff
changeset
|
97 { |
8730 | 98 /* Report failure, but defer exit until after closing stdout, |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
9309
diff
changeset
|
99 since the failure report should still be flushed. */ |
8674
72f80d715b09
Work around glibc's failure to reset seekable stdin on exit.
Eric Blake <ebb9@byu.net>
parents:
diff
changeset
|
100 char const *close_error = _("error closing file"); |
72f80d715b09
Work around glibc's failure to reset seekable stdin on exit.
Eric Blake <ebb9@byu.net>
parents:
diff
changeset
|
101 if (file_name) |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
9309
diff
changeset
|
102 error (0, errno, "%s: %s", quotearg_colon (file_name), |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
9309
diff
changeset
|
103 close_error); |
8674
72f80d715b09
Work around glibc's failure to reset seekable stdin on exit.
Eric Blake <ebb9@byu.net>
parents:
diff
changeset
|
104 else |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
9309
diff
changeset
|
105 error (0, errno, "%s", close_error); |
8674
72f80d715b09
Work around glibc's failure to reset seekable stdin on exit.
Eric Blake <ebb9@byu.net>
parents:
diff
changeset
|
106 } |
72f80d715b09
Work around glibc's failure to reset seekable stdin on exit.
Eric Blake <ebb9@byu.net>
parents:
diff
changeset
|
107 |
72f80d715b09
Work around glibc's failure to reset seekable stdin on exit.
Eric Blake <ebb9@byu.net>
parents:
diff
changeset
|
108 close_stdout (); |
72f80d715b09
Work around glibc's failure to reset seekable stdin on exit.
Eric Blake <ebb9@byu.net>
parents:
diff
changeset
|
109 |
72f80d715b09
Work around glibc's failure to reset seekable stdin on exit.
Eric Blake <ebb9@byu.net>
parents:
diff
changeset
|
110 if (fail) |
72f80d715b09
Work around glibc's failure to reset seekable stdin on exit.
Eric Blake <ebb9@byu.net>
parents:
diff
changeset
|
111 _exit (exit_failure); |
72f80d715b09
Work around glibc's failure to reset seekable stdin on exit.
Eric Blake <ebb9@byu.net>
parents:
diff
changeset
|
112 } |