summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBill Richardson <wfrichar@chromium.org>2015-03-11 11:21:47 -0700
committerChromeOS Commit Bot <chromeos-commit-bot@chromium.org>2015-03-18 23:07:36 +0000
commit01466d36afd10b3947de475bc9b4fb23848e81ce (patch)
tree331e22905fc988641f111cdb5bd49b7970207290
parent49a422fab9afb3f013ee6115738c7e13d9ec8191 (diff)
downloadvboot-01466d36afd10b3947de475bc9b4fb23848e81ce.tar.gz
futility: Let each command provide its own help
Instead of a separate help function for each command, let's just require each command to handle a --help option. This will make it easier to layer the commands (for example, "sign" could have several subcommand variants, each with its own help). BUG=none BRANCH=none TEST=make runtests I also compared the result of running "futility help CMD" before and after this change. The help still shows up correctly. Change-Id: I5c58176f32b41b0a2c2b8f0afb17dddd80fddc70 Signed-off-by: Bill Richardson <wfrichar@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/260495 Reviewed-by: Randall Spangler <rspangler@chromium.org>
-rw-r--r--Makefile2
-rw-r--r--futility/cmd_create.c11
-rw-r--r--futility/cmd_dump_fmap.c19
-rw-r--r--futility/cmd_dump_kernel_config.c15
-rw-r--r--futility/cmd_gbb_utility.c12
-rw-r--r--futility/cmd_load_fmap.c14
-rw-r--r--futility/cmd_pcr.c19
-rw-r--r--futility/cmd_show.c14
-rw-r--r--futility/cmd_sign.c12
-rw-r--r--futility/cmd_vbutil_firmware.c11
-rw-r--r--futility/cmd_vbutil_kernel.c11
-rw-r--r--futility/cmd_vbutil_key.c11
-rw-r--r--futility/cmd_vbutil_keyblock.c11
-rw-r--r--futility/futility.c94
-rw-r--r--futility/futility.h10
15 files changed, 172 insertions, 94 deletions
diff --git a/Makefile b/Makefile
index 14fd69cd..28d302e0 100644
--- a/Makefile
+++ b/Makefile
@@ -1422,7 +1422,7 @@ TEST_DEPS += ${TEST_OBJS:%.o=%.o.d}
SRCDIRPAT=$(subst /,\/,${SRCDIR}/)
# Note: vboot 2.0 is deprecated, so don't index those files
-${BUILD}/cscope.files: test_setup
+${BUILD}/cscope.files: all test_setup
${Q}rm -f $@
${Q}cat ${ALL_DEPS} | tr -d ':\\' | tr ' ' '\012' | \
grep -v /lib20/ | \
diff --git a/futility/cmd_create.c b/futility/cmd_create.c
index 6138f428..c919eab3 100644
--- a/futility/cmd_create.c
+++ b/futility/cmd_create.c
@@ -31,6 +31,7 @@ enum {
OPT_DESC,
OPT_ID,
OPT_HASH_ALG,
+ OPT_HELP,
};
#define DEFAULT_VERSION 1
@@ -48,6 +49,7 @@ static const struct option long_opts[] = {
{"desc", 1, 0, OPT_DESC},
{"id", 1, 0, OPT_ID},
{"hash_alg", 1, 0, OPT_HASH_ALG},
+ {"help", 0, 0, OPT_HELP},
{NULL, 0, 0, 0}
};
@@ -331,6 +333,9 @@ static int do_create(int argc, char *argv[])
errorcnt++;
}
break;
+ case OPT_HELP:
+ print_help(argc, argv);
+ return !!errorcnt;
case '?':
if (optopt)
@@ -406,7 +411,5 @@ static int do_create(int argc, char *argv[])
return r;
}
-DECLARE_FUTIL_COMMAND(create, do_create,
- VBOOT_VERSION_ALL,
- "Create a keypair from an RSA .pem file",
- print_help);
+DECLARE_FUTIL_COMMAND(create, do_create, VBOOT_VERSION_ALL,
+ "Create a keypair from an RSA .pem file");
diff --git a/futility/cmd_dump_fmap.c b/futility/cmd_dump_fmap.c
index e57bbf7c..b512fdca 100644
--- a/futility/cmd_dump_fmap.c
+++ b/futility/cmd_dump_fmap.c
@@ -5,6 +5,7 @@
*/
#include <errno.h>
#include <fcntl.h>
+#include <getopt.h>
#include <inttypes.h>
#include <stdint.h>
#include <stdio.h>
@@ -411,6 +412,13 @@ static void print_help(int argc, char *argv[])
printf(usage, argv[0]);
}
+enum {
+ OPT_HELP = 1000,
+};
+static const struct option long_opts[] = {
+ {"help", 0, 0, OPT_HELP},
+ {NULL, 0, 0, 0}
+};
static int do_dump_fmap(int argc, char *argv[])
{
int c;
@@ -421,7 +429,7 @@ static int do_dump_fmap(int argc, char *argv[])
int retval = 1;
opterr = 0; /* quiet, you */
- while ((c = getopt(argc, argv, ":xpFhH")) != -1) {
+ while ((c = getopt_long(argc, argv, ":xpFhH", long_opts, 0)) != -1) {
switch (c) {
case 'x':
opt_extract = 1;
@@ -439,6 +447,9 @@ static int do_dump_fmap(int argc, char *argv[])
opt_format = FMT_HUMAN;
opt_overlap++;
break;
+ case OPT_HELP:
+ print_help(argc, argv);
+ return 0;
case '?':
fprintf(stderr, "%s: unrecognized switch: -%c\n",
argv[0], optopt);
@@ -510,7 +521,5 @@ static int do_dump_fmap(int argc, char *argv[])
return retval;
}
-DECLARE_FUTIL_COMMAND(dump_fmap, do_dump_fmap,
- VBOOT_VERSION_ALL,
- "Display FMAP contents from a firmware image",
- print_help);
+DECLARE_FUTIL_COMMAND(dump_fmap, do_dump_fmap, VBOOT_VERSION_ALL,
+ "Display FMAP contents from a firmware image");
diff --git a/futility/cmd_dump_kernel_config.c b/futility/cmd_dump_kernel_config.c
index d1a91fdc..a46a19d1 100644
--- a/futility/cmd_dump_kernel_config.c
+++ b/futility/cmd_dump_kernel_config.c
@@ -15,10 +15,12 @@
enum {
OPT_KLOADADDR = 1000,
+ OPT_HELP,
};
static const struct option long_opts[] = {
{"kloadaddr", 1, NULL, OPT_KLOADADDR},
+ {"help", 0, 0, OPT_HELP},
{NULL, 0, NULL, 0}
};
@@ -29,7 +31,7 @@ static void print_help(int argc, char *argv[])
"KERNEL_PARTITION\n\n", argv[0]);
}
-static int do_dump_kernel_config(int argc, char *argv[])
+static int do_dump_kern_cfg(int argc, char *argv[])
{
char *infile = NULL;
char *config = NULL;
@@ -58,6 +60,10 @@ static int do_dump_kernel_config(int argc, char *argv[])
parse_error = 1;
}
break;
+
+ case OPT_HELP:
+ print_help(argc, argv);
+ return 0;
}
}
@@ -87,7 +93,6 @@ static int do_dump_kernel_config(int argc, char *argv[])
return 0;
}
-DECLARE_FUTIL_COMMAND(dump_kernel_config, do_dump_kernel_config,
- VBOOT_VERSION_ALL,
- "Prints the kernel command line",
- print_help);
+DECLARE_FUTIL_COMMAND(dump_kernel_config, do_dump_kern_cfg, VBOOT_VERSION_ALL,
+ "Prints the kernel command line");
+
diff --git a/futility/cmd_gbb_utility.c b/futility/cmd_gbb_utility.c
index 1053eb2a..df0a51db 100644
--- a/futility/cmd_gbb_utility.c
+++ b/futility/cmd_gbb_utility.c
@@ -60,6 +60,7 @@ enum {
OPT_HWID = 1000,
OPT_FLAGS,
OPT_DIGEST,
+ OPT_HELP,
};
/* Command line options */
@@ -75,6 +76,7 @@ static struct option long_opts[] = {
{"hwid", 0, NULL, OPT_HWID},
{"flags", 0, NULL, OPT_FLAGS},
{"digest", 0, NULL, OPT_DIGEST},
+ {"help", 0, NULL, OPT_HELP},
{NULL, 0, NULL, 0},
};
@@ -410,6 +412,10 @@ static int do_gbb_utility(int argc, char *argv[])
case OPT_DIGEST:
sel_digest = 1;
break;
+ case OPT_HELP:
+ print_help(argc, argv);
+ return !!errorcnt;
+
case '?':
errorcnt++;
if (optopt)
@@ -637,7 +643,5 @@ static int do_gbb_utility(int argc, char *argv[])
return !!errorcnt;
}
-DECLARE_FUTIL_COMMAND(gbb_utility, do_gbb_utility,
- VBOOT_VERSION_ALL,
- "Manipulate the Google Binary Block (GBB)",
- print_help);
+DECLARE_FUTIL_COMMAND(gbb_utility, do_gbb_utility, VBOOT_VERSION_ALL,
+ "Manipulate the Google Binary Block (GBB)");
diff --git a/futility/cmd_load_fmap.c b/futility/cmd_load_fmap.c
index 7522759d..897a0850 100644
--- a/futility/cmd_load_fmap.c
+++ b/futility/cmd_load_fmap.c
@@ -44,8 +44,12 @@ static void print_help(int argc, char *argv[])
printf(usage, argv[0], argv[0]);
}
+enum {
+ OPT_HELP = 1000,
+};
static const struct option long_opts[] = {
/* name hasarg *flag val */
+ {"help", 0, NULL, OPT_HELP},
{NULL, 0, NULL, 0},
};
static char *short_opts = ":o:";
@@ -105,6 +109,9 @@ static int do_load_fmap(int argc, char *argv[])
case 'o':
outfile = optarg;
break;
+ case OPT_HELP:
+ print_help(argc, argv);
+ return !!errorcnt;
case '?':
if (optopt)
fprintf(stderr, "Unrecognized option: -%c\n",
@@ -198,7 +205,6 @@ done_file:
return !!errorcnt;
}
-DECLARE_FUTIL_COMMAND(load_fmap, do_load_fmap,
- VBOOT_VERSION_ALL,
- "Replace the contents of specified FMAP areas",
- print_help);
+DECLARE_FUTIL_COMMAND(load_fmap, do_load_fmap, VBOOT_VERSION_ALL,
+ "Replace the contents of specified FMAP areas");
+
diff --git a/futility/cmd_pcr.c b/futility/cmd_pcr.c
index 0de234dc..241bfb2f 100644
--- a/futility/cmd_pcr.c
+++ b/futility/cmd_pcr.c
@@ -96,7 +96,13 @@ static void print_digest(const uint8_t *buf, int len)
printf("%02x", buf[i]);
}
-
+enum {
+ OPT_HELP = 1000,
+};
+static const struct option long_opts[] = {
+ {"help", 0, 0, OPT_HELP},
+ {NULL, 0, 0, 0}
+};
static int do_pcr(int argc, char *argv[])
{
uint8_t accum[SHA256_DIGEST_SIZE * 2];
@@ -109,7 +115,7 @@ static int do_pcr(int argc, char *argv[])
int i;
opterr = 0; /* quiet, you */
- while ((i = getopt(argc, argv, ":i2")) != -1) {
+ while ((i = getopt_long(argc, argv, ":i2", long_opts, NULL)) != -1) {
switch (i) {
case 'i':
opt_init = 1;
@@ -118,6 +124,9 @@ static int do_pcr(int argc, char *argv[])
digest_alg = SHA256_DIGEST_ALGORITHM;
digest_size = SHA256_DIGEST_SIZE;
break;
+ case OPT_HELP:
+ print_help(argc, argv);
+ return !!errorcnt;
case '?':
if (optopt)
fprintf(stderr, "Unrecognized option: -%c\n",
@@ -181,7 +190,5 @@ static int do_pcr(int argc, char *argv[])
return 0;
}
-DECLARE_FUTIL_COMMAND(pcr, do_pcr,
- VBOOT_VERSION_ALL,
- "Simulate a TPM PCR extension operation",
- print_help);
+DECLARE_FUTIL_COMMAND(pcr, do_pcr, VBOOT_VERSION_ALL,
+ "Simulate a TPM PCR extension operation");
diff --git a/futility/cmd_show.c b/futility/cmd_show.c
index 660bbcb2..e24e7cf7 100644
--- a/futility/cmd_show.c
+++ b/futility/cmd_show.c
@@ -557,6 +557,7 @@ int futil_cb_show_begin(struct futil_traverse_state_s *state)
enum no_short_opts {
OPT_PADDING = 1000,
+ OPT_HELP,
};
static const char usage[] = "\n"
@@ -597,6 +598,7 @@ static const struct option long_opts[] = {
{"fv", 1, 0, 'f'},
{"pad", 1, NULL, OPT_PADDING},
{"verify", 0, &option.strict, 1},
+ {"help", 0, NULL, OPT_HELP},
{NULL, 0, NULL, 0},
};
static char *short_opts = ":f:k:t";
@@ -667,6 +669,9 @@ static int do_show(int argc, char *argv[])
errorcnt++;
}
break;
+ case OPT_HELP:
+ print_help(argc, argv);
+ return !!errorcnt;
case '?':
if (optopt)
@@ -746,10 +751,8 @@ done:
return !!errorcnt;
}
-DECLARE_FUTIL_COMMAND(show, do_show,
- VBOOT_VERSION_ALL,
- "Display the content of various binary components",
- print_help);
+DECLARE_FUTIL_COMMAND(show, do_show, VBOOT_VERSION_ALL,
+ "Display the content of various binary components");
static int do_verify(int argc, char *argv[])
{
@@ -759,5 +762,4 @@ static int do_verify(int argc, char *argv[])
DECLARE_FUTIL_COMMAND(verify, do_verify,
VBOOT_VERSION_ALL,
- "Verify the signatures of various binary components",
- print_help);
+ "Verify the signatures of various binary components");
diff --git a/futility/cmd_sign.c b/futility/cmd_sign.c
index 104fa2e1..bfd3a00d 100644
--- a/futility/cmd_sign.c
+++ b/futility/cmd_sign.c
@@ -666,6 +666,7 @@ enum no_short_opts {
OPT_PEM_SIGNPRIV,
OPT_PEM_ALGO,
OPT_PEM_EXTERNAL,
+ OPT_HELP,
};
static const struct option long_opts[] = {
@@ -693,6 +694,7 @@ static const struct option long_opts[] = {
{"pem_algo", 1, NULL, OPT_PEM_ALGO},
{"pem_external", 1, NULL, OPT_PEM_EXTERNAL},
{"vblockonly", 0, &option.vblockonly, 1},
+ {"help", 0, NULL, OPT_HELP},
{NULL, 0, NULL, 0},
};
static char *short_opts = ":s:b:k:S:B:v:f:d:l:";
@@ -856,6 +858,9 @@ static int do_sign(int argc, char *argv[])
case OPT_PEM_EXTERNAL:
option.pem_external = optarg;
break;
+ case OPT_HELP:
+ print_help(argc, argv);
+ return !!errorcnt;
case '?':
if (optopt)
@@ -1077,7 +1082,6 @@ done:
return !!errorcnt;
}
-DECLARE_FUTIL_COMMAND(sign, do_sign,
- VBOOT_VERSION_ALL,
- "Sign / resign various binary components",
- print_help);
+DECLARE_FUTIL_COMMAND(sign, do_sign, VBOOT_VERSION_ALL,
+ "Sign / resign various binary components");
+
diff --git a/futility/cmd_vbutil_firmware.c b/futility/cmd_vbutil_firmware.c
index ce2f0a61..4e312b29 100644
--- a/futility/cmd_vbutil_firmware.c
+++ b/futility/cmd_vbutil_firmware.c
@@ -30,6 +30,7 @@ enum {
OPT_FV,
OPT_KERNELKEY,
OPT_FLAGS,
+ OPT_HELP,
};
static const struct option long_opts[] = {
@@ -42,6 +43,7 @@ static const struct option long_opts[] = {
{"fv", 1, 0, OPT_FV},
{"kernelkey", 1, 0, OPT_KERNELKEY},
{"flags", 1, 0, OPT_FLAGS},
+ {"help", 0, 0, OPT_HELP},
{NULL, 0, 0, 0}
};
@@ -322,6 +324,9 @@ static int do_vbutil_firmware(int argc, char *argv[])
printf("Unknown option\n");
parse_error = 1;
break;
+ case OPT_HELP:
+ print_help(argc, argv);
+ return !!parse_error;
case OPT_MODE_VBLOCK:
case OPT_MODE_VERIFY:
@@ -385,7 +390,5 @@ static int do_vbutil_firmware(int argc, char *argv[])
}
}
-DECLARE_FUTIL_COMMAND(vbutil_firmware, do_vbutil_firmware,
- VBOOT_VERSION_1_0,
- "Verified boot firmware utility",
- print_help);
+DECLARE_FUTIL_COMMAND(vbutil_firmware, do_vbutil_firmware, VBOOT_VERSION_1_0,
+ "Verified boot firmware utility");
diff --git a/futility/cmd_vbutil_kernel.c b/futility/cmd_vbutil_kernel.c
index 635acdc4..8ddc5ef2 100644
--- a/futility/cmd_vbutil_kernel.c
+++ b/futility/cmd_vbutil_kernel.c
@@ -64,6 +64,7 @@ enum {
OPT_MINVERSION,
OPT_VMLINUZ_OUT,
OPT_FLAGS,
+ OPT_HELP,
};
static const struct option long_opts[] = {
@@ -87,6 +88,7 @@ static const struct option long_opts[] = {
{"verbose", 0, &opt_verbose, 1},
{"vmlinuz-out", 1, 0, OPT_VMLINUZ_OUT},
{"flags", 1, 0, OPT_FLAGS},
+ {"help", 0, 0, OPT_HELP},
{NULL, 0, 0, 0}
};
@@ -270,6 +272,9 @@ static int do_vbutil_kernel(int argc, char *argv[])
case 0:
/* silently handled option */
break;
+ case OPT_HELP:
+ print_help(argc, argv);
+ return !!parse_error;
case OPT_MODE_PACK:
case OPT_MODE_REPACK:
@@ -646,7 +651,5 @@ static int do_vbutil_kernel(int argc, char *argv[])
return 1;
}
-DECLARE_FUTIL_COMMAND(vbutil_kernel, do_vbutil_kernel,
- VBOOT_VERSION_1_0,
- "Creates, signs, and verifies the kernel partition",
- print_help);
+DECLARE_FUTIL_COMMAND(vbutil_kernel, do_vbutil_kernel, VBOOT_VERSION_1_0,
+ "Creates, signs, and verifies the kernel partition");
diff --git a/futility/cmd_vbutil_key.c b/futility/cmd_vbutil_key.c
index cfc21b7f..840a14df 100644
--- a/futility/cmd_vbutil_key.c
+++ b/futility/cmd_vbutil_key.c
@@ -26,6 +26,7 @@ enum {
OPT_MODE_PACK,
OPT_MODE_UNPACK,
OPT_COPYTO,
+ OPT_HELP,
};
static const struct option long_opts[] = {
@@ -35,6 +36,7 @@ static const struct option long_opts[] = {
{"pack", 1, 0, OPT_MODE_PACK},
{"unpack", 1, 0, OPT_MODE_UNPACK},
{"copyto", 1, 0, OPT_COPYTO},
+ {"help", 0, 0, OPT_HELP},
{NULL, 0, 0, 0}
};
@@ -180,6 +182,9 @@ static int do_vbutil_key(int argc, char *argv[])
VbExError("Unknown option\n");
parse_error = 1;
break;
+ case OPT_HELP:
+ print_help(argc, argv);
+ return !!parse_error;
case OPT_INKEY:
infile = optarg;
@@ -234,7 +239,5 @@ static int do_vbutil_key(int argc, char *argv[])
}
}
-DECLARE_FUTIL_COMMAND(vbutil_key, do_vbutil_key,
- VBOOT_VERSION_1_0,
- "Wraps RSA keys with vboot headers",
- print_help);
+DECLARE_FUTIL_COMMAND(vbutil_key, do_vbutil_key, VBOOT_VERSION_1_0,
+ "Wraps RSA keys with vboot headers");
diff --git a/futility/cmd_vbutil_keyblock.c b/futility/cmd_vbutil_keyblock.c
index 738ad4a2..4be6b2d0 100644
--- a/futility/cmd_vbutil_keyblock.c
+++ b/futility/cmd_vbutil_keyblock.c
@@ -28,6 +28,7 @@ enum {
OPT_PEM_ALGORITHM,
OPT_EXTERNAL_SIGNER,
OPT_FLAGS,
+ OPT_HELP,
};
static const struct option long_opts[] = {
@@ -40,6 +41,7 @@ static const struct option long_opts[] = {
{"pem_algorithm", 1, 0, OPT_PEM_ALGORITHM},
{"externalsigner", 1, 0, OPT_EXTERNAL_SIGNER},
{"flags", 1, 0, OPT_FLAGS},
+ {"help", 0, 0, OPT_HELP},
{NULL, 0, 0, 0}
};
@@ -244,6 +246,9 @@ static int do_vbutil_keyblock(int argc, char *argv[])
printf("Unknown option\n");
parse_error = 1;
break;
+ case OPT_HELP:
+ print_help(argc, argv);
+ return !!parse_error;
case OPT_MODE_PACK:
case OPT_MODE_UNPACK:
@@ -331,7 +336,5 @@ static int do_vbutil_keyblock(int argc, char *argv[])
}
}
-DECLARE_FUTIL_COMMAND(vbutil_keyblock, do_vbutil_keyblock,
- VBOOT_VERSION_1_0,
- "Creates, signs, and verifies a keyblock",
- print_help);
+DECLARE_FUTIL_COMMAND(vbutil_keyblock, do_vbutil_keyblock, VBOOT_VERSION_1_0,
+ "Creates, signs, and verifies a keyblock");
diff --git a/futility/futility.c b/futility/futility.c
index 2a7b6bcf..91b7cdc6 100644
--- a/futility/futility.c
+++ b/futility/futility.c
@@ -17,7 +17,6 @@
#include "futility.h"
-
/******************************************************************************/
/* Logging stuff */
@@ -201,7 +200,8 @@ static const struct futil_cmd_t *find_command(const char *name)
const struct futil_cmd_t *const *cmd;
for (cmd = futil_cmds; *cmd; cmd++)
- if (0 == strcmp((*cmd)->name, name))
+ if (((*cmd)->version & vboot_version) &&
+ !strcmp((*cmd)->name, name))
return *cmd;
return NULL;
@@ -217,18 +217,29 @@ static void list_commands(void)
(*cmd)->name, (*cmd)->shorthelp);
}
+static int run_command(const struct futil_cmd_t *cmd, int argc, char *argv[])
+{
+ int i;
+ Debug("%s(\"%s\") ...\n", __func__, cmd->name);
+ for (i = 0; i < argc; i++)
+ Debug(" argv[%d] = \"%s\"\n", i, argv[i]);
+
+ return cmd->handler(argc, argv);
+}
+
static int do_help(int argc, char *argv[])
{
const struct futil_cmd_t *cmd;
const char *vstr;
- if (argc >= 2) {
+ /* Help about a known command? */
+ if (argc > 1) {
cmd = find_command(argv[1]);
if (cmd) {
- printf("\n%s - %s\n", argv[1], cmd->shorthelp);
- if (cmd->longhelp)
- cmd->longhelp(argc - 1, argv + 1);
- return 0;
+ /* Let the command provide its own help */
+ argv[0] = argv[1];
+ argv[1] = "--help";
+ return run_command(cmd, argc, argv);
}
}
@@ -256,31 +267,21 @@ static int do_help(int argc, char *argv[])
}
DECLARE_FUTIL_COMMAND(help, do_help, VBOOT_VERSION_ALL,
- "Show a bit of help (you're looking at it)",
- NULL);
+ "Show a bit of help (you're looking at it)");
+static const char ver_help[] =
+ "Show the futility source revision and build date";
static int do_version(int argc, char *argv[])
{
- printf("%s\n", futility_version);
+ if (argc > 1)
+ printf("%s - %s\n", argv[0], ver_help);
+ else
+ printf("%s\n", futility_version);
return 0;
}
DECLARE_FUTIL_COMMAND(version, do_version, VBOOT_VERSION_ALL,
- "Show the futility source revision and build date",
- NULL);
-
-static int run_command(const struct futil_cmd_t *cmd, int argc, char *argv[])
-{
- /* Handle the "CMD --help" case ourselves */
- if (2 == argc && 0 == strcmp(argv[1], "--help")) {
- char *fake_argv[] = {"help",
- (char *)cmd->name,
- NULL};
- return do_help(2, fake_argv);
- }
-
- return cmd->handler(argc, argv);
-}
+ ver_help);
static char *simple_basename(char *str)
{
@@ -293,16 +294,19 @@ static char *simple_basename(char *str)
}
/* Here we go */
+#define OPT_HELP 1000
int main(int argc, char *argv[], char *envp[])
{
char *progname;
const struct futil_cmd_t *cmd;
int i, errorcnt = 0;
int vb_ver = VBOOT_VERSION_ALL;
+ int helpind = 0;
struct option long_opts[] = {
{"debug", 0, &debugging_enabled, 1},
{"vb1" , 0, &vb_ver, VBOOT_VERSION_1_0},
{"vb21", 0, &vb_ver, VBOOT_VERSION_2_1},
+ {"help", 0, 0, OPT_HELP},
{ 0, 0, 0, 0},
};
@@ -313,14 +317,20 @@ int main(int argc, char *argv[], char *envp[])
/* See if the program name is a command we recognize */
cmd = find_command(progname);
- if (cmd)
+ if (cmd) {
/* Yep, just do that */
return run_command(cmd, argc, argv);
+ }
/* Parse the global options, stopping at the first non-option. */
opterr = 0; /* quiet, you. */
while ((i = getopt_long(argc, argv, "+:", long_opts, NULL)) != -1) {
switch (i) {
+ case OPT_HELP:
+ /* Remember where we found this option */
+ /* Note: this might be GNU-specific */
+ helpind = optind - 1;
+ break;
case '?':
if (optopt)
fprintf(stderr, "Unrecognized option: -%c\n",
@@ -343,26 +353,38 @@ int main(int argc, char *argv[], char *envp[])
}
vboot_version = vb_ver;
- /* Reset the getopt state so commands can parse their own options. */
- argc -= optind;
- argv += optind;
- optind = 0;
+ /*
+ * Translate "--help" in the args to "help" as the first parameter,
+ * by rearranging argv[].
+ */
+ if (helpind) {
+ int i;
+ optind--;
+ for (i = helpind; i < optind; i++)
+ argv[i] = argv[i + 1];
+ argv[i] = "help";
+ }
/* We require a command name. */
- if (errorcnt || argc < 1) {
- do_help(0, 0);
+ if (errorcnt || argc == optind) {
+ do_help(1, argv);
return 1;
}
/* For reasons I've forgotten, treat /blah/blah/CMD the same as CMD */
- progname = simple_basename(argv[0]);
+ argv[optind] = simple_basename(argv[optind]);
/* Do we recognize the command? */
- cmd = find_command(progname);
- if (cmd)
+ cmd = find_command(argv[optind]);
+ if (cmd) {
+ /* Reset so commands can parse their own options */
+ argc -= optind;
+ argv += optind;
+ optind = 0;
return run_command(cmd, argc, argv);
+ }
/* Nope. We've no clue what we're being asked to do. */
- do_help(0, 0);
+ do_help(1, argv);
return 1;
}
diff --git a/futility/futility.h b/futility/futility.h
index c28f40e6..e0754d86 100644
--- a/futility/futility.h
+++ b/futility/futility.h
@@ -44,21 +44,25 @@ enum vboot_version vboot_version;
/* Here's a structure to define the commands that futility implements. */
struct futil_cmd_t {
+ /* String used to invoke this command */
const char *const name;
+ /* Function to do the work. Returns 0 on success.
+ * Called with argv[0] == "name".
+ * It should handle its own "--help" option. */
int (*const handler) (int argc, char **argv);
+ /* Supported ABIs */
enum vboot_version version;
+ /* One-line summary of what it does */
const char *const shorthelp;
- void (*longhelp) (int argc, char *argv[]); /* argv[0] is the command */
};
/* Macro to define a command */
-#define DECLARE_FUTIL_COMMAND(NAME, HANDLER, VERSION, SHORTHELP, LONGHELP) \
+#define DECLARE_FUTIL_COMMAND(NAME, HANDLER, VERSION, SHORTHELP) \
const struct futil_cmd_t __cmd_##NAME = { \
.name = #NAME, \
.handler = HANDLER, \
.version = VERSION, \
.shorthelp = SHORTHELP, \
- .longhelp = LONGHELP, \
}
/* This is the list of pointers to all commands. */