aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org.ua>2009-05-09 20:18:43 +0300
committerSergey Poznyakoff <gray@gnu.org.ua>2009-05-09 20:19:52 +0300
commit998eaf2cdb444ee77ff67068ce3586de1eea8e4e (patch)
tree5013d3978055eaf155b079076f1028edd0994b0a
parent30775f7ce1215423967c681ab9f3cf0a4704b51e (diff)
downloadmailfromd-998eaf2cdb444ee77ff67068ce3586de1eea8e4e.tar.gz
mailfromd-998eaf2cdb444ee77ff67068ce3586de1eea8e4e.tar.bz2
Implement current header access functions.
* mfd/bi_curhdr.m4: New file: implementation of current header functions. * mfd/Makefile.am (M4_FILES): Add bi_curhdr.m4 * mfd/bi_mbox.m4 (mailbox_open): Work over MU lossage. * mfd/bi_msg.m4 (bi_drop_current_message): Remove. (drop_current_message): New function. * mfd/mailfromd.h (env_reposition): New prototype. * mfd/msg.h (bi_drop_current_message): Remove. * mfd/prog.c (struct eval_environ.reposition): New member. (env_reposition): New function. Work over MU lossage. (env_capture_start): Call env_free_captured to release any module private captured data. Reset env->reposition to 0. (env_capture_write): If env->reposition is set, move stream pointer to the end of stream. (struct builtin_priv.free_capture): New member. (builtin_priv_register): Take 3 arguments. (env_free_captured): New function. * mfd/prog.h (builtin_priv_register): Update proto. * mfd/snarf.m4 (MF_DECLARE_DATA): Get at most 3 arguments. * NEWS, doc/mailutils.texi: Document new functions. * tests/etc/hdr.mts: New file (message transfer session). * tests/etc/hdr2.mts: Likewise. * tests/etc/Makefile.am (EXTRA_DIST): Add new files. * tests/hdr-all.at: New testcase. * tests/hdr-cap.at: New testcase. * tests/hdr-count.at: New testcase. * tests/hdr-gete.at: New testcase. * tests/hdr-getn.at: New testcase. * tests/hdr-itr.at: New testcase. * tests/hdr-mul.at: New testcase. * tests/Makefile.am (TESTSUITE_AT): Add new testcase. * tests/atlocal.in (TESTDIR): New variable. * tests/testsuite.at (MTASIM_DEFS): New define. (AT_MTA_TEST): Rename to AT_MTA_TEST_FILTER. All uses updated. (AT_MTA_TEST_SCRIPT,AT_MTA_TEST_FILTER_SCRIPT): New defines. Include new testcases. * tests/arg.at, tests/curmsg.at, tests/numrcpt.at, tests/reject.at, tests/tempfail.at: Updated.
-rw-r--r--NEWS38
-rw-r--r--doc/mailfromd.texi62
-rw-r--r--mfd/Makefile.am1
-rw-r--r--mfd/bi_curhdr.m4212
-rw-r--r--mfd/bi_mbox.m47
-rw-r--r--mfd/bi_msg.m426
-rw-r--r--mfd/mailfromd.h1
-rw-r--r--mfd/msg.h1
-rw-r--r--mfd/prog.c47
-rw-r--r--mfd/prog.h4
-rw-r--r--mfd/snarf.m46
-rw-r--r--tests/Makefile.am8
-rw-r--r--tests/accept.at4
-rw-r--r--tests/arg.at4
-rw-r--r--tests/atlocal.in3
-rw-r--r--tests/curmsg.at2
-rw-r--r--tests/etc/Makefile.am2
-rw-r--r--tests/etc/hdr.mts26
-rw-r--r--tests/etc/hdr2.mts48
-rw-r--r--tests/hdr-all.at47
-rw-r--r--tests/hdr-cap.at80
-rw-r--r--tests/hdr-count.at37
-rw-r--r--tests/hdr-get.at39
-rw-r--r--tests/hdr-gete.at38
-rw-r--r--tests/hdr-getn.at41
-rw-r--r--tests/hdr-itr.at44
-rw-r--r--tests/hdr-mul.at100
-rw-r--r--tests/numrcpt.at4
-rw-r--r--tests/reject.at4
-rw-r--r--tests/tempfail.at4
-rw-r--r--tests/testsuite.at30
31 files changed, 930 insertions, 40 deletions
diff --git a/NEWS b/NEWS
index 9db425d8..c79dfa7d 100644
--- a/NEWS
+++ b/NEWS
@@ -1,2 +1,2 @@
-Mailfromd NEWS -- history of user-visible changes. 2009-05-08
+Mailfromd NEWS -- history of user-visible changes. 2009-05-09
Copyright (C) 2005, 2006, 2007, 2008, 2009 Sergey Poznyakoff
@@ -26,2 +26,38 @@ each stage is limited (Mailfromd manual, section 11.1.2).
+* New functions
+
+A set of new functions is added that allow to access the headers
+from the current message in a uniform fashion. These functions are
+available in the following handlers: eoh, body, eom.
+
+- number current_header_count([string name])
+
+Return number of headers in the current message. With an argument -
+return number of headers that have this name.
+
+- string current_header_nth_name(number n)
+
+Return the name of the nth header. N is 1-based.
+
+- string current_header_nth_value(number n)
+
+Return the value of the nth header. N is 1-based.
+
+- string current_header(string name[, number index])
+
+Return the value of the named header, e.g.:
+
+ set s current_header("Subject")
+
+Optional second argument specifies the header instance, if there are
+more than 1 header of the same name, e.g.:
+
+ set s current_header("Received", 2)
+
+
+Index is 1-based.
+
+All current_header functions raise the e_not_found exception if the
+requested header is not found.
+
* New pragma `dbprop'
diff --git a/doc/mailfromd.texi b/doc/mailfromd.texi
index 8390fbea..0d171ab0 100644
--- a/doc/mailfromd.texi
+++ b/doc/mailfromd.texi
@@ -234,2 +234,3 @@ Built-in and Library Functions
* Mail body functions::
+* Current Message Functions::
* Mailbox functions::
@@ -303,2 +304,13 @@ Command Line Options.
+A universal socket-map program for MeTA1.
+
+* smap-conf:: Smap Configuration.
+* smap-invoke:: Smap Command Line Arguments.
+* smap-examples:: Examples of Using Smap
+
+Smap Examples
+
+* smap-userdb:: Configure local_user_map.
+* smap-aliases:: Configure aliases.
+
Pmilter multiplexer program.
@@ -5840,2 +5852,3 @@ in version @value{VERSION}.
* Mail body functions::
+* Current Message Functions::
* Mailbox functions::
@@ -6591,2 +6604,5 @@ information about its use, see @ref{body handler}.
+@node Current Message Functions
+@subsubsection Current Message Functions
+
@anchor{current_message}
@@ -6598,2 +6614,48 @@ functions}, for a description of functions for accessing messages.
+The functions below access the headers from the current message. They
+are available in the following handlers: @code{eoh}, @code{body}, @code{eom}.
+
+@deftypefn {Built-in Function} number current_header_count ([string @var{name}])
+
+Return number of headers in the current message. If @var{name}
+is specified, return number of headers that have this name.
+
+@smallexample
+ current_header_count() @result{} 6
+ current_header_count("Subject") @result{} 6
+@end smallexample
+@end deftypefn
+
+@deftypefn {Built-in Function} string current_header_nth_name (number @var{n})
+
+Return the name of the @var{n}th header. The index @var{n} is 1-based.
+@end deftypefn
+
+@deftypefn {Built-in Function} string current_header_nth_value (number @var{n})
+
+Return the value of the @var{n}th header. The index @var{n} is
+1-based.
+@end deftypefn
+
+@deftypefn {Built-in Function} string current_header (string name @
+ [, number @var{n}])
+Return the value of the named header, e.g.:
+
+@smallexample
+ set s current_header("Subject")
+@end smallexample
+
+Optional second argument specifies the header instance, if there are
+more than 1 header of the same name, e.g.:
+
+@smallexample
+ set s current_header("Received", 2)
+@end smallexample
+
+Header indices are 1-based.
+@end deftypefn
+
+All current_header function raise the @code{e_not_found} exception if the
+requested header is not found.
+
@node Mailbox functions
diff --git a/mfd/Makefile.am b/mfd/Makefile.am
index 700e51cf..03c2fca3 100644
--- a/mfd/Makefile.am
+++ b/mfd/Makefile.am
@@ -24,2 +24,3 @@ M4_FILES=\
bi_ctype.m4\
+ bi_curhdr.m4\
bi_db.m4\
diff --git a/mfd/bi_curhdr.m4 b/mfd/bi_curhdr.m4
new file mode 100644
index 00000000..1472131e
--- /dev/null
+++ b/mfd/bi_curhdr.m4
@@ -0,0 +1,212 @@
+/* This file is part of Mailfromd. -*- c -*-
+ Copyright (C) 2008 Sergey Poznyakoff
+
+ This program 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.
+
+ This program 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 this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#include "msg.h"
+
+struct current_header {
+ mu_header_t hdr;
+};
+
+static void *
+alloc_header()
+{
+ return xzalloc(sizeof(struct current_header));
+}
+
+static void
+destroy_header(void *data)
+{
+ struct current_header *chdr = data;
+ mu_header_destroy(&chdr->hdr, NULL);
+ free(chdr);
+}
+
+static void
+free_header(void *data)
+{
+ struct current_header *chdr = data;
+ mu_header_destroy(&chdr->hdr, NULL);
+}
+
+MF_DECLARE_DATA(HEADER, alloc_header, destroy_header, free_header)
+
+static mu_header_t
+get_current_header(eval_environ_t env, mu_stream_t mstr)
+{
+ struct current_header *chdr = MF_GET_DATA;
+ if (!chdr->hdr) {
+ mu_header_t hdr;
+ char *text;
+ int rc;
+ mu_off_t size;
+ size_t total;
+ size_t start;
+
+ rc = mu_stream_size (mstr, &size);
+ MF_ASSERT(rc == 0,
+ mfe_failure,
+ "mu_stream_size: %s",
+ mu_strerror (rc));
+ text = malloc (size + 1);
+ MF_ASSERT(text != NULL,
+ mfe_failure,
+ _("Not enough memory"));
+ rc = mu_stream_seek(mstr, 0, SEEK_SET);
+ MF_ASSERT(rc == 0,
+ mfe_failure,
+ "mu_stream_seek: %s",
+ mu_strerror(rc));
+
+ for (total = 0; total < size;) {
+ size_t nrd;
+
+ rc = mu_stream_sequential_read(mstr,
+ text + total,
+ size - total, &nrd);
+ if (rc || nrd == 0)
+ break;
+ total += nrd;
+ }
+ text[total] = 0;
+
+ /* FIXME: Reposition the stream at its end.
+ This call may happen in the middle of capturing
+ so I have to make sure to not disturb the capturing
+ process.
+ FIXME: MU: The env_reposition call is a kludge
+ necessary because MU stream interface does not offer
+ mu_stream_tell function.
+ */
+ env_reposition(env);
+
+ if (memcmp (text, "From ", 5) == 0)
+ start = strcspn (text, "\n") + 1;
+ else
+ start = 0;
+ rc = mu_header_create (&hdr, text + start, total - start,
+ NULL);
+ free(text);
+ MF_ASSERT(rc == 0,
+ mfe_failure,
+ "mu_header_create: %s",
+ mu_strerror (rc));
+ chdr->hdr = hdr;
+ }
+ return chdr->hdr;
+}
+
+/* number current_header_count([string name]) */
+MF_STATE(eoh)
+MF_STATE(body)
+MF_STATE(eom)
+MF_CAPTURE
+MF_DEFUN(current_header_count, NUMBER, OPTIONAL, STRING name)
+{
+ mu_header_t hdr = get_current_header(env, env_get_stream(env));
+ size_t total;
+ size_t count;
+ int rc = mu_header_get_field_count (hdr, &total);
+
+ MF_ASSERT(rc == 0,
+ mfe_failure,
+ "mu_header_get_field_count: %s",
+ mu_strerror (rc));
+ if (MF_DEFINED(name)) {
+ size_t i;
+ count = 0;
+ for (i = 1; i <= total; i++) {
+ const char *sptr;
+ if (mu_header_sget_field_name(hdr, i, &sptr) == 0
+ && strcasecmp(sptr, name) == 0)
+ count++;
+ }
+ } else
+ count = total;
+ MF_RETURN(count);
+}
+END
+
+/* string current_header_nth_name(number index) */
+MF_STATE(eoh)
+MF_STATE(body)
+MF_STATE(eom)
+MF_CAPTURE
+MF_DEFUN(current_header_nth_name, STRING, NUMBER index)
+{
+ mu_header_t hdr = get_current_header(env, env_get_stream(env));
+ const char *sptr;
+ int rc = mu_header_sget_field_name(hdr, index, &sptr);
+
+ if (rc == MU_ERR_NOENT)
+ MF_THROW(mfe_not_found,
+ _("requested item (#%ld) not found"),
+ index);
+ else if (rc != 0)
+ MF_THROW(mfe_failure,
+ "mu_header_sget_field_name: %s",
+ mu_strerror(rc));
+ MF_RETURN_STRING(sptr);
+}
+END
+
+/* string current_header_nth_value(number index) */
+MF_STATE(eoh)
+MF_STATE(body)
+MF_STATE(eom)
+MF_CAPTURE
+MF_DEFUN(current_header_nth_value, STRING, NUMBER index)
+{
+ mu_header_t hdr = get_current_header(env, env_get_stream(env));
+ const char *sptr;
+ int rc = mu_header_sget_field_value(hdr, index, &sptr);
+
+ if (rc == MU_ERR_NOENT)
+ MF_THROW(mfe_not_found,
+ _("requested item (#%ld) not found"),
+ index);
+ else if (rc != 0)
+ MF_THROW(mfe_failure,
+ "mu_header_sget_field_name: %s",
+ mu_strerror(rc));
+ MF_RETURN_STRING(sptr);
+}
+END
+
+/* string current_header(string name[, number index]) */
+MF_STATE(eoh)
+MF_STATE(body)
+MF_STATE(eom)
+MF_CAPTURE
+MF_DEFUN(current_header, STRING, STRING name, OPTIONAL, NUMBER index)
+{
+ mu_header_t hdr = get_current_header(env, env_get_stream(env));
+ const char *sptr;
+ int rc = mu_header_sget_value_n(hdr, name, MF_OPTVAL(index, 1),
+ &sptr);
+
+ if (rc == MU_ERR_NOENT)
+ MF_THROW(mfe_not_found,
+ _("requested item (%s,%ld) not found"),
+ name, MF_OPTVAL(index, 1));
+ else if (rc != 0)
+ MF_THROW(mfe_failure,
+ "mu_header_sget_field_name: %s",
+ mu_strerror(rc));
+ MF_RETURN_STRING(sptr);
+}
+END
+
+MF_INIT
diff --git a/mfd/bi_mbox.m4 b/mfd/bi_mbox.m4
index f21dcf9d..5a6b0d54 100644
--- a/mfd/bi_mbox.m4
+++ b/mfd/bi_mbox.m4
@@ -119,2 +119,9 @@ MF_DEFUN(mailbox_open, NUMBER, STRING url, OPTIONAL, STRING mode, STRING perms)
+ /* FIXME: MU: This is ridiculous! */
+ if ((flags & (MU_STREAM_READ|MU_STREAM_WRITE))
+ == (MU_STREAM_READ|MU_STREAM_WRITE)) {
+ flags &= ~(MU_STREAM_READ|MU_STREAM_WRITE);
+ flags |= MU_STREAM_RDWR;
+ }
+
if (MF_DEFINED(perms)) {
diff --git a/mfd/bi_msg.m4 b/mfd/bi_msg.m4
index 43882435..b788992d 100644
--- a/mfd/bi_msg.m4
+++ b/mfd/bi_msg.m4
@@ -35,3 +35,15 @@ destroy_msgs(void *data)
-MF_DECLARE_DATA(MSGTAB, alloc_msgs, destroy_msgs)
+void
+drop_current_message(void *data)
+{
+ int i;
+ struct mf_message *tab = data;
+ for (i = 0; i < NMSGS; i++)
+ if (tab[i].msg && tab[i].current) {
+ bi_close_message(&tab[i]);
+ break;
+ }
+}
+
+MF_DECLARE_DATA(MSGTAB, alloc_msgs, destroy_msgs, drop_current_message)
@@ -98,14 +110,2 @@ bi_get_current_message(eval_environ_t env)
-void
-bi_drop_current_message(eval_environ_t env)
-{
- int i;
- struct mf_message *tab = MF_GET_DATA;
- for (i = 0; i < NMSGS; i++)
- if (tab[i].msg && tab[i].current) {
- bi_close_message(&tab[i]);
- break;
- }
-}
-
diff --git a/mfd/mailfromd.h b/mfd/mailfromd.h
index a45bf346..ac93cba4 100644
--- a/mfd/mailfromd.h
+++ b/mfd/mailfromd.h
@@ -806,2 +806,3 @@ size_t env_get_line_count(eval_environ_t env);
mu_stream_t env_get_stream(eval_environ_t env);
+void env_reposition(eval_environ_t env);
int env_capture_start(eval_environ_t env);
diff --git a/mfd/msg.h b/mfd/msg.h
index de9b55d1..a62ec6b2 100644
--- a/mfd/msg.h
+++ b/mfd/msg.h
@@ -43,3 +43,2 @@ int bi_message_register(eval_environ_t env, mu_list_t list, mu_message_t msg,
int bi_get_current_message(eval_environ_t env);
-void bi_drop_current_message(eval_environ_t env);
mu_message_t bi_message_from_descr(eval_environ_t env, int md);
diff --git a/mfd/prog.c b/mfd/prog.c
index 5ab7b110..3c92a9a7 100644
--- a/mfd/prog.c
+++ b/mfd/prog.c
@@ -282,2 +282,4 @@ struct eval_environ {
size_t line_count; /* Number of lines in stream */
+ int reposition; /* When !0, stream must be repositioned to
+ its end before writing. */
@@ -359,2 +361,8 @@ env_get_reg(eval_environ_t env)
+void
+env_reposition(eval_environ_t env)
+{
+ env->reposition = 1;
+}
+
@@ -2140,4 +2148,4 @@ env_capture_start(eval_environ_t env)
if (env->stream) {
- /* Drop any previously registered current message */
- bi_drop_current_message(env);
+ /* Drop any previously captured message data */
+ env_free_captured(env);
@@ -2154,3 +2162,4 @@ env_capture_start(eval_environ_t env)
}
-
+ env->reposition = 0;
+
rc = mu_temp_file_stream_create(&env->stream, NULL);
@@ -2191,4 +2200,20 @@ env_capture_write(eval_environ_t env, const char *buf, size_t size)
{
+ int rc;
+
if (!env->stream)
return 1;
+
+ if (env->reposition) {
+ rc = mu_stream_seek(env->stream, 0, SEEK_END);
+ if (rc) {
+ mu_error(_("%sTemporary stream seek failed: %s"),
+ mailfromd_msgid(env->ctx),
+ mu_strerror(rc));
+ mu_stream_close(env->stream);
+ mu_stream_destroy(&env->stream,
+ mu_stream_get_owner(env->stream));
+ return rc;
+ }
+ env->reposition = 0;
+ }
@@ -2196,3 +2221,2 @@ env_capture_write(eval_environ_t env, const char *buf, size_t size)
while (size) {
- int rc;
size_t len = mem_search(buf, '\r', size);
@@ -2255,2 +2279,3 @@ struct builtin_priv { /* Built-in private data structure */
void (*destroy)(void*);
+ int (*free_capture)(void*);
};
@@ -2268,3 +2293,4 @@ builtin_priv_destroy(void *ptr)
int
-builtin_priv_register(void *(*init)(), void (*destroy)(void*))
+builtin_priv_register(void *(*init)(), void (*destroy)(void*),
+ void (*free_capture))
{
@@ -2285,2 +2311,3 @@ builtin_priv_register(void *(*init)(), void (*destroy)(void*))
p->destroy = destroy ? destroy : builtin_priv_destroy;
+ p->free_capture = free_capture;
return desc;
@@ -2288,2 +2315,12 @@ builtin_priv_register(void *(*init)(), void (*destroy)(void*))
+void
+env_free_captured(eval_environ_t env)
+{
+ int i;
+
+ for (i = 0; i < builtin_priv_count; i++)
+ if (bi_priv[i].free_capture && env->bi_priv_array[i])
+ bi_priv[i].free_capture(env->bi_priv_array[i]);
+}
+
void *
diff --git a/mfd/prog.h b/mfd/prog.h
index e8a14ef1..c0d4ffbc 100644
--- a/mfd/prog.h
+++ b/mfd/prog.h
@@ -57,3 +57,5 @@ char *env_vaptr(eval_environ_t env, size_t off);
void *env_get_builtin_priv(eval_environ_t env, int id);
-int builtin_priv_register(void *(*init)(void), void (*destroy)(void*));
+int builtin_priv_register(void *(*init)(void), void (*destroy)(void*),
+ void (*free_capture));
+void env_free_captured(eval_environ_t env);
diff --git a/mfd/snarf.m4 b/mfd/snarf.m4
index 7b8f2dd8..f6cf59ef 100644
--- a/mfd/snarf.m4
+++ b/mfd/snarf.m4
@@ -519,3 +519,3 @@ env_var_inc(env, $1_loc)>])
-/* MF_DECLARE_DATA(name, init [, destr]) - Declare private data for
+/* MF_DECLARE_DATA(name, init [, destr, freecap]) - Declare private data for
* the current module.
@@ -524,2 +524,3 @@ env_var_inc(env, $1_loc)>])
* DESTR - destructor function (void destr(void*))
+ * FREECAP - free capture function (void freecap(void*))
*/
@@ -530,3 +531,4 @@ m4_divert(1)m4_dnl
__MF_PRIV_ID__ = builtin_priv_register($2, m4_dnl
-m4_ifelse($3,,NULL,$3));
+m4_ifelse($3,,NULL,$3),
+m4_ifelse($4,,NULL,$4));
m4_divert(0)m4_dnl
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 25118260..e68992ab 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -69,2 +69,10 @@ TESTSUITE_AT = \
hasmx.at\
+ hdr-all.at\
+ hdr-cap.at\
+ hdr-count.at\
+ hdr-get.at\
+ hdr-gete.at\
+ hdr-getn.at\
+ hdr-itr.at\
+ hdr-mul.at\
hostname.at\
diff --git a/tests/accept.at b/tests/accept.at
index c96a80ec..2f10e6e7 100644
--- a/tests/accept.at
+++ b/tests/accept.at
@@ -1,3 +1,3 @@
# This file is part of Mailfromd testsuite. -*- Autotest -*-
-# Copyright (C) 2007, 2008 Sergey Poznyakoff
+# Copyright (C) 2007, 2008, 2009 Sergey Poznyakoff
#
@@ -19,3 +19,3 @@ AT_KEYWORDS([actions accept])
-AT_MTA_TEST([accept.rc],
+AT_MTA_TEST_FILTER([accept.rc],
[
diff --git a/tests/arg.at b/tests/arg.at
index 231eeb4a..dfc246f7 100644
--- a/tests/arg.at
+++ b/tests/arg.at
@@ -1,3 +1,3 @@
# This file is part of Mailfromd testsuite. -*- Autotest -*-
-# Copyright (C) 2007, 2008 Sergey Poznyakoff
+# Copyright (C) 2007, 2008, 2009 Sergey Poznyakoff
#
@@ -19,3 +19,3 @@ AT_KEYWORDS([arg])
-AT_MTA_TEST([arg.rc],
+AT_MTA_TEST_FILTER([arg.rc],
[
diff --git a/tests/atlocal.in b/tests/atlocal.in
index 29ebba77..00f865ae 100644
--- a/tests/atlocal.in
+++ b/tests/atlocal.in
@@ -2,3 +2,3 @@
# Configurable variable values for tar test suite.
-# Copyright (C) 2007, 2008 Sergey Poznyakoff
+# Copyright (C) 2007, 2008, 2009 Sergey Poznyakoff
@@ -25,2 +25,3 @@ trap "cleanup; test -r $XFAILFILE && cat $XFAILFILE; exit $?" 1 2 13 15
MFOPTS="-I@abs_builddir@ -I@abs_builddir@/etc -I@abs_top_srcdir@/tests/etc -I@abs_top_srcdir@/mfd -I@abs_top_srcdir@/mflib --no-preprocess --no-site-rcfile --no-user-rcfile"
+TESTDIR=@abs_builddir@
ETCDIR=@abs_top_srcdir@/tests/etc
diff --git a/tests/curmsg.at b/tests/curmsg.at
index b473e454..f7ee81d9 100644
--- a/tests/curmsg.at
+++ b/tests/curmsg.at
@@ -28,3 +28,3 @@ AT_KEYWORDS([curmsg])
AT_WITH_MAILFROMD_OPTIONS([--stderr],[
-AT_MTA_TEST([size.rc],[
+AT_MTA_TEST_FILTER([size.rc],[
\E250
diff --git a/tests/etc/Makefile.am b/tests/etc/Makefile.am
index f529f0bd..51a8fee1 100644
--- a/tests/etc/Makefile.am
+++ b/tests/etc/Makefile.am
@@ -48,3 +48,3 @@ RCFILES=\
noinst_DATA = $(RCFILES) config.rc
-EXTRA_DIST=config.in relayed.list $(RCFILES)
+EXTRA_DIST=config.in relayed.list hdr.mts hdr2.mts $(RCFILES)
CLEANFILES = config.rc
diff --git a/tests/etc/hdr.mts b/tests/etc/hdr.mts
new file mode 100644
index 00000000..34e4e196
--- /dev/null
+++ b/tests/etc/hdr.mts
@@ -0,0 +1,26 @@
+\E250
+HELO localhost
+\E250
+MAIL FROM:<gray@gnu.org.ua>
+\E250
+RCPT TO:<gray@localhost>
+\E354
+DATA
+Received: foo
+Received: bar
+From: Sergey Poznyakoff <gray@gnu.org.ua>
+To: gray@localhost
+Subject: Amsterdam (1)
+
+ Dans le port d'Amsterdam
+ Y a des marins qui chantent
+ Les rêves qui les hantent
+ Au large d'Amsterdam
+ Dans le port d'Amsterdam
+ Y a des marins qui dorment
+ Comme des oriflammes
+ Le long des berges mornes
+.
+\E221
+QUIT
+
diff --git a/tests/etc/hdr2.mts b/tests/etc/hdr2.mts
new file mode 100644
index 00000000..787502c5
--- /dev/null
+++ b/tests/etc/hdr2.mts
@@ -0,0 +1,48 @@
+\E250
+HELO localhost
+\E250
+MAIL FROM:<gray@gnu.org.ua>
+\E250
+RCPT TO:<gray@localhost>
+\E354
+DATA
+Received: foo
+Received: bar
+From: Sergey Poznyakoff <gray@gnu.org.ua>
+To: gray@localhost
+Subject: Amsterdam (1)
+
+ Dans le port d'Amsterdam
+ Y a des marins qui chantent
+ Les rêves qui les hantent
+ Au large d'Amsterdam
+ Dans le port d'Amsterdam
+ Y a des marins qui dorment
+ Comme des oriflammes
+ Le long des berges mornes
+.
+\E250
+MAIL FROM:<gray@gnu.org.ua>
+\E250
+RCPT TO:<gray@localhost>
+\E354
+DATA
+Received: foo
+Received: bar
+Received: quux
+From: Sergey Poznyakoff <gray@gnu.org.ua>
+To: gray@localhost
+Subject: Amsterdam (2)
+
+ Dans le port d'Amsterdam
+ Y a des marins qui meurent
+ Pleins de bière et de drames
+ Aux premières lueurs
+ Mais dans le port d'Amsterdam
+ Y a des marins qui naissent
+ Dans la chaleur épaisse
+ Des langueurs océanes
+.
+\E221
+QUIT
+
diff --git a/tests/hdr-all.at b/tests/hdr-all.at
new file mode 100644
index 00000000..ccb412cf
--- /dev/null
+++ b/tests/hdr-all.at
@@ -0,0 +1,47 @@
+# This file is part of Mailfromd testsuite. -*- Autotest -*-
+# Copyright (C) 2009 Sergey Poznyakoff
+#
+# This program 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.
+#
+# This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
+
+AT_SETUP(current_header(name,ind) - iteration over all)
+AT_KEYWORDS([curhdr current_header_a])
+
+AT_WITH_MAILFROMD_OPTIONS([--stderr --gacopyz-log=err],[
+AT_MTA_TEST_SCRIPT([
+prog eoh
+do
+ number limit current_header_count()
+ loop for number i 1,
+ while %i <= %limit,
+ set i %i + 1
+ do
+ echo current_header_nth_name(%i) ": " current_header_nth_value(%i)
+ done
+done
+],
+[hdr.mts],
+[0],
+[],
+[mailfromd: mailfromd (AT_PACKAGE_TARNAME AT_PACKAGE_VERSION) started
+Received: foo
+Received: bar
+From: Sergey Poznyakoff <gray@gnu.org.ua>
+To: gray@localhost
+Subject: Amsterdam (1)
+mailfromd: mailfromd terminating
+])
+])
+
+AT_CLEANUP
+
diff --git a/tests/hdr-cap.at b/tests/hdr-cap.at
new file mode 100644
index 00000000..7cfbe7d8
--- /dev/null
+++ b/tests/hdr-cap.at
@@ -0,0 +1,80 @@
+# This file is part of Mailfromd testsuite. -*- Autotest -*-
+# Copyright (C) 2009 Sergey Poznyakoff
+#
+# This program 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.
+#
+# This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
+
+AT_SETUP(current_header vs. capturing)
+AT_KEYWORDS([curhdr current_header_cap])
+
+m4_pushdef([MTASIM_DEFS],-DTESTDIR="$TESTDIR")
+AT_DATA([$TESTDIR/capture.mbx],[])
+
+AT_WITH_MAILFROMD_OPTIONS([--stderr --gacopyz-log=err],[
+AT_MTA_TEST_SCRIPT([
+prog eoh
+do
+ echo "TOTAL: " current_header_count()
+ echo "FROM: " current_header("From")
+done
+
+func deliver(string mailto)
+do
+ set m umask(0)
+ set mbx mailbox_open(%mailto, "w+")
+
+ set msg current_message()
+ mailbox_append_message(%mbx, %msg)
+ mailbox_close(%mbx)
+ umask(%m)
+done