summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOndrej Zajicek <santiago@crfreenet.org>2013-07-25 13:15:32 +0200
committerOndrej Zajicek <santiago@crfreenet.org>2013-07-25 13:15:32 +0200
commit508d936078aecc8fbbb9ca1218104599c4a3cb4a (patch)
treed84c6b098342fc2f366d960bd90d6a158610ea48
parenta0b176e3b2b50d3a30574afa927e0ee8ef65be68 (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.sgml16
-rw-r--r--doc/reply_codes2
-rw-r--r--filter/filter.c32
-rw-r--r--filter/filter.h3
-rw-r--r--nest/cmds.c20
-rw-r--r--nest/cmds.h3
-rw-r--r--nest/config.Y8
-rw-r--r--sysdep/unix/log.c2
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