aboutsummaryrefslogtreecommitdiffstats
path: root/design-notes.html
Commit message (Expand)AuthorAgeFilesLines
* Update documentation.Matthias Andree2019-08-191-7/+5
* Fix typo repsonsible -> responsible.Matthias Andree2012-11-061-1/+1
* Bless readonly mailboxes for --keep.Matthias Andree2006-01-231-5/+6
* Add missing apostrophe in 's-Genitive.Matthias Andree2005-09-081-1/+1
* Enable Date replacement.Matthias Andree2005-08-281-2/+2
* Add security thoughts.Matthias Andree2005-07-201-0/+17
* Add new design notes document.Matthias Andree2005-07-201-0/+112
* Rename design-notes.html to esrs-design-notes.html. Remove ~esr/ path from li...Matthias Andree2005-07-201-763/+0
* Remove RFCs from the trunk, since we don't distribute them anyways. All of th...Graham Wilson2004-11-291-0/+10
* Version bump.Eric S. Raymond2003-02-281-3/+3
* Remove -oem from sendmail options.Eric S. Raymond2003-01-171-3/+3
* XML headers everywhere.Eric S. Raymond2002-07-301-2/+3
* XML conversionEric S. Raymond2002-07-281-467/+653
* Cleanup.Eric S. Raymond2002-07-281-143/+144
* History fix.Eric S. Raymond2002-06-031-7/+7
* Expose the ESMTP name and password options.Eric S. Raymond2002-03-101-7/+9
* HMH's latest round of fixes.Eric S. Raymond2001-10-011-3/+3
* Must solve that damn linking problem next.Eric S. Raymond2001-07-311-8/+12
* Implemented fetchdomains.Eric S. Raymond2001-06-241-6/+3
* Correction, 1123 doesn't demand this.Eric S. Raymond2001-03-111-6/+6
* Added 1508.Eric S. Raymond2001-03-071-2/+4
* 2001 update.Eric S. Raymond2001-02-111-4/+4
* Ready to ship, but no ATRN.Eric S. Raymond2001-02-071-4/+7
* Ready to ship a gold version.Eric S. Raymond2000-11-261-5/+7
* Added some future standards.Eric S. Raymond2000-08-051-2/+7
* Ready to merge in Julian Haight's changes.Eric S. Raymond2000-06-071-3/+4
* Typo fix.Eric S. Raymond2000-04-041-3/+3
* Corrected the RFC list.Eric S. Raymond2000-04-041-7/+5
* Fix an incorrect anchor number.Eric S. Raymond2000-04-041-3/+3
* Take note of anmother RFC.Eric S. Raymond2000-03-221-4/+6
* Implemented support for RFC2177 IDLE command.Eric S. Raymond2000-03-061-2/+6
* LinuxWorld hacks.Eric S. Raymond2000-02-051-2/+6
* Typo fix.Eric S. Raymond2000-01-081-4/+2
* Cleanup patches from Gunther Leber.Eric S. Raymond2000-01-031-3/+3
* IPv6 patches.Eric S. Raymond1999-12-191-8/+2
* Prevent Pehr Anderson's goof.Eric S. Raymond1999-09-261-4/+10
* CRAM-MD5 authentication support a la RFC2195.Eric S. Raymond1999-06-081-2/+4
* Take official noitice of RFC2449.Eric S. Raymond1999-05-161-2/+4
* Added bouncemail option.Eric S. Raymond1999-02-071-8/+9
* This version is good.Eric S. Raymond1999-01-011-6/+6
* No 1894.Eric S. Raymond1998-12-301-2/+4
* Internationalization support via GNU gettext().Eric S. Raymond1998-11-261-7/+19
* *** empty log message ***Eric S. Raymond1998-11-221-6/+5
* Corrected RFC URLs.Eric S. Raymond1998-11-221-36/+36
* Added LMTP support.Eric S. Raymond1998-11-071-2/+4
* Fix properties editing.Eric S. Raymond1998-10-291-2/+4
* Correct RFC URLs.Eric S. Raymond1998-08-111-38/+72
* Added postmaster option.Eric S. Raymond1998-07-201-2/+4
* Version bump.Eric S. Raymond1998-07-011-8/+8
* Enrico Musio's IP-checkalias patch.Eric S. Raymond1998-06-291-4/+4
ss="cm"> * * 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 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> #include <string.h> #if defined(HAVE_SYSLOG) #include <syslog.h> #endif #include "i18n.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 #define MALLOC(n) xmalloc(n) #define REALLOC(n,s) xrealloc(n,s) /* 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 int partial_suppress_tag = 0; /* default size for the allocation of the report buffer */ const size_t defaultsize = 4096; static unsigned unbuffered; static unsigned int use_syslog; #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 { #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, 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 priority = (errfp == stderr) ? LOG_ERR : LOG_INFO; #ifdef HAVE_VSYSLOG vsyslog (priority, message, args); #else { char *a1 = va_arg(args, char *); char *a2 = va_arg(args, char *); char *a3 = va_arg(args, char *); char *a4 = va_arg(args, char *); char *a5 = va_arg(args, char *); char *a6 = va_arg(args, char *); char *a7 = va_arg(args, char *); char *a8 = va_arg(args, char *); syslog (priority, message, a1, a2, a3, a4, a5, a6, a7, a8); } #endif #ifdef VA_START va_end(args); #endif } else /* i. e. not using syslog */ #endif { if ( *message == '\n' ) { 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 defined(HAVE_VPRINTF) || defined(_LIBC) 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); } } /** * Configure the report module. The output is set according to * \a mode. */ void report_init(int mode /** 0: regular output, 1: unbuffered output, -1: syslog */) { switch(mode) { case 0: /* errfp, buffered */ default: unbuffered = FALSE; use_syslog = FALSE; break; case 1: /* errfp, unbuffered */ unbuffered = TRUE; use_syslog = FALSE; break; #ifdef HAVE_SYSLOG case -1: /* syslogd */ unbuffered = FALSE; use_syslog = TRUE; break; #endif /* HAVE_SYSLOG */ } } static void rep_ensuresize(size_t increment) { if (partial_message_size == 0) { /* initialization */ partial_message_size_used = 0; /* avoid too many small allocations initially */ if (increment < defaultsize) increment = defaultsize; partial_message_size = increment; partial_message = (char *)MALLOC (partial_message_size); } else /* already have buffer -> resize if too little room */ { if (increment < defaultsize) increment = defaultsize; if (partial_message_size - partial_message_size_used < increment) { partial_message_size += increment; partial_message = (char *)REALLOC (partial_message, partial_message_size); } } } /* 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 empty) by calling report_complete(). If an intervening call to report() occurs when a partially constructed message exists, then, in an attempt to keep the messages in their proper sequence, the partial message will be printed as-is (with a trailing newline) before report() prints its message. */ /* VARARGS */ #ifdef HAVE_STDARG_H static int report_vgetsize(const char *message, va_list args) { char tmp[1]; return vsnprintf(tmp, 1, message, args); } /* note that report_vbuild assumes that the buffer was already allocated. */ /* VARARGS */ static int report_vbuild(const char *message, va_list args) { int n; n = vsnprintf (partial_message + partial_message_size_used, partial_message_size - partial_message_size_used, message, args); /* output error, f. i. EILSEQ */ if (n < 0) return -1; if (n > 0) { partial_message_size_used += n; } return n; } #endif 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 { int n; #ifdef VA_START va_list args; #endif /* the logic is to first calculate the size, * then reallocate, then fill the buffer */ #if defined(VA_START) VA_START(args, message); n = report_vgetsize(message, args); va_end(args); rep_ensuresize(n + 1); VA_START(args, message); (void)report_vbuild(message, args); va_end(args); #else { char tmp[1]; /* note that SUSv2 specifies that with the 2nd argument zero, an * unspecified value less than 1 were to be returned. This is not * useful, so pass 1. */ n = snprintf (tmp, 1, message, a1, a2, a3, a4, a5, a6, a7, a8); if (n > 0) rep_ensuresize(n + 1); } 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) partial_message_size_used += n; #endif if (unbuffered && partial_message_size_used != 0) { partial_message_size_used = 0; fputs(partial_message, errfp); } } 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 { int n; #ifdef VA_START va_list args; VA_START(args, message); n = report_vgetsize(message, args); va_end(args); rep_ensuresize(n + 1); VA_START(args, message); (void)report_vbuild(message, args); va_end(args); #else report_build(errfp, message, a1, a2, a3, a4, a5, a6, a7, a8); #endif /* Finally... print it. */ partial_message_size_used = 0; if (unbuffered) { fputs(partial_message, errfp); fflush (errfp); } 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. */ 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, 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) { static const char *old_file_name; static unsigned int old_line_number; if (old_line_number == line_number && (file_name == old_file_name || (old_file_name != NULL && 0 == strcmp (old_file_name, file_name)))) /* Simply return and print nothing. */ return; old_file_name = file_name; old_line_number = line_number; } fflush (errfp); if ( *message == '\n' ) { fputc( '\n', errfp ); ++message; } fprintf (errfp, "%s:", program_name); 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) 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 if (errnum) fprintf (errfp, ": %s", strerror (errnum)); putc ('\n', errfp); fflush (errfp); }