-/* 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.
*
#include <stdio.h>
#include <errno.h>
#include <string.h>
-#if defined(HAVE_SYSLOG)
#include <syslog.h>
-#endif
-#include "i18n.h"
+#include "gettext.h"
#include "fetchmail.h"
-#if defined(HAVE_VPRINTF) || defined(HAVE_DOPRNT) || defined(_LIBC) || defined(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
+#include <stdarg.h>
#define MALLOC(n) xmalloc(n)
#define REALLOC(n,s) xrealloc(n,s)
static unsigned int partial_message_size = 0;
static unsigned int partial_message_size_used = 0;
static char *partial_message;
+static int partial_suppress_tag = 0;
+
static unsigned unbuffered;
static unsigned int use_syslog;
-/* This variable is incremented each time `report' is called. */
-static 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
-
-# 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 */
-
/* Print the program name and error message MESSAGE, which is a printf-style
format string with optional args. */
-/* 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
+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)
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 /* i. e. not using syslog */
-#endif
{
- fflush (errfp);
if ( *message == '\n' )
{
fputc( '\n', errfp );
++message;
}
- fprintf (errfp, "%s: ", program_name);
+ if (!partial_suppress_tag)
+ fprintf (errfp, "%s: ", program_name);
+ partial_suppress_tag = 0;
-#ifdef VA_START
- VA_START (args, message);
-# if defined(HAVE_VPRINTF) || defined(_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 report_build and report_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)
{
use_syslog = FALSE;
break;
-#ifdef HAVE_SYSLOG
case -1: /* syslogd */
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
}
}
-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
+static void report_vbuild(const char *message, va_list args)
{
-#ifdef VA_START
- va_list args;
int n;
-#endif
- rep_ensuresize();
-
-#if defined(VA_START)
for ( ; ; )
{
/*
* because vsnprintf() invokes va_arg macro and thus args is
* undefined after the call.
*/
- VA_START(args, message);
n = vsnprintf (partial_message + partial_message_size_used, partial_message_size - partial_message_size_used,
message, args);
- va_end (args);
+
+ /* output error, f. i. EILSEQ */
+ if (n < 0) break;
if (n >= 0
&& (unsigned)n < partial_message_size - partial_message_size_used)
partial_message_size += 2048;
partial_message = (char *)REALLOC (partial_message, partial_message_size);
}
-#else
- 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 >= 0
- && (unsigned)n < partial_message_size - partial_message_size_used)
- {
- partial_message_size_used += n;
- break;
- }
+void report_build (FILE *errfp, const char *message, ...)
+{
+ va_list args;
- partial_message_size += 2048;
- partial_message = REALLOC (partial_message, partial_message_size);
- }
-#endif
+ rep_ensuresize();
+
+ va_start(args, message);
+ report_vbuild(message, args);
+ va_end(args);
if (unbuffered && partial_message_size_used != 0)
{
fputs(partial_message, errfp);
}
}
-\f
+
+void report_flush(FILE *errfp)
+{
+ if (partial_message_size_used != 0)
+ {
+ partial_message_size_used = 0;
+ report(errfp, "%s", partial_message);
+ partial_suppress_tag = 1;
+ }
+}
+
/* 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
rep_ensuresize();
-#if defined(VA_START)
- for ( ; ; )
- {
- VA_START(args, message);
- n = vsnprintf (partial_message + partial_message_size_used,
- partial_message_size - partial_message_size_used,
- message, args);
- va_end(args);
-
- /* old glibc versions return -1 for truncation */
- if (n >= 0
- && (unsigned)n < partial_message_size - partial_message_size_used)
- {
- partial_message_size_used += n;
- break;
- }
-
- partial_message_size += 2048;
- partial_message = (char *)REALLOC (partial_message, partial_message_size);
- }
-#else
- 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 >= 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);
- }
-#endif
+ va_start(args, message);
+ report_vbuild(message, args);
+ va_end(args);
/* Finally... print it. */
partial_message_size_used = 0;
{
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. */
static int error_one_per_line;
/* If errnum is nonzero, print its corresponding system error message. */
-void
-#ifdef HAVE_STDARG_H
-report_at_line (FILE *errfp, int errnum, const char *file_name,
+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)
{
if (file_name != NULL)
fprintf (errfp, "%s:%u: ", file_name, line_number);
-#ifdef VA_START
- VA_START (args, message);
-# if defined(HAVE_VPRINTF) || defined(_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);