1*9663SMark.Logan@Sun.COM /* Error handler for noninteractive utilities
2*9663SMark.Logan@Sun.COM Copyright (C) 1990-1998, 2000-2007 Free Software Foundation, Inc.
3*9663SMark.Logan@Sun.COM This file is part of the GNU C Library.
4*9663SMark.Logan@Sun.COM
5*9663SMark.Logan@Sun.COM This program is free software; you can redistribute it and/or modify
6*9663SMark.Logan@Sun.COM it under the terms of the GNU General Public License as published by
7*9663SMark.Logan@Sun.COM the Free Software Foundation; either version 2, or (at your option)
8*9663SMark.Logan@Sun.COM any later version.
9*9663SMark.Logan@Sun.COM
10*9663SMark.Logan@Sun.COM This program is distributed in the hope that it will be useful,
11*9663SMark.Logan@Sun.COM but WITHOUT ANY WARRANTY; without even the implied warranty of
12*9663SMark.Logan@Sun.COM MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13*9663SMark.Logan@Sun.COM GNU General Public License for more details.
14*9663SMark.Logan@Sun.COM
15*9663SMark.Logan@Sun.COM You should have received a copy of the GNU General Public License along
16*9663SMark.Logan@Sun.COM with this program; if not, write to the Free Software Foundation,
17*9663SMark.Logan@Sun.COM Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
18*9663SMark.Logan@Sun.COM
19*9663SMark.Logan@Sun.COM /* Written by David MacKenzie <djm@gnu.ai.mit.edu>. */
20*9663SMark.Logan@Sun.COM
21*9663SMark.Logan@Sun.COM #if !_LIBC
22*9663SMark.Logan@Sun.COM # include <config.h>
23*9663SMark.Logan@Sun.COM #endif
24*9663SMark.Logan@Sun.COM
25*9663SMark.Logan@Sun.COM #include "error.h"
26*9663SMark.Logan@Sun.COM
27*9663SMark.Logan@Sun.COM #include <stdarg.h>
28*9663SMark.Logan@Sun.COM #include <stdio.h>
29*9663SMark.Logan@Sun.COM #include <stdlib.h>
30*9663SMark.Logan@Sun.COM #include <string.h>
31*9663SMark.Logan@Sun.COM
32*9663SMark.Logan@Sun.COM #if !_LIBC && ENABLE_NLS
33*9663SMark.Logan@Sun.COM # include "gettext.h"
34*9663SMark.Logan@Sun.COM # define _(msgid) gettext (msgid)
35*9663SMark.Logan@Sun.COM #endif
36*9663SMark.Logan@Sun.COM
37*9663SMark.Logan@Sun.COM #ifdef _LIBC
38*9663SMark.Logan@Sun.COM # include <libintl.h>
39*9663SMark.Logan@Sun.COM # include <stdbool.h>
40*9663SMark.Logan@Sun.COM # include <stdint.h>
41*9663SMark.Logan@Sun.COM # include <wchar.h>
42*9663SMark.Logan@Sun.COM # define mbsrtowcs __mbsrtowcs
43*9663SMark.Logan@Sun.COM #endif
44*9663SMark.Logan@Sun.COM
45*9663SMark.Logan@Sun.COM #if USE_UNLOCKED_IO
46*9663SMark.Logan@Sun.COM # include "unlocked-io.h"
47*9663SMark.Logan@Sun.COM #endif
48*9663SMark.Logan@Sun.COM
49*9663SMark.Logan@Sun.COM #ifndef _
50*9663SMark.Logan@Sun.COM # define _(String) String
51*9663SMark.Logan@Sun.COM #endif
52*9663SMark.Logan@Sun.COM
53*9663SMark.Logan@Sun.COM /* If NULL, error will flush stdout, then print on stderr the program
54*9663SMark.Logan@Sun.COM name, a colon and a space. Otherwise, error will call this
55*9663SMark.Logan@Sun.COM function without parameters instead. */
56*9663SMark.Logan@Sun.COM void (*error_print_progname) (void);
57*9663SMark.Logan@Sun.COM
58*9663SMark.Logan@Sun.COM /* This variable is incremented each time `error' is called. */
59*9663SMark.Logan@Sun.COM unsigned int error_message_count;
60*9663SMark.Logan@Sun.COM
61*9663SMark.Logan@Sun.COM #ifdef _LIBC
62*9663SMark.Logan@Sun.COM /* In the GNU C library, there is a predefined variable for this. */
63*9663SMark.Logan@Sun.COM
64*9663SMark.Logan@Sun.COM # define program_name program_invocation_name
65*9663SMark.Logan@Sun.COM # include <errno.h>
66*9663SMark.Logan@Sun.COM # include <limits.h>
67*9663SMark.Logan@Sun.COM # include <libio/libioP.h>
68*9663SMark.Logan@Sun.COM
69*9663SMark.Logan@Sun.COM /* In GNU libc we want do not want to use the common name `error' directly.
70*9663SMark.Logan@Sun.COM Instead make it a weak alias. */
71*9663SMark.Logan@Sun.COM extern void __error (int status, int errnum, const char *message, ...)
72*9663SMark.Logan@Sun.COM __attribute__ ((__format__ (__printf__, 3, 4)));
73*9663SMark.Logan@Sun.COM extern void __error_at_line (int status, int errnum, const char *file_name,
74*9663SMark.Logan@Sun.COM unsigned int line_number, const char *message,
75*9663SMark.Logan@Sun.COM ...)
76*9663SMark.Logan@Sun.COM __attribute__ ((__format__ (__printf__, 5, 6)));;
77*9663SMark.Logan@Sun.COM # define error __error
78*9663SMark.Logan@Sun.COM # define error_at_line __error_at_line
79*9663SMark.Logan@Sun.COM
80*9663SMark.Logan@Sun.COM # include <libio/iolibio.h>
81*9663SMark.Logan@Sun.COM # define fflush(s) INTUSE(_IO_fflush) (s)
82*9663SMark.Logan@Sun.COM # undef putc
83*9663SMark.Logan@Sun.COM # define putc(c, fp) INTUSE(_IO_putc) (c, fp)
84*9663SMark.Logan@Sun.COM
85*9663SMark.Logan@Sun.COM # include <bits/libc-lock.h>
86*9663SMark.Logan@Sun.COM
87*9663SMark.Logan@Sun.COM #else /* not _LIBC */
88*9663SMark.Logan@Sun.COM
89*9663SMark.Logan@Sun.COM # if !HAVE_DECL_STRERROR_R && STRERROR_R_CHAR_P
90*9663SMark.Logan@Sun.COM # ifndef HAVE_DECL_STRERROR_R
91*9663SMark.Logan@Sun.COM "this configure-time declaration test was not run"
92*9663SMark.Logan@Sun.COM # endif
93*9663SMark.Logan@Sun.COM char *strerror_r ();
94*9663SMark.Logan@Sun.COM # endif
95*9663SMark.Logan@Sun.COM
96*9663SMark.Logan@Sun.COM /* The calling program should define program_name and set it to the
97*9663SMark.Logan@Sun.COM name of the executing program. */
98*9663SMark.Logan@Sun.COM extern char *program_name;
99*9663SMark.Logan@Sun.COM
100*9663SMark.Logan@Sun.COM # if HAVE_STRERROR_R || defined strerror_r
101*9663SMark.Logan@Sun.COM # define __strerror_r strerror_r
102*9663SMark.Logan@Sun.COM # endif /* HAVE_STRERROR_R || defined strerror_r */
103*9663SMark.Logan@Sun.COM #endif /* not _LIBC */
104*9663SMark.Logan@Sun.COM
105*9663SMark.Logan@Sun.COM static void
print_errno_message(int errnum)106*9663SMark.Logan@Sun.COM print_errno_message (int errnum)
107*9663SMark.Logan@Sun.COM {
108*9663SMark.Logan@Sun.COM char const *s;
109*9663SMark.Logan@Sun.COM
110*9663SMark.Logan@Sun.COM #if defined HAVE_STRERROR_R || _LIBC
111*9663SMark.Logan@Sun.COM char errbuf[1024];
112*9663SMark.Logan@Sun.COM # if STRERROR_R_CHAR_P || _LIBC
113*9663SMark.Logan@Sun.COM s = __strerror_r (errnum, errbuf, sizeof errbuf);
114*9663SMark.Logan@Sun.COM # else
115*9663SMark.Logan@Sun.COM if (__strerror_r (errnum, errbuf, sizeof errbuf) == 0)
116*9663SMark.Logan@Sun.COM s = errbuf;
117*9663SMark.Logan@Sun.COM else
118*9663SMark.Logan@Sun.COM s = 0;
119*9663SMark.Logan@Sun.COM # endif
120*9663SMark.Logan@Sun.COM #else
121*9663SMark.Logan@Sun.COM s = strerror (errnum);
122*9663SMark.Logan@Sun.COM #endif
123*9663SMark.Logan@Sun.COM
124*9663SMark.Logan@Sun.COM #if !_LIBC
125*9663SMark.Logan@Sun.COM if (! s)
126*9663SMark.Logan@Sun.COM s = _("Unknown system error");
127*9663SMark.Logan@Sun.COM #endif
128*9663SMark.Logan@Sun.COM
129*9663SMark.Logan@Sun.COM #if _LIBC
130*9663SMark.Logan@Sun.COM __fxprintf (NULL, ": %s", s);
131*9663SMark.Logan@Sun.COM #else
132*9663SMark.Logan@Sun.COM fprintf (stderr, ": %s", s);
133*9663SMark.Logan@Sun.COM #endif
134*9663SMark.Logan@Sun.COM }
135*9663SMark.Logan@Sun.COM
136*9663SMark.Logan@Sun.COM static void
error_tail(int status,int errnum,const char * message,va_list args)137*9663SMark.Logan@Sun.COM error_tail (int status, int errnum, const char *message, va_list args)
138*9663SMark.Logan@Sun.COM {
139*9663SMark.Logan@Sun.COM #if _LIBC
140*9663SMark.Logan@Sun.COM if (_IO_fwide (stderr, 0) > 0)
141*9663SMark.Logan@Sun.COM {
142*9663SMark.Logan@Sun.COM # define ALLOCA_LIMIT 2000
143*9663SMark.Logan@Sun.COM size_t len = strlen (message) + 1;
144*9663SMark.Logan@Sun.COM wchar_t *wmessage = NULL;
145*9663SMark.Logan@Sun.COM mbstate_t st;
146*9663SMark.Logan@Sun.COM size_t res;
147*9663SMark.Logan@Sun.COM const char *tmp;
148*9663SMark.Logan@Sun.COM bool use_malloc = false;
149*9663SMark.Logan@Sun.COM
150*9663SMark.Logan@Sun.COM while (1)
151*9663SMark.Logan@Sun.COM {
152*9663SMark.Logan@Sun.COM if (__libc_use_alloca (len * sizeof (wchar_t)))
153*9663SMark.Logan@Sun.COM wmessage = (wchar_t *) alloca (len * sizeof (wchar_t));
154*9663SMark.Logan@Sun.COM else
155*9663SMark.Logan@Sun.COM {
156*9663SMark.Logan@Sun.COM if (!use_malloc)
157*9663SMark.Logan@Sun.COM wmessage = NULL;
158*9663SMark.Logan@Sun.COM
159*9663SMark.Logan@Sun.COM wchar_t *p = (wchar_t *) realloc (wmessage,
160*9663SMark.Logan@Sun.COM len * sizeof (wchar_t));
161*9663SMark.Logan@Sun.COM if (p == NULL)
162*9663SMark.Logan@Sun.COM {
163*9663SMark.Logan@Sun.COM free (wmessage);
164*9663SMark.Logan@Sun.COM fputws_unlocked (L"out of memory\n", stderr);
165*9663SMark.Logan@Sun.COM return;
166*9663SMark.Logan@Sun.COM }
167*9663SMark.Logan@Sun.COM wmessage = p;
168*9663SMark.Logan@Sun.COM use_malloc = true;
169*9663SMark.Logan@Sun.COM }
170*9663SMark.Logan@Sun.COM
171*9663SMark.Logan@Sun.COM memset (&st, '\0', sizeof (st));
172*9663SMark.Logan@Sun.COM tmp = message;
173*9663SMark.Logan@Sun.COM
174*9663SMark.Logan@Sun.COM res = mbsrtowcs (wmessage, &tmp, len, &st);
175*9663SMark.Logan@Sun.COM if (res != len)
176*9663SMark.Logan@Sun.COM break;
177*9663SMark.Logan@Sun.COM
178*9663SMark.Logan@Sun.COM if (__builtin_expect (len >= SIZE_MAX / 2, 0))
179*9663SMark.Logan@Sun.COM {
180*9663SMark.Logan@Sun.COM /* This really should not happen if everything is fine. */
181*9663SMark.Logan@Sun.COM res = (size_t) -1;
182*9663SMark.Logan@Sun.COM break;
183*9663SMark.Logan@Sun.COM }
184*9663SMark.Logan@Sun.COM
185*9663SMark.Logan@Sun.COM len *= 2;
186*9663SMark.Logan@Sun.COM }
187*9663SMark.Logan@Sun.COM
188*9663SMark.Logan@Sun.COM if (res == (size_t) -1)
189*9663SMark.Logan@Sun.COM {
190*9663SMark.Logan@Sun.COM /* The string cannot be converted. */
191*9663SMark.Logan@Sun.COM if (use_malloc)
192*9663SMark.Logan@Sun.COM {
193*9663SMark.Logan@Sun.COM free (wmessage);
194*9663SMark.Logan@Sun.COM use_malloc = false;
195*9663SMark.Logan@Sun.COM }
196*9663SMark.Logan@Sun.COM wmessage = (wchar_t *) L"???";
197*9663SMark.Logan@Sun.COM }
198*9663SMark.Logan@Sun.COM
199*9663SMark.Logan@Sun.COM __vfwprintf (stderr, wmessage, args);
200*9663SMark.Logan@Sun.COM
201*9663SMark.Logan@Sun.COM if (use_malloc)
202*9663SMark.Logan@Sun.COM free (wmessage);
203*9663SMark.Logan@Sun.COM }
204*9663SMark.Logan@Sun.COM else
205*9663SMark.Logan@Sun.COM #endif
206*9663SMark.Logan@Sun.COM vfprintf (stderr, message, args);
207*9663SMark.Logan@Sun.COM va_end (args);
208*9663SMark.Logan@Sun.COM
209*9663SMark.Logan@Sun.COM ++error_message_count;
210*9663SMark.Logan@Sun.COM if (errnum)
211*9663SMark.Logan@Sun.COM print_errno_message (errnum);
212*9663SMark.Logan@Sun.COM #if _LIBC
213*9663SMark.Logan@Sun.COM __fxprintf (NULL, "\n");
214*9663SMark.Logan@Sun.COM #else
215*9663SMark.Logan@Sun.COM putc ('\n', stderr);
216*9663SMark.Logan@Sun.COM #endif
217*9663SMark.Logan@Sun.COM fflush (stderr);
218*9663SMark.Logan@Sun.COM if (status)
219*9663SMark.Logan@Sun.COM exit (status);
220*9663SMark.Logan@Sun.COM }
221*9663SMark.Logan@Sun.COM
222*9663SMark.Logan@Sun.COM
223*9663SMark.Logan@Sun.COM /* Print the program name and error message MESSAGE, which is a printf-style
224*9663SMark.Logan@Sun.COM format string with optional args.
225*9663SMark.Logan@Sun.COM If ERRNUM is nonzero, print its corresponding system error message.
226*9663SMark.Logan@Sun.COM Exit with status STATUS if it is nonzero. */
227*9663SMark.Logan@Sun.COM void
error(int status,int errnum,const char * message,...)228*9663SMark.Logan@Sun.COM error (int status, int errnum, const char *message, ...)
229*9663SMark.Logan@Sun.COM {
230*9663SMark.Logan@Sun.COM va_list args;
231*9663SMark.Logan@Sun.COM
232*9663SMark.Logan@Sun.COM #if defined _LIBC && defined __libc_ptf_call
233*9663SMark.Logan@Sun.COM /* We do not want this call to be cut short by a thread
234*9663SMark.Logan@Sun.COM cancellation. Therefore disable cancellation for now. */
235*9663SMark.Logan@Sun.COM int state = PTHREAD_CANCEL_ENABLE;
236*9663SMark.Logan@Sun.COM __libc_ptf_call (pthread_setcancelstate, (PTHREAD_CANCEL_DISABLE, &state),
237*9663SMark.Logan@Sun.COM 0);
238*9663SMark.Logan@Sun.COM #endif
239*9663SMark.Logan@Sun.COM
240*9663SMark.Logan@Sun.COM fflush (stdout);
241*9663SMark.Logan@Sun.COM #ifdef _LIBC
242*9663SMark.Logan@Sun.COM _IO_flockfile (stderr);
243*9663SMark.Logan@Sun.COM #endif
244*9663SMark.Logan@Sun.COM if (error_print_progname)
245*9663SMark.Logan@Sun.COM (*error_print_progname) ();
246*9663SMark.Logan@Sun.COM else
247*9663SMark.Logan@Sun.COM {
248*9663SMark.Logan@Sun.COM #if _LIBC
249*9663SMark.Logan@Sun.COM __fxprintf (NULL, "%s: ", program_name);
250*9663SMark.Logan@Sun.COM #else
251*9663SMark.Logan@Sun.COM fprintf (stderr, "%s: ", program_name);
252*9663SMark.Logan@Sun.COM #endif
253*9663SMark.Logan@Sun.COM }
254*9663SMark.Logan@Sun.COM
255*9663SMark.Logan@Sun.COM va_start (args, message);
256*9663SMark.Logan@Sun.COM error_tail (status, errnum, message, args);
257*9663SMark.Logan@Sun.COM
258*9663SMark.Logan@Sun.COM #ifdef _LIBC
259*9663SMark.Logan@Sun.COM _IO_funlockfile (stderr);
260*9663SMark.Logan@Sun.COM # ifdef __libc_ptf_call
261*9663SMark.Logan@Sun.COM __libc_ptf_call (pthread_setcancelstate, (state, NULL), 0);
262*9663SMark.Logan@Sun.COM # endif
263*9663SMark.Logan@Sun.COM #endif
264*9663SMark.Logan@Sun.COM }
265*9663SMark.Logan@Sun.COM
266*9663SMark.Logan@Sun.COM /* Sometimes we want to have at most one error per line. This
267*9663SMark.Logan@Sun.COM variable controls whether this mode is selected or not. */
268*9663SMark.Logan@Sun.COM int error_one_per_line;
269*9663SMark.Logan@Sun.COM
270*9663SMark.Logan@Sun.COM void
error_at_line(int status,int errnum,const char * file_name,unsigned int line_number,const char * message,...)271*9663SMark.Logan@Sun.COM error_at_line (int status, int errnum, const char *file_name,
272*9663SMark.Logan@Sun.COM unsigned int line_number, const char *message, ...)
273*9663SMark.Logan@Sun.COM {
274*9663SMark.Logan@Sun.COM va_list args;
275*9663SMark.Logan@Sun.COM
276*9663SMark.Logan@Sun.COM if (error_one_per_line)
277*9663SMark.Logan@Sun.COM {
278*9663SMark.Logan@Sun.COM static const char *old_file_name;
279*9663SMark.Logan@Sun.COM static unsigned int old_line_number;
280*9663SMark.Logan@Sun.COM
281*9663SMark.Logan@Sun.COM if (old_line_number == line_number
282*9663SMark.Logan@Sun.COM && (file_name == old_file_name
283*9663SMark.Logan@Sun.COM || strcmp (old_file_name, file_name) == 0))
284*9663SMark.Logan@Sun.COM /* Simply return and print nothing. */
285*9663SMark.Logan@Sun.COM return;
286*9663SMark.Logan@Sun.COM
287*9663SMark.Logan@Sun.COM old_file_name = file_name;
288*9663SMark.Logan@Sun.COM old_line_number = line_number;
289*9663SMark.Logan@Sun.COM }
290*9663SMark.Logan@Sun.COM
291*9663SMark.Logan@Sun.COM #if defined _LIBC && defined __libc_ptf_call
292*9663SMark.Logan@Sun.COM /* We do not want this call to be cut short by a thread
293*9663SMark.Logan@Sun.COM cancellation. Therefore disable cancellation for now. */
294*9663SMark.Logan@Sun.COM int state = PTHREAD_CANCEL_ENABLE;
295*9663SMark.Logan@Sun.COM __libc_ptf_call (pthread_setcancelstate, (PTHREAD_CANCEL_DISABLE, &state),
296*9663SMark.Logan@Sun.COM 0);
297*9663SMark.Logan@Sun.COM #endif
298*9663SMark.Logan@Sun.COM
299*9663SMark.Logan@Sun.COM fflush (stdout);
300*9663SMark.Logan@Sun.COM #ifdef _LIBC
301*9663SMark.Logan@Sun.COM _IO_flockfile (stderr);
302*9663SMark.Logan@Sun.COM #endif
303*9663SMark.Logan@Sun.COM if (error_print_progname)
304*9663SMark.Logan@Sun.COM (*error_print_progname) ();
305*9663SMark.Logan@Sun.COM else
306*9663SMark.Logan@Sun.COM {
307*9663SMark.Logan@Sun.COM #if _LIBC
308*9663SMark.Logan@Sun.COM __fxprintf (NULL, "%s:", program_name);
309*9663SMark.Logan@Sun.COM #else
310*9663SMark.Logan@Sun.COM fprintf (stderr, "%s:", program_name);
311*9663SMark.Logan@Sun.COM #endif
312*9663SMark.Logan@Sun.COM }
313*9663SMark.Logan@Sun.COM
314*9663SMark.Logan@Sun.COM #if _LIBC
315*9663SMark.Logan@Sun.COM __fxprintf (NULL, file_name != NULL ? "%s:%d: " : " ",
316*9663SMark.Logan@Sun.COM file_name, line_number);
317*9663SMark.Logan@Sun.COM #else
318*9663SMark.Logan@Sun.COM fprintf (stderr, file_name != NULL ? "%s:%d: " : " ",
319*9663SMark.Logan@Sun.COM file_name, line_number);
320*9663SMark.Logan@Sun.COM #endif
321*9663SMark.Logan@Sun.COM
322*9663SMark.Logan@Sun.COM va_start (args, message);
323*9663SMark.Logan@Sun.COM error_tail (status, errnum, message, args);
324*9663SMark.Logan@Sun.COM
325*9663SMark.Logan@Sun.COM #ifdef _LIBC
326*9663SMark.Logan@Sun.COM _IO_funlockfile (stderr);
327*9663SMark.Logan@Sun.COM # ifdef __libc_ptf_call
328*9663SMark.Logan@Sun.COM __libc_ptf_call (pthread_setcancelstate, (state, NULL), 0);
329*9663SMark.Logan@Sun.COM # endif
330*9663SMark.Logan@Sun.COM #endif
331*9663SMark.Logan@Sun.COM }
332*9663SMark.Logan@Sun.COM
333*9663SMark.Logan@Sun.COM #ifdef _LIBC
334*9663SMark.Logan@Sun.COM /* Make the weak alias. */
335*9663SMark.Logan@Sun.COM # undef error
336*9663SMark.Logan@Sun.COM # undef error_at_line
337*9663SMark.Logan@Sun.COM weak_alias (__error, error)
338*9663SMark.Logan@Sun.COM weak_alias (__error_at_line, error_at_line)
339*9663SMark.Logan@Sun.COM #endif
340