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.
20 * Bludgeoned into submission for SunOS 4.1.3 by
21 * Chris Cheyney <cheyney@netcom.com>.
22 * Now it works even when the return from vprintf is unreliable.
31 #if defined(HAVE_SYSLOG)
35 #if HAVE_VPRINTF || HAVE_DOPRNT || _LIBC || HAVE_STDARG_H
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
57 #include "fetchmail.h"
58 #define MALLOC(n) xmalloc(n)
59 #define REALLOC(n,s) xrealloc(n,s)
61 /* If NULL, error will flush stderr, 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;
75 static unsigned int use_syslog;
77 /* This variable is incremented each time `error' is called. */
78 unsigned int error_message_count;
81 /* In the GNU C library, there is a predefined variable for this. */
83 # define program_name program_invocation_name
88 /* The calling program should define program_name and set it to the
89 name of the executing program. */
90 extern char *program_name;
92 # if !HAVE_STRERROR && !defined(strerror)
93 char *strerror (errnum)
96 extern char *sys_errlist[];
99 if (errnum > 0 && errnum <= sys_nerr)
100 return sys_errlist[errnum];
101 return _("Unknown system error");
103 # endif /* HAVE_STRERROR */
106 /* Print the program name and error message MESSAGE, which is a printf-style
107 format string with optional args.
108 If ERRNUM is nonzero, print its corresponding system error message. */
113 report (FILE *errfp, int errnum, const char *message, ...)
115 report (FILE *errfp, errnum, message, va_alist)
125 /* If a partially built message exists, print it now so it's not lost. */
126 if (partial_message_size_used != 0)
128 partial_message_size_used = 0;
129 report (errfp, 0, _("%s (log message incomplete)"), partial_message);
132 #if defined(HAVE_SYSLOG)
138 VA_START (args, message);
140 priority = errnum ? LOG_ERR : LOG_INFO;
146 xalloca(msg, char *, strlen (message) + 5);
148 strcpy (msg, message);
149 strcat (msg, ": %m");
153 vsyslog (priority, msg, args);
156 char *a1 = va_arg(args, char *);
157 char *a2 = va_arg(args, char *);
158 char *a3 = va_arg(args, char *);
159 char *a4 = va_arg(args, char *);
160 char *a5 = va_arg(args, char *);
161 char *a6 = va_arg(args, char *);
162 char *a7 = va_arg(args, char *);
163 char *a8 = va_arg(args, char *);
164 syslog (priority, msg, a1, a2, a3, a4, a5, a6, a7, a8);
171 vsyslog (priority, message, args);
174 char *a1 = va_arg(args, char *);
175 char *a2 = va_arg(args, char *);
176 char *a3 = va_arg(args, char *);
177 char *a4 = va_arg(args, char *);
178 char *a5 = va_arg(args, char *);
179 char *a6 = va_arg(args, char *);
180 char *a7 = va_arg(args, char *);
181 char *a8 = va_arg(args, char *);
182 syslog (priority, message, a1, a2, a3, a4, a5, a6, a7, a8);
194 if (error_print_progname)
195 (*error_print_progname) ();
199 if ( *message == '\n' )
201 fputc( '\n', errfp );
204 fprintf (errfp, "%s: ", program_name);
208 VA_START (args, message);
209 # if HAVE_VPRINTF || _LIBC
210 vfprintf (errfp, message, args);
212 _doprnt (message, args, errfp);
216 fprintf (errfp, message, a1, a2, a3, a4, a5, a6, a7, a8);
220 char *tmps = strerror(errnum);
222 fprintf (errfp, ": %s", tmps);
225 fprintf (errfp, _(": Error %d"), errnum);
231 ++error_message_count;
235 * Calling error_init(1) causes error_build and error_complete to write
236 * to errfp without buffering. This is needed for the ticker dots to
239 void error_init(int mode)
243 case 0: /* errfp, buffered */
249 case 1: /* errfp, unbuffered */
255 case -1: /* syslogd */
259 #endif /* HAVE_SYSLOG */
263 /* Build an error message by appending MESSAGE, which is a printf-style
264 format string with optional args, to the existing error message (which may
265 be empty.) The completed error message is finally printed (and reset to
266 empty) by calling error_complete().
267 If an intervening call to report() occurs when a partially constructed
268 message exists, then, in an attempt to keep the messages in their proper
269 sequence, the partial message will be printed as-is (with a trailing
270 newline) before report() prints its message. */
275 report_build (FILE *errfp, const char *message, ...)
277 report_build (FILE *errfp, message, va_alist)
287 /* Make an initial guess for the size of any single message fragment. */
288 if (partial_message_size == 0)
290 partial_message_size_used = 0;
291 partial_message_size = 2048;
292 partial_message = MALLOC (partial_message_size);
295 if (partial_message_size - partial_message_size_used < 1024)
297 partial_message_size += 2048;
298 partial_message = REALLOC (partial_message, partial_message_size);
301 #if defined(VA_START)
302 VA_START (args, message);
303 #if HAVE_VSNPRINTF || _LIBC
306 n = vsnprintf (partial_message + partial_message_size_used,
307 partial_message_size - partial_message_size_used,
310 if (n < partial_message_size - partial_message_size_used)
312 partial_message_size_used += n;
316 partial_message_size += 2048;
317 partial_message = REALLOC (partial_message, partial_message_size);
320 vsprintf (partial_message + partial_message_size_used, message, args);
321 partial_message_size_used += strlen(partial_message+partial_message_size_used);
323 /* Attempt to catch memory overwrites... */
324 if (partial_message_size_used >= partial_message_size)
326 partial_message_size_used = 0;
327 report (PS_UNDEFINED, 0, _("partial error message buffer overflow"));
335 n = snprintf (partial_message + partial_message_size_used,
336 partial_message_size - partial_message_size_used,
337 message, a1, a2, a3, a4, a5, a6, a7, a8);
339 if (n < partial_message_size - partial_message_size_used)
341 partial_message_size_used += n;
345 partial_message_size += 2048;
346 partial_message = REALLOC (partial_message, partial_message_size);
349 sprintf (partial_message + partial_message_size_used, message, a1, a2, a3, a4, a5, a6, a7, a8);
351 /* Attempt to catch memory overwrites... */
352 if ((partial_message_size_used = strlen (partial_message)) >= partial_message_size)
354 partial_message_size_used = 0;
355 report (PS_UNDEFINED, 0, _("partial error message buffer overflow"));
360 if (use_stderr && partial_message_size_used != 0)
362 partial_message_size_used = 0;
363 fputs(partial_message, errfp);
367 /* Complete an error message by appending MESSAGE, which is a printf-style
368 format string with optional args, to the existing error message (which may
369 be empty.) The completed error message is then printed (and reset to
375 report_complete (FILE *errfp, int errnum, const char *message, ...)
377 report_complete (FILE *errfp, errnum, message, va_alist)
388 /* Make an initial guess for the size of any single message fragment. */
389 if (partial_message_size == 0)
391 partial_message_size_used = 0;
392 partial_message_size = 2048;
393 partial_message = MALLOC (partial_message_size);
396 if (partial_message_size - partial_message_size_used < 1024)
398 partial_message_size += 2048;
399 partial_message = REALLOC (partial_message, partial_message_size);
402 #if defined(VA_START)
403 VA_START (args, message);
404 #if HAVE_VSNPRINTF || _LIBC
407 n = vsnprintf (partial_message + partial_message_size_used,
408 partial_message_size - partial_message_size_used,
411 if (n < partial_message_size - partial_message_size_used)
413 partial_message_size_used += n;
417 partial_message_size += 2048;
418 partial_message = REALLOC (partial_message, partial_message_size);
421 vsprintf (partial_message + partial_message_size_used, message, args);
422 partial_message_size_used += strlen(partial_message+partial_message_size_used);
424 /* Attempt to catch memory overwrites... */
425 if (partial_message_size_used >= partial_message_size)
427 partial_message_size_used = 0;
428 report (PS_UNDEFINED, 0, _("partial error message buffer overflow"));
436 n = snprintf (partial_message + partial_message_size_used,
437 partial_message_size - partial_message_size_used,
438 message, a1, a2, a3, a4, a5, a6, a7, a8);
440 if (n < partial_message_size - partial_message_size_used)
442 partial_message_size_used += n;
446 partial_message_size += 2048;
447 partial_message = REALLOC (partial_message, partial_message_size);
450 sprintf (partial_message + partial_message_size_used, message, a1, a2, a3, a4, a5, a6, a7, a8);
452 /* Attempt to catch memory overwrites... */
453 if ((partial_message_size_used = strlen (partial_message)) >= partial_message_size)
455 partial_message_size_used = 0;
456 report (PS_UNDEFINED, 0, _("partial error message buffer overflow"));
461 /* Finally... print it. */
462 partial_message_size_used = 0;
466 fputs(partial_message, errfp);
469 fprintf (errfp, ": %s", strerror (errnum));
474 ++error_message_count;
477 report (errfp, errnum, "%s", partial_message);
480 /* Sometimes we want to have at most one error per line. This
481 variable controls whether this mode is selected or not. */
482 int error_one_per_line;
486 report_at_line (FILE *errfp, int errnum, const char *file_name,
487 unsigned int line_number, const char *message, ...)
489 report_at_line (FILE *errfp, errnum, file_name, line_number, message, va_alist)
491 const char *file_name;
492 unsigned int line_number;
501 if (error_one_per_line)
503 static const char *old_file_name;
504 static unsigned int old_line_number;
506 if (old_line_number == line_number &&
507 (file_name == old_file_name || !strcmp (old_file_name, file_name)))
508 /* Simply return and print nothing. */
511 old_file_name = file_name;
512 old_line_number = line_number;
515 if (error_print_progname)
516 (*error_print_progname) ();
520 if ( *message == '\n' )
522 fputc( '\n', errfp );
525 fprintf (errfp, "%s:", program_name);
528 if (file_name != NULL)
529 fprintf (errfp, "%s:%d: ", file_name, line_number);
532 VA_START (args, message);
533 # if HAVE_VPRINTF || _LIBC
534 vfprintf (errfp, message, args);
536 _doprnt (message, args, errfp);
540 fprintf (errfp, message, a1, a2, a3, a4, a5, a6, a7, a8);
543 ++error_message_count;
545 fprintf (errfp, ": %s", strerror (errnum));