aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org.ua>2008-01-21 13:24:15 +0000
committerSergey Poznyakoff <gray@gnu.org.ua>2008-01-21 13:24:15 +0000
commit5cd62ab035e90d6580d7db4f430e916eb588fdfd (patch)
treee33eb8048c38e2ed2d09062fed2b10a438ae05b6
parent8e0985ffe8caa3399718bacb25e45eba6baa0d5c (diff)
downloadmailfromd-5cd62ab035e90d6580d7db4f430e916eb588fdfd.tar.gz
mailfromd-5cd62ab035e90d6580d7db4f430e916eb588fdfd.tar.bz2
* doc/mailfromd.texi, NEWS: Update.
* doc/Makefile.am: Rename /src/ to /mfd/. * mfd/symtab.c (rehash): Bugfix: Update variable owner. * mfd/mailfromd.h (SP): New macro. (struct locus.line): Change type to unsigned long. (enum header_opcode): Replace with enum msgmod_opcode. (struct old_header_node): Replace with struct msgmod_closure. (header_command_str): Replace with msgmod_opcode_str. (parse_error,parse_warning,parse_warning_locus): Mark as printflike. (env_throw,env_throw_bi): Likewise. (logmsg,trace): Likewise. (create_environment): Change proto. (env_msgmod): New function. * mfd/bi_rcpt.m4: New file. Envelope modification functions. * mfd/bi_qrnt.m4: New file. Quarantine functions. * mfd/bi_header.m4: New file. Header modification functions. * mfd/Makefile.am (M4_FILES): Add bi_rcpt.m4, bi_header.m4 and bi_qrnt.m4. * mfd/engine.c, mfd/gram.y, mfd/drivers.c, mfd/prog.c * gacopyz/server.c: Minor changes in debug diagnostics. git-svn-id: file:///svnroot/mailfromd/branches/gmach@1584 7a8a7f39-df28-0410-adc6-e0d955640f24
-rw-r--r--ChangeLog27
-rw-r--r--NEWS50
-rw-r--r--doc/Makefile.am8
-rw-r--r--doc/mailfromd.texi101
-rw-r--r--gacopyz/server.c12
-rw-r--r--mfd/Makefile.am5
-rw-r--r--mfd/bi_header.m456
-rw-r--r--mfd/bi_qrnt.m430
-rw-r--r--mfd/bi_rcpt.m443
-rw-r--r--mfd/drivers.c2
-rw-r--r--mfd/engine.c56
-rw-r--r--mfd/gram.y31
-rw-r--r--mfd/mailfromd.h53
-rw-r--r--mfd/prog.c50
-rw-r--r--mfd/symtab.c2
15 files changed, 435 insertions, 91 deletions
diff --git a/ChangeLog b/ChangeLog
index 51fad8d8..ca11586b 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,30 @@
+2008-01-21 Sergey Poznyakoff <gray@gnu.org.ua>
+
+ * doc/mailfromd.texi, NEWS: Update.
+ * doc/Makefile.am: Rename /src/ to /mfd/.
+
+ * mfd/symtab.c (rehash): Bugfix: Update variable owner.
+ * mfd/mailfromd.h (SP): New macro.
+ (struct locus.line): Change type to unsigned long.
+ (enum header_opcode): Replace with enum msgmod_opcode.
+ (struct old_header_node): Replace with struct msgmod_closure.
+ (header_command_str): Replace with msgmod_opcode_str.
+ (parse_error,parse_warning,parse_warning_locus): Mark as
+ printflike.
+ (env_throw,env_throw_bi): Likewise.
+ (logmsg,trace): Likewise.
+ (create_environment): Change proto.
+ (env_msgmod): New function.
+
+ * mfd/bi_rcpt.m4: New file. Envelope modification functions.
+ * mfd/bi_qrnt.m4: New file. Quarantine functions.
+ * mfd/bi_header.m4: New file. Header modification functions.
+ * mfd/Makefile.am (M4_FILES): Add bi_rcpt.m4, bi_header.m4 and
+ bi_qrnt.m4.
+ * mfd/engine.c, mfd/gram.y, mfd/drivers.c, mfd/prog.c
+
+ * gacopyz/server.c: Minor changes in debug diagnostics.
+
2008-01-19 Sergey Poznyakoff <gray@gnu.org.ua>
* pmult/pmult.c: Use callback to handle header modification
diff --git a/NEWS b/NEWS
index f76f8d30..6ef2e890 100644
--- a/NEWS
+++ b/NEWS
@@ -1,4 +1,4 @@
-Mailfromd NEWS -- history of user-visible changes. 2008-01-15
+Mailfromd NEWS -- history of user-visible changes. 2008-01-21
Copyright (C) 2005, 2006, 2007, 2008 Sergey Poznyakoff
See the end of file for copying conditions.
@@ -55,10 +55,48 @@ interpreter.
Unless this option is given to ./configure, asynchronous syslog
implementation will not be compiled.
-* Fix compilation on Sun.
+* New functions
+
+** rcpt_add(string rcpt)
+
+Adds a recipient to the message envelope.
+
+** rcpt_delete(string rcpt)
+
+Removes the given recipient from the envelope.
+
+** header_add(string hdr, string value)
+
+Adds a header "hdr: value" to the message. In contrast to `add'
+action, this function allows to use arbitrary MFL expressions to
+construct the header name.
+
+** header_delete(string hdr [, number index])
-* Fix header deletion (delete action).
+Delete header `hdr' from the envelope. This function differs from the
+`add' action in two regards:
+ 1. It allows to construct the header name, whereas `delete' requires it to
+ be a literal string;
+ 2. Optional `index' argument allows to select a particular header
+ instance to delete.
+
+** header_replace(string hdr, string value [, number index])
+
+Replace the value of the header `hdr' with `value'. Optional argument
+`index' specifies the number of `hdr' instance to replace (1-based).
+
+This function differs from the `replace' action in two regards:
+
+ 1. It allows to construct the header name, whereas `replace' requires it
+ to be a literal string;
+ 2. Optional `index' argument allows to select a particular header
+ instance to replace.
+
+** quarantine(string reason)
+
+Quarantines the message using the given reason.
+
* Removed depecated features:
1. #pragma option ehlo;
@@ -66,6 +104,12 @@ implementation will not be compiled.
3. The --config-file command line option;
4. Using built-in exception codes in catch statements.
+* Bugfixes
+** Fix compilation on Sun.
+** Fix header deletion (delete action).
+** Variable shadowing was broken if a rehash happened between vardcl and
+ forget_autos.
+
Version 4.2, 2007-10-23
diff --git a/doc/Makefile.am b/doc/Makefile.am
index 4a908460..0394d05f 100644
--- a/doc/Makefile.am
+++ b/doc/Makefile.am
@@ -44,7 +44,7 @@ check-pragmas:
@check-docs.sh pragmas \
'/} option_cache\[\] = {/,/^}/s/[ \t]*{ *"\(.*\)".*/\1/pg' \
's/@deffnx* {pragma option} *\([^@, ]*\) .*/\1/p' \
- $(top_srcdir)/src/main.c -- \
+ $(top_srcdir)/mfd/main.c -- \
$(MAKEINFO) $(AM_MAKEINFOFLAGS) $(MAKEINFOFLAGS) -I $(srcdir) -E - \
$(info_TEXINFOS)
@@ -52,7 +52,7 @@ check-options:
@check-docs.sh options \
'/argp_option options\[\] = /,/^}/s/[ \t]*{ *"\([^,"]*\)".*/\1/pg' \
's/@opindex *\([^@,]*\).*/\1/p' \
- $(top_srcdir)/src/main.c -- \
+ $(top_srcdir)/mfd/main.c -- \
$(MAKEINFO) $(AM_MAKEINFOFLAGS) $(MAKEINFOFLAGS) -I $(srcdir) -E - \
$(info_TEXINFOS)
@@ -61,7 +61,7 @@ check-builtins:
'/MF_DEFUN/{s/[ \t]*MF_DEFUN *(\([^,][^,]*\),.*/\1/p;\
s/[ \t]*MF_DEFUN_VARARGS *(\([^,][^,]*\),.*/\1/p}' \
's/@deftypefn {Built-in Function} *[^ ][^ ]* *\([^ ]*\).*/\1/p' \
- $(top_srcdir)/src/bi_*.m4 -- \
+ $(top_srcdir)/mfd/bi_*.m4 -- \
$(MAKEINFO) $(AM_MAKEINFOFLAGS) $(MAKEINFOFLAGS) -I $(srcdir) -E - \
$(info_TEXINFOS)
@@ -78,7 +78,7 @@ check-exceptions:
@check-docs.sh exceptions \
'/typedef enum mf_status_code {/,/^};/s/[ \t]*mf_\(.*\),.*/\1/p' \
's/@cindex \([^,][^,]*\), exception type/\1/p' \
- $(top_srcdir)/src/mailfromd.h -- \
+ $(top_srcdir)/mfd/mailfromd.h -- \
$(MAKEINFO) $(AM_MAKEINFOFLAGS) $(MAKEINFOFLAGS) -I $(srcdir) -E - \
$(info_TEXINFOS)
diff --git a/doc/mailfromd.texi b/doc/mailfromd.texi
index 1f1767ca..1d55fe5c 100644
--- a/doc/mailfromd.texi
+++ b/doc/mailfromd.texi
@@ -225,7 +225,10 @@ Built-in and Library Functions
* String manipulation::
* String formatting::
+* Envelope modification functions::
+* Header modification functions::
* Mail header functions::
+* Quarantine functions::
* Polling functions::
* Internet address manipulation functions::
* DNS functions::
@@ -5007,7 +5010,7 @@ recipient, immediately after @code{envfrom}.
@item Arguments:
@enumerate 1
@item @code{string}; First argument to the @code{RCPT TO} command,
-i.e. the email address of the sender.
+i.e. the email address of the recipient.
@item @code{string}; Rest of arguments to @code{RCPT TO} separated
by space character. This argument can be @samp{""}.
@end enumerate
@@ -5324,7 +5327,10 @@ in version @value{VERSION}.
@menu
* String manipulation::
* String formatting::
+* Envelope modification functions::
+* Header modification functions::
* Mail header functions::
+* Quarantine functions::
* Polling functions::
* Internet address manipulation functions::
* DNS functions::
@@ -5681,6 +5687,80 @@ A @samp{%} is written. No argument is converted. The complete
conversion specification is @samp{%%}.
@end table
+@node Envelope modification functions
+@subsubsection Envelope Modification Functions
+@UNREVISED{}
+
+ Envelope modification functions add or delete recipient addresses
+from the message envelope. This allows @acronym{MFL} scripts to
+redirect messages to another addresses.
+
+@deftypefn {Built-in Function} void rcpt_add (string @var{address})
+Add e-mail @var{address} to the envelope.
+@end deftypefn
+
+@deftypefn {Built-in Function} void rcpt_delete (string @var{address})
+Remove @var{address} from the envelope.
+@end deftypefn
+
+ The following example code implements a simple alias-like
+capability:
+
+@smallexample
+prog envrcpt
+do
+ string alias dbget(%aliasdb, $1, "NULL", 1)
+ if %alias != "NULL"
+ rcpt_delete($1)
+ rcpt_add(%alias)
+ fi
+done
+@end smallexample
+
+@node Header modification functions
+@subsubsection Header Modification Functions
+@UNREVISED{}
+
+@deftypefn {Built-in Function} void header_add (string @var{name}, @
+ string @var{value})
+Adds a header @samp{@var{name}: @var{value}} to the message. In
+contrast to @code{add} action, this function allows to construct
+the header name using arbitrary @acronym{MFL} expressions.
+@end deftypefn
+
+@deftypefn {Built-in Function} void header_delete (string @var{name} @
+ [, number @var{index}])
+Delete header @var{name} from the envelope. If @var{index} is given,
+delete @var{index}th instance of header @var{name}.
+
+Notice the differences between this function and the @code{delete}
+action:
+
+@enumerate 1
+@item It allows to construct the header name, whereas @code{delete}
+requires it to be a literal string.
+
+@item Optional @var{index} argument allows to select a particular header
+instance to delete.
+@end enumerate
+@end deftypefn
+
+@deftypefn {Built-in Function} void header_replace (string @var{name}, @
+ string @var{value} [, number @var{index}])
+Replace the value of the header @var{name} with @var{value}. If
+@var{index} is given, replace @var{index}th instance of header @var{name}.
+
+Notice the differences between this function and the @code{replace}
+action:
+
+@enumerate 1
+@item It allows to construct the header name, whereas @code{replace}
+requires it to be a literal string.
+
+@item Optional @var{index} argument allows to select a particular header
+instance to replace.
+@end enumerate
+@end deftypefn
@node Mail header functions
@subsubsection Mail Header Functions
@@ -5760,6 +5840,14 @@ Sent bugreports to <some-address@@some.net>
@end smallexample
@end deftypefn
+@node Quarantine functions
+@subsubsection Quarantine Functions
+
+@deftypefn {Built-in Function} void quarantine (string @var{text})
+Place the message to the quarantine queue, using @var{text} as
+explanatory reason.
+@end deftypefn
+
@node Polling functions
@subsubsection Polling Functions
@@ -8627,8 +8715,8 @@ reject 503 5.0.0 "Need HELO command"
@anchor{header manipulation}
@cindex header manipulation actions
@cindex actions, header manipulation
- Header manipulation actions allow you to add, delete or modify
-message @acronym{RFC} 2822 headers.
+ Header manipulation actions provide basic means to add, delete or modify
+the message @acronym{RFC} 2822 headers.
@table @command
@item add @var{name} @var{string}
@@ -8663,6 +8751,13 @@ delete "X-Envelope-Date"
@end smallexample
@end table
+ These actions impose some restrictions. First of all, their first
+argument must be a literal string (not a variable or expression).
+Secondly, there is no way to select a particular header instance
+to delete or replace, which may be necessary to properly handle
+multiple headers (e.g. @samp{Received}). For more elaborate ways of
+header modifications, @ref{Header modification functions}.
+
@node Assignments
@subsection Variable Assignments
diff --git a/gacopyz/server.c b/gacopyz/server.c
index 2a889021..583a4b24 100644
--- a/gacopyz/server.c
+++ b/gacopyz/server.c
@@ -1064,13 +1064,13 @@ gacopyz_srv_send_command(gacopyz_srv_t srv, unsigned char cmd,
srv->resp_ptr = srv->buf;
srv->resp_size = size;
gacopyz_io_log(&srv->iod, SMI_LOG_DEBUG,
- "action=%s, unhandled response=%c",
+ "action=%s, response=%c",
cp->action, rcmd);
break;
default:
gacopyz_io_log(&srv->iod, SMI_LOG_ERR,
- "action=%s, bogus response=%c",
+ "action=%s, unhandled response=%c",
cp->action, rcmd);
/*FIXME: Change to error state */
srv->state = srv_error;
@@ -1150,15 +1150,15 @@ gacopyz_srv_conn(gacopyz_srv_t srv, const char *hostname, struct sockaddr *sa)
*p++ = code;
switch (ps->sa.sa_family) {
case AF_UNIX:
- strcpy (p, ps->sunix.sun_path);
+ strcpy(p, ps->sunix.sun_path);
break;
case AF_INET:
q = (char*)&ps->sin.sin_port;
- memcpy (p, q, 2);
+ memcpy(p, q, 2);
p += 2;
- q = inet_ntoa (ps->sin.sin_addr);
- memcpy (p, q, 16);
+ q = inet_ntoa(ps->sin.sin_addr);
+ memcpy(p, q, 16);
}
rc = gacopyz_srv_send_command(srv, SMFIC_CONNECT, buf, size);
diff --git a/mfd/Makefile.am b/mfd/Makefile.am
index 436a6077..0c774b86 100644
--- a/mfd/Makefile.am
+++ b/mfd/Makefile.am
@@ -23,10 +23,12 @@ M4_FILES=\
bi_db.m4\
bi_dns.m4\
bi_gettext.m4\
+ bi_header.m4\
bi_io.m4\
bi_ipaddr.m4\
bi_mail.m4\
bi_poll.m4\
+ bi_rcpt.m4\
bi_sa.m4\
bi_sieve.m4\
bi_spf.m4\
@@ -34,7 +36,8 @@ M4_FILES=\
bi_string.m4\
bi_system.m4\
bi_other.m4\
- bi_vars.m4
+ bi_vars.m4\
+ bi_qrnt.m4
mailfromd_SOURCES = \
debug.c\
diff --git a/mfd/bi_header.m4 b/mfd/bi_header.m4
new file mode 100644
index 00000000..61b38f7c
--- /dev/null
+++ b/mfd/bi_header.m4
@@ -0,0 +1,56 @@
+/* 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/>. */
+
+MF_DEFUN(header_add, VOID, STRING name, STRING value)
+{
+ const struct locus *locus = env_get_locus(env);
+
+ trace("%s%s:%lu: %s \"%s: %s\"",
+ mailfromd_msgid(env_get_context(env)),
+ locus->file, locus->line,
+ msgmod_opcode_str(header_add),
+ name, value);
+ env_msgmod(env, header_add, name, value, 1);
+}
+END
+
+MF_DEFUN(header_delete, VOID, STRING name, OPTIONAL, NUMBER idx)
+{
+ const struct locus *locus = env_get_locus(env);
+
+ trace("%s%s:%lu: %s \"%s\" (%lu)",
+ mailfromd_msgid(env_get_context(env)),
+ locus->file, locus->line,
+ msgmod_opcode_str(header_delete),
+ name, MF_OPTVAL(idx, 1));
+ env_msgmod(env, header_delete, name, NULL, MF_OPTVAL(idx, 1));
+}
+END
+
+MF_DEFUN(header_replace, VOID, STRING name, STRING value, OPTIONAL, NUMBER idx)
+{
+ const struct locus *locus = env_get_locus(env);
+
+ trace("%s%s:%lu: %s \"%s: %s\" (%lu)",
+ mailfromd_msgid(env_get_context(env)),
+ locus->file, locus->line,
+ msgmod_opcode_str(header_delete),
+ name, value, MF_OPTVAL(idx, 1));
+ env_msgmod(env, header_replace, name, value, MF_OPTVAL(idx, 1));
+}
+END
+
+MF_INIT
diff --git a/mfd/bi_qrnt.m4 b/mfd/bi_qrnt.m4
new file mode 100644
index 00000000..f5b1b8fc
--- /dev/null
+++ b/mfd/bi_qrnt.m4
@@ -0,0 +1,30 @@
+/* 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/>. */
+
+MF_DEFUN(quarantine, VOID, STRING reason)
+{
+ const struct locus *locus = env_get_locus(env);
+
+ trace("%s%s:%lu: %s %s",
+ mailfromd_msgid(env_get_context(env)),
+ locus->file, locus->line,
+ msgmod_opcode_str(quarantine),
+ reason);
+ env_msgmod(env, quarantine, reason, NULL, 0);
+}
+END
+
+MF_INIT
diff --git a/mfd/bi_rcpt.m4 b/mfd/bi_rcpt.m4
new file mode 100644
index 00000000..d198e8a2
--- /dev/null
+++ b/mfd/bi_rcpt.m4
@@ -0,0 +1,43 @@
+/* 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/>. */
+
+MF_DEFUN(rcpt_add, VOID, STRING addr)
+{
+ const struct locus *locus = env_get_locus(env);
+
+ trace("%s%s:%lu: %s %s",
+ mailfromd_msgid(env_get_context(env)),
+ locus->file, locus->line,
+ msgmod_opcode_str(rcpt_add),
+ addr);
+ env_msgmod(env, rcpt_add, addr, NULL, 0);
+}
+END
+
+MF_DEFUN(rcpt_delete, VOID, STRING addr)
+{
+ const struct locus *locus = env_get_locus(env);
+
+ trace("%s%s:%lu: %s %s",
+ mailfromd_msgid(env_get_context(env)),
+ locus->file, locus->line,
+ msgmod_opcode_str(rcpt_delete),
+ addr);
+ env_msgmod(env, rcpt_delete, addr, NULL, 0);
+}
+END
+
+MF_INIT
diff --git a/mfd/drivers.c b/mfd/drivers.c
index 2b5f9aec..0d4bb601 100644
--- a/mfd/drivers.c
+++ b/mfd/drivers.c
@@ -955,7 +955,7 @@ void
print_type_header(NODE *node, int level)
{
print_level(level);
- printf("%s %s: \n", header_command_str(node->v.hdr.opcode),
+ printf("%s %s: \n", msgmod_opcode_str(node->v.hdr.opcode),
node->v.hdr.name->text);
print_node_list(node->v.hdr.value, level+1);
}
diff --git a/mfd/engine.c b/mfd/engine.c
index 0bb0e3e0..92e2fbe3 100644
--- a/mfd/engine.c
+++ b/mfd/engine.c
@@ -46,7 +46,7 @@
static char *ctx_getsym(void *data, char *str);
static int ctx_setreply(void *data, char *code, char *xcode, char *message);
-static void ctx_setheader(void *data, struct old_header_node *hdr);
+static void ctx_msgmod(void *data, struct msgmod_closure *cmd);
/* Per-message data */
struct smtp_io_data; /* Declared later on */
@@ -77,7 +77,7 @@ priv_get(SMFICTX *ctx)
md->env = create_environment(ctx,
ctx_getsym,
ctx_setreply,
- ctx_setheader,
+ ctx_msgmod,
ctx);
clear_rcpt_count(md->env);
md->hdr = NULL;
@@ -134,23 +134,27 @@ mailfromd_timestr(time_t timestamp, char *timebuf, size_t bufsize)
}
void
-destroy_old_header(void *item)
+destroy_msgmod_closure(void *item)
{
- struct old_header_node *node = item;
- free(node->value);
+ struct msgmod_closure *cmd = item;
+ free(cmd->name);
+ free(cmd->value);
}
int
-priv_store_header_command(SMFICTX *ctx, struct old_header_node *node)
+priv_store_msgmod_closure(SMFICTX *ctx, struct msgmod_closure *cmd)
{
struct message_data *md = priv_get(ctx);
if (!md)
return 1;
if (!md->hdr) {
mu_list_create(&md->hdr);
- mu_list_set_destroy_item(md->hdr, destroy_old_header);
+ mu_list_set_destroy_item(md->hdr, destroy_msgmod_closure);
}
- mu_list_append(md->hdr, node);
+ debug4(10, "adding msgmod_closure: %s \"%s\" %s %u",
+ msgmod_opcode_str(cmd->opcode),
+ cmd->name, SP(cmd->value), cmd->idx);
+ mu_list_append(md->hdr, cmd);
return 0;
}
@@ -178,9 +182,9 @@ ctx_setreply(void *data, char *code, char *xcode, char *message)
}
static void
-ctx_setheader(void *data, struct old_header_node *hdr)
+ctx_msgmod(void *data, struct msgmod_closure *cmd)
{
- priv_store_header_command(data, hdr);
+ priv_store_msgmod_closure(data, cmd);
}
@@ -1116,26 +1120,38 @@ mlfi_body(SMFICTX *ctx, unsigned char *bodyp, size_t len)
}
static int
-run_header_command(void *item, void *data)
+run_msgmod(void *item, void *data)
{
- struct old_header_node *hdr = item;
+ struct msgmod_closure *hdr = item;
SMFICTX *ctx = data;
- debug3(50,
- "%s %s: %s",
- header_command_str(hdr->opcode),
- hdr->name, hdr->value);
+ debug4(50,
+ "%s %s: %s %u",
+ msgmod_opcode_str(hdr->opcode),
+ hdr->name, SP(hdr->value), hdr->idx);
switch (hdr->opcode) {
case header_add:
gacopyz_add_header(ctx, hdr->name, hdr->value);
break;
case header_replace:
- gacopyz_change_header(ctx, 1, hdr->name, hdr->value);
+ gacopyz_change_header(ctx, hdr->idx, hdr->name, hdr->value);
break;
case header_delete:
- gacopyz_change_header(ctx, 1, hdr->name, NULL);
+ gacopyz_change_header(ctx, hdr->idx, hdr->name, NULL);
+ break;
+
+ case rcpt_add:
+ gacopyz_add_rcpt(ctx, hdr->name);
+ break;
+
+ case rcpt_delete:
+ gacopyz_del_rcpt(ctx, hdr->name);
+ break;
+
+ case quarantine:
+ gacopyz_quarantine(ctx, hdr->name);
break;
}
return 0;
@@ -1157,7 +1173,7 @@ mlfi_eom(SMFICTX *ctx)
env_leave_frame(md->env, 0);
if ((status == SMFIS_ACCEPT || status == SMFIS_CONTINUE) && md->hdr) {
debug(50,"executing header commands");
- mu_list_do(md->hdr, run_header_command, ctx);
+ mu_list_do(md->hdr, run_msgmod, ctx);
}
clear_rcpt_count(md->env);
@@ -1239,7 +1255,7 @@ struct smfiDesc smfilter =
{
"MailfromFilter",
SMFI_VERSION,
- SMFIF_ADDHDRS|SMFIF_CHGHDRS,
+ SMFI_V2_ACTS, /* FIXME: Add flags as needed */
NULL, /* connection info filter */
NULL, /* SMTP HELO command filter */
NULL, /* envelope sender filter */
diff --git a/mfd/gram.y b/mfd/gram.y
index 7b6cdc4c..69f87836 100644
--- a/mfd/gram.y
+++ b/mfd/gram.y
@@ -1988,7 +1988,7 @@ static void print_node_list_reverse(NODE *node, int level);
static void print_node(NODE *node, int indent);
void print_stat(sfsistat stat);
static int dbg_setreply(void *data, char *code, char *xcode, char *message);
-static void dbg_setheader(void *data, struct old_header_node *hdr);
+static void dbg_msgmod(void *data, struct msgmod_closure *clos);
static void
print_level(int level)
@@ -2797,21 +2797,28 @@ print_stat(sfsistat stat)
}
const char *
-header_command_str(enum header_opcode opcode)
+msgmod_opcode_str(enum msgmod_opcode opcode)
{
switch (opcode) {
case header_add:
- return "ADD HEADER ";
+ return "ADD HEADER";
case header_replace:
- return "REPLACE HEADER ";
- break;
+ return "REPLACE HEADER";
case header_delete:
- return "DELETE HEADER ";
- break;
+ return "DELETE HEADER";
+
+ case rcpt_add:
+ return "ADD RECIPIENT";
+
+ case rcpt_delete:
+ return "DELETER RECIPIENT";
+
+ case quarantine:
+ return "QUARANTINE";
}
- return "UNKNOWN HEADER COMMAND ";
+ return "UNKNOWN HEADER COMMAND";
}
static int
@@ -2829,10 +2836,10 @@ dbg_setreply(void *data, char *code, char *xcode, char *message)
}
static void
-dbg_setheader(void *data, struct old_header_node *hdr)
+dbg_msgmod(void *data, struct msgmod_closure *clos)
{
- printf("%s %s: %s\n", header_command_str(hdr->opcode), hdr->name,
- hdr->value);
+ printf("%s %s: %s %u\n", msgmod_opcode_str(clos->opcode),
+ clos->name, SP(clos->value), clos->idx);
}
static char *
@@ -2854,7 +2861,7 @@ mailfromd_test(int argc, char **argv)
dict_init(&dict);
env = create_environment(NULL,
- dbg_dict_getsym, dbg_setreply, dbg_setheader,
+ dbg_dict_getsym, dbg_setreply, dbg_msgmod,
dict);
xeval(env, smtp_state_begin);
diff --git a/mfd/mailfromd.h b/mfd/mailfromd.h
index 85a6ff39..4dd8c1b1 100644
--- a/mfd/mailfromd.h
+++ b/mfd/mailfromd.h
@@ -26,6 +26,8 @@
#include "libmf.h"
+#define SP(s) ((s) ? (s) : "(null)")
+
/* Status values used throughout the program */
typedef enum mf_status_code {
mf_success,
@@ -212,8 +214,8 @@ typedef struct node NODE;
/* Input location */
struct locus {
- const char *file; /* File name */
- size_t line; /* Line number */
+ const char *file; /* File name */
+ unsigned long line; /* Line number */
};
#define LOCUS_EQ(a,b) \
@@ -283,22 +285,26 @@ struct return_node {
NODE *message; /* Subtree producing the textual message */
};
-enum header_opcode { /* Operation on a header */
+enum msgmod_opcode { /* Message modification operation */
header_add, /* Add a header */
header_replace, /* Replace a header value */
- header_delete /* Delete a header */
+ header_delete, /* Delete a header */
+ rcpt_add, /* Add a recipient */
+ rcpt_delete, /* Delete a recipient */
+ quarantine, /* Quarantine a message */
};
-struct old_header_node {
- enum header_opcode opcode; /* Operation code */
- const char *name; /* Header name */
- char *value; /* Header value */
+struct msgmod_closure {
+ enum msgmod_opcode opcode; /* Operation code */
+ char *name; /* Object name */
+ char *value; /* Object value */
+ unsigned idx; /* Object index */
};
struct header_node {
- enum header_opcode opcode; /* Operation code */
- struct literal *name; /* Header name */
- NODE *value; /* Header value */
+ enum msgmod_opcode opcode; /* Operation code */
+ struct literal *name; /* Header name */
+ NODE *value; /* Header value */
};
struct rate_node { /* Rate test */
@@ -636,17 +642,19 @@ void onblock(int enable);
int parse_program(char *name, int ydebug);
void parse_pragma(char *text);
const struct locus *get_locus(void);
-const char *header_command_str(enum header_opcode opcode);
+const char *msgmod_opcode_str(enum msgmod_opcode opcode);
const char *sfsistat_str(sfsistat stat);
const char *mf_status_str(mf_status stat);
const char *storage_class_str(storage_class_t sc);
int string_to_stat(const char *str, mf_status *status);
enum smtp_state string_to_state(const char *name);
const char *state_to_string(enum smtp_state state);
-void parse_error(const char *fmt, ...);
-void parse_error_locus(const struct locus *loc, const char *fmt, ...);
-void parse_warning(const char *fmt, ...);
-void parse_warning_locus(const struct locus *loc, const char *fmt, ...);
+void parse_error(const char *fmt, ...) MU_PRINTFLIKE(1,2);
+void parse_error_locus(const struct locus *loc, const char *fmt, ...)
+ MU_PRINTFLIKE(2,3);
+void parse_warning(const char *fmt, ...) MU_PRINTFLIKE(1,2);
+void parse_warning_locus(const struct locus *loc, const char *fmt, ...)
+ MU_PRINTFLIKE(2,3);
void print_syntax_tree(void);
void print_macros(void);
const char *function_name(void);
@@ -699,7 +707,7 @@ create_environment(SMFICTX *ctx,
char *(*getsym)(void *data, char *str),
int (*setreply)(void *data, char *code, char *xcode,
char *message),
- void (*setheader)(void *data, struct old_header_node *hdr),
+ void (*msgmod)(void *data, struct msgmod_closure *op),
void *data);
void destroy_environment(eval_environ_t env);
void env_init(eval_environ_t env);
@@ -710,9 +718,10 @@ void env_save_catches(eval_environ_t env);
# endif
void env_throw(eval_environ_t env, mf_status status,
- const char *fmt, ...) ATTRIBUTE_NORETURN;
+ const char *fmt, ...)
+ MU_PRINTFLIKE(3,4) ATTRIBUTE_NORETURN;
void env_throw_bi(eval_environ_t env, mf_status status, const char *biname,
- const char *fmt, ...) ATTRIBUTE_NORETURN;
+ const char *fmt, ...) MU_PRINTFLIKE(4,5) ATTRIBUTE_NORETURN;
void env_throw_0(eval_environ_t env, mf_status status,
size_t text_off) ATTRIBUTE_NORETURN;
@@ -731,16 +740,18 @@ int env_capture_start(eval_environ_t env);
int env_capture_write(eval_environ_t env, const char *buf, size_t size);
int env_capture_write_args(eval_environ_t env, ...);
void env_final_gc(eval_environ_t env);
+void env_msgmod(eval_environ_t env, enum msgmod_opcode opcode,
+ const char *name, const char *value, unsigned idx);
void capture_on(void);
/* Runtime functions */
const char *mailfromd_msgid(SMFICTX *ctx);
char *mailfromd_timestr(time_t timestamp, char *timebuf, size_t bufsize);
-void logmsg(int prio, const char *fmt, ...);
+void logmsg(int prio, const char *fmt, ...) MU_PRINTFLIKE(2,3);
void vlogmsg(int prio, const char *fmt, va_list ap);
void log_status(sfsistat status, SMFICTX *ctx);
-void trace(const char *fmt, ...);
+void trace(const char *fmt, ...) MU_PRINTFLIKE(1,2);
int convert_rate(const char *arg, double *rate);
extern void priv_setup(void);
void mailfromd_daemon(void);
diff --git a/mfd/prog.c b/mfd/prog.c
index 62a9dd92..2a33ba22 100644
--- a/mfd/prog.c
+++ b/mfd/prog.c
@@ -38,8 +38,6 @@
#define obstack_chunk_free free
#include <obstack.h>
-#define SP(s) ((s) ? (s) : "''")
-
/* Code generation support */
#define CODE_INITIAL 128
@@ -260,7 +258,7 @@ struct eval_environ {
/* methods to access the latter */
char *(*getsym)(void *data, char *str);
int (*setreply)(void *data, char *code, char *xcode, char *message);
- void (*setheader)(void *data, struct old_header_node *hdr);
+ void (*msgmod)(void *data, struct msgmod_closure *c);
/* Regular expression matching */
regmatch_t *matches; /* Match map */
@@ -1087,7 +1085,7 @@ instr_div(eval_environ_t env)
prog_trace(env, "DIV %ld %ld", a, b);
if (b == 0)
env_throw(env, mf_divzero,
- "Division by zero at %08x", env->pc);
+ "Division by zero at %08x", (unsigned int) env->pc);
push(env, (STKVAL) (a / b));
}
@@ -1349,33 +1347,28 @@ dump_result(prog_counter_t i)
void
instr_header(eval_environ_t env)
{
- struct old_header_node *hdr = xmalloc (sizeof(*hdr));
-
- hdr->opcode = (enum header_opcode) get_immediate(env, 0);
- hdr->name = get_literal(env, 1);
- hdr->value = st