diff options
Diffstat (limited to 'report.c')
-rw-r--r-- | report.c | 271 |
1 files changed, 254 insertions, 17 deletions
@@ -22,6 +22,13 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #endif #include <stdio.h> +#include <errno.h> +#if defined(HAVE_SYSLOG) +#include <syslog.h> +#endif +#if defined(HAVE_ALLOCA_H) +#include <alloca.h> +#endif #if HAVE_VPRINTF || HAVE_DOPRNT || _LIBC # if __STDC__ @@ -43,6 +50,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ void exit (); #endif +#include "fetchmail.h" + #ifndef _ # define _(String) String #endif @@ -56,6 +65,11 @@ void (*error_print_progname) ( #endif ); +/* Used by error_build() and error_complete() to accumulate partial messages. */ +static unsigned int partial_message_size = 0; +static unsigned int partial_message_size_used = 0; +static char *partial_message; + /* This variable is incremented each time `error' is called. */ unsigned int error_message_count; @@ -112,40 +126,263 @@ error (status, errnum, message, va_alist) va_list args; #endif - if (error_print_progname) - (*error_print_progname) (); + /* If a partially built message exists, print it now so it's not lost. */ + if (partial_message_size_used != 0) + { + partial_message_size_used = 0; + error (0, 0, "%s (message incomplete)", partial_message); + } + +#if defined(HAVE_SYSLOG) + if (use_syslog) + { + int priority; + +# ifdef VA_START + VA_START (args, message); +# endif + priority = status? LOG_ALERT : errnum? LOG_ERR : LOG_INFO; + + if (errnum) + { + char *msg = alloca (strlen (message) + 5); + + strcpy (msg, message); + strcat (msg, ": %m"); + + errno = errnum; +# ifdef VA_START + vsyslog (priority, msg, args); + va_end (args); +# else + syslog (priority, msg, a1, a2, a3, a4, a5, a6, a7, a8); +# endif + } + else + { +# ifdef VA_START + vsyslog (priority, message, args); + va_end (args); +# else + syslog (priority, message, a1, a2, a3, a4, a5, a6, a7, a8); +# endif + } + } else +#endif { - fflush (stdout); - if ( *message == '\n' ) + if (error_print_progname) + (*error_print_progname) (); + else { - fputc( '\n', stderr ); - ++message; + fflush (stdout); + if ( *message == '\n' ) + { + fputc( '\n', stderr ); + ++message; + } + fprintf (stderr, "%s: ", program_name); } - fprintf (stderr, "%s: ", program_name); - } #ifdef VA_START - VA_START (args, message); + VA_START (args, message); # if HAVE_VPRINTF || _LIBC - vfprintf (stderr, message, args); + vfprintf (stderr, message, args); # else - _doprnt (message, args, stderr); + _doprnt (message, args, stderr); # endif - va_end (args); + va_end (args); #else - fprintf (stderr, message, a1, a2, a3, a4, a5, a6, a7, a8); + fprintf (stderr, message, a1, a2, a3, a4, a5, a6, a7, a8); #endif + if (errnum) + fprintf (stderr, ": %s", strerror (errnum)); + putc ('\n', stderr); + fflush (stderr); + } ++error_message_count; - if (errnum) - fprintf (stderr, ": %s", strerror (errnum)); - putc ('\n', stderr); - fflush (stderr); if (status) exit (status); } +/* Build an error message by appending MESSAGE, which is a printf-style + format string with optional args, to the existing error message (which may + be empty.) The completed error message is finally printed (and reset to + empty) by calling error_complete(). + If an intervening call to error() occurs when a partially constructed + message exists, then, in an attempt to keep the messages in their proper + sequence, the partial message will be printed as-is (with a trailing newline) + before error() prints its message. +/* VARARGS */ + +void +#if defined(VA_START) && __STDC__ +error_build (const char *message, ...) +#else +error_build (message, va_alist) + char *message; + va_dcl +#endif +{ +#ifdef VA_START + va_list args; + int n; +#endif + + /* Make an initial guess for the size of any single message fragment. */ + if (partial_message_size == 0) + { + partial_message_size_used = 0; + partial_message_size = 512; + partial_message = xmalloc (partial_message_size); + } + else + if (partial_message_size - partial_message_size_used < 256) + { + partial_message_size += 512; + partial_message = xrealloc (partial_message, partial_message_size); + } + +#if defined(VA_START) && (HAVE_VSNPRINTF || _LIBC) + VA_START (args, message); + for ( ; ; ) + { + n = vsnprintf (partial_message + partial_message_size_used, + partial_message_size - partial_message_size_used, + message, args); + + if (n < partial_message_size - partial_message_size_used) + { + partial_message_size_used += n; + break; + } + + partial_message_size += 512; + partial_message = xrealloc (partial_message, partial_message_size); + } + va_end (args); +#else +#if HAVE_SNPRINTF + for ( ; ; ) + { + n = snprintf (partial_message + partial_message_size_used, + partial_message_size - partial_message_size_used, + message, a1, a2, a3, a4, a5, a6, a7, a8); + + if (n < partial_message_size - partial_message_size_used) + { + partial_message_size_used += n; + break; + } + + partial_message_size += 512; + partial_message = xrealloc (partial_message, partial_message_size); + } +#else + sprintf (partial_message + partial_message_size_used, message, a1, a2, a3, a4, a5, a6, a7, a8); + + /* Attempt to catch memory overwrites... */ + if ((partial_message_size_used = strlen (partial_message)) >= partial_message_size) + { + partial_message_size_used = 0; + error (PS_UNDEFINED, 0, "partial error message buffer overflow"); + } +#endif +#endif +} + +/* Complete an error message by appending MESSAGE, which is a printf-style + format string with optional args, to the existing error message (which may + be empty.) The completed error message is then printed (and reset to + empty.) +/* VARARGS */ + +void +#if defined(VA_START) && __STDC__ +error_complete (int status, int errnum, const char *message, ...) +#else +error_complete (status, errnum, message, va_alist) + int status; + int errnum; + char *message; + va_dcl +#endif +{ +#ifdef VA_START + va_list args; + int n; +#endif + + /* Make an initial guess for the size of any single message fragment. */ + if (partial_message_size == 0) + { + partial_message_size_used = 0; + partial_message_size = 512; + partial_message = xmalloc (partial_message_size); + } + else + if (partial_message_size - partial_message_size_used < 256) + { + partial_message_size += 512; + partial_message = xrealloc (partial_message, partial_message_size); + } + +#if defined(VA_START) && (HAVE_VSNPRINTF || _LIBC) + VA_START (args, message); + for ( ; ; ) + { + n = vsnprintf (partial_message + partial_message_size_used, + partial_message_size - partial_message_size_used, + message, args); + + if (n < partial_message_size - partial_message_size_used) + { + partial_message_size_used += n; + break; + } + + partial_message_size += 512; + partial_message = xrealloc (partial_message, partial_message_size); + } + va_end (args); +#else +#if HAVE_SNPRINTF + for ( ; ; ) + { + n = snprintf (partial_message + partial_message_size_used, + partial_message_size - partial_message_size_used, + message, a1, a2, a3, a4, a5, a6, a7, a8); + + if (n < partial_message_size - partial_message_size_used) + { + partial_message_size_used += n; + break; + } + + partial_message_size += 512; + partial_message = xrealloc (partial_message, partial_message_size); + } +#else + sprintf (partial_message + partial_message_size_used, message, a1, a2, a3, a4, a5, a6, a7, a8); + + /* Attempt to catch memory overwrites... */ + if ((partial_message_size_used = strlen (partial_message)) >= partial_message_size) + { + partial_message_size_used = 0; + error (PS_UNDEFINED, 0, "partial error message buffer overflow"); + } +#endif +#endif + + /* Finally... print it. */ + if (partial_message_size_used != 0) + { + partial_message_size_used = 0; + error (status, errnum, "%s", partial_message); + } +} + /* Sometimes we want to have at most one error per line. This variable controls whether this mode is selected or not. */ int error_one_per_line; |