From 3ada10be721a92845cbad1f2f78db2343b1fda50 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Mon, 10 Jan 2022 23:53:01 +0100 Subject: [PATCH] Add linenoise-ng as alternative to readline --- client/CMakeLists.txt | 25 ++++++++++ client/Makefile | 46 +++++++++++++++++++ client/deps/.gitignore | 2 + client/deps/CMakeLists.txt | 3 ++ client/deps/get_linenoise.sh | 58 ++++++++++++++++++++++++ client/deps/linenoise-ng-1.0.1.zip | Bin 0 -> 47590 bytes client/experimental_lib/CMakeLists.txt | 25 ++++++++++ client/src/cmdhw.c | 4 +- client/src/pm3line.c | 51 +++++++++++++++++++++ doc/md/Development/Maintainers.md | 5 ++ doc/md/Development/Makefile-vs-CMake.md | 3 +- 11 files changed, 220 insertions(+), 2 deletions(-) create mode 100644 client/deps/.gitignore create mode 100755 client/deps/get_linenoise.sh create mode 100644 client/deps/linenoise-ng-1.0.1.zip diff --git a/client/CMakeLists.txt b/client/CMakeLists.txt index e377616f8..f6a0c9e9f 100644 --- a/client/CMakeLists.txt +++ b/client/CMakeLists.txt @@ -140,6 +140,12 @@ if (NOT SKIPREADLINE EQUAL 1) if (READLINE_INCLUDE_DIRS AND READLINE_LIBRARIES) set(READLINE_FOUND ON) endif (READLINE_INCLUDE_DIRS AND READLINE_LIBRARIES) +else (NOT SKIPREADLINE EQUAL 1) + if (NOT SKIPLINENOISE EQUAL 1) + if (EXISTS ${PM3_ROOT}/client/deps/linenoise/) + set(LINENOISE_LOCAL_FOUND ON) + endif (EXISTS ${PM3_ROOT}/client/deps/linenoise/) + endif (NOT SKIPLINENOISE EQUAL 1) endif (NOT SKIPREADLINE EQUAL 1) if (NOT SKIPJANSSONSYSTEM EQUAL 1) @@ -500,6 +506,18 @@ else (SKIPREADLINE EQUAL 1) endif (READLINE_FOUND) endif(SKIPREADLINE EQUAL 1) +if (NOT READLINE_FOUND) + if (SKIPLINENOISE EQUAL 1) + message(STATUS "Linenoise library: skipped") + else (SKIPLINENOISE EQUAL 1) + if (LINENOISE_LOCAL_FOUND) + message(STATUS "Linenoise library: enabled") + else (LINENOISE_LOCAL_FOUND) + message(STATUS "Linenoise library: Linenoise not found, disabled") + endif (LINENOISE_LOCAL_FOUND) + endif (SKIPLINENOISE EQUAL 1) +endif (NOT READLINE_FOUND) + if (SKIPWHEREAMISYSTEM EQUAL 1) message(STATUS "Whereami library: local library forced") else (SKIPWHEREAMISYSTEM EQUAL 1) @@ -578,6 +596,13 @@ if (NOT JANSSON_FOUND) set(ADDITIONAL_LNK pm3rrg_rdv4_jansson ${ADDITIONAL_LNK}) endif (NOT JANSSON_FOUND) +if (NOT READLINE_FOUND) + if (LINENOISE_LOCAL_FOUND) + add_definitions("-DHAVE_LINENOISE") + set(ADDITIONAL_LNK pm3rrg_rdv4_linenoise ${ADDITIONAL_LNK}) + endif (LINENOISE_LOCAL_FOUND) +endif (NOT READLINE_FOUND) + if (NOT WHEREAMI_FOUND) set(ADDITIONAL_LNK pm3rrg_rdv4_whereami ${ADDITIONAL_LNK}) endif (NOT WHEREAMI_FOUND) diff --git a/client/Makefile b/client/Makefile index 905609b36..4debb130f 100644 --- a/client/Makefile +++ b/client/Makefile @@ -78,6 +78,14 @@ JANSSONLIBINC = -I$(JANSSONLIBPATH) JANSSONLIB = $(JANSSONLIBPATH)/libjansson.a JANSSONLIBLD = +## Linenoise +# Can be used if Readline is unavailable or explicitely disabled +# Requires to be unpacked, see deps/get_linenoise.sh +LINENOISELIBPATH = ./deps/linenoise +LINENOISELIBINC = -I$(LINENOISELIBPATH) +LINENOISELIB = $(LINENOISELIBPATH)/liblinenoise.a +LINENOISELIBLD = + ## Lua LUALIBPATH = ./deps/liblua LUALIBINC = -I$(LUALIBPATH) @@ -146,6 +154,9 @@ STATICLIBS += $(HARDNESTEDLIB) LDLIBS +=$(HARDNESTEDLIBLD) PM3INCLUDES += $(HARDNESTEDLIBINC) +## Linenoise +# wait to see if Readline is available + ## Lua ifneq ($(SKIPLUASYSTEM),1) ifdef MACPORTS_PREFIX @@ -325,6 +336,16 @@ ifneq ($(SKIPREADLINE),1) LDLIBS += -lreadline READLINE_FOUND = 1 +else +## Linenoise + ifneq ($(SKIPLINENOISE),1) + ifneq (,$(wildcard $(LINENOISELIBPATH))) + STATICLIBS += $(LINENOISELIB) + LDLIBS += $(LINENOISELIBLD) + PM3INCLUDES += $(LINENOISELIBINC) + LINENOISE_LOCAL_FOUND = 1 + endif + endif endif ######## @@ -362,6 +383,10 @@ ifeq ($(READLINE_FOUND),1) PM3CFLAGS += -DHAVE_READLINE endif +ifeq ($(LINENOISE_LOCAL_FOUND),1) + PM3CFLAGS += -DHAVE_LINENOISE +endif + ifeq ($(BT_FOUND),1) PM3CFLAGS += -DHAVE_BLUEZ endif @@ -466,6 +491,18 @@ else endif endif +ifneq ($(READLINE_FOUND),1) + ifeq ($(SKIPLINENOISE),1) + $(info Linenoise library: skipped) + else + ifeq ($(LINENOISE_LOCAL_FOUND),1) + $(info Linenoise library: enabled) + else + $(info Linenoise library: Linenoise not found, disabled) + endif + endif +endif + ifeq ($(SKIPWHEREAMISYSTEM),1) $(info Whereami library: local library forced) else @@ -737,6 +774,9 @@ clean: $(Q)$(MAKE) --no-print-directory -C $(CLIPARSERLIBPATH) clean $(Q)$(MAKE) --no-print-directory -C $(HARDNESTEDLIBPATH) clean $(Q)$(MAKE) --no-print-directory -C $(JANSSONLIBPATH) clean +ifeq ($(LINENOISE_LOCAL_FOUND), 1) + $(Q)$(MAKE) --no-print-directory -C $(LINENOISELIBPATH) clean +endif $(Q)$(MAKE) --no-print-directory -C $(LUALIBPATH) clean $(Q)$(MAKE) --no-print-directory -C $(REVENGLIBPATH) clean $(Q)$(MAKE) --no-print-directory -C $(TINYCBORLIBPATH) clean @@ -792,6 +832,12 @@ ifneq ($(JANSSON_FOUND),1) $(Q)$(MAKE) --no-print-directory -C $(JANSSONLIBPATH) all endif +$(LINENOISELIB): .FORCE +ifeq ($(LINENOISE_LOCAL_FOUND), 1) + $(info [*] MAKE $@) + $(Q)$(MAKE) --no-print-directory -C $(LINENOISELIBPATH) all +endif + $(LUALIB): .FORCE ifneq ($(LUA_FOUND),1) $(info [*] MAKE $@ for $(LUAPLATFORM)) diff --git a/client/deps/.gitignore b/client/deps/.gitignore new file mode 100644 index 000000000..c3eede102 --- /dev/null +++ b/client/deps/.gitignore @@ -0,0 +1,2 @@ +linenoise/ +linenoise.cmake diff --git a/client/deps/CMakeLists.txt b/client/deps/CMakeLists.txt index f7b96a7ea..87613c0fe 100644 --- a/client/deps/CMakeLists.txt +++ b/client/deps/CMakeLists.txt @@ -10,6 +10,9 @@ endif() if (NOT TARGET pm3rrg_rdv4_jansson) include(jansson.cmake) endif() +if ((NOT TARGET pm3rrg_rdv4_linenoise) AND (EXISTS ${PM3_ROOT}/client/deps/linenoise/)) + include(linenoise.cmake) +endif() if (NOT TARGET pm3rrg_rdv4_lua) include(lua.cmake) endif() diff --git a/client/deps/get_linenoise.sh b/client/deps/get_linenoise.sh new file mode 100755 index 000000000..4bb6dbc81 --- /dev/null +++ b/client/deps/get_linenoise.sh @@ -0,0 +1,58 @@ +#!/bin/bash + +# Can be used if Readline is unavailable or explicitely disabled +# Note that ConvertUTF.cpp is under redis-only license therefore +# if you are maintainer, think twice before including it + +version=1.0.1 +mkdir -p linenoise +ZP=linenoise-ng-$version +if [ ! -f "${ZP}.zip" ]; then + wget -O "${ZP}.zip" https://github.com/arangodb/linenoise-ng/archive/v$version.zip +fi +unzip -o -j "${ZP}.zip" $ZP/src/ConvertUTF.cpp $ZP/src/ConvertUTF.h $ZP/LICENSE $ZP/src/linenoise.cpp $ZP/include/linenoise.h $ZP/README.md $ZP/src/wcwidth.cpp -d linenoise +#echo "Please do make style" + +echo "Generating linenoise.cmake..." +cat > linenoise.cmake << EOF +add_library(pm3rrg_rdv4_linenoise STATIC + linenoise/ConvertUTF.cpp + linenoise/linenoise.cpp + linenoise/wcwidth.cpp +) + +target_compile_definitions(pm3rrg_rdv4_linenoise PRIVATE NDEBUG) +target_include_directories(pm3rrg_rdv4_linenoise INTERFACE linenoise) +target_compile_options(pm3rrg_rdv4_linenoise PRIVATE -Wall -Werror -O3) +set_property(TARGET pm3rrg_rdv4_linenoise PROPERTY POSITION_INDEPENDENT_CODE ON) +EOF + +cd linenoise +echo "Generating linenoise/Makefile..." +cat > Makefile << EOF +MYSRCPATHS = +MYINCLUDES = +MYCXXFLAGS = -DNDEBUG -std=c++11 -fomit-frame-pointer +MYDEFS = +MYCXXSRCS = ConvertUTF.cpp linenoise.cpp wcwidth.cpp + +LIB_A = liblinenoise.a + +include ../../../Makefile.host +EOF + +# Patch to get proper autocompletion of subcommands +patch << EOF +diff -Naur linenoise.cpp linenoise.cpp ++++ linenoise.cpp 2017-03-06 17:01:33.000000000 +0100 +--- linenoise.cpp 2022-01-29 10:37:19.656202922 +0100 +@@ -1956,7 +1956,7 @@ + // character and + // extract a copy to parse. we also handle the case where tab is hit while + // not at end-of-line. +- int startIndex = pos; ++ int startIndex = 0; + while (--startIndex >= 0) { + if (strchr(breakChars, buf32[startIndex])) { + break; +EOF diff --git a/client/deps/linenoise-ng-1.0.1.zip b/client/deps/linenoise-ng-1.0.1.zip new file mode 100644 index 0000000000000000000000000000000000000000..8093590c01eb391698ea2d65aab8c350c9579094 GIT binary patch literal 47590 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 literal 0 HcmV?d00001 diff --git a/client/experimental_lib/CMakeLists.txt b/client/experimental_lib/CMakeLists.txt index a31a3110d..618b5af28 100644 --- a/client/experimental_lib/CMakeLists.txt +++ b/client/experimental_lib/CMakeLists.txt @@ -141,6 +141,12 @@ if (NOT SKIPREADLINE EQUAL 1) if (READLINE_INCLUDE_DIRS AND READLINE_LIBRARIES) set(READLINE_FOUND ON) endif (READLINE_INCLUDE_DIRS AND READLINE_LIBRARIES) +else (NOT SKIPREADLINE EQUAL 1) + if (NOT SKIPLINENOISE EQUAL 1) + if (EXISTS ${PM3_ROOT}/client/deps/linenoise/) + set(LINENOISE_LOCAL_FOUND ON) + endif (EXISTS ${PM3_ROOT}/client/deps/linenoise/) + endif (NOT SKIPLINENOISE EQUAL 1) endif (NOT SKIPREADLINE EQUAL 1) if (NOT SKIPJANSSONSYSTEM EQUAL 1) @@ -501,6 +507,18 @@ else (SKIPREADLINE EQUAL 1) endif (READLINE_FOUND) endif(SKIPREADLINE EQUAL 1) +if (NOT READLINE_FOUND) + if (SKIPLINENOISE EQUAL 1) + message(STATUS "Linenoise library: skipped") + else (SKIPLINENOISE EQUAL 1) + if (LINENOISE_LOCAL_FOUND) + message(STATUS "Linenoise library: enabled") + else (LINENOISE_LOCAL_FOUND) + message(STATUS "Linenoise library: Linenoise not found, disabled") + endif (LINENOISE_LOCAL_FOUND) + endif (SKIPLINENOISE EQUAL 1) +endif (NOT READLINE_FOUND) + if (SKIPWHEREAMISYSTEM EQUAL 1) message(STATUS "Whereami library: local library forced") else (SKIPWHEREAMISYSTEM EQUAL 1) @@ -581,6 +599,13 @@ if (NOT JANSSON_FOUND) set(ADDITIONAL_LNK pm3rrg_rdv4_jansson ${ADDITIONAL_LNK}) endif (NOT JANSSON_FOUND) +if (NOT READLINE_FOUND) + if (LINENOISE_LOCAL_FOUND) + add_definitions("-DHAVE_LINENOISE") + set(ADDITIONAL_LNK pm3rrg_rdv4_linenoise ${ADDITIONAL_LNK}) + endif (LINENOISE_LOCAL_FOUND) +endif (NOT READLINE_FOUND) + if (NOT WHEREAMI_FOUND) set(ADDITIONAL_LNK pm3rrg_rdv4_whereami ${ADDITIONAL_LNK}) endif (NOT WHEREAMI_FOUND) diff --git a/client/src/cmdhw.c b/client/src/cmdhw.c index 991815e46..5e462ea8d 100644 --- a/client/src/cmdhw.c +++ b/client/src/cmdhw.c @@ -995,8 +995,10 @@ void pm3_version(bool verbose, bool oneliner) { PrintAndLogEx(NORMAL, " platform.................. " PM3HOSTOS " / " PM3HOSTARCH); #if defined(HAVE_READLINE) PrintAndLogEx(NORMAL, " Readline support.......... " _GREEN_("present")); +#elif defined(HAVE_LINENOISE) + PrintAndLogEx(NORMAL, " Linenoise support......... " _GREEN_("present")); #else - PrintAndLogEx(NORMAL, " Readline support.......... " _YELLOW_("absent")); + PrintAndLogEx(NORMAL, " Readline/Linenoise support." _YELLOW_("absent")); #endif #ifdef HAVE_GUI PrintAndLogEx(NORMAL, " QT GUI support............ " _GREEN_("present")); diff --git a/client/src/pm3line.c b/client/src/pm3line.c index f070d3813..91e7df6c2 100644 --- a/client/src/pm3line.c +++ b/client/src/pm3line.c @@ -24,6 +24,8 @@ #if defined(HAVE_READLINE) #include #include +#elif defined(HAVE_LINENOISE) +#include "linenoise.h" #endif #include "pm3line_vocabulory.h" #include "pm3_cmd.h" @@ -73,6 +75,39 @@ static char **rl_command_completion(const char *text, int start, int end) { return rl_completion_matches(text, rl_command_generator); } +#elif defined(HAVE_LINENOISE) +static void ln_command_completion(const char *text, linenoiseCompletions *lc) { + int index = 0; + const char *prev_match = ""; + size_t prev_match_len = 0; + size_t len = strlen(text); + const char *command; + while ((command = vocabulory[index].name)) { + + // When no pm3 device present + // and the command is not available offline, + // we skip it. + if ((g_session.pm3_present == false) && (vocabulory[index].offline == false )) { + index++; + continue; + } + + index++; + + if (strncmp (command, text, len) == 0) { + const char *space = strstr(command + len, " "); + if (space != NULL) { + if ((prev_match_len == 0) || (strncmp (prev_match, command, prev_match_len < space - command ? prev_match_len : space - command) != 0)) { + linenoiseAddCompletion(lc, str_ndup(command, space - command + 1)); + prev_match = command; + prev_match_len = space - command + 1; + } + } else { + linenoiseAddCompletion(lc, command); + } + } + } +} #endif // HAVE_READLINE # if defined(_WIN32) @@ -119,12 +154,17 @@ void pm3line_init(void) { #ifdef RL_STATE_READCMD rl_extend_line_buffer(1024); #endif // RL_STATE_READCMD +#elif defined(HAVE_LINENOISE) + linenoiseInstallWindowChangeHandler(); + linenoiseSetCompletionCallback(ln_command_completion); #endif // HAVE_READLINE } char *pm3line_read(const char *s) { #if defined(HAVE_READLINE) return readline(s); +#elif defined(HAVE_LINENOISE) + return linenoise(s); #else printf("%s", s); char *answer = NULL; @@ -160,6 +200,12 @@ int pm3line_load_history(const char *path) { } else { return PM3_ESOFT; } +#elif defined(HAVE_LINENOISE) + if (linenoiseHistoryLoad(path) == 0) { + return PM3_SUCCESS; + } else { + return PM3_ESOFT; + } #else (void) path; return PM3_ENOTIMPL; @@ -173,6 +219,9 @@ void pm3line_add_history(const char *line) { if ((!entry) || (strcmp(entry->line, line) != 0)) { add_history(line); } +#elif defined(HAVE_LINENOISE) + // linenoiseHistoryAdd takes already care of duplicate entries + linenoiseHistoryAdd(line); #else (void) line; #endif @@ -182,6 +231,8 @@ void pm3line_flush_history(void) { if (g_session.history_path) { #if defined(HAVE_READLINE) write_history(g_session.history_path); +#elif defined(HAVE_LINENOISE) + linenoiseHistorySave(g_session.history_path); #endif // HAVE_READLINE free(g_session.history_path); g_session.history_path = NULL; diff --git a/doc/md/Development/Maintainers.md b/doc/md/Development/Maintainers.md index 2055e5bd2..2a72e500f 100644 --- a/doc/md/Development/Maintainers.md +++ b/doc/md/Development/Maintainers.md @@ -66,6 +66,11 @@ It's also possible to skip parts even if libraries are present in the compilatio * `make client SKIPJANSSONSYSTEM=1` to skip system Jansson lib even if libjansson is present, use embedded Jansson lib instead * `make client SKIPWHEREAMISYSTEM=1` to skip system Whereami lib even if libwhereami is present, use embedded whereami lib instead +By default, the client is using Readline, but this can be disabled: +* `make client SKIPREADLINE=1` to skip system Readline lib even if libreadline is present + +When Readline is disabled, it is possible to use Linenoise instead. Note that Linenoise-ng contains `ConvertUTF.cpp` which is under a redistribution-only license, therefore think twice before including it in a release. To get Linenoise-ng, see `client/deps/get_linenoise.sh`. + If you're cross-compiling, these ones might be useful: * `make client SKIPREVENGTEST=1` to skip compilation and execution of a consistency test for reveng, which can be problematic in case of cross-compilation diff --git a/doc/md/Development/Makefile-vs-CMake.md b/doc/md/Development/Makefile-vs-CMake.md index 79ac43e2c..c54e911ff 100644 --- a/doc/md/Development/Makefile-vs-CMake.md +++ b/doc/md/Development/Makefile-vs-CMake.md @@ -62,7 +62,7 @@ At the moment both are maintained because they don't perfectly overlap yet. | dep libm | sys | sys | | | libm detection | **none** | **none** (1) | (1) cf https://cmake.org/pipermail/cmake/2019-March/069168.html ? | | dep mbedtls | in_common | in_common | no sys lib: missing support for CMAC in def conf (btw no .pc available) | -| dep python3 | opt, sys, <3.8 & 3.8 | opt, sys, <3.8 & 3.8 | | +| dep python3 | opt, sys, < 3.8 & 3.8 | opt, sys, < 3.8 & 3.8 | | | python3 detection | pc | pkg_search_module | | | `SKIPPYTHON` | yes | yes | | | dep pthread | sys | sys | | @@ -74,6 +74,7 @@ At the moment both are maintained because they don't perfectly overlap yet. | dep readline | sys | sys | | | readline detection | **none** (1) | find*(2), Cross:getzip | (1) OSX: hardcoded path (2) additional paths for OSX | | `SKIPREADLINE` | yes | yes | CLI not fully functional without Readline | +| `SKIPLINENOISE` | yes | yes | replacement of Readline, not as complete | | dep reveng | in_deps | in_deps | | | `SKIPREVENGTEST` | yes(1) | **no**(2) | (1) e.g. if cross-compilation (2) tests aren't compiled/ran with cmake | | dep tinycbor | in_deps | in_deps | |