diff options
Diffstat (limited to 'contrib/sendmail/src/collect.c')
-rw-r--r-- | contrib/sendmail/src/collect.c | 179 |
1 files changed, 87 insertions, 92 deletions
diff --git a/contrib/sendmail/src/collect.c b/contrib/sendmail/src/collect.c index 101bcd047c51..0bfe3f2d48a8 100644 --- a/contrib/sendmail/src/collect.c +++ b/contrib/sendmail/src/collect.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998-2004 Sendmail, Inc. and its suppliers. + * 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 @@ -13,9 +13,8 @@ #include <sendmail.h> -SM_RCSID("@(#)$Id: collect.c,v 8.261 2005/02/16 23:38:51 ca Exp $") +SM_RCSID("@(#)$Id: collect.c,v 8.272 2006/03/02 19:09:26 ca Exp $") -static void collecttimeout __P((int)); static void eatfrom __P((char *volatile, ENVELOPE *)); static void collect_doheader __P((ENVELOPE *)); static SM_FILE_T *collect_dfopen __P((ENVELOPE *)); @@ -263,10 +262,6 @@ collect_dfopen(e) ** If data file cannot be created, the process is terminated. */ -static jmp_buf CtxCollectTimeout; -static bool volatile CollectProgress; -static SM_EVENT *volatile CollectTimeout = NULL; - /* values for input state machine */ #define IS_NORM 0 /* middle of line */ #define IS_BOL 1 /* beginning of line */ @@ -288,27 +283,31 @@ collect(fp, smtpmode, hdrp, e, rsetsize) register ENVELOPE *e; bool rsetsize; { - register SM_FILE_T *volatile df; - volatile bool ignrdot; - volatile int dbto; - register char *volatile bp; - volatile int c; - volatile bool inputerr; + register SM_FILE_T *df; + bool ignrdot; + int dbto; + register char *bp; + int c; + bool inputerr; bool headeronly; - char *volatile buf; - volatile int buflen; - volatile int istate; - volatile int mstate; - volatile int hdrslen; - volatile int numhdrs; - volatile int afd; - unsigned char *volatile pbp; + 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; - dbto = smtpmode ? (int) TimeOuts.to_datablock : 0; + + /* 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; @@ -320,7 +319,6 @@ collect(fp, smtpmode, hdrp, e, rsetsize) pbp = peekbuf; istate = IS_BOL; mstate = SaveFrom ? MS_HEADER : MS_UFROM; - CollectProgress = false; /* ** Tell ARPANET to go ahead. @@ -329,6 +327,10 @@ collect(fp, smtpmode, hdrp, e, rsetsize) 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"); @@ -341,32 +343,6 @@ collect(fp, smtpmode, hdrp, e, rsetsize) ** the larger picture (e.g., header versus body). */ - if (dbto != 0) - { - /* handle possible input timeout */ - if (setjmp(CtxCollectTimeout) != 0) - { - if (LogLevel > 2) - sm_syslog(LOG_NOTICE, e->e_id, - "timeout waiting for input from %s during message collect", - CURHOSTNAME); - errno = 0; - if (smtpmode) - { - /* - ** Override e_message in usrerr() as this - ** is the reason for failure that should - ** be logged for undelivered recipients. - */ - - e->e_message = NULL; - } - usrerr("451 4.4.1 timeout waiting for input during message collect"); - goto readerr; - } - CollectTimeout = sm_setevent(dbto, collecttimeout, dbto); - } - if (rsetsize) e->e_msgsize = 0; for (;;) @@ -390,9 +366,26 @@ collect(fp, smtpmode, hdrp, e, rsetsize) 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; } - CollectProgress = true; if (TrafficLogFile != NULL && !headeronly) { if (istate == IS_BOL) @@ -446,7 +439,8 @@ collect(fp, smtpmode, hdrp, e, rsetsize) OpMode != MD_ARPAFTP)) { - SM_ASSERT(pbp < peekbuf + sizeof(peekbuf)); + SM_ASSERT(pbp < peekbuf + + sizeof(peekbuf)); *pbp++ = c; c = '.'; } @@ -458,7 +452,8 @@ collect(fp, smtpmode, hdrp, e, rsetsize) else { /* push back the ".\rx" */ - SM_ASSERT(pbp < peekbuf + sizeof(peekbuf)); + SM_ASSERT(pbp < peekbuf + + sizeof(peekbuf)); *pbp++ = c; if (OpMode != MD_SMTP && OpMode != MD_DAEMON && @@ -538,6 +533,18 @@ bufferchar: 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]; @@ -581,6 +588,7 @@ bufferchar: usrerrenh(e->e_status, "552 Headers too large (%d max)", MaxHeadersLength); + discard: mstate = MS_DISCARD; } } @@ -620,6 +628,24 @@ nextstate: 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); @@ -629,8 +655,12 @@ nextstate: continue; } - /* trim off trailing CRLF or NL */ 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'; @@ -696,10 +726,6 @@ readerr: inputerr = true; } - /* reset global timer */ - if (CollectTimeout != NULL) - sm_clrevent(CollectTimeout); - if (headeronly) return; @@ -786,6 +812,7 @@ readerr: } /* An EOF when running SMTP is an error */ + readabort: if (inputerr && (OpMode == MD_SMTP || OpMode == MD_DAEMON)) { char *host; @@ -808,13 +835,14 @@ readerr: 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", + usrerr("421 4.4.1 collect: %s on connection from %s, from=%s", problem, host, shortenstring(e->e_from.q_paddr, MAXSHORTSTR)); else - syserr("451 4.4.1 collect: %s on connection from %s, from=%s", + 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; @@ -907,39 +935,6 @@ readerr: } } -static void -collecttimeout(timeout) - int timeout; -{ - int save_errno = errno; - - /* - ** NOTE: THIS CAN BE CALLED FROM A SIGNAL HANDLER. DO NOT ADD - ** ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE - ** DOING. - */ - - if (CollectProgress) - { - /* reset the timeout */ - CollectTimeout = sm_sigsafe_setevent(timeout, collecttimeout, - timeout); - CollectProgress = false; - } - else - { - /* event is done */ - CollectTimeout = NULL; - } - - /* if no progress was made or problem resetting event, die now */ - if (CollectTimeout == NULL) - { - errno = ETIMEDOUT; - longjmp(CtxCollectTimeout, 1); - } - errno = save_errno; -} /* ** DFERROR -- signal error on writing the data file. ** |