mirror of
https://github.com/vdukhovni/postfix
synced 2025-08-29 05:07:58 +00:00
postfix-2.9-20111120
This commit is contained in:
parent
2cfc3431dc
commit
38b0a080dc
1
postfix/.indent.pro
vendored
1
postfix/.indent.pro
vendored
@ -186,6 +186,7 @@
|
||||
-TNAME_CODE
|
||||
-TNAME_MASK
|
||||
-TNBBIO
|
||||
-TPC_MASTER_ENT
|
||||
-TPC_SERVICE_DEF
|
||||
-TPC_STRING_NV
|
||||
-TPEER_NAME
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
====================================
|
||||
|
||||
|
@ -22,12 +22,14 @@ POSTCONF(1) POSTCONF(1)
|
||||
|
||||
<b>postconf</b> [<b>-fMv</b>] [<b>-c</b> <i>config</i><b>_</b><i>dir</i>] [<i>service ...</i>]
|
||||
|
||||
<b>Managing bounce message templates:</b>
|
||||
|
||||
<b>postconf</b> [<b>-btv</b>] [<b>-c</b> <i>config</i><b>_</b><i>dir</i>] [<i>template</i><b>_</b><i>file</i>]
|
||||
|
||||
<b>Managing other configuration:</b>
|
||||
|
||||
<b>postconf</b> [<b>-aAlmv</b>] [<b>-c</b> <i>config</i><b>_</b><i>dir</i>]
|
||||
|
||||
<b>postconf</b> [<b>-btv</b>] [<b>-c</b> <i>config</i><b>_</b><i>dir</i>] [<i>template</i><b>_</b><i>file</i>]
|
||||
|
||||
<b>DESCRIPTION</b>
|
||||
By default, the <a href="postconf.1.html"><b>postconf</b>(1)</a> command displays the values of
|
||||
<a href="postconf.5.html"><b>main.cf</b></a> configuration parameters, and warns about possible
|
||||
@ -133,7 +135,7 @@ POSTCONF(1) POSTCONF(1)
|
||||
human readability.
|
||||
|
||||
If <i>service ...</i> is specified, only the matching ser-
|
||||
vices will be output. For example, a <i>service</i> <b>of</b>
|
||||
vices will be output. For example, a <i>service</i> of
|
||||
<b>inet</b> will match all services that listen on the
|
||||
network.
|
||||
|
||||
@ -287,29 +289,23 @@ POSTCONF(1) POSTCONF(1)
|
||||
<b>DIAGNOSTICS</b>
|
||||
Problems are reported to the standard error stream.
|
||||
|
||||
<b>BUGS</b>
|
||||
<a href="postconf.1.html"><b>postconf</b>(1)</a> may log "unused parameter" warnings for <b>mas-</b>
|
||||
<b>ter.cf</b> entries with "-o user-defined-name=value".
|
||||
Addressing this limitation requires support for per-ser-
|
||||
vice parameter name spaces.
|
||||
|
||||
<b>ENVIRONMENT</b>
|
||||
<b>MAIL_CONFIG</b>
|
||||
Directory with Postfix configuration files.
|
||||
|
||||
<b>CONFIGURATION PARAMETERS</b>
|
||||
The following <a href="postconf.5.html"><b>main.cf</b></a> parameters are especially relevant
|
||||
The following <a href="postconf.5.html"><b>main.cf</b></a> 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
|
||||
<a href="postconf.5.html"><b>postconf</b>(5)</a> for more details including examples.
|
||||
|
||||
<b><a href="postconf.5.html#config_directory">config_directory</a> (see 'postconf -d' output)</b>
|
||||
The default location of the Postfix <a href="postconf.5.html">main.cf</a> and
|
||||
The default location of the Postfix <a href="postconf.5.html">main.cf</a> and
|
||||
<a href="master.5.html">master.cf</a> configuration files.
|
||||
|
||||
<b><a href="postconf.5.html#bounce_template_file">bounce_template_file</a> (empty)</b>
|
||||
Pathname of a configuration file with bounce mes-
|
||||
Pathname of a configuration file with bounce mes-
|
||||
sage templates.
|
||||
|
||||
<b>FILES</b>
|
||||
@ -324,7 +320,7 @@ POSTCONF(1) POSTCONF(1)
|
||||
<a href="DATABASE_README.html">DATABASE_README</a>, Postfix lookup table overview
|
||||
|
||||
<b>LICENSE</b>
|
||||
The Secure Mailer license must be distributed with this
|
||||
The Secure Mailer license must be distributed with this
|
||||
software.
|
||||
|
||||
<b>AUTHOR(S)</b>
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
2
postfix/src/postconf/test12.ref
Normal file
2
postfix/src/postconf/test12.ref
Normal file
@ -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
|
3
postfix/src/postconf/test13.ref
Normal file
3
postfix/src/postconf/test13.ref
Normal file
@ -0,0 +1,3 @@
|
||||
bar = yes
|
||||
config_directory = .
|
||||
./postconf: warning: ./main.cf: unused parameter: baz=xx
|
3
postfix/src/postconf/test14.ref
Normal file
3
postfix/src/postconf/test14.ref
Normal file
@ -0,0 +1,3 @@
|
||||
config_directory = .
|
||||
smtpd_restriction_classes = bar
|
||||
./postconf: warning: ./master.cf: unused parameter: baz=xx
|
3
postfix/src/postconf/test15.ref
Normal file
3
postfix/src/postconf/test15.ref
Normal file
@ -0,0 +1,3 @@
|
||||
baz = yy
|
||||
config_directory = .
|
||||
./postconf: warning: ./main.cf: unused parameter: bar=xx
|
@ -1,2 +1 @@
|
||||
config_directory = .
|
||||
./postconf: warning: ./master.cf: unused parameter: bar=yes
|
||||
|
Loading…
x
Reference in New Issue
Block a user