summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorPhilip Hazel <ph10@hermes.cam.ac.uk>2004-11-25 13:54:30 +0000
committerPhilip Hazel <ph10@hermes.cam.ac.uk>2004-11-25 13:54:30 +0000
commitf05da2e8b55f18554ebbcf97523fd54fb03d071e (patch)
tree35cc42b811298d359791f1a7cd0b93eed6217ff5 /src
parentfb636a0fbbfbc6fe24fde57dbb04198a6c99d3f3 (diff)
Allow both -bf and -bF in the same test run.
Diffstat (limited to 'src')
-rw-r--r--src/src/exim.c108
-rw-r--r--src/src/filter.c40
-rw-r--r--src/src/filtertest.c245
-rw-r--r--src/src/functions.h4
-rw-r--r--src/src/globals.c6
-rw-r--r--src/src/globals.h6
-rw-r--r--src/src/macros.h16
-rw-r--r--src/src/receive.c16
-rw-r--r--src/src/sieve.c12
9 files changed, 264 insertions, 189 deletions
diff --git a/src/src/exim.c b/src/src/exim.c
index e643cdeec..46dcd9100 100644
--- a/src/src/exim.c
+++ b/src/src/exim.c
@@ -1,4 +1,4 @@
-/* $Cambridge: exim/src/src/exim.c,v 1.9 2004/11/18 11:17:33 ph10 Exp $ */
+/* $Cambridge: exim/src/src/exim.c,v 1.10 2004/11/25 13:54:31 ph10 Exp $ */
/*************************************************
* Exim - an Internet mail transport agent *
@@ -1169,7 +1169,8 @@ uschar **argv = USS cargv;
int arg_receive_timeout = -1;
int arg_smtp_receive_timeout = -1;
int arg_error_handling = error_handling;
-int filter_fd = -1;
+int filter_sfd = -1;
+int filter_ufd = -1;
int group_count;
int i;
int list_queue_option = 0;
@@ -1215,7 +1216,6 @@ uschar *ftest_prefix = NULL;
uschar *ftest_suffix = NULL;
uschar *real_sender_address;
uschar *originator_home = US"/";
-BOOL ftest_system = FALSE;
void *reset_point;
struct passwd *pw;
@@ -1581,20 +1581,32 @@ for (i = 1; i < argc; i++)
else if (*argrest == 'e')
expansion_test = checking = TRUE;
- /* -bf: Run in mail filter testing mode
- -bF: Ditto, but for system filters
+ /* -bF: Run system filter test */
+
+ else if (*argrest == 'F')
+ {
+ filter_test |= FTEST_SYSTEM;
+ if (*(++argrest) != 0) { badarg = TRUE; break; }
+ if (++i < argc) filter_test_sfile = argv[i]; else
+ {
+ fprintf(stderr, "exim: file name expected after %s\n", argv[i-1]);
+ exit(EXIT_FAILURE);
+ }
+ }
+
+ /* -bf: Run user filter test
-bfd: Set domain for filter testing
-bfl: Set local part for filter testing
-bfp: Set prefix for filter testing
-bfs: Set suffix for filter testing
*/
- else if (*argrest == 'f' || *argrest == 'F')
+ else if (*argrest == 'f')
{
- ftest_system = *argrest++ == 'F';
- if (*argrest == 0)
+ if (*(++argrest) == 0)
{
- if(++i < argc) filter_test = argv[i]; else
+ filter_test |= FTEST_USER;
+ if (++i < argc) filter_test_ufile = argv[i]; else
{
fprintf(stderr, "exim: file name expected after %s\n", argv[i-1]);
exit(EXIT_FAILURE);
@@ -2761,7 +2773,7 @@ if ((
(smtp_input || extract_recipients || recipients_arg < argc) &&
(daemon_listen || queue_interval >= 0 || bi_option ||
test_retry_arg >= 0 || test_rewrite_arg >= 0 ||
- filter_test != NULL || (msg_action_arg > 0 && !one_msg_action))
+ filter_test != FTEST_NONE || (msg_action_arg > 0 && !one_msg_action))
) ||
(
msg_action_arg > 0 &&
@@ -2779,19 +2791,19 @@ if ((
(
list_options &&
(checking || smtp_input || extract_recipients ||
- filter_test != NULL || bi_option)
+ filter_test != FTEST_NONE || bi_option)
) ||
(
verify_address_mode &&
(address_test_mode || smtp_input || extract_recipients ||
- filter_test != NULL || bi_option)
+ filter_test != FTEST_NONE || bi_option)
) ||
(
address_test_mode && (smtp_input || extract_recipients ||
- filter_test != NULL || bi_option)
+ filter_test != FTEST_NONE || bi_option)
) ||
(
- smtp_input && (sender_address != NULL || filter_test != NULL ||
+ smtp_input && (sender_address != NULL || filter_test != FTEST_NONE ||
extract_recipients)
) ||
(
@@ -2951,7 +2963,7 @@ if (( /* EITHER */
) || /* OR */
expansion_test /* expansion testing */
|| /* OR */
- filter_test != NULL) /* Filter testing */
+ filter_test != FTEST_NONE) /* Filter testing */
{
setgroups(group_count, group_list);
exim_setugid(real_uid, real_gid, FALSE,
@@ -2974,15 +2986,26 @@ privileged user. */
else exim_setugid(geteuid(), getegid(), FALSE, US"forcing real = effective");
-/* If testing a filter, open the file now, before wasting time doing other
+/* If testing a filter, open the file(s) now, before wasting time doing other
setups and reading the message. */
-if (filter_test != NULL)
+if ((filter_test & FTEST_SYSTEM) != 0)
+ {
+ filter_sfd = Uopen(filter_test_sfile, O_RDONLY, 0);
+ if (filter_sfd < 0)
+ {
+ fprintf(stderr, "exim: failed to open %s: %s\n", filter_test_sfile,
+ strerror(errno));
+ return EXIT_FAILURE;
+ }
+ }
+
+if ((filter_test & FTEST_USER) != 0)
{
- filter_fd = Uopen(filter_test, O_RDONLY,0);
- if (filter_fd < 0)
+ filter_ufd = Uopen(filter_test_ufile, O_RDONLY, 0);
+ if (filter_ufd < 0)
{
- fprintf(stderr, "exim: failed to open %s: %s\n", filter_test,
+ fprintf(stderr, "exim: failed to open %s: %s\n", filter_test_ufile,
strerror(errno));
return EXIT_FAILURE;
}
@@ -3377,11 +3400,11 @@ if (real_uid != root_uid && real_uid != exim_uid &&
}
/* If the caller is not trusted, certain arguments are ignored when running for
-real, but are permitted when checking things (-be, -bv, -bt, -bh, -bf). Note
-that authority for performing certain actions on messages is tested in the
+real, but are permitted when checking things (-be, -bv, -bt, -bh, -bf, -bF).
+Note that authority for performing certain actions on messages is tested in the
queue_action() function. */
-if (!trusted_caller && !checking && filter_test == NULL)
+if (!trusted_caller && !checking && filter_test == FTEST_NONE)
{
sender_host_name = sender_host_address = interface_address =
sender_ident = received_protocol = NULL;
@@ -3778,7 +3801,7 @@ for (i = 0;;)
if (originator_name == NULL)
{
if (sender_address == NULL ||
- (!trusted_caller && filter_test == NULL))
+ (!trusted_caller && filter_test == FTEST_NONE))
{
uschar *name = US pw->pw_gecos;
uschar *amp = Ustrchr(name, '&');
@@ -3912,7 +3935,7 @@ unless a trusted caller supplies a sender address with -f, or is passing in the
message via SMTP (inetd invocation or otherwise). */
if ((sender_address == NULL && !smtp_input) ||
- (!trusted_caller && filter_test == NULL))
+ (!trusted_caller && filter_test == FTEST_NONE))
{
sender_local = TRUE;
@@ -3943,7 +3966,7 @@ if ((!smtp_input && sender_address == NULL) ||
|| /* OR */
(sender_address[0] != 0 && /* Non-empty sender address, AND */
!checking && /* Not running tests, AND */
- filter_test == NULL)) /* Not testing a filter */
+ filter_test == FTEST_NONE)) /* Not testing a filter */
{
sender_address = originator_login;
sender_address_forced = FALSE;
@@ -4153,7 +4176,7 @@ if (recipients_arg >= argc && !extract_recipients && !smtp_input)
printf("Configuration file is %s\n", config_main_filename);
return EXIT_SUCCESS;
}
- if (filter_test == NULL)
+ if (filter_test == FTEST_NONE)
{
fprintf(stderr,
"Exim is a Mail Transfer Agent. It is normally called by Mail User Agents,\n"
@@ -4507,9 +4530,9 @@ while (more)
}
}
- /* Read the data for the message. If filter_test is true, this will
- just read the headers for the message, and not write anything onto
- the spool. */
+ /* Read the data for the message. If filter_test is not FTEST_NONE, this
+ will just read the headers for the message, and not write anything onto the
+ spool. */
message_ended = END_NOTENDED;
more = receive_msg(extract_recipients);
@@ -4528,7 +4551,7 @@ while (more)
unless specified. The the return path is set to to the sender unless it has
already been set from a return-path header in the message. */
- if (filter_test != NULL)
+ if (filter_test != FTEST_NONE)
{
deliver_domain = (ftest_domain != NULL)?
ftest_domain : qualify_domain_recipient;
@@ -4563,8 +4586,27 @@ while (more)
if (ftest_suffix != NULL) printf("Suffix = %s\n", ftest_suffix);
chdir("/"); /* Get away from wherever the user is running this from */
- exim_exit(filter_runtest(filter_fd, ftest_system, more)?
- EXIT_SUCCESS : EXIT_FAILURE);
+
+ /* Now we run either a system filter test, or a user filter test, or both.
+ In the latter case, headers added by the system filter will persist and be
+ available to the user filter. We need to copy the filter variables
+ explicitly. */
+
+ if ((filter_test & FTEST_SYSTEM) != 0)
+ {
+ if (!filter_runtest(filter_sfd, filter_test_sfile, TRUE, more))
+ exim_exit(EXIT_FAILURE);
+ }
+
+ memcpy(filter_sn, filter_n, sizeof(filter_sn));
+
+ if ((filter_test & FTEST_USER) != 0)
+ {
+ if (!filter_runtest(filter_ufd, filter_test_ufile, FALSE, more))
+ exim_exit(EXIT_FAILURE);
+ }
+
+ exim_exit(EXIT_SUCCESS);
}
/* Else act on the result of message reception. We should not get here unless
diff --git a/src/src/filter.c b/src/src/filter.c
index 0e8e790a4..c876a8a68 100644
--- a/src/src/filter.c
+++ b/src/src/filter.c
@@ -1,4 +1,4 @@
-/* $Cambridge: exim/src/src/filter.c,v 1.1 2004/10/07 10:39:01 ph10 Exp $ */
+/* $Cambridge: exim/src/src/filter.c,v 1.2 2004/11/25 13:54:31 ph10 Exp $ */
/*************************************************
* Exim - an Internet mail transport agent *
@@ -1462,7 +1462,7 @@ switch (c->type)
and filter testing and verification. */
case cond_firsttime:
- yield = filter_test != NULL || message_id[0] == 0 || deliver_firsttime;
+ yield = filter_test != FTEST_NONE || message_id[0] == 0 || deliver_firsttime;
break;
/* Only TRUE if a message is actually being processed; FALSE for address
@@ -1503,7 +1503,7 @@ switch (c->type)
if (filter_thisaddress != NULL)
{
- if ((filter_test != NULL && debug_selector != 0) ||
+ if ((filter_test != FTEST_NONE && debug_selector != 0) ||
(debug_selector & D_filter) != 0)
{
indent();
@@ -1578,7 +1578,7 @@ switch (c->type)
case cond_matches:
case cond_MATCHES:
- if ((filter_test != NULL && debug_selector != 0) ||
+ if ((filter_test != FTEST_NONE && debug_selector != 0) ||
(debug_selector & D_filter) != 0)
{
debug_printf("Match expanded arguments:\n");
@@ -1621,7 +1621,7 @@ switch (c->type)
break;
}
-if ((filter_test != NULL && debug_selector != 0) ||
+if ((filter_test != FTEST_NONE && debug_selector != 0) ||
(debug_selector & D_filter) != 0)
{
indent();
@@ -1729,7 +1729,7 @@ while (commands != NULL)
}
filter_n[n[1]] += n[0];
- if (filter_test != NULL) printf("Add %d to n%d\n", n[0], n[1]);
+ if (filter_test != FTEST_NONE) printf("Add %d to n%d\n", n[0], n[1]);
break;
/* A deliver command's argument must be a valid address. Its optional
@@ -1777,7 +1777,7 @@ while (commands != NULL)
/* Test case: report what would happen */
- if (filter_test != NULL)
+ if (filter_test != FTEST_NONE)
{
indent();
printf("%seliver message to: %s%s%s%s\n",
@@ -1818,7 +1818,7 @@ while (commands != NULL)
/* Test case: report what would happen */
- if (filter_test != NULL)
+ if (filter_test != FTEST_NONE)
{
indent();
if (mode < 0)
@@ -1855,7 +1855,7 @@ while (commands != NULL)
case pipe_command:
s = string_copy(commands->args[0].u);
- if (filter_test != NULL)
+ if (filter_test != FTEST_NONE)
{
indent();
printf("%sipe message to: %s%s\n", (commands->seen)?
@@ -1911,7 +1911,7 @@ while (commands != NULL)
log_fd = -1;
}
log_filename = expargs[0];
- if (filter_test != NULL)
+ if (filter_test != FTEST_NONE)
{
indent();
printf("%sogfile %s\n", (commands->seen)? "Seen l" : "L", log_filename);
@@ -1921,7 +1921,7 @@ while (commands != NULL)
case logwrite_command:
s = expargs[0];
- if (filter_test != NULL)
+ if (filter_test != FTEST_NONE)
{
indent();
printf("%sogwrite \"%s\"\n", (commands->seen)? "Seen l" : "L",
@@ -1983,7 +1983,7 @@ while (commands != NULL)
int subtype = commands->args[1].i;
s = expargs[0];
- if (filter_test != NULL)
+ if (filter_test != FTEST_NONE)
printf("Headers %s \"%s\"\n", (subtype == TRUE)? "add" :
(subtype == FALSE)? "remove" : "charset", string_printing(s));
@@ -2042,7 +2042,7 @@ while (commands != NULL)
fmsg = string_printing(fmsg);
*error_pointer = fmsg;
- if (filter_test != NULL)
+ if (filter_test != FTEST_NONE)
{
indent();
printf("%c%s text \"%s\"\n", toupper(ff_name[0]), ff_name+1, fmsg);
@@ -2051,7 +2051,7 @@ while (commands != NULL)
return ff_ret;
case finish_command:
- if (filter_test != NULL)
+ if (filter_test != FTEST_NONE)
{
indent();
printf("%sinish\n", (commands->seen)? "Seen f" : "F");
@@ -2091,7 +2091,7 @@ while (commands != NULL)
case vacation_command:
if (return_path == NULL || return_path[0] == 0)
{
- if (filter_test != NULL)
+ if (filter_test != FTEST_NONE)
printf("%s command ignored because return_path is empty\n",
command_list[commands->command]);
else DEBUG(D_filter) debug_printf("%s command ignored because return_path "
@@ -2180,7 +2180,7 @@ while (commands != NULL)
/* Proceed with mail or vacation command */
- if (filter_test != NULL)
+ if (filter_test != FTEST_NONE)
{
uschar *to = commands->args[mailarg_index_to].u;
indent();
@@ -2278,10 +2278,10 @@ while (commands != NULL)
break;
case testprint_command:
- if (filter_test != NULL || (debug_selector & D_filter) != 0)
+ if (filter_test != FTEST_NONE || (debug_selector & D_filter) != 0)
{
uschar *s = string_printing(expargs[0]);
- if (filter_test == NULL)
+ if (filter_test == FTEST_NONE)
debug_printf("Filter: testprint: %s\n", s);
else
printf("Testprint: %s\n", s);
@@ -2460,7 +2460,7 @@ ptr = nextsigchar(ptr, TRUE);
if (read_command_list(&ptr, &lastcmdptr, FALSE))
yield = interpret_commands(commands, generated);
-if (filter_test != NULL || (debug_selector & D_filter) != 0)
+if (filter_test != FTEST_NONE || (debug_selector & D_filter) != 0)
{
uschar *s = US"";
switch(yield)
@@ -2493,7 +2493,7 @@ if (filter_test != NULL || (debug_selector & D_filter) != 0)
break;
}
- if (filter_test != NULL) printf("%s\n", CS s);
+ if (filter_test != FTEST_NONE) printf("%s\n", CS s);
else debug_printf("%s\n", s);
}
diff --git a/src/src/filtertest.c b/src/src/filtertest.c
index 0cdee0304..40da59b17 100644
--- a/src/src/filtertest.c
+++ b/src/src/filtertest.c
@@ -1,4 +1,4 @@
-/* $Cambridge: exim/src/src/filtertest.c,v 1.1 2004/10/07 10:39:01 ph10 Exp $ */
+/* $Cambridge: exim/src/src/filtertest.c,v 1.2 2004/11/25 13:54:31 ph10 Exp $ */
/*************************************************
* Exim - an Internet mail transport agent *
@@ -15,118 +15,29 @@
/*************************************************
-* Test a mail filter *
+* Read message and set body/size variables *
*************************************************/
-/* This is called when exim is run with the -bf option. The name
-of the filter file is in filter_test, and we are running under an
-unprivileged uid/gid. A test message's headers have been read into
-store, and the body of the message is still accessible on the
-standard input.
+/* We have to read the remainder of the message in order to find its size, so
+we can set up the message_body variables at the same time (in normal use, the
+message_body variables are not set up unless needed). The reading code is
+written out here rather than having options in read_message_data, in order to
+keep that function as efficient as possible. Handling message_body_end is
+somewhat more tedious. Pile it all into a circular buffer and sort out at the
+end.
-Argument:
- fd the standard input fd, containing the message body
- is_system TRUE if testing is to be as a system filter
+Arguments:
dot_ended TRUE if message already terminated by '.'
-Returns: TRUE if no errors
+Returns: nothing
*/
-
-BOOL
-filter_runtest(int fd, BOOL is_system, BOOL dot_ended)
-{
-int rc, body_len, body_end_len, filter_type, header_size;
+
+static void
+read_message_body(dot_ended)
+{
register int ch;
-BOOL yield;
-struct stat statbuf;
-address_item *generated = NULL;
-uschar *error, *filebuf, *s;
-
-/* Read the filter file into store as will be done by the router in a real
-case. */
-
-if (fstat(fd, &statbuf) != 0)
- {
- printf("exim: failed to get size of %s: %s\n", filter_test, strerror(errno));
- return FALSE;
- }
-
-filebuf = store_get(statbuf.st_size + 1);
-rc = read(fd, filebuf, statbuf.st_size);
-close(fd);
-
-if (rc != statbuf.st_size)
- {
- printf("exim: error while reading %s: %s\n", filter_test, strerror(errno));
- return FALSE;
- }
-
-filebuf[statbuf.st_size] = 0;
-
-/* Check the filter type. User filters start with "# Exim filter" or "# Sieve
-filter". If the filter type is not recognized, the file is treated as an
-ordinary .forward file. System filters do not need the "# Exim filter" in order
-to be recognized as Exim filters. */
-
-filter_type = rda_is_filter(filebuf);
-if (is_system && filter_type == FILTER_FORWARD) filter_type = FILTER_EXIM;
-
-printf("Testing %s file \"%s\"\n\n",
- (filter_type == FILTER_EXIM)? "Exim filter" :
- (filter_type == FILTER_SIEVE)? "Sieve filter" :
- "forward file",
- filter_test);
-
-/* Handle a plain .forward file */
-
-if (filter_type == FILTER_FORWARD)
- {
- yield = parse_forward_list(filebuf,
- RDO_REWRITE,
- &generated, /* for generated addresses */
- &error, /* for errors */
- deliver_domain, /* incoming domain for \name */
- NULL, /* no check on includes */
- NULL); /* fail on syntax errors */
-
- switch(yield)
- {
- case FF_FAIL:
- printf("exim: forward file contains \":fail:\"\n");
- break;
-
- case FF_BLACKHOLE:
- printf("exim: forwardfile contains \":blackhole:\"\n");
- break;
-
- case FF_ERROR:
- printf("exim: error in forward file: %s\n", error);
- return FALSE;
- }
-
- if (generated == NULL)
- printf("exim: no addresses generated from forward file\n");
-
- else
- {
- printf("exim: forward file generated:\n");
- while (generated != NULL)
- {
- printf(" %s\n", generated->address);
- generated = generated->next;
- }
- }
-
- return TRUE;
- }
-
-/* For a filter, we have to read the remainder of the message in order to find
-its size, so we might as well set up the message_body variable at the same time
-(when *really* filtering this is not read unless needed). The reading code is
-written out here rather than having options in read_message_data, in order to
-keep that function as efficient as possible. Handling message_body_end is
-somewhat more tedious. Pile it all into a circular buffer and sort out at the
-end. */
+int body_len, body_end_len, header_size;
+uschar *s;
message_body = store_malloc(message_body_visible + 1);
message_body_end = store_malloc(message_body_visible + 1);
@@ -227,13 +138,125 @@ while (body_end_len > 0)
message_body_end[body_end_len] == 0)
message_body_end[body_end_len] = ' ';
}
+}
+
+
+
+/*************************************************
+* Test a mail filter *
+*************************************************/
+
+/* This is called when exim is run with the -bf option. At this point it is
+running under an unprivileged uid/gid. A test message's headers have been read
+into store, and the body of the message is still accessible on the standard
+input if this is the first time this function has been called. It may be called
+twice if both system and user filters are being tested.
+
+Argument:
+ fd an fd containing the filter file
+ filename the name of the filter file
+ is_system TRUE if testing is to be as a system filter
+ dot_ended TRUE if message already terminated by '.'
+
+Returns: TRUE if no errors
+*/
+
+BOOL
+filter_runtest(int fd, uschar *filename, BOOL is_system, BOOL dot_ended)
+{
+int rc, filter_type;
+BOOL yield;
+struct stat statbuf;
+address_item *generated = NULL;
+uschar *error, *filebuf;
+
+/* Read the filter file into store as will be done by the router in a real
+case. */
+
+if (fstat(fd, &statbuf) != 0)
+ {
+ printf("exim: failed to get size of %s: %s\n", filename, strerror(errno));
+ return FALSE;
+ }
+
+filebuf = store_get(statbuf.st_size + 1);
+rc = read(fd, filebuf, statbuf.st_size);
+close(fd);
+
+if (rc != statbuf.st_size)
+ {
+ printf("exim: error while reading %s: %s\n", filename, strerror(errno));
+ return FALSE;
+ }
+
+filebuf[statbuf.st_size] = 0;
+
+/* Check the filter type. User filters start with "# Exim filter" or "# Sieve
+filter". If the filter type is not recognized, the file is treated as an
+ordinary .forward file. System filters do not need the "# Exim filter" in order
+to be recognized as Exim filters. */
+
+filter_type = rda_is_filter(filebuf);
+if (is_system && filter_type == FILTER_FORWARD) filter_type = FILTER_EXIM;
+
+printf("Testing %s file \"%s\"\n\n",
+ (filter_type == FILTER_EXIM)? "Exim filter" :
+ (filter_type == FILTER_SIEVE)? "Sieve filter" :
+ "forward file",
+ filename);
+
+/* Handle a plain .forward file */
+
+if (filter_type == FILTER_FORWARD)
+ {
+ yield = parse_forward_list(filebuf,
+ RDO_REWRITE,
+ &generated, /* for generated addresses */
+ &error, /* for errors */
+ deliver_domain, /* incoming domain for \name */
+ NULL, /* no check on includes */
+ NULL); /* fail on syntax errors */
+
+ switch(yield)
+ {
+ case FF_FAIL:
+ printf("exim: forward file contains \":fail:\"\n");
+ break;
+
+ case FF_BLACKHOLE:
+ printf("exim: forwardfile contains \":blackhole:\"\n");
+ break;
+
+ case FF_ERROR:
+ printf("exim: error in forward file: %s\n", error);
+ return FALSE;
+ }
+
+ if (generated == NULL)
+ printf("exim: no addresses generated from forward file\n");
+
+ else
+ {
+ printf("exim: forward file generated:\n");
+ while (generated != NULL)
+ {
+ printf(" %s\n", generated->address);
+ generated = generated->next;
+ }
+ }
+
+ return TRUE;
+ }
+
+/* For a filter, set up the message_body variables and the message size if this
+is the first time this function has been called. */
+
+if (message_body == NULL) read_message_body(dot_ended);
/* Now pass the filter file to the function that interprets it. Because
-filter_test is not NULL, the interpreter will output comments about what
-it is doing, but an error message will have to be output here. No need to
-clean up store. The last argument is 0 because Exim has given up root privilege
-when running a filter test, and in any case, as it is a test, is isn't going to
-try writing any files. */
+filter_test is not FILTER_NONE, the interpreter will output comments about what
+it is doing. No need to clean up store. Indeed, we must not, because we may be
+testing a system filter that is going to be followed by a user filter test. */
if (is_system)
{
diff --git a/src/src/functions.h b/src/src/functions.h
index 8b9f3bbe9..32a3c288a 100644
--- a/src/src/functions.h
+++ b/src/src/functions.h
@@ -1,4 +1,4 @@
-/* $Cambridge: exim/src/src/functions.h,v 1.5 2004/11/19 09:45:54 ph10 Exp $ */
+/* $Cambridge: exim/src/src/functions.h,v 1.6 2004/11/25 13:54:31 ph10 Exp $ */
/*************************************************
* Exim - an Internet mail transport agent *
@@ -92,7 +92,7 @@ extern int expand_string_integer(uschar *);
extern int filter_interpret(uschar *, int, address_item **, uschar **);
extern BOOL filter_personal(string_item *, BOOL);
-extern BOOL filter_runtest(int, BOOL, BOOL);
+extern BOOL filter_runtest(int, uschar *, BOOL, BOOL);
extern BOOL filter_system_interpret(address_item **, uschar **);
extern void header_add(int, char *, ...);
diff --git a/src/src/globals.c b/src/src/globals.c
index 53a9f0a00..f51033dcb 100644
--- a/src/src/globals.c
+++ b/src/src/globals.c
@@ -1,4 +1,4 @@
-/* $Cambridge: exim/src/src/globals.c,v 1.7 2004/11/24 14:38:13 ph10 Exp $ */
+/* $Cambridge: exim/src/src/globals.c,v 1.8 2004/11/25 13:54:31 ph10 Exp $ */
/*************************************************
* Exim - an Internet mail transport agent *
@@ -476,7 +476,9 @@ uschar *extra_local_interfaces = NULL;
int filter_n[FILTER_VARIABLE_COUNT];
BOOL filter_running = FALSE;
int filter_sn[FILTER_VARIABLE_COUNT];
-uschar *filter_test = NULL;
+int filter_test = FTEST_NONE;
+uschar *filter_test_sfile = NULL;
+uschar *filter_test_ufile = NULL;
uschar *filter_thisaddress = NULL;
int finduser_retries = 0;
uid_t fixed_never_users[] = { FIXED_NEVER_USERS };
diff --git a/src/src/globals.h b/src/src/globals.h
index 59154403e..44731b585 100644
--- a/src/src/globals.h
+++ b/src/src/globals.h
@@ -1,4 +1,4 @@
-/* $Cambridge: exim/src/src/globals.h,v 1.6 2004/11/10 10:29:56 ph10 Exp $ */
+/* $Cambridge: exim/src/src/globals.h,v 1.7 2004/11/25 13:54:31 ph10 Exp $ */
/*************************************************
* Exim - an Internet mail transport agent *
@@ -275,7 +275,9 @@ extern uschar *extra_local_interfaces; /* Local, non-listen interfaces */
extern int filter_n[FILTER_VARIABLE_COUNT]; /* filter variables */
extern BOOL filter_running; /* TRUE while running a filter */
extern int filter_sn[FILTER_VARIABLE_COUNT]; /* variables set by system filter */
-extern uschar *filter_test; /* Run as a filter tester on this file */
+extern int filter_test; /* Filter test type */
+extern uschar *filter_test_sfile; /* System filter test file */
+extern uschar *filter_test_ufile; /* User filter test file */
extern uschar *filter_thisaddress; /* For address looping */
extern int finduser_retries; /* Retry count for getpwnam() */
extern uid_t fixed_never_users[]; /* Can't be overridden */
diff --git a/src/src/macros.h b/src/src/macros.h
index 3b4407851..996e2e089 100644
--- a/src/src/macros.h
+++ b/src/src/macros.h
@@ -1,4 +1,4 @@
-/* $Cambridge: exim/src/src/macros.h,v 1.3 2004/11/24 14:38:13 ph10 Exp $ */
+/* $Cambridge: exim/src/src/macros.h,v 1.4 2004/11/25 13:54:31 ph10 Exp $ */
/*************************************************
* Exim - an Internet mail transport agent *
@@ -227,6 +227,12 @@ enum {
CEE_EXEC_PANIC /* Panic-die if exec fails */
};
+/* Bit values for filter_test */
+
+#define FTEST_NONE 0 /* Not filter testing */
+#define FTEST_USER 1 /* Testing user filter */
+#define FTEST_SYSTEM 2 /* Testing system filter */
+
/* Returns from the routing, transport and authentication functions (not all
apply to all of them). Some other functions also use these convenient values,
and some additional values are used only by non-driver functions.
@@ -234,10 +240,10 @@ and some additional values are used only by non-driver functions.
OK, FAIL, DEFER, and ERROR are also declared in local_scan.h for use in the
local_scan() function. Do not change them unilaterally. */
-#define OK 0 /* Successful match */
-#define DEFER 1 /* Defer - some problem */
-#define FAIL 2 /* Matching failed */
-#define ERROR 3 /* Internal or config error */
+#define OK 0 /* Successful match */
+#define DEFER 1 /* Defer - some problem */
+#define FAIL 2 /* Matching failed */
+#define ERROR 3 /* Internal or config error */
/***********/
#define DECLINE 4 /* Declined to handle the address, pass to next
router unless no_more is set */
diff --git a/src/src/receive.c b/src/src/receive.c
index f9a2d3c69..0ed05f1db 100644
--- a/src/src/receive.c
+++ b/src/src/receive.c
@@ -1,4 +1,4 @@
-/* $Cambridge: exim/src/src/receive.c,v 1.4 2004/11/17 14:32:25 ph10 Exp $ */
+/* $Cambridge: exim/src/src/receive.c,v 1.5 2004/11/25 13:54:31 ph10 Exp $ */
/*************************************************
* Exim - an Internet mail transport agent *
@@ -427,7 +427,7 @@ if (smtp_input)
}
else
{
- if (filter_test == NULL)
+ if (filter_test == FTEST_NONE)
{
fprintf(stderr, "\nexim: %s received - message abandoned\n",
(sig == SIGTERM)? "SIGTERM" : "SIGINT");
@@ -1508,18 +1508,18 @@ for (;;)
if (domain == 0 && newsender[0] != 0)
newsender = rewrite_address_qualify(newsender, FALSE);
- if (filter_test != NULL || receive_check_set_sender(newsender))
+ if (filter_test != FTEST_NONE || receive_check_set_sender(newsender))
{
sender_address = newsender;
- if (trusted_caller || filter_test != NULL)
+ if (trusted_caller || filter_test != FTEST_NONE)
{
authenticated_sender = NULL;
originator_name = US"";
sender_local = FALSE;
}
- if (filter_test != NULL)
+ if (filter_test != FTEST_NONE)
printf("Sender taken from \"From \" line\n");
}
}
@@ -1659,7 +1659,7 @@ if (smtp_input && (receive_feof)())
/* If this is a filter test run and no headers were read, output a warning
in case there is a mistake in the test message. */
-if (filter_test != NULL && header_list->next == NULL)
+if (filter_test != FTEST_NONE && header_list->next == NULL)
printf("Warning: no message headers read\n");
@@ -1781,7 +1781,7 @@ for (h = header_list->next; h != NULL; h = h->next)
otherwise set. However, remove any <> that surround the address
because the variable doesn't have these. */
- if (filter_test != NULL)
+ if (filter_test != FTEST_NONE)
{
uschar *start = h->text + 12;
uschar *end = start + Ustrlen(start);
@@ -2378,7 +2378,7 @@ DEBUG(D_receive)
testing mode, that is all this function does. Return TRUE if the message
ended with a dot. */
-if (filter_test != NULL)
+if (filter_test != FTEST_NONE)
{
process_info[process_info_len] = 0;
return message_ended == END_DOT;
diff --git a/src/src/sieve.c b/src/src/sieve.c
index 4301d1ab7..c684e34a9 100644
--- a/src/src/sieve.c
+++ b/src/src/sieve.c
@@ -1,4 +1,4 @@
-/* $Cambridge: exim/src/src/sieve.c,v 1.1 2004/10/07 10:39:01 ph10 Exp $ */
+/* $Cambridge: exim/src/src/sieve.c,v 1.2 2004/11/25 13:54:31 ph10 Exp $ */
/*************************************************
* Exim - an Internet mail transport agent *
@@ -631,7 +631,7 @@ static int compare(struct Sieve *filter, const struct String *needle, const stru
{
int r=0;
-if ((filter_test != NULL && debug_selector != 0) ||
+if ((filter_test != FTEST_NONE && debug_selector != 0) ||
(debug_selector & D_filter) != 0)
{
debug_printf("String comparison (match ");
@@ -728,7 +728,7 @@ switch (mt)
break;
}
}
-if ((filter_test != NULL && debug_selector != 0) ||
+if ((filter_test != FTEST_NONE && debug_selector != 0) ||
(debug_selector & D_filter) != 0)
debug_printf(" Result %s\n",r?"true":"false");
return r;
@@ -852,7 +852,7 @@ for (new_addr=*generated; new_addr; new_addr=new_addr->next)
{
if (Ustrcmp(new_addr->address,addr)==0 && (file ? testflag(new_addr, af_pfr|af_file) : 1))
{
- if ((filter_test != NULL && debug_selector != 0) || (debug_selector & D_filter) != 0)
+ if ((filter_test != FTEST_NONE && debug_selector != 0) || (debug_selector & D_filter) != 0)
{
debug_printf("Repeated %s `%s' ignored.\n",file ? "fileinto" : "redirect", addr);
}
@@ -860,7 +860,7 @@ for (new_addr=*generated; new_addr; new_addr=new_addr->next)
}
}
-if ((filter_test != NULL && debug_selector != 0) || (debug_selector & D_filter) != 0)
+if ((filter_test != FTEST_NONE && debug_selector != 0) || (debug_selector & D_filter) != 0)
{
debug_printf("%s `%s'\n",file ? "fileinto" : "redirect", addr);
}
@@ -2771,7 +2771,7 @@ else
}
#ifndef COMPILE_SYNTAX_CHECKER
-if (filter_test != NULL) printf("%s\n", (const char*) msg);
+if (filter_test != FTEST_NONE) printf("%s\n", (const char*) msg);
else debug_printf("%s\n", msg);
#endif