diff --git a/include/osmocom/vty/command.h b/include/osmocom/vty/command.h index d63dbdef1..88490f790 100644 --- a/include/osmocom/vty/command.h +++ b/include/osmocom/vty/command.h @@ -401,4 +401,6 @@ void print_version(int print_copyright); extern void *tall_vty_cmd_ctx; +int vty_dump_xml_ref(FILE *stream); + /*! @} */ diff --git a/src/vty/command.c b/src/vty/command.c index daee5c5aa..9b32d22df 100644 --- a/src/vty/command.c +++ b/src/vty/command.c @@ -619,15 +619,17 @@ static char *xml_escape(const char *inp) return out; } +typedef int (*print_func_t)(void *data, const char *fmt, ...); + /* - * Write one cmd_element as XML to the given VTY. + * Write one cmd_element as XML via a print_func_t. */ -static int vty_dump_element(struct cmd_element *cmd, struct vty *vty) +static int vty_dump_element(struct cmd_element *cmd, print_func_t print_func, void *data, const char *newline) { char *xml_string = xml_escape(cmd->string); - vty_out(vty, " %s", xml_string, VTY_NEWLINE); - vty_out(vty, " %s", VTY_NEWLINE); + print_func(data, " %s", xml_string, newline); + print_func(data, " %s", newline); int j; for (j = 0; j < vector_count(cmd->strvec); ++j) { @@ -641,15 +643,15 @@ static int vty_dump_element(struct cmd_element *cmd, struct vty *vty) xml_param = xml_escape(desc->cmd); xml_doc = xml_escape(desc->str); - vty_out(vty, " %s", - xml_param, xml_doc, VTY_NEWLINE); + print_func(data, " %s", + xml_param, xml_doc, newline); talloc_free(xml_param); talloc_free(xml_doc); } } - vty_out(vty, " %s", VTY_NEWLINE); - vty_out(vty, " %s", VTY_NEWLINE); + print_func(data, " %s", newline); + print_func(data, " %s", newline); talloc_free(xml_string); return 0; @@ -658,20 +660,20 @@ static int vty_dump_element(struct cmd_element *cmd, struct vty *vty) static bool vty_command_is_common(struct cmd_element *cmd); /* - * Dump all nodes and commands associated with a given node as XML to the VTY. + * Dump all nodes and commands associated with a given node as XML via a print_func_t. */ -static int vty_dump_nodes(struct vty *vty) +static int vty_dump_nodes(print_func_t print_func, void *data, const char *newline) { int i, j; int same_name_count; - vty_out(vty, "%s", VTY_NEWLINE); + print_func(data, "%s", newline); /* Only once, list all common node commands. Use the CONFIG node to find common node commands. */ - vty_out(vty, " %s", VTY_NEWLINE); - vty_out(vty, " Common Commands%s", VTY_NEWLINE); - vty_out(vty, " These commands are available on all VTY nodes. They are listed" - " here only once, to unclutter the VTY reference.%s", VTY_NEWLINE); + print_func(data, " %s", newline); + print_func(data, " Common Commands%s", newline); + print_func(data, " These commands are available on all VTY nodes. They are listed" + " here only once, to unclutter the VTY reference.%s", newline); for (i = 0; i < vector_active(cmdvec); ++i) { struct cmd_node *cnode; cnode = vector_slot(cmdvec, i); @@ -686,10 +688,10 @@ static int vty_dump_nodes(struct vty *vty) if (!vty_command_is_common(elem)) continue; if (!(elem->attr & (CMD_ATTR_DEPRECATED | CMD_ATTR_HIDDEN))) - vty_dump_element(elem, vty); + vty_dump_element(elem, print_func, data, newline); } } - vty_out(vty, " %s", VTY_NEWLINE); + print_func(data, " %s", newline); for (i = 0; i < vector_active(cmdvec); ++i) { struct cmd_node *cnode; @@ -712,11 +714,11 @@ static int vty_dump_nodes(struct vty *vty) same_name_count ++; } - vty_out(vty, " name); if (same_name_count > 1 || !*cnode->name) - vty_out(vty, "_%d", same_name_count); - vty_out(vty, "'>%s", VTY_NEWLINE); - vty_out(vty, " %s%s", cnode->name, VTY_NEWLINE); + print_func(data, "_%d", same_name_count); + print_func(data, "'>%s", newline); + print_func(data, " %s%s", cnode->name, newline); for (j = 0; j < vector_active(cnode->cmd_vector); ++j) { struct cmd_element *elem; @@ -724,17 +726,50 @@ static int vty_dump_nodes(struct vty *vty) if (vty_command_is_common(elem)) continue; if (!(elem->attr & (CMD_ATTR_DEPRECATED | CMD_ATTR_HIDDEN))) - vty_dump_element(elem, vty); + vty_dump_element(elem, print_func, data, newline); } - vty_out(vty, " %s", VTY_NEWLINE); + print_func(data, " %s", newline); } - vty_out(vty, "%s", VTY_NEWLINE); + print_func(data, "%s", newline); return 0; } +static int print_func_vty(void *data, const char *format, ...) +{ + struct vty *vty = data; + va_list args; + int rc; + va_start(args, format); + rc = vty_out_va(vty, format, args); + va_end(args); + return rc; +} + +static int vty_dump_xml_ref_to_vty(struct vty *vty) +{ + return vty_dump_nodes(print_func_vty, vty, VTY_NEWLINE); +} + +static int print_func_stream(void *data, const char *format, ...) +{ + va_list args; + int rc; + va_start(args, format); + rc = vfprintf((FILE*)data, format, args); + va_end(args); + return rc; +} + +/*! Print the XML reference of all VTY nodes to the given stream. + */ +int vty_dump_xml_ref(FILE *stream) +{ + return vty_dump_nodes(print_func_stream, stream, "\n"); +} + /* Check if a command with given string exists at given node */ static int check_element_exists(struct cmd_node *cnode, const char *cmdstring) { @@ -2772,7 +2807,7 @@ DEFUN(show_version, DEFUN(show_online_help, show_online_help_cmd, "show online-help", SHOW_STR "Online help\n") { - vty_dump_nodes(vty); + vty_dump_xml_ref_to_vty(vty); return CMD_SUCCESS; }