1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22: #ifdef HAVE_CONFIG_H
23: # include <config.h>
24: #endif
25:
26: #include <stdarg.h>
27: #include <stdio.h>
28: #include <stdlib.h>
29: #include <string.h>
30:
31: #ifdef _LIBC
32: # include <libintl.h>
33: # include <stdbool.h>
34: # include <stdint.h>
35: # include <wchar.h>
36: # define mbsrtowcs __mbsrtowcs
37: #endif
38:
39: #include "error.h"
40:
41: #ifndef _
42: # define _(String) String
43: #endif
44:
45:
46:
47:
48: void (*error_print_progname) (void);
49:
50:
51: unsigned int error_message_count;
52:
53: #ifdef _LIBC
54:
55:
56: # define program_name program_invocation_name
57: # include <errno.h>
58: # include <limits.h>
59: # include <libio/libioP.h>
60:
61:
62:
63: extern void __error (int status, int errnum, const char *message, ...)
64: __attribute__ ((__format__ (__printf__, 3, 4)));
65: extern void __error_at_line (int status, int errnum, const char *file_name,
66: unsigned int line_number, const char *message,
67: ...)
68: __attribute__ ((__format__ (__printf__, 5, 6)));;
69: # define error __error
70: # define error_at_line __error_at_line
71:
72: # include <libio/iolibio.h>
73: # define fflush(s) INTUSE(_IO_fflush) (s)
74: # undef putc
75: # define putc(c, fp) INTUSE(_IO_putc) (c, fp)
76:
77: # include <bits/libc-lock.h>
78:
79: #else
80:
81: # if !HAVE_DECL_STRERROR_R && STRERROR_R_CHAR_P
82: # ifndef HAVE_DECL_STRERROR_R
83: "this configure-time declaration test was not run"
84: # endif
85: char *strerror_r ();
86: # endif
87:
88:
89:
90: extern char *program_name;
91:
92: # if HAVE_STRERROR_R || defined strerror_r
93: # define __strerror_r strerror_r
94: # endif
95: #endif
96:
97: static void
98: print_errno_message (int errnum)
99: {
100: char const *s;
101:
102: #if defined HAVE_STRERROR_R || _LIBC
103: char errbuf[1024];
104: # if STRERROR_R_CHAR_P || _LIBC
105: s = __strerror_r (errnum, errbuf, sizeof errbuf);
106: # else
107: if (__strerror_r (errnum, errbuf, sizeof errbuf) == 0)
108: s = errbuf;
109: else
110: s = 0;
111: # endif
112: #else
113: s = strerror (errnum);
114: #endif
115:
116: #if !_LIBC
117: if (! s)
118: s = _("Unknown system error");
119: #endif
120:
121: #if _LIBC
122: __fxprintf (NULL, ": %s", s);
123: #else
124: fprintf (stderr, ": %s", s);
125: #endif
126: }
127:
128: static void
129: error_tail (int status, int errnum, const char *message, va_list args)
130: {
131: #if _LIBC
132: if (_IO_fwide (stderr, 0) > 0)
133: {
134: # define ALLOCA_LIMIT 2000
135: size_t len = strlen (message) + 1;
136: wchar_t *wmessage = NULL;
137: mbstate_t st;
138: size_t res;
139: const char *tmp;
140: bool use_malloc = false;
141:
142: while (1)
143: {
144: if (__libc_use_alloca (len * sizeof (wchar_t)))
145: wmessage = (wchar_t *) alloca (len * sizeof (wchar_t));
146: else
147: {
148: if (!use_malloc)
149: wmessage = NULL;
150:
151: wchar_t *p = (wchar_t *) realloc (wmessage,
152: len * sizeof (wchar_t));
153: if (p == NULL)
154: {
155: free (wmessage);
156: fputws_unlocked (L"out of memory\n", stderr);
157: return;
158: }
159: wmessage = p;
160: use_malloc = true;
161: }
162:
163: memset (&st, '\0', sizeof (st));
164: tmp = message;
165:
166: res = mbsrtowcs (wmessage, &tmp, len, &st);
167: if (res != len)
168: break;
169:
170: if (__builtin_expect (len >= SIZE_MAX / 2, 0))
171: {
172:
173: res = (size_t) -1;
174: break;
175: }
176:
177: len *= 2;
178: }
179:
180: if (res == (size_t) -1)
181: {
182:
183: if (use_malloc)
184: {
185: free (wmessage);
186: use_malloc = false;
187: }
188: wmessage = (wchar_t *) L"???";
189: }
190:
191: __vfwprintf (stderr, wmessage, args);
192:
193: if (use_malloc)
194: free (wmessage);
195: }
196: else
197: #endif
198: vfprintf (stderr, message, args);
199: va_end (args);
200:
201: ++error_message_count;
202: if (errnum)
203: print_errno_message (errnum);
204: #if _LIBC
205: __fxprintf (NULL, "\n");
206: #else
207: putc ('\n', stderr);
208: #endif
209: fflush (stderr);
210: if (status)
211: exit (status);
212: }
213:
214:
215:
216:
217:
218:
219: void
220: error (int status, int errnum, const char *message, ...)
221: {
222: va_list args;
223:
224: #if defined _LIBC && defined __libc_ptf_call
225:
226:
227: int state = PTHREAD_CANCEL_ENABLE;
228: __libc_ptf_call (pthread_setcancelstate, (PTHREAD_CANCEL_DISABLE, &state),
229: 0);
230: #endif
231:
232: fflush (stdout);
233: #ifdef _LIBC
234: _IO_flockfile (stderr);
235: #endif
236: if (error_print_progname)
237: (*error_print_progname) ();
238: else
239: {
240: #if _LIBC
241: __fxprintf (NULL, "%s: ", program_name);
242: #else
243: fprintf (stderr, "%s: ", program_name);
244: #endif
245: }
246:
247: va_start (args, message);
248: error_tail (status, errnum, message, args);
249:
250: #ifdef _LIBC
251: _IO_funlockfile (stderr);
252: # ifdef __libc_ptf_call
253: __libc_ptf_call (pthread_setcancelstate, (state, NULL), 0);
254: # endif
255: #endif
256: }
257: ^L
258:
259:
260: int error_one_per_line;
261:
262: void
263: error_at_line (int status, int errnum, const char *file_name,
264: unsigned int line_number, const char *message, ...)
265: {
266: va_list args;
267:
268: if (error_one_per_line)
269: {
270: static const char *old_file_name;
271: static unsigned int old_line_number;
272:
273: if (old_line_number == line_number
274: && (file_name == old_file_name
275: || strcmp (old_file_name, file_name) == 0))
276:
277: return;
278:
279: old_file_name = file_name;
280: old_line_number = line_number;
281: }
282:
283: #if defined _LIBC && defined __libc_ptf_call
284:
285:
286: int state = PTHREAD_CANCEL_ENABLE;
287: __libc_ptf_call (pthread_setcancelstate, (PTHREAD_CANCEL_DISABLE, &state),
288: 0);
289: #endif
290:
291: fflush (stdout);
292: #ifdef _LIBC
293: _IO_flockfile (stderr);
294: #endif
295: if (error_print_progname)
296: (*error_print_progname) ();
297: else
298: {
299: #if _LIBC
300: __fxprintf (NULL, "%s:", program_name);
301: #else
302: fprintf (stderr, "%s:", program_name);
303: #endif
304: }
305:
306: #if _LIBC
307: __fxprintf (NULL, file_name != NULL ? "%s:%d: " : " ",
308: file_name, line_number);
309: #else
310: fprintf (stderr, file_name != NULL ? "%s:%d: " : " ",
311: file_name, line_number);
312: #endif
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: #ifdef _LIBC
326:
327: # undef error
328: # undef error_at_line
329: weak_alias (__error, error)
330: weak_alias (__error_at_line, error_at_line)
331: #endif