summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorNeels Hofmeyr <neels@hofmeyr.de>2017-09-19 23:54:01 +0200
committerNeels Hofmeyr <neels@hofmeyr.de>2017-09-20 00:57:33 +0200
commit430636328c2fbd9fffc0eac5114462c200b7f2cb (patch)
tree9fbbecedf50ee4ff28e994855fb7cbf077a11319 /src
parent4a31ffa2f0097d96201f80305a0495c57552f0ad (diff)
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
Diffstat (limited to 'src')
-rw-r--r--src/vty/command.c39
1 files changed, 32 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. */