Commit 2e6b4a7f 2e6b4a7f2251ef9149e9f11216640a129114caa9 by Sergey Poznyakoff

sieve: improve "pipe" action, implement "pipe" test.

* libmu_sieve/extensions/pipe.c: Allow to specify which parts of the
message should be piped.
Implement "pipe" test.
* sieve/tests/pipeact.at: New file.
* sieve/tests/pipetest.at: New file.
* sieve/tests/Makefile.am (TESTSUITE_AT): Add pipeact.at
and pipetest.at
* sieve/tests/testsuite.at: Include pipeact.at
and pipetest.at
(MUT_SIEVE_EXT_TEST): Redefine MUT_SIEVE_OPTIONS.
Set envar "cwd".
Use cat and heredoc to create prog, instead of using AT_DATA.
* sieve/tests/moderator.at: Update to these changes.
1 parent 9bc59f54
......@@ -41,17 +41,6 @@
#include <mailutils/sieve.h>
#include <mailutils/prog.h>
int
sieve_action_pipe (mu_sieve_machine_t mach, mu_list_t args, mu_list_t tags)
{
int rc;
mu_message_t msg;
mu_sieve_value_t *val;
char *cmd;
mu_stream_t mstr, pstr;
mu_envelope_t env;
const char *error_diag = NULL;
const char *error_arg = NULL;
#define ONERR(rc, diag, arg) \
if (rc) \
{ \
......@@ -60,6 +49,25 @@ sieve_action_pipe (mu_sieve_machine_t mach, mu_list_t args, mu_list_t tags)
break; \
}
#define PIPE_ENVELOPE 0x01
#define PIPE_HEADERS 0x02
#define PIPE_BODY 0x04
#define PIPE_ALL (PIPE_ENVELOPE | PIPE_HEADERS | PIPE_BODY)
int
sieve_pipe (mu_sieve_machine_t mach, mu_list_t args, mu_list_t tags, int test)
{
int retval = 0;
int rc, result;
mu_message_t msg;
mu_sieve_value_t *val;
char *cmd;
mu_stream_t pstr;
mu_envelope_t env;
const char *error_diag = NULL;
const char *error_arg = NULL;
int pipe_mask = 0;
val = mu_sieve_value_get (args, 0);
if (!val)
{
......@@ -70,10 +78,9 @@ sieve_action_pipe (mu_sieve_machine_t mach, mu_list_t args, mu_list_t tags)
}
cmd = val->v.string;
mu_sieve_log_action (mach, "PIPE", NULL);
if (mu_sieve_get_debug_level (mach) & MU_SIEVE_DEBUG_TRACE)
{
mu_sieve_debug (mach, "PIPE");
mu_sieve_debug (mach, test ? "PIPE (test)" : "PIPE (action)");
}
if (mu_sieve_is_dry_run (mach))
......@@ -82,15 +89,22 @@ sieve_action_pipe (mu_sieve_machine_t mach, mu_list_t args, mu_list_t tags)
msg = mu_sieve_get_message (mach);
mu_message_get_envelope (msg, &env);
if (mu_sieve_tag_lookup (tags, "envelope", NULL))
pipe_mask |= PIPE_ENVELOPE;
if (mu_sieve_tag_lookup (tags, "header", NULL))
pipe_mask |= PIPE_HEADERS;
if (mu_sieve_tag_lookup (tags, "body", NULL))
pipe_mask |= PIPE_BODY;
if (pipe_mask == 0)
pipe_mask = PIPE_ALL;
do
{
rc = mu_message_get_streamref (msg, &mstr);
ONERR (rc, _("cannot get message stream"), NULL);
mu_stream_t mstr = NULL;
rc = mu_command_stream_create (&pstr, cmd, MU_STREAM_WRITE);
ONERR (rc, _("cannot create command stream"), cmd);
if (mu_sieve_tag_lookup (tags, "envelope", &val))
if (pipe_mask & PIPE_ENVELOPE)
{
char *p;
......@@ -111,14 +125,30 @@ sieve_action_pipe (mu_sieve_machine_t mach, mu_list_t args, mu_list_t tags)
ONERR (rc, _("stream write failed"), NULL);
}
rc = mu_stream_copy (pstr, mstr, 0, NULL);
ONERR (rc, _("command failed"), cmd);
if (pipe_mask & PIPE_HEADERS)
{
mu_header_t hdr;
mu_message_get_header (msg, &hdr);
mu_header_get_streamref (hdr, &mstr);
rc = mu_stream_copy (pstr, mstr, 0, NULL);
ONERR (rc, _("copying headers failed"), cmd);
mu_stream_destroy (&mstr);
}
if (pipe_mask & PIPE_BODY)
{
mu_body_t body;
mu_message_get_body (msg, &body);
mu_body_get_streamref (body, &mstr);
rc = mu_stream_copy (pstr, mstr, 0, NULL);
ONERR (rc, _("copying body failed"), cmd);
mu_stream_destroy (&mstr);
}
}
while (0);
mu_stream_destroy (&mstr);
mu_stream_close (pstr);
mu_stream_destroy (&pstr);
result = mu_stream_close (pstr);
if (rc)
{
......@@ -133,20 +163,91 @@ sieve_action_pipe (mu_sieve_machine_t mach, mu_list_t args, mu_list_t tags)
(unsigned long) mu_sieve_get_message_num (mach),
error_diag,
mu_strerror (rc));
mu_stream_destroy (&pstr);
mu_sieve_abort (mach);
}
return 0;
if (test)
{
int code = 0;
int status;
rc = mu_stream_ioctl (pstr, MU_IOCTL_PROGSTREAM,
MU_IOCTL_PROG_STATUS, &status);
if (rc)
{
mu_stream_destroy (&pstr);
mu_sieve_abort (mach);
}
if (mu_sieve_tag_lookup (tags, "exit", &val))
code = val->v.number;
if (result == 0)
retval = code == 0;
else if (result == MU_ERR_PROCESS_EXITED)
retval = code == WEXITSTATUS (status);
else if (result == MU_ERR_PROCESS_SIGNALED)
{
int signo = WTERMSIG (status);
if (mu_sieve_tag_lookup (tags, "signal", &val))
retval = signo == val->v.number;
else
{
mu_stream_destroy (&pstr);
mu_sieve_abort (mach);
}
}
else
{
mu_sieve_error (mach, "%lu: %s",
(unsigned long) mu_sieve_get_message_num (mach),
mu_strerror (result));
mu_stream_destroy (&pstr);
mu_sieve_abort (mach);
}
}
mu_stream_destroy (&pstr);
return retval;
}
int
sieve_action_pipe (mu_sieve_machine_t mach, mu_list_t args, mu_list_t tags)
{
mu_sieve_log_action (mach, "PIPE", NULL);
return sieve_pipe (mach, args, tags, 0);
}
int
sieve_test_pipe (mu_sieve_machine_t mach, mu_list_t args, mu_list_t tags)
{
return sieve_pipe (mach, args, tags, 1);
}
/* Tagged arguments: */
static mu_sieve_tag_def_t pipe_tags[] = {
{ "envelope", SVT_VOID },
{ "body", SVT_VOID },
{ "header", SVT_VOID },
{ NULL }
};
static mu_sieve_tag_group_t pipe_action_tag_groups[] = {
{ pipe_tags, NULL },
{ NULL }
};
static mu_sieve_tag_group_t pipe_tag_groups[] = {
static mu_sieve_tag_def_t pipe_test_tags[] = {
{ "exit", SVT_NUMBER },
{ "signal", SVT_NUMBER },
{ NULL }
};
static mu_sieve_tag_group_t pipe_test_tag_groups[] = {
{ pipe_tags, NULL },
{ pipe_test_tags, NULL },
{ NULL }
};
......@@ -159,6 +260,11 @@ static mu_sieve_data_type pipe_args[] = {
int
SIEVE_EXPORT (pipe, init) (mu_sieve_machine_t mach)
{
return mu_sieve_register_action (mach, "pipe", sieve_action_pipe,
pipe_args, pipe_tag_groups, 1);
int rc;
rc = mu_sieve_register_action (mach, "pipe", sieve_action_pipe,
pipe_args, pipe_action_tag_groups, 1);
if (rc)
return rc;
return mu_sieve_register_test (mach, "pipe", sieve_test_pipe,
pipe_args, pipe_test_tag_groups, 1);
}
......
......@@ -56,6 +56,8 @@ TESTSUITE_AT = \
moderator.at\
mul-addr.at\
not.at\
pipeact.at\
pipetest.at\
redirect.at\
reject.at\
relational.at\
......
......@@ -26,8 +26,7 @@ chmod +w mailbox
MTA_DIAG=`pwd`/mta.diag
export MTA_DIAG
sieve MUT_SIEVE_CMDLINE dnl
--clearpath -L "${abs_top_builddir}/libmu_sieve/extensions" -f ./mailbox prog || exit 1
sieve MUT_SIEVE_CMDLINE MUT_SIEVE_OPTIONS -f ./mailbox prog || exit 1
sed 's/ENVELOPE FROM:.*/ENVELOPE FROM/' ./mta.diag
],
[ENVELOPE FROM
......
# This file is part of GNU Mailutils. -*- Autotest -*-
# Copyright (C) 2010 Free Software Foundation, Inc.
#
# GNU Mailutils is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License as
# published by the Free Software Foundation; either version 3, or (at
# your option) any later version.
#
# GNU Mailutils is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with GNU Mailutils. If not, see <http://www.gnu.org/licenses/>.
m4_pushdef([MUT_SIEVE_EXT_NAME],[pipe action])
m4_pushdef([make_savemsg],[
AT_DATA([savemsg],[#! /bin/sh
echo "Message begin" >> $[]1
cat - >> $[]1
echo "Message end" >> $[]1
])
chmod +x savemsg
])
MUT_SIEVE_EXT_TEST([pipe entire message],[pipe00],
[require "pipe";
if header :is "Subject" "Coffee"
{
pipe "$cwd/savemsg $cwd/sieve.out";
}
],
[MUT_MBCOPY($abs_top_srcdir/testsuite/spool/sieve.mbox,mailbox)
make_savemsg
sieve MUT_SIEVE_CMDLINE MUT_SIEVE_OPTIONS -f ./mailbox prog
cat sieve.out
],
[Message begin
From bar@dontmailme.org Fri Dec 28 23:28:09 2001
Received: (from bar@dontmailme.org)
by dontmailme.org id fERKR9N16790
for foobar@nonexistent.net; Fri, 28 Dec 2001 22:18:08 +0200
Date: Fri, 28 Dec 2001 23:28:08 +0200
From: Bar <bar@dontmailme.org>
To: Foo Bar <foobar@nonexistent.net>
Message-Id: <200112232808.fERKR9N16790@dontmailme.org>
Subject: Coffee
How about some coffee?
Message end
],
[IMPLICIT KEEP on msg uid 1
IMPLICIT KEEP on msg uid 2
PIPE on msg uid 3
])
MUT_SIEVE_EXT_TEST([pipe envelope],[pipe01],
[require "pipe";
if header :is "Subject" "Coffee"
{
pipe :envelope "$cwd/savemsg $cwd/sieve.out";
}
],
[MUT_MBCOPY($abs_top_srcdir/testsuite/spool/sieve.mbox,mailbox)
make_savemsg
sieve MUT_SIEVE_CMDLINE MUT_SIEVE_OPTIONS -f ./mailbox prog
cat sieve.out
],
[Message begin
From bar@dontmailme.org Fri Dec 28 23:28:09 2001
Message end
],
[IMPLICIT KEEP on msg uid 1
IMPLICIT KEEP on msg uid 2
PIPE on msg uid 3
])
MUT_SIEVE_EXT_TEST([pipe header],[pipe02],
[require "pipe";
if header :is "Subject" "Coffee"
{
pipe :header "$cwd/savemsg $cwd/sieve.out";
}
],
[MUT_MBCOPY($abs_top_srcdir/testsuite/spool/sieve.mbox,mailbox)
make_savemsg
sieve MUT_SIEVE_CMDLINE MUT_SIEVE_OPTIONS -f ./mailbox prog
cat sieve.out
],
[Message begin
Received: (from bar@dontmailme.org)
by dontmailme.org id fERKR9N16790
for foobar@nonexistent.net; Fri, 28 Dec 2001 22:18:08 +0200
Date: Fri, 28 Dec 2001 23:28:08 +0200
From: Bar <bar@dontmailme.org>
To: Foo Bar <foobar@nonexistent.net>
Message-Id: <200112232808.fERKR9N16790@dontmailme.org>
Subject: Coffee
Message end
],
[IMPLICIT KEEP on msg uid 1
IMPLICIT KEEP on msg uid 2
PIPE on msg uid 3
])
MUT_SIEVE_EXT_TEST([pipe body],[pipe03],
[require "pipe";
if header :is "Subject" "Coffee"
{
pipe :body "$cwd/savemsg $cwd/sieve.out";
}
],
[MUT_MBCOPY($abs_top_srcdir/testsuite/spool/sieve.mbox,mailbox)
make_savemsg
sieve MUT_SIEVE_CMDLINE MUT_SIEVE_OPTIONS -f ./mailbox prog
cat sieve.out
],
[Message begin
How about some coffee?
Message end
],
[IMPLICIT KEEP on msg uid 1
IMPLICIT KEEP on msg uid 2
PIPE on msg uid 3
])
MUT_SIEVE_EXT_TEST([pipe combined],[pipe04],
[require "pipe";
if header :is "Subject" "Coffee"
{
pipe :envelope :body "$cwd/savemsg $cwd/sieve.out";
}
],
[MUT_MBCOPY($abs_top_srcdir/testsuite/spool/sieve.mbox,mailbox)
make_savemsg
sieve MUT_SIEVE_CMDLINE MUT_SIEVE_OPTIONS -f ./mailbox prog
cat sieve.out
],
[Message begin
From bar@dontmailme.org Fri Dec 28 23:28:09 2001
How about some coffee?
Message end
],
[IMPLICIT KEEP on msg uid 1
IMPLICIT KEEP on msg uid 2
PIPE on msg uid 3
])
m4_popdef([make_savemsg])
m4_popdef([MUT_SIEVE_EXT_NAME])
# This file is part of GNU Mailutils. -*- Autotest -*-
# Copyright (C) 2010 Free Software Foundation, Inc.
#
# GNU Mailutils is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License as
# published by the Free Software Foundation; either version 3, or (at
# your option) any later version.
#
# GNU Mailutils is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with GNU Mailutils. If not, see <http://www.gnu.org/licenses/>.
m4_pushdef([MUT_SIEVE_EXT_NAME],[pipe test])
MUT_SIEVE_EXT_TEST([],[pipetest00],
[require "test-pipe";
if pipe :header "$cwd/ckmsg"
{
discard;
}
],
[MUT_MBCOPY($abs_top_srcdir/testsuite/spool/sieve.mbox,mailbox)
AT_DATA([ckmsg],[#! /bin/sh
grep "^From:.*example\.org" >/dev/null
])
chmod +x ckmsg
sieve MUT_SIEVE_CMDLINE MUT_SIEVE_OPTIONS -f ./mailbox prog
],
[],
[DISCARD on msg uid 1: marking as deleted
IMPLICIT KEEP on msg uid 2
IMPLICIT KEEP on msg uid 3
])
m4_popdef([MUT_SIEVE_EXT_NAME])
......@@ -87,15 +87,19 @@ dnl [STDOUT = `'],[STDERR = `'])
m4_define([MUT_SIEVE_EXT_TEST],[
AT_SETUP(MUT_SIEVE_EXT_NAME[: $1])
AT_KEYWORDS([MUT_SIEVE_EXT_NAME $2])
m4_pushdef([MUT_SIEVE_OPTIONS],
[--clearpath -L "${abs_top_builddir}/libmu_sieve/extensions"])
AT_CHECK([
MUT_PREREQ_CAPA([HAVE_LIBLTDL])
AT_DATA([prog],[$3])
cwd=`pwd`
cat >>prog<<EOT
$3
EOT
$4
],
[0],
[$5],[$6])
m4_popdef([MUT_SIEVE_OPTIONS])
AT_CLEANUP])
......@@ -125,6 +129,8 @@ m4_include([redirect.at])
m4_include([reject.at])
m4_include([ext.at])
m4_include([moderator.at])
m4_include([pipeact.at])
m4_include([pipetest.at])
......