From: Fredrik Thulin Date: Thu, 13 Jan 2011 22:04:47 +0000 (+0100) Subject: Make argument parsing testable. X-Git-Tag: v1.4.0~19^2~3 X-Git-Url: https://err.no/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=dc17f09fae1a642434b35be22d7543823b41b3c6;p=yubikey-personalization.old Make argument parsing testable. --- diff --git a/ykpersonalize.c b/ykpersonalize.c index 1801f12..d4153e0 100644 --- a/ykpersonalize.c +++ b/ykpersonalize.c @@ -174,87 +174,34 @@ static void report_yk_error() } } -int main(int argc, char **argv) +/* + * Parse all arguments supplied to this program and turn it into mainly + * a YKP_CONFIG (but return some other parameters as well, like + * access_code, verbose etc.). + * + * Done in this way to be testable (see tests/test_args_to_config.c). + */ +int args_to_config(int argc, char **argv, YKP_CONFIG *cfg, + const char *infname, const char *outfname, + bool *autocommit, char *salt, + YK_STATUS *st, bool *verbose, + unsigned char *access_code, bool *use_access_code, + bool *aesviahash, + int *exit_code) { char c; - FILE *inf = NULL; const char *infname = NULL; - FILE *outf = NULL; const char *outfname = NULL; - bool verbose = false; - bool aesviahash = false; const char *aeshash = NULL; - bool use_access_code = false, new_access_code = false; - unsigned char access_code[256]; - YK_KEY *yk = 0; - YKP_CONFIG *cfg = ykp_create_config(); - YK_STATUS *st = ykds_alloc(); - bool autocommit = false; - - bool error = false; - int exit_code = 0; - - /* Options */ - char *salt = NULL; - - ykp_errno = 0; - yk_errno = 0; - - /* Assume the worst */ - error = true; - - if (!yk_init()) { - exit_code = 1; - goto err; - } - - if (argc == 2 && strcmp (argv[1], "-h") == 0) { - fputs(usage, stderr); - goto err; - } - - if (!(yk = yk_open_first_key())) { - exit_code = 1; - goto err; - } - - if (!yk_get_status(yk, st)) { - exit_code = 1; - goto err; - } - - printf("Firmware version %d.%d.%d Touch level %d ", - ykds_version_major(st), - ykds_version_minor(st), - ykds_version_build(st), - ykds_touch_level(st)); - if (ykds_pgm_seq(st)) - printf("Program sequence %d\n", - ykds_pgm_seq(st)); - else - printf("Unconfigured\n"); - - if (!(yk_check_firmware_version(yk))) { - if (yk_errno == YK_EFIRMWARE) { - printf("Unsupported firmware revision - some " - "features may not be available\n" - "Please see \n" - "http://code.google.com/p/yubikey-personalization/wiki/Compatibility\n" - "for more information.\n"); - } else { - goto err; - } - } - - if (!ykp_configure_for(cfg, 1, st)) - goto err; + const char *aeshash = NULL; + bool new_access_code = false; while((c = getopt(argc, argv, optstring)) != -1) { switch (c) { case '1': if (!ykp_configure_for(cfg, 1, st)) - goto err; + return 0; break; case '2': if (!ykp_configure_for(cfg, 2, st)) - goto err; + return 0; break; case 'i': infname = optarg; @@ -263,7 +210,7 @@ int main(int argc, char **argv) outfname = optarg; break; case 'a': - aesviahash = true; + *aesviahash = true; aeshash = optarg; break; case 'c': { @@ -275,14 +222,14 @@ int main(int argc, char **argv) fprintf(stderr, "Invalid access code string: %s\n", optarg); - exit_code = 1; - goto err; + *exit_code = 1; + return 0; } if (!new_access_code) ykp_set_access_code(cfg, access_code, access_code_len); - use_access_code = true; + *use_access_code = true; break; } case 'o': @@ -300,8 +247,8 @@ int main(int argc, char **argv) fprintf(stderr, "Invalid fixed string: %s\n", fixed); - exit_code = 1; - goto err; + *exit_code = 1; + return 0; } ykp_set_fixed(cfg, fixedbin, fixedbinlen); } @@ -317,8 +264,8 @@ int main(int argc, char **argv) fprintf(stderr, "Invalid uid string: %s\n", uid); - exit_code = 1; - goto err; + *exit_code = 1; + return 0; } ykp_set_uid(cfg, uidbin, uidbinlen); } @@ -334,8 +281,8 @@ int main(int argc, char **argv) fprintf(stderr, "Invalid access code string: %s\n", acc); - exit_code = 1; - goto err; + *exit_code = 1; + return 0; } ykp_set_access_code(cfg, accbin, accbinlen); new_access_code = true; @@ -343,13 +290,13 @@ int main(int argc, char **argv) #define TKTFLAG(o, f) \ else if (strcmp(optarg, o) == 0) { \ if (!ykp_set_tktflag_##f(cfg, true)) { \ - exit_code = 1; \ - goto err; \ + *exit_code = 1; \ + return 0; \ } \ } else if (strcmp(optarg, "-" o) == 0) { \ if (! ykp_set_tktflag_##f(cfg, false)) { \ - exit_code = 1; \ - goto err; \ + *exit_code = 1; \ + return 0; \ } \ } TKTFLAG("tab-first", TAB_FIRST) @@ -365,13 +312,13 @@ int main(int argc, char **argv) #define CFGFLAG(o, f) \ else if (strcmp(optarg, o) == 0) { \ if (! ykp_set_cfgflag_##f(cfg, true)) { \ - exit_code = 1; \ - goto err; \ + *exit_code = 1; \ + return 0; \ } \ } else if (strcmp(optarg, "-" o) == 0) { \ if (! ykp_set_cfgflag_##f(cfg, false)) { \ - exit_code = 1; \ - goto err; \ + *exit_code = 1; \ + return 0; \ } \ } CFGFLAG("send-ref", SEND_REF) @@ -393,24 +340,117 @@ int main(int argc, char **argv) fprintf(stderr, "Unknown option '%s'\n", optarg); fputs(usage, stderr); - exit_code = 1; - goto err; + *exit_code = 1; + return 0; } break; case 'v': - verbose = true; + *verbose = true; break; case 'y': - autocommit = true; + *autocommit = true; break; case 'h': default: fputs(usage, stderr); - exit_code = 0; + *exit_code = 0; + return 0; + } + } + + if (*aesviahash) { + if (ykp_AES_key_from_hex(cfg, aeshash)) { + fprintf(stderr, "Bad AES key: %s\n", aeshash); + fflush(stderr); + return 0; + } + } + + return 1; +} + +int main(int argc, char **argv) +{ + FILE *inf = NULL; const char *infname = NULL; + FILE *outf = NULL; const char *outfname = NULL; + bool verbose = false; + bool aesviahash = false; + bool use_access_code = false; + unsigned char access_code[256]; + YK_KEY *yk = 0; + YKP_CONFIG *cfg = ykp_create_config(); + YK_STATUS *st = ykds_alloc(); + bool autocommit = false; + + /* Options */ + char *salt = NULL; + + bool error = false; + int exit_code = 0; + + ykp_errno = 0; + yk_errno = 0; + + /* Assume the worst */ + error = true; + + if (!yk_init()) { + exit_code = 1; + goto err; + } + + if (argc == 2 && strcmp (argv[1], "-h") == 0) { + fputs(usage, stderr); + goto err; + } + + if (!(yk = yk_open_first_key())) { + exit_code = 1; + goto err; + } + + if (!yk_get_status(yk, st)) { + exit_code = 1; + goto err; + } + + printf("Firmware version %d.%d.%d Touch level %d ", + ykds_version_major(st), + ykds_version_minor(st), + ykds_version_build(st), + ykds_touch_level(st)); + if (ykds_pgm_seq(st)) + printf("Program sequence %d\n", + ykds_pgm_seq(st)); + else + printf("Unconfigured\n"); + + if (!(yk_check_firmware_version(yk))) { + if (yk_errno == YK_EFIRMWARE) { + printf("Unsupported firmware revision - some " + "features may not be available\n" + "Please see \n" + "http://code.google.com/p/yubikey-personalization/wiki/Compatibility\n" + "for more information.\n"); + } else { goto err; } } + if (!ykp_configure_for(cfg, 1, st)) + goto err; + + /* Parse all arguments in a testable way */ + if (! args_to_config(argc, argv, cfg, + infname, outfname, + &autocommit, salt, + st, &verbose, + access_code, &use_access_code, + &aesviahash, + &exit_code)) { + goto err; + } + if (infname) { if (strcmp(infname, "-") == 0) inf = stdin; @@ -443,13 +483,7 @@ int main(int argc, char **argv) if (inf) { if (!ykp_read_config(cfg, reader, inf)) goto err; - } else if (aesviahash) { - if (ykp_AES_key_from_hex(cfg, aeshash)) { - fprintf(stderr, "Bad AES key: %s\n", aeshash); - fflush(stderr); - goto err; - } - } else { + } else if (! aesviahash) { char passphrasebuf[256]; size_t passphraselen; fprintf(stderr, "Passphrase to create AES key: "); fflush(stderr);