From: Niels Möller Date: Sun, 10 Nov 2002 13:46:53 +0000 (+0100) Subject: Use supplied getopt. X-Git-Tag: nettle_1.7_release_20030311~142 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=e5380bdf58d770d05eee7dd0843145871fa97b88;p=thirdparty%2Fnettle.git Use supplied getopt. (werror): New function. (sexp_output_hash_init): New function. (sexp_put_char): Made base64 linebreaking configurable. Implemented hashing. (sexp_put_code_start, sexp_put_code_end): Don't output any delimiters here. (sexp_put_string): Output base64 delimiters. (sexp_put_digest): New function. (sexp_convert_item): Output transport delimiters. (sexp_convert_file): Deleted function, folded with main. (parse_options): New function. (main): Implemented --hash and --once, needed by lsh-authorize. Rev: src/nettle/tools/sexp-conv.c:1.2 --- diff --git a/tools/sexp-conv.c b/tools/sexp-conv.c index a3484ee5..060c7ab9 100644 --- a/tools/sexp-conv.c +++ b/tools/sexp-conv.c @@ -3,11 +3,19 @@ * Conversion tool for handling the different flavours of sexp * syntax. */ +#if HAVE_CONFIG_H +# include "config.h" +#endif + +#define BUG_ADDRESS "nettle-bugs@lists.lysator.liu.se" + #include "base16.h" #include "base64.h" #include "buffer.h" #include "nettle-meta.h" +#include "getopt.h" + #include #include #include @@ -15,10 +23,7 @@ #include #include -/* For getopt */ -#include - -void +static void die(const char *format, ...) #if __GNUC___ __attribute__((__format__ (__printf__,1, 2))) @@ -26,7 +31,7 @@ die(const char *format, ...) #endif ; -void +static void die(const char *format, ...) { va_list args; @@ -37,6 +42,25 @@ die(const char *format, ...) exit(EXIT_FAILURE); } +static void +werror(const char *format, ...) +#if __GNUC___ + __attribute__((__format__ (__printf__,1, 2))) + __attribute__((__noreturn__)) +#endif + ; + +static void +werror(const char *format, ...) +{ + va_list args; + va_start(args, format); + vfprintf(stderr, format, args); + va_end(args); + + exit(EXIT_FAILURE); +} + enum sexp_mode { SEXP_CANONICAL = 0, @@ -520,8 +544,13 @@ struct sexp_output { FILE *f; + unsigned line_width; + const struct nettle_armor *coding; unsigned coding_indent; + + const struct nettle_hash *hash; + void *ctx; union { struct base64_decode_ctx base64; @@ -532,15 +561,25 @@ struct sexp_output }; static void -sexp_output_init(struct sexp_output *output, FILE *f) +sexp_output_init(struct sexp_output *output, FILE *f, unsigned width) { output->f = f; + output->line_width = width; output->coding = NULL; - + output->hash = NULL; + output->ctx = NULL; + output->pos = 0; } -#define LINE_WIDTH 60 +static void +sexp_output_hash_init(struct sexp_output *output, + const struct nettle_hash *hash, void *ctx) +{ + output->hash = hash; + output->ctx = ctx; + hash->init(ctx); +} static void sexp_put_raw_char(struct sexp_output *output, uint8_t c) @@ -582,13 +621,16 @@ sexp_put_char(struct sexp_output *output, uint8_t c) for (i = 0; ipos > LINE_WIDTH - && output->pos > (output->coding_indent + 10)) + if (output->line_width + && output->pos >= output->line_width + && output->pos >= (output->coding_indent + 10)) sexp_put_newline(output, output->coding_indent); sexp_put_raw_char(output, encoded[i]); } } + else if (output->hash) + output->hash->update(output->ctx, 1, &c); else sexp_put_raw_char(output, c); } @@ -623,12 +665,10 @@ sexp_put_length(struct sexp_output *output, static void sexp_put_code_start(struct sexp_output *output, - const struct nettle_armor *coding, - uint8_t c) + const struct nettle_armor *coding) { assert(!output->coding); - sexp_put_raw_char(output, c); output->coding_indent = output->pos; output->coding = coding; @@ -636,7 +676,7 @@ sexp_put_code_start(struct sexp_output *output, } static void -sexp_put_code_end(struct sexp_output *output, uint8_t c) +sexp_put_code_end(struct sexp_output *output) { /* Enough for both hex and base64 */ uint8_t encoded[BASE64_ENCODE_FINAL_LENGTH]; @@ -651,7 +691,6 @@ sexp_put_code_end(struct sexp_output *output, uint8_t c) output->coding = NULL; sexp_put_data(output, done, encoded); - sexp_put_char(output, c); } static void @@ -718,9 +757,11 @@ sexp_put_string(struct sexp_output *output, enum sexp_mode mode, } else { - sexp_put_code_start(output, &nettle_base64, '|'); + sexp_put_char(output, '|'); + sexp_put_code_start(output, &nettle_base64); sexp_put_data(output, string->size, string->contents); - sexp_put_code_end(output, '|'); + sexp_put_code_end(output); + sexp_put_char(output, '|'); } } else @@ -731,6 +772,21 @@ sexp_put_string(struct sexp_output *output, enum sexp_mode mode, } } +static void +sexp_put_digest(struct sexp_output *output) +{ + uint8_t *digest; + + assert(output->hash); + + digest = alloca(output->hash->digest_size); + output->hash->digest(output->ctx, output->hash->digest_size, digest); + + sexp_put_code_start(output, &nettle_base16); + sexp_put_data(output, output->hash->digest_size, digest); + sexp_put_code_end(output); +} + /* Parsing and conversion functions. */ @@ -771,9 +827,11 @@ sexp_convert_item(struct sexp_input *input, enum sexp_mode mode_in, { if (mode_out == SEXP_TRANSPORT) { - sexp_put_code_start(output, &nettle_base64, '{'); + sexp_put_char(output, '{'); + sexp_put_code_start(output, &nettle_base64); sexp_convert_item(input, mode_in, output, SEXP_CANONICAL, 0); - sexp_put_code_end(output, '}'); + sexp_put_code_end(output); + sexp_put_char(output, '}'); } else switch(input->token) { @@ -853,30 +911,60 @@ sexp_convert_list(struct sexp_input *input, enum sexp_mode mode_in, } } -static void -sexp_convert_file(struct sexp_input *input, enum sexp_mode mode_in, - struct sexp_output *output, enum sexp_mode mode_out) -{ - sexp_get_char(input); - sexp_get_token(input, mode_in); - - while (input->token != SEXP_EOF) - { - sexp_convert_item(input, mode_in, output, mode_out, 0); - if (mode_out != SEXP_CANONICAL) - sexp_put_newline(output, 0); - - sexp_get_token(input, mode_in); - } - - if (fflush(output->f) < 0) - die("Final fflush failed: %s.\n", strerror(errno)); -} - /* Argument parsing and main program */ +/* The old lsh sexp-conv program took the following options: + * + * Usage: sexp-conv [OPTION...] + * Conversion: sexp-conv [options] OUTPUT + * or: sexp-conv [OPTION...] + * Fingerprinting: sexp-conv --raw-hash [ --hash=ALGORITHM ] + * mode = SEXP_ADVANCED; + o->once = 0; + o->hash = NULL; + o->width = 72; - int c; - while ( (c = getopt(argc, argv, "s:w:")) != -1) - switch (c) - { - case 's': - if (match_argument(optarg, "advanced")) - mode = SEXP_ADVANCED; - else if (match_argument(optarg, "transport")) - mode = SEXP_TRANSPORT; - else if (match_argument(optarg, "canonical")) - mode = SEXP_CANONICAL; - else - die("Available syntax variants: advanced, transport, canonical\n"); - break; + for (;;) + { + static const struct nettle_hash *hashes[] = + { &nettle_md5, &nettle_sha1, &nettle_sha256, NULL }; + + static const struct option options[] = + { + /* Name, args, flag, val */ + { "help", no_argument, NULL, '?' }, + { "version", no_argument, NULL, 'V' }, + { "once", no_argument, NULL, OPT_ONCE }, + { "syntax", required_argument, NULL, 's' }, + { "hash", optional_argument, NULL, OPT_HASH }, + { "width", required_argument, NULL, 'w' }, +#if 0 + /* Not yet implemented */ + { "replace", required_argument, NULL, OPT_REPLACE }, + { "select", required_argument, NULL, OPT_SELECT }, + { "spki-hash", optional_argument, NULL, OPT_SPKI_HASH }, +#endif + { NULL, 0, NULL, 0 } + }; + int c; + int option_index = 0; + unsigned i; + + c = getopt_long(argc, argv, "V?s:w:", options, &option_index); + + switch (c) + { + default: + abort(); + + case -1: + if (optind != argc) + die("sexp-conv: Command line takes no arguments, only options.\n"); + return; - case 'w': - die("Option -w not yet implemented.\n"); + case 'w': + { + char *end; + o->width = strtol(optarg, &end , 0); + if (!*optarg || *end || o->width < 0) + die("sexp-conv: Invalid width `%s'.\n", + optarg); + break; + } + case 's': + if (o->hash) + werror("sexp-conv: Combining --hash and -s usually makes no sense.\n"); + if (match_argument(optarg, "advanced")) + o->mode = SEXP_ADVANCED; + else if (match_argument(optarg, "transport")) + o->mode = SEXP_TRANSPORT; + else if (match_argument(optarg, "canonical")) + o->mode = SEXP_CANONICAL; + else + die("Available syntax variants: advanced, transport, canonical\n"); + break; + + case OPT_ONCE: + o->once = 1; + break; - case '?': - printf("Usage: sexp-conv [-m syntax]\n" - "Available syntax variants: advanced, transport, canonical\n"); - return EXIT_FAILURE; + case OPT_HASH: + o->mode = SEXP_CANONICAL; + if (!optarg) + o->hash = &nettle_sha1; + else + for (i = 0;; i++) + { + if (!hashes[i]) + die("sexp_conv: Unknown hash algorithm `%s'\n", + optarg); + + if (match_argument(optarg, hashes[i]->name)) + { + o->hash = hashes[i]; + break; + } + } + break; + + case '?': + printf("Usage: sexp-conv [OPTION...]\n" + " Conversion: sexp-conv [OPTION...] name); + } + printf(" (default is sha1).\n" + " -s, --syntax=SYNTAX The syntax used for the output. Available\n" + " variants: advanced, transport, canonical\n" + " --once Process only the first s-expression.\n" + " -w, --width=WIDTH Linewidth for base64 encoded data.\n" + " Zero means no limit.\n\n" + "Report bugs to " BUG_ADDRESS ".\n"); + exit(EXIT_SUCCESS); + + case 'V': + printf("sexp-conv (" PACKAGE_STRING ")\n"); + exit (EXIT_SUCCESS); + } + } +} - default: abort(); - } +int +main(int argc, char **argv) +{ + struct conv_options options; + struct sexp_input input; + struct sexp_output output; - sexp_input_init(&input, stdin); - sexp_output_init(&output, stdout); + parse_options(&options, argc, argv); - sexp_convert_file(&input, SEXP_ADVANCED, &output, mode); + sexp_input_init(&input, stdin); + sexp_output_init(&output, stdout, options.width); + if (options.hash) + sexp_output_hash_init(&output, + options.hash, + alloca(options.hash->context_size)); + + sexp_get_char(&input); + sexp_get_token(&input, SEXP_ADVANCED); + + if (input.token == SEXP_EOF) + { + if (options.once) + die("sexp-conv: No input expression.\n"); + return EXIT_SUCCESS; + } + + do + { + sexp_convert_item(&input, SEXP_ADVANCED, &output, options.mode, 0); + if (options.hash) + sexp_put_digest(&output); + else if (options.mode != SEXP_CANONICAL) + sexp_put_newline(&output, 0); + + sexp_get_token(&input, SEXP_ADVANCED); + } + while (!options.once && input.token != SEXP_EOF); + + if (fflush(output.f) < 0) + die("Final fflush failed: %s.\n", strerror(errno)); + return EXIT_SUCCESS; }