List separator specifiers in router/transport headers_add/remove. Bug 1581
[exim.git] / src / src / readconf.c
index 2e18b670e71e4855b4b2b6e31470d3176b6c69be..31a4f2da48ca35c56eec37f450e6de86405217bd 100644 (file)
@@ -11,6 +11,9 @@ implementation of the conditional .ifdef etc. */
 
 #include "exim.h"
 
+static void fn_smtp_receive_timeout(const uschar * name, const uschar * str);
+
+
 #define CSTATE_STACK_SIZE 10
 
 
@@ -205,9 +208,6 @@ 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 },
-#ifdef EXPERIMENTAL_TPDA
-  { "delivery_event_action",    opt_stringptr,   &delivery_event_action },
-#endif
 #ifdef ENABLE_DISABLE_FSYNC
   { "disable_fsync",            opt_bool,        &disable_fsync },
 #endif
@@ -232,13 +232,14 @@ static optionlist optionlist_config[] = {
  /* 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 },
@@ -394,7 +395,7 @@ static optionlist optionlist_config[] = {
   { "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_time,        &smtp_receive_timeout },
+  { "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 },
 #ifdef WITH_CONTENT_SCAN
@@ -497,7 +498,7 @@ for (i = 0; i < optionlist_config_size; i++)
 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))
@@ -508,11 +509,16 @@ for (r = routers; r != NULL; r = r->next)
 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;
     }
   }
 
@@ -1024,7 +1030,7 @@ Returns:        the time value, or -1 on syntax error
 */
 
 int
-readconf_readtime(uschar *s, int terminator, BOOL return_msec)
+readconf_readtime(const uschar *s, int terminator, BOOL return_msec)
 {
 int yield = 0;
 for (;;)
@@ -1033,7 +1039,7 @@ for (;;)
   double fraction;
 
   if (!isdigit(*s)) return -1;
-  (void)sscanf(CS s, "%d%n", &value, &count);
+  (void)sscanf(CCS s, "%d%n", &value, &count);
   s += count;
 
   switch (*s)
@@ -1047,7 +1053,7 @@ for (;;)
 
     case '.':
     if (!return_msec) return -1;
-    (void)sscanf(CS s, "%lf%n", &fraction, &count);
+    (void)sscanf(CCS s, "%lf%n", &fraction, &count);
     s += count;
     if (*s++ != 's') return -1;
     yield += (int)(fraction * 1000.0);
@@ -1347,6 +1353,26 @@ return yield;
 }
 
 
+/*************************************************
+*            Custom-handler options              *
+*************************************************/
+static void
+fn_smtp_receive_timeout(const uschar * name, const uschar * str)
+{
+int value;
+
+if (*str == '$')
+  smtp_receive_timeout_s = string_copy(str);
+else
+  {
+  /* "smtp_receive_timeout",     opt_time,        &smtp_receive_timeout */
+  smtp_receive_timeout = readconf_readtime(str, 0, FALSE);
+  if (smtp_receive_timeout < 0)
+    log_write(0, LOG_PANIC_DIE|LOG_CONFIG_IN, "invalid time value for %s",
+      name);
+  }
+}
+
 /*************************************************
 *            Handle option line                  *
 *************************************************/
@@ -1483,7 +1509,7 @@ if (type < opt_bool || type > opt_bool_last)
   }
 
 /* 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 != '='))
@@ -1571,18 +1597,16 @@ switch (type)
       }
     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);
+      uschar sep_o = Ustrncmp(name, "headers_add", 11)==0 ? '\n' : ':';
+      int    sep_i = -(int)sep_o;
+      uschar * list = sptr;
+      uschar * s;
+      uschar * list_o = *str_target;
+
+      while ((s = string_nextinlist(&list, &sep_i, NULL, 0)))
+       list_o = string_append_listele(list_o, sep_o, s);
+      if (list_o)
+       *str_target = string_copy_malloc(list_o);
       }
     else
       {
@@ -2113,9 +2137,15 @@ switch (type)
         name);
     if (count > 0 && list[2] == 0) count = 0;
     list[1] = count;
+    break;
     }
 
-  break;
+  case opt_func:
+    {
+    void (*fn)() = ol->value;
+    fn(name, s);
+    break;
+    }
   }
 
 return TRUE;
@@ -3003,7 +3033,12 @@ file is a serious disaster. */
 
 if (config_file != NULL)
   {
+  uschar *p;
   config_filename = config_main_filename = string_copy(filename);
+
+  p = Ustrrchr(filename, '/');
+  config_main_directory = p ? string_copyn(filename, p - filename) 
+                            : string_copy(US".");
   }
 else
   {