]> git.ipfire.org Git - thirdparty/postfix.git/commitdiff
snapshot-19990409
authorWietse Venema <wietse@porcupine.org>
Fri, 9 Apr 1999 05:00:00 +0000 (00:00 -0500)
committerWietse Venema <wietse@porcupine.org>
Thu, 17 Jan 2013 03:34:10 +0000 (22:34 -0500)
61 files changed:
postfix/.indent.pro
postfix/HISTORY
postfix/RELEASE_NOTES
postfix/bounce/.indent.pro
postfix/cleanup/.indent.pro
postfix/cleanup/cleanup.c
postfix/cleanup/cleanup.h
postfix/cleanup/cleanup_message.c
postfix/conf/main.cf
postfix/conf/main.cf.default
postfix/conf/sample-misc.cf
postfix/dns/.indent.pro
postfix/fsstone/.indent.pro
postfix/global/.indent.pro
postfix/global/deliver_flock.c
postfix/global/mail_params.c
postfix/global/mail_params.h
postfix/global/mail_version.h
postfix/html/uce.html
postfix/local/.indent.pro
postfix/local/local.c
postfix/master/.indent.pro
postfix/master/mail_server.h
postfix/master/multi_server.c
postfix/master/single_server.c
postfix/master/trigger_server.c
postfix/pickup/.indent.pro
postfix/pipe/.indent.pro
postfix/pipe/pipe.c
postfix/postalias/.indent.pro
postfix/postcat/.indent.pro
postfix/postconf/.indent.pro
postfix/postdrop/.indent.pro
postfix/postfix/.indent.pro
postfix/postkick/.indent.pro
postfix/postlock/.indent.pro
postfix/postlog/.indent.pro
postfix/postmap/.indent.pro
postfix/postsuper/.indent.pro
postfix/postsuper/postsuper.c
postfix/qmgr/.indent.pro
postfix/qmgr/qmgr.c
postfix/sendmail/.indent.pro
postfix/showq/.indent.pro
postfix/smtp/.indent.pro
postfix/smtp/smtp.c
postfix/smtpd/.indent.pro
postfix/smtpd/smtpd.c
postfix/smtpd/smtpd_state.c
postfix/smtpstone/.indent.pro
postfix/trivial-rewrite/.indent.pro
postfix/trivial-rewrite/trivial-rewrite.c
postfix/util/.indent.pro
postfix/util/Makefile.in
postfix/util/dict.c
postfix/util/dict.h
postfix/util/dict_db.c
postfix/util/dict_dbm.c
postfix/util/dict_open.c
postfix/util/watch_fd.c [new file with mode: 0644]
postfix/util/watch_fd.h [new file with mode: 0644]

index a39288416150661c21a3dc49ca2ff8e6c13e9aa9..7dd2776b00e928040cdd6cd35cdb3cc113d90787 100644 (file)
@@ -99,3 +99,4 @@
 -TVSTREAM
 -TVSTRING
 -TWAIT_STATUS_T
+-TWATCH_FD
index 86c376ed979708f7f9652a4659b26a3e30760ae2..4531b2e4e11913b18044ddae60050a014df7b082 100644 (file)
@@ -2568,12 +2568,34 @@ Apologies for any names omitted.
        Portability: on LINUX systems, if <db_185.h> exists, don't
        look for <db/db.h>.
 
-       Workaround: on Solaris 2.x, don't put an flock()/fcntl() lock
-       on mailboxes, to avoid clashes with the mailtool application.
+       Workaround: specify "sun_mailtool_compatibility = yes" to
+       avoid clashes with the mailtool application. This disables
+       kernel locks on mailbox files. Use only where needed.
 
        Portability: renamed readline to readlline, to avoid clashes
        with mysql.
 
+19990409
+
+       Bugfix: ignore temp queue files that aren't old enough.
+       Problem reported by Vivek Khera, Khera Communications, Inc.
+
+       Bugfix: fixed typo in dict_db.c that caused processes to
+       not release DB shared locks.
+
+       Feature: auto-detection of changes to DB or DBM lookup
+       tables.  This avoids the need to run "postfix reload" after
+       change to the smtp access table and other tables.
+
+       Feature: regular expression checks for message headers.
+       This requires support for POSIX or for PCRE regular
+       expressions.  Specify "header_checks = regexp:/file/name"
+       or "header_checks = pcre:/file/name", and specify
+       "/^header-name:  badstuff/ REJECT" in the pattern file
+       (patterns are case-insensitive by default).  Code by Lamont
+       Jones, Hewlett-Packard.  It is to be expected that full
+       content filtering will be delegated to an external command.
+
 Future:
 
        Planned: must be able to list the same hash table in
index 19725e1921ba34c912e8631f35e4a0ee744692a1..49cdc04121e6a43f36c82d8a8418cc54b9e5b868 100644 (file)
@@ -1,4 +1,4 @@
-Incompatible changes with snapshot-19990408:
+Incompatible changes with snapshot-19990409:
 ===========================================
 
 - If an address extension (+foo) matches a user's .forward+foo file
@@ -6,22 +6,35 @@ name, the +foo extension is no longer appended to recipient addresses
 listed in the .forward+foo file. This is more consistent with the
 way Postfix expands aliases.
 
-Major changes with snapshot-19990408:
+Major changes with snapshot-19990409:
 =====================================
 
 In addition to several little bugfixes, none related to security,
 lots of internal code cleanup, lots of new functionality, and lots
 of Solaris workarounds.
 
+- POSIX regular expression support, enabled by default on 4.4BSD,
+LINUX, and HP-UX. See conf/sample-regexp.cf.  Initial code by Lamont
+Jones, Hewlett-Packard, borrowing heavily from the PCRE implementation
+by Andrew McNamara, connect.com.au Pty. Ltd., Australia.
+
+- Regular expression checks for message headers.  This requires
+support for POSIX or for PCRE regular expressions.  Specify
+"header_checks = regexp:/file/name" or "header_checks = pcre:/file/name",
+and specify "/^header-name:  badstuff/ REJECT" in the pattern file
+(patterns are case-insensitive by default).  Code by Lamont Jones,
+Hewlett-Packard.  It is to be expected that full content filtering
+will be delegated to an external command.
+
 - Regular expression support for all lookup tables, including access
 control (full mail addresses only), address rewriting (canonical/virtual,
 full mail addresses only) and transport tables (full domain names
 only).  However, regular expressions are not allowed for aliases.
 
-- POSIX regular expression support, enabled by default on 4.4BSD,
-LINUX, and HP-UX. See conf/sample-regexp.cf.  Initial code by Lamont
-Jones, Hewlett-Packard, borrowing heavily from the PCRE implementation
-by Andrew McNamara, connect.com.au Pty. Ltd., Australia.
+- Automatic detection of changes to DB or DBM lookup tables.  This
+eliminates the need to run "postfix reload" after each change to
+the SMTP access table, or to the canonical, virtual, transport or
+aliases tables.
 
 - forward_path configuration parameter for .forward files (default:
 $home/.forward$recipient_delimiter$extension,$home/.forward).
@@ -34,8 +47,8 @@ Solaris UNIX-domain sockets, because they are still broken,
 even with Solaris 7.
 
 - Workaround for the Solaris mailtool, which keeps an exclusive
-fcntl/flock lock on the mailbox while its window is not iconified
-(specify "deliver_lock_disable = yes" in main.cf).
+kernel lock on the mailbox while its window is not iconified (specify
+"sun_mailtool_compatibility = yes" in main.cf).
 
 - Questionable workaround for Solaris, which reportedly loses
 long-lived exclusive locks that are held by the master daemon.
index a39288416150661c21a3dc49ca2ff8e6c13e9aa9..7dd2776b00e928040cdd6cd35cdb3cc113d90787 100644 (file)
@@ -99,3 +99,4 @@
 -TVSTREAM
 -TVSTRING
 -TWAIT_STATUS_T
+-TWATCH_FD
index a39288416150661c21a3dc49ca2ff8e6c13e9aa9..7dd2776b00e928040cdd6cd35cdb3cc113d90787 100644 (file)
@@ -99,3 +99,4 @@
 -TVSTREAM
 -TVSTRING
 -TWAIT_STATUS_T
+-TWATCH_FD
index 7666077f90ef3481195ccce6af3d053e73eaef38..367693634513daf100ab760ac8da934da81ba2a3 100644 (file)
 #include <vstream.h>
 #include <mymalloc.h>
 #include <iostuff.h>
+#include <dict.h>
 
 /* Global library. */
 
@@ -167,6 +168,7 @@ char   *var_rcpt_canon_maps;                /* recipient canonical maps */
 char   *var_virtual_maps;              /* virtual maps */
 char   *var_masq_domains;              /* masquerade domains */
 char   *var_masq_exceptions;           /* users not masqueraded */
+char   *var_header_checks;             /* any header checks */
 int     var_dup_filter_limit;          /* recipient dup filter */
 char   *var_empty_addr;                        /* destination of bounced bounces */
 int     var_delay_warn_time;           /* delay that triggers warning */
@@ -177,6 +179,7 @@ int     var_delay_warn_time;                /* delay that triggers warning */
 MAPS   *cleanup_comm_canon_maps;
 MAPS   *cleanup_send_canon_maps;
 MAPS   *cleanup_rcpt_canon_maps;
+MAPS   *cleanup_header_checks;
 MAPS   *cleanup_virtual_maps;
 ARGV   *cleanup_masq_domains;
 
@@ -389,6 +392,19 @@ static void pre_jail_init(void)
                                           DICT_FLAG_LOCK);
     if (*var_masq_domains)
        cleanup_masq_domains = argv_split(var_masq_domains, " ,\t\r\n");
+    if (*var_header_checks)
+       cleanup_header_checks = 
+           maps_create(VAR_HEADER_CHECKS, var_header_checks, DICT_FLAG_LOCK);
+}
+
+/* pre_accept - see if tables have changed */
+
+static void pre_accept(void)
+{
+    if (dict_changed()) {
+       msg_info("table has changed -- exiting");
+       exit(0);
+    }
 }
 
 /* post_jail_init - initialize after entering the chroot jail */
@@ -426,6 +442,7 @@ int     main(int argc, char **argv)
        VAR_MASQ_DOMAINS, DEF_MASQ_DOMAINS, &var_masq_domains, 0, 0,
        VAR_EMPTY_ADDR, DEF_EMPTY_ADDR, &var_empty_addr, 1, 0,
        VAR_MASQ_EXCEPTIONS, DEF_MASQ_EXCEPTIONS, &var_masq_exceptions, 0, 0,
+       VAR_HEADER_CHECKS, DEF_HEADER_CHECKS, &var_header_checks, 0, 0,
        0,
     };
 
@@ -444,5 +461,6 @@ int     main(int argc, char **argv)
                       MAIL_SERVER_STR_TABLE, str_table,
                       MAIL_SERVER_PRE_INIT, pre_jail_init,
                       MAIL_SERVER_POST_INIT, post_jail_init,
+                      MAIL_SERVER_PRE_ACCEPT, pre_accept,
                       0);
 }
index 56e42c28f9d316fe30684ce9c82ceda52ab0344b..7523262c6f927e80d9a4fee46362d7d4cd9704b8 100644 (file)
@@ -61,6 +61,7 @@ extern BH_TABLE *cleanup_dups;                /* recipient dup filter */
 extern MAPS *cleanup_comm_canon_maps;
 extern MAPS *cleanup_send_canon_maps;
 extern MAPS *cleanup_rcpt_canon_maps;
+extern MAPS *cleanup_header_checks;
 extern MAPS *cleanup_virtual_maps;
 extern ARGV *cleanup_masq_domains;
 
index 3e5d1dce1de8f00fea68bed4fe9d749d2d8b66d9..67a67919730f8dc22a329bb97ecb28fe130f8c12 100644 (file)
@@ -223,8 +223,23 @@ static void cleanup_rewrite_recip(HEADER_OPTS *hdr_opts)
 
 static void cleanup_header(void)
 {
+    char   *myname = "cleanup_header";
     HEADER_OPTS *hdr_opts;
 
+    if (msg_verbose)
+       msg_info("%s: '%s'", myname, vstring_str(cleanup_header_buf));
+
+    if (cleanup_header_checks) {
+       char   *header = vstring_str(cleanup_header_buf);
+       const char *value;
+
+       if ((value = maps_find(cleanup_header_checks, header, 0)) != 0) {
+           if (strcasecmp(value, "REJECT") == 0) {
+               msg_warn("%s: reject: header %.100s", cleanup_queue_id, header);
+               cleanup_errs |= CLEANUP_STAT_CONT;
+           }
+       }
+    }
 
     /*
      * If this is an "unknown" header, just copy it to the output without
index d47113a760f8a2dddd8efbea5c9433b79fe91d69..992cc849f689e170157f205ee1d9eaf41d249bcd 100644 (file)
@@ -259,6 +259,14 @@ program_directory = /some/where/postfix/bin
 # The controls listed here are only a very small subset. See the file
 # sample-smtpd.cf for an elaborate list of anti-UCE controls.
 
+# The header_checks parameter restricts what may appear in message
+# headers. This requires that POSIX or PCRE regular expression support
+# is built-in. Specify "/^header-name: stuff you don not want/ REJECT"
+# in the pattern file. Patterns are case-insensitive by default.
+#
+#header_checks = regexp:/etc/postfix/filename
+#header_checks = pcre:/etc/postfix/filename
+
 # The relay_domains parameter restricts what domains (and subdomains
 # thereof) this mail system will relay mail from or to.  See the
 # smtpd_recipient_restrictions restriction in the file sample-smtpd.cf.
index 6f6e351eb5ef6cb13653d3cd90c86ba1bad8d487..20a1312bbbfeb0330130409371d9d3faa4b1ddec 100644 (file)
@@ -30,7 +30,6 @@ delay_notice_recipient = postmaster
 delay_warning_time = 0
 deliver_lock_attempts = 5
 deliver_lock_delay = 1
-deliver_lock_disable = no
 disable_dns_lookups = no
 dont_remove = 0
 double_bounce_sender = double-bounce
@@ -44,6 +43,7 @@ fork_delay = 1
 forward_path = $home/.forward${recipient_delimiter}${extension},$home/.forward
 hash_queue_depth = 2
 hash_queue_names = defer
+header_checks = 
 header_size_limit = 102400
 home_mailbox = 
 hopcount_limit = 50
@@ -61,7 +61,7 @@ luser_relay =
 mail_name = Postfix
 mail_owner = postfix
 mail_spool_directory = /var/mail
-mail_version = Snapshot-19990408
+mail_version = Snapshot-19990409
 mailbox_command = 
 mailbox_transport = 
 maps_rbl_domains = rbl.maps.vix.com
@@ -122,6 +122,7 @@ smtpd_soft_error_limit = 10
 smtpd_timeout = 300
 soft_bounce = no
 stale_lock_time = 500
+sun_mailtool_compatibility = no
 swap_bangpath = yes
 transport_maps = 
 transport_retry_time = 60
index f6a1a92c8a7b455feef6f1009338d81b0ace8ec8..ca9df216687388ae63b531ea514f795916895c48 100644 (file)
@@ -28,15 +28,6 @@ daemon_timeout = 18000
 # default_transport = uucp
 default_transport = smtp
 
-# The deliver_lock_disable parameter disables fcntl/flock file locking
-# on mailboxes. This is needed on SUN workstations because the mailtool
-# program keeps an exclusive fcntl/flock lock while its window is open.
-# SUN software uses user.lock files only. Unless you remove all SUN
-# mail software, fcntl/flock just gives a false sense of security.
-#
-#deliver_lock_disable = yes
-deliver_lock_disable = no
-
 # The double_bounce_sender parameter specifies the sender address
 # for mail that must be discarded when it cannot be delivered. This
 # must be a unique name. All mail to this name is silently discarded,
@@ -266,6 +257,15 @@ relayhost =
 # relocated_maps = hash:/etc/postfix/relocated
 relocated_maps =
 
+# The sun_mailtool_compatibility parameter disables kernel file locks
+# on mailboxes. This is needed on SUN workstations because the mailtool
+# program keeps an exclusive kernel lock while its window is open.
+# SUN software uses user.lock files only. Unless you remove all SUN
+# mail software, kernel locks just give a false sense of security.
+#
+#sun_mailtool_compatibility = yes
+sun_mailtool_compatibility = no
+
 # The trigger_timeout parameter limits the time to send a trigger to
 # a Postfix daemon. This prevents programs from getting stuck when the
 # mail system is under heavy load.
index a39288416150661c21a3dc49ca2ff8e6c13e9aa9..7dd2776b00e928040cdd6cd35cdb3cc113d90787 100644 (file)
@@ -99,3 +99,4 @@
 -TVSTREAM
 -TVSTRING
 -TWAIT_STATUS_T
+-TWATCH_FD
index a39288416150661c21a3dc49ca2ff8e6c13e9aa9..7dd2776b00e928040cdd6cd35cdb3cc113d90787 100644 (file)
@@ -99,3 +99,4 @@
 -TVSTREAM
 -TVSTRING
 -TWAIT_STATUS_T
+-TWATCH_FD
index a39288416150661c21a3dc49ca2ff8e6c13e9aa9..7dd2776b00e928040cdd6cd35cdb3cc113d90787 100644 (file)
@@ -99,3 +99,4 @@
 -TVSTREAM
 -TVSTRING
 -TWAIT_STATUS_T
+-TWATCH_FD
index 7d97dba045b22ac1cc1237299b16ec4d78fa280a..5df58ada3d9bdf4a1fcf4c751c6d1ed6ca54e6be 100644 (file)
@@ -10,7 +10,7 @@
 /*     int     fd;
 /*     VSTRING *why;
 /* DESCRIPTION
-/*     deliver_flock() sets one exclusive lock on an open file
+/*     deliver_flock() sets one exclusive kernel lock on an open file
 /*     for the purpose of mail delivery. It attempts to acquire
 /*     the exclusive lock several times before giving up.
 /*
@@ -26,7 +26,7 @@
 /* CONFIGURATION PARAMETERS
 /*     deliver_lock_attempts, number of locking attempts
 /*     deliver_lock_delay, time in seconds between attempts
-/*     deliver_lock_disable, disable exclusive locking
+/*     sun_mailtool_compatibility, disable kernel locking
 /* LICENSE
 /* .ad
 /* .fi
@@ -59,7 +59,7 @@ int     deliver_flock(int fd, VSTRING *why)
 {
     int     i;
 
-    if (var_flock_disable)
+    if (var_mailtool_compat)
        return (0);
 
     for (i = 0; /* void */ ; i++) {
index 55862517b92736b3515189e4ffed36ec135d6b78..856156a920a83f14f41e5f764aabdc77e858c6b0 100644 (file)
@@ -51,7 +51,7 @@
 /*     int     var_flock_tries;
 /*     int     var_flock_delay;
 /*     int     var_flock_stale;
-/*     int     var_flock_disable;
+/*     int     var_mailtool_compat;
 /*     int     var_disable_dns;
 /*     int     var_soft_bounce;
 /*     time_t  var_starttime;
@@ -154,7 +154,7 @@ int     var_fork_delay;
 int     var_flock_tries;
 int     var_flock_delay;
 int     var_flock_stale;
-int     var_flock_disable;
+int     var_mailtool_compat;
 int     var_disable_dns;
 int     var_soft_bounce;
 time_t  var_starttime;
@@ -280,7 +280,7 @@ void    mail_params_init()
        VAR_DISABLE_DNS, DEF_DISABLE_DNS, &var_disable_dns,
        VAR_SOFT_BOUNCE, DEF_SOFT_BOUNCE, &var_soft_bounce,
        VAR_OWNREQ_SPECIAL, DEF_OWNREQ_SPECIAL, &var_ownreq_special,
-       VAR_FLOCK_DISABLE, DEF_FLOCK_DISABLE, &var_flock_disable,
+       VAR_MAILTOOL_COMPAT, DEF_MAILTOOL_COMPAT, &var_mailtool_compat,
        0,
     };
 
index a91c0feca0311ff6c05e5b3bbe9135bdf4b1ff1f..2c4a5280c5cc1fbdc09c6d35aef2b198e034ab87 100644 (file)
@@ -590,6 +590,10 @@ extern int var_message_limit;
 #define DEF_QUEUE_MINFREE      0
 extern int var_queue_minfree;
 
+#define VAR_HEADER_CHECKS      "header_checks"
+#define DEF_HEADER_CHECKS      ""
+extern char *var_header_checks;
+
  /*
   * Bounce service: truncate bounce message that exceed $bounce_size_limit.
   */
@@ -631,9 +635,9 @@ extern int var_flock_delay;
 #define DEF_FLOCK_STALE                500
 extern int var_flock_stale;
 
-#define VAR_FLOCK_DISABLE      "deliver_lock_disable"
-#define DEF_FLOCK_DISABLE      0
-extern int var_flock_disable;
+#define VAR_MAILTOOL_COMPAT    "sun_mailtool_compatibility"
+#define DEF_MAILTOOL_COMPAT    0
+extern int var_mailtool_compat;
 
  /*
   * How long a daemon command may take to receive or deliver a message etc.
index f4fb16867d17647c85f53510279a97c6d40139b7..2e4b49c4c2905879eeb232408ac072f07d647fe5 100644 (file)
@@ -15,7 +15,7 @@
   * Version of this program.
   */
 #define VAR_MAIL_VERSION       "mail_version"
-#define DEF_MAIL_VERSION       "Snapshot-19990408"
+#define DEF_MAIL_VERSION       "Snapshot-19990409"
 extern char *var_mail_version;
 
 /* LICENSE
index 8a93bbf86feb112c006792c6295cf1fb5e419d60..4fd7560001543a0beee744a6cba588492edfe519 100644 (file)
@@ -44,6 +44,10 @@ command.
 
 <ul>
 
+<li> <a href="#header_checks">Header filtering</a>
+
+<p>
+
 <li> <a href="#smtpd_client_restrictions">Client name/address
 restrictions</a>
 
@@ -80,6 +84,41 @@ restrictions</a>
 
 </ul>
 
+<a name="header_checks">
+
+<h2> Header filtering</h2>
+
+The <b>header_checks</b> parameter restricts what
+is allowed in message headers.
+
+<p>
+
+<dl>
+
+<dt>Default:
+
+<dd>Allow anything in message headers.
+
+<p>
+
+<dt>Syntax:
+
+<dd>Specify a list of zero or more lookup tables. Whenever a
+header matches a table, a REJECT result means reject the
+message; an OK result means pass.
+
+</dl>
+
+<p>
+
+<dt>Examples:
+
+<dd> <b>header_checks = regexp:/etc/postfix/header_checks</b>
+
+<dd> <b>header_checks = pcre:/etc/postfix/header_checks</b>
+
+<p>
+
 <a name="smtpd_client_restrictions">
 
 <h2> Client name/address restrictions</h2>
index a39288416150661c21a3dc49ca2ff8e6c13e9aa9..7dd2776b00e928040cdd6cd35cdb3cc113d90787 100644 (file)
@@ -99,3 +99,4 @@
 -TVSTREAM
 -TVSTRING
 -TWAIT_STATUS_T
+-TWATCH_FD
index ad1951a31d38838880e7a65c9ab76e106c7b6543..09d21b1d36b02066015aff913afe57574179fade 100644 (file)
 #include <iostuff.h>
 #include <name_mask.h>
 #include <set_eugid.h>
+#include <dict.h>
 
 /* Global library. */
 
@@ -501,6 +502,16 @@ static void local_mask_init(void)
     local_cmd_deliver_mask = name_mask(command_mask, var_allow_commands);
 }
 
+/* pre_accept - see if tables have changed */
+
+static void pre_accept(void)
+{
+    if (dict_changed()) {
+       msg_info("table has changed -- exiting");
+       exit(0);
+    }
+}
+
 /* post_init - post-jail initialization */
 
 static void post_init(void)
@@ -553,5 +564,6 @@ int     main(int argc, char **argv)
                       MAIL_SERVER_RAW_TABLE, raw_table,
                       MAIL_SERVER_BOOL_TABLE, bool_table,
                       MAIL_SERVER_POST_INIT, post_init,
+                      MAIL_SERVER_PRE_ACCEPT, pre_accept,
                       0);
 }
index a39288416150661c21a3dc49ca2ff8e6c13e9aa9..7dd2776b00e928040cdd6cd35cdb3cc113d90787 100644 (file)
@@ -99,3 +99,4 @@
 -TVSTREAM
 -TVSTRING
 -TWAIT_STATUS_T
+-TWATCH_FD
index c5f9b83ab79ab592d1d6bb1fad7b6fbdca9e04be..9bf37117cfa73444e7e3ab3d486c1d7d20d1d04c 100644 (file)
 #define MAIL_SERVER_POST_INIT  11
 #define MAIL_SERVER_LOOP       12
 #define MAIL_SERVER_EXIT       13
+#define MAIL_SERVER_PRE_ACCEPT 14
 
 typedef void (*MAIL_SERVER_INIT_FN) (void);
 typedef int (*MAIL_SERVER_LOOP_FN) (void);
 typedef void (*MAIL_SERVER_EXIT_FN) (void);
+typedef void (*MAIL_SERVER_ACCEPT_FN) (void);
 
  /*
   * single_server.c
index 0e8eb368b3f0c66087fc7859febea6917faadc5a..2f2cb4909039b540ab3100abdbcf8603b8eedebc 100644 (file)
@@ -80,6 +80,8 @@
 /* .IP "MAIL_SERVER_EXIT (void *(void))"
 /*     A pointer to function that is executed immediately before normal
 /*     process termination.
+/* .IP "MAIL_SERVER_PRE_ACCEPT (void *(void))"
+/*     Function to be executed prior to accepting a new connection.
 /* .PP
 /*     multi_server_disconnect() should be called by the application
 /*     when a client disconnects.
@@ -171,6 +173,7 @@ static char *multi_server_name;
 static char **multi_server_argv;
 static void (*multi_server_accept) (int, char *);
 static void (*multi_server_onexit) (void);
+static void (*multi_server_pre_accept) (void);
 static VSTREAM *multi_server_lock;
 
 /* multi_server_exit - normal termination */
@@ -287,6 +290,8 @@ static void multi_server_accept_local(int unused_event, char *context)
     if (client_count == 0 && var_idle_limit > 0)
        time_left = event_cancel_timer(multi_server_timeout, (char *) 0);
 
+    if (multi_server_pre_accept)
+       multi_server_pre_accept();
     fd = LOCAL_ACCEPT(listen_fd);
     if (multi_server_lock != 0
        && myflock(vstream_fileno(multi_server_lock), MYFLOCK_NONE) < 0)
@@ -422,6 +427,9 @@ NORETURN multi_server_main(int argc, char **argv, MULTI_SERVER_FN service,...)
        case MAIL_SERVER_EXIT:
            multi_server_onexit = va_arg(ap, MAIL_SERVER_EXIT_FN);
            break;
+       case MAIL_SERVER_PRE_ACCEPT:
+           multi_server_pre_accept = va_arg(ap, MAIL_SERVER_ACCEPT_FN);
+           break;
        default:
            msg_panic("%s: unknown argument type: %d", myname, key);
        }
index 8f37acd4d374c84c1a006b60f4cea324aebb28d8..b3084ab1a9bb55dec0a5f16092a1adb2013e859f 100644 (file)
@@ -75,6 +75,8 @@
 /* .IP "MAIL_SERVER_EXIT (void *(void))"
 /*     A pointer to function that is executed immediately before normal
 /*     process termination.
+/* .IP "MAIL_SERVER_PRE_ACCEPT (void *(void))"
+/*     Function to be executed prior to accepting a new connection.
 /* .PP
 /*     The var_use_limit variable limits the number of clients that
 /*     a server can service before it commits suicide.
@@ -161,6 +163,7 @@ static char *single_server_name;
 static char **single_server_argv;
 static void (*single_server_accept) (int, char *);
 static void (*single_server_onexit) (void);
+static void (*single_server_pre_accept) (void);
 static VSTREAM *single_server_lock;
 
 /* single_server_exit - normal termination */
@@ -257,6 +260,8 @@ static void single_server_accept_local(int unused_event, char *context)
     if (var_idle_limit > 0)
        time_left = event_cancel_timer(single_server_timeout, (char *) 0);
 
+    if (single_server_pre_accept)
+       single_server_pre_accept();
     fd = LOCAL_ACCEPT(listen_fd);
     if (single_server_lock != 0
        && myflock(vstream_fileno(single_server_lock), MYFLOCK_NONE) < 0)
@@ -391,6 +396,9 @@ NORETURN single_server_main(int argc, char **argv, SINGLE_SERVER_FN service,...)
        case MAIL_SERVER_EXIT:
            single_server_onexit = va_arg(ap, MAIL_SERVER_EXIT_FN);
            break;
+       case MAIL_SERVER_PRE_ACCEPT:
+           single_server_pre_accept = va_arg(ap, MAIL_SERVER_ACCEPT_FN);
+           break;
        default:
            msg_panic("%s: unknown argument type: %d", myname, key);
        }
index 2b5761b3b980861d438485aba468a8cff8c4dac8..1434617e7f2f707f9d273cbbc38397e751fd08ba 100644 (file)
@@ -82,6 +82,8 @@
 /* .IP "MAIL_SERVER_EXIT (void *(void))"
 /*     A pointer to function that is executed immediately before normal
 /*     process termination.
+/* .IP "MAIL_SERVER_PRE_ACCEPT (void *(void))"
+/*     Function to be executed prior to accepting a new request.
 /* .PP
 /*     The var_use_limit variable limits the number of clients that
 /*     a server can service before it commits suicide.
@@ -168,6 +170,7 @@ static char *trigger_server_name;
 static char **trigger_server_argv;
 static void (*trigger_server_accept) (int, char *);
 static void (*trigger_server_onexit) (void);
+static void (*trigger_server_pre_accept) (void);
 static VSTREAM *trigger_server_lock;
 
 /* trigger_server_exit - normal termination */
@@ -256,6 +259,8 @@ static void trigger_server_accept_fifo(int unused_event, char *context)
      * Read whatever the other side wrote into the FIFO. The FIFO read end is
      * non-blocking so we won't get stuck when multiple processes wake up.
      */
+    if (trigger_server_pre_accept)
+       trigger_server_pre_accept();
     trigger_server_wakeup(listen_fd);
 }
 
@@ -288,6 +293,8 @@ static void trigger_server_accept_local(int unused_event, char *context)
     if (var_idle_limit > 0)
        time_left = event_cancel_timer(trigger_server_timeout, (char *) 0);
 
+    if (trigger_server_pre_accept)
+       trigger_server_pre_accept();
     fd = LOCAL_ACCEPT(listen_fd);
     if (trigger_server_lock != 0
        && myflock(vstream_fileno(trigger_server_lock), MYFLOCK_NONE) < 0)
@@ -392,6 +399,9 @@ NORETURN trigger_server_main(int argc, char **argv, TRIGGER_SERVER_FN service,..
        case MAIL_SERVER_EXIT:
            trigger_server_onexit = va_arg(ap, MAIL_SERVER_EXIT_FN);
            break;
+       case MAIL_SERVER_PRE_ACCEPT:
+           trigger_server_pre_accept = va_arg(ap, MAIL_SERVER_ACCEPT_FN);
+           break;
        default:
            msg_panic("%s: unknown argument type: %d", myname, key);
        }
index a39288416150661c21a3dc49ca2ff8e6c13e9aa9..7dd2776b00e928040cdd6cd35cdb3cc113d90787 100644 (file)
@@ -99,3 +99,4 @@
 -TVSTREAM
 -TVSTRING
 -TWAIT_STATUS_T
+-TWATCH_FD
index a39288416150661c21a3dc49ca2ff8e6c13e9aa9..7dd2776b00e928040cdd6cd35cdb3cc113d90787 100644 (file)
@@ -99,3 +99,4 @@
 -TVSTREAM
 -TVSTRING
 -TWAIT_STATUS_T
+-TWATCH_FD
index 60c5e96a5413274a85294a7baff9b1f06671b6d7..cc2750112b87a4396ad8cd70af6043dcf2d30bcf 100644 (file)
@@ -675,6 +675,16 @@ static void pipe_service(VSTREAM *client_stream, char *service, char **argv)
     }
 }
 
+/* pre_accept - see if tables have changed */
+
+static void pre_accept(void)
+{
+    if (dict_changed()) {
+       msg_info("table has changed -- exiting");
+       exit(0);
+    }
+}
+
 /* drop_privileges - drop privileges most of the time */
 
 static void drop_privileges(void)
@@ -694,5 +704,6 @@ int     main(int argc, char **argv)
     single_server_main(argc, argv, pipe_service,
                       MAIL_SERVER_INT_TABLE, int_table,
                       MAIL_SERVER_POST_INIT, drop_privileges,
+                      MAIL_SERVER_PRE_ACCEPT, pre_accept,
                       0);
 }
index a39288416150661c21a3dc49ca2ff8e6c13e9aa9..7dd2776b00e928040cdd6cd35cdb3cc113d90787 100644 (file)
@@ -99,3 +99,4 @@
 -TVSTREAM
 -TVSTRING
 -TWAIT_STATUS_T
+-TWATCH_FD
index a39288416150661c21a3dc49ca2ff8e6c13e9aa9..7dd2776b00e928040cdd6cd35cdb3cc113d90787 100644 (file)
@@ -99,3 +99,4 @@
 -TVSTREAM
 -TVSTRING
 -TWAIT_STATUS_T
+-TWATCH_FD
index a39288416150661c21a3dc49ca2ff8e6c13e9aa9..7dd2776b00e928040cdd6cd35cdb3cc113d90787 100644 (file)
@@ -99,3 +99,4 @@
 -TVSTREAM
 -TVSTRING
 -TWAIT_STATUS_T
+-TWATCH_FD
index a39288416150661c21a3dc49ca2ff8e6c13e9aa9..7dd2776b00e928040cdd6cd35cdb3cc113d90787 100644 (file)
@@ -99,3 +99,4 @@
 -TVSTREAM
 -TVSTRING
 -TWAIT_STATUS_T
+-TWATCH_FD
index a39288416150661c21a3dc49ca2ff8e6c13e9aa9..7dd2776b00e928040cdd6cd35cdb3cc113d90787 100644 (file)
@@ -99,3 +99,4 @@
 -TVSTREAM
 -TVSTRING
 -TWAIT_STATUS_T
+-TWATCH_FD
index a39288416150661c21a3dc49ca2ff8e6c13e9aa9..7dd2776b00e928040cdd6cd35cdb3cc113d90787 100644 (file)
@@ -99,3 +99,4 @@
 -TVSTREAM
 -TVSTRING
 -TWAIT_STATUS_T
+-TWATCH_FD
index a39288416150661c21a3dc49ca2ff8e6c13e9aa9..7dd2776b00e928040cdd6cd35cdb3cc113d90787 100644 (file)
@@ -99,3 +99,4 @@
 -TVSTREAM
 -TVSTRING
 -TWAIT_STATUS_T
+-TWATCH_FD
index a39288416150661c21a3dc49ca2ff8e6c13e9aa9..7dd2776b00e928040cdd6cd35cdb3cc113d90787 100644 (file)
@@ -99,3 +99,4 @@
 -TVSTREAM
 -TVSTRING
 -TWAIT_STATUS_T
+-TWATCH_FD
index a39288416150661c21a3dc49ca2ff8e6c13e9aa9..7dd2776b00e928040cdd6cd35cdb3cc113d90787 100644 (file)
@@ -99,3 +99,4 @@
 -TVSTREAM
 -TVSTRING
 -TWAIT_STATUS_T
+-TWATCH_FD
index a39288416150661c21a3dc49ca2ff8e6c13e9aa9..7dd2776b00e928040cdd6cd35cdb3cc113d90787 100644 (file)
@@ -99,3 +99,4 @@
 -TVSTREAM
 -TVSTRING
 -TWAIT_STATUS_T
+-TWATCH_FD
index 9ebd498cd9b142611b8736cf4463493c5de3e21e..b225f84f2e6d264016de75131eea1dbda09b7dcf 100644 (file)
@@ -233,6 +233,12 @@ static void super(char **queues, int action)
                continue;
            }
 
+           /*
+            * Skip temporary files that aren't old enough.
+            */
+           if (mail_queue_id_ok(path) == 0)
+               continue;
+
            /*
             * See if this file sits in the right place in the file system
             * hierarchy. Its place may be wrong after a change to the
index a39288416150661c21a3dc49ca2ff8e6c13e9aa9..7dd2776b00e928040cdd6cd35cdb3cc113d90787 100644 (file)
@@ -99,3 +99,4 @@
 -TVSTREAM
 -TVSTRING
 -TWAIT_STATUS_T
+-TWATCH_FD
index b90ef97e7fd6d5ec2c433db6a742808fc08ccbb5..22a690f9656585bb71b1f53f50fe85100d2bc14a 100644 (file)
 #include <msg.h>
 #include <events.h>
 #include <vstream.h>
+#include <dict.h>
 
 /* Global library. */
 
@@ -387,6 +388,16 @@ static int qmgr_loop(void)
     return (WAIT_FOR_EVENT);
 }
 
+/* pre_accept - see if tables have changed */
+
+static void pre_accept(void)
+{
+    if (dict_changed()) {
+       msg_info("table has changed -- exiting");
+       exit(0);
+    }
+}
+
 /* qmgr_pre_init - pre-jail initialization */
 
 static void qmgr_pre_init(void)
@@ -461,5 +472,6 @@ int     main(int argc, char **argv)
                        MAIL_SERVER_PRE_INIT, qmgr_pre_init,
                        MAIL_SERVER_POST_INIT, qmgr_post_init,
                        MAIL_SERVER_LOOP, qmgr_loop,
+                       MAIL_SERVER_PRE_ACCEPT, pre_accept,
                        0);
 }
index a39288416150661c21a3dc49ca2ff8e6c13e9aa9..7dd2776b00e928040cdd6cd35cdb3cc113d90787 100644 (file)
@@ -99,3 +99,4 @@
 -TVSTREAM
 -TVSTRING
 -TWAIT_STATUS_T
+-TWATCH_FD
index a39288416150661c21a3dc49ca2ff8e6c13e9aa9..7dd2776b00e928040cdd6cd35cdb3cc113d90787 100644 (file)
@@ -99,3 +99,4 @@
 -TVSTREAM
 -TVSTRING
 -TWAIT_STATUS_T
+-TWATCH_FD
index a39288416150661c21a3dc49ca2ff8e6c13e9aa9..7dd2776b00e928040cdd6cd35cdb3cc113d90787 100644 (file)
@@ -99,3 +99,4 @@
 -TVSTREAM
 -TVSTRING
 -TWAIT_STATUS_T
+-TWATCH_FD
index 60c840b35f7c7a58c62bbb982ba6b66bea81089d..8287e67319bbaadd95249795702d2a83a550af50 100644 (file)
 #include <stdlib.h>
 #include <string.h>
 #include <fcntl.h>
+#include <dict.h>
 
 /* Utility library. */
 
@@ -320,6 +321,16 @@ static void smtp_service(VSTREAM *client_stream, char *unused_service, char **ar
     }
 }
 
+/* pre_accept - see if tables have changed */
+
+static void pre_accept(void)
+{
+    if (dict_changed()) {
+       msg_info("table has changed -- exiting");
+       exit(0);
+    }
+}
+
 /* main - pass control to the single-threaded skeleton */
 
 int     main(int argc, char **argv)
@@ -356,5 +367,6 @@ int     main(int argc, char **argv)
                       MAIL_SERVER_STR_TABLE, str_table,
                       MAIL_SERVER_BOOL_TABLE, bool_table,
                       MAIL_SERVER_PRE_INIT, debug_peer_init,
+                      MAIL_SERVER_PRE_ACCEPT, pre_accept,
                       0);
 }
index a39288416150661c21a3dc49ca2ff8e6c13e9aa9..7dd2776b00e928040cdd6cd35cdb3cc113d90787 100644 (file)
@@ -99,3 +99,4 @@
 -TVSTREAM
 -TVSTRING
 -TWAIT_STATUS_T
+-TWATCH_FD
index 80f4b7e543927ce7461a1b890d937c56c28c2116..f7482e4f798d7399bc66ec8e484b06580a6879cd 100644 (file)
 #include <events.h>
 #include <smtp_stream.h>
 #include <valid_hostname.h>
+#include <dict.h>
 
 /* Global library. */
 
@@ -459,6 +460,7 @@ static int mail_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv)
            return (-1);
        }
     }
+    state->time = time((time_t *) 0);
     if (SMTPD_STAND_ALONE(state) == 0
        && (err = smtpd_check_mail(state, argv[3].strval)) != 0) {
        smtpd_chat_reply(state, "%s", err);
@@ -712,6 +714,9 @@ static int data_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *unused_argv)
     } else if ((state->err & CLEANUP_STAT_HOPS) != 0) {
        state->error_mask |= MAIL_ERROR_BOUNCE;
        smtpd_chat_reply(state, "554 Error: too many hops");
+    } else if ((state->err & CLEANUP_STAT_CONT) != 0) {
+       state->error_mask |= MAIL_ERROR_BOUNCE;
+       smtpd_chat_reply(state, "552 Error: content rejected");
     } else if ((state->err & CLEANUP_STAT_WRITE) != 0) {
        state->error_mask |= MAIL_ERROR_RESOURCE;
        smtpd_chat_reply(state, "451 Error: queue file write error");
@@ -1089,6 +1094,16 @@ static void smtpd_sig(int sig)
     exit(sig);
 }
 
+/* pre_accept - see if tables have changed */
+
+static void pre_accept(void)
+{
+    if (dict_changed()) {
+       msg_info("lookup table has changed -- exiting");
+       exit(0);
+    }
+}
+
 /* post_jail_init - post-jail initialization */
 
 static void post_jail_init(void)
@@ -1169,5 +1184,6 @@ int     main(int argc, char **argv)
                       MAIL_SERVER_BOOL_TABLE, bool_table,
                       MAIL_SERVER_PRE_INIT, pre_jail_init,
                       MAIL_SERVER_POST_INIT, post_jail_init,
+                      MAIL_SERVER_PRE_ACCEPT, pre_accept,
                       0);
 }
index 27a08437d4c753308262be8ecd5a856d3c9dc66f..ef795d78c88ac33c829c7b673ba70bfcecff40e5 100644 (file)
@@ -78,7 +78,6 @@ void    smtpd_state_init(SMTPD_STATE *state, VSTREAM *stream,
     state->err = CLEANUP_STAT_OK;
     state->client = stream;
     state->buffer = vstring_alloc(100);
-    state->time = event_time();
     state->name = mystrdup(name);
     state->addr = mystrdup(addr);
     state->error_count = 0;
index a39288416150661c21a3dc49ca2ff8e6c13e9aa9..7dd2776b00e928040cdd6cd35cdb3cc113d90787 100644 (file)
@@ -99,3 +99,4 @@
 -TVSTREAM
 -TVSTRING
 -TWAIT_STATUS_T
+-TWATCH_FD
index a39288416150661c21a3dc49ca2ff8e6c13e9aa9..7dd2776b00e928040cdd6cd35cdb3cc113d90787 100644 (file)
@@ -99,3 +99,4 @@
 -TVSTREAM
 -TVSTRING
 -TWAIT_STATUS_T
+-TWATCH_FD
index e9f59b389519de42d2ac6436aa11ebae1ece7b91..1612317333f8f055caf7b5f34d17da56f70aa5c8 100644 (file)
 #include <vstring_vstream.h>
 #include <split_at.h>
 #include <stringops.h>
+#include <dict.h>
 
 /* Global library. */
 
@@ -182,6 +183,16 @@ static void rewrite_service(VSTREAM *stream, char *unused_service, char **argv)
        multi_server_disconnect(stream);
 }
 
+/* pre_accept - see if tables have changed */
+
+static void pre_accept(void)
+{
+    if (dict_changed()) {
+       msg_info("table has changed -- exiting");
+       exit(0);
+    }
+}
+
 /* pre_jail_init - initialize before entering chroot jail */
 
 static void pre_jail_init(void)
@@ -213,5 +224,6 @@ int     main(int argc, char **argv)
                      MAIL_SERVER_STR_TABLE, str_table,
                      MAIL_SERVER_BOOL_TABLE, bool_table,
                      MAIL_SERVER_PRE_INIT, pre_jail_init,
+                     MAIL_SERVER_PRE_ACCEPT, pre_accept,
                      0);
 }
index a39288416150661c21a3dc49ca2ff8e6c13e9aa9..7dd2776b00e928040cdd6cd35cdb3cc113d90787 100644 (file)
@@ -99,3 +99,4 @@
 -TVSTREAM
 -TVSTRING
 -TWAIT_STATUS_T
+-TWATCH_FD
index e50d1e623a214c7d2ea895049d93803f9a96e2a0..74de770ad640569eb0f048cf3c890299ff39f34e 100644 (file)
@@ -19,7 +19,7 @@ SRCS  = argv.c argv_split.c attr.c basename.c binhash.c chroot_uid.c \
        unsafe.c username.c valid_hostname.c vbuf.c vbuf_print.c \
        vstream.c vstream_popen.c vstring.c vstring_vstream.c writable.c \
        write_buf.c write_wait.c dict_unix.c dict_pcre.c stream_listen.c \
-       stream_connect.c stream_trigger.c dict_regexp.c
+       stream_connect.c stream_trigger.c dict_regexp.c watch_fd.c
 OBJS   = argv.o argv_split.o attr.o basename.o binhash.o chroot_uid.o \
        close_on_exec.o concatenate.o dict.o dict_db.o dict_dbm.o \
        dict_env.o dict_ht.o dict_ldap.o dict_ni.o dict_nis.o \
@@ -40,7 +40,7 @@ OBJS  = argv.o argv_split.o attr.o basename.o binhash.o chroot_uid.o \
        unsafe.o username.o valid_hostname.o vbuf.o vbuf_print.o \
        vstream.o vstream_popen.o vstring.o vstring_vstream.o writable.o \
        write_buf.o write_wait.o dict_unix.o dict_pcre.o stream_listen.o \
-       stream_connect.o stream_trigger.o dict_regexp.o
+       stream_connect.o stream_trigger.o dict_regexp.o watch_fd.o
 HDRS   = argv.h attr.h binhash.h chroot_uid.h connect.h dict.h dict_db.h \
        dict_dbm.h dict_env.h dict_ht.h dict_ldap.h dict_ni.h dict_nis.h \
        dict_nisplus.h dir_forest.h events.h exec_command.h find_inet.h \
@@ -54,7 +54,7 @@ HDRS  = argv.h attr.h binhash.h chroot_uid.h connect.h dict.h dict_db.h \
        sigdelay.h split_at.h stat_as.h stringops.h sys_defs.h \
        timed_connect.h timed_wait.h trigger.h username.h valid_hostname.h \
        vbuf.h vbuf_print.h vstream.h vstring.h vstring_vstream.h \
-       dict_unix.h dict_pcre.h dict_regexp.h
+       dict_unix.h dict_pcre.h dict_regexp.h watch_fd.h
 TESTSRC        = fifo_open.c fifo_rdwr_bug.c fifo_rdonly_bug.c select_bug.c \
        stream_test.c
 WARN   = -W -Wformat -Wimplicit -Wmissing-prototypes \
@@ -367,6 +367,7 @@ dict_open.o: dict_pcre.h
 dict_open.o: dict_regexp.h
 dict_open.o: stringops.h
 dict_open.o: split_at.h
+dict_open.o: htable.h
 dict_pcre.o: dict_pcre.c
 dict_pcre.o: sys_defs.h
 dict_regexp.o: dict_regexp.c
@@ -819,6 +820,12 @@ vstring_vstream.o: vstring.h
 vstring_vstream.o: vbuf.h
 vstring_vstream.o: vstream.h
 vstring_vstream.o: vstring_vstream.h
+watch_fd.o: watch_fd.c
+watch_fd.o: sys_defs.h
+watch_fd.o: msg.h
+watch_fd.o: binhash.h
+watch_fd.o: mymalloc.h
+watch_fd.o: watch_fd.h
 writable.o: writable.c
 writable.o: sys_defs.h
 writable.o: msg.h
index f6a1c5f53019a561c9f56cdb4e7848940491b2d4..f4931aec90546dc0f6172d4f84bf6e5260d989fc 100644 (file)
 /*     extern int dict_errno;
 /*
 /*     void    dict_register(dict_name, dict_info)
-/*     const const char *dict_name;
+/*     const char *dict_name;
 /*     DICT    *dict_info;
 /*
 /*     DICT    *dict_handle(dict_name)
-/*     const const char *dict_name;
+/*     const char *dict_name;
 /*
 /*     void    dict_unregister(dict_name)
-/*     const const char *dict_name;
+/*     const char *dict_name;
 /*
 /*     void    dict_update(dict_name, member, value)
-/*     const const char *dict_name;
-/*     const const char *member;
+/*     const char *dict_name;
+/*     const char *member;
 /*     const char *value;
 /*
 /*     const char *dict_lookup(dict_name, member)
-/*     const const char *dict_name;
-/*     const const char *member;
+/*     const char *dict_name;
+/*     const char *member;
 /*
 /*     const char *dict_eval(dict_name, string, int recursive)
-/*     const const char *dict_name;
+/*     const char *dict_name;
 /*     const char *string;
 /*     int     recursive;
+/*
+/*     int     dict_walk(action, context)
+/*     void    (*action)(dict_name, dict_handle, context)
+/*     char    *context;
+/*
+/*     int     dict_changed()
 /* AUXILIARY FUNCTIONS
 /*     void    dict_load_file(dict_name, path)
-/*     const const char *dict_name;
-/*     const const char *path;
+/*     const char *dict_name;
+/*     const char *path;
 /*
 /*     void    dict_load_fp(dict_name, fp)
-/*     const const char *dict_name;
+/*     const char *dict_name;
 /*     FILE    *fp;
 /* DESCRIPTION
 /*     This module maintains a collection of name-value dictionaries.
 /*     \fIrecursive\fR argument is non-zero, macros references are
 /*     expanded recursively.
 /*
+/*     dict_walk() iterates over all registered dictionaries in some
+/*     arbitrary order, and invokes the specified action routine with
+/*     as arguments:
+/* .IP "const char *dict_name"
+/*     Dictionary name.
+/* .IP "DICT *dict_handle"
+/*     Generic dictionary handle.
+/* .IP "char *context"
+/*     Application context from the caller.
+/* .PP
+/*     dict_changed() returns non-zero when any dictionary needs to
+/*     be re-opened because it has changed.
+/*
 /*     dict_load_file() reads name-value entries from the named file.
 /*     Lines that begin with whitespace are concatenated to the preceding
 /*     line (the newline is deleted).
 /* System libraries. */
 
 #include "sys_defs.h"
+#include <sys/stat.h>
 #include <fcntl.h>
 #include <ctype.h>
 #include <string.h>
@@ -415,3 +435,44 @@ const char *dict_eval(const char *dict_name, const char *value, int recursive)
 
     return (STR(buf));
 }
+
+/* dict_walk - iterate over all dictionaries in arbitrary order */
+
+void    dict_walk(DICT_WALK_ACTION action, char *ptr)
+{
+    HTABLE_INFO **ht_info_list;
+    HTABLE_INFO **ht;
+    HTABLE_INFO *h;
+
+    ht_info_list = htable_list(dict_table);
+    for (ht = ht_info_list; (h = *ht) != 0; ht++)
+       action(h->key, (DICT *) h->value, ptr);
+    myfree((char *) ht_info_list);
+}
+
+/* dict_changed - see if any dictionary has changed */
+
+int     dict_changed(void)
+{
+    char   *myname = "dict_changed";
+    struct stat st;
+    HTABLE_INFO **ht_info_list;
+    HTABLE_INFO **ht;
+    HTABLE_INFO *h;
+    int     status;
+    DICT   *dict;
+
+    ht_info_list = htable_list(dict_table);
+    for (status = 0, ht = ht_info_list; status == 0 && (h = *ht) != 0; ht++) {
+       dict = ((DICT_NODE *) h->value)->dict;
+       if (dict->fd < 0)                       /* not file-based */
+           continue;
+       if (dict->mtime == 0)                   /* not bloody likely */
+           msg_warn("%s: table %s: null time stamp", myname, h->key);
+       if (fstat(dict->fd, &st) < 0)
+           msg_fatal("%s: fstat: %m", myname);
+       status = (st.st_mtime != dict->mtime);
+    }
+    myfree((char *) ht_info_list);
+    return (status);
+}
index dc279298d16584a779f1c5fb820a99d026972d84..2dd4d5dc0da6c14d07ff3f66d7cd7035eff8bee2 100644 (file)
@@ -31,6 +31,7 @@ typedef struct DICT {
     void    (*update) (struct DICT *, const char *, const char *);
     void    (*close) (struct DICT *);
     int     fd;                                /* for dict_update() lock */
+    time_t  mtime;                     /* mod time at open */
 } DICT;
 
 #define DICT_FLAG_DUP_WARN     (1<<0)  /* if file, warn about dups */
@@ -65,10 +66,13 @@ extern const char *dict_eval(const char *, const char *, int);
   */
 extern DICT *dict_open(const char *, int, int);
 extern DICT *dict_open3(const char *, const char *, int, int);
-extern void dict_open_register(const char *, DICT *(*)(const char *, int, int));
+extern void dict_open_register(const char *, DICT *(*) (const char *, int, int));
 #define dict_get(dp, key)      (dp)->lookup((dp), (key))
 #define dict_put(dp, key, val) (dp)->update((dp), (key), (val))
 #define dict_close(dp)         (dp)->close(dp)
+typedef void (*DICT_WALK_ACTION) (const char *, DICT *, char *);
+extern void dict_walk(DICT_WALK_ACTION, char *);
+extern int dict_changed(void);
 
 /* LICENSE
 /* .ad
index 6933975893dbe03bfa74ff1c821476f57f43b6df..36e3bb96909ac8eb47b51274958eb865ea3a490d 100644 (file)
@@ -48,6 +48,7 @@
 
 /* System library. */
 
+#include <sys/stat.h>
 #include <limits.h>
 #ifdef PATH_DB_H
 #include PATH_DB_H
@@ -134,7 +135,7 @@ static const char *dict_db_lookup(DICT *dict, const char *name)
     /*
      * Release the shared lock.
      */
-    if ((dict->fd & DICT_FLAG_LOCK) && myflock(dict->fd, MYFLOCK_NONE) < 0)
+    if ((dict->flags & DICT_FLAG_LOCK) && myflock(dict->fd, MYFLOCK_NONE) < 0)
        msg_fatal("%s: unlock dictionary: %m", dict_db->path);
 
     return (result);
@@ -223,6 +224,7 @@ static DICT *dict_db_open(const char *path, int flags, int type,
                                  void *tweak, int dict_flags)
 {
     DICT_DB *dict_db;
+    struct stat st;
     DB     *db;
     char   *db_path;
 
@@ -235,6 +237,9 @@ static DICT *dict_db_open(const char *path, int flags, int type,
     dict_db->dict.update = dict_db_update;
     dict_db->dict.close = dict_db_close;
     dict_db->dict.fd = db->fd(db);
+    if (fstat(dict_db->dict.fd, &st) < 0)
+       msg_fatal("dict_db_open: fstat: %m");
+    dict_db->dict.mtime = st.st_mtime;
     close_on_exec(dict_db->dict.fd, CLOSE_ON_EXEC);
     dict_db->dict.flags = dict_flags | DICT_FLAG_FIXED;
     if ((flags & (DICT_FLAG_TRY1NULL | DICT_FLAG_TRY0NULL)) == 0)
index 1798202ff14fe6594ee1eda33ed7dddafdd4b3f9..78a73c0c2d2bc6a47275fcea93d8b004931fabff 100644 (file)
@@ -36,6 +36,7 @@
 
 /* System library. */
 
+#include <sys/stat.h>
 #include <ndbm.h>
 #include <string.h>
 
@@ -196,6 +197,7 @@ static void dict_dbm_close(DICT *dict)
 DICT   *dict_dbm_open(const char *path, int open_flags, int dict_flags)
 {
     DICT_DBM *dict_dbm;
+    struct stat st;
     DBM    *dbm;
 
     /*
@@ -209,6 +211,9 @@ DICT   *dict_dbm_open(const char *path, int open_flags, int dict_flags)
     dict_dbm->dict.update = dict_dbm_update;
     dict_dbm->dict.close = dict_dbm_close;
     dict_dbm->dict.fd = dbm_dirfno(dbm);
+    if (fstat(dict_dbm->dict.fd, &st) < 0)
+       msg_fatal("dict_dbm_open: fstat: %m");
+    dict_dbm->dict.mtime = st.st_mtime;
     close_on_exec(dict_dbm->dict.fd, CLOSE_ON_EXEC);
     dict_dbm->dict.flags = dict_flags | DICT_FLAG_FIXED;
     if ((dict_flags & (DICT_FLAG_TRY0NULL | DICT_FLAG_TRY1NULL)) == 0)
index 8d47e8dd95e040417d7c74013b520e60f64d659c..e5912b6ca5594bae63be646d94afd924a089efc5 100644 (file)
@@ -314,8 +314,13 @@ main(int argc, char **argv)
     else
        msg_fatal("unknown access mode: %s", argv[2]);
     dict_name = argv[optind];
-    dict = dict_open(dict_name, open_flags, 0);
+    dict = dict_open(dict_name, open_flags, DICT_FLAG_LOCK);
+    dict_register(dict_name, dict);
     while (vstring_fgets_nonl(keybuf, VSTREAM_IN)) {
+       if (dict_changed()) {
+           msg_warn("dictionary has changed -- exiting");
+           exit(0);
+       }
        if ((key = strtok(vstring_str(keybuf), " =")) == 0)
            continue;
        if ((value = strtok((char *) 0, " =")) == 0) {
diff --git a/postfix/util/watch_fd.c b/postfix/util/watch_fd.c
new file mode 100644 (file)
index 0000000..76dda72
--- /dev/null
@@ -0,0 +1,114 @@
+/*++
+/* NAME
+/*     watch_fd 3
+/* SUMMARY
+/*     monitor file descriptors for change
+/* SYNOPSIS
+/*     #include <watch_fd.h>
+/*
+/*     void    watch_fd_register(fd)
+/*     int     fd;
+/*
+/*     void    watch_fd_remove(fd)
+/*     int     fd;
+/*
+/*     int     watch_fd_changed()
+/* DESCRIPTION
+/*     This module monitors file modification times of arbitrary file
+/*     descriptors.
+/*
+/*     watch_fd_register() records information about the specified
+/*     file descriptor.
+/*
+/*     watch_fd_remove() releases storage allocated by watch_fd_register().
+/*
+/*     watch_fd_changed() returns non-zero if any of the registered
+/* SEE ALSO
+/*     msg(3) diagnostics interface
+/* DIAGNOSTICS
+/*     Problems are reported via the msg(3) diagnostics routines:
+/*     the requested amount of memory is not available; improper use
+/*     is detected; other fatal errors.
+/* LICENSE
+/* .ad
+/* .fi
+/*     The Secure Mailer license must be distributed with this software.
+/* AUTHOR(S)
+/*     Wietse Venema
+/*     IBM T.J. Watson Research
+/*     P.O. Box 704
+/*     Yorktown Heights, NY 10598, USA
+/*--*/
+
+/* System library. */
+
+#include <sys_defs.h>
+#include <sys/stat.h>
+
+/* Utility library. */
+
+#include <msg.h>
+#include <binhash.h>
+#include <mymalloc.h>
+#include <watch_fd.h>
+
+/* Application-specific. */
+
+typedef struct {
+    int     fd;                                /* file descriptor */
+    time_t  mtime;                     /* initial modification time */
+} WATCH_FD;
+
+static BINHASH *watch_fd_table;
+
+/* watch_fd_register - register file descriptor */
+
+void    watch_fd_register(int fd)
+{
+    char   *myname = "watch_fd_enter";
+    WATCH_FD *info;
+    struct stat st;
+
+    if (fstat(fd, &st) < 0)
+       msg_fatal("%s: fstat: %m", myname);
+
+    info = (WATCH_FD *) mymalloc(sizeof(*info));
+    info->fd = fd;
+    info->mtime = st.st_mtime;
+
+    if (watch_fd_table == 0)
+       watch_fd_table = binhash_create(0);
+    if (binhash_find(watch_fd_table, (char *) &fd, sizeof(fd)))
+       msg_panic("%s: entry %d exists", myname, fd);
+    binhash_enter(watch_fd_table, (char *) &fd, sizeof(fd), (char *) info);
+}
+
+/* watch_fd_remove - remove file descriptor */
+
+void    watch_fd_remove(int fd)
+{
+    binhash_delete(watch_fd_table, (char *) &fd, sizeof(fd), myfree);
+}
+
+/* watch_fd_changed - see if any file has changed */
+
+int     watch_fd_changed(void)
+{
+    char   *myname = "watch_fd_changed";
+    struct stat st;
+    BINHASH_INFO **ht_info_list;
+    BINHASH_INFO **ht;
+    BINHASH_INFO *h;
+    WATCH_FD *info;
+    int     status;
+
+    ht_info_list = binhash_list(watch_fd_table);
+    for (status = 0, ht = ht_info_list; status == 0 && (h = *ht) != 0; ht++) {
+       info = (WATCH_FD *) h->value;
+       if (fstat(info->fd, &st) < 0)
+           msg_fatal("%s: fstat: %m", myname);
+       status = (st.st_mtime != info->mtime);
+    }
+    myfree((char *) ht_info_list);
+    return (status);
+}
diff --git a/postfix/util/watch_fd.h b/postfix/util/watch_fd.h
new file mode 100644 (file)
index 0000000..ef02ccd
--- /dev/null
@@ -0,0 +1,32 @@
+#ifndef _WATCH_FD_H_INCLUDED_
+#define _WATCH_FD_H_INCLUDED_
+
+/*++
+/* NAME
+/*     watch_fd 3h
+/* SUMMARY
+/*     monitor file descriptors for change
+/* SYNOPSIS
+/*     #include "watch_fd.h"
+ DESCRIPTION
+ .nf
+
+ /*
+  * External interface.
+  */
+extern void watch_fd_register(int);
+extern void watch_fd_remove(int);
+extern int watch_fd_changed(void);
+
+/* LICENSE
+/* .ad
+/* .fi
+/*     The Secure Mailer license must be distributed with this software.
+/* AUTHOR(S)
+/*     Wietse Venema
+/*     IBM T.J. Watson Research
+/*     P.O. Box 704
+/*     Yorktown Heights, NY 10598, USA
+/*--*/
+
+#endif