error.c revision 1.1.1.1
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 54void 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. */ 67void (*error_print_progname) ( 68#if __STDC__ - 0 69 void 70#endif 71 ); 72 73/* This variable is incremented each time `error' is called. */ 74unsigned 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. */ 84extern void __error (int status, int errnum, const char *message, ...) 85 __attribute__ ((__format__ (__printf__, 3, 4))); 86extern 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 104char *strerror_r (); 105# endif 106 107/* The calling program should define program_name and set it to the 108 name of the executing program. */ 109extern 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 119char *strerror (); 120# endif 121# else 122static char * 123private_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 137static void 138print_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 173static void 174error_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 */ 246void 247#if defined VA_START && __STDC__ 248error (int status, int errnum, const char *message, ...) 249#else 250error (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. */ 307int error_one_per_line; 308 309void 310#if defined VA_START && __STDC__ 311error_at_line (int status, int errnum, const char *file_name, 312 unsigned int line_number, const char *message, ...) 313#else 314error_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 400weak_alias (__error, error) 401weak_alias (__error_at_line, error_at_line) 402#endif 403