mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-09 19:13:58 +00:00
vtysh: autocomplete variables
This asks the connected daemons for their variable completions through a hidden CLI command. Signed-off-by: David Lamparter <equinox@opensourcerouting.org>
This commit is contained in:
parent
70d44c5cd4
commit
7f059ea614
@ -727,6 +727,38 @@ cmd_variable_handler_register (const struct cmd_variable_handler *cvh)
|
|||||||
listnode_add(varhandlers, (void *)cvh);
|
listnode_add(varhandlers, (void *)cvh);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DEFUN_HIDDEN (autocomplete,
|
||||||
|
autocomplete_cmd,
|
||||||
|
"autocomplete TYPE TEXT VARNAME",
|
||||||
|
"Autocompletion handler (internal, for vtysh)\n"
|
||||||
|
"cmd_token->type\n"
|
||||||
|
"cmd_token->text\n"
|
||||||
|
"cmd_token->varname\n")
|
||||||
|
{
|
||||||
|
struct cmd_token tok;
|
||||||
|
vector comps = vector_init(32);
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
memset(&tok, 0, sizeof(tok));
|
||||||
|
tok.type = atoi(argv[1]->arg);
|
||||||
|
tok.text = argv[2]->arg;
|
||||||
|
tok.varname = argv[3]->arg;
|
||||||
|
if (!strcmp(tok.varname, "-"))
|
||||||
|
tok.varname = NULL;
|
||||||
|
|
||||||
|
cmd_variable_complete(&tok, NULL, comps);
|
||||||
|
|
||||||
|
for (i = 0; i < vector_active(comps); i++)
|
||||||
|
{
|
||||||
|
char *text = vector_slot(comps, i);
|
||||||
|
vty_out(vty, "%s\n", text);
|
||||||
|
XFREE(MTYPE_COMPLETION, text);
|
||||||
|
}
|
||||||
|
|
||||||
|
vector_free(comps);
|
||||||
|
return CMD_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generate possible tab-completions for the given input. This function only
|
* Generate possible tab-completions for the given input. This function only
|
||||||
* returns results that would result in a valid command if used as Readline
|
* returns results that would result in a valid command if used as Readline
|
||||||
@ -2434,6 +2466,8 @@ install_default (enum node_type node)
|
|||||||
|
|
||||||
install_element (node, &config_write_cmd);
|
install_element (node, &config_write_cmd);
|
||||||
install_element (node, &show_running_config_cmd);
|
install_element (node, &show_running_config_cmd);
|
||||||
|
|
||||||
|
install_element (node, &autocomplete_cmd);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Initialize command interface. Install basic nodes and commands.
|
/* Initialize command interface. Install basic nodes and commands.
|
||||||
@ -2483,6 +2517,7 @@ cmd_init (int terminal)
|
|||||||
install_element (VIEW_NODE, &show_logging_cmd);
|
install_element (VIEW_NODE, &show_logging_cmd);
|
||||||
install_element (VIEW_NODE, &show_commandtree_cmd);
|
install_element (VIEW_NODE, &show_commandtree_cmd);
|
||||||
install_element (VIEW_NODE, &echo_cmd);
|
install_element (VIEW_NODE, &echo_cmd);
|
||||||
|
install_element (VIEW_NODE, &autocomplete_cmd);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (terminal)
|
if (terminal)
|
||||||
|
@ -107,12 +107,9 @@ begins_with(const char *str, const char *prefix)
|
|||||||
return strncmp(str, prefix, lenprefix) == 0;
|
return strncmp(str, prefix, lenprefix) == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* NB: multiplexed function:
|
|
||||||
* if fp == NULL, this calls vtysh_config_parse_line
|
|
||||||
* if fp != NULL, this prints lines to fp
|
|
||||||
*/
|
|
||||||
static int
|
static int
|
||||||
vtysh_client_run (struct vtysh_client *vclient, const char *line, FILE *fp)
|
vtysh_client_run (struct vtysh_client *vclient, const char *line, FILE *fp,
|
||||||
|
void (*callback)(void *, const char *), void *cbarg)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
char stackbuf[4096];
|
char stackbuf[4096];
|
||||||
@ -178,8 +175,8 @@ vtysh_client_run (struct vtysh_client *vclient, const char *line, FILE *fp)
|
|||||||
fputs (buf, fp);
|
fputs (buf, fp);
|
||||||
fputc ('\n', fp);
|
fputc ('\n', fp);
|
||||||
}
|
}
|
||||||
else
|
if (callback)
|
||||||
vtysh_config_parse_line (buf);
|
callback(cbarg, buf);
|
||||||
|
|
||||||
if (eol == end)
|
if (eol == end)
|
||||||
/* \n\0\0\0 */
|
/* \n\0\0\0 */
|
||||||
@ -223,14 +220,15 @@ out:
|
|||||||
|
|
||||||
static int
|
static int
|
||||||
vtysh_client_run_all (struct vtysh_client *head_client, const char *line,
|
vtysh_client_run_all (struct vtysh_client *head_client, const char *line,
|
||||||
int continue_on_err, FILE *fp)
|
int continue_on_err, FILE *fp,
|
||||||
|
void (*callback)(void *, const char *), void *cbarg)
|
||||||
{
|
{
|
||||||
struct vtysh_client *client;
|
struct vtysh_client *client;
|
||||||
int rc, rc_all = CMD_SUCCESS;
|
int rc, rc_all = CMD_SUCCESS;
|
||||||
|
|
||||||
for (client = head_client; client; client = client->next)
|
for (client = head_client; client; client = client->next)
|
||||||
{
|
{
|
||||||
rc = vtysh_client_run(client, line, fp);
|
rc = vtysh_client_run(client, line, fp, callback, cbarg);
|
||||||
if (rc != CMD_SUCCESS)
|
if (rc != CMD_SUCCESS)
|
||||||
{
|
{
|
||||||
if (!continue_on_err)
|
if (!continue_on_err)
|
||||||
@ -245,13 +243,13 @@ static int
|
|||||||
vtysh_client_execute (struct vtysh_client *head_client, const char *line,
|
vtysh_client_execute (struct vtysh_client *head_client, const char *line,
|
||||||
FILE *fp)
|
FILE *fp)
|
||||||
{
|
{
|
||||||
return vtysh_client_run_all (head_client, line, 0, fp);
|
return vtysh_client_run_all (head_client, line, 0, fp, NULL, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
vtysh_client_config (struct vtysh_client *head_client, char *line)
|
vtysh_client_config (struct vtysh_client *head_client, char *line)
|
||||||
{
|
{
|
||||||
vtysh_client_run_all (head_client, line, 1, NULL);
|
vtysh_client_run_all (head_client, line, 1, NULL, vtysh_config_parse_line, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -796,6 +794,27 @@ vtysh_rl_describe (void)
|
|||||||
width,
|
width,
|
||||||
token->text,
|
token->text,
|
||||||
token->desc);
|
token->desc);
|
||||||
|
|
||||||
|
if (IS_VARYING_TOKEN(token->type))
|
||||||
|
{
|
||||||
|
const char *ref = vector_slot(vline, vector_active(vline) - 1);
|
||||||
|
|
||||||
|
vector varcomps = vector_init (VECTOR_MIN_SIZE);
|
||||||
|
cmd_variable_complete (token, ref, varcomps);
|
||||||
|
|
||||||
|
if (vector_active (varcomps) > 0)
|
||||||
|
{
|
||||||
|
fprintf(stdout, " ");
|
||||||
|
for (size_t j = 0; j < vector_active (varcomps); j++)
|
||||||
|
{
|
||||||
|
char *item = vector_slot (varcomps, j);
|
||||||
|
fprintf (stdout, " %s", item);
|
||||||
|
XFREE (MTYPE_COMPLETION, item);
|
||||||
|
}
|
||||||
|
vty_out (vty, "%s", VTY_NEWLINE);
|
||||||
|
}
|
||||||
|
vector_free (varcomps);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
cmd_free_strvec (vline);
|
cmd_free_strvec (vline);
|
||||||
@ -838,6 +857,7 @@ command_generator (const char *text, int state)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (matched && matched[index])
|
if (matched && matched[index])
|
||||||
|
/* this is free()'d by readline, but we leak 1 count of MTYPE_COMPLETION */
|
||||||
return matched[index++];
|
return matched[index++];
|
||||||
|
|
||||||
XFREE (MTYPE_TMP, matched);
|
XFREE (MTYPE_TMP, matched);
|
||||||
@ -3193,6 +3213,36 @@ vtysh_prompt (void)
|
|||||||
return buf;
|
return buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void vtysh_ac_line(void *arg, const char *line)
|
||||||
|
{
|
||||||
|
vector comps = arg;
|
||||||
|
size_t i;
|
||||||
|
for (i = 0; i < vector_active(comps); i++)
|
||||||
|
if (!strcmp(line, (char *)vector_slot(comps, i)))
|
||||||
|
return;
|
||||||
|
vector_set(comps, XSTRDUP(MTYPE_COMPLETION, line));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void vtysh_autocomplete(vector comps, struct cmd_token *token)
|
||||||
|
{
|
||||||
|
char accmd[256];
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
snprintf(accmd, sizeof(accmd), "autocomplete %d %s %s", token->type,
|
||||||
|
token->text, token->varname ? token->varname : "-");
|
||||||
|
|
||||||
|
for (i = 0; i < array_size(vtysh_client); i++)
|
||||||
|
vtysh_client_run_all (&vtysh_client[i], accmd, 1, NULL,
|
||||||
|
vtysh_ac_line, comps);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct cmd_variable_handler vtysh_var_handler = {
|
||||||
|
/* match all */
|
||||||
|
.tokenname = NULL,
|
||||||
|
.varname = NULL,
|
||||||
|
.completions = vtysh_autocomplete
|
||||||
|
};
|
||||||
|
|
||||||
void
|
void
|
||||||
vtysh_init_vty (void)
|
vtysh_init_vty (void)
|
||||||
{
|
{
|
||||||
@ -3203,6 +3253,7 @@ vtysh_init_vty (void)
|
|||||||
|
|
||||||
/* Initialize commands. */
|
/* Initialize commands. */
|
||||||
cmd_init (0);
|
cmd_init (0);
|
||||||
|
cmd_variable_handler_register(&vtysh_var_handler);
|
||||||
|
|
||||||
/* Install nodes. */
|
/* Install nodes. */
|
||||||
install_node (&bgp_node, NULL);
|
install_node (&bgp_node, NULL);
|
||||||
|
@ -85,7 +85,7 @@ int vtysh_mark_file(const char *filename);
|
|||||||
int vtysh_read_config (const char *);
|
int vtysh_read_config (const char *);
|
||||||
int vtysh_write_config_integrated (void);
|
int vtysh_write_config_integrated (void);
|
||||||
|
|
||||||
void vtysh_config_parse_line (const char *);
|
void vtysh_config_parse_line (void *, const char *);
|
||||||
|
|
||||||
void vtysh_config_dump (FILE *);
|
void vtysh_config_dump (FILE *);
|
||||||
|
|
||||||
|
@ -145,7 +145,7 @@ config_add_line_uniq (struct list *config, const char *line)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
vtysh_config_parse_line (const char *line)
|
vtysh_config_parse_line (void *arg, const char *line)
|
||||||
{
|
{
|
||||||
char c;
|
char c;
|
||||||
static struct config *config = NULL;
|
static struct config *config = NULL;
|
||||||
@ -418,12 +418,12 @@ vtysh_config_write ()
|
|||||||
if (host.name)
|
if (host.name)
|
||||||
{
|
{
|
||||||
sprintf (line, "hostname %s", host.name);
|
sprintf (line, "hostname %s", host.name);
|
||||||
vtysh_config_parse_line(line);
|
vtysh_config_parse_line(NULL, line);
|
||||||
}
|
}
|
||||||
if (vtysh_write_integrated == WRITE_INTEGRATED_NO)
|
if (vtysh_write_integrated == WRITE_INTEGRATED_NO)
|
||||||
vtysh_config_parse_line ("no service integrated-vtysh-config");
|
vtysh_config_parse_line (NULL, "no service integrated-vtysh-config");
|
||||||
if (vtysh_write_integrated == WRITE_INTEGRATED_YES)
|
if (vtysh_write_integrated == WRITE_INTEGRATED_YES)
|
||||||
vtysh_config_parse_line ("service integrated-vtysh-config");
|
vtysh_config_parse_line (NULL, "service integrated-vtysh-config");
|
||||||
|
|
||||||
user_config_write ();
|
user_config_write ();
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user