]> Pileus Git - ~andy/fetchmail/blobdiff - report.c
Minor bug fixes for socket.c
[~andy/fetchmail] / report.c
index cdded484726c7a34add13e2ffd36eecf6aeb9cf7..5d9abb73a8332bb48d0fc13dc4afd54494869016 100644 (file)
--- a/report.c
+++ b/report.c
@@ -1,4 +1,4 @@
-/* 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.  */
@@ -80,10 +70,8 @@ char *strerror (int errnum)
 #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, ...)
@@ -101,7 +89,7 @@ report (FILE *errfp, message, va_alist)
     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)
@@ -134,21 +122,17 @@ report (FILE *errfp, message, va_alist)
        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);
@@ -163,38 +147,36 @@ report (FILE *errfp, message, va_alist)
 #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
@@ -205,73 +187,86 @@ void report_init(int mode)
    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;
@@ -280,31 +275,30 @@ report_build (FILE *errfp, message, va_alist)
        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, ...)
@@ -316,100 +310,35 @@ report_complete (FILE *errfp, message, va_alist)
 {
 #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,
@@ -441,18 +370,13 @@ report_at_line (FILE *errfp, errnum, file_name, line_number, message, va_alist)
        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);
@@ -469,7 +393,6 @@ report_at_line (FILE *errfp, errnum, file_name, line_number, message, va_alist)
     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);