cake
/
p7utils
Archived
1
0
Fork 0
This repository has been archived on 2024-03-16. You can view files and clone it, but cannot push or open issues or pull requests.
p7utils/src/p7os/args.c

181 lines
5.4 KiB
C

/* ************************************************************************** */
/* _____ _ */
/* args.c |_ _|__ _ _| |__ ___ _ _ */
/* | Project: p7os | |/ _ \| | | | '_ \ / _ \ | | | */
/* | | (_) | |_| | | | | __/ |_| | */
/* By: thomas <thomas@touhey.fr> |_|\___/ \__,_|_| |_|\___|\__, |.fr */
/* Last updated: 2016/09/28 06:00:10 |___/ */
/* */
/* ************************************************************************** */
#include "main.h"
#include <stdlib.h>
#include <string.h>
#include <getopt.h>
#include <errno.h>
/* ************************************************************************** */
/* Help and version messages */
/* ************************************************************************** */
/* The version message - that's when the President comes in */
static const char version_message[] =
QUOTE(BIN) " - from " QUOTE(NAME) " v" QUOTE(VERSION) " (licensed under GPLv2)\n"
"Maintained by " QUOTE(MAINTAINER) ".\n"
"\n"
"This is free software; see the source for copying conditions.\n"
"There is NO warranty; not even for MERCHANTABILITY or\n"
"FITNESS FOR A PARTICULAR PURPOSE.";
/* Main help message */
static const char help_main[] =
"Usage: " QUOTE(BIN) " [--version|-v] [--help|-h] [--device /dev/omg0]\n"
" <subcommand> [options...]\n"
"\n"
"Subcommands you can use are :\n"
" prepare Prepare server on distant machine\n"
" get Get the OS image\n"
"\n"
"All subcommands that aren't \"prepare\" require \"prepare\" to be run\n"
"before them.\n"
"\n"
"General options:\n"
" -h, --help Display the help page of the (sub)command and quit.\n"
" -v, --version Display the version message and quit.\n"
" --device dev The calculator device (usually /dev/ttyUSBx).\n"
" By default, will use the first appropriate device found.\n"
"\n"
"Type \"" QUOTE(BIN) " <subcommand> --help\" for some help about a subcommand.\n"
"Report bugs to " QUOTE(MAINTAINER) ".";
/* Subcommands help messages footer */
#define FOOT \
"\nType \"" QUOTE(BIN) " --help\" for other subcommands and general options."
/* Help message for prepare subcommand */
static const char help_prepare[] =
"Usage: p7os prepare\n"
"Send the P7 server on the calculator for further operations.\n"
"This must be used before any other p7os operation.\n"
FOOT;
/* Help message for get subcommand */
static const char help_get[] =
"Usage: p7os get [-o <os.bin>]\n"
"Get the calculator OS image.\n"
"You must have \"p7os prepare\"-ed before.\n"
"\n"
"Options are :\n"
" -o <os.bin> Where to store the image (default is \"os.bin\")\n"
FOOT;
/* ************************************************************************** */
/* Main function */
/* ************************************************************************** */
/* Help macro */
#define sub_init(CMD, NARGS) { \
if (help || pc != (NARGS)) { \
puts(help_##CMD); \
return (1); \
} \
}
/**
* parse_args:
* Args parsing main function.
*
* Based on my very first experiment with getopt.
*
* @arg ac the arguments count
* @arg av the arguments values
* @arg args the parsed args pointer
* @return if has been parsed successfully
*/
int parse_args(int ac, char **av, args_t *args)
{
/* initialize args */
*args = (args_t){
.device = NULL,
.local = NULL, .localpath = NULL
};
/* define options */
const char short_options[] = "hvo:";
const struct option long_options[] = {
{"help", no_argument, NULL, 'h'},
{"version", no_argument, NULL, 'v'},
{"device", required_argument, NULL, 'p'},
{"output", required_argument, NULL, 'o'},
{NULL, 0, NULL, 0}
};
/* get all options */
int c; opterr = 0;
int help = 0, version = 0;
const char *s_out = "os.bin";
while ((c = getopt_long(ac, av, short_options, long_options, NULL)) != -1) {
switch (c) {
/* help */
case 'h': help = 1; break;
/* version */
case 'v': version = 1; break;
/* device */
case 'p': args->device = optarg; break;
/* output */
case 'o': s_out = optarg; break;
/* error */
case '?':
if (optopt == 'o')
log("-o, --output: expected an argument\n");
else if (optopt == 'p')
log("--device: expected an argument\n");
else
break;
return (1);
}
}
/* check for version */
if (version) {
puts(version_message);
return (1);
}
/* get non-option arguments (subcommand and parameters) */
int pc = ac - optind;
char **pv = &av[optind];
char *sub = pc ? pv[0] : NULL;
pc--; pv++;
/* subcommand. */
char fpmode[2] = "r";
if (!sub || !strcmp(sub, "help")) {
puts(help_main);
return (1);
} else if (!strcmp(sub, "version")) {
puts(version_message);
return (1);
} else if (!strcmp(sub, "prepare")) {
sub_init(prepare, 0)
} else if (!strcmp(sub, "get")) {
sub_init(get, 0)
args->localpath = s_out;
fpmode[0] = 'w';
} else {
log("Unknown subcommand '%s'.\n", sub);
return (1);
}
/* open destination file */
if (args->localpath) {
args->local = fopen(args->localpath, fpmode);
if (!args->local) {
log("Could not open local file: '%s'\n", strerror(errno));
return (1);
}
}
/* everything went well :) */
return (0);
}