📄 err.c
字号:
/*
* Copyright (c) 1998-2000 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.
*
*/
#ifndef lint
static char id[] = "@(#)$Id: err.c,v 8.120.4.1 2000/05/25 18:56:15 gshapiro Exp $";
#endif /* ! lint */
#include <sendmail.h>
#ifdef 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));
/*
** SYSERR -- Print error message.
**
** Prints an error message via 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.
**
** Parameters:
** fmt -- the format string. If it does not begin with
** a three-digit SMTP reply code, either 554 or
** 451 is assumed depending on whether errno
** is set.
** (others) -- parameters
**
** Returns:
** none
** Through TopFrame 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;
char *user;
char *enhsc;
char *errtxt;
struct passwd *pw;
char ubuf[80];
VA_LOCAL_DECL
panic = *fmt == '!';
if (panic)
{
fmt++;
HoldErrs = FALSE;
}
/* format and output the error message */
if (save_errno == 0)
{
p = "554";
enhsc = "5.0.0";
}
else
{
p = "451";
enhsc = "4.0.0";
}
VA_START(fmt);
errtxt = fmtmsg(MsgBuf, (char *) NULL, p, enhsc, save_errno, fmt, ap);
VA_END;
puterrmsg(MsgBuf);
/* save this message for mailq printing */
if (!panic && CurEnv != NULL)
{
if (CurEnv->e_message != NULL)
free(CurEnv->e_message);
CurEnv->e_message = newstr(errtxt);
}
/* 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))
dprintf("syserr: ExitStat = %d\n", ExitStat);
}
pw = sm_getpwuid(getuid());
if (pw != NULL)
user = pw->pw_name;
else
{
user = ubuf;
snprintf(ubuf, sizeof ubuf, "UID%d", (int) getuid());
}
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(TRUE);
break;
}
if (panic)
{
#ifdef XLA
xla_all_end();
#endif /* XLA */
sync_queue_time();
if (tTd(0, 1))
abort();
exit(EX_OSERR);
}
errno = 0;
if (QuickAbort)
longjmp(TopFrame, 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, 501 is assumed.
** (others) -- printf strings
**
** Returns:
** none
** Through TopFrame 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;
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;
VA_START(fmt);
errtxt = fmtmsg(MsgBuf, CurEnv->e_to, "501", enhsc, 0, fmt, ap);
VA_END;
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_message != NULL)
free(CurEnv->e_message);
if (MsgBuf[0] == '6')
{
char buf[MAXLINE];
snprintf(buf, sizeof buf, "Postmaster warning: %.*s",
(int) sizeof buf - 22, errtxt);
CurEnv->e_message = newstr(buf);
}
else
{
CurEnv->e_message = newstr(errtxt);
}
break;
}
puterrmsg(MsgBuf);
if (LogLevel > 3 && LogUsrErrs)
sm_syslog(LOG_NOTICE, CurEnv->e_id, "%.900s", errtxt);
if (QuickAbort)
longjmp(TopFrame, 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, 501 is assumed.
** (others) -- printf strings
**
** Returns:
** none
** Through TopFrame 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;
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";
}
VA_START(fmt);
errtxt = fmtmsg(MsgBuf, CurEnv->e_to, "501", enhsc, 0, fmt, ap);
VA_END;
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_message != NULL)
free(CurEnv->e_message);
if (MsgBuf[0] == '6')
{
char buf[MAXLINE];
snprintf(buf, sizeof buf, "Postmaster warning: %.*s",
(int) sizeof buf - 22, errtxt);
CurEnv->e_message = newstr(buf);
}
else
{
CurEnv->e_message = newstr(errtxt);
}
break;
}
puterrmsg(MsgBuf);
if (LogLevel > 3 && LogUsrErrs)
sm_syslog(LOG_NOTICE, CurEnv->e_id, "%.900s", errtxt);
if (QuickAbort)
longjmp(TopFrame, 1);
}
/*
** MESSAGE -- print message (not necessarily an error)
**
** Parameters:
** msg -- the message (printf fmt) -- it can begin with
** an SMTP reply code. If not, 050 is assumed.
** (others) -- 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;
VA_LOCAL_DECL
errno = 0;
VA_START(msg);
errtxt = fmtmsg(MsgBuf, CurEnv->e_to, "050", (char *) NULL, 0, msg, ap);
VA_END;
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_message != NULL)
free(CurEnv->e_message);
CurEnv->e_message = newstr(errtxt);
break;
}
}
/*
** NMESSAGE -- print message (not necessarily an error)
**
** Just like "message" except it never puts the to... tag on.
**
** Parameters:
** msg -- the message (printf fmt) -- if it begins
** with a three digit SMTP reply code, that is used,
** otherwise 050 is assumed.
** (others) -- 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;
VA_LOCAL_DECL
errno = 0;
VA_START(msg);
errtxt = fmtmsg(MsgBuf, (char *) NULL, "050",
(char *) NULL, 0, msg, ap);
VA_END;
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_message != NULL)
free(CurEnv->e_message);
CurEnv->e_message = newstr(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 *errtxt = msg;
char msgcode = msg[0];
/* display for debugging */
if (tTd(54, 8))
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';
/* output to transcript if serious */
if (!heldmsg && CurEnv != NULL && CurEnv->e_xfp != NULL &&
strchr("45", msg[0]) != NULL)
fprintf(CurEnv->e_xfp, "%s\n", msg);
if (LogLevel >= 15 && (OpMode == MD_SMTP || OpMode == MD_DAEMON))
sm_syslog(LOG_INFO, CurEnv->e_id,
"--> %s%s",
msg, holdmsg ? " (held)" : "");
if (msgcode == '8')
msg[0] = '0';
/* output to channel if appropriate */
if (!Verbose && msg[0] == '0')
return;
if (holdmsg)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -