From 926448aed51b57c3e2f3077de33c924cd93d6695 Mon Sep 17 00:00:00 2001 From: Wietse Venema Date: Sat, 7 May 2022 00:00:00 -0500 Subject: [PATCH] postfix-3.8-20220507 --- postfix/HISTORY | 108 +++++- postfix/INSTALL | 2 +- postfix/Makefile.in | 9 +- postfix/README_FILES/INSTALL | 2 +- postfix/README_FILES/IPV6_README | 6 +- postfix/RELEASE_NOTES | 8 + postfix/WISHLIST | 7 +- postfix/html/INSTALL.html | 2 +- postfix/html/IPV6_README.html | 7 +- postfix/html/postconf.5.html | 20 +- postfix/man/man5/postconf.5 | 18 +- postfix/mantools/check-double-history | 7 + postfix/mantools/check-spell-history | 9 + postfix/proto/INSTALL.html | 2 +- postfix/proto/IPV6_README.html | 7 +- postfix/proto/postconf.proto | 20 +- postfix/proto/stop.double-cc | 1 + postfix/proto/stop.double-history | 10 + postfix/proto/stop.spell-cc | 2 + postfix/proto/stop.spell-history | 21 ++ postfix/src/cleanup/cleanup_map1n.c | 2 +- postfix/src/global/Makefile.in | 150 +------- postfix/src/global/compat_level.c | 4 +- postfix/src/global/compat_level.h | 2 - postfix/src/global/dict_proxy.h | 7 + postfix/src/global/dynamicmaps.c | 149 ++++---- postfix/src/global/header_body_checks.h | 5 + postfix/src/global/mail_dict.c | 24 +- postfix/src/global/mail_version.h | 2 +- postfix/src/global/maps.c | 5 + postfix/src/global/mkmap.h | 64 ---- postfix/src/global/mkmap_proxy.c | 11 +- postfix/src/postalias/Makefile.in | 1 + postfix/src/postalias/postalias.c | 20 +- postfix/src/postconf/Makefile.in | 1 + postfix/src/postmap/Makefile.in | 1 + postfix/src/postmap/postmap.c | 24 +- postfix/src/postscreen/postscreen_smtpd.c | 2 +- postfix/src/proxymap/Makefile.in | 1 + postfix/src/smtp/Makefile.in | 1 + postfix/src/util/Makefile.in | 164 ++++++++- postfix/src/util/argv.c | 403 +++++++++++++++++++++- postfix/src/util/argv.h | 11 +- postfix/src/util/dict.c | 5 + postfix/src/util/dict.h | 10 +- postfix/src/util/dict_cdb.h | 7 + postfix/src/util/dict_db.h | 3 + postfix/src/util/dict_dbm.h | 7 + postfix/src/util/dict_fail.h | 7 + postfix/src/util/dict_lmdb.h | 7 + postfix/src/util/dict_open.c | 155 +++++---- postfix/src/util/dict_sdbm.h | 7 + postfix/src/util/mkmap.h | 50 +++ postfix/src/{global => util}/mkmap_cdb.c | 12 +- postfix/src/{global => util}/mkmap_db.c | 35 +- postfix/src/{global => util}/mkmap_dbm.c | 12 +- postfix/src/{global => util}/mkmap_fail.c | 12 +- postfix/src/{global => util}/mkmap_lmdb.c | 22 +- postfix/src/{global => util}/mkmap_open.c | 156 +-------- postfix/src/{global => util}/mkmap_sdbm.c | 12 +- 60 files changed, 1194 insertions(+), 647 deletions(-) create mode 100755 postfix/mantools/check-double-history create mode 100755 postfix/mantools/check-spell-history create mode 100644 postfix/proto/stop.double-history create mode 100644 postfix/proto/stop.spell-history delete mode 100644 postfix/src/global/mkmap.h create mode 100644 postfix/src/util/mkmap.h rename postfix/src/{global => util}/mkmap_cdb.c (92%) rename postfix/src/{global => util}/mkmap_db.c (81%) rename postfix/src/{global => util}/mkmap_dbm.c (96%) rename postfix/src/{global => util}/mkmap_fail.c (89%) rename postfix/src/{global => util}/mkmap_lmdb.c (83%) rename postfix/src/{global => util}/mkmap_open.c (55%) rename postfix/src/{global => util}/mkmap_sdbm.c (96%) diff --git a/postfix/HISTORY b/postfix/HISTORY index 867090235..3da460d7d 100644 --- a/postfix/HISTORY +++ b/postfix/HISTORY @@ -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. diff --git a/postfix/INSTALL b/postfix/INSTALL index 4ab046d40..17a8cf744 100644 --- a/postfix/INSTALL +++ b/postfix/INSTALL @@ -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. | diff --git a/postfix/Makefile.in b/postfix/Makefile.in index aa6c7ad9c..5bc7a7cb1 100644 --- a/postfix/Makefile.in +++ b/postfix/Makefile.in @@ -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 diff --git a/postfix/README_FILES/INSTALL b/postfix/README_FILES/INSTALL index e9d4f0695..e97c95c2d 100644 --- a/postfix/README_FILES/INSTALL +++ b/postfix/README_FILES/INSTALL @@ -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. | diff --git a/postfix/README_FILES/IPV6_README b/postfix/README_FILES/IPV6_README index a29560c47..188003be8 100644 --- a/postfix/README_FILES/IPV6_README +++ b/postfix/README_FILES/IPV6_README @@ -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. CCoonnffiigguurraattiioonn @@ -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: diff --git a/postfix/RELEASE_NOTES b/postfix/RELEASE_NOTES index 84541eda0..d49dbde13 100644 --- a/postfix/RELEASE_NOTES +++ b/postfix/RELEASE_NOTES @@ -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. diff --git a/postfix/WISHLIST b/postfix/WISHLIST index 4dccddda9..d0c3589c4 100644 --- a/postfix/WISHLIST +++ b/postfix/WISHLIST @@ -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: + WARN_IF_REJECT like prefix that disables the error counter increment. diff --git a/postfix/html/INSTALL.html b/postfix/html/INSTALL.html index 2070e3467..acf7b5572 100644 --- a/postfix/html/INSTALL.html +++ b/postfix/html/INSTALL.html @@ -837,7 +837,7 @@ unreachable code. -DNO_IPV6 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. diff --git a/postfix/html/IPV6_README.html b/postfix/html/IPV6_README.html index acf24b901..0b6b79359 100644 --- a/postfix/html/IPV6_README.html +++ b/postfix/html/IPV6_README.html @@ -78,8 +78,8 @@ 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.

Configuration

@@ -128,6 +128,9 @@ on a software distribution with IPv6 support, "ipv4" otherwise.

"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 diff --git a/postfix/html/postconf.5.html b/postfix/html/postconf.5.html index 837a5d38a..acfea50b1 100644 --- a/postfix/html/postconf.5.html +++ b/postfix/html/postconf.5.html @@ -4047,6 +4047,16 @@ environment. Examples of relevant environment variables:

    Needed to make "postfix -c" work.
    +
    POSTLOG_SERVICE
    + +
    Needed to make "maillog_file" work during daemon +process initialization.
    + +
    POSTLOG_HOSTNAME
    + +
    Needed to make "maillog_file" work during daemon +process initialization.
    +

    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.

    -

    An address is always considered "known" when it matches a -virtual(5) alias or a canonical(5) mapping. +

    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:

      @@ -16639,8 +16650,9 @@ sender addresses, even when no explicit virtual(5) alias or a canonical(5) mapping. +

      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:

        diff --git a/postfix/man/man5/postconf.5 b/postfix/man/man5/postconf.5 index 4ad946652..10d2e67d3 100644 --- a/postfix/man/man5/postconf.5 +++ b/postfix/man/man5/postconf.5 @@ -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 index 000000000..26e85c09c --- /dev/null +++ b/postfix/mantools/check-double-history @@ -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 index 000000000..242130c24 --- /dev/null +++ b/postfix/mantools/check-spell-history @@ -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 diff --git a/postfix/proto/INSTALL.html b/postfix/proto/INSTALL.html index 71bcc4ffb..756012ede 100644 --- a/postfix/proto/INSTALL.html +++ b/postfix/proto/INSTALL.html @@ -837,7 +837,7 @@ unreachable code. -DNO_IPV6 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. diff --git a/postfix/proto/IPV6_README.html b/postfix/proto/IPV6_README.html index 01ea51bae..f4cebda69 100644 --- a/postfix/proto/IPV6_README.html +++ b/postfix/proto/IPV6_README.html @@ -78,8 +78,8 @@ 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.

        Configuration

        @@ -128,6 +128,9 @@ inet_protocols configuration parameter.

        "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 diff --git a/postfix/proto/postconf.proto b/postfix/proto/postconf.proto index 7dfb60548..28ff0965a 100644 --- a/postfix/proto/postconf.proto +++ b/postfix/proto/postconf.proto @@ -1957,6 +1957,16 @@ environment. Examples of relevant environment variables:

        Needed to make "postfix -c" work.
        +
        POSTLOG_SERVICE
        + +
        Needed to make "maillog_file" work during daemon +process initialization.
        + +
        POSTLOG_HOSTNAME
        + +
        Needed to make "maillog_file" work during daemon +process initialization.
        +

        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.

        -

        An address is always considered "known" when it matches a -virtual(5) alias or a canonical(5) mapping. +

        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:

          @@ -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.

          -

          An address is always considered "known" when it matches a -virtual(5) alias or a canonical(5) mapping. +

          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:

            diff --git a/postfix/proto/stop.double-cc b/postfix/proto/stop.double-cc index 6bdd97f3a..ceddb7f5c 100644 --- a/postfix/proto/stop.double-cc +++ b/postfix/proto/stop.double-cc @@ -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 index 000000000..f143392c6 --- /dev/null +++ b/postfix/proto/stop.double-history @@ -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 diff --git a/postfix/proto/stop.spell-cc b/postfix/proto/stop.spell-cc index 10f22509a..ea6ad0038 100644 --- a/postfix/proto/stop.spell-cc +++ b/postfix/proto/stop.spell-cc @@ -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 index 000000000..16c43bfd2 --- /dev/null +++ b/postfix/proto/stop.spell-history @@ -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 diff --git a/postfix/src/cleanup/cleanup_map1n.c b/postfix/src/cleanup/cleanup_map1n.c index 9cecfcb59..2c8413b65 100644 --- a/postfix/src/cleanup/cleanup_map1n.c +++ b/postfix/src/cleanup/cleanup_map1n.c @@ -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 { \ diff --git a/postfix/src/global/Makefile.in b/postfix/src/global/Makefile.in index 0944a75a9..86390ede2 100644 --- a/postfix/src/global/Makefile.in +++ b/postfix/src/global/Makefile.in @@ -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 diff --git a/postfix/src/global/compat_level.c b/postfix/src/global/compat_level.c index 74308787c..af1cbbfcf 100644 --- a/postfix/src/global/compat_level.c +++ b/postfix/src/global/compat_level.c @@ -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: diff --git a/postfix/src/global/compat_level.h b/postfix/src/global/compat_level.h index 076e887e2..80f2a0765 100644 --- a/postfix/src/global/compat_level.h +++ b/postfix/src/global/compat_level.h @@ -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 diff --git a/postfix/src/global/dict_proxy.h b/postfix/src/global/dict_proxy.h index a5b79243a..67954f595 100644 --- a/postfix/src/global/dict_proxy.h +++ b/postfix/src/global/dict_proxy.h @@ -15,6 +15,7 @@ * Utility library. */ #include +#include /* * 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 diff --git a/postfix/src/global/dynamicmaps.c b/postfix/src/global/dynamicmaps.c index f0213d39d..0b66ab9f8 100644 --- a/postfix/src/global/dynamicmaps.c +++ b/postfix/src/global/dynamicmaps.c @@ -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 @@ -34,14 +37,19 @@ /* /* 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 @@ -56,6 +64,11 @@ /* 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 #include #include +#include #include #include #include @@ -86,7 +100,6 @@ /* * Global library. */ -#include #include #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. */ diff --git a/postfix/src/global/header_body_checks.h b/postfix/src/global/header_body_checks.h index 7a2718e05..b8838dbaa 100644 --- a/postfix/src/global/header_body_checks.h +++ b/postfix/src/global/header_body_checks.h @@ -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 diff --git a/postfix/src/global/mail_dict.c b/postfix/src/global/mail_dict.c index 6d6d729f2..c640a807a 100644 --- a/postfix/src/global/mail_dict.c +++ b/postfix/src/global/mail_dict.c @@ -25,6 +25,11 @@ /* 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. */ @@ -51,28 +56,23 @@ #include #include -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 diff --git a/postfix/src/global/mail_version.h b/postfix/src/global/mail_version.h index 4728aa874..567892093 100644 --- a/postfix/src/global/mail_version.h +++ b/postfix/src/global/mail_version.h @@ -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 diff --git a/postfix/src/global/maps.c b/postfix/src/global/maps.c index 7c84e9aa0..790396bba 100644 --- a/postfix/src/global/maps.c +++ b/postfix/src/global/maps.c @@ -95,6 +95,11 @@ /* 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 index e49311474..000000000 --- a/postfix/src/global/mkmap.h +++ /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 -/* DESCRIPTION -/* .nf - - /* - * Utility library. - */ -#include - - /* - * 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 diff --git a/postfix/src/global/mkmap_proxy.c b/postfix/src/global/mkmap_proxy.c index e4f4f34f1..ddfc708c2 100644 --- a/postfix/src/global/mkmap_proxy.c +++ b/postfix/src/global/mkmap_proxy.c @@ -4,7 +4,7 @@ /* SUMMARY /* create or proxied database /* SYNOPSIS -/* #include +/* #include /* /* MKMAP *mkmap_proxy_open(path) /* const char *path; @@ -26,6 +26,11 @@ /* 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. */ @@ -37,10 +42,6 @@ #include #include -/* Application-specific. */ - -#include "mkmap.h" - /* mkmap_proxy_open - create or open database */ MKMAP *mkmap_proxy_open(const char *unused_path) diff --git a/postfix/src/postalias/Makefile.in b/postfix/src/postalias/Makefile.in index 5e5b72dca..9c124e5c0 100644 --- a/postfix/src/postalias/Makefile.in +++ b/postfix/src/postalias/Makefile.in @@ -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 diff --git a/postfix/src/postalias/postalias.c b/postfix/src/postalias/postalias.c index 95388836a..d17e397de 100644 --- a/postfix/src/postalias/postalias.c +++ b/postfix/src/postalias/postalias.c @@ -264,6 +264,7 @@ #include #include #include +#include /* Global library. */ @@ -272,7 +273,6 @@ #include #include #include -#include #include #include #include @@ -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. diff --git a/postfix/src/postconf/Makefile.in b/postfix/src/postconf/Makefile.in index 60c797a73..4f6536fd3 100644 --- a/postfix/src/postconf/Makefile.in +++ b/postfix/src/postconf/Makefile.in @@ -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 diff --git a/postfix/src/postmap/Makefile.in b/postfix/src/postmap/Makefile.in index dc5369d9b..aac92717c 100644 --- a/postfix/src/postmap/Makefile.in +++ b/postfix/src/postmap/Makefile.in @@ -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 diff --git a/postfix/src/postmap/postmap.c b/postfix/src/postmap/postmap.c index 66421d008..2826fc6b6 100644 --- a/postfix/src/postmap/postmap.c +++ b/postfix/src/postmap/postmap.c @@ -343,6 +343,7 @@ #include #include #include +#include /* Global library. */ @@ -350,7 +351,6 @@ #include #include #include -#include #include #include #include @@ -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) { diff --git a/postfix/src/postscreen/postscreen_smtpd.c b/postfix/src/postscreen/postscreen_smtpd.c index edd5d7105..dfc5d544a 100644 --- a/postfix/src/postscreen/postscreen_smtpd.c +++ b/postfix/src/postscreen/postscreen_smtpd.c @@ -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")); diff --git a/postfix/src/proxymap/Makefile.in b/postfix/src/proxymap/Makefile.in index 925f98ffa..7ff2910a8 100644 --- a/postfix/src/proxymap/Makefile.in +++ b/postfix/src/proxymap/Makefile.in @@ -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 diff --git a/postfix/src/smtp/Makefile.in b/postfix/src/smtp/Makefile.in index 65f41982f..6412e0e36 100644 --- a/postfix/src/smtp/Makefile.in +++ b/postfix/src/smtp/Makefile.in @@ -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 diff --git a/postfix/src/util/Makefile.in b/postfix/src/util/Makefile.in index bfe146f5c..cdc671cff 100644 --- a/postfix/src/util/Makefile.in +++ b/postfix/src/util/Makefile.in @@ -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 diff --git a/postfix/src/util/argv.c b/postfix/src/util/argv.c index a364e2439..4e05fd0b4 100644 --- a/postfix/src/util/argv.c +++ b/postfix/src/util/argv.c @@ -6,11 +6,18 @@ /* SYNOPSIS /* #include /* +/* 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; @@ -64,8 +71,15 @@ /* 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. @@ -116,6 +130,11 @@ /* 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. */ @@ -131,6 +150,12 @@ #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 + + /* + * Utility library. + */ +#include +#include + +#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 diff --git a/postfix/src/util/argv.h b/postfix/src/util/argv.h index 1e3b46705..b0098ce13 100644 --- a/postfix/src/util/argv.h +++ b/postfix/src/util/argv.h @@ -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 diff --git a/postfix/src/util/dict.c b/postfix/src/util/dict.c index cb17601c5..35c02db05 100644 --- a/postfix/src/util/dict.c +++ b/postfix/src/util/dict.c @@ -240,6 +240,11 @@ /* 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. */ diff --git a/postfix/src/util/dict.h b/postfix/src/util/dict.h index 4f0cab81a..217deb7a6 100644 --- a/postfix/src/util/dict.h +++ b/postfix/src/util/dict.h @@ -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))) diff --git a/postfix/src/util/dict_cdb.h b/postfix/src/util/dict_cdb.h index e2c13d470..696ffbf46 100644 --- a/postfix/src/util/dict_cdb.h +++ b/postfix/src/util/dict_cdb.h @@ -15,6 +15,7 @@ * Utility library. */ #include +#include /* * 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_ */ diff --git a/postfix/src/util/dict_db.h b/postfix/src/util/dict_db.h index cc14dc833..0030f73b6 100644 --- a/postfix/src/util/dict_db.h +++ b/postfix/src/util/dict_db.h @@ -15,6 +15,7 @@ * Utility library. */ #include +#include /* * 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. diff --git a/postfix/src/util/dict_dbm.h b/postfix/src/util/dict_dbm.h index ecaab62b7..f954255cd 100644 --- a/postfix/src/util/dict_dbm.h +++ b/postfix/src/util/dict_dbm.h @@ -15,6 +15,7 @@ * Utility library. */ #include +#include /* * 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 diff --git a/postfix/src/util/dict_fail.h b/postfix/src/util/dict_fail.h index b42a31bcd..046ff6860 100644 --- a/postfix/src/util/dict_fail.h +++ b/postfix/src/util/dict_fail.h @@ -15,6 +15,7 @@ * Utility library. */ #include +#include /* * 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 diff --git a/postfix/src/util/dict_lmdb.h b/postfix/src/util/dict_lmdb.h index ccc165ac0..026bab5f8 100644 --- a/postfix/src/util/dict_lmdb.h +++ b/postfix/src/util/dict_lmdb.h @@ -15,6 +15,7 @@ * Utility library. */ #include +#include /* * 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 diff --git a/postfix/src/util/dict_open.c b/postfix/src/util/dict_open.c index afea3917f..c3b90d497 100644 --- a/postfix/src/util/dict_open.c +++ b/postfix/src/util/dict_open.c @@ -39,13 +39,23 @@ /* void dict_close(dict) /* DICT *dict; /* +/* typedef struct { +/* .in +4 +/* char *type; +/* DICT_OPEN_FN dict_fn; +/* MKMAP_OPEN_FN mkmap_fn; /* See */ +/* .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; /* -/* typedef DICT_OPEN_FN (*DICT_OPEN_EXTEND_FN)(const char *type); +/* const DICT_OPEN_INFO *dict_open_lookup(dict_type) +/* const char *dict_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; @@ -238,6 +248,11 @@ /* 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 @@ -348,60 +363,56 @@ #include #include #include +#include /* * 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; diff --git a/postfix/src/util/dict_sdbm.h b/postfix/src/util/dict_sdbm.h index 6a1b281ea..57b458c97 100644 --- a/postfix/src/util/dict_sdbm.h +++ b/postfix/src/util/dict_sdbm.h @@ -15,6 +15,7 @@ * Utility library. */ #include +#include /* * 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 index 000000000..01c09f231 --- /dev/null +++ b/postfix/src/util/mkmap.h @@ -0,0 +1,50 @@ +#ifndef _MKMAP_H_INCLUDED_ +#define _MKMAP_H_INCLUDED_ + +/*++ +/* NAME +/* mkmap 3h +/* SUMMARY +/* create or rewrite Postfix database +/* SYNOPSIS +/* #include +/* 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 diff --git a/postfix/src/global/mkmap_cdb.c b/postfix/src/util/mkmap_cdb.c similarity index 92% rename from postfix/src/global/mkmap_cdb.c rename to postfix/src/util/mkmap_cdb.c index 83bf96d37..abb2c7d41 100644 --- a/postfix/src/global/mkmap_cdb.c +++ b/postfix/src/util/mkmap_cdb.c @@ -4,7 +4,7 @@ /* SUMMARY /* create or open database, CDB style /* SYNOPSIS -/* #include +/* #include /* /* MKMAP *mkmap_cdb_open(path) /* const char *path; @@ -32,6 +32,11 @@ /* 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. */ @@ -43,11 +48,6 @@ /* Utility library. */ #include -#include - -/* Application-specific. */ - -#include "mkmap.h" #include /* This is a dummy module, since CDB has all the functionality diff --git a/postfix/src/global/mkmap_db.c b/postfix/src/util/mkmap_db.c similarity index 81% rename from postfix/src/global/mkmap_db.c rename to postfix/src/util/mkmap_db.c index d2c87efd5..b2d830f80 100644 --- a/postfix/src/global/mkmap_db.c +++ b/postfix/src/util/mkmap_db.c @@ -4,7 +4,7 @@ /* SUMMARY /* create or open database, DB style /* SYNOPSIS -/* #include +/* #include /* /* MKMAP *mkmap_hash_open(path) /* const char *path; @@ -30,6 +30,11 @@ /* 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. */ @@ -44,19 +49,10 @@ #include #include #include -#include #include #include #include -/* Global library. */ - -#include - -/* 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. diff --git a/postfix/src/global/mkmap_dbm.c b/postfix/src/util/mkmap_dbm.c similarity index 96% rename from postfix/src/global/mkmap_dbm.c rename to postfix/src/util/mkmap_dbm.c index 1db588bab..b1314781c 100644 --- a/postfix/src/global/mkmap_dbm.c +++ b/postfix/src/util/mkmap_dbm.c @@ -4,7 +4,7 @@ /* SUMMARY /* create or open database, DBM style /* SYNOPSIS -/* #include +/* #include /* /* MKMAP *mkmap_dbm_open(path) /* const char *path; @@ -28,6 +28,11 @@ /* 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. */ @@ -40,14 +45,9 @@ #include #include #include -#include #include #include -/* Application-specific. */ - -#include "mkmap.h" - #ifdef HAS_DBM #ifdef PATH_NDBM_H #include PATH_NDBM_H diff --git a/postfix/src/global/mkmap_fail.c b/postfix/src/util/mkmap_fail.c similarity index 89% rename from postfix/src/global/mkmap_fail.c rename to postfix/src/util/mkmap_fail.c index c35fe50db..b2a22971a 100644 --- a/postfix/src/global/mkmap_fail.c +++ b/postfix/src/util/mkmap_fail.c @@ -4,7 +4,7 @@ /* SUMMARY /* create or open database, fail: style /* SYNOPSIS -/* #include +/* #include /* /* MKMAP *mkmap_fail_open(path) /* const char *path; @@ -23,6 +23,11 @@ /* 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. */ @@ -32,11 +37,6 @@ /* Utility library. */ #include -#include - -/* Application-specific. */ - -#include #include /* diff --git a/postfix/src/global/mkmap_lmdb.c b/postfix/src/util/mkmap_lmdb.c similarity index 83% rename from postfix/src/global/mkmap_lmdb.c rename to postfix/src/util/mkmap_lmdb.c index 9aebd25c8..ac8b2115b 100644 --- a/postfix/src/global/mkmap_lmdb.c +++ b/postfix/src/util/mkmap_lmdb.c @@ -4,7 +4,7 @@ /* SUMMARY /* create or open database, LMDB style /* SYNOPSIS -/* #include +/* #include /* /* MKMAP *mkmap_lmdb_open(path) /* const char *path; @@ -26,6 +26,11 @@ /* AUTHOR(S) /* Howard Chu /* Symas Corporation +/* +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA /*--*/ /* System library. */ @@ -37,13 +42,9 @@ /* Utility library. */ -#include #include -#include -#include #include -#include -#include +#include #ifdef HAS_LMDB #ifdef PATH_LMDB_H @@ -52,15 +53,6 @@ #include #endif -/* Global library. */ - -#include -#include - -/* Application-specific. */ - -#include "mkmap.h" - /* mkmap_lmdb_open */ MKMAP *mkmap_lmdb_open(const char *path) diff --git a/postfix/src/global/mkmap_open.c b/postfix/src/util/mkmap_open.c similarity index 55% rename from postfix/src/global/mkmap_open.c rename to postfix/src/util/mkmap_open.c index 9d15eec30..961f54403 100644 --- a/postfix/src/global/mkmap_open.c +++ b/postfix/src/util/mkmap_open.c @@ -7,8 +7,8 @@ /* #include /* /* 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 */ @@ -28,16 +28,6 @@ /* /* 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 @@ -57,15 +47,6 @@ /* /* 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 @@ -77,6 +58,11 @@ /* 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. */ @@ -88,117 +74,11 @@ /* Utility library. */ #include -#include #include -#include -#include -#include -#include -#include -#include -#include #include #include #include - -/* 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_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 diff --git a/postfix/src/global/mkmap_sdbm.c b/postfix/src/util/mkmap_sdbm.c similarity index 96% rename from postfix/src/global/mkmap_sdbm.c rename to postfix/src/util/mkmap_sdbm.c index 7e87e4e82..54608f151 100644 --- a/postfix/src/global/mkmap_sdbm.c +++ b/postfix/src/util/mkmap_sdbm.c @@ -4,7 +4,7 @@ /* SUMMARY /* create or open database, SDBM style /* SYNOPSIS -/* #include +/* #include /* /* MKMAP *mkmap_sdbm_open(path) /* const char *path; @@ -28,6 +28,11 @@ /* 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. */ @@ -40,14 +45,9 @@ #include #include #include -#include #include #include -/* Application-specific. */ - -#include "mkmap.h" - #ifdef HAS_SDBM #include