summaryrefslogtreecommitdiffstats
path: root/lib/command_execute.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/command_execute.c')
-rw-r--r--lib/command_execute.c125
1 files changed, 45 insertions, 80 deletions
diff --git a/lib/command_execute.c b/lib/command_execute.c
index cc457ba3..cf04bb31 100644
--- a/lib/command_execute.c
+++ b/lib/command_execute.c
@@ -94,6 +94,7 @@ cmd_exec_new(vty vty)
context->dir_cd = qpath_dup(host.cwd) ;
context->dir_home = qpath_dup(host.config_dir) ;
+ context->dir_here = qpath_dup(host.config_dir) ;
switch (vty->type)
{
@@ -107,8 +108,6 @@ cmd_exec_new(vty vty)
context->can_enable = context->node >= ENABLE_NODE ;
context->can_auth_enable = true ;
- context->dir_here = qpath_dup(context->dir_cd) ;
-
break ;
case VTY_SHELL_SERVER:
@@ -123,8 +122,6 @@ cmd_exec_new(vty vty)
context->can_enable = true ;
context->can_auth_enable = false ;
- context->dir_here = qpath_dup(context->dir_cd) ;
-
break ;
case VTY_CONFIG_READ:
@@ -137,8 +134,6 @@ cmd_exec_new(vty vty)
context->can_enable = true ;
context->can_auth_enable = false ;
- context->dir_here = qpath_dup(context->dir_home) ;
-
break ;
default:
@@ -190,7 +185,7 @@ cmd_context_new_save(cmd_context context, qpath file_here)
} ;
/* The inheritance of can_enable is tricky. Will not bequeath can_enable
- * is is not already in ENABLE_NODE or better !
+ * is is not currently in ENABLE_NODE or better !
*/
if (context->node <= ENABLE_NODE)
context->can_enable = false ;
@@ -205,6 +200,10 @@ cmd_context_new_save(cmd_context context, qpath file_here)
*
* Has to free the directories in the context being restored to.
*
+ * Note that can restore any node it likes: if it was enabled, that's fine; if
+ * it was in some config mode, will still have the symbol of power because
+ * only at vin_depth <= 1 is the symbol of power actually released.
+ *
* Returns NULL.
*/
extern cmd_context
@@ -239,10 +238,10 @@ cmd_context_free(cmd_context context, bool copy)
qpath_free(context->dir_here) ;
} ;
- XFREE(MTYPE_CMD_EXEC, context) ; /* sets context = NULL */
+ XFREE(MTYPE_CMD_EXEC, context) ;
} ;
- return context ;
+ return NULL ;
} ;
/*------------------------------------------------------------------------------
@@ -253,8 +252,19 @@ cmd_exec_free(cmd_exec exec)
{
if (exec != NULL)
{
- exec->parsed = cmd_parsed_free(exec->parsed) ;
+ exec->vty = NULL ; /* no longer required. */
+
exec->context = cmd_context_free(exec->context, false) ; /* not a copy */
+ cmd_action_clear(exec->action) ;
+ exec->parsed = cmd_parsed_free(exec->parsed) ;
+
+ if (vty_nexus)
+ exec->cq.mqb = mqb_free(exec->cq.mqb) ;
+ else if (exec->cq.thread != NULL)
+ {
+ thread_cancel(exec->cq.thread) ;
+ exec->cq.thread = NULL ;
+ } ;
XFREE(MTYPE_CMD_EXEC, exec) ;
} ;
@@ -266,50 +276,6 @@ cmd_exec_free(cmd_exec exec)
*
*/
/*------------------------------------------------------------------------------
- * Parse and execute a command.
- *
- * The command is given by vty->buf and vty->node.
- *
- * Uses vty->parsed.
- *
- * -- use exact/completion parsing, as required.
- *
- * -- parse in current node and in ancestors, as required
- *
- * If does not find in any ancestor, return error from current node.
- *
- * -- implement the "do" shortcut, as required
- *
- * If qpthreads_enabled, then may queue the command rather than execute it
- * here.
- *
- * The vty->node may be changed during the execution of the command, and may
- * be returned changed once the command has completed.
- *
- * NB: expects to have free run of everything in the vty structure (except
- * the contents of the vty_io sub-structure) until the command completes.
- */
-#if 0
-extern enum cmd_return_code
-cmd_execute_command(struct vty *vty,
- cmd_parse_type_t type, struct cmd_command **cmd)
-{
- enum cmd_return_code ret ;
-
- /* Try to parse in vty->node or, if required, ancestors thereof. */
- ret = cmd_parse_command(vty->exec->parsed, vty->line, vty->node, type) ;
-
- if (cmd != NULL)
- *cmd = vty->exec->parsed->cmd ; /* for vtysh */
-
- if (ret == CMD_SUCCESS)
- ret = cmd_dispatch(vty, cmd_may_queue) ;
-
- return ret ;
-} ;
-#endif
-
-/*------------------------------------------------------------------------------
* Read configuration from file.
*
* In the qpthreads world this assumes that it is running with the vty
@@ -339,7 +305,7 @@ cmd_read_config(struct vty *vty, cmd_command first_cmd, bool ignore_warning)
{
cmd_exec exec = vty->exec ;
cmd_parsed parsed = exec->parsed ;
- cmd_return_code_t ret;
+ cmd_return_code_t ret, hret ;
ret = CMD_SUCCESS ; /* so far, so good */
@@ -361,11 +327,10 @@ cmd_read_config(struct vty *vty, cmd_command first_cmd, bool ignore_warning)
break ;
ret = vty_cmd_hiatus(vty, ret) ;
- /* for CMD_EOF & CMD_HIATUS only */
- if (ret == CMD_EOF)
- return CMD_SUCCESS ; /* eof on the config file is
- the expected outcome ! */
+ if (ret == CMD_STOP)
+ return CMD_SUCCESS ; /* the expected outcome ! */
+
if (ret != CMD_SUCCESS)
break ;
} ;
@@ -439,18 +404,21 @@ cmd_read_config(struct vty *vty, cmd_command first_cmd, bool ignore_warning)
* CMD_EOF is also impossible -- vty_cmd_fetch_line() or vty_cmd_hiatus()
* can return that, but that will have been dealt with.
*
- * CMD_CLOSE is also impossible -- commands can return that, but that will
- * have been dealt with.
+ * CMD_CLOSE is also impossible -- will have been given to vty_cmd_hiatus(),
+ * which never returns it.
*
* CMD_WAITING is not valid for blocking vio !
*/
- assert(ret != CMD_SUCCESS) ;
- assert(ret != CMD_EMPTY) ;
- assert(ret != CMD_EOF) ;
- assert(ret != CMD_CLOSE) ;
- assert(ret != CMD_WAITING) ;
+ qassert(ret != CMD_SUCCESS) ;
+ qassert(ret != CMD_EMPTY) ;
+ qassert(ret != CMD_EOF) ;
+ qassert(ret != CMD_CLOSE) ;
+ qassert(ret != CMD_WAITING) ;
- vty_cmd_hiatus(vty, ret) ;
+ hret = ret ;
+ do
+ hret = vty_cmd_hiatus(vty, hret) ;
+ while (hret == CMD_IO_ERROR) ;
return ret ;
} ;
@@ -473,13 +441,13 @@ cmd_open_pipes(vty vty)
cmd_parsed parsed = exec->parsed ;
cmd_return_code_t ret ;
vty_io vio ;
- bool sync_depth ;
+ bool after ;
VTY_LOCK() ;
vio = vty->vio ;
ret = CMD_SUCCESS ;
- sync_depth = false ; /* assuming no in pipe */
+ after = false ; /* assuming no in pipe */
/* Deal with any in pipe stuff */
if ((parsed->parts & cmd_part_in_pipe) != 0)
@@ -500,7 +468,7 @@ cmd_open_pipes(vty vty)
qs_free(args) ;
- sync_depth = true ;
+ after = true ;
} ;
/* Deal with any out pipe stuff */
@@ -513,18 +481,15 @@ 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, after) ;
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, after) ;
else if ((parsed->out_pipe & cmd_pipe_dev_null) != 0)
- ret = uty_cmd_open_out_dev_null(vio) ;
+ ret = uty_cmd_open_out_dev_null(vio, after) ;
else
zabort("invalid out pipe state") ;
- if (sync_depth && (ret == CMD_SUCCESS))
- uty_vout_sync_depth(vio) ;
-
qs_free(args) ;
} ;
@@ -540,7 +505,7 @@ cmd_open_pipes(vty vty)
* Returns: CMD_SUCCESS -- it all want very well
* CMD_WARNING -- not so good: warning message sent by vty_out()
* CMD_ERROR -- not so good: warning message sent by vty_out()
- * CMD_CLOSE -- close the current input
+ * CMD_EOF -- close the current input
*
* NB: the distinction between CMD_WARNING and CMD_ERROR is that CMD_WARNING
* may be ignored when reading a configuration file.
@@ -575,7 +540,7 @@ cmd_execute(vty vty)
* If the new node is < CONFIG_NODE, then we will here release the
* symbol of power iff we are at the vin_base !
*
- * If the new node is NULL_NODE, then treat as CMD_CLOSE.
+ * If the new node is NULL_NODE, then treat as CMD_EOF.
*/
if (context->node != parsed->nnode)
{
@@ -583,7 +548,7 @@ cmd_execute(vty vty)
vty_cmd_config_lock_check(vty, context->node) ;
if (context->node == NULL_NODE)
- ret = CMD_CLOSE ;
+ ret = CMD_EOF ;
} ;
/* The command should (no longer) change the vty->node, but if it does,
@@ -596,7 +561,7 @@ cmd_execute(vty vty)
{
/* Enforce restrictions on return codes. */
assert((ret == CMD_WARNING) || (ret == CMD_ERROR)
- || (ret == CMD_CLOSE)) ;
+ || (ret == CMD_EOF)) ;
} ;
return ret ;