diff options
-rw-r--r-- | NEWS | 19 | ||||
-rw-r--r-- | doc/mailfromd.texi | 86 | ||||
-rw-r--r-- | mfd/drivers.c | 115 | ||||
-rw-r--r-- | mfd/gram.y | 131 | ||||
-rw-r--r-- | mfd/lex.l | 4 | ||||
-rw-r--r-- | mfd/mailfromd.h | 8 | ||||
-rw-r--r-- | mfd/opcodes | 2 | ||||
-rw-r--r-- | mfd/prog.c | 10 |
8 files changed, 276 insertions, 99 deletions
@@ -1,2 +1,2 @@ | |||
1 | Mailfromd NEWS -- history of user-visible changes. 2009-05-10 | 1 | Mailfromd NEWS -- history of user-visible changes. 2009-05-11 |
2 | Copyright (C) 2005, 2006, 2007, 2008, 2009 Sergey Poznyakoff | 2 | Copyright (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 | |||
29 | The reply actions `reject' and `tempfail' allow functional notation, | ||
30 | i.e. their arguments can be supplied as to a function: | ||
31 | |||
32 | reject(550, 5.7.7, "IP address does not resolve") | ||
33 | |||
34 | An important feature of this notation is that all three arguments are | ||
35 | MFL expressions, which means that you can now compute the reply codes | ||
36 | at run time: | ||
37 | |||
38 | reject(550 + %n, "5.7." %x, "Transaction rejected") | ||
39 | |||
40 | An 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}, | |||
1357 | and @code{tempfail}. Among these, @code{reject} and @code{discard} | 1357 | and @code{tempfail}. Among these, @code{reject} and @code{discard} |
1358 | can optionally take one to three arguments. The first | 1358 | can optionally take one to three arguments. There are two ways of |
1359 | argument is a three-digit @acronym{RFC} 2821 reply code. It must begin with | 1359 | supplying the arguments. |
1360 | @samp{5} for @code{reject} and with @samp{4} for @code{tempfail}. If | 1360 | |
1361 | two arguments are supplied, the second argument must be either an | 1361 | In 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 | 1362 | the arguments are supplied as additional words after the action name, |
1363 | separated 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 | ||
1366 | are supplied, the second argument must be either an @dfn{extended | ||
1367 | reply code} (@acronym{RFC} 1893/2034) or a textual string to be | ||
1363 | returned along with the @acronym{SMTP} reply. Finally, if all three | 1368 | returned 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 | |||
1366 | examples illustrate all possible ways of using the @code{reject} | 1371 | examples illustrate all possible ways of using the @code{reject} |
1367 | statement: | 1372 | statement in literal notation: |
1368 | 1373 | ||
@@ -1381,2 +1386,21 @@ Please note the quotes around the textual string. | |||
1381 | 1386 | ||
1387 | Another form for these action is called @dfn{functional} notation, | ||
1388 | because it resembles the function syntax. When used in this form, the | ||
1389 | action word is followed by a parenthesized group of exactly three | ||
1390 | arguments, separated by commas. The meaning and ordering of the | ||
1391 | argument is the same as in literal form. Any of three arguments may | ||
1392 | be absent, in which case it will be replaced by the default value. To | ||
1393 | illustrate this, here are the statements from the previous example, | ||
1394 | written in functional notation: | ||
1395 | |||
1396 | @smallexample | ||
1397 | @group | ||
1398 | reject(,,) | ||
1399 | reject(503,,) | ||
1400 | reject(503, 5.0.0) | ||
1401 | reject(503,, "Need HELO command") | ||
1402 | reject(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 |
10281 | Reply actions tell @command{Sendmail} to return given response code | ||
10257 | to the remote party. There are five such actions: | 10282 | to 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 |
10295 | optional parameters. The first argument is a three-digit | 10322 | optional parameters. There are two forms of supplying these |
10323 | parameters. | ||
10324 | |||
10325 | In the first form, called @dfn{literal} or @dfn{traditional} notation, | ||
10326 | the arguments are supplied as additional words after the action name, | ||
10327 | and 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 | ||
10348 | The notion @dfn{textual string}, used above means either a literal | ||
10349 | string or an @acronym{MFL} expression that evaluates to string. | ||
10350 | However, both code and extended code must always be literal. | ||
10351 | |||
10352 | The second form of supplying arguments is called @dfn{functional} | ||
10353 | notation, because it resembles the function syntax. When used in this | ||
10354 | form, the action word is followed by a parenthesized group of exactly | ||
10355 | three arguments, separated by commas. Each argument is a | ||
10356 | @acronym{MFL} expression. The meaning and ordering of the arguments is | ||
10357 | the same as in literal form. Any or all of these three arguments may | ||
10358 | be absent, in which case it will be replaced by the default value. To | ||
10359 | illustrate this, here are the statements from the previous example, | ||
10360 | written in functional notation: | ||
10361 | |||
10362 | @smallexample | ||
10363 | @group | ||
10364 | reject(,,) | ||
10365 | reject(503,,) | ||
10366 | reject(503, 5.0.0) | ||
10367 | reject(503, "Need HELO command",) | ||
10368 | reject(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 | ||
10373 | notations. The functional notation allows to compute both reply codes | ||
10374 | at 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 | ||
933 | void | 932 | static void |
934 | code_type_result(NODE *node, struct locus **old_locus) | 933 | code_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 | |||
943 | static NODE * | ||
944 | result_argptr(NODE *arg) | ||
945 | { | ||