X-Git-Url: http://pileus.org/git/?a=blobdiff_plain;f=report.c;h=5d9abb73a8332bb48d0fc13dc4afd54494869016;hb=da989f7b8294e342572ec5f27f1a6f3f2b1fe56f;hp=3ea45852f61158185939932ea5f6a5d9e76d1510;hpb=5a653417508a814ece9f903f6f8474930251ef69;p=~andy%2Ffetchmail diff --git a/report.c b/report.c index 3ea45852..5d9abb73 100644 --- a/report.c +++ b/report.c @@ -1,10 +1,10 @@ -/* 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 . 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 * . It works even when the return from * vprintf(3) is unreliable. @@ -13,14 +13,16 @@ #ifdef HAVE_CONFIG_H # include "config.h" #endif - #include #include +#include #if defined(HAVE_SYSLOG) #include #endif +#include "i18n.h" +#include "fetchmail.h" -#if HAVE_VPRINTF || HAVE_DOPRNT || _LIBC || HAVE_STDARG_H +#if defined(HAVE_VPRINTF) || defined(HAVE_DOPRNT) || defined(_LIBC) || defined(HAVE_STDARG_H) # if HAVE_STDARG_H # include # define VA_START(args, lastarg) va_start(args, lastarg) @@ -33,37 +35,18 @@ # define va_dcl char *a1, *a2, *a3, *a4, *a5, *a6, *a7, *a8; #endif -#if STDC_HEADERS || _LIBC -# include -# include -#else -void exit (); -#endif - -#include "i18n.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; +static int partial_suppress_tag = 0; -/* This variable is incremented each time `report' is called. */ -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. */ @@ -73,10 +56,6 @@ unsigned int report_message_count; #else -/* 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) { @@ -91,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, ...) @@ -112,7 +89,7 @@ report (FILE *errfp, message, va_alist) 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) @@ -145,25 +122,21 @@ 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); -# if HAVE_VPRINTF || _LIBC +# if defined(HAVE_VPRINTF) || defined(_LIBC) vfprintf (errfp, message, args); # else _doprnt (message, args, errfp); @@ -174,38 +147,36 @@ report (FILE *errfp, message, va_alist) #endif fflush (errfp); } - ++report_message_count; } - -/* - * 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 */ } } - + /* 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 @@ -216,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 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); +} +#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; @@ -291,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; } } - -/* 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, ...) @@ -327,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 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; - } - - partial_message_size += 2048; - partial_message = REALLOC (partial_message, partial_message_size); - } + VA_START(args, message); + report_vbuild(message, args); + va_end(args); #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 + 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); } - + /* 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; +/* 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, @@ -452,25 +370,20 @@ 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:%d: ", file_name, line_number); + fprintf (errfp, "%s:%u: ", file_name, line_number); #ifdef VA_START VA_START (args, message); -# if HAVE_VPRINTF || _LIBC +# if defined(HAVE_VPRINTF) || defined(_LIBC) vfprintf (errfp, message, args); # else _doprnt (message, args, errfp); @@ -480,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);