「🏗️」 wip: parsing should be good
This commit is contained in:
@ -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);
|
||||||
|
@ -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;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1 +1,3 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
extern char *exec_name;
|
||||||
|
27
src/help.c
27
src/help.c
@ -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");
|
||||||
}
|
}
|
||||||
|
30
src/main.c
30
src/main.c
@ -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;
|
||||||
|
@ -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++;
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user