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