1/*++
2/* NAME
3/*	postconf_main 3
4/* SUMMARY
5/*	basic support for main.cf
6/* SYNOPSIS
7/*	#include <postconf.h>
8/*
9/*	void	pcf_read_parameters()
10/*
11/*	void	pcf_show_parameters(fp, mode, param_class, names)
12/*	VSTREAM	*fp;
13/*	int	mode;
14/*	int	param_class;
15/*	char	**names;
16/* DESCRIPTION
17/*	pcf_read_parameters() reads parameters from main.cf.
18/*
19/*	pcf_set_parameters() takes an array of \fIname=value\fR
20/*	pairs and overrides settings read with pcf_read_parameters().
21/*
22/*	pcf_show_parameters() writes main.cf parameters to the
23/*	specified output stream.
24/*
25/*	Arguments:
26/* .IP fp
27/*	Output stream.
28/* .IP mode
29/*	Bit-wise OR of zero or more of the following:
30/* .RS
31/* .IP PCF_FOLD_LINE
32/*	Fold long lines.
33/* .IP PCF_SHOW_DEFS
34/*	Output default parameter values.
35/* .IP PCF_SHOW_NONDEF
36/*	Output explicit settings only.
37/* .IP PCF_HIDE_NAME
38/*	Output parameter values without the "name =" prefix.
39/* .IP PCF_SHOW_EVAL
40/*	Expand $name in parameter values.
41/* .RE
42/* .IP param_class
43/*	Bit-wise OR of one or more of the following:
44/* .RS
45/* .IP PCF_PARAM_FLAG_BUILTIN
46/*	Show built-in parameters.
47/* .IP PCF_PARAM_FLAG_SERVICE
48/*	Show service-defined parameters.
49/* .IP PCF_PARAM_FLAG_USER
50/*	Show user-defined parameters.
51/* .RE
52/* .IP names
53/*	List of zero or more parameter names. If the list is empty,
54/*	output all parameters.
55/* DIAGNOSTICS
56/*	Problems are reported to the standard error stream.
57/* LICENSE
58/* .ad
59/* .fi
60/*	The Secure Mailer license must be distributed with this software.
61/* AUTHOR(S)
62/*	Wietse Venema
63/*	IBM T.J. Watson Research
64/*	P.O. Box 704
65/*	Yorktown Heights, NY 10598, USA
66/*--*/
67
68/* System library. */
69
70#include <sys_defs.h>
71#include <stdarg.h>
72#include <stdlib.h>
73#include <string.h>
74
75/* Utility library. */
76
77#include <msg.h>
78#include <mymalloc.h>
79#include <vstream.h>
80#include <vstring.h>
81#include <readlline.h>
82#include <dict.h>
83#include <stringops.h>
84#include <htable.h>
85#include <mac_expand.h>
86
87/* Global library. */
88
89#include <mail_params.h>
90#include <mail_conf.h>
91
92/* Application-specific. */
93
94#include <postconf.h>
95
96#define STR(x) vstring_str(x)
97
98/* pcf_read_parameters - read parameter info from file */
99
100void    pcf_read_parameters(void)
101{
102    char   *path;
103
104    /*
105     * A direct rip-off of mail_conf_read(). XXX Avoid code duplication by
106     * better code decomposition.
107     */
108    pcf_set_config_dir();
109    path = concatenate(var_config_dir, "/", MAIN_CONF_FILE, (char *) 0);
110    if (dict_load_file_xt(CONFIG_DICT, path) == 0)
111	msg_fatal("open %s: %m", path);
112    myfree(path);
113}
114
115/* pcf_set_parameters - add or override name=value pairs */
116
117void    pcf_set_parameters(char **name_val_array)
118{
119    char   *name, *value, *junk;
120    const char *err;
121    char  **cpp;
122
123    for (cpp = name_val_array; *cpp; cpp++) {
124	junk = mystrdup(*cpp);
125	if ((err = split_nameval(junk, &name, &value)) != 0)
126	    msg_fatal("invalid parameter override: %s: %s", *cpp, err);
127	mail_conf_update(name, value);
128	myfree(junk);
129    }
130}
131
132/* pcf_print_parameter - show specific parameter */
133
134static void pcf_print_parameter(VSTREAM *fp, int mode, const char *name,
135				        PCF_PARAM_NODE *node)
136{
137    const char *value;
138
139    /*
140     * Use the default or actual value.
141     */
142    value = pcf_lookup_parameter_value(mode, name, (PCF_MASTER_ENT *) 0, node);
143
144    /*
145     * Optionally expand $name in the parameter value. Print the result with
146     * or without the name= prefix.
147     */
148    if (value != 0) {
149	if ((mode & PCF_SHOW_EVAL) != 0 && PCF_RAW_PARAMETER(node) == 0)
150	    value = pcf_expand_parameter_value((VSTRING *) 0, mode, value,
151					       (PCF_MASTER_ENT *) 0);
152	if ((mode & PCF_HIDE_NAME) == 0) {
153	    pcf_print_line(fp, mode, "%s = %s\n", name, value);
154	} else {
155	    pcf_print_line(fp, mode, "%s\n", value);
156	}
157	if (msg_verbose)
158	    vstream_fflush(fp);
159    }
160}
161
162/* pcf_comp_names - qsort helper */
163
164static int pcf_comp_names(const void *a, const void *b)
165{
166    PCF_PARAM_INFO **ap = (PCF_PARAM_INFO **) a;
167    PCF_PARAM_INFO **bp = (PCF_PARAM_INFO **) b;
168
169    return (strcmp(PCF_PARAM_INFO_NAME(ap[0]),
170		   PCF_PARAM_INFO_NAME(bp[0])));
171}
172
173/* pcf_show_parameters - show parameter info */
174
175void    pcf_show_parameters(VSTREAM *fp, int mode, int param_class, char **names)
176{
177    PCF_PARAM_INFO **list;
178    PCF_PARAM_INFO **ht;
179    char  **namep;
180    PCF_PARAM_NODE *node;
181
182    /*
183     * Show all parameters.
184     */
185    if (*names == 0) {
186	list = PCF_PARAM_TABLE_LIST(pcf_param_table);
187	qsort((char *) list, pcf_param_table->used, sizeof(*list),
188	      pcf_comp_names);
189	for (ht = list; *ht; ht++)
190	    if (param_class & PCF_PARAM_INFO_NODE(*ht)->flags)
191		pcf_print_parameter(fp, mode, PCF_PARAM_INFO_NAME(*ht),
192				    PCF_PARAM_INFO_NODE(*ht));
193	myfree((char *) list);
194	return;
195    }
196
197    /*
198     * Show named parameters.
199     */
200    for (namep = names; *namep; namep++) {
201	if ((node = PCF_PARAM_TABLE_FIND(pcf_param_table, *namep)) == 0) {
202	    msg_warn("%s: unknown parameter", *namep);
203	} else {
204	    pcf_print_parameter(fp, mode, *namep, node);
205	}
206    }
207}
208