diff options
author | Ondrej Zajicek <santiago@crfreenet.org> | 2013-07-25 13:15:32 +0200 |
---|---|---|
committer | Ondrej Zajicek <santiago@crfreenet.org> | 2013-07-25 13:15:32 +0200 |
commit | 508d936078aecc8fbbb9ca1218104599c4a3cb4a (patch) | |
tree | d84c6b098342fc2f366d960bd90d6a158610ea48 | |
parent | a0b176e3b2b50d3a30574afa927e0ee8ef65be68 (diff) |
Implements eval command and minor CLI cleanups.
Implemented eval command can be used to evaluate expressions.
The patch also documents echo command and allows to use log classes
instead of integer as a mask for echo.
-rw-r--r-- | doc/bird.sgml | 16 | ||||
-rw-r--r-- | doc/reply_codes | 2 | ||||
-rw-r--r-- | filter/filter.c | 32 | ||||
-rw-r--r-- | filter/filter.h | 3 | ||||
-rw-r--r-- | nest/cmds.c | 20 | ||||
-rw-r--r-- | nest/cmds.h | 3 | ||||
-rw-r--r-- | nest/config.Y | 8 | ||||
-rw-r--r-- | sysdep/unix/log.c | 2 |
8 files changed, 70 insertions, 16 deletions
diff --git a/doc/bird.sgml b/doc/bird.sgml index 27f8b869..a1d3dc2c 100644 --- a/doc/bird.sgml +++ b/doc/bird.sgml @@ -282,7 +282,7 @@ protocol rip { <tag>include "<m/filename/"</tag> This statement causes inclusion of a new file. The maximal depth is set to 5. - <tag>log "<m/filename/"|syslog [name <m/name/]|stderr all|{ <m/list of classes/ }</tag> + <tag><label id="dsc-log">log "<m/filename/"|syslog [name <m/name/]|stderr all|{ <m/list of classes/ }</tag> Set logging of messages having the given class (either <cf/all/ or <cf/{ error, trace }/ etc.) into selected destination (a file specified as a filename string, syslog with optional name argument, or the stderr output). Classes are: @@ -651,9 +651,6 @@ This argument can be omitted if there exists only a single instance. <p>Here is a brief list of supported functions: <descrip> - <tag>dump resources|sockets|interfaces|neighbors|attributes|routes|protocols</tag> - Dump contents of internal data structures to the debugging output. - <tag>show status</tag> Show router status, that is BIRD version, uptime and time from last reconfiguration. @@ -812,6 +809,17 @@ This argument can be omitted if there exists only a single instance. <tag>debug <m/protocol/|<m/pattern/|all all|off|{ states | routes | filters | events | packets }</tag> Control protocol debugging. + + <tag>dump resources|sockets|interfaces|neighbors|attributes|routes|protocols</tag> + Dump contents of internal data structures to the debugging output. + + <tag>echo all|off|{ <m/list of log classes/ } [ <m/buffer-size/ ]</tag> + Control echoing of log messages to the command-line output. + See <ref id="dsc-log" name="log option"> for a list of log classes. + + <tag>eval <m/expr/</tag> + Evaluate given expression. + </descrip> <chapt>Filters diff --git a/doc/reply_codes b/doc/reply_codes index 58807241..e9996eef 100644 --- a/doc/reply_codes +++ b/doc/reply_codes @@ -31,6 +31,7 @@ Reply codes of BIRD command-line interface 0020 Configuration OK 0021 Undo requested 0022 Undo scheduled +0023 Evaluation of expression 1000 BIRD version 1001 Interface list @@ -61,6 +62,7 @@ Reply codes of BIRD command-line interface 8005 Protocol is down => cannot dump 8006 Reload failed 8007 Access denied +8008 Evaluation runtime error 9000 Command too long 9001 Parse error diff --git a/filter/filter.c b/filter/filter.c index 432fa122..d784c253 100644 --- a/filter/filter.c +++ b/filter/filter.c @@ -440,8 +440,6 @@ val_in_range(struct f_val v1, struct f_val v2) return CMP_ERROR; } -static void val_print(struct f_val v); - static void tree_node_print(struct f_tree *t, char **sep) { @@ -474,7 +472,7 @@ tree_print(struct f_tree *t) /* * val_print - format filter value */ -static void +void val_print(struct f_val v) { char buf2[1024]; @@ -558,6 +556,8 @@ static struct rate_limit rl_runtime_err; #define TWOARGS_C TWOARGS \ if (v1.type != v2.type) \ runtime( "Can't operate with values of incompatible types" ); +#define ACCESS_RTE \ + do { if (!f_rte) runtime("No route to access"); } while (0) /** * interpret @@ -821,6 +821,7 @@ interpret(struct f_inst *what) break; case 'a': /* rta access */ { + ACCESS_RTE; struct rta *rta = (*f_rte)->attrs; res.type = what->aux; switch(res.type) { @@ -845,6 +846,7 @@ interpret(struct f_inst *what) } break; case P('a','S'): + ACCESS_RTE; ONEARG; if (what->aux != v1.type) runtime( "Attempt to set static attribute to incompatible type" ); @@ -877,6 +879,7 @@ interpret(struct f_inst *what) } break; case P('e','a'): /* Access to extended attributes */ + ACCESS_RTE; { eattr *e = NULL; if (!(f_flags & FF_FORCE_TMPATTR)) @@ -944,6 +947,7 @@ interpret(struct f_inst *what) } break; case P('e','S'): + ACCESS_RTE; ONEARG; { struct ea_list *l = lp_alloc(f_pool, sizeof(struct ea_list) + sizeof(eattr)); @@ -1021,10 +1025,12 @@ interpret(struct f_inst *what) } break; case 'P': + ACCESS_RTE; res.type = T_INT; res.val.i = (*f_rte)->pref; break; case P('P','S'): + ACCESS_RTE; ONEARG; if (v1.type != T_INT) runtime( "Can't set preference to non-integer" ); @@ -1246,6 +1252,7 @@ interpret(struct f_inst *what) } else { + ACCESS_RTE; v1.val.px.ip = (*f_rte)->net->n.prefix; v1.val.px.len = (*f_rte)->net->n.pxlen; @@ -1478,22 +1485,27 @@ f_run(struct filter *filter, struct rte **rte, struct ea_list **tmp_attrs, struc return res.val.i; } -int -f_eval_int(struct f_inst *expr) +struct f_val +f_eval(struct f_inst *expr, struct linpool *tmp_pool) { - /* Called independently in parse-time to eval expressions */ - struct f_val res; - f_flags = 0; f_tmp_attrs = NULL; f_rte = NULL; - f_pool = cfg_mem; + f_pool = tmp_pool; log_reset(); - res = interpret(expr); + return interpret(expr); +} + +int +f_eval_int(struct f_inst *expr) +{ + /* Called independently in parse-time to eval expressions */ + struct f_val res = f_eval(expr, cfg_mem); if (res.type != T_INT) cf_error("Integer expression expected"); + return res.val.i; } diff --git a/filter/filter.h b/filter/filter.h index 2386fc95..1d5150e7 100644 --- a/filter/filter.h +++ b/filter/filter.h @@ -106,6 +106,7 @@ struct ea_list; struct rte; int f_run(struct filter *filter, struct rte **rte, struct ea_list **tmp_attrs, struct linpool *tmp_pool, int flags); +struct f_val f_eval(struct f_inst *expr, struct linpool *tmp_pool); int f_eval_int(struct f_inst *expr); u32 f_eval_asn(struct f_inst *expr); @@ -117,6 +118,8 @@ int i_same(struct f_inst *f1, struct f_inst *f2); int val_compare(struct f_val v1, struct f_val v2); int tree_compare(const void *p1, const void *p2); +void val_print(struct f_val v); + #define F_NOP 0 #define F_NONL 1 #define F_ACCEPT 2 /* Need to preserve ordering: accepts < rejects! */ diff --git a/nest/cmds.c b/nest/cmds.c index 54ace169..9bdd66cd 100644 --- a/nest/cmds.c +++ b/nest/cmds.c @@ -13,6 +13,7 @@ #include "nest/cmds.h" #include "lib/string.h" #include "lib/resource.h" +#include "filter/filter.h" extern int shutting_down; extern int configuring; @@ -90,3 +91,22 @@ cmd_show_memory(void) print_size("Total:", rmemsize(&root_pool)); cli_msg(0, ""); } + +extern const char *log_buffer_ptr; + +void +cmd_eval(struct f_inst *expr) +{ + struct f_val v = f_eval(expr, this_cli->parser_pool); + log_reset(); + + if (v.type == T_RETURN) + { + cli_msg(8008, "runtime error"); + return; + } + + val_print(v); + cli_msg(23, "%s", log_buffer_ptr); + log_reset(); +} diff --git a/nest/cmds.h b/nest/cmds.h index 8b0bff7e..4cf8fb1b 100644 --- a/nest/cmds.h +++ b/nest/cmds.h @@ -11,6 +11,9 @@ struct sym_show_data { struct symbol *sym; }; +struct f_inst; + void cmd_show_status(void); void cmd_show_symbols(struct sym_show_data *sym); void cmd_show_memory(void); +void cmd_eval(struct f_inst *expr); diff --git a/nest/config.Y b/nest/config.Y index b85a5733..a6f13808 100644 --- a/nest/config.Y +++ b/nest/config.Y @@ -612,7 +612,11 @@ CF_CLI(DUMP ROUTES,,, [[Dump routing table]]) CF_CLI(DUMP PROTOCOLS,,, [[Dump protocol information]]) { protos_dump_all(); cli_msg(0, ""); } ; -CF_CLI(ECHO, echo_mask echo_size, [all | off | <mask>] [<buffer-size>], [[Configure echoing of log messages]]) { +CF_CLI(EVAL, term, <expr>, [[Evaluate an expression]]) +{ cmd_eval($2); } ; + +CF_CLI_HELP(ECHO, ..., [[Control echoing of log messages]]) +CF_CLI(ECHO, echo_mask echo_size, (all | off | { debug | trace | info | remote | warning | error | auth }) [<buffer-size>], [[Control echoing of log messages]]) { cli_set_log_echo(this_cli, $2, $3); cli_msg(0, ""); } ; @@ -620,7 +624,7 @@ CF_CLI(ECHO, echo_mask echo_size, [all | off | <mask>] [<buffer-size>], [[Config echo_mask: ALL { $$ = ~0; } | OFF { $$ = 0; } - | NUM + | '{' log_mask_list '}' { $$ = $2; } ; echo_size: diff --git a/sysdep/unix/log.c b/sysdep/unix/log.c index 92f12f1e..f3a66f8b 100644 --- a/sysdep/unix/log.c +++ b/sysdep/unix/log.c @@ -70,6 +70,8 @@ static char log_buffer[LOG_BUFFER_SIZE]; static char *log_buffer_pos; static int log_buffer_remains; +const char *log_buffer_ptr = log_buffer; + /** * log_reset - reset the log buffer |