118 lines
4 KiB
C
118 lines
4 KiB
C
#include "trainlog/cli.h"
|
|
|
|
#include <errno.h>
|
|
#include <getopt.h>
|
|
#include <limits.h>
|
|
#include <stdbool.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
#define TRAINLOG_WEB_DEFAULT_PORT 8080U
|
|
|
|
static void cli_diagnostic(char *output, size_t capacity, const char *message)
|
|
{
|
|
if (output != NULL && capacity > 0U)
|
|
(void)snprintf(output, capacity, "%s", message);
|
|
}
|
|
|
|
static int parse_port(const char *value, uint16_t *port)
|
|
{
|
|
char *end = NULL;
|
|
unsigned long parsed;
|
|
if (value == NULL || value[0] == '\0' || value[0] == '-') return -1;
|
|
errno = 0;
|
|
parsed = strtoul(value, &end, 10);
|
|
if (errno != 0 || end == value || *end != '\0' || parsed == 0UL ||
|
|
parsed > 65535UL) return -1;
|
|
*port = (uint16_t)parsed;
|
|
return 0;
|
|
}
|
|
|
|
int trainlog_cli_parse(int argc, char *const argv[], TrainlogCliOptions *options,
|
|
char *diagnostic, size_t diagnostic_capacity)
|
|
{
|
|
static const struct option long_options[] = {
|
|
{"web", no_argument, NULL, 'w'},
|
|
{"port", required_argument, NULL, 1},
|
|
{"help", no_argument, NULL, 'h'},
|
|
{"version", no_argument, NULL, 'V'},
|
|
{NULL, 0, NULL, 0}
|
|
};
|
|
bool web_seen = false;
|
|
bool port_seen = false;
|
|
bool help_seen = false;
|
|
bool version_seen = false;
|
|
int option;
|
|
if (options == NULL || argc < 1 || argv == NULL) return -1;
|
|
options->mode = TRAINLOG_RUN_TUI;
|
|
options->port = TRAINLOG_WEB_DEFAULT_PORT;
|
|
cli_diagnostic(diagnostic, diagnostic_capacity, "");
|
|
opterr = 0;
|
|
optind = 0;
|
|
while ((option = getopt_long(argc, argv, "whV", long_options, NULL)) != -1) {
|
|
switch (option) {
|
|
case 'w':
|
|
if (web_seen) {
|
|
cli_diagnostic(diagnostic, diagnostic_capacity,
|
|
"l'option Web est répétée");
|
|
return -1;
|
|
}
|
|
web_seen = true;
|
|
break;
|
|
case 1:
|
|
if (port_seen) {
|
|
cli_diagnostic(diagnostic, diagnostic_capacity,
|
|
"l'option --port est répétée");
|
|
return -1;
|
|
}
|
|
if (parse_port(optarg, &options->port) != 0) {
|
|
cli_diagnostic(diagnostic, diagnostic_capacity,
|
|
"--port attend un entier compris entre 1 et 65535");
|
|
return -1;
|
|
}
|
|
port_seen = true;
|
|
break;
|
|
case 'h': help_seen = true; break;
|
|
case 'V': version_seen = true; break;
|
|
case '?':
|
|
default:
|
|
cli_diagnostic(diagnostic, diagnostic_capacity,
|
|
"option inconnue ou argument manquant");
|
|
return -1;
|
|
}
|
|
}
|
|
if (optind != argc) {
|
|
cli_diagnostic(diagnostic, diagnostic_capacity,
|
|
"aucun argument positionnel n'est accepté");
|
|
return -1;
|
|
}
|
|
if ((help_seen && version_seen) ||
|
|
((help_seen || version_seen) && (web_seen || port_seen))) {
|
|
cli_diagnostic(diagnostic, diagnostic_capacity,
|
|
"--help et --version doivent être utilisés seuls");
|
|
return -1;
|
|
}
|
|
if (port_seen && !web_seen) {
|
|
cli_diagnostic(diagnostic, diagnostic_capacity,
|
|
"--port n'est valide qu'avec -w ou --web");
|
|
return -1;
|
|
}
|
|
if (help_seen) options->mode = TRAINLOG_RUN_HELP;
|
|
else if (version_seen) options->mode = TRAINLOG_RUN_VERSION;
|
|
else if (web_seen) options->mode = TRAINLOG_RUN_WEB;
|
|
return 0;
|
|
}
|
|
|
|
void trainlog_cli_print_usage(const char *program_name)
|
|
{
|
|
const char *name = program_name != NULL && program_name[0] != '\0'
|
|
? program_name : "trainlog";
|
|
(void)printf(
|
|
"Usage : %s [--help | --version | -w|--web [--port PORT]]\n"
|
|
" sans option lancer la TUI\n"
|
|
" -w, --web lancer le serveur Web local\n"
|
|
" --port PORT port Web explicite (1..65535, défaut 8080)\n"
|
|
" --help afficher cette aide\n"
|
|
" --version afficher la version\n", name);
|
|
}
|