diff -cr --exclude=man --exclude=html --exclude=.indent.pro --new-file /var/tmp/postfix-2.5-20070516/HISTORY ./HISTORY
*** /var/tmp/postfix-2.5-20070516/HISTORY Tue May 15 15:51:27 2007
--- ./HISTORY Tue May 22 17:29:28 2007
***************
*** 13548,13553 ****
--- 13548,13561 ----
transports. Cause: insufficient documentation. Files:
error/error.c, discard/discard.c.
+ 20070522
+
+ Feature: recipient duplicate filter that sits between the
+ local(8) delivery agents and the cleanup(8) servers. This
+ eliminates duplicate recipients between distribution lists
+ that are implemented as local(8) aliases. It does not work
+ for list managers that re-inject mail into Postfix.
+
Wish list:
Would there be a problem adding $smtpd_mumble_restrictions
diff -cr --exclude=man --exclude=html --exclude=.indent.pro --new-file /var/tmp/postfix-2.5-20070516/Makefile.in ./Makefile.in
*** /var/tmp/postfix-2.5-20070516/Makefile.in Fri Jul 21 14:43:15 2006
--- ./Makefile.in Tue May 22 10:47:38 2007
***************
*** 8,14 ****
src/pipe src/showq src/postalias src/postcat src/postconf src/postdrop \
src/postkick src/postlock src/postlog src/postmap src/postqueue \
src/postsuper src/qmqpd src/spawn src/flush src/verify \
! src/virtual src/proxymap src/anvil src/scache src/discard src/tlsmgr
MANDIRS = proto man html
default: update
--- 8,15 ----
src/pipe src/showq src/postalias src/postcat src/postconf src/postdrop \
src/postkick src/postlock src/postlog src/postmap src/postqueue \
src/postsuper src/qmqpd src/spawn src/flush src/verify \
! src/virtual src/proxymap src/anvil src/scache src/discard src/tlsmgr \
! src/nodup
MANDIRS = proto man html
default: update
diff -cr --exclude=man --exclude=html --exclude=.indent.pro --new-file /var/tmp/postfix-2.5-20070516/conf/post-install ./conf/post-install
*** /var/tmp/postfix-2.5-20070516/conf/post-install Thu Mar 1 16:43:30 2007
--- ./conf/post-install Tue May 22 17:29:45 2007
***************
*** 659,664 ****
--- 659,673 ----
EOF
}
+ # Add missing nodup service to master.cf.
+
+ grep '^nodup.*nodup' $config_directory/master.cf >/dev/null || {
+ echo Editing $config_directory/master.cf, adding missing entry for nodup service
+ cat >>$config_directory/master.cf <$&;g;
s;\bdont_remove\b;$&;g;
s;\bdouble_bounce_sender\b;$&;g;
+ s;\bglobal_dupli[-]*\n* *[]*cate_filter_limit\b;$&;g;
s;\bdupli[-]*\n* *[]*cate_filter_limit\b;$&;g;
+ s;\bdupli[-]*\n* *[]*cate_filter_style\b;$&;g;
s;\bempty_address_recip[-]*\n* *[]*ient\b;$&;g;
s;\benable_original_recip[-]*\n* *[]*ient\b;$&;g;
s;\benable_errors_to\b;$&;g;
diff -cr --exclude=man --exclude=html --exclude=.indent.pro --new-file /var/tmp/postfix-2.5-20070516/proto/postconf.proto ./proto/postconf.proto
*** /var/tmp/postfix-2.5-20070516/proto/postconf.proto Fri May 11 19:46:17 2007
--- ./proto/postconf.proto Tue May 22 17:33:09 2007
***************
*** 1213,1223 ****
by the mail system. All mail to this address is silently discarded,
in order to terminate mail bounce loops.
! %PARAM duplicate_filter_limit 1000
The maximal number of addresses remembered by the address
duplicate filter for aliases(5) or virtual(5) alias expansion, or
! for showq(8) queue displays.
%PARAM enable_original_recipient yes
--- 1213,1224 ----
by the mail system. All mail to this address is silently discarded,
in order to terminate mail bounce loops.
! %PARAM duplicate_filter_limit 10000
The maximal number of addresses remembered by the address
duplicate filter for aliases(5) or virtual(5) alias expansion, or
! for showq(8) queue displays (with earlier Postfix releases the
! default limit was 1000).
%PARAM enable_original_recipient yes
***************
*** 10591,10595 ****
--- 10592,10624 ----
Automatically detect 8BITMIME body content by looking at
Content-Transfer-Encoding: message headers; historically, this
behavior was hard-coded to be "always on".
+
+ This feature is available in Postfix 2.5 and later.
+
+ %PARAM duplicate_filter_style strict
+
+ The duplicate recipient filter policy: strict or pragmatic.
+ With Postfix ≤ 2.2 use enable_original_recipient instead. With
+ Postfix 2.3 and 2.4, duplicate recipient elimination is currently
+ broken, because there is no option to ignore differences in DSN
+ (delivery status notification) attributes.
+
+
+
+ - strict
- Eliminate duplicate recipients only when
+ they have the exact same original recipient information, DSN (delivery
+ status notification) options, and the same envelope sender address.
+ This avoids loss of mail with "one domain per mailbox" applications,
+ and implements strict adherence to DSN standards. The X-Original-To:
+ header distinguishes between accounts within single-mailbox domains.
+
+
+ - pragmatic
- Eliminate duplicate recipients even
+ when they have different original recipient information or DSN
+ (delivery status notification) options. This avoids duplicate
+ deliveries to users that subscribe to multiple distribution lists.
+
+
+
This feature is available in Postfix 2.5 and later.
diff -cr --exclude=man --exclude=html --exclude=.indent.pro --new-file /var/tmp/postfix-2.5-20070516/src/cleanup/Makefile.in ./src/cleanup/Makefile.in
*** /var/tmp/postfix-2.5-20070516/src/cleanup/Makefile.in Sat Mar 17 13:51:40 2007
--- ./src/cleanup/Makefile.in Mon May 7 20:55:44 2007
***************
*** 310,315 ****
--- 310,316 ----
cleanup.o: ../../include/attr.h
cleanup.o: ../../include/been_here.h
cleanup.o: ../../include/cleanup_user.h
+ cleanup.o: ../../include/ctable.h
cleanup.o: ../../include/dict.h
cleanup.o: ../../include/header_opts.h
cleanup.o: ../../include/htable.h
***************
*** 329,338 ****
--- 330,341 ----
cleanup.o: ../../include/mymalloc.h
cleanup.o: ../../include/nvtable.h
cleanup.o: ../../include/rec_type.h
+ cleanup.o: ../../include/recipient_list.h
cleanup.o: ../../include/record.h
cleanup.o: ../../include/resolve_clnt.h
cleanup.o: ../../include/string_list.h
cleanup.o: ../../include/sys_defs.h
+ cleanup.o: ../../include/tcache.h
cleanup.o: ../../include/tok822.h
cleanup.o: ../../include/vbuf.h
cleanup.o: ../../include/vstream.h
***************
*** 344,349 ****
--- 347,353 ----
cleanup_addr.o: ../../include/been_here.h
cleanup_addr.o: ../../include/canon_addr.h
cleanup_addr.o: ../../include/cleanup_user.h
+ cleanup_addr.o: ../../include/ctable.h
cleanup_addr.o: ../../include/dict.h
cleanup_addr.o: ../../include/dsn_mask.h
cleanup_addr.o: ../../include/ext_prop.h
***************
*** 365,374 ****
--- 369,380 ----
cleanup_addr.o: ../../include/mymalloc.h
cleanup_addr.o: ../../include/nvtable.h
cleanup_addr.o: ../../include/rec_type.h
+ cleanup_addr.o: ../../include/recipient_list.h
cleanup_addr.o: ../../include/resolve_clnt.h
cleanup_addr.o: ../../include/string_list.h
cleanup_addr.o: ../../include/stringops.h
cleanup_addr.o: ../../include/sys_defs.h
+ cleanup_addr.o: ../../include/tcache.h
cleanup_addr.o: ../../include/tok822.h
cleanup_addr.o: ../../include/vbuf.h
cleanup_addr.o: ../../include/vstream.h
***************
*** 380,385 ****
--- 386,392 ----
cleanup_api.o: ../../include/been_here.h
cleanup_api.o: ../../include/bounce.h
cleanup_api.o: ../../include/cleanup_user.h
+ cleanup_api.o: ../../include/ctable.h
cleanup_api.o: ../../include/deliver_request.h
cleanup_api.o: ../../include/dict.h
cleanup_api.o: ../../include/dsn.h
***************
*** 407,412 ****
--- 414,420 ----
cleanup_api.o: ../../include/resolve_clnt.h
cleanup_api.o: ../../include/string_list.h
cleanup_api.o: ../../include/sys_defs.h
+ cleanup_api.o: ../../include/tcache.h
cleanup_api.o: ../../include/tok822.h
cleanup_api.o: ../../include/vbuf.h
cleanup_api.o: ../../include/vstream.h
***************
*** 416,421 ****
--- 424,430 ----
cleanup_body_edit.o: ../../include/argv.h
cleanup_body_edit.o: ../../include/been_here.h
cleanup_body_edit.o: ../../include/cleanup_user.h
+ cleanup_body_edit.o: ../../include/ctable.h
cleanup_body_edit.o: ../../include/dict.h
cleanup_body_edit.o: ../../include/header_opts.h
cleanup_body_edit.o: ../../include/htable.h
***************
*** 430,439 ****
--- 439,450 ----
cleanup_body_edit.o: ../../include/mymalloc.h
cleanup_body_edit.o: ../../include/nvtable.h
cleanup_body_edit.o: ../../include/rec_type.h
+ cleanup_body_edit.o: ../../include/recipient_list.h
cleanup_body_edit.o: ../../include/record.h
cleanup_body_edit.o: ../../include/resolve_clnt.h
cleanup_body_edit.o: ../../include/string_list.h
cleanup_body_edit.o: ../../include/sys_defs.h
+ cleanup_body_edit.o: ../../include/tcache.h
cleanup_body_edit.o: ../../include/tok822.h
cleanup_body_edit.o: ../../include/vbuf.h
cleanup_body_edit.o: ../../include/vstream.h
***************
*** 445,450 ****
--- 456,462 ----
cleanup_bounce.o: ../../include/been_here.h
cleanup_bounce.o: ../../include/bounce.h
cleanup_bounce.o: ../../include/cleanup_user.h
+ cleanup_bounce.o: ../../include/ctable.h
cleanup_bounce.o: ../../include/deliver_request.h
cleanup_bounce.o: ../../include/dict.h
cleanup_bounce.o: ../../include/dsn.h
***************
*** 476,481 ****
--- 488,494 ----
cleanup_bounce.o: ../../include/string_list.h
cleanup_bounce.o: ../../include/stringops.h
cleanup_bounce.o: ../../include/sys_defs.h
+ cleanup_bounce.o: ../../include/tcache.h
cleanup_bounce.o: ../../include/tok822.h
cleanup_bounce.o: ../../include/vbuf.h
cleanup_bounce.o: ../../include/vstream.h
***************
*** 486,491 ****
--- 499,505 ----
cleanup_envelope.o: ../../include/attr.h
cleanup_envelope.o: ../../include/been_here.h
cleanup_envelope.o: ../../include/cleanup_user.h
+ cleanup_envelope.o: ../../include/ctable.h
cleanup_envelope.o: ../../include/dict.h
cleanup_envelope.o: ../../include/dsn_mask.h
cleanup_envelope.o: ../../include/header_opts.h
***************
*** 506,516 ****
--- 520,532 ----
cleanup_envelope.o: ../../include/qmgr_user.h
cleanup_envelope.o: ../../include/rec_attr_map.h
cleanup_envelope.o: ../../include/rec_type.h
+ cleanup_envelope.o: ../../include/recipient_list.h
cleanup_envelope.o: ../../include/record.h
cleanup_envelope.o: ../../include/resolve_clnt.h
cleanup_envelope.o: ../../include/string_list.h
cleanup_envelope.o: ../../include/stringops.h
cleanup_envelope.o: ../../include/sys_defs.h
+ cleanup_envelope.o: ../../include/tcache.h
cleanup_envelope.o: ../../include/tok822.h
cleanup_envelope.o: ../../include/vbuf.h
cleanup_envelope.o: ../../include/verp_sender.h
***************
*** 522,527 ****
--- 538,544 ----
cleanup_extracted.o: ../../include/attr.h
cleanup_extracted.o: ../../include/been_here.h
cleanup_extracted.o: ../../include/cleanup_user.h
+ cleanup_extracted.o: ../../include/ctable.h
cleanup_extracted.o: ../../include/dict.h
cleanup_extracted.o: ../../include/dsn_mask.h
cleanup_extracted.o: ../../include/header_opts.h
***************
*** 542,552 ****
--- 559,571 ----
cleanup_extracted.o: ../../include/qmgr_user.h
cleanup_extracted.o: ../../include/rec_attr_map.h
cleanup_extracted.o: ../../include/rec_type.h
+ cleanup_extracted.o: ../../include/recipient_list.h
cleanup_extracted.o: ../../include/record.h
cleanup_extracted.o: ../../include/resolve_clnt.h
cleanup_extracted.o: ../../include/string_list.h
cleanup_extracted.o: ../../include/stringops.h
cleanup_extracted.o: ../../include/sys_defs.h
+ cleanup_extracted.o: ../../include/tcache.h
cleanup_extracted.o: ../../include/tok822.h
cleanup_extracted.o: ../../include/vbuf.h
cleanup_extracted.o: ../../include/vstream.h
***************
*** 556,561 ****
--- 575,581 ----
cleanup_final.o: ../../include/argv.h
cleanup_final.o: ../../include/been_here.h
cleanup_final.o: ../../include/cleanup_user.h
+ cleanup_final.o: ../../include/ctable.h
cleanup_final.o: ../../include/dict.h
cleanup_final.o: ../../include/header_opts.h
cleanup_final.o: ../../include/htable.h
***************
*** 570,578 ****
--- 590,600 ----
cleanup_final.o: ../../include/mymalloc.h
cleanup_final.o: ../../include/nvtable.h
cleanup_final.o: ../../include/rec_type.h
+ cleanup_final.o: ../../include/recipient_list.h
cleanup_final.o: ../../include/resolve_clnt.h
cleanup_final.o: ../../include/string_list.h
cleanup_final.o: ../../include/sys_defs.h
+ cleanup_final.o: ../../include/tcache.h
cleanup_final.o: ../../include/tok822.h
cleanup_final.o: ../../include/vbuf.h
cleanup_final.o: ../../include/vstream.h
***************
*** 582,587 ****
--- 604,610 ----
cleanup_init.o: ../../include/argv.h
cleanup_init.o: ../../include/been_here.h
cleanup_init.o: ../../include/cleanup_user.h
+ cleanup_init.o: ../../include/ctable.h
cleanup_init.o: ../../include/dict.h
cleanup_init.o: ../../include/ext_prop.h
cleanup_init.o: ../../include/flush_clnt.h
***************
*** 602,611 ****
--- 625,637 ----
cleanup_init.o: ../../include/mymalloc.h
cleanup_init.o: ../../include/name_mask.h
cleanup_init.o: ../../include/nvtable.h
+ cleanup_init.o: ../../include/rcpt_key.h
+ cleanup_init.o: ../../include/recipient_list.h
cleanup_init.o: ../../include/resolve_clnt.h
cleanup_init.o: ../../include/string_list.h
cleanup_init.o: ../../include/stringops.h
cleanup_init.o: ../../include/sys_defs.h
+ cleanup_init.o: ../../include/tcache.h
cleanup_init.o: ../../include/tok822.h
cleanup_init.o: ../../include/vbuf.h
cleanup_init.o: ../../include/vstream.h
***************
*** 615,620 ****
--- 641,647 ----
cleanup_map11.o: ../../include/argv.h
cleanup_map11.o: ../../include/been_here.h
cleanup_map11.o: ../../include/cleanup_user.h
+ cleanup_map11.o: ../../include/ctable.h
cleanup_map11.o: ../../include/dict.h
cleanup_map11.o: ../../include/header_opts.h
cleanup_map11.o: ../../include/htable.h
***************
*** 631,639 ****
--- 658,668 ----
cleanup_map11.o: ../../include/nvtable.h
cleanup_map11.o: ../../include/quote_822_local.h
cleanup_map11.o: ../../include/quote_flags.h
+ cleanup_map11.o: ../../include/recipient_list.h
cleanup_map11.o: ../../include/resolve_clnt.h
cleanup_map11.o: ../../include/string_list.h
cleanup_map11.o: ../../include/sys_defs.h
+ cleanup_map11.o: ../../include/tcache.h
cleanup_map11.o: ../../include/tok822.h
cleanup_map11.o: ../../include/vbuf.h
cleanup_map11.o: ../../include/vstream.h
***************
*** 643,648 ****
--- 672,678 ----
cleanup_map1n.o: ../../include/argv.h
cleanup_map1n.o: ../../include/been_here.h
cleanup_map1n.o: ../../include/cleanup_user.h
+ cleanup_map1n.o: ../../include/ctable.h
cleanup_map1n.o: ../../include/dict.h
cleanup_map1n.o: ../../include/header_opts.h
cleanup_map1n.o: ../../include/htable.h
***************
*** 660,668 ****
--- 690,700 ----
cleanup_map1n.o: ../../include/nvtable.h
cleanup_map1n.o: ../../include/quote_822_local.h
cleanup_map1n.o: ../../include/quote_flags.h
+ cleanup_map1n.o: ../../include/recipient_list.h
cleanup_map1n.o: ../../include/resolve_clnt.h
cleanup_map1n.o: ../../include/string_list.h
cleanup_map1n.o: ../../include/sys_defs.h
+ cleanup_map1n.o: ../../include/tcache.h
cleanup_map1n.o: ../../include/tok822.h
cleanup_map1n.o: ../../include/vbuf.h
cleanup_map1n.o: ../../include/vstream.h
***************
*** 672,677 ****
--- 704,710 ----
cleanup_masquerade.o: ../../include/argv.h
cleanup_masquerade.o: ../../include/been_here.h
cleanup_masquerade.o: ../../include/cleanup_user.h
+ cleanup_masquerade.o: ../../include/ctable.h
cleanup_masquerade.o: ../../include/dict.h
cleanup_masquerade.o: ../../include/header_opts.h
cleanup_masquerade.o: ../../include/htable.h
***************
*** 688,697 ****
--- 721,732 ----
cleanup_masquerade.o: ../../include/nvtable.h
cleanup_masquerade.o: ../../include/quote_822_local.h
cleanup_masquerade.o: ../../include/quote_flags.h
+ cleanup_masquerade.o: ../../include/recipient_list.h
cleanup_masquerade.o: ../../include/resolve_clnt.h
cleanup_masquerade.o: ../../include/string_list.h
cleanup_masquerade.o: ../../include/stringops.h
cleanup_masquerade.o: ../../include/sys_defs.h
+ cleanup_masquerade.o: ../../include/tcache.h
cleanup_masquerade.o: ../../include/tok822.h
cleanup_masquerade.o: ../../include/vbuf.h
cleanup_masquerade.o: ../../include/vstream.h
***************
*** 703,708 ****
--- 738,744 ----
cleanup_message.o: ../../include/been_here.h
cleanup_message.o: ../../include/cleanup_user.h
cleanup_message.o: ../../include/conv_time.h
+ cleanup_message.o: ../../include/ctable.h
cleanup_message.o: ../../include/dict.h
cleanup_message.o: ../../include/dsn_util.h
cleanup_message.o: ../../include/ext_prop.h
***************
*** 728,739 ****
--- 764,777 ----
cleanup_message.o: ../../include/quote_822_local.h
cleanup_message.o: ../../include/quote_flags.h
cleanup_message.o: ../../include/rec_type.h
+ cleanup_message.o: ../../include/recipient_list.h
cleanup_message.o: ../../include/record.h
cleanup_message.o: ../../include/resolve_clnt.h
cleanup_message.o: ../../include/split_at.h
cleanup_message.o: ../../include/string_list.h
cleanup_message.o: ../../include/stringops.h
cleanup_message.o: ../../include/sys_defs.h
+ cleanup_message.o: ../../include/tcache.h
cleanup_message.o: ../../include/tok822.h
cleanup_message.o: ../../include/vbuf.h
cleanup_message.o: ../../include/vstream.h
***************
*** 744,749 ****
--- 782,788 ----
cleanup_milter.o: ../../include/attr.h
cleanup_milter.o: ../../include/been_here.h
cleanup_milter.o: ../../include/cleanup_user.h
+ cleanup_milter.o: ../../include/ctable.h
cleanup_milter.o: ../../include/dict.h
cleanup_milter.o: ../../include/dsn_mask.h
cleanup_milter.o: ../../include/header_opts.h
***************
*** 768,778 ****
--- 807,819 ----
cleanup_milter.o: ../../include/quote_flags.h
cleanup_milter.o: ../../include/rec_attr_map.h
cleanup_milter.o: ../../include/rec_type.h
+ cleanup_milter.o: ../../include/recipient_list.h
cleanup_milter.o: ../../include/record.h
cleanup_milter.o: ../../include/resolve_clnt.h
cleanup_milter.o: ../../include/string_list.h
cleanup_milter.o: ../../include/stringops.h
cleanup_milter.o: ../../include/sys_defs.h
+ cleanup_milter.o: ../../include/tcache.h
cleanup_milter.o: ../../include/tok822.h
cleanup_milter.o: ../../include/vbuf.h
cleanup_milter.o: ../../include/vstream.h
***************
*** 782,787 ****
--- 823,829 ----
cleanup_out.o: ../../include/argv.h
cleanup_out.o: ../../include/been_here.h
cleanup_out.o: ../../include/cleanup_user.h
+ cleanup_out.o: ../../include/ctable.h
cleanup_out.o: ../../include/dict.h
cleanup_out.o: ../../include/header_opts.h
cleanup_out.o: ../../include/htable.h
***************
*** 798,808 ****
--- 840,852 ----
cleanup_out.o: ../../include/mymalloc.h
cleanup_out.o: ../../include/nvtable.h
cleanup_out.o: ../../include/rec_type.h
+ cleanup_out.o: ../../include/recipient_list.h
cleanup_out.o: ../../include/record.h
cleanup_out.o: ../../include/resolve_clnt.h
cleanup_out.o: ../../include/split_at.h
cleanup_out.o: ../../include/string_list.h
cleanup_out.o: ../../include/sys_defs.h
+ cleanup_out.o: ../../include/tcache.h
cleanup_out.o: ../../include/tok822.h
cleanup_out.o: ../../include/vbuf.h
cleanup_out.o: ../../include/vstream.h
***************
*** 814,819 ****
--- 858,864 ----
cleanup_out_recipient.o: ../../include/been_here.h
cleanup_out_recipient.o: ../../include/bounce.h
cleanup_out_recipient.o: ../../include/cleanup_user.h
+ cleanup_out_recipient.o: ../../include/ctable.h
cleanup_out_recipient.o: ../../include/deliver_request.h
cleanup_out_recipient.o: ../../include/dict.h
cleanup_out_recipient.o: ../../include/dsn.h
***************
*** 837,847 ****
--- 882,894 ----
cleanup_out_recipient.o: ../../include/msg_stats.h
cleanup_out_recipient.o: ../../include/mymalloc.h
cleanup_out_recipient.o: ../../include/nvtable.h
+ cleanup_out_recipient.o: ../../include/rcpt_key.h
cleanup_out_recipient.o: ../../include/rec_type.h
cleanup_out_recipient.o: ../../include/recipient_list.h
cleanup_out_recipient.o: ../../include/resolve_clnt.h
cleanup_out_recipient.o: ../../include/string_list.h
cleanup_out_recipient.o: ../../include/sys_defs.h
+ cleanup_out_recipient.o: ../../include/tcache.h
cleanup_out_recipient.o: ../../include/tok822.h
cleanup_out_recipient.o: ../../include/trace.h
cleanup_out_recipient.o: ../../include/vbuf.h
***************
*** 852,857 ****
--- 899,905 ----
cleanup_region.o: ../../include/argv.h
cleanup_region.o: ../../include/been_here.h
cleanup_region.o: ../../include/cleanup_user.h
+ cleanup_region.o: ../../include/ctable.h
cleanup_region.o: ../../include/dict.h
cleanup_region.o: ../../include/header_opts.h
cleanup_region.o: ../../include/htable.h
***************
*** 865,873 ****
--- 913,923 ----
cleanup_region.o: ../../include/msg.h
cleanup_region.o: ../../include/mymalloc.h
cleanup_region.o: ../../include/nvtable.h
+ cleanup_region.o: ../../include/recipient_list.h
cleanup_region.o: ../../include/resolve_clnt.h
cleanup_region.o: ../../include/string_list.h
cleanup_region.o: ../../include/sys_defs.h
+ cleanup_region.o: ../../include/tcache.h
cleanup_region.o: ../../include/tok822.h
cleanup_region.o: ../../include/vbuf.h
cleanup_region.o: ../../include/vstream.h
***************
*** 878,883 ****
--- 928,934 ----
cleanup_rewrite.o: ../../include/attr.h
cleanup_rewrite.o: ../../include/been_here.h
cleanup_rewrite.o: ../../include/cleanup_user.h
+ cleanup_rewrite.o: ../../include/ctable.h
cleanup_rewrite.o: ../../include/dict.h
cleanup_rewrite.o: ../../include/header_opts.h
cleanup_rewrite.o: ../../include/htable.h
***************
*** 895,904 ****
--- 946,957 ----
cleanup_rewrite.o: ../../include/nvtable.h
cleanup_rewrite.o: ../../include/quote_822_local.h
cleanup_rewrite.o: ../../include/quote_flags.h
+ cleanup_rewrite.o: ../../include/recipient_list.h
cleanup_rewrite.o: ../../include/resolve_clnt.h
cleanup_rewrite.o: ../../include/rewrite_clnt.h
cleanup_rewrite.o: ../../include/string_list.h
cleanup_rewrite.o: ../../include/sys_defs.h
+ cleanup_rewrite.o: ../../include/tcache.h
cleanup_rewrite.o: ../../include/tok822.h
cleanup_rewrite.o: ../../include/vbuf.h
cleanup_rewrite.o: ../../include/vstream.h
***************
*** 909,914 ****
--- 962,968 ----
cleanup_state.o: ../../include/attr.h
cleanup_state.o: ../../include/been_here.h
cleanup_state.o: ../../include/cleanup_user.h
+ cleanup_state.o: ../../include/ctable.h
cleanup_state.o: ../../include/dict.h
cleanup_state.o: ../../include/header_opts.h
cleanup_state.o: ../../include/htable.h
***************
*** 924,932 ****
--- 978,988 ----
cleanup_state.o: ../../include/mime_state.h
cleanup_state.o: ../../include/mymalloc.h
cleanup_state.o: ../../include/nvtable.h
+ cleanup_state.o: ../../include/recipient_list.h
cleanup_state.o: ../../include/resolve_clnt.h
cleanup_state.o: ../../include/string_list.h
cleanup_state.o: ../../include/sys_defs.h
+ cleanup_state.o: ../../include/tcache.h
cleanup_state.o: ../../include/tok822.h
cleanup_state.o: ../../include/vbuf.h
cleanup_state.o: ../../include/vstream.h
diff -cr --exclude=man --exclude=html --exclude=.indent.pro --new-file /var/tmp/postfix-2.5-20070516/src/cleanup/cleanup.c ./src/cleanup/cleanup.c
*** /var/tmp/postfix-2.5-20070516/src/cleanup/cleanup.c Tue May 1 13:43:57 2007
--- ./src/cleanup/cleanup.c Tue May 22 17:32:14 2007
***************
*** 257,266 ****
/* RESOURCE AND RATE CONTROLS
/* .ad
/* .fi
! /* .IP "\fBduplicate_filter_limit (1000)\fR"
/* The maximal number of addresses remembered by the address
/* duplicate filter for \fBaliases\fR(5) or \fBvirtual\fR(5) alias expansion, or
! /* for \fBshowq\fR(8) queue displays.
/* .IP "\fBheader_size_limit (102400)\fR"
/* The maximal amount of memory in bytes for storing a message header.
/* .IP "\fBhopcount_limit (50)\fR"
--- 257,267 ----
/* RESOURCE AND RATE CONTROLS
/* .ad
/* .fi
! /* .IP "\fBduplicate_filter_limit (10000)\fR"
/* The maximal number of addresses remembered by the address
/* duplicate filter for \fBaliases\fR(5) or \fBvirtual\fR(5) alias expansion, or
! /* for \fBshowq\fR(8) queue displays (with earlier Postfix releases the
! /* default limit was 1000).
/* .IP "\fBheader_size_limit (102400)\fR"
/* The maximal amount of memory in bytes for storing a message header.
/* .IP "\fBhopcount_limit (50)\fR"
***************
*** 290,295 ****
--- 291,300 ----
/* from each original recipient.
/* .IP "\fBvirtual_alias_recursion_limit (1000)\fR"
/* The maximal nesting depth of virtual alias expansion.
+ /* .PP
+ /* Available in Postfix version 2.5 and later:
+ /* .IP "\fBduplicate_filter_style (strict)\fR"
+ /* The duplicate recipient filter policy: strict or pragmatic.
/* MISCELLANEOUS CONTROLS
/* .ad
/* .fi
diff -cr --exclude=man --exclude=html --exclude=.indent.pro --new-file /var/tmp/postfix-2.5-20070516/src/cleanup/cleanup.h ./src/cleanup/cleanup.h
*** /var/tmp/postfix-2.5-20070516/src/cleanup/cleanup.h Thu Feb 15 14:34:34 2007
--- ./src/cleanup/cleanup.h Tue May 22 20:30:15 2007
***************
*** 52,57 ****
--- 52,58 ----
MAIL_STREAM *handle; /* mail stream handle */
char *queue_name; /* queue name */
char *queue_id; /* queue file basename */
+ char *org_tid; /* original transaction id */
struct timeval arrival_time; /* arrival time */
char *fullname; /* envelope sender full name */
char *sender; /* envelope sender address */
***************
*** 121,126 ****
--- 122,134 ----
#define CLEANUP_FLAG_END_SEEN (1<<18) /* REC_TYPE_END record seen */
/*
+ * Special "recip" value for deleted recipients, to avoid false "no
+ * recipients specified" bounces when all recipients were already marked as
+ * deleted (before "postsuper -r" or after agressive duplicate elimination).
+ */
+ extern char *cleanup_rcpt_deleted;
+
+ /*
* Mappings.
*/
extern MAPS *cleanup_comm_canon_maps;
***************
*** 139,144 ****
--- 147,154 ----
extern int cleanup_masq_flags;
extern MAPS *cleanup_send_bcc_maps;
extern MAPS *cleanup_rcpt_bcc_maps;
+
+ extern int cleanup_rcpt_key_flags;
/*
* Character filters.
diff -cr --exclude=man --exclude=html --exclude=.indent.pro --new-file /var/tmp/postfix-2.5-20070516/src/cleanup/cleanup_addr.c ./src/cleanup/cleanup_addr.c
*** /var/tmp/postfix-2.5-20070516/src/cleanup/cleanup_addr.c Tue May 9 11:14:10 2006
--- ./src/cleanup/cleanup_addr.c Tue May 22 15:09:37 2007
***************
*** 166,172 ****
}
cleanup_out_recipient(state, state->dsn_orcpt, state->dsn_notify,
state->orig_rcpt, STR(clean_addr));
! if (state->recip == 0)
state->recip = mystrdup(STR(clean_addr));
if ((state->flags & CLEANUP_FLAG_BCC_OK)
&& *STR(clean_addr)
--- 166,172 ----
}
cleanup_out_recipient(state, state->dsn_orcpt, state->dsn_notify,
state->orig_rcpt, STR(clean_addr));
! if (state->recip == 0 || state->recip == cleanup_rcpt_deleted)
state->recip = mystrdup(STR(clean_addr));
if ((state->flags & CLEANUP_FLAG_BCC_OK)
&& *STR(clean_addr)
diff -cr --exclude=man --exclude=html --exclude=.indent.pro --new-file /var/tmp/postfix-2.5-20070516/src/cleanup/cleanup_envelope.c ./src/cleanup/cleanup_envelope.c
*** /var/tmp/postfix-2.5-20070516/src/cleanup/cleanup_envelope.c Tue Jan 16 14:08:07 2007
--- ./src/cleanup/cleanup_envelope.c Tue May 22 20:27:43 2007
***************
*** 236,241 ****
--- 236,261 ----
}
/*
+ * The invisible Postfix original and actual transaction IDs are
+ * assigned when mail enters the queue. The org_tid is propagated
+ * when mail is forwarded internally, and is generated when mail
+ * arrives from outside Postfix.
+ *
+ * XXX The queue_id is unique to within a second, but we include the
+ * time in microseconds anyway just in case the queue ID generating
+ * algorithm changes.
+ */
+ if (state->org_tid == 0) {
+ vstring_sprintf(state->temp1, "%lx.%lx.%s",
+ (long) state->arrival_time.tv_sec,
+ (long) state->arrival_time.tv_usec,
+ state->queue_id);
+ state->org_tid = mystrdup(STR(state->temp1));
+ }
+ cleanup_out_format(state, REC_TYPE_ATTR, "%s=%s",
+ MAIL_ATTR_ORG_TID, state->org_tid);
+
+ /*
* XXX This works by accident, because the sender is recorded at the
* beginning of the envelope segment.
*/
***************
*** 276,281 ****
--- 296,303 ----
return;
}
if (type == REC_TYPE_DONE || type == REC_TYPE_DRCP) {
+ if (state->recip == 0)
+ state->recip = cleanup_rcpt_deleted;
if (state->orig_rcpt != 0) {
myfree(state->orig_rcpt);
state->orig_rcpt = 0;
***************
*** 357,362 ****
--- 379,390 ----
/* Generate our own expiration time base record. */
cleanup_out_format(state, REC_TYPE_ATTR, "%s=%ld",
MAIL_ATTR_CREATE_TIME, (long) time((time_t *) 0));
+ return;
+ }
+ if (type == REC_TYPE_OTID) {
+ /* First instance wins. */
+ if (state->org_tid == 0 && *buf)
+ state->org_tid = mystrdup(buf);
return;
}
if (type == REC_TYPE_FULL) {
diff -cr --exclude=man --exclude=html --exclude=.indent.pro --new-file /var/tmp/postfix-2.5-20070516/src/cleanup/cleanup_extracted.c ./src/cleanup/cleanup_extracted.c
*** /var/tmp/postfix-2.5-20070516/src/cleanup/cleanup_extracted.c Sun May 6 20:09:23 2007
--- ./src/cleanup/cleanup_extracted.c Tue May 22 15:07:34 2007
***************
*** 217,222 ****
--- 217,224 ----
return;
}
if (type == REC_TYPE_DONE || type == REC_TYPE_DRCP) {
+ if (state->recip == 0)
+ state->recip = cleanup_rcpt_deleted;
if (state->orig_rcpt != 0) {
myfree(state->orig_rcpt);
state->orig_rcpt = 0;
diff -cr --exclude=man --exclude=html --exclude=.indent.pro --new-file /var/tmp/postfix-2.5-20070516/src/cleanup/cleanup_init.c ./src/cleanup/cleanup_init.c
*** /var/tmp/postfix-2.5-20070516/src/cleanup/cleanup_init.c Tue May 1 09:42:14 2007
--- ./src/cleanup/cleanup_init.c Tue May 22 20:31:22 2007
***************
*** 93,98 ****
--- 93,99 ----
#include /* milter_macro_v */
#include
#include
+ #include
/* Application-specific. */
***************
*** 111,116 ****
--- 112,129 ----
VSTRING *cleanup_trace_path;
/*
+ * Control of recipient duplicate elimination.
+ */
+ int cleanup_rcpt_key_flags = RCPT_KEY_FLAG_FOLD;
+
+ /*
+ * Special "recip" value for deleted recipients, to avoid false "no
+ * recipients specified" bounces when all recipients were already marked as
+ * deleted (before "postsuper -r" or after agressive duplicate elimination).
+ */
+ char *cleanup_rcpt_deleted = "(deleted recipient)";
+
+ /*
* Tunable parameters.
*/
int var_hopcount_limit; /* max mailer hop count */
***************
*** 161,166 ****
--- 174,180 ----
char *var_milt_unk_macros; /* unknown command macros */
char *var_cleanup_milters; /* non-SMTP mail */
int var_auto_8bit_enc_hdr; /* auto-detect 8bit encoding header */
+ char *var_dup_filter_style; /* strict or pragmatic */
CONFIG_INT_TABLE cleanup_int_table[] = {
VAR_HOPCOUNT_LIMIT, DEF_HOPCOUNT_LIMIT, &var_hopcount_limit, 1, 0,
***************
*** 223,228 ****
--- 237,243 ----
VAR_MILT_EOD_MACROS, DEF_MILT_EOD_MACROS, &var_milt_eod_macros, 0, 0,
VAR_MILT_UNK_MACROS, DEF_MILT_UNK_MACROS, &var_milt_unk_macros, 0, 0,
VAR_CLEANUP_MILTERS, DEF_CLEANUP_MILTERS, &var_cleanup_milters, 0, 0,
+ VAR_DUP_FILTER_STYLE, DEF_DUP_FILTER_STYLE, &var_dup_filter_style, 1, 0,
0,
};
***************
*** 433,436 ****
--- 448,457 ----
cleanup_strip_chars = vstring_alloc(strlen(var_msg_strip_chars));
unescape(cleanup_strip_chars, var_msg_strip_chars);
}
+
+ /*
+ * Duplicate filter style.
+ */
+ cleanup_rcpt_key_flags |=
+ rcpt_key_style(VAR_DUP_FILTER_STYLE, var_dup_filter_style);
}
diff -cr --exclude=man --exclude=html --exclude=.indent.pro --new-file /var/tmp/postfix-2.5-20070516/src/cleanup/cleanup_out_recipient.c ./src/cleanup/cleanup_out_recipient.c
*** /var/tmp/postfix-2.5-20070516/src/cleanup/cleanup_out_recipient.c Thu Jan 5 19:22:04 2006
--- ./src/cleanup/cleanup_out_recipient.c Tue May 22 17:18:29 2007
***************
*** 79,84 ****
--- 79,85 ----
#include /* cleanup_trace_path */
#include
#include
+ #include
/* Application-specific. */
***************
*** 112,117 ****
--- 113,120 ----
const char *orcpt,
const char *recip)
{
+ RECIPIENT rcpt;
+ char *key;
ARGV *argv;
char **cpp;
***************
*** 124,129 ****
--- 127,137 ----
dsn_orcpt = "";
/*
+ * Not elegant, but avoids up-stream damage.
+ */
+ RECIPIENT_ASSIGN(&rcpt, (off_t) 0, dsn_orcpt, dsn_notify, orcpt, recip);
+
+ /*
* Distinguish between different original recipient addresses that map
* onto the same mailbox. The recipient will use our original recipient
* message header to figure things out.
***************
*** 132,139 ****
if ((state->flags & CLEANUP_FLAG_MAP_OK) == 0
|| cleanup_virt_alias_maps == 0) {
! if (been_here(state->dups, "%s\n%d\n%s\n%s",
! dsn_orcpt, dsn_notify, orcpt, recip) == 0) {
if (dsn_notify)
cleanup_out_format(state, REC_TYPE_ATTR, "%s=%d",
MAIL_ATTR_DSN_NOTIFY, dsn_notify);
--- 140,148 ----
if ((state->flags & CLEANUP_FLAG_MAP_OK) == 0
|| cleanup_virt_alias_maps == 0) {
! key = vstring_str(rcpt_key_format(state->temp1, "", &rcpt,
! cleanup_rcpt_key_flags));
! if (been_here_fixed(state->dups, key) == 0) {
if (dsn_notify)
cleanup_out_format(state, REC_TYPE_ATTR, "%s=%d",
MAIL_ATTR_DSN_NOTIFY, dsn_notify);
***************
*** 183,189 ****
* notification records.
*/
else {
- RECIPIENT rcpt;
DSN dsn;
argv = cleanup_map1n_internal(state, recip, cleanup_virt_alias_maps,
--- 192,197 ----
***************
*** 192,205 ****
&& (argv->argc > 1 || strcmp(recip, argv->argv[0]) != 0)) {
(void) DSN_SIMPLE(&dsn, "2.0.0", "alias expanded");
dsn.action = "expanded";
- RECIPIENT_ASSIGN(&rcpt, 0, dsn_orcpt, dsn_notify, orcpt, recip);
cleanup_trace_append(state, &rcpt, &dsn);
dsn_notify = (dsn_notify == DSN_NOTIFY_SUCCESS ? DSN_NOTIFY_NEVER :
dsn_notify & ~DSN_NOTIFY_SUCCESS);
}
for (cpp = argv->argv; *cpp; cpp++) {
! if (been_here(state->dups, "%s\n%d\n%s\n%s",
! dsn_orcpt, dsn_notify, orcpt, *cpp) == 0) {
if (dsn_notify)
cleanup_out_format(state, REC_TYPE_ATTR, "%s=%d",
MAIL_ATTR_DSN_NOTIFY, dsn_notify);
--- 200,215 ----
&& (argv->argc > 1 || strcmp(recip, argv->argv[0]) != 0)) {
(void) DSN_SIMPLE(&dsn, "2.0.0", "alias expanded");
dsn.action = "expanded";
cleanup_trace_append(state, &rcpt, &dsn);
dsn_notify = (dsn_notify == DSN_NOTIFY_SUCCESS ? DSN_NOTIFY_NEVER :
dsn_notify & ~DSN_NOTIFY_SUCCESS);
+ rcpt.dsn_notify = dsn_notify;
}
for (cpp = argv->argv; *cpp; cpp++) {
! rcpt.address = *cpp;
! key = vstring_str(rcpt_key_format(state->temp1, "", &rcpt,
! cleanup_rcpt_key_flags));
! if (been_here_fixed(state->dups, key) == 0) {
if (dsn_notify)
cleanup_out_format(state, REC_TYPE_ATTR, "%s=%d",
MAIL_ATTR_DSN_NOTIFY, dsn_notify);
diff -cr --exclude=man --exclude=html --exclude=.indent.pro --new-file /var/tmp/postfix-2.5-20070516/src/cleanup/cleanup_state.c ./src/cleanup/cleanup_state.c
*** /var/tmp/postfix-2.5-20070516/src/cleanup/cleanup_state.c Wed Jan 17 19:38:29 2007
--- ./src/cleanup/cleanup_state.c Tue May 22 15:08:36 2007
***************
*** 71,76 ****
--- 71,77 ----
state->handle = 0;
state->queue_name = 0;
state->queue_id = 0;
+ state->org_tid = 0;
state->arrival_time.tv_sec = state->arrival_time.tv_usec = 0;
state->fullname = 0;
state->sender = 0;
***************
*** 134,140 ****
myfree(state->fullname);
if (state->sender)
myfree(state->sender);
! if (state->recip)
myfree(state->recip);
if (state->orig_rcpt)
myfree(state->orig_rcpt);
--- 135,141 ----
myfree(state->fullname);
if (state->sender)
myfree(state->sender);
! if (state->recip && state->recip != cleanup_rcpt_deleted)
myfree(state->recip);
if (state->orig_rcpt)
myfree(state->orig_rcpt);
***************
*** 146,151 ****
--- 147,154 ----
myfree(state->queue_name);
if (state->queue_id)
myfree(state->queue_id);
+ if (state->org_tid)
+ myfree(state->org_tid);
been_here_free(state->dups);
if (state->reason)
myfree(state->reason);
diff -cr --exclude=man --exclude=html --exclude=.indent.pro --new-file /var/tmp/postfix-2.5-20070516/src/global/Makefile.in ./src/global/Makefile.in
*** /var/tmp/postfix-2.5-20070516/src/global/Makefile.in Tue May 8 11:27:11 2007
--- ./src/global/Makefile.in Mon May 7 20:55:40 2007
***************
*** 28,34 ****
tok822_resolve.c tok822_rewrite.c tok822_tree.c trace.c \
user_acl.c valid_mailhost_addr.c verify.c verify_clnt.c \
verp_sender.c wildcard_inet_addr.c xtext.c delivered_hdr.c \
! fold_addr.c
OBJS = abounce.o anvil_clnt.o been_here.o bounce.o bounce_log.o \
canon_addr.o cfg_parser.o cleanup_strerror.o cleanup_strflags.o \
clnt_stream.o conv_time.o db_common.o debug_peer.o debug_process.o \
--- 28,34 ----
tok822_resolve.c tok822_rewrite.c tok822_tree.c trace.c \
user_acl.c valid_mailhost_addr.c verify.c verify_clnt.c \
verp_sender.c wildcard_inet_addr.c xtext.c delivered_hdr.c \
! fold_addr.c rcpt_key.c
OBJS = abounce.o anvil_clnt.o been_here.o bounce.o bounce_log.o \
canon_addr.o cfg_parser.o cleanup_strerror.o cleanup_strflags.o \
clnt_stream.o conv_time.o db_common.o debug_peer.o debug_process.o \
***************
*** 58,64 ****
tok822_resolve.o tok822_rewrite.o tok822_tree.o trace.o \
user_acl.o valid_mailhost_addr.o verify.o verify_clnt.o \
verp_sender.o wildcard_inet_addr.o xtext.o delivered_hdr.o \
! fold_addr.o
HDRS = abounce.h anvil_clnt.h been_here.h bounce.h bounce_log.h \
canon_addr.h cfg_parser.h cleanup_user.h clnt_stream.h config.h \
conv_time.h db_common.h debug_peer.h debug_process.h defer.h \
--- 58,64 ----
tok822_resolve.o tok822_rewrite.o tok822_tree.o trace.o \
user_acl.o valid_mailhost_addr.o verify.o verify_clnt.o \
verp_sender.o wildcard_inet_addr.o xtext.o delivered_hdr.o \
! fold_addr.o rcpt_key.o
HDRS = abounce.h anvil_clnt.h been_here.h bounce.h bounce_log.h \
canon_addr.h cfg_parser.h cleanup_user.h clnt_stream.h config.h \
conv_time.h db_common.h debug_peer.h debug_process.h defer.h \
***************
*** 82,88 ****
string_list.h strip_addr.h sys_exits.h timed_ipc.h tok822.h \
trace.h user_acl.h valid_mailhost_addr.h verify.h verify_clnt.h \
verp_sender.h wildcard_inet_addr.h xtext.h delivered_hdr.h \
! fold_addr.h
TESTSRC = rec2stream.c stream2rec.c recdump.c
DEFS = -I. -I$(INC_DIR) -D$(SYSTYPE)
CFLAGS = $(DEBUG) $(OPT) $(DEFS)
--- 82,88 ----
string_list.h strip_addr.h sys_exits.h timed_ipc.h tok822.h \
trace.h user_acl.h valid_mailhost_addr.h verify.h verify_clnt.h \
verp_sender.h wildcard_inet_addr.h xtext.h delivered_hdr.h \
! fold_addr.h rcpt_key.h
TESTSRC = rec2stream.c stream2rec.c recdump.c
DEFS = -I. -I$(INC_DIR) -D$(SYSTYPE)
CFLAGS = $(DEBUG) $(OPT) $(DEFS)
***************
*** 1525,1530 ****
--- 1525,1540 ----
rcpt_buf.o: rcpt_buf.c
rcpt_buf.o: rcpt_buf.h
rcpt_buf.o: recipient_list.h
+ rcpt_key.o: ../../include/msg.h
+ rcpt_key.o: ../../include/name_code.h
+ rcpt_key.o: ../../include/stringops.h
+ rcpt_key.o: ../../include/sys_defs.h
+ rcpt_key.o: ../../include/vbuf.h
+ rcpt_key.o: ../../include/vstring.h
+ rcpt_key.o: mail_params.h
+ rcpt_key.o: rcpt_key.c
+ rcpt_key.o: rcpt_key.h
+ rcpt_key.o: recipient_list.h
rcpt_print.o: ../../include/attr.h
rcpt_print.o: ../../include/iostuff.h
rcpt_print.o: ../../include/sys_defs.h
diff -cr --exclude=man --exclude=html --exclude=.indent.pro --new-file /var/tmp/postfix-2.5-20070516/src/global/deliver_pass.c ./src/global/deliver_pass.c
*** /var/tmp/postfix-2.5-20070516/src/global/deliver_pass.c Mon Jun 5 20:47:38 2006
--- ./src/global/deliver_pass.c Sun May 20 20:10:31 2007
***************
*** 101,106 ****
--- 101,107 ----
ATTR_TYPE_INT, MAIL_ATTR_FLAGS, request->flags,
ATTR_TYPE_STR, MAIL_ATTR_QUEUE, request->queue_name,
ATTR_TYPE_STR, MAIL_ATTR_QUEUEID, request->queue_id,
+ ATTR_TYPE_STR, MAIL_ATTR_ORG_TID, request->org_tid,
ATTR_TYPE_LONG, MAIL_ATTR_OFFSET, request->data_offset,
ATTR_TYPE_LONG, MAIL_ATTR_SIZE, request->data_size,
ATTR_TYPE_STR, MAIL_ATTR_NEXTHOP, nexthop,
diff -cr --exclude=man --exclude=html --exclude=.indent.pro --new-file /var/tmp/postfix-2.5-20070516/src/global/deliver_request.c ./src/global/deliver_request.c
*** /var/tmp/postfix-2.5-20070516/src/global/deliver_request.c Tue May 15 17:00:12 2007
--- ./src/global/deliver_request.c Tue May 22 14:21:22 2007
***************
*** 12,17 ****
--- 12,18 ----
/* int flags;
/* char *queue_name;
/* char *queue_id;
+ /* char *org_tid;
/* long data_offset;
/* long data_size;
/* char *nexthop;
***************
*** 190,195 ****
--- 191,197 ----
struct stat st;
static VSTRING *queue_name;
static VSTRING *queue_id;
+ static VSTRING *org_tid;
static VSTRING *nexthop;
static VSTRING *encoding;
static VSTRING *address;
***************
*** 214,219 ****
--- 216,222 ----
if (queue_name == 0) {
queue_name = vstring_alloc(10);
queue_id = vstring_alloc(10);
+ org_tid = vstring_alloc(10);
nexthop = vstring_alloc(10);
encoding = vstring_alloc(10);
address = vstring_alloc(10);
***************
*** 237,242 ****
--- 240,246 ----
ATTR_TYPE_INT, MAIL_ATTR_FLAGS, &request->flags,
ATTR_TYPE_STR, MAIL_ATTR_QUEUE, queue_name,
ATTR_TYPE_STR, MAIL_ATTR_QUEUEID, queue_id,
+ ATTR_TYPE_STR, MAIL_ATTR_ORG_TID, org_tid,
ATTR_TYPE_LONG, MAIL_ATTR_OFFSET, &request->data_offset,
ATTR_TYPE_LONG, MAIL_ATTR_SIZE, &request->data_size,
ATTR_TYPE_STR, MAIL_ATTR_NEXTHOP, nexthop,
***************
*** 254,260 ****
ATTR_TYPE_STR, MAIL_ATTR_SASL_SENDER, sasl_sender,
ATTR_TYPE_STR, MAIL_ATTR_RWR_CONTEXT, rewrite_context,
ATTR_TYPE_INT, MAIL_ATTR_RCPT_COUNT, &rcpt_count,
! ATTR_TYPE_END) != 20) {
msg_warn("%s: error receiving common attributes", myname);
return (-1);
}
--- 258,264 ----
ATTR_TYPE_STR, MAIL_ATTR_SASL_SENDER, sasl_sender,
ATTR_TYPE_STR, MAIL_ATTR_RWR_CONTEXT, rewrite_context,
ATTR_TYPE_INT, MAIL_ATTR_RCPT_COUNT, &rcpt_count,
! ATTR_TYPE_END) != 21) {
msg_warn("%s: error receiving common attributes", myname);
return (-1);
}
***************
*** 268,273 ****
--- 272,278 ----
request->queue_name = mystrdup(vstring_str(queue_name));
request->queue_id = mystrdup(vstring_str(queue_id));
+ request->org_tid = mystrdup(vstring_str(org_tid));
request->nexthop = mystrdup(vstring_str(nexthop));
request->encoding = mystrdup(vstring_str(encoding));
request->sender = mystrdup(vstring_str(address));
***************
*** 344,349 ****
--- 349,355 ----
request->fp = 0;
request->queue_name = 0;
request->queue_id = 0;
+ request->org_tid = 0;
request->nexthop = 0;
request->encoding = 0;
request->sender = 0;
***************
*** 373,378 ****
--- 379,386 ----
myfree(request->queue_name);
if (request->queue_id)
myfree(request->queue_id);
+ if (request->org_tid)
+ myfree(request->org_tid);
if (request->nexthop)
myfree(request->nexthop);
if (request->encoding)
diff -cr --exclude=man --exclude=html --exclude=.indent.pro --new-file /var/tmp/postfix-2.5-20070516/src/global/deliver_request.h ./src/global/deliver_request.h
*** /var/tmp/postfix-2.5-20070516/src/global/deliver_request.h Tue Feb 21 14:26:59 2006
--- ./src/global/deliver_request.h Sun May 20 20:12:03 2007
***************
*** 32,37 ****
--- 32,38 ----
int flags; /* see below */
char *queue_name; /* message queue name */
char *queue_id; /* message queue id */
+ char *org_tid; /* original transaction */
long data_offset; /* offset to message */
long data_size; /* message size */
char *nexthop; /* next hop name */
diff -cr --exclude=man --exclude=html --exclude=.indent.pro --new-file /var/tmp/postfix-2.5-20070516/src/global/mail_params.c ./src/global/mail_params.c
*** /var/tmp/postfix-2.5-20070516/src/global/mail_params.c Tue May 1 14:55:43 2007
--- ./src/global/mail_params.c Sun May 20 13:16:08 2007
***************
*** 90,95 ****
--- 90,96 ----
/* char *var_flush_service;
/* char *var_verify_service;
/* char *var_trace_service;
+ /* char *var_nodup_service;
/* int var_db_create_buf;
/* int var_db_read_buf;
/* int var_mime_maxdepth;
***************
*** 263,268 ****
--- 264,270 ----
char *var_flush_service;
char *var_verify_service;
char *var_trace_service;
+ char *var_nodup_service;
int var_db_create_buf;
int var_db_read_buf;
int var_mime_maxdepth;
***************
*** 536,541 ****
--- 538,544 ----
VAR_FLUSH_SERVICE, DEF_FLUSH_SERVICE, &var_flush_service, 1, 0,
VAR_VERIFY_SERVICE, DEF_VERIFY_SERVICE, &var_verify_service, 1, 0,
VAR_TRACE_SERVICE, DEF_TRACE_SERVICE, &var_trace_service, 1, 0,
+ VAR_NODUP_SERVICE, DEF_NODUP_SERVICE, &var_nodup_service, 1, 0,
VAR_INT_FILT_CLASSES, DEF_INT_FILT_CLASSES, &var_int_filt_classes, 0, 0,
0,
};
diff -cr --exclude=man --exclude=html --exclude=.indent.pro --new-file /var/tmp/postfix-2.5-20070516/src/global/mail_params.h ./src/global/mail_params.h
*** /var/tmp/postfix-2.5-20070516/src/global/mail_params.h Thu May 3 15:54:55 2007
--- ./src/global/mail_params.h Sun May 20 20:16:20 2007
***************
*** 587,595 ****
* default, we do graceful degradation with huge mailing lists.
*/
#define VAR_DUP_FILTER_LIMIT "duplicate_filter_limit"
! #define DEF_DUP_FILTER_LIMIT 1000
extern int var_dup_filter_limit;
#define VAR_TLS_RAND_EXCH_NAME "tls_random_exchange_name"
#define DEF_TLS_RAND_EXCH_NAME "${config_directory}/prng_exch"
extern char *var_tls_rand_exch_name;
--- 587,601 ----
* default, we do graceful degradation with huge mailing lists.
*/
#define VAR_DUP_FILTER_LIMIT "duplicate_filter_limit"
! #define DEF_DUP_FILTER_LIMIT 10000
extern int var_dup_filter_limit;
+ #define DUP_FILTER_STYLE_STRICT "strict"
+ #define DUP_FILTER_STYLE_PRAGMA "pragmatic"
+ #define VAR_DUP_FILTER_STYLE "duplicate_filter_style"
+ #define DEF_DUP_FILTER_STYLE DUP_FILTER_STYLE_STRICT
+ extern char *var_dup_filter_style;
+
#define VAR_TLS_RAND_EXCH_NAME "tls_random_exchange_name"
#define DEF_TLS_RAND_EXCH_NAME "${config_directory}/prng_exch"
extern char *var_tls_rand_exch_name;
***************
*** 2293,2298 ****
--- 2299,2308 ----
#define VAR_QUEUE_SERVICE "queue_service_name"
#define DEF_QUEUE_SERVICE MAIL_SERVICE_QUEUE
extern char *var_queue_service;
+
+ #define VAR_NODUP_SERVICE "nodup_service_name"
+ #define DEF_NODUP_SERVICE MAIL_SERVICE_NODUP
+ extern char *var_nodup_service;
/* XXX resolve does not exist as a separate service */
diff -cr --exclude=man --exclude=html --exclude=.indent.pro --new-file /var/tmp/postfix-2.5-20070516/src/global/mail_proto.h ./src/global/mail_proto.h
*** /var/tmp/postfix-2.5-20070516/src/global/mail_proto.h Wed Nov 1 15:03:12 2006
--- ./src/global/mail_proto.h Sun May 20 13:07:17 2007
***************
*** 57,62 ****
--- 57,63 ----
#define MAIL_SERVICE_RELAY "relay"
#define MAIL_SERVICE_PROXYMAP "proxymap"
#define MAIL_SERVICE_SCACHE "scache"
+ #define MAIL_SERVICE_NODUP "nodup"
/*
* Well-known socket or FIFO directories. The main difference is in file
***************
*** 141,146 ****
--- 142,152 ----
#define MAIL_ATTR_CRYPTO_PROTOCOL "encryption_protocol"
#define MAIL_ATTR_CRYPTO_CIPHER "encryption_cipher"
#define MAIL_ATTR_CRYPTO_KEYSIZE "encryption_keysize"
+
+ /*
+ * Attributes for duplicate elimination.
+ */
+ #define MAIL_ATTR_ORG_TID "original_tid"
/*
* Suffixes for sender_name, sender_domain etc.
diff -cr --exclude=man --exclude=html --exclude=.indent.pro --new-file /var/tmp/postfix-2.5-20070516/src/global/rcpt_key.c ./src/global/rcpt_key.c
*** /var/tmp/postfix-2.5-20070516/src/global/rcpt_key.c Wed Dec 31 19:00:00 1969
--- ./src/global/rcpt_key.c Tue May 22 17:17:00 2007
***************
*** 0 ****
--- 1,142 ----
+ /*++
+ /* NAME
+ /* rcpt_key 3
+ /* SUMMARY
+ /* format recipient lookup key
+ /* SYNOPSIS
+ /* #include
+ /*
+ /* VSTRING *rcpt_key_format(buf, sender, rcpt, flags)
+ /* VSTRING *buf;
+ /* const char *sender;
+ /* RECIPIENT *rcpt;
+ /* int flags;
+ /*
+ /* int rcpt_key_style(name, value)
+ /* const char *name;
+ /* const char *value;
+ /* DESCRIPTION
+ /* rcpt_key_format() formats envelope information, typically
+ /* for use in recipient duplicate filtering.
+ /*
+ /* rcpt_key_style() converts the specified style to a bit-mask.
+ /*
+ /* Arguments:
+ /* .IP buf
+ /* Storage for the result, and the function result value.
+ /* .IP sender
+ /* The envelope sender address.
+ /* .IP rcpt
+ /* Recipient information. Original recipients may be passed
+ /* as null pointers.
+ /* .IP flags
+ /* The bit-wise OR of zero or more of the following:
+ /* .RS
+ /* .IP RCPT_KEY_FLAG_APPEND
+ /* Do not truncate the buffer to zero length before updating.
+ /* .IP RCPT_KEY_FLAG_FOLD
+ /* Case fold the result.
+ /* .IP RCPT_KEY_FLAG_ADDR
+ /* Include the recipient address in the result.
+ /* This attribute is required.
+ /* .IP RCPT_KEY_FLAG_X_ORIG
+ /* Include the x-original-to address in the result.
+ /* .IP RCPT_KEY_FLAG_DSN_ORIG
+ /* Include the DSN original address in the result.
+ /* .IP RCPT_KEY_FLAG_DSN_NOTIFY
+ /* Include the DSN NOTIFY options in the result.
+ /* .IP RCPT_KEY_FLAG_FROM
+ /* Include the envelope sender in the result.
+ /* .RE
+ /* .IP name
+ /* Context for error messages.
+ /* .IP value
+ /* Recipient lookup key formatting style: "strict" or "pragmatic".
+ /* DIAGNOSTICS
+ /* Fatal: incorrect formatting style; out of memory.
+ /* SEE ALSO
+ /* rcpt_cache(3) recipient duplicate detector
+ /* LICENSE
+ /* .ad
+ /* .fi
+ /* The Secure Mailer license must be distributed with this software.
+ /* AUTHOR(S)
+ /* Wietse Venema
+ /* IBM T.J. Watson Research
+ /* P.O. Box 704
+ /* Yorktown Heights, NY 10598, USA
+ /*--*/
+
+ /* System library. */
+
+ #include
+ #include
+
+ #ifdef STRCASECMP_IN_STRINGS_H
+ #include
+ #endif
+
+ /* Utility library. */
+
+ #include
+ #include
+ #include
+
+ /* Global library. */
+
+ #include
+ #include
+
+ /* rcpt_key_format - format recipient lookup key */
+
+ VSTRING *rcpt_key_format(VSTRING *buf, const char *sender,
+ RECIPIENT *rcpt, int flags)
+ {
+ int (*cmp) (const char *, const char *);
+
+ cmp = (flags & RCPT_KEY_FLAG_FOLD) ? strcasecmp : strcmp;
+
+ /*
+ * To save some memory, represent a repeated string by a control
+ * character; \1 means the string was the same as the first string
+ * attribute.
+ */
+ #define RCPT_KEY_ADDR(str) \
+ ((str) == 0 ? "" : cmp(rcpt->address, (str)) == 0 ? "\1" : (str))
+
+ if ((flags & RCPT_KEY_FLAG_APPEND) == 0)
+ VSTRING_RESET(buf);
+ if (flags & RCPT_KEY_FLAG_ADDR)
+ vstring_sprintf_append(buf, "%s\n", rcpt->address);
+ else
+ msg_panic("rcpt_key_format: recipient address attribute not requested");
+ if (flags & RCPT_KEY_FLAG_X_ORIG)
+ vstring_sprintf_append(buf, "%s\n", RCPT_KEY_ADDR(rcpt->orig_addr));
+ if (flags & RCPT_KEY_FLAG_DSN_NOTIFY)
+ vstring_sprintf_append(buf, "%d\n", rcpt->dsn_notify);
+ if (flags & RCPT_KEY_FLAG_DSN_ORIG)
+ vstring_sprintf_append(buf, "%s\n", RCPT_KEY_ADDR(rcpt->dsn_orcpt));
+ if (flags & RCPT_KEY_FLAG_FROM)
+ vstring_sprintf_append(buf, "%s\n", sender ? sender : "");
+ if (flags & RCPT_KEY_FLAG_FOLD)
+ lowercase(vstring_str(buf));
+
+ return (buf);
+ }
+
+ /* rcpt_key_style - parse recipient lookup key style */
+
+ int rcpt_key_style(const char *name, const char *value)
+ {
+ static NAME_CODE styles[] = {
+ DUP_FILTER_STYLE_STRICT, RCPT_KEY_FLAG_STRICT,
+ DUP_FILTER_STYLE_PRAGMA, RCPT_KEY_FLAG_PRAGMA,
+ 0, 0,
+ };
+ int style;
+
+ if ((style = name_code(styles, NAME_CODE_FLAG_NONE, value)) == 0)
+ msg_fatal("%s: bad duplicate filter style: %s",
+ name, value);
+ return (style);
+ }
diff -cr --exclude=man --exclude=html --exclude=.indent.pro --new-file /var/tmp/postfix-2.5-20070516/src/global/rcpt_key.h ./src/global/rcpt_key.h
*** /var/tmp/postfix-2.5-20070516/src/global/rcpt_key.h Wed Dec 31 19:00:00 1969
--- ./src/global/rcpt_key.h Tue May 22 17:17:51 2007
***************
*** 0 ****
--- 1,56 ----
+ #ifndef _RCPT_KEY_H_INCLUDED_
+ #define _RCPT_KEY_H_INCLUDED_
+
+ /*++
+ /* NAME
+ /* rcpt_key 5
+ /* SUMMARY
+ /* recipient lookup key formatter
+ /* SYNOPSIS
+ /* #include
+ /* DESCRIPTION
+ /* .nf
+
+ /*
+ * Utility library.
+ */
+ #include
+
+ /*
+ * Global library.
+ */
+ #include
+
+ /*
+ * External interface.
+ */
+ #define RCPT_KEY_FLAG_APPEND (1<<0)
+ #define RCPT_KEY_FLAG_FOLD (1<<1)
+ #define RCPT_KEY_FLAG_ADDR (1<<2)
+ #define RCPT_KEY_FLAG_X_ORIG (1<<3)
+ #define RCPT_KEY_FLAG_DSN_ORIG (1<<4)
+ #define RCPT_KEY_FLAG_DSN_NOTIFY (1<<5)
+ #define RCPT_KEY_FLAG_FROM (1<<6)
+
+ #define RCPT_KEY_FLAG_STRICT (RCPT_KEY_FLAG_X_ORIG | \
+ RCPT_KEY_FLAG_DSN_ORIG | \
+ RCPT_KEY_FLAG_DSN_NOTIFY | \
+ RCPT_KEY_FLAG_FROM | \
+ RCPT_KEY_FLAG_ADDR)
+ #define RCPT_KEY_FLAG_PRAGMA (RCPT_KEY_FLAG_ADDR)
+
+ extern VSTRING *rcpt_key_format(VSTRING *, const char *, RECIPIENT *, int);
+ extern int rcpt_key_style(const char *, const char *);
+
+ /* LICENSE
+ /* .ad
+ /* .fi
+ /* The Secure Mailer license must be distributed with this software.
+ /* AUTHOR(S)
+ /* Wietse Venema
+ /* IBM T.J. Watson Research
+ /* P.O. Box 704
+ /* Yorktown Heights, NY 10598, USA
+ /*--*/
+
+ #endif
diff -cr --exclude=man --exclude=html --exclude=.indent.pro --new-file /var/tmp/postfix-2.5-20070516/src/global/rec_attr_map.c ./src/global/rec_attr_map.c
*** /var/tmp/postfix-2.5-20070516/src/global/rec_attr_map.c Mon Mar 13 18:12:50 2006
--- ./src/global/rec_attr_map.c Sun May 20 13:00:49 2007
***************
*** 48,53 ****
--- 48,55 ----
return (REC_TYPE_DSN_RET);
} else if (strcmp(attr_name, MAIL_ATTR_CREATE_TIME) == 0) {
return (REC_TYPE_CTIME);
+ } else if (strcmp(attr_name, MAIL_ATTR_ORG_TID) == 0) {
+ return (REC_TYPE_OTID);
} else {
return (0);
}
diff -cr --exclude=man --exclude=html --exclude=.indent.pro --new-file /var/tmp/postfix-2.5-20070516/src/global/rec_type.h ./src/global/rec_type.h
*** /var/tmp/postfix-2.5-20070516/src/global/rec_type.h Tue Mar 20 11:25:10 2007
--- ./src/global/rec_type.h Sun May 20 13:00:23 2007
***************
*** 36,41 ****
--- 36,42 ----
*/
#define REC_TYPE_SIZE 'C' /* first record, created by cleanup */
#define REC_TYPE_TIME 'T' /* arrival time, required */
+ #define REC_TYPE_OTID 't' /* original transaction id, optional */
#define REC_TYPE_CTIME 'c' /* create time, optional */
#define REC_TYPE_FULL 'F' /* full name, optional */
#define REC_TYPE_INSP 'I' /* inspector transport */
***************
*** 103,109 ****
* Note: REC_TYPE_FILT and REC_TYPE_CONT are encoded with the same 'L'
* constant, and it is too late to change that now.
*/
! #define REC_TYPE_ENVELOPE "MCTcFILSDRO/WVA>KKon"
--- 104,110 ----
* Note: REC_TYPE_FILT and REC_TYPE_CONT are encoded with the same 'L'
* constant, and it is too late to change that now.
*/
! #define REC_TYPE_ENVELOPE "MCTtcFILSDRO/WVA>KKon"
diff -cr --exclude=man --exclude=html --exclude=.indent.pro --new-file /var/tmp/postfix-2.5-20070516/src/local/forward.c ./src/local/forward.c
*** /var/tmp/postfix-2.5-20070516/src/local/forward.c Mon Jun 26 08:59:19 2006
--- ./src/local/forward.c Tue May 22 20:35:24 2007
***************
*** 127,133 ****
* "message too large", perhaps some others. The reason not to bounce
* ourselves is that we don't really know who the recipients are.
*/
! cleanup = mail_connect(MAIL_CLASS_PUBLIC, var_cleanup_service, BLOCKING);
if (cleanup == 0)
return (0);
close_on_exec(vstream_fileno(cleanup), CLOSE_ON_EXEC);
--- 127,133 ----
* "message too large", perhaps some others. The reason not to bounce
* ourselves is that we don't really know who the recipients are.
*/
! cleanup = mail_connect(MAIL_CLASS_PRIVATE, var_nodup_service, BLOCKING);
if (cleanup == 0)
return (0);
close_on_exec(vstream_fileno(cleanup), CLOSE_ON_EXEC);
***************
*** 151,160 ****
--- 151,166 ----
/*
* Send initial message envelope information. For bounces, set the
* designated sender: mailing list owner, posting user, whatever.
+ *
+ * Forward the original transaction ID, to enable duplicate recipient
+ * elimination.
*/
rec_fprintf(cleanup, REC_TYPE_TIME, REC_TYPE_TIME_FORMAT,
REC_TYPE_TIME_ARG(info->posting_time));
rec_fputs(cleanup, REC_TYPE_FROM, sender);
+ if (request->org_tid[0])
+ rec_fprintf(cleanup, REC_TYPE_ATTR, "%s=%s",
+ MAIL_ATTR_ORG_TID, request->org_tid);
/*
* Don't send the original envelope ID or full/headers return mask if it
***************
*** 186,191 ****
--- 192,202 ----
PASS_ATTR(cleanup, MAIL_ATTR_SASL_SENDER, request->sasl_sender);
PASS_ATTR(cleanup, MAIL_ATTR_RWR_CONTEXT, request->rewrite_context);
+ /*
+ * Avoid select-thread blocking in the duplicate filter.
+ */
+ (void) vstream_fflush(cleanup);
+
vstring_free(buffer);
return (info);
}
***************
*** 234,239 ****
--- 245,255 ----
if (*attr.rcpt.orig_addr)
rec_fputs(info->cleanup, REC_TYPE_ORCP, attr.rcpt.orig_addr);
rec_fputs(info->cleanup, REC_TYPE_RCPT, attr.rcpt.address);
+
+ /*
+ * Avoid select-thread blocking in the duplicate filter.
+ */
+ (void) vstream_fflush(info->cleanup);
return (vstream_ferror(info->cleanup));
}
diff -cr --exclude=man --exclude=html --exclude=.indent.pro --new-file /var/tmp/postfix-2.5-20070516/src/local/local.c ./src/local/local.c
*** /var/tmp/postfix-2.5-20070516/src/local/local.c Sun Apr 29 11:49:34 2007
--- ./src/local/local.c Tue May 22 17:37:36 2007
***************
*** 443,452 ****
/* .fi
/* .IP "\fBcommand_time_limit (1000s)\fR"
/* Time limit for delivery to external commands.
! /* .IP "\fBduplicate_filter_limit (1000)\fR"
/* The maximal number of addresses remembered by the address
/* duplicate filter for \fBaliases\fR(5) or \fBvirtual\fR(5) alias expansion, or
! /* for \fBshowq\fR(8) queue displays.
/* .IP "\fBlocal_destination_concurrency_limit (2)\fR"
/* The maximal number of parallel deliveries via the local mail
/* delivery transport to the same recipient (when
--- 443,453 ----
/* .fi
/* .IP "\fBcommand_time_limit (1000s)\fR"
/* Time limit for delivery to external commands.
! /* .IP "\fBduplicate_filter_limit (10000)\fR"
/* The maximal number of addresses remembered by the address
/* duplicate filter for \fBaliases\fR(5) or \fBvirtual\fR(5) alias expansion, or
! /* for \fBshowq\fR(8) queue displays (with earlier Postfix releases the
! /* default limit was 1000).
/* .IP "\fBlocal_destination_concurrency_limit (2)\fR"
/* The maximal number of parallel deliveries via the local mail
/* delivery transport to the same recipient (when
***************
*** 537,542 ****
--- 538,544 ----
/* SEE ALSO
/* qmgr(8), queue manager
/* bounce(8), delivery status reports
+ /* nodup(8), duplicate recipient filter
/* newaliases(1), create/update alias database
/* postalias(1), create/update alias database
/* aliases(5), format of alias database
diff -cr --exclude=man --exclude=html --exclude=.indent.pro --new-file /var/tmp/postfix-2.5-20070516/src/master/mail_server.h ./src/master/mail_server.h
*** /var/tmp/postfix-2.5-20070516/src/master/mail_server.h Thu Feb 3 13:38:25 2005
--- ./src/master/mail_server.h Tue May 22 12:51:17 2007
***************
*** 31,42 ****
--- 31,44 ----
#define MAIL_SERVER_UNLIMITED 16
#define MAIL_SERVER_PRE_DISCONN 17
#define MAIL_SERVER_PRIVILEGED 18
+ #define MAIL_SERVER_CONNECT 19
#define MAIL_SERVER_IN_FLOW_DELAY 20
typedef void (*MAIL_SERVER_INIT_FN) (char *, char **);
typedef int (*MAIL_SERVER_LOOP_FN) (char *, char **);
typedef void (*MAIL_SERVER_EXIT_FN) (char *, char **);
+ typedef void (*MAIL_SERVER_CONNECT_FN) (VSTREAM *, char *, char **);
typedef void (*MAIL_SERVER_ACCEPT_FN) (char *, char **);
typedef void (*MAIL_SERVER_DISCONN_FN) (VSTREAM *, char *, char **);
diff -cr --exclude=man --exclude=html --exclude=.indent.pro --new-file /var/tmp/postfix-2.5-20070516/src/master/multi_server.c ./src/master/multi_server.c
*** /var/tmp/postfix-2.5-20070516/src/master/multi_server.c Mon Apr 2 15:09:09 2007
--- ./src/master/multi_server.c Tue May 22 12:52:35 2007
***************
*** 34,41 ****
/* A pointer to a function that is called by the skeleton each
/* time a client sends data to the program's service port. The
/* function is run after the program has optionally dropped its
! /* privileges. This function should not attempt to preserve state
! /* across calls. The stream initial state is non-blocking mode.
/* The service name argument corresponds to the service name in the
/* master.cf file.
/* The argv argument specifies command-line arguments left over
--- 34,40 ----
/* A pointer to a function that is called by the skeleton each
/* time a client sends data to the program's service port. The
/* function is run after the program has optionally dropped its
! /* privileges. The stream initial state is non-blocking mode.
/* The service name argument corresponds to the service name in the
/* master.cf file.
/* The argv argument specifies command-line arguments left over
***************
*** 90,95 ****
--- 89,97 ----
/* the next event. Specify -1 to wait for "as long as it takes".
/* .sp
/* Only the last instance of this parameter type is remembered.
+ /* .IP "MAIL_SERVER_CONNECT (void (*service)(VSTREAM *stream, char *service_name, char **argv))"
+ /* A pointer to a function that is called by the skeleton each
+ /* time a client connects to the program's service port.
/* .IP "MAIL_SERVER_EXIT (void *(char *service_name, char **argv))"
/* A pointer to function that is executed immediately before normal
/* process termination.
***************
*** 221,226 ****
--- 223,229 ----
static void (*multi_server_accept) (int, char *);
static void (*multi_server_onexit) (char *, char **);
static void (*multi_server_pre_accept) (char *, char **);
+ static void (*multi_server_connect) (VSTREAM *, char *, char **);
static VSTREAM *multi_server_lock;
static int multi_server_in_flow_delay;
static unsigned multi_server_generation;
***************
*** 367,372 ****
--- 370,377 ----
var_in_flow_delay);
else
multi_server_enable_read(0, (char *) stream);
+ if (multi_server_connect)
+ multi_server_connect(stream, multi_server_name, multi_server_argv);
}
/* multi_server_accept_local - accept client connection request */
***************
*** 669,674 ****
--- 674,682 ----
break;
case MAIL_SERVER_EXIT:
multi_server_onexit = va_arg(ap, MAIL_SERVER_EXIT_FN);
+ break;
+ case MAIL_SERVER_CONNECT:
+ multi_server_connect = va_arg(ap, MAIL_SERVER_CONNECT_FN);
break;
case MAIL_SERVER_PRE_ACCEPT:
multi_server_pre_accept = va_arg(ap, MAIL_SERVER_ACCEPT_FN);
diff -cr --exclude=man --exclude=html --exclude=.indent.pro --new-file /var/tmp/postfix-2.5-20070516/src/nodup/Makefile.in ./src/nodup/Makefile.in
*** /var/tmp/postfix-2.5-20070516/src/nodup/Makefile.in Wed Dec 31 19:00:00 1969
--- ./src/nodup/Makefile.in Tue May 22 15:27:07 2007
***************
*** 0 ****
--- 1,83 ----
+ SHELL = /bin/sh
+ SRCS = nodup.c
+ OBJS = nodup.o
+ HDRS =
+ TESTSRC =
+ DEFS = -I. -I$(INC_DIR) -D$(SYSTYPE)
+ CFLAGS = $(DEBUG) $(OPT) $(DEFS)
+ TESTPROG=
+ PROG = nodup
+ INC_DIR = ../../include
+ LIBS = ../../lib/libmaster.a ../../lib/libglobal.a ../../lib/libutil.a
+
+ .c.o:; $(CC) $(CFLAGS) -c $*.c
+
+ $(PROG): $(OBJS) $(LIBS)
+ $(CC) $(CFLAGS) -o $@ $(OBJS) $(LIBS) $(SYSLIBS)
+
+ $(OBJS): ../../conf/makedefs.out
+
+ Makefile: Makefile.in
+ cat ../../conf/makedefs.out $? >$@
+
+ test: $(TESTPROG)
+
+ tests: test
+
+ root_tests:
+
+ update: ../../libexec/$(PROG)
+
+ ../../libexec/$(PROG): $(PROG)
+ cp $(PROG) ../../libexec
+
+ printfck: $(OBJS) $(PROG)
+ rm -rf printfck
+ mkdir printfck
+ sed '1,/^# do not edit/!d' Makefile >printfck/Makefile
+ set -e; for i in *.c; do printfck -f .printfck $$i >printfck/$$i; done
+ cd printfck; make "INC_DIR=../../../include" `cd ..; ls *.o`
+
+ lint:
+ lint $(DEFS) $(SRCS) $(LINTFIX)
+
+ clean:
+ rm -f *.o *core $(PROG) $(TESTPROG) junk
+ rm -rf printfck
+
+ tidy: clean
+
+ depend: $(MAKES)
+ (sed '1,/^# do not edit/!d' Makefile.in; \
+ set -e; for i in [a-z][a-z0-9]*.c; do \
+ $(CC) -E $(DEFS) $(INCL) $$i | grep -v '[<>]' | sed -n -e '/^# *1 *"\([^"]*\)".*/{' \
+ -e 's//'`echo $$i|sed 's/c$$/o/'`': \1/' \
+ -e 's/o: \.\//o: /' -e p -e '}' ; \
+ done | sort -u) | grep -v '[.][o][:][ ][/]' >$$$$ && mv $$$$ Makefile.in
+ @$(EXPORT) make -f Makefile.in Makefile 1>&2
+
+ # do not edit below this line - it is generated by 'make depend'
+ nodup.o: ../../include/attr.h
+ nodup.o: ../../include/ctable.h
+ nodup.o: ../../include/dsn_mask.h
+ nodup.o: ../../include/iostuff.h
+ nodup.o: ../../include/mail_conf.h
+ nodup.o: ../../include/mail_params.h
+ nodup.o: ../../include/mail_proto.h
+ nodup.o: ../../include/mail_server.h
+ nodup.o: ../../include/mail_stream.h
+ nodup.o: ../../include/mail_version.h
+ nodup.o: ../../include/msg.h
+ nodup.o: ../../include/mymalloc.h
+ nodup.o: ../../include/rcpt_key.h
+ nodup.o: ../../include/rec_attr_map.h
+ nodup.o: ../../include/rec_type.h
+ nodup.o: ../../include/recipient_list.h
+ nodup.o: ../../include/record.h
+ nodup.o: ../../include/stringops.h
+ nodup.o: ../../include/sys_defs.h
+ nodup.o: ../../include/tcache.h
+ nodup.o: ../../include/vbuf.h
+ nodup.o: ../../include/vstream.h
+ nodup.o: ../../include/vstring.h
+ nodup.o: nodup.c
diff -cr --exclude=man --exclude=html --exclude=.indent.pro --new-file /var/tmp/postfix-2.5-20070516/src/nodup/nodup.c ./src/nodup/nodup.c
*** /var/tmp/postfix-2.5-20070516/src/nodup/nodup.c Wed Dec 31 19:00:00 1969
--- ./src/nodup/nodup.c Tue May 22 20:40:52 2007
***************
*** 0 ****
--- 1,554 ----
+ /*++
+ /* NAME
+ /* nodup 8
+ /* SUMMARY
+ /* Postfix duplicate recipient filter
+ /* SYNOPSIS
+ /* \fBnodup\fR [generic Postfix daemon options]
+ /* DESCRIPTION
+ /* The \fBnodup\fR(8) server performs duplicate recipient
+ /* elimination for multiple \fBlocal\fR(8) distribution list
+ /* expansions of the same email message. It is implemented as
+ /* a multi-stream filter that sits between \fBlocal\fR(8)
+ /* delivery processes and \fBcleanup\fR(8) processes.
+ /*
+ /* To benefit from this service:
+ /* .IP \(bu
+ /* \fBlocal\fR(8) Distribution lists must be configured with
+ /* their own \fBowner-\fIlistname\fR alias (see aliases(5) for
+ /* details). \fBlocal\fR(8) Distribution lists without such
+ /* an alias are not processed by the \fBnodup\fR(8) server.
+ /* .sp
+ /* Note: when an \fBowner-\fIlistname\fR alias exists, it will
+ /* be used as the envelope sender address of the message that
+ /* is sent to the members of the distribution list.
+ /* .IP \(bu
+ /* \fBlocal\fR(8) Distribution lists must be expanded before
+ /* mail leaves the Postfix system. When a distribution list
+ /* expands after, for example, delivery to external command,
+ /* Postfix will treat the result as a different email message.
+ /* The duplicate filter never eliminates duplicate recipients
+ /* that appear in different email messages.
+ /* .IP \(bu
+ /* Specify "\fBduplicate_filter_style = pragmatic\fR". With
+ /* "\fBduplicate_filter_style = strict\fR", recipients would
+ /* not only need have the same email address if they are to
+ /* count as duplicate. They would also need to have identical
+ /* original recipient and DSN attributes, and the envelope
+ /* sender addresses of different distribution list expansions
+ /* would also have to be identical. This is clearly impossible.
+ /* .sp
+ /* Note: "\fBduplicate_filter_style = strict\fR" is required
+ /* when all recipients in a domain deliver to the same mailbox.
+ /* With "\fBduplicate_filter_style = pragmatic\fR", mail would
+ /* be lost when one message is sent to multiple recipients in
+ /* a single-mailbox domain; only one delivery would be made
+ /* instead of multiple.
+ /* SECURITY
+ /* .ad
+ /* .fi
+ /* The \fBnodup\fR service is not security-sensitive. It does
+ /* not talk to the network, and it does not talk to local
+ /* users. The server can run chrooted at fixed low privilege.
+ /* DIAGNOSTICS
+ /* Problems are logged to \fBsyslogd\fR(8).
+ /* BUGS
+ /* The \fBnodup\fR(8) server maintains a volatile cache to
+ /* remember what recipients it has seen recently. This state
+ /* is lost after "\fBpostfix reload\fR"; avoid this command
+ /* while Postfix is expanding multiple distribution lists.
+ /* CONFIGURATION PARAMETERS
+ /* .ad
+ /* .fi
+ /* Changes to \fBmain.cf\fR are picked up automatically, as
+ /* \fBnodup\fR(8) processes run for only a limited amount of
+ /* time. Use the command "\fBpostfix reload\fR" to speed up
+ /* a change.
+ /*
+ /* The text below provides only a parameter summary. See
+ /* \fBpostconf\fR(5) for more details including examples.
+ /* CACHE CONTROLS
+ /* .ad
+ /* .fi
+ /* The \fBnodup\fR(8) server maintains a volatile cache to
+ /* remember what recipients it has seen recently. To avoid
+ /* failure to eliminate duplicates under load, the duplicate
+ /* cache size should be several times the size of the largest
+ /* distribution list expansion.
+ /* .IP "\fBduplicate_filter_limit (10000)\fR"
+ /* The maximal number of addresses remembered by the address
+ /* duplicate filter for \fBaliases\fR(5) or \fBvirtual\fR(5) alias expansion, or
+ /* for \fBshowq\fR(8) queue displays (with earlier Postfix releases the
+ /* default limit was 1000).
+ /* .IP "\fBduplicate_filter_style (strict)\fR"
+ /* The duplicate recipient filter policy: strict or pragmatic.
+ /* MISCELLANEOUS CONTROLS
+ /* .ad
+ /* .fi
+ /* .IP "\fBconfig_directory (see 'postconf -d' output)\fR"
+ /* The default location of the Postfix main.cf and master.cf
+ /* configuration files.
+ /* .IP "\fBdaemon_timeout (18000s)\fR"
+ /* How much time a Postfix daemon process may take to handle a
+ /* request before it is terminated by a built-in watchdog timer.
+ /* .IP "\fBipc_timeout (3600s)\fR"
+ /* The time limit for sending or receiving information over an internal
+ /* communication channel.
+ /* .IP "\fBprocess_id (read-only)\fR"
+ /* The process ID of a Postfix command or daemon process.
+ /* .IP "\fBprocess_name (read-only)\fR"
+ /* The process name of a Postfix command or daemon process.
+ /* .IP "\fBsyslog_facility (mail)\fR"
+ /* The syslog facility of Postfix logging.
+ /* .IP "\fBsyslog_name (postfix)\fR"
+ /* The mail system name that is prepended to the process name in syslog
+ /* records, so that "smtpd" becomes, for example, "postfix/smtpd".
+ /* SEE ALSO
+ /* cleanup(8), enqueue Postfix message
+ /* postconf(5), configuration parameters
+ /* syslogd(5), system logging
+ /* LICENSE
+ /* .ad
+ /* .fi
+ /* The Secure Mailer license must be distributed with this software.
+ /* HISTORY
+ /* .ad
+ /* .fi
+ /* This service was introduced with Postfix version 2.5.
+ /* AUTHOR(S)
+ /* Wietse Venema
+ /* IBM T.J. Watson Research
+ /* P.O. Box 704
+ /* Yorktown Heights, NY 10598, USA
+ /*--*/
+
+ /* System library. */
+
+ #include
+ #include
+ #include
+ #include
+
+ /* Utility library. */
+
+ #include
+ #include
+ #include
+ #include
+ #include
+
+ /* Global library. */
+
+ #include
+ #include
+ #include
+ #include
+ #include
+ #include
+ #include
+ #include
+ #include
+ #include
+ #include
+
+ /* Server skeleton. */
+
+ #include
+
+ /* Application-specific. */
+
+ /*
+ * Tunable parameters.
+ */
+ int var_dupfilter_limit;
+ char *var_dupfilter_style;
+
+ /*
+ * State information per record stream. To avoid repeated memory allocation
+ * we use long-lived buffers for original recipient information.
+ */
+ typedef struct {
+ MAIL_STREAM *cleanup_info; /* cleanup server state */
+ VSTRING *dsn_orcpt_buf; /* DSN original recipient buffer */
+ VSTRING *orig_addr_buf; /* Postfix original recipient buffer */
+ RECIPIENT rcpt; /* Generic recipient state */
+ char *sender; /* Envelope sender */
+ char *org_tid; /* Invisible original transaction ID */
+ } NODUP_STATE;
+
+ /*
+ * This is a select-threaded process, so these buffers can be global.
+ */
+ VSTRING *nodup_rec_buf; /* Record buffer */
+ VSTRING *nodup_key_buf; /* Filter lookup key */
+
+ /*
+ * Support for the global duplicate filter.
+ */
+ static int nodup_key_flags = RCPT_KEY_FLAG_FOLD;
+ TCACHE *nodup_rcpt_table; /* Recipient duplicate filter */
+
+ /*
+ * Silly little macros.
+ */
+ #define STR(x) vstring_str(x)
+ #define LEN(x) VSTRING_LEN(x)
+
+ static void nodup_receive(VSTREAM *, char *, char **);
+
+ /* nodup_connect - handle connection event */
+
+ static void nodup_connect(VSTREAM *client_stream, char *unused_service,
+ char **argv)
+ {
+ NODUP_STATE *state;
+ int flags;
+
+ /*
+ * Sanity check. This service takes no command-line arguments.
+ */
+ if (vstream_context(client_stream) != 0)
+ msg_panic("nodup_connect: server stream exists");
+ if (argv[0])
+ msg_fatal("unexpected command-line argument: %s", argv[0]);
+
+ /*
+ * This routine runs whenever a client connects to the socket dedicated
+ * to the nodup service. All connection-management stuff is handled by
+ * the common code in multi_server.c.
+ *
+ * Set up the initial connection state: connect to the cleanup server and
+ * reply with the queue ID.
+ */
+ state = (NODUP_STATE *) mymalloc(sizeof(*state));
+ state->dsn_orcpt_buf = vstring_alloc(100);
+ state->orig_addr_buf = vstring_alloc(100);
+ state->rcpt.dsn_orcpt = 0;
+ state->rcpt.dsn_notify = 0;
+ state->rcpt.orig_addr = 0;
+ state->sender = 0;
+ state->org_tid = 0;
+ vstream_control(client_stream,
+ VSTREAM_CTL_CONTEXT, (char *) state,
+ VSTREAM_CTL_END);
+
+ /*
+ * Act as aproxy for the initial handshake with the cleanup server. Note:
+ * this part of the conversation is in the form of named attributes, not
+ * queue file records.
+ */
+ state->cleanup_info =
+ mail_stream_service(MAIL_CLASS_PUBLIC, var_cleanup_service);
+ attr_print(client_stream, ATTR_FLAG_NONE,
+ ATTR_TYPE_STR, MAIL_ATTR_QUEUEID, state->cleanup_info->id,
+ ATTR_TYPE_END);
+ attr_scan(client_stream, ATTR_FLAG_STRICT,
+ ATTR_TYPE_INT, MAIL_ATTR_FLAGS, &flags,
+ ATTR_TYPE_END);
+ attr_print(state->cleanup_info->stream, ATTR_FLAG_NONE,
+ ATTR_TYPE_INT, MAIL_ATTR_FLAGS, flags,
+ ATTR_TYPE_END);
+
+ /*
+ * Don't lose the read event when input has already arrived in the
+ * VSTREAM buffer.
+ */
+ if (vstream_peek(client_stream) > 0)
+ nodup_receive(client_stream, unused_service, argv);
+ }
+
+ /* nodup_receive - perform service for client */
+
+ static void nodup_receive(VSTREAM *client_stream, char *unused_service,
+ char **argv)
+ {
+ NODUP_STATE *state = (NODUP_STATE *) vstream_context(client_stream);
+ int rec_type;
+ char *rec_val;
+ ssize_t rec_len;
+ VSTREAM *cleanup_stream;
+ RECIPIENT *rcpt;
+ char *queue_id;
+
+ /*
+ * Sanity check. This service takes no command-line arguments.
+ */
+ if (state == 0)
+ msg_panic("nodup_receive: no server stream");
+ if (argv[0])
+ msg_fatal("unexpected command-line argument: %s", argv[0]);
+
+ /*
+ * This routine runs whenever a client sends queue file records over an
+ * already open socket.
+ */
+ cleanup_stream = state->cleanup_info->stream;
+ rcpt = &state->rcpt;
+ queue_id = state->cleanup_info->id;
+
+ /*
+ * Don't block when the socket drains. With a select-threaded server,
+ * this requires that the sender flushes the stream after each recipient.
+ */
+ while (vstream_peek(client_stream) > 0
+ || readable(vstream_fileno(client_stream))) {
+ if ((rec_type = rec_get(client_stream, nodup_rec_buf, 0)) < 0) {
+ /* This calls nodup_close() to destroy the cleanup handle. */
+ multi_server_disconnect(client_stream);
+ return;
+ }
+ rec_val = STR(nodup_rec_buf);
+ rec_len = LEN(nodup_rec_buf);
+
+ /*
+ * Attribute mapping, so we can avoid clumsy code later. Pass through
+ * any named attributes that we know we don't care about.
+ */
+ if (rec_type == REC_TYPE_ATTR) {
+ const char *error_text;
+ char *attr_name;
+ char *attr_value;
+ int attr_type;
+
+ error_text = split_nameval(rec_val, &attr_name, &attr_value);
+ if (error_text != 0) {
+ msg_warn("%s: ignoring bad attribute: %s: %.200s",
+ queue_id, error_text, rec_val);
+ continue;
+ } else if ((attr_type = rec_attr_map(attr_name)) == 0) {
+ rec_fprintf(cleanup_stream, REC_TYPE_ATTR, "%s=%s",
+ attr_name, attr_value);
+ continue;
+ } else {
+ rec_len -= (attr_value - rec_val);
+ rec_val = attr_value;
+ rec_type = attr_type;
+ }
+ }
+
+ /*
+ * Save the envelope sender.
+ */
+ if (rec_type == REC_TYPE_FROM) {
+ if (state->sender)
+ msg_warn("%s: ignoring out-of-order envelope sender"
+ " record <%.200s>", queue_id, rec_val);
+ else
+ state->sender = mystrdup(rec_val);
+ }
+
+ /*
+ * Save original and DSN recipient attributes.
+ */
+ if (rec_type == REC_TYPE_DSN_ORCPT) {
+ if (rcpt->dsn_orcpt)
+ msg_warn("%s: ignoring out-of-order DSN original recipient"
+ " record <%.200s>", queue_id, rcpt->dsn_orcpt);
+ rcpt->dsn_orcpt =
+ STR(vstring_strcpy(state->dsn_orcpt_buf, rec_val));
+ continue;
+ }
+ if (rec_type == REC_TYPE_DSN_NOTIFY) {
+ int junk;
+
+ if (rcpt->dsn_notify)
+ msg_warn("%s: ignoring out-of-order DSN notify record <%d>",
+ queue_id, rcpt->dsn_notify);
+ if (!alldig(rec_val) || (junk = atoi(rec_val)) == 0
+ || DSN_NOTIFY_OK(junk) == 0)
+ msg_warn("%s: ignoring malformed DSN notify"
+ " record <%.200s>", queue_id, rec_val);
+ else
+ rcpt->dsn_notify = junk;
+ continue;
+ }
+ if (rec_type == REC_TYPE_ORCP) {
+ if (rcpt->orig_addr)
+ msg_warn("%s: ignoring out-of-order original recipient"
+ " record <%.200s>", queue_id, rcpt->orig_addr);
+ rcpt->orig_addr =
+ STR(vstring_strcpy(state->orig_addr_buf, rec_val));
+ continue;
+ }
+
+ /*
+ * Eliminate duplicate recipient, and reset the saved original and
+ * DSN recipient attributes.
+ */
+ if (rec_type == REC_TYPE_RCPT) {
+ int dup;
+
+ rcpt->address = rec_val;
+
+ /*
+ * Compute cache lookup key and eliminate duplicate recipients.
+ */
+ if (state->org_tid == 0 || state->org_tid[0] == 0) {
+ if (msg_verbose)
+ msg_info("%s: keep %s (no orig transaction id)",
+ queue_id, rcpt->address);
+ dup = 0;
+ } else {
+ rcpt_key_format(nodup_key_buf, state->sender, rcpt,
+ nodup_key_flags);
+ vstring_sprintf_append(nodup_key_buf, "\n%s", state->org_tid);
+ if (tcache_lookup(nodup_rcpt_table, STR(nodup_key_buf))) {
+ if (msg_verbose)
+ msg_info("%s: drop %s",
+ queue_id, STR(nodup_key_buf));
+ dup = 1;
+ } else {
+ if (msg_verbose)
+ msg_info("%s: keep %s",
+ queue_id, STR(nodup_key_buf));
+ TCACHE_ENTER(nodup_rcpt_table, STR(nodup_key_buf), "");
+ dup = 0;
+ }
+ }
+
+ /*
+ * If the recipient is not a duplicate, send the saved recipient
+ * information. There is no need to use REC_TYPE_ATTR here: we're
+ * not writing to queue file, so we don't need the Postfix 2.2
+ * backwards compatibility.
+ */
+ if (dup == 0) {
+ if (rcpt->dsn_orcpt)
+ REC_PUT_BUF(cleanup_stream, REC_TYPE_DSN_ORCPT,
+ state->dsn_orcpt_buf);
+ if (rcpt->dsn_notify)
+ rec_fprintf(cleanup_stream, REC_TYPE_DSN_NOTIFY,
+ "%d", rcpt->dsn_notify);
+ if (rcpt->orig_addr)
+ REC_PUT_BUF(cleanup_stream, REC_TYPE_ORCP,
+ state->orig_addr_buf);
+ REC_PUT_BUF(cleanup_stream, rec_type, nodup_rec_buf);
+ vstream_fflush(cleanup_stream);
+ }
+
+ /*
+ * If the recipient is a duplicate, send SOME recipient
+ * information to the cleanup server, otherwise the cleanup
+ * server will not be able to see the difference with malformed
+ * mail that has no recipients.
+ */
+ else {
+ REC_PUT_BUF(cleanup_stream, REC_TYPE_DONE, nodup_rec_buf);
+ }
+ rcpt->dsn_orcpt = 0;
+ rcpt->dsn_notify = 0;
+ rcpt->orig_addr = 0;
+ continue;
+ }
+
+ /*
+ * XXX Add support to forward the file descriptor so we don't waste
+ * cycles with copying mail from one socket to another.
+ */
+ if (rec_type == REC_TYPE_OTID) {
+ if (state->org_tid)
+ msg_warn("%s: ignoring duplicate original transaction ID"
+ " record <%.200s>", queue_id, rec_val);
+ else
+ state->org_tid = mystrdup(rec_val);
+ }
+
+ /*
+ * Forward the record to the cleanup server.
+ */
+ rec_put(cleanup_stream, rec_type, rec_val, rec_len);
+
+ /*
+ * Act as proxy for the cleanup server's completion status. Note:
+ * this part of the conversation is in the form of named attributes,
+ * not queue file records.
+ */
+ if (rec_type == REC_TYPE_END) {
+ int status;
+
+ /* This kills cleanup_stream, queue_id, rec_val, rec_len. */
+ status = mail_stream_finish(state->cleanup_info, nodup_rec_buf);
+ state->cleanup_info = 0;
+ attr_print(client_stream, ATTR_FLAG_NONE,
+ ATTR_TYPE_INT, MAIL_ATTR_STATUS, status,
+ ATTR_TYPE_STR, MAIL_ATTR_WHY, STR(nodup_rec_buf),
+ ATTR_TYPE_END);
+ vstream_fflush(client_stream);
+ return;
+ }
+ }
+ }
+
+ /* nodup_close - clean up per-connection state */
+
+ static void nodup_close(VSTREAM *client_stream, int unused_name,
+ char **unused_argv)
+ {
+ NODUP_STATE *state = (NODUP_STATE *) vstream_context(client_stream);
+
+ /*
+ * Abort transaction in progress.
+ */
+ if (state != 0) {
+ if (state->cleanup_info)
+ mail_stream_cleanup(state->cleanup_info);
+ vstring_free(state->dsn_orcpt_buf);
+ vstring_free(state->orig_addr_buf);
+ if (state->sender)
+ myfree(state->sender);
+ if (state->org_tid)
+ myfree(state->org_tid);
+ myfree((char *) state);
+ }
+ }
+
+ /* post_jail_init - post-jail initialization */
+
+ static void post_jail_init(char *unused_name, char **unused_argv)
+ {
+
+ /*
+ * Initialize the global duplicate filter.
+ */
+ nodup_key_flags |=
+ rcpt_key_style(VAR_DUP_FILTER_STYLE, var_dupfilter_style);
+ nodup_rcpt_table = tcache_create(var_dupfilter_limit, mystrdup, myfree);
+
+ /*
+ * Initialize other global state.
+ */
+ nodup_key_buf = vstring_alloc(100);
+ nodup_rec_buf = vstring_alloc(100);
+ }
+
+ /* Fingerprint executables and core dumps */
+
+ MAIL_VERSION_STAMP_DECLARE;
+
+ /* main - pass control to the multi-threaded skeleton */
+
+ int main(int argc, char **argv)
+ {
+ static CONFIG_INT_TABLE int_table[] = {
+ VAR_DUP_FILTER_LIMIT, DEF_DUP_FILTER_LIMIT, &var_dupfilter_limit, 0, 0,
+ 0,
+ };
+ static CONFIG_STR_TABLE str_table[] = {
+ VAR_DUP_FILTER_STYLE, DEF_DUP_FILTER_STYLE, &var_dupfilter_style, 1, 0,
+ 0,
+ };
+
+ /*
+ * Fingerprint executables and core dumps.
+ */
+ MAIL_VERSION_STAMP_ALLOCATE;
+
+ multi_server_main(argc, argv, nodup_receive,
+ MAIL_SERVER_INT_TABLE, int_table,
+ MAIL_SERVER_STR_TABLE, str_table,
+ MAIL_SERVER_POST_INIT, post_jail_init,
+ MAIL_SERVER_CONNECT, nodup_connect,
+ MAIL_SERVER_PRE_DISCONN, nodup_close,
+ MAIL_SERVER_SOLITARY,
+ 0);
+ }
diff -cr --exclude=man --exclude=html --exclude=.indent.pro --new-file /var/tmp/postfix-2.5-20070516/src/postfix/postfix.c ./src/postfix/postfix.c
*** /var/tmp/postfix-2.5-20070516/src/postfix/postfix.c Sun Apr 29 11:57:24 2007
--- ./src/postfix/postfix.c Tue May 22 11:19:04 2007
***************
*** 200,205 ****
--- 200,206 ----
/* flush(8), Postfix fast ETRN service
/* local(8), Postfix local delivery agent
/* master(8), Postfix master daemon
+ /* nodup(8), Postfix recipient duplicate filter
/* oqmgr(8), old Postfix queue manager
/* pickup(8), Postfix local mail pickup
/* pipe(8), deliver mail to non-Postfix command
diff -cr --exclude=man --exclude=html --exclude=.indent.pro --new-file /var/tmp/postfix-2.5-20070516/src/qmgr/qmgr.c ./src/qmgr/qmgr.c
*** /var/tmp/postfix-2.5-20070516/src/qmgr/qmgr.c Sat Mar 17 13:59:38 2007
--- ./src/qmgr/qmgr.c Sun May 20 13:25:06 2007
***************
*** 238,252 ****
/* OTHER RESOURCE AND RATE CONTROLS
/* .ad
/* .fi
! /* .IP "\fBminimal_backoff_time (version dependent)\fR"
! /* The minimal time between attempts to deliver a deferred message.
/* .IP "\fBmaximal_backoff_time (4000s)\fR"
/* The maximal time between attempts to deliver a deferred message.
/* .IP "\fBmaximal_queue_lifetime (5d)\fR"
/* The maximal time a message is queued before it is sent back as
/* undeliverable.
! /* .IP "\fBqueue_run_delay (version dependent)\fR"
! /* The time between deferred queue scans by the queue manager.
/* .IP "\fBtransport_retry_time (60s)\fR"
/* The time between attempts by the Postfix queue manager to contact
/* a malfunctioning message delivery transport.
--- 238,254 ----
/* OTHER RESOURCE AND RATE CONTROLS
/* .ad
/* .fi
! /* .IP "\fBminimal_backoff_time (300s)\fR"
! /* The minimal time between attempts to deliver a deferred message;
! /* prior to Postfix 2.4 the default value was 1000s.
/* .IP "\fBmaximal_backoff_time (4000s)\fR"
/* The maximal time between attempts to deliver a deferred message.
/* .IP "\fBmaximal_queue_lifetime (5d)\fR"
/* The maximal time a message is queued before it is sent back as
/* undeliverable.
! /* .IP "\fBqueue_run_delay (300s)\fR"
! /* The time between deferred queue scans by the queue manager;
! /* prior to Postfix 2.4 the default value was 1000s.
/* .IP "\fBtransport_retry_time (60s)\fR"
/* The time between attempts by the Postfix queue manager to contact
/* a malfunctioning message delivery transport.
diff -cr --exclude=man --exclude=html --exclude=.indent.pro --new-file /var/tmp/postfix-2.5-20070516/src/qmgr/qmgr.h ./src/qmgr/qmgr.h
*** /var/tmp/postfix-2.5-20070516/src/qmgr/qmgr.h Tue Jan 16 14:25:10 2007
--- ./src/qmgr/qmgr.h Sun May 20 13:25:31 2007
***************
*** 268,273 ****
--- 268,274 ----
char *queue_name; /* queue name */
char *queue_id; /* queue file */
char *encoding; /* content encoding */
+ char *org_tid; /* original transaction id */
char *sender; /* complete address */
char *dsn_envid; /* DSN envelope ID */
int dsn_ret; /* DSN headers/full */
diff -cr --exclude=man --exclude=html --exclude=.indent.pro --new-file /var/tmp/postfix-2.5-20070516/src/qmgr/qmgr_deliver.c ./src/qmgr/qmgr_deliver.c
*** /var/tmp/postfix-2.5-20070516/src/qmgr/qmgr_deliver.c Tue Jan 16 14:25:10 2007
--- ./src/qmgr/qmgr_deliver.c Mon May 7 10:12:48 2007
***************
*** 162,167 ****
--- 162,168 ----
ATTR_TYPE_INT, MAIL_ATTR_FLAGS, flags,
ATTR_TYPE_STR, MAIL_ATTR_QUEUE, message->queue_name,
ATTR_TYPE_STR, MAIL_ATTR_QUEUEID, message->queue_id,
+ ATTR_TYPE_STR, MAIL_ATTR_ORG_TID, message->org_tid,
ATTR_TYPE_LONG, MAIL_ATTR_OFFSET, message->data_offset,
ATTR_TYPE_LONG, MAIL_ATTR_SIZE, message->cont_length,
ATTR_TYPE_STR, MAIL_ATTR_NEXTHOP, entry->queue->nexthop,
diff -cr --exclude=man --exclude=html --exclude=.indent.pro --new-file /var/tmp/postfix-2.5-20070516/src/qmgr/qmgr_message.c ./src/qmgr/qmgr_message.c
*** /var/tmp/postfix-2.5-20070516/src/qmgr/qmgr_message.c Tue Jan 16 14:25:10 2007
--- ./src/qmgr/qmgr_message.c Tue May 22 20:43:55 2007
***************
*** 176,181 ****
--- 176,182 ----
message->queue_id = mystrdup(queue_id);
message->queue_name = mystrdup(queue_name);
message->encoding = 0;
+ message->org_tid = 0;
message->sender = 0;
message->dsn_envid = 0;
message->dsn_ret = 0;
***************
*** 615,620 ****
--- 616,625 ----
message->redirect_addr = mystrdup(start);
continue;
}
+ if (rec_type == REC_TYPE_OTID) {
+ if (message->org_tid == 0)
+ message->org_tid = mystrdup(start);
+ }
if (rec_type == REC_TYPE_FROM) {
if (message->sender == 0) {
message->sender = mystrdup(start);
***************
*** 795,800 ****
--- 800,807 ----
message->sasl_sender = mystrdup("");
if (message->rewrite_context == 0)
message->rewrite_context = mystrdup(MAIL_ATTR_RWR_LOCAL);
+ if (message->org_tid == 0)
+ message->org_tid = mystrdup("");
/* Postfix < 2.3 compatibility. */
if (message->create_time == 0)
message->create_time = message->arrival_time.tv_sec;
***************
*** 1357,1362 ****
--- 1364,1371 ----
myfree(message->dsn_envid);
if (message->encoding)
myfree(message->encoding);
+ if (message->org_tid)
+ myfree(message->org_tid);
if (message->sender)
myfree(message->sender);
if (message->verp_delims)
diff -cr --exclude=man --exclude=html --exclude=.indent.pro --new-file /var/tmp/postfix-2.5-20070516/src/util/Makefile.in ./src/util/Makefile.in
*** /var/tmp/postfix-2.5-20070516/src/util/Makefile.in Sat Mar 17 13:51:33 2007
--- ./src/util/Makefile.in Mon May 7 20:55:36 2007
***************
*** 30,36 ****
username.c valid_hostname.c vbuf.c vbuf_print.c vstream.c \
vstream_popen.c vstring.c vstring_vstream.c watchdog.c writable.c \
write_buf.c write_wait.c sane_basename.c format_tv.c allspace.c \
! allascii.c load_file.c killme_after.c
OBJS = alldig.o allprint.o argv.o argv_split.o attr_clnt.o attr_print0.o \
attr_print64.o attr_print_plain.o attr_scan0.o attr_scan64.o \
attr_scan_plain.o auto_clnt.o base64_code.o basename.o binhash.o \
--- 30,36 ----
username.c valid_hostname.c vbuf.c vbuf_print.c vstream.c \
vstream_popen.c vstring.c vstring_vstream.c watchdog.c writable.c \
write_buf.c write_wait.c sane_basename.c format_tv.c allspace.c \
! allascii.c load_file.c killme_after.c tcache.c
OBJS = alldig.o allprint.o argv.o argv_split.o attr_clnt.o attr_print0.o \
attr_print64.o attr_print_plain.o attr_scan0.o attr_scan64.o \
attr_scan_plain.o auto_clnt.o base64_code.o basename.o binhash.o \
***************
*** 62,68 ****
username.o valid_hostname.o vbuf.o vbuf_print.o vstream.o \
vstream_popen.o vstring.o vstring_vstream.o watchdog.o writable.o \
write_buf.o write_wait.o sane_basename.o format_tv.o allspace.o \
! allascii.o load_file.o killme_after.o
HDRS = argv.h attr.h attr_clnt.h auto_clnt.h base64_code.h binhash.h \
chroot_uid.h cidr_match.h clean_env.h connect.h ctable.h dict.h \
dict_cdb.h dict_cidr.h dict_db.h dict_dbm.h dict_env.h dict_ht.h \
--- 62,68 ----
username.o valid_hostname.o vbuf.o vbuf_print.o vstream.o \
vstream_popen.o vstring.o vstring_vstream.o watchdog.o writable.o \
write_buf.o write_wait.o sane_basename.o format_tv.o allspace.o \
! allascii.o load_file.o killme_after.o tcache.o
HDRS = argv.h attr.h attr_clnt.h auto_clnt.h base64_code.h binhash.h \
chroot_uid.h cidr_match.h clean_env.h connect.h ctable.h dict.h \
dict_cdb.h dict_cidr.h dict_db.h dict_dbm.h dict_env.h dict_ht.h \
***************
*** 81,87 ****
sigdelay.h sock_addr.h spawn_command.h split_at.h stat_as.h \
stringops.h sys_defs.h timed_connect.h timed_wait.h trigger.h \
username.h valid_hostname.h vbuf.h vbuf_print.h vstream.h vstring.h \
! vstring_vstream.h watchdog.h format_tv.h load_file.h killme_after.h
TESTSRC = fifo_open.c fifo_rdwr_bug.c fifo_rdonly_bug.c select_bug.c \
stream_test.c dup2_pass_on_exec.c
DEFS = -I. -D$(SYSTYPE)
--- 81,88 ----
sigdelay.h sock_addr.h spawn_command.h split_at.h stat_as.h \
stringops.h sys_defs.h timed_connect.h timed_wait.h trigger.h \
username.h valid_hostname.h vbuf.h vbuf_print.h vstream.h vstring.h \
! vstring_vstream.h watchdog.h format_tv.h load_file.h killme_after.h \
! tcache.h
TESTSRC = fifo_open.c fifo_rdwr_bug.c fifo_rdonly_bug.c select_bug.c \
stream_test.c dup2_pass_on_exec.c
DEFS = -I. -D$(SYSTYPE)
***************
*** 1484,1489 ****
--- 1485,1497 ----
sys_compat.o: iostuff.h
sys_compat.o: sys_compat.c
sys_compat.o: sys_defs.h
+ tcache.o: ctable.h
+ tcache.o: mymalloc.h
+ tcache.o: sys_defs.h
+ tcache.o: tcache.c
+ tcache.o: tcache.h
+ tcache.o: vbuf.h
+ tcache.o: vstring.h
timed_connect.o: iostuff.h
timed_connect.o: msg.h
timed_connect.o: sane_connect.h
diff -cr --exclude=man --exclude=html --exclude=.indent.pro --new-file /var/tmp/postfix-2.5-20070516/src/util/ctable.c ./src/util/ctable.c
*** /var/tmp/postfix-2.5-20070516/src/util/ctable.c Thu Jun 15 14:07:16 2006
--- ./src/util/ctable.c Tue May 8 08:16:49 2007
***************
*** 2,8 ****
/* NAME
/* ctable 3
/* SUMMARY
! /* cache manager
/* SYNOPSIS
/* #include
/*
--- 2,8 ----
/* NAME
/* ctable 3
/* SUMMARY
! /* push/pull cache manager
/* SYNOPSIS
/* #include
/*
***************
*** 12,17 ****
--- 12,21 ----
/* void (*delete)(void *value, void *context);
/* void *context;
/*
+ /* const void *ctable_enter(cache, key, value)
+ /* CTABLE *cache;
+ /* const char *key;
+ /*
/* const void *ctable_locate(cache, key)
/* CTABLE *cache;
/* const char *key;
***************
*** 33,41 ****
--- 37,56 ----
/* specify pointers to call-back functions that create a value, given
/* a key, and delete a given value, respectively. The context argument
/* is passed on to the call-back routines.
+ /* Specify CTABLE_NOCREATE or CTABLE_NOCREATE to suppress these
+ /* call-back actions.
+ /*
+ /* ctable_enter() stores the specified value into the cache
+ /* under the specified key. The result value is the value
+ /* argument. No attempt is made to detect duplicate cache
+ /* entries. Use ctable_locate() for that.
/*
/* ctable_locate() looks up or generates the value that corresponds to
/* the specified key, and returns that value.
+ /* If the value is not present in the cache and the create()
+ /* call-back is not CTABLE_NOCREATE, that function is called
+ /* to create the requested value. Otherwise the result is a
+ /* null pointer.
/*
/* ctable_free() destroys the specified cache, including its contents.
/*
***************
*** 119,124 ****
--- 134,165 ----
return (cache);
}
+ /* ctable_enter - enter something into the cache */
+
+ const void *ctable_enter(CTABLE *cache, const char *key, void *value)
+ {
+ const char *myname = "ctable_enter";
+ CTABLE_ENTRY *entry;
+
+ if (cache->used >= cache->limit) {
+ entry = RING_TO_CTABLE_ENTRY(ring_pred(RING_PTR_OF(cache)));
+ if (msg_verbose)
+ msg_info("%s: purge entry key %s", myname, entry->key);
+ ring_detach(RING_PTR_OF(entry));
+ cache->delete(entry->value, cache->context);
+ htable_delete(cache->table, entry->key, (void (*) (char *)) 0);
+ } else {
+ entry = (CTABLE_ENTRY *) mymalloc(sizeof(CTABLE_ENTRY));
+ cache->used++;
+ }
+ entry->value = value;
+ entry->key = htable_enter(cache->table, key, (char *) entry)->key;
+ ring_append(RING_PTR_OF(cache), RING_PTR_OF(entry));
+ if (msg_verbose)
+ msg_info("%s: install entry key %s", myname, entry->key);
+ return (value);
+ }
+
/* ctable_locate - look up or create cache item */
const void *ctable_locate(CTABLE *cache, const char *key)
***************
*** 133,154 ****
* All this means that the cache never shrinks.
*/
if ((entry = (CTABLE_ENTRY *) htable_find(cache->table, key)) == 0) {
! if (cache->used >= cache->limit) {
! entry = RING_TO_CTABLE_ENTRY(ring_pred(RING_PTR_OF(cache)));
! if (msg_verbose)
! msg_info("%s: purge entry key %s", myname, entry->key);
! ring_detach(RING_PTR_OF(entry));
! cache->delete(entry->value, cache->context);
! htable_delete(cache->table, entry->key, (void (*) (char *)) 0);
! } else {
! entry = (CTABLE_ENTRY *) mymalloc(sizeof(CTABLE_ENTRY));
! cache->used++;
! }
! entry->value = cache->create(key, cache->context);
! entry->key = htable_enter(cache->table, key, (char *) entry)->key;
! ring_append(RING_PTR_OF(cache), RING_PTR_OF(entry));
! if (msg_verbose)
! msg_info("%s: install entry key %s", myname, entry->key);
} else if (entry == RING_TO_CTABLE_ENTRY(ring_succ(RING_PTR_OF(cache)))) {
if (msg_verbose)
msg_info("%s: leave existing entry key %s", myname, entry->key);
--- 174,184 ----
* All this means that the cache never shrinks.
*/
if ((entry = (CTABLE_ENTRY *) htable_find(cache->table, key)) == 0) {
! if (cache->create == 0)
! return (0);
! else
! return (ctable_enter(cache, key,
! cache->create(key, cache->context)));
} else if (entry == RING_TO_CTABLE_ENTRY(ring_succ(RING_PTR_OF(cache)))) {
if (msg_verbose)
msg_info("%s: leave existing entry key %s", myname, entry->key);
diff -cr --exclude=man --exclude=html --exclude=.indent.pro --new-file /var/tmp/postfix-2.5-20070516/src/util/ctable.h ./src/util/ctable.h
*** /var/tmp/postfix-2.5-20070516/src/util/ctable.h Sun Jul 29 14:31:44 2001
--- ./src/util/ctable.h Mon May 7 11:27:30 2007
***************
*** 20,29 ****
--- 20,33 ----
typedef void *(*CTABLE_CREATE_FN) (const char *, void *);
typedef void (*CTABLE_DELETE_FN) (void *, void *);
+ #define CTABLE_NOCREATE ((CTABLE_CREATE_FN) 0)
+ #define CTABLE_NODELETE ((CTABLE_DELETE_FN) 0)
+
extern CTABLE *ctable_create(int, CTABLE_CREATE_FN, CTABLE_DELETE_FN, void *);
extern void ctable_free(CTABLE *);
extern void ctable_walk(CTABLE *, void (*) (const char *, const void *));
extern const void *ctable_locate(CTABLE *, const char *);
+ extern const void *ctable_enter(CTABLE *, const char *, void *);
/* LICENSE
/* .ad
diff -cr --exclude=man --exclude=html --exclude=.indent.pro --new-file /var/tmp/postfix-2.5-20070516/src/util/ctable.ref ./src/util/ctable.ref
*** /var/tmp/postfix-2.5-20070516/src/util/ctable.ref Sun Jul 29 12:15:20 2001
--- ./src/util/ctable.ref Fri May 4 20:13:29 2007
***************
*** 1,60 ****
key = a
ask: a = 1
! ./ctable: ctable_locate: install entry key a
result: 1
key = b
ask: b = 2
! ./ctable: ctable_locate: install entry key b
result: 2
key = c
ask: c = 3
! ./ctable: ctable_locate: install entry key c
result: 3
key = d
ask: d = 4
! ./ctable: ctable_locate: install entry key d
result: 4
key = e
ask: e = 5
! ./ctable: ctable_locate: install entry key e
result: 5
key = f
- ./ctable: ctable_locate: purge entry key a
ask: f = 6
! ./ctable: ctable_locate: install entry key f
result: 6
key = f
./ctable: ctable_locate: leave existing entry key f
result: 6
key = a
- ./ctable: ctable_locate: purge entry key b
ask: a = 1
! ./ctable: ctable_locate: install entry key a
result: 1
key = b
- ./ctable: ctable_locate: purge entry key c
ask: b = 2
! ./ctable: ctable_locate: install entry key b
result: 2
key = c
- ./ctable: ctable_locate: purge entry key d
ask: c = 3
! ./ctable: ctable_locate: install entry key c
result: 3
key = d
- ./ctable: ctable_locate: purge entry key e
ask: d = 4
! ./ctable: ctable_locate: install entry key d
result: 4
key = e
- ./ctable: ctable_locate: purge entry key f
ask: e = 5
! ./ctable: ctable_locate: install entry key e
result: 5
key = f
- ./ctable: ctable_locate: purge entry key a
ask: f = 6
! ./ctable: ctable_locate: install entry key f
result: 6
key = f
./ctable: ctable_locate: leave existing entry key f
--- 1,60 ----
key = a
ask: a = 1
! ./ctable: ctable_enter: install entry key a
result: 1
key = b
ask: b = 2
! ./ctable: ctable_enter: install entry key b
result: 2
key = c
ask: c = 3
! ./ctable: ctable_enter: install entry key c
result: 3
key = d
ask: d = 4
! ./ctable: ctable_enter: install entry key d
result: 4
key = e
ask: e = 5
! ./ctable: ctable_enter: install entry key e
result: 5
key = f
ask: f = 6
! ./ctable: ctable_enter: purge entry key a
! ./ctable: ctable_enter: install entry key f
result: 6
key = f
./ctable: ctable_locate: leave existing entry key f
result: 6
key = a
ask: a = 1
! ./ctable: ctable_enter: purge entry key b
! ./ctable: ctable_enter: install entry key a
result: 1
key = b
ask: b = 2
! ./ctable: ctable_enter: purge entry key c
! ./ctable: ctable_enter: install entry key b
result: 2
key = c
ask: c = 3
! ./ctable: ctable_enter: purge entry key d
! ./ctable: ctable_enter: install entry key c
result: 3
key = d
ask: d = 4
! ./ctable: ctable_enter: purge entry key e
! ./ctable: ctable_enter: install entry key d
result: 4
key = e
ask: e = 5
! ./ctable: ctable_enter: purge entry key f
! ./ctable: ctable_enter: install entry key e
result: 5
key = f
ask: f = 6
! ./ctable: ctable_enter: purge entry key a
! ./ctable: ctable_enter: install entry key f
result: 6
key = f
./ctable: ctable_locate: leave existing entry key f
***************
*** 72,80 ****
./ctable: ctable_locate: move existing entry key b
result: 2
key = a
- ./ctable: ctable_locate: purge entry key f
ask: a = 1
! ./ctable: ctable_locate: install entry key a
result: 1
key = b
./ctable: ctable_locate: move existing entry key b
--- 72,80 ----
./ctable: ctable_locate: move existing entry key b
result: 2
key = a
ask: a = 1
! ./ctable: ctable_enter: purge entry key f
! ./ctable: ctable_enter: install entry key a
result: 1
key = b
./ctable: ctable_locate: move existing entry key b
***************
*** 89,97 ****
./ctable: ctable_locate: move existing entry key e
result: 5
key = f
- ./ctable: ctable_locate: purge entry key a
ask: f = 6
! ./ctable: ctable_locate: install entry key f
result: 6
key = f
./ctable: ctable_locate: leave existing entry key f
--- 89,97 ----
./ctable: ctable_locate: move existing entry key e
result: 5
key = f
ask: f = 6
! ./ctable: ctable_enter: purge entry key a
! ./ctable: ctable_enter: install entry key f
result: 6
key = f
./ctable: ctable_locate: leave existing entry key f
diff -cr --exclude=man --exclude=html --exclude=.indent.pro --new-file /var/tmp/postfix-2.5-20070516/src/util/tcache.c ./src/util/tcache.c
*** /var/tmp/postfix-2.5-20070516/src/util/tcache.c Wed Dec 31 19:00:00 1969
--- ./src/util/tcache.c Tue May 22 16:09:14 2007
***************
*** 0 ****
--- 1,124 ----
+ /*++
+ /* NAME
+ /* tcache 3
+ /* SUMMARY
+ /* trivial push-mode cache manager
+ /* SYNOPSIS
+ /* #include
+ /*
+ /* typedef struct TCACHE {
+ /* VSTRING *key_buf;
+ /* /* private members... */
+ /* } TCACHE;
+ /*
+ /* TCACHE *tcache_create(size, save_fn, delete_fn)
+ /* int size;
+ /* char *(*save_fn)(const char *value);
+ /* void (*delete_fn)(char *value);
+ /*
+ /* const char *TCACHE_ENTER(tcache, key, value)
+ /* TCACHE *tcache;
+ /* const char *key;
+ /* const char *value;
+ /*
+ /* const char *tcache_lookup(tcache, key)
+ /* TCACHE *tcache;
+ /* const char *key;
+ /*
+ /* void tcache_free(tcache)
+ /* TCACHE *tcache;
+ /* DESCRIPTION
+ /* This module maintains a trivial push-mode cache, where the
+ /* caller pushes information into the cache and where the cache
+ /* manager silently throws information away.
+ /*
+ /* tcache_create() creates a trivial cache instance.
+ /*
+ /* TCACHE_ENTER() enters a value into the cache under the
+ /* specified key. No duplicate check is done: use tcache_lookup()
+ /* for that.
+ /*
+ /* tcache_lookup() looks up a value that was stored under the
+ /* specified key, or a null pointer value.
+ /*
+ /* tcache_free() destroys a trivial cache instance.
+ /*
+ /* Arguments:
+ /* .IP size
+ /* The number of cache entries. Old entries are removed when
+ /* new entries are added while the cache is full.
+ /* .IP save_fn
+ /* Null pointer, or pointer to function that saves a copy of
+ /* its value argument.
+ /* .IP delete_fn
+ /* Null pointer, or pointer to function that deletes a saved
+ /* value.
+ /* .IP key
+ /* Lookup key. For convenience, each TCACHE provides a buffer
+ /* that the application can (but does not have to) use to
+ /* save the key for the _lookup and _enter operations.
+ /* .IP delete
+ /* A null pointer, or pointer to call-back function that
+ /* receives as arguments a cached value and a pointer to the
+ /* TCACHE object.
+ /* BUGS
+ /* No tcache_delete() or tcache_update() operations.
+ /* SEE ALSO
+ /* rcpt_key(3) recipient lookup key formatter.
+ /* LICENSE
+ /* .ad
+ /* .fi
+ /* The Secure Mailer license must be distributed with this software.
+ /* AUTHOR(S)
+ /* Wietse Venema
+ /* IBM T.J. Watson Research
+ /* P.O. Box 704
+ /* Yorktown Heights, NY 10598, USA
+ /*--*/
+
+ /* System library. */
+
+ #include
+
+ /* Utility library. */
+
+ #include
+
+ /* Global library. */
+
+ #include
+
+ /* tcache_delete_cb - delete call-back adapter */
+
+ static void tcache_delete_cb(void *value, void *context)
+ {
+ TCACHE *tp = (TCACHE *) context;
+
+ tp->delete_fn(value);
+ }
+
+ /* tcache_create - create trivial cache */
+
+ TCACHE *tcache_create(int size, TCACHE_SAVE_FN save_fn,
+ TCACHE_DELETE_FN delete_fn)
+ {
+ TCACHE *tp;
+
+ tp = (TCACHE *) mymalloc(sizeof(*tp));
+ tp->key_buf = vstring_alloc(10);
+ tp->table = ctable_create(size, CTABLE_NOCREATE, delete_fn ?
+ tcache_delete_cb : CTABLE_NODELETE,
+ (void *) tp);
+ tp->save_fn = save_fn;
+ tp->delete_fn = delete_fn;
+ return (tp);
+ }
+
+ /* tcache_free - destroy trivial cache */
+
+ void tcache_free(TCACHE *tp)
+ {
+ vstring_free(tp->key_buf);
+ ctable_free(tp->table);
+ myfree((char *) tp);
+ }
diff -cr --exclude=man --exclude=html --exclude=.indent.pro --new-file /var/tmp/postfix-2.5-20070516/src/util/tcache.h ./src/util/tcache.h
*** /var/tmp/postfix-2.5-20070516/src/util/tcache.h Wed Dec 31 19:00:00 1969
--- ./src/util/tcache.h Tue May 22 16:07:01 2007
***************
*** 0 ****
--- 1,53 ----
+ #ifndef _TCACHE_H_INCLUDED_
+ #define _TCACHE_H_INCLUDED_
+
+ /*++
+ /* NAME
+ /* tcache 5
+ /* SUMMARY
+ /* trivial cache manager
+ /* SYNOPSIS
+ /* #include
+ /* DESCRIPTION
+ /* .nf
+
+ /*
+ * Utility library.
+ */
+ #include
+ #include
+
+ /*
+ * External interface.
+ */
+ typedef char *(*TCACHE_SAVE_FN) (const char *);
+ typedef void (*TCACHE_DELETE_FN) (char *);
+
+ typedef struct {
+ VSTRING *key_buf;
+ CTABLE *table;
+ TCACHE_SAVE_FN save_fn;
+ TCACHE_DELETE_FN delete_fn;
+ } TCACHE;
+
+ extern TCACHE *tcache_create(int, TCACHE_SAVE_FN, TCACHE_DELETE_FN);
+ extern void tcache_free(TCACHE *);
+
+ #define tcache_lookup(tp, key) \
+ ((char *) ctable_locate((tp)->table, (key)))
+ #define TCACHE_ENTER(tp, key, val) \
+ ((char *) ctable_enter((tp)->table, (key), (tp)->save_fn ? \
+ (tp)->save_fn(val) : (val)))
+
+ /* LICENSE
+ /* .ad
+ /* .fi
+ /* The Secure Mailer license must be distributed with this software.
+ /* AUTHOR(S)
+ /* Wietse Venema
+ /* IBM T.J. Watson Research
+ /* P.O. Box 704
+ /* Yorktown Heights, NY 10598, USA
+ /*--*/
+
+ #endif