summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/vty/command.c39
-rw-r--r--tests/Makefile.am1
-rw-r--r--tests/vty/ok_empty_parent.cfg2
-rw-r--r--tests/vty/vty_test.c1
-rw-r--r--tests/vty/vty_test.ok2
5 files changed, 38 insertions, 7 deletions
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. */
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 8935bf72..b1387174 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -222,6 +222,7 @@ EXTRA_DIST = testsuite.at $(srcdir)/package.m4 $(TESTSUITE) \
vty/fail_tabs_and_spaces.cfg \
vty/fail_too_much_indent.cfg \
vty/ok.cfg \
+ vty/ok_empty_parent.cfg \
vty/ok_ignore_blank.cfg \
vty/ok_ignore_comment.cfg \
vty/ok_indented_root.cfg \
diff --git a/tests/vty/ok_empty_parent.cfg b/tests/vty/ok_empty_parent.cfg
new file mode 100644
index 00000000..fe04fcfa
--- /dev/null
+++ b/tests/vty/ok_empty_parent.cfg
@@ -0,0 +1,2 @@
+line vty
+log stderr
diff --git a/tests/vty/vty_test.c b/tests/vty/vty_test.c
index eba9995c..d9af6aee 100644
--- a/tests/vty/vty_test.c
+++ b/tests/vty/vty_test.c
@@ -342,6 +342,7 @@ int main(int argc, char **argv)
test_exit_by_indent("fail_too_much_indent.cfg", -EINVAL);
test_exit_by_indent("fail_tabs_and_spaces.cfg", -EINVAL);
test_exit_by_indent("ok_indented_root.cfg", 0);
+ test_exit_by_indent("ok_empty_parent.cfg", 0);
/* Leak check */
OSMO_ASSERT(talloc_total_blocks(stats_ctx) == 1);
diff --git a/tests/vty/vty_test.ok b/tests/vty/vty_test.ok
index b2df1a11..f9fea34d 100644
--- a/tests/vty/vty_test.ok
+++ b/tests/vty/vty_test.ok
@@ -128,4 +128,6 @@ reading file fail_tabs_and_spaces.cfg, expecting rc=-22
got rc=-22
reading file ok_indented_root.cfg, expecting rc=0
got rc=0
+reading file ok_empty_parent.cfg, expecting rc=0
+got rc=0
All tests passed