*************************************************/
/* Copyright (c) University of Cambridge 1995 - 2018 */
+/* Copyright (c) The Exim Maintainers 2020 - 2021 */
/* See the file NOTICE for conditions of use and distribution. */
/* Functions for reading the configuration file, and for displaying
must be in alphabetic order because it is searched by binary chop. */
static optionlist optionlist_config[] = {
- { "*set_exim_group", opt_bool|opt_hidden, &exim_gid_set },
- { "*set_exim_user", opt_bool|opt_hidden, &exim_uid_set },
- { "*set_system_filter_group", opt_bool|opt_hidden, &system_filter_gid_set },
- { "*set_system_filter_user", opt_bool|opt_hidden, &system_filter_uid_set },
- { "accept_8bitmime", opt_bool, &accept_8bitmime },
- { "acl_not_smtp", opt_stringptr, &acl_not_smtp },
+ { "*set_exim_group", opt_bool|opt_hidden, {&exim_gid_set} },
+ { "*set_exim_user", opt_bool|opt_hidden, {&exim_uid_set} },
+ { "*set_system_filter_group", opt_bool|opt_hidden, {&system_filter_gid_set} },
+ { "*set_system_filter_user", opt_bool|opt_hidden, {&system_filter_uid_set} },
+ { "accept_8bitmime", opt_bool, {&accept_8bitmime} },
+ { "acl_not_smtp", opt_stringptr, {&acl_not_smtp} },
#ifdef WITH_CONTENT_SCAN
- { "acl_not_smtp_mime", opt_stringptr, &acl_not_smtp_mime },
+ { "acl_not_smtp_mime", opt_stringptr, {&acl_not_smtp_mime} },
#endif
- { "acl_not_smtp_start", opt_stringptr, &acl_not_smtp_start },
- { "acl_smtp_auth", opt_stringptr, &acl_smtp_auth },
- { "acl_smtp_connect", opt_stringptr, &acl_smtp_connect },
- { "acl_smtp_data", opt_stringptr, &acl_smtp_data },
+ { "acl_not_smtp_start", opt_stringptr, {&acl_not_smtp_start} },
+ { "acl_smtp_auth", opt_stringptr, {&acl_smtp_auth} },
+ { "acl_smtp_connect", opt_stringptr, {&acl_smtp_connect} },
+ { "acl_smtp_data", opt_stringptr, {&acl_smtp_data} },
#ifndef DISABLE_PRDR
- { "acl_smtp_data_prdr", opt_stringptr, &acl_smtp_data_prdr },
+ { "acl_smtp_data_prdr", opt_stringptr, {&acl_smtp_data_prdr} },
#endif
#ifndef DISABLE_DKIM
- { "acl_smtp_dkim", opt_stringptr, &acl_smtp_dkim },
+ { "acl_smtp_dkim", opt_stringptr, {&acl_smtp_dkim} },
#endif
- { "acl_smtp_etrn", opt_stringptr, &acl_smtp_etrn },
- { "acl_smtp_expn", opt_stringptr, &acl_smtp_expn },
- { "acl_smtp_helo", opt_stringptr, &acl_smtp_helo },
- { "acl_smtp_mail", opt_stringptr, &acl_smtp_mail },
- { "acl_smtp_mailauth", opt_stringptr, &acl_smtp_mailauth },
+ { "acl_smtp_etrn", opt_stringptr, {&acl_smtp_etrn} },
+ { "acl_smtp_expn", opt_stringptr, {&acl_smtp_expn} },
+ { "acl_smtp_helo", opt_stringptr, {&acl_smtp_helo} },
+ { "acl_smtp_mail", opt_stringptr, {&acl_smtp_mail} },
+ { "acl_smtp_mailauth", opt_stringptr, {&acl_smtp_mailauth} },
#ifdef WITH_CONTENT_SCAN
- { "acl_smtp_mime", opt_stringptr, &acl_smtp_mime },
+ { "acl_smtp_mime", opt_stringptr, {&acl_smtp_mime} },
#endif
- { "acl_smtp_notquit", opt_stringptr, &acl_smtp_notquit },
- { "acl_smtp_predata", opt_stringptr, &acl_smtp_predata },
- { "acl_smtp_quit", opt_stringptr, &acl_smtp_quit },
- { "acl_smtp_rcpt", opt_stringptr, &acl_smtp_rcpt },
+ { "acl_smtp_notquit", opt_stringptr, {&acl_smtp_notquit} },
+ { "acl_smtp_predata", opt_stringptr, {&acl_smtp_predata} },
+ { "acl_smtp_quit", opt_stringptr, {&acl_smtp_quit} },
+ { "acl_smtp_rcpt", opt_stringptr, {&acl_smtp_rcpt} },
#ifndef DISABLE_TLS
- { "acl_smtp_starttls", opt_stringptr, &acl_smtp_starttls },
+ { "acl_smtp_starttls", opt_stringptr, {&acl_smtp_starttls} },
#endif
- { "acl_smtp_vrfy", opt_stringptr, &acl_smtp_vrfy },
- { "add_environment", opt_stringptr, &add_environment },
- { "admin_groups", opt_gidlist, &admin_groups },
- { "allow_domain_literals", opt_bool, &allow_domain_literals },
- { "allow_mx_to_ip", opt_bool, &allow_mx_to_ip },
- { "allow_utf8_domains", opt_bool, &allow_utf8_domains },
- { "auth_advertise_hosts", opt_stringptr, &auth_advertise_hosts },
- { "auto_thaw", opt_time, &auto_thaw },
+ { "acl_smtp_vrfy", opt_stringptr, {&acl_smtp_vrfy} },
+ { "add_environment", opt_stringptr, {&add_environment} },
+ { "admin_groups", opt_gidlist, {&admin_groups} },
+ { "allow_domain_literals", opt_bool, {&allow_domain_literals} },
+#ifdef ALLOW_INSECURE_TAINTED_DATA
+ { "allow_insecure_tainted_data", opt_bool, {&allow_insecure_tainted_data} },
+#endif
+ { "allow_mx_to_ip", opt_bool, {&allow_mx_to_ip} },
+ { "allow_utf8_domains", opt_bool, {&allow_utf8_domains} },
+ { "auth_advertise_hosts", opt_stringptr, {&auth_advertise_hosts} },
+ { "auto_thaw", opt_time, {&auto_thaw} },
#ifdef WITH_CONTENT_SCAN
- { "av_scanner", opt_stringptr, &av_scanner },
+ { "av_scanner", opt_stringptr, {&av_scanner} },
#endif
- { "bi_command", opt_stringptr, &bi_command },
+ { "bi_command", opt_stringptr, {&bi_command} },
#ifdef EXPERIMENTAL_BRIGHTMAIL
- { "bmi_config_file", opt_stringptr, &bmi_config_file },
+ { "bmi_config_file", opt_stringptr, {&bmi_config_file} },
#endif
- { "bounce_message_file", opt_stringptr, &bounce_message_file },
- { "bounce_message_text", opt_stringptr, &bounce_message_text },
- { "bounce_return_body", opt_bool, &bounce_return_body },
- { "bounce_return_linesize_limit", opt_mkint, &bounce_return_linesize_limit },
- { "bounce_return_message", opt_bool, &bounce_return_message },
- { "bounce_return_size_limit", opt_mkint, &bounce_return_size_limit },
- { "bounce_sender_authentication",opt_stringptr,&bounce_sender_authentication },
- { "callout_domain_negative_expire", opt_time, &callout_cache_domain_negative_expire },
- { "callout_domain_positive_expire", opt_time, &callout_cache_domain_positive_expire },
- { "callout_negative_expire", opt_time, &callout_cache_negative_expire },
- { "callout_positive_expire", opt_time, &callout_cache_positive_expire },
- { "callout_random_local_part",opt_stringptr, &callout_random_local_part },
- { "check_log_inodes", opt_int, &check_log_inodes },
- { "check_log_space", opt_Kint, &check_log_space },
- { "check_rfc2047_length", opt_bool, &check_rfc2047_length },
- { "check_spool_inodes", opt_int, &check_spool_inodes },
- { "check_spool_space", opt_Kint, &check_spool_space },
- { "chunking_advertise_hosts", opt_stringptr, &chunking_advertise_hosts },
- { "commandline_checks_require_admin", opt_bool,&commandline_checks_require_admin },
- { "daemon_smtp_port", opt_stringptr|opt_hidden, &daemon_smtp_port },
- { "daemon_smtp_ports", opt_stringptr, &daemon_smtp_port },
- { "daemon_startup_retries", opt_int, &daemon_startup_retries },
- { "daemon_startup_sleep", opt_time, &daemon_startup_sleep },
+ { "bounce_message_file", opt_stringptr, {&bounce_message_file} },
+ { "bounce_message_text", opt_stringptr, {&bounce_message_text} },
+ { "bounce_return_body", opt_bool, {&bounce_return_body} },
+ { "bounce_return_linesize_limit", opt_mkint, {&bounce_return_linesize_limit} },
+ { "bounce_return_message", opt_bool, {&bounce_return_message} },
+ { "bounce_return_size_limit", opt_mkint, {&bounce_return_size_limit} },
+ { "bounce_sender_authentication",opt_stringptr,{&bounce_sender_authentication} },
+ { "callout_domain_negative_expire", opt_time, {&callout_cache_domain_negative_expire} },
+ { "callout_domain_positive_expire", opt_time, {&callout_cache_domain_positive_expire} },
+ { "callout_negative_expire", opt_time, {&callout_cache_negative_expire} },
+ { "callout_positive_expire", opt_time, {&callout_cache_positive_expire} },
+ { "callout_random_local_part",opt_stringptr, {&callout_random_local_part} },
+ { "check_log_inodes", opt_int, {&check_log_inodes} },
+ { "check_log_space", opt_Kint, {&check_log_space} },
+ { "check_rfc2047_length", opt_bool, {&check_rfc2047_length} },
+ { "check_spool_inodes", opt_int, {&check_spool_inodes} },
+ { "check_spool_space", opt_Kint, {&check_spool_space} },
+ { "chunking_advertise_hosts", opt_stringptr, {&chunking_advertise_hosts} },
+ { "commandline_checks_require_admin", opt_bool,{&commandline_checks_require_admin} },
+ { "daemon_smtp_port", opt_stringptr|opt_hidden, {&daemon_smtp_port} },
+ { "daemon_smtp_ports", opt_stringptr, {&daemon_smtp_port} },
+ { "daemon_startup_retries", opt_int, {&daemon_startup_retries} },
+ { "daemon_startup_sleep", opt_time, {&daemon_startup_sleep} },
#ifdef EXPERIMENTAL_DCC
- { "dcc_direct_add_header", opt_bool, &dcc_direct_add_header },
- { "dccifd_address", opt_stringptr, &dccifd_address },
- { "dccifd_options", opt_stringptr, &dccifd_options },
+ { "dcc_direct_add_header", opt_bool, {&dcc_direct_add_header} },
+ { "dccifd_address", opt_stringptr, {&dccifd_address} },
+ { "dccifd_options", opt_stringptr, {&dccifd_options} },
#endif
- { "debug_store", opt_bool, &debug_store },
- { "delay_warning", opt_timelist, &delay_warning },
- { "delay_warning_condition", opt_stringptr, &delay_warning_condition },
- { "deliver_drop_privilege", opt_bool, &deliver_drop_privilege },
- { "deliver_queue_load_max", opt_fixed, &deliver_queue_load_max },
- { "delivery_date_remove", opt_bool, &delivery_date_remove },
+ { "debug_store", opt_bool, {&debug_store} },
+ { "delay_warning", opt_timelist, {&delay_warning} },
+ { "delay_warning_condition", opt_stringptr, {&delay_warning_condition} },
+ { "deliver_drop_privilege", opt_bool, {&deliver_drop_privilege} },
+ { "deliver_queue_load_max", opt_fixed, {&deliver_queue_load_max} },
+ { "delivery_date_remove", opt_bool, {&delivery_date_remove} },
#ifdef ENABLE_DISABLE_FSYNC
- { "disable_fsync", opt_bool, &disable_fsync },
+ { "disable_fsync", opt_bool, {&disable_fsync} },
#endif
- { "disable_ipv6", opt_bool, &disable_ipv6 },
+ { "disable_ipv6", opt_bool, {&disable_ipv6} },
#ifndef DISABLE_DKIM
- { "dkim_verify_hashes", opt_stringptr, &dkim_verify_hashes },
- { "dkim_verify_keytypes", opt_stringptr, &dkim_verify_keytypes },
- { "dkim_verify_minimal", opt_bool, &dkim_verify_minimal },
- { "dkim_verify_signers", opt_stringptr, &dkim_verify_signers },
+ { "dkim_verify_hashes", opt_stringptr, {&dkim_verify_hashes} },
+ { "dkim_verify_keytypes", opt_stringptr, {&dkim_verify_keytypes} },
+ { "dkim_verify_min_keysizes", opt_stringptr, {&dkim_verify_min_keysizes} },
+ { "dkim_verify_minimal", opt_bool, {&dkim_verify_minimal} },
+ { "dkim_verify_signers", opt_stringptr, {&dkim_verify_signers} },
#endif
-#ifdef EXPERIMENTAL_DMARC
- { "dmarc_forensic_sender", opt_stringptr, &dmarc_forensic_sender },
- { "dmarc_history_file", opt_stringptr, &dmarc_history_file },
- { "dmarc_tld_file", opt_stringptr, &dmarc_tld_file },
+#ifdef SUPPORT_DMARC
+ { "dmarc_forensic_sender", opt_stringptr, {&dmarc_forensic_sender} },
+ { "dmarc_history_file", opt_stringptr, {&dmarc_history_file} },
+ { "dmarc_tld_file", opt_stringptr, {&dmarc_tld_file} },
#endif
- { "dns_again_means_nonexist", opt_stringptr, &dns_again_means_nonexist },
- { "dns_check_names_pattern", opt_stringptr, &check_dns_names_pattern },
- { "dns_cname_loops", opt_int, &dns_cname_loops },
- { "dns_csa_search_limit", opt_int, &dns_csa_search_limit },
- { "dns_csa_use_reverse", opt_bool, &dns_csa_use_reverse },
- { "dns_dnssec_ok", opt_int, &dns_dnssec_ok },
- { "dns_ipv4_lookup", opt_stringptr, &dns_ipv4_lookup },
- { "dns_retrans", opt_time, &dns_retrans },
- { "dns_retry", opt_int, &dns_retry },
- { "dns_trust_aa", opt_stringptr, &dns_trust_aa },
- { "dns_use_edns0", opt_int, &dns_use_edns0 },
+ { "dns_again_means_nonexist", opt_stringptr, {&dns_again_means_nonexist} },
+ { "dns_check_names_pattern", opt_stringptr, {&check_dns_names_pattern} },
+ { "dns_cname_loops", opt_int, {&dns_cname_loops} },
+ { "dns_csa_search_limit", opt_int, {&dns_csa_search_limit} },
+ { "dns_csa_use_reverse", opt_bool, {&dns_csa_use_reverse} },
+ { "dns_dnssec_ok", opt_int, {&dns_dnssec_ok} },
+ { "dns_ipv4_lookup", opt_stringptr, {&dns_ipv4_lookup} },
+ { "dns_retrans", opt_time, {&dns_retrans} },
+ { "dns_retry", opt_int, {&dns_retry} },
+ { "dns_trust_aa", opt_stringptr, {&dns_trust_aa} },
+ { "dns_use_edns0", opt_int, {&dns_use_edns0} },
/* This option is now a no-op, retained for compatibility */
- { "drop_cr", opt_bool, &drop_cr },
+ { "drop_cr", opt_bool, {&drop_cr} },
/*********************************************************/
- { "dsn_advertise_hosts", opt_stringptr, &dsn_advertise_hosts },
- { "dsn_from", opt_stringptr, &dsn_from },
- { "envelope_to_remove", opt_bool, &envelope_to_remove },
- { "errors_copy", opt_stringptr, &errors_copy },
- { "errors_reply_to", opt_stringptr, &errors_reply_to },
+ { "dsn_advertise_hosts", opt_stringptr, {&dsn_advertise_hosts} },
+ { "dsn_from", opt_stringptr, {&dsn_from} },
+ { "envelope_to_remove", opt_bool, {&envelope_to_remove} },
+ { "errors_copy", opt_stringptr, {&errors_copy} },
+ { "errors_reply_to", opt_stringptr, {&errors_reply_to} },
#ifndef DISABLE_EVENT
- { "event_action", opt_stringptr, &event_action },
+ { "event_action", opt_stringptr, {&event_action} },
#endif
- { "exim_group", opt_gid, &exim_gid },
- { "exim_path", opt_stringptr, &exim_path },
- { "exim_user", opt_uid, &exim_uid },
- { "exim_version", opt_stringptr, &version_string },
- { "extra_local_interfaces", opt_stringptr, &extra_local_interfaces },
- { "extract_addresses_remove_arguments", opt_bool, &extract_addresses_remove_arguments },
- { "finduser_retries", opt_int, &finduser_retries },
- { "freeze_tell", opt_stringptr, &freeze_tell },
- { "gecos_name", opt_stringptr, &gecos_name },
- { "gecos_pattern", opt_stringptr, &gecos_pattern },
+ { "exim_group", opt_gid, {&exim_gid} },
+ { "exim_path", opt_stringptr, {&exim_path} },
+ { "exim_user", opt_uid, {&exim_uid} },
+ { "exim_version", opt_stringptr, {&version_string} },
+ { "extra_local_interfaces", opt_stringptr, {&extra_local_interfaces} },
+ { "extract_addresses_remove_arguments", opt_bool, {&extract_addresses_remove_arguments} },
+ { "finduser_retries", opt_int, {&finduser_retries} },
+ { "freeze_tell", opt_stringptr, {&freeze_tell} },
+ { "gecos_name", opt_stringptr, {&gecos_name} },
+ { "gecos_pattern", opt_stringptr, {&gecos_pattern} },
#ifndef DISABLE_TLS
- { "gnutls_allow_auto_pkcs11", opt_bool, &gnutls_allow_auto_pkcs11 },
- { "gnutls_compat_mode", opt_bool, &gnutls_compat_mode },
+ { "gnutls_allow_auto_pkcs11", opt_bool, {&gnutls_allow_auto_pkcs11} },
+ { "gnutls_compat_mode", opt_bool, {&gnutls_compat_mode} },
#endif
- { "header_line_maxsize", opt_int, &header_line_maxsize },
- { "header_maxsize", opt_int, &header_maxsize },
- { "headers_charset", opt_stringptr, &headers_charset },
- { "helo_accept_junk_hosts", opt_stringptr, &helo_accept_junk_hosts },
- { "helo_allow_chars", opt_stringptr, &helo_allow_chars },
- { "helo_lookup_domains", opt_stringptr, &helo_lookup_domains },
- { "helo_try_verify_hosts", opt_stringptr, &helo_try_verify_hosts },
- { "helo_verify_hosts", opt_stringptr, &helo_verify_hosts },
- { "hold_domains", opt_stringptr, &hold_domains },
- { "host_lookup", opt_stringptr, &host_lookup },
- { "host_lookup_order", opt_stringptr, &host_lookup_order },
- { "host_reject_connection", opt_stringptr, &host_reject_connection },
- { "hosts_connection_nolog", opt_stringptr, &hosts_connection_nolog },
+ { "header_line_maxsize", opt_int, {&header_line_maxsize} },
+ { "header_maxsize", opt_int, {&header_maxsize} },
+ { "headers_charset", opt_stringptr, {&headers_charset} },
+ { "helo_accept_junk_hosts", opt_stringptr, {&helo_accept_junk_hosts} },
+ { "helo_allow_chars", opt_stringptr, {&helo_allow_chars} },
+ { "helo_lookup_domains", opt_stringptr, {&helo_lookup_domains} },
+ { "helo_try_verify_hosts", opt_stringptr, {&helo_try_verify_hosts} },
+ { "helo_verify_hosts", opt_stringptr, {&helo_verify_hosts} },
+ { "hold_domains", opt_stringptr, {&hold_domains} },
+ { "host_lookup", opt_stringptr, {&host_lookup} },
+ { "host_lookup_order", opt_stringptr, {&host_lookup_order} },
+ { "host_reject_connection", opt_stringptr, {&host_reject_connection} },
+ { "hosts_connection_nolog", opt_stringptr, {&hosts_connection_nolog} },
#ifdef SUPPORT_PROXY
- { "hosts_proxy", opt_stringptr, &hosts_proxy },
+ { "hosts_proxy", opt_stringptr, {&hosts_proxy} },
+#endif
+#ifndef DISABLE_TLS
+ { "hosts_require_alpn", opt_stringptr, {&hosts_require_alpn} },
#endif
- { "hosts_treat_as_local", opt_stringptr, &hosts_treat_as_local },
+ { "hosts_require_helo", opt_stringptr, {&hosts_require_helo} },
+ { "hosts_treat_as_local", opt_stringptr, {&hosts_treat_as_local} },
#ifdef LOOKUP_IBASE
- { "ibase_servers", opt_stringptr, &ibase_servers },
+ { "ibase_servers", opt_stringptr, {&ibase_servers} },
#endif
- { "ignore_bounce_errors_after", opt_time, &ignore_bounce_errors_after },
- { "ignore_fromline_hosts", opt_stringptr, &ignore_fromline_hosts },
- { "ignore_fromline_local", opt_bool, &ignore_fromline_local },
- { "keep_environment", opt_stringptr, &keep_environment },
- { "keep_malformed", opt_time, &keep_malformed },
+ { "ignore_bounce_errors_after", opt_time, {&ignore_bounce_errors_after} },
+ { "ignore_fromline_hosts", opt_stringptr, {&ignore_fromline_hosts} },
+ { "ignore_fromline_local", opt_bool, {&ignore_fromline_local} },
+ { "keep_environment", opt_stringptr, {&keep_environment} },
+ { "keep_malformed", opt_time, {&keep_malformed} },
#ifdef LOOKUP_LDAP
- { "ldap_ca_cert_dir", opt_stringptr, &eldap_ca_cert_dir },
- { "ldap_ca_cert_file", opt_stringptr, &eldap_ca_cert_file },
- { "ldap_cert_file", opt_stringptr, &eldap_cert_file },
- { "ldap_cert_key", opt_stringptr, &eldap_cert_key },
- { "ldap_cipher_suite", opt_stringptr, &eldap_cipher_suite },
- { "ldap_default_servers", opt_stringptr, &eldap_default_servers },
- { "ldap_require_cert", opt_stringptr, &eldap_require_cert },
- { "ldap_start_tls", opt_bool, &eldap_start_tls },
- { "ldap_version", opt_int, &eldap_version },
+ { "ldap_ca_cert_dir", opt_stringptr, {&eldap_ca_cert_dir} },
+ { "ldap_ca_cert_file", opt_stringptr, {&eldap_ca_cert_file} },
+ { "ldap_cert_file", opt_stringptr, {&eldap_cert_file} },
+ { "ldap_cert_key", opt_stringptr, {&eldap_cert_key} },
+ { "ldap_cipher_suite", opt_stringptr, {&eldap_cipher_suite} },
+ { "ldap_default_servers", opt_stringptr, {&eldap_default_servers} },
+ { "ldap_require_cert", opt_stringptr, {&eldap_require_cert} },
+ { "ldap_start_tls", opt_bool, {&eldap_start_tls} },
+ { "ldap_version", opt_int, {&eldap_version} },
+#endif
+#ifdef EXPERIMENTAL_ESMTP_LIMITS
+ { "limits_advertise_hosts", opt_stringptr, {&limits_advertise_hosts} },
#endif
- { "local_from_check", opt_bool, &local_from_check },
- { "local_from_prefix", opt_stringptr, &local_from_prefix },
- { "local_from_suffix", opt_stringptr, &local_from_suffix },
- { "local_interfaces", opt_stringptr, &local_interfaces },
+ { "local_from_check", opt_bool, {&local_from_check} },
+ { "local_from_prefix", opt_stringptr, {&local_from_prefix} },
+ { "local_from_suffix", opt_stringptr, {&local_from_suffix} },
+ { "local_interfaces", opt_stringptr, {&local_interfaces} },
#ifdef HAVE_LOCAL_SCAN
- { "local_scan_timeout", opt_time, &local_scan_timeout },
+ { "local_scan_timeout", opt_time, {&local_scan_timeout} },
#endif
- { "local_sender_retain", opt_bool, &local_sender_retain },
- { "localhost_number", opt_stringptr, &host_number_string },
- { "log_file_path", opt_stringptr, &log_file_path },
- { "log_selector", opt_stringptr, &log_selector_string },
- { "log_timezone", opt_bool, &log_timezone },
- { "lookup_open_max", opt_int, &lookup_open_max },
- { "max_username_length", opt_int, &max_username_length },
- { "message_body_newlines", opt_bool, &message_body_newlines },
- { "message_body_visible", opt_mkint, &message_body_visible },
- { "message_id_header_domain", opt_stringptr, &message_id_domain },
- { "message_id_header_text", opt_stringptr, &message_id_text },
- { "message_logs", opt_bool, &message_logs },
- { "message_size_limit", opt_stringptr, &message_size_limit },
+ { "local_sender_retain", opt_bool, {&local_sender_retain} },
+ { "localhost_number", opt_stringptr, {&host_number_string} },
+ { "log_file_path", opt_stringptr, {&log_file_path} },
+ { "log_selector", opt_stringptr, {&log_selector_string} },
+ { "log_timezone", opt_bool, {&log_timezone} },
+ { "lookup_open_max", opt_int, {&lookup_open_max} },
+ { "max_username_length", opt_int, {&max_username_length} },
+ { "message_body_newlines", opt_bool, {&message_body_newlines} },
+ { "message_body_visible", opt_mkint, {&message_body_visible} },
+ { "message_id_header_domain", opt_stringptr, {&message_id_domain} },
+ { "message_id_header_text", opt_stringptr, {&message_id_text} },
+ { "message_logs", opt_bool, {&message_logs} },
+ { "message_size_limit", opt_stringptr, {&message_size_limit} },
#ifdef SUPPORT_MOVE_FROZEN_MESSAGES
- { "move_frozen_messages", opt_bool, &move_frozen_messages },
+ { "move_frozen_messages", opt_bool, {&move_frozen_messages} },
#endif
- { "mua_wrapper", opt_bool, &mua_wrapper },
+ { "mua_wrapper", opt_bool, {&mua_wrapper} },
#ifdef LOOKUP_MYSQL
- { "mysql_servers", opt_stringptr, &mysql_servers },
+ { "mysql_servers", opt_stringptr, {&mysql_servers} },
#endif
- { "never_users", opt_uidlist, &never_users },
+ { "never_users", opt_uidlist, {&never_users} },
+ { "notifier_socket", opt_stringptr, {¬ifier_socket} },
#ifndef DISABLE_TLS
- { "openssl_options", opt_stringptr, &openssl_options },
+ { "openssl_options", opt_stringptr, {&openssl_options} },
#endif
#ifdef LOOKUP_ORACLE
- { "oracle_servers", opt_stringptr, &oracle_servers },
+ { "oracle_servers", opt_stringptr, {&oracle_servers} },
#endif
- { "percent_hack_domains", opt_stringptr, &percent_hack_domains },
+ { "percent_hack_domains", opt_stringptr, {&percent_hack_domains} },
#ifdef EXIM_PERL
- { "perl_at_start", opt_bool, &opt_perl_at_start },
- { "perl_startup", opt_stringptr, &opt_perl_startup },
- { "perl_taintmode", opt_bool, &opt_perl_taintmode },
+ { "perl_at_start", opt_bool, {&opt_perl_at_start} },
+ { "perl_startup", opt_stringptr, {&opt_perl_startup} },
+ { "perl_taintmode", opt_bool, {&opt_perl_taintmode} },
#endif
#ifdef LOOKUP_PGSQL
- { "pgsql_servers", opt_stringptr, &pgsql_servers },
+ { "pgsql_servers", opt_stringptr, {&pgsql_servers} },
#endif
- { "pid_file_path", opt_stringptr, &pid_file_path },
- { "pipelining_advertise_hosts", opt_stringptr, &pipelining_advertise_hosts },
-#ifdef SUPPORT_PIPE_CONNECT
+ { "pid_file_path", opt_stringptr, {&pid_file_path} },
+ { "pipelining_advertise_hosts", opt_stringptr, {&pipelining_advertise_hosts} },
+#ifndef DISABLE_PIPE_CONNECT
{ "pipelining_connect_advertise_hosts", opt_stringptr,
- &pipe_connect_advertise_hosts },
+ {&pipe_connect_advertise_hosts} },
#endif
#ifndef DISABLE_PRDR
- { "prdr_enable", opt_bool, &prdr_enable },
+ { "prdr_enable", opt_bool, {&prdr_enable} },
#endif
- { "preserve_message_logs", opt_bool, &preserve_message_logs },
- { "primary_hostname", opt_stringptr, &primary_hostname },
- { "print_topbitchars", opt_bool, &print_topbitchars },
- { "process_log_path", opt_stringptr, &process_log_path },
- { "prod_requires_admin", opt_bool, &prod_requires_admin },
- { "qualify_domain", opt_stringptr, &qualify_domain_sender },
- { "qualify_recipient", opt_stringptr, &qualify_domain_recipient },
- { "queue_domains", opt_stringptr, &queue_domains },
- { "queue_list_requires_admin",opt_bool, &queue_list_requires_admin },
- { "queue_only", opt_bool, &queue_only },
- { "queue_only_file", opt_stringptr, &queue_only_file },
- { "queue_only_load", opt_fixed, &queue_only_load },
- { "queue_only_load_latch", opt_bool, &queue_only_load_latch },
- { "queue_only_override", opt_bool, &queue_only_override },
- { "queue_run_in_order", opt_bool, &queue_run_in_order },
- { "queue_run_max", opt_stringptr, &queue_run_max },
- { "queue_smtp_domains", opt_stringptr, &queue_smtp_domains },
- { "receive_timeout", opt_time, &receive_timeout },
- { "received_header_text", opt_stringptr, &received_header_text },
- { "received_headers_max", opt_int, &received_headers_max },
- { "recipient_unqualified_hosts", opt_stringptr, &recipient_unqualified_hosts },
- { "recipients_max", opt_int, &recipients_max },
- { "recipients_max_reject", opt_bool, &recipients_max_reject },
+ { "preserve_message_logs", opt_bool, {&preserve_message_logs} },
+ { "primary_hostname", opt_stringptr, {&primary_hostname} },
+ { "print_topbitchars", opt_bool, {&print_topbitchars} },
+ { "process_log_path", opt_stringptr, {&process_log_path} },
+ { "prod_requires_admin", opt_bool, {&prod_requires_admin} },
+#ifdef SUPPORT_PROXY
+ { "proxy_protocol_timeout", opt_time, {&proxy_protocol_timeout} },
+#endif
+ { "qualify_domain", opt_stringptr, {&qualify_domain_sender} },
+ { "qualify_recipient", opt_stringptr, {&qualify_domain_recipient} },
+ { "queue_domains", opt_stringptr, {&queue_domains} },
+#ifndef DISABLE_QUEUE_RAMP
+ { "queue_fast_ramp", opt_bool, {&queue_fast_ramp} },
+#endif
+ { "queue_list_requires_admin",opt_bool, {&queue_list_requires_admin} },
+ { "queue_only", opt_bool, {&queue_only} },
+ { "queue_only_file", opt_stringptr, {&queue_only_file} },
+ { "queue_only_load", opt_fixed, {&queue_only_load} },
+ { "queue_only_load_latch", opt_bool, {&queue_only_load_latch} },
+ { "queue_only_override", opt_bool, {&queue_only_override} },
+ { "queue_run_in_order", opt_bool, {&queue_run_in_order} },
+ { "queue_run_max", opt_stringptr, {&queue_run_max} },
+ { "queue_smtp_domains", opt_stringptr, {&queue_smtp_domains} },
+ { "receive_timeout", opt_time, {&receive_timeout} },
+ { "received_header_text", opt_stringptr, {&received_header_text} },
+ { "received_headers_max", opt_int, {&received_headers_max} },
+ { "recipient_unqualified_hosts", opt_stringptr, {&recipient_unqualified_hosts} },
+ { "recipients_max", opt_int, {&recipients_max} },
+ { "recipients_max_reject", opt_bool, {&recipients_max_reject} },
#ifdef LOOKUP_REDIS
- { "redis_servers", opt_stringptr, &redis_servers },
+ { "redis_servers", opt_stringptr, {&redis_servers} },
#endif
- { "remote_max_parallel", opt_int, &remote_max_parallel },
- { "remote_sort_domains", opt_stringptr, &remote_sort_domains },
- { "retry_data_expire", opt_time, &retry_data_expire },
- { "retry_interval_max", opt_time, &retry_interval_max },
- { "return_path_remove", opt_bool, &return_path_remove },
- { "return_size_limit", opt_mkint|opt_hidden, &bounce_return_size_limit },
- { "rfc1413_hosts", opt_stringptr, &rfc1413_hosts },
- { "rfc1413_query_timeout", opt_time, &rfc1413_query_timeout },
- { "sender_unqualified_hosts", opt_stringptr, &sender_unqualified_hosts },
- { "slow_lookup_log", opt_int, &slow_lookup_log },
- { "smtp_accept_keepalive", opt_bool, &smtp_accept_keepalive },
- { "smtp_accept_max", opt_int, &smtp_accept_max },
- { "smtp_accept_max_nonmail", opt_int, &smtp_accept_max_nonmail },
- { "smtp_accept_max_nonmail_hosts", opt_stringptr, &smtp_accept_max_nonmail_hosts },
- { "smtp_accept_max_per_connection", opt_int, &smtp_accept_max_per_connection },
- { "smtp_accept_max_per_host", opt_stringptr, &smtp_accept_max_per_host },
- { "smtp_accept_queue", opt_int, &smtp_accept_queue },
- { "smtp_accept_queue_per_connection", opt_int, &smtp_accept_queue_per_connection },
- { "smtp_accept_reserve", opt_int, &smtp_accept_reserve },
- { "smtp_active_hostname", opt_stringptr, &raw_active_hostname },
- { "smtp_banner", opt_stringptr, &smtp_banner },
- { "smtp_check_spool_space", opt_bool, &smtp_check_spool_space },
- { "smtp_connect_backlog", opt_int, &smtp_connect_backlog },
- { "smtp_enforce_sync", opt_bool, &smtp_enforce_sync },
- { "smtp_etrn_command", opt_stringptr, &smtp_etrn_command },
- { "smtp_etrn_serialize", opt_bool, &smtp_etrn_serialize },
- { "smtp_load_reserve", opt_fixed, &smtp_load_reserve },
- { "smtp_max_synprot_errors", opt_int, &smtp_max_synprot_errors },
- { "smtp_max_unknown_commands",opt_int, &smtp_max_unknown_commands },
- { "smtp_ratelimit_hosts", opt_stringptr, &smtp_ratelimit_hosts },
- { "smtp_ratelimit_mail", opt_stringptr, &smtp_ratelimit_mail },
- { "smtp_ratelimit_rcpt", opt_stringptr, &smtp_ratelimit_rcpt },
- { "smtp_receive_timeout", opt_func, (void *) &fn_smtp_receive_timeout },
- { "smtp_reserve_hosts", opt_stringptr, &smtp_reserve_hosts },
- { "smtp_return_error_details",opt_bool, &smtp_return_error_details },
+ { "remote_max_parallel", opt_int, {&remote_max_parallel} },
+ { "remote_sort_domains", opt_stringptr, {&remote_sort_domains} },
+ { "retry_data_expire", opt_time, {&retry_data_expire} },
+ { "retry_interval_max", opt_time, {&retry_interval_max} },
+ { "return_path_remove", opt_bool, {&return_path_remove} },
+ { "return_size_limit", opt_mkint|opt_hidden, {&bounce_return_size_limit} },
+ { "rfc1413_hosts", opt_stringptr, {&rfc1413_hosts} },
+ { "rfc1413_query_timeout", opt_time, {&rfc1413_query_timeout} },
+ { "sender_unqualified_hosts", opt_stringptr, {&sender_unqualified_hosts} },
+ { "slow_lookup_log", opt_int, {&slow_lookup_log} },
+ { "smtp_accept_keepalive", opt_bool, {&smtp_accept_keepalive} },
+ { "smtp_accept_max", opt_int, {&smtp_accept_max} },
+ { "smtp_accept_max_nonmail", opt_int, {&smtp_accept_max_nonmail} },
+ { "smtp_accept_max_nonmail_hosts", opt_stringptr, {&smtp_accept_max_nonmail_hosts} },
+ { "smtp_accept_max_per_connection", opt_stringptr, {&smtp_accept_max_per_connection} },
+ { "smtp_accept_max_per_host", opt_stringptr, {&smtp_accept_max_per_host} },
+ { "smtp_accept_queue", opt_int, {&smtp_accept_queue} },
+ { "smtp_accept_queue_per_connection", opt_int, {&smtp_accept_queue_per_connection} },
+ { "smtp_accept_reserve", opt_int, {&smtp_accept_reserve} },
+ { "smtp_active_hostname", opt_stringptr, {&raw_active_hostname} },
+ { "smtp_backlog_monitor", opt_int, {&smtp_backlog_monitor} },
+ { "smtp_banner", opt_stringptr, {&smtp_banner} },
+ { "smtp_check_spool_space", opt_bool, {&smtp_check_spool_space} },
+ { "smtp_connect_backlog", opt_int, {&smtp_connect_backlog} },
+ { "smtp_enforce_sync", opt_bool, {&smtp_enforce_sync} },
+ { "smtp_etrn_command", opt_stringptr, {&smtp_etrn_command} },
+ { "smtp_etrn_serialize", opt_bool, {&smtp_etrn_serialize} },
+ { "smtp_load_reserve", opt_fixed, {&smtp_load_reserve} },
+ { "smtp_max_synprot_errors", opt_int, {&smtp_max_synprot_errors} },
+ { "smtp_max_unknown_commands",opt_int, {&smtp_max_unknown_commands} },
+ { "smtp_ratelimit_hosts", opt_stringptr, {&smtp_ratelimit_hosts} },
+ { "smtp_ratelimit_mail", opt_stringptr, {&smtp_ratelimit_mail} },
+ { "smtp_ratelimit_rcpt", opt_stringptr, {&smtp_ratelimit_rcpt} },
+ { "smtp_receive_timeout", opt_func, {.fn = &fn_smtp_receive_timeout} },
+ { "smtp_reserve_hosts", opt_stringptr, {&smtp_reserve_hosts} },
+ { "smtp_return_error_details",opt_bool, {&smtp_return_error_details} },
#ifdef SUPPORT_I18N
- { "smtputf8_advertise_hosts", opt_stringptr, &smtputf8_advertise_hosts },
+ { "smtputf8_advertise_hosts", opt_stringptr, {&smtputf8_advertise_hosts} },
#endif
#ifdef WITH_CONTENT_SCAN
- { "spamd_address", opt_stringptr, &spamd_address },
+ { "spamd_address", opt_stringptr, {&spamd_address} },
#endif
#ifdef SUPPORT_SPF
- { "spf_guess", opt_stringptr, &spf_guess },
+ { "spf_guess", opt_stringptr, {&spf_guess} },
+ { "spf_smtp_comment_template",opt_stringptr, {&spf_smtp_comment_template} },
#endif
- { "split_spool_directory", opt_bool, &split_spool_directory },
- { "spool_directory", opt_stringptr, &spool_directory },
- { "spool_wireformat", opt_bool, &spool_wireformat },
+ { "split_spool_directory", opt_bool, {&split_spool_directory} },
+ { "spool_directory", opt_stringptr, {&spool_directory} },
+ { "spool_wireformat", opt_bool, {&spool_wireformat} },
#ifdef LOOKUP_SQLITE
- { "sqlite_lock_timeout", opt_int, &sqlite_lock_timeout },
+ { "sqlite_dbfile", opt_stringptr, {&sqlite_dbfile} },
+ { "sqlite_lock_timeout", opt_int, {&sqlite_lock_timeout} },
#endif
-#ifdef EXPERIMENTAL_SRS
- { "srs_config", opt_stringptr, &srs_config },
- { "srs_hashlength", opt_int, &srs_hashlength },
- { "srs_hashmin", opt_int, &srs_hashmin },
- { "srs_maxage", opt_int, &srs_maxage },
- { "srs_secrets", opt_stringptr, &srs_secrets },
- { "srs_usehash", opt_bool, &srs_usehash },
- { "srs_usetimestamp", opt_bool, &srs_usetimestamp },
+#ifdef EXPERIMENTAL_SRS_ALT
+ { "srs_config", opt_stringptr, {&srs_config} },
+ { "srs_hashlength", opt_int, {&srs_hashlength} },
+ { "srs_hashmin", opt_int, {&srs_hashmin} },
+ { "srs_maxage", opt_int, {&srs_maxage} },
+ { "srs_secrets", opt_stringptr, {&srs_secrets} },
+ { "srs_usehash", opt_bool, {&srs_usehash} },
+ { "srs_usetimestamp", opt_bool, {&srs_usetimestamp} },
#endif
- { "strict_acl_vars", opt_bool, &strict_acl_vars },
- { "strip_excess_angle_brackets", opt_bool, &strip_excess_angle_brackets },
- { "strip_trailing_dot", opt_bool, &strip_trailing_dot },
- { "syslog_duplication", opt_bool, &syslog_duplication },
- { "syslog_facility", opt_stringptr, &syslog_facility_str },
- { "syslog_pid", opt_bool, &syslog_pid },
- { "syslog_processname", opt_stringptr, &syslog_processname },
- { "syslog_timestamp", opt_bool, &syslog_timestamp },
- { "system_filter", opt_stringptr, &system_filter },
- { "system_filter_directory_transport", opt_stringptr,&system_filter_directory_transport },
- { "system_filter_file_transport",opt_stringptr,&system_filter_file_transport },
- { "system_filter_group", opt_gid, &system_filter_gid },
- { "system_filter_pipe_transport",opt_stringptr,&system_filter_pipe_transport },
- { "system_filter_reply_transport",opt_stringptr,&system_filter_reply_transport },
- { "system_filter_user", opt_uid, &system_filter_uid },
- { "tcp_nodelay", opt_bool, &tcp_nodelay },
+ { "strict_acl_vars", opt_bool, {&strict_acl_vars} },
+ { "strip_excess_angle_brackets", opt_bool, {&strip_excess_angle_brackets} },
+ { "strip_trailing_dot", opt_bool, {&strip_trailing_dot} },
+ { "syslog_duplication", opt_bool, {&syslog_duplication} },
+ { "syslog_facility", opt_stringptr, {&syslog_facility_str} },
+ { "syslog_pid", opt_bool, {&syslog_pid} },
+ { "syslog_processname", opt_stringptr, {&syslog_processname} },
+ { "syslog_timestamp", opt_bool, {&syslog_timestamp} },
+ { "system_filter", opt_stringptr, {&system_filter} },
+ { "system_filter_directory_transport", opt_stringptr,{&system_filter_directory_transport} },
+ { "system_filter_file_transport",opt_stringptr,{&system_filter_file_transport} },
+ { "system_filter_group", opt_gid, {&system_filter_gid} },
+ { "system_filter_pipe_transport",opt_stringptr,{&system_filter_pipe_transport} },
+ { "system_filter_reply_transport",opt_stringptr,{&system_filter_reply_transport} },
+ { "system_filter_user", opt_uid, {&system_filter_uid} },
+ { "tcp_nodelay", opt_bool, {&tcp_nodelay} },
#ifdef USE_TCP_WRAPPERS
- { "tcp_wrappers_daemon_name", opt_stringptr, &tcp_wrappers_daemon_name },
+ { "tcp_wrappers_daemon_name", opt_stringptr, {&tcp_wrappers_daemon_name} },
#endif
- { "timeout_frozen_after", opt_time, &timeout_frozen_after },
- { "timezone", opt_stringptr, &timezone_string },
- { "tls_advertise_hosts", opt_stringptr, &tls_advertise_hosts },
+ { "timeout_frozen_after", opt_time, {&timeout_frozen_after} },
+ { "timezone", opt_stringptr, {&timezone_string} },
+ { "tls_advertise_hosts", opt_stringptr, {&tls_advertise_hosts} },
#ifndef DISABLE_TLS
- { "tls_certificate", opt_stringptr, &tls_certificate },
- { "tls_crl", opt_stringptr, &tls_crl },
- { "tls_dh_max_bits", opt_int, &tls_dh_max_bits },
- { "tls_dhparam", opt_stringptr, &tls_dhparam },
- { "tls_eccurve", opt_stringptr, &tls_eccurve },
+ { "tls_alpn", opt_stringptr, {&tls_alpn} },
+ { "tls_certificate", opt_stringptr, {&tls_certificate} },
+ { "tls_crl", opt_stringptr, {&tls_crl} },
+ { "tls_dh_max_bits", opt_int, {&tls_dh_max_bits} },
+ { "tls_dhparam", opt_stringptr, {&tls_dhparam} },
+ { "tls_eccurve", opt_stringptr, {&tls_eccurve} },
# ifndef DISABLE_OCSP
- { "tls_ocsp_file", opt_stringptr, &tls_ocsp_file },
+ { "tls_ocsp_file", opt_stringptr, {&tls_ocsp_file} },
# endif
- { "tls_on_connect_ports", opt_stringptr, &tls_in.on_connect_ports },
- { "tls_privatekey", opt_stringptr, &tls_privatekey },
- { "tls_remember_esmtp", opt_bool, &tls_remember_esmtp },
- { "tls_require_ciphers", opt_stringptr, &tls_require_ciphers },
-# ifdef EXPERIMENTAL_TLS_RESUME
- { "tls_resumption_hosts", opt_stringptr, &tls_resumption_hosts },
+ { "tls_on_connect_ports", opt_stringptr, {&tls_in.on_connect_ports} },
+ { "tls_privatekey", opt_stringptr, {&tls_privatekey} },
+ { "tls_remember_esmtp", opt_bool, {&tls_remember_esmtp} },
+ { "tls_require_ciphers", opt_stringptr, {&tls_require_ciphers} },
+# ifndef DISABLE_TLS_RESUME
+ { "tls_resumption_hosts", opt_stringptr, {&tls_resumption_hosts} },
# endif
- { "tls_try_verify_hosts", opt_stringptr, &tls_try_verify_hosts },
- { "tls_verify_certificates", opt_stringptr, &tls_verify_certificates },
- { "tls_verify_hosts", opt_stringptr, &tls_verify_hosts },
+ { "tls_try_verify_hosts", opt_stringptr, {&tls_try_verify_hosts} },
+ { "tls_verify_certificates", opt_stringptr, {&tls_verify_certificates} },
+ { "tls_verify_hosts", opt_stringptr, {&tls_verify_hosts} },
#endif
- { "trusted_groups", opt_gidlist, &trusted_groups },
- { "trusted_users", opt_uidlist, &trusted_users },
- { "unknown_login", opt_stringptr, &unknown_login },
- { "unknown_username", opt_stringptr, &unknown_username },
- { "untrusted_set_sender", opt_stringptr, &untrusted_set_sender },
- { "uucp_from_pattern", opt_stringptr, &uucp_from_pattern },
- { "uucp_from_sender", opt_stringptr, &uucp_from_sender },
- { "warn_message_file", opt_stringptr, &warn_message_file },
- { "write_rejectlog", opt_bool, &write_rejectlog }
+ { "trusted_groups", opt_gidlist, {&trusted_groups} },
+ { "trusted_users", opt_uidlist, {&trusted_users} },
+ { "unknown_login", opt_stringptr, {&unknown_login} },
+ { "unknown_username", opt_stringptr, {&unknown_username} },
+ { "untrusted_set_sender", opt_stringptr, {&untrusted_set_sender} },
+ { "uucp_from_pattern", opt_stringptr, {&uucp_from_pattern} },
+ { "uucp_from_sender", opt_stringptr, {&uucp_from_sender} },
+ { "warn_message_file", opt_stringptr, {&warn_message_file} },
+ { "write_rejectlog", opt_bool, {&write_rejectlog} }
};
#ifndef MACRO_PREDEF
void
options_auths(void)
{
-uschar buf[64];
+uschar buf[EXIM_DRIVERNAME_MAX];
options_from_list(optionlist_auths, optionlist_auths_size, US"AUTHENTICATORS", NULL);
spf(buf, sizeof(buf), US"_DRIVER_AUTHENTICATOR_%T", ai->driver_name);
builtin_macro_create(buf);
options_from_list(ai->options, (unsigned)*ai->options_count, US"AUTHENTICATOR", ai->driver_name);
+
+ if (ai->macros_create) (ai->macros_create)();
}
}
void
options_logging(void)
{
-uschar buf[64];
+uschar buf[EXIM_DRIVERNAME_MAX];
for (bit_table * bp = log_options; bp < log_options + log_options_count; bp++)
{
} syslog_fac_item;
/* constants */
-static const char * const hidden = "<value not displayable>";
+static const uschar * const hidden = US"<value not displayable>";
/* Static variables */
readconf_find_option(void *p)
{
for (int i = 0; i < nelem(optionlist_config); i++)
- if (p == optionlist_config[i].value) return US optionlist_config[i].name;
+ if (p == optionlist_config[i].v.value) return US optionlist_config[i].name;
for (router_instance * r = routers; r; r = r->next)
{
for (int i = 0; i < *ri->options_count; i++)
{
if ((ri->options[i].type & opt_mask) != opt_stringptr) continue;
- if (p == CS (r->options_block) + (long int)(ri->options[i].value))
+ if (p == CS (r->options_block) + ri->options[i].v.offset)
return US ri->options[i].name;
}
}
? CS t
: CS t->options_block
)
- + (long int)op->value)
+ + op->v.offset)
return US op->name;
}
}
BOOL
macro_read_assignment(uschar *s)
{
-uschar name[64];
+uschar name[EXIM_DRIVERNAME_MAX];
int namelen = 0;
BOOL redef = FALSE;
macro_item *m;
}
name[namelen] = 0;
-while (isspace(*s)) s++;
+Uskip_whitespace(&s);
if (*s++ != '=')
{
log_write(0, LOG_PANIC|LOG_CONFIG_IN, "malformed macro definition");
redef = TRUE;
s++;
}
-while (isspace(*s)) s++;
+Uskip_whitespace(&s);
/* If an existing macro of the same name was defined on the command line, we
just skip this definition. It's an error to attempt to redefine a macro without
/* Find the true start of the physical line - leading spaces are always
ignored. */
-while (isspace(*ss)) ss++;
+Uskip_whitespace(&ss);
/* Process the physical line for macros. If this is the start of the logical
line, skip over initial text at the start of the line if it starts with an
if (len == 0 && isupper(*s))
{
while (isalnum(*s) || *s == '_') s++;
- while (isspace(*s)) s++;
- if (*s != '=') s = ss; /* Not a macro definition */
+ if (Uskip_whitespace(&s) != '=') s = ss; /* Not a macro definition */
}
/* Skip leading chars which cannot start a macro name, to avoid multiple
/* An empty macro replacement at the start of a line could mean that ss no
longer points to the first non-blank character. */
-while (isspace(*ss)) ss++;
+Uskip_whitespace(&ss);
return ss;
}
struct stat statbuf;
ss += 9 + include_if_exists;
- while (isspace(*ss)) ss++;
+ Uskip_whitespace(&ss);
t = ss + Ustrlen(ss);
while (t > ss && isspace(t[-1])) t--;
if (*ss == '\"' && t[-1] == '\"')
if (strncmpic(s, US"begin ", 6) == 0)
{
s += 6;
- while (isspace(*s)) s++;
+ Uskip_whitespace(&s);
if (big_buffer + len - s > sizeof(next_section) - 2)
s[sizeof(next_section) - 2] = 0;
Ustrcpy(next_section, s);
readconf_readname(uschar *name, int len, uschar *s)
{
int p = 0;
-while (isspace(*s)) s++;
-if (isalpha(*s))
- {
+BOOL broken = FALSE;
+
+if (isalpha(Uskip_whitespace(&s)))
while (isalnum(*s) || *s == '_')
{
if (p < len-1) name[p++] = *s;
+ else {
+ broken = TRUE;
+ break;
+ }
s++;
}
- }
+
name[p] = 0;
-while (isspace(*s)) s++;
+if (broken) {
+ log_write(0, LOG_PANIC_DIE|LOG_CONFIG_IN,
+ "exim item name too long (>%d), unable to use \"%s\" (truncated)",
+ len, name);
+}
+Uskip_whitespace(&s);
return s;
}
*/
static optionlist *
-find_option(uschar *name, optionlist *ol, int last)
+find_option(const uschar *name, optionlist *ol, int last)
{
int first = 0;
while (last > first)
*/
static BOOL *
-get_set_flag(uschar *name, optionlist *oltop, int last, void *data_block)
+get_set_flag(const uschar *name, optionlist *oltop, int last, void *data_block)
{
optionlist *ol;
-uschar name2[64];
+uschar name2[EXIM_DRIVERNAME_MAX];
sprintf(CS name2, "*set_%.50s", name);
-ol = find_option(name2, oltop, last);
-if (ol == NULL) log_write(0, LOG_MAIN|LOG_PANIC_DIE,
- "Exim internal error: missing set flag for %s", name);
-return (data_block == NULL)? (BOOL *)(ol->value) :
- (BOOL *)(US data_block + (long int)(ol->value));
+if (!(ol = find_option(name2, oltop, last)))
+ log_write(0, LOG_MAIN|LOG_PANIC_DIE,
+ "Exim internal error: missing set flag for %s", name);
+return data_block
+ ? (BOOL *)(US data_block + ol->v.offset) : (BOOL *)ol->v.value;
}
next->next = NULL;
next->key = string_dequote(&p);
-while (isspace(*p)) p++;
-if (*p == 0)
+Uskip_whitespace(&p);
+if (!*p)
log_write(0, LOG_PANIC_DIE|LOG_CONFIG_IN,
"missing rewrite replacement string");
next->flags = 0;
next->replacement = string_dequote(&p);
-while (*p != 0) switch (*p++)
+while (*p) switch (*p++)
{
case ' ': case '\t': break;
{
if (flags & opt_fn_print_label) printf("%s = ", name);
printf("%s\n", smtp_receive_timeout_s
- ? string_printing2(smtp_receive_timeout_s, FALSE)
+ ? string_printing2(smtp_receive_timeout_s, SP_TAB)
: readconf_printtime(smtp_receive_timeout));
}
else if (*str == '$')
uschar *sptr;
uschar *s = buffer;
uschar **str_target;
-uschar name[64];
-uschar name2[64];
+uschar name[EXIM_DRIVERNAME_MAX];
+uschar name2[EXIM_DRIVERNAME_MAX];
/* There may be leading spaces; thereafter, we expect an option name starting
with a letter. */
if (!(ol = find_option(name + offset, oltop, last)))
{
- if (unknown_txt == NULL) return FALSE;
+ if (!unknown_txt) return FALSE;
log_write(0, LOG_PANIC_DIE|LOG_CONFIG_IN, CS unknown_txt, name);
}
if (offset != 0)
log_write(0, LOG_PANIC_DIE|LOG_CONFIG_IN,
"negation prefix applied to a non-boolean option");
- if (*s == 0)
+ if (!*s)
log_write(0, LOG_PANIC_DIE|LOG_CONFIG_IN,
"unexpected end of line (data missing) after %s", name);
if (*s != '=')
true/false/yes/no, or, in the case of opt_expand_bool, a general string that
ultimately expands to one of those values. */
-else if (*s != 0 && (offset != 0 || *s != '='))
+else if (*s && (offset != 0 || *s != '='))
extra_chars_error(s, US"boolean option ", name, US"");
/* Skip white space after = */
/* If there is a data block and the opt_public flag is not set, change
the data block pointer to the private options block. */
-if (data_block != NULL && (ol->type & opt_public) == 0)
+if (data_block && !(ol->type & opt_public))
data_block = (void *)(((driver_instance *)data_block)->options_block);
/* Now get the data according to the type. */
control block and flags word. */
case opt_stringptr:
- str_target = data_block ? USS (US data_block + (long int)(ol->value))
- : USS (ol->value);
+ str_target = data_block ? USS (US data_block + ol->v.offset)
+ : USS ol->v.value;
if (ol->type & opt_rep_con)
{
uschar * saved_condition;
case opt_rewrite:
if (data_block)
- *USS (US data_block + (long int)(ol->value)) = sptr;
+ *USS (US data_block + ol->v.offset) = sptr;
else
- *USS (ol->value) = sptr;
+ *USS ol->v.value = sptr;
freesptr = FALSE;
if (type == opt_rewrite)
{
sprintf(CS name2, "*%.50s_flags", name);
ol3 = find_option(name2, oltop, last);
- if (ol2 == NULL || ol3 == NULL)
+ if (!ol2 || !ol3)
log_write(0, LOG_PANIC_DIE|LOG_CONFIG_IN,
"rewrite rules not available for driver");
- if (data_block == NULL)
+ if (data_block)
{
- chain = (rewrite_rule **)(ol2->value);
- flagptr = (int *)(ol3->value);
+ chain = (rewrite_rule **)(US data_block + ol2->v.offset);
+ flagptr = (int *)(US data_block + ol3->v.offset);
}
else
{
- chain = (rewrite_rule **)(US data_block + (long int)(ol2->value));
- flagptr = (int *)(US data_block + (long int)(ol3->value));
+ chain = (rewrite_rule **)ol2->v.value;
+ flagptr = (int *)ol3->v.value;
}
+ /* This will trap if sptr is tainted. Not sure if that can happen */
while ((p = string_nextinlist(CUSS &sptr, &sep, big_buffer, BIG_BUFFER_SIZE)))
{
rewrite_rule *next = readconf_one_rewrite(p, flagptr, FALSE);
case opt_expand_uid:
sprintf(CS name2, "*expand_%.50s", name);
- ol2 = find_option(name2, oltop, last);
- if (ol2 != NULL)
+ if ((ol2 = find_option(name2, oltop, last)))
{
- uschar *ss = (Ustrchr(sptr, '$') != NULL)? sptr : NULL;
+ uschar *ss = (Ustrchr(sptr, '$') != NULL) ? sptr : NULL;
- if (data_block == NULL)
- *((uschar **)(ol2->value)) = ss;
+ if (data_block)
+ *(USS(US data_block + ol2->v.offset)) = ss;
else
- *((uschar **)(US data_block + (long int)(ol2->value))) = ss;
+ *(USS ol2->v.value) = ss;
- if (ss != NULL)
+ if (ss)
{
*(get_set_flag(name, oltop, last, data_block)) = FALSE;
freesptr = FALSE;
case opt_uid:
if (!route_finduser(sptr, &pw, &uid))
log_write(0, LOG_PANIC_DIE|LOG_CONFIG_IN, "user %s was not found", sptr);
- if (data_block == NULL)
- *((uid_t *)(ol->value)) = uid;
+ if (data_block)
+ *(uid_t *)(US data_block + ol->v.offset) = uid;
else
- *((uid_t *)(US data_block + (long int)(ol->value))) = uid;
+ *(uid_t *)ol->v.value = uid;
/* Set the flag indicating a fixed value is set */
if (pw == NULL) break;
Ustrcpy(name+Ustrlen(name)-4, US"group");
ol2 = find_option(name, oltop, last);
- if (ol2 != NULL && ((ol2->type & opt_mask) == opt_gid ||
+ if (ol2 && ((ol2->type & opt_mask) == opt_gid ||
(ol2->type & opt_mask) == opt_expand_gid))
{
BOOL *set_flag = get_set_flag(name, oltop, last, data_block);
- if (! *set_flag)
+ if (!*set_flag)
{
- if (data_block == NULL)
- *((gid_t *)(ol2->value)) = pw->pw_gid;
+ if (data_block)
+ *((gid_t *)(US data_block + ol2->v.offset)) = pw->pw_gid;
else
- *((gid_t *)(US data_block + (long int)(ol2->value))) = pw->pw_gid;
+ *((gid_t *)ol2->v.value) = pw->pw_gid;
*set_flag = TRUE;
}
}
case opt_expand_gid:
sprintf(CS name2, "*expand_%.50s", name);
- ol2 = find_option(name2, oltop, last);
- if (ol2 != NULL)
+ if ((ol2 = find_option(name2, oltop, last)))
{
- uschar *ss = (Ustrchr(sptr, '$') != NULL)? sptr : NULL;
+ uschar *ss = (Ustrchr(sptr, '$') != NULL) ? sptr : NULL;
- if (data_block == NULL)
- *((uschar **)(ol2->value)) = ss;
+ if (data_block)
+ *(USS(US data_block + ol2->v.offset)) = ss;
else
- *((uschar **)(US data_block + (long int)(ol2->value))) = ss;
+ *(USS ol2->v.value) = ss;
- if (ss != NULL)
+ if (ss)
{
*(get_set_flag(name, oltop, last, data_block)) = FALSE;
freesptr = FALSE;
case opt_gid:
if (!route_findgroup(sptr, &gid))
log_write(0, LOG_PANIC_DIE|LOG_CONFIG_IN, "group %s was not found", sptr);
- if (data_block == NULL)
- *((gid_t *)(ol->value)) = gid;
+ if (data_block)
+ *((gid_t *)(US data_block + ol->v.offset)) = gid;
else
- *((gid_t *)(US data_block + (long int)(ol->value))) = gid;
+ *((gid_t *)ol->v.value) = gid;
*(get_set_flag(name, oltop, last, data_block)) = TRUE;
break;
list = store_malloc(count*sizeof(uid_t));
list[ptr++] = (uid_t)(count - 1);
- if (data_block == NULL)
- *((uid_t **)(ol->value)) = list;
+ if (data_block)
+ *((uid_t **)(US data_block + ol->v.offset)) = list;
else
- *((uid_t **)(US data_block + (long int)(ol->value))) = list;
+ *((uid_t **)ol->v.value) = list;
p = op;
while (count-- > 1)
{
int sep = 0;
+ /* If p is tainted we trap. Not sure that can happen */
(void)string_nextinlist(&p, &sep, big_buffer, BIG_BUFFER_SIZE);
if (!route_finduser(big_buffer, NULL, &uid))
log_write(0, LOG_PANIC_DIE|LOG_CONFIG_IN, "user %s was not found",
const uschar *p;
const uschar *op = expand_string (sptr);
- if (op == NULL)
+ if (!op)
log_write(0, LOG_PANIC_DIE|LOG_CONFIG_IN, "failed to expand %s: %s",
name, expand_string_message);
list = store_malloc(count*sizeof(gid_t));
list[ptr++] = (gid_t)(count - 1);
- if (data_block == NULL)
- *((gid_t **)(ol->value)) = list;
+ if (data_block)
+ *((gid_t **)(US data_block + ol->v.offset)) = list;
else
- *((gid_t **)(US data_block + (long int)(ol->value))) = list;
+ *((gid_t **)ol->v.value) = list;
p = op;
while (count-- > 1)
{
int sep = 0;
+ /* If p is tainted we trap. Not sure that can happen */
(void)string_nextinlist(&p, &sep, big_buffer, BIG_BUFFER_SIZE);
if (!route_findgroup(big_buffer, &gid))
log_write(0, LOG_PANIC_DIE|LOG_CONFIG_IN, "group %s was not found",
save the string for later expansion in the alternate place. */
case opt_expand_bool:
- if (*s != 0 && Ustrchr(s, '$') != 0)
+ if (*s && Ustrchr(s, '$') != 0)
{
sprintf(CS name2, "*expand_%.50s", name);
if ((ol2 = find_option(name2, oltop, last)))
{
reset_point = store_mark();
sptr = read_string(s, name);
- if (data_block == NULL)
- *((uschar **)(ol2->value)) = sptr;
+ if (data_block)
+ *(USS(US data_block + ol2->v.offset)) = sptr;
else
- *((uschar **)(US data_block + (long int)(ol2->value))) = sptr;
+ *(USS ol2->v.value) = sptr;
freesptr = FALSE;
break;
}
case opt_bool_set:
if (*s != 0)
{
- s = readconf_readname(name2, 64, s);
+ s = readconf_readname(name2, EXIM_DRIVERNAME_MAX, s);
if (strcmpic(name2, US"true") == 0 || strcmpic(name2, US"yes") == 0)
boolvalue = TRUE;
else if (strcmpic(name2, US"false") == 0 || strcmpic(name2, US"no") == 0)
if (type == opt_bit)
{
int bit = 1 << ((ol->type >> 16) & 31);
- int *ptr = (data_block == NULL)?
- (int *)(ol->value) :
- (int *)(US data_block + (long int)ol->value);
+ int * ptr = data_block
+ ? (int *)(US data_block + ol->v.offset)
+ : (int *)ol->v.value;
if (boolvalue) *ptr |= bit; else *ptr &= ~bit;
break;
}
/* Handle full BOOL types */
- if (data_block == NULL)
- *((BOOL *)(ol->value)) = boolvalue;
+ if (data_block)
+ *((BOOL *)(US data_block + ol->v.offset)) = boolvalue;
else
- *((BOOL *)(US data_block + (long int)(ol->value))) = boolvalue;
+ *((BOOL *)ol->v.value) = boolvalue;
/* Verify fudge */
if (type == opt_bool_verify)
{
sprintf(CS name2, "%.50s_recipient", name + offset);
- ol2 = find_option(name2, oltop, last);
- if (ol2 != NULL)
- {
- if (data_block == NULL)
- *((BOOL *)(ol2->value)) = boolvalue;
+ if ((ol2 = find_option(name2, oltop, last)))
+ if (data_block)
+ *((BOOL *)(US data_block + ol2->v.offset)) = boolvalue;
else
- *((BOOL *)(US data_block + (long int)(ol2->value))) = boolvalue;
- }
+ *((BOOL *)ol2->v.value) = boolvalue;
}
/* Note that opt_bool_set type is set, if there is somewhere to do so */
else if (type == opt_bool_set)
{
sprintf(CS name2, "*set_%.50s", name + offset);
- ol2 = find_option(name2, oltop, last);
- if (ol2 != NULL)
- {
- if (data_block == NULL)
- *((BOOL *)(ol2->value)) = TRUE;
+ if ((ol2 = find_option(name2, oltop, last)))
+ if (data_block)
+ *((BOOL *)(US data_block + ol2->v.offset)) = TRUE;
else
- *((BOOL *)(US data_block + (long int)(ol2->value))) = TRUE;
- }
+ *((BOOL *)ol2->v.value) = TRUE;
}
break;
}
if (data_block)
- *(int *)(US data_block + (long int)ol->value) = value;
+ *(int *)(US data_block + ol->v.offset) = value;
else
- *(int *)ol->value = value;
+ *(int *)ol->v.value = value;
break;
/* Integer held in K: again, allow formats and suffixes as above. */
extra_chars_error(endptr, inttype, US"integer value for ", name);
if (data_block)
- *(int_eximarith_t *)(US data_block + (long int)ol->value) = lvalue;
+ *(int_eximarith_t *)(US data_block + ol->v.offset) = lvalue;
else
- *(int_eximarith_t *)ol->value = lvalue;
+ *(int_eximarith_t *)ol->v.value = lvalue;
break;
}
if (s[count] != 0)
extra_chars_error(s+count, US"fixed-point value for ", name, US"");
- if (data_block == NULL)
- *((int *)(ol->value)) = value;
+ if (data_block)
+ *((int *)(US data_block + ol->v.offset)) = value;
else
- *((int *)(US data_block + (long int)(ol->value))) = value;
+ *((int *)ol->v.value) = value;
break;
/* There's a special routine to read time values. */
if (value < 0)
log_write(0, LOG_PANIC_DIE|LOG_CONFIG_IN, "invalid time value for %s",
name);
- if (data_block == NULL)
- *((int *)(ol->value)) = value;
+ if (data_block)
+ *((int *)(US data_block + ol->v.offset)) = value;
else
- *((int *)(US data_block + (long int)(ol->value))) = value;
+ *((int *)ol->v.value) = value;
break;
/* A time list is a list of colon-separated times, with the first
case opt_timelist:
{
int count = 0;
- int *list = (data_block == NULL)?
- (int *)(ol->value) :
- (int *)(US data_block + (long int)(ol->value));
+ int * list = data_block
+ ? (int *)(US data_block + ol->v.offset)
+ : (int *)ol->v.value;
if (*s != 0) for (count = 1; count <= list[0] - 2; count++)
{
case opt_func:
{
- void (*fn)() = ol->value;
+ void (*fn)() = ol->v.fn;
fn(name, s, 0);
break;
}
*/
static BOOL
-print_ol(optionlist *ol, uschar *name, void *options_block,
+print_ol(optionlist *ol, const uschar *name, void *options_block,
optionlist *oltop, int last, BOOL no_labels)
{
struct passwd *pw;
uid_t *uidlist;
gid_t *gidlist;
uschar *s;
-uschar name2[64];
+uschar name2[EXIM_DRIVERNAME_MAX];
if (!ol)
{
if (!f.admin_user && ol->type & opt_secure)
{
if (no_labels)
- printf("%s\n", hidden);
+ printf("%s\n", CCS hidden);
else
- printf("%s = %s\n", name, hidden);
+ printf("%s = %s\n", name, CCS hidden);
return TRUE;
}
/* Else show the value of the option */
-value = ol->value;
+value = ol->v.value;
if (options_block)
{
if (!(ol->type & opt_public))
case opt_rewrite: /* Show the text value */
s = *(USS value);
if (!no_labels) printf("%s = ", name);
- printf("%s\n", s ? string_printing2(s, FALSE) : US"");
+ printf("%s\n", s ? string_printing2(s, SP_TAB) : US"");
break;
case opt_int:
sprintf(CS name2, "*expand_%.50s", name);
if ((ol2 = find_option(name2, oltop, last)))
{
- void *value2 = ol2->value;
if (options_block)
- value2 = (void *)(US options_block + (long int)value2);
- s = *(USS value2);
+ s = *USS (US options_block + ol2->v.offset);
+ else
+ s = *USS ol2->v.value;
if (!no_labels) printf("%s = ", name);
printf("%s\n", s ? string_printing(s) : US"");
break;
if ( (ol2 = find_option(name2, oltop, last))
&& (ol2->type & opt_mask) == opt_stringptr)
{
- void *value2 = ol2->value;
if (options_block)
- value2 = (void *)(US options_block + (long int)value2);
- s = *(USS value2);
+ s = *USS (US options_block + ol2->v.offset);
+ else
+ s = *USS ol2->v.value;
if (!no_labels) printf("%s = ", name);
printf("%s\n", s ? string_printing(s) : US"");
break;
case opt_expand_bool:
sprintf(CS name2, "*expand_%.50s", name);
- if ((ol2 = find_option(name2, oltop, last)) && ol2->value)
+ if ((ol2 = find_option(name2, oltop, last)) && ol2->v.value)
{
- void *value2 = ol2->value;
if (options_block)
- value2 = (void *)(US options_block + (long int)value2);
- s = *(USS value2);
+ s = *USS (US options_block + ol2->v.offset);
+ else
+ s = *USS ol2->v.value;
if (s)
{
if (!no_labels) printf("%s = ", name);
break;
case opt_func:
- {
- void (*fn)() = ol->value;
- fn(name, NULL, no_labels ? opt_fn_print : opt_fn_print|opt_fn_print_label);
+ ol->v.fn(name, NULL, no_labels ? opt_fn_print : opt_fn_print|opt_fn_print_label);
break;
- }
}
return TRUE;
}
*/
BOOL
-readconf_print(uschar *name, uschar *type, BOOL no_labels)
+readconf_print(const uschar *name, uschar *type, BOOL no_labels)
{
BOOL names_only = FALSE;
optionlist *ol2 = NULL;
for (int i = 0; i < 4; i++)
if ((t = tree_search(*(anchors[i]), name+1)))
{
+ namedlist_block * nb = t->data.ptr;
+ const uschar * s = nb->hide ? hidden : nb->string;
found = TRUE;
if (no_labels)
- printf("%s\n", ((namedlist_block *)(t->data.ptr))->string);
+ printf("%s\n", CCS s);
else
- printf("%slist %s = %s\n", types[i], name+1,
- ((namedlist_block *)(t->data.ptr))->string);
+ printf("%slist %s = %s\n", types[i], name+1, CCS s);
}
if (!found)
else
return print_ol(find_option(name,
- optionlist_config, nelem(optionlist_config)),
+ optionlist_config, nelem(optionlist_config)),
name, NULL, optionlist_config, nelem(optionlist_config), no_labels);
}
s the text of the option line, starting immediately after the name
of the list type
tname the name of the list type, for messages
+ hide do not output value on "-bP"
Returns: nothing
*/
static void
read_named_list(tree_node **anchorp, int *numberp, int max, uschar *s,
- uschar *tname)
+ uschar *tname, BOOL hide)
{
BOOL forcecache = FALSE;
uschar *ss;
tree_node *t;
-namedlist_block *nb = store_get(sizeof(namedlist_block), FALSE);
+namedlist_block * nb = store_get_perm(sizeof(namedlist_block), FALSE);
if (Ustrncmp(s, "_cache", 6) == 0)
{
log_write(0, LOG_PANIC_DIE|LOG_CONFIG_IN, "too many named %ss (max is %d)\n",
tname, max);
-while (isspace(*s)) s++;
+Uskip_whitespace(&s);
ss = s;
while (isalnum(*s) || *s == '_') s++;
t = store_get(sizeof(tree_node) + s-ss, is_tainted(ss));
Ustrncpy(t->name, ss, s-ss);
t->name[s-ss] = 0;
-while (isspace(*s)) s++;
+Uskip_whitespace(&s);
if (!tree_insertnode(anchorp, t))
log_write(0, LOG_PANIC_DIE|LOG_CONFIG_IN,
t->data.ptr = nb;
nb->number = *numberp;
*numberp += 1;
+nb->hide = hide;
if (*s++ != '=') log_write(0, LOG_PANIC_DIE|LOG_CONFIG_IN,
"missing '=' after \"%s\"", t->name);
-while (isspace(*s)) s++;
+Uskip_whitespace(&s);
nb->string = read_string(s, t->name);
nb->cache_data = NULL;
-/*************************************************
-* Drop privs for checking TLS config *
-*************************************************/
-
-/* We want to validate TLS options during readconf, but do not want to be
-root when we call into the TLS library, in case of library linkage errors
-which cause segfaults; before this check, those were always done as the Exim
-runtime user and it makes sense to continue with that.
-
-Assumes: tls_require_ciphers has been set, if it will be
- exim_user has been set, if it will be
- exim_group has been set, if it will be
-
-Returns: bool for "okay"; false will cause caller to immediately exit.
-*/
-
-#ifndef DISABLE_TLS
-static BOOL
-tls_dropprivs_validate_require_cipher(BOOL nowarn)
-{
-const uschar *errmsg;
-pid_t pid;
-int rc, status;
-void (*oldsignal)(int);
-
-/* If TLS will never be used, no point checking ciphers */
-
-if ( !tls_advertise_hosts
- || !*tls_advertise_hosts
- || Ustrcmp(tls_advertise_hosts, ":") == 0
- )
- return TRUE;
-else if (!nowarn && !tls_certificate)
- log_write(0, LOG_MAIN,
- "Warning: No server certificate defined; will use a selfsigned one.\n"
- " Suggested action: either install a certificate or change tls_advertise_hosts option");
-
-oldsignal = signal(SIGCHLD, SIG_DFL);
-
-fflush(NULL);
-if ((pid = fork()) < 0)
- log_write(0, LOG_MAIN|LOG_PANIC_DIE, "fork failed for TLS check");
-
-if (pid == 0)
- {
- /* in some modes, will have dropped privilege already */
- if (!geteuid())
- exim_setugid(exim_uid, exim_gid, FALSE,
- US"calling tls_validate_require_cipher");
-
- if ((errmsg = tls_validate_require_cipher()))
- log_write(0, LOG_PANIC_DIE|LOG_CONFIG,
- "tls_require_ciphers invalid: %s", errmsg);
- fflush(NULL);
- exim_underbar_exit(0);
- }
-
-do {
- rc = waitpid(pid, &status, 0);
-} while (rc < 0 && errno == EINTR);
-
-DEBUG(D_tls)
- debug_printf("tls_validate_require_cipher child %d ended: status=0x%x\n",
- (int)pid, status);
-
-signal(SIGCHLD, oldsignal);
-
-return status == 0;
-}
-#endif /*DISABLE_TLS*/
-
-
-
-
/*************************************************
* Read main configuration options *
*************************************************/
/* Loop through the possible file names */
+/* Should never be a tainted list */
while((filename = string_nextinlist(&list, &sep, big_buffer, big_buffer_size)))
{
/* Cut out all the fancy processing unless specifically wanted */
- #if defined(CONFIGURE_FILE_USE_NODE) || defined(CONFIGURE_FILE_USE_EUID)
+#if defined(CONFIGURE_FILE_USE_NODE) || defined(CONFIGURE_FILE_USE_EUID)
uschar *suffix = filename + Ustrlen(filename);
/* Try for the node-specific file if a node name exists */
- #ifdef CONFIGURE_FILE_USE_NODE
+# ifdef CONFIGURE_FILE_USE_NODE
struct utsname uts;
if (uname(&uts) >= 0)
{
- #ifdef CONFIGURE_FILE_USE_EUID
+# ifdef CONFIGURE_FILE_USE_EUID
sprintf(CS suffix, ".%ld.%.256s", (long int)original_euid, uts.nodename);
- config_file = Ufopen(filename, "rb");
- if (config_file == NULL)
- #endif /* CONFIGURE_FILE_USE_EUID */
+ if (!(config_file = Ufopen(filename, "rb")))
+# endif /* CONFIGURE_FILE_USE_EUID */
{
sprintf(CS suffix, ".%.256s", uts.nodename);
config_file = Ufopen(filename, "rb");
}
}
- #endif /* CONFIGURE_FILE_USE_NODE */
+# endif /* CONFIGURE_FILE_USE_NODE */
/* Otherwise, try the generic name, possibly with the euid added */
- #ifdef CONFIGURE_FILE_USE_EUID
- if (config_file == NULL)
+# ifdef CONFIGURE_FILE_USE_EUID
+ if (!config_file)
{
sprintf(CS suffix, ".%ld", (long int)original_euid);
config_file = Ufopen(filename, "rb");
}
- #endif /* CONFIGURE_FILE_USE_EUID */
+# endif /* CONFIGURE_FILE_USE_EUID */
/* Finally, try the unadorned name */
- if (config_file == NULL)
+ if (!config_file)
{
*suffix = 0;
config_file = Ufopen(filename, "rb");
}
- #else /* if neither defined */
+#else /* if neither defined */
/* This is the common case when the fancy processing is not included. */
config_file = Ufopen(filename, "rb");
- #endif
+#endif
/* If the file does not exist, continue to try any others. For any other
error, break out (and die). */
- if (config_file != NULL || errno != ENOENT) break;
+ if (config_file || errno != ENOENT) break;
}
/* On success, save the name for verification; config_filename is used when
config_main_directory = last_slash == filename ? US"/" : string_copyn(filename, last_slash - filename);
else
{
- /* relative configuration file name: working dir + / + basename(filename) */
+ /* relative configuration file name: working dir + / + basename(filename) */
- uschar buf[PATH_MAX];
- gstring * g;
+ uschar buf[PATH_MAX];
+ gstring * g;
- if (os_getcwd(buf, PATH_MAX) == NULL)
- {
- perror("exim: getcwd");
- exit(EXIT_FAILURE);
- }
- g = string_cat(NULL, buf);
+ if (os_getcwd(buf, PATH_MAX) == NULL)
+ {
+ perror("exim: getcwd");
+ exit(EXIT_FAILURE);
+ }
+ g = string_cat(NULL, buf);
- /* If the dir does not end with a "/", append one */
- if (g->s[g->ptr-1] != '/')
- g = string_catn(g, US"/", 1);
+ /* If the dir does not end with a "/", append one */
+ if (g->s[g->ptr-1] != '/')
+ g = string_catn(g, US"/", 1);
- /* If the config file contains a "/", extract the directory part */
- if (last_slash)
- g = string_catn(g, filename, last_slash - filename);
+ /* If the config file contains a "/", extract the directory part */
+ if (last_slash)
+ g = string_catn(g, filename, last_slash - filename);
- config_main_directory = string_from_gstring(g);
+ config_main_directory = string_from_gstring(g);
}
config_directory = config_main_directory;
}
else
- {
- if (filename == NULL)
+ if (!filename)
log_write(0, LOG_MAIN|LOG_PANIC_DIE, "non-existent configuration file(s): "
"%s", config_main_filelist);
else
- log_write(0, LOG_MAIN|LOG_PANIC_DIE, "%s", string_open_failed(errno,
- "configuration file %s", filename));
- }
+ log_write(0, LOG_MAIN|LOG_PANIC_DIE, "%s",
+ string_open_failed("configuration file %s", filename));
/* Now, once we found and opened our configuration file, we change the directory
to a safe place. Later we change to $spool_directory. */
log_write(0, LOG_MAIN|LOG_PANIC_DIE, "failed to stat configuration file %s",
big_buffer);
- if ((statbuf.st_uid != root_uid /* owner not root */
- #ifdef CONFIGURE_OWNER
- && statbuf.st_uid != config_uid /* owner not the special one */
- #endif
- ) || /* or */
- (statbuf.st_gid != root_gid /* group not root & */
- #ifdef CONFIGURE_GROUP
- && statbuf.st_gid != config_gid /* group not the special one */
- #endif
- && (statbuf.st_mode & 020) != 0) || /* group writeable */
- /* or */
- ((statbuf.st_mode & 2) != 0)) /* world writeable */
-
+ if ( statbuf.st_uid != root_uid /* owner not root */
+#ifdef CONFIGURE_OWNER
+ && statbuf.st_uid != config_uid /* owner not the special one */
+#endif
+ || /* or */
+ statbuf.st_gid != root_gid /* group not root & */
+#ifdef CONFIGURE_GROUP
+ && statbuf.st_gid != config_gid /* group not the special one */
+#endif
+ && (statbuf.st_mode & 020) != 0 /* group writeable */
+ || /* or */
+ (statbuf.st_mode & 2) != 0 /* world writeable */
+ )
log_write(0, LOG_MAIN|LOG_PANIC_DIE, "Exim configuration file %s has the "
"wrong owner, group, or mode", big_buffer);
}
}
-/* Do a dummy store-allocation of a size related to the (toplevel) file size.
-This assumes we will need this much storage to handle all the allocations
-during startup; it won't help when .include is being used. When it does, it
-will cut down on the number of store blocks (and malloc calls, and sbrk
-syscalls). It also assume we're on the relevant pool. */
-
-if (statbuf.st_size > 8192)
- {
- rmark r = store_mark();
- void * dummy = store_get((int)statbuf.st_size, FALSE);
- store_reset(r);
- }
-
/* Process the main configuration settings. They all begin with a lower case
letter. If we see something starting with an upper case letter, it is taken as
a macro definition. */
while ((s = get_config_line()))
{
+ BOOL hide;
+ uschar * t;
+
if (config_lineno == 1 && Ustrstr(s, "\xef\xbb\xbf") == s)
log_write(0, LOG_PANIC_DIE|LOG_CONFIG_IN,
"found unexpected BOM (Byte Order Mark)");
- if (isupper(s[0]))
- { if (!macro_read_assignment(s)) exim_exit(EXIT_FAILURE, US""); }
+ if (isupper(*s))
+ {
+ if (!macro_read_assignment(s)) exim_exit(EXIT_FAILURE);
+ continue;
+ }
+
+ t = (hide = Ustrncmp(s, "hide", 4) == 0 && isspace(s[4])) ? s + 5 : s;
- else if (Ustrncmp(s, "domainlist", 10) == 0)
+ if (Ustrncmp(t, "domainlist", 10) == 0)
read_named_list(&domainlist_anchor, &domainlist_count,
- MAX_NAMED_LIST, s+10, US"domain list");
+ MAX_NAMED_LIST, t+10, US"domain list", hide);
- else if (Ustrncmp(s, "hostlist", 8) == 0)
+ else if (Ustrncmp(t, "hostlist", 8) == 0)
read_named_list(&hostlist_anchor, &hostlist_count,
- MAX_NAMED_LIST, s+8, US"host list");
+ MAX_NAMED_LIST, t+8, US"host list", hide);
- else if (Ustrncmp(s, US"addresslist", 11) == 0)
+ else if (Ustrncmp(t, "addresslist", 11) == 0)
read_named_list(&addresslist_anchor, &addresslist_count,
- MAX_NAMED_LIST, s+11, US"address list");
+ MAX_NAMED_LIST, t+11, US"address list", hide);
- else if (Ustrncmp(s, US"localpartlist", 13) == 0)
+ else if (Ustrncmp(t, "localpartlist", 13) == 0)
read_named_list(&localpartlist_anchor, &localpartlist_count,
- MAX_NAMED_LIST, s+13, US"local part list");
+ MAX_NAMED_LIST, t+13, US"local part list", hide);
else
(void) readconf_handle_option(s, optionlist_config, optionlist_config_size,
/* If the timezone string is empty, set it to NULL, implying no TZ variable
wanted. */
-if (timezone_string != NULL && *timezone_string == 0) timezone_string = NULL;
+if (timezone_string && !*timezone_string) timezone_string = NULL;
/* The max retry interval must not be greater than 24 hours. */
canonize it. Some people like upper case letters in their host names, so we
don't force the case. */
-if (primary_hostname == NULL)
+if (!primary_hostname)
{
- const uschar *hostname;
+ const uschar * hostname;
struct utsname uts;
+
if (uname(&uts) < 0)
log_write(0, LOG_MAIN|LOG_PANIC_DIE, "uname() failed to yield host name");
hostname = US uts.nodename;
int af = AF_INET;
struct hostent *hostdata;
- #if HAVE_IPV6
- if (!disable_ipv6 && (dns_ipv4_lookup == NULL ||
- match_isinlist(hostname, CUSS &dns_ipv4_lookup, 0, NULL, NULL,
+#if HAVE_IPV6
+ if ( !disable_ipv6
+ && ( !dns_ipv4_lookup
+ || match_isinlist(hostname, CUSS &dns_ipv4_lookup, 0, NULL, NULL,
MCL_DOMAIN, TRUE, NULL) != OK))
af = AF_INET6;
- #else
- af = AF_INET;
- #endif
+#endif
for (;;)
{
- #if HAVE_IPV6
- #if HAVE_GETIPNODEBYNAME
+#if HAVE_IPV6
+# if HAVE_GETIPNODEBYNAME
int error_num;
hostdata = getipnodebyname(CS hostname, af, 0, &error_num);
#else
hostdata = gethostbyname2(CS hostname, af);
- #endif
- #else
+# endif
+#else
hostdata = gethostbyname(CS hostname);
- #endif
+#endif
- if (hostdata != NULL)
- {
- hostname = US hostdata->h_name;
- break;
- }
+ if (hostdata)
+ { hostname = US hostdata->h_name; break; }
if (af == AF_INET) break;
af = AF_INET;
"\"%s\": %s", log_file_path, expand_string_message);
ss = s;
+ /* should never be a tainted list */
while ((sss = string_nextinlist(&ss, &sep, big_buffer, big_buffer_size)))
{
uschar *t;
/* Expand pid_file_path */
-if (*pid_file_path != 0)
+if (*pid_file_path)
{
if (!(s = expand_string(pid_file_path)))
log_write(0, LOG_MAIN|LOG_PANIC_DIE, "failed to expand pid_file_path "
/* Set default value of process_log_path */
-if (!process_log_path || *process_log_path =='\0')
+if (!process_log_path || !*process_log_path)
process_log_path = string_sprintf("%s/exim-process.info", spool_directory);
/* Compile the regex for matching a UUCP-style "From_" line in an incoming
log_write(0, LOG_PANIC_DIE|LOG_CONFIG,
"error in errors_reply_to (%s): %s", errors_reply_to, errmess);
- if (domain == 0)
+ if (!domain)
log_write(0, LOG_PANIC_DIE|LOG_CONFIG,
"errors_reply_to (%s) does not contain a domain", errors_reply_to);
}
/* If smtp_accept_queue or smtp_accept_max_per_host is set, then
smtp_accept_max must also be set. */
-if (smtp_accept_max == 0 &&
- (smtp_accept_queue > 0 || smtp_accept_max_per_host != NULL))
+if (smtp_accept_max == 0 && (smtp_accept_queue > 0 || smtp_accept_max_per_host))
log_write(0, LOG_PANIC_DIE|LOG_CONFIG,
"smtp_accept_max must be set if smtp_accept_queue or "
"smtp_accept_max_per_host is set");
host_number_string, expand_string_message);
n = Ustrtol(s, &end, 0);
while (isspace(*end)) end++;
- if (*end != 0)
+ if (*end)
log_write(0, LOG_PANIC_DIE|LOG_CONFIG,
"localhost_number value is not a number: %s", s);
if (n > LOCALHOST_MAX)
"tls_%sverify_hosts is set, but tls_verify_certificates is not set",
tls_verify_hosts ? "" : "try_");
-/* This also checks that the library linkage is working and we can call
-routines in it, so call even if tls_require_ciphers is unset */
-if (!tls_dropprivs_validate_require_cipher(nowarn))
- exit(1);
-
/* Magic number: at time of writing, 1024 has been the long-standing value
used by so many clients, and what Exim used to use always, that it makes
sense to just min-clamp this max-clamp at that. */
{
int len = dd->options_len;
d->info = dd;
- d->options_block = store_get(len, FALSE);
+ d->options_block = store_get_perm(len, FALSE);
memcpy(d->options_block, dd->options_block, len);
for (int i = 0; i < *(dd->options_count); i++)
dd->options[i].type &= ~opt_set;
+static void
+driver_init_fini(driver_instance * d, const uschar * class)
+{
+if (!d->driver_name)
+ log_write(0, LOG_PANIC_DIE|LOG_CONFIG,
+ "no driver defined for %s \"%s\"", class, d->name);
+(d->info->init)(d);
+}
+
+
/*************************************************
* Initialize driver list *
*************************************************/
driver_instance *d = NULL;
uschar *buffer;
-while ((buffer = get_config_line()) != NULL)
+while ((buffer = get_config_line()))
{
- uschar name[64];
+ uschar name[EXIM_DRIVERNAME_MAX];
uschar *s;
/* Read the first name on the line and test for the start of a new driver. A
{
if (d)
{
- if (!d->driver_name)
- log_write(0, LOG_PANIC_DIE|LOG_CONFIG,
- "no driver defined for %s \"%s\"", class, d->name);
- (d->info->init)(d);
+ /* s is using big_buffer, so this call had better not */
+ driver_init_fini(d, class);
d = NULL;
}
- if (!macro_read_assignment(buffer)) exim_exit(EXIT_FAILURE, US"");
+ if (!macro_read_assignment(buffer)) exim_exit(EXIT_FAILURE);
continue;
}
/* Finish off initializing the previous driver. */
if (d)
- {
- if (!d->driver_name)
- log_write(0, LOG_PANIC_DIE|LOG_CONFIG,
- "no driver defined for %s \"%s\"", class, d->name);
- (d->info->init)(d);
- }
+ driver_init_fini(d, class);
/* Check that we haven't already got a driver of this name */
/* Set up a new driver instance data block on the chain, with
its default values installed. */
- d = store_get(instance_size, FALSE);
+ d = store_get_perm(instance_size, FALSE);
memcpy(d, instance_default, instance_size);
*p = d;
p = &d->next;
/* Check nothing more on this line, then do the next loop iteration. */
- while (isspace(*s)) s++;
- if (*s != 0) extra_chars_error(s, US"driver name ", name, US"");
+ Uskip_whitespace(&s);
+ if (*s) extra_chars_error(s, US"driver name ", name, US"");
continue;
}
/* Run the initialization function for the final driver. */
if (d)
- {
- if (!d->driver_name)
- log_write(0, LOG_PANIC_DIE|LOG_CONFIG,
- "no driver defined for %s \"%s\"", class, d->name);
- (d->info->init)(d);
- }
+ driver_init_fini(d, class);
}
uschar *ss;
for (optionlist * ol = d->info->options; ol < d->info->options + count; ol++)
- {
- void *options_block;
- uschar *value;
- int type = ol->type & opt_mask;
- if (type != opt_stringptr) continue;
- options_block = ((ol->type & opt_public) == 0)? d->options_block : (void *)d;
- value = *(uschar **)(US options_block + (long int)(ol->value));
- if (value != NULL && (ss = Ustrstr(value, s)) != NULL)
+ if ((ol->type & opt_mask) == opt_stringptr)
{
- if (ss <= value || (ss[-1] != '$' && ss[-1] != '{') ||
- isalnum(ss[Ustrlen(s)])) continue;
- DEBUG(D_transport) debug_printf("driver %s: \"%s\" option depends on %s\n",
- d->name, ol->name, s);
- return TRUE;
+ void * options_block = ol->type & opt_public ? (void *)d : d->options_block;
+ uschar * value = *USS(US options_block + ol->v.offset);
+
+ if (value && (ss = Ustrstr(value, s)) != NULL)
+ {
+ if (ss <= value || (ss[-1] != '$' && ss[-1] != '{') ||
+ isalnum(ss[Ustrlen(s)])) continue;
+ DEBUG(D_transport) debug_printf("driver %s: \"%s\" option depends on %s\n",
+ d->name, ol->name, s);
+ return TRUE;
+ }
}
- }
DEBUG(D_transport) debug_printf("driver %s does not depend on %s\n", d->name, s);
return FALSE;
if (*p++ != ',') log_write(0, LOG_PANIC_DIE|LOG_CONFIG_IN, "comma expected");
-while (isspace(*p)) p++;
+Uskip_whitespace(&p);
pp = p;
while (isalnum(*p) || (type == 1 && *p == '.')) p++;
rchain = &(next->rules);
next->pattern = string_dequote(&p);
- while (isspace(*p)) p++;
+ Uskip_whitespace(&p);
pp = p;
while (mac_isgraph(*p)) p++;
if (p - pp <= 0) log_write(0, LOG_PANIC_DIE|LOG_CONFIG_IN,
fudge. Anything that is not a retry rule starting "F," or "G," is treated as
an address list. */
- while (isspace(*p)) p++;
+ Uskip_whitespace(&p);
if (Ustrncmp(p, "senders", 7) == 0)
{
p += 7;
- while (isspace(*p)) p++;
+ Uskip_whitespace(&p);
if (*p++ != '=') log_write(0, LOG_PANIC_DIE|LOG_CONFIG_IN,
"\"=\" expected after \"senders\" in retry rule");
- while (isspace(*p)) p++;
+ Uskip_whitespace(&p);
next->senders = string_dequote(&p);
}
/* Now the retry rules. Keep the maximum timeout encountered. */
- while (isspace(*p)) p++;
+ Uskip_whitespace(&p);
- while (*p != 0)
+ while (*p)
{
retry_rule *rule = store_get(sizeof(retry_rule), FALSE);
*rchain = rule;
log_write(0, LOG_PANIC_DIE|LOG_CONFIG_IN,
"bad parameters for retry rule");
- while (isspace(*p)) p++;
- if (*p == ';')
+ if (Uskip_whitespace(&p) == ';')
{
p++;
- while (isspace(*p)) p++;
+ Uskip_whitespace(&p);
}
- else if (*p != 0)
+ else if (*p)
log_write(0, LOG_PANIC_DIE|LOG_CONFIG_IN, "semicolon expected");
}
}
static void
auths_init(void)
{
-#ifdef SUPPORT_PIPE_CONNECT
+#ifndef DISABLE_PIPE_CONNECT
int nauths = 0;
#endif
for (auth_instance * bu = au->next; bu; bu = bu->next)
if (strcmpic(au->public_name, bu->public_name) == 0)
- if ((au->client && bu->client) || (au->server && bu->server))
+ if ( au->client && bu->client
+ || au->server && bu->server)
log_write(0, LOG_PANIC_DIE|LOG_CONFIG, "two %s authenticators "
"(%s and %s) have the same public name (%s)",
- au->client ? US"client" : US"server", au->name, bu->name,
- au->public_name);
-#ifdef SUPPORT_PIPE_CONNECT
+ au->client && bu->client ? US"client" : US"server",
+ au->name, bu->name, au->public_name);
+#ifndef DISABLE_PIPE_CONNECT
nauths++;
#endif
}
-#ifdef SUPPORT_PIPE_CONNECT
+#ifndef DISABLE_PIPE_CONNECT
f.smtp_in_early_pipe_no_auth = nauths > 16;
#endif
}
while(acl_line)
{
- uschar name[64];
+ uschar name[EXIM_DRIVERNAME_MAX];
tree_node *node;
uschar *error;
p = readconf_readname(name, sizeof(name), acl_line);
if (isupper(*name) && *p == '=')
{
- if (!macro_read_assignment(acl_line)) exim_exit(EXIT_FAILURE, US"");
+ if (!macro_read_assignment(acl_line)) exim_exit(EXIT_FAILURE);
acl_line = get_config_line();
continue;
}
if (*p != ':' || name[0] == 0)
log_write(0, LOG_PANIC_DIE|LOG_CONFIG_IN, "missing or malformed ACL name");
- node = store_get(sizeof(tree_node) + Ustrlen(name), is_tainted(name));
+ node = store_get_perm(sizeof(tree_node) + Ustrlen(name), is_tainted(name));
Ustrcpy(node->name, name);
if (!tree_insertnode(&acl_anchor, node))
log_write(0, LOG_PANIC_DIE|LOG_CONFIG_IN,
uschar *p;
while ((p = get_config_line()))
- {
(void) readconf_handle_option(p, local_scan_options, local_scan_options_count,
NULL, US"local_scan option \"%s\" unknown");
- }
#endif
}
{
const int TS = terse ? 0 : 2;
int indent = 0;
+rmark r = NULL;
-for (config_line_item * i = config_lines; i; i = i->next)
+for (const config_line_item * i = config_lines; i; i = i->next)
{
- uschar *current;
- uschar *p;
+ uschar * current, * p;
+
+ if (r) store_reset(r);
+ r = store_mark();
/* skip over to the first non-space */
- for (current = i->line; *current && isspace(*current); ++current)
+ for (current = string_copy(i->line); *current && isspace(*current); ++current)
;
- if (*current == '\0')
+ if (!*current)
continue;
/* Collapse runs of spaces. We stop this if we encounter one of the
- * following characters: "'$, as this may indicate careful formatting */
- for (p = current; *p; ++p)
+ following characters: "'$, as this may indicate careful formatting */
+
+ for (p = current; *p; p++) if (isspace(*p))
{
uschar *next;
- if (!isspace(*p)) continue;
if (*p != ' ') *p = ' ';
for (next = p; isspace(*next); ++next)
if ((p = Ustrchr(current, '=')))
{
*p = '\0';
- printf("%*s%s= %s\n", indent, "", current, hidden);
+ printf("%*s%s= %s\n", indent, "", current, CCS hidden);
}
/* e.g.: hide split_spool_directory */
else
- printf("%*s\n", indent, hidden);
+ printf("%*s\n", indent, CCS hidden);
}
else
/* rest is public */
printf("%*s%s\n", indent, "", current);
}
+if (r) store_reset(r);
}
#endif /*!MACRO_PREDEF*/