From: Peter Krempa <pkre...@redhat.com>

Add a new handler callback for command handlers which will want to
return more than just EXIT_SUCCESS/EXIT_FAILURE.

The new handler allows returning integers. Any negative values are
converted to EXIT_FAILURE, other values are returned as reported in
cases where we forward the command state (non-interactive usage) as
return value of the virt shell program.

Signed-off-by: Peter Krempa <pkre...@redhat.com>
---
 tools/vsh.c | 25 ++++++++++++++++++++-----
 tools/vsh.h |  1 +
 2 files changed, 21 insertions(+), 5 deletions(-)

diff --git a/tools/vsh.c b/tools/vsh.c
index 497b7ec631..4aacc5feac 100644
--- a/tools/vsh.c
+++ b/tools/vsh.c
@@ -293,7 +293,7 @@ vshCmddefCheckInternals(vshControl *ctl,
             return -1;
         }

-        if (cmd->handler) {
+        if (cmd->handler || cmd->handler_rv) {
             vshError(ctl, _("command '%1$s' has handler set"), cmd->name);
             return -1;
         }
@@ -323,6 +323,11 @@ vshCmddefCheckInternals(vshControl *ctl,
         return -1;
     }

+    if (!!cmd->handler + !!cmd->handler_rv != 1) {
+        vshError(ctl, _("command '%1$s' must have exactly one of the handler 
callbacks set"), cmd->name);
+        return -1;
+    }
+
     if (!cmd->opts)
         return 0;

@@ -1350,6 +1355,9 @@ vshBlockJobOptionBandwidth(vshControl *ctl,
  * which return boolean are converted as:
  *   true -> EXIT_SUCCESS
  *   false -> EXIT_FAILURE
+ * Return values from command handlers returning integers are converted as:
+ *   '< 0' -> EXIT_FAILURE
+ *   others -> use value returned by handler callback.
  */
 int
 vshCommandRun(vshControl *ctl,
@@ -1366,10 +1374,17 @@ vshCommandRun(vshControl *ctl,

         if ((cmd->def->flags & VSH_CMD_FLAG_NOCONNECT) ||
             (hooks && hooks->connHandler && hooks->connHandler(ctl))) {
-            if (cmd->def->handler(ctl, cmd))
-                ret = EXIT_SUCCESS;
-            else
-                ret = EXIT_FAILURE;
+            if (cmd->def->handler_rv) {
+                ret = cmd->def->handler_rv(ctl, cmd);
+
+                if (ret < 0)
+                    ret = EXIT_FAILURE;
+            } else {
+                if (cmd->def->handler(ctl, cmd))
+                    ret = EXIT_SUCCESS;
+                else
+                    ret = EXIT_FAILURE;
+            }
         } else {
             /* connection is not usable, return error */
             ret = EXIT_FAILURE;
diff --git a/tools/vsh.h b/tools/vsh.h
index 284da36e32..bd2494e899 100644
--- a/tools/vsh.h
+++ b/tools/vsh.h
@@ -167,6 +167,7 @@ enum {
 struct _vshCmdDef {
     const char *name;           /* name of command, or NULL for list end */
     bool (*handler) (vshControl *, const vshCmd *);    /* command handler */
+    int (*handler_rv) (vshControl *, const vshCmd *); /* command handler - 
allows return codes */
     const vshCmdOptDef *opts;   /* definition of command options */
     const vshCmdInfo *info;     /* details about command */
     unsigned int flags;         /* bitwise OR of VSH_CMD_FLAG */
-- 
2.49.0

Reply via email to