diff options
| author | Neels Hofmeyr <neels@hofmeyr.de> | 2017-09-19 23:54:01 +0200 | 
|---|---|---|
| committer | Neels Hofmeyr <neels@hofmeyr.de> | 2017-09-20 00:57:33 +0200 | 
| commit | 430636328c2fbd9fffc0eac5114462c200b7f2cb (patch) | |
| tree | 9fbbecedf50ee4ff28e994855fb7cbf077a11319 /src | |
| parent | 4a31ffa2f0097d96201f80305a0495c57552f0ad (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.c | 39 | 
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. */  | 
