Add new errors mail_4xx, data_4xx, lost_connection, tls_required.
[exim.git] / src / src / readconf.c
index 220438ada3504d94d514f6b3921cc2280e3906c9..d1911a7b634289e69c31162613b89e9c8a496208 100644 (file)
@@ -1,10 +1,10 @@
-/* $Cambridge: exim/src/src/readconf.c,v 1.12 2005/08/08 10:48:27 ph10 Exp $ */
+/* $Cambridge: exim/src/src/readconf.c,v 1.22 2006/03/09 15:10:16 ph10 Exp $ */
 
 /*************************************************
 *     Exim - an Internet mail transport agent    *
 *************************************************/
 
-/* Copyright (c) University of Cambridge 1995 - 2005 */
+/* Copyright (c) University of Cambridge 1995 - 2006 */
 /* See the file NOTICE for conditions of use and distribution. */
 
 /* Functions for reading the configuration file, and for displaying
@@ -182,6 +182,7 @@ static optionlist optionlist_config[] = {
   { "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 },
   { "daemon_smtp_port",         opt_stringptr|opt_hidden, &daemon_smtp_port },
@@ -193,6 +194,7 @@ static optionlist optionlist_config[] = {
   { "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 },
+  { "disable_ipv6",             opt_bool,        &disable_ipv6 },
   { "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 },
@@ -810,6 +812,10 @@ for (;;)
       }
     *t = 0;
 
+    if (*ss != '/')
+      log_write(0, LOG_PANIC_DIE|LOG_CONFIG_IN, ".include specifies a non-"
+        "absolute path \"%s\"", ss);
+
     if (include_if_exists != 0 && (Ustat(ss, &statbuf) != 0)) continue;
 
     save = store_get(sizeof(config_file_item));
@@ -1625,10 +1631,16 @@ switch (type)
       int count = 1;
       uid_t *list;
       int ptr = 0;
-      uschar *p = sptr;
+      uschar *p;
+      uschar *op = expand_string (sptr);
 
+      if (op == NULL)
+        log_write(0, LOG_PANIC_DIE|LOG_CONFIG_IN, "failed to expand %s: %s",
+          name, expand_string_message);
+
+      p = op;
       if (*p != 0) count++;
-      while (*p != 0) if (*p++ == ':') count++;
+      while (*p != 0) if (*p++ == ':' && *p != 0) count++;
       list = store_malloc(count*sizeof(uid_t));
       list[ptr++] = (uid_t)(count - 1);
 
@@ -1637,7 +1649,7 @@ switch (type)
       else
         *((uid_t **)((uschar *)data_block + (long int)(ol->value))) = list;
 
-      p = sptr;
+      p = op;
       while (count-- > 1)
         {
         int sep = 0;
@@ -1660,10 +1672,16 @@ switch (type)
       int count = 1;
       gid_t *list;
       int ptr = 0;
-      uschar *p = sptr;
+      uschar *p;
+      uschar *op = expand_string (sptr);
 
+      if (op == NULL)
+        log_write(0, LOG_PANIC_DIE|LOG_CONFIG_IN, "failed to expand %s: %s",
+          name, expand_string_message);
+
+      p = op;
       if (*p != 0) count++;
-      while (*p != 0) if (*p++ == ':') count++;
+      while (*p != 0) if (*p++ == ':' && *p != 0) count++;
       list = store_malloc(count*sizeof(gid_t));
       list[ptr++] = (gid_t)(count - 1);
 
@@ -1672,7 +1690,7 @@ switch (type)
       else
         *((gid_t **)((uschar *)data_block + (long int)(ol->value))) = list;
 
-      p = sptr;
+      p = op;
       while (count-- > 1)
         {
         int sep = 0;
@@ -1997,6 +2015,12 @@ readconf_printtime(int t)
 int s, m, h, d, w;
 uschar *p = time_buffer;
 
+if (t < 0)
+  {
+  *p++ = '-';
+  t = -t;
+  }
+
 s = t % 60;
 t /= 60;
 m = t % 60;
@@ -2795,10 +2819,19 @@ wanted. */
 
 if (timezone_string != NULL && *timezone_string == 0) timezone_string = NULL;
 
+/* The max retry interval must not be greater than 24 hours. */
+
+if (retry_interval_max > 24*60*60) retry_interval_max = 24*60*60;
+
 /* remote_max_parallel must be > 0 */
 
 if (remote_max_parallel <= 0) remote_max_parallel = 1;
 
+/* Save the configured setting of freeze_tell, so we can re-instate it at the
+start of a new SMTP message. */
+
+freeze_tell_config = freeze_tell;
+
 /* The primary host name may be required for expansion of spool_directory
 and log_file_path, so make sure it is set asap. It is obtained from uname(),
 but if that yields an unqualified value, make a FQDN by using gethostbyname to
@@ -2819,9 +2852,9 @@ if (primary_hostname == NULL)
     struct hostent *hostdata;
 
     #if HAVE_IPV6
-    if (dns_ipv4_lookup == NULL ||
+    if (!disable_ipv6 && (dns_ipv4_lookup == NULL ||
          match_isinlist(hostname, &dns_ipv4_lookup, 0, NULL, NULL, MCL_DOMAIN,
-           TRUE, NULL) != OK)
+           TRUE, NULL) != OK))
       af = AF_INET6;
     #else
     af = AF_INET;
@@ -3388,7 +3421,9 @@ else if (len == 7 && strncmpic(pp, US"timeout", len) == 0)
     }
   }
 
-else if (strncmpic(pp, US"rcpt_4", 6) == 0)
+else if (strncmpic(pp, US"mail_4", 6) == 0 ||
+         strncmpic(pp, US"rcpt_4", 6) == 0 ||
+         strncmpic(pp, US"data_4", 6) == 0)
   {
   BOOL bad = FALSE;
   int x = 255;                           /* means "any 4xx code" */
@@ -3405,18 +3440,24 @@ else if (strncmpic(pp, US"rcpt_4", 6) == 0)
     else if (a != 'x' || b != 'x') bad = TRUE;
     }
 
-  if (bad) return US"rcpt_4 must be followed by xx, dx, or dd, where "
-    "x is literal and d is any digit";
+  if (bad)
+    return string_sprintf("%.4s_4 must be followed by xx, dx, or dd, where "
+      "x is literal and d is any digit", pp);
 
-  *basic_errno = ERRNO_RCPT4XX;
+  *basic_errno = (*pp == 'm')? ERRNO_MAIL4XX :
+                 (*pp == 'r')? ERRNO_RCPT4XX : ERRNO_DATA4XX;
   *more_errno = x << 8;
   }
 
 else if (len == 4 && strncmpic(pp, US"auth", len) == 0 &&
          strncmpic(q+1, US"failed", p-q-1) == 0)
-  {
   *basic_errno = ERRNO_AUTHFAIL;
-  }
+
+else if (strcmpic(pp, US"lost_connection") == 0)
+  *basic_errno = ERRNO_SMTPCLOSED;
+
+else if (strcmpic(pp, US"tls_required") == 0)
+  *basic_errno = ERRNO_TLSREQUIRED;
 
 else if (len != 1 || Ustrncmp(pp, "*", 1) != 0)
   return string_sprintf("unknown or malformed retry error \"%.*s\"", p-pp, pp);
@@ -3554,6 +3595,7 @@ while ((p = get_config_line()) != NULL)
       break;
 
       case 'G':   /* Geometrically increasing intervals */
+      case 'H':   /* Ditto, but with randomness */
       rule->p1 = retry_arg(&p, 0);
       rule->p2 = retry_arg(&p, 1);
       break;
@@ -3564,7 +3606,7 @@ while ((p = get_config_line()) != NULL)
       }
 
     if (rule->timeout <= 0 || rule->p1 <= 0 ||
-          (rule->rule == 'G' && rule->p2 < 1000))
+          (rule->rule != 'F' && rule->p2 < 1000))
       log_write(0, LOG_PANIC_DIE|LOG_CONFIG_IN,
         "bad parameters for retry rule");