diff options
author | Sergey Poznyakoff <gray@gnu.org.ua> | 2011-08-27 13:21:33 +0300 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org.ua> | 2011-08-27 13:59:27 +0300 |
commit | 427478b98f0748faf1bae813e613000cb4a9aa2c (patch) | |
tree | d5b577b15013108333db7f7b64343c6a0296bac3 /src | |
parent | 19f41d6c5bcebc79cfa80bf39e242e4b5e8e7a6c (diff) | |
download | mailfromd-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/.gitignore | 1 | ||||
-rw-r--r-- | src/builtin/Makefile.am | 1 | ||||
-rw-r--r-- | src/builtin/body.bi | 2 | ||||
-rw-r--r-- | src/builtin/burst.bi | 417 | ||||
-rw-r--r-- | src/builtin/mbox.bi | 2 | ||||
-rw-r--r-- | src/builtin/msg.bi | 20 | ||||
-rw-r--r-- | src/builtin/msg.h | 10 | ||||
-rw-r--r-- | src/builtin/sieve.bi | 6 | ||||
-rw-r--r-- | src/builtin/snarf.m4 | 3 | ||||
-rw-r--r-- | src/prog.c | 18 | ||||
-rw-r--r-- | src/prog.h | 1 |
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)>]) @@ -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 *)) { @@ -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); |