From 01c4d7cc515db4e81f1de1c3571c8dd90dca1e10 Mon Sep 17 00:00:00 2001 From: tomoron Date: Fri, 15 Aug 2025 02:17:19 +0200 Subject: [PATCH] replace parsing to use getopt (safer), change count opt behavior, close socket when needed --- Makefile | 2 + srcs/ft_ping.c | 4 +- srcs/icmp.c | 4 +- srcs/includes/ft_ping.h | 10 ++- srcs/main.c | 28 +++--- srcs/parsing.c | 187 ++++++++++++++++++---------------------- 6 files changed, 110 insertions(+), 125 deletions(-) diff --git a/Makefile b/Makefile index d47b563..edb8446 100644 --- a/Makefile +++ b/Makefile @@ -21,6 +21,8 @@ OBJS = $(addprefix $(OBJS_DIR)/,$(SRCS:.c=.o))\ all: $(NAME) +bonus: all + $(NAME): $(OBJS_DIR) $(OBJS) $(CC) $(FLAGS) $(OBJS) -o $@ -lm diff --git a/srcs/ft_ping.c b/srcs/ft_ping.c index 3332e24..65a71c9 100644 --- a/srcs/ft_ping.c +++ b/srcs/ft_ping.c @@ -6,7 +6,7 @@ /* By: tomoron +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/04/26 19:54:25 by tomoron #+# #+# */ -/* Updated: 2025/06/02 22:10:42 by tomoron ### ########.fr */ +/* Updated: 2025/08/13 16:59:55 by tomoron ### ########.fr */ /* */ /* ************************************************************************** */ @@ -83,7 +83,7 @@ int ping_host(t_settings *set, char *host) wl = 0; inet_ntop(info->ai_family, (void *)&((struct sockaddr_in *)(info->ai_addr))->sin_addr, set->current_ip, sizeof(set->current_ip)); ping_start_print(set, host); - while((seq < set->count || set->count == -1) && !g_stop) + while((seq < set->count || set->count == 0) && !g_stop) { tmp = send_icmp(set, info, &seq, &last_sent, &stats); if(tmp) diff --git a/srcs/icmp.c b/srcs/icmp.c index caf62f5..ed3a6ce 100644 --- a/srcs/icmp.c +++ b/srcs/icmp.c @@ -6,7 +6,7 @@ /* By: tomoron +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/04/24 22:49:22 by tomoron #+# #+# */ -/* Updated: 2025/08/08 22:19:52 by tomoron ### ########.fr */ +/* Updated: 2025/08/13 16:35:29 by tomoron ### ########.fr */ /* */ /* ************************************************************************** */ #include "includes/ft_ping.h" @@ -125,7 +125,7 @@ void ttl_exceeded(t_icmp_ip_reply *res,t_settings *settings, size_t len) sent->header.ttl, sent->header.protocol, htons(sent->header.check),\ convert_ip(sent->header.saddr)); printf(" %s\nICMP: ", convert_ip(sent->header.daddr)); - printf("type %d, code %d, size %zu, id 0x%04x, seq 0x%04x\n", sent->icmp.type, sent->icmp.code, sent->header.tot_len - sizeof(struct iphdr), sent->icmp.identifier, sent->icmp.sequence); + printf("type %d, code %d, size %zu, id 0x%04x, seq 0x%04x\n", sent->icmp.type, sent->icmp.code, htons(sent->header.tot_len) - sizeof(struct iphdr), sent->icmp.identifier, sent->icmp.sequence); } diff --git a/srcs/includes/ft_ping.h b/srcs/includes/ft_ping.h index 442b3c5..97ebe81 100644 --- a/srcs/includes/ft_ping.h +++ b/srcs/includes/ft_ping.h @@ -16,6 +16,7 @@ #include #include #include +#include #include @@ -29,8 +30,9 @@ Send ICMP ECHO_REQUEST packets to network hosts.\n\ -i, --interval=N Wait N seconds between sending each packet\n\ -w, --timeout=N Stop after N seconds\n\ -W, --linger=N Number of seconds to wait for response\n\ + -v, --verbose Enable verbose mode\n\ \n\ - -?, --help Give this help list\n" + -h, --help Print this usage info\n" extern int g_stop; @@ -56,7 +58,7 @@ typedef struct s_settings int linger; //-W (--linger) int ttl; // --ttl short setTtl; // is ttl set - short verbose; // -v (--verbose) + int verbose; // -v (--verbose) int socket; uint16_t id; @@ -102,8 +104,8 @@ typedef struct s_stats t_icmp_echo prepare_icmp_echo(uint16_t sequence, uint16_t identifier); int add_host(t_settings *res, char *host); void free_hosts(t_host_list *list); -t_settings parse_args(int argc, char **argv); -void show_help(t_settings *set, char *name); +int parse_args(int argc, char **argv, t_settings *set); +void show_help(t_settings *set); void send_pings(t_settings *set); uint16_t calc_checksum(void *ptr, size_t len); double timediff(struct timeval *from); diff --git a/srcs/main.c b/srcs/main.c index 8f51db3..f738ebc 100644 --- a/srcs/main.c +++ b/srcs/main.c @@ -6,7 +6,7 @@ /* By: tomoron +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/04/24 00:03:56 by tomoron #+# #+# */ -/* Updated: 2025/08/08 22:30:18 by tomoron ### ########.fr */ +/* Updated: 2025/08/15 02:14:40 by tomoron ### ########.fr */ /* */ /* ************************************************************************** */ @@ -14,10 +14,10 @@ int g_stop = 0; -void show_help(t_settings *set, char *name) +void show_help(t_settings *set) { set->stop = 1; - printf("Usage: %s %s", name, HELP_MESSAGE); + printf("Usage: %s %s", set->name, HELP_MESSAGE); } int init_socket(char *name) @@ -58,25 +58,23 @@ int main(int argc, char **argv) { t_settings settings; - settings = parse_args(argc, argv); - if(settings.stop) - goto early_stop; - settings.socket = init_socket(argv[0]); - settings.id = get_id(); - settings.name = argv[0]; signal(SIGINT, signal_handler); + settings.name = argv[0]; + if(parse_args(argc, argv, &settings)) + return(1); + settings.id = get_id(); + if(!settings.err && !settings.stop) + settings.socket = init_socket(argv[0]); if(settings.stop || settings.err || settings.socket == -1) { -early_stop: + if(settings.socket != -1) + close(settings.socket); free_hosts(settings.hosts); return((settings.err != 0) * 64); } - if(!settings.hosts) - { - fprintf(stderr, "%s: missing host operand\n", argv[0]); - return(64); - } send_pings(&settings); + if(settings.socket != -1) + close(settings.socket); free_hosts(settings.hosts); return(0); } diff --git a/srcs/parsing.c b/srcs/parsing.c index 71b7df9..63a2f5e 100644 --- a/srcs/parsing.c +++ b/srcs/parsing.c @@ -6,80 +6,40 @@ /* By: tomoron +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/04/26 17:01:53 by tomoron #+# #+# */ -/* Updated: 2025/06/01 21:37:16 by tomoron ### ########.fr */ +/* Updated: 2025/08/15 02:16:12 by tomoron ### ########.fr */ /* */ /* ************************************************************************** */ #include "includes/ft_ping.h" -char *get_value_in_arg(char *arg, int end) +int get_set_int(char *arg, t_settings *set) { - char *res; - - res = strstr(arg, "="); - if(res - arg != end) - return (0); - if (!res) - return (0); - res++; - return(res); -} - -char *get_setting(int *i, int argc, char **argv, int end, t_settings *set) -{ - char *value; - - value = 0; - if(argv[*i][0] == '-' && argv[*i][1] == '-') - value = get_value_in_arg(argv[*i], end); - else if((*i) + 1 < argc) - value = argv[++(*i)]; - if(!value) - { - fprintf(stderr, "%s: option '%s' requires an option\n", argv[0], argv[*i]); - set->err = 1; - return(0); - } - return(value); -} - -int get_set_int(int *i, int argc, char **argv, int end, t_settings *set) -{ - char *value; char *tmp; - value = get_setting(i, argc, argv, end, set); - if(!value) - return(0); - tmp = value; + tmp = arg; while(*tmp) { if(!isdigit(*tmp)) { - fprintf(stderr, "%s: invalid value (`%s' near `%s')\n", argv[0], value, tmp); + fprintf(stderr, "%s: invalid value (`%s' near `%s')\n", set->name, arg, tmp); set->err = 1; return(0); } tmp++; } - return(atoi(value)); + return(atoi(arg)); } -double get_set_float(int *i, int argc, char **argv, int end, t_settings *set) +double get_set_float(char *arg, t_settings *set) { - char *value; char *tmp; int point; - value = get_setting(i, argc, argv, end, set); - if(!value) - return(0); - tmp = value; - point = 0; + tmp = arg; while(*tmp) { if((!isdigit(*tmp) && *tmp != '.') || (*tmp == '.' && point)) { - fprintf(stderr, "%s: invalid value (`%s' near `%s')\n", argv[0], value, tmp); + fprintf(stderr, "%s: invalid value (`%s' near `%s')\n", set->name, arg, tmp); set->err = 1; return(0); } @@ -87,33 +47,7 @@ double get_set_float(int *i, int argc, char **argv, int end, t_settings *set) point = 1; tmp++; } - return(atof(value)); -} - -void parse_opt(int *i, t_settings *set, int argc, char **argv) -{ - if(!strcmp(argv[*i], "-?") || !strcmp(argv[*i], "--help")) - show_help(set, *argv); - else if(!strcmp(argv[*i], "-c") || !strncmp(argv[*i], "--count", 7)) - set->count = get_set_int(i, argc, argv, 7, set); - else if(!strcmp(argv[*i], "-v") || !strncmp(argv[*i], "--verbose", 7)) - set->verbose = 1; - else if(!strcmp(argv[*i], "-w") || !strncmp(argv[*i], "--timeout", 9)) - set->timeout = get_set_int(i, argc, argv, 9, set); - else if(!strcmp(argv[*i], "-W") || !strncmp(argv[*i], "--linger", 8)) - set->linger = get_set_int(i, argc, argv, 8, set); - else if(!strcmp(argv[*i], "-i") || !strncmp(argv[*i], "--interval", 10)) - set->interval = get_set_float(i, argc, argv, 10, set); - else if(!strncmp(argv[*i], "--ttl", 5)) - { - set->ttl = get_set_int(i, argc, argv, 5, set); - set->setTtl = 1; - } - else - { - fprintf(stderr, "%s: unrecognized option '%s'\n", argv[0], argv[*i]); - set->err = 1; - } + return(atof(arg)); } int check_values(t_settings *set, char *name) @@ -139,32 +73,81 @@ int check_values(t_settings *set, char *name) return(1); } -t_settings parse_args(int argc, char **argv) +void init_settings(t_settings *set) { - int i; - t_settings res; - - i = 1; - bzero(&res, sizeof(t_settings)); - res.count = -1; - res.timeout = -1; - res.interval = 1; - res.linger = 10; - while(i < argc) - { - if(*argv[i] == '-') - parse_opt(&i, &res, argc, argv); - else - { - if(!add_host(&res, argv[i])) - { - res.err = 1; - return(res); - } - } - i++; - } - if(!res.err) - res.err = !check_values(&res, argv[0]); - return(res); + char *tmp; + tmp = set->name; + bzero(set, sizeof(t_settings)); + set->name = tmp; + set->timeout = -1; + set->interval = 1; + set->socket = -1; + set->linger = 10; +} + +int parse_args(int argc, char **argv, t_settings *set) +{ + int arg; + struct option opts[] = + { + {"count", required_argument, 0, 'c'}, + {"interval", required_argument, 0, 'i'}, + {"timeout", required_argument, 0, 'w'}, + {"linger", required_argument, 0, 'W'}, + {"ttl", required_argument , 0, 1000}, + {"verbose", no_argument, &set->verbose, 1}, + {"help", no_argument, 0, 'h'}, + {0, 0, 0, 0} + }; + + + unsetenv("POSIXLY_CORRECT"); + init_settings(set); + arg = 0; + while (arg != -1) + { + arg = getopt_long(argc, argv, "c:i:w:W:vh", opts, NULL); + switch (arg) { + case 'c': + set->count = get_set_int(optarg, set); + break; + case 'i': + set->interval = get_set_float(optarg, set); + break; + case 'w': + set->timeout = get_set_int(optarg, set); + break; + case 'W': + set->linger = get_set_int(optarg, set); + break; + case 1000: + set->ttl = get_set_int(optarg, set); + break; + case 'h': + case '?': + show_help(set); + return(1); + default : + break; + } + } + + while(optind < argc) + { + if(!add_host(set, argv[optind])) + { + set->err = 1; + return (0); + } + optind++; + } + if(!set->hosts) + { + fprintf(stderr, "%s: missing host operand\n", set->name); + set->err = 1; + return(1); + } + if (!set->err) + set->err = !check_values(set, argv[0]); + return (0); }