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