aboutsummaryrefslogtreecommitdiff
path: root/mfd
diff options
context:
space:
mode:
Diffstat (limited to 'mfd')
-rw-r--r--mfd/drivers.c113
-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
6 files changed, 181 insertions, 87 deletions
diff --git a/mfd/drivers.c b/mfd/drivers.c
index d8dfb4b2..ed8a288a 100644
--- a/mfd/drivers.c
+++ b/mfd/drivers.c
@@ -888,64 +888,109 @@ code_type_un(NODE *node, struct locus **old_locus)
void
print_type_result(NODE *node, int level)
{
- if (node->v.ret.code) {
- const char *s = NULL;
- int expr = 0;
+ NODE *code, *xcode;
+
+ code = node->v.ret.code;
+ xcode = node->v.ret.xcode;
print_level(level);
- if (node->v.ret.message) {
- if (node->v.ret.message->type == node_type_string)
- s = node->v.ret.message->v.literal->text;
- else {
- expr = 1;
- s = "(expression)";
- }
- }
- dbg_setreply(NULL,
- (char*) LITERAL_TEXT(node->v.ret.code),
- (char*) LITERAL_TEXT(node->v.ret.xcode),
- (char*) s);
- if (expr)
- print_node(node->v.ret.message, level+1);
- }
- print_level(level);
+ printf("SET REPLY ");
print_stat(node->v.ret.stat);
printf("\n");
+ print_level(level);
+ printf("CODE:\n");
+ if (code)
+ print_node(code, level+1);
+ print_level(level);
+ printf("XCODE:\n");
+ if (xcode)
+ print_node(xcode, level+1);
+ print_level(level);
+ printf("MESSAGE:\n");
+ if (node->v.ret.message)
+ print_node(node->v.ret.message, level+1);
+ printf("\n");
}
void
mark_type_result(NODE *node)
{
- if (node->v.ret.code)
- node->v.ret.code->flags |= VAR_REFERENCED;
- if (node->v.ret.xcode)
- node->v.ret.xcode->flags |= VAR_REFERENCED;
+ mark(node->v.ret.code);
+ mark(node->v.ret.xcode);
mark(node->v.ret.message);
}
void
optimize_type_result(NODE *node)
{
+ optimize(node->v.ret.code);
+ optimize(node->v.ret.xcode);
optimize(node->v.ret.message);
}
-void
-code_type_result(NODE *node, struct locus **old_locus)
+static void
+code_result_arg(NODE *node)
{
- MARK_LOCUS();
- if (node->v.ret.message)
- code_node(node->v.ret.message);
+ if (node)
+ code_node(node);
else {
code_op(opcode_push);
code_immediate(NULL);
}
+}
+
+static NODE *
+result_argptr(NODE *arg)
+{
+ if (arg && arg->type == node_type_string
+ && arg->v.literal->text[0] == 0)
+ arg = NULL;
+ return arg;
+}
+
+void
+code_type_result(NODE *node, struct locus **old_locus)
+{
+ NODE *code, *xcode;
+
+ code = result_argptr(node->v.ret.code);
+ xcode = result_argptr(node->v.ret.xcode);
+
+ switch (node->v.ret.stat) {
+ case SMFIS_REJECT:
+ if (code && code->type == node_type_string
+ && code->v.literal->text[0] != '5')
+ parse_error_locus(&node->locus,
+ _("Reject code should be 5xx"));
+ if (xcode && xcode->type == node_type_string
+ && xcode->v.literal->text[0] != '5')
+ parse_error_locus(&node->locus,
+ _("Reject extended code should be 5.x.x"));
+ break;
+
+ case SMFIS_TEMPFAIL:
+ if (code && code->type == node_type_string
+ && code->v.literal->text[0] != '4')
+ parse_error_locus(&node->locus,
+ _("Tempfail code should be 4xx"));
+ if (xcode && xcode->type == node_type_string
+ && xcode->v.literal->text[0] != '4')
+ parse_error_locus(&node->locus,
+ _("Tempfail extended code should be 4.x.x"));
+ break;
+ default:
+ break;
+ }
+
+ code_result_arg(node->v.ret.message);
+ code_result_arg(xcode);
+ code_result_arg(code);
+
MARK_LOCUS();
code_op(opcode_result);
code_immediate((void*)node->v.ret.stat);
- code_immediate((void*)LITERAL_OFF(node->v.ret.code));
- code_immediate((void*)LITERAL_OFF(node->v.ret.xcode));
code_op(opcode_nil);
}
@@ -1481,15 +1526,13 @@ code_type_catch(NODE *node, struct locus **old_locus)
code_immediate((void*)1);
code_op(opcode_jmp);
jump_pc = code_immediate((void*)jump_pc);
} else {
- code_op(opcode_push);
- code_immediate(NULL);
+ code_result_arg(NULL);
+ code_result_arg(NULL);
+ code_result_arg(NULL);
code_op(opcode_result);
code_immediate(SMFIS_CONTINUE);
- code_immediate(NULL);
- code_immediate(NULL);
- code_immediate(NULL);
}
endpos = code_get_counter ();
code_put(pos1, (void *)(endpos - pos1));
diff --git a/mfd/gram.y b/mfd/gram.y
index 332a748a..15ee9602 100644
--- a/mfd/gram.y
+++ b/mfd/gram.y
@@ -298,9 +298,9 @@ _create_alias(void *item, void *data)
%}
%error-verbose
-%expect 29
+%expect 28
%union {
struct literal *literal;
struct stmtlist stmtlist;
@@ -359,9 +359,9 @@ _create_alias(void *item, void *data)
%token <locus> MXMATCHES MXFNMATCHES
%token <locus> WHEN PASS SET CATCH THROW KW_ECHO RETURNS RETURN FUNC
%token <locus> SWITCH CASE DEFAULT CONST
%token <locus> FOR LOOP WHILE BREAK NEXT ARGCOUNT ALIAS DOTS ARGX VAPTR
-%token <literal> STRING CODE XCODE
+%token <literal> STRING
%token <literal> SYMBOL IDENTIFIER
%token <number> ARG NUMBER BACKREF
%token <builtin> BUILTIN BUILTIN_PROC BUILTIN_P
%token <locus> OR AND EQ NE LT LE GT GE NOT LOGAND LOGOR LOGXOR LOGNOT
@@ -385,20 +385,20 @@ _create_alias(void *item, void *data)
%left BUILTIN FUNCTION FUNCTION_P BUILTIN_P
%type <node> decl stmt condition action sendmail_action header_action
if_cond else_cond on_cond atom argref paren_argref
- funcall proccall expr common_expr simp_expr atom_expr
+ funcall proccall expr maybe_expr maybe_xcode_expr
+ common_expr simp_expr atom_expr
asgn catch throw return case_cond autodcl constdecl
loopstmt opt_while jumpstmt
%type <stmtlist> stmtlist decllist
%type <ret> triplet maybe_triplet
%type <poll> pollstmt pollarglist
%type <pollarg> pollarg loop_parm
%type <loop> opt_loop_parms loop_parm_list
-%type <number> number
%type <arglist> arglist
%type <var> variable
-%type <literal> string opt_ident loop_ident alias
+%type <literal> string opt_ident loop_ident alias code xcode
%type <state> state_ident
%type <matchtype> matches fnmatches
%type <type> retdecl
%type <parmlist> params parmlist fparmlist parmdecl
@@ -891,26 +891,34 @@ sendmail_action:
$$->v.ret.stat = SMFIS_ACCEPT;
}
| ACT_REJECT maybe_triplet
{
- if ($2.code && $2.code->text[0] != '5')
- parse_error(_("Reject code should be 5xx"));
- if ($2.xcode && $2.xcode->text[0] != '5')
- parse_error(_("Reject extended code should be 5.x.x"));
$$ = alloc_node(node_type_result, &$1);
$$->v.ret = $2;
$$->v.ret.stat = SMFIS_REJECT;
}
+ | ACT_REJECT '(' maybe_expr ',' maybe_xcode_expr ',' maybe_expr ')'
+ {
+ $$ = alloc_node(node_type_result, &$1);
+ $$->v.ret.stat = SMFIS_REJECT;
+ $$->v.ret.code = $3 ? cast_to(dtype_string, $3) : NULL;
+ $$->v.ret.xcode = $5 ? cast_to(dtype_string, $5) : NULL;
+ $$->v.ret.message = $7 ? cast_to(dtype_string, $7) : NULL;
+ }
| ACT_TEMPFAIL maybe_triplet
{
- if ($2.code && $2.code->text[0] != '4')
- parse_error(_("Tempfail code should be 4xx"));
- if ($2.xcode && $2.xcode->text[0] != '4')
- parse_error(_("Tempfail extended code should be 4.x.x"));
$$ = alloc_node(node_type_result, &$1);
$$->v.ret = $2;
$$->v.ret.stat = SMFIS_TEMPFAIL;
}
+ | ACT_TEMPFAIL '(' maybe_expr ',' maybe_xcode_expr ',' maybe_expr ')'
+ {
+ $$ = alloc_node(node_type_result, &$1);
+ $$->v.ret.stat = SMFIS_TEMPFAIL;
+ $$->v.ret.code = $3 ? cast_to(dtype_string, $3) : NULL;
+ $$->v.ret.xcode = $5 ? cast_to(dtype_string, $5) : NULL;
+ $$->v.ret.message = $7 ? cast_to(dtype_string, $7) : NULL;
+ }
| ACT_CONTINUE
{
$$ = alloc_node(node_type_result, &$1);
memset(&$$->v.ret, 0, sizeof $$->v.ret);
@@ -923,8 +931,17 @@ sendmail_action:
$$->v.ret.stat = SMFIS_DISCARD;
}
;
+maybe_xcode_expr: maybe_expr
+ | xcode
+ {
+ $$ = alloc_node(node_type_string, get_locus());
+ $$->v.literal = $1;
+ }
+ ;
+
+
header_action:
ADD string expr
{
$$ = alloc_node(node_type_header, &$1);
@@ -954,34 +971,76 @@ maybe_triplet: /* empty */
}
| triplet
;
-triplet : CODE
+triplet : code
{
- $$.code = $1;
+ $$.code = alloc_node(node_type_string, get_locus());
+ $$.code->v.literal = $1;
$$.xcode = NULL;
$$.message = NULL;
}
- | CODE XCODE
+ | code xcode
{
- $$.code = $1;
- $$.xcode = $2;
+ $$.code = alloc_node(node_type_string, get_locus());
+ $$.code->v.literal = $1;
+ $$.xcode = alloc_node(node_type_string, get_locus());
+ $$.xcode->v.literal = $2;
$$.message = NULL;
}
- | CODE XCODE expr
+ | code xcode expr
{
- $$.code = $1;
- $$.xcode = $2;
+ $$.code = alloc_node(node_type_string, get_locus());
+ $$.code->v.literal = $1;
+ $$.xcode = alloc_node(node_type_string, get_locus());
+ $$.xcode->v.literal = $2;
$$.message = cast_to(dtype_string, $3);
}
- | CODE expr
+ | code expr
{
- $$.code = $1;
+ $$.code = alloc_node(node_type_string, get_locus());
+ $$.code->v.literal = $1;
$$.xcode = NULL;
$$.message = cast_to(dtype_string, $2);
}
;
+code : NUMBER
+ {
+ char buf[4];
+
+ if ($1 < 200 || $1 > 599) {
+ yyerror(_("Invalid SMTP reply code"));
+ buf[0] = 0;
+ } else
+ snprintf(buf, sizeof(buf), "%lu", $1);
+ $$ = string_alloc(buf, strlen(buf));
+ }
+ ;
+
+xcode : NUMBER '.' NUMBER '.' NUMBER
+ {
+ char buf[sizeof("5.999.999")];
+
+ /* RFC 1893:
+ The syntax of the new status codes is defined as:
+
+ status-code = class "." subject "." detail
+ class = "2"/"4"/"5"
+ subject = 1*3digit
+ detail = 1*3digit
+ */
+ if (($1 != 2 && $1 != 4 && $1 !=5)
+ || $3 > 999 || $5 > 999) {
+ yyerror(_("Invalid extended reply code"));
+ buf[0] = 0;
+ } else
+ snprintf(buf, sizeof(buf), "%lu.%lu.%lu",
+ $1, $3, $5);
+ $$ = string_alloc(buf, strlen(buf));
+ }
+ ;
+
condition : if_cond
| case_cond
| on_cond
;
@@ -1120,9 +1179,9 @@ value : STRING
$$.type = dtype_string;
$$.v.literal = $1;
}
}
- | number
+ | NUMBER
{
$$.type = dtype_number;
$$.v.number = $1;
}
@@ -1163,21 +1222,8 @@ fnmatches : FNMATCHES
$$.qualifier = QUALIFIER_MX;
}
;
-number : NUMBER
- | CODE
- {
- char *p;
- $$ = strtol($1->text, &p, 10);
- if (*p) {
- /* should not happen */
- parse_error(_("Invalid number (near `%s')"), p);
- YYERROR;
- }
- }
- ;
-
/* Loop statements */
loopstmt : LOOP loop_ident opt_loop_parms DO stmtlist DONE opt_while
@@ -1401,8 +1447,15 @@ expr : NOT expr
}
| common_expr
;
+maybe_expr : /* empty */
+ {
+ $$ = NULL;
+ }
+ | expr
+ ;
+
common_expr: simp_expr
| common_expr simp_expr %prec CONCAT
{
$$ = alloc_node(node_type_concat, get_locus());
@@ -1949,15 +2002,15 @@ on_cond : on pollstmt do branches DONE
;
on : ON
{
- onblock(1);
+ tie_in_onblock(1);
}
;
do : DO
{
- onblock(0);
+ tie_in_onblock(0);
}
;
pollstmt : POLL expr
diff --git a/mfd/lex.l b/mfd/lex.l
index 3ceabfce..c1f9c3e8 100644
--- a/mfd/lex.l
+++ b/mfd/lex.l
@@ -317,10 +317,8 @@ vaptr return keyword(VAPTR);
<INITIAL,ONBLOCK,ML,CML,STR>\\{P} {
yylval.number = strtoul(yytext+1, NULL, 0);
return BACKREF; }
/* Numeric strings */
-{N}\.{N}\.{N} { string(yytext, yyleng); return XCODE; }
-[0-9]{3} { string(yytext, yyleng); return CODE; }
0[xX]{X}{X}* { yylval.number = strtoul(yytext, NULL, 16); return NUMBER; };
0{O}{O}* { yylval.number = strtoul(yytext, NULL, 8); return NUMBER; };
0|{P} { yylval.number = strtoul(yytext, NULL, 10); return NUMBER; };
/* Strings */
@@ -790,9 +788,9 @@ isemptystr(char *text)
return *text == 0;
}
void
-onblock(int enable)
+tie_in_onblock(int enable)
{
if (enable)
BEGIN(ONBLOCK);
else
diff --git a/mfd/mailfromd.h b/mfd/mailfromd.h
index ac93cba4..bdf09dcd 100644
--- a/mfd/mailfromd.h
+++ b/mfd/mailfromd.h
@@ -306,11 +306,11 @@ struct un_node { /* A unary operation node */
/* Return action node: accept/reject/tempfail/continue */
struct return_node {
sfsistat stat; /* Return status */
- struct literal *code; /* Code */
- struct literal *xcode; /* Extended code */
- NODE *message; /* Subtree producing the textual message */
+ NODE *code; /* Code */
+ NODE *xcode; /* Extended code */
+ NODE *message; /* Textual message */
};
enum msgmod_opcode { /* Message modification operation */
header_add, /* Add a header */
@@ -696,9 +696,9 @@ void pp_done(void);
int yyparse();
int yylex();
int yyerror(char *s);
void add_include_dir(const char *dir);
-void onblock(int enable);
+void tie_in_onblock(int enable);
int parse_program(char *name, int ydebug);
void parse_pragma(const char *text);
const struct locus *get_locus(void);
const char *msgmod_opcode_str(enum msgmod_opcode opcode);
diff --git a/mfd/opcodes b/mfd/opcodes
index cee68d46..dd883ea3 100644
--- a/mfd/opcodes
+++ b/mfd/opcodes
@@ -89,6 +89,6 @@ RETURN NULL 0
RETCATCH NULL 0
FUNCALL dump_funcall 2
NEXT NULL 0
-RESULT dump_result 3
+RESULT dump_result 1
HEADER dump_header 2
diff --git a/mfd/prog.c b/mfd/prog.c
index 90a426eb..f8e58a92 100644
--- a/mfd/prog.c
+++ b/mfd/prog.c
@@ -1486,11 +1486,11 @@ instr_result(eval_environ_t env)
sfsistat status = (sfsistat) get_immediate(env, 0);
char *code, *xcode;
char *message;
- get_string_arg(env, 0, &message);
- get_literal(env, 1, (const char**)&code);
- get_literal(env, 2, (const char**)&xcode);
+ get_string_arg(env, 2, &message);
+ get_string_arg(env, 1, &xcode);
+ get_string_arg(env, 0, &code);
if (PROG_TRACE_ENGINE)
prog_trace(env, "RESULT %d %s %s %s",
status,
@@ -1512,10 +1512,10 @@ instr_result(eval_environ_t env)
xcode = NULL;
env->status = status;
env->setreply(env->data, code, xcode, message);
- advance_pc(env, 3);
- adjust_stack(env, 1);
+ advance_pc(env, 1);
+ adjust_stack(env, 3);
}
void
dump_result(prog_counter_t i)

Return to:

Send suggestions and report system problems to the System administrator.