From: Alan T. DeKok Date: Fri, 3 Aug 2018 20:32:47 +0000 (-0400) Subject: add place-holder for commands X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=d69abe7abc9453c614c2aea40e6bee29c0bebbdd;p=thirdparty%2Ffreeradius-server.git add place-holder for commands so that if we add 100 commands of "... module foo", the help text will only show help for "... module STRING ..." which is much more polite than showing hundreds of possible commands --- diff --git a/src/bin/radmin.c b/src/bin/radmin.c index f64e13de9e1..e5fd55340c9 100644 --- a/src/bin/radmin.c +++ b/src/bin/radmin.c @@ -421,12 +421,19 @@ static int cmd_exit(UNUSED FILE *fp, UNUSED FILE *fp_err, UNUSED void *ctx, UNUS static int cmd_help(FILE *fp, UNUSED FILE *fp_err, UNUSED void *ctx, fr_cmd_info_t const *info) { int max = 1; + int options = FR_COMMAND_OPTION_HELP; - if ((info->argc > 0) && (strcmp(info->argv[0], "all") == 0)) { - max = CMD_MAX_ARGV; + if (info->argc > 0) { + if (strcmp(info->argv[0], "all") == 0) { + max = CMD_MAX_ARGV; + } + else if (strcmp(info->argv[0], "commands") == 0) { + max = CMD_MAX_ARGV; + options = FR_COMMAND_OPTION_NONE; + } } - fr_command_list(fp, max, radmin_cmd, FR_COMMAND_OPTION_NONE); + fr_command_list(fp, max, radmin_cmd, options); return 0; } @@ -781,7 +788,7 @@ static fr_cmd_table_t cmd_table[] = { { .name = "help", - .syntax = "[all]", + .syntax = "[(all|commands)]", .func = cmd_help, .help = "Display list of commands and their help text.", .read_only = true diff --git a/src/lib/server/command.c b/src/lib/server/command.c index 1f8fcd7bdb6..ad3304ae64a 100644 --- a/src/lib/server/command.c +++ b/src/lib/server/command.c @@ -64,6 +64,7 @@ struct fr_cmd_t { bool read_only; bool intermediate; //!< intermediate commands can't have callbacks bool live; //!< is this entry live? + bool added_name; //!< was this name added? }; @@ -702,8 +703,11 @@ int fr_command_add(TALLOC_CTX *talloc_ctx, fr_cmd_t **head, char const *name, vo int argc = 0, depth = 0; fr_cmd_argv_t *syntax_argv; + /* + * This is a place-holder for tab expansion. + */ if (!table->name) { - fr_strerror_printf("A name MUST be specified for table with parent %s syntax %s", table->parent, table->syntax); + fr_strerror_printf("A name MUST be specified."); return -1; } @@ -749,6 +753,7 @@ int fr_command_add(TALLOC_CTX *talloc_ctx, fr_cmd_t **head, char const *name, vo cmd = fr_command_find(start, parents[i], &insert); if (!cmd) { cmd = fr_command_alloc(talloc_ctx, insert, parents[i]); + cmd->live = true; } if (!cmd->intermediate) { @@ -772,9 +777,37 @@ int fr_command_add(TALLOC_CTX *talloc_ctx, fr_cmd_t **head, char const *name, vo * Add an intermediate name, e.g. "network X" */ if (table->add_name) { + fr_cmd_t **added_insert; + + /* + * See if we need to create the automatic + * place-holder command for help text. + */ + cmd = fr_command_find(start, "STRING", &added_insert); + if (!cmd) { + cmd = fr_command_alloc(talloc_ctx, added_insert, "STRING"); + } + + /* + * In the place-holders children, see if we need + * to add this subcommand. + */ + cmd = fr_command_find(&(cmd->child), table->name, &added_insert); + if (!cmd) { + cmd = fr_command_alloc(talloc_ctx, added_insert, table->name); + + if (table->syntax) cmd->syntax = talloc_strdup(cmd, table->syntax); + if (table->help) cmd->help = talloc_strdup(cmd, table->help); + } + + /* + * Now insert or add the extended name to the command hierarchy. + */ cmd = fr_command_find(start, name, &insert); if (!cmd) { cmd = fr_command_alloc(talloc_ctx, insert, name); + cmd->added_name = true; + cmd->live = true; } start = &(cmd->child); @@ -1442,7 +1475,7 @@ static void fr_command_list_node(FILE *fp, fr_cmd_t *cmd, int depth, char const fprintf(fp, "%s %s\n", cmd->name, cmd->syntax); } - if (cmd->help) { + if (cmd->help && ((options & FR_COMMAND_OPTION_HELP) != 0)) { fprintf(fp, "\t%s\n", cmd->help); } } @@ -1452,6 +1485,10 @@ static void fr_command_list_internal(FILE *fp, fr_cmd_t *head, int depth, int ma fr_cmd_t *cmd; for (cmd = head; cmd != NULL; cmd = cmd->next) { + if (cmd->added_name) continue; + + // We DO print out commands are !cmd->live + if (cmd->child && ((depth + 1) < max_depth)) { argv[depth] = cmd->name; fr_command_list_internal(fp, cmd->child, depth + 1, max_depth, argv, options); @@ -2037,6 +2074,14 @@ int fr_command_str_to_argv(fr_cmd_t *head, fr_cmd_info_t *info, char const *text while (cmd) { SKIP_SPACES; + /* + * Skip commands which we shouldn't know about... + */ + if (!cmd->live) { + cmd = cmd->next; + continue; + } + /* * End of the input. Tab expand everything here. */ @@ -2476,12 +2521,22 @@ int fr_command_complete(fr_cmd_t *head, char const *text, int start, while (cmd) { SKIP_SPACES; + /* + * Skip commands which we shouldn't know about... + */ + if (!cmd->live) { + cmd = cmd->next; + continue; + } + /* * End of the input. Tab expand everything here. */ if (!*word) { expand: while (cmd && (count < max_expansions)) { + if (!cmd->live) goto next; + SKIP_NAME(cmd->name); /* @@ -2492,6 +2547,8 @@ int fr_command_complete(fr_cmd_t *head, char const *text, int start, expansions[count] = strdup(cmd->name); count++; } + + next: cmd = cmd->next; } diff --git a/src/lib/server/command.h b/src/lib/server/command.h index 18b52eae3f1..e512888ea21 100644 --- a/src/lib/server/command.h +++ b/src/lib/server/command.h @@ -87,6 +87,7 @@ int fr_command_clear(int new_argc, fr_cmd_info_t *info) CC_HINT(nonnull); #define FR_COMMAND_OPTION_NONE (0) #define FR_COMMAND_OPTION_LIST_CHILD (1 << 0) #define FR_COMMAND_OPTION_NAME (1 << 1) +#define FR_COMMAND_OPTION_HELP (1 << 2) void fr_command_list(FILE *fp, int max_depth, fr_cmd_t *head, int options); void fr_command_info_init(TALLOC_CTX *ctx, fr_cmd_info_t *info); diff --git a/src/lib/server/module.c b/src/lib/server/module.c index eb8e9f50c04..c84450aa43a 100644 --- a/src/lib/server/module.c +++ b/src/lib/server/module.c @@ -40,6 +40,7 @@ static _Thread_local rbtree_t *module_thread_inst_tree; static TALLOC_CTX *instance_ctx = NULL; static int module_instantiate(CONF_SECTION *root, char const *name); +static fr_cmd_table_t cmd_module_table[]; /** Initialise a module specific exfile handle * @@ -648,6 +649,12 @@ static int _module_instantiate(void *instance, UNUSED void *ctx) if (mi->instantiated) return 0; + if (fr_command_register_hook(mi->name, mi, cmd_module_table) < 0) { + ERROR("Failed registering radmin commands for module %s - %s", + mi->name, fr_strerror()); + return -1; + } + /* * Now that ALL modules are instantiated, and ALL xlats * are defined, go compile the config items marked as XLAT. @@ -726,16 +733,9 @@ static int module_instantiate(CONF_SECTION *root, char const *name) } -static int cmd_show_module_config(FILE *fp, FILE *fp_err, void *ctx, fr_cmd_info_t const *info) +static int cmd_show_module_config(FILE *fp, UNUSED FILE *fp_err, void *ctx, UNUSED fr_cmd_info_t const *info) { - module_instance_t *mi; - CONF_SECTION *modules = (CONF_SECTION *) ctx; - - mi = cf_data_value(cf_data_find(modules, module_instance_t, info->argv[0])); - if (!mi) { - fprintf(fp_err, "No such module '%s'\n", info->argv[0]); - return -1; - } + module_instance_t *mi = ctx; rad_assert(mi->dl_inst->conf != NULL); @@ -804,17 +804,9 @@ static int cmd_show_module_list(FILE *fp, UNUSED FILE *fp_err, void *ctx, UNUSED return 0; } - -static int cmd_show_module_status(FILE *fp, FILE *fp_err, void *ctx, fr_cmd_info_t const *info) +static int cmd_show_module_status(FILE *fp, UNUSED FILE *fp_err, void *ctx, UNUSED fr_cmd_info_t const *info) { - module_instance_t *mi; - CONF_SECTION *modules = (CONF_SECTION *) ctx; - - mi = cf_data_value(cf_data_find(modules, module_instance_t, info->argv[0])); - if (!mi) { - fprintf(fp_err, "No such module '%s'\n", info->argv[0]); - return -1; - } + module_instance_t *mi = ctx; if (!mi->force) { fprintf(fp, "alive\n"); @@ -826,18 +818,11 @@ static int cmd_show_module_status(FILE *fp, FILE *fp_err, void *ctx, fr_cmd_info return 0; } -static int cmd_set_module_status(UNUSED FILE *fp, FILE *fp_err, void *ctx, fr_cmd_info_t const *info) +static int cmd_set_module_status(UNUSED FILE *fp, UNUSED FILE *fp_err, void *ctx, fr_cmd_info_t const *info) { - module_instance_t *mi; - CONF_SECTION *modules = (CONF_SECTION *) ctx; + module_instance_t *mi = ctx; rlm_rcode_t rcode; - mi = cf_data_value(cf_data_find(modules, module_instance_t, info->argv[0])); - if (!mi) { - fprintf(fp_err, "No such module '%s'\n", info->argv[0]); - return -1; - } - if (strcmp(info->argv[1], "alive") == 0) { mi->force = false; return 0; @@ -852,40 +837,56 @@ static int cmd_set_module_status(UNUSED FILE *fp, FILE *fp_err, void *ctx, fr_cm return 0; } -static fr_cmd_table_t cmd_table[] = { + +static fr_cmd_table_t cmd_module_table[] = { { - .parent = "show", - .name = "module", - .help = "Show information about modules.", + .parent = "show module", + .add_name = true, + .name = "status", + .func = cmd_show_module_status, + .help = "Show the status of a particular module.", .read_only = true, }, { .parent = "show module", - .name = "list", - .func = cmd_show_module_list, - .help = "Show the list of modules loaded in the server.", + .add_name = true, + .name = "config", + .func = cmd_show_module_config, + .help = "Show configuration for a module", + // @todo - do tab expand, by walking over the whole module list... .read_only = true, }, { - .parent = "show config", + .parent = "set module", + .add_name = true, + .name = "status", + .syntax = "(alive|ok|fail|reject|handled|invalid|userlock|notfound|noop|updated)", + .func = cmd_set_module_status, + .help = "Change module status to fixed value.", + .read_only = false, + }, + + CMD_TABLE_END +}; + + +static fr_cmd_table_t cmd_table[] = { + { + .parent = "show", .name = "module", - .syntax = "STRING", - .func = cmd_show_module_config, + .help = "Show information about modules.", .tab_expand = module_name_tab_expand, - .help = "show module config NAME", - // @todo - do tab expand, by walking over the whole module list... .read_only = true, }, + // @todo - what if there's a module called "list" ? { .parent = "show module", - .name = "status", - .syntax = "STRING", - .func = cmd_show_module_status, - .tab_expand = module_name_tab_expand, - .help = "show module status NAME", + .name = "list", + .func = cmd_show_module_list, + .help = "Show the list of modules loaded in the server.", .read_only = true, }, @@ -893,17 +894,10 @@ static fr_cmd_table_t cmd_table[] = { .parent = "set", .name = "module", .help = "Change module settings.", + .tab_expand = module_name_tab_expand, .read_only = false, }, - { - .parent = "set module", - .name = "status", - .syntax = "STRING (alive|ok|fail|reject|handled|invalid|userlock|notfound|noop|updated)", - .func = cmd_set_module_status, - .help = "Change module status to fixed value.", - .read_only = false, - }, CMD_TABLE_END };