diff --git a/includes/internal/cli/cli_handlers.h b/includes/internal/cli/cli_handlers.h index eea0c59..f72dcd9 100644 --- a/includes/internal/cli/cli_handlers.h +++ b/includes/internal/cli/cli_handlers.h @@ -3,8 +3,6 @@ #include -extern const struct option_descriptor g_options[]; - int cli_handle_help(const char *arg, void *config); int cli_handle_version(const char *arg, void *config); int cli_handle_p(const char *arg, void *config); diff --git a/includes/internal/cmd/digest_cmd.h b/includes/internal/cmd/digest_cmd.h new file mode 100644 index 0000000..d7d3582 --- /dev/null +++ b/includes/internal/cmd/digest_cmd.h @@ -0,0 +1,84 @@ +#ifndef FT_SSL_CMD_DIGEST_H +#define FT_SSL_CMD_DIGEST_H + +#include +#include + +#include "internal/cli/cli_handlers.h" +#include "internal/cmd/command.h" + +#define DIGEST_OPTION_LIST \ + X( \ + 'h', \ + "help", \ + no_argument, \ + cli_handle_help, \ + OPT_ARG_NONE, \ + "Display this help and exit", \ + 0 \ + ) \ + X( \ + 'V', \ + "version", \ + no_argument, \ + cli_handle_version, \ + OPT_ARG_NONE, \ + "Display version information and exit", \ + 0 \ + ) \ + X( \ + 'p', \ + "stdin", \ + no_argument, \ + cli_handle_p, \ + OPT_ARG_NONE, \ + "Echo stdin to stdout and append checksum to output", \ + 0 \ + ) \ + X( \ + 'q', \ + "quiet", \ + no_argument, \ + cli_handle_q, \ + OPT_ARG_NONE, \ + "Quiet mode: only print the digest", \ + 0 \ + ) \ + X( \ + 'r', \ + "reverse", \ + no_argument, \ + cli_handle_r, \ + OPT_ARG_NONE, \ + "Reverse the output format (digest then filename)", \ + 0 \ + ) \ + X( \ + 's', \ + "string", \ + required_argument, \ + cli_handle_s, \ + OPT_ARG_STRING, \ + "Hash a string", \ + CLI_OPT_F_REPEATABLE \ + ) + +#undef X +#define X(short_opt, long_opt, has_arg, handler, arg_type, desc, flags) + 1 +enum { DIGEST_OPT_LEN = (0 DIGEST_OPTION_LIST) }; + +#undef X +#define X(short_opt, long_opt, has_arg, handler, arg_type, desc, flags) \ + + (1 * (has_arg == no_argument) \ + + (2 * (has_arg == required_argument) \ + + (3 * (has_arg == optional_argument)))) +enum { DIGEST_OPTSTR_LEN = (2 DIGEST_OPTION_LIST) }; +/* +2 for ':' to disable getopt error messages and \0 */ + +#undef X + +extern const struct option_descriptor g_digest_opts[]; +int digest_run(int argc, char **argv, + const struct command_descriptor *self); + +#endif diff --git a/src/cli/handlers/handle_help.c b/src/cli/handlers/handle_help.c index 7bb4d39..972a2c8 100644 --- a/src/cli/handlers/handle_help.c +++ b/src/cli/handlers/handle_help.c @@ -1,15 +1,17 @@ #include #include + #include "compiler.h" +#include "ft_ssl.h" +#include "internal/cmd/digest_cmd.h" #include "version_gen.h" -#include "internal/cli/option.h" -#include "internal/cli/cli_handlers.h" int -cli_handle_help(__unused const char *arg, __unused void *config_void) +cli_handle_help(__unused const char *arg, void *config_void) { - print_usage(g_prog_name); - printf("\n"); - cli_print_options(g_options, FT_SSL_OPT_LEN, cli_arg_type_to_str); + struct digest_config *config = (struct digest_config *)config_void; + + printf("Usage: %s %s [OPTIONS] [FILE...]\n\n", g_prog_name, config->cmd_name); + cli_print_options(g_digest_opts, DIGEST_OPT_LEN, cli_arg_type_to_str); return CLI_EXIT_SUCCESS; } diff --git a/src/cli/handlers/option_map.c b/src/cli/handlers/option_map.c index ddc149b..3f42467 100644 --- a/src/cli/handlers/option_map.c +++ b/src/cli/handlers/option_map.c @@ -1,13 +1,12 @@ -#include "internal/cli/cli_handlers.h" -#include "internal/cli/option.h" +#include "internal/cmd/digest_cmd.h" #undef X #define X(short_opt, long_opt, has_arg, handler, arg_type, desc, flags) \ { short_opt, long_opt, has_arg, handler, arg_type, desc, flags }, -const struct option_descriptor g_options[] = { - FT_SSL_OPTION_LIST - {0, NULL, 0, NULL, OPT_ARG_NONE, NULL, 0 } +const struct option_descriptor g_digest_opts[] = { + DIGEST_OPTION_LIST + {0, NULL, 0, NULL, OPT_ARG_NONE, NULL, 0} }; #undef X diff --git a/src/cmd/digest_run.c b/src/cmd/digest_run.c new file mode 100644 index 0000000..fb8b93c --- /dev/null +++ b/src/cmd/digest_run.c @@ -0,0 +1,75 @@ +#include +#include + +#include +#include + +#include "compiler.h" +#include "ft_ssl.h" +#include "ft_ssl_flags.h" +#include "internal/cmd/command.h" +#include "internal/cmd/digest_cmd.h" +#include "internal/ssl/ssl.h" +#include "version_gen.h" + +/* Forward declarations */ +static int check_algo(const struct digest_config *config); +static void update_ret(int *ret, int result); +/* ------------------- */ + +int +digest_run(int argc, char **argv, const struct command_descriptor *self) +{ + struct digest_config config = {0}; + char opt_str[DIGEST_OPTSTR_LEN + 1]; + struct option long_opts[DIGEST_OPT_LEN + 1]; + enum cli_code ret; + int ret_val; + int has_input; + int i; + + config.algo = (const struct digest_algo *)self->impl; + config.cmd_name = self->name; + + ret = cli_parse(argc, argv, &config, self->opts, self->nb_opts, + opt_str, long_opts); + if (CLI_SUCCESS != ret) + return (int)ret; + + config.files = argv + optind; + config.nb_files = argc - optind; + + if (CLI_SUCCESS != check_algo(&config)) + return (int)CLI_ERROR; + + ret_val = (int)CLI_SUCCESS; + has_input = (0 < config.nb_strings || 0 < config.nb_files); + if (HAS_FLAG(config.flags, FLAG_P) || !has_input) + update_ret(&ret_val, run_stdin(&config)); + for (i = 0; i < config.nb_strings; i++) + update_ret(&ret_val, run_string(&config, config.strings[i])); + for (i = 0; i < config.nb_files; i++) + update_ret(&ret_val, run_file(&config, config.files[i])); + return ret_val; +} + +static int +check_algo(const struct digest_config *config) +{ + if (NULL == config->algo->init + || NULL == config->algo->update + || NULL == config->algo->final) + { + fprintf(stderr, "%s: %s: not yet implemented\n", + g_prog_name, config->algo->name); + return (int)CLI_ERROR; + } + return (int)CLI_SUCCESS; +} + +static void +update_ret(int *ret, int result) +{ + if ((int)CLI_ERROR == result) + *ret = (int)CLI_ERROR; +}