collect.c
来自「< linux网络编程工具>>配套源码」· C语言 代码 · 共 887 行 · 第 1/2 页
C
887 行
bp[0] == '\r' && bp[1] == '\n') ||
(!bitset(EF_NL_NOT_EOL, e->e_flags) &&
bp[0] == '\n'))
{
break;
}
/* if not a blank separator, write it out */
if (!bitset(EF_TOOBIG, e->e_flags))
{
while (*bp != '\0')
(void) putc(*bp++, df);
}
break;
}
bp = buf;
}
readerr:
if ((feof(fp) && smtpmode) || ferror(fp))
{
const char *errmsg = errstring(errno);
if (tTd(30, 1))
dprintf("collect: premature EOM: %s\n", errmsg);
if (LogLevel >= 2)
sm_syslog(LOG_WARNING, e->e_id,
"collect: premature EOM: %s", errmsg);
inputerr = TRUE;
}
/* reset global timer */
clrevent(CollectTimeout);
if (headeronly)
return;
if (df == NULL)
{
/* skip next few clauses */
/* EMPTY */
}
else if (fflush(df) != 0 || ferror(df))
{
dferror(df, "fflush||ferror", e);
flush_errors(TRUE);
finis(TRUE, ExitStat);
/* NOTREACHED */
}
else if (!SuperSafe)
{
/* skip next few clauses */
/* EMPTY */
}
else if ((afd = fileno(df)) >= 0 && fsync(afd) < 0)
{
dferror(df, "fsync", e);
flush_errors(TRUE);
finis(TRUE, ExitStat);
/* NOTREACHED */
}
else if (bfcommit(df) < 0)
{
int save_errno = errno;
if (save_errno == EEXIST)
{
char *dfile;
struct stat st;
dfile = queuename(e, 'd');
if (stat(dfile, &st) < 0)
st.st_size = -1;
errno = EEXIST;
syserr("collect: bfcommit(%s): already on disk, size = %ld",
dfile, (long) st.st_size);
dfd = fileno(df);
if (dfd >= 0)
dumpfd(dfd, TRUE, TRUE);
}
errno = save_errno;
dferror(df, "bfcommit", e);
flush_errors(TRUE);
finis(save_errno != EEXIST, ExitStat);
}
else if (bfclose(df) < 0)
{
dferror(df, "bfclose", e);
flush_errors(TRUE);
finis(TRUE, ExitStat);
/* NOTREACHED */
}
else
{
/* everything is happily flushed to disk */
df = NULL;
}
/* An EOF when running SMTP is an error */
if (inputerr && (OpMode == MD_SMTP || OpMode == MD_DAEMON))
{
char *host;
char *problem;
host = RealHostName;
if (host == NULL)
host = "localhost";
if (feof(fp))
problem = "unexpected close";
else if (ferror(fp))
problem = "I/O error";
else
problem = "read timeout";
if (LogLevel > 0 && feof(fp))
sm_syslog(LOG_NOTICE, e->e_id,
"collect: %s on connection from %.100s, sender=%s: %s",
problem, host,
shortenstring(e->e_from.q_paddr, MAXSHORTSTR),
errstring(errno));
if (feof(fp))
usrerr("451 4.4.1 collect: %s on connection from %s, from=%s",
problem, host,
shortenstring(e->e_from.q_paddr, MAXSHORTSTR));
else
syserr("451 4.4.1 collect: %s on connection from %s, from=%s",
problem, host,
shortenstring(e->e_from.q_paddr, MAXSHORTSTR));
/* don't return an error indication */
e->e_to = NULL;
e->e_flags &= ~EF_FATALERRS;
e->e_flags |= EF_CLRQUEUE;
/* and don't try to deliver the partial message either */
if (InChild)
ExitStat = EX_QUIT;
finis(TRUE, ExitStat);
/* NOTREACHED */
}
/*
** Find out some information from the headers.
** Examples are who is the from person & the date.
*/
eatheader(e, TRUE);
if (GrabTo && e->e_sendqueue == NULL)
usrerr("No recipient addresses found in header");
/* collect statistics */
if (OpMode != MD_VERIFY)
markstats(e, (ADDRESS *) NULL, FALSE);
/*
** If we have a Return-Receipt-To:, turn it into a DSN.
*/
if (RrtImpliesDsn && hvalue("return-receipt-to", e->e_header) != NULL)
{
ADDRESS *q;
for (q = e->e_sendqueue; q != NULL; q = q->q_next)
if (!bitset(QHASNOTIFY, q->q_flags))
q->q_flags |= QHASNOTIFY|QPINGONSUCCESS;
}
/*
** Add an Apparently-To: line if we have no recipient lines.
*/
if (hvalue("to", e->e_header) != NULL ||
hvalue("cc", e->e_header) != NULL ||
hvalue("apparently-to", e->e_header) != NULL)
{
/* have a valid recipient header -- delete Bcc: headers */
e->e_flags |= EF_DELETE_BCC;
}
else if (hvalue("bcc", e->e_header) == NULL)
{
/* no valid recipient headers */
register ADDRESS *q;
char *hdr = NULL;
/* create an Apparently-To: field */
/* that or reject the message.... */
switch (NoRecipientAction)
{
case NRA_ADD_APPARENTLY_TO:
hdr = "Apparently-To";
break;
case NRA_ADD_TO:
hdr = "To";
break;
case NRA_ADD_BCC:
addheader("Bcc", " ", 0, &e->e_header);
break;
case NRA_ADD_TO_UNDISCLOSED:
addheader("To", "undisclosed-recipients:;", 0, &e->e_header);
break;
}
if (hdr != NULL)
{
for (q = e->e_sendqueue; q != NULL; q = q->q_next)
{
if (q->q_alias != NULL)
continue;
if (tTd(30, 3))
dprintf("Adding %s: %s\n",
hdr, q->q_paddr);
addheader(hdr, q->q_paddr, 0, &e->e_header);
}
}
}
/* check for message too large */
if (bitset(EF_TOOBIG, e->e_flags))
{
e->e_flags |= EF_NO_BODY_RETN|EF_CLRQUEUE;
e->e_status = "5.2.3";
usrerrenh(e->e_status,
"552 Message exceeds maximum fixed size (%ld)",
MaxMessageSize);
if (LogLevel > 6)
sm_syslog(LOG_NOTICE, e->e_id,
"message size (%ld) exceeds maximum (%ld)",
e->e_msgsize, MaxMessageSize);
}
/* check for illegal 8-bit data */
if (HasEightBits)
{
e->e_flags |= EF_HAS8BIT;
if (!bitset(MM_PASS8BIT|MM_MIME8BIT, MimeMode) &&
!bitset(EF_IS_MIME, e->e_flags))
{
e->e_status = "5.6.1";
usrerrenh(e->e_status, "554 Eight bit data not allowed");
}
}
else
{
/* if it claimed to be 8 bits, well, it lied.... */
if (e->e_bodytype != NULL &&
strcasecmp(e->e_bodytype, "8BITMIME") == 0)
e->e_bodytype = "7BIT";
}
if (SuperSafe)
{
if ((e->e_dfp = fopen(dfname, "r")) == NULL)
{
/* we haven't acked receipt yet, so just chuck this */
syserr("Cannot reopen %s", dfname);
finis(TRUE, ExitStat);
/* NOTREACHED */
}
}
else
e->e_dfp = df;
if (e->e_dfp == NULL)
syserr("!collect: no e_dfp");
}
static void
collecttimeout(timeout)
time_t timeout;
{
/* if no progress was made, die now */
if (!CollectProgress)
longjmp(CtxCollectTimeout, 1);
/* otherwise reset the timeout */
CollectTimeout = setevent(timeout, collecttimeout, timeout);
CollectProgress = FALSE;
}
/*
** DFERROR -- signal error on writing the data file.
**
** Parameters:
** df -- the file pointer for the data file.
** msg -- detailed message.
** e -- the current envelope.
**
** Returns:
** none.
**
** Side Effects:
** Gives an error message.
** Arranges for following output to go elsewhere.
*/
static void
dferror(df, msg, e)
FILE *volatile df;
char *msg;
register ENVELOPE *e;
{
char *dfname;
dfname = queuename(e, 'd');
setstat(EX_IOERR);
if (errno == ENOSPC)
{
#if STAT64 > 0
struct stat64 st;
#else /* STAT64 > 0 */
struct stat st;
#endif /* STAT64 > 0 */
long avail;
long bsize;
e->e_flags |= EF_NO_BODY_RETN;
if (
#if STAT64 > 0
fstat64(fileno(df), &st)
#else /* STAT64 > 0 */
fstat(fileno(df), &st)
#endif /* STAT64 > 0 */
< 0)
st.st_size = 0;
(void) freopen(dfname, "w", df);
if (st.st_size <= 0)
fprintf(df, "\n*** Mail could not be accepted");
/*CONSTCOND*/
else if (sizeof st.st_size > sizeof (long))
fprintf(df, "\n*** Mail of at least %s bytes could not be accepted\n",
quad_to_string(st.st_size));
else
fprintf(df, "\n*** Mail of at least %lu bytes could not be accepted\n",
(unsigned long) st.st_size);
fprintf(df, "*** at %s due to lack of disk space for temp file.\n",
MyHostName);
avail = freediskspace(qid_printqueue(e->e_queuedir), &bsize);
if (avail > 0)
{
if (bsize > 1024)
avail *= bsize / 1024;
else if (bsize < 1024)
avail /= 1024 / bsize;
fprintf(df, "*** Currently, %ld kilobytes are available for mail temp files.\n",
avail);
}
e->e_status = "4.3.1";
usrerrenh(e->e_status, "452 Out of disk space for temp file");
}
else
syserr("collect: Cannot write %s (%s, uid=%d)",
dfname, msg, geteuid());
if (freopen("/dev/null", "w", df) == NULL)
sm_syslog(LOG_ERR, e->e_id,
"dferror: freopen(\"/dev/null\") failed: %s",
errstring(errno));
}
/*
** EATFROM -- chew up a UNIX style from line and process
**
** This does indeed make some assumptions about the format
** of UNIX messages.
**
** Parameters:
** fm -- the from line.
**
** Returns:
** none.
**
** Side Effects:
** extracts what information it can from the header,
** such as the date.
*/
#ifndef NOTUNIX
static char *DowList[] =
{
"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", NULL
};
static char *MonthList[] =
{
"Jan", "Feb", "Mar", "Apr", "May", "Jun",
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec",
NULL
};
static void
eatfrom(fm, e)
char *volatile fm;
register ENVELOPE *e;
{
register char *p;
register char **dt;
if (tTd(30, 2))
dprintf("eatfrom(%s)\n", fm);
/* find the date part */
p = fm;
while (*p != '\0')
{
/* skip a word */
while (*p != '\0' && *p != ' ')
p++;
while (*p == ' ')
p++;
if (!(isascii(*p) && isupper(*p)) ||
p[3] != ' ' || p[13] != ':' || p[16] != ':')
continue;
/* we have a possible date */
for (dt = DowList; *dt != NULL; dt++)
if (strncmp(*dt, p, 3) == 0)
break;
if (*dt == NULL)
continue;
for (dt = MonthList; *dt != NULL; dt++)
if (strncmp(*dt, &p[4], 3) == 0)
break;
if (*dt != NULL)
break;
}
if (*p != '\0')
{
char *q;
/* we have found a date */
q = xalloc(25);
(void) strlcpy(q, p, 25);
q = arpadate(q);
define('a', newstr(q), e);
}
}
#endif /* ! NOTUNIX */
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?