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. */ 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 <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. */ 69 extern void __error (int status, int errnum, const char *message, ...) 70 __attribute__ ((__format__ (__printf__, 3, 4))); 71 extern 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 91 char *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. */ 100 extern 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 107 static void 108 print_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 138 static void 139 error_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. */ 191 void 192 error (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. */ 233 int error_one_per_line; 234 235 void 236 error_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 305 weak_alias (__error, error) 306 weak_alias (__error_at_line, error_at_line) 307 #endif 308