2
0
mirror of https://github.com/vdukhovni/postfix synced 2025-08-30 21:55:20 +00:00

postfix-1.1.11-20020910

This commit is contained in:
Wietse Venema
2002-09-10 00:00:00 -05:00
committed by Viktor Dukhovni
parent 7a8151a014
commit e01fc53a21
10 changed files with 214 additions and 79 deletions

View 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

View 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.

View 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
==========================================================

View 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

View 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 */

View 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);
}

View 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 */

View 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

View 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. */
@@ -57,6 +61,13 @@
#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);
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);
}
while (*p && ISSPACE(*p))
++p;
if (!*p) {
msg_warn("regexp map %s, line %d: using empty replacement string",
/*
* The ENDIF operator takes no patterns and no replacement text.
*/
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;
}
/*
* Unrecognized request.
*/
else {
msg_warn("regexp map %s, line %d: ignoring unrecognized request",
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.
*/
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);
}
/*
* 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.
* Do some compile-time optimizations to speed up pattern matches.
*/
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);
}
if (negated_pat.regexp != 0) {
negated_pat.options |= REG_NOSUB;
if ((negated_exp = dict_regexp_compile(map, lineno, &negated_pat)) == 0) {
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.

View 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;