diff -c ../sendmail.org/00READ_ME.WIDE ./00READ_ME.WIDE
*** ../sendmail.org/00READ_ME.WIDE	Thu Nov 16 02:49:20 2000
--- ./00READ_ME.WIDE	Thu Nov 16 01:53:41 2000
***************
*** 0 ****
--- 1,205 ----
+             Patch kit for R8 sendmail (3.4W) by WIDE Project
+ 							        Aug.18,2000
+ 							  Motonori NAKAMURA
+ 							       WIDE Project
+ 							motonori@wide.ad.jp
+ 
+ INTRODUCTION
+ 
+ This patch-kit provides some enhancement for the sendmail. Please apply
+ this patch if you want to use "smtpfeed", which is an external SMTP mailer.
+ 
+ Current original sendmail includes many features, especially for Japanese
+ workstations, which had been offered with patch kit 2.xW by WIDE Project.
+ Many normal workstations (non-mail-servers), therefore, will not need
+ features offered by this patch-kit. Be sure on features offered by
+ this patch-kit if you apply it to the sendmail.
+ 
+ 
+ FEATURES
+ 
+ Each features are enabled/disabled with the following flags in conf.h.
+ 
+  QUICK_RESPONSE
+ 	When sendmail is executed with -odq switch from rmail program,
+ 	bounce mails will also be queued. If feature is enabled, bounce
+ 	mails will not be queued and sent immediately (not well tested).
+ 
+  MULTI_MAILER
+ 	This feature allows multiple description of the triple in a rule
+ 	for mailer dispatching in ruleset 0 or its sub-rulesets like:
+ 		R$*<@dom>$*	$#smtp$@dom$:$1<@dom>$2 $#uucp$@dom$:$1<@dom>$2
+ 	The above rule will try smtp mailer at first and then try uucp
+ 	mailer if smtp mailer fails.
+ 	Lower number limit of recipients can be defined at *= equate
+ 	in definition line of a mailer which will be used at first.
+ 	If number of recipients is less than the value defined at *=
+ 	equate, first mailer will be skipped without trial.
+ 	Message size limitation defined by M= equate will also be treated
+ 	like the above -- if size of message is larger than the value
+ 	defined, first mailer will be skipped without trial.
+ 	If there is a flag '!' in F= equate, the mailer will be skipped
+ 	when queue processing (in case following mailer is found).
+ 	If there is a flag '_' in F= equate, the following mailer will
+ 	not be used when the mailer (having '_' flag) is tried and
+ 	failed with TEMPFAIL response code.
+ 
+  CF_ALIASING
+ 	This feature supplies "aliasing" in ruleset 5 (ruleset 5 is
+ 	applied after aliases expansuin).
+ 	The following rule will forward messages for user-a to multiple
+ 	recipients, user-a and user-b. In other words, this feature
+ 	provides aliasing by rules of the sendmail.cf.
+ 		R user-a	$# local $@ alias $: user-a, user-b
+ 	A mailer specified at $# must have 'l' in F= equate (local mailer).
+ 	host portion specified at $@ must be 'alias'.
+ 	You can specify multiple addresses separated with ',' at $:
+ 
+  _FFR_DYNAMIC_TOBUF
+ 	Number of recipients passed in a SMTP transaction is limited by
+ 	size of tobuf[] (TOBUFSIZE) with current implementation of the
+ 	sendmail(tobuf[] is used for logging recipients to syslog).
+ 	The _FFR_DYNAMIC_TOBUF feature uses dynamic allocation technique
+ 	to relax this limitation so that a SMTP transaction not be
+ 	splited into many small transactions which takes long time to
+ 	finish a sequence of deliveries in case the message has many
+ 	recipients on an identical host. Default of the maximum number
+ 	of recipients which can be passed at a time is 100 since it is
+ 	limited up to 100 by RFC821. But you can change the value par
+ 	mailer using r= equate in mailer definition lines.
+ 
+  MAILER_PREF
+ 	Mailer preference can be defined in configuration file to determine
+ 	order of mailers to be executed. If a message which has multiple
+ 	recipients will be delivered with multiple mailers, order of mailers
+ 	is determined by preference values. For example, if you define 10
+ 	for local mailer and 20 for smtp mailer, delivery with local mailer
+ 	will be done first and then smtp mailer will be used. Preference
+ 	values can be defined at %= equate on mailer definition lines.
+ 	Lower values are more preferred like MX RRs. Default value is 0
+ 	in case %= equate is missing. Negative values can be specified.
+ 	If there is a flag '<' in F= equate of a mailer definition,
+ 	list of destination addresses for the mailer will be sorted by
+ 	domain part. This feature will be effective if number of recipients
+ 	to be processed in one transaction is limited with r= equate.
+ 
+  CLIENT_SMTP_CONFIG
+ 	3 parameters of client-side SMTP connection can be configured.
+ 	Parameters are:
+ 		FQDN: FQDN used as a hostname with SMTP HELO
+ 		SrcIPaddr: source IP address for client-side SMTP (12.34.56.78)
+ 		SrcPort: source port number for client-side SMTP
+ 	Define these parameters at @= equate on IPC mailer definition lines
+ 	like:
+ 		@=FQDN/SrcIPaddr/SrcPort
+ 	Default value will be used if a parameter omitted.
+ 	When a '@' is specified at FQDN part, a hostname which is resolved
+ 	from source IP address of SMTP connection dynamically is used.
+ 	If any hostname can not be obtained with DNS or etc., [IP.addres]
+ 	notation will be used.
+ 	When a '@' is specified at SrcIPaddr part, an IP address associated
+ 	with FQDN will be used. If multiple IP addresses are defined for the
+ 	FQDN, the first found address will be used.
+ 
+  CTE8CHECK
+ 	Manage incorrect "Content-Transfer-Encoding: 8bit" header label
+ 	(having such a header without 8bit data in message body).
+ 	To enable this feature, CTE8BitCheck option should be defined in
+ 	configuration file.
+ 		O CTE8BitCheck=correct	(correct CTE label to "7bit")
+ 		O CTE8BitCheck=reject	(reject such messages)
+ 
+  OO_NULLSENDER
+ 	Set NULL sender envelope address (<>) on messages delivered to
+ 	the alias entry "owner-owner" to avoid loops.
+ 
+  MF_SEPARATE
+ 	Even if recipient list of a message includes multiple identical
+ 	address, only one copy of the message will be sent to the address.
+ 	If you define MF_SEPARATE and set flag '^' to a mailer, the
+ 	address will not be unified and equal number of copies will be
+ 	sent to the address.
+ 
+  MASKED_ADDR
+ 	Traditional class-macro matching in sendmail is just a tokenized
+ 	character string pattern matching. But this type of matching does
+ 	not support masked IP address matching, so you must list up every
+ 	host addresses as elements of a class. It is complicated especially
+ 	for IP address authentication in check_* rulesets.
+ 	If you define MASKED_ADDR, masked IP address matching feature can
+ 	be used. For example, if you describe the following lines in your
+ 	sendmail.cf, an IP address between 172.16.0.0 and 172.31.255.255
+ 	will be matched to $=C in a rule.
+ 
+ 		CC _MASKED_ADDRESS_MATCH_
+ 		CC 172.16.0.0/12
+ 
+ 	Note that you must include the keyword _MASKED_ADDRESS_MATCH_ to
+ 	a class to enable masked IP address matching for the class.
+ 
+ 	If you define MASKED_ADDR, maskedaddr map is also enabled.
+ 	For example, if you create a map file /etc/maskedaddr.map with
+ 	the following content:
+ 
+ 		172.16.0.0/12		OK
+ 
+ 	and describe the following lines in your sendmail.cf, an IP
+ 	address between 172.16.0.0 and 172.31.255.255 will match to
+ 	the entry in the map file, and the address pattern will be
+ 	changed to "OK".
+ 
+ 		Kma maskedaddr -t /etc/maskedaddr.map
+ 
+ 		R $-.$-.$-.$-	$: $( ma $1.$2.$3.$4 $)
+ 
+ 	This map file is not DB style but TEXT style, so the file will
+ 	be open and read at every matching processing. If you set option
+ 	-t as avobe example, the file will be read only once at startup
+ 	time of sendmail. In this case, you must restart sendmail when
+ 	you modified the map file.
+ 
+ 	3ffe:501::1 address spec is also supported under IPv6 environment.
+ 
+  SPR_CON_CACHE
+ 	This feature supplies connection-caching control par mailer basis.
+ 	You can use mailer flag ';' at F= equate of mailer definition.
+ 	If your set the mailer flag ';', connection-caching feature for
+ 	the mailer is disabled.
+ 
+  FORWARDPROGCTL
+ 	This feature supplies privilege control on execution of programs
+ 	via ~/.forward file. With this feature, only users defined in
+ 	class macro 'f' can execute programs via ~/.forward. To enable
+ 	this feature you must also define a character '@' in the class
+ 	macro 'f', or every users can execute programs via ~/.forward.
+ 
+  MAILER_TIMEOUTS
+ 	With this feature, you can control message timeout (how long
+ 	an unsent message will be kept in the mqueue) par mailer basis.
+ 	To specify timeout value for a mailer, use ?= equate like:
+ 		Msmtp ...., ?=7d,....
+ 
+  CHECK_WARNING
+ 	This enables a feature to control whether a queue-warning
+ 	(unsent yet, but still trying) notification should be sent to
+ 	sender or not. For decision, envelope sender address is processed
+ 	with "check_warning" ruleset and if it reaches to an error mailer,
+ 	a notification will be sent. Of course, notifications to messages
+ 	whose value in Precedence: header field is negative or envelope
+ 	sender address is <> are not sent as before. If "check_warning"
+ 	ruleset is not defined, notifications are sent as before.
+ 	An example of check_warning ruleset:
+ 		Scheck_warning
+ 		R $* - request@$*	$@ OK
+ 		R $* - ctl@$*		$@ OK
+ 		R owner - $*@$*		$@ OK
+ 		R $* @ mydomain		$#error$:warning
+ 		R $*			$@ OK
+ 	Note: in check_warning ruleset, character '-' is also treated as
+ 	an OperaterChar. But it should be surrounded by spaces.
+ 
+ 
+ ACKNOWLEDGEMENTS
+ 
+ Development of this patch-kit has been supported by WIDE Project, Kyoto
+ University, Ritsumeikan University, TDI Co., Ltd., and many contributors.
diff -c ../sendmail.org/00READ_ME.WIDE.j ./00READ_ME.WIDE.j
*** ../sendmail.org/00READ_ME.WIDE.j	Thu Nov 16 02:49:20 2000
--- ./00READ_ME.WIDE.j	Thu Nov 16 01:53:41 2000
***************
*** 0 ****
--- 1,227 ----
+ Patch kit for R8 sendmail (3.4W) by WIDE Project	Aug.18,2000
+ 							中村 素典/WIDE Project
+ 							motonori@wide.ad.jp
+ 
+ 《はじめに》
+ 
+ このパッチキットは、sendmail に対して SMTP による配信を行う外部メーラで
+ ある smtpfeed を利用するための変更を中心とした拡張を行なうためのものです。
+ 
+ 現在のオリジナルの sendmail には、従来の WIDE 版 sendmail として提供され
+ てきた多くの機能が取り込まれているので、ほとんどの場合はオリジナルのまま
+ で問題なく利用できます。特に、日本製のワークステーションでうまくコンパイ
+ ルできない、という問題はほとんど解消されていますから、これをあてればコン
+ パイルできるようになるというパッチではありません。このパッチによって実現
+ される機能の必要性を十分に検討してからご利用下さい。
+ 
+ 
+ 《拡張される機能について》
+ 
+ 各種機能は以下のフラグによって制御できます。
+ 
+  QUICK_RESPONSE
+ 	rmail などから -odq フラグつきで sendmail が起動された場合、配信
+ 	エラーが発生しても、エラーメールは mqueue に一旦保存されます。この
+ 	ようなレスポンスメールについては、mqueue に落さずにすぐに配送する
+ 	ようにしたい場合に 1 にします(テストが十分でないので注意)。
+ 
+  MULTI_MAILER
+ 	ルールセット 0 のメーラディスパッチルールにおいて、一行に
+ 	$#...$@...$:... の三つ組を繰り返し記述できるようにします。
+ 	$#smtp.... $#uucp.... のように書くことにより、smtp mailer による
+ 	配送に失敗した場合に、即座に uucp mailer に切替えて配信させるよう
+ 	にすることができます。
+ 	sendmail.cf の mailer 定義行において *= 式が指定された場合、受信者
+ 	数がその式に指定された数値に満たない場合で、さらに後続の mailer が
+ 	存在する場合には、当該 mailer は利用せずに後続の mailer に skip し
+ 	ます。
+ 	また、M= 式で指定されるメッセージサイズについても、上限を越えてお
+ 	り、かつ後続の mailer が存在する場合には、同様に skip します。
+ 	F= 式に mailer flag ! を追加した場合、run queue の際には利用されず
+ 	に、後続の mailer に skip します(後続の mailer が定義されている場合
+ 	のみ)。
+ 	F= 式に mailer flag _ を指定した場合、この mailer が起動されたなら
+ 	ば、先行する mailer の処理結果が TEMPFAIL になっても後続の mailer
+ 	を試みません。
+ 
+  CF_ALIASING
+ 	ルールセット 5 のローカルユーザに関する書き換えルールにおいて、エイ
+ 	リアス機能(複数のアドレスに展開する機能)を提供します。つまり、
+ 	CF_ALIASING は aliases の機能を、sendmail.cf のルールレベルで提供し
+ 	ます。例えば、S5 で始まるルールセット5に以下のようなルールを書くこ
+ 	とで、user-a 宛のメールは user-a および user-b に送られるようになり
+ 	ます(ルールセット 5 は aliases の処理の後で適用されます)。
+ 		R user-a	$# local $@ alias $: user-a, user-b
+ 	$# で指定する mailer は F= に l を持つローカルメーラです。
+ 	$@ では必ず alias を指定します。
+ 	$: で、aliases ファイルのように、複数のアドレスをコンマで区切って
+ 	指定します。
+ 
+  _FFR_DYNAMIC_TOBUF
+ 	従来の sendmail において、同時に配信可能なメールアドレスを記録する
+ 	tobuf[] のサイズが TOBUFSIZE で固定であったのを可変長で動的に確保
+ 	するようにし、SMTP における配送において同じメールサーバ宛のアドレス
+ 	が多く含まれる場合に、配送が細切れになるのを防ぎます。RFC821 では、
+ 	一回の SMTP トランザクションにおいて同時に配信可能な受信者の数は
+ 	100 までと規定されています。_FFR_DYNAMIC_TOBUF では、上限のデフォ
+ 	ルトは 100 となりますが、mailer 定義の r= 式において上限を任意に設
+ 	定することができます。
+ 
+  MAILER_PREF
+ 	mailer の起動順序の設定を可能にします。複数の宛先を持つメッセージが
+ 	複数の mailer を利用して配信される場合、mailer ごとにあらかじめ指定
+ 	された順位付けに従って、配信が行なわれます。例えば、local mailer に
+ 	対して 10、smtp mailer に対して 20 という値を設定しておくと、まず
+ 	local mailer を経由する配信処理を済ませてから、smtp mailer を経由
+ 	する配信処理に移ります。順位付けのための値は、mailer 定義行の %= 式
+ 	で指定します。より小さな値を持つ mailer の処理が優先されます。
+ 	%= 式を定義しなかった場合のデフォルト値は 0 です。負の数も指定可能
+ 	です。
+ 	また、F= 式に mailer flag < が指定された mailer については、配送先の
+ 	アドレスがソートされてから処理されます。 r= 式で一回の処理で渡される
+ 	アドレス数が制限される場合に、できるだけ同じアドレスを同時に処理させ
+ 	たい場合に有効でしょう。
+ 	従来のパッチで提供されていた LOCAL_FIRST は、この機能に置き換えられ
+ 	ました。
+ 
+  CLIENT_SMTP_CONFIG
+ 	SMTP によってメールを配信する際の、発信側サイドに関するいくつかの
+ 	設定を可能にします。ここで可能になるのは、SMTP の HELO コマンドで
+ 	名乗るホスト名、ソース IP アドレス、ソースポート番号です。
+ 	設定は mailer 定義行の @= 式にて行ないます。
+ 	形式は @=family:FQDN/SrcIPaddr/SrcPort で、各項目は以下の通りです。
+ 		family: inet または inet6
+ 		FQDN: SMTP HELO で使用されるホスト名
+ 		SrcIPaddr: ソース IP アドレス(12.34.56.78 という形式で記述)
+ 		SrcPort: ソースポート番号
+ 	/ で区切られた項目のいずれかを省略した場合は従来のデフォルト値が
+ 	使用されます。
+ 	FQDN に @ のみを指定した場合は、SMTP 接続で用いられているソース側
+ 	IP アドレスに対応づけられている名前を動的に検索し、それを用います。
+ 	もし、DNS 等に対応するホスト名が登録されていなかった場合は、
+ 	[IP.addres] 表記を用います。
+ 	SrcIPaddr に @ のみを指定した場合は、FQDN に対応する IP アドレスが
+ 	利用されます。FQDN に複数の IP アドレスが対応づけられている場合は、
+ 	最初に見つけたアドレスを使用します。
+ 
+  CTE8CHECK
+ 	本文が 8bit 文字を含まないメッセージであるにもかかわらず、
+ 	Content-Transfer-Encoding: に 8bit を指定して送信されてくるメッセー
+ 	ジをチェックし、オプションで指定した処理を行ないます。オプション名
+ 	は CTE8BitCheck です。
+ 		O CTE8BitCheck=correct
+ 			CTE: に記述された 8bit を強制的に 7bit に変更します。
+ 		O CTE8BitCheck=reject
+ 			配信を拒否します。
+ 
+  OO_NULLSENDER
+ 	owner-owner というエイリアスエントリにメールが送信された場合に、
+ 	エンベロープの発信者アドレスを NULL アドレス (<>) に書き換えます。
+ 	これは、配信先におけるエラーのためのループを避けるためです。
+ 
+  MF_SEPARATE
+ 	通常、メールの配信時に同一の宛先が複数含まれている場合には、その
+ 	宛先には一通しかメールが送られませんが、MF_SEPARATE を定義すると、
+ 	そのような場合であっても複数のメールが送られるようにするための機
+ 	能が利用可能になります。MF_SEPARATE を定義すると、mailer flag ^
+ 	が利用可能になるので、メールを一つにまとめたくない mailer の flag
+ 	に ^ を追加してください。
+ 
+  MASKED_ADDR
+ 	通常、sendmail における文字列マッチングは、単純なパターンマッチン
+ 	グによって処理されます。しかし、このような文字列マッチングでは、
+ 	ネットマスクを伴う IP アドレスの範囲マッチングができず、IP アドレ
+ 	スによる認証処理などの記述が非常に煩雑になってしまいます。
+ 	MASKED_ADDR を定義すると、sendmail.cf のクラスマッチングにおいて
+ 	ネットマスク表記を含んだクラス要素へのマッチング機能が利用可能に
+ 	なります。例えば、
+ 
+ 		CC _MASKED_ADDRESS_MATCH_
+ 		CC 172.16.0.0/12
+ 
+ 	と定義しておくと、172.16.0.0 から 172.31.255.255 までのアドレスは
+ 	ルール中の $=C にマッチします。なお、このマッチング処理を利用した
+ 	いクラスに対しては、その要素として _MASKED_ADDRESS_MATCH_ を定義
+ 	しておく必要があります。_MASKED_ADDRESS_MATCH_ を要素に持たないク
+ 	ラスは、従来通りのマッチング処理を行います。
+ 
+ 	また、MASKED_ADDR を定義すると、maskedaddr マップが利用可能になり
+ 	ます。例えば、次のような内容のマップファイル /etc/maskedaddr.map
+ 	を用意しておき、
+ 
+ 		172.16.0.0/12		OK
+ 
+ 	sendmail.cf で次のように定義すると
+ 
+ 		Kma maskedaddr -t /etc/maskedaddr.map
+ 
+ 		R $-.$-.$-.$-	$: $( ma $1.$2.$3.$4 $)
+ 
+ 	172.16.0.0 から 172.31.255.255 までのアドレスに対して、マップファ
+ 	イル中のエントリがマッチし、OK に書き換えられます。このマップファ
+ 	イルはテキスト形式で、データベース形式への変換は必要ありません。
+ 	そのため、マップファイルをマッチング処理の度に毎回読み込むことに
+ 	なります。起動時に一度だけ読み込むようにしたい場合は、上の例のよう
+ 	に -t オプションを指定します(この場合、マップの変更後は sendmail
+ 	の再起動が必要です)。-t オプションを指定しない場合は、毎回マップ
+ 	ファイルが読み込まれます。
+ 
+ 	なお、IPv6 環境では 3ffe:501::1 といった表記にも対応します。
+ 
+  SPR_CON_CACHE
+ 	メーラ単位にコネクションキャッシュ機能を抑制する機能を提供します。
+ 	メーラフラグ ; をメーラ定義(M行)の F= に追加することで、そのメー
+ 	ラの処理に関してコネクションキャッシュ機能が抑制されます。
+ 
+  FORWARDPROGCTL
+ 	.forward においてプログラムを実行できる権限を特定のユーザのみに制
+ 	限する機能を提供します。この機能が有効になっている場合、クラス f
+ 	に登録されているユーザのみが、プログラムの実行を許されます。この
+ 	機能を有効にするには、クラス f に文字 @ を登録しておきます。クラ
+ 	ス f に文字 @ が登録されていなければ、通常通り誰でもプログラムを
+ 	実行することができます。
+ 
+  MAILER_TIMEOUTS
+ 	配信未完了状態が続いているメールはキューに保存されますが、ある期
+ 	限を過ぎると、発信者に返送されます。この期限を、メーラ毎に指定で
+ 	きる機能を提供します。sendmail.cf のメーラ定義行(Mで始まる行)に
+ 	おいて ?= 式で、そのメーラでの保存期限を指定します。
+ 	例:
+ 		Msmtp ...., ?=7d,....
+ 
+  CHECK_WARNING
+ 	配信未完了状態が続いた場合、sendmail は発信者に「未完了であるが、
+ 	継続して試行する」という旨を通知する機能を持っています。この期限
+ 	は Timeout.queuewarn などで設定しますが、標準では、全ての通常メー
+ 	ルに関して通知を出すか出さないかの選択しかできません。
+ 	CHECK_WARNING は、この通知を選択的に行うようにするための機能を提
+ 	供します。新たに check_warning ルールセットが用意され、このルール
+ 	セットに対して、エンベロープの発信者アドレスが渡されます。このルー
+ 	ルセットが定義されている場合、処理の結果が error mailer を含むも
+ 	のであった場合は通知が発信され、そうでない場合は通知の発信は抑制
+ 	されます。check_warning ルールセットが未定義の場合は、通常通りの
+ 	動作となります(check_warning が定義されていても、これまで通り、
+ 	Precedence: ヘッダの値が負であるものや、エンベロープの発信者アド
+ 	レスが <> であるものに対する通知は抑制されます)。
+ 	check_warning ルールセットの例:
+ 		Scheck_warning
+ 		R $* - request@$*	$@ OK
+ 		R $* - ctl@$*		$@ OK
+ 		R owner - $*@$*		$@ OK
+ 		R $* @ mydomain		$#error$:warning
+ 		R $*			$@ OK
+ 	なお、check_warning ルールセットでは、文字 '-' も、OperatorChars
+ 	として扱われます。ルールセットを記述する場合は、上記のように、
+ 	文字 '-' の前後にはスペースをいれるようにします。
+ 
+  RCPT_HASH
+ 	一度に多数のアドレスを扱う場合(大規模なメーリングリスト等で)、
+ 	同一アドレスの存在の有無をチェックする処理がリニアサーチになっ
+ 	ているため処理が遅い。RCPT_HASH は、ハッシュを用いてこの処理を
+ 	高速化する。十分な動作確認が行われていないので注意。
+ 
+ 《謝辞》
+ 
+ このパッチは、WIDE Project、京都大学、立命館大学、情報技術開発株式会社
+ ならびにその他の人々の協力によって作成されたものです。ここに感謝の意を
+ 表します。
diff -c ../sendmail.org/COPYRIGHT.WIDE ./COPYRIGHT.WIDE
*** ../sendmail.org/COPYRIGHT.WIDE	Thu Nov 16 02:49:20 2000
--- ./COPYRIGHT.WIDE	Thu Nov 16 01:53:41 2000
***************
*** 0 ****
--- 1,30 ----
+  * Copyright (c) 1995-2000 WIDE Project. All rights reserved.
+  *
+  * Redistribution and use in source and binary forms, with or without
+  * modification, are permitted provided that the following conditions
+  * are met:
+  *
+  * 1. Redistributions of source code must retain the above copyright
+  *    notice, this list of conditions and the following disclaimer.
+  * 2. Redistributions in binary form must reproduce the above copyright
+  *    notice, this list of conditions and the following disclaimer in the
+  *    documentation and/or other materials provided with the distribution.
+  * 3. All advertising materials mentioning features or use of this software
+  *    must display the following acknowledgement:
+  *      This product includes software developed by WIDE Project and
+  *      its contributors.
+  * 4. Neither the name of the Project, the University nor the names of
+  *    its contributors may be used to endorse or promote products derived
+  *    from this software without specific prior written permission.
+  *
+  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+  * SUCH DAMAGE.
diff -c ../sendmail.org/INSTALL.WIDE ./INSTALL.WIDE
*** ../sendmail.org/INSTALL.WIDE	Thu Nov 16 02:49:20 2000
--- ./INSTALL.WIDE	Thu Nov 16 01:53:41 2000
***************
*** 0 ****
--- 1,23 ----
+ INSTALLATION
+ 
+ This kit is provided in a "patch" format. Simply apply it in the directory
+ sendmail-8.11.x/sendmail/.
+ 
+ 	1. gunzip sendmail.8.11.x.tar.gz
+ 	2. tar xvf sendmail.8.11.x.tar
+ 	3. cd sendmail-8.11.x/sendmail/
+ 	4. patch < THISFILE
+ 
+ If your system does not have the "patch" program. Install the GNU version
+ of "patch."
+ 
+ After applying the patch, type "sh Build" to make binary of sendmail.
+ 
+ 	5. sh Build
+ 
+ and install new sendmail carefully ("make install" does not save
+ old binaries to revert).
+ 
+ Read 00READ_ME.WIDE to utilize features provided by this patch-kit.
+ You should, of course, read other documents such as READ_ME or FAQs
+ included in the original distribution of the sendmail.
diff -c ../sendmail.org/INSTALL.WIDE.j ./INSTALL.WIDE.j
*** ../sendmail.org/INSTALL.WIDE.j	Thu Nov 16 02:49:20 2000
--- ./INSTALL.WIDE.j	Thu Nov 16 01:53:41 2000
***************
*** 0 ****
--- 1,16 ----
+ 《インストール方法》
+ 
+ このパッチキットは、パッチ形式による配布となっています。sendmail.8.11.x.tar
+ を展開してできたディレクトリ sendmail-8.11.x/sendmail/ の中で
+ 	patch < "パッチファイル名"
+ として当てください。patch コマンドは GNU のものを利用することを推奨します。
+ 
+ パッチを当てた後、オリジナルの sendmail のコンパイルと同様に sh Build を
+ 実行します。Build は、BIND8 や NEWDB の環境の存在も自動チェックします。
+ include や lib のディレクトリを追加するには、Build の -I や -L オプション
+ で適宜補ってください。
+ 
+ その他、sendmail 8.11.x の利用にあたっては、オリジナルの sendmail に付属
+ の READ_ME や FAQ 等も良く読んでください。また、このパッチの機能を効果的
+ に利用するための sendmail.cf の設定については、00READ_ME.WIDE ファイルを
+ 参照してください。
Only in .: RCS
diff -c ../sendmail.org/RELEASE_NOTES.WIDE ./RELEASE_NOTES.WIDE
*** ../sendmail.org/RELEASE_NOTES.WIDE	Thu Nov 16 02:49:20 2000
--- ./RELEASE_NOTES.WIDE	Thu Nov 16 01:53:41 2000
***************
*** 0 ****
--- 1,276 ----
+ Aug. 18, 2000/8.11.0+3.4W
+ 	recipient.c:
+ 		same addresses were not unified.
+ 		remove spaces before #@# sequence (start of comment).
+ 
+ Jul. 30, 2000/8.11.0+3.3W
+ 	applied to 8.11.0
+ 	DYNAMIC_TOBUF is implemented in original sendmail,
+ 	but for future release.
+ 		!!! CAUTION !!! equate character %= changed to r=.
+ 
+ Jun. 12, 2000/8.10.2+3.3W
+ 	applied to 8.10.2
+ 
+ Apr. 15, 2000/8.10.1+3.3W
+ 	applied to 8.10.1
+ 	LOGWVERSION deleted.
+ 	BOUNCE_REASON deleted. (officially supported by 8.10)
+ 	DEFINE_MAP deleted. (officially supported by 8.10)
+ 		!!! CAUTION !!! mapname changed from "define" to "macro".
+ 	mailer flag characters are changed on MULTI_MAILER feature:
+ 		'-' is replaced by '_'.
+ 	mailer flag characters are changed on MAILER_PREF feature:
+ 		'%' is replaced by '<'.
+ 	mailer flag characters are changed on MF_SEPARATE feature:
+ 		'+' is replaced by '^'.
+ 
+ Mar. 6, 1999/8.9.3+3.2W
+ 	parseaddr.c:
+ 		!!! CAUTION !!! CF_ALIASING feature modified.
+ 		You can use aliasing in ruleset 5 as follows:
+ 			R user@domain	$#local$@alias$: alias1,alias2,...
+ 		Mailer must be a local mailer (F= includes 'l') and host
+ 		part must be "alias".
+ 	conf.h, sendmail.h, recipient.c:
+ 		FORWARDPROGCTL added.
+ 		If you define a character '@' in the class macro 'f',
+ 		only users defined in the class macro 'f' can use
+ 		'prog' mailer via his/her ~/.forward.
+ 	conf.h, sendmail.h, readcf.c, savemail.c, envelope.c:
+ 		MAILER_TIMEOUTS added.
+ 		Queue-return timeout par mailer can be defined with ?= equate
+ 		like: Msmtp ...., ?=7d,....
+ 	conf.h, envelope.c:
+ 		CHECK_WARNING added.
+ 		Queue-warning timeout operation can be controlled with the
+ 		check_warning ruleset. Envelope sender address will be
+ 		processed with the check_warning ruleset. If the chech_warning
+ 		ruleset is defined and the sender address does not reach to
+ 		an error mailer, queue-warning message will be suppressed.
+ 		e.g.:
+ 			Scheck_warning
+ 			R $* - request@$*	$@ OK
+ 			R $* - ctl@$*		$@ OK
+ 			R owner - $*@$*		$@ OK
+ 			R $* @ mydomain		$#error$:warning
+ 			R $*			$@ OK
+ 	readcf.c:
+ 		O_CTE8CHECK should not be 0xaa (fix).
+ 	sendmail.h, deliver.c:
+ 		mailer flag ';' added to suppress connection caching -- to
+ 		change process of external mailer.
+ 	deliver.c:
+ 		use strcpy() instead of strcat() for performance improvement
+ 	daemon.c:
+ 		initialize a pointer "hp" to NULL
+ 		reported by Kojima Kenichi <k-kojima@mms.mt.nec.co.jp>
+ 	recipient.c conf.h sendmail.h:
+ 		RCPT_HASH feature added
+ 
+ Feb. 19, 1999/8.9.3+3.1W
+ 	applied to 8.9.3
+ 	deliver.c:
+ 		enable SuperSafe on LMTP data response
+ 	map.c:
+ 		fix return value in maskedaddr_build()
+ 		reported by Toshiki Ohkawa <ohkawa@nibb.ac.jp>
+ 	conf.c:
+ 		still use _PATH_SENDMAILCF in case of NETINET6
+ 
+ Jan. 13, 1999/8.9.2+3.1W
+ 	applied to 8.9.2
+ 
+ Sep. 24, 1998/8.9.1+3.1W
+ 	queue.c
+ 		${runqueue} defined if in runqueue processing
+ 	main.c
+ 		//coment to be echoed in test mode
+ 	map.c, parseaddr.c, conf.c:
+ 		masked address matching support by class macro (MASKED_ADDR)
+ 	many files:
+ 		IPv6 support
+ 	map.c, conf.c:
+ 		macro can be defined dynamically in a rule with map (DEFINE_MAP)
+ 
+ July 3, 1998/8.9.1+3.0W
+ 	applied to 8.9.1
+ 
+ May 26, 1998/8.9.0+3.0W
+ 	parseaddr.c
+ 		alias expansion supported in ruleset 5 (CF_ALIASING)
+ 		the following rule in ruleset 5 splits an envelope for
+ 		a recipient (user) into 2 recipients (user1 and user2).
+ 			R user	$# local $: user1 $# local $# user2
+ 
+ Apr. 30, 1998/8.9.0+3.0Wbeta14
+ 	domain.c
+ 		CANON_OTHER feature removed.
+ 	deliver.c
+ 		mailer flag % added to sort address list
+ 
+ Mar. 17, 1998/8.9.0+3.0Wbeta13
+ 	applied to 8.9.0
+ 
+ Mar. 6, 1998/8.8.8+3.0Wbeta13
+ 	deliver.c
+ 		more fix around smtpquit() (mci pointer was not initialized)
+ 
+ Mar. 5, 1998/8.8.8+3.0Wbeta12
+ 	deliver.c
+ 		fix around smtpquit()
+ 
+ Jan. 6, 1998/8.8.8+3.0Wbeta11
+ 	readcf.c
+ 		=M support in test mode (values defined with %=, @=, *=, &=,
+ 		etc. are shown),
+ 	deliver.c
+ 		show preference values (defined with %= equate) in -bv mode.
+ 
+ Jan. 5, 1998/8.8.8+3.0Wbeta10
+ 	deliver.c, readcf.c:
+ 		Fix on MAILER_PREF.
+ 		Implementation in beta9 has not any effect.
+ 
+ Jan. 4, 1998/8.8.8+3.0Wbeta9
+ 	!!! CAUTION !!! MaxSendRcptPerMessage option is obsolete.
+ 	 Use &= equate at mailer definition instead.
+ 	new features:
+ 	  MAILER_PREF
+ 		Mailer preference can be defined in configuration file
+ 		to determin order to execute. Define numerical values
+ 		at %= equate on mailer definition lines. Lower values
+ 		are more prefered like MX RRs.
+ 	  CLIENT_SMTP_CONFIG
+ 		To configure parameters of client-side SMTP connection.
+ 		Define three parameters at @= equate on IPC mailer definition
+ 		lines: @=FQDN/SrcIPaddr/SrcPort
+ 			FQDN: FQDN used as a hostname with SMTP HELO
+ 			SrcIPaddr: source IP address for client-side SMTP
+ 			SrcPort: source port number for client-side SMTP
+ 		Default value will be used if a parameter omitted.
+ 	  CTE8CHECK
+ 		Manage incorrect CTE: 8bit header label (without 8bit data
+ 		in message body). To enable this feature, CTE8BitCheck
+ 		option should be defined in configuration file.
+ 			O CTE8BitCheck=correct	correct CTE to 7bit
+ 			O CTE8BitCheck=reject	reject such messages
+ 	  BOUNCE_REASON
+ 		Show reason on each address reported in bounceed message.
+ 	  OO_NULLSENDER
+ 		Set NULL sender address (<>) on messages delivered to
+ 		the alias entry, owner-owner.
+ 
+ Dec. 25, 1997/8.8.8+3.0Wbeta8
+ 	deliver.c:
+ 		fix on free() problem (in case of LMTP; around smtpgetstat())
+ 		reported by Fumitoshi UKAI <ukai@debian.or.jp>
+ 
+ Oct. 31, 1997/8.8.8+3.0Wbeta7
+ 	readcf.c:
+ 		value of O_MAXSENDRCPT
+ 	deliver.c:
+ 		behavior with mailer flag !
+ 
+ Oct. 27, 1997/8.8.8+3.0Wbeta5
+ 	sendmail.h, readcf.c, deliver.c:
+ 		mailer flag '!' and '-' added
+ 		*= equate added
+ 		mailer flag '2' removed
+ 
+ Oct. 26, 1997/8.8.8+3.0Wbeta4
+ 	applied to 8.8.8
+ 	usersmtp.c:
+ 		to manage LMTP response messages corrently
+ 
+ Oct. 24, 1997/8.8.7+3.0Wbeta3
+ 	deliver.c, sendmail.h:
+ 		mailer flag 2 added
+ 	readcf.c, deliver.c:
+ 		MaxSendRcptPerMessage added
+ 
+ Oct. 15, 1997/8.8.7+3.0Wbeta1
+ 	features (ANOTHER_MXPB, RCPT_NEXT, CONNECT_HACK, RESOLV_HACK,
+ 	STAT_HACK) deleted.
+ 
+ 
+ Aug. 20, 1997/8.8.7+2.7Wbeta7
+ 	deliver.c:
+ 		fix on syslog bufsize boundary problem
+ 		 suggested by Kenji Ikeda <ikeda@impress.co.jp>
+ 
+ Aug. 17, 1997/8.8.7+2.7Wbeta6
+ 	deliver.c:
+ 		fix on parameter mismatch for sm_syslog()
+ 		 reported by Makoto MATSUSHITA <matusita@ics.es.osaka-u.ac.jp>
+ 
+ Aug. 15, 1997/8.8.7+2.7Wbeta5
+ 	deliver.c:
+ 		counter implemented to restrict number of recipients less
+ 		than 101.
+ 	applied to 8.8.7
+ 
+ Feb. 2, 1997/8.8.5+2.7Wbeta5
+ 	deliver.c:
+ 		declare resethostsignature() at out side of funtions.
+ 		clear QDONTSEND flag when QQUEUEUP set
+ 	applied to 8.8.5
+ 
+ Dec. 4, 1996/8.8.4+2.7Wbeta4
+ 	deliver.c: LOCAL_FIRST added
+ 	again: compile failed if ANOTHER_MXPB && DYNAMIC_TOBUF
+ 
+ Dec. 4, 1996/8.8.4+2.7Wbeta3
+ 	deliver.c: algorithm changed for bufsize limitation checking
+ 	compile failed if ANOTHER_MXPB && DYNAMIC_TOBUF
+ 
+ Dec. 4, 1996/8.8.4+2.7Wbeta2
+ 	deliver.c: fix on dumping core when local delivery
+ 
+ Dec. 3, 1996/8.8.4+2.7Wbeta1
+ 	applied to 8.8.4
+ 	DYNAMIC_TOBUF hack is added in deliver.c.
+ 
+ Nov. 18, 1996/8.8.3+2.6Wbeta9-pre
+ 	applied to 8.8.3
+ 
+ Oct. 27, 1996/8.8.2+2.6Wbeta9
+ 	applied to 8.8.2
+ 	/usr/bsd added to PATH in newvers.sh
+ 	res_send.c is replaced by one in bind4.9.4-P1
+ 	static function decl. is moved to outside of a func.
+ 	 in domain.c, deliver.c
+ 
+ Sep. 19, 1996/8.7.6+2.6Wbeta8
+ 	applied to 8.7.6
+ 
+ Jul. 3, 1996/8.7.5+2.6Wbeta7
+ 	fix on DNS_AR_HACK in savemail.c and domain.c
+ 	 reported by Shigeki Yoshida <shige@iis.u-tokyo.ac.jp>
+ 	tweaks on res_send.c for .nomx in Patch-makefiles
+ 	 reported bu y-koga@ccs.mt.nec.co.jp
+ 
+ Apr. 18, 1996/8.7.5+2.6Wbeta6
+ 	applied to 8.7.5
+ 
+ Feb. 23, 1996/8.7.4+2.6Wbeta6
+ 	applied to 8.7.4
+ 
+ Jan. 26, 1996/8.7.3+2.6Wbeta5
+ 	applied to 8.7.3
+ 	fix CONNECT_HACK to use all multiple A records
+ 
+ Oct. 21, 1995/8.7.1+2.6Wbeta4
+ 	applied to 8.7.1
+ 
+ Oct. 11, 1995/8.7+2.6Wbeta4
+ 	fix on MULTIMAILER hack
+ 
+ Sep. 26, 1995/8.7+2.6Wbeta2
+ 	flag bit for RES_NONBLOCK is changed
+ 
+ Sep. 25, 1995/8.7+2.6Wbeta2
+ 	turn off CANON_OTHER flag if NAMED_BIND == 0
+ 
+ Sep. 20, 1995/8.7+2.6Wbeta
+ 	Beta release
diff -c ../sendmail.org/alias.c ./alias.c
*** ../sendmail.org/alias.c	Sat Sep 23 01:30:09 2000
--- ./alias.c	Thu Nov 16 02:29:38 2000
***************
*** 13,19 ****
  #include <sendmail.h>
  
  #ifndef lint
! static char id[] = "@(#)$Id: alias.c,v 8.142.4.3 2000/09/21 21:52:16 ca Exp $";
  #endif /* ! lint */
  
  # define SEPARATOR ':'
--- 13,20 ----
  #include <sendmail.h>
  
  #ifndef lint
! static char id[] = "@(#)$Id: alias.c,v 8.142.4.3 2000/09/21 21:52:16 ca Exp";
! static char Wid[] = "@(#)$Id: alias.c,v 1.3 2000/11/15 17:29:29 motonori Exp $";
  #endif /* ! lint */
  
  # define SEPARATOR ':'
***************
*** 160,165 ****
--- 161,172 ----
  	**  Look for owner of alias
  	*/
  
+ #if OO_NULLSENDER
+ 	if (strcmp(a->q_user, "owner-owner") == 0)
+ 		owner = "<>";
+ 	else
+ 	{
+ #endif
  	(void) strlcpy(obuf, "owner-", sizeof obuf);
  	if (strncmp(a->q_user, "owner-", 6) == 0 ||
  	    strlen(a->q_user) > (SIZE_T) sizeof obuf - 7)
***************
*** 167,172 ****
--- 174,182 ----
  	else
  		(void) strlcat(obuf, a->q_user, sizeof obuf);
  	owner = aliaslookup(obuf, &status);
+ #if OO_NULLSENDER
+ 	}
+ #endif
  	if (owner == NULL)
  		return;
  
diff -c ../sendmail.org/collect.c ./collect.c
*** ../sendmail.org/collect.c	Sat Sep 23 01:30:09 2000
--- ./collect.c	Thu Nov 16 02:29:41 2000
***************
*** 12,18 ****
   */
  
  #ifndef lint
! static char id[] = "@(#)$Id: collect.c,v 8.136.4.6 2000/09/21 21:52:16 ca Exp $";
  #endif /* ! lint */
  
  #include <sendmail.h>
--- 12,19 ----
   */
  
  #ifndef lint
! static char id[] = "@(#)$Id: collect.c,v 8.136.4.6 2000/09/21 21:52:16 ca Exp";
! static char Wid[] = "@(#)$Id: collect.c,v 1.3 2000/11/15 17:29:29 motonori Exp $";
  #endif /* ! lint */
  
  #include <sendmail.h>
***************
*** 662,667 ****
--- 663,700 ----
  		}
  	}
  
+ #if _MICROSOFT_TIMEZONE_HACK_ /* just a sample code */
+ #define DOMAIN_PART	"domain.part.of.mail.address.for.clients"
+ {
+ 	char *p, *pp;
+ 	int l;
+ 
+ 	if (e->e_hopcount <= 1)
+ 	{
+ 		p = strchr(e->e_sender, '@');
+ 		if (p != NULL && strcasecmp(++p, DOMAIN_PART) == 0)
+ 		{
+ 			p = hvalue("x-mailer", e->e_header);
+ 			if (p != NULL && strstr(p, "Microsoft") != NULL)
+ 			{
+ 				p = hvalue("date", e->e_header);
+ 				if (p != NULL && (l = strlen(p)) > 5)
+ 				{
+ 					pp = p + l - 5;
+ 					if (strcmp(pp, "-0000") == 0 ||
+ 					    strcmp(pp, "+1000") == 0)
+ 					{
+ 						pp[0] = '+';
+ 						pp[1] = '0';
+ 						pp[2] = '9';
+ 					}
+ 				}
+ 			}
+ 		}
+ 	}
+ }
+ #endif
+ 
  	/* check for message too large */
  	if (bitset(EF_TOOBIG, e->e_flags))
  	{
***************
*** 689,698 ****
--- 722,770 ----
  	}
  	else
  	{
+ #if CTE8CHECK
+ 		char *p, buf[MAXLINE];
+ #endif
  		/* if it claimed to be 8 bits, well, it lied.... */
  		if (e->e_bodytype != NULL &&
  		    strcasecmp(e->e_bodytype, "8BITMIME") == 0)
  			e->e_bodytype = "7BIT";
+ #if CTE8CHECK
+ 		p = hvalue("Content-Transfer-Encoding", e->e_header);
+ 		if (CTE8BitCheck != NULL && bitset(EF_IS_MIME, e->e_flags) &&
+ 		    p != NULL && (strcasecmp(p, "8bit") == 0))
+ 		{
+ 			HDR *h;
+ 
+ 			switch (*CTE8BitCheck) {
+ 			  case 'c':	/* correct */
+ 				for (h = e->e_header; h != NULL; h = h->h_link)
+ 				{
+ 					if (strcasecmp(h->h_field, "Content-Transfer-Encoding") == 0)
+ 					{
+ 						if (h->h_value != NULL)
+ 							free(h->h_value);
+ 						h->h_value = newstr("7bit");
+ 					}
+ 				}
+ 				snprintf(buf, sizeof buf,
+ 					"Content-Transfer-Encoding from 8bit to 7bit by %s id %s",
+ 					MyHostName, e->e_id);
+ 
+ 				addheader("X-MIME-Autoconverted:", buf, 0,
+ 					&e->e_header);
+ 				break;
+ 			  case 'r':	/* reject */
+ 				e->e_status = "5.6.1";
+ 				usrerrenh(e->e_status, "554 Seven bit data with eight bit label not allowed");
+ #if 1
+ 				sm_syslog(LOG_NOTICE, e->e_id,
+ 					"seven bit data with eight bit label not allowed");
+ #endif
+ 				break;
+ 			}
+ 		}
+ #endif
  	}
  
  	if (SuperSafe)
diff -c ../sendmail.org/conf.c ./conf.c
*** ../sendmail.org/conf.c	Sun Sep 24 01:54:01 2000
--- ./conf.c	Thu Nov 16 02:29:42 2000
***************
*** 12,18 ****
   */
  
  #ifndef lint
! static char id[] = "@(#)$Id: conf.c,v 8.646.2.2.2.32 2000/09/23 00:31:33 ca Exp $";
  #endif /* ! lint */
  
  #include <sendmail.h>
--- 12,19 ----
   */
  
  #ifndef lint
! static char id[] = "@(#)$Id: conf.c,v 8.646.2.2.2.32 2000/09/23 00:31:33 ca Exp";
! static char Wid[] = "@(#)$Id: conf.c,v 1.3 2000/11/15 17:29:29 motonori Exp $";
  #endif /* ! lint */
  
  #include <sendmail.h>
***************
*** 505,510 ****
--- 506,517 ----
  		map_parseargs, text_map_open, null_map_close,
  		text_map_lookup, null_map_store);
  
+ #if MASKED_ADDR
+ 	MAPDEF("maskedaddr", NULL, MCF_ALIASOK,
+ 		map_parseargs, maskedaddr_map_open, null_map_close,
+ 		maskedaddr_map_lookup, null_map_store);
+ #endif
+ 
  	MAPDEF("stab", NULL, MCF_ALIASOK|MCF_ALIASONLY,
  		map_parseargs, stab_map_open, null_map_close,
  		stab_map_lookup, stab_map_store);
***************
*** 5561,5566 ****
--- 5568,5615 ----
  #ifdef XLA
  	"XLA",
  #endif /* XLA */
+ #if QUICK_RESPONSE
+ 	"QUICK_RESPONSE",
+ #endif
+ #if MULTI_MAILER
+ 	"MULTI_MAILER",
+ #endif
+ #if _FFR_DYNAMIC_TOBUF
+ 	"DYNAMIC_TOBUF",
+ #endif
+ #if MAILER_PREF
+ 	"MAILER_PREF",
+ #endif
+ #if CLIENT_SMTP_CONFIG
+ 	"CLIENT_SMTP_CONFIG",
+ #endif
+ #if CTE8CHECK
+ 	"CTE8CHECK",
+ #endif
+ #if OO_NULLSENDER
+ 	"OO_NULLSENDER",
+ #endif
+ #if CF_ALIASING
+ 	"CF_ALIASING",
+ #endif
+ #if MF_SEPARATE
+ 	"MF_SEPARATE",
+ #endif
+ #if MASKED_ADDR
+ 	"MASKED_ADDR",
+ #endif
+ #if SPR_CON_CACHE
+ 	"SPR_CON_CACHE",
+ #endif
+ #if FORWARDPROGCTL
+ 	"FORWARDPROGCTL",
+ #endif
+ #if MAILER_TIMEOUTS
+ 	"MAILER_TIMEOUTS",
+ #endif
+ #if CHECK_WARNING
+ 	"CHECK_WARNING",
+ #endif
  	NULL
  };
  
diff -c ../sendmail.org/conf.h ./conf.h
*** ../sendmail.org/conf.h	Thu Aug 10 01:14:39 2000
--- ./conf.h	Thu Nov 16 02:29:44 2000
***************
*** 10,16 ****
   * the sendmail distribution.
   *
   *
!  *	$Id: conf.h,v 8.496.4.25 2000/08/08 23:50:40 ca Exp $
   */
  
  /*
--- 10,17 ----
   * the sendmail distribution.
   *
   *
!  *	$Id: conf.h,v 8.496.4.25 2000/08/08 23:50:40 ca Exp
!  *	$Id: conf.h,v 1.2 2000/11/15 17:29:29 motonori Exp $
   */
  
  /*
***************
*** 44,49 ****
--- 45,71 ----
  # include <netdb.h>
  # include <pwd.h>
  # include <grp.h>
+ 
+ /* ==================  Enhancements of WIDE version  ================== */
+ # define QUICK_RESPONSE	1	/* not queue up error response even with -odq */
+ # define MULTI_MAILER	1	/* enable multiple mailer dispatching feature */
+ # define _FFR_DYNAMIC_TOBUF 1	/* enable tobuf[] dynamic allocation */
+ # define MAILER_PREF	1	/* enable mailer preference configuration */
+ # define CLIENT_SMTP_CONFIG 1	/* enable configuration for SMTP client */
+ # define CTE8CHECK	1	/* enable incorrect CTE: 8bit checking */
+ # define OO_NULLSENDER	1	/* set NULL sender for owner-owner */
+ # define CF_ALIASING	1	/* enable aliasing in ruleset 5 */
+ # define MF_SEPARATE	1	/* enable mailerflag + not to suppress dups */
+ # define MASKED_ADDR	1	/* enable masked class matching/maskaddr map */
+ # define SPR_CON_CACHE	1	/* enable mailerflag ; not to cache conn. */
+ # define FORWARDPROGCTL	1	/* control forwarding to program on .forward */
+ # define MAILER_TIMEOUTS 1	/* timeouts configuration par mailer */
+ # define CHECK_WARNING	1	/* use ruleset for decision on delay warning */
+ # define RCPT_HASH	1	/* use hash to check address duplicates */
+ /* ===========================  parameters  =========================== */
+ /* for MULTI_MAILER */
+ # define MAXDSPTMAILERS	3	/* max # of dispatching mailers in one rule */
+ /* ==================================================================== */
  
  /* make sure TOBUFSIZ isn't larger than system limit for size of exec() args */
  #ifdef ARG_MAX
diff -c ../sendmail.org/deliver.c ./deliver.c
*** ../sendmail.org/deliver.c	Sat Sep 23 01:30:09 2000
--- ./deliver.c	Thu Nov 16 02:29:45 2000
***************
*** 12,18 ****
   */
  
  #ifndef lint
! static char id[] = "@(#)$Id: deliver.c,v 8.600.2.1.2.44 2000/09/21 21:52:17 ca Exp $";
  #endif /* ! lint */
  
  #include <sendmail.h>
--- 12,19 ----
   */
  
  #ifndef lint
! static char id[] = "@(#)$Id: deliver.c,v 8.600.2.1.2.44 2000/09/21 21:52:17 ca Exp";
! static char Wid[] = "@(#)$Id: deliver.c,v 1.4 2000/11/15 17:29:29 motonori Exp $";
  #endif /* ! lint */
  
  #include <sendmail.h>
***************
*** 725,730 ****
--- 726,735 ----
  	int mode;
  {
  	register ADDRESS *q;
+ #if MAILER_PREF
+ 	ADDRESS *qnext, *newqhead, *qq, *qqlast;
+ 	int i;
+ #endif
  	bool didany;
  
  	if (tTd(13, 10))
***************
*** 769,774 ****
--- 774,911 ----
  	define(macid("{bodytype}", NULL), e->e_bodytype, e);
  	didany = FALSE;
  
+ #if MAILER_PREF
+ 	/* move more un-prefered recipients later */
+ 	for (i = 0; i < MAXMAILERS; i++)
+ 	{
+ 		if (Mailer[i] != NULL)
+ 		{
+ 			Mailer[i]->m_addrtail = NULL;
+ 			Mailer[i]->m_addrhead = NULL;
+ 		}
+ 	}
+ 	newqhead = NULL;
+ 
+ 	for (q = e->e_sendqueue; q != NULL; q = qnext)
+ 	{
+ 		qnext = q->q_next;
+ 
+ 		if (newqhead == NULL)
+ 		{
+ 			/* first recipient */
+ 			newqhead = q;
+ 			q->q_mailer->m_addrtail = q;
+ 			q->q_mailer->m_addrhead = q;
+ 			q->q_next = NULL;
+ 		}
+ 		else if (q->q_mailer->m_addrtail == NULL)
+ 		{
+ 			/* only for the first recipient of the mailer */
+ 			/* finding insertion point */
+ 			q->q_mailer->m_addrtail = q;
+ 			q->q_mailer->m_addrhead = q;
+ 			for (qqlast = NULL, qq = newqhead; qq != NULL;
+ 				qqlast = qq, qq = qq->q_next)
+ 			{
+ 				if (qq->q_mailer == q->q_mailer)
+ 				{
+ 					/* skip to the tail */
+ 					qq = q->q_mailer->m_addrtail;
+ 					continue;
+ 				}
+ 				if (qq->q_mailer->m_pref > q->q_mailer->m_pref)
+ 					break;
+ 			}
+ 			if (qq == NULL)
+ 				q->q_next = NULL; /* append at the tail */
+ 			else
+ 			{
+ 				q->q_next = qq;
+ 			}
+ 			if (qq == newqhead)
+ 				newqhead = q;
+ 			else
+ 				qqlast->q_next = q;
+ 		}
+ 		else if (bitnset(M_SORT, q->q_mailer->m_flags))
+ 		{
+ 			/* insert in order */
+ 
+ 			char a[512], b[512];
+ 
+ #define strrev(d, s, l)	{ \
+ 				char *sp = s + strlen(s) - 1; \
+ 				char *dp = d; \
+ 				int ll = l; \
+ 				while (--ll > 0 && sp >= s) \
+ 				{ \
+ 					if (*sp == '@') \
+ 						break; \
+ 					*dp++ = *sp--; \
+ 				} \
+ 				*dp = '\0'; \
+ 			}
+ 
+ 			strrev(a, q->q_user, sizeof(a));
+ 			qqlast = NULL;
+ 			/* XXX lenear search should be avoided */
+ 			for (qq = q->q_mailer->m_addrhead;; qq = qq->q_next)
+ 			{
+ 				strrev(b, qq->q_user, sizeof(b));
+ 				if (strcasecmp(a, b) < 0)
+ 					break;
+ 				if (qq == q->q_mailer->m_addrtail)
+ 				{
+ 					qq = NULL;
+ 					break;
+ 				}
+ 				qqlast = qq;
+ 			}
+ 
+ 			if (qq == NULL)
+ 			{
+ 				/* append at the tail */
+ 				q->q_next = q->q_mailer->m_addrtail->q_next;
+ 				q->q_mailer->m_addrtail->q_next = q;
+ 				q->q_mailer->m_addrtail = q;
+ 			}
+ 			else if (qqlast == NULL)
+ 			{
+ 				/* insert at the head */
+ 				q->q_next = q->q_mailer->m_addrhead;
+ 				q->q_mailer->m_addrhead = q;
+ 				if (newqhead == q->q_next)
+ 					newqhead = q;
+ 				else for (i = 0; i < MAXMAILERS; i++)
+ 				{
+ 					if (Mailer[i] != NULL &&
+ 					    Mailer[i]->m_addrtail != NULL &&
+ 					    Mailer[i]->m_addrtail->q_next == qq)
+ 					{
+ 						Mailer[i]->m_addrtail->q_next
+ 							= q;
+ 						break;
+ 					}
+ 				}
+ 			}
+ 			else
+ 			{
+ 				/* insert after *qqlast */
+ 				q->q_next = qqlast->q_next;
+ 				qqlast->q_next = q;
+ 			}
+ 		}
+ 		else
+ 		{
+ 			/* just insert */
+ 			q->q_next = q->q_mailer->m_addrtail->q_next;
+ 			q->q_mailer->m_addrtail->q_next = q;
+ 			q->q_mailer->m_addrtail = q;
+ 		}
+ 	}
+ 	e->e_sendqueue = newqhead;
+ #endif
+ 
  	/* now run through the queue */
  	for (q = e->e_sendqueue; q != NULL; q = q->q_next)
  	{
***************
*** 784,789 ****
--- 921,939 ----
  			e->e_to = q->q_paddr;
  			if (QS_IS_SENDABLE(q->q_state))
  			{
+ #if MAILER_PREF
+ 				if (q->q_host != NULL && q->q_host[0] != '\0')
+ 					message("deliverable: mailer %s (pref=%d), host %s, user %s",
+ 						q->q_mailer->m_name,
+ 						q->q_mailer->m_pref,
+ 						q->q_host,
+ 						q->q_user);
+ 				else
+ 					message("deliverable: mailer %s (pref=%d), user %s",
+ 						q->q_mailer->m_name,
+ 						q->q_mailer->m_pref,
+ 						q->q_user);
+ #else
  				if (q->q_host != NULL && q->q_host[0] != '\0')
  					message("deliverable: mailer %s, host %s, user %s",
  						q->q_mailer->m_name,
***************
*** 793,798 ****
--- 943,949 ----
  					message("deliverable: mailer %s, user %s",
  						q->q_mailer->m_name,
  						q->q_user);
+ #endif
  			}
  		}
  		else if (QS_IS_OK(q->q_state))
***************
*** 1004,1009 ****
--- 1155,1163 ----
  	int rcptcount;
  	static int tobufsize = 0;
  	static char *tobuf = NULL;
+ #if 1
+ 	int tobuflen;
+ #endif
  #else /* _FFR_DYNAMIC_TOBUF */
  	char tobuf[TOBUFSIZE];		/* text line of to people */
  #endif /* _FFR_DYNAMIC_TOBUF */
***************
*** 1013,1018 ****
--- 1167,1175 ----
  	char *pv[MAXPV + 1];
  	char buf[MAXNAME + 1];
  	char rpathbuf[MAXNAME + 1];	/* translated return path */
+ #if MULTI_MAILER
+     retry_deliver:	/* retry on next MX/mailer  */
+ #endif
  
  	errno = 0;
  	if (!QS_IS_OK(to->q_state))
***************
*** 1215,1222 ****
--- 1372,1384 ----
  		**  Check also for overflow of e_msgsize.
  		*/
  
+ #if MULTI_MAILER
+ 		if (to->q_mailers[1] == NULL && m->m_maxsize != 0 &&
+ 		    (e->e_msgsize > m->m_maxsize || e->e_msgsize < 0))
+ #else
  		if (m->m_maxsize != 0 &&
  		    (e->e_msgsize > m->m_maxsize || e->e_msgsize < 0))
+ #endif
  		{
  			e->e_flags |= EF_NO_BODY_RETN;
  			if (bitnset(M_LOCALMAILER, to->q_mailer->m_flags))
***************
*** 1416,1421 ****
--- 1578,1623 ----
  		}
  	}
  
+ #if MULTI_MAILER
+ 	if (firstto->q_mailers[1] != NULL)
+ 	{
+ 		if (firstto->q_mailer->m_rmin > 0
+ 		 && rcptcount < firstto->q_mailer->m_rmin)
+ 		{
+ 			/* skip to next mailer */
+ 			sm_syslog(LOG_INFO, e->e_id,
+ 				"skip mailer: recipients = %d", rcptcount);
+ 			mci = NULL;
+ 			goto nextmailer;
+ 		}
+ 		if (firstto->q_mailer->m_maxsize != 0
+ 		 && e->e_msgsize > firstto->q_mailer->m_maxsize)
+ 		{
+ 			/* skip to next mailer */
+ 			sm_syslog(LOG_INFO, e->e_id,
+ 				"skip mailer: message size = %d", e->e_msgsize);
+ 			mci = NULL;
+ 			goto nextmailer;
+ 		}
+ 		if (bitnset(M_DIRECTONLY, firstto->q_mailer->m_flags)
+ 		 && e->e_ntries > 0)
+ 		{
+ 			/* skip to next mailer */
+ 			sm_syslog(LOG_INFO, e->e_id,
+ 				"skip mailer: retry count = %d", e->e_ntries);
+ 			mci = NULL;
+ 			goto nextmailer;
+ 		}
+ 	}
+ 	if (bitnset(M_NONEXT, firstto->q_mailer->m_flags))
+ 	{
+ 		for (to = tochain; to != NULL; to = to->q_tchain)
+ 		{
+ 			to->q_mailers[1] = NULL;
+ 		}
+ 	}
+ #endif
+ 
  	/* see if any addresses still exist */
  #if _FFR_DYNAMIC_TOBUF
  	if (tochain == NULL)
***************
*** 1720,1725 ****
--- 1922,1930 ----
  			{
  				goodmxfound = TRUE;
  				mci->mci_state = MCIS_OPENING;
+ #if SPR_CON_CACHE
+ 				if (!bitnset(M_NOCACHE, m->m_flags))
+ #endif
  				mci_cache(mci);
  				if (TrafficLogFile != NULL)
  					fprintf(TrafficLogFile, "%05d === CONNECT %s\n",
***************
*** 2166,2171 ****
--- 2371,2408 ----
  			/* run disconnected from terminal */
  			(void) setsid();
  
+ #if 1	/* to pass some information to SMTPfeed */
+ 		{
+ 			char lbuf[32];
+ 			snprintf(lbuf, sizeof(lbuf), "%d", e->e_stime);
+ 			setuserenv("SM_START_TIME", lbuf);
+ 		}
+ #endif
+ #if 1 /* to see real local addresses */
+ 			if (LogLevel > 9)
+ 			{
+ 				char execstr[SYSLOG_BUFSIZE];
+ 				char **p = pv;
+ 				int l;
+ 
+ 				strncpy(execstr, pv[0], sizeof(execstr) - 4);
+ 				if (strlen(pv[0]) >= sizeof(execstr) - 4)
+ 					execstr[sizeof(execstr)-1] = '\0';
+ 				l = strlen(execstr);
+ 				p++;
+ 				while (*p != NULL &&
+ 				      l + strlen(*p) + 1 <= sizeof(execstr) - 4)
+ 				{
+ 					execstr[l++] = ' ';
+ 					strcpy(execstr + l, *p);
+ 					l += strlen(*p);
+ 					p++;
+ 				}
+ 				if (*p != NULL)
+ 					strcpy(execstr + l, " ...");
+ 				sm_syslog(LOG_INFO, e->e_id, "EXEC: %s", execstr);
+ 			}
+ #endif
  			/* try to execute the mailer */
  			(void) execve(m->m_mailer, (ARGV_T) pv,
  				      (ARGV_T) UserEnviron);
***************
*** 2190,2195 ****
--- 2427,2435 ----
  		if (clever)
  		{
  			mci->mci_state = MCIS_OPENING;
+ #if SPR_CON_CACHE
+ 			if (!bitnset(M_NOCACHE, m->m_flags))
+ #endif
  			mci_cache(mci);
  		}
  		else
***************
*** 2686,2691 ****
--- 2926,2934 ----
  		lmtp_rcode = rcode;
  		tobuf[0] = '\0';
  		anyok = FALSE;
+ #if _FFR_DYNAMIC_TOBUF
+ 		tobuflen = 0;
+ #endif /* _FFR_DYNAMIC_TOBUF */
  	}
  	else
  #endif /* SMTP */
***************
*** 2706,2713 ****
--- 2949,2965 ----
  			if (rcode == EX_OK)
  			{
  #if _FFR_DYNAMIC_TOBUF
+ #if 0
  				(void) strlcat(tobuf, ",", tobufsize);
  				(void) strlcat(tobuf, to->q_paddr, tobufsize);
+ #else
+ 				(void) strlcat(tobuf+tobuflen, ",",
+ 					tobufsize-tobuflen);
+ 				tobuflen++;
+ 				(void) strlcat(tobuf+tobuflen, to->q_paddr,
+ 					tobufsize-tobuflen);
+ 				tobuflen += strlen(to->q_paddr);
+ #endif
  #else /* _FFR_DYNAMIC_TOBUF */
  				if (strlen(to->q_paddr) +
  				    strlen(tobuf) + 2 > sizeof tobuf)
***************
*** 2801,2806 ****
--- 3053,3109 ----
  
  	if (tobuf[0] != '\0')
  		giveresponse(rcode, NULL, m, mci, ctladdr, xstart, e);
+ # if MULTI_MAILER
+ 	else
+ 	{
+ 		bool mailer_changed;
+ 		int i;
+ 
+   nextmailer:
+ 		mailer_changed = FALSE;
+ 		if (firstto->q_mailers[1] != NULL)
+ 		{
+ 			mailer_changed = TRUE;
+ 		}
+ 		for (to = tochain; to != NULL; to = to->q_tchain)
+ 		{
+ 			if (to->q_mailers[1] != NULL) {
+ 				to->q_state = QS_OK;
+ 				/* change to next mailer */
+ 				for (i = 0; i < MAXDSPTMAILERS - 1; i++)
+ 				{
+ 					to->q_mailers[i] = to->q_mailers[i+1];
+ 					to->q_hosts[i] = to->q_hosts[i+1];
+ 					to->q_users[i] = to->q_users[i+1];
+ 				}
+ 				to->q_mailers[MAXDSPTMAILERS-1] = NULL;
+ 				to->q_hosts[MAXDSPTMAILERS-1] = NULL;
+ 				to->q_users[MAXDSPTMAILERS-1] = NULL;
+ 			}
+ 			else if (mailer_changed)
+ 			{
+ 				markfailure(e, to, mci, rcode, TRUE);
+ 			}
+ 			/* if not changed, will be done later */
+ 		}
+ 		if (mailer_changed)
+ 		{
+ 			mci_store_persistent(mci);
+ #if SMTP
+ 			/* now close the connection */
+ 			if (clever && mci != NULL &&
+ 			    mci->mci_state != MCIS_CLOSED &&
+ 			    !bitset(MCIF_CACHED, mci->mci_flags))
+ 				smtpquit(m, mci, e);
+ #endif
+ 			/* re-initialize variables */
+ 			to = firstto;
+ 			clever = FALSE;
+ 			tochain = NULL;
+ 			goto retry_deliver;
+ 		}
+ 	}
+ # endif
  	if (anyok)
  		markstats(e, tochain, FALSE);
  	mci_store_persistent(mci);
diff -c ../sendmail.org/envelope.c ./envelope.c
*** ../sendmail.org/envelope.c	Wed Aug 23 10:14:07 2000
--- ./envelope.c	Thu Nov 16 02:29:45 2000
***************
*** 12,18 ****
   */
  
  #ifndef lint
! static char id[] = "@(#)$Id: envelope.c,v 8.180.14.4 2000/08/22 18:22:39 gshapiro Exp $";
  #endif /* ! lint */
  
  #include <sendmail.h>
--- 12,19 ----
   */
  
  #ifndef lint
! static char id[] = "@(#)$Id: envelope.c,v 8.180.14.4 2000/08/22 18:22:39 gshapiro Exp";
! static char Wid[] = "@(#)$Id: envelope.c,v 1.3 2000/11/15 17:29:29 motonori Exp $";
  #endif /* ! lint */
  
  #include <sendmail.h>
***************
*** 92,97 ****
--- 93,102 ----
  	register ADDRESS *q;
  	char *id = e->e_id;
  	char buf[MAXLINE];
+ #if MAILER_TIMEOUTS
+ 	bool no_expire = FALSE;
+ 	int to_r = 0;
+ #endif
  
  	if (tTd(50, 1))
  	{
***************
*** 130,137 ****
--- 135,144 ----
  	**  Extract state information from dregs of send list.
  	*/
  
+ #if !MAILER_TIMEOUTS
  	if (curtime() > e->e_ctime + TimeOuts.to_q_return[e->e_timeoutclass])
  		message_timeout = TRUE;
+ #endif
  
  	if (TimeOuts.to_q_return[e->e_timeoutclass] == NOW &&
  	    !bitset(EF_RESPONSE, e->e_flags))
***************
*** 143,148 ****
--- 150,167 ----
  	e->e_flags &= ~EF_QUEUERUN;
  	for (q = e->e_sendqueue; q != NULL; q = q->q_next)
  	{
+ #if MAILER_TIMEOUTS
+ 		int to1;
+ 
+ 		if (q->q_mailer->m_to_q_return > 0)
+ 			to1 = q->q_mailer->m_to_q_return;
+ 		else
+ 			to1 = TimeOuts.to_q_return[e->e_timeoutclass];
+ 		if (!message_timeout && curtime() > e->e_ctime + to1)
+ 			message_timeout = TRUE;
+ 		else
+ 			no_expire = TRUE;
+ #endif
  		if (QS_IS_UNDELIVERED(q->q_state))
  			queueit = TRUE;
  
***************
*** 162,167 ****
--- 181,190 ----
  						  &e->e_errorqueue, 0, e);
  				done = TRUE;
  			}
+ #if MAILER_TIMEOUTS
+ 			if (to_r < to1)
+ 				to_r = to1;
+ #endif
  		}
  		else if (bitset(QPINGONSUCCESS, q->q_flags) &&
  			 ((QS_IS_SENT(q->q_state) &&
***************
*** 186,205 ****
--- 209,255 ----
  	{
  		if (failure_return)
  		{
+ #if MAILER_TIMEOUTS
+ 			(void) snprintf(buf, sizeof buf,
+ 					"Cannot send message for %s",
+ 					pintvl(to_r, FALSE));
+ #else
  			(void) snprintf(buf, sizeof buf,
  					"Cannot send message for %s",
  					pintvl(TimeOuts.to_q_return[e->e_timeoutclass], FALSE));
+ #endif
  			if (e->e_message != NULL)
  				free(e->e_message);
  			e->e_message = newstr(buf);
  			message(buf);
+ #if MAILER_TIMEOUTS
+ 			if (!no_expire)
+ #endif
  			e->e_flags |= EF_CLRQUEUE;
  		}
+ #if MAILER_TIMEOUTS
+ 		fprintf(e->e_xfp, "Message could not be delivered for %s\n",
+ 			pintvl(to_r, FALSE));
+ #else
  		fprintf(e->e_xfp, "Message could not be delivered for %s\n",
  			pintvl(TimeOuts.to_q_return[e->e_timeoutclass], FALSE));
+ #endif
+ #if MAILER_TIMEOUTS
+ 		if (!no_expire)
+ #endif
  		fprintf(e->e_xfp, "Message will be deleted from queue\n");
  		for (q = e->e_sendqueue; q != NULL; q = q->q_next)
  		{
+ #if MAILER_TIMEOUTS
+ 			int to1;
+ 
+ 			if (q->q_mailer->m_to_q_return > 0)
+ 				to1 = q->q_mailer->m_to_q_return;
+ 			else
+ 				to1 = TimeOuts.to_q_return[e->e_timeoutclass];
+ 			if (curtime() <= e->e_ctime + to1)
+ 				continue;
+ #endif
  			if (QS_IS_UNDELIVERED(q->q_state))
  			{
  				q->q_state = QS_BADADDR;
***************
*** 210,222 ****
--- 260,286 ----
  	else if (TimeOuts.to_q_warning[e->e_timeoutclass] > 0 &&
  	    curtime() > e->e_ctime + TimeOuts.to_q_warning[e->e_timeoutclass])
  	{
+ #if CHECK_WARNING
+ # define OPR		0	/* operator */
+ 		extern u_char TokTypeTab[];
+ 		u_char savetok = TokTypeTab['-'];
+ 		TokTypeTab['-'] = OPR;
+ #endif
  		if (!bitset(EF_WARNING|EF_RESPONSE, e->e_flags) &&
  		    e->e_class >= 0 &&
  		    e->e_from.q_paddr != NULL &&
  		    strcmp(e->e_from.q_paddr, "<>") != 0 &&
  		    strncasecmp(e->e_from.q_paddr, "owner-", 6) != 0 &&
+ #if CHECK_WARNING
+ 		    (strlen(e->e_from.q_paddr) <= (SIZE_T) 8 ||
+ 		     strcasecmp(&e->e_from.q_paddr[strlen(e->e_from.q_paddr) - 8], "-request") != 0) &&
+ 		    (strtorwset("check_warning", NULL, ST_FIND) < 0 ||
+ 		     rscheck("check_warning", e->e_from.q_paddr,
+ 			     NULL, e, TRUE, TRUE, 4) != EX_OK))
+ #else
  		    (strlen(e->e_from.q_paddr) <= (SIZE_T) 8 ||
  		     strcasecmp(&e->e_from.q_paddr[strlen(e->e_from.q_paddr) - 8], "-request") != 0))
+ #endif
  		{
  			for (q = e->e_sendqueue; q != NULL; q = q->q_next)
  			{
***************
*** 247,252 ****
--- 311,319 ----
  			pintvl(TimeOuts.to_q_warning[e->e_timeoutclass], FALSE));
  		fprintf(e->e_xfp, "Will keep trying until message is %s old\n",
  			pintvl(TimeOuts.to_q_return[e->e_timeoutclass], FALSE));
+ #if CHECK_WARNING
+ 		TokTypeTab['-'] = savetok;
+ #endif
  	}
  
  	if (tTd(50, 2))
***************
*** 467,472 ****
--- 534,542 ----
  	setnewqueue(e);
  	openxscript(e);
  	e->e_ctime = curtime();
+ #if 1	/* start time of sendmail to pass to SMTPfeed for statistics */
+ 	e->e_stime = e->e_ctime;
+ #endif
  #if _FFR_QUEUEDELAY
  	e->e_queuealg = QueueAlg;
  	e->e_queuedelay = QueueInitDelay;
diff -c ../sendmail.org/headers.c ./headers.c
*** ../sendmail.org/headers.c	Wed Aug 23 10:14:07 2000
--- ./headers.c	Thu Nov 16 02:29:46 2000
***************
*** 12,18 ****
   */
  
  #ifndef lint
! static char id[] = "@(#)$Id: headers.c,v 8.203.4.7 2000/08/22 21:50:36 gshapiro Exp $";
  #endif /* ! lint */
  
  #include <sendmail.h>
--- 12,19 ----
   */
  
  #ifndef lint
! static char id[] = "@(#)$Id: headers.c,v 8.203.4.7 2000/08/22 21:50:36 gshapiro Exp";
! static char Wid[] = "@(#)$Id: headers.c,v 1.3 2000/11/15 17:29:29 motonori Exp $";
  #endif /* ! lint */
  
  #include <sendmail.h>
***************
*** 634,641 ****
--- 635,648 ----
  		}
  
  		/* do early binding */
+ #if 1	/* do not bind $h early */
+ 		if (bitset(H_DEFAULT, h->h_flags) &&
+ 		    !bitset(H_BINDLATE, h->h_flags) &&
+ 		    strstr("\201h", h->h_value) == NULL)
+ #else
  		if (bitset(H_DEFAULT, h->h_flags) &&
  		    !bitset(H_BINDLATE, h->h_flags))
+ #endif
  		{
  			if (tTd(32, 1))
  			{
diff -c ../sendmail.org/main.c ./main.c
*** ../sendmail.org/main.c	Wed Sep 27 13:07:25 2000
--- ./main.c	Thu Nov 16 02:29:47 2000
***************
*** 21,27 ****
  #endif /* ! lint */
  
  #ifndef lint
! static char id[] = "@(#)$Id: main.c,v 8.485.4.27 2000/09/26 01:30:38 gshapiro Exp $";
  #endif /* ! lint */
  
  #define	_DEFINE
--- 21,28 ----
  #endif /* ! lint */
  
  #ifndef lint
! static char id[] = "@(#)$Id: main.c,v 8.485.4.27 2000/09/26 01:30:38 gshapiro Exp";
! static char Wid[] = "@(#)$Id: main.c,v 1.4 2000/11/15 17:29:29 motonori Exp $";
  #endif /* ! lint */
  
  #define	_DEFINE
diff -c ../sendmail.org/map.c ./map.c
*** ../sendmail.org/map.c	Wed Sep 27 13:11:29 2000
--- ./map.c	Thu Nov 16 02:29:47 2000
***************
*** 12,18 ****
   */
  
  #ifndef lint
! static char id[] = "@(#)$Id: map.c,v 8.414.4.24 2000/09/27 04:11:29 gshapiro Exp $";
  #endif /* ! lint */
  
  #include <sendmail.h>
--- 12,19 ----
   */
  
  #ifndef lint
! static char id[] = "@(#)$Id: map.c,v 8.414.4.24 2000/09/27 04:11:29 gshapiro Exp";
! static char Wid[] = "@(#)$Id: map.c,v 1.3 2000/11/15 17:29:29 motonori Exp $";
  #endif /* ! lint */
  
  #include <sendmail.h>
***************
*** 7079,7084 ****
--- 7080,7359 ----
  	return regex_map_rewrite(map, "", (size_t)0, av);
  }
  #endif /* MAP_REGEX */
+ #if MASKED_ADDR
+ /*
+ **  MASKED ADDR (IP address with mask matching) Modules
+ */
+ 
+ 
+ /*
+ **  MASKEDADDR_MAP_OPEN
+ */
+ 
+ bool
+ maskedaddr_map_open(map, mode)
+ 	MAP *map;
+ 	int mode;
+ {
+ 	int sff;
+ 	int i;
+ 
+ 	if (tTd(38, 2))
+ 		printf("maskedaddr_map_open(%s, %s, %d)\n",
+ 			map->map_mname, map->map_file, mode);
+ 
+ 	mode &= O_ACCMODE;
+ 	if (mode != O_RDONLY)
+ 	{
+ 		errno = EPERM;
+ 		return FALSE;
+ 	}
+ 
+ 	if (*map->map_file == '\0')
+ 	{
+ 		syserr("maskedaddr map \"%s\": file name required",
+ 			map->map_mname);
+ 		return FALSE;
+ 	}
+ 
+ 	if (map->map_file[0] != '/')
+ 	{
+ 		syserr("maskedaddr map \"%s\": file name must be fully qualified",
+ 			map->map_mname);
+ 		return FALSE;
+ 	}
+ 
+ 	sff = SFF_ROOTOK|SFF_REGONLY;
+ 	if (!bitnset(DBS_LINKEDMAPINWRITABLEDIR, DontBlameSendmail))
+ 		sff |= SFF_NOWLINK;
+ 	if (!bitnset(DBS_MAPINUNSAFEDIRPATH, DontBlameSendmail))
+ 		sff |= SFF_SAFEDIRPATH;
+ 	if ((i = safefile(map->map_file, RunAsUid, RunAsGid, RunAsUserName,
+ 			  sff, S_IRUSR, NULL)) != 0)
+ 	{
+ 		/* cannot open this map */
+ 		if (tTd(38, 2))
+ 			printf("\tunsafe map file: %d\n", i);
+ 		if (!bitset(MF_OPTIONAL, map->map_mflags))
+ 			syserr("maskedaddr map \"%s\": unsafe map file %s",
+ 				map->map_mname, map->map_file);
+ 		return FALSE;
+ 	}
+ 
+ 	if (bitset(MF_NODEFER, map->map_mflags))
+ 	{
+ 		if (maskedaddr_build(map) == FALSE)
+ 			return FALSE;
+ 	}
+ 
+ 	map->map_sff = sff;
+ 	return TRUE;
+ }
+ 
+ struct addr_list {
+ 	struct addr_list *next;
+ 	SOCKADDR addr;
+ 	int masklen;
+ 	char *val;
+ };
+ 
+ /*
+ **  MASKEDADDR_MAP_LOOKUP
+ */
+ 
+ char *
+ maskedaddr_map_lookup(map, name, av, statp)
+ 	MAP *map;
+ 	char *name;
+ 	char **av;
+ 	int *statp;
+ {
+ 	bool found_it;
+ 	struct addr_list *alp, *alpnext;
+ 	SOCKADDR sa;
+ 	char *vp;
+ 	auto int vsize;
+ 
+ 	if (!bitset(MF_NODEFER, map->map_mflags))
+ 	{
+ 		if ((alp = (struct addr_list*)map->map_rebuild) != NULL)
+ 		{
+ 			alpnext = alp->next;
+ 			free(alp);
+ 			alp = alpnext;
+ 			map->map_rebuild = NULL;
+ 		}
+ 
+ 		if (maskedaddr_build(map) == FALSE)
+ 		{
+ 			*statp = EX_UNAVAILABLE;
+ 			return NULL;
+ 		}
+ 	}
+ 
+ 	if (tTd(38, 20))
+ 		printf("maskedaddr_map_lookup(%s, %s)\n",
+ 			map->map_mname,  name);
+ 
+ 	bzero(&sa, sizeof(sa));
+ 	if (anynet_aton(name, &sa) == 0)
+ 	{
+ 		if (tTd(38, 20))
+ 			printf("maskedaddr_map_lookup: invalid address format\n");
+ 		*statp = EX_NOTFOUND;
+ 		return NULL;
+ 	}
+ 
+ 	alp = (struct addr_list*)map->map_rebuild;
+ 	while (alp != NULL)
+ 	{
+ 		if (alp->addr.sa.sa_family != sa.sa.sa_family)
+ 		{
+ 			alp = alp->next;
+ 			continue;
+ 		}
+ 		if (maskedaddrcmp(&sa, &alp->addr, alp->masklen) == 0)
+ 		{
+ 			if (tTd(38, 20))
+ 				printf("maskedaddr_map_lookup: found %s\n",
+ 					alp->val);
+ 			*statp = EX_OK;
+ 			vp = alp->val;
+ 			vsize = strlen(vp);
+ 			if (bitset(MF_MATCHONLY, map->map_mflags))
+ 				return map_rewrite(map, name, strlen(name),
+ 					NULL);
+ 			else
+ 				return map_rewrite(map, vp, vsize, av);
+ 		}
+ 		alp = alp->next;
+ 	}
+ 
+ 	*statp = EX_NOTFOUND;
+ 	return NULL;
+ }
+ 
+ int
+ maskedaddr_build(map)
+ 	MAP *map;
+ {
+ 	FILE *f;
+ 	int sff = map->map_sff;
+ 	char linebuf[MAXLINE];
+ 	SOCKADDR sa;
+ 	int masklen;
+ 	struct addr_list *alp, *alp2, *alp3;
+ 
+ 	f = safefopen(map->map_file, O_RDONLY, FileMode, sff);
+ 	if (f == NULL)
+ 	{
+ 		map->map_mflags &= ~(MF_VALID|MF_OPEN);
+ 		return FALSE;
+ 	}
+ 
+ 	while (fgets(linebuf, MAXLINE, f) != NULL)
+ 	{
+ 		char *p, *q;
+ 
+ 		/* skip comment line */
+ 		if (linebuf[0] == '#')
+ 			continue;
+ 		p = strchr(linebuf, '\n');
+ 		if (p != NULL)
+ 			*p = '\0';
+ 		masklen = -1;
+ 		p = strchr(linebuf, '/');
+ 		if (p != NULL)
+ 		{
+ 			*p++ = '\0';
+ 			q = p;
+ 			while (isdigit(*q))
+ 				q++;
+ 			if (*q != '\0' && !isspace(*q))
+ 			{
+ 				/* ignore it */
+ 				continue;
+ 			}
+ 			*q++ = '\0';
+ 			masklen = atoi(p);
+ 		}
+ 		else
+ 		{
+ 			q = linebuf;
+ 			while (*q != '\0' && !isspace(*q))
+ 				q++;
+ 			*q++ = '\0';
+ 		}
+ 		while (isspace(*q))
+ 			q++;
+ 
+ 		bzero(&sa, sizeof(sa));
+ 		if (anynet_aton(linebuf, &sa) > 0)
+ 		{
+ 			alp = (struct addr_list*)xalloc(sizeof(struct addr_list));
+ 			bzero(alp, sizeof(struct addr_list));
+ 			alp->addr.sa.sa_family = sa.sa.sa_family;
+ 			switch (sa.sa.sa_family)
+ 			{
+ 			  case AF_INET:
+ 				alp->addr.sin.sin_addr = sa.sin.sin_addr;
+ 				if (masklen < 0 || masklen > 32)
+ 					alp->masklen = 32;
+ 				else
+ 					alp->masklen = masklen;
+ 				break;
+ #if NETINET6
+ 			  case AF_INET6:
+ 				alp->addr.sin6.sin6_addr = sa.sin6.sin6_addr;
+ 				if (masklen < 0 || masklen > 128)
+ 					alp->masklen = 128;
+ 				else
+ 					alp->masklen = masklen;
+ 				break;
+ #endif
+ 			}
+ 			alp->val = newstr(q);
+ 
+ 			if (tTd(38, 20))
+ 				printf("maskedaddr_store(%s, %s/%d, %s)\n",
+ 					map->map_mname, linebuf, masklen, q);
+ 		}
+ 		else
+ 			continue;
+ 
+ 		/* insertion sort (longer mask first) */
+ 		alp2 = (struct addr_list*)map->map_rebuild;
+ 		alp3 = NULL;
+ 
+ 		if (alp2 == NULL)
+ 		{
+ 			map->map_rebuild = (char *)alp;
+ 			continue;
+ 		}
+ 		while (alp2 != NULL)
+ 		{
+ 			if (alp->masklen > alp2->masklen)
+ 			{
+ 				if (alp3 == NULL)
+ 					map->map_rebuild = (char *)alp;
+ 				else
+ 					alp3->next = alp;
+ 				alp->next = alp2;
+ 				break;
+ 			}
+ 			alp3 = alp2;
+ 			alp2 = alp2->next;
+ 		}
+ 		if (alp2 == NULL)
+ 		{
+ 			alp3->next = alp;
+ 		}
+ 	}
+ 	fclose(f);
+ 
+ 	return TRUE;
+ }
+ #endif /* MASKED_ADDR */
  /*
  **  NSD modules
  */
diff -c ../sendmail.org/parseaddr.c ./parseaddr.c
*** ../sendmail.org/parseaddr.c	Mon Sep 25 16:53:29 2000
--- ./parseaddr.c	Thu Nov 16 02:29:48 2000
***************
*** 12,18 ****
   */
  
  #ifndef lint
! static char id[] = "@(#)$Id: parseaddr.c,v 8.234.4.5 2000/09/25 07:53:29 gshapiro Exp $";
  #endif /* ! lint */
  
  #include <sendmail.h>
--- 12,19 ----
   */
  
  #ifndef lint
! static char id[] = "@(#)$Id: parseaddr.c,v 8.234.4.5 2000/09/25 07:53:29 gshapiro Exp";
! static char Wid[] = "@(#)$Id: parseaddr.c,v 1.3 2000/11/15 17:29:29 motonori Exp $";
  #endif /* ! lint */
  
  #include <sendmail.h>
***************
*** 332,338 ****
  };
  
  /* token type table -- it gets modified with $o characters */
! static u_char	TokTypeTab[256] =
  {
      /*	nul soh stx etx eot enq ack bel  bs  ht  nl  vt  np  cr  so  si   */
  	ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM, ATM,SPC,SPC,SPC,SPC,SPC,ATM,ATM,
--- 333,342 ----
  };
  
  /* token type table -- it gets modified with $o characters */
! #if !MASKED_ADDR
! static
! #endif
! u_char	TokTypeTab[256] =
  {
      /*	nul soh stx etx eot enq ack bel  bs  ht  nl  vt  np  cr  so  si   */
  	ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM, ATM,SPC,SPC,SPC,SPC,SPC,ATM,ATM,
***************
*** 769,774 ****
--- 773,973 ----
  
  #define MAXMATCH	9	/* max params per rewrite */
  
+ #if MASKED_ADDR
+ static int maskedaddrcmp_match;
+ static SOCKADDR matchingaddr;
+ 
+ static void
+ maskedaddrcmp_class(s, id)
+         register STAB *s;
+         int id;
+ {
+ 	SOCKADDR matchaddr;
+ 	char *p;
+ 	int masklen, r;
+ 
+ 	if (maskedaddrcmp_match)
+ 		return;
+         if (s->s_type != ST_CLASS)
+                 return;
+         if (bitnset(id & 0xff, s->s_class))
+ 	{
+ #if NETINET6
+ 		if (strchr(s->s_name, ':') == NULL && !isdigit(*s->s_name))
+ #else
+ 		if (!isdigit(*s->s_name))
+ #endif
+ 			return;
+ 		p = strchr(s->s_name, '/');
+ 		if (p != NULL)
+ 			*p = '\0';
+ 		r = anynet_aton(s->s_name, &matchaddr);
+ 		if (p != NULL)
+ 			*p = '/';
+ 		if (r == 0)
+ 			return;
+ 
+ 		if (p != NULL)
+ 			masklen = atoi(++p);
+ 		else
+ 		{
+ 			switch (matchaddr.sa.sa_family)
+ 			{
+ 			  case AF_INET:
+ 				masklen = 32;
+ 				break;
+ #if NETINET6
+ 			  case AF_INET6:
+ 				masklen = 128;
+ 				break;
+ #endif
+ 			}
+ 		}
+ 		if (maskedaddrcmp(&matchingaddr, &matchaddr, masklen) == 0)
+ 			maskedaddrcmp_match = 1;
+ 	}
+ }
+ 
+ int
+ anynet_aton(str, addr)
+ char *str;
+ SOCKADDR *addr;
+ {
+ 	char *p;
+ #if NETINET6
+ 	if (strchr(str, ':') != NULL)
+ 	{
+ 		/* IPv6 address */
+ 	}
+ 	else
+ #endif
+ 	if ((p = strchr(str, '.')) != NULL)
+ 	{
+ 		/* need quad for IPv4 addr */
+ 		if ((p = strchr(p+1, '.')) == NULL
+ 		 || (p = strchr(p+1, '.')) == NULL)
+ 			return 0;
+ 		if (strchr(p+1, '.') != NULL)
+ 			return 0;
+ 	}
+ 	else
+ 		return 0;
+ 
+ 	bzero(addr, sizeof(SOCKADDR));
+ 	if ((addr->sin.sin_addr.s_addr = inet_addr(str)) != INADDR_NONE)
+ 	{
+ 		addr->sin.sin_family = AF_INET;
+ 		return 1;
+ 	}
+ #if NETINET6
+ 	else if (inet_pton(AF_INET6, str, &addr->sin6.sin6_addr) > 0)
+ 	{
+ 		addr->sin6.sin6_family = AF_INET6;
+ 		return 1;
+ 	}
+ #endif
+ 	return 0;
+ }
+ 
+ static unsigned long netmask[33] = {
+ 	0x00000000, 0x80000000, 0xc0000000, 0xe0000000,
+ 	0xf0000000, 0xf8000000, 0xfc000000, 0xfe000000,
+ 	0xff000000, 0xff800000, 0xffc00000, 0xffe00000,
+ 	0xfff00000, 0xfff80000, 0xfffc0000, 0xfffe0000,
+ 	0xffff0000, 0xffff8000, 0xffffc000, 0xffffe000,
+ 	0xfffff000, 0xfffff800, 0xfffffc00, 0xfffffe00,
+ 	0xffffff00, 0xffffff80, 0xffffffc0, 0xffffffe0,
+ 	0xfffffff0, 0xfffffff8, 0xfffffffc, 0xfffffffe,
+ 	0xffffffff
+ };
+ 
+ int
+ maskedaddrcmp(adr1, adr2, masklen)
+ SOCKADDR *adr1, *adr2;
+ int masklen;
+ {
+ 	unsigned long a1, a2;
+ 
+ 	if (tTd(21, 40))
+ 	{
+ 		printf("maskedaddrcmp: a1 = %s\n", anynet_ntoa(adr1));
+ 		printf("maskedaddrcmp: a2 = %s\n", anynet_ntoa(adr1));
+ 		printf("maskedaddrcmp: ml = %d\n", masklen);
+ 	}
+ 
+ 	if (adr1->sa.sa_family != adr2->sa.sa_family)
+ 		return -1;
+ 
+ 	switch (adr1->sa.sa_family)
+ 	{
+ 	  case AF_INET:
+ 		a1 = ntohl(adr1->sin.sin_addr.s_addr) & netmask[masklen];
+ 		a2 = ntohl(adr2->sin.sin_addr.s_addr) & netmask[masklen];
+ 		if (a1 == a2)
+ 			return 0;
+ 		break;
+ #if NETINET6
+ 	  case AF_INET6:
+ 		if (masklen < 32)
+ 		{
+ 			a1 = ntohl(((u_long *)&adr1->sin6.sin6_addr)[0])
+ 				& netmask[masklen];
+ 			a2 = ntohl(((u_long *)&adr2->sin6.sin6_addr)[0])
+ 				& netmask[masklen];
+ 			if (a1 == a2)
+ 				return 0;
+ 		}
+ 		else if (masklen < 64)
+ 		{
+ 			if (((u_long *)&adr1->sin6.sin6_addr)[0]
+ 			 != ((u_long *)&adr2->sin6.sin6_addr)[0])
+ 				break;
+ 			a1 = ntohl(((u_long *)&adr1->sin6.sin6_addr)[1])
+ 				& netmask[masklen-32];
+ 			a2 = ntohl(((u_long *)&adr2->sin6.sin6_addr)[1])
+ 				& netmask[masklen-32];
+ 			if (a1 == a2)
+ 				return 0;
+ 		}
+ 		else if (masklen < 96)
+ 		{
+ 			if (((u_long *)&adr1->sin6.sin6_addr)[0]
+ 			 != ((u_long *)&adr2->sin6.sin6_addr)[0])
+ 				break;
+ 			if (((u_long *)&adr1->sin6.sin6_addr)[1]
+ 			 != ((u_long *)&adr2->sin6.sin6_addr)[1])
+ 				break;
+ 			a1 = ntohl(((u_long *)&adr1->sin6.sin6_addr)[2])
+ 				& netmask[masklen-64];
+ 			a2 = ntohl(((u_long *)&adr2->sin6.sin6_addr)[2])
+ 				& netmask[masklen-64];
+ 			if (a1 == a2)
+ 				return 0;
+ 		}
+ 		else
+ 		{
+ 			if (((u_long *)&adr1->sin6.sin6_addr)[0]
+ 			 != ((u_long *)&adr2->sin6.sin6_addr)[0])
+ 				break;
+ 			if (((u_long *)&adr1->sin6.sin6_addr)[1]
+ 			 != ((u_long *)&adr2->sin6.sin6_addr)[1])
+ 				break;
+ 			if (((u_long *)&adr1->sin6.sin6_addr)[2]
+ 			 != ((u_long *)&adr2->sin6.sin6_addr)[2])
+ 				break;
+ 			a1 = ntohl(((u_long *)&adr1->sin6.sin6_addr)[3])
+ 				& netmask[masklen-96];
+ 			a2 = ntohl(((u_long *)&adr2->sin6.sin6_addr)[3])
+ 				& netmask[masklen-96];
+ 			if (a1 == a2)
+ 				return 0;
+ 		}
+ 		break;
+ #endif
+ 	}
+ 	return -1;
+ }
+ #endif
  
  int
  rewrite(pvp, ruleset, reclevel, e)
***************
*** 870,875 ****
--- 1069,1077 ----
  
  		while ((ap = *avp) != NULL || *rvp != NULL)
  		{
+ #if MASKED_ADDR
+ 			bool maskedaddr_match;
+ #endif
  			rp = *rvp;
  			if (tTd(21, 35))
  			{
***************
*** 895,900 ****
--- 1097,1109 ----
  			{
  			  case MATCHCLASS:
  				/* match any phrase in a class */
+ #if MASKED_ADDR
+ 				if (wordinclass("_MASKED_ADDRESS_MATCH_",
+ 						rp[1]))
+ 					maskedaddr_match = 1;
+ 				else
+ 					maskedaddr_match = 0;
+ #endif
  				mlp->match_pattern = rvp;
  				mlp->match_first = avp;
  	extendclass:
***************
*** 904,909 ****
--- 1113,1144 ----
  				mlp->match_last = avp++;
  				cataddr(mlp->match_first, mlp->match_last,
  					buf, sizeof buf, '\0');
+ #if MASKED_ADDR
+ 				if (maskedaddr_match
+ 				 && anynet_aton(buf, &matchingaddr) > 0)
+ 				{
+ 					if (tTd(21, 40))
+ 						printf("maskedaddr check: %s\n",
+ 							buf);
+ 
+ 					maskedaddrcmp_match = 0;
+ 					stabapply(maskedaddrcmp_class, rp[1]);
+ 
+ 					if (!maskedaddrcmp_match)
+ 					{
+ 						if (tTd(21, 36))
+ 						{
+ 							printf("EXTEND  rp=");
+ 							xputs(rp);
+ 							printf(", ap=");
+ 							xputs(ap);
+ 							printf("\n");
+ 						}
+ 						goto extendclass;
+ 					}
+ 				}
+ 				else
+ #endif
  				if (!wordinclass(buf, rp[1]))
  				{
  					if (tTd(21, 36))
***************
*** 1684,1689 ****
--- 1919,1929 ----
  	char **hostp;
  	char hbuf[MAXNAME + 1];
  	static char ubuf[MAXNAME + 2];
+ #if MULTI_MAILER
+ 	char **tvnext;
+ 	char *tvsave;
+ 	int nmailer = 0;
+ #endif
  
  	if (tTd(24, 5))
  	{
***************
*** 1699,1704 ****
--- 1939,1962 ----
  	/* set up default error return flags */
  	a->q_flags |= DefaultNotify;
  
+ #if MULTI_MAILER
+  	tvnext = tv;
+ 	do {
+ 		while (*++tvnext != NULL)
+ 		{
+ 			if ((**tvnext & 0377) == CANONNET)
+ 			{
+ 				break;
+ 			}
+ 		}
+ 		if (*tvnext != NULL)
+ 		{
+ 			tvsave = *tvnext;
+ 			*tvnext = NULL;
+ 		} else {
+ 			tvnext = NULL;
+ 		}
+ #endif
  	/* figure out what net/mailer to use */
  	if (*tv == NULL || (**tv & 0377) != CANONNET)
  	{
***************
*** 1709,1715 ****
--- 1967,1977 ----
  		else
  		{
  			a->q_state = QS_BADADDR;
+ #if MULTI_MAILER
+ 			a->q_mailers[nmailer] = &errormailer;
+ #else
  			a->q_mailer = &errormailer;
+ #endif
  		}
  		return a;
  	}
***************
*** 1809,1815 ****
--- 2071,2081 ----
  		syserr("554 5.3.5 buildaddr: unknown mailer %s", mname);
  		goto badaddr;
  	}
+ #if MULTI_MAILER
+ 	a->q_mailers[nmailer] = m;
+ #else
  	a->q_mailer = m;
+ #endif
  
  	/* figure out what host (if any) */
  	if (hostp == NULL)
***************
*** 1819,1828 ****
--- 2085,2102 ----
  			syserr("554 5.3.5 buildaddr: no host");
  			goto badaddr;
  		}
+ #if MULTI_MAILER
+ 		a->q_hosts[nmailer] = NULL;
+ #else
  		a->q_host = NULL;
+ #endif
  	}
  	else
+ #if MULTI_MAILER
+ 		a->q_hosts[nmailer] = newstr(hbuf);
+ #else
  		a->q_host = newstr(hbuf);
+ #endif
  
  	/* figure out the user */
  	p = ubuf;
***************
*** 1837,1845 ****
--- 2111,2127 ----
  	if (*p == '"')
  		p++;
  	if (*p == '|' && bitnset(M_CHECKPROG, m->m_flags))
+ #if MULTI_MAILER
+ 		a->q_mailers[nmailer] = m = ProgMailer;
+ #else
  		a->q_mailer = m = ProgMailer;
+ #endif
  	else if (*p == '/' && bitnset(M_CHECKFILE, m->m_flags))
+ #if MULTI_MAILER
+ 		a->q_mailers[nmailer] = m = FileMailer;
+ #else
  		a->q_mailer = m = FileMailer;
+ #endif
  	else if (*p == ':' && bitnset(M_CHECKINCLUDE, m->m_flags))
  	{
  		/* may be :include: */
***************
*** 1847,1860 ****
--- 2129,2151 ----
  		if (strncasecmp(ubuf, ":include:", 9) == 0)
  		{
  			/* if :include:, don't need further rewriting */
+ #if MULTI_MAILER
+ 			a->q_mailers[nmailer] = m = InclMailer;
+ 			a->q_users[nmailer] = newstr(&ubuf[9]);
+ #else
  			a->q_mailer = m = InclMailer;
  			a->q_user = newstr(&ubuf[9]);
+ #endif
  			return a;
  		}
  	}
  
  	/* rewrite according recipient mailer rewriting rules */
+ #if MULTI_MAILER
+ 	define('h', a->q_hosts[nmailer], e);
+ #else
  	define('h', a->q_host, e);
+ #endif
  
  #if _FFR_ADDR_TYPE
  	/*
***************
*** 1877,1898 ****
--- 2168,2209 ----
  
  	/* save the result for the command line/RCPT argument */
  	cataddr(tv, NULL, ubuf, sizeof ubuf, '\0');
+ #if MULTI_MAILER
+ 	a->q_users[nmailer] = newstr(ubuf);
+ #else
  	a->q_user = newstr(ubuf);
+ #endif
  
  	/*
  	**  Do mapping to lower case as requested by mailer
  	*/
  
+ #if MULTI_MAILER
+ 	if (a->q_hosts[nmailer] != NULL && !bitnset(M_HST_UPPER, m->m_flags))
+ 		makelower(a->q_hosts[nmailer]);
+ 	if (!bitnset(M_USR_UPPER, m->m_flags))
+ 		makelower(a->q_users[nmailer]);
+ #else
  	if (a->q_host != NULL && !bitnset(M_HST_UPPER, m->m_flags))
  		makelower(a->q_host);
  	if (!bitnset(M_USR_UPPER, m->m_flags))
  		makelower(a->q_user);
+ #endif
  
  	if (tTd(24, 6))
  	{
  		dprintf("buildaddr => ");
  		printaddr(a, FALSE);
  	}
+ #if MULTI_MAILER
+ 		if (tvnext != NULL)
+ 		{
+ 			*tvnext = tvsave;
+ 			tv = tvnext;
+ 			nmailer++;
+ 		}
+ 	} while (tvnext && (nmailer < MAXDSPTMAILERS));
+ #endif
  	return a;
  }
  /*
***************
*** 2456,2461 ****
--- 2767,2790 ----
  
  	/* if non-null, mailer destination specified -- has it changed? */
  	a1 = buildaddr(pvp, NULL, 0, e);
+ #if CF_ALIASING
+ 	if (a1 != NULL && a1->q_mailer != NULL && 
+ 	    bitnset(M_LOCALMAILER, a1->q_mailer->m_flags) &&
+ 	    a1->q_host != NULL && strcasecmp(a1->q_host, "alias") == 0)
+ 	{
+ 		/* aliasing mode */
+ 
+ 		/* mark old address as dead; insert new address */
+ 
+ 		a->q_state = QS_REPLACED;
+ 		(void) sendtolist(a1->q_user, a, sendq, aliaslevel + 1, e);
+ 		if (bitset(QSELFREF, a->q_flags) &&
+ 		    !bitset(QPRIMARY, a->q_flags))
+ 			a->q_state = QS_OK;
+ 
+ 		return;
+ 	}
+ #endif
  	if (a1 == NULL || sameaddr(a, a1))
  	{
  		if (tTd(29, 9))
diff -c ../sendmail.org/queue.c ./queue.c
*** ../sendmail.org/queue.c	Fri Sep 15 12:34:51 2000
--- ./queue.c	Thu Nov 16 01:53:42 2000
***************
*** 1793,1798 ****
--- 1793,1802 ----
  		if (requeueflag)
  			queueup(e, FALSE);
  
+ #if 1
+ 		define(macid("{runqueue}", NULL), "runqueue", e);
+ #endif
+ 
  		/* do the delivery */
  		sendall(e, SM_DELIVER);
  
diff -c ../sendmail.org/readcf.c ./readcf.c
*** ../sendmail.org/readcf.c	Fri Sep 29 02:54:21 2000
--- ./readcf.c	Thu Nov 16 02:29:49 2000
***************
*** 12,18 ****
   */
  
  #ifndef lint
! static char id[] = "@(#)$Id: readcf.c,v 8.382.4.27 2000/09/28 01:31:16 gshapiro Exp $";
  #endif /* ! lint */
  
  #include <sendmail.h>
--- 12,19 ----
   */
  
  #ifndef lint
! static char id[] = "@(#)$Id: readcf.c,v 8.382.4.27 2000/09/28 01:31:16 gshapiro Exp";
! static char Wid[] = "@(#)$Id: readcf.c,v 1.7 2000/11/15 17:29:29 motonori Exp $";
  #endif /* ! lint */
  
  #include <sendmail.h>
***************
*** 858,863 ****
--- 859,869 ----
  	char fcode;
  	auto char *endp;
  	extern int NextMailer;
+ #if CLIENT_SMTP_CONFIG
+ 	char *c_fqdn, *c_addr;
+ 	int c_family, c_port;
+ 	struct client_config *ccnf;
+ #endif
  
  	/* allocate a mailer and set up defaults */
  	m = (struct mailer *) xalloc(sizeof *m);
***************
*** 1091,1096 ****
--- 1097,1298 ----
  				m->m_rootdir = newstr(p);
  			break;
  
+ #if MULTI_MAILER
+ 		  case '*':		/* recipient lower limit */
+ 			m->m_rmin = atoi(p);
+ 			break;
+ #endif
+ #if MAILER_PREF
+ 		  case '%':		/* mailer preference */
+ 			m->m_pref = atoi(p);
+ 			break;
+ #endif
+ #if MAILER_TIMEOUTS
+ 		  case '?':		/* mailer preference */
+ 			m->m_to_q_return = atoi(p);
+ 			break;
+ #endif
+ #if CLIENT_SMTP_CONFIG
+ 		  case '@':		/* client-side SMTP configuration */
+ 			/* Family:FQDN/address/port */
+ 			if (strncasecmp(p, "inet:", 5) == 0)
+ 			{
+ 				c_family = AF_INET;
+ 				p += 5;
+ 			}
+ #if NETINET6
+ 			else if (strncasecmp(p, "inet6:", 6) == 0)
+ 			{
+ 				c_family = AF_INET6;
+ 				p += 6;
+ 			}
+ #endif
+ 			else
+ 			{
+ 				c_family = AF_INET;
+ 			}
+ 
+ 			if (*p == '\0' || *p == '/')
+ 			{
+ 				c_fqdn = NULL;
+ 				if (*p == '/')
+ 					p++;
+ 			}
+ 			else
+ 			{
+ 				char *q = strchr(p, '/');
+ 				if (q == NULL)
+ 				{
+ 					c_fqdn = p;
+ 					p += strlen(p);
+ 				}
+ 				else
+ 				{
+ 					*q = '\0';
+ 					c_fqdn = p;
+ 					p = q + 1;
+ 				}
+ 			}
+ 
+ 			if (*p == '\0' || *p == '/')
+ 			{
+ 				c_addr = NULL;
+ 				if (*p == '/')
+ 					p++;
+ 			}
+ 			else
+ 			{
+ 				char *q = strchr(p, '/');
+ 				if (q == NULL)
+ 				{
+ 					c_addr = p;
+ 					p += strlen(p);
+ 				}
+ 				else
+ 				{
+ 					*q = '\0';
+ 					c_addr = p;
+ 					p = q + 1;
+ 				}
+ 			}
+ 
+ 			if (isdigit(*p))
+ 				c_port = atoi(p);
+ 			else
+ 				c_port = 0;
+ 
+ 			if (c_fqdn == NULL && c_addr == NULL)
+ 				break;
+ 
+ 			ccnf = (struct client_config*)
+ 				malloc(sizeof(struct client_config));
+ 			bzero(ccnf, sizeof(ccnf));
+ 			ccnf->next = m->m_ccnf;
+ 			m->m_ccnf = ccnf;
+ 
+ 			ccnf->addr.sa.sa_family = c_family;
+ 
+ 			switch (c_family)
+ 			{
+ 			  case AF_INET:
+ 				ccnf->addr.sin.sin_addr.s_addr = INADDR_ANY;
+ 				ccnf->addr.sin.sin_port = htons(c_port);
+ 				break;
+ #if NETINET6
+ 			  case AF_INET6:
+ 				ccnf->addr.sin6.sin6_addr = in6addr_any;
+ 				ccnf->addr.sin6.sin6_port = htons(c_port);
+ 				break;
+ #endif
+ 			}
+ 
+ 			if (c_addr == NULL)
+ 			{
+ 				/* any address */
+ 			}
+ 			else if (strcmp(c_addr, "@") == 0)
+ 			{
+ 				/* use DNS map for FQDN */
+ 				struct hostent *hp;
+ 
+ 				switch (c_family)
+ 				{
+ 				  case AF_INET:
+ 					hp = sm_gethostbyname(c_fqdn, AF_INET);
+ 					break;
+ #if NETINET6
+ 				  case AF_INET6:
+ 					hp = sm_gethostbyname(c_fqdn, AF_INET6);
+ 					break;
+ #endif
+ 				}
+ 				if (hp != NULL)
+ 				{
+ 					switch (c_family)
+ 					{
+ 					  case AF_INET:
+ 						bcopy(hp->h_addr, &ccnf->addr.sin.sin_addr, INADDRSZ);
+ 						break;
+ #if NETINET6
+ 					  case AF_INET6:
+ 						bcopy(hp->h_addr, &ccnf->addr.sin6.sin6_addr, IN6ADDRSZ);
+ 						break;
+ #endif
+ 					}
+ 				}
+ 				else
+ 				{
+ 					sm_syslog(LOG_NOTICE, NOQID,
+ 						"can't resolv %.100s", c_addr);
+ 				}
+ 			}
+ 			else
+ 			{
+ 				switch (c_family)
+ 				{
+ 				  case AF_INET:
+ 					ccnf->addr.sin.sin_addr.s_addr =
+ 						inet_addr(c_addr);
+ 					break;
+ #if NETINET6
+ 				  case AF_INET6:
+ 					inet_pton(AF_INET6, c_addr, &ccnf->addr.sin6.sin6_addr);
+ 					break;
+ #endif
+ 				}
+ 			}
+ 
+ 			if (c_fqdn == NULL)
+ 			{
+ 				/* use DNS reverse map for ADDR */
+ 				struct hostent *hp;
+ 
+ 				switch (c_family)
+ 				{
+ #if NETINET6
+ 				  case AF_INET6:
+ 					hp = sm_gethostbyaddr((char *)&ccnf->addr.sin6.sin6_addr, IN6ADDRSZ, AF_INET6);
+ 					break;
+ #endif
+ 				  case AF_INET:
+ 					hp = sm_gethostbyaddr((char *)&ccnf->addr.sin.sin_addr, INADDRSZ, AF_INET);
+ 					break;
+ 				}
+ 				if (hp != NULL)
+ 				{
+ 					ccnf->heloname = newstr(hp->h_name);
+ 				}
+ 				else
+ 				{
+ 					sm_syslog(LOG_NOTICE, NOQID,
+ 						"can't resolv %.100s", c_addr);
+ 				}
+ 			}
+ 			else
+ 			{
+ 				ccnf->heloname = newstr(c_fqdn);
+ 			}
+ #endif
  		  default:
  			syserr("M%s: unknown mailer equate %c=",
  			       m->m_name, fcode);
***************
*** 1439,1444 ****
--- 1641,1683 ----
  		m->m_mtatype == NULL ? "<undefined>" : m->m_mtatype,
  		m->m_addrtype == NULL ? "<undefined>" : m->m_addrtype,
  		m->m_diagtype == NULL ? "<undefined>" : m->m_diagtype);
+ #if MULTI_MAILER
+ 	if (m->m_rmin > 0)
+ 		printf(" *=%d", m->m_rmin);
+ #endif
+ #if MAILER_PREF
+ 	printf(" %%=%d", m->m_pref);
+ #endif
+ #if MAILER_TIMEOUTS
+ 	if (m->m_to_q_return > 0)
+ 		printf(" ?=[%s]", pintvl(m->m_to_q_return, FALSE));
+ #endif
+ #if CLIENT_SMTP_CONFIG
+ {
+ 	struct client_config *ccnf = m->m_ccnf;
+ 	while (ccnf != NULL)
+ 	{
+ 		switch (ccnf->addr.sa.sa_family)
+ 		{
+ 		  case AF_INET:
+ 			printf(" @=inet:%s/%s/%d",
+ 				(ccnf->heloname == NULL)?"":ccnf->heloname,
+ 				anynet_ntoa(&ccnf->addr),
+ 				ntohs(ccnf->addr.sin.sin_port));
+ 			break;
+ #if NETINET6
+ 		  case AF_INET6:
+ 			printf(" @=inet6:%s/%s/%d",
+ 				(ccnf->heloname == NULL)?"":ccnf->heloname,
+ 				anynet_ntoa(&ccnf->addr),
+ 				ntohs(ccnf->addr.sin6.sin6_port));
+ 			break;
+ #endif
+ 		}
+ 		ccnf = ccnf->next;
+ 	}
+ }
+ #endif
  #if _FFR_DYNAMIC_TOBUF
  	printf(" r=%d", m->m_maxrcpt);
  #endif /* _FFR_DYNAMIC_TOBUF */
***************
*** 1569,1574 ****
--- 1808,1817 ----
  	{ "ForkEachJob",		'Y',		OI_NONE	},
  	{ "ClassFactor",		'z',		OI_NONE	},
  	{ "RetryFactor",		'Z',		OI_NONE	},
+ #if CTE8CHECK
+ #define O_CTE8CHECK	0xf0
+ 	{ "CTE8BitCheck",		O_CTE8CHECK,	OI_SAFE	},
+ #endif
  #define O_QUEUESORTORD	0x81
  	{ "QueueSortOrder",		O_QUEUESORTORD,	OI_SAFE	},
  #define O_HOSTSFILE	0x82
***************
*** 2646,2651 ****
--- 2889,2900 ----
  	  case O_MAXALIASRCSN:
  		MaxAliasRecursion = atoi(val);
  		break;
+ 
+ #if CTE8CHECK
+ 	  case O_CTE8CHECK:
+ 		CTE8BitCheck = newstr(val);
+ 		break;
+ #endif
  
  	  case O_CNCTONLYTO:
  		/* XXX should probably use gethostbyname */
diff -c ../sendmail.org/recipient.c ./recipient.c
*** ../sendmail.org/recipient.c	Fri Sep 15 10:43:55 2000
--- ./recipient.c	Thu Nov 16 02:29:50 2000
***************
*** 12,18 ****
   */
  
  #ifndef lint
! static char id[] = "@(#)$Id: recipient.c,v 8.231.14.8 2000/09/14 23:32:27 gshapiro Exp $";
  #endif /* ! lint */
  
  #include <sendmail.h>
--- 12,19 ----
   */
  
  #ifndef lint
! static char id[] = "@(#)$Id: recipient.c,v 8.231.14.8 2000/09/14 23:32:27 gshapiro Exp";
! static char Wid[] = "@(#)$Id: recipient.c,v 1.7 2000/11/15 17:29:29 motonori Exp $";
  #endif /* ! lint */
  
  #include <sendmail.h>
***************
*** 21,26 ****
--- 22,82 ----
  static void	includetimeout __P((void));
  static ADDRESS	*self_reference __P((ADDRESS *));
  
+ #if RCPT_HASH
+ #define HASH_SIZE	2003
+ static ADDRESS *addrhash[HASH_SIZE];
+ static int use_hash = 0;
+ static ADDRESS **chainlast;
+ 
+ void
+ make_rcpt_hash(sendq, e)
+ 	register ADDRESS **sendq;
+ 	register ENVELOPE *e;
+ {
+ 	ADDRESS **pq, *q;
+ 	int hfunc;
+ 
+ 	if (use_hash++ > 0)
+ 		return;
+ 
+ 	for (pq = sendq; (q = *pq) != NULL; pq = &q->q_next)
+ 	{
+ 		char *p;
+ 		ADDRESS *a;
+ 
+ 		a = parseaddr(q->q_paddr, NULLADDR, RF_COPYALL, '\0', NULL, e);
+ 		if (a == NULL)
+ 			p = "";
+ 		else
+ 			p = a->q_user;
+ 		hfunc = 0;
+ 		while (*p != '\0')
+ 		{
+ 			int c = *p++;
+ 
+ 			if (isascii(c) && isupper(c))
+ 				c = tolower(c);
+ 			hfunc = ((hfunc << 1) ^ c) % HASH_SIZE;
+ 		}
+ 		q->q_nhash = addrhash[hfunc];
+ 		addrhash[hfunc] = q;
+ 	}
+ 	chainlast = pq;
+ }
+ 
+ void
+ clear_rcpt_hash()
+ {
+ 	int i;
+ 
+ 	if (--use_hash > 0)
+ 		return;
+ 
+ 	for (i = 0; i < HASH_SIZE; i++)
+ 		addrhash[i] = NULL;
+ }
+ #endif
+ 
  /*
  **  SENDTOLIST -- Designate a send list.
  **
***************
*** 165,170 ****
--- 221,229 ----
  			/* various flag bits */
  			a->q_flags &= ~QINHERITEDBITS;
  			a->q_flags |= ctladdr->q_flags & QINHERITEDBITS;
+ #if FORWARDPROGCTL
+ 			a->q_flags |= ctladdr->q_flags & QDOTFORWARD;
+ #endif
  
  			/* original recipient information */
  			a->q_orcpt = ctladdr->q_orcpt;
***************
*** 337,342 ****
--- 396,404 ----
  	int i, buflen;
  	char *buf;
  	char buf0[MAXNAME + 1];		/* unquoted image of the user name */
+ #if RCPT_HASH
+ 	int hfunc;
+ #endif
  
  	e->e_to = a->q_paddr;
  	m = a->q_mailer;
***************
*** 458,463 ****
--- 520,536 ----
  			usrerrenh(a->q_status,
  				  "550 Cannot mail directly to programs");
  		}
+ #if FORWARDPROGCTL
+ 		else if (bitset(QDOTFORWARD, a->q_flags) &&
+ 			 wordinclass("@", 'f') &&
+ 			 a->q_alias->q_ruser != NULL &&
+ 			 !wordinclass(a->q_alias->q_ruser, 'f'))
+ 		{
+ 			a->q_state = QS_BADADDR;
+ 			a->q_status = "5.7.1";
+ 			usrerr("550 User %s does not have permission for mailing to programs", a->q_alias->q_ruser);
+ 		}
+ #endif
  		else if (bitset(QBOGUSSHELL, a->q_alias->q_flags))
  		{
  			a->q_state = QS_BADADDR;
***************
*** 491,499 ****
--- 564,606 ----
  	**	[Please note: the emphasis is on "hack."]
  	*/
  
+ #if RCPT_HASH
+ 	if (use_hash)
+ 	{
+ 		/* get hash entry */
+ 		char *p;
+ 		register ADDRESS *b;
+ 
+ 		b = parseaddr(a->q_paddr, NULLADDR, RF_COPYALL, '\0', NULL, e);
+ 		if (b == NULL)
+ 			p = "";
+ 		else
+ 			p = b->q_user;
+ 		hfunc = 0;
+ 		while (*p != '\0')
+ 		{
+ 			int c = *p++;
+ 
+ 			if (isascii(c) && isupper(c))
+ 				c = tolower(c);
+ 			hfunc = ((hfunc << 1) ^ c) % HASH_SIZE;
+ 		}
+ 		pq = &addrhash[hfunc];
+ 	}
+ 	else
+ 		pq = sendq;
+ 
+ 	for (; (q = *pq) != NULL; pq = use_hash?(&q->q_nhash):(&q->q_next))
+ #else
  	for (pq = sendq; (q = *pq) != NULL; pq = &q->q_next)
+ #endif
  	{
+ #if MF_SEPARATE
+ 		if (!bitnset(M_SEP, m->m_flags) &&
+ 		    sameaddr(q, a) &&
+ #else
  		if (sameaddr(q, a) &&
+ #endif
  		    (bitset(QRCPTOK, q->q_flags) ||
  		     !bitset(QPRIMARY, q->q_flags)))
  		{
***************
*** 531,536 ****
--- 638,654 ----
  	}
  
  	/* add address on list */
+ #if RCPT_HASH
+ 	if (use_hash)
+ 	{
+ 		a->q_nhash = addrhash[hfunc];
+ 		addrhash[hfunc] = a;
+ 		*chainlast = a;
+ 		chainlast = &a->q_next;
+ 		a->q_next = NULL;
+ 	}
+ 	else
+ #endif
  	if (pq != NULL)
  	{
  		*pq = a;
***************
*** 1501,1506 ****
--- 1619,1627 ----
  	LineNumber = 0;
  	ctladdr->q_flags &= ~QSELFREF;
  	nincludes = 0;
+ #if RCPT_HASH
+ 	make_rcpt_hash(sendq, e);
+ #endif
  	while (fgets(buf, sizeof buf, fp) != NULL && !maxreached)
  	{
  		fixcrlf(buf, TRUE);
***************
*** 1535,1541 ****
--- 1656,1670 ----
  				  "forward %.200s => %s",
  				  oldto, shortenstring(buf, MAXSHORTSTR));
  
+ #if FORWARDPROGCTL
+ 		if (forwarding)
+ 			ctladdr->q_flags |= QDOTFORWARD;
+ #endif
  		nincludes += sendtolist(buf, ctladdr, sendq, aliaslevel + 1, e);
+ #if FORWARDPROGCTL
+ 		if (forwarding)
+ 			ctladdr->q_flags &= ~QDOTFORWARD;
+ #endif
  
  		if (forwarding &&
  		    MaxForwardEntries > 0 &&
***************
*** 1562,1567 ****
--- 1691,1699 ----
  		}
  		ctladdr->q_state = QS_DONTSEND;
  	}
+ #if RCPT_HASH
+ 	clear_rcpt_hash();
+ #endif
  
  	(void) fclose(fp);
  	FileName = oldfilename;
diff -c ../sendmail.org/savemail.c ./savemail.c
*** ../sendmail.org/savemail.c	Wed Aug 23 10:14:07 2000
--- ./savemail.c	Thu Nov 16 02:29:50 2000
***************
*** 12,18 ****
   */
  
  #ifndef lint
! static char id[] = "@(#)$Id: savemail.c,v 8.212.4.5 2000/08/22 22:46:00 gshapiro Exp $";
  #endif /* ! lint */
  
  #include <sendmail.h>
--- 12,19 ----
   */
  
  #ifndef lint
! static char id[] = "@(#)$Id: savemail.c,v 8.212.4.5 2000/08/22 22:46:00 gshapiro Exp";
! static char Wid[] = "@(#)$Id: savemail.c,v 1.3 2000/11/15 17:29:29 motonori Exp $";
  #endif /* ! lint */
  
  #include <sendmail.h>
***************
*** 904,909 ****
--- 905,918 ----
  		snprintf(buf, sizeof buf, "%s",
  			 shortenstring(q->q_paddr, MAXSHORTSTR));
  		putline(buf, mci);
+ #if 1
+ 		if (q->q_rstatus != NULL)
+ 		{
+ 			snprintf(buf, sizeof buf, "    (reason: %s)",
+ 				shortenstring(q->q_rstatus, 203));
+ 			putline(buf, mci);
+ 		}
+ #endif
  		if (q->q_alias != NULL)
  		{
  			snprintf(buf, sizeof buf, "    (expanded from: %s)",
***************
*** 1207,1214 ****
--- 1216,1232 ----
  			{
  				time_t xdate;
  
+ #if MAILER_TIMEOUTS
+ 				if (q->q_mailer->m_to_q_return > 0)
+ 					xdate = e->e_parent->e_ctime +
+ 						q->q_mailer->m_to_q_return;
+ 				else
+ 					xdate = e->e_parent->e_ctime +
+ 						TimeOuts.to_q_return[e->e_parent->e_timeoutclass];
+ #else
  				xdate = e->e_parent->e_ctime +
  					TimeOuts.to_q_return[e->e_parent->e_timeoutclass];
+ #endif
  				snprintf(buf, sizeof buf,
  					 "Will-Retry-Until: %s",
  					 arpadate(ctime(&xdate)));
diff -c ../sendmail.org/sendmail.h ./sendmail.h
*** ../sendmail.org/sendmail.h	Mon Sep 25 16:53:29 2000
--- ./sendmail.h	Thu Nov 16 02:29:52 2000
***************
*** 20,26 ****
  #ifdef _DEFINE
  # define EXTERN
  # ifndef lint
! static char SmailId[] =	"@(#)$Id: sendmail.h,v 8.517.4.37 2000/09/25 07:53:29 gshapiro Exp $";
  # endif /* ! lint */
  #else /* _DEFINE */
  # define EXTERN extern
--- 20,27 ----
  #ifdef _DEFINE
  # define EXTERN
  # ifndef lint
! static char SmailId[] =	"@(#)$Id: sendmail.h,v 8.517.4.37 2000/09/25 07:53:29 gshapiro Exp";
! static char WSmailId[] = "@(#)$Id: sendmail.h,v 1.3 2000/11/15 17:29:29 motonori Exp $";
  # endif /* ! lint */
  #else /* _DEFINE */
  # define EXTERN extern
***************
*** 171,189 ****
--- 172,208 ----
  **	Addresses are stored internally in this structure.
  */
  
+ #if MULTI_MAILER
+ #define q_user		q_users[0]
+ #define q_host		q_hosts[0]
+ #define q_mailer	q_mailers[0]
+ #endif /* MULTI_MAILER */
+ 
  struct address
  {
  	char		*q_paddr;	/* the printname for the address */
+ #if MULTI_MAILER
+ 	char		*q_users[MAXDSPTMAILERS];	/* user name */
+ #else /* MULTI_MAILER */
  	char		*q_user;	/* user name */
+ #endif /* MULTI_MAILER */
  	char		*q_ruser;	/* real user name, or NULL if q_user */
+ #if MULTI_MAILER
+ 	char		*q_hosts[MAXDSPTMAILERS];	/* host name */
+ 	struct mailer	*q_mailers[MAXDSPTMAILERS];	/* mailer to use */
+ #else /* MULTI_MAILER */
  	char		*q_host;	/* host name */
  	struct mailer	*q_mailer;	/* mailer to use */
+ #endif /* MULTI_MAILER */
  	u_long		q_flags;	/* status flags, see below */
  	uid_t		q_uid;		/* user-id of receiver (if known) */
  	gid_t		q_gid;		/* group-id of receiver (if known) */
  	char		*q_home;	/* home dir (local mailer only) */
  	char		*q_fullname;	/* full name if known */
  	struct address	*q_next;	/* chain */
+ #if RCPT_HASH
+ 	struct address  *q_nhash;	/* hashed chain */
+ #endif
  	struct address	*q_alias;	/* address this results from */
  	char		*q_owner;	/* owner of q_alias */
  	struct address	*q_tchain;	/* temporary use chain */
***************
*** 214,219 ****
--- 233,241 ----
  #define QDELIVERED	0x00001000	/* DSN: successful final delivery */
  #define QDELAYED	0x00002000	/* DSN: message delayed */
  #define QALIAS		0x00004000	/* expanded alias */
+ #if FORWARDPROGCTL
+ # define QDOTFORWARD	0x10000000	/* this address is from .forward */
+ #endif
  #define QTHISPASS	0x40000000	/* temp: address set this pass */
  #define QRCPTOK		0x80000000	/* recipient() processed address */
  
***************
*** 323,328 ****
--- 345,364 ----
  #if _FFR_DYNAMIC_TOBUF
  	int	m_maxrcpt;	/* max recipients per envelope client-side */
  #endif /* _FFR_DYNAMIC_TOBUF */
+ #if MULTI_MAILER
+ 	int	m_rmin;		/* recipient lower limit */
+ #endif
+ #if MAILER_PREF
+ 	int	m_pref;		/* mailer preference */
+ 	ADDRESS	*m_addrhead;	/* working address pointer (head) */
+ 	ADDRESS	*m_addrtail;	/* working address pointer (tail) */
+ #endif
+ #if CLIENT_SMTP_CONFIG
+ 	struct client_config *m_ccnf;
+ #endif
+ #if MAILER_TIMEOUTS
+ 	time_t  m_to_q_return;	/* queue return timeouts */
+ #endif
  };
  
  /* bits for m_flags */
***************
*** 383,388 ****
--- 419,437 ----
  #define M_HOLD		'%'	/* Hold delivery until ETRN/-qI/-qR/-qS */
  #define M_PLUS		'+'	/* Reserved: Used in mc for adding new flags */
  #define M_MINUS		'-'	/* Reserved: Used in mc for removing flags */
+ #if MULTI_MAILER
+ # define M_DIRECTONLY	'!'	/* do not use for run-queuing */
+ # define M_NONEXT	'_'	/* do not try next mailer */
+ #endif
+ #if MAILER_PREF
+ # define M_SORT		'<'	/* sort recipient list by domain name */
+ #endif
+ #if SPR_CON_CACHE
+ # define M_NOCACHE	';'	/* suppress connection caching on this mailer */
+ #endif
+ #if MF_SEPARATE
+ # define M_SEP		'^'	/* do not supress duplicates */
+ #endif
  
  /* functions */
  extern void	initerrmailers __P((void));
***************
*** 584,589 ****
--- 633,641 ----
  	HDR		*e_header;	/* head of header list */
  	long		e_msgpriority;	/* adjusted priority of this message */
  	time_t		e_ctime;	/* time message appeared in the queue */
+ #if 1   /* start time of sendmail to pass to SMTPfeed for statistics */
+ 	time_t		e_stime;	/* time processing started */
+ #endif
  	char		*e_to;		/* the target person */
  	ADDRESS		e_from;		/* the person it is from */
  	char		*e_sender;	/* e_from.q_paddr w comments stripped */
***************
*** 1704,1709 ****
--- 1756,1770 ----
  EXTERN int	DefaultNotify;	/* default DSN notification flags */
  EXTERN int	Errors;		/* set if errors (local to single pass) */
  EXTERN int	ExitStat;	/* exit status code */
+ 
+ #if CLIENT_SMTP_CONFIG
+ struct client_config
+ {
+ 	char *heloname;
+ 	SOCKADDR addr;
+ 	struct client_config *next;
+ };
+ #endif
  EXTERN int	FileMode;	/* mode on files */
  EXTERN int	LineNumber;	/* line number in current input */
  EXTERN int	LogLevel;	/* level of logging to perform */
***************
*** 1797,1802 ****
--- 1858,1866 ----
  EXTERN char	*PostMasterCopy;	/* address to get errs cc's */
  EXTERN char	*ProcTitlePrefix; /* process title prefix */
  EXTERN char	*QueueDir;	/* location of queue directory */
+ #if CTE8CHECK
+ EXTERN char	*CTE8BitCheck;	/* incorrect CTE: 8bit check */
+ #endif
  #if _FFR_QUEUEDELAY
  EXTERN int	QueueAlg;	/* algorithm for queue delays */
  EXTERN time_t	QueueInitDelay;	/* initial queue delay */
diff -c ../sendmail.org/usersmtp.c ./usersmtp.c
*** ../sendmail.org/usersmtp.c	Wed Sep 27 13:07:25 2000
--- ./usersmtp.c	Thu Nov 16 02:29:51 2000
***************
*** 15,23 ****
  
  #ifndef lint
  # if SMTP
! static char id[] = "@(#)$Id: usersmtp.c,v 8.245.4.13 2000/09/26 00:46:21 gshapiro Exp $ (with SMTP)";
  # else /* SMTP */
! static char id[] = "@(#)$Id: usersmtp.c,v 8.245.4.13 2000/09/26 00:46:21 gshapiro Exp $ (without SMTP)";
  # endif /* SMTP */
  #endif /* ! lint */
  
--- 15,24 ----
  
  #ifndef lint
  # if SMTP
! static char id[] = "@(#)$Id: usersmtp.c,v 8.245.4.13 2000/09/26 00:46:21 gshapiro Exp (with SMTP)";
  # else /* SMTP */
! static char id[] = "@(#)$Id: usersmtp.c,v 8.245.4.13 2000/09/26 00:46:21 gshapiro Exp (without SMTP)";
! static char Wid[] = "@(#)$Id: usersmtp.c,v 1.3 2000/11/15 17:29:29 motonori Exp $";
  # endif /* SMTP */
  #endif /* ! lint */
  
***************
*** 74,79 ****
--- 75,83 ----
  	register char *p;
  	register char *hn;
  	char *enhsc;
+ #if CLIENT_SMTP_CONFIG
+ 	char adrbuf[32], *myheloname;
+ #endif
  
  	enhsc = NULL;
  	if (tTd(18, 1))
***************
*** 145,150 ****
--- 149,232 ----
  	*/
  
  helo:
+ #if CLIENT_SMTP_CONFIG
+ 	myheloname = NULL;
+ 	if (m->m_ccnf == NULL)
+ 		myheloname = MyHostName;
+ 	else
+ 	{
+ 		SOCKADDR sa;
+ 		int len = sizeof(SOCKADDR);
+ 		int s = fileno(mci->mci_out);
+ 
+ 		if (getsockname(s, (struct sockaddr*)&sa, &len) >= 0)
+ 		{
+ 			struct hostent *hp;
+ 			struct client_config *ccnf;
+ 
+ 			ccnf = m->m_ccnf;
+ 			while (ccnf != NULL)
+ 			{
+ 				if (ccnf->addr.sa.sa_family == sa.sa.sa_family)
+ 					break;
+ 				ccnf = ccnf->next;
+ 			}
+ 			if (ccnf == NULL || ccnf->heloname == NULL)
+ 			{
+ 				myheloname = MyHostName;
+ 				goto skip_resolv;
+ 			}
+ 			if (strcmp(ccnf->heloname, "@") != 0)
+ 			{
+ 				myheloname = ccnf->heloname;
+ 				goto skip_resolv;
+ 			}
+ 
+ 			switch (sa.sa.sa_family)
+ 			{
+ 			  case AF_INET:
+ 				hp = sm_gethostbyaddr((char *) &sa.sin.sin_addr.s_addr, INADDRSZ, AF_INET);
+ 				if (hp != NULL)
+ 				{
+ 					myheloname = hp->h_name;
+ 					while (strchr(myheloname, '.') == NULL && hp->h_aliases != NULL && *hp->h_aliases != NULL)
+ 					{
+ 						if (strchr(*hp->h_aliases, '.') != NULL)
+ 							myheloname = *hp->h_aliases;
+ 						hp->h_aliases++;
+ 					}
+ 				}
+ 				break;
+ #if NETINET6
+ 			  case AF_INET6:
+ 				hp = sm_gethostbyaddr((char *) &sa.sin6.sin6_addr, IN6ADDRSZ, AF_INET6);
+ 				if (hp != NULL)
+ 				{
+ 					myheloname = hp->h_name;
+ 					while (strchr(myheloname, '.') == NULL && hp->h_aliases != NULL && *hp->h_aliases != NULL)
+ 					{
+ 						if (strchr(*hp->h_aliases, '.') != NULL)
+ 							myheloname = *hp->h_aliases;
+ 						hp->h_aliases++;
+ 					}
+ 				}
+ 				break;
+ #endif
+   			}
+ 
+ 			if (myheloname == NULL && sa.sa.sa_family != 0)
+ 			{
+ 				snprintf(adrbuf, sizeof(adrbuf), "[%s]",
+ 					anynet_ntoa(&sa));
+ 				myheloname = adrbuf;
+ 			}
+ 		}
+ 	}
+   skip_resolv:
+ 	if (myheloname == NULL)
+ 		myheloname = MyHostName;
+ #endif
+ 
  	if (bitnset(M_ESMTP, m->m_flags) || bitnset(M_LMTP, m->m_flags))
  		mci->mci_flags |= MCIF_ESMTP;
  	hn = mci->mci_heloname ? mci->mci_heloname : MyHostName;
***************
*** 152,168 ****
--- 234,262 ----
  tryhelo:
  	if (bitnset(M_LMTP, m->m_flags))
  	{
+ #if CLIENT_SMTP_CONFIG
+ 		smtpmessage("LHLO %s", m, mci, myheloname);
+ #else
  		smtpmessage("LHLO %s", m, mci, hn);
+ #endif
  		SmtpPhase = mci->mci_phase = "client LHLO";
  	}
  	else if (bitset(MCIF_ESMTP, mci->mci_flags))
  	{
+ #if CLIENT_SMTP_CONFIG
+ 		smtpmessage("EHLO %s", m, mci, myheloname);
+ #else
  		smtpmessage("EHLO %s", m, mci, hn);
+ #endif
  		SmtpPhase = mci->mci_phase = "client EHLO";
  	}
  	else
  	{
+ #if CLIENT_SMTP_CONFIG
+ 		smtpmessage("HELO %s", m, mci, myheloname);
+ #else
  		smtpmessage("HELO %s", m, mci, hn);
+ #endif
  		SmtpPhase = mci->mci_phase = "client HELO";
  	}
  	sm_setproctitle(TRUE, e, "%s %s: %s", qid_printname(e),
diff -c ../sendmail.org/version.c ./version.c
*** ../sendmail.org/version.c	Sat Sep 23 01:30:09 2000
--- ./version.c	Thu Nov 16 02:51:38 2000
***************
*** 12,18 ****
   */
  
  #ifndef lint
! static char id[] = "@(#)$Id: version.c,v 8.43.4.16 2000/09/21 04:12:23 geir Exp $";
  #endif /* ! lint */
  
! char	Version[] = "8.11.1";
--- 12,19 ----
   */
  
  #ifndef lint
! static char id[] = "@(#)$Id: version.c,v 8.43.4.16 2000/09/21 04:12:23 geir Exp";
! static char Wid[] = "@(#)$Id: version.c,v 1.5 2000/11/15 17:51:37 motonori Exp $";
  #endif /* ! lint */
  
! char	Version[] = "8.11.1+3.4W";