Apply by doing:
       cd /usr/src
       patch -p0 < 012_sendmail.patch

And then rebuild and install sendmail:
       cd gnu/usr.sbin/sendmail
       make obj
       make depend
       make
       make install

Index: gnu/usr.sbin/sendmail/libsm/fflush.c
===================================================================
RCS file: /cvs/src/gnu/usr.sbin/sendmail/libsm/fflush.c,v
retrieving revision 1.2
diff -u -p -r1.2 fflush.c
--- gnu/usr.sbin/sendmail/libsm/fflush.c        1 Oct 2001 17:18:29 -0000       1.2
+++ gnu/usr.sbin/sendmail/libsm/fflush.c        24 Mar 2006 00:50:46 -0000
@@ -145,6 +145,7 @@ sm_flush(fp, timeout)
                               return SM_IO_EOF;
                       }
                       SM_IO_WR_TIMEOUT(fp, fd, *timeout);
+                       t = 0;
               }
       }
       return 0;
Index: gnu/usr.sbin/sendmail/libsm/local.h
===================================================================
RCS file: /cvs/src/gnu/usr.sbin/sendmail/libsm/local.h,v
retrieving revision 1.6
diff -u -p -r1.6 local.h
--- gnu/usr.sbin/sendmail/libsm/local.h 24 Jun 2004 03:59:26 -0000      1.6
+++ gnu/usr.sbin/sendmail/libsm/local.h 24 Mar 2006 00:50:46 -0000
@@ -192,7 +192,7 @@ extern const char SmFileMagic[];
       else \
       { \
               (time)->tv_sec = (val) / 1000; \
-               (time)->tv_usec = ((val) - ((time)->tv_sec * 1000)) * 10; \
+               (time)->tv_usec = ((val) - ((time)->tv_sec * 1000)) * 1000; \
       } \
       if ((val) == SM_TIME_FOREVER) \
       { \
@@ -276,7 +276,7 @@ extern const char SmFileMagic[];
       else \
       { \
               sm_io_to.tv_sec = (to) / 1000; \
-               sm_io_to.tv_usec = ((to) - (sm_io_to.tv_sec * 1000)) * 10; \
+               sm_io_to.tv_usec = ((to) - (sm_io_to.tv_sec * 1000)) * 1000; \
       } \
       if (FD_SETSIZE > 0 && (fd) >= FD_SETSIZE) \
       { \
@@ -289,8 +289,11 @@ extern const char SmFileMagic[];
       FD_SET((fd), &sm_io_x_mask); \
       if (gettimeofday(&sm_io_to_before, NULL) < 0) \
               return SM_IO_EOF; \
-       sm_io_to_sel = select((fd) + 1, NULL, &sm_io_to_mask, &sm_io_x_mask, \
-                             &sm_io_to); \
+       do \
+       {       \
+               sm_io_to_sel = select((fd) + 1, NULL, &sm_io_to_mask, \
+                                       &sm_io_x_mask, &sm_io_to); \
+       } while (sm_io_to_sel < 0 && errno == EINTR); \
       if (sm_io_to_sel < 0) \
       { \
               /* something went wrong, errno set */ \
@@ -305,10 +308,9 @@ extern const char SmFileMagic[];
       /* else loop again */ \
       if (gettimeofday(&sm_io_to_after, NULL) < 0) \
               return SM_IO_EOF; \
-       timersub(&sm_io_to_before, &sm_io_to_after, &sm_io_to_diff); \
-       timersub(&sm_io_to, &sm_io_to_diff, &sm_io_to); \
-       (to) -= (sm_io_to.tv_sec * 1000); \
-       (to) -= (sm_io_to.tv_usec / 10); \
+       timersub(&sm_io_to_after, &sm_io_to_before, &sm_io_to_diff); \
+       (to) -= (sm_io_to_diff.tv_sec * 1000); \
+       (to) -= (sm_io_to_diff.tv_usec / 1000); \
       if ((to) < 0) \
               (to) = 0; \
}
Index: gnu/usr.sbin/sendmail/libsm/refill.c
===================================================================
RCS file: /cvs/src/gnu/usr.sbin/sendmail/libsm/refill.c,v
retrieving revision 1.4
diff -u -p -r1.4 refill.c
--- gnu/usr.sbin/sendmail/libsm/refill.c        24 Jun 2004 03:59:26 -0000      1.4
+++ gnu/usr.sbin/sendmail/libsm/refill.c        24 Mar 2006 00:50:46 -0000
@@ -76,8 +76,11 @@ static int sm_lflush __P((SM_FILE_T *, i
       FD_SET((fd), &sm_io_x_mask);                                    \
       if (gettimeofday(&sm_io_to_before, NULL) < 0)                   \
               return SM_IO_EOF;                                       \
-       (sel_ret) = select((fd) + 1, &sm_io_to_mask, NULL,              \
-                          &sm_io_x_mask, (to));                        \
+       do                                                              \
+       {                                                               \
+               (sel_ret) = select((fd) + 1, &sm_io_to_mask, NULL,      \
+                               &sm_io_x_mask, (to));                   \
+       } while ((sel_ret) < 0 && errno == EINTR);                      \
       if ((sel_ret) < 0)                                              \
       {                                                               \
               /* something went wrong, errno set */                   \
@@ -94,7 +97,7 @@ static int sm_lflush __P((SM_FILE_T *, i
       /* calulate wall-clock time used */                             \
       if (gettimeofday(&sm_io_to_after, NULL) < 0)                    \
               return SM_IO_EOF;                                       \
-       timersub(&sm_io_to_before, &sm_io_to_after, &sm_io_to_diff);    \
+       timersub(&sm_io_to_after, &sm_io_to_before, &sm_io_to_diff);    \
       timersub((to), &sm_io_to_diff, (to));                           \
}

Index: gnu/usr.sbin/sendmail/sendmail/collect.c
===================================================================
RCS file: /cvs/src/gnu/usr.sbin/sendmail/sendmail/collect.c,v
retrieving revision 1.18
diff -u -p -r1.18 collect.c
--- gnu/usr.sbin/sendmail/sendmail/collect.c    16 Dec 2004 00:21:30 -0000      1.18
+++ gnu/usr.sbin/sendmail/sendmail/collect.c    24 Mar 2006 00:50:47 -0000
@@ -15,7 +15,6 @@

SM_RCSID("@(#)$Sendmail: collect.c,v 8.260 2004/11/30 23:29:15 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.
@@ -341,32 +339,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 +362,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)
@@ -538,6 +527,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 +582,7 @@ bufferchar:
                                       usrerrenh(e->e_status,
                                                 "552 Headers too large (%d max)",
                                                 MaxHeadersLength);
+  discard:
                                       mstate = MS_DISCARD;
                               }
                       }
@@ -620,6 +622,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 +649,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 +720,6 @@ readerr:
               inputerr = true;
       }

-       /* reset global timer */
-       if (CollectTimeout != NULL)
-               sm_clrevent(CollectTimeout);
-
       if (headeronly)
               return;

@@ -785,6 +805,7 @@ readerr:
       }

       /* An EOF when running SMTP is an error */
+  readabort:
       if (inputerr && (OpMode == MD_SMTP || OpMode == MD_DAEMON))
       {
               char *host;
@@ -807,13 +828,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;
@@ -906,39 +928,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.
**
Index: gnu/usr.sbin/sendmail/sendmail/conf.c
===================================================================
RCS file: /cvs/src/gnu/usr.sbin/sendmail/sendmail/conf.c,v
retrieving revision 1.25
diff -u -p -r1.25 conf.c
--- gnu/usr.sbin/sendmail/sendmail/conf.c       12 Jan 2005 18:15:46 -0000      1.25
+++ gnu/usr.sbin/sendmail/sendmail/conf.c       24 Mar 2006 00:50:49 -0000
@@ -5300,8 +5300,8 @@ sm_syslog(level, id, fmt, va_alist)
       va_dcl
#endif /* __STDC__ */
{
-       static char *buf = NULL;
-       static size_t bufsize;
+       char *buf;
+       size_t bufsize;
       char *begin, *end;
       int save_errno;
       int seq = 1;
@@ -5325,11 +5325,8 @@ sm_syslog(level, id, fmt, va_alist)
       else
               idlen = strlen(id) + SyslogPrefixLen;

-       if (buf == NULL)
-       {
-               buf = buf0;
-               bufsize = sizeof buf0;
-       }
+       buf = buf0;
+       bufsize = sizeof buf0;

       for (;;)
       {
@@ -5371,8 +5368,8 @@ sm_syslog(level, id, fmt, va_alist)
                       (void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT,
                                            "%s: %s\n", id, newstring);
#endif /* LOG */
-               if (buf == buf0)
-                       buf = NULL;
+               if (buf != buf0)
+                       sm_free(buf);
               errno = save_errno;
               return;
       }
@@ -5436,8 +5433,8 @@ sm_syslog(level, id, fmt, va_alist)
               (void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT,
                                    "%s[%d]: %s\n", id, seq, begin);
#endif /* LOG */
-       if (buf == buf0)
-               buf = NULL;
+       if (buf != buf0)
+               sm_free(buf);
       errno = save_errno;
}
/*
Index: gnu/usr.sbin/sendmail/sendmail/deliver.c
===================================================================
RCS file: /cvs/src/gnu/usr.sbin/sendmail/sendmail/deliver.c,v
retrieving revision 1.25
diff -u -p -r1.25 deliver.c
--- gnu/usr.sbin/sendmail/sendmail/deliver.c    12 Jan 2005 18:15:46 -0000      1.25
+++ gnu/usr.sbin/sendmail/sendmail/deliver.c    24 Mar 2006 00:50:51 -0000
@@ -3257,16 +3257,33 @@ do_transfer:
       }
       else if (!clever)
       {
+               bool ok;
+
               /*
               **  Format and send message.
               */

-               putfromline(mci, e);
-               (*e->e_puthdr)(mci, e->e_header, e, M87F_OUTER);
-               (*e->e_putbody)(mci, e, NULL);
+               rcode = EX_OK;
+               errno = 0;
+               ok = putfromline(mci, e);
+               if (ok)
+                       ok = (*e->e_puthdr)(mci, e->e_header, e, M87F_OUTER);
+               if (ok)
+                       ok = (*e->e_putbody)(mci, e, NULL);
+
+               /*
+               **  Ignore an I/O error that was caused by EPIPE.
+               **  Some broken mailers don't read the entire body
+               **  but just exit() thus causing an I/O error.
+               */
+
+               if (!ok && (sm_io_error(mci->mci_out) && errno == EPIPE))
+                       ok = true;

-               /* get the exit status */
+               /* (always) get the exit status */
               rcode = endmailer(mci, e, pv);
+               if (!ok)
+                       rcode = EX_TEMPFAIL;
               if (rcode == EX_TEMPFAIL && SmtpError[0] == '\0')
               {
                       /*
@@ -4420,13 +4437,13 @@ logdelivery(m, mci, dsn, status, ctladdr
**             e -- the envelope.
**
**     Returns:
-**             none
+**             true iff line was written successfully
**
**     Side Effects:
**             outputs some text to fp.
*/

-void
+bool
putfromline(mci, e)
       register MCI *mci;
       ENVELOPE *e;
@@ -4436,7 +4453,7 @@ putfromline(mci, e)
       char xbuf[MAXLINE];

       if (bitnset(M_NHDR, mci->mci_mailer->m_flags))
-               return;
+               return true;

       mci->mci_flags |= MCIF_INHEADER;

@@ -4477,8 +4494,9 @@ putfromline(mci, e)
               }
       }
       expand(template, buf, sizeof buf, e);
-       putxline(buf, strlen(buf), mci, PXLF_HEADER);
+       return putxline(buf, strlen(buf), mci, PXLF_HEADER);
}
+
/*
**  PUTBODY -- put the body of a message.
**
@@ -4489,7 +4507,7 @@ putfromline(mci, e)
**                     not be permitted in the resulting message.
**
**     Returns:
-**             none.
+**             true iff message was written successfully
**
**     Side Effects:
**             The message is written onto fp.
@@ -4500,13 +4518,15 @@ putfromline(mci, e)
#define OS_CR          1       /* read a carriage return */
#define OS_INLINE      2       /* putting rest of line */

-void
+bool
putbody(mci, e, separator)
       register MCI *mci;
       register ENVELOPE *e;
       char *separator;
{
       bool dead = false;
+       bool ioerr = false;
+       int save_errno;
       char buf[MAXLINE];
#if MIME8TO7
       char *boundaries[MAXMIMENESTING + 1];
@@ -4536,10 +4556,12 @@ putbody(mci, e, separator)
       {
               if (bitset(MCIF_INHEADER, mci->mci_flags))
               {
-                       putline("", mci);
+                       if (!putline("", mci))
+                               goto writeerr;
                       mci->mci_flags &= ~MCIF_INHEADER;
               }
-               putline("<<< No Message Collected >>>", mci);
+               if (!putline("<<< No Message Collected >>>", mci))
+                       goto writeerr;
               goto endofmessage;
       }

@@ -4568,26 +4590,31 @@ putbody(mci, e, separator)
               */

               /* make sure it looks like a MIME message */
-               if (hvalue("MIME-Version", e->e_header) == NULL)
-                       putline("MIME-Version: 1.0", mci);
+               if (hvalue("MIME-Version", e->e_header) == NULL &&
+                   !putline("MIME-Version: 1.0", mci))
+                       goto writeerr;

               if (hvalue("Content-Type", e->e_header) == NULL)
               {
                       (void) sm_snprintf(buf, sizeof buf,
                                          "Content-Type: text/plain; charset=%s",
                                          defcharset(e));
-                       putline(buf, mci);
+                       if (!putline(buf, mci))
+                               goto writeerr;
               }

               /* now do the hard work */
               boundaries[0] = NULL;
               mci->mci_flags |= MCIF_INHEADER;
-               (void) mime8to7(mci, e->e_header, e, boundaries, M87F_OUTER);
+               if (mime8to7(mci, e->e_header, e, boundaries, M87F_OUTER) ==
+                                                               SM_IO_EOF)
+                       goto writeerr;
       }
# if MIME7TO8
       else if (bitset(MCIF_CVT7TO8, mci->mci_flags))
       {
-               (void) mime7to8(mci, e->e_header, e);
+               if (!mime7to8(mci, e->e_header, e))
+                       goto writeerr;
       }
# endif /* MIME7TO8 */
       else if (MaxMimeHeaderLength > 0 || MaxMimeFieldLength > 0)
@@ -4609,8 +4636,9 @@ putbody(mci, e, separator)
               if (bitset(EF_DONT_MIME, e->e_flags))
                       SuprErrs = true;

-               (void) mime8to7(mci, e->e_header, e, boundaries,
-                               M87F_OUTER|M87F_NO8TO7);
+               if (mime8to7(mci, e->e_header, e, boundaries,
+                               M87F_OUTER|M87F_NO8TO7) == SM_IO_EOF)
+                       goto writeerr;

               /* restore SuprErrs */
               SuprErrs = oldsuprerrs;
@@ -4630,7 +4658,8 @@ putbody(mci, e, separator)

               if (bitset(MCIF_INHEADER, mci->mci_flags))
               {
-                       putline("", mci);
+                       if (!putline("", mci))
+                               goto writeerr;
                       mci->mci_flags &= ~MCIF_INHEADER;
               }

@@ -4721,11 +4750,6 @@ putbody(mci, e, separator)
                                               dead = true;
                                               continue;
                                       }
-                                       else
-                                       {
-                                               /* record progress for DATA timeout */
-                                               DataProgress = true;
-                                       }
                                       pos++;
                               }
                               for (xp = buf; xp < bp; xp++)
@@ -4738,11 +4762,6 @@ putbody(mci, e, separator)
                                               dead = true;
                                               break;
                                       }
-                                       else
-                                       {
-                                               /* record progress for DATA timeout */
-                                               DataProgress = true;
-                                       }
                               }
                               if (dead)
                                       continue;
@@ -4753,11 +4772,6 @@ putbody(mci, e, separator)
                                                       mci->mci_mailer->m_eol)
                                                       == SM_IO_EOF)
                                               break;
-                                       else
-                                       {
-                                               /* record progress for DATA timeout */
-                                               DataProgress = true;
-                                       }
                                       pos = 0;
                               }
                               else
@@ -4791,11 +4805,6 @@ putbody(mci, e, separator)
                                                       mci->mci_mailer->m_eol)
                                                       == SM_IO_EOF)
                                               continue;
-                                       else
-                                       {
-                                               /* record progress for DATA timeout */
-                                               DataProgress = true;
-                                       }

                                       if (TrafficLogFile != NULL)
                                       {
@@ -4857,11 +4866,6 @@ putch:
                                                       dead = true;
                                                       continue;
                                               }
-                                               else
-                                               {
-                                                       /* record progress for DATA timeout */
-                                                       DataProgress = true;
-                                               }
                                               pos++;
                                               continue;
                                       }
@@ -4877,11 +4881,6 @@ putch:
                                               dead = true;
                                               continue;
                                       }
-                                       else
-                                       {
-                                               /* record progress for DATA timeout */
-                                               DataProgress = true;
-                                       }

                                       if (TrafficLogFile != NULL)
                                       {
@@ -4907,11 +4906,6 @@ putch:
                                                       mci->mci_mailer->m_eol)
                                                       == SM_IO_EOF)
                                               continue;
-                                       else
-                                       {
-                                               /* record progress for DATA timeout */
-                                               DataProgress = true;
-                                       }
                                       pos = 0;
                                       ostate = OS_HEAD;
                               }
@@ -4929,11 +4923,6 @@ putch:
                                               dead = true;
                                               continue;
                                       }
-                                       else
-                                       {
-                                               /* record progress for DATA timeout */
-                                               DataProgress = true;
-                                       }
                                       pos++;
                                       ostate = OS_INLINE;
                               }
@@ -4960,11 +4949,6 @@ putch:
                                       dead = true;
                                       break;
                               }
-                               else
-                               {
-                                       /* record progress for DATA timeout */
-                                       DataProgress = true;
-                               }
                       }
                       pos += bp - buf;
               }
@@ -4974,11 +4958,9 @@ putch:
                               (void) sm_io_fputs(TrafficLogFile,
                                                  SM_TIME_DEFAULT,
                                                  mci->mci_mailer->m_eol);
-                       (void) sm_io_fputs(mci->mci_out, SM_TIME_DEFAULT,
-                                          mci->mci_mailer->m_eol);
-
-                       /* record progress for DATA timeout */
-                       DataProgress = true;
+                       if (sm_io_fputs(mci->mci_out, SM_TIME_DEFAULT,
+                                          mci->mci_mailer->m_eol) == SM_IO_EOF)
+                               goto writeerr;
               }
       }

@@ -4988,6 +4970,7 @@ putch:
                      qid_printqueue(e->e_dfqgrp, e->e_dfqdir),
                      DATAFL_LETTER, e->e_id);
               ExitStat = EX_IOERR;
+               ioerr = true;
       }

endofmessage:
@@ -5002,23 +4985,35 @@ endofmessage:
       **  offset to match.
       */

+       save_errno = errno;
       if (e->e_dfp != NULL)
               (void) bfrewind(e->e_dfp);

       /* some mailers want extra blank line at end of message */
       if (!dead && bitnset(M_BLANKEND, mci->mci_mailer->m_flags) &&
           buf[0] != '\0' && buf[0] != '\n')
-               putline("", mci);
+       {
+               if (!putline("", mci))
+                       goto writeerr;
+       }

-       (void) sm_io_flush(mci->mci_out, SM_TIME_DEFAULT);
-       if (sm_io_error(mci->mci_out) && errno != EPIPE)
+       if (!dead &&
+           (sm_io_flush(mci->mci_out, SM_TIME_DEFAULT) == SM_IO_EOF ||
+            (sm_io_error(mci->mci_out) && errno != EPIPE)))
       {
+               save_errno = errno;
               syserr("putbody: write error");
               ExitStat = EX_IOERR;
+               ioerr = true;
       }

-       errno = 0;
+       errno = save_errno;
+       return !dead && !ioerr;
+
+  writeerr:
+       return false;
}
+
/*
**  MAILFILE -- Send a message to a file.
**
@@ -5549,14 +5544,14 @@ mailfile(filename, mailer, ctladdr, sffl
               }
#endif /* MIME7TO8 */

-               putfromline(&mcibuf, e);
-               (*e->e_puthdr)(&mcibuf, e->e_header, e, M87F_OUTER);
-               (*e->e_putbody)(&mcibuf, e, NULL);
-               putline("\n", &mcibuf);
-               if (sm_io_flush(f, SM_TIME_DEFAULT) != 0 ||
+               if (!putfromline(&mcibuf, e) ||
+                   !(*e->e_puthdr)(&mcibuf, e->e_header, e, M87F_OUTER) ||
+                   !(*e->e_putbody)(&mcibuf, e, NULL) ||
+                   !putline("\n", &mcibuf) ||
+                   (sm_io_flush(f, SM_TIME_DEFAULT) != 0 ||
                   (SuperSafe != SAFE_NO &&
                    fsync(sm_io_getinfo(f, SM_IO_WHAT_FD, NULL)) < 0) ||
-                   sm_io_error(f))
+                   sm_io_error(f)))
               {
                       setstat(EX_IOERR);
#if !NOFTRUNCATE
@@ -6114,86 +6109,23 @@ starttls(m, mci, e)
ssl_retry:
       if ((result = SSL_connect(clt_ssl)) <= 0)
       {
-               int i;
-               bool timedout;
-               time_t left;
-               time_t now = curtime();
-               struct timeval tv;
+               int i, ssl_err;

-               /* what to do in this case? */
-               i = SSL_get_error(clt_ssl, result);
+               ssl_err = SSL_get_error(clt_ssl, result);
+               i = tls_retry(clt_ssl, rfd, wfd, tlsstart,
+                       TimeOuts.to_starttls, ssl_err, "client");
+               if (i > 0)
+                       goto ssl_retry;

-               /*
-               **  For SSL_ERROR_WANT_{READ,WRITE}:
-               **  There is not a complete SSL record available yet
-               **  or there is only a partial SSL record removed from
-               **  the network (socket) buffer into the SSL buffer.
-               **  The SSL_connect will only succeed when a full
-               **  SSL record is available (assuming a "real" error
-               **  doesn't happen). To handle when a "real" error
-               **  does happen the select is set for exceptions too.
-               **  The connection may be re-negotiated during this time
-               **  so both read and write "want errors" need to be handled.
-               **  A select() exception loops back so that a proper SSL
-               **  error message can be gotten.
-               */
-
-               left = TimeOuts.to_starttls - (now - tlsstart);
-               timedout = left <= 0;
-               if (!timedout)
-               {
-                       tv.tv_sec = left;
-                       tv.tv_usec = 0;
-               }
-
-               if (!timedout && FD_SETSIZE > 0 &&
-                   (rfd >= FD_SETSIZE ||
-                    (i == SSL_ERROR_WANT_WRITE && wfd >= FD_SETSIZE)))
-               {
-                       if (LogLevel > 5)
-                       {
-                               sm_syslog(LOG_ERR, e->e_id,
-                                         "STARTTLS=client, error: fd %d/%d too large",
-                                         rfd, wfd);
-                       if (LogLevel > 8)
-                               tlslogerr("client");
-                       }
-                       errno = EINVAL;
-                       goto tlsfail;
-               }
-               if (!timedout && i == SSL_ERROR_WANT_READ)
-               {
-                       fd_set ssl_maskr, ssl_maskx;
-
-                       FD_ZERO(&ssl_maskr);
-                       FD_SET(rfd, &ssl_maskr);
-                       FD_ZERO(&ssl_maskx);
-                       FD_SET(rfd, &ssl_maskx);
-                       if (select(rfd + 1, &ssl_maskr, NULL, &ssl_maskx, &tv)
-                           > 0)
-                               goto ssl_retry;
-               }
-               if (!timedout && i == SSL_ERROR_WANT_WRITE)
-               {
-                       fd_set ssl_maskw, ssl_maskx;
-
-                       FD_ZERO(&ssl_maskw);
-                       FD_SET(wfd, &ssl_maskw);
-                       FD_ZERO(&ssl_maskx);
-                       FD_SET(rfd, &ssl_maskx);
-                       if (select(wfd + 1, NULL, &ssl_maskw, &ssl_maskx, &tv)
-                           > 0)
-                               goto ssl_retry;
-               }
               if (LogLevel > 5)
               {
-                       sm_syslog(LOG_ERR, e->e_id,
-                                 "STARTTLS=client, error: connect failed=%d, SSL_error=%d, timedout=%d, errno=%d",
-                                 result, i, (int) timedout, errno);
+                       sm_syslog(LOG_WARNING, NOQID,
+                                 "STARTTLS=client, error: connect failed=%d, SSL_error=%d, errno=%d, retry=%d",
+                                 result, ssl_err, errno, i);
                       if (LogLevel > 8)
                               tlslogerr("client");
               }
-tlsfail:
+
               SSL_free(clt_ssl);
               clt_ssl = NULL;
               return EX_SOFTWARE;
Index: gnu/usr.sbin/sendmail/sendmail/headers.c
===================================================================
RCS file: /cvs/src/gnu/usr.sbin/sendmail/sendmail/headers.c,v
retrieving revision 1.17
diff -u -p -r1.17 headers.c
--- gnu/usr.sbin/sendmail/sendmail/headers.c    16 Dec 2004 00:21:30 -0000      1.17
+++ gnu/usr.sbin/sendmail/sendmail/headers.c    24 Mar 2006 00:50:51 -0000
@@ -18,7 +18,7 @@ SM_RCSID("@(#)$Sendmail: headers.c,v 8.2
static HDR     *allocheader __P((char *, char *, int, SM_RPOOL_T *));
static size_t  fix_mime_header __P((HDR *, ENVELOPE *));
static int     priencode __P((char *));
-static void    put_vanilla_header __P((HDR *, char *, MCI *));
+static bool    put_vanilla_header __P((HDR *, char *, MCI *));

/*
**  SETUPHEADERS -- initialize headers in symbol table
@@ -993,7 +993,6 @@ logsender(e, msgid)
       char *name;
       register char *sbp;
       register char *p;
-       int l;
       char hbuf[MAXNAME + 1];
       char sbuf[MAXLINE + 1];
       char mbuf[MAXNAME + 1];
@@ -1002,6 +1001,8 @@ logsender(e, msgid)
       /* XXX do we still need this? sm_syslog() replaces control chars */
       if (msgid != NULL)
       {
+               size_t l;
+
               l = strlen(msgid);
               if (l > sizeof mbuf - 1)
                       l = sizeof mbuf - 1;
@@ -1541,13 +1542,13 @@ crackaddr(addr, e)
**             flags -- MIME conversion flags.
**
**     Returns:
-**             none.
+**             success
**
**     Side Effects:
**             none.
*/

-void
+bool
putheader(mci, hdr, e, flags)
       register MCI *mci;
       HDR *hdr;
@@ -1682,7 +1683,8 @@ putheader(mci, hdr, e, flags)
               {
                       if (tTd(34, 11))
                               sm_dprintf("\n");
-                       put_vanilla_header(h, p, mci);
+                       if (!put_vanilla_header(h, p, mci))
+                               goto writeerr;
                       continue;
               }

@@ -1741,7 +1743,8 @@ putheader(mci, hdr, e, flags)
                               /* no other recipient headers: truncate value */
                               (void) sm_strlcpyn(obuf, sizeof obuf, 2,
                                                  h->h_field, ":");
-                               putline(obuf, mci);
+                               if (!putline(obuf, mci))
+                                       goto writeerr;
                       }
                       continue;
               }
@@ -1760,7 +1763,8 @@ putheader(mci, hdr, e, flags)
               }
               else
               {
-                       put_vanilla_header(h, p, mci);
+                       if (!put_vanilla_header(h, p, mci))
+                               goto writeerr;
               }
       }

@@ -1777,18 +1781,25 @@ putheader(mci, hdr, e, flags)
           !bitset(MCIF_CVT8TO7|MCIF_CVT7TO8|MCIF_INMIME, mci->mci_flags) &&
           hvalue("MIME-Version", e->e_header) == NULL)
       {
-               putline("MIME-Version: 1.0", mci);
+               if (!putline("MIME-Version: 1.0", mci))
+                       goto writeerr;
               if (hvalue("Content-Type", e->e_header) == NULL)
               {
                       (void) sm_snprintf(obuf, sizeof obuf,
                                       "Content-Type: text/plain; charset=%s",
                                       defcharset(e));
-                       putline(obuf, mci);
+                       if (!putline(obuf, mci))
+                               goto writeerr;
               }
-               if (hvalue("Content-Transfer-Encoding", e->e_header) == NULL)
-                       putline("Content-Transfer-Encoding: 8bit", mci);
+               if (hvalue("Content-Transfer-Encoding", e->e_header) == NULL
+                   && !putline("Content-Transfer-Encoding: 8bit", mci))
+                       goto writeerr;
       }
#endif /* MIME8TO7 */
+       return true;
+
+  writeerr:
+       return false;
}
/*
**  PUT_VANILLA_HEADER -- output a fairly ordinary header
@@ -1799,10 +1810,10 @@ putheader(mci, hdr, e, flags)
**             mci -- the connection info for output
**
**     Returns:
-**             none.
+**             success
*/

-static void
+static bool
put_vanilla_header(h, v, mci)
       HDR *h;
       char *v;
@@ -1833,7 +1844,8 @@ put_vanilla_header(h, v, mci)
                       l = SPACELEFT(obuf, obp) - 1;

               (void) sm_snprintf(obp, SPACELEFT(obuf, obp), "%.*s", l, v);
-               putxline(obuf, strlen(obuf), mci, putflags);
+               if (!putxline(obuf, strlen(obuf), mci, putflags))
+                       goto writeerr;
               v += l + 1;
               obp = obuf;
               if (*v != ' ' && *v != '\t')
@@ -1843,7 +1855,10 @@ put_vanilla_header(h, v, mci)
       /* XXX This is broken for SPACELEFT()==0 */
       (void) sm_snprintf(obp, SPACELEFT(obuf, obp), "%.*s",
                          (int) (SPACELEFT(obuf, obp) - 1), v);
-       putxline(obuf, strlen(obuf), mci, putflags);
+       return putxline(obuf, strlen(obuf), mci, putflags);
+
+  writeerr:
+       return false;
}
/*
**  COMMAIZE -- output a header field, making a comma-translated list.
@@ -1856,13 +1871,13 @@ put_vanilla_header(h, v, mci)
**             e -- the envelope containing the message.
**
**     Returns:
-**             none.
+**             success
**
**     Side Effects:
**             outputs "p" to file "fp".
*/

-void
+bool
commaize(h, p, oldstyle, mci, e)
       register HDR *h;
       register char *p;
@@ -2001,13 +2016,6 @@ commaize(h, p, oldstyle, mci, e)
               }
               name = denlstring(name, false, true);

-               /*
-               **  record data progress so DNS timeouts
-               **  don't cause DATA timeouts
-               */
-
-               DataProgress = true;
-
               /* output the name with nice formatting */
               opos += strlen(name);
               if (!firstone)
@@ -2015,7 +2023,8 @@ commaize(h, p, oldstyle, mci, e)
               if (opos > omax && !firstone)
               {
                       (void) sm_strlcpy(obp, ",\n", SPACELEFT(obuf, obp));
-                       putxline(obuf, strlen(obuf), mci, putflags);
+                       if (!putxline(obuf, strlen(obuf), mci, putflags))
+                               goto writeerr;
                       obp = obuf;
                       (void) sm_strlcpy(obp, "        ", sizeof obuf);
                       opos = strlen(obp);
@@ -2037,8 +2046,12 @@ commaize(h, p, oldstyle, mci, e)
               *obp = '\0';
       else
               obuf[sizeof obuf - 1] = '\0';
-       putxline(obuf, strlen(obuf), mci, putflags);
+       return putxline(obuf, strlen(obuf), mci, putflags);
+
+  writeerr:
+       return false;
}
+
/*
**  COPYHEADER -- copy header list
**
Index: gnu/usr.sbin/sendmail/sendmail/mime.c
===================================================================
RCS file: /cvs/src/gnu/usr.sbin/sendmail/sendmail/mime.c,v
retrieving revision 1.10
diff -u -p -r1.10 mime.c
--- gnu/usr.sbin/sendmail/sendmail/mime.c       16 Dec 2004 00:21:31 -0000      1.10
+++ gnu/usr.sbin/sendmail/sendmail/mime.c       24 Mar 2006 00:50:52 -0000
@@ -86,6 +86,7 @@ static bool   MapNLtoCRLF;
**               MBT_FINAL -- the final boundary
**               MBT_INTERMED -- an intermediate boundary
**               MBT_NOTSEP -- an end of file
+**               SM_IO_EOF -- I/O error occurred
*/

struct args
@@ -298,7 +299,8 @@ mime8to7(mci, header, e, boundaries, fla
               mci->mci_flags |= MCIF_INMIME;

               /* skip the early "comment" prologue */
-               putline("", mci);
+               if (!putline("", mci))
+                       goto writeerr;
               mci->mci_flags &= ~MCIF_INHEADER;
               bt = MBT_FINAL;
               while (sm_io_fgets(e->e_dfp, SM_TIME_DEFAULT, buf, sizeof buf)
@@ -307,8 +309,9 @@ mime8to7(mci, header, e, boundaries, fla
                       bt = mimeboundary(buf, boundaries);
                       if (bt != MBT_NOTSEP)
                               break;
-                       putxline(buf, strlen(buf), mci,
-                                PXLF_MAPFROM|PXLF_STRIP8BIT);
+                       if (!putxline(buf, strlen(buf), mci,
+                                       PXLF_MAPFROM|PXLF_STRIP8BIT))
+                               goto writeerr;
                       if (tTd(43, 99))
                               sm_dprintf("  ...%s", buf);
               }
@@ -319,19 +322,24 @@ mime8to7(mci, header, e, boundaries, fla
                       auto HDR *hdr = NULL;

                       (void) sm_strlcpyn(buf, sizeof buf, 2, "--", bbuf);
-                       putline(buf, mci);
+                       if (!putline(buf, mci))
+                               goto writeerr;
                       if (tTd(43, 35))
                               sm_dprintf("  ...%s\n", buf);
                       collect(e->e_dfp, false, &hdr, e, false);
                       if (tTd(43, 101))
                               putline("+++after collect", mci);
-                       putheader(mci, hdr, e, flags);
+                       if (!putheader(mci, hdr, e, flags))
+                               goto writeerr;
                       if (tTd(43, 101))
                               putline("+++after putheader", mci);
                       bt = mime8to7(mci, hdr, e, boundaries, flags);
+                       if (bt == SM_IO_EOF)
+                               goto writeerr;
               }
               (void) sm_strlcpyn(buf, sizeof buf, 3, "--", bbuf, "--");
-               putline(buf, mci);
+               if (!putline(buf, mci))
+                       goto writeerr;
               if (tTd(43, 35))
                       sm_dprintf("  ...%s\n", buf);
               boundaries[i] = NULL;
@@ -344,8 +352,9 @@ mime8to7(mci, header, e, boundaries, fla
                       bt = mimeboundary(buf, boundaries);
                       if (bt != MBT_NOTSEP)
                               break;
-                       putxline(buf, strlen(buf), mci,
-                                PXLF_MAPFROM|PXLF_STRIP8BIT);
+                       if (!putxline(buf, strlen(buf), mci,
+                                       PXLF_MAPFROM|PXLF_STRIP8BIT))
+                               goto writeerr;
                       if (tTd(43, 99))
                               sm_dprintf("  ...%s", buf);
               }
@@ -373,18 +382,21 @@ mime8to7(mci, header, e, boundaries, fla
               {
                       auto HDR *hdr = NULL;

-                       putline("", mci);
+                       if (!putline("", mci))
+                               goto writeerr;

                       mci->mci_flags |= MCIF_INMIME;
                       collect(e->e_dfp, false, &hdr, e, false);
                       if (tTd(43, 101))
                               putline("+++after collect", mci);
-                       putheader(mci, hdr, e, flags);
+                       if (!putheader(mci, hdr, e, flags))
+                               goto writeerr;
                       if (tTd(43, 101))
                               putline("+++after putheader", mci);
                       if (hvalue("MIME-Version", hdr) == NULL &&
-                           !bitset(M87F_NO8TO7, flags))
-                               putline("MIME-Version: 1.0", mci);
+                           !bitset(M87F_NO8TO7, flags) &&
+                           !putline("MIME-Version: 1.0", mci))
+                               goto writeerr;
                       bt = mime8to7(mci, hdr, e, boundaries, flags);
                       mci->mci_flags &= ~MCIF_INMIME;
                       return bt;
@@ -480,11 +492,13 @@ mime8to7(mci, header, e, boundaries, fla

                       (void) sm_snprintf(buf, sizeof buf,
                               "Content-Transfer-Encoding: %.200s", cte);
-                       putline(buf, mci);
+                       if (!putline(buf, mci))
+                               goto writeerr;
                       if (tTd(43, 36))
                               sm_dprintf("  ...%s\n", buf);
               }
-               putline("", mci);
+               if (!putline("", mci))
+                       goto writeerr;
               mci->mci_flags &= ~MCIF_INHEADER;
               while (sm_io_fgets(e->e_dfp, SM_TIME_DEFAULT, buf, sizeof buf)
                       != NULL)
@@ -492,7 +506,8 @@ mime8to7(mci, header, e, boundaries, fla
                       bt = mimeboundary(buf, boundaries);
                       if (bt != MBT_NOTSEP)
                               break;
-                       putline(buf, mci);
+                       if (!putline(buf, mci))
+                               goto writeerr;
               }
               if (sm_io_eof(e->e_dfp))
                       bt = MBT_FINAL;
@@ -505,12 +520,13 @@ mime8to7(mci, header, e, boundaries, fla

               if (tTd(43, 36))
                       sm_dprintf("  ...Content-Transfer-Encoding: base64\n");
-               putline("Content-Transfer-Encoding: base64", mci);
+               if (!putline("Content-Transfer-Encoding: base64", mci))
+                       goto writeerr;
               (void) sm_snprintf(buf, sizeof buf,
                       "X-MIME-Autoconverted: from 8bit to base64 by %s id %s",
                       MyHostName, e->e_id);
-               putline(buf, mci);
-               putline("", mci);
+               if (!putline(buf, mci) || !putline("", mci))
+                       goto writeerr;
               mci->mci_flags &= ~MCIF_INHEADER;
               while ((c1 = mime_getchar_crlf(e->e_dfp, boundaries, &bt)) !=
                       SM_IO_EOF)
@@ -518,7 +534,8 @@ mime8to7(mci, header, e, boundaries, fla
                       if (linelen > 71)
                       {
                               *bp = '\0';
-                               putline(buf, mci);
+                               if (!putline(buf, mci))
+                                       goto writeerr;
                               linelen = 0;
                               bp = buf;
                       }
@@ -548,7 +565,8 @@ mime8to7(mci, header, e, boundaries, fla
                       *bp++ = Base64Code[c2 & 0x3f];
               }
               *bp = '\0';
-               putline(buf, mci);
+               if (!putline(buf, mci))
+                       goto writeerr;
       }
       else
       {
@@ -571,12 +589,14 @@ mime8to7(mci, header, e, boundaries, fla

               if (tTd(43, 36))
                       sm_dprintf("  ...Content-Transfer-Encoding: quoted-printable\n");
-               putline("Content-Transfer-Encoding: quoted-printable", mci);
+               if (!putline("Content-Transfer-Encoding: quoted-printable",
+                               mci))
+                       goto writeerr;
               (void) sm_snprintf(buf, sizeof buf,
                       "X-MIME-Autoconverted: from 8bit to quoted-printable by %s id %s",
                       MyHostName, e->e_id);
-               putline(buf, mci);
-               putline("", mci);
+               if (!putline(buf, mci) || !putline("", mci))
+                       goto writeerr;
               mci->mci_flags &= ~MCIF_INHEADER;
               fromstate = 0;
               c2 = '\n';
@@ -598,7 +618,8 @@ mime8to7(mci, header, e, boundaries, fla
                                       *bp++ = Base16Code['.' & 0x0f];
                               }
                               *bp = '\0';
-                               putline(buf, mci);
+                               if (!putline(buf, mci))
+                                       goto writeerr;
                               linelen = fromstate = 0;
                               bp = buf;
                               c2 = c1;
@@ -627,7 +648,8 @@ mime8to7(mci, header, e, boundaries, fla
                                       c2 = '\n';
                               *bp++ = '=';
                               *bp = '\0';
-                               putline(buf, mci);
+                               if (!putline(buf, mci))
+                                       goto writeerr;
                               linelen = fromstate = 0;
                               bp = buf;
                               if (c2 == '.')
@@ -665,13 +687,17 @@ mime8to7(mci, header, e, boundaries, fla
               if (linelen > 0 || boundaries[0] != NULL)
               {
                       *bp = '\0';
-                       putline(buf, mci);
+                       if (!putline(buf, mci))
+                               goto writeerr;
               }

       }
       if (tTd(43, 3))
               sm_dprintf("\t\t\tmime8to7=>%s (basic)\n", MimeBoundaryNames[bt]);
       return bt;
+
+  writeerr:
+       return SM_IO_EOF;
}
/*
**  MIME_GETCHAR -- get a character for MIME processing
@@ -958,7 +984,7 @@ static int  mime_fromqp __P((unsigned cha
**             e -- envelope.
**
**     Returns:
-**             none.
+**             true iff body was written successfully
*/

static char index_64[128] =
@@ -975,7 +1001,7 @@ static char index_64[128] =

# define CHAR64(c)  (((c) < 0 || (c) > 127) ? -1 : index_64[(c)])

-void
+bool
mime7to8(mci, header, e)
       register MCI *mci;
       HDR *header;
@@ -1008,25 +1034,31 @@ mime7to8(mci, header, e)
               {
                       (void) sm_snprintf(buf, sizeof buf,
                               "Content-Transfer-Encoding: %s", p);
-                       putline(buf, mci);
+                       if (!putline(buf, mci))
+                               goto writeerr;
               }
-               putline("", mci);
+               if (!putline("", mci))
+                       goto writeerr;
               mci->mci_flags &= ~MCIF_INHEADER;
               while (sm_io_fgets(e->e_dfp, SM_TIME_DEFAULT, buf, sizeof buf)
                       != NULL)
-                       putline(buf, mci);
-               return;
+               {
+                       if (!putline(buf, mci))
+                               goto writeerr;
+               }
+               return true;
       }
       cataddr(pvp, NULL, buf, sizeof buf, '\0');
       cte = sm_rpool_strdup_x(e->e_rpool, buf);

       mci->mci_flags |= MCIF_INHEADER;
-       putline("Content-Transfer-Encoding: 8bit", mci);
+       if (!putline("Content-Transfer-Encoding: 8bit", mci))
+               goto writeerr;
       (void) sm_snprintf(buf, sizeof buf,
               "X-MIME-Autoconverted: from %.200s to 8bit by %s id %s",
               cte, MyHostName, e->e_id);
-       putline(buf, mci);
-       putline("", mci);
+       if (!putline(buf, mci) || !putline("", mci))
+               goto writeerr;
       mci->mci_flags &= ~MCIF_INHEADER;

       /*
@@ -1090,7 +1122,8 @@ mime7to8(mci, header, e)
               if (*fbufp++ == '\n' || fbufp >= &fbuf[MAXLINE])        \
               {                                                       \
                       CHK_EOL;                                        \
-                       putxline((char *) fbuf, fbufp - fbuf, mci, pxflags); \
+                       if (!putxline((char *) fbuf, fbufp - fbuf, mci, pxflags)) \
+                               goto writeerr;                          \
                       pxflags &= ~PXLF_NOADDEOL;                      \
                       fbufp = fbuf;                                   \
               }       \
@@ -1127,8 +1160,11 @@ again:
                               continue;

                       if (fbufp - fbuf > 0)
-                               putxline((char *) fbuf, fbufp - fbuf - 1, mci,
-                                        pxflags);
+                       {
+                               if (!putxline((char *) fbuf, fbufp - fbuf - 1,
+                                               mci, pxflags))
+                                       goto writeerr;
+                       }
                       fbufp = fbuf;
                       if (off >= 0 && buf[off] != '\0')
                       {
@@ -1144,7 +1180,8 @@ again:
       if (fbufp > fbuf)
       {
               *fbufp = '\0';
-               putxline((char *) fbuf, fbufp - fbuf, mci, pxflags);
+               if (!putxline((char *) fbuf, fbufp - fbuf, mci, pxflags))
+                       goto writeerr;
       }

       /*
@@ -1154,10 +1191,15 @@ again:
       **  but so is auto-converting MIME in the first place.
       */

-       putline("", mci);
+       if (!putline("", mci))
+               goto writeerr;

       if (tTd(43, 3))
               sm_dprintf("\t\t\tmime7to8 => %s to 8bit done\n", cte);
+       return true;
+
+  writeerr:
+       return false;
}
/*
**  The following is based on Borenstein's "codes.c" module, with simplifying
Index: gnu/usr.sbin/sendmail/sendmail/parseaddr.c
===================================================================
RCS file: /cvs/src/gnu/usr.sbin/sendmail/sendmail/parseaddr.c,v
retrieving revision 1.20
diff -u -p -r1.20 parseaddr.c
--- gnu/usr.sbin/sendmail/sendmail/parseaddr.c  16 Dec 2004 00:21:31 -0000      1.20
+++ gnu/usr.sbin/sendmail/sendmail/parseaddr.c  24 Mar 2006 00:50:53 -0000
@@ -1337,7 +1337,7 @@ rewrite(pvp, ruleset, reclevel, e, maxat
                                       /* $&{x} replacement */
                                       char *mval = macvalue(rp[1], e);
                                       char **xpvp;
-                                       int trsize = 0;
+                                       size_t trsize = 0;
                                       static size_t pvpb1_size = 0;
                                       static char **pvpb1 = NULL;
                                       char pvpbuf[PSBUFSIZE];
@@ -1352,7 +1352,7 @@ rewrite(pvp, ruleset, reclevel, e, maxat
                                       /* save the remainder of the input */
                                       for (xpvp = pvp; *xpvp != NULL; xpvp++)
                                               trsize += sizeof *xpvp;
-                                       if ((size_t) trsize > pvpb1_size)
+                                       if (trsize > pvpb1_size)
                                       {
                                               if (pvpb1 != NULL)
                                                       sm_free(pvpb1);
@@ -1407,7 +1407,7 @@ rewrite(pvp, ruleset, reclevel, e, maxat
               {
                       char **hbrvp;
                       char **xpvp;
-                       int trsize;
+                       size_t trsize;
                       char *replac;
                       int endtoken;
                       STAB *map;
@@ -1509,7 +1509,7 @@ rewrite(pvp, ruleset, reclevel, e, maxat
                               *++arg_rvp = NULL;

                       /* save the remainder of the input string */
-                       trsize = (int) (avp - rvp + 1) * sizeof *rvp;
+                       trsize = (avp - rvp + 1) * sizeof *rvp;
                       memmove((char *) pvpb1, (char *) rvp, trsize);

                       /* look it up */
@@ -2936,7 +2936,7 @@ rscheck(rwset, p1, p2, e, flags, logl, h
       char *logid;
{
       char *volatile buf;
-       int bufsize;
+       size_t bufsize;
       int saveexitstat;
       int volatile rstat = EX_OK;
       char **pvp;
@@ -3150,7 +3150,7 @@ rscap(rwset, p1, p2, e, pvp, pvpbuf, siz
       int size;
{
       char *volatile buf;
-       int bufsize;
+       size_t bufsize;
       int volatile rstat = EX_OK;
       int rsno;
       bool saveQuickAbort = QuickAbort;
Index: gnu/usr.sbin/sendmail/sendmail/savemail.c
===================================================================
RCS file: /cvs/src/gnu/usr.sbin/sendmail/sendmail/savemail.c,v
retrieving revision 1.12
diff -u -p -r1.12 savemail.c
--- gnu/usr.sbin/sendmail/sendmail/savemail.c   16 Dec 2004 00:21:31 -0000      1.12
+++ gnu/usr.sbin/sendmail/sendmail/savemail.c   24 Mar 2006 00:50:53 -0000
@@ -15,7 +15,7 @@

SM_RCSID("@(#)$Sendmail: savemail.c,v 8.304 2004/10/06 21:36:06 ca Exp $")

-static void    errbody __P((MCI *, ENVELOPE *, char *));
+static bool    errbody __P((MCI *, ENVELOPE *, char *));
static bool    pruneroute __P((char *));

/*
@@ -432,12 +432,13 @@ savemail(e, sendbody)
                       p = macvalue('g', e);
                       macdefine(&e->e_macro, A_PERM, 'g', e->e_sender);

-                       putfromline(&mcibuf, e);
-                       (*e->e_puthdr)(&mcibuf, e->e_header, e, M87F_OUTER);
-                       (*e->e_putbody)(&mcibuf, e, NULL);
-                       putline("\n", &mcibuf); /* XXX EOL from FileMailer? */
-                       (void) sm_io_flush(fp, SM_TIME_DEFAULT);
-                       if (sm_io_error(fp) ||
+                       if (!putfromline(&mcibuf, e) ||
+                           !(*e->e_puthdr)(&mcibuf, e->e_header, e,
+                                       M87F_OUTER) ||
+                           !(*e->e_putbody)(&mcibuf, e, NULL) ||
+                           !putline("\n", &mcibuf) ||
+                           sm_io_flush(fp, SM_TIME_DEFAULT) == SM_IO_EOF ||
+                           sm_io_error(fp) ||
                           sm_io_close(fp, SM_TIME_DEFAULT) < 0)
                               state = ESM_PANIC;
                       else
@@ -732,14 +733,14 @@ returntosender(msg, returnq, flags, e)
**             separator -- any possible MIME separator (unused).
**
**     Returns:
-**             none
+**             success
**
**     Side Effects:
**             Outputs the body of an error message.
*/

/* ARGSUSED2 */
-static void
+static bool
errbody(mci, e, separator)
       register MCI *mci;
       register ENVELOPE *e;
@@ -757,14 +758,16 @@ errbody(mci, e, separator)

       if (bitset(MCIF_INHEADER, mci->mci_flags))
       {
-               putline("", mci);
+               if (!putline("", mci))
+                       goto writeerr;
               mci->mci_flags &= ~MCIF_INHEADER;
       }
       if (e->e_parent == NULL)
       {
               syserr("errbody: null parent");
-               putline("   ----- Original message lost -----\n", mci);
-               return;
+               if (!putline("   ----- Original message lost -----\n", mci))
+                       goto writeerr;
+               return true;
       }

       /*
@@ -773,11 +776,12 @@ errbody(mci, e, separator)

       if (e->e_msgboundary != NULL)
       {
-               putline("This is a MIME-encapsulated message", mci);
-               putline("", mci);
               (void) sm_strlcpyn(buf, sizeof buf, 2, "--", e->e_msgboundary);
-               putline(buf, mci);
-               putline("", mci);
+               if (!putline("This is a MIME-encapsulated message", mci) ||
+                   !putline("", mci) ||
+                   !putline(buf, mci) ||
+                   !putline("", mci))
+                       goto writeerr;
       }

       /*
@@ -799,31 +803,36 @@ errbody(mci, e, separator)
       if (!pm_notify && q == NULL &&
           !bitset(EF_FATALERRS|EF_SENDRECEIPT, e->e_parent->e_flags))
       {
-               putline("    **********************************************",
-                       mci);
-               putline("    **      THIS IS A WARNING MESSAGE ONLY      **",
-                       mci);
-               putline("    **  YOU DO NOT NEED TO RESEND YOUR MESSAGE  **",
-                       mci);
-               putline("    **********************************************",
-                       mci);
-               putline("", mci);
+               if (!putline("    **********************************************",
+                       mci) ||
+                   !putline("    **      THIS IS A WARNING MESSAGE ONLY      **",
+                       mci) ||
+                   !putline("    **  YOU DO NOT NEED TO RESEND YOUR MESSAGE  **",
+                       mci) ||
+                   !putline("    **********************************************",
+                       mci) ||
+                   !putline("", mci))
+                       goto writeerr;
       }
       (void) sm_snprintf(buf, sizeof buf,
               "The original message was received at %s",
               arpadate(ctime(&e->e_parent->e_ctime)));
-       putline(buf, mci);
+       if (!putline(buf, mci))
+               goto writeerr;
       expand("from \201_", buf, sizeof buf, e->e_parent);
-       putline(buf, mci);
+       if (!putline(buf, mci))
+               goto writeerr;

       /* include id in postmaster copies */
       if (pm_notify && e->e_parent->e_id != NULL)
       {
               (void) sm_strlcpyn(buf, sizeof buf, 2, "with id ",
                       e->e_parent->e_id);
-               putline(buf, mci);
+               if (!putline(buf, mci))
+                       goto writeerr;
       }
-       putline("", mci);
+       if (!putline("", mci))
+               goto writeerr;

       /*
       **  Output error message header (if specified and available).
@@ -849,17 +858,19 @@ errbody(mci, e, separator)
                               {
                                       translate_dollars(buf);
                                       expand(buf, buf, sizeof buf, e);
-                                       putline(buf, mci);
+                                       if (!putline(buf, mci))
+                                               goto writeerr;
                               }
                               (void) sm_io_close(xfile, SM_TIME_DEFAULT);
-                               putline("\n", mci);
+                               if (!putline("\n", mci))
+                                       goto writeerr;
                       }
               }
               else
               {
                       expand(ErrMsgFile, buf, sizeof buf, e);
-                       putline(buf, mci);
-                       putline("", mci);
+                       if (!putline(buf, mci) || !putline("", mci))
+                               goto writeerr;
               }
       }

@@ -877,21 +888,24 @@ errbody(mci, e, separator)

               if (printheader)
               {
-                       putline("   ----- The following addresses had permanent fatal errors -----",
-                               mci);
+                       if (!putline("   ----- The following addresses had permanent fatal errors -----",
+                                       mci))
+                               goto writeerr;
                       printheader = false;
               }

               (void) sm_strlcpy(buf, shortenstring(q->q_paddr, MAXSHORTSTR),
                                 sizeof buf);
-               putline(buf, mci);
+               if (!putline(buf, mci))
+                       goto writeerr;
               if (q->q_rstatus != NULL)
               {
                       (void) sm_snprintf(buf, sizeof buf,
                               "    (reason: %s)",
                               shortenstring(exitstat(q->q_rstatus),
                                             MAXSHORTSTR));
-                       putline(buf, mci);
+                       if (!putline(buf, mci))
+                               goto writeerr;
               }
               if (q->q_alias != NULL)
               {
@@ -899,11 +913,12 @@ errbody(mci, e, separator)
                               "    (expanded from: %s)",
                               shortenstring(q->q_alias->q_paddr,
                                             MAXSHORTSTR));
-                       putline(buf, mci);
+                       if (!putline(buf, mci))
+                               goto writeerr;
               }
       }
-       if (!printheader)
-               putline("", mci);
+       if (!printheader && !putline("", mci))
+               goto writeerr;

       /* transient non-fatal errors */
       printheader = true;
@@ -917,25 +932,28 @@ errbody(mci, e, separator)

               if (printheader)
               {
-                       putline("   ----- The following addresses had transient non-fatal errors -----",
-                               mci);
+                       if (!putline("   ----- The following addresses had transient non-fatal errors -----",
+                                       mci))
+                               goto writeerr;
                       printheader = false;
               }

               (void) sm_strlcpy(buf, shortenstring(q->q_paddr, MAXSHORTSTR),
                                 sizeof buf);
-               putline(buf, mci);
+               if (!putline(buf, mci))
+                       goto writeerr;
               if (q->q_alias != NULL)
               {
                       (void) sm_snprintf(buf, sizeof buf,
                               "    (expanded from: %s)",
                               shortenstring(q->q_alias->q_paddr,
                                             MAXSHORTSTR));
-                       putline(buf, mci);
+                       if (!putline(buf, mci))
+                               goto writeerr;
               }
       }
-       if (!printheader)
-               putline("", mci);
+       if (!printheader && !putline("", mci))
+               goto writeerr;

       /* successful delivery notifications */
       printheader = true;
@@ -968,25 +986,28 @@ errbody(mci, e, separator)

               if (printheader)
               {
-                       putline("   ----- The following addresses had successful delivery notifications -----",
-                               mci);
+                       if (!putline("   ----- The following addresses had successful delivery notifications -----",
+                                       mci))
+                               goto writeerr;
                       printheader = false;
               }

               (void) sm_snprintf(buf, sizeof buf, "%s  (%s)",
                        shortenstring(q->q_paddr, MAXSHORTSTR), p);
-               putline(buf, mci);
+               if (!putline(buf, mci))
+                       goto writeerr;
               if (q->q_alias != NULL)
               {
                       (void) sm_snprintf(buf, sizeof buf,
                               "    (expanded from: %s)",
                               shortenstring(q->q_alias->q_paddr,
                                             MAXSHORTSTR));
-                       putline(buf, mci);
+                       if (!putline(buf, mci))
+                               goto writeerr;
               }
       }
-       if (!printheader)
-               putline("", mci);
+       if (!printheader && !putline("", mci))
+               goto writeerr;

       /*
       **  Output transcript of errors
@@ -995,8 +1016,9 @@ errbody(mci, e, separator)
       (void) sm_io_flush(smioout, SM_TIME_DEFAULT);
       if (e->e_parent->e_xfp == NULL)
       {
-               putline("   ----- Transcript of session is unavailable -----\n",
-                       mci);
+               if (!putline("   ----- Transcript of session is unavailable -----\n",
+                               mci))
+                       goto writeerr;
       }
       else
       {
@@ -1007,11 +1029,12 @@ errbody(mci, e, separator)
               while (sm_io_fgets(e->e_parent->e_xfp, SM_TIME_DEFAULT, buf,
                                  sizeof buf) != NULL)
               {
-                       if (printheader)
-                               putline("   ----- Transcript of session follows -----\n",
-                                       mci);
+                       if (printheader && !putline("   ----- Transcript of session follows -----\n",
+                                               mci))
+                               goto writeerr;
                       printheader = false;
-                       putline(buf, mci);
+                       if (!putline(buf, mci))
+                               goto writeerr;
               }
       }
       errno = 0;
@@ -1023,11 +1046,12 @@ errbody(mci, e, separator)

       if (e->e_msgboundary != NULL)
       {
-               putline("", mci);
               (void) sm_strlcpyn(buf, sizeof buf, 2, "--", e->e_msgboundary);
-               putline(buf, mci);
-               putline("Content-Type: message/delivery-status", mci);
-               putline("", mci);
+               if (!putline("", mci) ||
+                   !putline(buf, mci) ||
+                   !putline("Content-Type: message/delivery-status", mci) ||
+                   !putline("", mci))
+                       goto writeerr;

               /*
               **  Output per-message information.
@@ -1039,13 +1063,15 @@ errbody(mci, e, separator)
                       (void) sm_snprintf(buf, sizeof buf,
                                       "Original-Envelope-Id: %.800s",
                                       xuntextify(e->e_parent->e_envid));
-                       putline(buf, mci);
+                       if (!putline(buf, mci))
+                               goto writeerr;
               }

               /* Reporting-MTA: is us (required) */
               (void) sm_snprintf(buf, sizeof buf,
                                  "Reporting-MTA: dns; %.800s", MyHostName);
-               putline(buf, mci);
+               if (!putline(buf, mci))
+                       goto writeerr;

               /* DSN-Gateway: not relevant since we are not translating */

@@ -1059,13 +1085,15 @@ errbody(mci, e, separator)
                       (void) sm_snprintf(buf, sizeof buf,
                                       "Received-From-MTA: %s; %.800s",
                                       p, RealHostName);
-                       putline(buf, mci);
+                       if (!putline(buf, mci))
+                               goto writeerr;
               }

               /* Arrival-Date: -- when it arrived here */
               (void) sm_strlcpyn(buf, sizeof buf, 2, "Arrival-Date: ",
                               arpadate(ctime(&e->e_parent->e_ctime)));
-               putline(buf, mci);
+               if (!putline(buf, mci))
+                       goto writeerr;

               /* Deliver-By-Date: -- when it should have been delivered */
               if (IS_DLVR_BY(e->e_parent))
@@ -1076,7 +1104,8 @@ errbody(mci, e, separator)
                       (void) sm_strlcpyn(buf, sizeof buf, 2,
                                       "Deliver-By-Date: ",
                                       arpadate(ctime(&dbyd)));
-                       putline(buf, mci);
+                       if (!putline(buf, mci))
+                               goto writeerr;
               }

               /*
@@ -1119,7 +1148,8 @@ errbody(mci, e, separator)
                       else
                               continue;

-                       putline("", mci);
+                       if (!putline("", mci))
+                               goto writeerr;

                       /* Original-Recipient: -- passed from on high */
                       if (q->q_orcpt != NULL)
@@ -1127,7 +1157,8 @@ errbody(mci, e, separator)
                               (void) sm_snprintf(buf, sizeof buf,
                                               "Original-Recipient: %.800s",
                                               q->q_orcpt);
-                               putline(buf, mci);
+                               if (!putline(buf, mci))
+                                       goto writeerr;
                       }

                       /* Figure out actual recipient */
@@ -1176,7 +1207,8 @@ errbody(mci, e, separator)
                               (void) sm_snprintf(buf, sizeof buf,
                                                  "Final-Recipient: %s",
                                                  q->q_finalrcpt);
-                               putline(buf, mci);
+                               if (!putline(buf, mci))
+                                       goto writeerr;
                       }

                       /* X-Actual-Recipient: -- the real problem address */
@@ -1190,13 +1222,15 @@ errbody(mci, e, separator)
                               (void) sm_snprintf(buf, sizeof buf,
                                                  "X-Actual-Recipient: %s",
                                                  actual);
-                               putline(buf, mci);
+                               if (!putline(buf, mci))
+                                       goto writeerr;
                       }

                       /* Action: -- what happened? */
                       (void) sm_strlcpyn(buf, sizeof buf, 2, "Action: ",
                               action);
-                       putline(buf, mci);
+                       if (!putline(buf, mci))
+                               goto writeerr;

                       /* Status: -- what _really_ happened? */
                       if (q->q_status != NULL)
@@ -1208,7 +1242,8 @@ errbody(mci, e, separator)
                       else
                               p = "2.0.0";
                       (void) sm_strlcpyn(buf, sizeof buf, 2, "Status: ", p);
-                       putline(buf, mci);
+                       if (!putline(buf, mci))
+                               goto writeerr;

                       /* Remote-MTA: -- who was I talking to? */
                       if (q->q_statmta != NULL)
@@ -1222,7 +1257,8 @@ errbody(mci, e, separator)
                               p = &buf[strlen(buf) - 1];
                               if (*p == '.')
                                       *p = '\0';
-                               putline(buf, mci);
+                               if (!putline(buf, mci))
+                                       goto writeerr;
                       }

                       /* Diagnostic-Code: -- actual result from other end */
@@ -1234,7 +1270,8 @@ errbody(mci, e, separator)
                               (void) sm_snprintf(buf, sizeof buf,
                                               "Diagnostic-Code: %s; %.800s",
                                               p, q->q_rstatus);
-                               putline(buf, mci);
+                               if (!putline(buf, mci))
+                                       goto writeerr;
                       }

                       /* Last-Attempt-Date: -- fine granularity */
@@ -1243,7 +1280,8 @@ errbody(mci, e, separator)
                       (void) sm_strlcpyn(buf, sizeof buf, 2,
                                       "Last-Attempt-Date: ",
                                       arpadate(ctime(&q->q_statdate)));
-                       putline(buf, mci);
+                       if (!putline(buf, mci))
+                               goto writeerr;

                       /* Will-Retry-Until: -- for delayed messages only */
                       if (QS_IS_QUEUEUP(q->q_state))
@@ -1255,7 +1293,8 @@ errbody(mci, e, separator)
                               (void) sm_strlcpyn(buf, sizeof buf, 2,
                                        "Will-Retry-Until: ",
                                        arpadate(ctime(&xdate)));
-                               putline(buf, mci);
+                               if (!putline(buf, mci))
+                                       goto writeerr;
                       }
               }
       }
@@ -1265,7 +1304,8 @@ errbody(mci, e, separator)
       **  Output text of original message
       */

-       putline("", mci);
+       if (!putline("", mci))
+               goto writeerr;
       if (bitset(EF_HAS_DF, e->e_parent->e_flags))
       {
               sendbody = !bitset(EF_NO_BODY_RETN, e->e_parent->e_flags) &&
@@ -1273,21 +1313,27 @@ errbody(mci, e, separator)

               if (e->e_msgboundary == NULL)
               {
-                       if (sendbody)
-                               putline("   ----- Original message follows -----\n", mci);
-                       else
-                               putline("   ----- Message header follows -----\n", mci);
+                       if (!putline(
+                               sendbody
+                               ? "   ----- Original message follows -----\n"
+                               : "   ----- Message header follows -----\n",
+                               mci))
+                       {
+                               goto writeerr;
+                       }
               }
               else
               {
                       (void) sm_strlcpyn(buf, sizeof buf, 2, "--",
                                       e->e_msgboundary);

-                       putline(buf, mci);
+                       if (!putline(buf, mci))
+                               goto writeerr;
                       (void) sm_strlcpyn(buf, sizeof buf, 2, "Content-Type: ",
                                       sendbody ? "message/rfc822"
                                                : "text/rfc822-headers");
-                       putline(buf, mci);
+                       if (!putline(buf, mci))
+                               goto writeerr;

                       p = hvalue("Content-Transfer-Encoding",
                                  e->e_parent->e_header);
@@ -1301,43 +1347,62 @@ errbody(mci, e, separator)
                               (void) sm_snprintf(buf, sizeof buf,
                                               "Content-Transfer-Encoding: %s",
                                               p);
-                               putline(buf, mci);
+                               if (!putline(buf, mci))
+                                       goto writeerr;
                       }
               }
-               putline("", mci);
+               if (!putline("", mci))
+                       goto writeerr;
               save_errno = errno;
-               putheader(mci, e->e_parent->e_header, e->e_parent, M87F_OUTER);
+               if (!putheader(mci, e->e_parent->e_header, e->e_parent,
+                               M87F_OUTER))
+                       goto writeerr;
               errno = save_errno;
               if (sendbody)
-                       putbody(mci, e->e_parent, e->e_msgboundary);
+               {
+                       if (!putbody(mci, e->e_parent, e->e_msgboundary))
+                               goto writeerr;
+               }
               else if (e->e_msgboundary == NULL)
               {
-                       putline("", mci);
-                       putline("   ----- Message body suppressed -----", mci);
+                       if (!putline("", mci) ||
+                           !putline("   ----- Message body suppressed -----",
+                                       mci))
+                       {
+                               goto writeerr;
+                       }
               }
       }
       else if (e->e_msgboundary == NULL)
       {
-               putline("  ----- No message was collected -----\n", mci);
+               if (!putline("  ----- No message was collected -----\n", mci))
+                       goto writeerr;
       }

       if (e->e_msgboundary != NULL)
       {
-               putline("", mci);
               (void) sm_strlcpyn(buf, sizeof buf, 3, "--", e->e_msgboundary,
                                  "--");
-               putline(buf, mci);
+               if (!putline("", mci) || !putline(buf, mci))
+                       goto writeerr;
       }
-       putline("", mci);
-       (void) sm_io_flush(mci->mci_out, SM_TIME_DEFAULT);
+       if (!putline("", mci) ||
+           sm_io_flush(mci->mci_out, SM_TIME_DEFAULT) == SM_IO_EOF)
+                       goto writeerr;

       /*
       **  Cleanup and exit
       */

       if (errno != 0)
+       {
+  writeerr:
               syserr("errbody: I/O error");
+               return false;
+       }
+       return true;
}
+
/*
**  SMTPTODSN -- convert SMTP to DSN status code
**
Index: gnu/usr.sbin/sendmail/sendmail/sendmail.h
===================================================================
RCS file: /cvs/src/gnu/usr.sbin/sendmail/sendmail/sendmail.h,v
retrieving revision 1.23
diff -u -p -r1.23 sendmail.h
--- gnu/usr.sbin/sendmail/sendmail/sendmail.h   16 Dec 2004 00:21:31 -0000      1.23
+++ gnu/usr.sbin/sendmail/sendmail/sendmail.h   24 Mar 2006 00:50:54 -0000
@@ -808,13 +808,13 @@ extern struct hdrinfo     HdrInfo[];
/* functions */
extern void    addheader __P((char *, char *, int, ENVELOPE *));
extern unsigned long   chompheader __P((char *, int, HDR **, ENVELOPE *));
-extern void    commaize __P((HDR *, char *, bool, MCI *, ENVELOPE *));
+extern bool    commaize __P((HDR *, char *, bool, MCI *, ENVELOPE *));
extern HDR     *copyheader __P((HDR *, SM_RPOOL_T *));
extern void    eatheader __P((ENVELOPE *, bool, bool));
extern char    *hvalue __P((char *, HDR *));
extern void    insheader __P((int, char *, char *, int, ENVELOPE *));
extern bool    isheader __P((char *));
-extern void    putfromline __P((MCI *, ENVELOPE *));
+extern bool    putfromline __P((MCI *, ENVELOPE *));
extern void    setupheaders __P((void));

/*
@@ -869,9 +869,9 @@ struct envelope
       short           e_sendmode;     /* message send mode */
       short           e_errormode;    /* error return mode */
       short           e_timeoutclass; /* message timeout class */
-       void            (*e_puthdr)__P((MCI *, HDR *, ENVELOPE *, int));
+       bool            (*e_puthdr)__P((MCI *, HDR *, ENVELOPE *, int));
                                       /* function to put header of message */
-       void            (*e_putbody)__P((MCI *, ENVELOPE *, char *));
+       bool            (*e_putbody)__P((MCI *, ENVELOPE *, char *));
                                       /* function to put body of message */
       ENVELOPE        *e_parent;      /* the message this one encloses */
       ENVELOPE        *e_sibling;     /* the next envelope of interest */
@@ -964,8 +964,8 @@ extern void dropenvelope __P((ENVELOPE *
extern ENVELOPE        *newenvelope __P((ENVELOPE *, ENVELOPE *, SM_RPOOL_T *));
extern void    clrsessenvelope __P((ENVELOPE *));
extern void    printenvflags __P((ENVELOPE *));
-extern void    putbody __P((MCI *, ENVELOPE *, char *));
-extern void    putheader __P((MCI *, HDR *, ENVELOPE *, int));
+extern bool    putbody __P((MCI *, ENVELOPE *, char *));
+extern bool    putheader __P((MCI *, HDR *, ENVELOPE *, int));

/*
**  Message priority classes.
@@ -1649,7 +1649,7 @@ EXTERN unsigned long      PrivacyFlags;   /* pr
#define M87F_NO8TO7            0x0004  /* don't do 8->7 bit conversions */

/* functions */
-extern void    mime7to8 __P((MCI *, HDR *, ENVELOPE *));
+extern bool    mime7to8 __P((MCI *, HDR *, ENVELOPE *));
extern int     mime8to7 __P((MCI *, HDR *, ENVELOPE *, char **, int));

/*
@@ -2144,7 +2144,6 @@ EXTERN bool       ColonOkInAddr;  /* single col
#if !defined(_USE_SUN_NSSWITCH_) && !defined(_USE_DEC_SVC_CONF_)
EXTERN bool    ConfigFileRead; /* configuration file has been read */
#endif /* !defined(_USE_SUN_NSSWITCH_) && !defined(_USE_DEC_SVC_CONF_) */
-EXTERN bool    volatile DataProgress;  /* have we sent anything since last check */
EXTERN bool    DisConnected;   /* running with OutChannel redirect to transcript file */
EXTERN bool    DontExpandCnames;       /* do not $[...$] expand CNAMEs */
EXTERN bool    DontInitGroups; /* avoid initgroups() because of NIS cost */
@@ -2518,8 +2517,8 @@ extern void       printopenfds __P((bool));
extern void    printqueue __P((void));
extern void    printrules __P((void));
extern pid_t   prog_open __P((char **, int *, ENVELOPE *));
-extern void    putline __P((char *, MCI *));
-extern void    putxline __P((char *, size_t, MCI *, int));
+extern bool    putline __P((char *, MCI *));
+extern bool    putxline __P((char *, size_t, MCI *, int));
extern void    queueup_macros __P((int, SM_FILE_T *, ENVELOPE *));
extern void    readcf __P((char *, bool, ENVELOPE *));
extern SIGFUNC_DECL    reapchild __P((int));
Index: gnu/usr.sbin/sendmail/sendmail/sfsasl.c
===================================================================
RCS file: /cvs/src/gnu/usr.sbin/sendmail/sendmail/sfsasl.c,v
retrieving revision 1.17
diff -u -p -r1.17 sfsasl.c
--- gnu/usr.sbin/sendmail/sendmail/sfsasl.c     12 Jan 2005 18:15:46 -0000      1.17
+++ gnu/usr.sbin/sendmail/sendmail/sfsasl.c     24 Mar 2006 00:50:55 -0000
@@ -541,6 +541,125 @@ tls_close(fp)
# define MAX_TLS_IOS   4

/*
+**  TLS_RETRY -- check whether a failed SSL operation can be retried
+**
+**     Parameters:
+**             ssl -- TLS structure
+**             rfd -- read fd
+**             wfd -- write fd
+**             tlsstart -- start time of TLS operation
+**             timeout -- timeout for TLS operation
+**             err -- SSL error
+**             where -- description of operation
+**
+**     Results:
+**             >0 on success
+**             0 on timeout
+**             <0 on error
+*/
+
+int
+tls_retry(ssl, rfd, wfd, tlsstart, timeout, err, where)
+       SSL *ssl;
+       int rfd;
+       int wfd;
+       time_t tlsstart;
+       int timeout;
+       int err;
+       const char *where;
+{
+       int ret;
+       time_t left;
+       time_t now = curtime();
+       struct timeval tv;
+
+       ret = -1;
+
+       /*
+       **  For SSL_ERROR_WANT_{READ,WRITE}:
+       **  There is not a complete SSL record available yet
+       **  or there is only a partial SSL record removed from
+       **  the network (socket) buffer into the SSL buffer.
+       **  The SSL_connect will only succeed when a full
+       **  SSL record is available (assuming a "real" error
+       **  doesn't happen). To handle when a "real" error
+       **  does happen the select is set for exceptions too.
+       **  The connection may be re-negotiated during this time
+       **  so both read and write "want errors" need to be handled.
+       **  A select() exception loops back so that a proper SSL
+       **  error message can be gotten.
+       */
+
+       left = timeout - (now - tlsstart);
+       if (left <= 0)
+               return 0;       /* timeout */
+       tv.tv_sec = left;
+       tv.tv_usec = 0;
+
+       if (LogLevel > 14)
+       {
+               sm_syslog(LOG_INFO, NOQID,
+                         "STARTTLS=%s, info: fds=%d/%d, err=%d",
+                         where, rfd, wfd, err);
+       }
+
+       if (FD_SETSIZE > 0 &&
+           ((err == SSL_ERROR_WANT_READ && rfd >= FD_SETSIZE) ||
+            (err == SSL_ERROR_WANT_WRITE && wfd >= FD_SETSIZE)))
+       {
+               if (LogLevel > 5)
+               {
+                       sm_syslog(LOG_ERR, NOQID,
+                                 "STARTTLS=%s, error: fd %d/%d too large",
+                                 where, rfd, wfd);
+               if (LogLevel > 8)
+                       tlslogerr(where);
+               }
+               errno = EINVAL;
+       }
+       else if (err == SSL_ERROR_WANT_READ)
+       {
+               fd_set ssl_maskr, ssl_maskx;
+
+               FD_ZERO(&ssl_maskr);
+               FD_SET(rfd, &ssl_maskr);
+               FD_ZERO(&ssl_maskx);
+               FD_SET(rfd, &ssl_maskx);
+               do
+               {
+                       ret = select(rfd + 1, &ssl_maskr, NULL, &ssl_maskx,
+                                       &tv);
+               } while (ret < 0 && errno == EINTR);
+               if (ret < 0 && errno > 0)
+                       ret = -errno;
+       }
+       else if (err == SSL_ERROR_WANT_WRITE)
+       {
+               fd_set ssl_maskw, ssl_maskx;
+
+               FD_ZERO(&ssl_maskw);
+               FD_SET(wfd, &ssl_maskw);
+               FD_ZERO(&ssl_maskx);
+               FD_SET(rfd, &ssl_maskx);
+               do
+               {
+                       ret = select(wfd + 1, NULL, &ssl_maskw, &ssl_maskx,
+                                       &tv);
+               } while (ret < 0 && errno == EINTR);
+               if (ret < 0 && errno > 0)
+                       ret = -errno;
+       }
+       return ret;
+}
+
+/* errno to force refill() etc to stop (see IS_IO_ERROR()) */
+#ifdef ETIMEDOUT
+# define SM_ERR_TIMEOUT        ETIMEDOUT
+#else /* ETIMEDOUT */
+# define SM_ERR_TIMEOUT        EIO
+#endif /* ETIMEDOUT */
+
+/*
**  TLS_READ -- read secured information for the caller
**
**     Parameters:
@@ -561,38 +680,42 @@ tls_read(fp, buf, size)
       char *buf;
       size_t size;
{
-       int r;
-       static int again = MAX_TLS_IOS;
+       int r, rfd, wfd, try, ssl_err;
       struct tls_obj *so = (struct tls_obj *) fp->f_cookie;
+       time_t tlsstart;
       char *err;

+       try = 99;
+       err = NULL;
+       tlsstart = curtime();
+
+  retry:
       r = SSL_read(so->con, (char *) buf, size);

       if (r > 0)
-       {
-               again = MAX_TLS_IOS;
               return r;
-       }

       err = NULL;
-       switch (SSL_get_error(so->con, r))
+       switch (ssl_err = SSL_get_error(so->con, r))
       {
         case SSL_ERROR_NONE:
         case SSL_ERROR_ZERO_RETURN:
-               again = MAX_TLS_IOS;
               break;
         case SSL_ERROR_WANT_WRITE:
-               if (--again <= 0)
-                       err = "read W BLOCK";
-               else
-                       errno = EAGAIN;
-               break;
+               err = "read W BLOCK";
+               /* FALLTHROUGH */
         case SSL_ERROR_WANT_READ:
-               if (--again <= 0)
+               if (err == NULL)
                       err = "read R BLOCK";
-               else
-                       errno = EAGAIN;
+               rfd = SSL_get_rfd(so->con);
+               wfd = SSL_get_wfd(so->con);
+               try = tls_retry(so->con, rfd, wfd, tlsstart,
+                               TimeOuts.to_datablock, ssl_err, "read");
+               if (try > 0)
+                       goto retry;
+               errno = SM_ERR_TIMEOUT;
               break;
+
         case SSL_ERROR_WANT_X509_LOOKUP:
               err = "write X BLOCK";
               break;
@@ -625,15 +748,22 @@ tls_read(fp, buf, size)
               int save_errno;

               save_errno = (errno == 0) ? EIO : errno;
-               again = MAX_TLS_IOS;
-               if (LogLevel > 9)
+               if (try == 0 && save_errno == SM_ERR_TIMEOUT)
+               {
+                       if (LogLevel > 7)
+                               sm_syslog(LOG_WARNING, NOQID,
+                                         "STARTTLS: read error=timeout");
+               }
+               else if (LogLevel > 8)
                       sm_syslog(LOG_WARNING, NOQID,
-                                 "STARTTLS: read error=%s (%d), errno=%d, get_error=%s",
+                                 "STARTTLS: read error=%s (%d), errno=%d, get_error=%s, retry=%d, ssl_err=%d",
                                 err, r, errno,
-                                 ERR_error_string(ERR_get_error(), NULL));
+                                 ERR_error_string(ERR_get_error(), NULL), try,
+                                 ssl_err);
               else if (LogLevel > 7)
                       sm_syslog(LOG_WARNING, NOQID,
-                                 "STARTTLS: read error=%s (%d)", err, r);
+                                 "STARTTLS: read error=%s (%d), retry=%d, ssl_err=%d",
+                                 err, r, errno, try, ssl_err);
               errno = save_errno;
       }
       return r;
@@ -660,36 +790,39 @@ tls_write(fp, buf, size)
       const char *buf;
       size_t size;
{
-       int r;
-       static int again = MAX_TLS_IOS;
+       int r, rfd, wfd, try, ssl_err;
       struct tls_obj *so = (struct tls_obj *) fp->f_cookie;
+       time_t tlsstart;
       char *err;

+       try = 99;
+       err = NULL;
+       tlsstart = curtime();
+
+  retry:
       r = SSL_write(so->con, (char *) buf, size);

       if (r > 0)
-       {
-               again = MAX_TLS_IOS;
               return r;
-       }
       err = NULL;
-       switch (SSL_get_error(so->con, r))
+       switch (ssl_err = SSL_get_error(so->con, r))
       {
         case SSL_ERROR_NONE:
         case SSL_ERROR_ZERO_RETURN:
-               again = MAX_TLS_IOS;
               break;
         case SSL_ERROR_WANT_WRITE:
-               if (--again <= 0)
-                       err = "write W BLOCK";
-               else
-                       errno = EAGAIN;
-               break;
+               err = "read W BLOCK";
+               /* FALLTHROUGH */
         case SSL_ERROR_WANT_READ:
-               if (--again <= 0)
-                       err = "write R BLOCK";
-               else
-                       errno = EAGAIN;
+               if (err == NULL)
+                       err = "read R BLOCK";
+               rfd = SSL_get_rfd(so->con);
+               wfd = SSL_get_wfd(so->con);
+               try = tls_retry(so->con, rfd, wfd, tlsstart,
+                               DATA_PROGRESS_TIMEOUT, ssl_err, "write");
+               if (try > 0)
+                       goto retry;
+               errno = SM_ERR_TIMEOUT;
               break;
         case SSL_ERROR_WANT_X509_LOOKUP:
               err = "write X BLOCK";
@@ -722,15 +855,22 @@ tls_write(fp, buf, size)
               int save_errno;

               save_errno = (errno == 0) ? EIO : errno;
-               again = MAX_TLS_IOS;
-               if (LogLevel > 9)
+               if (try == 0 && save_errno == SM_ERR_TIMEOUT)
+               {
+                       if (LogLevel > 7)
+                               sm_syslog(LOG_WARNING, NOQID,
+                                         "STARTTLS: write error=timeout");
+               }
+               else if (LogLevel > 8)
                       sm_syslog(LOG_WARNING, NOQID,
-                                 "STARTTLS: write error=%s (%d), errno=%d, get_error=%s",
+                                 "STARTTLS: write error=%s (%d), errno=%d, get_error=%s, retry=%d, ssl_err=%d",
                                 err, r, errno,
-                                 ERR_error_string(ERR_get_error(), NULL));
+                                 ERR_error_string(ERR_get_error(), NULL), try,
+                                 ssl_err);
               else if (LogLevel > 7)
                       sm_syslog(LOG_WARNING, NOQID,
-                                 "STARTTLS: write error=%s (%d)", err, r);
+                                 "STARTTLS: write error=%s (%d), errno=%d, retry=%d, ssl_err=%d",
+                                 err, r, errno, try, ssl_err);
               errno = save_errno;
       }
       return r;
Index: gnu/usr.sbin/sendmail/sendmail/sfsasl.h
===================================================================
RCS file: /cvs/src/gnu/usr.sbin/sendmail/sendmail/sfsasl.h,v
retrieving revision 1.4
diff -u -p -r1.4 sfsasl.h
--- gnu/usr.sbin/sendmail/sendmail/sfsasl.h     11 Sep 2001 19:02:50 -0000      1.4
+++ gnu/usr.sbin/sendmail/sendmail/sfsasl.h     24 Mar 2006 00:50:55 -0000
@@ -17,6 +17,8 @@ extern int    sfdcsasl __P((SM_FILE_T **, S
#endif /* SASL */

# if STARTTLS
+extern int     tls_retry __P((SSL *, int, int, time_t, int, int,
+                               const char *));
extern int     sfdctls __P((SM_FILE_T **, SM_FILE_T **, SSL *));
# endif /* STARTTLS */

Index: gnu/usr.sbin/sendmail/sendmail/srvrsmtp.c
===================================================================
RCS file: /cvs/src/gnu/usr.sbin/sendmail/sendmail/srvrsmtp.c,v
retrieving revision 1.22
diff -u -p -r1.22 srvrsmtp.c
--- gnu/usr.sbin/sendmail/sendmail/srvrsmtp.c   16 Dec 2004 00:21:31 -0000      1.22
+++ gnu/usr.sbin/sendmail/sendmail/srvrsmtp.c   24 Mar 2006 00:50:56 -0000
@@ -503,7 +503,6 @@ smtp(nullserver, d_flags, e)
#endif /* SASL */
       int r;
#if STARTTLS
-       int fdfl;
       int rfd, wfd;
       volatile bool tls_active = false;
       volatile bool smtps = bitnset(D_SMTPS, d_flags);
@@ -1693,97 +1692,26 @@ smtp(nullserver, d_flags, e)
#  define SSL_ACC(s)   SSL_accept(s)

                       tlsstart = curtime();
-                       fdfl = fcntl(rfd, F_GETFL);
-                       if (fdfl != -1)
-                               fcntl(rfd, F_SETFL, fdfl|O_NONBLOCK);
  ssl_retry:
                       if ((r = SSL_ACC(srv_ssl)) <= 0)
                       {
-                               int i;
-                               bool timedout;
-                               time_t left;
-                               time_t now = curtime();
-                               struct timeval tv;
+                               int i, ssl_err;

-                               /* what to do in this case? */
-                               i = SSL_get_error(srv_ssl, r);
+                               ssl_err = SSL_get_error(srv_ssl, r);
+                               i = tls_retry(srv_ssl, rfd, wfd, tlsstart,
+                                               TimeOuts.to_starttls, ssl_err,
+                                               "server");
+                               if (i > 0)
+                                       goto ssl_retry;

-                               /*
-                               **  For SSL_ERROR_WANT_{READ,WRITE}:
-                               **  There is no SSL record available yet
-                               **  or there is only a partial SSL record
-                               **  removed from the network (socket) buffer
-                               **  into the SSL buffer. The SSL_accept will
-                               **  only succeed when a full SSL record is
-                               **  available (assuming a "real" error
-                               **  doesn't happen). To handle when a "real"
-                               **  error does happen the select is set for
-                               **  exceptions too.
-                               **  The connection may be re-negotiated
-                               **  during this time so both read and write
-                               **  "want errors" need to be handled.
-                               **  A select() exception loops back so that
-                               **  a proper SSL error message can be gotten.
-                               */
-
-                               left = TimeOuts.to_starttls - (now - tlsstart);
-                               timedout = left <= 0;
-                               if (!timedout)
-                               {
-                                       tv.tv_sec = left;
-                                       tv.tv_usec = 0;
-                               }
-
-                               if (!timedout && FD_SETSIZE > 0 &&
-                                   (rfd >= FD_SETSIZE ||
-                                    (i == SSL_ERROR_WANT_WRITE &&
-                                     wfd >= FD_SETSIZE)))
-                               {
-                                       if (LogLevel > 5)
-                                       {
-                                               sm_syslog(LOG_ERR, NOQID,
-                                                         "STARTTLS=server, error: fd %d/%d too large",
-                                                         rfd, wfd);
-                                               if (LogLevel > 8)
-                                                       tlslogerr("server");
-                                       }
-                                       goto tlsfail;
-                               }
-
-                               /* XXX what about SSL_pending() ? */
-                               if (!timedout && i == SSL_ERROR_WANT_READ)
-                               {
-                                       fd_set ssl_maskr, ssl_maskx;
-
-                                       FD_ZERO(&ssl_maskr);
-                                       FD_SET(rfd, &ssl_maskr);
-                                       FD_ZERO(&ssl_maskx);
-                                       FD_SET(rfd, &ssl_maskx);
-                                       if (select(rfd + 1, &ssl_maskr, NULL,
-                                                  &ssl_maskx, &tv) > 0)
-                                               goto ssl_retry;
-                               }
-                               if (!timedout && i == SSL_ERROR_WANT_WRITE)
-                               {
-                                       fd_set ssl_maskw, ssl_maskx;
-
-                                       FD_ZERO(&ssl_maskw);
-                                       FD_SET(wfd, &ssl_maskw);
-                                       FD_ZERO(&ssl_maskx);
-                                       FD_SET(rfd, &ssl_maskx);
-                                       if (select(wfd + 1, NULL, &ssl_maskw,
-                                                  &ssl_maskx, &tv) > 0)
-                                               goto ssl_retry;
-                               }
                               if (LogLevel > 5)
                               {
                                       sm_syslog(LOG_WARNING, NOQID,
-                                                 "STARTTLS=server, error: accept failed=%d, SSL_error=%d, timedout=%d, errno=%d",
-                                                 r, i, (int) timedout, errno);
+                                                 "STARTTLS=server, error: accept failed=%d, SSL_error=%d, errno=%d, retry=%d",
+                                                 r, ssl_err, errno, i);
                                       if (LogLevel > 8)
                                               tlslogerr("server");
                               }
-tlsfail:
                               tls_ok_srv = false;
                               SSL_free(srv_ssl);
                               srv_ssl = NULL;
@@ -1797,9 +1725,6 @@ tlsfail:
                               e->e_sendqueue = NULL;
                               goto doquit;
                       }
-
-                       if (fdfl != -1)
-                               fcntl(rfd, F_SETFL, fdfl);

                       /* ignore return code for now, it's in {verify} */
                       (void) tls_get_info(srv_ssl, true,
Index: gnu/usr.sbin/sendmail/sendmail/usersmtp.c
===================================================================
RCS file: /cvs/src/gnu/usr.sbin/sendmail/sendmail/usersmtp.c,v
retrieving revision 1.18
diff -u -p -r1.18 usersmtp.c
--- gnu/usr.sbin/sendmail/sendmail/usersmtp.c   12 Jan 2005 18:15:46 -0000      1.18
+++ gnu/usr.sbin/sendmail/sendmail/usersmtp.c   24 Mar 2006 00:50:57 -0000
@@ -18,7 +18,6 @@ SM_RCSID("@(#)$Sendmail: usersmtp.c,v 8.
#include <sysexits.h>


-static void    datatimeout __P((int));
static void    esmtp_check __P((char *, bool, MAILER *, MCI *, ENVELOPE *));
static void    helo_options __P((char *, bool, MAILER *, MCI *, ENVELOPE *));
static int     smtprcptstat __P((ADDRESS *, MAILER *, MCI *, ENVELOPE *));
@@ -2492,9 +2491,6 @@ smtprcptstat(to, m, mci, e)
**             exit status corresponding to DATA command.
*/

-static jmp_buf CtxDataTimeout;
-static SM_EVENT        *volatile DataTimeout = NULL;
-
int
smtpdata(m, mci, e, ctladdr, xstart)
       MAILER *m;
@@ -2630,43 +2626,22 @@ smtpdata(m, mci, e, ctladdr, xstart)
       **  factor.  The main thing is that it should not be infinite.
       */

-       if (setjmp(CtxDataTimeout) != 0)
-       {
-               mci->mci_errno = errno;
-               mci->mci_state = MCIS_ERROR;
-               mci_setstat(mci, EX_TEMPFAIL, "4.4.2", NULL);
-
-               /*
-               **  If putbody() couldn't finish due to a timeout,
-               **  rewind it here in the timeout handler.  See
-               **  comments at the end of putbody() for reasoning.
-               */
-
-               if (e->e_dfp != NULL)
-                       (void) bfrewind(e->e_dfp);
-
-               errno = mci->mci_errno;
-               syserr("451 4.4.1 timeout writing message to %s", CurHostName);
-               smtpquit(m, mci, e);
-               return EX_TEMPFAIL;
-       }
-
       if (tTd(18, 101))
       {
               /* simulate a DATA timeout */
-               timeout = 1;
+               timeout = 10;
       }
       else
-               timeout = DATA_PROGRESS_TIMEOUT;
-
-       DataTimeout = sm_setevent(timeout, datatimeout, 0);
+               timeout = DATA_PROGRESS_TIMEOUT * 1000;
+       sm_io_setinfo(mci->mci_out, SM_IO_WHAT_TIMEOUT, &timeout);


       /*
       **  Output the actual message.
       */

-       (*e->e_puthdr)(mci, e->e_header, e, M87F_OUTER);
+       if (!(*e->e_puthdr)(mci, e->e_header, e, M87F_OUTER))
+               goto writeerr;

       if (tTd(18, 101))
       {
@@ -2674,14 +2649,13 @@ smtpdata(m, mci, e, ctladdr, xstart)
               (void) sleep(2);
       }

-       (*e->e_putbody)(mci, e, NULL);
+       if (!(*e->e_putbody)(mci, e, NULL))
+               goto writeerr;

       /*
       **  Cleanup after sending message.
       */

-       if (DataTimeout != NULL)
-               sm_clrevent(DataTimeout);

#if PIPELINING
       }
@@ -2721,7 +2695,9 @@ smtpdata(m, mci, e, ctladdr, xstart)
       }

       /* terminate the message */
-       (void) sm_io_fprintf(mci->mci_out, SM_TIME_DEFAULT, ".%s", m->m_eol);
+       if (sm_io_fprintf(mci->mci_out, SM_TIME_DEFAULT, ".%s", m->m_eol) ==
+                                                               SM_IO_EOF)
+               goto writeerr;
       if (TrafficLogFile != NULL)
               (void) sm_io_fprintf(TrafficLogFile, SM_TIME_DEFAULT,
                                    "%05d >>> .\n", (int) CurrentPid);
@@ -2772,51 +2748,27 @@ smtpdata(m, mci, e, ctladdr, xstart)
                         shortenstring(SmtpReplyBuffer, 403));
       }
       return rstat;
-}

-static void
-datatimeout(ignore)
-       int ignore;
-{
-       int save_errno = errno;
+  writeerr:
+       mci->mci_errno = errno;
+       mci->mci_state = MCIS_ERROR;
+       mci_setstat(mci, EX_TEMPFAIL, "4.4.2", NULL);

       /*
-       **  NOTE: THIS CAN BE CALLED FROM A SIGNAL HANDLER.  DO NOT ADD
-       **      ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE
-       **      DOING.
+       **  If putbody() couldn't finish due to a timeout,
+       **  rewind it here in the timeout handler.  See
+       **  comments at the end of putbody() for reasoning.
       */

-       if (DataProgress)
-       {
-               time_t timeout;
-
-               /* check back again later */
-               if (tTd(18, 101))
-               {
-                       /* simulate a DATA timeout */
-                       timeout = 1;
-               }
-               else
-                       timeout = DATA_PROGRESS_TIMEOUT;
-
-               /* reset the timeout */
-               DataTimeout = sm_sigsafe_setevent(timeout, datatimeout, 0);
-               DataProgress = false;
-       }
-       else
-       {
-               /* event is done */
-               DataTimeout = NULL;
-       }
+       if (e->e_dfp != NULL)
+               (void) bfrewind(e->e_dfp);

-       /* if no progress was made or problem resetting event, die now */
-       if (DataTimeout == NULL)
-       {
-               errno = ETIMEDOUT;
-               longjmp(CtxDataTimeout, 1);
-       }
-       errno = save_errno;
+       errno = mci->mci_errno;
+       syserr("451 4.4.1 timeout writing message to %s", CurHostName);
+       smtpquit(m, mci, e);
+       return EX_TEMPFAIL;
}
+
/*
**  SMTPGETSTAT -- get status code from DATA in LMTP
**
Index: gnu/usr.sbin/sendmail/sendmail/util.c
===================================================================
RCS file: /cvs/src/gnu/usr.sbin/sendmail/sendmail/util.c,v
retrieving revision 1.17
diff -u -p -r1.17 util.c
--- gnu/usr.sbin/sendmail/sendmail/util.c       16 Dec 2004 00:21:31 -0000      1.17
+++ gnu/usr.sbin/sendmail/sendmail/util.c       24 Mar 2006 00:50:57 -0000
@@ -456,6 +456,8 @@ xalloc(sz)
{
       register char *p;

+       SM_REQUIRE(sz >= 0);
+
       /* some systems can't handle size zero mallocs */
       if (sz <= 0)
               sz = 1;
@@ -970,18 +972,18 @@ fixcrlf(line, stripnl)
**             mci -- the mailer connection information.
**
**     Returns:
-**             none
+**             true iff line was written successfully
**
**     Side Effects:
**             output of l to mci->mci_out.
*/

-void
+bool
putline(l, mci)
       register char *l;
       register MCI *mci;
{
-       putxline(l, strlen(l), mci, PXLF_MAPFROM);
+       return putxline(l, strlen(l), mci, PXLF_MAPFROM);
}
/*
**  PUTXLINE -- putline with flags bits.
@@ -1000,13 +1002,13 @@ putline(l, mci)
**                 PXLF_NOADDEOL -- don't add an EOL if one wasn't present.
**
**     Returns:
-**             none
+**             true iff line was written successfully
**
**     Side Effects:
**             output of l to mci->mci_out.
*/

-void
+bool
putxline(l, len, mci, pxflags)
       register char *l;
       size_t len;
@@ -1058,11 +1060,6 @@ putxline(l, len, mci, pxflags)
                               if (sm_io_putc(mci->mci_out, SM_TIME_DEFAULT,
                                              '.') == SM_IO_EOF)
                                       dead = true;
-                               else
-                               {
-                                       /* record progress for DATA timeout */
-                                       DataProgress = true;
-                               }
                               if (TrafficLogFile != NULL)
                                       (void) sm_io_putc(TrafficLogFile,
                                                         SM_TIME_DEFAULT, '.');
@@ -1075,11 +1072,6 @@ putxline(l, len, mci, pxflags)
                               if (sm_io_putc(mci->mci_out, SM_TIME_DEFAULT,
                                              '>') == SM_IO_EOF)
                                       dead = true;
-                               else
-                               {
-                                       /* record progress for DATA timeout */
-                                       DataProgress = true;
-                               }
                               if (TrafficLogFile != NULL)
                                       (void) sm_io_putc(TrafficLogFile,
                                                         SM_TIME_DEFAULT,
@@ -1091,16 +1083,11 @@ putxline(l, len, mci, pxflags)
                       while (l < q)
                       {
                               if (sm_io_putc(mci->mci_out, SM_TIME_DEFAULT,
-                                              (unsigned char) *l++) == SM_IO_EOF)
+                                      (unsigned char) *l++) == SM_IO_EOF)
                               {
                                       dead = true;
                                       break;
                               }
-                               else
-                               {
-                                       /* record progress for DATA timeout */
-                                       DataProgress = true;
-                               }
                       }
                       if (dead)
                               break;
@@ -1116,11 +1103,6 @@ putxline(l, len, mci, pxflags)
                               dead = true;
                               break;
                       }
-                       else
-                       {
-                               /* record progress for DATA timeout */
-                               DataProgress = true;
-                       }
                       if (TrafficLogFile != NULL)
                       {
                               for (l = l_base; l < q; l++)
@@ -1144,11 +1126,9 @@ putxline(l, len, mci, pxflags)
               {
                       if (sm_io_putc(mci->mci_out, SM_TIME_DEFAULT, '.') ==
                           SM_IO_EOF)
-                               break;
-                       else
                       {
-                               /* record progress for DATA timeout */
-                               DataProgress = true;
+                               dead = true;
+                               break;
                       }
                       if (TrafficLogFile != NULL)
                               (void) sm_io_putc(TrafficLogFile,
@@ -1161,11 +1141,9 @@ putxline(l, len, mci, pxflags)
               {
                       if (sm_io_putc(mci->mci_out, SM_TIME_DEFAULT, '>') ==
                           SM_IO_EOF)
-                               break;
-                       else
                       {
-                               /* record progress for DATA timeout */
-                               DataProgress = true;
+                               dead = true;
+                               break;
                       }
                       if (TrafficLogFile != NULL)
                               (void) sm_io_putc(TrafficLogFile,
@@ -1183,11 +1161,6 @@ putxline(l, len, mci, pxflags)
                               dead = true;
                               break;
                       }
-                       else
-                       {
-                               /* record progress for DATA timeout */
-                               DataProgress = true;
-                       }
               }
               if (dead)
                       break;
@@ -1198,11 +1171,9 @@ putxline(l, len, mci, pxflags)
               if ((!bitset(PXLF_NOADDEOL, pxflags) || !noeol) &&
                   sm_io_fputs(mci->mci_out, SM_TIME_DEFAULT,
                               mci->mci_mailer->m_eol) == SM_IO_EOF)
-                       break;
-               else
               {
-                       /* record progress for DATA timeout */
-                       DataProgress = true;
+                       dead = true;
+                       break;
               }
               if (l < end && *l == '\n')
               {
@@ -1211,11 +1182,9 @@ putxline(l, len, mci, pxflags)
                       {
                               if (sm_io_putc(mci->mci_out, SM_TIME_DEFAULT,
                                              ' ') == SM_IO_EOF)
-                                       break;
-                               else
                               {
-                                       /* record progress for DATA timeout */
-                                       DataProgress = true;
+                                       dead = true;
+                                       break;
                               }

                               if (TrafficLogFile != NULL)
@@ -1224,10 +1193,10 @@ putxline(l, len, mci, pxflags)
                       }
               }

-               /* record progress for DATA timeout */
-               DataProgress = true;
       } while (l < end);
+       return !dead;
}
+
/*
**  XUNLINK -- unlink a file, doing logging as appropriate.
**
@@ -2433,6 +2402,7 @@ str2prt(s)
                               *h++ = 'r';
                               break;
                         default:
+                               SM_ASSERT(l >= 2);
                               (void) sm_snprintf(h, l, "%03o",
                                       (unsigned int)((unsigned char) c));