diff --git a/includes/help.h b/includes/help.h index 2be4d52..b883e84 100644 --- a/includes/help.h +++ b/includes/help.h @@ -19,12 +19,13 @@ static options_t options[] = { {"verbose", 'v', "verbose output", 0, GRP}, #undef GRP #define GRP 2 // AKA bonus - {"count", 'c', "stop after sending NUMBER packets", 1, - GRP}, + {"count", 'c', "stop after sending NUMBER packets", 1, GRP}, {"size", 's', "send NUMBER data octets", 1, GRP}, {"timeout", 'w', "stop after N seconds", 1, GRP}, {"ttl", 't', "specify N as time-to-live", 1, GRP}, - {"ip-timestamp", 'i', "IP timestamp of type FLAG, which is one of \"tsonly\" and \"tsaddr\"", 1, GRP} + {"ip-timestamp", 'i', + "IP timestamp of type FLAG, which is one of \"tsonly\" and \"tsaddr\"", 1, + GRP} #undef GRP }; @@ -43,12 +44,17 @@ static options_t options[] = { } \ args->arg[i] = *(av + 1); \ } \ - args->opts[i] = true; + args->opts[i] = true; \ + return EXIT_SUCCESS; + +typedef enum { MISSING_HOST, INVALID_OPT, NEED_ARG } error_t; /** * @brief Can be used to print the help message if no host (or addr) are * provided */ -void print_no_host(char *av); +void print_parse_err(error_t err, char *opt); void print_help(void); + +void print_usage(void); diff --git a/includes/opt_parse.h b/includes/opt_parse.h index a856dbd..2b23dfd 100644 --- a/includes/opt_parse.h +++ b/includes/opt_parse.h @@ -8,6 +8,7 @@ typedef struct { bool opts[OPT_NB]; char *arg[OPT_NB]; + char **hosts; } args_t; /** diff --git a/includes/ping.h b/includes/ping.h index 6f70f09..cd6f93e 100644 --- a/includes/ping.h +++ b/includes/ping.h @@ -1 +1,3 @@ #pragma once + +extern char *exec_name; diff --git a/src/help.c b/src/help.c index 805b2ee..f685ca9 100644 --- a/src/help.c +++ b/src/help.c @@ -1,8 +1,10 @@ +#include "ping.h" #include #include #include #include +#include void print_help(void) { printf("Usage: ping [OPTION...] HOST ...\n"); @@ -52,7 +54,26 @@ void print_help(void) { printf("Report bugs to :D.\n"); } -void print_no_host(char *av) { - printf("%s: missing host operand\n", av); - printf("Try 'ping --help' or 'ping -?' for more information.\n"); +void print_parse_err(error_t err, char *opt) { + switch (err) { + case MISSING_HOST: + printf("%s: missing host operand\n", exec_name); + break; + case INVALID_OPT: + printf("%s: invalid option -- %s\n", exec_name, opt); + break; + case NEED_ARG: + printf("%s: option '--%s' requires an argument\n", exec_name, opt); + + } + printf("Try 'ping --help' or 'ping --usage' for more information.\n"); +} + +void print_usage(void) { + printf("Usage %s:", exec_name); + OPT_WHILE { + printf(" [--%s] ", options[i].name); + i++; + } + printf("HOST ...\n"); } diff --git a/src/main.c b/src/main.c index b786621..df12b4d 100644 --- a/src/main.c +++ b/src/main.c @@ -6,42 +6,58 @@ #include #include +char *exec_name; + void init_args_t(args_t *args) { OPT_WHILE { args->opts[i] = false; args->arg[i] = NULL; + args->hosts = NULL; i++; } } int handle_options(args_t *args, char **av) { - // TODO: need to make this function D: if (args->opts[1]) { print_help(); return EXIT_SUCCESS; } else if (args->opts[0]) { - print_no_host(*av); + print_usage(); return EX_USAGE; } else if (args->opts[2]) { printf("adjoly's %s: v%s\n", *av, FT_PING_V); return EXIT_SUCCESS; + } else if (args->opts[1]) { + print_help(); + return EXIT_SUCCESS; + } else { + for (int i = 0; args->hosts[i] != NULL; ++i) + printf("%s\n", args->hosts[i]); } return EXIT_SUCCESS; } int main(int ac, char **av) { + exec_name = *av; args_t args; init_args_t(&args); if (ac > 1) { int ret = opt_parse(av, &args); - if (ret == -1) + if (ret == -1) { + free(args.hosts); return EXIT_SUCCESS; - else if (ret != EXIT_SUCCESS) + } + else if (ret != EXIT_SUCCESS) { + free(args.hosts); return ret; - else - return handle_options(&args, av); + } + else { + ret = handle_options(&args, av); + free(args.hosts); + return ret; + } } else { - print_no_host(*av); + print_parse_err(MISSING_HOST, NULL); return EX_USAGE; } return EXIT_SUCCESS; diff --git a/src/opt_parse.c b/src/opt_parse.c index a81fd2f..77340fc 100644 --- a/src/opt_parse.c +++ b/src/opt_parse.c @@ -10,39 +10,58 @@ int handle_long_args(char **av, args_t *args) { OPT_WHILE { if (strncmp((*av) + 2, options[i].name, strlen(options[i].name)) == 0) { - OPT_HANDLE(i) + OPT_HANDLE(i); } i++; } - return EXIT_SUCCESS; + print_parse_err(INVALID_OPT, (*av) + 2); + return EXIT_FAILURE; } int opt_parse(char **av, args_t *args) { - char *exec_name = *av; - + av++; while (*av != NULL) { char *a = *av; if (*a == '-') { char opt = *(a + 1); if (!opt) { - print_no_host(exec_name); + print_parse_err(MISSING_HOST, 0); return EX_USAGE; } else if (opt == '-') { int ret = handle_long_args(av, args); - if (ret == EX_USAGE) { - print_no_host(exec_name); - return EX_USAGE; + if (ret != EXIT_SUCCESS) { + if (ret == EX_USAGE) + print_parse_err(NEED_ARG, (*av) + 2); + return ret; } } else { OPT_WHILE { if (opt == options[i].opt) { OPT_HANDLE(i) + } else { + print_parse_err(INVALID_OPT, a); + return EXIT_FAILURE; } i++; } } } else { + if (args->hosts == NULL) { + args->hosts = calloc(sizeof(char *), 2); + args->hosts[0] = *av; + args->hosts[1] = NULL; + } else { + int i; + for (i = 0; args->hosts[i] != NULL; ++i) + ; + char **old = args->hosts; + args->hosts = reallocarray(old, i + 2, sizeof(char *)); + if (args->hosts == NULL) + return EXIT_FAILURE; + args->hosts[i] = *av; + args->hosts[i + 1] = NULL; + } } av++; }