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"