-/* report.c -- report function for noninteractive utilities
+/** \file report.c report function for noninteractive utilities
*
* For license terms, see the file COPYING in this directory.
*
* This code is distantly descended from the error.c module written by
* David MacKenzie <djm@gnu.ai.mit.edu>. It was redesigned and
- * rewritten by Dave Bodenstab, then reseedesigned again by ESR, then
+ * rewritten by Dave Bodenstab, then redesigned again by ESR, then
* bludgeoned into submission for SunOS 4.1.3 by Chris Cheyney
* <cheyney@netcom.com>. It works even when the return from
* vprintf(3) is unreliable.
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
-
#include <stdio.h>
#include <errno.h>
-#if defined(HAVE_SYSLOG)
+#include <string.h>
#include <syslog.h>
-#endif
-
-#if HAVE_VPRINTF || HAVE_DOPRNT || _LIBC || HAVE_STDARG_H
-# if HAVE_STDARG_H
-# include <stdarg.h>
-# define VA_START(args, lastarg) va_start(args, lastarg)
-# else
-# include <varargs.h>
-# define VA_START(args, lastarg) va_start(args)
-# endif
-#else
-# define va_alist a1, a2, a3, a4, a5, a6, a7, a8
-# define va_dcl char *a1, *a2, *a3, *a4, *a5, *a6, *a7, *a8;
-#endif
-
-#if STDC_HEADERS || _LIBC
-# include <stdlib.h>
-# include <string.h>
-#else
-void exit ();
-#endif
+#include "gettext.h"
+#include "fetchmail.h"
-#include "i18n.h"
+#include <stdarg.h>
-#include "fetchmail.h"
#define MALLOC(n) xmalloc(n)
#define REALLOC(n,s) xrealloc(n,s)
-/* If NULL, report will flush stderr, then print on stderr the program
- name, a colon and a space. Otherwise, report will call this
- function without parameters instead. */
-void (*report_print_progname) (
-#if __STDC__ - 0
- void
-#endif
- );
-
-/* Used by report_build() and report_complete() to accumulate partial messages. */
+/* Used by report_build() and report_complete() to accumulate partial messages.
+ */
static unsigned int partial_message_size = 0;
static unsigned int partial_message_size_used = 0;
static char *partial_message;
-static unsigned use_stderr;
-static unsigned int use_syslog;
-
-/* This variable is incremented each time `report' is called. */
-unsigned int report_message_count;
-
-#ifdef _LIBC
-/* In the GNU C library, there is a predefined variable for this. */
-
-# define program_name program_invocation_name
-# include <errno.h>
-
-#else
+static int partial_suppress_tag = 0;
-/* The calling program should define program_name and set it to the
- name of the executing program. */
-extern char *program_name;
-
-# if !HAVE_STRERROR && !defined(strerror)
-char *strerror (int errnum)
-{
- extern char *sys_errlist[];
- extern int sys_nerr;
-
- if (errnum > 0 && errnum <= sys_nerr)
- return sys_errlist[errnum];
- return GT_("Unknown system error");
-}
-# endif /* HAVE_STRERROR */
-#endif /* _LIBC */
+static unsigned unbuffered;
+static unsigned int use_syslog;
/* Print the program name and error message MESSAGE, which is a printf-style
- format string with optional args.
- If ERRNUM is nonzero, print its corresponding system error message. */
-/* VARARGS */
-
-void
-#ifdef HAVE_STDARG_H
-report (FILE *errfp, const char *message, ...)
-#else
-report (FILE *errfp, message, va_alist)
- const char *message;
- va_dcl
-#endif
+ format string with optional args. */
+void report(FILE *errfp, const char *message, ...)
{
-#ifdef VA_START
va_list args;
-#endif
/* 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;
- report (errfp, 0, GT_("%s (log message incomplete)"), partial_message);
+ report (errfp, GT_("%s (log message incomplete)\n"), partial_message);
}
-#if defined(HAVE_SYSLOG)
if (use_syslog)
{
int priority;
-#ifdef VA_START
- VA_START (args, message);
-#endif
+ va_start (args, message);
priority = (errfp == stderr) ? LOG_ERR : LOG_INFO;
#ifdef HAVE_VSYSLOG
}
#endif
-#ifdef VA_START
va_end(args);
-#endif
}
- else
-#endif
+ else /* i. e. not using syslog */
{
- if (report_print_progname)
- (*report_print_progname) ();
- else
+ if ( *message == '\n' )
{
- fflush (errfp);
- if ( *message == '\n' )
- {
- fputc( '\n', errfp );
- ++message;
- }
- fprintf (errfp, "%s: ", program_name);
+ fputc( '\n', errfp );
+ ++message;
}
+ if (!partial_suppress_tag)
+ fprintf (errfp, "%s: ", program_name);
+ partial_suppress_tag = 0;
-#ifdef VA_START
- VA_START (args, message);
-# if HAVE_VPRINTF || _LIBC
+ va_start (args, message);
vfprintf (errfp, message, args);
-# else
- _doprnt (message, args, errfp);
-# endif
va_end (args);
-#else
- fprintf (errfp, message, a1, a2, a3, a4, a5, a6, a7, a8);
-#endif
fflush (errfp);
}
- ++report_message_count;
}
-\f
-/*
- * Calling report_init(1) causes error_build and error_complete to write
- * to errfp without buffering. This is needed for the ticker dots to
- * work correctly.
+
+/**
+ * Configure the report module. The output is set according to
+ * \a mode.
*/
-void report_init(int mode)
+void report_init(int mode /** 0: regular output, 1: unbuffered output, -1: syslog */)
{
switch(mode)
{
case 0: /* errfp, buffered */
default:
- use_stderr = FALSE;
+ unbuffered = FALSE;
use_syslog = FALSE;
break;
case 1: /* errfp, unbuffered */
- use_stderr = TRUE;
+ unbuffered = TRUE;
use_syslog = FALSE;
break;
-#ifdef HAVE_SYSLOG
case -1: /* syslogd */
- use_stderr = FALSE;
+ unbuffered = FALSE;
use_syslog = TRUE;
break;
-#endif /* HAVE_SYSLOG */
}
}
-\f
+
/* Build an report message by appending MESSAGE, which is a printf-style
format string with optional args, to the existing report message (which may
be empty.) The completed report message is finally printed (and reset to
newline) before report() prints its message. */
/* VARARGS */
-void
-#ifdef HAVE_STDARG_H
-report_build (FILE *errfp, const char *message, ...)
-#else
-report_build (FILE *errfp, message, va_alist)
- const char *message;
- va_dcl
-#endif
-{
-#ifdef VA_START
- va_list args;
- int n;
-#endif
-
+static void rep_ensuresize(void) {
/* 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 = 2048;
- partial_message = MALLOC (partial_message_size);
+ partial_message = (char *)MALLOC (partial_message_size);
}
else
if (partial_message_size - partial_message_size_used < 1024)
{
partial_message_size += 2048;
- partial_message = REALLOC (partial_message, partial_message_size);
+ partial_message = (char *)REALLOC (partial_message, partial_message_size);
}
+}
+
+static void report_vbuild(const char *message, va_list args)
+{
+ int n;
-#if defined(VA_START)
- VA_START (args, message);
-#if HAVE_VSNPRINTF || _LIBC
for ( ; ; )
{
- n = vsnprintf (partial_message + partial_message_size_used,
- partial_message_size - partial_message_size_used,
+ /*
+ * args has to be initialized before every call of vsnprintf(),
+ * because vsnprintf() invokes va_arg macro and thus args is
+ * undefined after the call.
+ */
+ 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)
+ /* output error, f. i. EILSEQ */
+ if (n < 0) break;
+
+ if (n >= 0
+ && (unsigned)n < partial_message_size - partial_message_size_used)
{
partial_message_size_used += n;
break;
}
partial_message_size += 2048;
- partial_message = REALLOC (partial_message, partial_message_size);
+ partial_message = (char *)REALLOC (partial_message, partial_message_size);
}
-#else
- vsprintf (partial_message + partial_message_size_used, message, args);
- partial_message_size_used += strlen(partial_message+partial_message_size_used);
+}
- /* Attempt to catch memory overwrites... */
- if (partial_message_size_used >= partial_message_size)
- {
- partial_message_size_used = 0;
- report (stderr, GT_("partial error message buffer overflow"));
- }
-#endif
- 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);
+void report_build (FILE *errfp, const char *message, ...)
+{
+ va_list args;
- if (n < partial_message_size - partial_message_size_used)
- {
- partial_message_size_used += n;
- break;
- }
+ rep_ensuresize();
- partial_message_size += 2048;
- partial_message = REALLOC (partial_message, partial_message_size);
- }
-#else
- sprintf (partial_message + partial_message_size_used, message, a1, a2, a3, a4, a5, a6, a7, a8);
+ va_start(args, message);
+ report_vbuild(message, args);
+ va_end(args);
- /* Attempt to catch memory overwrites... */
- if ((partial_message_size_used = strlen (partial_message)) >= partial_message_size)
+ if (unbuffered && partial_message_size_used != 0)
{
partial_message_size_used = 0;
- report (stderr, GT_("partial error message buffer overflow"));
+ fputs(partial_message, errfp);
}
-#endif
-#endif
+}
- if (use_stderr && partial_message_size_used != 0)
+void report_flush(FILE *errfp)
+{
+ if (partial_message_size_used != 0)
{
partial_message_size_used = 0;
- fputs(partial_message, errfp);
+ report(errfp, "%s", partial_message);
+ partial_suppress_tag = 1;
}
}
-\f
-/* Complete an report message by appending MESSAGE, which is a printf-style
+
+/* Complete a report message by appending MESSAGE, which is a printf-style
format string with optional args, to the existing report message (which may
be empty.) The completed report message is then printed (and reset to
empty.) */
/* VARARGS */
-
-void
-#ifdef HAVE_STDARG_H
-report_complete (FILE *errfp, const char *message, ...)
-#else
-report_complete (FILE *errfp, message, va_alist)
- const char *message;
- va_dcl
-#endif
+void report_complete (FILE *errfp, const char *message, ...)
{
-#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 = 2048;
- partial_message = MALLOC (partial_message_size);
- }
- else
- if (partial_message_size - partial_message_size_used < 1024)
- {
- partial_message_size += 2048;
- partial_message = REALLOC (partial_message, partial_message_size);
- }
-
-#if defined(VA_START)
- VA_START (args, message);
-#if HAVE_VSNPRINTF || _LIBC
- 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;
- }
+ rep_ensuresize();
- partial_message_size += 2048;
- partial_message = REALLOC (partial_message, partial_message_size);
- }
-#else
- vsprintf (partial_message + partial_message_size_used, message, args);
- partial_message_size_used += strlen(partial_message+partial_message_size_used);
-
- /* Attempt to catch memory overwrites... */
- if (partial_message_size_used >= partial_message_size)
- {
- partial_message_size_used = 0;
- report (stderr, GT_("partial error message buffer overflow"));
- }
-#endif
- 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 += 2048;
- partial_message = REALLOC (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;
- report (stderr, GT_("partial error message buffer overflow"));
- }
-#endif
-#endif
+ va_start(args, message);
+ report_vbuild(message, args);
+ va_end(args);
/* Finally... print it. */
partial_message_size_used = 0;
- if (use_stderr)
+ if (unbuffered)
{
fputs(partial_message, errfp);
fflush (errfp);
-
- ++report_message_count;
}
else
report(errfp, "%s", partial_message);
}
-\f
+
/* 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;
+static int error_one_per_line;
-void
-#ifdef HAVE_STDARG_H
-report_at_line (FILE *errfp, int errnum, const char *file_name,
+/* If errnum is nonzero, print its corresponding system error message. */
+void report_at_line (FILE *errfp, int errnum, const char *file_name,
unsigned int line_number, const char *message, ...)
-#else
-report_at_line (FILE *errfp, errnum, file_name, line_number, message, va_alist)
- int errnum;
- const char *file_name;
- unsigned int line_number;
- const char *message;
- va_dcl
-#endif
{
-#ifdef VA_START
va_list args;
-#endif
if (error_one_per_line)
{
old_line_number = line_number;
}
- if (report_print_progname)
- (*report_print_progname) ();
- else
+ fflush (errfp);
+ if ( *message == '\n' )
{
- fflush (errfp);
- if ( *message == '\n' )
- {
- fputc( '\n', errfp );
- ++message;
- }
- fprintf (errfp, "%s:", program_name);
+ fputc( '\n', errfp );
+ ++message;
}
+ fprintf (errfp, "%s:", program_name);
if (file_name != NULL)
- fprintf (errfp, "%s:%d: ", file_name, line_number);
+ fprintf (errfp, "%s:%u: ", file_name, line_number);
-#ifdef VA_START
- VA_START (args, message);
-# if HAVE_VPRINTF || _LIBC
+ va_start (args, message);
vfprintf (errfp, message, args);
-# else
- _doprnt (message, args, errfp);
-# endif
va_end (args);
-#else
- fprintf (errfp, message, a1, a2, a3, a4, a5, a6, a7, a8);
-#endif
- ++report_message_count;
if (errnum)
fprintf (errfp, ": %s", strerror (errnum));
putc ('\n', errfp);