aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org.ua>2011-08-27 13:21:33 +0300
committerSergey Poznyakoff <gray@gnu.org.ua>2011-08-27 13:59:27 +0300
commit427478b98f0748faf1bae813e613000cb4a9aa2c (patch)
treed5b577b15013108333db7f7b64343c6a0296bac3 /src
parent19f41d6c5bcebc79cfa80bf39e242e4b5e8e7a6c (diff)
downloadmailfromd-427478b98f0748faf1bae813e613000cb4a9aa2c.tar.gz
mailfromd-427478b98f0748faf1bae813e613000cb4a9aa2c.tar.bz2
Implement a built-in function for bursting RFC 934 digests.
* configure.ac: Require Mailutils 2.99.93 * src/prog.c (_cleanup_destroy) allow for clos->cleanup == NULL. (env_function_cleanup_del): New function. * src/prog.h (env_function_cleanup_del): New proto. * mflib/status.mf (e_format): New exception. * src/builtin/snarf.m4 (MF_CLR_CLEANUP): New macro. * src/builtin/burst.bi: New source. * src/builtin/Makefile.am (BI_FILES): Add burst.bi * src/builtin/body.bi (current_message): Pass MF_MSG_CURRENT to bi_message_register. * src/builtin/mbox.bi (mailbox_get_message): Pass MF_MSG_MAILBOX to bi_message_register. * src/builtin/msg.bi (drop_current_message) (bi_get_current_message): Check for MF_MSG_CURRENT (bi_close_message): Destroy the message if type is MF_MSG_STANDALONE. (bi_message_register): Change meaning of the last argument. * src/builtin/msg.h (MF_MSG_MAILBOX) (MF_MSG_CURRENT,MF_MSG_STANDALONE): New defines. (mf_message) <mylist>: Remove. (mf_message) <current>: Rename to type. * src/builtin/sieve.bi: Fix a bug introduced in 19f41d6c5b. * NEWS: Document message_burst. * doc/functions.texi: Restructure the "Message functions" section.
Diffstat (limited to 'src')
-rw-r--r--src/builtin/.gitignore1
-rw-r--r--src/builtin/Makefile.am1
-rw-r--r--src/builtin/body.bi2
-rw-r--r--src/builtin/burst.bi417
-rw-r--r--src/builtin/mbox.bi2
-rw-r--r--src/builtin/msg.bi20
-rw-r--r--src/builtin/msg.h10
-rw-r--r--src/builtin/sieve.bi6
-rw-r--r--src/builtin/snarf.m43
-rw-r--r--src/prog.c18
-rw-r--r--src/prog.h1
11 files changed, 462 insertions, 19 deletions
diff --git a/src/builtin/.gitignore b/src/builtin/.gitignore
index e72cf081..b82c6f37 100644
--- a/src/builtin/.gitignore
+++ b/src/builtin/.gitignore
@@ -1,5 +1,6 @@
builtin.h
body.c
+burst.c
callout.c
ctype.c
curhdr.c
diff --git a/src/builtin/Makefile.am b/src/builtin/Makefile.am
index 8a93e340..c82079c1 100644
--- a/src/builtin/Makefile.am
+++ b/src/builtin/Makefile.am
@@ -20,6 +20,7 @@ noinst_HEADERS = builtin.h msg.h
BI_FILES=\
body.bi\
+ burst.bi\
callout.bi\
ctype.bi\
curhdr.bi\
diff --git a/src/builtin/body.bi b/src/builtin/body.bi
index f684801b..be39da6e 100644
--- a/src/builtin/body.bi
+++ b/src/builtin/body.bi
@@ -45,7 +45,7 @@ MF_DEFUN(current_message, NUMBER)
rc = bi_get_current_message(env);
if (rc < 0) {
msg = MF_STREAM_TO_MESSAGE(mstr);
- rc = bi_message_register(env, NULL, msg, 1);
+ rc = bi_message_register(env, NULL, msg, MF_MSG_CURRENT);
MF_ASSERT(rc >= 0,
mfe_failure,
_("no more message slots available"));
diff --git a/src/builtin/burst.bi b/src/builtin/burst.bi
new file mode 100644
index 00000000..dd9b944b
--- /dev/null
+++ b/src/builtin/burst.bi
@@ -0,0 +1,417 @@
+/* This file is part of Mailfromd. -*- c -*-
+ Copyright (C) 2011 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/>. */
+
+/* Functions for converting RFC-934 digests into MIME messages.
+ Largely inspired by MU's mh/burst.c */
+
+#include "msg.h"
+#include "global.h"
+
+/* Minimal length of encapsulation boundary */
+MF_VAR(burst_eb_min_length, NUMBER, SYM_PRECIOUS);
+
+/* Digest messages */
+
+/* Bursting FSA states accoring to RFC 934:
+
+ S1 :: "-" S3
+ | CRLF {CRLF} S1
+ | c {c} S2
+
+ S2 :: CRLF {CRLF} S1
+ | c {c} S2
+
+ S3 :: " " S2
+ | c S4 ;; the bursting agent should consider the current
+ ;; message ended.
+
+ S4 :: CRLF S5
+ | c S4
+
+ S5 :: CRLF S5
+ | c {c} S2 ;; The bursting agent should consider a new
+ ;; message started
+*/
+
+#define S1 1
+#define S2 2
+#define S3 3
+#define S4 4
+#define S5 5
+
+/* Negative state means no write */
+static int transtab[5][256] = {
+/* S1 */ { S2, S2, S2, S2, S2, S2, S2, S2,
+ S2, S2, S1, S2, S2, S2, S2, S2,
+ S2, S2, S2, S2, S2, S2, S2, S2,
+ S2, S2, S2, S2, S2, S2, S2, S2,
+ S2, S2, S2, S2, S2, S2, S2, S2,
+ S2, S2, S2, S2, S2, -S3, S2, S2,
+ S2, S2, S2, S2, S2, S2, S2, S2,
+ S2, S2, S2, S2, S2, S2, S2, S2,
+ S2, S2, S2, S2, S2, S2, S2, S2,
+ S2, S2, S2, S2, S2, S2, S2, S2,
+ S2, S2, S2, S2, S2, S2, S2, S2,
+ S2, S2, S2, S2, S2, S2, S2, S2,
+ S2, S2, S2, S2, S2, S2, S2, S2,
+ S2, S2, S2, S2, S2, S2, S2, S2,
+ S2, S2, S2, S2, S2, S2, S2, S2,
+ S2, S2, S2, S2, S2, S2, S2, S2,
+ S2, S2, S2, S2, S2, S2, S2, S2,
+ S2, S2, S2, S2, S2, S2, S2, S2,
+ S2, S2, S2, S2, S2, S2, S2, S2,
+ S2, S2, S2, S2, S2, S2, S2, S2,
+ S2, S2, S2, S2, S2, S2, S2, S2,
+ S2, S2, S2, S2, S2, S2, S2, S2,
+ S2, S2, S2, S2, S2, S2, S2, S2,
+ S2, S2, S2, S2, S2, S2, S2, S2,
+ S2, S2, S2, S2, S2, S2, S2, S2,
+ S2, S2, S2, S2, S2, S2, S2, S2,
+ S2, S2, S2, S2, S2, S2, S2, S2,
+ S2, S2, S2, S2, S2, S2, S2, S2,
+ S2, S2, S2, S2, S2, S2, S2, S2,
+ S2, S2, S2, S2, S2, S2, S2, S2,
+ S2, S2, S2, S2, S2, S2, S2, S2,
+ S2, S2, S2, S2, S2, S2, S2, S2 },
+/* S2 */ { S2, S2, S2, S2, S2, S2, S2, S2,
+ S2, S2, S1, S2, S2, S2, S2, S2,
+ S2, S2, S2, S2, S2, S2, S2, S2,
+ S2, S2, S2, S2, S2, S2, S2, S2,
+ S2, S2, S2, S2, S2, S2, S2, S2,
+ S2, S2, S2, S2, S2, S2, S2, S2,
+ S2, S2, S2, S2, S2, S2, S2, S2,
+ S2, S2, S2, S2, S2, S2, S2, S2,
+ S2, S2, S2, S2, S2, S2, S2, S2,
+ S2, S2, S2, S2, S2, S2, S2, S2,
+ S2, S2, S2, S2, S2, S2, S2, S2,
+ S2, S2, S2, S2, S2, S2, S2, S2,
+ S2, S2, S2, S2, S2, S2, S2, S2,
+ S2, S2, S2, S2, S2, S2, S2, S2,
+ S2, S2, S2, S2, S2, S2, S2, S2,
+ S2, S2, S2, S2, S2, S2, S2, S2,
+ S2, S2, S2, S2, S2, S2, S2, S2,
+ S2, S2, S2, S2, S2, S2, S2, S2,
+ S2, S2, S2, S2, S2, S2, S2, S2,
+ S2, S2, S2, S2, S2, S2, S2, S2,
+ S2, S2, S2, S2, S2, S2, S2, S2,
+ S2, S2, S2, S2, S2, S2, S2, S2,
+ S2, S2, S2, S2, S2, S2, S2, S2,
+ S2, S2, S2, S2, S2, S2, S2, S2,
+ S2, S2, S2, S2, S2, S2, S2, S2,
+ S2, S2, S2, S2, S2, S2, S2, S2,
+ S2, S2, S2, S2, S2, S2, S2, S2,
+ S2, S2, S2, S2, S2, S2, S2, S2,
+ S2, S2, S2, S2, S2, S2, S2, S2,
+ S2, S2, S2, S2, S2, S2, S2, S2,
+ S2, S2, S2, S2, S2, S2, S2, S2,
+ S2, S2, S2, S2, S2, S2, S2, S2 },
+/* S3 */ { -S4, -S4, -S4, -S4, -S4, -S4, -S4, -S4,
+ -S4, -S4, -S4, -S4, -S4, -S4, -S4, -S4,
+ -S4, -S4, -S4, -S4, -S4, -S4, -S4, -S4,
+ -S4, -S4, -S4, -S4, -S4, -S4, -S4, -S4,
+ -S2, -S4, -S4, -S4, -S4, -S4, -S4, -S4,
+ -S4, -S4, -S4, -S4, -S4, -S4, -S4, -S4,
+ -S4, -S4, -S4, -S4, -S4, -S4, -S4, -S4,
+ -S4, -S4, -S4, -S4, -S4, -S4, -S4, -S4,
+ -S4, -S4, -S4, -S4, -S4, -S4, -S4, -S4,
+ -S4, -S4, -S4, -S4, -S4, -S4, -S4, -S4,
+ -S4, -S4, -S4, -S4, -S4, -S4, -S4, -S4,
+ -S4, -S4, -S4, -S4, -S4, -S4, -S4, -S4,
+ -S4, -S4, -S4, -S4, -S4, -S4, -S4, -S4,
+ -S4, -S4, -S4, -S4, -S4, -S4, -S4, -S4,
+ -S4, -S4, -S4, -S4, -S4, -S4, -S4, -S4,
+ -S4, -S4, -S4, -S4, -S4, -S4, -S4, -S4,
+ -S4, -S4, -S4, -S4, -S4, -S4, -S4, -S4,
+ -S4, -S4, -S4, -S4, -S4, -S4, -S4, -S4,
+ -S4, -S4, -S4, -S4, -S4, -S4, -S4, -S4,
+ -S4, -S4, -S4, -S4, -S4, -S4, -S4, -S4,
+ -S4, -S4, -S4, -S4, -S4, -S4, -S4, -S4,
+ -S4, -S4, -S4, -S4, -S4, -S4, -S4, -S4,
+ -S4, -S4, -S4, -S4, -S4, -S4, -S4, -S4,
+ -S4, -S4, -S4, -S4, -S4, -S4, -S4, -S4,
+ -S4, -S4, -S4, -S4, -S4, -S4, -S4, -S4,
+ -S4, -S4, -S4, -S4, -S4, -S4, -S4, -S4,
+ -S4, -S4, -S4, -S4, -S4, -S4, -S4, -S4,
+ -S4, -S4, -S4, -S4, -S4, -S4, -S4, -S4,
+ -S4, -S4, -S4, -S4, -S4, -S4, -S4, -S4,
+ -S4, -S4, -S4, -S4, -S4, -S4, -S4, -S4,
+ -S4, -S4, -S4, -S4, -S4, -S4, -S4, -S4,
+ -S4, -S4, -S4, -S4, -S4, -S4, -S4, -S4 },
+/* S4 */ { -S4, -S4, -S4, -S4, -S4, -S4, -S4, -S4,
+ -S4, -S4, -S5, -S4, -S4, -S4, -S4, -S4,
+ -S4, -S4, -S4, -S4, -S4, -S4, -S4, -S4,
+ -S4, -S4, -S4, -S4, -S4, -S4, -S4, -S4,
+ -S4, -S4, -S4, -S4, -S4, -S4, -S4, -S4,
+ -S4, -S4, -S4, -S4, -S4, -S4, -S4, -S4,
+ -S4, -S4, -S4, -S4, -S4, -S4, -S4, -S4,
+ -S4, -S4, -S4, -S4, -S4, -S4, -S4, -S4,
+ -S4, -S4, -S4, -S4, -S4, -S4, -S4, -S4,
+ -S4, -S4, -S4, -S4, -S4, -S4, -S4, -S4,
+ -S4, -S4, -S4, -S4, -S4, -S4, -S4, -S4,
+ -S4, -S4, -S4, -S4, -S4, -S4, -S4, -S4,
+ -S4, -S4, -S4, -S4, -S4, -S4, -S4, -S4,
+ -S4, -S4, -S4, -S4, -S4, -S4, -S4, -S4,
+ -S4, -S4, -S4, -S4, -S4, -S4, -S4, -S4,
+ -S4, -S4, -S4, -S4, -S4, -S4, -S4, -S4,
+ -S4, -S4, -S4, -S4, -S4, -S4, -S4, -S4,
+ -S4, -S4, -S4, -S4, -S4, -S4, -S4, -S4,
+ -S4, -S4, -S4, -S4, -S4, -S4, -S4, -S4,
+ -S4, -S4, -S4, -S4, -S4, -S4, -S4, -S4,
+ -S4, -S4, -S4, -S4, -S4, -S4, -S4, -S4,
+ -S4, -S4, -S4, -S4, -S4, -S4, -S4, -S4,
+ -S4, -S4, -S4, -S4, -S4, -S4, -S4, -S4,
+ -S4, -S4, -S4, -S4, -S4, -S4, -S4, -S4,
+ -S4, -S4, -S4, -S4, -S4, -S4, -S4, -S4,
+ -S4, -S4, -S4, -S4, -S4, -S4, -S4, -S4,
+ -S4, -S4, -S4, -S4, -S4, -S4, -S4, -S4,
+ -S4, -S4, -S4, -S4, -S4, -S4, -S4, -S4,
+ -S4, -S4, -S4, -S4, -S4, -S4, -S4, -S4,
+ -S4, -S4, -S4, -S4, -S4, -S4, -S4, -S4,
+ -S4, -S4, -S4, -S4, -S4, -S4, -S4, -S4,
+ -S4, -S4, -S4, -S4, -S4, -S4, -S4, -S4 },
+/* S5 */ { S2, S2, S2, S2, S2, S2, S2, S2,
+ S2, S2, -S5, S2, S2, S2, S2, S2,
+ S2, S2, S2, S2, S2, S2, S2, S2,
+ S2, S2, S2, S2, S2, S2, S2, S2,
+ S2, S2, S2, S2, S2, S2, S2, S2,
+ S2, S2, S2, S2, S2, S2, S2, S2,
+ S2, S2, S2, S2, S2, S2, S2, S2,
+ S2, S2, S2, S2, S2, S2, S2, S2,
+ S2, S2, S2, S2, S2, S2, S2, S2,
+ S2, S2, S2, S2, S2, S2, S2, S2,
+ S2, S2, S2, S2, S2, S2, S2, S2,
+ S2, S2, S2, S2, S2, S2, S2, S2,
+ S2, S2, S2, S2, S2, S2, S2, S2,
+ S2, S2, S2, S2, S2, S2, S2, S2,
+ S2, S2, S2, S2, S2, S2, S2, S2,
+ S2, S2, S2, S2, S2, S2, S2, S2,
+ S2, S2, S2, S2, S2, S2, S2, S2,
+ S2, S2, S2, S2, S2, S2, S2, S2,
+ S2, S2, S2, S2, S2, S2, S2, S2,
+ S2, S2, S2, S2, S2, S2, S2, S2,
+ S2, S2, S2, S2, S2, S2, S2, S2,
+ S2, S2, S2, S2, S2, S2, S2, S2,
+ S2, S2, S2, S2, S2, S2, S2, S2,
+ S2, S2, S2, S2, S2, S2, S2, S2,
+ S2, S2, S2, S2, S2, S2, S2, S2,
+ S2, S2, S2, S2, S2, S2, S2, S2,
+ S2, S2, S2, S2, S2, S2, S2, S2,
+ S2, S2, S2, S2, S2, S2, S2, S2,
+ S2, S2, S2, S2, S2, S2, S2, S2,
+ S2, S2, S2, S2, S2, S2, S2, S2,
+ S2, S2, S2, S2, S2, S2, S2, S2,
+ S2, S2, S2, S2, S2, S2, S2, S2 }
+};
+
+#define F_FIRST 0x01 /* First part of the message (no EB seen so far) */
+#define F_ENCAPS 0x02 /* Within encapsulated part */
+
+struct burst_stream {
+ mu_mime_t mime;
+ mu_stream_t stream; /* Output stream */
+ int flags; /* See F_ flags above */
+ size_t partno; /* Number of the part within the message */
+};
+
+static inline void
+finish_stream(eval_environ_t env, struct burst_stream *bs)
+{
+ if (bs->stream) {
+ mu_message_t msg;
+
+ mu_stream_seek(bs->stream, 0, SEEK_SET, NULL);
+ msg = MF_STREAM_TO_MESSAGE(bs->stream);
+ mu_mime_add_part(bs->mime, msg);
+ mu_message_unref(msg);
+ bs->stream = 0;
+ bs->partno++;
+ bs->flags &= ~F_FIRST;
+ }
+}
+
+static inline void
+flush_stream(eval_environ_t env, struct burst_stream *bs,
+ char *buf, size_t size)
+{
+ int rc;
+
+ if (size == 0)
+ return;
+ if (!bs->stream) {
+ rc = mu_temp_file_stream_create(&bs->stream, NULL, 0);
+ MF_ASSERT(rc == 0,
+ mfe_failure,
+ _("Cannot open temporary file: %s"),
+ mu_strerror(rc));
+ /*
+ mu_stream_printf(bs->stream, "X-Burst-Part: 0 %lu %02x\n",
+ (unsigned long) bs->partno, bs->flags);
+ if (!bs->flags)
+ mu_stream_write(bs->stream, "\n", 1, NULL);
+ */
+ }
+
+ rc = mu_stream_write(bs->stream, buf, size, NULL);
+ MF_ASSERT(rc == 0,
+ mfe_failure,
+ _("error writing temporary stream: %s"),
+ mu_strerror(rc));
+}
+
+static void
+burst_stream_cleanup(void *data)
+{
+ struct burst_stream *bs = data;
+ mu_stream_unref(bs->stream);
+ mu_mime_destroy(&bs->mime);
+ free(bs);
+}
+
+/* Burst an RFC 934 digest. Return 0 if OK, 1 if the message is not
+ a valid digest.
+ FIXME: On errors, cleanup and return -1.
+*/
+int
+burst_digest(eval_environ_t env, mu_mime_t mime, mu_message_t msg)
+{
+ int rc;
+ mu_body_t body;
+ mu_stream_t is;
+ unsigned char c;
+ size_t n;
+ int state = S1;
+ int eb_length = 0;
+ struct burst_stream *bs;
+ int result = 0;
+
+ int eb_min_length = (int) MF_VAR_REF(burst_eb_min_length);
+ if (eb_min_length <= 0)
+ eb_min_length = 1;
+
+ bs = xmalloc(sizeof(*bs));
+ bs->mime = mime;
+ bs->stream = NULL;
+ bs->flags = F_FIRST;
+ bs->partno = 1;
+ MF_DCL_CLEANUP(bs, burst_stream_cleanup);
+
+ rc = mu_message_get_body(msg, &body);
+ MF_ASSERT(rc == 0,
+ mfe_failure,
+ "mu_message_get_body: %s",
+ mu_strerror(rc));
+
+ rc = mu_body_get_streamref(body, &is);
+ MF_ASSERT(rc == 0,
+ mfe_failure,
+ "mu_body_get_streamref: %s",
+ mu_strerror(rc));
+
+ while (mu_stream_read(is, &c, 1, &n) == 0 && n == 1) {
+ int newstate = transtab[state - 1][c];
+ int silent = 0;
+
+ if (newstate < 0) {
+ newstate = -newstate;
+ silent = 1;
+ }
+
+ if (state == S1) {
+ /* GNU extension: check if we have seen enough
+ dashes to constitute a valid encapsulation
+ boundary. */
+ if (newstate == S3) {
+ eb_length++;
+ if (eb_length < eb_min_length)
+ continue; /* Ignore state change */
+ if (eb_min_length > 1) {
+ newstate = S4;
+ finish_stream(env, bs);
+ bs->flags ^= F_ENCAPS;
+ }
+ } else
+ for (; eb_length; eb_length--)
+ flush_stream(env, bs, "-", 1);
+ eb_length = 0;
+ } else if (state == S5 && newstate == S2) {
+ /* As the automaton traverses from state S5 to S2, the
+ bursting agent should consider a new message started
+ and output the first character. */
+ finish_stream(env, bs);
+ } else if (state == S3 && newstate == S4) {
+ /* As the automaton traverses from state S3 to S4, the
+ bursting agent should consider the current message
+ ended. */
+ finish_stream(env, bs);
+ bs->flags ^= F_ENCAPS;
+ }
+ state = newstate;
+ if (!silent)
+ flush_stream(env, bs, (char*)&c, 1);
+ }
+ mu_stream_destroy(&is);
+
+ if (bs->flags == F_FIRST) {
+ mu_stream_destroy(&bs->stream);
+ result = 1;
+ } else {
+ if (bs->stream) {
+ mu_off_t size = 0;
+ mu_stream_size(bs->stream, &size);
+ if (size)
+ finish_stream(env, bs);
+ else
+ mu_stream_destroy(&bs->stream);
+ }
+ bs->mime = NULL;
+ }
+ MF_CLEANUP(bs);
+ return result;
+}
+
+MF_DEFUN(message_burst, NUMBER, NUMBER nmsg)
+{
+ int rc;
+ mu_message_t msg;
+ mu_mime_t mime;
+
+ msg = bi_message_from_descr(env, nmsg);
+ rc = mu_mime_create(&mime, NULL, 0);
+ MF_ASSERT(rc == 0,
+ mfe_failure,
+ _("mu_mime_create: %s"),
+ mu_strerror(rc));
+ rc = burst_digest(env, mime, msg);
+ MF_ASSERT(rc == 0,
+ mfe_format,
+ _("message is not a RFC-934 digest"));
+ rc = mu_mime_to_message(mime, &msg);
+ mu_mime_unref(mime);
+ MF_ASSERT(rc == 0,
+ mfe_failure,
+ _("mu_mime_get_message: %s"),
+ mu_strerror(rc));
+ rc = bi_message_register(env, NULL, msg, MF_MSG_STANDALONE);
+ if (rc < 0) {
+ mu_message_destroy(&msg, mu_message_get_owner(msg));
+ MF_THROW(mfe_failure,
+ _("no more message slots available"));
+ }
+ MF_RETURN(rc);
+}
+END
+
+MF_INIT
diff --git a/src/builtin/mbox.bi b/src/builtin/mbox.bi
index 5ac5b794..03b2227e 100644
--- a/src/builtin/mbox.bi
+++ b/src/builtin/mbox.bi
@@ -223,7 +223,7 @@ MF_DEFUN(mailbox_get_message, NUMBER, NUMBER nmbx, NUMBER msgno)
mfe_failure,
"%s",
mu_strerror(rc));
- rc = bi_message_register(env, mp->msglist, msg, 0);
+ rc = bi_message_register(env, mp->msglist, msg, MF_MSG_MAILBOX);
MF_ASSERT(rc >= 0,
mfe_failure,
_("no more message slots available"));
diff --git a/src/builtin/msg.bi b/src/builtin/msg.bi
index aa25b1f4..369d5e30 100644
--- a/src/builtin/msg.bi
+++ b/src/builtin/msg.bi
@@ -48,7 +48,7 @@ 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) {
+ if (tab[i].msg && tab[i].type == MF_MSG_CURRENT) {
bi_close_message(&tab[i]);
break;
}
@@ -79,10 +79,9 @@ bi_close_message(struct mf_message *mp)
if (mp->msg) {
mu_stream_destroy(&mp->mstr);
mu_stream_destroy(&mp->bstr);
- if (mp->mylist) {
- mu_list_remove(mp->mylist, mp);
- mu_list_destroy(&mp->mylist);
- }
+ if (mp->type == MF_MSG_STANDALONE)
+ mu_message_destroy(&mp->msg,
+ mu_message_get_owner(mp->msg));
mu_list_do(mp->msglist, do_msg_close, NULL);
mu_list_destroy(&mp->msglist);
free(mp->buf);
@@ -92,15 +91,14 @@ bi_close_message(struct mf_message *mp)
int
bi_message_register(eval_environ_t env,
- mu_list_t msglist, mu_message_t msg, int current)
+ mu_list_t msglist, mu_message_t msg, int type)
{
struct mf_message *msgtab = MF_GET_DATA;
int idx = find_slot(msgtab);
if (idx >= 0) {
struct mf_message *mp = msgtab + idx;
mp->msg = msg;
- mp->current = current;
- mu_list_create(&mp->mylist);
+ mp->type = type;
mu_list_create(&mp->msglist);
if (msglist)
mu_list_append(msglist, mp);
@@ -114,7 +112,7 @@ bi_get_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)
+ if (tab[i].msg && tab[i].type == MF_MSG_CURRENT)
return i;
return -1;
}
@@ -413,7 +411,7 @@ MF_DEFUN(message_get_part, NUMBER, NUMBER nmsg, NUMBER idx)
mfe_failure,
"%s",
mu_strerror(rc));
- rc = bi_message_register(env, mp->msglist, msg, 0);
+ rc = bi_message_register(env, mp->msglist, msg, MF_MSG_MAILBOX);
MF_ASSERT(rc >= 0,
mfe_failure,
_("no more message slots available"));
@@ -593,7 +591,7 @@ MF_DEFUN(message_from_stream, NUMBER, NUMBER fd, OPTIONAL,
msg = MF_STREAM_TO_MESSAGE(src);
- rc = bi_message_register(env, NULL, msg, 0);
+ rc = bi_message_register(env, NULL, msg, MF_MSG_STANDALONE);
if (rc < 0) {
mu_message_destroy(&msg, mu_message_get_owner(msg));
MF_THROW(mfe_failure,
diff --git a/src/builtin/msg.h b/src/builtin/msg.h
index 05052f85..87fcfdac 100644
--- a/src/builtin/msg.h
+++ b/src/builtin/msg.h
@@ -22,6 +22,10 @@ struct mf_mbox {
mu_list_t /* of struct mf_message */ msglist;
};
+#define MF_MSG_MAILBOX 0
+#define MF_MSG_CURRENT 1
+#define MF_MSG_STANDALONE 2
+
struct mf_message {
mu_message_t msg;
mu_stream_t mstr;
@@ -31,13 +35,13 @@ struct mf_message {
mu_stream_t bstr;
char *buf;
size_t bufsize;
- int current;
- mu_list_t /* of struct mf_message */ mylist, msglist;
+ int type;
+ mu_list_t /* of struct mf_message */ msglist;
};
void bi_close_message(struct mf_message *msg);
int bi_message_register(eval_environ_t env, mu_list_t list, mu_message_t msg,
- int current);
+ int type);
int bi_get_current_message(eval_environ_t env);
mu_message_t bi_message_from_descr(eval_environ_t env, int md);
diff --git a/src/builtin/sieve.bi b/src/builtin/sieve.bi
index 3b4f5879..528c8762 100644
--- a/src/builtin/sieve.bi
+++ b/src/builtin/sieve.bi
@@ -92,16 +92,18 @@ MF_DEFUN(sieve, NUMBER, NUMBER nmsg, STRING script, OPTIONAL, NUMBER flags,
mu_sieve_set_data(mach, env);
- if (f & MF_SIEVE_LOG)
- mu_sieve_set_logger(mach, _sieve_text_action_log);
if (f & MF_SIEVE_TEXT) {
struct locus locus;
env_get_locus(env, &locus);
+ if (f & MF_SIEVE_LOG)
+ mu_sieve_set_logger(mach, _sieve_text_action_log);
rc = mu_sieve_compile_buffer(mach, script, strlen(script),
MF_OPTVAL(file, locus.file),
MF_OPTVAL(line, locus.line));
} else {
+ if (f & MF_SIEVE_LOG)
+ mu_sieve_set_logger(mach, _sieve_file_action_log);
rc = mu_sieve_compile(mach, script);
}
diff --git a/src/builtin/snarf.m4 b/src/builtin/snarf.m4
index b07ee7c8..53dbfc9c 100644
--- a/src/builtin/snarf.m4
+++ b/src/builtin/snarf.m4
@@ -681,6 +681,9 @@ m4_define([<__mf_dataseg>])m4_dnl
m4_define([<MF_DCL_CLEANUP>],[<env_function_cleanup_add(env, $1, m4_dnl
m4_ifelse($2,,NULL,$2))>])
+/* MF_CLR_CLEANUP(ptr) */
+m4_define([<MF_CLR_CLEANUP>],[<env_function_cleanup_del(env, $1)>])
+
/* MF_CLEANUP(ptr) */
m4_define([<MF_CLEANUP>],[<env_function_cleanup_flush(env, $1)>])
diff --git a/src/prog.c b/src/prog.c
index 940e9aa1..89482813 100644
--- a/src/prog.c
+++ b/src/prog.c
@@ -423,7 +423,8 @@ static void
_cleanup_destroy(void *item)
{
struct environ_cleanup_closure *clos = item;
- clos->cleanup(clos->data);
+ if (clos->cleanup)
+ clos->cleanup(clos->data);
}
static void
@@ -447,6 +448,21 @@ env_function_cleanup_flush(eval_environ_t env, void *ptr)
}
void
+env_function_cleanup_del(eval_environ_t env, void *ptr)
+{
+ int rc;
+ struct environ_cleanup_closure clos, *cptr;
+
+ clos.data = ptr;
+
+ rc = mu_list_locate(env->cleanup_list, &clos, (void**)cptr);
+ if (rc == 0) {
+ cptr->cleanup = NULL;
+ mu_list_remove(env->cleanup_list, &clos);
+ }
+}
+
+void
env_function_cleanup_add(eval_environ_t env, void *data,
void (*func)(void *))
{
diff --git a/src/prog.h b/src/prog.h
index 40f91f45..16169364 100644
--- a/src/prog.h
+++ b/src/prog.h
@@ -69,6 +69,7 @@ void env_free_captured(eval_environ_t env);
void env_function_cleanup_add(eval_environ_t env, void *data,
void (*func)(void *));
+void env_function_cleanup_del(eval_environ_t env, void *data);
void env_function_cleanup_flush(eval_environ_t env, void *ptr);
void ensure_initialized_variable(const char *name, struct value *val);

Return to:

Send suggestions and report system problems to the System administrator.