summaryrefslogtreecommitdiffstats
path: root/lib/vty_command.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/vty_command.c')
-rw-r--r--lib/vty_command.c102
1 files changed, 87 insertions, 15 deletions
diff --git a/lib/vty_command.c b/lib/vty_command.c
index d195f193..79a8a294 100644
--- a/lib/vty_command.c
+++ b/lib/vty_command.c
@@ -121,6 +121,7 @@ static bool uty_cmd_loop_prepare(vty_io vio) ;
static void uty_cmd_stopping(vty_io vio, bool exeunt) ;
static cmd_return_code_t uty_cmd_hiatus(vty_io vio, cmd_return_code_t ret) ;
static cmd_return_code_t vty_cmd_auth(vty vty, node_type_t* p_next_node) ;
+static void uty_cmd_complete(vty_io vio) ;
static void uty_cmd_out_cancel(vio_vf vf, bool base) ;
static uint uty_show_error_context(vio_fifo ebuf, vio_vf vf) ;
static uint uty_cmd_failed(vty_io vio, cmd_return_code_t ret) ;
@@ -544,8 +545,7 @@ vty_cmd_fetch_line(vty vty)
break ;
case VIN_TERM:
- ret = uty_term_fetch_command_line(vf, exec->action,
- exec->context) ;
+ ret = uty_term_fetch_command_line(vf, exec->action) ;
break ;
case VIN_VTYSH:
@@ -976,8 +976,8 @@ vty_cmd_auth(vty vty, node_type_t* p_next_node)
*
* The command_queue command loop runs until something happens that it
* cannot immediately deal with, at which point it enters "exec_hiatus", and
- * this function is called. The command loop will deal with CMD_SUCCESS and
- * CMD_EMPTY, but otherwise this function must deal with:
+ * this function is called. The command loop will deal with CMD_SUCCESS,
+ * but otherwise this function must deal with:
*
* CMD_HIATUS -- something requires attention, eg:
*
@@ -1010,8 +1010,6 @@ vty_cmd_auth(vty vty, node_type_t* p_next_node)
*
* CMD_SUCCESS -- see below
*
- * CMD_EMPTY -- should not appear, but is treated as CMD_SUCCESS
- *
* anything else -- treated as a command or I/O or other error.
*
* The handling of errors depends on the type of error:
@@ -1180,7 +1178,6 @@ uty_cmd_hiatus(vty_io vio, cmd_return_code_t ret)
switch (ret)
{
case CMD_SUCCESS:
- case CMD_EMPTY:
case CMD_HIATUS:
ret = CMD_SUCCESS ; /* OK */
break ;
@@ -1320,6 +1317,11 @@ uty_cmd_hiatus(vty_io vio, cmd_return_code_t ret)
*
* If the vty is about to be closed, this step ensures that all output
* is tidily dealt with, before uty_close() performs its "final" close.
+ *
+ * If we are also down to the vin_base, then signal that the last base
+ * level command has completed. Need to do this even if the vin_depth
+ * is zero -- so that, if required, the output side will signal that
+ * all I/O is complete.
*/
if (vio->vout_depth == 1)
{
@@ -1327,6 +1329,8 @@ uty_cmd_hiatus(vty_io vio, cmd_return_code_t ret)
{
/* Once we have cleared the output buffer etc., clear the cancel
* flag and output "^C" to show what has happened.
+ *
+ * Also, for VTY_TERMINAL, clears the cos_cancel down to cos_active.
*/
uty_cmd_out_cancel(vio->vout, true) ; /* stop output & pipe return
* is vout_base */
@@ -1350,6 +1354,9 @@ uty_cmd_hiatus(vty_io vio, cmd_return_code_t ret)
ret = uty_cmd_out_push(vio->vout, false) ;
+ if (vio->vin_depth <= 1)
+ uty_cmd_complete(vio) ;
+
if (ret != CMD_SUCCESS)
return ret ; /* CMD_WAITING or CMD_IO_ERROR */
} ;
@@ -1688,19 +1695,27 @@ vty_cmd_success(vty vty)
vty_io vio ;
VTY_LOCK() ;
- vio = vty->vio ; /* once locked */
+ vio = vty->vio ; /* once locked */
ret = vio->signal ; /* signal can interrupt */
- if (ret == CMD_SUCCESS)
+ /* out_suppress is set only when is VTY_CONFIG_READ and the output is not
+ * required -- not even if there is a signal outstanding.
+ *
+ * NB: we do not need to worry about uty_cmd_complete() for VTY_CONFIG_READ.
+ *
+ * If not interrupted by a signal, push anything there is to push, and
+ * if we are at the base stack level, signal uty_cmd_complete().
+ */
+ if (vty->exec->out_suppress)
+ vio_fifo_back_to_end_mark(vio->obuf, true) ; /* keep end mark */
+ else if (ret == CMD_SUCCESS)
{
if (!vio_fifo_tail_empty(vio->obuf))
- {
- if (!vty->exec->out_suppress)
- ret = uty_cmd_out_push(vio->vout, false) ; /* not final */
- else
- vio_fifo_back_to_end_mark(vio->obuf, true) ; /* keep end mark */
- } ;
+ ret = uty_cmd_out_push(vio->vout, false) ; /* not final */
+
+ if ((vio->vin_depth == 1) && (vio->vout_depth == 1))
+ uty_cmd_complete(vio) ;
} ;
VTY_UNLOCK() ;
@@ -1709,6 +1724,60 @@ vty_cmd_success(vty vty)
} ;
/*------------------------------------------------------------------------------
+ * A command has completed -- for whatever reason -- no further output will
+ * appear, so the output buffer can now emptied out (including any trailing
+ * line without a line ending) and when that finishes the output is, again,
+ * idle.
+ *
+ * This is *only* when is at the base vin and vout level (or if vin is closed
+ * and is at base vout).
+ *
+ * For VTY_TERMINAL, the completion of all output associated with a command
+ * signals the time to start fetching the next one.
+ *
+ * For VTY_SHELL_SERVER, ditto.
+ *
+ * For VTY_CONFIG_READ, nothing is required.
+ */
+static void
+uty_cmd_complete(vty_io vio)
+{
+ VTY_ASSERT_LOCKED() ;
+
+ qassert((vio->vin_depth <= 1) && (vio->vout_depth == 1)) ;
+
+ switch (vio->vin->vin_type)
+ {
+ case VIN_NONE:
+ zabort("invalid vin_none") ;
+ break ;
+
+ case VIN_TERM:
+ uty_term_cmd_complete(vio->vin, vio->vty->exec->context) ;
+ break ;
+
+ case VIN_VTYSH:
+ /* Signal end of command return */
+ break ;
+
+ case VIN_FILE:
+ break ;
+
+ case VIN_PIPE:
+ break ;
+
+ case VIN_CONFIG:
+ break ; /* do nothing ! */
+
+ case VIN_DEV_NULL:
+ break ;
+
+ default:
+ zabort("unknown vin_type") ;
+ } ;
+} ;
+
+/*------------------------------------------------------------------------------
* If there is anything after the end_mark, push it to be written, now.
*
* This is used by configuration file output, which outputs to the fifo and
@@ -1858,6 +1927,9 @@ uty_cmd_out_cancel(vio_vf vf, bool base)
*/
vio_fifo_clear(vf->obuf, false) ;
+ if (vf->vout_type == VOUT_TERM)
+ uty_term_out_cancelled(vf) ;
+
if (!base && (vf->vout_state == vf_open))
vf->vout_state = vf_end ;