Apply this patch to update an 8.6.3 sendmail to 8.6.4.

THIS IS A CRITICAL PATCH!  There were some bugs in 8.6.3 that caused
core dumps and other serious problems.  It also includes some patches
designed to completely thwart a class of security problems that have
been causing a lot of grief recently.


*** RELEASE_NOTES.OLD	Sun Oct 24 16:55:04 1993
--- RELEASE_NOTES	Sun Oct 31 13:04:54 1993
***************
*** 1,3 ****
--- 1,51 ----
+ 8.6.4/8.6.4	93/10/31
+ 	Repair core-dump problem (write to read-only memory segment)
+ 		if you fall back to the return-to-Postmaster case in
+ 		savemail.  Problem reported by Richard Liu.
+ 	Immediately diagnose bogus sender addresses in SMTP.  This
+ 		makes quite certain that crackers can't use this
+ 		class of attack.
+ 	Reliability Fix:  check return value from fclose() and fsync()
+ 		in a few critical places.
+ 	Minor problem in initsys() that reversed a condition for
+ 		redirecting the output channel on queue runs.  It's
+ 		not clear this code even does anything.  From Eric
+ 		Wassenaar of the Dutch National Institute for Nuclear
+ 		and High-Energy Physics.
+ 	Fix some problems that caused queue runs to do "too much work",
+ 		such as double-reading the Errors-To: header.  From
+ 		Eric Wassenaar.
+ 	Error messages on writing the temporary file (including the
+ 		data file) were getting suppressed in SMTP -- this
+ 		fix causes them to be properly reported.  From Eric
+ 		Wassenaar.
+ 	Some changes to support AF_UNIX sockets -- this will only
+ 		really become relevant in the next release, but some
+ 		people need it for local patches.  From Michael
+ 		Corrigan of UC San Diego.
+ 	Use dynamically allocated memory (instead of static buffers)
+ 		for macros defined in initsys() and settime(); since
+ 		these can have different values depending on which
+ 		envelope they are in.  From Eric Wassenaar.
+ 	Improve logging to show ctladdr on to= logging; this tells you
+ 		what uid/gid processes ran as.
+ 	Fix a problem that caused error messages to be discarded if
+ 		the sender address was unparseable for some reason;
+ 		this was supposed to fall back to the "return to
+ 		postmaster" case.
+ 	Improve aliaswait backoff algorithm.
+ 	Portability patches for Linux (8.6.3 required another header
+ 		file) (from Karl London) and SCO UNIX.
+ 	CONFIG: patch prog mailer to not strip host name off of envelope
+ 		addresses (so that it matches local again).  From
+ 		Christopher Davis.
+ 	CONFIG: change uucp-dom mailer so that "<>" translates to $n;
+ 		this prevents uux from seeing lines with null names like
+ 		``From   Sat Oct 30 14:55:31 1993''.  From Motonori
+ 		Nakamura of Kyoto University.
+ 	CONFIG: handle <list:;> syntax correctly.  This isn't legal, but
+ 		it shouldn't fail miserably.  From Motonori Nakamura.
+ 
  8.6.3/8.6.3	93/10/24
  	IMPORTANT FIX: Fix several problems that caused open files to
  		be "lost" during queue runs; this overflowed the open
*** KNOWNBUGS.OLD	Thu Oct 28 09:28:23 1993
--- KNOWNBUGS	Sun Oct 31 11:39:06 1993
***************
*** 43,51 ****
    hub name.  Some sites might prefer to expose some names such as
    root.  This information is always available in Received: lines.
  
  * If you EXPN a list or user that has a program mailer, the output of
    EXPN will include ``@local.host.name''.  You can't actually mail to
    this address.  It's not clear what the right behaviour is in this
    circumstance.
  
! (Version 8.8, last updated 10/24/93)
--- 43,59 ----
    hub name.  Some sites might prefer to expose some names such as
    root.  This information is always available in Received: lines.
  
+ * $c (hop count) macro improperly set.
+ 
+   The $c macro is supposed to contain the current hop count, for use
+   when calling a mailer.  This macro is initialized too early, and
+   is always zero (or the value of the -c command line flag, if any).
+   This macro will probably be removed entirely in a future release;
+   I don't believe there are any mailers left that require it.
+ 
  * If you EXPN a list or user that has a program mailer, the output of
    EXPN will include ``@local.host.name''.  You can't actually mail to
    this address.  It's not clear what the right behaviour is in this
    circumstance.
  
! (Version 8.9, last updated 10/31/93)
*** src/Makefile.Linux.OLD	Wed Oct 27 06:48:26 1993
--- src/Makefile.Linux	Thu Oct 28 07:02:16 1993
***************
*** 35,53 ****
  LIBS=	-lbsd -ldbm
  
  # location of sendmail binary (usually /usr/sbin or /usr/lib)
! BINDIR=	${DESTDIR}/etc/sendmail
  
  # location of sendmail.st file (usually /var/log or /usr/lib)
! STDIR=	${DESTDIR}/etc/sendmail
  
  # location of sendmail.hf file (usually /usr/share/misc or /usr/lib)
! HFDIR=	${DESTDIR}/etc/sendmail
  
  # additional .o files needed
  OBJADD=
  
  # additional pseudo-sources needed
! BEFORE=	unistd.h dirent.h
  
  ###################  end of user configuration flags  ######################
  
--- 35,53 ----
  LIBS=	-lbsd -ldbm
  
  # location of sendmail binary (usually /usr/sbin or /usr/lib)
! BINDIR=	${DESTDIR}/usr/lib
  
  # location of sendmail.st file (usually /var/log or /usr/lib)
! STDIR=	${DESTDIR}/usr/lib
  
  # location of sendmail.hf file (usually /usr/share/misc or /usr/lib)
! HFDIR=	${DESTDIR}/usr/lib
  
  # additional .o files needed
  OBJADD=
  
  # additional pseudo-sources needed
! BEFORE=
  
  ###################  end of user configuration flags  ######################
  
***************
*** 78,91 ****
  	echo "#include <sys/dir.h>" > dirent.h
  	echo "#define dirent	direct" >> dirent.h
  
  aliases.0: aliases.5
! 	nroff -mandoc aliases.5 > aliases.0
  
  newaliases.0: newaliases.1
! 	nroff -mandoc newaliases.1 > newaliases.0
  
  sendmail.0: sendmail.8
! 	nroff -mandoc sendmail.8 > sendmail.0
  
  install: install-sendmail install-docs
  
--- 78,93 ----
  	echo "#include <sys/dir.h>" > dirent.h
  	echo "#define dirent	direct" >> dirent.h
  
+ NROFF=	nroff
+ 
  aliases.0: aliases.5
! 	${NROFF} -mandoc aliases.5 > aliases.0
  
  newaliases.0: newaliases.1
! 	${NROFF} -mandoc newaliases.1 > newaliases.0
  
  sendmail.0: sendmail.8
! 	${NROFF} -mandoc sendmail.8 > sendmail.0
  
  install: install-sendmail install-docs
  
*** src/Makefile.OSF1.OLD	Mon Oct 25 12:38:03 1993
--- src/Makefile.OSF1	Mon Oct 25 12:39:01 1993
***************
*** 83,92 ****
  install: install-sendmail install-docs
  
  install-sendmail: sendmail
! 	install -o ${BINOWN} -g ${BINGRP} -m ${BINMODE} sendmail ${BINDIR}
  	for i in ${LINKS}; do rm -f $$i; ln -s ${BINDIR}/sendmail $$i; done
  	cp /dev/null ${STDIR}/sendmail.st
! 	chmod ${BINMOD}.${BINGRP} ${STDIR}/sendmail.st
  	installbsd -c -o ${BINOWN} -g ${BINGRP} -m 444 sendmail.hf ${HFDIR}
  	rm -f /usr/sbin/smtpd
  
--- 83,93 ----
  install: install-sendmail install-docs
  
  install-sendmail: sendmail
! 	installbsd -o ${BINOWN} -g ${BINGRP} -m ${BINMODE} sendmail ${BINDIR}
  	for i in ${LINKS}; do rm -f $$i; ln -s ${BINDIR}/sendmail $$i; done
  	cp /dev/null ${STDIR}/sendmail.st
! 	chmod ${BINMOD} ${STDIR}/sendmail.st
! 	chown ${BINGRP}.${BINGRP} ${STDIR}/sendmail.st
  	installbsd -c -o ${BINOWN} -g ${BINGRP} -m 444 sendmail.hf ${HFDIR}
  	rm -f /usr/sbin/smtpd
  
*** src/Makefile.SunOS.OLD	Sun Oct 24 13:39:28 1993
--- src/Makefile.SunOS	Sun Oct 24 13:39:49 1993
***************
*** 41,47 ****
  BINDIR=	${DESTDIR}/usr/lib
  
  # location of sendmail.st file (usually /var/log or /usr/lib)
! STDIR=	${DESTDIR}/var/log
  
  # location of sendmail.hf file (usually /usr/share/misc or /usr/lib)
  HFDIR=	${DESTDIR}/usr/lib
--- 41,47 ----
  BINDIR=	${DESTDIR}/usr/lib
  
  # location of sendmail.st file (usually /var/log or /usr/lib)
! STDIR=	${DESTDIR}/etc
  
  # location of sendmail.hf file (usually /usr/share/misc or /usr/lib)
  HFDIR=	${DESTDIR}/usr/lib
*** src/READ_ME.OLD	Wed Oct 27 08:24:33 1993
--- src/READ_ME	Sun Oct 31 11:33:11 1993
***************
*** 30,36 ****
  # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  # SUCH DAMAGE.
  #
! #	@(#)READ_ME	8.30 (Berkeley) 10/24/93
  #
  
  This directory contains the source files for sendmail.
--- 30,36 ----
  # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  # SUCH DAMAGE.
  #
! #	@(#)READ_ME	8.31 (Berkeley) 10/31/93
  #
  
  This directory contains the source files for sendmail.
***************
*** 265,270 ****
--- 265,276 ----
  	this links in a new version of gethostbyname that does not
  	understand NIS, so you must have all of your hosts in DNS.
  
+ 	Some people have reported problems with the SunOS version of
+ 	-lresolv and/or in.named, and suggest that you get a newer
+ 	version.  The symptoms are delays when you connect to the
+ 	SMTP server on a SunOS machine.  There is a version of BIND
+ 	version 4.9 on gatekeeper.DEC.COM in pub/BSD/bind/4.9.
+ 
  	There is substantial disagreement about whether you can make
  	this work with resolv+, which allows you to specify a search-path
  	of services.  Some people report that it works fine, others
***************
*** 483,486 ****
  
  Eric Allman
  
! (Version 8.30, last update 10/24/93 10:39:02)
--- 489,492 ----
  
  Eric Allman
  
! (Version 8.31, last update 10/31/93 11:32:52)
*** src/alias.c.OLD	Fri Oct 29 07:00:24 1993
--- src/alias.c	Sun Oct 31 11:07:17 1993
***************
*** 36,42 ****
  # include <pwd.h>
  
  #ifndef lint
! static char sccsid[] = "@(#)alias.c	8.17 (Berkeley) 10/15/93";
  #endif /* not lint */
  
  
--- 36,42 ----
  # include <pwd.h>
  
  #ifndef lint
! static char sccsid[] = "@(#)alias.c	8.19 (Berkeley) 10/31/93";
  #endif /* not lint */
  
  
***************
*** 299,305 ****
  	char *ext;
  	int isopen;
  {
! 	int atcnt;
  	time_t mtime;
  	struct stat stb;
  	char buf[MAXNAME];
--- 299,305 ----
  	char *ext;
  	int isopen;
  {
! 	bool attimeout = FALSE;
  	time_t mtime;
  	struct stat stb;
  	char buf[MAXNAME];
***************
*** 308,324 ****
  		printf("aliaswait(%s:%s)\n",
  			map->map_class->map_cname, map->map_file);
  	if (bitset(MF_ALIASWAIT, map->map_mflags))
! 		return;
  	map->map_mflags |= MF_ALIASWAIT;
  
! 	atcnt = SafeAlias * 2;
! 	if (atcnt > 0)
  	{
  		auto int st;
  
! 		while (isopen && atcnt-- >= 0 &&
  		       map->map_class->map_lookup(map, "@", NULL, &st) == NULL)
  		{
  			/*
  			**  Close and re-open the alias database in case
  			**  the one is mv'ed instead of cp'ed in.
--- 308,332 ----
  		printf("aliaswait(%s:%s)\n",
  			map->map_class->map_cname, map->map_file);
  	if (bitset(MF_ALIASWAIT, map->map_mflags))
! 		return isopen;
  	map->map_mflags |= MF_ALIASWAIT;
  
! 	if (SafeAlias > 0)
  	{
  		auto int st;
+ 		time_t toolong = curtime() + SafeAlias;
+ 		unsigned int sleeptime = 2;
  
! 		while (isopen &&
  		       map->map_class->map_lookup(map, "@", NULL, &st) == NULL)
  		{
+ 			if (curtime() > toolong)
+ 			{
+ 				/* we timed out */
+ 				attimeout = TRUE;
+ 				break;
+ 			}
+ 
  			/*
  			**  Close and re-open the alias database in case
  			**  the one is mv'ed instead of cp'ed in.
***************
*** 325,334 ****
  			*/
  
  			if (tTd(27, 2))
! 				printf("aliaswait: sleeping\n");
  
  			map->map_class->map_close(map);
! 			sleep(30);
  			isopen = map->map_class->map_open(map, O_RDONLY);
  		}
  	}
--- 333,346 ----
  			*/
  
  			if (tTd(27, 2))
! 				printf("aliaswait: sleeping for %d seconds\n",
! 					sleeptime);
  
  			map->map_class->map_close(map);
! 			sleep(sleeptime);
! 			sleeptime *= 2;
! 			if (sleeptime > 60)
! 				sleeptime = 60;
  			isopen = map->map_class->map_open(map, O_RDONLY);
  		}
  	}
***************
*** 352,358 ****
  	(void) strcpy(buf, map->map_file);
  	if (ext != NULL)
  		(void) strcat(buf, ext);
! 	if (stat(buf, &stb) < 0 || stb.st_mtime < mtime || atcnt < 0)
  	{
  		/* database is out of date */
  		if (AutoRebuild && stb.st_ino != 0 && stb.st_uid == geteuid())
--- 364,370 ----
  	(void) strcpy(buf, map->map_file);
  	if (ext != NULL)
  		(void) strcat(buf, ext);
! 	if (stat(buf, &stb) < 0 || stb.st_mtime < mtime || attimeout)
  	{
  		/* database is out of date */
  		if (AutoRebuild && stb.st_ino != 0 && stb.st_uid == geteuid())
***************
*** 437,443 ****
  			(void) lockfile(fileno(af), map->map_file, NULL,
  					LOCK_EX);
  		}
! 		(void) fclose(af);
  		errno = 0;
  		return;
  	}
--- 449,455 ----
  			(void) lockfile(fileno(af), map->map_file, NULL,
  					LOCK_EX);
  		}
! 		(void) xfclose(af, "rebuildaliases1", map->map_file);
  		errno = 0;
  		return;
  	}
***************
*** 468,474 ****
  	}
  
  	/* close the file, thus releasing locks */
! 	fclose(af);
  
  	/* add distinguished entries and close the database */
  	if (bitset(MF_OPEN, map->map_mflags))
--- 480,486 ----
  	}
  
  	/* close the file, thus releasing locks */
! 	xfclose(af, "rebuildaliases2", map->map_file);
  
  	/* add distinguished entries and close the database */
  	if (bitset(MF_OPEN, map->map_mflags))
*** src/collect.c.OLD	Wed Oct 27 08:30:13 1993
--- src/collect.c	Fri Oct 29 07:04:42 1993
***************
*** 33,39 ****
   */
  
  #ifndef lint
! static char sccsid[] = "@(#)collect.c	8.5 (Berkeley) 10/15/93";
  #endif /* not lint */
  
  # include <errno.h>
--- 33,39 ----
   */
  
  #ifndef lint
! static char sccsid[] = "@(#)collect.c	8.6 (Berkeley) 10/27/93";
  #endif /* not lint */
  
  # include <errno.h>
***************
*** 283,290 ****
  
  	if (fflush(tf) != 0)
  		tferror(tf, e);
! 	(void) fsync(fileno(tf));
! 	(void) fclose(tf);
  
  	/* An EOF when running SMTP is an error */
  	if (inputerr && OpMode == MD_SMTP)
--- 283,293 ----
  
  	if (fflush(tf) != 0)
  		tferror(tf, e);
! 	if (fsync(fileno(tf)) < 0 || fclose(tf) < 0)
! 	{
! 		syserr("cannot sync message data to disk (%s)", e->e_df);
! 		finis();
! 	}
  
  	/* An EOF when running SMTP is an error */
  	if (inputerr && OpMode == MD_SMTP)
*** src/conf.h.OLD	Thu Oct 28 06:45:24 1993
--- src/conf.h	Fri Oct 29 06:44:30 1993
***************
*** 31,37 ****
   * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   *
!  *	@(#)conf.h	8.42 (Berkeley) 10/21/93
   */
  
  /*
--- 31,37 ----
   * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   *
!  *	@(#)conf.h	8.44 (Berkeley) 10/29/93
   */
  
  /*
***************
*** 382,388 ****
  **	From Karl London <karl@borg.demon.co.uk>.
  */
  
! #ifdef linux
  # define BSD		1	/* pretend to be BSD based today */
  # undef  NEEDVPRINTF	1	/* need a replacement for vprintf(3) */
  # define NEEDGETOPT	1	/* need a replacement for getopt(3) */
--- 382,388 ----
  **	From Karl London <karl@borg.demon.co.uk>.
  */
  
! #ifdef __linux__
  # define BSD		1	/* pretend to be BSD based today */
  # undef  NEEDVPRINTF	1	/* need a replacement for vprintf(3) */
  # define NEEDGETOPT	1	/* need a replacement for getopt(3) */
***************
*** 390,395 ****
--- 390,396 ----
  # ifndef LA_TYPE
  #  define LA_TYPE	LA_FLOAT
  # endif
+ # include <sys/sysmacros.h>
  #endif
  
  
*** src/daemon.c.OLD	Sun Oct 24 13:59:30 1993
--- src/daemon.c	Sun Oct 31 11:30:14 1993
***************
*** 37,45 ****
  
  #ifndef lint
  #ifdef DAEMON
! static char sccsid[] = "@(#)daemon.c	8.19 (Berkeley) 10/23/93 (with daemon mode)";
  #else
! static char sccsid[] = "@(#)daemon.c	8.19 (Berkeley) 10/23/93 (without daemon mode)";
  #endif
  #endif /* not lint */
  
--- 37,45 ----
  
  #ifndef lint
  #ifdef DAEMON
! static char sccsid[] = "@(#)daemon.c	8.21 (Berkeley) 10/31/93 (with daemon mode)";
  #else
! static char sccsid[] = "@(#)daemon.c	8.21 (Berkeley) 10/31/93 (without daemon mode)";
  #endif
  #endif /* not lint */
  
***************
*** 1049,1054 ****
--- 1049,1055 ----
  	char *cp;
  	int i;
  	register STAB *s;
+ 	char *timeoutmsg = "Recipient domain nameserver timed out";
  	char hbuf[MAXNAME];
  	extern struct hostent *gethostbyaddr();
  	extern int h_errno;
***************
*** 1067,1072 ****
--- 1068,1075 ----
  		errno = s->s_namecanon.nc_errno;
  		h_errno = s->s_namecanon.nc_herrno;
  		*statp = s->s_namecanon.nc_stat;
+ 		if (CurEnv->e_message == NULL && *statp == EX_TEMPFAIL)
+ 			CurEnv->e_message = newstr(timeoutmsg);
  		return s->s_namecanon.nc_cname;
  	}
  
***************
*** 1106,1116 ****
  			  case TRY_AGAIN:
  				if (UseNameServer)
  				{
! 					char *msg = "Recipient domain nameserver timed out";
! 
! 					message(msg);
  					if (CurEnv->e_message == NULL)
! 						CurEnv->e_message = newstr(msg);
  				}
  				*statp = EX_TEMPFAIL;
  				break;
--- 1109,1117 ----
  			  case TRY_AGAIN:
  				if (UseNameServer)
  				{
! 					message(timeoutmsg);
  					if (CurEnv->e_message == NULL)
! 						CurEnv->e_message = newstr(timeoutmsg);
  				}
  				*statp = EX_TEMPFAIL;
  				break;
***************
*** 1200,1207 ****
  	{
  #ifdef MAYBENEXTRELEASE		/*** UNTESTED *** UNTESTED *** UNTESTED ***/
  	  case AF_UNIX:
! 	  	if (sap->sun.sun_path[0] != '\0')
! 	  		sprintf(buf, "[UNIX: %.64s]", sap->sun.sun_path);
  	  	else
  	  		sprintf(buf, "[UNIX: localhost]");
  		return buf;
--- 1201,1208 ----
  	{
  #ifdef MAYBENEXTRELEASE		/*** UNTESTED *** UNTESTED *** UNTESTED ***/
  	  case AF_UNIX:
! 	  	if (sap->sunix.sun_path[0] != '\0')
! 	  		sprintf(buf, "[UNIX: %.64s]", sap->sunix.sun_path);
  	  	else
  	  		sprintf(buf, "[UNIX: localhost]");
  		return buf;
*** src/deliver.c.OLD	Fri Oct 29 09:49:43 1993
--- src/deliver.c	Fri Oct 29 19:24:45 1993
***************
*** 33,39 ****
   */
  
  #ifndef lint
! static char sccsid[] = "@(#)deliver.c	8.36 (Berkeley) 10/23/93";
  #endif /* not lint */
  
  #include "sendmail.h"
--- 33,39 ----
   */
  
  #ifndef lint
! static char sccsid[] = "@(#)deliver.c	8.37 (Berkeley) 10/29/93";
  #endif /* not lint */
  
  #include "sendmail.h"
***************
*** 636,642 ****
  			e->e_to = to->q_paddr;
  			message("queued");
  			if (LogLevel > 8)
! 				logdelivery(m, NULL, "queued", e);
  		}
  		e->e_to = NULL;
  		return (0);
--- 636,642 ----
  			e->e_to = to->q_paddr;
  			message("queued");
  			if (LogLevel > 8)
! 				logdelivery(m, NULL, "queued", NULL, e);
  		}
  		e->e_to = NULL;
  		return (0);
***************
*** 780,786 ****
  		{
  			NoReturn = TRUE;
  			usrerr("552 Message is too large; %ld bytes max", m->m_maxsize);
! 			giveresponse(EX_UNAVAILABLE, m, NULL, e);
  			continue;
  		}
  		rcode = checkcompat(to, e);
--- 780,786 ----
  		{
  			NoReturn = TRUE;
  			usrerr("552 Message is too large; %ld bytes max", m->m_maxsize);
! 			giveresponse(EX_UNAVAILABLE, m, NULL, ctladdr, e);
  			continue;
  		}
  		rcode = checkcompat(to, e);
***************
*** 787,793 ****
  		if (rcode != EX_OK)
  		{
  			markfailure(e, to, rcode);
! 			giveresponse(rcode, m, NULL, e);
  			continue;
  		}
  
--- 787,793 ----
  		if (rcode != EX_OK)
  		{
  			markfailure(e, to, rcode);
! 			giveresponse(rcode, m, NULL, ctladdr, e);
  			continue;
  		}
  
***************
*** 831,838 ****
  
  		if (m == FileMailer)
  		{
! 			rcode = mailfile(user, getctladdr(to), e);
! 			giveresponse(rcode, m, NULL, e);
  			if (rcode == EX_OK)
  				to->q_flags |= QSENT;
  			continue;
--- 831,840 ----
  
  		if (m == FileMailer)
  		{
! 			ADDRESS *caddr = getctladdr(to);
! 
! 			rcode = mailfile(user, caddr, e);
! 			giveresponse(rcode, m, NULL, caddr, e);
  			if (rcode == EX_OK)
  				to->q_flags |= QSENT;
  			continue;
***************
*** 1372,1378 ****
  				if ((i = smtprcpt(to, m, mci, e)) != EX_OK)
  				{
  					markfailure(e, to, i);
! 					giveresponse(i, m, mci, e);
  				}
  				else
  				{
--- 1374,1380 ----
  				if ((i = smtprcpt(to, m, mci, e)) != EX_OK)
  				{
  					markfailure(e, to, i);
! 					giveresponse(i, m, mci, ctladdr, e);
  				}
  				else
  				{
***************
*** 1436,1442 ****
  
    give_up:
  	if (tobuf[0] != '\0')
! 		giveresponse(rcode, m, mci, e);
  	for (to = tochain; to != NULL; to = to->q_tchain)
  	{
  		if (rcode != EX_OK)
--- 1438,1444 ----
  
    give_up:
  	if (tobuf[0] != '\0')
! 		giveresponse(rcode, m, mci, ctladdr, e);
  	for (to = tochain; to != NULL; to = to->q_tchain)
  	{
  		if (rcode != EX_OK)
***************
*** 1586,1591 ****
--- 1588,1595 ----
  **		m -- the mailer info for this mailer.
  **		mci -- the mailer connection info -- can be NULL if the
  **			response is given before the connection is made.
+ **		ctladdr -- the controlling address for the recipient
+ **			address(es).
  **		e -- the current envelope.
  **
  **	Returns:
***************
*** 1596,1605 ****
  **		ExitStat may be set.
  */
  
! giveresponse(stat, m, mci, e)
  	int stat;
  	register MAILER *m;
  	register MCI *mci;
  	ENVELOPE *e;
  {
  	register const char *statmsg;
--- 1600,1610 ----
  **		ExitStat may be set.
  */
  
! giveresponse(stat, m, mci, ctladdr, e)
  	int stat;
  	register MAILER *m;
  	register MCI *mci;
+ 	ADDRESS *ctladdr;
  	ENVELOPE *e;
  {
  	register const char *statmsg;
***************
*** 1701,1707 ****
  	*/
  
  	if (LogLevel > ((stat == EX_TEMPFAIL) ? 8 : (stat == EX_OK) ? 7 : 6))
! 		logdelivery(m, mci, &statmsg[4], e);
  
  	if (stat != EX_TEMPFAIL)
  		setstat(stat);
--- 1706,1712 ----
  	*/
  
  	if (LogLevel > ((stat == EX_TEMPFAIL) ? 8 : (stat == EX_OK) ? 7 : 6))
! 		logdelivery(m, mci, &statmsg[4], ctladdr, e);
  
  	if (stat != EX_TEMPFAIL)
  		setstat(stat);
***************
*** 1724,1729 ****
--- 1729,1735 ----
  **		mci -- the mailer connection info -- can be NULL if the
  **			log is occuring when no connection is active.
  **		stat -- the message to print for the status.
+ **		ctladdr -- the controlling address for the to list.
  **		e -- the current envelope.
  **
  **	Returns:
***************
*** 1733,1753 ****
  **		none
  */
  
! logdelivery(m, mci, stat, e)
  	MAILER *m;
  	register MCI *mci;
  	char *stat;
  	register ENVELOPE *e;
  {
  # ifdef LOG
  	char buf[512];
  
! 	(void) sprintf(buf, "delay=%s", pintvl(curtime() - e->e_ctime, TRUE));
  
  	if (m != NULL)
  	{
! 		(void) strcat(buf, ", mailer=");
! 		(void) strcat(buf, m->m_name);
  	}
  
  	if (mci != NULL && mci->mci_host != NULL)
--- 1739,1777 ----
  **		none
  */
  
! logdelivery(m, mci, stat, ctladdr, e)
  	MAILER *m;
  	register MCI *mci;
  	char *stat;
+ 	ADDRESS *ctladdr;
  	register ENVELOPE *e;
  {
  # ifdef LOG
+ 	register char *bp;
  	char buf[512];
  
! 	bp = buf;
! 	if (ctladdr != NULL)
! 	{
! 		strcpy(bp, ", ctladdr=");
! 		strcat(bp, ctladdr->q_paddr);
! 		bp += strlen(bp);
! 		if (bitset(QGOODUID, ctladdr->q_flags))
! 		{
! 			(void) sprintf(bp, " (%d/%d)",
! 					ctladdr->q_uid, ctladdr->q_gid);
! 			bp += strlen(bp);
! 		}
! 	}
  
+ 	(void) sprintf(bp, ", delay=%s", pintvl(curtime() - e->e_ctime, TRUE));
+ 	bp += strlen(bp);
+ 
  	if (m != NULL)
  	{
! 		(void) strcpy(bp, ", mailer=");
! 		(void) strcat(bp, m->m_name);
! 		bp += strlen(bp);
  	}
  
  	if (mci != NULL && mci->mci_host != NULL)
***************
*** 1756,1768 ****
  		extern SOCKADDR CurHostAddr;
  # endif
  
! 		(void) strcat(buf, ", relay=");
! 		(void) strcat(buf, mci->mci_host);
  
  # ifdef DAEMON
! 		(void) strcat(buf, " (");
! 		(void) strcat(buf, anynet_ntoa(&CurHostAddr));
! 		(void) strcat(buf, ")");
  # endif
  	}
  	else
--- 1780,1792 ----
  		extern SOCKADDR CurHostAddr;
  # endif
  
! 		(void) strcpy(bp, ", relay=");
! 		(void) strcat(bp, mci->mci_host);
  
  # ifdef DAEMON
! 		(void) strcat(bp, " (");
! 		(void) strcat(bp, anynet_ntoa(&CurHostAddr));
! 		(void) strcat(bp, ")");
  # endif
  	}
  	else
***************
*** 1771,1782 ****
  
  		if (p != NULL && p[0] != '\0')
  		{
! 			(void) strcat(buf, ", relay=");
! 			(void) strcat(buf, p);
  		}
  	}
  		
! 	syslog(LOG_INFO, "%s: to=%s, %s, stat=%s",
  	       e->e_id, e->e_to, buf, stat);
  # endif /* LOG */
  }
--- 1795,1806 ----
  
  		if (p != NULL && p[0] != '\0')
  		{
! 			(void) strcpy(bp, ", relay=");
! 			(void) strcat(bp, p);
  		}
  	}
  		
! 	syslog(LOG_INFO, "%s: to=%s%s, stat=%s",
  	       e->e_id, e->e_to, buf, stat);
  # endif /* LOG */
  }
*** src/envelope.c.OLD	Sun Oct 24 14:28:51 1993
--- src/envelope.c	Sun Oct 31 10:19:05 1993
***************
*** 33,39 ****
   */
  
  #ifndef lint
! static char sccsid[] = "@(#)envelope.c	8.13 (Berkeley) 10/23/93";
  #endif /* not lint */
  
  #include "sendmail.h"
--- 33,39 ----
   */
  
  #ifndef lint
! static char sccsid[] = "@(#)envelope.c	8.17 (Berkeley) 10/31/93";
  #endif /* not lint */
  
  #include "sendmail.h"
***************
*** 350,357 ****
  initsys(e)
  	register ENVELOPE *e;
  {
! 	static char cbuf[5];			/* holds hop count */
! 	static char pbuf[10];			/* holds pid */
  #ifdef TTYNAME
  	static char ybuf[60];			/* holds tty id */
  	register char *p;
--- 350,357 ----
  initsys(e)
  	register ENVELOPE *e;
  {
! 	char cbuf[5];				/* holds hop count */
! 	char pbuf[10];				/* holds pid */
  #ifdef TTYNAME
  	static char ybuf[60];			/* holds tty id */
  	register char *p;
***************
*** 375,381 ****
  	**	tucked away in the transcript).
  	*/
  
! 	if (OpMode == MD_DAEMON && !bitset(EF_QUEUERUN, e->e_flags) &&
  	    e->e_xfp != NULL)
  		OutChannel = e->e_xfp;
  
--- 375,381 ----
  	**	tucked away in the transcript).
  	*/
  
! 	if (OpMode == MD_DAEMON && bitset(EF_QUEUERUN, e->e_flags) &&
  	    e->e_xfp != NULL)
  		OutChannel = e->e_xfp;
  
***************
*** 385,395 ****
  
  	/* process id */
  	(void) sprintf(pbuf, "%d", getpid());
! 	define('p', pbuf, e);
  
  	/* hop count */
  	(void) sprintf(cbuf, "%d", e->e_hopcount);
! 	define('c', cbuf, e);
  
  	/* time as integer, unix time, arpa time */
  	settime(e);
--- 385,395 ----
  
  	/* process id */
  	(void) sprintf(pbuf, "%d", getpid());
! 	define('p', newstr(pbuf), e);
  
  	/* hop count */
  	(void) sprintf(cbuf, "%d", e->e_hopcount);
! 	define('c', newstr(cbuf), e);
  
  	/* time as integer, unix time, arpa time */
  	settime(e);
***************
*** 428,435 ****
  {
  	register char *p;
  	auto time_t now;
! 	static char tbuf[20];			/* holds "current" time */
! 	static char dbuf[30];			/* holds ctime(tbuf) */
  	register struct tm *tm;
  	extern char *arpadate();
  	extern struct tm *gmtime();
--- 428,435 ----
  {
  	register char *p;
  	auto time_t now;
! 	char tbuf[20];				/* holds "current" time */
! 	char dbuf[30];				/* holds ctime(tbuf) */
  	register struct tm *tm;
  	extern char *arpadate();
  	extern struct tm *gmtime();
***************
*** 438,449 ****
  	tm = gmtime(&now);
  	(void) sprintf(tbuf, "%04d%02d%02d%02d%02d", tm->tm_year + 1900,
  			tm->tm_mon+1, tm->tm_mday, tm->tm_hour, tm->tm_min);
! 	define('t', tbuf, e);
  	(void) strcpy(dbuf, ctime(&now));
  	p = strchr(dbuf, '\n');
  	if (p != NULL)
  		*p = '\0';
! 	define('d', dbuf, e);
  	p = arpadate(dbuf);
  	p = newstr(p);
  	if (macvalue('a', e) == NULL)
--- 438,449 ----
  	tm = gmtime(&now);
  	(void) sprintf(tbuf, "%04d%02d%02d%02d%02d", tm->tm_year + 1900,
  			tm->tm_mon+1, tm->tm_mday, tm->tm_hour, tm->tm_min);
! 	define('t', newstr(tbuf), e);
  	(void) strcpy(dbuf, ctime(&now));
  	p = strchr(dbuf, '\n');
  	if (p != NULL)
  		*p = '\0';
! 	define('d', newstr(dbuf), e);
  	p = arpadate(dbuf);
  	p = newstr(p);
  	if (macvalue('a', e) == NULL)
***************
*** 592,600 ****
  		SuprErrs = TRUE;
  
  	delimchar = internal ? '\0' : ' ';
  	if (from == NULL ||
  	    parseaddr(from, &e->e_from, RF_COPYALL|RF_SENDERADDR,
! 		      delimchar, delimptr, e) == NULL)
  	{
  		/* log garbage addresses for traceback */
  # ifdef LOG
--- 592,605 ----
  		SuprErrs = TRUE;
  
  	delimchar = internal ? '\0' : ' ';
+ 	e->e_from.q_flags = QBADADDR;
  	if (from == NULL ||
  	    parseaddr(from, &e->e_from, RF_COPYALL|RF_SENDERADDR,
! 		      delimchar, delimptr, e) == NULL ||
! 	    bitset(QBADADDR, e->e_from.q_flags) ||
! 	    e->e_from.q_mailer == ProgMailer ||
! 	    e->e_from.q_mailer == FileMailer ||
! 	    e->e_from.q_mailer == InclMailer)
  	{
  		/* log garbage addresses for traceback */
  # ifdef LOG
***************
*** 613,631 ****
  				p = ebuf;
  			}
  			syslog(LOG_NOTICE,
! 				"from=%s unparseable, received from %s",
  				from, p);
  		}
  # endif /* LOG */
  		if (from != NULL)
  			SuprErrs = TRUE;
  		if (from == realname ||
  		    parseaddr(from = newstr(realname), &e->e_from,
  			      RF_COPYALL|RF_SENDERADDR, ' ', NULL, e) == NULL)
  		{
  			SuprErrs = TRUE;
! 			if (parseaddr("postmaster", &e->e_from, RF_COPYALL,
! 				      ' ', NULL, e) == NULL)
  				syserr("553 setsender: can't even parse postmaster!");
  		}
  	}
--- 618,648 ----
  				p = ebuf;
  			}
  			syslog(LOG_NOTICE,
! 				"setsender: %s: invalid or unparseable, received from %s",
  				from, p);
  		}
  # endif /* LOG */
  		if (from != NULL)
+ 		{
+ 			if (!bitset(QBADADDR, e->e_from.q_flags))
+ 			{
+ 				/* it was a bogus mailer in the from addr */
+ 				usrerr("553 Invalid sender address");
+ 			}
  			SuprErrs = TRUE;
+ 		}
  		if (from == realname ||
  		    parseaddr(from = newstr(realname), &e->e_from,
  			      RF_COPYALL|RF_SENDERADDR, ' ', NULL, e) == NULL)
  		{
+ 			char nbuf[100];
+ 
  			SuprErrs = TRUE;
! 			expand("\201n", nbuf, &nbuf[sizeof nbuf], e);
! 			if (parseaddr(from = newstr(nbuf), &e->e_from,
! 				      RF_COPYALL, ' ', NULL, e) == NULL &&
! 			    parseaddr(from = "postmaster", &e->e_from,
! 			    	      RF_COPYALL, ' ', NULL, e) == NULL)
  				syserr("553 setsender: can't even parse postmaster!");
  		}
  	}
*** src/err.c.OLD	Thu Oct 28 18:01:18 1993
--- src/err.c	Fri Oct 29 20:19:28 1993
***************
*** 33,39 ****
   */
  
  #ifndef lint
! static char sccsid[] = "@(#)err.c	8.12 (Berkeley) 10/21/93";
  #endif /* not lint */
  
  # include "sendmail.h"
--- 33,39 ----
   */
  
  #ifndef lint
! static char sccsid[] = "@(#)err.c	8.14 (Berkeley) 10/29/93";
  #endif /* not lint */
  
  # include "sendmail.h"
***************
*** 341,356 ****
  	putoutmsg(msg, HoldErrs);
  
  	/* signal the error */
  	if (msgcode == '6')
  	{
  		/* notify the postmaster */
  		CurEnv->e_flags |= EF_PM_NOTIFY;
  	}
! 	else
  	{
! 		Errors++;
! 		if (msgcode == '5' && bitset(EF_GLOBALERRS, CurEnv->e_flags))
! 			CurEnv->e_flags |= EF_FATALERRS;
  	}
  }
  /*
--- 341,356 ----
  	putoutmsg(msg, HoldErrs);
  
  	/* signal the error */
+ 	Errors++;
  	if (msgcode == '6')
  	{
  		/* notify the postmaster */
  		CurEnv->e_flags |= EF_PM_NOTIFY;
  	}
! 	else if (msgcode == '5' && bitset(EF_GLOBALERRS, CurEnv->e_flags))
  	{
! 		/* mark long-term fatal errors */
! 		CurEnv->e_flags |= EF_FATALERRS;
  	}
  }
  /*
*** src/parseaddr.c.OLD	Wed Oct 27 16:06:40 1993
--- src/parseaddr.c	Sun Oct 31 10:18:01 1993
***************
*** 33,39 ****
   */
  
  #ifndef lint
! static char sccsid[] = "@(#)parseaddr.c	8.14 (Berkeley) 10/22/93";
  #endif /* not lint */
  
  # include "sendmail.h"
--- 33,39 ----
   */
  
  #ifndef lint
! static char sccsid[] = "@(#)parseaddr.c	8.17 (Berkeley) 10/31/93";
  #endif /* not lint */
  
  # include "sendmail.h"
***************
*** 211,225 ****
  	char savedelim;
  
  	if (delimptr != NULL)
  		savedelim = *delimptr;
  #if 0
  	/* for testing.... */
  	if (strcmp(addr, "INvalidADDR") == 0)
  	{
  		usrerr("553 INvalid ADDRess");
! 		if (delimptr != NULL)
! 			*delimptr = savedelim;
! 		return TRUE;
  	}
  #endif
  	for (; *addr != '\0'; addr++)
--- 211,227 ----
  	char savedelim;
  
  	if (delimptr != NULL)
+ 	{
  		savedelim = *delimptr;
+ 		if (savedelim != '\0')
+ 			*delimptr = '\0';
+ 	}
  #if 0
  	/* for testing.... */
  	if (strcmp(addr, "INvalidADDR") == 0)
  	{
  		usrerr("553 INvalid ADDRess");
! 		goto addrfailure;
  	}
  #endif
  	for (; *addr != '\0'; addr++)
***************
*** 227,238 ****
  		if ((*addr & 0340) == 0200)
  			break;
  	}
- 	if (delimptr != NULL)
- 		*delimptr = savedelim;
  	if (*addr == '\0')
  		return FALSE;
  	setstat(EX_USAGE);
  	usrerr("553 Address contained invalid control characters");
  	return TRUE;
  }
  /*
--- 229,245 ----
  		if ((*addr & 0340) == 0200)
  			break;
  	}
  	if (*addr == '\0')
+ 	{
+ 		if (savedelim != '\0' && delimptr != NULL)
+ 			*delimptr = savedelim;
  		return FALSE;
+ 	}
  	setstat(EX_USAGE);
  	usrerr("553 Address contained invalid control characters");
+   addrfailure:
+ 	if (savedelim != '\0' && delimptr != NULL)
+ 		*delimptr = savedelim;
  	return TRUE;
  }
  /*
***************
*** 406,423 ****
  				/* diagnose and patch up bad syntax */
  				if (state == QST)
  				{
! 					usrerr("653 Unbalanced '\"' (fixed)");
  					c = '"';
  				}
  				else if (cmntcnt > 0)
  				{
! 					usrerr("653 Unbalanced '(' (fixed)");
  					c = ')';
  				}
  				else if (anglecnt > 0)
  				{
  					c = '>';
! 					usrerr("653 Unbalanced '<' (fixed)");
  				}
  				else
  					break;
--- 413,430 ----
  				/* diagnose and patch up bad syntax */
  				if (state == QST)
  				{
! 					usrerr("653 Unbalanced '\"'");
  					c = '"';
  				}
  				else if (cmntcnt > 0)
  				{
! 					usrerr("653 Unbalanced '('");
  					c = ')';
  				}
  				else if (anglecnt > 0)
  				{
  					c = '>';
! 					usrerr("653 Unbalanced '<'");
  				}
  				else
  					break;
***************
*** 467,473 ****
  			{
  				if (cmntcnt <= 0)
  				{
! 					usrerr("653 Unbalanced ')' (fixed)");
  					c = NOCHAR;
  				}
  				else
--- 474,480 ----
  			{
  				if (cmntcnt <= 0)
  				{
! 					usrerr("653 Unbalanced ')'");
  					c = NOCHAR;
  				}
  				else
***************
*** 481,487 ****
  			{
  				if (anglecnt <= 0)
  				{
! 					usrerr("653 Unbalanced '>' (fixed)");
  					c = NOCHAR;
  				}
  				else
--- 488,494 ----
  			{
  				if (anglecnt <= 0)
  				{
! 					usrerr("653 Unbalanced '>'");
  					c = NOCHAR;
  				}
  				else
***************
*** 1231,1236 ****
--- 1238,1249 ----
  	static MAILER errormailer;
  	static char *errorargv[] = { "ERROR", NULL };
  	static char buf[MAXNAME];
+ 
+ 	if (tTd(24, 5))
+ 	{
+ 		printf("buildaddr, flags=%o, tv=", flags);
+ 		printav(tv);
+ 	}
  
  	if (a == NULL)
  		a = (ADDRESS *) xalloc(sizeof *a);
*** src/queue.c.OLD	Wed Oct 27 08:30:26 1993
--- src/queue.c	Fri Oct 29 19:24:47 1993
***************
*** 36,44 ****
  
  #ifndef lint
  #ifdef QUEUE
! static char sccsid[] = "@(#)queue.c	8.24 (Berkeley) 10/23/93 (with queueing)";
  #else
! static char sccsid[] = "@(#)queue.c	8.24 (Berkeley) 10/23/93 (without queueing)";
  #endif
  #endif /* not lint */
  
--- 36,44 ----
  
  #ifndef lint
  #ifdef QUEUE
! static char sccsid[] = "@(#)queue.c	8.27 (Berkeley) 10/29/93 (with queueing)";
  #else
! static char sccsid[] = "@(#)queue.c	8.27 (Berkeley) 10/29/93 (without queueing)";
  #endif
  #endif /* not lint */
  
***************
*** 249,255 ****
  				e->e_to = q->q_paddr;
  				message("queued");
  				if (LogLevel > 8)
! 					logdelivery(NULL, NULL, "queued", e);
  				e->e_to = NULL;
  			}
  			if (tTd(40, 1))
--- 249,255 ----
  				e->e_to = q->q_paddr;
  				message("queued");
  				if (LogLevel > 8)
! 					logdelivery(NULL, NULL, "queued", NULL, e);
  				e->e_to = NULL;
  			}
  			if (tTd(40, 1))
***************
*** 332,340 ****
  	**  Clean up.
  	*/
  
! 	fflush(tfp);
! 	fsync(fileno(tfp));
! 	if (ferror(tfp))
  	{
  		if (newid)
  			syserr("!552 Error writing control file %s", tf);
--- 332,338 ----
  	**  Clean up.
  	*/
  
! 	if (fflush(tfp) < 0 || fsync(fileno(tfp)) < 0 || ferror(tfp))
  	{
  		if (newid)
  			syserr("!552 Error writing control file %s", tf);
***************
*** 874,880 ****
  		e->e_flags |= EF_QUEUERUN|EF_GLOBALERRS;
  		e->e_errormode = EM_MAIL;
  		e->e_id = id;
! 		GrabTo = FALSE;
  		if (forkflag)
  		{
  			disconnect(1, e);
--- 872,878 ----
  		e->e_flags |= EF_QUEUERUN|EF_GLOBALERRS;
  		e->e_errormode = EM_MAIL;
  		e->e_id = id;
! 		GrabTo = UseErrorsTo = FALSE;
  		if (forkflag)
  		{
  			disconnect(1, e);
*** src/readcf.c.OLD	Sun Oct 31 10:53:41 1993
--- src/readcf.c	Sun Oct 31 11:29:49 1993
***************
*** 33,39 ****
   */
  
  #ifndef lint
! static char sccsid[] = "@(#)readcf.c	8.13 (Berkeley) 10/15/93";
  #endif /* not lint */
  
  # include "sendmail.h"
--- 33,39 ----
   */
  
  #ifndef lint
! static char sccsid[] = "@(#)readcf.c	8.14 (Berkeley) 10/31/93";
  #endif /* not lint */
  
  # include "sendmail.h"
***************
*** 1093,1101 ****
  
  	  case 'a':		/* look N minutes for "@:@" in alias file */
  		if (val[0] == '\0')
! 			SafeAlias = 5;
  		else
! 			SafeAlias = atoi(val);
  		break;
  
  	  case 'B':		/* substitution for blank character */
--- 1093,1101 ----
  
  	  case 'a':		/* look N minutes for "@:@" in alias file */
  		if (val[0] == '\0')
! 			SafeAlias = 5 * 60;		/* five minutes */
  		else
! 			SafeAlias = convtime(val, 'm');
  		break;
  
  	  case 'B':		/* substitution for blank character */
*** src/recipient.c.OLD	Mon Oct 25 20:15:14 1993
--- src/recipient.c	Fri Oct 29 19:24:46 1993
***************
*** 33,39 ****
   */
  
  #ifndef lint
! static char sccsid[] = "@(#)recipient.c	8.19 (Berkeley) 9/29/93";
  #endif /* not lint */
  
  # include "sendmail.h"
--- 33,39 ----
   */
  
  #ifndef lint
! static char sccsid[] = "@(#)recipient.c	8.21 (Berkeley) 10/29/93";
  #endif /* not lint */
  
  # include "sendmail.h"
***************
*** 222,229 ****
  	stripquotes(buf);
  
  	/* check for direct mailing to restricted mailers */
! 	if (a->q_alias == NULL && m == ProgMailer &&
! 	    !bitset(EF_QUEUERUN, e->e_flags))
  	{
  		a->q_flags |= QBADADDR;
  		usrerr("550 Cannot mail directly to programs");
--- 222,228 ----
  	stripquotes(buf);
  
  	/* check for direct mailing to restricted mailers */
! 	if (a->q_alias == NULL && m == ProgMailer)
  	{
  		a->q_flags |= QBADADDR;
  		usrerr("550 Cannot mail directly to programs");
***************
*** 276,282 ****
  	if (m == InclMailer)
  	{
  		a->q_flags |= QDONTSEND;
! 		if (a->q_alias == NULL && !bitset(EF_QUEUERUN, e->e_flags))
  		{
  			a->q_flags |= QBADADDR;
  			usrerr("550 Cannot mail directly to :include:s");
--- 275,281 ----
  	if (m == InclMailer)
  	{
  		a->q_flags |= QDONTSEND;
! 		if (a->q_alias == NULL)
  		{
  			a->q_flags |= QBADADDR;
  			usrerr("550 Cannot mail directly to :include:s");
***************
*** 313,319 ****
  
  		p = strrchr(buf, '/');
  		/* check if writable or creatable */
! 		if (a->q_alias == NULL && !bitset(EF_QUEUERUN, e->e_flags))
  		{
  			a->q_flags |= QBADADDR;
  			usrerr("550 Cannot mail directly to files");
--- 312,318 ----
  
  		p = strrchr(buf, '/');
  		/* check if writable or creatable */
! 		if (a->q_alias == NULL)
  		{
  			a->q_flags |= QBADADDR;
  			usrerr("550 Cannot mail directly to files");
***************
*** 322,328 ****
  		    (*p = '\0', safefile(buf, RealUid, RealGid, NULL, TRUE, S_IWRITE|S_IEXEC) != 0))
  		{
  			a->q_flags |= QBADADDR;
! 			giveresponse(EX_CANTCREAT, m, NULL, e);
  		}
  	}
  
--- 321,327 ----
  		    (*p = '\0', safefile(buf, RealUid, RealGid, NULL, TRUE, S_IWRITE|S_IEXEC) != 0))
  		{
  			a->q_flags |= QBADADDR;
! 			giveresponse(EX_CANTCREAT, m, NULL, a->q_alias, e);
  		}
  	}
  
***************
*** 400,406 ****
  		if (pw == NULL)
  		{
  			a->q_flags |= QBADADDR;
! 			giveresponse(EX_NOUSER, m, NULL, e);
  		}
  		else
  		{
--- 399,405 ----
  		if (pw == NULL)
  		{
  			a->q_flags |= QBADADDR;
! 			giveresponse(EX_NOUSER, m, NULL, a->q_alias, e);
  		}
  		else
  		{
*** src/savemail.c.OLD	Sun Oct 31 08:19:50 1993
--- src/savemail.c	Sun Oct 31 10:18:15 1993
***************
*** 33,39 ****
   */
  
  #ifndef lint
! static char sccsid[] = "@(#)savemail.c	8.16 (Berkeley) 10/21/93";
  #endif /* not lint */
  
  # include "sendmail.h"
--- 33,39 ----
   */
  
  #ifndef lint
! static char sccsid[] = "@(#)savemail.c	8.17 (Berkeley) 10/31/93";
  #endif /* not lint */
  
  # include "sendmail.h"
***************
*** 267,273 ****
  
  			e->e_flags |= EF_PM_NOTIFY;
  
! 			q = e->e_errorqueue;
  			if (q == NULL)
  			{
  				/* this is an error-error */
--- 267,276 ----
  
  			e->e_flags |= EF_PM_NOTIFY;
  
! 			/* check to see if there are any good addresses */
! 			for (q = e->e_errorqueue; q != NULL; q = q->q_next)
! 				if (!bitset(QBADADDR|QDONTSEND, q->q_flags))
! 					break;
  			if (q == NULL)
  			{
  				/* this is an error-error */
*** src/sendmail.h.OLD	Sun Oct 24 13:49:09 1993
--- src/sendmail.h	Sun Oct 31 11:22:57 1993
***************
*** 31,37 ****
   * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   *
!  *	@(#)sendmail.h	8.24 (Berkeley) 10/15/93
   */
  
  /*
--- 31,37 ----
   * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   *
!  *	@(#)sendmail.h	8.26 (Berkeley) 10/31/93
   */
  
  /*
***************
*** 41,47 ****
  # ifdef _DEFINE
  # define EXTERN
  # ifndef lint
! static char SmailSccsId[] =	"@(#)sendmail.h	8.24		10/15/93";
  # endif
  # else /*  _DEFINE */
  # define EXTERN extern
--- 41,47 ----
  # ifdef _DEFINE
  # define EXTERN
  # ifndef lint
! static char SmailSccsId[] =	"@(#)sendmail.h	8.26		10/31/93";
  # endif
  # else /*  _DEFINE */
  # define EXTERN extern
***************
*** 57,62 ****
--- 57,63 ----
  # include <string.h>
  # include <time.h>
  # include <errno.h>
+ # include <sys/un.h>
  
  # include "conf.h"
  # include "useful.h"
***************
*** 729,734 ****
--- 730,736 ----
  union bigsockaddr
  {
  	struct sockaddr		sa;	/* general version */
+ 	struct sockaddr_un	sunix;	/* UNIX family */
  #ifdef NETINET
  	struct sockaddr_in	sin;	/* INET family */
  #endif
***************
*** 765,771 ****
  EXTERN bool	NoAlias;	/* suppress aliasing */
  EXTERN bool	UseNameServer;	/* use internet domain name server */
  EXTERN bool	SevenBit;	/* force 7-bit data */
! EXTERN int	SafeAlias;	/* minutes to wait until @:@ in alias file */
  EXTERN FILE	*InChannel;	/* input connection */
  EXTERN FILE	*OutChannel;	/* output connection */
  EXTERN uid_t	RealUid;	/* when Daemon, real uid of caller */
--- 767,773 ----
  EXTERN bool	NoAlias;	/* suppress aliasing */
  EXTERN bool	UseNameServer;	/* use internet domain name server */
  EXTERN bool	SevenBit;	/* force 7-bit data */
! EXTERN time_t	SafeAlias;	/* interval to wait until @:@ in alias file */
  EXTERN FILE	*InChannel;	/* input connection */
  EXTERN FILE	*OutChannel;	/* output connection */
  EXTERN uid_t	RealUid;	/* when Daemon, real uid of caller */
*** src/srvrsmtp.c.OLD	Thu Oct 28 17:51:54 1993
--- src/srvrsmtp.c	Thu Oct 28 19:38:21 1993
***************
*** 36,44 ****
  
  #ifndef lint
  #ifdef SMTP
! static char sccsid[] = "@(#)srvrsmtp.c	8.17 (Berkeley) 10/15/93 (with SMTP)";
  #else
! static char sccsid[] = "@(#)srvrsmtp.c	8.17 (Berkeley) 10/15/93 (without SMTP)";
  #endif
  #endif /* not lint */
  
--- 36,44 ----
  
  #ifndef lint
  #ifdef SMTP
! static char sccsid[] = "@(#)srvrsmtp.c	8.18 (Berkeley) 10/28/93 (with SMTP)";
  #else
! static char sccsid[] = "@(#)srvrsmtp.c	8.18 (Berkeley) 10/28/93 (without SMTP)";
  #endif
  #endif /* not lint */
  
***************
*** 531,538 ****
  
  			/* collect the text of the message */
  			SmtpPhase = "collect";
- 			HoldErrs = TRUE;
  			collect(TRUE, doublequeue, e);
  
  			/*
  			**  Arrange to send to everyone.
--- 531,540 ----
  
  			/* collect the text of the message */
  			SmtpPhase = "collect";
  			collect(TRUE, doublequeue, e);
+ 			if (Errors != 0)
+ 				goto abortmessage;
+ 			HoldErrs = TRUE;
  
  			/*
  			**  Arrange to send to everyone.
*** src/util.c.OLD	Sun Oct 31 13:03:51 1993
--- src/util.c	Sun Oct 31 13:05:26 1993
***************
*** 33,39 ****
   */
  
  #ifndef lint
! static char sccsid[] = "@(#)util.c	8.14 (Berkeley) 10/23/93";
  #endif /* not lint */
  
  # include "sendmail.h"
--- 33,39 ----
   */
  
  #ifndef lint
! static char sccsid[] = "@(#)util.c	8.15 (Berkeley) 10/31/93";
  #endif /* not lint */
  
  # include "sendmail.h"
***************
*** 1241,1246 ****
--- 1241,1247 ----
  	p += strlen(p);
  	switch (st.st_mode & S_IFMT)
  	{
+ #ifdef S_IFSOCK
  	  case S_IFSOCK:
  		sprintf(p, "SOCK ");
  		p += strlen(p);
***************
*** 1266,1271 ****
--- 1267,1273 ----
  						   : hp->h_name, ntohs(sin.sin_port));
  		}
  		break;
+ #endif
  
  	  case S_IFCHR:
  		sprintf(p, "CHR: ");
*** src/version.c.OLD	Sun Oct 31 13:09:46 1993
--- src/version.c	Sun Oct 31 11:34:48 1993
***************
*** 33,39 ****
   */
  
  #ifndef lint
! static char sccsid[] = "@(#)version.c	8.6.1.3 (Berkeley) 10/24/93";
  #endif /* not lint */
  
! char	Version[] = "8.6.3";
--- 33,39 ----
   */
  
  #ifndef lint
! static char sccsid[] = "@(#)version.c	8.6.1.4 (Berkeley) 10/31/93";
  #endif /* not lint */
  
! char	Version[] = "8.6.4";
*** cf/README.OLD	Sun Oct 31 07:17:52 1993
--- cf/README	Sun Oct 31 11:35:24 1993
***************
*** 4,10 ****
  
  		Eric Allman <eric@CS.Berkeley.EDU>
  
! 		@(#)README	8.14 (Berkeley) 9/19/93
  
  
  This document describes the sendmail configuration files being used
--- 4,10 ----
  
  		Eric Allman <eric@CS.Berkeley.EDU>
  
! 		@(#)README	8.15 (Berkeley) 10/31/93
  
  
  This document describes the sendmail configuration files being used
***************
*** 1004,1009 ****
--- 1004,1015 ----
     5 *	Local address rewrite (after aliasing)
    1x	mailer rules (sender qualification)
    2x	mailer rules (recipient qualification)
+   3x	mailer rules (sender header qualification)
+   4x	mailer rules (recipient header qualification)
+   5x	mailer subroutines (general)
+   6x	mailer subroutines (general)
+   7x	mailer subroutines (general)
+   8x	reserved
    90	Mailertable host stripping
    96	Bottom half of Ruleset 3 (ruleset 6 in old sendmail)
    97	Hook for recursive ruleset 0 call (ruleset 7 in old sendmail)
*** cf/m4/proto.m4.OLD	Sun Oct 31 07:23:08 1993
--- cf/m4/proto.m4	Sun Oct 31 11:35:58 1993
***************
*** 34,40 ****
  #
  divert(0)
  
! VERSIONID(`@(#)proto.m4	8.19 (Berkeley) 10/15/93')
  
  MAILER(local)dnl
  
--- 34,40 ----
  #
  divert(0)
  
! VERSIONID(`@(#)proto.m4	8.20 (Berkeley) 10/31/93')
  
  MAILER(local)dnl
  
***************
*** 393,401 ****
  ###########################################
  S3
  
! # handle null input and list syntax (translate to <@> special case)
  R$@			$@ <@>
- R$*:;$*			$@ $1 :; <@>
  
  # basic textual canonicalization -- note RFC733 heuristic here
  R$*<$*>$*<$*>$*		$2$3<$4>$5			strip multiple <> <>
--- 393,400 ----
  ###########################################
  S3
  
! # handle null input (translate to <@> special case)
  R$@			$@ <@>
  
  # basic textual canonicalization -- note RFC733 heuristic here
  R$*<$*>$*<$*>$*		$2$3<$4>$5			strip multiple <> <>
***************
*** 402,407 ****
--- 401,409 ----
  R$*<$*<$+>$*>$*		<$3>$5				2-level <> nesting
  R$*<>$*			$@ <@>				MAIL FROM:<> case
  R$*<$+>$*		$2				basic RFC821/822 parsing
+ 
+ # handle list:; syntax as special case
+ R$*:;$*			$@ $1 :; <@>
  
  # make sure <@a,@b,@c:user@d> syntax is easy to parse -- undone later
  R@ $+ , $+		@ $1 : $2			change all "," to ":"
*** cf/m4/version.m4.OLD	Sun Oct 31 12:35:27 1993
--- cf/m4/version.m4	Sun Oct 31 12:35:42 1993
***************
*** 32,39 ****
  # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  # SUCH DAMAGE.
  #
! VERSIONID(`@(#)version.m4	8.6.1.3 (Berkeley) 10/24/93')
  #
  divert(0)
  # Configuration version number
! DZ8.6.3
--- 32,39 ----
  # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  # SUCH DAMAGE.
  #
! VERSIONID(`@(#)version.m4	8.6.1.4 (Berkeley) 10/31/93')
  #
  divert(0)
  # Configuration version number
! DZ8.6.4
*** cf/mailer/local.m4.OLD	Sun Oct 24 14:57:03 1993
--- cf/mailer/local.m4	Sun Oct 24 16:27:18 1993
***************
*** 44,54 ****
  ###   Local and Program Mailer specification   ###
  ##################################################
  
! VERSIONID(`@(#)local.m4	8.5 (Berkeley) 10/23/93')
  
  Mlocal,		P=LOCAL_MAILER_PATH, F=CONCAT(`lsDFM', LOCAL_MAILER_FLAGS), S=10, R=20/40,
  		A=LOCAL_MAILER_ARGS
! Mprog,		P=LOCAL_SHELL_PATH, F=CONCAT(`lsDFM', LOCAL_SHELL_FLAGS), S=10, R=20, D=$z:/,
  		A=LOCAL_SHELL_ARGS
  
  S10
--- 44,54 ----
  ###   Local and Program Mailer specification   ###
  ##################################################
  
! VERSIONID(`@(#)local.m4	8.6 (Berkeley) 10/24/93')
  
  Mlocal,		P=LOCAL_MAILER_PATH, F=CONCAT(`lsDFM', LOCAL_MAILER_FLAGS), S=10, R=20/40,
  		A=LOCAL_MAILER_ARGS
! Mprog,		P=LOCAL_SHELL_PATH, F=CONCAT(`lsDFM', LOCAL_SHELL_FLAGS), S=10, R=20/40, D=$z:/,
  		A=LOCAL_SHELL_ARGS
  
  S10
*** cf/mailer/smtp.m4.OLD	Sun Oct 31 07:19:59 1993
--- cf/mailer/smtp.m4	Sun Oct 31 11:38:08 1993
***************
*** 40,52 ****
  ###   SMTP Mailer specification   ###
  #####################################
  
! VERSIONID(`@(#)smtp.m4	8.6 (Berkeley) 10/23/93')
  
  Msmtp,		P=[IPC], F=CONCAT(mDFMuX, SMTP_MAILER_FLAGS), S=11/31, R=ifdef(`_ALL_MASQUERADE_', `11/31', `21'), E=\r\n,
  		ifdef(`_OLD_SENDMAIL_',, `L=990, ')A=IPC $h
  Mesmtp,		P=[IPC], F=CONCAT(mDFMuXa, SMTP_MAILER_FLAGS), S=11/31, R=ifdef(`_ALL_MASQUERADE_', `11/31', `21'), E=\r\n,
  		ifdef(`_OLD_SENDMAIL_',, `L=990, ')A=IPC $h
! Mrelay,		P=[IPC], F=CONCAT(mDFMuXa, SMTP_MAILER_FLAGS), S=11/31, R=19, E=\r\n,
  		ifdef(`_OLD_SENDMAIL_',, `L=2040, ')A=IPC $h
  
  #
--- 40,52 ----
  ###   SMTP Mailer specification   ###
  #####################################
  
! VERSIONID(`@(#)smtp.m4	8.7 (Berkeley) 10/31/93')
  
  Msmtp,		P=[IPC], F=CONCAT(mDFMuX, SMTP_MAILER_FLAGS), S=11/31, R=ifdef(`_ALL_MASQUERADE_', `11/31', `21'), E=\r\n,
  		ifdef(`_OLD_SENDMAIL_',, `L=990, ')A=IPC $h
  Mesmtp,		P=[IPC], F=CONCAT(mDFMuXa, SMTP_MAILER_FLAGS), S=11/31, R=ifdef(`_ALL_MASQUERADE_', `11/31', `21'), E=\r\n,
  		ifdef(`_OLD_SENDMAIL_',, `L=990, ')A=IPC $h
! Mrelay,		P=[IPC], F=CONCAT(mDFMuXa, SMTP_MAILER_FLAGS), S=11/31, R=51, E=\r\n,
  		ifdef(`_OLD_SENDMAIL_',, `L=2040, ')A=IPC $h
  
  #
***************
*** 53,64 ****
  #  envelope sender and masquerading recipient rewriting
  #
  S11
! R$+			$: $>19 $1			sender/recipient common
  R$* :; <@>		$@ $1 :;			list:; special case
  
  # handle unqualified names
  R$* < @ $* > $*		$@ $1 < @ $2 > $3		already qualified
! R$*			$@ $>29 $1
  
  
  #
--- 53,64 ----
  #  envelope sender and masquerading recipient rewriting
  #
  S11
! R$+			$: $>51 $1			sender/recipient common
  R$* :; <@>		$@ $1 :;			list:; special case
  
  # handle unqualified names
  R$* < @ $* > $*		$@ $1 < @ $2 > $3		already qualified
! R$*			$@ $>61 $1
  
  
  #
***************
*** 67,73 ****
  S21
  
  # do sender/recipient common rewriting
! R$+			$: $>19 $1
  
  # unqualified names (e.g., "eric") are qualified by local host
  R$* < @ $* > $*		$@ $1 < @ $2 > $3		already qualified
--- 67,73 ----
  S21
  
  # do sender/recipient common rewriting
! R$+			$: $>51 $1
  
  # unqualified names (e.g., "eric") are qualified by local host
  R$* < @ $* > $*		$@ $1 < @ $2 > $3		already qualified
***************
*** 78,84 ****
  #  header sender and masquerading recipient rewriting
  #
  S31
! R$+			$: $>19 $1			sender/recipient common
  R$* :; <@>		$@ $1 :;			list:; special case
  
  # do special header rewriting
--- 78,84 ----
  #  header sender and masquerading recipient rewriting
  #
  S31
! R$+			$: $>51 $1			sender/recipient common
  R$* :; <@>		$@ $1 :;			list:; special case
  
  # do special header rewriting
***************
*** 90,102 ****
  
  # handle unqualified names
  R$* < @ $* > $*		$@ $1 < @ $2 > $3		already qualified
! R$*			$@ $>29 $1
  
  
  #
  #  common rewriting for all SMTP addresses
  #
! S19
  
  # pass <route-addr>s through
  R< @ $+ > $*		$@ < @ $1 > $2			resolve <route-addr>
--- 90,102 ----
  
  # handle unqualified names
  R$* < @ $* > $*		$@ $1 < @ $2 > $3		already qualified
! R$*			$@ $>61 $1
  
  
  #
  #  common rewriting for all SMTP addresses
  #
! S51
  
  # pass <route-addr>s through
  R< @ $+ > $*		$@ < @ $1 > $2			resolve <route-addr>
***************
*** 117,123 ****
  #
  #  common sender and masquerading recipient rewriting
  #
! S29
  R$=E			$@ $1 < @ $j>			show exposed names
  R$+			$: $1 < @ $M >			user w/o host
  R$+ <@>			$: $1 < @ $j >			in case $M undefined
--- 117,124 ----
  #
  #  common sender and masquerading recipient rewriting
  #
! S61
! 
  R$=E			$@ $1 < @ $j>			show exposed names
  R$+			$: $1 < @ $M >			user w/o host
  R$+ <@>			$: $1 < @ $j >			in case $M undefined
*** cf/mailer/uucp.m4.OLD	Sun Oct 31 07:04:26 1993
--- cf/mailer/uucp.m4	Sun Oct 31 11:38:35 1993
***************
*** 42,48 ****
  ###   UUCP Mailer specification   ###
  #####################################
  
! VERSIONID(`@(#)uucp.m4	8.5 (Berkeley) 7/28/93')
  
  # old UUCP mailer
  Muucp,		P=UUCP_MAILER_PATH, F=CONCAT(DFMhuU, UUCP_MAILER_FLAGS), S=12, R=22, M=UUCP_MAX_SIZE,
--- 42,48 ----
  ###   UUCP Mailer specification   ###
  #####################################
  
! VERSIONID(`@(#)uucp.m4	8.6 (Berkeley) 10/31/93')
  
  # old UUCP mailer
  Muucp,		P=UUCP_MAILER_PATH, F=CONCAT(DFMhuU, UUCP_MAILER_FLAGS), S=12, R=22, M=UUCP_MAX_SIZE,
***************
*** 54,64 ****
  
  ifdef(`_MAILER_smtp_',
  `# domain-ized UUCP mailer
! Muucp-dom,	P=UUCP_MAILER_PATH, F=CONCAT(mDFMhu, UUCP_MAILER_FLAGS), S=11, R=21, M=UUCP_MAX_SIZE,
  		A=UUCP_MAILER_ARGS')
  
  
! # sender rewriting
  S12
  
  # handle error address as a special case
--- 54,66 ----
  
  ifdef(`_MAILER_smtp_',
  `# domain-ized UUCP mailer
! Muucp-dom,	P=UUCP_MAILER_PATH, F=CONCAT(mDFMhu, UUCP_MAILER_FLAGS), S=52/31, R=ifdef(`_ALL_MASQUERADE_', `11/31', `21'), M=UUCP_MAX_SIZE,
  		A=UUCP_MAILER_ARGS')
  
  
! #
! #  envelope and header sender rewriting
! #
  S12
  
  # handle error address as a special case
***************
*** 73,79 ****
  R$* < @ $+ >			$2 ! $1			convert to UUCP format
  R$+				$: $U ! $1		prepend our name
  
! # recipient rewriting
  S22
  
  # don't touch list:; syntax
--- 75,83 ----
  R$* < @ $+ >			$2 ! $1			convert to UUCP format
  R$+				$: $U ! $1		prepend our name
  
! #
! #  envelope and header recipient rewriting
! #
  S22
  
  # don't touch list:; syntax
***************
*** 83,88 ****
--- 87,105 ----
  R$* < @ $j >			$1			strip local name
  R$* < @ $- . UUCP >		$2 ! $1			convert to UUCP format
  R$* < @ $+ >			$2 ! $1			convert to UUCP format
+ 
+ 
+ #
+ #  envelope sender rewriting for uucp-dom mailer
+ #
+ S52
+ 
+ # handle error address as a special case
+ R<@>				$n			errors to mailer-daemon
+ 
+ # pass everything to standard SMTP mailer rewriting
+ R$*				$@ $>11 $1
+ 
  
  PUSHDIVERT(4)
  # resolve locally connected UUCP links
