diff options
-rw-r--r-- | futility/futility.c | 130 | ||||
-rwxr-xr-x | tests/futility/test_main.sh | 48 |
2 files changed, 92 insertions, 86 deletions
diff --git a/futility/futility.c b/futility/futility.c index bc98a75f..19ee65b7 100644 --- a/futility/futility.c +++ b/futility/futility.c @@ -256,108 +256,80 @@ static const char *const dep_usage = "\n" "\n" MYNAME " %s [...]\n" "\n"; -static void deprecated(const char *depname) +static int deprecated(const char *depname) { fprintf(stderr, dep_usage, depname, depname); - exit(1); + return 1; } -/******************************************************************************/ -/* Here we go */ +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); + } -#define MYNAME_S MYNAME "_s" + return cmd->handler(argc, argv); +} +static char *simple_basename(char *str) +{ + char *s = strrchr(str, '/'); + if (s) + s++; + else + s = str; + return s; +} + +/* Here we go */ int main(int argc, char *argv[], char *envp[]) { - char *fullname, *progname; - char truename[PATH_MAX]; - char buf[80]; - pid_t myproc; - ssize_t r; + char *progname; const struct futil_cmd_t *cmd; int i; - int via_symlink = 0; log_args(argc, argv); /* How were we invoked? */ - fullname = strdup(argv[0]); - progname = strrchr(argv[0], '/'); - if (progname) - progname++; - else - progname = argv[0]; + progname = simple_basename(argv[0]); - /* Invoked directly by name */ - if (0 == strcmp(progname, MYNAME) || 0 == strcmp(progname, MYNAME_S)) { - - if (argc < 2) { /* must have an argument */ - do_help(0, 0); - exit(1); - } - - /* We can just pass the rest along, then */ - argc--; - argv++; - - /* So now what function do we want to invoke? */ - progname = strrchr(argv[0], '/'); - if (progname) - progname++; - else - progname = argv[0]; - /* Oh, and treat "--foo" the same as "foo" */ - while (*progname == '-') - progname++; - - } else { /* Invoked by symlink */ - via_symlink = 1; - /* Block any deprecated functions. */ + /* See if the program name is a command we recognize */ + cmd = find_command(progname); + if (cmd) { + /* Block any deprecated functions invoked directly. */ for (i = 0; i < ARRAY_SIZE(dep_cmds); i++) if (0 == strcmp(dep_cmds[i], progname)) - deprecated(progname); - } + return deprecated(progname); - /* See if it's asking for something we know how to do ourselves */ - cmd = find_command(progname); - if (cmd) { - /* 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); - } else { - return cmd->handler(argc, argv); - } + return run_command(cmd, argc, argv); } - /* Never heard of it */ - if (!via_symlink) { + /* The program name means nothing, so we require an argument. */ + if (argc < 2) { do_help(0, 0); - exit(1); + return 1; } - /* Complain about bogus symlink */ - myproc = getpid(); - snprintf(buf, sizeof(buf), "/proc/%d/exe", myproc); - r = readlink(buf, truename, PATH_MAX - 1); - if (r < 0) { - fprintf(stderr, "%s is lost: %s => %s: %s\n", MYNAME, argv[0], - buf, strerror(errno)); - exit(1); - } - truename[r] = '\0'; + /* The first arg should be a command we recognize */ + argc--; + argv++; - fprintf(stderr, "\n" -"The program\n\n %s\n\nis a symlink to\n\n %s\n" -"\n" -"However, " MYNAME " doesn't know how to implement that function.\n" -"\n" -"This is probably an error in your installation. If the problem persists\n" -"after a fresh checkout/build/install, please open a bug at\n" -"\n" -" http://dev.chromium.org/for-testers/bug-reporting-guidelines\n" -"\n", fullname, truename); + /* For reasons I've forgotten, treat /blah/blah/CMD the same as CMD */ + progname = simple_basename(argv[0]); + /* Oh, and treat "--foo" the same as "foo" */ + while (*progname == '-') + progname++; + + /* Do we recognize the command? */ + cmd = find_command(progname); + if (cmd) + return run_command(cmd, argc, argv); + + /* Nope. We've no clue what we're being asked to do. */ + do_help(0, 0); return 1; } diff --git a/tests/futility/test_main.sh b/tests/futility/test_main.sh index 17a54675..83fc53db 100755 --- a/tests/futility/test_main.sh +++ b/tests/futility/test_main.sh @@ -10,18 +10,18 @@ TMP="$me.tmp" cd "$OUTDIR" # No args returns nonzero exit code -"$FUTILITY" && false +${FUTILITY} && false # It's weird but okay if the command is a full path. -"$FUTILITY" /fake/path/to/help > "$TMP" +${FUTILITY} /fake/path/to/help > "$TMP" grep Usage "$TMP" # Make sure logging does something. LOG="/tmp/futility.log" [ -f ${LOG} ] && mv ${LOG} ${LOG}.backup touch ${LOG} -"$FUTILITY" help -grep "$FUTILITY" ${LOG} +${FUTILITY} help +grep ${FUTILITY} ${LOG} rm -f ${LOG} [ -f ${LOG}.backup ] && mv ${LOG}.backup ${LOG} @@ -29,16 +29,50 @@ rm -f ${LOG} DEPRECATED="dev_sign_file" for i in $DEPRECATED; do - ln -sf "$FUTILITY" $i + ln -sf ${FUTILITY} $i if ./$i 2>${TMP}.outmsg ; then false; fi grep deprecated ${TMP}.outmsg # They may still fail when invoked through futility # but with a different error message. - "$FUTILITY" $i 1>${TMP}.outmsg2 2>&1 || true + ${FUTILITY} $i 1>${TMP}.outmsg2 2>&1 || true if grep deprecated ${TMP}.outmsg2; then false; fi rm -f $i done +# Use some known digests to verify that things work... +DEVKEYS=${SRCDIR}/tests/devkeys +SHA=e78ce746a037837155388a1096212ded04fb86eb + +# all progs in the pipelines should work +set -o pipefail + +# If it's invoked as the name of a command we know, it should do that command +ln -sf ${FUTILITY} vbutil_key +./vbutil_key --unpack ${DEVKEYS}/installer_kernel_data_key.vbpubk | grep ${SHA} +ln -sf ${FUTILITY} vbutil_keyblock +./vbutil_keyblock --unpack ${DEVKEYS}/installer_kernel.keyblock | grep ${SHA} +cp ${FUTILITY} show +./show ${SCRIPTDIR}/data/rec_kernel_part.bin | grep ${SHA} + +# If it's invoked by any other name, expect the command to be the first arg. +ln -sf ${FUTILITY} muggle +./muggle vbutil_key --unpack ${DEVKEYS}/installer_kernel_data_key.vbpubk \ + | grep ${SHA} +ln -sf ${FUTILITY} buggle +./buggle vbutil_keyblock --unpack ${DEVKEYS}/installer_kernel.keyblock \ + | grep ${SHA} +cp ${FUTILITY} boo +./boo show ${SCRIPTDIR}/data/rec_kernel_part.bin | grep ${SHA} + + +# we expect the first command fail, but the output to match anyway +set +o pipefail + +# If it can't figure out the command at all, it should complain. +${FUTILITY} muggle | grep Usage: +./buggle futility | grep Usage: +./boo | grep Usage: + # cleanup -rm -f ${TMP}* +rm -f ${TMP}* vbutil_key vbutil_keyblock show muggle buggle boo exit 0 |