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"
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
------------
}
+/*************************************************
+* 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 *
*************************************************/
/* 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);
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;
/* 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 */
{
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 */
deliver_datafile = -1;
}
- exim_exit(EXIT_SUCCESS, US"main");
+ exim_exit(EXIT_SUCCESS, US"main: expansion test");
}
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);
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;
}
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;
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 == '=')
{
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).
/* 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. */
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 *
*************************************************/
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
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, ¯o_found);
/* Check for comment lines - these are physical lines. */
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,
(d->info->init)(d);
d = NULL;
}
- read_macro_assignment(buffer);
+ if (!macro_read_assignment(buffer)) exim_exit(EXIT_FAILURE, US"");
continue;
}
acl_line = get_config_line();
-while(acl_line != NULL)
+while(acl_line)
{
uschar name[64];
tree_node *node;
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;
}
#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");
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,
{
uschar *mime_body,*reason_end;
static const uschar nlnl[]="\r\n\r\n";
+ gstring * g;
for
(
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.
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}}
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}}
# 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
${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}
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
# 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
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>
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
# 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}}
# 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}}
****
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
****
┌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
┌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
┌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
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 >>>>>>>>>>>>>>>>
-LOG: PANIC DIE
+LOG: PANIC
Exim configuration error in line 10 of TESTSUITE/test-config:
macro name too long (maximum is 63 characters)
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 >>>>>>>>>>>>>>>>
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 >>>>>>>>>>>>>>>>
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
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
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 >>>>>>>>>>>>>>>>
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
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 >>>>>>>>>>>>>>>>
> 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.
>
> 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
> 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
>
> # 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
>
> 2
> 2
> 2
-> Empty:<>
-> Empty:<>
+> empty:<>
+> empty:<>
> <3>
> <3>
-> Empty:<>
-> Empty:<>
+> empty:<>
+> empty:<>
> no Z
> no 4
> Failed: "extract" failed and "fail" requested
> 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
>
> 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
>
-> 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
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
-> BadCrypt: no
-> MySecret: yes
-> MySecret: no
-> MySecret: yes
-> MySecret: no
+> badCrypt: no
+> mySecret: yes
+> mySecret: no
+> mySecret: yes
+> mySecret: no
>
> crypt16: yes
> crypt16: yes
>
> # Combinations
>
-> Y: Y
-> Y: Y
-> Y: Y
-> N: N
-> N: N
+> y: Y
+> y: Y
+> y: Y
+> n: N
+> n: N
>
> 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
>
>
>