diff options
author | peter <peter@FreeBSD.org> | 2008-08-28 02:25:51 +0000 |
---|---|---|
committer | peter <peter@FreeBSD.org> | 2008-08-28 02:25:51 +0000 |
commit | ea50d71feb02a78d4d5fa746a26ca7ddc6e8cb19 (patch) | |
tree | daf40952cf309641cc6c7d987989fd2abce2d758 /contrib/sendmail/src/collect.c | |
parent | a2b986fa722f9860a6c56bb5cc724b7e2937d1b7 (diff) | |
download | FreeBSD-src-ea50d71feb02a78d4d5fa746a26ca7ddc6e8cb19.zip FreeBSD-src-ea50d71feb02a78d4d5fa746a26ca7ddc6e8cb19.tar.gz |
Stage 1 of sendmail dist tree flattening. contrib/sendmail/contrib
prevents doing this in one pass.
Diffstat (limited to 'contrib/sendmail/src/collect.c')
-rw-r--r-- | contrib/sendmail/src/collect.c | 1101 |
1 files changed, 0 insertions, 1101 deletions
diff --git a/contrib/sendmail/src/collect.c b/contrib/sendmail/src/collect.c deleted file mode 100644 index 56fed0a..0000000 --- a/contrib/sendmail/src/collect.c +++ /dev/null @@ -1,1101 +0,0 @@ -/* - * Copyright (c) 1998-2006 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: collect.c,v 8.280 2006/11/29 00:20:40 ca Exp $") - -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, RSF_UNSTRUCTURED|RSF_COUNT, - 3, NULL, e->e_id, NULL); - - /* - ** 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"); - - /* - ** 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, true); - break; - - case NRA_ADD_TO_UNDISCLOSED: - addheader("To", "undisclosed-recipients:;", 0, e, true); - 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, true); - } - } - } -} - -/* -** 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(false, 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 -** input to that file. Leading UNIX-style "From" lines are -** stripped off (after important information is extracted). -** -** Parameters: -** fp -- file to read. -** smtpmode -- if set, we are running SMTP: give an RFC821 -** style message to say we are ready to collect -** input, and never ignore a single dot to mean -** end of message. -** hdrp -- the location to stash the header. -** e -- the current envelope. -** rsetsize -- reset e_msgsize? -** -** Returns: -** none. -** -** Side Effects: -** 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. -*/ - -/* values for input state machine */ -#define IS_NORM 0 /* middle of line */ -#define IS_BOL 1 /* beginning of line */ -#define IS_DOT 2 /* read a dot at beginning of line */ -#define IS_DOTCR 3 /* read ".\r" at beginning of line */ -#define IS_CR 4 /* read a carriage return */ - -/* values for message state machine */ -#define MS_UFROM 0 /* reading Unix from line */ -#define MS_HEADER 1 /* reading message header */ -#define MS_BODY 2 /* reading message body */ -#define MS_DISCARD 3 /* discarding rest of message */ - -void -collect(fp, smtpmode, hdrp, e, rsetsize) - SM_FILE_T *fp; - bool smtpmode; - HDR **hdrp; - register ENVELOPE *e; - bool rsetsize; -{ - register SM_FILE_T *df; - bool ignrdot; - int dbto; - register char *bp; - int c; - bool inputerr; - bool headeronly; - char *buf; - int buflen; - int istate; - int mstate; - int hdrslen; - int numhdrs; - int afd; - unsigned char *pbp; - unsigned char peekbuf[8]; - char bufbuf[MAXLINE]; - - df = NULL; - ignrdot = smtpmode ? false : IgnrDot; - - /* timeout for I/O functions is in milliseconds */ - dbto = smtpmode ? ((int) TimeOuts.to_datablock * 1000) - : SM_TIME_FOREVER; - sm_io_setinfo(fp, SM_IO_WHAT_TIMEOUT, &dbto); - c = SM_IO_EOF; - inputerr = false; - headeronly = hdrp != NULL; - hdrslen = 0; - numhdrs = 0; - HasEightBits = false; - buf = bp = bufbuf; - buflen = sizeof(bufbuf); - pbp = peekbuf; - istate = IS_BOL; - mstate = SaveFrom ? MS_HEADER : MS_UFROM; - - /* - ** Tell ARPANET to go ahead. - */ - - if (smtpmode) - message("354 Enter mail, end with \".\" on a line by itself"); - - /* simulate an I/O timeout when used as sink */ - if (tTd(83, 101)) - sleep(319); - - if (tTd(30, 2)) - sm_dprintf("collect\n"); - - /* - ** Read the message. - ** - ** This is done using two interleaved state machines. - ** The input state machine is looking for things like - ** hidden dots; the message state machine is handling - ** the larger picture (e.g., header versus body). - */ - - if (rsetsize) - e->e_msgsize = 0; - for (;;) - { - if (tTd(30, 35)) - sm_dprintf("top, istate=%d, mstate=%d\n", istate, - mstate); - for (;;) - { - if (pbp > peekbuf) - c = *--pbp; - else - { - while (!sm_io_eof(fp) && !sm_io_error(fp)) - { - errno = 0; - c = sm_io_getc(fp, SM_TIME_DEFAULT); - if (c == SM_IO_EOF && errno == EINTR) - { - /* Interrupted, retry */ - sm_io_clearerr(fp); - continue; - } - - /* timeout? */ - if (c == SM_IO_EOF && errno == EAGAIN - && smtpmode) - { - /* - ** Override e_message in - ** usrerr() as this is the - ** reason for failure that - ** should be logged for - ** undelivered recipients. - */ - - e->e_message = NULL; - errno = 0; - inputerr = true; - goto readabort; - } - break; - } - if (TrafficLogFile != NULL && !headeronly) - { - if (istate == IS_BOL) - (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) sm_io_putc(TrafficLogFile, - SM_TIME_DEFAULT, - c); - } - if (c == SM_IO_EOF) - goto readerr; - if (SevenBitInput) - c &= 0x7f; - else - HasEightBits |= bitset(0x80, c); - } - if (tTd(30, 94)) - sm_dprintf("istate=%d, c=%c (0x%x)\n", - istate, (char) c, c); - switch (istate) - { - case IS_BOL: - if (c == '.') - { - istate = IS_DOT; - continue; - } - break; - - case IS_DOT: - if (c == '\n' && !ignrdot && - !bitset(EF_NL_NOT_EOL, e->e_flags)) - goto readerr; - else if (c == '\r' && - !bitset(EF_CRLF_NOT_EOL, e->e_flags)) - { - istate = IS_DOTCR; - continue; - } - else if (ignrdot || - (c != '.' && - OpMode != MD_SMTP && - OpMode != MD_DAEMON && - OpMode != MD_ARPAFTP)) - - { - SM_ASSERT(pbp < peekbuf + - sizeof(peekbuf)); - *pbp++ = c; - c = '.'; - } - break; - - case IS_DOTCR: - if (c == '\n' && !ignrdot) - goto readerr; - else - { - /* push back the ".\rx" */ - SM_ASSERT(pbp < peekbuf + - sizeof(peekbuf)); - *pbp++ = c; - if (OpMode != MD_SMTP && - OpMode != MD_DAEMON && - OpMode != MD_ARPAFTP) - { - SM_ASSERT(pbp < peekbuf + - sizeof(peekbuf)); - *pbp++ = '\r'; - c = '.'; - } - else - c = '\r'; - } - break; - - case IS_CR: - if (c == '\n') - istate = IS_BOL; - else - { - (void) sm_io_ungetc(fp, SM_TIME_DEFAULT, - c); - c = '\r'; - istate = IS_NORM; - } - goto bufferchar; - } - - if (c == '\r' && !bitset(EF_CRLF_NOT_EOL, e->e_flags)) - { - istate = IS_CR; - continue; - } - else if (c == '\n' && !bitset(EF_NL_NOT_EOL, - e->e_flags)) - istate = IS_BOL; - else - istate = IS_NORM; - -bufferchar: - if (!headeronly) - { - /* no overflow? */ - if (e->e_msgsize >= 0) - { - e->e_msgsize++; - if (MaxMessageSize > 0 && - !bitset(EF_TOOBIG, e->e_flags) && - e->e_msgsize > MaxMessageSize) - e->e_flags |= EF_TOOBIG; - } - } - switch (mstate) - { - case MS_BODY: - /* just put the character out */ - if (!bitset(EF_TOOBIG, e->e_flags)) - (void) sm_io_putc(df, SM_TIME_DEFAULT, - c); - - /* FALLTHROUGH */ - - case MS_DISCARD: - continue; - } - - SM_ASSERT(mstate == MS_UFROM || mstate == MS_HEADER); - - /* header -- buffer up */ - if (bp >= &buf[buflen - 2]) - { - char *obuf; - - /* out of space for header */ - obuf = buf; - if (buflen < MEMCHUNKSIZE) - buflen *= 2; - else - buflen += MEMCHUNKSIZE; - if (buflen <= 0) - { - sm_syslog(LOG_NOTICE, e->e_id, - "header overflow from %s during message collect", - CURHOSTNAME); - errno = 0; - e->e_flags |= EF_CLRQUEUE; - e->e_status = "5.6.0"; - usrerrenh(e->e_status, - "552 Headers too large"); - goto discard; - } - buf = xalloc(buflen); - memmove(buf, obuf, bp - obuf); - bp = &buf[bp - obuf]; - if (obuf != bufbuf) - sm_free(obuf); /* XXX */ - } - - if (c != '\0') - { - *bp++ = c; - ++hdrslen; - if (!headeronly && - MaxHeadersLength > 0 && - hdrslen > MaxHeadersLength) - { - sm_syslog(LOG_NOTICE, e->e_id, - "headers too large (%d max) from %s during message collect", - MaxHeadersLength, - CURHOSTNAME); - errno = 0; - e->e_flags |= EF_CLRQUEUE; - e->e_status = "5.6.0"; - usrerrenh(e->e_status, - "552 Headers too large (%d max)", - MaxHeadersLength); - discard: - mstate = MS_DISCARD; - } - } - if (istate == IS_BOL) - break; - } - *bp = '\0'; - -nextstate: - if (tTd(30, 35)) - sm_dprintf("nextstate, istate=%d, mstate=%d, line=\"%s\"\n", - istate, mstate, buf); - switch (mstate) - { - case MS_UFROM: - mstate = MS_HEADER; -#ifndef NOTUNIX - if (strncmp(buf, "From ", 5) == 0) - { - bp = buf; - eatfrom(buf, e); - continue; - } -#endif /* ! NOTUNIX */ - /* FALLTHROUGH */ - - case MS_HEADER: - if (!isheader(buf)) - { - mstate = MS_BODY; - goto nextstate; - } - - /* check for possible continuation line */ - do - { - sm_io_clearerr(fp); - errno = 0; - c = sm_io_getc(fp, SM_TIME_DEFAULT); - - /* timeout? */ - if (c == SM_IO_EOF && errno == EAGAIN - && smtpmode) - { - /* - ** Override e_message in - ** usrerr() as this is the - ** reason for failure that - ** should be logged for - ** undelivered recipients. - */ - - e->e_message = NULL; - errno = 0; - inputerr = true; - goto readabort; - } - } 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 */ - continue; - } - - SM_ASSERT(bp > buf); - - /* guaranteed by isheader(buf) */ - SM_ASSERT(*(bp - 1) != '\n' || bp > buf + 1); - - /* trim off trailing CRLF or NL */ - if (*--bp != '\n' || *--bp != '\r') - bp++; - *bp = '\0'; - - if (bitset(H_EOH, chompheader(buf, - CHHDR_CHECK | CHHDR_USER, - hdrp, e))) - { - mstate = MS_BODY; - goto nextstate; - } - numhdrs++; - break; - - case MS_BODY: - if (tTd(30, 1)) - sm_dprintf("EOH\n"); - - if (headeronly) - goto readerr; - - df = collect_eoh(e, numhdrs, hdrslen); - if (df == NULL) - e->e_flags |= EF_TOOBIG; - - bp = buf; - - /* toss blank line */ - if ((!bitset(EF_CRLF_NOT_EOL, e->e_flags) && - 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) sm_io_putc(df, SM_TIME_DEFAULT, - *bp++); - } - break; - } - bp = buf; - } - -readerr: - if ((sm_io_eof(fp) && smtpmode) || sm_io_error(fp)) - { - const char *errmsg; - - if (sm_io_eof(fp)) - errmsg = "unexpected close"; - else - errmsg = sm_errstring(errno); - if (tTd(30, 1)) - 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; - } - - 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 (sm_io_flush(df, SM_TIME_DEFAULT) != 0 || sm_io_error(df)) - { - dferror(df, "sm_io_flush||sm_io_error", e); - flush_errors(true); - finis(true, true, ExitStat); - /* NOTREACHED */ - } - else if (SuperSafe == SAFE_NO || - SuperSafe == SAFE_INTERACTIVE || - (SuperSafe == SAFE_REALLY_POSTMILTER && smtpmode)) - { - /* skip next few clauses */ - /* EMPTY */ - /* Note: updfs() is not called in this case! */ - } - else if (sm_io_setinfo(df, SM_BF_COMMIT, NULL) < 0 && errno != EINVAL) - { - int save_errno = errno; - - if (save_errno == EEXIST) - { - char *dfile; - struct stat st; - int dfd; - - 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", - dfile, (long) st.st_size); - dfd = sm_io_getinfo(df, SM_IO_WHAT_FD, NULL); - if (dfd >= 0) - dumpfd(dfd, true, true); - } - errno = save_errno; - dferror(df, "bfcommit", e); - flush_errors(true); - finis(save_errno != EEXIST, true, ExitStat); - } - else if ((afd = sm_io_getinfo(df, SM_IO_WHAT_FD, NULL)) < 0) - { - dferror(df, "sm_io_getinfo", e); - flush_errors(true); - finis(true, true, ExitStat); - /* NOTREACHED */ - } - else if (fsync(afd) < 0) - { - dferror(df, "fsync", e); - flush_errors(true); - finis(true, true, ExitStat); - /* NOTREACHED */ - } - else if (sm_io_close(df, SM_TIME_DEFAULT) < 0) - { - 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, 0, 1, "collect"); - } - - /* An EOF when running SMTP is an error */ - readabort: - if (inputerr && (OpMode == MD_SMTP || OpMode == MD_DAEMON)) - { - char *host; - char *problem; - ADDRESS *q; - - host = RealHostName; - if (host == NULL) - host = "localhost"; - - if (sm_io_eof(fp)) - problem = "unexpected close"; - else if (sm_io_error(fp)) - problem = "I/O error"; - else - problem = "read timeout"; - if (LogLevel > 0 && sm_io_eof(fp)) - sm_syslog(LOG_NOTICE, e->e_id, - "collect: %s on connection from %.100s, sender=%s", - problem, host, - shortenstring(e->e_from.q_paddr, MAXSHORTSTR)); - if (sm_io_eof(fp)) - usrerr("421 4.4.1 collect: %s on connection from %s, from=%s", - problem, host, - shortenstring(e->e_from.q_paddr, MAXSHORTSTR)); - else - syserr("421 4.4.1 collect: %s on connection from %s, from=%s", - problem, host, - shortenstring(e->e_from.q_paddr, MAXSHORTSTR)); - flush_errors(true); - - /* don't return an error indication */ - e->e_to = NULL; - e->e_flags &= ~EF_FATALERRS; - e->e_flags |= EF_CLRQUEUE; - - /* Don't send any message notification to sender */ - for (q = e->e_sendqueue; q != NULL; q = q->q_next) - { - if (QS_IS_DEAD(q->q_state)) - continue; - q->q_state = QS_FATALERR; - } - - (void) sm_io_close(df, SM_TIME_DEFAULT); - df = NULL; - finis(true, true, ExitStat); - /* NOTREACHED */ - } - - /* Log collection information. */ - if (bitset(EF_LOGSENDER, e->e_flags) && LogLevel > 4) - { - 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; - 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 */ - 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 && - sm_strcasecmp(e->e_bodytype, "8BITMIME") == 0) - e->e_bodytype = "7BIT"; - } - - if (SuperSafe == SAFE_REALLY && !bitset(EF_FATALERRS, e->e_flags)) - { - char *dfname = queuename(e, DATAFL_LETTER); - if ((e->e_dfp = sm_io_open(SmFtStdio, SM_TIME_DEFAULT, dfname, - SM_IO_RDONLY_B, NULL)) == NULL) - { - /* we haven't acked receipt yet, so just chuck this */ - syserr("@Cannot reopen %s", dfname); - finis(true, true, ExitStat); - /* NOTREACHED */ - } - } - else - e->e_dfp = df; - - /* collect statistics */ - if (OpMode != MD_VERIFY) - { - /* - ** Recalculate e_msgpriority, it is done at in eatheader() - ** which is called (in 8.12) after the header is collected, - ** hence e_msgsize is (most likely) incorrect. - */ - - e->e_msgpriority = e->e_msgsize - - e->e_class * WkClassFact - + e->e_nrcpts * WkRecipFact; - markstats(e, (ADDRESS *) NULL, STATS_NORMAL); - } -} - -/* -** 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. -** e -- the current envelope. -** -** Returns: -** none. -** -** Side Effects: -** Gives an error message. -** Arranges for following output to go elsewhere. -*/ - -void -dferror(df, msg, e) - SM_FILE_T *volatile df; - char *msg; - register ENVELOPE *e; -{ - char *dfname; - - dfname = queuename(e, DATAFL_LETTER); - 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(sm_io_getinfo(df, SM_IO_WHAT_FD, NULL), &st) -#else /* STAT64 > 0 */ - fstat(sm_io_getinfo(df, SM_IO_WHAT_FD, NULL), &st) -#endif /* STAT64 > 0 */ - < 0) - st.st_size = 0; - (void) sm_io_reopen(SmFtStdio, SM_TIME_DEFAULT, dfname, - SM_IO_WRONLY_B, NULL, df); - if (st.st_size <= 0) - (void) sm_io_fprintf(df, SM_TIME_DEFAULT, - "\n*** Mail could not be accepted"); - else - (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_qgrp, e->e_qdir), - &bsize); - if (avail > 0) - { - if (bsize > 1024) - avail *= bsize / 1024; - else if (bsize < 1024) - avail /= 1024 / bsize; - (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("421 4.3.0 collect: Cannot write %s (%s, uid=%d, gid=%d)", - dfname, msg, (int) geteuid(), (int) 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: 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 -** of UNIX messages. -** -** Parameters: -** fm -- the from line. -** e -- envelope -** -** 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)) - sm_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 (strlen(p) < 17) - { - /* no room for the date */ - return; - } - 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, buf[25]; - - /* we have found a date */ - (void) sm_strlcpy(buf, p, sizeof(buf)); - q = arpadate(buf); - macdefine(&e->e_macro, A_TEMP, 'a', q); - } -} -#endif /* ! NOTUNIX */ |