/*++ /* NAME /* postconf_main 3 /* SUMMARY /* basic support for main.cf /* SYNOPSIS /* #include <postconf.h> /* /* void read_parameters() /* /* void set_parameters() /* /* void show_parameters(mode, param_class, names) /* int mode; /* int param_class; /* char **names; /* DESCRIPTION /* read_parameters() reads parameters from main.cf. /* /* set_parameters() does nothing. It is a place holder for /* code that assigns actual or default parameter values, which /* could be needed to implement "postconf -e" parameter value /* expansion. /* /* show_parameters() writes main.cf parameters to the standard /* output stream. /* /* Arguments: /* .IP mode /* Bit-wise OR of zero or more of the following: /* .RS /* .IP FOLD_LINE /* Fold long lines. /* .IP SHOW_DEFS /* Output default parameter values. /* .IP SHOW_NONDEF /* Output explicit settings only. /* .IP SHOW_NAME /* Output the parameter as "name = value". /* .IP SHOW_EVAL /* Expand parameter values (not implemented). /* .RE /* .IP param_class /* Bit-wise OR of one or more of the following: /* .RS /* .IP PC_PARAM_FLAG_BUILTIN /* Show built-in parameters. /* .IP PC_PARAM_FLAG_SERVICE /* Show service-defined parameters. /* .IP PC_PARAM_FLAG_USER /* Show user-defined parameters. /* .RE /* .IP names /* List of zero or more parameter names. If the list is empty, /* output all parameters. /* DIAGNOSTICS /* Problems are reported to the standard error stream. /* LICENSE /* .ad /* .fi /* The Secure Mailer license must be distributed with this software. /* AUTHOR(S) /* Wietse Venema /* IBM T.J. Watson Research /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA /*--*/ /* System library. */ #include <sys_defs.h> #include <stdarg.h> #include <stdlib.h> #include <string.h> /* Utility library. */ #include <msg.h> #include <mymalloc.h> #include <vstream.h> #include <vstring.h> #include <readlline.h> #include <dict.h> #include <stringops.h> #include <htable.h> /* Global library. */ #include <mail_params.h> #include <mail_conf.h> /* Application-specific. */ #include <postconf.h> #define STR(x) vstring_str(x) /* read_parameters - read parameter info from file */ void read_parameters(void) { char *path; /* * A direct rip-off of mail_conf_read(). XXX Avoid code duplication by * better code decomposition. */ set_config_dir(); path = concatenate(var_config_dir, "/", MAIN_CONF_FILE, (char *) 0); if (dict_load_file_xt(CONFIG_DICT, path) == 0) msg_fatal("open %s: %m", path); myfree(path); } /* set_parameters - set parameter values from default or explicit setting */ void set_parameters(void) { /* * The proposal below describes some of the steps needed to expand * parameter values. It has a problem: it updates the configuration * parameter dictionary, and in doing so breaks the "postconf -d" * implementation. This makes "-d" and "-e" mutually exclusive. * * Populate the configuration parameter dictionary with default settings or * with actual settings. * * Iterate over each entry in str_fn_table, str_fn_table_2, time_table, * bool_table, int_table, str_table, and raw_table. Look up each * parameter name in the configuration parameter dictionary. If the * parameter is not set, take the default value, or take the value from * main.cf, without doing $name expansions. This includes converting * default values from numeric/boolean internal forms to external string * form. * * Once the configuration parameter dictionary is populated, printing a * parameter setting is a matter of querying the configuration parameter * dictionary, optionally expanding of $name values, and printing the * result. */ } /* print_line - show line possibly folded, and with normalized whitespace */ static void print_line(int mode, const char *fmt,...) { va_list ap; static VSTRING *buf = 0; char *start; char *next; int line_len = 0; int word_len; /* * One-off initialization. */ if (buf == 0) buf = vstring_alloc(100); /* * Format the text. */ va_start(ap, fmt); vstring_vsprintf(buf, fmt, ap); va_end(ap); /* * Normalize the whitespace. We don't use the line_wrap() routine because * 1) that function does not normalize whitespace between words and 2) we * want to normalize whitespace even when not wrapping lines. * * XXX Some parameters preserve whitespace: for example, smtpd_banner and * smtpd_reject_footer. If we have to preserve whitespace between words, * then perhaps readlline() can be changed to canonicalize whitespace * that follows a newline. */ for (start = STR(buf); *(start += strspn(start, SEPARATORS)) != 0; start = next) { word_len = strcspn(start, SEPARATORS); if (*(next = start + word_len) != 0) *next++ = 0; if (word_len > 0 && line_len > 0) { if ((mode & FOLD_LINE) == 0 || line_len + word_len < LINE_LIMIT) { vstream_fputs(" ", VSTREAM_OUT); line_len += 1; } else { vstream_fputs("\n" INDENT_TEXT, VSTREAM_OUT); line_len = INDENT_LEN; } } vstream_fputs(start, VSTREAM_OUT); line_len += word_len; } vstream_fputs("\n", VSTREAM_OUT); } /* print_parameter - show specific parameter */ static void print_parameter(int mode, const char *name, PC_PARAM_NODE *node) { const char *value; /* * Use the default or actual value. */ if ((mode & SHOW_DEFS) != 0 || ((value = dict_lookup(CONFIG_DICT, name)) == 0 && (mode & SHOW_NONDEF) == 0)) value = convert_param_node(SHOW_DEFS, name, node); /* * Print with or without the name= prefix. */ if (value != 0) { if (mode & SHOW_NAME) { print_line(mode, "%s = %s\n", name, value); } else { print_line(mode, "%s\n", value); } if (msg_verbose) vstream_fflush(VSTREAM_OUT); } } /* comp_names - qsort helper */ static int comp_names(const void *a, const void *b) { PC_PARAM_INFO **ap = (PC_PARAM_INFO **) a; PC_PARAM_INFO **bp = (PC_PARAM_INFO **) b; return (strcmp(PC_PARAM_INFO_NAME(ap[0]), PC_PARAM_INFO_NAME(bp[0]))); } /* show_parameters - show parameter info */ void show_parameters(int mode, int param_class, char **names) { PC_PARAM_INFO **list; PC_PARAM_INFO **ht; char **namep; PC_PARAM_NODE *node; /* * Show all parameters. */ if (*names == 0) { list = PC_PARAM_TABLE_LIST(param_table); qsort((char *) list, param_table->used, sizeof(*list), comp_names); for (ht = list; *ht; ht++) if (param_class & PC_PARAM_INFO_NODE(*ht)->flags) print_parameter(mode, PC_PARAM_INFO_NAME(*ht), PC_PARAM_INFO_NODE(*ht)); myfree((char *) list); return; } /* * Show named parameters. */ for (namep = names; *namep; namep++) { if ((node = PC_PARAM_TABLE_FIND(param_table, *namep)) == 0) { msg_warn("%s: unknown parameter", *namep); } else { print_parameter(mode, *namep, node); } } }