From: Peter Krempa Date: Tue, 3 Jun 2025 15:25:36 +0000 (+0200) Subject: vsh: Add support for commands with more return values X-Git-Tag: v11.5.0-rc1~41 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=71e276ed1da2525264a7fb4cc4df6d6777b2e1ca;p=thirdparty%2Flibvirt.git vsh: Add support for commands with more return values 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 Reviewed-by: Ján Tomko --- 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 */