]> git.ipfire.org Git - thirdparty/postfix.git/commitdiff
postfix-2.7-20100101
authorWietse Venema <wietse@porcupine.org>
Fri, 1 Jan 2010 05:00:00 +0000 (00:00 -0500)
committerViktor Dukhovni <viktor@dukhovni.org>
Tue, 5 Feb 2013 06:35:55 +0000 (06:35 +0000)
32 files changed:
postfix/HISTORY
postfix/README_FILES/DATABASE_README
postfix/RELEASE_NOTES
postfix/html/ADDRESS_REWRITING_README.html
postfix/html/DATABASE_README.html
postfix/html/MULTI_INSTANCE_README.html
postfix/html/SOHO_README.html
postfix/html/STANDARD_CONFIGURATION_README.html
postfix/html/VIRTUAL_README.html
postfix/html/postconf.1.html
postfix/html/postconf.5.html
postfix/html/virtual.5.html
postfix/man/man1/postconf.1
postfix/man/man5/postconf.5
postfix/mantools/postlink
postfix/proto/DATABASE_README.html
postfix/proto/postconf.proto
postfix/src/global/mail_version.h
postfix/src/postconf/postconf.c
postfix/src/postscreen/postscreen.c
postfix/src/smtpd/smtpd_exp.ref
postfix/src/util/Makefile.in
postfix/src/util/dict.c
postfix/src/util/dict_cache.c
postfix/src/util/dict_cache.h
postfix/src/util/dict_ht.c
postfix/src/util/dict_ht.h
postfix/src/util/dict_open.c
postfix/src/util/events.c
postfix/src/util/htable.c
postfix/src/util/htable.h
postfix/src/verify/verify.c

index 3911a488350ff4d1120e4f0219facbe4648fb971..7e074741d9b6aaeeac0bda936e9e523d221c9691 100644 (file)
@@ -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.
index 31796e0a68ed37da8e5d4157714d94cd183ce492..284f391e59138c0e46c5ef80fbe8830e2e082c6a 100644 (file)
@@ -204,6 +204,9 @@ To find out what database types your Postfix system supports, use the "p\bpo\bos\bs
         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.
+    i\bin\bnt\bte\ber\brn\bna\bal\bl
+        A non-shared, in-memory hash table. Its content are lost when a process
+        terminates.
     l\bld\bda\bap\bp (read-only)
         Perform lookups using the LDAP protocol. Configuration details are
         given in the ldap_table(5).
index 95f1d77df53df99f4d585392f2acd3ff8f6a1e1b..2782086a5becad73412772cce9b4b0c54dfcd762 100644 (file)
@@ -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
index 609060dea9856fd22c94f1a0e89a4afc427ca443..e934bf3107eaa1785586b9f4f724151a39ef05d0 100644 (file)
@@ -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>
index 642ce78c41574a012124c815bd09bed3df1c7333..5d85c8beeb47584f07964eb0bdd67447318ecad6 100644 (file)
@@ -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
index 502b22da4878b8cf72a0ea014ed6077693f7127a..9bd65467f664aad0715ffa60507f14f45c7e8282 100644 (file)
@@ -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
index 2e22103b440569456224f7373ac7cf7c53629b75..6d59437bc971ac0fa38bb894cbc20d08c4af0677 100644 (file)
@@ -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>
index bb746e369d6e399a77d1309736f15d2c1137487d..90a42fdf61035aabea5e5f66e605e5960b02b5ce 100644 (file)
@@ -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>
index 6b0d3abc0e2aafea12ce57d7482a2a250811ba67..9af7adbb8fe201d96dc73b514415bc686393f8bf 100644 (file)
@@ -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>
index 0a12cb19646ba3f2a191a61140411764f2ed1d28..8a4041dd325b2bc8099469d173231a57d4f0ac06 100644 (file)
@@ -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>
index 83c9a2abeb8f29b8e7554ff898ce134b0baa6fee..9bae584ca598033e145c933f453048a045b9f4f5 100644 (file)
@@ -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>
index c92826c651cfa25f26a56e25b50993dec08bfe64..5306885f21b6539a5bd9ecdbe407b4a66cd00d83 100644 (file)
@@ -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>
index 2468a03b4b54a0b969c18432042f49e0acaef9bc..530aa0677b623c00ba87db163b6cc8e503cbcc93 100644 (file)
@@ -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).
index 5d4c9ddad60a04187aea25159c11738eeb9bd7aa..7e5f62d27250ab4298dfed0241579bcc6ec07f9a 100644 (file)
@@ -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
index ad64fb78b7c6366dc319384d22f5cedc30ca046d..c01171bfcba4dd9ee7012348928260f82fc2a194 100755 (executable)
@@ -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)
index 36fbcb66a0b2935107d6c7d368f6480348139aef..b9ffa3a5292dd389f23e640c108277858d35b5b4 100644 (file)
@@ -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
index 5cb6237b266403dd483fd159c06af8ffa4238660..46070e5d95e8e951ac4100e5ad3137314e1cfc1f 100644 (file)
@@ -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
 
index 5da201516e3a6439042c1fa61c59e091ecb7eebe..ef6c78c8cfb9137ed3daab70dd5f0e79f42237f0 100644 (file)
@@ -20,7 +20,7 @@
   * Patches change both the patchlevel and the release date. Snapshots have no
   * patchlevel; they change the release date only.
   */
-#define MAIL_RELEASE_DATE      "20091229"
+#define MAIL_RELEASE_DATE      "20100101"
 #define MAIL_VERSION_NUMBER    "2.7"
 
 #ifdef SNAPSHOT
index cebe6cacbfd812d02ec5aed3cc6774f556459b61..d1ae43427bab09d957580010ef024300cf453ba7 100644 (file)
 /*     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).
index c0a6ede279f17ec36e57c7d152cbdc61faff6d82..bef281ff48d5a23b98fa45a379e5beb2c75a2344 100644 (file)
@@ -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;
index f514c545741574961e268dd5636620cc0fdb52cf..c4d518afa4dbfbe308fed57e9ca0497eac98f4c8 100644 (file)
@@ -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
index 48f9fae22c3f5ddd6c0bc1f45876b47e71a95950..4a808884052477c58c087529d15a0c5859b4e7c6 100644 (file)
@@ -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
index 68645d4015884aa21874533a9847fd6f7d8cd3a6..b8813f83170661be372ea8874ab2cbcfcdea210e 100644 (file)
@@ -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;
index 16e17037da4b52bdc682c23f00ed67e4aa595e03..e079dcbc08d5199a4b4b018f24ad42408c8195c8 100644 (file)
 /*     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
 /*     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
 /*
 /*     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
 /*     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
   * 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);
index 08523c4129b79aa55eeac150044913c1c47c1e6e..33d606124a438132b4b7151f791be2e605bb73de 100644 (file)
@@ -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
index 55b7c0d6210ef7235af80b5b612383acd6387434..8e44bad19d41cf58570fe0378eacc27783405432 100644 (file)
@@ -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
 #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);
 }
index c0b49654e12bb9ab3583db94652704431cd9a4a4..7cb31aa5f0506e950c71f6bf62cd60720ff751d5 100644 (file)
@@ -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
index beef2e6d222257307beb802960ab54366cdf822e..700eaee35e6a9b43949ab930eb6b124aa9978179 100644 (file)
 #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,
index c87dc5ce41d27a187c23448d698c3098b235f83a..485697c30999663c4533dda46aa404a2447374af 100644 (file)
 /*     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,
index aa87a3edfc3acbd7637ab643ae723c2edb48d772..3fc981a35558f60a7b03be495ea0b2ec9cdb83db 100644 (file)
@@ -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)
 {
index 23507b1a23ab2e50c2c6907482aa00e93e4715b6..d82e4056207e5835e4197e2eeb7e3f4bd83552f5 100644 (file)
@@ -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;
 
index 70a5a7158799fa199599edab7f65d0be5b75715c..43be02e272053c260dbdd2b965468846d73215bf 100644 (file)
@@ -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.