]> git.ipfire.org Git - thirdparty/postfix.git/commitdiff
postfix-2.9-20111108
authorWietse Venema <wietse@porcupine.org>
Tue, 8 Nov 2011 05:00:00 +0000 (00:00 -0500)
committerViktor Dukhovni <viktor@dukhovni.org>
Tue, 5 Feb 2013 06:37:34 +0000 (06:37 +0000)
postfix/.indent.pro
postfix/HISTORY
postfix/conf/master.cf
postfix/src/global/mail_version.h
postfix/src/postconf/Makefile.in
postfix/src/postconf/auto.awk [deleted file]
postfix/src/postconf/postconf.c

index 48488243b4d6fa7fe0e2adb9574d685c550d2342..76ec68cd60b243a4b632ae6f985fbcd8de416518 100644 (file)
 -TDSN_BUF
 -TDSN_SPLIT
 -TDSN_STAT
--TDYNAMIC_TABLE
 -TEDIT_FILE
 -TEVENT_MASK
 -TEXPAND_ATTR
 -TSSL_CTX
 -TSSL_SESSION
 -TSTRING_LIST
+-TSTRING_NV
 -TSTRING_TABLE
 -TSYS_EXITS_DETAIL
 -TTLSMGR_SCACHE
index 72d11daa4ef39ec764bfd859f91a13ecac347f0a..d4ababc45480b96f559aebd5938b30450f4a2dcb 100644 (file)
@@ -17052,3 +17052,13 @@ Apologies for any names omitted.
 
        Feature: postconf "-f" option to "nicely" format long lines
        from main.cf or master.cf. File: postconf/postconf.c.
+
+201108
+
+       Cleanup: postconf finally supports dynamic configuration
+       parameter names: parameters whose name depend on a mail
+       delivery transport name in master.cf, and parameters whose
+       names are specified with smtpd_restriction_classes in
+       main.cf. This adds 70 parameters to the "postconf" output,
+       more if additional mail delivery transports are defined in
+       master.cf.  File: postconf/postconf.c.
index 213f534c9113b2df811a53c8bcfd807b501cf083..e71ac17eed5aa741f23757797604b85ad3951cbf 100644 (file)
@@ -38,9 +38,7 @@ flush     unix  n       -       n       1000?   0       flush
 proxymap  unix  -       -       n       -       -       proxymap
 proxywrite unix -       -       n       -       1       proxymap
 smtp      unix  -       -       n       -       -       smtp
-# When relaying mail as backup MX, disable fallback_relay to avoid MX loops
 relay     unix  -       -       n       -       -       smtp
-       -o smtp_fallback_relay=
 #       -o smtp_helo_timeout=5 -o smtp_connect_timeout=5
 showq     unix  n       -       n       -       -       showq
 error     unix  -       -       n       -       -       error
index 6200634bbddd076a0a5006749f90bcda96f219a5..3db456fda4acf4b942f42981713e74ae569d6819 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      "20111106"
+#define MAIL_RELEASE_DATE      "20111108"
 #define MAIL_VERSION_NUMBER    "2.9"
 
 #ifdef SNAPSHOT
index a6716db8322bccc21072cc1bfe191ca0e542c5c0..48598e8167ef18eea704cb81f09e34c6bdcf9c4e 100644 (file)
@@ -10,8 +10,7 @@ MAKES = bool_table.h bool_vars.h int_table.h int_vars.h str_table.h \
        str_vars.h time_table.h time_vars.h raw_table.h raw_vars.h \
        nint_table.h nint_vars.h nbool_table.h nbool_vars.h long_table.h \
        long_vars.h
-AUTOS  = auto_table.h auto_vars.h
-DUMMIES        = makes_dummy autos_dummy # for "make -j"
+DUMMIES        = makes_dummy # for "make -j"
 PROG   = postconf
 SAMPLES        = ../../conf/main.cf.default
 INC_DIR        = ../../include
@@ -26,8 +25,8 @@ $(PROG): $(OBJS) $(LIBS)
        rm -f $@
        (echo "# DO NOT EDIT THIS FILE. EDIT THE MAIN.CF FILE INSTEAD. THE"; \
         echo "# TEXT HERE JUST SHOWS DEFAULT SETTINGS BUILT INTO POSTFIX."; \
-        echo "#"; \
-        ./$(PROG) -d) |egrep -v '^(myhostname|mydomain|mynetworks) ' >$@
+        echo "#"; ./$(PROG) -d -c ../../conf) | \
+           egrep -v '^(myhostname|mydomain|mynetworks) ' >$@
 
 $(OBJS): ../../conf/makedefs.out
 
@@ -51,12 +50,6 @@ makes_dummy: $(INC_DIR)/mail_params.h ../global/mail_params.c
        $(AWK) -f extract.awk ../*/*.c | $(SHELL)
        touch makes_dummy
 
-$(AUTOS): autos_dummy
-
-autos_dummy: auto.awk
-       $(AWK) -f auto.awk
-       touch autos_dummy
-
 printfck: $(OBJS) $(PROG)
        rm -rf printfck
        mkdir printfck
@@ -99,6 +92,7 @@ postconf.o: ../../include/mail_params.h
 postconf.o: ../../include/mail_proto.h
 postconf.o: ../../include/mail_run.h
 postconf.o: ../../include/mail_version.h
+postconf.o: ../../include/master_proto.h
 postconf.o: ../../include/mbox_conf.h
 postconf.o: ../../include/msg.h
 postconf.o: ../../include/msg_vstream.h
@@ -115,8 +109,6 @@ postconf.o: ../../include/vstream.h
 postconf.o: ../../include/vstring.h
 postconf.o: ../../include/vstring_vstream.h
 postconf.o: ../../include/xsasl.h
-postconf.o: auto_table.h
-postconf.o: auto_vars.h
 postconf.o: bool_table.h
 postconf.o: bool_vars.h
 postconf.o: install_table.h
diff --git a/postfix/src/postconf/auto.awk b/postfix/src/postconf/auto.awk
deleted file mode 100644 (file)
index 74e6401..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
-BEGIN {
-
-    split("local lmtp relay smtp virtual", transports)
-
-    vars["destination_concurrency_failed_cohort_limit"] = "default_destination_concurrency_failed_cohort_limit"
-    vars["destination_concurrency_limit"] = "default_destination_concurrency_limit"
-    vars["destination_concurrency_negative_feedback"] = "default_destination_concurrency_negative_feedback"
-    vars["destination_concurrency_positive_feedback"] = "default_destination_concurrency_positive_feedback"
-    vars["destination_recipient_limit"] = "default_destination_recipient_limit"
-    vars["initial_destination_concurrency"] = "initial_destination_concurrency"
-    vars["destination_rate_delay"] = "default_destination_rate_delay"
-
-    # auto_table.h
-
-    for (var in vars) {
-       for (transport in transports) {
-           if (transports[transport] != "local" || (var != "destination_recipient_limit" && var != "destination_concurrency_limit"))
-               print "\"" transports[transport] "_" var "\", \"$" vars[var] "\", &var_" transports[transport] "_" var ", 0, 0," > "auto_table.h" 
-        }
-       print "" > "auto_table.h"
-    }
-
-    # auto_vars.h
-
-    for (var in vars) {
-       for (transport in transports) {
-           if (transports[transport] != "local" || (var != "destination_recipient_limit" && var != "destination_concurrency_limit"))
-               print "char *var_" transports[transport] "_" var ";" > "auto_vars.h"
-       }
-       print "" > "auto_vars.h"
-    }
-    exit(0)
-}
index e30ced0dcd5d6076a570a5db9eb8b0fc0d6cd767..8c2107c54c056b973a53c3ff1a4049a8461f62b8 100644 (file)
 
 #include <xsasl.h>
 
+/* master library. */
+
+#include <master_proto.h>
+
  /*
   * What we're supposed to be doing.
   */
-#define SHOW_NONDEF    (1<<0)          /* show non-default settings */
-#define SHOW_DEFS      (1<<1)          /* show default setting */
-#define SHOW_NAME      (1<<2)          /* show parameter name */
+#define SHOW_NONDEF    (1<<0)          /* show main.cf non-default settings */
+#define SHOW_DEFS      (1<<1)          /* show main.cf default setting */
+#define SHOW_NAME      (1<<2)          /* show main.cf parameter name */
 #define SHOW_MAPS      (1<<3)          /* show map types */
 #define EDIT_MAIN      (1<<4)          /* edit main.cf */
 #define SHOW_LOCKS     (1<<5)          /* show mailbox lock methods */
@@ -338,7 +342,7 @@ DICT   *text_table;
  /*
   * Lookup table for master.cf info.
   */
-ARGV  **master_table;
+static ARGV **master_table;
 
  /*
   * Declarations generated by scanning actual C source files.
@@ -355,7 +359,6 @@ ARGV  **master_table;
  /*
   * Manually extracted.
   */
-#include "auto_vars.h"
 #include "install_vars.h"
 
  /*
@@ -378,7 +381,6 @@ static const CONFIG_INT_TABLE int_table[] = {
 
 static const CONFIG_STR_TABLE str_table[] = {
 #include "str_table.h"
-#include "auto_table.h"                        /* XXX */
 #include "install_table.h"
     0,
 };
@@ -403,6 +405,30 @@ static const CONFIG_LONG_TABLE long_table[] = {
     0,
 };
 
+ /*
+  * Ad-hoc name-value string pair.
+  */
+typedef struct {
+    const char *name;
+    const char *value;
+} 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.
+  */
+static STRING_NV *del_transp_table;
+static ssize_t del_transp_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.
+  */
+static char **rest_class_table;
+static ssize_t rest_class_tablen;
+
  /*
   * Parameters with default values obtained via function calls.
   */
@@ -674,11 +700,23 @@ static void edit_parameters(int cmd_mode, int argc, char **argv)
     htable_free(table, myfree);
 }
 
+/* set_config_dir - forcibly override var_config_dir */
+
+static void set_config_dir(void)
+{
+    char   *config_dir;
+
+    if (var_config_dir)
+       myfree(var_config_dir);
+    var_config_dir = mystrdup((config_dir = safe_getenv(CONF_ENV_PATH)) != 0 ?
+                             config_dir : DEF_CONFIG_DIR);     /* XXX */
+    set_mail_conf_str(VAR_CONFIG_DIR, var_config_dir);
+}
+
 /* read_parameters - read parameter info from file */
 
 static void read_parameters(void)
 {
-    char   *config_dir;
     char   *path;
 
     /*
@@ -686,11 +724,7 @@ static void read_parameters(void)
      * better code decomposition.
      */
     dict_unknown_allowed = 1;
-    if (var_config_dir)
-       myfree(var_config_dir);
-    var_config_dir = mystrdup((config_dir = safe_getenv(CONF_ENV_PATH)) != 0 ?
-                             config_dir : DEF_CONFIG_DIR);     /* XXX */
-    set_mail_conf_str(VAR_CONFIG_DIR, var_config_dir);
+    set_config_dir();
     path = concatenate(var_config_dir, "/", "main.cf", (char *) 0);
     dict_load_file(CONFIG_DICT, path);
     myfree(path);
@@ -720,6 +754,146 @@ static void set_parameters(void)
      */
 }
 
+ /*
+  * Basename of programs in $daemon_directory. XXX These belong in a header
+  * file, or they should be made configurable.
+  */
+#ifndef MAIL_PROGRAM_LOCAL
+#define MAIL_PROGRAM_LOCAL     "local"
+#define MAIL_PROGRAM_ERROR     "error"
+#define MAIL_PROGRAM_VIRTUAL   "virtual"
+#define MAIL_PROGRAM_SMTP      "smtp"
+#define MAIL_PROGRAM_LMTP      "lmtp"
+#define MAIL_PROGRAM_PIPE      "pipe"
+#define MAIL_PROGRAM_SPAWN     "spawn"
+#endif
+
+/* add_restriction_class - add one smtpd_restriction_classes name */
+
+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,
+                                         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;
+}
+
+/* add_dynamic_parameters - add all dynamic parameters with defaults */
+
+static void add_dynamic_parameters(int mode)
+{
+    /* XXX Should this list be configurable? */
+    static const char *delivery_agents[] = {
+       MAIL_PROGRAM_LOCAL, MAIL_PROGRAM_ERROR,
+       MAIL_PROGRAM_VIRTUAL, MAIL_PROGRAM_SMTP,
+       MAIL_PROGRAM_LMTP, MAIL_PROGRAM_PIPE,
+       0,
+    };
+    static const STRING_NV del_transp_params[] = {
+       /* suffix, default parameter name */
+       _XPORT_RCPT_LIMIT, VAR_XPORT_RCPT_LIMIT,
+       _STACK_RCPT_LIMIT, VAR_STACK_RCPT_LIMIT,
+       _XPORT_REFILL_LIMIT, VAR_XPORT_REFILL_LIMIT,
+       _XPORT_REFILL_DELAY, VAR_XPORT_REFILL_DELAY,
+       _DELIVERY_SLOT_COST, VAR_DELIVERY_SLOT_COST,
+       _DELIVERY_SLOT_LOAN, VAR_DELIVERY_SLOT_LOAN,
+       _DELIVERY_SLOT_DISCOUNT, VAR_DELIVERY_SLOT_DISCOUNT,
+       _MIN_DELIVERY_SLOTS, VAR_MIN_DELIVERY_SLOTS,
+       _INIT_DEST_CON, VAR_INIT_DEST_CON,
+       _DEST_CON_LIMIT, VAR_DEST_CON_LIMIT,
+       _DEST_RCPT_LIMIT, VAR_DEST_RCPT_LIMIT,
+       _CONC_POS_FDBACK, VAR_CONC_POS_FDBACK,
+       _CONC_NEG_FDBACK, VAR_CONC_NEG_FDBACK,
+       _CONC_COHORT_LIM, VAR_CONC_COHORT_LIM,
+       _DEST_RATE_DELAY, VAR_DEST_RATE_DELAY,
+       0,
+    };
+    static const STRING_NV spawn_params[] = {
+       /* suffix, default parameter name */
+       _MAXTIME, VAR_COMMAND_MAXTIME,
+       0,
+    };
+    const STRING_NV *sp;
+    const char *progname;
+    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.
+     */
+    del_transp_table = (STRING_NV *) mymalloc(1);
+    del_transp_tablen = 0;
+
+    rest_class_table = (char **) mymalloc(1);
+    rest_class_tablen = 0;
+
+    /*
+     * Extract message delivery transport names from master.cf and generate
+     * dynamic parameter information.
+     */
+    for (argvp = master_table; (argv = *argvp) != 0; argvp++) {
+
+       /*
+        * Skip all endpoints except UNIX-domain sockets.
+        */
+       if (strcmp(argv->argv[1], MASTER_XPORT_NAME_UNIX) != 0)
+           continue;
+
+       /*
+        * Add dynamic 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);
+           continue;
+       }
+
+       /*
+        * Add dynamic parameters for spawn(8)-based services.
+        */
+       if (strcmp(MAIL_PROGRAM_SPAWN, progname) == 0) {
+           for (sp = spawn_params; sp->name; sp++)
+               add_dynamic_parameter(argv->argv[0], sp->name, sp->value);
+           continue;
+       }
+    }
+
+    /*
+     * Add parameters specified with smtpd_restriction_classes.
+     */
+    if ((mode & SHOW_DEFS) == 0
+       && (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);
+       myfree(saved_class_list);
+    }
+}
+
 /* hash_parameters - hash all parameter names so we can find and sort them */
 
 static void hash_parameters(void)
@@ -733,9 +907,14 @@ 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++)
@@ -756,19 +935,32 @@ 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);
 }
 
 /* read_master - read and digest the master.cf file */
 
 static void read_master(void)
 {
-    char   *path = concatenate(var_config_dir, "/", MASTER_CONF_FILE, (char *) 0);
+    char   *path;
     VSTRING *buf = vstring_alloc(100);
     ARGV   *argv;
     VSTREAM *fp;
     int     entry_count = 0;
     int     line_count = 0;
 
+    /*
+     * Get the location of master.cf.
+     */
+    if (var_config_dir == 0)
+       set_config_dir();
+    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.
@@ -894,145 +1086,145 @@ static void show_longval(int mode, const char *name, long value)
 
 /* print_bool - print boolean parameter */
 
-static void print_bool(int mode, CONFIG_BOOL_TABLE *cbt)
+static void print_bool(int mode, const char *name, CONFIG_BOOL_TABLE *cbt)
 {
     const char *value;
 
     if (mode & SHOW_DEFS) {
-       show_strval(mode, cbt->name, cbt->defval ? "yes" : "no");
+       show_strval(mode, name, cbt->defval ? "yes" : "no");
     } else {
-       value = dict_lookup(CONFIG_DICT, cbt->name);
+       value = dict_lookup(CONFIG_DICT, name);
        if ((mode & SHOW_NONDEF) == 0) {
            if (value == 0) {
-               show_strval(mode, cbt->name, cbt->defval ? "yes" : "no");
+               show_strval(mode, name, cbt->defval ? "yes" : "no");
            } else {
-               show_strval(mode, cbt->name, value);
+               show_strval(mode, name, value);
            }
        } else {
            if (value != 0)
-               show_strval(mode, cbt->name, value);
+               show_strval(mode, name, value);
        }
     }
 }
 
 /* print_time - print relative time parameter */
 
-static void print_time(int mode, CONFIG_TIME_TABLE *ctt)
+static void print_time(int mode, const char *name, CONFIG_TIME_TABLE *ctt)
 {
     const char *value;
 
     if (mode & SHOW_DEFS) {
-       show_strval(mode, ctt->name, ctt->defval);
+       show_strval(mode, name, ctt->defval);
     } else {
-       value = dict_lookup(CONFIG_DICT, ctt->name);
+       value = dict_lookup(CONFIG_DICT, name);
        if ((mode & SHOW_NONDEF) == 0) {
            if (value == 0) {
-               show_strval(mode, ctt->name, ctt->defval);
+               show_strval(mode, name, ctt->defval);
            } else {
-               show_strval(mode, ctt->name, value);
+               show_strval(mode, name, value);
            }
        } else {
            if (value != 0)
-               show_strval(mode, ctt->name, value);
+               show_strval(mode, name, value);
        }
     }
 }
 
 /* print_int - print integer parameter */
 
-static void print_int(int mode, CONFIG_INT_TABLE *cit)
+static void print_int(int mode, const char *name, CONFIG_INT_TABLE *cit)
 {
     const char *value;
 
     if (mode & SHOW_DEFS) {
-       show_intval(mode, cit->name, cit->defval);
+       show_intval(mode, name, cit->defval);
     } else {
-       value = dict_lookup(CONFIG_DICT, cit->name);
+       value = dict_lookup(CONFIG_DICT, name);
        if ((mode & SHOW_NONDEF) == 0) {
            if (value == 0) {
-               show_intval(mode, cit->name, cit->defval);
+               show_intval(mode, name, cit->defval);
            } else {
-               show_strval(mode, cit->name, value);
+               show_strval(mode, name, value);
            }
        } else {
            if (value != 0)
-               show_strval(mode, cit->name, value);
+               show_strval(mode, name, value);
        }
     }
 }
 
 /* print_str - print string parameter */
 
-static void print_str(int mode, CONFIG_STR_TABLE *cst)
+static void print_str(int mode, const char *name, CONFIG_STR_TABLE *cst)
 {
     const char *value;
 
     if (mode & SHOW_DEFS) {
-       show_strval(mode, cst->name, cst->defval);
+       show_strval(mode, name, cst->defval);
     } else {
-       value = dict_lookup(CONFIG_DICT, cst->name);
+       value = dict_lookup(CONFIG_DICT, name);
        if ((mode & SHOW_NONDEF) == 0) {
            if (value == 0) {
-               show_strval(mode, cst->name, cst->defval);
+               show_strval(mode, name, cst->defval);
            } else {
-               show_strval(mode, cst->name, value);
+               show_strval(mode, name, value);
            }
        } else {
            if (value != 0)
-               show_strval(mode, cst->name, value);
+               show_strval(mode, name, value);
        }
     }
 }
 
 /* print_str_fn - print string-function parameter */
 
-static void print_str_fn(int mode, CONFIG_STR_FN_TABLE *csft)
+static void print_str_fn(int mode, const char *name, CONFIG_STR_FN_TABLE *csft)
 {
     const char *value;
 
     if (mode & SHOW_DEFS) {
-       show_strval(mode, csft->name, csft->defval());
+       show_strval(mode, name, csft->defval());
     } else {
-       value = dict_lookup(CONFIG_DICT, csft->name);
+       value = dict_lookup(CONFIG_DICT, name);
        if ((mode & SHOW_NONDEF) == 0) {
            if (value == 0) {
-               show_strval(mode, csft->name, csft->defval());
+               show_strval(mode, name, csft->defval());
            } else {
-               show_strval(mode, csft->name, value);
+               show_strval(mode, name, value);
            }
        } else {
            if (value != 0)
-               show_strval(mode, csft->name, value);
+               show_strval(mode, name, value);
        }
     }
 }
 
 /* print_str_fn_2 - print string-function parameter */
 
-static void print_str_fn_2(int mode, CONFIG_STR_FN_TABLE *csft)
+static void print_str_fn_2(int mode, const char *name, CONFIG_STR_FN_TABLE *csft)
 {
     const char *value;
 
     if (mode & SHOW_DEFS) {
-       show_strval(mode, csft->name, csft->defval());
+       show_strval(mode, name, csft->defval());
     } else {
-       value = dict_lookup(CONFIG_DICT, csft->name);
+       value = dict_lookup(CONFIG_DICT, name);
        if ((mode & SHOW_NONDEF) == 0) {
            if (value == 0) {
-               show_strval(mode, csft->name, csft->defval());
+               show_strval(mode, name, csft->defval());
            } else {
-               show_strval(mode, csft->name, value);
+               show_strval(mode, name, value);
            }
        } else {
            if (value != 0)
-               show_strval(mode, csft->name, value);
+               show_strval(mode, name, value);
        }
     }
 }
 
 /* print_raw - print raw string parameter */
 
-static void print_raw(int mode, CONFIG_RAW_TABLE *rst)
+static void print_raw(int mode, const char *name, CONFIG_RAW_TABLE *rst)
 {
     const char *value;
 
@@ -1041,129 +1233,200 @@ static void print_raw(int mode, CONFIG_RAW_TABLE *rst)
     mode &= ~SHOW_EVAL;
 
     if (mode & SHOW_DEFS) {
-       show_strval(mode, rst->name, rst->defval);
+       show_strval(mode, name, rst->defval);
     } else {
-       value = dict_lookup(CONFIG_DICT, rst->name);
+       value = dict_lookup(CONFIG_DICT, name);
        if ((mode & SHOW_NONDEF) == 0) {
            if (value == 0) {
-               show_strval(mode, rst->name, rst->defval);
+               show_strval(mode, name, rst->defval);
            } else {
-               show_strval(mode, rst->name, value);
+               show_strval(mode, name, value);
            }
        } else {
            if (value != 0)
-               show_strval(mode, rst->name, value);
+               show_strval(mode, name, value);
        }
     }
 }
 
 /* print_nint - print new integer parameter */
 
-static void print_nint(int mode, CONFIG_NINT_TABLE *rst)
+static void print_nint(int mode, const char *name, CONFIG_NINT_TABLE *rst)
 {
     const char *value;
 
     if (mode & SHOW_EVAL)
-       msg_warn("parameter %s expands at run-time", rst->name);
+       msg_warn("parameter %s expands at run-time", name);
     mode &= ~SHOW_EVAL;
 
     if (mode & SHOW_DEFS) {
-       show_strval(mode, rst->name, rst->defval);
+       show_strval(mode, name, rst->defval);
     } else {
-       value = dict_lookup(CONFIG_DICT, rst->name);
+       value = dict_lookup(CONFIG_DICT, name);
        if ((mode & SHOW_NONDEF) == 0) {
            if (value == 0) {
-               show_strval(mode, rst->name, rst->defval);
+               show_strval(mode, name, rst->defval);
            } else {
-               show_strval(mode, rst->name, value);
+               show_strval(mode, name, value);
            }
        } else {
            if (value != 0)
-               show_strval(mode, rst->name, value);
+               show_strval(mode, name, value);
        }
     }
 }
 
 /* print_nbool - print new boolean parameter */
 
-static void print_nbool(int mode, CONFIG_NBOOL_TABLE *bst)
+static void print_nbool(int mode, const char *name, CONFIG_NBOOL_TABLE *bst)
 {
     const char *value;
 
     if (mode & SHOW_EVAL)
-       msg_warn("parameter %s expands at run-time", bst->name);
+       msg_warn("parameter %s expands at run-time", name);
     mode &= ~SHOW_EVAL;
 
     if (mode & SHOW_DEFS) {
-       show_strval(mode, bst->name, bst->defval);
+       show_strval(mode, name, bst->defval);
     } else {
-       value = dict_lookup(CONFIG_DICT, bst->name);
+       value = dict_lookup(CONFIG_DICT, name);
        if ((mode & SHOW_NONDEF) == 0) {
            if (value == 0) {
-               show_strval(mode, bst->name, bst->defval);
+               show_strval(mode, name, bst->defval);
            } else {
-               show_strval(mode, bst->name, value);
+               show_strval(mode, name, value);
            }
        } else {
            if (value != 0)
-               show_strval(mode, bst->name, value);
+               show_strval(mode, name, value);
        }
     }
 }
 
 /* print_long - print long parameter */
 
-static void print_long(int mode, CONFIG_LONG_TABLE *clt)
+static void print_long(int mode, const char *name, CONFIG_LONG_TABLE *clt)
 {
     const char *value;
 
     if (mode & SHOW_DEFS) {
-       show_longval(mode, clt->name, clt->defval);
+       show_longval(mode, name, clt->defval);
     } else {
-       value = dict_lookup(CONFIG_DICT, clt->name);
+       value = dict_lookup(CONFIG_DICT, name);
        if ((mode & SHOW_NONDEF) == 0) {
            if (value == 0) {
-               show_longval(mode, clt->name, clt->defval);
+               show_longval(mode, name, clt->defval);
            } else {
-               show_strval(mode, clt->name, value);
+               show_strval(mode, name, value);
            }
        } else {
            if (value != 0)
-               show_strval(mode, clt->name, value);
+               show_strval(mode, name, value);
+       }
+    }
+}
+
+static void print_parameter(int, const char *, char *);
+
+/* print_del_transp_param_default show delivery agent parameter default value */
+
+static void print_del_transp_param_default(int mode, const char *name,
+                                                  const char *defparam)
+{
+    const char *myname = "print_del_transp_param_default";
+    char   *ptr;
+
+    if ((ptr = htable_find(param_table, defparam)) == 0)
+       msg_panic("%s: dynamic parameter %s has unknown default value $%s",
+                 myname, name, defparam);
+    if (mode & SHOW_EVAL)
+       print_parameter(mode, name, ptr);
+    else
+       print_line(mode, "%s = $%s\n", name, defparam);
+}
+
+/* print_del_transp_param - show dynamic delivery agent parameter */
+
+static void print_del_transp_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);
+    } else {
+       value = dict_lookup(CONFIG_DICT, name);
+       if ((mode & SHOW_NONDEF) == 0) {
+           if (value == 0) {
+               print_del_transp_param_default(mode, name, dst->value);
+           } else {
+               show_strval(mode, name, value);
+           }
+       } else {
+           if (value != 0)
+               show_strval(mode, name, value);
+       }
+    }
+}
+
+/* print_rest_class_param - show dynamic parameter */
+
+static void print_rest_class_param(int mode, const char *name)
+{
+    const char *value;
+
+    if (mode & SHOW_DEFS) {                    /* can't happen */
+       show_strval(mode, name, "");
+    } else {
+       value = dict_lookup(CONFIG_DICT, name);
+       if ((mode & SHOW_NONDEF) == 0) {
+           if (value == 0) {
+               show_strval(mode, name, "");
+           } else {
+               show_strval(mode, name, value);
+           }
+       } else {
+           if (value != 0)
+               show_strval(mode, name, value);
        }
     }
 }
 
 /* print_parameter - show specific parameter */
 
-static void print_parameter(int mode, char *ptr)
+static void print_parameter(int mode, const char *name, char *ptr)
 {
 
 #define INSIDE(p,t) (ptr >= (char *) t && ptr < ((char *) t) + sizeof(t))
+#define INSIDE3(p,t,l) (ptr >= (char *) t && ptr < (char *) ((t) + (l)))
 
     /*
      * This is gross, but the best we can do on short notice.
      */
     if (INSIDE(ptr, time_table))
-       print_time(mode, (CONFIG_TIME_TABLE *) ptr);
+       print_time(mode, name, (CONFIG_TIME_TABLE *) ptr);
     if (INSIDE(ptr, bool_table))
-       print_bool(mode, (CONFIG_BOOL_TABLE *) ptr);
+       print_bool(mode, name, (CONFIG_BOOL_TABLE *) ptr);
     if (INSIDE(ptr, int_table))
-       print_int(mode, (CONFIG_INT_TABLE *) ptr);
+       print_int(mode, name, (CONFIG_INT_TABLE *) ptr);
     if (INSIDE(ptr, str_table))
-       print_str(mode, (CONFIG_STR_TABLE *) ptr);
+       print_str(mode, name, (CONFIG_STR_TABLE *) ptr);
     if (INSIDE(ptr, str_fn_table))
-       print_str_fn(mode, (CONFIG_STR_FN_TABLE *) ptr);
+       print_str_fn(mode, name, (CONFIG_STR_FN_TABLE *) ptr);
     if (INSIDE(ptr, str_fn_table_2))
-       print_str_fn_2(mode, (CONFIG_STR_FN_TABLE *) ptr);
+       print_str_fn_2(mode, name, (CONFIG_STR_FN_TABLE *) ptr);
     if (INSIDE(ptr, raw_table))
-       print_raw(mode, (CONFIG_RAW_TABLE *) ptr);
+       print_raw(mode, name, (CONFIG_RAW_TABLE *) ptr);
     if (INSIDE(ptr, nint_table))
-       print_nint(mode, (CONFIG_NINT_TABLE *) ptr);
+       print_nint(mode, name, (CONFIG_NINT_TABLE *) ptr);
     if (INSIDE(ptr, nbool_table))
-       print_nbool(mode, (CONFIG_NBOOL_TABLE *) ptr);
+       print_nbool(mode, name, (CONFIG_NBOOL_TABLE *) ptr);
     if (INSIDE(ptr, long_table))
-       print_long(mode, (CONFIG_LONG_TABLE *) ptr);
+       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 (msg_verbose)
        vstream_fflush(VSTREAM_OUT);
 }
@@ -1335,7 +1598,7 @@ static void show_parameters(int mode, char **names)
        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]->value);
+           print_parameter(mode, ht[0]->key, ht[0]->value);
        myfree((char *) list);
        return;
     }
@@ -1347,7 +1610,7 @@ static void show_parameters(int mode, char **names)
        if ((value = htable_find(param_table, *namep)) == 0) {
            msg_warn("%s: unknown parameter", *namep);
        } else {
-           print_parameter(mode, value);
+           print_parameter(mode, *namep, value);
        }
     }
 }
@@ -1515,7 +1778,6 @@ int     main(int argc, char **argv)
      * If showing master.cf entries, show them and exit
      */
     else if (cmd_mode & SHOW_MASTER) {
-       mail_conf_read();
        read_master();
        show_master(cmd_mode);
     }
@@ -1547,6 +1809,8 @@ int     main(int argc, char **argv)
            read_parameters();
            set_parameters();
        }
+       read_master();
+       add_dynamic_parameters(cmd_mode);
 
        /*
         * Throw together all parameters and show the asked values.