diff options
Diffstat (limited to 'mfd')
-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 |
6 files changed, 182 insertions, 88 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; - - 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); - } + NODE *code, *xcode; + + code = node->v.ret.code; + xcode = node->v.ret.xcode; + 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)); @@ -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 @@ -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 @@ -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) |