pm3line API to hide readline, linenoise as alternative
This commit is contained in:
@@ -279,6 +279,7 @@ set (TARGET_SOURCES
|
|||||||
${PM3_ROOT}/client/src/preferences.c
|
${PM3_ROOT}/client/src/preferences.c
|
||||||
${PM3_ROOT}/client/src/pm3_binlib.c
|
${PM3_ROOT}/client/src/pm3_binlib.c
|
||||||
${PM3_ROOT}/client/src/pm3_bitlib.c
|
${PM3_ROOT}/client/src/pm3_bitlib.c
|
||||||
|
${PM3_ROOT}/client/src/pm3line.c
|
||||||
${PM3_ROOT}/client/src/prng.c
|
${PM3_ROOT}/client/src/prng.c
|
||||||
${PM3_ROOT}/client/src/scandir.c
|
${PM3_ROOT}/client/src/scandir.c
|
||||||
${PM3_ROOT}/client/src/scripting.c
|
${PM3_ROOT}/client/src/scripting.c
|
||||||
|
|||||||
@@ -516,6 +516,7 @@ SRCS = aidsearch.c \
|
|||||||
pm3_bitlib.c \
|
pm3_bitlib.c \
|
||||||
preferences.c \
|
preferences.c \
|
||||||
prng.c \
|
prng.c \
|
||||||
|
pm3line.c \
|
||||||
proxmark3.c \
|
proxmark3.c \
|
||||||
scandir.c \
|
scandir.c \
|
||||||
uart/uart_posix.c \
|
uart/uart_posix.c \
|
||||||
|
|||||||
@@ -9,13 +9,8 @@
|
|||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
#include "cmdhflegic.h"
|
#include "cmdhflegic.h"
|
||||||
|
|
||||||
#include <stdio.h> // for Mingw readline
|
|
||||||
#include <ctype.h> // tolower
|
#include <ctype.h> // tolower
|
||||||
|
#include "pm3line.h" // pm3line_read, pm3line_free
|
||||||
#ifdef HAVE_READLINE
|
|
||||||
#include <readline/readline.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "cmdparser.h" // command_t
|
#include "cmdparser.h" // command_t
|
||||||
#include "comms.h" // clearCommandBuffer
|
#include "comms.h" // clearCommandBuffer
|
||||||
#include "cmdtrace.h"
|
#include "cmdtrace.h"
|
||||||
@@ -705,18 +700,11 @@ static int CmdLegicWrbl(const char *Cmd) {
|
|||||||
PrintAndLogEx(NORMAL, "#####################################");
|
PrintAndLogEx(NORMAL, "#####################################");
|
||||||
const char *confirm = "Do you really want to continue? y(es)/n(o) : ";
|
const char *confirm = "Do you really want to continue? y(es)/n(o) : ";
|
||||||
bool overwrite = false;
|
bool overwrite = false;
|
||||||
#ifdef HAVE_READLINE
|
|
||||||
char *answer = readline(confirm);
|
char *answer = pm3line_read(confirm);
|
||||||
overwrite = (answer[0] == 'y' || answer[0] == 'Y');
|
overwrite = (answer[0] == 'y' || answer[0] == 'Y');
|
||||||
#else
|
pm3line_free(answer);
|
||||||
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) {
|
if (!overwrite) {
|
||||||
PrintAndLogEx(NORMAL, "command cancelled");
|
PrintAndLogEx(NORMAL, "command cancelled");
|
||||||
return PM3_EOPABORTED;
|
return PM3_EOPABORTED;
|
||||||
|
|||||||
124
client/src/pm3line.c
Normal file
124
client/src/pm3line.c
Normal file
@@ -0,0 +1,124 @@
|
|||||||
|
// Copyright (C) 2020 Doegox
|
||||||
|
//
|
||||||
|
// This code is licensed to you under the terms of the GNU GPL, version 2 or,
|
||||||
|
// at your option, any later version. See the LICENSE.txt file for the text of
|
||||||
|
// the license.
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#include "pm3line.h"
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h> // for Mingw readline and for getline
|
||||||
|
#ifdef HAVE_READLINE
|
||||||
|
#include <readline/readline.h>
|
||||||
|
#include <readline/history.h>
|
||||||
|
#elif HAVE_LINENOISE
|
||||||
|
#include "linenoise.h"
|
||||||
|
#endif
|
||||||
|
#include "pm3_cmd.h"
|
||||||
|
|
||||||
|
void pm3line_init(void) {
|
||||||
|
#ifdef HAVE_READLINE
|
||||||
|
/* initialize history */
|
||||||
|
using_history();
|
||||||
|
|
||||||
|
#ifdef RL_STATE_READCMD
|
||||||
|
rl_extend_line_buffer(1024);
|
||||||
|
#endif // RL_STATE_READCMD
|
||||||
|
#elif HAVE_LINENOISE
|
||||||
|
linenoiseInstallWindowChangeHandler();
|
||||||
|
#endif // HAVE_READLINE
|
||||||
|
}
|
||||||
|
|
||||||
|
char *pm3line_read(const char *s) {
|
||||||
|
#ifdef HAVE_READLINE
|
||||||
|
return readline(s);
|
||||||
|
#elif HAVE_LINENOISE
|
||||||
|
return linenoise(s);
|
||||||
|
#else
|
||||||
|
printf("%s", s);
|
||||||
|
char *answer = NULL;
|
||||||
|
size_t anslen = 0;
|
||||||
|
int ret;
|
||||||
|
if ((ret = getline(&answer, &anslen, stdin)) < 0) {
|
||||||
|
// TODO this happens also when kbd_enter_pressed() is used, with a key pressed or not
|
||||||
|
printf("DEBUG: getline returned %i", ret);
|
||||||
|
free(answer);
|
||||||
|
answer = NULL;
|
||||||
|
}
|
||||||
|
return answer;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void pm3line_free(void *ref) {
|
||||||
|
free(ref);
|
||||||
|
}
|
||||||
|
|
||||||
|
void pm3line_update_prompt(const char *prompt) {
|
||||||
|
#ifdef HAVE_READLINE
|
||||||
|
rl_set_prompt(prompt);
|
||||||
|
rl_forced_update_display();
|
||||||
|
#else
|
||||||
|
(void) prompt;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
int pm3line_load_history(const char *path) {
|
||||||
|
#ifdef HAVE_READLINE
|
||||||
|
if (read_history(path) == 0) {
|
||||||
|
return PM3_SUCCESS;
|
||||||
|
} else {
|
||||||
|
return PM3_ESOFT;
|
||||||
|
}
|
||||||
|
#elif HAVE_LINENOISE
|
||||||
|
if (linenoiseHistoryLoad(path) == 0) {
|
||||||
|
return PM3_SUCCESS;
|
||||||
|
} else {
|
||||||
|
return PM3_ESOFT;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
(void) path;
|
||||||
|
return PM3_ENOTIMPL;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void pm3line_add_history(const char *line) {
|
||||||
|
#ifdef HAVE_READLINE
|
||||||
|
HIST_ENTRY *entry = history_get(history_length);
|
||||||
|
// add if not identical to latest recorded line
|
||||||
|
if ((!entry) || (strcmp(entry->line, line) != 0)) {
|
||||||
|
add_history(line);
|
||||||
|
}
|
||||||
|
#elif HAVE_LINENOISE
|
||||||
|
// linenoiseHistoryAdd takes already care of duplicate entries
|
||||||
|
linenoiseHistoryAdd(line);
|
||||||
|
#else
|
||||||
|
(void) line;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
int pm3line_save_history(const char *path) {
|
||||||
|
#ifdef HAVE_READLINE
|
||||||
|
if (write_history(path) == 0) {
|
||||||
|
return PM3_SUCCESS;
|
||||||
|
} else {
|
||||||
|
return PM3_ESOFT;
|
||||||
|
}
|
||||||
|
#elif HAVE_LINENOISE
|
||||||
|
if (linenoiseHistorySave(path) == 0) {
|
||||||
|
return PM3_SUCCESS;
|
||||||
|
} else {
|
||||||
|
return PM3_ESOFT;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
(void) path;
|
||||||
|
return PM3_ENOTIMPL;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void pm3line_check(int (check)(void)) {
|
||||||
|
#ifdef HAVE_READLINE
|
||||||
|
rl_event_hook = check;
|
||||||
|
#else
|
||||||
|
check();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
20
client/src/pm3line.h
Normal file
20
client/src/pm3line.h
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
// Copyright (C) 2020 Doegox
|
||||||
|
//
|
||||||
|
// This code is licensed to you under the terms of the GNU GPL, version 2 or,
|
||||||
|
// at your option, any later version. See the LICENSE.txt file for the text of
|
||||||
|
// the license.
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#ifndef PM3LINE_H__
|
||||||
|
#define PM3LINE_H__
|
||||||
|
|
||||||
|
void pm3line_init(void);
|
||||||
|
char *pm3line_read(const char* s);
|
||||||
|
void pm3line_free(void *ref);
|
||||||
|
void pm3line_update_prompt(const char *prompt);
|
||||||
|
int pm3line_load_history(const char *path);
|
||||||
|
void pm3line_add_history(const char *line);
|
||||||
|
int pm3line_save_history(const char *path);
|
||||||
|
void pm3line_check(int (check)(void));
|
||||||
|
|
||||||
|
#endif // PM3LINE_H__
|
||||||
@@ -10,16 +10,12 @@
|
|||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
#include "proxmark3.h"
|
#include "proxmark3.h"
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdio.h> // for Mingw readline
|
#include <stdio.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#ifdef HAVE_READLINE
|
|
||||||
#include <readline/readline.h>
|
|
||||||
#include <readline/history.h>
|
|
||||||
#endif
|
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
|
#include "pm3line.h"
|
||||||
#include "usart_defs.h"
|
#include "usart_defs.h"
|
||||||
#include "util_posix.h"
|
#include "util_posix.h"
|
||||||
#include "proxgui.h"
|
#include "proxgui.h"
|
||||||
@@ -122,14 +118,11 @@ static int check_comm(void) {
|
|||||||
if (IsCommunicationThreadDead() && session.pm3_present) {
|
if (IsCommunicationThreadDead() && session.pm3_present) {
|
||||||
PrintAndLogEx(INFO, "Running in " _YELLOW_("OFFLINE") " mode. Use "_YELLOW_("\"hw connect\"") " to reconnect\n");
|
PrintAndLogEx(INFO, "Running in " _YELLOW_("OFFLINE") " mode. Use "_YELLOW_("\"hw connect\"") " to reconnect\n");
|
||||||
prompt_dev = PROXPROMPT_DEV_OFFLINE;
|
prompt_dev = PROXPROMPT_DEV_OFFLINE;
|
||||||
#ifdef HAVE_READLINE
|
|
||||||
char prompt[PROXPROMPT_MAX_SIZE] = {0};
|
char prompt[PROXPROMPT_MAX_SIZE] = {0};
|
||||||
prompt_compose(prompt, sizeof(prompt), prompt_ctx, prompt_dev);
|
prompt_compose(prompt, sizeof(prompt), prompt_ctx, prompt_dev);
|
||||||
char prompt_filtered[PROXPROMPT_MAX_SIZE] = {0};
|
char prompt_filtered[PROXPROMPT_MAX_SIZE] = {0};
|
||||||
memcpy_filter_ansi(prompt_filtered, prompt, sizeof(prompt_filtered), !session.supports_colors);
|
memcpy_filter_ansi(prompt_filtered, prompt, sizeof(prompt_filtered), !session.supports_colors);
|
||||||
rl_set_prompt(prompt_filtered);
|
pm3line_update_prompt(prompt_filtered);
|
||||||
rl_forced_update_display();
|
|
||||||
#endif
|
|
||||||
CloseProxmark();
|
CloseProxmark();
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
@@ -210,15 +203,17 @@ main_loop(char *script_cmds_file, char *script_cmd, bool stayInCommandLoop) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HAVE_READLINE
|
bool loaded_history = false;
|
||||||
char *my_history_path = NULL;
|
char *my_history_path = NULL;
|
||||||
if (searchHomeFilePath(&my_history_path, NULL, PROXHISTORY, true) != PM3_SUCCESS) {
|
if (searchHomeFilePath(&my_history_path, NULL, PROXHISTORY, true) != PM3_SUCCESS) {
|
||||||
PrintAndLogEx(ERR, "No history will be recorded");
|
|
||||||
my_history_path = NULL;
|
my_history_path = NULL;
|
||||||
} else {
|
} else {
|
||||||
read_history(my_history_path);
|
loaded_history = (pm3line_load_history(my_history_path) == PM3_SUCCESS);
|
||||||
}
|
}
|
||||||
#endif
|
if (! loaded_history) {
|
||||||
|
PrintAndLogEx(ERR, "No history will be recorded");
|
||||||
|
}
|
||||||
|
|
||||||
// loops every time enter is pressed...
|
// loops every time enter is pressed...
|
||||||
while (1) {
|
while (1) {
|
||||||
bool printprompt = false;
|
bool printprompt = false;
|
||||||
@@ -293,30 +288,13 @@ check_script:
|
|||||||
printprompt = true;
|
printprompt = true;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
#ifdef HAVE_READLINE
|
pm3line_check(check_comm);
|
||||||
rl_event_hook = check_comm;
|
|
||||||
#else
|
|
||||||
check_comm();
|
|
||||||
#endif
|
|
||||||
prompt_ctx = PROXPROMPT_CTX_INTERACTIVE;
|
prompt_ctx = PROXPROMPT_CTX_INTERACTIVE;
|
||||||
char prompt[PROXPROMPT_MAX_SIZE] = {0};
|
char prompt[PROXPROMPT_MAX_SIZE] = {0};
|
||||||
prompt_compose(prompt, sizeof(prompt), prompt_ctx, prompt_dev);
|
prompt_compose(prompt, sizeof(prompt), prompt_ctx, prompt_dev);
|
||||||
char prompt_filtered[PROXPROMPT_MAX_SIZE] = {0};
|
char prompt_filtered[PROXPROMPT_MAX_SIZE] = {0};
|
||||||
memcpy_filter_ansi(prompt_filtered, prompt, sizeof(prompt_filtered), !session.supports_colors);
|
memcpy_filter_ansi(prompt_filtered, prompt, sizeof(prompt_filtered), !session.supports_colors);
|
||||||
#ifdef HAVE_READLINE
|
cmd = pm3line_read(prompt_filtered);
|
||||||
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);
|
fflush(NULL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -354,16 +332,10 @@ check_script:
|
|||||||
PrintAndLogEx(NORMAL, "%s%s", prompt_filtered, cmd);
|
PrintAndLogEx(NORMAL, "%s%s", prompt_filtered, cmd);
|
||||||
g_printAndLog = PRINTANDLOG_PRINT | PRINTANDLOG_LOG;
|
g_printAndLog = PRINTANDLOG_PRINT | PRINTANDLOG_LOG;
|
||||||
|
|
||||||
#ifdef HAVE_READLINE
|
|
||||||
// add to history if not from a script
|
// add to history if not from a script
|
||||||
if (!current_cmdscriptfile()) {
|
if (!current_cmdscriptfile()) {
|
||||||
HIST_ENTRY *entry = history_get(history_length);
|
pm3line_add_history(cmd);
|
||||||
// add if not identical to latest recorded cmd
|
|
||||||
if ((!entry) || (strcmp(entry->line, cmd) != 0)) {
|
|
||||||
add_history(cmd);
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
#endif
|
|
||||||
// process cmd
|
// process cmd
|
||||||
int ret = CommandReceived(cmd);
|
int ret = CommandReceived(cmd);
|
||||||
// exit or quit
|
// exit or quit
|
||||||
@@ -390,12 +362,10 @@ check_script:
|
|||||||
while (current_cmdscriptfile())
|
while (current_cmdscriptfile())
|
||||||
pop_cmdscriptfile();
|
pop_cmdscriptfile();
|
||||||
|
|
||||||
#ifdef HAVE_READLINE
|
|
||||||
if (my_history_path) {
|
if (my_history_path) {
|
||||||
write_history(my_history_path);
|
pm3line_save_history(my_history_path);;
|
||||||
free(my_history_path);
|
free(my_history_path);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
if (cmd) {
|
if (cmd) {
|
||||||
free(cmd);
|
free(cmd);
|
||||||
cmd = NULL;
|
cmd = NULL;
|
||||||
@@ -700,14 +670,7 @@ int main(int argc, char *argv[]) {
|
|||||||
char *port = NULL;
|
char *port = NULL;
|
||||||
uint32_t speed = 0;
|
uint32_t speed = 0;
|
||||||
|
|
||||||
#ifdef HAVE_READLINE
|
pm3line_init();
|
||||||
/* initialize history */
|
|
||||||
using_history();
|
|
||||||
|
|
||||||
#ifdef RL_STATE_READCMD
|
|
||||||
rl_extend_line_buffer(1024);
|
|
||||||
#endif // RL_STATE_READCMD
|
|
||||||
#endif // HAVE_READLINE
|
|
||||||
|
|
||||||
char *exec_name = argv[0];
|
char *exec_name = argv[0];
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
|
|||||||
Reference in New Issue
Block a user