]> git.ipfire.org Git - thirdparty/postfix.git/commitdiff
postfix-3.8-20220507
authorWietse Venema <wietse@porcupine.org>
Sat, 7 May 2022 05:00:00 +0000 (00:00 -0500)
committerViktor Dukhovni <postfix-users@dukhovni.org>
Sun, 8 May 2022 05:03:23 +0000 (15:03 +1000)
60 files changed:
postfix/HISTORY
postfix/INSTALL
postfix/Makefile.in
postfix/README_FILES/INSTALL
postfix/README_FILES/IPV6_README
postfix/RELEASE_NOTES
postfix/WISHLIST
postfix/html/INSTALL.html
postfix/html/IPV6_README.html
postfix/html/postconf.5.html
postfix/man/man5/postconf.5
postfix/mantools/check-double-history [new file with mode: 0755]
postfix/mantools/check-spell-history [new file with mode: 0755]
postfix/proto/INSTALL.html
postfix/proto/IPV6_README.html
postfix/proto/postconf.proto
postfix/proto/stop.double-cc
postfix/proto/stop.double-history [new file with mode: 0644]
postfix/proto/stop.spell-cc
postfix/proto/stop.spell-history [new file with mode: 0644]
postfix/src/cleanup/cleanup_map1n.c
postfix/src/global/Makefile.in
postfix/src/global/compat_level.c
postfix/src/global/compat_level.h
postfix/src/global/dict_proxy.h
postfix/src/global/dynamicmaps.c
postfix/src/global/header_body_checks.h
postfix/src/global/mail_dict.c
postfix/src/global/mail_version.h
postfix/src/global/maps.c
postfix/src/global/mkmap.h [deleted file]
postfix/src/global/mkmap_proxy.c
postfix/src/postalias/Makefile.in
postfix/src/postalias/postalias.c
postfix/src/postconf/Makefile.in
postfix/src/postmap/Makefile.in
postfix/src/postmap/postmap.c
postfix/src/postscreen/postscreen_smtpd.c
postfix/src/proxymap/Makefile.in
postfix/src/smtp/Makefile.in
postfix/src/util/Makefile.in
postfix/src/util/argv.c
postfix/src/util/argv.h
postfix/src/util/dict.c
postfix/src/util/dict.h
postfix/src/util/dict_cdb.h
postfix/src/util/dict_db.h
postfix/src/util/dict_dbm.h
postfix/src/util/dict_fail.h
postfix/src/util/dict_lmdb.h
postfix/src/util/dict_open.c
postfix/src/util/dict_sdbm.h
postfix/src/util/mkmap.h [new file with mode: 0644]
postfix/src/util/mkmap_cdb.c [moved from postfix/src/global/mkmap_cdb.c with 92% similarity]
postfix/src/util/mkmap_db.c [moved from postfix/src/global/mkmap_db.c with 81% similarity]
postfix/src/util/mkmap_dbm.c [moved from postfix/src/global/mkmap_dbm.c with 96% similarity]
postfix/src/util/mkmap_fail.c [moved from postfix/src/global/mkmap_fail.c with 89% similarity]
postfix/src/util/mkmap_lmdb.c [moved from postfix/src/global/mkmap_lmdb.c with 83% similarity]
postfix/src/util/mkmap_open.c [moved from postfix/src/global/mkmap_open.c with 55% similarity]
postfix/src/util/mkmap_sdbm.c [moved from postfix/src/global/mkmap_sdbm.c with 96% similarity]

index 86709023587d605cffea4d73b00b09c6cc706317..3da460d7d301dc7dc91f95d1605dbcfac5ba88e0 100644 (file)
@@ -26207,7 +26207,7 @@ Apologies for any names omitted.
 
        Cleanup: unit tests. File: cleanup/cleanup_milter.c.
 
-       Cleamup: disable hash-table seed in unit tests. Many
+       Cleanup: disable hash-table seed in unit tests. Many
        Makefiles, some unit test 'reference' files.
 
        Bugfix (documented but not implemented since Postfix 2.2):
@@ -26234,7 +26234,7 @@ Apologies for any names omitted.
        mantools/check-spell-install-proto-text.
 
        Cleanup: for consistent parameter naming (tlsproxy_client_xxx
-       correspnds to smtp_tls_xxx), renamed tlsproxy_client_level
+       corresponds to smtp_tls_xxx), renamed tlsproxy_client_level
        to tlsproxy_client_security_level, and tlsproxy_client_policy
        to tlsproxy_client_policy_maps, with backwards-compatible
        defaults and updated documentation. Problem reported by
@@ -26258,7 +26258,7 @@ Apologies for any names omitted.
 
 20220128
 
-       Clenaup: standardize on FNV hash, after having verified
+       Cleanup: standardize on FNV hash, after having verified
        that collisions will change with the hash seed value, and
        that the collision rate is low. Files: util/htable.c,
        util/hash_fnv.[hc].
@@ -26399,9 +26399,99 @@ Apologies for any names omitted.
 20220421
 
        Bugfix (introduced: Postfix 3.7): reverted an overly complex
-       change in the postscreen SMTP engine from 20211023, that
-       was segfaulting on malformed input, where the Postfix 3.6
-       implementation worked properly. The purpose of the change
-       was to prevent complaints about "malformed UTF8" from Postfix
-       lookup tables. Replaced the change with a trivial guard.
-       File: postscreen/postscreen_smtpd.c.
+       change in the postscreen SMTP engine from 20211023, and
+       replaced it with a much simpler change. The bad change was
+       segfaulting on some systems after receiving malformed input
+       (for example, TLS "hello"). File: postscreen/postscreen_smtpd.c.
+
+       Under conditions described below, the postscreen program
+       attempted to read through an uninitialized 'const' pointer.
+       The pointer value depended on the compiler type and compiler
+       options, but crucially, it did not depend on network inputs.
+
+       The conditions were that SMTPUTF8 support was enabled (the
+       default), and that postscreen received non-UTF8 input, for
+       example, a TLS or RDP handshake request.
+
+       Depending on compiler details, the result of the read
+       operation could be uninteresting, a combined memory leak
+       and file handle leak, or a segmentation violation (signal
+       11).
+
+       The segmentation violation result was reported by Michael
+       Grimm who used a FreeBSD 13.1 early version. The result was
+       "uninteresting" with FreeBSD 13.0. Both FreeBSD systems use
+       Clang instead of GCC. The result was also "uninteresting"
+       on Linux-based systems that use GCC, or on a few older
+       systems that use GCC.
+
+20220427
+
+       Cleanup: incorrect error message after postscreen received
+       a STARTTLS command with too many arguments. File:
+       postscreen/postscreen_smtpd.c.
+
+20220429
+
+       Noise: shut up a useless warning. File: cleanup_map1n.c.
+
+       Documentation: IPv6 support, by Pau Amma. Files: proto/INSTALL,
+       proto/IPV6_README.html.
+
+20220501
+
+       Cleanup: merged the infrastructure that "knows" which tables
+       are created with "postmap" or "postalias", with infrastructure
+       that has other information about lookup tables. The old design
+       pre-dated dynamically-loaded table drivers, and was difficult
+       to maintain.
+
+       The following files were moved from the "global" directory to
+       the "util" directory: src/util/mkmap.h, src/util/mkmap_cdb.c,
+       src/util/mkmap_db.c, src/util/mkmap_dbm.c, src/util/mkmap_fail.c,
+       src/util/mkmap_lmdb.c, src/util/mkmap_open.c,
+       src/util/mkmap_sdbm.c.
+
+       The corresponding postfix-xxx.so shared objects are now created
+       by util/Makefile instead of global/Makefile. There is no change
+       in how these files are installed or deployed.
+
+       Other files affected by this change: src/util/dict_open.c,
+       src/global/dynamicmaps.c, src/global/mail_version.h,
+       src/global/header_body_checks.h, src/global/maps.c,
+       src/global/dict_proxy.h, src/util/dict.c, src/util/dict_dbm.h,
+       src/util/dict_fail.h, src/util/dict_db.h, src/util/dict_lmdb.h,
+       src/util/dict_cdb.h, src/util/dict_sdbm.h, src/util/dict.h,
+       src/global/mail_dict.c, src/postalias/postalias.c,
+       src/postmap/postmap.c.
+
+       Portability: variable declaration after code. File:
+       global/compat_level.c.
+
+20220504
+
+       Documentation: dymap_init() description. File:
+       global/dynamicmaps.c.
+
+20220506
+
+       Added an argv_uniq() function to deduplicate same-value
+       adjacent array elements. Added a ton of tests to validate
+       the argv implementation. File: util/argv.c.
+
+       Cleanup: the dict_mapnames() function (used in "postconf
+       -m") now deduplicates dictionary type names. File:
+       util/dict_open.c.
+
+20220507
+
+       Documentation: inverted the paragraph about "known" addresses,
+       in the descriptions of smtpd_reject_unlisted_sender and
+       smtpd_reject_unlisted_recipient. File: proto/postconf.proto.
+
+       Documentation: added the HISTORY file to the pre-release-checks.
+       Files: mantools/check-double-history, mantools/check-spell-history,
+       proto/stop.double-history, proto/stop.spell-history.
+
+       Documentation: added POSTLOG_SERVICE and POSTLOG_HOSTNAME
+       to the import_environment description. File: proto/postconf.proto.
index 4ab046d40d19d7f9084291859222833d7b3724ba..17a8cf74456b3b2477ba920f3d14440d524c7bea 100644 (file)
@@ -567,7 +567,7 @@ The following is an extensive list of names and values.
 ||                             |Do not build with IPv6 support. By default,  |
 ||                             |IPv6 support is compiled in on platforms that|
 ||                             |are known to have IPv6 support. Note: this   |
-||-DNO_IPV6                    |directive is for debugging And testing only. |
+||-DNO_IPV6                    |directive is for debugging and testing only. |
 ||                             |It is not guaranteed to work on all          |
 ||                             |platforms. If you don't want IPv6 support,   |
 ||                             |set "inet_protocols = ipv4" in main.cf.      |
index aa6c7ad9c72e03b82bfde4adda564fe95e926e3e..5bc7a7cb173a6e5e982b9e4fd669715f84971078 100644 (file)
@@ -116,7 +116,8 @@ manpages:
 
 # Some checks require a bin/postconf executable.
 pre-release-checks: typo-check missing-proxy-read-maps-check \
-       postlink-check postfix-files-check
+       postlink-check postfix-files-check check-spell-history \
+       check-double-history
 
 postfix-files-check:
        mantools/check-postfix-files | diff /dev/null -
@@ -148,6 +149,12 @@ double-install-proto-text:
 double-proto-html:
        mantools/check-double-proto-html | diff /dev/null -
 
+check-spell-history:
+       mantools/check-spell-history | diff /dev/null -
+
+check-double-history:
+       mantools/check-double-history | diff /dev/null -
+
 # The build-time shlib_directory setting must take precedence over
 # the installed main.cf settings, otherwise we can't update an
 # installed system from dynamicmaps=yes<->dynamicmaps=no or from
index e9d4f0695b451550e14fb38a8e18d90a604459c4..e97c95c2d93fe251bd679a464a1fcb4080a0e3ef 100644 (file)
@@ -567,7 +567,7 @@ The following is an extensive list of names and values.
 ||                              |Do not build with IPv6 support. By default,  |
 ||                              |IPv6 support is compiled in on platforms that|
 ||                              |are known to have IPv6 support. Note: this   |
-||-DNO_IPV6                     |directive is for debugging And testing only. |
+||-DNO_IPV6                     |directive is for debugging and testing only. |
 ||                              |It is not guaranteed to work on all          |
 ||                              |platforms. If you don't want IPv6 support,   |
 ||                              |set "inet_protocols = ipv4" in main.cf.      |
index a29560c472eec812d524eb26ee14a796269cf5ed..188003be807731bea0d44664a1e2d8861e9a7e7a 100644 (file)
@@ -43,7 +43,8 @@ Postfix version 2.2 supports IPv4 and IPv6 on the following platforms:
 
 On other platforms Postfix will simply use IPv4 as it has always done.
 
-See below for tips how to port Postfix IPv6 support to other environments.
+See "IPv6 Support for unsupported platforms" for tips to port Postfix IPv6
+support to other environments.
 
 C\bCo\bon\bnf\bfi\big\bgu\bur\bra\bat\bti\bio\bon\bn
 
@@ -83,6 +84,9 @@ configuration work with Postfix.
     Note 2: on older Linux and Solaris systems, the setting "inet_protocols =
     ipv6" will not prevent Postfix from accepting IPv4 connections.
 
+    For an unsupported test option to build Postfix without IPv6 support, see
+    the NO_IPV6 option in the INSTALL document.
+
   * The other new parameter is smtp_bind_address6. This sets the local
     interface address for outgoing IPv6 SMTP connections, just like the
     smtp_bind_address parameter does for IPv4:
index 84541eda0fcab691d184f2ca2b1425e7be367429..d49dbde13fd438bac1240035373d420e63e4e79a 100644 (file)
@@ -24,3 +24,11 @@ historical IBM Public License 1.0, it is now also distributed with the
 more recent Eclipse Public License 2.0. Recipients can choose to take
 the software under the license of their choice. Those who are more
 comfortable with the IPL can continue with that license.
+
+Incompatible changes with snapshot 20220507
+===========================================
+
+Most global/mkmap*.[hc] files have moved to the util directory;
+only global/mkmap_proxy.* remains. The old file organization was
+designed before support for dynamically-loadable databases was
+added, and the code suffered from complexity.
index 4dccddda9d9f5146d1e9116a56c1894998a60751..d0c3589c4f340ef22f38b4eb1626ba50016ab8ca 100644 (file)
@@ -9,13 +9,18 @@ Wish list:
        Scan Postfix code with github.com/googleprojectzero/weggli
        (depends on "rust").
 
+       Enforce var_line_limit in util/attr_scan*c.
+
        Can tests use LD_PRELOAD to inject fake modules such as
        fake_dns(3), fake_msg(3), fake_myaddrinfo(3) and so on?
        One limitation is that functions etc. in a preloaded object
        always take precedence, even in code that is not being
        tested.
 
-       '%l' support. ef7c661c-d86a-2366-6a73-ec8d51d75012@dev.snart.me
+       '%l' support, similar to %D in the Dovecot LDAP driver.
+       Subject: Feature request: '%l' expansion for ldap_table,
+       Date: Tue, 5 Apr 2022.  Message-ID:
+       <ef7c661c-d86a-2366-6a73-ec8d51d75012@dev.snart.me>
 
        WARN_IF_REJECT like prefix that disables the error counter increment.
 
index 2070e3467de43834d2fad67432bf197e42d7ef25..acf7b55722ff51283af480ac5f05989a4c65536e 100644 (file)
@@ -837,7 +837,7 @@ unreachable code. </td> </tr>
 <tr> <td> </td> <td> -DNO_IPV6 </td> <td> Do not build with IPv6
 support. By default, IPv6 support is compiled in on platforms that
 are known to have IPv6 support. Note: this directive is for debugging
-And testing only. It is not guaranteed to work on all platforms.
+and testing only. It is not guaranteed to work on all platforms.
 If you don't want IPv6 support, set "<a href="postconf.5.html#inet_protocols">inet_protocols</a> = ipv4" in
 <a href="postconf.5.html">main.cf</a>.
 </td> </tr>
index acf24b9014cfa744dada1bdef4d0ff793193cd56..0b6b79359a345b8214b67518169bf3b504810f2b 100644 (file)
@@ -78,8 +78,8 @@ platforms:  </p>
 <p> On other platforms Postfix will simply use IPv4 as it has always
 done. </p>
 
-<p> See <a href="#porting">below</a> for tips how to port Postfix
-IPv6 support to other environments.  </p>
+<p> See "<a href="#porting">IPv6 Support for unsupported platforms</a>"
+for tips to port Postfix IPv6 support to other environments.  </p>
 
 <h2><a name="configuration">Configuration</a></h2>
 
@@ -128,6 +128,9 @@ on a software distribution with IPv6 support, "ipv4" otherwise. </p>
 "<a href="postconf.5.html#inet_protocols">inet_protocols</a> = ipv6" will not prevent Postfix from
 accepting IPv4 connections. </p>
 
+<p> For an unsupported test option to build Postfix without IPv6
+support, see the NO_IPV6 option in the <a href="INSTALL.html">INSTALL</a> document. </p>
+
 <li> <p> The other new parameter is <a href="postconf.5.html#smtp_bind_address6">smtp_bind_address6</a>.
 This sets the local interface address for outgoing IPv6 SMTP
 connections, just like the <a href="postconf.5.html#smtp_bind_address">smtp_bind_address</a> parameter
index 837a5d38a2f01c9e3a33c3c744951001f6d41712..acfea50b1cc25fce98bbd2a136dbabd574b79f59 100644 (file)
@@ -4047,6 +4047,16 @@ environment.  Examples of relevant environment variables: </p>
 
 <dd>Needed to make "<b>postfix -c</b>" work. </dd>
 
+<dt><b>POSTLOG_SERVICE</b></dt>
+
+<dd>Needed to make "<b><a href="postconf.5.html#maillog_file">maillog_file</a></b>" work during daemon
+process initialization. </dd>
+
+<dt><b>POSTLOG_HOSTNAME</b></dt>
+
+<dd>Needed to make "<b><a href="postconf.5.html#maillog_file">maillog_file</a></b>" work during daemon
+process initialization. </dd>
+
 </dl>
 
 <p> Specify a list of names and/or name=value pairs, separated by
@@ -16602,8 +16612,9 @@ access restriction is specified. This prevents the Postfix queue
 from filling up with undeliverable MAILER-DAEMON messages.
 </p>
 
-<p> An address is always considered "known" when it matches a
-<a href="virtual.5.html">virtual(5)</a> alias or a <a href="canonical.5.html">canonical(5)</a> mapping.
+<p> An address is considered "unknown" when it does not match a
+<a href="virtual.5.html">virtual(5)</a> alias or a <a href="canonical.5.html">canonical(5)</a> mapping, and one of the following
+conditions holds: </p>
 
 <ul>
 
@@ -16639,8 +16650,9 @@ sender addresses, even when no explicit <a href="postconf.5.html#reject_unlisted
 access restriction is specified. This can slow down an explosion
 of forged mail from worms or viruses.  </p>
 
-<p> An address is always considered "known" when it matches a
-<a href="virtual.5.html">virtual(5)</a> alias or a <a href="canonical.5.html">canonical(5)</a> mapping.
+<p> An address is considered "unknown" when it does not match a
+<a href="virtual.5.html">virtual(5)</a> alias or a <a href="canonical.5.html">canonical(5)</a> mapping, and one of the following
+conditions holds: </p>
 
 <ul>
 
index 4ad946652bc2a7be3e24443a8a98b0c8c9387800..10d2e67d30ab264215ecf68a3bdffd6548d36d65 100644 (file)
@@ -2561,6 +2561,14 @@ Needed for debugging Postfix daemons with an X\-windows debugger.
 .IP "\fBMAIL_CONFIG\fR"
 Needed to make "\fBpostfix \-c\fR" work.
 .br
+.IP "\fBPOSTLOG_SERVICE\fR"
+Needed to make "\fBmaillog_file\fR" work during daemon
+process initialization.
+.br
+.IP "\fBPOSTLOG_HOSTNAME\fR"
+Needed to make "\fBmaillog_file\fR" work during daemon
+process initialization.
+.br
 .br
 .PP
 Specify a list of names and/or name=value pairs, separated by
@@ -11482,8 +11490,9 @@ recipient addresses, even when no explicit reject_unlisted_recipient
 access restriction is specified. This prevents the Postfix queue
 from filling up with undeliverable MAILER\-DAEMON messages.
 .PP
-An address is always considered "known" when it matches a
-\fBvirtual\fR(5) alias or a \fBcanonical\fR(5) mapping.
+An address is considered "unknown" when it does not match a
+\fBvirtual\fR(5) alias or a \fBcanonical\fR(5) mapping, and one of the following
+conditions holds:
 .IP \(bu
 The recipient domain matches $mydestination, $inet_interfaces
 or $proxy_interfaces, but the recipient is not listed in
@@ -11508,8 +11517,9 @@ sender addresses, even when no explicit reject_unlisted_sender
 access restriction is specified. This can slow down an explosion
 of forged mail from worms or viruses.
 .PP
-An address is always considered "known" when it matches a
-\fBvirtual\fR(5) alias or a \fBcanonical\fR(5) mapping.
+An address is considered "unknown" when it does not match a
+\fBvirtual\fR(5) alias or a \fBcanonical\fR(5) mapping, and one of the following
+conditions holds:
 .IP \(bu
 The sender domain matches $mydestination, $inet_interfaces or
 $proxy_interfaces, but the sender is not listed in
diff --git a/postfix/mantools/check-double-history b/postfix/mantools/check-double-history
new file mode 100755 (executable)
index 0000000..26e85c0
--- /dev/null
@@ -0,0 +1,7 @@
+#!/bin/sh
+
+# Finds double words the HISTORY file, starting with 2022. 
+
+LANG=C; export LANG
+
+sed '1,/^2022/d' HISTORY | mantools/find-double | fgrep -vxf proto/stop.double-history
diff --git a/postfix/mantools/check-spell-history b/postfix/mantools/check-spell-history
new file mode 100755 (executable)
index 0000000..242130c
--- /dev/null
@@ -0,0 +1,9 @@
+#!/bin/sh
+
+# Spellchecks text in the HISTORY file, starting with 2022.
+
+LANG=C; export LANG
+
+sed '1,/^2022/d' HISTORY | spell | fgrep -vxf proto/stop | \
+       fgrep -vxf proto/stop.spell-cc | \
+       fgrep -vxf proto/stop.spell-history
index 71bcc4ffbe553b72756711b7510f56df5a42979f..756012ede6d0e2a6f5bda783e6b83ebb431567c4 100644 (file)
@@ -837,7 +837,7 @@ unreachable code. </td> </tr>
 <tr> <td> </td> <td> -DNO_IPV6 </td> <td> Do not build with IPv6
 support. By default, IPv6 support is compiled in on platforms that
 are known to have IPv6 support. Note: this directive is for debugging
-And testing only. It is not guaranteed to work on all platforms.
+and testing only. It is not guaranteed to work on all platforms.
 If you don't want IPv6 support, set "inet_protocols = ipv4" in
 main.cf.
 </td> </tr>
index 01ea51baeeb2d8112e617927cfd3e5c739117905..f4cebda6967f75fc124e3a2d0d5f51cfd7f13a52 100644 (file)
@@ -78,8 +78,8 @@ platforms:  </p>
 <p> On other platforms Postfix will simply use IPv4 as it has always
 done. </p>
 
-<p> See <a href="#porting">below</a> for tips how to port Postfix
-IPv6 support to other environments.  </p>
+<p> See "<a href="#porting">IPv6 Support for unsupported platforms</a>"
+for tips to port Postfix IPv6 support to other environments.  </p>
 
 <h2><a name="configuration">Configuration</a></h2>
 
@@ -128,6 +128,9 @@ inet_protocols configuration parameter. </p>
 "inet_protocols = ipv6" will not prevent Postfix from
 accepting IPv4 connections. </p>
 
+<p> For an unsupported test option to build Postfix without IPv6
+support, see the NO_IPV6 option in the INSTALL document. </p>
+
 <li> <p> The other new parameter is smtp_bind_address6.
 This sets the local interface address for outgoing IPv6 SMTP
 connections, just like the smtp_bind_address parameter
index 7dfb60548e03f7229185f79ade9006b7b00241c4..28ff0965a7ac131386abdb5a546ee71c32abbb8f 100644 (file)
@@ -1957,6 +1957,16 @@ environment.  Examples of relevant environment variables: </p>
 
 <dd>Needed to make "<b>postfix -c</b>" work. </dd>
 
+<dt><b>POSTLOG_SERVICE</b></dt>
+
+<dd>Needed to make "<b>maillog_file</b>" work during daemon 
+process initialization. </dd>
+
+<dt><b>POSTLOG_HOSTNAME</b></dt>
+
+<dd>Needed to make "<b>maillog_file</b>" work during daemon  
+process initialization. </dd>
+
 </dl>
 
 <p> Specify a list of names and/or name=value pairs, separated by
@@ -8740,8 +8750,9 @@ access restriction is specified. This prevents the Postfix queue
 from filling up with undeliverable MAILER-DAEMON messages.
 </p>
 
-<p> An address is always considered "known" when it matches a
-virtual(5) alias or a canonical(5) mapping.
+<p> An address is considered "unknown" when it does not match a
+virtual(5) alias or a canonical(5) mapping, and one of the following
+conditions holds: </p>
 
 <ul>
 
@@ -8773,8 +8784,9 @@ sender addresses, even when no explicit reject_unlisted_sender
 access restriction is specified. This can slow down an explosion
 of forged mail from worms or viruses.  </p>
 
-<p> An address is always considered "known" when it matches a
-virtual(5) alias or a canonical(5) mapping.
+<p> An address is considered "unknown" when it does not match a 
+virtual(5) alias or a canonical(5) mapping, and one of the following
+conditions holds: </p>
 
 <ul>
 
index 6bdd97f3a3f909c105fe356d0ccfdd0ffd3535df..ceddb7f5cddcd2d150e498b3ae0195221b4ab145 100644 (file)
@@ -329,3 +329,4 @@ XXX  XXX
  int compar DNS_RR DNS_RR 
 USE_FNV_32BIT  USE_FNV_32BIT 
 void  void cleanup_milter_receive state count 
+ struct DICT open const char int int dict_xx_open 
diff --git a/postfix/proto/stop.double-history b/postfix/proto/stop.double-history
new file mode 100644 (file)
index 0000000..f143392
--- /dev/null
@@ -0,0 +1,10 @@
+ message from the postqueue command File postqueue postqueue c 
+ or kernel bug emits a weird error File postqueue postqueue c 
+ Dukhovni File auxiliary collate collate pl 
+ sanitization File showq showq c 
+ with setgid permissions File postlogd postlogd c 
+ cleanup server enters the chroot jail Files cleanup cleanup h 
+ global maps c global maps h smtp smtp c 
+ cleanup cleanup h cleanup cleanup_init c 
+ src global mail_dict c src postalias postalias c 
+ src postmap postmap c 
index 10f22509a1acf153568a74ec9e7ab25582f12df3..ea6ad0038b188d009608bae4524a7a99c2d560be 100644 (file)
@@ -1784,3 +1784,5 @@ stdint
 Noll
 deinit
 reinit
+COMPAR
+deduplicate
diff --git a/postfix/proto/stop.spell-history b/postfix/proto/stop.spell-history
new file mode 100644 (file)
index 0000000..16c43bf
--- /dev/null
@@ -0,0 +1,21 @@
+AppArmor
+Bugfix
+Degenkolb
+Dybdal
+Jaroslav
+Kimura
+Kitterman
+Klanderman
+Pelletier
+RDP
+Raf
+Skarvada
+Velasco
+WISHLIST
+Yasuhiro
+deduplicates
+hmtl
+libs
+segfaulting
+srctoman
+systemd
index 9cecfcb599a0abb5b658b0c530a3e5de17362c84..2c8413b65d2a46823913bc54bebce1030896a388 100644 (file)
@@ -101,7 +101,7 @@ ARGV   *cleanup_map1n_internal(CLEANUP_STATE *state, const char *addr,
      * pointer.
      */
 #define UPDATE(ptr,new)        do { \
-       if (ptr) myfree(ptr); ptr = mystrdup(new); \
+       if (ptr) { myfree(ptr); } ptr = mystrdup(new); \
     } while (0)
 #define STR    vstring_str
 #define RETURN(x) do { \
index 0944a75a9f3d7bccb3cda0a4e98c96e62ef1f472..86390ede24c3b8c65352a853e61e51386bd5526d 100644 (file)
@@ -16,8 +16,7 @@ SRCS  = abounce.c anvil_clnt.c been_here.c bounce.c bounce_log.c \
        mail_params.c mail_pathname.c mail_queue.c mail_run.c \
        mail_scan_dir.c mail_stream.c mail_task.c mail_trigger.c maps.c \
        mark_corrupt.c match_parent_style.c mbox_conf.c mbox_open.c \
-       mime_state.c mkmap_cdb.c mkmap_db.c mkmap_dbm.c mkmap_lmdb.c mkmap_open.c \
-       mkmap_sdbm.c msg_stats_print.c msg_stats_scan.c mynetworks.c \
+       mime_state.c msg_stats_print.c msg_stats_scan.c mynetworks.c \
        mypwd.c namadr_list.c off_cvt.c opened.c own_inet_addr.c \
        pipe_command.c post_mail.c quote_821_local.c quote_822_local.c \
        rcpt_buf.c rcpt_print.c rec_attr_map.c rec_streamlf.c rec_type.c \
@@ -32,7 +31,7 @@ SRCS  = abounce.c anvil_clnt.c been_here.c bounce.c bounce_log.c \
        match_service.c mail_conf_nint.c addr_match_list.c mail_conf_nbool.c \
        smtp_reply_footer.c safe_ultostr.c verify_sender_addr.c \
        dict_memcache.c mail_version.c memcache_proto.c server_acl.c \
-       mkmap_fail.c haproxy_srvr.c dsn_filter.c dynamicmaps.c uxtext.c \
+       haproxy_srvr.c dsn_filter.c dynamicmaps.c uxtext.c \
        smtputf8.c mail_conf_over.c mail_parm_split.c midna_adomain.c \
        mail_addr_form.c quote_flags.c maillog_client.c \
        normalize_mailhost_addr.c map_search.c reject_deliver_request.c \
@@ -56,8 +55,7 @@ OBJS  = abounce.o anvil_clnt.o been_here.o bounce.o bounce_log.o \
        mail_params.o mail_pathname.o mail_queue.o mail_run.o \
        mail_scan_dir.o mail_stream.o mail_task.o mail_trigger.o maps.o \
        mark_corrupt.o match_parent_style.o mbox_conf.o mbox_open.o \
-       mime_state.o mkmap_db.o mkmap_dbm.o mkmap_open.o \
-       msg_stats_print.o msg_stats_scan.o mynetworks.o \
+       mime_state.o msg_stats_print.o msg_stats_scan.o mynetworks.o \
        mypwd.o namadr_list.o off_cvt.o opened.o own_inet_addr.o \
        pipe_command.o post_mail.o quote_821_local.o quote_822_local.o \
        rcpt_buf.o rcpt_print.o rec_attr_map.o rec_streamlf.o rec_type.o \
@@ -72,7 +70,7 @@ OBJS  = abounce.o anvil_clnt.o been_here.o bounce.o bounce_log.o \
        match_service.o mail_conf_nint.o addr_match_list.o mail_conf_nbool.o \
        smtp_reply_footer.o safe_ultostr.o verify_sender_addr.o \
        dict_memcache.o mail_version.o memcache_proto.o server_acl.o \
-       mkmap_fail.o haproxy_srvr.o dsn_filter.o dynamicmaps.o uxtext.o \
+       haproxy_srvr.o dsn_filter.o dynamicmaps.o uxtext.o \
        smtputf8.o attr_override.o mail_parm_split.o midna_adomain.o \
        $(NON_PLUGIN_MAP_OBJ) mail_addr_form.o quote_flags.o maillog_client.o \
        normalize_mailhost_addr.o map_search.o reject_deliver_request.o \
@@ -82,8 +80,8 @@ OBJS  = abounce.o anvil_clnt.o been_here.o bounce.o bounce_log.o \
 # MAP_OBJ is for maps that may be dynamically loaded with dynamicmaps.cf.
 # When hard-linking these maps, makedefs sets NON_PLUGIN_MAP_OBJ=$(MAP_OBJ),
 # otherwise it sets the PLUGIN_* macros.
-MAP_OBJ = dict_ldap.o dict_mysql.o dict_pgsql.o dict_sqlite.o mkmap_cdb.o \
-       mkmap_lmdb.o mkmap_sdbm.o 
+MAP_OBJ = dict_ldap.o dict_mysql.o dict_pgsql.o dict_sqlite.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 \
@@ -98,7 +96,7 @@ HDRS  = abounce.h anvil_clnt.h been_here.h bounce.h bounce_log.h \
        mail_open_ok.h mail_params.h mail_proto.h mail_queue.h mail_run.h \
        mail_scan_dir.h mail_stream.h mail_task.h mail_version.h maps.h \
        mark_corrupt.h match_parent_style.h mbox_conf.h mbox_open.h \
-       mime_state.h mkmap.h msg_stats.h mynetworks.h mypwd.h namadr_list.h \
+       mime_state.h msg_stats.h mynetworks.h mypwd.h namadr_list.h \
        off_cvt.h opened.h own_inet_addr.h pipe_command.h post_mail.h \
        qmgr_user.h qmqp_proto.h quote_821_local.h quote_822_local.h \
        quote_flags.h rcpt_buf.h rcpt_print.h rec_attr_map.h rec_streamlf.h \
@@ -138,9 +136,7 @@ LIBS        = ../../lib/lib$(LIB_PREFIX)util$(LIB_SUFFIX)
 LIB_DIR        = ../../lib
 INC_DIR        = ../../include
 PLUGIN_MAP_SO = $(LIB_PREFIX)ldap$(LIB_SUFFIX) $(LIB_PREFIX)mysql$(LIB_SUFFIX) \
-       $(LIB_PREFIX)pgsql$(LIB_SUFFIX) $(LIB_PREFIX)sqlite$(LIB_SUFFIX) \
-       $(LIB_PREFIX)lmdb$(LIB_SUFFIX) $(LIB_PREFIX)cdb$(LIB_SUFFIX) \
-       $(LIB_PREFIX)sdbm$(LIB_SUFFIX)
+       $(LIB_PREFIX)pgsql$(LIB_SUFFIX) $(LIB_PREFIX)sqlite$(LIB_SUFFIX)
 MAKES  =
 
 .c.o:; $(CC) $(SHLIB_CFLAGS) $(CFLAGS) -c $*.c
@@ -177,19 +173,6 @@ $(LIB_PREFIX)pgsql$(LIB_SUFFIX): dict_pgsql.o
 $(LIB_PREFIX)sqlite$(LIB_SUFFIX): dict_sqlite.o
        $(PLUGIN_LD) $(SHLIB_RPATH) -o $@ dict_sqlite.o $(AUXLIBS_SQLITE)
 
-$(LIB_PREFIX)cdb$(LIB_SUFFIX): mkmap_cdb.o $(LIB_DIR)/dict_cdb.o
-       $(PLUGIN_LD) $(SHLIB_RPATH) -o $@ mkmap_cdb.o \
-           $(LIB_DIR)/dict_cdb.o $(AUXLIBS_CDB)
-
-$(LIB_PREFIX)lmdb$(LIB_SUFFIX): mkmap_lmdb.o $(LIB_DIR)/dict_lmdb.o \
-           $(LIB_DIR)/slmdb.o
-       $(PLUGIN_LD) $(SHLIB_RPATH) -o $@ mkmap_lmdb.o $(LIB_DIR)/dict_lmdb.o \
-           $(LIB_DIR)/slmdb.o $(AUXLIBS_LMDB)
-
-$(LIB_PREFIX)sdbm$(LIB_SUFFIX): mkmap_sdbm.o $(LIB_DIR)/dict_sdbm.o
-       $(PLUGIN_LD) $(SHLIB_RPATH) -o $@ mkmap_sdbm.o \
-           $(LIB_DIR)/dict_sdbm.o $(AUXLIBS_SDBM)
-
 update: $(LIB_DIR)/$(LIB) $(HDRS) $(PLUGIN_MAP_SO_UPDATE)
        -for i in $(HDRS); \
        do \
@@ -1024,6 +1007,7 @@ data_redirect.o: ../../include/dict_cdb.h
 data_redirect.o: ../../include/dict_db.h
 data_redirect.o: ../../include/dict_dbm.h
 data_redirect.o: ../../include/dict_lmdb.h
+data_redirect.o: ../../include/mkmap.h
 data_redirect.o: ../../include/msg.h
 data_redirect.o: ../../include/myflock.h
 data_redirect.o: ../../include/name_code.h
@@ -1273,6 +1257,7 @@ dict_proxy.o: ../../include/check_arg.h
 dict_proxy.o: ../../include/dict.h
 dict_proxy.o: ../../include/htable.h
 dict_proxy.o: ../../include/iostuff.h
+dict_proxy.o: ../../include/mkmap.h
 dict_proxy.o: ../../include/msg.h
 dict_proxy.o: ../../include/myflock.h
 dict_proxy.o: ../../include/mymalloc.h
@@ -1413,6 +1398,7 @@ dynamicmaps.o: ../../include/check_arg.h
 dynamicmaps.o: ../../include/dict.h
 dynamicmaps.o: ../../include/htable.h
 dynamicmaps.o: ../../include/load_lib.h
+dynamicmaps.o: ../../include/mkmap.h
 dynamicmaps.o: ../../include/msg.h
 dynamicmaps.o: ../../include/myflock.h
 dynamicmaps.o: ../../include/mymalloc.h
@@ -1426,7 +1412,6 @@ dynamicmaps.o: ../../include/vstring.h
 dynamicmaps.o: ../../include/vstring_vstream.h
 dynamicmaps.o: dynamicmaps.c
 dynamicmaps.o: dynamicmaps.h
-dynamicmaps.o: mkmap.h
 ehlo_mask.o: ../../include/check_arg.h
 ehlo_mask.o: ../../include/name_mask.h
 ehlo_mask.o: ../../include/sys_defs.h
@@ -1865,6 +1850,7 @@ mail_date.o: mail_date.h
 mail_dict.o: ../../include/argv.h
 mail_dict.o: ../../include/check_arg.h
 mail_dict.o: ../../include/dict.h
+mail_dict.o: ../../include/mkmap.h
 mail_dict.o: ../../include/msg.h
 mail_dict.o: ../../include/myflock.h
 mail_dict.o: ../../include/mymalloc.h
@@ -1926,6 +1912,7 @@ mail_params.o: ../../include/inet_addr_list.h
 mail_params.o: ../../include/inet_proto.h
 mail_params.o: ../../include/iostuff.h
 mail_params.o: ../../include/midna_domain.h
+mail_params.o: ../../include/mkmap.h
 mail_params.o: ../../include/msg.h
 mail_params.o: ../../include/msg_syslog.h
 mail_params.o: ../../include/myaddrinfo.h
@@ -1941,8 +1928,8 @@ mail_params.o: ../../include/vbuf.h
 mail_params.o: ../../include/vstream.h
 mail_params.o: ../../include/vstring.h
 mail_params.o: ../../include/vstring_vstream.h
-mail_params.o: config_known_tcp_ports.h
 mail_params.o: compat_level.h
+mail_params.o: config_known_tcp_ports.h
 mail_params.o: mail_conf.h
 mail_params.o: mail_params.c
 mail_params.o: mail_params.h
@@ -2212,102 +2199,10 @@ mime_state.o: mail_params.h
 mime_state.o: mime_state.c
 mime_state.o: mime_state.h
 mime_state.o: rec_type.h
-mkmap_cdb.o: ../../include/argv.h
-mkmap_cdb.o: ../../include/check_arg.h
-mkmap_cdb.o: ../../include/dict.h
-mkmap_cdb.o: ../../include/dict_cdb.h
-mkmap_cdb.o: ../../include/myflock.h
-mkmap_cdb.o: ../../include/mymalloc.h
-mkmap_cdb.o: ../../include/sys_defs.h
-mkmap_cdb.o: ../../include/vbuf.h
-mkmap_cdb.o: ../../include/vstream.h
-mkmap_cdb.o: ../../include/vstring.h
-mkmap_cdb.o: mkmap.h
-mkmap_cdb.o: mkmap_cdb.c
-mkmap_db.o: ../../include/argv.h
-mkmap_db.o: ../../include/check_arg.h
-mkmap_db.o: ../../include/dict.h
-mkmap_db.o: ../../include/dict_db.h
-mkmap_db.o: ../../include/msg.h
-mkmap_db.o: ../../include/myflock.h
-mkmap_db.o: ../../include/mymalloc.h
-mkmap_db.o: ../../include/stringops.h
-mkmap_db.o: ../../include/sys_defs.h
-mkmap_db.o: ../../include/vbuf.h
-mkmap_db.o: ../../include/vstream.h
-mkmap_db.o: ../../include/vstring.h
-mkmap_db.o: ../../include/warn_stat.h
-mkmap_db.o: mail_params.h
-mkmap_db.o: mkmap.h
-mkmap_db.o: mkmap_db.c
-mkmap_dbm.o: ../../include/argv.h
-mkmap_dbm.o: ../../include/check_arg.h
-mkmap_dbm.o: ../../include/dict.h
-mkmap_dbm.o: ../../include/dict_dbm.h
-mkmap_dbm.o: ../../include/msg.h
-mkmap_dbm.o: ../../include/myflock.h
-mkmap_dbm.o: ../../include/mymalloc.h
-mkmap_dbm.o: ../../include/stringops.h
-mkmap_dbm.o: ../../include/sys_defs.h
-mkmap_dbm.o: ../../include/vbuf.h
-mkmap_dbm.o: ../../include/vstream.h
-mkmap_dbm.o: ../../include/vstring.h
-mkmap_dbm.o: mkmap.h
-mkmap_dbm.o: mkmap_dbm.c
-mkmap_fail.o: ../../include/argv.h
-mkmap_fail.o: ../../include/check_arg.h
-mkmap_fail.o: ../../include/dict.h
-mkmap_fail.o: ../../include/dict_fail.h
-mkmap_fail.o: ../../include/myflock.h
-mkmap_fail.o: ../../include/mymalloc.h
-mkmap_fail.o: ../../include/sys_defs.h
-mkmap_fail.o: ../../include/vbuf.h
-mkmap_fail.o: ../../include/vstream.h
-mkmap_fail.o: ../../include/vstring.h
-mkmap_fail.o: mkmap.h
-mkmap_fail.o: mkmap_fail.c
-mkmap_lmdb.o: ../../include/argv.h
-mkmap_lmdb.o: ../../include/check_arg.h
-mkmap_lmdb.o: ../../include/dict.h
-mkmap_lmdb.o: ../../include/dict_lmdb.h
-mkmap_lmdb.o: ../../include/msg.h
-mkmap_lmdb.o: ../../include/myflock.h
-mkmap_lmdb.o: ../../include/mymalloc.h
-mkmap_lmdb.o: ../../include/stringops.h
-mkmap_lmdb.o: ../../include/sys_defs.h
-mkmap_lmdb.o: ../../include/vbuf.h
-mkmap_lmdb.o: ../../include/vstream.h
-mkmap_lmdb.o: ../../include/vstring.h
-mkmap_lmdb.o: ../../include/warn_stat.h
-mkmap_lmdb.o: mail_conf.h
-mkmap_lmdb.o: mail_params.h
-mkmap_lmdb.o: mkmap.h
-mkmap_lmdb.o: mkmap_lmdb.c
-mkmap_open.o: ../../include/argv.h
-mkmap_open.o: ../../include/check_arg.h
-mkmap_open.o: ../../include/dict.h
-mkmap_open.o: ../../include/dict_cdb.h
-mkmap_open.o: ../../include/dict_db.h
-mkmap_open.o: ../../include/dict_dbm.h
-mkmap_open.o: ../../include/dict_fail.h
-mkmap_open.o: ../../include/dict_lmdb.h
-mkmap_open.o: ../../include/dict_sdbm.h
-mkmap_open.o: ../../include/htable.h
-mkmap_open.o: ../../include/msg.h
-mkmap_open.o: ../../include/myflock.h
-mkmap_open.o: ../../include/mymalloc.h
-mkmap_open.o: ../../include/sigdelay.h
-mkmap_open.o: ../../include/stringops.h
-mkmap_open.o: ../../include/sys_defs.h
-mkmap_open.o: ../../include/vbuf.h
-mkmap_open.o: ../../include/vstream.h
-mkmap_open.o: ../../include/vstring.h
-mkmap_open.o: dict_proxy.h
-mkmap_open.o: mkmap.h
-mkmap_open.o: mkmap_open.c
 mkmap_proxy.o: ../../include/argv.h
 mkmap_proxy.o: ../../include/check_arg.h
 mkmap_proxy.o: ../../include/dict.h
+mkmap_proxy.o: ../../include/mkmap.h
 mkmap_proxy.o: ../../include/myflock.h
 mkmap_proxy.o: ../../include/mymalloc.h
 mkmap_proxy.o: ../../include/sys_defs.h
@@ -2315,22 +2210,7 @@ mkmap_proxy.o: ../../include/vbuf.h
 mkmap_proxy.o: ../../include/vstream.h
 mkmap_proxy.o: ../../include/vstring.h
 mkmap_proxy.o: dict_proxy.h
-mkmap_proxy.o: mkmap.h
 mkmap_proxy.o: mkmap_proxy.c
-mkmap_sdbm.o: ../../include/argv.h
-mkmap_sdbm.o: ../../include/check_arg.h
-mkmap_sdbm.o: ../../include/dict.h
-mkmap_sdbm.o: ../../include/dict_sdbm.h
-mkmap_sdbm.o: ../../include/msg.h
-mkmap_sdbm.o: ../../include/myflock.h
-mkmap_sdbm.o: ../../include/mymalloc.h
-mkmap_sdbm.o: ../../include/stringops.h
-mkmap_sdbm.o: ../../include/sys_defs.h
-mkmap_sdbm.o: ../../include/vbuf.h
-mkmap_sdbm.o: ../../include/vstream.h
-mkmap_sdbm.o: ../../include/vstring.h
-mkmap_sdbm.o: mkmap.h
-mkmap_sdbm.o: mkmap_sdbm.c
 msg_stats_print.o: ../../include/attr.h
 msg_stats_print.o: ../../include/check_arg.h
 msg_stats_print.o: ../../include/htable.h
index 74308787c0f581a9deb676ee8dcebd948d2d8f59..af1cbbfcf7131915f00edcf349b65a3c6d7ec33c 100644 (file)
@@ -266,7 +266,7 @@ static MAC_EXP_OP_RES compat_relop_eval(const char *left_str, int relop,
                                                const char *rite_str)
 {
     const char myname[] = "compat_relop_eval";
-    long    left_val, rite_val;
+    long    left_val, rite_val, delta;
 
     /*
      * Negative result means error.
@@ -279,7 +279,7 @@ static MAC_EXP_OP_RES compat_relop_eval(const char *left_str, int relop,
      * Valid result. The difference between non-negative numbers will no
      * overflow.
      */
-    long    delta = left_val - rite_val;
+    delta = left_val - rite_val;
 
     switch (relop) {
     case MAC_EXP_OP_TOK_EQ:
index 076e887e294c32ae5bf36a24cfc67ad4f8915024..80f2a076565c4476a4fdeb09f58d00b63c735dbb 100644 (file)
@@ -27,8 +27,6 @@ extern const char *compat_level_to_string(long,
 #define compat_level_from_major_minor(major, minor, msg_fn) \
        compat_level_from_numbers((major), (minor), 0, (msg_fn))
 
-#
-
 /* LICENSE
 /* .ad
 /* .fi
index a5b79243a1f3e4527fc84a441a00279cabed23ca..67954f59568f50998c8e1e381f78a897b044cd51 100644 (file)
@@ -15,6 +15,7 @@
   * Utility library.
   */
 #include <dict.h>
+#include <mkmap.h>
 
  /*
   * External interface.
@@ -22,6 +23,7 @@
 #define DICT_TYPE_PROXY        "proxy"
 
 extern DICT *dict_proxy_open(const char *, int, int);
+extern MKMAP *mkmap_proxy_open(const char *);
 
  /*
   * Protocol interface.
@@ -48,6 +50,11 @@ extern DICT *dict_proxy_open(const char *, int, int);
 /*     IBM T.J. Watson Research
 /*     P.O. Box 704
 /*     Yorktown Heights, NY 10598, USA
+/*
+/*     Wietse Venema
+/*     Google, Inc.
+/*     111 8th Avenue
+/*     New York, NY 10011, USA
 /*--*/
 
 #endif
index f0213d39d8dbd4bbdf664829db0b4ae541970032..0b66ab9f8d7d343d2297c4db771fd153214f06ae 100644 (file)
@@ -8,23 +8,26 @@
 /*
 /*     void dymap_init(const char *conf_path, const char *plugin_dir)
 /* DESCRIPTION
-/*     This module reads the dynamicmaps.cf file and performs
-/*     run-time loading of Postfix dictionaries. Each dynamicmaps.cf
-/*     entry specifies the name of a dictionary type, the pathname
-/*     of a shared-library object, the name of a "dict_open"
-/*     function for access to individual dictionary entries, and
-/*     optionally the name of a "mkmap_open" function for bulk-mode
+/*     This module reads the dynamicmaps.cf file and on-demand
+/*     loads Postfix dictionaries. Each dynamicmaps.cf entry
+/*     specifies the name of a dictionary type, the pathname of a
+/*     shared-library object, the name of a "dict_open" function
+/*     for access to individual dictionary entries, and optionally
+/*     the name of a "mkmap_open" wrapper function for bulk-mode
 /*     dictionary creation. Plugins may be specified with a relative
 /*     pathname.
 /*
-/*     A dictionary may be installed without editing the file
-/*     dynamicmaps.cf, by placing a configuration file under the
-/*     directory dynamicmaps.cf.d, with the same format as
-/*     dynamicmaps.cf.
+/*     A dictionary shared object may be installed on a system
+/*     without editing the file dynamicmaps.cf, by placing a
+/*     configuration file under the directory dynamicmaps.cf.d,
+/*     with the same format as dynamicmaps.cf.
 /*
 /*     dymap_init() reads the specified configuration file which
-/*     is in dynamicmaps.cf format, and hooks itself into the
-/*     dict_open(), dict_mapnames(), and mkmap_open() functions.
+/*     must be in dynamicmaps.cf format, appends ".d" to the path
+/*     and scans the named directory for other configuration files,
+/*     and on the first call hooks itself into the dict_open() and
+/*     dict_mapnames() functions. All files are optional, but if
+/*     an existing file cannot be opened, that is a fatal error.
 /*
 /*     dymap_init() may be called multiple times during a process
 /*     lifetime, but it will not "unload" dictionaries that have
 /*
 /*     Arguments:
 /* .IP conf_path
-/*     Pathname for the dynamicmaps configuration file.
+/*     Pathname for the dynamicmaps configuration file. With ".d"
+/*     appended,  this becomes the pathname for a directory with
+/*     other files in dynamicmaps.cf format.
 /* .IP plugin_dir
 /*     Default directory for plugins with a relative pathname.
 /* SEE ALSO
-/*     load_lib(3) low-level run-time linker adapter
+/*     load_lib(3) low-level run-time linker adapter.
 /* DIAGNOSTICS
-/*     Fatal errors: memory allocation problem, dictionary or
-/*     dictionary function not available.  Panic: invalid use.
+/*     Warnings: unsupported dictionary type, shared object file
+/*     does not exist, shared object permissions are not safe-for-root,
+/*     configuration file permissions are not safe-for-root.
+/*     Fatal errors: memory allocation problem, error opening an
+/*     existing configuration file, bad configuration file syntax.
 /* LICENSE
 /* .ad
 /* .fi
 /*     IBM T.J. Watson Research
 /*     P.O. Box 704
 /*     Yorktown Heights, NY 10598, USA
+/*
+/*     Wietse Venema
+/*     Google, Inc.
+/*     111 8th Avenue
+/*     New York, NY 10011, USA
 /*--*/
 
  /*
@@ -75,6 +88,7 @@
 #include <htable.h>
 #include <argv.h>
 #include <dict.h>
+#include <mkmap.h>
 #include <load_lib.h>
 #include <vstring.h>
 #include <vstream.h>
  /*
   * Global library.
   */
-#include <mkmap.h>
 #include <dynamicmaps.h>
 
 #ifdef USE_DYNAMIC_MAPS
@@ -103,34 +116,43 @@ typedef struct {
 static HTABLE *dymap_info;
 static int dymap_hooks_done = 0;
 static DICT_OPEN_EXTEND_FN saved_dict_open_hook = 0;
-static MKMAP_OPEN_EXTEND_FN saved_mkmap_open_hook = 0;
 static DICT_MAPNAMES_EXTEND_FN saved_dict_mapnames_hook = 0;
 
 #define STREQ(x, y) (strcmp((x), (y)) == 0)
 
-/* dymap_dict_lookup - look up "dict_foo_open" function */
 
-static DICT_OPEN_FN dymap_dict_lookup(const char *dict_type)
+/* dymap_dict_lookup - look up DICT_OPEN_INFO */
+
+static const DICT_OPEN_INFO *dymap_dict_lookup(const char *dict_type)
 {
+    const char myname[] = "dymap_dict_lookup";
     struct stat st;
-    LIB_FN  fn[2];
-    DICT_OPEN_FN dict_open_fn;
+    LIB_FN  fn[3];
     DYMAP_INFO *dp;
+    const DICT_OPEN_INFO *op;
+    DICT_OPEN_INFO *np;
+
+    if (msg_verbose > 1)
+       msg_info("%s: %s", myname, dict_type);
 
     /*
      * Respect the hook nesting order.
      */
     if (saved_dict_open_hook != 0
-       && (dict_open_fn = saved_dict_open_hook(dict_type)) != 0)
-       return (dict_open_fn);
+       && (op = saved_dict_open_hook(dict_type)) != 0)
+       return (op);
 
     /*
      * Allow for graceful degradation when a database is unavailable. This
      * allows Postfix daemon processes to continue handling email with
      * reduced functionality.
      */
-    if ((dp = (DYMAP_INFO *) htable_find(dymap_info, dict_type)) == 0)
+    if ((dp = (DYMAP_INFO *) htable_find(dymap_info, dict_type)) == 0) {
+       msg_warn("unsupported dictionary type: %s. "
+                "Is the postfix-%s package installed?",
+                dict_type, dict_type);
        return (0);
+    }
     if (stat(dp->soname, &st) < 0) {
        msg_warn("unsupported dictionary type: %s (%s: %m)",
                 dict_type, dp->soname);
@@ -142,64 +164,15 @@ static DICT_OPEN_FN dymap_dict_lookup(const char *dict_type)
                 dict_type, dp->soname);
        return (0);
     }
-    fn[0].name = dp->dict_name;
-    fn[1].name = 0;
+    fn[0].name = dp->dict_name;                        /* not null */
+    fn[1].name = dp->mkmap_name;               /* may be null */
+    fn[2].name = 0;
     load_library_symbols(dp->soname, fn, (LIB_DP *) 0);
-    return ((DICT_OPEN_FN) fn[0].fptr);
-}
-
-/* dymap_mkmap_lookup - look up "mkmap_foo_open" function */
-
-static MKMAP_OPEN_FN dymap_mkmap_lookup(const char *dict_type)
-{
-    struct stat st;
-    LIB_FN  fn[2];
-    MKMAP_OPEN_FN mkmap_open_fn;
-    DYMAP_INFO *dp;
-
-    /*
-     * Respect the hook nesting order.
-     */
-    if (saved_mkmap_open_hook != 0
-       && (mkmap_open_fn = saved_mkmap_open_hook(dict_type)) != 0)
-       return (mkmap_open_fn);
-
-    /*
-     * All errors are fatal. If the postmap(1) or postalias(1) command can't
-     * create the requested database, then graceful degradation is not
-     * useful.
-     * 
-     * Fix 20220416: if this dictionary type is registered for some non-mkmap
-     * purpose, then don't talk nonsense about a missing package.
-     */
-    if ((dp = (DYMAP_INFO *) htable_find(dymap_info, dict_type)) == 0) {
-       ARGV   *types = dict_mapnames();
-       char  **cpp;
-
-       for (cpp = types->argv; *cpp; cpp++) {
-           if (strcmp(dict_type, *cpp) == 0)
-               msg_fatal("unsupported dictionary type: %s does not support "
-                         "bulk-mode creation.", dict_type);
-       }
-       msg_fatal("unsupported dictionary type: %s. "
-                 "Is the postfix-%s package installed?",
-                 dict_type, dict_type);
-    }
-    if (!dp->mkmap_name)
-       msg_fatal("unsupported dictionary type: %s does not support "
-                 "bulk-mode creation.", dict_type);
-    if (stat(dp->soname, &st) < 0)
-       msg_fatal("unsupported dictionary type: %s (%s: %m). "
-                 "Is the postfix-%s package installed?",
-                 dict_type, dp->soname, dict_type);
-    if (st.st_uid != 0 || (st.st_mode & (S_IWGRP | S_IWOTH)) != 0)
-       msg_fatal("unsupported dictionary type: %s "
-                 "(%s: file is owned or writable by non-root users)",
-                 dict_type, dp->soname);
-    fn[0].name = dp->mkmap_name;
-    fn[1].name = 0;
-    load_library_symbols(dp->soname, fn, (LIB_DP *) 0);
-    return ((MKMAP_OPEN_FN) fn[0].fptr);
+    np = (DICT_OPEN_INFO *) mymalloc(sizeof(*op));
+    np->type = mystrdup(dict_type);
+    np->dict_fn = (DICT_OPEN_FN) fn[0].fptr;
+    np->mkmap_fn = (MKMAP_OPEN_FN) (dp->mkmap_name ? fn[1].fptr : 0);
+    return (np);
 }
 
 /* dymap_list - enumerate dynamically-linked database type names */
@@ -249,6 +222,7 @@ static void dymap_entry_free(void *ptr)
 
 static void dymap_read_conf(const char *path, const char *path_base)
 {
+    const char myname[] = "dymap_read_conf";
     VSTREAM *fp;
     VSTRING *buf;
     char   *cp;
@@ -260,6 +234,8 @@ static void dymap_read_conf(const char *path, const char *path_base)
      * Silently ignore a missing dynamicmaps.cf file, but be explicit about
      * problems when the file does exist.
      */
+    if (msg_verbose > 1)
+       msg_info("%s: opening %s", myname, path);
     if ((fp = vstream_fopen(path, O_RDONLY, 0)) != 0) {
        if (fstat(vstream_fileno(fp), &st) < 0)
            msg_fatal("%s: fstat failed; %m", path);
@@ -270,6 +246,8 @@ static void dymap_read_conf(const char *path, const char *path_base)
            buf = vstring_alloc(100);
            while (vstring_get_nonl(buf, fp) != VSTREAM_EOF) {
                cp = vstring_str(buf);
+               if (msg_verbose > 1)
+                   msg_info("%s: read: %s", myname, cp);
                linenum++;
                if (*cp == '#' || *cp == '\0')
                    continue;
@@ -296,13 +274,11 @@ static void dymap_read_conf(const char *path, const char *path_base)
            vstring_free(buf);
 
            /*
-            * Once-only: hook into the dict_open(3) and mkmap_open(3)
-            * infrastructure,
+            * Once-only: hook into the dict_open(3) infrastructure.
             */
            if (dymap_hooks_done == 0) {
                dymap_hooks_done = 1;
                saved_dict_open_hook = dict_open_extend(dymap_dict_lookup);
-               saved_mkmap_open_hook = mkmap_open_extend(dymap_mkmap_lookup);
                saved_dict_mapnames_hook = dict_mapnames_extend(dymap_list);
            }
        }
@@ -322,6 +298,9 @@ void    dymap_init(const char *conf_path, const char *plugin_dir)
     const char *conf_name;
     VSTRING *sub_conf_path;
 
+    if (msg_verbose > 1)
+       msg_info("%s: %s %s", myname, conf_path, plugin_dir);
+
     /*
      * Reload dynamicmaps.cf, but don't reload already-loaded plugins.
      */
index 7a2718e0592158c3c61e537007c22e364d402162..b8838dbaa45a2cc61de73e38fbf20e8b22f4e3a0 100644 (file)
@@ -78,6 +78,11 @@ extern const char hbc_checks_unknown;
 /*     IBM T.J. Watson Research
 /*     P.O. Box 704
 /*     Yorktown Heights, NY 10598, USA
+/*
+/*     Wietse Venema
+/*     Google, Inc.
+/*     111 8th Avenue
+/*     New York, NY 10011, USA
 /*--*/
 
 #endif
index 6d6d729f28b2068aafdc26852e5f5b631fda9096..c640a807a3226eb5cba7237c30f64f24e7982548 100644 (file)
 /*     IBM T.J. Watson Research
 /*     P.O. Box 704
 /*     Yorktown Heights, NY 10598, USA
+/*
+/*     Wietse Venema
+/*     Google, Inc.
+/*     111 8th Avenue
+/*     New York, NY 10011, USA
 /*--*/
 
 /* System library. */
 #include <mail_params.h>
 #include <mail_dict.h>
 
-typedef struct {
-    char   *type;
-    struct DICT *(*open) (const char *, int, int);
-} DICT_OPEN_INFO;
-
 static const DICT_OPEN_INFO dict_open_info[] = {
-    DICT_TYPE_PROXY, dict_proxy_open,
+    DICT_TYPE_PROXY, dict_proxy_open, mkmap_proxy_open,
 #ifndef USE_DYNAMIC_MAPS
 #ifdef HAS_LDAP
-    DICT_TYPE_LDAP, dict_ldap_open,
+    DICT_TYPE_LDAP, dict_ldap_open, 0,
 #endif
 #ifdef HAS_MYSQL
-    DICT_TYPE_MYSQL, dict_mysql_open,
+    DICT_TYPE_MYSQL, dict_mysql_open, 0,
 #endif
 #ifdef HAS_PGSQL
-    DICT_TYPE_PGSQL, dict_pgsql_open,
+    DICT_TYPE_PGSQL, dict_pgsql_open, 0,
 #endif
 #ifdef HAS_SQLITE
-    DICT_TYPE_SQLITE, dict_sqlite_open,
+    DICT_TYPE_SQLITE, dict_sqlite_open, 0,
 #endif
 #endif                                 /* !USE_DYNAMIC_MAPS */
-    DICT_TYPE_MEMCACHE, dict_memcache_open,
+    DICT_TYPE_MEMCACHE, dict_memcache_open, 0,
     0,
 };
 
@@ -95,7 +95,7 @@ void    mail_dict_init(void)
 #endif
 
     for (dp = dict_open_info; dp->type; dp++)
-       dict_open_register(dp->type, dp->open);
+       dict_open_register(dp);
 }
 
 #ifdef TEST
index 4728aa874222426220fd6138e2c2bafe15f2c88e..56789209320138172a9b3f2164438cd5f6466987 100644 (file)
@@ -20,7 +20,7 @@
   * Patches change both the patchlevel and the release date. Snapshots have no
   * patchlevel; they change the release date only.
   */
-#define MAIL_RELEASE_DATE      "20220421"
+#define MAIL_RELEASE_DATE      "20220507"
 #define MAIL_VERSION_NUMBER    "3.8"
 
 #ifdef SNAPSHOT
index 7c84e9aa01a145396e430cda09ebab8f334e621a..790396bbabfb41c915c400adf93d7fe7f82c6ad6 100644 (file)
 /*     IBM T.J. Watson Research
 /*     P.O. Box 704
 /*     Yorktown Heights, NY 10598, USA
+/*
+/*     Wietse Venema
+/*     Google, Inc.
+/*     111 8th Avenue
+/*     New York, NY 10011, USA
 /*--*/
 
 /* System library. */
diff --git a/postfix/src/global/mkmap.h b/postfix/src/global/mkmap.h
deleted file mode 100644 (file)
index e493114..0000000
+++ /dev/null
@@ -1,64 +0,0 @@
-#ifndef _MKMAP_H_INCLUDED_
-#define _MKMAP_H_INCLUDED_
-
-/*++
-/* NAME
-/*     mkmap 3h
-/* SUMMARY
-/*     create or rewrite Postfix database
-/* SYNOPSIS
-/*     #include <mkmap.h>
-/* DESCRIPTION
-/* .nf
-
- /*
-  * Utility library.
-  */
-#include <dict.h>
-
- /*
-  * A database handle is an opaque structure. The user is not supposed to
-  * know its implementation. We try to open and lock a file before DB/DBM
-  * initialization. However, if the file does not exist then we may have to
-  * acquire the lock after the DB/DBM initialization.
-  */
-typedef struct MKMAP {
-    DICT_OPEN_FN open;                 /* dict_xx_open() */
-    struct DICT *dict;                 /* dict_xx_open() result */
-    void    (*after_open) (struct MKMAP *);    /* may be null */
-    void    (*after_close) (struct MKMAP *);   /* may be null */
-    int     multi_writer;              /* multi-writer safe */
-} MKMAP;
-
-extern MKMAP *mkmap_open(const char *, const char *, int, int);
-extern void mkmap_append(MKMAP *, const char *, const char *);
-extern void mkmap_close(MKMAP *);
-
-#define mkmap_append(map, key, val) dict_put((map)->dict, (key), (val))
-
-extern MKMAP *mkmap_dbm_open(const char *);
-extern MKMAP *mkmap_cdb_open(const char *);
-extern MKMAP *mkmap_hash_open(const char *);
-extern MKMAP *mkmap_btree_open(const char *);
-extern MKMAP *mkmap_lmdb_open(const char *);
-extern MKMAP *mkmap_sdbm_open(const char *);
-extern MKMAP *mkmap_proxy_open(const char *);
-extern MKMAP *mkmap_fail_open(const char *);
-
-typedef MKMAP *(*MKMAP_OPEN_FN) (const char *);
-typedef MKMAP_OPEN_FN (*MKMAP_OPEN_EXTEND_FN) (const char *);
-extern void mkmap_open_register(const char *, MKMAP_OPEN_FN);
-extern MKMAP_OPEN_EXTEND_FN mkmap_open_extend(MKMAP_OPEN_EXTEND_FN);
-
-/* 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
index e4f4f34f151dc113db327fa1d1741334a27c8aef..ddfc708c2da3067f582cd6af9a9d049368c99566 100644 (file)
@@ -4,7 +4,7 @@
 /* SUMMARY
 /*     create or proxied database
 /* SYNOPSIS
-/*     #include <mkmap.h>
+/*     #include <dict_proxy.h>
 /*
 /*     MKMAP   *mkmap_proxy_open(path)
 /*     const char *path;
 /*     IBM T.J. Watson Research
 /*     P.O. Box 704
 /*     Yorktown Heights, NY 10598, USA
+/*
+/*     Wietse Venema
+/*     Google, Inc.
+/*     111 8th Avenue
+/*     New York, NY 10011, USA
 /*--*/
 
 /* System library. */
 #include <mymalloc.h>
 #include <dict_proxy.h>
 
-/* Application-specific. */
-
-#include "mkmap.h"
-
 /* mkmap_proxy_open - create or open database */
 
 MKMAP  *mkmap_proxy_open(const char *unused_path)
index 5e5b72dca97dbc04c54297234b25246a0476a99c..9c124e5c05169197239d4080ed17bbaac85c50fa 100644 (file)
@@ -93,6 +93,7 @@ postalias.o: ../../include/argv.h
 postalias.o: ../../include/check_arg.h
 postalias.o: ../../include/clean_env.h
 postalias.o: ../../include/dict.h
+postalias.o: ../../include/dict_db.h
 postalias.o: ../../include/dict_proxy.h
 postalias.o: ../../include/mail_conf.h
 postalias.o: ../../include/mail_dict.h
index 95388836a9a879b35c0049463c654fb6242cba11..d17e397de4847a74506557c3ba50f35883f3a08b 100644 (file)
 #include <set_eugid.h>
 #include <warn_stat.h>
 #include <clean_env.h>
+#include <dict_db.h>
 
 /* Global library. */
 
 #include <mail_dict.h>
 #include <mail_params.h>
 #include <mail_version.h>
-#include <mkmap.h>
 #include <mail_task.h>
 #include <dict_proxy.h>
 #include <mail_parm_split.h>
@@ -342,6 +342,24 @@ static void postalias(char *map_type, char *path_name, int postalias_flags,
        && (st.st_uid != geteuid() || st.st_gid != getegid()))
        set_eugid(st.st_uid, st.st_gid);
 
+    /*
+     * Override the default per-table cache size for DB map (re)builds. We
+     * can't do this in the mkmap* functions because those don't have access
+     * to Postfix parameter settings.
+     * 
+     * db_cache_size" is defined in util/dict_open.c and defaults to 128kB,
+     * which works well for the lookup code.
+     * 
+     * We use a larger per-table cache when building ".db" files. For "hash"
+     * files performance degrades rapidly unless the memory pool is O(file
+     * size).
+     * 
+     * For "btree" files performance is good with sorted input even for small
+     * memory pools, but with random input degrades rapidly unless the memory
+     * pool is O(file size).
+     */
+    dict_db_cache_size = var_db_create_buf;
+
     /*
      * Open the database, create it when it does not exist, truncate it when
      * it does exist, and lock out any spectators.
index 60c797a73d462084175c9acfe931ec0d11452de4..4f6536fd346c2b015c7a3c9c367167969e7deb24 100644 (file)
@@ -1080,6 +1080,7 @@ postconf_dbms.o: ../../include/mac_expand.h
 postconf_dbms.o: ../../include/mac_parse.h
 postconf_dbms.o: ../../include/mail_conf.h
 postconf_dbms.o: ../../include/mail_params.h
+postconf_dbms.o: ../../include/mkmap.h
 postconf_dbms.o: ../../include/msg.h
 postconf_dbms.o: ../../include/myflock.h
 postconf_dbms.o: ../../include/mymalloc.h
index dc5369d9b066bb7412c5130dddfcda9a7fc83f30..aac92717cc964da49c01050f673889d4c89f446c 100644 (file)
@@ -133,6 +133,7 @@ postmap.o: ../../include/argv.h
 postmap.o: ../../include/check_arg.h
 postmap.o: ../../include/clean_env.h
 postmap.o: ../../include/dict.h
+postmap.o: ../../include/dict_db.h
 postmap.o: ../../include/dict_proxy.h
 postmap.o: ../../include/header_opts.h
 postmap.o: ../../include/mail_conf.h
index 66421d008f36da8ab5b543bc1cc28a0654e956a8..2826fc6b62db47a9ed98540efdfbe85b33bf0880 100644 (file)
 #include <set_eugid.h>
 #include <warn_stat.h>
 #include <clean_env.h>
+#include <dict_db.h>
 
 /* Global library. */
 
 #include <mail_dict.h>
 #include <mail_params.h>
 #include <mail_version.h>
-#include <mkmap.h>
 #include <mail_task.h>
 #include <dict_proxy.h>
 #include <mime_state.h>
@@ -435,6 +435,24 @@ static void postmap(char *map_type, char *path_name, int postmap_flags,
        && (st.st_uid != geteuid() || st.st_gid != getegid()))
        set_eugid(st.st_uid, st.st_gid);
 
+    /*
+     * Override the default per-table cache size for DB map (re)builds. We
+     * can't do this in the mkmap* functions because those don't have access
+     * to Postfix parameter settings.
+     * 
+     * db_cache_size" is defined in util/dict_open.c and defaults to 128kB,
+     * which works well for the lookup code.
+     * 
+     * We use a larger per-table cache when building ".db" files. For "hash"
+     * files performance degrades rapidly unless the memory pool is O(file
+     * size).
+     * 
+     * For "btree" files performance is good with sorted input even for small
+     * memory pools, but with random input degrades rapidly unless the memory
+     * pool is O(file size).
+     */
+    dict_db_cache_size = var_db_create_buf;
+
     /*
      * Open the database, optionally create it when it does not exist,
      * optionally truncate it when it does exist, and lock out any
@@ -660,8 +678,8 @@ static int postmap_queries(VSTREAM *in, char **maps, const int map_count,
        dicts[n] = 0;
 
     /*
-     * Perform all queries. Open maps on the fly, to avoid opening unnecessary
-     * maps.
+     * Perform all queries. Open maps on the fly, to avoid opening
+     * unnecessary maps.
      */
     if ((postmap_flags & POSTMAP_FLAG_HB_KEY) == 0) {
        while (vstring_get_nonl(keybuf, in) != VSTREAM_EOF) {
index edd5d710506a524cf4641e9dc349679c839522d2..dfc5d544a86cddce77bd358b35aa2c24489bea8a 100644 (file)
@@ -435,7 +435,7 @@ static int psc_starttls_cmd(PSC_STATE *state, char *args)
      * unavailable when tlsproxy(8) detects the problem too late.
      */
     if (PSC_SMTPD_NEXT_TOKEN(args) != 0)
-       return (PSC_SEND_REPLY(state, "501 Syntax: EHLO hostname\r\n"));
+       return (PSC_SEND_REPLY(state, "501 5.5.4 Syntax: STARTTLS\r\n"));
     if (state->flags & PSC_STATE_FLAG_USING_TLS)
        return (PSC_SEND_REPLY(state,
                               "554 5.5.1 Error: TLS already active\r\n"));
index 925f98ffa295668d6d228ac80f4f9008114a090e..7ff2910a80132d63f5bec6a44ae5c0546a76bb28 100644 (file)
@@ -73,6 +73,7 @@ proxymap.o: ../../include/mail_params.h
 proxymap.o: ../../include/mail_proto.h
 proxymap.o: ../../include/mail_server.h
 proxymap.o: ../../include/mail_version.h
+proxymap.o: ../../include/mkmap.h
 proxymap.o: ../../include/msg.h
 proxymap.o: ../../include/myflock.h
 proxymap.o: ../../include/mymalloc.h
index 65f41982f64cb52ff6305970f7952c4c2a32ef13..6412e0e36170b95527558012774c03ac90f1051a 100644 (file)
@@ -567,6 +567,7 @@ smtp_sasl_auth_cache.o: ../../include/htable.h
 smtp_sasl_auth_cache.o: ../../include/maps.h
 smtp_sasl_auth_cache.o: ../../include/match_list.h
 smtp_sasl_auth_cache.o: ../../include/mime_state.h
+smtp_sasl_auth_cache.o: ../../include/mkmap.h
 smtp_sasl_auth_cache.o: ../../include/msg.h
 smtp_sasl_auth_cache.o: ../../include/msg_stats.h
 smtp_sasl_auth_cache.o: ../../include/myaddrinfo.h
index bfe146f5c799543ce921f6fab691b254e7dd15d2..cdc671cffb267f761f811ac5b90fedcf66d2be62 100644 (file)
@@ -43,7 +43,8 @@ SRCS  = alldig.c allprint.c argv.c argv_split.c attr_clnt.c attr_print0.c \
        split_qnameval.c argv_attr_print.c argv_attr_scan.c dict_file.c \
        msg_logger.c logwriter.c unix_dgram_connect.c unix_dgram_listen.c \
        byte_mask.c known_tcp_ports.c argv_split_at.c dict_stream.c \
-       sane_strtol.c hash_fnv.c ldseed.c
+       sane_strtol.c hash_fnv.c ldseed.c mkmap_cdb.c mkmap_db.c mkmap_dbm.c \
+       mkmap_fail.c mkmap_lmdb.c mkmap_open.c mkmap_sdbm.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 \
@@ -88,12 +89,13 @@ OBJS        = alldig.o allprint.o argv.o argv_split.o attr_clnt.o attr_print0.o \
        split_qnameval.o argv_attr_print.o argv_attr_scan.o dict_file.o \
        msg_logger.o logwriter.o unix_dgram_connect.o unix_dgram_listen.o \
        byte_mask.o known_tcp_ports.o argv_split_at.o dict_stream.o \
-       sane_strtol.o hash_fnv.o ldseed.o
+       sane_strtol.o hash_fnv.o ldseed.o mkmap_db.o mkmap_dbm.o \
+       mkmap_fail.o mkmap_open.o
 # MAP_OBJ is for maps that may be dynamically loaded with dynamicmaps.cf.
 # When hard-linking these, makedefs sets NON_PLUGIN_MAP_OBJ=$(MAP_OBJ),
 # otherwise it sets the PLUGIN_* macros.
-MAP_OBJ        = dict_pcre.o $(LIB_MAP_OBJ)
-LIB_MAP_OBJ = dict_cdb.o dict_lmdb.o dict_sdbm.o slmdb.o
+MAP_OBJ        = dict_pcre.o dict_cdb.o dict_lmdb.o dict_sdbm.o slmdb.o \
+       mkmap_cdb.o mkmap_lmdb.o mkmap_sdbm.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 \
@@ -119,7 +121,7 @@ HDRS        = argv.h attr.h attr_clnt.h auto_clnt.h base64_code.h binhash.h \
        slmdb.h compat_va_copy.h dict_pipe.h dict_random.h \
        valid_utf8_hostname.h midna_domain.h dict_union.h dict_inline.h \
        check_arg.h argv_attr.h msg_logger.h logwriter.h byte_mask.h \
-       known_tcp_ports.h sane_strtol.h hash_fnv.h ldseed.h
+       known_tcp_ports.h sane_strtol.h hash_fnv.h ldseed.h mkmap.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)
@@ -140,8 +142,9 @@ TESTPROG= dict_open dup2_pass_on_exec events exec_command fifo_open \
        valid_utf8_string ip_match base32_code msg_rate_delay netstring \
        vstream timecmp dict_cache midna_domain casefold strcasecmp_utf8 \
        vbuf_print split_qnameval vstream msg_logger byte_mask \
-       known_tcp_ports dict_stream find_inet binhash hash_fnv
-PLUGIN_MAP_SO = $(LIB_PREFIX)pcre$(LIB_SUFFIX)
+       known_tcp_ports dict_stream find_inet binhash hash_fnv argv
+PLUGIN_MAP_SO = $(LIB_PREFIX)pcre$(LIB_SUFFIX) $(LIB_PREFIX)lmdb$(LIB_SUFFIX) \
+       $(LIB_PREFIX)cdb$(LIB_SUFFIX) $(LIB_PREFIX)sdbm$(LIB_SUFFIX)
 HTABLE_FIX = NORANDOMIZE=1
 LIB_DIR        = ../../lib
 INC_DIR        = ../../include
@@ -171,6 +174,18 @@ plugin_map_so_make: $(PLUGIN_MAP_SO)
 $(LIB_PREFIX)pcre$(LIB_SUFFIX): dict_pcre.o
        $(PLUGIN_LD) $(SHLIB_RPATH) -o $@ dict_pcre.o $(AUXLIBS_PCRE)
 
+$(LIB_PREFIX)cdb$(LIB_SUFFIX): mkmap_cdb.o dict_cdb.o
+       $(PLUGIN_LD) $(SHLIB_RPATH) -o $@ mkmap_cdb.o \
+           dict_cdb.o $(AUXLIBS_CDB)
+
+$(LIB_PREFIX)lmdb$(LIB_SUFFIX): mkmap_lmdb.o dict_lmdb.o slmdb.o
+       $(PLUGIN_LD) $(SHLIB_RPATH) -o $@ mkmap_lmdb.o dict_lmdb.o \
+           slmdb.o $(AUXLIBS_LMDB)
+
+$(LIB_PREFIX)sdbm$(LIB_SUFFIX): mkmap_sdbm.o dict_sdbm.o
+       $(PLUGIN_LD) $(SHLIB_RPATH) -o $@ mkmap_sdbm.o \
+           dict_sdbm.o $(AUXLIBS_SDBM)
+
 update: $(LIB_DIR)/$(LIB) $(HDRS) $(PLUGIN_MAP_SO_UPDATE) \
        $(PLUGIN_MAP_OBJ_UPDATE)
        -for i in $(HDRS); \
@@ -576,21 +591,29 @@ dict_stream: $(LIB)
        $(CC) $(CFLAGS) -DTEST -o $@ $@.c $(LIB) $(SYSLIBS)
        mv junk $@.o
 
+argv: $(LIB)
+       mv $@.o junk
+       $(CC) $(CFLAGS) -DTEST -o $@ $@.c $(LIB) $(SYSLIBS)
+       mv junk $@.o
+
 tests: all valid_hostname_test mac_expand_test dict_test unescape_test \
        hex_quote_test ctable_test inet_addr_list_test base64_code_test \
-       attr_scan64_test attr_scan0_test dict_pcre_tests host_port_test \
-       dict_cidr_test attr_scan_plain_test htable_test hex_code_test \
-       myaddrinfo_test format_tv_test ip_match_test name_mask_tests \
-       base32_code_test dict_thash_test surrogate_test timecmp_test \
-       dict_static_test dict_inline_test midna_domain_test casefold_test \
-       dict_utf8_test strcasecmp_utf8_test vbuf_print_test dict_regexp_test \
-       dict_union_test dict_pipe_test miss_endif_cidr_test \
+       attr_scan64_test attr_scan0_test host_port_test dict_tests \
+       attr_scan_plain_test htable_test hex_code_test myaddrinfo_test \
+       format_tv_test ip_match_test name_mask_tests base32_code_test \
+       surrogate_test timecmp_test midna_domain_test casefold_test \
+       strcasecmp_utf8_test vbuf_print_test miss_endif_cidr_test \
        miss_endif_regexp_test split_qnameval_test vstring_test \
-       vstream_test dict_regexp_file_test dict_cidr_file_test \
+       vstream_test byte_mask_tests mystrtok_test known_tcp_ports_test \
+       binhash_test argv_test
+dict_tests: all dict_test \
+       dict_pcre_tests dict_cidr_test dict_thash_test dict_static_test \
+       dict_inline_test dict_utf8_test dict_regexp_test dict_union_test \
+       dict_pipe_test dict_regexp_file_test dict_cidr_file_test \
        dict_static_file_test dict_random_test dict_random_file_test \
-       dict_inline_file_test byte_mask_tests mystrtok_test \
-       known_tcp_ports_test dict_stream_test dict_inline_regexp_test \
-       dict_inline_cidr_test binhash_test
+       dict_inline_file_test dict_stream_test dict_inline_regexp_test \
+       dict_inline_cidr_test
 
 dict_pcre_tests: dict_pcre_test miss_endif_pcre_test dict_pcre_file_test \
        dict_inline_pcre_test
@@ -1037,10 +1060,13 @@ dict_inline_cidr_test: dict_open dict_inline_cidr.ref
        rm -f dict_inline_cidr.tmp
 
 find_inet_test: find_inet find_inet.ref
-           $(SHLIB_ENV) ${VALGRIND} ./find_inet >find_inet.tmp 2>&1
+       $(SHLIB_ENV) ${VALGRIND} ./find_inet >find_inet.tmp 2>&1
        diff find_inet.ref find_inet.tmp
        rm -f find_inet.tmp
 
+argv_test: argv
+       $(SHLIB_ENV) ${VALGRIND} ./argv
+
 depend: $(MAKES)
        (sed '1,/^# do not edit/!d' Makefile.in; \
        set -e; for i in [a-z][a-z0-9]*.c; do \
@@ -1378,6 +1404,7 @@ dict_cdb.o: dict.h
 dict_cdb.o: dict_cdb.c
 dict_cdb.o: dict_cdb.h
 dict_cdb.o: iostuff.h
+dict_cdb.o: mkmap.h
 dict_cdb.o: msg.h
 dict_cdb.o: myflock.h
 dict_cdb.o: mymalloc.h
@@ -1411,6 +1438,7 @@ dict_db.o: dict.h
 dict_db.o: dict_db.c
 dict_db.o: dict_db.h
 dict_db.o: iostuff.h
+dict_db.o: mkmap.h
 dict_db.o: msg.h
 dict_db.o: myflock.h
 dict_db.o: mymalloc.h
@@ -1452,6 +1480,7 @@ dict_fail.o: check_arg.h
 dict_fail.o: dict.h
 dict_fail.o: dict_fail.c
 dict_fail.o: dict_fail.h
+dict_fail.o: mkmap.h
 dict_fail.o: msg.h
 dict_fail.o: myflock.h
 dict_fail.o: mymalloc.h
@@ -1506,6 +1535,7 @@ dict_lmdb.o: dict_lmdb.c
 dict_lmdb.o: dict_lmdb.h
 dict_lmdb.o: htable.h
 dict_lmdb.o: iostuff.h
+dict_lmdb.o: mkmap.h
 dict_lmdb.o: msg.h
 dict_lmdb.o: myflock.h
 dict_lmdb.o: mymalloc.h
@@ -1572,6 +1602,7 @@ dict_open.o: dict_thash.h
 dict_open.o: dict_union.h
 dict_open.o: dict_unix.h
 dict_open.o: htable.h
+dict_open.o: mkmap.h
 dict_open.o: msg.h
 dict_open.o: myflock.h
 dict_open.o: mymalloc.h
@@ -1652,6 +1683,7 @@ dict_sdbm.o: dict_sdbm.c
 dict_sdbm.o: dict_sdbm.h
 dict_sdbm.o: htable.h
 dict_sdbm.o: iostuff.h
+dict_sdbm.o: mkmap.h
 dict_sdbm.o: msg.h
 dict_sdbm.o: myflock.h
 dict_sdbm.o: mymalloc.h
@@ -1738,6 +1770,7 @@ dict_test.o: dict.h
 dict_test.o: dict_db.h
 dict_test.o: dict_lmdb.h
 dict_test.o: dict_test.c
+dict_test.o: mkmap.h
 dict_test.o: msg.h
 dict_test.o: msg_vstream.h
 dict_test.o: myflock.h
@@ -2182,6 +2215,99 @@ midna_domain.o: sys_defs.h
 midna_domain.o: valid_hostname.h
 midna_domain.o: vbuf.h
 midna_domain.o: vstring.h
+mkmap_cdb.o: argv.h
+mkmap_cdb.o: check_arg.h
+mkmap_cdb.o: dict.h
+mkmap_cdb.o: dict_cdb.h
+mkmap_cdb.o: mkmap.h
+mkmap_cdb.o: mkmap_cdb.c
+mkmap_cdb.o: myflock.h
+mkmap_cdb.o: mymalloc.h
+mkmap_cdb.o: sys_defs.h
+mkmap_cdb.o: vbuf.h
+mkmap_cdb.o: vstream.h
+mkmap_cdb.o: vstring.h
+mkmap_db.o: argv.h
+mkmap_db.o: check_arg.h
+mkmap_db.o: dict.h
+mkmap_db.o: dict_db.h
+mkmap_db.o: mkmap.h
+mkmap_db.o: mkmap_db.c
+mkmap_db.o: msg.h
+mkmap_db.o: myflock.h
+mkmap_db.o: mymalloc.h
+mkmap_db.o: stringops.h
+mkmap_db.o: sys_defs.h
+mkmap_db.o: vbuf.h
+mkmap_db.o: vstream.h
+mkmap_db.o: vstring.h
+mkmap_db.o: warn_stat.h
+mkmap_dbm.o: argv.h
+mkmap_dbm.o: check_arg.h
+mkmap_dbm.o: dict.h
+mkmap_dbm.o: dict_dbm.h
+mkmap_dbm.o: mkmap.h
+mkmap_dbm.o: mkmap_dbm.c
+mkmap_dbm.o: msg.h
+mkmap_dbm.o: myflock.h
+mkmap_dbm.o: mymalloc.h
+mkmap_dbm.o: stringops.h
+mkmap_dbm.o: sys_defs.h
+mkmap_dbm.o: vbuf.h
+mkmap_dbm.o: vstream.h
+mkmap_dbm.o: vstring.h
+mkmap_fail.o: argv.h
+mkmap_fail.o: check_arg.h
+mkmap_fail.o: dict.h
+mkmap_fail.o: dict_fail.h
+mkmap_fail.o: mkmap.h
+mkmap_fail.o: mkmap_fail.c
+mkmap_fail.o: myflock.h
+mkmap_fail.o: mymalloc.h
+mkmap_fail.o: sys_defs.h
+mkmap_fail.o: vbuf.h
+mkmap_fail.o: vstream.h
+mkmap_fail.o: vstring.h
+mkmap_lmdb.o: argv.h
+mkmap_lmdb.o: check_arg.h
+mkmap_lmdb.o: dict.h
+mkmap_lmdb.o: dict_lmdb.h
+mkmap_lmdb.o: mkmap.h
+mkmap_lmdb.o: mkmap_lmdb.c
+mkmap_lmdb.o: myflock.h
+mkmap_lmdb.o: mymalloc.h
+mkmap_lmdb.o: sys_defs.h
+mkmap_lmdb.o: vbuf.h
+mkmap_lmdb.o: vstream.h
+mkmap_lmdb.o: vstring.h
+mkmap_open.o: argv.h
+mkmap_open.o: check_arg.h
+mkmap_open.o: dict.h
+mkmap_open.o: mkmap.h
+mkmap_open.o: mkmap_open.c
+mkmap_open.o: msg.h
+mkmap_open.o: myflock.h
+mkmap_open.o: mymalloc.h
+mkmap_open.o: sigdelay.h
+mkmap_open.o: stringops.h
+mkmap_open.o: sys_defs.h
+mkmap_open.o: vbuf.h
+mkmap_open.o: vstream.h
+mkmap_open.o: vstring.h
+mkmap_sdbm.o: argv.h
+mkmap_sdbm.o: check_arg.h
+mkmap_sdbm.o: dict.h
+mkmap_sdbm.o: dict_sdbm.h
+mkmap_sdbm.o: mkmap.h
+mkmap_sdbm.o: mkmap_sdbm.c
+mkmap_sdbm.o: msg.h
+mkmap_sdbm.o: myflock.h
+mkmap_sdbm.o: mymalloc.h
+mkmap_sdbm.o: stringops.h
+mkmap_sdbm.o: sys_defs.h
+mkmap_sdbm.o: vbuf.h
+mkmap_sdbm.o: vstream.h
+mkmap_sdbm.o: vstring.h
 msg.o: msg.c
 msg.o: msg.h
 msg.o: msg_output.h
index a364e243998a63d1d145dc5c0b321414e268af45..4e05fd0b4b3ae9dcd1caa83efdf1bfb6215589f0 100644 (file)
@@ -6,11 +6,18 @@
 /* SYNOPSIS
 /*     #include <argv.h>
 /*
+/*     typedef int (*ARGV_COMPAR_FN)(const void *, const void *);
+/*
 /*     ARGV    *argv_alloc(len)
 /*     ssize_t len;
 /*
-/*     ARGV    *argv_sort(argvp)
+/*     ARGV    *argv_qsort(argvp, compar)
 /*     ARGV    *argvp;
+/*     ARGV_COMPAR_FN compar;
+/*
+/*     void    argv_uniq(argvp, compar)
+/*     ARGV    *argvp;
+/*     ARGV_COMPAR_FN compar;
 /*
 /*     ARGV    *argv_free(argvp)
 /*     ARGV    *argvp;
 /*     length. The result is ready for use by argv_add(). The array
 /*     is null terminated.
 /*
-/*     argv_sort() sorts the elements of argvp in place returning
-/*     the original array.
+/*     argv_qsort() sorts the elements of argvp in place, and
+/*     returns its first argument. If the compar argument specifies
+/*     a null pointer, then argv_qsort() will use byte-by-byte
+/*     comparison.
+/*
+/*     argv_uniq() reduces adjacent same-value elements to one
+/*     element, and returns its first argument. If the compar
+/*     argument specifies a null pointer, then argv_uniq() will
+/*     use byte-by-byte comparison.
 /*
 /*     argv_add() copies zero or more strings and adds them to the
 /*     specified string array. The array is null terminated.
 /*     IBM T.J. Watson Research
 /*     P.O. Box 704
 /*     Yorktown Heights, NY 10598, USA
+/*
+/*     Wietse Venema
+/*     Google, Inc.
+/*     111 8th Avenue
+/*     New York, NY 10011, USA
 /*--*/
 
 /* System libraries. */
 #include "msg.h"
 #include "argv.h"
 
+#ifdef TEST
+extern NORETURN PRINTFLIKE(1, 2) test_msg_panic(const char *,...);
+
+#define msg_panic test_msg_panic
+#endif
+
 /* argv_free - destroy string array */
 
 ARGV   *argv_free(ARGV *argvp)
@@ -172,7 +197,16 @@ static int argv_cmp(const void *e1, const void *e2)
     return strcmp(s1, s2);
 }
 
-/* argv_sort - sort array in place */
+/* argv_qsort - sort array in place */
+
+ARGV   *argv_qsort(ARGV *argvp, ARGV_COMPAR_FN compar)
+{
+    qsort(argvp->argv, argvp->argc, sizeof(argvp->argv[0]),
+         compar ? compar : argv_cmp);
+    return (argvp);
+}
+
+/* argv_sort - binary compatibility */
 
 ARGV   *argv_sort(ARGV *argvp)
 {
@@ -180,6 +214,26 @@ ARGV   *argv_sort(ARGV *argvp)
     return (argvp);
 }
 
+/* argv_uniq - deduplicate adjacent array elements */
+
+ARGV   *argv_uniq(ARGV *argvp, ARGV_COMPAR_FN compar)
+{
+    char  **cpp;
+    char  **prev;
+
+    if (compar == 0)
+       compar = argv_cmp;
+    for (prev = 0, cpp = argvp->argv; cpp < argvp->argv + argvp->argc; cpp++) {
+       if (prev != 0 && compar(prev, cpp) == 0) {
+           argv_delete(argvp, cpp - argvp->argv, 1);
+           cpp = prev;
+       } else {
+           prev = cpp;
+       }
+    }
+    return (argvp);
+}
+
 /* argv_extend - extend array */
 
 static void argv_extend(ARGV *argvp)
@@ -324,3 +378,344 @@ void    argv_delete(ARGV *argvp, ssize_t first, ssize_t how_many)
        argvp->argv[pos] = argvp->argv[pos + how_many];
     argvp->argc -= how_many;
 }
+
+#ifdef TEST
+
+ /*
+  * System library.
+  */
+#include <setjmp.h>
+
+ /*
+  * Utility library.
+  */
+#include <msg_vstream.h>
+#include <stringops.h>
+
+#define ARRAY_LEN      (10)
+
+typedef struct TEST_CASE {
+    const char *label;                 /* identifies test case */
+    const char *inputs[ARRAY_LEN];     /* input strings */
+    int     terminate;                 /* terminate result */
+    ARGV   *(*populate_fn) (const struct TEST_CASE *, ARGV *);
+    const char *exp_panic_msg;         /* expected panic */
+    int     exp_argc;                  /* expected array length */
+    const char *exp_argv[ARRAY_LEN];   /* expected array content */
+} TEST_CASE;
+
+#define TERMINATE_ARRAY        (1)
+
+#define        PASS    (0)
+#define FAIL   (1)
+
+VSTRING *test_panic_str;
+jmp_buf test_panic_jbuf;
+
+/* test_msg_panic - does not return, and does not terminate */
+
+void    test_msg_panic(const char *fmt,...)
+{
+    va_list ap;
+
+    va_start(ap, fmt);
+    test_panic_str = vstring_alloc(100);
+    vstring_vsprintf(test_panic_str, fmt, ap);
+    va_end(ap);
+    longjmp(test_panic_jbuf, 1);
+}
+
+/* test_argv_populate - populate result, optionally terminate */
+
+static ARGV *test_argv_populate(const TEST_CASE *tp, ARGV *argvp)
+{
+    const char *const * cpp;
+
+    for (cpp = tp->inputs; *cpp; cpp++)
+       argv_add(argvp, *cpp, (char *) 0);
+    if (tp->terminate)
+       argv_terminate(argvp);
+    return (argvp);
+}
+
+/* test_argv_sort - populate and sort result */
+
+static ARGV *test_argv_sort(const TEST_CASE *tp, ARGV *argvp)
+{
+    test_argv_populate(tp, argvp);
+    argv_qsort(argvp, (ARGV_COMPAR_FN) 0);
+    return (argvp);
+}
+
+/* test_argv_sort_uniq - populate, sort, uniq result */
+
+static ARGV *test_argv_sort_uniq(const TEST_CASE *tp, ARGV *argvp)
+{
+
+    /*
+     * This also tests argv_delete().
+     */
+    test_argv_sort(tp, argvp);
+    argv_uniq(argvp, (ARGV_COMPAR_FN) 0);
+    return (argvp);
+}
+
+/* test_argv_good_truncate - populate and truncate to good size */
+
+static ARGV *test_argv_good_truncate(const TEST_CASE *tp, ARGV *argvp)
+{
+    test_argv_populate(tp, argvp);
+    argv_truncate(argvp, tp->exp_argc);
+    return (argvp);
+}
+
+/* test_argv_bad_truncate - populate and truncate to bad size */
+
+static ARGV *test_argv_bad_truncate(const TEST_CASE *tp, ARGV *argvp)
+{
+    test_argv_populate(tp, argvp);
+    argv_truncate(argvp, -1);
+    return (argvp);
+}
+
+/* test_argv_good_insert - populate and insert at good position */
+
+static ARGV *test_argv_good_insert(const TEST_CASE *tp, ARGV *argvp)
+{
+    test_argv_populate(tp, argvp);
+    argv_insert_one(argvp, 1, "new");
+    return (argvp);
+}
+
+/* test_argv_bad_insert1 - populate and insert at bad position */
+
+static ARGV *test_argv_bad_insert1(const TEST_CASE *tp, ARGV *argvp)
+{
+    test_argv_populate(tp, argvp);
+    argv_insert_one(argvp, -1, "new");
+    return (argvp);
+}
+
+/* test_argv_bad_insert2 - populate and insert at bad position */
+
+static ARGV *test_argv_bad_insert2(const TEST_CASE *tp, ARGV *argvp)
+{
+    test_argv_populate(tp, argvp);
+    argv_insert_one(argvp, 100, "new");
+    return (argvp);
+}
+
+/* test_argv_good_replace - populate and replace at good position */
+
+static ARGV *test_argv_good_replace(const TEST_CASE *tp, ARGV *argvp)
+{
+    test_argv_populate(tp, argvp);
+    argv_replace_one(argvp, 1, "new");
+    return (argvp);
+}
+
+/* test_argv_bad_replace1 - populate and replace at bad position */
+
+static ARGV *test_argv_bad_replace1(const TEST_CASE *tp, ARGV *argvp)
+{
+    test_argv_populate(tp, argvp);
+    argv_replace_one(argvp, -1, "new");
+    return (argvp);
+}
+
+/* test_argv_bad_replace2 - populate and replace at bad position */
+
+static ARGV *test_argv_bad_replace2(const TEST_CASE *tp, ARGV *argvp)
+{
+    test_argv_populate(tp, argvp);
+    argv_replace_one(argvp, 100, "new");
+    return (argvp);
+}
+
+/* test_argv_bad_delete1 - populate and delete at bad position */
+
+static ARGV *test_argv_bad_delete1(const TEST_CASE *tp, ARGV *argvp)
+{
+    test_argv_populate(tp, argvp);
+    argv_delete(argvp, -1, 1);
+    return (argvp);
+}
+
+/* test_argv_bad_delete2 - populate and delete at bad position */
+
+static ARGV *test_argv_bad_delete2(const TEST_CASE *tp, ARGV *argvp)
+{
+    test_argv_populate(tp, argvp);
+    argv_delete(argvp, 0, -1);
+    return (argvp);
+}
+
+/* test_argv_bad_delete3 - populate and delete at bad position */
+
+static ARGV *test_argv_bad_delete3(const TEST_CASE *tp, ARGV *argvp)
+{
+    test_argv_populate(tp, argvp);
+    argv_delete(argvp, 100, 1);
+    return (argvp);
+}
+
+/* test_argv_verify - verify result */
+
+static int test_argv_verify(const TEST_CASE *tp, ARGV *argvp)
+{
+    int     idx;
+
+    if (tp->exp_panic_msg != 0) {
+       if (test_panic_str == 0) {
+           msg_warn("test case '%s': got no panic, want: '%s'",
+                    tp->label, tp->exp_panic_msg);
+           return (FAIL);
+       }
+       if (strcmp(vstring_str(test_panic_str), tp->exp_panic_msg) != 0) {
+           msg_warn("test case '%s': got '%s', want: '%s'",
+                    tp->label, vstring_str(test_panic_str), tp->exp_panic_msg);
+           return (FAIL);
+       }
+       return (PASS);
+    }
+    if (test_panic_str != 0) {
+       msg_warn("test case '%s': got '%s', want: no panic",
+                tp->label, vstring_str(test_panic_str));
+       return (FAIL);
+    }
+    if (argvp->argc != tp->exp_argc) {
+       msg_warn("test case '%s': got argc: %ld, want: %d",
+                tp->label, (long) argvp->argc, tp->exp_argc);
+       return (FAIL);
+    }
+    if (argvp->argv[argvp->argc] != 0 && tp->terminate) {
+       msg_warn("test case '%s': got unterminated, want: terminated", tp->label);
+       return (FAIL);
+    }
+    for (idx = 0; idx < argvp->argc; idx++) {
+       if (strcmp(argvp->argv[idx], tp->exp_argv[idx]) != 0) {
+           msg_warn("test case '%s': index %d: got '%s', want: '%s'",
+                    tp->label, idx, argvp->argv[idx], tp->exp_argv[idx]);
+           return (FAIL);
+       }
+    }
+    return (PASS);
+}
+
+ /*
+  * The test cases. TODO: argv_addn with good and bad string length.
+  */
+static const TEST_CASE test_cases[] = {
+    {"multiple strings, unterminated array",
+       {"foo", "baz", "bar", 0}, 0, test_argv_populate,
+       0, 3, {"foo", "baz", "bar", 0}
+    },
+    {"multiple strings, terminated array",
+       {"foo", "baz", "bar", 0}, TERMINATE_ARRAY, test_argv_populate,
+       0, 3, {"foo", "baz", "bar", 0}
+    },
+    {"distinct strings, sorted array",
+       {"foo", "baz", "bar", 0}, 0, test_argv_sort,
+       0, 3, {"bar", "baz", "foo", 0}
+    },
+    {"duplicate strings, sorted array",
+       {"foo", "baz", "baz", "bar", 0}, 0, test_argv_sort,
+       0, 4, {"bar", "baz", "baz", "foo", 0}
+    },
+    {"duplicate strings, sorted, uniqued-middle elements",
+       {"foo", "baz", "baz", "bar", 0}, 0, test_argv_sort_uniq,
+       0, 3, {"bar", "baz", "foo", 0}
+    },
+    {"duplicate strings, sorted, uniqued-first elements",
+       {"foo", "bar", "baz", "bar", 0}, 0, test_argv_sort_uniq,
+       0, 3, {"bar", "baz", "foo", 0}
+    },
+    {"duplicate strings, sorted, uniqued-last elements",
+       {"foo", "foo", "baz", "bar", 0}, 0, test_argv_sort_uniq,
+       0, 3, {"bar", "baz", "foo", 0}
+    },
+    {"multiple strings, truncate array by one",
+       {"foo", "baz", "bar", 0}, 0, test_argv_good_truncate,
+       0, 2, {"foo", "baz", 0}
+    },
+    {"multiple strings, truncate whole array",
+       {"foo", "baz", "bar", 0}, 0, test_argv_good_truncate,
+       0, 0, {"foo", "baz", 0}
+    },
+    {"multiple strings, bad truncate",
+       {"foo", "baz", "bar", 0}, 0, test_argv_bad_truncate,
+       "argv_truncate: bad length -1"
+    },
+    {"multiple strings, insert one at good position",
+       {"foo", "baz", "bar", 0}, 0, test_argv_good_insert,
+       0, 4, {"foo", "new", "baz", "bar", 0}
+    },
+    {"multiple strings, insert one at bad position",
+       {"foo", "baz", "bar", 0}, 0, test_argv_bad_insert1,
+       "argv_insert_one bad position: -1"
+    },
+    {"multiple strings, insert one at bad position",
+       {"foo", "baz", "bar", 0}, 0, test_argv_bad_insert2,
+       "argv_insert_one bad position: 100"
+    },
+    {"multiple strings, replace one at good position",
+       {"foo", "baz", "bar", 0}, 0, test_argv_good_replace,
+       0, 3, {"foo", "new", "bar", 0}
+    },
+    {"multiple strings, replace one at bad position",
+       {"foo", "baz", "bar", 0}, 0, test_argv_bad_replace1,
+       "argv_replace_one bad position: -1"
+    },
+    {"multiple strings, replace one at bad position",
+       {"foo", "baz", "bar", 0}, 0, test_argv_bad_replace2,
+       "argv_replace_one bad position: 100"
+    },
+    {"multiple strings, delete one at negative position",
+       {"foo", "baz", "bar", 0}, 0, test_argv_bad_delete1,
+       "argv_delete bad range: (start=-1 count=1)"
+    },
+    {"multiple strings, delete with bad range end",
+       {"foo", "baz", "bar", 0}, 0, test_argv_bad_delete2,
+       "argv_delete bad range: (start=0 count=-1)"
+    },
+    {"multiple strings, delete at too large position",
+       {"foo", "baz", "bar", 0}, 0, test_argv_bad_delete3,
+       "argv_delete bad range: (start=100 count=1)"
+    },
+    0,
+};
+
+int     main(int argc, char **argv)
+{
+    const TEST_CASE *tp;
+    int     pass = 0;
+    int     fail = 0;
+
+    msg_vstream_init(sane_basename((VSTRING *) 0, argv[0]), VSTREAM_ERR);
+
+    for (tp = test_cases; tp->label != 0; tp++) {
+       int     test_failed;
+       ARGV   *argvp;
+
+       argvp = argv_alloc(1);
+       if (setjmp(test_panic_jbuf) == 0)
+           tp->populate_fn(tp, argvp);
+       test_failed = test_argv_verify(tp, argvp);
+       if (test_failed) {
+           msg_info("%s: FAIL", tp->label);
+           fail++;
+       } else {
+           msg_info("%s: PASS", tp->label);
+           pass++;
+       }
+       argv_free(argvp);
+       if (test_panic_str) {
+           vstring_free(test_panic_str);
+           test_panic_str = 0;
+       }
+    }
+    msg_info("PASS=%d FAIL=%d", pass, fail);
+    exit(fail != 0);
+}
+
+#endif
index 1e3b4670542081c51983b2a3066dfa4e9c1629c2..b0098ce1303ab1f5ea0d55232c2f5bb48c6ec528 100644 (file)
@@ -20,8 +20,12 @@ typedef struct ARGV {
     char  **argv;                      /* string array */
 } ARGV;
 
+typedef int (*ARGV_COMPAR_FN)(const void *, const void *);
+
 extern ARGV *argv_alloc(ssize_t);
-extern ARGV *argv_sort(ARGV *);
+extern ARGV *argv_sort(ARGV *);                /* backwards compatibility */
+extern ARGV *argv_qsort(ARGV *, ARGV_COMPAR_FN);
+extern ARGV *argv_uniq(ARGV *, ARGV_COMPAR_FN);
 extern void argv_add(ARGV *,...);
 extern void argv_addn(ARGV *,...);
 extern void argv_terminate(ARGV *);
@@ -64,6 +68,11 @@ extern ARGV *argv_split_at_append(ARGV *, const char *, int);
 /*     IBM T.J. Watson Research
 /*     P.O. Box 704
 /*     Yorktown Heights, NY 10598, USA
+/*
+/*     Wietse Venema
+/*     Google, Inc.
+/*     111 8th Avenue
+/*     New York, NY 10011, USA
 /*--*/
 
 #endif
index cb17601c571161d7668fd81f76ffd16d2c1aeb61..35c02db050195afa4bc8aa53d4bbef36aa998a67 100644 (file)
 /*     IBM T.J. Watson Research
 /*     P.O. Box 704
 /*     Yorktown Heights, NY 10598, USA
+/*
+/*     Wietse Venema
+/*     Google, Inc.
+/*     111 8th Avenue
+/*     New York, NY 10011, USA
 /*--*/
 
 /* System libraries. */
index 4f0cab81ad42c5e93bdde3445041a1307ac96fb2..217deb7a6287fd8670dbd2cbfec4b3473a8e50c0 100644 (file)
@@ -232,10 +232,16 @@ extern int dict_error(const char *);
   * Low-level interface, with physical dictionary handles.
   */
 typedef DICT *(*DICT_OPEN_FN) (const char *, int, int);
-typedef DICT_OPEN_FN (*DICT_OPEN_EXTEND_FN) (const char *);
+typedef struct {
+    const char *type;
+    DICT_OPEN_FN dict_fn;
+    struct MKMAP *(*mkmap_fn) (const char *);
+} DICT_OPEN_INFO;
+typedef const DICT_OPEN_INFO *(*DICT_OPEN_EXTEND_FN) (const char *);
 extern DICT *dict_open(const char *, int, int);
 extern DICT *dict_open3(const char *, const char *, int, int);
-extern void dict_open_register(const char *, DICT_OPEN_FN);
+extern void dict_open_register(const DICT_OPEN_INFO *);
+extern const DICT_OPEN_INFO *dict_open_lookup(const char *);
 extern DICT_OPEN_EXTEND_FN dict_open_extend(DICT_OPEN_EXTEND_FN);
 
 #define dict_get(dp, key)      ((const char *) (dp)->lookup((dp), (key)))
index e2c13d470516575394adb3dc68779b8d9c36587e..696ffbf46f304bfc76913995e81f4dadeeccdf65 100644 (file)
@@ -15,6 +15,7 @@
   * Utility library.
   */
 #include <dict.h>
+#include <mkmap.h>
 
  /*
   * External interface.
@@ -22,6 +23,7 @@
 #define DICT_TYPE_CDB "cdb"
 
 extern DICT *dict_cdb_open(const char *, int, int);
+extern MKMAP *mkmap_cdb_open(const char *);
 
 /* LICENSE
 /* .ad
@@ -32,6 +34,11 @@ extern DICT *dict_cdb_open(const char *, int, int);
 /*     IBM T.J. Watson Research
 /*     P.O. Box 704
 /*     Yorktown Heights, NY 10598, USA
+/*
+/*     Wietse Venema
+/*     Google, Inc.
+/*     111 8th Avenue
+/*     New York, NY 10011, USA
 /*--*/
 
 #endif /* _DICT_CDB_H_INCLUDED_ */
index cc14dc83314c471f983711ed6e2d9bfc1b764954..0030f73b6407e0e69fa5fb8c6181426fcea56006 100644 (file)
@@ -15,6 +15,7 @@
   * Utility library.
   */
 #include <dict.h>
+#include <mkmap.h>
 
  /*
   * External interface.
@@ -24,6 +25,8 @@
 
 extern DICT *dict_hash_open(const char *, int, int);
 extern DICT *dict_btree_open(const char *, int, int);
+extern MKMAP *mkmap_hash_open(const char *);
+extern MKMAP *mkmap_btree_open(const char *);
 
  /*
   * XXX Should be part of the DICT interface.
index ecaab62b7991fc5cbda9fe1fe3207af03cf4ce95..f954255cd12c26ba680ea5b3275e0f7a3e7832a9 100644 (file)
@@ -15,6 +15,7 @@
   * Utility library.
   */
 #include <dict.h>
+#include <mkmap.h>
 
  /*
   * External interface.
@@ -22,6 +23,7 @@
 #define DICT_TYPE_DBM  "dbm"
 
 extern DICT *dict_dbm_open(const char *, int, int);
+extern MKMAP *mkmap_dbm_open(const char *);
 
 /* LICENSE
 /* .ad
@@ -32,6 +34,11 @@ extern DICT *dict_dbm_open(const char *, int, int);
 /*     IBM T.J. Watson Research
 /*     P.O. Box 704
 /*     Yorktown Heights, NY 10598, USA
+/*
+/*     Wietse Venema
+/*     Google, Inc.
+/*     111 8th Avenue
+/*     New York, NY 10011, USA
 /*--*/
 
 #endif
index b42a31bcd4fe7558e643053b17548d5c0e9eba3a..046ff68608304c7c1c4254974aede16601a93489 100644 (file)
@@ -15,6 +15,7 @@
   * Utility library.
   */
 #include <dict.h>
+#include <mkmap.h>
 
  /*
   * External interface.
@@ -22,6 +23,7 @@
 #define DICT_TYPE_FAIL "fail"
 
 extern DICT *dict_fail_open(const char *, int, int);
+extern MKMAP *mkmap_fail_open(const char *);
 
 /* LICENSE
 /* .ad
@@ -30,6 +32,11 @@ extern DICT *dict_fail_open(const char *, int, int);
 /* AUTHOR(S)
 /*     jeffm
 /*     ghostgun.com
+/*
+/*     Wietse Venema
+/*     Google, Inc.
+/*     111 8th Avenue
+/*     New York, NY 10011, USA
 /*--*/
 
 #endif
index ccc165ac0481986d282dbcaae011cae67235a9ee..026bab5f84c5a614a25ee39a4e9cf7fc8eb34cd9 100644 (file)
@@ -15,6 +15,7 @@
   * Utility library.
   */
 #include <dict.h>
+#include <mkmap.h>
 
  /*
   * External interface.
@@ -22,6 +23,7 @@
 #define DICT_TYPE_LMDB "lmdb"
 
 extern DICT *dict_lmdb_open(const char *, int, int);
+extern MKMAP *mkmap_lmdb_open(const char *);
 
  /*
   * XXX Should be part of the DICT interface.
@@ -38,6 +40,11 @@ extern size_t dict_lmdb_map_size;
 /* AUTHOR(S)
 /*     Howard Chu
 /*     Symas Corporation
+/*
+/*     Wietse Venema
+/*     Google, Inc.
+/*     111 8th Avenue
+/*     New York, NY 10011, USA
 /*--*/
 
 #endif
index afea3917f05496cc9a0c2a398fca6f414064cfa3..c3b90d497f9e8fe1e14b1d0174b4ee2b2e557778 100644 (file)
 /*     void    dict_close(dict)
 /*     DICT    *dict;
 /*
+/*     typedef struct {
+/* .in +4
+/*         char   *type;
+/*         DICT_OPEN_FN dict_fn;
+/*         MKMAP_OPEN_FN mkmap_fn;     /* See <mkmap.h> */
+/* .in -4
+/*     } DICT_OPEN_INFO;
+/*
 /*     typedef DICT *(*DICT_OPEN_FN) (const char *, int, int);
 /*
-/*     dict_open_register(type, open)
-/*     const char *type;
-/*     DICT_OPEN_FN open;
+/*     void    dict_open_register(open_info)
+/*     DICT_OPEN_INFO *open_info;
+/*
+/*     const DICT_OPEN_INFO *dict_open_lookup(dict_type)
+/*     const char *dict_type;
 /*
-/*     typedef DICT_OPEN_FN (*DICT_OPEN_EXTEND_FN)(const char *type);
+/*     typedef DICT_OPEN_INFO (*DICT_OPEN_EXTEND_FN)(char *);
 /*
 /*     DICT_OPEN_EXTEND_FN dict_open_extend(call_back)
 /*     DICT_OPEN_EXTEND_FN call_back;
 /*     associated data structures.
 /*
 /*     dict_open_register() adds support for a new dictionary type.
+/*     NOTE: this function does not copy its argument.
+/*
+/*     dict_open_lookup() returns a pointer to the DICT_OPEN_INFO
+/*     for the specified dictionary type, or a null pointer if the
+/*     requested information is not found.
 /*
 /*     dict_open_extend() registers a call-back function that looks
 /*     up the dictionary open() function for a type that is not
 #include <split_at.h>
 #include <htable.h>
 #include <myflock.h>
+#include <mkmap.h>
 
  /*
   * lookup table for available map types.
   */
-typedef struct {
-    char   *type;
-    DICT_OPEN_FN open;
-} DICT_OPEN_INFO;
-
 static const DICT_OPEN_INFO dict_open_info[] = {
-    DICT_TYPE_ENVIRON, dict_env_open,
-    DICT_TYPE_HT, dict_ht_open,
-    DICT_TYPE_UNIX, dict_unix_open,
-    DICT_TYPE_TCP, dict_tcp_open,
+    DICT_TYPE_ENVIRON, dict_env_open, 0,
+    DICT_TYPE_HT, dict_ht_open, 0,
+    DICT_TYPE_UNIX, dict_unix_open, 0,
+    DICT_TYPE_TCP, dict_tcp_open, 0,
 #ifdef HAS_DBM
-    DICT_TYPE_DBM, dict_dbm_open,
+    DICT_TYPE_DBM, dict_dbm_open, mkmap_dbm_open,
 #endif
 #ifdef HAS_DB
-    DICT_TYPE_HASH, dict_hash_open,
-    DICT_TYPE_BTREE, dict_btree_open,
+    DICT_TYPE_HASH, dict_hash_open, mkmap_hash_open,
+    DICT_TYPE_BTREE, dict_btree_open, mkmap_btree_open,
 #endif
 #ifdef HAS_NIS
-    DICT_TYPE_NIS, dict_nis_open,
+    DICT_TYPE_NIS, dict_nis_open, 0,
 #endif
 #ifdef HAS_NISPLUS
-    DICT_TYPE_NISPLUS, dict_nisplus_open,
+    DICT_TYPE_NISPLUS, dict_nisplus_open, 0,
 #endif
 #ifdef HAS_NETINFO
-    DICT_TYPE_NETINFO, dict_ni_open,
+    DICT_TYPE_NETINFO, dict_ni_open, 0,
 #endif
 #ifdef HAS_POSIX_REGEXP
-    DICT_TYPE_REGEXP, dict_regexp_open,
+    DICT_TYPE_REGEXP, dict_regexp_open, 0,
 #endif
-    DICT_TYPE_STATIC, dict_static_open,
-    DICT_TYPE_CIDR, dict_cidr_open,
-    DICT_TYPE_THASH, dict_thash_open,
-    DICT_TYPE_SOCKMAP, dict_sockmap_open,
-    DICT_TYPE_FAIL, dict_fail_open,
-    DICT_TYPE_PIPE, dict_pipe_open,
-    DICT_TYPE_RANDOM, dict_random_open,
-    DICT_TYPE_UNION, dict_union_open,
-    DICT_TYPE_INLINE, dict_inline_open,
+    DICT_TYPE_STATIC, dict_static_open, 0,
+    DICT_TYPE_CIDR, dict_cidr_open, 0,
+    DICT_TYPE_THASH, dict_thash_open, 0,
+    DICT_TYPE_SOCKMAP, dict_sockmap_open, 0,
+    DICT_TYPE_FAIL, dict_fail_open, mkmap_fail_open,
+    DICT_TYPE_PIPE, dict_pipe_open, 0,
+    DICT_TYPE_RANDOM, dict_random_open, 0,
+    DICT_TYPE_UNION, dict_union_open, 0,
+    DICT_TYPE_INLINE, dict_inline_open, 0,
 #ifndef USE_DYNAMIC_MAPS
 #ifdef HAS_PCRE
-    DICT_TYPE_PCRE, dict_pcre_open,
+    DICT_TYPE_PCRE, dict_pcre_open, 0,
 #endif
 #ifdef HAS_CDB
-    DICT_TYPE_CDB, dict_cdb_open,
+    DICT_TYPE_CDB, dict_cdb_open, mkmap_cdb_open,
 #endif
 #ifdef HAS_SDBM
-    DICT_TYPE_SDBM, dict_sdbm_open,
+    DICT_TYPE_SDBM, dict_sdbm_open, mkmap_sdbm_open,
 #endif
 #ifdef HAS_LMDB
-    DICT_TYPE_LMDB, dict_lmdb_open,
+    DICT_TYPE_LMDB, dict_lmdb_open, mkmap_lmdb_open,
 #endif
 #endif                                 /* !USE_DYNAMIC_MAPS */
     0,
@@ -416,11 +427,19 @@ static DICT_OPEN_EXTEND_FN dict_open_extend_hook;
 static DICT_MAPNAMES_EXTEND_FN dict_mapnames_extend_hook;
 
  /*
-  * Workaround.
+  * Workaround: define global variables here to control database cache sizes.
+  * When a database driver is dynamically loaded, global control variables
+  * cannot simply be owned by the loadable objects because that would result
+  * in build-time linker errors.
   */
 DEFINE_DICT_LMDB_MAP_SIZE;
 DEFINE_DICT_DB_CACHE_SIZE;
 
+ /*
+  * Replace obscure code with a more readable expression.
+  */
+#define NEED_DICT_OPEN_INIT()  (dict_open_hash == 0)
+
 /* dict_open_init - one-off initialization */
 
 static void dict_open_init(void)
@@ -428,7 +447,7 @@ static void dict_open_init(void)
     const char *myname = "dict_open_init";
     const DICT_OPEN_INFO *dp;
 
-    if (dict_open_hash != 0)
+    if (!NEED_DICT_OPEN_INIT())
        msg_panic("%s: multiple initialization", myname);
     dict_open_hash = htable_create(10);
 
@@ -453,33 +472,24 @@ DICT   *dict_open(const char *dict_spec, int open_flags, int dict_flags)
     return (dict);
 }
 
-
 /* dict_open3 - open dictionary */
 
 DICT   *dict_open3(const char *dict_type, const char *dict_name,
                           int open_flags, int dict_flags)
 {
     const char *myname = "dict_open";
-    DICT_OPEN_INFO *dp;
-    DICT_OPEN_FN open_fn;
+    const DICT_OPEN_INFO *dp;
     DICT   *dict;
 
     if (*dict_type == 0 || *dict_name == 0)
        msg_fatal("open dictionary: expecting \"type:name\" form instead of \"%s:%s\"",
                  dict_type, dict_name);
-    if (dict_open_hash == 0)
+    if (NEED_DICT_OPEN_INIT())
        dict_open_init();
-    if ((dp = (DICT_OPEN_INFO *) htable_find(dict_open_hash, dict_type)) == 0) {
-       if (dict_open_extend_hook != 0
-           && (open_fn = dict_open_extend_hook(dict_type)) != 0) {
-           dict_open_register(dict_type, open_fn);
-           dp = (DICT_OPEN_INFO *) htable_find(dict_open_hash, dict_type);
-       }
-       if (dp == 0)
-           return (dict_surrogate(dict_type, dict_name, open_flags, dict_flags,
+    if ((dp = dict_open_lookup(dict_type)) == 0)
+       return (dict_surrogate(dict_type, dict_name, open_flags, dict_flags,
                             "unsupported dictionary type: %s", dict_type));
-    }
-    if ((dict = dp->open(dict_name, open_flags, dict_flags)) == 0)
+    if ((dict = dp->dict_fn(dict_name, open_flags, dict_flags)) == 0)
        return (dict_surrogate(dict_type, dict_name, open_flags, dict_flags,
                            "cannot open %s:%s: %m", dict_type, dict_name));
     if (msg_verbose)
@@ -508,20 +518,33 @@ DICT   *dict_open3(const char *dict_type, const char *dict_name,
 
 /* dict_open_register - register dictionary type */
 
-void    dict_open_register(const char *type, DICT_OPEN_FN open)
+void    dict_open_register(const DICT_OPEN_INFO *dp)
 {
     const char *myname = "dict_open_register";
-    DICT_OPEN_INFO *dp;
-    HTABLE_INFO *ht;
 
-    if (dict_open_hash == 0)
+    if (msg_verbose > 1)
+       msg_info("%s: %s", myname, dp->type);
+    if (NEED_DICT_OPEN_INIT())
        dict_open_init();
-    if (htable_find(dict_open_hash, type))
-       msg_panic("%s: dictionary type exists: %s", myname, type);
-    dp = (DICT_OPEN_INFO *) mymalloc(sizeof(*dp));
-    dp->open = open;
-    ht = htable_enter(dict_open_hash, type, (void *) dp);
-    dp->type = ht->key;
+    if (htable_find(dict_open_hash, dp->type))
+       msg_panic("%s: dictionary type exists: %s", myname, dp->type);
+    (void) htable_enter(dict_open_hash, dp->type, (void *) dp);
+}
+
+/* dict_open_lookup - look up DICT_OPEN_INFO for dictionary type */
+
+const DICT_OPEN_INFO *dict_open_lookup(const char *dict_type)
+{
+    const char myname[] = "dict_open_lookup";
+    const DICT_OPEN_INFO *dp;
+
+    if (msg_verbose > 1)
+       msg_info("%s: %s", myname, dict_type);
+    if ((dp = (DICT_OPEN_INFO *) htable_find(dict_open_hash, dict_type)) == 0
+       && dict_open_extend_hook != 0
+       && (dp = dict_open_extend_hook(dict_type)) != 0)
+       dict_open_register(dp);
+    return (dp);
 }
 
 /* dict_open_extend - register alternate dictionary search routine */
@@ -535,13 +558,6 @@ DICT_OPEN_EXTEND_FN dict_open_extend(DICT_OPEN_EXTEND_FN new_cb)
     return (old_cb);
 }
 
-/* dict_sort_alpha_cpp - qsort() callback */
-
-static int dict_sort_alpha_cpp(const void *a, const void *b)
-{
-    return (strcmp(((char **) a)[0], ((char **) b)[0]));
-}
-
 /* dict_mapnames - return an ARGV of available map_names */
 
 ARGV   *dict_mapnames()
@@ -551,7 +567,7 @@ ARGV   *dict_mapnames()
     DICT_OPEN_INFO *dp;
     ARGV   *mapnames;
 
-    if (dict_open_hash == 0)
+    if (NEED_DICT_OPEN_INIT())
        dict_open_init();
     mapnames = argv_alloc(dict_open_hash->used + 1);
     for (ht_info = ht = htable_list(dict_open_hash); *ht; ht++) {
@@ -560,8 +576,9 @@ ARGV   *dict_mapnames()
     }
     if (dict_mapnames_extend_hook != 0)
        (void) dict_mapnames_extend_hook(mapnames);
-    qsort((void *) mapnames->argv, mapnames->argc, sizeof(mapnames->argv[0]),
-         dict_sort_alpha_cpp);
+    argv_qsort(mapnames, (ARGV_COMPAR_FN) 0);
+    /* In case some drivers have been loaded dynamically. */
+    argv_uniq(mapnames, (ARGV_COMPAR_FN) 0);
     myfree((void *) ht_info);
     argv_terminate(mapnames);
     return mapnames;
index 6a1b281eadf7e46189a147d1b6efde16707e8f66..57b458c97e527b725f1eed70a06b2f921b54fb93 100644 (file)
@@ -15,6 +15,7 @@
   * Utility library.
   */
 #include <dict.h>
+#include <mkmap.h>
 
  /*
   * External interface.
@@ -22,6 +23,7 @@
 #define DICT_TYPE_SDBM "sdbm"
 
 extern DICT *dict_sdbm_open(const char *, int, int);
+extern MKMAP *mkmap_sdbm_open(const char *);
 
 /* LICENSE
 /* .ad
@@ -32,6 +34,11 @@ extern DICT *dict_sdbm_open(const char *, int, int);
 /*     IBM T.J. Watson Research
 /*     P.O. Box 704
 /*     Yorktown Heights, NY 10598, USA
+/*
+/*     Wietse Venema
+/*     Google, Inc.
+/*     111 8th Avenue
+/*     New York, NY 10011, USA
 /*--*/
 
 #endif
diff --git a/postfix/src/util/mkmap.h b/postfix/src/util/mkmap.h
new file mode 100644 (file)
index 0000000..01c09f2
--- /dev/null
@@ -0,0 +1,50 @@
+#ifndef _MKMAP_H_INCLUDED_
+#define _MKMAP_H_INCLUDED_
+
+/*++
+/* NAME
+/*     mkmap 3h
+/* SUMMARY
+/*     create or rewrite Postfix database
+/* SYNOPSIS
+/*     #include <mkmap.h>
+/* DESCRIPTION
+/* .nf
+
+ /*
+  * We try to open and lock a file before DB/DBM initialization. However, if
+  * the file does not exist then we may have to acquire the lock after the
+  * DB/DBM initialization.
+  */
+typedef struct MKMAP {
+    struct DICT *(*open) (const char *, int, int);     /* dict_xx_open() */
+    struct DICT *dict;                 /* dict_xx_open() result */
+    void    (*after_open) (struct MKMAP *);    /* may be null */
+    void    (*after_close) (struct MKMAP *);   /* may be null */
+    int     multi_writer;              /* multi-writer safe */
+} MKMAP;
+
+extern MKMAP *mkmap_open(const char *, const char *, int, int);
+extern void mkmap_close(MKMAP *);
+
+#define mkmap_append(map, key, val) dict_put((map)->dict, (key), (val))
+
+typedef MKMAP *(*MKMAP_OPEN_FN) (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
+/*
+/*     Wietse Venema
+/*     Google, Inc.
+/*     111 8th Avenue
+/*     New York, NY 10011, USA
+/*--*/
+
+#endif
similarity index 92%
rename from postfix/src/global/mkmap_cdb.c
rename to postfix/src/util/mkmap_cdb.c
index 83bf96d37c977ad59bf831129b3334bcb063deb9..abb2c7d411f0087697b6d73c0ac4de84cccb7d4c 100644 (file)
@@ -4,7 +4,7 @@
 /* SUMMARY
 /*     create or open database, CDB style
 /* SYNOPSIS
-/*     #include <mkmap.h>
+/*     #include <dict_cdb.h>
 /*
 /*     MKMAP   *mkmap_cdb_open(path)
 /*     const char *path;
 /*     IBM T.J. Watson Research
 /*     P.O. Box 704
 /*     Yorktown Heights, NY 10598, USA
+/*
+/*     Wietse Venema
+/*     Google, Inc.
+/*     111 8th Avenue
+/*     New York, NY 10011, USA
 /*--*/
 
 /* System library. */
 /* Utility library. */
 
 #include <mymalloc.h>
-#include <dict.h>
-
-/* Application-specific. */
-
-#include "mkmap.h"
 #include <dict_cdb.h>
 
 /* This is a dummy module, since CDB has all the functionality
similarity index 81%
rename from postfix/src/global/mkmap_db.c
rename to postfix/src/util/mkmap_db.c
index d2c87efd53c0ecec397a894fbb16facf9cedf2fa..b2d830f807e5268d1f287f99cfead91f250f52be 100644 (file)
@@ -4,7 +4,7 @@
 /* SUMMARY
 /*     create or open database, DB style
 /* SYNOPSIS
-/*     #include <mkmap.h>
+/*     #include <dict_db.h>
 /*
 /*     MKMAP   *mkmap_hash_open(path)
 /*     const char *path;
 /*     IBM T.J. Watson Research
 /*     P.O. Box 704
 /*     Yorktown Heights, NY 10598, USA
+/*
+/*     Wietse Venema
+/*     Google, Inc.
+/*     111 8th Avenue
+/*     New York, NY 10011, USA
 /*--*/
 
 /* System library. */
 #include <msg.h>
 #include <mymalloc.h>
 #include <stringops.h>
-#include <dict.h>
 #include <dict_db.h>
 #include <myflock.h>
 #include <warn_stat.h>
 
-/* Global library. */
-
-#include <mail_params.h>
-
-/* Application-specific. */
-
-#include "mkmap.h"
-
 #ifdef HAS_DB
 #ifdef PATH_DB_H
 #include PATH_DB_H
@@ -104,24 +100,9 @@ static MKMAP *mkmap_db_before_open(const char *path,
     struct stat st;
 
     /*
-     * Override the default per-table cache size for map (re)builds.
-     * 
-     * db_cache_size" is defined in util/dict_db.c and defaults to 128kB, which
-     * works well for the lookup code.
-     * 
-     * We use a larger per-table cache when building ".db" files. For "hash"
-     * files performance degrades rapidly unless the memory pool is O(file
-     * size).
-     * 
-     * For "btree" files performance is good with sorted input even for small
-     * memory pools, but with random input degrades rapidly unless the memory
-     * pool is O(file size).
-     * 
-     * XXX This should be specified via the DICT interface so that the buffer
-     * size becomes an object property, instead of being specified by poking
-     * a global variable so that it becomes a class property.
+     * Assumes that  dict_db_cache_size = var_db_create_buf was done in the
+     * caller, because this code has no access to Postfix variables.
      */
-    dict_db_cache_size = var_db_create_buf;
 
     /*
      * Fill in the generic members.
similarity index 96%
rename from postfix/src/global/mkmap_dbm.c
rename to postfix/src/util/mkmap_dbm.c
index 1db588bab4107cfe3e6b45bdb8080b38b0e4fb98..b1314781c520e22968e154a3166b8e55e5f0e266 100644 (file)
@@ -4,7 +4,7 @@
 /* SUMMARY
 /*     create or open database, DBM style
 /* SYNOPSIS
-/*     #include <mkmap.h>
+/*     #include <dict_dbm.h>
 /*
 /*     MKMAP   *mkmap_dbm_open(path)
 /*     const char *path;
 /*     IBM T.J. Watson Research
 /*     P.O. Box 704
 /*     Yorktown Heights, NY 10598, USA
+/*
+/*     Wietse Venema
+/*     Google, Inc.
+/*     111 8th Avenue
+/*     New York, NY 10011, USA
 /*--*/
 
 /* System library. */
 #include <msg.h>
 #include <mymalloc.h>
 #include <stringops.h>
-#include <dict.h>
 #include <dict_dbm.h>
 #include <myflock.h>
 
-/* Application-specific. */
-
-#include "mkmap.h"
-
 #ifdef HAS_DBM
 #ifdef PATH_NDBM_H
 #include PATH_NDBM_H
similarity index 89%
rename from postfix/src/global/mkmap_fail.c
rename to postfix/src/util/mkmap_fail.c
index c35fe50db9d47f97ea9b629d0714151a8e613722..b2a22971a666978a36e718579882c680b8e6957b 100644 (file)
@@ -4,7 +4,7 @@
 /* SUMMARY
 /*     create or open database, fail: style
 /* SYNOPSIS
-/*     #include <mkmap.h>
+/*     #include <dict_fail.h>
 /*
 /*     MKMAP   *mkmap_fail_open(path)
 /*     const char *path;
 /*     IBM T.J. Watson Research
 /*     P.O. Box 704
 /*     Yorktown Heights, NY 10598, USA
+/*
+/*     Wietse Venema
+/*     Google, Inc.
+/*     111 8th Avenue
+/*     New York, NY 10011, USA
 /*--*/
 
 /* System library. */
 /* Utility library. */
 
 #include <mymalloc.h>
-#include <dict.h>
-
-/* Application-specific. */
-
-#include <mkmap.h>
 #include <dict_fail.h>
 
  /*
similarity index 83%
rename from postfix/src/global/mkmap_lmdb.c
rename to postfix/src/util/mkmap_lmdb.c
index 9aebd25c88c4f5edaebdc8e2bad7936ea2296ca4..ac8b2115b3a7938ec33b16dcd16ae81f674a6d79 100644 (file)
@@ -4,7 +4,7 @@
 /* SUMMARY
 /*     create or open database, LMDB style
 /* SYNOPSIS
-/*     #include <mkmap.h>
+/*     #include <dict_lmdb.h>
 /*
 /*     MKMAP   *mkmap_lmdb_open(path)
 /*     const char *path;
 /* AUTHOR(S)
 /*     Howard Chu
 /*     Symas Corporation
+/*
+/*     Wietse Venema
+/*     Google, Inc.
+/*     111 8th Avenue
+/*     New York, NY 10011, USA
 /*--*/
 
 /* System library. */
 
 /* Utility library. */
 
-#include <msg.h>
 #include <mymalloc.h>
-#include <stringops.h>
-#include <dict.h>
 #include <dict_lmdb.h>
-#include <myflock.h>
-#include <warn_stat.h>
+#include <mkmap.h>
 
 #ifdef HAS_LMDB
 #ifdef PATH_LMDB_H
 #include <lmdb.h>
 #endif
 
-/* Global library. */
-
-#include <mail_conf.h>
-#include <mail_params.h>
-
-/* Application-specific. */
-
-#include "mkmap.h"
-
 /* mkmap_lmdb_open */
 
 MKMAP  *mkmap_lmdb_open(const char *path)
similarity index 55%
rename from postfix/src/global/mkmap_open.c
rename to postfix/src/util/mkmap_open.c
index 9d15eec30a27f0557c590458e1cddc165ad45e01..961f54403ece2458849a1ebfd4cc27e85407e46d 100644 (file)
@@ -7,8 +7,8 @@
 /*     #include <mkmap.h>
 /*
 /*     typedef struct MKMAP {
-/*         DICT_OPEN_FN open;                          /* dict_xx_open() */
-/*         DICT *dict;                                 /* dict_xx_open() result */
+/*         struct DICT *(*open) (const char *, int, int); /* dict_xx_open() */
+/*         struct DICT *dict;                          /* dict_xx_open() result */
 /*         void    (*after_open) (struct MKMAP *);     /* may be null */
 /*         void    (*after_close) (struct MKMAP *);    /* may be null */
 /*         int     multi_writer;                       /* multi-writer safe */
 /*
 /*     void    mkmap_close(mkmap)
 /*     MKMAP   *mkmap;
-/*
-/*     typedef MKMAP *(*MKMAP_OPEN_FN) (const char *);
-/*     typedef MKMAP_OPEN_FN *(*MKMAP_OPEN_EXTEND_FN) (const char *);
-/*
-/*     void    mkmap_open_register(type, open_fn)
-/*     const char *type;
-/*     MKMAP_OPEN_FN open_fn;
-/*
-/*     MKMAP_OPEN_EXTEND_FN mkmap_open_extend(call_back)
-/*     MKMAP_OPEN_EXTEND_FN call_back;
 /* DESCRIPTION
 /*     This module implements support for creating Postfix databases.
 /*     It is a dict(3) wrapper that adds global locking to dict-level
 /*
 /*     mkmap_close() closes the database, releases any locks,
 /*     and resumes signal delivery. All errors are fatal.
-/*
-/*     mkmap_open_register() adds support for a new database type.
-/*
-/*     mkmap_open_extend() registers a call-back function that looks
-/*     up the mkmap open() function for a database type that is not
-/*     registered, or null in case of error. The result value is the
-/*     last previously-registered call-back or null. A mkmap open()
-/*     function is cached after it is looked up through this extension
-/*     mechanism.
 /* SEE ALSO
 /*     sigdelay(3) suspend/resume signal delivery
 /* LICENSE
 /*     IBM T.J. Watson Research
 /*     P.O. Box 704
 /*     Yorktown Heights, NY 10598, USA
+/*
+/*     Wietse Venema
+/*     Google, Inc.
+/*     111 8th Avenue
+/*     New York, NY 10011, USA
 /*--*/
 
 /* System library. */
 /* Utility library. */
 
 #include <msg.h>
-#include <htable.h>
 #include <dict.h>
-#include <dict_db.h>
-#include <dict_cdb.h>
-#include <dict_dbm.h>
-#include <dict_lmdb.h>
-#include <dict_sdbm.h>
-#include <dict_proxy.h>
-#include <dict_fail.h>
 #include <sigdelay.h>
 #include <mymalloc.h>
 #include <stringops.h>
-
-/* Global library. */
-
-#include "mkmap.h"
-
- /*
-  * Information about available database types. Here, we list only those map
-  * types that support "bulk create" operations.
-  * 
-  * We use a different table (in dict_open.c and mail_dict.c) when querying maps
-  * or when making incremental updates.
-  */
-typedef struct {
-    const char *type;
-    MKMAP_OPEN_FN before_open;
-} MKMAP_OPEN_INFO;
-
-static const MKMAP_OPEN_INFO mkmap_open_info[] = {
-#ifndef USE_DYNAMIC_MAPS
-#ifdef HAS_CDB
-    DICT_TYPE_CDB, mkmap_cdb_open,
-#endif
-#ifdef HAS_SDBM
-    DICT_TYPE_SDBM, mkmap_sdbm_open,
-#endif
-#ifdef HAS_LMDB
-    DICT_TYPE_LMDB, mkmap_lmdb_open,
-#endif
-#endif                                 /* !USE_DYNAMIC_MAPS */
-#ifdef HAS_DBM
-    DICT_TYPE_DBM, mkmap_dbm_open,
-#endif
-#ifdef HAS_DB
-    DICT_TYPE_HASH, mkmap_hash_open,
-    DICT_TYPE_BTREE, mkmap_btree_open,
-#endif
-    DICT_TYPE_FAIL, mkmap_fail_open,
-    0,
-};
-
-static HTABLE *mkmap_open_hash;
-
-static MKMAP_OPEN_EXTEND_FN mkmap_open_extend_hook = 0;
-
-/* mkmap_open_init - one-off initialization */
-
-static void mkmap_open_init(void)
-{
-    static const char myname[] = "mkmap_open_init";
-    const MKMAP_OPEN_INFO *mp;
-
-    if (mkmap_open_hash != 0)
-       msg_panic("%s: multiple initialization", myname);
-    mkmap_open_hash = htable_create(10);
-
-    for (mp = mkmap_open_info; mp->type; mp++)
-       htable_enter(mkmap_open_hash, mp->type, (void *) mp);
-}
-
-/* mkmap_open_register - register dictionary type */
-
-void    mkmap_open_register(const char *type, MKMAP_OPEN_FN open_fn)
-{
-    static const char myname[] = "mkmap_open_register";
-    MKMAP_OPEN_INFO *mp;
-    HTABLE_INFO *ht;
-
-    if (mkmap_open_hash == 0)
-       mkmap_open_init();
-    if (htable_find(mkmap_open_hash, type))
-       msg_panic("%s: database type exists: %s", myname, type);
-    mp = (MKMAP_OPEN_INFO *) mymalloc(sizeof(*mp));
-    mp->before_open = open_fn;
-    ht = htable_enter(mkmap_open_hash, type, (void *) mp);
-    mp->type = ht->key;
-}
-
-/* mkmap_open_extend - register alternate lookup function */
-
-MKMAP_OPEN_EXTEND_FN mkmap_open_extend(MKMAP_OPEN_EXTEND_FN new_cb)
-{
-    MKMAP_OPEN_EXTEND_FN old_cb;
-
-    old_cb = mkmap_open_extend_hook;
-    mkmap_open_extend_hook = new_cb;
-    return (old_cb);
-}
-
-/* mkmap_append - append entry to map */
-
-#undef mkmap_append
-
-void    mkmap_append(MKMAP *mkmap, const char *key, const char *value)
-{
-    DICT   *dict = mkmap->dict;
-
-    if (dict_put(dict, key, value) != 0 && dict->error != 0)
-       msg_fatal("%s:%s: update failed", dict->type, dict->name);
-}
+#include <mkmap.h>
 
 /* mkmap_close - close database */
 
@@ -238,23 +118,15 @@ MKMAP  *mkmap_open(const char *type, const char *path,
                           int open_flags, int dict_flags)
 {
     MKMAP  *mkmap;
-    const MKMAP_OPEN_INFO *mp;
-    MKMAP_OPEN_FN open_fn;
+    const DICT_OPEN_INFO *dp;
 
     /*
      * Find out what map type to use.
      */
-    if (mkmap_open_hash == 0)
-       mkmap_open_init();
-    if ((mp = (MKMAP_OPEN_INFO *) htable_find(mkmap_open_hash, type)) == 0) {
-       if (mkmap_open_extend_hook != 0 &&
-           (open_fn = mkmap_open_extend_hook(type)) != 0) {
-           mkmap_open_register(type, open_fn);
-           mp = (MKMAP_OPEN_INFO *) htable_find(mkmap_open_hash, type);
-       }
-       if (mp == 0)
-           msg_fatal("unsupported map type for this operation: %s", type);
-    }
+    if ((dp = dict_open_lookup(type)) == 0)
+       msg_fatal("unsupported map type: %s", type);
+    if (dp->mkmap_fn == 0)
+       msg_fatal("no 'map create' support for this type: %s", type);
     if (msg_verbose)
        msg_info("open %s %s", type, path);
 
@@ -264,7 +136,7 @@ MKMAP  *mkmap_open(const char *type, const char *path,
      * dict modules implement locking only for individual record operations,
      * because most Postfix applications don't need global exclusive locks.
      */
-    mkmap = mp->before_open(path);
+    mkmap = dp->mkmap_fn(path);
 
     /*
      * Delay signal delivery, so that we won't leave the database in an
similarity index 96%
rename from postfix/src/global/mkmap_sdbm.c
rename to postfix/src/util/mkmap_sdbm.c
index 7e87e4e823e2a78584c274dc549c0162d9d364cd..54608f1510b58b4339bfae0dd046c98646d20f52 100644 (file)
@@ -4,7 +4,7 @@
 /* SUMMARY
 /*     create or open database, SDBM style
 /* SYNOPSIS
-/*     #include <mkmap.h>
+/*     #include <dict_sdbm.h>
 /*
 /*     MKMAP   *mkmap_sdbm_open(path)
 /*     const char *path;
 /*     IBM T.J. Watson Research
 /*     P.O. Box 704
 /*     Yorktown Heights, NY 10598, USA
+/*
+/*     Wietse Venema
+/*     Google, Inc.
+/*     111 8th Avenue
+/*     New York, NY 10011, USA
 /*--*/
 
 /* System library. */
 #include <msg.h>
 #include <mymalloc.h>
 #include <stringops.h>
-#include <dict.h>
 #include <dict_sdbm.h>
 #include <myflock.h>
 
-/* Application-specific. */
-
-#include "mkmap.h"
-
 #ifdef HAS_SDBM
 
 #include <sdbm.h>