From: Wietse Venema Date: Mon, 24 Dec 2012 05:00:00 +0000 (-0500) Subject: postfix-2.10-20121224 X-Git-Tag: v2.10.0-RC1~7 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=1d2c74f60566f909db0569a07f822a1a221cb903;p=thirdparty%2Fpostfix.git postfix-2.10-20121224 --- diff --git a/postfix/.indent.pro b/postfix/.indent.pro index b7ea3324c..204f673d7 100644 --- a/postfix/.indent.pro +++ b/postfix/.indent.pro @@ -197,6 +197,7 @@ -TPC_DBMS_INFO -TPC_EVAL_CTX -TPC_MASTER_ENT +-TPC_PARAM_CTX -TPC_PARAM_NODE -TPC_SERVICE_DEF -TPC_STRING_NV diff --git a/postfix/HISTORY b/postfix/HISTORY index 2c8b8713e..8cabbf735 100644 --- a/postfix/HISTORY +++ b/postfix/HISTORY @@ -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. diff --git a/postfix/RELEASE_NOTES b/postfix/RELEASE_NOTES index dfb95f1f2..ccd464e83 100644 --- a/postfix/RELEASE_NOTES +++ b/postfix/RELEASE_NOTES @@ -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 ==================================== diff --git a/postfix/html/postconf.1.html b/postfix/html/postconf.1.html index 8b7afa1e4..3c7f55962 100644 --- a/postfix/html/postconf.1.html +++ b/postfix/html/postconf.1.html @@ -21,7 +21,7 @@ POSTCONF(1) POSTCONF(1) Managing master.cf: - postconf [-fMv] [-c config_dir] [service ...] + postconf [-fMnvx] [-c config_dir] [service ...] Managing bounce message templates: @@ -295,10 +295,12 @@ POSTCONF(1) POSTCONF(1) This feature is available with Postfix 2.9 and later. - -n Print main.cf parameter settings that are explic- - itly specified in main.cf. Specify -nf to fold - long lines for human readability (Postfix 2.9 and - later). + -n Print only name=value parameter settings that are + explicitly specified in main.cf. When specified + with -M, print only master.cf entries that have "-o + name=value" parameter settings (Postfix 2.10 and + later). Specify -nf to fold long lines for human + readability (Postfix 2.9 and later). -t [template_file] Display the templates for text that appears at the @@ -321,29 +323,32 @@ POSTCONF(1) POSTCONF(1) tiple -v options make the software increasingly verbose. - -x Expand $name in parameter values. The expansion is - recursive. + -x Expand $name in main.cf or master.cf parameter val- + ues. The expansion is recursive. + + This feature is available with Postfix 2.10 and + later. -X Edit the main.cf configuration file, and remove the - parameters named on the postconf(1) command line. + parameters named on the postconf(1) command line. The file is copied to a temporary file then renamed into place. Specify a list of parameter names, not - "name=value" pairs. There is no postconf(1) com- + "name=value" pairs. There is no postconf(1) 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. - -# Edit the main.cf configuration file, and comment + -# Edit the main.cf configuration file, and comment out the parameters named on the postconf(1) 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 "name=value" 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 "name=value" pairs. There is no postconf(1) 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. DIAGNOSTICS @@ -354,18 +359,18 @@ POSTCONF(1) POSTCONF(1) Directory with Postfix configuration files. CONFIGURATION PARAMETERS - The following main.cf parameters are especially relevant + The following main.cf parameters are especially relevant to this program. - The text below provides only a parameter summary. See + The text below provides only a parameter summary. See postconf(5) for more details including examples. config_directory (see 'postconf -d' output) - The default location of the Postfix main.cf and + The default location of the Postfix main.cf and master.cf configuration files. bounce_template_file (empty) - Pathname of a configuration file with bounce mes- + Pathname of a configuration file with bounce mes- sage templates. FILES @@ -381,7 +386,7 @@ POSTCONF(1) POSTCONF(1) DATABASE_README, Postfix lookup table overview LICENSE - The Secure Mailer license must be distributed with this + The Secure Mailer license must be distributed with this software. AUTHOR(S) diff --git a/postfix/man/man1/postconf.1 b/postfix/man/man1/postconf.1 index 4fca7a677..a9903f4ca 100644 --- a/postfix/man/man1/postconf.1 +++ b/postfix/man/man1/postconf.1 @@ -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. diff --git a/postfix/src/global/mail_version.h b/postfix/src/global/mail_version.h index 55f0b5d65..d3bbd539a 100644 --- a/postfix/src/global/mail_version.h +++ b/postfix/src/global/mail_version.h @@ -20,7 +20,7 @@ * Patches change both the patchlevel and the release date. Snapshots have no * patchlevel; they change the release date only. */ -#define MAIL_RELEASE_DATE "20121221" +#define MAIL_RELEASE_DATE "20121224" #define MAIL_VERSION_NUMBER "2.10" #ifdef SNAPSHOT diff --git a/postfix/src/postconf/Makefile.in b/postfix/src/postconf/Makefile.in index 18474fd5d..6b44aa677 100644 --- a/postfix/src/postconf/Makefile.in +++ b/postfix/src/postconf/Makefile.in @@ -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 diff --git a/postfix/src/postconf/extract.awk b/postfix/src/postconf/extract.awk index 3b7a189ff..7385788de 100644 --- a/postfix/src/postconf/extract.awk +++ b/postfix/src/postconf/extract.awk @@ -34,6 +34,15 @@ } } } +/^(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 diff --git a/postfix/src/postconf/postconf.c b/postfix/src/postconf/postconf.c index 401e50430..e4619e11b 100644 --- a/postfix/src/postconf/postconf.c +++ b/postfix/src/postconf/postconf.c @@ -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 @@ -253,8 +253,11 @@ /* /* 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]" @@ -276,8 +279,10 @@ /* 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) diff --git a/postfix/src/postconf/postconf.h b/postfix/src/postconf/postconf.h index 86e37d033..0f7e5864d 100644 --- a/postfix/src/postconf/postconf.h +++ b/postfix/src/postconf/postconf.h @@ -8,6 +8,11 @@ /* DESCRIPTION /* .nf + /* + * System library. + */ +#include + /* * 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. */ diff --git a/postfix/src/postconf/postconf_builtin.c b/postfix/src/postconf/postconf_builtin.c index 1e2fed674..239477ed5 100644 --- a/postfix/src/postconf/postconf_builtin.c +++ b/postfix/src/postconf/postconf_builtin.c @@ -6,10 +6,18 @@ /* SYNOPSIS /* #include /* -/* 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); } diff --git a/postfix/src/postconf/postconf_dbms.c b/postfix/src/postconf/postconf_dbms.c index 6ac07aa26..024c2bf5a 100644 --- a/postfix/src/postconf/postconf_dbms.c +++ b/postfix/src/postconf/postconf_dbms.c @@ -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 *) ¶m_ctx); } break; } diff --git a/postfix/src/postconf/postconf_lookup.c b/postfix/src/postconf/postconf_lookup.c new file mode 100644 index 000000000..6ad1b9f8c --- /dev/null +++ b/postfix/src/postconf/postconf_lookup.c @@ -0,0 +1,183 @@ +/*++ +/* NAME +/* postconf_lookup 3 +/* SUMMARY +/* parameter lookup routines +/* SYNOPSIS +/* #include +/* +/* 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 +#include + +/* Utility library. */ + +#include +#include +#include +#include +#include +#include + +/* Global library. */ + +#include + +/* Application-specific. */ + +#include + +#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)); +} diff --git a/postfix/src/postconf/postconf_main.c b/postfix/src/postconf/postconf_main.c index d2233dae1..21626cd2a 100644 --- a/postfix/src/postconf/postconf_main.c +++ b/postfix/src/postconf/postconf_main.c @@ -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 { diff --git a/postfix/src/postconf/postconf_master.c b/postfix/src/postconf/postconf_master.c index 0aa6c3a92..0e1ac970e 100644 --- a/postfix/src/postconf/postconf_master.c +++ b/postfix/src/postconf/postconf_master.c @@ -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. diff --git a/postfix/src/postconf/postconf_node.c b/postfix/src/postconf/postconf_node.c index 1047cfc07..afdf60219 100644 --- a/postfix/src/postconf/postconf_node.c +++ b/postfix/src/postconf/postconf_node.c @@ -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); } diff --git a/postfix/src/postconf/postconf_user.c b/postfix/src/postconf/postconf_user.c index c72406587..563da5c09 100644 --- a/postfix/src/postconf/postconf_user.c +++ b/postfix/src/postconf/postconf_user.c @@ -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); diff --git a/postfix/src/postconf/test1.ref b/postfix/src/postconf/test1.ref index 882771561..2aa9903e6 100644 --- a/postfix/src/postconf/test1.ref +++ b/postfix/src/postconf/test1.ref @@ -1,3 +1,4 @@ +./postconf: warning: ./main.cf: undefined parameter: bar config_directory = . foo = yes smtpd_restriction_classes = foo bar diff --git a/postfix/src/postconf/test20.ref b/postfix/src/postconf/test20.ref index 667c93d90..0a430d273 100644 --- a/postfix/src/postconf/test20.ref +++ b/postfix/src/postconf/test20.ref @@ -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 diff --git a/postfix/src/postconf/test28.ref b/postfix/src/postconf/test28.ref index a16ae5e02..f3310e1d9 100644 --- a/postfix/src/postconf/test28.ref +++ b/postfix/src/postconf/test28.ref @@ -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 diff --git a/postfix/src/postconf/test29.ref b/postfix/src/postconf/test29.ref index 75a2efafd..8ab8fdb53 100644 --- a/postfix/src/postconf/test29.ref +++ b/postfix/src/postconf/test29.ref @@ -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 index 000000000..e7712932f --- /dev/null +++ b/postfix/src/postconf/test34.ref @@ -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 index 000000000..dc27f397b --- /dev/null +++ b/postfix/src/postconf/test35.ref @@ -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 index 000000000..bf0992122 --- /dev/null +++ b/postfix/src/postconf/test36.ref @@ -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 index 000000000..4da3f96cd --- /dev/null +++ b/postfix/src/postconf/test37.ref @@ -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 index 000000000..186ffc340 --- /dev/null +++ b/postfix/src/postconf/test38.ref @@ -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 index 000000000..35b078de3 --- /dev/null +++ b/postfix/src/postconf/test39.ref @@ -0,0 +1,2 @@ +foo unix - n n - 0 other +baz unix - n n - 0 other diff --git a/postfix/src/util/dict_ht.c b/postfix/src/util/dict_ht.c index aaa4f90fe..a79676c86 100644 --- a/postfix/src/util/dict_ht.c +++ b/postfix/src/util/dict_ht.c @@ -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; diff --git a/postfix/src/util/htable.c b/postfix/src/util/htable.c index 009e0fcdf..110b94fc6 100644 --- a/postfix/src/util/htable.c +++ b/postfix/src/util/htable.c @@ -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 diff --git a/postfix/src/util/htable.h b/postfix/src/util/htable.h index d82e40562..52182518c 100644 --- a/postfix/src/util/htable.h +++ b/postfix/src/util/htable.h @@ -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);