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;
94 # ifndef strerror /* On some systems, strerror is a macro */
99 private_strerror (errnum)
102 extern char *sys_errlist[];
105 if (errnum > 0 && errnum <= sys_nerr)
106 return sys_errlist[errnum];
107 return _("Unknown system error");
109 # define strerror private_strerror
110 # endif /* HAVE_STRERROR */
113 /* Print the program name and error message MESSAGE, which is a printf-style
114 format string with optional args.
115 If ERRNUM is nonzero, print its corresponding system error message.
116 Exit with status STATUS if it is nonzero. */
121 error (int status, int errnum, const char *message, ...)
123 error (status, errnum, message, va_alist)
134 /* If a partially built message exists, print it now so it's not lost. */
135 if (partial_message_size_used != 0)
137 partial_message_size_used = 0;
138 error (0, 0, _("%s (log message incomplete)"), partial_message);
141 #if defined(HAVE_SYSLOG)
147 VA_START (args, message);
149 priority = status? LOG_ALERT : errnum? LOG_ERR : LOG_INFO;
155 xalloca(msg, char *, strlen (message) + 5);
157 strcpy (msg, message);
158 strcat (msg, ": %m");
162 vsyslog (priority, msg, args);
165 char *a1 = va_arg(args, char *);
166 char *a2 = va_arg(args, char *);
167 char *a3 = va_arg(args, char *);
168 char *a4 = va_arg(args, char *);
169 char *a5 = va_arg(args, char *);
170 char *a6 = va_arg(args, char *);
171 char *a7 = va_arg(args, char *);
172 char *a8 = va_arg(args, char *);
173 syslog (priority, msg, a1, a2, a3, a4, a5, a6, a7, a8);
180 vsyslog (priority, message, args);
183 char *a1 = va_arg(args, char *);
184 char *a2 = va_arg(args, char *);
185 char *a3 = va_arg(args, char *);
186 char *a4 = va_arg(args, char *);
187 char *a5 = va_arg(args, char *);
188 char *a6 = va_arg(args, char *);
189 char *a7 = va_arg(args, char *);
190 char *a8 = va_arg(args, char *);
191 syslog (priority, message, a1, a2, a3, a4, a5, a6, a7, a8);
203 if (error_print_progname)
204 (*error_print_progname) ();
208 if ( *message == '\n' )
210 fputc( '\n', stderr );
213 fprintf (stderr, "%s: ", program_name);
217 VA_START (args, message);
218 # if HAVE_VPRINTF || _LIBC
219 vfprintf (stderr, message, args);
221 _doprnt (message, args, stderr);
225 fprintf (stderr, message, a1, a2, a3, a4, a5, a6, a7, a8);
228 if (errnum && errnum != -1) {
229 char *tmps = strerror(errnum);
231 fprintf (stderr, ": %s", tmps);
234 fprintf (stderr, _(": Error %d"), errnum);
240 ++error_message_count;
246 * Calling error_init(1) causes error_build and error_complete to write
247 * to stderr without buffering. This is needed for the ticker dots to
250 void error_init(int mode)
254 case 0: /* stderr, buffered */
260 case 1: /* stderr, unbuffered */
266 case -1: /* syslogd */
270 #endif /* HAVE_SYSLOG */
274 /* Build an error message by appending MESSAGE, which is a printf-style
275 format string with optional args, to the existing error message (which may
276 be empty.) The completed error message is finally printed (and reset to
277 empty) by calling error_complete().
278 If an intervening call to error() occurs when a partially constructed
279 message exists, then, in an attempt to keep the messages in their proper
280 sequence, the partial message will be printed as-is (with a trailing
281 newline) before error() prints its message. */
286 error_build (const char *message, ...)
288 error_build (message, va_alist)
298 /* Make an initial guess for the size of any single message fragment. */
299 if (partial_message_size == 0)
301 partial_message_size_used = 0;
302 partial_message_size = 2048;
303 partial_message = MALLOC (partial_message_size);
306 if (partial_message_size - partial_message_size_used < 1024)
308 partial_message_size += 2048;
309 partial_message = REALLOC (partial_message, partial_message_size);
312 #if defined(VA_START)
313 VA_START (args, message);
314 #if HAVE_VSNPRINTF || _LIBC
317 n = vsnprintf (partial_message + partial_message_size_used,
318 partial_message_size - partial_message_size_used,
321 if (n < partial_message_size - partial_message_size_used)
323 partial_message_size_used += n;
327 partial_message_size += 2048;
328 partial_message = REALLOC (partial_message, partial_message_size);
331 vsprintf (partial_message + partial_message_size_used, message, args);
332 partial_message_size_used += strlen(partial_message+partial_message_size_used);
334 /* Attempt to catch memory overwrites... */
335 if (partial_message_size_used >= partial_message_size)
337 partial_message_size_used = 0;
338 error (PS_UNDEFINED, 0, _("partial error message buffer overflow"));
346 n = snprintf (partial_message + partial_message_size_used,
347 partial_message_size - partial_message_size_used,
348 message, a1, a2, a3, a4, a5, a6, a7, a8);
350 if (n < partial_message_size - partial_message_size_used)
352 partial_message_size_used += n;
356 partial_message_size += 2048;
357 partial_message = REALLOC (partial_message, partial_message_size);
360 sprintf (partial_message + partial_message_size_used, message, a1, a2, a3, a4, a5, a6, a7, a8);
362 /* Attempt to catch memory overwrites... */
363 if ((partial_message_size_used = strlen (partial_message)) >= partial_message_size)
365 partial_message_size_used = 0;
366 error (PS_UNDEFINED, 0, _("partial error message buffer overflow"));
371 if (use_stderr && partial_message_size_used != 0)
373 partial_message_size_used = 0;
374 fputs(partial_message, stderr);
378 /* Complete an error message by appending MESSAGE, which is a printf-style
379 format string with optional args, to the existing error message (which may
380 be empty.) The completed error message is then printed (and reset to
386 error_complete (int status, int errnum, const char *message, ...)
388 error_complete (status, errnum, message, va_alist)
400 /* Make an initial guess for the size of any single message fragment. */
401 if (partial_message_size == 0)
403 partial_message_size_used = 0;
404 partial_message_size = 2048;
405 partial_message = MALLOC (partial_message_size);
408 if (partial_message_size - partial_message_size_used < 1024)
410 partial_message_size += 2048;
411 partial_message = REALLOC (partial_message, partial_message_size);
414 #if defined(VA_START)
415 VA_START (args, message);
416 #if HAVE_VSNPRINTF || _LIBC
419 n = vsnprintf (partial_message + partial_message_size_used,
420 partial_message_size - partial_message_size_used,
423 if (n < partial_message_size - partial_message_size_used)
425 partial_message_size_used += n;
429 partial_message_size += 2048;
430 partial_message = REALLOC (partial_message, partial_message_size);
433 vsprintf (partial_message + partial_message_size_used, message, args);
434 partial_message_size_used += strlen(partial_message+partial_message_size_used);
436 /* Attempt to catch memory overwrites... */
437 if (partial_message_size_used >= partial_message_size)
439 partial_message_size_used = 0;
440 error (PS_UNDEFINED, 0, _("partial error message buffer overflow"));
448 n = snprintf (partial_message + partial_message_size_used,
449 partial_message_size - partial_message_size_used,
450 message, a1, a2, a3, a4, a5, a6, a7, a8);
452 if (n < partial_message_size - partial_message_size_used)
454 partial_message_size_used += n;
458 partial_message_size += 2048;
459 partial_message = REALLOC (partial_message, partial_message_size);
462 sprintf (partial_message + partial_message_size_used, message, a1, a2, a3, a4, a5, a6, a7, a8);
464 /* Attempt to catch memory overwrites... */
465 if ((partial_message_size_used = strlen (partial_message)) >= partial_message_size)
467 partial_message_size_used = 0;
468 error (PS_UNDEFINED, 0, _("partial error message buffer overflow"));
473 /* Finally... print it. */
474 partial_message_size_used = 0;
478 fputs(partial_message, stderr);
481 fprintf (stderr, ": %s", strerror (errnum));
486 ++error_message_count;
492 error (status, errnum, "%s", partial_message);
495 /* Sometimes we want to have at most one error per line. This
496 variable controls whether this mode is selected or not. */
497 int error_one_per_line;
501 error_at_line (int status, int errnum, const char *file_name,
502 unsigned int line_number, const char *message, ...)
504 error_at_line (status, errnum, file_name, line_number, message, va_alist)
507 const char *file_name;
508 unsigned int line_number;
517 if (error_one_per_line)
519 static const char *old_file_name;
520 static unsigned int old_line_number;
522 if (old_line_number == line_number &&
523 (file_name == old_file_name || !strcmp (old_file_name, file_name)))
524 /* Simply return and print nothing. */
527 old_file_name = file_name;
528 old_line_number = line_number;
531 if (error_print_progname)
532 (*error_print_progname) ();
536 if ( *message == '\n' )
538 fputc( '\n', stderr );
541 fprintf (stderr, "%s:", program_name);
544 if (file_name != NULL)
545 fprintf (stderr, "%s:%d: ", file_name, line_number);
548 VA_START (args, message);
549 # if HAVE_VPRINTF || _LIBC
550 vfprintf (stderr, message, args);
552 _doprnt (message, args, stderr);
556 fprintf (stderr, message, a1, a2, a3, a4, a5, a6, a7, a8);
559 ++error_message_count;
561 fprintf (stderr, ": %s", strerror (errnum));