Annotation of embedaddon/libiconv/srclib/error.c, revision 1.1.1.1
1.1 misho 1: /* Error handler for noninteractive utilities
2: Copyright (C) 1990-1998, 2000-2007 Free Software Foundation, Inc.
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,
73: unsigned int line_number, const char *message,
74: ...)
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:
88: # if !HAVE_DECL_STRERROR_R && STRERROR_R_CHAR_P
89: # ifndef HAVE_DECL_STRERROR_R
90: "this configure-time declaration test was not run"
91: # endif
92: char *strerror_r ();
93: # endif
94:
95: /* The calling program should define program_name and set it to the
96: name of the executing program. */
97: extern char *program_name;
98:
99: # if HAVE_STRERROR_R || defined strerror_r
100: # define __strerror_r strerror_r
101: # endif /* HAVE_STRERROR_R || defined strerror_r */
102: #endif /* not _LIBC */
103:
104: static void
105: print_errno_message (int errnum)
106: {
107: char const *s;
108:
109: #if defined HAVE_STRERROR_R || _LIBC
110: char errbuf[1024];
111: # if STRERROR_R_CHAR_P || _LIBC
112: s = __strerror_r (errnum, errbuf, sizeof errbuf);
113: # else
114: if (__strerror_r (errnum, errbuf, sizeof errbuf) == 0)
115: s = errbuf;
116: else
117: s = 0;
118: # endif
119: #else
120: s = strerror (errnum);
121: #endif
122:
123: #if !_LIBC
124: if (! s)
125: s = _("Unknown system error");
126: #endif
127:
128: #if _LIBC
129: __fxprintf (NULL, ": %s", s);
130: #else
131: fprintf (stderr, ": %s", s);
132: #endif
133: }
134:
135: static void
136: error_tail (int status, int errnum, const char *message, va_list args)
137: {
138: #if _LIBC
139: if (_IO_fwide (stderr, 0) > 0)
140: {
141: # define ALLOCA_LIMIT 2000
142: size_t len = strlen (message) + 1;
143: wchar_t *wmessage = NULL;
144: mbstate_t st;
145: size_t res;
146: const char *tmp;
147: bool use_malloc = false;
148:
149: while (1)
150: {
151: if (__libc_use_alloca (len * sizeof (wchar_t)))
152: wmessage = (wchar_t *) alloca (len * sizeof (wchar_t));
153: else
154: {
155: if (!use_malloc)
156: wmessage = NULL;
157:
158: wchar_t *p = (wchar_t *) realloc (wmessage,
159: len * sizeof (wchar_t));
160: if (p == NULL)
161: {
162: free (wmessage);
163: fputws_unlocked (L"out of memory\n", stderr);
164: return;
165: }
166: wmessage = p;
167: use_malloc = true;
168: }
169:
170: memset (&st, '\0', sizeof (st));
171: tmp = message;
172:
173: res = mbsrtowcs (wmessage, &tmp, len, &st);
174: if (res != len)
175: break;
176:
177: if (__builtin_expect (len >= SIZE_MAX / 2, 0))
178: {
179: /* This really should not happen if everything is fine. */
180: res = (size_t) -1;
181: break;
182: }
183:
184: len *= 2;
185: }
186:
187: if (res == (size_t) -1)
188: {
189: /* The string cannot be converted. */
190: if (use_malloc)
191: {
192: free (wmessage);
193: use_malloc = false;
194: }
195: wmessage = (wchar_t *) L"???";
196: }
197:
198: __vfwprintf (stderr, wmessage, args);
199:
200: if (use_malloc)
201: free (wmessage);
202: }
203: else
204: #endif
205: vfprintf (stderr, message, args);
206: va_end (args);
207:
208: ++error_message_count;
209: if (errnum)
210: print_errno_message (errnum);
211: #if _LIBC
212: __fxprintf (NULL, "\n");
213: #else
214: putc ('\n', stderr);
215: #endif
216: fflush (stderr);
217: if (status)
218: exit (status);
219: }
220:
221:
222: /* Print the program name and error message MESSAGE, which is a printf-style
223: format string with optional args.
224: If ERRNUM is nonzero, print its corresponding system error message.
225: Exit with status STATUS if it is nonzero. */
226: void
227: error (int status, int errnum, const char *message, ...)
228: {
229: va_list args;
230:
231: #if defined _LIBC && defined __libc_ptf_call
232: /* We do not want this call to be cut short by a thread
233: cancellation. Therefore disable cancellation for now. */
234: int state = PTHREAD_CANCEL_ENABLE;
235: __libc_ptf_call (pthread_setcancelstate, (PTHREAD_CANCEL_DISABLE, &state),
236: 0);
237: #endif
238:
239: fflush (stdout);
240: #ifdef _LIBC
241: _IO_flockfile (stderr);
242: #endif
243: if (error_print_progname)
244: (*error_print_progname) ();
245: else
246: {
247: #if _LIBC
248: __fxprintf (NULL, "%s: ", program_name);
249: #else
250: fprintf (stderr, "%s: ", program_name);
251: #endif
252: }
253:
254: va_start (args, message);
255: error_tail (status, errnum, message, args);
256:
257: #ifdef _LIBC
258: _IO_funlockfile (stderr);
259: # ifdef __libc_ptf_call
260: __libc_ptf_call (pthread_setcancelstate, (state, NULL), 0);
261: # endif
262: #endif
263: }
264:
265: /* Sometimes we want to have at most one error per line. This
266: variable controls whether this mode is selected or not. */
267: int error_one_per_line;
268:
269: void
270: error_at_line (int status, int errnum, const char *file_name,
271: unsigned int line_number, const char *message, ...)
272: {
273: va_list args;
274:
275: if (error_one_per_line)
276: {
277: static const char *old_file_name;
278: static unsigned int old_line_number;
279:
280: if (old_line_number == line_number
281: && (file_name == old_file_name
282: || strcmp (old_file_name, file_name) == 0))
283: /* Simply return and print nothing. */
284: return;
285:
286: old_file_name = file_name;
287: old_line_number = line_number;
288: }
289:
290: #if defined _LIBC && defined __libc_ptf_call
291: /* We do not want this call to be cut short by a thread
292: cancellation. Therefore disable cancellation for now. */
293: int state = PTHREAD_CANCEL_ENABLE;
294: __libc_ptf_call (pthread_setcancelstate, (PTHREAD_CANCEL_DISABLE, &state),
295: 0);
296: #endif
297:
298: fflush (stdout);
299: #ifdef _LIBC
300: _IO_flockfile (stderr);
301: #endif
302: if (error_print_progname)
303: (*error_print_progname) ();
304: else
305: {
306: #if _LIBC
307: __fxprintf (NULL, "%s:", program_name);
308: #else
309: fprintf (stderr, "%s:", program_name);
310: #endif
311: }
312:
313: #if _LIBC
314: __fxprintf (NULL, file_name != NULL ? "%s:%d: " : " ",
315: file_name, line_number);
316: #else
317: fprintf (stderr, file_name != NULL ? "%s:%d: " : " ",
318: file_name, line_number);
319: #endif
320:
321: va_start (args, message);
322: error_tail (status, errnum, message, args);
323:
324: #ifdef _LIBC
325: _IO_funlockfile (stderr);
326: # ifdef __libc_ptf_call
327: __libc_ptf_call (pthread_setcancelstate, (state, NULL), 0);
328: # endif
329: #endif
330: }
331:
332: #ifdef _LIBC
333: /* Make the weak alias. */
334: # undef error
335: # undef error_at_line
336: weak_alias (__error, error)
337: weak_alias (__error_at_line, error_at_line)
338: #endif
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>