Add macro support to -be expansion test mode. Bug 1623
authorJeremy Harris <jgh146exb@wizmail.org>
Tue, 31 Oct 2017 15:31:50 +0000 (15:31 +0000)
committerJeremy Harris <jgh146exb@wizmail.org>
Tue, 31 Oct 2017 15:31:50 +0000 (15:31 +0000)
22 files changed:
doc/doc-docbook/spec.xfpt
doc/doc-txt/NewStuff
src/src/exim.c
src/src/functions.h
src/src/readconf.c
src/src/sieve.c
test/scripts/0000-Basic/0002
test/scripts/0000-Basic/0542
test/scripts/3300-crypteq/3300
test/scripts/4200-International/4200
test/stderr/0002
test/stderr/0236
test/stderr/0387
test/stderr/0484
test/stderr/2200
test/stderr/2600
test/stderr/3000
test/stderr/3212
test/stdout/0002
test/stdout/0542
test/stdout/3300
test/stdout/4200

index a9a048ecb3640fa30028675eece740f19011cebe..13fcad7244359f9ac7be40b59b0d87be08527688 100644 (file)
@@ -2791,6 +2791,13 @@ files or databases you are using, you must exit and restart Exim before trying
 the same lookup again. Otherwise, because each Exim process caches the results
 of lookups, you will just get the same result as before.
 
+.new
+Macro processing is done on lines before string-expansion: new macros can be
+defined and macros will be expanded.
+Because macros in the config file are often used for secrets, those are only
+available to admin users.
+.wen
+
 .vitem &%-bem%&&~<&'filename'&>
 .oindex "&%-bem%&"
 .cindex "testing" "string expansion"
index 6d875d5f42ba6e0020b0ed9d07fd4b864fd815af..22af13554e3f75f98e766c564c1f768bd62a8894 100644 (file)
@@ -61,6 +61,9 @@ Version 4.90
 15. TCP Fast Open used, with data-on-SYN, for client SMTP via SOCKS5 proxy,
     for ${readsocket } expansions, and for ClamAV.
 
+16. The "-be" expansion test mode now supports macros.  Macros are expanded
+    in test lines, and new macros can be defined.
+
 
 Version 4.89
 ------------
index 7dd08453419d84f31aac4cdb6432c6d34af69c15..d71af0ac4056768586320b24e8b00b615ae19a03 100644 (file)
@@ -1457,6 +1457,39 @@ return TRUE;
 }
 
 
+/*************************************************
+*          Expansion testing                    *
+*************************************************/
+
+/* Expand and print one item, doing macro-processing.
+
+Arguments:
+  item         line for expansion
+*/
+
+static void
+expansion_test_line(uschar * line)
+{
+int len;
+BOOL dummy_macexp;
+
+Ustrncpy(big_buffer, line, big_buffer_size);
+big_buffer[big_buffer_size-1] = '\0';
+len = Ustrlen(big_buffer);
+
+(void) macros_expand(0, &len, &dummy_macexp);
+
+if (isupper(big_buffer[0]))
+  {
+  if (macro_read_assignment(big_buffer))
+    printf("Defined macro '%s'\n", mlast->name);
+  }
+else
+  if ((line = expand_string(big_buffer))) printf("%s\n", CS line);
+  else printf("Failed: %s\n", expand_string_message);
+}
+
+
 /*************************************************
 *          Entry point and high-level code       *
 *************************************************/
@@ -4988,7 +5021,7 @@ if (expansion_test)
   /* Read a test message from a file. We fudge it up to be on stdin, saving
   stdin itself for later reading of expansion strings. */
 
-  else if (expansion_test_message != NULL)
+  else if (expansion_test_message)
     {
     int save_stdin = dup(0);
     int fd = Uopen(expansion_test_message, O_RDONLY, 0);
@@ -5008,6 +5041,10 @@ if (expansion_test)
     clearerr(stdin);               /* Required by Darwin */
     }
 
+  /* Only admin users may see config-file macros this way */
+
+  if (!admin_user) macros = mlast = NULL;
+
   /* Allow $recipients for this testing */
 
   enable_dollar_recipients = TRUE;
@@ -5015,15 +5052,8 @@ if (expansion_test)
   /* Expand command line items */
 
   if (recipients_arg < argc)
-    {
     while (recipients_arg < argc)
-      {
-      uschar *s = argv[recipients_arg++];
-      uschar *ss = expand_string(s);
-      if (ss == NULL) printf ("Failed: %s\n", expand_string_message);
-      else printf("%s\n", CS ss);
-      }
-    }
+      expansion_test_line(argv[recipients_arg++]);
 
   /* Read stdin */
 
@@ -5031,25 +5061,18 @@ if (expansion_test)
     {
     char *(*fn_readline)(const char *) = NULL;
     void (*fn_addhist)(const char *) = NULL;
+    uschar * s;
 
-    #ifdef USE_READLINE
+#ifdef USE_READLINE
     void *dlhandle = set_readline(&fn_readline, &fn_addhist);
-    #endif
+#endif
 
-    for (;;)
-      {
-      uschar *ss;
-      uschar *source = get_stdinput(fn_readline, fn_addhist);
-      if (source == NULL) break;
-      ss = expand_string(source);
-      if (ss == NULL)
-        printf ("Failed: %s\n", expand_string_message);
-      else printf("%s\n", CS ss);
-      }
+    while (s = get_stdinput(fn_readline, fn_addhist))
+      expansion_test_line(s);
 
-    #ifdef USE_READLINE
-    if (dlhandle != NULL) dlclose(dlhandle);
-    #endif
+#ifdef USE_READLINE
+    if (dlhandle) dlclose(dlhandle);
+#endif
     }
 
   /* The data file will be open after -Mset */
@@ -5060,7 +5083,7 @@ if (expansion_test)
     deliver_datafile = -1;
     }
 
-  exim_exit(EXIT_SUCCESS, US"main");
+  exim_exit(EXIT_SUCCESS, US"main: expansion test");
   }
 
 
index 1fe561f5675864e81ada389e3064eddf72168dbc..e50fa6f92751ddd28b4170a065d3feb01aeba764 100644 (file)
@@ -257,6 +257,8 @@ extern int     log_create_as_exim(uschar *);
 extern void    log_close_all(void);
 
 extern macro_item * macro_create(const uschar *, const uschar *, BOOL);
+extern BOOL    macro_read_assignment(uschar *);
+extern uschar *macros_expand(int, int *, BOOL *);
 extern void    mainlog_close(void);
 #ifdef WITH_CONTENT_SCAN
 extern int     malware(const uschar *, int);
index b34372c445d756734532cbb131270c23c71d555a..8d5f38c58c24105e93ad2c14164ab0a8b0554ec4 100644 (file)
@@ -615,7 +615,10 @@ m->namelen = Ustrlen(name);
 m->replen = Ustrlen(val);
 m->name = name;
 m->replacement = val;
-mlast->next = m;
+if (mlast)
+  mlast->next = m;
+else
+  macros = m;
 mlast = m;
 return m;
 }
@@ -630,11 +633,11 @@ non-command line, macros is permitted using '==' instead of '='.
 Arguments:
   s            points to the start of the logical line
 
-Returns:       nothing
+Returns:       FALSE iff fatal error
 */
 
-static void
-read_macro_assignment(uschar *s)
+BOOL
+macro_read_assignment(uschar *s)
 {
 uschar name[64];
 int namelen = 0;
@@ -644,15 +647,21 @@ macro_item *m;
 while (isalnum(*s) || *s == '_')
   {
   if (namelen >= sizeof(name) - 1)
-    log_write(0, LOG_PANIC_DIE|LOG_CONFIG_IN,
+    {
+    log_write(0, LOG_PANIC|LOG_CONFIG_IN,
       "macro name too long (maximum is " SIZE_T_FMT " characters)", sizeof(name) - 1);
+    return FALSE;
+    }
   name[namelen++] = *s++;
   }
 name[namelen] = 0;
 
 while (isspace(*s)) s++;
 if (*s++ != '=')
-  log_write(0, LOG_PANIC_DIE|LOG_CONFIG_IN, "malformed macro definition");
+  {
+  log_write(0, LOG_PANIC|LOG_CONFIG_IN, "malformed macro definition");
+  return FALSE;
+  }
 
 if (*s == '=')
   {
@@ -675,15 +684,21 @@ for (m = macros; m; m = m->next)
   if (Ustrcmp(m->name, name) == 0)
     {
     if (!m->command_line && !redef)
-      log_write(0, LOG_CONFIG|LOG_PANIC_DIE, "macro \"%s\" is already "
+      {
+      log_write(0, LOG_CONFIG|LOG_PANIC, "macro \"%s\" is already "
        "defined (use \"==\" if you want to redefine it", name);
+      return FALSE;
+      }
     break;
     }
 
   if (m->namelen < namelen && Ustrstr(name, m->name) != NULL)
-    log_write(0, LOG_CONFIG|LOG_PANIC_DIE, "\"%s\" cannot be defined as "
+    {
+    log_write(0, LOG_CONFIG|LOG_PANIC, "\"%s\" cannot be defined as "
       "a macro because previously defined macro \"%s\" is a substring",
       name, m->name);
+    return FALSE;
+    }
 
   /* We cannot have this test, because it is documented that a substring
   macro is permitted (there is even an example).
@@ -697,7 +712,7 @@ for (m = macros; m; m = m->next)
 
 /* Check for an overriding command-line definition. */
 
-if (m && m->command_line) return;
+if (m && m->command_line) return TRUE;
 
 /* Redefinition must refer to an existing macro. */
 
@@ -708,18 +723,119 @@ if (redef)
     m->replacement = string_copy(s);
     }
   else
-    log_write(0, LOG_CONFIG|LOG_PANIC_DIE, "can't redefine an undefined macro "
+    {
+    log_write(0, LOG_CONFIG|LOG_PANIC, "can't redefine an undefined macro "
       "\"%s\"", name);
+    return FALSE;
+    }
 
 /* We have a new definition. */
 else
   (void) macro_create(string_copy(name), string_copy(s), FALSE);
+return TRUE;
 }
 
 
 
 
 
+/* Process line for macros. The line is in big_buffer starting at offset len.
+Expand big_buffer if needed.  Handle definitions of new macros, and
+imacro expansions, rewriting the line in thw buffer.
+
+Arguments:
+ len           Offset in buffer of start of line
+ newlen                Pointer to offset of end of line, updated on return
+ macro_found   Pointer to return that a macro was expanded
+
+Return: pointer to first nonblank char in line
+*/
+
+uschar *
+macros_expand(int len, int * newlen, BOOL * macro_found)
+{
+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++;
+
+/* 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
+upper case character followed by a sequence of name characters and an equals
+sign, because that is the definition of a new macro, and we don't do
+replacement therein. */
+
+s = ss;
+if (len == 0 && isupper(*s))
+  {
+  while (isalnum(*s) || *s == '_') s++;
+  while (isspace(*s)) s++;
+  if (*s != '=') s = ss;          /* Not a macro definition */
+  }
+
+/* Skip leading chars which cannot start a macro name, to avoid multiple
+pointless rescans in Ustrstr calls. */
+
+while (*s && !isupper(*s) && *s != '_') s++;
+
+/* For each defined macro, scan the line (from after XXX= if present),
+replacing all occurrences of the macro. */
+
+*macro_found = FALSE;
+for (m = macros; m; m = m->next)
+  {
+  uschar * p, *pp;
+  uschar * t = s;
+
+  while ((p = Ustrstr(t, m->name)) != NULL)
+    {
+    int moveby;
+
+/* fprintf(stderr, "%s: matched '%s' in '%s'\n", __FUNCTION__, m->name, ss); */
+    /* Expand the buffer if necessary */
+
+    while (*newlen - m->namelen + m->replen + 1 > big_buffer_size)
+      {
+      int newsize = big_buffer_size + BIG_BUFFER_SIZE;
+      uschar *newbuffer = store_malloc(newsize);
+      memcpy(newbuffer, big_buffer, *newlen + 1);
+      p = newbuffer  + (p - big_buffer);
+      s = newbuffer  + (s - big_buffer);
+      ss = newbuffer + (ss - big_buffer);
+      t = newbuffer  + (t - big_buffer);
+      big_buffer_size = newsize;
+      store_free(big_buffer);
+      big_buffer = newbuffer;
+      }
+
+    /* Shuffle the remaining characters up or down in the buffer before
+    copying in the replacement text. Don't rescan the replacement for this
+    same macro. */
+
+    pp = p + m->namelen;
+    if ((moveby = m->replen - m->namelen) != 0)
+      {
+      memmove(p + m->replen, pp, (big_buffer + *newlen) - pp + 1);
+      *newlen += moveby;
+      }
+    Ustrncpy(p, m->replacement, m->replen);
+    t = p + m->replen;
+    while (*t && !isupper(*t) && *t != '_') t++;
+    *macro_found = TRUE;
+    }
+  }
+
+/* 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++;
+return ss;
+}
+
 /*************************************************
 *            Read configuration line             *
 *************************************************/
@@ -749,7 +865,6 @@ int startoffset = 0;         /* To first non-blank char in logical line */
 int len = 0;                 /* Of logical line so far */
 int newlen;
 uschar *s, *ss;
-macro_item *m;
 BOOL macro_found;
 
 /* Loop for handling continuation lines, skipping comments, and dealing with
@@ -810,82 +925,7 @@ for (;;)
     newlen += Ustrlen(big_buffer + newlen);
     }
 
-  /* Find the true start of the physical line - leading spaces are always
-  ignored. */
-
-  ss = big_buffer + len;
-  while (isspace(*ss)) 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
-  upper case character followed by a sequence of name characters and an equals
-  sign, because that is the definition of a new macro, and we don't do
-  replacement therein. */
-
-  s = ss;
-  if (len == 0 && isupper(*s))
-    {
-    while (isalnum(*s) || *s == '_') s++;
-    while (isspace(*s)) s++;
-    if (*s != '=') s = ss;          /* Not a macro definition */
-    }
-
-  /* Skip leading chars which cannot start a macro name, to avoid multiple
-  pointless rescans in Ustrstr calls. */
-
-  while (*s && !isupper(*s) && *s != '_') s++;
-
-  /* For each defined macro, scan the line (from after XXX= if present),
-  replacing all occurrences of the macro. */
-
-  macro_found = FALSE;
-  for (m = macros; m; m = m->next)
-    {
-    uschar * p, *pp;
-    uschar * t = s;
-
-    while ((p = Ustrstr(t, m->name)) != NULL)
-      {
-      int moveby;
-
-/* fprintf(stderr, "%s: matched '%s' in '%s'\n", __FUNCTION__, m->name, ss); */
-      /* Expand the buffer if necessary */
-
-      while (newlen - m->namelen + m->replen + 1 > big_buffer_size)
-        {
-        int newsize = big_buffer_size + BIG_BUFFER_SIZE;
-        uschar *newbuffer = store_malloc(newsize);
-        memcpy(newbuffer, big_buffer, newlen + 1);
-        p = newbuffer  + (p - big_buffer);
-        s = newbuffer  + (s - big_buffer);
-        ss = newbuffer + (ss - big_buffer);
-        t = newbuffer  + (t - big_buffer);
-        big_buffer_size = newsize;
-        store_free(big_buffer);
-        big_buffer = newbuffer;
-        }
-
-      /* Shuffle the remaining characters up or down in the buffer before
-      copying in the replacement text. Don't rescan the replacement for this
-      same macro. */
-
-      pp = p + m->namelen;
-      if ((moveby = m->replen - m->namelen) != 0)
-        {
-        memmove(p + m->replen, pp, (big_buffer + newlen) - pp + 1);
-        newlen += moveby;
-        }
-      Ustrncpy(p, m->replacement, m->replen);
-      t = p + m->replen;
-      while (*t && !isupper(*t) && *t != '_') t++;
-      macro_found = TRUE;
-      }
-    }
-
-  /* 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++;
+  ss = macros_expand(len, &newlen, &macro_found);
 
   /* Check for comment lines - these are physical lines. */
 
@@ -3277,7 +3317,8 @@ while ((s = get_config_line()))
     log_write(0, LOG_PANIC_DIE|LOG_CONFIG_IN,
       "found unexpected BOM (Byte Order Mark)");
 
-  if (isupper(s[0])) read_macro_assignment(s);
+  if (isupper(s[0]))
+    { if (!macro_read_assignment(s)) exim_exit(EXIT_FAILURE, US""); }
 
   else if (Ustrncmp(s, "domainlist", 10) == 0)
     read_named_list(&domainlist_anchor, &domainlist_count,
@@ -3724,7 +3765,7 @@ while ((buffer = get_config_line()) != NULL)
       (d->info->init)(d);
       d = NULL;
       }
-    read_macro_assignment(buffer);
+    if (!macro_read_assignment(buffer)) exim_exit(EXIT_FAILURE, US"");
     continue;
     }
 
@@ -4225,7 +4266,7 @@ between ACLs. */
 
 acl_line = get_config_line();
 
-while(acl_line != NULL)
+while(acl_line)
   {
   uschar name[64];
   tree_node *node;
@@ -4234,7 +4275,7 @@ while(acl_line != NULL)
   p = readconf_readname(name, sizeof(name), acl_line);
   if (isupper(*name) && *p == '=')
     {
-    read_macro_assignment(acl_line);
+    if (!macro_read_assignment(acl_line)) exim_exit(EXIT_FAILURE, US"");
     acl_line = get_config_line();
     continue;
     }
@@ -4278,7 +4319,7 @@ log_write(0, LOG_PANIC_DIE|LOG_CONFIG_IN, "local_scan() options not supported: "
 #else
 
 uschar *p;
-while ((p = get_config_line()) != NULL)
+while ((p = get_config_line()))
   {
   (void) readconf_handle_option(p, local_scan_options, local_scan_options_count,
     NULL, US"local_scan option \"%s\" unknown");
@@ -4368,14 +4409,14 @@ while(next_section[0] != 0)
 void
 readconf_save_config(const uschar *s)
 {
-  save_config_line(string_sprintf("# Exim Configuration (%s)",
-    running_in_test_harness ? US"X" : s));
+save_config_line(string_sprintf("# Exim Configuration (%s)",
+  running_in_test_harness ? US"X" : s));
 }
 
 static void
 save_config_position(const uschar *file, int line)
 {
-  save_config_line(string_sprintf("# %d \"%s\"", line, file));
+save_config_line(string_sprintf("# %d \"%s\"", line, file));
 }
 
 /* Append a pre-parsed logical line to the config lines store,
index f4ce58402f5e7f7a32e39bd93dff6b24c7f54316..5d6b611c37eecb109e55f1a3e7a5f23ba52e8836 100644 (file)
@@ -3381,6 +3381,7 @@ while (*filter->pc)
             {
             uschar *mime_body,*reason_end;
             static const uschar nlnl[]="\r\n\r\n";
+           gstring * g;
 
             for
               (
index dd9cea25532d2e5379ce8da9462470281c08669c..27bf70806fbe37ee95bfcbdf8ee65824100f11d1 100644 (file)
@@ -198,7 +198,7 @@ base32d: 32 ${base32d:${base32:32}}
 base32d: 42 ${base32d:${base32:42}}
 base32d error: ABC ${base32d:ABC}
 
-The base62 operator is actually a base36 operator in the Darwin and Cygwin
+the base62 operator is actually a base36 operator in the Darwin and Cygwin
 environments. Write cunning tests that produce the same output in both cases,
 while doing a reasonable check.
 
@@ -531,8 +531,8 @@ abc:   ${lookup{abc}wildlsearch{DIR/aux-var/0002.wild}}
 a.b.c: ${lookup{a.b.c}wildlsearch{DIR/aux-var/0002.wild}}
 ab.c:  ${lookup{ab.c}wildlsearch{DIR/aux-var/0002.wild}}
 xyz:   ${lookup{xyz}wildlsearch{DIR/aux-var/0002.wild}}
-Xyz:   ${lookup{Xyz}wildlsearch{DIR/aux-var/0002.wild}}
-Zyz:   ${lookup{Zyz}wildlsearch{DIR/aux-var/0002.wild}}
+.Xyz:   ${lookup{Xyz}wildlsearch{DIR/aux-var/0002.wild}}
+.Zyz:   ${lookup{Zyz}wildlsearch{DIR/aux-var/0002.wild}}
 a b:   ${lookup{a b}wildlsearch{DIR/aux-var/0002.wild}}
 a  b:  ${lookup{a  b}wildlsearch{DIR/aux-var/0002.wild}}
 a:b:   ${lookup{a:b}wildlsearch{DIR/aux-var/0002.wild}}
@@ -547,8 +547,8 @@ abc:   ${lookup{abc}nwildlsearch{DIR/aux-var/0002.wild}}
 a.b.c: ${lookup{a.b.c}nwildlsearch{DIR/aux-var/0002.wild}}
 ab.c:  ${lookup{ab.c}nwildlsearch{DIR/aux-var/0002.wild}}
 xyz:   ${lookup{xyz}nwildlsearch{DIR/aux-var/0002.wild}}
-Xyz:   ${lookup{Xyz}nwildlsearch{DIR/aux-var/0002.wild}}
-Zyz:   ${lookup{Zyz}nwildlsearch{DIR/aux-var/0002.wild}}
+.Xyz:   ${lookup{Xyz}nwildlsearch{DIR/aux-var/0002.wild}}
+.Zyz:   ${lookup{Zyz}nwildlsearch{DIR/aux-var/0002.wild}}
 a b:   ${lookup{a b}nwildlsearch{DIR/aux-var/0002.wild}}
 a  b:  ${lookup{a  b}nwildlsearch{DIR/aux-var/0002.wild}}
 a:b:   ${lookup{a:b}nwildlsearch{DIR/aux-var/0002.wild}}
@@ -567,10 +567,10 @@ a\\:Xb: ${lookup{a\\:Xb}nwildlsearch{DIR/aux-var/0002.wild}}
 
 # Some tests of case-(in)dependence
 
-MiXeD-CD:  ${lookup{MiXeD-CD}nwildlsearch{DIR/aux-var/0002.wild}{$value}{NOT FOUND}}
-MixeD-CD:  ${lookup{MixeD-CD}nwildlsearch{DIR/aux-var/0002.wild}{$value}{NOT FOUND}}
-MiXeD-Ncd: ${lookup{MiXeD-Ncd}nwildlsearch{DIR/aux-var/0002.wild}{$value}{NOT FOUND}}
-MixeD-Ncd: ${lookup{MixeD-Ncd}nwildlsearch{DIR/aux-var/0002.wild}{$value}{NOT FOUND}}
+.MiXeD-CD:  ${lookup{MiXeD-CD}nwildlsearch{DIR/aux-var/0002.wild}{$value}{NOT FOUND}}
+.MixeD-CD:  ${lookup{MixeD-CD}nwildlsearch{DIR/aux-var/0002.wild}{$value}{NOT FOUND}}
+.MiXeD-Ncd: ${lookup{MiXeD-Ncd}nwildlsearch{DIR/aux-var/0002.wild}{$value}{NOT FOUND}}
+.MixeD-Ncd: ${lookup{MixeD-Ncd}nwildlsearch{DIR/aux-var/0002.wild}{$value}{NOT FOUND}}
 
 # IP address (CIDR) lookups
 
@@ -614,12 +614,12 @@ ${extract{B}{A=1 B=2 C=3}}
 ${extract{ B }{A=1 B=2 C=3}{$value}{NOT FOUND}}
 ${extract{2}{:}{1:2:3}}
 ${extract{ 2 }{:}{1:2:3}{$value}{NOT FOUND}}
-Empty:<${extract{D}{A=1 B=2 C=3}}>
-Empty:<${extract{4}{:}{1:2:3}}>
+empty:<${extract{D}{A=1 B=2 C=3}}>
+empty:<${extract{4}{:}{1:2:3}}>
 ${extract{C}{A=1 B=2 C=3}{<$value>}}
 ${extract{3}{:}{1:2:3}{<$value>}}
-Empty:<${extract{Z}{A=1 B=2 C=3}{<$value>}}>
-Empty:<${extract{4}{:}{1:2:3}{<$value>}}>
+empty:<${extract{Z}{A=1 B=2 C=3}{<$value>}}>
+empty:<${extract{4}{:}{1:2:3}{<$value>}}>
 ${extract{Z}{A=1 B=2 C=3}{<$value>}{no Z}}
 ${extract{4}{:}{1:2:3}{<$value>}{no 4}}
 ${extract{Z}{A=1 B=2 C=3}{<$value>}fail}
@@ -698,8 +698,8 @@ abcdea abc z   ${tr{abcdea}{abc}{z}}
 abcd      ${rfc2047:abcd}
 <:abcd:>  ${rfc2047:<:abcd:>}
 <:ab cd:> ${rfc2047:<:ab cd:>}
-Long:     ${rfc2047: here we go: a string that is going to be encoded: it will go over the 75-char limit}
-Long:     ${rfc2047: here we go: a string that is going to be encoded: it will go over the 75-char limit by a long way; in fact this one will go over the 150 character limit}
+long:     ${rfc2047: here we go: a string that is going to be encoded: it will go over the 75-char limit}
+long:     ${rfc2047: here we go: a string that is going to be encoded: it will go over the 75-char limit by a long way; in fact this one will go over the 150 character limit}
 
 # RFC 2047 decode
 
@@ -739,21 +739,21 @@ ${if exists{/non/exist/file}{${readfile{/non/exist/file}}}{non-exist}}
 # Calling a command
 
 ${run{DIR/aux-fixed/0002.runfile 0}}
-RC=$runrc
+rc=$runrc
 ${run{DIR/aux-fixed/0002.runfile 0}{1}{2}}
-RC=$runrc
+rc=$runrc
 ${run{DIR/aux-fixed/0002.runfile 0}{$value}{2}}
-RC=$runrc
+rc=$runrc
 ${run{DIR/aux-fixed/0002.runfile 1}{$value}{2}}
-RC=$runrc
+rc=$runrc
 ${run{DIR/aux-fixed/0002.runfile 1}{$value}{$value}}
-RC=$runrc
+rc=$runrc
 ${run{DIR/test-nonexist}{Y}{N}}
-RC=$runrc
+rc=$runrc
 >>${run{DIR/bin/iefbr14}}<<
-RC=$runrc
+rc=$runrc
 ${if eq{1}{2}{${run{/non/exist}}}{1!=2}}
-RC=$runrc
+rc=$runrc
 
 # PRVS
 
index 0c6362bded3f06f0fb1957deac668500d91df226..1c8c03b5f3d96b3801620099bc4e902455bd2077 100644 (file)
@@ -7,13 +7,15 @@ Subject: The subject is not the object
 This is the body of the message. Make the line longer than any header.
 ****
 sudo exim -be -Mset $msg1
-From: $h_from:
-Subject: $h_subject:
+from: $h_from:
+subject: $h_subject:
 message_body_size=$message_body_size
 message_id=$message_id
 message_exim_id=$message_exim_id
 max_received_linelength=$max_received_linelength
 recipients=$recipients
+TESTING_MACROS=$recipients
+(TESTING_MACROS)
 ****
 exim -bs
 mail from:<userz@test.ex>
@@ -29,8 +31,8 @@ This is the body of the message. Make the line much longer than any header.
 quit
 ****
 sudo exim -be -Mset $msg2
-From: $h_from:
-Subject: $h_subject:
+from: $h_from:
+subject: $h_subject:
 message_body_size=$message_body_size
 message_id=$message_id
 message_exim_id=$message_exim_id
index bd4dfccd2c5fe13fb995b9b341f40c86083ac6fb..2ca0fdd129a974da47a6285b453a1bb31296f923 100644 (file)
@@ -1,11 +1,11 @@
 # crypteq expansions
 
 exim -be
-BadCrypt: ${if crypteq{MySecret}{}{yes}{no}}
-MySecret: ${if crypteq{MySecret}{azrazPWCQJhyg}{yes}{no}}
-MySecret: ${if crypteq{MySecret}{aarazPWCQJhyg}{yes}{no}}
-MySecret: ${if crypteq{MySecret}{\{crypt\}azrazPWCQJhyg}{yes}{no}}
-MySecret: ${if crypteq{MySecret}{\{CRYPT\}zzrazPWCQJhyg}{yes}{no}}
+badCrypt: ${if crypteq{MySecret}{}{yes}{no}}
+mySecret: ${if crypteq{MySecret}{azrazPWCQJhyg}{yes}{no}}
+mySecret: ${if crypteq{MySecret}{aarazPWCQJhyg}{yes}{no}}
+mySecret: ${if crypteq{MySecret}{\{crypt\}azrazPWCQJhyg}{yes}{no}}
+mySecret: ${if crypteq{MySecret}{\{CRYPT\}zzrazPWCQJhyg}{yes}{no}}
 
 crypt16: ${if crypteq{MySecret}{\{crypt16\}azrazPWCQJhyg}{yes}{no}}
 crypt16: ${if crypteq{MySecretRhubarb}{\{crypt\}azrazPWCQJhyg}{yes}{no}}
@@ -26,9 +26,9 @@ abd:  ${if crypteq{abd}{\{sha1\}A9993E364706816ABA3E25717850C26C9CD0D89D}{yes}{n
 
 # Combinations
 
-Y:      ${if and {{crypteq{MySecret}{azrazPWCQJhyg}}{exists{/etc/passwd}}}{Y}{N}}
-Y:      ${if or  {{crypteq{MySecret}{azrazQWCQJhyg}}{exists{/etc/passwd}}}{Y}{N}}
-Y:      ${if or  {{crypteq{MySecret}{azrazPWCQJhyg}}{exists{/etc/pxsswd}}}{Y}{N}}
-N:      ${if or  {{crypteq{MySecret}{azrazQWCQJhyg}}{exists{/etc/pxsswd}}}{Y}{N}}
-N:      ${if and {{crypteq{MySecret}{azrazQWCQJhyg}}{exists{/etc/passwd}}}{Y}{N}}
+y:      ${if and {{crypteq{MySecret}{azrazPWCQJhyg}}{exists{/etc/passwd}}}{Y}{N}}
+y:      ${if or  {{crypteq{MySecret}{azrazQWCQJhyg}}{exists{/etc/passwd}}}{Y}{N}}
+y:      ${if or  {{crypteq{MySecret}{azrazPWCQJhyg}}{exists{/etc/pxsswd}}}{Y}{N}}
+n:      ${if or  {{crypteq{MySecret}{azrazQWCQJhyg}}{exists{/etc/pxsswd}}}{Y}{N}}
+n:      ${if and {{crypteq{MySecret}{azrazQWCQJhyg}}{exists{/etc/passwd}}}{Y}{N}}
 ****
index 81fbae865b0bf965f3ab7619bae9cdc498e2af39..b22094c0849b82d1ad8d65bdca1f1272f982e7bb 100644 (file)
@@ -124,13 +124,13 @@ conversion: ${utf8_domain_from_alabel:german.xn--strae-oqa.de}
 imapfolder conversions:
 
 ${imapfolder {Foo/Bar}}
-Foo.Bar
+.  Foo.Bar
 
 ${imapfolder {Foo/Bar} {.} {/}}
-Foo&AC8-Bar
+.  Foo&AC8-Bar
 
 ${imapfolder{Räksmörgås}}
-R&AOQ-ksm&APY-rg&AOU-s
+.  R&AOQ-ksm&APY-rg&AOU-s
 
 
 ****
index 8bf8f886f3c57c80e3d77447ac2e193c90fe0821..7f9a50999bdd22dfe7eb0a2fa5bf27f532039bbd 100644 (file)
@@ -78,9 +78,9 @@ LOG: MAIN PANIC
   ┌considering: no}}
   ├──expanding: no
   └─────result: no
- ├──expanding: match_address:   ${if match_address{a.b.c}{a.b.c}{yes}{no}}
+ ├──expanding: a.b.c
  └─────result: match_address:   no
->>>>>>>>>>>>>>>> Exim pid=pppp (main) terminating with rc=0 >>>>>>>>>>>>>>>>
+>>>>>>>>>>>>>>>> Exim pid=pppp (main: expansion test) terminating with rc=0 >>>>>>>>>>>>>>>>
 Exim version x.yz ....
 configuration file is TESTSUITE/test-config
 admin user
@@ -111,7 +111,7 @@ admin user
  ┌considering: -oMt  sender_ident = $sender_ident
  ├──expanding: -oMt  sender_ident = $sender_ident
  └─────result: -oMt  sender_ident = me
->>>>>>>>>>>>>>>> Exim pid=pppp (main) terminating with rc=0 >>>>>>>>>>>>>>>>
+>>>>>>>>>>>>>>>> Exim pid=pppp (main: expansion test) terminating with rc=0 >>>>>>>>>>>>>>>>
 1999-03-02 09:44:33 no host name found for IP address V4NET.11.12.13
 Exim version x.yz ....
 configuration file is TESTSUITE/test-config
@@ -171,7 +171,7 @@ sender_rcvhost = ten-1.test.ex ([V4NET.0.0.1] ident=me)
  ┌considering: -oMt  sender_ident = $sender_ident
  ├──expanding: -oMt  sender_ident = $sender_ident
  └─────result: -oMt  sender_ident = me
->>>>>>>>>>>>>>>> Exim pid=pppp (main) terminating with rc=0 >>>>>>>>>>>>>>>>
+>>>>>>>>>>>>>>>> Exim pid=pppp (main: expansion test) terminating with rc=0 >>>>>>>>>>>>>>>>
 Exim version x.yz ....
 changed uid/gid: forcing real = effective
   uid=uuuu gid=CALLER_GID pid=pppp
@@ -425,4 +425,4 @@ sender address = CALLER@myhost.test.ex
 1.2.3.4 in "1.2.3"? no (malformed IPv4 address or address mask)
 1.2.3.4 in "1.2.3.4/abc"? no (malformed IPv4 address or address mask)
 search_tidyup called
->>>>>>>>>>>>>>>> Exim pid=pppp (main) terminating with rc=0 >>>>>>>>>>>>>>>>
+>>>>>>>>>>>>>>>> Exim pid=pppp (main: expansion test) terminating with rc=0 >>>>>>>>>>>>>>>>
index f51e4e8cf2bfef60d582d863330beafe1d63585e..996fa2a4782be5595e0785583b61b5162fb46eed 100644 (file)
@@ -1,3 +1,3 @@
-LOG: PANIC DIE
+LOG: PANIC
   Exim configuration error in line 10 of TESTSUITE/test-config:
   macro name too long (maximum is 63 characters)
index 0d0d319ced554b37a7ff3c9b08818f53abb40b78..12d73e5a9f7c6a03a039faba0ee6183f69365b05 100644 (file)
@@ -434,4 +434,4 @@ cached data used for lookup of *.b.c
   in TESTSUITE/aux-fixed/0387.1
 lookup yielded: [*.b.c]
 search_tidyup called
->>>>>>>>>>>>>>>> Exim pid=pppp (main) terminating with rc=0 >>>>>>>>>>>>>>>>
+>>>>>>>>>>>>>>>> Exim pid=pppp (main: expansion test) terminating with rc=0 >>>>>>>>>>>>>>>>
index dbf8f66bf24589970a1f3ba4b89ec1e52ec9aaa3..874ac06e2c7d9d0ed10ecc2e54eac4a1ecbe47d9 100644 (file)
@@ -129,4 +129,4 @@ cached data used for lookup of root
   in TESTSUITE/aux-fixed/0484.aliases
 lookup yielded: userx
 search_tidyup called
->>>>>>>>>>>>>>>> Exim pid=pppp (main) terminating with rc=0 >>>>>>>>>>>>>>>>
+>>>>>>>>>>>>>>>> Exim pid=pppp (main: expansion test) terminating with rc=0 >>>>>>>>>>>>>>>>
index 72aad3d26eb3296e4bd84187cf39f7a333e9015a..4b9d87c16b5550bd1f81d8923100cbea86bbfe64 100644 (file)
@@ -20,7 +20,7 @@ internal_search_find: file="NULL"
 cached data used for lookup of a=localhost.test.ex
 lookup yielded: 127.0.0.1
 search_tidyup called
->>>>>>>>>>>>>>>> Exim pid=pppp (main) terminating with rc=0 >>>>>>>>>>>>>>>>
+>>>>>>>>>>>>>>>> Exim pid=pppp (main: expansion test) terminating with rc=0 >>>>>>>>>>>>>>>>
 Exim version x.yz ....
 configuration file is TESTSUITE/test-config
 admin user
index 1ea06926f3aa75dc13bb81c330734b284bb2a0c6..cdb2409b86d599be8eeac93d16d5dccd17754bb1 100644 (file)
@@ -103,7 +103,7 @@ file lookup required for select * from them where name='it''s';
   in TESTSUITE/aux-fixed/sqlitedb
 lookup yielded: name=it's id=its 
 search_tidyup called
->>>>>>>>>>>>>>>> Exim pid=pppp (main) terminating with rc=0 >>>>>>>>>>>>>>>>
+>>>>>>>>>>>>>>>> Exim pid=pppp (main: expansion test) terminating with rc=0 >>>>>>>>>>>>>>>>
 Exim version x.yz ....
 changed uid/gid: forcing real = effective
   uid=uuuu gid=CALLER_GID pid=pppp
@@ -491,4 +491,4 @@ file lookup required for select name from them where id='userx';
   in TESTSUITE/aux-fixed/sqlitedb
 lookup yielded: Ayen Other
 search_tidyup called
->>>>>>>>>>>>>>>> Exim pid=pppp (main) terminating with rc=0 >>>>>>>>>>>>>>>>
+>>>>>>>>>>>>>>>> Exim pid=pppp (main: expansion test) terminating with rc=0 >>>>>>>>>>>>>>>>
index 17f48ab73c61fb31306d7d643ae15bb4047a8c52..3f8338b67def685b237607bad24ff219b9a6e054 100644 (file)
@@ -41,7 +41,7 @@ LOG: MAIN
   log from Perl
  ├──expanding: ${perl{log_write}{log from Perl}}
  └─────result: Wrote log
->>>>>>>>>>>>>>>> Exim pid=pppp (main) terminating with rc=0 >>>>>>>>>>>>>>>>
+>>>>>>>>>>>>>>>> Exim pid=pppp (main: expansion test) terminating with rc=0 >>>>>>>>>>>>>>>>
 LOG: smtp_connection MAIN
   SMTP connection from CALLER
 LOG: MAIN
index 31c81e3b21aa8b32356fbc658c6f9918efe29e51..0b6c7446486ce0bda2f1a90230a679eb7e380a50 100644 (file)
@@ -133,4 +133,4 @@ cached data used for lookup of root
   in TESTSUITE/aux-fixed/3212.aliases
 lookup yielded: userx
 search_tidyup called
->>>>>>>>>>>>>>>> Exim pid=pppp (main) terminating with rc=0 >>>>>>>>>>>>>>>>
+>>>>>>>>>>>>>>>> Exim pid=pppp (main: expansion test) terminating with rc=0 >>>>>>>>>>>>>>>>
index 1422289a759a796d2c77e018bdce573581e93c75..c7f8cce80a7f69aeeec7fe81cd4afdd283e6d84f 100644 (file)
@@ -189,7 +189,7 @@ newline     tab\134backslash ~tilde\177DEL\200\201.
 > base32d: 42 42
 > Failed: argument for base32d operator is "ABC", which is not a base 32 number
 > 
-> The base62 operator is actually a base36 operator in the Darwin and Cygwin
+> the base62 operator is actually a base36 operator in the Darwin and Cygwin
 > environments. Write cunning tests that produce the same output in both cases,
 > while doing a reasonable check.
 > 
@@ -495,8 +495,8 @@ newline     tab\134backslash ~tilde\177DEL\200\201.
 > a.b.c: *.b.c
 > ab.c:  *b.c
 > xyz:   ^X
-> Xyz:   ^X
-> Zyz:   ^Z
+> .Xyz:   ^X
+> .Zyz:   ^Z
 > a b:   "^a +b"
 > a  b:  "^a +b"
 > a:b:   lookup succeeded
@@ -511,8 +511,8 @@ newline     tab\134backslash ~tilde\177DEL\200\201.
 > a.b.c: *.b.c
 > ab.c:  *b.c
 > xyz:   ^X
-> Xyz:   ^X
-> Zyz:   ^Z
+> .Xyz:   ^X
+> .Zyz:   ^Z
 > a b:   "^a +b"
 > a  b:  "^a +b"
 > a:b:   lookup succeeded
@@ -531,10 +531,10 @@ newline   tab\134backslash ~tilde\177DEL\200\201.
 > 
 > # Some tests of case-(in)dependence
 > 
-> MiXeD-CD:  Data found for case-dependent MiXeD-CD
-> MixeD-CD:  NOT FOUND
-> MiXeD-Ncd: Data found for case-independent MiXeD-nCD
-> MixeD-Ncd: Data found for case-independent MiXeD-nCD
+> .MiXeD-CD:  Data found for case-dependent MiXeD-CD
+> .MixeD-CD:  NOT FOUND
+> .MiXeD-Ncd: Data found for case-independent MiXeD-nCD
+> .MixeD-Ncd: Data found for case-independent MiXeD-nCD
 > 
 > # IP address (CIDR) lookups
 > 
@@ -578,12 +578,12 @@ newline   tab\134backslash ~tilde\177DEL\200\201.
 > 2
 > 2
 > 2
-> Empty:<>
-> Empty:<>
+> empty:<>
+> empty:<>
 > <3>
 > <3>
-> Empty:<>
-> Empty:<>
+> empty:<>
+> empty:<>
 > no Z
 > no 4
 > Failed: "extract" failed and "fail" requested
@@ -662,8 +662,8 @@ newline     tab\134backslash ~tilde\177DEL\200\201.
 > abcd      abcd
 > <:abcd:>  =?iso-8859-8?Q?=3C=3Aabcd=3A=3E?=
 > <:ab cd:> =?iso-8859-8?Q?=3C=3Aab_cd=3A=3E?=
-> Long:     =?iso-8859-8?Q?_here_we_go=3A_a_string_that_is_going_to_be_encoded=3A_?= =?iso-8859-8?Q?it_will_go_over_the_75-char_limit?=
-> Long:     =?iso-8859-8?Q?_here_we_go=3A_a_string_that_is_going_to_be_encoded=3A_?= =?iso-8859-8?Q?it_will_go_over_the_75-char_limit_by_a_long_way=3B_in?= =?iso-8859-8?Q?_fact_this_one_will_go_over_the_150_character_limit?=
+> long:     =?iso-8859-8?Q?_here_we_go=3A_a_string_that_is_going_to_be_encoded=3A_?= =?iso-8859-8?Q?it_will_go_over_the_75-char_limit?=
+> long:     =?iso-8859-8?Q?_here_we_go=3A_a_string_that_is_going_to_be_encoded=3A_?= =?iso-8859-8?Q?it_will_go_over_the_75-char_limit_by_a_long_way=3B_in?= =?iso-8859-8?Q?_fact_this_one_will_go_over_the_150_character_limit?=
 > 
 > # RFC 2047 decode
 > 
@@ -708,25 +708,25 @@ xyz
 > abcd
 1234
 
-> RC=0
+> rc=0
 > 1
-> RC=0
+> rc=0
 > abcd
 1234
 
-> RC=0
+> rc=0
 > 2
-> RC=1
+> rc=1
 > abcd
 1234
 
-> RC=1
+> rc=1
 > N
-> RC=127
+> rc=127
 > >><<
-> RC=0
+> rc=0
 > 1!=2
-> RC=0
+> rc=0
 > 
 > # PRVS
 > 
index ab29dc9c0cff36a3e81061c475e52127a06f60b4..ce255a7443ca4c274d365117c63cacab9be92e38 100644 (file)
@@ -1,10 +1,12 @@
-> From: Himself <himself@there.tld>
-> Subject: The subject is not the object
+> from: Himself <himself@there.tld>
+> subject: The subject is not the object
 > message_body_size=71
 > message_id=10HmaX-0005vi-00
 > message_exim_id=10HmaX-0005vi-00
 > max_received_linelength=70
 > recipients=userx@test.x, usery@test.ex
+> Defined macro 'TESTING_MACROS'
+> (userx@test.x, usery@test.ex)
 > 
 220 myhost.test.ex ESMTP Exim x.yz Tue, 2 Mar 1999 09:44:33 +0000\r
 250 OK\r
@@ -13,8 +15,8 @@
 354 Enter message, ending with "." on a line by itself\r
 250 OK id=10HmaY-0005vi-00\r
 221 myhost.test.ex closing connection\r
-> From: Himself <himself@there.tld>
-> Subject: The subject is not the object
+> from: Himself <himself@there.tld>
+> subject: The subject is not the object
 > message_body_size=76
 > message_id=10HmaY-0005vi-00
 > message_exim_id=10HmaY-0005vi-00
index 1859bb184f69577dbe6b042c59c2e6cd0076e6c9..e12e7c31919930cdbce4f8d2bc1eac06916e8cae 100644 (file)
@@ -1,8 +1,8 @@
-> BadCrypt: no
-> MySecret: yes
-> MySecret: no
-> MySecret: yes
-> MySecret: no
+> badCrypt: no
+> mySecret: yes
+> mySecret: no
+> mySecret: yes
+> mySecret: no
 > 
 > crypt16: yes
 > crypt16: yes
@@ -23,9 +23,9 @@
 > 
 > # Combinations
 > 
-> Y:      Y
-> Y:      Y
-> Y:      Y
-> N:      N
-> N:      N
+> y:      Y
+> y:      Y
+> y:      Y
+> n:      N
+> n:      N
 > 
index af39676df02c5c8023b6fcd8e0517d5adad10aba..ac02d8f223076705b370026788f9cb14de3d51cc 100644 (file)
 > imapfolder conversions:
 > 
 > Foo.Bar
-> Foo.Bar
+> .  Foo.Bar
 > 
 > Foo&AC8-Bar
-> Foo&AC8-Bar
+> .  Foo&AC8-Bar
 > 
 > R&AOQ-ksm&APY-rg&AOU-s
-> R&AOQ-ksm&APY-rg&AOU-s
+> .  R&AOQ-ksm&APY-rg&AOU-s
 > 
 > 
 >