🏗️」 wip: parsing should be good

This commit is contained in:
2025-08-12 12:37:05 +02:00
parent 4add0312bc
commit 577563da37
6 changed files with 88 additions and 23 deletions

View File

@ -19,12 +19,13 @@ static options_t options[] = {
{"verbose", 'v', "verbose output", 0, GRP}, {"verbose", 'v', "verbose output", 0, GRP},
#undef GRP #undef GRP
#define GRP 2 // AKA bonus #define GRP 2 // AKA bonus
{"count", 'c', "stop after sending NUMBER packets", 1, {"count", 'c', "stop after sending NUMBER packets", 1, GRP},
GRP},
{"size", 's', "send NUMBER data octets", 1, GRP}, {"size", 's', "send NUMBER data octets", 1, GRP},
{"timeout", 'w', "stop after N seconds", 1, GRP}, {"timeout", 'w', "stop after N seconds", 1, GRP},
{"ttl", 't', "specify N as time-to-live", 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 #undef GRP
}; };
@ -43,12 +44,17 @@ static options_t options[] = {
} \ } \
args->arg[i] = *(av + 1); \ 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 * @brief Can be used to print the help message if no host (or addr) are
* provided * provided
*/ */
void print_no_host(char *av); void print_parse_err(error_t err, char *opt);
void print_help(void); void print_help(void);
void print_usage(void);

View File

@ -8,6 +8,7 @@
typedef struct { typedef struct {
bool opts[OPT_NB]; bool opts[OPT_NB];
char *arg[OPT_NB]; char *arg[OPT_NB];
char **hosts;
} args_t; } args_t;
/** /**

View File

@ -1 +1,3 @@
#pragma once #pragma once
extern char *exec_name;

View File

@ -1,8 +1,10 @@
#include "ping.h"
#include <help.h> #include <help.h>
#include <stdint.h> #include <stdint.h>
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <unistd.h>
void print_help(void) { void print_help(void) {
printf("Usage: ping [OPTION...] HOST ...\n"); printf("Usage: ping [OPTION...] HOST ...\n");
@ -52,7 +54,26 @@ void print_help(void) {
printf("Report bugs to <noreply@adjoly.fr> :D.\n"); printf("Report bugs to <noreply@adjoly.fr> :D.\n");
} }
void print_no_host(char *av) { void print_parse_err(error_t err, char *opt) {
printf("%s: missing host operand\n", av); switch (err) {
printf("Try 'ping --help' or 'ping -?' for more information.\n"); 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");
} }

View File

@ -6,42 +6,58 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
char *exec_name;
void init_args_t(args_t *args) { void init_args_t(args_t *args) {
OPT_WHILE { OPT_WHILE {
args->opts[i] = false; args->opts[i] = false;
args->arg[i] = NULL; args->arg[i] = NULL;
args->hosts = NULL;
i++; i++;
} }
} }
int handle_options(args_t *args, char **av) { int handle_options(args_t *args, char **av) {
// TODO: need to make this function D:
if (args->opts[1]) { if (args->opts[1]) {
print_help(); print_help();
return EXIT_SUCCESS; return EXIT_SUCCESS;
} else if (args->opts[0]) { } else if (args->opts[0]) {
print_no_host(*av); print_usage();
return EX_USAGE; return EX_USAGE;
} else if (args->opts[2]) { } else if (args->opts[2]) {
printf("adjoly's %s: v%s\n", *av, FT_PING_V); printf("adjoly's %s: v%s\n", *av, FT_PING_V);
return EXIT_SUCCESS; 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; return EXIT_SUCCESS;
} }
int main(int ac, char **av) { int main(int ac, char **av) {
exec_name = *av;
args_t args; args_t args;
init_args_t(&args); init_args_t(&args);
if (ac > 1) { if (ac > 1) {
int ret = opt_parse(av, &args); int ret = opt_parse(av, &args);
if (ret == -1) if (ret == -1) {
free(args.hosts);
return EXIT_SUCCESS; return EXIT_SUCCESS;
else if (ret != EXIT_SUCCESS) }
else if (ret != EXIT_SUCCESS) {
free(args.hosts);
return ret; return ret;
else }
return handle_options(&args, av); else {
ret = handle_options(&args, av);
free(args.hosts);
return ret;
}
} else { } else {
print_no_host(*av); print_parse_err(MISSING_HOST, NULL);
return EX_USAGE; return EX_USAGE;
} }
return EXIT_SUCCESS; return EXIT_SUCCESS;

View File

@ -10,39 +10,58 @@
int handle_long_args(char **av, args_t *args) { int handle_long_args(char **av, args_t *args) {
OPT_WHILE { OPT_WHILE {
if (strncmp((*av) + 2, options[i].name, strlen(options[i].name)) == 0) { if (strncmp((*av) + 2, options[i].name, strlen(options[i].name)) == 0) {
OPT_HANDLE(i) OPT_HANDLE(i);
} }
i++; i++;
} }
return EXIT_SUCCESS; print_parse_err(INVALID_OPT, (*av) + 2);
return EXIT_FAILURE;
} }
int opt_parse(char **av, args_t *args) { int opt_parse(char **av, args_t *args) {
char *exec_name = *av; av++;
while (*av != NULL) { while (*av != NULL) {
char *a = *av; char *a = *av;
if (*a == '-') { if (*a == '-') {
char opt = *(a + 1); char opt = *(a + 1);
if (!opt) { if (!opt) {
print_no_host(exec_name); print_parse_err(MISSING_HOST, 0);
return EX_USAGE; return EX_USAGE;
} else if (opt == '-') { } else if (opt == '-') {
int ret = handle_long_args(av, args); int ret = handle_long_args(av, args);
if (ret == EX_USAGE) { if (ret != EXIT_SUCCESS) {
print_no_host(exec_name); if (ret == EX_USAGE)
return EX_USAGE; print_parse_err(NEED_ARG, (*av) + 2);
return ret;
} }
} else { } else {
OPT_WHILE { OPT_WHILE {
if (opt == options[i].opt) { if (opt == options[i].opt) {
OPT_HANDLE(i) OPT_HANDLE(i)
} else {
print_parse_err(INVALID_OPT, a);
return EXIT_FAILURE;
} }
i++; i++;
} }
} }
} else { } 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++; av++;
} }