aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--NEWS19
-rw-r--r--doc/mailfromd.texi86
-rw-r--r--mfd/drivers.c115
-rw-r--r--mfd/gram.y131
-rw-r--r--mfd/lex.l4
-rw-r--r--mfd/mailfromd.h8
-rw-r--r--mfd/opcodes2
-rw-r--r--mfd/prog.c10
8 files changed, 276 insertions, 99 deletions
diff --git a/NEWS b/NEWS
index b50d87a8..90b7a889 100644
--- a/NEWS
+++ b/NEWS
@@ -1,2 +1,2 @@
1Mailfromd NEWS -- history of user-visible changes. 2009-05-10 1Mailfromd NEWS -- history of user-visible changes. 2009-05-11
2Copyright (C) 2005, 2006, 2007, 2008, 2009 Sergey Poznyakoff 2Copyright (C) 2005, 2006, 2007, 2008, 2009 Sergey Poznyakoff
@@ -26,2 +26,19 @@ each stage is limited (Mailfromd manual, section 11.1.2).
26 26
27* Reject and tempfail actions: Functional notation
28
29The reply actions `reject' and `tempfail' allow functional notation,
30i.e. their arguments can be supplied as to a function:
31
32 reject(550, 5.7.7, "IP address does not resolve")
33
34An important feature of this notation is that all three arguments are
35MFL expressions, which means that you can now compute the reply codes
36at run time:
37
38 reject(550 + %n, "5.7." %x, "Transaction rejected")
39
40An argument can be omitted, in which case the default value is used, e.g.:
41
42 reject(550 + %n, , "Transaction rejected")
43
27* New functions 44* New functions
diff --git a/doc/mailfromd.texi b/doc/mailfromd.texi
index 3d2e43c5..090222eb 100644
--- a/doc/mailfromd.texi
+++ b/doc/mailfromd.texi
@@ -1357,7 +1357,12 @@ code: @code{continue}, @code{accept}, @code{reject}, @code{discard},
1357and @code{tempfail}. Among these, @code{reject} and @code{discard} 1357and @code{tempfail}. Among these, @code{reject} and @code{discard}
1358can optionally take one to three arguments. The first 1358can optionally take one to three arguments. There are two ways of
1359argument is a three-digit @acronym{RFC} 2821 reply code. It must begin with 1359supplying the arguments.
1360@samp{5} for @code{reject} and with @samp{4} for @code{tempfail}. If 1360
1361two arguments are supplied, the second argument must be either an 1361In the first form, called @dfn{literal} or @dfn{traditional} notation,
1362@dfn{extended reply code} (@acronym{RFC} 1893/2034) or a textual string to be 1362the arguments are supplied as additional words after the action name,
1363separated by whitespace. The first argument is a three-digit
1364@acronym{RFC} 2821 reply code. It must begin with @samp{5} for
1365@code{reject} and with @samp{4} for @code{tempfail}. If two arguments
1366are supplied, the second argument must be either an @dfn{extended
1367reply code} (@acronym{RFC} 1893/2034) or a textual string to be
1363returned along with the @acronym{SMTP} reply. Finally, if all three 1368returned along with the @acronym{SMTP} reply. Finally, if all three
@@ -1366,3 +1371,3 @@ code and the third one must supply the textual string. The following
1366examples illustrate all possible ways of using the @code{reject} 1371examples illustrate all possible ways of using the @code{reject}
1367statement: 1372statement in literal notation:
1368 1373
@@ -1381,2 +1386,21 @@ Please note the quotes around the textual string.
1381 1386
1387Another form for these action is called @dfn{functional} notation,
1388because it resembles the function syntax. When used in this form, the
1389action word is followed by a parenthesized group of exactly three
1390arguments, separated by commas. The meaning and ordering of the
1391argument is the same as in literal form. Any of three arguments may
1392be absent, in which case it will be replaced by the default value. To
1393illustrate this, here are the statements from the previous example,
1394written in functional notation:
1395
1396@smallexample
1397@group
1398reject(,,)
1399reject(503,,)
1400reject(503, 5.0.0)
1401reject(503,, "Need HELO command")
1402reject(503, 5.0.0, "Need HELO command")
1403@end group
1404@end smallexample
1405
1382@node Conditional Execution 1406@node Conditional Execution
@@ -10255,3 +10279,4 @@ two kinds of actions: return actions and header manipulation actions.
10255 10279
10256 Return actions tell @command{Sendmail} to return given response code 10280@subsubheading Reply Actions
10281Reply actions tell @command{Sendmail} to return given response code
10257to the remote party. There are five such actions: 10282to the remote party. There are five such actions:
@@ -10265,3 +10290,4 @@ transmitting its message.
10265 10290
10266@item reject [@var{code}] [@var{excode}] [@var{message}] 10291@item reject @var{code} @var{excode} @var{message-expr}
10292@itemx reject (@var{code-expr}, @var{excode-expr}, @var{message-expr})
10267@cindex reject action, defined 10293@cindex reject action, defined
@@ -10272,3 +10298,4 @@ their usage is described below.
10272 10298
10273@item tempfail [@var{code}] [@var{excode}] [@var{message}] 10299@item tempfail @var{code} @var{excode} @var{message}
10300@itemx tempfail (@var{code-expr}, @var{excode-expr}, @var{message-expr})
10274@cindex tempfail action, defined 10301@cindex tempfail action, defined
@@ -10294,3 +10321,8 @@ continue processing of the message.
10294 Two actions, @code{reject} and @code{tempfail} can take up to three 10321 Two actions, @code{reject} and @code{tempfail} can take up to three
10295optional parameters. The first argument is a three-digit 10322optional parameters. There are two forms of supplying these
10323parameters.
10324
10325In the first form, called @dfn{literal} or @dfn{traditional} notation,
10326the arguments are supplied as additional words after the action name,
10327and are separated by whitespace. The first argument is a three-digit
10296@acronym{RFC} 2821 reply code. It must begin with @samp{5} for 10328@acronym{RFC} 2821 reply code. It must begin with @samp{5} for
@@ -10315,2 +10347,36 @@ reject 503 5.0.0 "Need HELO command"
10315 10347
10348The notion @dfn{textual string}, used above means either a literal
10349string or an @acronym{MFL} expression that evaluates to string.
10350However, both code and extended code must always be literal.
10351
10352The second form of supplying arguments is called @dfn{functional}
10353notation, because it resembles the function syntax. When used in this
10354form, the action word is followed by a parenthesized group of exactly
10355three arguments, separated by commas. Each argument is a
10356@acronym{MFL} expression. The meaning and ordering of the arguments is
10357the same as in literal form. Any or all of these three arguments may
10358be absent, in which case it will be replaced by the default value. To
10359illustrate this, here are the statements from the previous example,
10360written in functional notation:
10361
10362@smallexample
10363@group
10364reject(,,)
10365reject(503,,)
10366reject(503, 5.0.0)
10367reject(503, "Need HELO command",)
10368reject(503, 5.0.0, "Need HELO command")
10369@end group
10370@end smallexample
10371
10372 Notice that there is an important difference between the two
10373notations. The functional notation allows to compute both reply codes
10374at run time, e.g.:
10375
10376@smallexample
10377 reject(500 + %dig2*10 + %dig3, "5." %edig2 "." %edig2)
10378@end smallexample
10379
10380@subsubheading Header Actions
10381
10316@anchor{header manipulation} 10382@anchor{header manipulation}
diff --git a/mfd/drivers.c b/mfd/drivers.c
index d8dfb4b2..ed8a288a 100644
--- a/mfd/drivers.c
+++ b/mfd/drivers.c
@@ -891,25 +891,24 @@ print_type_result(NODE *node, int level)
891{ 891{
892 if (node->v.ret.code) { 892 NODE *code, *xcode;
893 const char *s = NULL; 893
894 int expr = 0; 894 code = node->v.ret.code;
895 895 xcode = node->v.ret.xcode;
896 print_level(level); 896
897 if (node->v.ret.message) {
898 if (node->v.ret.message->type == node_type_string)
899 s = node->v.ret.message->v.literal->text;
900 else {
901 expr = 1;
902 s = "(expression)";
903 }
904 }
905 dbg_setreply(NULL,
906 (char*) LITERAL_TEXT(node->v.ret.code),
907 (char*) LITERAL_TEXT(node->v.ret.xcode),
908 (char*) s);
909 if (expr)
910 print_node(node->v.ret.message, level+1);
911 }
912 print_level(level); 897 print_level(level);
898 printf("SET REPLY ");
913 print_stat(node->v.ret.stat); 899 print_stat(node->v.ret.stat);
914 printf("\n"); 900 printf("\n");
901 print_level(level);
902 printf("CODE:\n");
903 if (code)
904 print_node(code, level+1);
905 print_level(level);
906 printf("XCODE:\n");
907 if (xcode)
908 print_node(xcode, level+1);
909 print_level(level);
910 printf("MESSAGE:\n");
911 if (node->v.ret.message)
912 print_node(node->v.ret.message, level+1);
913 printf("\n");
915} 914}
@@ -919,6 +918,4 @@ mark_type_result(NODE *node)
919{ 918{
920 if (node->v.ret.code) 919 mark(node->v.ret.code);
921 node->v.ret.code->flags |= VAR_REFERENCED; 920 mark(node->v.ret.xcode);
922 if (node->v.ret.xcode)
923 node->v.ret.xcode->flags |= VAR_REFERENCED;
924 mark(node->v.ret.message); 921 mark(node->v.ret.message);
@@ -929,2 +926,4 @@ optimize_type_result(NODE *node)
929{ 926{
927 optimize(node->v.ret.code);
928 optimize(node->v.ret.xcode);
930 optimize(node->v.ret.message); 929 optimize(node->v.ret.message);
@@ -932,8 +931,7 @@ optimize_type_result(NODE *node)
932 931
933void 932static void
934code_type_result(NODE *node, struct locus **old_locus) 933code_result_arg(NODE *node)
935{ 934{
936 MARK_LOCUS(); 935 if (node)
937 if (node->v.ret.message) 936 code_node(node);
938 code_node(node->v.ret.message);
939 else { 937 else {
@@ -942,2 +940,51 @@ code_type_result(NODE *node, struct locus **old_locus)
942 } 940 }
941}
942
943static NODE *
944result_argptr(NODE *arg)
945{