1 /* error.c -- error handler for noninteractive utilities
2 Copyright (C) 1990, 91, 92, 93, 94, 95, 96 Free Software Foundation, Inc.
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2, or (at your option)
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
18 /* Written by David MacKenzie <djm@gnu.ai.mit.edu>.
19 * Heavily modified by Dave Bodenstab and ESR.
28 #if defined(HAVE_SYSLOG)
31 #if defined(HAVE_ALLOCA_H)
35 #if HAVE_VPRINTF || HAVE_DOPRNT || _LIBC
38 # define VA_START(args, lastarg) va_start(args, lastarg)
41 # define VA_START(args, lastarg) va_start(args)
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;
48 #if STDC_HEADERS || _LIBC
55 #include "fetchmail.h"
58 # define _(String) String
61 /* If NULL, error will flush stdout, then print on stderr the program
62 name, a colon and a space. Otherwise, error will call this
63 function without parameters instead. */
64 void (*error_print_progname) (
70 /* Used by error_build() and error_complete() to accumulate partial messages. */
71 static unsigned int partial_message_size = 0;
72 static unsigned int partial_message_size_used = 0;
73 static char *partial_message;
74 static unsigned use_stderr;
76 /* This variable is incremented each time `error' is called. */
77 unsigned int error_message_count;
80 /* In the GNU C library, there is a predefined variable for this. */
82 # define program_name program_invocation_name
87 /* The calling program should define program_name and set it to the
88 name of the executing program. */
89 extern char *program_name;
92 # ifndef strerror /* On some systems, strerror is a macro */
97 private_strerror (errnum)
100 extern char *sys_errlist[];
103 if (errnum > 0 && errnum <= sys_nerr)
104 return sys_errlist[errnum];
105 return _("Unknown system error");
107 # define strerror private_strerror
108 # endif /* HAVE_STRERROR */
111 /* Print the program name and error message MESSAGE, which is a printf-style
112 format string with optional args.
113 If ERRNUM is nonzero, print its corresponding system error message.
114 Exit with status STATUS if it is nonzero. */
117 #if !defined(HAVE_VSYSLOG) && !defined(VA_START)
118 int vsyslog(priority, message, va_alist)
127 string = (char *)malloc(LINELEN);
130 vsprintf(string, message, args);
133 syslog(priority, string);
139 #if defined(VA_START) && __STDC__
140 error (int status, int errnum, const char *message, ...)
142 error (status, errnum, message, va_alist)
153 /* If a partially built message exists, print it now so it's not lost. */
154 if (partial_message_size_used != 0)
156 partial_message_size_used = 0;
157 error (0, 0, "%s (message incomplete)", partial_message);
160 #if defined(HAVE_SYSLOG)
166 VA_START (args, message);
168 priority = status? LOG_ALERT : errnum? LOG_ERR : LOG_INFO;
172 char *msg = alloca (strlen (message) + 5);
174 strcpy (msg, message);
175 strcat (msg, ": %m");
179 vsyslog (priority, msg, args);
182 syslog (priority, msg, a1, a2, a3, a4, a5, a6, a7, a8);
188 vsyslog (priority, message, args);
191 syslog (priority, message, a1, a2, a3, a4, a5, a6, a7, a8);
198 if (error_print_progname)
199 (*error_print_progname) ();
203 if ( *message == '\n' )
205 fputc( '\n', stderr );
208 fprintf (stderr, "%s: ", program_name);
212 VA_START (args, message);
213 # if HAVE_VPRINTF || _LIBC
214 vfprintf (stderr, message, args);
216 _doprnt (message, args, stderr);
220 fprintf (stderr, message, a1, a2, a3, a4, a5, a6, a7, a8);
224 fprintf (stderr, ": %s", strerror (errnum));
228 ++error_message_count;
234 * Calling error_init(TRUE) causes error_build and error_complete to write
235 * to stderr without buffering. This is needed for the ticker dots to
238 void error_init(foreground)
241 use_stderr = foreground;
244 /* Build an error message by appending MESSAGE, which is a printf-style
245 format string with optional args, to the existing error message (which may
246 be empty.) The completed error message is finally printed (and reset to
247 empty) by calling error_complete().
248 If an intervening call to error() occurs when a partially constructed
249 message exists, then, in an attempt to keep the messages in their proper
250 sequence, the partial message will be printed as-is (with a trailing newline)
251 before error() prints its message.
255 #if defined(VA_START) && __STDC__
256 error_build (const char *message, ...)
258 error_build (message, va_alist)
268 /* Make an initial guess for the size of any single message fragment. */
269 if (partial_message_size == 0)
271 partial_message_size_used = 0;
272 partial_message_size = 512;
273 partial_message = xmalloc (partial_message_size);
276 if (partial_message_size - partial_message_size_used < 256)
278 partial_message_size += 512;
279 partial_message = xrealloc (partial_message, partial_message_size);
282 #if defined(VA_START) && (HAVE_VSNPRINTF || _LIBC)
283 VA_START (args, message);
286 n = vsnprintf (partial_message + partial_message_size_used,
287 partial_message_size - partial_message_size_used,
290 if (n < partial_message_size - partial_message_size_used)
292 partial_message_size_used += n;
296 partial_message_size += 512;
297 partial_message = xrealloc (partial_message, partial_message_size);
304 n = snprintf (partial_message + partial_message_size_used,
305 partial_message_size - partial_message_size_used,
306 message, a1, a2, a3, a4, a5, a6, a7, a8);
308 if (n < partial_message_size - partial_message_size_used)
310 partial_message_size_used += n;
314 partial_message_size += 512;
315 partial_message = xrealloc (partial_message, partial_message_size);
318 sprintf (partial_message + partial_message_size_used, message, a1, a2, a3, a4, a5, a6, a7, a8);
320 /* Attempt to catch memory overwrites... */
321 if ((partial_message_size_used = strlen (partial_message)) >= partial_message_size)
323 partial_message_size_used = 0;
324 error (PS_UNDEFINED, 0, "partial error message buffer overflow");
329 if (use_stderr && partial_message_size_used != 0)
331 partial_message_size_used = 0;
332 fputs(partial_message, stderr);
336 /* Complete an error message by appending MESSAGE, which is a printf-style
337 format string with optional args, to the existing error message (which may
338 be empty.) The completed error message is then printed (and reset to
343 #if defined(VA_START) && __STDC__
344 error_complete (int status, int errnum, const char *message, ...)
346 error_complete (status, errnum, message, va_alist)
358 /* Make an initial guess for the size of any single message fragment. */
359 if (partial_message_size == 0)
361 partial_message_size_used = 0;
362 partial_message_size = 512;
363 partial_message = xmalloc (partial_message_size);
366 if (partial_message_size - partial_message_size_used < 256)
368 partial_message_size += 512;
369 partial_message = xrealloc (partial_message, partial_message_size);
372 #if defined(VA_START) && (HAVE_VSNPRINTF || _LIBC)
373 VA_START (args, message);
376 n = vsnprintf (partial_message + partial_message_size_used,
377 partial_message_size - partial_message_size_used,
380 if (n < partial_message_size - partial_message_size_used)
382 partial_message_size_used += n;
386 partial_message_size += 512;
387 partial_message = xrealloc (partial_message, partial_message_size);
394 n = snprintf (partial_message + partial_message_size_used,
395 partial_message_size - partial_message_size_used,
396 message, a1, a2, a3, a4, a5, a6, a7, a8);
398 if (n < partial_message_size - partial_message_size_used)
400 partial_message_size_used += n;
404 partial_message_size += 512;
405 partial_message = xrealloc (partial_message, partial_message_size);
408 sprintf (partial_message + partial_message_size_used, message, a1, a2, a3, a4, a5, a6, a7, a8);
410 /* Attempt to catch memory overwrites... */
411 if ((partial_message_size_used = strlen (partial_message)) >= partial_message_size)
413 partial_message_size_used = 0;
414 error (PS_UNDEFINED, 0, "partial error message buffer overflow");
419 /* Finally... print it. */
420 partial_message_size_used = 0;
424 fputs(partial_message, stderr);
427 fprintf (stderr, ": %s", strerror (errnum));
432 ++error_message_count;
438 error (status, errnum, "%s", partial_message);
441 /* Sometimes we want to have at most one error per line. This
442 variable controls whether this mode is selected or not. */
443 int error_one_per_line;
446 #if defined(VA_START) && __STDC__
447 error_at_line (int status, int errnum, const char *file_name,
448 unsigned int line_number, const char *message, ...)
450 error_at_line (status, errnum, file_name, line_number, message, va_alist)
453 const char *file_name;
454 unsigned int line_number;
463 if (error_one_per_line)
465 static const char *old_file_name;
466 static unsigned int old_line_number;
468 if (old_line_number == line_number &&
469 (file_name == old_file_name || !strcmp (old_file_name, file_name)))
470 /* Simply return and print nothing. */
473 old_file_name = file_name;
474 old_line_number = line_number;
477 if (error_print_progname)
478 (*error_print_progname) ();
482 if ( *message == '\n' )
484 fputc( '\n', stderr );
487 fprintf (stderr, "%s:", program_name);
490 if (file_name != NULL)
491 fprintf (stderr, "%s:%d: ", file_name, line_number);
494 VA_START (args, message);
495 # if HAVE_VPRINTF || _LIBC
496 vfprintf (stderr, message, args);
498 _doprnt (message, args, stderr);
502 fprintf (stderr, message, a1, a2, a3, a4, a5, a6, a7, a8);
505 ++error_message_count;
507 fprintf (stderr, ": %s", strerror (errnum));