1 //----------------------------------------------------------------------------- 
   2 // Copyright (C) 2009 Michael Gernoth <michael at gernoth.net> 
   3 // Copyright (C) 2010 iZsh <izsh at fail0verflow.com> 
   5 // This code is licensed to you under the terms of the GNU GPL, version 2 or, 
   6 // at your option, any later version. See the LICENSE.txt file for the text of 
   8 //----------------------------------------------------------------------------- 
  10 //----------------------------------------------------------------------------- 
  17 #include <readline/readline.h> 
  18 #include <readline/history.h> 
  20 #include "proxmark3.h" 
  25 #include "cmdparser.h" 
  30 // a global mutex to prevent interlaced printing from different threads 
  31 pthread_mutex_t print_lock
; 
  33 static serial_port sp
; 
  34 static UsbCommand txcmd
; 
  35 volatile static bool txcmd_pending 
= false; 
  37 void SendCommand(UsbCommand 
*c
) { 
  39                 printf("Sending %d bytes\n", sizeof(UsbCommand
)); 
  43       PrintAndLog("Sending bytes to proxmark failed - offline"); 
  47         The while-loop below causes hangups at times, when the pm3 unit is unresponsive 
  48         or disconnected. The main console thread is alive, but comm thread just spins here. 
  60 struct main_loop_arg 
{ 
  62         char *script_cmds_file
; 
  68 static void *uart_receiver(void *targ
) { 
  69         struct receiver_arg 
*arg 
= (struct receiver_arg
*)targ
; 
  74                 rxlen 
= sizeof(UsbCommand
); 
  75                 if (uart_receive(sp
, prx
, &rxlen
)) { 
  77                         if (((prx
-rx
) % sizeof(UsbCommand
)) != 0) { 
  80                         cmd_count 
= (prx
-rx
) / sizeof(UsbCommand
); 
  82                         for (size_t i 
= 0; i 
< cmd_count
; i
++) { 
  83                                 UsbCommandReceived((UsbCommand
*)(rx
+(i
*sizeof(UsbCommand
)))); 
  89                         if (!uart_send(sp
, (byte_t
*) &txcmd
, sizeof(UsbCommand
))) { 
  90                                 PrintAndLog("Sending bytes to proxmark failed"); 
  92                         txcmd_pending 
= false; 
 100 static void *main_loop(void *targ
) { 
 101         struct main_loop_arg 
*arg 
= (struct main_loop_arg
*)targ
; 
 102         struct receiver_arg rarg
; 
 104         pthread_t reader_thread
; 
 106         if (arg
->usb_present 
== 1) { 
 108                 pthread_create(&reader_thread
, NULL
, &uart_receiver
, &rarg
); 
 109                 // cache Version information now: 
 113         FILE *script_file 
= NULL
; 
 114         char script_cmd_buf
[256];  // iceman, needs lua script the same file_path_buffer as the rest 
 116         if (arg
->script_cmds_file
) { 
 117                 script_file 
= fopen(arg
->script_cmds_file
, "r"); 
 119                         printf("using 'scripting' commands file %s\n", arg
->script_cmds_file
); 
 123         read_history(".history"); 
 127                 // If there is a script file 
 130                         if (!fgets(script_cmd_buf
, sizeof(script_cmd_buf
), script_file
)) { 
 135                                 nl 
= strrchr(script_cmd_buf
, '\r'); 
 138                                 nl 
= strrchr(script_cmd_buf
, '\n'); 
 141                                 if ((cmd 
= (char*) malloc(strlen(script_cmd_buf
) + 1)) != NULL
) { 
 142                                         memset(cmd
, 0, strlen(script_cmd_buf
)); 
 143                                         strcpy(cmd
, script_cmd_buf
); 
 150                         cmd 
= readline(PROXPROMPT
); 
 155                         while(cmd
[strlen(cmd
) - 1] == ' ') 
 156                                 cmd
[strlen(cmd
) - 1] = 0x00; 
 158                         if (cmd
[0] != 0x00) { 
 159                                 int ret 
= CommandReceived(cmd
); 
 161                                 if (ret 
== 99) {  // exit or quit 
 172         write_history(".history"); 
 174         if (arg
->usb_present 
== 1) { 
 176                 pthread_join(reader_thread
, NULL
); 
 189 static void dumpAllHelp(int markdown
) 
 191   printf("\n%sProxmark3 command dump%s\n\n",markdown
?"# ":"",markdown
?"":"\n======================"); 
 192   printf("Some commands are available only if a Proxmark is actually connected.%s\n",markdown
?"  ":""); 
 193   printf("Check column \"offline\" for their availability.\n"); 
 195   command_t 
*cmds 
= getTopLevelCommandTable(); 
 196   dumpCommandsRecursive(cmds
, markdown
); 
 199 static char *my_executable_path 
= NULL
; 
 200 static char *my_executable_directory 
= NULL
; 
 202 const char *get_my_executable_path(void) 
 204         return my_executable_path
; 
 207 const char *get_my_executable_directory(void) 
 209         return my_executable_directory
; 
 212 static void set_my_executable_path(void) 
 214         int path_length 
= wai_getExecutablePath(NULL
, 0, NULL
); 
 215         if (path_length 
!= -1) { 
 216                 my_executable_path 
= (char*)malloc(path_length 
+ 1); 
 217                 int dirname_length 
= 0; 
 218                 if (wai_getExecutablePath(my_executable_path
, path_length
, &dirname_length
) != -1) { 
 219                         my_executable_path
[path_length
] = '\0'; 
 220                         my_executable_directory 
= (char *)malloc(dirname_length 
+ 2); 
 221                         strncpy(my_executable_directory
, my_executable_path
, dirname_length
+1); 
 222                         my_executable_directory
[dirname_length
+1] = '\0'; 
 227 int main(int argc
, char* argv
[]) { 
 231                 printf("syntax: %s <port>\n\n",argv
[0]); 
 232                 printf("\tLinux example:'%s /dev/ttyACM0'\n\n", argv
[0]); 
 233                 printf("help:   %s -h\n\n", argv
[0]); 
 234                 printf("\tDump all interactive help at once\n"); 
 235                 printf("markdown:   %s -m\n\n", argv
[0]); 
 236                 printf("\tDump all interactive help at once in markdown syntax\n"); 
 239         if (strcmp(argv
[1], "-h") == 0) { 
 240                 printf("syntax: %s <port>\n\n",argv
[0]); 
 241                 printf("\tLinux example:'%s /dev/ttyACM0'\n\n", argv
[0]); 
 245         if (strcmp(argv
[1], "-m") == 0) { 
 250         set_my_executable_path(); 
 252         // Make sure to initialize 
 253         struct main_loop_arg marg 
= { 
 255                 .script_cmds_file 
= NULL
 
 257         pthread_t main_loop_thread
; 
 260         sp 
= uart_open(argv
[1]); 
 261         if (sp 
== INVALID_SERIAL_PORT
) { 
 262                 printf("ERROR: invalid serial port\n"); 
 263                 marg
.usb_present 
= 0; 
 265         } else if (sp 
== CLAIMED_SERIAL_PORT
) { 
 266                 printf("ERROR: serial port is claimed by another process\n"); 
 267                 marg
.usb_present 
= 0; 
 270                 marg
.usb_present 
= 1; 
 274         // If the user passed the filename of the 'script' to execute, get it 
 275         if (argc 
> 2 && argv
[2]) { 
 276                 if (argv
[2][0] == 'f' &&  //buzzy, if a word 'flush' passed, flush the output after every log entry. 
 282                         printf("Output will be flushed after every print.\n"); 
 286                 marg
.script_cmds_file 
= argv
[2]; 
 289         // create a mutex to avoid interlacing print commands from our different threads 
 290         pthread_mutex_init(&print_lock
, NULL
); 
 291         pthread_create(&main_loop_thread
, NULL
, &main_loop
, &marg
); 
 293         // build ui/graph forms on separate thread (killed on main_loop_thread); 
 294         InitGraphics(argc
, argv
); 
 296         //this won't return until ExitGraphics() is called 
 298         //wait for thread to finish 
 299         pthread_join(main_loop_thread
, NULL
); 
 308         pthread_mutex_destroy(&print_lock
);