textual
[RRG-proxmark3.git] / client / src / cmdmain.c
blobf291b6dfb47b757f3efdf7800815eaae83bcf986
1 //-----------------------------------------------------------------------------
2 // Copyright (C) 2010 iZsh <izsh at fail0verflow.com>
3 //
4 // Modified 2018 iceman <iceman at iuse.se>
5 // This code is licensed to you under the terms of the GNU GPL, version 2 or,
6 // at your option, any later version. See the LICENSE.txt file for the text of
7 // the license.
8 //-----------------------------------------------------------------------------
9 // Main command parser entry point
10 //-----------------------------------------------------------------------------
12 // ensure gmtime_r is available even with -std=c99; must be included before
13 #if !defined(_WIN32)
14 #define _POSIX_C_SOURCE 200112L
15 #endif
16 #include "cmdmain.h"
18 #include <string.h>
19 #include <ctype.h>
20 #include <time.h> // MingW
21 #include <stdlib.h> // calloc
23 #include "comms.h"
24 #include "cmdhf.h"
25 #include "cmddata.h"
26 #include "cmdhw.h"
27 #include "cmdlf.h"
28 #include "cmdnfc.h"
29 #include "cmdtrace.h"
30 #include "cmdscript.h"
31 #include "cmdcrc.h"
32 #include "cmdanalyse.h"
33 #include "emv/cmdemv.h" // EMV
34 #include "cmdflashmem.h" // rdv40 flashmem commands
35 #include "cmdsmartcard.h" // rdv40 smart card ISO7816 commands
36 #include "cmdusart.h" // rdv40 FPC USART commands
37 #include "cmdwiegand.h" // wiegand commands
38 #include "ui.h"
39 #include "util_posix.h"
40 #include "commonutil.h" // ARRAYLEN
41 #include "preferences.h"
42 #include "cliparser.h"
44 static int CmdHelp(const char *Cmd);
46 static void AppendDate(char *s, size_t slen, const char *fmt) {
47 struct tm *ct, tm_buf;
48 time_t now = time(NULL);
49 #if defined(_WIN32)
50 ct = gmtime_s(&tm_buf, &now) == 0 ? &tm_buf : NULL;
51 #else
52 ct = gmtime_r(&now, &tm_buf);
53 #endif
54 if (fmt == NULL)
55 strftime(s, slen, "%Y-%m-%dT%H:%M:%SZ", ct); // ISO8601
56 else
57 strftime(s, slen, fmt, ct);
60 static int lf_search_plus(const char *Cmd) {
62 sample_config oldconfig;
63 memset(&oldconfig, 0, sizeof(sample_config));
65 int retval = lf_getconfig(&oldconfig);
67 if (retval != PM3_SUCCESS) {
68 PrintAndLogEx(ERR, "failed to get current device config");
69 return retval;
72 // Divisor : frequency(khz)
73 // 95 88 47 31 23
74 // 125.00 134.83 250.00 375.00 500.00
76 int16_t default_divisor[] = {95, 88, 47, 31, 23};
79 default LF config is set to:
80 decimation = 1
81 bits_per_sample = 8
82 averaging = YES
83 divisor = 95 (125kHz)
84 trigger_threshold = 0
85 samples_to_skip = 0
86 verbose = YES
88 sample_config config = {
89 .decimation = 1,
90 .bits_per_sample = 8,
91 .averaging = 1,
92 .trigger_threshold = 0,
93 .samples_to_skip = 0,
94 .verbose = false
97 // Iteration defaults
98 for (int i = 0; i < ARRAYLEN(default_divisor); ++i) {
100 if (kbd_enter_pressed()) {
101 PrintAndLogEx(INFO, "Keyboard pressed. Done.");
102 break;
104 // Try to change config!
105 uint32_t d;
106 d = config.divisor = default_divisor[i];
107 PrintAndLogEx(INFO, "--> trying (" _GREEN_("%d.%02d kHz")")", 12000 / (d + 1), ((1200000 + (d + 1) / 2) / (d + 1)) - ((12000 / (d + 1)) * 100));
109 retval = lf_config(&config);
110 if (retval != PM3_SUCCESS)
111 break;
113 // The config for pm3 is changed, we can trying search!
114 retval = CmdLFfind(Cmd);
115 if (retval == PM3_SUCCESS)
116 break;
120 lf_config(&oldconfig);
121 return retval;
124 static int CmdAuto(const char *Cmd) {
125 CLIParserContext *ctx;
126 CLIParserInit(&ctx, "auto",
127 "Run LF SEARCH / HF SEARCH / DATA PLOT / DATA SAVE",
128 "auto"
131 void *argtable[] = {
132 arg_param_begin,
133 arg_lit0("c", NULL, "Continue searching even after a first hit"),
134 arg_param_end
136 CLIExecWithReturn(ctx, Cmd, argtable, true);
137 bool exit_first = (arg_get_lit(ctx, 1) == false);
138 CLIParserFree(ctx);
140 PrintAndLogEx(INFO, "lf search");
141 int ret = CmdLFfind("");
142 if (ret == PM3_SUCCESS && exit_first)
143 return ret;
145 PrintAndLogEx(INFO, "hf search");
146 ret = CmdHFSearch("");
147 if (ret == PM3_SUCCESS && exit_first)
148 return ret;
150 PrintAndLogEx(INFO, "lf search - unknown");
151 ret = lf_search_plus("");
152 if (ret == PM3_SUCCESS && exit_first)
153 return ret;
155 if (ret != PM3_SUCCESS)
156 PrintAndLogEx(INFO, "Failed both LF / HF SEARCH,");
158 PrintAndLogEx(INFO, "Trying " _YELLOW_("`lf read`") " and save a trace for you");
160 CmdPlot("");
161 lf_read(false, 40000);
162 char *fname = calloc(100, sizeof(uint8_t));
163 AppendDate(fname, 100, "-f lf_unknown_%Y-%m-%d_%H:%M");
164 CmdSave(fname);
165 free(fname);
166 return PM3_SUCCESS;
169 int CmdRem(const char *Cmd) {
170 CLIParserContext *ctx;
171 CLIParserInit(&ctx, "rem",
172 "Add a text line in log file",
173 "rem my message -> adds a timestamp with `my message`"
176 void *argtable[] = {
177 arg_param_begin,
178 arg_strx1(NULL, NULL, NULL, "message line you want inserted"),
179 arg_param_end
181 CLIExecWithReturn(ctx, Cmd, argtable, false);
183 struct arg_str *foo = arg_get_str(ctx, 1);
184 size_t count = 0;
185 size_t len = 0;
186 do {
187 count += strlen(foo->sval[len]);
188 } while (len++ < (foo->count - 1));
190 char s[count + foo->count];
191 memset(s, 0, sizeof(s));
193 len = 0;
194 do {
195 snprintf(s + strlen(s), sizeof(s) - strlen(s), "%s ", foo->sval[len]);
196 } while (len++ < (foo->count - 1));
198 CLIParserFree(ctx);
199 char buf[22] = {0};
200 AppendDate(buf, sizeof(buf), NULL);
201 PrintAndLogEx(SUCCESS, "%s remark: %s", buf, s);
202 return PM3_SUCCESS;
205 static int CmdHints(const char *Cmd) {
207 CLIParserContext *ctx;
208 CLIParserInit(&ctx, "hints",
209 "Turn on/off hints",
210 "hints --on\n"
211 "hints -1\n"
214 void *argtable[] = {
215 arg_param_begin,
216 arg_lit0("1", "on", "turn on hints"),
217 arg_lit0("0", "off", "turn off hints"),
218 arg_param_end
220 CLIExecWithReturn(ctx, Cmd, argtable, true);
222 bool turn_on = arg_get_lit(ctx, 1);
223 bool turn_off = arg_get_lit(ctx, 2);
224 CLIParserFree(ctx);
226 if (turn_on && turn_off) {
227 PrintAndLogEx(ERR, "you can't turn off and on at the same time");
228 return PM3_EINVARG;
231 if (turn_off) {
232 session.show_hints = false;
233 } else if (turn_on) {
234 session.show_hints = true;
237 PrintAndLogEx(INFO, "Hints are %s", (session.show_hints) ? "ON" : "OFF");
238 return PM3_SUCCESS;
241 static int CmdMsleep(const char *Cmd) {
242 CLIParserContext *ctx;
243 CLIParserInit(&ctx, "msleep",
244 "Sleep for given amount of milliseconds",
245 "msleep 100"
248 void *argtable[] = {
249 arg_param_begin,
250 arg_int0("t", "ms", "<ms>", "time in milliseconds"),
251 arg_param_end
253 CLIExecWithReturn(ctx, Cmd, argtable, false);
254 uint32_t ms = arg_get_u32_def(ctx, 1, 0);
255 CLIParserFree(ctx);
257 if (ms == 0) {
258 PrintAndLogEx(ERR, "Specified invalid input. Can't be zero");
259 return PM3_EINVARG;
262 msleep(ms);
263 return PM3_SUCCESS;
266 static int CmdQuit(const char *Cmd) {
267 CLIParserContext *ctx;
268 CLIParserInit(&ctx, "quit",
269 "Quit the Proxmark3 client terminal",
270 "quit"
272 void *argtable[] = {
273 arg_param_begin,
274 arg_param_end
276 CLIExecWithReturn(ctx, Cmd, argtable, true);
277 CLIParserFree(ctx);
278 return PM3_EFATAL;
281 static int CmdRev(const char *Cmd) {
282 CmdCrc(Cmd);
283 return PM3_SUCCESS;
286 static int CmdPref(const char *Cmd) {
287 CmdPreferences(Cmd);
288 return PM3_SUCCESS;
291 static int CmdClear(const char *Cmd) {
292 CLIParserContext *ctx;
293 CLIParserInit(&ctx, "clear",
294 "Clear the Proxmark3 client terminal screen",
295 "clear"
297 void *argtable[] = {
298 arg_param_begin,
299 arg_param_end
301 CLIExecWithReturn(ctx, Cmd, argtable, true);
302 CLIParserFree(ctx);
303 PrintAndLogEx(NORMAL, _CLEAR_ _TOP_ "");
304 return PM3_SUCCESS;
307 static command_t CommandTable[] = {
309 {"help", CmdHelp, AlwaysAvailable, "Use `" _YELLOW_("<command> help") "` for details of a command"},
310 {"prefs", CmdPref, AlwaysAvailable, "{ Edit client/device preferences... }"},
311 {"--------", CmdHelp, AlwaysAvailable, "----------------------- " _CYAN_("Technology") " -----------------------"},
312 {"analyse", CmdAnalyse, AlwaysAvailable, "{ Analyse utils... }"},
313 {"data", CmdData, AlwaysAvailable, "{ Plot window / data buffer manipulation... }"},
314 {"emv", CmdEMV, AlwaysAvailable, "{ EMV ISO-14443 / ISO-7816... }"},
315 {"hf", CmdHF, AlwaysAvailable, "{ High frequency commands... }"},
316 {"hw", CmdHW, AlwaysAvailable, "{ Hardware commands... }"},
317 {"lf", CmdLF, AlwaysAvailable, "{ Low frequency commands... }"},
318 {"mem", CmdFlashMem, IfPm3Flash, "{ Flash memory manipulation... }"},
319 {"nfc", CmdNFC, AlwaysAvailable, "{ NFC commands... }"},
320 {"reveng", CmdRev, AlwaysAvailable, "{ CRC calculations from RevEng software... }"},
321 {"smart", CmdSmartcard, AlwaysAvailable, "{ Smart card ISO-7816 commands... }"},
322 {"script", CmdScript, AlwaysAvailable, "{ Scripting commands... }"},
323 {"trace", CmdTrace, AlwaysAvailable, "{ Trace manipulation... }"},
324 {"usart", CmdUsart, IfPm3FpcUsartFromUsb, "{ USART commands... }"},
325 {"wiegand", CmdWiegand, AlwaysAvailable, "{ Wiegand format manipulation... }"},
326 {"--------", CmdHelp, AlwaysAvailable, "----------------------- " _CYAN_("General") " -----------------------"},
327 {"auto", CmdAuto, IfPm3Present, "Automated detection process for unknown tags"},
328 {"clear", CmdClear, AlwaysAvailable, "Clear screen"},
329 {"hints", CmdHints, AlwaysAvailable, "Turn hints on / off"},
330 {"msleep", CmdMsleep, AlwaysAvailable, "Add a pause in milliseconds"},
331 {"rem", CmdRem, AlwaysAvailable, "Add a text line in log file"},
332 {"quit", CmdQuit, AlwaysAvailable, ""},
333 {"exit", CmdQuit, AlwaysAvailable, "Exit program"},
334 {NULL, NULL, NULL, NULL}
337 static int CmdHelp(const char *Cmd) {
338 (void)Cmd; // Cmd is not used so far
339 CmdsHelp(CommandTable);
340 return PM3_SUCCESS;
343 //-----------------------------------------------------------------------------
344 // Entry point into our code: called whenever the user types a command and
345 // then presses Enter, which the full command line that they typed.
346 //-----------------------------------------------------------------------------
347 int CommandReceived(char *Cmd) {
348 return CmdsParse(CommandTable, Cmd);
351 command_t *getTopLevelCommandTable(void) {
352 return CommandTable;