/libr/fs/shell.c

https://github.com/Warlockk/radare2 · C · 313 lines · 300 code · 8 blank · 5 comment · 104 complexity · b537e231f51544237b07f05516aebfc3 MD5 · raw file

  1. /* radare2 - LGPL - Copyright 2018-2019 - pancake */
  2. #include <r_fs.h>
  3. #define PROMPT_PATH_BUFSIZE 1024
  4. static bool handlePipes(RFS *fs, char *msg, const ut8 *data, const char *cwd) {
  5. char *red = strchr (msg, '>');
  6. if (red) {
  7. *red++ = 0;
  8. r_str_trim (msg);
  9. red = r_str_trim_dup (red);
  10. if (*red != '/') {
  11. char *blu = r_str_newf ("%s/%s", cwd, red);
  12. free (red);
  13. red = blu;
  14. } else {
  15. }
  16. RFSFile *f = r_fs_open (fs, red, true);
  17. if (!f) {
  18. eprintf ("Cannot open %s for writing\n", red);
  19. free (red);
  20. return true;
  21. }
  22. r_fs_write (fs, f, 0, data == NULL ? (const ut8 *) msg : data, strlen (msg));
  23. free (red);
  24. r_fs_close (fs, f);
  25. r_fs_file_free (f);
  26. return true;
  27. }
  28. return false;
  29. }
  30. R_API int r_fs_shell_prompt(RFSShell* shell, RFS* fs, const char* root) {
  31. char buf[PROMPT_PATH_BUFSIZE];
  32. char path[PROMPT_PATH_BUFSIZE];
  33. char prompt[PROMPT_PATH_BUFSIZE];
  34. char str[2048];
  35. char* input;
  36. const char* ptr;
  37. RList* list = NULL;
  38. RListIter* iter;
  39. RFSFile* file = NULL;
  40. if (root && *root) {
  41. strncpy (buf, root, sizeof (buf) - 1);
  42. r_str_trim_path (buf);
  43. list = r_fs_root (fs, buf);
  44. if (r_list_empty (list)) {
  45. printf ("Unknown root\n");
  46. r_list_free (list);
  47. return false;
  48. }
  49. r_str_ncpy (path, buf, sizeof (path) - 1);
  50. } else {
  51. strcpy (path, "/");
  52. }
  53. PrintfCallback cb_printf = fs->csb.cb_printf;
  54. for (;;) {
  55. snprintf (prompt, sizeof (prompt), "[%.*s]> ", (int)sizeof (prompt) - 5, path);
  56. if (shell) {
  57. *shell->cwd = strdup (path);
  58. if (shell->set_prompt) {
  59. shell->set_prompt (prompt);
  60. }
  61. if (shell->readline) {
  62. ptr = shell->readline ();
  63. } else {
  64. if (!fgets (buf, sizeof (buf) - 1, stdin)) {
  65. break;
  66. }
  67. if (feof (stdin)) {
  68. break;
  69. }
  70. buf[strlen (buf) - 1] = '\0';
  71. ptr = buf;
  72. }
  73. if (!ptr) {
  74. break;
  75. }
  76. r_str_trim ((char *)ptr); // XXX abadidea
  77. if (shell->hist_add) {
  78. shell->hist_add (ptr);
  79. }
  80. if (ptr != buf) {
  81. r_str_ncpy (buf, ptr, sizeof (buf) - 1);
  82. }
  83. } else {
  84. printf ("%s", prompt);
  85. if (!fgets (buf, sizeof (buf) - 1, stdin)) {
  86. break;
  87. }
  88. if (feof (stdin)) {
  89. break;
  90. }
  91. buf[strlen (buf) - 1] = '\0';
  92. }
  93. char *wave = strchr (buf, '~');
  94. if (wave) {
  95. *wave++ = 0;
  96. }
  97. if (!strcmp (buf, "q") || !strcmp (buf, "exit")) {
  98. r_list_free (list);
  99. return true;
  100. }
  101. if (buf[0] == '#') {
  102. // comment
  103. continue;
  104. } else if (buf[0] == ':') {
  105. char *msg = fs->cob.cmdstr (fs->cob.core, buf + 1);
  106. printf ("%s\n", msg);
  107. free (msg);
  108. } else if (buf[0] == '!') {
  109. r_sandbox_system (buf + 1, 1);
  110. } else if (!strncmp (buf, "echo", 4)) {
  111. char *msg = r_str_trim_dup (buf + 4);
  112. if (!handlePipes (fs, msg, NULL, path)) {
  113. cb_printf ("%s\n", msg);
  114. }
  115. free (msg);
  116. } else if (!strncmp (buf, "ls", 2)) {
  117. char *ptr = str;
  118. r_list_free (list);
  119. if (buf[2] == ' ') {
  120. if (buf[3] != '/') {
  121. strncpy (str, path, sizeof (str) - 1);
  122. strcat (str, "/");
  123. strncat (str, buf + 3, sizeof (buf) - 1);
  124. list = r_fs_dir (fs, str);
  125. } else {
  126. list = r_fs_dir (fs, buf + 3);
  127. ptr = buf + 3;
  128. }
  129. } else {
  130. ptr = path;
  131. list = r_fs_dir (fs, path);
  132. }
  133. if (list) {
  134. r_list_foreach (list, iter, file) {
  135. cb_printf ("%c %s\n", file->type, file->name);
  136. }
  137. }
  138. // mountpoints if any
  139. RFSRoot *r;
  140. char *me = strdup (ptr);
  141. r_list_foreach (fs->roots, iter, r) {
  142. char *base = strdup (r->path);
  143. char *ls = (char *)r_str_lchr (base, '/');
  144. if (ls) {
  145. ls++;
  146. *ls = 0;
  147. }
  148. // TODO: adjust contents between //
  149. if (!strcmp (me, base)) {
  150. cb_printf ("m %s\n", (r->path && r->path[0]) ? r->path + 1: "");
  151. }
  152. free (base);
  153. }
  154. free (me);
  155. } else if (!strncmp (buf, "pwd", 3)) {
  156. eprintf ("%s\n", path);
  157. } else if (!memcmp (buf, "cd ", 3)) {
  158. char opath[PROMPT_PATH_BUFSIZE];
  159. r_str_ncpy (opath, path, sizeof (opath));
  160. input = buf + 3;
  161. while (*input == ' ') {
  162. input++;
  163. }
  164. if (!strcmp (input, "..")) {
  165. char* p = (char*) r_str_lchr (path, '/');
  166. if (p) {
  167. p[(p == path)? 1: 0] = 0;
  168. }
  169. } else {
  170. strcat (path, "/");
  171. if (*input == '/') {
  172. strncpy (path, input, sizeof (opath) - 1);
  173. } else {
  174. if ((strlen (path) + strlen (input)) >= sizeof (path)) {
  175. // overflow
  176. path[0] = 0;
  177. } else {
  178. strcat (path, input);
  179. }
  180. }
  181. path[sizeof (path) - 1] = 0;
  182. }
  183. r_str_trim_path (path);
  184. r_list_free (list);
  185. list = r_fs_dir (fs, path);
  186. if (r_list_empty (list)) {
  187. RFSRoot *root;
  188. RListIter *iter;
  189. r_list_foreach (fs->roots, iter, root) {
  190. if (!strcmp (path, root->path)) {
  191. r_list_append (list, root->path);
  192. }
  193. }
  194. }
  195. } else if (!memcmp (buf, "cat ", 4)) {
  196. input = buf + 3;
  197. while (input[0] == ' ') {
  198. input++;
  199. }
  200. if (input[0] == '/') {
  201. if (root) {
  202. strncpy (str, root, sizeof (str) - 1);
  203. } else {
  204. str[0] = 0;
  205. }
  206. } else {
  207. strncpy (str, path, sizeof (str) - 1);
  208. }
  209. strncat (str, "/", sizeof (str) - strlen (str) - 1);
  210. strncat (str, input, sizeof (str) - strlen (str) - 1);
  211. char *p = strchr (str, '>');
  212. if (p) {
  213. *p = 0;
  214. }
  215. file = r_fs_open (fs, str, false);
  216. if (file) {
  217. if (p) {
  218. *p = '>';
  219. }
  220. r_fs_read (fs, file, 0, file->size);
  221. if (!handlePipes (fs, str, file->data, path)) {
  222. char *s = r_str_ndup ((const char *)file->data, file->size);
  223. cb_printf ("%s\n", s);
  224. free (s);
  225. }
  226. write (1, "\n", 1);
  227. r_fs_close (fs, file);
  228. } else {
  229. eprintf ("Cannot open file\n");
  230. }
  231. } else if (!memcmp (buf, "mount", 5)) {
  232. RFSRoot* r;
  233. r_list_foreach (fs->roots, iter, r) {
  234. cb_printf ("%s %s\n", r->path, r->p->name);
  235. }
  236. } else if (!memcmp (buf, "get ", 4)) {
  237. char* s = 0;
  238. input = buf + 3;
  239. while (input[0] == ' ') {
  240. input++;
  241. }
  242. if (input[0] == '/') {
  243. if (root) {
  244. s = malloc (strlen (root) + strlen (input) + 2);
  245. if (!s) {
  246. goto beach;
  247. }
  248. strcpy (s, root);
  249. }
  250. } else {
  251. s = malloc (strlen (path) + strlen (input) + 2);
  252. if (!s) {
  253. goto beach;
  254. }
  255. strcpy (s, path);
  256. }
  257. if (!s) {
  258. s = calloc (strlen (input) + 32, 1);
  259. if (!s) {
  260. goto beach;
  261. }
  262. }
  263. strcat (s, "/");
  264. strcat (s, input);
  265. file = r_fs_open (fs, s, false);
  266. if (file) {
  267. r_fs_read (fs, file, 0, file->size);
  268. r_file_dump (input, file->data, file->size, 0);
  269. r_fs_close (fs, file);
  270. } else {
  271. input -= 2; //OMFG!!!! O_O
  272. memcpy (input, "./", 2);
  273. if (!r_fs_dir_dump (fs, s, input)) {
  274. eprintf ("Cannot open file\n");
  275. }
  276. }
  277. free (s);
  278. } else if (!memcmp (buf, "help", 4) || !strcmp (buf, "?")) {
  279. cb_printf (
  280. "Usage: [command (arguments)]([~grep-expression])\n"
  281. " !cmd ; escape to system\n"
  282. " :cmd ; escape to the r2 repl\n"
  283. " ls [path] ; list current directory\n"
  284. " cd path ; change current directory\n"
  285. " cat file ; print contents of file\n"
  286. " get file ; dump file to disk\n"
  287. " mount ; list mount points\n"
  288. " q/exit ; leave prompt mode\n"
  289. " ?/help ; show this help\n");
  290. } else {
  291. if (*buf) {
  292. eprintf ("Unknown command %s\n", buf);
  293. }
  294. }
  295. if (wave) {
  296. fs->csb.cb_grep (wave);
  297. }
  298. fs->csb.cb_flush ();
  299. }
  300. beach:
  301. clearerr (stdin);
  302. printf ("\n");
  303. r_list_free (list);
  304. return true;
  305. }