1170754Sdelphij/* Error handler for noninteractive utilities
2170754Sdelphij   Copyright (C) 1990-1998, 2000-2002, 2003 Free Software Foundation, Inc.
3170754Sdelphij   This file is part of the GNU C Library.
4170754Sdelphij
5170754Sdelphij   This program is free software; you can redistribute it and/or modify
6170754Sdelphij   it under the terms of the GNU General Public License as published by
7170754Sdelphij   the Free Software Foundation; either version 2, or (at your option)
8170754Sdelphij   any later version.
9170754Sdelphij
10170754Sdelphij   This program is distributed in the hope that it will be useful,
11170754Sdelphij   but WITHOUT ANY WARRANTY; without even the implied warranty of
12170754Sdelphij   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13170754Sdelphij   GNU General Public License for more details.
14170754Sdelphij
15170754Sdelphij   You should have received a copy of the GNU General Public License along
16170754Sdelphij   with this program; if not, write to the Free Software Foundation,
17170754Sdelphij   Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
18170754Sdelphij
19170754Sdelphij/* Written by David MacKenzie <djm@gnu.ai.mit.edu>.  */
20170754Sdelphij
21170754Sdelphij#ifdef HAVE_CONFIG_H
22170754Sdelphij# include <config.h>
23170754Sdelphij#endif
24170754Sdelphij
25170754Sdelphij#include "error.h"
26170754Sdelphij
27170754Sdelphij#include <stdarg.h>
28170754Sdelphij#include <stdio.h>
29170754Sdelphij#include <stdlib.h>
30170754Sdelphij#include <string.h>
31170754Sdelphij
32170754Sdelphij#ifdef _LIBC
33170754Sdelphij# include <libintl.h>
34170754Sdelphij#else
35170754Sdelphij# include "gettext.h"
36170754Sdelphij#endif
37170754Sdelphij
38170754Sdelphij#ifdef _LIBC
39170754Sdelphij# include <wchar.h>
40170754Sdelphij# define mbsrtowcs __mbsrtowcs
41170754Sdelphij#endif
42170754Sdelphij
43170754Sdelphij#if !_LIBC
44170754Sdelphij# include "unlocked-io.h"
45170754Sdelphij#endif
46170754Sdelphij
47170754Sdelphij#ifndef _
48170754Sdelphij# define _(String) String
49170754Sdelphij#endif
50170754Sdelphij
51170754Sdelphij/* If NULL, error will flush stdout, then print on stderr the program
52170754Sdelphij   name, a colon and a space.  Otherwise, error will call this
53170754Sdelphij   function without parameters instead.  */
54170754Sdelphijvoid (*error_print_progname) (void);
55170754Sdelphij
56170754Sdelphij/* This variable is incremented each time `error' is called.  */
57170754Sdelphijunsigned int error_message_count;
58170754Sdelphij
59170754Sdelphij#ifdef _LIBC
60170754Sdelphij/* In the GNU C library, there is a predefined variable for this.  */
61170754Sdelphij
62170754Sdelphij# define program_name program_invocation_name
63170754Sdelphij# include <errno.h>
64170754Sdelphij# include <libio/libioP.h>
65170754Sdelphij
66170754Sdelphij/* In GNU libc we want do not want to use the common name `error' directly.
67170754Sdelphij   Instead make it a weak alias.  */
68170754Sdelphijextern void __error (int status, int errnum, const char *message, ...)
69170754Sdelphij     __attribute__ ((__format__ (__printf__, 3, 4)));
70170754Sdelphijextern void __error_at_line (int status, int errnum, const char *file_name,
71170754Sdelphij			     unsigned int line_number, const char *message,
72170754Sdelphij			     ...)
73170754Sdelphij     __attribute__ ((__format__ (__printf__, 5, 6)));;
74170754Sdelphij# define error __error
75170754Sdelphij# define error_at_line __error_at_line
76170754Sdelphij
77170754Sdelphij# include <libio/iolibio.h>
78170754Sdelphij# define fflush(s) INTUSE(_IO_fflush) (s)
79170754Sdelphij# undef putc
80170754Sdelphij# define putc(c, fp) INTUSE(_IO_putc) (c, fp)
81170754Sdelphij
82170754Sdelphij# include <bits/libc-lock.h>
83170754Sdelphij
84170754Sdelphij#else /* not _LIBC */
85170754Sdelphij
86170754Sdelphij# if !HAVE_DECL_STRERROR_R && STRERROR_R_CHAR_P
87170754Sdelphij#  ifndef HAVE_DECL_STRERROR_R
88170754Sdelphij"this configure-time declaration test was not run"
89170754Sdelphij#  endif
90170754Sdelphijchar *strerror_r ();
91170754Sdelphij# endif
92170754Sdelphij
93170754Sdelphij# ifndef SIZE_MAX
94170754Sdelphij#  define SIZE_MAX ((size_t) -1)
95170754Sdelphij# endif
96170754Sdelphij
97170754Sdelphij/* The calling program should define program_name and set it to the
98170754Sdelphij   name of the executing program.  */
99170754Sdelphijextern char *program_name;
100170754Sdelphij
101170754Sdelphij# if HAVE_STRERROR_R || defined strerror_r
102170754Sdelphij#  define __strerror_r strerror_r
103170754Sdelphij# endif
104170754Sdelphij#endif	/* not _LIBC */
105170754Sdelphij
106170754Sdelphijstatic void
107170754Sdelphijprint_errno_message (int errnum)
108170754Sdelphij{
109170754Sdelphij  char const *s;
110170754Sdelphij
111170754Sdelphij#if defined HAVE_STRERROR_R || _LIBC
112170754Sdelphij  char errbuf[1024];
113170754Sdelphij# if STRERROR_R_CHAR_P || _LIBC
114170754Sdelphij  s = __strerror_r (errnum, errbuf, sizeof errbuf);
115170754Sdelphij# else
116170754Sdelphij  if (__strerror_r (errnum, errbuf, sizeof errbuf) == 0)
117170754Sdelphij    s = errbuf;
118170754Sdelphij  else
119170754Sdelphij    s = 0;
120170754Sdelphij# endif
121170754Sdelphij#else
122170754Sdelphij  s = strerror (errnum);
123170754Sdelphij#endif
124170754Sdelphij
125170754Sdelphij#if !_LIBC
126170754Sdelphij  if (! s)
127170754Sdelphij    s = _("Unknown system error");
128170754Sdelphij#endif
129170754Sdelphij
130170754Sdelphij#if _LIBC
131170754Sdelphij  if (_IO_fwide (stderr, 0) > 0)
132170754Sdelphij    {
133170754Sdelphij      __fwprintf (stderr, L": %s", s);
134170754Sdelphij      return;
135170754Sdelphij    }
136170754Sdelphij#endif
137170754Sdelphij
138170754Sdelphij  fprintf (stderr, ": %s", s);
139170754Sdelphij}
140170754Sdelphij
141170754Sdelphijstatic void
142170754Sdelphijerror_tail (int status, int errnum, const char *message, va_list args)
143170754Sdelphij{
144170754Sdelphij#if _LIBC
145170754Sdelphij  if (_IO_fwide (stderr, 0) > 0)
146170754Sdelphij    {
147170754Sdelphij# define ALLOCA_LIMIT 2000
148170754Sdelphij      size_t len = strlen (message) + 1;
149170754Sdelphij      const wchar_t *wmessage = L"out of memory";
150170754Sdelphij      wchar_t *wbuf = (len < ALLOCA_LIMIT
151170754Sdelphij		       ? alloca (len * sizeof *wbuf)
152170754Sdelphij		       : len <= SIZE_MAX / sizeof *wbuf
153170754Sdelphij		       ? malloc (len * sizeof *wbuf)
154170754Sdelphij		       : NULL);
155170754Sdelphij
156170754Sdelphij      if (wbuf)
157170754Sdelphij	{
158170754Sdelphij	  size_t res;
159170754Sdelphij	  mbstate_t st;
160170754Sdelphij	  const char *tmp = message;
161170754Sdelphij	  memset (&st, '\0', sizeof (st));
162170754Sdelphij	  res = mbsrtowcs (wbuf, &tmp, len, &st);
163170754Sdelphij	  wmessage = res == (size_t) -1 ? L"???" : wbuf;
164170754Sdelphij	}
165170754Sdelphij
166170754Sdelphij      __vfwprintf (stderr, wmessage, args);
167170754Sdelphij      if (! (len < ALLOCA_LIMIT))
168170754Sdelphij	free (wbuf);
169170754Sdelphij    }
170170754Sdelphij  else
171170754Sdelphij#endif
172170754Sdelphij    vfprintf (stderr, message, args);
173170754Sdelphij  va_end (args);
174170754Sdelphij
175170754Sdelphij  ++error_message_count;
176170754Sdelphij  if (errnum)
177170754Sdelphij    print_errno_message (errnum);
178170754Sdelphij#if _LIBC
179170754Sdelphij  if (_IO_fwide (stderr, 0) > 0)
180170754Sdelphij    putwc (L'\n', stderr);
181170754Sdelphij  else
182170754Sdelphij#endif
183170754Sdelphij    putc ('\n', stderr);
184170754Sdelphij  fflush (stderr);
185170754Sdelphij  if (status)
186170754Sdelphij    exit (status);
187170754Sdelphij}
188170754Sdelphij
189170754Sdelphij
190170754Sdelphij/* Print the program name and error message MESSAGE, which is a printf-style
191170754Sdelphij   format string with optional args.
192170754Sdelphij   If ERRNUM is nonzero, print its corresponding system error message.
193170754Sdelphij   Exit with status STATUS if it is nonzero.  */
194170754Sdelphijvoid
195170754Sdelphijerror (int status, int errnum, const char *message, ...)
196170754Sdelphij{
197170754Sdelphij  va_list args;
198170754Sdelphij
199170754Sdelphij#if defined _LIBC && defined __libc_ptf_call
200170754Sdelphij  /* We do not want this call to be cut short by a thread
201170754Sdelphij     cancellation.  Therefore disable cancellation for now.  */
202170754Sdelphij  int state = PTHREAD_CANCEL_ENABLE;
203170754Sdelphij  __libc_ptf_call (pthread_setcancelstate, (PTHREAD_CANCEL_DISABLE, &state),
204170754Sdelphij		   0);
205170754Sdelphij#endif
206170754Sdelphij
207170754Sdelphij  fflush (stdout);
208170754Sdelphij#ifdef _LIBC
209170754Sdelphij  _IO_flockfile (stderr);
210170754Sdelphij#endif
211170754Sdelphij  if (error_print_progname)
212170754Sdelphij    (*error_print_progname) ();
213170754Sdelphij  else
214170754Sdelphij    {
215170754Sdelphij#if _LIBC
216170754Sdelphij      if (_IO_fwide (stderr, 0) > 0)
217170754Sdelphij	__fwprintf (stderr, L"%s: ", program_name);
218170754Sdelphij      else
219170754Sdelphij#endif
220170754Sdelphij	fprintf (stderr, "%s: ", program_name);
221170754Sdelphij    }
222170754Sdelphij
223170754Sdelphij  va_start (args, message);
224170754Sdelphij  error_tail (status, errnum, message, args);
225170754Sdelphij
226170754Sdelphij#ifdef _LIBC
227170754Sdelphij  _IO_funlockfile (stderr);
228170754Sdelphij# ifdef __libc_ptf_call
229170754Sdelphij  __libc_ptf_call (pthread_setcancelstate, (state, NULL), 0);
230170754Sdelphij# endif
231170754Sdelphij#endif
232170754Sdelphij}
233170754Sdelphij
234170754Sdelphij/* Sometimes we want to have at most one error per line.  This
235170754Sdelphij   variable controls whether this mode is selected or not.  */
236170754Sdelphijint error_one_per_line;
237170754Sdelphij
238170754Sdelphijvoid
239170754Sdelphijerror_at_line (int status, int errnum, const char *file_name,
240170754Sdelphij	       unsigned int line_number, const char *message, ...)
241170754Sdelphij{
242170754Sdelphij  va_list args;
243170754Sdelphij
244170754Sdelphij  if (error_one_per_line)
245170754Sdelphij    {
246170754Sdelphij      static const char *old_file_name;
247170754Sdelphij      static unsigned int old_line_number;
248170754Sdelphij
249170754Sdelphij      if (old_line_number == line_number
250170754Sdelphij	  && (file_name == old_file_name
251170754Sdelphij	      || strcmp (old_file_name, file_name) == 0))
252170754Sdelphij	/* Simply return and print nothing.  */
253170754Sdelphij	return;
254170754Sdelphij
255170754Sdelphij      old_file_name = file_name;
256170754Sdelphij      old_line_number = line_number;
257170754Sdelphij    }
258170754Sdelphij
259170754Sdelphij#if defined _LIBC && defined __libc_ptf_call
260170754Sdelphij  /* We do not want this call to be cut short by a thread
261170754Sdelphij     cancellation.  Therefore disable cancellation for now.  */
262170754Sdelphij  int state = PTHREAD_CANCEL_ENABLE;
263170754Sdelphij  __libc_ptf_call (pthread_setcancelstate, (PTHREAD_CANCEL_DISABLE, &state),
264170754Sdelphij		   0);
265170754Sdelphij#endif
266170754Sdelphij
267170754Sdelphij  fflush (stdout);
268170754Sdelphij#ifdef _LIBC
269170754Sdelphij  _IO_flockfile (stderr);
270170754Sdelphij#endif
271170754Sdelphij  if (error_print_progname)
272170754Sdelphij    (*error_print_progname) ();
273170754Sdelphij  else
274170754Sdelphij    {
275170754Sdelphij#if _LIBC
276170754Sdelphij      if (_IO_fwide (stderr, 0) > 0)
277170754Sdelphij	__fwprintf (stderr, L"%s: ", program_name);
278170754Sdelphij      else
279170754Sdelphij#endif
280170754Sdelphij	fprintf (stderr, "%s:", program_name);
281170754Sdelphij    }
282170754Sdelphij
283170754Sdelphij  if (file_name != NULL)
284170754Sdelphij    {
285170754Sdelphij#if _LIBC
286170754Sdelphij      if (_IO_fwide (stderr, 0) > 0)
287170754Sdelphij	__fwprintf (stderr, L"%s:%d: ", file_name, line_number);
288170754Sdelphij      else
289170754Sdelphij#endif
290170754Sdelphij	fprintf (stderr, "%s:%d: ", file_name, line_number);
291170754Sdelphij    }
292170754Sdelphij
293170754Sdelphij  va_start (args, message);
294170754Sdelphij  error_tail (status, errnum, message, args);
295170754Sdelphij
296170754Sdelphij#ifdef _LIBC
297170754Sdelphij  _IO_funlockfile (stderr);
298170754Sdelphij# ifdef __libc_ptf_call
299170754Sdelphij  __libc_ptf_call (pthread_setcancelstate, (state, NULL), 0);
300170754Sdelphij# endif
301170754Sdelphij#endif
302170754Sdelphij}
303170754Sdelphij
304170754Sdelphij#ifdef _LIBC
305170754Sdelphij/* Make the weak alias.  */
306170754Sdelphij# undef error
307170754Sdelphij# undef error_at_line
308170754Sdelphijweak_alias (__error, error)
309170754Sdelphijweak_alias (__error_at_line, error_at_line)
310170754Sdelphij#endif
311