diff --git a/postfix/.indent.pro b/postfix/.indent.pro
index d79ef9582..b7ea3324c 100644
--- a/postfix/.indent.pro
+++ b/postfix/.indent.pro
@@ -195,6 +195,7 @@
-TNAME_MASK
-TNBBIO
-TPC_DBMS_INFO
+-TPC_EVAL_CTX
-TPC_MASTER_ENT
-TPC_PARAM_NODE
-TPC_SERVICE_DEF
diff --git a/postfix/HISTORY b/postfix/HISTORY
index 18a553df8..2c8b8713e 100644
--- a/postfix/HISTORY
+++ b/postfix/HISTORY
@@ -18140,3 +18140,18 @@ Apologies for any names omitted.
This part of the code is not documented and had escaped
testing. Files: util/ip_match.c, util/ip_match.in,
util/ip_match.ref.
+
+20121215
+
+ Bugfix (introduced: 19980218, when recipient_delimiter
+ support was added): The error message for unknown local
+ users (or missing required aliases) should report the user
+ name instead of the full localpart which may contain an
+ address extension. Problem reported by Christian Holler.
+ File: local/unknown.c.
+
+20121221
+
+ Feature: "postconf -x" support to expand $nama in parameter
+ values. Files: postconf/postconf_main.c, postconf/postconf.h,
+ postconf/postconf_node.c, postconf/postconf.c.
diff --git a/postfix/html/postconf.1.html b/postfix/html/postconf.1.html
index d9f66d353..8b7afa1e4 100644
--- a/postfix/html/postconf.1.html
+++ b/postfix/html/postconf.1.html
@@ -12,7 +12,7 @@ POSTCONF(1) POSTCONF(1)
SYNOPSIS
Managing main.cf:
- postconf [-dfhnv] [-c config_dir] [-C class,...] [parame-
+ postconf [-dfhnvx] [-c config_dir] [-C class,...] [parame-
ter ...]
postconf [-ev] [-c config_dir] [parameter=value ...]
@@ -321,26 +321,29 @@ POSTCONF(1) POSTCONF(1)
tiple -v options make the software increasingly
verbose.
+ -x Expand $name in parameter values. The expansion is
+ recursive.
+
-X Edit the main.cf configuration file, and remove the
- parameters named on the postconf(1) command line.
+ parameters named on the postconf(1) command line.
The file is copied to a temporary file then renamed
into place. Specify a list of parameter names, not
- "name=value" pairs. There is no postconf(1) com-
+ "name=value" pairs. There is no postconf(1) com-
mand to perform the reverse operation.
- This feature is available with Postfix 2.10 and
+ This feature is available with Postfix 2.10 and
later.
- -# Edit the main.cf configuration file, and comment
+ -# Edit the main.cf configuration file, and comment
out the parameters named on the postconf(1) command
- line, so that those parameters revert to their
- default values. The file is copied to a temporary
- file then renamed into place. Specify a list of
- parameter names, not "name=value" pairs. There is
+ line, so that those parameters revert to their
+ default values. The file is copied to a temporary
+ file then renamed into place. Specify a list of
+ parameter names, not "name=value" pairs. There is
no postconf(1) command to perform the reverse oper-
ation.
- This feature is available with Postfix 2.6 and
+ This feature is available with Postfix 2.6 and
later.
DIAGNOSTICS
@@ -351,18 +354,18 @@ POSTCONF(1) POSTCONF(1)
Directory with Postfix configuration files.
CONFIGURATION PARAMETERS
- The following main.cf parameters are especially relevant
+ The following main.cf parameters are especially relevant
to this program.
- The text below provides only a parameter summary. See
+ The text below provides only a parameter summary. See
postconf(5) for more details including examples.
config_directory (see 'postconf -d' output)
- The default location of the Postfix main.cf and
+ The default location of the Postfix main.cf and
master.cf configuration files.
bounce_template_file (empty)
- Pathname of a configuration file with bounce mes-
+ Pathname of a configuration file with bounce mes-
sage templates.
FILES
@@ -378,7 +381,7 @@ POSTCONF(1) POSTCONF(1)
DATABASE_README, Postfix lookup table overview
LICENSE
- The Secure Mailer license must be distributed with this
+ The Secure Mailer license must be distributed with this
software.
AUTHOR(S)
diff --git a/postfix/man/man1/postconf.1 b/postfix/man/man1/postconf.1
index ce153a374..4fca7a677 100644
--- a/postfix/man/man1/postconf.1
+++ b/postfix/man/man1/postconf.1
@@ -11,7 +11,7 @@ Postfix configuration utility
.fi
\fBManaging main.cf:\fR
-\fBpostconf\fR [\fB-dfhnv\fR] [\fB-c \fIconfig_dir\fR]
+\fBpostconf\fR [\fB-dfhnvx\fR] [\fB-c \fIconfig_dir\fR]
[\fB-C \fIclass,...\fR] [\fIparameter ...\fR]
\fBpostconf\fR [\fB-ev\fR] [\fB-c \fIconfig_dir\fR]
@@ -281,6 +281,9 @@ This feature is available with Postfix 2.3 and later.
.IP \fB-v\fR
Enable verbose logging for debugging purposes. Multiple \fB-v\fR
options make the software increasingly verbose.
+.IP \fB-x\fR
+Expand \fI$name\fR in parameter values. The expansion is
+recursive.
.IP \fB-X\fR
Edit the \fBmain.cf\fR configuration file, and remove
the parameters named on the \fBpostconf\fR(1) command line.
diff --git a/postfix/src/global/mail_version.h b/postfix/src/global/mail_version.h
index b747bb7ab..55f0b5d65 100644
--- a/postfix/src/global/mail_version.h
+++ b/postfix/src/global/mail_version.h
@@ -20,7 +20,7 @@
* Patches change both the patchlevel and the release date. Snapshots have no
* patchlevel; they change the release date only.
*/
-#define MAIL_RELEASE_DATE "20121210"
+#define MAIL_RELEASE_DATE "20121221"
#define MAIL_VERSION_NUMBER "2.10"
#ifdef SNAPSHOT
diff --git a/postfix/src/local/unknown.c b/postfix/src/local/unknown.c
index 9c3d185f8..37167458c 100644
--- a/postfix/src/local/unknown.c
+++ b/postfix/src/local/unknown.c
@@ -150,9 +150,9 @@ int deliver_unknown(LOCAL_STATE state, USER_ATTR usr_attr)
*/
#define STREQ(x,y) (strcasecmp(x,y) == 0)
- if (STREQ(state.msg_attr.local, MAIL_ADDR_MAIL_DAEMON)
- || STREQ(state.msg_attr.local, MAIL_ADDR_POSTMASTER)) {
- msg_warn("required alias not found: %s", state.msg_attr.local);
+ if (STREQ(state.msg_attr.user, MAIL_ADDR_MAIL_DAEMON)
+ || STREQ(state.msg_attr.user, MAIL_ADDR_POSTMASTER)) {
+ msg_warn("required alias not found: %s", state.msg_attr.user);
dsb_simple(state.msg_attr.why, "2.0.0", "discarded");
return (sent(BOUNCE_FLAGS(state.request), SENT_ATTR(state.msg_attr)));
}
@@ -161,7 +161,7 @@ int deliver_unknown(LOCAL_STATE state, USER_ATTR usr_attr)
* Bounce the message when no luser relay is specified.
*/
dsb_simple(state.msg_attr.why, "5.1.1",
- "unknown user: \"%s\"", state.msg_attr.local);
+ "unknown user: \"%s\"", state.msg_attr.user);
return (bounce_append(BOUNCE_FLAGS(state.request),
BOUNCE_ATTR(state.msg_attr)));
}
diff --git a/postfix/src/postconf/Makefile.in b/postfix/src/postconf/Makefile.in
index 86d44b3c3..18474fd5d 100644
--- a/postfix/src/postconf/Makefile.in
+++ b/postfix/src/postconf/Makefile.in
@@ -42,7 +42,8 @@ test: $(TESTPROG)
tests: test1 test2 test3 test4 test5 test6 test7 test8 test9 test10 test11 \
test12 test13 test14 test15 test16 test17 test18 test19 test20 test21 \
- test22 test23 test24 test25 test26 test27 test28 test29 test30 test4b
+ test22 test23 test24 test25 test26 test27 test28 test29 test30 test4b \
+ test31 test32 test33
root_tests:
@@ -429,6 +430,38 @@ test30: $(PROG) test30.ref
diff test30.ref test30.tmp
rm -f main.cf master.cf test30.tmp
+# Does a non-default setting propagate to a non-default value?
+
+test31: $(PROG) test31.ref
+ rm -f main.cf master.cf
+ touch main.cf master.cf
+ echo 'smtpd_helo_restrictions=whatever' >> main.cf
+ echo 'smtpd_sender_restrictions=$$smtpd_helo_restrictions' >> main.cf
+ ./$(PROG) -nxc . >test31.tmp 2>&1
+ diff test31.ref test31.tmp
+ rm -f main.cf master.cf test31.tmp
+
+# Does a non-default setting propagate to a default value?
+
+test32: $(PROG) test32.ref
+ rm -f main.cf master.cf
+ touch main.cf master.cf
+ echo 'relay_domains=whatever' >> main.cf
+ ./$(PROG) -xc . fast_flush_domains >test32.tmp 2>&1
+ diff test32.ref test32.tmp
+ rm -f main.cf master.cf test32.tmp
+
+# Does a default setting propagate to a non-default value?
+
+test33: $(PROG) test33.ref
+ rm -f main.cf master.cf
+ touch main.cf master.cf
+ echo 'mydestination=whatever' >> main.cf
+ echo 'always_bcc=$$relay_domains' >> main.cf
+ ./$(PROG) -xc . always_bcc >test33.tmp 2>&1
+ diff test33.ref test33.tmp
+ rm -f main.cf master.cf test33.tmp
+
printfck: $(OBJS) $(PROG)
rm -rf printfck
mkdir printfck
@@ -560,6 +593,8 @@ postconf_edit.o: postconf_edit.c
postconf_main.o: ../../include/argv.h
postconf_main.o: ../../include/dict.h
postconf_main.o: ../../include/htable.h
+postconf_main.o: ../../include/mac_expand.h
+postconf_main.o: ../../include/mac_parse.h
postconf_main.o: ../../include/mail_conf.h
postconf_main.o: ../../include/mail_params.h
postconf_main.o: ../../include/msg.h
diff --git a/postfix/src/postconf/postconf.c b/postfix/src/postconf/postconf.c
index cfe9ca675..401e50430 100644
--- a/postfix/src/postconf/postconf.c
+++ b/postfix/src/postconf/postconf.c
@@ -7,7 +7,7 @@
/* .fi
/* \fBManaging main.cf:\fR
/*
-/* \fBpostconf\fR [\fB-dfhnv\fR] [\fB-c \fIconfig_dir\fR]
+/* \fBpostconf\fR [\fB-dfhnvx\fR] [\fB-c \fIconfig_dir\fR]
/* [\fB-C \fIclass,...\fR] [\fIparameter ...\fR]
/*
/* \fBpostconf\fR [\fB-ev\fR] [\fB-c \fIconfig_dir\fR]
@@ -275,6 +275,9 @@
/* .IP \fB-v\fR
/* Enable verbose logging for debugging purposes. Multiple \fB-v\fR
/* options make the software increasingly verbose.
+/* .IP \fB-x\fR
+/* Expand \fI$name\fR in parameter values. The expansion is
+/* recursive.
/* .IP \fB-X\fR
/* Edit the \fBmain.cf\fR configuration file, and remove
/* the parameters named on the \fBpostconf\fR(1) command line.
@@ -430,7 +433,7 @@ int main(int argc, char **argv)
/*
* Parse JCL.
*/
- while ((ch = GETOPT(argc, argv, "aAbc:C:deEf#hlmMntvX")) > 0) {
+ while ((ch = GETOPT(argc, argv, "aAbc:C:deEf#hlmMntvxX")) > 0) {
switch (ch) {
case 'a':
cmd_mode |= SHOW_SASL_SERV;
@@ -462,17 +465,6 @@ int main(int argc, char **argv)
cmd_mode |= FOLD_LINE;
break;
- /*
- * People, this does not work unless you properly handle default
- * settings. For example, fast_flush_domains = $relay_domains
- * must not evaluate to the empty string when relay_domains is
- * left at its default setting of $mydestination.
- */
-#if 0
- case 'E':
- cmd_mode |= SHOW_EVAL;
- break;
-#endif
case '#':
cmd_mode = COMMENT_OUT;
break;
@@ -498,6 +490,9 @@ int main(int argc, char **argv)
ext_argv = argv_alloc(2);
argv_add(ext_argv, "bounce", "-SVndump_templates", (char *) 0);
break;
+ case 'x':
+ cmd_mode |= SHOW_EVAL;
+ break;
case 'X':
/* This is irreversible, therefore require two-finger action. */
cmd_mode = EDIT_EXCL;
@@ -521,6 +516,8 @@ int main(int argc, char **argv)
&& junk != EDIT_EXCL)
|| ext_argv != 0))
msg_fatal("specify one of -a, -A, -b, -d, -e, -#, -l, -m, -M, -n, and -X");
+ if ((cmd_mode & SHOW_EVAL) != 0 && junk != 0 && junk != SHOW_DEFS && junk != SHOW_NONDEF)
+ msg_fatal("do not specify -x with -a, -A, -b, -e, -#, -l, -m, -M, or -X");
/*
* Display bounce template information and exit.
@@ -591,7 +588,6 @@ int main(int argc, char **argv)
else {
if ((cmd_mode & SHOW_DEFS) == 0) {
read_parameters();
- set_parameters();
}
register_builtin_parameters();
diff --git a/postfix/src/postconf/postconf.h b/postfix/src/postconf/postconf.h
index f197d1223..86e37d033 100644
--- a/postfix/src/postconf/postconf.h
+++ b/postfix/src/postconf/postconf.h
@@ -43,6 +43,7 @@ typedef struct {
int flags; /* see below */
char *param_data; /* mostly, the default value */
const char *(*convert_fn) (char *); /* value to string */
+ const char *cached_defval; /* cached default value */
} PC_PARAM_NODE;
/* Values for flags. See the postconf_node module for narrative text. */
diff --git a/postfix/src/postconf/postconf_main.c b/postfix/src/postconf/postconf_main.c
index ad96c9afb..d2233dae1 100644
--- a/postfix/src/postconf/postconf_main.c
+++ b/postfix/src/postconf/postconf_main.c
@@ -8,8 +8,6 @@
/*
/* void read_parameters()
/*
-/* void set_parameters()
-/*
/* void show_parameters(mode, param_class, names)
/* int mode;
/* int param_class;
@@ -17,11 +15,6 @@
/* DESCRIPTION
/* read_parameters() reads parameters from main.cf.
/*
-/* set_parameters() does nothing. It is a place holder for
-/* code that assigns actual or default parameter values, which
-/* could be needed to implement "postconf -e" parameter value
-/* expansion.
-/*
/* show_parameters() writes main.cf parameters to the standard
/* output stream.
/*
@@ -38,7 +31,7 @@
/* .IP SHOW_NAME
/* Output the parameter as "name = value".
/* .IP SHOW_EVAL
-/* Expand parameter values (not implemented).
+/* Expand $name in parameter values.
/* .RE
/* .IP param_class
/* Bit-wise OR of one or more of the following:
@@ -83,6 +76,7 @@
#include
#include
#include
+#include
/* Global library. */
@@ -112,35 +106,6 @@ void read_parameters(void)
myfree(path);
}
-/* set_parameters - set parameter values from default or explicit setting */
-
-void set_parameters(void)
-{
-
- /*
- * The proposal below describes some of the steps needed to expand
- * parameter values. It has a problem: it updates the configuration
- * parameter dictionary, and in doing so breaks the "postconf -d"
- * implementation. This makes "-d" and "-e" mutually exclusive.
- *
- * Populate the configuration parameter dictionary with default settings or
- * with actual settings.
- *
- * Iterate over each entry in str_fn_table, str_fn_table_2, time_table,
- * bool_table, int_table, str_table, and raw_table. Look up each
- * parameter name in the configuration parameter dictionary. If the
- * parameter is not set, take the default value, or take the value from
- * main.cf, without doing $name expansions. This includes converting
- * default values from numeric/boolean internal forms to external string
- * form.
- *
- * Once the configuration parameter dictionary is populated, printing a
- * parameter setting is a matter of querying the configuration parameter
- * dictionary, optionally expanding of $name values, and printing the
- * result.
- */
-}
-
/* print_line - show line possibly folded, and with normalized whitespace */
static void print_line(int mode, const char *fmt,...)
@@ -194,6 +159,100 @@ static void print_line(int mode, const char *fmt,...)
vstream_fputs("\n", VSTREAM_OUT);
}
+/* lookup_parameter_value - look up specific parameter value */
+
+static const char *lookup_parameter_value(int mode, const char *name,
+ PC_PARAM_NODE *node)
+{
+ const char *value;
+
+ /*
+ * Use the actual or built-in default parameter value. Some default
+ * values are computed by functions that have side effects, and those
+ * functions should be invoked only once. Therefore, when expanding $name
+ * in parameter values, we cache the default values.
+ */
+ if ((mode & SHOW_DEFS) != 0
+ || ((value = dict_lookup(CONFIG_DICT, name)) == 0
+ && (mode & SHOW_NONDEF) == 0)) {
+ if ((value = node->cached_defval) == 0
+ && (value = convert_param_node(SHOW_DEFS, name, node)) != 0
+ && (mode & SHOW_EVAL) != 0)
+ node->cached_defval = value = mystrdup(value);
+ }
+ return (value);
+}
+
+ /*
+ * Data structure to pass private state while recursively expanding $name in
+ * parameter values.
+ */
+typedef struct {
+ int mode;
+} PC_EVAL_CTX;
+
+/* expand_parameter_value_helper - macro parser call-back routine */
+
+static const char *expand_parameter_value_helper(const char *key,
+ int unused_type,
+ char *context)
+{
+ PC_PARAM_NODE *node;
+ PC_EVAL_CTX *cp = (PC_EVAL_CTX *) context;
+
+ /*
+ * XXX Do not spam the user with warnings about legacy parameter names in
+ * backwards-compatible default settings.
+ */
+ if ((node = PC_PARAM_TABLE_FIND(param_table, key)) != 0) {
+ return (lookup_parameter_value(cp->mode, key, node));
+ } else {
+ /* msg_warn("%s: unknown parameter", key); */
+ return (0);
+ }
+}
+
+/* expand_parameter_value - expand $name in parameter value */
+
+static const char *expand_parameter_value(int mode, const char *value,
+ PC_PARAM_NODE *node)
+{
+ const char *myname = "expand_parameter_value";
+ static VSTRING *buf;
+ int status;
+ PC_EVAL_CTX eval_ctx;
+
+ /*
+ * Initialize.
+ */
+ if (buf == 0)
+ buf = vstring_alloc(10);
+
+ /*
+ * Expand macros recursively.
+ *
+ * When expanding $name in "postconf -n" parameter values, don't limit the
+ * search to only non-default parameter values.
+ *
+ * When expanding $name in "postconf -d" parameter values, do limit the
+ * search to only default parameter values.
+ */
+#define DONT_FILTER (char *) 0
+
+ eval_ctx.mode = mode & ~SHOW_NONDEF;
+ status = mac_expand(buf, value, MAC_EXP_FLAG_RECURSE, DONT_FILTER,
+ expand_parameter_value_helper, (char *) &eval_ctx);
+ if (status & MAC_PARSE_ERROR)
+ msg_fatal("macro processing error");
+ if (msg_verbose > 1) {
+ if (strcmp(value, STR(buf)) != 0)
+ msg_info("%s: expand %s -> %s", myname, value, STR(buf));
+ else
+ msg_info("%s: const %s", myname, value);
+ }
+ return (STR(buf));
+}
+
/* print_parameter - show specific parameter */
static void print_parameter(int mode, const char *name,
@@ -204,15 +263,15 @@ static void print_parameter(int mode, const char *name,
/*
* Use the default or actual value.
*/
- if ((mode & SHOW_DEFS) != 0
- || ((value = dict_lookup(CONFIG_DICT, name)) == 0
- && (mode & SHOW_NONDEF) == 0))
- value = convert_param_node(SHOW_DEFS, name, node);
+ value = lookup_parameter_value(mode, name, node);
/*
- * Print with or without the name= prefix.
+ * Optionally expand $name in the parameter value. Print the result with
+ * or without the name= prefix.
*/
if (value != 0) {
+ if ((mode & SHOW_EVAL) != 0 && PC_RAW_PARAMETER(node) == 0)
+ value = expand_parameter_value(mode, value, node);
if (mode & SHOW_NAME) {
print_line(mode, "%s = %s\n", name, value);
} else {
diff --git a/postfix/src/postconf/postconf_node.c b/postfix/src/postconf/postconf_node.c
index 05fb23370..1047cfc07 100644
--- a/postfix/src/postconf/postconf_node.c
+++ b/postfix/src/postconf/postconf_node.c
@@ -150,10 +150,11 @@ PC_PARAM_NODE *make_param_node(int flags, char *param_data,
node->flags = flags;
node->param_data = param_data;
node->convert_fn = convert_fn;
+ node->cached_defval = 0;
return (node);
}
-/* convert_param_node - get actual or default parameter value */
+/* convert_param_node - get default parameter value */
const char *convert_param_node(int mode, const char *name, PC_PARAM_NODE *node)
{
diff --git a/postfix/src/postconf/test31.ref b/postfix/src/postconf/test31.ref
new file mode 100644
index 000000000..6fda09cca
--- /dev/null
+++ b/postfix/src/postconf/test31.ref
@@ -0,0 +1,3 @@
+config_directory = .
+smtpd_helo_restrictions = whatever
+smtpd_sender_restrictions = whatever
diff --git a/postfix/src/postconf/test32.ref b/postfix/src/postconf/test32.ref
new file mode 100644
index 000000000..43e2b7ba8
--- /dev/null
+++ b/postfix/src/postconf/test32.ref
@@ -0,0 +1 @@
+fast_flush_domains = whatever
diff --git a/postfix/src/postconf/test33.ref b/postfix/src/postconf/test33.ref
new file mode 100644
index 000000000..7b3f52dbe
--- /dev/null
+++ b/postfix/src/postconf/test33.ref
@@ -0,0 +1 @@
+always_bcc = whatever
diff --git a/postfix/src/util/ip_match.in b/postfix/src/util/ip_match.in
index 072657bd9..eec13e3b1 100644
--- a/postfix/src/util/ip_match.in
+++ b/postfix/src/util/ip_match.in
@@ -22,3 +22,5 @@ a
1.2.[3;5;7;9;11].5 1.2.3.5 1.2.2.5 1.2.4.5 1.2.11.5 1.2.12.5 1.2.11.6
[1;2].3.4.5 1.3.4.5 2.3.4.5 3.3.4.5
[[1;2].3.4.5] 1.3.4.5 2.3.4.5 3.3.4.5
+[[1;2].3.4.5
+1;2].3.4.5
diff --git a/postfix/src/util/ip_match.ref b/postfix/src/util/ip_match.ref
index da06ca959..04b291f0e 100644
--- a/postfix/src/util/ip_match.ref
+++ b/postfix/src/util/ip_match.ref
@@ -63,3 +63,7 @@ Code: [1;2].3.4.5
Match 1.3.4.5: yes
Match 2.3.4.5: yes
Match 3.3.4.5: no
+> [[1;2].3.4.5
+Error: missing "]" character
+> 1;2].3.4.5
+Error: need "." at "1>;<2].3.4.5"