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