1/* Error handler for noninteractive utilities 2 Copyright (C) 1990-1998, 2000-2003, 2004 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#include <sys/cdefs.h> 19__RCSID("$NetBSD: error.c,v 1.2 2016/05/17 14:00:09 christos Exp $"); 20 21 22/* Written by David MacKenzie <djm@gnu.ai.mit.edu>. */ 23 24#ifdef HAVE_CONFIG_H 25# include <config.h> 26#endif 27 28#include "error.h" 29 30#include <stdarg.h> 31#include <stdio.h> 32#include <stdlib.h> 33#include <string.h> 34 35#if !_LIBC && ENABLE_NLS 36# include "gettext.h" 37#endif 38 39#ifdef _LIBC 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 <libio/libioP.h> 66 67/* In GNU libc we want do not want to use the common name `error' directly. 68 Instead make it a weak alias. */ 69extern void __error (int status, int errnum, const char *message, ...) 70 __attribute__ ((__format__ (__printf__, 3, 4))); 71extern void __error_at_line (int status, int errnum, const char *file_name, 72 unsigned int line_number, const char *message, 73 ...) 74 __attribute__ ((__format__ (__printf__, 5, 6)));; 75# define error __error 76# define error_at_line __error_at_line 77 78# include <libio/iolibio.h> 79# define fflush(s) INTUSE(_IO_fflush) (s) 80# undef putc 81# define putc(c, fp) INTUSE(_IO_putc) (c, fp) 82 83# include <bits/libc-lock.h> 84 85#else /* not _LIBC */ 86 87# if !HAVE_DECL_STRERROR_R && STRERROR_R_CHAR_P 88# ifndef HAVE_DECL_STRERROR_R 89"this configure-time declaration test was not run" 90# endif 91char *strerror_r (); 92# endif 93 94# ifndef SIZE_MAX 95# define SIZE_MAX ((size_t) -1) 96# endif 97 98/* The calling program should define program_name and set it to the 99 name of the executing program. */ 100extern char *program_name; 101 102# if HAVE_STRERROR_R || defined strerror_r 103# define __strerror_r strerror_r 104# endif 105#endif /* not _LIBC */ 106 107static void 108print_errno_message (int errnum) 109{ 110 char const *s = NULL; 111 112#if defined HAVE_STRERROR_R || _LIBC 113 char errbuf[1024]; 114# if STRERROR_R_CHAR_P || _LIBC 115 s = __strerror_r (errnum, errbuf, sizeof errbuf); 116# else 117 if (__strerror_r (errnum, errbuf, sizeof errbuf) == 0) 118 s = errbuf; 119# endif 120#endif 121 122#if !_LIBC 123 if (! s && ! (s = strerror (errnum))) 124 s = _("Unknown system error"); 125#endif 126 127#if _LIBC 128 if (_IO_fwide (stderr, 0) > 0) 129 { 130 __fwprintf (stderr, L": %s", s); 131 return; 132 } 133#endif 134 135 fprintf (stderr, ": %s", s); 136} 137 138static void 139error_tail (int status, int errnum, const char *message, va_list args) 140{ 141#if _LIBC 142 if (_IO_fwide (stderr, 0) > 0) 143 { 144# define ALLOCA_LIMIT 2000 145 size_t len = strlen (message) + 1; 146 const wchar_t *wmessage = L"out of memory"; 147 wchar_t *wbuf = (len < ALLOCA_LIMIT 148 ? alloca (len * sizeof *wbuf) 149 : len <= SIZE_MAX / sizeof *wbuf 150 ? malloc (len * sizeof *wbuf) 151 : NULL); 152 153 if (wbuf) 154 { 155 size_t res; 156 mbstate_t st; 157 const char *tmp = message; 158 memset (&st, '\0', sizeof (st)); 159 res = mbsrtowcs (wbuf, &tmp, len, &st); 160 wmessage = res == (size_t) -1 ? L"???" : wbuf; 161 } 162 163 __vfwprintf (stderr, wmessage, args); 164 if (! (len < ALLOCA_LIMIT)) 165 free (wbuf); 166 } 167 else 168#endif 169 vfprintf (stderr, message, args); 170 va_end (args); 171 172 ++error_message_count; 173 if (errnum) 174 print_errno_message (errnum); 175#if _LIBC 176 if (_IO_fwide (stderr, 0) > 0) 177 putwc (L'\n', stderr); 178 else 179#endif 180 putc ('\n', stderr); 181 fflush (stderr); 182 if (status) 183 exit (status); 184} 185 186 187/* Print the program name and error message MESSAGE, which is a printf-style 188 format string with optional args. 189 If ERRNUM is nonzero, print its corresponding system error message. 190 Exit with status STATUS if it is nonzero. */ 191void 192error (int status, int errnum, const char *message, ...) 193{ 194 va_list args; 195 196#if defined _LIBC && defined __libc_ptf_call 197 /* We do not want this call to be cut short by a thread 198 cancellation. Therefore disable cancellation for now. */ 199 int state = PTHREAD_CANCEL_ENABLE; 200 __libc_ptf_call (pthread_setcancelstate, (PTHREAD_CANCEL_DISABLE, &state), 201 0); 202#endif 203 204 fflush (stdout); 205#ifdef _LIBC 206 _IO_flockfile (stderr); 207#endif 208 if (error_print_progname) 209 (*error_print_progname) (); 210 else 211 { 212#if _LIBC 213 if (_IO_fwide (stderr, 0) > 0) 214 __fwprintf (stderr, L"%s: ", program_name); 215 else 216#endif 217 fprintf (stderr, "%s: ", program_name); 218 } 219 220 va_start (args, message); 221 error_tail (status, errnum, message, args); 222 223#ifdef _LIBC 224 _IO_funlockfile (stderr); 225# ifdef __libc_ptf_call 226 __libc_ptf_call (pthread_setcancelstate, (state, NULL), 0); 227# endif 228#endif 229} 230 231/* Sometimes we want to have at most one error per line. This 232 variable controls whether this mode is selected or not. */ 233int error_one_per_line; 234 235void 236error_at_line (int status, int errnum, const char *file_name, 237 unsigned int line_number, const char *message, ...) 238{ 239 va_list args; 240 241 if (error_one_per_line) 242 { 243 static const char *old_file_name; 244 static unsigned int old_line_number; 245 246 if (old_line_number == line_number 247 && (file_name == old_file_name 248 || strcmp (old_file_name, file_name) == 0)) 249 /* Simply return and print nothing. */ 250 return; 251 252 old_file_name = file_name; 253 old_line_number = line_number; 254 } 255 256#if defined _LIBC && defined __libc_ptf_call 257 /* We do not want this call to be cut short by a thread 258 cancellation. Therefore disable cancellation for now. */ 259 int state = PTHREAD_CANCEL_ENABLE; 260 __libc_ptf_call (pthread_setcancelstate, (PTHREAD_CANCEL_DISABLE, &state), 261 0); 262#endif 263 264 fflush (stdout); 265#ifdef _LIBC 266 _IO_flockfile (stderr); 267#endif 268 if (error_print_progname) 269 (*error_print_progname) (); 270 else 271 { 272#if _LIBC 273 if (_IO_fwide (stderr, 0) > 0) 274 __fwprintf (stderr, L"%s: ", program_name); 275 else 276#endif 277 fprintf (stderr, "%s:", program_name); 278 } 279 280 if (file_name != NULL) 281 { 282#if _LIBC 283 if (_IO_fwide (stderr, 0) > 0) 284 __fwprintf (stderr, L"%s:%d: ", file_name, line_number); 285 else 286#endif 287 fprintf (stderr, "%s:%d: ", file_name, line_number); 288 } 289 290 va_start (args, message); 291 error_tail (status, errnum, message, args); 292 293#ifdef _LIBC 294 _IO_funlockfile (stderr); 295# ifdef __libc_ptf_call 296 __libc_ptf_call (pthread_setcancelstate, (state, NULL), 0); 297# endif 298#endif 299} 300 301#ifdef _LIBC 302/* Make the weak alias. */ 303# undef error 304# undef error_at_line 305weak_alias (__error, error) 306weak_alias (__error_at_line, error_at_line) 307#endif 308