「🏗️」 wip: parsing should be good
This commit is contained in:
@ -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);
|
||||
|
@ -8,6 +8,7 @@
|
||||
typedef struct {
|
||||
bool opts[OPT_NB];
|
||||
char *arg[OPT_NB];
|
||||
char **hosts;
|
||||
} args_t;
|
||||
|
||||
/**
|
||||
|
@ -1 +1,3 @@
|
||||
#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 <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
void print_help(void) {
|
||||
printf("Usage: ping [OPTION...] HOST ...\n");
|
||||
@ -52,7 +54,26 @@ void print_help(void) {
|
||||
printf("Report bugs to <noreply@adjoly.fr> :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");
|
||||
}
|
||||
|
30
src/main.c
30
src/main.c
@ -6,42 +6,58 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
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;
|
||||
|
@ -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++;
|
||||
}
|
||||
|
Reference in New Issue
Block a user