diff --git a/client/CMakeLists.txt b/client/CMakeLists.txt index 449b4fdbe..8db8ebf9c 100644 --- a/client/CMakeLists.txt +++ b/client/CMakeLists.txt @@ -49,6 +49,21 @@ if (NOT SKIPPYTHON EQUAL 1) pkg_search_module(PYTHON3EMBED QUIET python3-embed) endif (NOT SKIPPYTHON EQUAL 1) +if (NOT SKIPREADLINE EQUAL 1) + if (APPLE) + find_path(READLINE_INCLUDE_DIRS readline/readline.h /usr/local/opt/readline/include /opt/local/include /opt/include /usr/local/include /usr/include NO_DEFAULT_PATH) + endif (APPLE) + find_path(READLINE_INCLUDE_DIRS readline/readline.h) + + if (APPLE) + find_library(READLINE_LIBRARIES readline /usr/local/opt/readline/lib /opt/local/lib /opt/lib /usr/local/lib /usr/lib NO_DEFAULT_PATH) + endif (APPLE) + find_library(READLINE_LIBRARIES readline) + if (READLINE_INCLUDE_DIRS AND READLINE_LIBRARIES) + set(READLINE_FOUND ON) + endif (READLINE_INCLUDE_DIRS AND READLINE_LIBRARIES) +endif (NOT SKIPREADLINE EQUAL 1) + add_subdirectory(${PM3_ROOT}/client/deps deps) set (TARGET_SOURCES @@ -246,6 +261,14 @@ if (NOT SKIPPYTHON EQUAL 1) endif (PYTHON3EMBED_FOUND) endif (NOT SKIPPYTHON EQUAL 1) +if (NOT SKIPREADLINE EQUAL 1) + if (READLINE_FOUND) + add_definitions("-DHAVE_READLINE") + set(ADDITIONAL_DIRS ${READLINE_INCLUDE_DIRS} ${ADDITIONAL_DIRS}) + set(ADDITIONAL_LNK ${READLINE_LIBRARIES} ${ADDITIONAL_LNK}) + endif (READLINE_FOUND) +endif(NOT SKIPREADLINE EQUAL 1) + message("===================================================================") if (SKIPQT EQUAL 1) message("GUI support: skipped") @@ -278,6 +301,16 @@ else (SKIPPYTHON EQUAL 1) message("Python3 library: Python3 not found, disabled") endif (PYTHON3EMBED_FOUND) endif(SKIPPYTHON EQUAL 1) + +if (SKIPREADLINE EQUAL 1) + message("Readline library: skipped") +else (SKIPREADLINE EQUAL 1) + if (READLINE_FOUND) + message("Readline library: enabled") + else (READLINE_FOUND) + message("Readline library: Readline not found, disabled") + endif (READLINE_FOUND) +endif(SKIPREADLINE EQUAL 1) message("===================================================================") add_executable(proxmark3 @@ -308,13 +341,10 @@ target_include_directories(proxmark3 PRIVATE ${ADDITIONAL_DIRS} ) -if (APPLE) - set_target_properties(proxmark3 PROPERTIES LINK_FLAGS "-Wl,-F/Library/Frameworks, -L/usr/local/opt/readline/lib") - set_target_properties(proxmark3 PROPERTIES COMPILE_FLAGS "-I/usr/local/opt/readline/include") -else (APPLE) +if (NOT APPLE) # required for Raspberry Pi, but breaks with clang (OSX). Need to be at the end of the linker line. set(ADDITIONAL_LNK ${ADDITIONAL_LNK} -Wl,--as-needed -latomic -Wl,--no-as-needed) -endif (APPLE) +endif (NOT APPLE) find_library(pm3rrg_rdv4_cliparser REQUIRED) @@ -328,7 +358,6 @@ find_library(pm3rrg_rdv4_whereami REQUIRED) target_link_libraries(proxmark3 PRIVATE bz2 - readline m pm3rrg_rdv4_mbedtls pm3rrg_rdv4_cliparser diff --git a/client/Makefile b/client/Makefile index 102bf62dd..3bd059318 100644 --- a/client/Makefile +++ b/client/Makefile @@ -256,11 +256,14 @@ LDLIBS += $(QTLDLIBS) CXXINCLUDES += $(QTINCLUDES) ## Readline -ifeq ($(platform),Darwin) - LDLIBS += -L/usr/local/opt/readline/lib - INCLUDES += -I/usr/local/opt/readline/include +ifneq ($(SKIPREADLINE),1) + ifeq ($(platform),Darwin) + LDLIBS += -L/usr/local/opt/readline/lib + INCLUDES += -I/usr/local/opt/readline/include + endif + LDLIBS += -lreadline + READLINE_FOUND = 1 endif -LDLIBS += -lreadline ####################################################################################################### CFLAGS ?= $(DEFCFLAGS) @@ -280,6 +283,10 @@ ifneq (,$(findstring MINGW,$(platform))) PM3CFLAGS += -mno-ms-bitfields -fexec-charset=cp850 endif +ifeq ($(READLINE_FOUND),1) + PM3CFLAGS += -DHAVE_READLINE +endif + ifeq ($(BT_FOUND),1) PM3CFLAGS += -DHAVE_BLUEZ endif @@ -366,6 +373,16 @@ else endif endif +ifeq ($(SKIPREADLINE),1) + $(info Readline library: skipped) +else + ifeq ($(READLINE_FOUND),1) + $(info Readline library: enabled) + else + $(info Readline library: Readline not found, disabled) + endif +endif + ifeq ($(SKIPWHEREAMISYSTEM),1) $(info Whereami library: local library forced) else diff --git a/client/src/cmdhflegic.c b/client/src/cmdhflegic.c index a97d13d3f..f5ba787ad 100644 --- a/client/src/cmdhflegic.c +++ b/client/src/cmdhflegic.c @@ -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 ] [d ]\n"); + PrintAndLogEx(NORMAL, "Usage: hf legic wrbl [h] [o ] [d ] [y]\n"); PrintAndLogEx(NORMAL, "Options:"); PrintAndLogEx(NORMAL, " h : this help"); PrintAndLogEx(NORMAL, " o : (hex) offset in data array to start writing"); //PrintAndLogEx(NORMAL, " : (optional) Initialization vector to use (ODD and 7bits)"); PrintAndLogEx(NORMAL, " d : (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); diff --git a/client/src/proxmark3.c b/client/src/proxmark3.c index eb34393ae..eea1718c3 100644 --- a/client/src/proxmark3.c +++ b/client/src/proxmark3.c @@ -15,8 +15,11 @@ #include // for Mingw readline #include #include +#ifdef HAVE_READLINE #include #include +#endif +#include #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) diff --git a/client/src/ui.c b/client/src/ui.c index 0f4e28a62..68f0eab24 100644 --- a/client/src/ui.c +++ b/client/src/ui.c @@ -22,7 +22,7 @@ #include #include -#ifndef ANDROID +#ifdef HAVE_READLINE #include #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;