7 /* Postfix configuration utility
10 /* \fBpostconf\fR [\fB-dhnv\fR] [\fB-c \fIconfig_dir\fR]
11 /* [\fIparameter ...\fR]
13 /* \fBpostconf\fR [\fB-aAmlv\fR] [\fB-c \fIconfig_dir\fR]
15 /* \fBpostconf\fR [\fB-ev\fR] [\fB-c \fIconfig_dir\fR]
16 /* [\fIparameter=value ...\fR]
18 /* \fBpostconf\fR [\fB-#v\fR] [\fB-c \fIconfig_dir\fR]
19 /* [\fIparameter ...\fR]
21 /* \fBpostconf\fR [\fB-btv\fR] [\fB-c \fIconfig_dir\fR] [\fItemplate_file\fR]
23 /* The \fBpostconf\fR(1) command displays the actual values
24 /* of configuration parameters, changes configuration parameter
25 /* values, or displays other configuration information about
26 /* the Postfix mail system.
30 /* List the available SASL server plug-in types. The SASL
31 /* plug-in type is selected with the \fBsmtpd_sasl_type\fR
32 /* configuration parameter by specifying one of the names
36 /* This server plug-in is available when Postfix is built with
37 /* Cyrus SASL support.
39 /* This server plug-in uses the Dovecot authentication server,
40 /* and is available when Postfix is built with any form of SASL
44 /* This feature is available with Postfix 2.3 and later.
46 /* List the available SASL client plug-in types. The SASL
47 /* plug-in type is selected with the \fBsmtp_sasl_type\fR or
48 /* \fBlmtp_sasl_type\fR configuration parameters by specifying
49 /* one of the names listed below.
52 /* This client plug-in is available when Postfix is built with
53 /* Cyrus SASL support.
56 /* This feature is available with Postfix 2.3 and later.
57 /* .IP "\fB-b\fR [\fItemplate_file\fR]"
58 /* Display the message text that appears at the beginning of
59 /* delivery status notification (DSN) messages, with $\fBname\fR
60 /* expressions replaced by actual values. To override the
61 /* built-in message text, specify a template file at the end
62 /* of the command line, or specify a template file in main.cf
63 /* with the \fBbounce_template_file\fR parameter.
64 /* To force selection of the built-in message text templates,
65 /* specify an empty template file name (in shell language: "").
67 /* This feature is available with Postfix 2.3 and later.
68 /* .IP "\fB-c \fIconfig_dir\fR"
69 /* The \fBmain.cf\fR configuration file is in the named directory
70 /* instead of the default configuration directory.
72 /* Print default parameter settings instead of actual settings.
74 /* Edit the \fBmain.cf\fR configuration file. The file is copied
75 /* to a temporary file then renamed into place. Parameters and
76 /* values are specified on the command line. Use quotes in order
77 /* to protect shell metacharacters and whitespace.
79 /* Show parameter values only, not the ``name = '' label
80 /* that normally precedes the value.
82 /* List the names of all supported mailbox locking methods.
83 /* Postfix supports the following methods:
86 /* A kernel-based advisory locking method for local files only.
87 /* This locking method is available on systems with a BSD
88 /* compatible library.
90 /* A kernel-based advisory locking method for local and remote files.
92 /* An application-level locking method. An application locks a file
93 /* named \fIfilename\fR by creating a file named \fIfilename\fB.lock\fR.
94 /* The application is expected to remove its own lock file, as well as
95 /* stale lock files that were left behind after abnormal termination.
98 /* List the names of all supported lookup table types. In Postfix
99 /* configuration files,
100 /* lookup tables are specified as \fItype\fB:\fIname\fR, where
101 /* \fItype\fR is one of the types listed below. The table \fIname\fR
102 /* syntax depends on the lookup table type as described in the
103 /* DATABASE_README document.
106 /* A sorted, balanced tree structure.
107 /* This is available on systems with support for Berkeley DB
110 /* A read-optimized structure with no support for incremental updates.
111 /* This is available on systems with support for CDB databases.
113 /* A table that associates values with Classless Inter-Domain Routing
114 /* (CIDR) patterns. This is described in \fBcidr_table\fR(5).
116 /* An indexed file type based on hashing.
117 /* This is available on systems with support for DBM databases.
119 /* The UNIX process environment array. The lookup key is the variable
120 /* name. Originally implemented for testing, someone may find this
123 /* An indexed file type based on hashing.
124 /* This is available on systems with support for Berkeley DB
126 /* .IP "\fBldap\fR (read-only)"
127 /* Perform lookups using the LDAP protocol. This is described
128 /* in \fBldap_table\fR(5).
129 /* .IP "\fBmysql\fR (read-only)"
130 /* Perform lookups using the MYSQL protocol. This is described
131 /* in \fBmysql_table\fR(5).
132 /* .IP "\fBpcre\fR (read-only)"
133 /* A lookup table based on Perl Compatible Regular Expressions. The
134 /* file format is described in \fBpcre_table\fR(5).
135 /* .IP "\fBpgsql\fR (read-only)"
136 /* Perform lookups using the PostgreSQL protocol. This is described
137 /* in \fBpgsql_table\fR(5).
138 /* .IP "\fBproxy\fR (read-only)"
139 /* A lookup table that is implemented via the Postfix
140 /* \fBproxymap\fR(8) service. The table name syntax is
141 /* \fItype\fB:\fIname\fR.
142 /* .IP "\fBregexp\fR (read-only)"
143 /* A lookup table based on regular expressions. The file format is
144 /* described in \fBregexp_table\fR(5).
146 /* An indexed file type based on hashing.
147 /* This is available on systems with support for SDBM databases.
148 /* .IP "\fBstatic\fR (read-only)"
149 /* A table that always returns its name as lookup result. For example,
150 /* \fBstatic:foobar\fR always returns the string \fBfoobar\fR as lookup
152 /* .IP "\fBtcp\fR (read-only)"
153 /* Perform lookups using a simple request-reply protocol that is
154 /* described in \fBtcp_table\fR(5).
155 /* This feature is not included with the stable Postfix release.
156 /* .IP "\fBunix\fR (read-only)"
157 /* A limited way to query the UNIX authentication database. The
158 /* following tables are implemented:
160 /*. IP \fBunix:passwd.byname\fR
161 /* The table is the UNIX password database. The key is a login name.
162 /* The result is a password file entry in \fBpasswd\fR(5) format.
163 /* .IP \fBunix:group.byname\fR
164 /* The table is the UNIX group database. The key is a group name.
165 /* The result is a group file entry in \fBgroup\fR(5) format.
169 /* Other table types may exist depending on how Postfix was built.
171 /* Print parameter settings that are not left at their built-in
172 /* default value, because they are explicitly specified in main.cf.
173 /* .IP "\fB-t\fR [\fItemplate_file\fR]"
174 /* Display the templates for delivery status notification (DSN)
175 /* messages. To override the built-in templates, specify a
176 /* template file at the end of the command line, or specify a
177 /* template file in main.cf with the \fBbounce_template_file\fR
178 /* parameter. To force selection of the built-in templates,
179 /* specify an empty template file name (in shell language:
182 /* This feature is available with Postfix 2.3 and later.
184 /* Enable verbose logging for debugging purposes. Multiple \fB-v\fR
185 /* options make the software increasingly verbose.
187 /* Edit the \fBmain.cf\fR configuration file. The file is copied
188 /* to a temporary file then renamed into place. The parameters
189 /* specified on the command line are commented-out, so that they
190 /* revert to their default values. Specify a list of parameter
191 /* names, not name=value pairs. There is no \fBpostconf\fR command
192 /* to perform the reverse operation.
194 /* This feature is available with Postfix 2.6 and later.
196 /* Problems are reported to the standard error stream.
200 /* .IP \fBMAIL_CONFIG\fR
201 /* Directory with Postfix configuration files.
202 /* CONFIGURATION PARAMETERS
205 /* The following \fBmain.cf\fR parameters are especially relevant to
208 /* The text below provides only a parameter summary. See
209 /* \fBpostconf\fR(5) for more details including examples.
210 /* .IP "\fBconfig_directory (see 'postconf -d' output)\fR"
211 /* The default location of the Postfix main.cf and master.cf
212 /* configuration files.
213 /* .IP "\fBbounce_template_file (empty)\fR"
214 /* Pathname of a configuration file with bounce message templates.
216 /* /etc/postfix/main.cf, Postfix configuration parameters
218 /* bounce(5), bounce template file format
219 /* postconf(5), configuration parameters
223 /* Use "\fBpostconf readme_directory\fR" or
224 /* "\fBpostconf html_directory\fR" to locate this information.
227 /* DATABASE_README, Postfix lookup table overview
231 /* The Secure Mailer license must be distributed with this software.
234 /* IBM T.J. Watson Research
236 /* Yorktown Heights, NY 10598, USA
239 /* System library. */
241 #include <sys_defs.h>
242 #include <sys/stat.h>
243 #include <stdio.h> /* rename() */
254 /* Utility library. */
258 #include <msg_vstream.h>
259 #include <get_hostname.h>
260 #include <stringops.h>
264 #include <mymalloc.h>
266 #include <split_at.h>
267 #include <vstring_vstream.h>
269 #include <inet_proto.h>
271 #include <edit_file.h>
273 /* Global library. */
275 #include <mynetworks.h>
276 #include <mail_conf.h>
277 #include <mail_dict.h>
278 #include <mail_proto.h>
279 #include <mail_version.h>
280 #include <mail_params.h>
281 #include <mail_addr.h>
282 #include <mbox_conf.h>
283 #include <mail_run.h>
290 * What we're supposed to be doing.
292 #define SHOW_NONDEF (1<<0) /* show non-default settings */
293 #define SHOW_DEFS (1<<1) /* show default setting */
294 #define SHOW_NAME (1<<2) /* show parameter name */
295 #define SHOW_MAPS (1<<3) /* show map types */
296 #define EDIT_MAIN (1<<4) /* edit main.cf */
297 #define SHOW_LOCKS (1<<5) /* show mailbox lock methods */
298 #define SHOW_EVAL (1<<6) /* expand right-hand sides */
299 #define SHOW_SASL_SERV (1<<7) /* show server auth plugin types */
300 #define SHOW_SASL_CLNT (1<<8) /* show client auth plugin types */
301 #define COMMENT_OUT (1<<9) /* #-out selected main.cf entries */
304 * Lookup table for in-core parameter info.
309 * Lookup table for external parameter info.
314 * Declarations generated by scanning actual C source files.
316 #include "time_vars.h"
317 #include "bool_vars.h"
318 #include "int_vars.h"
319 #include "str_vars.h"
320 #include "raw_vars.h"
321 #include "nint_vars.h"
324 * Manually extracted.
326 #include "auto_vars.h"
327 #include "install_vars.h"
330 * Lookup tables generated by scanning actual C source files.
332 static const CONFIG_TIME_TABLE time_table
[] = {
333 #include "time_table.h"
337 static const CONFIG_BOOL_TABLE bool_table
[] = {
338 #include "bool_table.h"
342 static const CONFIG_INT_TABLE int_table
[] = {
343 #include "int_table.h"
347 static const CONFIG_STR_TABLE str_table
[] = {
348 #include "str_table.h"
349 #include "auto_table.h" /* XXX */
350 #include "install_table.h"
354 static const CONFIG_RAW_TABLE raw_table
[] = {
355 #include "raw_table.h"
359 static const CONFIG_NINT_TABLE nint_table
[] = {
360 #include "nint_table.h"
365 * Parameters with default values obtained via function calls.
367 char *var_myhostname
;
369 char *var_mynetworks
;
371 static const char *check_myhostname(void);
372 static const char *check_mydomainname(void);
373 static const char *check_mynetworks(void);
375 static const CONFIG_STR_FN_TABLE str_fn_table
[] = {
376 VAR_MYHOSTNAME
, check_myhostname
, &var_myhostname
, 1, 0,
377 VAR_MYDOMAIN
, check_mydomainname
, &var_mydomain
, 1, 0,
380 static const CONFIG_STR_FN_TABLE str_fn_table_2
[] = {
381 VAR_MYNETWORKS
, check_mynetworks
, &var_mynetworks
, 1, 0,
386 * XXX Global so that call-backs can see it.
388 static int cmd_mode
= SHOW_NAME
;
390 /* check_myhostname - lookup hostname and validate */
392 static const char *check_myhostname(void)
394 static const char *name
;
405 * If the local machine name is not in FQDN form, try to append the
406 * contents of $mydomain.
408 name
= get_hostname();
409 if ((dot
= strchr(name
, '.')) == 0) {
410 if ((domain
= mail_conf_lookup_eval(VAR_MYDOMAIN
)) == 0)
411 domain
= DEF_MYDOMAIN
;
412 name
= concatenate(name
, ".", domain
, (char *) 0);
417 /* get_myhostname - look up and store my hostname */
419 static void get_myhostname(void)
423 if ((name
= mail_conf_lookup_eval(VAR_MYHOSTNAME
)) == 0)
424 name
= check_myhostname();
425 var_myhostname
= mystrdup(name
);
428 /* check_mydomainname - lookup domain name and validate */
430 static const char *check_mydomainname(void)
435 * Use the hostname when it is not a FQDN ("foo"), or when the hostname
436 * actually is a domain name ("foo.com").
438 if (var_myhostname
== 0)
440 if ((dot
= strchr(var_myhostname
, '.')) == 0 || strchr(dot
+ 1, '.') == 0)
441 return (DEF_MYDOMAIN
);
445 /* check_mynetworks - lookup network address list */
447 static const char *check_mynetworks(void)
449 INET_PROTO_INFO
*proto_info
;
452 if (var_inet_interfaces
== 0) {
453 if ((cmd_mode
& SHOW_DEFS
)
454 || (junk
= mail_conf_lookup_eval(VAR_INET_INTERFACES
)) == 0)
455 junk
= DEF_INET_INTERFACES
;
456 var_inet_interfaces
= mystrdup(junk
);
458 if (var_mynetworks_style
== 0) {
459 if ((cmd_mode
& SHOW_DEFS
)
460 || (junk
= mail_conf_lookup_eval(VAR_MYNETWORKS_STYLE
)) == 0)
461 junk
= DEF_MYNETWORKS_STYLE
;
462 var_mynetworks_style
= mystrdup(junk
);
464 if (var_inet_protocols
== 0) {
465 if ((cmd_mode
& SHOW_DEFS
)
466 || (junk
= mail_conf_lookup_eval(VAR_INET_PROTOCOLS
)) == 0)
467 junk
= DEF_INET_PROTOCOLS
;
468 var_inet_protocols
= mystrdup(junk
);
469 proto_info
= inet_proto_init(VAR_INET_PROTOCOLS
, var_inet_protocols
);
471 return (mynetworks());
474 /* edit_parameters - edit parameter file */
476 static void edit_parameters(int cmd_mode
, int argc
, char **argv
)
483 VSTRING
*buf
= vstring_alloc(100);
484 VSTRING
*key
= vstring_alloc(10);
493 struct cvalue
*cvalue
;
494 HTABLE_INFO
**ht_info
;
500 * Store command-line parameters for quick lookup.
502 table
= htable_create(argc
);
503 while ((cp
= *argv
++) != 0) {
504 if (strchr(cp
, '\n') != 0)
505 msg_fatal("-e or -# accepts no multi-line input");
509 msg_fatal("-e or -# accepts no comment input");
510 if (cmd_mode
& EDIT_MAIN
) {
511 if ((err
= split_nameval(cp
, &edit_key
, &edit_val
)) != 0)
512 msg_fatal("%s: \"%s\"", err
, cp
);
513 } else if (cmd_mode
& COMMENT_OUT
) {
515 msg_fatal("-# requires non-blank parameter names");
516 if (strchr(cp
, '=') != 0)
517 msg_fatal("-# requires parameter names only");
518 edit_key
= mystrdup(cp
);
519 trimblanks(edit_key
, 0);
522 msg_panic("edit_parameters: unknown mode %d", cmd_mode
);
524 cvalue
= (struct cvalue
*) mymalloc(sizeof(*cvalue
));
525 cvalue
->value
= edit_val
;
527 htable_enter(table
, edit_key
, (char *) cvalue
);
531 * XXX Avoid code duplication by better code decomposition.
534 myfree(var_config_dir
);
535 var_config_dir
= mystrdup((config_dir
= safe_getenv(CONF_ENV_PATH
)) != 0 ?
536 config_dir
: DEF_CONFIG_DIR
); /* XXX */
537 set_mail_conf_str(VAR_CONFIG_DIR
, var_config_dir
);
540 * Open a temp file for the result. This uses a deterministic name so we
541 * don't leave behind thrash with random names.
543 path
= concatenate(var_config_dir
, "/", "main.cf", (char *) 0);
544 if ((ep
= edit_file_open(path
, O_CREAT
| O_WRONLY
, 0644)) == 0)
545 msg_fatal("open %s%s: %m", path
, EDIT_FILE_SUFFIX
);
549 * Open the original file for input.
551 if ((src
= vstream_fopen(path
, O_RDONLY
, 0)) == 0) {
552 /* OK to delete, since we control the temp file name exclusively. */
553 (void) unlink(ep
->tmp_path
);
554 msg_fatal("open %s for reading: %m", path
);
558 * Copy original file to temp file, while replacing parameters on the
559 * fly. Issue warnings for names found multiple times.
561 #define STR(x) vstring_str(x)
564 while (vstring_get(buf
, src
) != VSTREAM_EOF
) {
565 for (cp
= STR(buf
); ISSPACE(*cp
) /* including newline */ ; cp
++)
567 /* Copy comment, all-whitespace, or empty line. */
568 if (*cp
== '#' || *cp
== 0) {
569 vstream_fputs(STR(buf
), dst
);
571 /* Copy, skip or replace continued text. */
572 else if (cp
> STR(buf
)) {
573 if (interesting
== 0)
574 vstream_fputs(STR(buf
), dst
);
575 else if (cmd_mode
& COMMENT_OUT
)
576 vstream_fprintf(dst
, "#%s", STR(buf
));
578 /* Copy or replace start of logical line. */
580 vstring_strncpy(key
, cp
, strcspn(cp
, " \t\r\n="));
581 cvalue
= (struct cvalue
*) htable_find(table
, STR(key
));
582 if ((interesting
= !!cvalue
) != 0) {
583 if (cvalue
->found
++ == 1)
584 msg_warn("%s: multiple entries for \"%s\"", path
, STR(key
));
585 if (cmd_mode
& EDIT_MAIN
)
586 vstream_fprintf(dst
, "%s = %s\n", STR(key
), cvalue
->value
);
587 else if (cmd_mode
& COMMENT_OUT
)
588 vstream_fprintf(dst
, "#%s", cp
);
590 msg_panic("edit_parameters: unknown mode %d", cmd_mode
);
592 vstream_fputs(STR(buf
), dst
);
598 * Generate new entries for parameters that were not found.
600 if (cmd_mode
& EDIT_MAIN
) {
601 for (ht_info
= ht
= htable_list(table
); *ht
; ht
++) {
602 cvalue
= (struct cvalue
*) ht
[0]->value
;
603 if (cvalue
->found
== 0)
604 vstream_fprintf(dst
, "%s = %s\n", ht
[0]->key
, cvalue
->value
);
606 myfree((char *) ht_info
);
610 * When all is well, rename the temp file to the original one.
612 if (vstream_fclose(src
))
613 msg_fatal("read %s: %m", path
);
614 if (edit_file_close(ep
) != 0)
615 msg_fatal("close %s%s: %m", path
, EDIT_FILE_SUFFIX
);
623 htable_free(table
, myfree
);
626 /* read_parameters - read parameter info from file */
628 static void read_parameters(void)
634 * A direct rip-off of mail_conf_read(). XXX Avoid code duplication by
635 * better code decomposition.
637 dict_unknown_allowed
= 1;
639 myfree(var_config_dir
);
640 var_config_dir
= mystrdup((config_dir
= safe_getenv(CONF_ENV_PATH
)) != 0 ?
641 config_dir
: DEF_CONFIG_DIR
); /* XXX */
642 set_mail_conf_str(VAR_CONFIG_DIR
, var_config_dir
);
643 path
= concatenate(var_config_dir
, "/", "main.cf", (char *) 0);
644 dict_load_file(CONFIG_DICT
, path
);
648 /* set_parameters - set parameter values from default or explicit setting */
650 static void set_parameters(void)
654 * Populate the configuration parameter dictionary with default settings
655 * or with actual settings.
657 * Iterate over each entry in str_fn_table, str_fn_table_2, time_table,
658 * bool_table, int_table, str_table, and raw_table. Look up each
659 * parameter name in the configuration parameter dictionary. If the
660 * parameter is not set, take the default value, or take the value from
661 * main.cf, without doing $name expansions. This includes converting
662 * default values from numeric/boolean internal forms to external string
665 * Once the configuration parameter dictionary is populated, printing a
666 * parameter setting is a matter of querying the configuration parameter
667 * dictionary, optionally expanding of $name values, and printing the
672 /* hash_parameters - hash all parameter names so we can find and sort them */
674 static void hash_parameters(void)
676 const CONFIG_TIME_TABLE
*ctt
;
677 const CONFIG_BOOL_TABLE
*cbt
;
678 const CONFIG_INT_TABLE
*cit
;
679 const CONFIG_STR_TABLE
*cst
;
680 const CONFIG_STR_FN_TABLE
*csft
;
681 const CONFIG_RAW_TABLE
*rst
;
682 const CONFIG_NINT_TABLE
*nst
;
684 param_table
= htable_create(100);
686 for (ctt
= time_table
; ctt
->name
; ctt
++)
687 htable_enter(param_table
, ctt
->name
, (char *) ctt
);
688 for (cbt
= bool_table
; cbt
->name
; cbt
++)
689 htable_enter(param_table
, cbt
->name
, (char *) cbt
);
690 for (cit
= int_table
; cit
->name
; cit
++)
691 htable_enter(param_table
, cit
->name
, (char *) cit
);
692 for (cst
= str_table
; cst
->name
; cst
++)
693 htable_enter(param_table
, cst
->name
, (char *) cst
);
694 for (csft
= str_fn_table
; csft
->name
; csft
++)
695 htable_enter(param_table
, csft
->name
, (char *) csft
);
696 for (csft
= str_fn_table_2
; csft
->name
; csft
++)
697 htable_enter(param_table
, csft
->name
, (char *) csft
);
698 for (rst
= raw_table
; rst
->name
; rst
++)
699 htable_enter(param_table
, rst
->name
, (char *) rst
);
700 for (nst
= nint_table
; nst
->name
; nst
++)
701 htable_enter(param_table
, nst
->name
, (char *) nst
);
704 /* show_strval - show string-valued parameter */
706 static void show_strval(int mode
, const char *name
, const char *value
)
708 if (mode
& SHOW_EVAL
)
709 value
= mail_conf_eval(value
);
711 if (mode
& SHOW_NAME
) {
712 vstream_printf("%s = %s\n", name
, value
);
714 vstream_printf("%s\n", value
);
718 /* show_intval - show integer-valued parameter */
720 static void show_intval(int mode
, const char *name
, int value
)
722 if (mode
& SHOW_NAME
) {
723 vstream_printf("%s = %d\n", name
, value
);
725 vstream_printf("%d\n", value
);
729 /* print_bool - print boolean parameter */
731 static void print_bool(int mode
, CONFIG_BOOL_TABLE
*cbt
)
735 if (mode
& SHOW_DEFS
) {
736 show_strval(mode
, cbt
->name
, cbt
->defval
? "yes" : "no");
738 value
= dict_lookup(CONFIG_DICT
, cbt
->name
);
739 if ((mode
& SHOW_NONDEF
) == 0) {
741 show_strval(mode
, cbt
->name
, cbt
->defval
? "yes" : "no");
743 show_strval(mode
, cbt
->name
, value
);
747 show_strval(mode
, cbt
->name
, value
);
752 /* print_time - print relative time parameter */
754 static void print_time(int mode
, CONFIG_TIME_TABLE
*ctt
)
758 if (mode
& SHOW_DEFS
) {
759 show_strval(mode
, ctt
->name
, ctt
->defval
);
761 value
= dict_lookup(CONFIG_DICT
, ctt
->name
);
762 if ((mode
& SHOW_NONDEF
) == 0) {
764 show_strval(mode
, ctt
->name
, ctt
->defval
);
766 show_strval(mode
, ctt
->name
, value
);
770 show_strval(mode
, ctt
->name
, value
);
775 /* print_int - print integer parameter */
777 static void print_int(int mode
, CONFIG_INT_TABLE
*cit
)
781 if (mode
& SHOW_DEFS
) {
782 show_intval(mode
, cit
->name
, cit
->defval
);
784 value
= dict_lookup(CONFIG_DICT
, cit
->name
);
785 if ((mode
& SHOW_NONDEF
) == 0) {
787 show_intval(mode
, cit
->name
, cit
->defval
);
789 show_strval(mode
, cit
->name
, value
);
793 show_strval(mode
, cit
->name
, value
);
798 /* print_str - print string parameter */
800 static void print_str(int mode
, CONFIG_STR_TABLE
*cst
)
804 if (mode
& SHOW_DEFS
) {
805 show_strval(mode
, cst
->name
, cst
->defval
);
807 value
= dict_lookup(CONFIG_DICT
, cst
->name
);
808 if ((mode
& SHOW_NONDEF
) == 0) {
810 show_strval(mode
, cst
->name
, cst
->defval
);
812 show_strval(mode
, cst
->name
, value
);
816 show_strval(mode
, cst
->name
, value
);
821 /* print_str_fn - print string-function parameter */
823 static void print_str_fn(int mode
, CONFIG_STR_FN_TABLE
*csft
)
827 if (mode
& SHOW_DEFS
) {
828 show_strval(mode
, csft
->name
, csft
->defval());
830 value
= dict_lookup(CONFIG_DICT
, csft
->name
);
831 if ((mode
& SHOW_NONDEF
) == 0) {
833 show_strval(mode
, csft
->name
, csft
->defval());
835 show_strval(mode
, csft
->name
, value
);
839 show_strval(mode
, csft
->name
, value
);
844 /* print_str_fn_2 - print string-function parameter */
846 static void print_str_fn_2(int mode
, CONFIG_STR_FN_TABLE
*csft
)
850 if (mode
& SHOW_DEFS
) {
851 show_strval(mode
, csft
->name
, csft
->defval());
853 value
= dict_lookup(CONFIG_DICT
, csft
->name
);
854 if ((mode
& SHOW_NONDEF
) == 0) {
856 show_strval(mode
, csft
->name
, csft
->defval());
858 show_strval(mode
, csft
->name
, value
);
862 show_strval(mode
, csft
->name
, value
);
867 /* print_raw - print raw string parameter */
869 static void print_raw(int mode
, CONFIG_RAW_TABLE
* rst
)
873 if (mode
& SHOW_EVAL
)
874 msg_warn("parameter %s expands at run-time", rst
->name
);
877 if (mode
& SHOW_DEFS
) {
878 show_strval(mode
, rst
->name
, rst
->defval
);
880 value
= dict_lookup(CONFIG_DICT
, rst
->name
);
881 if ((mode
& SHOW_NONDEF
) == 0) {
883 show_strval(mode
, rst
->name
, rst
->defval
);
885 show_strval(mode
, rst
->name
, value
);
889 show_strval(mode
, rst
->name
, value
);
894 /* print_nint - print new integer parameter */
896 static void print_nint(int mode
, CONFIG_NINT_TABLE
* rst
)
900 if (mode
& SHOW_EVAL
)
901 msg_warn("parameter %s expands at run-time", rst
->name
);
904 if (mode
& SHOW_DEFS
) {
905 show_strval(mode
, rst
->name
, rst
->defval
);
907 value
= dict_lookup(CONFIG_DICT
, rst
->name
);
908 if ((mode
& SHOW_NONDEF
) == 0) {
910 show_strval(mode
, rst
->name
, rst
->defval
);
912 show_strval(mode
, rst
->name
, value
);
916 show_strval(mode
, rst
->name
, value
);
921 /* print_parameter - show specific parameter */
923 static void print_parameter(int mode
, char *ptr
)
926 #define INSIDE(p,t) (ptr >= (char *) t && ptr < ((char *) t) + sizeof(t))
929 * This is gross, but the best we can do on short notice.
931 if (INSIDE(ptr
, time_table
))
932 print_time(mode
, (CONFIG_TIME_TABLE
*) ptr
);
933 if (INSIDE(ptr
, bool_table
))
934 print_bool(mode
, (CONFIG_BOOL_TABLE
*) ptr
);
935 if (INSIDE(ptr
, int_table
))
936 print_int(mode
, (CONFIG_INT_TABLE
*) ptr
);
937 if (INSIDE(ptr
, str_table
))
938 print_str(mode
, (CONFIG_STR_TABLE
*) ptr
);
939 if (INSIDE(ptr
, str_fn_table
))
940 print_str_fn(mode
, (CONFIG_STR_FN_TABLE
*) ptr
);
941 if (INSIDE(ptr
, str_fn_table_2
))
942 print_str_fn_2(mode
, (CONFIG_STR_FN_TABLE
*) ptr
);
943 if (INSIDE(ptr
, raw_table
))
944 print_raw(mode
, (CONFIG_RAW_TABLE
*) ptr
);
945 if (INSIDE(ptr
, nint_table
))
946 print_nint(mode
, (CONFIG_NINT_TABLE
*) ptr
);
948 vstream_fflush(VSTREAM_OUT
);
951 /* comp_names - qsort helper */
953 static int comp_names(const void *a
, const void *b
)
955 HTABLE_INFO
**ap
= (HTABLE_INFO
**) a
;
956 HTABLE_INFO
**bp
= (HTABLE_INFO
**) b
;
958 return (strcmp(ap
[0]->key
, bp
[0]->key
));
961 /* show_maps - show available maps */
963 static void show_maps(void)
968 maps_argv
= dict_mapnames();
969 for (i
= 0; i
< maps_argv
->argc
; i
++)
970 vstream_printf("%s\n", maps_argv
->argv
[i
]);
971 argv_free(maps_argv
);
974 /* show_locks - show available mailbox locking methods */
976 static void show_locks(void)
981 locks_argv
= mbox_lock_names();
982 for (i
= 0; i
< locks_argv
->argc
; i
++)
983 vstream_printf("%s\n", locks_argv
->argv
[i
]);
984 argv_free(locks_argv
);
987 /* show_sasl - show SASL plug-in types */
989 static void show_sasl(int what
)
994 sasl_argv
= (what
& SHOW_SASL_SERV
) ? xsasl_server_types() :
995 xsasl_client_types();
996 for (i
= 0; i
< sasl_argv
->argc
; i
++)
997 vstream_printf("%s\n", sasl_argv
->argv
[i
]);
998 argv_free(sasl_argv
);
1001 /* show_parameters - show parameter info */
1003 static void show_parameters(int mode
, char **names
)
1011 * Show all parameters.
1014 list
= htable_list(param_table
);
1015 qsort((char *) list
, param_table
->used
, sizeof(*list
), comp_names
);
1016 for (ht
= list
; *ht
; ht
++)
1017 print_parameter(mode
, ht
[0]->value
);
1018 myfree((char *) list
);
1023 * Show named parameters.
1025 for (namep
= names
; *namep
; namep
++) {
1026 if ((value
= htable_find(param_table
, *namep
)) == 0) {
1027 msg_warn("%s: unknown parameter", *namep
);
1029 print_parameter(mode
, value
);
1034 MAIL_VERSION_STAMP_DECLARE
;
1038 int main(int argc
, char **argv
)
1047 * Fingerprint executables and core dumps.
1049 MAIL_VERSION_STAMP_ALLOCATE
;
1052 * Be consistent with file permissions.
1057 * To minimize confusion, make sure that the standard file descriptors
1058 * are open before opening anything else. XXX Work around for 44BSD where
1059 * fstat can return EBADF on an open file descriptor.
1061 for (fd
= 0; fd
< 3; fd
++)
1062 if (fstat(fd
, &st
) == -1
1063 && (close(fd
), open("/dev/null", O_RDWR
, 0)) != fd
)
1064 msg_fatal("open /dev/null: %m");
1069 msg_vstream_init(argv
[0], VSTREAM_ERR
);
1074 while ((ch
= GETOPT(argc
, argv
, "aAbc:deE#hmlntv")) > 0) {
1077 cmd_mode
|= SHOW_SASL_SERV
;
1080 cmd_mode
|= SHOW_SASL_CLNT
;
1084 msg_fatal("specify one of -b and -t");
1085 ext_argv
= argv_alloc(2);
1086 argv_add(ext_argv
, "bounce", "-SVnexpand_templates", (char *) 0);
1089 if (setenv(CONF_ENV_PATH
, optarg
, 1) < 0)
1090 msg_fatal("out of memory");
1093 cmd_mode
|= SHOW_DEFS
;
1096 cmd_mode
|= EDIT_MAIN
;
1100 * People, this does not work unless you properly handle default
1101 * settings. For example, fast_flush_domains = $relay_domains
1102 * must not evaluate to the empty string when relay_domains is
1103 * left at its default setting of $mydestination.
1107 cmd_mode
|= SHOW_EVAL
;
1111 cmd_mode
= COMMENT_OUT
;
1115 cmd_mode
&= ~SHOW_NAME
;
1118 cmd_mode
|= SHOW_LOCKS
;
1121 cmd_mode
|= SHOW_MAPS
;
1124 cmd_mode
|= SHOW_NONDEF
;
1128 msg_fatal("specify one of -b and -t");
1129 ext_argv
= argv_alloc(2);
1130 argv_add(ext_argv
, "bounce", "-SVndump_templates", (char *) 0);
1136 msg_fatal("usage: %s [-a (server SASL types)] [-A (client SASL types)] [-b (bounce templates)] [-c config_dir] [-d (defaults)] [-e (edit)] [-# (comment-out)] [-h (no names)] [-l (lock types)] [-m (map types)] [-n (non-defaults)] [-v] [name...]", argv
[0]);
1143 junk
= (cmd_mode
& (SHOW_DEFS
| SHOW_NONDEF
| SHOW_MAPS
| SHOW_LOCKS
| EDIT_MAIN
| SHOW_SASL_SERV
| SHOW_SASL_CLNT
| COMMENT_OUT
));
1144 if (junk
!= 0 && ((junk
!= SHOW_DEFS
&& junk
!= SHOW_NONDEF
1145 && junk
!= SHOW_MAPS
&& junk
!= SHOW_LOCKS
&& junk
!= EDIT_MAIN
1146 && junk
!= SHOW_SASL_SERV
&& junk
!= SHOW_SASL_CLNT
1147 && junk
!= COMMENT_OUT
)
1149 msg_fatal("specify one of -a, -A, -b, -d, -e, -#, -m, -l and -n");
1152 * Display bounce template information and exit.
1156 if (argv
[optind
+ 1])
1157 msg_fatal("options -b and -t require at most one template file");
1158 argv_add(ext_argv
, "-o",
1159 concatenate(VAR_BOUNCE_TMPL
, "=",
1160 argv
[optind
], (char *) 0),
1164 argv_add(ext_argv
, "-o",
1165 concatenate(VAR_QUEUE_DIR
, "=", ".", (char *) 0),
1168 mail_run_replace(var_daemon_dir
, ext_argv
->argv
);
1173 * If showing map types, show them and exit
1175 if (cmd_mode
& SHOW_MAPS
) {
1181 * If showing locking methods, show them and exit
1183 else if (cmd_mode
& SHOW_LOCKS
) {
1188 * If showing SASL plug-in types, show them and exit
1190 else if (cmd_mode
& SHOW_SASL_SERV
) {
1191 show_sasl(SHOW_SASL_SERV
);
1192 } else if (cmd_mode
& SHOW_SASL_CLNT
) {
1193 show_sasl(SHOW_SASL_CLNT
);
1199 else if (cmd_mode
& (EDIT_MAIN
| COMMENT_OUT
)) {
1200 edit_parameters(cmd_mode
, argc
- optind
, argv
+ optind
);
1204 * If showing non-default values, read main.cf.
1207 if ((cmd_mode
& SHOW_DEFS
) == 0) {
1213 * Throw together all parameters and show the asked values.
1216 show_parameters(cmd_mode
, argv
+ optind
);
1218 vstream_fflush(VSTREAM_OUT
);