DEFINE_MTYPE_STATIC(MVTYSH, VTYSH_CMD, "Vtysh cmd copy")
+/* Destination for vtysh output */
+FILE *outputfile;
+
/* Struct VTY. */
struct vty *vty;
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++) {
if (vline == NULL) {
if (pager && vtysh_pager_name && fp
- && closepager) {
+ && fp != outputfile && closepager) {
if (pclose(fp) == -1) {
perror("pclose failed for 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");
}
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;
}
if (vty_buf_trimmed[0] == '!' || vty_buf_trimmed[0] == '#') {
- fprintf(stdout, "%s", vty->buf);
+ fprintf(outputfile, "%s", vty->buf);
continue;
}
vline = cmd_make_strvec(vty->buf);
if (vline == NULL) {
- fprintf(stdout, "%s", vty->buf);
+ fprintf(outputfile, "%s", vty->buf);
continue;
}
|| 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
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;
}
}
}
/* This is the end */
- fprintf(stdout, "\nend\n");
+ fprintf(outputfile, "\nend\n");
vty_close(vty);
XFREE(MTYPE_VTYSH_CMD, vty_buf_copy);
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
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;
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");
}
}
ret = vtysh_client_execute(&vtysh_client[i], "show work-queues\n",
- stdout);
+ outputfile);
return ret;
}
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");
}
{
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)
vtysh_config_dump(fp);
- if (vtysh_pager_name && fp) {
+ if (vtysh_pager_name && fp && fp != outputfile) {
fflush(fp);
if (pclose(fp) == -1) {
perror("pclose");
fp = NULL;
}
- vty_out(vty, "end\n");
+ fprintf(outputfile, "end\n");
return CMD_SUCCESS;
}
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. */
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 "
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;
}
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;
}
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;
}
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...",
{
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. */
.completions = vtysh_autocomplete},
{.completions = NULL}};
+void vtysh_uninit()
+{
+ if (outputfile != stdout)
+ fclose(outputfile);
+}
+
void vtysh_init_vty(void)
{
/* Make vty structure. */
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);