xref: /netbsd-src/external/ibm-public/postfix/dist/src/postconf/postconf_main.c (revision 413d532bcc3f62d122e56d92e13ac64825a40baf)
1 /*	$NetBSD: postconf_main.c,v 1.1.1.2 2013/09/25 19:06:33 tron Exp $	*/
2 
3 /*++
4 /* NAME
5 /*	postconf_main 3
6 /* SUMMARY
7 /*	basic support for main.cf
8 /* SYNOPSIS
9 /*	#include <postconf.h>
10 /*
11 /*	void	read_parameters()
12 /*
13 /*	void	show_parameters(fp, mode, param_class, names)
14 /*	VSTREAM	*fp;
15 /*	int	mode;
16 /*	int	param_class;
17 /*	char	**names;
18 /* DESCRIPTION
19 /*	read_parameters() reads parameters from main.cf.
20 /*
21 /*	set_parameters() takes an array of \fIname=value\fR pairs
22 /*	and overrides settings read with read_parameters().
23 /*
24 /*	show_parameters() writes main.cf parameters to the specified
25 /*	output stream.
26 /*
27 /*	Arguments:
28 /* .IP fp
29 /*	Output stream.
30 /* .IP mode
31 /*	Bit-wise OR of zero or more of the following:
32 /* .RS
33 /* .IP FOLD_LINE
34 /*	Fold long lines.
35 /* .IP SHOW_DEFS
36 /*	Output default parameter values.
37 /* .IP SHOW_NONDEF
38 /*	Output explicit settings only.
39 /* .IP SHOW_NAME
40 /*	Output the parameter as "name = value".
41 /* .IP SHOW_EVAL
42 /*	Expand $name in parameter values.
43 /* .RE
44 /* .IP param_class
45 /*	Bit-wise OR of one or more of the following:
46 /* .RS
47 /* .IP PC_PARAM_FLAG_BUILTIN
48 /*	Show built-in parameters.
49 /* .IP PC_PARAM_FLAG_SERVICE
50 /*	Show service-defined parameters.
51 /* .IP PC_PARAM_FLAG_USER
52 /*	Show user-defined parameters.
53 /* .RE
54 /* .IP names
55 /*	List of zero or more parameter names. If the list is empty,
56 /*	output all parameters.
57 /* DIAGNOSTICS
58 /*	Problems are reported to the standard error stream.
59 /* LICENSE
60 /* .ad
61 /* .fi
62 /*	The Secure Mailer license must be distributed with this software.
63 /* AUTHOR(S)
64 /*	Wietse Venema
65 /*	IBM T.J. Watson Research
66 /*	P.O. Box 704
67 /*	Yorktown Heights, NY 10598, USA
68 /*--*/
69 
70 /* System library. */
71 
72 #include <sys_defs.h>
73 #include <stdarg.h>
74 #include <stdlib.h>
75 #include <string.h>
76 
77 /* Utility library. */
78 
79 #include <msg.h>
80 #include <mymalloc.h>
81 #include <vstream.h>
82 #include <vstring.h>
83 #include <readlline.h>
84 #include <dict.h>
85 #include <stringops.h>
86 #include <htable.h>
87 #include <mac_expand.h>
88 
89 /* Global library. */
90 
91 #include <mail_params.h>
92 #include <mail_conf.h>
93 
94 /* Application-specific. */
95 
96 #include <postconf.h>
97 
98 #define STR(x) vstring_str(x)
99 
100 /* read_parameters - read parameter info from file */
101 
102 void    read_parameters(void)
103 {
104     char   *path;
105 
106     /*
107      * A direct rip-off of mail_conf_read(). XXX Avoid code duplication by
108      * better code decomposition.
109      */
110     set_config_dir();
111     path = concatenate(var_config_dir, "/", MAIN_CONF_FILE, (char *) 0);
112     if (dict_load_file_xt(CONFIG_DICT, path) == 0)
113 	msg_fatal("open %s: %m", path);
114     myfree(path);
115 }
116 
117 /* set_parameters - add or override name=value pairs */
118 
119 void    set_parameters(char **name_val_array)
120 {
121     char   *name, *value, *junk;
122     const char *err;
123     char  **cpp;
124 
125     for (cpp = name_val_array; *cpp; cpp++) {
126 	junk = mystrdup(*cpp);
127 	if ((err = split_nameval(junk, &name, &value)) != 0)
128 	    msg_fatal("invalid parameter override: %s: %s", *cpp, err);
129 	mail_conf_update(name, value);
130 	myfree(junk);
131     }
132 }
133 
134 /* print_line - show line possibly folded, and with normalized whitespace */
135 
136 static void print_line(VSTREAM *fp, int mode, const char *fmt,...)
137 {
138     va_list ap;
139     static VSTRING *buf = 0;
140     char   *start;
141     char   *next;
142     int     line_len = 0;
143     int     word_len;
144 
145     /*
146      * One-off initialization.
147      */
148     if (buf == 0)
149 	buf = vstring_alloc(100);
150 
151     /*
152      * Format the text.
153      */
154     va_start(ap, fmt);
155     vstring_vsprintf(buf, fmt, ap);
156     va_end(ap);
157 
158     /*
159      * Normalize the whitespace. We don't use the line_wrap() routine because
160      * 1) that function does not normalize whitespace between words and 2) we
161      * want to normalize whitespace even when not wrapping lines.
162      *
163      * XXX Some parameters preserve whitespace: for example, smtpd_banner and
164      * smtpd_reject_footer. If we have to preserve whitespace between words,
165      * then perhaps readlline() can be changed to canonicalize whitespace
166      * that follows a newline.
167      */
168     for (start = STR(buf); *(start += strspn(start, SEPARATORS)) != 0; start = next) {
169 	word_len = strcspn(start, SEPARATORS);
170 	if (*(next = start + word_len) != 0)
171 	    *next++ = 0;
172 	if (word_len > 0 && line_len > 0) {
173 	    if ((mode & FOLD_LINE) == 0 || line_len + word_len < LINE_LIMIT) {
174 		vstream_fputs(" ", fp);
175 		line_len += 1;
176 	    } else {
177 		vstream_fputs("\n" INDENT_TEXT, fp);
178 		line_len = INDENT_LEN;
179 	    }
180 	}
181 	vstream_fputs(start, fp);
182 	line_len += word_len;
183     }
184     vstream_fputs("\n", fp);
185 }
186 
187 /* print_parameter - show specific parameter */
188 
189 static void print_parameter(VSTREAM *fp, int mode, const char *name,
190 			            PC_PARAM_NODE *node)
191 {
192     const char *value;
193 
194     /*
195      * Use the default or actual value.
196      */
197     value = lookup_parameter_value(mode, name, (PC_MASTER_ENT *) 0, node);
198 
199     /*
200      * Optionally expand $name in the parameter value. Print the result with
201      * or without the name= prefix.
202      */
203     if (value != 0) {
204 	if ((mode & SHOW_EVAL) != 0 && PC_RAW_PARAMETER(node) == 0)
205 	    value = expand_parameter_value((VSTRING *) 0, mode, value,
206 					   (PC_MASTER_ENT *) 0);
207 	if (mode & SHOW_NAME) {
208 	    print_line(fp, mode, "%s = %s\n", name, value);
209 	} else {
210 	    print_line(fp, mode, "%s\n", value);
211 	}
212 	if (msg_verbose)
213 	    vstream_fflush(fp);
214     }
215 }
216 
217 /* comp_names - qsort helper */
218 
219 static int comp_names(const void *a, const void *b)
220 {
221     PC_PARAM_INFO **ap = (PC_PARAM_INFO **) a;
222     PC_PARAM_INFO **bp = (PC_PARAM_INFO **) b;
223 
224     return (strcmp(PC_PARAM_INFO_NAME(ap[0]),
225 		   PC_PARAM_INFO_NAME(bp[0])));
226 }
227 
228 /* show_parameters - show parameter info */
229 
230 void    show_parameters(VSTREAM *fp, int mode, int param_class, char **names)
231 {
232     PC_PARAM_INFO **list;
233     PC_PARAM_INFO **ht;
234     char  **namep;
235     PC_PARAM_NODE *node;
236 
237     /*
238      * Show all parameters.
239      */
240     if (*names == 0) {
241 	list = PC_PARAM_TABLE_LIST(param_table);
242 	qsort((char *) list, param_table->used, sizeof(*list), comp_names);
243 	for (ht = list; *ht; ht++)
244 	    if (param_class & PC_PARAM_INFO_NODE(*ht)->flags)
245 		print_parameter(fp, mode, PC_PARAM_INFO_NAME(*ht),
246 				PC_PARAM_INFO_NODE(*ht));
247 	myfree((char *) list);
248 	return;
249     }
250 
251     /*
252      * Show named parameters.
253      */
254     for (namep = names; *namep; namep++) {
255 	if ((node = PC_PARAM_TABLE_FIND(param_table, *namep)) == 0) {
256 	    msg_warn("%s: unknown parameter", *namep);
257 	} else {
258 	    print_parameter(fp, mode, *namep, node);
259 	}
260     }
261 }
262