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