]> git.ipfire.org Git - thirdparty/postfix.git/commitdiff
postfix-2.2-20050203
authorWietse Venema <wietse@porcupine.org>
Thu, 3 Feb 2005 05:00:00 +0000 (00:00 -0500)
committerViktor Dukhovni <viktor@dukhovni.org>
Tue, 5 Feb 2013 06:30:31 +0000 (06:30 +0000)
20 files changed:
postfix/HISTORY
postfix/RELEASE_NOTES
postfix/conf/postfix-script
postfix/src/anvil/anvil.c
postfix/src/global/input_transp.c
postfix/src/global/mail_version.h
postfix/src/global/resolve_clnt.c
postfix/src/global/rewrite_clnt.c
postfix/src/master/mail_server.h
postfix/src/master/master.c
postfix/src/master/multi_server.c
postfix/src/master/single_server.c
postfix/src/master/trigger_server.c
postfix/src/sendmail/sendmail.c
postfix/src/trivial-rewrite/Makefile.in
postfix/src/trivial-rewrite/resolve.c
postfix/src/trivial-rewrite/rewrite.c
postfix/src/trivial-rewrite/trivial-rewrite.c
postfix/src/trivial-rewrite/trivial-rewrite.h
postfix/src/util/sys_defs.h

index ab94cf30c7f969609c11fa5a7f3cec1509f876f1..55b9ddd0968746d8cbb883dda4e30ad09c533728 100644 (file)
@@ -10242,13 +10242,28 @@ Apologies for any names omitted.
        it is adjusted to maximal_queue_lifetime, and a warning is
        logged. Files:  *qmgr/qmgr.c.
 
-       Cleanup: trivial-rewrite detects changes to maps even in
-       the absence of connection events. File: trivial-rewrite.c.
+20050203
+
+       Cleanup: trivial-rewrite now restarts more timely after
+       changes in lookup tables.  Of the all the alternatives
+       tested, the simplest one produces the most bang for the
+       buck. The other code is left in place for illustrative
+       purposes. File:  trivial-rewrite/trivial-rewrite.c.
+
+       Cleanup: sendmail no longer ignores null command-line
+       recipients.  File: sendmail/sendmail.c.
+
+       Cleanup: "postfix start" background checks moved back
+       to the foreground so they can be stopped more easily.
+       File: conf/postfix-script.
 
 Open problems:
 
-       Med: SunOS 4 has no strtoul(). Instead of sprintf/strtoul()
-       use hexen/decode() for the process generation number.
+       Med: local and remote source port and IP address for
+       smtpd policy hook.
+
+       Med: smtp_connect_timeout_budget (default: 2x smtp_connect_timeout)
+       to limit the total time spent trying to connect.
 
        Low: pointers to postfinger and saslfinger. postfinger
        is now bundled.
@@ -10356,8 +10371,6 @@ Open problems:
        smtpd, qmgr, local, etc. use unquoted address forms as
        keys.  cleanup uses quoted forms.
 
-       Low: sendmail does not store null command-line recipients.
-
        Low: have a configurable list of errno values for mailbox
        or maildir delivery that result in deferral rather than
        bouncing mail.
index b317fedbd7d1b53c256bc1c86dae87949945b8bd..9090e046cc8de7d0dda01714b228f0b4e25e507b 100644 (file)
@@ -7,14 +7,17 @@ snapshot release).  Patches are issued for the official release
 and change the patchlevel and the release date. Patches are never
 issued for snapshot releases.
 
-Incompatible changes with snapshot Postfix-2.2-20050202
+Incompatible changes with snapshot Postfix-2.2-20050203
 =======================================================
 
 Postfix rewrites message header addresses only in mail that originates
 from the local machine. Specify "local_header_rewrite_clients =
 static:all" to get the old behavior of Postfix 2.1 and earlier.
 
-Major changes with snapshot Postfix-2.2-20050202
+All "postfix start" file permission checks are run in the foreground
+while Postfix is started.
+
+Major changes with snapshot Postfix-2.2-20050203
 ================================================
 
 To create a ready-to-install package for distribution to other
@@ -24,7 +27,7 @@ deprecated). See the PACKAGE_README file for details.
 
 New "permit_inet_interfaces" access restriction to allow access
 from local IP addresses only. This is used for the default, purist,
-setting of local_header_rewrite_clients.
+setting of local_header_rewrite_clients in the previous paragraph.
 
 New "sleep time-in-seconds" pseudo access restriction to block
 zombie clients with reject_unauthorized_pipelining before the
@@ -33,7 +36,7 @@ for example.
 
 Safety: Postfix no longer tries to send mail to the fallback_relay
 when the local machine is MX host for the mail destination. See
-postconf(5) description of fallback_relay for details.
+the postconf(5) description of fallback_relay for details.
 
 Incompatible changes with snapshot Postfix-2.2-20050117
 =======================================================
@@ -45,9 +48,6 @@ high load too much. Hashing is now turned on only for the defer and
 deferred queue directories, because those contain lots of mail when
 undeliverable mail is backing up.
 
-In order to speed up start-up, some Postfix file permission checks
-are run in the background after Postfix is started.
-
 The SMTP server now requires that IPv6 addresses in SMTP commands
 are specified as [ipv6:ipv6address], as described in RFC 2821.
 
index f18116473cfb5d8dcb7359e392204dfe3de8339c..c7251105ffb4e5a33f3a9f4bb01c0e97a88445d5 100644 (file)
@@ -98,9 +98,8 @@ start)
                        $FATAL Postfix integrity check failed!
                        exit 1
                }
-               # Warning checks proceed in the background.
-               $INFO starting background file permission checks in 60 seconds
-               (sleep 60; $config_directory/postfix-script check-warn) &
+               # Foreground this so it can be stopped. All inodes are cached.
+               $config_directory/postfix-script check-warn
        fi
        $INFO starting the Postfix mail system
        $daemon_directory/master &
index 40c00da10948b0bd91029704c62e5a314479cc74..d99611d837e99aeb98a16e4cc46879aa33e9dc4b 100644 (file)
@@ -840,7 +840,7 @@ static void anvil_status_dump(char *unused_name, char **unused_argv)
        max_rcpt = 0;
     }
     if (max_cache > 0) {
-       msg_info("statistics: max ident cache size %d at %.15s",
+       msg_info("statistics: max cache size %d at %.15s",
                 max_cache, ctime(&max_cache_time) + 4);
        max_cache = 0;
     }
index 426ba220365e2aa1b2cf2a428297e27e32c66efa..a9b1bede911b89143dca18bdfc311e9463a35703 100644 (file)
@@ -55,6 +55,7 @@
 /* Utility library. */
 
 #include <name_mask.h>
+#include <msg.h>
 
 /* Global library. */
 
@@ -80,9 +81,17 @@ int     input_transp_mask(const char *param_name, const char *pattern)
 
 int     input_transp_cleanup(int cleanup_flags, int transp_mask)
 {
+    const char *myname = "input_transp_cleanup";
+
+    if (msg_verbose)
+       msg_info("before %s: cleanup flags = %s",
+                myname, cleanup_strflags(cleanup_flags));
     if (transp_mask & INPUT_TRANSP_ADDRESS_MAPPING)
        cleanup_flags &= ~(CLEANUP_FLAG_BCC_OK | CLEANUP_FLAG_MAP_OK);
     if (transp_mask & INPUT_TRANSP_HEADER_BODY)
        cleanup_flags &= ~CLEANUP_FLAG_FILTER;
+    if (msg_verbose)
+       msg_info("after %s: cleanup flags = %s",
+                myname, cleanup_strflags(cleanup_flags));
     return (cleanup_flags);
 }
index 432ec315d75869cfc703c7684df633d4886f63a8..d90d4892df7125cbe2c3bfbb9ba45b3784366484 100644 (file)
@@ -20,7 +20,7 @@
   * Patches change the patchlevel and the release date. Snapshots change the
   * release date only.
   */
-#define MAIL_RELEASE_DATE      "20050202"
+#define MAIL_RELEASE_DATE      "20050203"
 #define MAIL_VERSION_NUMBER    "2.2"
 
 #define VAR_MAIL_VERSION       "mail_version"
index 358bc932adfbc456217db35b1194f6b26fd7e576..83906d5ae4dc6e74ebf8f6b2838fe78323c7555b 100644 (file)
@@ -147,6 +147,7 @@ void    resolve_clnt(const char *class, const char *addr, RESOLVE_REPLY *reply)
 {
     char   *myname = "resolve_clnt";
     VSTREAM *stream;
+    int     server_flags;
 
     /*
      * One-entry cache.
@@ -213,11 +214,12 @@ void    resolve_clnt(const char *class, const char *addr, RESOLVE_REPLY *reply)
                       ATTR_TYPE_END) != 0
            || vstream_fflush(stream)
            || attr_scan(stream, ATTR_FLAG_STRICT,
+                        ATTR_TYPE_NUM, MAIL_ATTR_FLAGS, &server_flags,
                       ATTR_TYPE_STR, MAIL_ATTR_TRANSPORT, reply->transport,
                         ATTR_TYPE_STR, MAIL_ATTR_NEXTHOP, reply->nexthop,
                         ATTR_TYPE_STR, MAIL_ATTR_RECIP, reply->recipient,
                         ATTR_TYPE_NUM, MAIL_ATTR_FLAGS, &reply->flags,
-                        ATTR_TYPE_END) != 4) {
+                        ATTR_TYPE_END) != 5) {
            if (msg_verbose || (errno != EPIPE && errno != ENOENT))
                msg_warn("problem talking to service %s: %m",
                         var_rewrite_service);
@@ -235,6 +237,9 @@ void    resolve_clnt(const char *class, const char *addr, RESOLVE_REPLY *reply)
                         IFSET(RESOLVE_CLASS_VIRTUAL, "virtual"),
                         IFSET(RESOLVE_CLASS_RELAY, "relay"),
                         IFSET(RESOLVE_CLASS_DEFAULT, "default"));
+           /* Server-requested disconnect. */
+           if (server_flags != 0)
+               clnt_stream_recover(rewrite_clnt_stream);
            if (STR(reply->transport)[0] == 0)
                msg_warn("%s: null transport result for: <%s>", myname, addr);
            else if (STR(reply->recipient)[0] == 0 && *addr != 0)
index ac28d25463c2129ac07cb9002b8e5748cbc0afad..7aaa756880a42b9de82c6a9662db712db6b862dd 100644 (file)
@@ -81,6 +81,7 @@ static VSTRING *last_result;
 VSTRING *rewrite_clnt(const char *rule, const char *addr, VSTRING *result)
 {
     VSTREAM *stream;
+    int     server_flags;
 
     /*
      * One-entry cache.
@@ -135,8 +136,9 @@ VSTRING *rewrite_clnt(const char *rule, const char *addr, VSTRING *result)
                       ATTR_TYPE_END) != 0
            || vstream_fflush(stream)
            || attr_scan(stream, ATTR_FLAG_STRICT,
+                        ATTR_TYPE_NUM, MAIL_ATTR_FLAGS, &server_flags,
                         ATTR_TYPE_STR, MAIL_ATTR_ADDR, result,
-                        ATTR_TYPE_END) != 1) {
+                        ATTR_TYPE_END) != 2) {
            if (msg_verbose || (errno != EPIPE && errno != ENOENT))
                msg_warn("problem talking to service %s: %m",
                         var_rewrite_service);
@@ -144,6 +146,9 @@ VSTRING *rewrite_clnt(const char *rule, const char *addr, VSTRING *result)
            if (msg_verbose)
                msg_info("rewrite_clnt: %s: %s -> %s",
                         rule, addr, vstring_str(result));
+           /* Server-requested disconnect. */
+           if (server_flags != 0)
+               clnt_stream_recover(rewrite_clnt_stream);
            break;
        }
        sleep(1);                               /* XXX make configurable */
index 1c69877b1b6450f705cc1e3802b32dbc5adc25a2..69d75324a9f08bc95dc6b6af00baf48e6be7bc82 100644 (file)
@@ -52,6 +52,7 @@ extern NORETURN single_server_main(int, char **, SINGLE_SERVER_FN, ...);
 typedef void (*MULTI_SERVER_FN) (VSTREAM *, char *, char **);
 extern NORETURN multi_server_main(int, char **, MULTI_SERVER_FN,...);
 extern void multi_server_disconnect(VSTREAM *);
+extern int multi_server_drain(void);
 
  /*
   * trigger_server.c
index c1589eb6ab7d11fb897adc745fb3638315d8b61a..f98893331d87e77a1f659531e0f47b117256978f 100644 (file)
@@ -426,7 +426,7 @@ int     main(int argc, char **argv)
        watchdog_start(watchdog);               /* same as trigger servers */
        event_loop(-1);
        if (master_gotsighup) {
-           msg_info("reload configuration");
+           msg_info("reload configuration %s", var_config_dir);
            master_gotsighup = 0;               /* this first */
            master_vars_init();                 /* then this */
            master_refresh();                   /* then this */
index e17df7203fbb85da59e05351d613a0c23fdfd3e6..52cfbdb2695e94ded5754abb890d571acef5e7b1 100644 (file)
@@ -15,6 +15,8 @@
 /*     void    multi_server_disconnect(stream, argv)
 /*     VSTREAM *stream;
 /*     char    **argv;
+/*
+/*     void    multi_server_drain()
 /* DESCRIPTION
 /*     This module implements a skeleton for multi-threaded
 /*     mail subsystems: mail subsystem programs that service multiple
 /*     multi_server_disconnect() should be called by the application
 /*     when a client disconnects.
 /*
+/*     multi_server_drain() should be called when the application
+/*     no longer wishes to accept new client connections. Existing
+/*     clients are handled in a background process. A non-zero
+/*     result means this call should be tried again later.
+/*
 /*     The var_use_limit variable limits the number of clients that
 /*     a server can service before it commits suicide.
 /*     This value is taken from the global \fBmain.cf\fR configuration
   */
 static int client_count;
 static int use_count;
+static int socket_count = 1;
 
 static void (*multi_server_service) (VSTREAM *, char *, char **);
 static char *multi_server_name;
@@ -238,6 +246,28 @@ static void multi_server_timeout(int unused_event, char *unused_context)
     multi_server_exit();
 }
 
+/*  multi_server_drain - stop accepting new clients */
+
+int multi_server_drain(void)
+{
+    int     fd;
+
+    switch (fork()) {
+       /* Try again later. */
+    case -1:
+       return (-1);
+       /* Finish existing clients in the background, then terminate. */
+    case 0:
+       for (fd = MASTER_LISTEN_FD; fd < MASTER_LISTEN_FD + socket_count; fd++)
+           event_disable_readwrite(fd);
+       var_use_limit = 1;
+       return (0);
+       /* Let the master start a new process. */
+    default:
+       exit(0);
+    }
+}
+
 /* multi_server_disconnect - terminate client session */
 
 void    multi_server_disconnect(VSTREAM *stream)
@@ -433,7 +463,6 @@ NORETURN multi_server_main(int argc, char **argv, MULTI_SERVER_FN service,...)
     char   *service_name = basename(argv[0]);
     int     delay;
     int     c;
-    int     socket_count = 1;
     int     fd;
     va_list ap;
     MAIL_SERVER_INIT_FN pre_init = 0;
@@ -656,7 +685,10 @@ NORETURN multi_server_main(int argc, char **argv, MULTI_SERVER_FN service,...)
     if ((generation = getenv(MASTER_GEN_NAME)) != 0) {
        if (!alldig(generation))
            msg_fatal("bad generation: %s", generation);
-       multi_server_generation = strtoul(generation, (char **) 0, 8);
+       OCTAL_TO_UNSIGNED(multi_server_generation, generation);
+       if (msg_verbose)
+           msg_info("process generation: %s (%o)",
+                    generation, multi_server_generation);
     }
 
     /*
index 069b8c839ccbfa07aba8020ee504c5c3fe297fc8..f3bb80a6ea461160a46198955dd2c05c1b36bdce 100644 (file)
@@ -598,7 +598,10 @@ NORETURN single_server_main(int argc, char **argv, SINGLE_SERVER_FN service,...)
     if ((generation = getenv(MASTER_GEN_NAME)) != 0) {
        if (!alldig(generation))
            msg_fatal("bad generation: %s", generation);
-       single_server_generation = strtoul(generation, (char **) 0, 8);
+       OCTAL_TO_UNSIGNED(single_server_generation, generation);
+       if (msg_verbose)
+           msg_info("process generation: %s (%o)",
+                    generation, single_server_generation);
     }
 
     /*
index 047bf7e9817f8fdc180766599a30949ddd7416f4..7c86be76f64090a750aa05a57589f33f508e428e 100644 (file)
@@ -618,7 +618,10 @@ NORETURN trigger_server_main(int argc, char **argv, TRIGGER_SERVER_FN service,..
     if ((generation = getenv(MASTER_GEN_NAME)) != 0) {
        if (!alldig(generation))
            msg_fatal("bad generation: %s", generation);
-       trigger_server_generation = strtoul(generation, (char **) 0, 8);
+       OCTAL_TO_UNSIGNED(trigger_server_generation, generation);
+       if (msg_verbose)
+           msg_info("process generation: %s (%o)",
+                    generation, trigger_server_generation);
     }
 
     /*
index ec73b757708fcbf123632abe5beb8cb95afb1278..9406751bb853fe8ca90b40ef15bcde252065f020 100644 (file)
@@ -556,6 +556,7 @@ static void enqueue(const int flags, const char *encoding, const char *sender,
     SM_STATE state;
     int     mime_errs;
     const char *errstr;
+    int     addr_count;
 
     /*
      * Access control is enforced in the postdrop command. The code here
@@ -643,7 +644,7 @@ static void enqueue(const int flags, const char *encoding, const char *sender,
     if (recipients) {
        for (cpp = recipients; *cpp != 0; cpp++) {
            tree = tok822_parse(*cpp);
-           for (tp = tree; tp != 0; tp = tp->next) {
+           for (addr_count = 0, tp = tree; tp != 0; tp = tp->next) {
                if (tp->type == TOK822_ADDR) {
                    tok822_internalize(buf, tp->head, TOK822_STR_DEFL);
                    if (REC_PUT_BUF(dst, REC_TYPE_RCPT, buf) < 0)
@@ -651,9 +652,17 @@ static void enqueue(const int flags, const char *encoding, const char *sender,
                                    "%s(%ld): error writing queue file: %m",
                                         saved_sender, (long) uid);
                    ++rcpt_count;
+                   ++addr_count;
                }
            }
            tok822_free_tree(tree);
+           if (addr_count == 0) {
+               if (rec_put(dst, REC_TYPE_RCPT, "", 0) < 0)
+                   msg_fatal_status(EX_TEMPFAIL,
+                                    "%s(%ld): error writing queue file: %m",
+                                    saved_sender, (long) uid);
+               ++rcpt_count;
+           }
        }
     }
 
index bffe190b7b27b0363a234c8fa27f1a839bb143dc..b2dc22a75f01edd8d361881903a2d63d8346f538 100644 (file)
@@ -88,6 +88,7 @@ resolve.o: ../../include/maps.h
 resolve.o: ../../include/dict.h
 resolve.o: ../../include/argv.h
 resolve.o: ../../include/mail_addr_find.h
+resolve.o: ../../include/valid_mailhost_addr.h
 resolve.o: trivial-rewrite.h
 resolve.o: transport.h
 rewrite.o: rewrite.c
@@ -138,6 +139,7 @@ trivial-rewrite.o: ../../include/split_at.h
 trivial-rewrite.o: ../../include/stringops.h
 trivial-rewrite.o: ../../include/dict.h
 trivial-rewrite.o: ../../include/argv.h
+trivial-rewrite.o: ../../include/events.h
 trivial-rewrite.o: ../../include/mail_params.h
 trivial-rewrite.o: ../../include/mail_proto.h
 trivial-rewrite.o: ../../include/iostuff.h
index 8809405fb2ee3e9202f07dce05a5ad83657b4655..ed5af4b2c78855c7277465c306cc66a78398c501 100644 (file)
@@ -74,6 +74,7 @@
 #include <match_parent_style.h>
 #include <maps.h>
 #include <mail_addr_find.h>
+#include <valid_mailhost_addr.h>
 
 /* Application-specific. */
 
@@ -639,6 +640,7 @@ int     resolve_proto(RES_CONTEXT *context, VSTREAM *stream)
                 STR(nexthop), STR(nextrcpt), flags);
 
     attr_print(stream, ATTR_FLAG_NONE,
+              ATTR_TYPE_NUM, MAIL_ATTR_FLAGS, server_flags,
               ATTR_TYPE_STR, MAIL_ATTR_TRANSPORT, STR(channel),
               ATTR_TYPE_STR, MAIL_ATTR_NEXTHOP, STR(nexthop),
               ATTR_TYPE_STR, MAIL_ATTR_RECIP, STR(nextrcpt),
index 675457cff77d3cd7659b8a194833003f209bb2a6..c1a275f994ce181ae4f46feebfc15838da170281 100644 (file)
@@ -259,6 +259,7 @@ int     rewrite_proto(VSTREAM *stream)
                 vstring_str(address), vstring_str(result));
 
     attr_print(stream, ATTR_FLAG_NONE,
+              ATTR_TYPE_NUM, MAIL_ATTR_FLAGS, server_flags,
               ATTR_TYPE_STR, MAIL_ATTR_ADDR, vstring_str(result),
               ATTR_TYPE_END);
 
index 9a869617d74eeb260da1ba35a99a46f0a24d25b6..b4602628f6792c09ad45ea4fd41571f74ef0d4e1 100644 (file)
@@ -9,7 +9,7 @@
 /*     The \fBtrivial-rewrite\fR daemon processes three types of client
 /*     service requests:
 /* .IP "\fBrewrite \fIcontext address\fR"
-/*     Rewrite an address to standard form, according to the 
+/*     Rewrite an address to standard form, according to the
 /*     address rewriting context:
 /* .RS
 /* .IP \fBlocal\fR
@@ -39,7 +39,7 @@
 /* .IP \fIrecipient\fR
 /*     The envelope recipient address that is passed on to \fInexthop\fR.
 /* .IP \fIflags\fR
-/*     The address class, whether the address requires relaying, 
+/*     The address class, whether the address requires relaying,
 /*     whether the address has problems, and whether the request failed.
 /* .RE
 /* .IP "\fBverify \fIaddress\fR"
 #include <split_at.h>
 #include <stringops.h>
 #include <dict.h>
+#include <events.h>
 
 /* Global library. */
 
@@ -328,15 +329,71 @@ RES_CONTEXT resolve_verify = {
     VAR_VRFY_XPORT_MAPS, &var_vrfy_xport_maps, 0
 };
 
+ /*
+  * Connection management. When file-based lookup tables change we should
+  * restart at our convenience, but avoid client read errors. We restart
+  * rather than reopen, because the process may be chrooted (and if it isn't
+  * we still need code that handles the chrooted case anyway).
+  * 
+  * Three variants are implemented. Only one should be used.
+  * 
+  * ifdef DETACH_AND_ASK_CLIENTS_TO_RECONNECT
+  * 
+  * This code detaches the trivial-rewrite process from the master, stops
+  * accepting new clients, and handles established clients in the background,
+  * asking them to reconnect the next time they send a request. The master
+  * create a new process that accepts connections. This is reasonably safe
+  * because the number of trivial-rewrite server processes is small compared
+  * to the number of trivial-rewrite client processes. The few extra
+  * background processes should not make a difference in Postfix's footprint.
+  * However, once a daemon detaches from the master, its exit status will be
+  * lost, and abnormal termination may remain undetected. Timely restart is
+  * achieved by checking the table changed status every 10 seconds or so
+  * before responding to a client request.
+  * 
+  * ifdef CHECK_TABLE_STATS_PERIODICALLY
+  * 
+  * This code runs every 10 seconds and terminates the process when lookup
+  * tables have changed. This is subject to race conditions when established
+  * clients send a request while the server exits; those clients may read EOF
+  * instead of a server reply. If the experience with the oldest option
+  * (below) is anything to go by, however, then this is unlikely to be a
+  * problem during real deployment.
+  * 
+  * ifdef CHECK_TABLE_STATS_BEFORE_ACCEPT
+  * 
+  * This is the old code. It checks the table changed status when a new client
+  * connects (i.e. before the server calls accept()), and terminates
+  * immediately. This is invisible for the connecting client, but is subject
+  * to race conditions when established clients send a request while the
+  * server exits; those clients may read EOF instead of a server reply. This
+  * has, however, not been a problem in real deployment. With the old code,
+  * timely restart is achieved by setting the ipc_ttl parameter to 60
+  * seconds, so that the table change status is checked several times a
+  * minute.
+  */
+int     server_flags;
+
+ /*
+  * Define exactly one of these.
+  */
+/* #define DETACH_AND_ASK_CLIENTS_TO_RECONNECT /* correct and complex */
+#define CHECK_TABLE_STATS_PERIODICALLY /* quick */
+/* #define CHECK_TABLE_STATS_BEFORE_ACCEPT     /* slow */
+
 /* rewrite_service - read request and send reply */
 
 static void rewrite_service(VSTREAM *stream, char *unused_service, char **argv)
 {
     int     status = -1;
+
+#ifdef DETACH_AND_ASK_CLIENTS_TO_RECONNECT
     static time_t last;
-    time_t  now = event_time();
+    time_t  now;
     const char *table;
 
+#endif
+
     /*
      * Sanity check. This service takes no command-line arguments.
      */
@@ -344,15 +401,18 @@ static void rewrite_service(VSTREAM *stream, char *unused_service, char **argv)
        msg_fatal("unexpected command-line argument: %s", argv[0]);
 
     /*
-     * Connections are persistent. Be sure to refesh timely.
+     * Client connections are long-lived. Be sure to refesh timely.
      */
-    if (now - last > 10) {
+#ifdef DETACH_AND_ASK_CLIENTS_TO_RECONNECT
+    if (server_flags == 0 && (now = event_time()) - last > 10) {
        if ((table = dict_changed_name()) != 0) {
            msg_info("table %s has changed -- restarting", table);
-           exit(0);
+           if (multi_server_drain() == 0)
+               server_flags = 1;
        }
        last = now;
     }
+#endif
 
     /*
      * This routine runs whenever a client connects to the UNIX-domain socket
@@ -376,6 +436,37 @@ static void rewrite_service(VSTREAM *stream, char *unused_service, char **argv)
        multi_server_disconnect(stream);
 }
 
+/* pre_accept - see if tables have changed */
+
+#ifdef CHECK_TABLE_STATS_BEFORE_ACCEPT
+
+static void pre_accept(char *unused_name, char **unused_argv)
+{
+    const char *table;
+
+    if ((table = dict_changed_name()) != 0) {
+       msg_info("table %s has changed -- restarting", table);
+       exit(0);
+    }
+}
+
+#endif
+
+#ifdef CHECK_TABLE_STATS_PERIODICALLY
+
+static void check_table_stats(int unused_event, char *unused_context)
+{
+    const char *table;
+
+    if ((table = dict_changed_name()) != 0) {
+       msg_info("table %s has changed -- restarting", table);
+       exit(0);
+    }
+    event_request_timer(check_table_stats, (char *) 0, 10);
+}
+
+#endif
+
 /* pre_jail_init - initialize before entering chroot jail */
 
 static void pre_jail_init(char *unused_name, char **unused_argv)
@@ -401,6 +492,9 @@ static void post_jail_init(char *unused_name, char **unused_argv)
        transport_post_init(resolve_regular.transport_info);
     if (resolve_verify.transport_info)
        transport_post_init(resolve_verify.transport_info);
+#ifdef CHECK_TABLE_STATS_PERIODICALLY
+    check_table_stats(0, (char *) 0);
+#endif
 }
 
 /* main - pass control to the multi-threaded skeleton code */
@@ -444,5 +538,8 @@ 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,
+#ifdef CHECK_TABLE_STATS_BEFORE_ACCEPT
+                     MAIL_SERVER_PRE_ACCEPT, pre_accept,
+#endif
                      0);
 }
index ce59970a9a273ef8037f0009e5a1aa7c6de65e7d..b8ceb4277a1907d2d9f771885f65ef17bbdae32f 100644 (file)
   */
 #include <tok822.h>
 
+ /*
+  * Connection management.
+  */
+int     server_flags;
+
  /*
   * rewrite.c
   */
@@ -27,7 +32,7 @@ typedef struct {
     char  **origin;                    /* default origin */
     const char *domain_name;           /* name of variable */
     char  **domain;                    /* default domain */
-} RWR_CONTEXT;
+}       RWR_CONTEXT;
 
 #define REW_PARAM_VALUE(x) (*(x))      /* make it easy to do it right */
 
index 19984f90e1d66157822ae59fb5275e89cb477335..42a36589648c1e3e8557620a6bd9d30d1e6b3754 100644 (file)
@@ -303,6 +303,7 @@ extern int opterr;
 #define NATIVE_COMMAND_DIR "/usr/etc"
 #define NATIVE_DAEMON_DIR "/usr/libexec/postfix"
 #define STRCASECMP_IN_STRINGS_H
+#define OCTAL_TO_UNSIGNED(res, str) sscanf((str), "%o", &(res))
 #endif
 
  /*
@@ -1116,6 +1117,10 @@ extern int inet_pton(int, const char *, void *);
 typedef int WAIT_STATUS_T;
 
 #define NORMAL_EXIT_STATUS(status)     ((status) == 0)
+#endif
+
+#ifndef OCTAL_TO_UNSIGNED
+#define OCTAL_TO_UNSIGNED(res, str)    ((res) = strtoul((str), (char **) 0, 8))
 #endif
 
  /*