From 430636328c2fbd9fffc0eac5114462c200b7f2cb Mon Sep 17 00:00:00 2001 From: Neels Hofmeyr Date: Tue, 19 Sep 2017 23:54:01 +0200 Subject: fix vty regression: empty parent node The recent exit-by-indent patch breaks a VTY case where a node is entered but directly followed by a sibling or ancestor without listing any child nodes. Regression introduced by I24cbb3f6de111f2d31110c3c484c066f1153aac9. An example is a common usage in osmo-bts, where 'phy N' / 'instance N' is a parent node that is commonly left empty: phy 0 instance 0 bts 0 band 1800 Before this patch, this case produces the error: There is no such command. Error occurred during reading the below line: bts 0 Fix indentation parsing logic in command.c to accomodate this case. Add a unit test for empty parent node. Change-Id: Ia0880a17ae55accb092ae8585cc3a1bec9986891 --- src/vty/command.c | 39 ++++++++++++++++++++++++++++++++------- 1 file changed, 32 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/vty/command.c b/src/vty/command.c index a65b4de5..46c9fa28 100644 --- a/src/vty/command.c +++ b/src/vty/command.c @@ -2374,14 +2374,39 @@ int config_from_file(struct vty *vty, FILE * fp) continue; } - /* We have a nonempty line. This might be the first on a deeper indenting level, so let's - * remember this indent if we don't have one yet. */ - if (!vty->indent) - vty->indent = talloc_strdup(vty, indent); + /* We have a nonempty line. */ + if (!vty->indent) { + /* We have just entered a node and expecting the first child to come up; but we + * may also skip right back to a parent or ancestor level. */ + parent = vty_parent(vty); - cmp = indent_cmp(indent, vty->indent); - if (cmp == EINVAL) - goto return_invalid_indent; + /* If there is no parent, record any indentation we encounter. */ + cmp = parent ? indent_cmp(indent, parent->indent) : 1; + + if (cmp == EINVAL) + goto return_invalid_indent; + + if (cmp <= 0) { + /* We have gone right back to the parent level or higher, we are skipping + * this child node level entirely. Pop the parent to go back to a node + * that was actually there (to reinstate vty->indent) and re-use below + * go-parent while-loop to find an accurate match of indent in the node + * ancestry. */ + vty_go_parent(vty); + } else { + /* The indent is deeper than the just entered parent, record the new + * indentation characters. */ + vty->indent = talloc_strdup(vty, indent); + /* This *is* the new indentation. */ + cmp = 0; + } + } else { + /* There is a known indentation for this node level, validate and detect node + * exits. */ + cmp = indent_cmp(indent, vty->indent); + if (cmp == EINVAL) + goto return_invalid_indent; + } /* Less indent: go up the parent nodes to find matching amount of less indent. When this * loop exits, we want to have found an exact match, i.e. cmp == 0. */ -- cgit v1.2.3