+static int run_usage(Jim_Interp *interp, int argc_valid, int argc, Jim_Obj * const *argv)
+{
+ struct command_context *cmd_ctx = current_command_context(interp);
+ char *command;
+ int retval;
+
+ assert(argc_valid >= 1);
+ assert(argc >= argc_valid);
+
+ command = alloc_concatenate_strings(argc_valid, argv);
+ if (!command)
+ return JIM_ERR;
+
+ retval = command_run_linef(cmd_ctx, "usage %s", command);
+ if (retval != ERROR_OK) {
+ LOG_ERROR("unable to execute command \"usage %s\"", command);
+ return JIM_ERR;
+ }
+
+ if (argc_valid == argc)
+ LOG_ERROR("%s: command requires more arguments", command);
+ else {
+ free(command);
+ command = alloc_concatenate_strings(argc - argc_valid, argv + argc_valid);
+ if (!command)
+ return JIM_ERR;
+ LOG_ERROR("invalid subcommand \"%s\"", command);
+ }
+
+ free(command);
+ return retval;
+}
+
+static int command_unknown(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+ const char *cmd_name = Jim_GetString(argv[0], NULL);
+ script_debug(interp, cmd_name, argc, argv);
+
+ struct command_context *cmd_ctx = current_command_context(interp);
+ struct command *c = cmd_ctx->commands;
+ int remaining = command_unknown_find(argc, argv, c, &c);
+ /* if nothing could be consumed, then it's really an unknown command */
+ if (remaining == argc) {
+ const char *cmd = Jim_GetString(argv[0], NULL);
+ LOG_ERROR("Unknown command:\n %s", cmd);
+ return JIM_OK;
+ }
+
+ Jim_Obj *const *start;
+ unsigned count;
+ if (c->handler || c->jim_handler) {
+ /* include the command name in the list */
+ count = remaining + 1;
+ start = argv + (argc - remaining - 1);
+ } else {
+ count = argc - remaining;
+ start = argv;
+ run_usage(interp, count, argc, start);
+ return JIM_ERR;
+ }
+ /* pass the command through to the intended handler */
+ if (c->jim_handler) {
+ if (!command_can_run(cmd_ctx, c))
+ return JIM_ERR;
+
+ interp->cmdPrivData = c->jim_handler_data;
+ return (*c->jim_handler)(interp, count, start);
+ }
+
+ return script_command_run(interp, count, start, c);
+}
+
+static int jim_command_mode(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+ struct command_context *cmd_ctx = current_command_context(interp);
+ enum command_mode mode;
+
+ if (argc > 1) {
+ struct command *c = cmd_ctx->commands;
+ int remaining = command_unknown_find(argc - 1, argv + 1, c, &c);
+ /* if nothing could be consumed, then it's an unknown command */
+ if (remaining == argc - 1) {
+ Jim_SetResultString(interp, "unknown", -1);
+ return JIM_OK;
+ }
+ mode = c->mode;
+ } else
+ mode = cmd_ctx->mode;
+
+ const char *mode_str;
+ switch (mode) {
+ case COMMAND_ANY:
+ mode_str = "any";
+ break;
+ case COMMAND_CONFIG:
+ mode_str = "config";
+ break;
+ case COMMAND_EXEC:
+ mode_str = "exec";
+ break;
+ default:
+ mode_str = "unknown";
+ break;
+ }
+ Jim_SetResultString(interp, mode_str, -1);
+ return JIM_OK;
+}