aboutsummaryrefslogtreecommitdiffstats
path: root/report.c
diff options
context:
space:
mode:
Diffstat (limited to 'report.c')
-rw-r--r--report.c271
1 files changed, 254 insertions, 17 deletions
diff --git a/report.c b/report.c
index 19fb3f45..3e973c84 100644
--- a/report.c
+++ b/report.c
@@ -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;