summaryrefslogtreecommitdiffstats
path: root/lib/error.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/error.c')
-rw-r--r--lib/error.c207
1 files changed, 64 insertions, 143 deletions
diff --git a/lib/error.c b/lib/error.c
index 2296124a..1149235a 100644
--- a/lib/error.c
+++ b/lib/error.c
@@ -1,5 +1,7 @@
1/* Error handler for noninteractive utilities 1/* Error handler for noninteractive utilities
2 Copyright (C) 1990-1998, 2000, 2001, 2002, 2003 Free Software Foundation, Inc. 2 Copyright (C) 1990-1998, 2000-2002, 2003 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
4
3 This program is free software; you can redistribute it and/or modify 5 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by 6 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation; either version 2, or (at your option) 7 the Free Software Foundation; either version 2, or (at your option)
@@ -20,7 +22,12 @@
20# include <config.h> 22# include <config.h>
21#endif 23#endif
22 24
25#include "error.h"
26
27#include <stdarg.h>
23#include <stdio.h> 28#include <stdio.h>
29#include <stdlib.h>
30#include <string.h>
24 31
25#ifdef _LIBC 32#ifdef _LIBC
26# include <libintl.h> 33# include <libintl.h>
@@ -33,28 +40,6 @@
33# define mbsrtowcs __mbsrtowcs 40# define mbsrtowcs __mbsrtowcs
34#endif 41#endif
35 42
36#if HAVE_VPRINTF || HAVE_DOPRNT || _LIBC
37# if __STDC__
38# include <stdarg.h>
39# define VA_START(args, lastarg) va_start(args, lastarg)
40# else
41# include <varargs.h>
42# define VA_START(args, lastarg) va_start(args)
43# endif
44#else
45# define va_alist a1, a2, a3, a4, a5, a6, a7, a8
46# define va_dcl char *a1, *a2, *a3, *a4, *a5, *a6, *a7, *a8;
47#endif
48
49#if STDC_HEADERS || _LIBC
50# include <stdlib.h>
51# include <string.h>
52#else
53void exit ();
54#endif
55
56#include "error.h"
57
58#if !_LIBC 43#if !_LIBC
59# include "unlocked-io.h" 44# include "unlocked-io.h"
60#endif 45#endif
@@ -66,11 +51,7 @@ void exit ();
66/* If NULL, error will flush stdout, then print on stderr the program 51/* If NULL, error will flush stdout, then print on stderr the program
67 name, a colon and a space. Otherwise, error will call this 52 name, a colon and a space. Otherwise, error will call this
68 function without parameters instead. */ 53 function without parameters instead. */
69void (*error_print_progname) ( 54void (*error_print_progname) (void);
70#if __STDC__ - 0
71 void
72#endif
73 );
74 55
75/* This variable is incremented each time `error' is called. */ 56/* This variable is incremented each time `error' is called. */
76unsigned int error_message_count; 57unsigned int error_message_count;
@@ -98,6 +79,8 @@ extern void __error_at_line (int status, int errnum, const char *file_name,
98# undef putc 79# undef putc
99# define putc(c, fp) INTUSE(_IO_putc) (c, fp) 80# define putc(c, fp) INTUSE(_IO_putc) (c, fp)
100 81
82# include <bits/libc-lock.h>
83
101#else /* not _LIBC */ 84#else /* not _LIBC */
102 85
103# if !HAVE_DECL_STRERROR_R && STRERROR_R_CHAR_P 86# if !HAVE_DECL_STRERROR_R && STRERROR_R_CHAR_P
@@ -107,34 +90,17 @@ extern void __error_at_line (int status, int errnum, const char *file_name,
107char *strerror_r (); 90char *strerror_r ();
108# endif 91# endif
109 92
93# ifndef SIZE_MAX
94# define SIZE_MAX ((size_t) -1)
95# endif
96
110/* The calling program should define program_name and set it to the 97/* The calling program should define program_name and set it to the
111 name of the executing program. */ 98 name of the executing program. */
112extern char *progname; 99extern char *program_name;
113 100
114# if HAVE_STRERROR_R || defined strerror_r 101# if HAVE_STRERROR_R || defined strerror_r
115# define __strerror_r strerror_r 102# define __strerror_r strerror_r
116# else 103# endif
117# if HAVE_STRERROR
118# ifndef HAVE_DECL_STRERROR
119"this configure-time declaration test was not run"
120# endif
121# if !HAVE_DECL_STRERROR
122char *strerror ();
123# endif
124# else
125static char *
126private_strerror (int errnum)
127{
128 extern char *sys_errlist[];
129 extern int sys_nerr;
130
131 if (errnum > 0 && errnum <= sys_nerr)
132 return _(sys_errlist[errnum]);
133 return _("Unknown system error");
134}
135# define strerror private_strerror
136# endif /* HAVE_STRERROR */
137# endif /* HAVE_STRERROR_R || defined strerror_r */
138#endif /* not _LIBC */ 104#endif /* not _LIBC */
139 105
140static void 106static void
@@ -172,93 +138,70 @@ print_errno_message (int errnum)
172 fprintf (stderr, ": %s", s); 138 fprintf (stderr, ": %s", s);
173} 139}
174 140
175#ifdef VA_START
176static void 141static void
177error_tail (int status, int errnum, const char *message, va_list args) 142error_tail (int status, int errnum, const char *message, va_list args)
178{ 143{
179# if HAVE_VPRINTF || _LIBC 144#if _LIBC
180# if _LIBC
181 if (_IO_fwide (stderr, 0) > 0) 145 if (_IO_fwide (stderr, 0) > 0)
182 { 146 {
183# define ALLOCA_LIMIT 2000 147# define ALLOCA_LIMIT 2000
184 size_t len = strlen (message) + 1; 148 size_t len = strlen (message) + 1;
185 wchar_t *wmessage = NULL; 149 const wchar_t *wmessage = L"out of memory";
186 mbstate_t st; 150 wchar_t *wbuf = (len < ALLOCA_LIMIT
187 size_t res; 151 ? alloca (len * sizeof *wbuf)
188 const char *tmp; 152 : len <= SIZE_MAX / sizeof *wbuf
189 153 ? malloc (len * sizeof *wbuf)
190 do 154 : NULL);
155
156 if (wbuf)
191 { 157 {
192 if (len < ALLOCA_LIMIT) 158 size_t res;
193 wmessage = (wchar_t *) alloca (len * sizeof (wchar_t)); 159 mbstate_t st;
194 else 160 const char *tmp = message;
195 {
196 if (wmessage != NULL && len / 2 < ALLOCA_LIMIT)
197 wmessage = NULL;
198
199 wmessage = (wchar_t *) realloc (wmessage,
200 len * sizeof (wchar_t));
201
202 if (wmessage == NULL)
203 {
204 fputws_unlocked (L"out of memory\n", stderr);
205 return;
206 }
207 }
208
209 memset (&st, '\0', sizeof (st)); 161 memset (&st, '\0', sizeof (st));
210 tmp =message; 162 res = mbsrtowcs (wbuf, &tmp, len, &st);
163 wmessage = res == (size_t) -1 ? L"???" : wbuf;
211 } 164 }
212 while ((res = mbsrtowcs (wmessage, &tmp, len, &st)) == len);
213
214 if (res == (size_t) -1)
215 /* The string cannot be converted. */
216 wmessage = (wchar_t *) L"???";
217 165
218 __vfwprintf (stderr, wmessage, args); 166 __vfwprintf (stderr, wmessage, args);
167 if (! (len < ALLOCA_LIMIT))
168 free (wbuf);
219 } 169 }
220 else 170 else
221# endif 171#endif
222 vfprintf (stderr, message, args); 172 vfprintf (stderr, message, args);
223# else
224 _doprnt (message, args, stderr);
225# endif
226 va_end (args); 173 va_end (args);
227 174
228 ++error_message_count; 175 ++error_message_count;
229 if (errnum) 176 if (errnum)
230 print_errno_message (errnum); 177 print_errno_message (errnum);
231# if _LIBC 178#if _LIBC
232 if (_IO_fwide (stderr, 0) > 0) 179 if (_IO_fwide (stderr, 0) > 0)
233 putwc (L'\n', stderr); 180 putwc (L'\n', stderr);
234 else 181 else
235# endif 182#endif
236 putc ('\n', stderr); 183 putc ('\n', stderr);
237 fflush (stderr); 184 fflush (stderr);
238 if (status) 185 if (status)
239 exit (status); 186 exit (status);
240} 187}
241#endif
242 188
243 189
244/* Print the program name and error message MESSAGE, which is a printf-style 190/* Print the program name and error message MESSAGE, which is a printf-style
245 format string with optional args. 191 format string with optional args.
246 If ERRNUM is nonzero, print its corresponding system error message. 192 If ERRNUM is nonzero, print its corresponding system error message.
247 Exit with status STATUS if it is nonzero. */ 193 Exit with status STATUS if it is nonzero. */
248/* VARARGS */
249void 194void
250#if defined VA_START && __STDC__
251error (int status, int errnum, const char *message, ...) 195error (int status, int errnum, const char *message, ...)
252#else
253error (status, errnum, message, va_alist)
254 int status;
255 int errnum;
256 char *message;
257 va_dcl
258#endif
259{ 196{
260#ifdef VA_START
261 va_list args; 197 va_list args;
198
199#if defined _LIBC && defined __libc_ptf_call
200 /* We do not want this call to be cut short by a thread
201 cancellation. Therefore disable cancellation for now. */
202 int state = PTHREAD_CANCEL_ENABLE;
203 __libc_ptf_call (pthread_setcancelstate, (PTHREAD_CANCEL_DISABLE, &state),
204 0);
262#endif 205#endif
263 206
264 fflush (stdout); 207 fflush (stdout);
@@ -271,29 +214,20 @@ error (status, errnum, message, va_alist)
271 { 214 {
272#if _LIBC 215#if _LIBC
273 if (_IO_fwide (stderr, 0) > 0) 216 if (_IO_fwide (stderr, 0) > 0)
274 __fwprintf (stderr, L"%s: ", progname); 217 __fwprintf (stderr, L"%s: ", program_name);
275 else 218 else
276#endif 219#endif
277 fprintf (stderr, "%s: ", progname); 220 fprintf (stderr, "%s: ", program_name);
278 } 221 }
279 222
280#ifdef VA_START 223 va_start (args, message);
281 VA_START (args, message);
282 error_tail (status, errnum, message, args); 224 error_tail (status, errnum, message, args);
283#else
284 fprintf (stderr, message, a1, a2, a3, a4, a5, a6, a7, a8);
285
286 ++error_message_count;
287 if (errnum)
288 print_errno_message (errnum);
289 putc ('\n', stderr);
290 fflush (stderr);
291 if (status)
292 exit (status);
293#endif
294 225
295#ifdef _LIBC 226#ifdef _LIBC
296 _IO_funlockfile (stderr); 227 _IO_funlockfile (stderr);
228# ifdef __libc_ptf_call
229 __libc_ptf_call (pthread_setcancelstate, (state, NULL), 0);
230# endif
297#endif 231#endif
298} 232}
299 233
@@ -302,22 +236,10 @@ error (status, errnum, message, va_alist)
302int error_one_per_line; 236int error_one_per_line;
303 237
304void 238void
305#if defined VA_START && __STDC__
306error_at_line (int status, int errnum, const char *file_name, 239error_at_line (int status, int errnum, const char *file_name,
307 unsigned int line_number, const char *message, ...) 240 unsigned int line_number, const char *message, ...)
308#else
309error_at_line (status, errnum, file_name, line_number, message, va_alist)
310 int status;
311 int errnum;
312 const char *file_name;
313 unsigned int line_number;
314 char *message;
315 va_dcl
316#endif
317{ 241{
318#ifdef VA_START
319 va_list args; 242 va_list args;
320#endif
321 243
322 if (error_one_per_line) 244 if (error_one_per_line)
323 { 245 {
@@ -334,6 +256,14 @@ error_at_line (status, errnum, file_name, line_number, message, va_alist)
334 old_line_number = line_number; 256 old_line_number = line_number;
335 } 257 }
336 258
259#if defined _LIBC && defined __libc_ptf_call
260 /* We do not want this call to be cut short by a thread
261 cancellation. Therefore disable cancellation for now. */
262 int state = PTHREAD_CANCEL_ENABLE;
263 __libc_ptf_call (pthread_setcancelstate, (PTHREAD_CANCEL_DISABLE, &state),
264 0);
265#endif
266
337 fflush (stdout); 267 fflush (stdout);
338#ifdef _LIBC 268#ifdef _LIBC
339 _IO_flockfile (stderr); 269 _IO_flockfile (stderr);
@@ -344,10 +274,10 @@ error_at_line (status, errnum, file_name, line_number, message, va_alist)
344 { 274 {
345#if _LIBC 275#if _LIBC
346 if (_IO_fwide (stderr, 0) > 0) 276 if (_IO_fwide (stderr, 0) > 0)
347 __fwprintf (stderr, L"%s: ", progname); 277 __fwprintf (stderr, L"%s: ", program_name);
348 else 278 else
349#endif 279#endif
350 fprintf (stderr, "%s:", progname); 280 fprintf (stderr, "%s:", program_name);
351 } 281 }
352 282
353 if (file_name != NULL) 283 if (file_name != NULL)
@@ -360,23 +290,14 @@ error_at_line (status, errnum, file_name, line_number, message, va_alist)
360 fprintf (stderr, "%s:%d: ", file_name, line_number); 290 fprintf (stderr, "%s:%d: ", file_name, line_number);
361 } 291 }
362 292
363#ifdef VA_START 293 va_start (args, message);
364 VA_START (args, message);
365 error_tail (status, errnum, message, args); 294 error_tail (status, errnum, message, args);
366#else
367 fprintf (stderr, message, a1, a2, a3, a4, a5, a6, a7, a8);
368
369 ++error_message_count;
370 if (errnum)
371 print_errno_message (errnum);
372 putc ('\n', stderr);
373 fflush (stderr);
374 if (status)
375 exit (status);
376#endif
377 295
378#ifdef _LIBC 296#ifdef _LIBC
379 _IO_funlockfile (stderr); 297 _IO_funlockfile (stderr);
298# ifdef __libc_ptf_call
299 __libc_ptf_call (pthread_setcancelstate, (state, NULL), 0);
300# endif
380#endif 301#endif
381} 302}
382 303