.
[glibc/history.git] / misc / error.c
blob66a8ccb5016aadae4f632634116d6cdd62a35956
1 /* Error handler for noninteractive utilities
2 Copyright (C) 1990-1998, 2000-2004, 2005 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
10 The GNU C Library 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 GNU
13 Lesser General Public License for more details.
15 You should have received a copy of the GNU Lesser General Public
16 License along with the GNU C Library; if not, write to the Free
17 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
18 02111-1307 USA. */
20 /* Written by David MacKenzie <djm@gnu.ai.mit.edu>. */
22 #ifdef HAVE_CONFIG_H
23 # include <config.h>
24 #endif
26 #include <stdio.h>
27 #include <libintl.h>
28 #ifdef _LIBC
29 # include <stdbool.h>
30 # include <stdint.h>
31 # include <wchar.h>
32 # define mbsrtowcs __mbsrtowcs
33 #endif
35 #if HAVE_VPRINTF || HAVE_DOPRNT || _LIBC
36 # if __STDC__
37 # include <stdarg.h>
38 # define VA_START(args, lastarg) va_start(args, lastarg)
39 # else
40 # include <varargs.h>
41 # define VA_START(args, lastarg) va_start(args)
42 # endif
43 #else
44 # define va_alist a1, a2, a3, a4, a5, a6, a7, a8
45 # define va_dcl char *a1, *a2, *a3, *a4, *a5, *a6, *a7, *a8;
46 #endif
48 #if STDC_HEADERS || _LIBC
49 # include <stdlib.h>
50 # include <string.h>
51 #else
52 void exit ();
53 #endif
55 #include "error.h"
57 #ifndef _
58 # define _(String) String
59 #endif
61 /* If NULL, error will flush stdout, then print on stderr the program
62 name, a colon and a space. Otherwise, error will call this
63 function without parameters instead. */
64 void (*error_print_progname) (
65 #if __STDC__ - 0
66 void
67 #endif
70 /* This variable is incremented each time `error' is called. */
71 unsigned int error_message_count;
73 #ifdef _LIBC
74 /* In the GNU C library, there is a predefined variable for this. */
76 # define program_name program_invocation_name
77 # include <errno.h>
78 # include <limits.h>
79 # include <libio/libioP.h>
81 /* In GNU libc we want do not want to use the common name `error' directly.
82 Instead make it a weak alias. */
83 extern void __error (int status, int errnum, const char *message, ...)
84 __attribute__ ((__format__ (__printf__, 3, 4)));
85 extern void __error_at_line (int status, int errnum, const char *file_name,
86 unsigned int line_number, const char *message,
87 ...)
88 __attribute__ ((__format__ (__printf__, 5, 6)));;
89 # define error __error
90 # define error_at_line __error_at_line
92 # include <libio/iolibio.h>
93 # define fflush(s) INTUSE(_IO_fflush) (s)
94 # undef putc
95 # define putc(c, fp) INTUSE(_IO_putc) (c, fp)
97 # include <bits/libc-lock.h>
99 #else /* not _LIBC */
101 # if !HAVE_DECL_STRERROR_R && STRERROR_R_CHAR_P
102 # ifndef HAVE_DECL_STRERROR_R
103 "this configure-time declaration test was not run"
104 # endif
105 char *strerror_r ();
106 # endif
108 /* The calling program should define program_name and set it to the
109 name of the executing program. */
110 extern char *program_name;
112 # if HAVE_STRERROR_R || defined strerror_r
113 # define __strerror_r strerror_r
114 # else
115 # if HAVE_STRERROR
116 # ifndef HAVE_DECL_STRERROR
117 "this configure-time declaration test was not run"
118 # endif
119 # if !HAVE_DECL_STRERROR
120 char *strerror ();
121 # endif
122 # else
123 static char *
124 private_strerror (int errnum)
126 extern char *sys_errlist[];
127 extern int sys_nerr;
129 if (errnum > 0 && errnum <= sys_nerr)
130 return _(sys_errlist[errnum]);
131 return _("Unknown system error");
133 # define strerror private_strerror
134 # endif /* HAVE_STRERROR */
135 # endif /* HAVE_STRERROR_R || defined strerror_r */
136 #endif /* not _LIBC */
138 static void
139 print_errno_message (int errnum)
141 char const *s;
143 #if defined HAVE_STRERROR_R || _LIBC
144 char errbuf[1024];
145 # if STRERROR_R_CHAR_P || _LIBC
146 s = __strerror_r (errnum, errbuf, sizeof errbuf);
147 # else
148 if (__strerror_r (errnum, errbuf, sizeof errbuf) == 0)
149 s = errbuf;
150 else
151 s = 0;
152 # endif
153 #else
154 s = strerror (errnum);
155 #endif
157 #if !_LIBC
158 if (! s)
159 s = _("Unknown system error");
160 #endif
162 #if _LIBC
163 __fxprintf (NULL, ": %s", s);
164 #else
165 fprintf (stderr, ": %s", s);
166 #endif
169 #ifdef VA_START
170 static void
171 error_tail (int status, int errnum, const char *message, va_list args)
173 # if HAVE_VPRINTF || _LIBC
174 # if _LIBC
175 if (_IO_fwide (stderr, 0) > 0)
177 # define ALLOCA_LIMIT 2000
178 size_t len = strlen (message) + 1;
179 wchar_t *wmessage = NULL;
180 mbstate_t st;
181 size_t res;
182 const char *tmp;
183 bool use_malloc = false;
185 while (1)
187 if (__libc_use_alloca (len * sizeof (wchar_t)))
188 wmessage = (wchar_t *) alloca (len * sizeof (wchar_t));
189 else
191 if (!use_malloc)
192 wmessage = NULL;
194 wchar_t *p = (wchar_t *) realloc (wmessage,
195 len * sizeof (wchar_t));
196 if (p == NULL)
198 free (wmessage);
199 fputws_unlocked (L"out of memory\n", stderr);
200 return;
202 wmessage = p;
203 use_malloc = true;
206 memset (&st, '\0', sizeof (st));
207 tmp = message;
209 res = mbsrtowcs (wmessage, &tmp, len, &st);
210 if (res != len)
211 break;
213 if (__builtin_expect (len >= SIZE_MAX / 2, 0))
215 /* This really should not happen if everything is fine. */
216 res = (size_t) -1;
217 break;
220 len *= 2;
223 if (res == (size_t) -1)
225 /* The string cannot be converted. */
226 if (use_malloc)
227 free (wmessage);
228 wmessage = (wchar_t *) L"???";
231 __vfwprintf (stderr, wmessage, args);
233 if (use_malloc)
234 free (wmessage);
236 else
237 # endif
238 vfprintf (stderr, message, args);
239 # else
240 _doprnt (message, args, stderr);
241 # endif
242 va_end (args);
244 ++error_message_count;
245 if (errnum)
246 print_errno_message (errnum);
247 # if _LIBC
248 __fxprintf (NULL, "\n");
249 # else
250 putc ('\n', stderr);
251 # endif
252 fflush (stderr);
253 if (status)
254 exit (status);
256 #endif
259 /* Print the program name and error message MESSAGE, which is a printf-style
260 format string with optional args.
261 If ERRNUM is nonzero, print its corresponding system error message.
262 Exit with status STATUS if it is nonzero. */
263 /* VARARGS */
264 void
265 #if defined VA_START && __STDC__
266 error (int status, int errnum, const char *message, ...)
267 #else
268 error (status, errnum, message, va_alist)
269 int status;
270 int errnum;
271 char *message;
272 va_dcl
273 #endif
275 #ifdef VA_START
276 va_list args;
277 #endif
279 #if defined _LIBC && defined __libc_ptf_call
280 /* We do not want this call to be cut short by a thread
281 cancellation. Therefore disable cancellation for now. */
282 int state = PTHREAD_CANCEL_ENABLE;
283 __libc_ptf_call (pthread_setcancelstate, (PTHREAD_CANCEL_DISABLE, &state),
285 #endif
287 fflush (stdout);
288 #ifdef _LIBC
289 _IO_flockfile (stderr);
290 #endif
291 if (error_print_progname)
292 (*error_print_progname) ();
293 else
295 #if _LIBC
296 __fxprintf (NULL, "%s: ", program_name);
297 #else
298 fprintf (stderr, "%s: ", program_name);
299 #endif
302 #ifdef VA_START
303 VA_START (args, message);
304 error_tail (status, errnum, message, args);
305 #else
306 fprintf (stderr, message, a1, a2, a3, a4, a5, a6, a7, a8);
308 ++error_message_count;
309 if (errnum)
310 print_errno_message (errnum);
311 putc ('\n', stderr);
312 fflush (stderr);
313 if (status)
314 exit (status);
315 #endif
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
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;
329 void
330 #if defined VA_START && __STDC__
331 error_at_line (int status, int errnum, const char *file_name,
332 unsigned int line_number, const char *message, ...)
333 #else
334 error_at_line (status, errnum, file_name, line_number, message, va_alist)
335 int status;
336 int errnum;
337 const char *file_name;
338 unsigned int line_number;
339 char *message;
340 va_dcl
341 #endif
343 #ifdef VA_START
344 va_list args;
345 #endif
347 if (error_one_per_line)
349 static const char *old_file_name;
350 static unsigned int old_line_number;
352 if (old_line_number == line_number
353 && (file_name == old_file_name
354 || strcmp (old_file_name, file_name) == 0))
355 /* Simply return and print nothing. */
356 return;
358 old_file_name = file_name;
359 old_line_number = line_number;
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),
368 #endif
370 fflush (stdout);
371 #ifdef _LIBC
372 _IO_flockfile (stderr);
373 #endif
374 if (error_print_progname)
375 (*error_print_progname) ();
376 else
378 #if _LIBC
379 __fxprintf (NULL, "%s:", program_name);
380 #else
381 fprintf (stderr, "%s:", program_name);
382 #endif
385 if (file_name != NULL)
387 #if _LIBC
388 __fxprintf (NULL, "%s:%d: ", file_name, line_number);
389 #else
390 fprintf (stderr, "%s:%d: ", file_name, line_number);
391 #endif
394 #ifdef VA_START
395 VA_START (args, message);
396 error_tail (status, errnum, message, args);
397 #else
398 fprintf (stderr, message, a1, a2, a3, a4, a5, a6, a7, a8);
400 ++error_message_count;
401 if (errnum)
402 print_errno_message (errnum);
403 putc ('\n', stderr);
404 fflush (stderr);
405 if (status)
406 exit (status);
407 #endif
409 #ifdef _LIBC
410 _IO_funlockfile (stderr);
411 # ifdef __libc_ptf_call
412 __libc_ptf_call (pthread_setcancelstate, (state, NULL), 0);
413 # endif
414 #endif
417 #ifdef _LIBC
418 /* Make the weak alias. */
419 # undef error
420 # undef error_at_line
421 weak_alias (__error, error)
422 weak_alias (__error_at_line, error_at_line)
423 #endif