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 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;
75 static unsigned int use_syslog;
77 /* This variable is incremented each time `error' is called. */
78 unsigned int error_message_count;
82 /* In the GNU C library, there is a predefined variable for this. */
84 # define program_name program_invocation_name
89 /* The calling program should define program_name and set it to the
90 name of the executing program. */
91 extern char *program_name;
93 # if !HAVE_STRERROR && !defined(strerror)
94 char *strerror (errnum)
97 extern char *sys_errlist[];
100 if (errnum > 0 && errnum <= sys_nerr)
101 return sys_errlist[errnum];
102 return _("Unknown system error");
104 # endif /* HAVE_STRERROR */
107 /* Print the program name and error message MESSAGE, which is a printf-style
108 format string with optional args.
109 If ERRNUM is nonzero, print its corresponding system error message.
110 Exit with status STATUS if it is nonzero. */
115 error (int status, int errnum, const char *message, ...)
117 error (status, errnum, message, va_alist)
128 /* If a partially built message exists, print it now so it's not lost. */
129 if (partial_message_size_used != 0)
131 partial_message_size_used = 0;
132 error (0, 0, _("%s (log message incomplete)"), partial_message);
135 #if defined(HAVE_SYSLOG)
141 VA_START (args, message);
143 priority = status? LOG_ALERT : errnum? LOG_ERR : LOG_INFO;
149 xalloca(msg, char *, strlen (message) + 5);
151 strcpy (msg, message);
152 strcat (msg, ": %m");
156 vsyslog (priority, msg, args);
159 char *a1 = va_arg(args, char *);
160 char *a2 = va_arg(args, char *);
161 char *a3 = va_arg(args, char *);
162 char *a4 = va_arg(args, char *);
163 char *a5 = va_arg(args, char *);
164 char *a6 = va_arg(args, char *);
165 char *a7 = va_arg(args, char *);
166 char *a8 = va_arg(args, char *);
167 syslog (priority, msg, a1, a2, a3, a4, a5, a6, a7, a8);
174 vsyslog (priority, message, args);
177 char *a1 = va_arg(args, char *);
178 char *a2 = va_arg(args, char *);
179 char *a3 = va_arg(args, char *);
180 char *a4 = va_arg(args, char *);
181 char *a5 = va_arg(args, char *);
182 char *a6 = va_arg(args, char *);
183 char *a7 = va_arg(args, char *);
184 char *a8 = va_arg(args, char *);
185 syslog (priority, message, a1, a2, a3, a4, a5, a6, a7, a8);
197 if (error_print_progname)
198 (*error_print_progname) ();
202 if ( *message == '\n' )
204 fputc( '\n', stderr );
207 fprintf (stderr, "%s: ", program_name);
211 VA_START (args, message);
212 # if HAVE_VPRINTF || _LIBC
213 vfprintf (stderr, message, args);
215 _doprnt (message, args, stderr);
219 fprintf (stderr, message, a1, a2, a3, a4, a5, a6, a7, a8);
222 if (errnum && errnum != -1) {
223 char *tmps = strerror(errnum);
225 fprintf (stderr, ": %s", tmps);
228 fprintf (stderr, _(": Error %d"), errnum);
234 ++error_message_count;
240 * Calling error_init(1) causes error_build and error_complete to write
241 * to stderr without buffering. This is needed for the ticker dots to
244 void error_init(int mode)
248 case 0: /* stderr, buffered */
254 case 1: /* stderr, unbuffered */
260 case -1: /* syslogd */
264 #endif /* HAVE_SYSLOG */
268 /* Build an error message by appending MESSAGE, which is a printf-style
269 format string with optional args, to the existing error message (which may
270 be empty.) The completed error message is finally printed (and reset to
271 empty) by calling error_complete().
272 If an intervening call to error() occurs when a partially constructed
273 message exists, then, in an attempt to keep the messages in their proper
274 sequence, the partial message will be printed as-is (with a trailing
275 newline) before error() prints its message. */
280 error_build (const char *message, ...)
282 error_build (message, va_alist)
292 /* Make an initial guess for the size of any single message fragment. */
293 if (partial_message_size == 0)
295 partial_message_size_used = 0;
296 partial_message_size = 2048;
297 partial_message = MALLOC (partial_message_size);
300 if (partial_message_size - partial_message_size_used < 1024)
302 partial_message_size += 2048;
303 partial_message = REALLOC (partial_message, partial_message_size);
306 #if defined(VA_START)
307 VA_START (args, message);
308 #if HAVE_VSNPRINTF || _LIBC
311 n = vsnprintf (partial_message + partial_message_size_used,
312 partial_message_size - partial_message_size_used,
315 if (n < partial_message_size - partial_message_size_used)
317 partial_message_size_used += n;
321 partial_message_size += 2048;
322 partial_message = REALLOC (partial_message, partial_message_size);
325 vsprintf (partial_message + partial_message_size_used, message, args);
326 partial_message_size_used += strlen(partial_message+partial_message_size_used);
328 /* Attempt to catch memory overwrites... */
329 if (partial_message_size_used >= partial_message_size)
331 partial_message_size_used = 0;
332 error (PS_UNDEFINED, 0, _("partial error message buffer overflow"));
340 n = snprintf (partial_message + partial_message_size_used,
341 partial_message_size - partial_message_size_used,
342 message, a1, a2, a3, a4, a5, a6, a7, a8);
344 if (n < partial_message_size - partial_message_size_used)
346 partial_message_size_used += n;
350 partial_message_size += 2048;
351 partial_message = REALLOC (partial_message, partial_message_size);
354 sprintf (partial_message + partial_message_size_used, message, a1, a2, a3, a4, a5, a6, a7, a8);
356 /* Attempt to catch memory overwrites... */
357 if ((partial_message_size_used = strlen (partial_message)) >= partial_message_size)
359 partial_message_size_used = 0;
360 error (PS_UNDEFINED, 0, _("partial error message buffer overflow"));
365 if (use_stderr && partial_message_size_used != 0)
367 partial_message_size_used = 0;
368 fputs(partial_message, stderr);
372 /* Complete an error message by appending MESSAGE, which is a printf-style
373 format string with optional args, to the existing error message (which may
374 be empty.) The completed error message is then printed (and reset to
380 error_complete (int status, int errnum, const char *message, ...)
382 error_complete (status, errnum, message, va_alist)
394 /* Make an initial guess for the size of any single message fragment. */
395 if (partial_message_size == 0)
397 partial_message_size_used = 0;
398 partial_message_size = 2048;
399 partial_message = MALLOC (partial_message_size);
402 if (partial_message_size - partial_message_size_used < 1024)
404 partial_message_size += 2048;
405 partial_message = REALLOC (partial_message, partial_message_size);
408 #if defined(VA_START)
409 VA_START (args, message);
410 #if HAVE_VSNPRINTF || _LIBC
413 n = vsnprintf (partial_message + partial_message_size_used,
414 partial_message_size - partial_message_size_used,
417 if (n < partial_message_size - partial_message_size_used)
419 partial_message_size_used += n;
423 partial_message_size += 2048;
424 partial_message = REALLOC (partial_message, partial_message_size);
427 vsprintf (partial_message + partial_message_size_used, message, args);
428 partial_message_size_used += strlen(partial_message+partial_message_size_used);
430 /* Attempt to catch memory overwrites... */
431 if (partial_message_size_used >= partial_message_size)
433 partial_message_size_used = 0;
434 error (PS_UNDEFINED, 0, _("partial error message buffer overflow"));
442 n = snprintf (partial_message + partial_message_size_used,
443 partial_message_size - partial_message_size_used,
444 message, a1, a2, a3, a4, a5, a6, a7, a8);
446 if (n < partial_message_size - partial_message_size_used)
448 partial_message_size_used += n;
452 partial_message_size += 2048;
453 partial_message = REALLOC (partial_message, partial_message_size);
456 sprintf (partial_message + partial_message_size_used, message, a1, a2, a3, a4, a5, a6, a7, a8);
458 /* Attempt to catch memory overwrites... */
459 if ((partial_message_size_used = strlen (partial_message)) >= partial_message_size)
461 partial_message_size_used = 0;
462 error (PS_UNDEFINED, 0, _("partial error message buffer overflow"));
467 /* Finally... print it. */
468 partial_message_size_used = 0;
472 fputs(partial_message, stderr);
475 fprintf (stderr, ": %s", strerror (errnum));
480 ++error_message_count;
486 error (status, errnum, "%s", partial_message);
489 /* Sometimes we want to have at most one error per line. This
490 variable controls whether this mode is selected or not. */
491 int error_one_per_line;
495 error_at_line (int status, int errnum, const char *file_name,
496 unsigned int line_number, const char *message, ...)
498 error_at_line (status, errnum, file_name, line_number, message, va_alist)
501 const char *file_name;
502 unsigned int line_number;
511 if (error_one_per_line)
513 static const char *old_file_name;
514 static unsigned int old_line_number;
516 if (old_line_number == line_number &&
517 (file_name == old_file_name || !strcmp (old_file_name, file_name)))
518 /* Simply return and print nothing. */
521 old_file_name = file_name;
522 old_line_number = line_number;
525 if (error_print_progname)
526 (*error_print_progname) ();
530 if ( *message == '\n' )
532 fputc( '\n', stderr );
535 fprintf (stderr, "%s:", program_name);
538 if (file_name != NULL)
539 fprintf (stderr, "%s:%d: ", file_name, line_number);
542 VA_START (args, message);
543 # if HAVE_VPRINTF || _LIBC
544 vfprintf (stderr, message, args);
546 _doprnt (message, args, stderr);
550 fprintf (stderr, message, a1, a2, a3, a4, a5, a6, a7, a8);
553 ++error_message_count;
555 fprintf (stderr, ": %s", strerror (errnum));