]> git.ipfire.org Git - thirdparty/postfix.git/commitdiff
postfix-2.9-20111112
authorWietse Venema <wietse@porcupine.org>
Sat, 12 Nov 2011 05:00:00 +0000 (00:00 -0500)
committerViktor Dukhovni <viktor@dukhovni.org>
Tue, 5 Feb 2013 06:37:35 +0000 (06:37 +0000)
postfix/HISTORY
postfix/html/postconf.1.html
postfix/man/man1/postconf.1
postfix/src/global/mail_version.h
postfix/src/postconf/install_table.h
postfix/src/postconf/install_vars.h
postfix/src/postconf/postconf.c
postfix/src/util/mac_expand.c
postfix/src/util/mac_expand.h

index 83b84ed74a93a6bab235fe65ba17cc69f1c62a58..2ad3e9ed094893b751321cfff495d2a8da6664e0 100644 (file)
@@ -17062,3 +17062,10 @@ Apologies for any names omitted.
 
        Cleanup: account for "," in smtpd_restriction_classes
        value (Victor Duchovni). File: postconf/postconf.c.
+
+20111112
+
+       Cleanup: postconf finally warns about possible mis-typed
+       main.cf and master.cf parameter names (i.e. parameters that
+       aren't used anywhere), and it finally displays user-defined
+       main.cf parameters that *are* used.  File: postconf/postconf.c.
index 34c1219e45309897b77648c270a61585c4bee062..5510507dacf78814d64fb6d871374426cd61820b 100644 (file)
@@ -21,10 +21,12 @@ POSTCONF(1)                                                        POSTCONF(1)
        <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>
-       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 by default. It  can  also  change
-       parameter  values, or display other configuration informa-
-       tion about the Postfix mail system.
+       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
+       mis-typed parameter names (Postfix 2.9 and later).  It can
+       also change <a href="postconf.5.html"><b>main.cf</b></a>  configuration  parameter  values,  or
+       display  other configuration information about the Postfix
+       mail system.
 
        Options:
 
index af9b6cf32d7dfe688098db953938818c08bab8e7..7f6f5794bb247fd60fd128cf69f62017d1f4e6e8 100644 (file)
@@ -24,8 +24,10 @@ Postfix configuration utility
 .SH DESCRIPTION
 .ad
 .fi
-The \fBpostconf\fR(1) command displays the values of \fBmain.cf\fR
-configuration parameters by default. It can also change
+By default, the \fBpostconf\fR(1) command displays the
+values of \fBmain.cf\fR configuration parameters, and warns
+about possible mis-typed parameter names (Postfix 2.9 and later).
+It can also change \fBmain.cf\fR configuration
 parameter values, or display other configuration information
 about the Postfix mail system.
 
index 1a653e442121c02fe8fd0913e82fe7082ccf360f..abe6e08103163d79fb0ceb01dccabdab173ba70b 100644 (file)
@@ -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      "20111109"
+#define MAIL_RELEASE_DATE      "20111112"
 #define MAIL_VERSION_NUMBER    "2.9"
 
 #ifdef SNAPSHOT
index a7dff6f3f18c142f334081eaca1552aac08f2e31..d6e21bd89de51db3f6e2c9827c1723c53de2e824 100644 (file)
@@ -1 +1,2 @@
     VAR_CONFIG_DIR, DEF_CONFIG_DIR, &var_config_dir, 1, 0,
+    VAR_DEBUG_COMMAND, "", &var_debug_command, 1, 0,
index c54581ee8ee54526a633c2a3dadbf944735f49ea..c46882b3443b41e1597507ad93cd725d91bc7442 100644 (file)
@@ -1 +1,2 @@
 char   *var_config_dir;
+char   *var_debug_command;
index 77460913cbe2ef0189513bd395d374826c8e4767..c3eb755117d80ff1d8866d389a22f0215131fb29 100644 (file)
 /*
 /*     \fBpostconf\fR [\fB-btv\fR] [\fB-c \fIconfig_dir\fR] [\fItemplate_file\fR]
 /* DESCRIPTION
-/*     The \fBpostconf\fR(1) command displays the values of \fBmain.cf\fR
-/*     configuration parameters by default. It can also change
+/*     By default, the \fBpostconf\fR(1) command displays the
+/*     values of \fBmain.cf\fR configuration parameters, and warns
+/*     about possible mis-typed parameter names (Postfix 2.9 and later).
+/*     It can also change \fBmain.cf\fR configuration
 /*     parameter values, or display other configuration information
 /*     about the Postfix mail system.
 /*
 #include <argv.h>
 #include <edit_file.h>
 #include <readlline.h>
+#include <mac_expand.h>
 
 /* Global library. */
 
   */
 HTABLE *param_table;
 
- /*
-  * Lookup table for external parameter info.
-  */
-DICT   *text_table;
-
  /*
   * Lookup table for master.cf info.
   */
@@ -414,20 +412,22 @@ typedef struct {
 } STRING_NV;
 
  /*
-  * Support for parameters whose names are derived from master.cf message
-  * delivery transport names. These parameters have default values that are
-  * defined by other parameters.
+  * Support for parameters whose postfix-defined names are derived from
+  * master.cf service names. These parameters have default values that are
+  * defined by built-in parameters.
   */
-static STRING_NV *del_transp_table;
-static ssize_t del_transp_tablen;
+static STRING_NV *serv_param_table;
+static ssize_t serv_param_tablen;
 
  /*
-  * Support for parameters whose names are specified in main.cf with
-  * smtpd_restriction_classes. These parameters have the empty string as
-  * their default value.
+  * Support for parameters whose user-defined names are specified in main.cf
+  * with smtpd_restriction_classes, and for user-defined parameters whose
+  * "name=value" appears in main.cf and whose $name appears in the value of
+  * in master.cf "-o name=value" entries, or in main.cf "name=value" entries
+  * for known parameters.
   */
-static char **rest_class_table;
-static ssize_t rest_class_tablen;
+static char **user_param_table;
+static ssize_t user_param_tablen;
 
  /*
   * Parameters with default values obtained via function calls.
@@ -820,34 +820,32 @@ static void read_master(void)
 #define MAIL_PROGRAM_SPAWN     "spawn"
 #endif
 
-/* add_restriction_class - add one smtpd_restriction_classes name */
+/* add_service_parameter - add one service parameter name and default */
 
-static void add_restriction_class(const char *name)
-{
-    rest_class_table = (char **)
-    myrealloc((char *) rest_class_table,
-             (rest_class_tablen + 1) * sizeof(*rest_class_table));
-    rest_class_table[rest_class_tablen] = mystrdup(name);
-    rest_class_tablen += 1;
-}
-
-/* add_dynamic_parameter - add one dynamic parameter name and default */
-
-static void add_dynamic_parameter(const char *service, const char *suffix,
+static void add_service_parameter(const char *service, const char *suffix,
                                          const char *defparam)
 {
-    del_transp_table = (STRING_NV *)
-    myrealloc((char *) del_transp_table,
-             (del_transp_tablen + 1) * sizeof(*del_transp_table));
-    del_transp_table[del_transp_tablen].name =
-       concatenate(service, suffix, (char *) 0);
-    del_transp_table[del_transp_tablen].value = defparam;
-    del_transp_tablen += 1;
+    STRING_NV *sp;
+
+    /*
+     * Skip service parameter names that have explicit built-in definitions.
+     * This happens with message delivery transports that have a non-default
+     * per-destination concurrency or recipient limit, such as local(8).
+     * 
+     * XXX Skip parameters that are already in the param_table hash.
+     */
+    serv_param_table = (STRING_NV *)
+       myrealloc((char *) serv_param_table,
+                 (serv_param_tablen + 1) * sizeof(*serv_param_table));
+    sp = serv_param_table + serv_param_tablen;
+    sp->name = concatenate(service, suffix, (char *) 0);
+    sp->value = defparam;
+    serv_param_tablen += 1;
 }
 
-/* add_dynamic_parameters - add all dynamic parameters with defaults */
+/* add_service_parameters - add all service parameters with defaults */
 
-static void add_dynamic_parameters(int mode)
+static void add_service_parameters(void)
 {
     /* XXX Should this list be configurable? */
     static const char *delivery_agents[] = {
@@ -856,7 +854,7 @@ static void add_dynamic_parameters(int mode)
        MAIL_PROGRAM_LMTP, MAIL_PROGRAM_PIPE,
        0,
     };
-    static const STRING_NV del_transp_params[] = {
+    static const STRING_NV service_params[] = {
        /* suffix, default parameter name */
        _XPORT_RCPT_LIMIT, VAR_XPORT_RCPT_LIMIT,
        _STACK_RCPT_LIMIT, VAR_STACK_RCPT_LIMIT,
@@ -882,26 +880,20 @@ static void add_dynamic_parameters(int mode)
     };
     const STRING_NV *sp;
     const char *progname;
+    const char *service;
     ARGV  **argvp;
     ARGV   *argv;
     const char **cpp;
-    const char *class_list;
-    char   *cp;
-    char   *saved_class_list;
-    char   *class_name;
 
     /*
-     * Initialize the tables with dynamic parameter names and defaults.
+     * Initialize the table with service parameter names and defaults.
      */
-    del_transp_table = (STRING_NV *) mymalloc(1);
-    del_transp_tablen = 0;
-
-    rest_class_table = (char **) mymalloc(1);
-    rest_class_tablen = 0;
+    serv_param_table = (STRING_NV *) mymalloc(1);
+    serv_param_tablen = 0;
 
     /*
-     * Extract message delivery transport names from master.cf and generate
-     * dynamic parameter information.
+     * Extract service names from master.cf and generate service parameter
+     * information.
      */
     for (argvp = master_table; (argv = *argvp) != 0; argvp++) {
 
@@ -912,50 +904,169 @@ static void add_dynamic_parameters(int mode)
            continue;
 
        /*
-        * Add dynamic parameters for message delivery transports.
+        * Add service parameters for message delivery transports.
         */
        progname = argv->argv[7];
        for (cpp = delivery_agents; *cpp; cpp++)
            if (strcmp(*cpp, progname) == 0)
                break;
        if (*cpp != 0) {
-           for (sp = del_transp_params; sp->name; sp++)
-               add_dynamic_parameter(argv->argv[0], sp->name, sp->value);
+           service = argv->argv[0];
+           for (sp = service_params; sp->name; sp++)
+               add_service_parameter(service, sp->name, sp->value);
            continue;
        }
 
        /*
-        * Add dynamic parameters for spawn(8)-based services.
+        * Add service parameters for spawn(8)-based services.
         */
        if (strcmp(MAIL_PROGRAM_SPAWN, progname) == 0) {
+           service = argv->argv[0];
            for (sp = spawn_params; sp->name; sp++)
-               add_dynamic_parameter(argv->argv[0], sp->name, sp->value);
+               add_service_parameter(service, sp->name, sp->value);
            continue;
        }
     }
 
     /*
-     * Add parameters specified with smtpd_restriction_classes.
+     * Now that the service parameter table size is frozen, enter the
+     * parameters into the hash so that we can find and print them.
+     */
+    for (sp = serv_param_table; sp < serv_param_table + serv_param_tablen; sp++)
+       if (htable_locate(param_table, sp->name) == 0)
+           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;
+}
+
+#ifdef MAC_EXP_FLAG_SCAN
+#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 { \
+    (void) mac_expand(NO_SCAN_RESULT, (value), MAC_EXP_FLAG_SCAN, \
+                   NO_SCAN_FILTER, check_user_parameter, NO_SCAN_CONTEXT); \
+} while (0)
+#else
+#define scan_user_parameter_value(value) do { /* void */; } while (0)
+#endif
+
+/* check_user_parameter - try to promote user-defined parameter */
+
+static const char *check_user_parameter(const char *mac_name,
+                                               int unused_mode,
+                                               char *unused_context)
+{
+    const char *mac_value;
+
+    /*
+     * Promote only user-defined parameters with an explicit "name=value"
+     * main.cf definition. Do not promote parameters whose name appears only
+     * as a macro expansion; this is how Postfix implements backwards
+     * compatibility after a feature name change.
+     * 
+     * XXX Skip parameters that are already in the param_table hash.
+     */
+    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);
+    }
+    return (0);
+}
+
+/* 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;
+    ARGV   *argv;
+    char   *arg;
+    int     field;
+    char   *saved_arg;
+    char   *param_name;
+    char   *param_value;
+    char  **up;
+
+    /*
+     * Initialize the table with user-defined parameter names and values.
      */
-    if ((mode & SHOW_DEFS) == 0
-       && (class_list = mail_conf_lookup_eval(VAR_REST_CLASSES)) != 0) {
+    user_param_table = (char **) mymalloc(1);
+    user_param_tablen = 0;
+
+    /*
+     * Add parameters whose names are defined with smtpd_restriction_classes,
+     * but only if they have a "name=value" entry in main.cf.
+     */
+    if ((class_list = mail_conf_lookup_eval(VAR_REST_CLASSES)) != 0) {
        cp = saved_class_list = mystrdup(class_list);
-       while ((class_name = mystrtok(&cp, ", \t\r\n")) != 0)
-           add_restriction_class(class_name);
+       while ((param_name = mystrtok(&cp, ", \t\r\n")) != 0)
+           check_user_parameter(param_name, NO_SCAN_MODE, NO_SCAN_CONTEXT);
        myfree(saved_class_list);
     }
 
     /*
-     * TODO: Parse all legitimate parameter values (in main.cf and in
-     * master.cf) for references to spontaneous parameters that are defined
-     * in main.cf, and flag those spontaneous parameters as legitimate. Then,
-     * flag all remaining spontaneous parameter definitions in main.cf as
-     * mistakes.
+     * 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 unknown parameter names as "known" if they have a
+     * "name=value" entry in main.cf.
+     */
+    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 for
+     * macro expansions of unknown parameter names, and flag those unknown
+     * parameter names as "known" if they have a "name=value" entry in
+     * main.cf.
      * 
-     * It is OK if a spontaneous name exists only in a reference; this is how
-     * Postfix implements backwards compatibility after a feature name
-     * change.
+     * XXX It is possible that a user-defined parameter is defined in master.cf
+     * with "-o name1=value1" and then used in a "-o name2=$name1" macro
+     * expansion in that same master.cf entry.
+     */
+    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, &param_name, &param_value) == 0)
+                   scan_user_parameter_value(param_value);
+               myfree(saved_arg);
+               field += 1;
+           }
+       }
+    }
+
+    /*
+     * Now that the user-defined parameter table size is frozen, enter the
+     * parameters into the hash so that we can find and print them.
      */
+    for (up = user_param_table; up < user_param_table + user_param_tablen; up++)
+       if (htable_locate(param_table, *up) == 0)
+           htable_enter(param_table, *up, (char *) up);
 }
 
 /* hash_parameters - hash all parameter names so we can find and sort them */
@@ -971,14 +1082,9 @@ static void hash_parameters(void)
     const CONFIG_NINT_TABLE *nst;
     const CONFIG_NBOOL_TABLE *bst;
     const CONFIG_LONG_TABLE *lst;
-    const STRING_NV *dst;
-    char  **rct;
 
     param_table = htable_create(100);
 
-    /*
-     * Don't allow dynamic parameter names to override built-in names.
-     */
     for (ctt = time_table; ctt->name; ctt++)
        htable_enter(param_table, ctt->name, (char *) ctt);
     for (cbt = bool_table; cbt->name; cbt++)
@@ -999,12 +1105,6 @@ static void hash_parameters(void)
        htable_enter(param_table, bst->name, (char *) bst);
     for (lst = long_table; lst->name; lst++)
        htable_enter(param_table, lst->name, (char *) lst);
-    for (dst = del_transp_table; dst < del_transp_table + del_transp_tablen; dst++)
-       if (htable_locate(param_table, dst->name) == 0)
-           htable_enter(param_table, dst->name, (char *) dst);
-    for (rct = rest_class_table; rct < rest_class_table + rest_class_tablen; rct++)
-       if (htable_locate(param_table, *rct) == 0)
-           htable_enter(param_table, *rct, (char *) rct);
 }
 
 /* print_line - show line possibly folded, and with normalized whitespace */
@@ -1340,16 +1440,16 @@ static void print_long(int mode, const char *name, CONFIG_LONG_TABLE *clt)
 
 static void print_parameter(int, const char *, char *);
 
-/* print_del_transp_param_default show delivery agent parameter default value */
+/* print_service_param_default show service parameter default value */
 
-static void print_del_transp_param_default(int mode, const char *name,
-                                                  const char *defparam)
+static void print_service_param_default(int mode, const char *name,
+                                               const char *defparam)
 {
-    const char *myname = "print_del_transp_param_default";
+    const char *myname = "print_service_param_default";
     char   *ptr;
 
     if ((ptr = htable_find(param_table, defparam)) == 0)
-       msg_panic("%s: dynamic parameter %s has unknown default value $%s",
+       msg_panic("%s: service parameter %s has unknown default value $%s",
                  myname, name, defparam);
     if (mode & SHOW_EVAL)
        print_parameter(mode, name, ptr);
@@ -1357,20 +1457,20 @@ static void print_del_transp_param_default(int mode, const char *name,
        print_line(mode, "%s = $%s\n", name, defparam);
 }
 
-/* print_del_transp_param - show dynamic delivery agent parameter */
+/* print_service_param - show service parameter */
 
-static void print_del_transp_param(int mode, const char *name,
-                                          const STRING_NV *dst)
+static void print_service_param(int mode, const char *name,
+                                       const STRING_NV *dst)
 {
     const char *value;
 
     if (mode & SHOW_DEFS) {
-       print_del_transp_param_default(mode, name, dst->value);
+       print_service_param_default(mode, name, dst->value);
     } else {
        value = dict_lookup(CONFIG_DICT, name);
        if ((mode & SHOW_NONDEF) == 0) {
            if (value == 0) {
-               print_del_transp_param_default(mode, name, dst->value);
+               print_service_param_default(mode, name, dst->value);
            } else {
                show_strval(mode, name, value);
            }
@@ -1381,9 +1481,9 @@ static void print_del_transp_param(int mode, const char *name,
     }
 }
 
-/* print_rest_class_param - show dynamic restriction class parameter */
+/* print_user_param - show user-defined parameter */
 
-static void print_rest_class_param(int mode, const char *name)
+static void print_user_param(int mode, const char *name)
 {
     const char *value;
 
@@ -1392,7 +1492,7 @@ static void print_rest_class_param(int mode, const char *name)
     } else {
        value = dict_lookup(CONFIG_DICT, name);
        if ((mode & SHOW_NONDEF) == 0) {
-           if (value == 0) {
+           if (value == 0) {                   /* can't happen */
                show_strval(mode, name, "");
            } else {
                show_strval(mode, name, value);
@@ -1435,10 +1535,10 @@ static void print_parameter(int mode, const char *name, char *ptr)
        print_nbool(mode, name, (CONFIG_NBOOL_TABLE *) ptr);
     if (INSIDE(ptr, long_table))
        print_long(mode, name, (CONFIG_LONG_TABLE *) ptr);
-    if (INSIDE3(ptr, del_transp_table, del_transp_tablen))
-       print_del_transp_param(mode, name, (STRING_NV *) ptr);
-    if (INSIDE3(ptr, rest_class_table, rest_class_tablen))
-       print_rest_class_param(mode, name);
+    if (INSIDE3(ptr, serv_param_table, serv_param_tablen))
+       print_service_param(mode, name, (STRING_NV *) ptr);
+    if (INSIDE3(ptr, user_param_table, user_param_tablen))
+       print_user_param(mode, name);
     if (msg_verbose)
        vstream_fflush(VSTREAM_OUT);
 }
@@ -1453,6 +1553,39 @@ static int comp_names(const void *a, const void *b)
     return (strcmp(ap[0]->key, bp[0]->key));
 }
 
+/* show_parameters - show parameter info */
+
+static void show_parameters(int mode, char **names)
+{
+    HTABLE_INFO **list;
+    HTABLE_INFO **ht;
+    char  **namep;
+    char   *value;
+
+    /*
+     * Show all parameters.
+     */
+    if (*names == 0) {
+       list = htable_list(param_table);
+       qsort((char *) list, param_table->used, sizeof(*list), comp_names);
+       for (ht = list; *ht; ht++)
+           print_parameter(mode, ht[0]->key, ht[0]->value);
+       myfree((char *) list);
+       return;
+    }
+
+    /*
+     * Show named parameters.
+     */
+    for (namep = names; *namep; namep++) {
+       if ((value = htable_find(param_table, *namep)) == 0) {
+           msg_warn("%s: unknown parameter", *namep);
+       } else {
+           print_parameter(mode, *namep, value);
+       }
+    }
+}
+
 /* show_maps - show available maps */
 
 static void show_maps(void)
@@ -1594,35 +1727,74 @@ static void show_sasl(int what)
     argv_free(sasl_argv);
 }
 
-/* show_parameters - show parameter info */
+/* flag_unused_main_parameters - warn about unused parameters */
 
-static void show_parameters(int mode, char **names)
+static void flag_unused_main_parameters(void)
 {
-    HTABLE_INFO **list;
-    HTABLE_INFO **ht;
-    char  **namep;
-    char   *value;
+    const char *myname = "flag_unused_main_parameters";
+    DICT   *dict;
+    const char *param_name;
+    const char *param_value;
+    int     how;
 
     /*
-     * Show all parameters.
+     * 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.
      */
-    if (*names == 0) {
-       list = htable_list(param_table);
-       qsort((char *) list, param_table->used, sizeof(*list), comp_names);
-       for (ht = list; *ht; ht++)
-           print_parameter(mode, ht[0]->key, ht[0]->value);
-       myfree((char *) list);
-       return;
+    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, &param_name, &param_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_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;
 
     /*
-     * Show named parameters.
+     * 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 name1=value1" and then used in a "-o name2=$name1" macro
+     * expansion in that same master.cf entry.
      */
-    for (namep = names; *namep; namep++) {
-       if ((value = htable_find(param_table, *namep)) == 0) {
-           msg_warn("%s: unknown parameter", *namep);
-       } else {
-           print_parameter(mode, *namep, value);
+    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, &param_name, &param_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;
+           }
        }
     }
 }
@@ -1821,14 +1993,34 @@ int     main(int argc, char **argv)
            read_parameters();
            set_parameters();
        }
+       hash_parameters();
+
+       /*
+        * Add service-dependent parameters (service names from master.cf)
+        * and user-defined parameters ($name macros in parameter values in
+        * main.cf and master.cf).
+        */
        read_master();
-       add_dynamic_parameters(cmd_mode);
+       add_service_parameters();
+       if ((cmd_mode & SHOW_DEFS) == 0)
+           add_user_parameters();
 
        /*
-        * Throw together all parameters and show the asked values.
+        * Show the requested values.
         */
-       hash_parameters();
        show_parameters(cmd_mode, argv + optind);
+
+       /*
+        * Flag unused parameters. This makes no sense with "postconf -d",
+        * because that ignores all the user-specified parameter values that
+        * may contain macro expansions with user-defined parameter names.
+        */
+#ifdef MAC_EXP_FLAG_SCAN
+       if ((cmd_mode & SHOW_DEFS) == 0) {
+           flag_unused_main_parameters();
+           flag_unused_master_parameters();
+       }
+#endif
     }
     vstream_fflush(VSTREAM_OUT);
     exit(0);
index 049d7c6ee34a1c85cf90626469bce65ca2473ade..c6974b8794466c303e3ef957a74260db3acdcc57 100644 (file)
 /*     data whose origin is untrusted.
 /* .IP MAC_EXP_FLAG_APPEND
 /*     Append text to the result buffer.
+/* .IP MAC_EXP_FLAG_SCAN
+/*     Invoke the call-back function each macro name in the input
+/*     string, including macro names in the values of conditional
+/*     expressions.  Do not expand macros, and do not write to the
+/*     result argument.
 /* .PP
 /*     The constant MAC_EXP_FLAG_NONE specifies a manifest null value.
 /* .RE
@@ -174,17 +179,17 @@ static int mac_expand_callback(int type, VSTRING *buf, char *ptr)
         */
        switch (ch) {
        case '?':
-           if (text != 0 && *text != 0)
+           if ((text != 0 && *text != 0) || (mc->flags & MAC_EXP_FLAG_SCAN))
                mac_parse(cp, mac_expand_callback, (char *) mc);
            break;
        case ':':
-           if (text == 0 || *text == 0)
+           if (text == 0 || *text == 0 || (mc->flags & MAC_EXP_FLAG_SCAN))
                mac_parse(cp, mac_expand_callback, (char *) mc);
            break;
        default:
            if (text == 0) {
                mc->status |= MAC_PARSE_UNDEF;
-           } else if (*text == 0) {
+           } else if (*text == 0 || (mc->flags & MAC_EXP_FLAG_SCAN)) {
                 /* void */ ;
            } else if (mc->flags & MAC_EXP_FLAG_RECURSE) {
                vstring_strcpy(buf, text);
@@ -205,7 +210,7 @@ static int mac_expand_callback(int type, VSTRING *buf, char *ptr)
     /*
      * Literal text.
      */
-    else {
+    else if ((mc->flags & MAC_EXP_FLAG_SCAN) == 0) {
        vstring_strcat(mc->result, vstring_str(buf));
     }
 
@@ -233,10 +238,11 @@ int     mac_expand(VSTRING *result, const char *pattern, int flags,
     mc.context = context;
     mc.status = 0;
     mc.level = 0;
-    if ((flags & MAC_EXP_FLAG_APPEND) == 0)
+    if ((flags & (MAC_EXP_FLAG_APPEND | MAC_EXP_FLAG_SCAN)) == 0)
        VSTRING_RESET(result);
     status = mac_parse(pattern, mac_expand_callback, (char *) &mc);
-    VSTRING_TERMINATE(result);
+    if ((flags & MAC_EXP_FLAG_SCAN) == 0)
+       VSTRING_TERMINATE(result);
 
     return (status);
 }
index 6cd375a39039e0a6cd1eb08902f82287fdcfea5e..f08cd9c862a33ee3d983fca78d03c01b2263320b 100644 (file)
@@ -23,6 +23,7 @@
 #define MAC_EXP_FLAG_NONE      (0)
 #define MAC_EXP_FLAG_RECURSE   (1<<0)
 #define MAC_EXP_FLAG_APPEND    (1<<1)
+#define MAC_EXP_FLAG_SCAN      (1<<2)
 
  /*
   * Real lookup or just a test?