diff options
author | gshapiro <gshapiro@FreeBSD.org> | 2002-02-17 21:56:45 +0000 |
---|---|---|
committer | gshapiro <gshapiro@FreeBSD.org> | 2002-02-17 21:56:45 +0000 |
commit | 8449595fe97f4474b9b9a7e4edee1ef35dcff393 (patch) | |
tree | e7a33b132264d449a512ddf4a8685df097669c1d /contrib/sendmail/src/collect.c | |
parent | 289b381b31415647269c7520d881017e2dcb27f1 (diff) | |
download | FreeBSD-src-8449595fe97f4474b9b9a7e4edee1ef35dcff393.zip FreeBSD-src-8449595fe97f4474b9b9a7e4edee1ef35dcff393.tar.gz |
Import sendmail 8.12.2
Diffstat (limited to 'contrib/sendmail/src/collect.c')
-rw-r--r-- | contrib/sendmail/src/collect.c | 714 |
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 */ |