]> git.ipfire.org Git - thirdparty/postfix.git/commitdiff
postfix-2.10-20121224
authorWietse Venema <wietse@porcupine.org>
Mon, 24 Dec 2012 05:00:00 +0000 (00:00 -0500)
committerViktor Dukhovni <viktor@dukhovni.org>
Tue, 5 Feb 2013 06:38:23 +0000 (06:38 +0000)
30 files changed:
postfix/.indent.pro
postfix/HISTORY
postfix/RELEASE_NOTES
postfix/html/postconf.1.html
postfix/man/man1/postconf.1
postfix/src/global/mail_version.h
postfix/src/postconf/Makefile.in
postfix/src/postconf/extract.awk
postfix/src/postconf/postconf.c
postfix/src/postconf/postconf.h
postfix/src/postconf/postconf_builtin.c
postfix/src/postconf/postconf_dbms.c
postfix/src/postconf/postconf_lookup.c [new file with mode: 0644]
postfix/src/postconf/postconf_main.c
postfix/src/postconf/postconf_master.c
postfix/src/postconf/postconf_node.c
postfix/src/postconf/postconf_user.c
postfix/src/postconf/test1.ref
postfix/src/postconf/test20.ref
postfix/src/postconf/test28.ref
postfix/src/postconf/test29.ref
postfix/src/postconf/test34.ref [new file with mode: 0644]
postfix/src/postconf/test35.ref [new file with mode: 0644]
postfix/src/postconf/test36.ref [new file with mode: 0644]
postfix/src/postconf/test37.ref [new file with mode: 0644]
postfix/src/postconf/test38.ref [new file with mode: 0644]
postfix/src/postconf/test39.ref [new file with mode: 0644]
postfix/src/util/dict_ht.c
postfix/src/util/htable.c
postfix/src/util/htable.h

index b7ea3324ccc8e278e05b61c27751a5daf8dcdfb9..204f673d7a6a65a3f61257498df32d06cb803ab4 100644 (file)
 -TPC_DBMS_INFO
 -TPC_EVAL_CTX
 -TPC_MASTER_ENT
+-TPC_PARAM_CTX
 -TPC_PARAM_NODE
 -TPC_SERVICE_DEF
 -TPC_STRING_NV
index 2c8b8713e4e10330e7d73ff6aebd862b9a75febd..8cabbf7357f661eb3e6af84075a675f20c826ea0 100644 (file)
@@ -18152,6 +18152,32 @@ Apologies for any names omitted.
 
 20121221
 
-       Feature: "postconf -x" support to expand $nama in parameter
-       values. Files: postconf/postconf_main.c, postconf/postconf.h,
-       postconf/postconf_node.c, postconf/postconf.c.
+       Feature: "postconf -x" support to expand $name in main.cf
+       parameter values. Files: postconf/postconf_main.c,
+       postconf/postconf.h, postconf/postconf_node.c, postconf/postconf.c.
+
+20121222
+
+       Feature: postconf support to warn about an attempt to modify
+       a read-only parameter (process_name etc.) in main.cf or
+       master.cf. Files: postconf/postconf_readonly.c,
+       postconf/postconf_builtin.c.
+
+20121223
+
+       Feature: postconf support to warn about an undefined $name
+       in a parameter value in main.cf or master.cf (except for
+       backwards-compatibility parameters such as $virtual_maps)
+       Files: postconf/postconf_user.c, postconf_dbms.c,
+       postconf_builtin.c, util/dict_ht.c, util/htable.c.
+
+       Feature: "postconf -Mx" support to expand $name in master.cf
+       parameter values.  Files: postconf/postconf_master.c,
+       postconf/postconf_lookup.c, postconf/postconf_main.c,
+       postconf/postconf.c.
+
+20121224
+
+       Feature: "postconf -Mn" support to print only master.cf
+       entries that have "-o name=value" parameter setttings.
+       Files: postconf/postconf_master.c.
index dfb95f1f216ad6b2f1fe28899c87c6b242be520e..ccd464e8301e46f7009ee47c32f9cbf99748f98a 100644 (file)
@@ -14,6 +14,38 @@ specifies the release date of a stable release or snapshot release.
 If you upgrade from Postfix 2.8 or earlier, read RELEASE_NOTES-2.9
 before proceeding.
 
+Incompatible changes with snapshot 20121224
+===========================================
+
+The postconf command produces more warnings:
+
+- An attempt to modify a read-only parameter (process_name, process_id)
+  in main.cf or master.cf.
+
+- An undefined $name in a parameter value in main.cf or master.cf
+  (except for backwards-compatibility parameters such as $virtual_maps).
+
+Major changes with snapshot 20121224
+====================================
+
+The postconf command has been updated to make trouble-shooting (and
+support) easier. In summary, use "postconf -Mnxf" and "postconf
+-nxf" to review master.cf and main.cf parameter settings with
+expanded parameter values.
+
+- "postconf -x" now expands $name in main.cf and master.cf parameter
+  values.
+
+- "postconf -Mn" now shows only master.cf entries with "-o name=value"
+  parameter settings.
+
+- postconf warns about attempts to modify a read-only parameter
+  (process_name, process_id) in main.cf or master.cf.
+
+- postconf warns about an undefined $name in a parameter value in
+  main.cf or master.cf (except for backwards-compatibility parameters
+  such as $virtual_maps).
+
 Incompatible changes with snapshot 20121123
 ===========================================
 
@@ -58,7 +90,6 @@ actions:
 
 There is no need to change the value of smtpd_recipient_restrictions.
 
-
 Major changes with snapshot 20121007
 ====================================
 
index 8b7afa1e4b90117d15e941618625ba4ff60f5ad8..3c7f55962845bacc33a870629931a0e174944027 100644 (file)
@@ -21,7 +21,7 @@ POSTCONF(1)                                                        POSTCONF(1)
 
        <b>Managing <a href="master.5.html">master.cf</a>:</b>
 
-       <b>postconf</b> [<b>-fMv</b>] [<b>-c</b> <i>config</i><b>_</b><i>dir</i>] [<i>service ...</i>]
+       <b>postconf</b> [<b>-fMnvx</b>] [<b>-c</b> <i>config</i><b>_</b><i>dir</i>] [<i>service ...</i>]
 
        <b>Managing bounce message templates:</b>
 
@@ -295,10 +295,12 @@ POSTCONF(1)                                                        POSTCONF(1)
               This  feature  is  available  with  Postfix 2.9 and
               later.
 
-       <b>-n</b>     Print <a href="postconf.5.html"><b>main.cf</b></a> parameter settings that  are  explic-
-              itly  specified  in  <a href="postconf.5.html"><b>main.cf</b></a>.   Specify <b>-nf</b> to fold
-              long lines for human readability (Postfix  2.9  and
-              later).
+       <b>-n</b>     Print only <i>name</i>=<i>value</i> parameter settings  that  are
+              explicitly  specified  in  <a href="postconf.5.html"><b>main.cf</b></a>.  When specified
+              with <b>-M</b>, print only <a href="master.5.html"><b>master.cf</b></a> entries that have "-o
+              <i>name</i>=<i>value</i>"  parameter  settings  (Postfix 2.10 and
+              later).  Specify <b>-nf</b> to fold long lines  for  human
+              readability (Postfix 2.9 and later).
 
        <b>-t</b> [<i>template</i><b>_</b><i>file</i>]
               Display  the templates for text that appears at the
@@ -321,29 +323,32 @@ POSTCONF(1)                                                        POSTCONF(1)
               tiple <b>-v</b> options  make  the  software  increasingly
               verbose.
 
-       <b>-x</b>     Expand  <i>$name</i> in parameter values. The expansion is
-              recursive.
+       <b>-x</b>     Expand <i>$name</i> in <a href="postconf.5.html"><b>main.cf</b></a> or <a href="master.5.html"><b>master.cf</b></a> parameter val-
+              ues. The expansion is recursive.
+
+              This feature is available  with  Postfix  2.10  and
+              later.
 
        <b>-X</b>     Edit the <a href="postconf.5.html"><b>main.cf</b></a> configuration file, and remove the
-              parameters  named  on the <a href="postconf.1.html"><b>postconf</b>(1)</a> command line.
+              parameters named on the <a href="postconf.1.html"><b>postconf</b>(1)</a>  command  line.
               The file is copied to a temporary file then renamed
               into place.  Specify a list of parameter names, not
-              "<i>name</i>=<i>value</i>" pairs.  There is no  <a href="postconf.1.html"><b>postconf</b>(1)</a>  com-
+              "<i>name</i>=<i>value</i>"  pairs.   There is no <a href="postconf.1.html"><b>postconf</b>(1)</a> com-
               mand to perform the reverse operation.
 
-              This  feature  is  available  with Postfix 2.10 and
+              This feature is available  with  Postfix  2.10  and
               later.
 
-       <b>-#</b>     Edit the <a href="postconf.5.html"><b>main.cf</b></a> configuration  file,  and  comment
+       <b>-#</b>     Edit  the  <a href="postconf.5.html"><b>main.cf</b></a>  configuration file, and comment
               out the parameters named on the <a href="postconf.1.html"><b>postconf</b>(1)</a> command
-              line, so that  those  parameters  revert  to  their
-              default  values.  The file is copied to a temporary
-              file then renamed into place.  Specify  a  list  of
-              parameter  names, not "<i>name</i>=<i>value</i>" pairs.  There is
+              line,  so  that  those  parameters  revert to their
+              default values.  The file is copied to a  temporary
+              file  then  renamed  into place.  Specify a list of
+              parameter names, not "<i>name</i>=<i>value</i>" pairs.  There  is
               no <a href="postconf.1.html"><b>postconf</b>(1)</a> command to perform the reverse oper-
               ation.
 
-              This  feature  is  available  with  Postfix 2.6 and
+              This feature is  available  with  Postfix  2.6  and
               later.
 
 <b>DIAGNOSTICS</b>
@@ -354,18 +359,18 @@ POSTCONF(1)                                                        POSTCONF(1)
               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>
@@ -381,7 +386,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>
index 4fca7a677cd4bf82f29e0db47be4e2bcc52dcf4b..a9903f4ca8d084a5eb6c53f218d530de99f5c279 100644 (file)
@@ -22,7 +22,7 @@ Postfix configuration utility
 
 \fBManaging master.cf:\fR
 
-\fBpostconf\fR [\fB-fMv\fR] [\fB-c \fIconfig_dir\fR]
+\fBpostconf\fR [\fB-fMnvx\fR] [\fB-c \fIconfig_dir\fR]
 [\fIservice ...\fR]
 
 \fBManaging bounce message templates:\fR
@@ -259,8 +259,11 @@ or with a \fIservice-name.service-type\fR pair, where
 
 This feature is available with Postfix 2.9 and later.
 .IP \fB-n\fR
-Print \fBmain.cf\fR parameter settings that are explicitly
-specified in \fBmain.cf\fR.
+Print only \fIname\fR=\fIvalue\fR parameter settings that
+are explicitly specified in \fBmain.cf\fR. When specified
+with \fB-M\fR, print only \fBmaster.cf\fR entries that have
+"-o \fIname\fR=\fIvalue\fR" parameter settings (Postfix
+2.10 and later).
 Specify \fB-nf\fR to fold long lines for human readability
 (Postfix 2.9 and later).
 .IP "\fB-t\fR [\fItemplate_file\fR]"
@@ -282,8 +285,10 @@ This feature is available with Postfix 2.3 and later.
 Enable verbose logging for debugging purposes. Multiple \fB-v\fR
 options make the software increasingly verbose.
 .IP \fB-x\fR
-Expand \fI$name\fR in parameter values. The expansion is
-recursive.
+Expand \fI$name\fR in \fBmain.cf\fR or \fBmaster.cf\fR
+parameter values. The expansion is recursive.
+
+This feature is available with Postfix 2.10 and later.
 .IP \fB-X\fR
 Edit the \fBmain.cf\fR configuration file, and remove
 the parameters named on the \fBpostconf\fR(1) command line.
index 55f0b5d65831939977122aad2308e973628c3a9a..d3bbd539a8c19c099788c38beee34695fe0aed6a 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      "20121221"
+#define MAIL_RELEASE_DATE      "20121224"
 #define MAIL_VERSION_NUMBER    "2.10"
 
 #ifdef SNAPSHOT
index 18474fd5dbbe8f1456d7205e315d4d49ce414053..6b44aa6773949e7648f8f22b1c6d951cea454f69 100644 (file)
@@ -1,10 +1,12 @@
 SHELL  = /bin/sh
 SRCS   = postconf.c postconf_builtin.c postconf_edit.c postconf_main.c \
        postconf_master.c postconf_misc.c postconf_node.c postconf_other.c \
-       postconf_service.c postconf_unused.c postconf_user.c postconf_dbms.c
+       postconf_service.c postconf_unused.c postconf_user.c postconf_dbms.c \
+       postconf_lookup.c
 OBJS   = postconf.o postconf_builtin.o postconf_edit.o postconf_main.o \
        postconf_master.o postconf_misc.o postconf_node.o postconf_other.o \
-       postconf_service.o postconf_unused.o postconf_user.o postconf_dbms.o
+       postconf_service.o postconf_unused.o postconf_user.o postconf_dbms.o \
+       postconf_lookup.o
 HDRS   = postconf.h
 TESTSRC        =
 DEFS   = -I. -I$(INC_DIR) -D$(SYSTYPE)
@@ -13,7 +15,7 @@ TESTPROG=
 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
+       long_vars.h str_fn_table.h str_fn_vars.h
 TEST_TMP= main.cf master.cf test*.tmp
 DUMMIES        = makes_dummy # for "make -j"
 PROG   = postconf
@@ -31,7 +33,7 @@ $(PROG): $(OBJS) $(LIBS)
        (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 -c ../../conf) | \
-           egrep -v '^(myhostname|mydomain|mynetworks) ' >$@
+           egrep -v '^(myhostname|mydomain|mynetworks|process_name|process_id) ' >$@
 
 $(OBJS): ../../conf/makedefs.out
 
@@ -43,7 +45,7 @@ test: $(TESTPROG)
 tests: test1 test2 test3 test4 test5 test6 test7 test8 test9 test10 test11 \
        test12 test13 test14 test15 test16 test17 test18 test19 test20 test21 \
        test22 test23 test24 test25 test26 test27 test28 test29 test30 test4b \
-       test31 test32 test33
+       test31 test32 test33 test34 test35 test36 test37 test38 test39
 
 root_tests:
 
@@ -375,7 +377,7 @@ test27:     $(PROG) test27.ref
 test28:        $(PROG) test28.ref
        rm -f main.cf master.cf
        touch main.cf master.cf
-       echo 'xx = proxy:ldap:foo' >> main.cf
+       echo 'xx = ldap:foo' >> main.cf
        echo 'foo_domain = bar' >> main.cf
        echo 'header_checks = ldap:hh' >> main.cf
        echo 'hh_domain = whatever' >> main.cf
@@ -395,19 +397,19 @@ test28:   $(PROG) test28.ref
 test29:        $(PROG) test29.ref
        rm -f main.cf master.cf
        touch main.cf master.cf
-       echo 'ldapxx = proxy:ldap:ldapfoo' >> main.cf
+       echo 'ldapxx = ldap:ldapfoo' >> main.cf
        echo 'ldapfoo_domain = bar' >> main.cf
        echo 'ldapfoo_domainx = bar' >> main.cf
-       echo 'mysqlxx = proxy:mysql:mysqlfoo' >> main.cf
+       echo 'mysqlxx = mysql:mysqlfoo' >> main.cf
        echo 'mysqlfoo_domain = bar' >> main.cf
        echo 'mysqlfoo_domainx = bar' >> main.cf
-       echo 'pgsqlxx = proxy:pgsql:pgsqlfoo' >> main.cf
+       echo 'pgsqlxx = pgsql:pgsqlfoo' >> main.cf
        echo 'pgsqlfoo_domain = bar' >> main.cf
        echo 'pgsqlfoo_domainx = bar' >> main.cf
-       echo 'sqlitexx = proxy:sqlite:sqlitefoo' >> main.cf
+       echo 'sqlitexx = sqlite:sqlitefoo' >> main.cf
        echo 'sqlitefoo_domain = bar' >> main.cf
        echo 'sqlitefoo_domainx = bar' >> main.cf
-       echo 'memcachexx = proxy:memcache:memcachefoo' >> main.cf
+       echo 'memcachexx = memcache:memcachefoo' >> main.cf
        echo 'memcachefoo_domain = bar' >> main.cf
        echo 'memcachefoo_domainx = bar' >> main.cf
        ./$(PROG) -nc . >test29.tmp 2>&1
@@ -462,6 +464,69 @@ test33:    $(PROG) test33.ref
        diff test33.ref test33.tmp
        rm -f main.cf master.cf test33.tmp
 
+test34:        $(PROG) test34.ref
+       rm -f main.cf master.cf
+       touch main.cf master.cf
+       echo 'mydestination=whatever' >> main.cf
+       echo 'process_name=xxx' >> main.cf
+       echo 'process_id=yyy' >> main.cf
+       ./$(PROG) -xc . mydestination process_name >test34.tmp 2>&1
+       diff test34.ref test34.tmp
+       rm -f main.cf master.cf test34.tmp
+
+test35:        $(PROG) test35.ref
+       rm -f main.cf master.cf
+       touch main.cf master.cf
+       echo whatevershebrings unix - n n - 0 other >> master.cf
+       echo ' -o body_checks=whatever' >> master.cf
+       echo ' -o process_name=aaa' >> master.cf
+       echo ' -o process_id=bbb' >> master.cf
+       ./$(PROG) -xc . process_name >test35.tmp 2>&1
+       diff test35.ref test35.tmp
+       rm -f main.cf master.cf test35.tmp
+
+test36:        $(PROG) test36.ref
+       rm -f main.cf master.cf
+       touch main.cf master.cf
+       echo 'mydestination=$$virtual_mapx' >> main.cf
+       echo 'virtual_alias_maps=$$virtual_maps' >> main.cf
+       ./$(PROG) -nxc . >test36.tmp 2>&1
+       diff test36.ref test36.tmp
+       rm -f main.cf master.cf test36.tmp
+
+test37: $(PROG) test37.ref
+       rm -f main.cf master.cf
+       touch main.cf master.cf
+       echo 'xxx=yyy' >> main.cf
+       echo 'aaa=bbb' >> main.cf
+       echo whatever unix - n n - 0 other >> master.cf
+       echo ' -o mydestination=$$xxx' >> master.cf
+       echo ' -o always_bcc=$$aaa' >> master.cf
+       echo ' -o aaa=ccc' >> master.cf
+       ./$(PROG) -Mfxc . >test37.tmp 2>&1
+       diff test37.ref test37.tmp
+       rm -f main.cf master.cf test37.tmp
+
+test38: $(PROG) test38.ref
+       rm -f main.cf master.cf
+       touch main.cf master.cf
+       echo foo unix - n n - 0 other >> master.cf
+       echo bar unix - n n - 0 other >> master.cf
+       echo ' -o aaa=ccc' >> master.cf
+       ./$(PROG) -Mnfxc . >test38.tmp 2>&1
+       diff test38.ref test38.tmp
+       rm -f main.cf master.cf test38.tmp
+
+test39: $(PROG) test39.ref
+       rm -f main.cf master.cf
+       touch main.cf master.cf
+       echo foo unix - n n - 0 other >> master.cf
+       echo bar inet - n n - 0 other >> master.cf
+       echo baz unix - n n - 0 other >> master.cf
+       ./$(PROG) -Mfc . unix >test39.tmp 2>&1
+       diff test39.ref test39.tmp
+       rm -f main.cf master.cf test39.tmp
+
 printfck: $(OBJS) $(PROG)
        rm -rf printfck
        mkdir printfck
@@ -548,6 +613,8 @@ postconf_builtin.o: postconf.h
 postconf_builtin.o: postconf_builtin.c
 postconf_builtin.o: raw_table.h
 postconf_builtin.o: raw_vars.h
+postconf_builtin.o: str_fn_table.h
+postconf_builtin.o: str_fn_vars.h
 postconf_builtin.o: str_table.h
 postconf_builtin.o: str_vars.h
 postconf_builtin.o: time_table.h
@@ -590,6 +657,22 @@ postconf_edit.o: ../../include/vstring.h
 postconf_edit.o: ../../include/vstring_vstream.h
 postconf_edit.o: postconf.h
 postconf_edit.o: postconf_edit.c
+postconf_lookup.o: ../../include/argv.h
+postconf_lookup.o: ../../include/dict.h
+postconf_lookup.o: ../../include/htable.h
+postconf_lookup.o: ../../include/mac_expand.h
+postconf_lookup.o: ../../include/mac_parse.h
+postconf_lookup.o: ../../include/mail_conf.h
+postconf_lookup.o: ../../include/msg.h
+postconf_lookup.o: ../../include/myflock.h
+postconf_lookup.o: ../../include/mymalloc.h
+postconf_lookup.o: ../../include/stringops.h
+postconf_lookup.o: ../../include/sys_defs.h
+postconf_lookup.o: ../../include/vbuf.h
+postconf_lookup.o: ../../include/vstream.h
+postconf_lookup.o: ../../include/vstring.h
+postconf_lookup.o: postconf.h
+postconf_lookup.o: postconf_lookup.c
 postconf_main.o: ../../include/argv.h
 postconf_main.o: ../../include/dict.h
 postconf_main.o: ../../include/htable.h
index 3b7a189ffdeaf591ba7ad4b8c763e1b459a66867..7385788def652ceffbf14a10957f13363c3773a5 100644 (file)
        }
     }
 }
+/^(static| )*(const +)?CONFIG_STR_FN_TABLE .*\{/,/\};/ { 
+    if ($1 ~ /^VAR/) {
+       str_fn_vars["char *" substr($3,2,length($3)-2) ";"] = 1
+       $2 = "pc_" $2
+       if (++stab[$1 $2 $4 $5 $6 $7 $8 $9] == 1) {
+           str_fn_table[$0] = 1
+       }
+    }
+}
 /^(static| )*(const +)?CONFIG_RAW_TABLE .*\{/,/\};/ { 
     if ($1 ~ /^VAR/) {
        raw_vars["char *" substr($3,2,length($3)-2) ";"] = 1
@@ -95,6 +104,11 @@ END {
        print key
     print "EOF"
 
+    print "cat >str_fn_vars.h <<'EOF'"
+    for (key in str_fn_vars)
+       print key
+    print "EOF"
+
     print "cat >raw_vars.h <<'EOF'"
     for (key in raw_vars)
        print key
@@ -136,6 +150,11 @@ END {
        print key
     print "EOF"
 
+    print "sed 's/[    ][      ]*/ /g' >str_fn_table.h <<'EOF'"
+    for (key in str_fn_table)
+       print key
+    print "EOF"
+
     print "sed 's/[    ][      ]*/ /g' >raw_table.h <<'EOF'"
     for (key in raw_table)
        print key
index 401e50430df47bdc52672e95808acbe202ee7b0a..e4619e11bde4089a89aab22531b531117b17521a 100644 (file)
@@ -18,7 +18,7 @@
 /*
 /*     \fBManaging master.cf:\fR
 /*
-/*     \fBpostconf\fR [\fB-fMv\fR] [\fB-c \fIconfig_dir\fR]
+/*     \fBpostconf\fR [\fB-fMnvx\fR] [\fB-c \fIconfig_dir\fR]
 /*     [\fIservice ...\fR]
 /*
 /*     \fBManaging bounce message templates:\fR
 /*
 /*     This feature is available with Postfix 2.9 and later.
 /* .IP \fB-n\fR
-/*     Print \fBmain.cf\fR parameter settings that are explicitly
-/*     specified in \fBmain.cf\fR.
+/*     Print only \fIname\fR=\fIvalue\fR parameter settings that
+/*     are explicitly specified in \fBmain.cf\fR. When specified
+/*     with \fB-M\fR, print only \fBmaster.cf\fR entries that have
+/*     "-o \fIname\fR=\fIvalue\fR" parameter settings (Postfix
+/*     2.10 and later).
 /*     Specify \fB-nf\fR to fold long lines for human readability
 /*     (Postfix 2.9 and later).
 /* .IP "\fB-t\fR [\fItemplate_file\fR]"
 /*     Enable verbose logging for debugging purposes. Multiple \fB-v\fR
 /*     options make the software increasingly verbose.
 /* .IP \fB-x\fR
-/*     Expand \fI$name\fR in parameter values. The expansion is
-/*     recursive.
+/*     Expand \fI$name\fR in \fBmain.cf\fR or \fBmaster.cf\fR
+/*     parameter values. The expansion is recursive.
+/*
+/*     This feature is available with Postfix 2.10 and later.
 /* .IP \fB-X\fR
 /*     Edit the \fBmain.cf\fR configuration file, and remove
 /*     the parameters named on the \fBpostconf\fR(1) command line.
@@ -508,16 +513,18 @@ int     main(int argc, char **argv)
     /*
      * Sanity check.
      */
-    junk = (cmd_mode & (SHOW_DEFS | SHOW_NONDEF | SHOW_MAPS | SHOW_LOCKS | EDIT_MAIN | SHOW_SASL_SERV | SHOW_SASL_CLNT | COMMENT_OUT | SHOW_MASTER | EDIT_EXCL));
-    if (junk != 0 && ((junk != SHOW_DEFS && junk != SHOW_NONDEF
+    junk = (cmd_mode & (SHOW_DEFS | SHOW_MAPS | SHOW_LOCKS | EDIT_MAIN | SHOW_SASL_SERV | SHOW_SASL_CLNT | COMMENT_OUT | SHOW_MASTER | EDIT_EXCL));
+    if (junk != 0 && ((junk != SHOW_DEFS
             && junk != SHOW_MAPS && junk != SHOW_LOCKS && junk != EDIT_MAIN
                       && junk != SHOW_SASL_SERV && junk != SHOW_SASL_CLNT
                       && junk != COMMENT_OUT && junk != SHOW_MASTER
                       && junk != EDIT_EXCL)
                      || ext_argv != 0))
-       msg_fatal("specify one of -a, -A, -b, -d, -e, -#, -l, -m, -M, -n, and -X");
-    if ((cmd_mode & SHOW_EVAL) != 0 && junk != 0 && junk != SHOW_DEFS && junk != SHOW_NONDEF)
-       msg_fatal("do not specify -x with -a, -A, -b, -e, -#, -l, -m, -M, or -X");
+       msg_fatal("specify one of -a, -A, -b, -d, -e, -#, -l, -m, -M, and -X");
+    if ((cmd_mode & SHOW_EVAL) != 0 && junk != 0 && junk != SHOW_DEFS && junk != SHOW_MASTER)
+       msg_fatal("do not specify -x with -a, -A, -b, -e, -#, -l, -m, or -X");
+    if ((cmd_mode & SHOW_NONDEF) != 0 && junk != 0 && junk != SHOW_MASTER)
+       msg_fatal("do not specify -n with -a, -A, -b, -d, -e, -#, -l, -m, or -X");
 
     /*
      * Display bounce template information and exit.
@@ -560,6 +567,10 @@ int     main(int argc, char **argv)
      */
     else if (cmd_mode & SHOW_MASTER) {
        read_master(FAIL_ON_OPEN_ERROR);
+       read_parameters();
+       register_builtin_parameters(basename(argv[0]), getpid());
+       register_service_parameters();
+       register_user_parameters();
        show_master(cmd_mode, argv + optind);
     }
 
@@ -589,7 +600,7 @@ int     main(int argc, char **argv)
        if ((cmd_mode & SHOW_DEFS) == 0) {
            read_parameters();
        }
-       register_builtin_parameters();
+       register_builtin_parameters(basename(argv[0]), getpid());
 
        /*
         * Add service-dependent parameters (service names from master.cf)
index 86e37d0333d73468cf2d91c186f5ec6e1d74fec3..0f7e5864d12681a741eae37fbeb3fd0b8eb8d5c8 100644 (file)
@@ -8,6 +8,11 @@
 /* DESCRIPTION
 /* .nf
 
+ /*
+  * System library.
+  */
+#include <unistd.h>
+
  /*
   * Utility library.
   */
@@ -43,7 +48,6 @@ typedef struct {
     int     flags;                     /* see below */
     char   *param_data;                        /* mostly, the default value */
     const char *(*convert_fn) (char *);        /* value to string */
-    const char *cached_defval;         /* cached default value */
 } PC_PARAM_NODE;
 
  /* Values for flags. See the postconf_node module for narrative text. */
@@ -51,6 +55,9 @@ typedef struct {
 #define PC_PARAM_FLAG_BUILTIN  (1<<1)  /* built-in parameter name */
 #define PC_PARAM_FLAG_SERVICE  (1<<2)  /* service-defined parameter name */
 #define PC_PARAM_FLAG_USER     (1<<3)  /* user-defined parameter name */
+#define PC_PARAM_FLAG_LEGACY   (1<<4)  /* legacy parameter name */
+#define PC_PARAM_FLAG_READONLY (1<<5)  /* legacy parameter name */
+#define PC_PARAM_FLAG_DBMS     (1<<6)  /* dbms-defined parameter name */
 
 #define PC_PARAM_MASK_CLASS \
        (PC_PARAM_FLAG_BUILTIN | PC_PARAM_FLAG_SERVICE | PC_PARAM_FLAG_USER)
@@ -58,6 +65,9 @@ typedef struct {
        ((node)->flags = (((node)->flags & ~PC_PARAM_MASK_CLASS) | (class)))
 
 #define PC_RAW_PARAMETER(node) ((node)->flags & PC_PARAM_FLAG_RAW)
+#define PC_LEGACY_PARAMETER(node) ((node)->flags & PC_PARAM_FLAG_LEGACY)
+#define PC_READONLY_PARAMETER(node) ((node)->flags & PC_PARAM_FLAG_READONLY)
+#define PC_DBMS_PARAMETER(node) ((node)->flags & PC_PARAM_FLAG_DBMS)
 
  /* Values for param_data. See postconf_node module for narrative text. */
 #define PC_PARAM_NO_DATA       ((char *) 0)
@@ -151,13 +161,21 @@ extern void show_master(int, char **);
  /*
   * postconf_builtin.c.
   */
-extern void register_builtin_parameters(void);
+extern void register_builtin_parameters(const char *, pid_t);
 
  /*
   * postconf_service.c.
   */
 extern void register_service_parameters(void);
 
+ /*
+  * Parameter context structure.
+  */
+typedef struct {
+    PC_MASTER_ENT *local_scope;
+    int     param_class;
+} PC_PARAM_CTX;
+
  /*
   * postconf_user.c.
   */
@@ -170,6 +188,13 @@ extern void register_dbms_parameters(const char *,
                                const char *(*) (const char *, int, char *),
                                             PC_MASTER_ENT *);
 
+ /*
+  * postconf_lookup.c.
+  */
+const char *lookup_parameter_value(int, const char *, PC_MASTER_ENT *,
+                                          PC_PARAM_NODE *);
+const char *expand_parameter_value(int, const char *, PC_MASTER_ENT *);
+
  /*
   * postconf_unused.c.
   */
index 1e2fed67433d7a592f4fe86af5af6cce12e7937b..239477ed522baafbecfe37609f0d1548781547b1 100644 (file)
@@ -6,10 +6,18 @@
 /* SYNOPSIS
 /*     #include <postconf.h>
 /*
-/*     void    register_builtin_parameters()
+/*     void    register_builtin_parameters(procname, pid)
+/*     const char *procname;
+/*     pid_t   pid;
 /* DESCRIPTION
 /*     register_builtin_parameters() initializes the global parameter
 /*     name space and adds all built-in parameter information.
+/*
+/*     Arguments:
+/*.IP procname
+/*     Provides the default value for the "process_name" parameter.
+/*.IP pid
+/*     Provides the default value for the "process_id" parameter.
 /* DIAGNOSTICS
 /*     Problems are reported to the standard error stream.
 /* LICENSE
@@ -120,31 +128,51 @@ static const CONFIG_LONG_TABLE long_table[] = {
 };
 
  /*
-  * Parameters with default values obtained via function calls.
+  * Legacy parameters for backwards compatibility.
   */
-char   *var_myhostname;
-char   *var_mydomain;
-char   *var_mynetworks;
+static const CONFIG_STR_TABLE legacy_str_table[] = {
+    {"virtual_maps", ""},
+    {"fallback_relay", ""},
+    {"authorized_verp_clients", ""},
+    {"smtpd_client_connection_limit_exceptions", ""},
+    0,
+};
 
-static const char *check_myhostname(void);
-static const char *check_mydomainname(void);
-static const char *check_mynetworks(void);
+ /*
+  * Parameters whose default values are normally initialized by calling a
+  * function. We direct the calls to our own versions of those functions
+  * because the run-time conditions are slightly different.
+  * 
+  * Important: if the evaluation of these parameters has any side effects, then
+  * those side effects must happen only once.
+  */
+static const char *pc_check_myhostname(void);
+static const char *pc_check_mydomainname(void);
+static const char *pc_mynetworks(void);
+
+#include "str_fn_vars.h"
 
 static const CONFIG_STR_FN_TABLE str_fn_table[] = {
-    VAR_MYHOSTNAME, check_myhostname, &var_myhostname, 1, 0,
-    VAR_MYDOMAIN, check_mydomainname, &var_mydomain, 1, 0,
-    0,
-};
-static const CONFIG_STR_FN_TABLE str_fn_table_2[] = {
-    VAR_MYNETWORKS, check_mynetworks, &var_mynetworks, 1, 0,
+#include "str_fn_table.h"
     0,
 };
 
+ /*
+  * Parameters whose default values are normally initialized by ad-hoc code.
+  * The AWK script cannot identify these parameters or values, so we provide
+  * our own.
+  * 
+  * Important: if the evaluation of these parameters has any side effects, then
+  * those side effects must happen only once.
+  */
+static CONFIG_STR_TABLE adhoc_procname = {VAR_PROCNAME};
+static CONFIG_INT_TABLE adhoc_pid = {VAR_PID};
+
 #define STR(x) vstring_str(x)
 
-/* check_myhostname - lookup hostname and validate */
+/* pc_check_myhostname - lookup hostname and validate */
 
-static const char *check_myhostname(void)
+static const char *pc_check_myhostname(void)
 {
     static const char *name;
     const char *dot;
@@ -176,34 +204,48 @@ static void get_myhostname(void)
     const char *name;
 
     if ((name = mail_conf_lookup_eval(VAR_MYHOSTNAME)) == 0)
-       name = check_myhostname();
-    var_myhostname = mystrdup(name);
+       name = pc_check_myhostname();
+    var_mynetworks = mystrdup(name);
 }
 
-/* check_mydomainname - lookup domain name and validate */
+/* pc_check_mydomainname - lookup domain name and validate */
 
-static const char *check_mydomainname(void)
+static const char *pc_check_mydomainname(void)
 {
+    static const char *domain;
     char   *dot;
 
+    /*
+     * Use cached result.
+     */
+    if (domain)
+       return (domain);
+
     /*
      * Use the hostname when it is not a FQDN ("foo"), or when the hostname
      * actually is a domain name ("foo.com").
      */
-    if (var_myhostname == 0)
+    if (var_mynetworks == 0)
        get_myhostname();
-    if ((dot = strchr(var_myhostname, '.')) == 0 || strchr(dot + 1, '.') == 0)
-       return (DEF_MYDOMAIN);
-    return (dot + 1);
+    if ((dot = strchr(var_mynetworks, '.')) == 0 || strchr(dot + 1, '.') == 0)
+       return (domain = DEF_MYDOMAIN);
+    return (domain = mystrdup(dot + 1));
 }
 
-/* check_mynetworks - lookup network address list */
+/* pc_mynetworks - lookup network address list */
 
-static const char *check_mynetworks(void)
+static const char *pc_mynetworks(void)
 {
+    static const char *networks;
     INET_PROTO_INFO *proto_info;
     const char *junk;
 
+    /*
+     * Use cached result.
+     */
+    if (networks)
+       return (networks);
+
     if (var_inet_interfaces == 0) {
        if ((cmd_mode & SHOW_DEFS)
            || (junk = mail_conf_lookup_eval(VAR_INET_INTERFACES)) == 0)
@@ -223,7 +265,7 @@ static const char *check_mynetworks(void)
        var_inet_protocols = mystrdup(junk);
        proto_info = inet_proto_init(VAR_INET_PROTOCOLS, var_inet_protocols);
     }
-    return (mynetworks());
+    return (networks = mystrdup(mynetworks()));
 }
 
 /* convert_bool_parameter - get boolean parameter string value */
@@ -309,7 +351,7 @@ static const char *convert_long_parameter(char *ptr)
 
 /* register_builtin_parameters - add built-ins to the global name space */
 
-void    register_builtin_parameters(void)
+void    register_builtin_parameters(const char *procname, pid_t pid)
 {
     const char *myname = "register_builtin_parameters";
     const CONFIG_TIME_TABLE *ctt;
@@ -353,9 +395,6 @@ void    register_builtin_parameters(void)
     for (cft = str_fn_table; cft->name; cft++)
        PC_PARAM_TABLE_ENTER(param_table, cft->name, PC_PARAM_FLAG_BUILTIN,
                             (char *) cft, convert_str_fn_parameter);
-    for (cft = str_fn_table_2; cft->name; cft++)
-       PC_PARAM_TABLE_ENTER(param_table, cft->name, PC_PARAM_FLAG_BUILTIN,
-                            (char *) cft, convert_str_fn_parameter);
     for (rst = raw_table; rst->name; rst++)
        PC_PARAM_TABLE_ENTER(param_table, rst->name,
                             PC_PARAM_FLAG_BUILTIN | PC_PARAM_FLAG_RAW,
@@ -369,4 +408,25 @@ void    register_builtin_parameters(void)
     for (lst = long_table; lst->name; lst++)
        PC_PARAM_TABLE_ENTER(param_table, lst->name, PC_PARAM_FLAG_BUILTIN,
                             (char *) lst, convert_long_parameter);
+
+    /*
+     * Register legacy parameters (used as a backwards-compatible migration
+     * aid).
+     */
+    for (cst = legacy_str_table; cst->name; cst++)
+       PC_PARAM_TABLE_ENTER(param_table, cst->name, PC_PARAM_FLAG_LEGACY,
+                            (char *) cst, convert_str_parameter);
+
+    /*
+     * Register parameters whose default value is normally initialized by
+     * ad-hoc code.
+     */
+    adhoc_procname.defval = mystrdup(procname);
+    PC_PARAM_TABLE_ENTER(param_table, adhoc_procname.name,
+                        PC_PARAM_FLAG_BUILTIN | PC_PARAM_FLAG_READONLY,
+                        (char *) &adhoc_procname, convert_str_parameter);
+    adhoc_pid.defval = pid;
+    PC_PARAM_TABLE_ENTER(param_table, adhoc_pid.name,
+                        PC_PARAM_FLAG_BUILTIN | PC_PARAM_FLAG_READONLY,
+                        (char *) &adhoc_pid, convert_int_parameter);
 }
index 6ac07aa260f26f5491daa4f6ca5ade92f9cb7f7b..024c2bf5a201646936f41053fb3159f59f0da672 100644 (file)
@@ -25,7 +25,7 @@
 /*     names for that database type.
 /* .IP flag_parameter
 /*     A function that takes as arguments a candidate parameter
-/*     name, an unused value, and a local namespace pointer. The
+/*     name, an unused value, and a PC_PARAM_CTX pointer.  The
 /*     function will flag the parameter as "used" if it has a
 /*     "name=value" entry in the local or global namespace.
 /* .IP local_scope
@@ -142,26 +142,6 @@ static const PC_DBMS_INFO dbms_info[] = {
     0,
 };
 
-/* register_dbms_parameters_cb - mac_expand() call-back */
-
-static const char *register_dbms_parameters_cb(const char *mac_name,
-                                                      int unused_mode,
-                                                      char *context)
-{
-    PC_MASTER_ENT *local_scope = (PC_MASTER_ENT *) context;
-    const char *mac_val;
-
-    /*
-     * Local namespace "name=value" settings are always explicit. They have
-     * precedence over global namespace "name=value" settings which are
-     * either explicit or defined by their default value.
-     */
-    if (local_scope == 0
-       || (mac_val = dict_get(local_scope->all_params, mac_name)) == 0)
-       mac_val = mail_conf_lookup(mac_name);
-    return (mac_val);
-}
-
 /* register_dbms_parameters - look for database_type:prefix_name */
 
 void    register_dbms_parameters(const char *param_value,
@@ -175,51 +155,44 @@ void    register_dbms_parameters(const char *param_value,
     static VSTRING *buffer = 0;
     static VSTRING *candidate = 0;
     const char **cpp;
+    PC_PARAM_CTX param_ctx;
+
+    param_ctx.local_scope = local_scope;
+    param_ctx.param_class = PC_PARAM_FLAG_DBMS | PC_PARAM_FLAG_USER;
 
     /*
-     * Emulate Postfix parameter value expansion, prepending the appropriate
-     * local (master.cf "-o name-value") namespace to the global (main.cf
-     * "name=value") namespace.
-     * 
-     * XXX This does not examine both sides of conditional macro expansion, and
-     * may expand the "wrong" conditional macros. This is the best we can do
-     * for legacy database configuration support.
+     * XXX This does not examine both sides of conditional macro expansion,
+     * and may expand the "wrong" conditional macros. This is the best we can
+     * do for legacy database configuration support.
      */
-#define NO_SCAN_FILTER ((char *) 0)
-
-    (void) mac_expand(buffer ? buffer : (buffer = vstring_alloc(100)),
-                     param_value, MAC_EXP_FLAG_RECURSE, NO_SCAN_FILTER,
-                     register_dbms_parameters_cb, (char *) local_scope);
+    bufp = STR(vstring_strcpy(buffer ? buffer : (buffer = vstring_alloc(100)),
+             expand_parameter_value(SHOW_EVAL, param_value, local_scope)));
 
     /*
      * Naive parsing. We don't really know if the parameter specifies free
      * text or a list of databases.
      */
-    bufp = STR(buffer);
     while ((db_type = mystrtok(&bufp, " ,\t\r\n")) != 0) {
 
        /*
-        * Skip over "proxy:" indirections.
-        */
-       while ((prefix = split_at(db_type, ':')) != 0
-              && strcmp(db_type, DICT_TYPE_PROXY) == 0)
-           db_type = prefix;
-
-       /*
-        * Look for database:prefix where the prefix is not a pathname and
-        * the database is a known type. Synthesize candidate parameter names
+        * Don't skip over "proxy:" indirections. They don't introduce
+        * database-specific main.cf parameters on the proxy client side.
+        * 
+        * Look for database:prefix where the prefix is not a pathname and the
+        * database is a known type. Synthesize candidate parameter names
         * from the user-defined prefix and from the database-defined suffix
         * list, and see if those parameters have a "name=value" entry in the
         * local or global namespace.
         */
-       if (prefix != 0 && *prefix != '/' && *prefix != '.') {
+       if ((prefix = split_at(db_type, ':')) != 0
+           && *prefix != '/' && *prefix != '.') {
            for (dp = dbms_info; dp->db_type != 0; dp++) {
                if (strcmp(db_type, dp->db_type) == 0) {
                    for (cpp = dp->db_suffixes; *cpp; cpp++) {
                        vstring_sprintf(candidate ? candidate :
                                        (candidate = vstring_alloc(30)),
                                        "%s_%s", prefix, *cpp);
-                       flag_parameter(STR(candidate), 0, (char *) local_scope);
+                       flag_parameter(STR(candidate), 0, (char *) &param_ctx);
                    }
                    break;
                }
diff --git a/postfix/src/postconf/postconf_lookup.c b/postfix/src/postconf/postconf_lookup.c
new file mode 100644 (file)
index 0000000..6ad1b9f
--- /dev/null
@@ -0,0 +1,183 @@
+/*++
+/* NAME
+/*     postconf_lookup 3
+/* SUMMARY
+/*     parameter lookup routines
+/* SYNOPSIS
+/*     #include <postconf.h>
+/*
+/*     const char *lookup_parameter_value(mode, name, local_scope, node)
+/*     int     mode;
+/*     const char *name;
+/*     PC_MASTER_ENT *local_scope;
+/*     PC_PARAM_NODE *node;
+/*
+/*     const char *expand_parameter_value(mode, value, local_scope)
+/*     int     mode;
+/*     const char *value;
+/*     PC_MASTER_ENT *local_scope;
+/* DESCRIPTION
+/*     These functions perform parameter value lookups.  The order
+/*     of decreasing precedence is:
+/* .IP \(bu
+/*     Search name=value parameter settings in master.cf.
+/*     These lookups are disabled with the SHOW_DEFS flag.
+/* .IP \(bu
+/*     Search name=value parameter settings in main.cf.
+/*     These lookups are disabled with the SHOW_DEFS flag.
+/* .IP \(bu
+/*     Search built-in default parameter settings. These lookups
+/*     are disabled with the SHOW_NONDEF flag.
+/* .PP
+/*     lookup_parameter_value() looks up the value for the named
+/*     parameter, and returns null if the name was not found.
+/*
+/*     expand_parameter_value() expands $name in the specified
+/*     parameter value. This function ignores the SHOW_NONDEF flag.
+/*     The result is in static memory that is overwritten with
+/*     each call.
+/*
+/*     Arguments:
+/* .IP mode
+/*     Bit-wise OR of zero or one of the following (other flags
+/*     are ignored):
+/* .RS
+/* .IP SHOW_DEFS
+/*     Search built-in default parameter settings only.
+/* .IP SHOW_NONDEF
+/*     Search local (master.cf) or global (main.cf) name=value
+/*     parameter settings only.
+/* .RE
+/* .IP name
+/*     The name of a parameter to be looked up.
+/* .IP value
+/*     The parameter value where $name should be expanded.
+/* .IP local_scope
+/*     Null pointer, or pointer to master.cf entry with local
+/*     parameter definitions.
+/* .IP node
+/*     Null pointer, or global default settings for the named
+/*     parameter.
+/* DIAGNOSTICS
+/*     Problems are reported to the standard error stream.
+/* LICENSE
+/* .ad
+/* .fi
+/*     The Secure Mailer license must be distributed with this software.
+/* AUTHOR(S)
+/*     Wietse Venema
+/*     IBM T.J. Watson Research
+/*     P.O. Box 704
+/*     Yorktown Heights, NY 10598, USA
+/*--*/
+
+/* System library. */
+
+#include <sys_defs.h>
+#include <string.h>
+
+/* Utility library. */
+
+#include <msg.h>
+#include <mymalloc.h>
+#include <vstring.h>
+#include <dict.h>
+#include <stringops.h>
+#include <mac_expand.h>
+
+/* Global library. */
+
+#include <mail_conf.h>
+
+/* Application-specific. */
+
+#include <postconf.h>
+
+#define STR(x) vstring_str(x)
+
+/* lookup_parameter_value - look up specific parameter value */
+
+const char *lookup_parameter_value(int mode, const char *name,
+                                          PC_MASTER_ENT *local_scope,
+                                          PC_PARAM_NODE *node)
+{
+    const char *value = 0;
+
+    /*
+     * Use the actual or built-in default parameter value. Local name=value
+     * entries in master.cf take precedence over global name=value entries in
+     * main.cf. Built-in defaults have the lowest precedence.
+     */
+    if ((mode & SHOW_DEFS) != 0
+       || ((local_scope == 0 || local_scope->all_params == 0
+            || (value = dict_get(local_scope->all_params, name)) == 0)
+           && (value = dict_lookup(CONFIG_DICT, name)) == 0
+           && (mode & SHOW_NONDEF) == 0)) {
+       if (node != 0 || (node = PC_PARAM_TABLE_FIND(param_table, name)) != 0)
+           value = convert_param_node(SHOW_DEFS, name, node);
+    }
+    return (value);
+}
+
+ /*
+  * Data structure to pass private state while recursively expanding $name in
+  * parameter values.
+  */
+typedef struct {
+    int     mode;
+    PC_MASTER_ENT *local_scope;
+} PC_EVAL_CTX;
+
+/* expand_parameter_value_helper - macro parser call-back routine */
+
+static const char *expand_parameter_value_helper(const char *key,
+                                                        int unused_type,
+                                                        char *context)
+{
+    PC_EVAL_CTX *cp = (PC_EVAL_CTX *) context;
+
+    return (lookup_parameter_value(cp->mode, key, cp->local_scope,
+                                  (PC_PARAM_NODE *) 0));
+}
+
+/* expand_parameter_value - expand $name in parameter value */
+
+const char *expand_parameter_value(int mode, const char *value,
+                                          PC_MASTER_ENT *local_scope)
+{
+    const char *myname = "expand_parameter_value";
+    static VSTRING *buf;
+    int     status;
+    PC_EVAL_CTX eval_ctx;
+
+    /*
+     * Initialize.
+     */
+    if (buf == 0)
+       buf = vstring_alloc(10);
+
+    /*
+     * Expand macros recursively.
+     * 
+     * When expanding $name in "postconf -n" parameter values, don't limit the
+     * search to only non-default parameter values.
+     * 
+     * When expanding $name in "postconf -d" parameter values, do limit the
+     * search to only default parameter values.
+     */
+#define DONT_FILTER (char *) 0
+
+    eval_ctx.mode = (mode & ~SHOW_NONDEF);
+    eval_ctx.local_scope = local_scope;
+    status = mac_expand(buf, value, MAC_EXP_FLAG_RECURSE, DONT_FILTER,
+                       expand_parameter_value_helper, (char *) &eval_ctx);
+    if (status & MAC_PARSE_ERROR)
+       msg_fatal("macro processing error");
+    if (msg_verbose > 1) {
+       if (strcmp(value, STR(buf)) != 0)
+           msg_info("%s: expand %s -> %s", myname, value, STR(buf));
+       else
+           msg_info("%s: const  %s", myname, value);
+    }
+    return (STR(buf));
+}
index d2233dae142ff828bca31374c192ae18f9c6de87..21626cd2a4440819b53350ae98ea8a126ae86fa5 100644 (file)
@@ -159,100 +159,6 @@ static void print_line(int mode, const char *fmt,...)
     vstream_fputs("\n", VSTREAM_OUT);
 }
 
-/* lookup_parameter_value - look up specific parameter value */
-
-static const char *lookup_parameter_value(int mode, const char *name,
-                                                 PC_PARAM_NODE *node)
-{
-    const char *value;
-
-    /*
-     * Use the actual or built-in default parameter value. Some default
-     * values are computed by functions that have side effects, and those
-     * functions should be invoked only once. Therefore, when expanding $name
-     * in parameter values, we cache the default values.
-     */
-    if ((mode & SHOW_DEFS) != 0
-       || ((value = dict_lookup(CONFIG_DICT, name)) == 0
-           && (mode & SHOW_NONDEF) == 0)) {
-       if ((value = node->cached_defval) == 0
-           && (value = convert_param_node(SHOW_DEFS, name, node)) != 0
-           && (mode & SHOW_EVAL) != 0)
-           node->cached_defval = value = mystrdup(value);
-    }
-    return (value);
-}
-
- /*
-  * Data structure to pass private state while recursively expanding $name in
-  * parameter values.
-  */
-typedef struct {
-    int     mode;
-} PC_EVAL_CTX;
-
-/* expand_parameter_value_helper - macro parser call-back routine */
-
-static const char *expand_parameter_value_helper(const char *key,
-                                                        int unused_type,
-                                                        char *context)
-{
-    PC_PARAM_NODE *node;
-    PC_EVAL_CTX *cp = (PC_EVAL_CTX *) context;
-
-    /*
-     * XXX Do not spam the user with warnings about legacy parameter names in
-     * backwards-compatible default settings.
-     */
-    if ((node = PC_PARAM_TABLE_FIND(param_table, key)) != 0) {
-       return (lookup_parameter_value(cp->mode, key, node));
-    } else {
-       /* msg_warn("%s: unknown parameter", key); */
-       return (0);
-    }
-}
-
-/* expand_parameter_value - expand $name in parameter value */
-
-static const char *expand_parameter_value(int mode, const char *value,
-                                                 PC_PARAM_NODE *node)
-{
-    const char *myname = "expand_parameter_value";
-    static VSTRING *buf;
-    int     status;
-    PC_EVAL_CTX eval_ctx;
-
-    /*
-     * Initialize.
-     */
-    if (buf == 0)
-       buf = vstring_alloc(10);
-
-    /*
-     * Expand macros recursively.
-     * 
-     * When expanding $name in "postconf -n" parameter values, don't limit the
-     * search to only non-default parameter values.
-     * 
-     * When expanding $name in "postconf -d" parameter values, do limit the
-     * search to only default parameter values.
-     */
-#define DONT_FILTER (char *) 0
-
-    eval_ctx.mode = mode & ~SHOW_NONDEF;
-    status = mac_expand(buf, value, MAC_EXP_FLAG_RECURSE, DONT_FILTER,
-                       expand_parameter_value_helper, (char *) &eval_ctx);
-    if (status & MAC_PARSE_ERROR)
-       msg_fatal("macro processing error");
-    if (msg_verbose > 1) {
-       if (strcmp(value, STR(buf)) != 0)
-           msg_info("%s: expand %s -> %s", myname, value, STR(buf));
-       else
-           msg_info("%s: const  %s", myname, value);
-    }
-    return (STR(buf));
-}
-
 /* print_parameter - show specific parameter */
 
 static void print_parameter(int mode, const char *name,
@@ -263,7 +169,7 @@ static void print_parameter(int mode, const char *name,
     /*
      * Use the default or actual value.
      */
-    value = lookup_parameter_value(mode, name, node);
+    value = lookup_parameter_value(mode, name, (PC_MASTER_ENT *) 0, node);
 
     /*
      * Optionally expand $name in the parameter value. Print the result with
@@ -271,7 +177,7 @@ static void print_parameter(int mode, const char *name,
      */
     if (value != 0) {
        if ((mode & SHOW_EVAL) != 0 && PC_RAW_PARAMETER(node) == 0)
-           value = expand_parameter_value(mode, value, node);
+           value = expand_parameter_value(mode, value, (PC_MASTER_ENT *) 0);
        if (mode & SHOW_NAME) {
            print_line(mode, "%s = %s\n", name, value);
        } else {
index 0aa6c3a9247e98565c45b043b7965a9370d6351c..0e1ac970e2349fec9de28159986b8b6b1b46c74d 100644 (file)
@@ -176,10 +176,12 @@ void    read_master(int fail_on_open_error)
 
 /* print_master_line - print one master line */
 
-static void print_master_line(int mode, ARGV *argv)
+static void print_master_line(int mode, PC_MASTER_ENT *masterp)
 {
-    char   *arg;
-    char   *aval;
+    char  **argv = masterp->argv->argv;
+    const char *arg;
+    const char *aval;
+    int     arg_len;
     int     line_len;
     int     field;
     int     in_daemon_options;
@@ -204,7 +206,7 @@ static void print_master_line(int mode, ARGV *argv)
      * least one-space column separation.
      */
     for (line_len = 0, field = 0; field < PC_MASTER_MIN_FIELDS; field++) {
-       arg = argv->argv[field];
+       arg = argv[field];
        if (line_len > 0) {
            do {
                ADD_SPACE;
@@ -219,8 +221,9 @@ static void print_master_line(int mode, ARGV *argv)
      * have argument grouping preferences.
      */
     in_daemon_options = 1;
-    for ( /* void */ ; argv->argv[field] != 0; field++) {
-       arg = argv->argv[field];
+    for ( /* void */ ; (arg = argv[field]) != 0; field++) {
+       arg_len = strlen(arg);
+       aval = 0;
        if (in_daemon_options) {
 
            /*
@@ -231,34 +234,33 @@ static void print_master_line(int mode, ARGV *argv)
                in_daemon_options = 0;
                if ((mode & FOLD_LINE)
                    && line_len > column_goal[PC_MASTER_MIN_FIELDS - 1]) {
-                   vstream_fputs("\n" INDENT_TEXT, VSTREAM_OUT);
-                   line_len = INDENT_LEN;
+                   /* Force line wrap. */
+                   line_len = LINE_LIMIT;
                }
-           }
+           } else {
 
-           /*
-            * Try to avoid breaking "-o name=value" over multiple lines if
-            * it would fit on one line.
-            */
-           else if ((mode & FOLD_LINE)
-                    && line_len > INDENT_LEN && strcmp(arg, "-o") == 0
-                    && (aval = argv->argv[field + 1]) != 0
-                    && INDENT_LEN + 3 + strlen(aval) < LINE_LIMIT) {
-               vstream_fputs("\n" INDENT_TEXT, VSTREAM_OUT);
-               line_len = INDENT_LEN;
-               ADD_TEXT(arg, strlen(arg));
-               arg = aval;
-               field += 1;
+               /*
+                * Process options with a value.
+                */
+               if (strcmp(arg, "-o") == 0
+                   && (aval = argv[field + 1]) != 0
+                   && (mode & SHOW_EVAL) != 0)
+                   aval = expand_parameter_value(mode, aval, masterp);
+
+               /*
+                * Keep option and value on the same line.
+                */
+               if (aval)
+                   arg_len += strlen(aval) + 1;
            }
        }
 
        /*
-        * Insert a line break when the next argument won't fit (unless, of
-        * course, we just inserted a line break).
+        * Insert a line break when the next item won't fit.
         */
        if (line_len > INDENT_LEN) {
            if ((mode & FOLD_LINE) == 0
-               || line_len + 1 + strlen(arg) < LINE_LIMIT) {
+               || line_len + 1 + arg_len < LINE_LIMIT) {
                ADD_SPACE;
            } else {
                vstream_fputs("\n" INDENT_TEXT, VSTREAM_OUT);
@@ -266,6 +268,11 @@ static void print_master_line(int mode, ARGV *argv)
            }
        }
        ADD_TEXT(arg, strlen(arg));
+       if (aval) {
+           ADD_SPACE;
+           ADD_TEXT(aval, strlen(aval));
+           field += 1;
+       }
     }
     vstream_fputs("\n", VSTREAM_OUT);
 }
@@ -275,7 +282,6 @@ static void print_master_line(int mode, ARGV *argv)
 void    show_master(int mode, char **filters)
 {
     PC_MASTER_ENT *masterp;
-    ARGV   *argv;
     ARGV   *service_filter = 0;
 
     /*
@@ -287,10 +293,11 @@ void    show_master(int mode, char **filters)
     /*
      * Iterate over the master table.
      */
-    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);
+    for (masterp = master_table; masterp->argv != 0; masterp++)
+       if ((service_filter == 0
+            || match_service_match(service_filter, masterp->name_space))
+           && ((mode & SHOW_NONDEF) == 0 || masterp->all_params != 0))
+           print_master_line(mode, masterp);
 
     /*
      * Cleanup.
index 1047cfc073954cd04ed211146f8b37d39c5905a2..afdf602193803e2c5fd3d9738f7e09bca64edc5a 100644 (file)
@@ -150,7 +150,6 @@ PC_PARAM_NODE *make_param_node(int flags, char *param_data,
     node->flags = flags;
     node->param_data = param_data;
     node->convert_fn = convert_fn;
-    node->cached_defval = 0;
     return (node);
 }
 
index c72406587b6a6d8a4cab26b8699b8f90785e996a..563da5c0912b5f401b4c910f97058fbb96ef604f 100644 (file)
@@ -91,15 +91,21 @@ static HTABLE *rest_class_table;
 
 /* SCAN_USER_PARAMETER_VALUE - examine macro names in parameter value */
 
-#define SCAN_USER_PARAMETER_VALUE(value, local_scope) do { \
+#define SCAN_USER_PARAMETER_VALUE(value, class, scope) do { \
+    PC_PARAM_CTX _ctx; \
+    _ctx.local_scope = (scope); \
+    _ctx.param_class = (class); \
     (void) mac_expand(NO_SCAN_RESULT, (value), MAC_EXP_FLAG_SCAN, \
-           NO_SCAN_FILTER, flag_user_parameter, ((char *) (local_scope))); \
+           NO_SCAN_FILTER, flag_user_parameter, (char *) &_ctx); \
 } while (0)
 
 /* FLAG_USER_PARAMETER - flag user-defined name "valid" if it has name=value */
 
-#define FLAG_USER_PARAMETER(name, local_scope) do { \
-    flag_user_parameter((name), NO_SCAN_MODE, ((char *) (local_scope))); \
+#define FLAG_USER_PARAMETER(name, class, scope) do { \
+    PC_PARAM_CTX _ctx; \
+    _ctx.local_scope = (scope); \
+    _ctx.param_class = (class); \
+    flag_user_parameter((name), NO_SCAN_MODE, (char *) &_ctx); \
 } while (0)
 
 /* convert_user_parameter - get user-defined parameter string value */
@@ -115,7 +121,11 @@ static const char *flag_user_parameter(const char *mac_name,
                                               int unused_mode,
                                               char *context)
 {
-    PC_MASTER_ENT *local_scope = (PC_MASTER_ENT *) context;
+    PC_PARAM_CTX *param_ctx = (PC_PARAM_CTX *) context;
+    PC_MASTER_ENT *local_scope = param_ctx->local_scope;
+    int     param_class = param_ctx->param_class;
+    const char *source = local_scope ? MASTER_CONF_FILE : MAIN_CONF_FILE;
+    int     user_supplied = 0;
 
     /*
      * If the name=value exists in the local (or global) name space, update
@@ -126,10 +136,11 @@ static const char *flag_user_parameter(const char *mac_name,
      * compatibility after a feature name change.
      */
     if (local_scope && dict_get(local_scope->all_params, mac_name)) {
+       user_supplied = 1;
        /* $name in master.cf references name=value in master.cf. */
        if (PC_PARAM_TABLE_LOCATE(local_scope->valid_names, mac_name) == 0) {
            PC_PARAM_TABLE_ENTER(local_scope->valid_names, mac_name,
-                                PC_PARAM_FLAG_USER, PC_PARAM_NO_DATA,
+                                param_class, PC_PARAM_NO_DATA,
                                 convert_user_parameter);
            if (msg_verbose)
                msg_info("$%s in %s:%s validates %s=value in %s:%s",
@@ -139,9 +150,10 @@ static const char *flag_user_parameter(const char *mac_name,
                         local_scope->name_space);
        }
     } else if (mail_conf_lookup(mac_name) != 0) {
+       user_supplied = 1;
        /* $name in main/master.cf references name=value in main.cf. */
        if (PC_PARAM_TABLE_LOCATE(param_table, mac_name) == 0) {
-           PC_PARAM_TABLE_ENTER(param_table, mac_name, PC_PARAM_FLAG_USER,
+           PC_PARAM_TABLE_ENTER(param_table, mac_name, param_class,
                                 PC_PARAM_NO_DATA, convert_user_parameter);
            if (msg_verbose) {
                if (local_scope)
@@ -159,20 +171,33 @@ static const char *flag_user_parameter(const char *mac_name,
     if (local_scope == 0) {
        for (local_scope = master_table; local_scope->argv; local_scope++) {
            if (local_scope->all_params != 0
-               && dict_get(local_scope->all_params, mac_name) != 0
-           /* $name in main.cf references name=value in master.cf. */
-               && PC_PARAM_TABLE_LOCATE(local_scope->valid_names, mac_name) == 0) {
-               PC_PARAM_TABLE_ENTER(local_scope->valid_names, mac_name,
-                                    PC_PARAM_FLAG_USER, PC_PARAM_NO_DATA,
-                                    convert_user_parameter);
-               if (msg_verbose)
-                   msg_info("$%s in %s validates %s=value in %s:%s",
-                            mac_name, MAIN_CONF_FILE,
-                            mac_name, MASTER_CONF_FILE,
-                            local_scope->name_space);
+               && dict_get(local_scope->all_params, mac_name) != 0) {
+               user_supplied = 1;
+               /* $name in main.cf references name=value in master.cf. */
+               if (PC_PARAM_TABLE_LOCATE(local_scope->valid_names, mac_name) == 0) {
+                   PC_PARAM_TABLE_ENTER(local_scope->valid_names, mac_name,
+                                        param_class, PC_PARAM_NO_DATA,
+                                        convert_user_parameter);
+                   if (msg_verbose)
+                       msg_info("$%s in %s validates %s=value in %s:%s",
+                                mac_name, MAIN_CONF_FILE,
+                                mac_name, MASTER_CONF_FILE,
+                                local_scope->name_space);
+               }
            }
        }
     }
+
+    /*
+     * Warn about a $name that has no user-supplied explicit value or
+     * Postfix-supplied default value. We don't enforce this for legacy DBMS
+     * parameters because they exist only for backwards compatibility, so we
+     * don't bother to figure out which parameters come without defaults.
+     */
+    if (user_supplied == 0 && (param_class & PC_PARAM_FLAG_DBMS) == 0
+       && PC_PARAM_TABLE_LOCATE(param_table, mac_name) == 0)
+       msg_warn("%s/%s: undefined parameter: %s",
+                var_config_dir, source, mac_name);
     return (0);
 }
 
@@ -204,6 +229,7 @@ static void scan_user_parameter_namespace(const char *dict_name,
     const char *cparam_name;
     const char *cparam_value;
     PC_PARAM_NODE *node;
+    const char *source = local_scope ? MASTER_CONF_FILE : MAIN_CONF_FILE;
 
     /*
      * Flag parameter names in smtpd_restriction_classes as "valid", but only
@@ -217,7 +243,7 @@ static void scan_user_parameter_namespace(const char *dict_name,
            if (local_scope == 0
                && htable_locate(rest_class_table, param_name) == 0)
                htable_enter(rest_class_table, param_name, "");
-           FLAG_USER_PARAMETER(param_name, local_scope);
+           FLAG_USER_PARAMETER(param_name, PC_PARAM_FLAG_USER, local_scope);
        }
        myfree(saved_class_list);
     }
@@ -228,6 +254,9 @@ static void scan_user_parameter_namespace(const char *dict_name,
      * "valid" in the local name space; 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.
+     * 
+     * We delete name=value entries for read-only parameters, to maintain
+     * compatibility with Postfix programs that ignore such settings.
      */
     if ((dict = dict_handle(dict_name)) == 0)
        msg_panic("%s: parameter dictionary %s not found",
@@ -244,11 +273,24 @@ static void scan_user_parameter_namespace(const char *dict_name,
            PC_PARAM_TABLE_ENTER(local_scope->valid_names, cparam_name,
                                 PC_PARAM_FLAG_USER, PC_PARAM_NO_DATA,
                                 convert_user_parameter);
-       /* Skip "do not expand" parameters. */
-       if ((node = PC_PARAM_TABLE_FIND(param_table, cparam_name)) != 0
-           && PC_RAW_PARAMETER(node))
-           continue;
-       SCAN_USER_PARAMETER_VALUE(cparam_value, local_scope);
+       if ((node = PC_PARAM_TABLE_FIND(param_table, cparam_name)) != 0) {
+           if (PC_READONLY_PARAMETER(node)) {
+               msg_warn("%s/%s: read-only parameter assignment: %s=%s",
+                        var_config_dir, source, cparam_name, cparam_value);
+               /* Can't use dict_del() with Postfix<2.10 htable_sequence(). */
+               if (dict_del(dict, cparam_name) != 0)
+                   msg_panic("%s: can't delete %s/%s parameter entry for %s",
+                             myname, var_config_dir, source, cparam_name);
+               continue;
+           }
+           /* Re-label legacy parameter as user-defined, so it's printed. */
+           if (PC_LEGACY_PARAMETER(node))
+               PC_PARAM_CLASS_OVERRIDE(node, PC_PARAM_FLAG_USER);
+           /* Skip "do not expand" parameters. */
+           if (PC_RAW_PARAMETER(node))
+               continue;
+       }
+       SCAN_USER_PARAMETER_VALUE(cparam_value, PC_PARAM_FLAG_USER, local_scope);
 #ifdef LEGACY_DBMS_SUPPORT
        register_dbms_parameters(cparam_value, flag_user_parameter,
                                 local_scope);
@@ -279,7 +321,7 @@ static void scan_default_parameter_values(HTABLE *valid_params,
                                              PC_PARAM_INFO_NODE(*ht))) == 0)
            msg_panic("%s: parameter %s has no default value",
                      myname, PC_PARAM_INFO_NAME(*ht));
-       SCAN_USER_PARAMETER_VALUE(param_value, local_scope);
+       SCAN_USER_PARAMETER_VALUE(param_value, PC_PARAM_FLAG_USER, local_scope);
        /* No need to scan default values for legacy DBMS configuration. */
     }
     myfree((char *) list);
index 88277156155d1dbb729a2a58819843ada182dcce..2aa9903e6cf732a6a93f811ecb63047d90ef4e00 100644 (file)
@@ -1,3 +1,4 @@
+./postconf: warning: ./main.cf: undefined parameter: bar
 config_directory = .
 foo = yes
 smtpd_restriction_classes = foo bar
index 667c93d906155412b1fe2d954e3d480bef0a106b..0a430d273ebbf6dd0edb49ba4419064c08b0bfc3 100644 (file)
@@ -1,2 +1,4 @@
+./postconf: warning: ./master.cf: undefined parameter: bar
+./postconf: warning: ./master.cf: undefined parameter: baz
 foo        inet  -       n       n       -       0       spawn
     -o always_bcc=$bar$baz
index a16ae5e020b8eda295a0e7f332aaf873ed930ad4..f3310e1d9b7dbfe0ef8386dceb2c284e6cf8a3ba 100644 (file)
@@ -7,4 +7,4 @@ yy = aap
 zz_domain = whatever
 ./postconf: warning: ./main.cf: unused parameter: zz=$yy
 ./postconf: warning: ./main.cf: unused parameter: aa_domain=whatever
-./postconf: warning: ./main.cf: unused parameter: xx=proxy:ldap:foo
+./postconf: warning: ./main.cf: unused parameter: xx=ldap:foo
index 75a2efafd320031dae88c71633539adbacb16cb8..8ab8fdb53c4d04aaaad2c0859544760b9688ea1f 100644 (file)
@@ -4,13 +4,13 @@ memcachefoo_domain = bar
 mysqlfoo_domain = bar
 pgsqlfoo_domain = bar
 sqlitefoo_domain = bar
-./postconf: warning: ./main.cf: unused parameter: sqlitexx=proxy:sqlite:sqlitefoo
-./postconf: warning: ./main.cf: unused parameter: pgsqlxx=proxy:pgsql:pgsqlfoo
+./postconf: warning: ./main.cf: unused parameter: sqlitexx=sqlite:sqlitefoo
+./postconf: warning: ./main.cf: unused parameter: pgsqlxx=pgsql:pgsqlfoo
 ./postconf: warning: ./main.cf: unused parameter: memcachefoo_domainx=bar
 ./postconf: warning: ./main.cf: unused parameter: sqlitefoo_domainx=bar
-./postconf: warning: ./main.cf: unused parameter: memcachexx=proxy:memcache:memcachefoo
-./postconf: warning: ./main.cf: unused parameter: mysqlxx=proxy:mysql:mysqlfoo
-./postconf: warning: ./main.cf: unused parameter: ldapxx=proxy:ldap:ldapfoo
+./postconf: warning: ./main.cf: unused parameter: memcachexx=memcache:memcachefoo
+./postconf: warning: ./main.cf: unused parameter: mysqlxx=mysql:mysqlfoo
+./postconf: warning: ./main.cf: unused parameter: ldapxx=ldap:ldapfoo
 ./postconf: warning: ./main.cf: unused parameter: ldapfoo_domainx=bar
 ./postconf: warning: ./main.cf: unused parameter: pgsqlfoo_domainx=bar
 ./postconf: warning: ./main.cf: unused parameter: mysqlfoo_domainx=bar
diff --git a/postfix/src/postconf/test34.ref b/postfix/src/postconf/test34.ref
new file mode 100644 (file)
index 0000000..e771293
--- /dev/null
@@ -0,0 +1,4 @@
+./postconf: warning: ./main.cf: read-only parameter assignment: process_id=yyy
+./postconf: warning: ./main.cf: read-only parameter assignment: process_name=xxx
+mydestination = whatever
+process_name = postconf
diff --git a/postfix/src/postconf/test35.ref b/postfix/src/postconf/test35.ref
new file mode 100644 (file)
index 0000000..dc27f39
--- /dev/null
@@ -0,0 +1,3 @@
+./postconf: warning: ./master.cf: read-only parameter assignment: process_id=bbb
+./postconf: warning: ./master.cf: read-only parameter assignment: process_name=aaa
+process_name = postconf
diff --git a/postfix/src/postconf/test36.ref b/postfix/src/postconf/test36.ref
new file mode 100644 (file)
index 0000000..bf09921
--- /dev/null
@@ -0,0 +1,4 @@
+./postconf: warning: ./main.cf: undefined parameter: virtual_mapx
+config_directory = .
+mydestination =
+virtual_alias_maps =
diff --git a/postfix/src/postconf/test37.ref b/postfix/src/postconf/test37.ref
new file mode 100644 (file)
index 0000000..4da3f96
--- /dev/null
@@ -0,0 +1,2 @@
+whatever   unix  -       n       n       -       0       other
+    -o mydestination=yyy -o always_bcc=ccc -o aaa=ccc
diff --git a/postfix/src/postconf/test38.ref b/postfix/src/postconf/test38.ref
new file mode 100644 (file)
index 0000000..186ffc3
--- /dev/null
@@ -0,0 +1 @@
+bar        unix  -       n       n       -       0       other -o aaa=ccc
diff --git a/postfix/src/postconf/test39.ref b/postfix/src/postconf/test39.ref
new file mode 100644 (file)
index 0000000..35b078d
--- /dev/null
@@ -0,0 +1,2 @@
+foo        unix  -       n       n       -       0       other
+baz        unix  -       n       n       -       0       other
index aaa4f90fe9c3521047c50ca1dc0d1ede65b32006..a79676c862a9ba2dd707e96ad2bc25c77d352f6d 100644 (file)
@@ -48,6 +48,29 @@ typedef struct {
     HTABLE *table;                     /* hash table */
 } DICT_HT;
 
+/* dict_ht_delete - delete hash-table entry */
+
+static int dict_ht_delete(DICT *dict, const char *name)
+{
+    DICT_HT *dict_ht = (DICT_HT *) dict;
+
+    /*
+     * Optionally fold the key.
+     */
+    if (dict->flags & DICT_FLAG_FOLD_FIX) {
+       if (dict->fold_buf == 0)
+           dict->fold_buf = vstring_alloc(10);
+       vstring_strcpy(dict->fold_buf, name);
+       name = lowercase(vstring_str(dict->fold_buf));
+    }
+    if (htable_locate(dict_ht->table, name) == 0) {
+       DICT_ERR_VAL_RETURN(dict, DICT_ERR_NONE, DICT_STAT_FAIL);
+    } else {
+       htable_delete(dict_ht->table, name, myfree);
+       DICT_ERR_VAL_RETURN(dict, DICT_ERR_NONE, DICT_STAT_SUCCESS);
+    }
+}
+
 /* dict_ht_lookup - find hash-table entry */
 
 static const char *dict_ht_lookup(DICT *dict, const char *name)
@@ -136,6 +159,7 @@ DICT   *dict_ht_open(const char *name, int unused_open_flags, int dict_flags)
     dict_ht = (DICT_HT *) dict_alloc(DICT_TYPE_HT, name, sizeof(*dict_ht));
     dict_ht->dict.lookup = dict_ht_lookup;
     dict_ht->dict.update = dict_ht_update;
+    dict_ht->dict.delete = dict_ht_delete;
     dict_ht->dict.sequence = dict_ht_sequence;
     dict_ht->dict.close = dict_ht_close;
     dict_ht->dict.flags = dict_flags | DICT_FLAG_FIXED;
index 009e0fcdf0d1dacb656d4487ec12cb10c42f974c..110b94fc692bc100d256f70d9c6358d886a8c200 100644 (file)
@@ -94,7 +94,7 @@
 /*     on the value of the "how" argument.  Specify HTABLE_SEQ_FIRST
 /*     to start a new sequence, HTABLE_SEQ_NEXT to continue, and
 /*     HTABLE_SEQ_STOP to terminate a sequence early.  The caller
-/*     must not delete the current element.
+/*     must not delete an element before it is visited.
 /* RESTRICTIONS
 /*     A callback function should not modify the hash table that is
 /*     specified to its caller.
@@ -182,7 +182,7 @@ HTABLE *htable_create(int size)
 
     table = (HTABLE *) mymalloc(sizeof(HTABLE));
     htable_size(table, size < 13 ? 13 : size);
-    table->seq_element = 0;
+    table->seq_bucket = table->seq_element = 0;
     return (table);
 }
 
@@ -213,7 +213,7 @@ HTABLE_INFO *htable_enter(HTABLE *table, const char *key, char *value)
 {
     HTABLE_INFO *ht;
 
-    if (table->used >= table->size && table->seq_element == 0)
+    if (table->used >= table->size)
        htable_grow(table);
     ht = (HTABLE_INFO *) mymalloc(sizeof(HTABLE_INFO));
     ht->key = mystrdup(key);
@@ -303,6 +303,9 @@ void    htable_free(HTABLE *table, void (*free_fn) (char *))
        }
        myfree((char *) table->data);
        table->data = 0;
+       if (table->seq_bucket)
+           myfree((char *) table->seq_bucket);
+       table->seq_bucket = 0;
        myfree((char *) table);
     }
 }
@@ -352,23 +355,22 @@ HTABLE_INFO *htable_sequence(HTABLE *table, int how)
 
     switch (how) {
     case HTABLE_SEQ_FIRST:                     /* start new sequence */
-       table->seq_bucket = table->data;
-       table->seq_element = table->seq_bucket[0];
-       break;
+       if (table->seq_bucket)
+           myfree((char *) table->seq_bucket);
+       table->seq_bucket = htable_list(table);
+       table->seq_element = table->seq_bucket;
+       return (*(table->seq_element)++);
     case HTABLE_SEQ_NEXT:                      /* next element */
-       if (table->seq_element) {
-           table->seq_element = table->seq_element->next;
-           break;
-       }
+       if (table->seq_element && *table->seq_element)
+           return (*(table->seq_element)++);
        /* FALLTHROUGH */
     default:                                   /* terminate sequence */
-       return (table->seq_element = 0);
+       if (table->seq_bucket) {
+           myfree((char *) table->seq_bucket);
+           table->seq_bucket = table->seq_element = 0;
+       }
+       return (0);
     }
-
-    while (table->seq_element == 0
-          && ++(table->seq_bucket) < table->data + table->size)
-       table->seq_element = table->seq_bucket[0];
-    return (table->seq_element);
 }
 
 #ifdef TEST
index d82e4056207e5835e4197e2eeb7e3f4bd83552f5..52182518cacc78d94e1790463a2e8fbcf4d85b78 100644 (file)
@@ -27,7 +27,7 @@ typedef struct HTABLE {
     int     used;                      /* number of entries in table */
     HTABLE_INFO **data;                        /* entries array, auto-resized */
     HTABLE_INFO **seq_bucket;          /* current sequence hash bucket */
-    HTABLE_INFO *seq_element;          /* current sequence element */
+    HTABLE_INFO **seq_element;         /* current sequence element */
 } HTABLE;
 
 extern HTABLE *htable_create(int);