]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
add place-holder for commands
authorAlan T. DeKok <aland@freeradius.org>
Fri, 3 Aug 2018 20:32:47 +0000 (16:32 -0400)
committerAlan T. DeKok <aland@freeradius.org>
Fri, 3 Aug 2018 20:32:47 +0000 (16:32 -0400)
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

src/bin/radmin.c
src/lib/server/command.c
src/lib/server/command.h
src/lib/server/module.c

index f64e13de9e1bd8a5be82e9ed8975d18a0f03a533..e5fd55340c905690cedaa0f65a5e1e62bb5193b5 100644 (file)
@@ -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
index 1f8fcd7bdb690cbd44c47aa532060ada84a3f513..ad3304ae64a0d6b91879149040e142dd21946219 100644 (file)
@@ -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;
                        }
 
index 18b52eae3f13e6e89bccd0aa6e156faf49e4a971..e512888ea2195b28150ecaa4f0650ea00884e907 100644 (file)
@@ -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);
index eb8e9f50c04783b25519268d84538e4c22461ba8..c84450aa43a69c34d7b1ca9a4f5ad5a188298e75 100644 (file)
@@ -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
 };