From 99fc209e6a465ccb6ea96ef81116e8d931e2261c Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Tue, 14 May 2013 19:49:13 +0200 Subject: cli: complete basic functionality of the interactive mode This patch adds missing code to get basic interactive mode operative via `nft -i', including parsing, evaluation, command execution via netlink and error reporting. Autocomplete is not yet implemented. Signed-off-by: Pablo Neira Ayuso --- src/cli.c | 12 ++++++----- src/main.c | 71 +++++++++++++++++++++++++++++++++++--------------------------- src/rule.c | 25 ++++++++++++++++------ 3 files changed, 66 insertions(+), 42 deletions(-) (limited to 'src') diff --git a/src/cli.c b/src/cli.c index e302dfa8..a5a891e2 100644 --- a/src/cli.c +++ b/src/cli.c @@ -32,6 +32,7 @@ static const struct input_descriptor indesc_cli = { .type = INDESC_CLI, + .name = "", }; static struct parser_state *state; @@ -86,6 +87,7 @@ static void cli_complete(char *line) { const HIST_ENTRY *hist; const char *c; + LIST_HEAD(msgs); line = cli_append_multiline(line); if (line == NULL) @@ -102,10 +104,10 @@ static void cli_complete(char *line) if (hist == NULL || strcmp(hist->line, line)) add_history(line); + parser_init(state, &msgs); scanner_push_buffer(scanner, &indesc_cli, line); - nft_parse(scanner, state); - - erec_print_list(stdout, state->msgs); + nft_run(scanner, state, &msgs); + erec_print_list(stdout, &msgs); xfree(line); } @@ -140,7 +142,7 @@ void __fmtstring(1, 0) cli_display(const char *fmt, va_list ap) rl_forced_update_display(); } -int cli_init(void *_scanner, struct parser_state *_state) +int cli_init(struct parser_state *_state) { const char *home; @@ -159,8 +161,8 @@ int cli_init(void *_scanner, struct parser_state *_state) read_history(histfile); history_set_pos(history_length); - scanner = _scanner; state = _state; + scanner = scanner_init(state); while (!eof) rl_callback_read_char(); diff --git a/src/main.c b/src/main.c index ab2ceab9..283ec289 100644 --- a/src/main.c +++ b/src/main.c @@ -141,17 +141,48 @@ static const struct input_descriptor indesc_cmdline = { .name = "", }; +int nft_run(void *scanner, struct parser_state *state, struct list_head *msgs) +{ + struct eval_ctx ctx; + int ret; + + ret = nft_parse(scanner, state); + if (ret != 0) + return -1; + + memset(&ctx, 0, sizeof(ctx)); + ctx.msgs = msgs; + if (evaluate(&ctx, &state->cmds) < 0) + return -1; + + { + struct netlink_ctx ctx; + struct cmd *cmd, *next; + + list_for_each_entry_safe(cmd, next, &state->cmds, list) { + memset(&ctx, 0, sizeof(ctx)); + ctx.msgs = msgs; + init_list_head(&ctx.list); + ret = do_command(&ctx, cmd); + list_del(&cmd->list); + cmd_free(cmd); + if (ret < 0) + return ret; + } + } + + return 0; +} + int main(int argc, char * const *argv) { struct parser_state state; - struct eval_ctx ctx; void *scanner; LIST_HEAD(msgs); char *buf = NULL, *filename = NULL; unsigned int len; bool interactive = false; int i, val; - int ret; while (1) { val = getopt_long(argc, argv, OPTSTRING, options, NULL); @@ -218,9 +249,6 @@ int main(int argc, char * const *argv) } } - parser_init(&state, &msgs); - scanner = scanner_init(&state); - if (optind != argc) { for (len = 0, i = optind; i < argc; i++) len += strlen(argv[i]) + strlen(" "); @@ -231,44 +259,25 @@ int main(int argc, char * const *argv) if (i + 1 < argc) strcat(buf, " "); } - + parser_init(&state, &msgs); + scanner = scanner_init(&state); scanner_push_buffer(scanner, &indesc_cmdline, buf); } else if (filename != NULL) { + parser_init(&state, &msgs); + scanner = scanner_init(&state); if (scanner_read_file(scanner, filename, &internal_location) < 0) goto out; } else if (interactive) { - cli_init(scanner, &state); + cli_init(&state); + return 0; } else { fprintf(stderr, "%s: no command specified\n", argv[0]); exit(NFT_EXIT_FAILURE); } - ret = nft_parse(scanner, &state); - if (ret != 0) - goto out; - - memset(&ctx, 0, sizeof(ctx)); - ctx.msgs = &msgs; - if (evaluate(&ctx, &state.cmds) < 0) - goto out; - - { - struct netlink_ctx ctx; - struct cmd *cmd, *next; - - list_for_each_entry_safe(cmd, next, &state.cmds, list) { - memset(&ctx, 0, sizeof(ctx)); - ctx.msgs = &msgs; - init_list_head(&ctx.list); - if (do_command(&ctx, cmd) < 0) - goto out; - list_del(&cmd->list); - cmd_free(cmd); - } - } + nft_run(scanner, &state, &msgs); out: scanner_destroy(scanner); - scope_release(&state.top_scope); erec_print_list(stdout, &msgs); xfree(buf); diff --git a/src/rule.c b/src/rule.c index 89c3607c..9d9eaee3 100644 --- a/src/rule.c +++ b/src/rule.c @@ -142,7 +142,6 @@ void rule_print(const struct rule *rule) struct scope *scope_init(struct scope *scope, const struct scope *parent) { scope->parent = parent; - init_list_head(&scope->symbols); return scope; } @@ -189,6 +188,7 @@ struct chain *chain_alloc(const char *name) chain = xzalloc(sizeof(*chain)); init_list_head(&chain->rules); + init_list_head(&chain->scope.symbols); if (name != NULL) chain->handle.chain = xstrdup(name); return chain; @@ -240,6 +240,7 @@ struct table *table_alloc(void) table = xzalloc(sizeof(*table)); init_list_head(&table->chains); init_list_head(&table->sets); + init_list_head(&table->scope.symbols); return table; } @@ -472,14 +473,20 @@ static int do_list_sets(struct netlink_ctx *ctx, const struct location *loc, static int do_command_list(struct netlink_ctx *ctx, struct cmd *cmd) { - struct table *table; - struct chain *chain; + struct table *table = NULL; + struct chain *chain, *nchain; struct rule *rule, *nrule; struct set *set, *nset; - table = table_alloc(); - handle_merge(&table->handle, &cmd->handle); - table_add_hash(table); + /* No need to allocate the table object when listing all tables */ + if (cmd->handle.table != NULL) { + table = table_lookup(&cmd->handle); + if (table == NULL) { + table = table_alloc(); + handle_merge(&table->handle, &cmd->handle); + table_add_hash(table); + } + } switch (cmd->obj) { case CMD_OBJ_TABLE: @@ -546,6 +553,12 @@ static int do_command_list(struct netlink_ctx *ctx, struct cmd *cmd) } table_print(table); + + list_for_each_entry_safe(chain, nchain, &table->chains, list) { + list_del(&chain->list); + chain_free(chain); + } + return 0; } -- cgit v1.2.3