add support for (nested) cmd scripts in script list/run

This commit is contained in:
Philippe Teuwen 2019-09-09 23:46:38 +02:00
commit d08f03058b
4 changed files with 111 additions and 57 deletions

View file

@ -33,7 +33,10 @@ static int CmdHelp(const char *Cmd);
*/ */
static int CmdScriptList(const char *Cmd) { static int CmdScriptList(const char *Cmd) {
(void)Cmd; // Cmd is not used so far (void)Cmd; // Cmd is not used so far
return searchAndList(LUA_SCRIPTS_SUBDIR, ".lua"); int ret = searchAndList(LUA_SCRIPTS_SUBDIR, ".lua");
if (ret != PM3_SUCCESS)
return ret;
return searchAndList(CMD_SCRIPTS_SUBDIR, ".cmd");
} }
/** /**
@ -43,6 +46,19 @@ static int CmdScriptList(const char *Cmd) {
* @return * @return
*/ */
static int CmdScriptRun(const char *Cmd) { static int CmdScriptRun(const char *Cmd) {
char preferredName[128] = {0};
char arguments[256] = {0};
int name_len = 0;
int arg_len = 0;
sscanf(Cmd, "%127s%n %255[^\n\r]%n", preferredName, &name_len, arguments, &arg_len);
char *script_path;
if ((!str_endswith(preferredName, ".cmd")) && (searchFile(&script_path, LUA_SCRIPTS_SUBDIR, preferredName, ".lua", true) == PM3_SUCCESS)) {
int error;
PrintAndLogEx(SUCCESS, "Executing Lua script: %s, args '%s'\n", script_path, arguments);
// create new Lua state // create new Lua state
lua_State *lua_state; lua_State *lua_state;
lua_state = luaL_newstate(); lua_state = luaL_newstate();
@ -59,20 +75,6 @@ static int CmdScriptRun(const char *Cmd) {
//Add the 'bit' library //Add the 'bit' library
set_bit_library(lua_state); set_bit_library(lua_state);
char preferredName[128] = {0};
char arguments[256] = {0};
int name_len = 0;
int arg_len = 0;
sscanf(Cmd, "%127s%n %255[^\n\r]%n", preferredName, &name_len, arguments, &arg_len);
char *script_path;
int res = searchFile(&script_path, LUA_SCRIPTS_SUBDIR, preferredName, ".lua", false);
if (res != PM3_SUCCESS)
return res;
int error;
PrintAndLogEx(SUCCESS, "Executing: %s, args '%s'\n", script_path, arguments);
error = luaL_loadfile(lua_state, script_path); error = luaL_loadfile(lua_state, script_path);
free(script_path); free(script_path);
if (!error) { if (!error) {
@ -97,7 +99,21 @@ static int CmdScriptRun(const char *Cmd) {
// close the Lua state // close the Lua state
lua_close(lua_state); lua_close(lua_state);
PrintAndLogEx(SUCCESS, "\nFinished\n"); PrintAndLogEx(SUCCESS, "\nFinished\n");
return 0; return PM3_SUCCESS;
}
if ((!str_endswith(preferredName, ".lua")) && (searchFile(&script_path, CMD_SCRIPTS_SUBDIR, preferredName, ".cmd", true) == PM3_SUCCESS)) {
PrintAndLogEx(SUCCESS, "Executing Cmd script: %s, args '%s'\n", script_path, arguments);
int ret = push_cmdscriptfile(script_path, true);
if (ret != PM3_SUCCESS)
PrintAndLogEx(ERR, "could not open " _YELLOW_("%s") "...", script_path);
free(script_path);
return ret;
}
// file not found, let's search again to display the error messages
int ret = PM3_EUNDEF;
if (!str_endswith(preferredName, ".cmd")) ret = searchFile(&script_path, LUA_SCRIPTS_SUBDIR, preferredName, ".lua", false);
if (!str_endswith(preferredName, ".lua")) ret = searchFile(&script_path, CMD_SCRIPTS_SUBDIR, preferredName, ".cmd", false);
return ret;
} }
static command_t CommandTable[] = { static command_t CommandTable[] = {

View file

@ -933,6 +933,7 @@ static int searchFinalFile(char **foundpath, const char *pm3dir, const char *sea
((strcmp(DICTIONARIES_SUBDIR, pm3dir) == 0) || ((strcmp(DICTIONARIES_SUBDIR, pm3dir) == 0) ||
(strcmp(LUA_LIBRARIES_SUBDIR, pm3dir) == 0) || (strcmp(LUA_LIBRARIES_SUBDIR, pm3dir) == 0) ||
(strcmp(LUA_SCRIPTS_SUBDIR, pm3dir) == 0) || (strcmp(LUA_SCRIPTS_SUBDIR, pm3dir) == 0) ||
(strcmp(CMD_SCRIPTS_SUBDIR, pm3dir) == 0) ||
(strcmp(RESOURCES_SUBDIR, pm3dir) == 0))) { (strcmp(RESOURCES_SUBDIR, pm3dir) == 0))) {
char *path = calloc(strlen(exec_path) + strlen(pm3dir) + strlen(filename) + 1, sizeof(char)); char *path = calloc(strlen(exec_path) + strlen(pm3dir) + strlen(filename) + 1, sizeof(char));
if (path == NULL) if (path == NULL)

View file

@ -63,6 +63,38 @@ int check_comm(void) {
return 0; return 0;
} }
// first slot is always NULL, indicating absence of script when idx=0
FILE *cmdscriptfile[MAX_NESTED_CMDSCRIPT + 1] = {0};
uint8_t cmdscriptfile_idx = 0;
bool cmdscriptfile_stayafter = false;
int push_cmdscriptfile(char *path, bool stayafter) {
if (cmdscriptfile_idx == MAX_NESTED_CMDSCRIPT) {
PrintAndLogEx(ERR, "Too many nested scripts, skipping %s\n", path);
return PM3_EMALLOC;
}
FILE *tmp = fopen(path, "r");
if (tmp == NULL)
return PM3_EFILE;
if (cmdscriptfile_idx == 0)
cmdscriptfile_stayafter = stayafter;
cmdscriptfile[++cmdscriptfile_idx] = tmp;
return PM3_SUCCESS;
}
FILE *current_cmdscriptfile() {
return cmdscriptfile[cmdscriptfile_idx];
}
bool pop_cmdscriptfile() {
fclose(cmdscriptfile[cmdscriptfile_idx]);
cmdscriptfile[cmdscriptfile_idx--] = NULL;
if (cmdscriptfile_idx == 0)
return cmdscriptfile_stayafter;
else
return true;
}
// Main thread of PM3 Client // Main thread of PM3 Client
void void
#ifdef __has_attribute #ifdef __has_attribute
@ -80,7 +112,6 @@ main_loop(char *script_cmds_file, char *script_cmd, bool stayInCommandLoop) {
strcreplace(script_cmd, script_cmd_len, ';', '\0'); strcreplace(script_cmd, script_cmd_len, ';', '\0');
} }
bool stdinOnPipe = !isatty(STDIN_FILENO); bool stdinOnPipe = !isatty(STDIN_FILENO);
FILE *sf = NULL;
char script_cmd_buf[256] = {0x00}; // iceman, needs lua script the same file_path_buffer as the rest char script_cmd_buf[256] = {0x00}; // iceman, needs lua script the same file_path_buffer as the rest
PrintAndLogEx(DEBUG, "ISATTY/STDIN_FILENO == %s\n", (stdinOnPipe) ? "true" : "false"); PrintAndLogEx(DEBUG, "ISATTY/STDIN_FILENO == %s\n", (stdinOnPipe) ? "true" : "false");
@ -98,8 +129,7 @@ main_loop(char *script_cmds_file, char *script_cmd, bool stayInCommandLoop) {
char *path; char *path;
int res = searchFile(&path, CMD_SCRIPTS_SUBDIR, script_cmds_file, ".cmd", false); int res = searchFile(&path, CMD_SCRIPTS_SUBDIR, script_cmds_file, ".cmd", false);
if (res == PM3_SUCCESS) { if (res == PM3_SUCCESS) {
sf = fopen(path, "r"); if (push_cmdscriptfile(path, stayInCommandLoop) == PM3_SUCCESS)
if (sf)
PrintAndLogEx(SUCCESS, "executing commands from file: %s\n", path); PrintAndLogEx(SUCCESS, "executing commands from file: %s\n", path);
else else
PrintAndLogEx(ERR, "could not open " _YELLOW_("%s") "...", path); PrintAndLogEx(ERR, "could not open " _YELLOW_("%s") "...", path);
@ -119,16 +149,18 @@ main_loop(char *script_cmds_file, char *script_cmd, bool stayInCommandLoop) {
bool printprompt = false; bool printprompt = false;
char *prompt = PROXPROMPT; char *prompt = PROXPROMPT;
check_script:
// If there is a script file // If there is a script file
if (sf) { if (current_cmdscriptfile()) {
// clear array // clear array
memset(script_cmd_buf, 0, sizeof(script_cmd_buf)); memset(script_cmd_buf, 0, sizeof(script_cmd_buf));
// read script file // read script file
if (!fgets(script_cmd_buf, sizeof(script_cmd_buf), sf)) { if (!fgets(script_cmd_buf, sizeof(script_cmd_buf), current_cmdscriptfile())) {
fclose(sf); if (!pop_cmdscriptfile())
sf = NULL; break;
goto check_script;
} else { } else {
// remove linebreaks // remove linebreaks
@ -205,12 +237,15 @@ main_loop(char *script_cmds_file, char *script_cmd, bool stayInCommandLoop) {
PrintAndLogEx(NORMAL, "%s%s", prompt, cmd); PrintAndLogEx(NORMAL, "%s%s", prompt, cmd);
g_printAndLog = PRINTANDLOG_PRINT | PRINTANDLOG_LOG; g_printAndLog = PRINTANDLOG_PRINT | PRINTANDLOG_LOG;
int ret = CommandReceived(cmd); // add to history if not from a script
if (!current_cmdscriptfile()) {
HIST_ENTRY *entry = history_get(history_length); HIST_ENTRY *entry = history_get(history_length);
// add if not identical to latest recorded cmd
if ((!entry) || (strcmp(entry->line, cmd) != 0)) if ((!entry) || (strcmp(entry->line, cmd) != 0))
add_history(cmd); add_history(cmd);
}
// process cmd
int ret = CommandReceived(cmd);
// exit or quit // exit or quit
if (ret == PM3_EFATAL) if (ret == PM3_EFATAL)
break; break;
@ -230,8 +265,8 @@ main_loop(char *script_cmds_file, char *script_cmd, bool stayInCommandLoop) {
SendCommandNG(CMD_QUIT_SESSION, NULL, 0); SendCommandNG(CMD_QUIT_SESSION, NULL, 0);
msleep(100); // Make sure command is sent before killing client msleep(100); // Make sure command is sent before killing client
if (sf) while (current_cmdscriptfile())
fclose(sf); pop_cmdscriptfile();
if (my_history_path) { if (my_history_path) {
write_history(my_history_path); write_history(my_history_path);

View file

@ -20,11 +20,13 @@
#define PROXPROMPT_OFFLINE "[offline] pm3 --> " #define PROXPROMPT_OFFLINE "[offline] pm3 --> "
#define PROXHISTORY "history.txt" #define PROXHISTORY "history.txt"
#define PROXLOG "log_%Y%m%d.txt" #define PROXLOG "log_%Y%m%d.txt"
#define MAX_NESTED_CMDSCRIPT 10
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
int push_cmdscriptfile(char *path, bool stayafter);
const char *get_my_executable_path(void); const char *get_my_executable_path(void);
const char *get_my_executable_directory(void); const char *get_my_executable_directory(void);
void main_loop(char *script_cmds_file, char *script_cmd, bool stayInCommandLoop); void main_loop(char *script_cmds_file, char *script_cmd, bool stayInCommandLoop);