Compare commits
6 commits
5944b16609
...
89eaf3402c
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
89eaf3402c | ||
|
|
a9eaeac940 | ||
|
|
09fe8cea87 | ||
|
|
8fb5ab6f12 | ||
|
|
c50154379c | ||
|
|
bf2e836447 |
6 changed files with 200 additions and 122 deletions
|
|
@ -6,7 +6,7 @@
|
||||||
/* By: rparodi <rparodi@student.42.fr> +#+ +:+ +#+ */
|
/* By: rparodi <rparodi@student.42.fr> +#+ +:+ +#+ */
|
||||||
/* +#+#+#+#+#+ +#+ */
|
/* +#+#+#+#+#+ +#+ */
|
||||||
/* Created: 2026/03/24 11:23:47 by rparodi #+# #+# */
|
/* Created: 2026/03/24 11:23:47 by rparodi #+# #+# */
|
||||||
/* Updated: 2026/03/24 13:20:48 by rparodi ### ########.fr */
|
/* Updated: 2026/03/30 12:29:28 by rparodi ### ########.fr */
|
||||||
/* */
|
/* */
|
||||||
/* ************************************************************************** */
|
/* ************************************************************************** */
|
||||||
|
|
||||||
|
|
@ -19,8 +19,8 @@
|
||||||
# define DEBUG 0
|
# define DEBUG 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define ERROR_LOG(str) dprintf(2, "%sError:\t%s (%s:%d in %s)%s\n", CLR_RED, str, __FILE_NAME__, __LINE__, __FUNCTION__, CLR_RESET);
|
#define ERROR_LOG(str) if (DEBUG) {dprintf(2, "%sError:\t%s (%s:%d in %s)%s\n", CLR_RED, str, __FILE_NAME__, __LINE__, __FUNCTION__, CLR_RESET);} else { dprintf(2, "%s\n", str); }
|
||||||
#define WARN_LOG(str) if (DEBUG) {dprintf(2, "%sWarning:\t%s (%s:%d in %s)%s\n", CLR_YELLOW, str, __FILE_NAME__, __LINE__, __FUNCTION__, CLR_RESET);}
|
#define WARN_LOG(str) if (DEBUG) {dprintf(2, "%sWarning:\t%s (%s:%d in %s)%s\n", CLR_YELLOW, str, __FILE_NAME__, __LINE__, __FUNCTION__, CLR_RESET);}
|
||||||
#define INFO_LOG(str) if (DEBUG) {dprintf(2, "%sInfo:\t%s (%s:%d in %s)%s\n", CLR_BLUE, str, __FILE_NAME__, __LINE__, __FUNCTION__, CLR_RESET);}
|
#define INFO_LOG(str) if (DEBUG) {dprintf(2, "%sInfo:\t%s (%s:%d in %s)%s\n", CLR_BLUE, str, __FILE_NAME__, __LINE__, __FUNCTION__, CLR_RESET);}
|
||||||
#define DEBUG_LOG(str) if (DEBUG) {dprintf(2, "%sDebug:\t%s (%s:%d in %s)%s\n", CLR_GREY, str, __FILE_NAME__, __LINE__, __FUNCTION__, CLR_RESET);}
|
#define DEBUG_LOG(str) if (DEBUG) {dprintf(2, "%sDebug:\t%s (%s:%d in %s)%s\n", CLR_GREY, str, __FILE_NAME__, __LINE__, __FUNCTION__, CLR_RESET);}
|
||||||
#define SUCCESS_LOG(str) if (DEBUG) {dprintf(2, "%sSuccess from %s:\t%s (%s:%d)%s\n", CLR_GREEN, str, __FILE_NAME__, __LINE__, __FUNCTION__, CLR_RESET);}
|
#define SUCCESS_LOG(str) if (DEBUG) {dprintf(2, "%sSuccess:\t%s (%s:%d in %s)%s\n", CLR_GREEN, str, __FILE_NAME__, __LINE__, __FUNCTION__, CLR_RESET);}
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@
|
||||||
/* By: rparodi <rparodi@student.42.fr> +#+ +:+ +#+ */
|
/* By: rparodi <rparodi@student.42.fr> +#+ +:+ +#+ */
|
||||||
/* +#+#+#+#+#+ +#+ */
|
/* +#+#+#+#+#+ +#+ */
|
||||||
/* Created: 2026/03/23 14:49:37 by rparodi #+# #+# */
|
/* Created: 2026/03/23 14:49:37 by rparodi #+# #+# */
|
||||||
/* Updated: 2026/03/28 15:25:03 by rparodi ### ########.fr */
|
/* Updated: 2026/03/30 12:19:17 by rparodi ### ########.fr */
|
||||||
/* */
|
/* */
|
||||||
/* ************************************************************************** */
|
/* ************************************************************************** */
|
||||||
|
|
||||||
|
|
@ -33,6 +33,8 @@ typedef struct s_args {
|
||||||
extern const t_args _flags[];
|
extern const t_args _flags[];
|
||||||
|
|
||||||
size_t args_size();
|
size_t args_size();
|
||||||
|
uint64_t check_num_arguments(char *arg);
|
||||||
|
void check_flags(int argc, char **argv, t_flags *flags);
|
||||||
|
void check_target(const char *target);
|
||||||
void print_help(const size_t size);
|
void print_help(const size_t size);
|
||||||
void print_usage(const size_t size);
|
void print_usage(const size_t size);
|
||||||
uint64_t check_num_arguments(char *arg);
|
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@
|
||||||
# By: rparodi <marvin@42.fr> +#+ +:+ +#+ #
|
# By: rparodi <marvin@42.fr> +#+ +:+ +#+ #
|
||||||
# +#+#+#+#+#+ +#+ #
|
# +#+#+#+#+#+ +#+ #
|
||||||
# Created: 2023/11/12 11:05:05 by rparodi #+# #+# #
|
# Created: 2023/11/12 11:05:05 by rparodi #+# #+# #
|
||||||
# Updated: 2026/03/28 15:15:58 by rparodi ### ########.fr #
|
# Updated: 2026/03/30 12:19:43 by rparodi ### ########.fr #
|
||||||
# #
|
# #
|
||||||
# **************************************************************************** #
|
# **************************************************************************** #
|
||||||
|
|
||||||
|
|
@ -19,6 +19,8 @@ NAME = lib$(MODULE_NAME).a
|
||||||
SRC = sources/utils.c \
|
SRC = sources/utils.c \
|
||||||
sources/help.c \
|
sources/help.c \
|
||||||
sources/usage.c \
|
sources/usage.c \
|
||||||
|
sources/flags.c \
|
||||||
|
sources/target.c \
|
||||||
sources/parsing.c
|
sources/parsing.c
|
||||||
|
|
||||||
CC ?= clang
|
CC ?= clang
|
||||||
|
|
|
||||||
140
parsing/sources/flags.c
Normal file
140
parsing/sources/flags.c
Normal file
|
|
@ -0,0 +1,140 @@
|
||||||
|
/* ************************************************************************** */
|
||||||
|
/* */
|
||||||
|
/* ::: :::::::: */
|
||||||
|
/* flags.c :+: :+: :+: */
|
||||||
|
/* +:+ +:+ +:+ */
|
||||||
|
/* By: rparodi <rparodi@student.42.fr> +#+ +:+ +#+ */
|
||||||
|
/* +#+#+#+#+#+ +#+ */
|
||||||
|
/* Created: 2026/03/30 12:06:19 by rparodi #+# #+# */
|
||||||
|
/* Updated: 2026/03/30 12:40:57 by rparodi ### ########.fr */
|
||||||
|
/* */
|
||||||
|
/* ************************************************************************** */
|
||||||
|
|
||||||
|
#include "parsing.h"
|
||||||
|
#include "macro.h"
|
||||||
|
#include <bits/getopt_core.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <getopt.h>
|
||||||
|
#include <asm-generic/errno-base.h>
|
||||||
|
|
||||||
|
const t_args _flags[] = {
|
||||||
|
{'?', "help", NULL, "print help and exit", true},
|
||||||
|
{'W', "linger","<timeout>,", "time to wait for response", false},
|
||||||
|
{'c', "count","<count>", "stop after <count> replies", false},
|
||||||
|
{'f', "flood",NULL, "flood ping", false},
|
||||||
|
{'l', "preload","<preload>,", "send <preload> number of packages while waiting replies", false},
|
||||||
|
{'n', "numeric",NULL, "no reverse DNS name resolution", false},
|
||||||
|
{'p', "pattern","<pattern>,", "contents of padding byte", false},
|
||||||
|
{'q', "quiet", NULL, "reply wait <deadline> in seconds", false},
|
||||||
|
{'v', "verbose",NULL, "verbose output", true},
|
||||||
|
{'w', "timeout","<deadline>,", "reply wait <deadline> in seconds", false},
|
||||||
|
{0, "usage", NULL, "give a short usage message", false},
|
||||||
|
{0, NULL, NULL,NULL, true},
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct option *_t_args_to_getopt_long(const size_t size) {
|
||||||
|
struct option *long_options = (struct option *)calloc((size + 1), sizeof(struct option));
|
||||||
|
if (!long_options) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (size_t i = 0; i < size; i++) {
|
||||||
|
long_options[i].name = _flags[i].long_option;
|
||||||
|
long_options[i].val = _flags[i].short_option;
|
||||||
|
if (_flags[i].usage == NULL) {
|
||||||
|
long_options[i].has_arg = no_argument;
|
||||||
|
} else {
|
||||||
|
long_options[i].has_arg = required_argument;
|
||||||
|
}
|
||||||
|
long_options[i].flag = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
long_options[size] = (struct option){0};
|
||||||
|
return long_options;
|
||||||
|
}
|
||||||
|
|
||||||
|
void check_flags(int argc, char **argv, t_flags *flags) {
|
||||||
|
const size_t size = args_size();
|
||||||
|
size_t j = 0;
|
||||||
|
char args[2 * size + 1];
|
||||||
|
bzero(args, sizeof(args));
|
||||||
|
|
||||||
|
for (size_t i = 0; i < size; i++) {
|
||||||
|
if (_flags[i].is_mandatory != false || BONUS == 1) {
|
||||||
|
args[j++] = _flags[i].short_option;
|
||||||
|
if (_flags[i].usage != NULL)
|
||||||
|
args[j++] = ':';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DEBUG_LOG(args);
|
||||||
|
|
||||||
|
struct option *options = _t_args_to_getopt_long(size);
|
||||||
|
if (!options) {
|
||||||
|
ERROR_LOG(strerror(ENOMEM));
|
||||||
|
exit(ENOMEM);
|
||||||
|
}
|
||||||
|
opterr = 1;
|
||||||
|
int opt;
|
||||||
|
while ((opt = getopt_long(argc, argv, args, options, NULL)) != -1) {
|
||||||
|
switch (opt) {
|
||||||
|
case 'v':
|
||||||
|
INFO_LOG("argument verbose");
|
||||||
|
flags->verbose = true;
|
||||||
|
break;
|
||||||
|
case 'f':
|
||||||
|
INFO_LOG("argument flood");
|
||||||
|
flags->flood = true;
|
||||||
|
break;
|
||||||
|
case 'n':
|
||||||
|
INFO_LOG("argument no-reverse");
|
||||||
|
flags->reverse_dns = true;
|
||||||
|
break;
|
||||||
|
case 'c':
|
||||||
|
INFO_LOG("argument count");
|
||||||
|
flags->count = check_num_arguments(optarg);
|
||||||
|
break;
|
||||||
|
case 'q':
|
||||||
|
INFO_LOG("argument quiet");
|
||||||
|
flags->quiet = true;
|
||||||
|
break;
|
||||||
|
case 'w':
|
||||||
|
INFO_LOG("argument wait");
|
||||||
|
flags->wait = check_num_arguments(optarg);
|
||||||
|
break;
|
||||||
|
case 'W':
|
||||||
|
INFO_LOG("argument timeout");
|
||||||
|
flags->timeout = check_num_arguments(optarg);
|
||||||
|
break;
|
||||||
|
case '?':
|
||||||
|
free(options);
|
||||||
|
if (optopt != 0) {
|
||||||
|
if (isprint(optopt)) {
|
||||||
|
char invalid_option[2] = {optopt, 0};
|
||||||
|
WARN_LOG(invalid_option);
|
||||||
|
}
|
||||||
|
ERROR_LOG("Try 'ft_ping --help' or 'ft_ping --usage' for more information.");
|
||||||
|
exit(64);
|
||||||
|
}
|
||||||
|
print_help(size);
|
||||||
|
exit(EXIT_SUCCESS);
|
||||||
|
default:
|
||||||
|
if (strcmp(options[optind - 1].name, "usage"))
|
||||||
|
print_usage(size);
|
||||||
|
else {
|
||||||
|
if (isprint(optopt)) {
|
||||||
|
char invalid_option[2] = {optopt, 0};
|
||||||
|
WARN_LOG(invalid_option);
|
||||||
|
}
|
||||||
|
ERROR_LOG("Try 'ft_ping --help' or 'ft_ping --usage' for more information.");
|
||||||
|
exit(64);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
free(options);
|
||||||
|
}
|
||||||
|
|
@ -6,140 +6,40 @@
|
||||||
/* By: rparodi <rparodi@student.42.fr> +#+ +:+ +#+ */
|
/* By: rparodi <rparodi@student.42.fr> +#+ +:+ +#+ */
|
||||||
/* +#+#+#+#+#+ +#+ */
|
/* +#+#+#+#+#+ +#+ */
|
||||||
/* Created: 2026/03/23 14:49:36 by rparodi #+# #+# */
|
/* Created: 2026/03/23 14:49:36 by rparodi #+# #+# */
|
||||||
/* Updated: 2026/03/28 15:43:45 by rparodi ### ########.fr */
|
/* Updated: 2026/03/30 12:22:07 by rparodi ### ########.fr */
|
||||||
/* */
|
/* */
|
||||||
/* ************************************************************************** */
|
/* ************************************************************************** */
|
||||||
|
|
||||||
#include "parsing.h"
|
#include "parsing.h"
|
||||||
#include "macro.h"
|
#include "macro.h"
|
||||||
#include <bits/getopt_core.h>
|
#include "struct.h"
|
||||||
#include <ctype.h>
|
|
||||||
#include <stdbool.h>
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdio.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <getopt.h>
|
#include <getopt.h>
|
||||||
#include <errno.h>
|
|
||||||
|
|
||||||
const t_args _flags[] = {
|
static const char *_find_target(int argc, char **argv) {
|
||||||
{'?', "help", NULL, "print help and exit", true},
|
const char *target = NULL;
|
||||||
{'W', "linger","<timeout>,", "time to wait for response", false},
|
|
||||||
{'c', "count","<count>", "stop after <count> replies", false},
|
|
||||||
{'f', "flood",NULL, "flood ping", false},
|
|
||||||
{'l', "preload","<preload>,", "send <preload> number of packages while waiting replies", false},
|
|
||||||
{'n', "numeric",NULL, "no reverse DNS name resolution", false},
|
|
||||||
{'p', "pattern","<pattern>,", "contents of padding byte", false},
|
|
||||||
{'q', "quiet", NULL, "reply wait <deadline> in seconds", false},
|
|
||||||
{'v', "verbose",NULL, "verbose output", true},
|
|
||||||
{'w', "timeout","<deadline>,", "reply wait <deadline> in seconds", false},
|
|
||||||
{0, "usage", NULL, "give a short usage message", false},
|
|
||||||
{0, NULL, NULL,NULL, true},
|
|
||||||
};
|
|
||||||
|
|
||||||
static struct option *_t_args_to_getopt_long(const size_t size) {
|
for (int i = optind; i < argc; i++) {
|
||||||
struct option *long_options = (struct option *)calloc((size + 1), sizeof(struct option));
|
if (argv[i][0] != '-') {
|
||||||
if (!long_options) {
|
target = argv[i];
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (size_t i = 0; i < size; i++) {
|
|
||||||
long_options[i].name = _flags[i].long_option;
|
|
||||||
long_options[i].val = _flags[i].short_option;
|
|
||||||
if (_flags[i].usage == NULL) {
|
|
||||||
long_options[i].has_arg = no_argument;
|
|
||||||
} else {
|
|
||||||
long_options[i].has_arg = required_argument;
|
|
||||||
}
|
}
|
||||||
long_options[i].flag = NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
long_options[size] = (struct option){0};
|
if (target == NULL || target[0] == '\0') {
|
||||||
return long_options;
|
dprintf(2, "%s: missing host operand \n Try 'ping --help' or 'ping --usage' for more information.", argv[0]);
|
||||||
}
|
exit(64);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (target);
|
||||||
|
}
|
||||||
void parsing_args(int argc, char **argv, t_flags *flags)
|
void parsing_args(int argc, char **argv, t_flags *flags)
|
||||||
{
|
{
|
||||||
if (argc == 1) {
|
if (argc == 1) {
|
||||||
dprintf(2, "%s: missing host operand \n Try 'ping --help' or 'ping --usage' for more information.", argv[0]);
|
dprintf(2, "%s: missing host operand \n Try 'ping --help' or 'ping --usage' for more information.", argv[0]);
|
||||||
exit(64);
|
exit(64);
|
||||||
}
|
}
|
||||||
const size_t size = args_size();
|
|
||||||
size_t j = 0;
|
|
||||||
char args[2 * size + 1];
|
|
||||||
bzero(args, sizeof(args));
|
|
||||||
|
|
||||||
for (size_t i = 0; i < size; i++) {
|
check_flags(argc, argv, flags);
|
||||||
if (_flags[i].is_mandatory != false || BONUS == 1) {
|
check_target(_find_target(argc, argv));
|
||||||
args[j++] = _flags[i].short_option;
|
SUCCESS_LOG("PARSING finished with success");
|
||||||
if (_flags[i].usage != NULL)
|
|
||||||
args[j++] = ':';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
DEBUG_LOG(args);
|
|
||||||
|
|
||||||
struct option *options = _t_args_to_getopt_long(size);
|
|
||||||
if (!options) {
|
|
||||||
ERROR_LOG(strerror(ENOMEM));
|
|
||||||
exit(ENOMEM);
|
|
||||||
}
|
|
||||||
opterr = 1;
|
|
||||||
int opt;
|
|
||||||
while ((opt = getopt_long(argc, argv, args, options, NULL)) != -1) {
|
|
||||||
switch (opt) {
|
|
||||||
case 'v':
|
|
||||||
INFO_LOG("argument verbose");
|
|
||||||
flags->verbose = true;
|
|
||||||
break;
|
|
||||||
case 'f':
|
|
||||||
INFO_LOG("argument flood");
|
|
||||||
flags->flood = true;
|
|
||||||
break;
|
|
||||||
case 'n':
|
|
||||||
INFO_LOG("argument no-reverse");
|
|
||||||
flags->reverse_dns = true;
|
|
||||||
break;
|
|
||||||
case 'c':
|
|
||||||
INFO_LOG("argument count");
|
|
||||||
flags->count = check_num_arguments(optarg);
|
|
||||||
break;
|
|
||||||
case 'q':
|
|
||||||
INFO_LOG("argument quiet");
|
|
||||||
flags->quiet = true;
|
|
||||||
break;
|
|
||||||
case 'w':
|
|
||||||
INFO_LOG("argument wait");
|
|
||||||
flags->wait = check_num_arguments(optarg);
|
|
||||||
break;
|
|
||||||
case 'W':
|
|
||||||
INFO_LOG("argument timeout");
|
|
||||||
flags->timeout = check_num_arguments(optarg);
|
|
||||||
break;
|
|
||||||
case '?':
|
|
||||||
free(options);
|
|
||||||
if (optopt != 0) {
|
|
||||||
if (isprint(optopt)) {
|
|
||||||
char invalid_option[2] = {optopt, 0};
|
|
||||||
WARN_LOG(invalid_option);
|
|
||||||
}
|
|
||||||
dprintf(2, "Try 'ping --help' or 'ping --usage' for more information.\n");
|
|
||||||
exit(64);
|
|
||||||
}
|
|
||||||
print_help(size);
|
|
||||||
exit(EXIT_SUCCESS);
|
|
||||||
default:
|
|
||||||
if (strcmp(options[optind - 1].name, "usage"))
|
|
||||||
print_usage(size);
|
|
||||||
else {
|
|
||||||
if (isprint(optopt)) {
|
|
||||||
char invalid_option[2] = {optopt, 0};
|
|
||||||
WARN_LOG(invalid_option);
|
|
||||||
}
|
|
||||||
dprintf(2, "Try 'ping --help' or 'ping --usage' for more information.\n");
|
|
||||||
exit(64);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
free(options);
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
34
parsing/sources/target.c
Normal file
34
parsing/sources/target.c
Normal file
|
|
@ -0,0 +1,34 @@
|
||||||
|
/* ************************************************************************** */
|
||||||
|
/* */
|
||||||
|
/* ::: :::::::: */
|
||||||
|
/* target.c :+: :+: :+: */
|
||||||
|
/* +:+ +:+ +:+ */
|
||||||
|
/* By: rparodi <rparodi@student.42.fr> +#+ +:+ +#+ */
|
||||||
|
/* +#+#+#+#+#+ +#+ */
|
||||||
|
/* Created: 2026/03/30 12:09:48 by rparodi #+# #+# */
|
||||||
|
/* Updated: 2026/03/30 12:33:54 by rparodi ### ########.fr */
|
||||||
|
/* */
|
||||||
|
/* ************************************************************************** */
|
||||||
|
|
||||||
|
#include "macro.h"
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <netdb.h>
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
|
||||||
|
void check_target(const char *target) {
|
||||||
|
struct addrinfo hints = {0}, *res;
|
||||||
|
hints.ai_family = AF_UNSPEC;
|
||||||
|
hints.ai_socktype = SOCK_RAW;
|
||||||
|
hints.ai_protocol = IPPROTO_ICMP;
|
||||||
|
|
||||||
|
int err = getaddrinfo(target, NULL, &hints, &res);
|
||||||
|
if (err != 0) {
|
||||||
|
ERROR_LOG("ft_ping: unknown host");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
freeaddrinfo(res);
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue