spawn-pipe: Simplify.
[gnulib.git] / lib / error.c
blob837d5e56c624996e72d42400c5de43384c9019e5
1 /* Error handler for noninteractive utilities
2 Copyright (C) 1990-2024 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
10 The GNU C Library 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 GNU
13 Lesser General Public License for more details.
15 You should have received a copy of the GNU Lesser General Public
16 License along with the GNU C Library; if not, see
17 <https://www.gnu.org/licenses/>. */
19 /* Written by David MacKenzie <djm@gnu.ai.mit.edu>. */
21 #if !_LIBC
22 # include <config.h>
23 # define _GL_NO_INLINE_ERROR
24 # define __error_internal(status, err, fmt, args, flags) \
25 verror (status, err, fmt, args)
26 # define __error_at_line_internal(status, err, file, line, fmt, args, flags) \
27 verror_at_line (status, err, file, line, fmt, args)
28 # define error_tail(status, err, fmt, args, flags) \
29 error_tail (status, err, fmt, args)
30 #endif
32 #include <error.h>
34 #include <stdarg.h>
35 #include <stdio.h>
36 #include <stdlib.h>
37 #include <string.h>
39 #if !_LIBC && ENABLE_NLS
40 # include "gettext.h"
41 # define _(msgid) gettext (msgid)
42 #endif
44 #ifdef _LIBC
45 # include <libintl.h>
46 # include <stdbool.h>
47 # include <stdint.h>
48 # include <wchar.h>
49 # define mbsrtowcs __mbsrtowcs
50 # define USE_UNLOCKED_IO 0
51 # define _GL_ATTRIBUTE_FORMAT_PRINTF_STANDARD(a, b)
52 # define _GL_ARG_NONNULL(a)
53 #endif
55 #if USE_UNLOCKED_IO
56 # include "unlocked-io.h"
57 #endif
59 #ifndef _
60 # define _(String) String
61 #endif
63 /* If NULL, error will flush stdout, then print on stderr the program
64 name, a colon and a space. Otherwise, error will call this
65 function without parameters instead. */
66 void (*error_print_progname) (void);
68 /* This variable is incremented each time 'error' is called. */
69 unsigned int error_message_count;
71 #ifdef _LIBC
72 /* In the GNU C library, there is a predefined variable for this. */
74 # define program_name program_invocation_name
75 # include <errno.h>
76 # include <limits.h>
77 # include <libio/libioP.h>
79 /* In GNU libc we want do not want to use the common name 'error' directly.
80 Instead make it a weak alias. */
81 extern void __error (int status, int errnum, const char *message, ...)
82 __attribute__ ((__format__ (__printf__, 3, 4)));
83 extern void __error_at_line (int status, int errnum, const char *file_name,
84 unsigned int line_number, const char *message,
85 ...)
86 __attribute__ ((__format__ (__printf__, 5, 6)));
87 # define error __error
88 # define error_at_line __error_at_line
90 # include <libio/iolibio.h>
91 # define fflush(s) _IO_fflush (s)
92 # undef putc
93 # define putc(c, fp) _IO_putc (c, fp)
95 # include <libc-lock.h>
97 #else /* not _LIBC */
99 # include <fcntl.h>
100 # include <unistd.h>
102 # if defined _WIN32 && ! defined __CYGWIN__
103 /* Get declarations of the native Windows API functions. */
104 # define WIN32_LEAN_AND_MEAN
105 # include <windows.h>
106 /* Get _get_osfhandle. */
107 # if GNULIB_MSVC_NOTHROW
108 # include "msvc-nothrow.h"
109 # else
110 # include <io.h>
111 # endif
112 # endif
114 /* The gnulib override of fcntl is not needed in this file. */
115 # undef fcntl
117 # if !(GNULIB_STRERROR_R_POSIX || HAVE_DECL_STRERROR_R)
118 # ifndef HAVE_DECL_STRERROR_R
119 "this configure-time declaration test was not run"
120 # endif
121 # if STRERROR_R_CHAR_P
122 char *strerror_r (int errnum, char *buf, size_t buflen);
123 # else
124 int strerror_r (int errnum, char *buf, size_t buflen);
125 # endif
126 # endif
128 # define program_name getprogname ()
130 # if GNULIB_STRERROR_R_POSIX || HAVE_STRERROR_R || defined strerror_r
131 # define __strerror_r strerror_r
132 # endif /* GNULIB_STRERROR_R_POSIX || HAVE_STRERROR_R || defined strerror_r */
134 # if GNULIB_defined_verror
135 # undef verror
136 # endif
137 # if GNULIB_defined_verror_at_line
138 # undef verror_at_line
139 # endif
140 #endif /* not _LIBC */
142 #if !_LIBC
143 /* Return non-zero if FD is open. */
144 static int
145 is_open (int fd)
147 # if defined _WIN32 && ! defined __CYGWIN__
148 /* On native Windows: The initial state of unassigned standard file
149 descriptors is that they are open but point to an INVALID_HANDLE_VALUE.
150 There is no fcntl, and the gnulib replacement fcntl does not support
151 F_GETFL. */
152 return (HANDLE) _get_osfhandle (fd) != INVALID_HANDLE_VALUE;
153 # else
154 # ifndef F_GETFL
155 # error Please port fcntl to your platform
156 # endif
157 return 0 <= fcntl (fd, F_GETFL);
158 # endif
160 #endif
162 static void
163 flush_stdout (void)
165 #if !_LIBC
166 int stdout_fd;
168 # if GNULIB_FREOPEN_SAFER
169 /* Use of gnulib's freopen-safer module normally ensures that
170 fileno (stdout) == 1
171 whenever stdout is open. */
172 stdout_fd = STDOUT_FILENO;
173 # else
174 /* POSIX states that fileno (stdout) after fclose is unspecified. But in
175 practice it is not a problem, because stdout is statically allocated and
176 the fd of a FILE stream is stored as a field in its allocated memory. */
177 stdout_fd = fileno (stdout);
178 # endif
179 /* POSIX states that fflush (stdout) after fclose is unspecified; it
180 is safe in glibc, but not on all other platforms. fflush (NULL)
181 is always defined, but too draconian. */
182 if (0 <= stdout_fd && is_open (stdout_fd))
183 #endif
184 fflush (stdout);
187 static void
188 print_errno_message (int errnum)
190 char const *s;
192 #if _LIBC || GNULIB_STRERROR_R_POSIX || defined HAVE_STRERROR_R
193 char errbuf[1024];
194 # if _LIBC || (!GNULIB_STRERROR_R_POSIX && STRERROR_R_CHAR_P)
195 s = __strerror_r (errnum, errbuf, sizeof errbuf);
196 # else
197 if (__strerror_r (errnum, errbuf, sizeof errbuf) == 0)
198 s = errbuf;
199 else
200 s = 0;
201 # endif
202 #else
203 s = strerror (errnum);
204 #endif
206 #if !_LIBC
207 if (! s)
208 s = _("Unknown system error");
209 #endif
211 #if _LIBC
212 __fxprintf (NULL, ": %s", s);
213 #else
214 fprintf (stderr, ": %s", s);
215 #endif
218 static void _GL_ATTRIBUTE_FORMAT_PRINTF_STANDARD (3, 0) _GL_ARG_NONNULL ((3))
219 error_tail (int status, int errnum, const char *message, va_list args,
220 unsigned int mode_flags)
222 #if _LIBC
223 int ret = __vfxprintf (stderr, message, args, mode_flags);
224 if (ret < 0 && errno == ENOMEM && _IO_fwide (stderr, 0) > 0)
225 /* Leave a trace in case the heap allocation of the message string
226 failed. */
227 fputws_unlocked (L"out of memory\n", stderr);
228 #else
229 vfprintf (stderr, message, args);
230 #endif
231 va_end (args);
233 ++error_message_count;
234 if (errnum)
235 print_errno_message (errnum);
236 #if _LIBC
237 __fxprintf (NULL, "\n");
238 #else
239 putc ('\n', stderr);
240 #endif
241 fflush (stderr);
242 if (status)
243 exit (status);
247 /* Print the program name and error message MESSAGE, which is a printf-style
248 format string with optional args.
249 If ERRNUM is nonzero, print its corresponding system error message.
250 Exit with status STATUS if it is nonzero. */
251 void
252 __error_internal (int status, int errnum, const char *message,
253 va_list args, unsigned int mode_flags)
255 #if defined _LIBC
256 /* We do not want this call to be cut short by a thread
257 cancellation. Therefore disable cancellation for now. */
258 int state = PTHREAD_CANCEL_ENABLE;
259 __pthread_setcancelstate (PTHREAD_CANCEL_DISABLE, &state);
260 #endif
262 flush_stdout ();
263 #ifdef _LIBC
264 _IO_flockfile (stderr);
265 #endif
266 if (error_print_progname)
267 (*error_print_progname) ();
268 else
270 #if _LIBC
271 __fxprintf (NULL, "%s: ", program_name);
272 #else
273 fprintf (stderr, "%s: ", program_name);
274 #endif
277 error_tail (status, errnum, message, args, mode_flags);
279 #ifdef _LIBC
280 _IO_funlockfile (stderr);
281 __pthread_setcancelstate (state, NULL);
282 #endif
285 void
286 error (int status, int errnum, const char *message, ...)
288 va_list ap;
289 va_start (ap, message);
290 __error_internal (status, errnum, message, ap, 0);
291 va_end (ap);
294 /* Sometimes we want to have at most one error per line. This
295 variable controls whether this mode is selected or not. */
296 int error_one_per_line;
298 void
299 __error_at_line_internal (int status, int errnum, const char *file_name,
300 unsigned int line_number, const char *message,
301 va_list args, unsigned int mode_flags)
303 if (error_one_per_line)
305 static const char *old_file_name;
306 static unsigned int old_line_number;
308 if (old_line_number == line_number
309 && (file_name == old_file_name
310 || (old_file_name != NULL
311 && file_name != NULL
312 && strcmp (old_file_name, file_name) == 0)))
314 /* Simply return and print nothing. */
315 return;
317 old_file_name = file_name;
318 old_line_number = line_number;
321 #if defined _LIBC
322 /* We do not want this call to be cut short by a thread
323 cancellation. Therefore disable cancellation for now. */
324 int state = PTHREAD_CANCEL_ENABLE;
325 __pthread_setcancelstate (PTHREAD_CANCEL_DISABLE, &state);
326 #endif
328 flush_stdout ();
329 #ifdef _LIBC
330 _IO_flockfile (stderr);
331 #endif
332 if (error_print_progname)
333 (*error_print_progname) ();
334 else
336 #if _LIBC
337 __fxprintf (NULL, "%s:", program_name);
338 #else
339 fprintf (stderr, "%s:", program_name);
340 #endif
343 #if _LIBC
344 __fxprintf (NULL, file_name != NULL ? "%s:%u: " : " ",
345 file_name, line_number);
346 #else
347 fprintf (stderr, file_name != NULL ? "%s:%u: " : " ",
348 file_name, line_number);
349 #endif
351 error_tail (status, errnum, message, args, mode_flags);
353 #ifdef _LIBC
354 _IO_funlockfile (stderr);
355 __pthread_setcancelstate (state, NULL);
356 #endif
359 void
360 error_at_line (int status, int errnum, const char *file_name,
361 unsigned int line_number, const char *message, ...)
363 va_list ap;
364 va_start (ap, message);
365 __error_at_line_internal (status, errnum, file_name, line_number,
366 message, ap, 0);
367 va_end (ap);
370 #ifdef _LIBC
371 /* Make the weak alias. */
372 # undef error
373 # undef error_at_line
374 weak_alias (__error, error)
375 weak_alias (__error_at_line, error_at_line)
376 #endif