summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChris Hall <chris.hall@highwayman.com>2011-03-30 12:22:34 +0100
committerChris Hall <chris.hall@highwayman.com>2011-03-30 12:22:34 +0100
commitf3255d1e9f062e7783b05ab5b32ca70085170d79 (patch)
tree2545e94650e88237baf6c0e04758f00e87dc335a
parent9c99076cf33bfa874db34151e28822f0e392ab3a (diff)
downloadquagga-f3255d1e9f062e7783b05ab5b32ca70085170d79.tar.bz2
quagga-f3255d1e9f062e7783b05ab5b32ca70085170d79.tar.xz
Better mechanism for handling depth_mark in vty->vio.
Previous mechanism required special steps before any new output vty was opened -- which was easy to forget. New mechanism requires extra step when input and output are opened at the same time, which is less common, and more obviously requires the extra step. Fixes problem with "write memory" command.
-rw-r--r--lib/command_execute.c13
-rw-r--r--lib/vty_command.c9
-rw-r--r--lib/vty_command.h1
-rw-r--r--lib/vty_io.c25
-rw-r--r--lib/vty_io.h3
-rw-r--r--lib/vty_io_file.c2
-rw-r--r--lib/vty_io_term.c2
7 files changed, 35 insertions, 20 deletions
diff --git a/lib/command_execute.c b/lib/command_execute.c
index 32698d94..cc457ba3 100644
--- a/lib/command_execute.c
+++ b/lib/command_execute.c
@@ -473,13 +473,13 @@ cmd_open_pipes(vty vty)
cmd_parsed parsed = exec->parsed ;
cmd_return_code_t ret ;
vty_io vio ;
-
+ bool sync_depth ;
VTY_LOCK() ;
vio = vty->vio ;
ret = CMD_SUCCESS ;
- uty_cmd_depth_mark(vio) ; /* about to push vin and/or vout */
+ sync_depth = false ; /* assuming no in pipe */
/* Deal with any in pipe stuff */
if ((parsed->parts & cmd_part_in_pipe) != 0)
@@ -499,6 +499,8 @@ cmd_open_pipes(vty vty)
zabort("invalid in pipe state") ;
qs_free(args) ;
+
+ sync_depth = true ;
} ;
/* Deal with any out pipe stuff */
@@ -511,15 +513,18 @@ cmd_open_pipes(vty vty)
if ((parsed->out_pipe & cmd_pipe_file) != 0)
ret = uty_cmd_open_out_pipe_file(vio, exec->context, args,
- parsed->out_pipe) ;
+ parsed->out_pipe) ;
else if ((parsed->out_pipe & cmd_pipe_shell) != 0)
ret = uty_cmd_open_out_pipe_shell(vio, exec->context, args,
- parsed->out_pipe) ;
+ parsed->out_pipe) ;
else if ((parsed->out_pipe & cmd_pipe_dev_null) != 0)
ret = uty_cmd_open_out_dev_null(vio) ;
else
zabort("invalid out pipe state") ;
+ if (sync_depth && (ret == CMD_SUCCESS))
+ uty_vout_sync_depth(vio) ;
+
qs_free(args) ;
} ;
diff --git a/lib/vty_command.c b/lib/vty_command.c
index 94ba6833..a63f6f0c 100644
--- a/lib/vty_command.c
+++ b/lib/vty_command.c
@@ -1155,15 +1155,6 @@ vty_cmd_reflect_line(vty vty)
} ;
/*------------------------------------------------------------------------------
- * Set the vio->depth_mark -- about to push vin and/or vout
- */
-extern void
-uty_cmd_depth_mark(vty_io vio)
-{
- vio->depth_mark = vio->vin_depth ;
-}
-
-/*------------------------------------------------------------------------------
* Open the given file as an in pipe, if possible.
*
* Puts error messages to vty if fails.
diff --git a/lib/vty_command.h b/lib/vty_command.h
index 125b9a03..38c95604 100644
--- a/lib/vty_command.h
+++ b/lib/vty_command.h
@@ -46,7 +46,6 @@ extern cmd_return_code_t uty_cmd_out_push(vio_vf vf, bool final) ;
extern void vty_cmd_set_full_lex(vty vty, bool full_lex) ;
-extern void uty_cmd_depth_mark(vty_io vio) ;
extern cmd_return_code_t uty_cmd_open_in_pipe_file(vty_io vio,
cmd_context context, qstring name, cmd_pipe_type_t type) ;
extern cmd_return_code_t uty_cmd_open_in_pipe_shell(vty_io vio,
diff --git a/lib/vty_io.c b/lib/vty_io.c
index 96df3850..619f8129 100644
--- a/lib/vty_io.c
+++ b/lib/vty_io.c
@@ -252,8 +252,6 @@ uty_new(vty_type_t type, node_type_t node)
* vout_base = NULL -- empty output stack
* vout_depth = 0 -- no stacked vout's, yet
*
- * depth_mark = 0 -- no stacked vin/vout, yet
- *
* err_hard = false -- no error at all, yet
* ebuf = NULL -- no error at all, yet
*
@@ -365,12 +363,17 @@ uty_vin_new_context(vty_io vio, cmd_context context, qpath file_here)
*
* Initialises an output buffer and sets an end_mark.
*
- * The depth_mark is set to the current vio->depth_mark + 1. This is the
+ * The depth_mark is set to the current vio->vin_depth + 1. This is the
* vin_depth below which the vout should be closed. Before a command line
* is fetched (and hence after the previous command line has completed) the
* vout->depth_mark is checked. If it is > the current vin_depth, then
* the vout is closed before a command line can be fetched.
*
+ * NB: where a vin and vout are opened together, so the vout should NOT
+ * be closed until after the vin, need to call uty_vout_sync_depth()
+ * *both* the vin and the vout are pushed, in order to set the correct
+ * depth_mark.
+ *
* NB: is usually called from the cli thread, but may be called from the cmd
* thread for vf which is blocking !
*
@@ -417,12 +420,26 @@ uty_vout_push(vty_io vio, vio_vf vf, vio_out_type_t type,
vf->obuf = vio_fifo_new(obuf_size) ;
vio_fifo_set_end_mark(vf->obuf) ;
- vf->depth_mark = vio->depth_mark + 1 ;
+ vf->depth_mark = vio->vin_depth + 1 ;
vio->obuf = vf->obuf ;
} ;
/*------------------------------------------------------------------------------
+ * Synchronise vout->depth_mark to current vin_depth.
+ *
+ * This *must* be called after a vin and vout have been opened together, and
+ * they are intended to be at the same depth. This applies when the base
+ * vin/vout are opened, and when an in pipe and an out pipe are present together
+ * on a command line.
+ */
+extern void
+uty_vout_sync_depth(vty_io vio)
+{
+ vio->vout->depth_mark = vio->vin_depth ;
+} ;
+
+/*------------------------------------------------------------------------------
* Set timeout value.
*
* This is only ever called when a command (eg exec-timeout) sets a new
diff --git a/lib/vty_io.h b/lib/vty_io.h
index 24790526..59ffb808 100644
--- a/lib/vty_io.h
+++ b/lib/vty_io.h
@@ -343,8 +343,6 @@ struct vty_io /* typedef appears above */
vio_vf vout_base ;
uint vout_depth ;
- uint depth_mark ; /* vin_depth before pipes opened */
-
/* Error handling */
bool err_hard ; /* eg I/O error */
vio_fifo ebuf ; /* buffer for error message */
@@ -441,6 +439,7 @@ extern void uty_vout_push(vty_io vio, vio_vf vf, vio_out_type_t type,
vio_vfd_action* write_action,
vio_timer_action* write_timer_action,
usize obuf_size) ;
+extern void uty_vout_sync_depth(vty_io vio) ;
extern cmd_return_code_t uty_vin_pop(vty_io vio, bool final,
cmd_context context) ;
extern cmd_return_code_t uty_vout_pop(vty_io vio, bool final) ;
diff --git a/lib/vty_io_file.c b/lib/vty_io_file.c
index 01a92a2d..4b1a8cfa 100644
--- a/lib/vty_io_file.c
+++ b/lib/vty_io_file.c
@@ -75,6 +75,8 @@ vty_config_read_open(int fd, const char* name, bool full_lex)
uty_vin_push( vio, vf, VIN_CONFIG, NULL, NULL, 64 * 1024) ;
uty_vout_push(vio, vf, VOUT_STDERR, NULL, NULL, 4 * 1024) ;
+ uty_vout_sync_depth(vio) ; /* vin & vout are at same level */
+
/* Deal with the possibility that while reading the configuration file, may
* use a pipe, and therefore may block waiting to collect a child process.
*
diff --git a/lib/vty_io_term.c b/lib/vty_io_term.c
index aea04734..416968bf 100644
--- a/lib/vty_io_term.c
+++ b/lib/vty_io_term.c
@@ -164,6 +164,8 @@ uty_term_open(int sock_fd, union sockunion *su)
uty_term_write_timeout,
4096) ; /* obuf is required */
+ uty_vout_sync_depth(vio) ; /* vin & vout are at same level */
+
vf->read_timeout = host.vty_timeout_val ; /* current EXEC timeout */
/* Set up the CLI object & initialise */