*************************************************/
/* Copyright (c) University of Cambridge 1995 - 2018 */
+/* Copyright (c) The Exim Maintainers 2020 */
/* See the file NOTICE for conditions of use and distribution. */
/* Functions for reading the configuration file, and for displaying
static uschar * syslog_facility_str;
-static void fn_smtp_receive_timeout(const uschar *, const uschar *);
+static void fn_smtp_receive_timeout(const uschar *, const uschar *, unsigned);
/*************************************************
* Main configuration options *
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 },
-#ifdef SUPPORT_TLS
- { "acl_smtp_starttls", opt_stringptr, &acl_smtp_starttls },
+ { "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} },
#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} },
+ { "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_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 },
- { "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 },
-#ifdef SUPPORT_TLS
- { "gnutls_allow_auto_pkcs11", opt_bool, &gnutls_allow_auto_pkcs11 },
- { "gnutls_compat_mode", opt_bool, &gnutls_compat_mode },
+ { "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} },
#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
- { "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
- { "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 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} },
#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 },
-#ifdef SUPPORT_TLS
- { "openssl_options", opt_stringptr, &openssl_options },
+ { "never_users", opt_uidlist, {&never_users} },
+ { "notifier_socket", opt_stringptr, {¬ifier_socket} },
+#ifndef DISABLE_TLS
+ { "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} },
+#ifndef DISABLE_PIPE_CONNECT
+ { "pipelining_connect_advertise_hosts", opt_stringptr,
+ {&pipe_connect_advertise_hosts} },
#endif
- { "pid_file_path", opt_stringptr, &pid_file_path },
- { "pipelining_advertise_hosts", opt_stringptr, &pipelining_advertise_hosts },
#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} },
+#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
- { "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 },
+ { "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, &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 },
-#ifdef SUPPORT_TLS
-# ifdef EXPERIMENTAL_REQUIRETLS
- { "tls_advertise_requiretls", opt_stringptr, &tls_advertise_requiretls },
-# endif
- { "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 },
+ { "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} },
# 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} },
+# ifndef DISABLE_TLS_RESUME
+ { "tls_resumption_hosts", opt_stringptr, {&tls_resumption_hosts} },
# 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 },
- { "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
#ifdef MACRO_PREDEF
-static void fn_smtp_receive_timeout(const uschar * name, const uschar * str) {/*Dummy*/}
+static void
+fn_smtp_receive_timeout(const uschar * name, const uschar * str, unsigned flags) {/*Dummy*/}
void
options_main(void)
void
options_auths(void)
{
-struct auth_info * ai;
-uschar buf[64];
+uschar buf[EXIM_DRIVERNAME_MAX];
options_from_list(optionlist_auths, optionlist_auths_size, US"AUTHENTICATORS", NULL);
-for (ai = auths_available; ai->driver_name[0]; ai++)
+for (struct auth_info * ai = auths_available; ai->driver_name[0]; ai++)
{
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)
{
-bit_table * bp;
-uschar buf[64];
+uschar buf[EXIM_DRIVERNAME_MAX];
-for (bp = log_options; bp < log_options + log_options_count; bp++)
+for (bit_table * bp = log_options; bp < log_options + log_options_count; bp++)
{
spf(buf, sizeof(buf), US"_LOG_%T", bp->name);
builtin_macro_create(buf);
} syslog_fac_item;
/* constants */
-static const char * const hidden = "<value not displayable>";
+static const uschar * const hidden = US"<value not displayable>";
/* Static variables */
static int syslog_list_size = sizeof(syslog_list)/sizeof(syslog_fac_item);
+#define opt_fn_print BIT(0)
+#define opt_fn_print_label BIT(1)
/*************************************************
uschar *
readconf_find_option(void *p)
{
-int i;
-router_instance *r;
-transport_instance *t;
-
-for (i = 0; i < nelem(optionlist_config); i++)
- if (p == optionlist_config[i].value) return US optionlist_config[i].name;
+for (int i = 0; i < nelem(optionlist_config); i++)
+ if (p == optionlist_config[i].v.value) return US optionlist_config[i].name;
-for (r = routers; r; r = r->next)
+for (router_instance * r = routers; r; r = r->next)
{
router_info *ri = r->info;
- for (i = 0; i < *ri->options_count; i++)
+ 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;
}
}
-for (t = transports; t; t = t->next)
+for (transport_instance * t = transports; t; t = t->next)
{
transport_info *ti = t->info;
- for (i = 0; i < *ti->options_count; i++)
+ for (int i = 0; i < *ti->options_count; i++)
{
optionlist * op = &ti->options[i];
if ((op->type & opt_mask) != opt_stringptr) continue;
? CS t
: CS t->options_block
)
- + (long int)op->value)
+ + op->v.offset)
return US op->name;
}
}
macro_item *
macro_create(const uschar * name, const uschar * val, BOOL command_line)
{
-macro_item * m = store_get(sizeof(macro_item));
+macro_item * m = store_get(sizeof(macro_item), FALSE);
READCONF_DEBUG fprintf(stderr, "%s: '%s' '%s'\n", __FUNCTION__, name, val);
m->next = NULL;
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
{
uschar * ss = big_buffer + len;
uschar * s;
-macro_item * m;
/* 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
replacing all occurrences of the macro. */
*macro_found = FALSE;
-if (*s) for (m = *s == '_' ? macros : macros_user; m; m = m->next)
+if (*s) for (macro_item * m = *s == '_' ? macros : macros_user; m; m = m->next)
{
uschar * p, *pp;
uschar * t;
/* 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;
}
/* Handle conditionals, which are also applied to physical lines. Conditions
are of the form ".ifdef ANYTEXT" and are treated as true if any macro
- expansion occured on the rest of the line. A preliminary test for the leading
+ expansion occurred on the rest of the line. A preliminary test for the leading
'.' saves effort on most lines. */
if (*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 (config_lines)
save_config_position(config_filename, config_lineno);
- save = store_get(sizeof(config_file_item));
+ save = store_get(sizeof(config_file_item), FALSE);
save->next = config_file_stack;
config_file_stack = save;
save->file = config_file;
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;
}
static rewrite_rule *
readconf_one_rewrite(const uschar *p, int *existflags, BOOL isglobal)
{
-rewrite_rule *next = store_get(sizeof(rewrite_rule));
+rewrite_rule *next = store_get(sizeof(rewrite_rule), FALSE);
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;
* Custom-handler options *
*************************************************/
static void
-fn_smtp_receive_timeout(const uschar * name, const uschar * str)
+fn_smtp_receive_timeout(const uschar * name, const uschar * str, unsigned flags)
{
-if (*str == '$')
+if (flags & opt_fn_print)
+ {
+ if (flags & opt_fn_print_label) printf("%s = ", name);
+ printf("%s\n", smtp_receive_timeout_s
+ ? string_printing2(smtp_receive_timeout_s, SP_TAB)
+ : readconf_printtime(smtp_receive_timeout));
+ }
+else if (*str == '$')
smtp_receive_timeout_s = string_copy(str);
else
{
{
int ptr = 0;
int offset = 0;
-int n, count, type, value;
+int count, type, value;
int issecure = 0;
uid_t uid;
gid_t gid;
BOOL freesptr = TRUE;
optionlist *ol, *ol2;
struct passwd *pw;
-void *reset_point;
+rmark reset_point;
int intbase = 0;
uschar *inttype = US"";
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. */
it turns out that what we read was "hide", set the flag indicating that
this is a secure option, and loop to read the next word. */
-for (n = 0; n < 2; n++)
+for (int n = 0; n < 2; n++)
{
while (isalnum(*s) || *s == '_')
{
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. */
case opt_gidlist:
case opt_rewrite:
- reset_point = sptr = read_string(s, name);
+ reset_point = store_mark();
+ sptr = read_string(s, name);
/* Having read a string, we now have several different ways of using it,
depending on the data type, so do another switch. If keeping the actual
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;
/* We already have a condition, we're conducting a crude hack to let
multiple condition rules be chained together, despite storing them in
text form. */
- *str_target = string_copy_malloc( (saved_condition = *str_target)
+ *str_target = string_copy_perm( (saved_condition = *str_target)
? string_sprintf("${if and{{bool_lax{%s}}{bool_lax{%s}}}}",
saved_condition, sptr)
- : sptr);
+ : sptr,
+ FALSE);
/* TODO(pdp): there is a memory leak here and just below
when we set 3 or more conditions; I still don't
understand the store mechanism enough to know
}
else if (ol->type & opt_rep_str)
{
- uschar sep_o = Ustrncmp(name, "headers_add", 11)==0 ? '\n' : ':';
+ uschar sep_o =
+ Ustrncmp(name, "headers_add", 11) == 0 ? '\n'
+ : Ustrncmp(name, "set", 3) == 0 ? ';'
+ : ':';
int sep_i = -(int)sep_o;
const uschar * list = sptr;
uschar * s;
list_o = string_append_listele(list_o, sep_o, s);
if (list_o)
- *str_target = string_copy_malloc(string_from_gstring(list_o));
+ *str_target = string_copy_perm(string_from_gstring(list_o), FALSE);
}
else
{
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 */
ignore. Also ignore if the value is already set. */
if (pw == NULL) break;
- Ustrcpy(name+Ustrlen(name)-4, "group");
+ 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",
/* Release store if the value of the string doesn't need to be kept. */
- if (freesptr) store_reset(reset_point);
+ if (freesptr) reset_point = store_reset(reset_point);
break;
/* Expanded boolean: if no characters follow, or if there are no dollar
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);
- ol2 = find_option(name2, oltop, last);
- if (ol2 != NULL)
+ if ((ol2 = find_option(name2, oltop, last)))
{
- reset_point = sptr = read_string(s, name);
- if (data_block == NULL)
- *((uschar **)(ol2->value)) = sptr;
+ reset_point = store_mark();
+ sptr = read_string(s, name);
+ 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;
inttype = US"octal ";
/* Integer: a simple(ish) case; allow octal and hex formats, and
- suffixes K, M and G. The different types affect output, not input. */
+ suffixes K, M, G, and T. The different types affect output, not input. */
case opt_mkint:
case opt_int:
log_write(0, LOG_PANIC_DIE|LOG_CONFIG_IN, "%sinteger expected for %s",
inttype, name);
- if (errno != ERANGE)
- if (tolower(*endptr) == 'k')
- {
- if (lvalue > INT_MAX/1024 || lvalue < INT_MIN/1024) errno = ERANGE;
- else lvalue *= 1024;
- endptr++;
- }
- else if (tolower(*endptr) == 'm')
- {
- if (lvalue > INT_MAX/(1024*1024) || lvalue < INT_MIN/(1024*1024))
- errno = ERANGE;
- else lvalue *= 1024*1024;
- endptr++;
- }
- else if (tolower(*endptr) == 'g')
- {
- if (lvalue > INT_MAX/(1024*1024*1024) || lvalue < INT_MIN/(1024*1024*1024))
- errno = ERANGE;
- else lvalue *= 1024*1024*1024;
- endptr++;
- }
+ if (errno != ERANGE && *endptr)
+ {
+ uschar * mp = US"TtGgMmKk\0"; /* YyZzEePpTtGgMmKk */
+
+ if ((mp = Ustrchr(mp, *endptr)))
+ {
+ endptr++;
+ do
+ {
+ if (lvalue > INT_MAX/1024 || lvalue < INT_MIN/1024)
+ {
+ errno = ERANGE;
+ break;
+ }
+ lvalue *= 1024;
+ }
+ while (*(mp += 2));
+ }
+ }
if (errno == ERANGE || lvalue > INT_MAX || lvalue < INT_MIN)
log_write(0, LOG_PANIC_DIE|LOG_CONFIG_IN,
"absolute value of integer \"%s\" is too large (overflow)", s);
while (isspace(*endptr)) endptr++;
- if (*endptr != 0)
+ if (*endptr)
extra_chars_error(endptr, inttype, US"integer value for ", name);
value = (int)lvalue;
}
- 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;
- /* Integer held in K: again, allow octal and hex formats, and suffixes K, M
- and G. */
- /*XXX consider moving to int_eximarith_t (but mind the overflow test 0415) */
+ /* Integer held in K: again, allow formats and suffixes as above. */
case opt_Kint:
{
uschar *endptr;
errno = 0;
- value = strtol(CS s, CSS &endptr, intbase);
+ int_eximarith_t lvalue = strtol(CS s, CSS &endptr, intbase);
if (endptr == s)
log_write(0, LOG_PANIC_DIE|LOG_CONFIG_IN, "%sinteger expected for %s",
inttype, name);
- if (errno != ERANGE)
- if (tolower(*endptr) == 'g')
- {
- if (value > INT_MAX/(1024*1024) || value < INT_MIN/(1024*1024))
- errno = ERANGE;
- else
- value *= 1024*1024;
- endptr++;
- }
- else if (tolower(*endptr) == 'm')
- {
- if (value > INT_MAX/1024 || value < INT_MIN/1024)
- errno = ERANGE;
- else
- value *= 1024;
- endptr++;
- }
- else if (tolower(*endptr) == 'k')
- endptr++;
+ if (errno != ERANGE && *endptr)
+ {
+ uschar * mp = US"ZzEePpTtGgMmKk\0"; /* YyZzEePpTtGgMmKk */
+
+ if ((mp = Ustrchr(mp, *endptr)))
+ {
+ endptr++;
+ while (*(mp += 2))
+ {
+ if (lvalue > EXIM_ARITH_MAX/1024 || lvalue < EXIM_ARITH_MIN/1024)
+ {
+ errno = ERANGE;
+ break;
+ }
+ lvalue *= 1024;
+ }
+ }
else
- value = (value + 512)/1024;
+ lvalue = (lvalue + 512)/1024;
+ }
if (errno == ERANGE) log_write(0, LOG_PANIC_DIE|LOG_CONFIG_IN,
"absolute value of integer \"%s\" is too large (overflow)", s);
while (isspace(*endptr)) endptr++;
if (*endptr != 0)
extra_chars_error(endptr, inttype, US"integer value for ", name);
- }
- if (data_block == NULL)
- *((int *)(ol->value)) = value;
- else
- *((int *)(US data_block + (long int)(ol->value))) = value;
- break;
+ if (data_block)
+ *(int_eximarith_t *)(US data_block + ol->v.offset) = lvalue;
+ else
+ *(int_eximarith_t *)ol->v.value = lvalue;
+ break;
+ }
/* Fixed-point number: held to 3 decimal places. */
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;
- fn(name, s);
+ 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:
case opt_Kint:
{
- int x = *((int *)value);
+ int_eximarith_t x = *((int_eximarith_t *)value);
if (!no_labels) printf("%s = ", name);
if (x == 0) printf("0\n");
- else if ((x & 1023) == 0) printf("%dM\n", x >> 10);
- else printf("%dK\n", x);
+ else if ((x & ((1<<30)-1)) == 0) printf(PR_EXIM_ARITH "T\n", x >> 30);
+ else if ((x & ((1<<20)-1)) == 0) printf(PR_EXIM_ARITH "G\n", x >> 20);
+ else if ((x & ((1<<10)-1)) == 0) printf(PR_EXIM_ARITH "M\n", x >> 10);
+ else printf(PR_EXIM_ARITH "K\n", x);
}
break;
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;
if (!no_labels) printf("%s =", name);
if (uidlist)
{
- int i;
uschar sep = no_labels ? '\0' : ' ';
- for (i = 1; i <= (int)(uidlist[0]); i++)
+ for (int i = 1; i <= (int)(uidlist[0]); i++)
{
uschar *name = NULL;
if ((pw = getpwuid(uidlist[i]))) name = US pw->pw_name;
if (!no_labels) printf("%s =", name);
if (gidlist)
{
- int i;
uschar sep = no_labels ? '\0' : ' ';
- for (i = 1; i <= (int)(gidlist[0]); i++)
+ for (int i = 1; i <= (int)(gidlist[0]); i++)
{
uschar *name = NULL;
if ((gr = getgrgid(gidlist[i]))) name = US gr->gr_name;
case opt_timelist:
{
- int i;
int *list = (int *)value;
if (!no_labels) printf("%s = ", name);
- for (i = 0; i < list[1]; i++)
+ for (int i = 0; i < list[1]; i++)
printf("%s%s", i == 0 ? "" : ":", readconf_printtime(list[i+2]));
printf("\n");
}
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);
case opt_bool_set:
printf("%s%s\n", (*((BOOL *)value))? "" : "no_", name);
break;
+
+ case opt_func:
+ 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 *ol;
optionlist *ol2 = NULL;
driver_instance *d = NULL;
-macro_item *m;
int size = 0;
if (!type)
{
if (*name == '+')
{
- int i;
tree_node *t;
BOOL found = FALSE;
static uschar *types[] = { US"address", US"domain", US"host",
static tree_node **anchors[] = { &addresslist_anchor, &domainlist_anchor,
&hostlist_anchor, &localpartlist_anchor };
- for (i = 0; i < 4; i++)
+ 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)
if (Ustrcmp(name, "all") == 0)
{
- for (ol = optionlist_config;
+ for (optionlist * ol = optionlist_config;
ol < optionlist_config + nelem(optionlist_config); ol++)
if (!(ol->type & opt_hidden))
(void) print_ol(ol, US ol->name, NULL,
printf("local_scan() options are not supported\n");
return FALSE;
#else
- for (ol = local_scan_options;
+ for (optionlist * ol = local_scan_options;
ol < local_scan_options + local_scan_options_count; ol++)
(void) print_ol(ol, US ol->name, NULL, local_scan_options,
local_scan_options_count, no_labels);
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);
}
fprintf(stderr, "exim: permission denied\n");
return FALSE;
}
- for (m = macros; m; m = m->next)
+ for (macro_item * m = macros; m; m = m->next)
if (!name || Ustrcmp(name, m->name) == 0)
{
if (names_only)
printf("\n%s %s:\n", d->name, type);
else if (Ustrcmp(d->name, name) != 0) continue;
- for (ol = ol2; ol < ol2 + size; ol++)
+ for (optionlist * ol = ol2; ol < ol2 + size; ol++)
if (!(ol->type & opt_hidden))
rc |= print_ol(ol, US ol->name, d, ol2, size, no_labels);
- for (ol = d->info->options;
+ for (optionlist * ol = d->info->options;
ol < d->info->options + *(d->info->options_count); ol++)
if (!(ol->type & opt_hidden))
rc |= print_ol(ol, US ol->name, d, d->info->options,
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));
+namedlist_block * nb = store_get(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);
+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.
-*/
-
-#ifdef SUPPORT_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);
- _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 /* SUPPORT_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)))
{
}
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
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
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, US"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, US"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,
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;
got set above. Of course, writing to the log may not work if log_file_path is
not set, but it will at least get to syslog or somewhere, with any luck. */
-if (*spool_directory == 0)
+if (!*spool_directory)
log_write(0, LOG_MAIN|LOG_PANIC_DIE, "spool_directory undefined: cannot "
"proceed");
/* Expand the spool directory name; it may, for example, contain the primary
host name. Same comment about failure. */
-s = expand_string(spool_directory);
-if (s == NULL)
+if (!(s = expand_string(spool_directory)))
log_write(0, LOG_MAIN|LOG_PANIC_DIE, "failed to expand spool_directory "
"\"%s\": %s", spool_directory, expand_string_message);
spool_directory = s;
the null string or "syslog". It is also allowed to contain one instance of %D
or %M. However, it must NOT contain % followed by anything else. */
-if (*log_file_path != 0)
+if (*log_file_path)
{
const uschar *ss, *sss;
int sep = ':'; /* Fixed for log file path */
- s = expand_string(log_file_path);
- if (s == NULL)
+ if (!(s = expand_string(log_file_path)))
log_write(0, LOG_MAIN|LOG_PANIC_DIE, "failed to expand log_file_path "
"\"%s\": %s", log_file_path, expand_string_message);
ss = s;
- while ((sss = string_nextinlist(&ss,&sep,big_buffer,big_buffer_size)) != NULL)
+ /* should never be a tainted list */
+ while ((sss = string_nextinlist(&ss, &sep, big_buffer, big_buffer_size)))
{
uschar *t;
if (sss[0] == 0 || Ustrcmp(sss, "syslog") == 0) continue;
- t = Ustrstr(sss, "%s");
- if (t == NULL)
+ if (!(t = Ustrstr(sss, "%s")))
log_write(0, LOG_MAIN|LOG_PANIC_DIE, "log_file_path \"%s\" does not "
"contain \"%%s\"", sss);
*t = 'X';
- t = Ustrchr(sss, '%');
- if (t != NULL)
- {
+ if ((t = Ustrchr(sss, '%')))
if ((t[1] != 'D' && t[1] != 'M') || Ustrchr(t+2, '%') != NULL)
log_write(0, LOG_MAIN|LOG_PANIC_DIE, "log_file_path \"%s\" contains "
"unexpected \"%%\" character", s);
- }
}
log_file_path = s;
host_number = n;
}
-#ifdef SUPPORT_TLS
+#ifndef DISABLE_TLS
/* If tls_verify_hosts is set, tls_verify_certificates must also be set */
if ((tls_verify_hosts || tls_try_verify_hosts) && !tls_verify_certificates)
"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. */
"openssl_options parse error: %s", openssl_options);
# endif
}
-#endif /*SUPPORT_TLS*/
+#endif /*DISABLE_TLS*/
if (!nowarn && !keep_environment && environ && *environ)
log_write(0, LOG_MAIN,
init_driver(driver_instance *d, driver_info *drivers_available,
int size_of_info, uschar *class)
{
-driver_info *dd;
-
-for (dd = drivers_available; dd->driver_name[0] != 0;
+for (driver_info * dd = drivers_available; dd->driver_name[0] != 0;
dd = (driver_info *)((US dd) + size_of_info))
- {
if (Ustrcmp(d->driver_name, dd->driver_name) == 0)
{
- int i;
int len = dd->options_len;
d->info = dd;
- d->options_block = store_get(len);
+ d->options_block = store_get(len, FALSE);
memcpy(d->options_block, dd->options_block, len);
- for (i = 0; i < *(dd->options_count); i++)
+ for (int i = 0; i < *(dd->options_count); i++)
dd->options[i].type &= ~opt_set;
return dd;
}
- }
log_write(0, LOG_PANIC_DIE|LOG_CONFIG_IN,
"%s %s: cannot find %s driver \"%s\"", class, d->name, class, d->driver_name);
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->driver_name)
log_write(0, LOG_PANIC_DIE|LOG_CONFIG,
"no driver defined for %s \"%s\"", class, d->name);
+ /* s is using big_buffer, so this call had better not */
(d->info->init)(d);
d = NULL;
}
- if (!macro_read_assignment(buffer)) exim_exit(EXIT_FAILURE, US"");
+ if (!macro_read_assignment(buffer)) exim_exit(EXIT_FAILURE);
continue;
}
if (*s++ == ':')
{
- int i;
-
/* Finish off initializing the previous driver. */
if (d)
/* Set up a new driver instance data block on the chain, with
its default values installed. */
- d = store_get(instance_size);
+ d = store_get(instance_size, FALSE);
memcpy(d, instance_default, instance_size);
*p = d;
p = &d->next;
/* Clear out the "set" bits in the generic options */
- for (i = 0; i < driver_optionlist_count; i++)
+ for (int i = 0; i < driver_optionlist_count; i++)
driver_optionlist[i].type &= ~opt_set;
/* 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;
}
readconf_depends(driver_instance *d, uschar *s)
{
int count = *(d->info->options_count);
-optionlist *ol;
uschar *ss;
-for (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)
+for (optionlist * ol = d->info->options; ol < d->info->options + count; ol++)
+ 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++;
const uschar *pp;
uschar *error;
- next = store_get(sizeof(retry_config));
+ next = store_get(sizeof(retry_config), FALSE);
next->next = NULL;
*chain = next;
chain = &(next->next);
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));
+ retry_rule *rule = store_get(sizeof(retry_rule), FALSE);
*rchain = rule;
rchain = &(rule->next);
rule->next = NULL;
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)
{
-auth_instance *au, *bu;
+#ifndef DISABLE_PIPE_CONNECT
+int nauths = 0;
+#endif
readconf_driver_init(US"authenticator",
(driver_instance **)(&auths), /* chain anchor */
optionlist_auths, /* generic options */
optionlist_auths_size);
-for (au = auths; au; au = au->next)
+for (auth_instance * au = auths; au; au = au->next)
{
if (!au->public_name)
log_write(0, LOG_PANIC_DIE|LOG_CONFIG, "no public name specified for "
"the %s authenticator", au->name);
- for (bu = au->next; bu; bu = bu->next)
+ 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))
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);
+#ifndef DISABLE_PIPE_CONNECT
+ nauths++;
+#endif
}
+#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));
+ node = store_get(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
}
int mid = last/2;
int n = Ustrlen(next_section);
- if (tolower(next_section[n-1]) != 's') Ustrcpy(next_section+n, "s");
+ if (tolower(next_section[n-1]) != 's') Ustrcpy(next_section+n, US"s");
for (;;)
{
static config_line_item *current;
config_line_item *next;
-next = (config_line_item*) store_get(sizeof(config_line_item));
+next = (config_line_item*) store_get(sizeof(config_line_item), FALSE);
next->line = string_copy(line);
next->next = NULL;
void
print_config(BOOL admin, BOOL terse)
{
-config_line_item *i;
const int TS = terse ? 0 : 2;
int indent = 0;
-for (i = config_lines; i; i = i->next)
+for (config_line_item * i = config_lines; i; i = i->next)
{
uschar *current;
uschar *p;
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