From 977a6f7fad8d2985e8e898bd8dc7d3d376164e9d Mon Sep 17 00:00:00 2001 From: Amitay Isaacs <amitay@gmail.com> Date: Mon, 11 Nov 2019 17:29:26 +1100 Subject: [PATCH] ctdb-common: Change cmdline implementation to support multiple sections Signed-off-by: Amitay Isaacs <amitay@gmail.com> Reviewed-by: Martin Schwenke <martin@meltin.net> --- ctdb/common/cmdline.c | 134 +++++++++++++++++++++++++++++++----------- 1 file changed, 101 insertions(+), 33 deletions(-) diff --git a/ctdb/common/cmdline.c b/ctdb/common/cmdline.c index eb5361cf61ab..0ce49b8311a3 100644 --- a/ctdb/common/cmdline.c +++ b/ctdb/common/cmdline.c @@ -29,11 +29,16 @@ #define CMDLINE_MAX_LEN 80 +struct cmdline_section { + const char *name; + struct cmdline_command *commands; +}; + struct cmdline_context { const char *prog; struct poptOption *options; - const char *section; - struct cmdline_command *commands; + struct cmdline_section *section; + int num_sections; int max_len; poptContext pc; int argc, arg0; @@ -207,16 +212,51 @@ static bool cmdline_commands_check(struct cmdline_command *commands, static int cmdline_context_destructor(struct cmdline_context *cmdline); +static int cmdline_section_add(struct cmdline_context *cmdline, + const char *name, + struct cmdline_command *commands) +{ + struct cmdline_section *section; + size_t max_len = 0; + bool ok; + + ok = cmdline_commands_check(commands, &max_len); + if (!ok) { + return EINVAL; + } + + section = talloc_realloc(cmdline, + cmdline->section, + struct cmdline_section, + cmdline->num_sections + 1); + if (section == NULL) { + return ENOMEM; + } + + section[cmdline->num_sections] = (struct cmdline_section) { + .name = name, + .commands = commands, + }; + + if (max_len > cmdline->max_len) { + cmdline->max_len = max_len; + } + + cmdline->section = section; + cmdline->num_sections += 1; + + return 0; +} + int cmdline_init(TALLOC_CTX *mem_ctx, const char *prog, struct poptOption *options, - const char *section, + const char *name, struct cmdline_command *commands, struct cmdline_context **result) { struct cmdline_context *cmdline; int ret; - size_t max_len = 0; bool ok; if (prog == NULL) { @@ -228,11 +268,6 @@ int cmdline_init(TALLOC_CTX *mem_ctx, return EINVAL; } - ok = cmdline_commands_check(commands, &max_len); - if (!ok) { - return EINVAL; - } - cmdline = talloc_zero(mem_ctx, struct cmdline_context); if (cmdline == NULL) { return ENOMEM; @@ -249,9 +284,12 @@ int cmdline_init(TALLOC_CTX *mem_ctx, talloc_free(cmdline); return ret; } - cmdline->section = section; - cmdline->commands = commands; - cmdline->max_len = max_len; + + ret = cmdline_section_add(cmdline, name, commands); + if (ret != 0) { + talloc_free(cmdline); + return ret; + } cmdline->argc = 1; cmdline->argv = talloc_array(cmdline, const char *, 2); @@ -326,16 +364,12 @@ static int cmdline_parse_options(struct cmdline_context *cmdline, return 0; } -static int cmdline_match(struct cmdline_context *cmdline) +static int cmdline_match_section(struct cmdline_context *cmdline, + struct cmdline_section *section) { int i; - if (cmdline->argc == 0 || cmdline->argv == NULL) { - cmdline->match_cmd = NULL; - return EINVAL; - } - - for (i=0; cmdline->commands[i].name != NULL; i++) { + for (i=0; section->commands[i].name != NULL; i++) { struct cmdline_command *cmd; char name[CMDLINE_MAX_LEN+1]; size_t len; @@ -343,7 +377,7 @@ static int cmdline_match(struct cmdline_context *cmdline) int n = 0; bool match = false; - cmd = &cmdline->commands[i]; + cmd = §ion->commands[i]; len = strlcpy(name, cmd->name, sizeof(name)); if (len >= sizeof(name)) { D_ERR("Skipping long command '%s'\n", cmd->name); @@ -382,6 +416,25 @@ static int cmdline_match(struct cmdline_context *cmdline) return ENOENT; } +static int cmdline_match(struct cmdline_context *cmdline) +{ + int i, ret = ENOENT; + + if (cmdline->argc == 0 || cmdline->argv == NULL) { + cmdline->match_cmd = NULL; + return EINVAL; + } + + for (i=0; i<cmdline->num_sections; i++) { + ret = cmdline_match_section(cmdline, &cmdline->section[i]); + if (ret == 0) { + break; + } + } + + return ret; +} + int cmdline_parse(struct cmdline_context *cmdline, int argc, const char **argv, @@ -445,38 +498,53 @@ static void cmdline_usage_command(struct cmdline_context *cmdline, printf(" %s\n", cmd->msg_help); } -static void cmdline_usage_full(struct cmdline_context *cmdline) +static void cmdline_usage_section(struct cmdline_context *cmdline, + struct cmdline_section *section) { int i; - poptSetOtherOptionHelp(cmdline->pc, "[<options>] <command> [<args>]"); - poptPrintHelp(cmdline->pc, stdout, 0); - printf("\n"); - if (cmdline->section != NULL) { - printf("%s ", cmdline->section); + + if (section->name != NULL) { + printf("%s ", section->name); } printf("Commands:\n"); - for (i=0; cmdline->commands[i].name != NULL; i++) { - cmdline_usage_command(cmdline, &cmdline->commands[i], true); + for (i=0; section->commands[i].name != NULL; i++) { + cmdline_usage_command(cmdline, §ion->commands[i], true); } } +static void cmdline_usage_full(struct cmdline_context *cmdline) +{ + int i; + + poptSetOtherOptionHelp(cmdline->pc, "[<options>] <command> [<args>]"); + poptPrintHelp(cmdline->pc, stdout, 0); + + for (i=0; i<cmdline->num_sections; i++) { + cmdline_usage_section(cmdline, &cmdline->section[i]); + } +} + void cmdline_usage(struct cmdline_context *cmdline, const char *cmd_name) { struct cmdline_command *cmd = NULL; - int i; + int i, j; if (cmd_name == NULL) { cmdline_usage_full(cmdline); return; } - for (i=0; cmdline->commands[i].name != NULL; i++) { - if (strcmp(cmdline->commands[i].name, cmd_name) == 0) { - cmd = &cmdline->commands[i]; - break; + for (j=0; j<cmdline->num_sections; j++) { + struct cmdline_section *section = &cmdline->section[j]; + + for (i=0; section->commands[i].name != NULL; i++) { + if (strcmp(section->commands[i].name, cmd_name) == 0) { + cmd = §ion->commands[i]; + break; + } } }