DEFINE_KOOH(cmd_execute_done, (struct vty * vty, const char *cmd_exec),
(vty, cmd_exec));
+/*
+ * cmd_execute hook subscriber to handle `|` actions.
+ */
+static int handle_pipe_action(struct vty *vty, const char *cmd_in,
+ char **cmd_out)
+{
+ /* look for `|` */
+ char *orig, *working, *token;
+ char *pipe = strstr(cmd_in, "| ");
+
+ if (!pipe)
+ return 0;
+
+ /* duplicate string for processing purposes, not including pipe */
+ orig = working = XSTRDUP(MTYPE_TMP, pipe + 2);
+
+ /* retrieve action */
+ token = strsep(&working, " ");
+
+ /* match result to known actions */
+ if (strmatch(token, "include")) {
+ /* the remaining text should be a regexp */
+ char *regexp = working;
+ bool succ = vty_set_include(vty, regexp);
+ if (!succ) {
+ vty_out(vty, "%% Bad regexp '%s'", regexp);
+ goto fail;
+ }
+ cmd_out = XSTRDUP(MTYPE_TMP, cmd_in);
+ *(strstr(cmd_in, "|")) = '\0';
+ } else {
+ vty_out(vty, "%% Unknown action '%s'", token);
+ goto fail;
+ }
+
+fail:
+ XFREE(MTYPE_TMP, orig);
+ return 0;
+}
+
+static int handle_pipe_action_done(struct vty *vty, const char *cmd_exec)
+{
+ if (vty->filter) {
+ vty_set_include(vty, NULL);
+ vty_out(vty, "\n");
+ }
+ return 0;
+}
+
int cmd_execute(struct vty *vty, const char *cmd,
const struct cmd_element **matched, int vtysh)
{
uname(&names);
qobj_init();
+ /* register command preprocessors */
+ hook_register(cmd_execute, handle_pipe_action);
+ hook_register(cmd_execute_done, handle_pipe_action_done);
+
varhandlers = list_new();
/* Allocate initial top vector of commands. */
#define FRR_CONFIG_ARGS "@CONFIG_ARGS@"
#define FRR_DEFAULT_MOTD \
- "\r\n" \
- "Hello, this is " FRR_FULL_NAME " (version " FRR_VERSION ").\r\n" \
- FRR_COPYRIGHT "\r\n" \
- GIT_INFO "\r\n"
+ "\n" \
+ "Hello, this is " FRR_FULL_NAME " (version " FRR_VERSION ").\n" \
+ FRR_COPYRIGHT "\n" \
+ GIT_INFO "\n"
pid_t pid_output (const char *);
#include <zebra.h>
+#include <lib/version.h>
+#include <sys/types.h>
+#include <regex.h>
+
#include "linklist.h"
#include "thread.h"
#include "buffer.h"
-#include <lib/version.h>
#include "command.h"
#include "sockunion.h"
#include "memory.h"
#include "privs.h"
#include "network.h"
#include "libfrr.h"
+#include "frrstr.h"
#include <arpa/telnet.h>
#include <termios.h>
vty->frame_pos = 0;
}
+bool vty_set_include(struct vty *vty, const char *regexp)
+{
+ int errcode;
+ bool ret = true;
+ char errbuf[256];
+
+ if (!regexp) {
+ memset(&vty->include, 0x00, sizeof(vty->include));
+ vty->filter = false;
+ return true;
+ }
+
+ errcode = regcomp(&vty->include, regexp,
+ REG_EXTENDED | REG_NEWLINE | REG_NOSUB);
+ if (errcode) {
+ ret = false;
+ regerror(ret, &vty->include, errbuf, sizeof(errbuf));
+ vty_out(vty, "%% Regex compilation error: %s", errbuf);
+ } else {
+ vty->filter = true;
+ }
+
+ return ret;
+}
+
/* VTY standard output function. */
int vty_out(struct vty *vty, const char *format, ...)
{
int size = 1024;
char buf[1024];
char *p = NULL;
+ char *filtered;
if (vty->frame_pos) {
vty->frame_pos = 0;
if (!p)
p = buf;
+ /* filter buffer */
+ if (vty->filter) {
+ vector lines = frrstr_split_vec(buf, "\n");
+ frrstr_filter_vec(lines, &vty->include);
+ if (buf[strlen(buf) - 1] == '\n' && vector_active(lines) > 0)
+ vector_set(lines, XSTRDUP(MTYPE_TMP, ""));
+ filtered = frrstr_join_vec(lines, "\n");
+ frrstr_strvec_free(lines);
+ } else {
+ filtered = p;
+ }
+
/* Pointer p must point out buffer. */
if (vty->type != VTY_TERM)
- buffer_put(vty->obuf, (uint8_t *)p, len);
+ buffer_put(vty->obuf, (uint8_t *)filtered,
+ strlen(filtered));
else
- buffer_put_crlf(vty->obuf, (uint8_t *)p, len);
+ buffer_put_crlf(vty->obuf, (uint8_t *)filtered,
+ strlen(filtered));
+
+ if (vty->filter)
+ XFREE(MTYPE_TMP, filtered);
/* If p is not different with buf, it is allocated buffer. */
if (p != buf)
static int vty_command(struct vty *vty, char *buf)
{
int ret;
- vector vline;
const char *protocolname;
char *cp = NULL;
/* now log the command */
zlog_err("%s%s", prompt_str, buf);
}
- /* Split readline string up into the vector */
- vline = cmd_make_strvec(buf);
-
- if (vline == NULL)
- return CMD_SUCCESS;
#ifdef CONSUMED_TIME_CHECK
{
GETRUSAGE(&before);
#endif /* CONSUMED_TIME_CHECK */
- ret = cmd_execute_command(vline, vty, NULL, 0);
+ ret = cmd_execute(vty, buf, NULL, 0);
/* Get the name of the protocol if any */
protocolname = frr_protoname;
vty_out(vty, "%% Command incomplete.\n");
break;
}
- cmd_free_strvec(vline);
return ret;
}
#ifndef _ZEBRA_VTY_H
#define _ZEBRA_VTY_H
+#include <sys/types.h>
+#include <regex.h>
+
#include "thread.h"
#include "log.h"
#include "sockunion.h"
/* Failure count */
int fail;
+ /* Output filer regex */
+ bool filter;
+ regex_t include;
+
/* Output buffer. */
struct buffer *obuf;
extern int vty_out(struct vty *, const char *, ...) PRINTF_ATTRIBUTE(2, 3);
extern void vty_frame(struct vty *, const char *, ...) PRINTF_ATTRIBUTE(2, 3);
extern void vty_endframe(struct vty *, const char *);
+bool vty_set_include(struct vty *vty, const char *regexp);
extern void vty_read_config(const char *, char *);
extern void vty_time_print(struct vty *, int);