Add SKIPREADLINE support to make and cmake

It's mostly for headless support.
At the moment, for interactive uage without readline, some commands will exit the client prematurely if they use kbd_enter_pressed().
This commit is contained in:
Philippe Teuwen
2020-06-08 22:15:47 +02:00
parent 4372a728f7
commit def475e747
5 changed files with 109 additions and 27 deletions

View File

@@ -73,12 +73,13 @@ static int usage_legic_sim(void) {
}
static int usage_legic_wrbl(void) {
PrintAndLogEx(NORMAL, "Write data to a LEGIC Prime tag. It autodetects tagsize to make sure size\n");
PrintAndLogEx(NORMAL, "Usage: hf legic wrbl [h] [o <offset>] [d <data (hex symbols)>]\n");
PrintAndLogEx(NORMAL, "Usage: hf legic wrbl [h] [o <offset>] [d <data (hex symbols)>] [y]\n");
PrintAndLogEx(NORMAL, "Options:");
PrintAndLogEx(NORMAL, " h : this help");
PrintAndLogEx(NORMAL, " o <offset> : (hex) offset in data array to start writing");
//PrintAndLogEx(NORMAL, " <IV> : (optional) Initialization vector to use (ODD and 7bits)");
PrintAndLogEx(NORMAL, " d <data> : (hex symbols) bytes to write ");
PrintAndLogEx(NORMAL, " y : Auto-confirm dangerous operations ");
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(NORMAL, "Examples:");
PrintAndLogEx(NORMAL, _YELLOW_(" hf legic wrbl o 10 d 11223344 - Write 0x11223344 starting from offset 0x10"));
@@ -596,6 +597,7 @@ static int CmdLegicWrbl(const char *Cmd) {
uint8_t *data = NULL;
uint8_t cmdp = 0;
bool errors = false;
bool autoconfirm = false;
int len = 0, bg, en;
uint32_t offset = 0, IV = 0x55;
@@ -655,6 +657,10 @@ static int CmdLegicWrbl(const char *Cmd) {
errors = true;
break;
}
case 'y': {
autoconfirm = true;
break;
}
default: {
PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp));
errors = true;
@@ -693,23 +699,28 @@ static int CmdLegicWrbl(const char *Cmd) {
return PM3_EOUTOFBOUND;
}
if (offset == 5 || offset == 6) {
if ((offset == 5 || offset == 6) && (! autoconfirm)) {
PrintAndLogEx(NORMAL, "############# DANGER ################");
PrintAndLogEx(NORMAL, "# changing the DCF is irreversible #");
PrintAndLogEx(NORMAL, "#####################################");
#ifndef ANDROID
char *answer = readline("do you really want to continue? y(es) n(o) : ");
bool overwrite = (answer[0] == 'y' || answer[0] == 'Y');
const char *confirm = "Do you really want to continue? y(es)/n(o) : ";
bool overwrite = false;
#ifdef HAVE_READLINE
char *answer = readline(confirm);
overwrite = (answer[0] == 'y' || answer[0] == 'Y');
#else
printf("%s", confirm);
char *answer = NULL;
size_t anslen = 0;
if (getline(&answer, &anslen, stdin) > 0) {
overwrite = (answer[0] == 'y' || answer[0] == 'Y');
}
#endif
free(answer);
if (!overwrite) {
PrintAndLogEx(NORMAL, "command cancelled");
return PM3_EOPABORTED;
}
#else
PrintAndLogEx(NORMAL, "\n No interactive support on Android. ");
PrintAndLogEx(NORMAL, " So no confirmation asked, beware! ");
#endif
}
legic_chk_iv(&IV);

View File

@@ -15,8 +15,11 @@
#include <stdio.h> // for Mingw readline
#include <limits.h>
#include <unistd.h>
#ifdef HAVE_READLINE
#include <readline/readline.h>
#include <readline/history.h>
#endif
#include <ctype.h>
#include "usart_defs.h"
#include "util_posix.h"
#include "proxgui.h"
@@ -117,6 +120,7 @@ static void prompt_compose(char *buf, size_t buflen, const char *promptctx, cons
snprintf(buf, buflen - 1, PROXPROMPT_COMPOSE, promptdev, promptctx);
}
#ifdef HAVE_READLINE
static int check_comm(void) {
// If communications thread goes down. Device disconnected then this should hook up PM3 again.
if (IsCommunicationThreadDead() && session.pm3_present) {
@@ -132,6 +136,7 @@ static int check_comm(void) {
}
return 0;
}
#endif
// first slot is always NULL, indicating absence of script when idx=0
static FILE *cmdscriptfile[MAX_NESTED_CMDSCRIPT + 1] = {0};
@@ -208,6 +213,7 @@ main_loop(char *script_cmds_file, char *script_cmd, bool stayInCommandLoop) {
}
}
#ifdef HAVE_READLINE
char *my_history_path = NULL;
if (searchHomeFilePath(&my_history_path, NULL, PROXHISTORY, true) != PM3_SUCCESS) {
PrintAndLogEx(ERR, "No history will be recorded");
@@ -215,6 +221,7 @@ main_loop(char *script_cmds_file, char *script_cmd, bool stayInCommandLoop) {
} else {
read_history(my_history_path);
}
#endif
// loops every time enter is pressed...
while (1) {
bool printprompt = false;
@@ -290,12 +297,25 @@ check_script:
} else {
prompt_ctx = PROXPROMPT_CTX_INTERACTIVE;
rl_event_hook = check_comm;
char prompt[PROXPROMPT_MAX_SIZE] = {0};
prompt_compose(prompt, sizeof(prompt), prompt_ctx, prompt_dev);
char prompt_filtered[PROXPROMPT_MAX_SIZE] = {0};
memcpy_filter_ansi(prompt_filtered, prompt, sizeof(prompt_filtered), !session.supports_colors);
#ifdef HAVE_READLINE
rl_event_hook = check_comm;
cmd = readline(prompt_filtered);
#else
printf("%s", prompt_filtered);
cmd = NULL;
size_t len = 0;
int ret;
if ((ret = getline(&cmd, &len, stdin)) < 0) {
// TODO this happens also when kbd_enter_pressed() is used, with a key pressed or not
printf("GETLINE ERR %i", ret);
free(cmd);
cmd = NULL;
}
#endif
fflush(NULL);
}
}
@@ -333,6 +353,7 @@ check_script:
PrintAndLogEx(NORMAL, "%s%s", prompt_filtered, cmd);
g_printAndLog = PRINTANDLOG_PRINT | PRINTANDLOG_LOG;
#ifdef HAVE_READLINE
// add to history if not from a script
if (!current_cmdscriptfile()) {
HIST_ENTRY *entry = history_get(history_length);
@@ -341,6 +362,7 @@ check_script:
add_history(cmd);
}
}
#endif
// process cmd
int ret = CommandReceived(cmd);
// exit or quit
@@ -367,11 +389,12 @@ check_script:
while (current_cmdscriptfile())
pop_cmdscriptfile();
#ifdef HAVE_READLINE
if (my_history_path) {
write_history(my_history_path);
free(my_history_path);
}
#endif
if (cmd) {
free(cmd);
cmd = NULL;
@@ -681,12 +704,14 @@ int main(int argc, char *argv[]) {
char *port = NULL;
uint32_t speed = 0;
#ifdef HAVE_READLINE
/* initialize history */
using_history();
#ifdef RL_STATE_READCMD
rl_extend_line_buffer(1024);
#endif
#endif // RL_STATE_READCMD
#endif // HAVE_READLINE
char *exec_name = argv[0];
#if defined(_WIN32)

View File

@@ -22,7 +22,7 @@
#include <stdarg.h>
#include <stdlib.h>
#ifndef ANDROID
#ifdef HAVE_READLINE
#include <readline/readline.h>
#endif
@@ -297,8 +297,6 @@ void PrintAndLogEx(logLevel_t level, const char *fmt, ...) {
}
static void fPrintAndLog(FILE *stream, const char *fmt, ...) {
char *saved_line;
int saved_point;
va_list argptr;
static FILE *logfile = NULL;
static int logging = 1;
@@ -344,6 +342,8 @@ static void fPrintAndLog(FILE *stream, const char *fmt, ...) {
#ifdef RL_STATE_READCMD
// We are using GNU readline. libedit (OSX) doesn't support this flag.
int need_hack = (rl_readline_state & RL_STATE_READCMD) > 0;
char *saved_line;
int saved_point;
if (need_hack) {
saved_point = rl_point;