~ubuntu-branches/ubuntu/saucy/numdiff/saucy

« back to all changes in this revision

Viewing changes to error.c

  • Committer: Package Import Robot
  • Author(s): Paolo Greppi
  • Date: 2011-11-28 19:45:34 UTC
  • Revision ID: package-import@ubuntu.com-20111128194534-wp8a412l2rdf5s1u
Tags: upstream-5.2.1
ImportĀ upstreamĀ versionĀ 5.2.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* Error handler for noninteractive utilities
 
2
   Copyright (C) 1990-1998, 2000-2005, 2006 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 2, or (at your option)
 
8
   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 along
 
16
   with this program; if not, write to the Free Software Foundation,
 
17
   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
 
18
 
 
19
/* Written by David MacKenzie <djm@gnu.ai.mit.edu>.  */
 
20
 
 
21
#if !_LIBC
 
22
# include <config.h>
 
23
#endif
 
24
 
 
25
#include "error.h"
 
26
 
 
27
#include <stdarg.h>
 
28
#include <stdio.h>
 
29
#include <stdlib.h>
 
30
#include <string.h>
 
31
 
 
32
#if !_LIBC && ENABLE_NLS
 
33
# include "gettext.h"
 
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.  */
 
55
void (*error_print_progname) (void);
 
56
 
 
57
/* This variable is incremented each time `error' is called.  */
 
58
unsigned 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.  */
 
70
extern void __error (int status, int errnum, const char *message, ...)
 
71
     __attribute__ ((__format__ (__printf__, 3, 4)));
 
72
extern 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
# if !HAVE_DECL_STRERROR_R && STRERROR_R_CHAR_P
 
89
#  ifndef HAVE_DECL_STRERROR_R
 
90
"this configure-time declaration test was not run"
 
91
#  endif
 
92
char *strerror_r ();
 
93
# endif
 
94
 
 
95
/* The calling program should define program_name and set it to the
 
96
   name of the executing program.  */
 
97
extern char *program_name;
 
98
 
 
99
# if HAVE_STRERROR_R || defined strerror_r
 
100
#  define __strerror_r strerror_r
 
101
# endif /* HAVE_STRERROR_R || defined strerror_r */
 
102
#endif  /* not _LIBC */
 
103
 
 
104
static void
 
105
print_errno_message (int errnum)
 
106
{
 
107
  char const *s;
 
108
 
 
109
#if defined HAVE_STRERROR_R || _LIBC
 
110
  char errbuf[1024];
 
111
# if STRERROR_R_CHAR_P || _LIBC
 
112
  s = __strerror_r (errnum, errbuf, sizeof errbuf);
 
113
# else
 
114
  if (__strerror_r (errnum, errbuf, sizeof errbuf) == 0)
 
115
    s = errbuf;
 
116
  else
 
117
    s = 0;
 
118
# endif
 
119
#else
 
120
  s = strerror (errnum);
 
121
#endif
 
122
 
 
123
#if !_LIBC
 
124
  if (! s)
 
125
    s = _("Unknown system error");
 
126
#endif
 
127
 
 
128
#if _LIBC
 
129
  __fxprintf (NULL, ": %s", s);
 
130
#else
 
131
  fprintf (stderr, ": %s", s);
 
132
#endif
 
133
}
 
134
 
 
135
static void
 
136
error_tail (int status, int errnum, const char *message, va_list args)
 
137
{
 
138
#if _LIBC
 
139
  if (_IO_fwide (stderr, 0) > 0)
 
140
    {
 
141
# define ALLOCA_LIMIT 2000
 
142
      size_t len = strlen (message) + 1;
 
143
      wchar_t *wmessage = NULL;
 
144
      mbstate_t st;
 
145
      size_t res;
 
146
      const char *tmp;
 
147
      bool use_malloc = false;
 
148
 
 
149
      while (1)
 
150
        {
 
151
          if (__libc_use_alloca (len * sizeof (wchar_t)))
 
152
            wmessage = (wchar_t *) alloca (len * sizeof (wchar_t));
 
153
          else
 
154
            {
 
155
              if (!use_malloc)
 
156
                wmessage = NULL;
 
157
 
 
158
              wchar_t *p = (wchar_t *) realloc (wmessage,
 
159
                                                len * sizeof (wchar_t));
 
160
              if (p == NULL)
 
161
                {
 
162
                  free (wmessage);
 
163
                  fputws_unlocked (L"out of memory\n", stderr);
 
164
                  return;
 
165
                }
 
166
              wmessage = p;
 
167
              use_malloc = true;
 
168
            }
 
169
 
 
170
          memset (&st, '\0', sizeof (st));
 
171
          tmp = message;
 
172
 
 
173
          res = mbsrtowcs (wmessage, &tmp, len, &st);
 
174
          if (res != len)
 
175
            break;
 
176
 
 
177
          if (__builtin_expect (len >= SIZE_MAX / 2, 0))
 
178
            {
 
179
              /* This really should not happen if everything is fine.  */
 
180
              res = (size_t) -1;
 
181
              break;
 
182
            }
 
183
 
 
184
          len *= 2;
 
185
        }
 
186
 
 
187
      if (res == (size_t) -1)
 
188
        {
 
189
          /* The string cannot be converted.  */
 
190
          if (use_malloc)
 
191
            {
 
192
              free (wmessage);
 
193
              use_malloc = false;
 
194
            }
 
195
          wmessage = (wchar_t *) L"???";
 
196
        }
 
197
 
 
198
      __vfwprintf (stderr, wmessage, args);
 
199
 
 
200
      if (use_malloc)
 
201
        free (wmessage);
 
202
    }
 
203
  else
 
204
#endif
 
205
    vfprintf (stderr, message, args);
 
206
  va_end (args);
 
207
 
 
208
  ++error_message_count;
 
209
  if (errnum)
 
210
    print_errno_message (errnum);
 
211
#if _LIBC
 
212
  __fxprintf (NULL, "\n");
 
213
#else
 
214
  putc ('\n', stderr);
 
215
#endif
 
216
  fflush (stderr);
 
217
  if (status)
 
218
    exit (status);
 
219
}
 
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
void
 
227
error (int status, int errnum, const char *message, ...)
 
228
{
 
229
  va_list args;
 
230
 
 
231
#if defined _LIBC && defined __libc_ptf_call
 
232
  /* We do not want this call to be cut short by a thread
 
233
     cancellation.  Therefore disable cancellation for now.  */
 
234
  int state = PTHREAD_CANCEL_ENABLE;
 
235
  __libc_ptf_call (pthread_setcancelstate, (PTHREAD_CANCEL_DISABLE, &state),
 
236
                   0);
 
237
#endif
 
238
 
 
239
  fflush (stdout);
 
240
#ifdef _LIBC
 
241
  _IO_flockfile (stderr);
 
242
#endif
 
243
  if (error_print_progname)
 
244
    (*error_print_progname) ();
 
245
  else
 
246
    {
 
247
#if _LIBC
 
248
      __fxprintf (NULL, "%s: ", program_name);
 
249
#else
 
250
      fprintf (stderr, "%s: ", program_name);
 
251
#endif
 
252
    }
 
253
 
 
254
  va_start (args, message);
 
255
  error_tail (status, errnum, message, args);
 
256
 
 
257
#ifdef _LIBC
 
258
  _IO_funlockfile (stderr);
 
259
# ifdef __libc_ptf_call
 
260
  __libc_ptf_call (pthread_setcancelstate, (state, NULL), 0);
 
261
# endif
 
262
#endif
 
263
}
 
264
 
 
265
/* Sometimes we want to have at most one error per line.  This
 
266
   variable controls whether this mode is selected or not.  */
 
267
int error_one_per_line;
 
268
 
 
269
void
 
270
error_at_line (int status, int errnum, const char *file_name,
 
271
               unsigned int line_number, const char *message, ...)
 
272
{
 
273
  va_list args;
 
274
 
 
275
  if (error_one_per_line)
 
276
    {
 
277
      static const char *old_file_name;
 
278
      static unsigned int old_line_number;
 
279
 
 
280
      if (old_line_number == line_number
 
281
          && (file_name == old_file_name
 
282
              || strcmp (old_file_name, file_name) == 0))
 
283
        /* Simply return and print nothing.  */
 
284
        return;
 
285
 
 
286
      old_file_name = file_name;
 
287
      old_line_number = line_number;
 
288
    }
 
289
 
 
290
#if defined _LIBC && defined __libc_ptf_call
 
291
  /* We do not want this call to be cut short by a thread
 
292
     cancellation.  Therefore disable cancellation for now.  */
 
293
  int state = PTHREAD_CANCEL_ENABLE;
 
294
  __libc_ptf_call (pthread_setcancelstate, (PTHREAD_CANCEL_DISABLE, &state),
 
295
                   0);
 
296
#endif
 
297
 
 
298
  fflush (stdout);
 
299
#ifdef _LIBC
 
300
  _IO_flockfile (stderr);
 
301
#endif
 
302
  if (error_print_progname)
 
303
    (*error_print_progname) ();
 
304
  else
 
305
    {
 
306
#if _LIBC
 
307
      __fxprintf (NULL, "%s:", program_name);
 
308
#else
 
309
      fprintf (stderr, "%s:", program_name);
 
310
#endif
 
311
    }
 
312
 
 
313
#if _LIBC
 
314
  __fxprintf (NULL, file_name != NULL ? "%s:%d: " : " ",
 
315
              file_name, line_number);
 
316
#else
 
317
  fprintf (stderr, file_name != NULL ? "%s:%d: " : " ",
 
318
           file_name, line_number);
 
319
#endif
 
320
 
 
321
  va_start (args, message);
 
322
  error_tail (status, errnum, message, args);
 
323
 
 
324
#ifdef _LIBC
 
325
  _IO_funlockfile (stderr);
 
326
# ifdef __libc_ptf_call
 
327
  __libc_ptf_call (pthread_setcancelstate, (state, NULL), 0);
 
328
# endif
 
329
#endif
 
330
}
 
331
 
 
332
#ifdef _LIBC
 
333
/* Make the weak alias.  */
 
334
# undef error
 
335
# undef error_at_line
 
336
weak_alias (__error, error)
 
337
weak_alias (__error_at_line, error_at_line)
 
338
#endif