Add cmdline option to append a log message. Bug 418
[exim.git] / src / src / readconf.c
CommitLineData
059ec3d9
PH
1/*************************************************
2* Exim - an Internet mail transport agent *
3*************************************************/
4
5a66c31b 5/* Copyright (c) University of Cambridge 1995 - 2014 */
059ec3d9
PH
6/* See the file NOTICE for conditions of use and distribution. */
7
8/* Functions for reading the configuration file, and for displaying
9overall configuration values. Thanks to Brian Candler for the original
10implementation of the conditional .ifdef etc. */
11
12#include "exim.h"
13
14#define CSTATE_STACK_SIZE 10
15
16
17/* Structure for chain (stack) of .included files */
18
19typedef struct config_file_item {
20 struct config_file_item *next;
21 uschar *filename;
22 FILE *file;
23 int lineno;
24} config_file_item;
25
26/* Structure of table of conditional words and their state transitions */
27
28typedef struct cond_item {
29 uschar *name;
30 int namelen;
31 int action1;
32 int action2;
33 int pushpop;
34} cond_item;
35
36/* Structure of table of syslog facility names and values */
37
38typedef struct syslog_fac_item {
39 uschar *name;
40 int value;
41} syslog_fac_item;
42
43
44/* Static variables */
45
46static config_file_item *config_file_stack = NULL; /* For includes */
47
48static uschar *syslog_facility_str = NULL;
49static uschar next_section[24];
50static uschar time_buffer[24];
51
52/* State variables for conditional loading (.ifdef / .else / .endif) */
53
54static int cstate = 0;
55static int cstate_stack_ptr = -1;
56static int cstate_stack[CSTATE_STACK_SIZE];
57
58/* Table of state transitions for handling conditional inclusions. There are
59four possible state transitions:
60
61 .ifdef true
62 .ifdef false
63 .elifdef true (or .else)
64 .elifdef false
65
66.endif just causes the previous cstate to be popped off the stack */
67
68static int next_cstate[3][4] =
69 {
70 /* State 0: reading from file, or reading until next .else or .endif */
71 { 0, 1, 2, 2 },
72 /* State 1: condition failed, skipping until next .else or .endif */
73 { 2, 2, 0, 1 },
74 /* State 2: skipping until .endif */
75 { 2, 2, 2, 2 },
76 };
77
78/* Table of conditionals and the states to set. For each name, there are four
79values: the length of the name (to save computing it each time), the state to
80set if a macro was found in the line, the state to set if a macro was not found
81in the line, and a stack manipulation setting which is:
82
83 -1 pull state value off the stack
84 0 don't alter the stack
85 +1 push value onto stack, before setting new state
86*/
87
88static cond_item cond_list[] = {
89 { US"ifdef", 5, 0, 1, 1 },
90 { US"ifndef", 6, 1, 0, 1 },
91 { US"elifdef", 7, 2, 3, 0 },
92 { US"elifndef", 8, 3, 2, 0 },
93 { US"else", 4, 2, 2, 0 },
94 { US"endif", 5, 0, 0, -1 }
95};
96
97static int cond_list_size = sizeof(cond_list)/sizeof(cond_item);
98
99/* Table of syslog facility names and their values */
100
101static syslog_fac_item syslog_list[] = {
102 { US"mail", LOG_MAIL },
103 { US"user", LOG_USER },
104 { US"news", LOG_NEWS },
105 { US"uucp", LOG_UUCP },
106 { US"local0", LOG_LOCAL0 },
107 { US"local1", LOG_LOCAL1 },
108 { US"local2", LOG_LOCAL2 },
109 { US"local3", LOG_LOCAL3 },
110 { US"local4", LOG_LOCAL4 },
111 { US"local5", LOG_LOCAL5 },
112 { US"local6", LOG_LOCAL6 },
113 { US"local7", LOG_LOCAL7 },
114 { US"daemon", LOG_DAEMON }
115};
116
117static int syslog_list_size = sizeof(syslog_list)/sizeof(syslog_fac_item);
118
119
120
121
122/*************************************************
123* Main configuration options *
124*************************************************/
125
126/* The list of options that can be set in the main configuration file. This
127must be in alphabetic order because it is searched by binary chop. */
128
129static optionlist optionlist_config[] = {
130 { "*set_exim_group", opt_bool|opt_hidden, &exim_gid_set },
131 { "*set_exim_user", opt_bool|opt_hidden, &exim_uid_set },
132 { "*set_system_filter_group", opt_bool|opt_hidden, &system_filter_gid_set },
133 { "*set_system_filter_user", opt_bool|opt_hidden, &system_filter_uid_set },
134 { "accept_8bitmime", opt_bool, &accept_8bitmime },
135 { "acl_not_smtp", opt_stringptr, &acl_not_smtp },
54cdb463
PH
136#ifdef WITH_CONTENT_SCAN
137 { "acl_not_smtp_mime", opt_stringptr, &acl_not_smtp_mime },
138#endif
45b91596 139 { "acl_not_smtp_start", opt_stringptr, &acl_not_smtp_start },
059ec3d9
PH
140 { "acl_smtp_auth", opt_stringptr, &acl_smtp_auth },
141 { "acl_smtp_connect", opt_stringptr, &acl_smtp_connect },
142 { "acl_smtp_data", opt_stringptr, &acl_smtp_data },
8ccd00b1 143#ifndef DISABLE_PRDR
fd98a5c6
JH
144 { "acl_smtp_data_prdr", opt_stringptr, &acl_smtp_data_prdr },
145#endif
80a47a2c
TK
146#ifndef DISABLE_DKIM
147 { "acl_smtp_dkim", opt_stringptr, &acl_smtp_dkim },
148#endif
059ec3d9
PH
149 { "acl_smtp_etrn", opt_stringptr, &acl_smtp_etrn },
150 { "acl_smtp_expn", opt_stringptr, &acl_smtp_expn },
151 { "acl_smtp_helo", opt_stringptr, &acl_smtp_helo },
152 { "acl_smtp_mail", opt_stringptr, &acl_smtp_mail },
153 { "acl_smtp_mailauth", opt_stringptr, &acl_smtp_mailauth },
8523533c
TK
154#ifdef WITH_CONTENT_SCAN
155 { "acl_smtp_mime", opt_stringptr, &acl_smtp_mime },
156#endif
8f128379 157 { "acl_smtp_notquit", opt_stringptr, &acl_smtp_notquit },
059ec3d9
PH
158 { "acl_smtp_predata", opt_stringptr, &acl_smtp_predata },
159 { "acl_smtp_quit", opt_stringptr, &acl_smtp_quit },
160 { "acl_smtp_rcpt", opt_stringptr, &acl_smtp_rcpt },
161#ifdef SUPPORT_TLS
162 { "acl_smtp_starttls", opt_stringptr, &acl_smtp_starttls },
163#endif
164 { "acl_smtp_vrfy", opt_stringptr, &acl_smtp_vrfy },
165 { "admin_groups", opt_gidlist, &admin_groups },
166 { "allow_domain_literals", opt_bool, &allow_domain_literals },
167 { "allow_mx_to_ip", opt_bool, &allow_mx_to_ip },
168 { "allow_utf8_domains", opt_bool, &allow_utf8_domains },
169 { "auth_advertise_hosts", opt_stringptr, &auth_advertise_hosts },
170 { "auto_thaw", opt_time, &auto_thaw },
8523533c
TK
171#ifdef WITH_CONTENT_SCAN
172 { "av_scanner", opt_stringptr, &av_scanner },
173#endif
059ec3d9 174 { "bi_command", opt_stringptr, &bi_command },
8523533c
TK
175#ifdef EXPERIMENTAL_BRIGHTMAIL
176 { "bmi_config_file", opt_stringptr, &bmi_config_file },
177#endif
059ec3d9
PH
178 { "bounce_message_file", opt_stringptr, &bounce_message_file },
179 { "bounce_message_text", opt_stringptr, &bounce_message_text },
180 { "bounce_return_body", opt_bool, &bounce_return_body },
181 { "bounce_return_message", opt_bool, &bounce_return_message },
182 { "bounce_return_size_limit", opt_mkint, &bounce_return_size_limit },
183 { "bounce_sender_authentication",opt_stringptr,&bounce_sender_authentication },
184 { "callout_domain_negative_expire", opt_time, &callout_cache_domain_negative_expire },
185 { "callout_domain_positive_expire", opt_time, &callout_cache_domain_positive_expire },
186 { "callout_negative_expire", opt_time, &callout_cache_negative_expire },
187 { "callout_positive_expire", opt_time, &callout_cache_positive_expire },
188 { "callout_random_local_part",opt_stringptr, &callout_random_local_part },
189 { "check_log_inodes", opt_int, &check_log_inodes },
190 { "check_log_space", opt_Kint, &check_log_space },
a0d6ba8a 191 { "check_rfc2047_length", opt_bool, &check_rfc2047_length },
059ec3d9
PH
192 { "check_spool_inodes", opt_int, &check_spool_inodes },
193 { "check_spool_space", opt_Kint, &check_spool_space },
194 { "daemon_smtp_port", opt_stringptr|opt_hidden, &daemon_smtp_port },
195 { "daemon_smtp_ports", opt_stringptr, &daemon_smtp_port },
4aee0225
PH
196 { "daemon_startup_retries", opt_int, &daemon_startup_retries },
197 { "daemon_startup_sleep", opt_time, &daemon_startup_sleep },
6a8f9482
TK
198#ifdef EXPERIMENTAL_DCC
199 { "dcc_direct_add_header", opt_bool, &dcc_direct_add_header },
200 { "dccifd_address", opt_stringptr, &dccifd_address },
201 { "dccifd_options", opt_stringptr, &dccifd_options },
202#endif
059ec3d9
PH
203 { "delay_warning", opt_timelist, &delay_warning },
204 { "delay_warning_condition", opt_stringptr, &delay_warning_condition },
205 { "deliver_drop_privilege", opt_bool, &deliver_drop_privilege },
206 { "deliver_queue_load_max", opt_fixed, &deliver_queue_load_max },
207 { "delivery_date_remove", opt_bool, &delivery_date_remove },
54fc8428
PH
208#ifdef ENABLE_DISABLE_FSYNC
209 { "disable_fsync", opt_bool, &disable_fsync },
210#endif
7e66e54d 211 { "disable_ipv6", opt_bool, &disable_ipv6 },
80a47a2c
TK
212#ifndef DISABLE_DKIM
213 { "dkim_verify_signers", opt_stringptr, &dkim_verify_signers },
214#endif
4840604e
TL
215#ifdef EXPERIMENTAL_DMARC
216 { "dmarc_forensic_sender", opt_stringptr, &dmarc_forensic_sender },
217 { "dmarc_history_file", opt_stringptr, &dmarc_history_file },
218 { "dmarc_tld_file", opt_stringptr, &dmarc_tld_file },
219#endif
059ec3d9
PH
220 { "dns_again_means_nonexist", opt_stringptr, &dns_again_means_nonexist },
221 { "dns_check_names_pattern", opt_stringptr, &check_dns_names_pattern },
e5a9dba6
PH
222 { "dns_csa_search_limit", opt_int, &dns_csa_search_limit },
223 { "dns_csa_use_reverse", opt_bool, &dns_csa_use_reverse },
83712b39 224 { "dns_dnssec_ok", opt_int, &dns_dnssec_ok },
059ec3d9
PH
225 { "dns_ipv4_lookup", opt_stringptr, &dns_ipv4_lookup },
226 { "dns_retrans", opt_time, &dns_retrans },
227 { "dns_retry", opt_int, &dns_retry },
e97d1f08 228 { "dns_use_edns0", opt_int, &dns_use_edns0 },
059ec3d9
PH
229 /* This option is now a no-op, retained for compability */
230 { "drop_cr", opt_bool, &drop_cr },
231/*********************************************************/
6c1c3d1d 232 { "dsn_advertise_hosts", opt_stringptr, &dsn_advertise_hosts },
0e22dfd1 233 { "dsn_from", opt_stringptr, &dsn_from },
059ec3d9
PH
234 { "envelope_to_remove", opt_bool, &envelope_to_remove },
235 { "errors_copy", opt_stringptr, &errors_copy },
236 { "errors_reply_to", opt_stringptr, &errors_reply_to },
774ef2d7
JH
237#ifdef EXPERIMENTAL_EVENT
238 { "event_action", opt_stringptr, &event_action },
239#endif
059ec3d9
PH
240 { "exim_group", opt_gid, &exim_gid },
241 { "exim_path", opt_stringptr, &exim_path },
242 { "exim_user", opt_uid, &exim_uid },
243 { "extra_local_interfaces", opt_stringptr, &extra_local_interfaces },
244 { "extract_addresses_remove_arguments", opt_bool, &extract_addresses_remove_arguments },
245 { "finduser_retries", opt_int, &finduser_retries },
246 { "freeze_tell", opt_stringptr, &freeze_tell },
247 { "gecos_name", opt_stringptr, &gecos_name },
248 { "gecos_pattern", opt_stringptr, &gecos_pattern },
83da1223 249#ifdef SUPPORT_TLS
2519e60d 250 { "gnutls_allow_auto_pkcs11", opt_bool, &gnutls_allow_auto_pkcs11 },
e6060e2c 251 { "gnutls_compat_mode", opt_bool, &gnutls_compat_mode },
b1770b6e 252 /* These three gnutls_require_* options stopped working in Exim 4.80 */
2d571266 253 /* From 4.83 we log a warning; a future relase will remove them */
83da1223
PH
254 { "gnutls_require_kx", opt_stringptr, &gnutls_require_kx },
255 { "gnutls_require_mac", opt_stringptr, &gnutls_require_mac },
256 { "gnutls_require_protocols", opt_stringptr, &gnutls_require_proto },
257#endif
059ec3d9
PH
258 { "header_line_maxsize", opt_int, &header_line_maxsize },
259 { "header_maxsize", opt_int, &header_maxsize },
260 { "headers_charset", opt_stringptr, &headers_charset },
261 { "helo_accept_junk_hosts", opt_stringptr, &helo_accept_junk_hosts },
262 { "helo_allow_chars", opt_stringptr, &helo_allow_chars },
263 { "helo_lookup_domains", opt_stringptr, &helo_lookup_domains },
264 { "helo_try_verify_hosts", opt_stringptr, &helo_try_verify_hosts },
265 { "helo_verify_hosts", opt_stringptr, &helo_verify_hosts },
266 { "hold_domains", opt_stringptr, &hold_domains },
267 { "host_lookup", opt_stringptr, &host_lookup },
268 { "host_lookup_order", opt_stringptr, &host_lookup_order },
269 { "host_reject_connection", opt_stringptr, &host_reject_connection },
270 { "hosts_connection_nolog", opt_stringptr, &hosts_connection_nolog },
271 { "hosts_treat_as_local", opt_stringptr, &hosts_treat_as_local },
272#ifdef LOOKUP_IBASE
273 { "ibase_servers", opt_stringptr, &ibase_servers },
274#endif
275 { "ignore_bounce_errors_after", opt_time, &ignore_bounce_errors_after },
276 { "ignore_fromline_hosts", opt_stringptr, &ignore_fromline_hosts },
277 { "ignore_fromline_local", opt_bool, &ignore_fromline_local },
278 { "keep_malformed", opt_time, &keep_malformed },
279#ifdef LOOKUP_LDAP
bc19a55b
PP
280 { "ldap_ca_cert_dir", opt_stringptr, &eldap_ca_cert_dir },
281 { "ldap_ca_cert_file", opt_stringptr, &eldap_ca_cert_file },
282 { "ldap_cert_file", opt_stringptr, &eldap_cert_file },
283 { "ldap_cert_key", opt_stringptr, &eldap_cert_key },
284 { "ldap_cipher_suite", opt_stringptr, &eldap_cipher_suite },
059ec3d9 285 { "ldap_default_servers", opt_stringptr, &eldap_default_servers },
bc19a55b
PP
286 { "ldap_require_cert", opt_stringptr, &eldap_require_cert },
287 { "ldap_start_tls", opt_bool, &eldap_start_tls },
059ec3d9
PH
288 { "ldap_version", opt_int, &eldap_version },
289#endif
290 { "local_from_check", opt_bool, &local_from_check },
291 { "local_from_prefix", opt_stringptr, &local_from_prefix },
292 { "local_from_suffix", opt_stringptr, &local_from_suffix },
293 { "local_interfaces", opt_stringptr, &local_interfaces },
294 { "local_scan_timeout", opt_time, &local_scan_timeout },
295 { "local_sender_retain", opt_bool, &local_sender_retain },
296 { "localhost_number", opt_stringptr, &host_number_string },
297 { "log_file_path", opt_stringptr, &log_file_path },
298 { "log_selector", opt_stringptr, &log_selector_string },
299 { "log_timezone", opt_bool, &log_timezone },
300 { "lookup_open_max", opt_int, &lookup_open_max },
301 { "max_username_length", opt_int, &max_username_length },
ddea74fa 302 { "message_body_newlines", opt_bool, &message_body_newlines },
059ec3d9
PH
303 { "message_body_visible", opt_mkint, &message_body_visible },
304 { "message_id_header_domain", opt_stringptr, &message_id_domain },
305 { "message_id_header_text", opt_stringptr, &message_id_text },
306 { "message_logs", opt_bool, &message_logs },
307 { "message_size_limit", opt_stringptr, &message_size_limit },
308#ifdef SUPPORT_MOVE_FROZEN_MESSAGES
309 { "move_frozen_messages", opt_bool, &move_frozen_messages },
310#endif
311 { "mua_wrapper", opt_bool, &mua_wrapper },
312#ifdef LOOKUP_MYSQL
313 { "mysql_servers", opt_stringptr, &mysql_servers },
314#endif
315 { "never_users", opt_uidlist, &never_users },
77bb000f
PP
316#ifdef SUPPORT_TLS
317 { "openssl_options", opt_stringptr, &openssl_options },
318#endif
059ec3d9
PH
319#ifdef LOOKUP_ORACLE
320 { "oracle_servers", opt_stringptr, &oracle_servers },
321#endif
322 { "percent_hack_domains", opt_stringptr, &percent_hack_domains },
323#ifdef EXIM_PERL
324 { "perl_at_start", opt_bool, &opt_perl_at_start },
325 { "perl_startup", opt_stringptr, &opt_perl_startup },
326#endif
327#ifdef LOOKUP_PGSQL
328 { "pgsql_servers", opt_stringptr, &pgsql_servers },
329#endif
330 { "pid_file_path", opt_stringptr, &pid_file_path },
331 { "pipelining_advertise_hosts", opt_stringptr, &pipelining_advertise_hosts },
8ccd00b1 332#ifndef DISABLE_PRDR
fd98a5c6
JH
333 { "prdr_enable", opt_bool, &prdr_enable },
334#endif
059ec3d9
PH
335 { "preserve_message_logs", opt_bool, &preserve_message_logs },
336 { "primary_hostname", opt_stringptr, &primary_hostname },
337 { "print_topbitchars", opt_bool, &print_topbitchars },
338 { "process_log_path", opt_stringptr, &process_log_path },
339 { "prod_requires_admin", opt_bool, &prod_requires_admin },
a3c86431
TL
340#ifdef EXPERIMENTAL_PROXY
341 { "proxy_required_hosts", opt_stringptr, &proxy_required_hosts },
342#endif
059ec3d9
PH
343 { "qualify_domain", opt_stringptr, &qualify_domain_sender },
344 { "qualify_recipient", opt_stringptr, &qualify_domain_recipient },
345 { "queue_domains", opt_stringptr, &queue_domains },
346 { "queue_list_requires_admin",opt_bool, &queue_list_requires_admin },
347 { "queue_only", opt_bool, &queue_only },
348 { "queue_only_file", opt_stringptr, &queue_only_file },
349 { "queue_only_load", opt_fixed, &queue_only_load },
8669f003 350 { "queue_only_load_latch", opt_bool, &queue_only_load_latch },
059ec3d9
PH
351 { "queue_only_override", opt_bool, &queue_only_override },
352 { "queue_run_in_order", opt_bool, &queue_run_in_order },
353 { "queue_run_max", opt_int, &queue_run_max },
354 { "queue_smtp_domains", opt_stringptr, &queue_smtp_domains },
355 { "receive_timeout", opt_time, &receive_timeout },
356 { "received_header_text", opt_stringptr, &received_header_text },
357 { "received_headers_max", opt_int, &received_headers_max },
358 { "recipient_unqualified_hosts", opt_stringptr, &recipient_unqualified_hosts },
359 { "recipients_max", opt_int, &recipients_max },
360 { "recipients_max_reject", opt_bool, &recipients_max_reject },
9bdd29ad
TL
361#ifdef EXPERIMENTAL_REDIS
362 { "redis_servers", opt_stringptr, &redis_servers },
363#endif
059ec3d9
PH
364 { "remote_max_parallel", opt_int, &remote_max_parallel },
365 { "remote_sort_domains", opt_stringptr, &remote_sort_domains },
366 { "retry_data_expire", opt_time, &retry_data_expire },
367 { "retry_interval_max", opt_time, &retry_interval_max },
368 { "return_path_remove", opt_bool, &return_path_remove },
369 { "return_size_limit", opt_mkint|opt_hidden, &bounce_return_size_limit },
370 { "rfc1413_hosts", opt_stringptr, &rfc1413_hosts },
371 { "rfc1413_query_timeout", opt_time, &rfc1413_query_timeout },
372 { "sender_unqualified_hosts", opt_stringptr, &sender_unqualified_hosts },
373 { "smtp_accept_keepalive", opt_bool, &smtp_accept_keepalive },
374 { "smtp_accept_max", opt_int, &smtp_accept_max },
375 { "smtp_accept_max_nonmail", opt_int, &smtp_accept_max_nonmail },
376 { "smtp_accept_max_nonmail_hosts", opt_stringptr, &smtp_accept_max_nonmail_hosts },
377 { "smtp_accept_max_per_connection", opt_int, &smtp_accept_max_per_connection },
378 { "smtp_accept_max_per_host", opt_stringptr, &smtp_accept_max_per_host },
379 { "smtp_accept_queue", opt_int, &smtp_accept_queue },
380 { "smtp_accept_queue_per_connection", opt_int, &smtp_accept_queue_per_connection },
381 { "smtp_accept_reserve", opt_int, &smtp_accept_reserve },
382 { "smtp_active_hostname", opt_stringptr, &raw_active_hostname },
383 { "smtp_banner", opt_stringptr, &smtp_banner },
384 { "smtp_check_spool_space", opt_bool, &smtp_check_spool_space },
385 { "smtp_connect_backlog", opt_int, &smtp_connect_backlog },
386 { "smtp_enforce_sync", opt_bool, &smtp_enforce_sync },
387 { "smtp_etrn_command", opt_stringptr, &smtp_etrn_command },
388 { "smtp_etrn_serialize", opt_bool, &smtp_etrn_serialize },
389 { "smtp_load_reserve", opt_fixed, &smtp_load_reserve },
390 { "smtp_max_synprot_errors", opt_int, &smtp_max_synprot_errors },
391 { "smtp_max_unknown_commands",opt_int, &smtp_max_unknown_commands },
392 { "smtp_ratelimit_hosts", opt_stringptr, &smtp_ratelimit_hosts },
393 { "smtp_ratelimit_mail", opt_stringptr, &smtp_ratelimit_mail },
394 { "smtp_ratelimit_rcpt", opt_stringptr, &smtp_ratelimit_rcpt },
395 { "smtp_receive_timeout", opt_time, &smtp_receive_timeout },
396 { "smtp_reserve_hosts", opt_stringptr, &smtp_reserve_hosts },
397 { "smtp_return_error_details",opt_bool, &smtp_return_error_details },
8523533c
TK
398#ifdef WITH_CONTENT_SCAN
399 { "spamd_address", opt_stringptr, &spamd_address },
400#endif
65a7d8c3
NM
401#ifdef EXPERIMENTAL_SPF
402 { "spf_guess", opt_stringptr, &spf_guess },
403#endif
059ec3d9
PH
404 { "split_spool_directory", opt_bool, &split_spool_directory },
405 { "spool_directory", opt_stringptr, &spool_directory },
31480e42
PH
406#ifdef LOOKUP_SQLITE
407 { "sqlite_lock_timeout", opt_int, &sqlite_lock_timeout },
408#endif
8523533c
TK
409#ifdef EXPERIMENTAL_SRS
410 { "srs_config", opt_stringptr, &srs_config },
384152a6
TK
411 { "srs_hashlength", opt_int, &srs_hashlength },
412 { "srs_hashmin", opt_int, &srs_hashmin },
413 { "srs_maxage", opt_int, &srs_maxage },
414 { "srs_secrets", opt_stringptr, &srs_secrets },
415 { "srs_usehash", opt_bool, &srs_usehash },
416 { "srs_usetimestamp", opt_bool, &srs_usetimestamp },
8523533c 417#endif
38a0a95f 418 { "strict_acl_vars", opt_bool, &strict_acl_vars },
059ec3d9
PH
419 { "strip_excess_angle_brackets", opt_bool, &strip_excess_angle_brackets },
420 { "strip_trailing_dot", opt_bool, &strip_trailing_dot },
421 { "syslog_duplication", opt_bool, &syslog_duplication },
422 { "syslog_facility", opt_stringptr, &syslog_facility_str },
423 { "syslog_processname", opt_stringptr, &syslog_processname },
424 { "syslog_timestamp", opt_bool, &syslog_timestamp },
425 { "system_filter", opt_stringptr, &system_filter },
426 { "system_filter_directory_transport", opt_stringptr,&system_filter_directory_transport },
427 { "system_filter_file_transport",opt_stringptr,&system_filter_file_transport },
428 { "system_filter_group", opt_gid, &system_filter_gid },
429 { "system_filter_pipe_transport",opt_stringptr,&system_filter_pipe_transport },
430 { "system_filter_reply_transport",opt_stringptr,&system_filter_reply_transport },
431 { "system_filter_user", opt_uid, &system_filter_uid },
432 { "tcp_nodelay", opt_bool, &tcp_nodelay },
5dc43717
JJ
433#ifdef USE_TCP_WRAPPERS
434 { "tcp_wrappers_daemon_name", opt_stringptr, &tcp_wrappers_daemon_name },
435#endif
059ec3d9
PH
436 { "timeout_frozen_after", opt_time, &timeout_frozen_after },
437 { "timezone", opt_stringptr, &timezone_string },
438#ifdef SUPPORT_TLS
439 { "tls_advertise_hosts", opt_stringptr, &tls_advertise_hosts },
440 { "tls_certificate", opt_stringptr, &tls_certificate },
441 { "tls_crl", opt_stringptr, &tls_crl },
3375e053 442 { "tls_dh_max_bits", opt_int, &tls_dh_max_bits },
059ec3d9 443 { "tls_dhparam", opt_stringptr, &tls_dhparam },
f2de3a33 444# ifndef DISABLE_OCSP
3f7eeb86 445 { "tls_ocsp_file", opt_stringptr, &tls_ocsp_file },
817d9f57
JH
446# endif
447 { "tls_on_connect_ports", opt_stringptr, &tls_in.on_connect_ports },
059ec3d9
PH
448 { "tls_privatekey", opt_stringptr, &tls_privatekey },
449 { "tls_remember_esmtp", opt_bool, &tls_remember_esmtp },
450 { "tls_require_ciphers", opt_stringptr, &tls_require_ciphers },
451 { "tls_try_verify_hosts", opt_stringptr, &tls_try_verify_hosts },
452 { "tls_verify_certificates", opt_stringptr, &tls_verify_certificates },
453 { "tls_verify_hosts", opt_stringptr, &tls_verify_hosts },
454#endif
455 { "trusted_groups", opt_gidlist, &trusted_groups },
456 { "trusted_users", opt_uidlist, &trusted_users },
457 { "unknown_login", opt_stringptr, &unknown_login },
458 { "unknown_username", opt_stringptr, &unknown_username },
459 { "untrusted_set_sender", opt_stringptr, &untrusted_set_sender },
460 { "uucp_from_pattern", opt_stringptr, &uucp_from_pattern },
461 { "uucp_from_sender", opt_stringptr, &uucp_from_sender },
462 { "warn_message_file", opt_stringptr, &warn_message_file },
463 { "write_rejectlog", opt_bool, &write_rejectlog }
464};
465
466static int optionlist_config_size =
467 sizeof(optionlist_config)/sizeof(optionlist);
468
469
470
471/*************************************************
472* Find the name of an option *
473*************************************************/
474
475/* This function is to aid debugging. Various functions take arguments that are
476pointer variables in the options table or in option tables for various drivers.
477For debugging output, it is useful to be able to find the name of the option
478which is currently being processed. This function finds it, if it exists, by
479searching the table(s).
480
481Arguments: a value that is presumed to be in the table above
482Returns: the option name, or an empty string
483*/
484
485uschar *
486readconf_find_option(void *p)
487{
488int i;
489router_instance *r;
490transport_instance *t;
491
492for (i = 0; i < optionlist_config_size; i++)
493 if (p == optionlist_config[i].value) return US optionlist_config[i].name;
494
495for (r = routers; r != NULL; r = r->next)
496 {
497 router_info *ri = r->info;
c4b738a9 498 for (i = 0; i < *ri->options_count; i++)
059ec3d9
PH
499 {
500 if ((ri->options[i].type & opt_mask) != opt_stringptr) continue;
501 if (p == (char *)(r->options_block) + (long int)(ri->options[i].value))
502 return US ri->options[i].name;
503 }
504 }
505
506for (t = transports; t != NULL; t = t->next)
507 {
508 transport_info *ti = t->info;
c4b738a9 509 for (i = 0; i < *ti->options_count; i++)
059ec3d9 510 {
c4b738a9
JH
511 optionlist * op = &ti->options[i];
512 if ((op->type & opt_mask) != opt_stringptr) continue;
513 if (p == ( op->type & opt_public
514 ? (char *)t
515 : (char *)t->options_block
516 )
517 + (long int)op->value)
518 return US op->name;
059ec3d9
PH
519 }
520 }
521
522return US"";
523}
524
525
526
527
cf00dad6
PH
528/*************************************************
529* Deal with an assignment to a macro *
530*************************************************/
531
532/* This function is called when a line that starts with an upper case letter is
533encountered. The argument "line" should contain a complete logical line, and
534start with the first letter of the macro name. The macro name and the
535replacement text are extracted and stored. Redefinition of existing,
536non-command line, macros is permitted using '==' instead of '='.
537
538Arguments:
539 s points to the start of the logical line
540
541Returns: nothing
542*/
543
544static void
545read_macro_assignment(uschar *s)
546{
547uschar name[64];
548int namelen = 0;
549BOOL redef = FALSE;
550macro_item *m;
551macro_item *mlast = NULL;
552
553while (isalnum(*s) || *s == '_')
554 {
555 if (namelen >= sizeof(name) - 1)
556 log_write(0, LOG_PANIC_DIE|LOG_CONFIG_IN,
ef840681 557 "macro name too long (maximum is " SIZE_T_FMT " characters)", sizeof(name) - 1);
cf00dad6
PH
558 name[namelen++] = *s++;
559 }
560name[namelen] = 0;
561
562while (isspace(*s)) s++;
563if (*s++ != '=')
564 log_write(0, LOG_PANIC_DIE|LOG_CONFIG_IN, "malformed macro definition");
565
566if (*s == '=')
567 {
568 redef = TRUE;
569 s++;
570 }
571while (isspace(*s)) s++;
572
573/* If an existing macro of the same name was defined on the command line, we
574just skip this definition. It's an error to attempt to redefine a macro without
575redef set to TRUE, or to redefine a macro when it hasn't been defined earlier.
576It is also an error to define a macro whose name begins with the name of a
577previously defined macro. Note: it is documented that the other way round
578works. */
579
580for (m = macros; m != NULL; m = m->next)
581 {
582 int len = Ustrlen(m->name);
583
584 if (Ustrcmp(m->name, name) == 0)
585 {
586 if (!m->command_line && !redef)
587 log_write(0, LOG_CONFIG|LOG_PANIC_DIE, "macro \"%s\" is already "
588 "defined (use \"==\" if you want to redefine it", name);
589 break;
590 }
591
592 if (len < namelen && Ustrstr(name, m->name) != NULL)
593 log_write(0, LOG_CONFIG|LOG_PANIC_DIE, "\"%s\" cannot be defined as "
594 "a macro because previously defined macro \"%s\" is a substring",
595 name, m->name);
596
597 /* We cannot have this test, because it is documented that a substring
598 macro is permitted (there is even an example).
599 *
600 * if (len > namelen && Ustrstr(m->name, name) != NULL)
601 * log_write(0, LOG_CONFIG|LOG_PANIC_DIE, "\"%s\" cannot be defined as "
602 * "a macro because it is a substring of previously defined macro \"%s\"",
603 * name, m->name);
604 */
605
606 mlast = m;
607 }
608
609/* Check for an overriding command-line definition. */
610
611if (m != NULL && m->command_line) return;
612
613/* Redefinition must refer to an existing macro. */
614
615if (redef)
616 {
617 if (m == NULL)
618 log_write(0, LOG_CONFIG|LOG_PANIC_DIE, "can't redefine an undefined macro "
619 "\"%s\"", name);
620 }
621
622/* We have a new definition. The macro_item structure includes a final vector
623called "name" which is one byte long. Thus, adding "namelen" gives us enough
624room to store the "name" string. */
625
626else
627 {
628 m = store_get(sizeof(macro_item) + namelen);
629 if (macros == NULL) macros = m; else mlast->next = m;
630 Ustrncpy(m->name, name, namelen);
631 m->name[namelen] = 0;
632 m->next = NULL;
633 m->command_line = FALSE;
634 }
635
636/* Set the value of the new or redefined macro */
637
638m->replacement = string_copy(s);
639}
640
641
642
643
059ec3d9
PH
644
645/*************************************************
646* Read configuration line *
647*************************************************/
648
649/* A logical line of text is read from the configuration file into the big
650buffer, taking account of macros, .includes, and continuations. The size of
651big_buffer is increased if necessary. The count of configuration lines is
652maintained. Physical input lines starting with # (ignoring leading white space,
653and after macro replacement) and empty logical lines are always ignored.
654Leading and trailing spaces are removed.
655
656If we hit a line of the form "begin xxxx", the xxxx is placed in the
657next_section vector, and the function returns NULL, indicating the end of a
658configuration section. On end-of-file, NULL is returned with next_section
659empty.
660
661Arguments: none
662
663Returns: a pointer to the first non-blank in the line,
664 or NULL if eof or end of section is reached
665*/
666
667static uschar *
668get_config_line(void)
669{
670int startoffset = 0; /* To first non-blank char in logical line */
671int len = 0; /* Of logical line so far */
672int newlen;
673uschar *s, *ss;
674macro_item *m;
675BOOL macro_found;
676
677/* Loop for handling continuation lines, skipping comments, and dealing with
678.include files. */
679
680for (;;)
681 {
682 if (Ufgets(big_buffer+len, big_buffer_size-len, config_file) == NULL)
683 {
684 if (config_file_stack != NULL) /* EOF inside .include */
685 {
f1e894f3 686 (void)fclose(config_file);
059ec3d9
PH
687 config_file = config_file_stack->file;
688 config_filename = config_file_stack->filename;
689 config_lineno = config_file_stack->lineno;
690 config_file_stack = config_file_stack->next;
691 continue;
692 }
693
694 /* EOF at top level */
695
696 if (cstate_stack_ptr >= 0)
697 log_write(0, LOG_PANIC_DIE|LOG_CONFIG_IN,
698 "Unexpected end of configuration file: .endif missing");
699
700 if (len != 0) break; /* EOF after continuation */
701 next_section[0] = 0; /* EOF at start of logical line */
702 return NULL;
703 }
704
705 config_lineno++;
706 newlen = len + Ustrlen(big_buffer + len);
707
708 /* Handle pathologically long physical lines - yes, it did happen - by
709 extending big_buffer at this point. The code also copes with very long
710 logical lines. */
711
712 while (newlen == big_buffer_size - 1 && big_buffer[newlen - 1] != '\n')
713 {
714 uschar *newbuffer;
715 big_buffer_size += BIG_BUFFER_SIZE;
716 newbuffer = store_malloc(big_buffer_size);
717
718 /* This use of strcpy is OK because we know that the string in the old
719 buffer is shorter than the new buffer. */
720
721 Ustrcpy(newbuffer, big_buffer);
722 store_free(big_buffer);
723 big_buffer = newbuffer;
724 if (Ufgets(big_buffer+newlen, big_buffer_size-newlen, config_file) == NULL)
725 break;
726 newlen += Ustrlen(big_buffer + newlen);
727 }
728
729 /* Find the true start of the physical line - leading spaces are always
730 ignored. */
731
732 ss = big_buffer + len;
733 while (isspace(*ss)) ss++;
734
735 /* Process the physical line for macros. If this is the start of the logical
736 line, skip over initial text at the start of the line if it starts with an
737 upper case character followed by a sequence of name characters and an equals
738 sign, because that is the definition of a new macro, and we don't do
739 replacement therein. */
740
741 s = ss;
742 if (len == 0 && isupper(*s))
743 {
744 while (isalnum(*s) || *s == '_') s++;
745 while (isspace(*s)) s++;
746 if (*s != '=') s = ss; /* Not a macro definition */
747 }
748
749 /* For each defined macro, scan the line (from after XXX= if present),
750 replacing all occurrences of the macro. */
751
752 macro_found = FALSE;
753 for (m = macros; m != NULL; m = m->next)
754 {
755 uschar *p, *pp;
756 uschar *t = s;
757
758 while ((p = Ustrstr(t, m->name)) != NULL)
759 {
760 int moveby;
761 int namelen = Ustrlen(m->name);
762 int replen = Ustrlen(m->replacement);
763
764 /* Expand the buffer if necessary */
765
766 while (newlen - namelen + replen + 1 > big_buffer_size)
767 {
768 int newsize = big_buffer_size + BIG_BUFFER_SIZE;
769 uschar *newbuffer = store_malloc(newsize);
770 memcpy(newbuffer, big_buffer, newlen + 1);
771 p = newbuffer + (p - big_buffer);
772 s = newbuffer + (s - big_buffer);
773 ss = newbuffer + (ss - big_buffer);
774 t = newbuffer + (t - big_buffer);
775 big_buffer_size = newsize;
776 store_free(big_buffer);
777 big_buffer = newbuffer;
778 }
779
780 /* Shuffle the remaining characters up or down in the buffer before
781 copying in the replacement text. Don't rescan the replacement for this
782 same macro. */
783
784 pp = p + namelen;
785 moveby = replen - namelen;
786 if (moveby != 0)
787 {
788 memmove(p + replen, pp, (big_buffer + newlen) - pp + 1);
789 newlen += moveby;
790 }
791 Ustrncpy(p, m->replacement, replen);
792 t = p + replen;
793 macro_found = TRUE;
794 }
795 }
796
797 /* An empty macro replacement at the start of a line could mean that ss no
798 longer points to the first non-blank character. */
799
800 while (isspace(*ss)) ss++;
801
802 /* Check for comment lines - these are physical lines. */
803
804 if (*ss == '#') continue;
805
806 /* Handle conditionals, which are also applied to physical lines. Conditions
807 are of the form ".ifdef ANYTEXT" and are treated as true if any macro
808 expansion occured on the rest of the line. A preliminary test for the leading
809 '.' saves effort on most lines. */
810
811 if (*ss == '.')
812 {
813 int i;
814
815 /* Search the list of conditional directives */
816
817 for (i = 0; i < cond_list_size; i++)
818 {
819 int n;
820 cond_item *c = cond_list+i;
821 if (Ustrncmp(ss+1, c->name, c->namelen) != 0) continue;
822
823 /* The following character must be white space or end of string */
824
825 n = ss[1 + c->namelen];
826 if (n != ' ' && n != 't' && n != '\n' && n != 0) break;
827
828 /* .ifdef and .ifndef push the current state onto the stack, then set
829 a new one from the table. Stack overflow is an error */
830
831 if (c->pushpop > 0)
832 {
833 if (cstate_stack_ptr >= CSTATE_STACK_SIZE - 1)
834 log_write(0, LOG_PANIC_DIE|LOG_CONFIG_IN,
835 ".%s nested too deeply", c->name);
836 cstate_stack[++cstate_stack_ptr] = cstate;
837 cstate = next_cstate[cstate][macro_found? c->action1 : c->action2];
838 }
839
840 /* For any of the others, stack underflow is an error. The next state
841 comes either from the stack (.endif) or from the table. */
842
843 else
844 {
845 if (cstate_stack_ptr < 0)
846 log_write(0, LOG_PANIC_DIE|LOG_CONFIG_IN,
847 ".%s without matching .ifdef", c->name);
848 cstate = (c->pushpop < 0)? cstate_stack[cstate_stack_ptr--] :
849 next_cstate[cstate][macro_found? c->action1 : c->action2];
850 }
851
852 /* Having dealt with a directive, break the loop */
853
854 break;
855 }
856
857 /* If we have handled a conditional directive, continue with the next
858 physical line. Otherwise, fall through. */
859
860 if (i < cond_list_size) continue;
861 }
862
863 /* If the conditional state is not 0 (actively using these lines), ignore
864 this input line. */
865
866 if (cstate != 0) continue; /* Conditional skip */
867
868 /* Handle .include lines - these are also physical lines. */
869
870 if (Ustrncmp(ss, ".include", 8) == 0 &&
871 (isspace(ss[8]) ||
872 (Ustrncmp(ss+8, "_if_exists", 10) == 0 && isspace(ss[18]))))
873 {
874 uschar *t;
875 int include_if_exists = isspace(ss[8])? 0 : 10;
876 config_file_item *save;
877 struct stat statbuf;
878
879 ss += 9 + include_if_exists;
880 while (isspace(*ss)) ss++;
881 t = ss + Ustrlen(ss);
882 while (t > ss && isspace(t[-1])) t--;
883 if (*ss == '\"' && t[-1] == '\"')
884 {
885 ss++;
886 t--;
887 }
888 *t = 0;
889
145396a6
PH
890 if (*ss != '/')
891 log_write(0, LOG_PANIC_DIE|LOG_CONFIG_IN, ".include specifies a non-"
892 "absolute path \"%s\"", ss);
893
059ec3d9
PH
894 if (include_if_exists != 0 && (Ustat(ss, &statbuf) != 0)) continue;
895
896 save = store_get(sizeof(config_file_item));
897 save->next = config_file_stack;
898 config_file_stack = save;
899 save->file = config_file;
900 save->filename = config_filename;
901 save->lineno = config_lineno;
902
903 config_file = Ufopen(ss, "rb");
904 if (config_file == NULL)
905 log_write(0, LOG_PANIC_DIE|LOG_CONFIG_IN, "failed to open included "
906 "configuration file %s", ss);
907 config_filename = string_copy(ss);
908 config_lineno = 0;
909 continue;
910 }
911
912 /* If this is the start of the logical line, remember where the non-blank
913 data starts. Otherwise shuffle down continuation lines to remove leading
914 white space. */
915
916 if (len == 0)
917 startoffset = ss - big_buffer;
918 else
919 {
920 s = big_buffer + len;
921 if (ss > s)
922 {
923 memmove(s, ss, (newlen - len) - (ss - s) + 1);
924 newlen -= ss - s;
925 }
926 }
927
928 /* Accept the new addition to the line. Remove trailing white space. */
929
930 len = newlen;
931 while (len > 0 && isspace(big_buffer[len-1])) len--;
932 big_buffer[len] = 0;
933
934 /* We are done if the line does not end in backslash and contains some data.
935 Empty logical lines are ignored. For continuations, remove the backslash and
936 go round the loop to read the continuation line. */
937
938 if (len > 0)
939 {
940 if (big_buffer[len-1] != '\\') break; /* End of logical line */
941 big_buffer[--len] = 0; /* Remove backslash */
942 }
943 } /* Loop for reading multiple physical lines */
944
945/* We now have a logical line. Test for the end of a configuration section (or,
946more accurately, for the start of the next section). Place the name of the next
947section in next_section, and return NULL. If the name given is longer than
948next_section, truncate it. It will be unrecognized later, because all the known
949section names do fit. Leave space for pluralizing. */
950
951s = big_buffer + startoffset; /* First non-space character */
952if (strncmpic(s, US"begin ", 6) == 0)
953 {
954 s += 6;
955 while (isspace(*s)) s++;
956 if (big_buffer + len - s > sizeof(next_section) - 2)
957 s[sizeof(next_section) - 2] = 0;
958 Ustrcpy(next_section, s);
959 return NULL;
960 }
961
962/* Return the first non-blank character. */
963
964return s;
965}
966
967
968
969/*************************************************
970* Read a name *
971*************************************************/
972
973/* The yield is the pointer to the next uschar. Names longer than the
974output space are silently truncated. This function is also used from acl.c when
975parsing ACLs.
976
977Arguments:
978 name where to put the name
979 len length of name
980 s input pointer
981
982Returns: new input pointer
983*/
984
985uschar *
986readconf_readname(uschar *name, int len, uschar *s)
987{
988int p = 0;
989while (isspace(*s)) s++;
990if (isalpha(*s))
991 {
992 while (isalnum(*s) || *s == '_')
993 {
994 if (p < len-1) name[p++] = *s;
995 s++;
996 }
997 }
998name[p] = 0;
999while (isspace(*s)) s++;
1000return s;
1001}
1002
1003
1004
1005
1006/*************************************************
1007* Read a time value *
1008*************************************************/
1009
1010/* This function is also called from outside, to read argument
1011time values. The format of a time value is:
1012
1013 [<n>w][<n>d][<n>h][<n>m][<n>s]
1014
1015as long as at least one is present. If a format error is encountered,
1016return a negative value. The value must be terminated by the given
1017terminator.
1018
1019Arguments:
1020 s input pointer
1021 terminator required terminating character
1022 return_msec if TRUE, allow fractional seconds and return milliseconds
1023
1024Returns: the time value, or -1 on syntax error
1025 value is seconds if return_msec is FALSE
1026 value is milliseconds if return_msec is TRUE
1027*/
1028
1029int
1030readconf_readtime(uschar *s, int terminator, BOOL return_msec)
1031{
1032int yield = 0;
1033for (;;)
1034 {
1035 int value, count;
1036 double fraction;
1037
1038 if (!isdigit(*s)) return -1;
1039 (void)sscanf(CS s, "%d%n", &value, &count);
1040 s += count;
1041
1042 switch (*s)
1043 {
1044 case 'w': value *= 7;
1045 case 'd': value *= 24;
1046 case 'h': value *= 60;
1047 case 'm': value *= 60;
1048 case 's': s++;
1049 break;
1050
1051 case '.':
1052 if (!return_msec) return -1;
1053 (void)sscanf(CS s, "%lf%n", &fraction, &count);
1054 s += count;
1055 if (*s++ != 's') return -1;
1056 yield += (int)(fraction * 1000.0);
1057 break;
1058
1059 default: return -1;
1060 }
1061
1062 if (return_msec) value *= 1000;
1063 yield += value;
1064 if (*s == terminator) return yield;
1065 }
1066/* Control never reaches here. */
1067}
1068
1069
1070
1071/*************************************************
1072* Read a fixed point value *
1073*************************************************/
1074
1075/* The value is returned *1000
1076
1077Arguments:
1078 s input pointer
1079 terminator required terminator
1080
1081Returns: the value, or -1 on error
1082*/
1083
1084static int
1085readconf_readfixed(uschar *s, int terminator)
1086{
1087int yield = 0;
1088int value, count;
1089if (!isdigit(*s)) return -1;
1090(void)sscanf(CS s, "%d%n", &value, &count);
1091s += count;
1092yield = value * 1000;
1093if (*s == '.')
1094 {
1095 int m = 100;
1096 while (isdigit((*(++s))))
1097 {
1098 yield += (*s - '0') * m;
1099 m /= 10;
1100 }
1101 }
1102
1103return (*s == terminator)? yield : (-1);
1104}
1105
1106
1107
1108/*************************************************
1109* Find option in list *
1110*************************************************/
1111
1112/* The lists are always in order, so binary chop can be used.
1113
1114Arguments:
1115 name the option name to search for
1116 ol the first entry in the option list
1117 last one more than the offset of the last entry in the option list
1118
1119Returns: pointer to an option entry, or NULL if not found
1120*/
1121
1122static optionlist *
1123find_option(uschar *name, optionlist *ol, int last)
1124{
1125int first = 0;
1126while (last > first)
1127 {
1128 int middle = (first + last)/2;
1129 int c = Ustrcmp(name, ol[middle].name);
1130 if (c == 0) return ol + middle;
1131 else if (c > 0) first = middle + 1;
1132 else last = middle;
1133 }
1134return NULL;
1135}
1136
1137
1138
1139/*************************************************
1140* Find a set flag in option list *
1141*************************************************/
1142
1143/* Because some versions of Unix make no restrictions on the values of uids and
1144gids (even negative ones), we cannot represent "unset" by a special value.
1145There is therefore a separate boolean variable for each one indicating whether
1146a value is set or not. This function returns a pointer to the boolean, given
1147the original option name. It is a major disaster if the flag cannot be found.
1148
1149Arguments:
1150 name the name of the uid or gid option
1151 oltop points to the start of the relevant option list
1152 last one more than the offset of the last item in the option list
1153 data_block NULL when reading main options => data values in the option
1154 list are absolute addresses; otherwise they are byte offsets
1155 in data_block (used for driver options)
1156
1157Returns: a pointer to the boolean flag.
1158*/
1159
1160static BOOL *
1161get_set_flag(uschar *name, optionlist *oltop, int last, void *data_block)
1162{
1163optionlist *ol;
1164uschar name2[64];
1165sprintf(CS name2, "*set_%.50s", name);
1166ol = find_option(name2, oltop, last);
1167if (ol == NULL) log_write(0, LOG_MAIN|LOG_PANIC_DIE,
1168 "Exim internal error: missing set flag for %s", name);
1169return (data_block == NULL)? (BOOL *)(ol->value) :
1170 (BOOL *)((uschar *)data_block + (long int)(ol->value));
1171}
1172
1173
1174
1175
1176/*************************************************
1177* Output extra characters message and die *
1178*************************************************/
1179
1180/* Called when an option line has junk on the end. Sometimes this is because
1181the sysadmin thinks comments are permitted.
1182
1183Arguments:
1184 s points to the extra characters
1185 t1..t3 strings to insert in the log message
1186
1187Returns: doesn't return; dies
1188*/
1189
1190static void
1191extra_chars_error(uschar *s, uschar *t1, uschar *t2, uschar *t3)
1192{
1193uschar *comment = US"";
1194if (*s == '#') comment = US" (# is comment only at line start)";
1195log_write(0, LOG_PANIC_DIE|LOG_CONFIG_IN,
1196 "extra characters follow %s%s%s%s", t1, t2, t3, comment);
1197}
1198
1199
1200
1201/*************************************************
1202* Read rewrite information *
1203*************************************************/
1204
1205/* Each line of rewrite information contains:
1206
1207. A complete address in the form user@domain, possibly with
1208 leading * for each part; or alternatively, a regex.
1209
1210. A replacement string (which will be expanded).
1211
1212. An optional sequence of one-letter flags, indicating which
1213 headers etc. to apply this rule to.
1214
1215All this is decoded and placed into a control block. The OR of the flags is
1216maintained in a common word.
1217
1218Arguments:
1219 p points to the string that makes up the rule
1220 existflags points to the overall flag word
1221 isglobal TRUE if reading global rewrite rules
1222
1223Returns: the control block for the parsed rule.
1224*/
1225
1226static rewrite_rule *
1227readconf_one_rewrite(uschar *p, int *existflags, BOOL isglobal)
1228{
1229rewrite_rule *next = store_get(sizeof(rewrite_rule));
1230
1231next->next = NULL;
1232next->key = string_dequote(&p);
1233
1234while (isspace(*p)) p++;
1235if (*p == 0)
1236 log_write(0, LOG_PANIC_DIE|LOG_CONFIG_IN,
1237 "missing rewrite replacement string");
1238
1239next->flags = 0;
1240next->replacement = string_dequote(&p);
1241
1242while (*p != 0) switch (*p++)
1243 {
1244 case ' ': case '\t': break;
1245
1246 case 'q': next->flags |= rewrite_quit; break;
1247 case 'w': next->flags |= rewrite_whole; break;
1248
1249 case 'h': next->flags |= rewrite_all_headers; break;
1250 case 's': next->flags |= rewrite_sender; break;
1251 case 'f': next->flags |= rewrite_from; break;
1252 case 't': next->flags |= rewrite_to; break;
1253 case 'c': next->flags |= rewrite_cc; break;
1254 case 'b': next->flags |= rewrite_bcc; break;
1255 case 'r': next->flags |= rewrite_replyto; break;
1256
1257 case 'E': next->flags |= rewrite_all_envelope; break;
1258 case 'F': next->flags |= rewrite_envfrom; break;
1259 case 'T': next->flags |= rewrite_envto; break;
1260
1261 case 'Q': next->flags |= rewrite_qualify; break;
1262 case 'R': next->flags |= rewrite_repeat; break;
1263
1264 case 'S':
1265 next->flags |= rewrite_smtp;
1266 if (next->key[0] != '^' && Ustrncmp(next->key, "\\N^", 3) != 0)
1267 log_write(0, LOG_PANIC_DIE|LOG_CONFIG_IN,
1268 "rewrite rule has the S flag but is not a regular expression");
1269 break;
1270
1271 default:
1272 log_write(0, LOG_PANIC_DIE|LOG_CONFIG_IN,
1273 "unknown rewrite flag character '%c' "
1274 "(could be missing quotes round replacement item)", p[-1]);
1275 break;
1276 }
1277
1278/* If no action flags are set, set all the "normal" rewrites. */
1279
1280if ((next->flags & (rewrite_all | rewrite_smtp)) == 0)
1281 next->flags |= isglobal? rewrite_all : rewrite_all_headers;
1282
1283/* Remember which exist, for optimization, and return the rule */
1284
1285*existflags |= next->flags;
1286return next;
1287}
1288
1289
1290
1291
1292/*************************************************
1293* Read global rewrite information *
1294*************************************************/
1295
1296/* Each line is a single rewrite rule; it is parsed into a control block
1297by readconf_one_rewrite(), and its flags are ORed into the global flag
1298word rewrite_existflags. */
1299
1300void
1301readconf_rewrites(void)
1302{
1303rewrite_rule **chain = &global_rewrite_rules;
1304uschar *p;
1305
1306while ((p = get_config_line()) != NULL)
1307 {
1308 rewrite_rule *next = readconf_one_rewrite(p, &rewrite_existflags, TRUE);
1309 *chain = next;
1310 chain = &(next->next);
1311 }
1312}
1313
1314
1315
1316/*************************************************
1317* Read a string *
1318*************************************************/
1319
1320/* Strings are read into the normal store pool. As long we aren't too
1321near the end of the current block, the string will just use what is necessary
1322on the top of the stacking pool, because string_cat() uses the extension
1323mechanism.
1324
1325Argument:
1326 s the rest of the input line
1327 name the option name (for errors)
1328
1329Returns: pointer to the string
1330*/
1331
1332static uschar *
1333read_string(uschar *s, uschar *name)
1334{
1335uschar *yield;
1336uschar *ss;
1337
1338if (*s != '\"') return string_copy(s);
1339
1340ss = s;
1341yield = string_dequote(&s);
1342
1343if (s == ss+1 || s[-1] != '\"')
1344 log_write(0, LOG_PANIC_DIE|LOG_CONFIG_IN,
1345 "missing quote at end of string value for %s", name);
1346
1347if (*s != 0) extra_chars_error(s, US"string value for ", name, US"");
1348
1349return yield;
1350}
1351
1352
1353/*************************************************
1354* Handle option line *
1355*************************************************/
1356
1357/* This function is called from several places to process a line containing the
1358setting of an option. The first argument is the line to be decoded; it has been
1359checked not to be empty and not to start with '#'. Trailing newlines and white
1360space have been removed. The second argument is a pointer to the list of
1361variable names that are to be recognized, together with their types and
1362locations, and the third argument gives the number of entries in the list.
1363
1364The fourth argument is a pointer to a data block. If it is NULL, then the data
1365values in the options list are absolute addresses. Otherwise, they are byte
1366offsets in the data block.
1367
1368String option data may continue onto several lines; this function reads further
1369data from config_file if necessary.
1370
1371The yield of this function is normally zero. If a string continues onto
1372multiple lines, then the data value is permitted to be followed by a comma
1373or a semicolon (for use in drivers) and the yield is that character.
1374
1375Arguments:
1376 buffer contains the configuration line to be handled
1377 oltop points to the start of the relevant option list
1378 last one more than the offset of the last item in the option list
1379 data_block NULL when reading main options => data values in the option
1380 list are absolute addresses; otherwise they are byte offsets
1381 in data_block when they have opt_public set; otherwise
1382 they are byte offsets in data_block->options_block.
1383 unknown_txt format string to use in panic message for unknown option;
1384 must contain %s for option name
1385 if given as NULL, don't panic on unknown option
1386
1387Returns: TRUE if an option was read successfully,
1388 FALSE false for an unknown option if unknown_txt == NULL,
1389 otherwise panic and die on an unknown option
1390*/
1391
1392static BOOL
1393readconf_handle_option(uschar *buffer, optionlist *oltop, int last,
1394 void *data_block, uschar *unknown_txt)
1395{
1396int ptr = 0;
1397int offset = 0;
1398int n, count, type, value;
1399int issecure = 0;
1400uid_t uid;
1401gid_t gid;
1402BOOL boolvalue = TRUE;
1403BOOL freesptr = TRUE;
1404optionlist *ol, *ol2;
1405struct passwd *pw;
1406void *reset_point;
1407int intbase = 0;
1408uschar *inttype = US"";
1409uschar *sptr;
1410uschar *s = buffer;
532be449
PP
1411uschar *saved_condition, *strtemp;
1412uschar **str_target;
059ec3d9
PH
1413uschar name[64];
1414uschar name2[64];
1415
1416/* There may be leading spaces; thereafter, we expect an option name starting
1417with a letter. */
1418
1419while (isspace(*s)) s++;
1420if (!isalpha(*s))
1421 log_write(0, LOG_PANIC_DIE|LOG_CONFIG_IN, "option setting expected: %s", s);
1422
1423/* Read the name of the option, and skip any subsequent white space. If
1424it turns out that what we read was "hide", set the flag indicating that
1425this is a secure option, and loop to read the next word. */
1426
1427for (n = 0; n < 2; n++)
1428 {
1429 while (isalnum(*s) || *s == '_')
1430 {
1431 if (ptr < sizeof(name)-1) name[ptr++] = *s;
1432 s++;
1433 }
1434 name[ptr] = 0;
1435 while (isspace(*s)) s++;
1436 if (Ustrcmp(name, "hide") != 0) break;
1437 issecure = opt_secure;
1438 ptr = 0;
1439 }
1440
1441/* Deal with "no_" or "not_" here for booleans */
1442
1443if (Ustrncmp(name, "no_", 3) == 0)
1444 {
1445 boolvalue = FALSE;
1446 offset = 3;
1447 }
1448
1449if (Ustrncmp(name, "not_", 4) == 0)
1450 {
1451 boolvalue = FALSE;
1452 offset = 4;
1453 }
1454
1455/* Search the list for the given name. A non-existent name, or an option that
1456is set twice, is a disaster. */
1457
1458ol = find_option(name + offset, oltop, last);
1459
1460if (ol == NULL)
1461 {
1462 if (unknown_txt == NULL) return FALSE;
1463 log_write(0, LOG_PANIC_DIE|LOG_CONFIG_IN, CS unknown_txt, name);
1464 }
1465
846726c5
JH
1466if ((ol->type & opt_set) && !(ol->type & (opt_rep_con | opt_rep_str)))
1467 log_write(0, LOG_PANIC_DIE|LOG_CONFIG_IN,
1468 "\"%s\" option set for the second time", name);
059ec3d9
PH
1469
1470ol->type |= opt_set | issecure;
1471type = ol->type & opt_mask;
1472
1473/* Types with data values must be followed by '='; the "no[t]_" prefix
1474applies only to boolean values. */
1475
1476if (type < opt_bool || type > opt_bool_last)
1477 {
1478 if (offset != 0)
1479 log_write(0, LOG_PANIC_DIE|LOG_CONFIG_IN,
1480 "negation prefix applied to a non-boolean option");
1481 if (*s == 0)
1482 log_write(0, LOG_PANIC_DIE|LOG_CONFIG_IN,
1483 "unexpected end of line (data missing) after %s", name);
1484 if (*s != '=')
1485 log_write(0, LOG_PANIC_DIE|LOG_CONFIG_IN, "missing \"=\" after %s", name);
1486 }
1487
1488/* If a boolean wasn't preceded by "no[t]_" it can be followed by = and
9c695f6d 1489true/false/yes/no, or, in the case of opt_expand_bool, a general string that
059ec3d9
PH
1490ultimately expands to one of those values. */
1491
1492else if (*s != 0 && (offset != 0 || *s != '='))
1493 extra_chars_error(s, US"boolean option ", name, US"");
1494
1495/* Skip white space after = */
1496
1497if (*s == '=') while (isspace((*(++s))));
1498
1499/* If there is a data block and the opt_public flag is not set, change
1500the data block pointer to the private options block. */
1501
1502if (data_block != NULL && (ol->type & opt_public) == 0)
1503 data_block = (void *)(((driver_instance *)data_block)->options_block);
1504
1505/* Now get the data according to the type. */
1506
1507switch (type)
1508 {
1509 /* If a string value is not enclosed in quotes, it consists of
1510 the rest of the current line, verbatim. Otherwise, string escapes
1511 are processed.
1512
1513 A transport is specified as a string, which is then looked up in the
1514 list of transports. A search type is specified as one of a number of
1515 known strings.
1516
1517 A set or rewrite rules for a driver is specified as a string, which is
1518 then parsed into a suitable chain of control blocks.
1519
1520 Uids and gids are specified as strings which are then looked up in the
1521 passwd file. Lists of uids and gids are similarly specified as colon-
1522 separated strings. */
1523
1524 case opt_stringptr:
1525 case opt_uid:
1526 case opt_gid:
1527 case opt_expand_uid:
1528 case opt_expand_gid:
1529 case opt_uidlist:
1530 case opt_gidlist:
1531 case opt_rewrite:
1532
1533 reset_point = sptr = read_string(s, name);
1534
1535 /* Having read a string, we now have several different ways of using it,
1536 depending on the data type, so do another switch. If keeping the actual
1537 string is not required (because it is interpreted), freesptr is set TRUE,
1538 and at the end we reset the pool. */
1539
1540 switch (type)
1541 {
1542 /* If this was a string, set the variable to point to the new string,
1543 and set the flag so its store isn't reclaimed. If it was a list of rewrite
1544 rules, we still keep the string (for printing), and parse the rules into a
1545 control block and flags word. */
1546
1547 case opt_stringptr:
532be449
PP
1548 if (data_block == NULL)
1549 str_target = (uschar **)(ol->value);
1550 else
1551 str_target = (uschar **)((uschar *)data_block + (long int)(ol->value));
846726c5 1552 if (ol->type & opt_rep_con)
532be449 1553 {
6a8de854
PP
1554 /* We already have a condition, we're conducting a crude hack to let
1555 multiple condition rules be chained together, despite storing them in
1556 text form. */
532be449 1557 saved_condition = *str_target;
6a8de854 1558 strtemp = string_sprintf("${if and{{bool_lax{%s}}{bool_lax{%s}}}}",
532be449
PP
1559 saved_condition, sptr);
1560 *str_target = string_copy_malloc(strtemp);
846726c5
JH
1561 /* TODO(pdp): there is a memory leak here and just below
1562 when we set 3 or more conditions; I still don't
1563 understand the store mechanism enough to know
1564 what's the safe way to free content from an earlier store.
6a8de854
PP
1565 AFAICT, stores stack, so freeing an early stored item also stores
1566 all data alloc'd after it. If we knew conditions were adjacent,
1567 we could survive that, but we don't. So I *think* we need to take
1568 another bit from opt_type to indicate "malloced"; this seems like
1569 quite a hack, especially for this one case. It also means that
1570 we can't ever reclaim the store from the *first* condition.
1571
1572 Because we only do this once, near process start-up, I'm prepared to
1573 let this slide for the time being, even though it rankles. */
532be449 1574 }
76146973
JH
1575 else if (ol->type & opt_rep_str)
1576 {
846726c5 1577 uschar sep = Ustrncmp(name, "headers_add", 11)==0 ? '\n' : ':';
76146973
JH
1578 uschar * cp;
1579
1580 /* Strip trailing whitespace and seperators */
1581 for (cp = sptr + Ustrlen(sptr) - 1;
1582 cp >= sptr && (*cp == '\n' || *cp == '\t' || *cp == ' ' || *cp == sep);
1583 cp--) *cp = '\0';
1584
1585 if (cp >= sptr)
1586 *str_target = string_copy_malloc(
1587 *str_target ? string_sprintf("%s%c%s", *str_target, sep, sptr)
1588 : sptr);
1589 }
532be449
PP
1590 else
1591 {
1592 *str_target = sptr;
1593 freesptr = FALSE;
1594 }
1595 break;
1596
059ec3d9
PH
1597 case opt_rewrite:
1598 if (data_block == NULL)
1599 *((uschar **)(ol->value)) = sptr;
1600 else
1601 *((uschar **)((uschar *)data_block + (long int)(ol->value))) = sptr;
1602 freesptr = FALSE;
1603 if (type == opt_rewrite)
1604 {
1605 int sep = 0;
1606 int *flagptr;
1607 uschar *p = sptr;
1608 rewrite_rule **chain;
1609 optionlist *ol3;
1610
1611 sprintf(CS name2, "*%.50s_rules", name);
1612 ol2 = find_option(name2, oltop, last);
1613 sprintf(CS name2, "*%.50s_flags", name);
1614 ol3 = find_option(name2, oltop, last);
1615
1616 if (ol2 == NULL || ol3 == NULL)
1617 log_write(0, LOG_PANIC_DIE|LOG_CONFIG_IN,
1618 "rewrite rules not available for driver");
1619
1620 if (data_block == NULL)
1621 {
1622 chain = (rewrite_rule **)(ol2->value);
1623 flagptr = (int *)(ol3->value);
1624 }
1625 else
1626 {
1627 chain = (rewrite_rule **)((uschar *)data_block + (long int)(ol2->value));
1628 flagptr = (int *)((uschar *)data_block + (long int)(ol3->value));
1629 }
1630
1631 while ((p = string_nextinlist(&sptr, &sep, big_buffer, BIG_BUFFER_SIZE))
1632 != NULL)
1633 {
1634 rewrite_rule *next = readconf_one_rewrite(p, flagptr, FALSE);
1635 *chain = next;
1636 chain = &(next->next);
1637 }
1638
1639 if ((*flagptr & (rewrite_all_envelope | rewrite_smtp)) != 0)
1640 log_write(0, LOG_PANIC_DIE|LOG_CONFIG_IN, "rewrite rule specifies a "
1641 "non-header rewrite - not allowed at transport time -");
1642 }
1643 break;
1644
1645 /* If it was an expanded uid, see if there is any expansion to be
1646 done by checking for the presence of a $ character. If there is, save it
1647 in the corresponding *expand_user option field. Otherwise, fall through
1648 to treat it as a fixed uid. Ensure mutual exclusivity of the two kinds
1649 of data. */
1650
1651 case opt_expand_uid:
1652 sprintf(CS name2, "*expand_%.50s", name);
1653 ol2 = find_option(name2, oltop, last);
1654 if (ol2 != NULL)
1655 {
1656 uschar *ss = (Ustrchr(sptr, '$') != NULL)? sptr : NULL;
1657
1658 if (data_block == NULL)
1659 *((uschar **)(ol2->value)) = ss;
1660 else
1661 *((uschar **)((uschar *)data_block + (long int)(ol2->value))) = ss;
1662
1663 if (ss != NULL)
1664 {
1665 *(get_set_flag(name, oltop, last, data_block)) = FALSE;
1666 freesptr = FALSE;
1667 break;
1668 }
1669 }
1670
1671 /* Look up a fixed uid, and also make use of the corresponding gid
1672 if a passwd entry is returned and the gid has not been set. */
1673
1674 case opt_uid:
1675 if (!route_finduser(sptr, &pw, &uid))
1676 log_write(0, LOG_PANIC_DIE|LOG_CONFIG_IN, "user %s was not found", sptr);
1677 if (data_block == NULL)
1678 *((uid_t *)(ol->value)) = uid;
1679 else
1680 *((uid_t *)((uschar *)data_block + (long int)(ol->value))) = uid;
1681
1682 /* Set the flag indicating a fixed value is set */
1683
1684 *(get_set_flag(name, oltop, last, data_block)) = TRUE;
1685
1686 /* Handle matching gid if we have a passwd entry: done by finding the
1687 same name with terminating "user" changed to "group"; if not found,
1688 ignore. Also ignore if the value is already set. */
1689
1690 if (pw == NULL) break;
1691 Ustrcpy(name+Ustrlen(name)-4, "group");
1692 ol2 = find_option(name, oltop, last);
1693 if (ol2 != NULL && ((ol2->type & opt_mask) == opt_gid ||
1694 (ol2->type & opt_mask) == opt_expand_gid))
1695 {
1696 BOOL *set_flag = get_set_flag(name, oltop, last, data_block);
1697 if (! *set_flag)
1698 {
1699 if (data_block == NULL)
1700 *((gid_t *)(ol2->value)) = pw->pw_gid;
1701 else
1702 *((gid_t *)((uschar *)data_block + (long int)(ol2->value))) = pw->pw_gid;
1703 *set_flag = TRUE;
1704 }
1705 }
1706 break;
1707
1708 /* If it was an expanded gid, see if there is any expansion to be
1709 done by checking for the presence of a $ character. If there is, save it
1710 in the corresponding *expand_user option field. Otherwise, fall through
1711 to treat it as a fixed gid. Ensure mutual exclusivity of the two kinds
1712 of data. */
1713
1714 case opt_expand_gid:
1715 sprintf(CS name2, "*expand_%.50s", name);
1716 ol2 = find_option(name2, oltop, last);
1717 if (ol2 != NULL)
1718 {
1719 uschar *ss = (Ustrchr(sptr, '$') != NULL)? sptr : NULL;
1720
1721 if (data_block == NULL)
1722 *((uschar **)(ol2->value)) = ss;
1723 else
1724 *((uschar **)((uschar *)data_block + (long int)(ol2->value))) = ss;
1725
1726 if (ss != NULL)
1727 {
1728 *(get_set_flag(name, oltop, last, data_block)) = FALSE;
1729 freesptr = FALSE;
1730 break;
1731 }
1732 }
1733
1734 /* Handle freestanding gid */
1735
1736 case opt_gid:
1737 if (!route_findgroup(sptr, &gid))
1738 log_write(0, LOG_PANIC_DIE|LOG_CONFIG_IN, "group %s was not found", sptr);
1739 if (data_block == NULL)
1740 *((gid_t *)(ol->value)) = gid;
1741 else
1742 *((gid_t *)((uschar *)data_block + (long int)(ol->value))) = gid;
1743 *(get_set_flag(name, oltop, last, data_block)) = TRUE;
1744 break;
1745
1746 /* If it was a uid list, look up each individual entry, and build
1747 a vector of uids, with a count in the first element. Put the vector
1748 in malloc store so we can free the string. (We are reading into
1749 permanent store already.) */
1750
1751 case opt_uidlist:
1752 {
1753 int count = 1;
1754 uid_t *list;
1755 int ptr = 0;
0925ede6
PH
1756 uschar *p;
1757 uschar *op = expand_string (sptr);
1758
1759 if (op == NULL)
1760 log_write(0, LOG_PANIC_DIE|LOG_CONFIG_IN, "failed to expand %s: %s",
1761 name, expand_string_message);
059ec3d9 1762
0925ede6 1763 p = op;
059ec3d9 1764 if (*p != 0) count++;
0925ede6 1765 while (*p != 0) if (*p++ == ':' && *p != 0) count++;
059ec3d9
PH
1766 list = store_malloc(count*sizeof(uid_t));
1767 list[ptr++] = (uid_t)(count - 1);
1768
1769 if (data_block == NULL)
1770 *((uid_t **)(ol->value)) = list;
1771 else
1772 *((uid_t **)((uschar *)data_block + (long int)(ol->value))) = list;
1773
0925ede6 1774 p = op;
059ec3d9
PH
1775 while (count-- > 1)
1776 {
1777 int sep = 0;
1778 (void)string_nextinlist(&p, &sep, big_buffer, BIG_BUFFER_SIZE);
1779 if (!route_finduser(big_buffer, NULL, &uid))
1780 log_write(0, LOG_PANIC_DIE|LOG_CONFIG_IN, "user %s was not found",
1781 big_buffer);
1782 list[ptr++] = uid;
1783 }
1784 }
1785 break;
1786
1787 /* If it was a gid list, look up each individual entry, and build
1788 a vector of gids, with a count in the first element. Put the vector
1789 in malloc store so we can free the string. (We are reading into permanent
1790 store already.) */
1791
1792 case opt_gidlist:
1793 {
1794 int count = 1;
1795 gid_t *list;
1796 int ptr = 0;
0925ede6
PH
1797 uschar *p;
1798 uschar *op = expand_string (sptr);
1799
1800 if (op == NULL)
1801 log_write(0, LOG_PANIC_DIE|LOG_CONFIG_IN, "failed to expand %s: %s",
1802 name, expand_string_message);
059ec3d9 1803
0925ede6 1804 p = op;
059ec3d9 1805 if (*p != 0) count++;
0925ede6 1806 while (*p != 0) if (*p++ == ':' && *p != 0) count++;
059ec3d9
PH
1807 list = store_malloc(count*sizeof(gid_t));
1808 list[ptr++] = (gid_t)(count - 1);
1809
1810 if (data_block == NULL)
1811 *((gid_t **)(ol->value)) = list;
1812 else
1813 *((gid_t **)((uschar *)data_block + (long int)(ol->value))) = list;
1814
0925ede6 1815 p = op;
059ec3d9
PH
1816 while (count-- > 1)
1817 {
1818 int sep = 0;
1819 (void)string_nextinlist(&p, &sep, big_buffer, BIG_BUFFER_SIZE);
1820 if (!route_findgroup(big_buffer, &gid))
1821 log_write(0, LOG_PANIC_DIE|LOG_CONFIG_IN, "group %s was not found",
1822 big_buffer);
1823 list[ptr++] = gid;
1824 }
1825 }
1826 break;
1827 }
1828
1829 /* Release store if the value of the string doesn't need to be kept. */
1830
1831 if (freesptr) store_reset(reset_point);
1832 break;
1833
1834 /* Expanded boolean: if no characters follow, or if there are no dollar
1835 characters, this is a fixed-valued boolean, and we fall through. Otherwise,
1836 save the string for later expansion in the alternate place. */
1837
1838 case opt_expand_bool:
1839 if (*s != 0 && Ustrchr(s, '$') != 0)
1840 {
1841 sprintf(CS name2, "*expand_%.50s", name);
1842 ol2 = find_option(name2, oltop, last);
1843 if (ol2 != NULL)
1844 {
1845 reset_point = sptr = read_string(s, name);
1846 if (data_block == NULL)
1847 *((uschar **)(ol2->value)) = sptr;
1848 else
1849 *((uschar **)((uschar *)data_block + (long int)(ol2->value))) = sptr;
1850 freesptr = FALSE;
1851 break;
1852 }
1853 }
1854 /* Fall through */
1855
1856 /* Boolean: if no characters follow, the value is boolvalue. Otherwise
1857 look for yes/not/true/false. Some booleans are stored in a single bit in
1858 a single int. There's a special fudge for verify settings; without a suffix
1859 they set both xx_sender and xx_recipient. The table points to the sender
1860 value; search subsequently for the recipient. There's another special case:
1861 opt_bool_set also notes when a boolean has been set. */
1862
1863 case opt_bool:
1864 case opt_bit:
1865 case opt_bool_verify:
1866 case opt_bool_set:
1867 if (*s != 0)
1868 {
1869 s = readconf_readname(name2, 64, s);
1870 if (strcmpic(name2, US"true") == 0 || strcmpic(name2, US"yes") == 0)
1871 boolvalue = TRUE;
1872 else if (strcmpic(name2, US"false") == 0 || strcmpic(name2, US"no") == 0)
1873 boolvalue = FALSE;
1874 else log_write(0, LOG_PANIC_DIE|LOG_CONFIG_IN,
1875 "\"%s\" is not a valid value for the \"%s\" option", name2, name);
1876 if (*s != 0) extra_chars_error(s, string_sprintf("\"%s\" ", name2),
1877 US"for boolean option ", name);
1878 }
1879
1880 /* Handle single-bit type. */
1881
1882 if (type == opt_bit)
1883 {
1884 int bit = 1 << ((ol->type >> 16) & 31);
1885 int *ptr = (data_block == NULL)?
1886 (int *)(ol->value) :
1887 (int *)((uschar *)data_block + (long int)ol->value);
1888 if (boolvalue) *ptr |= bit; else *ptr &= ~bit;
1889 break;
1890 }
1891
1892 /* Handle full BOOL types */
1893
1894 if (data_block == NULL)
1895 *((BOOL *)(ol->value)) = boolvalue;
1896 else
1897 *((BOOL *)((uschar *)data_block + (long int)(ol->value))) = boolvalue;
1898
1899 /* Verify fudge */
1900
1901 if (type == opt_bool_verify)
1902 {
1903 sprintf(CS name2, "%.50s_recipient", name + offset);
1904 ol2 = find_option(name2, oltop, last);
1905 if (ol2 != NULL)
1906 {
1907 if (data_block == NULL)
1908 *((BOOL *)(ol2->value)) = boolvalue;
1909 else
1910 *((BOOL *)((uschar *)data_block + (long int)(ol2->value))) = boolvalue;
1911 }
1912 }
1913
1914 /* Note that opt_bool_set type is set, if there is somewhere to do so */
1915
1916 else if (type == opt_bool_set)
1917 {
1918 sprintf(CS name2, "*set_%.50s", name + offset);
1919 ol2 = find_option(name2, oltop, last);
1920 if (ol2 != NULL)
1921 {
1922 if (data_block == NULL)
1923 *((BOOL *)(ol2->value)) = TRUE;
1924 else
1925 *((BOOL *)((uschar *)data_block + (long int)(ol2->value))) = TRUE;
1926 }
1927 }
1928 break;
1929
1930 /* Octal integer */
1931
1932 case opt_octint:
1933 intbase = 8;
1934 inttype = US"octal ";
1935
1936 /* Integer: a simple(ish) case; allow octal and hex formats, and
1937 suffixes K and M. The different types affect output, not input. */
1938
1939 case opt_mkint:
1940 case opt_int:
1941 {
1942 uschar *endptr;
7e8d92ba
PH
1943 long int lvalue;
1944
059ec3d9 1945 errno = 0;
7e8d92ba 1946 lvalue = strtol(CS s, CSS &endptr, intbase);
059ec3d9
PH
1947
1948 if (endptr == s)
1949 log_write(0, LOG_PANIC_DIE|LOG_CONFIG_IN, "%sinteger expected for %s",
1950 inttype, name);
1951
1952 if (errno != ERANGE)
1953 {
1954 if (tolower(*endptr) == 'k')
1955 {
7e8d92ba
PH
1956 if (lvalue > INT_MAX/1024 || lvalue < INT_MIN/1024) errno = ERANGE;
1957 else lvalue *= 1024;
059ec3d9
PH
1958 endptr++;
1959 }
1960 else if (tolower(*endptr) == 'm')
1961 {
7e8d92ba 1962 if (lvalue > INT_MAX/(1024*1024) || lvalue < INT_MIN/(1024*1024))
059ec3d9 1963 errno = ERANGE;
7e8d92ba 1964 else lvalue *= 1024*1024;
059ec3d9
PH
1965 endptr++;
1966 }
1967 }
1968
7e8d92ba
PH
1969 if (errno == ERANGE || lvalue > INT_MAX || lvalue < INT_MIN)
1970 log_write(0, LOG_PANIC_DIE|LOG_CONFIG_IN,
1971 "absolute value of integer \"%s\" is too large (overflow)", s);
059ec3d9
PH
1972
1973 while (isspace(*endptr)) endptr++;
1974 if (*endptr != 0)
1975 extra_chars_error(endptr, inttype, US"integer value for ", name);
7e8d92ba
PH
1976
1977 value = (int)lvalue;
059ec3d9
PH
1978 }
1979
1980 if (data_block == NULL)
1981 *((int *)(ol->value)) = value;
1982 else
1983 *((int *)((uschar *)data_block + (long int)(ol->value))) = value;
1984 break;
1985
1986 /* Integer held in K: again, allow octal and hex formats, and suffixes K and
1987 M. */
1988
1989 case opt_Kint:
1990 {
1991 uschar *endptr;
1992 errno = 0;
1993 value = strtol(CS s, CSS &endptr, intbase);
1994
1995 if (endptr == s)
1996 log_write(0, LOG_PANIC_DIE|LOG_CONFIG_IN, "%sinteger expected for %s",
1997 inttype, name);
1998
1999 if (errno != ERANGE)
2000 {
2001 if (tolower(*endptr) == 'm')
2002 {
2003 if (value > INT_MAX/1024 || value < INT_MIN/1024) errno = ERANGE;
2004 else value *= 1024;
2005 endptr++;
2006 }
2007 else if (tolower(*endptr) == 'k')
2008 {
2009 endptr++;
2010 }
2011 else
2012 {
2013 value = (value + 512)/1024;
2014 }
2015 }
2016
2017 if (errno == ERANGE) log_write(0, LOG_PANIC_DIE|LOG_CONFIG_IN,
2018 "absolute value of integer \"%s\" is too large (overflow)", s);
2019
2020 while (isspace(*endptr)) endptr++;
2021 if (*endptr != 0)
2022 extra_chars_error(endptr, inttype, US"integer value for ", name);
2023 }
2024
2025 if (data_block == NULL)
2026 *((int *)(ol->value)) = value;
2027 else
2028 *((int *)((uschar *)data_block + (long int)(ol->value))) = value;
2029 break;
2030
2031 /* Fixed-point number: held to 3 decimal places. */
2032
2033 case opt_fixed:
2034 if (sscanf(CS s, "%d%n", &value, &count) != 1)
2035 log_write(0, LOG_PANIC_DIE|LOG_CONFIG_IN,
2036 "fixed-point number expected for %s", name);
2037
2038 if (value < 0) log_write(0, LOG_PANIC_DIE|LOG_CONFIG_IN,
2039 "integer \"%s\" is too large (overflow)", s);
2040
2041 value *= 1000;
2042
2043 if (value < 0) log_write(0, LOG_PANIC_DIE|LOG_CONFIG_IN,
2044 "integer \"%s\" is too large (overflow)", s);
2045
2046 if (s[count] == '.')
2047 {
2048 int d = 100;
2049 while (isdigit(s[++count]))
2050 {
2051 value += (s[count] - '0') * d;
2052 d /= 10;
2053 }
2054 }
2055
2056 while (isspace(s[count])) count++;
2057
2058 if (s[count] != 0)
2059 extra_chars_error(s+count, US"fixed-point value for ", name, US"");
2060
2061 if (data_block == NULL)
2062 *((int *)(ol->value)) = value;
2063 else
2064 *((int *)((uschar *)data_block + (long int)(ol->value))) = value;
2065 break;
2066
2067 /* There's a special routine to read time values. */
2068
2069 case opt_time:
2070 value = readconf_readtime(s, 0, FALSE);
2071 if (value < 0)
2072 log_write(0, LOG_PANIC_DIE|LOG_CONFIG_IN, "invalid time value for %s",
2073 name);
2074 if (data_block == NULL)
2075 *((int *)(ol->value)) = value;
2076 else
2077 *((int *)((uschar *)data_block + (long int)(ol->value))) = value;
2078 break;
2079
2080 /* A time list is a list of colon-separated times, with the first
2081 element holding the size of the list and the second the number of
2082 entries used. */
2083
2084 case opt_timelist:
2085 {
2086 int count = 0;
2087 int *list = (data_block == NULL)?
2088 (int *)(ol->value) :
2089 (int *)((uschar *)data_block + (long int)(ol->value));
2090
2091 if (*s != 0) for (count = 1; count <= list[0] - 2; count++)
2092 {
2093 int terminator = 0;
2094 uschar *snext = Ustrchr(s, ':');
2095 if (snext != NULL)
2096 {
2097 uschar *ss = snext;
2098 while (ss > s && isspace(ss[-1])) ss--;
2099 terminator = *ss;
2100 }
2101 value = readconf_readtime(s, terminator, FALSE);
2102 if (value < 0)
2103 log_write(0, LOG_PANIC_DIE|LOG_CONFIG_IN, "invalid time value for %s",
2104 name);
2105 if (count > 1 && value <= list[count])
2106 log_write(0, LOG_PANIC_DIE|LOG_CONFIG_IN,
2107 "time value out of order for %s", name);
2108 list[count+1] = value;
2109 if (snext == NULL) break;
2110 s = snext + 1;
2111 while (isspace(*s)) s++;
2112 }
2113
2114 if (count > list[0] - 2)
2115 log_write(0, LOG_PANIC_DIE|LOG_CONFIG_IN, "too many time values for %s",
2116 name);
2117 if (count > 0 && list[2] == 0) count = 0;
2118 list[1] = count;
2119 }
2120
2121 break;
2122 }
2123
2124return TRUE;
2125}
2126
2127
2128
2129/*************************************************
2130* Print a time value *
2131*************************************************/
2132
2133/*
2134Argument: a time value in seconds
2135Returns: pointer to a fixed buffer containing the time as a string,
2136 in readconf_readtime() format
2137*/
2138
2139uschar *
2140readconf_printtime(int t)
2141{
2142int s, m, h, d, w;
2143uschar *p = time_buffer;
2144
ea49d0e1
PH
2145if (t < 0)
2146 {
2147 *p++ = '-';
2148 t = -t;
2149 }
2150
059ec3d9
PH
2151s = t % 60;
2152t /= 60;
2153m = t % 60;
2154t /= 60;
2155h = t % 24;
2156t /= 24;
2157d = t % 7;
2158w = t/7;
2159
2160if (w > 0) { sprintf(CS p, "%dw", w); while (*p) p++; }
2161if (d > 0) { sprintf(CS p, "%dd", d); while (*p) p++; }
2162if (h > 0) { sprintf(CS p, "%dh", h); while (*p) p++; }
2163if (m > 0) { sprintf(CS p, "%dm", m); while (*p) p++; }
2164if (s > 0 || p == time_buffer) sprintf(CS p, "%ds", s);
2165
2166return time_buffer;
2167}
2168
2169
2170
2171/*************************************************
2172* Print an individual option value *
2173*************************************************/
2174
2175/* This is used by the -bP option, so prints to the standard output.
2176The entire options list is passed in as an argument, because some options come
2177in pairs - typically uid/gid settings, which can either be explicit numerical
2178values, or strings to be expanded later. If the numerical value is unset,
2179search for "*expand_<name>" to see if there is a string equivalent.
2180
2181Arguments:
2182 ol option entry, or NULL for an unknown option
2183 name option name
2184 options_block NULL for main configuration options; otherwise points to
2185 a driver block; if the option doesn't have opt_public
2186 set, then options_block->options_block is where the item
2187 resides.
2188 oltop points to the option list in which ol exists
2189 last one more than the offset of the last entry in optop
12f69989 2190 no_labels do not show "foo = " at the start.
059ec3d9
PH
2191
2192Returns: nothing
2193*/
2194
2195static void
2196print_ol(optionlist *ol, uschar *name, void *options_block,
12f69989 2197 optionlist *oltop, int last, BOOL no_labels)
059ec3d9
PH
2198{
2199struct passwd *pw;
2200struct group *gr;
2201optionlist *ol2;
2202void *value;
2203uid_t *uidlist;
2204gid_t *gidlist;
2205uschar *s;
2206uschar name2[64];
2207
2208if (ol == NULL)
2209 {
2210 printf("%s is not a known option\n", name);
2211 return;
2212 }
2213
2214/* Non-admin callers cannot see options that have been flagged secure by the
2215"hide" prefix. */
2216
2217if (!admin_user && (ol->type & opt_secure) != 0)
2218 {
12f69989
PP
2219 const char * const hidden = "<value not displayable>";
2220 if (no_labels)
2221 printf("%s\n", hidden);
2222 else
2223 printf("%s = %s\n", name, hidden);
059ec3d9
PH
2224 return;
2225 }
2226
2227/* Else show the value of the option */
2228
2229value = ol->value;
2230if (options_block != NULL)
2231 {
2232 if ((ol->type & opt_public) == 0)
2233 options_block = (void *)(((driver_instance *)options_block)->options_block);
2234 value = (void *)((uschar *)options_block + (long int)value);
2235 }
2236
2237switch(ol->type & opt_mask)
2238 {
2239 case opt_stringptr:
2240 case opt_rewrite: /* Show the text value */
2241 s = *((uschar **)value);
12f69989
PP
2242 if (!no_labels) printf("%s = ", name);
2243 printf("%s\n", (s == NULL)? US"" : string_printing2(s, FALSE));
059ec3d9
PH
2244 break;
2245
2246 case opt_int:
12f69989
PP
2247 if (!no_labels) printf("%s = ", name);
2248 printf("%d\n", *((int *)value));
059ec3d9
PH
2249 break;
2250
2251 case opt_mkint:
2252 {
2253 int x = *((int *)value);
2254 if (x != 0 && (x & 1023) == 0)
2255 {
2256 int c = 'K';
2257 x >>= 10;
2258 if ((x & 1023) == 0)
2259 {
2260 c = 'M';
2261 x >>= 10;
2262 }
12f69989
PP
2263 if (!no_labels) printf("%s = ", name);
2264 printf("%d%c\n", x, c);
2265 }
2266 else
2267 {
2268 if (!no_labels) printf("%s = ", name);
2269 printf("%d\n", x);
059ec3d9 2270 }
059ec3d9
PH
2271 }
2272 break;
2273
2274 case opt_Kint:
2275 {
2276 int x = *((int *)value);
12f69989
PP
2277 if (!no_labels) printf("%s = ", name);
2278 if (x == 0) printf("0\n");
2279 else if ((x & 1023) == 0) printf("%dM\n", x >> 10);
2280 else printf("%dK\n", x);
059ec3d9
PH
2281 }
2282 break;
2283
2284 case opt_octint:
12f69989
PP
2285 if (!no_labels) printf("%s = ", name);
2286 printf("%#o\n", *((int *)value));
059ec3d9
PH
2287 break;
2288
2289 /* Can be negative only when "unset", in which case integer */
2290
2291 case opt_fixed:
2292 {
2293 int x = *((int *)value);
2294 int f = x % 1000;
2295 int d = 100;
2296 if (x < 0) printf("%s =\n", name); else
2297 {
12f69989
PP
2298 if (!no_labels) printf("%s = ", name);
2299 printf("%d.", x/1000);
059ec3d9
PH
2300 do
2301 {
2302 printf("%d", f/d);
2303 f %= d;
2304 d /= 10;
2305 }
2306 while (f != 0);
2307 printf("\n");
2308 }
2309 }
2310 break;
2311
2312 /* If the numerical value is unset, try for the string value */
2313
2314 case opt_expand_uid:
2315 if (! *get_set_flag(name, oltop, last, options_block))
2316 {
2317 sprintf(CS name2, "*expand_%.50s", name);
2318 ol2 = find_option(name2, oltop, last);
2319 if (ol2 != NULL)
2320 {
2321 void *value2 = ol2->value;
2322 if (options_block != NULL)
2323 value2 = (void *)((uschar *)options_block + (long int)value2);
2324 s = *((uschar **)value2);
12f69989
PP
2325 if (!no_labels) printf("%s = ", name);
2326 printf("%s\n", (s == NULL)? US"" : string_printing(s));
059ec3d9
PH
2327 break;
2328 }
2329 }
2330
2331 /* Else fall through */
2332
2333 case opt_uid:
12f69989 2334 if (!no_labels) printf("%s = ", name);
059ec3d9 2335 if (! *get_set_flag(name, oltop, last, options_block))
12f69989 2336 printf("\n");
059ec3d9
PH
2337 else
2338 {
2339 pw = getpwuid(*((uid_t *)value));
2340 if (pw == NULL)
12f69989
PP
2341 printf("%ld\n", (long int)(*((uid_t *)value)));
2342 else printf("%s\n", pw->pw_name);
059ec3d9
PH
2343 }
2344 break;
2345
2346 /* If the numerical value is unset, try for the string value */
2347
2348 case opt_expand_gid:
2349 if (! *get_set_flag(name, oltop, last, options_block))
2350 {
2351 sprintf(CS name2, "*expand_%.50s", name);
2352 ol2 = find_option(name2, oltop, last);
2353 if (ol2 != NULL && (ol2->type & opt_mask) == opt_stringptr)
2354 {
2355 void *value2 = ol2->value;
2356 if (options_block != NULL)
2357 value2 = (void *)((uschar *)options_block + (long int)value2);
2358 s = *((uschar **)value2);
12f69989
PP
2359 if (!no_labels) printf("%s = ", name);
2360 printf("%s\n", (s == NULL)? US"" : string_printing(s));
059ec3d9
PH
2361 break;
2362 }
2363 }
2364
2365 /* Else fall through */
2366
2367 case opt_gid:
12f69989 2368 if (!no_labels) printf("%s = ", name);
059ec3d9 2369 if (! *get_set_flag(name, oltop, last, options_block))
12f69989 2370 printf("\n");
059ec3d9
PH
2371 else
2372 {
2373 gr = getgrgid(*((int *)value));
2374 if (gr == NULL)
12f69989
PP
2375 printf("%ld\n", (long int)(*((int *)value)));
2376 else printf("%s\n", gr->gr_name);
059ec3d9
PH
2377 }
2378 break;
2379
2380 case opt_uidlist:
2381 uidlist = *((uid_t **)value);
12f69989 2382 if (!no_labels) printf("%s =", name);
059ec3d9
PH
2383 if (uidlist != NULL)
2384 {
2385 int i;
2386 uschar sep = ' ';
12f69989 2387 if (no_labels) sep = '\0';
059ec3d9
PH
2388 for (i = 1; i <= (int)(uidlist[0]); i++)
2389 {
2390 uschar *name = NULL;
2391 pw = getpwuid(uidlist[i]);
2392 if (pw != NULL) name = US pw->pw_name;
12f69989
PP
2393 if (sep != '\0') printf("%c", sep);
2394 if (name != NULL) printf("%s", name);
2395 else printf("%ld", (long int)(uidlist[i]));
059ec3d9
PH
2396 sep = ':';
2397 }
2398 }
2399 printf("\n");
2400 break;
2401
2402 case opt_gidlist:
2403 gidlist = *((gid_t **)value);
12f69989 2404 if (!no_labels) printf("%s =", name);
059ec3d9
PH
2405 if (gidlist != NULL)
2406 {
2407 int i;
2408 uschar sep = ' ';
12f69989 2409 if (no_labels) sep = '\0';
059ec3d9
PH
2410 for (i = 1; i <= (int)(gidlist[0]); i++)
2411 {
2412 uschar *name = NULL;
2413 gr = getgrgid(gidlist[i]);
2414 if (gr != NULL) name = US gr->gr_name;
12f69989
PP
2415 if (sep != '\0') printf("%c", sep);
2416 if (name != NULL) printf("%s", name);
2417 else printf("%ld", (long int)(gidlist[i]));
059ec3d9
PH
2418 sep = ':';
2419 }
2420 }
2421 printf("\n");
2422 break;
2423
2424 case opt_time:
12f69989
PP
2425 if (!no_labels) printf("%s = ", name);
2426 printf("%s\n", readconf_printtime(*((int *)value)));
059ec3d9
PH
2427 break;
2428
2429 case opt_timelist:
2430 {
2431 int i;
2432 int *list = (int *)value;
12f69989 2433 if (!no_labels) printf("%s = ", name);
059ec3d9
PH
2434 for (i = 0; i < list[1]; i++)
2435 printf("%s%s", (i == 0)? "" : ":", readconf_printtime(list[i+2]));
2436 printf("\n");
2437 }
2438 break;
2439
2440 case opt_bit:
2441 printf("%s%s\n", ((*((int *)value)) & (1 << ((ol->type >> 16) & 31)))?
2442 "" : "no_", name);
2443 break;
2444
2445 case opt_expand_bool:
2446 sprintf(CS name2, "*expand_%.50s", name);
2447 ol2 = find_option(name2, oltop, last);
2448 if (ol2 != NULL && ol2->value != NULL)
2449 {
2450 void *value2 = ol2->value;
2451 if (options_block != NULL)
2452 value2 = (void *)((uschar *)options_block + (long int)value2);
2453 s = *((uschar **)value2);
2454 if (s != NULL)
2455 {
12f69989
PP
2456 if (!no_labels) printf("%s = ", name);
2457 printf("%s\n", string_printing(s));
059ec3d9
PH
2458 break;
2459 }
2460 /* s == NULL => string not set; fall through */
2461 }
2462
2463 /* Fall through */
2464
2465 case opt_bool:
2466 case opt_bool_verify:
2467 case opt_bool_set:
2468 printf("%s%s\n", (*((BOOL *)value))? "" : "no_", name);
2469 break;
2470 }
2471}
2472
2473
2474
2475/*************************************************
2476* Print value from main configuration *
2477*************************************************/
2478
2479/* This function, called as a result of encountering the -bP option,
2480causes the value of any main configuration variable to be output if the
2481second argument is NULL. There are some special values:
2482
2483 all print all main configuration options
2484 configure_file print the name of the configuration file
2485 routers print the routers' configurations
2486 transports print the transports' configuration
2487 authenticators print the authenticators' configuration
5d9c27ec 2488 macros print the macros' configuration
059ec3d9
PH
2489 router_list print a list of router names
2490 transport_list print a list of transport names
2491 authenticator_list print a list of authentication mechanism names
5d9c27ec 2492 macro_list print a list of macro names
059ec3d9
PH
2493 +name print a named list item
2494 local_scan print the local_scan options
2495
5d9c27ec
TK
2496If the second argument is not NULL, it must be one of "router", "transport",
2497"authenticator" or "macro" in which case the first argument identifies the
2498driver whose options are to be printed.
059ec3d9
PH
2499
2500Arguments:
2501 name option name if type == NULL; else driver name
2502 type NULL or driver type name, as described above
12f69989 2503 no_labels avoid the "foo = " at the start of an item
059ec3d9
PH
2504
2505Returns: nothing
2506*/
2507
2508void
12f69989 2509readconf_print(uschar *name, uschar *type, BOOL no_labels)
059ec3d9
PH
2510{
2511BOOL names_only = FALSE;
2512optionlist *ol;
2513optionlist *ol2 = NULL;
2514driver_instance *d = NULL;
5d9c27ec 2515macro_item *m;
059ec3d9
PH
2516int size = 0;
2517
2518if (type == NULL)
2519 {
2520 if (*name == '+')
2521 {
2522 int i;
2523 tree_node *t;
2524 BOOL found = FALSE;
2525 static uschar *types[] = { US"address", US"domain", US"host",
2526 US"localpart" };
2527 static tree_node **anchors[] = { &addresslist_anchor, &domainlist_anchor,
2528 &hostlist_anchor, &localpartlist_anchor };
2529
2530 for (i = 0; i < 4; i++)
2531 {
2532 t = tree_search(*(anchors[i]), name+1);
2533 if (t != NULL)
2534 {
2535 found = TRUE;
12f69989
PP
2536 if (no_labels)
2537 printf("%s\n", ((namedlist_block *)(t->data.ptr))->string);
2538 else
2539 printf("%slist %s = %s\n", types[i], name+1,
2540 ((namedlist_block *)(t->data.ptr))->string);
059ec3d9
PH
2541 }
2542 }
2543
2544 if (!found)
2545 printf("no address, domain, host, or local part list called \"%s\" "
2546 "exists\n", name+1);
2547
2548 return;
2549 }
2550
2551 if (Ustrcmp(name, "configure_file") == 0)
2552 {
2553 printf("%s\n", CS config_main_filename);
2554 return;
2555 }
2556
2557 if (Ustrcmp(name, "all") == 0)
2558 {
2559 for (ol = optionlist_config;
2560 ol < optionlist_config + optionlist_config_size; ol++)
2561 {
2562 if ((ol->type & opt_hidden) == 0)
12f69989
PP
2563 print_ol(ol, US ol->name, NULL,
2564 optionlist_config, optionlist_config_size,
2565 no_labels);
059ec3d9
PH
2566 }
2567 return;
2568 }
2569
2570 if (Ustrcmp(name, "local_scan") == 0)
2571 {
2572 #ifndef LOCAL_SCAN_HAS_OPTIONS
2573 printf("local_scan() options are not supported\n");
2574 #else
2575 for (ol = local_scan_options;
2576 ol < local_scan_options + local_scan_options_count; ol++)
2577 {
2578 print_ol(ol, US ol->name, NULL, local_scan_options,
12f69989 2579 local_scan_options_count, no_labels);
059ec3d9
PH
2580 }
2581 #endif
2582 return;
2583 }
2584
2585 if (Ustrcmp(name, "routers") == 0)
2586 {
2587 type = US"router";
2588 name = NULL;
2589 }
2590 else if (Ustrcmp(name, "transports") == 0)
2591 {
2592 type = US"transport";
2593 name = NULL;
2594 }
2595
2596 else if (Ustrcmp(name, "authenticators") == 0)
2597 {
2598 type = US"authenticator";
2599 name = NULL;
2600 }
2601
5d9c27ec 2602 else if (Ustrcmp(name, "macros") == 0)
059ec3d9 2603 {
5d9c27ec 2604 type = US"macro";
059ec3d9 2605 name = NULL;
059ec3d9
PH
2606 }
2607
2608 else if (Ustrcmp(name, "router_list") == 0)
2609 {
2610 type = US"router";
2611 name = NULL;
2612 names_only = TRUE;
2613 }
5d9c27ec 2614
059ec3d9
PH
2615 else if (Ustrcmp(name, "transport_list") == 0)
2616 {
2617 type = US"transport";
2618 name = NULL;
2619 names_only = TRUE;
2620 }
5d9c27ec
TK
2621
2622 else if (Ustrcmp(name, "authenticator_list") == 0)
2623 {
2624 type = US"authenticator";
2625 name = NULL;
2626 names_only = TRUE;
2627 }
2628
2629 else if (Ustrcmp(name, "macro_list") == 0)
2630 {
2631 type = US"macro";
2632 name = NULL;
2633 names_only = TRUE;
2634 }
2635
059ec3d9
PH
2636 else
2637 {
2638 print_ol(find_option(name, optionlist_config, optionlist_config_size),
12f69989 2639 name, NULL, optionlist_config, optionlist_config_size, no_labels);
059ec3d9
PH
2640 return;
2641 }
2642 }
2643
2644/* Handle the options for a router or transport. Skip options that are flagged
2645as hidden. Some of these are options with names starting with '*', used for
2646internal alternative representations of other options (which the printing
2647function will sort out). Others are synonyms kept for backward compatibility.
2648*/
2649
2650if (Ustrcmp(type, "router") == 0)
2651 {
2652 d = (driver_instance *)routers;
2653 ol2 = optionlist_routers;
2654 size = optionlist_routers_size;
2655 }
2656else if (Ustrcmp(type, "transport") == 0)
2657 {
2658 d = (driver_instance *)transports;
2659 ol2 = optionlist_transports;
2660 size = optionlist_transports_size;
2661 }
2662else if (Ustrcmp(type, "authenticator") == 0)
2663 {
2664 d = (driver_instance *)auths;
2665 ol2 = optionlist_auths;
2666 size = optionlist_auths_size;
2667 }
2668
5d9c27ec
TK
2669else if (Ustrcmp(type, "macro") == 0)
2670 {
2671 /* People store passwords in macros and they were previously not available
2672 for printing. So we have an admin_users restriction. */
2673 if (!admin_user)
2674 {
2675 fprintf(stderr, "exim: permission denied\n");
2676 exit(EXIT_FAILURE);
2677 }
2678 for (m = macros; m != NULL; m = m->next)
2679 {
2680 if (name == NULL || Ustrcmp(name, m->name) == 0)
2681 {
2682 if (names_only)
2683 printf("%s\n", CS m->name);
2684 else
2685 printf("%s=%s\n", CS m->name, CS m->replacement);
2686 if (name != NULL)
2687 return;
2688 }
2689 }
2690 if (name != NULL)
2691 printf("%s %s not found\n", type, name);
2692 return;
2693 }
2694
059ec3d9
PH
2695if (names_only)
2696 {
2697 for (; d != NULL; d = d->next) printf("%s\n", CS d->name);
2698 return;
2699 }
2700
2701/* Either search for a given driver, or print all of them */
2702
2703for (; d != NULL; d = d->next)
2704 {
2705 if (name == NULL)
2706 printf("\n%s %s:\n", d->name, type);
2707 else if (Ustrcmp(d->name, name) != 0) continue;
2708
2709 for (ol = ol2; ol < ol2 + size; ol++)
2710 {
2711 if ((ol->type & opt_hidden) == 0)
12f69989 2712 print_ol(ol, US ol->name, d, ol2, size, no_labels);
059ec3d9
PH
2713 }
2714
2715 for (ol = d->info->options;
2716 ol < d->info->options + *(d->info->options_count); ol++)
2717 {
2718 if ((ol->type & opt_hidden) == 0)
12f69989 2719 print_ol(ol, US ol->name, d, d->info->options, *(d->info->options_count), no_labels);
059ec3d9
PH
2720 }
2721 if (name != NULL) return;
2722 }
2723if (name != NULL) printf("%s %s not found\n", type, name);
2724}
2725
2726
2727
2728/*************************************************
2729* Read a named list item *
2730*************************************************/
2731
2732/* This function reads a name and a list (i.e. string). The name is used to
2733save the list in a tree, sorted by its name. Each entry also has a number,
2734which can be used for caching tests, but if the string contains any expansion
2735items other than $key, the number is set negative to inhibit caching. This
2736mechanism is used for domain, host, and address lists that are referenced by
2737the "+name" syntax.
2738
2739Arguments:
2740 anchorp points to the tree anchor
2741 numberp points to the current number for this tree
2742 max the maximum number permitted
2743 s the text of the option line, starting immediately after the name
2744 of the list type
2745 tname the name of the list type, for messages
2746
2747Returns: nothing
2748*/
2749
2750static void
2751read_named_list(tree_node **anchorp, int *numberp, int max, uschar *s,
2752 uschar *tname)
2753{
2754BOOL forcecache = FALSE;
2755uschar *ss;
2756tree_node *t;
2757namedlist_block *nb = store_get(sizeof(namedlist_block));
2758
2759if (Ustrncmp(s, "_cache", 6) == 0)
2760 {
2761 forcecache = TRUE;
2762 s += 6;
2763 }
2764
2765if (!isspace(*s))
2766 log_write(0, LOG_PANIC_DIE|LOG_CONFIG_IN, "unrecognized configuration line");
2767
2768if (*numberp >= max)
2769 log_write(0, LOG_PANIC_DIE|LOG_CONFIG_IN, "too many named %ss (max is %d)\n",
2770 tname, max);
2771
2772while (isspace(*s)) s++;
2773ss = s;
2774while (isalnum(*s) || *s == '_') s++;
2775t = store_get(sizeof(tree_node) + s-ss);
2776Ustrncpy(t->name, ss, s-ss);
2777t->name[s-ss] = 0;
2778while (isspace(*s)) s++;
2779
2780if (!tree_insertnode(anchorp, t))
2781 log_write(0, LOG_PANIC_DIE|LOG_CONFIG_IN,
2782 "duplicate name \"%s\" for a named %s", t->name, tname);
2783
2784t->data.ptr = nb;
2785nb->number = *numberp;
2786*numberp += 1;
2787
2788if (*s++ != '=') log_write(0, LOG_PANIC_DIE|LOG_CONFIG_IN,
2789 "missing '=' after \"%s\"", t->name);
2790while (isspace(*s)) s++;
2791nb->string = read_string(s, t->name);
2792nb->cache_data = NULL;
2793
2794/* Check the string for any expansions; if any are found, mark this list
2795uncacheable unless the user has explicited forced caching. */
2796
2797if (!forcecache && Ustrchr(nb->string, '$') != NULL) nb->number = -1;
2798}
2799
2800
2801
2802
2803/*************************************************
2804* Unpick data for a rate limit *
2805*************************************************/
2806
2807/* This function is called to unpick smtp_ratelimit_{mail,rcpt} into four
2808separate values.
2809
2810Arguments:
2811 s string, in the form t,b,f,l
2812 where t is the threshold (integer)
2813 b is the initial delay (time)
2814 f is the multiplicative factor (fixed point)
2815 k is the maximum time (time)
2816 threshold where to store threshold
2817 base where to store base in milliseconds
2818 factor where to store factor in milliseconds
2819 limit where to store limit
2820
2821Returns: nothing (panics on error)
2822*/
2823
2824static void
2825unpick_ratelimit(uschar *s, int *threshold, int *base, double *factor,
2826 int *limit)
2827{
2828uschar bstring[16], lstring[16];
2829
2830if (sscanf(CS s, "%d, %15[0123456789smhdw.], %lf, %15s", threshold, bstring,
2831 factor, lstring) == 4)
2832 {
2833 *base = readconf_readtime(bstring, 0, TRUE);
2834 *limit = readconf_readtime(lstring, 0, TRUE);
2835 if (*base >= 0 && *limit >= 0) return;
2836 }
2837log_write(0, LOG_MAIN|LOG_PANIC_DIE, "malformed ratelimit data: %s", s);
2838}
2839
2840
2841
2842
2843/*************************************************
3375e053
PP
2844* Drop privs for checking TLS config *
2845*************************************************/
2846
2847/* We want to validate TLS options during readconf, but do not want to be
2848root when we call into the TLS library, in case of library linkage errors
2849which cause segfaults; before this check, those were always done as the Exim
2850runtime user and it makes sense to continue with that.
2851
2852Assumes: tls_require_ciphers has been set, if it will be
2853 exim_user has been set, if it will be
2854 exim_group has been set, if it will be
2855
2856Returns: bool for "okay"; false will cause caller to immediately exit.
2857*/
2858
2859#ifdef SUPPORT_TLS
2860static BOOL
2861tls_dropprivs_validate_require_cipher(void)
2862{
2863const uschar *errmsg;
2864pid_t pid;
2865int rc, status;
2866void (*oldsignal)(int);
2867
2868oldsignal = signal(SIGCHLD, SIG_DFL);
2869
2870fflush(NULL);
2871if ((pid = fork()) < 0)
2872 log_write(0, LOG_MAIN|LOG_PANIC_DIE, "fork failed for TLS check");
2873
2874if (pid == 0)
2875 {
1d7a353e
PP
2876 /* in some modes, will have dropped privilege already */
2877 if (!geteuid())
2878 exim_setugid(exim_uid, exim_gid, FALSE,
2879 US"calling tls_validate_require_cipher");
3375e053
PP
2880
2881 errmsg = tls_validate_require_cipher();
2882 if (errmsg)
2883 {
2884 log_write(0, LOG_PANIC_DIE|LOG_CONFIG,
2885 "tls_require_ciphers invalid: %s", errmsg);
2886 }
2887 fflush(NULL);
2888 _exit(0);
2889 }
2890
2891do {
2892 rc = waitpid(pid, &status, 0);
2893} while (rc < 0 && errno == EINTR);
2894
9d26b8c0 2895DEBUG(D_tls)
3375e053
PP
2896 debug_printf("tls_validate_require_cipher child %d ended: status=0x%x\n",
2897 (int)pid, status);
2898
2899signal(SIGCHLD, oldsignal);
2900
2901return status == 0;
2902}
2903#endif /* SUPPORT_TLS */
2904
2905
2906
2907
2908/*************************************************
059ec3d9
PH
2909* Read main configuration options *
2910*************************************************/
2911
2912/* This function is the first to be called for configuration reading. It
2913opens the configuration file and reads general configuration settings until
2914it reaches the end of the configuration section. The file is then left open so
2915that the remaining configuration data can subsequently be read if needed for
2916this run of Exim.
2917
2918The configuration file must be owned either by root or exim, and be writeable
2919only by root or uid/gid exim. The values for Exim's uid and gid can be changed
2920in the config file, so the test is done on the compiled in values. A slight
2921anomaly, to be carefully documented.
2922
2923The name of the configuration file is taken from a list that is included in the
2924binary of Exim. It can be altered from the command line, but if that is done,
2925root privilege is immediately withdrawn unless the caller is root or exim.
2926The first file on the list that exists is used.
2927
2928For use on multiple systems that share file systems, first look for a
2929configuration file whose name has the current node name on the end. If that is
2930not found, try the generic name. For really contorted configurations, that run
2931multiple Exims with different uid settings, first try adding the effective uid
2932before the node name. These complications are going to waste resources on most
2933systems. Therefore they are available only when requested by compile-time
2934options. */
2935
2936void
2937readconf_main(void)
2938{
2939int sep = 0;
2940struct stat statbuf;
2941uschar *s, *filename;
2942uschar *list = config_main_filelist;
2943
2944/* Loop through the possible file names */
2945
2946while((filename = string_nextinlist(&list, &sep, big_buffer, big_buffer_size))
2947 != NULL)
2948 {
2949 /* Cut out all the fancy processing unless specifically wanted */
2950
2951 #if defined(CONFIGURE_FILE_USE_NODE) || defined(CONFIGURE_FILE_USE_EUID)
2952 uschar *suffix = filename + Ustrlen(filename);
2953
2954 /* Try for the node-specific file if a node name exists */
2955
2956 #ifdef CONFIGURE_FILE_USE_NODE
2957 struct utsname uts;
2958 if (uname(&uts) >= 0)
2959 {
2960 #ifdef CONFIGURE_FILE_USE_EUID
2961 sprintf(CS suffix, ".%ld.%.256s", (long int)original_euid, uts.nodename);
2962 config_file = Ufopen(filename, "rb");
2963 if (config_file == NULL)
2964 #endif /* CONFIGURE_FILE_USE_EUID */
2965 {
2966 sprintf(CS suffix, ".%.256s", uts.nodename);
2967 config_file = Ufopen(filename, "rb");
2968 }
2969 }
2970 #endif /* CONFIGURE_FILE_USE_NODE */
2971
2972 /* Otherwise, try the generic name, possibly with the euid added */
2973
2974 #ifdef CONFIGURE_FILE_USE_EUID
2975 if (config_file == NULL)
2976 {
2977 sprintf(CS suffix, ".%ld", (long int)original_euid);
2978 config_file = Ufopen(filename, "rb");
2979 }
2980 #endif /* CONFIGURE_FILE_USE_EUID */
2981
2982 /* Finally, try the unadorned name */
2983
2984 if (config_file == NULL)
2985 {
2986 *suffix = 0;
2987 config_file = Ufopen(filename, "rb");
2988 }
2989 #else /* if neither defined */
2990
2991 /* This is the common case when the fancy processing is not included. */
2992
2993 config_file = Ufopen(filename, "rb");
2994 #endif
2995
2996 /* If the file does not exist, continue to try any others. For any other
2997 error, break out (and die). */
2998
2999 if (config_file != NULL || errno != ENOENT) break;
3000 }
3001
3002/* On success, save the name for verification; config_filename is used when
3003logging configuration errors (it changes for .included files) whereas
3004config_main_filename is the name shown by -bP. Failure to open a configuration
3005file is a serious disaster. */
3006
3007if (config_file != NULL)
3008 {
98b8312f 3009 uschar *p;
059ec3d9 3010 config_filename = config_main_filename = string_copy(filename);
98b8312f 3011
b6fbf22d 3012 p = Ustrrchr(filename, '/');
98b8312f 3013 config_main_directory = p ? string_copyn(filename, p - filename)
b6fbf22d 3014 : string_copy(US".");
059ec3d9
PH
3015 }
3016else
3017 {
3018 if (filename == NULL)
3019 log_write(0, LOG_MAIN|LOG_PANIC_DIE, "non-existent configuration file(s): "
3020 "%s", config_main_filelist);
3021 else
3022 log_write(0, LOG_MAIN|LOG_PANIC_DIE, "%s", string_open_failed(errno,
3023 "configuration file %s", filename));
3024 }
3025
e2f5dc15 3026/* Check the status of the file we have opened, if we have retained root
fea24b2e 3027privileges and the file isn't /dev/null (which *should* be 0666). */
059ec3d9 3028
fea24b2e 3029if (trusted_config && Ustrcmp(filename, US"/dev/null"))
059ec3d9
PH
3030 {
3031 if (fstat(fileno(config_file), &statbuf) != 0)
3032 log_write(0, LOG_MAIN|LOG_PANIC_DIE, "failed to stat configuration file %s",
3033 big_buffer);
3034
c1d94452 3035 if ((statbuf.st_uid != root_uid /* owner not root */
059ec3d9
PH
3036 #ifdef CONFIGURE_OWNER
3037 && statbuf.st_uid != config_uid /* owner not the special one */
3038 #endif
3039 ) || /* or */
c1d94452 3040 (statbuf.st_gid != root_gid /* group not root & */
35edf2ff
PH
3041 #ifdef CONFIGURE_GROUP
3042 && statbuf.st_gid != config_gid /* group not the special one */
8e669ac1 3043 #endif
35edf2ff 3044 && (statbuf.st_mode & 020) != 0) || /* group writeable */
059ec3d9
PH
3045 /* or */
3046 ((statbuf.st_mode & 2) != 0)) /* world writeable */
3047
3048 log_write(0, LOG_MAIN|LOG_PANIC_DIE, "Exim configuration file %s has the "
3049 "wrong owner, group, or mode", big_buffer);
3050 }
3051
3052/* Process the main configuration settings. They all begin with a lower case
3053letter. If we see something starting with an upper case letter, it is taken as
3054a macro definition. */
3055
3056while ((s = get_config_line()) != NULL)
3057 {
cf00dad6 3058 if (isupper(s[0])) read_macro_assignment(s);
059ec3d9
PH
3059
3060 else if (Ustrncmp(s, "domainlist", 10) == 0)
3061 read_named_list(&domainlist_anchor, &domainlist_count,
3062 MAX_NAMED_LIST, s+10, US"domain list");
3063
3064 else if (Ustrncmp(s, "hostlist", 8) == 0)
3065 read_named_list(&hostlist_anchor, &hostlist_count,
3066 MAX_NAMED_LIST, s+8, US"host list");
3067
3068 else if (Ustrncmp(s, US"addresslist", 11) == 0)
3069 read_named_list(&addresslist_anchor, &addresslist_count,
3070 MAX_NAMED_LIST, s+11, US"address list");
3071
3072 else if (Ustrncmp(s, US"localpartlist", 13) == 0)
3073 read_named_list(&localpartlist_anchor, &localpartlist_count,
3074 MAX_NAMED_LIST, s+13, US"local part list");
3075
3076 else
3077 (void) readconf_handle_option(s, optionlist_config, optionlist_config_size,
3078 NULL, US"main option \"%s\" unknown");
3079 }
3080
3081
3082/* If local_sender_retain is set, local_from_check must be unset. */
3083
3084if (local_sender_retain && local_from_check)
3085 log_write(0, LOG_MAIN|LOG_PANIC_DIE, "both local_from_check and "
3086 "local_sender_retain are set; this combination is not allowed");
3087
3088/* If the timezone string is empty, set it to NULL, implying no TZ variable
3089wanted. */
3090
3091if (timezone_string != NULL && *timezone_string == 0) timezone_string = NULL;
3092
944a9c55
PH
3093/* The max retry interval must not be greater than 24 hours. */
3094
3095if (retry_interval_max > 24*60*60) retry_interval_max = 24*60*60;
3096
059ec3d9
PH
3097/* remote_max_parallel must be > 0 */
3098
3099if (remote_max_parallel <= 0) remote_max_parallel = 1;
3100
6a3f1455
PH
3101/* Save the configured setting of freeze_tell, so we can re-instate it at the
3102start of a new SMTP message. */
3103
3104freeze_tell_config = freeze_tell;
3105
059ec3d9
PH
3106/* The primary host name may be required for expansion of spool_directory
3107and log_file_path, so make sure it is set asap. It is obtained from uname(),
3108but if that yields an unqualified value, make a FQDN by using gethostbyname to
3109canonize it. Some people like upper case letters in their host names, so we
3110don't force the case. */
3111
3112if (primary_hostname == NULL)
3113 {
3114 uschar *hostname;
3115 struct utsname uts;
3116 if (uname(&uts) < 0)
3117 log_write(0, LOG_MAIN|LOG_PANIC_DIE, "uname() failed to yield host name");
3118 hostname = US uts.nodename;
3119
3120 if (Ustrchr(hostname, '.') == NULL)
3121 {
3122 int af = AF_INET;
3123 struct hostent *hostdata;
3124
3125 #if HAVE_IPV6
7e66e54d 3126 if (!disable_ipv6 && (dns_ipv4_lookup == NULL ||
059ec3d9 3127 match_isinlist(hostname, &dns_ipv4_lookup, 0, NULL, NULL, MCL_DOMAIN,
7e66e54d 3128 TRUE, NULL) != OK))
059ec3d9
PH
3129 af = AF_INET6;
3130 #else
3131 af = AF_INET;
3132 #endif
3133
3134 for (;;)
3135 {
3136 #if HAVE_IPV6
3137 #if HAVE_GETIPNODEBYNAME
3138 int error_num;
3139 hostdata = getipnodebyname(CS hostname, af, 0, &error_num);
3140 #else
3141 hostdata = gethostbyname2(CS hostname, af);
3142 #endif
3143 #else
3144 hostdata = gethostbyname(CS hostname);
3145 #endif
3146
3147 if (hostdata != NULL)
3148 {
3149 hostname = US hostdata->h_name;
3150 break;
3151 }
3152
3153 if (af == AF_INET) break;
3154 af = AF_INET;
3155 }
3156 }
3157
3158 primary_hostname = string_copy(hostname);
3159 }
3160
3161/* Set up default value for smtp_active_hostname */
3162
3163smtp_active_hostname = primary_hostname;
3164
3165/* If spool_directory wasn't set in the build-time configuration, it must have
3166got set above. Of course, writing to the log may not work if log_file_path is
3167not set, but it will at least get to syslog or somewhere, with any luck. */
3168
3169if (*spool_directory == 0)
3170 log_write(0, LOG_MAIN|LOG_PANIC_DIE, "spool_directory undefined: cannot "
3171 "proceed");
3172
3173/* Expand the spool directory name; it may, for example, contain the primary
3174host name. Same comment about failure. */
3175
3176s = expand_string(spool_directory);
3177if (s == NULL)
3178 log_write(0, LOG_MAIN|LOG_PANIC_DIE, "failed to expand spool_directory "
3179 "\"%s\": %s", spool_directory, expand_string_message);
3180spool_directory = s;
3181
3182/* Expand log_file_path, which must contain "%s" in any component that isn't
f1e5fef5
PP
3183the null string or "syslog". It is also allowed to contain one instance of %D
3184or %M. However, it must NOT contain % followed by anything else. */
059ec3d9
PH
3185
3186if (*log_file_path != 0)
3187 {
3188 uschar *ss, *sss;
3189 int sep = ':'; /* Fixed for log file path */
3190 s = expand_string(log_file_path);
3191 if (s == NULL)
3192 log_write(0, LOG_MAIN|LOG_PANIC_DIE, "failed to expand log_file_path "
3193 "\"%s\": %s", log_file_path, expand_string_message);
3194
3195 ss = s;
3196 while ((sss = string_nextinlist(&ss,&sep,big_buffer,big_buffer_size)) != NULL)
3197 {
3198 uschar *t;
3199 if (sss[0] == 0 || Ustrcmp(sss, "syslog") == 0) continue;
3200 t = Ustrstr(sss, "%s");
3201 if (t == NULL)
3202 log_write(0, LOG_MAIN|LOG_PANIC_DIE, "log_file_path \"%s\" does not "
3203 "contain \"%%s\"", sss);
3204 *t = 'X';
3205 t = Ustrchr(sss, '%');
3206 if (t != NULL)
3207 {
f1e5fef5 3208 if ((t[1] != 'D' && t[1] != 'M') || Ustrchr(t+2, '%') != NULL)
059ec3d9
PH
3209 log_write(0, LOG_MAIN|LOG_PANIC_DIE, "log_file_path \"%s\" contains "
3210 "unexpected \"%%\" character", s);
3211 }
3212 }
3213
3214 log_file_path = s;
3215 }
3216
3217/* Interpret syslog_facility into an integer argument for 'ident' param to
3218openlog(). Default is LOG_MAIL set in globals.c. Allow the user to omit the
3219leading "log_". */
3220
3221if (syslog_facility_str != NULL)
3222 {
3223 int i;
3224 uschar *s = syslog_facility_str;
3225
3226 if ((Ustrlen(syslog_facility_str) >= 4) &&
3227 (strncmpic(syslog_facility_str, US"log_", 4) == 0))
3228 s += 4;
3229
3230 for (i = 0; i < syslog_list_size; i++)
3231 {
3232 if (strcmpic(s, syslog_list[i].name) == 0)
3233 {
3234 syslog_facility = syslog_list[i].value;
3235 break;
3236 }
3237 }
3238
3239 if (i >= syslog_list_size)
3240 {
3241 log_write(0, LOG_PANIC_DIE|LOG_CONFIG,
3242 "failed to interpret syslog_facility \"%s\"", syslog_facility_str);
3243 }
3244 }
3245
3246/* Expand pid_file_path */
3247
3248if (*pid_file_path != 0)
3249 {
3250 s = expand_string(pid_file_path);
3251 if (s == NULL)
3252 log_write(0, LOG_MAIN|LOG_PANIC_DIE, "failed to expand pid_file_path "
3253 "\"%s\": %s", pid_file_path, expand_string_message);
3254 pid_file_path = s;
3255 }
3256
921b12ca
TF
3257/* Set default value of process_log_path */
3258
3259if (process_log_path == NULL || *process_log_path =='\0')
3260 process_log_path = string_sprintf("%s/exim-process.info", spool_directory);
3261
059ec3d9
PH
3262/* Compile the regex for matching a UUCP-style "From_" line in an incoming
3263message. */
3264
3265regex_From = regex_must_compile(uucp_from_pattern, FALSE, TRUE);
3266
3267/* Unpick the SMTP rate limiting options, if set */
3268
3269if (smtp_ratelimit_mail != NULL)
3270 {
3271 unpick_ratelimit(smtp_ratelimit_mail, &smtp_rlm_threshold,
3272 &smtp_rlm_base, &smtp_rlm_factor, &smtp_rlm_limit);
3273 }
3274
3275if (smtp_ratelimit_rcpt != NULL)
3276 {
3277 unpick_ratelimit(smtp_ratelimit_rcpt, &smtp_rlr_threshold,
3278 &smtp_rlr_base, &smtp_rlr_factor, &smtp_rlr_limit);
3279 }
3280
3281/* The qualify domains default to the primary host name */
3282
3283if (qualify_domain_sender == NULL)
3284 qualify_domain_sender = primary_hostname;
3285if (qualify_domain_recipient == NULL)
3286 qualify_domain_recipient = qualify_domain_sender;
3287
3288/* Setting system_filter_user in the configuration sets the gid as well if a
3289name is given, but a numerical value does not. */
3290
3291if (system_filter_uid_set && !system_filter_gid_set)
3292 {
3293 struct passwd *pw = getpwuid(system_filter_uid);
3294 if (pw == NULL)
3295 log_write(0, LOG_MAIN|LOG_PANIC_DIE, "Failed to look up uid %ld",
3296 (long int)system_filter_uid);
3297 system_filter_gid = pw->pw_gid;
3298 system_filter_gid_set = TRUE;
3299 }
3300
3301/* If the errors_reply_to field is set, check that it is syntactically valid
3302and ensure it contains a domain. */
3303
3304if (errors_reply_to != NULL)
3305 {
3306 uschar *errmess;
3307 int start, end, domain;
3308 uschar *recipient = parse_extract_address(errors_reply_to, &errmess,
3309 &start, &end, &domain, FALSE);
3310
3311 if (recipient == NULL)
3312 log_write(0, LOG_PANIC_DIE|LOG_CONFIG,
3313 "error in errors_reply_to (%s): %s", errors_reply_to, errmess);
3314
3315 if (domain == 0)
3316 log_write(0, LOG_PANIC_DIE|LOG_CONFIG,
3317 "errors_reply_to (%s) does not contain a domain", errors_reply_to);
3318 }
3319
3320/* If smtp_accept_queue or smtp_accept_max_per_host is set, then
3321smtp_accept_max must also be set. */
3322
3323if (smtp_accept_max == 0 &&
3324 (smtp_accept_queue > 0 || smtp_accept_max_per_host != NULL))
3325 log_write(0, LOG_PANIC_DIE|LOG_CONFIG,
3326 "smtp_accept_max must be set if smtp_accept_queue or "
3327 "smtp_accept_max_per_host is set");
3328
3329/* Set up the host number if anything is specified. It is an expanded string
3330so that it can be computed from the host name, for example. We do this last
3331so as to ensure that everything else is set up before the expansion. */
3332
3333if (host_number_string != NULL)
3334 {
ef840681 3335 long int n;
059ec3d9
PH
3336 uschar *end;
3337 uschar *s = expand_string(host_number_string);
ef840681
PP
3338 if (s == NULL)
3339 log_write(0, LOG_MAIN|LOG_PANIC_DIE,
3340 "failed to expand localhost_number \"%s\": %s",
3341 host_number_string, expand_string_message);
3342 n = Ustrtol(s, &end, 0);
059ec3d9
PH
3343 while (isspace(*end)) end++;
3344 if (*end != 0)
3345 log_write(0, LOG_PANIC_DIE|LOG_CONFIG,
3346 "localhost_number value is not a number: %s", s);
3347 if (n > LOCALHOST_MAX)
3348 log_write(0, LOG_PANIC_DIE|LOG_CONFIG,
3349 "localhost_number is greater than the maximum allowed value (%d)",
3350 LOCALHOST_MAX);
3351 host_number = n;
3352 }
3353
3354#ifdef SUPPORT_TLS
3355/* If tls_verify_hosts is set, tls_verify_certificates must also be set */
3356
3357if ((tls_verify_hosts != NULL || tls_try_verify_hosts != NULL) &&
3358 tls_verify_certificates == NULL)
3359 log_write(0, LOG_PANIC_DIE|LOG_CONFIG,
3360 "tls_%sverify_hosts is set, but tls_verify_certificates is not set",
3361 (tls_verify_hosts != NULL)? "" : "try_");
77bb000f 3362
3375e053
PP
3363/* This also checks that the library linkage is working and we can call
3364routines in it, so call even if tls_require_ciphers is unset */
3365if (!tls_dropprivs_validate_require_cipher())
3366 exit(1);
3367
3368/* Magic number: at time of writing, 1024 has been the long-standing value
3369used by so many clients, and what Exim used to use always, that it makes
3370sense to just min-clamp this max-clamp at that. */
3371if (tls_dh_max_bits < 1024)
3372 log_write(0, LOG_PANIC_DIE|LOG_CONFIG,
3373 "tls_dh_max_bits is too small, must be at least 1024 for interop");
3374
77bb000f
PP
3375/* If openssl_options is set, validate it */
3376if (openssl_options != NULL)
3377 {
3378# ifdef USE_GNUTLS
3379 log_write(0, LOG_PANIC_DIE|LOG_CONFIG,
a053d125 3380 "openssl_options is set but we're using GnuTLS");
77bb000f
PP
3381# else
3382 long dummy;
3383 if (!(tls_openssl_options_parse(openssl_options, &dummy)))
3384 log_write(0, LOG_PANIC_DIE|LOG_CONFIG,
a053d125 3385 "openssl_options parse error: %s", openssl_options);
77bb000f
PP
3386# endif
3387 }
2d571266
JH
3388
3389if (gnutls_require_kx || gnutls_require_mac || gnutls_require_proto)
3390 log_write(0, LOG_MAIN, "WARNING: main options"
3391 " gnutls_require_kx, gnutls_require_mac and gnutls_require_protocols"
3392 " are obsolete\n");
32d07012 3393#endif /*SUPPORT_TLS*/
059ec3d9
PH
3394}
3395
3396
3397
3398/*************************************************
3399* Initialize one driver *
3400*************************************************/
3401
3402/* This is called once the driver's generic options, if any, have been read.
3403We can now find the driver, set up defaults for the private options, and
3404unset any "set" bits in the private options table (which might have been
3405set by another incarnation of the same driver).
3406
3407Arguments:
3408 d pointer to driver instance block, with generic
3409 options filled in
3410 drivers_available vector of available drivers
3411 size_of_info size of each block in drivers_available
3412 class class of driver, for error message
3413
3414Returns: pointer to the driver info block
3415*/
3416
3417static driver_info *
3418init_driver(driver_instance *d, driver_info *drivers_available,
3419 int size_of_info, uschar *class)
3420{
3421driver_info *dd;
3422
3423for (dd = drivers_available; dd->driver_name[0] != 0;
3424 dd = (driver_info *)(((uschar *)dd) + size_of_info))
3425 {
3426 if (Ustrcmp(d->driver_name, dd->driver_name) == 0)
3427 {
3428 int i;
3429 int len = dd->options_len;
3430 d->info = dd;
3431 d->options_block = store_get(len);
3432 memcpy(d->options_block, dd->options_block, len);
3433 for (i = 0; i < *(dd->options_count); i++)
3434 dd->options[i].type &= ~opt_set;
3435 return dd;
3436 }
3437 }
3438
3439log_write(0, LOG_PANIC_DIE|LOG_CONFIG_IN,
3440 "%s %s: cannot find %s driver \"%s\"", class, d->name, class, d->driver_name);
3441
3442return NULL; /* never obeyed */
3443}
3444
3445
3446
3447
3448/*************************************************
3449* Initialize driver list *
3450*************************************************/
3451
3452/* This function is called for routers, transports, and authentication
3453mechanisms. It reads the data from the current point in the configuration file
3454up to the end of the section, and sets up a chain of instance blocks according
3455to the file's contents. The file will already have been opened by a call to
3456readconf_main, and must be left open for subsequent reading of further data.
3457
3458Any errors cause a panic crash. Note that the blocks with names driver_info and
3459driver_instance must map the first portions of all the _info and _instance
3460blocks for this shared code to work.
3461
3462Arguments:
3463 class "router", "transport", or "authenticator"
3464 anchor &routers, &transports, &auths
3465 drivers_available available drivers
3466 size_of_info size of each info block
3467 instance_default points to default data for an instance
3468 instance_size size of instance block
3469 driver_optionlist generic option list
3470 driver_optionlist_count count of generic option list
3471
3472Returns: nothing
3473*/
3474
3475void
3476readconf_driver_init(
3477 uschar *class,
3478 driver_instance **anchor,
3479 driver_info *drivers_available,
3480 int size_of_info,
3481 void *instance_default,
3482 int instance_size,
3483 optionlist *driver_optionlist,
3484 int driver_optionlist_count)
3485{
3486driver_instance **p = anchor;
3487driver_instance *d = NULL;
3488uschar *buffer;
3489
059ec3d9
PH
3490while ((buffer = get_config_line()) != NULL)
3491 {
3492 uschar name[64];
cf00dad6 3493 uschar *s;
059ec3d9 3494
cf00dad6
PH
3495 /* Read the first name on the line and test for the start of a new driver. A
3496 macro definition indicates the end of the previous driver. If this isn't the
3497 start of a new driver, the line will be re-read. */
059ec3d9 3498
cf00dad6
PH
3499 s = readconf_readname(name, sizeof(name), buffer);
3500
3501 /* Handle macro definition, first finishing off the initialization of the
3502 previous driver, if any. */
3503
3504 if (isupper(*name) && *s == '=')
3505 {
3506 if (d != NULL)
3507 {
3508 if (d->driver_name == NULL)
3509 log_write(0, LOG_PANIC_DIE|LOG_CONFIG,
3510 "no driver defined for %s \"%s\"", class, d->name);
3511 (d->info->init)(d);
3512 d = NULL;
3513 }
3514 read_macro_assignment(buffer);
3515 continue;
3516 }
059ec3d9
PH
3517
3518 /* If the line starts with a name terminated by a colon, we are at the
3519 start of the definition of a new driver. The rest of the line must be
3520 blank. */
3521
3522 if (*s++ == ':')
3523 {
3524 int i;
3525
3526 /* Finish off initializing the previous driver. */
3527
3528 if (d != NULL)
3529 {
3530 if (d->driver_name == NULL)
3531 log_write(0, LOG_PANIC_DIE|LOG_CONFIG,
3532 "no driver defined for %s \"%s\"", class, d->name);
3533 (d->info->init)(d);
3534 }
3535
3536 /* Check that we haven't already got a driver of this name */
3537
3538 for (d = *anchor; d != NULL; d = d->next)
3539 if (Ustrcmp(name, d->name) == 0)
3540 log_write(0, LOG_PANIC_DIE|LOG_CONFIG,
3541 "there are two %ss called \"%s\"", class, name);
3542
3543 /* Set up a new driver instance data block on the chain, with
3544 its default values installed. */
3545
3546 d = store_get(instance_size);
3547 memcpy(d, instance_default, instance_size);
3548 *p = d;
3549 p = &(d->next);
3550 d->name = string_copy(name);
3551
3552 /* Clear out the "set" bits in the generic options */
3553
3554 for (i = 0; i < driver_optionlist_count; i++)
3555 driver_optionlist[i].type &= ~opt_set;
3556
3557 /* Check nothing more on this line, then do the next loop iteration. */
3558
3559 while (isspace(*s)) s++;
3560 if (*s != 0) extra_chars_error(s, US"driver name ", name, US"");
3561 continue;
3562 }
3563
cf00dad6
PH
3564 /* Not the start of a new driver. Give an error if we have not set up a
3565 current driver yet. */
059ec3d9
PH
3566
3567 if (d == NULL) log_write(0, LOG_PANIC_DIE|LOG_CONFIG_IN,
3568 "%s name missing", class);
3569
3570 /* First look to see if this is a generic option; if it is "driver",
3571 initialize the driver. If is it not a generic option, we can look for a
3572 private option provided that the driver has been previously set up. */
3573
3574 if (readconf_handle_option(buffer, driver_optionlist,
3575 driver_optionlist_count, d, NULL))
3576 {
3577 if (d->info == NULL && d->driver_name != NULL)
3578 init_driver(d, drivers_available, size_of_info, class);
3579 }
3580
3581 /* Handle private options - pass the generic block because some may
3582 live therein. A flag with each option indicates if it is in the public
3583 block. */
3584
3585 else if (d->info != NULL)
3586 {
3587 readconf_handle_option(buffer, d->info->options,
3588 *(d->info->options_count), d, US"option \"%s\" unknown");
3589 }
3590
3591 /* The option is not generic and the driver name has not yet been given. */
3592
3593 else log_write(0, LOG_PANIC_DIE|LOG_CONFIG_IN, "option \"%s\" unknown "
3594 "(\"driver\" must be specified before any private options)", name);
3595 }
3596
3597/* Run the initialization function for the final driver. */
3598
3599if (d != NULL)
3600 {
3601 if (d->driver_name == NULL)
3602 log_write(0, LOG_PANIC_DIE|LOG_CONFIG,
3603 "no driver defined for %s \"%s\"", class, d->name);
3604 (d->info->init)(d);
3605 }
3606}
3607
3608
3609
3610/*************************************************
3611* Check driver dependency *
3612*************************************************/
3613
3614/* This function is passed a driver instance and a string. It checks whether
3615any of the string options for the driver contains the given string as an
3616expansion variable.
3617
3618Arguments:
3619 d points to a driver instance block
3620 s the string to search for
3621
3622Returns: TRUE if a dependency is found
3623*/
3624
3625BOOL
3626readconf_depends(driver_instance *d, uschar *s)
3627{
3628int count = *(d->info->options_count);
3629optionlist *ol;
3630uschar *ss;
3631
3632for (ol = d->info->options; ol < d->info->options + count; ol++)
3633 {
3634 void *options_block;
3635 uschar *value;
3636 int type = ol->type & opt_mask;
3637 if (type != opt_stringptr) continue;
3638 options_block = ((ol->type & opt_public) == 0)? d->options_block : (void *)d;
3639 value = *(uschar **)((uschar *)options_block + (long int)(ol->value));
3640 if (value != NULL && (ss = Ustrstr(value, s)) != NULL)
3641 {
3642 if (ss <= value || (ss[-1] != '$' && ss[-1] != '{') ||
3643 isalnum(ss[Ustrlen(s)])) continue;
3644 DEBUG(D_transport) debug_printf("driver %s: \"%s\" option depends on %s\n",
3645 d->name, ol->name, s);
3646 return TRUE;
3647 }
3648 }
3649
3650DEBUG(D_transport) debug_printf("driver %s does not depend on %s\n", d->name, s);
3651return FALSE;
3652}
3653
3654
3655
3656
3657/*************************************************
3658* Decode an error type for retries *
3659*************************************************/
3660
3661/* This function is global because it is also called from the main
3662program when testing retry information. It decodes strings such as "quota_7d"
3663into numerical error codes.
3664
3665Arguments:
3666 pp points to start of text
3667 p points past end of text
3668 basic_errno points to an int to receive the main error number
3669 more_errno points to an int to receive the secondary error data
3670
3671Returns: NULL if decoded correctly; else points to error text
3672*/
3673
3674uschar *
3675readconf_retry_error(uschar *pp, uschar *p, int *basic_errno, int *more_errno)
3676{
3677int len;
3678uschar *q = pp;
3679while (q < p && *q != '_') q++;
3680len = q - pp;
3681
3682if (len == 5 && strncmpic(pp, US"quota", len) == 0)
3683 {
3684 *basic_errno = ERRNO_EXIMQUOTA;
3685 if (q != p && (*more_errno = readconf_readtime(q+1, *p, FALSE)) < 0)
3686 return US"bad time value";
3687 }
3688
3689else if (len == 7 && strncmpic(pp, US"refused", len) == 0)
3690 {
3691 *basic_errno = ECONNREFUSED;
3692 if (q != p)
3693 {
3694 if (strncmpic(q+1, US"MX", p-q-1) == 0) *more_errno = 'M';
3695 else if (strncmpic(q+1, US"A", p-q-1) == 0) *more_errno = 'A';
3696 else return US"A or MX expected after \"refused\"";
3697 }
3698 }
3699
3700else if (len == 7 && strncmpic(pp, US"timeout", len) == 0)
3701 {
3702 *basic_errno = ETIMEDOUT;
3703 if (q != p)
3704 {
3705 int i;
3706 int xlen = p - q - 1;
3707 uschar *x = q + 1;
3708
3709 static uschar *extras[] =
3710 { US"A", US"MX", US"connect", US"connect_A", US"connect_MX" };
3711 static int values[] =
3712 { 'A', 'M', RTEF_CTOUT, RTEF_CTOUT|'A', RTEF_CTOUT|'M' };
3713
3714 for (i = 0; i < sizeof(extras)/sizeof(uschar *); i++)
3715 {
3716 if (strncmpic(x, extras[i], xlen) == 0)
3717 {
3718 *more_errno = values[i];
3719 break;
3720 }
3721 }
3722
3723 if (i >= sizeof(extras)/sizeof(uschar *))
3724 {
3725 if (strncmpic(x, US"DNS", xlen) == 0)
3726 {
3727 log_write(0, LOG_MAIN|LOG_PANIC, "\"timeout_dns\" is no longer "
3728 "available in retry rules (it has never worked) - treated as "
3729 "\"timeout\"");
3730 }
3731 else return US"\"A\", \"MX\", or \"connect\" expected after \"timeout\"";
3732 }
3733 }
3734 }
3735
e97957bc
PH
3736else if (strncmpic(pp, US"mail_4", 6) == 0 ||
3737 strncmpic(pp, US"rcpt_4", 6) == 0 ||
3738 strncmpic(pp, US"data_4", 6) == 0)
059ec3d9
PH
3739 {
3740 BOOL bad = FALSE;
3741 int x = 255; /* means "any 4xx code" */
3742 if (p != pp + 8) bad = TRUE; else
3743 {
3744 int a = pp[6], b = pp[7];
3745 if (isdigit(a))
3746 {
3747 x = (a - '0') * 10;
3748 if (isdigit(b)) x += b - '0';
3749 else if (b == 'x') x += 100;
3750 else bad = TRUE;
3751 }
3752 else if (a != 'x' || b != 'x') bad = TRUE;
3753 }
3754
e97957bc
PH
3755 if (bad)
3756 return string_sprintf("%.4s_4 must be followed by xx, dx, or dd, where "
3757 "x is literal and d is any digit", pp);
059ec3d9 3758
e97957bc
PH
3759 *basic_errno = (*pp == 'm')? ERRNO_MAIL4XX :
3760 (*pp == 'r')? ERRNO_RCPT4XX : ERRNO_DATA4XX;
059ec3d9
PH
3761 *more_errno = x << 8;
3762 }
3763
3764else if (len == 4 && strncmpic(pp, US"auth", len) == 0 &&
3765 strncmpic(q+1, US"failed", p-q-1) == 0)
059ec3d9 3766 *basic_errno = ERRNO_AUTHFAIL;
e97957bc 3767
48da4259 3768else if (strncmpic(pp, US"lost_connection", p - pp) == 0)
e97957bc
PH
3769 *basic_errno = ERRNO_SMTPCLOSED;
3770
48da4259 3771else if (strncmpic(pp, US"tls_required", p - pp) == 0)
e97957bc 3772 *basic_errno = ERRNO_TLSREQUIRED;
059ec3d9
PH
3773
3774else if (len != 1 || Ustrncmp(pp, "*", 1) != 0)
ef840681 3775 return string_sprintf("unknown or malformed retry error \"%.*s\"", (int) (p-pp), pp);
059ec3d9
PH
3776
3777return NULL;
3778}
3779
3780
3781
3782
3783/*************************************************
3784* Read retry information *
3785*************************************************/
3786
3787/* Each line of retry information contains:
3788
3789. A domain name pattern or an address pattern;
3790
3791. An error name, possibly with additional data, or *;
3792
3793. An optional sequence of retry items, each consisting of an identifying
3794 letter, a cutoff time, and optional parameters.
3795
3796All this is decoded and placed into a control block. */
3797
3798
3799/* Subroutine to read an argument, preceded by a comma and terminated
3800by comma, semicolon, whitespace, or newline. The types are: 0 = time value,
38011 = fixed point number (returned *1000).
3802
3803Arguments:
3804 paddr pointer to pointer to current character; updated
3805 type 0 => read a time; 1 => read a fixed point number
3806
3807Returns: time in seconds or fixed point number * 1000
3808*/
3809
3810static int
3811retry_arg(uschar **paddr, int type)
3812{
3813uschar *p = *paddr;
3814uschar *pp;
3815
3816if (*p++ != ',') log_write(0, LOG_PANIC_DIE|LOG_CONFIG_IN, "comma expected");
3817
3818while (isspace(*p)) p++;
3819pp = p;
3820while (isalnum(*p) || (type == 1 && *p == '.')) p++;
3821
3822if (*p != 0 && !isspace(*p) && *p != ',' && *p != ';')
3823 log_write(0, LOG_PANIC_DIE|LOG_CONFIG_IN, "comma or semicolon expected");
3824
3825*paddr = p;
3826switch (type)
3827 {
3828 case 0:
3829 return readconf_readtime(pp, *p, FALSE);
3830 case 1:
3831 return readconf_readfixed(pp, *p);
3832 }
3833return 0; /* Keep picky compilers happy */
3834}
3835
3836/* The function proper */
3837
3838void
3839readconf_retries(void)
3840{
3841retry_config **chain = &retries;
3842retry_config *next;
3843uschar *p;
3844
3845while ((p = get_config_line()) != NULL)
3846 {
3847 retry_rule **rchain;
3848 uschar *pp, *error;
3849
3850 next = store_get(sizeof(retry_config));
3851 next->next = NULL;
3852 *chain = next;
3853 chain = &(next->next);
3854 next->basic_errno = next->more_errno = 0;
3855 next->senders = NULL;
3856 next->rules = NULL;
3857 rchain = &(next->rules);
3858
3859 next->pattern = string_dequote(&p);
3860 while (isspace(*p)) p++;
3861 pp = p;
3862 while (mac_isgraph(*p)) p++;
3863 if (p - pp <= 0) log_write(0, LOG_PANIC_DIE|LOG_CONFIG_IN,
41eff010 3864 "missing error type in retry rule");
059ec3d9
PH
3865
3866 /* Test error names for things we understand. */
3867
3868 if ((error = readconf_retry_error(pp, p, &(next->basic_errno),
3869 &(next->more_errno))) != NULL)
3870 log_write(0, LOG_PANIC_DIE|LOG_CONFIG_IN, "%s", error);
3871
3872 /* There may be an optional address list of senders to be used as another
3873 constraint on the rule. This was added later, so the syntax is a bit of a
3874 fudge. Anything that is not a retry rule starting "F," or "G," is treated as
3875 an address list. */
3876
3877 while (isspace(*p)) p++;
3878 if (Ustrncmp(p, "senders", 7) == 0)
3879 {
3880 p += 7;
3881 while (isspace(*p)) p++;
3882 if (*p++ != '=') log_write(0, LOG_PANIC_DIE|LOG_CONFIG_IN,
3883 "\"=\" expected after \"senders\" in retry rule");
3884 while (isspace(*p)) p++;
3885 next->senders = string_dequote(&p);
3886 }
3887
3888 /* Now the retry rules. Keep the maximum timeout encountered. */
3889
3890 while (isspace(*p)) p++;
3891
3892 while (*p != 0)
3893 {
3894 retry_rule *rule = store_get(sizeof(retry_rule));
3895 *rchain = rule;
3896 rchain = &(rule->next);
3897 rule->next = NULL;
3898 rule->rule = toupper(*p++);
3899 rule->timeout = retry_arg(&p, 0);
3900 if (rule->timeout > retry_maximum_timeout)
3901 retry_maximum_timeout = rule->timeout;
3902
3903 switch (rule->rule)
3904 {
3905 case 'F': /* Fixed interval */
3906 rule->p1 = retry_arg(&p, 0);
3907 break;
3908
3909 case 'G': /* Geometrically increasing intervals */
6af56900 3910 case 'H': /* Ditto, but with randomness */
059ec3d9
PH
3911 rule->p1 = retry_arg(&p, 0);
3912 rule->p2 = retry_arg(&p, 1);
3913 break;
3914
3915 default:
3916 log_write(0, LOG_PANIC_DIE|LOG_CONFIG_IN, "unknown retry rule letter");
3917 break;
3918 }
3919
3920 if (rule->timeout <= 0 || rule->p1 <= 0 ||
6af56900 3921 (rule->rule != 'F' && rule->p2 < 1000))
059ec3d9
PH
3922 log_write(0, LOG_PANIC_DIE|LOG_CONFIG_IN,
3923 "bad parameters for retry rule");
3924
3925 while (isspace(*p)) p++;
3926 if (*p == ';')
3927 {
3928 p++;
3929 while (isspace(*p)) p++;
3930 }
3931 else if (*p != 0)
3932 log_write(0, LOG_PANIC_DIE|LOG_CONFIG_IN, "semicolon expected");
3933 }
3934 }
3935}
3936
3937
3938
3939/*************************************************
3940* Initialize authenticators *
3941*************************************************/
3942
3943/* Read the authenticators section of the configuration file.
3944
3945Arguments: none
3946Returns: nothing
3947*/
3948
3949static void