-----BEGIN PGP SIGNED MESSAGE-----

diff -c -r sendmail-8.8.2/RELEASE_NOTES sendmail-8.8.3/RELEASE_NOTES
*** sendmail-8.8.2/RELEASE_NOTES	Fri Oct 18 08:32:05 1996
- --- sendmail-8.8.3/RELEASE_NOTES	Sat Nov 16 18:35:59 1996
***************
*** 1,12 ****
  			SENDMAIL RELEASE NOTES
! 	     @(#)RELEASE_NOTES	8.8.2.1 (Berkeley) 10/18/96
  
  
  This listing shows the version of the sendmail binary, the version
  of the sendmail configuration files, the date of release, and a
  summary of the changes in that release.
  
! 8.8.2/8.8.2	96/11/18
  	SECURITY: fix a botch in the 7-bit MIME patch; the previous patch
  		changed the code but didn't fix the problem.
  	PORTABILITY FIXES:
- --- 1,125 ----
  			SENDMAIL RELEASE NOTES
! 	     @(#)RELEASE_NOTES	8.8.3.2 (Berkeley) 11/16/96
  
  
  This listing shows the version of the sendmail binary, the version
  of the sendmail configuration files, the date of release, and a
  summary of the changes in that release.
  
! 8.8.3/8.8.3	96/11/17
! 	SECURITY: it was possible to get a root shell by lying to sendmail
! 		about argv[0] and then sending it a signal.  Problem noted
! 		by Leshka Zakharoff <leshka@leshka.chuvashia.su> on the
! 		best-of-security list.
! 	Log sendmail binary version number in "Warning: .cf version level
! 		(%d) exceeds program functionality (%d) message" -- this
! 		should make it clearer to people that they are running
! 		the wrong binary.
! 	Fix a problem that occurs when you open an SMTP connection and then
! 		do one or more ETRN commands followed by a MAIL command; at
! 		the end of the DATA phase sendmail would incorrectly report
! 		"451 SMTP-MAIL: lost child: No child processes".  Problem
! 		noted by Eric Bishop of Virginia Tech.
! 	When doing text-based host canonification (typically /etc/hosts
! 		lookup), a null host name would match any /etc/hosts entry
! 		with space at the end of the line.  Problem noted by Steve
! 		Hubert of the University of Washington, Seattle.
! 	7 to 8 bit BASE64 MIME conversions could duplicate bits of text.
! 		Problem reported by Tom Smith of Digital Equipment Corp.
! 	Increase the size of the DNS answer buffer -- the standard UDP packet
! 		size PACKETSZ (512) is not sufficient for some nameserver
! 		answers containing very many resource records.  The resolver
! 		may also switch to TCP and retry if it detects UDP packet
! 		overflow.  Also, allow for the fact that the resolver
! 		routines res_query and res_search return the size of the
! 		*un*truncated answer in case the supplied answer buffer it
! 		not big enough to accommodate the entire answer.  Patch from
! 		Eric Wassenaar.
! 	Improvements to MaxDaemonChildren code.  If you think you have too
! 		many children, probe the ones you have to verify that they
! 		are still around.  Suggested by Jared Mauch of CICnet, Inc.
! 		Also, do this probe before growing the vector of children
! 		pids; this previously caused the vector to grow indefinitely
! 		due to a race condition.  Problem reported by Kyle Jones of
! 		UUNET.
! 	On some architectures, <db.h> (from the Berkeley DB library) defines
! 		O_EXLOCK to zero; this fools the map compilation code into
! 		thinking that it can avoid race conditions by locking on open.
! 		Change it to check for O_EXLOCK non-zero.  Problem noted by
! 		Leif Erlingsson of Data Lege.
! 	Always call res_init() on startup (if compiled in, of course) to
! 		allow the sendmail.cf file to tweak resolver flags; without
! 		it, flag tweaks in ResolverOptions are ignored.  Patch from
! 		Andrew Sun of Merrill Lynch.
! 	Improvements to host status printing code.  Suggested by Steve Hubert
! 		of the University of Washington, Seattle.
! 	Change MinQueueAge option processing to do the check for the job age
! 		when reading the queue file, rather than at the end; this
! 		avoids parsing the addresses, which can do DNS lookups.
! 		Problem noted by John Beck of InReference, Inc.
! 	When MIME was being 7->8 bit decoded, "From " lines weren't being
! 		properly escaped.  Problem noted by Peter Nilsson of the
! 		University of Linkoping.
! 	In some cases, sendmail would retain root permissions during queue
! 		runs even if RunAsUser was set.  Problem noted by Mark
! 		Thomas of Mark G. Thomas Consulting.
! 	If the F=l flag was set on an SMTP mailer to indicate that it is
! 		actually local delivery, and NOTIFY=SUCCESS is specified in
! 		the envelope, and the receiving SMTP server speaks DSN, then
! 		the DSN would be both generated locally and propogated to the
! 		other end.
! 	The U= mailer field didn't correctly extract the group id if the
! 		user id was numeric.  Problem noted by Kenneth Herron of
! 		MCI Telecommunications Communications.
! 	If a message exceeded the fixed maximum size on input, the body of
! 		the message was included in the bounce.  Note that this did
! 		not occur if it exceeded the maximum _output_ size.  Problem
! 		reported by Kyle Jones of UUNET.
! 	PORTABILITY FIXES:
! 		AIX4: 4.1 does't have a working setreuid(2); change the
! 			AIX4 defines to use seteuid(2) instead, which
! 			works on 4.1 as well as 4.2.  Problem noted by
! 			Håkan Lindholm of interAF, Sweden.
! 		AIX4: use tzname[] vector to determine time zone name.
! 			Patch from NAKAMURA Motonori of Kyoto University.
! 		MkLinux: add Makefile.Linux.ppc and OSTYPE(mklinux) support.
! 			Contributed by Paul DeBois <dubois@primate.wisc.edu>.
! 		Solaris: kstat(3k) support for retrieving the load average.
! 			This adds the LA_KSTAT definition for LA_TYPE.
! 			The outline of the implementation was contributed
! 			by Michael Tokarev of Telecom Service, JSC, Moscow.
! 		HP-UX 10.0 gripes about the (perfectly legal!) forward
! 			declaration of struct rusage at the top of conf.h;
! 			change it to only be included if you are using gcc,
! 			which is apparently the only compiler that requires
! 			it in the first place.  Problem noted by Jeff
! 			Earickson of Colby College.
! 		IRIX: don't default to using gcc.  IRIX is a civilized
! 			operating system that comes with a decent compiler
! 			by default.  Problem noted by Barry Bouwsma and
! 			Kari Hurtta.
! 	CONFIG: specify F=9 as default in FEATURE(local_procmail) for
! 		consistency with other local mailers.  Inconsistency
! 		pointed out by Teddy Hogeborn <teddy@fukt.hk-r.se>.
! 	CONFIG: if the "limited best mx" feature is used (to reduce DNS
! 		overhead) as part of the bestmx_is_local feature, the
! 		domain part was dropped from the name.  Patch from Steve
! 		Hubert of the University of Washington, Seattle.
! 	CONFIG: catch addresses of the form "user@.dom.ain"; these could
! 		end up being translated to the null host name, which would
! 		return any entry in /etc/hosts that had a space at the end
! 		of the line.  Problem noted by Steve Hubert of the
! 		University of Washington, Seattle.
! 	CONFIG: add OSTYPE(aix4).  From Michael Sofka of Rensselaer
! 		Polytechnic Institute.
! 	MAKEMAP: tweak hash and btree parameters for better performance.
! 		Patch from Matt Dillon of Best Internet Communications.
! 	NEW FILES:
! 		src/Makefiles/Makefile.Linux.ppc
! 		cf/ostype/aix4.m4
! 		cf/ostype/mklinux.m4
! 
! 8.8.2/8.8.2	96/10/18
  	SECURITY: fix a botch in the 7-bit MIME patch; the previous patch
  		changed the code but didn't fix the problem.
  	PORTABILITY FIXES:
***************
*** 1089,1095 ****
  	Syntax errors such as unbalanced parentheses in the configuration
  		file could be omitted if you had "Oem" prior to the
  		syntax error in the config file.  Change to always print
! 		the error message.  It was especially wierd because it
  		would cause a "warning" message to be sent to the Postmaster
  		for every message sent (but with no transcript).  Problem
  		noted by Gregory Paris of Motorola.
- --- 1202,1208 ----
  	Syntax errors such as unbalanced parentheses in the configuration
  		file could be omitted if you had "Oem" prior to the
  		syntax error in the config file.  Change to always print
! 		the error message.  It was especially weird because it
  		would cause a "warning" message to be sent to the Postmaster
  		for every message sent (but with no transcript).  Problem
  		noted by Gregory Paris of Motorola.
***************
*** 1823,1829 ****
  		only works on adjacent preferences, so an MX list that
  		had A=5, B=10, A=15 would leave both As, but one that had
  		A=5, A=10, B=15 would reduce to A, B.  This is intentional,
! 		just in case there is something wierd I haven't thought of.
  		Suggested by Barry Shein of Software Tool & Die.
  	SECURITY: .forward files cannot be symbolic links.  If they are,
  		a bad guy can read your private files.
- --- 1936,1942 ----
  		only works on adjacent preferences, so an MX list that
  		had A=5, B=10, A=15 would leave both As, but one that had
  		A=5, A=10, B=15 would reduce to A, B.  This is intentional,
! 		just in case there is something weird I haven't thought of.
  		Suggested by Barry Shein of Software Tool & Die.
  	SECURITY: .forward files cannot be symbolic links.  If they are,
  		a bad guy can read your private files.
***************
*** 2420,2426 ****
  		fixed by Michael Corrigan and Christophe Wolfhugel.
  
  8.6.7/8.6.6	94/03/14
! 	SECURITY: it was possible to get root access by using wierd
  		values to the -d flag.  Thanks to Alain Durand of
  		INRIA for forwarding me the notice from the bugtraq
  		list.
- --- 2533,2539 ----
  		fixed by Michael Corrigan and Christophe Wolfhugel.
  
  8.6.7/8.6.6	94/03/14
! 	SECURITY: it was possible to get root access by using weird
  		values to the -d flag.  Thanks to Alain Durand of
  		INRIA for forwarding me the notice from the bugtraq
  		list.
***************
*** 2558,2564 ****
  	CNAME loops caused an error message to be generated, but also
  		re-queued the message.  Changed to just re-queue the
  		message (it's really hard to just bounce it because
! 		of the wierd way the name server works in the presence
  		of CNAME loops).  Problem noted by James M.R.Matheson
  		of Cambridge University.
  	Avoid giving ``warning: foo owned process doing -bs'' messages
- --- 2671,2677 ----
  	CNAME loops caused an error message to be generated, but also
  		re-queued the message.  Changed to just re-queue the
  		message (it's really hard to just bounce it because
! 		of the weird way the name server works in the presence
  		of CNAME loops).  Problem noted by James M.R.Matheson
  		of Cambridge University.
  	Avoid giving ``warning: foo owned process doing -bs'' messages
***************
*** 2823,2829 ****
  	Make sure that route-addrs always have <angle brackets> around
  		them in non-SMTP envelopes (SMTP envelopes already do
  		this properly).
! 	Avoid wierd headers on unbalanced punctuation of the form:
  		``Joe User <user)'' -- this caused reference to the
  		null macro.  Fix from Rick McCarty of IO.COM.
  	Fix a problem that caused an alias "user: user@local.host" to
- --- 2936,2942 ----
  	Make sure that route-addrs always have <angle brackets> around
  		them in non-SMTP envelopes (SMTP envelopes already do
  		this properly).
! 	Avoid weird headers on unbalanced punctuation of the form:
  		``Joe User <user)'' -- this caused reference to the
  		null macro.  Fix from Rick McCarty of IO.COM.
  	Fix a problem that caused an alias "user: user@local.host" to
***************
*** 3488,3494 ****
  		the "to" address).  Problem noted by John Myers.
  	Fix dfopen to return NULL if the open failed; I was depending
  		on fdopen(-1) returning NULL, which isn't the case.  This
! 		isn't serious, but does result in wierd error diagnoses.
  		From Michael Corrigan.
  	CONFIG: add UUCP_MAX_SIZE M4 macro to set the maximum size of
  		messages sent through UUCP-family mailers.  Suggested
- --- 3601,3607 ----
  		the "to" address).  Problem noted by John Myers.
  	Fix dfopen to return NULL if the open failed; I was depending
  		on fdopen(-1) returning NULL, which isn't the case.  This
! 		isn't serious, but does result in weird error diagnoses.
  		From Michael Corrigan.
  	CONFIG: add UUCP_MAX_SIZE M4 macro to set the maximum size of
  		messages sent through UUCP-family mailers.  Suggested
***************
*** 3524,3530 ****
  		Changes from Eric Wassenaar.
  	Open /dev/null for the transcript if the create of the xf file
  		failed; this avoids at least one possible null pointer
! 		reference in very wierd cases.  From Eric Wassenaar.
  	Clean up statistics gathering; it was over-reporting because of
  		forks.  From Eric Wassenaar.
  	Fix problem that causes old Return-Path: line to override new
- --- 3637,3643 ----
  		Changes from Eric Wassenaar.
  	Open /dev/null for the transcript if the create of the xf file
  		failed; this avoids at least one possible null pointer
! 		reference in very weird cases.  From Eric Wassenaar.
  	Clean up statistics gathering; it was over-reporting because of
  		forks.  From Eric Wassenaar.
  	Fix problem that causes old Return-Path: line to override new
***************
*** 3775,3781 ****
  	PRALIASES: support for printing NEWDB databases.  From
  		Michael J. Corrigan of U.C. San Diego.
  	CONFIG: don't pass pseudo-domains to $[ ... $] (if you have
! 		a wildcard MX it can have wierd results).  From
  		Christophe Wolfhugel.
  	CONFIG: dot terminate relay hostnames in S0.  From Christophe
  		Wolfhugel.
- --- 3888,3894 ----
  	PRALIASES: support for printing NEWDB databases.  From
  		Michael J. Corrigan of U.C. San Diego.
  	CONFIG: don't pass pseudo-domains to $[ ... $] (if you have
! 		a wildcard MX it can have weird results).  From
  		Christophe Wolfhugel.
  	CONFIG: dot terminate relay hostnames in S0.  From Christophe
  		Wolfhugel.
***************
*** 3888,3894 ****
  	Don't try to flock non-regular files when mailing to a file.
  		In particular, this was a problem if you tried to
  		send to /dev/null.
! 	Fix a wierd bug that can cause senders to be queued as
  		recipients if the name server is down when the mail
  		is initially sent.  This hack just ignores sender
  		deletion (essentially, it sets the MeToo flag) if there
- --- 4001,4007 ----
  	Don't try to flock non-regular files when mailing to a file.
  		In particular, this was a problem if you tried to
  		send to /dev/null.
! 	Fix a weird bug that can cause senders to be queued as
  		recipients if the name server is down when the mail
  		is initially sent.  This hack just ignores sender
  		deletion (essentially, it sets the MeToo flag) if there
***************
*** 4222,4228 ****
  		file to have an F line, and the format of the T option
  		to accept take the format "return/warn" (both intervals).
  	Don't force all local names to lower case -- this was left over
! 		from the wierd handling of case mapping on aliases.  It
  		is now driven (as expected) by the "u" mailer flag.
  		Problem noted by P{r Emanuelsson.
  	Fix problem that caused headers on returned email to be trashed;
- --- 4335,4341 ----
  		file to have an F line, and the format of the T option
  		to accept take the format "return/warn" (both intervals).
  	Don't force all local names to lower case -- this was left over
! 		from the weird handling of case mapping on aliases.  It
  		is now driven (as expected) by the "u" mailer flag.
  		Problem noted by P{r Emanuelsson.
  	Fix problem that caused headers on returned email to be trashed;
***************
*** 4325,4331 ****
  		mailer.
  	Additional debug printing in getcanonname (show query type).
  	Don't add the e_fromdomain on sender addresses -- this interacts
! 		wierdly with the owner- code.
  	Improve delivery logging to not log obvious or meaningless stuff.
  	Include numeric IP address in Received: lines per RFC 1123 section
  		5.2.8.
- --- 4438,4444 ----
  		mailer.
  	Additional debug printing in getcanonname (show query type).
  	Don't add the e_fromdomain on sender addresses -- this interacts
! 		weirdly with the owner- code.
  	Improve delivery logging to not log obvious or meaningless stuff.
  	Include numeric IP address in Received: lines per RFC 1123 section
  		5.2.8.
***************
*** 4407,4413 ****
  	Config extensions for Sam Leffler's FlexFAX software.
  
  6.31/6.10	93/02/28
! 	Fix some more bugs in alias owner code -- there were some wierd
  		cases where an error in a non-aliased name would override
  		the return info in an aliased name with an owner.
  	Changes from WIDE Project, forwarded to me by Motonori Nakamura:
- --- 4520,4526 ----
  	Config extensions for Sam Leffler's FlexFAX software.
  
  6.31/6.10	93/02/28
! 	Fix some more bugs in alias owner code -- there were some weird
  		cases where an error in a non-aliased name would override
  		the return info in an aliased name with an owner.
  	Changes from WIDE Project, forwarded to me by Motonori Nakamura:
diff -c -r sendmail-8.8.2/cf/README sendmail-8.8.3/cf/README
*** sendmail-8.8.2/cf/README	Sat Oct 12 09:27:28 1996
- --- sendmail-8.8.3/cf/README	Sat Nov 16 09:51:43 1996
***************
*** 4,10 ****
  
  		Eric Allman <eric@CS.Berkeley.EDU>
  
! 		@(#)README	8.106 (Berkeley) 10/12/96
  
  
  This document describes the sendmail configuration files being used
- --- 4,10 ----
  
  		Eric Allman <eric@CS.Berkeley.EDU>
  
! 		@(#)README	8.108 (Berkeley) 11/16/96
  
  
  This document describes the sendmail configuration files being used
***************
*** 128,134 ****
  	divert(0)
  
  The divert(-1) will delete the crud in the resulting output file.
! The copyright notice can be replace by whatever your lawyers require;
  our lawyers require the one that I've included in my files.  A copyleft
  is a copyright by another name.  The divert(0) restores regular output.
  
- --- 128,134 ----
  	divert(0)
  
  The divert(-1) will delete the crud in the resulting output file.
! The copyright notice can be replaced by whatever your lawyers require;
  our lawyers require the one that I've included in my files.  A copyleft
  is a copyright by another name.  The divert(0) restores regular output.
  
***************
*** 587,594 ****
  
  always_add_domain
  		Include the local host domain even on locally delivered
! 		mail.  Normally it is not added unless it is already
! 		present.
  
  allmasquerade	If masquerading is enabled (using MASQUERADE_AS), this
  		feature will cause recipient addresses to also masquerade
- --- 587,596 ----
  
  always_add_domain
  		Include the local host domain even on locally delivered
! 		mail.  Normally it is not added on unqualified names.
! 		However, if you use a shared message store but do not use
! 		the same user name space everywhere, you may need the host
! 		name on local names.
  
  allmasquerade	If masquerading is enabled (using MASQUERADE_AS), this
  		feature will cause recipient addresses to also masquerade
***************
*** 940,947 ****
  	MASQUERADE_AS(host.domain)
  
  This causes mail being sent to be labeled as coming from the
! indicated domain, rather than $j.  One normally masquerades as one
! of one's own subdomains (for example, it's unlikely that I would
  choose to masquerade as an MIT site).  This behaviour is modified by
  a plethora of FEATUREs; in particular, see masquerade_envelope,
  allmasquerade, limited_masquerade, and masquerade_entire_domain.
- --- 942,949 ----
  	MASQUERADE_AS(host.domain)
  
  This causes mail being sent to be labeled as coming from the
! indicated host.domain, rather than $j.  One normally masquerades as
! one of one's own subdomains (for example, it's unlikely that I would
  choose to masquerade as an MIT site).  This behaviour is modified by
  a plethora of FEATUREs; in particular, see masquerade_envelope,
  allmasquerade, limited_masquerade, and masquerade_entire_domain.
***************
*** 1216,1221 ****
- --- 1218,1228 ----
  	On the server, this will match an alias for "root+client1".
  	If that is not found, the alias "root+*" will be tried,
  	then "root".
+ 
+ LDAP
+ 	For notes on use LDAP in sendmail, see
+ 	http://www-leland.stanford.edu/~bbense/Inst.html
+ 
  
  
  +----------------+
diff -c -r sendmail-8.8.2/cf/feature/bestmx_is_local.m4 sendmail-8.8.3/cf/feature/bestmx_is_local.m4
*** sendmail-8.8.2/cf/feature/bestmx_is_local.m4	Sat May 11 11:59:07 1996
- --- sendmail-8.8.3/cf/feature/bestmx_is_local.m4	Wed Oct 23 08:43:46 1996
***************
*** 34,40 ****
  #
  
  divert(0)
! VERSIONID(`@(#)bestmx_is_local.m4	8.3 (Berkeley) 5/11/96')
  divert(-1)
  
  LOCAL_CONFIG
- --- 34,40 ----
  #
  
  divert(0)
! VERSIONID(`@(#)bestmx_is_local.m4	8.4 (Berkeley) 10/23/96')
  divert(-1)
  
  LOCAL_CONFIG
***************
*** 60,66 ****
  ifelse(_ARG_, `', `', `#')dnl		unlimited bestmx
  R$* < @ $* > $*			$: $1 < @ $2 @@ $(bestmx $2 $) > $3
  ifelse(_ARG_, `', `#', `')dnl		limit bestmx to $=B
! R$* < @ $* $=B > $*		$: $1 < @ $2 @@ $(bestmx $2 $3 $) > $4
  R$* $=O $* < @ $* @@ $=w . > $*	$@ $>97 $1 $2 $3
  R$* < @ $* @@ $=w . > $*	$#local $: $1
  R$* < @ $* @@ $* > $*		$: $1 < @ $2 > $4
- --- 60,66 ----
  ifelse(_ARG_, `', `', `#')dnl		unlimited bestmx
  R$* < @ $* > $*			$: $1 < @ $2 @@ $(bestmx $2 $) > $3
  ifelse(_ARG_, `', `#', `')dnl		limit bestmx to $=B
! R$* < @ $* $=B > $*		$: $1 < @ $2 $3 @@ $(bestmx $2 $3 $) > $4
  R$* $=O $* < @ $* @@ $=w . > $*	$@ $>97 $1 $2 $3
  R$* < @ $* @@ $=w . > $*	$#local $: $1
  R$* < @ $* @@ $* > $*		$: $1 < @ $2 > $4
diff -c -r sendmail-8.8.2/cf/feature/local_procmail.m4 sendmail-8.8.3/cf/feature/local_procmail.m4
*** sendmail-8.8.2/cf/feature/local_procmail.m4	Mon Feb 12 10:38:23 1996
- --- sendmail-8.8.3/cf/feature/local_procmail.m4	Sun Oct 20 07:46:49 1996
***************
*** 34,40 ****
  #
  
  divert(0)
! VERSIONID(`@(#)local_procmail.m4	8.5 (Berkeley) 2/12/96')
  divert(-1)
  
  define(`LOCAL_MAILER_PATH',
- --- 34,40 ----
  #
  
  divert(0)
! VERSIONID(`@(#)local_procmail.m4	8.6 (Berkeley) 10/20/96')
  divert(-1)
  
  define(`LOCAL_MAILER_PATH',
***************
*** 43,47 ****
  			PROCMAIL_MAILER_PATH,
  			`/usr/local/bin/procmail'),
  		_ARG_))
! define(`LOCAL_MAILER_FLAGS', `SPfhn')
  define(`LOCAL_MAILER_ARGS', `procmail -Y -a $h -d $u')
- --- 43,47 ----
  			PROCMAIL_MAILER_PATH,
  			`/usr/local/bin/procmail'),
  		_ARG_))
! define(`LOCAL_MAILER_FLAGS', `SPfhn9')
  define(`LOCAL_MAILER_ARGS', `procmail -Y -a $h -d $u')
diff -c -r sendmail-8.8.2/cf/m4/proto.m4 sendmail-8.8.3/cf/m4/proto.m4
*** sendmail-8.8.2/cf/m4/proto.m4	Sun Oct 13 13:45:36 1996
- --- sendmail-8.8.3/cf/m4/proto.m4	Sat Oct 26 09:12:17 1996
***************
*** 34,40 ****
  #
  divert(0)
  
! VERSIONID(`@(#)proto.m4	8.134 (Berkeley) 10/13/96')
  
  MAILER(local)dnl
  
- --- 34,40 ----
  #
  divert(0)
  
! VERSIONID(`@(#)proto.m4	8.135 (Berkeley) 10/26/96')
  
  MAILER(local)dnl
  
***************
*** 662,668 ****
  R<> $* < @ [ $+ ] > $*	$1 < @ [ $2 ] > $3
  R<> $* <$* : $* > $*	$#error $@ 5.1.1 $: "colon illegal in host name part"
  R<> $*			$1
! R$* < @ . > $*		$#error $@ 5.1.2 $: "invalid host name"
  
  ifdef(`_MAILER_smtp_',
  `# handle numeric address spec
- --- 662,668 ----
  R<> $* < @ [ $+ ] > $*	$1 < @ [ $2 ] > $3
  R<> $* <$* : $* > $*	$#error $@ 5.1.1 $: "colon illegal in host name part"
  R<> $*			$1
! R$* < @ . $* > $*	$#error $@ 5.1.2 $: "invalid host name"
  
  ifdef(`_MAILER_smtp_',
  `# handle numeric address spec
diff -c -r sendmail-8.8.2/cf/m4/version.m4 sendmail-8.8.3/cf/m4/version.m4
*** sendmail-8.8.2/cf/m4/version.m4	Fri Oct 18 08:28:28 1996
- --- sendmail-8.8.3/cf/m4/version.m4	Sat Nov 16 15:01:50 1996
***************
*** 32,39 ****
  # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  # SUCH DAMAGE.
  #
! VERSIONID(`@(#)version.m4	8.8.2.1 (Berkeley) 10/18/96')
  #
  divert(0)
  # Configuration version number
! DZ8.8.2`'ifdef(`confCF_VERSION', `/confCF_VERSION')
- --- 32,39 ----
  # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  # SUCH DAMAGE.
  #
! VERSIONID(`@(#)version.m4	8.8.3.1 (Berkeley) 11/16/96')
  #
  divert(0)
  # Configuration version number
! DZ8.8.3`'ifdef(`confCF_VERSION', `/confCF_VERSION')
Only in sendmail-8.8.3/cf/ostype: aix4.m4
Only in sendmail-8.8.3/cf/ostype: mklinux.m4
diff -c -r sendmail-8.8.2/contrib/mailprio sendmail-8.8.3/contrib/mailprio
*** sendmail-8.8.2/contrib/mailprio	Sat Dec 10 08:20:25 1994
- --- sendmail-8.8.3/contrib/mailprio	Thu Oct 31 09:38:16 1996
***************
*** 1,280 ****
! Message-Id: <199412081919.NAA23234@austin.BSDI.COM>
! To: Eric Allman <eric@cs.berkeley.edu>
! Subject: Re: sorting mailings lists with fastest delivery users first 
! In-reply-to: Your message of Thu, 08 Dec 1994 06:08:33 PST.
! References: <199412081408.GAA06210@mastodon.CS.Berkeley.EDU> 
! From: Tony Sanders <sanders@bsdi.com>
  Organization: Berkeley Software Design, Inc.
! Date: Thu, 08 Dec 1994 13:19:39 -0600
! Sender: sanders@austin.BSDI.COM
  
! Eric Allman writes:
! > Nope, that's a new one, so far as I know.  Any interest in
! > contributing it?  For small lists it seems overkill, but for
! > large lists it could be a major win.
  
! Sure, I will contribute it; after I sent you mail last night I went ahead
! and finished up what I thought needed to be done.  I would like to get
! some feedback from you on a few items, if you have time.
  
! There are two programs, mailprio_mkdb and mailprio (source below).
  
! mailprio_mkdb reads maillog files and creates a DB file of address vs.
! delay.  I'm not too happy with how it does the averages right now but this
! is just a quick hack.  However, it should at least order sites that take
! days vs. those that deliver on the first pass through.  One thing that
! would make this information a lot more accurate is if sendmail could log
! a "transaction delay" (on failures also), as well as total delivery delay.
! Perhaps, as an option, it could maintain the DB file itself?
! 
! mailprio then simply reads a list of addresses from stdin (the mailing
! list), and tries to prioritize them according to the info the database.
! It collects comment lines and other junk at the top of the file; all
! mailprio does is reorder lines, the actual text of the file should
! be unchanged to the extent that you can verify it with:
!     sort sorted_list > checkit; sort mailing-list | diff - checkit
! Users with no delay information are put next.  The prioritized list is last.
! Of course, this function could also be built-into sendmail (eventually).
! 
! Putting "new account" info at the top with the current averaging function
! probably adversly affects the prioritized list (at least in the short
! term), but putting it at the bottom would not really give the new accounts
! a fair chance.  I suspect this isn't that big of a problem.  I'm running
! this here on a list with 461 accounts and about 10 messages per day so
! I'll see how it goes.  I'll keep some stats on delay times and see what
! happens.
! 
! Another thing that would help this situation, is if sendmail had the queue
! ordered by site (but you already know this).  If you ever get to do per
! site queuing you should consider "blocking" a queue for some short period
! of time if a connection fails to that site [sendmail does this inside a
! single process on a per account basis now right?]; this would allow multiple
! sendmails to quickly skip over those sites for people like me that run:
! 
!     for i in 1 2 3 4 5 6 7 8 ; do daemon sendmail -q; done
! 
! to flush a queue that has gotten behind.  You could also do this inside
! sendmail with a parallelism option (when it is time to run the queue, how
! many processes to start).
! 
! #! /bin/sh
! # This is a shell archive.  Remove anything before this line, then unpack
! # it by saving it into a file and typing "sh file".  To overwrite existing
! # files, type "sh file -c".  You can also feed this as standard input via
! # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
! # will see the following message at the end:
! #		"End of shell archive."
! # Contents:  mailprio mailprio_mkdb
! # Wrapped by sanders@austin.BSDI.COM on Fri Dec  9 18:07:02 1994
! PATH=/bin:/usr/bin:/usr/ucb ; export PATH
! if test -f 'mailprio' -a "${1}" != "-c" ; then 
!   echo shar: Will not clobber existing file \"'mailprio'\"
  else
! echo shar: Extracting \"'mailprio'\" \(3093 characters\)
! sed "s/^X//" >'mailprio' <<'END_OF_FILE'
! X#!/usr/bin/perl
! X#
! X# mailprio -- setup mail priorities for a mailing list
! X#
! X# Sort mailing list by mailprio database:
! X#     mailprio < mailing-list > sorted_list
! X# Double check against orig:
! X#     sort sorted_list > checkit; sort mailing-list | diff - checkit
! X# If it checks out, install it.
! X#
! X# TODO:
! X#     option to process mqueue files so we can reorder files in the queue!
! X$usage = "Usage: mailprio [-p priodb]\n";
! X$home = "/home/sanders/lists";
! X$priodb = "$home/mailprio";
  X
! Xif ($main'ARGV[0] =~ /^-/) {
! X	$args = shift;
! X	if ($args =~ m/\?/) { print $usage; exit 0; }
! X	if ($args =~ m/p/) {
! X	    $priodb = shift || die $usage, "-p requires argument\n"; }
! X}
  X
! X# In shell script, it goes something like this:
! X#     old_mailprio > /tmp/a
! X#     fgrep -f lists/inet-access /tmp/a | sed -e 's/^.......//' > /tmp/b
! X#         ; /tmp/b contains list of known users, faster delivery first
! X#     fgrep -v -f /tmp/b lists/inet-access > /tmp/c
! X#         ; put all unknown stuff at the top of new list for now
! X#     echo '# -----' >> /tmp/c
! X#     cat /tmp/b >> /tmp/c
! X
! X# Setup %list and @list
! Xlocal($addr, $canon);
! Xwhile ($addr = <STDIN>) {
! X    chop $addr;
! X    next if $addr =~ /^# ----- /;			# that's our line
! X    push(@list, $addr), next if $addr =~ /^\s*#/;	# save comments
! X    $canon = &canonicalize((&simplify_address($addr))[0]);
! X    unless (defined $canon) {
! X	warn "no address found: $addr\n";
! X	push(@list, $addr);				# save it anyway
! X	next;
  X    }
! X    if (defined $list{$canon}) {
! X	warn "duplicate: ``$addr -> $canon''\n";
! X	push(@list, $addr);				# save it anyway
! X	next;
  X    }
! X    $list{$canon} = $addr;
! X}
  X
! Xlocal(*prio);
! Xdbmopen(%prio, $priodb, 0644) || die "$priodb: $!\n";
! Xforeach $to (keys %list) {
! X    if (defined $prio{$to}) {
! X	# add to list of found users (%userprio) and remove from %list
! X	# so that we know what users were not yet prioritized
! X	$userprio{$to} = $prio{$to};	# priority
! X	$useracct{$to} = $list{$to};	# string
! X	delete $list{$to};
  X    }
! X}
! Xdbmclose(%prio);
  X
! X# Put all the junk we found at the very top
! X# (this might not always be a feature)
! Xprint join("\n", @list), "\n";
! X
! X# unprioritized users go next, slow accounts will get moved down quickly
! Xprint '# ----- unprioritized users', "\n";
! Xforeach $to (keys %list) { print $list{$to}, "\n"; }
! X
! X# finally, our prioritized list of users
! Xprint '# ----- prioritized users', "\n";
! Xforeach $to (sort { $userprio{$a} <=> $userprio{$b}; } keys %userprio) {
! X    die "Opps! Something is seriously wrong with useracct: $to\n"
! X	unless defined $useracct{$to};
! X    print $useracct{$to}, "\n";
! X}
  X
! Xexit(0);
  X
! X# REPL-LIB ---------------------------------------------------------------
  X
! Xsub canonicalize {
  X    local($addr) = @_;
  X    # lowercase, strip leading/trailing whitespace
  X    $addr =~ y/A-Z/a-z/; $addr =~ s/^\s+//; $addr =~ s/\s+$//; $addr;
! X}
  X
! X# @addrs = simplify_address($addr);
! Xsub simplify_address {
  X    local($_) = shift;
! X    1 while s/\([^\(\)]*\)//g; 		# strip comments
! X    1 while s/"[^"]*"//g;		# strip comments
! X    split(/,/);				# split into parts
  X    foreach (@_) {
! X	1 while s/.*<(.*)>.*/\1/;
! X	s/^\s+//;
! X	s/\s+$//;
  X    }
  X    @_;
! X}
! END_OF_FILE
! if test 3093 -ne `wc -c <'mailprio'`; then
!     echo shar: \"'mailprio'\" unpacked with wrong size!
  fi
! chmod +x 'mailprio'
! # end of 'mailprio'
  fi
! if test -f 'mailprio_mkdb' -a "${1}" != "-c" ; then 
!   echo shar: Will not clobber existing file \"'mailprio_mkdb'\"
  else
! echo shar: Extracting \"'mailprio_mkdb'\" \(3504 characters\)
! sed "s/^X//" >'mailprio_mkdb' <<'END_OF_FILE'
! X#!/usr/bin/perl
! X#
! X# mailprio_mkdb -- make mail priority database based on delay times
! X#
! X$usage = "Usage: mailprio_mkdb [-l maillog] [-p priodb]\n";
! X$home = "/home/sanders/lists";
! X$maillog = "/var/log/maillog";
! X$priodb = "$home/mailprio";
  X
! Xif ($main'ARGV[0] =~ /^-/) {
  X	$args = shift;
  X	if ($args =~ m/\?/) { print $usage; exit 0; }
  X	if ($args =~ m/l/) {
  X	    $maillog = shift || die $usage, "-l requires argument\n"; }
  X	if ($args =~ m/p/) {
  X	    $priodb = shift || die $usage, "-p requires argument\n"; }
! X}
  X
! Xlocal(*prio);
! X# We'll merge with existing information if it's already there.
! Xdbmopen(%prio, $priodb, 0644) || die "$priodb: $!\n";
! X&getlog_stats($maillog, *prio);
! X# foreach $addr (sort { $prio{$a} <=> $prio{$b}; } keys %prio) {
! X#     printf("%06d %s\n", $prio{$addr}, $addr); }
! Xdbmclose(%prio);
! Xexit(0);
  X
! Xsub getlog_stats {
  X    local($maillog, *stats) = @_;
  X    local($to, $delay);
  X    local($h, $m, $s);
  X    open(MAILLOG, "< $maillog") || die "$maillog: $!\n";
  X    while (<MAILLOG>) {
! X	($delay) = (m/, delay=([^,]*), /);
! X	$delay || next;
! X	($h, $m, $s) = split(/:/, $delay);
! X	$delay = ($h * 60 * 60) + ($m * 60) + $s;
! X
! X	# deleting everything after ", " seems safe enough, though
! X	# it is possible that it was inside "..."'s and that we will
! X	# miss some addresses because of it.  However, I'm not willing
! X	# to do full parsing just for that case.  If this bothers you
! X	# you could do something like: s/, (delay|ctladdr)=.*//;
! X	# but you have to make sure you catch all the possible names.
! X	$to = $_; $to =~ s/^.* to=//; $to =~ s/, .*//;
  X	foreach $addr (&simplify_address($to)) {
  X	    next unless $addr;
  X	    $addr = &canonicalize($addr);
- - X	    # print $delay, " ", $addr, "\n";
  X	    $stats{$addr} = $delay unless defined $stats{$addr};	# init
! X
! X	    # This average function moves the value around quite rapidly
! X	    # which may or may not be a feature.
! X	    #
! X	    # This has at least one odd behavior because we currently only
! X	    # use the delay information from maillog which is only logged
! X	    # on actual delivery.  This works backwards from what we really
! X	    # want to happen when a fast host goes down for a while and then
! X	    # comes back up.
! X	    #
! X	    # I spoke with Eric and he suggested adding an xdelay statistic
! X	    # for a per transaction delay which would help that situation
! X	    # a lot.  What I believe you want in that cases something like:
! X	    #   delay fast, xdelay fast: smokin', these hosts go first
! X	    #   delay slow, xdelay fast: put host high on the list (back up?)
! X	    #   delay fast, xdelay slow: host is down/having problems/slow
! X	    #   delay slow, xdelay slow: poorly connected sites, very last
! X	    # Of course, you have to reorder the distribution list fairly
! X	    # often for that to help.  Come to think of it, you should
! X	    # also reorder /var/spool/mqueue files also (if they aren't
! X	    # locked of course).  Hmmm....
  X	    $stats{$addr} = int(($stats{$addr} + $delay) / 2);
  X	}
  X    }
  X    close(MAILLOG);
! X}
  X
! X# REPL-LIB ---------------------------------------------------------------
  X
! Xsub canonicalize {
  X    local($addr) = @_;
  X    # lowercase, strip leading/trailing whitespace
  X    $addr =~ y/A-Z/a-z/; $addr =~ s/^\s+//; $addr =~ s/\s+$//; $addr;
! X}
  X
! X# @addrs = simplify_address($addr);
! Xsub simplify_address {
  X    local($_) = shift;
  X    1 while s/\([^\(\)]*\)//g; 		# strip comments
  X    1 while s/"[^"]*"//g;		# strip comments
- --- 1,540 ----
! Received: from austin.bsdi.com (root{9l9gVDC7v8t3dlv0OtXTlby6X1zBWd56}@austin.BSDI.COM [205.230.224.49]) by knecht.Sendmail.ORG (8.8.2/8.8.2) with ESMTP id JAA05023 for <eric@sendmail.org>; Thu, 31 Oct 1996 09:29:47 -0800 (PST)
! Received: from austin.bsdi.com (localhost [127.0.0.1]) by austin.bsdi.com (8.7.4/8.7.3) with ESMTP id KAA19250; Thu, 31 Oct 1996 10:28:18 -0700 (MST)
! Message-Id: <199610311728.KAA19250@austin.bsdi.com>
! To: Eric Allman <eric@sendmail.org>
! cc: marc@xfree86.org
! Subject: Updated mailprio_0_93.shar
! From: Tony Sanders <sanders@earth.com>
  Organization: Berkeley Software Design, Inc.
! Date: Thu, 31 Oct 1996 10:28:14 -0700
! Sender: sanders@austin.bsdi.com
  
! Eric, please update contrib/mailprio in the sendmail distribution
! to this version at your convenience.  Thanks.
  
! I've also made this available in:
! 	ftp://ftp.earth.com/pub/postmaster/
  
! mailprio_0_93.shar follows...
  
! #!/bin/sh
! # This is a shell archive (produced by GNU sharutils 4.1).
! # To extract the files from this archive, save it to some FILE, remove
! # everything before the `!/bin/sh' line above, then type `sh FILE'.
! #
! # Made on 1996-10-31 10:07 MST by <sanders@earth.com>.
! #
! # Existing files will *not* be overwritten unless `-c' is specified.
! #
! # This shar contains:
! # length mode       name
! # ------ ---------- ------------------------------------------
! #   8260 -rwxr-xr-x mailprio
! #   3402 -rw-r--r-- mailprio.README
! #   4182 -rwxr-xr-x mailprio_mkdb
! #
! touch -am 1231235999 $$.touch >/dev/null 2>&1
! if test ! -f 1231235999 && test -f $$.touch; then
!   shar_touch=touch
! else
!   shar_touch=:
!   echo
!   echo 'WARNING: not restoring timestamps.  Consider getting and'
!   echo "installing GNU \`touch', distributed in GNU File Utilities..."
!   echo
! fi
! rm -f 1231235999 $$.touch
! #
! # ============= mailprio ==============
! if test -f 'mailprio' && test X"$1" != X"-c"; then
!   echo 'x - skipping mailprio (file already exists)'
  else
!   echo 'x - extracting mailprio (text)'
!   sed 's/^X//' << 'SHAR_EOF' > 'mailprio' &&
! #!/usr/bin/perl
! #
! # mailprio,v 1.4 1996/10/31 17:03:52 sanders Exp
! # Version 0.93 -- Thu Oct 31 09:42:25 MST 1996
! #
! # mailprio -- setup mail priorities for a mailing list
! #
! # Copyright 1994, 1996, Tony Sanders <sanders@earth.com>
! # Rights are hereby granted to download, use, modify, sell, copy, and
! # redistribute this software so long as the original copyright notice
! # and this list of conditions remain intact and modified versions are
! # noted as such.
! #
! # I would also very much appreciate it if you could send me a copy of
! # any changes you make so I can possibly integrate them into my version.
! #
! # Options:
! #     -p priority_database      -- Specify database to use if not default
! #     -q                        -- Process sendmail V8.8.X queue format files
! #
! # Sort mailing lists or sendmail queue files by mailprio database.
! # Files listed on the command line are locked and then sorted in place, in
! # the absence of any file arguments it will read STDIN and write STDOUT.
! #
! # Examples:
! #     mailprio < mailing-list > sorted_list
! #     mailprio mailing-list1 mailing-list2 mailing-list3 ...
! #     mailprio -q /var/spool/mqueue/qf*
! # To double check results:
! #     sort sorted_list > checkit; sort orig-mailing-list | diff - checkit
! #
! # To get the maximum value from a transaction delay based priority
! # function you need to reorder the distribution list (and the mail
! # queue files for that matter) fairly often; you could even have
! # your mailing list software reorder the list before each outgoing
! # message.
! #
! $usage = "Usage: mailprio [-p priodb] [-q] [mailinglists ...]\n";
! $home = "/home/sanders/lists";
! $priodb = "$home/mailprio";
! $locking = "flock";     # "flock" or "fcntl"
! X
! # In shell, it would go more or less like this:
! #     old_mailprio > /tmp/a
! #     fgrep -f lists/inet-access /tmp/a | sed -e 's/^.......//' > /tmp/b
! #         ; /tmp/b contains list of known users, faster delivery first
! #     fgrep -v -f /tmp/b lists/inet-access > /tmp/c
! #         ; put all unknown stuff at the top of new list for now
! #     echo '# -----' >> /tmp/c
! #     cat /tmp/b >> /tmp/c
! X
! $qflag = 0;
! while ($main'ARGV[0] =~ /^-/) {
! X        $args = shift;
! X        if ($args =~ m/\?/) { print $usage; exit 0; }
! X        if ($args =~ m/q/) { $qflag = 1; }
! X        if ($args =~ m/p/) {
! X            $priodb = shift || die $usage, "-p requires argument\n"; }
! }
! X
! push(@main'ARGV, '-') if ($#ARGV < 0);
! while ($file = shift @ARGV) {
! X    if ($file eq "-") {
! X        $source = "main'STDIN";
! X        $sink = "main'STDOUT";
! X    } else {
! X        $sink = $source = "FH";
! X        open($source, "+< $file") || do { warn "$file: $!\n"; next; };
! X        if (!defined &seize($source, &LOCK_EX | &LOCK_NB)) {
! X            # couldn't get lock, just skip it
! X            close($source);
! X            next;
! X        }
! X    }
  X
! X    local(*list);
! X    &process($source, *list);
  X
! X    # setup to write output
! X    if ($file ne "-") {
! X	# zero the file (FH is hardcoded because truncate requires it, sigh)
! X        seek(FH, 0, 0) || die "$file: seek: $!\n";
! X        truncate(FH, 0) || die "$file: truncate: $!\n";
  X    }
! X
! X    # do the dirty work
! X    &output($sink, *list);
! X
! X    close($sink) || warn "$file: $!\n";         # close clears the lock
! X    close($source);
! }
! X
! sub process {
! X    # Setup %list and @list
! X    local($source, *list) = @_;
! X    local($addr, $canon);
! X    while ($addr = <$source>) {
! X        chop $addr;
! X        next if $addr =~ /^# ----- /;                   # that's our line
! X        push(@list, $addr), next if $addr =~ /^\s*#/;   # save comments
! X	if ($qflag) {
! X	    next if $addr =~ m/^\./;
! X	    push(@list, $addr), next if !($addr =~ s/^(R[^:]*:)//);
! X	    $Rflags = $1;
! X	}
! X        $canon = &canonicalize((&simplify_address($addr))[0]);
! X        unless (defined $canon) {
! X            warn "$file: no address found: $addr\n";
! X            push(@list, ($qflag?$Rflags:'') . $addr);       # save it as is
! X            next;
! X        }
! X        if (defined $list{$canon}) {
! X            warn "$file: duplicate: ``$addr -> $canon''\n";
! X            push(@list, ($qflag?$Rflags:'') . $addr);       # save it as is
! X            next;
! X        }
! X        $list{$canon} = $addr;
  X    }
! }
! X
! sub output {
! X    local($sink, *list) = @_;
  X
! X    local($to, *prio, *userprio, *useracct);
! X    dbmopen(%prio, $priodb, 0644) || die "$priodb: $!\n";
! X    foreach $to (keys %list) {
! X        if (defined $prio{$to}) {
! X            # add to list of found users (%userprio) and remove from %list
! X            # so that we know what users were not yet prioritized
! X            $userprio{$to} = $prio{$to};        # priority
! X            $useracct{$to} = $list{$to};        # string
! X            delete $list{$to};
! X        }
  X    }
! X    dbmclose(%prio);
  X
! X    # Put all the junk we found at the very top
! X    # (this might not always be a feature)
! X    print $sink join("\n", @list), "\n" if int(@list);
! X
! X    # prioritized list of users
! X    if (int(keys %userprio)) {
! X        print $sink '# ----- prioritized users', "\n" unless $qflag;
! X        foreach $to (sort by_userprio keys %userprio) {
! X            die "Opps! Something is seriously wrong with useracct: $to\n"
! X                unless defined $useracct{$to};
! X	    print $sink 'RFD:' if $qflag;
! X            print $sink $useracct{$to}, "\n";
! X        }
! X    }
  X
! X    # unprioritized users go last, fast accounts will get moved up eventually
! X    # XXX: should go before the "really slow" prioritized users?
! X    if (int(keys %list)) {
! X        print $sink '# ----- unprioritized users', "\n" unless $qflag;
! X        foreach $to (keys %list) {
! X            print $sink 'RFD:' if $qflag;
! X            print $sink $list{$to}, "\n";
! X        }
! X    }
  X
! X    print $sink ".\n" if $qflag;
! }
  X
! sub by_userprio {
! X    # sort first by priority, then by key.
! X    $userprio{$a} <=> $userprio{$b} || $a cmp $b;
! }
! X
! # REPL-LIB ---------------------------------------------------------------
! X
! sub canonicalize {
  X    local($addr) = @_;
  X    # lowercase, strip leading/trailing whitespace
  X    $addr =~ y/A-Z/a-z/; $addr =~ s/^\s+//; $addr =~ s/\s+$//; $addr;
! }
  X
! # @addrs = simplify_address($addr);
! sub simplify_address {
  X    local($_) = shift;
! X    1 while s/\([^\(\)]*\)//g;          # strip comments
! X    1 while s/"[^"]*"//g;               # strip comments
! X    split(/,/);                         # split into parts
  X    foreach (@_) {
! X        1 while s/.*<(.*)>.*/\1/;
! X        s/^\s+//;
! X        s/\s+$//;
  X    }
  X    @_;
! }
! X
! ### ---- ###
! #
! # Error codes
! #
! do 'errno.ph';
! eval 'sub ENOENT {2;}'          unless defined &ENOENT;
! eval 'sub EINTR {4;}'           unless defined &EINTR;
! eval 'sub EINVAL {22;}'         unless defined &EINVAL;
! X
! #
! # File locking
! #
! do 'sys/unistd.ph';
! eval 'sub SEEK_SET {0;}'        unless defined &SEEK_SET;
! X
! do 'sys/file.ph';
! eval 'sub LOCK_SH {0x01;}'      unless defined &LOCK_SH;
! eval 'sub LOCK_EX {0x02;}'      unless defined &LOCK_EX;
! eval 'sub LOCK_NB {0x04;}'      unless defined &LOCK_NB;
! eval 'sub LOCK_UN {0x08;}'      unless defined &LOCK_UN;
! X
! do 'fcntl.ph';
! eval 'sub F_GETFD {1;}'         unless defined &F_GETFD;
! eval 'sub F_SETFD {2;}'         unless defined &F_SETFD;
! eval 'sub F_GETFL {3;}'         unless defined &F_GETFL;
! eval 'sub F_SETFL {4;}'         unless defined &F_SETFL;
! eval 'sub O_NONBLOCK {0x0004;}' unless defined &O_NONBLOCK;
! eval 'sub F_SETLK {8;}'         unless defined &F_SETLK;        # nonblocking
! eval 'sub F_SETLKW {9;}'        unless defined &F_SETLKW;       # lockwait
! eval 'sub F_RDLCK {1;}'         unless defined &F_RDLCK;
! eval 'sub F_UNLCK {2;}'         unless defined &F_UNLCK;
! eval 'sub F_WRLCK {3;}'         unless defined &F_WRLCK;
! $s_flock = "sslll";             # struct flock {type, whence, start, len, pid}
! X
! # return undef on failure
! sub seize {
! X    local ($FH, $lock) = @_;
! X    local ($ret);
! X    if ($locking eq "flock") {
! X        $ret = flock($FH, $lock);
! X	return ($ret == 0 ? undef : 1);
! X    } else {
! X        local ($flock, $type) = 0;
! X        if ($lock & &LOCK_SH) { $type = &F_RDLCK; }
! X        elsif ($lock & &LOCK_EX) { $type = &F_WRLCK; }
! X        elsif ($lock & &LOCK_UN) { $type = &F_UNLCK; }
! X        else { $! = &EINVAL; return undef; }
! X        $flock = pack($s_flock, $type, &SEEK_SET, 0, 0, 0);
! X        $ret = fcntl($FH, ($lock & &LOCK_NB) ? &F_SETLK : &F_SETLKW, $flock);
! X	return ($ret == -1 ? undef : 1);
! X    }
! }
! SHAR_EOF
!   $shar_touch -am 1031100396 'mailprio' &&
!   chmod 0755 'mailprio' ||
!   echo 'restore of mailprio failed'
!   shar_count="`wc -c < 'mailprio'`"
!   test 8260 -eq "$shar_count" ||
!     echo "mailprio: original size 8260, current size $shar_count"
  fi
! # ============= mailprio.README ==============
! if test -f 'mailprio.README' && test X"$1" != X"-c"; then
!   echo 'x - skipping mailprio.README (file already exists)'
! else
!   echo 'x - extracting mailprio.README (text)'
!   sed 's/^X//' << 'SHAR_EOF' > 'mailprio.README' &&
! mailprio README
! X
! mailprio.README,v 1.2 1996/10/31 17:03:54 sanders Exp
! Version 0.93 -- Thu Oct 31 09:42:25 MST 1996
! X
! Copyright 1994, 1996, Tony Sanders <sanders@earth.com>
! Rights are hereby granted to download, use, modify, sell, copy, and
! redistribute this software so long as the original copyright notice
! and this list of conditions remain intact and modified versions are
! noted as such.
! X
! I would also very much appreciate it if you could send me a copy of
! any changes you make so I can possibly integrate them into my version.
! X
! The current version of this and other related mail tools are available in:
! X	ftp://ftp.earth.com/pub/postmaster/
! X
! Even with the new persistent host status in sendmail V8.8.X this
! function can still reduce the lag time distributing mail to a large
! group of people.  It also makes it a little more likely that everyone
! will get mailing list mail in the order sent which can help reduce
! duplicate postings.  Basically, the goal is to put slow hosts at
! the bottom of the list so that as many fast hosts are delivered
! as quickly as possible.
! X
! CONTENTS
! ========
! X
! X    mailprio.README		-- simple docs
! X    mailprio			-- the address sorter
! X    mailprio_mkdb		-- builds the database for the sorter
! X
! X
! CHANGES
! =======
! X    Version 0.92
! X	Initial public release.
! X
! X    Version 0.93
! X	Updated to make use of the (somewhat) new xdelay statistic.
! X	Changed -q flag to support new sendmail queue file format (RFD:<addr>).
! X	Fixed argument parsing bug.
! X	Fixed bug with database getting "garbage" in it.
! X
! X
! CONFIGURATION
! =============
! X
! X    You need to edit each script and ensure proper configuration.
! X
! X    In mailprio check:        #!perl path, $home, $priodb, $locking
! X
! X    In mailprio_mkdb check:   #!perl path, $home, $priodb, $maillog
! X
! X
! USAGE: mailprio
! ===============
! X
! X    Usage: mailprio [-p priodb] [-q] [mailinglists ...]
! X	-p priority_database   -- Specify database to use if not default
! X	-q                     -- Process sendmail queue format files
! X				  [USE WITH CAUTION]
! X
! X    Sort mailing lists or sendmail V8 queue files by mailprio database.
! X    Files listed on the command line are locked and then sorted in place, in
! X    the absence of any file arguments it will read STDIN and write STDOUT.
! X
! X    Examples:
! X	mailprio < mailing-list > sorted_list
! X	mailprio mailing-list1 mailing-list2 mailing-list3 ...
! X	mailprio -q /var/spool/mqueue/qf*	[not recommended]
! X    To double check results:
! X	sort sorted_list > checkit; sort orig-mailing-list | diff - checkit
! X
! X    NOTE:
! X	To get the maximum value from a transaction delay based priority
! X	function you need to reorder the distribution list (and the mail
! X	queue files for that matter) fairly often; you could even have
! X	your mailing list software reorder the list before each outgoing
! X	message.
! X
! X
! USAGE: mailprio_mkdb
! ====================
! X
! X    Usage: mailprio_mkdb [-l maillog] [-p priodb]
! X	-l maillog             -- Specify maillog to process if not default
! X	-p priority_database   -- Specify database to use if not default
! X
! X    Builds the mail priority database using information from the maillog.
! X
! X    Run at least nightly before you rotate the maillog.  If you are
! X    going to run mailprio more often than that then you will need to
! X    load the current maillog information before that will do any good
! X    (and to keep from reloading the same information you will need
! X    some kind of incremental maillog information to load from).
! SHAR_EOF
!   $shar_touch -am 1031100396 'mailprio.README' &&
!   chmod 0644 'mailprio.README' ||
!   echo 'restore of mailprio.README failed'
!   shar_count="`wc -c < 'mailprio.README'`"
!   test 3402 -eq "$shar_count" ||
!     echo "mailprio.README: original size 3402, current size $shar_count"
  fi
! # ============= mailprio_mkdb ==============
! if test -f 'mailprio_mkdb' && test X"$1" != X"-c"; then
!   echo 'x - skipping mailprio_mkdb (file already exists)'
  else
!   echo 'x - extracting mailprio_mkdb (text)'
!   sed 's/^X//' << 'SHAR_EOF' > 'mailprio_mkdb' &&
! #!/usr/bin/perl
! #
! # mailprio_mkdb,v 1.5 1996/10/31 17:03:53 sanders Exp
! # Version 0.93 -- Thu Oct 31 09:42:25 MST 1996
! #
! # mailprio_mkdb -- make mail priority database based on delay times
! #
! # Copyright 1994, 1996, Tony Sanders <sanders@earth.com>
! # Rights are hereby granted to download, use, modify, sell, copy, and
! # redistribute this software so long as the original copyright notice 
! # and this list of conditions remain intact and modified versions are
! # noted as such.
! #
! # I would also very much appreciate it if you could send me a copy of
! # any changes you make so I can possibly integrate them into my version.
! #
! # The average function moves the value around quite rapidly (half-steps)
! # which may or may not be a feature.  This version uses the new xdelay
! # statistic (new as of sendmail V8) which is per transaction.  We also
! # weight the result based on the overall delay.
! #
! # Something that might be worth doing for systems that don't support
! # xdelay would be to compute an approximation of the transaction delay
! # by sorting by messages-id and delay then computing the difference
! # between adjacent delay values.
! #
! # To get the maximum value from a transaction delay based priority
! # function you need to reorder the distribution list (and the mail
! # queue files for that matter) fairly often; you could even have
! # your mailing list software reorder the list before each outgoing
! # message.
! X
! $usage = "Usage: mailprio_mkdb [-l maillog] [-p priodb]\n";
! $home = "/home/sanders/lists";
! $maillog = "/var/log/maillog";
! $priodb = "$home/mailprio";
  X
! while ($ARGV[0] =~ /^-/) {
  X	$args = shift;
  X	if ($args =~ m/\?/) { print $usage; exit 0; }
  X	if ($args =~ m/l/) {
  X	    $maillog = shift || die $usage, "-l requires argument\n"; }
  X	if ($args =~ m/p/) {
  X	    $priodb = shift || die $usage, "-p requires argument\n"; }
! }
! X
! $SIG{'PIPE'} = 'handle_pipe';
  X
! # will merge with existing information
! dbmopen(%prio, $priodb, 0644) || die "$priodb: $!\n";
! &getlog_stats($maillog, *prio);
! dbmclose(%prio);
! exit(0);
  X
! sub handle_pipe {
! X    dbmclose(%prio);
! }
! X
! sub getlog_stats {
  X    local($maillog, *stats) = @_;
  X    local($to, $delay);
  X    local($h, $m, $s);
  X    open(MAILLOG, "< $maillog") || die "$maillog: $!\n";
  X    while (<MAILLOG>) {
! X	next unless / to=/ && / stat=/;
! X	next if / stat=queued/;
! X	if (/ stat=sent/i) {
! X	    # read delay and xdelay and convert to seconds
! X	    ($delay) = (m/ delay=([^,]*),/);
! X	    next unless $delay;
! X	    ($h, $m, $s) = split(/:/, $delay);
! X	    $delay = ($h * 60 * 60) + ($m * 60) + $s;
! X
! X	    ($xdelay) = (m/ xdelay=([^,]*),/);
! X	    next unless $xdelay;
! X	    ($h, $m, $s) = split(/:/, $xdelay);
! X	    $xdelay = ($h * 60 * 60) + ($m * 60) + $s;
! X
! X	    # Now weight the delay factor by the transaction delay (xdelay).
! X	    $xdelay /= 300;			# [0 - 1(@5 min)]
! X	    $xdelay += 0.5;			# [0.5 - 1.5]
! X	    $xdelay = 1.5 if $xdelay > 1.5;	# clamp
! X	    $delay *= $xdelay;			# weight delay by xdelay
! X	}
! X	elsif (/, stat=/) {
! X	    # delivery failure of some sort (i.e. bad)
! X	    $delay = 432000;		# force 5 days
! X	}
! X	$delay = 1000000 if $delay > 1000000;
! X
! X	# filter the address(es); isn't perfect but is "good enough"
! X	$to = $_; $to =~ s/^.* to=//;
! X	1 while $to =~ s/\([^\(\)]*\)//g;	# strip comments
! X	1 while $to =~ s/"[^"]*"//g;		# strip comments
! X	$to =~ s/, .*//;			# remove other stat info
  X	foreach $addr (&simplify_address($to)) {
  X	    next unless $addr;
  X	    $addr = &canonicalize($addr);
  X	    $stats{$addr} = $delay unless defined $stats{$addr};	# init
! X	    # pseudo-average in the new delay (half-steps)
! X	    # simple, moving average
  X	    $stats{$addr} = int(($stats{$addr} + $delay) / 2);
  X	}
  X    }
  X    close(MAILLOG);
! }
  X
! # REPL-LIB ---------------------------------------------------------------
  X
! sub canonicalize {
  X    local($addr) = @_;
  X    # lowercase, strip leading/trailing whitespace
  X    $addr =~ y/A-Z/a-z/; $addr =~ s/^\s+//; $addr =~ s/\s+$//; $addr;
! }
  X
! # @addrs = simplify_address($addr);
! sub simplify_address {
  X    local($_) = shift;
  X    1 while s/\([^\(\)]*\)//g; 		# strip comments
  X    1 while s/"[^"]*"//g;		# strip comments
***************
*** 285,297 ****
  X	s/\s+$//;
  X    }
  X    @_;
! X}
! END_OF_FILE
! if test 3504 -ne `wc -c <'mailprio_mkdb'`; then
!     echo shar: \"'mailprio_mkdb'\" unpacked with wrong size!
! fi
! chmod +x 'mailprio_mkdb'
! # end of 'mailprio_mkdb'
  fi
- - echo shar: End of shell archive.
  exit 0
- --- 545,557 ----
  X	s/\s+$//;
  X    }
  X    @_;
! }
! SHAR_EOF
!   $shar_touch -am 1031100396 'mailprio_mkdb' &&
!   chmod 0755 'mailprio_mkdb' ||
!   echo 'restore of mailprio_mkdb failed'
!   shar_count="`wc -c < 'mailprio_mkdb'`"
!   test 4182 -eq "$shar_count" ||
!     echo "mailprio_mkdb: original size 4182, current size $shar_count"
  fi
  exit 0
diff -c -r sendmail-8.8.2/doc/op/op.me sendmail-8.8.3/doc/op/op.me
*** sendmail-8.8.2/doc/op/op.me	Thu Oct 17 18:08:21 1996
- --- sendmail-8.8.3/doc/op/op.me	Sat Nov 16 08:08:23 1996
***************
*** 30,36 ****
  .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  .\" SUCH DAMAGE.
  .\"
! .\"	@(#)op.me	8.97 (Berkeley) 10/17/96
  .\"
  .\" eqn op.me | pic | troff -me
  .eh 'SMM:08-%''Sendmail Installation and Operation Guide'
- --- 30,36 ----
  .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  .\" SUCH DAMAGE.
  .\"
! .\"	@(#)op.me	8.98 (Berkeley) 11/16/96
  .\"
  .\" eqn op.me | pic | troff -me
  .eh 'SMM:08-%''Sendmail Installation and Operation Guide'
***************
*** 68,74 ****
  InReference, Inc.
  eric@Sendmail.ORG
  .sp
! Version 8.97
  .sp
  For Sendmail Version 8.8
  .)l
- --- 68,74 ----
  InReference, Inc.
  eric@Sendmail.ORG
  .sp
! Version 8.98
  .sp
  For Sendmail Version 8.8
  .)l
***************
*** 3561,3566 ****
- --- 3561,3585 ----
  The home directory of the recipient.
  .ip $_
  The validated sender address.
+ .ip ${bodytype}
+ The message body type
+ (7BIT or 8BITMIME),
+ as determined from the envelope.
+ .ip ${client_addr}
+ The IP address of the SMTP client.
+ Defined in the SMTP server only.
+ .ip ${client_name}
+ The host name of the SMTP client.
+ Defined in the SMTP server only.
+ .ip ${client_port}
+ The port number of the SMTP client.
+ Defined in the SMTP server only.
+ .ip ${envid}
+ The envelope id passed to sendmail as part of the envelope.
+ .ip ${opMode}
+ The current operation mode (from the
+ .b \-b
+ flag).
  .pp
  There are three types of dates that can be used.
  The
***************
*** 3758,3767 ****
  it will include the user name on that host.
  .pp
  The
! .b ${client_name}
  and
! .b ${client_addr}
! are set to the name and address of the SMTP client
  who is invoking
  .i sendmail
  as a server.
- --- 3777,3788 ----
  it will include the user name on that host.
  .pp
  The
! .b ${client_name} ,
! .b ${client_addr} ,
  and
! .b ${client_port}
! macros
! are set to the name, address, and port number of the SMTP client
  who is invoking
  .i sendmail
  as a server.
***************
*** 8129,8135 ****
  .\"Eric Allman
  .\"InReference, Inc.
  .\".sp
! .\"Version 8.97
  .\".ce 0
  .bp 2
  .rs
- --- 8150,8156 ----
  .\"Eric Allman
  .\"InReference, Inc.
  .\".sp
! .\"Version 8.98
  .\".ce 0
  .bp 2
  .rs
diff -c -r sendmail-8.8.2/mail.local/mail.local.c sendmail-8.8.3/mail.local/mail.local.c
*** sendmail-8.8.2/mail.local/mail.local.c	Wed Oct  9 13:15:32 1996
- --- sendmail-8.8.3/mail.local/mail.local.c	Wed Nov 13 16:17:43 1996
***************
*** 38,44 ****
  #endif /* not lint */
  
  #ifndef lint
! static char sccsid[] = "@(#)mail.local.c	8.30 (Berkeley) 10/9/96";
  #endif /* not lint */
  
  /*
- --- 38,44 ----
  #endif /* not lint */
  
  #ifndef lint
! static char sccsid[] = "@(#)mail.local.c	8.33 (Berkeley) 11/13/96";
  #endif /* not lint */
  
  /*
diff -c -r sendmail-8.8.2/makemap/makemap.c sendmail-8.8.3/makemap/makemap.c
*** sendmail-8.8.2/makemap/makemap.c	Wed Sep 25 08:38:02 1996
- --- sendmail-8.8.3/makemap/makemap.c	Wed Nov 13 10:04:03 1996
***************
*** 33,39 ****
   */
  
  #ifndef lint
! static char sccsid[] = "@(#)makemap.c	8.17 (Berkeley) 9/25/96";
  #endif /* not lint */
  
  #include <stdio.h>
- --- 33,39 ----
   */
  
  #ifndef lint
! static char sccsid[] = "@(#)makemap.c	8.18 (Berkeley) 11/13/96";
  #endif /* not lint */
  
  #include <stdio.h>
***************
*** 97,102 ****
- --- 97,103 ----
  	int st;
  	int mode;
  	int putflags;
+ 	long dbcachesize = 1024 * 1024;
  	enum type type;
  	int fd;
  	union
***************
*** 112,117 ****
- --- 113,119 ----
  	union dbent key, val;
  #ifdef NEWDB
  	BTREEINFO bti;
+ 	HASHINFO hinfo;
  #endif
  	char ibuf[BUFSIZE];
  	char fbuf[MAXNAME];
***************
*** 122,128 ****
  
  	progname = argv[0];
  
! 	while ((opt = getopt(argc, argv, "Ndforv")) != EOF)
  	{
  		switch (opt)
  		{
- --- 124,135 ----
  
  	progname = argv[0];
  
! #ifdef FFR_CFLAG
! #define OPTIONS		"Nc:dforv"
! #else
! #define OPTIONS		"Ndforv"
! #endif
! 	while ((opt = getopt(argc, argv, OPTIONS)) != EOF)
  	{
  		switch (opt)
  		{
***************
*** 130,135 ****
- --- 137,148 ----
  			inclnull = TRUE;
  			break;
  
+ #ifdef FFR_CFLAG
+ 		  case 'c':
+ 			dbcachesize = atol(optarg);
+ 			break;
+ #endif
+ 
  		  case 'd':
  			allowdups = TRUE;
  			break;
***************
*** 189,195 ****
- --- 202,212 ----
  	switch (type)
  	{
  	  case T_ERR:
+ #ifdef FFR_CFLAG
+ 		fprintf(stderr, "Usage: %s [-N] [-c cachesize] [-d] [-f] [-o] [-r] [-v] type mapname\n", progname);
+ #else
  		fprintf(stderr, "Usage: %s [-N] [-d] [-f] [-o] [-r] [-v] type mapname\n", progname);
+ #endif
  		exit(EX_USAGE);
  
  	  case T_UNKNOWN:
***************
*** 294,300 ****
  
  #ifdef NEWDB
  	  case T_HASH:
! 		dbp.db = dbopen(mapname, mode, 0644, DB_HASH, NULL);
  		if (dbp.db != NULL)
  		{
  # if OLD_NEWDB
- --- 311,321 ----
  
  #ifdef NEWDB
  	  case T_HASH:
! 		/* tweak some parameters for performance */
! 		hinfo.nelem = 4096;
! 		hinfo.cachesize = dbcachesize;
! 
! 		dbp.db = dbopen(mapname, mode, 0644, DB_HASH, &hinfo);
  		if (dbp.db != NULL)
  		{
  # if OLD_NEWDB
***************
*** 306,311 ****
- --- 327,335 ----
  		break;
  
  	  case T_BTREE:
+ 		/* tweak some parameters for performance */
+ 		bti.cachesize = dbcachesize;
+ 
  		dbp.db = dbopen(mapname, mode, 0644, DB_BTREE, &bti);
  		if (dbp.db != NULL)
  		{
diff -c -r sendmail-8.8.2/src/Makefiles/Makefile.IRIX sendmail-8.8.3/src/Makefiles/Makefile.IRIX
*** sendmail-8.8.2/src/Makefiles/Makefile.IRIX	Fri Sep 20 07:35:43 1996
- --- sendmail-8.8.3/src/Makefiles/Makefile.IRIX	Sat Nov 16 09:29:07 1996
***************
*** 7,19 ****
  #
  #  This has been tested on IRIX 4.0.4.
  #
! #	@(#)Makefile.IRIX	8.11 (Berkeley) 9/20/96
  #
  SHELL=	/bin/sh
  
  # use O=-O (usual) or O=-g (debugging)
  O=	-O
- - CC=gcc
  
  # define the database mechanisms available for map & alias lookups:
  #	-DNDBM -- use new DBM
- --- 7,18 ----
  #
  #  This has been tested on IRIX 4.0.4.
  #
! #	@(#)Makefile.IRIX	8.12 (Berkeley) 11/16/96
  #
  SHELL=	/bin/sh
  
  # use O=-O (usual) or O=-g (debugging)
  O=	-O
  
  # define the database mechanisms available for map & alias lookups:
  #	-DNDBM -- use new DBM
diff -c -r sendmail-8.8.2/src/Makefiles/Makefile.IRIX64 sendmail-8.8.3/src/Makefiles/Makefile.IRIX64
*** sendmail-8.8.2/src/Makefiles/Makefile.IRIX64	Fri Sep 20 07:35:44 1996
- --- sendmail-8.8.3/src/Makefiles/Makefile.IRIX64	Sat Nov 16 09:29:07 1996
***************
*** 8,20 ****
  #  This has been tested on IRIX64 6.0.
  #  Changes from Mark R. Levinson <ml@cvdev.rochester.edu>.
  #
! #	@(#)Makefile.IRIX64	8.5 (Berkeley) 9/20/96
  #
  SHELL=	/bin/sh
  
  # use O=-O (usual) or O=-g (debugging)
  O=	-O
- - CC=gcc
  
  # define the database mechanisms available for map & alias lookups:
  #	-DNDBM -- use new DBM
- --- 8,19 ----
  #  This has been tested on IRIX64 6.0.
  #  Changes from Mark R. Levinson <ml@cvdev.rochester.edu>.
  #
! #	@(#)Makefile.IRIX64	8.6 (Berkeley) 11/16/96
  #
  SHELL=	/bin/sh
  
  # use O=-O (usual) or O=-g (debugging)
  O=	-O
  
  # define the database mechanisms available for map & alias lookups:
  #	-DNDBM -- use new DBM
Only in sendmail-8.8.3/src/Makefiles: Makefile.Linux.ppc
diff -c -r sendmail-8.8.2/src/Makefiles/Makefile.NEWS-OS.4.x sendmail-8.8.3/src/Makefiles/Makefile.NEWS-OS.4.x
*** sendmail-8.8.2/src/Makefiles/Makefile.NEWS-OS.4.x	Thu Sep 26 07:16:19 1996
- --- sendmail-8.8.3/src/Makefiles/Makefile.NEWS-OS.4.x	Sat Nov 16 18:16:48 1996
***************
*** 5,18 ****
  #  old make program (I recommend that you get and port the new make if you
  #  are going to be doing any signficant work on sendmail).
  #
! #	@(#)Makefile.NEWS-OS.4.x	8.6 (Berkeley) 9/26/96
  #
  
  # use O=-O (usual) or O=-g (debugging)
  O=	-O
  
! # native compiler requires -Olimit to optimize properly
! CC=	cc -Olimit 1100
  
  # define the database mechanisms available for map & alias lookups:
  #	-DNDBM -- use new DBM
- --- 5,18 ----
  #  old make program (I recommend that you get and port the new make if you
  #  are going to be doing any signficant work on sendmail).
  #
! #	@(#)Makefile.NEWS-OS.4.x	8.7 (Berkeley) 11/16/96
  #
  
  # use O=-O (usual) or O=-g (debugging)
  O=	-O
  
! # native compiler on RISC OS requires -Olimit to optimize properly
! #CC=	cc -Olimit 1100
  
  # define the database mechanisms available for map & alias lookups:
  #	-DNDBM -- use new DBM
diff -c -r sendmail-8.8.2/src/Makefiles/Makefile.SCO sendmail-8.8.3/src/Makefiles/Makefile.SCO
*** sendmail-8.8.2/src/Makefiles/Makefile.SCO	Fri Sep 20 07:35:44 1996
- --- sendmail-8.8.3/src/Makefiles/Makefile.SCO	Sun Nov 10 11:15:56 1996
***************
*** 7,13 ****
  #
  #  This has been tested on SCO.
  #
! #	@(#)Makefile.SCO	8.9 (Berkeley) 9/20/96
  #
  
  # use O=-O (usual) or O=-g (debugging)
- --- 7,13 ----
  #
  #  This has been tested on SCO.
  #
! #	@(#)Makefile.SCO	8.10 (Berkeley) 11/10/96
  #
  
  # use O=-O (usual) or O=-g (debugging)
***************
*** 34,40 ****
  LIBDIRS=
  
  # libraries required on your system
! LIBS=	-lsocket
  
  # location of sendmail binary (usually /usr/sbin or /usr/lib)
  BINDIR=	${DESTDIR}/usr/lib
- --- 34,40 ----
  LIBDIRS=
  
  # libraries required on your system
! LIBS=	-lsocket -lprot_s -lx -lc_s
  
  # location of sendmail binary (usually /usr/sbin or /usr/lib)
  BINDIR=	${DESTDIR}/usr/lib
diff -c -r sendmail-8.8.2/src/Makefiles/Makefile.SCO.4.2 sendmail-8.8.3/src/Makefiles/Makefile.SCO.4.2
*** sendmail-8.8.2/src/Makefiles/Makefile.SCO.4.2	Fri Sep 20 07:35:45 1996
- --- sendmail-8.8.3/src/Makefiles/Makefile.SCO.4.2	Sun Nov 10 11:15:56 1996
***************
*** 7,13 ****
  #
  #  Tested on SCO rel 4.2 by Marian Durkovic <marian@svf.stuba.sk>.
  #
! #	@(#)Makefile.SCO.4.2	8.3 (Berkeley) 9/20/96
  #
  
  # use O=-O (usual) or O=-g (debugging)
- --- 7,13 ----
  #
  #  Tested on SCO rel 4.2 by Marian Durkovic <marian@svf.stuba.sk>.
  #
! #	@(#)Makefile.SCO.4.2	8.4 (Berkeley) 11/10/96
  #
  
  # use O=-O (usual) or O=-g (debugging)
***************
*** 34,40 ****
  LIBDIRS=
  
  # libraries required on your system
! LIBS=	-lsocket -lndbm
  
  # location of sendmail binary (usually /usr/sbin or /usr/lib)
  BINDIR=	${DESTDIR}/usr/lib
- --- 34,40 ----
  LIBDIRS=
  
  # libraries required on your system
! LIBS=	-lsocket -lndbm -lprot_s -lx -lc_s
  
  # location of sendmail binary (usually /usr/sbin or /usr/lib)
  BINDIR=	${DESTDIR}/usr/lib
diff -c -r sendmail-8.8.2/src/Makefiles/Makefile.SCO.5.x sendmail-8.8.3/src/Makefiles/Makefile.SCO.5.x
*** sendmail-8.8.2/src/Makefiles/Makefile.SCO.5.x	Fri Sep 20 07:35:45 1996
- --- sendmail-8.8.3/src/Makefiles/Makefile.SCO.5.x	Sun Nov 10 11:15:56 1996
***************
*** 7,13 ****
  #
  #  Tested on SCO OpenServer 5 by Keith Reynolds <keithr@sco.COM>.
  #
! #	@(#)Makefile.SCO.5.x	8.2 (Berkeley) 9/20/96
  #
  
  # use O=-O (usual) or O=-g (debugging)
- --- 7,13 ----
  #
  #  Tested on SCO OpenServer 5 by Keith Reynolds <keithr@sco.COM>.
  #
! #	@(#)Makefile.SCO.5.x	8.3 (Berkeley) 11/10/96
  #
  
  # use O=-O (usual) or O=-g (debugging)
***************
*** 34,40 ****
  LIBDIRS=
  
  # libraries required on your system
! LIBS=	-lsocket -lndbm
  
  # location of sendmail binary (usually /usr/sbin or /usr/lib)
  BINDIR=	${DESTDIR}/usr/lib
- --- 34,40 ----
  LIBDIRS=
  
  # libraries required on your system
! LIBS=	-lsocket -lndbm -lcurses -lm -lx
  
  # location of sendmail binary (usually /usr/sbin or /usr/lib)
  BINDIR=	${DESTDIR}/usr/lib
diff -c -r sendmail-8.8.2/src/Makefiles/Makefile.UXPDS.V10 sendmail-8.8.3/src/Makefiles/Makefile.UXPDS.V10
*** sendmail-8.8.2/src/Makefiles/Makefile.UXPDS.V10	Fri Sep 20 07:35:46 1996
- --- sendmail-8.8.3/src/Makefiles/Makefile.UXPDS.V10	Sat Nov 16 09:28:17 1996
***************
*** 12,18 ****
  #	and Toshiaki Nomura of the Fujitsu FreeSoftware Group
  #	<dsfrsoft@oai6.yk.fujitsu.co.jp>.
  #
! #	@(#)Makefile.UXPDS.V10	8.6 (Berkeley) 9/20/96
  #
  
  # make sure the shell constructs below use the right shell
- --- 12,18 ----
  #	and Toshiaki Nomura of the Fujitsu FreeSoftware Group
  #	<dsfrsoft@oai6.yk.fujitsu.co.jp>.
  #
! #	@(#)Makefile.UXPDS.V10	8.7 (Berkeley) 11/16/96
  #
  
  # make sure the shell constructs below use the right shell
***************
*** 119,125 ****
  	${INSTALL} -c -o ${BINOWN} -g ${BINGRP} -m 444 sendmail.hf ${HFDIR}
  
  # doesn't actually install them -- you may want to install pre-nroff versions
! install-docs: aliases.0 mailq.0 newaliases.0 sendmail.0
  	cp aliases.0 ${MAN4}/aliases.4
  	chmod ${MANMODE} ${MAN4}/aliases.4
  	cp mailq.0 ${MAN1}/mailq.1m
- --- 119,125 ----
  	${INSTALL} -c -o ${BINOWN} -g ${BINGRP} -m 444 sendmail.hf ${HFDIR}
  
  # doesn't actually install them -- you may want to install pre-nroff versions
! install-docs: ${MAN1} ${MAN4} aliases.0 mailq.0 newaliases.0 sendmail.0
  	cp aliases.0 ${MAN4}/aliases.4
  	chmod ${MANMODE} ${MAN4}/aliases.4
  	cp mailq.0 ${MAN1}/mailq.1m
***************
*** 129,137 ****
- --- 129,142 ----
  	cp sendmail.0 ${MAN1}/sendmail.1m
  	chmod ${MANMODE} ${MAN1}/sendmail.1m
  
+ ${MAN1} ${MAN4}:
+ 	mkdir -p $@
+ 
  clean:
  	rm -f ${OBJS} sendmail aliases.0 mailq.0 newaliases.0 sendmail.0
  
  # dependencies
  #   gross overkill, and yet still not quite enough....
  ${OBJS}: sendmail.h conf.h
+ 
+ depend:
diff -c -r sendmail-8.8.2/src/READ_ME sendmail-8.8.3/src/READ_ME
*** sendmail-8.8.2/src/READ_ME	Fri Oct 18 08:32:41 1996
- --- sendmail-8.8.3/src/READ_ME	Sun Nov 10 11:15:33 1996
***************
*** 30,36 ****
  # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  # SUCH DAMAGE.
  #
! #	@(#)READ_ME	8.125 (Berkeley) 10/18/96
  #
  
  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.130 (Berkeley) 11/10/96
  #
  
  This directory contains the source files for sendmail.
***************
*** 168,174 ****
  		this flag.
  
  >>>  NOTE WELL for NEWDB support: it is CRITICAL that you remove ndbm.o
! >>>  from libdb.a and ndbm.h from the appropriate include directories if
  >>>  you want to get ndbm support.  If you don't delete these, there is
  >>>  absolutely no point to including -DNDBM, since it will just get you
  >>>  another (inferior) API to the same format database.  These files
- --- 168,174 ----
  		this flag.
  
  >>>  NOTE WELL for NEWDB support: it is CRITICAL that you remove ndbm.o
! >>>  from libdb.a before you install it and DO NOT install ndbm.h if
  >>>  you want to get ndbm support.  If you don't delete these, there is
  >>>  absolutely no point to including -DNDBM, since it will just get you
  >>>  another (inferior) API to the same format database.  These files
***************
*** 355,365 ****
  			the dg_sys_info system call.
  		 LA_HPUX (10) is an HP-UX specific version that uses the
  			pstat_getdynamic system call.
  		LA_INT, LA_SHORT, LA_FLOAT, and LA_READKSYM have several
  		other parameters that they try to divine: the name of your
  		kernel, the name of the variable in the kernel to examine,
  		the number of bits of precision in a fixed point load average,
! 		and so forth.
  		In desperation, use LA_ZERO.  The actual code is in
  		conf.c -- it can be tweaked if you are brave.
  FSHIFT		For LA_INT, LA_SHORT, and LA_READKSYM, this is the number
- --- 355,374 ----
  			the dg_sys_info system call.
  		 LA_HPUX (10) is an HP-UX specific version that uses the
  			pstat_getdynamic system call.
+ 		 LA_IRIX6 (11) is an IRIX 6.x specific version that adapts
+ 			to 32 or 64 bit kernels; it is otherwise very similar
+ 			to LA_INT.
+ 		 LA_KSTAT (12) uses the (Solaris-specific) kstat(3k)
+ 			implementation.
+ 		 LA_DEVSHORT (13) reads a short from a system file (default:
+ 			/dev/table/avenrun) and scales it in the same manner
+ 			as LA_SHORT.
  		LA_INT, LA_SHORT, LA_FLOAT, and LA_READKSYM have several
  		other parameters that they try to divine: the name of your
  		kernel, the name of the variable in the kernel to examine,
  		the number of bits of precision in a fixed point load average,
! 		and so forth.  LA_DEVSHORT uses _PATH_AVENRUN to find the
! 		device to be read to find the load average.
  		In desperation, use LA_ZERO.  The actual code is in
  		conf.c -- it can be tweaked if you are brave.
  FSHIFT		For LA_INT, LA_SHORT, and LA_READKSYM, this is the number
***************
*** 809,814 ****
- --- 818,843 ----
  	the developers' option in order to get the necessary include
  	files.
  
+ 	If you compile with -lmalloc (the fast memory allocator), you may
+ 	get warning messages such as the following:
+ 
+ 	   ld32: WARNING 85: definition of _calloc in /usr/lib32/libmalloc.so
+ 		preempts that definition in /usr/lib32/mips3/libc.so.
+ 	   ld32: WARNING 85: definition of _malloc in /usr/lib32/libmalloc.so
+ 		preempts that definition in /usr/lib32/mips3/libc.so.
+ 	   ld32: WARNING 85: definition of _realloc in /usr/lib32/libmalloc.so
+ 		preempts that definition in /usr/lib32/mips3/libc.so.
+ 	   ld32: WARNING 85: definition of _free in /usr/lib32/libmalloc.so
+ 		preempts that definition in /usr/lib32/mips3/libc.so.
+ 	   ld32: WARNING 85: definition of _cfree in /usr/lib32/libmalloc.so
+ 		preempts that definition in /usr/lib32/mips3/libc.so.
+ 
+ 	These are unavoidable and innocuous -- just ignore them.
+ 
+ 	According to Dave Sill <de5@ornl.gov>, there is a version of the
+ 	Berkeley db library patched to run on Irix 6.2 available from
+ 	http://reality.sgi.com/ariel/db-1.85-irix.tar.Z .
+ 
  NeXT or NEXTSTEP
  	NEXTSTEP 3.3 and earlier ship with the old DBM library.  You will
  	need to acquire the new Berkeley DB from ftp.cs.berkeley.edu.
***************
*** 1348,1351 ****
  
  Eric Allman
  
! (Version 8.125, last update 10/18/96 07:32:40)
- --- 1377,1380 ----
  
  Eric Allman
  
! (Version 8.130, last update 11/10/96 11:15:30)
diff -c -r sendmail-8.8.2/src/collect.c sendmail-8.8.3/src/collect.c
*** sendmail-8.8.2/src/collect.c	Wed Sep 18 14:49:26 1996
- --- sendmail-8.8.3/src/collect.c	Fri Nov 15 07:23:02 1996
***************
*** 33,39 ****
   */
  
  #ifndef lint
! static char sccsid[] = "@(#)collect.c	8.58 (Berkeley) 9/18/96";
  #endif /* not lint */
  
  # include <errno.h>
- --- 33,39 ----
   */
  
  #ifndef lint
! static char sccsid[] = "@(#)collect.c	8.60 (Berkeley) 11/15/96";
  #endif /* not lint */
  
  # include <errno.h>
***************
*** 488,494 ****
  	**	Examples are who is the from person & the date.
  	*/
  
! 	eatheader(e, !requeueflag);
  
  	if (GrabTo && e->e_sendqueue == NULL)
  		usrerr("No recipient addresses found in header");
- --- 488,494 ----
  	**	Examples are who is the from person & the date.
  	*/
  
! 	eatheader(e, TRUE);
  
  	if (GrabTo && e->e_sendqueue == NULL)
  		usrerr("No recipient addresses found in header");
***************
*** 557,562 ****
- --- 557,563 ----
  	/* check for message too large */
  	if (MaxMessageSize > 0 && e->e_msgsize > MaxMessageSize)
  	{
+ 		e->e_flags |= EF_NO_BODY_RETN;
  		e->e_status = "5.2.3";
  		usrerr("552 Message exceeds maximum fixed size (%ld)",
  			MaxMessageSize);
diff -c -r sendmail-8.8.2/src/conf.c sendmail-8.8.3/src/conf.c
*** sendmail-8.8.2/src/conf.c	Thu Oct 17 07:52:56 1996
- --- sendmail-8.8.3/src/conf.c	Sun Nov 10 11:15:35 1996
***************
*** 33,39 ****
   */
  
  #ifndef lint
! static char sccsid[] = "@(#)conf.c	8.312 (Berkeley) 10/17/96";
  #endif /* not lint */
  
  # include "sendmail.h"
- --- 33,39 ----
   */
  
  #ifndef lint
! static char sccsid[] = "@(#)conf.c	8.315 (Berkeley) 11/10/96";
  #endif /* not lint */
  
  # include "sendmail.h"
***************
*** 1188,1195 ****
  	/* keep gethostby*() from stripping the local domain name */
  	set_domain_trim_off();
  #endif
! #if SECUREWARE
  	set_auth_parameters(argc, argv);
  #endif
  
  #ifdef VENDOR_DEFAULT
- --- 1188,1206 ----
  	/* keep gethostby*() from stripping the local domain name */
  	set_domain_trim_off();
  #endif
! #if SECUREWARE || defined(_SCO_unix_)
  	set_auth_parameters(argc, argv);
+ 
+ # ifdef _SCO_unix_
+ 	/*
+ 	**  This is required for highest security levels (the kernel
+ 	**  won't let it call set*uid() or run setuid binaries without
+ 	**  it).  It may be necessary on other SECUREWARE systems.
+ 	*/
+ 
+ 	if (getluid() == -1)
+ 		setluid(0);
+ # endif
  #endif
  
  #ifdef VENDOR_DEFAULT
***************
*** 1245,1250 ****
- --- 1256,1263 ----
  #define LA_DGUX		9	/* special DGUX implementation */
  #define LA_HPUX		10	/* special HPUX implementation */
  #define LA_IRIX6	11	/* special IRIX 6.2 implementation */
+ #define LA_KSTAT	12	/* special Solaris kstat(3k) implementation */
+ #define LA_DEVSHORT	13	/* read short from a device */
  
  /* do guesses based on general OS type */
  #ifndef LA_TYPE
***************
*** 1780,1787 ****
- --- 1793,1892 ----
  }
  #endif
  
+ #if LA_TYPE == LA_KSTAT
+ 
+ #include <kstat.h>
+ 
+ int
+ getla()
+ {
+ 	kstat_ctl_t *kc;
+ 	kstat_t *ksp;
+ 	kstat_named_t *ksn;
+ 	int la;
+ 
+ 	kc = kstat_open();
+ 	if (kc == NULL)
+ 	{
+ 		if (tTd(3, 1))
+ 			printf("getla: kstat_open(): %s\n",
+ 				errstring(errno));
+ 		return -1;
+ 	}
+ 	ksp = kstat_lookup(kc, "unix", 0, "system_misc"); /* NULL on error */
+ 	if (ksp == NULL)
+ 	{
+ 		if (tTd(3, 1))
+ 			printf("getla: kstat_lookup(): %s\n",
+ 				errstring(errno);
+ 		return -1;
+ 	}
+ 	if (kstat_read(kc, ksp, NULL) < 0)
+ 	{
+ 		if (tTd(3, 1))
+ 			printf("getla: kstat_read(): %s\n",
+ 				errstring(errno);
+ 		return -1;
+ 	}
+ 	ksn = (kstat_named_t *) kstat_data_lookup(ksp, "avenrun_1min");
+ 	la = (ksn->value.ul + FSCALE/2) >> FSHIFT;
+ 	kstat_close(kc);
+ 	return la;
+ }
+ 
+ #endif /* LA_TYPE == LA_KSTAT */
+ 
+ #if LA_TYPE == LA_DEVSHORT
+ 
+ /*
+ **  Read /dev/table/avenrun for the load average.  This should contain
+ **  three shorts for the 1, 5, and 15 minute loads.  We only read the
+ **  first, since that's all we care about.
+ **
+ **	Intended for SCO OpenServer 5.
+ */
+ 
+ # ifndef _PATH_AVENRUN
+ #  define _PATH_AVENRUN	"/dev/table/avenrun"
+ # endif
+ 
+ int
+ getla()
+ {
+ 	static int afd = -1;
+ 	short avenrun;
+ 	int loadav;
+ 	int r;
+ 
+ 	errno = EBADF;
+ 
+ 	if (afd == -1 || lseek(afd, 0L, SEEK_SET) == -1)
+ 	{
+ 		if (errno != EBADF)
+ 			return -1;
+ 		afd = open(_PATH_AVENRUN, O_RDONLY|O_SYNC);
+ 		if (afd < 0)
+ 		{
+ 			syslog(LOG_ERR, "can't open %s: %m", _PATH_AVENRUN);
+ 			return -1;
+ 		}
+ 	}
+ 
+ 	r = read(afd, &avenrun, sizeof avenrun);
+ 
+ 	if (tTd(3, 5))
+ 		printf("getla: avenrun = %d\n", avenrun);
+ 	loadav = (int) (avenrun + FSCALE/2) >> FSHIFT;
+ 	if (tTd(3, 1))
+ 		printf("getla: %d\n", loadav);
+ 	return loadav;
+ }
+ 
+ #endif /* LA_TYPE == LA_DEVSHORT */
+ 
  #if LA_TYPE == LA_ZERO
  
+ int
  getla()
  {
  	if (tTd(3, 1))
***************
*** 1941,1948 ****
  			syslog(LOG_INFO, "rejecting connections on port %d: load average: %d",
  				port, CurrentLA);
  #endif
  	}
! 	else if (!enoughdiskspace(MinBlocksFree + 1))
  	{
  		setproctitle("rejecting connections on port %d: min free: %d",
  			port, MinBlocksFree);
- --- 2046,2055 ----
  			syslog(LOG_INFO, "rejecting connections on port %d: load average: %d",
  				port, CurrentLA);
  #endif
+ 		return TRUE;
  	}
! 
! 	if (!enoughdiskspace(MinBlocksFree + 1))
  	{
  		setproctitle("rejecting connections on port %d: min free: %d",
  			port, MinBlocksFree);
***************
*** 1951,1970 ****
  			syslog(LOG_INFO, "rejecting connections on port %d: min free: %d",
  				port, MinBlocksFree);
  #endif
  	}
! 	else if (MaxChildren > 0 && CurChildren >= MaxChildren)
  	{
! 		setproctitle("rejecting connections on port %d: %d children, max %d",
! 			port, CurChildren, MaxChildren);
! #ifdef LOG
! 		if (LogLevel >= 14)
! 			syslog(LOG_INFO, "rejecting connections on port %d: %d children, max %d",
  				port, CurChildren, MaxChildren);
  #endif
  	}
! 	else
! 		return FALSE;
! 	return TRUE;
  }
  /*
  **  SETPROCTITLE -- set process title for ps
- --- 2058,2083 ----
  			syslog(LOG_INFO, "rejecting connections on port %d: min free: %d",
  				port, MinBlocksFree);
  #endif
+ 		return TRUE;
  	}
! 
! 	if (MaxChildren > 0 && CurChildren >= MaxChildren)
  	{
! 		proc_list_probe();
! 		if (CurChildren >= MaxChildren)
! 		{
! 			setproctitle("rejecting connections on port %d: %d children, max %d",
  				port, CurChildren, MaxChildren);
+ #ifdef LOG
+ 			if (LogLevel >= 14)
+ 				syslog(LOG_INFO, "rejecting connections on port %d: %d children, max %d",
+ 					port, CurChildren, MaxChildren);
  #endif
+ 			return TRUE;
+ 		}
  	}
! 
! 	return FALSE;
  }
  /*
  **  SETPROCTITLE -- set process title for ps
diff -c -r sendmail-8.8.2/src/conf.h sendmail-8.8.3/src/conf.h
*** sendmail-8.8.2/src/conf.h	Thu Oct 17 18:09:04 1996
- --- sendmail-8.8.3/src/conf.h	Sat Nov 16 18:32:10 1996
***************
*** 31,37 ****
   * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   *
!  *	@(#)conf.h	8.267 (Berkeley) 10/17/96
   */
  
  /*
- --- 31,37 ----
   * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   *
!  *	@(#)conf.h	8.272 (Berkeley) 11/16/96
   */
  
  /*
***************
*** 41,47 ****
- --- 41,49 ----
  **	included in the next release.
  */
  
+ #ifdef __GNUC__
  struct rusage;	/* forward declaration to get gcc to shut up in wait.h */
+ #endif
  
  # include <sys/param.h>
  # include <sys/types.h>
***************
*** 216,222 ****
  
  #ifdef _AIX4
  # define _AIX3		1	/* pull in AIX3 stuff */
! # define HASSETREUID	1	/* setreuid(2) works */
  #endif
  
  
- --- 218,228 ----
  
  #ifdef _AIX4
  # define _AIX3		1	/* pull in AIX3 stuff */
! # define USESETEUID	1	/* seteuid(2) works */
! # define TZ_TYPE	TZ_NAME	/* use tzname[] vector */
! # if _AIX4 >= 40200
! #  define HASSETREUID	1	/* setreuid(2) works as of AIX 4.2 */
! # endif
  #endif
  
  
***************
*** 409,414 ****
- --- 415,423 ----
  #    define snprintf	__snprintf	/* but names it oddly in 2.5 */
  #    define vsnprintf	__vsnprintf
  #   endif
+ #   ifndef LA_TYPE
+ #    define LA_TYPE	LA_KSTAT	/* use kstat(3k) -- may work in < 2.5 */
+ #   endif
  #  endif
  #  ifndef HASGETUSERSHELL
  #   define HASGETUSERSHELL 0	/* getusershell(3) causes core dumps */
***************
*** 588,593 ****
- --- 597,603 ----
  # define WAITUNION	1	/* use "union wait" as wait argument type */
  # define UID_T		int	/* compiler gripes on uid_t */
  # define GID_T		int	/* ditto for gid_t */
+ # define MODE_T		int	/* and mode_t */
  # define sleep		sleepX
  # define setpgid	setpgrp
  # ifndef LA_TYPE
***************
*** 791,821 ****
  **	The third is for SCO UNIX 3.2v4.0/Open Desktop 2.0 and earlier.
  */
  
  #if _SCO_DS >= 1
  # include <paths.h>
  # define _SCO_unix_4_2
! # define HASSNPRINTF	1	/* has snprintf() call */
! # define HASFCHMOD	1	/* has fchmod() call */
! # define HASSETRLIMIT	1	/* has setrlimit() call */
  # define RLIMIT_NEEDS_SYS_TIME_H	1
  #endif
  
! 
  #ifdef _SCO_unix_4_2
  # define _SCO_unix_
  # define HASSETREUID	1	/* has setreuid(2) call */
  #endif
  
  #ifdef _SCO_unix_
  # include <sys/stream.h>	/* needed for IP_SRCROUTE */
  # define SYSTEM5	1	/* include all the System V defines */
  # define HASGETUSERSHELL 0	/* does not have getusershell(3) call */
  # define MAXPATHLEN	PATHSIZE
- - # define LA_TYPE	LA_SHORT
  # define SFS_TYPE	SFS_4ARGS	/* use <sys/statfs.h> 4-arg impl */
  # define SFS_BAVAIL	f_bfree		/* alternate field name */
  # define SPT_TYPE	SPT_SCO		/* write kernel u. area */
  # define TZ_TYPE	TZ_TM_NAME	/* use tm->tm_name */
  # define _PATH_UNIX		"/unix"
  # define _PATH_VENDOR_CF	"/usr/lib/sendmail.cf"
  # ifndef _PATH_SENDMAILPID
- --- 801,843 ----
  **	The third is for SCO UNIX 3.2v4.0/Open Desktop 2.0 and earlier.
  */
  
+ /* SCO OpenServer 5 */
  #if _SCO_DS >= 1
  # include <paths.h>
  # define _SCO_unix_4_2
! # define HASSNPRINTF	1	/* has snprintf(3) call */
! # define HASFCHMOD	1	/* has fchmod(2) call */
! # define HASSETRLIMIT	1	/* has setrlimit(2) call */
! # define USESETEUID	1	/* has seteuid(2) call */
! # define HASINITGROUPS	1	/* has initgroups(3) call */
! # define HASGETDTABLESIZE 1	/* has getdtablesize(2) call */
  # define RLIMIT_NEEDS_SYS_TIME_H	1
+ # ifndef LA_TYPE
+ #  define LA_TYPE	LA_DEVSHORT
+ # endif
+ # define _PATH_AVENRUN	"/dev/table/avenrun"
  #endif
  
! /* SCO UNIX 3.2v4.2/Open Desktop 3.0 */
  #ifdef _SCO_unix_4_2
  # define _SCO_unix_
  # define HASSETREUID	1	/* has setreuid(2) call */
  #endif
  
+ /* SCO UNIX 3.2v4.0 Open Desktop 2.0 and earlier */
  #ifdef _SCO_unix_
  # include <sys/stream.h>	/* needed for IP_SRCROUTE */
  # define SYSTEM5	1	/* include all the System V defines */
  # define HASGETUSERSHELL 0	/* does not have getusershell(3) call */
+ # define NOFTRUNCATE	0	/* has (simulated) ftruncate call */
  # define MAXPATHLEN	PATHSIZE
  # define SFS_TYPE	SFS_4ARGS	/* use <sys/statfs.h> 4-arg impl */
  # define SFS_BAVAIL	f_bfree		/* alternate field name */
  # define SPT_TYPE	SPT_SCO		/* write kernel u. area */
  # define TZ_TYPE	TZ_TM_NAME	/* use tm->tm_name */
+ # define UID_T		uid_t
+ # define GID_T		gid_t
+ # define GIDSET_T	gid_t
  # define _PATH_UNIX		"/unix"
  # define _PATH_VENDOR_CF	"/usr/lib/sendmail.cf"
  # ifndef _PATH_SENDMAILPID
***************
*** 828,836 ****
  # endif
  
  # ifndef _SCO_DS
! #  define NOFTRUNCATE	0	/* does not have ftruncate(3) call */
  #  define NEEDFSYNC	1	/* needs the fsync(2) call stub */
  #  define NETUNIX	0	/* no unix domain socket support */
  # endif
  
  #endif
- --- 850,859 ----
  # endif
  
  # ifndef _SCO_DS
! #  define ftruncate	chsize	/* use chsize(2) to emulate ftruncate */
  #  define NEEDFSYNC	1	/* needs the fsync(2) call stub */
  #  define NETUNIX	0	/* no unix domain socket support */
+ #  define LA_TYPE	LA_SHORT
  # endif
  
  #endif
***************
*** 1848,1853 ****
- --- 1871,1880 ----
  
  #ifndef SIZE_T
  # define SIZE_T		size_t
+ #endif
+ 
+ #ifndef MODE_T
+ # define MODE_T		mode_t
  #endif
  
  #ifndef ARGV_T
diff -c -r sendmail-8.8.2/src/daemon.c sendmail-8.8.3/src/daemon.c
*** sendmail-8.8.2/src/daemon.c	Sat Oct 12 13:35:11 1996
- --- sendmail-8.8.3/src/daemon.c	Fri Nov  8 09:09:27 1996
***************
*** 37,45 ****
  
  #ifndef lint
  #ifdef DAEMON
! static char sccsid[] = "@(#)daemon.c	8.145 (Berkeley) 10/12/96 (with daemon mode)";
  #else
! static char sccsid[] = "@(#)daemon.c	8.145 (Berkeley) 10/12/96 (without daemon mode)";
  #endif
  #endif /* not lint */
  
- --- 37,45 ----
  
  #ifndef lint
  #ifdef DAEMON
! static char sccsid[] = "@(#)daemon.c	8.148 (Berkeley) 11/8/96 (with daemon mode)";
  #else
! static char sccsid[] = "@(#)daemon.c	8.148 (Berkeley) 11/8/96 (without daemon mode)";
  #endif
  #endif /* not lint */
  
***************
*** 193,199 ****
  
  	for (;;)
  	{
! 		register int pid;
  		auto int lotherend;
  		extern bool refuseconnections();
  		extern int getla();
- --- 193,199 ----
  
  	for (;;)
  	{
! 		register pid_t pid;
  		auto int lotherend;
  		extern bool refuseconnections();
  		extern int getla();
***************
*** 244,249 ****
- --- 244,259 ----
  		/* wait for a connection */
  		setproctitle("accepting connections on port %d",
  			     ntohs(DaemonAddr.sin.sin_port));
+ #if 0
+ 		/*
+ 		**  Andrew Sun <asun@ieps-sun.ml.com> claims that this will
+ 		**  fix the SVr4 problem.  But it seems to have gone away,
+ 		**  so is it worth doing this?
+ 		*/
+ 
+ 		if (SetNonBlocking(DaemonSocket, FALSE) < 0)
+ 			log an error here;
+ #endif
  		do
  		{
  			errno = 0;
***************
*** 734,742 ****
  			extern char MsgBuf[];
  
  			usrerr("553 Invalid numeric domain spec \"%s\"", host);
! 			mci->mci_status = "5.1.2";
! 			mci->mci_rstatus = newstr(MsgBuf);
! 			return (EX_NOHOST);
  		}
  #if NETINET
  		addr.sin.sin_family = AF_INET;		/*XXX*/
- --- 744,751 ----
  			extern char MsgBuf[];
  
  			usrerr("553 Invalid numeric domain spec \"%s\"", host);
! 			mci_setstat(mci, EX_NOHOST, "5.1.2", MsgBuf);
! 			return EX_NOHOST;
  		}
  #if NETINET
  		addr.sin.sin_family = AF_INET;		/*XXX*/
***************
*** 773,783 ****
  			if (errno == ETIMEDOUT || h_errno == TRY_AGAIN ||
  			    (errno == ECONNREFUSED && UseNameServer))
  			{
! 				mci->mci_status = "4.4.3";
! 				mci->mci_rstatus = NULL;
! 				return (EX_TEMPFAIL);
  			}
  #endif
  			return (EX_NOHOST);
  		}
  		addr.sa.sa_family = hp->h_addrtype;
- --- 782,792 ----
  			if (errno == ETIMEDOUT || h_errno == TRY_AGAIN ||
  			    (errno == ECONNREFUSED && UseNameServer))
  			{
! 				mci_setstat(mci, EX_TEMPFAIL, "4.4.3", NULL);
! 				return EX_TEMPFAIL;
  			}
  #endif
+ 			mci_setstat(mci, EX_NOHOST, "5.1.2", NULL);
  			return (EX_NOHOST);
  		}
  		addr.sa.sa_family = hp->h_addrtype;
***************
*** 839,844 ****
- --- 848,854 ----
  
  	  default:
  		syserr("Can't connect to address family %d", addr.sa.sa_family);
+ 		mci_setstat(mci, EX_NOHOST, "5.1.2", NULL);
  		return (EX_NOHOST);
  	}
  
***************
*** 876,882 ****
  		{
  			sav_errno = errno;
  			syserr("makeconnection: cannot create socket");
! 			goto failure;
  		}
  
  #ifdef SO_SNDBUF
- --- 886,896 ----
  		{
  			sav_errno = errno;
  			syserr("makeconnection: cannot create socket");
! #ifdef XLA
! 			xla_host_end(host);
! #endif
! 			mci_setstat(mci, EX_TEMPFAIL, "4.4.5", NULL);
! 			return EX_TEMPFAIL;
  		}
  
  #ifdef SO_SNDBUF
***************
*** 964,981 ****
  			continue;
  		}
  
! 		/* failure, decide if temporary or not */
! 	failure:
  #ifdef XLA
  		xla_host_end(host);
  #endif
! 		if (transienterror(sav_errno))
! 			return EX_TEMPFAIL;
! 		else
! 		{
! 			message("%s", errstring(sav_errno));
! 			return (EX_UNAVAILABLE);
! 		}
  	}
  
  	/* connection ok, put it into canonical form */
- --- 978,989 ----
  			continue;
  		}
  
! 		/* couldn't open connection */
  #ifdef XLA
  		xla_host_end(host);
  #endif
! 		mci_setstat(mci, EX_TEMPFAIL, "4.4.1", NULL);
! 		return EX_TEMPFAIL;
  	}
  
  	/* connection ok, put it into canonical form */
***************
*** 984,992 ****
- --- 992,1002 ----
  	    (mci->mci_in = fdopen(s, "r")) == NULL)
  	{
  		syserr("cannot open SMTP client channel, fd=%d", s);
+ 		mci_setstat(mci, EX_TEMPFAIL, "4.4.5", NULL);
  		return EX_TEMPFAIL;
  	}
  
+ 	mci_setstat(mci, EX_OK, NULL, NULL);
  	return (EX_OK);
  }
  /*
diff -c -r sendmail-8.8.2/src/deliver.c sendmail-8.8.3/src/deliver.c
*** sendmail-8.8.2/src/deliver.c	Thu Oct 17 07:54:08 1996
- --- sendmail-8.8.3/src/deliver.c	Sat Nov 16 07:40:26 1996
***************
*** 33,39 ****
   */
  
  #ifndef lint
! static char sccsid[] = "@(#)deliver.c	8.246 (Berkeley) 10/17/96";
  #endif /* not lint */
  
  #include "sendmail.h"
- --- 33,39 ----
   */
  
  #ifndef lint
! static char sccsid[] = "@(#)deliver.c	8.251 (Berkeley) 11/11/96";
  #endif /* not lint */
  
  #include "sendmail.h"
***************
*** 78,84 ****
  	ENVELOPE *splitenv = NULL;
  	bool oldverbose = Verbose;
  	bool somedeliveries = FALSE;
! 	int pid;
  	extern void sendenvelope();
  
  	/*
- --- 78,84 ----
  	ENVELOPE *splitenv = NULL;
  	bool oldverbose = Verbose;
  	bool somedeliveries = FALSE;
! 	pid_t pid;
  	extern void sendenvelope();
  
  	/*
***************
*** 760,766 ****
  int
  dofork()
  {
! 	register int pid = -1;
  
  	DOFORK(fork);
  	return (pid);
- --- 760,766 ----
  int
  dofork()
  {
! 	register pid_t pid = -1;
  
  	DOFORK(fork);
  	return (pid);
***************
*** 813,823 ****
  	ADDRESS *volatile tochain = NULL; /* users chain in this mailer call */
  	int rcode;			/* response code */
  	char *firstsig;			/* signature of firstto */
! 	int pid = -1;
  	char *volatile curhost;
  	register volatile u_short port = 0;
  	time_t xstart;
  	bool suidwarn;
  	int mpvect[2];
  	int rpvect[2];
  	char *pv[MAXPV+1];
- --- 813,824 ----
  	ADDRESS *volatile tochain = NULL; /* users chain in this mailer call */
  	int rcode;			/* response code */
  	char *firstsig;			/* signature of firstto */
! 	pid_t pid = -1;
  	char *volatile curhost;
  	register volatile u_short port = 0;
  	time_t xstart;
  	bool suidwarn;
+ 	bool anyok;			/* at least one address was OK */
  	int mpvect[2];
  	int rpvect[2];
  	char *pv[MAXPV+1];
***************
*** 1314,1320 ****
  
  			if (mci_lock_host(mci) != EX_OK)
  			{
! 				mci->mci_exitstat = EX_TEMPFAIL;
  				continue;
  			}
  
- --- 1315,1321 ----
  
  			if (mci_lock_host(mci) != EX_OK)
  			{
! 				mci_setstat(mci, EX_TEMPFAIL, "4.4.5", NULL);
  				continue;
  			}
  
***************
*** 1840,1845 ****
- --- 1841,1847 ----
  		extern int smtpmailfrom __P((MAILER *, MCI *, ENVELOPE *));
  		extern int smtprcpt __P((ADDRESS *, MAILER *, MCI *, ENVELOPE *));
  		extern int smtpdata __P((MAILER *, MCI *, ENVELOPE *));
+ 		extern int smtpgetstat __P((MAILER *, MCI *, ENVELOPE *));
  
  		/*
  		**  Send the MAIL FROM: protocol
***************
*** 1883,1892 ****
  				e->e_to = tobuf + 1;
  				rcode = smtpdata(m, mci, e);
  			}
- - 
- - 			/* now close the connection */
- - 			if (!bitset(MCIF_CACHED, mci->mci_flags))
- - 				smtpquit(m, mci, e);
  		}
  		if (rcode == EX_TEMPFAIL && curhost != NULL && *curhost != '\0')
  		{
- --- 1885,1890 ----
***************
*** 1917,1927 ****
  	*/
  
    give_up:
! 	if (tobuf[0] != '\0')
! 		giveresponse(rcode, m, mci, ctladdr, xstart, e);
! 	if (rcode == EX_OK)
! 		markstats(e, tochain);
! 	mci_store_persistent(mci);
  
  	for (to = tochain; to != NULL; to = to->q_tchain)
  	{
- --- 1915,1931 ----
  	*/
  
    give_up:
! #ifdef SMTP
! # if FFR_LMTP
! 	if (bitnset(M_LMTP, m->m_flags))
! 	{
! 		tobuf[0] = '\0';
! 		anyok = FALSE;
! 	}
! 	else
! # endif
! #endif
! 		anyok = rcode == EX_OK;
  
  	for (to = tochain; to != NULL; to = to->q_tchain)
  	{
***************
*** 1929,1939 ****
  		if (bitset(QBADADDR|QQUEUEUP, to->q_flags))
  			continue;
  
! 		/* mark bad addresses */
! 		if (rcode != EX_OK)
  		{
! 			markfailure(e, to, mci, rcode);
! 			continue;
  		}
  
  		/* successful delivery */
- --- 1933,1969 ----
  		if (bitset(QBADADDR|QQUEUEUP, to->q_flags))
  			continue;
  
! #ifdef SMTP
! # if FFR_LMTP
! 		/* if running LMTP, get the status for each address */
! 		if (bitnset(M_LMTP, m->m_flags))
  		{
! 			rcode = smtpgetstat(m, mci, e);
! 			if (rcode == EX_OK)
! 			{
! 				strcat(tobuf, ",");
! 				strcat(tobuf, to->q_paddr);
! 				anyok = TRUE;
! 			}
! 			else
! 			{
! 				e->e_to = to->q_paddr;
! 				markfailure(e, to, mci, rcode);
! 				giveresponse(rcode, m, mci, ctladdr, xstart, e);
! 				e->e_to = tobuf + 1;
! 				continue;
! 			}
! 		}
! 		else
! # endif
! #endif
! 		{
! 			/* mark bad addresses */
! 			if (rcode != EX_OK)
! 			{
! 				markfailure(e, to, mci, rcode);
! 				continue;
! 			}
  		}
  
  		/* successful delivery */
***************
*** 1958,1963 ****
- --- 1988,2025 ----
  		}
  	}
  
+ #ifdef SMTP
+ # if FFR_LMTP
+ 	if (bitnset(M_LMTP, m->m_flags))
+ 	{
+ 		/*
+ 		**  Global information applies to the last recipient only;
+ 		**  clear it out to avoid bogus errors.
+ 		*/
+ 
+ 		rcode = EX_OK;
+ 		e->e_statmsg = NULL;
+ 
+ 		/* reset the mci state for the next transaction */
+ 		if (mci->mci_state == MCIS_ACTIVE)
+ 			mci->mci_state = MCIS_OPEN;
+ 	}
+ # endif
+ #endif
+ 
+ 	if (tobuf[0] != '\0')
+ 		giveresponse(rcode, m, mci, ctladdr, xstart, e);
+ 	if (anyok)
+ 		markstats(e, tochain);
+ 	mci_store_persistent(mci);
+ 
+ #ifdef SMTP
+ 	/* now close the connection */
+ 	if (clever && mci->mci_state != MCIS_CLOSED &&
+ 	    !bitset(MCIF_CACHED, mci->mci_flags))
+ 		smtpquit(m, mci, e);
+ #endif
+ 
  	/*
  	**  Restore state and return.
  	*/
***************
*** 2142,2148 ****
  	st = waitfor(mci->mci_pid);
  	if (st == -1)
  	{
! 		syserr("endmailer %s: wait", pv[0]);
  		return (EX_SOFTWARE);
  	}
  
- --- 2204,2210 ----
  	st = waitfor(mci->mci_pid);
  	if (st == -1)
  	{
! 		syserr("endmailer %s: wait", mci->mci_mailer->m_name);
  		return (EX_SOFTWARE);
  	}
  
***************
*** 2951,2957 ****
  	register ENVELOPE *e;
  {
  	register FILE *f;
! 	register int pid = -1;
  	int mode;
  	bool suidwarn = geteuid() == 0;
  
- --- 3013,3019 ----
  	register ENVELOPE *e;
  {
  	register FILE *f;
! 	register pid_t pid = -1;
  	int mode;
  	bool suidwarn = geteuid() == 0;
  
***************
*** 3146,3154 ****
  
  		/* reset ISUID & ISGID bits for paranoid systems */
  #if HASFCHMOD
! 		(void) fchmod(fileno(f), (int) stb.st_mode);
  #else
! 		(void) chmod(filename, (int) stb.st_mode);
  #endif
  		(void) xfclose(f, "mailfile", filename);
  		(void) fflush(stdout);
- --- 3208,3216 ----
  
  		/* reset ISUID & ISGID bits for paranoid systems */
  #if HASFCHMOD
! 		(void) fchmod(fileno(f), (MODE_T) stb.st_mode);
  #else
! 		(void) chmod(filename, (MODE_T) stb.st_mode);
  #endif
  		(void) xfclose(f, "mailfile", filename);
  		(void) fflush(stdout);
***************
*** 3259,3268 ****
  
  				/* update the connection info for this host */
  				mci = mci_get(hp, m);
- - 				mci->mci_lastuse = curtime();
- - 				mci->mci_exitstat = rcode;
  				mci->mci_errno = errno;
  				mci->mci_herrno = h_errno;
  
  				/* use the original host name as signature */
  				nmx = 1;
- --- 3321,3330 ----
  
  				/* update the connection info for this host */
  				mci = mci_get(hp, m);
  				mci->mci_errno = errno;
  				mci->mci_herrno = h_errno;
+ 				mci->mci_lastuse = curtime();
+ 				mci_setstat(mci, rcode, NULL, NULL);
  
  				/* use the original host name as signature */
  				nmx = 1;
diff -c -r sendmail-8.8.2/src/domain.c sendmail-8.8.3/src/domain.c
*** sendmail-8.8.2/src/domain.c	Sat Oct 12 17:14:28 1996
- --- sendmail-8.8.3/src/domain.c	Wed Oct 30 09:42:41 1996
***************
*** 36,44 ****
  
  #ifndef lint
  #if NAMED_BIND
! static char sccsid[] = "@(#)domain.c	8.63 (Berkeley) 9/15/96 (with name server)";
  #else
! static char sccsid[] = "@(#)domain.c	8.63 (Berkeley) 9/15/96 (without name server)";
  #endif
  #endif /* not lint */
  
- --- 36,44 ----
  
  #ifndef lint
  #if NAMED_BIND
! static char sccsid[] = "@(#)domain.c	8.64 (Berkeley) 10/30/96 (with name server)";
  #else
! static char sccsid[] = "@(#)domain.c	8.64 (Berkeley) 10/30/96 (without name server)";
  #endif
  #endif /* not lint */
  
***************
*** 48,57 ****
  #include <resolv.h>
  #include <arpa/inet.h>
  
  typedef union
  {
  	HEADER	qb1;
! 	u_char	qb2[PACKETSZ];
  } querybuf;
  
  #ifndef MXHOSTBUFSIZE
- --- 48,70 ----
  #include <resolv.h>
  #include <arpa/inet.h>
  
+ /*
+ **  The standard udp packet size PACKETSZ (512) is not sufficient for some
+ **  nameserver answers containing very many resource records. The resolver
+ **  may switch to tcp and retry if it detects udp packet overflow.
+ **  Also note that the resolver routines res_query and res_search return
+ **  the size of the *un*truncated answer in case the supplied answer buffer
+ **  it not big enough to accommodate the entire answer.
+ */
+ 
+ #ifndef MAXPACKET
+ # define MAXPACKET 8192		/* max packet size used internally by BIND */
+ #endif
+ 
  typedef union
  {
  	HEADER	qb1;
! 	u_char	qb2[MAXPACKET];
  } querybuf;
  
  #ifndef MXHOSTBUFSIZE
***************
*** 206,211 ****
- --- 219,228 ----
  		return (-1);
  	}
  
+ 	/* avoid problems after truncation in tcp packets */
+ 	if (n > sizeof(answer))
+ 		n = sizeof(answer);
+ 
  	/* find first satisfactory answer */
  	hp = (HEADER *)&answer;
  	cp = (u_char *)&answer + HFIXEDSZ;
***************
*** 515,521 ****
  	int qtype;
  	int loopcnt;
  	char *xp;
! 	char nbuf[MAX(PACKETSZ, MAXDNAME*2+2)];
  	char *searchlist[MAXDNSRCH+2];
  	extern char *gethostalias();
  
- --- 532,538 ----
  	int qtype;
  	int loopcnt;
  	char *xp;
! 	char nbuf[MAX(MAXPACKET, MAXDNAME*2+2)];
  	char *searchlist[MAXDNSRCH+2];
  	extern char *gethostalias();
  
***************
*** 647,652 ****
- --- 664,673 ----
  		}
  		else if (tTd(8, 7))
  			printf("\tYES\n");
+ 
+ 		/* avoid problems after truncation in tcp packets */
+ 		if (ret > sizeof(answer))
+ 			ret = sizeof(answer);
  
  		/*
  		**  Appear to have a match.  Confirm it by searching for A or
diff -c -r sendmail-8.8.2/src/envelope.c sendmail-8.8.3/src/envelope.c
*** sendmail-8.8.2/src/envelope.c	Sat Oct 12 17:14:28 1996
- --- sendmail-8.8.3/src/envelope.c	Mon Nov 11 09:34:08 1996
***************
*** 33,39 ****
   */
  
  #ifndef lint
! static char sccsid[] = "@(#)envelope.c	8.93 (Berkeley) 9/26/96";
  #endif /* not lint */
  
  #include "sendmail.h"
- --- 33,39 ----
   */
  
  #ifndef lint
! static char sccsid[] = "@(#)envelope.c	8.96 (Berkeley) 11/11/96";
  #endif /* not lint */
  
  #include "sendmail.h"
***************
*** 153,161 ****
  	e->e_flags &= ~EF_QUEUERUN;
  	for (q = e->e_sendqueue; q != NULL; q = q->q_next)
  	{
! 		if (!bitset(QBADADDR|QDONTSEND|QSENT, q->q_flags) ||
! 		    bitset(QQUEUEUP, q->q_flags))
  			queueit = TRUE;
  
  		/* see if a notification is needed */
  		if (bitset(QPINGONFAILURE, q->q_flags) &&
- --- 153,176 ----
  	e->e_flags &= ~EF_QUEUERUN;
  	for (q = e->e_sendqueue; q != NULL; q = q->q_next)
  	{
! 		if (bitset(QQUEUEUP, q->q_flags) &&
! 		    bitset(QDONTSEND, q->q_flags))
! 		{
! 			/* I'm not sure how this happens..... */
! 			if (tTd(50, 2))
! 			{
! 				printf("Bogus flags: ");
! 				printaddr(q, FALSE);
! 			}
! 			q->q_flags &= ~QDONTSEND;
! 		}
! 		if (!bitset(QBADADDR|QDONTSEND|QSENT, q->q_flags))
  			queueit = TRUE;
+ #if XDEBUG
+ 		else if (bitset(QQUEUEUP, q->q_flags))
+ 			syslog(LOG_DEBUG, "%s: q_flags = %x",
+ 				e->e_id, q->q_flags);
+ #endif
  
  		/* see if a notification is needed */
  		if (bitset(QPINGONFAILURE, q->q_flags) &&
***************
*** 203,210 ****
  		fprintf(e->e_xfp, "Message will be deleted from queue\n");
  		for (q = e->e_sendqueue; q != NULL; q = q->q_next)
  		{
! 			if (bitset(QQUEUEUP, q->q_flags) ||
! 			    !bitset(QBADADDR|QDONTSEND|QSENT, q->q_flags))
  			{
  				q->q_flags |= QBADADDR;
  				q->q_status = "4.4.7";
- --- 218,224 ----
  		fprintf(e->e_xfp, "Message will be deleted from queue\n");
  		for (q = e->e_sendqueue; q != NULL; q = q->q_next)
  		{
! 			if (!bitset(QBADADDR|QDONTSEND|QSENT, q->q_flags))
  			{
  				q->q_flags |= QBADADDR;
  				q->q_status = "4.4.7";
diff -c -r sendmail-8.8.2/src/main.c sendmail-8.8.3/src/main.c
*** sendmail-8.8.2/src/main.c	Sat Oct 12 17:19:41 1996
- --- sendmail-8.8.3/src/main.c	Sat Nov 16 10:34:25 1996
***************
*** 39,45 ****
  #endif /* not lint */
  
  #ifndef lint
! static char sccsid[] = "@(#)main.c	8.211 (Berkeley) 10/12/96";
  #endif /* not lint */
  
  #define	_DEFINE
- --- 39,45 ----
  #endif /* not lint */
  
  #ifndef lint
! static char sccsid[] = "@(#)main.c	8.215 (Berkeley) 11/16/96";
  #endif /* not lint */
  
  #define	_DEFINE
***************
*** 387,398 ****
  	OpMode = MD_DELIVER;
  	FullName = getextenv("NAME");
  
  #if NAMED_BIND
! 	if (tTd(8, 8))
! 	{
  		res_init();
  		_res.options |= RES_DEBUG;
! 	}
  #endif
  
  	errno = 0;
- --- 387,404 ----
  	OpMode = MD_DELIVER;
  	FullName = getextenv("NAME");
  
+ 	/*
+ 	**  Initialize name server if it is going to be used.
+ 	*/
+ 
  #if NAMED_BIND
! 	if (!bitset(RES_INIT, _res.options))
  		res_init();
+ 	if (tTd(8, 8))
  		_res.options |= RES_DEBUG;
! # ifdef RES_NOALIASES
! 	_res.options |= RES_NOALIASES;
! # endif
  #endif
  
  	errno = 0;
***************
*** 513,527 ****
  			{
  			  case MD_DAEMON:
  			  case MD_FGDAEMON:
! # ifdef DAEMON
! 				if (RealUid != 0)
! 				{
! 					usrerr("Permission denied");
! 					exit(EX_USAGE);
! 				}
! 				vendor_daemon_setup(CurEnv);
! 				/* fall through ... */
! # else
  				usrerr("Daemon mode not implemented");
  				ExitStat = EX_USAGE;
  				break;
- --- 519,525 ----
  			{
  			  case MD_DAEMON:
  			  case MD_FGDAEMON:
! # ifndef DAEMON
  				usrerr("Daemon mode not implemented");
  				ExitStat = EX_USAGE;
  				break;
***************
*** 534,541 ****
  # endif /* SMTP */
  
  			  case MD_INITALIAS:
- - 				/* fall through ... */
- - 
  			  case MD_DELIVER:
  			  case MD_VERIFY:
  			  case MD_TEST:
- --- 532,537 ----
***************
*** 845,862 ****
  	}
  
  	/*
- - 	**  Initialize name server if it is going to be used.
- - 	*/
- - 
- - #if NAMED_BIND
- - 	if (UseNameServer && !bitset(RES_INIT, _res.options))
- - 		res_init();
- - # ifdef RES_NOALIASES
- - 	_res.options |= RES_NOALIASES;
- - # endif
- - #endif
- - 
- - 	/*
  	**  Do more command line checking -- these are things that
  	**  have to modify the results of reading the config file.
  	*/
- --- 841,846 ----
***************
*** 897,904 ****
  	/* check for sane configuration level */
  	if (ConfigLevel > MAXCONFIGLEVEL)
  	{
! 		syserr("Warning: .cf version level (%d) exceeds program functionality (%d)",
! 			ConfigLevel, MAXCONFIGLEVEL);
  	}
  
  	/* need MCI cache to have persistence */
- --- 881,888 ----
  	/* check for sane configuration level */
  	if (ConfigLevel > MAXCONFIGLEVEL)
  	{
! 		syserr("Warning: .cf version level (%d) exceeds sendmail version %s functionality (%d)",
! 			ConfigLevel, Version, MAXCONFIGLEVEL);
  	}
  
  	/* need MCI cache to have persistence */
***************
*** 931,936 ****
- --- 915,933 ----
  		/* fall through ... */
  
  	  case MD_DAEMON:
+ 		/* check for permissions */
+ 		if (RealUid != 0)
+ 		{
+ #ifdef LOG
+ 			if (LogLevel > 1)
+ 				syslog(LOG_ALERT, "user %d attempted to run daemon",
+ 					RealUid);
+ #endif
+ 			usrerr("Permission denied");
+ 			exit(EX_USAGE);
+ 		}
+ 		vendor_daemon_setup(CurEnv);
+ 
  		/* remove things that don't make sense in daemon mode */
  		FullName = NULL;
  		GrabTo = FALSE;
***************
*** 1964,1969 ****
- --- 1961,1975 ----
  		syslog(LOG_INFO, "restarting %s on signal", SaveArgv[0]);
  #endif
  	releasesignal(SIGHUP);
+ 	if (setgid(RealGid) < 0 || setuid(RealUid) < 0)
+ 	{
+ #ifdef LOG
+ 		if (LogLevel > 0)
+ 			syslog(LOG_ALERT, "could not set[ug]id(%d, %d): %m",
+ 				RealUid, RealGid);
+ #endif
+ 		exit(EX_OSERR);
+ 	}
  	execv(SaveArgv[0], (ARGV_T) SaveArgv);
  #ifdef LOG
  	if (LogLevel > 0)
diff -c -r sendmail-8.8.2/src/makesendmail sendmail-8.8.3/src/makesendmail
*** sendmail-8.8.2/src/makesendmail	Mon Sep 23 07:00:30 1996
- --- sendmail-8.8.3/src/makesendmail	Sun Nov 10 11:15:33 1996
***************
*** 32,38 ****
  # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  # SUCH DAMAGE.
  #
! #       @(#)makesendmail	8.41 (Berkeley) 9/23/96
  #
  
  #
- --- 32,38 ----
  # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  # SUCH DAMAGE.
  #
! #       @(#)makesendmail	8.42 (Berkeley) 11/10/96
  #
  
  #
***************
*** 109,114 ****
- --- 109,121 ----
  esac
  
  # tweak operating system type and release
+ node=`uname -n | sed -e 's/\//-/g' -e 's/ //g'`
+ if [ "$os" = "$node" -a "$arch" = "i386" -a "$rel" = 3.2 -a "`uname -v`" = 2 ]
+ then
+ 	# old versions of SCO UNIX set uname -s the same as uname -n
+ 	os=SCO_SV
+ fi
+ 
  case $os
  in
    DYNIX-ptx)	os=PTX;;
diff -c -r sendmail-8.8.2/src/map.c sendmail-8.8.3/src/map.c
*** sendmail-8.8.2/src/map.c	Sat Oct 12 10:12:11 1996
- --- sendmail-8.8.3/src/map.c	Sat Nov 16 18:32:45 1996
***************
*** 33,39 ****
   */
  
  #ifndef lint
! static char sccsid[] = "@(#)map.c	8.140 (Berkeley) 10/12/96";
  #endif /* not lint */
  
  #include "sendmail.h"
- --- 33,39 ----
   */
  
  #ifndef lint
! static char sccsid[] = "@(#)map.c	8.144 (Berkeley) 11/16/96";
  #endif /* not lint */
  
  #include "sendmail.h"
***************
*** 107,113 ****
  extern bool	aliaswait __P((MAP *, char *, int));
  extern bool	extract_canonname __P((char *, char *, char[], int));
  
! #if defined(O_EXLOCK) && HASFLOCK
  # define LOCK_ON_OPEN	1	/* we can open/create a locked file */
  #else
  # define LOCK_ON_OPEN	0	/* no such luck -- bend over backwards */
- --- 107,113 ----
  extern bool	aliaswait __P((MAP *, char *, int));
  extern bool	extract_canonname __P((char *, char *, char[], int));
  
! #if O_EXLOCK && HASFLOCK
  # define LOCK_ON_OPEN	1	/* we can open/create a locked file */
  #else
  # define LOCK_ON_OPEN	0	/* no such luck -- bend over backwards */
***************
*** 690,695 ****
- --- 690,697 ----
  		p = get_column(line, i, '\0', nbuf, sizeof nbuf);
  		if (p == NULL)
  			break;
+ 		if (*p == '\0')
+ 			continue;
  		if (cbuf[0] == '\0' ||
  		    (strchr(cbuf, '.') == NULL && strchr(p, '.') != NULL))
  		{
***************
*** 1034,1050 ****
  **	be pokey about it.  That's hard to do.
  */
  
! extern bool	db_map_open __P((MAP *, int, DBTYPE));
  
  bool
  bt_map_open(map, mode)
  	MAP *map;
  	int mode;
  {
  	if (tTd(38, 2))
  		printf("bt_map_open(%s, %s, %d)\n",
  			map->map_mname, map->map_file, mode);
! 	return db_map_open(map, mode, DB_BTREE);
  }
  
  bool
- --- 1036,1065 ----
  **	be pokey about it.  That's hard to do.
  */
  
! extern bool	db_map_open __P((MAP *, int, DBTYPE, const void *));
! 
! /* these should be K line arguments */
! #ifndef DB_CACHE_SIZE
! # define DB_CACHE_SIZE	(1024 * 1024)	/* database memory cache size */
! #endif
! #ifndef DB_HASH_NELEM
! # define DB_HASH_NELEM	4096		/* (starting) size of hash table */
! #endif
  
  bool
  bt_map_open(map, mode)
  	MAP *map;
  	int mode;
  {
+ 	BTREEINFO btinfo;
+ 
  	if (tTd(38, 2))
  		printf("bt_map_open(%s, %s, %d)\n",
  			map->map_mname, map->map_file, mode);
! 
! 	bzero(&btinfo, sizeof btinfo);
! 	btinfo.cachesize = DB_CACHE_SIZE;
! 	return db_map_open(map, mode, DB_BTREE, &btinfo);
  }
  
  bool
***************
*** 1052,1068 ****
  	MAP *map;
  	int mode;
  {
  	if (tTd(38, 2))
  		printf("hash_map_open(%s, %s, %d)\n",
  			map->map_mname, map->map_file, mode);
! 	return db_map_open(map, mode, DB_HASH);
  }
  
  bool
! db_map_open(map, mode, dbtype)
  	MAP *map;
  	int mode;
  	DBTYPE dbtype;
  {
  	DB *db;
  	int i;
- --- 1067,1090 ----
  	MAP *map;
  	int mode;
  {
+ 	HASHINFO hinfo;
+ 
  	if (tTd(38, 2))
  		printf("hash_map_open(%s, %s, %d)\n",
  			map->map_mname, map->map_file, mode);
! 
! 	bzero(&hinfo, sizeof hinfo);
! 	hinfo.nelem = DB_HASH_NELEM;
! 	hinfo.cachesize = DB_CACHE_SIZE;
! 	return db_map_open(map, mode, DB_HASH, &hinfo);
  }
  
  bool
! db_map_open(map, mode, dbtype, openinfo)
  	MAP *map;
  	int mode;
  	DBTYPE dbtype;
+ 	const void *openinfo;
  {
  	DB *db;
  	int i;
***************
*** 1113,1119 ****
  		omode |= O_TRUNC;
  #endif
  
! 	db = dbopen(buf, omode, DBMMODE, dbtype, NULL);
  	saveerrno = errno;
  
  #if !LOCK_ON_OPEN
- --- 1135,1141 ----
  		omode |= O_TRUNC;
  #endif
  
! 	db = dbopen(buf, omode, DBMMODE, dbtype, openinfo);
  	saveerrno = errno;
  
  #if !LOCK_ON_OPEN
diff -c -r sendmail-8.8.2/src/mci.c sendmail-8.8.3/src/mci.c
*** sendmail-8.8.2/src/mci.c	Wed Oct  9 11:48:43 1996
- --- sendmail-8.8.3/src/mci.c	Sun Nov  3 15:23:30 1996
***************
*** 33,39 ****
   */
  
  #ifndef lint
! static char sccsid[] = "@(#)mci.c	8.44 (Berkeley) 10/9/96";
  #endif /* not lint */
  
  #include "sendmail.h"
- --- 33,39 ----
   */
  
  #ifndef lint
! static char sccsid[] = "@(#)mci.c	8.46 (Berkeley) 11/3/96";
  #endif /* not lint */
  
  #include "sendmail.h"
***************
*** 362,367 ****
- --- 362,368 ----
  **
  **	Parameters:
  **		mci -- the MCI structure to set.
+ **		xstat -- the exit status code.
  **		dstat -- the DSN status code.
  **		rstat -- the SMTP status code.
  **
***************
*** 370,387 ****
  */
  
  void
! mci_setstat(mci, dstat, rstat)
  	MCI *mci;
  	char *dstat;
  	char *rstat;
  {
  	mci->mci_status = dstat;
  	if (rstat != NULL)
! 	{
! 		if (mci->mci_rstatus != NULL)
! 			free(mci->mci_rstatus);
! 		mci->mci_rstatus = newstr(rstat);
! 	}
  }
  /*
  **  MCI_DUMP -- dump the contents of an MCI structure.
- --- 371,389 ----
  */
  
  void
! mci_setstat(mci, xstat, dstat, rstat)
  	MCI *mci;
+ 	int xstat;
  	char *dstat;
  	char *rstat;
  {
+ 	mci->mci_exitstat = xstat;
  	mci->mci_status = dstat;
+ 	if (mci->mci_rstatus != NULL)
+ 		free(mci->mci_rstatus);
  	if (rstat != NULL)
! 		rstat = newstr(rstat);
! 	mci->mci_rstatus = rstat;
  }
  /*
  **  MCI_DUMP -- dump the contents of an MCI structure.
***************
*** 1032,1037 ****
- --- 1034,1040 ----
  	int status;
  	int width = Verbose ? 78 : 25;
  	bool locked;
+ 	char *p;
  	MCI mcib;
  
  	if (!initflag)
***************
*** 1061,1076 ****
  	locked = !lockfile(fileno(fp), pathname, "", LOCK_EX|LOCK_NB);
  	fclose(fp);
  
! 	if (mcib.mci_rstatus == NULL)
! 		printf("%c%-39s %12s %.*s\n",
! 			locked ? '*' : ' ', hostname,
! 			pintvl(curtime() - mcib.mci_lastuse, TRUE),
! 			width, errstring(mcib.mci_errno));
  	else
! 		printf("%c%-39s %12s %.*s\n",
! 			locked ? '*' : ' ', hostname,
! 			pintvl(curtime() - mcib.mci_lastuse, TRUE),
! 			width, mcib.mci_rstatus);
  
  	return 0;
  }
- --- 1064,1097 ----
  	locked = !lockfile(fileno(fp), pathname, "", LOCK_EX|LOCK_NB);
  	fclose(fp);
  
! 	printf("%c%-39s %12s ",
! 		locked ? '*' : ' ', hostname,
! 		pintvl(curtime() - mcib.mci_lastuse, TRUE));
! 	if (mcib.mci_rstatus != NULL)
! 		printf("%.*s\n", width, mcib.mci_rstatus);
! 	else if (mcib.mci_exitstat == EX_TEMPFAIL && mcib.mci_errno != 0)
! 		printf("Deferred: %.*s\n", width - 10, errstring(mcib.mci_errno));
! 	else if (mcib.mci_exitstat != 0)
! 	{
! 		int i = mcib.mci_exitstat - EX__BASE;
! 		extern int N_SysEx;
! 		extern char *SysExMsg[];
! 
! 		if (i < 0 || i > N_SysEx)
! 		{
! 			char buf[80];
! 
! 			snprintf(buf, sizeof buf, "Unknown mailer error %d",
! 				mcib.mci_exitstat);
! 			printf("%.*s\n", width, buf);
! 		}
! 		else
! 			printf("%.*s\n", width, &(SysExMsg[i])[5]);
! 	}
! 	else if (mcib.mci_errno == 0)
! 		printf("OK\n");
  	else
! 		printf("OK: %.*s\n", width - 4, errstring(mcib.mci_errno));
  
  	return 0;
  }
diff -c -r sendmail-8.8.2/src/mime.c sendmail-8.8.3/src/mime.c
*** sendmail-8.8.2/src/mime.c	Fri Oct 18 08:33:00 1996
- --- sendmail-8.8.3/src/mime.c	Wed Oct 30 09:20:43 1996
***************
*** 36,42 ****
  # include <string.h>
  
  #ifndef lint
! static char sccsid[] = "@(#)mime.c	8.48 (Berkeley) 10/18/96";
  #endif /* not lint */
  
  /*
- --- 36,42 ----
  # include <string.h>
  
  #ifndef lint
! static char sccsid[] = "@(#)mime.c	8.49 (Berkeley) 10/30/96";
  #endif /* not lint */
  
  /*
***************
*** 932,940 ****
  **		none.
  */
  
- - extern void	mime_from64 __P((u_char *, u_char *, int));
  extern int	mime_fromqp __P((u_char *, u_char **, int, int));
  
  void
  mime7to8(mci, header, e)
  	register MCI *mci;
- --- 932,954 ----
  **		none.
  */
  
  extern int	mime_fromqp __P((u_char *, u_char **, int, int));
  
+ static char index_64[128] =
+ {
+ 	-1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
+ 	-1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
+ 	-1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,62, -1,-1,-1,63,
+ 	52,53,54,55, 56,57,58,59, 60,61,-1,-1, -1,-1,-1,-1,
+ 	-1, 0, 1, 2,  3, 4, 5, 6,  7, 8, 9,10, 11,12,13,14,
+ 	15,16,17,18, 19,20,21,22, 23,24,25,-1, -1,-1,-1,-1,
+ 	-1,26,27,28, 29,30,31,32, 33,34,35,36, 37,38,39,40,
+ 	41,42,43,44, 45,46,47,48, 49,50,51,-1, -1,-1,-1,-1
+ };
+ 
+ #define CHAR64(c)  (((c) < 0 || (c) > 127) ? -1 : index_64[(c)])
+ 
+ 
  void
  mime7to8(mci, header, e)
  	register MCI *mci;
***************
*** 996,1024 ****
  
  	if (strcasecmp(cte, "base64") == 0)
  	{
  		fbufp = fbuf;
! 		while (fgets(buf, sizeof buf, e->e_dfp) != NULL)
  		{
! 			obufp = obuf;
! 			mime_from64((u_char *) buf, obuf, MAXLINE);
! 			while ((ch = *obufp++) != '\0')
  			{
! 				*fbufp++ = ch;
! 				if (ch == '\n' || fbufp >= &fbuf[MAXLINE])
! 				{
! 					*fbufp = '\0';
! 					putline((char *) fbuf, mci);
! 					fbufp = fbuf;
! 				}
! 			}
  
! 			/* force out partial last line */
! 			if (fbufp > fbuf)
  			{
  				*fbufp = '\0';
  				putline((char *) fbuf, mci);
  			}
  		}
  	}
  	else
  	{
- --- 1010,1091 ----
  
  	if (strcasecmp(cte, "base64") == 0)
  	{
+ 		int nchar = 0;
+ 		int c1, c2, c3, c4;
+ 
  		fbufp = fbuf;
! 		while ((c1 = fgetc(e->e_dfp)) != EOF)
  		{
! 			if (isascii(c1) && isspace(c1))
! 				continue;
! 
! 			do
  			{
! 				c2 = fgetc(e->e_dfp);
! 			} while (isascii(c2) && isspace(c2));
! 			if (c2 == EOF)
! 				break;
  
! 			do
  			{
+ 				c3 = fgetc(e->e_dfp);
+ 			} while (isascii(c3) && isspace(c3));
+ 			if (c3 == EOF)
+ 				break;
+ 
+ 			do
+ 			{
+ 				c4 = fgetc(e->e_dfp);
+ 			} while (isascii(c4) && isspace(c4));
+ 			if (c4 == EOF)
+ 				break;
+ 
+ 			if (c1 == '=' || c2 == '=')
+ 				continue;
+ 			c1 = CHAR64(c1);
+ 			c2 = CHAR64(c2);
+ 
+ 			*fbufp = (c1 << 2) | ((c2 & 0x30) >> 4);
+ 			if (*fbufp++ == '\n' || fbuf >= &fbuf[MAXLINE])
+ 			{
+ 				if (*--fbufp != '\n' || *--fbufp != '\r')
+ 					fbufp++;
+ 				*fbufp = '\0';
+ 				putline((char *) fbuf, mci);
+ 				fbufp = fbuf;
+ 			}
+ 			if (c3 == '=')
+ 				continue;
+ 			c3 = CHAR64(c3);
+ 			*fbufp = ((c2 & 0x0f) << 4) | ((c3 & 0x3c) >> 2);
+ 			if (*fbufp++ == '\n' || fbuf >= &fbuf[MAXLINE])
+ 			{
+ 				if (*--fbufp != '\n' || *--fbufp != '\r')
+ 					fbufp++;
+ 				*fbufp = '\0';
+ 				putline((char *) fbuf, mci);
+ 				fbufp = fbuf;
+ 			}
+ 			if (c4 == '=')
+ 				continue;
+ 			c4 = CHAR64(c4);
+ 			*fbufp = ((c3 & 0x03) << 6) | c4;
+ 			if (*fbufp++ == '\n' || fbuf >= &fbuf[MAXLINE])
+ 			{
+ 				if (*--fbufp != '\n' || *--fbufp != '\r')
+ 					fbufp++;
  				*fbufp = '\0';
  				putline((char *) fbuf, mci);
+ 				fbufp = fbuf;
  			}
  		}
+ 
+ 		/* force out partial last line */
+ 		if (fbufp > fbuf)
+ 		{
+ 			*fbufp = '\0';
+ 			putline((char *) fbuf, mci);
+ 		}
  	}
  	else
  	{
***************
*** 1113,1201 ****
  	return 1;
  }
  
- - static char index_64[128] =
- - {
- - 	-1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
- - 	-1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
- - 	-1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,62, -1,-1,-1,63,
- - 	52,53,54,55, 56,57,58,59, 60,61,-1,-1, -1,-1,-1,-1,
- - 	-1, 0, 1, 2,  3, 4, 5, 6,  7, 8, 9,10, 11,12,13,14,
- - 	15,16,17,18, 19,20,21,22, 23,24,25,-1, -1,-1,-1,-1,
- - 	-1,26,27,28, 29,30,31,32, 33,34,35,36, 37,38,39,40,
- - 	41,42,43,44, 45,46,47,48, 49,50,51,-1, -1,-1,-1,-1
- - };
- - 
- - #define CHAR64(c)  (((c) < 0 || (c) > 127) ? -1 : index_64[(c)])
- - 
- - void
- - mime_from64(infile, outfile, maxlen)
- - 	u_char *infile;
- - 	u_char *outfile;
- - 	int maxlen;
- - {
- - 	int nchar = 0;
- - 	int c1, c2, c3, c4;
- - 
- - 	while ((c1 = *infile++) != '\0')
- - 	{
- - 		if (isascii(c1) && isspace(c1))
- - 			continue;
- - 
- - 		do
- - 		{
- - 			c2 = *infile++;
- - 		} while (isascii(c2) && isspace(c2));
- - 		if (c2 == '\0')
- - 			break;
- - 
- - 		do
- - 		{
- - 			c3 = *infile++;
- - 		} while (isascii(c3) && isspace(c3));
- - 		if (c3 == '\0')
- - 			break;
- - 
- - 		do
- - 		{
- - 			c4 = *infile++;
- - 		} while (isascii(c4) && isspace(c4));
- - 		if (c4 == '\0')
- - 			break;
- - 
- - 		if (c1 == '=' || c2 == '=')
- - 		{
- - 			continue;
- - 		}
- - 		c1 = CHAR64(c1);
- - 		c2 = CHAR64(c2);
- - 
- - 		if (++nchar > maxlen)
- - 			break;
- - 
- - 		*outfile++ = (c1 << 2) | ((c2 & 0x30) >> 4);
- - 
- - 		if (c3 != '=')
- - 		{
- - 			c3 = CHAR64(c3);
- - 
- - 			if (++nchar > maxlen)
- - 				break;
- - 
- - 			*outfile++ = ((c2 & 0x0f) << 4) | ((c3 & 0x3c) >> 2);
- - 			if (c4 != '=')
- - 			{
- - 				c4 = CHAR64(c4);
- - 
- - 				if (++nchar > maxlen)
- - 					break;
- - 
- - 				*outfile++ = ((c3 & 0x03) << 6) | c4;
- - 			}
- - 		}
- - 	}
- - 
- - 	*outfile = '\0';
- - 	return;
- - }
  
  #endif /* MIME7TO8 */
- --- 1180,1184 ----
diff -c -r sendmail-8.8.2/src/queue.c sendmail-8.8.3/src/queue.c
*** sendmail-8.8.2/src/queue.c	Sat Oct 12 13:35:12 1996
- --- sendmail-8.8.3/src/queue.c	Sun Nov 10 14:04:48 1996
***************
*** 36,44 ****
  
  #ifndef lint
  #ifdef QUEUE
! static char sccsid[] = "@(#)queue.c	8.125 (Berkeley) 10/12/96 (with queueing)";
  #else
! static char sccsid[] = "@(#)queue.c	8.125 (Berkeley) 10/12/96 (without queueing)";
  #endif
  #endif /* not lint */
  
- --- 36,44 ----
  
  #ifndef lint
  #ifdef QUEUE
! static char sccsid[] = "@(#)queue.c	8.131 (Berkeley) 11/8/96 (with queueing)";
  #else
! static char sccsid[] = "@(#)queue.c	8.131 (Berkeley) 11/8/96 (without queueing)";
  #endif
  #endif /* not lint */
  
***************
*** 296,335 ****
  	printctladdr(NULL, NULL);
  	for (q = e->e_sendqueue; q != NULL; q = q->q_next)
  	{
! 		if (bitset(QQUEUEUP, q->q_flags) ||
! 		    !bitset(QDONTSEND|QBADADDR|QSENT, q->q_flags))
  		{
! 			printctladdr(q, tfp);
! 			if (q->q_orcpt != NULL)
! 				fprintf(tfp, "Q%s\n",
! 					denlstring(q->q_orcpt, TRUE, FALSE));
! 			putc('R', tfp);
! 			if (bitset(QPRIMARY, q->q_flags))
! 				putc('P', tfp);
! 			if (bitset(QHASNOTIFY, q->q_flags))
! 				putc('N', tfp);
! 			if (bitset(QPINGONSUCCESS, q->q_flags))
! 				putc('S', tfp);
! 			if (bitset(QPINGONFAILURE, q->q_flags))
! 				putc('F', tfp);
! 			if (bitset(QPINGONDELAY, q->q_flags))
! 				putc('D', tfp);
! 			putc(':', tfp);
! 			fprintf(tfp, "%s\n", denlstring(q->q_paddr, TRUE, FALSE));
! 			if (announce)
! 			{
! 				e->e_to = q->q_paddr;
! 				message("queued");
! 				if (LogLevel > 8)
! 					logdelivery(q->q_mailer, NULL, "queued",
! 						    NULL, (time_t) 0, e);
! 				e->e_to = NULL;
! 			}
! 			if (tTd(40, 1))
! 			{
! 				printf("queueing ");
! 				printaddr(q, FALSE);
! 			}
  		}
  	}
  
- --- 296,340 ----
  	printctladdr(NULL, NULL);
  	for (q = e->e_sendqueue; q != NULL; q = q->q_next)
  	{
! 		if (bitset(QDONTSEND|QBADADDR|QSENT, q->q_flags))
  		{
! #if XDEBUG
! 			if (bitset(QQUEUEUP, q->q_flags))
! 				syslog(LOG_DEBUG, "%s: q_flags = %x",
! 					e->e_id, q->q_flags);
! #endif
! 			continue;
! 		}
! 		printctladdr(q, tfp);
! 		if (q->q_orcpt != NULL)
! 			fprintf(tfp, "Q%s\n",
! 				denlstring(q->q_orcpt, TRUE, FALSE));
! 		putc('R', tfp);
! 		if (bitset(QPRIMARY, q->q_flags))
! 			putc('P', tfp);
! 		if (bitset(QHASNOTIFY, q->q_flags))
! 			putc('N', tfp);
! 		if (bitset(QPINGONSUCCESS, q->q_flags))
! 			putc('S', tfp);
! 		if (bitset(QPINGONFAILURE, q->q_flags))
! 			putc('F', tfp);
! 		if (bitset(QPINGONDELAY, q->q_flags))
! 			putc('D', tfp);
! 		putc(':', tfp);
! 		fprintf(tfp, "%s\n", denlstring(q->q_paddr, TRUE, FALSE));
! 		if (announce)
! 		{
! 			e->e_to = q->q_paddr;
! 			message("queued");
! 			if (LogLevel > 8)
! 				logdelivery(q->q_mailer, NULL, "queued",
! 					    NULL, (time_t) 0, e);
! 			e->e_to = NULL;
! 		}
! 		if (tTd(40, 1))
! 		{
! 			printf("queueing ");
! 			printaddr(q, FALSE);
  		}
  	}
  
***************
*** 574,580 ****
  
  	if (forkflag)
  	{
! 		int pid;
  		extern void intsig();
  #ifdef SIGCHLD
  		extern void reapchild();
- --- 579,585 ----
  
  	if (forkflag)
  	{
! 		pid_t pid;
  		extern void intsig();
  #ifdef SIGCHLD
  		extern void reapchild();
***************
*** 625,630 ****
- --- 630,644 ----
  	/* force it to run expensive jobs */
  	NoConnect = FALSE;
  
+ 	/* drop privileges */
+ 	if (geteuid() == (uid_t) 0)
+ 	{
+ 		if (RunAsGid != (gid_t) 0)
+ 			(void) setgid(RunAsGid);
+ 		if (RunAsUid != (uid_t) 0)
+ 			(void) setuid(RunAsUid);
+ 	}
+ 
  	/*
  	**  Create ourselves an envelope
  	*/
***************
*** 1387,1392 ****
- --- 1401,1407 ----
  	struct stat st;
  	char *bp;
  	int qfver = 0;
+ 	long hdrsize = 0;
  	register char *p;
  	char *orcpt = NULL;
  	bool nomore = FALSE;
***************
*** 1579,1584 ****
- --- 1594,1600 ----
  
  		  case 'H':		/* header */
  			(void) chompheader(&bp[1], FALSE, NULL, e);
+ 			hdrsize += strlen(&bp[1]);
  			break;
  
  		  case 'M':		/* message */
***************
*** 1611,1616 ****
- --- 1627,1652 ----
  
  		  case 'N':		/* number of delivery attempts */
  			e->e_ntries = atoi(&buf[1]);
+ 
+ 			/* if this has been tried recently, let it be */
+ 			if (e->e_ntries > 0 &&
+ 			    (curtime() - e->e_dtime) < MinQueueAge)
+ 			{
+ 				char *howlong = pintvl(curtime() - e->e_dtime, TRUE);
+ 				extern void unlockqueue();
+ 
+ 				if (Verbose || tTd(40, 8))
+ 					printf("%s: too young (%s)\n",
+ 						e->e_id, howlong);
+ #ifdef LOG
+ 				if (LogLevel > 19)
+ 					syslog(LOG_DEBUG, "%s: too young (%s)",
+ 						e->e_id, howlong);
+ #endif
+ 				e->e_id = NULL;
+ 				unlockqueue(e);
+ 				return FALSE;
+ 			}
  			break;
  
  		  case 'P':		/* message priority */
***************
*** 1694,1718 ****
  		return TRUE;
  	}
  
- - 	/* if this has been tried recently, let it be */
- - 	if (e->e_ntries > 0 && (curtime() - e->e_dtime) < MinQueueAge)
- - 	{
- - 		char *howlong = pintvl(curtime() - e->e_dtime, TRUE);
- - 		extern void unlockqueue();
- - 
- - 		if (Verbose || tTd(40, 8))
- - 			printf("%s: too young (%s)\n",
- - 				e->e_id, howlong);
- - #ifdef LOG
- - 		if (LogLevel > 19)
- - 			syslog(LOG_DEBUG, "%s: too young (%s)",
- - 				e->e_id, howlong);
- - #endif
- - 		e->e_id = NULL;
- - 		unlockqueue(e);
- - 		return FALSE;
- - 	}
- - 
  	/*
  	**  Arrange to read the data file.
  	*/
- --- 1730,1735 ----
***************
*** 1728,1734 ****
  		e->e_flags |= EF_HAS_DF;
  		if (fstat(fileno(e->e_dfp), &st) >= 0)
  		{
! 			e->e_msgsize = st.st_size;
  			e->e_dfdev = st.st_dev;
  			e->e_dfino = st.st_ino;
  		}
- --- 1745,1751 ----
  		e->e_flags |= EF_HAS_DF;
  		if (fstat(fileno(e->e_dfp), &st) >= 0)
  		{
! 			e->e_msgsize = st.st_size + hdrsize;
  			e->e_dfdev = st.st_dev;
  			e->e_dfino = st.st_ino;
  		}
***************
*** 1971,1977 ****
  	register ENVELOPE *e;
  	int type;
  {
! 	static int pid = -1;
  	static char c0;
  	static char c1;
  	static char c2;
- --- 1988,1994 ----
  	register ENVELOPE *e;
  	int type;
  {
! 	static pid_t pid = -1;
  	static char c0;
  	static char c1;
  	static char c2;
diff -c -r sendmail-8.8.2/src/readcf.c sendmail-8.8.3/src/readcf.c
*** sendmail-8.8.2/src/readcf.c	Wed Oct  9 11:46:22 1996
- --- sendmail-8.8.3/src/readcf.c	Sun Nov 10 10:25:26 1996
***************
*** 33,39 ****
   */
  
  #ifndef lint
! static char sccsid[] = "@(#)readcf.c	8.174 (Berkeley) 10/9/96";
  #endif /* not lint */
  
  # include "sendmail.h"
- --- 33,39 ----
   */
  
  #ifndef lint
! static char sccsid[] = "@(#)readcf.c	8.176 (Berkeley) 11/10/96";
  #endif /* not lint */
  
  # include "sendmail.h"
***************
*** 715,721 ****
  {
  	FILE *f;
  	int sff;
! 	int pid;
  	register char *p;
  	char buf[MAXLINE];
  
- --- 715,721 ----
  {
  	FILE *f;
  	int sff;
! 	pid_t pid;
  	register char *p;
  	char buf[MAXLINE];
  
***************
*** 1024,1029 ****
- --- 1024,1033 ----
  
  				m->m_uid = strtol(p, &q, 0);
  				p = q;
+ 				while (isascii(*p) && isspace(*p))
+ 					p++;
+ 				if (*p != '\0')
+ 					p++;
  			}
  			while (isascii(*p) && isspace(*p))
  				p++;
diff -c -r sendmail-8.8.2/src/sendmail.h sendmail-8.8.3/src/sendmail.h
*** sendmail-8.8.2/src/sendmail.h	Thu Oct 17 18:09:15 1996
- --- sendmail-8.8.3/src/sendmail.h	Fri Nov  8 09:09:26 1996
***************
*** 31,37 ****
   * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   *
!  *	@(#)sendmail.h	8.206 (Berkeley) 10/17/96
   */
  
  /*
- --- 31,37 ----
   * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   *
!  *	@(#)sendmail.h	8.209 (Berkeley) 11/8/96
   */
  
  /*
***************
*** 41,47 ****
  # ifdef _DEFINE
  # define EXTERN
  # ifndef lint
! static char SmailSccsId[] =	"@(#)sendmail.h	8.206		10/17/96";
  # endif
  # else /*  _DEFINE */
  # define EXTERN extern
- --- 41,47 ----
  # ifdef _DEFINE
  # define EXTERN
  # ifndef lint
! static char SmailSccsId[] =	"@(#)sendmail.h	8.209		11/8/96";
  # endif
  # else /*  _DEFINE */
  # define EXTERN extern
***************
*** 275,280 ****
- --- 275,281 ----
  # define M_HASPWENT	'w'	/* check for /etc/passwd entry */
  		/*	'x'	   CF: include Full-Name: */
  # define M_XDOT		'X'	/* use hidden-dot algorithm */
+ # define M_LMTP		'z'	/* run Local Mail Transport Protocol */
  # define M_NOMX		'0'	/* turn off MX lookups */
  # define M_EBCDIC	'3'	/* extend Q-P encoding for EBCDIC */
  # define M_TRYRULESET5	'5'	/* use ruleset 5 after local aliasing */
***************
*** 310,316 ****
  	long		mci_maxsize;	/* max size this server will accept */
  	FILE		*mci_in;	/* input side of connection */
  	FILE		*mci_out;	/* output side of connection */
! 	int		mci_pid;	/* process id of subordinate proc */
  	char		*mci_phase;	/* SMTP phase string */
  	struct mailer	*mci_mailer;	/* ptr to the mailer for this conn */
  	char		*mci_host;	/* host name */
- --- 311,317 ----
  	long		mci_maxsize;	/* max size this server will accept */
  	FILE		*mci_in;	/* input side of connection */
  	FILE		*mci_out;	/* output side of connection */
! 	pid_t		mci_pid;	/* process id of subordinate proc */
  	char		*mci_phase;	/* SMTP phase string */
  	struct mailer	*mci_mailer;	/* ptr to the mailer for this conn */
  	char		*mci_host;	/* host name */
***************
*** 1095,1101 ****
  EXTERN uid_t	DefUid;		/* default uid to run as */
  EXTERN gid_t	DefGid;		/* default gid to run as */
  EXTERN char	*DefUser;	/* default user to run as (from DefUid) */
! EXTERN int	OldUmask;	/* umask when sendmail starts up */
  EXTERN int	Errors;		/* set if errors (local to single pass) */
  EXTERN int	ExitStat;	/* exit status code */
  EXTERN int	LineNumber;	/* line number in current input */
- --- 1096,1102 ----
  EXTERN uid_t	DefUid;		/* default uid to run as */
  EXTERN gid_t	DefGid;		/* default gid to run as */
  EXTERN char	*DefUser;	/* default user to run as (from DefUid) */
! EXTERN MODE_T	OldUmask;	/* umask when sendmail starts up */
  EXTERN int	Errors;		/* set if errors (local to single pass) */
  EXTERN int	ExitStat;	/* exit status code */
  EXTERN int	LineNumber;	/* line number in current input */
***************
*** 1303,1309 ****
  extern void	logdelivery __P((MAILER *, MCI *, const char *, ADDRESS *, time_t, ENVELOPE *));
  extern void	giveresponse __P((int, MAILER *, MCI *, ADDRESS *, time_t, ENVELOPE *));
  extern void	buildfname __P((char *, char *, char *, int));
! extern void	mci_setstat __P((MCI *, char *, char *));
  extern char	*smtptodsn __P((int));
  extern int	rscheck __P((char *, char *, char *, ENVELOPE *e));
  extern void	mime7to8 __P((MCI *, HDR *, ENVELOPE *));
- --- 1304,1310 ----
  extern void	logdelivery __P((MAILER *, MCI *, const char *, ADDRESS *, time_t, ENVELOPE *));
  extern void	giveresponse __P((int, MAILER *, MCI *, ADDRESS *, time_t, ENVELOPE *));
  extern void	buildfname __P((char *, char *, char *, int));
! extern void	mci_setstat __P((MCI *, int, char *, char *));
  extern char	*smtptodsn __P((int));
  extern int	rscheck __P((char *, char *, char *, ENVELOPE *e));
  extern void	mime7to8 __P((MCI *, HDR *, ENVELOPE *));
diff -c -r sendmail-8.8.2/src/srvrsmtp.c sendmail-8.8.3/src/srvrsmtp.c
*** sendmail-8.8.2/src/srvrsmtp.c	Fri Oct 18 08:27:47 1996
- --- sendmail-8.8.3/src/srvrsmtp.c	Sun Nov 10 13:55:16 1996
***************
*** 36,44 ****
  
  #ifndef lint
  #ifdef SMTP
! static char sccsid[] = "@(#)srvrsmtp.c	8.123 (Berkeley) 10/12/96 (with SMTP)";
  #else
! static char sccsid[] = "@(#)srvrsmtp.c	8.123 (Berkeley) 10/12/96 (without SMTP)";
  #endif
  #endif /* not lint */
  
- --- 36,44 ----
  
  #ifndef lint
  #ifdef SMTP
! static char sccsid[] = "@(#)srvrsmtp.c	8.125 (Berkeley) 11/8/96 (with SMTP)";
  #else
! static char sccsid[] = "@(#)srvrsmtp.c	8.125 (Berkeley) 11/8/96 (without SMTP)";
  #endif
  #endif /* not lint */
  
***************
*** 1270,1279 ****
  	char *label;
  	register ENVELOPE *e;
  {
! 	int childpid;
  
  	if (!OneXact)
  	{
  		childpid = dofork();
  		if (childpid < 0)
  		{
- --- 1270,1289 ----
  	char *label;
  	register ENVELOPE *e;
  {
! 	pid_t childpid;
! 	sigfunc_t chldsig;
  
  	if (!OneXact)
  	{
+ 		/*
+ 		**  Disable child process reaping, in case ETRN has preceeded
+ 		**  MAIL command.
+ 		*/
+ 
+ #ifdef SIGCHLD
+ 		chldsig = setsignal(SIGCHLD, SIG_IGN);
+ #endif
+ 
  		childpid = dofork();
  		if (childpid < 0)
  		{
***************
*** 1299,1304 ****
- --- 1309,1319 ----
  				disconnect(1, e);
  				finis();
  			}
+ 
+ #ifdef SIGCHLD
+ 			/* restore the child signal */
+ 			(void) setsignal(SIGCHLD, chldsig);
+ #endif
  
  			return (1);
  		}
diff -c -r sendmail-8.8.2/src/usersmtp.c sendmail-8.8.3/src/usersmtp.c
*** sendmail-8.8.2/src/usersmtp.c	Sun Sep 15 11:46:25 1996
- --- sendmail-8.8.3/src/usersmtp.c	Sat Nov 16 07:40:07 1996
***************
*** 36,44 ****
  
  #ifndef lint
  #ifdef SMTP
! static char sccsid[] = "@(#)usersmtp.c	8.72 (Berkeley) 9/15/96 (with SMTP)";
  #else
! static char sccsid[] = "@(#)usersmtp.c	8.72 (Berkeley) 9/15/96 (without SMTP)";
  #endif
  #endif /* not lint */
  
- --- 36,44 ----
  
  #ifndef lint
  #ifdef SMTP
! static char sccsid[] = "@(#)usersmtp.c	8.75 (Berkeley) 11/6/96 (with SMTP)";
  #else
! static char sccsid[] = "@(#)usersmtp.c	8.75 (Berkeley) 11/6/96 (without SMTP)";
  #endif
  #endif /* not lint */
  
***************
*** 143,150 ****
  	SmtpPhase = mci->mci_phase = "client greeting";
  	setproctitle("%s %s: %s", e->e_id, CurHostName, mci->mci_phase);
  	r = reply(m, mci, e, TimeOuts.to_initial, esmtp_check);
! 	if (r < 0 || REPLYTYPE(r) == 4)
  		goto tempfail1;
  	if (REPLYTYPE(r) != 2)
  		goto unavailable;
  
- --- 143,152 ----
  	SmtpPhase = mci->mci_phase = "client greeting";
  	setproctitle("%s %s: %s", e->e_id, CurHostName, mci->mci_phase);
  	r = reply(m, mci, e, TimeOuts.to_initial, esmtp_check);
! 	if (r < 0)
  		goto tempfail1;
+ 	if (REPLYTYPE(r) == 4)
+ 		goto tempfail2;
  	if (REPLYTYPE(r) != 2)
  		goto unavailable;
  
***************
*** 153,163 ****
- --- 155,178 ----
  	**	My mother taught me to always introduce myself.
  	*/
  
+ #if FFR_LMTP
+ 	if (bitnset(M_ESMTP, m->m_flags) || bitnset(M_LMTP, m->m_flags))
+ #else
  	if (bitnset(M_ESMTP, m->m_flags))
+ #endif
  		mci->mci_flags |= MCIF_ESMTP;
  
  tryhelo:
+ #if FFR_LMTP
+ 	if (bitnset(M_LMTP, m->m_flags))
+ 	{
+ 		smtpmessage("LHLO %s", m, mci, MyHostName);
+ 		SmtpPhase = mci->mci_phase = "client LHLO";
+ 	}
+ 	else if (bitset(MCIF_ESMTP, mci->mci_flags))
+ #else
  	if (bitset(MCIF_ESMTP, mci->mci_flags))
+ #endif
  	{
  		smtpmessage("EHLO %s", m, mci, MyHostName);
  		SmtpPhase = mci->mci_phase = "client EHLO";
***************
*** 173,179 ****
- --- 188,199 ----
  		goto tempfail1;
  	else if (REPLYTYPE(r) == 5)
  	{
+ #if FFR_LMTP
+ 		if (bitset(MCIF_ESMTP, mci->mci_flags) &&
+ 		    !bitnset(M_LMTP, m->m_flags))
+ #else
  		if (bitset(MCIF_ESMTP, mci->mci_flags))
+ #endif
  		{
  			/* try old SMTP instead */
  			mci->mci_flags &= ~MCIF_ESMTP;
***************
*** 182,188 ****
  		goto unavailable;
  	}
  	else if (REPLYTYPE(r) != 2)
! 		goto tempfail1;
  
  	/*
  	**  Check to see if we actually ended up talking to ourself.
- --- 202,208 ----
  		goto unavailable;
  	}
  	else if (REPLYTYPE(r) != 2)
! 		goto tempfail2;
  
  	/*
  	**  Check to see if we actually ended up talking to ourself.
***************
*** 194,204 ****
  	if (p != NULL)
  		*p = '\0';
  	if (!bitnset(M_NOLOOPCHECK, m->m_flags) &&
  	    strcasecmp(&SmtpReplyBuffer[4], MyHostName) == 0)
  	{
  		syserr("553 %s config error: mail loops back to me (MX problem?)",
  			mci->mci_host);
! 		mci->mci_exitstat = EX_CONFIG;
  		mci->mci_errno = 0;
  		smtpquit(m, mci, e);
  		return;
- --- 214,227 ----
  	if (p != NULL)
  		*p = '\0';
  	if (!bitnset(M_NOLOOPCHECK, m->m_flags) &&
+ #if FFR_LMTP
+ 	    !bitnset(M_LMTP, m->m_flags) &&
+ #endif
  	    strcasecmp(&SmtpReplyBuffer[4], MyHostName) == 0)
  	{
  		syserr("553 %s config error: mail loops back to me (MX problem?)",
  			mci->mci_host);
! 		mci_setstat(mci, EX_CONFIG, NULL, NULL);
  		mci->mci_errno = 0;
  		smtpquit(m, mci, e);
  		return;
***************
*** 215,221 ****
  		smtpmessage("VERB", m, mci);
  		r = reply(m, mci, e, TimeOuts.to_miscshort, NULL);
  		if (r < 0)
! 			goto tempfail2;
  	}
  
  	if (mci->mci_state != MCIS_CLOSED)
- --- 238,244 ----
  		smtpmessage("VERB", m, mci);
  		r = reply(m, mci, e, TimeOuts.to_miscshort, NULL);
  		if (r < 0)
! 			goto tempfail1;
  	}
  
  	if (mci->mci_state != MCIS_CLOSED)
***************
*** 227,243 ****
  	/* got a 421 error code during startup */
  
    tempfail1:
    tempfail2:
- - 	mci->mci_exitstat = EX_TEMPFAIL;
  	if (mci->mci_errno == 0)
  		mci->mci_errno = errno;
  	if (mci->mci_state != MCIS_CLOSED)
  		smtpquit(m, mci, e);
  	return;
  
    unavailable:
- - 	mci->mci_exitstat = EX_UNAVAILABLE;
  	mci->mci_errno = errno;
  	smtpquit(m, mci, e);
  	return;
  }
- --- 250,274 ----
  	/* got a 421 error code during startup */
  
    tempfail1:
+ 	if (mci->mci_errno == 0)
+ 		mci->mci_errno = errno;
+ 	mci_setstat(mci, EX_TEMPFAIL, "4.4.2", NULL);
+ 	if (mci->mci_state != MCIS_CLOSED)
+ 		smtpquit(m, mci, e);
+ 	return;
+ 
    tempfail2:
  	if (mci->mci_errno == 0)
  		mci->mci_errno = errno;
+ 	/* XXX should use code from other end iff ENHANCEDSTATUSCODES */
+ 	mci_setstat(mci, EX_TEMPFAIL, "4.5.0", SmtpReplyBuffer);
  	if (mci->mci_state != MCIS_CLOSED)
  		smtpquit(m, mci, e);
  	return;
  
    unavailable:
  	mci->mci_errno = errno;
+ 	mci_setstat(mci, EX_UNAVAILABLE, "5.5.0", SmtpReplyBuffer);
  	smtpquit(m, mci, e);
  	return;
  }
***************
*** 387,393 ****
  		extern char MsgBuf[];
  
  		usrerr("%s does not support 8BITMIME", mci->mci_host);
! 		mci_setstat(mci, "5.6.3", MsgBuf);
  		return EX_DATAERR;
  	}
  
- --- 418,424 ----
  		extern char MsgBuf[];
  
  		usrerr("%s does not support 8BITMIME", mci->mci_host);
! 		mci_setstat(mci, EX_DATAERR, "5.6.3", MsgBuf);
  		return EX_DATAERR;
  	}
  
***************
*** 447,463 ****
  	SmtpPhase = mci->mci_phase = "client MAIL";
  	setproctitle("%s %s: %s", e->e_id, CurHostName, mci->mci_phase);
  	r = reply(m, mci, e, TimeOuts.to_mail, NULL);
! 	if (r < 0 || r == 421)
  	{
! 		/* communications failure/service shutting down */
! 		mci->mci_exitstat = EX_TEMPFAIL;
  		mci->mci_errno = errno;
  		smtpquit(m, mci, e);
  		return EX_TEMPFAIL;
  	}
  	else if (REPLYTYPE(r) == 4)
  	{
! 		mci_setstat(mci, smtptodsn(r), SmtpReplyBuffer);
  		return EX_TEMPFAIL;
  	}
  	else if (REPLYTYPE(r) == 2)
- --- 478,501 ----
  	SmtpPhase = mci->mci_phase = "client MAIL";
  	setproctitle("%s %s: %s", e->e_id, CurHostName, mci->mci_phase);
  	r = reply(m, mci, e, TimeOuts.to_mail, NULL);
! 	if (r < 0)
  	{
! 		/* communications failure */
  		mci->mci_errno = errno;
+ 		mci_setstat(mci, EX_TEMPFAIL, "4.4.2", NULL);
+ 		smtpquit(m, mci, e);
+ 		return EX_TEMPFAIL;
+ 	}
+ 	else if (r == 421)
+ 	{
+ 		/* service shutting down */
+ 		mci_setstat(mci, EX_TEMPFAIL, "4.5.0", SmtpReplyBuffer);
  		smtpquit(m, mci, e);
  		return EX_TEMPFAIL;
  	}
  	else if (REPLYTYPE(r) == 4)
  	{
! 		mci_setstat(mci, EX_TEMPFAIL, smtptodsn(r), SmtpReplyBuffer);
  		return EX_TEMPFAIL;
  	}
  	else if (REPLYTYPE(r) == 2)
***************
*** 467,491 ****
  	else if (r == 501)
  	{
  		/* syntax error in arguments */
! 		mci_setstat(mci, "5.5.2", SmtpReplyBuffer);
  		return EX_DATAERR;
  	}
  	else if (r == 553)
  	{
  		/* mailbox name not allowed */
! 		mci_setstat(mci, "5.1.3", SmtpReplyBuffer);
  		return EX_DATAERR;
  	}
  	else if (r == 552)
  	{
  		/* exceeded storage allocation */
! 		mci_setstat(mci, "5.2.2", SmtpReplyBuffer);
  		return EX_UNAVAILABLE;
  	}
  	else if (REPLYTYPE(r) == 5)
  	{
  		/* unknown error */
! 		mci_setstat(mci, "5.0.0", SmtpReplyBuffer);
  		return EX_UNAVAILABLE;
  	}
  
- --- 505,529 ----
  	else if (r == 501)
  	{
  		/* syntax error in arguments */
! 		mci_setstat(mci, EX_DATAERR, "5.5.2", SmtpReplyBuffer);
  		return EX_DATAERR;
  	}
  	else if (r == 553)
  	{
  		/* mailbox name not allowed */
! 		mci_setstat(mci, EX_DATAERR, "5.1.3", SmtpReplyBuffer);
  		return EX_DATAERR;
  	}
  	else if (r == 552)
  	{
  		/* exceeded storage allocation */
! 		mci_setstat(mci, EX_UNAVAILABLE, "5.2.2", SmtpReplyBuffer);
  		return EX_UNAVAILABLE;
  	}
  	else if (REPLYTYPE(r) == 5)
  	{
  		/* unknown error */
! 		mci_setstat(mci, EX_UNAVAILABLE, "5.0.0", SmtpReplyBuffer);
  		return EX_UNAVAILABLE;
  	}
  
***************
*** 499,505 ****
  #endif
  
  	/* protocol error -- close up */
! 	mci_setstat(mci, "5.5.1", SmtpReplyBuffer);
  	smtpquit(m, mci, e);
  	return EX_PROTOCOL;
  }
- --- 537,543 ----
  #endif
  
  	/* protocol error -- close up */
! 	mci_setstat(mci, EX_PROTOCOL, "5.5.1", SmtpReplyBuffer);
  	smtpquit(m, mci, e);
  	return EX_PROTOCOL;
  }
***************
*** 536,542 ****
  	{
  		/* NOTIFY= parameter */
  		if (bitset(QHASNOTIFY, to->q_flags) &&
! 		    bitset(QPRIMARY, to->q_flags))
  		{
  			bool firstone = TRUE;
  
- --- 574,581 ----
  	{
  		/* NOTIFY= parameter */
  		if (bitset(QHASNOTIFY, to->q_flags) &&
! 		    bitset(QPRIMARY, to->q_flags) &&
! 		    !bitnset(M_LOCALMAILER, m->m_flags))
  		{
  			bool firstone = TRUE;
  
***************
*** 622,627 ****
- --- 661,667 ----
  **
  **	Parameters:
  **		m -- mailer being sent to.
+ **		mci -- the mailer connection information.
  **		e -- the envelope for this message.
  **
  **	Returns:
***************
*** 642,647 ****
- --- 682,688 ----
  {
  	register int r;
  	register EVENT *ev;
+ 	int rstat;
  	time_t timeout;
  
  	/*
***************
*** 690,697 ****
  	if (setjmp(CtxDataTimeout) != 0)
  	{
  		mci->mci_errno = errno;
- - 		mci->mci_exitstat = EX_TEMPFAIL;
  		mci->mci_state = MCIS_ERROR;
  		syserr("451 timeout writing message to %s", mci->mci_host);
  		smtpquit(m, mci, e);
  		return EX_TEMPFAIL;
- --- 731,738 ----
  	if (setjmp(CtxDataTimeout) != 0)
  	{
  		mci->mci_errno = errno;
  		mci->mci_state = MCIS_ERROR;
+ 		mci_setstat(mci, EX_TEMPFAIL, "4.4.2", NULL);
  		syserr("451 timeout writing message to %s", mci->mci_host);
  		smtpquit(m, mci, e);
  		return EX_TEMPFAIL;
***************
*** 720,727 ****
  	{
  		/* error during processing -- don't send the dot */
  		mci->mci_errno = EIO;
- - 		mci->mci_exitstat = EX_IOERR;
  		mci->mci_state = MCIS_ERROR;
  		smtpquit(m, mci, e);
  		return EX_IOERR;
  	}
- --- 761,768 ----
  	{
  		/* error during processing -- don't send the dot */
  		mci->mci_errno = EIO;
  		mci->mci_state = MCIS_ERROR;
+ 		mci_setstat(mci, EX_IOERR, "4.4.2", NULL);
  		smtpquit(m, mci, e);
  		return EX_IOERR;
  	}
***************
*** 734,741 ****
  		nmessage(">>> .");
  
  	/* check for the results of the transaction */
! 	SmtpPhase = mci->mci_phase = "client DATA 250";
  	setproctitle("%s %s: %s", e->e_id, CurHostName, mci->mci_phase);
  	r = reply(m, mci, e, TimeOuts.to_datafinal, NULL);
  	if (r < 0)
  	{
- --- 775,786 ----
  		nmessage(">>> .");
  
  	/* check for the results of the transaction */
! 	SmtpPhase = mci->mci_phase = "client DATA status";
  	setproctitle("%s %s: %s", e->e_id, CurHostName, mci->mci_phase);
+ #if FFR_LMTP
+ 	if (bitnset(M_LMTP, m->m_flags))
+ 		return EX_OK;
+ #endif
  	r = reply(m, mci, e, TimeOuts.to_datafinal, NULL);
  	if (r < 0)
  	{
***************
*** 743,758 ****
  		return EX_TEMPFAIL;
  	}
  	mci->mci_state = MCIS_OPEN;
- - 	mci_setstat(mci, smtptodsn(r), SmtpReplyBuffer);
- - 	e->e_statmsg = newstr(&SmtpReplyBuffer[4]);
  	if (REPLYTYPE(r) == 4)
! 		return EX_TEMPFAIL;
  	else if (REPLYCLASS(r) != 5)
! 		/* fall through */ ;
  	else if (REPLYTYPE(r) == 2)
! 		return EX_OK;
  	else if (REPLYTYPE(r) == 5)
! 		return EX_UNAVAILABLE;
  #ifdef LOG
  	if (LogLevel > 1)
  	{
- --- 788,809 ----
  		return EX_TEMPFAIL;
  	}
  	mci->mci_state = MCIS_OPEN;
  	if (REPLYTYPE(r) == 4)
! 		rstat = EX_TEMPFAIL;
  	else if (REPLYCLASS(r) != 5)
! 		rstat = EX_PROTOCOL;
  	else if (REPLYTYPE(r) == 2)
! 		rstat = EX_OK;
  	else if (REPLYTYPE(r) == 5)
! 		rstat = EX_UNAVAILABLE;
! 	else
! 		rstat = EX_PROTOCOL;
! 	mci_setstat(mci, rstat, smtptodsn(r), SmtpReplyBuffer);
! 	if (e->e_statmsg != NULL)
! 		free(e->e_statmsg);
! 	e->e_statmsg = newstr(&SmtpReplyBuffer[4]);
! 	if (rstat != EX_PROTOCOL)
! 		return rstat;
  #ifdef LOG
  	if (LogLevel > 1)
  	{
***************
*** 761,767 ****
  			shortenstring(SmtpReplyBuffer, 403));
  	}
  #endif
! 	return EX_PROTOCOL;
  }
  
  
- --- 812,818 ----
  			shortenstring(SmtpReplyBuffer, 403));
  	}
  #endif
! 	return rstat;
  }
  
  
***************
*** 771,780 ****
- --- 822,887 ----
  	longjmp(CtxDataTimeout, 1);
  }
  /*
+ **  SMTPGETSTAT -- get status code from DATA in LMTP
+ **
+ **	Parameters:
+ **		m -- the mailer to which we are sending the message.
+ **		mci -- the mailer connection structure.
+ **		e -- the current envelope.
+ **
+ **	Returns:
+ **		The exit status corresponding to the reply code.
+ */
+ 
+ #if FFR_LMTP
+ 
+ int
+ smtpgetstat(m, mci, e)
+ 	MAILER *m;
+ 	MCI *mci;
+ 	ENVELOPE *e;
+ {
+ 	int r;
+ 	int stat;
+ 
+ 	/* check for the results of the transaction */
+ 	r = reply(m, mci, e, TimeOuts.to_datafinal, NULL);
+ 	if (r < 0)
+ 	{
+ 		smtpquit(m, mci, e);
+ 		return EX_TEMPFAIL;
+ 	}
+ 	if (e->e_statmsg != NULL)
+ 		free(e->e_statmsg);
+ 	e->e_statmsg = newstr(&SmtpReplyBuffer[4]);
+ 	if (REPLYTYPE(r) == 4)
+ 		stat = EX_TEMPFAIL;
+ 	else if (REPLYCLASS(r) != 5)
+ 		stat = EX_PROTOCOL;
+ 	else if (REPLYTYPE(r) == 2)
+ 		stat = EX_OK;
+ 	else if (REPLYTYPE(r) == 5)
+ 		stat = EX_UNAVAILABLE;
+ 	mci_setstat(mci, stat, smtptodsn(r), SmtpReplyBuffer);
+ #ifdef LOG
+ 	if (LogLevel > 1 && stat == EX_PROTOCOL)
+ 	{
+ 		syslog(LOG_CRIT, "%s: %.100s: SMTP DATA-3 protocol error: %s",
+ 			e->e_id, mci->mci_host,
+ 			shortenstring(SmtpReplyBuffer, 403));
+ 	}
+ #endif
+ 	return stat;
+ }
+ 
+ #endif
+ /*
  **  SMTPQUIT -- close the SMTP connection.
  **
  **	Parameters:
  **		m -- a pointer to the mailer.
+ **		mci -- the mailer connection information.
+ **		e -- the current envelope.
  **
  **	Returns:
  **		none.
***************
*** 927,932 ****
- --- 1034,1040 ----
  		if (p == NULL)
  		{
  			bool oldholderrs;
+ 			extern char MsgBuf[];
  
  			/* if the remote end closed early, fake an error */
  			if (errno == 0)
***************
*** 937,946 ****
  # endif /* ECONNRESET */
  
  			mci->mci_errno = errno;
- - 			mci->mci_exitstat = EX_TEMPFAIL;
  			oldholderrs = HoldErrs;
  			HoldErrs = TRUE;
  			usrerr("451 reply: read error from %s", mci->mci_host);
  
  			/* if debugging, pause so we can see state */
  			if (tTd(18, 100))
- --- 1045,1054 ----
  # endif /* ECONNRESET */
  
  			mci->mci_errno = errno;
  			oldholderrs = HoldErrs;
  			HoldErrs = TRUE;
  			usrerr("451 reply: read error from %s", mci->mci_host);
+ 			mci_setstat(mci, EX_TEMPFAIL, "4.4.2", MsgBuf);
  
  			/* if debugging, pause so we can see state */
  			if (tTd(18, 100))
diff -c -r sendmail-8.8.2/src/util.c sendmail-8.8.3/src/util.c
*** sendmail-8.8.2/src/util.c	Sat Oct 12 13:35:11 1996
- --- sendmail-8.8.3/src/util.c	Sat Nov 16 18:32:28 1996
***************
*** 33,39 ****
   */
  
  #ifndef lint
! static char sccsid[] = "@(#)util.c	8.105 (Berkeley) 10/12/96";
  #endif /* not lint */
  
  # include "sendmail.h"
- --- 33,39 ----
   */
  
  #ifndef lint
! static char sccsid[] = "@(#)util.c	8.109 (Berkeley) 11/16/96";
  #endif /* not lint */
  
  # include "sendmail.h"
***************
*** 1012,1017 ****
- --- 1012,1026 ----
  			if (TrafficLogFile != NULL)
  				(void) putc('.', TrafficLogFile);
  		}
+ 		else if (l[0] == 'F' && slop == 0 &&
+ 			 bitset(PXLF_MAPFROM, pxflags) &&
+ 			 strncmp(l, "From ", 5) == 0 &&
+ 			 bitnset(M_ESCFROM, mci->mci_mailer->m_flags))
+ 		{
+ 			(void) putc('>', mci->mci_out);
+ 			if (TrafficLogFile != NULL)
+ 				(void) putc('>', TrafficLogFile);
+ 		}
  		if (TrafficLogFile != NULL)
  			fprintf(TrafficLogFile, "%.*s\n", p - l, l);
  		for ( ; l < p; ++l)
***************
*** 2197,2202 ****
- --- 2206,2212 ----
  	pid_t pid;
  {
  	int i;
+ 	extern void proc_list_probe __P((void));
  
  	for (i = 0; i < ProcListSize; i++)
  	{
***************
*** 2205,2210 ****
- --- 2215,2232 ----
  	}
  	if (i >= ProcListSize)
  	{
+ 		/* probe the existing vector to avoid growing infinitely */
+ 		proc_list_probe();
+ 
+ 		/* now scan again */
+ 		for (i = 0; i < ProcListSize; i++)
+ 		{
+ 			if (ProcListVec[i] == NO_PID)
+ 				break;
+ 		}
+ 	}
+ 	if (i >= ProcListSize)
+ 	{
  		/* grow process list */
  		pid_t *npv;
  
***************
*** 2244,2251 ****
  		if (ProcListVec[i] == pid)
  		{
  			ProcListVec[i] = NO_PID;
- - 			CurChildren--;
  			break;
  		}
  	}
  }
- --- 2266,2307 ----
  		if (ProcListVec[i] == pid)
  		{
  			ProcListVec[i] = NO_PID;
  			break;
  		}
  	}
+ 	if (CurChildren > 0)
+ 		CurChildren--;
+ }
+ /*
+ **  PROC_LIST_PROBE -- probe processes in the list to see if they still exist
+ **
+ **	Parameters:
+ **		none
+ **
+ **	Returns:
+ **		none
+ */
+ 
+ void
+ proc_list_probe()
+ {
+ 	int i;
+ 
+ 	for (i = 0; i < ProcListSize; i++)
+ 	{
+ 		if (ProcListVec[i] == NO_PID)
+ 			continue;
+ 		if (kill(ProcListVec[i], 0) < 0)
+ 		{
+ #ifdef LOG
+ 			if (LogLevel > 3)
+ 				syslog(LOG_DEBUG, "proc_list_probe: lost pid %d",
+ 					ProcListVec[i]);
+ #endif
+ 			ProcListVec[i] = NO_PID;
+ 			CurChildren--;
+ 		}
+ 	}
+ 	if (CurChildren < 0)
+ 		CurChildren = 0;
  }
diff -c -r sendmail-8.8.2/src/version.c sendmail-8.8.3/src/version.c
*** sendmail-8.8.2/src/version.c	Fri Oct 18 08:28:13 1996
- --- sendmail-8.8.3/src/version.c	Sat Nov 16 18:33:07 1996
***************
*** 33,39 ****
   */
  
  #ifndef lint
! static char sccsid[] = "@(#)version.c	8.8.2.1 (Berkeley) 10/18/96";
  #endif /* not lint */
  
! char	Version[] = "8.8.2";
- --- 33,39 ----
   */
  
  #ifndef lint
! static char sccsid[] = "@(#)version.c	8.8.3.2 (Berkeley) 11/16/96";
  #endif /* not lint */
  
! char	Version[] = "8.8.3";
diff -c -r sendmail-8.8.2/test/Results sendmail-8.8.3/test/Results
*** sendmail-8.8.2/test/Results	Wed Oct 16 10:01:48 1996
- --- sendmail-8.8.3/test/Results	Mon Oct 21 07:12:10 1996
***************
*** 39,44 ****
- --- 39,45 ----
  AIX	3.2.3e	FAIL	93.07.26  Steve Bauer <sbauer@silver.sdsmt.edu>
  AIX	3.2.4	FAIL	93.10.07  David J. N. Begley
  AIX	3.2.5	FAIL	94.05.17  Steve Bauer <sbauer@hpcmmib.hpc.sdsmt.edu>
+ AIX	4.1	FAIL	96.10.21  Hakan Lindholm <hakan@af.lu.se>
  AIX	4.2	OK	96.10.16  Steve Bauer <sbauer@krypton.hpc.sdsmt.edu>
  
  IRIX	4.0.4	OK	93.09.25  Robert Elz
***************
*** 77,82 ****
- --- 78,85 ----
  
  Linux	1.2.13	FAIL	95.11.02  Sven Neuhaus <sven@ping.de>
  Linux	2.0.17	FAIL	96.09.03  Horst von Brand <vonbrand@sleipnir.valparaiso.cl>
+ 
+ AIX	4.1	OK	96.10.21  Hakan Lindholm <hakan@af.lu.se>
  
  IRIX	5.2	OK	95.12.01  Mark Andrews <mandrews@aw.sgi.com>
  IRIX	5.3	OK	95.12.01  Mark Andrews <mandrews@aw.sgi.com>

-----BEGIN PGP SIGNATURE-----
Version: 2.6.2

iQCVAwUBMo9USCPkYtS/e6QhAQHqdgP/WYbk0ue9iNsevGaTc1oF6vwB3GUqCDFd
V9JfnRoMqzmRkHU+AKt/r+Vk5pow3VeOXHGxMp7fghgdm3QylsV7UC0cXeTgZoVq
/VnH4+nwajoX9KfF4kPBYdtHMeg4IEZTaMWY0APlWXse0LDUyr1n3JIUADRv+ZLn
Yki60zhoPbs=
=hBv3
-----END PGP SIGNATURE-----
