]> git.ipfire.org Git - thirdparty/postfix.git/commitdiff
postfix-1.1.11-20020910
authorWietse Venema <wietse@porcupine.org>
Tue, 10 Sep 2002 05:00:00 +0000 (00:00 -0500)
committerViktor Dukhovni <viktor@dukhovni.org>
Tue, 5 Feb 2013 06:28:13 +0000 (06:28 +0000)
postfix/HISTORY
postfix/README_FILES/VIRTUAL_README
postfix/RELEASE_NOTES
postfix/src/global/mail_version.h
postfix/src/smtp/smtp_chat.c
postfix/src/smtp/smtp_connect.c
postfix/src/smtpd/smtpd_chat.c
postfix/src/util/dict_ldap.c
postfix/src/util/dict_regexp.c
postfix/src/util/dict_static.c

index f31d85e1ab3ec698dbc54509b420cf01629785a6..ae7f7ee64f5c84e8e8e70d91299a78d6a92d71d8 100644 (file)
@@ -6926,6 +6926,25 @@ Apologies for any names omitted.
        Bugfix: the LDAP client dumped core in verbose mode.
        Reported by Will Day and others.  File: util/dict_ldap.c.
 
+20020906
+
+       Cleanup: dict_regexp module speedups by avoiding unnecessary
+       work while matching strings. File: util/dict_regexp.c.
+
+20020907
+
+       Feature: IF..ENDIF support based on code by Bert Driehuis.
+       File: util/dict_regexp.c.
+
+200209010
+
+       Bugfix: the SMTP client produced unnecessary warnings about
+       trouble with the fallback_relay hosts. File:  smtp/smtp_connect.c.
+
+       Robustness: don't wait with detecting broken SMTP connections
+       until reading input. Leandro Santi. File: smtpd/smtpd_chat.c.
+
 Open problems:
 
        Low: smtpd should log queue ID with reject/warn/hold/discard
index 6ad5fe7bd8fbfa9ad8045e1e0421afa1411c5c10..2f8439dd7f96110d2ecc269dbeb27d867424c206 100644 (file)
@@ -138,7 +138,7 @@ virtual_mailbox_lock
     Use the "postconf -m" command to find out what locking methods
     Postfix supports on your system.
 
-virtual_mailbox_size
+virtual_mailbox_limit
 
     An upper limit on the size of a mailbox file or maildir file.
 
index c5df4ce846e8e7c529280895236e125091a1c874..1168c9d7801ec93d0a1fa36be2edb933e6a7eb0f 100644 (file)
@@ -12,6 +12,12 @@ snapshot release).  Patches change the patchlevel and the release
 date. Snapshots change only the release date, unless they include
 the same bugfixes as a patch release.
 
+Incompatible changes with Postfix snapshot 1.1.11-20020910
+==========================================================
+
+The relayhost setting now behaves as documented, i.e. you can no
+longer specify multiple destinations.
+
 Incompatible changes with Postfix snapshot 1.1.11-20020906
 ==========================================================
 
index 68abbfa228a83d55e5576f27167df6904060de56..76b4acfed936327cb500896c5541f77cded855ca 100644 (file)
@@ -20,7 +20,7 @@
   * Patches change the patchlevel and the release date. Snapshots change the
   * release date only, unless they include the same bugfix as a patch release.
   */
-#define MAIL_RELEASE_DATE      "20020906"
+#define MAIL_RELEASE_DATE      "20020910"
 
 #define VAR_MAIL_VERSION       "mail_version"
 #define DEF_MAIL_VERSION       "1.1.11-" MAIL_RELEASE_DATE
index cbd81a2656289da1272a5d7c7c3dcd7d217c8e2f..d33a90e4e0454931d72d45fe401dd557d9788f23 100644 (file)
@@ -149,14 +149,6 @@ void    smtp_chat_cmd(SMTP_STATE *state, char *fmt,...)
      * Send the command to the SMTP server.
      */
     smtp_fputs(STR(state->buffer), LEN(state->buffer), session->stream);
-
-    /*
-     * Flush unsent output if no I/O happened for a while. This avoids
-     * timeouts with pipelined SMTP sessions that have lots of delays
-     * (typically, DNS lookups for sender/recipient unaliasing).
-     */
-    if (time((time_t *) 0) - vstream_ftime(session->stream) > 10)
-       vstream_fflush(session->stream);
 }
 
 /* smtp_chat_resp - read and process SMTP server response */
index c6ea16c4357bc0718df071defb120ebeead71f4a..38d769a7bf5a9789b1fee59073f5b0e130920a5c 100644 (file)
@@ -391,9 +391,9 @@ SMTP_SESSION *smtp_connect(char *destination, VSTRING *why)
     char   *host;
     unsigned port;
     char   *def_service = "smtp";      /* XXX configurable? */
-    char   *save;
+    ARGV   *sites;
     char   *dest;
-    char   *cp;
+    char  **cpp;
     int     found_myself = 0;
 
     /*
@@ -401,9 +401,11 @@ SMTP_SESSION *smtp_connect(char *destination, VSTRING *why)
      * to the optional fall-back relays. Each can be a list of destinations
      * by itself, with domain, host, [], numerical address, and port.
      */
-    cp = save = concatenate(destination, " ", var_fallback_relay, (char *) 0);
+    sites = argv_alloc(1);
+    argv_add(sites, destination, (char *) 0);
+    argv_split_append(sites, var_fallback_relay, ", \t\r\n");
 
-    while ((dest = mystrtok(&cp, ", \t\r\n")) != 0) {
+    for (cpp = sites->argv; (dest = *cpp) != 0; cpp++) {
 
        /*
         * Parse the destination. Default is to use the SMTP port.
@@ -448,8 +450,8 @@ SMTP_SESSION *smtp_connect(char *destination, VSTRING *why)
                     VAR_RELAYHOST, var_relayhost);
            smtp_errno = SMTP_RETRY;
        }
-       if (*var_fallback_relay) {
-           msg_warn("%s configuration problem: %s",
+       if (cpp > sites->argv && sites->argc > 1) {
+           msg_warn("%s problem: %s",
                     VAR_FALLBACK_RELAY, var_fallback_relay);
            smtp_errno = SMTP_RETRY;
        }
@@ -458,6 +460,6 @@ SMTP_SESSION *smtp_connect(char *destination, VSTRING *why)
     /*
      * Cleanup.
      */
-    myfree(save);
+    argv_free(sites);
     return (session);
 }
index b9be60015cdb7631ca06b08765cab1141b50f49e..ae2cf344b28a9679ca93c97955d4e21ed8541dc0 100644 (file)
@@ -139,6 +139,7 @@ void    smtpd_chat_query(SMTPD_STATE *state)
 void    smtpd_chat_reply(SMTPD_STATE *state, char *format,...)
 {
     va_list ap;
+    int     delay = 0;
 
     va_start(ap, format);
     vstring_vsprintf(state->buffer, format, ap);
@@ -157,9 +158,10 @@ void    smtpd_chat_reply(SMTPD_STATE *state, char *format,...)
      * errors within a session.
      */
     if (state->error_count > var_smtpd_soft_erlim)
-       sleep(state->error_count);
+       sleep(delay = (state->error_count > var_smtpd_err_sleep ?
+                      state->error_count : var_smtpd_err_sleep));
     else if (STR(state->buffer)[0] == '4' || STR(state->buffer)[0] == '5')
-       sleep(var_smtpd_err_sleep);
+       sleep(delay = var_smtpd_err_sleep);
 
     smtp_fputs(STR(state->buffer), LEN(state->buffer), state->client);
 
@@ -168,8 +170,14 @@ void    smtpd_chat_reply(SMTPD_STATE *state, char *format,...)
      * timeouts with pipelined SMTP sessions that have lots of server-side
      * delays (tarpit delays or DNS lookups for UCE restrictions).
      */
-    if (time((time_t *) 0) - vstream_ftime(state->client) > 10)
+    if (delay || time((time_t *) 0) - vstream_ftime(state->client) > 10)
        vstream_fflush(state->client);
+
+    /*
+     * Abort immediately if the connection is broken.
+     */
+    if (vstream_ferror(state->client))
+       vstream_longjmp(state->client, SMTP_ERR_EOF);
 }
 
 /* print_line - line_wrap callback */
index 7b2333b6b0673e3c18ef2366c8a5be273a0f004c..e8e7683eab14f79397b0fc1abf28a69627beb76a 100644 (file)
@@ -308,7 +308,7 @@ static int dict_ldap_connect(DICT_LDAP *dict_ldap)
                            &dict_ldap->version) != LDAP_OPT_SUCCESS)
            msg_warn("%s: Unable to get LDAP protocol version", myname);
        else
-           msg_warn("%s: Actual Protocol version used was %d.",
+           msg_warn("%s: Actual Protocol version used is %d.",
                     myname, dict_ldap->version);
     }
 #endif
index 1a55680b6df1b07b5ef1ec960f1bdba5645049f4..df1e3abd6eaa7861967924435635cc23e18300a6 100644 (file)
@@ -16,6 +16,7 @@
 /*     against the table.
 /* SEE ALSO
 /*     dict(3) generic dictionary manager
+/*     regexp_table(5) format of Postfix regular expression tables
 /* AUTHOR(S)
 /*     LaMont Jones
 /*     lamont@hp.com
@@ -43,6 +44,9 @@
 #include <string.h>
 #include <ctype.h>
 #include <regex.h>
+#ifdef STRCASECMP_IN_STRINGS_H
+#include <strings.h>
+#endif
 
 /* Utility library. */
 
 #include "dict_regexp.h"
 #include "mac_parse.h"
 
+ /*
+  * Support for IF/ENDIF based on code by Bert Driehuis.
+  */
+#define REGEXP_OP_MATCH                1       /* Match this regexp */
+#define REGEXP_OP_IF           2       /* Increase if/endif nesting on match */
+#define REGEXP_OP_ENDIF                3       /* Decrease if/endif nesting */
+
  /*
   * Regular expression before compiling.
   */
@@ -75,6 +86,8 @@ typedef struct dict_regexp_list {
     char   *replacement;               /* replacement text */
     size_t  max_nsub;                  /* largest replacement $number */
     int     lineno;                    /* source file line number */
+    int     nesting;                   /* Level of search nesting */
+    int     op;                                /* REGEXP_OP_MATCH, OP_IF, OP_ENDIF */
 } DICT_REGEXP_RULE;
 
  /*
@@ -168,6 +181,7 @@ static const char *dict_regexp_lookup(DICT *dict, const char *name)
     DICT_REGEXP_EXPAND_CONTEXT ctxt;
     static VSTRING *buf;
     int     error;
+    int     nesting = 0;
 
     dict_errno = 0;
 
@@ -179,6 +193,12 @@ static const char *dict_regexp_lookup(DICT *dict, const char *name)
      * for substring substitution to the bare minimum.
      */
     for (rule = dict_regexp->head; rule; rule = rule->next) {
+       if (nesting < rule->nesting)            /* inside false IF/ENDIF */
+           continue;
+       if (rule->op == REGEXP_OP_ENDIF) {
+           nesting--;
+           continue;
+       }
        error = regexec(rule->primary_exp, name, rule->max_nsub + 1,
                        rule->max_nsub ? dict_regexp->pmatch :
                        (regmatch_t *) 0, 0);
@@ -213,8 +233,16 @@ static const char *dict_regexp_lookup(DICT *dict, const char *name)
        }
 
        /*
-        * Match found. Skip $number substitutions when the replacement text
-        * contains no $number strings (as learned during the pre-scan).
+        * Match found.
+        */
+       if (rule->op == REGEXP_OP_IF) {
+           nesting++;
+           continue;
+       }
+
+       /*
+        * Skip $number substitutions when the replacement text contains no
+        * $number strings (as learned during the pre-scan).
         */
        if (rule->max_nsub == 0)
            return (rule->replacement);
@@ -364,10 +392,32 @@ static int dict_regexp_prescan(int type, VSTRING *buf, char *context)
     return (MAC_PARSE_OK);
 }
 
+/* dict_regexp_patterns - get the primary and negated patterns and flags */
+
+static int dict_regexp_patterns(const char *map, int lineno, char **p,
+                                       DICT_REGEXP_PATTERN *primary_pat,
+                                       DICT_REGEXP_PATTERN *negated_pat)
+{
+
+    /*
+     * Get the primary and optional negated patterns and their flags.
+     */
+    if (dict_regexp_get_pattern(map, lineno, p, primary_pat) == 0)
+       return (0);
+    if (*(*p) == '!' && (*p)[1] && !ISSPACE((*p)[1])) {
+       (*p)++;
+       if (dict_regexp_get_pattern(map, lineno, p, negated_pat) == 0)
+           return (0);
+    } else {
+       negated_pat->regexp = 0;
+    }
+    return (1);
+}
+
 /* dict_regexp_parseline - parse one rule */
 
 static DICT_REGEXP_RULE *dict_regexp_parseline(const char *map, int lineno,
-                                                      char *line)
+                                                   char *line, int nesting)
 {
     DICT_REGEXP_RULE *rule;
     char   *p;
@@ -376,79 +426,126 @@ static DICT_REGEXP_RULE *dict_regexp_parseline(const char *map, int lineno,
     DICT_REGEXP_PATTERN primary_pat;
     DICT_REGEXP_PATTERN negated_pat;
     DICT_REGEXP_PRESCAN_CONTEXT ctxt;
+    int     op = REGEXP_OP_MATCH;
 
     p = line;
 
     /*
-     * Get the primary and optional negated patterns and their flags.
+     * The MATCH operator takes both patterns and replacement text.
      */
-    if (dict_regexp_get_pattern(map, lineno, &p, &primary_pat) == 0)
-       return (0);
-    if (*p == '!' && p[1] && !ISSPACE(p[1])) {
-       p++;
-       if (dict_regexp_get_pattern(map, lineno, &p, &negated_pat) == 0)
+    if (!ISALNUM(*p)) {
+       op = REGEXP_OP_MATCH;
+       if (!dict_regexp_patterns(map, lineno, &p, &primary_pat, &negated_pat))
            return (0);
-    } else {
-       negated_pat.regexp = 0;
+
+       /*
+        * Get the replacement text.
+        */
+       if (!ISSPACE(*p)) {
+           msg_warn("regexp map %s, line %d: invalid expression: "
+                    "skipping this rule", map, lineno);
+           return (0);
+       }
+       while (*p && ISSPACE(*p))
+           ++p;
+       if (!*p) {
+           msg_warn("regexp map %s, line %d: using empty replacement string",
+                    map, lineno);
+       }
     }
 
     /*
-     * Get the replacement text.
+     * The IF operator takes patterns but no replacement text.
      */
-    if (!ISSPACE(*p)) {
-       msg_warn("regexp map %s, line %d: invalid expression: "
-                "skipping this rule", map, lineno);
-       return (0);
-    }
-    while (*p && ISSPACE(*p))
-       ++p;
-    if (!*p) {
-       msg_warn("regexp map %s, line %d: using empty replacement string",
-                map, lineno);
+    else if (strncasecmp(p, "IF", 2) == 0 && !ISALNUM(p[2])) {
+       op = REGEXP_OP_IF;
+       p += 2;
+       while (*p && ISSPACE(*p))
+           p++;
+       if (!dict_regexp_patterns(map, lineno, &p, &primary_pat, &negated_pat))
+           return (0);
+       if (*p)
+           msg_warn("%s, line %d: ignoring extra text after IF", map, lineno);
     }
 
     /*
-     * Find the highest-numbered $number substitution string. We can speed up
-     * processing 1) by passing hints to the regexp compiler, setting the
-     * REG_NOSUB flag when the replacement text contains no $number string;
-     * 2) by passing hints to the regexp execution code, limiting the amount
-     * of text that is made available for substitution.
+     * The ENDIF operator takes no patterns and no replacement text.
      */
-    ctxt.map = map;
-    ctxt.lineno = lineno;
-    ctxt.max_nsub = 0;
-    if (mac_parse(p, dict_regexp_prescan, (char *) &ctxt) & MAC_PARSE_ERROR) {
-       msg_warn("regexp map %s, line %d: bad replacement syntax: "
-                "skipping this rule", map, lineno);
-       return (0);
+    else if (strncasecmp(p, "ENDIF", 5) == 0 && !ISALNUM(p[5])) {
+       op = REGEXP_OP_ENDIF;
+       p += 5;
+       if (*p)
+           msg_warn("%s, line %d: ignoring extra text after ENDIF",
+                    map, lineno);
+       if (nesting == 0) {
+           msg_warn("%s, line %d: ignoring ENDIF without matching IF",
+                    map, lineno);
+           return (0);
+       }
+       primary_pat.regexp = negated_pat.regexp = 0;
     }
 
     /*
-     * Compile the primary and the optional negated pattern. Speed up
-     * execution when no matched text needs to be substituted into the result
-     * string, or when the highest numbered substring is less than the total
-     * number of () subpatterns.
+     * Unrecognized request.
      */
-    if (ctxt.max_nsub == 0)
-       primary_pat.options |= REG_NOSUB;
-    if ((primary_exp = dict_regexp_compile(map, lineno, &primary_pat)) == 0)
-       return (0);
-    if (ctxt.max_nsub > primary_exp->re_nsub) {
-       msg_warn("regexp map %s, line %d: out of range replacement index \"%d\": "
-                "skipping this rule", map, lineno, ctxt.max_nsub);
-       regfree(primary_exp);
-       myfree((char *) primary_exp);
+    else {
+       msg_warn("regexp map %s, line %d: ignoring unrecognized request",
+                map, lineno);
        return (0);
     }
-    if (negated_pat.regexp != 0) {
-       negated_pat.options |= REG_NOSUB;
-       if ((negated_exp = dict_regexp_compile(map, lineno, &negated_pat)) == 0) {
+
+    /*
+     * Do some compile-time optimizations to speed up pattern matches.
+     */
+    if (primary_pat.regexp) {
+       ctxt.map = map;
+       ctxt.lineno = lineno;
+       ctxt.max_nsub = 0;
+
+       /*
+        * Find the highest-numbered $number substitution string. We can
+        * speed up processing 1) by passing hints to the regexp compiler,
+        * setting the REG_NOSUB flag when the replacement text contains no
+        * $number string; 2) by passing hints to the regexp execution code,
+        * limiting the amount of text that is made available for
+        * substitution.
+        */
+       if (mac_parse(p, dict_regexp_prescan, (char *) &ctxt) & MAC_PARSE_ERROR) {
+           msg_warn("regexp map %s, line %d: bad replacement syntax: "
+                    "skipping this rule", map, lineno);
+           return (0);
+       }
+
+       /*
+        * Compile the primary and the optional negated pattern. Speed up
+        * execution when no matched text needs to be substituted into the
+        * result string, or when the highest numbered substring is less than
+        * the total number of () subpatterns.
+        */
+       if (ctxt.max_nsub == 0)
+           primary_pat.options |= REG_NOSUB;
+       if ((primary_exp = dict_regexp_compile(map, lineno, &primary_pat)) == 0)
+           return (0);
+       if (ctxt.max_nsub > primary_exp->re_nsub) {
+           msg_warn("regexp map %s, line %d: out of range replacement index \"%d\": "
+                    "skipping this rule", map, lineno, ctxt.max_nsub);
            regfree(primary_exp);
            myfree((char *) primary_exp);
            return (0);
        }
-    } else
-       negated_exp = 0;
+       if (negated_pat.regexp != 0) {
+           negated_pat.options |= REG_NOSUB;
+           if ((negated_exp = dict_regexp_compile(map, lineno, &negated_pat)) == 0) {
+               regfree(primary_exp);
+               myfree((char *) primary_exp);
+               return (0);
+           }
+       } else
+           negated_exp = 0;
+    } else {
+       primary_exp = negated_exp = 0;
+       ctxt.max_nsub = 0;
+    }
 
     /*
      * Package up the result.
@@ -459,6 +556,8 @@ static DICT_REGEXP_RULE *dict_regexp_parseline(const char *map, int lineno,
     rule->replacement = mystrdup(p);
     rule->max_nsub = ctxt.max_nsub;
     rule->lineno = lineno;
+    rule->op = op;
+    rule->nesting = nesting;
     rule->next = 0;
     return (rule);
 }
@@ -474,6 +573,7 @@ DICT   *dict_regexp_open(const char *map, int unused_flags, int dict_flags)
     DICT_REGEXP_RULE *last_rule = 0;
     int     lineno = 0;
     size_t  max_nsub = 0;
+    int     nesting = 0;
     char   *p;
 
     line_buffer = vstring_alloc(100);
@@ -495,11 +595,16 @@ DICT   *dict_regexp_open(const char *map, int unused_flags, int dict_flags)
     while (readlline(line_buffer, map_fp, &lineno)) {
        p = vstring_str(line_buffer);
        trimblanks(p, 0)[0] = 0;
-       rule = dict_regexp_parseline(map, lineno, p);
+       if (*p == 0)
+           continue;
+       rule = dict_regexp_parseline(map, lineno, p, nesting);
        if (rule) {
            if (rule->max_nsub > max_nsub)
                max_nsub = rule->max_nsub;
-
+           if (rule->op == REGEXP_OP_IF)
+               nesting++;
+           if (rule->op == REGEXP_OP_ENDIF)
+               nesting--;
            if (last_rule == 0)
                dict_regexp->head = rule;
            else
@@ -508,6 +613,9 @@ DICT   *dict_regexp_open(const char *map, int unused_flags, int dict_flags)
        }
     }
 
+    if (nesting)
+       msg_warn("%s, line %d: more IFs than ENDIFs", map, lineno);
+
     /*
      * Allocate space for only as many matched substrings as used in the
      * replacement text.
index 1b06a89aba40ff3ff2b2ccfdbaedf01956352e11..346e166b96f7528e76617a722e9aa9283ac786d8 100644 (file)
@@ -44,7 +44,7 @@
 
 /* dict_static_lookup - access static value*/
 
-static const char *dict_static_lookup(DICT *dict, const char *name)
+static const char *dict_static_lookup(DICT *dict, const char *unused_name)
 {
     dict_errno = 0;