]> git.ipfire.org Git - thirdparty/postfix.git/commitdiff
snapshot-19990527
authorWietse Venema <wietse@porcupine.org>
Thu, 27 May 1999 05:00:00 +0000 (00:00 -0500)
committerWietse Venema <wietse@porcupine.org>
Thu, 17 Jan 2013 03:34:27 +0000 (22:34 -0500)
27 files changed:
postfix/HISTORY
postfix/RELEASE_NOTES
postfix/cleanup/cleanup_envelope.c
postfix/cleanup/cleanup_extracted.c
postfix/cleanup/cleanup_map11.c
postfix/cleanup/cleanup_message.c
postfix/cleanup/cleanup_out.c
postfix/cleanup/cleanup_skip.c
postfix/conf/main.cf.default
postfix/global/mail_params.h
postfix/global/mail_version.h
postfix/html/faq.html
postfix/makedefs
postfix/master/Makefile.in
postfix/master/master.c
postfix/master/master.h
postfix/master/master_avail.c
postfix/master/master_conf.c
postfix/master/master_ent.c
postfix/master/master_sample.c [new file with mode: 0644]
postfix/smtp/smtp.h
postfix/smtp/smtp_addr.c
postfix/smtp/smtp_chat.c
postfix/smtp/smtp_connect.c
postfix/smtp/smtp_proto.c
postfix/smtp/smtp_session.c
postfix/smtp/smtp_trouble.c

index cd0b2e921b5ce075ca5f8ade719d8873f22bc16d..db56eee6ff92577097d3e8a3a8feaaf1f2238b15 100644 (file)
@@ -2790,8 +2790,22 @@ Apologies for any names omitted.
        discarded" warning when mail is dropped on the floor.
        Requested by Michael Hasenstein, SuSE, Germany.
 
+19990516
+
+       Feature: per-service peak and average process limit. When
+       the system is lightly loaded, use the per-service peak
+       process limit.  When the system is under stress, use the
+       per-service average process limit. The per-service average
+       process count is computed once a minute.
+
 19990517
 
        Bugfix: reject_non_fqdn_sender/recipient would pass
        user@[ip_address] regardless of destination. Eric Cholet
        had the honor of suffering from this one.
+
+19990527
+
+       More SMTP client logging for easier debugging: the smtp
+       client now logs hostname[ip.addr], and logs every failed
+       attempt to reach an MX host, not just the last one.
index 79ddd58e7a0cba9f8a20c337696e08f4158d7934..0d3f3744aeaf881aa31f02ed6cf6b176071bd86d 100644 (file)
@@ -27,12 +27,12 @@ commands into separate directories.
 Major changes with snapshot-19990513:
 =====================================
 
-- New USER, EXTENSION, LOCAL and DOMAIN environment variables for
-delivery to command (including mailbox_command) by the local delivery
-agent. As you might expect, the information is censored. The list
-of acceptable characters is specified with the command_expansion_filter
-configuration parameter.  Unacceptable characters are replaced by
-underscores.
+- New USER, EXTENSION, LOCAL, DOMAIN. and RECIPIENT environment
+variables for delivery to command (including mailbox_command) by
+the local delivery agent. As you might expect, the information is
+censored. The list of acceptable characters is specified with the
+command_expansion_filter configuration parameter.  Unacceptable
+characters are replaced by underscores. See html/local.8.html.
 
 - Specify "forward_path = /var/forward/$user" to avoid looking up
 .forward files in user home directories.  The default value is
index e7c29bf1c8189bf9c7364d3a8597bbf916636e23..6e009b23ec764f18f25c32dc6664d9acc1ae2cc6 100644 (file)
@@ -78,7 +78,8 @@ void    cleanup_envelope(void)
        }
        if (type == REC_TYPE_MESG) {
            if (cleanup_sender == 0 || cleanup_time == 0) {
-               msg_warn("missing sender or time envelope record");
+               msg_warn("%s: missing sender or time envelope record",
+                        cleanup_queue_id);
                cleanup_errs |= CLEANUP_STAT_BAD;
            } else {
                if (warn_time == 0 && var_delay_warn_time > 0)
@@ -90,7 +91,8 @@ void    cleanup_envelope(void)
            break;
        }
        if (strchr(REC_TYPE_ENVELOPE, type) == 0) {
-           msg_warn("unexpected record type %d in envelope", type);
+           msg_warn("%s: unexpected record type %d in envelope", type,
+                    cleanup_queue_id);
            cleanup_errs |= CLEANUP_STAT_BAD;
            break;
        }
@@ -117,7 +119,8 @@ void    cleanup_envelope(void)
                cleanup_sender = mystrdup(STR(clean_addr));
        } else if (type == REC_TYPE_RCPT) {
            if (cleanup_sender == 0) {          /* protect showq */
-               msg_warn("envelope recipient precedes sender");
+               msg_warn("%s: envelope recipient precedes sender",
+                        cleanup_queue_id);
                cleanup_errs |= CLEANUP_STAT_BAD;
                break;
            }
index 3bd442b79bdfe95c986ef0868a4489a5d4b23e91..1057273f5669049854904b063a24f7f53ed44273 100644 (file)
@@ -90,7 +90,8 @@ void    cleanup_extracted(void)
        } else if (type == REC_TYPE_END) {
            break;
        } else {
-           msg_warn("unexpected record type %d in extracted segment", type);
+           msg_warn("%s: unexpected record type %d in extracted segment",
+                    cleanup_queue_id, type);
            cleanup_errs |= CLEANUP_STAT_BAD;
            if (type >= 0)
                cleanup_skip();
index 0680191a87eecb80f95678e52ee4407671f78a04..96069324a90217dc2e66b0fe438f311ee7173bae 100644 (file)
@@ -103,8 +103,8 @@ void    cleanup_map11_external(VSTRING *addr, MAPS *maps, int propagate)
     for (count = 0; count < MAX_RECURSION; count++) {
        if ((new_addr = mail_addr_map(maps, STR(addr), propagate)) != 0) {
            if (new_addr->argc > 1)
-               msg_warn("multi-valued %s entry for %s",
-                        maps->title, STR(addr));
+               msg_warn("%s: multi-valued %s entry for %s",
+                        cleanup_queue_id, maps->title, STR(addr));
            saved_addr = mystrdup(STR(addr));
            vstring_strcpy(addr, new_addr->argv[0]);
            expand_to_self = !strcasecmp(saved_addr, STR(addr));
index 592a8696d3f7f916d15f083a73567944e5db8830..2a862e54cc3cee641d2845a07a98cf30656873f0 100644 (file)
@@ -391,7 +391,8 @@ void    cleanup_message(void)
            break;
        }
        if (strchr(REC_TYPE_CONTENT, type) == 0) {
-           msg_warn("%s: unexpected record type %d", myname, type);
+           msg_warn("%s: %s: unexpected record type %d",
+                    cleanup_queue_id, myname, type);
            cleanup_errs |= CLEANUP_STAT_BAD;
            break;
        }
index dd51383e6a950229f4ea4edab3472638a5be296b..7be237040813e84a5a6b8100b78f9b0f8efb2b3d 100644 (file)
@@ -84,7 +84,8 @@ void    cleanup_out(int type, char *string, int len)
     if (CLEANUP_OUT_OK()) {
        if (rec_put(cleanup_dst, type, string, len) < 0) {
            if (errno == EFBIG) {
-               msg_warn("queue file size limit exceeded");
+               msg_warn("%s: queue file size limit exceeded",
+                        cleanup_queue_id);
                cleanup_errs |= CLEANUP_STAT_SIZE;
            } else {
                msg_warn("%s: write queue file: %m", cleanup_queue_id);
index 00f73aa4b9778943e5f21a4564f668dbcd5d6c2b..d9d22ed5cc2794525cf7c5ea7ef60630d88c5bc2 100644 (file)
@@ -46,7 +46,7 @@ void    cleanup_skip(void)
 {
     int     type;
 
-    msg_warn("skipping further client input");
+    msg_warn("%s: skipping further client input", cleanup_queue_id);
 
     /*
      * XXX Rely on the front-end programs to enforce record size limits.
index ef7182e6f5ff5f0119a7e60af937475caff474d0..45bfd12e97b2be0e9cc78980b5a03eb2259c1a65 100644 (file)
@@ -62,7 +62,7 @@ luser_relay =
 mail_name = Postfix
 mail_owner = postfix
 mail_spool_directory = /var/mail
-mail_version = Snapshot-19990513
+mail_version = Snapshot-19990527
 mailbox_command = 
 mailbox_transport = 
 maps_rbl_domains = rbl.maps.vix.com
@@ -82,7 +82,7 @@ notify_classes = resource,software
 owner_request_special = yes
 process_id_directory = pid
 program_directory = /usr/libexec/postfix
-propagate_unmatched_extension = canonical, virtual
+propagate_unmatched_extensions = canonical, virtual
 qmgr_message_active_limit = 1000
 qmgr_message_recipient_limit = 10000
 queue_directory = /var/spool/postfix
index bd1ce7422d84aef10d0b66a64851176fe416fe7a..517e6fc5a76c0b90ecad3f9e5418186dbbaa20ae 100644 (file)
@@ -328,7 +328,7 @@ extern char *var_fallback_transport;
 #define DEF_FORWARD_PATH       "$home/.forward${recipient_delimiter}${extension},$home/.forward"
 extern char *var_forward_path;
 
-#define VAR_PROP_EXTENSION     "propagate_unmatched_extension"
+#define VAR_PROP_EXTENSION     "propagate_unmatched_extensions"
 #define DEF_PROP_EXTENSION     "canonical, virtual"
 extern char *var_prop_extension;
 
index caac8b2f4c83c8f707d0b921891bfc62f546a206..369c9134a61882560a31c814500b17a39223d957 100644 (file)
@@ -15,7 +15,7 @@
   * Version of this program.
   */
 #define VAR_MAIL_VERSION       "mail_version"
-#define DEF_MAIL_VERSION       "Snapshot-19990518"
+#define DEF_MAIL_VERSION       "Snapshot-19990527"
 extern char *var_mail_version;
 
 /* LICENSE
index 9070ba017bb3e46ac133cf85912599aea5577360..16cbd5033ff8f4044599e54df7384b9e31198819 100644 (file)
 
 <li><a href="#firewall">Running Postfix on a firewall</a>
 
+<li><a href="#dialup">Running Postfix on a dialup machine</a>
+
+<p>
+
 <li><a href="#local">Delivering some users locally while sending mail as user@domain</a>
 
 <li><a href="#maildir">Support for maildir-style mailboxes</a>
 
 <li><a href="#approve">Postfix breaks the majordomo "approve" command</a>
 
+<p>
+
 <li><a href="#uucp">Setting up an Internet to UUCP gateway</a>
 
 <li><a href="#uucp-only">Using UUCP as the default transport</a>
 
 <li><a href="#fax">Sending mail to a FAX machine</a>
 
+<p>
+
 <li><a href="#timeouts">Mail fails with timeout or lost connection</a>
 
 <li><a href="#bind">Undefined symbols: ___dn_expand, ___res_init etc.</a>
@@ -241,6 +249,105 @@ Unfortunately, the solution cannot use the transport table, because
 that table is ignored for destinations that match <b>$mydestination</b>.
 That's an implementation error, and it will be removed.
 
+<hr>
+
+<a name="dialup"><h2>Running Postfix on a dialup machine</h2></a>
+
+<ul>
+
+<li> Route all outgoing mail to your provider.
+
+<p>
+
+If your machine is disconnected most of the time, there isn't
+a lot of opportunity for Postfix to deliver mail to hard-to-reach
+corners of the Internet. It's better to drop the mail to a machine
+that is connected all the time.
+
+<p>
+
+<dl>
+
+<dt><b>/etc/postfix/main.cf:</b>
+
+<dd><b>relayhost = smtprelay.someprovider.com</b>
+
+</dl>
+
+<p>
+
+<li> <a name="spontaneous_smtp">Disable spontaneous SMTP mail
+delivery.</a>
+
+<p>
+
+Normally, Postfix attempts to deliver outbound mail at its convenience.
+If your machine uses on-demand dialup IP, this causes your system
+to place a telephone call whenever you submit mail, and whenever
+Postfix retries to deliver delayed mail. To prevent such telephone
+calls from being placed, disable spontaneous SMTP mail deliveries.
+
+<p>
+
+<dl>
+
+<dt><b>/etc/postfix/main.cf:</b>
+
+<dd><b>defer_transports = smtp</b> (Only for systems that use
+on-demand dialup IP)
+
+</dl>
+
+<p>
+
+<li> Disable SMTP client DNS lookups.
+
+<p>
+
+Some people use Postfix to deliver mail across a LAN that is
+disconnected most of the time.  Under such conditions, mail delivery
+can suffer from delays while the Postfix SMTP client performs sender
+and recipient domain DNS lookups in order to be standards-compliant.
+To prevent these delays, disable all SMTP client DNS lookups.
+
+<p>
+
+<dl>
+
+<dt><b>/etc/postfix/main.cf:</b>
+
+<dd><b>disable_dns_lookups = yes</b> (Only for delivery across LANs
+that are disconnected most of the time)
+
+</dl>
+
+<p>
+
+<li> Flush the mail queue whenever the Internet link is established.
+
+<p>
+
+Put the following command into your PPP or SLIP dialup scripts:
+
+<p>
+
+<dl>
+
+<dd><b>/usr/sbin/sendmail -q</b> (whenever the Internet link is up)
+
+</dl>
+
+<p>
+
+The exact location of the <b>sendmail</b> command is system-specific.
+With some UNIX versions, usr <b>/usr/lib/sendmail</b>.
+
+If you have disabled <a href="#spontaneous_smtp">spontaneous SMTP
+mail delivery</a> you need to run this command occasionally while
+the dialup link is up, so that newly-posted mail is flushed from
+the queue.
+
+</ul>
 
 <hr>
 
@@ -249,14 +356,14 @@ That's an implementation error, and it will be removed.
 <ul>
 
 <li>In order to send mail as <i>user@domain</i>, edit
-<b>/etc/postfix/main.cf</b> and specify that the local domain
+<b>/etc/postfix/main.cf</b> and specify what domain
 is to be appended to addresses that do not have a domain:
 
 <p>
 
 <dl>
 
-<dd><b>myorigin = </b><i>$mydomain</i>
+<dd><b>myorigin = </b><i>domain</i>
 
 </dl>
 
@@ -287,9 +394,9 @@ is to be appended to addresses that do not have a domain:
 
 <dl>
 
-<dd><b>root &nbsp; root@</b><i>my.host.name</i>
+<dd><b>root &nbsp; root@localhost</b>
 
-<dd><b>postmaster &nbsp; postmaster@</b><i>my.host.name</i>
+<dd><b>postmaster &nbsp; postmaster@localhost</b>
 
 </dl>
 
@@ -337,13 +444,18 @@ command for mailbox delivery:
 
 <dd><b>mailbox_command = </b><i>/path/to/procmail</i>
 
+<p>
+
+<dd><b>mailbox_command = </b><i>/path/to/procmail</i><b> &nbsp; -a
+&nbsp; "$EXTENSION"</b>
+
 </dl>
 
 <p>
 
-Do not use any shell meta characters or built-ins
-such as <b>IFS</b> or <b>&amp;&amp;</b>, because they force Postfix
-to run an expensive shell process.
+If you can, avoid using any shell meta characters or built-ins
+such as <b>$</b> or <b>"</b> or <b>IFS</b> or <b>&amp;&amp;</b>,
+because they force Postfix to run an expensive shell process.
 
 <p>
 
@@ -352,6 +464,39 @@ effective.
 
 </ul>
 
+Postfix exports information via environment variables. The contents
+are censored. Any characters that may have special meaning to the
+shell are replaced by underscores.
+
+<p>
+
+<dl>
+
+<dl>
+
+<dt><b>DOMAIN</b> <dd> The text to the right-hand side of the
+<b>@</b> in the recipient address.
+
+<dt><b>EXTENSION</b> <dd> Optional address extension part.
+
+<dt><b>HOME</b> <dd> The recpient's home directory.
+
+<dt><b>LOCAL</b> <dd> The text to the left-hand side of the <b>@</b>
+in the recipient address, for example, <b>$USER+$EXTENSION</b>.
+
+<dt><b>LOGNAME</b> <dd> The recipient username.
+
+<dt><b>RECIPIENT</b> <dd> The entire recipient address,
+<b>$LOCAL@$DOMAIN</b>.
+
+<dt><b>SHELL</b> <dd> The recipient's login shell.
+
+<dt><b>USER</b> <dd> The recipient username.
+
+</dl>
+
+</dl>
+
 <hr>
 
 <a name="verbose"><h2>Postfix breaks "sendmail -v"</h2> </a>
index 33ae8d1687ba425754b3dcc3ee6c7bc4440656e8..50e58dec2594b488ba43938ecc3c0c22a0d3111b 100644 (file)
@@ -195,7 +195,8 @@ case "$CC" in
 */gcc|gcc) case `$CC -v` in
           "gcc version 2.8"*) : ${OPT=};;
           esac;;
-       *) : ${OPT='-O'};;
+      *CC) echo "Don't use CC. That's the C++ compiler" 1>&2; exit 1;;
+        *) : ${OPT='-O'};;
 esac
 
 : ${CC='gcc $(WARN)'} ${OPT='-O'} ${DEBUG='-g'}
index fe194f86e4d5b8fa6ef6811eb008474ebd292569..a8d7b963186b51e8916fa4c5e2809ecccd5a403d 100644 (file)
@@ -2,10 +2,10 @@ SHELL = /bin/sh
 SRCS   = master.c master_conf.c master_ent.c master_sig.c master_avail.c \
        master_spawn.c master_service.c master_status.o master_listen.c \
        master_proto.c single_server.c multi_server.c master_vars.c \
-       master_wakeup.c
+       master_wakeup.c master_sample.c
 OBJS   = master.o master_conf.o master_ent.o master_sig.o master_avail.o \
        master_spawn.o master_service.o master_status.o master_listen.o \
-       master_vars.o master_wakeup.o
+       master_vars.o master_wakeup.o master_sample.o
 LIB_OBJ        = single_server.o multi_server.o trigger_server.o master_proto.o
 HDRS   = mail_server.h master_proto.h
 INT_HDR        = master.h
@@ -118,6 +118,7 @@ master_ent.o: ../include/argv.h
 master_ent.o: ../include/stringops.h
 master_ent.o: ../include/readlline.h
 master_ent.o: ../include/inet_addr_list.h
+master_ent.o: ../include/split_at.h
 master_ent.o: ../include/mail_proto.h
 master_ent.o: ../include/iostuff.h
 master_ent.o: ../include/mail_params.h
@@ -139,6 +140,11 @@ master_proto.o: master_proto.c
 master_proto.o: ../include/sys_defs.h
 master_proto.o: ../include/msg.h
 master_proto.o: master_proto.h
+master_sample.o: master_sample.c
+master_sample.o: ../include/sys_defs.h
+master_sample.o: ../include/events.h
+master_sample.o: ../include/msg.h
+master_sample.o: master.h
 master_service.o: master_service.c
 master_service.o: ../include/sys_defs.h
 master_service.o: ../include/msg.h
index 463d324aea9357b5a0b676d58a5f45e54a827f2a..36f0b1e36ec134e232c7a9e984bfa0c2ede8351b 100644 (file)
@@ -331,6 +331,7 @@ int     main(int argc, char **argv)
      * that there are no concurrency conflicts within the master process.
      */
     signal(SIGALRM, master_watchdog);
+    master_sample_start();
     for (;;) {
 #ifdef HAS_VOLATILE_LOCKS
        if (myflock(vstream_fileno(lock_fp), MYFLOCK_EXCLUSIVE) < 0)
index f09af8770c54a7ebbc77ebbcbc8f0bfcc630a975..d54748f6e7f323d4585792d042359c15c22b6309 100644 (file)
@@ -27,10 +27,13 @@ typedef struct MASTER_SERV {
        struct INET_ADDR_LIST *inet;
     } addr_list;
     int     max_proc;                  /* upper bound on # processes */
+    int     max_proc_pk;               /* peak upper bound */
+    int     max_proc_avg;              /* average upper bound */
     char   *path;                      /* command pathname */
     struct ARGV *args;                 /* argument vector */
     int     avail_proc;                        /* idle processes */
     int     total_proc;                        /* number of processes */
+    float   total_proc_avg;            /* average number of processes */
     int     throttle_delay;            /* failure recovery parameter */
     int     status_fd[2];              /* child status reports */
     struct BINHASH *children;          /* linkage */
@@ -155,6 +158,12 @@ extern void master_spawn(MASTER_SERV *);
 extern void master_reap_child(void);
 extern void master_delete_children(MASTER_SERV *);
 
+ /*
+  * master_sample.c
+  */
+extern void master_sample_start(void);
+extern void master_sample_stop(void);
+
 /* DIAGNOSTICS
 /* BUGS
 /* SEE ALSO
index e5507ef6d9b95f1fb196458c43a45a99b8f319d8..7defd510b2efefe3011084ee482d42dd1dc39641 100644 (file)
@@ -102,8 +102,10 @@ void    master_avail_listen(MASTER_SERV *serv)
      * request.
      */
     if (msg_verbose)
-       msg_info("%s: avail %d total %d max %d", myname,
-                serv->avail_proc, serv->total_proc, serv->max_proc);
+       msg_info("%s: avail %d total/avg %d/%.1f max/pk/avg %d/%d/%d", myname,
+                serv->avail_proc, serv->total_proc, serv->total_proc_avg,
+                serv->max_proc, serv->max_proc, serv->max_proc_pk,
+                serv->max_proc_avg);
     if (serv->avail_proc < 1
        && MASTER_LIMIT_OK(serv->max_proc, serv->total_proc)
        && !MASTER_THROTTLED(serv)) {
index 08329553115ee679e196d639d9be4deb49089a56..85da4619dbf6a0fae919fd9f42fc78c77c2ec3f6 100644 (file)
@@ -124,7 +124,8 @@ void    master_config(void)
        else {
            serv->flags &= ~MASTER_FLAG_MARK;
            serv->wakeup_time = entry->wakeup_time;
-           serv->max_proc = entry->max_proc;
+           serv->max_proc_pk = entry->max_proc_pk;
+           serv->max_proc_avg = entry->max_proc_avg;
            serv->throttle_delay = entry->throttle_delay;
            SWAP(char *, serv->path, entry->path);
            SWAP(ARGV *, serv->args, entry->args);
index ae77491caf2dbd584011dd30a67eec9cd62b09bd..3557f4fa18cfc7ecfc37a9b568b301da34f4f991 100644 (file)
@@ -84,6 +84,7 @@
 #include <stringops.h>
 #include <readlline.h>
 #include <inet_addr_list.h>
+#include <split_at.h>
 
 /* Global library. */
 
@@ -183,13 +184,10 @@ static char *get_str_ent(char **bufp, char *name, char *def_val)
     }
 }
 
-/* get_bool_ent - extract boolean field */
+/* cvt_bool_ent - convert boolean field */
 
-static int get_bool_ent(char **bufp, char *name, char *def_val)
+static int cvt_bool_ent(char *name, char *value)
 {
-    char   *value;
-
-    value = get_str_ent(bufp, name, def_val);
     if (strcmp("y", value) == 0) {
        return (1);
     } else if (strcmp("n", value) == 0) {
@@ -200,19 +198,37 @@ static int get_bool_ent(char **bufp, char *name, char *def_val)
     /* NOTREACHED */
 }
 
-/* get_int_ent - extract integer field */
+/* get_bool_ent - extract boolean field */
 
-static int get_int_ent(char **bufp, char *name, char *def_val, int min_val)
+static int get_bool_ent(char **bufp, char *name, char *def_val)
 {
     char   *value;
-    int     n;
 
     value = get_str_ent(bufp, name, def_val);
+    return (cvt_bool_ent(name, value));
+}
+
+/* cvt_int_ent - convert integer field */
+
+static int cvt_int_ent(char *name, char *value, int min_val)
+{
+    int     n;
+
     if (!ISDIGIT(*value) || (n = atoi(value)) < min_val)
        fatal_invalid_field(name, value);
     return (n);
 }
 
+/* get_int_ent - extract integer field */
+
+static int get_int_ent(char **bufp, char *name, char *def_val, int min_val)
+{
+    char   *value;
+
+    value = get_str_ent(bufp, name, def_val);
+    return (cvt_int_ent(name, value, min_val));
+}
+
 /* get_master_ent - read entry from configuration file */
 
 MASTER_SERV *get_master_ent()
@@ -229,6 +245,7 @@ MASTER_SERV *get_master_ent()
     char   *command;
     int     n;
     char   *bufp;
+    char   *cp2;
 
     if (master_fp == 0)
        msg_panic("get_master_ent: config file not open");
@@ -343,7 +360,23 @@ MASTER_SERV *get_master_ent()
      * Concurrency limit. Zero means no limit.
      */
     vstring_sprintf(junk, "%d", var_proc_limit);
-    serv->max_proc = get_int_ent(&bufp, "max_proc", vstring_str(junk), 0);
+    cp = get_str_ent(&bufp, "max_proc", vstring_str(junk));
+    if ((cp2 = split_at(cp, '/')) != 0) {
+       serv->max_proc_pk = cvt_int_ent("max_proc", strcmp(cp, "-") != 0 ?
+                                       cp : vstring_str(junk), 0);
+       serv->max_proc_avg = cvt_int_ent("max_proc", strcmp(cp2, "-") != 0 ?
+                                        cp2 : vstring_str(junk), 0);
+       if (serv->max_proc_pk == 0 && serv->max_proc_avg != 0)
+           fatal_with_context("specify a non-zero peak process limit");
+       if (serv->max_proc_pk != 0 && serv->max_proc_avg == 0)
+           fatal_with_context("specify a non-zero average process limit");
+       if (serv->max_proc_pk < serv->max_proc_avg)
+           fatal_with_context("peak < average process limit");
+    } else {
+       serv->max_proc_pk = cvt_int_ent("max_proc", cp, 0);
+       serv->max_proc_avg = serv->max_proc;
+    }
+    serv->max_proc = serv->max_proc_pk;
 
     /*
      * Path to command,
@@ -356,6 +389,7 @@ MASTER_SERV *get_master_ent()
      */
     serv->avail_proc = 0;
     serv->total_proc = 0;
+    serv->total_proc_avg = 0;
 
     /*
      * Backoff time in case a service is broken.
@@ -378,7 +412,7 @@ MASTER_SERV *get_master_ent()
      */
     serv->args = argv_alloc(0);
     argv_add(serv->args, command, (char *) 0);
-    if (serv->max_proc == 1)
+    if (serv->max_proc_pk == 1)
        argv_add(serv->args, "-l", (char *) 0);
     if (strcmp(basename(command), name) != 0)
        argv_add(serv->args, "-n", name, (char *) 0);
@@ -422,11 +456,14 @@ void    print_master_ent(MASTER_SERV *serv)
     msg_info("listen_fd_count: %d", serv->listen_fd_count);
     msg_info("wakeup: %d", serv->wakeup_time);
     msg_info("max_proc: %d", serv->max_proc);
+    msg_info("max_proc_pk: %d", serv->max_proc_pk);
+    msg_info("max_proc_avg: %d", serv->max_proc_avg);
     msg_info("path: %s", serv->path);
     for (cpp = serv->args->argv; *cpp; cpp++)
        msg_info("arg[%d]: %s", (int) (cpp - serv->args->argv), *cpp);
     msg_info("avail_proc: %d", serv->avail_proc);
     msg_info("total_proc: %d", serv->total_proc);
+    msg_info("total_proc_avg: %f", serv->total_proc_avg);
     msg_info("throttle_delay: %d", serv->throttle_delay);
     msg_info("status_fd %d %d", serv->status_fd[0], serv->status_fd[1]);
     msg_info("children: 0x%lx", (long) serv->children);
diff --git a/postfix/master/master_sample.c b/postfix/master/master_sample.c
new file mode 100644 (file)
index 0000000..e3200b2
--- /dev/null
@@ -0,0 +1,98 @@
+/*++
+/* NAME
+/*     master_sample 3
+/* SUMMARY
+/*     Postfix master - statistics sampling
+/* SYNOPSIS
+/*     #include "master.h"
+/*
+/*     void    master_sample_start()
+/*
+/*     void    master_sample_stop(serv)
+/* DESCRIPTION
+/*     This module samples statistics at one-minute intervals.
+/*     Currently, it maintains the average process counts.
+/*
+/*     master_sample_start() resets the statistics and starts
+/*     the statistics sampling process.
+/*
+/*     master_sample_start() stops the statistics sampling process.
+/* DIAGNOSTICS
+/* BUGS
+/* SEE ALSO
+/* 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 libraries. */
+
+#include <sys_defs.h>
+
+/* Utility library. */
+
+#include <events.h>
+#include <msg.h>
+
+/* Application-specific. */
+
+#include "master.h"
+
+/* master_sample_action - take sample */
+
+static void master_sample_action(int unused_event, char *unused_context)
+{
+    MASTER_SERV *serv;
+
+#define TSAMPLE        60
+#define NSAMPLE 5
+
+    /*
+     * Update the process limit for services that have different peak/average
+     * concurrency limits. Gradually change from idle mode (allowing peak
+     * concurrency) to stress mode (long-term average process limit).
+     */
+    for (serv = master_head; serv != 0; serv = serv->next) {
+       if (serv->max_proc_pk == 0 || serv->max_proc_avg == 0
+           || serv->max_proc_pk == serv->max_proc_avg)
+           continue;
+       serv->total_proc_avg +=
+           (serv->total_proc - serv->total_proc_avg) / NSAMPLE;
+       if (msg_verbose)
+           msg_info("%s total/avg %d/%.1f",
+                    serv->name, serv->total_proc, serv->total_proc_avg);
+       if (serv->max_proc_pk < serv->max_proc_avg)
+           msg_panic("%s: process limit botch: %d < %d",
+                     serv->name, serv->max_proc_pk, serv->max_proc_avg);
+       if (serv->total_proc_avg >= serv->max_proc_avg)
+           serv->max_proc = serv->max_proc_avg;
+       else
+           serv->max_proc = serv->max_proc_pk
+               - serv->total_proc_avg * (serv->max_proc_pk - serv->max_proc_avg) / (double) serv->max_proc_avg;
+    }
+    event_request_timer(master_sample_action, (char *) 0, TSAMPLE);
+}
+
+/* master_sample_start - start sampling */
+
+void    master_sample_start(void)
+{
+    MASTER_SERV *serv;
+
+    for (serv = master_head; serv != 0; serv = serv->next)
+       serv->total_proc_avg = 0;
+    event_request_timer(master_sample_action, (char *) 0, TSAMPLE);
+}
+
+/* master_sample_stop - stop sampling */
+
+void    master_sample_stop(void)
+{
+    event_cancel_timer(master_sample_action, (char *) 0);
+}
index 0d34d8372127614a7f723c41ffb3827e6879ce91..e236d9a07707f7647ea0029a88ad29658455b717 100644 (file)
@@ -54,6 +54,7 @@ typedef struct SMTP_SESSION {
     VSTREAM *stream;                   /* network connection */
     char   *host;                      /* mail exchanger */
     char   *addr;                      /* mail exchanger */
+    char   *namaddr;                   /* mail exchanger */
     int     best;                      /* most preferred host */
 } SMTP_SESSION;
 
index 9d32ba0749a459f88717a29837d5ad3671619f47..7d44ad2ecfe87cb7db039e373fda8b1c2e61063b 100644 (file)
@@ -143,9 +143,11 @@ static DNS_RR *smtp_addr_one(DNS_RR *addr_list, char *host, unsigned pref, VSTRI
      */
     if (ISDIGIT(host[0]) && (inaddr.s_addr = inet_addr(host)) != INADDR_NONE) {
        memset((char *) &fixed, 0, sizeof(fixed));
-       return (dns_rr_append(addr_list,
-                             dns_rr_create(host, &fixed, pref,
-                                       (char *) &inaddr, sizeof(inaddr))));
+       rr = dns_rr_create(host, &fixed, pref,
+                          (char *) &inaddr, sizeof(inaddr));
+       if (msg_verbose)
+           smtp_print_addr(host, rr);
+       return (dns_rr_append(addr_list, rr));
     }
 
     /*
@@ -163,10 +165,12 @@ static DNS_RR *smtp_addr_one(DNS_RR *addr_list, char *host, unsigned pref, VSTRI
            smtp_errno = SMTP_FAIL;
        } else {
            while (hp->h_addr_list[0]) {
-               addr_list = dns_rr_append(addr_list,
-                                         dns_rr_create(host, &fixed, pref,
-                                                       hp->h_addr_list[0],
-                                                       sizeof(inaddr)));
+               rr = dns_rr_create(host, &fixed, pref,
+                                  hp->h_addr_list[0],
+                                  sizeof(inaddr));
+               if (msg_verbose)
+                   smtp_print_addr(host, rr);
+               addr_list = dns_rr_append(addr_list, rr);
                hp->h_addr_list++;
            }
        }
@@ -180,6 +184,8 @@ static DNS_RR *smtp_addr_one(DNS_RR *addr_list, char *host, unsigned pref, VSTRI
     case DNS_OK:
        for (rr = addr; rr; rr = rr->next)
            rr->pref = pref;
+       if (msg_verbose)
+           smtp_print_addr(host, addr_list);
        addr_list = dns_rr_append(addr_list, addr);
        break;
     default:
index 7d3547461456e51848b47c0d074e26fe62aa10d7..de11387a122625ccf8a81d8a660610bbfd1267a9 100644 (file)
@@ -142,7 +142,7 @@ void    smtp_chat_cmd(SMTP_STATE *state, char *fmt,...)
      * program is trying to do.
      */
     if (msg_verbose)
-       msg_info("> %s: %s", session->host, STR(state->buffer));
+       msg_info("> %s: %s", session->namaddr, STR(state->buffer));
 
     /*
      * Send the command to the SMTP server.
@@ -177,9 +177,9 @@ SMTP_RESP *smtp_chat_resp(SMTP_STATE *state)
        cp = printable(STR(state->buffer), '?');
        if (last_char != '\n')
            msg_warn("%s: response longer than %d: %.30s...",
-                    session->host, var_line_limit, cp);
+                    session->namaddr, var_line_limit, cp);
        if (msg_verbose)
-           msg_info("< %s: %s", session->host, cp);
+           msg_info("< %s: %s", session->namaddr, cp);
        while (ISDIGIT(*cp))
            cp++;
        rdata.code = (cp - STR(state->buffer) == 3 ?
@@ -256,9 +256,9 @@ void    smtp_chat_notify(SMTP_STATE *state)
                      mail_addr_mail_daemon());
     post_mail_fprintf(notice, "To: %s (Postmaster)", var_error_rcpt);
     post_mail_fprintf(notice, "Subject: %s SMTP client: errors from %s",
-                     var_mail_name, session->host);
+                     var_mail_name, session->namaddr);
     post_mail_fputs(notice, "");
-    post_mail_fprintf(notice, "Unexpected response from %s.", session->host);
+    post_mail_fprintf(notice, "Unexpected response from %s.", session->namaddr);
     post_mail_fputs(notice, "");
     post_mail_fputs(notice, "Transcript of session follows.");
     post_mail_fputs(notice, "");
index 1cd81061ab0a68d78e17dec8db7bd9789023dc60..525add1b7722d3eff7e91ad7cc9d1f9bae0f5268 100644 (file)
@@ -256,6 +256,7 @@ SMTP_SESSION *smtp_connect_host(char *host, unsigned port, VSTRING *why)
 
 SMTP_SESSION *smtp_connect_domain(char *name, unsigned port, VSTRING *why)
 {
+    struct in_addr inaddr;
     SMTP_SESSION *session = 0;
     DNS_RR *addr_list;
     DNS_RR *addr;
@@ -274,6 +275,11 @@ SMTP_SESSION *smtp_connect_domain(char *name, unsigned port, VSTRING *why)
            session->best = (addr->pref == addr_list->pref);
            break;
        }
+       if (addr->next) {
+           memcpy((char *) &inaddr, addr->data, sizeof(inaddr));
+           msg_info("%s: connect to %s port %d: %s",
+                    name, inet_ntoa(inaddr), port, vstring_str(why));
+       }
     }
     dns_rr_free(addr_list);
     return (session);
index b29b5c4184f9d15f386c9877e273693a2d6d9fa7..11db0bfeef152c0b0658b3d369ab0a4ec98231d5 100644 (file)
@@ -166,7 +166,7 @@ int     smtp_helo(SMTP_STATE *state)
     if (((resp = smtp_chat_resp(state))->code / 100) != 2)
        return (smtp_site_fail(state, resp->code,
                               "host %s refused to talk to me: %s",
-                           session->host, translit(resp->str, "\n", " ")));
+                        session->namaddr, translit(resp->str, "\n", " ")));
 
     /*
      * See if we are talking to ourself. This should not be possible with the
@@ -179,7 +179,7 @@ int     smtp_helo(SMTP_STATE *state)
     for (n = 0; (word = mystrtok(&words, " \t\n")) != 0; n++) {
        if (n == 0 && strcasecmp(word, var_myhostname) == 0) {
            msg_warn("host %s greeted me with my own hostname %s",
-                    session->host, var_myhostname);
+                    session->namaddr, var_myhostname);
            return (smtp_site_fail(state, session->best ? 550 : 450,
                                   "mail for %s loops back to myself",
                                   request->nexthop));
@@ -201,7 +201,7 @@ int     smtp_helo(SMTP_STATE *state)
        if ((resp = smtp_chat_resp(state))->code / 100 != 2)
            return (smtp_site_fail(state, resp->code,
                                   "host %s refused to talk to me: %s",
-                                  session->host,
+                                  session->namaddr,
                                   translit(resp->str, "\n", " ")));
     }
 
@@ -441,7 +441,7 @@ int     smtp_xfer(SMTP_STATE *state)
                case SMTP_STATE_MAIL:
                    if (resp->code / 100 != 2) {
                        smtp_mesg_fail(state, resp->code,
-                                      "host %s said: %s", session->host,
+                                      "host %s said: %s", session->namaddr,
                                       translit(resp->str, "\n", " "));
                        mail_from_rejected = 1;
                    }
@@ -461,7 +461,7 @@ int     smtp_xfer(SMTP_STATE *state)
                        } else {
                            rcpt = request->rcpt_list.info + recv_rcpt;
                            smtp_rcpt_fail(state, resp->code, rcpt,
-                                          "host %s said: %s", session->host,
+                                      "host %s said: %s", session->namaddr,
                                           translit(resp->str, "\n", " "));
                            rcpt->offset = 0;   /* in case deferred */
                        }
@@ -479,7 +479,7 @@ int     smtp_xfer(SMTP_STATE *state)
                    if (resp->code / 100 != 3) {
                        if (nrcpt > 0)
                            smtp_mesg_fail(state, resp->code,
-                                          "host %s said: %s", session->host,
+                                      "host %s said: %s", session->namaddr,
                                           translit(resp->str, "\n", " "));
                        nrcpt = -1;
                    }
@@ -500,14 +500,15 @@ int     smtp_xfer(SMTP_STATE *state)
                        if (resp->code / 100 != 2) {
                            smtp_mesg_fail(state, resp->code,
                                           "host %s said: %s",
-                                          session->host,
+                                          session->namaddr,
                                           translit(resp->str, "\n", " "));
                        } else {
                            for (nrcpt = 0; nrcpt < recv_rcpt; nrcpt++) {
                                rcpt = request->rcpt_list.info + nrcpt;
                                if (rcpt->offset) {
                                    sent(request->queue_id, rcpt->address,
-                                        session->host, request->arrival_time, "%s",
+                                        session->namaddr,
+                                        request->arrival_time, "%s",
                                         resp->str);
                                    deliver_completed(state->src, rcpt->offset);
                                    rcpt->offset = 0;
@@ -604,6 +605,9 @@ int     smtp_xfer(SMTP_STATE *state)
                msg_fatal("queue file read error");
            if (rec_type != REC_TYPE_XTRA)
                RETURN(mark_corrupt(state->src));
+#if 0
+           vstream_fflush(session->stream);
+#endif
        }
 
        /*
index 549bf14034057b9afb829258069058b1ca781d2e..4e95587238c2d5f48f65e3d1d58a95f64e637fc1 100644 (file)
@@ -40,6 +40,7 @@
 
 #include <mymalloc.h>
 #include <vstream.h>
+#include <stringops.h>
 
 /* Application-specific. */
 
@@ -55,6 +56,7 @@ SMTP_SESSION *smtp_session_alloc(VSTREAM *stream, char *host, char *addr)
     session->stream = stream;
     session->host = mystrdup(host);
     session->addr = mystrdup(addr);
+    session->namaddr = concatenate(host, "[", addr, "]", (char *) 0);
     session->best = 1;
     return (session);
 }
@@ -66,6 +68,7 @@ void    smtp_session_free(SMTP_SESSION *session)
     vstream_fclose(session->stream);
     myfree(session->host);
     myfree(session->addr);
+    myfree(session->namaddr);
     myfree((char *) session);
 }
 
index 0cf53a2896860482c75f505786ffaf815e0af292..2bf2c64b72d93852731cea4d9056acd16c7fbed0 100644 (file)
@@ -168,7 +168,7 @@ int     smtp_site_fail(SMTP_STATE *state, int code, char *format,...)
            continue;
        status = (soft_error ? defer_append : bounce_append)
            (KEEP, request->queue_id, rcpt->address,
-            session ? session->host : "none",
+            session ? session->namaddr : "none",
             request->arrival_time, "%s", vstring_str(why));
        if (status == 0) {
            deliver_completed(state->src, rcpt->offset);
@@ -215,7 +215,7 @@ int     smtp_mesg_fail(SMTP_STATE *state, int code, char *format,...)
            continue;
        status = (SMTP_SOFT(code) ? defer_append : bounce_append)
            (KEEP, request->queue_id, rcpt->address,
-            session->host, request->arrival_time,
+            session->namaddr, request->arrival_time,
             "%s", vstring_str(why));
        if (status == 0) {
            deliver_completed(state->src, rcpt->offset);
@@ -248,7 +248,7 @@ void    smtp_rcpt_fail(SMTP_STATE *state, int code, RECIPIENT *rcpt,
      */
     va_start(ap, format);
     status = (SMTP_SOFT(code) ? vdefer_append : vbounce_append)
-       (KEEP, request->queue_id, rcpt->address, session->host,
+       (KEEP, request->queue_id, rcpt->address, session->namaddr,
         request->arrival_time, format, ap);
     va_end(ap);
     if (status == 0) {
@@ -277,11 +277,11 @@ int     smtp_stream_except(SMTP_STATE *state, int code, char *description)
        msg_panic("smtp_stream_except: unknown exception %d", code);
     case SMTP_ERR_EOF:
        vstring_sprintf(why, "lost connection with %s while %s",
-                       session->host, description);
+                       session->namaddr, description);
        break;
     case SMTP_ERR_TIME:
        vstring_sprintf(why, "conversation with %s timed out while %s",
-                       session->host, description);
+                       session->namaddr, description);
        break;
     }
 
@@ -294,7 +294,7 @@ int     smtp_stream_except(SMTP_STATE *state, int code, char *description)
        if (rcpt->offset == 0)
            continue;
        state->status |= defer_append(KEEP, request->queue_id,
-                                     rcpt->address, session->host,
+                                     rcpt->address, session->namaddr,
                                      request->arrival_time,
                                      "%s", vstring_str(why));
     }