return -1;
}
- if (cmd->handler) {
+ if (cmd->handler || cmd->handler_rv) {
vshError(ctl, _("command '%1$s' has handler set"), cmd->name);
return -1;
}
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;
* 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,
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;
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 */