1 /* $NetBSD: error.c,v 1.1.1.1 2016/01/13 03:15:30 christos Exp $ */ 2 3 /* Error handler for noninteractive utilities 4 Copyright (C) 1990-1998, 2000, 2001 Free Software Foundation, Inc. 5 This file is part of the GNU C Library. Its master source is NOT part of 6 the C library, however. The master source lives in /gd/gnu/lib. 7 8 This program is free software; you can redistribute it and/or modify 9 it under the terms of the GNU General Public License as published by 10 the Free Software Foundation; either version 2, or (at your option) 11 any later version. 12 13 This program is distributed in the hope that it will be useful, 14 but WITHOUT ANY WARRANTY; without even the implied warranty of 15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 GNU General Public License for more details. 17 18 You should have received a copy of the GNU General Public License 19 along with this program; if not, write to the Free Software Foundation, 20 Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ 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 <stdio.h> 29 #if HAVE_LIBINTL_H 30 # include <libintl.h> 31 #endif 32 #ifdef _LIBC 33 # include <wchar.h> 34 # define mbsrtowcs __mbsrtowcs 35 #endif 36 37 #if HAVE_VPRINTF || HAVE_DOPRNT || _LIBC 38 # if __STDC__ 39 # include <stdarg.h> 40 # define VA_START(args, lastarg) va_start(args, lastarg) 41 # else 42 # include <varargs.h> 43 # define VA_START(args, lastarg) va_start(args) 44 # endif 45 #else 46 # define va_alist a1, a2, a3, a4, a5, a6, a7, a8 47 # define va_dcl char *a1, *a2, *a3, *a4, *a5, *a6, *a7, *a8; 48 #endif 49 50 #if STDC_HEADERS || _LIBC 51 # include <stdlib.h> 52 # include <string.h> 53 #else 54 void exit (); 55 #endif 56 57 #include "error.h" 58 #include "unlocked-io.h" 59 60 #ifndef _ 61 # define _(String) String 62 #endif 63 64 /* If NULL, error will flush stdout, then print on stderr the program 65 name, a colon and a space. Otherwise, error will call this 66 function without parameters instead. */ 67 void (*error_print_progname) ( 68 #if __STDC__ - 0 69 void 70 #endif 71 ); 72 73 /* This variable is incremented each time `error' is called. */ 74 unsigned int error_message_count; 75 76 #ifdef _LIBC 77 /* In the GNU C library, there is a predefined variable for this. */ 78 79 # define program_name program_invocation_name 80 # include <errno.h> 81 82 /* In GNU libc we want do not want to use the common name `error' directly. 83 Instead make it a weak alias. */ 84 extern void __error (int status, int errnum, const char *message, ...) 85 __attribute__ ((__format__ (__printf__, 3, 4))); 86 extern void __error_at_line (int status, int errnum, const char *file_name, 87 unsigned int line_number, const char *message, 88 ...) 89 __attribute__ ((__format__ (__printf__, 5, 6)));; 90 # define error __error 91 # define error_at_line __error_at_line 92 93 # ifdef USE_IN_LIBIO 94 # include <libio/iolibio.h> 95 # define fflush(s) _IO_fflush (s) 96 # endif 97 98 #else /* not _LIBC */ 99 100 # if !HAVE_DECL_STRERROR_R && STRERROR_R_CHAR_P 101 # ifndef HAVE_DECL_STRERROR_R 102 "this configure-time declaration test was not run" 103 # endif 104 char *strerror_r (); 105 # endif 106 107 /* The calling program should define program_name and set it to the 108 name of the executing program. */ 109 extern char *program_name; 110 111 # if HAVE_STRERROR_R || defined strerror_r 112 # define __strerror_r strerror_r 113 # else 114 # if HAVE_STRERROR 115 # ifndef HAVE_DECL_STRERROR 116 "this configure-time declaration test was not run" 117 # endif 118 # if !HAVE_DECL_STRERROR 119 char *strerror (); 120 # endif 121 # else 122 static char * 123 private_strerror (int errnum) 124 { 125 extern char *sys_errlist[]; 126 extern int sys_nerr; 127 128 if (errnum > 0 && errnum <= sys_nerr) 129 return _(sys_errlist[errnum]); 130 return _("Unknown system error"); 131 } 132 # define strerror private_strerror 133 # endif /* HAVE_STRERROR */ 134 # endif /* HAVE_STRERROR_R || defined strerror_r */ 135 #endif /* not _LIBC */ 136 137 static void 138 print_errno_message (int errnum) 139 { 140 char const *s; 141 142 #if defined HAVE_STRERROR_R || _LIBC 143 char errbuf[1024]; 144 # if STRERROR_R_CHAR_P || _LIBC 145 s = __strerror_r (errnum, errbuf, sizeof errbuf); 146 # else 147 if (__strerror_r (errnum, errbuf, sizeof errbuf) == 0) 148 s = errbuf; 149 else 150 s = 0; 151 # endif 152 #else 153 s = strerror (errnum); 154 #endif 155 156 #if !_LIBC 157 if (! s) 158 s = _("Unknown system error"); 159 #endif 160 161 #if _LIBC && USE_IN_LIBIO 162 if (_IO_fwide (stderr, 0) > 0) 163 { 164 __fwprintf (stderr, L": %s", s); 165 return; 166 } 167 #endif 168 169 fprintf (stderr, ": %s", s); 170 } 171 172 #ifdef VA_START 173 static void 174 error_tail (int status, int errnum, const char *message, va_list args) 175 { 176 # if HAVE_VPRINTF || _LIBC 177 # if _LIBC && USE_IN_LIBIO 178 if (_IO_fwide (stderr, 0) > 0) 179 { 180 # define ALLOCA_LIMIT 2000 181 size_t len = strlen (message) + 1; 182 wchar_t *wmessage = NULL; 183 mbstate_t st; 184 size_t res; 185 const char *tmp; 186 187 do 188 { 189 if (len < ALLOCA_LIMIT) 190 wmessage = (wchar_t *) alloca (len * sizeof (wchar_t)); 191 else 192 { 193 if (wmessage != NULL && len / 2 < ALLOCA_LIMIT) 194 wmessage = NULL; 195 196 wmessage = (wchar_t *) realloc (wmessage, 197 len * sizeof (wchar_t)); 198 199 if (wmessage == NULL) 200 { 201 fputws_unlocked (L"out of memory\n", stderr); 202 return; 203 } 204 } 205 206 memset (&st, '\0', sizeof (st)); 207 tmp =message; 208 } 209 while ((res = mbsrtowcs (wmessage, &tmp, len, &st)) == len); 210 211 if (res == (size_t) -1) 212 /* The string cannot be converted. */ 213 wmessage = (wchar_t *) L"???"; 214 215 __vfwprintf (stderr, wmessage, args); 216 } 217 else 218 # endif 219 vfprintf (stderr, message, args); 220 # else 221 _doprnt (message, args, stderr); 222 # endif 223 va_end (args); 224 225 ++error_message_count; 226 if (errnum) 227 print_errno_message (errnum); 228 # if _LIBC && USE_IN_LIBIO 229 if (_IO_fwide (stderr, 0) > 0) 230 putwc (L'\n', stderr); 231 else 232 # endif 233 putc ('\n', stderr); 234 fflush (stderr); 235 if (status) 236 exit (status); 237 } 238 #endif 239 240 241 /* Print the program name and error message MESSAGE, which is a printf-style 242 format string with optional args. 243 If ERRNUM is nonzero, print its corresponding system error message. 244 Exit with status STATUS if it is nonzero. */ 245 /* VARARGS */ 246 void 247 #if defined VA_START && __STDC__ 248 error (int status, int errnum, const char *message, ...) 249 #else 250 error (status, errnum, message, va_alist) 251 int status; 252 int errnum; 253 char *message; 254 va_dcl 255 #endif 256 { 257 #ifdef VA_START 258 va_list args; 259 #endif 260 261 fflush (stdout); 262 #ifdef _LIBC 263 # ifdef USE_IN_LIBIO 264 _IO_flockfile (stderr); 265 # else 266 __flockfile (stderr); 267 # endif 268 #endif 269 if (error_print_progname) 270 (*error_print_progname) (); 271 else 272 { 273 #if _LIBC && USE_IN_LIBIO 274 if (_IO_fwide (stderr, 0) > 0) 275 __fwprintf (stderr, L"%s: ", program_name); 276 else 277 #endif 278 fprintf (stderr, "%s: ", program_name); 279 } 280 281 #ifdef VA_START 282 VA_START (args, message); 283 error_tail (status, errnum, message, args); 284 #else 285 fprintf (stderr, message, a1, a2, a3, a4, a5, a6, a7, a8); 286 287 ++error_message_count; 288 if (errnum) 289 print_errno_message (errnum); 290 putc ('\n', stderr); 291 fflush (stderr); 292 if (status) 293 exit (status); 294 #endif 295 296 #ifdef _LIBC 297 # ifdef USE_IN_LIBIO 298 _IO_funlockfile (stderr); 299 # else 300 __funlockfile (stderr); 301 # endif 302 #endif 303 } 304 305 /* Sometimes we want to have at most one error per line. This 306 variable controls whether this mode is selected or not. */ 307 int error_one_per_line; 308 309 void 310 #if defined VA_START && __STDC__ 311 error_at_line (int status, int errnum, const char *file_name, 312 unsigned int line_number, const char *message, ...) 313 #else 314 error_at_line (status, errnum, file_name, line_number, message, va_alist) 315 int status; 316 int errnum; 317 const char *file_name; 318 unsigned int line_number; 319 char *message; 320 va_dcl 321 #endif 322 { 323 #ifdef VA_START 324 va_list args; 325 #endif 326 327 if (error_one_per_line) 328 { 329 static const char *old_file_name; 330 static unsigned int old_line_number; 331 332 if (old_line_number == line_number 333 && (file_name == old_file_name 334 || strcmp (old_file_name, file_name) == 0)) 335 /* Simply return and print nothing. */ 336 return; 337 338 old_file_name = file_name; 339 old_line_number = line_number; 340 } 341 342 fflush (stdout); 343 #ifdef _LIBC 344 # ifdef USE_IN_LIBIO 345 _IO_flockfile (stderr); 346 # else 347 __flockfile (stderr); 348 # endif 349 #endif 350 if (error_print_progname) 351 (*error_print_progname) (); 352 else 353 { 354 #if _LIBC && USE_IN_LIBIO 355 if (_IO_fwide (stderr, 0) > 0) 356 __fwprintf (stderr, L"%s: ", program_name); 357 else 358 #endif 359 fprintf (stderr, "%s:", program_name); 360 } 361 362 if (file_name != NULL) 363 { 364 #if _LIBC && USE_IN_LIBIO 365 if (_IO_fwide (stderr, 0) > 0) 366 __fwprintf (stderr, L"%s:%d: ", file_name, line_number); 367 else 368 #endif 369 fprintf (stderr, "%s:%d: ", file_name, line_number); 370 } 371 372 #ifdef VA_START 373 VA_START (args, message); 374 error_tail (status, errnum, message, args); 375 #else 376 fprintf (stderr, message, a1, a2, a3, a4, a5, a6, a7, a8); 377 378 ++error_message_count; 379 if (errnum) 380 print_errno_message (errnum); 381 putc ('\n', stderr); 382 fflush (stderr); 383 if (status) 384 exit (status); 385 #endif 386 387 #ifdef _LIBC 388 # ifdef USE_IN_LIBIO 389 _IO_funlockfile (stderr); 390 # else 391 __funlockfile (stderr); 392 # endif 393 #endif 394 } 395 396 #ifdef _LIBC 397 /* Make the weak alias. */ 398 # undef error 399 # undef error_at_line 400 weak_alias (__error, error) 401 weak_alias (__error_at_line, error_at_line) 402 #endif 403