931d68cd20dbeed1a99c948ec0a0ed17d430cc67
[proxmark3-svn] / client / cliparser / cliparser.c
1 //-----------------------------------------------------------------------------
2 // Copyright (C) 2017 Merlok
3 //
4 // This code is licensed to you under the terms of the GNU GPL, version 2 or,
5 // at your option, any later version. See the LICENSE.txt file for the text of
6 // the license.
7 //-----------------------------------------------------------------------------
8 // Command line parser core commands
9 //-----------------------------------------------------------------------------
10
11 #include "cliparser.h"
12 #include <stdio.h>
13 #include <string.h>
14
15 void **argtable = NULL;
16 size_t argtableLen = 0;
17 char *programName = NULL;
18 char *programHint = NULL;
19 char *programHelp = NULL;
20 char buf[500] = {0};
21
22 int CLIParserInit(char *vprogramName, char *vprogramHint, char *vprogramHelp) {
23 argtable = NULL;
24 argtableLen = 0;
25 programName = vprogramName;
26 programHint = vprogramHint;
27 programHelp = vprogramHelp;
28 memset(buf, 0x00, 500);
29
30 return 0;
31 }
32
33 int CLIParserParseArg(int argc, char **argv, void* vargtable[], size_t vargtableLen, bool allowEmptyExec) {
34 int nerrors;
35
36 argtable = vargtable;
37 argtableLen = vargtableLen;
38
39 /* verify the argtable[] entries were allocated sucessfully */
40 if (arg_nullcheck(argtable) != 0) {
41 /* NULL entries were detected, some allocations must have failed */
42 printf("ERROR: Insufficient memory\n");
43 return 2;
44 }
45 /* Parse the command line as defined by argtable[] */
46 nerrors = arg_parse(argc, argv, argtable);
47
48 /* special case: '--help' takes precedence over error reporting */
49 if ((argc < 2 && !allowEmptyExec) ||((struct arg_lit *)argtable[0])->count > 0) { // help must be the first record
50 printf("Usage: %s", programName);
51 arg_print_syntaxv(stdout, argtable, "\n");
52 if (programHint)
53 printf("%s\n\n", programHint);
54 arg_print_glossary(stdout, argtable, " %-20s %s\n");
55 printf("\n");
56 if (programHelp)
57 printf("%s \n", programHelp);
58
59 return 1;
60 }
61
62 /* If the parser returned any errors then display them and exit */
63 if (nerrors > 0) {
64 /* Display the error details contained in the arg_end struct.*/
65 arg_print_errors(stdout, ((struct arg_end *)argtable[vargtableLen - 1]), programName);
66 printf("Try '%s --help' for more information.\n", programName);
67
68 return 3;
69 }
70
71 return 0;
72 }
73
74 enum ParserState {
75 PS_FIRST,
76 PS_ARGUMENT,
77 PS_OPTION,
78 };
79
80 #define isSpace(c)(c == ' ' || c == '\t')
81
82 int CLIParserParseString(const char* str, void* vargtable[], size_t vargtableLen, bool allowEmptyExec) {
83 return CLIParserParseStringEx(str, vargtable, vargtableLen, allowEmptyExec, false);
84 }
85
86 int CLIParserParseStringEx(const char* str, void* vargtable[], size_t vargtableLen, bool allowEmptyExec, bool clueData) {
87 int argc = 0;
88 char *argv[200] = {NULL};
89
90 int len = strlen(str);
91 char *bufptr = buf;
92 char *spaceptr = NULL;
93 enum ParserState state = PS_FIRST;
94
95 argv[argc++] = bufptr;
96 // param0 = program name
97 memcpy(buf, programName, strlen(programName) + 1); // with 0x00
98 bufptr += strlen(programName) + 1;
99 if (len)
100 argv[argc++] = bufptr;
101
102 // parse params
103 for (int i = 0; i < len; i++) {
104 switch(state){
105 case PS_FIRST: // first char
106 if (!clueData || str[i] == '-'){ // first char before space is '-' - next element - option OR not "clueData" for not-option fields
107 state = PS_OPTION;
108
109 if (spaceptr) {
110 bufptr = spaceptr;
111 *bufptr = 0x00;
112 bufptr++;
113 argv[argc++] = bufptr;
114 }
115 }
116 spaceptr = NULL;
117 case PS_ARGUMENT:
118 if (state == PS_FIRST)
119 state = PS_ARGUMENT;
120 if (isSpace(str[i])) {
121 spaceptr = bufptr;
122 state = PS_FIRST;
123 }
124 *bufptr = str[i];
125 bufptr++;
126 break;
127 case PS_OPTION:
128 if (isSpace(str[i])){
129 state = PS_FIRST;
130
131 *bufptr = 0x00;
132 bufptr++;
133 argv[argc++] = bufptr;
134 break;
135 }
136
137 *bufptr = str[i];
138 bufptr++;
139 break;
140 }
141 }
142
143 return CLIParserParseArg(argc, argv, vargtable, vargtableLen, allowEmptyExec);
144 }
145
146 void CLIParserFree() {
147 arg_freetable(argtable, argtableLen);
148 argtable = NULL;
149
150 return;
151 }
152
153 // convertors
154 int CLIParamHexToBuf(struct arg_str *argstr, uint8_t *data, int maxdatalen, int *datalen) {
155 *datalen = 0;
156
157 int ibuf = 0;
158 uint8_t buf[256] = {0};
159 int res = CLIParamStrToBuf(argstr, buf, maxdatalen, &ibuf);
160 if (res || !ibuf)
161 return res;
162
163 switch(param_gethex_to_eol((char *)buf, 0, data, maxdatalen, datalen)) {
164 case 1:
165 printf("Parameter error: Invalid HEX value.\n");
166 return 1;
167 case 2:
168 printf("Parameter error: parameter too large.\n");
169 return 2;
170 case 3:
171 printf("Parameter error: Hex string must have even number of digits.\n");
172 return 3;
173 }
174
175 return 0;
176 }
177
178 int CLIParamStrToBuf(struct arg_str *argstr, uint8_t *data, int maxdatalen, int *datalen) {
179 *datalen = 0;
180 if (!argstr->count)
181 return 0;
182
183 uint8_t buf[256] = {0};
184 int ibuf = 0;
185
186 for (int i = 0; i < argstr->count; i++) {
187 int len = strlen(argstr->sval[i]);
188 memcpy(&buf[ibuf], argstr->sval[i], len);
189 ibuf += len;
190 }
191 buf[ibuf] = 0;
192
193 if (!ibuf)
194 return 0;
195
196 if (ibuf > maxdatalen)
197 return 2;
198
199 memcpy(data, buf, ibuf);
200 *datalen = ibuf;
201
202 return 0;
203 }
204
205
Impressum, Datenschutz