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