Merge from vendor branch CVS:
[dragonfly.git] / contrib / tar / lib / error.c
1 /* Error handler for noninteractive utilities
2    Copyright (C) 1990-1998, 2000, 2001 Free Software Foundation, Inc.
3    This file is part of the GNU C Library.  Its master source is NOT part of
4    the C library, however.  The master source lives in /gd/gnu/lib.
5
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 2, or (at your option)
9    any later version.
10
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15
16    You should have received a copy of the GNU General Public License
17    along with this program; if not, write to the Free Software Foundation,
18    Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
19
20 /* Written by David MacKenzie <djm@gnu.ai.mit.edu>.  */
21
22 /* $FreeBSD: src/contrib/tar/lib/error.c,v 1.2.2.1 2002/07/14 13:19:40 sobomax Exp $ */
23 /* $DragonFly: src/contrib/tar/lib/Attic/error.c,v 1.2 2003/06/17 04:24:06 dillon Exp $ */
24
25 #ifdef HAVE_CONFIG_H
26 # include <config.h>
27 #endif
28
29 #include <stdio.h>
30 #if HAVE_LIBINTL_H
31 # include <libintl.h>
32 #endif
33 #ifdef _LIBC
34 # include <wchar.h>
35 # define mbsrtowcs __mbsrtowcs
36 #endif
37
38 #if HAVE_VPRINTF || HAVE_DOPRNT || _LIBC
39 # if __STDC__
40 #  include <stdarg.h>
41 #  define VA_START(args, lastarg) va_start(args, lastarg)
42 # else
43 #  include <varargs.h>
44 #  define VA_START(args, lastarg) va_start(args)
45 # endif
46 #else
47 # define va_alist a1, a2, a3, a4, a5, a6, a7, a8
48 # define va_dcl char *a1, *a2, *a3, *a4, *a5, *a6, *a7, *a8;
49 #endif
50
51 #if STDC_HEADERS || _LIBC
52 # include <stdlib.h>
53 # include <string.h>
54 #else
55 void exit ();
56 #endif
57
58 #include "error.h"
59
60 #ifndef HAVE_DECL_STRERROR_R
61 "this configure-time declaration test was not run"
62 #endif
63 #if !HAVE_DECL_STRERROR_R
64 char *strerror_r ();
65 #endif
66
67 #ifndef _
68 # define _(String) String
69 #endif
70
71 /* If NULL, error will flush stdout, then print on stderr the program
72    name, a colon and a space.  Otherwise, error will call this
73    function without parameters instead.  */
74 void (*error_print_progname) (
75 #if __STDC__ - 0
76                               void
77 #endif
78                               );
79
80 /* This variable is incremented each time `error' is called.  */
81 unsigned int error_message_count;
82
83 #ifdef _LIBC
84 /* In the GNU C library, there is a predefined variable for this.  */
85
86 # define program_name program_invocation_name
87 # include <errno.h>
88
89 /* In GNU libc we want do not want to use the common name `error' directly.
90    Instead make it a weak alias.  */
91 extern void __error (int status, int errnum, const char *message, ...)
92      __attribute__ ((__format__ (__printf__, 3, 4)));
93 extern void __error_at_line (int status, int errnum, const char *file_name,
94                              unsigned int line_number, const char *message,
95                              ...)
96      __attribute__ ((__format__ (__printf__, 5, 6)));;
97 # define error __error
98 # define error_at_line __error_at_line
99
100 # ifdef USE_IN_LIBIO
101 #  include <libio/iolibio.h>
102 #  define fflush(s) _IO_fflush (s)
103 # endif
104
105 #else /* not _LIBC */
106
107 /* The calling program should define program_name and set it to the
108    name of the executing program.  */
109 extern char *program_name;
110
111 # ifdef HAVE_STRERROR_R
112 #  define __strerror_r strerror_r
113 # else
114 #  if HAVE_STRERROR
115 #   ifndef strerror             /* On some systems, strerror is a macro */
116 char *strerror ();
117 #   endif
118 #  else
119 static char *
120 private_strerror (errnum)
121      int errnum;
122 {
123   extern char *sys_errlist[];
124   extern int sys_nerr;
125
126   if (errnum > 0 && errnum <= sys_nerr)
127     return _(sys_errlist[errnum]);
128   return _("Unknown system error");
129 }
130 #   define strerror private_strerror
131 #  endif /* HAVE_STRERROR */
132 # endif /* HAVE_STRERROR_R */
133 #endif  /* not _LIBC */
134
135
136 #ifdef VA_START
137 static void
138 error_tail (int status, int errnum, const char *message, va_list args)
139 {
140 # if HAVE_VPRINTF || _LIBC
141 #  if _LIBC && USE_IN_LIBIO
142   if (_IO_fwide (stderr, 0) > 0)
143     {
144 #   define ALLOCA_LIMIT 2000
145       size_t len = strlen (message) + 1;
146       wchar_t *wmessage = NULL;
147       mbstate_t st;
148       size_t res;
149       const char *tmp;
150
151       do
152         {
153           if (len < ALLOCA_LIMIT)
154             wmessage = (wchar_t *) alloca (len * sizeof (wchar_t));
155           else
156             {
157               if (wmessage != NULL && len / 2 < ALLOCA_LIMIT)
158                 wmessage = NULL;
159
160               wmessage = (wchar_t *) realloc (wmessage,
161                                               len * sizeof (wchar_t));
162
163               if (wmessage == NULL)
164                 {
165                   fputws_unlocked (L"out of memory\n", stderr);
166                   return;
167                 }
168             }
169
170           memset (&st, '\0', sizeof (st));
171           tmp =message;
172         }
173       while ((res = mbsrtowcs (wmessage, &tmp, len, &st)) == len);
174
175       if (res == (size_t) -1)
176         /* The string cannot be converted.  */
177         wmessage = (wchar_t *) L"???";
178
179       __vfwprintf (stderr, wmessage, args);
180     }
181   else
182 #  endif
183     vfprintf (stderr, message, args);
184 # else
185   _doprnt (message, args, stderr);
186 # endif
187   va_end (args);
188
189   ++error_message_count;
190   if (errnum)
191     {
192 # if defined HAVE_STRERROR_R || _LIBC
193       char errbuf[1024];
194       char *s;
195       /* Don't use __strerror_r's return value because on some systems
196          (at least DEC UNIX 4.0[A-D]) strerror_r returns `int'.  */
197       (void)__strerror_r (errnum, errbuf, sizeof errbuf);
198       s = errbuf;
199 #  if _LIBC && USE_IN_LIBIO
200       if (_IO_fwide (stderr, 0) > 0)
201         __fwprintf (stderr, L": %s", s);
202       else
203 #  endif
204         fprintf (stderr, ": %s", s);
205 # else
206       fprintf (stderr, ": %s", strerror (errnum));
207 # endif
208     }
209 # if _LIBC && USE_IN_LIBIO
210   if (_IO_fwide (stderr, 0) > 0)
211     putwc (L'\n', stderr);
212   else
213 # endif
214     putc ('\n', stderr);
215   fflush (stderr);
216   if (status)
217     exit (status);
218 }
219 #endif
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 /* VARARGS */
227 void
228 #if defined VA_START && __STDC__
229 error (int status, int errnum, const char *message, ...)
230 #else
231 error (status, errnum, message, va_alist)
232      int status;
233      int errnum;
234      char *message;
235      va_dcl
236 #endif
237 {
238 #ifdef VA_START
239   va_list args;
240 #endif
241
242   fflush (stdout);
243 #ifdef _LIBC
244 # ifdef USE_IN_LIBIO
245   _IO_flockfile (stderr);
246 # else
247   __flockfile (stderr);
248 # endif
249 #endif
250   if (error_print_progname)
251     (*error_print_progname) ();
252   else
253     {
254 #if _LIBC && USE_IN_LIBIO
255       if (_IO_fwide (stderr, 0) > 0)
256         __fwprintf (stderr, L"%s: ", program_name);
257       else
258 #endif
259         fprintf (stderr, "%s: ", program_name);
260     }
261
262 #ifdef VA_START
263   VA_START (args, message);
264   error_tail (status, errnum, message, args);
265 #else
266   fprintf (stderr, message, a1, a2, a3, a4, a5, a6, a7, a8);
267
268   ++error_message_count;
269   if (errnum)
270     {
271 # if defined HAVE_STRERROR_R || _LIBC
272       char errbuf[1024];
273       /* Don't use __strerror_r's return value because on some systems
274          (at least DEC UNIX 4.0[A-D]) strerror_r returns `int'.  */
275       __strerror_r (errnum, errbuf, sizeof errbuf);
276       fprintf (stderr, ": %s", errbuf);
277 # else
278       fprintf (stderr, ": %s", strerror (errnum));
279 # endif
280     }
281   putc ('\n', stderr);
282   fflush (stderr);
283   if (status)
284     exit (status);
285 #endif
286
287 #ifdef _LIBC
288 # ifdef USE_IN_LIBIO
289   _IO_funlockfile (stderr);
290 # else
291   __funlockfile (stderr);
292 # endif
293 #endif
294 }
295 \f
296 /* Sometimes we want to have at most one error per line.  This
297    variable controls whether this mode is selected or not.  */
298 int error_one_per_line;
299
300 void
301 #if defined VA_START && __STDC__
302 error_at_line (int status, int errnum, const char *file_name,
303                unsigned int line_number, const char *message, ...)
304 #else
305 error_at_line (status, errnum, file_name, line_number, message, va_alist)
306      int status;
307      int errnum;
308      const char *file_name;
309      unsigned int line_number;
310      char *message;
311      va_dcl
312 #endif
313 {
314 #ifdef VA_START
315   va_list args;
316 #endif
317
318   if (error_one_per_line)
319     {
320       static const char *old_file_name;
321       static unsigned int old_line_number;
322
323       if (old_line_number == line_number
324           && (file_name == old_file_name
325               || strcmp (old_file_name, file_name) == 0))
326         /* Simply return and print nothing.  */
327         return;
328
329       old_file_name = file_name;
330       old_line_number = line_number;
331     }
332
333   fflush (stdout);
334 #ifdef _LIBC
335 # ifdef USE_IN_LIBIO
336   _IO_flockfile (stderr);
337 # else
338   __flockfile (stderr);
339 # endif
340 #endif
341   if (error_print_progname)
342     (*error_print_progname) ();
343   else
344     {
345 #if _LIBC && USE_IN_LIBIO
346       if (_IO_fwide (stderr, 0) > 0)
347         __fwprintf (stderr, L"%s: ", program_name);
348       else
349 #endif
350         fprintf (stderr, "%s:", program_name);
351     }
352
353   if (file_name != NULL)
354     {
355 #if _LIBC && USE_IN_LIBIO
356       if (_IO_fwide (stderr, 0) > 0)
357         __fwprintf (stderr, L"%s:%d: ", file_name, line_number);
358       else
359 #endif
360         fprintf (stderr, "%s:%d: ", file_name, line_number);
361     }
362
363 #ifdef VA_START
364   VA_START (args, message);
365   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     {
372 # if defined HAVE_STRERROR_R || _LIBC
373       char errbuf[1024];
374       /* Don't use __strerror_r's return value because on some systems
375          (at least DEC UNIX 4.0[A-D]) strerror_r returns `int'.  */
376       __strerror_r (errnum, errbuf, sizeof errbuf);
377       fprintf (stderr, ": %s", errbuf);
378 # else
379       fprintf (stderr, ": %s", strerror (errnum));
380 # endif
381     }
382   putc ('\n', stderr);
383   fflush (stderr);
384   if (status)
385     exit (status);
386 #endif
387
388 #ifdef _LIBC
389 # ifdef USE_IN_LIBIO
390   _IO_funlockfile (stderr);
391 # else
392   __funlockfile (stderr);
393 # endif
394 #endif
395 }
396
397 #ifdef _LIBC
398 /* Make the weak alias.  */
399 # undef error
400 # undef error_at_line
401 weak_alias (__error, error)
402 weak_alias (__error_at_line, error_at_line)
403 #endif