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