1 //-----------------------------------------------------------------------------
2 // Copyright (C) Proxmark3 contributors. See AUTHORS.md for details.
4 // This program is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation, either version 3 of the License, or
7 // (at your option) any later version.
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU General Public License for more details.
14 // See LICENSE.txt for the text of the license.
15 //-----------------------------------------------------------------------------
17 //-----------------------------------------------------------------------------
19 #include "cmdparser.h"
26 #include "util_posix.h" // msleep
29 #define MAX_PM3_INPUT_ARGS_LENGTH 4096
31 bool AlwaysAvailable(void) {
35 bool IfClientDebugEnabled(void) {
39 bool IfPm3Present(void) {
40 if (g_session
.help_dump_mode
)
42 return g_session
.pm3_present
;
45 bool IfPm3Rdv4Fw(void) {
46 if (IfPm3Present() == false)
48 return (g_pm3_capabilities
.is_rdv4
);
51 bool IfPm3Flash(void) {
52 if (IfPm3Present() == false)
54 if (g_pm3_capabilities
.compiled_with_flash
== false)
56 return g_pm3_capabilities
.hw_available_flash
;
59 bool IfPm3Smartcard(void) {
60 if (IfPm3Present() == false)
62 if (g_pm3_capabilities
.compiled_with_smartcard
== false)
64 return g_pm3_capabilities
.hw_available_smartcard
;
67 bool IfPm3FpcUsart(void) {
68 if (IfPm3Present() == false)
70 return g_pm3_capabilities
.compiled_with_fpc_usart
;
73 bool IfPm3FpcUsartHost(void) {
74 if (IfPm3Present() == false)
76 return g_pm3_capabilities
.compiled_with_fpc_usart_host
;
79 bool IfPm3FpcUsartHostFromUsb(void) {
80 // true if FPC USART Host support and if talking from USB-CDC interface
81 if (IfPm3Present() == false)
83 if (g_pm3_capabilities
.compiled_with_fpc_usart_host
== false)
85 return !g_conn
.send_via_fpc_usart
;
88 bool IfPm3FpcUsartDevFromUsb(void) {
89 // true if FPC USART developer support and if talking from USB-CDC interface
90 if (IfPm3Present() == false)
92 if (g_pm3_capabilities
.compiled_with_fpc_usart_dev
== false)
95 return !g_conn
.send_via_fpc_usart
;
98 bool IfPm3FpcUsartFromUsb(void) {
99 // true if FPC USART Host or developer support and if talking from USB-CDC interface
100 return IfPm3FpcUsartHostFromUsb() || IfPm3FpcUsartDevFromUsb();
104 if (IfPm3Present() == false)
106 return g_pm3_capabilities
.compiled_with_lf
;
109 bool IfPm3Hitag(void) {
110 if (IfPm3Present() == false)
112 return g_pm3_capabilities
.compiled_with_hitag
;
115 bool IfPm3EM4x50(void) {
116 if (IfPm3Present() == false)
118 return g_pm3_capabilities
.compiled_with_em4x50
;
121 bool IfPm3EM4x70(void) {
122 if (IfPm3Present() == false)
124 return g_pm3_capabilities
.compiled_with_em4x70
;
127 bool IfPm3Hfsniff(void) {
128 if (IfPm3Present() == false)
130 return g_pm3_capabilities
.compiled_with_hfsniff
;
133 bool IfPm3Hfplot(void) {
134 if (IfPm3Present() == false)
136 return g_pm3_capabilities
.compiled_with_hfplot
;
139 bool IfPm3Iso14443a(void) {
140 if (IfPm3Present() == false)
142 return g_pm3_capabilities
.compiled_with_iso14443a
;
145 bool IfPm3Iso14443b(void) {
146 if (IfPm3Present() == false)
148 return g_pm3_capabilities
.compiled_with_iso14443b
;
151 bool IfPm3Iso14443(void) {
152 if (IfPm3Present() == false)
154 return g_pm3_capabilities
.compiled_with_iso14443a
|| g_pm3_capabilities
.compiled_with_iso14443b
;
157 bool IfPm3Iso15693(void) {
158 if (IfPm3Present() == false)
160 return g_pm3_capabilities
.compiled_with_iso15693
;
163 bool IfPm3Felica(void) {
164 if (IfPm3Present() == false)
166 return g_pm3_capabilities
.compiled_with_felica
;
169 bool IfPm3Legicrf(void) {
170 if (IfPm3Present() == false)
172 return g_pm3_capabilities
.compiled_with_legicrf
;
175 bool IfPm3Iclass(void) {
176 if (IfPm3Present() == false)
178 return g_pm3_capabilities
.compiled_with_iclass
;
181 bool IfPm3NfcBarcode(void) {
182 if (IfPm3Present() == false)
184 return g_pm3_capabilities
.compiled_with_nfcbarcode
;
187 bool IfPm3Lcd(void) {
188 if (IfPm3Present() == false)
190 return g_pm3_capabilities
.compiled_with_lcd
;
193 bool IfPm3Zx8211(void) {
194 if (IfPm3Present() == false)
196 return g_pm3_capabilities
.compiled_with_zx8211
;
199 void CmdsHelp(const command_t Commands
[]) {
200 if (Commands
[0].Name
== NULL
) return;
202 PrintAndLogEx(NORMAL
, "");
205 while (Commands
[i
].Name
) {
206 if (Commands
[i
].IsAvailable()) {
207 uint8_t old_printAndLog
= g_printAndLog
;
208 g_printAndLog
&= PRINTANDLOG_PRINT
;
209 if (Commands
[i
].Name
[0] == '-' || Commands
[i
].Name
[0] == ' ') {
210 PrintAndLogEx(NORMAL
, "%-16s %s", Commands
[i
].Name
, Commands
[i
].Help
);
212 PrintAndLogEx(NORMAL
, _GREEN_("%-16s")" %s", Commands
[i
].Name
, Commands
[i
].Help
);
214 g_printAndLog
= old_printAndLog
;
218 // empty line needed for the help2json parser
219 PrintAndLogEx(NORMAL
, "");
222 int CmdsParse(const command_t Commands
[], const char *Cmd
) {
224 if (g_session
.client_exe_delay
!= 0) {
225 msleep(g_session
.client_exe_delay
);
228 // Help dump children
229 if (strcmp(Cmd
, "XX_internal_command_dump_XX") == 0) {
230 dumpCommandsRecursive(Commands
, 0, false);
233 // Help dump children with help
234 if (strcmp(Cmd
, "XX_internal_command_dump_full_XX") == 0) {
235 dumpCommandsRecursive(Commands
, 0, true);
238 // Markdown help dump children
239 if (strcmp(Cmd
, "XX_internal_command_dump_markdown_XX") == 0) {
240 dumpCommandsRecursive(Commands
, 1, false);
243 // Markdown help dump children with help
244 if (strcmp(Cmd
, "XX_internal_command_dump_markdown_help_XX") == 0) {
245 dumpCommandsRecursive(Commands
, 1, true);
249 if (strcmp(Cmd
, "coffee") == 0) {
250 PrintAndLogEx(NORMAL
, "");
251 PrintAndLogEx(NORMAL
, " ((\n ))\n" _YELLOW_(" .______.\n | |]\n \\ /\n `----ยด\n\n"));
255 if (strcmp(Cmd
, "star") == 0) {
256 PrintAndLogEx(NORMAL
, "");
257 PrintAndLogEx(NORMAL
, " \\o o/");
258 PrintAndLogEx(NORMAL
, " v\\ /v");
259 PrintAndLogEx(NORMAL
, " <\\ />");
260 PrintAndLogEx(NORMAL
, " |\\o/|");
261 PrintAndLogEx(NORMAL
, " _\\__o | o__/");
262 PrintAndLogEx(NORMAL
, " |/ \\|");
263 PrintAndLogEx(NORMAL
, " o/ \\o");
264 PrintAndLogEx(NORMAL
, " /v v\\");
265 PrintAndLogEx(NORMAL
, " /> <\\");
266 PrintAndLogEx(NORMAL
, "");
271 char cmd_name
[128] = {0};
272 memset(cmd_name
, 0, sizeof(cmd_name
));
275 // %n == receives an integer of value equal to the number of chars read so far.
277 sscanf(Cmd
, "%127s%n", cmd_name
, &len
);
281 // iceman: I mistyped "list" so many times with "lsit". No more.
282 char *lsit
= strstr(cmd_name
, "lsit");
284 lsit
[1] = lsit
[2] ^ lsit
[1];
285 lsit
[2] = lsit
[1] ^ lsit
[2];
286 lsit
[1] = lsit
[2] ^ lsit
[1];
290 if (cmd_name
[0] == '#')
293 // find args, check for -h / --help
295 while (Cmd
[tmplen
] == ' ') {
299 bool request_help
= (strcmp(Cmd
+ tmplen
, "-h") == 0) || (strcmp(Cmd
+ tmplen
, "--help") == 0);
302 while (Commands
[i
].Name
) {
303 if (0 == strcmp(Commands
[i
].Name
, cmd_name
)) {
304 if ((Commands
[i
].Help
[0] == '{') || // always allow parsing categories
305 request_help
|| // always allow requesting help
306 Commands
[i
].IsAvailable()) {
309 PrintAndLogEx(WARNING
, "This command is " _YELLOW_("not available") " in this mode");
316 /* try to find exactly one prefix-match */
317 if (!Commands
[i
].Name
) {
321 for (i
= 0; Commands
[i
].Name
; i
++) {
322 if (!strncmp(Commands
[i
].Name
, cmd_name
, strlen(cmd_name
)) && Commands
[i
].IsAvailable()) {
332 if (Commands
[i
].Name
) {
333 while (Cmd
[len
] == ' ') {
336 return Commands
[i
].Parse(Cmd
+ len
);
338 // show help for selected hierarchy or if command not recognised
345 static char pparent
[MAX_PM3_INPUT_ARGS_LENGTH
] = {0};
346 static char *parent
= pparent
;
348 void dumpCommandsRecursive(const command_t cmds
[], int markdown
, bool full_help
) {
349 if (cmds
[0].Name
== NULL
) return;
354 // First, dump all single commands, which are not a container for
357 PrintAndLogEx(NORMAL
, "|%-*s|%-*s|%s", w_cmd
, "command", w_off
, "offline", "description");
358 PrintAndLogEx(NORMAL
, "|%-*s|%-*s|%s", w_cmd
, "-------", w_off
, "-------", "-----------");
359 } else if (! full_help
) {
360 PrintAndLogEx(NORMAL
, "%-*s|%-*s|%s", w_cmd
, "command", w_off
, "offline", "description");
361 PrintAndLogEx(NORMAL
, "%-*s|%-*s|%s", w_cmd
, "-------", w_off
, "-------", "-----------");
364 while (cmds
[i
].Name
) {
366 if ((cmds
[i
].Name
[0] == '-' || strlen(cmds
[i
].Name
) == 0) && ++i
) continue;
367 if (cmds
[i
].Help
[0] == '{' && ++i
) continue;
369 const char *cmd_offline
= "N";
371 if (cmds
[i
].IsAvailable()) {
376 PrintAndLogEx(NORMAL
, "|`%s%-*s`|%-*s|`%s`", parent
, w_cmd
- (int)strlen(parent
) - 2, cmds
[i
].Name
, w_off
, cmd_offline
, cmds
[i
].Help
);
377 } else if (full_help
) {
378 PrintAndLogEx(NORMAL
, "---------------------------------------------------------------------------------------");
379 PrintAndLogEx(NORMAL
, _RED_("%s%-*s\n") "available offline: %s", parent
, w_cmd
- (int)strlen(parent
), cmds
[i
].Name
, cmds
[i
].IsAvailable() ? _GREEN_("yes") : _RED_("no"));
380 cmds
[i
].Parse("--help");
382 PrintAndLogEx(NORMAL
, "%s%-*s|%-*s|%s", parent
, w_cmd
- (int)strlen(parent
), cmds
[i
].Name
, w_off
, cmd_offline
, cmds
[i
].Help
);
386 PrintAndLogEx(NORMAL
, "\n");
389 // Then, print the categories. These will go into subsections with their own tables
390 while (cmds
[i
].Name
) {
392 if ((cmds
[i
].Name
[0] == '-' || strlen(cmds
[i
].Name
) == 0) && ++i
) continue;
393 if (cmds
[i
].Help
[0] != '{' && ++i
) continue;
396 PrintAndLogEx(NORMAL
, "=======================================================================================");
397 PrintAndLogEx(NORMAL
, _RED_("%s%s\n\n ")_CYAN_("%s\n"), parent
, cmds
[i
].Name
, cmds
[i
].Help
);
399 PrintAndLogEx(NORMAL
, "### %s%s\n\n %s\n", parent
, cmds
[i
].Name
, cmds
[i
].Help
);
402 char currentparent
[MAX_PM3_INPUT_ARGS_LENGTH
] = {0};
403 snprintf(currentparent
, sizeof currentparent
, "%s%s ", parent
, cmds
[i
].Name
);
405 char *old_parent
= parent
;
406 parent
= currentparent
;
407 // This is what causes the recursion, since commands Parse-implementation
408 // in turn calls the CmdsParse above.
410 cmds
[i
].Parse("XX_internal_command_dump_markdown_XX");
411 } else if (full_help
) {
412 cmds
[i
].Parse("XX_internal_command_dump_full_XX");
414 cmds
[i
].Parse("XX_internal_command_dump_XX");