xref: /netbsd-src/external/ibm-public/postfix/dist/src/postconf/postconf.c (revision 63aea4bd5b445e491ff0389fe27ec78b3099dba3)
1 /*	$NetBSD: postconf.c,v 1.1.1.8 2014/07/06 19:27:53 tron Exp $	*/
2 
3 /*++
4 /* NAME
5 /*	postconf 1
6 /* SUMMARY
7 /*	Postfix configuration utility
8 /* SYNOPSIS
9 /* .fi
10 /*	\fBManaging main.cf:\fR
11 /*
12 /*	\fBpostconf\fR [\fB-dfhnopvx\fR] [\fB-c \fIconfig_dir\fR]
13 /*	[\fB-C \fIclass,...\fR] [\fIparameter ...\fR]
14 /*
15 /*	\fBpostconf\fR [\fB-epv\fR] [\fB-c \fIconfig_dir\fR]
16 /*	\fIparameter\fB=\fIvalue ...\fR
17 /*
18 /*	\fBpostconf\fR \fB-#\fR [\fB-pv\fR] [\fB-c \fIconfig_dir\fR]
19 /*	\fIparameter ...\fR
20 /*
21 /*	\fBpostconf\fR \fB-X\fR [\fB-pv\fR] [\fB-c \fIconfig_dir\fR]
22 /*	\fIparameter ...\fR
23 /*
24 /*	\fBManaging master.cf service entries:\fR
25 /*
26 /*	\fBpostconf\fR \fB-M\fR [\fB-fovx\fR] [\fB-c \fIconfig_dir\fR]
27 /*	[\fIservice\fR[\fB/\fItype\fR]\fI ...\fR]
28 /*
29 /*	\fBpostconf\fR \fB-M\fR [\fB-ev\fR] [\fB-c \fIconfig_dir\fR]
30 /*	\fIservice\fB/\fItype\fB=\fIvalue ...\fR
31 /*
32 /*	\fBpostconf\fR \fB-M#\fR [\fB-v\fR] [\fB-c \fIconfig_dir\fR]
33 /*	\fIservice\fB/\fItype ...\fR
34 /*
35 /*	\fBpostconf\fR \fB-MX\fR [\fB-v\fR] [\fB-c \fIconfig_dir\fR]
36 /*	\fIservice\fB/\fItype ...\fR
37 /*
38 /*	\fBManaging master.cf service fields:\fR
39 /*
40 /*	\fBpostconf\fR \fB-F\fR [\fB-fovx\fR] [\fB-c \fIconfig_dir\fR]
41 /*	[\fIservice\fR[\fB/\fItype\fR[\fB/\fIfield\fR]]\fI ...\fR]
42 /*
43 /*	\fBpostconf\fR \fB-F\fR [\fB-ev\fR] [\fB-c \fIconfig_dir\fR]
44 /*	\fIservice\fB/\fItype\fB/\fIfield\fB=\fIvalue ...\fR
45 /*
46 /*	\fBManaging master.cf service parameters:\fR
47 /*
48 /*	\fBpostconf\fR \fB-P\fR [\fB-fovx\fR] [\fB-c \fIconfig_dir\fR]
49 /*	[\fIservice\fR[\fB/\fItype\fR[\fB/\fIparameter\fR]]\fI ...\fR]
50 /*
51 /*	\fBpostconf\fR \fB-P\fR [\fB-ev\fR] [\fB-c \fIconfig_dir\fR]
52 /*	\fIservice\fB/\fItype\fB/\fIparameter\fB=\fIvalue ...\fR
53 /*
54 /*	\fBpostconf\fR \fB-PX\fR [\fB-v\fR] [\fB-c \fIconfig_dir\fR]
55 /*	\fIservice\fB/\fItype\fB/\fIparameter ...\fR
56 /*
57 /*	\fBManaging bounce message templates:\fR
58 /*
59 /*	\fBpostconf\fR \fB-b\fR [\fB-v\fR] [\fB-c \fIconfig_dir\fR]
60 /*	[\fItemplate_file\fR]
61 /*
62 /*	\fBpostconf\fR \fB-t\fR [\fB-v\fR] [\fB-c \fIconfig_dir\fR]
63 /*	[\fItemplate_file\fR]
64 /*
65 /*	\fBManaging other configuration:\fR
66 /*
67 /*      \fBpostconf\fR \fB-a\fR|\fB-A\fR|\fB-l\fR|\fB-m\fR [\fB-v\fR]
68 /*	[\fB-c \fIconfig_dir\fR]
69 /* DESCRIPTION
70 /*	By default, the \fBpostconf\fR(1) command displays the
71 /*	values of \fBmain.cf\fR configuration parameters, and warns
72 /*	about possible mis-typed parameter names (Postfix 2.9 and later).
73 /*	It can also change \fBmain.cf\fR configuration
74 /*	parameter values, or display other configuration information
75 /*	about the Postfix mail system.
76 /*
77 /*	Options:
78 /* .IP \fB-a\fR
79 /*	List the available SASL server plug-in types.  The SASL
80 /*	plug-in type is selected with the \fBsmtpd_sasl_type\fR
81 /*	configuration parameter by specifying one of the names
82 /*	listed below.
83 /* .RS
84 /* .IP \fBcyrus\fR
85 /*	This server plug-in is available when Postfix is built with
86 /*	Cyrus SASL support.
87 /* .IP \fBdovecot\fR
88 /*	This server plug-in uses the Dovecot authentication server,
89 /*	and is available when Postfix is built with any form of SASL
90 /*	support.
91 /* .RE
92 /* .IP
93 /*	This feature is available with Postfix 2.3 and later.
94 /* .IP \fB-A\fR
95 /*	List the available SASL client plug-in types.  The SASL
96 /*	plug-in type is selected with the \fBsmtp_sasl_type\fR or
97 /*	\fBlmtp_sasl_type\fR configuration parameters by specifying
98 /*	one of the names listed below.
99 /* .RS
100 /* .IP \fBcyrus\fR
101 /*	This client plug-in is available when Postfix is built with
102 /*	Cyrus SASL support.
103 /* .RE
104 /* .IP
105 /*	This feature is available with Postfix 2.3 and later.
106 /* .IP "\fB-b\fR [\fItemplate_file\fR]"
107 /*	Display the message text that appears at the beginning of
108 /*	delivery status notification (DSN) messages, replacing
109 /*	$\fBname\fR expressions with actual values as described in
110 /*	\fBbounce\fR(5).
111 /*
112 /*	To override the built-in templates, specify a template file
113 /*	name at the end of the \fBpostconf\fR(1) command line, or
114 /*	specify a file name in \fBmain.cf\fR with the
115 /*	\fBbounce_template_file\fR parameter.
116 /*
117 /*	To force selection of the built-in templates, specify an
118 /*	empty template file name on the \fBpostconf\fR(1) command
119 /*	line (in shell language: "").
120 /*
121 /*	This feature is available with Postfix 2.3 and later.
122 /* .IP "\fB-c \fIconfig_dir\fR"
123 /*	The \fBmain.cf\fR configuration file is in the named directory
124 /*	instead of the default configuration directory.
125 /* .IP "\fB-C \fIclass,...\fR"
126 /*	When displaying \fBmain.cf\fR parameters, select only
127 /*	parameters from the specified class(es):
128 /* .RS
129 /* .IP \fBbuiltin\fR
130 /*	Parameters with built-in names.
131 /* .IP \fBservice\fR
132 /*	Parameters with service-defined names (the first field of
133 /*	a \fBmaster.cf\fR entry plus a Postfix-defined suffix).
134 /* .IP \fBuser\fR
135 /*	Parameters with user-defined names.
136 /* .IP \fBall\fR
137 /*	All the above classes.
138 /* .RE
139 /* .IP
140 /*	The default is as if "\fB-C all\fR" is
141 /*	specified.
142 /*
143 /*	This feature is available with Postfix 2.9 and later.
144 /* .IP \fB-d\fR
145 /*	Print \fBmain.cf\fR default parameter settings instead of
146 /*	actual settings.
147 /*	Specify \fB-df\fR to fold long lines for human readability
148 /*	(Postfix 2.9 and later).
149 /* .IP \fB-e\fR
150 /*	Edit the \fBmain.cf\fR configuration file, and update
151 /*	parameter settings with the "\fIname=value\fR" pairs on the
152 /*	\fBpostconf\fR(1) command line.
153 /*
154 /*	With \fB-M\fR, edit the \fBmaster.cf\fR configuration file,
155 /*	and replace one or more service entries with new values as
156 /*	specified with "\fIservice/type=value\fR" on the \fBpostconf\fR(1)
157 /*	command line.
158 /*
159 /*	With \fB-F\fR, edit the \fBmaster.cf\fR configuration file,
160 /*	and replace one or more service fields with new values as
161 /*	specied with "\fIservice/type/field=value\fR" on the
162 /*	\fBpostconf\fR(1) command line. Currently, the "command"
163 /*	field contains the command name and command arguments.  this
164 /*	may change in the near future, so that the "command" field
165 /*	contains only the command name, and a new "arguments"
166 /*	pseudofield contains the command arguments.
167 /*
168 /*	With \fB-P\fR, edit the \fBmaster.cf\fR configuration file,
169 /*	and add or update one or more service parameter settings
170 /*	(-o parameter=value settings) with new values as specied
171 /*	with "\fIservice/type/parameter=value\fR" on the \fBpostconf\fR(1)
172 /*	command line.
173 /*
174 /*	In all cases the file is copied to a temporary file then
175 /*	renamed into place.  Specify quotes to protect special
176 /*	characters and whitespace on the \fBpostconf\fR(1) command
177 /*	line.
178 /*
179 /*	The \fB-e\fR option is no longer needed with Postfix version
180 /*	2.8 and later.
181 /* .IP \fB-f\fR
182 /*	Fold long lines when printing \fBmain.cf\fR or \fBmaster.cf\fR
183 /*	configuration file entries, for human readability.
184 /*
185 /*	This feature is available with Postfix 2.9 and later.
186 /* .IP \fB-F\fR
187 /*	Show \fBmaster.cf\fR per-entry field settings (by default
188 /*	all services and all fields), formatted as one
189 /*	"\fIservice/type/field=value\fR" per line. Specify \fB-Ff\fR
190 /*	to fold long lines.
191 /*
192 /*	Specify one or more "\fIservice/type/field\fR" instances
193 /*	on the \fBpostconf\fR(1) command line to limit the output
194 /*	to fields of interest.  Trailing parameter name or service
195 /*	type fields that are omitted will be handled as "*" wildcard
196 /*	fields.
197 /*
198 /*	This feature is available with Postfix 2.11 and later.
199 /* .IP \fB-h\fR
200 /*	Show parameter or attribute values without the "\fIname\fR
201 /*	= " label that normally precedes the value.
202 /* .IP \fB-l\fR
203 /*	List the names of all supported mailbox locking methods.
204 /*	Postfix supports the following methods:
205 /* .RS
206 /* .IP \fBflock\fR
207 /*	A kernel-based advisory locking method for local files only.
208 /*	This locking method is available on systems with a BSD
209 /*	compatible library.
210 /* .IP \fBfcntl\fR
211 /*	A kernel-based advisory locking method for local and remote
212 /*	files.
213 /* .IP \fBdotlock\fR
214 /*	An application-level locking method. An application locks
215 /*	a file named \fIfilename\fR by creating a file named
216 /*	\fIfilename\fB.lock\fR.  The application is expected to
217 /*	remove its own lock file, as well as stale lock files that
218 /*	were left behind after abnormal program termination.
219 /* .RE
220 /* .IP \fB-m\fR
221 /*	List the names of all supported lookup table types. In
222 /*	Postfix configuration files, lookup tables are specified
223 /*	as \fItype\fB:\fIname\fR, where \fItype\fR is one of the
224 /*	types listed below. The table \fIname\fR syntax depends on
225 /*	the lookup table type as described in the DATABASE_README
226 /*	document.
227 /* .RS
228 /* .IP \fBbtree\fR
229 /*	A sorted, balanced tree structure.  Available on systems
230 /*	with support for Berkeley DB databases.
231 /* .IP \fBcdb\fR
232 /*	A read-optimized structure with no support for incremental
233 /*	updates.  Available on systems with support for CDB databases.
234 /* .IP \fBcidr\fR
235 /*	A table that associates values with Classless Inter-Domain
236 /*	Routing (CIDR) patterns. This is described in \fBcidr_table\fR(5).
237 /* .IP \fBdbm\fR
238 /*	An indexed file type based on hashing.  Available on systems
239 /*	with support for DBM databases.
240 /* .IP \fBenviron\fR
241 /*	The UNIX process environment array. The lookup key is the
242 /*	variable name. Originally implemented for testing, someone
243 /*	may find this useful someday.
244 /* .IP \fBfail\fR
245 /*	A table that reliably fails all requests. The lookup table
246 /*	name is used for logging. This table exists to simplify
247 /*	Postfix error tests.
248 /* .IP \fBhash\fR
249 /*	An indexed file type based on hashing.  Available on systems
250 /*	with support for Berkeley DB databases.
251 /* .IP \fBinternal\fR
252 /*	A non-shared, in-memory hash table. Its content are lost
253 /*	when a process terminates.
254 /* .IP "\fBlmdb\fR"
255 /*	OpenLDAP LMDB database (a memory-mapped, persistent file).
256 /*	Available on systems with support for LMDB databases.  This
257 /*	is described in \fBlmdb_table\fR(5).
258 /* .IP "\fBldap\fR (read-only)"
259 /*	LDAP database client. This is described in \fBldap_table\fR(5).
260 /* .IP "\fBmemcache\fR"
261 /*	Memcache database client. This is described in
262 /*	\fBmemcache_table\fR(5).
263 /* .IP "\fBmysql\fR (read-only)"
264 /*	MySQL database client.  Available on systems with support
265 /*	for MySQL databases.  This is described in \fBmysql_table\fR(5).
266 /* .IP "\fBpcre\fR (read-only)"
267 /*	A lookup table based on Perl Compatible Regular Expressions.
268 /*	The file format is described in \fBpcre_table\fR(5).
269 /* .IP "\fBpgsql\fR (read-only)"
270 /*	PostgreSQL database client. This is described in
271 /*	\fBpgsql_table\fR(5).
272 /* .IP "\fBproxy\fR"
273 /*	Postfix \fBproxymap\fR(8) client for shared access to Postfix
274 /*	databases. The table name syntax is \fItype\fB:\fIname\fR.
275 /* .IP "\fBregexp\fR (read-only)"
276 /*	A lookup table based on regular expressions. The file format
277 /*	is described in \fBregexp_table\fR(5).
278 /* .IP \fBsdbm\fR
279 /*	An indexed file type based on hashing.  Available on systems
280 /*	with support for SDBM databases.
281 /* .IP "\fBsocketmap\fR (read-only)"
282 /*	Sendmail-style socketmap client. The table name is
283 /*	\fBinet\fR:\fIhost\fR:\fIport\fR:\fIname\fR for a TCP/IP
284 /*	server, or \fBunix\fR:\fIpathname\fR:\fIname\fR for a
285 /*	UNIX-domain server. This is described in \fBsocketmap_table\fR(5).
286 /* .IP "\fBsqlite\fR (read-only)"
287 /*	SQLite database. This is described in \fBsqlite_table\fR(5).
288 /* .IP "\fBstatic\fR (read-only)"
289 /*	A table that always returns its name as lookup result. For
290 /*	example, \fBstatic:foobar\fR always returns the string
291 /*	\fBfoobar\fR as lookup result.
292 /* .IP "\fBtcp\fR (read-only)"
293 /*	TCP/IP client. The protocol is described in \fBtcp_table\fR(5).
294 /* .IP "\fBtexthash\fR (read-only)"
295 /*	Produces similar results as hash: files, except that you
296 /*	don't need to run the \fBpostmap\fR(1) command before you
297 /*	can use the file, and that it does not detect changes after
298 /*	the file is read.
299 /* .IP "\fBunix\fR (read-only)"
300 /*	A limited view of the UNIX authentication database. The
301 /*	following tables are implemented:
302 /* .RS
303 /*. IP \fBunix:passwd.byname\fR
304 /*	The table is the UNIX password database. The key is a login
305 /*	name.  The result is a password file entry in \fBpasswd\fR(5)
306 /*	format.
307 /* .IP \fBunix:group.byname\fR
308 /*	The table is the UNIX group database. The key is a group
309 /*	name.  The result is a group file entry in \fBgroup\fR(5)
310 /*	format.
311 /* .RE
312 /* .RE
313 /* .IP
314 /*	Other table types may exist depending on how Postfix was
315 /*	built.
316 /* .IP \fB-M\fR
317 /*	Show \fBmaster.cf\fR file contents instead of \fBmain.cf\fR
318 /*	file contents.  Specify \fB-Mf\fR to fold long lines for
319 /*	human readability.
320 /*
321 /*	Specify zero or more arguments, each with a \fIservice-name\fR
322 /*	or \fIservice-name/service-type\fR pair, where \fIservice-name\fR
323 /*	is the first field of a master.cf entry and \fIservice-type\fR
324 /*	is one of (\fBinet\fR, \fBunix\fR, \fBfifo\fR, or \fBpass\fR).
325 /*
326 /*	If \fIservice-name\fR or \fIservice-name/service-type\fR
327 /*	is specified, only the matching master.cf entries will be
328 /*	output. For example, "\fBpostconf -Mf smtp\fR" will output
329 /*	all services named "smtp", and "\fBpostconf -Mf smtp/inet\fR"
330 /*	will output only the smtp service that listens on the
331 /*	network.  Trailing service type fields that are omitted
332 /*	will be handled as "*" wildcard fields.
333 /*
334 /*	This feature is available with Postfix 2.9 and later. The
335 /*	syntax was changed from "\fIname.type\fR" to "\fIname/type\fR",
336 /*	and "*" wildcard support was added with Postfix 2.11.
337 /* .IP \fB-n\fR
338 /*	Show only configuration parameters that have explicit
339 /*	\fIname=value\fR settings in \fBmain.cf\fR.  Specify \fB-nf\fR
340 /*	to fold long lines for human readability (Postfix 2.9 and
341 /*	later).
342 /* .IP "\fB-o \fIname=value\fR"
343 /*	Override \fBmain.cf\fR parameter settings.
344 /*
345 /*	This feature is available with Postfix 2.10 and later.
346 /* .IP \fB-p\fR
347 /*	Show \fBmain.cf\fR parameter settings. This is the default.
348 /*
349 /*	This feature is available with Postfix 2.11 and later.
350 /* .IP \fB-P\fR
351 /*	Show \fBmaster.cf\fR service parameter settings (by default
352 /*	all services and all parameters).  formatted as one
353 /*	"\fIservice/type/parameter=value\fR" per line.  Specify
354 /*	\fB-Pf\fR to fold long lines.
355 /*
356 /*	Specify one or more "\fIservice/type/parameter\fR" instances
357 /*	on the \fBpostconf\fR(1) command line to limit the output
358 /*	to parameters of interest.  Trailing parameter name or
359 /*	service type fields that are omitted will be handled as "*"
360 /*	wildcard fields.
361 /*
362 /*	This feature is available with Postfix 2.11 and later.
363 /* .IP "\fB-t\fR [\fItemplate_file\fR]"
364 /*	Display the templates for text that appears at the beginning
365 /*	of delivery status notification (DSN) messages, without
366 /*	expanding $\fBname\fR expressions.
367 /*
368 /*	To override the built-in templates, specify a template file
369 /*	name at the end of the \fBpostconf\fR(1) command line, or
370 /*	specify a file name in \fBmain.cf\fR with the
371 /*	\fBbounce_template_file\fR parameter.
372 /*
373 /*	To force selection of the built-in templates, specify an
374 /*	empty template file name on the \fBpostconf\fR(1) command
375 /*	line (in shell language: "").
376 /*
377 /*	This feature is available with Postfix 2.3 and later.
378 /* .IP \fB-v\fR
379 /*	Enable verbose logging for debugging purposes. Multiple
380 /*	\fB-v\fR options make the software increasingly verbose.
381 /* .IP \fB-x\fR
382 /*	Expand \fI$name\fR in \fBmain.cf\fR or \fBmaster.cf\fR
383 /*	parameter values. The expansion is recursive.
384 /*
385 /*	This feature is available with Postfix 2.10 and later.
386 /* .IP \fB-X\fR
387 /*	Edit the \fBmain.cf\fR configuration file, and remove the
388 /*	parameters named on the \fBpostconf\fR(1) command line.
389 /*	Specify a list of parameter names, not "\fIname=value\fR"
390 /*	pairs.
391 /*
392 /*	With \fB-M\fR, edit the \fBmaster.cf\fR configuration file,
393 /*	and remove one or more service entries as specified with
394 /*	"\fIservice/type\fR" on the \fBpostconf\fR(1) command line.
395 /*
396 /*	With \fB-P\fR, edit the \fBmaster.cf\fR configuration file,
397 /*	and remove one or more service parameter settings (-o
398 /*	parameter=value settings) as specied with
399 /*	"\fIservice/type/parameter\fR" on the \fBpostconf\fR(1)
400 /*	command line.
401 /*
402 /*	In all cases the file is copied to a temporary file then
403 /*	renamed into place.  Specify quotes to protect special
404 /*	characters on the \fBpostconf\fR(1) command line.
405 /*
406 /*	There is no \fBpostconf\fR(1) command to perform the reverse
407 /*	operation.
408 /*
409 /*	This feature is available with Postfix 2.10 and later.
410 /*	Support for -M and -P was added with Postfix 2.11.
411 /* .IP \fB-#\fR
412 /*	Edit the \fBmain.cf\fR configuration file, and comment out
413 /*	the parameters named on the \fBpostconf\fR(1) command line,
414 /*	so that those parameters revert to their default values.
415 /*	Specify a list of parameter names, not "\fIname=value\fR"
416 /*	pairs.
417 /*
418 /*	With \fB-M\fR, edit the \fBmaster.cf\fR configuration file,
419 /*	and comment out one or more service entries as specified
420 /*	with "\fIservice/type\fR" on the \fBpostconf\fR(1) command
421 /*	line.
422 /*
423 /*	In all cases the file is copied to a temporary file then
424 /*	renamed into place.  Specify quotes to protect special
425 /*	characters on the \fBpostconf\fR(1) command line.
426 /*
427 /*	There is no \fBpostconf\fR(1) command to perform the reverse
428 /*	operation.
429 /*
430 /*	This feature is available with Postfix 2.6 and later. Support
431 /*	for -M was added with Postfix 2.11.
432 /* DIAGNOSTICS
433 /*	Problems are reported to the standard error stream.
434 /* ENVIRONMENT
435 /* .ad
436 /* .fi
437 /* .IP \fBMAIL_CONFIG\fR
438 /*	Directory with Postfix configuration files.
439 /* CONFIGURATION PARAMETERS
440 /* .ad
441 /* .fi
442 /*	The following \fBmain.cf\fR parameters are especially
443 /*	relevant to this program.
444 /*
445 /*	The text below provides only a parameter summary. See
446 /*	\fBpostconf\fR(5) for more details including examples.
447 /* .IP "\fBconfig_directory (see 'postconf -d' output)\fR"
448 /*	The default location of the Postfix main.cf and master.cf
449 /*	configuration files.
450 /* .IP "\fBbounce_template_file (empty)\fR"
451 /*	Pathname of a configuration file with bounce message templates.
452 /* FILES
453 /*	/etc/postfix/main.cf, Postfix configuration parameters
454 /*	/etc/postfix/master.cf, Postfix master daemon configuration
455 /* SEE ALSO
456 /*	bounce(5), bounce template file format master(5), master.cf
457 /*	configuration file syntax postconf(5), main.cf configuration
458 /*	file syntax
459 /* README FILES
460 /* .ad
461 /* .fi
462 /*	Use "\fBpostconf readme_directory\fR" or "\fBpostconf
463 /*	html_directory\fR" to locate this information.
464 /* .na
465 /* .nf
466 /*	DATABASE_README, Postfix lookup table overview
467 /* LICENSE
468 /* .ad
469 /* .fi
470 /*	The Secure Mailer license must be distributed with this
471 /*	software.
472 /* AUTHOR(S)
473 /*	Wietse Venema
474 /*	IBM T.J. Watson Research
475 /*	P.O. Box 704
476 /*	Yorktown Heights, NY 10598, USA
477 /*--*/
478 
479 /* System library. */
480 
481 #include <sys_defs.h>
482 #include <sys/stat.h>
483 #include <stdlib.h>
484 
485 /* Utility library. */
486 
487 #include <msg.h>
488 #include <msg_vstream.h>
489 #include <dict.h>
490 #include <htable.h>
491 #include <vstring.h>
492 #include <vstream.h>
493 #include <stringops.h>
494 #include <name_mask.h>
495 #include <warn_stat.h>
496 #include <mymalloc.h>
497 
498 /* Global library. */
499 
500 #include <mail_params.h>
501 #include <mail_conf.h>
502 #include <mail_version.h>
503 #include <mail_run.h>
504 #include <mail_dict.h>
505 
506 /* Application-specific. */
507 
508 #include <postconf.h>
509 
510  /*
511   * Global storage. See postconf.h for description.
512   */
513 PCF_PARAM_TABLE *pcf_param_table;
514 PCF_MASTER_ENT *pcf_master_table;
515 int     pcf_cmd_mode = PCF_DEF_MODE;
516 
517  /*
518   * Application fingerprinting.
519   */
520 MAIL_VERSION_STAMP_DECLARE;
521 
522  /*
523   * This program has so many command-line options that we have to implement a
524   * compatibility matrix to weed out the conflicting option combinations, and
525   * to alert the user about option combinations that have no effect.
526   */
527 
528  /*
529   * Options that are mutually-exclusive. First entry must specify the major
530   * modes. Other entries specify conflicts between option modifiers.
531   */
532 static const int pcf_incompat_options[] = {
533     /* Major modes. */
534     PCF_SHOW_SASL_SERV | PCF_SHOW_SASL_CLNT | PCF_EXP_DSN_TEMPL \
535     |PCF_SHOW_LOCKS | PCF_SHOW_MAPS | PCF_DUMP_DSN_TEMPL | PCF_MAIN_PARAM \
536     |PCF_MASTER_ENTRY | PCF_MASTER_FLD | PCF_MASTER_PARAM,
537     /* Modifiers. */
538     PCF_SHOW_DEFS | PCF_EDIT_CONF | PCF_SHOW_NONDEF | PCF_COMMENT_OUT \
539     |PCF_EDIT_EXCL,
540     PCF_FOLD_LINE | PCF_EDIT_CONF | PCF_COMMENT_OUT | PCF_EDIT_EXCL,
541     PCF_SHOW_EVAL | PCF_EDIT_CONF | PCF_COMMENT_OUT | PCF_EDIT_EXCL,
542     PCF_MAIN_OVER | PCF_SHOW_DEFS | PCF_EDIT_CONF | PCF_COMMENT_OUT \
543     |PCF_EDIT_EXCL,
544     PCF_HIDE_NAME | PCF_EDIT_CONF | PCF_COMMENT_OUT | PCF_EDIT_EXCL,
545     0,
546 };
547 
548  /*
549   * Options, and the only options that they are compatible with. There must
550   * be one entry for each major mode. Other entries specify compatibility
551   * between option modifiers.
552   */
553 static const int pcf_compat_options[][2] = {
554     /* Major modes. */
555     {PCF_SHOW_SASL_SERV, 0},
556     {PCF_SHOW_SASL_CLNT, 0},
557     {PCF_EXP_DSN_TEMPL, 0},
558     {PCF_SHOW_LOCKS, 0},
559     {PCF_SHOW_MAPS, 0,},
560     {PCF_DUMP_DSN_TEMPL, 0},
561     {PCF_MAIN_PARAM, (PCF_EDIT_CONF | PCF_EDIT_EXCL | PCF_COMMENT_OUT \
562 		      |PCF_FOLD_LINE | PCF_HIDE_NAME | PCF_PARAM_CLASS \
563 		      |PCF_SHOW_EVAL | PCF_SHOW_DEFS | PCF_SHOW_NONDEF \
564 		      |PCF_MAIN_OVER)},
565     {PCF_MASTER_ENTRY, (PCF_EDIT_CONF | PCF_EDIT_EXCL | PCF_COMMENT_OUT \
566 			|PCF_FOLD_LINE | PCF_MAIN_OVER | PCF_SHOW_EVAL)},
567     {PCF_MASTER_FLD, (PCF_EDIT_CONF | PCF_FOLD_LINE | PCF_HIDE_NAME \
568 		      |PCF_MAIN_OVER | PCF_SHOW_EVAL)},
569     {PCF_MASTER_PARAM, (PCF_EDIT_CONF | PCF_EDIT_EXCL | PCF_FOLD_LINE \
570 			|PCF_HIDE_NAME | PCF_MAIN_OVER | PCF_SHOW_EVAL)},
571     /* Modifiers. */
572     {PCF_PARAM_CLASS, (PCF_MAIN_PARAM | PCF_SHOW_DEFS | PCF_SHOW_NONDEF)},
573     0,
574 };
575 
576  /*
577   * Compatibility to string conversion support.
578   */
579 static const NAME_MASK pcf_compat_names[] = {
580     "-a", PCF_SHOW_SASL_SERV,
581     "-A", PCF_SHOW_SASL_CLNT,
582     "-b", PCF_EXP_DSN_TEMPL,
583     "-C", PCF_PARAM_CLASS,
584     "-d", PCF_SHOW_DEFS,
585     "-e", PCF_EDIT_CONF,
586     "-f", PCF_FOLD_LINE,
587     "-F", PCF_MASTER_FLD,
588     "-h", PCF_HIDE_NAME,
589     "-l", PCF_SHOW_LOCKS,
590     "-m", PCF_SHOW_MAPS,
591     "-M", PCF_MASTER_ENTRY,
592     "-n", PCF_SHOW_NONDEF,
593     "-o", PCF_MAIN_OVER,
594     "-p", PCF_MAIN_PARAM,
595     "-P", PCF_MASTER_PARAM,
596     "-t", PCF_DUMP_DSN_TEMPL,
597     "-x", PCF_SHOW_EVAL,
598     "-X", PCF_EDIT_EXCL,
599     "-#", PCF_COMMENT_OUT,
600     0,
601 };
602 
603 /* usage - enumerate parameters without compatibility info */
604 
605 static void usage(const char *progname)
606 {
607     msg_fatal("usage: %s"
608 	      " [-a (server SASL types)]"
609 	      " [-A (client SASL types)]"
610 	      " [-b (bounce templates)]"
611 	      " [-c config_dir]"
612 	      " [-c param_class]"
613 	      " [-d (parameter defaults)]"
614 	      " [-e (edit configuration)]"
615 	      " [-f (fold lines)]"
616 	      " [-F (master.cf fields)]"
617 	      " [-h (no names)]"
618 	      " [-l (lock types)]"
619 	      " [-m (map types)]"
620 	      " [-M (master.cf)]"
621 	      " [-n (non-default parameters)]"
622 	      " [-o name=value (override parameter value)]"
623 	      " [-p (main.cf, default)]"
624 	      " [-P (master.cf parameters)]"
625 	      " [-t (bounce templates)]"
626 	      " [-v (verbose)]"
627 	      " [-x (expand parameter values)]"
628 	      " [-X (exclude)]"
629 	      " [-# (comment-out)]"
630 	      " [name...]", progname);
631 }
632 
633 /* pcf_check_exclusive_options - complain about mutually-exclusive options */
634 
635 static void pcf_check_exclusive_options(int optval)
636 {
637     const char *myname = "pcf_check_exclusive_options";
638     const int *op;
639     int     oval;
640     unsigned mask;
641 
642     for (op = pcf_incompat_options; (oval = *op) != 0; op++) {
643 	oval &= optval;
644 	for (mask = ~0; (mask & oval) != 0; mask >>= 1) {
645 	    if ((mask & oval) != oval)
646 		msg_fatal("specify one of %s",
647 			  str_name_mask(myname, pcf_compat_names, oval));
648 	}
649     }
650 }
651 
652 /* pcf_check_compat_options - complain about incompatible options */
653 
654 static void pcf_check_compat_options(int optval)
655 {
656     const char *myname = "pcf_check_compat_options";
657     VSTRING *buf1 = vstring_alloc(10);
658     VSTRING *buf2 = vstring_alloc(10);
659     const int (*op)[2];
660     int     excess;
661 
662     for (op = pcf_compat_options; op[0][0] != 0; op++) {
663 	if ((optval & *op[0]) != 0
664 	    && (excess = (optval & ~((*op)[0] | (*op)[1]))) != 0)
665 	    msg_fatal("with option %s, do not specify %s",
666 		      str_name_mask_opt(buf1, myname, pcf_compat_names,
667 					(*op)[0], NAME_MASK_NUMBER),
668 		      str_name_mask_opt(buf2, myname, pcf_compat_names,
669 					excess, NAME_MASK_NUMBER));
670     }
671     vstring_free(buf1);
672     vstring_free(buf2);
673 }
674 
675 /* main */
676 
677 int     main(int argc, char **argv)
678 {
679     int     ch;
680     int     fd;
681     struct stat st;
682     ARGV   *ext_argv = 0;
683     int     param_class = PCF_PARAM_MASK_CLASS;
684     static const NAME_MASK param_class_table[] = {
685 	"builtin", PCF_PARAM_FLAG_BUILTIN,
686 	"service", PCF_PARAM_FLAG_SERVICE,
687 	"user", PCF_PARAM_FLAG_USER,
688 	"all", PCF_PARAM_MASK_CLASS,
689 	0,
690     };
691     ARGV   *override_params = 0;
692 
693     /*
694      * Fingerprint executables and core dumps.
695      */
696     MAIL_VERSION_STAMP_ALLOCATE;
697 
698     /*
699      * Be consistent with file permissions.
700      */
701     umask(022);
702 
703     /*
704      * To minimize confusion, make sure that the standard file descriptors
705      * are open before opening anything else. XXX Work around for 44BSD where
706      * fstat can return EBADF on an open file descriptor.
707      */
708     for (fd = 0; fd < 3; fd++)
709 	if (fstat(fd, &st) == -1
710 	    && (close(fd), open("/dev/null", O_RDWR, 0)) != fd)
711 	    msg_fatal("open /dev/null: %m");
712 
713     /*
714      * Set up logging.
715      */
716     msg_vstream_init(argv[0], VSTREAM_ERR);
717 
718     /*
719      * Parse JCL.
720      */
721     while ((ch = GETOPT(argc, argv, "aAbc:C:deEfFhlmMno:pPtvxX#")) > 0) {
722 	switch (ch) {
723 	case 'a':
724 	    pcf_cmd_mode |= PCF_SHOW_SASL_SERV;
725 	    break;
726 	case 'A':
727 	    pcf_cmd_mode |= PCF_SHOW_SASL_CLNT;
728 	    break;
729 	case 'b':
730 	    pcf_cmd_mode |= PCF_EXP_DSN_TEMPL;
731 	    if (ext_argv)
732 		msg_fatal("specify one of -b and -t");
733 	    ext_argv = argv_alloc(2);
734 	    argv_add(ext_argv, "bounce", "-SVnexpand_templates", (char *) 0);
735 	    break;
736 	case 'c':
737 	    if (setenv(CONF_ENV_PATH, optarg, 1) < 0)
738 		msg_fatal("out of memory");
739 	    break;
740 	case 'C':
741 	    param_class = name_mask_opt("-C option", param_class_table,
742 			      optarg, NAME_MASK_ANY_CASE | NAME_MASK_FATAL);
743 	    break;
744 	case 'd':
745 	    pcf_cmd_mode |= PCF_SHOW_DEFS;
746 	    break;
747 	case 'e':
748 	    pcf_cmd_mode |= PCF_EDIT_CONF;
749 	    break;
750 	case 'f':
751 	    pcf_cmd_mode |= PCF_FOLD_LINE;
752 	    break;
753 	case 'F':
754 	    pcf_cmd_mode |= PCF_MASTER_FLD;
755 	    break;
756 	case '#':
757 	    pcf_cmd_mode |= PCF_COMMENT_OUT;
758 	    break;
759 	case 'h':
760 	    pcf_cmd_mode |= PCF_HIDE_NAME;
761 	    break;
762 	case 'l':
763 	    pcf_cmd_mode |= PCF_SHOW_LOCKS;
764 	    break;
765 	case 'm':
766 	    pcf_cmd_mode |= PCF_SHOW_MAPS;
767 	    break;
768 	case 'M':
769 	    pcf_cmd_mode |= PCF_MASTER_ENTRY;
770 	    break;
771 	case 'n':
772 	    pcf_cmd_mode |= PCF_SHOW_NONDEF;
773 	    break;
774 	case 'o':
775 	    pcf_cmd_mode |= PCF_MAIN_OVER;
776 	    if (override_params == 0)
777 		override_params = argv_alloc(2);
778 	    argv_add(override_params, optarg, (char *) 0);
779 	    break;
780 	case 'p':
781 	    pcf_cmd_mode |= PCF_MAIN_PARAM;
782 	    break;
783 	case 'P':
784 	    pcf_cmd_mode |= PCF_MASTER_PARAM;
785 	    break;
786 	case 't':
787 	    pcf_cmd_mode |= PCF_DUMP_DSN_TEMPL;
788 	    if (ext_argv)
789 		msg_fatal("specify one of -b and -t");
790 	    ext_argv = argv_alloc(2);
791 	    argv_add(ext_argv, "bounce", "-SVndump_templates", (char *) 0);
792 	    break;
793 	case 'x':
794 	    pcf_cmd_mode |= PCF_SHOW_EVAL;
795 	    break;
796 	case 'X':
797 	    /* This is irreversible, therefore require two-finger action. */
798 	    pcf_cmd_mode |= PCF_EDIT_EXCL;
799 	    break;
800 	case 'v':
801 	    msg_verbose++;
802 	    break;
803 	default:
804 	    usage(argv[0]);
805 	}
806     }
807 
808     /*
809      * Make all options explicit, before checking their compatibility.
810      */
811 #define PCF_MAIN_OR_MASTER \
812 	(PCF_MAIN_PARAM | PCF_MASTER_ENTRY | PCF_MASTER_FLD | PCF_MASTER_PARAM)
813 
814     if ((pcf_cmd_mode & pcf_incompat_options[0]) == 0)
815 	pcf_cmd_mode |= PCF_MAIN_PARAM;
816     if ((pcf_cmd_mode & PCF_MAIN_OR_MASTER)
817 	&& argv[optind] && strchr(argv[optind], '='))
818 	pcf_cmd_mode |= PCF_EDIT_CONF;
819 
820     /*
821      * Sanity check.
822      */
823     pcf_check_exclusive_options(pcf_cmd_mode);
824     pcf_check_compat_options(pcf_cmd_mode);
825 
826     if ((pcf_cmd_mode & PCF_EDIT_CONF) && argc == optind)
827 	msg_fatal("-e requires name=value argument");
828 
829     /*
830      * Display bounce template information and exit.
831      */
832     if (ext_argv) {
833 	if (argv[optind]) {
834 	    if (argv[optind + 1])
835 		msg_fatal("options -b and -t require at most one template file");
836 	    argv_add(ext_argv, "-o",
837 		     concatenate(VAR_BOUNCE_TMPL, "=",
838 				 argv[optind], (char *) 0),
839 		     (char *) 0);
840 	}
841 	/* Grr... */
842 	argv_add(ext_argv, "-o",
843 		 concatenate(VAR_QUEUE_DIR, "=", ".", (char *) 0),
844 		 (char *) 0);
845 	mail_conf_read();
846 	mail_run_replace(var_daemon_dir, ext_argv->argv);
847 	/* NOTREACHED */
848     }
849 
850     /*
851      * If showing map types, show them and exit
852      */
853     if (pcf_cmd_mode & PCF_SHOW_MAPS) {
854 	mail_dict_init();
855 	pcf_show_maps();
856     }
857 
858     /*
859      * If showing locking methods, show them and exit
860      */
861     else if (pcf_cmd_mode & PCF_SHOW_LOCKS) {
862 	pcf_show_locks();
863     }
864 
865     /*
866      * If showing master.cf entries, show them and exit
867      */
868     else if ((pcf_cmd_mode & (PCF_MASTER_ENTRY | PCF_MASTER_FLD | PCF_MASTER_PARAM))
869     && !(pcf_cmd_mode & (PCF_EDIT_CONF | PCF_EDIT_EXCL | PCF_COMMENT_OUT))) {
870 	pcf_read_master(PCF_FAIL_ON_OPEN_ERROR);
871 	pcf_read_parameters();
872 	if (override_params)
873 	    pcf_set_parameters(override_params->argv);
874 	pcf_register_builtin_parameters(basename(argv[0]), getpid());
875 	pcf_register_service_parameters();
876 	pcf_register_user_parameters();
877 	if (pcf_cmd_mode & PCF_MASTER_FLD)
878 	    pcf_show_master_fields(VSTREAM_OUT, pcf_cmd_mode, argc - optind,
879 				   argv + optind);
880 	else if (pcf_cmd_mode & PCF_MASTER_PARAM)
881 	    pcf_show_master_params(VSTREAM_OUT, pcf_cmd_mode, argc - optind,
882 				   argv + optind);
883 	else
884 	    pcf_show_master_entries(VSTREAM_OUT, pcf_cmd_mode, argc - optind,
885 				    argv + optind);
886     }
887 
888     /*
889      * If showing SASL plug-in types, show them and exit
890      */
891     else if (pcf_cmd_mode & PCF_SHOW_SASL_SERV) {
892 	pcf_show_sasl(PCF_SHOW_SASL_SERV);
893     } else if (pcf_cmd_mode & PCF_SHOW_SASL_CLNT) {
894 	pcf_show_sasl(PCF_SHOW_SASL_CLNT);
895     }
896 
897     /*
898      * Edit main.cf or master.cf.
899      */
900     else if (pcf_cmd_mode & (PCF_EDIT_CONF | PCF_COMMENT_OUT | PCF_EDIT_EXCL)) {
901 	if (optind == argc)
902 	    msg_fatal("missing service argument");
903 	if (pcf_cmd_mode & (PCF_MASTER_ENTRY | PCF_MASTER_FLD | PCF_MASTER_PARAM)) {
904 	    pcf_edit_master(pcf_cmd_mode, argc - optind, argv + optind);
905 	} else {
906 	    pcf_edit_main(pcf_cmd_mode, argc - optind, argv + optind);
907 	}
908     }
909 
910     /*
911      * If showing non-default values, read main.cf.
912      */
913     else {
914 	if ((pcf_cmd_mode & PCF_SHOW_DEFS) == 0) {
915 	    pcf_read_parameters();
916 	    if (override_params)
917 		pcf_set_parameters(override_params->argv);
918 	}
919 	pcf_register_builtin_parameters(basename(argv[0]), getpid());
920 
921 	/*
922 	 * Add service-dependent parameters (service names from master.cf)
923 	 * and user-defined parameters ($name macros in parameter values in
924 	 * main.cf and master.cf, but only if those names have a name=value
925 	 * in main.cf or master.cf).
926 	 */
927 	pcf_read_master(PCF_WARN_ON_OPEN_ERROR);
928 	pcf_register_service_parameters();
929 	if ((pcf_cmd_mode & PCF_SHOW_DEFS) == 0)
930 	    pcf_register_user_parameters();
931 
932 	/*
933 	 * Show the requested values.
934 	 */
935 	pcf_show_parameters(VSTREAM_OUT, pcf_cmd_mode, param_class,
936 			    argv + optind);
937 
938 	/*
939 	 * Flag unused parameters. This makes no sense with "postconf -d",
940 	 * because that ignores all the user-specified parameters and
941 	 * user-specified macro expansions in main.cf.
942 	 */
943 	if ((pcf_cmd_mode & PCF_SHOW_DEFS) == 0) {
944 	    pcf_flag_unused_main_parameters();
945 	    pcf_flag_unused_master_parameters();
946 	}
947     }
948     vstream_fflush(VSTREAM_OUT);
949     exit(0);
950 }
951