lib: Clean up completions code, fix segfault on no match

Signed-off-by: Quentin Young <qlyoung@cumulusnetworks.com>
This commit is contained in:
Quentin Young 2016-10-03 23:21:11 +00:00
parent 73baf6a3a6
commit 268316d185

View File

@ -597,46 +597,24 @@ cmd_describe_command (vector vline, struct vty *vty, int *status)
char ** char **
cmd_complete_command_lib (vector vline, struct vty *vty, int *status, int islib) cmd_complete_command_lib (vector vline, struct vty *vty, int *status, int islib)
{ {
char **ret; char **ret = NULL;
int original_node = vty->node;
vector input_line = vector_init (vector_count (vline));
if ( cmd_try_do_shortcut(vty->node, vector_slot(vline, 0) ) ) // if the first token is 'do' we'll want to execute the command in the enable node
int do_shortcut = cmd_try_do_shortcut (vty->node, vector_slot (vline, 0));
vty->node = do_shortcut ? ENABLE_NODE : original_node;
// construct the input line we'll be matching on
unsigned int offset = (do_shortcut) ? 1 : 0;
for (unsigned index = 0; index + offset < vector_active (vline); index++)
vector_set_index (input_line, index + offset, vector_lookup (vline, index));
// get token completions -- this is a copying operation
vector comps = cmd_complete_command_real (input_line, vty, status);
if (!MATCHER_ERROR (*status))
{ {
enum node_type onode; // copy completions text into an array of char*
vector shifted_vline;
unsigned int index;
onode = vty->node;
vty->node = ENABLE_NODE;
/* We can try it on enable node, cos' the vty is authenticated */
shifted_vline = vector_init (vector_count(vline));
/* use memcpy? */
for (index = 1; index < vector_active (vline); index++)
{
vector_set_index (shifted_vline, index-1, vector_lookup(vline, index));
}
// get token completions
vector comps = cmd_complete_command_real (shifted_vline, vty, status);
ret = XMALLOC (MTYPE_TMP, vector_active (comps) * sizeof (char *) + 1);
unsigned int i;
for (i = 0; i < vector_active (comps); i++)
{
struct cmd_token *token = vector_slot (comps, i);
ret[i] = XSTRDUP (MTYPE_TMP, token->text);
vector_unset (comps, i);
del_cmd_token (token);
}
vector_free (comps);
ret[i] = NULL;
vector_free(shifted_vline);
vty->node = onode;
return ret;
}
// get token completions
vector comps = cmd_complete_command_real (vline, vty, status);
ret = XMALLOC (MTYPE_TMP, vector_active (comps) * sizeof (char *) + 1); ret = XMALLOC (MTYPE_TMP, vector_active (comps) * sizeof (char *) + 1);
unsigned int i; unsigned int i;
for (i = 0; i < vector_active (comps); i++) for (i = 0; i < vector_active (comps); i++)
@ -646,8 +624,20 @@ cmd_complete_command_lib (vector vline, struct vty *vty, int *status, int islib)
vector_unset (comps, i); vector_unset (comps, i);
del_cmd_token (token); del_cmd_token (token);
} }
// set the last element to NULL, which vty/vtysh uses as a sentinel value
ret[i] = NULL; ret[i] = NULL;
vector_free (comps); vector_free (comps);
comps = NULL;
}
// comps should always be null here
assert (!comps);
// free the adjusted input line
vector_free (input_line);
// reset vty->node to its original value
vty->node = original_node;
return ret; return ret;
} }