From 38b0a080dce53184d3fd2663a52b0f5de201abf9 Mon Sep 17 00:00:00 2001 From: Wietse Venema Date: Sun, 20 Nov 2011 00:00:00 -0500 Subject: [PATCH] postfix-2.9-20111120 --- postfix/.indent.pro | 1 + postfix/HISTORY | 10 + postfix/RELEASE_NOTES | 8 + postfix/html/postconf.1.html | 24 +- postfix/man/man1/postconf.1 | 15 +- postfix/src/global/mail_version.h | 2 +- postfix/src/postconf/Makefile.in | 59 ++++- postfix/src/postconf/postconf.c | 382 ++++++++++++++++-------------- postfix/src/postconf/test12.ref | 2 + postfix/src/postconf/test13.ref | 3 + postfix/src/postconf/test14.ref | 3 + postfix/src/postconf/test15.ref | 3 + postfix/src/postconf/test5.ref | 1 - 13 files changed, 309 insertions(+), 204 deletions(-) create mode 100644 postfix/src/postconf/test12.ref create mode 100644 postfix/src/postconf/test13.ref create mode 100644 postfix/src/postconf/test14.ref create mode 100644 postfix/src/postconf/test15.ref diff --git a/postfix/.indent.pro b/postfix/.indent.pro index 789741ca4..32e60db68 100644 --- a/postfix/.indent.pro +++ b/postfix/.indent.pro @@ -186,6 +186,7 @@ -TNAME_CODE -TNAME_MASK -TNBBIO +-TPC_MASTER_ENT -TPC_SERVICE_DEF -TPC_STRING_NV -TPEER_NAME diff --git a/postfix/HISTORY b/postfix/HISTORY index 5dcb4d224..1febd6715 100644 --- a/postfix/HISTORY +++ b/postfix/HISTORY @@ -17109,3 +17109,13 @@ Apologies for any names omitted. Cleanup: "postconf" commands in postfix-install needed to be updated before master.cf was installed. Reported by Sahil Tandon. File: postfix-install. + +20111120 + + Cleanup: support for parameter name spaces for master.cf + entries. With this, postconf should no longer log false + warnings for "-o user-defined-name=value" in master.cf. As + a benefit, it will warn for user-defined parameters with + "name=value" entries that are unused because they are hidden + by master.cf "-o name=value" entries with the same parameter + name. File: postconf/postconf.c. diff --git a/postfix/RELEASE_NOTES b/postfix/RELEASE_NOTES index 6e8ce5ad1..2b03dba0b 100644 --- a/postfix/RELEASE_NOTES +++ b/postfix/RELEASE_NOTES @@ -14,6 +14,14 @@ specifies the release date of a stable release or snapshot release. If you upgrade from Postfix 2.7 or earlier, read RELEASE_NOTES-2.8 before proceeding. +Major changes with snapshot 20111120 +==================================== + +Eliminated the postconf limitation documented on 20111113 as "lack +of support for per-service parameter name spaces in master.cf, +meaning that "-o user-defined-name=value" always results in an +"unused parameter" warning". + Major changes with snapshot 20111118 ==================================== diff --git a/postfix/html/postconf.1.html b/postfix/html/postconf.1.html index 0c4ed0a04..b966b6a62 100644 --- a/postfix/html/postconf.1.html +++ b/postfix/html/postconf.1.html @@ -22,12 +22,14 @@ POSTCONF(1) POSTCONF(1) postconf [-fMv] [-c config_dir] [service ...] + Managing bounce message templates: + + postconf [-btv] [-c config_dir] [template_file] + Managing other configuration: postconf [-aAlmv] [-c config_dir] - postconf [-btv] [-c config_dir] [template_file] - DESCRIPTION By default, the postconf(1) command displays the values of main.cf configuration parameters, and warns about possible @@ -133,7 +135,7 @@ POSTCONF(1) POSTCONF(1) human readability. If service ... is specified, only the matching ser- - vices will be output. For example, a service of + vices will be output. For example, a service of inet will match all services that listen on the network. @@ -287,29 +289,23 @@ POSTCONF(1) POSTCONF(1) DIAGNOSTICS Problems are reported to the standard error stream. -BUGS - postconf(1) may log "unused parameter" warnings for mas- - ter.cf entries with "-o user-defined-name=value". - Addressing this limitation requires support for per-ser- - vice parameter name spaces. - ENVIRONMENT MAIL_CONFIG 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 @@ -324,7 +320,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 e572dd5a8..fbcf98f69 100644 --- a/postfix/man/man1/postconf.1 +++ b/postfix/man/man1/postconf.1 @@ -25,11 +25,13 @@ Postfix configuration utility \fBpostconf\fR [\fB-fMv\fR] [\fB-c \fIconfig_dir\fR] [\fIservice ...\fR] +\fBManaging bounce message templates:\fR + +\fBpostconf\fR [\fB-btv\fR] [\fB-c \fIconfig_dir\fR] [\fItemplate_file\fR] + \fBManaging other configuration:\fR \fBpostconf\fR [\fB-aAlmv\fR] [\fB-c \fIconfig_dir\fR] - -\fBpostconf\fR [\fB-btv\fR] [\fB-c \fIconfig_dir\fR] [\fItemplate_file\fR] .SH DESCRIPTION .ad .fi @@ -124,7 +126,7 @@ file contents. Use \fB-Mf\fR to fold long lines for human readability. If \fIservice ...\fR is specified, only the matching services -will be output. For example, a \fIservice\fB of \fBinet\fR +will be output. For example, a \fIservice\fR of \fBinet\fR will match all services that listen on the network. Specify zero or more arguments, each with a \fIservice-type\fR @@ -244,13 +246,6 @@ This feature is available with Postfix 2.6 and later. .ad .fi Problems are reported to the standard error stream. -.SH BUGS -.ad -.fi -\fBpostconf\fR(1) may log "unused parameter" warnings for -\fBmaster.cf\fR entries with "-o user-defined-name=value". -Addressing this limitation requires support for per-service -parameter name spaces. .SH "ENVIRONMENT" .na .nf diff --git a/postfix/src/global/mail_version.h b/postfix/src/global/mail_version.h index f92a34a82..07aee6e5d 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 "20111119" +#define MAIL_RELEASE_DATE "20111120" #define MAIL_VERSION_NUMBER "2.9" #ifdef SNAPSHOT diff --git a/postfix/src/postconf/Makefile.in b/postfix/src/postconf/Makefile.in index 63701be54..ca31397cd 100644 --- a/postfix/src/postconf/Makefile.in +++ b/postfix/src/postconf/Makefile.in @@ -36,7 +36,8 @@ Makefile: Makefile.in test: $(TESTPROG) -tests: test1 test2 test3 test4 test5 test6 test7 test8 test9 test10 test11 +tests: test1 test2 test3 test4 test5 test6 test7 test8 test9 test10 test11 \ + test12 test13 test14 test15 root_tests: @@ -100,9 +101,7 @@ test4: $(PROG) test4.ref rm -f main.cf master.cf test4.tmp # Define one user-defined parameter with name=value in master.cf, -# validate it with known_parameter=$name in master.cf. Currently, -# user-defined parameter definitions in master.cf are not recognized -# as definitions, and result in an "unused parameter" warning. +# validate it with known_parameter=$name in master.cf. test5: $(PROG) test5.ref rm -f main.cf master.cf @@ -169,6 +168,58 @@ test11: $(PROG) test11.ref diff test11.ref test11.tmp rm -f main.cf master.cf test11.tmp +# Duplicate service entry. + +test12: $(PROG) test12.ref + rm -f main.cf master.cf + touch main.cf master.cf + echo bar=yes >> main.cf + echo foo inet - n n - 0 spawn >> master.cf + echo ' -o always_bcc=$$bar -o' >> master.cf + echo foo inet - n n - 0 spawn >> master.cf + echo ' -o always_bcc=$$bar -o' >> master.cf + ./$(PROG) -c . -M >test12.tmp 2>&1 + diff test12.ref test12.tmp + rm -f main.cf master.cf test12.tmp + +# Define parameter with restriction_classes in master.cf, validate in main.cf. + +test13: $(PROG) test13.ref + rm -f main.cf master.cf + touch main.cf master.cf + echo bar=yes >> main.cf + echo baz=xx >> main.cf + echo foo inet - n n - 0 spawn >> master.cf + echo ' -o smtpd_restriction_classes=bar' >> master.cf + ./$(PROG) -nc . >test13.tmp 2>&1 + diff test13.ref test13.tmp + rm -f main.cf master.cf test13.tmp + +# Define parameter with restriction_classes in main.cf, validate in master.cf. + +test14: $(PROG) test14.ref + rm -f main.cf master.cf + touch main.cf master.cf + echo smtpd_restriction_classes=bar >> main.cf + echo foo inet - n n - 0 spawn >> master.cf + echo ' -o bar=yes -o baz=xx' >> master.cf + ./$(PROG) -nc . >test14.tmp 2>&1 + diff test14.ref test14.tmp + rm -f main.cf master.cf test14.tmp + +# Define two parameters, one is hidden by master.cf. + +test15: $(PROG) test15.ref + rm -f main.cf master.cf + touch main.cf master.cf + echo bar=xx >> main.cf + echo baz=yy >> main.cf + echo foo inet - n n - 0 spawn >> master.cf + echo ' -o bar=yes -o always_bcc=$$bar$$baz' >> master.cf + ./$(PROG) -nc . >test15.tmp 2>&1 + diff test15.ref test15.tmp + rm -f main.cf master.cf test15.tmp + printfck: $(OBJS) $(PROG) rm -rf printfck mkdir printfck diff --git a/postfix/src/postconf/postconf.c b/postfix/src/postconf/postconf.c index ac96720ca..6c8108db2 100644 --- a/postfix/src/postconf/postconf.c +++ b/postfix/src/postconf/postconf.c @@ -21,11 +21,13 @@ /* \fBpostconf\fR [\fB-fMv\fR] [\fB-c \fIconfig_dir\fR] /* [\fIservice ...\fR] /* +/* \fBManaging bounce message templates:\fR +/* +/* \fBpostconf\fR [\fB-btv\fR] [\fB-c \fIconfig_dir\fR] [\fItemplate_file\fR] +/* /* \fBManaging other configuration:\fR /* /* \fBpostconf\fR [\fB-aAlmv\fR] [\fB-c \fIconfig_dir\fR] -/* -/* \fBpostconf\fR [\fB-btv\fR] [\fB-c \fIconfig_dir\fR] [\fItemplate_file\fR] /* DESCRIPTION /* By default, the \fBpostconf\fR(1) command displays the /* values of \fBmain.cf\fR configuration parameters, and warns @@ -118,7 +120,7 @@ /* readability. /* /* If \fIservice ...\fR is specified, only the matching services -/* will be output. For example, a \fIservice\fB of \fBinet\fR +/* will be output. For example, a \fIservice\fR of \fBinet\fR /* will match all services that listen on the network. /* /* Specify zero or more arguments, each with a \fIservice-type\fR @@ -236,11 +238,6 @@ /* This feature is available with Postfix 2.6 and later. /* DIAGNOSTICS /* Problems are reported to the standard error stream. -/* BUGS -/* \fBpostconf\fR(1) may log "unused parameter" warnings for -/* \fBmaster.cf\fR entries with "-o user-defined-name=value". -/* Addressing this limitation requires support for per-service -/* parameter name spaces. /* ENVIRONMENT /* .ad /* .fi @@ -358,7 +355,7 @@ #define FOLD_LINE (1<<11) /* fold long *.cf entries */ /* - * Lookup table for in-core parameter info. + * Lookup table for global parameter info. * * XXX Change the value pointers from table indices into pointers to parameter * objects with print methods. @@ -366,13 +363,21 @@ HTABLE *param_table; /* - * Lookup table for master.cf info. - * - * XXX Replace by data structures with per-entry hashes for "-o name=value", so - * that we can properly handle name=value definitions in per-service name - * spaces. + * Global restriction_classes hash. */ -static ARGV **master_table; +HTABLE *rest_class_table; + + /* + * Lookup table for master.cf info. The table is null-terminated. + */ +typedef struct { + char *name_space; /* service.type, parameter name space */ + ARGV *argv; /* terminator, or master.cf fields */ + DICT *all_params; /* all name=value entries */ + HTABLE *valid_names; /* "blessed" parameters */ +} PC_MASTER_ENT; + +static PC_MASTER_ENT *master_table; /* * Support for built-in parameters: declarations generated by scanning @@ -458,24 +463,25 @@ static ssize_t serv_param_tablen; * * There are three categories of known parameters: built-in, service-defined * (see previous comment), and valid user-defined. In addition there are - * multiple name spaces: the global main.cf name space, and the per-service - * name space of each master.cf entry. + * multiple name spaces: the global main.cf name space, and the local name + * space of each master.cf entry. * * There are two categories of valid user-defined parameters: * - * - Parameters whose name appears in the value of smtpd_restriction_classes in - * main.cf, and whose name has a "name=value" entry in main.cf (todo: - * support for creating names with "-o smtpd_restriction_classes=name" - * within a master.cf per-service name space). + * - Parameters whose user-defined-name appears in the value of + * smtpd_restriction_classes in main.cf or master.cf, and that have a + * "user-defined-name=value" entry in main.cf or master.cf. * - * - Parameters whose $name (macro expansion) appears in the value of a - * "name=value" entry in main.cf or master.cf of a "known" parameter, and - * whose name has a "name=value" entry in main.cf (todo: master.cf). + * - Parameters whose $user-defined-name appears in the value of a "name=value" + * entry in main.cf or master.cf, and whose user-defined-name has a + * "name=value" entry in main.cf or master.cf. * - * All other user-defined parameters are invalid. We currently log a warning - * for "name=value" entries in main.cf or master.cf whose $name does not - * appear in the value of a main.cf or master.cf "name=value" entry of a - * "known" parameter. + * Other user-defined parameters are flagged as "unused". + */ + + /* + * Global-scope valid user-defined parameter names. The local-scope valid + * user-defined names are kept in the table with master.cf entries. */ static char **user_param_table; static ssize_t user_param_tablen; @@ -820,10 +826,12 @@ static void read_master(void) path = concatenate(var_config_dir, "/", MASTER_CONF_FILE, (char *) 0); /* - * We can't use the master_ent routines in their current form. They - * convert everything to internal form, and they skip disabled services. - * We need to be able to show default fields as "-", and we need to know - * about all service names so that we can generate service-dependent + * We can't use the master daemon's master_ent routines in their current + * form. They convert everything to internal form, and they skip disabled + * services. + * + * The postconf command needs to show default fields as "-", and needs to + * know about all service names so that it can generate service-dependent * parameter names (transport-dependent etc.). */ #define MASTER_BLANKS " \t\r\n" /* XXX */ @@ -832,7 +840,7 @@ static void read_master(void) /* * Initialize the in-memory master table. */ - master_table = (ARGV **) mymalloc(sizeof(*master_table)); + master_table = (PC_MASTER_ENT *) mymalloc(sizeof(*master_table)); /* * Skip blank lines and comment lines. @@ -840,14 +848,23 @@ static void read_master(void) if ((fp = vstream_fopen(path, O_RDONLY, 0)) == 0) msg_fatal("open %s: %m", path); while (readlline(buf, fp, &line_count) != 0) { - master_table = (ARGV **) myrealloc((char *) master_table, + master_table = (PC_MASTER_ENT *) myrealloc((char *) master_table, (entry_count + 2) * sizeof(*master_table)); argv = argv_split(STR(buf), MASTER_BLANKS); if (argv->argc < MASTER_FIELD_COUNT) msg_fatal("file %s: line %d: bad field count", path, line_count); - master_table[entry_count++] = argv; + master_table[entry_count].name_space = + concatenate(argv->argv[0], ".", argv->argv[1], (char *) 0); + master_table[entry_count].argv = argv; + master_table[entry_count].valid_names = 0; + master_table[entry_count].all_params = 0; + entry_count += 1; } - master_table[entry_count] = 0; + + /* + * Null-terminate the master table and clean up. + */ + master_table[entry_count].argv = 0; vstream_fclose(fp); myfree(path); vstring_free(buf); @@ -938,7 +955,7 @@ static void add_service_parameters(void) const PC_STRING_NV *sp; const char *progname; const char *service; - ARGV **argvp; + PC_MASTER_ENT *masterp; ARGV *argv; const PC_SERVICE_DEF *sd; @@ -952,7 +969,7 @@ static void add_service_parameters(void) * Extract service names from master.cf and generate service parameter * information. */ - for (argvp = master_table; (argv = *argvp) != 0; argvp++) { + for (masterp = master_table; (argv = masterp->argv) != 0; masterp++) { /* * Add service parameters for message delivery transports or spawn @@ -978,118 +995,152 @@ static void add_service_parameters(void) htable_enter(param_table, sp->name, (char *) sp); } -/* add_user_parameter - add one user-defined parameter name */ - -static void add_user_parameter(const char *name) -{ - /* XXX Merge this with check_parameter_value() */ - user_param_table = (char **) - myrealloc((char *) user_param_table, - (user_param_tablen + 1) * sizeof(*user_param_table)); - user_param_table[user_param_tablen] = mystrdup(name); - user_param_tablen += 1; -} - -/* scan_user_parameter_value - extract macro names from parameter value */ +/* scan_user_parameter_value - examine macro names in parameter value */ #define NO_SCAN_RESULT ((VSTRING *) 0) #define NO_SCAN_FILTER ((char *) 0) #define NO_SCAN_MODE (0) -#define NO_SCAN_CONTEXT ((char *) 0) -#define scan_user_parameter_value(value) do { \ +#define scan_user_parameter_value(value, context) do { \ (void) mac_expand(NO_SCAN_RESULT, (value), MAC_EXP_FLAG_SCAN, \ - NO_SCAN_FILTER, check_user_parameter, NO_SCAN_CONTEXT); \ + NO_SCAN_FILTER, check_user_parameter, (context)); \ } while (0) -/* check_user_parameter - try to promote user-defined parameter */ +/* check_user_parameter - promote user-defined name if it has name=value */ static const char *check_user_parameter(const char *mac_name, int unused_mode, - char *unused_context) + char *context) { - const char *mac_value; + PC_MASTER_ENT *local_scope = (PC_MASTER_ENT *) context; /* * Promote only user-defined parameters with an explicit "name=value" - * definition in main.cf (todo: master.cf). Do not promote parameters - * whose name appears only as a macro expansion; this is how Postfix - * implements backwards compatibility after a feature name change. + * definition. If the name=value exists in the local scope, update the + * local "valid" parameter name table, otherwise update the global one. * - * Skip parameters that are already in the param_table hash. + * Do not promote user-defined parameters whose name appears only as macro + * expansion; this is how Postfix implements backwards compatibility + * after a feature name change. + * + * Skip global names that are already in the param_table hash. */ - if (htable_locate(param_table, mac_name) == 0) { - mac_value = mail_conf_lookup(mac_name); - if (mac_value != 0) { - add_user_parameter(mac_name); - /* Promote parameter names recursively. */ - scan_user_parameter_value(mac_value); + if (local_scope && dict_get(local_scope->all_params, mac_name)) { + if (htable_locate(local_scope->valid_names, mac_name) == 0) + htable_enter(local_scope->valid_names, mac_name, ""); + } else if (htable_locate(param_table, mac_name) == 0) { + if (mail_conf_lookup(mac_name) != 0) { + user_param_table = (char **) + myrealloc((char *) user_param_table, + (user_param_tablen + 1) * sizeof(*user_param_table)); + user_param_table[user_param_tablen] = mystrdup(mac_name); + user_param_tablen += 1; } } return (0); } +/* pc_lookup_eval - generalized mail_conf_lookup_eval */ + +static const char *pc_lookup_eval(const char *dict_name, const char *name) +{ + const char *value; + +#define RECURSIVE 1 + + if ((value = dict_lookup(dict_name, name)) != 0) + value = dict_eval(dict_name, value, RECURSIVE); + return (value); +} + +/* scan_user_parameter_namespace - scan parameters in name space */ + +static void scan_user_parameter_namespace(const char *dict_name, + PC_MASTER_ENT *local_scope) +{ + const char *myname = "scan_user_parameter_namespace"; + const char *class_list; + char *saved_class_list; + char *cp; + DICT *dict; + char *param_name; + int how; + const char *cparam_name; + const char *cparam_value; + + /* + * Add parameters whose names are defined with smtpd_restriction_classes, + * but only if they have a "name=value" entry. If we are in the global + * scope, update the global restriction class name table, so that we can + * query the table from within a local master.cf name space. + */ + if ((class_list = pc_lookup_eval(dict_name, VAR_REST_CLASSES)) != 0) { + cp = saved_class_list = mystrdup(class_list); + while ((param_name = mystrtok(&cp, ", \t\r\n")) != 0) { + if (local_scope == 0 + && htable_locate(rest_class_table, param_name) == 0) + htable_enter(rest_class_table, param_name, ""); + check_user_parameter(param_name, NO_SCAN_MODE, + (char *) local_scope); + } + myfree(saved_class_list); + } + + /* + * For all "name=value" instances: a) if the scope is local and the name + * appears in the global restriction class table, flag the name as + * "valid" in the local scope; b) scan the value for macro expansions of + * unknown parameter names, and flag those parameter names as "valid" if + * they have a "name=value" entry. + */ + if ((dict = dict_handle(dict_name)) == 0) + msg_panic("%s: parameter dictionary %s not found", + myname, dict_name); + if (dict->sequence == 0) + msg_panic("%s: parameter dictionary %s has no iterator", + myname, dict_name); + for (how = DICT_SEQ_FUN_FIRST; + dict->sequence(dict, how, &cparam_name, &cparam_value) == 0; + how = DICT_SEQ_FUN_NEXT) { + if (local_scope != 0 + && htable_locate(local_scope->valid_names, cparam_name) == 0 + && htable_locate(rest_class_table, cparam_name) != 0) + htable_enter(local_scope->valid_names, cparam_name, ""); + scan_user_parameter_value(cparam_value, (char *) local_scope); + } +} + /* add_user_parameters - add parameters with user-defined names */ static void add_user_parameters(void) { - const char *class_list; - char *saved_class_list; - char *cp; - const char *cparam_value; - HTABLE_INFO **ht_info; - HTABLE_INFO **ht; - ARGV **argvp; + PC_MASTER_ENT *masterp; ARGV *argv; char *arg; int field; char *saved_arg; char *param_name; char *param_value; + DICT *dict; char **up; /* - * Initialize the table with user-defined parameter names and values. + * Initialize the global table with user-defined parameter names, and the + * table with global restriction class names. */ user_param_table = (char **) mymalloc(1); user_param_tablen = 0; + rest_class_table = htable_create(1); /* - * Add parameters whose names are defined with smtpd_restriction_classes, - * but only if they have a "name=value" entry in main.cf. - * - * XXX It is possible that a user-defined parameter is defined in master.cf - * with "-o smtpd_restriction_classes=name -o name=value". This requires - * name space support for master.cf entries. Without this, we always log - * "unused parameter" warnings for "-o user-defined-name=value" entries. + * Scan the explicit name=value entries in the global name space. */ - if ((class_list = mail_conf_lookup_eval(VAR_REST_CLASSES)) != 0) { - cp = saved_class_list = mystrdup(class_list); - while ((param_name = mystrtok(&cp, ", \t\r\n")) != 0) - check_user_parameter(param_name, NO_SCAN_MODE, NO_SCAN_CONTEXT); - myfree(saved_class_list); - } + scan_user_parameter_namespace(CONFIG_DICT, (PC_MASTER_ENT *) 0); /* - * Parse the "name=value" instances in main.cf of built-in and service - * parameters only, look for macro expansions of unknown parameter names, - * and flag those parameter names as "known" if they have a "name=value" - * entry in main.cf. Recursively apply the procedure to the values of - * newly-flagged parameters. + * Scan the "-o parameter=value" instances in each master.cf name space. */ - for (ht_info = ht = htable_list(param_table); *ht; ht++) - if ((cparam_value = mail_conf_lookup(ht[0]->key)) != 0) - scan_user_parameter_value(cparam_value); - myfree((char *) ht_info); - - /* - * Parse all "-o parameter=value" instances in master.cf, look for macro - * expansions of unknown parameter names, and flag those parameter names - * as "known" if they have a "name=value" entry in main.cf (XXX todo: in - * master.cf; without master.cf name space support we always log "unused - * parameter" warnings for "-o user-defined-name=value" entries). - */ - for (argvp = master_table; (argv = *argvp) != 0; argvp++) { + for (masterp = master_table; (argv = masterp->argv) != 0; masterp++) { for (field = MASTER_FIELD_COUNT; argv->argv[field] != 0; field++) { arg = argv->argv[field]; if (arg[0] != '-') @@ -1097,11 +1148,16 @@ static void add_user_parameters(void) if (strcmp(arg, "-o") == 0 && (arg = argv->argv[field + 1]) != 0) { saved_arg = mystrdup(arg); if (split_nameval(saved_arg, ¶m_name, ¶m_value) == 0) - scan_user_parameter_value(param_value); + dict_update(masterp->name_space, param_name, param_value); myfree(saved_arg); field += 1; } } + if ((dict = dict_handle(masterp->name_space)) != 0) { + masterp->all_params = dict; + masterp->valid_names = htable_create(1); + scan_user_parameter_namespace(masterp->name_space, masterp); + } } /* @@ -1756,35 +1812,25 @@ static void print_master_line(int mode, ARGV *argv) static void show_master(int mode, char **filters) { - ARGV **argvp; + PC_MASTER_ENT *masterp; ARGV *argv; - VSTRING *service_name = 0; ARGV *service_filter = 0; /* * Initialize the service filter. */ - if (filters[0]) { - service_name = vstring_alloc(10); + if (filters[0]) service_filter = match_service_init_argv(filters); - } /* * Iterate over the master table. */ - for (argvp = master_table; (argv = *argvp) != 0; argvp++) { - if (service_filter) { - vstring_sprintf(service_name, "%s.%s", - argv->argv[0], argv->argv[1]); - if (match_service_match(service_filter, STR(service_name)) == 0) - continue; - } - print_master_line(mode, argv); - } - if (service_filter) { + for (masterp = master_table; (argv = masterp->argv) != 0; masterp++) + if (service_filter == 0 + || match_service_match(service_filter, masterp->name_space) != 0) + print_master_line(mode, argv); + if (service_filter != 0) argv_free(service_filter); - vstring_free(service_name); - } } /* show_sasl - show SASL plug-in types */ @@ -1801,79 +1847,67 @@ static void show_sasl(int what) argv_free(sasl_argv); } +/* flag_unused_parameters - warn about unused parameters */ + +static void flag_unused_parameters(DICT *dict, const char *conf_name, + PC_MASTER_ENT *local_scope) +{ + const char *myname = "flag_unused_parameters"; + const char *param_name; + const char *param_value; + int how; + + /* + * Iterate over all entries, and flag parameter names that aren't used + * anywhere. Show the warning message at the end of the output. + */ + if (dict->sequence == 0) + msg_panic("%s: parameter dictionary %s has no iterator", + myname, conf_name); + for (how = DICT_SEQ_FUN_FIRST; + dict->sequence(dict, how, ¶m_name, ¶m_value) == 0; + how = DICT_SEQ_FUN_NEXT) { + if (htable_locate(param_table, param_name) == 0 + && (local_scope == 0 + || htable_locate(local_scope->valid_names, param_name) == 0)) { + vstream_fflush(VSTREAM_OUT); + msg_warn("%s/%s: unused parameter: %s=%s", + var_config_dir, conf_name, param_name, param_value); + } + } +} + /* flag_unused_main_parameters - warn about unused parameters */ static void flag_unused_main_parameters(void) { const char *myname = "flag_unused_main_parameters"; DICT *dict; - const char *param_name; - const char *param_value; - int how; /* * Iterate over all main.cf entries, and flag parameter names that aren't - * used anywhere. Show the warning message at the end of the output. + * used anywhere. */ if ((dict = dict_handle(CONFIG_DICT)) == 0) msg_panic("%s: parameter dictionary %s not found", myname, CONFIG_DICT); - if (dict->sequence == 0) - msg_panic("%s: parameter dictionary %s has no iterator", - myname, CONFIG_DICT); - for (how = DICT_SEQ_FUN_FIRST; - dict->sequence(dict, how, ¶m_name, ¶m_value) == 0; - how = DICT_SEQ_FUN_NEXT) { - if (htable_locate(param_table, param_name) == 0) { - vstream_fflush(VSTREAM_OUT); - msg_warn("%s/" MAIN_CONF_FILE ": unused parameter: %s=%s", - var_config_dir, param_name, param_value); - } - } + flag_unused_parameters(dict, MAIN_CONF_FILE, (PC_MASTER_ENT *) 0); } /* flag_unused_master_parameters - warn about unused parameters */ static void flag_unused_master_parameters(void) { - ARGV **argvp; - ARGV *argv; - int field; - char *arg; - char *saved_arg; - char *param_name; - char *param_value; + PC_MASTER_ENT *masterp; + DICT *dict; /* * Iterate over all master.cf entries, and flag parameter names that - * aren't used anywhere. Show the warning message at the end of the - * output. - * - * XXX It is possible that a user-defined parameter is defined in master.cf - * with "-o smtpd_restriction_classes=name", or with "-o name1=value1" - * and then used in a "-o name2=$name1" macro expansion in that same - * master.cf entry. To handle this we need to give each master.cf entry - * its own name space. Until then, we always log "unused parameter" - * warnings for "-o user-defined-name=value" entries. + * aren't used anywhere. */ - for (argvp = master_table; (argv = *argvp) != 0; argvp++) { - for (field = MASTER_FIELD_COUNT; argv->argv[field] != 0; field++) { - arg = argv->argv[field]; - if (arg[0] != '-') - break; - if (strcmp(arg, "-o") == 0 && (arg = argv->argv[field + 1]) != 0) { - saved_arg = mystrdup(arg); - if (split_nameval(saved_arg, ¶m_name, ¶m_value) == 0 - && htable_locate(param_table, param_name) == 0) { - vstream_fflush(VSTREAM_OUT); - msg_warn("%s/" MASTER_CONF_FILE ": unused parameter: %s=%s", - var_config_dir, param_name, param_value); - } - myfree(saved_arg); - field += 1; - } - } - } + for (masterp = master_table; masterp->argv != 0; masterp++) + if ((dict = masterp->all_params) != 0) + flag_unused_parameters(dict, MASTER_CONF_FILE, masterp); } MAIL_VERSION_STAMP_DECLARE; diff --git a/postfix/src/postconf/test12.ref b/postfix/src/postconf/test12.ref new file mode 100644 index 000000000..a9f5eb4a2 --- /dev/null +++ b/postfix/src/postconf/test12.ref @@ -0,0 +1,2 @@ +foo inet - n n - 0 spawn -o always_bcc=$bar -o +foo inet - n n - 0 spawn -o always_bcc=$bar -o diff --git a/postfix/src/postconf/test13.ref b/postfix/src/postconf/test13.ref new file mode 100644 index 000000000..09787fadb --- /dev/null +++ b/postfix/src/postconf/test13.ref @@ -0,0 +1,3 @@ +bar = yes +config_directory = . +./postconf: warning: ./main.cf: unused parameter: baz=xx diff --git a/postfix/src/postconf/test14.ref b/postfix/src/postconf/test14.ref new file mode 100644 index 000000000..98884f3f0 --- /dev/null +++ b/postfix/src/postconf/test14.ref @@ -0,0 +1,3 @@ +config_directory = . +smtpd_restriction_classes = bar +./postconf: warning: ./master.cf: unused parameter: baz=xx diff --git a/postfix/src/postconf/test15.ref b/postfix/src/postconf/test15.ref new file mode 100644 index 000000000..2a15ca84d --- /dev/null +++ b/postfix/src/postconf/test15.ref @@ -0,0 +1,3 @@ +baz = yy +config_directory = . +./postconf: warning: ./main.cf: unused parameter: bar=xx diff --git a/postfix/src/postconf/test5.ref b/postfix/src/postconf/test5.ref index 3c853fff1..41bee93ae 100644 --- a/postfix/src/postconf/test5.ref +++ b/postfix/src/postconf/test5.ref @@ -1,2 +1 @@ config_directory = . -./postconf: warning: ./master.cf: unused parameter: bar=yes