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;
80 /* for now, send all error messages to stderr */
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;
95 # if !HAVE_STRERROR && !defined(strerror)
96 char *strerror (errnum)
99 extern char *sys_errlist[];
102 if (errnum > 0 && errnum <= sys_nerr)
103 return sys_errlist[errnum];
104 return _("Unknown system error");
106 # endif /* HAVE_STRERROR */
109 /* Print the program name and error message MESSAGE, which is a printf-style
110 format string with optional args.
111 If ERRNUM is nonzero, print its corresponding system error message.
112 Exit with status STATUS if it is nonzero. */
117 error (int status, int errnum, const char *message, ...)
119 error (status, errnum, message, va_alist)
130 /* If a partially built message exists, print it now so it's not lost. */
131 if (partial_message_size_used != 0)
133 partial_message_size_used = 0;
134 error (0, 0, _("%s (log message incomplete)"), partial_message);
137 #if defined(HAVE_SYSLOG)
143 VA_START (args, message);
145 priority = status? LOG_ALERT : errnum? LOG_ERR : LOG_INFO;
151 xalloca(msg, char *, strlen (message) + 5);
153 strcpy (msg, message);
154 strcat (msg, ": %m");
158 vsyslog (priority, msg, args);
161 char *a1 = va_arg(args, char *);
162 char *a2 = va_arg(args, char *);
163 char *a3 = va_arg(args, char *);
164 char *a4 = va_arg(args, char *);
165 char *a5 = va_arg(args, char *);
166 char *a6 = va_arg(args, char *);
167 char *a7 = va_arg(args, char *);
168 char *a8 = va_arg(args, char *);
169 syslog (priority, msg, a1, a2, a3, a4, a5, a6, a7, a8);
176 vsyslog (priority, message, args);
179 char *a1 = va_arg(args, char *);
180 char *a2 = va_arg(args, char *);
181 char *a3 = va_arg(args, char *);
182 char *a4 = va_arg(args, char *);
183 char *a5 = va_arg(args, char *);
184 char *a6 = va_arg(args, char *);
185 char *a7 = va_arg(args, char *);
186 char *a8 = va_arg(args, char *);
187 syslog (priority, message, a1, a2, a3, a4, a5, a6, a7, a8);
199 if (error_print_progname)
200 (*error_print_progname) ();
204 if ( *message == '\n' )
206 fputc( '\n', errfp );
209 fprintf (errfp, "%s: ", program_name);
213 VA_START (args, message);
214 # if HAVE_VPRINTF || _LIBC
215 vfprintf (errfp, message, args);
217 _doprnt (message, args, errfp);
221 fprintf (errfp, message, a1, a2, a3, a4, a5, a6, a7, a8);
224 if (errnum && errnum != -1) {
225 char *tmps = strerror(errnum);
227 fprintf (errfp, ": %s", tmps);
230 fprintf (errfp, _(": Error %d"), errnum);
236 ++error_message_count;
242 * Calling error_init(1) causes error_build and error_complete to write
243 * to errfp without buffering. This is needed for the ticker dots to
246 void error_init(int mode)
250 case 0: /* errfp, buffered */
256 case 1: /* errfp, unbuffered */
262 case -1: /* syslogd */
266 #endif /* HAVE_SYSLOG */
270 /* Build an error message by appending MESSAGE, which is a printf-style
271 format string with optional args, to the existing error message (which may
272 be empty.) The completed error message is finally printed (and reset to
273 empty) by calling error_complete().
274 If an intervening call to error() occurs when a partially constructed
275 message exists, then, in an attempt to keep the messages in their proper
276 sequence, the partial message will be printed as-is (with a trailing
277 newline) before error() prints its message. */
282 error_build (const char *message, ...)
284 error_build (message, va_alist)
294 /* Make an initial guess for the size of any single message fragment. */
295 if (partial_message_size == 0)
297 partial_message_size_used = 0;
298 partial_message_size = 2048;
299 partial_message = MALLOC (partial_message_size);
302 if (partial_message_size - partial_message_size_used < 1024)
304 partial_message_size += 2048;
305 partial_message = REALLOC (partial_message, partial_message_size);
308 #if defined(VA_START)
309 VA_START (args, message);
310 #if HAVE_VSNPRINTF || _LIBC
313 n = vsnprintf (partial_message + partial_message_size_used,
314 partial_message_size - partial_message_size_used,
317 if (n < partial_message_size - partial_message_size_used)
319 partial_message_size_used += n;
323 partial_message_size += 2048;
324 partial_message = REALLOC (partial_message, partial_message_size);
327 vsprintf (partial_message + partial_message_size_used, message, args);
328 partial_message_size_used += strlen(partial_message+partial_message_size_used);
330 /* Attempt to catch memory overwrites... */
331 if (partial_message_size_used >= partial_message_size)
333 partial_message_size_used = 0;
334 error (PS_UNDEFINED, 0, _("partial error message buffer overflow"));
342 n = snprintf (partial_message + partial_message_size_used,
343 partial_message_size - partial_message_size_used,
344 message, a1, a2, a3, a4, a5, a6, a7, a8);
346 if (n < partial_message_size - partial_message_size_used)
348 partial_message_size_used += n;
352 partial_message_size += 2048;
353 partial_message = REALLOC (partial_message, partial_message_size);
356 sprintf (partial_message + partial_message_size_used, message, a1, a2, a3, a4, a5, a6, a7, a8);
358 /* Attempt to catch memory overwrites... */
359 if ((partial_message_size_used = strlen (partial_message)) >= partial_message_size)
361 partial_message_size_used = 0;
362 error (PS_UNDEFINED, 0, _("partial error message buffer overflow"));
367 if (use_stderr && partial_message_size_used != 0)
369 partial_message_size_used = 0;
370 fputs(partial_message, errfp);
374 /* Complete an error message by appending MESSAGE, which is a printf-style
375 format string with optional args, to the existing error message (which may
376 be empty.) The completed error message is then printed (and reset to
382 error_complete (int status, int errnum, const char *message, ...)
384 error_complete (status, errnum, message, va_alist)
396 /* Make an initial guess for the size of any single message fragment. */
397 if (partial_message_size == 0)
399 partial_message_size_used = 0;
400 partial_message_size = 2048;
401 partial_message = MALLOC (partial_message_size);
404 if (partial_message_size - partial_message_size_used < 1024)
406 partial_message_size += 2048;
407 partial_message = REALLOC (partial_message, partial_message_size);
410 #if defined(VA_START)
411 VA_START (args, message);
412 #if HAVE_VSNPRINTF || _LIBC
415 n = vsnprintf (partial_message + partial_message_size_used,
416 partial_message_size - partial_message_size_used,
419 if (n < partial_message_size - partial_message_size_used)
421 partial_message_size_used += n;
425 partial_message_size += 2048;
426 partial_message = REALLOC (partial_message, partial_message_size);
429 vsprintf (partial_message + partial_message_size_used, message, args);
430 partial_message_size_used += strlen(partial_message+partial_message_size_used);
432 /* Attempt to catch memory overwrites... */
433 if (partial_message_size_used >= partial_message_size)
435 partial_message_size_used = 0;
436 error (PS_UNDEFINED, 0, _("partial error message buffer overflow"));
444 n = snprintf (partial_message + partial_message_size_used,
445 partial_message_size - partial_message_size_used,
446 message, a1, a2, a3, a4, a5, a6, a7, a8);
448 if (n < partial_message_size - partial_message_size_used)
450 partial_message_size_used += n;
454 partial_message_size += 2048;
455 partial_message = REALLOC (partial_message, partial_message_size);
458 sprintf (partial_message + partial_message_size_used, message, a1, a2, a3, a4, a5, a6, a7, a8);
460 /* Attempt to catch memory overwrites... */
461 if ((partial_message_size_used = strlen (partial_message)) >= partial_message_size)
463 partial_message_size_used = 0;
464 error (PS_UNDEFINED, 0, _("partial error message buffer overflow"));
469 /* Finally... print it. */
470 partial_message_size_used = 0;
474 fputs(partial_message, errfp);
477 fprintf (errfp, ": %s", strerror (errnum));
482 ++error_message_count;
488 error (status, errnum, "%s", partial_message);
491 /* Sometimes we want to have at most one error per line. This
492 variable controls whether this mode is selected or not. */
493 int error_one_per_line;
497 error_at_line (int status, int errnum, const char *file_name,
498 unsigned int line_number, const char *message, ...)
500 error_at_line (status, errnum, file_name, line_number, message, va_alist)
503 const char *file_name;
504 unsigned int line_number;
513 if (error_one_per_line)
515 static const char *old_file_name;
516 static unsigned int old_line_number;
518 if (old_line_number == line_number &&
519 (file_name == old_file_name || !strcmp (old_file_name, file_name)))
520 /* Simply return and print nothing. */
523 old_file_name = file_name;
524 old_line_number = line_number;
527 if (error_print_progname)
528 (*error_print_progname) ();
532 if ( *message == '\n' )
534 fputc( '\n', errfp );
537 fprintf (errfp, "%s:", program_name);
540 if (file_name != NULL)
541 fprintf (errfp, "%s:%d: ", file_name, line_number);
544 VA_START (args, message);
545 # if HAVE_VPRINTF || _LIBC
546 vfprintf (errfp, message, args);
548 _doprnt (message, args, errfp);
552 fprintf (errfp, message, a1, a2, a3, a4, a5, a6, a7, a8);
555 ++error_message_count;
557 fprintf (errfp, ": %s", strerror (errnum));