From f366ad31ae6bf7e2fb7271cf8eab6dee4af3baf9 Mon Sep 17 00:00:00 2001 From: "Andrew J. Schorr" Date: Thu, 27 Jul 2006 18:01:41 +0000 Subject: [vtysh] Never skip authentication, and add support for multiple -c commands 2006-07-27 Andrew J. Schorr * vtysh.1: Document new options -d and -E, and note that now multiple -c options may be supplied, with embedded linefeed now supported. In BUGS section, remove warning about vtysh causing a daemon to freeze, since this has been fixed. * vtysh_main.c: (usage) Add new -d and -E options. And note that -c can be used multiple times, possibly with embedded linefeeds. (longopts) Add new -d and -E options. (main) Add new -d and -E options, and create a linked list to support multiple -c options. Do not call vtysh_connect_all until after vtysh_read_config(config_default) and vtysh_auth have succeeded. This prevents the vtysh.conf file from configuring any daemons, and it ensures that authentication has been passed before we send any commands to any daemons. Call vtysh_connect_all with any daemon name supplied with -d. If it is unable to connect to any daemons, issue an error message and exit immediately. When used in -c mode, call vtysh_execute("enable") before executing the commands in order to match interactive behavior. And detect embedded linefeed chars in -c commands and break them up appropriately. * vtysh.h: (vtysh_connect_all) Fix proto to reflect new daemon_name argument, and that it now returns an integer -- the number of daemons to which we were able to connect. * vtysh.c: (vtysh_connect_all) Add a new daemon_name argument. If supplied, connect only to that daemon. And return the number of daemons to which we were able to connect. (vtysh_prompt): Performance enhancement -- make struct utsname static so we call uname to get the hostname only once. --- doc/ChangeLog | 7 +++++ doc/vtysh.1 | 37 ++++++++++++++++++----- vtysh/ChangeLog | 26 ++++++++++++++++ vtysh/vtysh.c | 27 ++++++++++++----- vtysh/vtysh.h | 2 +- vtysh/vtysh_main.c | 87 +++++++++++++++++++++++++++++++++++++++++++++--------- 6 files changed, 155 insertions(+), 31 deletions(-) diff --git a/doc/ChangeLog b/doc/ChangeLog index c811cb31..a0c39953 100644 --- a/doc/ChangeLog +++ b/doc/ChangeLog @@ -1,3 +1,10 @@ +2006-07-27 Andrew J. Schorr + + * vtysh.1: Document new options -d and -E, and note that now multiple + -c options may be supplied, with embedded linefeed now supported. + In BUGS section, remove warning about vtysh causing a daemon + to freeze, since this has been fixed. + 2006-07-04 Paul Jakma * quagga.info: remove auto-generated file. It will still be diff --git a/doc/vtysh.1 b/doc/vtysh.1 index e5fccb11..eb960cdc 100644 --- a/doc/vtysh.1 +++ b/doc/vtysh.1 @@ -1,4 +1,4 @@ -.TH VTYSH 1 "3 October 2004" "Quagga VTY shell" "Version 0.96.5" +.TH VTYSH 1 "27 July 2006" "Quagga VTY shell" "Version 0.96.5" .SH NAME vtysh \- a integrated shell for Quagga routing software .SH SYNOPSIS @@ -9,6 +9,12 @@ vtysh \- a integrated shell for Quagga routing software .br .B vtysh [ +.B \-E +] [ +.B \-d +.I daemon +] +] [ .B \-c .I command ] @@ -29,13 +35,32 @@ info. Specify command to be executed under batch mode. It behaves like -c option in any other shell - .I command -is executed and vtysh exits. +is executed and +.B vtysh +exits. -It's useful for gathering info from Quagga routing software from shell scripts -etc. +It's useful for gathering info from Quagga routing software or reconfiguring +daemons from inside shell scripts, etc. +Note that multiple commands may be executed by using more than one +-c option and/or embedding linefeed characters inside the +.I command +string. +.IP "\fB\-d, \-\-daemon \fIdaemon_name\fP" +Specify which daemon to connect to. By default, +.B vtysh +attempts to connect to all Quagga daemons running on the system. With this +flag, one can specify a single daemon to connect to instead. For example, +specifying '-d ospfd' will connect only to ospfd. This can be particularly +useful inside scripts with -c where the command is targeted for a single daemon. .IP "\fB\-e, \-\-execute \fIcommand\fP" Alias for -c. It's here only for compatibility with Zebra routing software and older Quagga versions. This will be removed in future. +.IP "\fB\-E, \-\-echo\fP" +When the -c option is being used, this flag will cause the standard +.B vtysh +prompt and command to be echoed prior to displaying the results. +This is particularly useful to separate the results +when executing multiple commands. .IP "\fB\-h, \-\-help\fP" Display a usage message on standard output and exit. .SH ENVIRONMENT VARIABLES @@ -63,10 +88,6 @@ options. The definitive document is the Info file \fBQuagga\fR. .BR isisd (8), .BR zebra (8) .SH BUGS -Running the command which outputs large amount of data through pager ("show ip -ospf database", "show ip bgp" etc. in big networks) will cause daemon to be -unresponsive until vtysh returns back to the prompt. - .B vtysh eats bugs for breakfast. If you have food for the maintainers try .BI http://bugzilla.quagga.net diff --git a/vtysh/ChangeLog b/vtysh/ChangeLog index ac038e1c..b9b78f5e 100644 --- a/vtysh/ChangeLog +++ b/vtysh/ChangeLog @@ -1,3 +1,29 @@ +2006-07-27 Andrew J. Schorr + + * vtysh_main.c: (usage) Add new -d and -E options. And note that + -c can be used multiple times, possibly with embedded linefeeds. + (longopts) Add new -d and -E options. + (main) Add new -d and -E options, and create a linked list to + support multiple -c options. Do not call vtysh_connect_all until + after vtysh_read_config(config_default) and vtysh_auth have + succeeded. This prevents the vtysh.conf file from configuring + any daemons, and it ensures that authentication has been passed + before we send any commands to any daemons. Call vtysh_connect_all + with any daemon name supplied with -d. If it is unable to connect + to any daemons, issue an error message and exit immediately. + When used in -c mode, call vtysh_execute("enable") before + executing the commands in order to match interactive behavior. + And detect embedded linefeed chars in -c commands and break them up + appropriately. + * vtysh.h: (vtysh_connect_all) Fix proto to reflect new + daemon_name argument, and that it now returns an integer -- the + number of daemons to which we were able to connect. + * vtysh.c: (vtysh_connect_all) Add a new daemon_name argument. + If supplied, connect only to that daemon. And return + the number of daemons to which we were able to connect. + (vtysh_prompt): Performance enhancement -- make struct utsname + static so we call uname to get the hostname only once. + 2006-05-24 Paul Jakma * vtysh.c: (general) Add 'show memory' command. diff --git a/vtysh/vtysh.c b/vtysh/vtysh.c index 110c361a..9b7d300f 100644 --- a/vtysh/vtysh.c +++ b/vtysh/vtysh.c @@ -2119,18 +2119,28 @@ vtysh_connect (struct vtysh_client *vclient) return 0; } -void -vtysh_connect_all(void) +int +vtysh_connect_all(const char *daemon_name) { u_int i; + int rc = 0; + int matches = 0; for (i = 0; i < VTYSH_INDEX_MAX; i++) { - vtysh_connect(&vtysh_client[i]); - /* We need direct access to ripd in vtysh_exit_ripd_only. */ - if (vtysh_client[i].flag == VTYSH_RIPD) - ripd_client = &vtysh_client[i]; + if (!daemon_name || !strcmp(daemon_name, vtysh_client[i].name)) + { + matches++; + if (vtysh_connect(&vtysh_client[i]) == 0) + rc++; + /* We need direct access to ripd in vtysh_exit_ripd_only. */ + if (vtysh_client[i].flag == VTYSH_RIPD) + ripd_client = &vtysh_client[i]; + } } + if (!matches) + fprintf(stderr, "Error: no daemons match name %s!\n", daemon_name); + return rc; } /* To disable readline's filename completion. */ @@ -2155,7 +2165,7 @@ vtysh_readline_init (void) char * vtysh_prompt (void) { - struct utsname names; + static struct utsname names; static char buf[100]; const char*hostname; extern struct host host; @@ -2164,7 +2174,8 @@ vtysh_prompt (void) if (!hostname) { - uname (&names); + if (!names.nodename[0]) + uname (&names); hostname = names.nodename; } diff --git a/vtysh/vtysh.h b/vtysh/vtysh.h index d619c294..dd2bcbd0 100644 --- a/vtysh/vtysh.h +++ b/vtysh/vtysh.h @@ -38,7 +38,7 @@ void vtysh_init_vty (void); void vtysh_init_cmd (void); -void vtysh_connect_all (void); +extern int vtysh_connect_all (const char *optional_daemon_name); void vtysh_readline_init (void); void vtysh_user_init (void); diff --git a/vtysh/vtysh_main.c b/vtysh/vtysh_main.c index 7f8e0592..134bcf73 100644 --- a/vtysh/vtysh_main.c +++ b/vtysh/vtysh_main.c @@ -32,6 +32,7 @@ #include #include "getopt.h" #include "command.h" +#include "memory.h" #include "vtysh/vtysh.h" #include "vtysh/vtysh_user.h" @@ -132,10 +133,15 @@ usage (int status) fprintf (stderr, "Try `%s --help' for more information.\n", progname); else printf ("Usage : %s [OPTION...]\n\n" \ - "Integrated shell for Quagga routing software suite. \n\n"\ + "Integrated shell for Quagga routing software suite. \n\n" \ "-b, --boot Execute boot startup configuration\n" \ - "-c, --command Execute argument as command\n "\ + "-c, --command Execute argument as command\n" \ + "-d, --daemon Connect only to the specified daemon\n" \ + "-E, --echo Echo prompt and command in -c mode\n" \ "-h, --help Display this help and exit\n\n" \ + "Note that multiple commands may be executed from the command\n" \ + "line by passing multiple -c args, or by embedding linefeed\n" \ + "characters in one or more of the commands.\n\n" \ "Report bugs to %s\n", progname, ZEBRA_BUG_ADDRESS); exit (status); @@ -148,6 +154,8 @@ struct option longopts[] = /* For compatibility with older zebra/quagga versions */ { "eval", required_argument, NULL, 'e'}, { "command", required_argument, NULL, 'c'}, + { "daemon", required_argument, NULL, 'd'}, + { "echo", no_argument, NULL, 'E'}, { "help", no_argument, NULL, 'h'}, { 0 } }; @@ -187,9 +195,14 @@ main (int argc, char **argv, char **env) { char *p; int opt; - int eval_flag = 0; int boot_flag = 0; - char *eval_line = NULL; + const char *daemon_name = NULL; + struct cmd_rec { + const char *line; + struct cmd_rec *next; + } *cmd = NULL; + struct cmd_rec *tail = NULL; + int echo_command = 0; /* Preserve name of myself. */ progname = ((p = strrchr (argv[0], '/')) ? ++p : argv[0]); @@ -197,7 +210,7 @@ main (int argc, char **argv, char **env) /* Option handling. */ while (1) { - opt = getopt_long (argc, argv, "be:c:h", longopts, 0); + opt = getopt_long (argc, argv, "be:c:d:Eh", longopts, 0); if (opt == EOF) break; @@ -211,8 +224,23 @@ main (int argc, char **argv, char **env) break; case 'e': case 'c': - eval_flag = 1; - eval_line = optarg; + { + struct cmd_rec *cr; + cr = XMALLOC(0, sizeof(*cr)); + cr->line = optarg; + cr->next = NULL; + if (tail) + tail->next = cr; + else + cmd = cr; + tail = cr; + } + break; + case 'd': + daemon_name = optarg; + break; + case 'E': + echo_command = 1; break; case 'h': usage (0); @@ -239,15 +267,48 @@ main (int argc, char **argv, char **env) sort_node (); - vtysh_connect_all (); - - /* Read vtysh configuration file. */ + /* Read vtysh configuration file before connecting to daemons. */ vtysh_read_config (config_default); + /* Make sure we pass authentication before proceeding. */ + vtysh_auth (); + + /* Do not connect until we have passed authentication. */ + if (vtysh_connect_all (daemon_name) <= 0) + { + fprintf(stderr, "Exiting: failed to connect to any daemons.\n"); + exit(1); + } + /* If eval mode. */ - if (eval_flag) + if (cmd) { - vtysh_execute_no_pager (eval_line); + /* Enter into enable node. */ + vtysh_execute ("enable"); + + while (cmd != NULL) + { + char *eol; + + while ((eol = strchr(cmd->line, '\n')) != NULL) + { + *eol = '\0'; + if (echo_command) + printf("%s%s\n", vtysh_prompt(), cmd->line); + vtysh_execute_no_pager(cmd->line); + cmd->line = eol+1; + } + if (echo_command) + printf("%s%s\n", vtysh_prompt(), cmd->line); + vtysh_execute_no_pager (cmd->line); + + { + struct cmd_rec *cr; + cr = cmd; + cmd = cmd->next; + XFREE(0, cr); + } + } exit (0); } @@ -270,8 +331,6 @@ main (int argc, char **argv, char **env) vty_hello (vty); - vtysh_auth (); - /* Enter into enable node. */ vtysh_execute ("enable"); -- cgit v1.2.1