Annotation of embedaddon/libiconv/srclib/error.c, revision 1.1.1.3
1.1 misho 1: /* Error handler for noninteractive utilities
1.1.1.3 ! misho 2: Copyright (C) 1990-1998, 2000-2007, 2009-2019 Free Software Foundation, Inc.
1.1 misho 3: This file is part of the GNU C Library.
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
1.1.1.3 ! misho 16: along with this program. If not, see <https://www.gnu.org/licenses/>. */
1.1 misho 17:
18: /* Written by David MacKenzie <djm@gnu.ai.mit.edu>. */
19:
20: #if !_LIBC
21: # include <config.h>
22: #endif
23:
24: #include "error.h"
25:
26: #include <stdarg.h>
27: #include <stdio.h>
28: #include <stdlib.h>
29: #include <string.h>
30:
31: #if !_LIBC && ENABLE_NLS
32: # include "gettext.h"
33: # define _(msgid) gettext (msgid)
34: #endif
35:
36: #ifdef _LIBC
37: # include <libintl.h>
38: # include <stdbool.h>
39: # include <stdint.h>
40: # include <wchar.h>
41: # define mbsrtowcs __mbsrtowcs
1.1.1.3 ! misho 42: # define USE_UNLOCKED_IO 0
! 43: # define _GL_ATTRIBUTE_FORMAT_PRINTF(a, b)
! 44: # define _GL_ARG_NONNULL(a)
! 45: #else
! 46: # include "getprogname.h"
1.1 misho 47: #endif
48:
49: #if USE_UNLOCKED_IO
50: # include "unlocked-io.h"
51: #endif
52:
53: #ifndef _
54: # define _(String) String
55: #endif
56:
57: /* If NULL, error will flush stdout, then print on stderr the program
58: name, a colon and a space. Otherwise, error will call this
59: function without parameters instead. */
60: void (*error_print_progname) (void);
61:
1.1.1.3 ! misho 62: /* This variable is incremented each time 'error' is called. */
1.1 misho 63: unsigned int error_message_count;
64:
65: #ifdef _LIBC
66: /* In the GNU C library, there is a predefined variable for this. */
67:
68: # define program_name program_invocation_name
69: # include <errno.h>
70: # include <limits.h>
71: # include <libio/libioP.h>
72:
1.1.1.3 ! misho 73: /* In GNU libc we want do not want to use the common name 'error' directly.
1.1 misho 74: Instead make it a weak alias. */
75: extern void __error (int status, int errnum, const char *message, ...)
76: __attribute__ ((__format__ (__printf__, 3, 4)));
77: extern void __error_at_line (int status, int errnum, const char *file_name,
1.1.1.2 misho 78: unsigned int line_number, const char *message,
79: ...)
1.1.1.3 ! misho 80: __attribute__ ((__format__ (__printf__, 5, 6)));
1.1 misho 81: # define error __error
82: # define error_at_line __error_at_line
83:
84: # include <libio/iolibio.h>
1.1.1.3 ! misho 85: # define fflush(s) _IO_fflush (s)
1.1 misho 86: # undef putc
1.1.1.3 ! misho 87: # define putc(c, fp) _IO_putc (c, fp)
1.1 misho 88:
89: # include <bits/libc-lock.h>
90:
91: #else /* not _LIBC */
92:
1.1.1.2 misho 93: # include <fcntl.h>
94: # include <unistd.h>
95:
1.1.1.3 ! misho 96: # if defined _WIN32 && ! defined __CYGWIN__
! 97: /* Get declarations of the native Windows API functions. */
1.1.1.2 misho 98: # define WIN32_LEAN_AND_MEAN
99: # include <windows.h>
1.1.1.3 ! misho 100: /* Get _get_osfhandle. */
! 101: # if GNULIB_MSVC_NOTHROW
! 102: # include "msvc-nothrow.h"
! 103: # else
! 104: # include <io.h>
! 105: # endif
1.1.1.2 misho 106: # endif
107:
108: /* The gnulib override of fcntl is not needed in this file. */
109: # undef fcntl
110:
1.1.1.3 ! misho 111: # if !(GNULIB_STRERROR_R_POSIX || HAVE_DECL_STRERROR_R)
1.1 misho 112: # ifndef HAVE_DECL_STRERROR_R
113: "this configure-time declaration test was not run"
114: # endif
1.1.1.2 misho 115: # if STRERROR_R_CHAR_P
1.1.1.3 ! misho 116: char *strerror_r (int errnum, char *buf, size_t buflen);
1.1.1.2 misho 117: # else
1.1.1.3 ! misho 118: int strerror_r (int errnum, char *buf, size_t buflen);
1.1.1.2 misho 119: # endif
1.1 misho 120: # endif
121:
1.1.1.3 ! misho 122: #define program_name getprogname ()
1.1 misho 123:
1.1.1.3 ! misho 124: # if GNULIB_STRERROR_R_POSIX || HAVE_STRERROR_R || defined strerror_r
1.1 misho 125: # define __strerror_r strerror_r
1.1.1.3 ! misho 126: # endif /* GNULIB_STRERROR_R_POSIX || HAVE_STRERROR_R || defined strerror_r */
1.1.1.2 misho 127: #endif /* not _LIBC */
128:
129: #if !_LIBC
130: /* Return non-zero if FD is open. */
1.1.1.3 ! misho 131: static int
1.1.1.2 misho 132: is_open (int fd)
133: {
1.1.1.3 ! misho 134: # if defined _WIN32 && ! defined __CYGWIN__
! 135: /* On native Windows: The initial state of unassigned standard file
! 136: descriptors is that they are open but point to an INVALID_HANDLE_VALUE.
! 137: There is no fcntl, and the gnulib replacement fcntl does not support
! 138: F_GETFL. */
1.1.1.2 misho 139: return (HANDLE) _get_osfhandle (fd) != INVALID_HANDLE_VALUE;
140: # else
141: # ifndef F_GETFL
142: # error Please port fcntl to your platform
143: # endif
144: return 0 <= fcntl (fd, F_GETFL);
145: # endif
146: }
147: #endif
148:
1.1.1.3 ! misho 149: static void
1.1.1.2 misho 150: flush_stdout (void)
151: {
152: #if !_LIBC
153: int stdout_fd;
154:
155: # if GNULIB_FREOPEN_SAFER
156: /* Use of gnulib's freopen-safer module normally ensures that
157: fileno (stdout) == 1
158: whenever stdout is open. */
159: stdout_fd = STDOUT_FILENO;
160: # else
161: /* POSIX states that fileno (stdout) after fclose is unspecified. But in
162: practice it is not a problem, because stdout is statically allocated and
163: the fd of a FILE stream is stored as a field in its allocated memory. */
164: stdout_fd = fileno (stdout);
165: # endif
166: /* POSIX states that fflush (stdout) after fclose is unspecified; it
167: is safe in glibc, but not on all other platforms. fflush (NULL)
168: is always defined, but too draconian. */
169: if (0 <= stdout_fd && is_open (stdout_fd))
170: #endif
171: fflush (stdout);
172: }
1.1 misho 173:
174: static void
175: print_errno_message (int errnum)
176: {
177: char const *s;
178:
1.1.1.3 ! misho 179: #if _LIBC || GNULIB_STRERROR_R_POSIX || defined HAVE_STRERROR_R
1.1 misho 180: char errbuf[1024];
1.1.1.3 ! misho 181: # if _LIBC || (!GNULIB_STRERROR_R_POSIX && STRERROR_R_CHAR_P)
1.1 misho 182: s = __strerror_r (errnum, errbuf, sizeof errbuf);
183: # else
184: if (__strerror_r (errnum, errbuf, sizeof errbuf) == 0)
185: s = errbuf;
186: else
187: s = 0;
188: # endif
189: #else
190: s = strerror (errnum);
191: #endif
192:
193: #if !_LIBC
194: if (! s)
195: s = _("Unknown system error");
196: #endif
197:
198: #if _LIBC
199: __fxprintf (NULL, ": %s", s);
200: #else
201: fprintf (stderr, ": %s", s);
202: #endif
203: }
204:
1.1.1.3 ! misho 205: static void _GL_ATTRIBUTE_FORMAT_PRINTF (3, 0) _GL_ARG_NONNULL ((3))
1.1 misho 206: error_tail (int status, int errnum, const char *message, va_list args)
207: {
208: #if _LIBC
209: if (_IO_fwide (stderr, 0) > 0)
210: {
211: size_t len = strlen (message) + 1;
212: wchar_t *wmessage = NULL;
213: mbstate_t st;
214: size_t res;
215: const char *tmp;
216: bool use_malloc = false;
217:
218: while (1)
1.1.1.2 misho 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:
1.1.1.3 ! misho 246: if (__builtin_expect (len >= SIZE_MAX / sizeof (wchar_t) / 2, 0))
1.1.1.2 misho 247: {
248: /* This really should not happen if everything is fine. */
249: res = (size_t) -1;
250: break;
251: }
1.1 misho 252:
1.1.1.2 misho 253: len *= 2;
254: }
1.1 misho 255:
256: if (res == (size_t) -1)
1.1.1.2 misho 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: }
1.1 misho 266:
267: __vfwprintf (stderr, wmessage, args);
268:
269: if (use_malloc)
1.1.1.2 misho 270: free (wmessage);
1.1 misho 271: }
272: else
273: #endif
274: vfprintf (stderr, message, args);
275:
276: ++error_message_count;
277: if (errnum)
278: print_errno_message (errnum);
279: #if _LIBC
280: __fxprintf (NULL, "\n");
281: #else
282: putc ('\n', stderr);
283: #endif
284: fflush (stderr);
285: if (status)
286: exit (status);
287: }
288:
289:
290: /* Print the program name and error message MESSAGE, which is a printf-style
291: format string with optional args.
292: If ERRNUM is nonzero, print its corresponding system error message.
293: Exit with status STATUS if it is nonzero. */
294: void
295: error (int status, int errnum, const char *message, ...)
296: {
297: va_list args;
298:
299: #if defined _LIBC && defined __libc_ptf_call
300: /* We do not want this call to be cut short by a thread
301: cancellation. Therefore disable cancellation for now. */
302: int state = PTHREAD_CANCEL_ENABLE;
303: __libc_ptf_call (pthread_setcancelstate, (PTHREAD_CANCEL_DISABLE, &state),
1.1.1.2 misho 304: 0);
1.1 misho 305: #endif
306:
1.1.1.2 misho 307: flush_stdout ();
1.1 misho 308: #ifdef _LIBC
309: _IO_flockfile (stderr);
310: #endif
311: if (error_print_progname)
312: (*error_print_progname) ();
313: else
314: {
315: #if _LIBC
316: __fxprintf (NULL, "%s: ", program_name);
317: #else
318: fprintf (stderr, "%s: ", program_name);
319: #endif
320: }
321:
322: va_start (args, message);
323: error_tail (status, errnum, message, args);
1.1.1.3 ! misho 324: va_end (args);
1.1 misho 325:
326: #ifdef _LIBC
327: _IO_funlockfile (stderr);
328: # ifdef __libc_ptf_call
329: __libc_ptf_call (pthread_setcancelstate, (state, NULL), 0);
330: # endif
331: #endif
332: }
333:
334: /* Sometimes we want to have at most one error per line. This
335: variable controls whether this mode is selected or not. */
336: int error_one_per_line;
337:
338: void
339: error_at_line (int status, int errnum, const char *file_name,
1.1.1.2 misho 340: unsigned int line_number, const char *message, ...)
1.1 misho 341: {
342: va_list args;
343:
344: if (error_one_per_line)
345: {
346: static const char *old_file_name;
347: static unsigned int old_line_number;
348:
349: if (old_line_number == line_number
1.1.1.2 misho 350: && (file_name == old_file_name
1.1.1.3 ! misho 351: || (old_file_name != NULL
! 352: && file_name != NULL
! 353: && strcmp (old_file_name, file_name) == 0)))
! 354:
1.1.1.2 misho 355: /* Simply return and print nothing. */
356: return;
1.1 misho 357:
358: old_file_name = file_name;
359: old_line_number = line_number;
360: }
361:
362: #if defined _LIBC && defined __libc_ptf_call
363: /* We do not want this call to be cut short by a thread
364: cancellation. Therefore disable cancellation for now. */
365: int state = PTHREAD_CANCEL_ENABLE;
366: __libc_ptf_call (pthread_setcancelstate, (PTHREAD_CANCEL_DISABLE, &state),
1.1.1.2 misho 367: 0);
1.1 misho 368: #endif
369:
1.1.1.2 misho 370: flush_stdout ();
1.1 misho 371: #ifdef _LIBC
372: _IO_flockfile (stderr);
373: #endif
374: if (error_print_progname)
375: (*error_print_progname) ();
376: else
377: {
378: #if _LIBC
379: __fxprintf (NULL, "%s:", program_name);
380: #else
381: fprintf (stderr, "%s:", program_name);
382: #endif
383: }
384:
385: #if _LIBC
1.1.1.3 ! misho 386: __fxprintf (NULL, file_name != NULL ? "%s:%u: " : " ",
1.1.1.2 misho 387: file_name, line_number);
1.1 misho 388: #else
1.1.1.3 ! misho 389: fprintf (stderr, file_name != NULL ? "%s:%u: " : " ",
1.1.1.2 misho 390: file_name, line_number);
1.1 misho 391: #endif
392:
393: va_start (args, message);
394: error_tail (status, errnum, message, args);
1.1.1.3 ! misho 395: va_end (args);
1.1 misho 396:
397: #ifdef _LIBC
398: _IO_funlockfile (stderr);
399: # ifdef __libc_ptf_call
400: __libc_ptf_call (pthread_setcancelstate, (state, NULL), 0);
401: # endif
402: #endif
403: }
404:
405: #ifdef _LIBC
406: /* Make the weak alias. */
407: # undef error
408: # undef error_at_line
409: weak_alias (__error, error)
410: weak_alias (__error_at_line, error_at_line)
411: #endif
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>