diff options
author | Sergey Poznyakoff <gray@gnu.org.ua> | 2008-01-21 13:24:15 +0000 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org.ua> | 2008-01-21 13:24:15 +0000 |
commit | 5cd62ab035e90d6580d7db4f430e916eb588fdfd (patch) | |
tree | e33eb8048c38e2ed2d09062fed2b10a438ae05b6 | |
parent | 8e0985ffe8caa3399718bacb25e45eba6baa0d5c (diff) | |
download | mailfromd-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-- | ChangeLog | 27 | ||||
-rw-r--r-- | NEWS | 50 | ||||
-rw-r--r-- | doc/Makefile.am | 8 | ||||
-rw-r--r-- | doc/mailfromd.texi | 101 | ||||
-rw-r--r-- | gacopyz/server.c | 12 | ||||
-rw-r--r-- | mfd/Makefile.am | 5 | ||||
-rw-r--r-- | mfd/bi_header.m4 | 56 | ||||
-rw-r--r-- | mfd/bi_qrnt.m4 | 30 | ||||
-rw-r--r-- | mfd/bi_rcpt.m4 | 43 | ||||
-rw-r--r-- | mfd/drivers.c | 2 | ||||
-rw-r--r-- | mfd/engine.c | 56 | ||||
-rw-r--r-- | mfd/gram.y | 31 | ||||
-rw-r--r-- | mfd/mailfromd.h | 53 | ||||
-rw-r--r-- | mfd/prog.c | 50 | ||||
-rw-r--r-- | mfd/symtab.c | 2 |
15 files changed, 435 insertions, 91 deletions
@@ -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 @@ -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 */ @@ -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); @@ -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 |