From: Wietse Venema
Date: Wed, 15 Dec 2004 05:00:00 +0000 (-0500)
Subject: postfix-2.2-20041215
X-Git-Tag: v2.2.0-RC1~24
X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=9ef211dc61e3e78296d1a48ac9271da3fef4dc92;p=thirdparty%2Fpostfix.git
postfix-2.2-20041215
---
diff --git a/postfix/HISTORY b/postfix/HISTORY
index ac72609b5..67a0f671c 100644
--- a/postfix/HISTORY
+++ b/postfix/HISTORY
@@ -9926,6 +9926,39 @@ Apologies for any names omitted.
Hexadecimal encode/decode routines, from the TLS-enabled
version. Files: util/hext_code.[hc].
+20041212
+
+ Solaris 10/ix86 chroot setup script update by J.D. Bronson.
+
+20041213
+
+ Updated the SDBM dictionary interface. It had fallen behind
+ with the Postfix dictionary interfaces that were already
+ bundled with Postfix. Files: util/dict_sdbm.[hc].
+
+ Cleanup: "postconf -m" (show all available map types) now
+ produces sorted output. File: util/dict_open.c.
+
+20041215
+
+ No bugfix: tests with the new "postmap -s" feature show
+ that SDBM first/next operations never worked with Postfix/TLS
+ patch 20040829 (verified with the 20040829 dict_sdbm.c
+ module on Linux and FreeBSD). The code stops after finding
+ one database element. Other SDBM versions found on the
+ Internet will find all database entries, but report an I/O
+ error after the last database element is found. All this
+ would be easy enough to fix, but the SDBM library is not
+ part of Postfix, and never will be.
+
+ Bugfix: the sequence operator in the DBM and SDBM clients
+ released the shared lock after reading the next key but
+ before reading the corresponding value. This was never a
+ problem, because the sequence operator was used only in
+ the Postfix/TLS patch. This used the SDBM sequence operator
+ which didn't work as discussed above. Files: util/dict_dbm.c,
+ util/dict_sdbm.c.
+
Open problems:
Med: implement ${name[?:]value} in main.cf or update the
@@ -10024,9 +10057,6 @@ Open problems:
servers seem to need this in particular. Need a way to
expire cached results that are too old.
- Medium: make address rewriting on/off configurable for
- envelopes and/or headers.
-
Low: generic showq protocol, to allow for more intelligent
processing than just mailq. Maybe marry this with postsuper.
diff --git a/postfix/examples/chroot-setup/Solaris10 b/postfix/examples/chroot-setup/Solaris10
new file mode 100644
index 000000000..a815218f9
--- /dev/null
+++ b/postfix/examples/chroot-setup/Solaris10
@@ -0,0 +1,110 @@
+#!/bin/sh
+# From original Solaris 8 version by Matthew X. Economou
+# Solaris 10 version updated by JD Bronson. Caution: this copies
+# too many files. There is no need to copy libc.so and other files
+# that are already linked in before a Postfix daemon chroots itself.
+
+COMMAND_DIRECTORY="/usr/sbin"
+DAEMON_DIRECTORY="/usr/libexec/postfix"
+QUEUE_DIRECTORY="/var/spool/postfix"
+
+## Copy any shared libraries, device entries, or configuration files
+## needed by Postfix into the jail.
+binlist="
+$DAEMON_DIRECTORY/virtual
+$DAEMON_DIRECTORY/trivial-rewrite
+$DAEMON_DIRECTORY/spawn
+$DAEMON_DIRECTORY/smtpd
+$DAEMON_DIRECTORY/smtp
+$DAEMON_DIRECTORY/showq
+$DAEMON_DIRECTORY/qmqpd
+$DAEMON_DIRECTORY/qmgr
+$DAEMON_DIRECTORY/proxymap
+$DAEMON_DIRECTORY/pipe
+$DAEMON_DIRECTORY/pickup
+$DAEMON_DIRECTORY/nqmgr
+$DAEMON_DIRECTORY/master
+$DAEMON_DIRECTORY/local
+$DAEMON_DIRECTORY/lmtp
+$DAEMON_DIRECTORY/flush
+$DAEMON_DIRECTORY/error
+$DAEMON_DIRECTORY/cleanup
+$DAEMON_DIRECTORY/bounce
+/usr/lib/sendmail
+$COMMAND_DIRECTORY/postsuper
+$COMMAND_DIRECTORY/postqueue
+$COMMAND_DIRECTORY/postmap
+$COMMAND_DIRECTORY/postlog
+$COMMAND_DIRECTORY/postlock
+$COMMAND_DIRECTORY/postkick
+$COMMAND_DIRECTORY/postfix
+$COMMAND_DIRECTORY/postdrop
+$COMMAND_DIRECTORY/postconf
+$COMMAND_DIRECTORY/postcat
+$COMMAND_DIRECTORY/postalias
+"
+ldd $binlist | awk '/[=]>/ { print $3 }' | sort -u | while read i
+do
+ mkdir -p $QUEUE_DIRECTORY`dirname $i`
+ ## Sun's version of tar sucks. We'll have to remove the leading
+ ## slashes from file names ourself, otherwise the copy doesn't
+ ## work.
+ (cd / && tar cphf - `echo $i | sed -e 's/^\///'`) | (cd $QUEUE_DIRECTORY && tar xpf -)
+done
+
+## More stuff for the jail, mostly discovered by inspection
+## (e.g. strings, lsof).
+more="
+/dev/zero
+/dev/null
+/dev/udp6
+/dev/tcp6
+/dev/udp
+/dev/tcp
+/dev/rawip
+/dev/ticlts
+/dev/ticotsord
+/dev/ticots
+/devices/pseudo/mm@0:zero
+/devices/pseudo/mm@0:null
+/devices/pseudo/udp6@0:udp6
+/devices/pseudo/tcp6@0:tcp6
+/devices/pseudo/udp@0:udp
+/devices/pseudo/tcp@0:tcp
+/devices/pseudo/icmp@0:icmp
+/devices/pseudo/tl@0:ticlts
+/devices/pseudo/tl@0:ticotsord
+/devices/pseudo/tl@0:ticots
+/etc/hosts
+/etc/nsswitch.conf
+/etc/netconfig
+/etc/passwd
+/etc/resolv.conf
+/etc/default/init
+/etc/default/nss
+/etc/inet/services
+/etc/inet/hosts
+/etc/services
+/lib/ld.so
+/lib/ld.so.1
+/usr/lib/nss_dns.so.1
+/usr/lib/sparcv9/straddr.so
+/usr/lib/straddr.so
+/usr/lib/straddr.so.2
+/lib/libintl.so
+/lib/libintl.so.1
+/lib/libw.so
+/lib/libw.so.1
+/lib/nss_nis.so.1
+/lib/nss_nisplus.so.1
+/lib/nss_dns.so.1
+/lib/nss_files.so.1
+/usr/share/lib/zoneinfo
+/var/ld/ld.config
+"
+for i in $more; do
+ mkdir -p $QUEUE_DIRECTORY`dirname $i`
+ (cd / && tar cpf - `echo $i | sed -e 's/^\///'`) | (cd $QUEUE_DIRECTORY && tar xpf -)
+done
+
+exit 0
diff --git a/postfix/html/postconf.1.html b/postfix/html/postconf.1.html
index 0398b2c0b..0150a6bb4 100644
--- a/postfix/html/postconf.1.html
+++ b/postfix/html/postconf.1.html
@@ -112,6 +112,10 @@ POSTCONF(1) POSTCONF(1)
The file format is described in reg-
exp_table(5).
+ sdbm An indexed file type based on hashing. This
+ is available only on systems with support
+ for SDBM databases.
+
static (read-only)
A table that always returns its name as
lookup result. For example, static:foobar
diff --git a/postfix/html/postconf.5.html b/postfix/html/postconf.5.html
index 3b5f2f4b2..f36e3b6c8 100644
--- a/postfix/html/postconf.5.html
+++ b/postfix/html/postconf.5.html
@@ -5948,11 +5948,12 @@ Example:
(default: empty)
-If non-empty, filters the SMTP server's list of offered SASL mechanisms.
-Different client and server implementations may support different
-mechanism lists. By default, the client will use the intersection of the
-two. smtp_sasl_mechanism_filter further restricts what server mechanisms
-the client will take into consideration.
+If non-empty, a Postfix SMTP client filter for the remote SMTP
+server's list of offered SASL mechanisms. Different client and
+server implementations may support different mechanism lists. By
+default, the Postfix SMTP client will use the intersection of the
+two. smtp_sasl_mechanism_filter further restricts what server
+mechanisms the client will take into consideration.
Specify mechanism names, "/file/name" patterns or "type:table"
lookup tables. The right-hand side result from "type:table" lookups
diff --git a/postfix/html/smtp.8.html b/postfix/html/smtp.8.html
index 28fc4b42b..46f3659cb 100644
--- a/postfix/html/smtp.8.html
+++ b/postfix/html/smtp.8.html
@@ -173,29 +173,30 @@ SMTP(8) SMTP(8)
Available in Postfix version 2.2 and later:
smtp_sasl_mechanism_filter (empty)
- If non-empty, filters the SMTP server's list of
- offered SASL mechanisms.
+ If non-empty, a Postfix SMTP client filter for the
+ remote SMTP server's list of offered SASL mecha-
+ nisms.
RESOURCE AND RATE CONTROLS
smtp_destination_concurrency_limit ($default_destina-
tion_concurrency_limit)
- The maximal number of parallel deliveries to the
- same destination via the smtp message delivery
+ The maximal number of parallel deliveries to the
+ same destination via the smtp message delivery
transport.
smtp_destination_recipient_limit ($default_destina-
tion_recipient_limit)
- The maximal number of recipients per delivery via
+ The maximal number of recipients per delivery via
the smtp message delivery transport.
smtp_connect_timeout (30s)
- The SMTP client time limit for completing a TCP
+ The SMTP client time limit for completing a TCP
connection, or zero (use the operating system
built-in time limit).
smtp_helo_timeout (300s)
- The SMTP client time limit for sending the HELO or
- EHLO command, and for receiving the initial server
+ The SMTP client time limit for sending the HELO or
+ EHLO command, and for receiving the initial server
response.
smtp_xforward_timeout (300s)
@@ -203,30 +204,30 @@ SMTP(8) SMTP(8)
command, and for receiving the server response.
smtp_mail_timeout (300s)
- The SMTP client time limit for sending the MAIL
- FROM command, and for receiving the server
+ The SMTP client time limit for sending the MAIL
+ FROM command, and for receiving the server
response.
smtp_rcpt_timeout (300s)
- The SMTP client time limit for sending the SMTP
- RCPT TO command, and for receiving the server
+ The SMTP client time limit for sending the SMTP
+ RCPT TO command, and for receiving the server
response.
smtp_data_init_timeout (120s)
- The SMTP client time limit for sending the SMTP
- DATA command, and for receiving the server
+ The SMTP client time limit for sending the SMTP
+ DATA command, and for receiving the server
response.
smtp_data_xfer_timeout (180s)
- The SMTP client time limit for sending the SMTP
+ The SMTP client time limit for sending the SMTP
message content.
smtp_data_done_timeout (600s)
- The SMTP client time limit for sending the SMTP
+ The SMTP client time limit for sending the SMTP
".", and for receiving the server response.
smtp_quit_timeout (300s)
- The SMTP client time limit for sending the QUIT
+ The SMTP client time limit for sending the QUIT
command, and for receiving the server response.
Available in Postfix version 2.1 and later:
@@ -237,77 +238,77 @@ SMTP(8) SMTP(8)
lookups, or zero (no limit).
smtp_mx_session_limit (2)
- The maximal number of SMTP sessions per delivery
- request before giving up or delivering to a fall-
+ The maximal number of SMTP sessions per delivery
+ request before giving up or delivering to a fall-
back relay host, or zero (no limit).
smtp_rset_timeout (20s)
- The SMTP client time limit for sending the RSET
+ The SMTP client time limit for sending the RSET
command, and for receiving the server response.
Available in Postfix version 2.2 and later:
smtp_connection_cache_destinations (empty)
- Permanently enable SMTP connection caching for the
+ Permanently enable SMTP connection caching for the
specified destinations.
smtp_connection_cache_on_demand (yes)
- Temporarily enable SMTP connection caching while a
+ Temporarily enable SMTP connection caching while a
destination has a high volume of mail in the active
queue.
smtp_connection_cache_reuse_limit (10)
When SMTP connection caching is enabled, the number
- of times that an SMTP session is reused before it
+ of times that an SMTP session is reused before it
is closed.
smtp_connection_cache_time_limit (2s)
When SMTP connection caching is enabled, the amount
- of time that an unused SMTP client socket is kept
+ of time that an unused SMTP client socket is kept
open before it is closed.
TROUBLE SHOOTING CONTROLS
debug_peer_level (2)
- The increment in verbose logging level when a
- remote client or server matches a pattern in the
+ The increment in verbose logging level when a
+ remote client or server matches a pattern in the
debug_peer_list parameter.
debug_peer_list (empty)
- Optional list of remote client or server hostname
- or network address patterns that cause the verbose
- logging level to increase by the amount specified
+ Optional list of remote client or server hostname
+ or network address patterns that cause the verbose
+ logging level to increase by the amount specified
in $debug_peer_level.
error_notice_recipient (postmaster)
- The recipient of postmaster notifications about
- mail delivery problems that are caused by policy,
+ The recipient of postmaster notifications about
+ mail delivery problems that are caused by policy,
resource, software or protocol errors.
notify_classes (resource, software)
- The list of error classes that are reported to the
+ The list of error classes that are reported to the
postmaster.
MISCELLANEOUS CONTROLS
best_mx_transport (empty)
- Where the Postfix SMTP client should deliver mail
+ Where the Postfix SMTP client should deliver mail
when it detects a "mail loops back to myself" error
condition.
config_directory (see 'postconf -d' output)
- The default location of the Postfix main.cf and
+ The default location of the Postfix main.cf and
master.cf configuration files.
daemon_timeout (18000s)
- How much time a Postfix daemon process may take to
- handle a request before it is terminated by a
+ How much time a Postfix daemon process may take to
+ handle a request before it is terminated by a
built-in watchdog timer.
disable_dns_lookups (no)
- Disable DNS lookups in the Postfix SMTP and LMTP
+ Disable DNS lookups in the Postfix SMTP and LMTP
clients.
fallback_relay (empty)
- Optional list of relay hosts for SMTP destinations
+ Optional list of relay hosts for SMTP destinations
that can't be found or that are unreachable.
inet_interfaces (all)
@@ -319,25 +320,25 @@ SMTP(8) SMTP(8)
over an internal communication channel.
max_idle (100s)
- The maximum amount of time that an idle Postfix
- daemon process waits for the next service request
+ The maximum amount of time that an idle Postfix
+ daemon process waits for the next service request
before exiting.
max_use (100)
- The maximal number of connection requests before a
+ The maximal number of connection requests before a
Postfix daemon process terminates.
process_id (read-only)
- The process ID of a Postfix command or daemon pro-
+ The process ID of a Postfix command or daemon pro-
cess.
process_name (read-only)
- The process name of a Postfix command or daemon
+ The process name of a Postfix command or daemon
process.
proxy_interfaces (empty)
The network interface addresses that this mail sys-
- tem receives mail on by way of a proxy or network
+ tem receives mail on by way of a proxy or network
address translation unit.
smtp_bind_address (empty)
@@ -345,22 +346,22 @@ SMTP(8) SMTP(8)
client should bind to when making a connection.
smtp_helo_name ($myhostname)
- The hostname to send in the SMTP EHLO or HELO com-
+ The hostname to send in the SMTP EHLO or HELO com-
mand.
smtp_host_lookup (dns)
- What mechanisms when the SMTP client uses to look
+ What mechanisms when the SMTP client uses to look
up a host's IP address.
smtp_randomize_addresses (yes)
- Randomize the order of equal-preference MX host
+ Randomize the order of equal-preference MX host
addresses.
syslog_facility (mail)
The syslog facility of Postfix logging.
syslog_name (postfix)
- The mail system name that is prepended to the pro-
+ The mail system name that is prepended to the pro-
cess name in syslog records, so that "smtpd"
becomes, for example, "postfix/smtpd".
@@ -377,7 +378,7 @@ SMTP(8) SMTP(8)
SASL_README, Postfix SASL howto
LICENSE
- The Secure Mailer license must be distributed with this
+ The Secure Mailer license must be distributed with this
software.
AUTHOR(S)
diff --git a/postfix/man/man1/postconf.1 b/postfix/man/man1/postconf.1
index b2a24623d..24d2114b5 100644
--- a/postfix/man/man1/postconf.1
+++ b/postfix/man/man1/postconf.1
@@ -95,6 +95,9 @@ A lookup table that is implemented via the Postfix
.IP "\fBregexp\fR (read-only)"
A lookup table based on regular expressions. The file format is
described in \fBregexp_table\fR(5).
+.IP \fBsdbm\fR
+An indexed file type based on hashing.
+This is available only on systems with support for SDBM databases.
.IP "\fBstatic\fR (read-only)"
A table that always returns its name as lookup result. For example,
\fBstatic:foobar\fR always returns the string \fBfoobar\fR as lookup
diff --git a/postfix/man/man5/postconf.5 b/postfix/man/man5/postconf.5
index accb79de3..5bf87ce68 100644
--- a/postfix/man/man5/postconf.5
+++ b/postfix/man/man5/postconf.5
@@ -3174,11 +3174,12 @@ smtp_sasl_auth_enable = yes
.ad
.ft R
.SH smtp_sasl_mechanism_filter (default: empty)
-If non-empty, filters the SMTP server's list of offered SASL mechanisms.
-Different client and server implementations may support different
-mechanism lists. By default, the client will use the intersection of the
-two. smtp_sasl_mechanism_filter further restricts what server mechanisms
-the client will take into consideration.
+If non-empty, a Postfix SMTP client filter for the remote SMTP
+server's list of offered SASL mechanisms. Different client and
+server implementations may support different mechanism lists. By
+default, the Postfix SMTP client will use the intersection of the
+two. smtp_sasl_mechanism_filter further restricts what server
+mechanisms the client will take into consideration.
.PP
Specify mechanism names, "/file/name" patterns or "type:table"
lookup tables. The right-hand side result from "type:table" lookups
diff --git a/postfix/man/man8/smtp.8 b/postfix/man/man8/smtp.8
index 83bb849e1..d14b61a70 100644
--- a/postfix/man/man8/smtp.8
+++ b/postfix/man/man8/smtp.8
@@ -165,7 +165,8 @@ to use.
.PP
Available in Postfix version 2.2 and later:
.IP "\fBsmtp_sasl_mechanism_filter (empty)\fR"
-If non-empty, filters the SMTP server's list of offered SASL mechanisms.
+If non-empty, a Postfix SMTP client filter for the remote SMTP
+server's list of offered SASL mechanisms.
.SH "RESOURCE AND RATE CONTROLS"
.na
.nf
diff --git a/postfix/proto/postconf.proto b/postfix/proto/postconf.proto
index 1ced6c059..433b64bcc 100644
--- a/postfix/proto/postconf.proto
+++ b/postfix/proto/postconf.proto
@@ -3730,11 +3730,12 @@ smtp_sasl_security_options = noplaintext
%PARAM smtp_sasl_mechanism_filter
-If non-empty, filters the SMTP server's list of offered SASL mechanisms.
-Different client and server implementations may support different
-mechanism lists. By default, the client will use the intersection of the
-two. smtp_sasl_mechanism_filter further restricts what server mechanisms
-the client will take into consideration.
+If non-empty, a Postfix SMTP client filter for the remote SMTP
+server's list of offered SASL mechanisms. Different client and
+server implementations may support different mechanism lists. By
+default, the Postfix SMTP client will use the intersection of the
+two. smtp_sasl_mechanism_filter further restricts what server
+mechanisms the client will take into consideration.
Specify mechanism names, "/file/name" patterns or "type:table"
lookup tables. The right-hand side result from "type:table" lookups
diff --git a/postfix/src/global/Makefile.in b/postfix/src/global/Makefile.in
index 4adf152e8..0f23fb940 100644
--- a/postfix/src/global/Makefile.in
+++ b/postfix/src/global/Makefile.in
@@ -1070,6 +1070,7 @@ mkmap_open.o: ../../include/argv.h
mkmap_open.o: ../../include/dict_db.h
mkmap_open.o: ../../include/dict_cdb.h
mkmap_open.o: ../../include/dict_dbm.h
+mkmap_open.o: ../../include/dict_sdbm.h
mkmap_open.o: ../../include/sigdelay.h
mkmap_open.o: ../../include/mymalloc.h
mkmap_open.o: mkmap.h
diff --git a/postfix/src/global/mail_version.h b/postfix/src/global/mail_version.h
index 2361aaba1..bf355f8ed 100644
--- a/postfix/src/global/mail_version.h
+++ b/postfix/src/global/mail_version.h
@@ -20,7 +20,7 @@
* Patches change the patchlevel and the release date. Snapshots change the
* release date only.
*/
-#define MAIL_RELEASE_DATE "20041211"
+#define MAIL_RELEASE_DATE "20041215"
#define MAIL_VERSION_NUMBER "2.2"
#define VAR_MAIL_VERSION "mail_version"
diff --git a/postfix/src/global/mkmap.h b/postfix/src/global/mkmap.h
index 848dbc003..45e32c69c 100644
--- a/postfix/src/global/mkmap.h
+++ b/postfix/src/global/mkmap.h
@@ -39,6 +39,7 @@ 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_sdbm_open(const char *);
/* LICENSE
/* .ad
diff --git a/postfix/src/global/mkmap_open.c b/postfix/src/global/mkmap_open.c
index 92ed0f96c..a3caf952f 100644
--- a/postfix/src/global/mkmap_open.c
+++ b/postfix/src/global/mkmap_open.c
@@ -65,6 +65,7 @@
#include
#include
#include
+#include
#include
#include
diff --git a/postfix/src/postconf/postconf.c b/postfix/src/postconf/postconf.c
index 07567361d..8da57e1e2 100644
--- a/postfix/src/postconf/postconf.c
+++ b/postfix/src/postconf/postconf.c
@@ -89,6 +89,9 @@
/* .IP "\fBregexp\fR (read-only)"
/* A lookup table based on regular expressions. The file format is
/* described in \fBregexp_table\fR(5).
+/* .IP \fBsdbm\fR
+/* An indexed file type based on hashing.
+/* This is available only on systems with support for SDBM databases.
/* .IP "\fBstatic\fR (read-only)"
/* A table that always returns its name as lookup result. For example,
/* \fBstatic:foobar\fR always returns the string \fBfoobar\fR as lookup
diff --git a/postfix/src/smtp/smtp.c b/postfix/src/smtp/smtp.c
index 0ecc7140e..9ffad1b5c 100644
--- a/postfix/src/smtp/smtp.c
+++ b/postfix/src/smtp/smtp.c
@@ -141,7 +141,8 @@
/* .PP
/* Available in Postfix version 2.2 and later:
/* .IP "\fBsmtp_sasl_mechanism_filter (empty)\fR"
-/* If non-empty, filters the SMTP server's list of offered SASL mechanisms.
+/* If non-empty, a Postfix SMTP client filter for the remote SMTP
+/* server's list of offered SASL mechanisms.
/* RESOURCE AND RATE CONTROLS
/* .ad
/* .fi
diff --git a/postfix/src/util/dict_dbm.c b/postfix/src/util/dict_dbm.c
index fa58ad004..87e527694 100644
--- a/postfix/src/util/dict_dbm.c
+++ b/postfix/src/util/dict_dbm.c
@@ -213,7 +213,6 @@ static int dict_dbm_delete(DICT *dict, const char *name)
DICT_DBM *dict_dbm = (DICT_DBM *) dict;
datum dbm_key;
int status = 1;
- int flags = 0;
/*
* Sanity check.
@@ -281,7 +280,6 @@ static int dict_dbm_sequence(DICT *dict, int function,
DICT_DBM *dict_dbm = (DICT_DBM *) dict;
datum dbm_key;
datum dbm_value;
- int status = 0;
/*
* Acquire a shared lock.
@@ -304,13 +302,6 @@ static int dict_dbm_sequence(DICT *dict, int function,
msg_panic("%s: invalid function: %d", myname, function);
}
- /*
- * Release the shared lock.
- */
- if ((dict->flags & DICT_FLAG_LOCK)
- && myflock(dict->lock_fd, INTERNAL_LOCK, MYFLOCK_OP_NONE) < 0)
- msg_fatal("%s: unlock dictionary: %m", dict_dbm->dict.name);
-
if (dbm_key.dptr != 0 && dbm_key.dsize > 0) {
/*
@@ -349,6 +340,14 @@ static int dict_dbm_sequence(DICT *dict, int function,
msg_fatal("error seeking %s: %m", dict_dbm->dict.name);
return (1); /* no error: eof/not found */
}
+
+ /*
+ * Release the shared lock.
+ */
+ if ((dict->flags & DICT_FLAG_LOCK)
+ && myflock(dict->lock_fd, INTERNAL_LOCK, MYFLOCK_OP_NONE) < 0)
+ msg_fatal("%s: unlock dictionary: %m", dict_dbm->dict.name);
+
return (0);
}
diff --git a/postfix/src/util/dict_open.c b/postfix/src/util/dict_open.c
index 008d3becb..0a1ff93ab 100644
--- a/postfix/src/util/dict_open.c
+++ b/postfix/src/util/dict_open.c
@@ -42,6 +42,8 @@
/* dict_open_register(type, open)
/* char *type;
/* DICT *(*open) (const char *, int, int);
+/*
+/* ARGV *dict_mapnames()
/* DESCRIPTION
/* This module implements a low-level interface to multiple
/* physical dictionary types.
@@ -135,6 +137,9 @@
/* associated data structures.
/*
/* dict_open_register() adds support for a new dictionary type.
+/*
+/* dict_mapnames() returns a sorted list with the names of all available
+/* dictionary types.
/* DIAGNOSTICS
/* Fatal error: open error, unsupported dictionary type, attempt to
/* update non-writable dictionary.
@@ -153,6 +158,7 @@
#include
#include
+#include
#ifdef STRCASECMP_IN_STRINGS_H
#include
@@ -302,6 +308,13 @@ void dict_open_register(const char *type,
htable_enter(dict_open_hash, dp->type, (char *) dp);
}
+/* 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()
@@ -318,6 +331,8 @@ ARGV *dict_mapnames()
dp = (DICT_OPEN_INFO *) ht[0]->value;
argv_add(mapnames, dp->type, ARGV_END);
}
+ qsort((void *) mapnames->argv, mapnames->argc, sizeof(mapnames->argv[0]),
+ dict_sort_alpha_cpp);
myfree((char *) ht_info);
argv_terminate(mapnames);
return mapnames;
diff --git a/postfix/src/util/dict_sdbm.c b/postfix/src/util/dict_sdbm.c
index d123fcf8d..35ee7782e 100644
--- a/postfix/src/util/dict_sdbm.c
+++ b/postfix/src/util/dict_sdbm.c
@@ -60,9 +60,13 @@
typedef struct {
DICT dict; /* generic members */
SDBM *dbm; /* open database */
- char *path; /* pathname */
+ VSTRING *key_buf; /* key buffer */
+ VSTRING *val_buf; /* result buffer */
} DICT_SDBM;
+#define SCOPY(buf, data, size) \
+ vstring_str(vstring_strncpy(buf ? buf : (buf = vstring_alloc(10)), data, size))
+
/* dict_sdbm_lookup - find database entry */
static const char *dict_sdbm_lookup(DICT *dict, const char *name)
@@ -70,9 +74,14 @@ static const char *dict_sdbm_lookup(DICT *dict, const char *name)
DICT_SDBM *dict_sdbm = (DICT_SDBM *) dict;
datum dbm_key;
datum dbm_value;
- static VSTRING *buf;
const char *result = 0;
+ /*
+ * Sanity check.
+ */
+ if ((dict->flags & (DICT_FLAG_TRY1NULL | DICT_FLAG_TRY0NULL)) == 0)
+ msg_panic("dict_sdbm_lookup: no DICT_FLAG_TRY1NULL | DICT_FLAG_TRY0NULL flag");
+
dict_errno = 0;
/*
@@ -80,7 +89,7 @@ static const char *dict_sdbm_lookup(DICT *dict, const char *name)
*/
if ((dict->flags & DICT_FLAG_LOCK)
&& myflock(dict->lock_fd, INTERNAL_LOCK, MYFLOCK_OP_SHARED) < 0)
- msg_fatal("%s: lock dictionary: %m", dict_sdbm->path);
+ msg_fatal("%s: lock dictionary: %m", dict_sdbm->dict.name);
/*
* See if this DBM file was written with one null byte appended to key
@@ -92,7 +101,7 @@ static const char *dict_sdbm_lookup(DICT *dict, const char *name)
dbm_value = sdbm_fetch(dict_sdbm->dbm, dbm_key);
if (dbm_value.dptr != 0) {
dict->flags &= ~DICT_FLAG_TRY0NULL;
- result = dbm_value.dptr;
+ result = SCOPY(dict_sdbm->val_buf, dbm_value.dptr, dbm_value.dsize);
}
}
@@ -105,11 +114,8 @@ static const char *dict_sdbm_lookup(DICT *dict, const char *name)
dbm_key.dsize = strlen(name);
dbm_value = sdbm_fetch(dict_sdbm->dbm, dbm_key);
if (dbm_value.dptr != 0) {
- if (buf == 0)
- buf = vstring_alloc(10);
- vstring_strncpy(buf, dbm_value.dptr, dbm_value.dsize);
dict->flags &= ~DICT_FLAG_TRY1NULL;
- result = vstring_str(buf);
+ result = SCOPY(dict_sdbm->val_buf, dbm_value.dptr, dbm_value.dsize);
}
}
@@ -118,7 +124,7 @@ static const char *dict_sdbm_lookup(DICT *dict, const char *name)
*/
if ((dict->flags & DICT_FLAG_LOCK)
&& myflock(dict->lock_fd, INTERNAL_LOCK, MYFLOCK_OP_NONE) < 0)
- msg_fatal("%s: unlock dictionary: %m", dict_sdbm->path);
+ msg_fatal("%s: unlock dictionary: %m", dict_sdbm->dict.name);
return (result);
}
@@ -132,6 +138,12 @@ static void dict_sdbm_update(DICT *dict, const char *name, const char *value)
datum dbm_value;
int status;
+ /*
+ * Sanity check.
+ */
+ if ((dict->flags & (DICT_FLAG_TRY1NULL | DICT_FLAG_TRY0NULL)) == 0)
+ msg_panic("dict_sdbm_update: no DICT_FLAG_TRY1NULL | DICT_FLAG_TRY0NULL flag");
+
dbm_key.dptr = (void *) name;
dbm_value.dptr = (void *) value;
dbm_key.dsize = strlen(name);
@@ -163,21 +175,21 @@ static void dict_sdbm_update(DICT *dict, const char *name, const char *value)
*/
if ((dict->flags & DICT_FLAG_LOCK)
&& myflock(dict->lock_fd, INTERNAL_LOCK, MYFLOCK_OP_EXCLUSIVE) < 0)
- msg_fatal("%s: lock dictionary: %m", dict_sdbm->path);
+ msg_fatal("%s: lock dictionary: %m", dict_sdbm->dict.name);
/*
* Do the update.
*/
if ((status = sdbm_store(dict_sdbm->dbm, dbm_key, dbm_value,
(dict->flags & DICT_FLAG_DUP_REPLACE) ? DBM_REPLACE : DBM_INSERT)) < 0)
- msg_fatal("error writing SDBM database %s: %m", dict_sdbm->path);
+ msg_fatal("error writing SDBM database %s: %m", dict_sdbm->dict.name);
if (status) {
if (dict->flags & DICT_FLAG_DUP_IGNORE)
/* void */ ;
else if (dict->flags & DICT_FLAG_DUP_WARN)
- msg_warn("%s: duplicate entry: \"%s\"", dict_sdbm->path, name);
+ msg_warn("%s: duplicate entry: \"%s\"", dict_sdbm->dict.name, name);
else
- msg_fatal("%s: duplicate entry: \"%s\"", dict_sdbm->path, name);
+ msg_fatal("%s: duplicate entry: \"%s\"", dict_sdbm->dict.name, name);
}
/*
@@ -185,10 +197,9 @@ static void dict_sdbm_update(DICT *dict, const char *name, const char *value)
*/
if ((dict->flags & DICT_FLAG_LOCK)
&& myflock(dict->lock_fd, INTERNAL_LOCK, MYFLOCK_OP_NONE) < 0)
- msg_fatal("%s: unlock dictionary: %m", dict_sdbm->path);
+ msg_fatal("%s: unlock dictionary: %m", dict_sdbm->dict.name);
}
-
/* dict_sdbm_delete - delete one entry from the dictionary */
static int dict_sdbm_delete(DICT *dict, const char *name)
@@ -196,14 +207,19 @@ static int dict_sdbm_delete(DICT *dict, const char *name)
DICT_SDBM *dict_sdbm = (DICT_SDBM *) dict;
datum dbm_key;
int status = 1;
- int flags = 0;
+
+ /*
+ * Sanity check.
+ */
+ if ((dict->flags & (DICT_FLAG_TRY1NULL | DICT_FLAG_TRY0NULL)) == 0)
+ msg_panic("dict_sdbm_delete: no DICT_FLAG_TRY1NULL | DICT_FLAG_TRY0NULL flag");
/*
* Acquire an exclusive lock.
*/
if ((dict->flags & DICT_FLAG_LOCK)
&& myflock(dict->lock_fd, INTERNAL_LOCK, MYFLOCK_OP_EXCLUSIVE) < 0)
- msg_fatal("%s: lock dictionary: %m", dict_sdbm->path);
+ msg_fatal("%s: lock dictionary: %m", dict_sdbm->dict.name);
/*
* See if this DBM file was written with one null byte appended to key
@@ -214,8 +230,8 @@ static int dict_sdbm_delete(DICT *dict, const char *name)
dbm_key.dsize = strlen(name) + 1;
sdbm_clearerr(dict_sdbm->dbm);
if ((status = sdbm_delete(dict_sdbm->dbm, dbm_key)) < 0) {
- if (sdbm_error(dict_sdbm->dbm) != 0) /* fatal error */
- msg_fatal("error deleting from %s: %m", dict_sdbm->path);
+ if (sdbm_error(dict_sdbm->dbm) != 0)/* fatal error */
+ msg_fatal("error deleting from %s: %m", dict_sdbm->dict.name);
status = 1; /* not found */
} else {
dict->flags &= ~DICT_FLAG_TRY0NULL; /* found */
@@ -231,8 +247,8 @@ static int dict_sdbm_delete(DICT *dict, const char *name)
dbm_key.dsize = strlen(name);
sdbm_clearerr(dict_sdbm->dbm);
if ((status = sdbm_delete(dict_sdbm->dbm, dbm_key)) < 0) {
- if (sdbm_error(dict_sdbm->dbm) != 0) /* fatal error */
- msg_fatal("error deleting from %s: %m", dict_sdbm->path);
+ if (sdbm_error(dict_sdbm->dbm) != 0)/* fatal error */
+ msg_fatal("error deleting from %s: %m", dict_sdbm->dict.name);
status = 1; /* not found */
} else {
dict->flags &= ~DICT_FLAG_TRY1NULL; /* found */
@@ -244,7 +260,7 @@ static int dict_sdbm_delete(DICT *dict, const char *name)
*/
if ((dict->flags & DICT_FLAG_LOCK)
&& myflock(dict->lock_fd, INTERNAL_LOCK, MYFLOCK_OP_NONE) < 0)
- msg_fatal("%s: unlock dictionary: %m", dict_sdbm->path);
+ msg_fatal("%s: unlock dictionary: %m", dict_sdbm->dict.name);
return (status);
}
@@ -252,26 +268,24 @@ static int dict_sdbm_delete(DICT *dict, const char *name)
/* traverse the dictionary */
static int dict_sdbm_sequence(DICT *dict, const int function,
- const char **key, const char **value)
+ const char **key, const char **value)
{
char *myname = "dict_sdbm_sequence";
DICT_SDBM *dict_sdbm = (DICT_SDBM *) dict;
datum dbm_key;
datum dbm_value;
- int status = 0;
- static VSTRING *key_buf;
- static VSTRING *value_buf;
/*
* Acquire a shared lock.
*/
if ((dict->flags & DICT_FLAG_LOCK)
&& myflock(dict->lock_fd, INTERNAL_LOCK, MYFLOCK_OP_SHARED) < 0)
- msg_fatal("%s: lock dictionary: %m", dict_sdbm->path);
+ msg_fatal("%s: lock dictionary: %m", dict_sdbm->dict.name);
/*
* Determine and execute the seek function. It returns the key.
*/
+ sdbm_clearerr(dict_sdbm->dbm);
switch (function) {
case DICT_SEQ_FUN_FIRST:
dbm_key = sdbm_firstkey(dict_sdbm->dbm);
@@ -283,27 +297,12 @@ static int dict_sdbm_sequence(DICT *dict, const int function,
msg_panic("%s: invalid function: %d", myname, function);
}
- /*
- * Release the shared lock.
- */
- if ((dict->flags & DICT_FLAG_LOCK)
- && myflock(dict->lock_fd, INTERNAL_LOCK, MYFLOCK_OP_NONE) < 0)
- msg_fatal("%s: unlock dictionary: %m", dict_sdbm->path);
-
if (dbm_key.dptr != 0 && dbm_key.dsize > 0) {
/*
- * See if this DB file was written with one null byte appended to key
- * and value or not. If necessary, copy the key.
+ * Copy the key so that it is guaranteed null terminated.
*/
- if (((char *) dbm_key.dptr)[dbm_key.dsize - 1] == 0) {
- *key = dbm_key.dptr;
- } else {
- if (key_buf == 0)
- key_buf = vstring_alloc(10);
- vstring_strncpy(key_buf, dbm_key.dptr, dbm_key.dsize);
- *key = vstring_str(key_buf);
- }
+ *key = SCOPY(dict_sdbm->key_buf, dbm_key.dptr, dbm_key.dsize);
/*
* Fetch the corresponding value.
@@ -313,17 +312,9 @@ static int dict_sdbm_sequence(DICT *dict, const int function,
if (dbm_value.dptr != 0 && dbm_value.dsize > 0) {
/*
- * See if this DB file was written with one null byte appended to
- * key and value or not. If necessary, copy the key.
+ * Copy the value so that it is guaranteed null terminated.
*/
- if (((char *) dbm_value.dptr)[dbm_value.dsize - 1] == 0) {
- *value = dbm_value.dptr;
- } else {
- if (value_buf == 0)
- value_buf = vstring_alloc(10);
- vstring_strncpy(value_buf, dbm_value.dptr, dbm_value.dsize);
- *value = vstring_str(value_buf);
- }
+ *value = SCOPY(dict_sdbm->val_buf, dbm_value.dptr, dbm_value.dsize);
} else {
/*
@@ -331,7 +322,7 @@ static int dict_sdbm_sequence(DICT *dict, const int function,
* condition.
*/
if (sdbm_error(dict_sdbm->dbm))
- msg_fatal("error seeking %s: %m", dict_sdbm->path);
+ msg_fatal("error seeking %s: %m", dict_sdbm->dict.name);
return (1); /* no error: eof/not found
* (should not happen!) */
}
@@ -341,9 +332,17 @@ static int dict_sdbm_sequence(DICT *dict, const int function,
* Determine if we have hit the last record or an error condition.
*/
if (sdbm_error(dict_sdbm->dbm))
- msg_fatal("error seeking %s: %m", dict_sdbm->path);
+ msg_fatal("error seeking %s: %m", dict_sdbm->dict.name);
return (1); /* no error: eof/not found */
}
+
+ /*
+ * Release the shared lock.
+ */
+ if ((dict->flags & DICT_FLAG_LOCK)
+ && myflock(dict->lock_fd, INTERNAL_LOCK, MYFLOCK_OP_NONE) < 0)
+ msg_fatal("%s: unlock dictionary: %m", dict_sdbm->dict.name);
+
return (0);
}
@@ -354,8 +353,11 @@ static void dict_sdbm_close(DICT *dict)
DICT_SDBM *dict_sdbm = (DICT_SDBM *) dict;
sdbm_close(dict_sdbm->dbm);
- myfree(dict_sdbm->path);
- myfree((char *) dict_sdbm);
+ if (dict_sdbm->key_buf)
+ vstring_free(dict_sdbm->key_buf);
+ if (dict_sdbm->val_buf)
+ vstring_free(dict_sdbm->val_buf);
+ dict_free(dict);
}
/* dict_sdbm_open - open SDBM data base */
@@ -368,8 +370,15 @@ DICT *dict_sdbm_open(const char *path, int open_flags, int dict_flags)
char *dbm_path;
int lock_fd;
+ /*
+ * Note: DICT_FLAG_LOCK is used only by programs that do fine-grained (in
+ * the time domain) locking while accessing individual database records.
+ *
+ * Programs such as postmap/postalias use their own large-grained (in the
+ * time domain) locks while rewriting the entire file.
+ */
if (dict_flags & DICT_FLAG_LOCK) {
- dbm_path = concatenate(path, ".pag", (char *) 0);
+ dbm_path = concatenate(path, ".dir", (char *) 0);
if ((lock_fd = open(dbm_path, open_flags, 0644)) < 0)
msg_fatal("open database %s: %m", dbm_path);
if (myflock(lock_fd, INTERNAL_LOCK, MYFLOCK_OP_SHARED) < 0)
@@ -387,9 +396,8 @@ DICT *dict_sdbm_open(const char *path, int open_flags, int dict_flags)
msg_fatal("unlock database %s for open: %m", dbm_path);
if (close(lock_fd) < 0)
msg_fatal("close database %s: %m", dbm_path);
- myfree(dbm_path);
}
- dict_sdbm = (DICT_SDBM *) mymalloc(sizeof(*dict_sdbm));
+ dict_sdbm = (DICT_SDBM *) dict_alloc(DICT_TYPE_SDBM, path, sizeof(*dict_sdbm));
dict_sdbm->dict.lookup = dict_sdbm_lookup;
dict_sdbm->dict.update = dict_sdbm_update;
dict_sdbm->dict.delete = dict_sdbm_delete;
@@ -400,15 +408,30 @@ DICT *dict_sdbm_open(const char *path, int open_flags, int dict_flags)
if (fstat(dict_sdbm->dict.stat_fd, &st) < 0)
msg_fatal("dict_sdbm_open: fstat: %m");
dict_sdbm->dict.mtime = st.st_mtime;
+
+ /*
+ * Warn if the source file is newer than the indexed file, except when
+ * the source file changed only seconds ago.
+ */
+ if ((dict_flags & DICT_FLAG_LOCK) != 0
+ && stat(path, &st) == 0
+ && st.st_mtime > dict_sdbm->dict.mtime
+ && st.st_mtime < time((time_t *) 0) - 100)
+ msg_warn("database %s is older than source file %s", dbm_path, path);
+
close_on_exec(sdbm_pagfno(dbm), CLOSE_ON_EXEC);
close_on_exec(sdbm_dirfno(dbm), CLOSE_ON_EXEC);
dict_sdbm->dict.flags = dict_flags | DICT_FLAG_FIXED;
if ((dict_flags & (DICT_FLAG_TRY0NULL | DICT_FLAG_TRY1NULL)) == 0)
dict_sdbm->dict.flags |= (DICT_FLAG_TRY0NULL | DICT_FLAG_TRY1NULL);
dict_sdbm->dbm = dbm;
- dict_sdbm->path = mystrdup(path);
+ dict_sdbm->key_buf = 0;
+ dict_sdbm->val_buf = 0;
+
+ if ((dict_flags & DICT_FLAG_LOCK))
+ myfree(dbm_path);
- return (&dict_sdbm->dict);
+ return (DICT_DEBUG (&dict_sdbm->dict));
}
#endif