diff --git a/Makefile.am b/Makefile.am index 18d2b35..6353890 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,6 +1,6 @@ ACLOCAL_AMFLAGS = -I m4 -SUBDIRS = src +SUBDIRS = if BUILD_BUNDLED_LIBCLI SUBDIRS += libcli @@ -9,3 +9,5 @@ endif if BUILD_BUNDLED_LIBFT_SSL SUBDIRS += libft_ssl endif + +SUBDIRS += src diff --git a/configure.ac b/configure.ac index 82ebb4b..d495946 100644 --- a/configure.ac +++ b/configure.ac @@ -69,9 +69,6 @@ AS_IF([test "x$have_system_libcli" != "xyes"], [ AC_CONFIG_SUBDIRS([libcli]) ]) - -/// - AC_ARG_WITH([bundled-libft_ssl], AS_HELP_STRING( [--with-bundled-libft_ssl], @@ -98,10 +95,6 @@ AS_IF([test "x$have_system_libft_ssl" != "xyes"], [ ]) - -//// - - AC_CONFIG_FILES([ Makefile src/Makefile diff --git a/includes/.gitkeep b/includes/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/includes/compiler.h b/includes/compiler.h new file mode 100644 index 0000000..17f557a --- /dev/null +++ b/includes/compiler.h @@ -0,0 +1,16 @@ +#ifndef COMPILER_H +#define COMPILER_H + +#define __unused __attribute__((unused)) + +#define COUNT_OF(arr) (sizeof(arr) / sizeof((arr)[0])) + +#define STATIC_ARRAY_FOREACH(arr, ptr) \ + for ((ptr) = (arr); (ptr) < (arr) + COUNT_OF(arr); (ptr)++) + +#define HAS_FLAG(flags, flag) ((flags) & (flag)) +#define SET_FLAG(flags, flag) ((flags) |= (flag)) +#define CLEAR_FLAG(flags, flag) ((flags) &= ~(flag)) +#define TOGGLE_FLAG(flags, flag) ((flags) ^= (flag)) + +#endif diff --git a/includes/ft_ssl.h b/includes/ft_ssl.h new file mode 100644 index 0000000..a2afb62 --- /dev/null +++ b/includes/ft_ssl.h @@ -0,0 +1,19 @@ +#ifndef FT_SSL_H +#define FT_SSL_H + +#include +#include +#include + +struct ssl_config +{ + const struct digest_algo *algo; + uint8_t flags; + const char *string; + char **files; + int nb_files; +}; + +enum cli_code cli_parse_arguments(int argc, char **argv, struct ssl_config *config); + +#endif diff --git a/includes/ft_ssl_flags.h b/includes/ft_ssl_flags.h new file mode 100644 index 0000000..9802724 --- /dev/null +++ b/includes/ft_ssl_flags.h @@ -0,0 +1,8 @@ +#ifndef FT_SSL_FLAGS_H +#define FT_SSL_FLAGS_H + +#define FLAG_P (1 << 0) +#define FLAG_Q (1 << 1) +#define FLAG_R (1 << 2) + +#endif diff --git a/includes/internal/cli/cli_handlers.h b/includes/internal/cli/cli_handlers.h new file mode 100644 index 0000000..eea0c59 --- /dev/null +++ b/includes/internal/cli/cli_handlers.h @@ -0,0 +1,15 @@ +#ifndef FT_SSL_CLI_HANDLER_H +#define FT_SSL_CLI_HANDLER_H + +#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); +int cli_handle_q(const char *arg, void *config); +int cli_handle_r(const char *arg, void *config); +int cli_handle_s(const char *arg, void *config); + +#endif diff --git a/includes/internal/cli/option.h b/includes/internal/cli/option.h new file mode 100644 index 0000000..9bb069a --- /dev/null +++ b/includes/internal/cli/option.h @@ -0,0 +1,68 @@ +#ifndef FT_SSL_OPT_H +#define FT_SSL_OPT_H + +#include + +#define FT_SSL_OPTION_LIST \ + X( \ + 'h', \ + "help", \ + no_argument, \ + cli_handle_help, \ + OPT_ARG_NONE, \ + "Display this help and exit" \ + ) \ + X( \ + 'V', \ + "version", \ + no_argument, \ + cli_handle_version, \ + OPT_ARG_NONE, \ + "Display version information and exit" \ + ) \ + X( \ + 'p', \ + "stdin", \ + no_argument, \ + cli_handle_p, \ + OPT_ARG_NONE, \ + "Echo stdin to stdout and append checksum to output" \ + ) \ + X( \ + 'q', \ + "quiet", \ + no_argument, \ + cli_handle_q, \ + OPT_ARG_NONE, \ + "Quiet mode: only print the digest" \ + ) \ + X( \ + 'r', \ + "reverse", \ + no_argument, \ + cli_handle_r, \ + OPT_ARG_NONE, \ + "Reverse the output format (digest then filename)" \ + ) \ + X( \ + 's', \ + "string", \ + required_argument, \ + cli_handle_s, \ + OPT_ARG_STRING, \ + "Hash a string" \ + ) + +#undef X +#define X(short_opt, long_opt, has_arg, handler, arg_type, desc) + 1 +enum { FT_SSL_OPT_LEN = (0 FT_SSL_OPTION_LIST ) }; + +#undef X +#define X(short_opt, long_opt, has_arg, handler, arg_type, desc) \ + + (1 * (has_arg == no_argument) \ + + (2 * (has_arg == required_argument) \ + + (3 * (has_arg == optional_argument)))) +enum { FT_SSL_OPTSTR_LEN = (2 FT_SSL_OPTION_LIST) }; +/* +2 for ':' to disable getopt error messages and \0 */ + +#endif diff --git a/libft_ssl b/libft_ssl index bf43c7a..f21811b 160000 --- a/libft_ssl +++ b/libft_ssl @@ -1 +1 @@ -Subproject commit bf43c7a124130db8fbbce1e496af4f3aacd07316 +Subproject commit f21811b66f4f5d29ada3a53bd91763cac3f6d87f diff --git a/src/Makefile.am b/src/Makefile.am index 2c22450..3ee173d 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,9 +1,11 @@ bin_PROGRAMS = ft_ssl FT_SSL_VERSION = 0.0.1 -BUILT_SOURCES = $(VERSION_HEADER) VERSION_HEADER = $(top_srcdir)/includes/version_gen.h +BUILT_SOURCES = $(VERSION_HEADER) +CLEANFILES = $(VERSION_HEADER) + $(VERSION_HEADER): FORCE @NEW_HEADER=$$(mktemp); \ FT_SSL_BUILD_DATE=$$(git -C $(top_srcdir) log -1 --format=%cd \ @@ -38,13 +40,21 @@ FORCE: .PHONY: FORCE ft_ssl_SOURCES = \ - main.c + main.c \ + cli/parse.c \ + cli/handlers/option_map.c \ + cli/handlers/handle_help.c \ + cli/handlers/handle_version.c \ + cli/handlers/handle_p.c \ + cli/handlers/handle_q.c \ + cli/handlers/handle_r.c \ + cli/handlers/handle_s.c ft_ssl_CPPFLAGS = \ -I $(top_srcdir)/includes \ -D_GNU_SOURCE -BASE_CFLAGS = -std=c99 $(STRICT_CFLAGS) +ft_ssl_CFLAGS = -std=c99 $(STRICT_CFLAGS) ft_ssl_LDADD = -lm @@ -53,13 +63,13 @@ ft_ssl_CPPFLAGS += $(LIBCLI_CFLAGS) ft_ssl_LDADD += $(LIBCLI_LIBS) else ft_ssl_CPPFLAGS += -I $(top_srcdir)/libcli/include +ft_ssl_LDADD += $(top_builddir)/libcli/src/libcli.la endif - if USE_SYSTEM_LIBFT_SSL ft_ssl_CPPFLAGS += $(LIBFT_SSL_CFLAGS) ft_ssl_LDADD += $(LIBFT_SSL_LIBS) else ft_ssl_CPPFLAGS += -I $(top_srcdir)/libft_ssl/include +ft_ssl_LDADD += $(top_builddir)/libft_ssl/src/libft_ssl.la endif - diff --git a/src/cli/handlers/handle_help.c b/src/cli/handlers/handle_help.c new file mode 100644 index 0000000..2b727dd --- /dev/null +++ b/src/cli/handlers/handle_help.c @@ -0,0 +1,11 @@ +#include +#include "compiler.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_print_options(g_options, FT_SSL_OPT_LEN, cli_arg_type_to_str); + return CLI_EXIT_SUCCESS; +} diff --git a/src/cli/handlers/handle_p.c b/src/cli/handlers/handle_p.c new file mode 100644 index 0000000..be5ecd7 --- /dev/null +++ b/src/cli/handlers/handle_p.c @@ -0,0 +1,13 @@ +#include "compiler.h" +#include "ft_ssl.h" +#include "ft_ssl_flags.h" +#include "internal/cli/cli_handlers.h" + +int +cli_handle_p(__unused const char *arg, void *config_void) +{ + struct ssl_config *config = (struct ssl_config *)config_void; + + SET_FLAG(config->flags, FLAG_P); + return CLI_SUCCESS; +} diff --git a/src/cli/handlers/handle_q.c b/src/cli/handlers/handle_q.c new file mode 100644 index 0000000..e971031 --- /dev/null +++ b/src/cli/handlers/handle_q.c @@ -0,0 +1,13 @@ +#include "compiler.h" +#include "ft_ssl.h" +#include "ft_ssl_flags.h" +#include "internal/cli/cli_handlers.h" + +int +cli_handle_q(__unused const char *arg, void *config_void) +{ + struct ssl_config *config = (struct ssl_config *)config_void; + + SET_FLAG(config->flags, FLAG_Q); + return CLI_SUCCESS; +} diff --git a/src/cli/handlers/handle_r.c b/src/cli/handlers/handle_r.c new file mode 100644 index 0000000..f663d64 --- /dev/null +++ b/src/cli/handlers/handle_r.c @@ -0,0 +1,13 @@ +#include "compiler.h" +#include "ft_ssl.h" +#include "ft_ssl_flags.h" +#include "internal/cli/cli_handlers.h" + +int +cli_handle_r(__unused const char *arg, void *config_void) +{ + struct ssl_config *config = (struct ssl_config *)config_void; + + SET_FLAG(config->flags, FLAG_R); + return CLI_SUCCESS; +} diff --git a/src/cli/handlers/handle_s.c b/src/cli/handlers/handle_s.c new file mode 100644 index 0000000..2e857d5 --- /dev/null +++ b/src/cli/handlers/handle_s.c @@ -0,0 +1,11 @@ +#include "ft_ssl.h" +#include "internal/cli/cli_handlers.h" + +int +cli_handle_s(const char *arg, void *config_void) +{ + struct ssl_config *config = (struct ssl_config *)config_void; + + config->string = arg; + return CLI_SUCCESS; +} diff --git a/src/cli/handlers/handle_version.c b/src/cli/handlers/handle_version.c new file mode 100644 index 0000000..b5157a1 --- /dev/null +++ b/src/cli/handlers/handle_version.c @@ -0,0 +1,12 @@ +#include + +#include +#include "compiler.h" + + +int +cli_handle_version(__unused const char *arg, __unused void *config_void) +{ + printf("version x\n"); + return CLI_EXIT_SUCCESS; +} diff --git a/src/cli/handlers/option_map.c b/src/cli/handlers/option_map.c new file mode 100644 index 0000000..d25ff38 --- /dev/null +++ b/src/cli/handlers/option_map.c @@ -0,0 +1,13 @@ +#include "internal/cli/cli_handlers.h" +#include "internal/cli/option.h" + +#undef X +#define X(short_opt, long_opt, has_arg, handler, arg_type, desc) \ +{ short_opt, long_opt, has_arg, handler, arg_type, desc }, + +const struct option_descriptor g_options[] = { + FT_SSL_OPTION_LIST + {0, NULL, 0, NULL, OPT_ARG_NONE, NULL } +}; + +#undef X diff --git a/src/cli/parse.c b/src/cli/parse.c new file mode 100644 index 0000000..cb90c80 --- /dev/null +++ b/src/cli/parse.c @@ -0,0 +1,80 @@ +#include +#include +#include + +#include +#include + +#include "ft_ssl.h" +#include "internal/cli/cli_handlers.h" +#include "internal/cli/option.h" + +/* Forward declarations */ +static void init_config(struct ssl_config *config); +static const struct digest_algo *find_algo(const char *name); +static enum cli_code parse_subcommand(int argc, char **argv, int first_arg, + struct ssl_config *config); +/* ------------------- */ + +static const struct digest_algo * const s_algos[] = { + &g_md5, + &g_sha256, + NULL +}; + +enum cli_code +cli_parse_arguments(int argc, char **argv, struct ssl_config *config) +{ + char opt_str[FT_SSL_OPTSTR_LEN]; + struct option long_opts[FT_SSL_OPT_LEN + 1]; + enum cli_code ret; + + init_config(config); + ret = cli_parse(argc, argv, config, g_options, FT_SSL_OPT_LEN, opt_str, long_opts); + if (CLI_SUCCESS != ret) + return ret; + return parse_subcommand(argc, argv, optind, config); +} + +static enum cli_code +parse_subcommand(int argc, char **argv, int first_arg, + struct ssl_config *config) +{ + if (first_arg >= argc) + { + fprintf(stderr, "%s: missing command\n", argv[0]); + fprintf(stderr, "usage: %s {md5|sha256} [-pqr] [-s string] [file...]\n", + argv[0]); + return CLI_ERROR; + } + config->algo = find_algo(argv[first_arg]); + if (NULL == config->algo) + { + fprintf(stderr, "%s: unknown command -- '%s'\n", argv[0], argv[first_arg]); + fprintf(stderr, "usage: %s {md5|sha256} [-pqr] [-s string] [file...]\n", + argv[0]); + return CLI_ERROR; + } + config->files = argv + first_arg + 1; + config->nb_files = argc - first_arg - 1; + return CLI_SUCCESS; +} + +static const struct digest_algo * +find_algo(const char *name) +{ + size_t i; + + for (i = 0; NULL != s_algos[i]; i++) + { + if (0 == strcmp(s_algos[i]->name, name)) + return s_algos[i]; + } + return NULL; +} + +static void +init_config(struct ssl_config *config) +{ + memset(config, 0, sizeof(struct ssl_config)); +} diff --git a/src/main.c b/src/main.c index d659c45..42f8be3 100644 --- a/src/main.c +++ b/src/main.c @@ -1,6 +1,27 @@ +#include + +#include + +#include "ft_ssl.h" + +char *g_prog_name = NULL; int -main() +main(int argc, char **argv) { - return 0; + struct ssl_config config = {0}; + int ret = CLI_ERROR; + + g_prog_name = argv[0]; + cli_set_prog_name(g_prog_name); + ret = cli_parse_arguments(argc, argv, &config); + if (CLI_SUCCESS != ret) + goto cleanup; + + /* TODO: + * ret = ssl_run(&config); + */ + +cleanup: + return (CLI_ERROR == ret) ? 2 : EXIT_SUCCESS; }