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);
230 ++error_message_count;
234 * Calling report_init(1) causes error_build and error_complete to write
235 * to errfp without buffering. This is needed for the ticker dots to
238 void report_init(int mode)
242 case 0: /* errfp, buffered */
248 case 1: /* errfp, unbuffered */
254 case -1: /* syslogd */
258 #endif /* HAVE_SYSLOG */
262 /* Build an error message by appending MESSAGE, which is a printf-style
263 format string with optional args, to the existing error message (which may
264 be empty.) The completed error message is finally printed (and reset to
265 empty) by calling error_complete().
266 If an intervening call to report() occurs when a partially constructed
267 message exists, then, in an attempt to keep the messages in their proper
268 sequence, the partial message will be printed as-is (with a trailing
269 newline) before report() prints its message. */
274 report_build (FILE *errfp, const char *message, ...)
276 report_build (FILE *errfp, message, va_alist)
286 /* Make an initial guess for the size of any single message fragment. */
287 if (partial_message_size == 0)
289 partial_message_size_used = 0;
290 partial_message_size = 2048;
291 partial_message = MALLOC (partial_message_size);
294 if (partial_message_size - partial_message_size_used < 1024)
296 partial_message_size += 2048;
297 partial_message = REALLOC (partial_message, partial_message_size);
300 #if defined(VA_START)
301 VA_START (args, message);
302 #if HAVE_VSNPRINTF || _LIBC
305 n = vsnprintf (partial_message + partial_message_size_used,
306 partial_message_size - partial_message_size_used,
309 if (n < partial_message_size - partial_message_size_used)
311 partial_message_size_used += n;
315 partial_message_size += 2048;
316 partial_message = REALLOC (partial_message, partial_message_size);
319 vsprintf (partial_message + partial_message_size_used, message, args);
320 partial_message_size_used += strlen(partial_message+partial_message_size_used);
322 /* Attempt to catch memory overwrites... */
323 if (partial_message_size_used >= partial_message_size)
325 partial_message_size_used = 0;
326 report (PS_UNDEFINED, 0, _("partial error message buffer overflow"));
334 n = snprintf (partial_message + partial_message_size_used,
335 partial_message_size - partial_message_size_used,
336 message, a1, a2, a3, a4, a5, a6, a7, a8);
338 if (n < partial_message_size - partial_message_size_used)
340 partial_message_size_used += n;
344 partial_message_size += 2048;
345 partial_message = REALLOC (partial_message, partial_message_size);
348 sprintf (partial_message + partial_message_size_used, message, a1, a2, a3, a4, a5, a6, a7, a8);
350 /* Attempt to catch memory overwrites... */
351 if ((partial_message_size_used = strlen (partial_message)) >= partial_message_size)
353 partial_message_size_used = 0;
354 report (PS_UNDEFINED, 0, _("partial error message buffer overflow"));
359 if (use_stderr && partial_message_size_used != 0)
361 partial_message_size_used = 0;
362 fputs(partial_message, errfp);
366 /* Complete an error message by appending MESSAGE, which is a printf-style
367 format string with optional args, to the existing error message (which may
368 be empty.) The completed error message is then printed (and reset to
374 report_complete (FILE *errfp, int errnum, const char *message, ...)
376 report_complete (FILE *errfp, errnum, message, va_alist)
387 /* Make an initial guess for the size of any single message fragment. */
388 if (partial_message_size == 0)
390 partial_message_size_used = 0;
391 partial_message_size = 2048;
392 partial_message = MALLOC (partial_message_size);
395 if (partial_message_size - partial_message_size_used < 1024)
397 partial_message_size += 2048;
398 partial_message = REALLOC (partial_message, partial_message_size);
401 #if defined(VA_START)
402 VA_START (args, message);
403 #if HAVE_VSNPRINTF || _LIBC
406 n = vsnprintf (partial_message + partial_message_size_used,
407 partial_message_size - partial_message_size_used,
410 if (n < partial_message_size - partial_message_size_used)
412 partial_message_size_used += n;
416 partial_message_size += 2048;
417 partial_message = REALLOC (partial_message, partial_message_size);
420 vsprintf (partial_message + partial_message_size_used, message, args);
421 partial_message_size_used += strlen(partial_message+partial_message_size_used);
423 /* Attempt to catch memory overwrites... */
424 if (partial_message_size_used >= partial_message_size)
426 partial_message_size_used = 0;
427 report (PS_UNDEFINED, 0, _("partial error message buffer overflow"));
435 n = snprintf (partial_message + partial_message_size_used,
436 partial_message_size - partial_message_size_used,
437 message, a1, a2, a3, a4, a5, a6, a7, a8);
439 if (n < partial_message_size - partial_message_size_used)
441 partial_message_size_used += n;
445 partial_message_size += 2048;
446 partial_message = REALLOC (partial_message, partial_message_size);
449 sprintf (partial_message + partial_message_size_used, message, a1, a2, a3, a4, a5, a6, a7, a8);
451 /* Attempt to catch memory overwrites... */
452 if ((partial_message_size_used = strlen (partial_message)) >= partial_message_size)
454 partial_message_size_used = 0;
455 report (PS_UNDEFINED, 0, _("partial error message buffer overflow"));
460 /* Finally... print it. */
461 partial_message_size_used = 0;
465 fputs(partial_message, errfp);
468 fprintf (errfp, ": %s", strerror (errnum));
472 ++error_message_count;
475 report (errfp, errnum, "%s", partial_message);
478 /* Sometimes we want to have at most one error per line. This
479 variable controls whether this mode is selected or not. */
480 int error_one_per_line;
484 report_at_line (FILE *errfp, int errnum, const char *file_name,
485 unsigned int line_number, const char *message, ...)
487 report_at_line (FILE *errfp, errnum, file_name, line_number, message, va_alist)
489 const char *file_name;
490 unsigned int line_number;
499 if (error_one_per_line)
501 static const char *old_file_name;
502 static unsigned int old_line_number;
504 if (old_line_number == line_number &&
505 (file_name == old_file_name || !strcmp (old_file_name, file_name)))
506 /* Simply return and print nothing. */
509 old_file_name = file_name;
510 old_line_number = line_number;
513 if (error_print_progname)
514 (*error_print_progname) ();
518 if ( *message == '\n' )
520 fputc( '\n', errfp );
523 fprintf (errfp, "%s:", program_name);
526 if (file_name != NULL)
527 fprintf (errfp, "%s:%d: ", file_name, line_number);
530 VA_START (args, message);
531 # if HAVE_VPRINTF || _LIBC
532 vfprintf (errfp, message, args);
534 _doprnt (message, args, errfp);
538 fprintf (errfp, message, a1, a2, a3, a4, a5, a6, a7, a8);
541 ++error_message_count;
543 fprintf (errfp, ": %s", strerror (errnum));