diff options
author | Ton Voon <tonvoon@users.sourceforge.net> | 2007-01-24 22:47:25 (GMT) |
---|---|---|
committer | Ton Voon <tonvoon@users.sourceforge.net> | 2007-01-24 22:47:25 (GMT) |
commit | fe856aa957978504137c1d425815d4ed8a22be40 (patch) | |
tree | a5bb46ce0e64b2056f75700eadbf27aba7c39418 /gl/error.c | |
parent | 210f39bc84cfbb21cd72dc054e43f13815ee0616 (diff) | |
download | monitoring-plugins-fe856aa957978504137c1d425815d4ed8a22be40.tar.gz |
Sync with gnulib - lots of extraneous code removed in preference to GNU code
git-svn-id: https://nagiosplug.svn.sourceforge.net/svnroot/nagiosplug/nagiosplug/trunk@1580 f882894a-f735-0410-b71e-b25c423dba1c
Diffstat (limited to 'gl/error.c')
-rw-r--r-- | gl/error.c | 338 |
1 files changed, 338 insertions, 0 deletions
diff --git a/gl/error.c b/gl/error.c new file mode 100644 index 0000000..cf86343 --- /dev/null +++ b/gl/error.c | |||
@@ -0,0 +1,338 @@ | |||
1 | /* Error handler for noninteractive utilities | ||
2 | Copyright (C) 1990-1998, 2000-2005, 2006 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 | |||
19 | /* Written by David MacKenzie <djm@gnu.ai.mit.edu>. */ | ||
20 | |||
21 | #if !_LIBC | ||
22 | # include <config.h> | ||
23 | #endif | ||
24 | |||
25 | #include "error.h" | ||
26 | |||
27 | #include <stdarg.h> | ||
28 | #include <stdio.h> | ||
29 | #include <stdlib.h> | ||
30 | #include <string.h> | ||
31 | |||
32 | #if !_LIBC && ENABLE_NLS | ||
33 | # include "gettext.h" | ||
34 | #endif | ||
35 | |||
36 | #ifdef _LIBC | ||
37 | # include <libintl.h> | ||
38 | # include <stdbool.h> | ||
39 | # include <stdint.h> | ||
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 <limits.h> | ||
66 | # include <libio/libioP.h> | ||
67 | |||
68 | /* In GNU libc we want do not want to use the common name `error' directly. | ||
69 | Instead make it a weak alias. */ | ||
70 | extern void __error (int status, int errnum, const char *message, ...) | ||
71 | __attribute__ ((__format__ (__printf__, 3, 4))); | ||
72 | extern void __error_at_line (int status, int errnum, const char *file_name, | ||
73 | unsigned int line_number, const char *message, | ||
74 | ...) | ||
75 | __attribute__ ((__format__ (__printf__, 5, 6)));; | ||
76 | # define error __error | ||
77 | # define error_at_line __error_at_line | ||
78 | |||
79 | # include <libio/iolibio.h> | ||
80 | # define fflush(s) INTUSE(_IO_fflush) (s) | ||
81 | # undef putc | ||
82 | # define putc(c, fp) INTUSE(_IO_putc) (c, fp) | ||
83 | |||
84 | # include <bits/libc-lock.h> | ||
85 | |||
86 | #else /* not _LIBC */ | ||
87 | |||
88 | # if !HAVE_DECL_STRERROR_R && STRERROR_R_CHAR_P | ||
89 | # ifndef HAVE_DECL_STRERROR_R | ||
90 | "this configure-time declaration test was not run" | ||
91 | # endif | ||
92 | char *strerror_r (); | ||
93 | # endif | ||
94 | |||
95 | /* The calling program should define program_name and set it to the | ||
96 | name of the executing program. */ | ||
97 | extern char *program_name; | ||
98 | |||
99 | # if HAVE_STRERROR_R || defined strerror_r | ||
100 | # define __strerror_r strerror_r | ||
101 | # endif /* HAVE_STRERROR_R || defined strerror_r */ | ||
102 | #endif /* not _LIBC */ | ||
103 | |||
104 | static void | ||
105 | print_errno_message (int errnum) | ||
106 | { | ||
107 | char const *s; | ||
108 | |||
109 | #if defined HAVE_STRERROR_R || _LIBC | ||
110 | char errbuf[1024]; | ||
111 | # if STRERROR_R_CHAR_P || _LIBC | ||
112 | s = __strerror_r (errnum, errbuf, sizeof errbuf); | ||
113 | # else | ||
114 | if (__strerror_r (errnum, errbuf, sizeof errbuf) == 0) | ||
115 | s = errbuf; | ||
116 | else | ||
117 | s = 0; | ||
118 | # endif | ||
119 | #else | ||
120 | s = strerror (errnum); | ||
121 | #endif | ||
122 | |||
123 | #if !_LIBC | ||
124 | if (! s) | ||
125 | s = _("Unknown system error"); | ||
126 | #endif | ||
127 | |||
128 | #if _LIBC | ||
129 | __fxprintf (NULL, ": %s", s); | ||
130 | #else | ||
131 | fprintf (stderr, ": %s", s); | ||
132 | #endif | ||
133 | } | ||
134 | |||
135 | static void | ||
136 | error_tail (int status, int errnum, const char *message, va_list args) | ||
137 | { | ||
138 | #if _LIBC | ||
139 | if (_IO_fwide (stderr, 0) > 0) | ||
140 | { | ||
141 | # define ALLOCA_LIMIT 2000 | ||
142 | size_t len = strlen (message) + 1; | ||
143 | wchar_t *wmessage = NULL; | ||
144 | mbstate_t st; | ||
145 | size_t res; | ||
146 | const char *tmp; | ||
147 | bool use_malloc = false; | ||
148 | |||
149 | while (1) | ||
150 | { | ||
151 | if (__libc_use_alloca (len * sizeof (wchar_t))) | ||
152 | wmessage = (wchar_t *) alloca (len * sizeof (wchar_t)); | ||
153 | else | ||
154 | { | ||
155 | if (!use_malloc) | ||
156 | wmessage = NULL; | ||
157 | |||
158 | wchar_t *p = (wchar_t *) realloc (wmessage, | ||
159 | len * sizeof (wchar_t)); | ||
160 | if (p == NULL) | ||
161 | { | ||
162 | free (wmessage); | ||
163 | fputws_unlocked (L"out of memory\n", stderr); | ||
164 | return; | ||
165 | } | ||
166 | wmessage = p; | ||
167 | use_malloc = true; | ||
168 | } | ||
169 | |||
170 | memset (&st, '\0', sizeof (st)); | ||
171 | tmp = message; | ||
172 | |||
173 | res = mbsrtowcs (wmessage, &tmp, len, &st); | ||
174 | if (res != len) | ||
175 | break; | ||
176 | |||
177 | if (__builtin_expect (len >= SIZE_MAX / 2, 0)) | ||
178 | { | ||
179 | /* This really should not happen if everything is fine. */ | ||
180 | res = (size_t) -1; | ||
181 | break; | ||
182 | } | ||
183 | |||
184 | len *= 2; | ||
185 | } | ||
186 | |||
187 | if (res == (size_t) -1) | ||
188 | { | ||
189 | /* The string cannot be converted. */ | ||
190 | if (use_malloc) | ||
191 | { | ||
192 | free (wmessage); | ||
193 | use_malloc = false; | ||
194 | } | ||
195 | wmessage = (wchar_t *) L"???"; | ||
196 | } | ||
197 | |||
198 | __vfwprintf (stderr, wmessage, args); | ||
199 | |||
200 | if (use_malloc) | ||
201 | free (wmessage); | ||
202 | } | ||
203 | else | ||
204 | #endif | ||
205 | vfprintf (stderr, message, args); | ||
206 | va_end (args); | ||
207 | |||
208 | ++error_message_count; | ||
209 | if (errnum) | ||
210 | print_errno_message (errnum); | ||
211 | #if _LIBC | ||
212 | __fxprintf (NULL, "\n"); | ||
213 | #else | ||
214 | putc ('\n', stderr); | ||
215 | #endif | ||
216 | fflush (stderr); | ||
217 | if (status) | ||
218 | exit (status); | ||
219 | } | ||
220 | |||
221 | |||
222 | /* Print the program name and error message MESSAGE, which is a printf-style | ||
223 | format string with optional args. | ||
224 | If ERRNUM is nonzero, print its corresponding system error message. | ||
225 | Exit with status STATUS if it is nonzero. */ | ||
226 | void | ||
227 | error (int status, int errnum, const char *message, ...) | ||
228 | { | ||
229 | va_list args; | ||
230 | |||
231 | #if defined _LIBC && defined __libc_ptf_call | ||
232 | /* We do not want this call to be cut short by a thread | ||
233 | cancellation. Therefore disable cancellation for now. */ | ||
234 | int state = PTHREAD_CANCEL_ENABLE; | ||
235 | __libc_ptf_call (pthread_setcancelstate, (PTHREAD_CANCEL_DISABLE, &state), | ||
236 | 0); | ||
237 | #endif | ||
238 | |||
239 | fflush (stdout); | ||
240 | #ifdef _LIBC | ||
241 | _IO_flockfile (stderr); | ||
242 | #endif | ||
243 | if (error_print_progname) | ||
244 | (*error_print_progname) (); | ||
245 | else | ||
246 | { | ||
247 | #if _LIBC | ||
248 | __fxprintf (NULL, "%s: ", program_name); | ||
249 | #else | ||
250 | fprintf (stderr, "%s: ", program_name); | ||
251 | #endif | ||
252 | } | ||
253 | |||
254 | va_start (args, message); | ||
255 | error_tail (status, errnum, message, args); | ||
256 | |||
257 | #ifdef _LIBC | ||
258 | _IO_funlockfile (stderr); | ||
259 | # ifdef __libc_ptf_call | ||
260 | __libc_ptf_call (pthread_setcancelstate, (state, NULL), 0); | ||
261 | # endif | ||
262 | #endif | ||
263 | } | ||
264 | |||
265 | /* Sometimes we want to have at most one error per line. This | ||
266 | variable controls whether this mode is selected or not. */ | ||
267 | int error_one_per_line; | ||
268 | |||
269 | void | ||
270 | error_at_line (int status, int errnum, const char *file_name, | ||
271 | unsigned int line_number, const char *message, ...) | ||
272 | { | ||
273 | va_list args; | ||
274 | |||
275 | if (error_one_per_line) | ||
276 | { | ||
277 | static const char *old_file_name; | ||
278 | static unsigned int old_line_number; | ||
279 | |||
280 | if (old_line_number == line_number | ||
281 | && (file_name == old_file_name | ||
282 | || strcmp (old_file_name, file_name) == 0)) | ||
283 | /* Simply return and print nothing. */ | ||
284 | return; | ||
285 | |||
286 | old_file_name = file_name; | ||
287 | old_line_number = line_number; | ||
288 | } | ||
289 | |||
290 | #if defined _LIBC && defined __libc_ptf_call | ||
291 | /* We do not want this call to be cut short by a thread | ||
292 | cancellation. Therefore disable cancellation for now. */ | ||
293 | int state = PTHREAD_CANCEL_ENABLE; | ||
294 | __libc_ptf_call (pthread_setcancelstate, (PTHREAD_CANCEL_DISABLE, &state), | ||
295 | 0); | ||
296 | #endif | ||
297 | |||
298 | fflush (stdout); | ||
299 | #ifdef _LIBC | ||
300 | _IO_flockfile (stderr); | ||
301 | #endif | ||
302 | if (error_print_progname) | ||
303 | (*error_print_progname) (); | ||
304 | else | ||
305 | { | ||
306 | #if _LIBC | ||
307 | __fxprintf (NULL, "%s:", program_name); | ||
308 | #else | ||
309 | fprintf (stderr, "%s:", program_name); | ||
310 | #endif | ||
311 | } | ||
312 | |||
313 | #if _LIBC | ||
314 | __fxprintf (NULL, file_name != NULL ? "%s:%d: " : " ", | ||
315 | file_name, line_number); | ||
316 | #else | ||
317 | fprintf (stderr, file_name != NULL ? "%s:%d: " : " ", | ||
318 | file_name, line_number); | ||
319 | #endif | ||
320 | |||
321 | va_start (args, message); | ||
322 | error_tail (status, errnum, message, args); | ||
323 | |||
324 | #ifdef _LIBC | ||
325 | _IO_funlockfile (stderr); | ||
326 | # ifdef __libc_ptf_call | ||
327 | __libc_ptf_call (pthread_setcancelstate, (state, NULL), 0); | ||
328 | # endif | ||
329 | #endif | ||
330 | } | ||
331 | |||
332 | #ifdef _LIBC | ||
333 | /* Make the weak alias. */ | ||
334 | # undef error | ||
335 | # undef error_at_line | ||
336 | weak_alias (__error, error) | ||
337 | weak_alias (__error_at_line, error_at_line) | ||
338 | #endif | ||