mirror of
https://github.com/vdukhovni/postfix
synced 2025-08-22 09:57:34 +00:00
postfix-2.7-20100101
This commit is contained in:
parent
2ccf57f4ac
commit
a92fc14c5d
@ -15602,3 +15602,16 @@ Apologies for any names omitted.
|
||||
Final slution for the I/O event starvation problem when a
|
||||
timer call-back schedules a zero-delay timer request. File:
|
||||
util/events.c.
|
||||
|
||||
20091231
|
||||
|
||||
Cleanup: the non-shared, in-memory hash table is now
|
||||
accessible as the "internal:" map type. This simplifies
|
||||
code by eliminating some special cases. Files: util/dict_ht.c,
|
||||
util/dict_open.c, and documentation.
|
||||
|
||||
20100101
|
||||
|
||||
Bugfix: the mantools/postlink script applied hyperlinks
|
||||
for the "virtual:" transport to "/etc/postfix/virtual:".
|
||||
Symptom reported by Christoph Anton Mitterer.
|
||||
|
@ -204,6 +204,9 @@ To find out what database types your Postfix system supports, use the "ppooss
|
||||
created with the postmap(1) or postalias(1) command. The database name
|
||||
as used in "hash:table" is the database file name without the ".db"
|
||||
suffix.
|
||||
iinntteerrnnaall
|
||||
A non-shared, in-memory hash table. Its content are lost when a process
|
||||
terminates.
|
||||
llddaapp (read-only)
|
||||
Perform lookups using the LDAP protocol. Configuration details are
|
||||
given in the ldap_table(5).
|
||||
|
@ -14,7 +14,7 @@ specifies the release date of a stable release or snapshot release.
|
||||
If you upgrade from Postfix 2.5 or earlier, read RELEASE_NOTES-2.6
|
||||
before proceeding.
|
||||
|
||||
Incompatibility with snapshot 20091229
|
||||
Incompatibility with snapshot 20100101
|
||||
======================================
|
||||
|
||||
The verify(8) service now uses a persistent cache by default
|
||||
@ -24,9 +24,9 @@ disable, specify "address_verify_map =" in main.cf.
|
||||
When periodic cache cleanup is enabled (the default), the postscreen(8)
|
||||
and verify(8) servers now require that their cache databases support
|
||||
the "delete" and "sequence" operations. To disable periodic cache
|
||||
cleanup specify a zero xxx_cache_cleanup_interval.
|
||||
cleanup specify a zero xxx_cache_cleanup_interval value.
|
||||
|
||||
Major changes with snapshot 20091229
|
||||
Major changes with snapshot 20100101
|
||||
====================================
|
||||
|
||||
Periodic cache cleanup for the postscreen(8) and verify(8) cache
|
||||
|
@ -785,7 +785,7 @@ commas. </p>
|
||||
/etc/postfix/<a href="postconf.5.html">main.cf</a>:
|
||||
<a href="postconf.5.html#virtual_alias_maps">virtual_alias_maps</a> = hash:/etc/postfix/virtual
|
||||
|
||||
/etc/postfix/<a href="virtual.8.html">virtual</a>:
|
||||
/etc/postfix/virtual:
|
||||
Wietse.Venema wietse
|
||||
</pre>
|
||||
</blockquote>
|
||||
|
@ -299,6 +299,11 @@ created with the <a href="postmap.1.html">postmap(1)</a> or <a href="postalias.1
|
||||
name as used in "hash:table" is the database file name without the
|
||||
".db" suffix. </dd>
|
||||
|
||||
<dt> <b>internal</b> </dt>
|
||||
|
||||
<dd> A non-shared, in-memory hash table. Its content are lost when
|
||||
a process terminates. </dd>
|
||||
|
||||
<dt> <b>ldap</b> (read-only) </dt>
|
||||
|
||||
<dd> Perform lookups using the LDAP protocol. Configuration details
|
||||
|
@ -211,7 +211,7 @@ href="STANDARD_CONFIGURATION_README.html#null_client">null client</a>:
|
||||
#
|
||||
root mtaadmin+root=mta1
|
||||
|
||||
/etc/postfix/<a href="virtual.8.html">virtual</a>:
|
||||
/etc/postfix/virtual:
|
||||
# Caretaker aliases:
|
||||
#
|
||||
root mtaadmin
|
||||
|
@ -180,7 +180,7 @@ discussed the first half of this document. </p>
|
||||
9 /etc/postfix/canonical:
|
||||
10 your-login-name your-account@your-isp.com
|
||||
11
|
||||
12 /etc/postfix/<a href="virtual.8.html">virtual</a>:
|
||||
12 /etc/postfix/virtual:
|
||||
13 your-account@your-isp.com your-login-name
|
||||
</pre>
|
||||
</blockquote>
|
||||
|
@ -319,7 +319,7 @@ All the mail to these two accounts is forwarded to an inside address.
|
||||
1 /etc/postfix/<a href="postconf.5.html">main.cf</a>:
|
||||
2 <a href="postconf.5.html#virtual_alias_maps">virtual_alias_maps</a> = hash:/etc/postfix/virtual
|
||||
3
|
||||
4 /etc/postfix/<a href="virtual.8.html">virtual</a>:
|
||||
4 /etc/postfix/virtual:
|
||||
5 postmaster postmaster@example.com
|
||||
6 abuse abuse@example.com
|
||||
</pre>
|
||||
@ -425,7 +425,7 @@ follows: </p>
|
||||
1 /etc/postfix/<a href="postconf.5.html">main.cf</a>:
|
||||
2 <a href="postconf.5.html#virtual_alias_maps">virtual_alias_maps</a> = hash:/etc/postfix/virtual
|
||||
3
|
||||
4 /etc/postfix/<a href="virtual.8.html">virtual</a>:
|
||||
4 /etc/postfix/virtual:
|
||||
5 root root@localhost
|
||||
6 . . .
|
||||
</pre>
|
||||
@ -785,7 +785,7 @@ discussed the first half of this document. </p>
|
||||
9 /etc/postfix/canonical:
|
||||
10 your-login-name your-account@your-isp.com
|
||||
11
|
||||
12 /etc/postfix/<a href="virtual.8.html">virtual</a>:
|
||||
12 /etc/postfix/virtual:
|
||||
13 your-account@your-isp.com your-login-name
|
||||
</pre>
|
||||
</blockquote>
|
||||
|
@ -167,7 +167,7 @@ below shows how to use this mechanism for the example.com domain.
|
||||
2 <a href="postconf.5.html#virtual_alias_domains">virtual_alias_domains</a> = example.com ...other <a href="VIRTUAL_README.html#canonical">hosted domains</a>...
|
||||
3 <a href="postconf.5.html#virtual_alias_maps">virtual_alias_maps</a> = hash:/etc/postfix/virtual
|
||||
4
|
||||
5 /etc/postfix/<a href="virtual.8.html">virtual</a>:
|
||||
5 /etc/postfix/virtual:
|
||||
6 postmaster@example.com postmaster
|
||||
7 info@example.com joe
|
||||
8 sales@example.com jane
|
||||
@ -271,7 +271,7 @@ section at the top of this document.</p>
|
||||
14 # @example.com example.com/catchall
|
||||
15 ...virtual mailboxes for more domains...
|
||||
16
|
||||
17 /etc/postfix/<a href="virtual.8.html">virtual</a>:
|
||||
17 /etc/postfix/virtual:
|
||||
18 postmaster@example.com postmaster
|
||||
</pre>
|
||||
</blockquote>
|
||||
@ -389,7 +389,7 @@ to a non-Postfix delivery agent: </p>
|
||||
12 # @example.com whatever
|
||||
13 ...virtual mailboxes for more domains...
|
||||
14
|
||||
15 /etc/postfix/<a href="virtual.8.html">virtual</a>:
|
||||
15 /etc/postfix/virtual:
|
||||
16 postmaster@example.com postmaster
|
||||
</pre>
|
||||
</blockquote>
|
||||
@ -486,7 +486,7 @@ as a mail forwarding domain: </p>
|
||||
2 <a href="postconf.5.html#virtual_alias_domains">virtual_alias_domains</a> = example.com ...other <a href="VIRTUAL_README.html#canonical">hosted domains</a>...
|
||||
3 <a href="postconf.5.html#virtual_alias_maps">virtual_alias_maps</a> = hash:/etc/postfix/virtual
|
||||
4
|
||||
5 /etc/postfix/<a href="virtual.8.html">virtual</a>:
|
||||
5 /etc/postfix/virtual:
|
||||
6 postmaster@example.com postmaster
|
||||
7 joe@example.com joe@somewhere
|
||||
8 jane@example.com jane@somewhere-else
|
||||
@ -553,7 +553,7 @@ virtual addresses to the local delivery agent: </p>
|
||||
/etc/postfix/<a href="postconf.5.html">main.cf</a>:
|
||||
<a href="postconf.5.html#virtual_alias_maps">virtual_alias_maps</a> = hash:/etc/postfix/virtual
|
||||
|
||||
/etc/postfix/<a href="virtual.8.html">virtual</a>:
|
||||
/etc/postfix/virtual:
|
||||
listname-request@example.com listname-request
|
||||
listname@example.com listname
|
||||
owner-listname@example.com owner-listname
|
||||
@ -601,7 +601,7 @@ table: </p>
|
||||
/etc/postfix/<a href="postconf.5.html">main.cf</a>:
|
||||
<a href="postconf.5.html#virtual_alias_maps">virtual_alias_maps</a> = hash:/etc/postfix/virtual
|
||||
|
||||
/etc/postfix/<a href="virtual.8.html">virtual</a>:
|
||||
/etc/postfix/virtual:
|
||||
user@domain.tld user@domain.tld, user@domain.tld@autoreply.<a href="postconf.5.html#mydomain">mydomain</a>.tld
|
||||
</pre>
|
||||
</blockquote>
|
||||
|
@ -140,67 +140,71 @@ POSTCONF(1) POSTCONF(1)
|
||||
is available on systems with support for
|
||||
Berkeley DB databases.
|
||||
|
||||
<b>internal</b>
|
||||
A non-shared, in-memory hash table. Its con-
|
||||
tent are lost when a process terminates.
|
||||
|
||||
<b>ldap</b> (read-only)
|
||||
Perform lookups using the LDAP protocol.
|
||||
Perform lookups using the LDAP protocol.
|
||||
This is described in <a href="ldap_table.5.html"><b>ldap_table</b>(5)</a>.
|
||||
|
||||
<b>mysql</b> (read-only)
|
||||
Perform lookups using the MYSQL protocol.
|
||||
Perform lookups using the MYSQL protocol.
|
||||
This is described in <a href="mysql_table.5.html"><b>mysql_table</b>(5)</a>.
|
||||
|
||||
<b>pcre</b> (read-only)
|
||||
A lookup table based on Perl Compatible Reg-
|
||||
ular Expressions. The file format is
|
||||
ular Expressions. The file format is
|
||||
described in <a href="pcre_table.5.html"><b>pcre_table</b>(5)</a>.
|
||||
|
||||
<b>pgsql</b> (read-only)
|
||||
Perform lookups using the PostgreSQL proto-
|
||||
Perform lookups using the PostgreSQL proto-
|
||||
col. This is described in <a href="pgsql_table.5.html"><b>pgsql_table</b>(5)</a>.
|
||||
|
||||
<b>proxy</b> (read-only)
|
||||
A lookup table that is implemented via the
|
||||
Postfix <a href="proxymap.8.html"><b>proxymap</b>(8)</a> service. The table name
|
||||
A lookup table that is implemented via the
|
||||
Postfix <a href="proxymap.8.html"><b>proxymap</b>(8)</a> service. The table name
|
||||
syntax is <i>type</i><b>:</b><i>name</i>.
|
||||
|
||||
<b>regexp</b> (read-only)
|
||||
A lookup table based on regular expressions.
|
||||
The file format is described in <a href="regexp_table.5.html"><b>regexp_ta-</b></a>
|
||||
The file format is described in <a href="regexp_table.5.html"><b>regexp_ta-</b></a>
|
||||
<a href="regexp_table.5.html"><b>ble</b>(5)</a>.
|
||||
|
||||
<b>sdbm</b> An indexed file type based on hashing. This
|
||||
is available on systems with support for
|
||||
is available on systems with support for
|
||||
SDBM databases.
|
||||
|
||||
<b>static</b> (read-only)
|
||||
A table that always returns its name as
|
||||
lookup result. For example, <b>static:foobar</b>
|
||||
always returns the string <b>foobar</b> as lookup
|
||||
A table that always returns its name as
|
||||
lookup result. For example, <b>static:foobar</b>
|
||||
always returns the string <b>foobar</b> as lookup
|
||||
result.
|
||||
|
||||
<b>tcp</b> (read-only)
|
||||
Perform lookups using a simple request-reply
|
||||
protocol that is described in <a href="tcp_table.5.html"><b>tcp_table</b>(5)</a>.
|
||||
protocol that is described in <a href="tcp_table.5.html"><b>tcp_table</b>(5)</a>.
|
||||
This feature is not included with the stable
|
||||
Postfix release.
|
||||
|
||||
<b>unix</b> (read-only)
|
||||
A limited way to query the UNIX authentica-
|
||||
A limited way to query the UNIX authentica-
|
||||
tion database. The following tables are
|
||||
implemented:
|
||||
|
||||
<b>unix:passwd.byname</b>
|
||||
The table is the UNIX password data-
|
||||
base. The key is a login name. The
|
||||
result is a password file entry in
|
||||
The table is the UNIX password data-
|
||||
base. The key is a login name. The
|
||||
result is a password file entry in
|
||||
<b>passwd</b>(5) format.
|
||||
|
||||
<b>unix:group.byname</b>
|
||||
The table is the UNIX group database.
|
||||
The key is a group name. The result
|
||||
is a group file entry in <b>group</b>(5)
|
||||
The key is a group name. The result
|
||||
is a group file entry in <b>group</b>(5)
|
||||
format.
|
||||
|
||||
Other table types may exist depending on how Post-
|
||||
Other table types may exist depending on how Post-
|
||||
fix was built.
|
||||
|
||||
<b>-n</b> Print parameter settings that are not left at their
|
||||
@ -209,29 +213,29 @@ POSTCONF(1) POSTCONF(1)
|
||||
|
||||
<b>-t</b> [<i>template</i><b>_</b><i>file</i>]
|
||||
Display the templates for delivery status notifica-
|
||||
tion (DSN) messages. To override the built-in tem-
|
||||
plates, specify a template file at the end of the
|
||||
tion (DSN) messages. To override the built-in tem-
|
||||
plates, specify a template file at the end of the
|
||||
command line, or specify a template file in <a href="postconf.5.html">main.cf</a>
|
||||
with the <b><a href="postconf.5.html#bounce_template_file">bounce_template_file</a></b> parameter. To force
|
||||
selection of the built-in templates, specify an
|
||||
with the <b><a href="postconf.5.html#bounce_template_file">bounce_template_file</a></b> parameter. To force
|
||||
selection of the built-in templates, specify an
|
||||
empty template file name (in shell language: "").
|
||||
|
||||
This feature is available with Postfix 2.3 and
|
||||
This feature is available with Postfix 2.3 and
|
||||
later.
|
||||
|
||||
<b>-v</b> Enable verbose logging for debugging purposes. Mul-
|
||||
tiple <b>-v</b> options make the software increasingly
|
||||
tiple <b>-v</b> options make the software increasingly
|
||||
verbose.
|
||||
|
||||
<b>-#</b> Edit the <a href="postconf.5.html"><b>main.cf</b></a> configuration file. The file is
|
||||
<b>-#</b> Edit the <a href="postconf.5.html"><b>main.cf</b></a> configuration file. The file is
|
||||
copied to a temporary file then renamed into place.
|
||||
The parameters specified on the command line are
|
||||
The parameters specified on the command line are
|
||||
commented-out, so that they revert to their default
|
||||
values. Specify a list of parameter names, not
|
||||
name=value pairs. There is no <b>postconf</b> command to
|
||||
values. Specify a list of parameter names, not
|
||||
name=value pairs. There is no <b>postconf</b> command to
|
||||
perform the reverse operation.
|
||||
|
||||
This feature is available with Postfix 2.6 and
|
||||
This feature is available with Postfix 2.6 and
|
||||
later.
|
||||
|
||||
<b>DIAGNOSTICS</b>
|
||||
@ -242,18 +246,18 @@ POSTCONF(1) POSTCONF(1)
|
||||
Directory with Postfix configuration files.
|
||||
|
||||
<b>CONFIGURATION PARAMETERS</b>
|
||||
The following <a href="postconf.5.html"><b>main.cf</b></a> parameters are especially relevant
|
||||
The following <a href="postconf.5.html"><b>main.cf</b></a> parameters are especially relevant
|
||||
to this program.
|
||||
|
||||
The text below provides only a parameter summary. See
|
||||
The text below provides only a parameter summary. See
|
||||
<a href="postconf.5.html"><b>postconf</b>(5)</a> for more details including examples.
|
||||
|
||||
<b><a href="postconf.5.html#config_directory">config_directory</a> (see 'postconf -d' output)</b>
|
||||
The default location of the Postfix <a href="postconf.5.html">main.cf</a> and
|
||||
The default location of the Postfix <a href="postconf.5.html">main.cf</a> and
|
||||
<a href="master.5.html">master.cf</a> configuration files.
|
||||
|
||||
<b><a href="postconf.5.html#bounce_template_file">bounce_template_file</a> (empty)</b>
|
||||
Pathname of a configuration file with bounce mes-
|
||||
Pathname of a configuration file with bounce mes-
|
||||
sage templates.
|
||||
|
||||
<b>FILES</b>
|
||||
@ -267,7 +271,7 @@ POSTCONF(1) POSTCONF(1)
|
||||
<a href="DATABASE_README.html">DATABASE_README</a>, Postfix lookup table overview
|
||||
|
||||
<b>LICENSE</b>
|
||||
The Secure Mailer license must be distributed with this
|
||||
The Secure Mailer license must be distributed with this
|
||||
software.
|
||||
|
||||
<b>AUTHOR(S)</b>
|
||||
|
@ -12226,6 +12226,9 @@ access restriction is specified. This prevents the Postfix queue
|
||||
from filling up with undeliverable MAILER-DAEMON messages.
|
||||
</p>
|
||||
|
||||
<p> An address is always considered "known" when it matches a
|
||||
<a href="virtual.5.html">virtual(5)</a> alias or a <a href="canonical.5.html">canonical(5)</a> mapping.
|
||||
|
||||
<ul>
|
||||
|
||||
<li> The recipient domain matches $<a href="postconf.5.html#mydestination">mydestination</a>, $<a href="postconf.5.html#inet_interfaces">inet_interfaces</a>
|
||||
@ -12260,6 +12263,9 @@ sender addresses, even when no explicit <a href="postconf.5.html#reject_unlisted
|
||||
access restriction is specified. This can slow down an explosion
|
||||
of forged mail from worms or viruses. </p>
|
||||
|
||||
<p> An address is always considered "known" when it matches a
|
||||
<a href="virtual.5.html">virtual(5)</a> alias or a <a href="canonical.5.html">canonical(5)</a> mapping.
|
||||
|
||||
<ul>
|
||||
|
||||
<li> The sender domain matches $<a href="postconf.5.html#mydestination">mydestination</a>, $<a href="postconf.5.html#inet_interfaces">inet_interfaces</a> or
|
||||
@ -15033,9 +15039,8 @@ value is backwards compatible with Postfix version 1.1.
|
||||
(default: 51200000)</b></DT><DD>
|
||||
|
||||
<p>
|
||||
The maximal size in bytes of an individual mailbox or maildir file,
|
||||
or zero (no limit).
|
||||
</p>
|
||||
The maximal size in bytes of an individual <a href="virtual.8.html">virtual(8)</a> mailbox or
|
||||
maildir file, or zero (no limit). </p>
|
||||
|
||||
|
||||
</DD>
|
||||
|
@ -168,7 +168,7 @@ VIRTUAL(5) VIRTUAL(5)
|
||||
the output from "<b>postconf -m</b>" for available database
|
||||
types.
|
||||
|
||||
/etc/postfix/<a href="virtual.8.html">virtual</a>:
|
||||
/etc/postfix/virtual:
|
||||
<i>virtual-alias.domain anything</i> (right-hand content does not matter)
|
||||
<i>postmaster@virtual-alias.domain postmaster</i>
|
||||
<i>user1@virtual-alias.domain address1</i>
|
||||
|
@ -127,6 +127,9 @@ useful someday.
|
||||
An indexed file type based on hashing.
|
||||
This is available on systems with support for Berkeley DB
|
||||
databases.
|
||||
.IP \fBinternal\fR
|
||||
A non-shared, in-memory hash table. Its content are lost
|
||||
when a process terminates.
|
||||
.IP "\fBldap\fR (read-only)"
|
||||
Perform lookups using the LDAP protocol. This is described
|
||||
in \fBldap_table\fR(5).
|
||||
|
@ -7539,6 +7539,9 @@ Request that the Postfix SMTP server rejects mail for unknown
|
||||
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.
|
||||
.IP \(bu
|
||||
The recipient domain matches $mydestination, $inet_interfaces
|
||||
or $proxy_interfaces, but the recipient is not listed in
|
||||
@ -7561,6 +7564,9 @@ Request that the Postfix SMTP server rejects mail from unknown
|
||||
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.
|
||||
.IP \(bu
|
||||
The sender domain matches $mydestination, $inet_interfaces or
|
||||
$proxy_interfaces, but the sender is not listed in
|
||||
@ -9411,8 +9417,8 @@ configuration parameter.
|
||||
This feature is available in Postfix 2.0 and later. The default
|
||||
value is backwards compatible with Postfix version 1.1.
|
||||
.SH virtual_mailbox_limit (default: 51200000)
|
||||
The maximal size in bytes of an individual mailbox or maildir file,
|
||||
or zero (no limit).
|
||||
The maximal size in bytes of an individual \fBvirtual\fR(8) mailbox or
|
||||
maildir file, or zero (no limit).
|
||||
.SH virtual_mailbox_lock (default: see "postconf -d" output)
|
||||
How to lock a UNIX-style \fBvirtual\fR(8) mailbox before attempting
|
||||
delivery. For a list of available file locking methods, use the
|
||||
|
@ -981,7 +981,7 @@ while (<>) {
|
||||
s/\b(smtp):/<a href="smtp.8.html">$1<\/a>:/g;
|
||||
s/\b(lmtp):/<a href="lmtp.8.html">$1<\/a>:/g;
|
||||
s/\b(local):/<a href="local.8.html">$1<\/a>:/g;
|
||||
s/\b(virtual):/<a href="virtual.8.html">$1<\/a>:/g;
|
||||
s/([^\/])\b(virtual):/$1<a href="virtual.8.html">$2<\/a>:/g;
|
||||
}
|
||||
continue {
|
||||
if ($printit)
|
||||
|
@ -299,6 +299,11 @@ created with the postmap(1) or postalias(1) command. The database
|
||||
name as used in "hash:table" is the database file name without the
|
||||
".db" suffix. </dd>
|
||||
|
||||
<dt> <b>internal</b> </dt>
|
||||
|
||||
<dd> A non-shared, in-memory hash table. Its content are lost when
|
||||
a process terminates. </dd>
|
||||
|
||||
<dt> <b>ldap</b> (read-only) </dt>
|
||||
|
||||
<dd> Perform lookups using the LDAP protocol. Configuration details
|
||||
|
@ -7846,6 +7846,9 @@ access restriction is specified. This prevents the Postfix queue
|
||||
from filling up with undeliverable MAILER-DAEMON messages.
|
||||
</p>
|
||||
|
||||
<p> An address is always considered "known" when it matches a
|
||||
virtual(5) alias or a canonical(5) mapping.
|
||||
|
||||
<ul>
|
||||
|
||||
<li> The recipient domain matches $mydestination, $inet_interfaces
|
||||
@ -7876,6 +7879,9 @@ sender addresses, even when no explicit reject_unlisted_sender
|
||||
access restriction is specified. This can slow down an explosion
|
||||
of forged mail from worms or viruses. </p>
|
||||
|
||||
<p> An address is always considered "known" when it matches a
|
||||
virtual(5) alias or a canonical(5) mapping.
|
||||
|
||||
<ul>
|
||||
|
||||
<li> The sender domain matches $mydestination, $inet_interfaces or
|
||||
@ -8143,9 +8149,8 @@ value is backwards compatible with Postfix version 1.1.
|
||||
%PARAM virtual_mailbox_limit 51200000
|
||||
|
||||
<p>
|
||||
The maximal size in bytes of an individual mailbox or maildir file,
|
||||
or zero (no limit).
|
||||
</p>
|
||||
The maximal size in bytes of an individual virtual(8) mailbox or
|
||||
maildir file, or zero (no limit). </p>
|
||||
|
||||
%PARAM virtual_mailbox_lock see "postconf -d" output
|
||||
|
||||
|
@ -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 "20091229"
|
||||
#define MAIL_RELEASE_DATE "20100101"
|
||||
#define MAIL_VERSION_NUMBER "2.7"
|
||||
|
||||
#ifdef SNAPSHOT
|
||||
|
@ -121,6 +121,9 @@
|
||||
/* An indexed file type based on hashing.
|
||||
/* This is available on systems with support for Berkeley DB
|
||||
/* databases.
|
||||
/* .IP \fBinternal\fR
|
||||
/* A non-shared, in-memory hash table. Its content are lost
|
||||
/* when a process terminates.
|
||||
/* .IP "\fBldap\fR (read-only)"
|
||||
/* Perform lookups using the LDAP protocol. This is described
|
||||
/* in \fBldap_table\fR(5).
|
||||
|
@ -1343,12 +1343,16 @@ static void post_jail_init(char *unused_name, char **unused_argv)
|
||||
* verbose logging more informative (we get positive confirmation that
|
||||
* the cleanup thread runs).
|
||||
*/
|
||||
expire_flags = DICT_CACHE_FLAG_EXP_SUMMARY;
|
||||
expire_flags = DICT_CACHE_FLAG_STATISTICS;
|
||||
if (msg_verbose)
|
||||
expire_flags |= DICT_CACHE_FLAG_EXP_VERBOSE;
|
||||
expire_flags |= DICT_CACHE_FLAG_VERBOSE;
|
||||
if (cache_map != 0 && var_ps_cache_scan > 0)
|
||||
dict_cache_expire(cache_map, expire_flags, var_ps_cache_scan,
|
||||
postscreen_cache_validator, (char *) 0);
|
||||
dict_cache_control(cache_map,
|
||||
DICT_CACHE_CTL_FLAGS, expire_flags,
|
||||
DICT_CACHE_CTL_INTERVAL, var_ps_cache_scan,
|
||||
DICT_CACHE_CTL_VALIDATOR, postscreen_cache_validator,
|
||||
DICT_CACHE_CTL_CONTEXT, (char *) 0,
|
||||
DICT_CACHE_CTL_END);
|
||||
}
|
||||
|
||||
MAIL_VERSION_STAMP_DECLARE;
|
||||
|
@ -118,7 +118,7 @@ OK
|
||||
>>> helo verisign.com
|
||||
OK
|
||||
>>> helo example.tld
|
||||
./smtpd_check: warning: Unable to look up MX host for example.tld: Host not found
|
||||
./smtpd_check: warning: Unable to look up MX host example.tld for Helo command example.tld: hostname nor servname provided, or not known
|
||||
OK
|
||||
>>> sender_restrictions check_sender_mx_access,hash:smtpd_check_access
|
||||
OK
|
||||
|
@ -820,6 +820,7 @@ dict_ht.o: dict_ht.c
|
||||
dict_ht.o: dict_ht.h
|
||||
dict_ht.o: htable.h
|
||||
dict_ht.o: mymalloc.h
|
||||
dict_ht.o: stringops.h
|
||||
dict_ht.o: sys_defs.h
|
||||
dict_ht.o: vbuf.h
|
||||
dict_ht.o: vstream.h
|
||||
@ -855,6 +856,7 @@ dict_open.o: dict_cidr.h
|
||||
dict_open.o: dict_db.h
|
||||
dict_open.o: dict_dbm.h
|
||||
dict_open.o: dict_env.h
|
||||
dict_open.o: dict_ht.h
|
||||
dict_open.o: dict_ni.h
|
||||
dict_open.o: dict_nis.h
|
||||
dict_open.o: dict_nisplus.h
|
||||
|
@ -290,7 +290,7 @@ void dict_update(const char *dict_name, const char *member, const char *value
|
||||
if ((node = dict_node(dict_name)) == 0) {
|
||||
if (dict_unknown_allowed == 0)
|
||||
msg_fatal("%s: unknown dictionary: %s", myname, dict_name);
|
||||
dict = dict_ht_open(dict_name, htable_create(0), myfree);
|
||||
dict = dict_ht_open(dict_name, O_CREAT | O_RDWR, 0);
|
||||
dict_register(dict_name, dict);
|
||||
} else
|
||||
dict = node->dict;
|
||||
@ -334,7 +334,7 @@ int dict_delete(const char *dict_name, const char *member)
|
||||
if ((node = dict_node(dict_name)) == 0) {
|
||||
if (dict_unknown_allowed == 0)
|
||||
msg_fatal("%s: unknown dictionary: %s", myname, dict_name);
|
||||
dict = dict_ht_open(dict_name, htable_create(0), myfree);
|
||||
dict = dict_ht_open(dict_name, O_CREAT | O_RDWR, 0);
|
||||
dict_register(dict_name, dict);
|
||||
} else
|
||||
dict = node->dict;
|
||||
@ -358,7 +358,7 @@ int dict_sequence(const char *dict_name, const int func,
|
||||
if ((node = dict_node(dict_name)) == 0) {
|
||||
if (dict_unknown_allowed == 0)
|
||||
msg_fatal("%s: unknown dictionary: %s", myname, dict_name);
|
||||
dict = dict_ht_open(dict_name, htable_create(0), myfree);
|
||||
dict = dict_ht_open(dict_name, O_CREAT | O_RDWR, 0);
|
||||
dict_register(dict_name, dict);
|
||||
} else
|
||||
dict = node->dict;
|
||||
|
@ -32,20 +32,16 @@
|
||||
/* int first_next;
|
||||
/* const char **cache_key;
|
||||
/* const char **cache_val;
|
||||
/*
|
||||
/* void dict_cache_expire(cache, flags, interval, validator, context)
|
||||
/* DICT_CACHE *cache;
|
||||
/* int flags;
|
||||
/* int interval;
|
||||
/* int (*validator)(const char *cache_key, const char *cache_val,
|
||||
/* char *context);
|
||||
/* char *context;
|
||||
/* AUXILIARY FUNCTIONS
|
||||
/* void dict_cache_control(cache, name, value, ...)
|
||||
/* DICT_CACHE *cache;
|
||||
/* int name;
|
||||
/*
|
||||
/* typedef int (*DICT_CACHE_VALIDATOR_FN) (const char *cache_key,
|
||||
/* const char *cache_val, char *context);
|
||||
/*
|
||||
/* const char *dict_cache_name(cache)
|
||||
/* DICT_CACHE *cache;
|
||||
/*
|
||||
/* DICT_CACHE *dict_cache_import(table)
|
||||
/* DICT *table;
|
||||
/* DESCRIPTION
|
||||
/* This module maintains external cache files with support
|
||||
/* for expiration. The underlying table must implement the
|
||||
@ -56,22 +52,23 @@
|
||||
/* between the iterators that access all cache elements, and
|
||||
/* other operations that access individual cache elements.
|
||||
/*
|
||||
/* In particular, when a "sequence" or "expire" operation is
|
||||
/* In particular, when a "sequence" or "cleanup" operation is
|
||||
/* in progress the cache intercepts requests to delete the
|
||||
/* "current" entry, as this would cause some databases to
|
||||
/* mis-behave. Instead, the cache implements a "delete behind"
|
||||
/* strategy, and deletes such an entry after the "sequence"
|
||||
/* or "expire" operation moves on to the next cache element.
|
||||
/* or "cleanup" operation moves on to the next cache element.
|
||||
/* The "delete behind" strategy also affects the cache lookup
|
||||
/* and update operations as detailed below.
|
||||
/*
|
||||
/* dict_cache_open() opens the specified cache and returns a
|
||||
/* handle that must be used for subsequent access. This function
|
||||
/* does not return in case of error.
|
||||
/* dict_cache_open() is a wrapper around the dict_open()
|
||||
/* function. It opens the specified cache and returns a handle
|
||||
/* that must be used for subsequent access. This function does
|
||||
/* not return in case of error.
|
||||
/*
|
||||
/* dict_cache_close() closes the specified cache and releases
|
||||
/* memory that was allocated by dict_cache_open(), and terminates
|
||||
/* any thread that was started with dict_cache_expire().
|
||||
/* any thread that was started with dict_cache_control().
|
||||
/*
|
||||
/* dict_cache_lookup() looks up the specified cache entry.
|
||||
/* The result value is a null pointer when the cache entry was
|
||||
@ -80,9 +77,9 @@
|
||||
/*
|
||||
/* dict_cache_update() updates the specified cache entry. If
|
||||
/* the entry is scheduled for "delete behind", the delete
|
||||
/* operation is canceled (meaning that the cache must be opened
|
||||
/* with DICT_FLAG_DUP_REPLACE). This function does not return
|
||||
/* in case of error.
|
||||
/* operation is canceled (because of this, the cache must be
|
||||
/* opened with DICT_FLAG_DUP_REPLACE). This function does not
|
||||
/* return in case of error.
|
||||
/*
|
||||
/* dict_cache_delete() removes the specified cache entry. If
|
||||
/* this is the "current" entry of a "sequence" operation, the
|
||||
@ -91,25 +88,45 @@
|
||||
/*
|
||||
/* dict_cache_sequence() iterates over the specified cache and
|
||||
/* returns each entry in an implementation-defined order. The
|
||||
/* result value is zero when a cache entry was found. Programs
|
||||
/* must not use both dict_cache_sequence() and dict_cache_expire().
|
||||
/* result value is zero when a cache entry was found.
|
||||
/*
|
||||
/* dict_cache_expire() schedules a thread that expires cache
|
||||
/* entries periodically. Specify a null validator argument to
|
||||
/* cancel the thread. It is an error to schedule a cache
|
||||
/* cleanup thread when one already exists. Programs must not
|
||||
/* use both dict_cache_sequence() and dict_cache_expire().
|
||||
/* Important: programs must not use both dict_cache_sequence()
|
||||
/* and the built-in cache cleanup feature.
|
||||
/*
|
||||
/* dict_cache_control() provides control over the built-in
|
||||
/* cache cleanup feature and logging. The arguments are a list
|
||||
/* of (name, value) pairs, terminated with DICT_CACHE_CTL_END.
|
||||
/* The following lists the names and the types of the corresponding
|
||||
/* value arguments.
|
||||
/* .IP "DICT_CACHE_FLAGS (int flags)"
|
||||
/* The arguments to this command are the bit-wise OR of zero
|
||||
/* or more of the following:
|
||||
/* .RS
|
||||
/* .IP DICT_CACHE_FLAG_VERBOSE
|
||||
/* Enable verbose logging of cache activity.
|
||||
/* .IP DICT_CACHE_FLAG_EXP_SUMMARY
|
||||
/* Log cache statistics after each cache cleanup run.
|
||||
/* .RE
|
||||
/* .IP "DICT_CACHE_CTL_INTERVAL (int interval)"
|
||||
/* The interval between cache cleanup runs. Specify a null
|
||||
/* validator or interval to stop cache cleanup.
|
||||
/* .IP "DICT_CACHE_CTL_VALIDATOR (DICT_CACHE_VALIDATOR_FN validator)"
|
||||
/* An application call-back routine that returns non-zero when
|
||||
/* a cache entry should be kept. The call-back function should
|
||||
/* not make changes to the cache. Specify a null validator or
|
||||
/* interval to stop cache cleanup.
|
||||
/* .IP "DICT_CACHE_CTL_CONTEXT (char *context)"
|
||||
/* Application context that is passed to the validator function.
|
||||
/* .RE
|
||||
/* .PP
|
||||
/* dict_cache_name() returns the name of the specified cache.
|
||||
/*
|
||||
/* dict_cache_import() encapsulates a pre-opened database
|
||||
/* handle and adds the above features.
|
||||
/*
|
||||
/* Arguments:
|
||||
/* .IP "dbname, open_flags, dict_flags"
|
||||
/* These are passed unchanged to dict_open().
|
||||
/* These are passed unchanged to dict_open(). The cache must
|
||||
/* be opened with DICT_FLAG_DUP_REPLACE.
|
||||
/* .IP cache
|
||||
/* Cache handle created with dict_cache_open()or dict_cache_import().
|
||||
/* Cache handle created with dict_cache_open().
|
||||
/* .IP cache_key
|
||||
/* Cache lookup key.
|
||||
/* .IP cache_val
|
||||
@ -121,24 +138,6 @@
|
||||
/* Note: there is no "stop" request. To ensure that the "delete
|
||||
/* behind" strategy does not interfere with database access,
|
||||
/* allow dict_cache_sequence() to run to completion.
|
||||
/* .IP flags
|
||||
/* Bit-wise OR of zero or more of the following:
|
||||
/* .RS
|
||||
/* .IP DICT_CACHE_FLAG_EXP_VERBOSE
|
||||
/* Log each cache entry's status during a cache cleanup run.
|
||||
/* .IP DICT_CACHE_FLAG_EXP_SUMMARY
|
||||
/* Log the number of cache entries retained and dropped after
|
||||
/* a cache cleaning run.
|
||||
/* .RE
|
||||
/* .IP interval
|
||||
/* The non-zero time between scans for expired cache entries.
|
||||
/* The interval timer starts after a scan completes.
|
||||
/* .IP validator
|
||||
/* Application call-back routine that returns non-zero when a
|
||||
/* cache entry should be kept. The validator must not modify
|
||||
/* or close the cache.
|
||||
/* .IP context
|
||||
/* Application-specific context.
|
||||
/* .IP table
|
||||
/* A bare dictonary handle.
|
||||
/* DIAGNOSTICS
|
||||
@ -198,15 +197,15 @@
|
||||
* underlying database.
|
||||
*/
|
||||
struct DICT_CACHE {
|
||||
int flags; /* see below */
|
||||
int cache_flags; /* see below */
|
||||
int user_flags; /* logging */
|
||||
DICT *db; /* database handle */
|
||||
|
||||
/* Iterator support. */
|
||||
/* Delete-behind support. */
|
||||
char *saved_curr_key; /* "current" cache lookup key */
|
||||
char *saved_curr_val; /* "current" cache lookup result */
|
||||
|
||||
/* Cleanup support. */
|
||||
int exp_flags; /* logging */
|
||||
int exp_interval; /* time between cleanup runs */
|
||||
DICT_CACHE_VALIDATOR_FN exp_validator; /* expiration call-back */
|
||||
char *exp_context; /* call-back context */
|
||||
@ -220,20 +219,20 @@ struct DICT_CACHE {
|
||||
* Macros to make obscure code more readable.
|
||||
*/
|
||||
#define DC_SCHEDULE_FOR_DELETE_BEHIND(cp) \
|
||||
((cp)->flags |= DC_FLAG_DEL_SAVED_CURRENT_KEY)
|
||||
((cp)->cache_flags |= DC_FLAG_DEL_SAVED_CURRENT_KEY)
|
||||
|
||||
#define DC_MATCH_SAVED_CURRENT_KEY(cp, cache_key) \
|
||||
((cp)->saved_curr_key && strcmp((cp)->saved_curr_key, (cache_key)) == 0)
|
||||
|
||||
#define DC_IS_SCHEDULED_FOR_DELETE_BEHIND(cp) \
|
||||
(/* NOT: (cp)->saved_curr_key && */ \
|
||||
((cp)->flags & DC_FLAG_DEL_SAVED_CURRENT_KEY) != 0)
|
||||
((cp)->cache_flags & DC_FLAG_DEL_SAVED_CURRENT_KEY) != 0)
|
||||
|
||||
#define DC_CANCEL_DELETE_BEHIND(cp) \
|
||||
((cp)->flags &= ~DC_FLAG_DEL_SAVED_CURRENT_KEY)
|
||||
((cp)->cache_flags &= ~DC_FLAG_DEL_SAVED_CURRENT_KEY)
|
||||
|
||||
/*
|
||||
* Special key to store the time of last cache cleanup run completion.
|
||||
* Special key to store the time of the last cache cleanup run completion.
|
||||
*/
|
||||
#define DC_LAST_CACHE_CLEANUP_COMPLETED "_LAST_CACHE_CLEANUP_COMPLETED_"
|
||||
|
||||
@ -241,16 +240,25 @@ struct DICT_CACHE {
|
||||
|
||||
const char *dict_cache_lookup(DICT_CACHE *cp, const char *cache_key)
|
||||
{
|
||||
const char *myname = "dict_cache_lookup";
|
||||
const char *cache_val;
|
||||
|
||||
/*
|
||||
* Search for the cache entry. Don't return an entry that was scheduled
|
||||
* for deletion.
|
||||
* Search for the cache entry. Don't return an entry that is scheduled
|
||||
* for delete-behind.
|
||||
*/
|
||||
if (DC_IS_SCHEDULED_FOR_DELETE_BEHIND(cp)
|
||||
&& DC_MATCH_SAVED_CURRENT_KEY(cp, cache_key)) {
|
||||
if (cp->user_flags & DICT_CACHE_FLAG_VERBOSE)
|
||||
msg_info("%s: key=%s (pretend not found - scheduled for deletion)",
|
||||
myname, cache_key);
|
||||
return (0);
|
||||
} else {
|
||||
return (dict_get(cp->db, cache_key));
|
||||
cache_val = dict_get(cp->db, cache_key);
|
||||
if (cp->user_flags & DICT_CACHE_FLAG_VERBOSE)
|
||||
msg_info("%s: key=%s value=%s", myname, cache_key,
|
||||
cache_val ? cache_val : "(not found)");
|
||||
return (cache_val);
|
||||
}
|
||||
}
|
||||
|
||||
@ -259,13 +267,19 @@ const char *dict_cache_lookup(DICT_CACHE *cp, const char *cache_key)
|
||||
void dict_cache_update(DICT_CACHE *cp, const char *cache_key,
|
||||
const char *cache_val)
|
||||
{
|
||||
const char *myname = "dict_cache_update";
|
||||
|
||||
/*
|
||||
* Store the cache entry and cancel a scheduled delete-behind operation.
|
||||
* Store the cache entry and cancel the delete-behind operation.
|
||||
*/
|
||||
if (DC_IS_SCHEDULED_FOR_DELETE_BEHIND(cp)
|
||||
&& DC_MATCH_SAVED_CURRENT_KEY(cp, cache_key))
|
||||
&& DC_MATCH_SAVED_CURRENT_KEY(cp, cache_key)) {
|
||||
if (cp->user_flags & DICT_CACHE_FLAG_VERBOSE)
|
||||
msg_info("%s: cancel delete-behind for key=%s", myname, cache_key);
|
||||
DC_CANCEL_DELETE_BEHIND(cp);
|
||||
}
|
||||
if (cp->user_flags & DICT_CACHE_FLAG_VERBOSE)
|
||||
msg_info("%s: key=%s value=%s", myname, cache_key, cache_val);
|
||||
dict_put(cp->db, cache_key, cache_val);
|
||||
}
|
||||
|
||||
@ -273,18 +287,25 @@ void dict_cache_update(DICT_CACHE *cp, const char *cache_key,
|
||||
|
||||
int dict_cache_delete(DICT_CACHE *cp, const char *cache_key)
|
||||
{
|
||||
const char *myname = "dict_cache_delete";
|
||||
int zero_means_found;
|
||||
|
||||
/*
|
||||
* Delete the entry, unless we would delete the current first/next entry.
|
||||
* Instead, schedule the "current" entry for delete-behind to avoid
|
||||
* In that case, schedule the "current" entry for delete-behind to avoid
|
||||
* mis-behavior by some databases.
|
||||
*/
|
||||
if (DC_MATCH_SAVED_CURRENT_KEY(cp, cache_key)) {
|
||||
DC_SCHEDULE_FOR_DELETE_BEHIND(cp);
|
||||
if (cp->user_flags & DICT_CACHE_FLAG_VERBOSE)
|
||||
msg_info("%s: key=%s (current entry - schedule for delete-behind)",
|
||||
myname, cache_key);
|
||||
zero_means_found = 0;
|
||||
} else {
|
||||
zero_means_found = dict_del(cp->db, cache_key);
|
||||
if (cp->user_flags & DICT_CACHE_FLAG_VERBOSE)
|
||||
msg_info("%s: key=%s (%s)", myname, cache_key,
|
||||
zero_means_found == 0 ? "found" : "not found");
|
||||
}
|
||||
return (zero_means_found);
|
||||
}
|
||||
@ -295,6 +316,7 @@ int dict_cache_sequence(DICT_CACHE *cp, int first_next,
|
||||
const char **cache_key,
|
||||
const char **cache_val)
|
||||
{
|
||||
const char *myname = "dict_cache_sequence";
|
||||
int zero_means_found;
|
||||
const char *raw_cache_key;
|
||||
const char *raw_cache_val;
|
||||
@ -311,6 +333,10 @@ int dict_cache_sequence(DICT_CACHE *cp, int first_next,
|
||||
&& strcmp(raw_cache_key, DC_LAST_CACHE_CLEANUP_COMPLETED) == 0)
|
||||
zero_means_found =
|
||||
dict_seq(cp->db, DICT_SEQ_FUN_NEXT, &raw_cache_key, &raw_cache_val);
|
||||
if (cp->user_flags & DICT_CACHE_FLAG_VERBOSE)
|
||||
msg_info("%s: key=%s value=%s", myname,
|
||||
zero_means_found == 0 ? raw_cache_key : "(not found)",
|
||||
zero_means_found == 0 ? raw_cache_val : "(not found)");
|
||||
|
||||
/*
|
||||
* Save the current cache_key and cache_val before they are clobbered by
|
||||
@ -335,6 +361,9 @@ int dict_cache_sequence(DICT_CACHE *cp, int first_next,
|
||||
*/
|
||||
if (DC_IS_SCHEDULED_FOR_DELETE_BEHIND(cp)) {
|
||||
DC_CANCEL_DELETE_BEHIND(cp);
|
||||
if (cp->user_flags & DICT_CACHE_FLAG_VERBOSE)
|
||||
msg_info("%s: delete-behind key=%s value=%s",
|
||||
myname, previous_curr_key, previous_curr_val);
|
||||
if (dict_del(cp->db, previous_curr_key) != 0)
|
||||
msg_warn("database %s: could not delete entry for %s",
|
||||
cp->db->name, previous_curr_key);
|
||||
@ -370,18 +399,19 @@ static void dict_cache_delete_behind_reset(DICT_CACHE *cp)
|
||||
/* dict_cache_clean_stat_log_reset - log and reset cache cleanup statistics */
|
||||
|
||||
static void dict_cache_clean_stat_log_reset(DICT_CACHE *cp,
|
||||
const char *full_partial)
|
||||
const char *full_partial)
|
||||
{
|
||||
if (cp->flags & DICT_CACHE_FLAG_EXP_SUMMARY)
|
||||
if (cp->user_flags & DICT_CACHE_FLAG_STATISTICS)
|
||||
msg_info("cache %s %s cleanup: retained=%d dropped=%d entries",
|
||||
cp->db->name, full_partial, cp->retained, cp->dropped);
|
||||
cp->retained = cp->dropped = 0;
|
||||
}
|
||||
|
||||
/* dict_cache_expire_event - examine one cache entry */
|
||||
/* dict_cache_clean_event - examine one cache entry */
|
||||
|
||||
static void dict_cache_expire_event(int unused_event, char *cache_context)
|
||||
static void dict_cache_clean_event(int unused_event, char *cache_context)
|
||||
{
|
||||
const char *myname = "dict_cache_clean_event";
|
||||
DICT_CACHE *cp = (DICT_CACHE *) cache_context;
|
||||
const char *cache_key;
|
||||
const char *cache_val;
|
||||
@ -401,8 +431,8 @@ static void dict_cache_expire_event(int unused_event, char *cache_context)
|
||||
if (cp->saved_curr_key == 0) {
|
||||
cp->retained = cp->dropped = 0;
|
||||
first_next = DICT_SEQ_FUN_FIRST;
|
||||
if (cp->exp_flags & DICT_CACHE_FLAG_EXP_VERBOSE)
|
||||
msg_info("start %s cache cleanup", cp->db->name);
|
||||
if (cp->user_flags & DICT_CACHE_FLAG_VERBOSE)
|
||||
msg_info("%s: start %s cache cleanup", myname, cp->db->name);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -419,12 +449,14 @@ static void dict_cache_expire_event(int unused_event, char *cache_context)
|
||||
if (cp->exp_validator(cache_key, cache_val, cp->exp_context) == 0) {
|
||||
DC_SCHEDULE_FOR_DELETE_BEHIND(cp);
|
||||
cp->dropped++;
|
||||
if (cp->exp_flags & DICT_CACHE_FLAG_EXP_VERBOSE)
|
||||
msg_info("drop %s cache entry for %s", cp->db->name, cache_key);
|
||||
if (cp->user_flags & DICT_CACHE_FLAG_VERBOSE)
|
||||
msg_info("%s: drop %s cache entry for %s",
|
||||
myname, cp->db->name, cache_key);
|
||||
} else {
|
||||
cp->retained++;
|
||||
if (cp->exp_flags & DICT_CACHE_FLAG_EXP_VERBOSE)
|
||||
msg_info("keep %s cache entry for %s", cp->db->name, cache_key);
|
||||
if (cp->user_flags & DICT_CACHE_FLAG_VERBOSE)
|
||||
msg_info("%s: keep %s cache entry for %s",
|
||||
myname, cp->db->name, cache_key);
|
||||
}
|
||||
next_interval = 0;
|
||||
}
|
||||
@ -433,8 +465,8 @@ static void dict_cache_expire_event(int unused_event, char *cache_context)
|
||||
* Cache cleanup completed. Report vital statistics.
|
||||
*/
|
||||
else {
|
||||
if (cp->exp_flags & DICT_CACHE_FLAG_EXP_VERBOSE)
|
||||
msg_info("done %s cache cleanup scan", cp->db->name);
|
||||
if (cp->user_flags & DICT_CACHE_FLAG_VERBOSE)
|
||||
msg_info("%s: done %s cache cleanup scan", myname, cp->db->name);
|
||||
dict_cache_clean_stat_log_reset(cp, "full");
|
||||
stamp_buf = vstring_alloc(100);
|
||||
vstring_sprintf(stamp_buf, "%ld", (long) event_time());
|
||||
@ -443,37 +475,60 @@ static void dict_cache_expire_event(int unused_event, char *cache_context)
|
||||
vstring_free(stamp_buf);
|
||||
next_interval = cp->exp_interval;
|
||||
}
|
||||
event_request_timer(dict_cache_expire_event, cache_context, next_interval);
|
||||
event_request_timer(dict_cache_clean_event, cache_context, next_interval);
|
||||
}
|
||||
|
||||
/* dict_cache_expire - schedule or stop the cache cleanup thread */
|
||||
/* dict_cache_control - schedule or stop the cache cleanup thread */
|
||||
|
||||
void dict_cache_expire(DICT_CACHE *cp, int flags, int interval,
|
||||
DICT_CACHE_VALIDATOR_FN validator,
|
||||
char *context)
|
||||
void dict_cache_control(DICT_CACHE *cp,...)
|
||||
{
|
||||
const char *myname = "dict_cache_expire";
|
||||
const char *myname = "dict_cache_control";
|
||||
const char *last_done;
|
||||
time_t next_interval;
|
||||
int cache_cleanup_is_active = (cp->exp_validator && cp->exp_interval);
|
||||
va_list ap;
|
||||
int name;
|
||||
|
||||
/*
|
||||
* Update the control settings.
|
||||
*/
|
||||
va_start(ap, cp);
|
||||
while ((name = va_arg(ap, int)) > 0) {
|
||||
switch (name) {
|
||||
case DICT_CACHE_CTL_END:
|
||||
break;
|
||||
case DICT_CACHE_CTL_FLAGS:
|
||||
cp->user_flags = va_arg(ap, int);
|
||||
break;
|
||||
case DICT_CACHE_CTL_INTERVAL:
|
||||
cp->exp_interval = va_arg(ap, int);
|
||||
if (cp->exp_interval < 0)
|
||||
msg_panic("%s: bad %s cache cleanup interval %d",
|
||||
myname, cp->db->name, cp->exp_interval);
|
||||
break;
|
||||
case DICT_CACHE_CTL_VALIDATOR:
|
||||
cp->exp_validator = va_arg(ap, DICT_CACHE_VALIDATOR_FN);
|
||||
break;
|
||||
case DICT_CACHE_CTL_CONTEXT:
|
||||
cp->exp_context = va_arg(ap, char *);
|
||||
break;
|
||||
default:
|
||||
msg_panic("%s: bad command: %d", myname, name);
|
||||
}
|
||||
}
|
||||
va_end(ap);
|
||||
|
||||
/*
|
||||
* Schedule the cache cleanup thread.
|
||||
*/
|
||||
if (validator != 0) {
|
||||
if (cp->exp_interval && cp->exp_validator) {
|
||||
|
||||
/*
|
||||
* Sanity checks.
|
||||
*/
|
||||
if (cp->exp_validator != 0)
|
||||
if (cache_cleanup_is_active)
|
||||
msg_panic("%s: %s cache cleanup is already scheduled",
|
||||
myname, cp->db->name);
|
||||
if (interval <= 0)
|
||||
msg_panic("%s: bad %s cache cleanup interval %d",
|
||||
myname, cp->db->name, interval);
|
||||
cp->exp_flags = flags;
|
||||
cp->exp_interval = interval;
|
||||
cp->exp_validator = validator;
|
||||
cp->exp_context = context;
|
||||
|
||||
/*
|
||||
* The next start time depends on the last completion time.
|
||||
@ -482,28 +537,25 @@ void dict_cache_expire(DICT_CACHE *cp, int flags, int interval,
|
||||
#define NOW (time((time_t *) 0)) /* NOT: event_time() */
|
||||
|
||||
if ((last_done = dict_get(cp->db, DC_LAST_CACHE_CLEANUP_COMPLETED)) == 0
|
||||
|| (next_interval = (NEXT_START(last_done, interval) - NOW)) < 0)
|
||||
|| (next_interval = (NEXT_START(last_done, cp->exp_interval) - NOW)) < 0)
|
||||
next_interval = 0;
|
||||
if (next_interval > interval)
|
||||
next_interval = interval;
|
||||
if ((cp->exp_flags & DICT_CACHE_FLAG_EXP_VERBOSE) && next_interval > 0)
|
||||
if (next_interval > cp->exp_interval)
|
||||
next_interval = cp->exp_interval;
|
||||
if ((cp->user_flags & DICT_CACHE_FLAG_VERBOSE) && next_interval > 0)
|
||||
msg_info("%s cache cleanup will start after %ds",
|
||||
cp->db->name, (int) next_interval);
|
||||
event_request_timer(dict_cache_expire_event, (char *) cp,
|
||||
event_request_timer(dict_cache_clean_event, (char *) cp,
|
||||
(int) next_interval);
|
||||
}
|
||||
|
||||
/*
|
||||
* Cancel the cache cleanup thread.
|
||||
*/
|
||||
else if (cp->exp_validator) {
|
||||
else if (cache_cleanup_is_active) {
|
||||
if (cp->retained || cp->dropped)
|
||||
dict_cache_clean_stat_log_reset(cp, "partial");
|
||||
dict_cache_delete_behind_reset(cp);
|
||||
cp->exp_interval = 0;
|
||||
cp->exp_validator = 0;
|
||||
cp->exp_context = 0;
|
||||
event_cancel_timer(dict_cache_expire_event, (char *) cp);
|
||||
event_cancel_timer(dict_cache_clean_event, (char *) cp);
|
||||
}
|
||||
}
|
||||
|
||||
@ -511,6 +563,7 @@ void dict_cache_expire(DICT_CACHE *cp, int flags, int interval,
|
||||
|
||||
DICT_CACHE *dict_cache_open(const char *dbname, int open_flags, int dict_flags)
|
||||
{
|
||||
DICT_CACHE *cp;
|
||||
DICT *dict;
|
||||
|
||||
/*
|
||||
@ -518,20 +571,13 @@ DICT_CACHE *dict_cache_open(const char *dbname, int open_flags, int dict_flags)
|
||||
* application.
|
||||
*/
|
||||
dict = dict_open(dbname, open_flags, dict_flags);
|
||||
return (dict_cache_import(dict));
|
||||
}
|
||||
|
||||
/* dict_cache_import - encapsulate pre-opened database */
|
||||
|
||||
DICT_CACHE *dict_cache_import(DICT *dict)
|
||||
{
|
||||
DICT_CACHE *cp;
|
||||
|
||||
/*
|
||||
* Create the DICT_CACHE object.
|
||||
*/
|
||||
cp = (DICT_CACHE *) mymalloc(sizeof(*cp));
|
||||
cp->flags = 0;
|
||||
cp->cache_flags = 0;
|
||||
cp->user_flags = 0;
|
||||
cp->db = dict;
|
||||
cp->saved_curr_key = 0;
|
||||
cp->saved_curr_val = 0;
|
||||
@ -552,8 +598,7 @@ void dict_cache_close(DICT_CACHE *cp)
|
||||
/*
|
||||
* Destroy the DICT_CACHE object.
|
||||
*/
|
||||
if (cp->exp_validator)
|
||||
dict_cache_expire(cp, 0, 0, (DICT_CACHE_VALIDATOR_FN) 0, (char *) 0);
|
||||
dict_cache_control(cp, DICT_CACHE_CTL_INTERVAL, 0, DICT_CACHE_CTL_END);
|
||||
dict_close(cp->db);
|
||||
if (cp->saved_curr_key)
|
||||
myfree(cp->saved_curr_key);
|
||||
|
@ -28,12 +28,17 @@ extern const char *dict_cache_lookup(DICT_CACHE *, const char *);
|
||||
extern void dict_cache_update(DICT_CACHE *, const char *, const char *);
|
||||
extern int dict_cache_delete(DICT_CACHE *, const char *);
|
||||
extern int dict_cache_sequence(DICT_CACHE *, int, const char **, const char **);
|
||||
extern void dict_cache_expire(DICT_CACHE *, int, int, DICT_CACHE_VALIDATOR_FN, char *);
|
||||
extern void dict_cache_control(DICT_CACHE *,...);
|
||||
extern const char *dict_cache_name(DICT_CACHE *);
|
||||
extern DICT_CACHE *dict_cache_import(DICT *);
|
||||
|
||||
#define DICT_CACHE_FLAG_EXP_VERBOSE (1<<0)
|
||||
#define DICT_CACHE_FLAG_EXP_SUMMARY (1<<1)
|
||||
#define DICT_CACHE_FLAG_VERBOSE (1<<0) /* verbose operation */
|
||||
#define DICT_CACHE_FLAG_STATISTICS (1<<1) /* log cache statistics */
|
||||
|
||||
#define DICT_CACHE_CTL_END 0 /* list terminator */
|
||||
#define DICT_CACHE_CTL_FLAGS 1 /* see above */
|
||||
#define DICT_CACHE_CTL_INTERVAL 2 /* cleanup interval */
|
||||
#define DICT_CACHE_CTL_VALIDATOR 3 /* call-back validator */
|
||||
#define DICT_CACHE_CTL_CONTEXT 4 /* call-back context */
|
||||
|
||||
/* LICENSE
|
||||
/* .ad
|
||||
|
@ -6,17 +6,15 @@
|
||||
/* SYNOPSIS
|
||||
/* #include <dict_ht.h>
|
||||
/*
|
||||
/* DICT *dict_ht_open(name, table, remove)
|
||||
/* DICT *dict_ht_open(name, open_flags, dict_flags)
|
||||
/* const char *name;
|
||||
/* HTABLE *table;
|
||||
/* void (*remove)(char *value)
|
||||
/* int open_flags;
|
||||
/* int dict_flags;
|
||||
/* DESCRIPTION
|
||||
/* dict_ht_open() makes specified hash table accessible via the
|
||||
/* generic dictionary operations documented in dict_open(3).
|
||||
/* \fIremove\fR specifies an optional callback function
|
||||
/* that is called by the hash table manager when the hash table is
|
||||
/* removed from the dictionary manager's care. The hash table is not
|
||||
/* destroyed when \fIremove\fR is a null pointer.
|
||||
/* dict_ht_open() creates a memory-resident hash table and
|
||||
/* makes it accessible via the generic dictionary operations
|
||||
/* documented in dict_open(3). The open_flags argument is
|
||||
/* ignored.
|
||||
/* SEE ALSO
|
||||
/* dict(3) generic dictionary manager
|
||||
/* LICENSE
|
||||
@ -40,13 +38,14 @@
|
||||
#include "htable.h"
|
||||
#include "dict.h"
|
||||
#include "dict_ht.h"
|
||||
#include "stringops.h"
|
||||
#include "vstring.h"
|
||||
|
||||
/* Application-specific. */
|
||||
|
||||
typedef struct {
|
||||
DICT dict; /* generic members */
|
||||
HTABLE *table; /* hash table */
|
||||
void (*remove) (char *); /* callback */
|
||||
} DICT_HT;
|
||||
|
||||
/* dict_ht_lookup - find hash-table entry */
|
||||
@ -57,6 +56,15 @@ static const char *dict_ht_lookup(DICT *dict, const char *name)
|
||||
|
||||
dict_errno = 0;
|
||||
|
||||
/*
|
||||
* Optionally fold the key.
|
||||
*/
|
||||
if (dict->flags & DICT_FLAG_FOLD_FIX) {
|
||||
if (dict->fold_buf == 0)
|
||||
dict->fold_buf = vstring_alloc(10);
|
||||
vstring_strcpy(dict->fold_buf, name);
|
||||
name = lowercase(vstring_str(dict->fold_buf));
|
||||
}
|
||||
return (htable_find(dict_ht->table, name));
|
||||
}
|
||||
|
||||
@ -67,6 +75,15 @@ static void dict_ht_update(DICT *dict, const char *name, const char *value)
|
||||
DICT_HT *dict_ht = (DICT_HT *) dict;
|
||||
HTABLE_INFO *ht;
|
||||
|
||||
/*
|
||||
* Optionally fold the key.
|
||||
*/
|
||||
if (dict->flags & DICT_FLAG_FOLD_FIX) {
|
||||
if (dict->fold_buf == 0)
|
||||
dict->fold_buf = vstring_alloc(10);
|
||||
vstring_strcpy(dict->fold_buf, name);
|
||||
name = lowercase(vstring_str(dict->fold_buf));
|
||||
}
|
||||
if ((ht = htable_locate(dict_ht->table, name)) != 0) {
|
||||
myfree(ht->value);
|
||||
} else {
|
||||
@ -104,14 +121,13 @@ static void dict_ht_close(DICT *dict)
|
||||
{
|
||||
DICT_HT *dict_ht = (DICT_HT *) dict;
|
||||
|
||||
if (dict_ht->remove)
|
||||
htable_free(dict_ht->table, dict_ht->remove);
|
||||
htable_free(dict_ht->table, myfree);
|
||||
dict_free(dict);
|
||||
}
|
||||
|
||||
/* dict_ht_open - create association with hash table */
|
||||
|
||||
DICT *dict_ht_open(const char *name, HTABLE *table, void (*remove) (char *))
|
||||
DICT *dict_ht_open(const char *name, int unused_open_flags, int dict_flags)
|
||||
{
|
||||
DICT_HT *dict_ht;
|
||||
|
||||
@ -120,7 +136,9 @@ DICT *dict_ht_open(const char *name, HTABLE *table, void (*remove) (char *))
|
||||
dict_ht->dict.update = dict_ht_update;
|
||||
dict_ht->dict.sequence = dict_ht_sequence;
|
||||
dict_ht->dict.close = dict_ht_close;
|
||||
dict_ht->table = table;
|
||||
dict_ht->remove = remove;
|
||||
dict_ht->dict.flags = dict_flags | DICT_FLAG_FIXED;
|
||||
if (dict_flags & DICT_FLAG_FOLD_FIX)
|
||||
dict_ht->dict.fold_buf = vstring_alloc(10);
|
||||
dict_ht->table = htable_create(0);
|
||||
return (&dict_ht->dict);
|
||||
}
|
||||
|
@ -22,7 +22,7 @@
|
||||
*/
|
||||
#define DICT_TYPE_HT "internal"
|
||||
|
||||
extern DICT *dict_ht_open(const char *, HTABLE *, void (*) (char *));
|
||||
extern DICT *dict_ht_open(const char *, int, int);
|
||||
|
||||
/* LICENSE
|
||||
/* .ad
|
||||
|
@ -203,6 +203,7 @@
|
||||
#include <dict_regexp.h>
|
||||
#include <dict_static.h>
|
||||
#include <dict_cidr.h>
|
||||
#include <dict_ht.h>
|
||||
#include <stringops.h>
|
||||
#include <split_at.h>
|
||||
#include <htable.h>
|
||||
@ -220,6 +221,7 @@ static const DICT_OPEN_INFO dict_open_info[] = {
|
||||
DICT_TYPE_CDB, dict_cdb_open,
|
||||
#endif
|
||||
DICT_TYPE_ENVIRON, dict_env_open,
|
||||
DICT_TYPE_HT, dict_ht_open,
|
||||
DICT_TYPE_UNIX, dict_unix_open,
|
||||
#ifdef SNAPSHOT
|
||||
DICT_TYPE_TCP, dict_tcp_open,
|
||||
|
@ -110,8 +110,8 @@
|
||||
/* event_drain() repeatedly calls event_loop() until no more timer
|
||||
/* events or I/O events are pending or until the time limit is reached.
|
||||
/* This routine must not be called from an event_whatever() callback
|
||||
/* routine. Note: this function ignores pending timer events, and
|
||||
/* assumes that no new I/O events will be registered.
|
||||
/* routine. Note: this function assumes that no new I/O events
|
||||
/* will be registered.
|
||||
/*
|
||||
/* event_fork() must be called by a child process after it is
|
||||
/* created with fork(), to re-initialize event processing.
|
||||
@ -912,6 +912,7 @@ time_t event_request_timer(EVENT_NOTIFY_TIME callback, char *context, int delay
|
||||
timer = RING_TO_TIMER(ring);
|
||||
if (timer->callback == callback && timer->context == context) {
|
||||
timer->when = event_present + delay;
|
||||
timer->loop_instance = event_loop_instance;
|
||||
ring_detach(ring);
|
||||
if (msg_verbose > 2)
|
||||
msg_info("%s: reset 0x%lx 0x%lx %d", myname,
|
||||
|
@ -343,7 +343,7 @@ HTABLE_INFO **htable_list(HTABLE *table)
|
||||
return (list);
|
||||
}
|
||||
|
||||
/* htable_sequence - dict_cache(3) compatibility iterator */
|
||||
/* htable_sequence - dict(3) compatibility iterator */
|
||||
|
||||
HTABLE_INFO *htable_sequence(HTABLE *table, int how)
|
||||
{
|
||||
|
@ -26,7 +26,7 @@ typedef struct HTABLE {
|
||||
int size; /* length of entries array */
|
||||
int used; /* number of entries in table */
|
||||
HTABLE_INFO **data; /* entries array, auto-resized */
|
||||
HTABLE_INFO **seq_bucket; /* current sequence bucket */
|
||||
HTABLE_INFO **seq_bucket; /* current sequence hash bucket */
|
||||
HTABLE_INFO *seq_element; /* current sequence element */
|
||||
} HTABLE;
|
||||
|
||||
|
@ -605,12 +605,15 @@ static void post_jail_init(char *unused_name, char **unused_argv)
|
||||
if (var_verify_scan_cache > 0) {
|
||||
int expire_flags;
|
||||
|
||||
expire_flags = DICT_CACHE_FLAG_EXP_SUMMARY;
|
||||
expire_flags = DICT_CACHE_FLAG_STATISTICS;
|
||||
if (msg_verbose)
|
||||
expire_flags |= DICT_CACHE_FLAG_EXP_VERBOSE;
|
||||
dict_cache_expire(verify_map, expire_flags, var_verify_scan_cache,
|
||||
verify_cache_validator,
|
||||
(char *) vstring_alloc(100));
|
||||
expire_flags |= DICT_CACHE_FLAG_VERBOSE;
|
||||
dict_cache_control(verify_map,
|
||||
DICT_CACHE_CTL_FLAGS, expire_flags,
|
||||
DICT_CACHE_CTL_INTERVAL, var_verify_scan_cache,
|
||||
DICT_CACHE_CTL_VALIDATOR, verify_cache_validator,
|
||||
DICT_CACHE_CTL_CONTEXT, (char *) vstring_alloc(100),
|
||||
DICT_CACHE_CTL_END);
|
||||
}
|
||||
}
|
||||
|
||||
@ -658,16 +661,13 @@ static void pre_jail_init(char *unused_name, char **unused_argv)
|
||||
*/
|
||||
#define VERIFY_DICT_OPEN_FLAGS (DICT_FLAG_DUP_REPLACE | DICT_FLAG_SYNC_UPDATE)
|
||||
|
||||
if (*var_verify_map) {
|
||||
saved_mask = umask(022);
|
||||
verify_map =
|
||||
dict_cache_open(data_redirect_map(redirect, var_verify_map),
|
||||
O_CREAT | O_RDWR, VERIFY_DICT_OPEN_FLAGS);
|
||||
(void) umask(saved_mask);
|
||||
} else {
|
||||
verify_map =
|
||||
dict_cache_import(dict_ht_open("verify", htable_create(0), myfree));
|
||||
}
|
||||
saved_mask = umask(022);
|
||||
verify_map =
|
||||
dict_cache_open(*var_verify_map ?
|
||||
data_redirect_map(redirect, var_verify_map) :
|
||||
"internal:verify",
|
||||
O_CREAT | O_RDWR, VERIFY_DICT_OPEN_FLAGS);
|
||||
(void) umask(saved_mask);
|
||||
|
||||
/*
|
||||
* Clean up and restore privilege.
|
||||
|
Loading…
x
Reference in New Issue
Block a user