radare2/libr/fs/shell.c
Riccardo Schirone 738bc9cb19 Fix warnings by using more r_str_ncpy
* Fix wrong logic in visual_search

When the string to be searched is wrapped in " ", you want to remove the
first and last quotes and look only for the internal string.

* Increase size to prevent string truncation (and fix compiler warning)
* Fix "destination unchanged after copying no bytes" warning
* Move msp430_register_names where it belongs to
* Fix Wstringop-truncation warning
2018-12-19 12:07:49 +01:00

257 lines
5.8 KiB
C

/* radare2 - LGPL - Copyright 2018 - pancake */
#include <r_fs.h>
#define PROMPT_PATH_BUFSIZE 1024
R_API int r_fs_shell_prompt(RFSShell* shell, RFS* fs, const char* root) {
char buf[PROMPT_PATH_BUFSIZE];
char path[PROMPT_PATH_BUFSIZE];
char prompt[PROMPT_PATH_BUFSIZE];
char str[2048];
char* input;
const char* ptr;
RList* list = NULL;
RListIter* iter;
RFSFile* file = NULL;
if (root && *root) {
strncpy (buf, root, sizeof (buf) - 1);
r_str_trim_path (buf);
list = r_fs_root (fs, buf);
if (r_list_empty (list)) {
printf ("Unknown root\n");
r_list_free (list);
return false;
}
r_str_ncpy (path, buf, sizeof (path) - 1);
} else {
strcpy (path, "/");
}
for (;;) {
snprintf (prompt, sizeof (prompt), "[%.*s]> ", (int)sizeof (prompt) - 5, path);
if (shell) {
*shell->cwd = strdup (path);
if (shell->set_prompt) {
shell->set_prompt (prompt);
}
if (shell->readline) {
ptr = shell->readline ();
} else {
if (!fgets (buf, sizeof (buf) - 1, stdin)) {
break;
}
if (feof (stdin)) {
break;
}
buf[strlen (buf) - 1] = '\0';
ptr = buf;
}
if (!ptr) {
break;
}
ptr = r_str_trim ((char *)ptr);
if (shell->hist_add) {
shell->hist_add (ptr);
}
if (ptr != buf) {
r_str_ncpy (buf, ptr, sizeof (buf) - 1);
}
} else {
printf ("%s", prompt);
if (!fgets (buf, sizeof (buf) - 1, stdin)) {
break;
}
if (feof (stdin)) {
break;
}
buf[strlen (buf) - 1] = '\0';
}
if (!strcmp (buf, "q") || !strcmp (buf, "exit")) {
r_list_free (list);
return true;
}
if (buf[0] == '!') {
r_sandbox_system (buf + 1, 1);
} else if (!strncmp (buf, "ls", 2)) {
char *ptr = str;
r_list_free (list);
if (buf[2] == ' ') {
if (buf[3] != '/') {
strncpy (str, path, sizeof (str) - 1);
strcat (str, "/");
strncat (str, buf + 3, sizeof (buf) - 1);
list = r_fs_dir (fs, str);
} else {
list = r_fs_dir (fs, buf + 3);
ptr = buf + 3;
}
} else {
ptr = path;
list = r_fs_dir (fs, path);
}
if (list) {
r_list_foreach (list, iter, file) {
printf ("%c %s\n", file->type, file->name);
}
}
// mountpoints if any
RFSRoot *r;
char *me = strdup (ptr);
r_list_foreach (fs->roots, iter, r) {
char *base = strdup (r->path);
char *ls = (char *)r_str_lchr (base, '/');
if (ls) {
ls++;
*ls = 0;
}
// TODO: adjust contents between //
if (!strcmp (me, base)) {
printf ("m %s\n", (r->path && r->path[0]) ? r->path + 1: "");
}
free (base);
}
free (me);
} else if (!strncmp (buf, "pwd", 3)) {
eprintf ("%s\n", path);
} else if (!memcmp (buf, "cd ", 3)) {
char opath[PROMPT_PATH_BUFSIZE];
r_str_ncpy (opath, path, sizeof (opath));
input = buf + 3;
while (*input == ' ') {
input++;
}
if (!strcmp (input, "..")) {
char* p = (char*) r_str_lchr (path, '/');
if (p) {
p[(p == path)? 1: 0] = 0;
}
} else {
strcat (path, "/");
if (*input == '/') {
strncpy (path, input, sizeof (opath) - 1);
} else {
if ((strlen (path) + strlen (input)) >= sizeof (path)) {
// overflow
path[0] = 0;
} else {
strcat (path, input);
}
}
path[sizeof (path) - 1] = 0;
}
r_str_trim_path (path);
r_list_free (list);
list = r_fs_dir (fs, path);
if (r_list_empty (list)) {
RFSRoot *root;
bool found = false;
RListIter *iter;
r_list_foreach (fs->roots, iter, root) {
if (!strcmp (path, root->path)) {
r_list_append (list, root->path);
found = true;
}
}
if (!found) {
strcpy (path, opath);
}
}
} else if (!memcmp (buf, "cat ", 4)) {
input = buf + 3;
while (input[0] == ' ') {
input++;
}
if (input[0] == '/') {
if (root) {
strncpy (str, root, sizeof (str) - 1);
} else {
str[0] = 0;
}
} else {
strncpy (str, path, sizeof (str) - 1);
}
strncat (str, "/", sizeof (str) - strlen (str) - 1);
strncat (str, input, sizeof (str) - strlen (str) - 1);
file = r_fs_open (fs, str);
if (file) {
r_fs_read (fs, file, 0, file->size);
write (1, file->data, file->size);
r_fs_close (fs, file);
} else {
eprintf ("Cannot open file\n");
}
} else if (!memcmp (buf, "mount", 5)) {
RFSRoot* r;
r_list_foreach (fs->roots, iter, r) {
eprintf ("%s %s\n", r->path, r->p->name);
}
} else if (!memcmp (buf, "get ", 4)) {
char* s = 0;
input = buf + 3;
while (input[0] == ' ') {
input++;
}
if (input[0] == '/') {
if (root) {
s = malloc (strlen (root) + strlen (input) + 2);
if (!s) {
goto beach;
}
strcpy (s, root);
}
} else {
s = malloc (strlen (path) + strlen (input) + 2);
if (!s) {
goto beach;
}
strcpy (s, path);
}
if (!s) {
s = calloc (strlen (input) + 32, 1);
if (!s) {
goto beach;
}
}
strcat (s, "/");
strcat (s, input);
file = r_fs_open (fs, s);
if (file) {
r_fs_read (fs, file, 0, file->size);
r_file_dump (input, file->data, file->size, 0);
r_fs_close (fs, file);
} else {
input -= 2; //OMFG!!!! O_O
memcpy (input, "./", 2);
if (!r_fs_dir_dump (fs, s, input)) {
printf ("Cannot open file\n");
}
}
free (s);
} else if (!memcmp (buf, "help", 4) || !strcmp (buf, "?")) {
eprintf (
"Commands:\n"
" !cmd ; escape to system\n"
" ls [path] ; list current directory\n"
" cd path ; change current directory\n"
" cat file ; print contents of file\n"
" get file ; dump file to disk\n"
" mount ; list mount points\n"
" q/exit ; leave prompt mode\n"
" ?/help ; show this help\n");
} else {
if (*buf) {
eprintf ("Unknown command %s\n", buf);
}
}
}
beach:
clearerr (stdin);
printf ("\n");
r_list_free (list);
return true;
}