diff options
author | gshapiro <gshapiro@FreeBSD.org> | 2000-08-12 21:55:49 +0000 |
---|---|---|
committer | gshapiro <gshapiro@FreeBSD.org> | 2000-08-12 21:55:49 +0000 |
commit | c3cd75415d60bc002b20182ffd3383ea9e901a80 (patch) | |
tree | 211dfd0f771f89d6abe14fa94cab53985a9d0116 /contrib/sendmail/src/collect.c | |
parent | 231592eb7942ebd4becae24ea8e018acea3742a9 (diff) | |
parent | 4332139a9a11f773ffe5109bed871561e3c290a1 (diff) | |
download | FreeBSD-src-c3cd75415d60bc002b20182ffd3383ea9e901a80.zip FreeBSD-src-c3cd75415d60bc002b20182ffd3383ea9e901a80.tar.gz |
This commit was generated by cvs2svn to compensate for changes in r64562,
which included commits to RCS files with non-trunk default branches.
Diffstat (limited to 'contrib/sendmail/src/collect.c')
-rw-r--r-- | contrib/sendmail/src/collect.c | 293 |
1 files changed, 197 insertions, 96 deletions
diff --git a/contrib/sendmail/src/collect.c b/contrib/sendmail/src/collect.c index a8916b1..f6c3682 100644 --- a/contrib/sendmail/src/collect.c +++ b/contrib/sendmail/src/collect.c @@ -1,5 +1,6 @@ /* - * Copyright (c) 1998 Sendmail, Inc. All rights reserved. + * 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. @@ -11,13 +12,17 @@ */ #ifndef lint -static char sccsid[] = "@(#)collect.c 8.93 (Berkeley) 1/26/1999"; -#endif /* not lint */ +static char id[] = "@(#)$Id: collect.c,v 8.136.4.3 2000/06/22 22:13:45 geir Exp $"; +#endif /* ! lint */ -# include <errno.h> -# include "sendmail.h" +#include <sendmail.h> -/* + +static void collecttimeout __P((time_t)); +static void dferror __P((FILE *volatile, char *, ENVELOPE *)); +static void eatfrom __P((char *volatile, ENVELOPE *)); + +/* ** COLLECT -- read & parse message header & make temp file. ** ** Creates a temporary file name and copies the standard @@ -42,7 +47,6 @@ static char sccsid[] = "@(#)collect.c 8.93 (Berkeley) 1/26/1999"; */ static jmp_buf CtxCollectTimeout; -static void collecttimeout __P((time_t)); static bool CollectProgress; static EVENT *CollectTimeout; @@ -66,7 +70,7 @@ collect(fp, smtpmode, hdrp, e) HDR **hdrp; register ENVELOPE *e; { - register FILE *volatile tf; + register FILE *volatile df; volatile bool ignrdot = smtpmode ? FALSE : IgnrDot; volatile time_t dbto = smtpmode ? TimeOuts.to_datablock : 0; register char *volatile bp; @@ -77,13 +81,17 @@ collect(fp, smtpmode, hdrp, e) volatile int buflen; volatile int istate; volatile int mstate; + volatile int hdrslen = 0; + volatile int numhdrs = 0; + volatile int dfd; + volatile int afd; + volatile int rstat = EX_OK; u_char *volatile pbp; - int hdrslen = 0; u_char peekbuf[8]; - char dfname[MAXQFNAME]; + char hsize[16]; + char hnum[16]; + char dfname[MAXPATHLEN]; char bufbuf[MAXLINE]; - extern bool isheader __P((char *)); - extern void tferror __P((FILE *volatile, ENVELOPE *)); headeronly = hdrp != NULL; @@ -93,18 +101,33 @@ collect(fp, smtpmode, hdrp, e) if (!headeronly) { - int tfd; struct stat stbuf; - strcpy(dfname, queuename(e, 'd')); - tfd = dfopen(dfname, O_WRONLY|O_CREAT|O_TRUNC, FileMode, SFF_ANYFILE); - if (tfd < 0 || (tf = fdopen(tfd, "w")) == NULL) + (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_OPENASROOT); + if (bitset(S_IWGRP, QueueFileMode)) + (void) umask(oldumask); + } +#else /* _FFR_QUEUE_FILE_MODE */ + df = bfopen(dfname, FileMode, DataFileBufferSize, + SFF_OPENASROOT); +#endif /* _FFR_QUEUE_FILE_MODE */ + if (df == NULL) { syserr("Cannot create %s", dfname); e->e_flags |= EF_NO_BODY_RETN; finis(TRUE, ExitStat); + /* NOTREACHED */ } - if (fstat(fileno(tf), &stbuf) < 0) + dfd = fileno(df); + if (dfd < 0 || fstat(dfd, &stbuf) < 0) e->e_dfino = -1; else { @@ -124,7 +147,7 @@ collect(fp, smtpmode, hdrp, e) message("354 Enter mail, end with \".\" on a line by itself"); if (tTd(30, 2)) - printf("collect\n"); + dprintf("collect\n"); /* ** Read the message. @@ -152,7 +175,7 @@ collect(fp, smtpmode, hdrp, e) "timeout waiting for input from %s during message collect", CurHostName ? CurHostName : "<local machine>"); errno = 0; - usrerr("451 timeout waiting for input during message collect"); + usrerr("451 4.4.1 timeout waiting for input during message collect"); goto readerr; } CollectTimeout = setevent(dbto, collecttimeout, dbto); @@ -161,7 +184,7 @@ collect(fp, smtpmode, hdrp, e) for (;;) { if (tTd(30, 35)) - printf("top, istate=%d, mstate=%d\n", istate, mstate); + dprintf("top, istate=%d, mstate=%d\n", istate, mstate); for (;;) { if (pbp > peekbuf) @@ -180,12 +203,12 @@ collect(fp, smtpmode, hdrp, e) if (TrafficLogFile != NULL && !headeronly) { if (istate == IS_BOL) - fprintf(TrafficLogFile, "%05d <<< ", + (void) fprintf(TrafficLogFile, "%05d <<< ", (int) getpid()); if (c == EOF) - fprintf(TrafficLogFile, "[EOF]\n"); + (void) fprintf(TrafficLogFile, "[EOF]\n"); else - putc(c, TrafficLogFile); + (void) putc(c, TrafficLogFile); } if (c == EOF) goto readerr; @@ -195,8 +218,8 @@ collect(fp, smtpmode, hdrp, e) HasEightBits |= bitset(0x80, c); } if (tTd(30, 94)) - printf("istate=%d, c=%c (0x%x)\n", - istate, c, c); + dprintf("istate=%d, c=%c (0x%x)\n", + istate, (char) c, c); switch (istate) { case IS_BOL: @@ -244,7 +267,7 @@ collect(fp, smtpmode, hdrp, e) istate = IS_BOL; else { - ungetc(c, fp); + (void) ungetc(c, fp); c = '\r'; istate = IS_NORM; } @@ -270,9 +293,9 @@ bufferchar: /* just put the character out */ if (MaxMessageSize <= 0 || e->e_msgsize <= MaxMessageSize) - putc(c, tf); + (void) putc(c, df); - /* fall through */ + /* FALLTHROUGH */ case MS_DISCARD: continue; @@ -293,16 +316,18 @@ bufferchar: else buflen += MEMCHUNKSIZE; buf = xalloc(buflen); - bcopy(obuf, buf, bp - obuf); + memmove(buf, obuf, bp - obuf); bp = &buf[bp - obuf]; if (obuf != bufbuf) free(obuf); } if (c >= 0200 && c <= 0237) { -#if 0 /* causes complaints -- figure out something for 8.9 */ +#if 0 /* causes complaints -- figure out something for 8.11 */ usrerr("Illegal character 0x%x in header", c); -#endif +#else /* 0 */ + /* EMPTY */ +#endif /* 0 */ } else if (c != '\0') { @@ -317,8 +342,9 @@ bufferchar: errno = 0; e->e_flags |= EF_CLRQUEUE; e->e_status = "5.6.0"; - usrerr("552 Headers too large (%d max)", - MaxHeadersLength); + usrerrenh(e->e_status, + "552 Headers too large (%d max)", + MaxHeadersLength); mstate = MS_DISCARD; } } @@ -329,7 +355,7 @@ bufferchar: nextstate: if (tTd(30, 35)) - printf("nextstate, istate=%d, mstate=%d, line = \"%s\"\n", + dprintf("nextstate, istate=%d, mstate=%d, line = \"%s\"\n", istate, mstate, buf); switch (mstate) { @@ -338,14 +364,12 @@ nextstate: #ifndef NOTUNIX if (strncmp(buf, "From ", 5) == 0) { - extern void eatfrom __P((char *volatile, ENVELOPE *)); - bp = buf; eatfrom(buf, e); continue; } -#endif - /* fall through */ +#endif /* ! NOTUNIX */ + /* FALLTHROUGH */ case MS_HEADER: if (!isheader(buf)) @@ -362,7 +386,7 @@ nextstate: c = getc(fp); } while (errno == EINTR); if (c != EOF) - ungetc(c, fp); + (void) ungetc(c, fp); if (c == ' ' || c == '\t') { /* yep -- defer this */ @@ -374,18 +398,32 @@ nextstate: bp++; *bp = '\0'; - if (bitset(H_EOH, chompheader(buf, FALSE, hdrp, e))) + 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)) - printf("EOH\n"); + 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); + bp = buf; /* toss blank line */ @@ -402,7 +440,7 @@ nextstate: e->e_msgsize <= MaxMessageSize) { while (*bp != '\0') - putc(*bp++, tf); + (void) putc(*bp++, df); } break; } @@ -415,7 +453,7 @@ readerr: const char *errmsg = errstring(errno); if (tTd(30, 1)) - printf("collect: premature EOM: %s\n", errmsg); + dprintf("collect: premature EOM: %s\n", errmsg); if (LogLevel >= 2) sm_syslog(LOG_WARNING, e->e_id, "collect: premature EOM: %s", errmsg); @@ -428,14 +466,65 @@ readerr: if (headeronly) return; - if (tf != NULL && - (fflush(tf) != 0 || ferror(tf) || - (SuperSafe && fsync(fileno(tf)) < 0) || - fclose(tf) < 0)) + if (df == NULL) { - tferror(tf, e); + /* 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, 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 */ @@ -461,11 +550,11 @@ readerr: shortenstring(e->e_from.q_paddr, MAXSHORTSTR), errstring(errno)); if (feof(fp)) - usrerr("451 collect: %s on connection from %s, from=%s", + 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 collect: %s on connection from %s, from=%s", + syserr("451 4.4.1 collect: %s on connection from %s, from=%s", problem, host, shortenstring(e->e_from.q_paddr, MAXSHORTSTR)); @@ -478,6 +567,7 @@ readerr: if (InChild) ExitStat = EX_QUIT; finis(TRUE, ExitStat); + /* NOTREACHED */ } /* @@ -494,7 +584,6 @@ readerr: if (OpMode != MD_VERIFY) markstats(e, (ADDRESS *) NULL, FALSE); -#if _FFR_DSN_RRT_OPTION /* ** If we have a Return-Receipt-To:, turn it into a DSN. */ @@ -507,7 +596,6 @@ readerr: if (!bitset(QHASNOTIFY, q->q_flags)) q->q_flags |= QHASNOTIFY|QPINGONSUCCESS; } -#endif /* ** Add an Apparently-To: line if we have no recipient lines. @@ -539,11 +627,11 @@ readerr: break; case NRA_ADD_BCC: - addheader("Bcc", " ", &e->e_header); + addheader("Bcc", " ", 0, &e->e_header); break; case NRA_ADD_TO_UNDISCLOSED: - addheader("To", "undisclosed-recipients:;", &e->e_header); + addheader("To", "undisclosed-recipients:;", 0, &e->e_header); break; } @@ -554,9 +642,9 @@ readerr: if (q->q_alias != NULL) continue; if (tTd(30, 3)) - printf("Adding %s: %s\n", + dprintf("Adding %s: %s\n", hdr, q->q_paddr); - addheader(hdr, q->q_paddr, &e->e_header); + addheader(hdr, q->q_paddr, 0, &e->e_header); } } } @@ -566,8 +654,9 @@ readerr: { e->e_flags |= EF_NO_BODY_RETN|EF_CLRQUEUE; e->e_status = "5.2.3"; - usrerr("552 Message exceeds maximum fixed size (%ld)", - MaxMessageSize); + 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)", @@ -582,7 +671,7 @@ readerr: !bitset(EF_IS_MIME, e->e_flags)) { e->e_status = "5.6.1"; - usrerr("554 Eight bit data not allowed"); + usrerrenh(e->e_status, "554 Eight bit data not allowed"); } } else @@ -593,12 +682,20 @@ readerr: e->e_bodytype = "7BIT"; } - if ((e->e_dfp = fopen(dfname, "r")) == NULL) + if (SuperSafe) { - /* we haven't acked receipt yet, so just chuck this */ - syserr("Cannot reopen %s", dfname); - finis(TRUE, ExitStat); + 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"); } @@ -614,11 +711,12 @@ collecttimeout(timeout) CollectTimeout = setevent(timeout, collecttimeout, timeout); CollectProgress = FALSE; } -/* -** TFERROR -- signal error on writing the temporary file. +/* +** DFERROR -- signal error on writing the data file. ** ** Parameters: -** tf -- the file pointer for the temporary file. +** df -- the file pointer for the data file. +** msg -- detailed message. ** e -- the current envelope. ** ** Returns: @@ -629,62 +727,67 @@ collecttimeout(timeout) ** Arranges for following output to go elsewhere. */ -void -tferror(tf, e) - FILE *volatile tf; +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 +#else /* STAT64 > 0 */ struct stat st; -#endif +#endif /* STAT64 > 0 */ long avail; long bsize; - extern long freediskspace __P((char *, long *)); e->e_flags |= EF_NO_BODY_RETN; if ( #if STAT64 > 0 - fstat64(fileno(tf), &st) -#else - fstat(fileno(tf), &st) -#endif + fstat64(fileno(df), &st) +#else /* STAT64 > 0 */ + fstat(fileno(df), &st) +#endif /* STAT64 > 0 */ < 0) st.st_size = 0; - (void) freopen(queuename(e, 'd'), "w", tf); + (void) freopen(dfname, "w", df); if (st.st_size <= 0) - fprintf(tf, "\n*** Mail could not be accepted"); + fprintf(df, "\n*** Mail could not be accepted"); + /*CONSTCOND*/ else if (sizeof st.st_size > sizeof (long)) - fprintf(tf, "\n*** Mail of at least %s bytes could not be accepted\n", + fprintf(df, "\n*** Mail of at least %s bytes could not be accepted\n", quad_to_string(st.st_size)); else - fprintf(tf, "\n*** Mail of at least %lu bytes could not be accepted\n", + fprintf(df, "\n*** Mail of at least %lu bytes could not be accepted\n", (unsigned long) st.st_size); - fprintf(tf, "*** at %s due to lack of disk space for temp file.\n", + fprintf(df, "*** at %s due to lack of disk space for temp file.\n", MyHostName); - avail = freediskspace(QueueDir, &bsize); + 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(tf, "*** Currently, %ld kilobytes are available for mail temp files.\n", + fprintf(df, "*** Currently, %ld kilobytes are available for mail temp files.\n", avail); } e->e_status = "4.3.1"; - usrerr("452 Out of disk space for temp file"); + usrerrenh(e->e_status, "452 Out of disk space for temp file"); } else - syserr("collect: Cannot write tf%s", e->e_id); - if (freopen("/dev/null", "w", tf) == NULL) + 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, - "tferror: freopen(\"/dev/null\") failed: %s", + "dferror: freopen(\"/dev/null\") failed: %s", errstring(errno)); } /* @@ -704,21 +807,21 @@ tferror(tf, e) ** such as the date. */ -# ifndef NOTUNIX +#ifndef NOTUNIX -char *DowList[] = +static char *DowList[] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", NULL }; -char *MonthList[] = +static char *MonthList[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", NULL }; -void +static void eatfrom(fm, e) char *volatile fm; register ENVELOPE *e; @@ -727,7 +830,7 @@ eatfrom(fm, e) register char **dt; if (tTd(30, 2)) - printf("eatfrom(%s)\n", fm); + dprintf("eatfrom(%s)\n", fm); /* find the date part */ p = fm; @@ -762,11 +865,9 @@ eatfrom(fm, e) /* we have found a date */ q = xalloc(25); - (void) strncpy(q, p, 25); - q[24] = '\0'; + (void) strlcpy(q, p, 25); q = arpadate(q); define('a', newstr(q), e); } } - -# endif /* NOTUNIX */ +#endif /* ! NOTUNIX */ |