summaryrefslogtreecommitdiffstats
path: root/gl/error.c
diff options
context:
space:
mode:
Diffstat (limited to 'gl/error.c')
-rw-r--r--gl/error.c182
1 files changed, 73 insertions, 109 deletions
diff --git a/gl/error.c b/gl/error.c
index 6875f134..9231c79c 100644
--- a/gl/error.c
+++ b/gl/error.c
@@ -1,27 +1,35 @@
1/* Error handler for noninteractive utilities 1/* Error handler for noninteractive utilities
2 Copyright (C) 1990-1998, 2000-2007, 2009-2023 Free Software Foundation, Inc. 2 Copyright (C) 1990-2025 Free Software Foundation, Inc.
3 This file is part of the GNU C Library. 3 This file is part of the GNU C Library.
4 4
5 This file is free software: you can redistribute it and/or modify 5 The GNU C Library is free software; you can redistribute it and/or
6 it under the terms of the GNU Lesser General Public License as 6 modify it under the terms of the GNU Lesser General Public
7 published by the Free Software Foundation; either version 2.1 of the 7 License as published by the Free Software Foundation; either
8 License, or (at your option) any later version. 8 version 2.1 of the License, or (at your option) any later version.
9 9
10 This file is distributed in the hope that it will be useful, 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 11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 GNU Lesser General Public License for more details. 13 Lesser General Public License for more details.
14 14
15 You should have received a copy of the GNU Lesser General Public License 15 You should have received a copy of the GNU Lesser General Public
16 along with this program. If not, see <https://www.gnu.org/licenses/>. */ 16 License along with the GNU C Library; if not, see
17 <https://www.gnu.org/licenses/>. */
17 18
18/* Written by David MacKenzie <djm@gnu.ai.mit.edu>. */ 19/* Written by David MacKenzie <djm@gnu.ai.mit.edu>. */
19 20
20#if !_LIBC 21#if !_LIBC
21# include <config.h> 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)
22#endif 30#endif
23 31
24#include "error.h" 32#include <error.h>
25 33
26#include <stdarg.h> 34#include <stdarg.h>
27#include <stdio.h> 35#include <stdio.h>
@@ -30,7 +38,7 @@
30 38
31#if !_LIBC && ENABLE_NLS 39#if !_LIBC && ENABLE_NLS
32# include "gettext.h" 40# include "gettext.h"
33# define _(msgid) gettext (msgid) 41# define _(msgid) dgettext ("gnulib", msgid)
34#endif 42#endif
35 43
36#ifdef _LIBC 44#ifdef _LIBC
@@ -42,8 +50,6 @@
42# define USE_UNLOCKED_IO 0 50# define USE_UNLOCKED_IO 0
43# define _GL_ATTRIBUTE_FORMAT_PRINTF_STANDARD(a, b) 51# define _GL_ATTRIBUTE_FORMAT_PRINTF_STANDARD(a, b)
44# define _GL_ARG_NONNULL(a) 52# define _GL_ARG_NONNULL(a)
45#else
46# include "getprogname.h"
47#endif 53#endif
48 54
49#if USE_UNLOCKED_IO 55#if USE_UNLOCKED_IO
@@ -86,7 +92,7 @@ extern void __error_at_line (int status, int errnum, const char *file_name,
86# undef putc 92# undef putc
87# define putc(c, fp) _IO_putc (c, fp) 93# define putc(c, fp) _IO_putc (c, fp)
88 94
89# include <bits/libc-lock.h> 95# include <libc-lock.h>
90 96
91#else /* not _LIBC */ 97#else /* not _LIBC */
92 98
@@ -124,6 +130,13 @@ int strerror_r (int errnum, char *buf, size_t buflen);
124# if GNULIB_STRERROR_R_POSIX || HAVE_STRERROR_R || defined strerror_r 130# if GNULIB_STRERROR_R_POSIX || HAVE_STRERROR_R || defined strerror_r
125# define __strerror_r strerror_r 131# define __strerror_r strerror_r
126# endif /* GNULIB_STRERROR_R_POSIX || HAVE_STRERROR_R || defined strerror_r */ 132# endif /* GNULIB_STRERROR_R_POSIX || HAVE_STRERROR_R || defined strerror_r */
133
134# if GNULIB_defined_verror
135# undef verror
136# endif
137# if GNULIB_defined_verror_at_line
138# undef verror_at_line
139# endif
127#endif /* not _LIBC */ 140#endif /* not _LIBC */
128 141
129#if !_LIBC 142#if !_LIBC
@@ -152,8 +165,8 @@ flush_stdout (void)
152#if !_LIBC 165#if !_LIBC
153 int stdout_fd; 166 int stdout_fd;
154 167
155# if GNULIB_FREOPEN_SAFER 168# if GNULIB_FREOPEN_SAFER || GNULIB_XSTDOPEN
156 /* Use of gnulib's freopen-safer module normally ensures that 169 /* Gnulib's freopen-safer and/or xstdopen modules normally ensure that
157 fileno (stdout) == 1 170 fileno (stdout) == 1
158 whenever stdout is open. */ 171 whenever stdout is open. */
159 stdout_fd = STDOUT_FILENO; 172 stdout_fd = STDOUT_FILENO;
@@ -184,7 +197,7 @@ print_errno_message (int errnum)
184 if (__strerror_r (errnum, errbuf, sizeof errbuf) == 0) 197 if (__strerror_r (errnum, errbuf, sizeof errbuf) == 0)
185 s = errbuf; 198 s = errbuf;
186 else 199 else
187 s = 0; 200 s = NULL;
188# endif 201# endif
189#else 202#else
190 s = strerror (errnum); 203 s = strerror (errnum);
@@ -203,75 +216,18 @@ print_errno_message (int errnum)
203} 216}
204 217
205static void _GL_ATTRIBUTE_FORMAT_PRINTF_STANDARD (3, 0) _GL_ARG_NONNULL ((3)) 218static void _GL_ATTRIBUTE_FORMAT_PRINTF_STANDARD (3, 0) _GL_ARG_NONNULL ((3))
206error_tail (int status, int errnum, const char *message, va_list args) 219error_tail (int status, int errnum, const char *message, va_list args,
220 unsigned int mode_flags)
207{ 221{
208#if _LIBC 222#if _LIBC
209 if (_IO_fwide (stderr, 0) > 0) 223 int ret = __vfxprintf (stderr, message, args, mode_flags);
210 { 224 if (ret < 0 && errno == ENOMEM && _IO_fwide (stderr, 0) > 0)
211 size_t len = strlen (message) + 1; 225 /* Leave a trace in case the heap allocation of the message string
212 wchar_t *wmessage = NULL; 226 failed. */
213 mbstate_t st; 227 fputws_unlocked (L"out of memory\n", stderr);
214 size_t res; 228#else
215 const char *tmp; 229 vfprintf (stderr, message, args);
216 bool use_malloc = false;
217
218 while (1)
219 {
220 if (__libc_use_alloca (len * sizeof (wchar_t)))
221 wmessage = (wchar_t *) alloca (len * sizeof (wchar_t));
222 else
223 {
224 if (!use_malloc)
225 wmessage = NULL;
226
227 wchar_t *p = (wchar_t *) realloc (wmessage,
228 len * sizeof (wchar_t));
229 if (p == NULL)
230 {
231 free (wmessage);
232 fputws_unlocked (L"out of memory\n", stderr);
233 return;
234 }
235 wmessage = p;
236 use_malloc = true;
237 }
238
239 memset (&st, '\0', sizeof (st));
240 tmp = message;
241
242 res = mbsrtowcs (wmessage, &tmp, len, &st);
243 if (res != len)
244 break;
245
246 if (__builtin_expect (len >= SIZE_MAX / sizeof (wchar_t) / 2, 0))
247 {
248 /* This really should not happen if everything is fine. */
249 res = (size_t) -1;
250 break;
251 }
252
253 len *= 2;
254 }
255
256 if (res == (size_t) -1)
257 {
258 /* The string cannot be converted. */
259 if (use_malloc)
260 {
261 free (wmessage);
262 use_malloc = false;
263 }
264 wmessage = (wchar_t *) L"???";
265 }
266
267 __vfwprintf (stderr, wmessage, args);
268
269 if (use_malloc)
270 free (wmessage);
271 }
272 else
273#endif 230#endif
274 vfprintf (stderr, message, args);
275 231
276 ++error_message_count; 232 ++error_message_count;
277 if (errnum) 233 if (errnum)
@@ -292,16 +248,14 @@ error_tail (int status, int errnum, const char *message, va_list args)
292 If ERRNUM is nonzero, print its corresponding system error message. 248 If ERRNUM is nonzero, print its corresponding system error message.
293 Exit with status STATUS if it is nonzero. */ 249 Exit with status STATUS if it is nonzero. */
294void 250void
295error (int status, int errnum, const char *message, ...) 251__error_internal (int status, int errnum, const char *message,
252 va_list args, unsigned int mode_flags)
296{ 253{
297 va_list args; 254#if defined _LIBC
298
299#if defined _LIBC && defined __libc_ptf_call
300 /* We do not want this call to be cut short by a thread 255 /* We do not want this call to be cut short by a thread
301 cancellation. Therefore disable cancellation for now. */ 256 cancellation. Therefore disable cancellation for now. */
302 int state = PTHREAD_CANCEL_ENABLE; 257 int state = PTHREAD_CANCEL_ENABLE;
303 __libc_ptf_call (pthread_setcancelstate, (PTHREAD_CANCEL_DISABLE, &state), 258 __pthread_setcancelstate (PTHREAD_CANCEL_DISABLE, &state);
304 0);
305#endif 259#endif
306 260
307 flush_stdout (); 261 flush_stdout ();
@@ -319,28 +273,32 @@ error (int status, int errnum, const char *message, ...)
319#endif 273#endif
320 } 274 }
321 275
322 va_start (args, message); 276 error_tail (status, errnum, message, args, mode_flags);
323 error_tail (status, errnum, message, args);
324 va_end (args);
325 277
326#ifdef _LIBC 278#ifdef _LIBC
327 _IO_funlockfile (stderr); 279 _IO_funlockfile (stderr);
328# ifdef __libc_ptf_call 280 __pthread_setcancelstate (state, NULL);
329 __libc_ptf_call (pthread_setcancelstate, (state, NULL), 0);
330# endif
331#endif 281#endif
332} 282}
283
284void
285error (int status, int errnum, const char *message, ...)
286{
287 va_list ap;
288 va_start (ap, message);
289 __error_internal (status, errnum, message, ap, 0);
290 va_end (ap);
291}
333 292
334/* Sometimes we want to have at most one error per line. This 293/* Sometimes we want to have at most one error per line. This
335 variable controls whether this mode is selected or not. */ 294 variable controls whether this mode is selected or not. */
336int error_one_per_line; 295int error_one_per_line;
337 296
338void 297void
339error_at_line (int status, int errnum, const char *file_name, 298__error_at_line_internal (int status, int errnum, const char *file_name,
340 unsigned int line_number, const char *message, ...) 299 unsigned int line_number, const char *message,
300 va_list args, unsigned int mode_flags)
341{ 301{
342 va_list args;
343
344 if (error_one_per_line) 302 if (error_one_per_line)
345 { 303 {
346 static const char *old_file_name; 304 static const char *old_file_name;
@@ -359,12 +317,11 @@ error_at_line (int status, int errnum, const char *file_name,
359 old_line_number = line_number; 317 old_line_number = line_number;
360 } 318 }
361 319
362#if defined _LIBC && defined __libc_ptf_call 320#if defined _LIBC
363 /* We do not want this call to be cut short by a thread 321 /* We do not want this call to be cut short by a thread
364 cancellation. Therefore disable cancellation for now. */ 322 cancellation. Therefore disable cancellation for now. */
365 int state = PTHREAD_CANCEL_ENABLE; 323 int state = PTHREAD_CANCEL_ENABLE;
366 __libc_ptf_call (pthread_setcancelstate, (PTHREAD_CANCEL_DISABLE, &state), 324 __pthread_setcancelstate (PTHREAD_CANCEL_DISABLE, &state);
367 0);
368#endif 325#endif
369 326
370 flush_stdout (); 327 flush_stdout ();
@@ -390,18 +347,25 @@ error_at_line (int status, int errnum, const char *file_name,
390 file_name, line_number); 347 file_name, line_number);
391#endif 348#endif
392 349
393 va_start (args, message); 350 error_tail (status, errnum, message, args, mode_flags);
394 error_tail (status, errnum, message, args);
395 va_end (args);
396 351
397#ifdef _LIBC 352#ifdef _LIBC
398 _IO_funlockfile (stderr); 353 _IO_funlockfile (stderr);
399# ifdef __libc_ptf_call 354 __pthread_setcancelstate (state, NULL);
400 __libc_ptf_call (pthread_setcancelstate, (state, NULL), 0);
401# endif
402#endif 355#endif
403} 356}
404 357
358void
359error_at_line (int status, int errnum, const char *file_name,
360 unsigned int line_number, const char *message, ...)
361{
362 va_list ap;
363 va_start (ap, message);
364 __error_at_line_internal (status, errnum, file_name, line_number,
365 message, ap, 0);
366 va_end (ap);
367}
368
405#ifdef _LIBC 369#ifdef _LIBC
406/* Make the weak alias. */ 370/* Make the weak alias. */
407# undef error 371# undef error