• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src-rt-6.x.4708/router/libiconv-1.14/srclib/
1/* Error handler for noninteractive utilities
2   Copyright (C) 1990-1998, 2000-2007, 2009-2011 Free Software Foundation, Inc.
3   This file is part of the GNU C Library.
4
5   This program is free software: you can redistribute it and/or modify
6   it under the terms of the GNU General Public License as published by
7   the Free Software Foundation; either version 3 of the License, or
8   (at your option) any later version.
9
10   This program 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
13   GNU General Public License for more details.
14
15   You should have received a copy of the GNU General Public License
16   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
17
18/* Written by David MacKenzie <djm@gnu.ai.mit.edu>.  */
19
20#if !_LIBC
21# include <config.h>
22#endif
23
24#include "error.h"
25
26#include <stdarg.h>
27#include <stdio.h>
28#include <stdlib.h>
29#include <string.h>
30
31#if !_LIBC && ENABLE_NLS
32# include "gettext.h"
33# define _(msgid) gettext (msgid)
34#endif
35
36#ifdef _LIBC
37# include <libintl.h>
38# include <stdbool.h>
39# include <stdint.h>
40# include <wchar.h>
41# define mbsrtowcs __mbsrtowcs
42#endif
43
44#if USE_UNLOCKED_IO
45# include "unlocked-io.h"
46#endif
47
48#ifndef _
49# define _(String) String
50#endif
51
52/* If NULL, error will flush stdout, then print on stderr the program
53   name, a colon and a space.  Otherwise, error will call this
54   function without parameters instead.  */
55void (*error_print_progname) (void);
56
57/* This variable is incremented each time `error' is called.  */
58unsigned int error_message_count;
59
60#ifdef _LIBC
61/* In the GNU C library, there is a predefined variable for this.  */
62
63# define program_name program_invocation_name
64# include <errno.h>
65# include <limits.h>
66# include <libio/libioP.h>
67
68/* In GNU libc we want do not want to use the common name `error' directly.
69   Instead make it a weak alias.  */
70extern void __error (int status, int errnum, const char *message, ...)
71     __attribute__ ((__format__ (__printf__, 3, 4)));
72extern void __error_at_line (int status, int errnum, const char *file_name,
73                             unsigned int line_number, const char *message,
74                             ...)
75     __attribute__ ((__format__ (__printf__, 5, 6)));;
76# define error __error
77# define error_at_line __error_at_line
78
79# include <libio/iolibio.h>
80# define fflush(s) INTUSE(_IO_fflush) (s)
81# undef putc
82# define putc(c, fp) INTUSE(_IO_putc) (c, fp)
83
84# include <bits/libc-lock.h>
85
86#else /* not _LIBC */
87
88# include <fcntl.h>
89# include <unistd.h>
90
91# if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
92/* Get declarations of the Win32 API functions.  */
93#  define WIN32_LEAN_AND_MEAN
94#  include <windows.h>
95# endif
96
97/* The gnulib override of fcntl is not needed in this file.  */
98# undef fcntl
99
100# if !HAVE_DECL_STRERROR_R
101#  ifndef HAVE_DECL_STRERROR_R
102"this configure-time declaration test was not run"
103#  endif
104#  if STRERROR_R_CHAR_P
105char *strerror_r ();
106#  else
107int strerror_r ();
108#  endif
109# endif
110
111/* The calling program should define program_name and set it to the
112   name of the executing program.  */
113extern char *program_name;
114
115# if HAVE_STRERROR_R || defined strerror_r
116#  define __strerror_r strerror_r
117# endif /* HAVE_STRERROR_R || defined strerror_r */
118#endif  /* not _LIBC */
119
120#if !_LIBC
121/* Return non-zero if FD is open.  */
122static inline int
123is_open (int fd)
124{
125# if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
126  /* On Win32: The initial state of unassigned standard file descriptors is
127     that they are open but point to an INVALID_HANDLE_VALUE.  There is no
128     fcntl, and the gnulib replacement fcntl does not support F_GETFL.  */
129  return (HANDLE) _get_osfhandle (fd) != INVALID_HANDLE_VALUE;
130# else
131#  ifndef F_GETFL
132#   error Please port fcntl to your platform
133#  endif
134  return 0 <= fcntl (fd, F_GETFL);
135# endif
136}
137#endif
138
139static inline void
140flush_stdout (void)
141{
142#if !_LIBC
143  int stdout_fd;
144
145# if GNULIB_FREOPEN_SAFER
146  /* Use of gnulib's freopen-safer module normally ensures that
147       fileno (stdout) == 1
148     whenever stdout is open.  */
149  stdout_fd = STDOUT_FILENO;
150# else
151  /* POSIX states that fileno (stdout) after fclose is unspecified.  But in
152     practice it is not a problem, because stdout is statically allocated and
153     the fd of a FILE stream is stored as a field in its allocated memory.  */
154  stdout_fd = fileno (stdout);
155# endif
156  /* POSIX states that fflush (stdout) after fclose is unspecified; it
157     is safe in glibc, but not on all other platforms.  fflush (NULL)
158     is always defined, but too draconian.  */
159  if (0 <= stdout_fd && is_open (stdout_fd))
160#endif
161    fflush (stdout);
162}
163
164static void
165print_errno_message (int errnum)
166{
167  char const *s;
168
169#if defined HAVE_STRERROR_R || _LIBC
170  char errbuf[1024];
171# if STRERROR_R_CHAR_P || _LIBC
172  s = __strerror_r (errnum, errbuf, sizeof errbuf);
173# else
174  if (__strerror_r (errnum, errbuf, sizeof errbuf) == 0)
175    s = errbuf;
176  else
177    s = 0;
178# endif
179#else
180  s = strerror (errnum);
181#endif
182
183#if !_LIBC
184  if (! s)
185    s = _("Unknown system error");
186#endif
187
188#if _LIBC
189  __fxprintf (NULL, ": %s", s);
190#else
191  fprintf (stderr, ": %s", s);
192#endif
193}
194
195static void
196error_tail (int status, int errnum, const char *message, va_list args)
197{
198#if _LIBC
199  if (_IO_fwide (stderr, 0) > 0)
200    {
201# define ALLOCA_LIMIT 2000
202      size_t len = strlen (message) + 1;
203      wchar_t *wmessage = NULL;
204      mbstate_t st;
205      size_t res;
206      const char *tmp;
207      bool use_malloc = false;
208
209      while (1)
210        {
211          if (__libc_use_alloca (len * sizeof (wchar_t)))
212            wmessage = (wchar_t *) alloca (len * sizeof (wchar_t));
213          else
214            {
215              if (!use_malloc)
216                wmessage = NULL;
217
218              wchar_t *p = (wchar_t *) realloc (wmessage,
219                                                len * sizeof (wchar_t));
220              if (p == NULL)
221                {
222                  free (wmessage);
223                  fputws_unlocked (L"out of memory\n", stderr);
224                  return;
225                }
226              wmessage = p;
227              use_malloc = true;
228            }
229
230          memset (&st, '\0', sizeof (st));
231          tmp = message;
232
233          res = mbsrtowcs (wmessage, &tmp, len, &st);
234          if (res != len)
235            break;
236
237          if (__builtin_expect (len >= SIZE_MAX / 2, 0))
238            {
239              /* This really should not happen if everything is fine.  */
240              res = (size_t) -1;
241              break;
242            }
243
244          len *= 2;
245        }
246
247      if (res == (size_t) -1)
248        {
249          /* The string cannot be converted.  */
250          if (use_malloc)
251            {
252              free (wmessage);
253              use_malloc = false;
254            }
255          wmessage = (wchar_t *) L"???";
256        }
257
258      __vfwprintf (stderr, wmessage, args);
259
260      if (use_malloc)
261        free (wmessage);
262    }
263  else
264#endif
265    vfprintf (stderr, message, args);
266  va_end (args);
267
268  ++error_message_count;
269  if (errnum)
270    print_errno_message (errnum);
271#if _LIBC
272  __fxprintf (NULL, "\n");
273#else
274  putc ('\n', stderr);
275#endif
276  fflush (stderr);
277  if (status)
278    exit (status);
279}
280
281
282/* Print the program name and error message MESSAGE, which is a printf-style
283   format string with optional args.
284   If ERRNUM is nonzero, print its corresponding system error message.
285   Exit with status STATUS if it is nonzero.  */
286void
287error (int status, int errnum, const char *message, ...)
288{
289  va_list args;
290
291#if defined _LIBC && defined __libc_ptf_call
292  /* We do not want this call to be cut short by a thread
293     cancellation.  Therefore disable cancellation for now.  */
294  int state = PTHREAD_CANCEL_ENABLE;
295  __libc_ptf_call (pthread_setcancelstate, (PTHREAD_CANCEL_DISABLE, &state),
296                   0);
297#endif
298
299  flush_stdout ();
300#ifdef _LIBC
301  _IO_flockfile (stderr);
302#endif
303  if (error_print_progname)
304    (*error_print_progname) ();
305  else
306    {
307#if _LIBC
308      __fxprintf (NULL, "%s: ", program_name);
309#else
310      fprintf (stderr, "%s: ", program_name);
311#endif
312    }
313
314  va_start (args, message);
315  error_tail (status, errnum, message, args);
316
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
323}
324
325/* Sometimes we want to have at most one error per line.  This
326   variable controls whether this mode is selected or not.  */
327int error_one_per_line;
328
329void
330error_at_line (int status, int errnum, const char *file_name,
331               unsigned int line_number, const char *message, ...)
332{
333  va_list args;
334
335  if (error_one_per_line)
336    {
337      static const char *old_file_name;
338      static unsigned int old_line_number;
339
340      if (old_line_number == line_number
341          && (file_name == old_file_name
342              || strcmp (old_file_name, file_name) == 0))
343        /* Simply return and print nothing.  */
344        return;
345
346      old_file_name = file_name;
347      old_line_number = line_number;
348    }
349
350#if defined _LIBC && defined __libc_ptf_call
351  /* We do not want this call to be cut short by a thread
352     cancellation.  Therefore disable cancellation for now.  */
353  int state = PTHREAD_CANCEL_ENABLE;
354  __libc_ptf_call (pthread_setcancelstate, (PTHREAD_CANCEL_DISABLE, &state),
355                   0);
356#endif
357
358  flush_stdout ();
359#ifdef _LIBC
360  _IO_flockfile (stderr);
361#endif
362  if (error_print_progname)
363    (*error_print_progname) ();
364  else
365    {
366#if _LIBC
367      __fxprintf (NULL, "%s:", program_name);
368#else
369      fprintf (stderr, "%s:", program_name);
370#endif
371    }
372
373#if _LIBC
374  __fxprintf (NULL, file_name != NULL ? "%s:%d: " : " ",
375              file_name, line_number);
376#else
377  fprintf (stderr, file_name != NULL ? "%s:%d: " : " ",
378           file_name, line_number);
379#endif
380
381  va_start (args, message);
382  error_tail (status, errnum, message, args);
383
384#ifdef _LIBC
385  _IO_funlockfile (stderr);
386# ifdef __libc_ptf_call
387  __libc_ptf_call (pthread_setcancelstate, (state, NULL), 0);
388# endif
389#endif
390}
391
392#ifdef _LIBC
393/* Make the weak alias.  */
394# undef error
395# undef error_at_line
396weak_alias (__error, error)
397weak_alias (__error_at_line, error_at_line)
398#endif
399