1 /* Error handler for noninteractive utilities
   2    Copyright (C) 1990-1998, 2000-2007 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 # define _(msgid) gettext (msgid)
  35 #endif
  36 
  37 #ifdef _LIBC
  38 # include <libintl.h>
  39 # include <stdbool.h>
  40 # include <stdint.h>
  41 # include <wchar.h>
  42 # define mbsrtowcs __mbsrtowcs
  43 #endif
  44 
  45 #if USE_UNLOCKED_IO
  46 # include "unlocked-io.h"
  47 #endif
  48 
  49 #ifndef _
  50 # define _(String) String
  51 #endif
  52 
  53 /* If NULL, error will flush stdout, then print on stderr the program
  54    name, a colon and a space.  Otherwise, error will call this
  55    function without parameters instead.  */
  56 void (*error_print_progname) (void);
  57 
  58 /* This variable is incremented each time `error' is called.  */
  59 unsigned int error_message_count;
  60 
  61 #ifdef _LIBC
  62 /* In the GNU C library, there is a predefined variable for this.  */
  63 
  64 # define program_name program_invocation_name
  65 # include <errno.h>
  66 # include <limits.h>
  67 # include <libio/libioP.h>
  68 
  69 /* In GNU libc we want do not want to use the common name `error' directly.
  70    Instead make it a weak alias.  */
  71 extern void __error (int status, int errnum, const char *message, ...)
  72      __attribute__ ((__format__ (__printf__, 3, 4)));
  73 extern void __error_at_line (int status, int errnum, const char *file_name,
  74                              unsigned int line_number, const char *message,
  75                              ...)
  76      __attribute__ ((__format__ (__printf__, 5, 6)));;
  77 # define error __error
  78 # define error_at_line __error_at_line
  79 
  80 # include <libio/iolibio.h>
  81 # define fflush(s) INTUSE(_IO_fflush) (s)
  82 # undef putc
  83 # define putc(c, fp) INTUSE(_IO_putc) (c, fp)
  84 
  85 # include <bits/libc-lock.h>
  86 
  87 #else /* not _LIBC */
  88 
  89 # if !HAVE_DECL_STRERROR_R && STRERROR_R_CHAR_P
  90 #  ifndef HAVE_DECL_STRERROR_R
  91 "this configure-time declaration test was not run"
  92 #  endif
  93 char *strerror_r ();
  94 # endif
  95 
  96 /* The calling program should define program_name and set it to the
  97    name of the executing program.  */
  98 extern char *program_name;
  99 
 100 # if HAVE_STRERROR_R || defined strerror_r
 101 #  define __strerror_r strerror_r
 102 # endif /* HAVE_STRERROR_R || defined strerror_r */
 103 #endif  /* not _LIBC */
 104 
 105 static void
 106 print_errno_message (int errnum)
 107 {
 108   char const *s;
 109 
 110 #if defined HAVE_STRERROR_R || _LIBC
 111   char errbuf[1024];
 112 # if STRERROR_R_CHAR_P || _LIBC
 113   s = __strerror_r (errnum, errbuf, sizeof errbuf);
 114 # else
 115   if (__strerror_r (errnum, errbuf, sizeof errbuf) == 0)
 116     s = errbuf;
 117   else
 118     s = 0;
 119 # endif
 120 #else
 121   s = strerror (errnum);
 122 #endif
 123 
 124 #if !_LIBC
 125   if (! s)
 126     s = _("Unknown system error");
 127 #endif
 128 
 129 #if _LIBC
 130   __fxprintf (NULL, ": %s", s);
 131 #else
 132   fprintf (stderr, ": %s", s);
 133 #endif
 134 }
 135 
 136 static void
 137 error_tail (int status, int errnum, const char *message, va_list args)
 138 {
 139 #if _LIBC
 140   if (_IO_fwide (stderr, 0) > 0)
 141     {
 142 # define ALLOCA_LIMIT 2000
 143       size_t len = strlen (message) + 1;
 144       wchar_t *wmessage = NULL;
 145       mbstate_t st;
 146       size_t res;
 147       const char *tmp;
 148       bool use_malloc = false;
 149 
 150       while (1)
 151         {
 152           if (__libc_use_alloca (len * sizeof (wchar_t)))
 153             wmessage = (wchar_t *) alloca (len * sizeof (wchar_t));
 154           else
 155             {
 156               if (!use_malloc)
 157                 wmessage = NULL;
 158 
 159               wchar_t *p = (wchar_t *) realloc (wmessage,
 160                                                 len * sizeof (wchar_t));
 161               if (p == NULL)
 162                 {
 163                   free (wmessage);
 164                   fputws_unlocked (L"out of memory\n", stderr);
 165                   return;
 166                 }
 167               wmessage = p;
 168               use_malloc = true;
 169             }
 170 
 171           memset (&st, '\0', sizeof (st));
 172           tmp = message;
 173 
 174           res = mbsrtowcs (wmessage, &tmp, len, &st);
 175           if (res != len)
 176             break;
 177 
 178           if (__builtin_expect (len >= SIZE_MAX / 2, 0))
 179             {
 180               /* This really should not happen if everything is fine.  */
 181               res = (size_t) -1;
 182               break;
 183             }
 184 
 185           len *= 2;
 186         }
 187 
 188       if (res == (size_t) -1)
 189         {
 190           /* The string cannot be converted.  */
 191           if (use_malloc)
 192             {
 193               free (wmessage);
 194               use_malloc = false;
 195             }
 196           wmessage = (wchar_t *) L"???";
 197         }
 198 
 199       __vfwprintf (stderr, wmessage, args);
 200 
 201       if (use_malloc)
 202         free (wmessage);
 203     }
 204   else
 205 #endif
 206     vfprintf (stderr, message, args);
 207   va_end (args);
 208 
 209   ++error_message_count;
 210   if (errnum)
 211     print_errno_message (errnum);
 212 #if _LIBC
 213   __fxprintf (NULL, "\n");
 214 #else
 215   putc ('\n', stderr);
 216 #endif
 217   fflush (stderr);
 218   if (status)
 219     exit (status);
 220 }
 221 
 222 
 223 /* Print the program name and error message MESSAGE, which is a printf-style
 224    format string with optional args.
 225    If ERRNUM is nonzero, print its corresponding system error message.
 226    Exit with status STATUS if it is nonzero.  */
 227 void
 228 error (int status, int errnum, const char *message, ...)
 229 {
 230   va_list args;
 231 
 232 #if defined _LIBC && defined __libc_ptf_call
 233   /* We do not want this call to be cut short by a thread
 234      cancellation.  Therefore disable cancellation for now.  */
 235   int state = PTHREAD_CANCEL_ENABLE;
 236   __libc_ptf_call (pthread_setcancelstate, (PTHREAD_CANCEL_DISABLE, &state),
 237                    0);
 238 #endif
 239 
 240   fflush (stdout);
 241 #ifdef _LIBC
 242   _IO_flockfile (stderr);
 243 #endif
 244   if (error_print_progname)
 245     (*error_print_progname) ();
 246   else
 247     {
 248 #if _LIBC
 249       __fxprintf (NULL, "%s: ", program_name);
 250 #else
 251       fprintf (stderr, "%s: ", program_name);
 252 #endif
 253     }
 254 
 255   va_start (args, message);
 256   error_tail (status, errnum, message, args);
 257 
 258 #ifdef _LIBC
 259   _IO_funlockfile (stderr);
 260 # ifdef __libc_ptf_call
 261   __libc_ptf_call (pthread_setcancelstate, (state, NULL), 0);
 262 # endif
 263 #endif
 264 }
 265 
 266 /* Sometimes we want to have at most one error per line.  This
 267    variable controls whether this mode is selected or not.  */
 268 int error_one_per_line;
 269 
 270 void
 271 error_at_line (int status, int errnum, const char *file_name,
 272                unsigned int line_number, const char *message, ...)
 273 {
 274   va_list args;
 275 
 276   if (error_one_per_line)
 277     {
 278       static const char *old_file_name;
 279       static unsigned int old_line_number;
 280 
 281       if (old_line_number == line_number
 282           && (file_name == old_file_name
 283               || strcmp (old_file_name, file_name) == 0))
 284         /* Simply return and print nothing.  */
 285         return;
 286 
 287       old_file_name = file_name;
 288       old_line_number = line_number;
 289     }
 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   fflush (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 #if _LIBC
 315   __fxprintf (NULL, file_name != NULL ? "%s:%d: " : " ",
 316               file_name, line_number);
 317 #else
 318   fprintf (stderr, file_name != NULL ? "%s:%d: " : " ",
 319            file_name, line_number);
 320 #endif
 321 
 322   va_start (args, message);
 323   error_tail (status, errnum, message, args);
 324 
 325 #ifdef _LIBC
 326   _IO_funlockfile (stderr);
 327 # ifdef __libc_ptf_call
 328   __libc_ptf_call (pthread_setcancelstate, (state, NULL), 0);
 329 # endif
 330 #endif
 331 }
 332 
 333 #ifdef _LIBC
 334 /* Make the weak alias.  */
 335 # undef error
 336 # undef error_at_line
 337 weak_alias (__error, error)
 338 weak_alias (__error_at_line, error_at_line)
 339 #endif