mirror of
https://github.com/vdukhovni/postfix
synced 2025-09-01 14:45:32 +00:00
postfix-1.1.11-20020910
This commit is contained in:
committed by
Viktor Dukhovni
parent
7a8151a014
commit
e01fc53a21
@@ -6926,6 +6926,25 @@ Apologies for any names omitted.
|
|||||||
Bugfix: the LDAP client dumped core in verbose mode.
|
Bugfix: the LDAP client dumped core in verbose mode.
|
||||||
Reported by Will Day and others. File: util/dict_ldap.c.
|
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:
|
Open problems:
|
||||||
|
|
||||||
Low: smtpd should log queue ID with reject/warn/hold/discard
|
Low: smtpd should log queue ID with reject/warn/hold/discard
|
||||||
|
@@ -138,7 +138,7 @@ virtual_mailbox_lock
|
|||||||
Use the "postconf -m" command to find out what locking methods
|
Use the "postconf -m" command to find out what locking methods
|
||||||
Postfix supports on your system.
|
Postfix supports on your system.
|
||||||
|
|
||||||
virtual_mailbox_size
|
virtual_mailbox_limit
|
||||||
|
|
||||||
An upper limit on the size of a mailbox file or maildir file.
|
An upper limit on the size of a mailbox file or maildir file.
|
||||||
|
|
||||||
|
@@ -12,6 +12,12 @@ snapshot release). Patches change the patchlevel and the release
|
|||||||
date. Snapshots change only the release date, unless they include
|
date. Snapshots change only the release date, unless they include
|
||||||
the same bugfixes as a patch release.
|
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
|
Incompatible changes with Postfix snapshot 1.1.11-20020906
|
||||||
==========================================================
|
==========================================================
|
||||||
|
|
||||||
|
@@ -20,7 +20,7 @@
|
|||||||
* Patches change the patchlevel and the release date. Snapshots change the
|
* Patches change the patchlevel and the release date. Snapshots change the
|
||||||
* release date only, unless they include the same bugfix as a patch release.
|
* 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 VAR_MAIL_VERSION "mail_version"
|
||||||
#define DEF_MAIL_VERSION "1.1.11-" MAIL_RELEASE_DATE
|
#define DEF_MAIL_VERSION "1.1.11-" MAIL_RELEASE_DATE
|
||||||
|
@@ -149,14 +149,6 @@ void smtp_chat_cmd(SMTP_STATE *state, char *fmt,...)
|
|||||||
* Send the command to the SMTP server.
|
* Send the command to the SMTP server.
|
||||||
*/
|
*/
|
||||||
smtp_fputs(STR(state->buffer), LEN(state->buffer), session->stream);
|
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 */
|
/* smtp_chat_resp - read and process SMTP server response */
|
||||||
|
@@ -391,9 +391,9 @@ SMTP_SESSION *smtp_connect(char *destination, VSTRING *why)
|
|||||||
char *host;
|
char *host;
|
||||||
unsigned port;
|
unsigned port;
|
||||||
char *def_service = "smtp"; /* XXX configurable? */
|
char *def_service = "smtp"; /* XXX configurable? */
|
||||||
char *save;
|
ARGV *sites;
|
||||||
char *dest;
|
char *dest;
|
||||||
char *cp;
|
char **cpp;
|
||||||
int found_myself = 0;
|
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
|
* to the optional fall-back relays. Each can be a list of destinations
|
||||||
* by itself, with domain, host, [], numerical address, and port.
|
* 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.
|
* 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);
|
VAR_RELAYHOST, var_relayhost);
|
||||||
smtp_errno = SMTP_RETRY;
|
smtp_errno = SMTP_RETRY;
|
||||||
}
|
}
|
||||||
if (*var_fallback_relay) {
|
if (cpp > sites->argv && sites->argc > 1) {
|
||||||
msg_warn("%s configuration problem: %s",
|
msg_warn("%s problem: %s",
|
||||||
VAR_FALLBACK_RELAY, var_fallback_relay);
|
VAR_FALLBACK_RELAY, var_fallback_relay);
|
||||||
smtp_errno = SMTP_RETRY;
|
smtp_errno = SMTP_RETRY;
|
||||||
}
|
}
|
||||||
@@ -458,6 +460,6 @@ SMTP_SESSION *smtp_connect(char *destination, VSTRING *why)
|
|||||||
/*
|
/*
|
||||||
* Cleanup.
|
* Cleanup.
|
||||||
*/
|
*/
|
||||||
myfree(save);
|
argv_free(sites);
|
||||||
return (session);
|
return (session);
|
||||||
}
|
}
|
||||||
|
@@ -139,6 +139,7 @@ void smtpd_chat_query(SMTPD_STATE *state)
|
|||||||
void smtpd_chat_reply(SMTPD_STATE *state, char *format,...)
|
void smtpd_chat_reply(SMTPD_STATE *state, char *format,...)
|
||||||
{
|
{
|
||||||
va_list ap;
|
va_list ap;
|
||||||
|
int delay = 0;
|
||||||
|
|
||||||
va_start(ap, format);
|
va_start(ap, format);
|
||||||
vstring_vsprintf(state->buffer, format, ap);
|
vstring_vsprintf(state->buffer, format, ap);
|
||||||
@@ -157,9 +158,10 @@ void smtpd_chat_reply(SMTPD_STATE *state, char *format,...)
|
|||||||
* errors within a session.
|
* errors within a session.
|
||||||
*/
|
*/
|
||||||
if (state->error_count > var_smtpd_soft_erlim)
|
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')
|
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);
|
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
|
* timeouts with pipelined SMTP sessions that have lots of server-side
|
||||||
* delays (tarpit delays or DNS lookups for UCE restrictions).
|
* 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);
|
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 */
|
/* print_line - line_wrap callback */
|
||||||
|
@@ -308,7 +308,7 @@ static int dict_ldap_connect(DICT_LDAP *dict_ldap)
|
|||||||
&dict_ldap->version) != LDAP_OPT_SUCCESS)
|
&dict_ldap->version) != LDAP_OPT_SUCCESS)
|
||||||
msg_warn("%s: Unable to get LDAP protocol version", myname);
|
msg_warn("%s: Unable to get LDAP protocol version", myname);
|
||||||
else
|
else
|
||||||
msg_warn("%s: Actual Protocol version used was %d.",
|
msg_warn("%s: Actual Protocol version used is %d.",
|
||||||
myname, dict_ldap->version);
|
myname, dict_ldap->version);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@@ -16,6 +16,7 @@
|
|||||||
/* against the table.
|
/* against the table.
|
||||||
/* SEE ALSO
|
/* SEE ALSO
|
||||||
/* dict(3) generic dictionary manager
|
/* dict(3) generic dictionary manager
|
||||||
|
/* regexp_table(5) format of Postfix regular expression tables
|
||||||
/* AUTHOR(S)
|
/* AUTHOR(S)
|
||||||
/* LaMont Jones
|
/* LaMont Jones
|
||||||
/* lamont@hp.com
|
/* lamont@hp.com
|
||||||
@@ -43,6 +44,9 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <regex.h>
|
#include <regex.h>
|
||||||
|
#ifdef STRCASECMP_IN_STRINGS_H
|
||||||
|
#include <strings.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Utility library. */
|
/* Utility library. */
|
||||||
|
|
||||||
@@ -57,6 +61,13 @@
|
|||||||
#include "dict_regexp.h"
|
#include "dict_regexp.h"
|
||||||
#include "mac_parse.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.
|
* Regular expression before compiling.
|
||||||
*/
|
*/
|
||||||
@@ -75,6 +86,8 @@ typedef struct dict_regexp_list {
|
|||||||
char *replacement; /* replacement text */
|
char *replacement; /* replacement text */
|
||||||
size_t max_nsub; /* largest replacement $number */
|
size_t max_nsub; /* largest replacement $number */
|
||||||
int lineno; /* source file line 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;
|
} DICT_REGEXP_RULE;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -168,6 +181,7 @@ static const char *dict_regexp_lookup(DICT *dict, const char *name)
|
|||||||
DICT_REGEXP_EXPAND_CONTEXT ctxt;
|
DICT_REGEXP_EXPAND_CONTEXT ctxt;
|
||||||
static VSTRING *buf;
|
static VSTRING *buf;
|
||||||
int error;
|
int error;
|
||||||
|
int nesting = 0;
|
||||||
|
|
||||||
dict_errno = 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 substring substitution to the bare minimum.
|
||||||
*/
|
*/
|
||||||
for (rule = dict_regexp->head; rule; rule = rule->next) {
|
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,
|
error = regexec(rule->primary_exp, name, rule->max_nsub + 1,
|
||||||
rule->max_nsub ? dict_regexp->pmatch :
|
rule->max_nsub ? dict_regexp->pmatch :
|
||||||
(regmatch_t *) 0, 0);
|
(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
|
* Match found.
|
||||||
* contains no $number strings (as learned during the pre-scan).
|
*/
|
||||||
|
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)
|
if (rule->max_nsub == 0)
|
||||||
return (rule->replacement);
|
return (rule->replacement);
|
||||||
@@ -364,10 +392,32 @@ static int dict_regexp_prescan(int type, VSTRING *buf, char *context)
|
|||||||
return (MAC_PARSE_OK);
|
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 */
|
/* dict_regexp_parseline - parse one rule */
|
||||||
|
|
||||||
static DICT_REGEXP_RULE *dict_regexp_parseline(const char *map, int lineno,
|
static DICT_REGEXP_RULE *dict_regexp_parseline(const char *map, int lineno,
|
||||||
char *line)
|
char *line, int nesting)
|
||||||
{
|
{
|
||||||
DICT_REGEXP_RULE *rule;
|
DICT_REGEXP_RULE *rule;
|
||||||
char *p;
|
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 primary_pat;
|
||||||
DICT_REGEXP_PATTERN negated_pat;
|
DICT_REGEXP_PATTERN negated_pat;
|
||||||
DICT_REGEXP_PRESCAN_CONTEXT ctxt;
|
DICT_REGEXP_PRESCAN_CONTEXT ctxt;
|
||||||
|
int op = REGEXP_OP_MATCH;
|
||||||
|
|
||||||
p = line;
|
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)
|
if (!ISALNUM(*p)) {
|
||||||
return (0);
|
op = REGEXP_OP_MATCH;
|
||||||
if (*p == '!' && p[1] && !ISSPACE(p[1])) {
|
if (!dict_regexp_patterns(map, lineno, &p, &primary_pat, &negated_pat))
|
||||||
p++;
|
|
||||||
if (dict_regexp_get_pattern(map, lineno, &p, &negated_pat) == 0)
|
|
||||||
return (0);
|
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)) {
|
else if (strncasecmp(p, "IF", 2) == 0 && !ISALNUM(p[2])) {
|
||||||
msg_warn("regexp map %s, line %d: invalid expression: "
|
op = REGEXP_OP_IF;
|
||||||
"skipping this rule", map, lineno);
|
p += 2;
|
||||||
return (0);
|
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) {
|
* The ENDIF operator takes no patterns and no replacement text.
|
||||||
msg_warn("regexp map %s, line %d: using empty replacement string",
|
*/
|
||||||
|
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);
|
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);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Compile the primary and the optional negated pattern. Speed up
|
* Do some compile-time optimizations to speed up pattern matches.
|
||||||
* 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)
|
if (primary_pat.regexp) {
|
||||||
primary_pat.options |= REG_NOSUB;
|
ctxt.map = map;
|
||||||
if ((primary_exp = dict_regexp_compile(map, lineno, &primary_pat)) == 0)
|
ctxt.lineno = lineno;
|
||||||
return (0);
|
ctxt.max_nsub = 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);
|
* Find the highest-numbered $number substitution string. We can
|
||||||
regfree(primary_exp);
|
* speed up processing 1) by passing hints to the regexp compiler,
|
||||||
myfree((char *) primary_exp);
|
* setting the REG_NOSUB flag when the replacement text contains no
|
||||||
return (0);
|
* $number string; 2) by passing hints to the regexp execution code,
|
||||||
}
|
* limiting the amount of text that is made available for
|
||||||
if (negated_pat.regexp != 0) {
|
* substitution.
|
||||||
negated_pat.options |= REG_NOSUB;
|
*/
|
||||||
if ((negated_exp = dict_regexp_compile(map, lineno, &negated_pat)) == 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.
|
||||||
|
*/
|
||||||
|
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);
|
regfree(primary_exp);
|
||||||
myfree((char *) primary_exp);
|
myfree((char *) primary_exp);
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
} else
|
if (negated_pat.regexp != 0) {
|
||||||
negated_exp = 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.
|
* 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->replacement = mystrdup(p);
|
||||||
rule->max_nsub = ctxt.max_nsub;
|
rule->max_nsub = ctxt.max_nsub;
|
||||||
rule->lineno = lineno;
|
rule->lineno = lineno;
|
||||||
|
rule->op = op;
|
||||||
|
rule->nesting = nesting;
|
||||||
rule->next = 0;
|
rule->next = 0;
|
||||||
return (rule);
|
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;
|
DICT_REGEXP_RULE *last_rule = 0;
|
||||||
int lineno = 0;
|
int lineno = 0;
|
||||||
size_t max_nsub = 0;
|
size_t max_nsub = 0;
|
||||||
|
int nesting = 0;
|
||||||
char *p;
|
char *p;
|
||||||
|
|
||||||
line_buffer = vstring_alloc(100);
|
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)) {
|
while (readlline(line_buffer, map_fp, &lineno)) {
|
||||||
p = vstring_str(line_buffer);
|
p = vstring_str(line_buffer);
|
||||||
trimblanks(p, 0)[0] = 0;
|
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) {
|
||||||
if (rule->max_nsub > max_nsub)
|
if (rule->max_nsub > max_nsub)
|
||||||
max_nsub = rule->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)
|
if (last_rule == 0)
|
||||||
dict_regexp->head = rule;
|
dict_regexp->head = rule;
|
||||||
else
|
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
|
* Allocate space for only as many matched substrings as used in the
|
||||||
* replacement text.
|
* replacement text.
|
||||||
|
@@ -44,7 +44,7 @@
|
|||||||
|
|
||||||
/* dict_static_lookup - access static value*/
|
/* 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;
|
dict_errno = 0;
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user