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
56 # define _(String) String
59 #include "fetchmail.h"
60 #define MALLOC(n) xmalloc(n)
61 #define REALLOC(n,s) xrealloc(n,s)
63 /* If NULL, error will flush stdout, then print on stderr the program
64 name, a colon and a space. Otherwise, error will call this
65 function without parameters instead. */
66 void (*error_print_progname) (
72 /* Used by error_build() and error_complete() to accumulate partial messages. */
73 static unsigned int partial_message_size = 0;
74 static unsigned int partial_message_size_used = 0;
75 static char *partial_message;
76 static unsigned use_stderr;
77 static unsigned int use_syslog;
79 /* This variable is incremented each time `error' is called. */
80 unsigned int error_message_count;
84 /* In the GNU C library, there is a predefined variable for this. */
86 # define program_name program_invocation_name
91 /* The calling program should define program_name and set it to the
92 name of the executing program. */
93 extern char *program_name;
96 # ifndef strerror /* On some systems, strerror is a macro */
101 private_strerror (errnum)
104 extern char *sys_errlist[];
107 if (errnum > 0 && errnum <= sys_nerr)
108 return sys_errlist[errnum];
109 return _("Unknown system error");
111 # define strerror private_strerror
112 # endif /* HAVE_STRERROR */
115 /* Print the program name and error message MESSAGE, which is a printf-style
116 format string with optional args.
117 If ERRNUM is nonzero, print its corresponding system error message.
118 Exit with status STATUS if it is nonzero. */
123 error (int status, int errnum, const char *message, ...)
125 error (status, errnum, message, va_alist)
136 /* If a partially built message exists, print it now so it's not lost. */
137 if (partial_message_size_used != 0)
139 partial_message_size_used = 0;
140 error (0, 0, "%s (log message incomplete)", partial_message);
143 #if defined(HAVE_SYSLOG)
149 VA_START (args, message);
151 priority = status? LOG_ALERT : errnum? LOG_ERR : LOG_INFO;
157 xalloca(msg, char *, strlen (message) + 5);
159 strcpy (msg, message);
160 strcat (msg, ": %m");
164 vsyslog (priority, msg, args);
167 char *a1 = va_arg(args, char *);
168 char *a2 = va_arg(args, char *);
169 char *a3 = va_arg(args, char *);
170 char *a4 = va_arg(args, char *);
171 char *a5 = va_arg(args, char *);
172 char *a6 = va_arg(args, char *);
173 char *a7 = va_arg(args, char *);
174 char *a8 = va_arg(args, char *);
175 syslog (priority, msg, a1, a2, a3, a4, a5, a6, a7, a8);
182 vsyslog (priority, message, args);
185 char *a1 = va_arg(args, char *);
186 char *a2 = va_arg(args, char *);
187 char *a3 = va_arg(args, char *);
188 char *a4 = va_arg(args, char *);
189 char *a5 = va_arg(args, char *);
190 char *a6 = va_arg(args, char *);
191 char *a7 = va_arg(args, char *);
192 char *a8 = va_arg(args, char *);
193 syslog (priority, message, a1, a2, a3, a4, a5, a6, a7, a8);
205 if (error_print_progname)
206 (*error_print_progname) ();
210 if ( *message == '\n' )
212 fputc( '\n', stderr );
215 fprintf (stderr, "%s: ", program_name);
219 VA_START (args, message);
220 # if HAVE_VPRINTF || _LIBC
221 vfprintf (stderr, message, args);
223 _doprnt (message, args, stderr);
227 fprintf (stderr, message, a1, a2, a3, a4, a5, a6, a7, a8);
230 if (errnum && errnum != -1) {
231 char *tmps = strerror(errnum);
233 fprintf (stderr, ": %s", tmps);
236 fprintf (stderr, ": Error %d", errnum);
242 ++error_message_count;
248 * Calling error_init(1) causes error_build and error_complete to write
249 * to stderr without buffering. This is needed for the ticker dots to
252 void error_init(int mode)
256 case 0: /* stderr, buffered */
262 case 1: /* stderr, unbuffered */
268 case -1: /* syslogd */
272 #endif /* HAVE_SYSLOG */
276 /* Build an error message by appending MESSAGE, which is a printf-style
277 format string with optional args, to the existing error message (which may
278 be empty.) The completed error message is finally printed (and reset to
279 empty) by calling error_complete().
280 If an intervening call to error() occurs when a partially constructed
281 message exists, then, in an attempt to keep the messages in their proper
282 sequence, the partial message will be printed as-is (with a trailing
283 newline) before error() prints its message. */
288 error_build (const char *message, ...)
290 error_build (message, va_alist)
300 /* Make an initial guess for the size of any single message fragment. */
301 if (partial_message_size == 0)
303 partial_message_size_used = 0;
304 partial_message_size = 2048;
305 partial_message = MALLOC (partial_message_size);
308 if (partial_message_size - partial_message_size_used < 1024)
310 partial_message_size += 2048;
311 partial_message = REALLOC (partial_message, partial_message_size);
314 #if defined(VA_START)
315 VA_START (args, message);
316 #if HAVE_VSNPRINTF || _LIBC
319 n = vsnprintf (partial_message + partial_message_size_used,
320 partial_message_size - partial_message_size_used,
323 if (n < partial_message_size - partial_message_size_used)
325 partial_message_size_used += n;
329 partial_message_size += 2048;
330 partial_message = REALLOC (partial_message, partial_message_size);
333 vsprintf (partial_message + partial_message_size_used, message, args);
334 partial_message_size_used += strlen(partial_message+partial_message_size_used);
336 /* Attempt to catch memory overwrites... */
337 if (partial_message_size_used >= partial_message_size)
339 partial_message_size_used = 0;
340 error (PS_UNDEFINED, 0, "partial error message buffer overflow");
348 n = snprintf (partial_message + partial_message_size_used,
349 partial_message_size - partial_message_size_used,
350 message, a1, a2, a3, a4, a5, a6, a7, a8);
352 if (n < partial_message_size - partial_message_size_used)
354 partial_message_size_used += n;
358 partial_message_size += 2048;
359 partial_message = REALLOC (partial_message, partial_message_size);
362 sprintf (partial_message + partial_message_size_used, message, a1, a2, a3, a4, a5, a6, a7, a8);
364 /* Attempt to catch memory overwrites... */
365 if ((partial_message_size_used = strlen (partial_message)) >= partial_message_size)
367 partial_message_size_used = 0;
368 error (PS_UNDEFINED, 0, "partial error message buffer overflow");
373 if (use_stderr && partial_message_size_used != 0)
375 partial_message_size_used = 0;
376 fputs(partial_message, stderr);
380 /* Complete an error message by appending MESSAGE, which is a printf-style
381 format string with optional args, to the existing error message (which may
382 be empty.) The completed error message is then printed (and reset to
388 error_complete (int status, int errnum, const char *message, ...)
390 error_complete (status, errnum, message, va_alist)
402 /* Make an initial guess for the size of any single message fragment. */
403 if (partial_message_size == 0)
405 partial_message_size_used = 0;
406 partial_message_size = 2048;
407 partial_message = MALLOC (partial_message_size);
410 if (partial_message_size - partial_message_size_used < 1024)
412 partial_message_size += 2048;
413 partial_message = REALLOC (partial_message, partial_message_size);
416 #if defined(VA_START)
417 VA_START (args, message);
418 #if HAVE_VSNPRINTF || _LIBC
421 n = vsnprintf (partial_message + partial_message_size_used,
422 partial_message_size - partial_message_size_used,
425 if (n < partial_message_size - partial_message_size_used)
427 partial_message_size_used += n;
431 partial_message_size += 2048;
432 partial_message = REALLOC (partial_message, partial_message_size);
435 vsprintf (partial_message + partial_message_size_used, message, args);
436 partial_message_size_used += strlen(partial_message+partial_message_size_used);
438 /* Attempt to catch memory overwrites... */
439 if (partial_message_size_used >= partial_message_size)
441 partial_message_size_used = 0;
442 error (PS_UNDEFINED, 0, "partial error message buffer overflow");
450 n = snprintf (partial_message + partial_message_size_used,
451 partial_message_size - partial_message_size_used,
452 message, a1, a2, a3, a4, a5, a6, a7, a8);
454 if (n < partial_message_size - partial_message_size_used)
456 partial_message_size_used += n;
460 partial_message_size += 2048;
461 partial_message = REALLOC (partial_message, partial_message_size);
464 sprintf (partial_message + partial_message_size_used, message, a1, a2, a3, a4, a5, a6, a7, a8);
466 /* Attempt to catch memory overwrites... */
467 if ((partial_message_size_used = strlen (partial_message)) >= partial_message_size)
469 partial_message_size_used = 0;
470 error (PS_UNDEFINED, 0, "partial error message buffer overflow");
475 /* Finally... print it. */
476 partial_message_size_used = 0;
480 fputs(partial_message, stderr);
483 fprintf (stderr, ": %s", strerror (errnum));
488 ++error_message_count;
494 error (status, errnum, "%s", partial_message);
497 /* Sometimes we want to have at most one error per line. This
498 variable controls whether this mode is selected or not. */
499 int error_one_per_line;
503 error_at_line (int status, int errnum, const char *file_name,
504 unsigned int line_number, const char *message, ...)
506 error_at_line (status, errnum, file_name, line_number, message, va_alist)
509 const char *file_name;
510 unsigned int line_number;
519 if (error_one_per_line)
521 static const char *old_file_name;
522 static unsigned int old_line_number;
524 if (old_line_number == line_number &&
525 (file_name == old_file_name || !strcmp (old_file_name, file_name)))
526 /* Simply return and print nothing. */
529 old_file_name = file_name;
530 old_line_number = line_number;
533 if (error_print_progname)
534 (*error_print_progname) ();
538 if ( *message == '\n' )
540 fputc( '\n', stderr );
543 fprintf (stderr, "%s:", program_name);
546 if (file_name != NULL)
547 fprintf (stderr, "%s:%d: ", file_name, line_number);
550 VA_START (args, message);
551 # if HAVE_VPRINTF || _LIBC
552 vfprintf (stderr, message, args);
554 _doprnt (message, args, stderr);
558 fprintf (stderr, message, a1, a2, a3, a4, a5, a6, a7, a8);
561 ++error_message_count;
563 fprintf (stderr, ": %s", strerror (errnum));