1 /* $NetBSD: error.c,v 1.1.1.1 2016/01/10 21:36:18 christos Exp $ */
2
3 /* Error handler for noninteractive utilities
4 Copyright (C) 1990-1998, 2000 Free Software Foundation, Inc.
5
6 This file is part of the GNU C Library. Its master source is NOT part of
7 the C library, however. The master source lives in /gd/gnu/lib.
8
9 The GNU C Library is free software; you can redistribute it and/or
10 modify it under the terms of the GNU Library General Public License as
11 published by the Free Software Foundation; either version 2 of the
12 License, or (at your option) any later version.
13
14 The GNU C Library is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 Library General Public License for more details.
18
19 You should have received a copy of the GNU Library General Public
20 License along with the GNU C Library; see the file COPYING.LIB. If not,
21 write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
22 Boston, MA 02111-1307, USA. */
23
24 /* Written by David MacKenzie <djm@gnu.ai.mit.edu>. */
25
26 #ifdef HAVE_CONFIG_H
27 # include <config.h>
28 #endif
29
30 #include <stdio.h>
31 #if HAVE_LIBINTL_H
32 # include <libintl.h>
33 #endif
34
35 #if HAVE_VPRINTF || HAVE_DOPRNT || _LIBC
36 # if __STDC__
37 # include <stdarg.h>
38 # define VA_START(args, lastarg) va_start(args, lastarg)
39 # else
40 # include <varargs.h>
41 # define VA_START(args, lastarg) va_start(args)
42 # endif
43 #else
44 # define va_alist a1, a2, a3, a4, a5, a6, a7, a8
45 # define va_dcl char *a1, *a2, *a3, *a4, *a5, *a6, *a7, *a8;
46 #endif
47
48 #if STDC_HEADERS || _LIBC
49 # include <stdlib.h>
50 # include <string.h>
51 #else
52 void exit ();
53 #endif
54
55 #include "error.h"
56
57 #ifndef HAVE_DECL_STRERROR_R
58 "this configure-time declaration test was not run"
59 #endif
60 #if !HAVE_DECL_STRERROR_R
61 char *strerror_r ();
62 #endif
63
64 #ifndef _
65 # define _(String) String
66 #endif
67
68 /* If NULL, error will flush stdout, then print on stderr the program
69 name, a colon and a space. Otherwise, error will call this
70 function without parameters instead. */
71 void (*error_print_progname) (
72 #if __STDC__ - 0
73 void
74 #endif
75 );
76
77 /* This variable is incremented each time `error' is called. */
78 unsigned int error_message_count;
79
80 #ifdef _LIBC
81 /* In the GNU C library, there is a predefined variable for this. */
82
83 # define program_name program_invocation_name
84 # include <errno.h>
85
86 /* In GNU libc we want do not want to use the common name `error' directly.
87 Instead make it a weak alias. */
88 # define error __error
89 # define error_at_line __error_at_line
90
91 # ifdef USE_IN_LIBIO
92 # include <libio/iolibio.h>
93 # define fflush(s) _IO_fflush (s)
94 # endif
95
96 #else /* not _LIBC */
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 # ifdef HAVE_STRERROR_R
103 # define __strerror_r strerror_r
104 # else
105 # if HAVE_STRERROR
106 # ifndef strerror /* On some systems, strerror is a macro */
107 char *strerror ();
108 # endif
109 # else
110 static char *
private_strerror(errnum)111 private_strerror (errnum)
112 int errnum;
113 {
114 extern char *sys_errlist[];
115 extern int sys_nerr;
116
117 if (errnum > 0 && errnum <= sys_nerr)
118 return _(sys_errlist[errnum]);
119 return _("Unknown system error");
120 }
121 # define strerror private_strerror
122 # endif /* HAVE_STRERROR */
123 # endif /* HAVE_STRERROR_R */
124 #endif /* not _LIBC */
125
126 /* Print the program name and error message MESSAGE, which is a printf-style
127 format string with optional args.
128 If ERRNUM is nonzero, print its corresponding system error message.
129 Exit with status STATUS if it is nonzero. */
130 /* VARARGS */
131
132 void
133 #if defined VA_START && __STDC__
error(int status,int errnum,const char * message,...)134 error (int status, int errnum, const char *message, ...)
135 #else
136 error (status, errnum, message, va_alist)
137 int status;
138 int errnum;
139 char *message;
140 va_dcl
141 #endif
142 {
143 #ifdef VA_START
144 va_list args;
145 #endif
146
147 if (error_print_progname)
148 (*error_print_progname) ();
149 else
150 {
151 fflush (stdout);
152 fprintf (stderr, "%s: ", program_name);
153 }
154
155 #ifdef VA_START
156 VA_START (args, message);
157 # if HAVE_VPRINTF || _LIBC
158 vfprintf (stderr, message, args);
159 # else
160 _doprnt (message, args, stderr);
161 # endif
162 va_end (args);
163 #else
164 fprintf (stderr, message, a1, a2, a3, a4, a5, a6, a7, a8);
165 #endif
166
167 ++error_message_count;
168 if (errnum)
169 {
170 #if defined HAVE_STRERROR_R || _LIBC
171 char errbuf[1024];
172 # if HAVE_WORKING_STRERROR_R || _LIBC
173 fprintf (stderr, ": %s", __strerror_r (errnum, errbuf, sizeof errbuf));
174 # else
175 /* Don't use __strerror_r's return value because on some systems
176 (at least DEC UNIX 4.0[A-D]) strerror_r returns `int'. */
177 __strerror_r (errnum, errbuf, sizeof errbuf);
178 fprintf (stderr, ": %s", errbuf);
179 # endif
180 #else
181 fprintf (stderr, ": %s", strerror (errnum));
182 #endif
183 }
184 putc ('\n', stderr);
185 fflush (stderr);
186 if (status)
187 exit (status);
188 }
189
190 /* Sometimes we want to have at most one error per line. This
191 variable controls whether this mode is selected or not. */
192 int error_one_per_line;
193
194 void
195 #if defined VA_START && __STDC__
error_at_line(int status,int errnum,const char * file_name,unsigned int line_number,const char * message,...)196 error_at_line (int status, int errnum, const char *file_name,
197 unsigned int line_number, const char *message, ...)
198 #else
199 error_at_line (status, errnum, file_name, line_number, message, va_alist)
200 int status;
201 int errnum;
202 const char *file_name;
203 unsigned int line_number;
204 char *message;
205 va_dcl
206 #endif
207 {
208 #ifdef VA_START
209 va_list args;
210 #endif
211
212 if (error_one_per_line)
213 {
214 static const char *old_file_name;
215 static unsigned int old_line_number;
216
217 if (old_line_number == line_number &&
218 (file_name == old_file_name || !strcmp (old_file_name, file_name)))
219 /* Simply return and print nothing. */
220 return;
221
222 old_file_name = file_name;
223 old_line_number = line_number;
224 }
225
226 if (error_print_progname)
227 (*error_print_progname) ();
228 else
229 {
230 fflush (stdout);
231 fprintf (stderr, "%s:", program_name);
232 }
233
234 if (file_name != NULL)
235 fprintf (stderr, "%s:%d: ", file_name, line_number);
236
237 #ifdef VA_START
238 VA_START (args, message);
239 # if HAVE_VPRINTF || _LIBC
240 vfprintf (stderr, message, args);
241 # else
242 _doprnt (message, args, stderr);
243 # endif
244 va_end (args);
245 #else
246 fprintf (stderr, message, a1, a2, a3, a4, a5, a6, a7, a8);
247 #endif
248
249 ++error_message_count;
250 if (errnum)
251 {
252 #if defined HAVE_STRERROR_R || _LIBC
253 char errbuf[1024];
254 # if HAVE_WORKING_STRERROR_R || _LIBC
255 fprintf (stderr, ": %s", __strerror_r (errnum, errbuf, sizeof errbuf));
256 # else
257 /* Don't use __strerror_r's return value because on some systems
258 (at least DEC UNIX 4.0[A-D]) strerror_r returns `int'. */
259 __strerror_r (errnum, errbuf, sizeof errbuf);
260 fprintf (stderr, ": %s", errbuf);
261 # endif
262 #else
263 fprintf (stderr, ": %s", strerror (errnum));
264 #endif
265 }
266 putc ('\n', stderr);
267 fflush (stderr);
268 if (status)
269 exit (status);
270 }
271
272 #ifdef _LIBC
273 /* Make the weak alias. */
274 # undef error
275 # undef error_at_line
276 weak_alias (__error, error)
277 weak_alias (__error_at_line, error_at_line)
278 #endif
279