-/* 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.
*
#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. */
-static void (*report_print_progname) (
-#if __STDC__ - 0
- void
-#endif
- );
-
/* 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;
+static int partial_suppress_tag = 0;
-/* This variable is incremented each time `report' is called. */
-static unsigned int report_message_count;
+static unsigned unbuffered;
+static unsigned int use_syslog;
#ifdef _LIBC
/* In the GNU C library, there is a predefined variable for this. */
#endif /* _LIBC */
/* 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. */
+ format string with optional args. */
/* VARARGS */
-
void
#ifdef HAVE_STDARG_H
report (FILE *errfp, const char *message, ...)
if (partial_message_size_used != 0)
{
partial_message_size_used = 0;
- report (errfp, GT_("%s (log message incomplete)"), partial_message);
+ report (errfp, GT_("%s (log message incomplete)\n"), partial_message);
}
#if defined(HAVE_SYSLOG)
va_end(args);
#endif
}
- else
+ else /* i. e. not using syslog */
#endif
{
- 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);
#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)
{
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);
}
+}
+
+#ifdef HAVE_STDARG_H
+static void report_vbuild(const char *message, va_list args)
+{
+ int n;
-#if defined(VA_START)
- VA_START (args, message);
-#if defined(HAVE_VSNPRINTF) || defined(_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);
+}
+#endif
- /* 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"));
- }
+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
- va_end (args);
+{
+#ifdef VA_START
+ va_list args;
+#else
+ int n;
+#endif
+
+ rep_ensuresize();
+
+#if defined(VA_START)
+ VA_START(args, message);
+ report_vbuild(message, args);
+ 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)
+ /* 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);
}
-#else
- sprintf (partial_message + partial_message_size_used, message, a1, a2, a3, a4, a5, a6, a7, a8);
+#endif
- /* 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 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, ...)
{
#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);
- }
+ rep_ensuresize();
#if defined(VA_START)
- VA_START (args, message);
-#if defined(HAVE_VSNPRINTF) || defined(_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;
- }
-
- 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);
+ VA_START(args, message);
+ report_vbuild(message, args);
+ 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
+ report_build(errfp, message, a1, a2, a3, a4, a5, a6, a7, a8);
#endif
/* 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. */
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,
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:%u: ", file_name, line_number);
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);