]> git.ipfire.org Git - thirdparty/libvirt.git/commitdiff
vsh: Add support for commands with more return values
authorPeter Krempa <pkrempa@redhat.com>
Tue, 3 Jun 2025 15:25:36 +0000 (17:25 +0200)
committerPeter Krempa <pkrempa@redhat.com>
Thu, 12 Jun 2025 08:17:03 +0000 (10:17 +0200)
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 <pkrempa@redhat.com>
Reviewed-by: Ján Tomko <jtomko@redhat.com>
tools/vsh.c
tools/vsh.h

index 497b7ec63177e3cfca038b6b324405a4b9ea4bc2..4aacc5feacc63a9730527b75b0871818b7696e42 100644 (file)
@@ -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;
index 284da36e3274549560502be89e0ba88addbc15ff..bd2494e899a663758589785239c23aee3a8b9dbf 100644 (file)
@@ -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 */