summaryrefslogtreecommitdiffstats
path: root/contrib/sendmail/src/collect.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/sendmail/src/collect.c')
-rw-r--r--contrib/sendmail/src/collect.c714
1 files changed, 429 insertions, 285 deletions
diff --git a/contrib/sendmail/src/collect.c b/contrib/sendmail/src/collect.c
index fcf3117..95a14ae 100644
--- a/contrib/sendmail/src/collect.c
+++ b/contrib/sendmail/src/collect.c
@@ -11,18 +11,232 @@
*
*/
-#ifndef lint
-static char id[] = "@(#)$Id: collect.c,v 8.136.4.22 2001/06/07 21:01:02 ca Exp $";
-#endif /* ! lint */
-
#include <sendmail.h>
+SM_RCSID("@(#)$Id: collect.c,v 8.237 2001/12/10 19:56:03 ca Exp $")
static void collecttimeout __P((time_t));
-static void dferror __P((FILE *volatile, char *, ENVELOPE *));
+static void dferror __P((SM_FILE_T *volatile, char *, ENVELOPE *));
static void eatfrom __P((char *volatile, ENVELOPE *));
+static void collect_doheader __P((ENVELOPE *));
+static SM_FILE_T *collect_dfopen __P((ENVELOPE *));
+static SM_FILE_T *collect_eoh __P((ENVELOPE *, int, int));
+
+/*
+** COLLECT_EOH -- end-of-header processing in collect()
+**
+** Called by collect() when it encounters the blank line
+** separating the header from the message body, or when it
+** encounters EOF in a message that contains only a header.
+**
+** Parameters:
+** e -- envelope
+** numhdrs -- number of headers
+** hdrslen -- length of headers
+**
+** Results:
+** NULL, or handle to open data file
+**
+** Side Effects:
+** end-of-header check ruleset is invoked.
+** envelope state is updated.
+** headers may be added and deleted.
+** selects the queue.
+** opens the data file.
+*/
+
+static SM_FILE_T *
+collect_eoh(e, numhdrs, hdrslen)
+ ENVELOPE *e;
+ int numhdrs;
+ int hdrslen;
+{
+ char hnum[16];
+ char hsize[16];
+
+ /* call the end-of-header check ruleset */
+ (void) sm_snprintf(hnum, sizeof hnum, "%d", numhdrs);
+ (void) sm_snprintf(hsize, sizeof hsize, "%d", hdrslen);
+ if (tTd(30, 10))
+ sm_dprintf("collect: rscheck(\"check_eoh\", \"%s $| %s\")\n",
+ hnum, hsize);
+ (void) rscheck("check_eoh", hnum, hsize, e, false, true, 3, NULL,
+ e->e_id);
+
+ /*
+ ** Process the header,
+ ** select the queue, open the data file.
+ */
+
+ collect_doheader(e);
+ return collect_dfopen(e);
+}
+
+/*
+** COLLECT_DOHEADER -- process header in collect()
+**
+** Called by collect() after it has finished parsing the header,
+** but before it selects the queue and creates the data file.
+** The results of processing the header will affect queue selection.
+**
+** Parameters:
+** e -- envelope
+**
+** Results:
+** none.
+**
+** Side Effects:
+** envelope state is updated.
+** headers may be added and deleted.
+*/
+
+static void
+collect_doheader(e)
+ ENVELOPE *e;
+{
+ /*
+ ** Find out some information from the headers.
+ ** Examples are who is the from person & the date.
+ */
+
+ eatheader(e, true, false);
+
+ if (GrabTo && e->e_sendqueue == NULL)
+ usrerr("No recipient addresses found in header");
+
+ /* collect statistics */
+ if (OpMode != MD_VERIFY)
+ markstats(e, (ADDRESS *) NULL, STATS_NORMAL);
+
+ /*
+ ** 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 appropriate recipient line if we have none.
+ */
+
+ 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 a recipient field */
+ 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);
+ break;
+
+ case NRA_ADD_TO_UNDISCLOSED:
+ addheader("To", "undisclosed-recipients:;", 0, e);
+ 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))
+ sm_dprintf("Adding %s: %s\n",
+ hdr, q->q_paddr);
+ addheader(hdr, q->q_paddr, 0, e);
+ }
+ }
+ }
+}
+
+/*
+** COLLECT_DFOPEN -- open the message data file
+**
+** Called by collect() after it has finished processing the header.
+** Queue selection occurs at this point, possibly based on the
+** envelope's recipient list and on header information.
+**
+** Parameters:
+** e -- envelope
+**
+** Results:
+** NULL, or a pointer to an open data file,
+** into which the message body will be written by collect().
+**
+** Side Effects:
+** Calls syserr, sets EF_FATALERRS and returns NULL
+** if there is insufficient disk space.
+** Aborts process if data file could not be opened.
+** Otherwise, the queue is selected,
+** e->e_{dfino,dfdev,msgsize,flags} are updated,
+** and a pointer to an open data file is returned.
+*/
+
+static SM_FILE_T *
+collect_dfopen(e)
+ ENVELOPE *e;
+{
+ MODE_T oldumask = 0;
+ int dfd;
+ struct stat stbuf;
+ SM_FILE_T *df;
+ char *dfname;
+
+ if (!setnewqueue(e))
+ return NULL;
+
+ dfname = queuename(e, DATAFL_LETTER);
+ if (bitset(S_IWGRP, QueueFileMode))
+ oldumask = umask(002);
+ df = bfopen(dfname, QueueFileMode, DataFileBufferSize,
+ SFF_OPENASROOT);
+ if (bitset(S_IWGRP, QueueFileMode))
+ (void) umask(oldumask);
+ if (df == NULL)
+ {
+ syserr("@Cannot create %s", dfname);
+ e->e_flags |= EF_NO_BODY_RETN;
+ flush_errors(true);
+ finis(true, true, ExitStat);
+ /* NOTREACHED */
+ }
+ dfd = sm_io_getinfo(df, SM_IO_WHAT_FD, NULL);
+ if (dfd < 0 || fstat(dfd, &stbuf) < 0)
+ e->e_dfino = -1;
+ else
+ {
+ e->e_dfdev = stbuf.st_dev;
+ e->e_dfino = stbuf.st_ino;
+ }
+ e->e_flags |= EF_HAS_DF;
+ return df;
+}
- /*
+/*
** COLLECT -- read & parse message header & make temp file.
**
** Creates a temporary file name and copies the standard
@@ -42,13 +256,20 @@ static void eatfrom __P((char *volatile, ENVELOPE *));
** none.
**
** Side Effects:
-** Temp file is created and filled.
-** The from person may be set.
+** If successful,
+** - Data file is created and filled, and e->e_dfp is set.
+** - The from person may be set.
+** If the "enough disk space" check fails,
+** - syserr is called.
+** - e->e_dfp is NULL.
+** - e->e_flags & EF_FATALERRS is set.
+** - collect() returns.
+** If data file cannot be created, the process is terminated.
*/
static jmp_buf CtxCollectTimeout;
static bool volatile CollectProgress;
-static EVENT *volatile CollectTimeout = NULL;
+static SM_EVENT *volatile CollectTimeout = NULL;
/* values for input state machine */
#define IS_NORM 0 /* middle of line */
@@ -65,83 +286,44 @@ static EVENT *volatile CollectTimeout = NULL;
void
collect(fp, smtpmode, hdrp, e)
- FILE *fp;
+ SM_FILE_T *fp;
bool smtpmode;
HDR **hdrp;
register ENVELOPE *e;
{
- register FILE *volatile df;
- volatile bool ignrdot = smtpmode ? FALSE : IgnrDot;
- volatile time_t dbto = smtpmode ? TimeOuts.to_datablock : 0;
+ register SM_FILE_T *volatile df;
+ volatile bool ignrdot;
+ volatile time_t dbto;
register char *volatile bp;
- volatile int c = EOF;
- volatile bool inputerr = FALSE;
+ volatile int c;
+ volatile bool inputerr;
bool headeronly;
char *volatile buf;
volatile int buflen;
volatile int istate;
volatile int mstate;
- volatile int hdrslen = 0;
- volatile int numhdrs = 0;
- volatile int dfd;
- volatile int rstat = EX_OK;
- u_char *volatile pbp;
- u_char peekbuf[8];
- char hsize[16];
- char hnum[16];
- char dfname[MAXPATHLEN];
+ volatile int hdrslen;
+ volatile int numhdrs;
+ volatile int afd;
+ unsigned char *volatile pbp;
+ unsigned char peekbuf[8];
char bufbuf[MAXLINE];
+ df = NULL;
+ ignrdot = smtpmode ? false : IgnrDot;
+ dbto = smtpmode ? TimeOuts.to_datablock : 0;
+ c = SM_IO_EOF;
+ inputerr = false;
headeronly = hdrp != NULL;
-
- /*
- ** Create the temp file name and create the file.
- */
-
- if (!headeronly)
- {
- struct stat stbuf;
- long sff = SFF_OPENASROOT;
-
-
- (void) strlcpy(dfname, queuename(e, 'd'), sizeof dfname);
-#if _FFR_QUEUE_FILE_MODE
- {
- MODE_T oldumask;
-
- if (bitset(S_IWGRP, QueueFileMode))
- oldumask = umask(002);
- df = bfopen(dfname, QueueFileMode,
- DataFileBufferSize, sff);
- if (bitset(S_IWGRP, QueueFileMode))
- (void) umask(oldumask);
- }
-#else /* _FFR_QUEUE_FILE_MODE */
- df = bfopen(dfname, FileMode, DataFileBufferSize, sff);
-#endif /* _FFR_QUEUE_FILE_MODE */
- if (df == NULL)
- {
- HoldErrs = FALSE;
- if (smtpmode)
- syserr("421 4.3.5 Unable to create data file");
- else
- syserr("Cannot create %s", dfname);
- e->e_flags |= EF_NO_BODY_RETN;
- finis(TRUE, ExitStat);
- /* NOTREACHED */
- }
- dfd = fileno(df);
- if (dfd < 0 || fstat(dfd, &stbuf) < 0)
- e->e_dfino = -1;
- else
- {
- e->e_dfdev = stbuf.st_dev;
- e->e_dfino = stbuf.st_ino;
- }
- HasEightBits = FALSE;
- e->e_msgsize = 0;
- e->e_flags |= EF_HAS_DF;
- }
+ hdrslen = 0;
+ numhdrs = 0;
+ HasEightBits = false;
+ buf = bp = bufbuf;
+ buflen = sizeof bufbuf;
+ pbp = peekbuf;
+ istate = IS_BOL;
+ mstate = SaveFrom ? MS_HEADER : MS_UFROM;
+ CollectProgress = false;
/*
** Tell ARPANET to go ahead.
@@ -151,7 +333,7 @@ collect(fp, smtpmode, hdrp, e)
message("354 Enter mail, end with \".\" on a line by itself");
if (tTd(30, 2))
- dprintf("collect\n");
+ sm_dprintf("collect\n");
/*
** Read the message.
@@ -162,13 +344,6 @@ collect(fp, smtpmode, hdrp, e)
** the larger picture (e.g., header versus body).
*/
- buf = bp = bufbuf;
- buflen = sizeof bufbuf;
- pbp = peekbuf;
- istate = IS_BOL;
- mstate = SaveFrom ? MS_HEADER : MS_UFROM;
- CollectProgress = FALSE;
-
if (dbto != 0)
{
/* handle possible input timeout */
@@ -176,52 +351,57 @@ collect(fp, smtpmode, hdrp, e)
{
if (LogLevel > 2)
sm_syslog(LOG_NOTICE, e->e_id,
- "timeout waiting for input from %s during message collect",
- CurHostName ? CurHostName : "<local machine>");
+ "timeout waiting for input from %s during message collect",
+ CURHOSTNAME);
errno = 0;
usrerr("451 4.4.1 timeout waiting for input during message collect");
goto readerr;
}
- CollectTimeout = setevent(dbto, collecttimeout, dbto);
+ CollectTimeout = sm_setevent(dbto, collecttimeout, dbto);
}
+ e->e_msgsize = 0;
for (;;)
{
if (tTd(30, 35))
- dprintf("top, istate=%d, mstate=%d\n", istate, mstate);
+ sm_dprintf("top, istate=%d, mstate=%d\n", istate,
+ mstate);
for (;;)
{
if (pbp > peekbuf)
c = *--pbp;
else
{
- while (!feof(fp) && !ferror(fp))
+ while (!sm_io_eof(fp) && !sm_io_error(fp))
{
errno = 0;
- c = getc(fp);
-
- if (c == EOF && errno == EINTR)
+ c = sm_io_getc(fp, SM_TIME_DEFAULT);
+ if (c == SM_IO_EOF && errno == EINTR)
{
/* Interrupted, retry */
- clearerr(fp);
+ sm_io_clearerr(fp);
continue;
}
break;
}
- CollectProgress = TRUE;
+ CollectProgress = true;
if (TrafficLogFile != NULL && !headeronly)
{
if (istate == IS_BOL)
- (void) fprintf(TrafficLogFile,
- "%05d <<< ",
- (int) getpid());
- if (c == EOF)
- (void) fprintf(TrafficLogFile,
- "[EOF]\n");
+ (void) sm_io_fprintf(TrafficLogFile,
+ SM_TIME_DEFAULT,
+ "%05d <<< ",
+ (int) CurrentPid);
+ if (c == SM_IO_EOF)
+ (void) sm_io_fprintf(TrafficLogFile,
+ SM_TIME_DEFAULT,
+ "[EOF]\n");
else
- (void) putc(c, TrafficLogFile);
+ (void) sm_io_putc(TrafficLogFile,
+ SM_TIME_DEFAULT,
+ c);
}
- if (c == EOF)
+ if (c == SM_IO_EOF)
goto readerr;
if (SevenBitInput)
c &= 0x7f;
@@ -229,7 +409,7 @@ collect(fp, smtpmode, hdrp, e)
HasEightBits |= bitset(0x80, c);
}
if (tTd(30, 94))
- dprintf("istate=%d, c=%c (0x%x)\n",
+ sm_dprintf("istate=%d, c=%c (0x%x)\n",
istate, (char) c, c);
switch (istate)
{
@@ -278,7 +458,8 @@ collect(fp, smtpmode, hdrp, e)
istate = IS_BOL;
else
{
- (void) ungetc(c, fp);
+ (void) sm_io_ungetc(fp, SM_TIME_DEFAULT,
+ c);
c = '\r';
istate = IS_NORM;
}
@@ -290,7 +471,8 @@ collect(fp, smtpmode, hdrp, e)
istate = IS_CR;
continue;
}
- else if (c == '\n' && !bitset(EF_NL_NOT_EOL, e->e_flags))
+ else if (c == '\n' && !bitset(EF_NL_NOT_EOL,
+ e->e_flags))
istate = IS_BOL;
else
istate = IS_NORM;
@@ -313,7 +495,9 @@ bufferchar:
case MS_BODY:
/* just put the character out */
if (!bitset(EF_TOOBIG, e->e_flags))
- (void) putc(c, df);
+ (void) sm_io_putc(df, SM_TIME_DEFAULT,
+ c);
+
/* FALLTHROUGH */
case MS_DISCARD:
@@ -338,11 +522,22 @@ bufferchar:
memmove(buf, obuf, bp - obuf);
bp = &buf[bp - obuf];
if (obuf != bufbuf)
- sm_free(obuf);
+ sm_free(obuf); /* XXX */
}
+
+ /*
+ ** XXX Notice: the logic here is broken.
+ ** An input to sendmail that doesn't contain a
+ ** header but starts immediately with the body whose
+ ** first line contain characters which match the
+ ** following "if" will cause problems: those
+ ** characters will NOT appear in the output...
+ ** Do we care?
+ */
+
if (c >= 0200 && c <= 0237)
{
-#if 0 /* causes complaints -- figure out something for 8.11 */
+#if 0 /* causes complaints -- figure out something for 8.n+1 */
usrerr("Illegal character 0x%x in header", c);
#else /* 0 */
/* EMPTY */
@@ -351,7 +546,7 @@ bufferchar:
else if (c != '\0')
{
*bp++ = c;
- hdrslen++;
+ ++hdrslen;
if (!headeronly &&
MaxHeadersLength > 0 &&
hdrslen > MaxHeadersLength)
@@ -359,7 +554,7 @@ bufferchar:
sm_syslog(LOG_NOTICE, e->e_id,
"headers too large (%d max) from %s during message collect",
MaxHeadersLength,
- CurHostName != NULL ? CurHostName : "localhost");
+ CURHOSTNAME);
errno = 0;
e->e_flags |= EF_CLRQUEUE;
e->e_status = "5.6.0";
@@ -376,7 +571,7 @@ bufferchar:
nextstate:
if (tTd(30, 35))
- dprintf("nextstate, istate=%d, mstate=%d, line = \"%s\"\n",
+ sm_dprintf("nextstate, istate=%d, mstate=%d, line = \"%s\"\n",
istate, mstate, buf);
switch (mstate)
{
@@ -402,12 +597,12 @@ nextstate:
/* check for possible continuation line */
do
{
- clearerr(fp);
+ sm_io_clearerr(fp);
errno = 0;
- c = getc(fp);
- } while (c == EOF && errno == EINTR);
- if (c != EOF)
- (void) ungetc(c, fp);
+ c = sm_io_getc(fp, SM_TIME_DEFAULT);
+ } while (c == SM_IO_EOF && errno == EINTR);
+ if (c != SM_IO_EOF)
+ (void) sm_io_ungetc(fp, SM_TIME_DEFAULT, c);
if (c == ' ' || c == '\t')
{
/* yep -- defer this */
@@ -431,19 +626,14 @@ nextstate:
case MS_BODY:
if (tTd(30, 1))
- dprintf("EOH\n");
+ sm_dprintf("EOH\n");
if (headeronly)
goto readerr;
- /* call the end-of-header check ruleset */
- snprintf(hnum, sizeof hnum, "%d", numhdrs);
- snprintf(hsize, sizeof hsize, "%d", hdrslen);
- if (tTd(30, 10))
- dprintf("collect: rscheck(\"check_eoh\", \"%s $| %s\")\n",
- hnum, hsize);
- rstat = rscheck("check_eoh", hnum, hsize, e, FALSE,
- TRUE, 4, NULL);
+ df = collect_eoh(e, numhdrs, hdrslen);
+ if (df == NULL)
+ e->e_flags |= EF_TOOBIG;
bp = buf;
@@ -460,7 +650,8 @@ nextstate:
if (!bitset(EF_TOOBIG, e->e_flags))
{
while (*bp != '\0')
- (void) putc(*bp++, df);
+ (void) sm_io_putc(df, SM_TIME_DEFAULT,
+ *bp++);
}
break;
}
@@ -468,43 +659,54 @@ nextstate:
}
readerr:
- if ((feof(fp) && smtpmode) || ferror(fp))
+ if ((sm_io_eof(fp) && smtpmode) || sm_io_error(fp))
{
- const char *errmsg = errstring(errno);
+ const char *errmsg;
+ if (sm_io_eof(fp))
+ errmsg = "unexpected close";
+ else
+ errmsg = sm_errstring(errno);
if (tTd(30, 1))
- dprintf("collect: premature EOM: %s\n", errmsg);
- if (LogLevel >= 2)
+ sm_dprintf("collect: premature EOM: %s\n", errmsg);
+ if (LogLevel > 1)
sm_syslog(LOG_WARNING, e->e_id,
"collect: premature EOM: %s", errmsg);
- inputerr = TRUE;
+ inputerr = true;
}
/* reset global timer */
if (CollectTimeout != NULL)
- clrevent(CollectTimeout);
+ sm_clrevent(CollectTimeout);
if (headeronly)
return;
+ if (mstate != MS_BODY)
+ {
+ /* no body or discard, so we never opened the data file */
+ SM_ASSERT(df == NULL);
+ df = collect_eoh(e, numhdrs, hdrslen);
+ }
+
if (df == NULL)
{
/* skip next few clauses */
/* EMPTY */
}
- else if (fflush(df) != 0 || ferror(df))
+ else if (sm_io_flush(df, SM_TIME_DEFAULT) != 0 || sm_io_error(df))
{
- dferror(df, "fflush||ferror", e);
- flush_errors(TRUE);
- finis(TRUE, ExitStat);
+ dferror(df, "sm_io_flush||sm_io_error", e);
+ flush_errors(true);
+ finis(true, true, ExitStat);
/* NOTREACHED */
}
- else if (!SuperSafe)
+ else if (SuperSafe != SAFE_REALLY)
{
/* skip next few clauses */
/* EMPTY */
}
- else if (bfcommit(df) < 0)
+ else if (sm_io_setinfo(df, SM_BF_COMMIT, NULL) < 0 && errno != EINVAL)
{
int save_errno = errno;
@@ -512,40 +714,45 @@ readerr:
{
char *dfile;
struct stat st;
+ int dfd;
- dfile = queuename(e, 'd');
+ dfile = queuename(e, DATAFL_LETTER);
if (stat(dfile, &st) < 0)
st.st_size = -1;
errno = EEXIST;
- syserr("collect: bfcommit(%s): already on disk, size = %ld",
+ syserr("@collect: bfcommit(%s): already on disk, size = %ld",
dfile, (long) st.st_size);
- dfd = fileno(df);
+ dfd = sm_io_getinfo(df, SM_IO_WHAT_FD, NULL);
if (dfd >= 0)
- dumpfd(dfd, TRUE, TRUE);
+ dumpfd(dfd, true, true);
}
errno = save_errno;
dferror(df, "bfcommit", e);
- flush_errors(TRUE);
- finis(save_errno != EEXIST, ExitStat);
+ flush_errors(true);
+ finis(save_errno != EEXIST, true, ExitStat);
}
- else if (bffsync(df) < 0)
+ else if ((afd = sm_io_getinfo(df, SM_IO_WHAT_FD, NULL)) >= 0 &&
+ fsync(afd) < 0)
{
- dferror(df, "bffsync", e);
- flush_errors(TRUE);
- finis(TRUE, ExitStat);
+ dferror(df, "fsync", e);
+ flush_errors(true);
+ finis(true, true, ExitStat);
/* NOTREACHED */
}
- else if (bfclose(df) < 0)
+ else if (sm_io_close(df, SM_TIME_DEFAULT) < 0)
{
- dferror(df, "bfclose", e);
- flush_errors(TRUE);
- finis(TRUE, ExitStat);
+ dferror(df, "sm_io_close", e);
+ flush_errors(true);
+ finis(true, true, ExitStat);
/* NOTREACHED */
}
else
{
/* everything is happily flushed to disk */
df = NULL;
+
+ /* remove from available space in filesystem */
+ updfs(e, false, true);
}
/* An EOF when running SMTP is an error */
@@ -558,19 +765,18 @@ readerr:
if (host == NULL)
host = "localhost";
- if (feof(fp))
+ if (sm_io_eof(fp))
problem = "unexpected close";
- else if (ferror(fp))
+ else if (sm_io_error(fp))
problem = "I/O error";
else
problem = "read timeout";
- if (LogLevel > 0 && feof(fp))
+ if (LogLevel > 0 && sm_io_eof(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))
+ "collect: %s on connection from %.100s, sender=%s",
+ problem, host,
+ shortenstring(e->e_from.q_paddr, MAXSHORTSTR));
+ if (sm_io_eof(fp))
usrerr("451 4.4.1 collect: %s on connection from %s, from=%s",
problem, host,
shortenstring(e->e_from.q_paddr, MAXSHORTSTR));
@@ -584,104 +790,32 @@ readerr:
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);
+ finis(true, 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)
+ /* Log collection information. */
+ if (bitset(EF_LOGSENDER, e->e_flags) && LogLevel > 4)
{
- 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);
- }
- }
+ logsender(e, e->e_msgid);
+ e->e_flags &= ~EF_LOGSENDER;
}
/* 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);
+ if (!bitset(EF_FATALERRS, e->e_flags))
+ {
+ 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 */
@@ -699,27 +833,26 @@ readerr:
{
/* if it claimed to be 8 bits, well, it lied.... */
if (e->e_bodytype != NULL &&
- strcasecmp(e->e_bodytype, "8BITMIME") == 0)
+ sm_strcasecmp(e->e_bodytype, "8BITMIME") == 0)
e->e_bodytype = "7BIT";
}
- if (SuperSafe)
+ if (SuperSafe == SAFE_REALLY && !bitset(EF_FATALERRS, e->e_flags))
{
- if ((e->e_dfp = fopen(dfname, "r")) == NULL)
+ char *dfname = queuename(e, DATAFL_LETTER);
+ if ((e->e_dfp = sm_io_open(SmFtStdio, SM_TIME_DEFAULT, dfname,
+ SM_IO_RDONLY, NULL)) == NULL)
{
/* we haven't acked receipt yet, so just chuck this */
- syserr("Cannot reopen %s", dfname);
- finis(TRUE, ExitStat);
+ syserr("@Cannot reopen %s", dfname);
+ finis(true, 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;
@@ -735,9 +868,9 @@ collecttimeout(timeout)
if (CollectProgress)
{
/* reset the timeout */
- CollectTimeout = sigsafe_setevent(timeout, collecttimeout,
- timeout);
- CollectProgress = FALSE;
+ CollectTimeout = sm_sigsafe_setevent(timeout, collecttimeout,
+ timeout);
+ CollectProgress = false;
}
else
{
@@ -751,12 +884,16 @@ collecttimeout(timeout)
errno = ETIMEDOUT;
longjmp(CtxCollectTimeout, 1);
}
-
errno = save_errno;
}
- /*
+/*
** DFERROR -- signal error on writing the data file.
**
+** Called by collect(). Collect() always terminates the process
+** immediately after calling dferror(), which means that the SMTP
+** session will be terminated, which means that any error message
+** issued by dferror must be a 421 error, as per RFC 821.
+**
** Parameters:
** df -- the file pointer for the data file.
** msg -- detailed message.
@@ -772,13 +909,13 @@ collecttimeout(timeout)
static void
dferror(df, msg, e)
- FILE *volatile df;
+ SM_FILE_T *volatile df;
char *msg;
register ENVELOPE *e;
{
char *dfname;
- dfname = queuename(e, 'd');
+ dfname = queuename(e, DATAFL_LETTER);
setstat(EX_IOERR);
if (errno == ENOSPC)
{
@@ -794,46 +931,54 @@ dferror(df, msg, e)
if (
#if STAT64 > 0
- fstat64(fileno(df), &st)
+ fstat64(sm_io_getinfo(df, SM_IO_WHAT_FD, NULL), &st)
#else /* STAT64 > 0 */
- fstat(fileno(df), &st)
+ fstat(sm_io_getinfo(df, SM_IO_WHAT_FD, NULL), &st)
#endif /* STAT64 > 0 */
< 0)
st.st_size = 0;
- (void) freopen(dfname, "w", df);
+ (void) sm_io_reopen(SmFtStdio, SM_TIME_DEFAULT, dfname,
+ SM_IO_WRONLY, NULL, 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));
+ (void) sm_io_fprintf(df, SM_TIME_DEFAULT,
+ "\n*** Mail could not be accepted");
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",
+ (void) sm_io_fprintf(df, SM_TIME_DEFAULT,
+ "\n*** Mail of at least %llu bytes could not be accepted\n",
+ (ULONGLONG_T) st.st_size);
+ (void) sm_io_fprintf(df, SM_TIME_DEFAULT,
+ "*** at %s due to lack of disk space for temp file.\n",
MyHostName);
- avail = freediskspace(qid_printqueue(e->e_queuedir), &bsize);
+ avail = freediskspace(qid_printqueue(e->e_qgrp, e->e_qdir),
+ &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",
+ (void) sm_io_fprintf(df, SM_TIME_DEFAULT,
+ "*** Currently, %ld kilobytes are available for mail temp files.\n",
avail);
}
+#if 0
+ /* Wrong response code; should be 421. */
e->e_status = "4.3.1";
usrerrenh(e->e_status, "452 Out of disk space for temp file");
+#else /* 0 */
+ syserr("421 4.3.1 Out of disk space for temp file");
+#endif /* 0 */
}
else
- syserr("collect: Cannot write %s (%s, uid=%d)",
- dfname, msg, geteuid());
- if (freopen("/dev/null", "w", df) == NULL)
+ syserr("421 4.3.0 collect: Cannot write %s (%s, uid=%d, gid=%d)",
+ dfname, msg, geteuid(), getegid());
+ if (sm_io_reopen(SmFtStdio, SM_TIME_DEFAULT, SM_PATH_DEVNULL,
+ SM_IO_WRONLY, NULL, df) == NULL)
sm_syslog(LOG_ERR, e->e_id,
- "dferror: freopen(\"/dev/null\") failed: %s",
- errstring(errno));
+ "dferror: sm_io_reopen(\"/dev/null\") failed: %s",
+ sm_errstring(errno));
}
- /*
+/*
** EATFROM -- chew up a UNIX style from line and process
**
** This does indeed make some assumptions about the format
@@ -873,7 +1018,7 @@ eatfrom(fm, e)
register char **dt;
if (tTd(30, 2))
- dprintf("eatfrom(%s)\n", fm);
+ sm_dprintf("eatfrom(%s)\n", fm);
/* find the date part */
p = fm;
@@ -911,13 +1056,12 @@ eatfrom(fm, e)
if (*p != '\0')
{
- char *q;
+ char *q, buf[25];
/* we have found a date */
- q = xalloc(25);
- (void) strlcpy(q, p, 25);
- q = arpadate(q);
- define('a', newstr(q), e);
+ (void) sm_strlcpy(buf, p, sizeof(buf));
+ q = arpadate(buf);
+ macdefine(&e->e_macro, A_TEMP, 'a', q);
}
}
#endif /* ! NOTUNIX */
OpenPOWER on IntegriCloud