diff options
author | Damjan Marion <damarion@cisco.com> | 2022-05-08 20:48:37 +0200 |
---|---|---|
committer | Dave Wallace <dwallacelf@gmail.com> | 2022-05-13 16:58:03 +0000 |
commit | c50bcbd6c28f2fd87f87b86bd5b215892daf46a6 (patch) | |
tree | 33144a097d64ff018972a73692ccc4f86b93a20a | |
parent | c0a08cadee9161554246f707eaf24f782086914d (diff) |
vlib: process startup config exec scripts line by line
This fixes long standing annoyance that CLIs with optional args cannot
be executed from file, as they cannot distinguish between valid optional
args and next line in the file.
Multiline statements can be provided simply by using backslash before \n.
Also comments are supported - everything after # is ignored up to the
end of the line.
Example:
# multiline cli using backslash
show version \
verbose # end of line comment
packet-generator new { \
name x \
limit 5 \
# comment inside cmultiline cli \
size 128-128 \
interface local0 \
node null-node \
data { \
incrementing 30 \
} \
}
Type: fix
Change-Id: Ia6d588169bae14e6e3f18effe94820d05ace1dbf
Signed-off-by: Damjan Marion <damarion@cisco.com>
-rw-r--r-- | src/vlib/cli.c | 58 | ||||
-rw-r--r-- | src/vlib/cli.h | 1 | ||||
-rw-r--r-- | src/vlib/unix/main.c | 14 | ||||
-rw-r--r-- | src/vnet/ipsec/ipsec_cli.c | 2 |
4 files changed, 73 insertions, 2 deletions
diff --git a/src/vlib/cli.c b/src/vlib/cli.c index 01409b8b677..80da2d59992 100644 --- a/src/vlib/cli.c +++ b/src/vlib/cli.c @@ -199,6 +199,64 @@ unformat_vlib_cli_args (unformat_input_t *i, va_list *va) return 1; } +uword +unformat_vlib_cli_line (unformat_input_t *i, va_list *va) +{ + unformat_input_t *result = va_arg (*va, unformat_input_t *); + u8 *line = 0; + uword c; + int skip; + +next_line: + skip = 0; + + /* skip leading whitespace if any */ + unformat_skip_white_space (i); + + if (unformat_is_eof (i)) + return 0; + + while ((c = unformat_get_input (i)) != UNFORMAT_END_OF_INPUT) + { + if (c == '\\') + { + c = unformat_get_input (i); + + if (c == '\n') + { + if (!skip) + vec_add1 (line, '\n'); + skip = 0; + continue; + } + + if (!skip) + vec_add1 (line, '\\'); + + if (c == UNFORMAT_END_OF_INPUT) + break; + + if (!skip) + vec_add1 (line, c); + continue; + } + + if (c == '#') + skip = 1; + else if (c == '\n') + break; + + if (!skip) + vec_add1 (line, c); + } + + if (line == 0) + goto next_line; + + unformat_init_vector (result, line); + return 1; +} + /* Looks for string based sub-input formatted { SUB-INPUT }. */ uword unformat_vlib_cli_sub_input (unformat_input_t * i, va_list * args) diff --git a/src/vlib/cli.h b/src/vlib/cli.h index 32e46f9e0da..86913e9708c 100644 --- a/src/vlib/cli.h +++ b/src/vlib/cli.h @@ -205,6 +205,7 @@ clib_error_t *vlib_cli_register_parse_rule (struct vlib_main_t *vm, vlib_cli_parse_rule_t * c); uword unformat_vlib_cli_args (unformat_input_t *i, va_list *va); +unformat_function_t unformat_vlib_cli_line; uword unformat_vlib_cli_sub_input (unformat_input_t * i, va_list * args); /* Return an vector of strings consisting of possible auto-completions diff --git a/src/vlib/unix/main.c b/src/vlib/unix/main.c index 3710d8e8b68..fd8a7e863a1 100644 --- a/src/vlib/unix/main.c +++ b/src/vlib/unix/main.c @@ -347,8 +347,20 @@ startup_config_process (vlib_main_t * vm, if (vec_len (buf)) { + unformat_input_t in; unformat_init_vector (&sub_input, buf); - vlib_cli_input (vm, &sub_input, 0, 0); + + while (unformat_user (&sub_input, unformat_vlib_cli_line, &in)) + { + if (vlib_cli_input (vm, &in, 0, 0) != 0) + { + /* cli failed - stop */ + unformat_free (&in); + break; + } + unformat_free (&in); + } + /* frees buf for us */ unformat_free (&sub_input); } diff --git a/src/vnet/ipsec/ipsec_cli.c b/src/vnet/ipsec/ipsec_cli.c index e1263037c6c..df8f9378111 100644 --- a/src/vnet/ipsec/ipsec_cli.c +++ b/src/vnet/ipsec/ipsec_cli.c @@ -143,7 +143,7 @@ ipsec_sa_add_del_command_fn (vlib_main_t * vm, else if (unformat (line_input, "integ-alg %U", unformat_ipsec_integ_alg, &integ_alg)) ; - else if (unformat (line_input, " %U", unformat_tunnel, &tun)) + else if (unformat (line_input, "%U", unformat_tunnel, &tun)) { flags |= IPSEC_SA_FLAG_IS_TUNNEL; if (AF_IP6 == tunnel_get_af (&tun)) |