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