* Exim - an Internet mail transport agent *
*************************************************/
-/* Copyright (c) University of Cambridge 1995 - 2012 */
+/* Copyright (c) University of Cambridge 1995 - 2014 */
/* See the file NOTICE for conditions of use and distribution. */
/* Functions for reading the configuration file, and for displaying
{ "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 },
+#endif
#ifndef DISABLE_DKIM
{ "acl_smtp_dkim", opt_stringptr, &acl_smtp_dkim },
#endif
{ "disable_ipv6", opt_bool, &disable_ipv6 },
#ifndef DISABLE_DKIM
{ "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 },
#endif
{ "dns_again_means_nonexist", opt_stringptr, &dns_again_means_nonexist },
{ "dns_check_names_pattern", opt_stringptr, &check_dns_names_pattern },
{ "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_use_dnssec", opt_int, &dns_use_dnssec },
{ "dns_use_edns0", opt_int, &dns_use_edns0 },
/* This option is now a no-op, retained for compability */
{ "drop_cr", opt_bool, &drop_cr },
/*********************************************************/
+#ifdef EXPERIMENTAL_DSN
+ { "dsn_advertise_hosts", opt_stringptr, &dsn_advertise_hosts },
+#endif
{ "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 },
+#ifdef EXPERIMENTAL_EVENT
+ { "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 },
{ "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 },
/* These three gnutls_require_* options stopped working in Exim 4.80 */
+ /* From 4.83 we log a warning; a future relase will remove them */
{ "gnutls_require_kx", opt_stringptr, &gnutls_require_kx },
{ "gnutls_require_mac", opt_stringptr, &gnutls_require_mac },
{ "gnutls_require_protocols", opt_stringptr, &gnutls_require_proto },
#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 },
+#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 EXPERIMENTAL_PROXY
+ { "proxy_required_hosts", opt_stringptr, &proxy_required_hosts },
+#endif
{ "qualify_domain", opt_stringptr, &qualify_domain_sender },
{ "qualify_recipient", opt_stringptr, &qualify_domain_recipient },
{ "queue_domains", opt_stringptr, &queue_domains },
{ "recipient_unqualified_hosts", opt_stringptr, &recipient_unqualified_hosts },
{ "recipients_max", opt_int, &recipients_max },
{ "recipients_max_reject", opt_bool, &recipients_max_reject },
+#ifdef EXPERIMENTAL_REDIS
+ { "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 },
{ "tls_crl", opt_stringptr, &tls_crl },
{ "tls_dh_max_bits", opt_int, &tls_dh_max_bits },
{ "tls_dhparam", opt_stringptr, &tls_dhparam },
-# if defined(EXPERIMENTAL_OCSP) && !defined(USE_GNUTLS)
+# ifndef DISABLE_OCSP
{ "tls_ocsp_file", opt_stringptr, &tls_ocsp_file },
# endif
{ "tls_on_connect_ports", opt_stringptr, &tls_in.on_connect_ports },
for (r = routers; r != NULL; r = r->next)
{
router_info *ri = r->info;
- for (i = 0; i < ri->options_count[0]; i++)
+ for (i = 0; i < *ri->options_count; i++)
{
if ((ri->options[i].type & opt_mask) != opt_stringptr) continue;
if (p == (char *)(r->options_block) + (long int)(ri->options[i].value))
for (t = transports; t != NULL; t = t->next)
{
transport_info *ti = t->info;
- for (i = 0; i < ti->options_count[0]; i++)
+ for (i = 0; i < *ti->options_count; i++)
{
- if ((ti->options[i].type & opt_mask) != opt_stringptr) continue;
- if (p == (char *)(t->options_block) + (long int)(ti->options[i].value))
- return US ti->options[i].name;
+ optionlist * op = &ti->options[i];
+ if ((op->type & opt_mask) != opt_stringptr) continue;
+ if (p == ( op->type & opt_public
+ ? (char *)t
+ : (char *)t->options_block
+ )
+ + (long int)op->value)
+ return US op->name;
}
}
gid_t gid;
BOOL boolvalue = TRUE;
BOOL freesptr = TRUE;
-BOOL extra_condition = FALSE;
optionlist *ol, *ol2;
struct passwd *pw;
void *reset_point;
log_write(0, LOG_PANIC_DIE|LOG_CONFIG_IN, CS unknown_txt, name);
}
-if ((ol->type & opt_set) != 0)
- {
- uschar *mname = name;
- if (Ustrncmp(mname, "no_", 3) == 0) mname += 3;
- if (Ustrcmp(mname, "condition") == 0)
- extra_condition = TRUE;
- else
- log_write(0, LOG_PANIC_DIE|LOG_CONFIG_IN,
- "\"%s\" option set for the second time", mname);
- }
+if ((ol->type & opt_set) && !(ol->type & (opt_rep_con | opt_rep_str)))
+ log_write(0, LOG_PANIC_DIE|LOG_CONFIG_IN,
+ "\"%s\" option set for the second time", name);
ol->type |= opt_set | issecure;
type = ol->type & opt_mask;
}
/* If a boolean wasn't preceded by "no[t]_" it can be followed by = and
-true/false/yes/no, or, in the case of opt_expanded_bool, a general string that
+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 != '='))
str_target = (uschar **)(ol->value);
else
str_target = (uschar **)((uschar *)data_block + (long int)(ol->value));
- if (extra_condition)
+ if (ol->type & opt_rep_con)
{
/* We already have a condition, we're conducting a crude hack to let
multiple condition rules be chained together, despite storing them in
strtemp = string_sprintf("${if and{{bool_lax{%s}}{bool_lax{%s}}}}",
saved_condition, sptr);
*str_target = string_copy_malloc(strtemp);
- /* TODO(pdp): there is a memory leak here when we set 3 or more
- conditions; I still don't understand the store mechanism enough
- to know what's the safe way to free content from an earlier store.
+ /* 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
+ what's the safe way to free content from an earlier store.
AFAICT, stores stack, so freeing an early stored item also stores
all data alloc'd after it. If we knew conditions were adjacent,
we could survive that, but we don't. So I *think* we need to take
Because we only do this once, near process start-up, I'm prepared to
let this slide for the time being, even though it rankles. */
}
+ else if (ol->type & opt_rep_str)
+ {
+ uschar sep = Ustrncmp(name, "headers_add", 11)==0 ? '\n' : ':';
+ uschar * cp;
+
+ /* Strip trailing whitespace and seperators */
+ for (cp = sptr + Ustrlen(sptr) - 1;
+ cp >= sptr && (*cp == '\n' || *cp == '\t' || *cp == ' ' || *cp == sep);
+ cp--) *cp = '\0';
+
+ if (cp >= sptr)
+ *str_target = string_copy_malloc(
+ *str_target ? string_sprintf("%s%c%s", *str_target, sep, sptr)
+ : sptr);
+ }
else
{
*str_target = sptr;
if (config_file != NULL)
{
+ uschar *p;
config_filename = config_main_filename = string_copy(filename);
+
+ p = strrchr(filename, '/');
+ config_main_directory = p ? string_copyn(filename, p - filename)
+ : string_copy(".");
}
else
{
"openssl_options parse error: %s", openssl_options);
# endif
}
-#endif
+
+if (gnutls_require_kx || gnutls_require_mac || gnutls_require_proto)
+ log_write(0, LOG_MAIN, "WARNING: main options"
+ " gnutls_require_kx, gnutls_require_mac and gnutls_require_protocols"
+ " are obsolete\n");
+#endif /*SUPPORT_TLS*/
}
pp = p;
while (mac_isgraph(*p)) p++;
if (p - pp <= 0) log_write(0, LOG_PANIC_DIE|LOG_CONFIG_IN,
- "missing error type");
+ "missing error type in retry rule");
/* Test error names for things we understand. */
/* Now the main function:
-Arguments:
- skip TRUE when this Exim process is doing something that will
- not need the ACL data
-
+Arguments: none
Returns: nothing
*/
static void
-readconf_acl(BOOL skip)
+readconf_acl(void)
{
uschar *p;
-/* Not receiving messages, don't need to parse the ACL data */
-
-if (skip)
- {
- DEBUG(D_acl) debug_printf("skipping ACL configuration - not needed\n");
- while ((p = get_config_line()) != NULL);
- return;
- }
-
/* Read each ACL and add it into the tree. Macro (re)definitions are allowed
between ACLs. */
we add "s" if it's missing. There is always enough room in next_section for
this. This function is basically just a switch.
-Arguments:
- skip_acl TRUE if ACL information is not needed
-
+Arguments: none
Returns: nothing
*/
US"transports"};
void
-readconf_rest(BOOL skip_acl)
+readconf_rest(void)
{
int had = 0;
switch(mid)
{
- case 0: readconf_acl(skip_acl); break;
+ case 0: readconf_acl(); break;
case 1: auths_init(); break;
case 2: local_scan_init(); break;
case 3: readconf_retries(); break;
(void)fclose(config_file);
}
+/* vi: aw ai sw=2
+*/
/* End of readconf.c */