Skip to content

Commit

Permalink
Merge pull request #1634 from qlyoung/vtysh-output-file
Browse files Browse the repository at this point in the history
vtysh: add ability to output to file
  • Loading branch information
riw777 authored Jan 16, 2018
2 parents 7256280 + 193a5a9 commit 7c0c85a
Show file tree
Hide file tree
Showing 3 changed files with 93 additions and 45 deletions.
135 changes: 90 additions & 45 deletions vtysh/vtysh.c
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,9 @@

DEFINE_MTYPE_STATIC(MVTYSH, VTYSH_CMD, "Vtysh cmd copy")

/* Destination for vtysh output */
FILE *outputfile;

/* Struct VTY. */
struct vty *vty;

Expand Down Expand Up @@ -391,21 +394,21 @@ static int vtysh_execute_func(const char *line, int pager)
fprintf(stdout, "%% Command incomplete.\n");
break;
case CMD_SUCCESS_DAEMON: {
/* FIXME: Don't open pager for exit commands. popen() causes
* problems
* if exited from vtysh at all. This hack shouldn't cause any
* problem
* but is really ugly. */
if (pager && vtysh_pager_name
/*
* FIXME: Don't open pager for exit commands. popen() causes
* problems if exited from vtysh at all. This hack shouldn't
* cause any problem but is really ugly.
*/
fp = outputfile;
if (pager && vtysh_pager_name && outputfile == stdout
&& (strncmp(line, "exit", 4) != 0)) {
fp = popen(vtysh_pager_name, "w");
if (fp == NULL) {
perror("popen failed for pager");
fp = stdout;
fp = outputfile;
} else
closepager = 1;
} else
fp = stdout;
}

if (!strcmp(cmd->string, "configure terminal")) {
for (i = 0; i < array_size(vtysh_client); i++) {
Expand All @@ -421,7 +424,7 @@ static int vtysh_execute_func(const char *line, int pager)

if (vline == NULL) {
if (pager && vtysh_pager_name && fp
&& closepager) {
&& fp != outputfile && closepager) {
if (pclose(fp) == -1) {
perror("pclose failed for pager");
}
Expand Down Expand Up @@ -471,7 +474,7 @@ static int vtysh_execute_func(const char *line, int pager)
(*cmd->func)(cmd, vty, 0, NULL);
}
}
if (pager && vtysh_pager_name && fp && closepager) {
if (pager && vtysh_pager_name && fp && closepager && fp != outputfile) {
if (pclose(fp) == -1) {
perror("pclose failed for pager");
}
Expand Down Expand Up @@ -553,19 +556,19 @@ int vtysh_mark_file(const char *filename)
switch (vty->node) {
case LDP_IPV4_IFACE_NODE:
if (strncmp(vty_buf_copy, " ", 3)) {
fprintf(stdout, " end\n");
fprintf(outputfile, " end\n");
vty->node = LDP_IPV4_NODE;
}
break;
case LDP_IPV6_IFACE_NODE:
if (strncmp(vty_buf_copy, " ", 3)) {
fprintf(stdout, " end\n");
fprintf(outputfile, " end\n");
vty->node = LDP_IPV6_NODE;
}
break;
case LDP_PSEUDOWIRE_NODE:
if (strncmp(vty_buf_copy, " ", 2)) {
fprintf(stdout, " end\n");
fprintf(outputfile, " end\n");
vty->node = LDP_L2VPN_NODE;
}
break;
Expand All @@ -574,15 +577,15 @@ int vtysh_mark_file(const char *filename)
}

if (vty_buf_trimmed[0] == '!' || vty_buf_trimmed[0] == '#') {
fprintf(stdout, "%s", vty->buf);
fprintf(outputfile, "%s", vty->buf);
continue;
}

/* Split readline string up into the vector. */
vline = cmd_make_strvec(vty->buf);

if (vline == NULL) {
fprintf(stdout, "%s", vty->buf);
fprintf(outputfile, "%s", vty->buf);
continue;
}

Expand Down Expand Up @@ -625,15 +628,15 @@ int vtysh_mark_file(const char *filename)
|| prev_node == BGP_IPV6M_NODE
|| prev_node == BGP_EVPN_NODE)
&& (tried == 1)) {
fprintf(stdout, "exit-address-family\n");
fprintf(outputfile, "exit-address-family\n");
} else if ((prev_node == BGP_EVPN_VNI_NODE)
&& (tried == 1)) {
fprintf(stdout, "exit-vni\n");
fprintf(outputfile, "exit-vni\n");
} else if ((prev_node == KEYCHAIN_KEY_NODE)
&& (tried == 1)) {
fprintf(stdout, "exit\n");
fprintf(outputfile, "exit\n");
} else if (tried) {
fprintf(stdout, "end\n");
fprintf(outputfile, "end\n");
}
}
/* If command didn't succeed in any node, continue with return
Expand Down Expand Up @@ -683,12 +686,12 @@ int vtysh_mark_file(const char *filename)
u_int i;
int cmd_stat = CMD_SUCCESS;

fprintf(stdout, "%s", vty->buf);
fprintf(outputfile, "%s", vty->buf);
for (i = 0; i < array_size(vtysh_client); i++) {
if (cmd->daemon & vtysh_client[i].flag) {
cmd_stat = vtysh_client_execute(
&vtysh_client[i], vty->buf,
stdout);
outputfile);
if (cmd_stat != CMD_SUCCESS)
break;
}
Expand All @@ -702,7 +705,7 @@ int vtysh_mark_file(const char *filename)
}
}
/* This is the end */
fprintf(stdout, "\nend\n");
fprintf(outputfile, "\nend\n");
vty_close(vty);
XFREE(MTYPE_VTYSH_CMD, vty_buf_copy);

Expand Down Expand Up @@ -765,7 +768,7 @@ int vtysh_config_from_file(struct vty *vty, FILE *fp)
if (cmd->daemon & vtysh_client[i].flag) {
cmd_stat = vtysh_client_execute(
&vtysh_client[i], vty->buf,
stdout);
outputfile);
/*
* CMD_WARNING - Can mean that the
* command was
Expand Down Expand Up @@ -1870,7 +1873,7 @@ DEFUN (vtysh_show_thread,
fprintf(stdout, "Thread statistics for %s:\n",
vtysh_client[i].name);
ret = vtysh_client_execute(&vtysh_client[i], line,
stdout);
outputfile);
fprintf(stdout, "\n");
}
return ret;
Expand All @@ -1891,7 +1894,7 @@ DEFUN (vtysh_show_work_queues,
fprintf(stdout, "Work queue statistics for %s:\n",
vtysh_client[i].name);
ret = vtysh_client_execute(&vtysh_client[i], line,
stdout);
outputfile);
fprintf(stdout, "\n");
}

Expand Down Expand Up @@ -1921,7 +1924,7 @@ DEFUN (vtysh_show_work_queues_daemon,
}

ret = vtysh_client_execute(&vtysh_client[i], "show work-queues\n",
stdout);
outputfile);

return ret;
}
Expand All @@ -1948,9 +1951,9 @@ static int show_per_daemon(const char *line, const char *headline)

for (i = 0; i < array_size(vtysh_client); i++)
if (vtysh_client[i].fd >= 0) {
fprintf(stdout, headline, vtysh_client[i].name);
fprintf(outputfile, headline, vtysh_client[i].name);
ret = vtysh_client_execute(&vtysh_client[i], line,
stdout);
outputfile);
fprintf(stdout, "\n");
}

Expand Down Expand Up @@ -2242,20 +2245,19 @@ DEFUN (vtysh_write_terminal,
{
u_int i;
char line[] = "do write terminal\n";
FILE *fp = NULL;
FILE *fp = outputfile;

if (vtysh_pager_name) {
if (fp == stdout && vtysh_pager_name) {
fp = popen(vtysh_pager_name, "w");
if (fp == NULL) {
perror("popen");
exit(1);
}
} else
fp = stdout;
}

vty_out(vty, "Building configuration...\n");
vty_out(vty, "\nCurrent configuration:\n");
vty_out(vty, "!\n");
fprintf(outputfile, "Building configuration...\n");
fprintf(outputfile, "\nCurrent configuration:\n");
fprintf(outputfile, "!\n");

for (i = 0; i < array_size(vtysh_client); i++)
if ((argc < 3)
Expand All @@ -2267,7 +2269,7 @@ DEFUN (vtysh_write_terminal,

vtysh_config_dump(fp);

if (vtysh_pager_name && fp) {
if (vtysh_pager_name && fp && fp != outputfile) {
fflush(fp);
if (pclose(fp) == -1) {
perror("pclose");
Expand All @@ -2276,7 +2278,7 @@ DEFUN (vtysh_write_terminal,
fp = NULL;
}

vty_out(vty, "end\n");
fprintf(outputfile, "end\n");
return CMD_SUCCESS;
}

Expand Down Expand Up @@ -2445,7 +2447,7 @@ DEFUN (vtysh_write_memory,
char line[] = "do write memory\n";
u_int i;

fprintf(stdout,
fprintf(outputfile,
"Note: this version of vtysh never writes vtysh.conf\n");

/* If integrated frr.conf explicitely set. */
Expand All @@ -2457,7 +2459,7 @@ DEFUN (vtysh_write_memory,
if (i < array_size(vtysh_client) && vtysh_client[i].fd != -1)
ret = vtysh_client_execute(&vtysh_client[i],
"do write integrated",
stdout);
outputfile);

if (ret != CMD_SUCCESS) {
printf("\nWarning: attempting direct configuration write without "
Expand All @@ -2468,10 +2470,10 @@ DEFUN (vtysh_write_memory,
return ret;
}

fprintf(stdout, "Building Configuration...\n");
fprintf(outputfile, "Building Configuration...\n");

for (i = 0; i < array_size(vtysh_client); i++)
ret = vtysh_client_execute(&vtysh_client[i], line, stdout);
ret = vtysh_client_execute(&vtysh_client[i], line, outputfile);

return ret;
}
Expand Down Expand Up @@ -2500,7 +2502,7 @@ DEFUN (vtysh_terminal_length,

lines = strtol(argv[idx_number]->arg, &endptr, 10);
if (lines < 0 || lines > 512 || *endptr != '\0') {
vty_out(vty, "length is malformed\n");
fprintf(outputfile, "length is malformed\n");
return CMD_WARNING;
}

Expand Down Expand Up @@ -2543,8 +2545,8 @@ DEFUN (vtysh_show_daemons,

for (i = 0; i < array_size(vtysh_client); i++)
if (vtysh_client[i].fd >= 0)
vty_out(vty, " %s", vtysh_client[i].name);
vty_out(vty, "\n");
fprintf(outputfile, " %s", vtysh_client[i].name);
fprintf(outputfile, "\n");

return CMD_SUCCESS;
}
Expand Down Expand Up @@ -2719,6 +2721,38 @@ DEFUN (config_list,
return cmd_list_cmds(vty, argc == 2);
}

DEFUN (vtysh_output_file,
vtysh_output_file_cmd,
"output file FILE",
"Direct vtysh output to file\n"
"Direct vtysh output to file\n"
"Path to dump output to\n")
{
const char *path = argv[argc - 1]->arg;
outputfile = fopen(path, "a");
if (!outputfile) {
fprintf(stdout, "Failed to open file '%s': %s\n", path,
safe_strerror(errno));
outputfile = stdout;
}
return CMD_SUCCESS;
}

DEFUN (no_vtysh_output_file,
no_vtysh_output_file_cmd,
"no output file [FILE]",
NO_STR
"Direct vtysh output to file\n"
"Direct vtysh output to file\n"
"Path to dump output to\n")
{
if (outputfile != stdout) {
fclose(outputfile);
outputfile = stdout;
}
return CMD_SUCCESS;
}

DEFUN(find,
find_cmd,
"find COMMAND...",
Expand Down Expand Up @@ -2752,6 +2786,8 @@ static void vtysh_install_default(enum node_type node)
{
install_element(node, &config_list_cmd);
install_element(node, &find_cmd);
install_element(node, &vtysh_output_file_cmd);
install_element(node, &no_vtysh_output_file_cmd);
}

/* Making connection to protocol daemon. */
Expand Down Expand Up @@ -2980,13 +3016,22 @@ static const struct cmd_variable_handler vtysh_var_handler[] = {
.completions = vtysh_autocomplete},
{.completions = NULL}};

void vtysh_uninit()
{
if (outputfile != stdout)
fclose(outputfile);
}

void vtysh_init_vty(void)
{
/* Make vty structure. */
vty = vty_new();
vty->type = VTY_SHELL;
vty->node = VIEW_NODE;

/* set default output */
outputfile = stdout;

/* Initialize commands. */
cmd_init(0);
cmd_variable_handler_register(vtysh_var_handler);
Expand Down
1 change: 1 addition & 0 deletions vtysh/vtysh.h
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ extern char frr_config[];
extern char vtydir[];

void vtysh_init_vty(void);
void vtysh_uninit(void);
void vtysh_init_cmd(void);
extern int vtysh_connect_all(const char *optional_daemon_name);
void vtysh_readline_init(void);
Expand Down
2 changes: 2 additions & 0 deletions vtysh/vtysh_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -644,6 +644,8 @@ int main(int argc, char **argv, char **env)
while (vtysh_rl_gets())
vtysh_execute(line_read);

vtysh_uninit();

history_truncate_file(history_file, 1000);
printf("\n");

Expand Down

0 comments on commit 7c0c85a

Please sign in to comment.