proxmark3/client/deps/cliparser/cliparser.c

213 lines
6.4 KiB
C
Raw Normal View History

//-----------------------------------------------------------------------------
// Copyright (C) 2017 Merlok
//
// This code is licensed to you under the terms of the GNU GPL, version 2 or,
// at your option, any later version. See the LICENSE.txt file for the text of
// the license.
//-----------------------------------------------------------------------------
// Command line parser core commands
//-----------------------------------------------------------------------------
#include "cliparser.h"
#include <string.h>
2020-06-01 23:30:33 +08:00
#include <stdlib.h>
2020-06-10 17:33:15 +08:00
#ifndef ARRAYLEN
# define ARRAYLEN(x) (sizeof(x)/sizeof((x)[0]))
#endif
2020-06-01 23:30:33 +08:00
int CLIParserInit(CLIParserContext **ctx, const char *vprogramName, const char *vprogramHint, const char *vprogramHelp) {
*ctx = malloc(sizeof(CLIParserContext));
if (!*ctx) {
printf("ERROR: Insufficient memory\n");
fflush(stdout);
return 2;
}
(*ctx)->argtable = NULL;
(*ctx)->argtableLen = 0;
(*ctx)->programName = vprogramName;
(*ctx)->programHint = vprogramHint;
(*ctx)->programHelp = vprogramHelp;
memset((*ctx)->buf, 0x00, sizeof((*ctx)->buf));
2019-03-10 06:35:06 +08:00
return 0;
}
2020-06-01 23:30:33 +08:00
int CLIParserParseArg(CLIParserContext *ctx, int argc, char **argv, void *vargtable[], size_t vargtableLen, bool allowEmptyExec) {
2019-03-10 06:35:06 +08:00
int nerrors;
2020-06-01 23:30:33 +08:00
ctx->argtable = vargtable;
ctx->argtableLen = vargtableLen;
2019-03-10 06:35:06 +08:00
/* verify the argtable[] entries were allocated sucessfully */
2020-06-01 23:30:33 +08:00
if (arg_nullcheck(ctx->argtable) != 0) {
2019-03-10 06:35:06 +08:00
/* NULL entries were detected, some allocations must have failed */
printf("ERROR: Insufficient memory\n");
fflush(stdout);
2019-03-10 06:35:06 +08:00
return 2;
}
/* Parse the command line as defined by argtable[] */
2020-06-01 23:30:33 +08:00
nerrors = arg_parse(argc, argv, ctx->argtable);
2019-03-10 06:35:06 +08:00
/* special case: '--help' takes precedence over error reporting */
2020-06-01 23:30:33 +08:00
if ((argc < 2 && !allowEmptyExec) || ((struct arg_lit *)(ctx->argtable)[0])->count > 0) { // help must be the first record
printf("Usage: %s", ctx->programName);
arg_print_syntaxv(stdout, ctx->argtable, "\n");
if (ctx->programHint)
printf("%s\n\n", ctx->programHint);
arg_print_glossary(stdout, ctx->argtable, " %-20s %s\n");
2019-03-10 06:35:06 +08:00
printf("\n");
2020-06-01 23:30:33 +08:00
if (ctx->programHelp)
printf("%s \n", ctx->programHelp);
2019-03-10 06:35:06 +08:00
fflush(stdout);
2019-03-10 06:35:06 +08:00
return 1;
}
/* If the parser returned any errors then display them and exit */
if (nerrors > 0) {
/* Display the error details contained in the arg_end struct.*/
2020-06-01 23:30:33 +08:00
arg_print_errors(stdout, ((struct arg_end *)(ctx->argtable)[vargtableLen - 1]), ctx->programName);
printf("Try '%s --help' for more information.\n", ctx->programName);
fflush(stdout);
2019-03-10 06:35:06 +08:00
return 3;
}
return 0;
}
enum ParserState {
2019-03-10 06:35:06 +08:00
PS_FIRST,
PS_ARGUMENT,
PS_OPTION,
};
#define isSpace(c)(c == ' ' || c == '\t')
2020-06-01 23:30:33 +08:00
int CLIParserParseString(CLIParserContext *ctx, const char *str, void *vargtable[], size_t vargtableLen, bool allowEmptyExec) {
return CLIParserParseStringEx(ctx, str, vargtable, vargtableLen, allowEmptyExec, false);
}
2020-06-01 23:30:33 +08:00
int CLIParserParseStringEx(CLIParserContext *ctx, const char *str, void *vargtable[], size_t vargtableLen, bool allowEmptyExec, bool clueData) {
2019-03-10 06:35:06 +08:00
int argc = 0;
char *argv[200] = {NULL};
int len = strlen(str);
2020-06-10 17:33:15 +08:00
memset(ctx->buf, 0x00, ARRAYLEN(ctx->buf));
char *bufptr = ctx->buf;
2019-03-10 06:35:06 +08:00
char *spaceptr = NULL;
enum ParserState state = PS_FIRST;
argv[argc++] = bufptr;
// param0 = program name
2020-06-10 17:33:15 +08:00
memcpy(ctx->buf, ctx->programName, strlen(ctx->programName) + 1); // with 0x00
2020-06-01 23:30:33 +08:00
bufptr += strlen(ctx->programName) + 1;
2019-03-10 06:35:06 +08:00
if (len)
argv[argc++] = bufptr;
// parse params
for (int i = 0; i < len; i++) {
2019-03-10 07:00:59 +08:00
switch (state) {
2019-03-10 06:35:06 +08:00
case PS_FIRST: // first char
2019-03-10 07:00:59 +08:00
if (!clueData || str[i] == '-') { // first char before space is '-' - next element - option OR not "clueData" for not-option fields
2019-03-10 06:35:06 +08:00
state = PS_OPTION;
if (spaceptr) {
bufptr = spaceptr;
*bufptr = 0x00;
bufptr++;
argv[argc++] = bufptr;
}
}
spaceptr = NULL;
case PS_ARGUMENT:
if (state == PS_FIRST)
state = PS_ARGUMENT;
if (isSpace(str[i])) {
spaceptr = bufptr;
state = PS_FIRST;
}
*bufptr = str[i];
bufptr++;
break;
case PS_OPTION:
2019-03-10 07:00:59 +08:00
if (isSpace(str[i])) {
2019-03-10 06:35:06 +08:00
state = PS_FIRST;
*bufptr = 0x00;
bufptr++;
argv[argc++] = bufptr;
break;
}
*bufptr = str[i];
bufptr++;
break;
}
}
2020-06-01 23:30:33 +08:00
return CLIParserParseArg(ctx, argc, argv, vargtable, vargtableLen, allowEmptyExec);
}
// convertors
int CLIParamHexToBuf(struct arg_str *argstr, uint8_t *data, int maxdatalen, int *datalen) {
2019-03-10 06:35:06 +08:00
*datalen = 0;
int ibuf = 0;
2019-04-07 18:30:25 +08:00
uint8_t tmp_buf[256] = {0};
int res = CLIParamStrToBuf(argstr, tmp_buf, maxdatalen * 2, &ibuf); // *2 because here HEX
if (res) {
printf("Parameter error: buffer overflow.\n");
fflush(stdout);
2019-03-10 06:35:06 +08:00
return res;
}
if (ibuf == 0) {
return res;
}
2020-04-16 15:01:14 +08:00
2019-04-07 18:30:25 +08:00
switch (param_gethex_to_eol((char *)tmp_buf, 0, data, maxdatalen, datalen)) {
2019-03-10 07:00:59 +08:00
case 1:
printf("Parameter error: Invalid HEX value.\n");
fflush(stdout);
2019-03-10 07:00:59 +08:00
return 1;
case 2:
printf("Parameter error: parameter too large.\n");
fflush(stdout);
2019-03-10 07:00:59 +08:00
return 2;
case 3:
printf("Parameter error: Hex string must have even number of digits.\n");
fflush(stdout);
2019-03-10 07:00:59 +08:00
return 3;
2019-03-10 06:35:06 +08:00
}
return 0;
2018-10-24 23:18:05 +08:00
}
int CLIParamStrToBuf(struct arg_str *argstr, uint8_t *data, int maxdatalen, int *datalen) {
2019-03-10 06:35:06 +08:00
*datalen = 0;
if (!argstr->count)
return 0;
2019-04-07 18:30:25 +08:00
uint8_t tmp_buf[256] = {0};
2019-03-10 06:35:06 +08:00
int ibuf = 0;
2019-03-10 06:35:06 +08:00
for (int i = 0; i < argstr->count; i++) {
int len = strlen(argstr->sval[i]);
2019-04-07 18:30:25 +08:00
memcpy(&tmp_buf[ibuf], argstr->sval[i], len);
2019-03-10 06:35:06 +08:00
ibuf += len;
}
2019-04-07 18:30:25 +08:00
tmp_buf[ibuf] = 0;
2019-03-10 06:35:06 +08:00
if (!ibuf)
return 0;
2018-10-24 23:18:05 +08:00
if (ibuf > maxdatalen) {
fflush(stdout);
2019-03-10 06:35:06 +08:00
return 2;
}
2019-04-07 18:30:25 +08:00
memcpy(data, tmp_buf, ibuf);
2019-03-10 06:35:06 +08:00
*datalen = ibuf;
return 0;
}