diff options
Diffstat (limited to 'contrib/sendmail/src/err.c')
-rw-r--r-- | contrib/sendmail/src/err.c | 1158 |
1 files changed, 0 insertions, 1158 deletions
diff --git a/contrib/sendmail/src/err.c b/contrib/sendmail/src/err.c deleted file mode 100644 index 5825666..0000000 --- a/contrib/sendmail/src/err.c +++ /dev/null @@ -1,1158 +0,0 @@ -/* - * Copyright (c) 1998-2003 Sendmail, Inc. and its suppliers. - * All rights reserved. - * Copyright (c) 1983, 1995-1997 Eric P. Allman. All rights reserved. - * Copyright (c) 1988, 1993 - * The Regents of the University of California. All rights reserved. - * - * By using this file, you agree to the terms and conditions set - * forth in the LICENSE file which can be found at the top level of - * the sendmail distribution. - * - */ - -#include <sendmail.h> - -SM_RCSID("@(#)$Id: err.c,v 8.196 2006/11/10 23:14:08 ca Exp $") - -#if LDAPMAP -# include <lber.h> -# include <ldap.h> /* for LDAP error codes */ -#endif /* LDAPMAP */ - -static void putoutmsg __P((char *, bool, bool)); -static void puterrmsg __P((char *)); -static char *fmtmsg __P((char *, const char *, const char *, const char *, - int, const char *, va_list)); - -/* -** FATAL_ERROR -- handle a fatal exception -** -** This function is installed as the default exception handler -** in the main sendmail process, and in all child processes -** that we create. Its job is to handle exceptions that are not -** handled at a lower level. -** -** The theory is that unhandled exceptions will be 'fatal' class -** exceptions (with an "F:" prefix), such as the out-of-memory -** exception "F:sm.heap". As such, they are handled by exiting -** the process in exactly the same way that xalloc() in Sendmail 8.10 -** exits the process when it fails due to lack of memory: -** we call syserr with a message beginning with "!". -** -** Parameters: -** exc -- exception which is terminating this process -** -** Returns: -** none -*/ - -void -fatal_error(exc) - SM_EXC_T *exc; -{ - static char buf[256]; - SM_FILE_T f; - - /* - ** This function may be called when the heap is exhausted. - ** The following code writes the message for 'exc' into our - ** static buffer without allocating memory or raising exceptions. - */ - - sm_strio_init(&f, buf, sizeof(buf)); - sm_exc_write(exc, &f); - (void) sm_io_flush(&f, SM_TIME_DEFAULT); - - /* - ** Terminate the process after logging an error and cleaning up. - ** Problems: - ** - syserr decides what class of error this is by looking at errno. - ** That's no good; we should look at the exc structure. - ** - The cleanup code should be moved out of syserr - ** and into individual exception handlers - ** that are part of the module they clean up after. - */ - - errno = ENOMEM; - syserr("!%s", buf); -} - -/* -** SYSERR -- Print error message. -** -** Prints an error message via sm_io_printf to the diagnostic output. -** -** If the first character of the syserr message is `!' it will -** log this as an ALERT message and exit immediately. This can -** leave queue files in an indeterminate state, so it should not -** be used lightly. -** -** If the first character of the syserr message is '!' or '@' -** then syserr knows that the process is about to be terminated, -** so the SMTP reply code defaults to 421. Otherwise, the -** reply code defaults to 451 or 554, depending on errno. -** -** Parameters: -** fmt -- the format string. An optional '!' or '@', -** followed by an optional three-digit SMTP -** reply code, followed by message text. -** (others) -- parameters -** -** Returns: -** none -** Raises E:mta.quickabort if QuickAbort is set. -** -** Side Effects: -** increments Errors. -** sets ExitStat. -*/ - -char MsgBuf[BUFSIZ*2]; /* text of most recent message */ -static char HeldMessageBuf[sizeof(MsgBuf)]; /* for held messages */ - -#if NAMED_BIND && !defined(NO_DATA) -# define NO_DATA NO_ADDRESS -#endif /* NAMED_BIND && !defined(NO_DATA) */ - -void -/*VARARGS1*/ -#ifdef __STDC__ -syserr(const char *fmt, ...) -#else /* __STDC__ */ -syserr(fmt, va_alist) - const char *fmt; - va_dcl -#endif /* __STDC__ */ -{ - register char *p; - int save_errno = errno; - bool panic; - bool exiting; - char *user; - char *enhsc; - char *errtxt; - struct passwd *pw; - char ubuf[80]; - SM_VA_LOCAL_DECL - - switch (*fmt) - { - case '!': - ++fmt; - panic = true; - exiting = true; - break; - case '@': - ++fmt; - panic = false; - exiting = true; - break; - default: - panic = false; - exiting = false; - break; - } - - /* format and output the error message */ - if (exiting) - { - /* - ** Since we are terminating the process, - ** we are aborting the entire SMTP session, - ** rather than just the current transaction. - */ - - p = "421"; - enhsc = "4.0.0"; - } - else if (save_errno == 0) - { - p = "554"; - enhsc = "5.0.0"; - } - else - { - p = "451"; - enhsc = "4.0.0"; - } - SM_VA_START(ap, fmt); - errtxt = fmtmsg(MsgBuf, (char *) NULL, p, enhsc, save_errno, fmt, ap); - SM_VA_END(ap); - puterrmsg(MsgBuf); - - /* save this message for mailq printing */ - if (!panic && CurEnv != NULL) - { - char *nmsg = sm_rpool_strdup_x(CurEnv->e_rpool, errtxt); - - if (CurEnv->e_rpool == NULL && CurEnv->e_message != NULL) - sm_free(CurEnv->e_message); - CurEnv->e_message = nmsg; - } - - /* determine exit status if not already set */ - if (ExitStat == EX_OK) - { - if (save_errno == 0) - ExitStat = EX_SOFTWARE; - else - ExitStat = EX_OSERR; - if (tTd(54, 1)) - sm_dprintf("syserr: ExitStat = %d\n", ExitStat); - } - - pw = sm_getpwuid(RealUid); - if (pw != NULL) - user = pw->pw_name; - else - { - user = ubuf; - (void) sm_snprintf(ubuf, sizeof(ubuf), "UID%d", (int) RealUid); - } - - if (LogLevel > 0) - sm_syslog(panic ? LOG_ALERT : LOG_CRIT, - CurEnv == NULL ? NOQID : CurEnv->e_id, - "SYSERR(%s): %.900s", - user, errtxt); - switch (save_errno) - { - case EBADF: - case ENFILE: - case EMFILE: - case ENOTTY: -#ifdef EFBIG - case EFBIG: -#endif /* EFBIG */ -#ifdef ESPIPE - case ESPIPE: -#endif /* ESPIPE */ -#ifdef EPIPE - case EPIPE: -#endif /* EPIPE */ -#ifdef ENOBUFS - case ENOBUFS: -#endif /* ENOBUFS */ -#ifdef ESTALE - case ESTALE: -#endif /* ESTALE */ - printopenfds(true); - mci_dump_all(smioout, true); - break; - } - if (panic) - { -#if XLA - xla_all_end(); -#endif /* XLA */ - sync_queue_time(); - if (tTd(0, 1)) - abort(); - exit(EX_OSERR); - } - errno = 0; - if (QuickAbort) - sm_exc_raisenew_x(&EtypeQuickAbort, 2); -} -/* -** USRERR -- Signal user error. -** -** This is much like syserr except it is for user errors. -** -** Parameters: -** fmt -- the format string. If it does not begin with -** a three-digit SMTP reply code, 550 is assumed. -** (others) -- sm_io_printf strings -** -** Returns: -** none -** Raises E:mta.quickabort if QuickAbort is set. -** -** Side Effects: -** increments Errors. -*/ - -/*VARARGS1*/ -void -#ifdef __STDC__ -usrerr(const char *fmt, ...) -#else /* __STDC__ */ -usrerr(fmt, va_alist) - const char *fmt; - va_dcl -#endif /* __STDC__ */ -{ - char *enhsc; - char *errtxt; - SM_VA_LOCAL_DECL - - if (fmt[0] == '5' || fmt[0] == '6') - enhsc = "5.0.0"; - else if (fmt[0] == '4' || fmt[0] == '8') - enhsc = "4.0.0"; - else if (fmt[0] == '2') - enhsc = "2.0.0"; - else - enhsc = NULL; - SM_VA_START(ap, fmt); - errtxt = fmtmsg(MsgBuf, CurEnv->e_to, "550", enhsc, 0, fmt, ap); - SM_VA_END(ap); - - if (SuprErrs) - return; - - /* save this message for mailq printing */ - switch (MsgBuf[0]) - { - case '4': - case '8': - if (CurEnv->e_message != NULL) - break; - - /* FALLTHROUGH */ - - case '5': - case '6': - if (CurEnv->e_rpool == NULL && CurEnv->e_message != NULL) - sm_free(CurEnv->e_message); - if (MsgBuf[0] == '6') - { - char buf[MAXLINE]; - - (void) sm_snprintf(buf, sizeof(buf), - "Postmaster warning: %.*s", - (int) sizeof(buf) - 22, errtxt); - CurEnv->e_message = - sm_rpool_strdup_x(CurEnv->e_rpool, buf); - } - else - { - CurEnv->e_message = - sm_rpool_strdup_x(CurEnv->e_rpool, errtxt); - } - break; - } - - puterrmsg(MsgBuf); - if (LogLevel > 3 && LogUsrErrs) - sm_syslog(LOG_NOTICE, CurEnv->e_id, "%.900s", errtxt); - if (QuickAbort) - sm_exc_raisenew_x(&EtypeQuickAbort, 1); -} -/* -** USRERRENH -- Signal user error. -** -** Same as usrerr but with enhanced status code. -** -** Parameters: -** enhsc -- the enhanced status code. -** fmt -- the format string. If it does not begin with -** a three-digit SMTP reply code, 550 is assumed. -** (others) -- sm_io_printf strings -** -** Returns: -** none -** Raises E:mta.quickabort if QuickAbort is set. -** -** Side Effects: -** increments Errors. -*/ - -/*VARARGS1*/ -void -#ifdef __STDC__ -usrerrenh(char *enhsc, const char *fmt, ...) -#else /* __STDC__ */ -usrerrenh(enhsc, fmt, va_alist) - char *enhsc; - const char *fmt; - va_dcl -#endif /* __STDC__ */ -{ - char *errtxt; - SM_VA_LOCAL_DECL - - if (enhsc == NULL || *enhsc == '\0') - { - if (fmt[0] == '5' || fmt[0] == '6') - enhsc = "5.0.0"; - else if (fmt[0] == '4' || fmt[0] == '8') - enhsc = "4.0.0"; - else if (fmt[0] == '2') - enhsc = "2.0.0"; - } - SM_VA_START(ap, fmt); - errtxt = fmtmsg(MsgBuf, CurEnv->e_to, "550", enhsc, 0, fmt, ap); - SM_VA_END(ap); - - if (SuprErrs) - return; - - /* save this message for mailq printing */ - switch (MsgBuf[0]) - { - case '4': - case '8': - if (CurEnv->e_message != NULL) - break; - - /* FALLTHROUGH */ - - case '5': - case '6': - if (CurEnv->e_rpool == NULL && CurEnv->e_message != NULL) - sm_free(CurEnv->e_message); - if (MsgBuf[0] == '6') - { - char buf[MAXLINE]; - - (void) sm_snprintf(buf, sizeof(buf), - "Postmaster warning: %.*s", - (int) sizeof(buf) - 22, errtxt); - CurEnv->e_message = - sm_rpool_strdup_x(CurEnv->e_rpool, buf); - } - else - { - CurEnv->e_message = - sm_rpool_strdup_x(CurEnv->e_rpool, errtxt); - } - break; - } - - puterrmsg(MsgBuf); - if (LogLevel > 3 && LogUsrErrs) - sm_syslog(LOG_NOTICE, CurEnv->e_id, "%.900s", errtxt); - if (QuickAbort) - sm_exc_raisenew_x(&EtypeQuickAbort, 1); -} -/* -** MESSAGE -- print message (not necessarily an error) -** -** Parameters: -** msg -- the message (sm_io_printf fmt) -- it can begin with -** an SMTP reply code. If not, 050 is assumed. -** (others) -- sm_io_printf arguments -** -** Returns: -** none -** -** Side Effects: -** none. -*/ - -/*VARARGS1*/ -void -#ifdef __STDC__ -message(const char *msg, ...) -#else /* __STDC__ */ -message(msg, va_alist) - const char *msg; - va_dcl -#endif /* __STDC__ */ -{ - char *errtxt; - SM_VA_LOCAL_DECL - - errno = 0; - SM_VA_START(ap, msg); - errtxt = fmtmsg(MsgBuf, CurEnv->e_to, "050", (char *) NULL, 0, msg, ap); - SM_VA_END(ap); - putoutmsg(MsgBuf, false, false); - - /* save this message for mailq printing */ - switch (MsgBuf[0]) - { - case '4': - case '8': - if (CurEnv->e_message != NULL) - break; - /* FALLTHROUGH */ - - case '5': - if (CurEnv->e_rpool == NULL && CurEnv->e_message != NULL) - sm_free(CurEnv->e_message); - CurEnv->e_message = - sm_rpool_strdup_x(CurEnv->e_rpool, errtxt); - break; - } -} -/* -** NMESSAGE -- print message (not necessarily an error) -** -** Just like "message" except it never puts the to... tag on. -** -** Parameters: -** msg -- the message (sm_io_printf fmt) -- if it begins -** with a three digit SMTP reply code, that is used, -** otherwise 050 is assumed. -** (others) -- sm_io_printf arguments -** -** Returns: -** none -** -** Side Effects: -** none. -*/ - -/*VARARGS1*/ -void -#ifdef __STDC__ -nmessage(const char *msg, ...) -#else /* __STDC__ */ -nmessage(msg, va_alist) - const char *msg; - va_dcl -#endif /* __STDC__ */ -{ - char *errtxt; - SM_VA_LOCAL_DECL - - errno = 0; - SM_VA_START(ap, msg); - errtxt = fmtmsg(MsgBuf, (char *) NULL, "050", - (char *) NULL, 0, msg, ap); - SM_VA_END(ap); - putoutmsg(MsgBuf, false, false); - - /* save this message for mailq printing */ - switch (MsgBuf[0]) - { - case '4': - case '8': - if (CurEnv->e_message != NULL) - break; - /* FALLTHROUGH */ - - case '5': - if (CurEnv->e_rpool == NULL && CurEnv->e_message != NULL) - sm_free(CurEnv->e_message); - CurEnv->e_message = sm_rpool_strdup_x(CurEnv->e_rpool, errtxt); - break; - } -} -/* -** PUTOUTMSG -- output error message to transcript and channel -** -** Parameters: -** msg -- message to output (in SMTP format). -** holdmsg -- if true, don't output a copy of the message to -** our output channel. -** heldmsg -- if true, this is a previously held message; -** don't log it to the transcript file. -** -** Returns: -** none. -** -** Side Effects: -** Outputs msg to the transcript. -** If appropriate, outputs it to the channel. -** Deletes SMTP reply code number as appropriate. -*/ - -static void -putoutmsg(msg, holdmsg, heldmsg) - char *msg; - bool holdmsg; - bool heldmsg; -{ - char msgcode = msg[0]; - char *errtxt = msg; - char *id; - - /* display for debugging */ - if (tTd(54, 8)) - sm_dprintf("--- %s%s%s\n", msg, holdmsg ? " (hold)" : "", - heldmsg ? " (held)" : ""); - - /* map warnings to something SMTP can handle */ - if (msgcode == '6') - msg[0] = '5'; - else if (msgcode == '8') - msg[0] = '4'; - id = (CurEnv != NULL) ? CurEnv->e_id : NULL; - - /* output to transcript if serious */ - if (!heldmsg && CurEnv != NULL && CurEnv->e_xfp != NULL && - strchr("45", msg[0]) != NULL) - (void) sm_io_fprintf(CurEnv->e_xfp, SM_TIME_DEFAULT, "%s\n", - msg); - - if (LogLevel > 14 && (OpMode == MD_SMTP || OpMode == MD_DAEMON)) - sm_syslog(LOG_INFO, id, - "--- %s%s%s", msg, holdmsg ? " (hold)" : "", - heldmsg ? " (held)" : ""); - - if (msgcode == '8') - msg[0] = '0'; - - /* output to channel if appropriate */ - if (!Verbose && msg[0] == '0') - return; - if (holdmsg) - { - /* save for possible future display */ - msg[0] = msgcode; - if (HeldMessageBuf[0] == '5' && msgcode == '4') - return; - (void) sm_strlcpy(HeldMessageBuf, msg, sizeof(HeldMessageBuf)); - return; - } - - (void) sm_io_flush(smioout, SM_TIME_DEFAULT); - - if (OutChannel == NULL) - return; - - /* find actual text of error (after SMTP status codes) */ - if (ISSMTPREPLY(errtxt)) - { - int l; - - errtxt += 4; - l = isenhsc(errtxt, ' '); - if (l <= 0) - l = isenhsc(errtxt, '\0'); - if (l > 0) - errtxt += l + 1; - } - - /* if DisConnected, OutChannel now points to the transcript */ - if (!DisConnected && - (OpMode == MD_SMTP || OpMode == MD_DAEMON || OpMode == MD_ARPAFTP)) - (void) sm_io_fprintf(OutChannel, SM_TIME_DEFAULT, "%s\r\n", - msg); - else - (void) sm_io_fprintf(OutChannel, SM_TIME_DEFAULT, "%s\n", - errtxt); - if (TrafficLogFile != NULL) - (void) sm_io_fprintf(TrafficLogFile, SM_TIME_DEFAULT, - "%05d >>> %s\n", (int) CurrentPid, - (OpMode == MD_SMTP || OpMode == MD_DAEMON) - ? msg : errtxt); -#if !PIPELINING - /* XXX can't flush here for SMTP pipelining */ - if (msg[3] == ' ') - (void) sm_io_flush(OutChannel, SM_TIME_DEFAULT); - if (!sm_io_error(OutChannel) || DisConnected) - return; - - /* - ** Error on output -- if reporting lost channel, just ignore it. - ** Also, ignore errors from QUIT response (221 message) -- some - ** rude servers don't read result. - */ - - if (InChannel == NULL || sm_io_eof(InChannel) || - sm_io_error(InChannel) || strncmp(msg, "221", 3) == 0) - return; - - /* can't call syserr, 'cause we are using MsgBuf */ - HoldErrs = true; - if (LogLevel > 0) - sm_syslog(LOG_CRIT, id, - "SYSERR: putoutmsg (%s): error on output channel sending \"%s\": %s", - CURHOSTNAME, - shortenstring(msg, MAXSHORTSTR), sm_errstring(errno)); -#endif /* !PIPELINING */ -} -/* -** PUTERRMSG -- like putoutmsg, but does special processing for error messages -** -** Parameters: -** msg -- the message to output. -** -** Returns: -** none. -** -** Side Effects: -** Sets the fatal error bit in the envelope as appropriate. -*/ - -static void -puterrmsg(msg) - char *msg; -{ - char msgcode = msg[0]; - - /* output the message as usual */ - putoutmsg(msg, HoldErrs, false); - - /* be careful about multiple error messages */ - if (OnlyOneError) - HoldErrs = true; - - /* signal the error */ - Errors++; - - if (CurEnv == NULL) - return; - - if (msgcode == '6') - { - /* notify the postmaster */ - CurEnv->e_flags |= EF_PM_NOTIFY; - } - else if (msgcode == '5' && bitset(EF_GLOBALERRS, CurEnv->e_flags)) - { - /* mark long-term fatal errors */ - CurEnv->e_flags |= EF_FATALERRS; - } -} -/* -** ISENHSC -- check whether a string contains an enhanced status code -** -** Parameters: -** s -- string with possible enhanced status code. -** delim -- delim for enhanced status code. -** -** Returns: -** 0 -- no enhanced status code. -** >4 -- length of enhanced status code. -** -** Side Effects: -** none. -*/ -int -isenhsc(s, delim) - const char *s; - int delim; -{ - int l, h; - - if (s == NULL) - return 0; - if (!((*s == '2' || *s == '4' || *s == '5') && s[1] == '.')) - return 0; - h = 0; - l = 2; - while (h < 3 && isascii(s[l + h]) && isdigit(s[l + h])) - ++h; - if (h == 0 || s[l + h] != '.') - return 0; - l += h + 1; - h = 0; - while (h < 3 && isascii(s[l + h]) && isdigit(s[l + h])) - ++h; - if (h == 0 || s[l + h] != delim) - return 0; - return l + h; -} -/* -** EXTENHSC -- check and extract an enhanced status code -** -** Parameters: -** s -- string with possible enhanced status code. -** delim -- delim for enhanced status code. -** e -- pointer to storage for enhanced status code. -** must be != NULL and have space for at least -** 10 characters ([245].[0-9]{1,3}.[0-9]{1,3}) -** -** Returns: -** 0 -- no enhanced status code. -** >4 -- length of enhanced status code. -** -** Side Effects: -** fills e with enhanced status code. -*/ - -int -extenhsc(s, delim, e) - const char *s; - int delim; - char *e; -{ - int l, h; - - if (s == NULL) - return 0; - if (!((*s == '2' || *s == '4' || *s == '5') && s[1] == '.')) - return 0; - h = 0; - l = 2; - e[0] = s[0]; - e[1] = '.'; - while (h < 3 && isascii(s[l + h]) && isdigit(s[l + h])) - { - e[l + h] = s[l + h]; - ++h; - } - if (h == 0 || s[l + h] != '.') - return 0; - e[l + h] = '.'; - l += h + 1; - h = 0; - while (h < 3 && isascii(s[l + h]) && isdigit(s[l + h])) - { - e[l + h] = s[l + h]; - ++h; - } - if (h == 0 || s[l + h] != delim) - return 0; - e[l + h] = '\0'; - return l + h; -} -/* -** FMTMSG -- format a message into buffer. -** -** Parameters: -** eb -- error buffer to get result -- MUST BE MsgBuf. -** to -- the recipient tag for this message. -** num -- default three digit SMTP reply code. -** enhsc -- enhanced status code. -** en -- the error number to display. -** fmt -- format of string. -** ap -- arguments for fmt. -** -** Returns: -** pointer to error text beyond status codes. -** -** Side Effects: -** none. -*/ - -static char * -fmtmsg(eb, to, num, enhsc, eno, fmt, ap) - register char *eb; - const char *to; - const char *num; - const char *enhsc; - int eno; - const char *fmt; - SM_VA_LOCAL_DECL -{ - char del; - int l; - int spaceleft = sizeof(MsgBuf); - char *errtxt; - - /* output the reply code */ - if (ISSMTPCODE(fmt)) - { - num = fmt; - fmt += 4; - } - if (num[3] == '-') - del = '-'; - else - del = ' '; - if (SoftBounce && num[0] == '5') - { - /* replace 5 by 4 */ - (void) sm_snprintf(eb, spaceleft, "4%2.2s%c", num + 1, del); - } - else - (void) sm_snprintf(eb, spaceleft, "%3.3s%c", num, del); - eb += 4; - spaceleft -= 4; - - if ((l = isenhsc(fmt, ' ' )) > 0 && l < spaceleft - 4) - { - /* copy enh.status code including trailing blank */ - l++; - (void) sm_strlcpy(eb, fmt, l + 1); - eb += l; - spaceleft -= l; - fmt += l; - } - else if ((l = isenhsc(enhsc, '\0')) > 0 && l < spaceleft - 4) - { - /* copy enh.status code */ - (void) sm_strlcpy(eb, enhsc, l + 1); - eb[l] = ' '; - eb[++l] = '\0'; - eb += l; - spaceleft -= l; - } - if (SoftBounce && eb[-l] == '5') - { - /* replace 5 by 4 */ - eb[-l] = '4'; - } - errtxt = eb; - - /* output the file name and line number */ - if (FileName != NULL) - { - (void) sm_snprintf(eb, spaceleft, "%s: line %d: ", - shortenstring(FileName, 83), LineNumber); - eb += (l = strlen(eb)); - spaceleft -= l; - } - - /* - ** output the "to" address only if it is defined and one of the - ** following codes is used: - ** 050 internal notices, e.g., alias expansion - ** 250 Ok - ** 252 Cannot VRFY user, but will accept message and attempt delivery - ** 450 Requested mail action not taken: mailbox unavailable - ** 550 Requested action not taken: mailbox unavailable - ** 553 Requested action not taken: mailbox name not allowed - ** - ** Notice: this still isn't "the right thing", this code shouldn't - ** (indirectly) depend on CurEnv->e_to. - */ - - if (to != NULL && to[0] != '\0' && - (strncmp(num, "050", 3) == 0 || - strncmp(num, "250", 3) == 0 || - strncmp(num, "252", 3) == 0 || - strncmp(num, "450", 3) == 0 || - strncmp(num, "550", 3) == 0 || - strncmp(num, "553", 3) == 0)) - { - (void) sm_strlcpyn(eb, spaceleft, 2, - shortenstring(to, MAXSHORTSTR), "... "); - spaceleft -= strlen(eb); - while (*eb != '\0') - *eb++ &= 0177; - } - - /* output the message */ - (void) sm_vsnprintf(eb, spaceleft, fmt, ap); - spaceleft -= strlen(eb); - while (*eb != '\0') - *eb++ &= 0177; - - /* output the error code, if any */ - if (eno != 0) - (void) sm_strlcpyn(eb, spaceleft, 2, ": ", sm_errstring(eno)); - - return errtxt; -} -/* -** BUFFER_ERRORS -- arrange to buffer future error messages -** -** Parameters: -** none -** -** Returns: -** none. -*/ - -void -buffer_errors() -{ - HeldMessageBuf[0] = '\0'; - HoldErrs = true; -} -/* -** FLUSH_ERRORS -- flush the held error message buffer -** -** Parameters: -** print -- if set, print the message, otherwise just -** delete it. -** -** Returns: -** none. -*/ - -void -flush_errors(print) - bool print; -{ - if (print && HeldMessageBuf[0] != '\0') - putoutmsg(HeldMessageBuf, false, true); - HeldMessageBuf[0] = '\0'; - HoldErrs = false; -} -/* -** SM_ERRSTRING -- return string description of error code -** -** Parameters: -** errnum -- the error number to translate -** -** Returns: -** A string description of errnum. -** -** Side Effects: -** none. -*/ - -const char * -sm_errstring(errnum) - int errnum; -{ - char *dnsmsg; - char *bp; - static char buf[MAXLINE]; -#if HASSTRERROR - char *err; - char errbuf[30]; -#endif /* HASSTRERROR */ -#if !HASSTRERROR && !defined(ERRLIST_PREDEFINED) - extern char *sys_errlist[]; - extern int sys_nerr; -#endif /* !HASSTRERROR && !defined(ERRLIST_PREDEFINED) */ - - /* - ** Handle special network error codes. - ** - ** These are 4.2/4.3bsd specific; they should be in daemon.c. - */ - - dnsmsg = NULL; - switch (errnum) - { - case ETIMEDOUT: - case ECONNRESET: - bp = buf; -#if HASSTRERROR - err = strerror(errnum); - if (err == NULL) - { - (void) sm_snprintf(errbuf, sizeof(errbuf), - "Error %d", errnum); - err = errbuf; - } - (void) sm_strlcpy(bp, err, SPACELEFT(buf, bp)); -#else /* HASSTRERROR */ - if (errnum >= 0 && errnum < sys_nerr) - (void) sm_strlcpy(bp, sys_errlist[errnum], - SPACELEFT(buf, bp)); - else - (void) sm_snprintf(bp, SPACELEFT(buf, bp), - "Error %d", errnum); -#endif /* HASSTRERROR */ - bp += strlen(bp); - if (CurHostName != NULL) - { - if (errnum == ETIMEDOUT) - { - (void) sm_snprintf(bp, SPACELEFT(buf, bp), - " with "); - bp += strlen(bp); - } - else - { - bp = buf; - (void) sm_snprintf(bp, SPACELEFT(buf, bp), - "Connection reset by "); - bp += strlen(bp); - } - (void) sm_strlcpy(bp, - shortenstring(CurHostName, MAXSHORTSTR), - SPACELEFT(buf, bp)); - bp += strlen(buf); - } - if (SmtpPhase != NULL) - { - (void) sm_snprintf(bp, SPACELEFT(buf, bp), - " during %s", SmtpPhase); - } - return buf; - - case EHOSTDOWN: - if (CurHostName == NULL) - break; - (void) sm_snprintf(buf, sizeof(buf), "Host %s is down", - shortenstring(CurHostName, MAXSHORTSTR)); - return buf; - - case ECONNREFUSED: - if (CurHostName == NULL) - break; - (void) sm_strlcpyn(buf, sizeof(buf), 2, "Connection refused by ", - shortenstring(CurHostName, MAXSHORTSTR)); - return buf; - -#if NAMED_BIND - case HOST_NOT_FOUND + E_DNSBASE: - dnsmsg = "host not found"; - break; - - case TRY_AGAIN + E_DNSBASE: - dnsmsg = "host name lookup failure"; - break; - - case NO_RECOVERY + E_DNSBASE: - dnsmsg = "non-recoverable error"; - break; - - case NO_DATA + E_DNSBASE: - dnsmsg = "no data known"; - break; -#endif /* NAMED_BIND */ - - case EPERM: - /* SunOS gives "Not owner" -- this is the POSIX message */ - return "Operation not permitted"; - - /* - ** Error messages used internally in sendmail. - */ - - case E_SM_OPENTIMEOUT: - return "Timeout on file open"; - - case E_SM_NOSLINK: - return "Symbolic links not allowed"; - - case E_SM_NOHLINK: - return "Hard links not allowed"; - - case E_SM_REGONLY: - return "Regular files only"; - - case E_SM_ISEXEC: - return "Executable files not allowed"; - - case E_SM_WWDIR: - return "World writable directory"; - - case E_SM_GWDIR: - return "Group writable directory"; - - case E_SM_FILECHANGE: - return "File changed after open"; - - case E_SM_WWFILE: - return "World writable file"; - - case E_SM_GWFILE: - return "Group writable file"; - - case E_SM_GRFILE: - return "Group readable file"; - - case E_SM_WRFILE: - return "World readable file"; - } - - if (dnsmsg != NULL) - { - bp = buf; - bp += sm_strlcpy(bp, "Name server: ", sizeof(buf)); - if (CurHostName != NULL) - { - (void) sm_strlcpyn(bp, SPACELEFT(buf, bp), 2, - shortenstring(CurHostName, MAXSHORTSTR), ": "); - bp += strlen(bp); - } - (void) sm_strlcpy(bp, dnsmsg, SPACELEFT(buf, bp)); - return buf; - } - -#if LDAPMAP - if (errnum >= E_LDAPBASE) - return ldap_err2string(errnum - E_LDAPBASE); -#endif /* LDAPMAP */ - -#if HASSTRERROR - err = strerror(errnum); - if (err == NULL) - { - (void) sm_snprintf(buf, sizeof(buf), "Error %d", errnum); - return buf; - } - return err; -#else /* HASSTRERROR */ - if (errnum > 0 && errnum < sys_nerr) - return sys_errlist[errnum]; - - (void) sm_snprintf(buf, sizeof(buf), "Error %d", errnum); - return buf; -#endif /* HASSTRERROR */ -} |