radare2/libr/core/cmd.c

2751 lines
69 KiB
C
Raw Normal View History

2016-04-27 20:30:29 +00:00
/* radare - LGPL - Copyright 2009-2016 - nibble, pancake */
2014-03-17 23:05:44 +00:00
#if 0
* Use RList
* Support callback for null command (why?)
* Show help of commands
- long commands not yet tested at all
- added interface to export command list into an autocompletable
argc, argv for dietline
* r_cmd must provide a nesting char table indexing for commands
- this is already partially done
- this is pretty similar to r_db
- every module can register their own commands
- commands can be listed like in a tree
#endif
#define INTERACTIVE_MAX_REP 1024
#include <r_core.h>
#include <r_anal.h>
2015-02-24 13:50:14 +00:00
#include <stdint.h>
#include <sys/types.h>
#include <ctype.h>
#include <stdarg.h>
2012-02-27 01:40:27 +00:00
static void cmd_debug_reg(RCore *core, const char *str);
#include "cmd_quit.c"
2012-02-27 01:40:27 +00:00
#include "cmd_hash.c"
#include "cmd_debug.c"
#include "cmd_log.c"
2012-02-27 01:40:27 +00:00
#include "cmd_zign.c"
#include "cmd_section.c"
#include "cmd_flag.c"
#include "cmd_project.c"
#include "cmd_write.c"
#include "cmd_cmp.c"
#include "cmd_eval.c"
2012-02-27 01:40:27 +00:00
#include "cmd_anal.c"
#include "cmd_open.c"
#include "cmd_meta.c"
#include "cmd_type.c"
#include "cmd_egg.c"
#include "cmd_info.c"
2012-02-27 01:40:27 +00:00
#include "cmd_macro.c"
#include "cmd_magic.c"
#include "cmd_mount.c"
#include "cmd_seek.c"
#include "cmd_print.c"
#include "cmd_help.c"
#include "cmd_search.c"
static void recursive_help (RCore *core, const char *cmd) {
char *nl, *line;
r_cons_push ();
2016-10-15 23:46:03 +00:00
if (strchr (cmd, '[')) {
eprintf ("Skip ((%s))\n", cmd);
return;
}
char *msg = r_core_cmd_str (core, cmd);
r_cons_pop ();
line = msg;
r_cons_print (msg);
2016-10-15 23:46:03 +00:00
(void) r_str_ansi_filter (msg, NULL, NULL, strlen (msg));
do {
nl = strchr (line, '\n');
if (nl) {
*nl = 0;
}
char *help_token = strstr (line, "[?]");
if (help_token) {
help_token[0] = '?';
help_token[1] = 0;
const char *sp = strchr (line, ' ');
if (sp) {
recursive_help (core, sp + 1);
}
}
// eprintf (" -- ((%s))\n", line);
line = nl + 1;
} while (nl);
}
static int r_core_cmd_nullcallback(void *data) {
RCore *core = (RCore*) data;
if (core->cons->breaked) {
2015-09-14 10:35:38 +00:00
core->cons->breaked = false;
return 0;
}
if (!core->cmdrepeat) return 0;
2015-09-14 10:35:38 +00:00
r_core_cmd_repeat (core, true);
return 1;
}
// TODO: move somewhere else
R_API RAsmOp *r_core_disassemble (RCore *core, ut64 addr) {
int delta;
ut8 buf[128];
static RBuffer *b = NULL; // XXX: never freed and non-thread safe. move to RCore
RAsmOp *op;
if (!b) {
b = r_buf_new ();
2016-05-24 20:22:15 +00:00
if (!b) return NULL;
if (!r_core_read_at (core, addr, buf, sizeof (buf)))
return NULL;
b->base = addr;
r_buf_set_bytes (b, buf, sizeof (buf));
} else {
if ((addr < b->base) || addr > (b->base+b->length-32)) {
if (!r_core_read_at (core, addr, buf, sizeof (buf)))
return NULL;
b->base = addr;
r_buf_set_bytes (b, buf, sizeof (buf));
}
}
delta = addr - b->base;
2014-02-22 00:58:40 +00:00
op = R_NEW0 (RAsmOp);
r_asm_set_pc (core->assembler, addr);
if (r_asm_disassemble (core->assembler, op, b->buf+delta, b->length)<1) {
free (op);
return NULL;
}
return op;
}
2015-12-31 22:55:06 +00:00
#if __UNIX__
#include <sys/utsname.h>
#endif
2015-12-30 11:43:15 +00:00
static int cmd_uname(void *data, const char *input) {
const char* help_msg[] = {
"Usage:", "u", "uname or undo write/seek",
"u", "", "show system uname",
"uw", "", "alias for wc (requires: e io.cache=true)",
"us", "", "alias for s- (seek history)",
NULL};
switch (input[0]) {
case '?':
r_core_cmd_help (data, help_msg);
return 1;
case 's':
r_core_cmdf (data, "s-%s", input+1);
return 1;
case 'w':
r_core_cmdf (data, "wc%s", input+1);
return 1;
}
#if __UNIX__
struct utsname un;
uname (&un);
r_cons_printf ("%s %s %s %s\n", un.sysname,
un.nodename, un.release, un.machine);
#elif __WINDOWS__
r_cons_printf ("windows\n");
#else
r_cons_printf ("unknown\n");
#endif
return 0;
}
static int cmd_alias(void *data, const char *input) {
int i;
2015-05-19 11:06:27 +00:00
char *def, *q, *desc, *buf;
RCore *core = (RCore *)data;
if (*input=='?') {
2014-06-20 16:35:49 +00:00
const char* help_msg[] = {
"Usage:", "$alias[=cmd] [args...]", "Alias commands",
"$", "", "list all defined aliases",
"$*", "", "same as above, but using r2 commands",
"$", "dis='af;pdf'", "create command - analyze to show function",
"$", "test=#!pipe node /tmp/test.js", "create command - rlangpipe script",
2014-06-20 16:35:49 +00:00
"$", "dis=", "undefine alias",
"$", "dis", "execute the previously defined alias",
"$", "dis?", "show commands aliased by 'analyze'",
NULL};
r_core_cmd_help (core, help_msg);
return 0;
}
i = strlen (input);
buf = malloc (i+2);
if (!buf) return 0;
*buf = '$'; // prefix aliases with a dash
memcpy (buf+1, input, i+1);
q = strchr (buf, ' ');
2015-05-19 11:06:27 +00:00
def = strchr (buf, '=');
desc = strchr (buf, '?');
/* create alias */
if ((def && q && (def < q)) || (def && !q)) {
*def++ = 0;
size_t len = strlen(def);
/* Remove quotes */
if ((def[0] == '\'') && (def[len-1] == '\'')) {
def[len-1] = 0x00;
def++;
}
2015-05-19 11:06:27 +00:00
if (!q || (q && q>def)) {
if (*def) r_cmd_alias_set (core->rcmd, buf, def, 0);
else r_cmd_alias_del (core->rcmd, buf);
}
2015-05-19 11:06:27 +00:00
/* Show command for alias */
} else if (desc && !q) {
char *v;
*desc = 0;
v = r_cmd_alias_get (core->rcmd, buf, 0);
2015-05-19 11:06:27 +00:00
if (v) {
2016-06-26 04:16:57 +00:00
r_cons_println (v);
2015-05-19 11:06:27 +00:00
free (buf);
return 1;
} else {
eprintf ("unknown key '%s'\n", buf);
}
/* Show aliases */
} else if (buf[1]=='*') {
int i, count = 0;
char **keys = r_cmd_alias_keys (core->rcmd, &count);
for (i=0; i<count; i++) {
const char *v = r_cmd_alias_get (core->rcmd, keys[i], 0);
r_cons_printf ("%s=%s\n", keys[i], v);
}
2015-05-19 11:06:27 +00:00
} else if (!buf[1]) {
int i, count = 0;
char **keys = r_cmd_alias_keys (core->rcmd, &count);
for (i=0; i<count; i++) {
r_cons_println (keys[i]);
}
/* Execute alias */
} else {
char *v;
if (q) *q = 0;
v = r_cmd_alias_get (core->rcmd, buf, 0);
if (v) {
if (q) {
char *out, *args = q+1;
out = malloc (strlen (v) + strlen (args) + 2);
if (out) { //XXX slow
strcpy (out, v);
strcat (out, " ");
strcat (out, args);
r_core_cmd0 (core, out);
free (out);
} else eprintf ("cannot malloc\n");
} else {
r_core_cmd0 (core, v);
}
2015-05-19 11:06:27 +00:00
} else {
eprintf ("unknown key '%s'\n", buf);
}
}
2014-08-18 01:22:16 +00:00
free (buf);
return 0;
}
static int getArg(char ch, int def) {
switch (ch) {
case '&':
case '-':
return ch;
}
return def;
}
static void aliascmd(RCore *core, const char *str) {
switch (str[0]) {
case '-':
if (str[1]) {
r_cmd_alias_del (core->rcmd, str+2);
} else {
r_cmd_alias_del (core->rcmd, NULL);
// r_cmd_alias_reset (core->rcmd);
}
break;
case '?':
eprintf ("Usage: =$[-][remotecmd] # remote command alias\n");
eprintf (" =$dr # makes 'dr' alias for =!dr\n");
eprintf (" =$-dr # unset 'dr' alias\n");
break;
case 0:
r_core_cmd0 (core, "$");
break;
default:
r_cmd_alias_set (core->rcmd, str, "", 1);
break;
}
}
static int cmd_rap(void *data, const char *input) {
RCore *core = (RCore *)data;
2011-06-04 01:51:33 +00:00
switch (*input) {
case '$': aliascmd (core, input+1); break;
case '\0': r_core_rtr_list (core); break;
case 'h':
r_core_rtr_http (core, getArg (input[1], 'h'), input + 1);
break;
case 'H':
while (input[1]==' ') {
input++;
}
r_core_rtr_http (core, getArg (input[1], 'H'), input + 1);
break;
case '?': r_core_rtr_help (core); break;
case '+': r_core_rtr_add (core, input + 1); break;
case '-': r_core_rtr_remove (core, input + 1); break;
case '=': r_core_rtr_session (core, input + 1); break;
//case ':': r_core_rtr_cmds (core, input+1); break;
case '<': r_core_rtr_pushout (core, input + 1); break;
case '!':
if (input[1]=='=') {
// swap core->cmdremote = core->cmdremote? 0: 1;
core->cmdremote = input[2]? 1: 0;
r_cons_println (r_str_bool (core->cmdremote));
} else {
r_io_system (core->io, input+1);
}
break;
default: r_core_rtr_cmd (core, input);
}
return 0;
}
static int cmd_yank(void *data, const char *input) {
ut64 n;
RCore *core = (RCore *)data;
switch (input[0]) {
case ' ':
r_core_yank (core, core->offset, r_num_math (core->num, input+1));
break;
case 'l':
core->num->value = core->yank_buf->length;
break;
case 'y':
while (input[1]==' ') input++;
n = input[1]? r_num_math (core->num, input+1): core->offset;
r_core_yank_paste (core, n, 0);
break;
case 'x':
r_core_yank_hexdump (core, r_num_math (core->num, input+1));
break;
case 'z':
r_core_yank_string (core, core->offset, r_num_math (core->num, input+1));
break;
case 'w':
switch (input[1]) {
case ' ':
2016-03-31 11:21:51 +00:00
r_core_yank_set (core, 0, (const ut8*)input + 2, strlen (input + 2));
break;
case 'x':
if (input[2] == ' ') {
char *out = strdup (input + 3);
2016-03-31 11:21:51 +00:00
int len = r_hex_str2bin (input+3, (ut8*)out);
if (len> 0) {
2016-03-31 11:21:51 +00:00
r_core_yank_set (core, 0LL, (const ut8*)out, len);
} else {
eprintf ("Invalid length\n");
}
free (out);
} else eprintf ("Usage: ywx [hexpairs]\n");
// r_core_yank_write_hex (core, input + 2);
break;
}
break;
case 'p':
r_core_yank_cat (core, r_num_math (core->num, input+1));
break;
case 's':
r_core_yank_cat_string (core, r_num_math (core->num, input+1));
break;
case 't':
r_core_yank_to (core, input+1);
break;
case 'f':
if (*(input+1) == ' ' ) r_core_yank_file_ex (core, input+1);
else if (*(input+1) == 'a' ) r_core_yank_file_all (core, input+2);
break;
case '\0':
r_core_yank_dump (core, r_num_math (core->num, ""));
break;
2014-06-20 16:35:49 +00:00
default:{
const char* help_msg[] = {
"Usage:", "y[ptxy] [len] [[@]addr]", " # See wd? for memcpy, same as 'yf'.",
"y", "", "show yank buffer information (srcoff len bytes)",
"y", " 16", "copy 16 bytes into clipboard",
"y", " 16 0x200", "copy 16 bytes into clipboard from 0x200",
"y", " 16 @ 0x200", "copy 16 bytes into clipboard from 0x200",
"yz", "", "copy up to blocksize zero terminated string bytes into clipboard",
"yz", " 16", "copy up to 16 zero terminated string bytes into clipboard",
"yz", " @ 0x200", "copy up to blocksize zero terminated string bytes into clipboard from 0x200",
"yz", " 16 @ 0x200", "copy up to 16 zero terminated string bytes into clipboard from 0x200",
"yp", "", "print contents of clipboard",
2014-06-20 16:35:49 +00:00
"yx", "", "print contents of clipboard in hexadecimal",
"ys", "", "print contents of clipboard as string",
2014-06-20 16:35:49 +00:00
"yt", " 64 0x200", "copy 64 bytes from current seek to 0x200",
"yf", " 64 0x200", "file copy 64 bytes from 0x200 from file (opens w/ io), use -1 for all bytes",
"yfa", " file copy", "copy all bytes from file (opens w/ io)",
2014-06-20 16:35:49 +00:00
"yy", " 0x3344", "paste clipboard",
NULL};
r_core_cmd_help (core, help_msg);
}
break;
}
2015-09-14 10:35:38 +00:00
return true;
}
R_API int r_core_run_script (RCore *core, const char *file) {
2015-09-14 10:35:38 +00:00
int ret = false;
RListIter *iter;
RLangPlugin *p;
char *name;
r_list_foreach (core->scriptstack, iter, name) {
if (!strcmp (file, name)) {
eprintf ("WARNING: ignored nested source: %s\n", file);
2015-09-14 10:35:38 +00:00
return false;
}
}
r_list_push (core->scriptstack, strdup (file));
if (!strcmp (file, "-")) {
char *out = r_core_editor (core, NULL, NULL);
if (out) {
ret = r_core_cmd_lines (core, out);
free (out);
}
} else if (r_parse_is_c_file (file)) {
char *out = r_parse_c_file (file);
if (out) {
r_cons_strcat (out);
sdb_query_lines (core->anal->sdb_types, out);
free (out);
}
2015-09-14 10:35:38 +00:00
ret = out? true: false;
} else {
p = r_lang_get_by_extension (core->lang, file);
if (p) {
r_lang_use (core->lang, p->name);
ret = r_lang_run_file (core->lang, file);
} else {
2015-10-23 00:58:48 +00:00
#if __WINDOWS__
#define cmdstr(x) r_str_newf (x" %s", file);
#else
2015-10-23 20:27:04 +00:00
#define cmdstr(x) r_str_newf (x" '%s'", file);
2015-10-23 00:58:48 +00:00
#endif
const char *p = r_str_lchr (file, '.');
if (p) {
const char *ext = p+1;
/* TODO: handle this inside r_lang_pipe with new APIs */
if (!strcmp (ext, "js")) {
2015-10-23 00:58:48 +00:00
char *cmd = cmdstr("node");
r_lang_use (core->lang, "pipe");
r_lang_run_file (core->lang, cmd);
free (cmd);
ret = 1;
2015-04-30 22:50:25 +00:00
} else if (!strcmp (ext, "exe")) {
2015-10-23 00:58:48 +00:00
#if __WINDOWS__
2015-04-30 22:50:25 +00:00
char *cmd = r_str_newf ("%s", file);
#else
2015-10-23 00:58:48 +00:00
char *cmd = cmdstr("wine");
2015-04-30 22:50:25 +00:00
#endif
r_lang_use (core->lang, "pipe");
r_lang_run_file (core->lang, cmd);
free (cmd);
ret = 1;
2015-04-07 16:34:28 +00:00
} else if (!strcmp (ext, "d")) {
2015-10-23 00:58:48 +00:00
char *cmd = cmdstr ("dmd -run");
2015-04-07 16:34:28 +00:00
r_lang_use (core->lang, "pipe");
r_lang_run_file (core->lang, cmd);
free (cmd);
ret = 1;
} else if (!strcmp (ext, "lsp")) {
2015-10-23 00:58:48 +00:00
char *cmd = cmdstr("newlisp -n");
r_lang_use (core->lang, "pipe");
r_lang_run_file (core->lang, cmd);
free (cmd);
2015-04-07 16:34:28 +00:00
ret = 1;
} else if (!strcmp (ext, "go")) {
2015-10-23 00:58:48 +00:00
char *cmd = cmdstr ("go run");
2015-04-07 16:34:28 +00:00
r_lang_use (core->lang, "pipe");
r_lang_run_file (core->lang, cmd);
free (cmd);
ret = 1;
} else if (!strcmp (ext, "es6")) {
2015-10-23 00:58:48 +00:00
char *cmd = cmdstr ("babel-node");
r_lang_use (core->lang, "pipe");
r_lang_run_file (core->lang, cmd);
free (cmd);
ret = 1;
2015-04-30 22:50:25 +00:00
} else if (!strcmp (ext, "rb")) {
2015-10-23 00:58:48 +00:00
char *cmd = cmdstr ("ruby %s");
2015-04-30 22:50:25 +00:00
r_lang_use (core->lang, "pipe");
r_lang_run_file (core->lang, cmd);
free (cmd);
ret = 1;
} else if (!strcmp (ext, "pl")) {
2015-10-23 00:58:48 +00:00
char *cmd = cmdstr ("perl");
2015-04-30 22:50:25 +00:00
r_lang_use (core->lang, "pipe");
r_lang_run_file (core->lang, cmd);
free (cmd);
ret = 1;
} else if (!strcmp (ext, "py")) {
2015-10-23 00:58:48 +00:00
char *cmd = cmdstr ("python");
r_lang_use (core->lang, "pipe");
r_lang_run_file (core->lang, cmd);
free (cmd);
ret = 1;
}
}
if (!ret) {
ret = r_core_cmd_file (core, file);
}
}
}
free (r_list_pop (core->scriptstack));
return ret;
}
2014-08-28 20:51:03 +00:00
static int cmd_ls(void *data, const char *input) {
r_core_syscmd_ls (input);
return 0;
}
static int cmd_stdin(void *data, const char *input) {
RCore *core = (RCore *)data;
if (input[0]=='?') {
r_cons_printf ("Usage: '-' '.-' '. -' do the same\n");
2015-09-14 10:35:38 +00:00
return false;
}
return r_core_run_script (core, "-");
}
static int cmd_interpret(void *data, const char *input) {
2013-08-13 00:28:17 +00:00
char *str, *ptr, *eol, *rbuf, *filter, *inp;
const char *host, *port, *cmd;
RCore *core = (RCore *)data;
2013-08-13 00:28:17 +00:00
switch (*input) {
case '\0':
r_core_cmd_repeat (core, 0);
break;
case ':':
if ((ptr = strchr (input+1, ' '))) {
/* .:port cmd */
/* .:host:port cmd */
cmd = ptr+1;
*ptr = 0;
eol = strchr (input + 1, ':');
if (eol) {
*eol = 0;
host = input+1;
port = eol+1;
} else {
host = "localhost";
port = input + ((input[1] == ':')? 2: 1);
}
rbuf = r_core_rtr_cmds_query (core, host, port, cmd);
if (rbuf) {
r_cons_print (rbuf);
free (rbuf);
}
} else {
r_core_rtr_cmds (core, input + 1);
}
break;
case '.': // same as \n
r_core_cmd_repeat (core, 1);
break;
case '-':
if (input[1]=='?') {
r_cons_printf ("Usage: '-' '.-' '. -' do the same\n");
} else r_core_run_script (core, "-");
break;
case ' ':
if (!r_core_run_script (core, input+1)) {
eprintf ("Cannot find script '%s'\n", input+1);
core->num->value = 1;
} else {
core->num->value = 0;
}
break;
case '!':
/* from command */
2016-04-27 20:30:29 +00:00
r_core_cmd_command (core, input + 1);
break;
case '(':
2016-04-27 20:30:29 +00:00
r_cmd_macro_call (&core->rcmd->macro, input + 1);
break;
2014-06-20 11:25:17 +00:00
case '?':{
const char* help_msg[] = {
2014-08-19 09:22:30 +00:00
"Usage:", ".[r2cmd] | [file] | [!command] | [(macro)]", " # define macro or load r2, cparse or rlang file",
2014-06-20 11:25:17 +00:00
".", "", "repeat last command backward",
2014-08-19 09:22:30 +00:00
".", "r2cmd", "interpret the output of the command as r2 commands",
2014-06-20 11:25:17 +00:00
"..", "", "repeat last command forward (same as \\n)",
".:", "8080", "listen for commands on given tcp port",
".", " foo.r2", "interpret r2 script",
".-", "", "open cfg.editor and interpret tmp file",
".!", "rabin -ri $FILE", "interpret output of command",
".", "(foo 1 2 3)", "run macro 'foo' with args 1, 2, 3",
"./", " ELF", "interpret output of command /m ELF as r. commands",
NULL};
r_core_cmd_help (core, help_msg);
}
break;
#if 1
case '0'...'9':
eprintf ("|ERROR| No .[0..9] to avoid infinite loops\n");
break;
#endif
default:
2013-08-13 00:28:17 +00:00
inp = strdup (input);
filter = strchr (inp, '~');
if (filter) *filter = 0;
ptr = str = r_core_cmd_str (core, inp);
if (filter) *filter = '~';
r_cons_break (NULL, NULL);
if (ptr)
for (;;) {
if (r_cons_singleton()->breaked) break;
eol = strchr (ptr, '\n');
if (eol) *eol = '\0';
2013-08-13 00:28:17 +00:00
if (*ptr) {
char *p = r_str_concat (strdup (ptr), filter);
r_core_cmd0 (core, p);
free (p);
}
if (!eol) break;
ptr = eol+1;
}
r_cons_break_end ();
free (str);
2013-08-13 00:28:17 +00:00
free (inp);
break;
}
return 0;
}
static int callback_foreach_kv (void *user, const char *k, const char *v) {
r_cons_printf ("%s=%s\n", k, v);
return 1;
}
static int cmd_kuery(void *data, const char *input) {
char buf[1024], *out;
RCore *core = (RCore*)data;
const char *sp, *p = "[sdb]> ";
const int buflen = sizeof (buf)-1;
Sdb *s = core->sdb;
switch (input[0]) {
case ' ':
out = sdb_querys (s, NULL, 0, input+1);
if (out) {
r_cons_println (out);
}
free (out);
break;
//case 's': r_pair_save (s, input+3); break;
//case 'l': r_pair_load (sdb, input+3); break;
case '\0':
sdb_foreach (s, callback_foreach_kv, NULL);
break;
// TODO: add command to list all namespaces // sdb_ns_foreach ?
case 's':
if (core->http_up) {
2015-09-14 10:35:38 +00:00
return false;
}
if (!r_config_get_i (core->config, "scr.interactive")) {
2015-09-14 10:35:38 +00:00
return false;
}
if (input[1]==' ') {
char *n, *o, *p = strdup (input+2);
// TODO: slash split here? or inside sdb_ns ?
for (n = o = p; n; o = n) {
n = strchr (o, '/'); // SDB_NS_SEPARATOR NAMESPACE
if (n) *n++ = 0;
2014-06-05 22:06:30 +00:00
s = sdb_ns (s, o, 1);
}
free (p);
}
if (!s) s = core->sdb;
for (;;) {
r_line_set_prompt (p);
if (r_cons_fgets (buf, buflen, 0, NULL)<1)
break;
if (!*buf) break;
out = sdb_querys (s, NULL, 0, buf);
if (out) {
r_cons_println (out);
}
}
break;
case 'o':
2014-12-21 03:33:15 +00:00
if (r_sandbox_enable (0)) {
eprintf ("This command is disabled in sandbox mode\n");
return 0;
}
if (input[1] == ' ') {
2016-05-24 20:22:15 +00:00
char *fn = strdup (input + 2);
if (!fn) {
eprintf("Unable to allocate memory\n");
return 0;
}
char *ns = strchr (fn, ' ');
if (ns) {
Sdb *db;
*ns++ = 0;
2014-12-21 03:33:15 +00:00
if (r_file_exists (fn)) {
db = sdb_ns_path (core->sdb, ns, 1);
if (db) {
Sdb *newdb = sdb_new (NULL, fn, 0);
if (newdb) {
sdb_drain (db, newdb);
} else {
eprintf ("Cannot open sdb '%s'\n", fn);
}
} else eprintf ("Cannot find sdb '%s'\n", ns);
} else eprintf ("Cannot open file\n");
} else eprintf ("Missing sdb namespace\n");
free (fn);
} else {
2016-08-24 14:30:23 +00:00
eprintf ("Usage: ko [file] [namespace]\n");
}
break;
case 'd':
2014-12-21 03:33:15 +00:00
if (r_sandbox_enable (0)) {
eprintf ("This command is disabled in sandbox mode\n");
return 0;
}
if (input[1] == ' ') {
char *fn = strdup (input+2);
char *ns = strchr (fn, ' ');
if (ns) {
*ns++ = 0;
Sdb *db = sdb_ns_path (core->sdb, ns, 0);
if (db) {
sdb_file (db, fn);
sdb_sync (db);
} else eprintf ("Cannot find sdb '%s'\n", ns);
} else eprintf ("Missing sdb namespace\n");
free (fn);
} else {
2016-08-24 14:30:23 +00:00
eprintf ("Usage: kd [file] [namespace]\n");
}
break;
case '?': {
2014-06-20 16:35:49 +00:00
const char* help_msg[] = {
"Usage:", "k[s] [key[=value]]", "Sdb Query",
"k", " foo=bar", "set value",
"k", " foo", "show value",
"k", "", "list keys",
"ko", " [file.sdb] [ns]", "open file into namespace",
"kd", " [file.sdb] [ns]", "dump namespace to disk",
2014-06-20 16:35:49 +00:00
"ks", " [ns]", "enter the sdb query shell",
"k", " anal/meta/*", "ist kv from anal > meta namespaces",
"k", " anal/**", "list namespaces under anal",
"k", " anal/meta/meta.0x80404", "get value for meta.0x80404 key",
//"kl", " ha.sdb", "load keyvalue from ha.sdb",
//"ks", " ha.sdb", "save keyvalue to ha.sdb",
NULL,
};
r_core_cmd_help (core, help_msg);
}
break;
}
if (input[0] == '\0') {
/* nothing more to do, the command has been parsed. */
return 0;
}
sp = strchr (input + 1, ' ');
if (sp) {
char *inp = strdup (input);
inp [(size_t)(sp-input)] = 0;
2014-06-05 22:06:30 +00:00
s = sdb_ns (core->sdb, inp+1, 1);
out = sdb_querys (s, NULL, 0, sp+1);
2014-04-29 22:15:36 +00:00
if (out) {
r_cons_println (out);
2014-04-29 22:15:36 +00:00
free (out);
}
free (inp);
return 0;
}
return 0;
}
2012-02-27 01:40:27 +00:00
static int cmd_bsize(void *data, const char *input) {
ut64 n;
2012-02-27 01:40:27 +00:00
RFlagItem *flag;
RCore *core = (RCore *)data;
2012-02-27 01:40:27 +00:00
switch (input[0]) {
case 'm':
n = r_num_math (core->num, input+1);
if (n>1) core->blocksize_max = n;
else r_cons_printf ("0x%x\n", (ut32)core->blocksize_max);
break;
case '+':
n = r_num_math (core->num, input+1);
r_core_block_size (core, core->blocksize+n);
break;
case '-':
n = r_num_math (core->num, input+1);
r_core_block_size (core, core->blocksize-n);
break;
2012-02-27 01:40:27 +00:00
case 'f':
if (input[1]==' ') {
flag = r_flag_get (core->flags, input+2);
if (flag) {
2012-02-27 01:40:27 +00:00
r_core_block_size (core, flag->size);
} else {
eprintf ("bf: cannot find flag named '%s'\n", input+2);
}
} else {
eprintf ("Usage: bf [flagname]\n");
}
break;
2012-02-27 01:40:27 +00:00
case '\0':
r_cons_printf ("0x%x\n", core->blocksize);
break;
2014-06-19 18:59:07 +00:00
case '?':{
const char* help_msg[] = {
"Usage:", "b[f] [arg]\n", "Get/Set block size",
"b", "", "display current block size",
"b", " 33", "set block size to 33",
"b", "+3", "increase blocksize by 3",
2014-09-27 08:40:38 +00:00
"b", "-16", "decrease blocksize by 16",
2014-06-19 18:59:07 +00:00
"b", " eip+4", "numeric argument can be an expression",
"bf", " foo", "set block size to flag size",
"bm", " 1M", "set max block size",
NULL
};
r_core_cmd_help (core, help_msg);
}
break;
2012-02-27 01:40:27 +00:00
default:
//input = r_str_clean(input);
r_core_block_size (core, r_num_math (core->num, input));
break;
2012-02-27 01:40:27 +00:00
}
return 0;
}
2012-02-27 01:40:27 +00:00
static int cmd_resize(void *data, const char *input) {
RCore *core = (RCore *)data;
ut64 oldsize, newsize=0;
2012-02-27 01:40:27 +00:00
st64 delta = 0;
int grow, ret;
2014-10-30 23:00:43 +00:00
if (core->file && core->file->desc)
oldsize = r_io_desc_size (core->io, core->file->desc);
else oldsize = 0;
switch (*input) {
2015-10-30 00:45:49 +00:00
case '2':
// TODO: use argv[0] instead of 'radare2'
r_sys_cmdf ("radare%s", input);
return true;
2014-05-19 00:52:51 +00:00
case 'm':
if (input[1]==' ')
r_file_rm (input+2);
else eprintf ("Usage: rm [file] # removes a file\n");
2015-09-14 10:35:38 +00:00
return true;
2014-05-19 00:52:51 +00:00
case '\0':
if (core->file && core->file->desc) {
if (oldsize != -1) {
r_cons_printf ("%"PFMT64d"\n", oldsize);
}
}
2015-09-14 10:35:38 +00:00
return true;
2014-05-19 00:52:51 +00:00
case '+':
case '-':
delta = (st64)r_num_math (core->num, input);
newsize = oldsize + delta;
break;
case ' ':
newsize = r_num_math (core->num, input+1);
if (newsize==0) {
if (input[1]=='0')
eprintf ("Invalid size\n");
2015-09-14 10:35:38 +00:00
return false;
2014-05-19 00:52:51 +00:00
}
break;
default:
2014-06-20 16:35:49 +00:00
case '?':{
const char* help_msg[] = {
"Usage:", "r[+-][ size]", "Resize file",
"r", "", "display file size",
"r", " size", "expand or truncate file to given size",
"r-", "num", "remove num bytes, move following data down",
"r+", "num", "insert num bytes, move following data up",
"rm" ," [file]", "remove file",
2015-10-30 00:45:49 +00:00
"r2" ," [file]", "launch r2",
2014-06-20 16:35:49 +00:00
NULL};
r_core_cmd_help (core, help_msg);
}
2015-09-14 10:35:38 +00:00
return true;
}
2012-02-27 01:40:27 +00:00
grow = (newsize > oldsize);
if (grow) {
ret = r_io_resize (core->io, newsize);
2014-09-27 22:05:20 +00:00
if (ret<1)
eprintf ("r_io_resize: cannot resize\n");
}
2012-02-27 01:40:27 +00:00
if (delta && core->offset < newsize)
r_io_shift (core->io, core->offset, grow?newsize:oldsize, delta);
2012-02-27 01:40:27 +00:00
if (!grow) {
ret = r_io_resize (core->io, newsize);
2014-09-27 22:05:20 +00:00
if (ret<1)
eprintf ("r_io_resize: cannot resize\n");
}
2012-02-27 01:40:27 +00:00
if (newsize < core->offset+core->blocksize ||
oldsize < core->offset+core->blocksize) {
r_core_block_read (core);
}
2015-09-14 10:35:38 +00:00
return true;
}
2012-02-27 01:40:27 +00:00
static int cmd_visual(void *data, const char *input) {
RCore *core = (RCore*) data;
2016-10-17 12:38:43 +00:00
if (core->http_up) {
2015-09-14 10:35:38 +00:00
return false;
2016-10-17 12:38:43 +00:00
}
if (!r_config_get_i (core->config, "scr.interactive")) {
2015-09-14 10:35:38 +00:00
return false;
2016-10-17 12:38:43 +00:00
}
return r_core_visual ((RCore *)data, input);
}
static int task_finished(void *user, void *data) {
eprintf ("TASK FINISHED\n");
return 0;
}
static int taskbgrun(RThread *th) {
2016-01-03 01:32:56 +00:00
char *res;
RCoreTask *task = th->user;
RCore *core = task->core;
2016-01-03 01:32:56 +00:00
close (2); // no stderr
res = r_core_cmd_str (core, task->msg->text);
task->msg->res = res;
2016-01-03 01:32:56 +00:00
task->state = 'd';
eprintf ("Task %d finished\n", task->id);
// TODO: run callback and pass result
return 0;
}
static int cmd_thread(void *data, const char *input) {
RCore *core = (RCore*) data;
if (r_sandbox_enable (0)) {
eprintf ("This command is disabled in sandbox mode\n");
return 0;
}
switch (input[0]) {
case '\0':
2014-11-01 04:18:37 +00:00
case 'j':
r_core_task_list (core, *input);
break;
case '&':
if (input[1]=='&') {
// wait until ^C
} else {
int tid = r_num_math (core->num, input+1);
if (tid) {
RCoreTask *task = r_core_task_get (core, tid);
if (task) {
r_core_task_join (core, task);
} else eprintf ("Cannot find task\n");
} else {
r_core_task_run (core, NULL);
}
}
break;
case '=': {
int tid = r_num_math (core->num, input+1);
if (tid) {
RCoreTask *task = r_core_task_get (core, tid);
if (task) {
r_cons_printf ("Task %d Status %c Command %s\n",
task->id, task->state, task->msg->text);
if (task->msg->res)
r_cons_println (task->msg->res);
} else eprintf ("Cannot find task\n");
} else {
r_core_task_list (core, 1);
}}
break;
case '+':
r_core_task_add (core, r_core_task_new (core, input+1, (RCoreTaskCallback)task_finished, core));
break;
case '-':
if (input[1]=='*') {
r_core_task_del (core, -1);
} else {
r_core_task_del (core, r_num_math (core->num, input+1));
}
break;
case '?':
{
const char* help_msg[] = {
"Usage:", "&[-|<cmd>]", "Manage tasks",
"&", "", "list all running threads",
"&=", "", "show output of all tasks",
"&=", " 3", "show output of task 3",
2014-11-01 04:18:37 +00:00
"&j", "", "list all running threads (in JSON)",
"&?", "", "show this help",
"&+", " aa", "push to the task list",
"&-", " 1", "delete task #1",
"&", "-*", "delete all threads",
2014-11-01 04:18:37 +00:00
"&", " aa", "run analysis in background",
"&", " &&", "run all tasks in background",
"&&", "", "run all pendings tasks (and join threads)",
"&&&", "", "run all pendings tasks until ^C",
2015-10-29 19:02:13 +00:00
"","","TODO: last command should honor asm.bits",
"","","WARN: this feature is very experimental. Use it with caution",
NULL};
2014-11-01 04:18:37 +00:00
// TODO: integrate with =h& and bg anal/string/searchs/..
r_core_cmd_help (core, help_msg);
}
break;
case ' ':
{
int tid = r_num_math (core->num, input+1);
if (tid) {
RCoreTask *task = r_core_task_get (core, tid);
if (task) {
r_core_task_join (core, task);
} else eprintf ("Cannot find task\n");
} else {
RCoreTask *task = r_core_task_add (core, r_core_task_new (
core, input+1, (RCoreTaskCallback)task_finished, core));
RThread *th = r_th_new (taskbgrun, task, 0);
task->msg->th = th;
}
//r_core_cmd0 (core, task->msg->text);
//r_core_task_del (core, task->id);
}
break;
default:
eprintf ("&?\n");
break;
}
return 0;
2012-02-27 01:40:27 +00:00
}
static int cmd_pointer(void *data, const char *input) {
2014-06-20 16:35:49 +00:00
RCore *core = (RCore*) data;
2015-09-14 10:35:38 +00:00
int ret = true;
char *str, *eq;
while (*input==' ') input++;
if (!*input || *input=='?') {
2014-06-20 16:35:49 +00:00
const char* help_msg[] = {
"Usage:", "*<addr>[=[0x]value]", "Pointer read/write data/values",
"*", "entry0=cc", "write trap in entrypoint",
"*", "entry0+10=0x804800", "write value in delta address",
"*", "entry0", "read byte at given address",
"TODO: last command should honor asm.bits", "", "",
NULL};
r_core_cmd_help (core, help_msg);
return ret;
}
str = strdup (input);
eq = strchr (str, '=');
if (eq) {
*eq++ = 0;
if (!strncmp (eq, "0x", 2)) {
2014-06-20 16:35:49 +00:00
ret = r_core_cmdf (core, "wv %s@%s", eq, str);
} else {
2014-06-20 16:35:49 +00:00
ret = r_core_cmdf (core, "wx %s@%s", eq, str);
}
} else {
2014-06-20 16:35:49 +00:00
ret = r_core_cmdf (core, "?v [%s]", input);
}
free (str);
return ret;
}
static int cmd_env(void *data, const char *input) {
return r_core_cmdf ((RCore*)data, "env %s", input);
}
2012-02-27 01:40:27 +00:00
static int cmd_system(void *data, const char *input) {
RCore *core = (RCore*)data;
ut64 n;
2012-02-27 01:40:27 +00:00
int ret = 0;
switch (*input) {
case '=':
if (input[1] == '?') {
r_cons_printf ("Usage: !=[!] - enable/disable remote commands\n");
} else {
if (!r_sandbox_enable (0)) {
core->cmdremote = input[1]? 1: 0;
r_cons_println (r_str_bool (core->cmdremote));
}
}
break;
2014-04-27 23:27:45 +00:00
case '!':
if (r_sandbox_enable (0)) {
eprintf ("This command is disabled in sandbox mode\n");
return 0;
}
if (input[1]) {
int olen;
char *out = NULL;
char *cmd = r_core_sysenv_begin (core, input);
if (cmd) {
ret = r_sys_cmd_str_full (cmd+1, NULL, &out, &olen, NULL);
r_core_sysenv_end (core, input);
r_cons_memcat (out, olen);
free (out);
free (cmd);
} //else eprintf ("Error setting up system environment\n");
} else {
eprintf ("History saved to "R2_HOMEDIR"/history\n");
r_line_hist_save (R2_HOMEDIR"/history");
}
break;
case '\0':
r_line_hist_list ();
break;
case '?':
2014-06-20 11:25:17 +00:00
r_core_sysenv_help (core);
break;
default:
2013-12-17 22:45:03 +00:00
n = atoi (input);
if (*input=='0' || n > 0) {
2013-04-02 10:45:16 +00:00
const char *cmd = r_line_hist_get (n);
if (cmd) r_core_cmd0 (core, cmd);
2013-09-30 00:19:19 +00:00
//else eprintf ("Error setting up system environment\n");
} else {
char *cmd = r_core_sysenv_begin (core, input);
if (cmd) {
ret = r_sys_cmd (cmd);
r_core_sysenv_end (core, input);
free (cmd);
} else eprintf ("Error setting up system environment\n");
}
break;
}
2012-02-27 01:40:27 +00:00
return ret;
}
R_API int r_core_cmd_pipe(RCore *core, char *radare_cmd, char *shell_cmd) {
char *_ptr;
2015-08-04 12:17:09 +00:00
#if __UNIX__ || __CYGWIN__
int stdout_fd, fds[2];
int child;
#endif
int si, olen, ret = -1, pipecolor = -1;
char *str, *out = NULL;
if (r_sandbox_enable (0)) {
eprintf ("Pipes are not allowed in sandbox mode\n");
return -1;
}
si = r_config_get_i (core->config, "scr.interactive");
r_config_set_i (core->config, "scr.interactive", 0);
if (!r_config_get_i (core->config, "scr.pipecolor")) {
pipecolor = r_config_get_i (core->config, "scr.color");
r_config_set_i (core->config, "scr.color", 0);
}
if (*shell_cmd=='!') {
_ptr = (char *)r_str_lastbut (shell_cmd, '~', "\"");
if (_ptr) {
*_ptr = '\0';
_ptr++;
}
olen = 0;
out = NULL;
// TODO: implement foo
str = r_core_cmd_str (core, radare_cmd);
r_sys_cmd_str_full (shell_cmd+1, str, &out, &olen, NULL);
2014-04-30 19:02:22 +00:00
free (str);
r_cons_memcat (out, olen);
if (_ptr)
r_cons_grep (_ptr);
free (out);
ret = 0;
}
2015-08-04 12:17:09 +00:00
#if __UNIX__ || __CYGWIN__
radare_cmd = (char*)r_str_trim_head (radare_cmd);
shell_cmd = (char*)r_str_trim_head (shell_cmd);
signal (SIGPIPE, SIG_IGN);
stdout_fd = dup (1);
2014-01-18 22:02:53 +00:00
if (stdout_fd != -1) {
pipe (fds);
2015-04-11 03:00:05 +00:00
child = r_sys_fork ();
if (child == -1) {
eprintf ("Cannot fork\n");
2015-10-29 19:02:13 +00:00
close (stdout_fd);
2015-04-11 03:00:05 +00:00
} else if (child) {
2014-01-18 22:02:53 +00:00
dup2 (fds[1], 1);
close (fds[1]);
close (fds[0]);
r_core_cmd (core, radare_cmd, 0);
r_cons_flush ();
close (1);
wait (&ret);
dup2 (stdout_fd, 1);
close (stdout_fd);
} else {
close (fds[1]);
dup2 (fds[0], 0);
//dup2 (1, 2); // stderr goes to stdout
r_sandbox_system (shell_cmd, 0);
close (stdout_fd);
}
}
#else
#warning r_core_cmd_pipe UNIMPLEMENTED FOR THIS PLATFORM
eprintf ("r_core_cmd_pipe: unimplemented for this platform\n");
#endif
if (pipecolor != -1)
r_config_set_i (core->config, "scr.color", pipecolor);
r_config_set_i (core->config, "scr.interactive", si);
return ret;
}
2015-07-15 00:02:11 +00:00
static char *parse_tmp_evals(RCore *core, const char *str) {
char *res = NULL;
RStrBuf *buf;
char *s = strdup (str);
buf = r_strbuf_new ("");
int i, argc = r_str_split (s, ',');
for (i = 0; i < argc; i++) {
2015-07-15 00:02:11 +00:00
char *eq, *kv = (char *)r_str_word_get0 (s, i);
if (!kv) break;
eq = strchr (kv, '=');
if (eq) {
*eq = 0;
const char *ov = r_config_get (core->config, kv);
r_strbuf_appendf (buf, "e %s=%s;", kv, ov);
r_config_set (core->config, kv, eq+1);
*eq = '=';
} else {
eprintf ("Missing '=' in e: expression (%s)\n", kv);
}
}
res = strdup (r_strbuf_get (buf));
r_strbuf_free (buf);
free (s);
return res;
}
static int r_core_cmd_subst_i(RCore *core, char *cmd, char* colon);
static int r_core_cmd_subst(RCore *core, char *cmd) {
int ret = 0, rep = atoi (cmd), orep;
char *cmt, *colon = NULL, *icmd = strdup (cmd);
const char *cmdrep = NULL;
cmd = r_str_trim_head_tail (icmd);
2014-01-18 22:02:53 +00:00
if (!icmd || !strncmp (cmd, "# ", 2))
goto beach;
cmt = *icmd ? strchr (icmd+1, '#'): NULL;
2014-10-17 08:20:08 +00:00
if (cmt && (cmt[1]==' ' || cmt[1]=='\t'))
*cmt = 0;
2013-02-25 01:35:16 +00:00
if (*cmd != '"') {
if (!strchr (cmd, '\'')) { // allow | awk '{foo;bar}' // ignore ; if there's a single quote
if ((colon = strchr (cmd, ';')))
*colon = 0;
}
} else {
colon = NULL;
}
if (rep > 0) {
while (*cmd >= '0' && *cmd <= '9') {
cmd++;
}
2014-01-18 22:02:53 +00:00
// do not repeat null cmd
if (!*cmd) {
goto beach;
}
2014-04-27 23:27:45 +00:00
}
if (rep<1) rep = 1;
// XXX if output is a pipe then we dont want to be interactive
if (rep > 1 && r_sandbox_enable (0)) {
eprintf ("Command repeat sugar disabled in sandbox mode (%s)\n", cmd);
goto beach;
} else {
if (rep > INTERACTIVE_MAX_REP) {
if (r_config_get_i (core->config, "scr.interactive")) {
if (!r_cons_yesno ('n', "Are you sure to repeat this %d times? (y/N)", rep))
goto beach;
}
}
}
// TODO: store in core->cmdtimes to speedup ?
cmdrep = r_config_get (core->config, "cmd.times");
orep = rep;
int ocur_enabled = core->print->cur_enabled;
while (rep-- && *cmd) {
core->print->cur_enabled = false;
if (ocur_enabled && core->seltab >= 0) {
if (core->seltab == core->curtab) {
core->print->cur_enabled = true;
}
}
char *cr = strdup (cmdrep);
core->break_loop = false;
ret = r_core_cmd_subst_i (core, cmd, colon);
if (ret && *cmd == 'q') {
free (cr);
2014-01-18 22:02:53 +00:00
goto beach;
}
if (core->break_loop) {
break;
}
if (cr && *cr) {
if (orep > 1) {
// XXX: do not flush here, we need r_cons_push () and r_cons_pop()
r_cons_flush ();
// XXX: we must inport register flags in C
(void)r_core_cmd0 (core, ".dr*");
(void)r_core_cmd0 (core, cr);
}
}
free (cr);
}
core->print->cur_enabled = ocur_enabled;
if (colon && colon[1]) {
for (++colon; *colon==';'; colon++);
r_core_cmd_subst (core, colon);
} else {
if (!*icmd) {
r_core_cmd_nullcallback (core);
}
}
2014-01-18 22:02:53 +00:00
beach:
free (icmd);
2014-01-18 22:02:53 +00:00
return ret;
}
static char *find_eoq (char *p) {
for (; *p; p++) {
if (*p=='"') break;
if (*p=='\\' && p[1]=='"')
p++;
}
return p;
}
static int r_core_cmd_subst_i(RCore *core, char *cmd, char *colon) {
const char *quotestr = "`";
const char *tick = NULL;
char *ptr, *ptr2, *str;
char *arroba = NULL;
2014-02-02 23:19:55 +00:00
int i, ret = 0, pipefd;
int usemyblock = 0;
2014-01-18 22:02:53 +00:00
if (!cmd) return 0;
cmd = r_str_trim_head_tail (cmd);
/* quoted / raw command */
switch (*cmd) {
case '.':
if (cmd[1] == '"') /* interpret */
return r_cmd_call (core->rcmd, cmd);
break;
case '"':
for (cmd++; *cmd; ) {
2013-12-03 00:02:08 +00:00
int pipefd = -1;
ut64 oseek = UT64_MAX;
char *line, *p = find_eoq (cmd);
2013-12-03 03:20:45 +00:00
if (!p || !*p) {
eprintf ("Missing \" in (%s).", cmd);
2015-09-14 10:35:38 +00:00
return false;
}
2013-12-03 03:20:45 +00:00
*p = 0;
// SKIPSPACES in p+1
while (IS_WHITESPACE (p[1])) p++;
if (p[1]=='@' || (p[1] && p[2]=='@')) {
char *q = strchr (p+1, '"');
if (q) *q = 0;
oseek = core->offset;
r_core_seek (core, r_num_math (
core->num, p+2), 1);
if (q) {
*p = '"';
p = q;
} else p = NULL;
}
if (p && *p && p[1]=='>') {
str = p + 2;
while (*str=='>') {
str++;
}
while (IS_WHITESPACE (*str)) {
str++;
}
2013-12-03 03:20:45 +00:00
r_cons_flush ();
pipefd = r_cons_pipe_open (str, 1, p[2]=='>');
}
line = strdup (cmd);
2015-09-14 10:35:38 +00:00
line = r_str_replace (line, "\\\"", "\"", true);
2013-12-03 03:20:45 +00:00
if (p && p[1]=='|') {
str = p+2;
2014-01-18 22:02:53 +00:00
while (IS_WHITESPACE (*str)) str++;
2013-12-03 03:20:45 +00:00
r_core_cmd_pipe (core, cmd, str);
} else {
r_cmd_call (core->rcmd, line);
}
free (line);
if (oseek != UT64_MAX) {
r_core_seek (core, oseek, 1);
oseek = UT64_MAX;
}
if (pipefd != -1) {
r_cons_flush ();
r_cons_pipe_close (pipefd);
}
if (!p) break;
*p = '"';
cmd = p + 1;
}
2015-09-14 10:35:38 +00:00
return true;
case '(':
if (cmd[1] != '*')
return r_cmd_call (core->rcmd, cmd);
}
// TODO must honor " and `
/* comments */
if (*cmd != '#') {
ptr = (char *)r_str_lastbut (cmd, '#', quotestr);
2014-10-17 08:20:08 +00:00
if (ptr && (ptr[1]==' '||ptr[1]=='\t')) *ptr = '\0';
}
/* multiple commands */
// TODO: must honor " and ` boundaries
//ptr = strrchr (cmd, ';');
if (*cmd != '#') {
ptr = (char *)r_str_lastbut (cmd, ';', quotestr);
if (colon && ptr) {
int ret ;
*ptr = '\0';
if (r_core_cmd_subst (core, cmd) == -1)
return -1;
cmd = ptr+1;
ret = r_core_cmd_subst (core, cmd);
*ptr = ';';
return ret;
//r_cons_flush ();
}
}
2013-02-25 01:35:16 +00:00
// TODO must honor " and `
/* pipe console to shell process */
//ptr = strchr (cmd, '|');
ptr = (char *)r_str_lastbut (cmd, '|', quotestr);
if (ptr) {
char *ptr2 = strchr (cmd, '`');
if (!ptr2 || (ptr2 && ptr2>ptr)) {
if (!tick || (tick && tick > ptr)) {
*ptr = '\0';
cmd = r_str_clean (cmd);
int value = core->num->value;
if (*cmd) r_core_cmd_pipe (core, cmd, ptr+1);
else r_io_system (core->io, ptr+1);
core->num->value = value;
return 0;
}
}
}
2013-02-25 01:35:16 +00:00
// TODO must honor " and `
/* bool conditions */
ptr = (char *)r_str_lastbut (cmd, '&', quotestr);
//ptr = strchr (cmd, '&');
while (ptr && ptr[1]=='&') {
*ptr = '\0';
ret = r_cmd_call (core->rcmd, cmd);
if (ret == -1) {
eprintf ("command error(%s)\n", cmd);
return ret;
}
for (cmd=ptr+2; cmd && *cmd==' '; cmd++);
ptr = strchr (cmd, '&');
}
/* Out Of Band Input */
free (core->oobi);
core->oobi = NULL;
2016-10-15 23:46:03 +00:00
ptr = strstr (cmd, "?*");
2016-10-17 12:38:43 +00:00
if (ptr && !ptr[2] && ptr > cmd) {
char *prech = ptr - 1;
if (*prech != '~') {
ptr[1] = 0;
if (*cmd != '#' && strlen (cmd) < 5) {
recursive_help (core, cmd);
return 0;
}
}
}
ptr = strchr (cmd, '<');
if (ptr) {
ptr[0] = '\0';
if (r_cons_singleton()->is_interactive) {
if (ptr[1]=='<') {
/* this is a bit mess */
//const char *oprompt = strdup (r_line_singleton ()->prompt);
//oprompt = ">";
for (str=ptr+2; str[0]==' '; str++);
eprintf ("==> Reading from stdin until '%s'\n", str);
free (core->oobi);
core->oobi = malloc (1);
if (core->oobi)
core->oobi[0] = '\0';
core->oobi_len = 0;
for (;;) {
char buf[1024];
int ret;
write (1, "> ", 2);
fgets (buf, sizeof (buf)-1, stdin); // XXX use r_line ??
if (feof (stdin))
break;
if (*buf) buf[strlen (buf)-1]='\0';
ret = strlen (buf);
core->oobi_len += ret;
core->oobi = realloc (core->oobi, core->oobi_len+1);
if (core->oobi) {
if (!strcmp (buf, str))
break;
strcat ((char *)core->oobi, buf);
}
}
//r_line_set_prompt (oprompt);
} else {
for (str=ptr+1; *str== ' '; str++);
if (!*str) goto next;
eprintf ("Slurping file '%s'\n", str);
free (core->oobi);
core->oobi = (ut8*)r_file_slurp (str, &core->oobi_len);
if (!core->oobi)
eprintf ("cannot open file\n");
else if (ptr == cmd)
return r_core_cmd_buffer (core, (const char *)core->oobi);
}
} else {
eprintf ("Cannot slurp with << in non-interactive mode\n");
return 0;
}
}
next:
// TODO must honor " and `
/* pipe console to file */
ptr = strchr (cmd, '>');
if (ptr) {
int fdn = 1;
int pipecolor = r_config_get_i (core->config, "scr.pipecolor");
2015-09-14 10:35:38 +00:00
int use_editor = false;
int ocolor = r_config_get_i (core->config, "scr.color");
*ptr = '\0';
str = r_str_trim_head_tail (ptr + 1 + (ptr[1] == '>'));
if (!*str) goto next2;
/* r_cons_flush() handles interactive output (to the terminal)
* differently (e.g. asking about too long output). This conflicts
* with piping to a file. Disable it while piping. */
if (ptr > cmd) {
char *fdnum = ptr-1;
if (*fdnum >= '0' && *fdnum <= '9') {
fdn = *fdnum - '0';
}
*fdnum = 0;
}
2015-09-14 10:35:38 +00:00
r_cons_set_interactive (false);
if (!strcmp (str, "-")) {
2015-09-14 10:35:38 +00:00
use_editor = true;
str = r_file_temp ("dumpedit");
r_config_set (core->config, "scr.color", "false");
}
if (fdn > 0) {
pipefd = r_cons_pipe_open (str, fdn, ptr[1] == '>');
if (pipefd != -1) {
if (!pipecolor) {
r_config_set_i (core->config, "scr.color", 0);
}
ret = r_core_cmd_subst (core, cmd);
r_cons_flush ();
r_cons_pipe_close (pipefd);
}
}
r_cons_set_last_interactive ();
if (!pipecolor) {
r_config_set_i (core->config, "scr.color", ocolor);
}
if (use_editor) {
const char *editor = r_config_get (core->config, "cfg.editor");
2015-03-31 00:26:36 +00:00
if (editor && *editor) {
r_sys_cmdf ("%s '%s'", editor, str);
2015-03-31 00:26:36 +00:00
r_file_rm (str);
} else {
eprintf ("No cfg.editor configured\n");
}
r_config_set_i (core->config, "scr.color", ocolor);
free (str);
}
return ret;
}
next2:
/* sub commands */
ptr = strchr (cmd, '`');
if (ptr) {
2013-12-21 23:45:50 +00:00
int empty = 0;
int oneline = 1;
if (ptr[1]=='`') {
memmove (ptr, ptr + 1, strlen (ptr));
oneline = 0;
2013-12-21 23:45:50 +00:00
empty = 1;
}
ptr2 = strchr (ptr+1, '`');
2013-12-21 23:45:50 +00:00
if (empty) {
/* do nothing */
} else if (!ptr2) {
eprintf ("parse: Missing backtick in expression.\n");
return -1;
} else {
int value = core->num->value;
*ptr = '\0';
*ptr2 = '\0';
if (ptr[1] == '!') {
str = r_core_cmd_str_pipe (core, ptr+1);
2014-01-09 00:09:40 +00:00
} else {
str = r_core_cmd_str (core, ptr+1);
2014-01-09 00:09:40 +00:00
}
if (!str)
return -1;
2014-02-22 02:36:45 +00:00
// ignore contents if first char is pipe or comment
if (*str=='|' || *str=='*') {
eprintf ("r_core_cmd_subst_i: invalid backticked command\n");
2014-02-22 02:36:45 +00:00
free (str);
return -1;
2014-02-22 02:36:45 +00:00
}
if (oneline && str) {
for (i = 0; str[i]; i++) {
if (str[i] == '\n') {
str[i] = ' ';
}
}
}
str = r_str_concat (str, ptr2+1);
cmd = r_str_concat (strdup (cmd), str);
core->num->value = value;
ret = r_core_cmd_subst (core, cmd);
free (cmd);
free (str);
return ret;
}
}
// TODO must honor " and `
2015-10-20 23:51:34 +00:00
core->fixedblock = false;
/* grep the content */
ptr = (char *)r_str_lastbut (cmd, '~', quotestr);
2015-04-07 11:21:52 +00:00
if (ptr && ptr>cmd) {
char *escape = ptr-1;
if (*escape == '\\') {
memmove (escape, ptr, strlen (escape));
ptr = NULL;
}
}
if (ptr && *cmd != '.') {
*ptr = '\0';
ptr++;
2015-04-07 11:21:52 +00:00
cmd = r_str_chop (cmd);
2013-06-24 21:06:32 +00:00
r_cons_grep (ptr);
}
/* temporary seek commands */
if (*cmd!='(' && *cmd!='"') {
ptr = strchr (cmd, '@');
if (ptr == cmd + 1 && *cmd=='?') {
ptr = NULL;
}
} else {
ptr = NULL;
}
2016-10-17 12:38:43 +00:00
2015-09-14 10:35:38 +00:00
core->tmpseek = ptr? true: false;
if (ptr) {
char *f, *ptr2 = strchr (ptr+1, '!');
ut64 addr = UT64_MAX;
const char *tmpbits = NULL;
2015-07-15 00:02:11 +00:00
const char *offstr = NULL;
ut64 tmpbsz = core->blocksize;
ut64 tmpoff = core->offset;
char *tmpeval = NULL;
char *tmpasm = NULL;
int tmpfd = -1;
int sz, len;
ut8 *buf;
*ptr = '\0';
for (ptr++; *ptr== ' '; ptr++);
2015-03-24 03:55:47 +00:00
if (*ptr && ptr[1]==':') {
/* do nothing here */
} else {
ptr--;
}
if (ptr[0] && ptr[1] && ptr[2]) {
arroba = strchr (ptr + 2, '@');
} else {
arroba = NULL;
}
repeat_arroba:
if (arroba) {
*arroba = 0;
}
2015-03-24 03:52:36 +00:00
if (ptr[0] && ptr[1]==':' && ptr[2]) {
usemyblock = 1;
2015-03-24 03:52:36 +00:00
switch (ptr[0]) {
2015-04-18 23:25:50 +00:00
case 'f': // "@f:" // slurp file in block
2015-03-24 03:52:36 +00:00
f = r_file_slurp (ptr+2, &sz);
if (f) {
buf = malloc (sz);
if (buf) {
free (core->block);
core->block = buf;
core->blocksize = sz;
memcpy (core->block, f, sz);
} else eprintf ("cannot alloc %d", sz);
free (f);
} else eprintf ("cannot open '%s'\n", ptr+3);
break;
case 'r': // "@r:" // regname
if (ptr[1]==':') {
ut64 regval = r_debug_reg_get (core->dbg, ptr+2);
r_core_seek (core, regval, 1);
} else {
eprintf ("Fin\n");
}
break;
2015-04-18 23:25:50 +00:00
case 'b': // "@b:" // bits
2015-10-23 15:11:04 +00:00
tmpbits = strdup (r_config_get (core->config, "asm.bits"));
2015-04-18 23:25:50 +00:00
r_config_set_i (core->config, "asm.bits",
r_num_math (core->num, ptr+2));
break;
case 'i': // "@i:"
2016-10-08 01:07:26 +00:00
{
ut64 addr = r_num_math (core->num, ptr + 2);
if (addr) {
r_core_cmdf (core, "so %s", ptr + 2);
}
}
// tmpseek = true;
break;
2015-07-15 00:02:11 +00:00
case 'e': // "@e:"
tmpeval = parse_tmp_evals (core, ptr+2);
break;
2015-04-18 23:25:50 +00:00
case 'x': // "@x:" // hexpairs
if (ptr[1]==':') {
buf = malloc (strlen (ptr+2)+1);
if (buf) {
len = r_hex_str2bin (ptr+2, buf);
r_core_block_size (core, R_ABS(len));
2015-04-18 23:25:50 +00:00
memcpy (core->block, buf, core->blocksize);
2015-10-20 23:51:34 +00:00
core->fixedblock = true;
2015-04-18 23:25:50 +00:00
free (buf);
} else eprintf ("cannot allocate\n");
} else eprintf ("Invalid @x: syntax\n");
break;
case 'k': // "@k"
2015-04-19 09:54:50 +00:00
{
char *out = sdb_querys (core->sdb, NULL, 0, ptr+((ptr[1])?2:1));
if (out) {
r_core_seek (core, r_num_math (core->num, out), 1);
free (out);
}
}
break;
case 'o': // "@o:3"
if (ptr[1] ==':') {
tmpfd = core->io->raised;
r_io_raise (core->io, atoi (ptr + 2));
}
break;
2015-04-09 22:17:47 +00:00
case 'a': // "@a:"
if (ptr[1]==':') {
char *q = strchr (ptr+2, ':');
tmpasm = strdup (r_config_get (core->config, "asm.arch"));
if (q) {
*q++ = 0;
tmpbits = r_config_get (core->config, "asm.bits");
r_config_set (core->config, "asm.bits", q);
}
r_config_set (core->config, "asm.arch", ptr+2);
// TODO: handle asm.bits
} else {
eprintf ("Usage: pd 10 @a:arm:32\n");
}
break;
2015-04-09 22:17:47 +00:00
case 's': // "@s:"
len = strlen (ptr+2);
r_core_block_size (core, len);
2015-03-24 03:52:36 +00:00
memcpy (core->block, ptr+2, len);
break;
default:
goto ignore;
}
*ptr = '@';
goto next_arroba; //ignore; //return ret;
}
ignore:
ptr = r_str_trim_head (ptr + 1);
ptr--;
cmd = r_str_clean (cmd);
if (ptr2) {
if (strlen (ptr+1)==13 && strlen (ptr2+1)==6 && \
!memcmp (ptr+1,"0x", 2) && !memcmp (ptr2+1, "0x", 2)) {
/* 0xXXXX:0xYYYY */
} else
if (strlen (ptr+1)==9 && strlen (ptr2+1)==4) {
/* XXXX:YYYY */
} else {
*ptr2 = '\0';
if (!ptr2[1]) return -1;
r_core_block_size (core, r_num_math (core->num, ptr2+1));
}
}
offstr = r_str_trim_head (ptr+1);
addr = r_num_math (core->num, offstr);
if (isalpha ((unsigned char)ptr[1]) && addr== 0) {
if (!r_flag_get (core->flags, ptr+1)) {
eprintf ("Invalid address (%s)\n", ptr+1);
2015-09-14 10:35:38 +00:00
return false;
}
} else {
char ch = *offstr;
if (ch=='-' || ch=='+') {
addr = core->offset + addr;
}
}
next_arroba:
if (arroba) {
ptr = arroba;
arroba = NULL;
goto repeat_arroba;
}
if (ptr[1]=='@') {
2009-03-21 02:17:43 +00:00
// TODO: remove temporally seek (should be done by cmd_foreach)
if (ptr[2] == '@') {
2016-05-24 22:44:41 +00:00
char *rule = ptr + 3;
while (*rule && *rule==' ') rule++;
ret = r_core_cmd_foreach3 (core, cmd, rule);
} else {
ret = r_core_cmd_foreach (core, cmd, ptr+2);
}
//ret = -1; /* do not run out-of-foreach cmd */
} else {
bool tmpseek = false;
const char *fromvars[] = { "anal.from", "diff.from", "graph.from",
"io.buffer.from", "lines.from", "search.from", "zoom.from", NULL };
const char *tovars[] = { "anal.to", "diff.to", "graph.to",
"io.buffer.to", "lines.to", "search.to", "zoom.to", NULL };
ut64 curfrom[R_ARRAY_SIZE (fromvars) - 1], curto[R_ARRAY_SIZE (tovars) - 1];
// @..
2016-05-24 23:24:52 +00:00
if (ptr[1] == '.' && ptr[2] == '.') {
char *range = ptr + 3;
char *p = strchr (range, ' ');
2016-05-24 22:44:41 +00:00
if (!p) {
eprintf ("Usage: / ABCD @..0x1000 0x3000\n");
2016-05-24 22:44:41 +00:00
free (tmpeval);
free (tmpasm);
return false;
}
*p = '\x00';
ut64 from = r_num_math (core->num, range);
ut64 to = r_num_math (core->num, p + 1);
// save current ranges
for (i = 0; fromvars[i]; i++) {
curfrom[i] = r_config_get_i (core->config, fromvars[i]);
}
for (i = 0; tovars[i]; i++) {
curto[i] = r_config_get_i (core->config, tovars[i]);
}
// set new ranges
for (i = 0; fromvars[i]; i++) {
r_config_set_i (core->config, fromvars[i], from);
}
for (i = 0; tovars[i]; i++) {
r_config_set_i (core->config, tovars[i], to);
}
tmpseek = true;
}
if (usemyblock) {
2015-07-15 00:02:11 +00:00
if (addr != UT64_MAX) {
core->offset = addr;
}
ret = r_cmd_call (core->rcmd, r_str_trim_head (cmd));
} else {
2016-05-24 22:44:41 +00:00
if (addr != UT64_MAX) {
if (!ptr[1] || r_core_seek (core, addr, 1)) {
r_core_block_read (core);
2016-05-24 22:44:41 +00:00
ret = r_cmd_call (core->rcmd, r_str_trim_head (cmd));
} else {
ret = 0;
}
}
}
if (tmpseek) {
// restore ranges
for (i = 0; fromvars[i]; i++) {
r_config_set_i (core->config, fromvars[i], curfrom[i]);
}
for (i = 0; tovars[i]; i++) {
r_config_set_i (core->config, tovars[i], curto[i]);
}
}
}
if (ptr2) {
*ptr2 = '!';
r_core_block_size (core, tmpbsz);
}
if (tmpasm) {
r_config_set (core->config, "asm.arch", tmpasm);
tmpasm = NULL;
}
if (tmpfd != -1) {
r_io_raise (core->io, tmpfd);
}
if (tmpbits) {
r_config_set (core->config, "asm.bits", tmpbits);
tmpbits = NULL;
}
2015-07-15 00:02:11 +00:00
if (tmpeval) {
r_core_cmd0 (core, tmpeval);
2016-05-24 22:44:41 +00:00
R_FREE (tmpeval);
2015-07-15 00:02:11 +00:00
}
r_core_seek (core, tmpoff, 1);
*ptr = '@';
return ret;
}
2015-10-20 23:57:56 +00:00
int rc = cmd? r_cmd_call (core->rcmd, r_str_trim_head (cmd)): false;
2015-10-20 23:51:34 +00:00
core->fixedblock = false;
return rc;
}
static int foreach_comment(void *user, const char *k, const char *v) {
RAnalMetaUserItem *ui = user;
RCore *core = ui->anal->user;
const char *cmd = ui->user;
if (!strncmp (k, "meta.C.", 7)) {
char *cmt = (char *)sdb_decode (v, 0);
if (!cmt) cmt = strdup ("");
//eprintf ("--> %s = %s\n", k+7, cmt);
r_core_cmdf (core, "s %s", k+7);
r_core_cmd0 (core, cmd);
free (cmt);
}
return 1;
}
R_API int r_core_cmd_foreach3(RCore *core, const char *cmd, char *each) {
RDebug *dbg = core->dbg;
RList *list, *head;
RListIter *iter;
int i;
switch (each[0]) {
case '?':
r_cons_printf ("Usage: @@@ [type] # types:\n");
r_cons_printf (" symbols\n");
r_cons_printf (" imports\n");
r_cons_printf (" regs\n");
r_cons_printf (" threads\n");
r_cons_printf (" comments\n");
r_cons_printf (" functions\n");
r_cons_printf (" flags\n");
break;
case 'c':
switch (each[1]) {
case 'a': // call
2015-10-29 19:02:13 +00:00
break;
default:
r_meta_list_cb (core->anal, R_META_TYPE_COMMENT, 0, foreach_comment, (void*)cmd);
break;
}
break;
case 't':
// iterate over all threads
if (dbg && dbg->h && dbg->h->threads) {
int origpid = dbg->pid;
RDebugPid *p;
list = dbg->h->threads (dbg, dbg->pid);
if (!list)
2015-09-14 10:35:38 +00:00
return false;
r_list_foreach (list, iter, p) {
r_core_cmdf (core, "dp %d", p->pid);
r_cons_printf ("PID %d\n", p->pid);
r_core_cmd0 (core, cmd);
}
r_core_cmdf (core, "dp %d", origpid);
r_list_free (list);
}
break;
case 'r':
// registers
{
ut64 offorig = core->offset;
for (i=0; i<128; i++) {
RRegItem *item;
ut64 value;
head = r_reg_get_list (dbg->reg, i);
if (!head) continue;
r_list_foreach (head, iter, item) {
if (item->size != core->anal->bits)
continue;
value = r_reg_get_value (dbg->reg, item);
r_core_seek (core, value, 1);
r_cons_printf ("%s: ", item->name);
r_core_cmd0 (core, cmd);
}
}
r_core_seek (core, offorig, 1);
}
break;
case 'i':
// imports
if (0) {
RBinImport *imp;
ut64 offorig = core->offset;
list = r_bin_get_imports (core->bin);
r_list_foreach (list, iter, imp) {
r_core_seek (core, 0, 1);
r_core_cmd0 (core, cmd);
}
r_core_seek (core, offorig, 1);
} else {
eprintf ("TODO @@@ imports ^^\n");
}
break;
case 's':
// symbols
2015-10-29 19:02:13 +00:00
{
RBinSymbol *sym;
ut64 offorig = core->offset;
list = r_bin_get_symbols (core->bin);
r_list_foreach (list, iter, sym) {
r_core_seek (core, sym->vaddr, 1);
r_core_cmd0 (core, cmd);
}
r_core_seek (core, offorig, 1);
}
break;
case 'f':
switch (each[1]) {
case 'l': // flags
eprintf ("TODO @@@ flags ^^\n");
break;
case 'u': // functions
{
ut64 offorig = core->offset;
RAnalFunction *fcn;
list = core->anal->fcns;
r_list_foreach (list, iter, fcn) {
r_cons_printf ("[0x%08"PFMT64x" %s\n", fcn->addr, fcn->name);
r_core_seek (core, fcn->addr, 1);
r_core_cmd0 (core, cmd);
}
r_core_seek (core, offorig, 1);
}
break;
}
break;
}
return 0;
}
R_API int r_core_cmd_foreach(RCore *core, const char *cmd, char *each) {
int i, j;
char ch;
char *word = NULL;
char *str, *ostr;
2010-12-23 23:51:01 +00:00
RListIter *iter;
RFlagItem *flag;
ut64 oseek, addr;
2016-10-18 00:12:43 +00:00
// for (; *each==' '; each++);
for (; *cmd==' '; cmd++);
oseek = core->offset;
ostr = str = strdup (each);
//r_cons_break();
switch (each[0]) {
2014-06-20 16:35:49 +00:00
case '?':{
2014-09-27 08:40:38 +00:00
const char* help_msg[] = {
2014-06-20 16:35:49 +00:00
"@@", "", " # foreach iterator command:",
"Repeat a command over a list of offsets", "", "",
"x", " @@ sym.*", "run 'x' over all flags matching 'sym.' in current flagspace",
"x", " @@dbt[abs]", "run a command on every backtrace address, bp or sp",
2014-06-20 16:35:49 +00:00
"x", " @@.file", "\"\" over the offsets specified in the file (one offset per line)",
"x", " @@=off1 off2 ..", "manual list of offsets",
2015-04-19 09:54:50 +00:00
"x", " @@k sdbquery", "\"\" on all offsets returned by that sdbquery",
"x", " @@t", "\"\" on all threads (see dp)",
"x", " @@b", "\"\" on all basic blocks of current function (see afb)",
"x", " @@i", "\"\" on all instructions of the current function (see pdr)",
"x", " @@f", "\"\" on all functions (see aflq)",
"x", " @@f:write", "\"\" on all functions matching write in the name",
2014-06-20 16:35:49 +00:00
"x", " @@=`pdf~call[0]`", "run 'x' at every call offset of the current function",
2015-04-18 23:25:50 +00:00
// TODO: Add @@k sdb-query-expression-here
2014-06-20 16:35:49 +00:00
NULL};
r_core_cmd_help (core, help_msg);
}
break;
case 'b': // "@@b" - function basic blocks
{
RListIter *iter;
RAnalBlock *bb;
RAnalFunction *fcn = r_anal_get_fcn_at (core->anal, core->offset, 0);
int bs = core->blocksize;
if (fcn) {
r_list_sort (fcn->bbs, bb_cmp);
r_list_foreach (fcn->bbs, iter, bb) {
r_core_block_size (core, bb->size);
r_core_seek (core, bb->addr, 1);
r_core_cmd (core, cmd, 0);
}
}
free (ostr);
r_core_block_size (core, bs);
return false;
}
break;
case 'i': // "@@i" - function instructions
{
RListIter *iter;
RAnalBlock *bb;
int i;
RAnalFunction *fcn = r_anal_get_fcn_at (core->anal, core->offset, 0);
if (fcn) {
r_list_sort (fcn->bbs, bb_cmp);
r_list_foreach (fcn->bbs, iter, bb) {
for (i = 0; i < bb->op_pos_size; i++) {
ut64 addr = bb->addr + bb->op_pos[i];
r_core_seek (core, addr, 1);
r_core_cmd (core, cmd, 0);
}
}
}
free (ostr);
return false;
}
break;
case 'f': // "@@f"
if (each[1] == ':') {
RAnalFunction *fcn;
RListIter *iter;
if (core->anal) {
r_list_foreach (core->anal->fcns, iter, fcn) {
if (each[2] && strstr (fcn->name, each + 2)) {
r_core_seek (core, fcn->addr, 1);
r_core_cmd (core, cmd, 0);
}
}
}
free (ostr);
return false;
} else {
RAnalFunction *fcn;
RListIter *iter;
if (core->anal) {
2016-10-18 00:12:43 +00:00
RConsGrep grep = core->cons->grep;
r_list_foreach (core->anal->fcns, iter, fcn) {
r_core_seek (core, fcn->addr, 1);
2016-10-18 00:12:43 +00:00
r_cons_push ();
r_core_cmd (core, cmd, 0);
2016-10-18 00:12:43 +00:00
char *buf = strdup (r_cons_get_buffer ());
r_cons_pop ();
r_cons_strcat (buf);
r_cons_newline();
free (buf);
}
2016-10-18 00:12:43 +00:00
core->cons->grep = grep;
}
free (ostr);
return false;
}
break;
case 't':
{
RDebugPid *p;
int pid = core->dbg->pid;
2015-09-03 10:23:49 +00:00
if (core->dbg->h && core->dbg->h->pids) {
RList *list = core->dbg->h->pids (R_MAX (0, pid));
r_list_foreach (list, iter, p) {
r_cons_printf ("# PID %d\n", p->pid);
r_debug_select (core->dbg, p->pid, p->pid);
r_core_cmd (core, cmd, 0);
r_cons_newline ();
}
r_list_free (list);
}
r_debug_select (core->dbg, pid, pid);
2015-09-03 10:23:49 +00:00
free (ostr);
2015-09-14 10:35:38 +00:00
return false;
}
break;
case '=':
/* foreach list of items */
each = str+1;
do {
while (*each == ' ') {
each++;
}
if (!*each) {
break;
}
str = strchr (each, ' ');
2009-03-21 02:17:43 +00:00
if (str) {
*str = '\0';
addr = r_num_math (core->num, each);
*str = ' ';
} else {
addr = r_num_math (core->num, each);
}
//eprintf ("; 0x%08"PFMT64x":\n", addr);
each = str + 1;
r_core_seek (core, addr, 1);
r_core_cmd (core, cmd, 0);
r_cons_flush ();
} while (str != NULL);
break;
case 'd':
if (each[1] == 'b' && each[2] == 't') {
ut64 oseek = core->offset;
RDebugFrame *frame;
RListIter *iter;
RList *list;
list = r_debug_frames (core->dbg, UT64_MAX);
i = 0;
r_list_foreach (list, iter, frame) {
switch (each[3]) {
case 'b':
r_core_seek (core, frame->bp, 1);
break;
case 's':
r_core_seek (core, frame->sp, 1);
break;
default:
case 'a':
r_core_seek (core, frame->addr, 1);
break;
}
r_core_cmd (core, cmd, 0);
2015-10-23 10:07:07 +00:00
r_cons_newline ();
i++;
}
r_core_seek (core, oseek, 0);
r_list_free (list);
} else {
eprintf("Invalid for-each statement. Use @@=dbt[abs]\n");
}
break;
2015-04-19 09:54:50 +00:00
case 'k':
/* foreach list of items */
{
char *out = sdb_querys (core->sdb, NULL, 0, str+((str[1])?2:1));
if (out) {
each = out;
do {
while (*each==' ') each++;
if (!*each) break;
str = strchr (each, ' ');
if (str) {
*str = '\0';
addr = r_num_math (core->num, each);
*str = ' ';
} else addr = r_num_math (core->num, each);
//eprintf ("; 0x%08"PFMT64x":\n", addr);
each = str+1;
r_core_seek (core, addr, 1);
r_core_cmd (core, cmd, 0);
r_cons_flush ();
} while (str != NULL);
free (out);
}
}
break;
case '.':
if (each[1]=='(') {
char cmd2[1024];
// TODO: use r_cons_break() here
// XXX whats this 999 ?
i = 0;
r_cons_break (NULL, NULL);
for (core->rcmd->macro.counter=0;i<999;core->rcmd->macro.counter++) {
if (r_cons_singleton ()->breaked)
break;
r_cmd_macro_call (&core->rcmd->macro, each+2);
if (!core->rcmd->macro.brk_value)
break;
addr = core->rcmd->macro._brk_value;
sprintf (cmd2, "%s @ 0x%08"PFMT64x"", cmd, addr);
eprintf ("0x%08"PFMT64x" (%s)\n", addr, cmd2);
r_core_seek (core, addr, 1);
r_core_cmd (core, cmd2, 0);
i++;
}
r_cons_break_end();
} else {
char buf[1024];
char cmd2[1024];
FILE *fd = r_sandbox_fopen (each+1, "r");
if (fd) {
core->rcmd->macro.counter=0;
while (!feof (fd)) {
buf[0] = '\0';
if (!fgets (buf, sizeof (buf), fd))
break;
addr = r_num_math (core->num, buf);
eprintf ("0x%08"PFMT64x": %s\n", addr, cmd);
sprintf (cmd2, "%s @ 0x%08"PFMT64x"", cmd, addr);
r_core_seek (core, addr, 1); // XXX
r_core_cmd (core, cmd2, 0);
core->rcmd->macro.counter++;
}
fclose (fd);
} else {
eprintf ("cannot open file '%s' to read offsets\n", each+1);
}
}
break;
default:
core->rcmd->macro.counter = 0;
2016-10-18 00:12:43 +00:00
for (; *each==' '; each++);
//while(str[i]) && !core->interrupted) {
// split by keywords
i = 0;
while (str[i]) {
j = i;
for (; str[j] && str[j] == ' '; j++); // skip spaces
for (i = j; str[i] && str[i] != ' '; i++); // find EOS
ch = str[i];
str[i] = '\0';
word = strdup (str + j);
2016-10-18 00:12:43 +00:00
if (!word) {
break;
2016-10-18 00:12:43 +00:00
}
str[i] = ch;
{
int flagspace = core->flags->space_idx;
/* for all flags in current flagspace */
// XXX: dont ask why, but this only works with _prev..
r_list_foreach (core->flags->flags, iter, flag) {
2016-10-18 00:12:43 +00:00
if (r_cons_singleton()->breaked) {
2009-03-21 02:17:43 +00:00
break;
2016-10-18 00:12:43 +00:00
}
/* filter per flag spaces */
2016-10-18 00:12:43 +00:00
if ((flagspace != -1) && (flag->space != flagspace)) {
continue;
2016-10-18 00:12:43 +00:00
}
if (r_str_glob (flag->name, word)) {
r_core_seek (core, flag->offset, 1);
2016-10-18 00:12:43 +00:00
r_cons_push ();
//r_cons_printf ("# @@ 0x%08"PFMT64x" (%s)\n", core->offset, flag->name);
// r_cons_printf ("0x%08"PFMT64x" %s\n", core->offset, flag->name);
//eprintf ("# 0x%08"PFMT64x": %s\n", flag->offset, cmd);
r_core_cmd (core, cmd, 0);
2016-10-18 00:12:43 +00:00
char *buf = strdup (r_cons_get_buffer ());
r_cons_pop ();
r_cons_strcat (buf);
free (buf);
}
}
r_cons_break (NULL, NULL);
core->flags->space_idx = flagspace;
core->rcmd->macro.counter++ ;
free (word);
word = NULL;
}
}
}
r_cons_break_end ();
2009-03-21 02:17:43 +00:00
// XXX: use r_core_seek here
core->offset = oseek;
free (word);
free (ostr);
2015-09-14 10:35:38 +00:00
return true;
}
2011-04-06 09:35:18 +00:00
R_API int r_core_cmd(RCore *core, const char *cstr, int log) {
char *cmd, *ocmd, *ptr, *rcmd;
int ret = false, i;
2016-08-14 17:29:59 +00:00
if (core->cmdfilter) {
2016-08-14 17:55:54 +00:00
const char *invalid_chars = ";|>`@";
for (i = 0; invalid_chars[i]; i++) {
if (strchr (cstr, invalid_chars[i])) {
return 1;
}
}
if (strncmp (cstr, core->cmdfilter, strlen (core->cmdfilter))) {
2016-08-14 17:29:59 +00:00
return 1;
}
}
if (core->cmdremote) {
if (*cstr != '=' && *cstr != 'q' && strncmp (cstr, "!=", 2)) {
r_io_system (core->io, cstr);
return 0;
}
}
if (!cstr || *cstr == '|') {
// raw comment syntax
2015-09-14 10:35:38 +00:00
return false;
2013-12-22 03:58:41 +00:00
}
if (!strncmp (cstr, "/*", 2)) {
2015-02-04 00:15:48 +00:00
if (r_sandbox_enable (0)) {
eprintf ("This command is disabled in sandbox mode\n");
return 0;
}
2015-09-14 10:35:38 +00:00
core->incomment = true;
} else if (!strncmp (cstr, "*/", 2)) {
2015-09-14 10:35:38 +00:00
core->incomment = false;
return false;
}
if (core->incomment)
2015-09-14 10:35:38 +00:00
return false;
2016-04-27 20:30:29 +00:00
if (log && (*cstr && (*cstr != '.' || !strncmp (cstr, ".(", 2)))) {
free (core->lastcmd);
core->lastcmd = strdup (cstr);
}
ocmd = cmd = malloc (strlen (cstr) + 4096);
if (!ocmd) return false;
r_str_cpy (cmd, cstr);
if (log) r_line_hist_add (cstr);
2015-10-18 13:49:46 +00:00
if (core->cmd_depth < 1) {
2014-01-09 00:09:40 +00:00
eprintf ("r_core_cmd: That was too deep (%s)...\n", cmd);
free (ocmd);
free (core->oobi);
core->oobi = NULL;
core->oobi_len = 0;
return 0;
}
core->cmd_depth --;
for (rcmd = cmd;;) {
ptr = strchr (rcmd, '\n');
if (ptr) *ptr = '\0';
ret = r_core_cmd_subst (core, rcmd);
if (ret == -1) {
eprintf ("|ERROR| Invalid command '%s' (0x%02x)\n",
rcmd, *rcmd);
break;
}
if (!ptr) break;
rcmd = ptr + 1;
}
core->cmd_depth ++;
free (ocmd);
free (core->oobi);
core->oobi = NULL;
core->oobi_len = 0;
return ret;
}
R_API int r_core_cmd_lines(RCore *core, const char *lines) {
2015-09-14 10:35:38 +00:00
int r, ret = true;
char *nl, *data, *odata;
2015-09-14 10:35:38 +00:00
if (!lines || !*lines) return true;
data = odata = strdup (lines);
2016-05-24 20:22:15 +00:00
if (!odata) return false;
nl = strchr (odata, '\n');
if (nl) {
2015-03-26 21:41:57 +00:00
r_cons_break (NULL, NULL);
do {
2015-03-26 21:41:57 +00:00
if (core->cons->breaked) {
free (odata);
return ret;
}
*nl = '\0';
r = r_core_cmd (core, data, 0);
2016-03-31 02:48:36 +00:00
if (r < 0) { //== -1) {
2015-03-26 21:41:57 +00:00
data = nl+1;
ret = -1; //r; //false;
break;
}
r_cons_flush ();
if (data[0]=='q') {
if (data[1]=='!')
ret = -1;
else eprintf ("'q': quit ignored. Use 'q!'\n");
2016-03-31 02:48:36 +00:00
data = nl + 1;
break;
}
data = nl+1;
} while ((nl = strchr (data, '\n')));
2015-03-26 21:41:57 +00:00
r_cons_break_end ();
}
if (ret>=0 && data && *data)
r_core_cmd (core, data, 0);
free (odata);
return ret;
}
R_API int r_core_cmd_file(RCore *core, const char *file) {
char *data, *odata;
data = r_file_abspath (file);
2015-09-14 10:35:38 +00:00
if (!data) return false;
odata = r_file_slurp (data, NULL);
free (data);
2015-09-14 10:35:38 +00:00
if (!odata) return false;
if (!r_core_cmd_lines (core, odata)) {
eprintf ("Failed to run script '%s'\n", file);
2014-04-27 23:27:45 +00:00
free (odata);
2015-09-14 10:35:38 +00:00
return false;
}
2014-04-27 23:27:45 +00:00
free (odata);
2015-09-14 10:35:38 +00:00
return true;
}
R_API int r_core_cmd_command(RCore *core, const char *command) {
int ret, len;
char *buf, *rcmd, *ptr;
char *cmd = r_core_sysenv_begin (core, command);
rcmd = ptr = buf = r_sys_cmd_str (cmd, 0, &len);
if (!buf) {
2015-10-21 14:44:59 +00:00
free (cmd);
return -1;
2015-10-21 14:44:59 +00:00
}
ret = r_core_cmd (core, rcmd, 0);
r_core_sysenv_end (core, command);
free (buf);
return ret;
}
//TODO: Fix disasm loop is mandatory
R_API char *r_core_disassemble_instr(RCore *core, ut64 addr, int l) {
char *cmd, *ret = NULL;
cmd = r_str_newf ("pd %i @ 0x%08"PFMT64x, l, addr);
if (cmd) {
ret = r_core_cmd_str (core, cmd);
free (cmd);
}
return ret;
}
R_API char *r_core_disassemble_bytes(RCore *core, ut64 addr, int b) {
char *cmd, *ret = NULL;
cmd = r_str_newf ("pD %i @ 0x%08"PFMT64x, b, addr);
if (cmd) {
ret = r_core_cmd_str (core, cmd);
free (cmd);
}
return ret;
}
R_API int r_core_cmd_buffer(void *user, const char *buf) {
char *ptr, *optr, *str = strdup (buf);
2016-05-24 20:22:15 +00:00
if (!str) return false;
optr = str;
ptr = strchr (str, '\n');
while (ptr) {
*ptr = '\0';
r_core_cmd (user, optr, 0);
optr = ptr+1;
ptr = strchr (str, '\n');
}
r_core_cmd (user, optr, 0);
free (str);
2015-09-14 10:35:38 +00:00
return true;
}
R_API int r_core_cmdf(void *user, const char *fmt, ...) {
char string[4096];
int ret;
va_list ap;
va_start (ap, fmt);
vsnprintf (string, sizeof (string), fmt, ap);
ret = r_core_cmd ((RCore *)user, string, 0);
va_end (ap);
return ret;
}
R_API int r_core_cmd0(void *user, const char *cmd) {
return r_core_cmd ((RCore *)user, cmd, 0);
}
R_API int r_core_flush(void *user, const char *cmd) {
int ret = r_core_cmd ((RCore *)user, cmd, 0);
r_cons_flush ();
return ret;
}
R_API char *r_core_cmd_str_pipe(RCore *core, const char *cmd) {
char *s, *tmp;
r_sandbox_disable (1);
if (r_sandbox_enable (0))
return r_core_cmd_str (core, cmd);
r_cons_reset ();
2014-04-26 20:26:10 +00:00
if (r_file_mkstemp ("cmd", &tmp) != -1) {
char *_cmd = strdup (cmd);
int pipefd = r_cons_pipe_open (tmp, 1, 0);
r_sandbox_disable (0);
r_core_cmd_subst (core, _cmd);
r_cons_flush ();
r_cons_pipe_close (pipefd);
r_sandbox_disable (1);
s = r_file_slurp (tmp, NULL);
r_file_rm (tmp);
r_sandbox_disable (0);
free (tmp);
free (_cmd);
return s;
}
r_sandbox_disable (0);
return NULL;
}
2013-04-10 23:25:25 +00:00
R_API char *r_core_cmd_strf(RCore *core, const char *fmt, ...) {
char string[4096];
char *ret;
va_list ap;
va_start (ap, fmt);
vsnprintf (string, sizeof (string), fmt, ap);
ret = r_core_cmd_str (core, string);
va_end (ap);
return ret;
}
/* return: pointer to a buffer with the output of the command */
R_API char *r_core_cmd_str(RCore *core, const char *cmd) {
const char *static_str;
char *retstr = NULL;
r_cons_reset ();
if (r_core_cmd (core, cmd, 0) == -1) {
2014-01-23 08:44:47 +00:00
//eprintf ("Invalid command: %s\n", cmd);
return NULL;
}
r_cons_filter ();
static_str = r_cons_get_buffer ();
retstr = strdup (static_str? static_str: "");
r_cons_reset ();
return retstr;
}
R_API void r_core_cmd_repeat(RCore *core, int next) {
2014-01-09 00:09:40 +00:00
// Fix for backtickbug px`~`
if (core->cmd_depth + 1 < R_CORE_CMD_DEPTH)
2014-01-09 00:09:40 +00:00
return;
if (core->lastcmd)
switch (*core->lastcmd) {
2016-04-22 08:52:25 +00:00
case '.':
if (core->lastcmd[1] == '(') // macro call
r_core_cmd0 (core, core->lastcmd);
break;
case 'd': // debug
r_core_cmd0 (core, core->lastcmd);
switch (core->lastcmd[1]) {
case 's':
case 'c':
2015-10-31 00:57:52 +00:00
r_core_cmd0 (core, "sr PC;pd 1");
}
break;
case 'p': // print
case 'x':
case '$':
if (next) {
r_core_seek (core, core->offset + core->blocksize, 1);
} else {
if (core->blocksize > core->offset) {
r_core_seek (core, 0, 1);
} else {
r_core_seek (core, core->offset - core->blocksize, 1);
}
}
r_core_cmd0 (core, core->lastcmd);
break;
}
}
2013-11-10 02:43:16 +00:00
static int cmd_ox(void *data, const char *input) {
return r_core_cmdf ((RCore*)data, "s 0%s", input);
}
R_API void r_core_cmd_init(RCore *core) {
core->rcmd = r_cmd_new ();
core->rcmd->macro.user = core;
core->rcmd->macro.num = core->num;
core->rcmd->macro.cmd = r_core_cmd0;
core->rcmd->nullcallback = r_core_cmd_nullcallback;
core->rcmd->macro.cb_printf = (PrintfCallback)r_cons_printf;
r_cmd_set_data (core->rcmd, core);
2013-11-10 02:43:16 +00:00
r_cmd_add (core->rcmd, "0x", "alias for px", &cmd_ox);
r_cmd_add (core->rcmd, "x", "alias for px", &cmd_hexdump);
r_cmd_add (core->rcmd, "mount", "mount filesystem", &cmd_mount);
r_cmd_add (core->rcmd, "analysis", "analysis", &cmd_anal);
r_cmd_add (core->rcmd, "flag", "get/set flags", &cmd_flag);
r_cmd_add (core->rcmd, "g", "egg manipulation", &cmd_egg);
r_cmd_add (core->rcmd, "debug", "debugger operations", &cmd_debug);
r_cmd_add (core->rcmd, "ls", "list files and directories", &cmd_ls);
r_cmd_add (core->rcmd, "info", "get file info", &cmd_info);
r_cmd_add (core->rcmd, "cmp", "compare memory", &cmd_cmp);
r_cmd_add (core->rcmd, "seek", "seek to an offset", &cmd_seek);
r_cmd_add (core->rcmd, "Text", "Text log utility", &cmd_log);
r_cmd_add (core->rcmd, "t", "type information (cparse)", &cmd_type);
r_cmd_add (core->rcmd, "zign", "zignatures", &cmd_zign);
r_cmd_add (core->rcmd, "Section", "setup section io information", &cmd_section);
r_cmd_add (core->rcmd, "bsize", "change block size", &cmd_bsize);
r_cmd_add (core->rcmd, "kuery", "perform sdb query", &cmd_kuery);
r_cmd_add (core->rcmd, "eval", "evaluate configuration variable", &cmd_eval);
r_cmd_add (core->rcmd, "print", "print current block", &cmd_print);
r_cmd_add (core->rcmd, "write", "write bytes", &cmd_write);
r_cmd_add (core->rcmd, "Code", "code metadata", &cmd_meta);
r_cmd_add (core->rcmd, "Project", "project", &cmd_project);
r_cmd_add (core->rcmd, "open", "open or map file", &cmd_open);
r_cmd_add (core->rcmd, "yank", "yank bytes", &cmd_yank);
r_cmd_add (core->rcmd, "resize", "change file size", &cmd_resize);
r_cmd_add (core->rcmd, "Visual", "enter visual mode", &cmd_visual);
2016-05-14 14:42:25 +00:00
r_cmd_add (core->rcmd, "visual", "enter visual mode", &cmd_visual);
r_cmd_add (core->rcmd, "*", "pointer read/write", &cmd_pointer);
r_cmd_add (core->rcmd, "&", "threading capabilities", &cmd_thread);
r_cmd_add (core->rcmd, "%", "short version of 'env' command", &cmd_env);
r_cmd_add (core->rcmd, "!", "run system command", &cmd_system);
r_cmd_add (core->rcmd, "=", "io pipe", &cmd_rap);
r_cmd_add (core->rcmd, "#", "calculate hash", &cmd_hash);
r_cmd_add (core->rcmd, "?", "help message", &cmd_help);
r_cmd_add (core->rcmd, "$", "alias", &cmd_alias);
r_cmd_add (core->rcmd, ".", "interpret", &cmd_interpret);
r_cmd_add (core->rcmd, "/", "search kw, pattern aes", &cmd_search);
r_cmd_add (core->rcmd, "-", "open cfg.editor and run script", &cmd_stdin);
r_cmd_add (core->rcmd, "(", "macro", &cmd_macro);
2015-12-30 11:43:15 +00:00
r_cmd_add (core->rcmd, "u", "uname/undo", &cmd_uname);
r_cmd_add (core->rcmd, "quit", "exit program session", &cmd_quit);
}