diff --git a/includes/cli.h b/includes/cli.h index 4508e3f..63582e0 100644 --- a/includes/cli.h +++ b/includes/cli.h @@ -9,7 +9,8 @@ enum e_cli_code { CLI_ERROR = 1 }; -enum e_cli_code -cli_parse_arguments(int argc, char **argv, t_ping_config *config); +enum e_cli_code cli_parse_arguments(int argc, char **argv, + t_ping_config *config); +void cli_config_free(t_ping_config *config); #endif diff --git a/includes/ft_ping.h b/includes/ft_ping.h index c83109d..0ee488e 100644 --- a/includes/ft_ping.h +++ b/includes/ft_ping.h @@ -3,11 +3,13 @@ #include #include +#include typedef struct s_ping_config { - /* Target */ - char *destination; + /* Targets */ + struct in_addr *destinations; + size_t nb_destinations; /* Options */ uint64_t count; diff --git a/includes/internal/cli/messages.h b/includes/internal/cli/messages.h index 8392b0e..4bfb1e2 100644 --- a/includes/internal/cli/messages.h +++ b/includes/internal/cli/messages.h @@ -10,5 +10,7 @@ enum e_cli_code error_unknown_opt(const char *current_opt); enum e_cli_code error_invalid_arg(const char *current_opt); enum e_cli_code error_invalid_opt(const char *current_opt); enum e_cli_code error_duplicate_opt(const char *current_opt); +enum e_cli_code error_missing_dest(void); +enum e_cli_code error_invalid_dest(void); #endif diff --git a/includes/internal/cli/parse_utils.h b/includes/internal/cli/parse_utils.h index 8b54717..71e21e9 100644 --- a/includes/internal/cli/parse_utils.h +++ b/includes/internal/cli/parse_utils.h @@ -2,8 +2,12 @@ #define CLI_INTERNAL_PARSE_UTILS #include +#include +#include "ft_ping.h" int cli_parse_uint64(const char *s, uint64_t *out); int cli_parse_float(const char *s, float *out); +int cli_parse_inet_addr(const char *s, struct in_addr *out); +int cli_parse_destinations(int argc, char **argv, int optind, t_ping_config *config); #endif diff --git a/sources.mk b/sources.mk index 17a4a75..5ebe43f 100644 --- a/sources.mk +++ b/sources.mk @@ -15,7 +15,10 @@ SRCS = $(SRC_DIR)/main.c \ $(SRC_DIR)/cli/handlers/handle_verbose.c \ $(SRC_DIR)/cli/parse_utils/parse_int.c \ $(SRC_DIR)/cli/parse_utils/parse_float.c \ + $(SRC_DIR)/cli/parse_utils/parse_inet_addr.c \ + $(SRC_DIR)/cli/parse_utils/parse_destinations.c \ $(SRC_DIR)/cli/parse_utils/get_optstr.c \ + $(SRC_DIR)/cli/config_free.c \ $(SRC_DIR)/cli/messages/help.c \ $(SRC_DIR)/cli/messages/version.c \ $(SRC_DIR)/cli/messages/error.c \ diff --git a/src/cli/config_free.c b/src/cli/config_free.c new file mode 100644 index 0000000..557270a --- /dev/null +++ b/src/cli/config_free.c @@ -0,0 +1,10 @@ +#include + +#include "cli.h" + +void +cli_config_free(t_ping_config *config) +{ + free(config->destinations); + config->destinations = NULL; +} diff --git a/src/cli/messages/error.c b/src/cli/messages/error.c index f002540..760cfba 100644 --- a/src/cli/messages/error.c +++ b/src/cli/messages/error.c @@ -46,6 +46,22 @@ error_duplicate_opt(const char *current_opt) return CLI_ERROR; } +enum e_cli_code +error_missing_dest(void) +{ + dprintf(STDERR_FILENO, "%s: usage error: Destination address required\n", + CMD_NAME); + print_suggest_help(); + return CLI_ERROR; +} + +enum e_cli_code +error_invalid_dest(void) +{ + dprintf(STDERR_FILENO, "%s: unknown host\n", CMD_NAME); + return CLI_ERROR; +} + void static inline print_suggest_help(void) { diff --git a/src/cli/parse.c b/src/cli/parse.c index fe6a3f5..64e3ecb 100644 --- a/src/cli/parse.c +++ b/src/cli/parse.c @@ -1,3 +1,4 @@ +#include #include #include @@ -7,6 +8,7 @@ #include "internal/cli/messages.h" #include "internal/cli/options.h" #include "internal/cli/arg_handler.h" +#include "internal/cli/parse_utils.h" /* Map -? to -h to support help shortcut */ #define HANDLE_QUESTION_MARK(opt) \ @@ -42,7 +44,7 @@ cli_parse_arguments(int argc, char **argv, t_ping_config *config) if (CLI_SUCCESS != res) return res; } - return CLI_SUCCESS; + return cli_parse_destinations(argc, argv, optind, config); } static int diff --git a/src/cli/parse_utils/parse_destinations.c b/src/cli/parse_utils/parse_destinations.c new file mode 100644 index 0000000..84d55e9 --- /dev/null +++ b/src/cli/parse_utils/parse_destinations.c @@ -0,0 +1,28 @@ +#include + +#include "cli.h" +#include "internal/cli/messages.h" +#include "internal/cli/parse_utils.h" + +int +cli_parse_destinations(int argc, char **argv, int optind, t_ping_config *config) +{ + if (optind >= argc) + return error_missing_dest(); + + config->nb_destinations = (size_t)(argc - optind); + config->destinations = malloc(config->nb_destinations * sizeof(struct in_addr)); + if (NULL == config->destinations) + return CLI_ERROR; + + for (int i = optind; i < argc; i++) + { + if (0 != cli_parse_inet_addr(argv[i], &config->destinations[i - optind])) + { + free(config->destinations); + config->destinations = NULL; + return error_invalid_dest(); + } + } + return CLI_SUCCESS; +} diff --git a/src/cli/parse_utils/parse_inet_addr.c b/src/cli/parse_utils/parse_inet_addr.c new file mode 100644 index 0000000..d0274ef --- /dev/null +++ b/src/cli/parse_utils/parse_inet_addr.c @@ -0,0 +1,23 @@ +#include +#include +#include + +int +cli_parse_inet_addr(const char *s, struct in_addr *out) +{ + struct addrinfo hints; + struct addrinfo *res; + + bzero(&hints, sizeof(struct addrinfo)); + hints.ai_family = AF_INET; + + if (0 != getaddrinfo(s, NULL, &hints, &res)) + return 1; + + struct sockaddr_in sin; + + memcpy(&sin, res->ai_addr, sizeof(sin)); + freeaddrinfo(res); + *out = sin.sin_addr; + return 0; +} diff --git a/src/main.c b/src/main.c index e54c80e..a7543db 100644 --- a/src/main.c +++ b/src/main.c @@ -21,15 +21,14 @@ main(int argc, char **argv) return EXIT_FAILURE; ret = cli_parse_arguments(argc, argv, &config); if (ret != CLI_SUCCESS) - { - free(g_prog_name.alloc); - return (ret == CLI_ERROR) ? EXIT_FAILURE : EXIT_SUCCESS; - } + goto cleanup; printf("PING: Not yet implemented\n"); +cleanup: + cli_config_free(&config); free(g_prog_name.alloc); - return EXIT_SUCCESS; + return (ret == CLI_ERROR) ? EXIT_FAILURE : EXIT_SUCCESS; } static int