2017-01-13 13:13:53 +00:00
|
|
|
/* radare - LGPL - Copyright 2009-2017 - 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
|
2009-02-05 21:08:46 +00:00
|
|
|
|
2014-10-10 23:21:17 +00:00
|
|
|
#define INTERACTIVE_MAX_REP 1024
|
|
|
|
|
2012-07-22 08:00:35 +00:00
|
|
|
#include <r_core.h>
|
|
|
|
#include <r_anal.h>
|
2016-12-12 19:22:25 +00:00
|
|
|
#include <r_cons.h>
|
2017-07-25 07:11:29 +00:00
|
|
|
#include <r_cmd.h>
|
2015-02-24 13:50:14 +00:00
|
|
|
#include <stdint.h>
|
2009-12-31 00:27:03 +00:00
|
|
|
#include <sys/types.h>
|
2011-05-21 12:27:46 +00:00
|
|
|
#include <ctype.h>
|
2009-02-18 00:43:57 +00:00
|
|
|
#include <stdarg.h>
|
2016-10-30 10:10:20 +00:00
|
|
|
#if __UNIX__
|
|
|
|
#include <sys/utsname.h>
|
|
|
|
#endif
|
2010-07-03 01:35:26 +00:00
|
|
|
|
2017-08-11 09:45:32 +00:00
|
|
|
#define DEFINE_CMD_DESCRIPTOR(core, cmd_) \
|
|
|
|
{ \
|
|
|
|
RCmdDescriptor *d = R_NEW0 (RCmdDescriptor); \
|
|
|
|
if (d) { \
|
|
|
|
d->cmd = #cmd_; \
|
|
|
|
d->help_msg = help_msg_##cmd_; \
|
|
|
|
r_list_append (core->cmd_descriptors, d); \
|
|
|
|
} \
|
|
|
|
}
|
|
|
|
|
|
|
|
#define DEFINE_CMD_DESCRIPTOR_WITH_DETAIL(core, cmd_) \
|
|
|
|
{ \
|
|
|
|
RCmdDescriptor *d = R_NEW0 (RCmdDescriptor); \
|
|
|
|
if (d) { \
|
|
|
|
d->cmd = #cmd_; \
|
|
|
|
d->help_msg = help_msg_##cmd_; \
|
|
|
|
d->help_detail = help_detail_##cmd_; \
|
|
|
|
r_list_append (core->cmd_descriptors, d); \
|
|
|
|
} \
|
|
|
|
}
|
|
|
|
|
|
|
|
#define DEFINE_CMD_DESCRIPTOR_WITH_DETAIL2(core, cmd_) \
|
|
|
|
{ \
|
|
|
|
RCmdDescriptor *d = R_NEW0 (RCmdDescriptor); \
|
|
|
|
if (d) { \
|
|
|
|
d->cmd = #cmd_; \
|
|
|
|
d->help_msg = help_msg_##cmd_; \
|
|
|
|
d->help_detail = help_detail_##cmd_; \
|
|
|
|
d->help_detail2 = help_detail2_##cmd_; \
|
|
|
|
r_list_append (core->cmd_descriptors, d); \
|
|
|
|
} \
|
|
|
|
}
|
|
|
|
|
|
|
|
#define DEFINE_CMD_DESCRIPTOR_SPECIAL(core, cmd_, named_cmd) \
|
|
|
|
{ \
|
|
|
|
RCmdDescriptor *d = R_NEW0 (RCmdDescriptor); \
|
|
|
|
if (d) { \
|
|
|
|
d->cmd = #cmd_; \
|
|
|
|
d->help_msg = help_msg_##named_cmd; \
|
|
|
|
r_list_append (core->cmd_descriptors, d); \
|
|
|
|
} \
|
2017-07-27 12:52:17 +00:00
|
|
|
}
|
2017-07-25 11:20:25 +00:00
|
|
|
|
2012-02-27 01:40:27 +00:00
|
|
|
static void cmd_debug_reg(RCore *core, const char *str);
|
2014-05-27 23:07:02 +00:00
|
|
|
#include "cmd_quit.c"
|
2012-02-27 01:40:27 +00:00
|
|
|
#include "cmd_hash.c"
|
|
|
|
#include "cmd_debug.c"
|
2014-07-29 22:33:54 +00:00
|
|
|
#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"
|
2014-05-27 23:07:02 +00:00
|
|
|
#include "cmd_eval.c"
|
2012-02-27 01:40:27 +00:00
|
|
|
#include "cmd_anal.c"
|
|
|
|
#include "cmd_open.c"
|
|
|
|
#include "cmd_meta.c"
|
2012-07-18 09:29:24 +00:00
|
|
|
#include "cmd_type.c"
|
2012-02-27 02:07:32 +00:00
|
|
|
#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"
|
2010-10-28 18:47:21 +00:00
|
|
|
|
2017-07-27 12:52:17 +00:00
|
|
|
static const char *help_msg_dollar[] = {
|
|
|
|
"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",
|
|
|
|
"$", "dis=", "undefine alias",
|
|
|
|
"$", "dis", "execute the previously defined alias",
|
|
|
|
"$", "dis?", "show commands aliased by 'analyze'",
|
|
|
|
NULL
|
|
|
|
};
|
|
|
|
|
|
|
|
static const char *help_msg_percent[] = {
|
|
|
|
"Usage:", "%[name[=value]]", "Set each NAME to VALUE in the environment",
|
|
|
|
"%", "", "list all environment variables",
|
|
|
|
"%", "SHELL", "prints SHELL value",
|
|
|
|
"%", "TMPDIR=/tmp", "sets TMPDIR value to \"/tmp\"",
|
|
|
|
NULL
|
|
|
|
};
|
|
|
|
|
|
|
|
static const char *help_msg_star[] = {
|
|
|
|
"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
|
|
|
|
};
|
|
|
|
|
2017-08-11 09:45:32 +00:00
|
|
|
static const char *help_msg_dot[] = {
|
|
|
|
"Usage:", ".[r2cmd] | [file] | [!command] | [(macro)]", " # define macro or load r2, cparse or rlang file",
|
|
|
|
".", "", "repeat last command backward",
|
|
|
|
".", "r2cmd", "interpret the output of the command as r2 commands",
|
2017-09-23 00:05:30 +00:00
|
|
|
"..", " [file]", "run the output of the execution of a script as r2 commands",
|
|
|
|
"...", "", "repeat last command forward (same as \\n)",
|
2017-08-11 09:45:32 +00:00
|
|
|
".:", "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
|
|
|
|
};
|
|
|
|
|
|
|
|
static const char *help_msg_equal[] = {
|
|
|
|
"Usage:", " =[:!+-=hH] [...]", " # radare remote command execution protocol",
|
|
|
|
"\nrap commands:", "", "",
|
|
|
|
"=", "", "list all open connections",
|
|
|
|
"=<", "[fd] cmd", "send output of local command to remote fd",
|
|
|
|
"=", "[fd] cmd", "exec cmd at remote 'fd' (last open is default one)",
|
|
|
|
"=!", " cmd", "run command via r_io_system",
|
|
|
|
"=+", " [proto://]host", "add host (default=rap://, tcp://, udp://)",
|
|
|
|
"=-", "[fd]", "remove all hosts or host 'fd'",
|
|
|
|
"==", "[fd]", "open remote session with host 'fd', 'q' to quit",
|
|
|
|
"=!=", "", "disable remote cmd mode",
|
|
|
|
"!=!", "", "enable remote cmd mode",
|
|
|
|
"\nrap server:","","",
|
|
|
|
"=", ":port", "listen on given port using rap protocol (o rap://9999)",
|
|
|
|
"=&", ":port", "start rap server in background",
|
|
|
|
"=", ":host:port cmd", "run 'cmd' command on remote server",
|
|
|
|
"\nhttp server:", "", "",
|
|
|
|
"=h", " port", "listen for http connections (r2 -qc=H /bin/ls)",
|
|
|
|
"=h-", "", "stop background webserver",
|
|
|
|
"=h*", "", "restart current webserver",
|
|
|
|
"=h&", " port", "start http server in background)",
|
|
|
|
"=H", " port", "launch browser and listen for http",
|
|
|
|
"=H&", " port", "launch browser and listen for http in background",
|
|
|
|
"\ngdbserver:", "", "",
|
|
|
|
"=g", " port file [args]", "listen on 'port' debugging 'file' using gdbserver",
|
|
|
|
"=g!", " port file [args]", "same as above, but debug protocol messages (like gdbserver --remote-debug)",
|
|
|
|
NULL
|
|
|
|
};
|
|
|
|
|
2017-07-27 12:52:17 +00:00
|
|
|
static const char *help_msg_b[] = {
|
|
|
|
"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",
|
|
|
|
"b", "-16", "decrease blocksize by 16",
|
|
|
|
"b", " eip+4", "numeric argument can be an expression",
|
|
|
|
"bf", " foo", "set block size to flag size",
|
|
|
|
"bm", " 1M", "set max block size",
|
|
|
|
NULL
|
|
|
|
};
|
|
|
|
|
|
|
|
static const char *help_msg_k[] = {
|
|
|
|
"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",
|
|
|
|
"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,
|
|
|
|
};
|
|
|
|
|
|
|
|
static const char *help_msg_r[] = {
|
|
|
|
"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",
|
|
|
|
"r2" ," [file]", "launch r2",
|
|
|
|
NULL
|
|
|
|
};
|
|
|
|
|
|
|
|
static const char *help_msg_u[] = {
|
|
|
|
"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
|
|
|
|
};
|
|
|
|
|
|
|
|
static const char *help_msg_y[] = {
|
|
|
|
"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",
|
|
|
|
"yx", "", "print contents of clipboard in hexadecimal",
|
|
|
|
"ys", "", "print contents of clipboard as string",
|
|
|
|
"yt", " 64 0x200", "copy 64 bytes from current seek to 0x200",
|
|
|
|
"ytf", " file", "dump the clipboard to given file",
|
|
|
|
"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)",
|
|
|
|
"yy", " 0x3344", "paste clipboard",
|
|
|
|
NULL
|
|
|
|
};
|
|
|
|
|
2017-09-12 09:05:24 +00:00
|
|
|
static void recursive_help_go(RCore *core, int detail, RCmdDescriptor *desc) {
|
2017-09-12 11:56:00 +00:00
|
|
|
int i;
|
2017-09-12 09:05:24 +00:00
|
|
|
if (desc->help_msg) {
|
|
|
|
r_core_cmd_help (core, desc->help_msg);
|
|
|
|
}
|
|
|
|
if (detail >= 1) {
|
|
|
|
if (desc->help_detail) {
|
|
|
|
r_core_cmd_help (core, desc->help_detail);
|
2016-12-12 19:22:25 +00:00
|
|
|
}
|
2017-09-12 09:05:24 +00:00
|
|
|
if (detail >= 2 && desc->help_detail2) {
|
|
|
|
r_core_cmd_help (core, desc->help_detail2);
|
|
|
|
}
|
|
|
|
}
|
2017-09-12 11:56:00 +00:00
|
|
|
for (i = 32; i < R_ARRAY_SIZE (desc->sub); i++)
|
2017-09-12 09:05:24 +00:00
|
|
|
if (desc->sub[i]) {
|
|
|
|
recursive_help_go (core, detail, desc->sub[i]);
|
2016-10-15 22:48:39 +00:00
|
|
|
}
|
2017-09-12 09:05:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void recursive_help(RCore *core, int detail, const char *cmd_prefix) {
|
2017-09-12 11:56:00 +00:00
|
|
|
const ut8 *p;
|
2017-09-12 09:05:24 +00:00
|
|
|
RCmdDescriptor *desc = &core->root_cmd_descriptor;
|
2017-09-12 11:56:00 +00:00
|
|
|
for (p = (const ut8 *)cmd_prefix; *p && *p < R_ARRAY_SIZE (desc->sub); p++) {
|
2017-09-12 09:05:24 +00:00
|
|
|
if (!(desc = desc->sub[*p])) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
recursive_help_go (core, detail, desc);
|
2016-10-15 22:48:39 +00:00
|
|
|
}
|
|
|
|
|
2012-09-20 01:38:48 +00:00
|
|
|
static int r_core_cmd_nullcallback(void *data) {
|
|
|
|
RCore *core = (RCore*) data;
|
2014-11-24 02:10:29 +00:00
|
|
|
if (core->cons->breaked) {
|
2015-09-14 10:35:38 +00:00
|
|
|
core->cons->breaked = false;
|
2014-11-24 02:10:29 +00:00
|
|
|
return 0;
|
|
|
|
}
|
2016-10-30 10:10:20 +00:00
|
|
|
if (!core->cmdrepeat) {
|
|
|
|
return 0;
|
|
|
|
}
|
2015-09-14 10:35:38 +00:00
|
|
|
r_core_cmd_repeat (core, true);
|
2012-09-21 00:25:44 +00:00
|
|
|
return 1;
|
2012-09-20 01:38:48 +00:00
|
|
|
}
|
|
|
|
|
2011-02-24 08:40:19 +00:00
|
|
|
// TODO: move somewhere else
|
2011-02-24 15:50:29 +00:00
|
|
|
R_API RAsmOp *r_core_disassemble (RCore *core, ut64 addr) {
|
2012-06-14 15:41:07 +00:00
|
|
|
int delta;
|
|
|
|
ut8 buf[128];
|
2011-02-24 08:40:19 +00:00
|
|
|
static RBuffer *b = NULL; // XXX: never freed and non-thread safe. move to RCore
|
2012-06-14 15:41:07 +00:00
|
|
|
RAsmOp *op;
|
2016-09-19 12:44:47 +00:00
|
|
|
if (!b) {
|
2011-02-24 08:40:19 +00:00
|
|
|
b = r_buf_new ();
|
2016-10-30 10:10:20 +00:00
|
|
|
if (!b || !r_core_read_at (core, addr, buf, sizeof (buf))) {
|
2013-04-11 23:15:00 +00:00
|
|
|
return NULL;
|
2016-10-30 10:10:20 +00:00
|
|
|
}
|
2013-04-11 23:15:00 +00:00
|
|
|
b->base = addr;
|
|
|
|
r_buf_set_bytes (b, buf, sizeof (buf));
|
2011-02-24 08:40:19 +00:00
|
|
|
} else {
|
2017-01-30 18:27:40 +00:00
|
|
|
if ((addr < b->base) || addr > (b->base + b->length - 32)) {
|
2016-10-30 10:10:20 +00:00
|
|
|
if (!r_core_read_at (core, addr, buf, sizeof (buf))) {
|
2013-04-11 23:15:00 +00:00
|
|
|
return NULL;
|
2016-10-30 10:10:20 +00:00
|
|
|
}
|
2013-04-11 23:15:00 +00:00
|
|
|
b->base = addr;
|
|
|
|
r_buf_set_bytes (b, buf, sizeof (buf));
|
2011-02-24 08:40:19 +00:00
|
|
|
}
|
|
|
|
}
|
2012-06-14 15:41:07 +00:00
|
|
|
delta = addr - b->base;
|
2014-02-22 00:58:40 +00:00
|
|
|
op = R_NEW0 (RAsmOp);
|
2012-06-14 15:41:07 +00:00
|
|
|
r_asm_set_pc (core->assembler, addr);
|
2017-01-30 18:27:40 +00:00
|
|
|
if (r_asm_disassemble (core->assembler, op, b->buf + delta, b->length) < 1) {
|
2011-02-24 15:50:29 +00:00
|
|
|
free (op);
|
2011-02-24 08:40:19 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
2011-02-24 15:50:29 +00:00
|
|
|
return op;
|
2011-02-24 08:40:19 +00:00
|
|
|
}
|
|
|
|
|
2015-12-30 11:43:15 +00:00
|
|
|
static int cmd_uname(void *data, const char *input) {
|
|
|
|
switch (input[0]) {
|
2017-08-11 09:45:32 +00:00
|
|
|
case '?': // "u?"
|
2017-07-27 12:52:17 +00:00
|
|
|
r_core_cmd_help (data, help_msg_u);
|
2015-12-30 11:43:15 +00:00
|
|
|
return 1;
|
2017-08-11 09:45:32 +00:00
|
|
|
case 's': // "us"
|
2017-01-30 18:27:40 +00:00
|
|
|
r_core_cmdf (data, "s-%s", input + 1);
|
2015-12-30 11:43:15 +00:00
|
|
|
return 1;
|
2017-08-11 09:45:32 +00:00
|
|
|
case 'w': // "uw"
|
2017-01-30 18:27:40 +00:00
|
|
|
r_core_cmdf (data, "wc%s", input + 1);
|
2015-12-30 11:43:15 +00:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2012-10-30 01:49:05 +00:00
|
|
|
static int cmd_alias(void *data, const char *input) {
|
|
|
|
int i;
|
2015-05-19 11:06:27 +00:00
|
|
|
char *def, *q, *desc, *buf;
|
2012-10-30 01:49:05 +00:00
|
|
|
RCore *core = (RCore *)data;
|
2017-01-30 18:27:40 +00:00
|
|
|
if (*input == '?') {
|
2017-07-27 12:52:17 +00:00
|
|
|
r_core_cmd_help (core, help_msg_dollar);
|
2012-10-30 01:49:05 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
i = strlen (input);
|
2017-01-30 18:27:40 +00:00
|
|
|
buf = malloc (i + 2);
|
2017-05-13 00:35:31 +00:00
|
|
|
if (!buf) {
|
|
|
|
return 0;
|
|
|
|
}
|
2012-12-23 12:52:57 +00:00
|
|
|
*buf = '$'; // prefix aliases with a dash
|
2017-01-30 18:27:40 +00:00
|
|
|
memcpy (buf + 1, input, i + 1);
|
2012-10-30 01:49:05 +00:00
|
|
|
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;
|
2017-05-13 00:35:31 +00:00
|
|
|
size_t len = strlen (def);
|
2015-05-19 11:30:50 +00:00
|
|
|
/* Remove quotes */
|
2017-01-30 18:27:40 +00:00
|
|
|
if ((def[0] == '\'') && (def[len - 1] == '\'')) {
|
|
|
|
def[len - 1] = 0x00;
|
2015-05-19 11:30:50 +00:00
|
|
|
def++;
|
|
|
|
}
|
2015-05-19 11:06:27 +00:00
|
|
|
if (!q || (q && q>def)) {
|
2015-08-20 00:24:46 +00:00
|
|
|
if (*def) r_cmd_alias_set (core->rcmd, buf, def, 0);
|
2012-10-30 02:22:30 +00:00
|
|
|
else r_cmd_alias_del (core->rcmd, buf);
|
|
|
|
}
|
2015-05-19 11:06:27 +00:00
|
|
|
/* Show command for alias */
|
|
|
|
} else if (desc && !q) {
|
|
|
|
*desc = 0;
|
2017-08-22 09:12:06 +00:00
|
|
|
char *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);
|
|
|
|
}
|
2017-01-30 18:27:40 +00:00
|
|
|
} else if (buf[1] == '*') {
|
2017-08-22 09:12:06 +00:00
|
|
|
/* Show aliases */
|
2013-07-12 23:13:23 +00:00
|
|
|
int i, count = 0;
|
|
|
|
char **keys = r_cmd_alias_keys (core->rcmd, &count);
|
2017-01-30 18:27:40 +00:00
|
|
|
for (i = 0; i < count; i++) {
|
2015-08-20 00:24:46 +00:00
|
|
|
const char *v = r_cmd_alias_get (core->rcmd, keys[i], 0);
|
2013-07-12 23:13:23 +00:00
|
|
|
r_cons_printf ("%s=%s\n", keys[i], v);
|
|
|
|
}
|
2015-05-19 11:06:27 +00:00
|
|
|
} else if (!buf[1]) {
|
2013-07-12 23:13:23 +00:00
|
|
|
int i, count = 0;
|
2012-10-30 02:22:30 +00:00
|
|
|
char **keys = r_cmd_alias_keys (core->rcmd, &count);
|
2017-01-30 18:27:40 +00:00
|
|
|
for (i = 0; i < count; i++) {
|
2016-06-26 04:51:17 +00:00
|
|
|
r_cons_println (keys[i]);
|
|
|
|
}
|
2012-10-30 01:49:05 +00:00
|
|
|
} else {
|
2017-08-22 09:12:06 +00:00
|
|
|
/* Execute alias */
|
|
|
|
if (q) {
|
|
|
|
*q = 0;
|
|
|
|
}
|
|
|
|
char *v = r_cmd_alias_get (core->rcmd, buf, 0);
|
2012-10-30 01:49:05 +00:00
|
|
|
if (v) {
|
|
|
|
if (q) {
|
2017-01-30 18:27:40 +00:00
|
|
|
char *out, *args = q + 1;
|
2012-10-30 01:49:05 +00:00
|
|
|
out = malloc (strlen (v) + strlen (args) + 2);
|
2012-12-23 12:52:57 +00:00
|
|
|
if (out) { //XXX slow
|
2012-10-30 01:49:05 +00:00
|
|
|
strcpy (out, v);
|
|
|
|
strcat (out, " ");
|
|
|
|
strcat (out, args);
|
|
|
|
r_core_cmd0 (core, out);
|
|
|
|
free (out);
|
2017-08-22 09:12:06 +00:00
|
|
|
} else {
|
|
|
|
eprintf ("cannot malloc\n");
|
|
|
|
}
|
2012-10-30 01:49:05 +00:00
|
|
|
} else {
|
|
|
|
r_core_cmd0 (core, v);
|
|
|
|
}
|
2015-05-19 11:06:27 +00:00
|
|
|
} else {
|
|
|
|
eprintf ("unknown key '%s'\n", buf);
|
|
|
|
}
|
2012-10-30 01:49:05 +00:00
|
|
|
}
|
2014-08-18 01:22:16 +00:00
|
|
|
free (buf);
|
2013-07-12 23:13:23 +00:00
|
|
|
return 0;
|
2012-10-30 01:49:05 +00:00
|
|
|
}
|
|
|
|
|
2014-09-01 22:01:56 +00:00
|
|
|
static int getArg(char ch, int def) {
|
|
|
|
switch (ch) {
|
|
|
|
case '&':
|
|
|
|
case '-':
|
|
|
|
return ch;
|
|
|
|
}
|
|
|
|
return def;
|
|
|
|
}
|
|
|
|
|
2015-08-20 00:24:46 +00:00
|
|
|
static void aliascmd(RCore *core, const char *str) {
|
|
|
|
switch (str[0]) {
|
2017-08-11 09:45:32 +00:00
|
|
|
case '\0': // "=$"
|
|
|
|
r_core_cmd0 (core, "$");
|
|
|
|
break;
|
|
|
|
case '-': // "=$-"
|
2015-08-20 00:24:46 +00:00
|
|
|
if (str[1]) {
|
2017-01-30 18:27:40 +00:00
|
|
|
r_cmd_alias_del (core->rcmd, str + 2);
|
2015-08-20 00:24:46 +00:00
|
|
|
} else {
|
|
|
|
r_cmd_alias_del (core->rcmd, NULL);
|
|
|
|
// r_cmd_alias_reset (core->rcmd);
|
|
|
|
}
|
|
|
|
break;
|
2017-08-11 09:45:32 +00:00
|
|
|
case '?': // "=$?"
|
2015-08-20 00:24:46 +00:00
|
|
|
eprintf ("Usage: =$[-][remotecmd] # remote command alias\n");
|
|
|
|
eprintf (" =$dr # makes 'dr' alias for =!dr\n");
|
|
|
|
eprintf (" =$-dr # unset 'dr' alias\n");
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
r_cmd_alias_set (core->rcmd, str, "", 1);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-08-23 04:39:23 +00:00
|
|
|
static int cmd_rap(void *data, const char *input) {
|
2010-02-05 11:21:37 +00:00
|
|
|
RCore *core = (RCore *)data;
|
2011-06-04 01:51:33 +00:00
|
|
|
switch (*input) {
|
2017-08-11 09:45:32 +00:00
|
|
|
case '\0': // "="
|
|
|
|
r_core_rtr_list (core);
|
2016-10-09 21:56:52 +00:00
|
|
|
break;
|
2017-08-11 09:45:32 +00:00
|
|
|
case '!': // "=!"
|
2017-01-30 18:27:40 +00:00
|
|
|
if (input[1] == '=') {
|
2015-07-09 21:44:45 +00:00
|
|
|
// swap core->cmdremote = core->cmdremote? 0: 1;
|
|
|
|
core->cmdremote = input[2]? 1: 0;
|
2016-06-26 04:51:17 +00:00
|
|
|
r_cons_println (r_str_bool (core->cmdremote));
|
2015-07-09 21:44:45 +00:00
|
|
|
} else {
|
2017-01-30 18:27:40 +00:00
|
|
|
r_io_system (core->io, input + 1);
|
2015-07-09 21:44:45 +00:00
|
|
|
}
|
|
|
|
break;
|
2017-08-11 09:45:32 +00:00
|
|
|
case '$': // "=$"
|
|
|
|
aliascmd (core, input + 1);
|
|
|
|
break;
|
|
|
|
case '+': // "=+"
|
|
|
|
r_core_rtr_add (core, input + 1);
|
|
|
|
break;
|
|
|
|
case '-': // "=-"
|
|
|
|
r_core_rtr_remove (core, input + 1);
|
|
|
|
break;
|
|
|
|
//case ':': r_core_rtr_cmds (core, input + 1); break;
|
|
|
|
case '<': // "=<"
|
|
|
|
r_core_rtr_pushout (core, input + 1);
|
|
|
|
break;
|
|
|
|
case '=': // "=="
|
|
|
|
r_core_rtr_session (core, input + 1);
|
|
|
|
break;
|
|
|
|
case 'g': // "=g"
|
|
|
|
r_core_rtr_gdb (core, getArg (input[1], 'g'), input + 1);
|
|
|
|
break;
|
|
|
|
case 'h': // "=h"
|
|
|
|
r_core_rtr_http (core, getArg (input[1], 'h'), input + 1);
|
|
|
|
break;
|
|
|
|
case 'H': // "=H"
|
|
|
|
while (input[1] == ' ') {
|
|
|
|
input++;
|
|
|
|
}
|
|
|
|
r_core_rtr_http (core, getArg (input[1], 'H'), input + 1);
|
|
|
|
break;
|
|
|
|
case '?': // "=?"
|
|
|
|
r_core_cmd_help (core, help_msg_equal);
|
|
|
|
break;
|
2017-05-13 00:35:31 +00:00
|
|
|
default:
|
|
|
|
r_core_rtr_cmd (core, input);
|
|
|
|
break;
|
2010-08-24 09:58:09 +00:00
|
|
|
}
|
2015-05-12 21:47:26 +00:00
|
|
|
return 0;
|
2009-02-05 21:08:46 +00:00
|
|
|
}
|
|
|
|
|
2016-12-24 10:26:17 +00:00
|
|
|
static int cmd_rap_run(void *data, const char *input) {
|
|
|
|
RCore *core = (RCore *)data;
|
|
|
|
return r_io_system (core->io, input);
|
|
|
|
}
|
|
|
|
|
2009-09-25 02:04:51 +00:00
|
|
|
static int cmd_yank(void *data, const char *input) {
|
2013-03-07 22:47:41 +00:00
|
|
|
ut64 n;
|
2010-03-30 21:12:19 +00:00
|
|
|
RCore *core = (RCore *)data;
|
2010-02-28 21:58:21 +00:00
|
|
|
switch (input[0]) {
|
2017-08-11 09:45:32 +00:00
|
|
|
case ' ': // "y "
|
2017-01-30 18:27:40 +00:00
|
|
|
r_core_yank (core, core->offset, r_num_math (core->num, input + 1));
|
2009-02-18 12:10:59 +00:00
|
|
|
break;
|
2017-08-11 09:45:32 +00:00
|
|
|
case 'l': // "yl"
|
2016-03-31 03:42:37 +00:00
|
|
|
core->num->value = core->yank_buf->length;
|
|
|
|
break;
|
2017-08-11 09:45:32 +00:00
|
|
|
case 'y': // "yy"
|
2017-05-13 00:35:31 +00:00
|
|
|
while (input[1] == ' ') {
|
|
|
|
input++;
|
|
|
|
}
|
2017-01-30 18:27:40 +00:00
|
|
|
n = input[1]? r_num_math (core->num, input + 1): core->offset;
|
2013-03-07 22:47:41 +00:00
|
|
|
r_core_yank_paste (core, n, 0);
|
2012-02-04 23:33:34 +00:00
|
|
|
break;
|
2017-08-11 09:45:32 +00:00
|
|
|
case 'x': // "yx"
|
2017-01-30 18:27:40 +00:00
|
|
|
r_core_yank_hexdump (core, r_num_math (core->num, input + 1));
|
2009-02-18 12:10:59 +00:00
|
|
|
break;
|
2017-08-11 09:45:32 +00:00
|
|
|
case 'z': // "yz"
|
2017-01-30 18:27:40 +00:00
|
|
|
r_core_yank_string (core, core->offset, r_num_math (core->num, input + 1));
|
2014-05-23 10:39:05 +00:00
|
|
|
break;
|
2017-08-11 09:45:32 +00:00
|
|
|
case 'w': // "yw"
|
2016-03-31 03:42:37 +00:00
|
|
|
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));
|
2016-03-31 03:42:37 +00:00
|
|
|
break;
|
|
|
|
case 'x':
|
|
|
|
if (input[2] == ' ') {
|
|
|
|
char *out = strdup (input + 3);
|
2017-01-30 18:27:40 +00:00
|
|
|
int len = r_hex_str2bin (input + 3, (ut8*)out);
|
2016-03-31 03:42:37 +00:00
|
|
|
if (len> 0) {
|
2016-03-31 11:21:51 +00:00
|
|
|
r_core_yank_set (core, 0LL, (const ut8*)out, len);
|
2016-03-31 03:42:37 +00:00
|
|
|
} else {
|
|
|
|
eprintf ("Invalid length\n");
|
|
|
|
}
|
|
|
|
free (out);
|
2017-01-25 10:11:14 +00:00
|
|
|
} else {
|
|
|
|
eprintf ("Usage: ywx [hexpairs]\n");
|
|
|
|
}
|
2016-03-31 03:42:37 +00:00
|
|
|
// r_core_yank_write_hex (core, input + 2);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
2017-08-11 09:45:32 +00:00
|
|
|
case 'p': // "yp"
|
2017-01-30 18:27:40 +00:00
|
|
|
r_core_yank_cat (core, r_num_math (core->num, input + 1));
|
2011-02-23 01:10:28 +00:00
|
|
|
break;
|
2017-08-11 09:45:32 +00:00
|
|
|
case 's': // "ys"
|
2017-01-11 15:54:06 +00:00
|
|
|
r_core_yank_cat_string (core, r_num_math (core->num, input + 1));
|
2016-03-31 03:15:20 +00:00
|
|
|
break;
|
2017-01-11 15:54:06 +00:00
|
|
|
case 't': // "wt"
|
|
|
|
if (input[1] == 'f') { // "wtf"
|
|
|
|
const char *file = r_str_chop_ro (input + 2);
|
|
|
|
if (!r_file_dump (file, core->yank_buf->buf, core->yank_buf->length, false)) {
|
|
|
|
eprintf ("Cannot dump to '%s'\n", file);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
r_core_yank_to (core, input + 1);
|
|
|
|
}
|
2009-04-15 18:24:19 +00:00
|
|
|
break;
|
2017-08-11 09:45:32 +00:00
|
|
|
case 'f': // "yf"
|
2017-01-11 15:54:06 +00:00
|
|
|
switch (input[1]) {
|
|
|
|
case ' ': // "wf"
|
|
|
|
r_core_yank_file_ex (core, input + 1);
|
|
|
|
break;
|
|
|
|
case 'a': // "wfa"
|
|
|
|
r_core_yank_file_all (core, input + 2);
|
|
|
|
break;
|
|
|
|
}
|
2014-03-21 04:16:41 +00:00
|
|
|
break;
|
2017-08-11 09:45:32 +00:00
|
|
|
case '\0': // "y"
|
2015-03-22 22:24:13 +00:00
|
|
|
r_core_yank_dump (core, r_num_math (core->num, ""));
|
2009-02-18 12:10:59 +00:00
|
|
|
break;
|
2017-07-27 12:52:17 +00:00
|
|
|
default:
|
|
|
|
r_core_cmd_help (core, help_msg_y);
|
2009-02-18 12:10:59 +00:00
|
|
|
break;
|
|
|
|
}
|
2015-09-14 10:35:38 +00:00
|
|
|
return true;
|
2009-02-18 12:10:59 +00:00
|
|
|
}
|
|
|
|
|
2013-08-17 17:53:04 +00:00
|
|
|
R_API int r_core_run_script (RCore *core, const char *file) {
|
2015-09-14 10:35:38 +00:00
|
|
|
int ret = false;
|
2013-11-09 02:25:43 +00:00
|
|
|
RListIter *iter;
|
2013-09-03 21:47:18 +00:00
|
|
|
RLangPlugin *p;
|
2013-11-09 02:25:43 +00:00
|
|
|
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;
|
2013-11-09 02:25:43 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
r_list_push (core->scriptstack, strdup (file));
|
|
|
|
|
2013-09-03 22:35:48 +00:00
|
|
|
if (!strcmp (file, "-")) {
|
2014-12-19 02:17:28 +00:00
|
|
|
char *out = r_core_editor (core, NULL, NULL);
|
2013-09-03 22:35:48 +00:00
|
|
|
if (out) {
|
|
|
|
ret = r_core_cmd_lines (core, out);
|
|
|
|
free (out);
|
|
|
|
}
|
2013-12-18 23:05:49 +00:00
|
|
|
} else if (r_parse_is_c_file (file)) {
|
2017-06-01 14:57:00 +00:00
|
|
|
char *out = r_parse_c_file (core->anal, file);
|
2013-09-03 21:47:18 +00:00
|
|
|
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;
|
2013-12-18 23:05:49 +00:00
|
|
|
} else {
|
|
|
|
p = r_lang_get_by_extension (core->lang, file);
|
2017-09-04 01:09:12 +00:00
|
|
|
r_core_sysenv_begin (core, NULL);
|
2013-12-18 23:05:49 +00:00
|
|
|
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
|
2015-03-25 02:25:40 +00:00
|
|
|
const char *p = r_str_lchr (file, '.');
|
|
|
|
if (p) {
|
2017-01-30 18:27:40 +00:00
|
|
|
const char *ext = p + 1;
|
2015-03-25 02:25:40 +00:00
|
|
|
/* TODO: handle this inside r_lang_pipe with new APIs */
|
|
|
|
if (!strcmp (ext, "js")) {
|
2017-01-30 18:27:40 +00:00
|
|
|
char *cmd = cmdstr ("node");
|
2015-03-25 02:25:40 +00:00
|
|
|
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
|
2017-01-30 18:27:40 +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);
|
2015-04-08 13:39:25 +00:00
|
|
|
ret = 1;
|
|
|
|
} else if (!strcmp (ext, "lsp")) {
|
2017-01-30 18:27:40 +00:00
|
|
|
char *cmd = cmdstr ("newlisp -n");
|
2015-04-08 13:39:25 +00:00
|
|
|
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;
|
2015-03-25 11:49:10 +00:00
|
|
|
} else if (!strcmp (ext, "es6")) {
|
2015-10-23 00:58:48 +00:00
|
|
|
char *cmd = cmdstr ("babel-node");
|
2015-03-25 11:49:10 +00:00
|
|
|
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;
|
2017-09-04 04:03:37 +00:00
|
|
|
} else if (!strcmp (ext, "vala")) {
|
|
|
|
r_lang_use (core->lang, "vala");
|
|
|
|
r_lang_run_file (core->lang, file);
|
|
|
|
ret = 1;
|
2015-04-30 22:50:25 +00:00
|
|
|
} 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;
|
2015-03-25 02:25:40 +00:00
|
|
|
} else if (!strcmp (ext, "py")) {
|
2015-10-23 00:58:48 +00:00
|
|
|
char *cmd = cmdstr ("python");
|
2015-03-25 02:25:40 +00:00
|
|
|
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);
|
|
|
|
}
|
2013-12-18 23:05:49 +00:00
|
|
|
}
|
2013-08-17 17:53:04 +00:00
|
|
|
}
|
2013-11-09 02:25:43 +00:00
|
|
|
free (r_list_pop (core->scriptstack));
|
|
|
|
return ret;
|
2013-08-17 17:53:04 +00:00
|
|
|
}
|
|
|
|
|
2014-08-28 20:51:03 +00:00
|
|
|
static int cmd_ls(void *data, const char *input) {
|
2017-01-29 22:14:54 +00:00
|
|
|
if (*input) {
|
|
|
|
char *res = r_syscmd_ls (input + 1);
|
|
|
|
if (res) {
|
|
|
|
r_cons_print (res);
|
|
|
|
free (res);
|
|
|
|
}
|
2017-01-03 02:48:55 +00:00
|
|
|
}
|
2014-08-28 20:51:03 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2013-09-03 23:14:35 +00:00
|
|
|
static int cmd_stdin(void *data, const char *input) {
|
|
|
|
RCore *core = (RCore *)data;
|
2017-01-30 18:27:40 +00:00
|
|
|
if (input[0] == '?') {
|
2013-09-03 23:14:35 +00:00
|
|
|
r_cons_printf ("Usage: '-' '.-' '. -' do the same\n");
|
2015-09-14 10:35:38 +00:00
|
|
|
return false;
|
2013-09-03 23:14:35 +00:00
|
|
|
}
|
|
|
|
return r_core_run_script (core, "-");
|
|
|
|
}
|
|
|
|
|
2009-09-25 02:04:51 +00:00
|
|
|
static int cmd_interpret(void *data, const char *input) {
|
2013-08-13 00:28:17 +00:00
|
|
|
char *str, *ptr, *eol, *rbuf, *filter, *inp;
|
2012-11-20 02:59:00 +00:00
|
|
|
const char *host, *port, *cmd;
|
2010-02-22 23:26:13 +00:00
|
|
|
RCore *core = (RCore *)data;
|
2013-08-13 00:28:17 +00:00
|
|
|
|
2011-08-27 18:25:37 +00:00
|
|
|
switch (*input) {
|
2017-08-11 09:45:32 +00:00
|
|
|
case '\0': // "."
|
2011-08-27 18:25:37 +00:00
|
|
|
r_core_cmd_repeat (core, 0);
|
|
|
|
break;
|
2017-08-11 09:45:32 +00:00
|
|
|
case ':': // ".:"
|
2017-01-30 18:27:40 +00:00
|
|
|
if ((ptr = strchr (input + 1, ' '))) {
|
2012-11-05 01:00:34 +00:00
|
|
|
/* .:port cmd */
|
|
|
|
/* .:host:port cmd */
|
2017-01-30 18:27:40 +00:00
|
|
|
cmd = ptr + 1;
|
2012-11-05 01:00:34 +00:00
|
|
|
*ptr = 0;
|
2016-10-09 21:56:52 +00:00
|
|
|
eol = strchr (input + 1, ':');
|
2012-11-05 01:00:34 +00:00
|
|
|
if (eol) {
|
|
|
|
*eol = 0;
|
2017-01-30 18:27:40 +00:00
|
|
|
host = input + 1;
|
|
|
|
port = eol + 1;
|
2012-11-05 01:00:34 +00:00
|
|
|
} else {
|
|
|
|
host = "localhost";
|
2016-10-09 21:56:52 +00:00
|
|
|
port = input + ((input[1] == ':')? 2: 1);
|
2012-11-05 01:00:34 +00:00
|
|
|
}
|
|
|
|
rbuf = r_core_rtr_cmds_query (core, host, port, cmd);
|
|
|
|
if (rbuf) {
|
2016-06-26 04:51:17 +00:00
|
|
|
r_cons_print (rbuf);
|
2012-11-05 01:00:34 +00:00
|
|
|
free (rbuf);
|
|
|
|
}
|
2016-10-09 21:56:52 +00:00
|
|
|
} else {
|
|
|
|
r_core_rtr_cmds (core, input + 1);
|
|
|
|
}
|
2012-11-05 01:00:34 +00:00
|
|
|
break;
|
2017-08-11 09:45:32 +00:00
|
|
|
case '.': // ".." same as \n
|
2017-09-23 00:03:07 +00:00
|
|
|
if (input[1] == '.') { // ... same as \n with e cmd.repeat=true
|
|
|
|
r_core_cmd_repeat (core, 1);
|
|
|
|
} else {
|
|
|
|
char *str = r_core_cmd_str_pipe (core, input);
|
|
|
|
if (str) {
|
|
|
|
r_core_cmd (core, str, 0);
|
|
|
|
free (str);
|
|
|
|
}
|
|
|
|
}
|
2010-03-19 03:02:23 +00:00
|
|
|
break;
|
2017-08-11 09:45:32 +00:00
|
|
|
case '-': // ".-"
|
2017-01-30 18:27:40 +00:00
|
|
|
if (input[1] == '?') {
|
2013-09-03 23:14:35 +00:00
|
|
|
r_cons_printf ("Usage: '-' '.-' '. -' do the same\n");
|
2016-11-20 18:20:14 +00:00
|
|
|
} else {
|
|
|
|
r_core_run_script (core, "-");
|
|
|
|
}
|
2013-09-03 22:35:48 +00:00
|
|
|
break;
|
2017-08-11 09:45:32 +00:00
|
|
|
case ' ': // ". "
|
2016-11-03 10:51:10 +00:00
|
|
|
if (!r_core_run_script (core, input + 1)) {
|
|
|
|
eprintf ("Cannot find script '%s'\n", input + 1);
|
2015-08-09 01:58:53 +00:00
|
|
|
core->num->value = 1;
|
|
|
|
} else {
|
|
|
|
core->num->value = 0;
|
|
|
|
}
|
2009-02-05 21:08:46 +00:00
|
|
|
break;
|
2017-08-11 09:45:32 +00:00
|
|
|
case '!': // ".!"
|
2009-02-05 21:08:46 +00:00
|
|
|
/* from command */
|
2016-04-27 20:30:29 +00:00
|
|
|
r_core_cmd_command (core, input + 1);
|
2009-02-05 21:08:46 +00:00
|
|
|
break;
|
2017-08-11 09:45:32 +00:00
|
|
|
case '(': // ".("
|
2016-04-27 20:30:29 +00:00
|
|
|
r_cmd_macro_call (&core->rcmd->macro, input + 1);
|
2009-02-05 21:08:46 +00:00
|
|
|
break;
|
2017-08-11 09:45:32 +00:00
|
|
|
case '?': // ".?"
|
|
|
|
r_core_cmd_help (core, help_msg_dot);
|
2009-02-16 23:09:40 +00:00
|
|
|
break;
|
|
|
|
default:
|
2017-05-09 12:25:57 +00:00
|
|
|
if (*input >= 0 && *input <= 9) {
|
|
|
|
eprintf ("|ERROR| No .[0..9] to avoid infinite loops\n");
|
|
|
|
break;
|
|
|
|
}
|
2013-08-13 00:28:17 +00:00
|
|
|
inp = strdup (input);
|
|
|
|
filter = strchr (inp, '~');
|
2016-11-03 10:51:10 +00:00
|
|
|
if (filter) {
|
|
|
|
*filter = 0;
|
|
|
|
}
|
2013-08-13 00:28:17 +00:00
|
|
|
ptr = str = r_core_cmd_str (core, inp);
|
2016-11-03 10:51:10 +00:00
|
|
|
if (filter) {
|
|
|
|
*filter = '~';
|
|
|
|
}
|
2016-11-20 18:20:14 +00:00
|
|
|
r_cons_break_push (NULL, NULL);
|
2016-11-03 10:51:10 +00:00
|
|
|
if (ptr) {
|
|
|
|
for (;;) {
|
2016-11-20 18:20:14 +00:00
|
|
|
if (r_cons_is_breaked ()) {
|
|
|
|
break;
|
|
|
|
}
|
2016-11-03 10:51:10 +00:00
|
|
|
eol = strchr (ptr, '\n');
|
2017-09-23 00:03:07 +00:00
|
|
|
if (eol) {
|
|
|
|
*eol = '\0';
|
|
|
|
}
|
2016-11-03 10:51:10 +00:00
|
|
|
if (*ptr) {
|
2017-03-16 21:29:49 +00:00
|
|
|
char *p = r_str_append (strdup (ptr), filter);
|
2016-11-03 10:51:10 +00:00
|
|
|
r_core_cmd0 (core, p);
|
|
|
|
free (p);
|
|
|
|
}
|
2017-09-23 00:03:07 +00:00
|
|
|
if (!eol) {
|
|
|
|
break;
|
|
|
|
}
|
2016-11-03 10:51:10 +00:00
|
|
|
ptr = eol + 1;
|
2013-08-13 00:28:17 +00:00
|
|
|
}
|
2009-02-16 23:09:40 +00:00
|
|
|
}
|
2016-11-20 18:20:14 +00:00
|
|
|
r_cons_break_pop ();
|
2010-02-22 23:26:13 +00:00
|
|
|
free (str);
|
2013-08-13 00:28:17 +00:00
|
|
|
free (inp);
|
2009-02-05 21:08:46 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2014-03-07 00:26:11 +00:00
|
|
|
static int callback_foreach_kv (void *user, const char *k, const char *v) {
|
|
|
|
r_cons_printf ("%s=%s\n", k, v);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2014-03-05 02:52:42 +00:00
|
|
|
static int cmd_kuery(void *data, const char *input) {
|
|
|
|
char buf[1024], *out;
|
|
|
|
RCore *core = (RCore*)data;
|
|
|
|
const char *sp, *p = "[sdb]> ";
|
2017-01-30 18:27:40 +00:00
|
|
|
const int buflen = sizeof (buf) - 1;
|
2014-03-07 00:26:11 +00:00
|
|
|
Sdb *s = core->sdb;
|
2014-03-05 02:52:42 +00:00
|
|
|
|
2014-03-07 00:26:11 +00:00
|
|
|
switch (input[0]) {
|
|
|
|
case ' ':
|
2017-01-30 18:27:40 +00:00
|
|
|
out = sdb_querys (s, NULL, 0, input + 1);
|
2016-06-26 04:51:17 +00:00
|
|
|
if (out) {
|
|
|
|
r_cons_println (out);
|
|
|
|
}
|
2014-03-07 00:26:11 +00:00
|
|
|
free (out);
|
|
|
|
break;
|
2017-01-30 18:27:40 +00:00
|
|
|
//case 's': r_pair_save (s, input + 3); break;
|
|
|
|
//case 'l': r_pair_load (sdb, input + 3); break;
|
2014-03-07 00:26:11 +00:00
|
|
|
case '\0':
|
|
|
|
sdb_foreach (s, callback_foreach_kv, NULL);
|
|
|
|
break;
|
|
|
|
// TODO: add command to list all namespaces // sdb_ns_foreach ?
|
|
|
|
case 's':
|
2016-09-19 15:44:22 +00:00
|
|
|
if (core->http_up) {
|
2015-09-14 10:35:38 +00:00
|
|
|
return false;
|
2016-09-19 15:44:22 +00:00
|
|
|
}
|
|
|
|
if (!r_config_get_i (core->config, "scr.interactive")) {
|
2015-09-14 10:35:38 +00:00
|
|
|
return false;
|
2016-09-19 15:44:22 +00:00
|
|
|
}
|
2017-01-30 18:27:40 +00:00
|
|
|
if (input[1] == ' ') {
|
|
|
|
char *n, *o, *p = strdup (input + 2);
|
2014-03-12 01:44:49 +00:00
|
|
|
// TODO: slash split here? or inside sdb_ns ?
|
2015-11-22 10:27:45 +00:00
|
|
|
for (n = o = p; n; o = n) {
|
2014-03-12 01:44:49 +00:00
|
|
|
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);
|
2014-03-12 01:44:49 +00:00
|
|
|
}
|
|
|
|
free (p);
|
|
|
|
}
|
2014-03-07 00:26:11 +00:00
|
|
|
if (!s) s = core->sdb;
|
|
|
|
for (;;) {
|
|
|
|
r_line_set_prompt (p);
|
2017-09-18 14:18:12 +00:00
|
|
|
if (r_cons_fgets (buf, buflen, 0, NULL) < 1) {
|
2014-03-07 00:26:11 +00:00
|
|
|
break;
|
2017-09-18 14:18:12 +00:00
|
|
|
}
|
|
|
|
if (!*buf) {
|
|
|
|
break;
|
|
|
|
}
|
2014-03-07 00:26:11 +00:00
|
|
|
out = sdb_querys (s, NULL, 0, buf);
|
2016-06-26 04:51:17 +00:00
|
|
|
if (out) {
|
|
|
|
r_cons_println (out);
|
|
|
|
}
|
2014-03-07 00:26:11 +00:00
|
|
|
}
|
|
|
|
break;
|
2014-12-20 23:54:42 +00:00
|
|
|
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;
|
|
|
|
}
|
2014-12-20 23:54:42 +00:00
|
|
|
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;
|
|
|
|
}
|
2014-12-20 23:54:42 +00:00
|
|
|
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");
|
2014-12-20 23:54:42 +00:00
|
|
|
} else eprintf ("Missing sdb namespace\n");
|
|
|
|
free (fn);
|
|
|
|
} else {
|
2016-08-24 14:30:23 +00:00
|
|
|
eprintf ("Usage: ko [file] [namespace]\n");
|
2014-12-20 23:54:42 +00:00
|
|
|
}
|
|
|
|
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;
|
|
|
|
}
|
2014-12-20 23:54:42 +00:00
|
|
|
if (input[1] == ' ') {
|
2017-01-30 18:27:40 +00:00
|
|
|
char *fn = strdup (input + 2);
|
2014-12-20 23:54:42 +00:00
|
|
|
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");
|
2014-12-20 23:54:42 +00:00
|
|
|
}
|
|
|
|
break;
|
2016-01-10 11:10:38 +00:00
|
|
|
case '?': {
|
2017-07-27 12:52:17 +00:00
|
|
|
r_core_cmd_help (core, help_msg_k);
|
2014-06-20 16:35:49 +00:00
|
|
|
}
|
2014-03-07 00:26:11 +00:00
|
|
|
break;
|
2014-03-05 02:52:42 +00:00
|
|
|
}
|
|
|
|
|
2016-09-19 15:44:22 +00:00
|
|
|
if (input[0] == '\0') {
|
2014-06-20 17:45:22 +00:00
|
|
|
/* nothing more to do, the command has been parsed. */
|
|
|
|
return 0;
|
2016-09-19 15:44:22 +00:00
|
|
|
}
|
2014-06-20 17:45:22 +00:00
|
|
|
|
2016-09-19 15:44:22 +00:00
|
|
|
sp = strchr (input + 1, ' ');
|
2014-03-05 02:52:42 +00:00
|
|
|
if (sp) {
|
|
|
|
char *inp = strdup (input);
|
2017-01-30 18:27:40 +00:00
|
|
|
inp [(size_t)(sp - input)] = 0;
|
|
|
|
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) {
|
2016-06-26 04:51:17 +00:00
|
|
|
r_cons_println (out);
|
2014-04-29 22:15:36 +00:00
|
|
|
free (out);
|
|
|
|
}
|
2014-03-05 02:52:42 +00:00
|
|
|
free (inp);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2012-02-27 01:40:27 +00:00
|
|
|
static int cmd_bsize(void *data, const char *input) {
|
2012-06-22 01:49:25 +00:00
|
|
|
ut64 n;
|
2012-02-27 01:40:27 +00:00
|
|
|
RFlagItem *flag;
|
2010-03-30 21:12:19 +00:00
|
|
|
RCore *core = (RCore *)data;
|
2012-02-27 01:40:27 +00:00
|
|
|
switch (input[0]) {
|
2017-08-21 07:53:23 +00:00
|
|
|
case 'm': // "bm"
|
2017-01-30 18:27:40 +00:00
|
|
|
n = r_num_math (core->num, input + 1);
|
|
|
|
if (n > 1) core->blocksize_max = n;
|
2013-10-19 21:10:08 +00:00
|
|
|
else r_cons_printf ("0x%x\n", (ut32)core->blocksize_max);
|
|
|
|
break;
|
2017-08-21 07:53:23 +00:00
|
|
|
case '+': // "b+"
|
2017-01-30 18:27:40 +00:00
|
|
|
n = r_num_math (core->num, input + 1);
|
|
|
|
r_core_block_size (core, core->blocksize + n);
|
2012-06-22 01:49:25 +00:00
|
|
|
break;
|
2017-08-21 07:53:23 +00:00
|
|
|
case '-': // "b-"
|
2017-01-30 18:27:40 +00:00
|
|
|
n = r_num_math (core->num, input + 1);
|
|
|
|
r_core_block_size (core, core->blocksize - n);
|
2012-06-22 01:49:25 +00:00
|
|
|
break;
|
2017-08-21 07:53:23 +00:00
|
|
|
case 'f': // "bf"
|
2017-01-30 18:27:40 +00:00
|
|
|
if (input[1] == ' ') {
|
|
|
|
flag = r_flag_get (core->flags, input + 2);
|
2016-09-19 15:44:22 +00:00
|
|
|
if (flag) {
|
2012-02-27 01:40:27 +00:00
|
|
|
r_core_block_size (core, flag->size);
|
2016-09-19 15:44:22 +00:00
|
|
|
} else {
|
2017-01-30 18:27:40 +00:00
|
|
|
eprintf ("bf: cannot find flag named '%s'\n", input + 2);
|
2016-09-19 15:44:22 +00:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
eprintf ("Usage: bf [flagname]\n");
|
|
|
|
}
|
2011-04-18 22:59:16 +00:00
|
|
|
break;
|
2017-08-21 07:53:23 +00:00
|
|
|
case '\0': // "b"
|
2012-02-27 01:40:27 +00:00
|
|
|
r_cons_printf ("0x%x\n", core->blocksize);
|
2011-11-16 01:05:23 +00:00
|
|
|
break;
|
2017-08-21 07:53:23 +00:00
|
|
|
case '?': // "b?"
|
2017-07-27 12:52:17 +00:00
|
|
|
r_core_cmd_help (core, help_msg_b);
|
2011-11-16 01:05:23 +00:00
|
|
|
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));
|
2010-01-31 13:22:27 +00:00
|
|
|
break;
|
2012-02-27 01:40:27 +00:00
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
2010-02-05 11:21:37 +00:00
|
|
|
|
2012-02-27 01:40:27 +00:00
|
|
|
static int cmd_resize(void *data, const char *input) {
|
2010-02-28 21:58:21 +00:00
|
|
|
RCore *core = (RCore *)data;
|
2017-01-30 18:27:40 +00:00
|
|
|
ut64 oldsize, newsize = 0;
|
2012-02-27 01:40:27 +00:00
|
|
|
st64 delta = 0;
|
2014-06-23 23:04:38 +00:00
|
|
|
int grow, ret;
|
2009-03-09 13:08:53 +00:00
|
|
|
|
2017-08-22 07:42:16 +00:00
|
|
|
if (core->file)
|
|
|
|
oldsize = r_io_fd_size (core->io, core->file->fd);
|
2014-10-30 23:00:43 +00:00
|
|
|
else oldsize = 0;
|
2011-09-02 01:45:50 +00:00
|
|
|
switch (*input) {
|
2017-08-21 07:53:23 +00:00
|
|
|
case '2': // "r2"
|
2015-10-30 00:45:49 +00:00
|
|
|
// TODO: use argv[0] instead of 'radare2'
|
|
|
|
r_sys_cmdf ("radare%s", input);
|
|
|
|
return true;
|
2017-08-21 07:53:23 +00:00
|
|
|
case 'm': // "rm"
|
2017-01-30 18:27:40 +00:00
|
|
|
if (input[1] == ' ')
|
|
|
|
r_file_rm (input + 2);
|
2014-05-19 00:52:51 +00:00
|
|
|
else eprintf ("Usage: rm [file] # removes a file\n");
|
2015-09-14 10:35:38 +00:00
|
|
|
return true;
|
2017-08-22 07:42:16 +00:00
|
|
|
case '\0':
|
|
|
|
if (core->file) {
|
2015-06-30 09:34:38 +00:00
|
|
|
if (oldsize != -1) {
|
|
|
|
r_cons_printf ("%"PFMT64d"\n", oldsize);
|
|
|
|
}
|
|
|
|
}
|
2015-09-14 10:35:38 +00:00
|
|
|
return true;
|
2017-08-21 07:53:23 +00:00
|
|
|
case '+': // "r+"
|
|
|
|
case '-': // "r-"
|
2014-05-19 00:52:51 +00:00
|
|
|
delta = (st64)r_num_math (core->num, input);
|
|
|
|
newsize = oldsize + delta;
|
|
|
|
break;
|
2017-08-21 07:53:23 +00:00
|
|
|
case ' ': // "r "
|
2017-01-30 18:27:40 +00:00
|
|
|
newsize = r_num_math (core->num, input + 1);
|
|
|
|
if (newsize == 0) {
|
|
|
|
if (input[1] == '0')
|
2014-05-19 00:52:51 +00:00
|
|
|
eprintf ("Invalid size\n");
|
2015-09-14 10:35:38 +00:00
|
|
|
return false;
|
2014-05-19 00:52:51 +00:00
|
|
|
}
|
|
|
|
break;
|
2017-08-21 07:53:23 +00:00
|
|
|
case '?': // "r?"
|
2014-05-19 00:52:51 +00:00
|
|
|
default:
|
2017-07-27 12:52:17 +00:00
|
|
|
r_core_cmd_help (core, help_msg_r);
|
2015-09-14 10:35:38 +00:00
|
|
|
return true;
|
2010-03-04 00:46:25 +00:00
|
|
|
}
|
2010-08-22 16:41:57 +00:00
|
|
|
|
2012-02-27 01:40:27 +00:00
|
|
|
grow = (newsize > oldsize);
|
|
|
|
if (grow) {
|
2014-06-23 23:04:38 +00:00
|
|
|
ret = r_io_resize (core->io, newsize);
|
2017-01-30 18:27:40 +00:00
|
|
|
if (ret < 1)
|
2014-06-23 23:04:38 +00:00
|
|
|
eprintf ("r_io_resize: cannot resize\n");
|
2010-08-22 16:41:57 +00:00
|
|
|
}
|
|
|
|
|
2012-02-27 01:40:27 +00:00
|
|
|
if (delta && core->offset < newsize)
|
|
|
|
r_io_shift (core->io, core->offset, grow?newsize:oldsize, delta);
|
2011-07-05 23:29:18 +00:00
|
|
|
|
2012-02-27 01:40:27 +00:00
|
|
|
if (!grow) {
|
2014-06-23 23:04:38 +00:00
|
|
|
ret = r_io_resize (core->io, newsize);
|
2017-01-30 18:27:40 +00:00
|
|
|
if (ret < 1)
|
2014-06-23 23:04:38 +00:00
|
|
|
eprintf ("r_io_resize: cannot resize\n");
|
2011-07-05 23:29:18 +00:00
|
|
|
}
|
|
|
|
|
2012-02-27 01:40:27 +00:00
|
|
|
if (newsize < core->offset+core->blocksize ||
|
2017-01-30 18:27:40 +00:00
|
|
|
oldsize < core->offset + core->blocksize) {
|
2016-08-15 18:56:23 +00:00
|
|
|
r_core_block_read (core);
|
2012-09-21 00:25:44 +00:00
|
|
|
}
|
2015-09-14 10:35:38 +00:00
|
|
|
return true;
|
2011-10-11 00:13:15 +00:00
|
|
|
}
|
|
|
|
|
2012-02-27 01:40:27 +00:00
|
|
|
static int cmd_visual(void *data, const char *input) {
|
2012-12-22 01:37:01 +00:00
|
|
|
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
|
|
|
}
|
2014-11-01 03:46:33 +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;
|
2014-11-01 03:46:33 +00:00
|
|
|
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);
|
2014-11-01 03:46:33 +00:00
|
|
|
task->msg->res = res;
|
2016-01-03 01:32:56 +00:00
|
|
|
task->state = 'd';
|
2014-11-01 03:46:33 +00:00
|
|
|
eprintf ("Task %d finished\n", task->id);
|
|
|
|
// TODO: run callback and pass result
|
2014-11-02 01:01:09 +00:00
|
|
|
return 0;
|
2014-11-01 03:46:33 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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);
|
2014-11-01 03:46:33 +00:00
|
|
|
break;
|
|
|
|
case '&':
|
2017-01-30 18:27:40 +00:00
|
|
|
if (input[1] == '&') {
|
2014-11-01 03:46:33 +00:00
|
|
|
// wait until ^C
|
|
|
|
} else {
|
2017-01-30 18:27:40 +00:00
|
|
|
int tid = r_num_math (core->num, input + 1);
|
2014-11-01 03:46:33 +00:00
|
|
|
if (tid) {
|
|
|
|
RCoreTask *task = r_core_task_get (core, tid);
|
|
|
|
if (task) {
|
2014-11-02 01:01:09 +00:00
|
|
|
r_core_task_join (core, task);
|
2014-11-01 03:46:33 +00:00
|
|
|
} else eprintf ("Cannot find task\n");
|
|
|
|
} else {
|
|
|
|
r_core_task_run (core, NULL);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case '=': {
|
2017-01-30 18:27:40 +00:00
|
|
|
int tid = r_num_math (core->num, input + 1);
|
2014-11-01 03:46:33 +00:00
|
|
|
if (tid) {
|
|
|
|
RCoreTask *task = r_core_task_get (core, tid);
|
|
|
|
if (task) {
|
2014-11-02 01:01:09 +00:00
|
|
|
r_cons_printf ("Task %d Status %c Command %s\n",
|
|
|
|
task->id, task->state, task->msg->text);
|
|
|
|
if (task->msg->res)
|
2016-06-26 04:51:17 +00:00
|
|
|
r_cons_println (task->msg->res);
|
2014-11-01 03:46:33 +00:00
|
|
|
} else eprintf ("Cannot find task\n");
|
|
|
|
} else {
|
|
|
|
r_core_task_list (core, 1);
|
|
|
|
}}
|
|
|
|
break;
|
|
|
|
case '+':
|
2017-01-30 18:27:40 +00:00
|
|
|
r_core_task_add (core, r_core_task_new (core, input + 1, (RCoreTaskCallback)task_finished, core));
|
2014-11-01 03:46:33 +00:00
|
|
|
break;
|
|
|
|
case '-':
|
2017-01-30 18:27:40 +00:00
|
|
|
if (input[1] == '*') {
|
2014-11-01 03:46:33 +00:00
|
|
|
r_core_task_del (core, -1);
|
|
|
|
} else {
|
2017-01-30 18:27:40 +00:00
|
|
|
r_core_task_del (core, r_num_math (core->num, input + 1));
|
2014-11-01 03:46:33 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case '?':
|
|
|
|
{
|
2017-03-02 09:39:11 +00:00
|
|
|
helpCmdTasks (core);
|
2014-11-01 03:46:33 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case ' ':
|
|
|
|
{
|
2017-01-30 18:27:40 +00:00
|
|
|
int tid = r_num_math (core->num, input + 1);
|
2014-11-02 01:01:09 +00:00
|
|
|
if (tid) {
|
|
|
|
RCoreTask *task = r_core_task_get (core, tid);
|
|
|
|
if (task) {
|
|
|
|
r_core_task_join (core, task);
|
2016-12-12 19:21:20 +00:00
|
|
|
} else {
|
|
|
|
eprintf ("Cannot find task\n");
|
|
|
|
}
|
2014-11-02 01:01:09 +00:00
|
|
|
} else {
|
|
|
|
RCoreTask *task = r_core_task_add (core, r_core_task_new (
|
2017-01-30 18:27:40 +00:00
|
|
|
core, input + 1, (RCoreTaskCallback)task_finished, core));
|
2014-11-02 01:01:09 +00:00
|
|
|
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);
|
2014-11-01 03:46:33 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
eprintf ("&?\n");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return 0;
|
2012-02-27 01:40:27 +00:00
|
|
|
}
|
|
|
|
|
2013-12-14 01:47:25 +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;
|
2013-12-14 01:47:25 +00:00
|
|
|
char *str, *eq;
|
2017-01-30 18:27:40 +00:00
|
|
|
while (*input == ' ') input++;
|
|
|
|
if (!*input || *input == '?') {
|
2017-07-27 12:52:17 +00:00
|
|
|
r_core_cmd_help (core, help_msg_star);
|
2013-12-14 01:47:25 +00:00
|
|
|
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);
|
2013-12-14 01:47:25 +00:00
|
|
|
} else {
|
2014-06-20 16:35:49 +00:00
|
|
|
ret = r_core_cmdf (core, "wx %s@%s", eq, str);
|
2013-12-14 01:47:25 +00:00
|
|
|
}
|
|
|
|
} else {
|
2014-06-20 16:35:49 +00:00
|
|
|
ret = r_core_cmdf (core, "?v [%s]", input);
|
2013-12-14 01:47:25 +00:00
|
|
|
}
|
|
|
|
free (str);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int cmd_env(void *data, const char *input) {
|
2017-04-16 07:42:30 +00:00
|
|
|
RCore *core = (RCore*)data;
|
|
|
|
int ret = true;
|
|
|
|
switch (*input) {
|
|
|
|
case '?':
|
2017-07-27 12:52:17 +00:00
|
|
|
r_core_cmd_help (core, help_msg_percent);
|
2017-04-16 07:42:30 +00:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
ret = r_core_cmdf (core, "env %s", input);
|
|
|
|
}
|
|
|
|
return ret;
|
2013-12-14 01:47:25 +00:00
|
|
|
}
|
|
|
|
|
2012-02-27 01:40:27 +00:00
|
|
|
static int cmd_system(void *data, const char *input) {
|
2013-03-14 01:32:53 +00:00
|
|
|
RCore *core = (RCore*)data;
|
|
|
|
ut64 n;
|
2012-02-27 01:40:27 +00:00
|
|
|
int ret = 0;
|
2012-07-01 22:38:02 +00:00
|
|
|
switch (*input) {
|
2017-06-14 15:31:57 +00:00
|
|
|
case '-':
|
|
|
|
if (input[1]) {
|
|
|
|
r_line_hist_free();
|
|
|
|
r_line_hist_save (R2_HOMEDIR"/history");
|
|
|
|
} else {
|
|
|
|
r_line_hist_free();
|
|
|
|
}
|
|
|
|
break;
|
2015-07-09 21:20:48 +00:00
|
|
|
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;
|
2016-06-26 04:51:17 +00:00
|
|
|
r_cons_println (r_str_bool (core->cmdremote));
|
2015-07-09 21:20:48 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
2014-04-27 23:27:45 +00:00
|
|
|
case '!':
|
2015-03-21 02:43:07 +00:00
|
|
|
if (r_sandbox_enable (0)) {
|
|
|
|
eprintf ("This command is disabled in sandbox mode\n");
|
|
|
|
return 0;
|
|
|
|
}
|
2013-07-17 01:51:53 +00:00
|
|
|
if (input[1]) {
|
|
|
|
int olen;
|
|
|
|
char *out = NULL;
|
|
|
|
char *cmd = r_core_sysenv_begin (core, input);
|
|
|
|
if (cmd) {
|
2017-01-30 18:27:40 +00:00
|
|
|
ret = r_sys_cmd_str_full (cmd + 1, NULL, &out, &olen, NULL);
|
2013-07-17 01:51:53 +00:00
|
|
|
r_core_sysenv_end (core, input);
|
|
|
|
r_cons_memcat (out, olen);
|
|
|
|
free (out);
|
|
|
|
free (cmd);
|
|
|
|
} //else eprintf ("Error setting up system environment\n");
|
|
|
|
} else {
|
2013-07-17 17:34:27 +00:00
|
|
|
eprintf ("History saved to "R2_HOMEDIR"/history\n");
|
2013-07-17 01:51:53 +00:00
|
|
|
r_line_hist_save (R2_HOMEDIR"/history");
|
2012-07-01 22:38:02 +00:00
|
|
|
}
|
|
|
|
break;
|
2013-03-14 01:32:53 +00:00
|
|
|
case '\0':
|
|
|
|
r_line_hist_list ();
|
|
|
|
break;
|
2012-07-01 22:38:02 +00:00
|
|
|
case '?':
|
2014-06-20 11:25:17 +00:00
|
|
|
r_core_sysenv_help (core);
|
2012-07-01 22:38:02 +00:00
|
|
|
break;
|
|
|
|
default:
|
2013-12-17 22:45:03 +00:00
|
|
|
n = atoi (input);
|
2017-01-30 18:27:40 +00:00
|
|
|
if (*input == '0' || n > 0) {
|
2013-04-02 10:45:16 +00:00
|
|
|
const char *cmd = r_line_hist_get (n);
|
2013-03-14 01:32:53 +00:00
|
|
|
if (cmd) r_core_cmd0 (core, cmd);
|
2013-09-30 00:19:19 +00:00
|
|
|
//else eprintf ("Error setting up system environment\n");
|
2013-03-14 01:32:53 +00:00
|
|
|
} 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");
|
2012-07-01 22:38:02 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
2012-02-27 01:40:27 +00:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2017-08-03 14:46:06 +00:00
|
|
|
#if __WINDOWS__ && !__CYGWIN__
|
|
|
|
static void r_w32_cmd_pipe(RCore *core, char *radare_cmd, char *shell_cmd) {
|
|
|
|
STARTUPINFO si = {0};
|
|
|
|
PROCESS_INFORMATION pi = {0};
|
|
|
|
SECURITY_ATTRIBUTES sa;
|
|
|
|
HANDLE pipe[2] = {NULL, NULL};
|
|
|
|
int fd_out = -1, cons_out = -1;
|
|
|
|
char *_shell_cmd;
|
|
|
|
|
|
|
|
sa.nLength = sizeof (SECURITY_ATTRIBUTES);
|
|
|
|
sa.bInheritHandle = TRUE;
|
|
|
|
sa.lpSecurityDescriptor = NULL;
|
|
|
|
if (!CreatePipe (&pipe[0], &pipe[1], &sa, 0)) {
|
|
|
|
r_sys_perror ("r_w32_cmd_pipe/CreatePipe");
|
|
|
|
goto err_r_w32_cmd_pipe;
|
|
|
|
}
|
|
|
|
if (!SetHandleInformation (pipe[1], HANDLE_FLAG_INHERIT, 0)) {
|
|
|
|
r_sys_perror ("r_w32_cmd_pipe/SetHandleInformation");
|
|
|
|
goto err_r_w32_cmd_pipe;
|
|
|
|
}
|
|
|
|
si.hStdError = GetStdHandle (STD_ERROR_HANDLE);
|
|
|
|
si.hStdOutput = GetStdHandle (STD_OUTPUT_HANDLE);
|
|
|
|
si.hStdInput = pipe[0];
|
|
|
|
si.dwFlags |= STARTF_USESTDHANDLES;
|
|
|
|
si.cb = sizeof (si);
|
|
|
|
_shell_cmd = shell_cmd;
|
|
|
|
while (*_shell_cmd && isspace (*_shell_cmd)) {
|
|
|
|
_shell_cmd++;
|
|
|
|
}
|
|
|
|
// exec windows process
|
|
|
|
if (!CreateProcess (NULL, _shell_cmd, NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi)) {
|
|
|
|
r_sys_perror ("r_w32_cmd_pipe/CreateProcess");
|
|
|
|
goto err_r_w32_cmd_pipe;
|
|
|
|
}
|
|
|
|
fd_out = _open_osfhandle ((intptr_t)pipe[1], _O_WRONLY|_O_TEXT);
|
|
|
|
if (fd_out == -1) {
|
|
|
|
perror ("_open_osfhandle");
|
|
|
|
goto err_r_w32_cmd_pipe;
|
|
|
|
}
|
|
|
|
cons_out = dup (1);
|
|
|
|
dup2 (fd_out, 1);
|
|
|
|
// exec radare command
|
|
|
|
r_core_cmd (core, radare_cmd, 0);
|
|
|
|
r_cons_flush ();
|
|
|
|
close (1);
|
|
|
|
close (fd_out);
|
|
|
|
fd_out = -1;
|
|
|
|
WaitForSingleObject (pi.hProcess, INFINITE);
|
|
|
|
err_r_w32_cmd_pipe:
|
|
|
|
if (pi.hProcess) {
|
|
|
|
CloseHandle (pi.hProcess);
|
|
|
|
}
|
|
|
|
if (pi.hThread) {
|
|
|
|
CloseHandle (pi.hThread);
|
|
|
|
}
|
|
|
|
if (pipe[0]) {
|
|
|
|
CloseHandle (pipe[0]);
|
|
|
|
}
|
|
|
|
if (pipe[1]) {
|
|
|
|
CloseHandle (pipe[1]);
|
|
|
|
}
|
|
|
|
if (fd_out != -1) {
|
|
|
|
close (fd_out);
|
|
|
|
}
|
|
|
|
if (cons_out != -1) {
|
|
|
|
dup2 (cons_out, 1);
|
|
|
|
close (cons_out);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2012-09-06 01:12:54 +00:00
|
|
|
R_API int r_core_cmd_pipe(RCore *core, char *radare_cmd, char *shell_cmd) {
|
2015-08-04 12:17:09 +00:00
|
|
|
#if __UNIX__ || __CYGWIN__
|
2015-01-22 01:22:29 +00:00
|
|
|
int stdout_fd, fds[2];
|
2015-06-11 10:54:39 +00:00
|
|
|
int child;
|
2012-07-01 22:38:02 +00:00
|
|
|
#endif
|
2015-06-11 10:54:39 +00:00
|
|
|
int si, olen, ret = -1, pipecolor = -1;
|
2013-09-26 23:38:49 +00:00
|
|
|
char *str, *out = NULL;
|
2014-10-17 22:25:55 +00:00
|
|
|
|
2014-06-14 01:01:27 +00:00
|
|
|
if (r_sandbox_enable (0)) {
|
|
|
|
eprintf ("Pipes are not allowed in sandbox mode\n");
|
|
|
|
return -1;
|
|
|
|
}
|
2015-01-16 23:09:19 +00:00
|
|
|
si = r_config_get_i (core->config, "scr.interactive");
|
|
|
|
r_config_set_i (core->config, "scr.interactive", 0);
|
2012-11-13 10:42:21 +00:00
|
|
|
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);
|
|
|
|
}
|
2012-07-01 22:38:02 +00:00
|
|
|
if (*shell_cmd=='!') {
|
2017-06-10 10:39:04 +00:00
|
|
|
r_cons_grep_parsecmd (shell_cmd, "\"");
|
2013-09-26 23:38:49 +00:00
|
|
|
olen = 0;
|
|
|
|
out = NULL;
|
2012-07-01 22:38:02 +00:00
|
|
|
// TODO: implement foo
|
|
|
|
str = r_core_cmd_str (core, radare_cmd);
|
2016-10-25 10:03:55 +00:00
|
|
|
r_sys_cmd_str_full (shell_cmd + 1, str, &out, &olen, NULL);
|
2014-04-30 19:02:22 +00:00
|
|
|
free (str);
|
2012-07-01 22:38:02 +00:00
|
|
|
r_cons_memcat (out, olen);
|
|
|
|
free (out);
|
2012-11-13 10:42:21 +00:00
|
|
|
ret = 0;
|
2012-07-01 22:38:02 +00:00
|
|
|
}
|
2015-08-04 12:17:09 +00:00
|
|
|
#if __UNIX__ || __CYGWIN__
|
2011-10-06 23:16:45 +00:00
|
|
|
radare_cmd = (char*)r_str_trim_head (radare_cmd);
|
|
|
|
shell_cmd = (char*)r_str_trim_head (shell_cmd);
|
2012-07-01 22:38:02 +00:00
|
|
|
|
2013-11-15 00:54:14 +00:00
|
|
|
signal (SIGPIPE, SIG_IGN);
|
2012-07-01 22:38:02 +00:00
|
|
|
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);
|
|
|
|
}
|
2009-12-31 00:27:03 +00:00
|
|
|
}
|
2017-08-03 14:46:06 +00:00
|
|
|
#elif __WINDOWS__
|
|
|
|
r_w32_cmd_pipe (core, radare_cmd, shell_cmd);
|
2010-01-15 16:02:04 +00:00
|
|
|
#else
|
2017-05-09 12:25:57 +00:00
|
|
|
#ifdef _MSC_VER
|
|
|
|
#pragma message ("r_core_cmd_pipe UNIMPLEMENTED FOR THIS PLATFORM")
|
|
|
|
#else
|
2010-01-15 16:02:04 +00:00
|
|
|
#warning r_core_cmd_pipe UNIMPLEMENTED FOR THIS PLATFORM
|
2017-05-09 12:25:57 +00:00
|
|
|
#endif
|
2010-08-22 22:48:44 +00:00
|
|
|
eprintf ("r_core_cmd_pipe: unimplemented for this platform\n");
|
2010-01-15 16:02:04 +00:00
|
|
|
#endif
|
2012-11-13 10:42:21 +00:00
|
|
|
if (pipecolor != -1)
|
|
|
|
r_config_set_i (core->config, "scr.color", pipecolor);
|
2015-01-16 23:09:19 +00:00
|
|
|
r_config_set_i (core->config, "scr.interactive", si);
|
2012-11-13 10:42:21 +00:00
|
|
|
return ret;
|
2009-12-31 00:27:03 +00:00
|
|
|
}
|
|
|
|
|
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 ("");
|
2016-02-25 09:28:54 +00:00
|
|
|
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);
|
2017-03-19 00:20:06 +00:00
|
|
|
if (!kv) {
|
|
|
|
break;
|
|
|
|
}
|
2015-07-15 00:02:11 +00:00
|
|
|
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);
|
2017-01-30 18:27:40 +00:00
|
|
|
r_config_set (core->config, kv, eq + 1);
|
2015-07-15 00:02:11 +00:00
|
|
|
*eq = '=';
|
|
|
|
} else {
|
|
|
|
eprintf ("Missing '=' in e: expression (%s)\n", kv);
|
|
|
|
}
|
|
|
|
}
|
2017-03-19 00:20:06 +00:00
|
|
|
res = r_strbuf_drain (buf);
|
2015-07-15 00:02:11 +00:00
|
|
|
free (s);
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
2014-11-29 00:41:58 +00:00
|
|
|
static int r_core_cmd_subst_i(RCore *core, char *cmd, char* colon);
|
2010-03-30 21:12:19 +00:00
|
|
|
static int r_core_cmd_subst(RCore *core, char *cmd) {
|
2015-01-17 03:23:07 +00:00
|
|
|
int ret = 0, rep = atoi (cmd), orep;
|
2014-10-17 22:25:55 +00:00
|
|
|
char *cmt, *colon = NULL, *icmd = strdup (cmd);
|
2015-01-17 03:23:07 +00:00
|
|
|
const char *cmdrep = NULL;
|
2012-02-27 01:02:44 +00:00
|
|
|
cmd = r_str_trim_head_tail (icmd);
|
2016-11-06 20:54:50 +00:00
|
|
|
// lines starting with # are ignored (never reach cmd_hash()), except #! and #?
|
2017-09-18 14:18:12 +00:00
|
|
|
if (!*cmd) {
|
2017-09-20 11:35:12 +00:00
|
|
|
r_core_cmd_repeat (core, true);
|
|
|
|
ret = r_core_cmd_nullcallback (core);
|
|
|
|
goto beach;
|
2017-09-18 14:18:12 +00:00
|
|
|
}
|
2016-11-06 20:54:50 +00:00
|
|
|
if (!icmd || (cmd[0] == '#' && cmd[1] != '!' && cmd[1] != '?')) {
|
2014-01-18 22:02:53 +00:00
|
|
|
goto beach;
|
2017-05-22 17:37:48 +00:00
|
|
|
}
|
2017-01-30 18:27:40 +00:00
|
|
|
cmt = *icmd ? strchr (icmd + 1, '#'): NULL;
|
|
|
|
if (cmt && (cmt[1] == ' ' || cmt[1] == '\t')) {
|
2012-08-13 11:16:06 +00:00
|
|
|
*cmt = 0;
|
2016-10-19 11:38:29 +00:00
|
|
|
}
|
2013-02-25 01:35:16 +00:00
|
|
|
if (*cmd != '"') {
|
2014-10-17 22:25:55 +00:00
|
|
|
if (!strchr (cmd, '\'')) { // allow | awk '{foo;bar}' // ignore ; if there's a single quote
|
2016-10-19 11:38:29 +00:00
|
|
|
if ((colon = strchr (cmd, ';'))) {
|
2014-10-17 22:25:55 +00:00
|
|
|
*colon = 0;
|
2016-10-19 11:38:29 +00:00
|
|
|
}
|
2014-10-17 22:25:55 +00:00
|
|
|
}
|
2016-09-03 23:05:14 +00:00
|
|
|
} else {
|
|
|
|
colon = NULL;
|
|
|
|
}
|
|
|
|
if (rep > 0) {
|
2017-02-05 21:50:54 +00:00
|
|
|
while (IS_DIGIT(*cmd)) {
|
2012-02-27 01:02:44 +00:00
|
|
|
cmd++;
|
2016-09-03 23:05:14 +00:00
|
|
|
}
|
2014-01-18 22:02:53 +00:00
|
|
|
// do not repeat null cmd
|
2016-09-03 23:05:14 +00:00
|
|
|
if (!*cmd) {
|
|
|
|
goto beach;
|
|
|
|
}
|
2014-04-27 23:27:45 +00:00
|
|
|
}
|
2016-10-19 11:38:29 +00:00
|
|
|
if (rep < 1) {
|
|
|
|
rep = 1;
|
|
|
|
}
|
2015-01-16 23:09:19 +00:00
|
|
|
// XXX if output is a pipe then we dont want to be interactive
|
2016-01-10 11:10:38 +00:00
|
|
|
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")) {
|
2016-10-19 11:38:29 +00:00
|
|
|
if (!r_cons_yesno ('n', "Are you sure to repeat this %d times? (y/N)", rep)) {
|
2016-01-10 11:10:38 +00:00
|
|
|
goto beach;
|
2016-10-19 11:38:29 +00:00
|
|
|
}
|
2016-01-10 11:10:38 +00:00
|
|
|
}
|
2014-10-10 23:21:17 +00:00
|
|
|
}
|
|
|
|
}
|
2015-01-17 03:23:07 +00:00
|
|
|
// TODO: store in core->cmdtimes to speedup ?
|
|
|
|
cmdrep = r_config_get (core->config, "cmd.times");
|
2016-11-16 00:24:38 +00:00
|
|
|
if (!cmdrep) {
|
|
|
|
cmdrep = "";
|
|
|
|
}
|
2015-01-17 03:23:07 +00:00
|
|
|
orep = rep;
|
2016-02-25 09:28:54 +00:00
|
|
|
|
|
|
|
int ocur_enabled = core->print->cur_enabled;
|
2012-08-19 01:28:17 +00:00
|
|
|
while (rep-- && *cmd) {
|
2016-02-25 09:28:54 +00:00
|
|
|
core->print->cur_enabled = false;
|
|
|
|
if (ocur_enabled && core->seltab >= 0) {
|
|
|
|
if (core->seltab == core->curtab) {
|
|
|
|
core->print->cur_enabled = true;
|
|
|
|
}
|
|
|
|
}
|
2015-03-22 23:32:31 +00:00
|
|
|
char *cr = strdup (cmdrep);
|
2016-09-03 23:05:14 +00:00
|
|
|
core->break_loop = false;
|
2014-11-29 00:41:58 +00:00
|
|
|
ret = r_core_cmd_subst_i (core, cmd, colon);
|
2016-09-03 23:05:14 +00:00
|
|
|
if (ret && *cmd == 'q') {
|
2015-03-22 23:32:31 +00:00
|
|
|
free (cr);
|
2014-01-18 22:02:53 +00:00
|
|
|
goto beach;
|
2015-03-22 23:32:31 +00:00
|
|
|
}
|
2016-09-03 23:05:14 +00:00
|
|
|
if (core->break_loop) {
|
|
|
|
break;
|
|
|
|
}
|
2015-03-22 23:32:31 +00:00
|
|
|
if (cr && *cr) {
|
2016-09-03 23:05:14 +00:00
|
|
|
if (orep > 1) {
|
2015-01-17 03:23:07 +00:00
|
|
|
// XXX: do not flush here, we need r_cons_push () and r_cons_pop()
|
|
|
|
r_cons_flush ();
|
2017-02-21 10:52:02 +00:00
|
|
|
// XXX: we must import register flags in C
|
2016-09-03 23:05:14 +00:00
|
|
|
(void)r_core_cmd0 (core, ".dr*");
|
|
|
|
(void)r_core_cmd0 (core, cr);
|
2015-01-17 03:23:07 +00:00
|
|
|
}
|
|
|
|
}
|
2015-03-22 23:32:31 +00:00
|
|
|
free (cr);
|
2012-02-27 01:02:44 +00:00
|
|
|
}
|
2016-02-25 09:28:54 +00:00
|
|
|
core->print->cur_enabled = ocur_enabled;
|
2013-06-11 09:49:15 +00:00
|
|
|
if (colon && colon[1]) {
|
2017-01-30 18:27:40 +00:00
|
|
|
for (++colon; *colon == ';'; colon++);
|
2012-08-19 01:28:17 +00:00
|
|
|
r_core_cmd_subst (core, colon);
|
2012-09-20 01:38:48 +00:00
|
|
|
} else {
|
2016-09-03 23:05:14 +00:00
|
|
|
if (!*icmd) {
|
2013-06-11 09:49:15 +00:00
|
|
|
r_core_cmd_nullcallback (core);
|
2016-09-03 23:05:14 +00:00
|
|
|
}
|
2012-08-19 01:28:17 +00:00
|
|
|
}
|
2014-01-18 22:02:53 +00:00
|
|
|
beach:
|
2012-02-27 02:07:32 +00:00
|
|
|
free (icmd);
|
2014-01-18 22:02:53 +00:00
|
|
|
return ret;
|
2012-02-27 01:02:44 +00:00
|
|
|
}
|
|
|
|
|
2016-10-19 11:38:29 +00:00
|
|
|
static char *find_eoq(char *p) {
|
2012-10-30 01:49:05 +00:00
|
|
|
for (; *p; p++) {
|
2017-01-30 18:27:40 +00:00
|
|
|
if (*p == '"') {
|
2016-10-19 11:38:29 +00:00
|
|
|
break;
|
|
|
|
}
|
2017-01-30 18:27:40 +00:00
|
|
|
if (*p == '\\' && p[1] == '"') {
|
2012-08-19 01:28:17 +00:00
|
|
|
p++;
|
2016-10-19 11:38:29 +00:00
|
|
|
}
|
2012-08-19 01:28:17 +00:00
|
|
|
}
|
|
|
|
return p;
|
|
|
|
}
|
|
|
|
|
2016-12-27 13:48:35 +00:00
|
|
|
static char* findSeparator(char *p) {
|
|
|
|
char *q = strchr (p, '+');
|
|
|
|
if (q) {
|
|
|
|
return q;
|
|
|
|
}
|
|
|
|
return strchr (p, '-');
|
|
|
|
}
|
2016-10-15 22:48:39 +00:00
|
|
|
|
2014-11-29 00:41:58 +00:00
|
|
|
static int r_core_cmd_subst_i(RCore *core, char *cmd, char *colon) {
|
2012-10-30 01:49:05 +00:00
|
|
|
const char *quotestr = "`";
|
2013-10-08 22:29:49 +00:00
|
|
|
const char *tick = NULL;
|
|
|
|
char *ptr, *ptr2, *str;
|
2013-01-16 11:17:14 +00:00
|
|
|
char *arroba = NULL;
|
2014-02-02 23:19:55 +00:00
|
|
|
int i, ret = 0, pipefd;
|
2016-12-27 13:48:35 +00:00
|
|
|
bool usemyblock = false;
|
2016-11-10 11:02:27 +00:00
|
|
|
int scr_html = -1;
|
2017-03-19 00:20:06 +00:00
|
|
|
int scr_color = -1;
|
2017-03-10 16:02:23 +00:00
|
|
|
bool eos = false;
|
|
|
|
bool haveQuote = false;
|
2009-02-05 21:08:46 +00:00
|
|
|
|
2016-12-04 18:54:01 +00:00
|
|
|
if (!cmd) {
|
|
|
|
return 0;
|
|
|
|
}
|
2010-02-22 23:26:13 +00:00
|
|
|
cmd = r_str_trim_head_tail (cmd);
|
2009-12-31 00:27:03 +00:00
|
|
|
|
2017-09-13 09:13:43 +00:00
|
|
|
char *$0 = strstr (cmd, "$(");
|
|
|
|
if ($0) {
|
|
|
|
char *$1 = strchr ($0 + 2, ')');
|
|
|
|
if ($1) {
|
|
|
|
*$0 = '`';
|
|
|
|
*$1 = '`';
|
|
|
|
memmove ($0 + 1, $0 + 2, strlen ($0) + 1);
|
|
|
|
} else {
|
|
|
|
eprintf ("Unterminated $() block\n");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-08-17 11:15:18 +00:00
|
|
|
/* quoted / raw command */
|
2011-06-26 19:24:22 +00:00
|
|
|
switch (*cmd) {
|
|
|
|
case '.':
|
2016-11-10 11:02:27 +00:00
|
|
|
if (cmd[1] == '"') { /* interpret */
|
2013-10-08 22:29:49 +00:00
|
|
|
return r_cmd_call (core->rcmd, cmd);
|
2016-11-10 11:02:27 +00:00
|
|
|
}
|
2011-06-26 19:24:22 +00:00
|
|
|
break;
|
|
|
|
case '"':
|
2017-03-10 16:02:23 +00:00
|
|
|
for (; *cmd; ) {
|
2013-12-03 00:02:08 +00:00
|
|
|
int pipefd = -1;
|
2012-08-19 01:28:17 +00:00
|
|
|
ut64 oseek = UT64_MAX;
|
2017-03-10 16:02:23 +00:00
|
|
|
char *line, *p;
|
|
|
|
haveQuote = *cmd == '"';
|
|
|
|
if (haveQuote) {
|
|
|
|
// *cmd = 0;
|
|
|
|
cmd++;
|
2017-06-12 13:50:52 +00:00
|
|
|
p = cmd[0] ? find_eoq (cmd + 1) : NULL;
|
2017-03-10 16:02:23 +00:00
|
|
|
if (!p || !*p) {
|
|
|
|
eprintf ("Missing \" in (%s).", cmd);
|
|
|
|
return false;
|
2016-12-12 19:21:20 +00:00
|
|
|
}
|
2017-03-10 16:02:23 +00:00
|
|
|
*p++ = 0;
|
|
|
|
if (!*p) {
|
|
|
|
eos = true;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
char *sc = strchr (cmd, ';');
|
|
|
|
if (sc) {
|
|
|
|
*sc = 0;
|
|
|
|
}
|
|
|
|
r_core_cmd0 (core, cmd);
|
|
|
|
if (!sc) {
|
|
|
|
break;
|
2016-12-12 19:21:20 +00:00
|
|
|
}
|
2017-03-10 16:02:23 +00:00
|
|
|
cmd = sc + 1;
|
|
|
|
continue;
|
2013-12-03 03:20:45 +00:00
|
|
|
}
|
2017-03-10 16:02:23 +00:00
|
|
|
if (p[0]) {
|
|
|
|
// workaround :D
|
|
|
|
if (p[0] == '@') {
|
|
|
|
p--;
|
2016-09-19 15:44:22 +00:00
|
|
|
}
|
2017-03-10 16:02:23 +00:00
|
|
|
while (p[1] == ';' || IS_WHITESPACE (p[1])) {
|
|
|
|
p++;
|
|
|
|
}
|
|
|
|
if (p[1] == '@' || (p[1] && p[2] == '@')) {
|
|
|
|
char *q = strchr (p + 1, '"');
|
|
|
|
if (q) {
|
|
|
|
*q = 0;
|
|
|
|
}
|
|
|
|
haveQuote = q != NULL;
|
|
|
|
oseek = core->offset;
|
2017-08-22 09:12:06 +00:00
|
|
|
r_core_seek (core, r_num_math (core->num, p + 2), 1);
|
2017-03-10 16:02:23 +00:00
|
|
|
if (q) {
|
|
|
|
*p = '"';
|
|
|
|
p = q;
|
|
|
|
} else {
|
|
|
|
p = strchr (p + 1, ';');
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (p && *p && p[1] == '>') {
|
|
|
|
str = p + 2;
|
|
|
|
while (*str == '>') {
|
|
|
|
str++;
|
|
|
|
}
|
|
|
|
while (IS_WHITESPACE (*str)) {
|
|
|
|
str++;
|
|
|
|
}
|
|
|
|
r_cons_flush ();
|
|
|
|
pipefd = r_cons_pipe_open (str, 1, p[2] == '>');
|
2016-09-19 15:44:22 +00:00
|
|
|
}
|
2013-12-03 03:20:45 +00:00
|
|
|
}
|
|
|
|
line = strdup (cmd);
|
2015-09-14 10:35:38 +00:00
|
|
|
line = r_str_replace (line, "\\\"", "\"", true);
|
2017-03-10 16:02:23 +00:00
|
|
|
if (p && *p && p[1] == '|') {
|
2017-01-30 18:27:40 +00:00
|
|
|
str = p + 2;
|
2016-12-12 19:21:20 +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);
|
|
|
|
}
|
2016-11-10 11:02:27 +00:00
|
|
|
if (!p) {
|
|
|
|
break;
|
|
|
|
}
|
2017-03-10 16:02:23 +00:00
|
|
|
if (eos) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (haveQuote) {
|
|
|
|
if (*p == ';') {
|
|
|
|
cmd = p + 1;
|
|
|
|
} else {
|
|
|
|
if (*p == '"') {
|
|
|
|
cmd = p + 1;
|
|
|
|
} else {
|
|
|
|
*p = '"';
|
|
|
|
cmd = p;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
cmd = p + 1;
|
|
|
|
}
|
2009-12-31 00:27:03 +00:00
|
|
|
}
|
2015-09-14 10:35:38 +00:00
|
|
|
return true;
|
2011-06-26 19:24:22 +00:00
|
|
|
case '(':
|
2016-11-10 11:02:27 +00:00
|
|
|
if (cmd[1] != '*') {
|
2012-09-19 12:08:44 +00:00
|
|
|
return r_cmd_call (core->rcmd, cmd);
|
2016-11-10 11:02:27 +00:00
|
|
|
}
|
2009-12-31 00:27:03 +00:00
|
|
|
}
|
|
|
|
|
2012-01-31 01:45:17 +00:00
|
|
|
// TODO must honor " and `
|
2010-08-16 11:59:48 +00:00
|
|
|
/* comments */
|
2016-10-15 22:48:39 +00:00
|
|
|
if (*cmd != '#') {
|
2012-01-31 01:45:17 +00:00
|
|
|
ptr = (char *)r_str_lastbut (cmd, '#', quotestr);
|
2017-03-19 00:20:06 +00:00
|
|
|
if (ptr && (ptr[1] == ' ' || ptr[1] == '\t')) {
|
|
|
|
*ptr = '\0';
|
|
|
|
}
|
2010-08-24 02:09:12 +00:00
|
|
|
}
|
2010-08-16 11:59:48 +00:00
|
|
|
|
2009-12-31 00:27:03 +00:00
|
|
|
/* multiple commands */
|
2017-03-19 00:20:06 +00:00
|
|
|
// TODO: must honor " and ` boundaries
|
2012-01-31 01:45:17 +00:00
|
|
|
//ptr = strrchr (cmd, ';');
|
2016-10-15 22:48:39 +00:00
|
|
|
if (*cmd != '#') {
|
2012-02-27 01:02:44 +00:00
|
|
|
ptr = (char *)r_str_lastbut (cmd, ';', quotestr);
|
2014-11-29 00:41:58 +00:00
|
|
|
if (colon && ptr) {
|
2012-02-27 01:02:44 +00:00
|
|
|
int ret ;
|
|
|
|
*ptr = '\0';
|
2016-12-04 18:54:01 +00:00
|
|
|
if (r_core_cmd_subst (core, cmd) == -1) {
|
2012-02-27 01:02:44 +00:00
|
|
|
return -1;
|
2016-12-04 18:54:01 +00:00
|
|
|
}
|
2016-12-12 19:21:20 +00:00
|
|
|
cmd = ptr + 1;
|
2012-02-27 01:02:44 +00:00
|
|
|
ret = r_core_cmd_subst (core, cmd);
|
|
|
|
*ptr = ';';
|
|
|
|
return ret;
|
|
|
|
//r_cons_flush ();
|
|
|
|
}
|
2009-12-31 00:27:03 +00:00
|
|
|
}
|
2009-02-18 00:43:57 +00:00
|
|
|
|
2013-02-25 01:35:16 +00:00
|
|
|
// TODO must honor " and `
|
2009-12-31 00:27:03 +00:00
|
|
|
/* pipe console to shell process */
|
2012-01-31 01:45:17 +00:00
|
|
|
//ptr = strchr (cmd, '|');
|
|
|
|
ptr = (char *)r_str_lastbut (cmd, '|', quotestr);
|
2009-02-05 21:08:46 +00:00
|
|
|
if (ptr) {
|
2012-07-01 22:38:02 +00:00
|
|
|
char *ptr2 = strchr (cmd, '`');
|
2017-01-30 18:27:40 +00:00
|
|
|
if (!ptr2 || (ptr2 && ptr2 > ptr)) {
|
2012-07-01 22:38:02 +00:00
|
|
|
if (!tick || (tick && tick > ptr)) {
|
|
|
|
*ptr = '\0';
|
|
|
|
cmd = r_str_clean (cmd);
|
2017-03-19 00:20:06 +00:00
|
|
|
if (!strcmp (ptr + 1, "?")) { // "|?"
|
|
|
|
// TODO: should be disable scr.color in pd| ?
|
|
|
|
eprintf ("Usage: <r2command> | <program|H|>\n");
|
|
|
|
eprintf (" pd|? - show this help\n");
|
|
|
|
eprintf (" pd| - disable scr.html and scr.color\n");
|
|
|
|
eprintf (" pd|H - enable scr.html, respect scr.color\n");
|
2017-06-27 23:16:13 +00:00
|
|
|
eprintf (" pi 1|T - use scr.tts to speak out the stdout\n");
|
2017-03-19 00:20:06 +00:00
|
|
|
return ret;
|
|
|
|
} else if (!strcmp (ptr + 1, "H")) { // "|H"
|
|
|
|
scr_html = r_config_get_i (core->config, "scr.html");
|
|
|
|
r_config_set_i (core->config, "scr.html", true);
|
2017-06-27 23:16:13 +00:00
|
|
|
} else if (!strcmp (ptr + 1, "T")) { // "|T"
|
|
|
|
scr_color = r_config_get_i (core->config, "scr.color");
|
|
|
|
r_config_set_i (core->config, "scr.color", false);
|
|
|
|
core->cons->use_tts = true;
|
2017-03-19 00:20:06 +00:00
|
|
|
} else if (ptr[1]) { // "| grep .."
|
|
|
|
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;
|
|
|
|
} else { // "|"
|
|
|
|
scr_html = r_config_get_i (core->config, "scr.html");
|
|
|
|
r_config_set_i (core->config, "scr.html", 0);
|
|
|
|
scr_color = r_config_get_i (core->config, "scr.color");
|
|
|
|
r_config_set_i (core->config, "scr.color", false);
|
2016-12-12 19:21:20 +00:00
|
|
|
}
|
2012-07-01 22:38:02 +00:00
|
|
|
}
|
|
|
|
}
|
2009-12-31 00:27:03 +00:00
|
|
|
}
|
|
|
|
|
2013-02-25 01:35:16 +00:00
|
|
|
// TODO must honor " and `
|
2009-12-31 00:27:03 +00:00
|
|
|
/* bool conditions */
|
2012-01-31 01:45:17 +00:00
|
|
|
ptr = (char *)r_str_lastbut (cmd, '&', quotestr);
|
|
|
|
//ptr = strchr (cmd, '&');
|
2017-01-30 18:27:40 +00:00
|
|
|
while (ptr && ptr[1] == '&') {
|
2011-06-26 21:49:11 +00:00
|
|
|
*ptr = '\0';
|
2012-09-19 12:08:44 +00:00
|
|
|
ret = r_cmd_call (core->rcmd, cmd);
|
2011-08-27 18:25:37 +00:00
|
|
|
if (ret == -1) {
|
2010-02-22 23:26:13 +00:00
|
|
|
eprintf ("command error(%s)\n", cmd);
|
2017-03-19 00:20:06 +00:00
|
|
|
if (scr_html != -1) {
|
|
|
|
r_config_set_i (core->config, "scr.html", scr_html);
|
|
|
|
}
|
|
|
|
if (scr_color != -1) {
|
|
|
|
r_config_set_i (core->config, "scr.color", scr_color);
|
|
|
|
}
|
2009-12-31 00:27:03 +00:00
|
|
|
return ret;
|
|
|
|
}
|
2017-01-30 18:27:40 +00:00
|
|
|
for (cmd = ptr + 2; cmd && *cmd == ' '; cmd++);
|
2010-02-22 23:26:13 +00:00
|
|
|
ptr = strchr (cmd, '&');
|
2009-02-05 21:08:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Out Of Band Input */
|
2010-02-22 23:26:13 +00:00
|
|
|
free (core->oobi);
|
2009-02-05 21:08:46 +00:00
|
|
|
core->oobi = NULL;
|
2012-08-19 01:28:17 +00:00
|
|
|
|
2016-10-15 23:46:03 +00:00
|
|
|
ptr = strstr (cmd, "?*");
|
2017-09-12 09:05:24 +00:00
|
|
|
if (ptr && (ptr == cmd || ptr[-1] != '~')) {
|
|
|
|
ptr[0] = 0;
|
|
|
|
if (*cmd != '#') {
|
|
|
|
int detail = 0;
|
|
|
|
if (cmd < ptr && ptr[-1] == '?') {
|
|
|
|
detail++;
|
|
|
|
if (cmd < ptr - 1 && ptr[-2] == '?') {
|
|
|
|
detail++;
|
2017-03-19 00:20:06 +00:00
|
|
|
}
|
2017-09-12 09:05:24 +00:00
|
|
|
}
|
|
|
|
r_cons_break_push (NULL, NULL);
|
|
|
|
recursive_help (core, detail, cmd);
|
|
|
|
r_cons_break_pop ();
|
|
|
|
r_cons_grep_parsecmd (ptr + 2, "`");
|
|
|
|
if (scr_html != -1) {
|
|
|
|
r_config_set_i (core->config, "scr.html", scr_html);
|
|
|
|
}
|
2017-03-19 00:20:06 +00:00
|
|
|
if (scr_color != -1) {
|
|
|
|
r_config_set_i (core->config, "scr.color", scr_color);
|
|
|
|
}
|
2017-09-12 09:05:24 +00:00
|
|
|
return 0;
|
2016-10-15 22:48:39 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-03-18 23:29:55 +00:00
|
|
|
#if 0
|
2010-02-22 23:26:13 +00:00
|
|
|
ptr = strchr (cmd, '<');
|
2009-02-05 21:08:46 +00:00
|
|
|
if (ptr) {
|
|
|
|
ptr[0] = '\0';
|
2015-06-25 09:50:29 +00:00
|
|
|
if (r_cons_singleton()->is_interactive) {
|
2016-11-10 11:02:27 +00:00
|
|
|
if (ptr[1] == '<') {
|
2015-06-25 09:50:29 +00:00
|
|
|
/* this is a bit mess */
|
|
|
|
//const char *oprompt = strdup (r_line_singleton ()->prompt);
|
|
|
|
//oprompt = ">";
|
2016-12-12 19:21:20 +00:00
|
|
|
for (str = ptr + 2; str[0] == ' '; str++) {
|
|
|
|
//nothing to see here
|
|
|
|
}
|
2015-06-25 09:50:29 +00:00
|
|
|
eprintf ("==> Reading from stdin until '%s'\n", str);
|
|
|
|
free (core->oobi);
|
|
|
|
core->oobi = malloc (1);
|
2016-12-12 19:21:20 +00:00
|
|
|
if (core->oobi) {
|
2015-06-25 09:50:29 +00:00
|
|
|
core->oobi[0] = '\0';
|
2016-12-12 19:21:20 +00:00
|
|
|
}
|
2015-06-25 09:50:29 +00:00
|
|
|
core->oobi_len = 0;
|
|
|
|
for (;;) {
|
|
|
|
char buf[1024];
|
|
|
|
int ret;
|
|
|
|
write (1, "> ", 2);
|
2016-12-12 19:21:20 +00:00
|
|
|
fgets (buf, sizeof (buf) - 1, stdin); // XXX use r_line ??
|
|
|
|
if (feof (stdin)) {
|
2012-08-19 01:28:17 +00:00
|
|
|
break;
|
2016-12-12 19:21:20 +00:00
|
|
|
}
|
2017-01-30 18:27:40 +00:00
|
|
|
if (*buf) buf[strlen (buf) - 1]='\0';
|
2015-06-25 09:50:29 +00:00
|
|
|
ret = strlen (buf);
|
|
|
|
core->oobi_len += ret;
|
2017-01-30 18:27:40 +00:00
|
|
|
core->oobi = realloc (core->oobi, core->oobi_len + 1);
|
2015-06-25 09:50:29 +00:00
|
|
|
if (core->oobi) {
|
2016-12-12 19:21:20 +00:00
|
|
|
if (!strcmp (buf, str)) {
|
2015-06-25 09:50:29 +00:00
|
|
|
break;
|
2016-12-12 19:21:20 +00:00
|
|
|
}
|
2015-06-25 09:50:29 +00:00
|
|
|
strcat ((char *)core->oobi, buf);
|
|
|
|
}
|
2012-08-19 01:28:17 +00:00
|
|
|
}
|
2015-06-25 09:50:29 +00:00
|
|
|
//r_line_set_prompt (oprompt);
|
|
|
|
} else {
|
2016-12-12 19:21:20 +00:00
|
|
|
for (str = ptr + 1; *str == ' '; str++) {
|
|
|
|
//nothing to see here
|
|
|
|
}
|
|
|
|
if (!*str) {
|
|
|
|
goto next;
|
|
|
|
}
|
2015-06-25 09:50:29 +00:00
|
|
|
eprintf ("Slurping file '%s'\n", str);
|
|
|
|
free (core->oobi);
|
|
|
|
core->oobi = (ut8*)r_file_slurp (str, &core->oobi_len);
|
2016-12-12 19:21:20 +00:00
|
|
|
if (!core->oobi) {
|
2015-06-25 09:50:29 +00:00
|
|
|
eprintf ("cannot open file\n");
|
2016-12-12 19:21:20 +00:00
|
|
|
} else if (ptr == cmd) {
|
2015-06-25 09:50:29 +00:00
|
|
|
return r_core_cmd_buffer (core, (const char *)core->oobi);
|
2016-12-12 19:21:20 +00:00
|
|
|
}
|
2009-02-05 21:08:46 +00:00
|
|
|
}
|
|
|
|
} else {
|
2015-06-25 09:50:29 +00:00
|
|
|
eprintf ("Cannot slurp with << in non-interactive mode\n");
|
|
|
|
return 0;
|
2009-02-05 21:08:46 +00:00
|
|
|
}
|
|
|
|
}
|
2012-10-30 02:22:30 +00:00
|
|
|
next:
|
2017-03-18 23:29:55 +00:00
|
|
|
#endif
|
2016-09-19 15:44:22 +00:00
|
|
|
// TODO must honor " and `
|
2009-12-31 00:27:03 +00:00
|
|
|
/* pipe console to file */
|
2010-02-28 21:58:21 +00:00
|
|
|
ptr = strchr (cmd, '>');
|
2009-02-05 21:08:46 +00:00
|
|
|
if (ptr) {
|
2013-11-29 16:27:46 +00:00
|
|
|
int fdn = 1;
|
2012-11-13 10:42:21 +00:00
|
|
|
int pipecolor = r_config_get_i (core->config, "scr.pipecolor");
|
2015-09-14 10:35:38 +00:00
|
|
|
int use_editor = false;
|
2012-08-13 15:42:25 +00:00
|
|
|
int ocolor = r_config_get_i (core->config, "scr.color");
|
2012-11-13 10:42:21 +00:00
|
|
|
*ptr = '\0';
|
2016-09-19 15:44:22 +00:00
|
|
|
str = r_str_trim_head_tail (ptr + 1 + (ptr[1] == '>'));
|
2016-11-11 17:56:29 +00:00
|
|
|
if (!*str) {
|
2017-03-18 23:29:55 +00:00
|
|
|
eprintf ("No output?\n");
|
2016-11-11 17:56:29 +00:00
|
|
|
goto next2;
|
|
|
|
}
|
2012-02-05 00:25:40 +00:00
|
|
|
/* 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. */
|
2017-02-05 21:50:54 +00:00
|
|
|
if (ptr > (cmd + 1) && ISWHITECHAR (ptr[-2])) {
|
2016-11-10 11:02:27 +00:00
|
|
|
char *fdnum = ptr - 1;
|
2017-03-19 00:20:06 +00:00
|
|
|
if (*fdnum == 'H') { // "H>"
|
2016-11-10 11:02:27 +00:00
|
|
|
scr_html = r_config_get_i (core->config, "scr.html");
|
|
|
|
r_config_set_i (core->config, "scr.html", true);
|
|
|
|
pipecolor = true;
|
2017-01-18 15:47:10 +00:00
|
|
|
*fdnum = 0;
|
2016-11-10 11:02:27 +00:00
|
|
|
} else {
|
2017-02-05 21:50:54 +00:00
|
|
|
if (IS_DIGIT(*fdnum)) {
|
2016-11-10 11:02:27 +00:00
|
|
|
fdn = *fdnum - '0';
|
|
|
|
}
|
2017-01-18 15:47:10 +00:00
|
|
|
*fdnum = 0;
|
2016-09-19 15:44:22 +00:00
|
|
|
}
|
2013-11-29 16:27:46 +00:00
|
|
|
}
|
2015-09-14 10:35:38 +00:00
|
|
|
r_cons_set_interactive (false);
|
2012-08-13 15:42:25 +00:00
|
|
|
if (!strcmp (str, "-")) {
|
2015-09-14 10:35:38 +00:00
|
|
|
use_editor = true;
|
2012-08-13 15:42:25 +00:00
|
|
|
str = r_file_temp ("dumpedit");
|
|
|
|
r_config_set (core->config, "scr.color", "false");
|
|
|
|
}
|
2016-09-19 15:44:22 +00:00
|
|
|
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);
|
|
|
|
}
|
2013-09-18 22:03:39 +00:00
|
|
|
}
|
2012-02-05 00:25:40 +00:00
|
|
|
r_cons_set_last_interactive ();
|
2016-09-19 15:44:22 +00:00
|
|
|
if (!pipecolor) {
|
2012-11-13 10:42:21 +00:00
|
|
|
r_config_set_i (core->config, "scr.color", ocolor);
|
2016-09-19 15:44:22 +00:00
|
|
|
}
|
2012-08-13 15:42:25 +00:00
|
|
|
if (use_editor) {
|
|
|
|
const char *editor = r_config_get (core->config, "cfg.editor");
|
2015-03-31 00:26:36 +00:00
|
|
|
if (editor && *editor) {
|
2012-08-13 15:42:25 +00:00
|
|
|
r_sys_cmdf ("%s '%s'", editor, str);
|
2015-03-31 00:26:36 +00:00
|
|
|
r_file_rm (str);
|
2016-09-19 15:44:22 +00:00
|
|
|
} else {
|
|
|
|
eprintf ("No cfg.editor configured\n");
|
|
|
|
}
|
2012-08-13 15:42:25 +00:00
|
|
|
r_config_set_i (core->config, "scr.color", ocolor);
|
|
|
|
free (str);
|
|
|
|
}
|
2016-11-11 17:56:29 +00:00
|
|
|
if (scr_html != -1) {
|
|
|
|
r_config_set_i (core->config, "scr.html", scr_html);
|
|
|
|
}
|
2017-06-27 23:16:13 +00:00
|
|
|
if (scr_color != -1) {
|
|
|
|
r_config_set_i (core->config, "scr.color", scr_color);
|
|
|
|
}
|
|
|
|
core->cons->use_tts = false;
|
2009-12-31 00:27:03 +00:00
|
|
|
return ret;
|
2009-02-05 21:08:46 +00:00
|
|
|
}
|
2012-10-30 02:22:30 +00:00
|
|
|
next2:
|
2009-12-31 00:27:03 +00:00
|
|
|
/* sub commands */
|
2010-02-05 11:21:37 +00:00
|
|
|
ptr = strchr (cmd, '`');
|
2009-12-31 00:27:03 +00:00
|
|
|
if (ptr) {
|
2017-09-18 14:18:12 +00:00
|
|
|
bool empty = false;
|
2012-06-22 01:49:25 +00:00
|
|
|
int oneline = 1;
|
2016-12-12 19:21:20 +00:00
|
|
|
if (ptr[1] == '`') {
|
2016-09-19 15:44:22 +00:00
|
|
|
memmove (ptr, ptr + 1, strlen (ptr));
|
2012-06-22 01:49:25 +00:00
|
|
|
oneline = 0;
|
2017-09-18 14:18:12 +00:00
|
|
|
empty = true;
|
2012-06-22 01:49:25 +00:00
|
|
|
}
|
2016-12-12 19:21:20 +00:00
|
|
|
ptr2 = strchr (ptr + 1, '`');
|
2013-12-21 23:45:50 +00:00
|
|
|
if (empty) {
|
|
|
|
/* do nothing */
|
2016-09-19 15:44:22 +00:00
|
|
|
} else if (!ptr2) {
|
2013-08-29 17:46:48 +00:00
|
|
|
eprintf ("parse: Missing backtick in expression.\n");
|
2016-11-11 17:56:29 +00:00
|
|
|
goto fail;
|
2009-12-31 00:27:03 +00:00
|
|
|
} else {
|
2013-11-30 01:47:29 +00:00
|
|
|
int value = core->num->value;
|
2011-06-26 21:49:11 +00:00
|
|
|
*ptr = '\0';
|
|
|
|
*ptr2 = '\0';
|
2012-10-25 10:55:28 +00:00
|
|
|
if (ptr[1] == '!') {
|
2017-01-30 18:27:40 +00:00
|
|
|
str = r_core_cmd_str_pipe (core, ptr + 1);
|
2014-01-09 00:09:40 +00:00
|
|
|
} else {
|
2017-01-30 18:27:40 +00:00
|
|
|
str = r_core_cmd_str (core, ptr + 1);
|
2014-01-09 00:09:40 +00:00
|
|
|
}
|
2016-11-11 17:56:29 +00:00
|
|
|
if (!str) {
|
|
|
|
goto fail;
|
|
|
|
}
|
2014-02-22 02:36:45 +00:00
|
|
|
// ignore contents if first char is pipe or comment
|
2016-11-02 21:59:32 +00:00
|
|
|
if (*str == '|' || *str == '*') {
|
2014-02-23 00:20:20 +00:00
|
|
|
eprintf ("r_core_cmd_subst_i: invalid backticked command\n");
|
2014-02-22 02:36:45 +00:00
|
|
|
free (str);
|
2016-11-11 17:56:29 +00:00
|
|
|
goto fail;
|
2014-02-22 02:36:45 +00:00
|
|
|
}
|
2016-09-19 15:44:22 +00:00
|
|
|
if (oneline && str) {
|
|
|
|
for (i = 0; str[i]; i++) {
|
|
|
|
if (str[i] == '\n') {
|
|
|
|
str[i] = ' ';
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2017-03-16 21:29:49 +00:00
|
|
|
str = r_str_append (str, ptr2 + 1);
|
|
|
|
cmd = r_str_append (strdup (cmd), str);
|
2013-11-30 01:47:29 +00:00
|
|
|
core->num->value = value;
|
2010-02-05 11:21:37 +00:00
|
|
|
ret = r_core_cmd_subst (core, cmd);
|
|
|
|
free (cmd);
|
2016-11-11 17:56:29 +00:00
|
|
|
if (scr_html != -1) {
|
|
|
|
r_config_set_i (core->config, "scr.html", scr_html);
|
|
|
|
}
|
2010-02-05 11:21:37 +00:00
|
|
|
free (str);
|
2009-12-31 00:27:03 +00:00
|
|
|
return ret;
|
2009-03-21 22:59:35 +00:00
|
|
|
}
|
|
|
|
}
|
2013-01-16 11:17:14 +00:00
|
|
|
// TODO must honor " and `
|
2015-10-20 23:51:34 +00:00
|
|
|
core->fixedblock = false;
|
2009-03-21 22:59:35 +00:00
|
|
|
|
2017-06-03 20:54:22 +00:00
|
|
|
if (r_str_endswith (cmd, "~?") && cmd[2] == '\0') {
|
2017-04-17 15:15:20 +00:00
|
|
|
r_cons_grep_help ();
|
2017-06-03 20:54:22 +00:00
|
|
|
return true;
|
2014-08-20 09:29:44 +00:00
|
|
|
}
|
2017-06-03 20:54:22 +00:00
|
|
|
if (*cmd != '.') {
|
2017-06-10 10:39:04 +00:00
|
|
|
r_cons_grep_parsecmd (cmd, quotestr);
|
2011-08-27 18:25:37 +00:00
|
|
|
}
|
2009-03-21 22:59:35 +00:00
|
|
|
|
2013-01-16 11:17:14 +00:00
|
|
|
/* temporary seek commands */
|
2017-01-30 18:27:40 +00:00
|
|
|
if (*cmd!= '(' && *cmd != '"') {
|
2011-01-26 22:40:16 +00:00
|
|
|
ptr = strchr (cmd, '@');
|
2016-12-12 19:21:20 +00:00
|
|
|
if (ptr == cmd + 1 && *cmd == '?') {
|
2012-12-22 02:37:50 +00:00
|
|
|
ptr = NULL;
|
2016-10-07 21:08:36 +00:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
ptr = NULL;
|
|
|
|
}
|
2016-10-17 12:38:43 +00:00
|
|
|
|
2015-09-14 10:35:38 +00:00
|
|
|
core->tmpseek = ptr? true: false;
|
2017-03-19 00:20:06 +00:00
|
|
|
int rc = 0;
|
2009-02-05 21:08:46 +00:00
|
|
|
if (ptr) {
|
2016-12-12 19:21:20 +00:00
|
|
|
char *f, *ptr2 = strchr (ptr + 1, '!');
|
2017-09-25 17:26:47 +00:00
|
|
|
ut64 addr = core->offset;
|
2017-09-16 22:23:40 +00:00
|
|
|
bool addr_is_set = false;
|
2017-08-29 11:27:24 +00:00
|
|
|
char *tmpbits = NULL;
|
2015-07-15 00:02:11 +00:00
|
|
|
const char *offstr = NULL;
|
2016-06-25 01:27:04 +00:00
|
|
|
ut64 tmpbsz = core->blocksize;
|
|
|
|
char *tmpeval = NULL;
|
2017-03-19 00:20:06 +00:00
|
|
|
ut64 tmpoff = core->offset;
|
2016-06-25 01:27:04 +00:00
|
|
|
char *tmpasm = NULL;
|
2016-06-25 01:43:32 +00:00
|
|
|
int tmpfd = -1;
|
2014-09-20 12:43:18 +00:00
|
|
|
int sz, len;
|
2015-04-07 23:08:09 +00:00
|
|
|
ut8 *buf;
|
2012-12-05 23:55:22 +00:00
|
|
|
|
2017-08-22 21:37:27 +00:00
|
|
|
*ptr++ = '\0';
|
|
|
|
for (; *ptr == ' '; ptr++) {
|
2016-12-12 19:21:20 +00:00
|
|
|
//nothing to see here
|
|
|
|
}
|
2017-01-30 18:27:40 +00:00
|
|
|
if (*ptr && ptr[1] == ':') {
|
2015-03-24 03:55:47 +00:00
|
|
|
/* do nothing here */
|
|
|
|
} else {
|
|
|
|
ptr--;
|
|
|
|
}
|
2016-12-27 13:48:35 +00:00
|
|
|
arroba = (ptr[0] && ptr[1] && ptr[2])?
|
|
|
|
strchr (ptr + 2, '@'): NULL;
|
2013-01-16 11:17:14 +00:00
|
|
|
repeat_arroba:
|
2016-06-25 01:27:04 +00:00
|
|
|
if (arroba) {
|
2013-01-16 11:17:14 +00:00
|
|
|
*arroba = 0;
|
2016-06-25 01:27:04 +00:00
|
|
|
}
|
2017-03-02 09:39:11 +00:00
|
|
|
if (ptr[1] == '?') {
|
2017-08-11 09:45:32 +00:00
|
|
|
r_core_cmd_help (core, help_msg_at);
|
2017-03-02 09:39:11 +00:00
|
|
|
} else if (ptr[0] && ptr[1] == ':' && ptr[2]) {
|
2016-12-27 13:48:35 +00:00
|
|
|
usemyblock = true;
|
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
|
2016-12-12 19:21:20 +00:00
|
|
|
f = r_file_slurp (ptr + 2, &sz);
|
2012-09-20 01:38:48 +00:00
|
|
|
if (f) {
|
|
|
|
buf = malloc (sz);
|
|
|
|
if (buf) {
|
|
|
|
free (core->block);
|
|
|
|
core->block = buf;
|
|
|
|
core->blocksize = sz;
|
|
|
|
memcpy (core->block, f, sz);
|
2016-12-12 19:21:20 +00:00
|
|
|
} else {
|
|
|
|
eprintf ("cannot alloc %d", sz);
|
|
|
|
}
|
2012-09-20 01:38:48 +00:00
|
|
|
free (f);
|
2016-12-12 19:21:20 +00:00
|
|
|
} else {
|
2017-01-30 18:27:40 +00:00
|
|
|
eprintf ("cannot open '%s'\n", ptr + 3);
|
2016-12-12 19:21:20 +00:00
|
|
|
}
|
2012-09-20 01:38:48 +00:00
|
|
|
break;
|
2015-08-31 03:06:01 +00:00
|
|
|
case 'r': // "@r:" // regname
|
2016-12-27 13:48:35 +00:00
|
|
|
if (ptr[1] == ':') {
|
|
|
|
ut64 regval;
|
|
|
|
char *mander = strdup (ptr + 2);
|
|
|
|
char *sep = findSeparator (mander);
|
|
|
|
if (sep) {
|
|
|
|
char ch = *sep;
|
|
|
|
*sep = 0;
|
|
|
|
regval = r_debug_reg_get (core->dbg, mander);
|
|
|
|
*sep = ch;
|
|
|
|
char *numexpr = r_str_newf ("0x%"PFMT64x"%s", regval, sep);
|
|
|
|
regval = r_num_math (core->num, numexpr);
|
|
|
|
free (numexpr);
|
|
|
|
} else {
|
|
|
|
regval = r_debug_reg_get (core->dbg, ptr + 2);
|
|
|
|
}
|
2015-08-31 03:06:01 +00:00
|
|
|
r_core_seek (core, regval, 1);
|
2016-12-27 13:48:35 +00:00
|
|
|
free (mander);
|
2015-08-31 03:06:01 +00:00
|
|
|
}
|
|
|
|
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",
|
2016-12-12 19:21:20 +00:00
|
|
|
r_num_math (core->num, ptr + 2));
|
2015-04-18 23:25:50 +00:00
|
|
|
break;
|
2016-10-07 21:08:36 +00:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
}
|
2016-10-07 21:08:36 +00:00
|
|
|
break;
|
2015-07-15 00:02:11 +00:00
|
|
|
case 'e': // "@e:"
|
2017-01-30 18:27:40 +00:00
|
|
|
tmpeval = parse_tmp_evals (core, ptr + 2);
|
2015-07-15 00:02:11 +00:00
|
|
|
break;
|
2015-04-18 23:25:50 +00:00
|
|
|
case 'x': // "@x:" // hexpairs
|
2016-12-12 19:21:20 +00:00
|
|
|
if (ptr[1] == ':') {
|
2017-01-30 18:27:40 +00:00
|
|
|
buf = malloc (strlen (ptr + 2) + 1);
|
2015-04-18 23:25:50 +00:00
|
|
|
if (buf) {
|
2017-01-30 18:27:40 +00:00
|
|
|
len = r_hex_str2bin (ptr + 2, buf);
|
2016-01-23 06:27:00 +00:00
|
|
|
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);
|
2016-12-12 19:21:20 +00:00
|
|
|
} else {
|
|
|
|
eprintf ("cannot allocate\n");
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
eprintf ("Invalid @x: syntax\n");
|
|
|
|
}
|
2012-09-20 01:38:48 +00:00
|
|
|
break;
|
2016-06-25 01:43:32 +00:00
|
|
|
case 'k': // "@k"
|
2015-04-19 09:54:50 +00:00
|
|
|
{
|
2017-01-30 18:27:40 +00:00
|
|
|
char *out = sdb_querys (core->sdb, NULL, 0, ptr + ((ptr[1])? 2: 1));
|
2015-04-19 09:54:50 +00:00
|
|
|
if (out) {
|
|
|
|
r_core_seek (core, r_num_math (core->num, out), 1);
|
|
|
|
free (out);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
2016-06-25 01:43:32 +00:00
|
|
|
case 'o': // "@o:3"
|
2016-12-12 19:21:20 +00:00
|
|
|
if (ptr[1] == ':') {
|
2017-08-22 07:42:16 +00:00
|
|
|
tmpfd = core->io->desc ? core->io->desc->fd : -1;
|
|
|
|
r_io_use_fd (core->io, atoi (ptr + 2));
|
2016-06-25 01:43:32 +00:00
|
|
|
}
|
|
|
|
break;
|
2015-04-09 22:17:47 +00:00
|
|
|
case 'a': // "@a:"
|
2016-12-12 19:21:20 +00:00
|
|
|
if (ptr[1] == ':') {
|
|
|
|
char *q = strchr (ptr + 2, ':');
|
2015-06-04 10:38:54 +00:00
|
|
|
tmpasm = strdup (r_config_get (core->config, "asm.arch"));
|
2015-04-07 23:08:09 +00:00
|
|
|
if (q) {
|
|
|
|
*q++ = 0;
|
2017-08-29 11:27:24 +00:00
|
|
|
tmpbits = strdup (r_config_get (core->config, "asm.bits"));
|
2015-04-07 23:08:09 +00:00
|
|
|
r_config_set (core->config, "asm.bits", q);
|
|
|
|
}
|
2017-01-30 18:27:40 +00:00
|
|
|
r_config_set (core->config, "asm.arch", ptr + 2);
|
2015-04-07 23:08:09 +00:00
|
|
|
// 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:"
|
2016-12-12 19:21:20 +00:00
|
|
|
len = strlen (ptr + 2);
|
2012-09-20 01:38:48 +00:00
|
|
|
r_core_block_size (core, len);
|
2016-12-12 19:21:20 +00:00
|
|
|
memcpy (core->block, ptr + 2, len);
|
2012-09-20 01:38:48 +00:00
|
|
|
break;
|
2012-10-31 15:37:19 +00:00
|
|
|
default:
|
|
|
|
goto ignore;
|
2012-09-20 01:38:48 +00:00
|
|
|
}
|
|
|
|
*ptr = '@';
|
2013-01-16 11:17:14 +00:00
|
|
|
goto next_arroba; //ignore; //return ret;
|
2012-09-20 01:38:48 +00:00
|
|
|
}
|
2012-09-21 00:25:44 +00:00
|
|
|
ignore:
|
2016-06-05 22:33:11 +00:00
|
|
|
ptr = r_str_trim_head (ptr + 1);
|
|
|
|
ptr--;
|
|
|
|
|
2012-09-20 01:38:48 +00:00
|
|
|
cmd = r_str_clean (cmd);
|
2010-08-10 10:34:10 +00:00
|
|
|
if (ptr2) {
|
2016-12-12 19:21:20 +00:00
|
|
|
if (strlen (ptr + 1) == 13 && strlen (ptr2 + 1) == 6 &&
|
|
|
|
!memcmp (ptr + 1, "0x", 2) &&
|
|
|
|
!memcmp (ptr2 + 1, "0x", 2)) {
|
2012-12-05 23:55:22 +00:00
|
|
|
/* 0xXXXX:0xYYYY */
|
2016-12-12 19:21:20 +00:00
|
|
|
} else if (strlen (ptr + 1) == 9 && strlen (ptr2 + 1) == 4) {
|
2012-12-05 23:55:22 +00:00
|
|
|
/* XXXX:YYYY */
|
|
|
|
} else {
|
|
|
|
*ptr2 = '\0';
|
2016-11-11 17:56:29 +00:00
|
|
|
if (!ptr2[1]) {
|
|
|
|
goto fail;
|
|
|
|
}
|
2016-12-12 19:21:20 +00:00
|
|
|
r_core_block_size (
|
|
|
|
core, r_num_math (core->num, ptr2 + 1));
|
2012-12-05 23:55:22 +00:00
|
|
|
}
|
2010-08-10 10:34:10 +00:00
|
|
|
}
|
|
|
|
|
2017-01-30 18:27:40 +00:00
|
|
|
offstr = r_str_trim_head (ptr + 1);
|
2012-07-12 01:55:09 +00:00
|
|
|
|
|
|
|
addr = r_num_math (core->num, offstr);
|
2017-09-16 22:23:40 +00:00
|
|
|
addr_is_set = true;
|
2017-08-22 09:12:06 +00:00
|
|
|
if (isalpha ((ut8)ptr[1]) && !addr) {
|
2017-01-30 18:27:40 +00:00
|
|
|
if (!r_flag_get (core->flags, ptr + 1)) {
|
2016-12-12 19:21:20 +00:00
|
|
|
eprintf ("Invalid address (%s)\n", ptr + 1);
|
2016-11-11 17:56:29 +00:00
|
|
|
goto fail;
|
2016-12-12 19:21:20 +00:00
|
|
|
}
|
|
|
|
} else {
|
2012-07-12 01:55:09 +00:00
|
|
|
char ch = *offstr;
|
2016-12-12 19:21:20 +00:00
|
|
|
if (ch == '-' || ch == '+') {
|
2016-10-07 21:08:36 +00:00
|
|
|
addr = core->offset + addr;
|
|
|
|
}
|
2012-07-12 01:55:09 +00:00
|
|
|
}
|
2013-01-16 11:17:14 +00:00
|
|
|
next_arroba:
|
|
|
|
if (arroba) {
|
2014-05-14 01:53:22 +00:00
|
|
|
ptr = arroba;
|
2013-01-16 11:17:14 +00:00
|
|
|
arroba = NULL;
|
|
|
|
goto repeat_arroba;
|
|
|
|
}
|
2016-12-12 19:21:20 +00:00
|
|
|
if (ptr[1] == '@') {
|
2009-03-21 02:17:43 +00:00
|
|
|
// TODO: remove temporally seek (should be done by cmd_foreach)
|
2015-06-01 01:05:15 +00:00
|
|
|
if (ptr[2] == '@') {
|
2016-05-24 22:44:41 +00:00
|
|
|
char *rule = ptr + 3;
|
2017-01-30 18:27:40 +00:00
|
|
|
while (*rule && *rule == ' ') rule++;
|
2015-06-01 01:05:15 +00:00
|
|
|
ret = r_core_cmd_foreach3 (core, cmd, rule);
|
|
|
|
} else {
|
2017-01-30 18:27:40 +00:00
|
|
|
ret = r_core_cmd_foreach (core, cmd, ptr + 2);
|
2015-06-01 01:05:15 +00:00
|
|
|
}
|
2010-03-05 12:18:44 +00:00
|
|
|
//ret = -1; /* do not run out-of-foreach cmd */
|
2009-12-31 00:27:03 +00:00
|
|
|
} else {
|
2016-05-23 21:41:39 +00:00
|
|
|
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] == '.') {
|
2016-05-23 21:41:39 +00:00
|
|
|
char *range = ptr + 3;
|
|
|
|
char *p = strchr (range, ' ');
|
2016-05-24 22:44:41 +00:00
|
|
|
if (!p) {
|
2016-05-23 21:41:39 +00:00
|
|
|
eprintf ("Usage: / ABCD @..0x1000 0x3000\n");
|
2016-05-24 22:44:41 +00:00
|
|
|
free (tmpeval);
|
|
|
|
free (tmpasm);
|
2017-08-29 11:27:24 +00:00
|
|
|
free (tmpbits);
|
2016-11-11 17:56:29 +00:00
|
|
|
goto fail;
|
2016-05-23 21:41:39 +00:00
|
|
|
}
|
|
|
|
*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;
|
|
|
|
}
|
2013-01-16 11:17:14 +00:00
|
|
|
if (usemyblock) {
|
2017-09-16 22:23:40 +00:00
|
|
|
if (addr_is_set) {
|
2017-09-16 00:41:48 +00:00
|
|
|
core->offset = addr;
|
|
|
|
}
|
2012-09-19 12:08:44 +00:00
|
|
|
ret = r_cmd_call (core->rcmd, r_str_trim_head (cmd));
|
2013-01-16 11:17:14 +00:00
|
|
|
} else {
|
2017-09-16 22:23:40 +00:00
|
|
|
if (addr_is_set) {
|
2017-09-16 00:41:48 +00:00
|
|
|
if (ptr[1]) {
|
|
|
|
r_core_seek (core, addr, 1);
|
|
|
|
r_core_block_read (core);
|
|
|
|
}
|
|
|
|
ret = r_cmd_call (core->rcmd, r_str_trim_head (cmd));
|
2016-05-23 21:41:39 +00:00
|
|
|
}
|
2013-01-16 11:17:14 +00:00
|
|
|
}
|
2016-05-23 21:41:39 +00:00
|
|
|
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]);
|
|
|
|
}
|
|
|
|
}
|
2009-12-31 00:27:03 +00:00
|
|
|
}
|
2010-08-10 10:34:10 +00:00
|
|
|
if (ptr2) {
|
2012-12-05 23:55:22 +00:00
|
|
|
*ptr2 = '!';
|
2010-08-10 10:34:10 +00:00
|
|
|
r_core_block_size (core, tmpbsz);
|
|
|
|
}
|
2015-04-07 23:08:09 +00:00
|
|
|
if (tmpasm) {
|
|
|
|
r_config_set (core->config, "asm.arch", tmpasm);
|
|
|
|
tmpasm = NULL;
|
|
|
|
}
|
2016-06-25 01:43:32 +00:00
|
|
|
if (tmpfd != -1) {
|
2017-08-22 07:42:16 +00:00
|
|
|
r_io_use_fd (core->io, tmpfd);
|
2016-06-25 01:43:32 +00:00
|
|
|
}
|
2015-04-07 23:08:09 +00:00
|
|
|
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
|
|
|
}
|
2010-02-05 11:21:37 +00:00
|
|
|
r_core_seek (core, tmpoff, 1);
|
2010-08-10 10:34:10 +00:00
|
|
|
*ptr = '@';
|
2017-03-19 00:20:06 +00:00
|
|
|
rc = ret;
|
|
|
|
goto beach;
|
2009-02-05 21:08:46 +00:00
|
|
|
}
|
2009-03-20 21:05:12 +00:00
|
|
|
|
2017-03-19 00:20:06 +00:00
|
|
|
rc = cmd? r_cmd_call (core->rcmd, r_str_trim_head (cmd)): false;
|
2016-11-11 17:56:29 +00:00
|
|
|
beach:
|
2016-11-10 11:02:27 +00:00
|
|
|
if (scr_html != -1) {
|
2017-03-19 00:20:06 +00:00
|
|
|
r_cons_flush ();
|
2016-11-10 11:02:27 +00:00
|
|
|
r_config_set_i (core->config, "scr.html", scr_html);
|
|
|
|
}
|
2017-03-19 00:20:06 +00:00
|
|
|
if (scr_color != -1) {
|
|
|
|
r_config_set_i (core->config, "scr.color", scr_color);
|
|
|
|
}
|
2015-10-20 23:51:34 +00:00
|
|
|
core->fixedblock = false;
|
|
|
|
return rc;
|
2016-11-11 17:56:29 +00:00
|
|
|
fail:
|
|
|
|
rc = -1;
|
|
|
|
goto beach;
|
2009-02-05 21:08:46 +00:00
|
|
|
}
|
|
|
|
|
2015-06-01 01:05:15 +00:00
|
|
|
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 ("");
|
2017-01-30 18:27:40 +00:00
|
|
|
//eprintf ("--> %s = %s\n", k + 7, cmt);
|
|
|
|
r_core_cmdf (core, "s %s", k + 7);
|
2015-06-01 01:05:15 +00:00
|
|
|
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;
|
2017-03-10 17:33:06 +00:00
|
|
|
RFlagItem *flg;
|
2015-06-01 01:05:15 +00:00
|
|
|
int i;
|
|
|
|
|
|
|
|
switch (each[0]) {
|
2017-02-09 23:25:00 +00:00
|
|
|
case '=':
|
|
|
|
{
|
|
|
|
char *arg;
|
|
|
|
for (arg = each + 1; ; ) {
|
|
|
|
char *next = strchr (arg, ' ');
|
|
|
|
if (next) {
|
|
|
|
*next = 0;
|
|
|
|
}
|
|
|
|
if (arg && *arg) {
|
|
|
|
r_core_cmdf (core, "%s %s", cmd, arg);
|
|
|
|
}
|
|
|
|
if (!next) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
arg = next + 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
2015-06-01 01:05:15 +00:00
|
|
|
case '?':
|
2017-03-10 17:33:06 +00:00
|
|
|
r_cons_printf ("Usage: @@@ [type] # types:\n"
|
|
|
|
" symbols\n"
|
|
|
|
" imports\n"
|
|
|
|
" regs\n"
|
|
|
|
" threads\n"
|
|
|
|
" comments\n"
|
|
|
|
" functions\n"
|
|
|
|
" flags\n");
|
2015-06-01 01:05:15 +00:00
|
|
|
break;
|
|
|
|
case 'c':
|
|
|
|
switch (each[1]) {
|
|
|
|
case 'a': // call
|
2015-10-29 19:02:13 +00:00
|
|
|
break;
|
2015-06-01 01:05:15 +00:00
|
|
|
default:
|
2016-11-06 00:40:51 +00:00
|
|
|
r_meta_list_cb (core->anal, R_META_TYPE_COMMENT, 0, foreach_comment, (void*)cmd, UT64_MAX);
|
2015-06-01 01:05:15 +00:00
|
|
|
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);
|
2016-09-19 12:44:47 +00:00
|
|
|
if (!list)
|
2015-09-14 10:35:38 +00:00
|
|
|
return false;
|
2015-06-01 01:05:15 +00:00
|
|
|
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);
|
2016-04-28 08:47:50 +00:00
|
|
|
r_list_free (list);
|
2015-06-01 01:05:15 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 'r':
|
|
|
|
// registers
|
|
|
|
{
|
|
|
|
ut64 offorig = core->offset;
|
2017-03-10 17:33:06 +00:00
|
|
|
for (i = 0; i < 128; i++) {
|
2015-06-01 01:05:15 +00:00
|
|
|
RRegItem *item;
|
|
|
|
ut64 value;
|
|
|
|
head = r_reg_get_list (dbg->reg, i);
|
2017-03-10 17:33:06 +00:00
|
|
|
if (!head) {
|
|
|
|
continue;
|
|
|
|
}
|
2015-06-01 01:05:15 +00:00
|
|
|
r_list_foreach (head, iter, item) {
|
2017-03-10 17:33:06 +00:00
|
|
|
if (item->size != core->anal->bits) {
|
2015-06-01 01:05:15 +00:00
|
|
|
continue;
|
2017-03-10 17:33:06 +00:00
|
|
|
}
|
2015-06-01 01:05:15 +00:00
|
|
|
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
|
2017-03-10 17:33:06 +00:00
|
|
|
{
|
2015-06-01 01:05:15 +00:00
|
|
|
RBinImport *imp;
|
|
|
|
ut64 offorig = core->offset;
|
|
|
|
list = r_bin_get_imports (core->bin);
|
|
|
|
r_list_foreach (list, iter, imp) {
|
2017-03-10 17:33:06 +00:00
|
|
|
char *impflag = r_str_newf ("sym.imp.%s", imp->name);
|
|
|
|
ut64 addr = r_num_math (core->num, impflag);
|
|
|
|
if (addr && addr != UT64_MAX) {
|
|
|
|
r_core_seek (core, addr, 1);
|
|
|
|
r_core_cmd0 (core, cmd);
|
|
|
|
}
|
2015-06-01 01:05:15 +00:00
|
|
|
}
|
|
|
|
r_core_seek (core, offorig, 1);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 's':
|
|
|
|
// symbols
|
2015-10-29 19:02:13 +00:00
|
|
|
{
|
2015-06-01 01:05:15 +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
|
2017-03-10 17:33:06 +00:00
|
|
|
r_list_foreach (core->flags->flags, iter, flg) {
|
|
|
|
r_core_seek (core, flg->offset, 1);
|
|
|
|
r_core_cmd0 (core, cmd);
|
|
|
|
}
|
2015-06-01 01:05:15 +00:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2017-05-13 10:41:30 +00:00
|
|
|
static void foreachOffset (RCore *core, const char *_cmd, const char *each) {
|
|
|
|
char *cmd = strdup (_cmd);
|
|
|
|
char *str = cmd;
|
|
|
|
char *nextLine = NULL;
|
2016-10-30 10:10:20 +00:00
|
|
|
ut64 addr;
|
|
|
|
/* foreach list of items */
|
2017-05-13 10:41:30 +00:00
|
|
|
while (each) {
|
|
|
|
// skip spaces
|
2016-10-30 10:10:20 +00:00
|
|
|
while (*each == ' ') {
|
|
|
|
each++;
|
|
|
|
}
|
2017-05-13 10:41:30 +00:00
|
|
|
// stahp if empty string
|
2016-10-30 10:10:20 +00:00
|
|
|
if (!*each) {
|
|
|
|
break;
|
|
|
|
}
|
2017-05-13 10:41:30 +00:00
|
|
|
// find newline
|
2017-05-13 00:35:31 +00:00
|
|
|
char *nl = strchr (each, '\n');
|
|
|
|
if (nl) {
|
|
|
|
*nl = 0;
|
2017-05-13 10:41:30 +00:00
|
|
|
nextLine = nl + 1;
|
2016-10-30 10:10:20 +00:00
|
|
|
} else {
|
2017-05-13 10:41:30 +00:00
|
|
|
nextLine = NULL;
|
2016-10-30 10:10:20 +00:00
|
|
|
}
|
2017-05-13 10:41:30 +00:00
|
|
|
// chop comment in line
|
|
|
|
nl = strchr (each, '#');
|
|
|
|
if (nl) {
|
|
|
|
*nl = 0;
|
|
|
|
}
|
|
|
|
// space separated numbers
|
|
|
|
while (each && *each) {
|
|
|
|
// find spaces
|
|
|
|
while (*each== ' ') each++;
|
|
|
|
str = strchr (each, ' ');
|
|
|
|
if (str) {
|
|
|
|
*str = '\0';
|
|
|
|
addr = r_num_math (core->num, each);
|
|
|
|
*str = ' ';
|
|
|
|
each = str + 1;
|
|
|
|
} else {
|
|
|
|
if (!*each) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
addr = r_num_math (core->num, each);
|
|
|
|
each = NULL;
|
|
|
|
}
|
|
|
|
r_core_seek (core, addr, 1);
|
|
|
|
r_core_cmd (core, cmd, 0);
|
|
|
|
r_cons_flush ();
|
|
|
|
}
|
|
|
|
each = nextLine;
|
|
|
|
}
|
|
|
|
free (cmd);
|
2016-10-30 10:10:20 +00:00
|
|
|
}
|
|
|
|
|
2010-02-22 23:26:13 +00:00
|
|
|
R_API int r_core_cmd_foreach(RCore *core, const char *cmd, char *each) {
|
2011-08-27 18:25:37 +00:00
|
|
|
int i, j;
|
2009-03-20 21:05:12 +00:00
|
|
|
char ch;
|
|
|
|
char *word = NULL;
|
2017-08-25 16:56:29 +00:00
|
|
|
char *str, *ostr = NULL;
|
2010-12-23 23:51:01 +00:00
|
|
|
RListIter *iter;
|
|
|
|
RFlagItem *flag;
|
2009-07-08 11:49:55 +00:00
|
|
|
ut64 oseek, addr;
|
2009-03-20 21:05:12 +00:00
|
|
|
|
2017-01-30 18:27:40 +00:00
|
|
|
// for (; *each == ' '; each++);
|
|
|
|
for (; *cmd == ' '; cmd++);
|
2009-03-20 21:05:12 +00:00
|
|
|
|
2010-01-12 01:12:18 +00:00
|
|
|
oseek = core->offset;
|
2015-09-02 13:49:38 +00:00
|
|
|
ostr = str = strdup (each);
|
2016-11-20 18:20:14 +00:00
|
|
|
r_cons_break_push (NULL, NULL); //pop on return
|
2010-02-28 21:58:21 +00:00
|
|
|
switch (each[0]) {
|
2017-03-08 23:36:18 +00:00
|
|
|
case '/': // "@@/"
|
2017-03-09 00:23:02 +00:00
|
|
|
{
|
2017-03-12 16:13:02 +00:00
|
|
|
char *cmdhit = strdup (r_config_get (core->config, "cmd.hit"));
|
2017-03-08 23:36:18 +00:00
|
|
|
r_config_set (core->config, "cmd.hit", cmd);
|
|
|
|
r_core_cmd0 (core, each);
|
|
|
|
r_config_set (core->config, "cmd.hit", cmdhit);
|
2017-03-12 16:13:02 +00:00
|
|
|
free (cmdhit);
|
2017-03-09 00:23:02 +00:00
|
|
|
}
|
2017-03-08 23:36:18 +00:00
|
|
|
return 0;
|
2017-08-11 09:45:32 +00:00
|
|
|
case '?': // "@@?"
|
|
|
|
r_core_cmd_help (core, help_msg_at_at);
|
2009-03-20 21:05:12 +00:00
|
|
|
break;
|
2016-08-31 01:30:41 +00:00
|
|
|
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);
|
2016-11-20 18:20:14 +00:00
|
|
|
if (r_cons_is_breaked ()) {
|
|
|
|
break;
|
|
|
|
}
|
2016-08-31 01:30:41 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
r_core_block_size (core, bs);
|
2016-11-20 18:20:14 +00:00
|
|
|
goto out_finish;
|
2016-08-31 01:30:41 +00:00
|
|
|
}
|
|
|
|
break;
|
2017-08-25 16:56:29 +00:00
|
|
|
case 's': // "@@s" - sequence
|
|
|
|
{
|
|
|
|
char *str = each + 1;
|
|
|
|
if (*str == ':' || *str == ' ') {
|
|
|
|
str++;
|
|
|
|
}
|
|
|
|
int count = r_str_split (str, ' ');
|
|
|
|
if (count == 3) {
|
|
|
|
ut64 cur;
|
|
|
|
ut64 from = r_num_math (core->num, r_str_word_get0 (str, 0));
|
|
|
|
ut64 to = r_num_math (core->num, r_str_word_get0 (str, 1));
|
|
|
|
ut64 step = r_num_math (core->num, r_str_word_get0 (str, 2));
|
|
|
|
for (cur = from; cur < to; cur += step) {
|
|
|
|
(void)r_core_seek (core, cur, 1);
|
|
|
|
r_core_cmd (core, cmd, 0);
|
|
|
|
if (r_cons_is_breaked ()) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
eprintf ("Usage: cmd @@s:from to step\n");
|
|
|
|
}
|
|
|
|
goto out_finish;
|
|
|
|
}
|
|
|
|
break;
|
2016-09-02 16:11:56 +00:00
|
|
|
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);
|
2016-11-20 18:20:14 +00:00
|
|
|
if (r_cons_is_breaked ()) {
|
|
|
|
break;
|
|
|
|
}
|
2016-09-02 16:11:56 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2016-11-20 18:20:14 +00:00
|
|
|
goto out_finish;
|
2016-09-02 16:11:56 +00:00
|
|
|
}
|
|
|
|
break;
|
2016-08-31 01:30:41 +00:00
|
|
|
case 'f': // "@@f"
|
2016-09-26 15:16:21 +00:00
|
|
|
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);
|
2016-11-20 18:20:14 +00:00
|
|
|
if (r_cons_is_breaked ()) {
|
|
|
|
break;
|
|
|
|
}
|
2016-09-26 15:16:21 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2016-11-20 18:20:14 +00:00
|
|
|
goto out_finish;
|
2016-09-26 15:16:21 +00:00
|
|
|
} else {
|
2016-08-20 22:25:03 +00:00
|
|
|
RAnalFunction *fcn;
|
|
|
|
RListIter *iter;
|
|
|
|
if (core->anal) {
|
2016-10-18 00:12:43 +00:00
|
|
|
RConsGrep grep = core->cons->grep;
|
2016-08-20 22:25:03 +00:00
|
|
|
r_list_foreach (core->anal->fcns, iter, fcn) {
|
2016-10-18 23:09:14 +00:00
|
|
|
char *buf;
|
2016-08-20 22:25:03 +00:00
|
|
|
r_core_seek (core, fcn->addr, 1);
|
2016-10-18 00:12:43 +00:00
|
|
|
r_cons_push ();
|
2016-08-20 22:25:03 +00:00
|
|
|
r_core_cmd (core, cmd, 0);
|
2016-10-18 23:09:14 +00:00
|
|
|
buf = (char *)r_cons_get_buffer ();
|
|
|
|
if (buf) {
|
|
|
|
buf = strdup (buf);
|
|
|
|
}
|
2016-10-18 00:12:43 +00:00
|
|
|
r_cons_pop ();
|
|
|
|
r_cons_strcat (buf);
|
|
|
|
free (buf);
|
2016-11-20 18:20:14 +00:00
|
|
|
if (r_cons_is_breaked ()) {
|
|
|
|
break;
|
|
|
|
}
|
2016-08-20 22:25:03 +00:00
|
|
|
}
|
2016-10-18 00:12:43 +00:00
|
|
|
core->cons->grep = grep;
|
2016-08-20 22:25:03 +00:00
|
|
|
}
|
2016-11-20 18:20:14 +00:00
|
|
|
goto out_finish;
|
2016-08-20 22:25:03 +00:00
|
|
|
}
|
|
|
|
break;
|
2017-08-11 09:45:32 +00:00
|
|
|
case 't': // "@@t"
|
2015-09-02 13:49:38 +00:00
|
|
|
{
|
|
|
|
RDebugPid *p;
|
|
|
|
int pid = core->dbg->pid;
|
2015-09-03 10:23:49 +00:00
|
|
|
if (core->dbg->h && core->dbg->h->pids) {
|
2016-12-09 17:07:06 +00:00
|
|
|
RList *list = core->dbg->h->pids (core->dbg, R_MAX (0, pid));
|
2015-09-02 13:49:38 +00:00
|
|
|
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);
|
2016-08-20 22:25:03 +00:00
|
|
|
r_cons_newline ();
|
2015-09-02 13:49:38 +00:00
|
|
|
}
|
|
|
|
r_list_free (list);
|
|
|
|
}
|
|
|
|
r_debug_select (core->dbg, pid, pid);
|
2016-11-20 18:20:14 +00:00
|
|
|
goto out_finish;
|
2015-09-02 13:49:38 +00:00
|
|
|
}
|
|
|
|
break;
|
2017-05-13 00:35:31 +00:00
|
|
|
case 'c': // "@@c:"
|
2016-10-30 10:10:20 +00:00
|
|
|
if (each[1] == ':') {
|
|
|
|
char *arg = r_core_cmd_str (core, each + 2);
|
|
|
|
if (arg) {
|
|
|
|
foreachOffset (core, cmd, arg);
|
2016-10-15 22:48:39 +00:00
|
|
|
}
|
2016-10-30 10:10:20 +00:00
|
|
|
}
|
|
|
|
break;
|
2017-08-11 09:45:32 +00:00
|
|
|
case '=': // "@@="
|
2016-10-30 10:10:20 +00:00
|
|
|
foreachOffset (core, cmd, str + 1);
|
2009-03-20 21:05:12 +00:00
|
|
|
break;
|
2017-08-11 09:45:32 +00:00
|
|
|
case 'd': // "@@d"
|
2015-10-22 11:08:05 +00:00
|
|
|
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);
|
2015-10-23 08:55:13 +00:00
|
|
|
i = 0;
|
2015-10-22 11:08:05 +00:00
|
|
|
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 ();
|
2015-10-22 11:08:05 +00:00
|
|
|
i++;
|
|
|
|
}
|
|
|
|
r_core_seek (core, oseek, 0);
|
|
|
|
r_list_free (list);
|
|
|
|
} else {
|
|
|
|
eprintf("Invalid for-each statement. Use @@=dbt[abs]\n");
|
|
|
|
}
|
|
|
|
break;
|
2017-08-11 09:45:32 +00:00
|
|
|
case 'k': // "@@k"
|
2015-04-19 09:54:50 +00:00
|
|
|
/* foreach list of items */
|
|
|
|
{
|
2017-01-30 18:27:40 +00:00
|
|
|
char *out = sdb_querys (core->sdb, NULL, 0, str + ((str[1])? 2: 1));
|
2015-04-19 09:54:50 +00:00
|
|
|
if (out) {
|
|
|
|
each = out;
|
|
|
|
do {
|
2016-11-20 18:20:14 +00:00
|
|
|
while (*each == ' ') each++;
|
|
|
|
if (!*each) {
|
|
|
|
break;
|
|
|
|
}
|
2015-04-19 09:54:50 +00:00
|
|
|
str = strchr (each, ' ');
|
|
|
|
if (str) {
|
|
|
|
*str = '\0';
|
|
|
|
addr = r_num_math (core->num, each);
|
|
|
|
*str = ' ';
|
2016-11-20 18:20:14 +00:00
|
|
|
} else {
|
|
|
|
addr = r_num_math (core->num, each);
|
|
|
|
}
|
2015-04-19 09:54:50 +00:00
|
|
|
//eprintf ("; 0x%08"PFMT64x":\n", addr);
|
2017-01-30 18:27:40 +00:00
|
|
|
each = str + 1;
|
2015-04-19 09:54:50 +00:00
|
|
|
r_core_seek (core, addr, 1);
|
|
|
|
r_core_cmd (core, cmd, 0);
|
|
|
|
r_cons_flush ();
|
|
|
|
} while (str != NULL);
|
|
|
|
free (out);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
2017-08-11 09:45:32 +00:00
|
|
|
case '.': // "@@."
|
2016-11-20 18:20:14 +00:00
|
|
|
if (each[1] == '(') {
|
2009-03-20 21:05:12 +00:00
|
|
|
char cmd2[1024];
|
2010-02-05 11:21:37 +00:00
|
|
|
// XXX whats this 999 ?
|
2011-08-27 18:25:37 +00:00
|
|
|
i = 0;
|
2017-01-30 18:27:40 +00:00
|
|
|
for (core->rcmd->macro.counter = 0; i < 999; core->rcmd->macro.counter++) {
|
2016-11-20 18:20:14 +00:00
|
|
|
if (r_cons_is_breaked ()) {
|
2011-09-11 01:59:24 +00:00
|
|
|
break;
|
2016-11-20 18:20:14 +00:00
|
|
|
}
|
2017-01-30 18:27:40 +00:00
|
|
|
r_cmd_macro_call (&core->rcmd->macro, each + 2);
|
2016-11-20 18:20:14 +00:00
|
|
|
if (!core->rcmd->macro.brk_value) {
|
2009-03-20 21:05:12 +00:00
|
|
|
break;
|
2017-05-22 17:37:48 +00:00
|
|
|
}
|
2012-09-19 12:08:44 +00:00
|
|
|
addr = core->rcmd->macro._brk_value;
|
2010-04-14 11:02:23 +00:00
|
|
|
sprintf (cmd2, "%s @ 0x%08"PFMT64x"", cmd, addr);
|
|
|
|
eprintf ("0x%08"PFMT64x" (%s)\n", addr, cmd2);
|
2010-02-05 11:21:37 +00:00
|
|
|
r_core_seek (core, addr, 1);
|
|
|
|
r_core_cmd (core, cmd2, 0);
|
2009-03-20 21:05:12 +00:00
|
|
|
i++;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
char buf[1024];
|
|
|
|
char cmd2[1024];
|
2016-11-20 18:20:14 +00:00
|
|
|
FILE *fd = r_sandbox_fopen (each + 1, "r");
|
2009-09-24 10:29:05 +00:00
|
|
|
if (fd) {
|
2012-09-19 12:08:44 +00:00
|
|
|
core->rcmd->macro.counter=0;
|
2010-02-05 11:21:37 +00:00
|
|
|
while (!feof (fd)) {
|
|
|
|
buf[0] = '\0';
|
2016-11-20 18:20:14 +00:00
|
|
|
if (!fgets (buf, sizeof (buf), fd)) {
|
2010-02-05 11:21:37 +00:00
|
|
|
break;
|
2016-11-20 18:20:14 +00:00
|
|
|
}
|
2010-05-19 22:59:42 +00:00
|
|
|
addr = r_num_math (core->num, buf);
|
2010-04-14 11:02:23 +00:00
|
|
|
eprintf ("0x%08"PFMT64x": %s\n", addr, cmd);
|
|
|
|
sprintf (cmd2, "%s @ 0x%08"PFMT64x"", cmd, addr);
|
2010-02-05 11:21:37 +00:00
|
|
|
r_core_seek (core, addr, 1); // XXX
|
|
|
|
r_core_cmd (core, cmd2, 0);
|
2012-09-19 12:08:44 +00:00
|
|
|
core->rcmd->macro.counter++;
|
2009-03-20 21:05:12 +00:00
|
|
|
}
|
2010-02-05 11:21:37 +00:00
|
|
|
fclose (fd);
|
2016-10-15 22:48:39 +00:00
|
|
|
} else {
|
2017-01-30 18:27:40 +00:00
|
|
|
eprintf ("cannot open file '%s' to read offsets\n", each + 1);
|
2016-10-15 22:48:39 +00:00
|
|
|
}
|
2009-03-20 21:05:12 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
2012-09-19 12:08:44 +00:00
|
|
|
core->rcmd->macro.counter = 0;
|
2017-01-30 18:27:40 +00:00
|
|
|
for (; *each == ' '; each++);
|
2011-08-27 18:25:37 +00:00
|
|
|
i = 0;
|
2010-02-05 11:21:37 +00:00
|
|
|
while (str[i]) {
|
2009-03-20 21:05:12 +00:00
|
|
|
j = i;
|
2016-01-10 11:10:38 +00:00
|
|
|
for (; str[j] && str[j] == ' '; j++); // skip spaces
|
|
|
|
for (i = j; str[i] && str[i] != ' '; i++); // find EOS
|
2009-03-20 21:05:12 +00:00
|
|
|
ch = str[i];
|
|
|
|
str[i] = '\0';
|
2016-01-10 11:10:38 +00:00
|
|
|
word = strdup (str + j);
|
2016-10-18 00:12:43 +00:00
|
|
|
if (!word) {
|
2009-03-20 21:05:12 +00:00
|
|
|
break;
|
2016-10-18 00:12:43 +00:00
|
|
|
}
|
2009-03-20 21:05:12 +00:00
|
|
|
str[i] = ch;
|
2011-06-07 15:53:15 +00:00
|
|
|
{
|
2014-05-14 01:53:22 +00:00
|
|
|
int flagspace = core->flags->space_idx;
|
2009-03-20 21:05:12 +00:00
|
|
|
/* for all flags in current flagspace */
|
2011-06-07 15:53:15 +00:00
|
|
|
// XXX: dont ask why, but this only works with _prev..
|
2015-01-09 17:54:31 +00:00
|
|
|
r_list_foreach (core->flags->flags, iter, flag) {
|
2016-11-20 18:20:14 +00:00
|
|
|
if (r_cons_is_breaked ()) {
|
2009-03-21 02:17:43 +00:00
|
|
|
break;
|
2016-10-18 00:12:43 +00:00
|
|
|
}
|
2009-03-20 21:05:12 +00:00
|
|
|
/* filter per flag spaces */
|
2016-10-18 00:12:43 +00:00
|
|
|
if ((flagspace != -1) && (flag->space != flagspace)) {
|
2009-03-20 21:05:12 +00:00
|
|
|
continue;
|
2016-10-18 00:12:43 +00:00
|
|
|
}
|
2011-06-07 15:53:15 +00:00
|
|
|
if (r_str_glob (flag->name, word)) {
|
2016-11-18 11:59:27 +00:00
|
|
|
char *buf = NULL;
|
|
|
|
const char *tmp = NULL;
|
2010-02-05 11:21:37 +00:00
|
|
|
r_core_seek (core, flag->offset, 1);
|
2016-10-18 00:12:43 +00:00
|
|
|
r_cons_push ();
|
2010-02-05 11:21:37 +00:00
|
|
|
r_core_cmd (core, cmd, 0);
|
2016-11-18 11:59:27 +00:00
|
|
|
tmp = r_cons_get_buffer ();
|
2016-11-20 11:19:49 +00:00
|
|
|
buf = tmp? strdup (tmp): NULL;
|
2016-10-18 00:12:43 +00:00
|
|
|
r_cons_pop ();
|
|
|
|
r_cons_strcat (buf);
|
|
|
|
free (buf);
|
2009-03-20 21:05:12 +00:00
|
|
|
}
|
|
|
|
}
|
2014-05-14 01:53:22 +00:00
|
|
|
core->flags->space_idx = flagspace;
|
2012-09-19 12:08:44 +00:00
|
|
|
core->rcmd->macro.counter++ ;
|
2010-02-05 11:21:37 +00:00
|
|
|
free (word);
|
|
|
|
word = NULL;
|
2009-03-20 21:05:12 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2016-11-20 18:20:14 +00:00
|
|
|
r_cons_break_pop ();
|
2009-03-21 02:17:43 +00:00
|
|
|
// XXX: use r_core_seek here
|
2010-01-12 01:12:18 +00:00
|
|
|
core->offset = oseek;
|
2009-03-20 21:05:12 +00:00
|
|
|
|
2010-02-05 11:21:37 +00:00
|
|
|
free (word);
|
|
|
|
free (ostr);
|
2015-09-14 10:35:38 +00:00
|
|
|
return true;
|
2016-11-20 18:20:14 +00:00
|
|
|
out_finish:
|
2017-08-25 16:56:29 +00:00
|
|
|
free (ostr);
|
2016-11-20 18:20:14 +00:00
|
|
|
r_cons_break_pop ();
|
|
|
|
return false;
|
2009-03-20 21:05:12 +00:00
|
|
|
}
|
|
|
|
|
2011-04-06 09:35:18 +00:00
|
|
|
R_API int r_core_cmd(RCore *core, const char *cstr, int log) {
|
2013-09-11 21:41:40 +00:00
|
|
|
char *cmd, *ocmd, *ptr, *rcmd;
|
2016-08-14 21:24:32 +00:00
|
|
|
int ret = false, i;
|
2013-09-11 21:41:40 +00:00
|
|
|
|
2017-04-07 22:52:49 +00:00
|
|
|
r_th_lock_enter (core->lock);
|
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])) {
|
2017-04-07 22:52:49 +00:00
|
|
|
ret = true;
|
|
|
|
goto beach;
|
2016-08-14 17:55:54 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
if (strncmp (cstr, core->cmdfilter, strlen (core->cmdfilter))) {
|
2017-04-07 22:52:49 +00:00
|
|
|
ret = true;
|
|
|
|
goto beach;
|
2016-08-14 17:29:59 +00:00
|
|
|
}
|
|
|
|
}
|
2015-07-09 21:20:48 +00:00
|
|
|
if (core->cmdremote) {
|
2015-07-09 21:44:45 +00:00
|
|
|
if (*cstr != '=' && *cstr != 'q' && strncmp (cstr, "!=", 2)) {
|
2015-07-09 21:20:48 +00:00
|
|
|
r_io_system (core->io, cstr);
|
2017-04-07 22:52:49 +00:00
|
|
|
goto beach; // false
|
2015-07-09 21:20:48 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-06-29 15:16:24 +00:00
|
|
|
if (!cstr || (*cstr == '|' && cstr[1] != '?')) {
|
2016-01-10 11:10:38 +00:00
|
|
|
// raw comment syntax
|
2017-06-03 16:02:30 +00:00
|
|
|
goto beach; // false;
|
2013-12-22 03:58:41 +00:00
|
|
|
}
|
2014-11-07 23:45:31 +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");
|
2017-04-07 22:52:49 +00:00
|
|
|
goto beach; // false
|
2015-02-04 00:15:48 +00:00
|
|
|
}
|
2015-09-14 10:35:38 +00:00
|
|
|
core->incomment = true;
|
2014-11-07 23:45:31 +00:00
|
|
|
} else if (!strncmp (cstr, "*/", 2)) {
|
2015-09-14 10:35:38 +00:00
|
|
|
core->incomment = false;
|
2017-04-07 22:52:49 +00:00
|
|
|
goto beach; // false
|
|
|
|
}
|
|
|
|
if (core->incomment) {
|
|
|
|
goto beach; // false
|
2014-11-07 23:45:31 +00:00
|
|
|
}
|
2016-04-27 20:30:29 +00:00
|
|
|
if (log && (*cstr && (*cstr != '.' || !strncmp (cstr, ".(", 2)))) {
|
2011-08-27 18:25:37 +00:00
|
|
|
free (core->lastcmd);
|
|
|
|
core->lastcmd = strdup (cstr);
|
|
|
|
}
|
2015-01-22 01:43:06 +00:00
|
|
|
|
2016-01-10 11:10:38 +00:00
|
|
|
ocmd = cmd = malloc (strlen (cstr) + 4096);
|
2016-10-19 11:38:29 +00:00
|
|
|
if (!ocmd) {
|
2017-04-07 22:52:49 +00:00
|
|
|
goto beach;
|
2016-10-19 11:38:29 +00:00
|
|
|
}
|
2011-06-04 01:14:04 +00:00
|
|
|
r_str_cpy (cmd, cstr);
|
2016-10-19 11:38:29 +00:00
|
|
|
if (log) {
|
|
|
|
r_line_hist_add (cstr);
|
|
|
|
}
|
2011-06-04 01:14:04 +00:00
|
|
|
|
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;
|
2017-04-07 22:52:49 +00:00
|
|
|
goto beach;
|
2013-12-22 00:53:15 +00:00
|
|
|
}
|
2016-10-19 11:38:29 +00:00
|
|
|
core->cmd_depth--;
|
2013-09-11 21:41:40 +00:00
|
|
|
for (rcmd = cmd;;) {
|
2014-05-28 22:49:28 +00:00
|
|
|
ptr = strchr (rcmd, '\n');
|
2016-10-19 11:38:29 +00:00
|
|
|
if (ptr) {
|
|
|
|
*ptr = '\0';
|
|
|
|
}
|
2013-09-11 21:41:40 +00:00
|
|
|
ret = r_core_cmd_subst (core, rcmd);
|
|
|
|
if (ret == -1) {
|
2016-10-19 11:38:29 +00:00
|
|
|
eprintf ("|ERROR| Invalid command '%s' (0x%02x)\n", rcmd, *rcmd);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (!ptr) {
|
2013-09-11 21:41:40 +00:00
|
|
|
break;
|
|
|
|
}
|
2016-01-10 11:10:38 +00:00
|
|
|
rcmd = ptr + 1;
|
2013-09-11 21:41:40 +00:00
|
|
|
}
|
2017-06-03 16:02:30 +00:00
|
|
|
r_th_lock_leave (core->lock);
|
|
|
|
/* run pending analysis commands */
|
2017-05-23 21:55:22 +00:00
|
|
|
if (core->anal->cmdtail) {
|
|
|
|
char *res = core->anal->cmdtail;
|
|
|
|
core->anal->cmdtail = NULL;
|
|
|
|
r_core_cmd_lines (core, res);
|
|
|
|
free (res);
|
|
|
|
}
|
2017-01-30 18:27:40 +00:00
|
|
|
core->cmd_depth++;
|
2011-06-04 01:14:04 +00:00
|
|
|
free (ocmd);
|
|
|
|
free (core->oobi);
|
|
|
|
core->oobi = NULL;
|
|
|
|
core->oobi_len = 0;
|
2017-05-23 21:55:22 +00:00
|
|
|
return ret;
|
2017-04-07 22:52:49 +00:00
|
|
|
beach:
|
|
|
|
r_th_lock_leave (core->lock);
|
2017-05-23 21:55:22 +00:00
|
|
|
/* run pending analysis commands */
|
|
|
|
if (core->anal->cmdtail) {
|
|
|
|
char *res = core->anal->cmdtail;
|
|
|
|
core->anal->cmdtail = NULL;
|
|
|
|
r_core_cmd0 (core, res);
|
|
|
|
free (res);
|
|
|
|
}
|
2009-09-24 10:29:05 +00:00
|
|
|
return ret;
|
2009-02-05 21:08:46 +00:00
|
|
|
}
|
|
|
|
|
2013-09-03 22:35:48 +00:00
|
|
|
R_API int r_core_cmd_lines(RCore *core, const char *lines) {
|
2015-09-14 10:35:38 +00:00
|
|
|
int r, ret = true;
|
2013-09-03 23:14:35 +00:00
|
|
|
char *nl, *data, *odata;
|
2013-09-03 22:35:48 +00:00
|
|
|
|
2016-11-20 18:20:14 +00:00
|
|
|
if (!lines || !*lines) {
|
|
|
|
return true;
|
|
|
|
}
|
2013-09-03 23:14:35 +00:00
|
|
|
data = odata = strdup (lines);
|
2016-11-20 18:20:14 +00:00
|
|
|
if (!odata) {
|
|
|
|
return false;
|
|
|
|
}
|
2012-07-12 23:23:05 +00:00
|
|
|
nl = strchr (odata, '\n');
|
|
|
|
if (nl) {
|
2016-11-20 18:20:14 +00:00
|
|
|
r_cons_break_push (NULL, NULL);
|
2012-07-12 23:23:05 +00:00
|
|
|
do {
|
2016-11-20 18:20:14 +00:00
|
|
|
if (r_cons_is_breaked ()) {
|
2015-03-26 21:41:57 +00:00
|
|
|
free (odata);
|
2016-11-20 18:20:14 +00:00
|
|
|
r_cons_break_pop ();
|
2015-03-26 21:41:57 +00:00
|
|
|
return ret;
|
|
|
|
}
|
2012-07-12 23:23:05 +00:00
|
|
|
*nl = '\0';
|
2013-09-04 00:31:14 +00:00
|
|
|
r = r_core_cmd (core, data, 0);
|
2016-03-31 02:48:36 +00:00
|
|
|
if (r < 0) { //== -1) {
|
2017-01-30 18:27:40 +00:00
|
|
|
data = nl + 1;
|
2016-03-31 03:42:37 +00:00
|
|
|
ret = -1; //r; //false;
|
2012-07-12 23:23:05 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
r_cons_flush ();
|
2016-12-12 19:21:20 +00:00
|
|
|
if (data[0] == 'q') {
|
2016-11-20 18:20:14 +00:00
|
|
|
if (data[1] == '!') {
|
2012-07-20 15:14:28 +00:00
|
|
|
ret = -1;
|
2016-11-20 18:20:14 +00:00
|
|
|
} else {
|
|
|
|
eprintf ("'q': quit ignored. Use 'q!'\n");
|
|
|
|
}
|
2016-03-31 02:48:36 +00:00
|
|
|
data = nl + 1;
|
2012-07-12 23:23:05 +00:00
|
|
|
break;
|
|
|
|
}
|
2017-01-30 18:27:40 +00:00
|
|
|
data = nl + 1;
|
2012-07-12 23:23:05 +00:00
|
|
|
} while ((nl = strchr (data, '\n')));
|
2016-11-20 18:20:14 +00:00
|
|
|
r_cons_break_pop ();
|
2013-09-03 23:14:35 +00:00
|
|
|
}
|
2016-11-20 18:20:14 +00:00
|
|
|
if (ret >= 0 && data && *data) {
|
2013-09-03 23:14:35 +00:00
|
|
|
r_core_cmd (core, data, 0);
|
2016-11-20 18:20:14 +00:00
|
|
|
}
|
2012-07-12 23:23:05 +00:00
|
|
|
free (odata);
|
2013-09-03 22:35:48 +00:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
R_API int r_core_cmd_file(RCore *core, const char *file) {
|
2017-07-18 00:15:49 +00:00
|
|
|
char *data = r_file_abspath (file);
|
|
|
|
if (!data) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
char *odata = r_file_slurp (data, NULL);
|
2013-09-03 22:35:48 +00:00
|
|
|
free (data);
|
2017-07-18 00:15:49 +00:00
|
|
|
if (!odata) {
|
|
|
|
return false;
|
|
|
|
}
|
2013-09-03 22:35:48 +00:00
|
|
|
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;
|
2013-09-03 22:35:48 +00:00
|
|
|
}
|
2014-04-27 23:27:45 +00:00
|
|
|
free (odata);
|
2015-09-14 10:35:38 +00:00
|
|
|
return true;
|
2009-02-05 21:08:46 +00:00
|
|
|
}
|
|
|
|
|
2010-03-30 21:12:19 +00:00
|
|
|
R_API int r_core_cmd_command(RCore *core, const char *command) {
|
2013-09-11 21:41:40 +00:00
|
|
|
int ret, len;
|
2010-02-15 21:59:26 +00:00
|
|
|
char *buf, *rcmd, *ptr;
|
2015-10-19 11:21:12 +00:00
|
|
|
char *cmd = r_core_sysenv_begin (core, command);
|
|
|
|
rcmd = ptr = buf = r_sys_cmd_str (cmd, 0, &len);
|
2016-09-19 12:44:47 +00:00
|
|
|
if (!buf) {
|
2015-10-21 14:44:59 +00:00
|
|
|
free (cmd);
|
2009-12-30 10:03:18 +00:00
|
|
|
return -1;
|
2015-10-21 14:44:59 +00:00
|
|
|
}
|
2013-09-11 21:41:40 +00:00
|
|
|
ret = r_core_cmd (core, rcmd, 0);
|
2015-10-19 11:21:12 +00:00
|
|
|
r_core_sysenv_end (core, command);
|
2011-11-11 16:14:09 +00:00
|
|
|
free (buf);
|
2013-09-11 21:41:40 +00:00
|
|
|
return ret;
|
2009-12-30 10:03:18 +00:00
|
|
|
}
|
|
|
|
|
2010-10-09 17:13:10 +00:00
|
|
|
//TODO: Fix disasm loop is mandatory
|
2010-10-09 11:54:08 +00:00
|
|
|
R_API char *r_core_disassemble_instr(RCore *core, ut64 addr, int l) {
|
|
|
|
char *cmd, *ret = NULL;
|
2013-12-03 23:20:52 +00:00
|
|
|
cmd = r_str_newf ("pd %i @ 0x%08"PFMT64x, l, addr);
|
2010-10-09 11:54:08 +00:00
|
|
|
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;
|
2013-12-03 23:20:52 +00:00
|
|
|
cmd = r_str_newf ("pD %i @ 0x%08"PFMT64x, b, addr);
|
2010-10-09 11:54:08 +00:00
|
|
|
if (cmd) {
|
|
|
|
ret = r_core_cmd_str (core, cmd);
|
|
|
|
free (cmd);
|
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2010-02-22 23:26:13 +00:00
|
|
|
R_API int r_core_cmd_buffer(void *user, const char *buf) {
|
2010-06-20 22:48:06 +00:00
|
|
|
char *ptr, *optr, *str = strdup (buf);
|
2016-05-24 20:22:15 +00:00
|
|
|
if (!str) return false;
|
2010-06-20 22:48:06 +00:00
|
|
|
optr = str;
|
|
|
|
ptr = strchr (str, '\n');
|
2010-02-28 21:58:21 +00:00
|
|
|
while (ptr) {
|
2011-08-27 18:25:37 +00:00
|
|
|
*ptr = '\0';
|
2010-02-28 21:58:21 +00:00
|
|
|
r_core_cmd (user, optr, 0);
|
2017-01-30 18:27:40 +00:00
|
|
|
optr = ptr + 1;
|
2010-06-20 22:48:06 +00:00
|
|
|
ptr = strchr (str, '\n');
|
2009-03-14 11:39:37 +00:00
|
|
|
}
|
2010-02-28 21:58:21 +00:00
|
|
|
r_core_cmd (user, optr, 0);
|
|
|
|
free (str);
|
2015-09-14 10:35:38 +00:00
|
|
|
return true;
|
2009-03-14 11:39:37 +00:00
|
|
|
}
|
|
|
|
|
2010-02-22 23:26:13 +00:00
|
|
|
R_API int r_core_cmdf(void *user, const char *fmt, ...) {
|
2012-07-12 23:23:05 +00:00
|
|
|
char string[4096];
|
2009-02-18 00:43:57 +00:00
|
|
|
int ret;
|
|
|
|
va_list ap;
|
2010-02-01 10:55:56 +00:00
|
|
|
va_start (ap, fmt);
|
2010-06-20 22:48:06 +00:00
|
|
|
vsnprintf (string, sizeof (string), fmt, ap);
|
2010-03-30 21:12:19 +00:00
|
|
|
ret = r_core_cmd ((RCore *)user, string, 0);
|
2011-08-27 18:25:37 +00:00
|
|
|
va_end (ap);
|
2009-02-18 00:43:57 +00:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2010-02-22 23:26:13 +00:00
|
|
|
R_API int r_core_cmd0(void *user, const char *cmd) {
|
2010-03-30 21:12:19 +00:00
|
|
|
return r_core_cmd ((RCore *)user, cmd, 0);
|
2009-02-05 21:08:46 +00:00
|
|
|
}
|
|
|
|
|
2012-06-27 23:27:40 +00:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2012-09-06 01:12:54 +00:00
|
|
|
R_API char *r_core_cmd_str_pipe(RCore *core, const char *cmd) {
|
2017-04-26 13:31:27 +00:00
|
|
|
char *s, *tmp = NULL;
|
|
|
|
if (r_sandbox_enable (0)) {
|
2017-06-12 21:34:51 +00:00
|
|
|
char *p = (*cmd != '"')? strchr (cmd, '|'): NULL;
|
|
|
|
if (p) {
|
|
|
|
// This code works but its pretty ugly as its a workaround to
|
|
|
|
// make the webserver work as expected, this was broken some
|
|
|
|
// weeks. let's use this hackaround for now
|
|
|
|
char *c = strdup (cmd);
|
|
|
|
c[p - cmd] = 0;
|
|
|
|
if (!strcmp (p + 1, "H")) {
|
2017-07-20 13:36:49 +00:00
|
|
|
char *res = r_core_cmd_str (core, c);
|
2017-06-12 21:34:51 +00:00
|
|
|
free (c);
|
2017-07-20 13:36:49 +00:00
|
|
|
char *hres = r_cons_html_filter (res, NULL);
|
|
|
|
free (res);
|
|
|
|
return hres;
|
2017-06-12 21:34:51 +00:00
|
|
|
} else {
|
|
|
|
int sh = r_config_get_i (core->config, "scr.color");
|
|
|
|
r_config_set_i (core->config, "scr.color", 0);
|
|
|
|
char *ret = r_core_cmd_str (core, c);
|
|
|
|
r_config_set_i (core->config, "scr.color", sh);
|
|
|
|
free (c);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
}
|
2012-11-27 13:09:53 +00:00
|
|
|
return r_core_cmd_str (core, cmd);
|
2017-04-26 13:31:27 +00:00
|
|
|
}
|
2012-09-06 01:12:54 +00:00
|
|
|
r_cons_reset ();
|
2017-04-26 13:31:27 +00:00
|
|
|
r_sandbox_disable (1);
|
2014-04-26 20:26:10 +00:00
|
|
|
if (r_file_mkstemp ("cmd", &tmp) != -1) {
|
2013-11-29 16:27:46 +00:00
|
|
|
int pipefd = r_cons_pipe_open (tmp, 1, 0);
|
2017-04-26 13:31:27 +00:00
|
|
|
if (pipefd == -1) {
|
2017-07-26 06:41:03 +00:00
|
|
|
r_file_rm (tmp);
|
2017-04-26 13:31:27 +00:00
|
|
|
r_sandbox_disable (0);
|
2017-07-26 06:41:03 +00:00
|
|
|
free (tmp);
|
2017-04-26 13:31:27 +00:00
|
|
|
return r_core_cmd_str (core, cmd);
|
|
|
|
}
|
|
|
|
char *_cmd = strdup (cmd);
|
2012-09-06 01:12:54 +00:00
|
|
|
r_core_cmd_subst (core, _cmd);
|
|
|
|
r_cons_flush ();
|
|
|
|
r_cons_pipe_close (pipefd);
|
|
|
|
s = r_file_slurp (tmp, NULL);
|
2017-04-26 13:31:27 +00:00
|
|
|
if (s) {
|
|
|
|
r_file_rm (tmp);
|
|
|
|
r_sandbox_disable (0);
|
|
|
|
free (tmp);
|
|
|
|
free (_cmd);
|
|
|
|
return s;
|
|
|
|
}
|
|
|
|
eprintf ("slurp %s fails\n", tmp);
|
2012-09-06 01:12:54 +00:00
|
|
|
r_file_rm (tmp);
|
|
|
|
free (tmp);
|
|
|
|
free (_cmd);
|
2017-04-26 13:31:27 +00:00
|
|
|
r_sandbox_disable (0);
|
|
|
|
return r_core_cmd_str (core, cmd);
|
2012-09-06 01:12:54 +00:00
|
|
|
}
|
2013-10-08 22:29:49 +00:00
|
|
|
r_sandbox_disable (0);
|
2012-09-06 01:12:54 +00:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2010-06-20 22:48:06 +00:00
|
|
|
/* return: pointer to a buffer with the output of the command */
|
2010-03-30 21:12:19 +00:00
|
|
|
R_API char *r_core_cmd_str(RCore *core, const char *cmd) {
|
2011-11-11 16:14:09 +00:00
|
|
|
const char *static_str;
|
2009-09-20 00:16:14 +00:00
|
|
|
char *retstr = NULL;
|
2016-11-02 21:59:32 +00:00
|
|
|
r_cons_push ();
|
2010-02-01 10:55:56 +00:00
|
|
|
if (r_core_cmd (core, cmd, 0) == -1) {
|
2014-01-23 08:44:47 +00:00
|
|
|
//eprintf ("Invalid command: %s\n", cmd);
|
2013-10-08 22:29:49 +00:00
|
|
|
return NULL;
|
2009-02-05 21:08:46 +00:00
|
|
|
}
|
2013-10-08 22:29:49 +00:00
|
|
|
r_cons_filter ();
|
|
|
|
static_str = r_cons_get_buffer ();
|
|
|
|
retstr = strdup (static_str? static_str: "");
|
2016-11-02 21:59:32 +00:00
|
|
|
r_cons_pop ();
|
2009-02-05 21:08:46 +00:00
|
|
|
return retstr;
|
|
|
|
}
|
|
|
|
|
2011-08-27 18:25:37 +00:00
|
|
|
R_API void r_core_cmd_repeat(RCore *core, int next) {
|
2014-01-09 00:09:40 +00:00
|
|
|
// Fix for backtickbug px`~`
|
2017-09-18 14:18:12 +00:00
|
|
|
if (!core->lastcmd || core->cmd_depth < 1) {
|
2014-01-09 00:09:40 +00:00
|
|
|
return;
|
2017-07-18 00:15:49 +00:00
|
|
|
}
|
2011-08-27 18:25:37 +00:00
|
|
|
switch (*core->lastcmd) {
|
2016-04-22 08:52:25 +00:00
|
|
|
case '.':
|
2017-07-18 00:15:49 +00:00
|
|
|
if (core->lastcmd[1] == '(') { // macro call
|
2016-04-22 08:52:25 +00:00
|
|
|
r_core_cmd0 (core, core->lastcmd);
|
2017-07-18 00:15:49 +00:00
|
|
|
}
|
2016-04-22 08:52:25 +00:00
|
|
|
break;
|
2011-08-27 18:25:37 +00:00
|
|
|
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");
|
2011-08-27 18:25:37 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 'p': // print
|
|
|
|
case 'x':
|
2014-11-18 09:53:22 +00:00
|
|
|
case '$':
|
2017-09-18 14:18:12 +00:00
|
|
|
if (!strncmp (core->lastcmd, "pd", 2)) {
|
|
|
|
if (core->lastcmd[2]== ' ') {
|
|
|
|
r_core_cmdf (core, "so %s", core->lastcmd + 3);
|
|
|
|
} else {
|
|
|
|
r_core_cmd0 (core, "so `pi~?`");
|
|
|
|
}
|
2015-01-01 12:02:36 +00:00
|
|
|
} else {
|
2017-09-18 14:18:12 +00:00
|
|
|
if (next) {
|
|
|
|
r_core_seek (core, core->offset + core->blocksize, 1);
|
2015-01-01 12:02:36 +00:00
|
|
|
} else {
|
2017-09-18 14:18:12 +00:00
|
|
|
if (core->blocksize > core->offset) {
|
|
|
|
r_core_seek (core, 0, 1);
|
|
|
|
} else {
|
|
|
|
r_core_seek (core, core->offset - core->blocksize, 1);
|
|
|
|
}
|
2015-01-01 12:02:36 +00:00
|
|
|
}
|
|
|
|
}
|
2011-08-27 18:25:37 +00:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2017-07-25 07:11:29 +00:00
|
|
|
static int compare_cmd_descriptor_name(const void *a, const void *b) {
|
2017-08-11 09:45:32 +00:00
|
|
|
return strcmp (((RCmdDescriptor *)a)->cmd, ((RCmdDescriptor *)b)->cmd);
|
2017-07-25 07:11:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void cmd_descriptor_init(RCore *core) {
|
2017-07-27 12:52:17 +00:00
|
|
|
const ut8 *p;
|
|
|
|
RListIter *iter;
|
|
|
|
RCmdDescriptor *x, *y;
|
|
|
|
int n = core->cmd_descriptors->length;
|
|
|
|
r_list_sort (core->cmd_descriptors, compare_cmd_descriptor_name);
|
|
|
|
r_list_foreach (core->cmd_descriptors, iter, y) {
|
|
|
|
if (--n < 0) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
x = &core->root_cmd_descriptor;
|
2017-08-11 09:45:32 +00:00
|
|
|
for (p = (const ut8 *)y->cmd; *p; p++) {
|
2017-07-25 07:11:29 +00:00
|
|
|
if (!x->sub[*p]) {
|
2017-07-27 12:52:17 +00:00
|
|
|
if (p[1]) {
|
|
|
|
RCmdDescriptor *d = R_NEW0 (RCmdDescriptor);
|
|
|
|
r_list_append (core->cmd_descriptors, d);
|
|
|
|
x->sub[*p] = d;
|
|
|
|
} else {
|
|
|
|
x->sub[*p] = y;
|
2017-07-25 07:11:29 +00:00
|
|
|
}
|
2017-07-27 12:52:17 +00:00
|
|
|
} else if (!p[1]) {
|
2017-08-11 09:45:32 +00:00
|
|
|
eprintf ("Command '%s' is duplicated, please check\n", y->cmd);
|
2017-07-25 07:11:29 +00:00
|
|
|
}
|
|
|
|
x = x->sub[*p];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-08-27 18:25:37 +00:00
|
|
|
R_API void r_core_cmd_init(RCore *core) {
|
2017-08-10 09:52:13 +00:00
|
|
|
struct {
|
|
|
|
const char *cmd;
|
|
|
|
const char *description;
|
|
|
|
r_cmd_callback(cb);
|
|
|
|
void (*descriptor_init)(RCore *core);
|
|
|
|
} cmds[] = {
|
2017-08-11 09:45:32 +00:00
|
|
|
{"!", "run system command", cmd_system},
|
|
|
|
{"#", "calculate hash", cmd_hash},
|
|
|
|
{"$", "alias", cmd_alias},
|
|
|
|
{"%", "short version of 'env' command", cmd_env},
|
|
|
|
{"&", "threading capabilities", cmd_thread},
|
2017-08-21 07:53:23 +00:00
|
|
|
{"(", "macro", cmd_macro, cmd_macro_init},
|
2017-08-11 09:45:32 +00:00
|
|
|
{"*", "pointer read/write", cmd_pointer},
|
|
|
|
{"-", "open cfg.editor and run script", cmd_stdin},
|
|
|
|
{".", "interpret", cmd_interpret},
|
|
|
|
{"/", "search kw, pattern aes", cmd_search, cmd_search_init},
|
|
|
|
{"=", "io pipe", cmd_rap},
|
|
|
|
{"?", "help message", cmd_help, cmd_help_init},
|
|
|
|
{"\\", "alias for =!", cmd_rap_run},
|
|
|
|
{"0x", "alias for s 0x", cmd_ox},
|
2017-08-10 09:52:13 +00:00
|
|
|
{"analysis", "analysis", cmd_anal, cmd_anal_init},
|
2017-08-11 09:45:32 +00:00
|
|
|
{"bsize", "change block size", cmd_bsize},
|
2017-08-21 07:53:23 +00:00
|
|
|
{"cmp", "compare memory", cmd_cmp, cmd_cmp_init},
|
2017-08-11 09:45:32 +00:00
|
|
|
{"Code", "code metadata", cmd_meta, cmd_meta_init},
|
|
|
|
{"debug", "debugger operations", cmd_debug, cmd_debug_init},
|
|
|
|
{"eval", "evaluate configuration variable", cmd_eval, cmd_eval_init},
|
2017-08-10 09:52:13 +00:00
|
|
|
{"flag", "get/set flags", cmd_flag, cmd_flag_init},
|
|
|
|
{"g", "egg manipulation", cmd_egg, cmd_egg_init},
|
|
|
|
{"info", "get file info", cmd_info, cmd_info_init},
|
|
|
|
{"kuery", "perform sdb query", cmd_kuery},
|
2017-08-11 09:45:32 +00:00
|
|
|
{"ls", "list files and directories", cmd_ls},
|
|
|
|
{"L", "manage dynamically loaded plugins", cmd_plugins},
|
|
|
|
{"mount", "mount filesystem", cmd_mount, cmd_mount_init},
|
|
|
|
{"open", "open or map file", cmd_open, cmd_open_init},
|
2017-08-10 09:52:13 +00:00
|
|
|
{"print", "print current block", cmd_print, cmd_print_init},
|
|
|
|
{"Project", "project", cmd_project, cmd_project_init},
|
|
|
|
{"quit", "exit program session", cmd_quit, cmd_quit_init},
|
|
|
|
{"Q", "alias for q!", cmd_Quit},
|
2017-08-11 09:45:32 +00:00
|
|
|
{"resize", "change file size", cmd_resize},
|
|
|
|
{"seek", "seek to an offset", cmd_seek, cmd_seek_init},
|
|
|
|
{"Section", "setup section io information", cmd_section, cmd_section_init},
|
|
|
|
{"t", "type information (cparse)", cmd_type, cmd_type_init},
|
|
|
|
{"Text", "Text log utility", cmd_log, cmd_log_init},
|
|
|
|
{"u", "uname/undo", cmd_uname},
|
|
|
|
{"visual", "enter visual mode", cmd_visual},
|
|
|
|
{"Visual", "enter visual mode", cmd_visual},
|
|
|
|
{"write", "write bytes", cmd_write, cmd_write_init},
|
|
|
|
{"x", "alias for px", cmd_hexdump},
|
|
|
|
{"yank", "yank bytes", cmd_yank},
|
|
|
|
{"zign", "zignatures", cmd_zign, cmd_zign_init},
|
2017-08-10 09:52:13 +00:00
|
|
|
};
|
|
|
|
|
2012-09-19 12:08:44 +00:00
|
|
|
core->rcmd = r_cmd_new ();
|
|
|
|
core->rcmd->macro.user = core;
|
2013-02-01 02:15:48 +00:00
|
|
|
core->rcmd->macro.num = core->num;
|
2012-09-19 12:08:44 +00:00
|
|
|
core->rcmd->macro.cmd = r_core_cmd0;
|
|
|
|
core->rcmd->nullcallback = r_core_cmd_nullcallback;
|
2015-08-08 18:15:13 +00:00
|
|
|
core->rcmd->macro.cb_printf = (PrintfCallback)r_cons_printf;
|
2012-09-19 12:08:44 +00:00
|
|
|
r_cmd_set_data (core->rcmd, core);
|
2017-07-27 12:52:17 +00:00
|
|
|
core->cmd_descriptors = r_list_newf (free);
|
2017-08-10 10:44:28 +00:00
|
|
|
int i;
|
|
|
|
for (i = 0; i < R_ARRAY_SIZE (cmds); i++) {
|
2017-08-10 09:52:13 +00:00
|
|
|
r_cmd_add (core->rcmd, cmds[i].cmd, cmds[i].description, cmds[i].cb);
|
|
|
|
if (cmds[i].descriptor_init) {
|
|
|
|
cmds[i].descriptor_init (core);
|
|
|
|
}
|
|
|
|
}
|
2017-07-27 12:52:17 +00:00
|
|
|
DEFINE_CMD_DESCRIPTOR_SPECIAL (core, $, dollar);
|
|
|
|
DEFINE_CMD_DESCRIPTOR_SPECIAL (core, %, percent);
|
|
|
|
DEFINE_CMD_DESCRIPTOR_SPECIAL (core, *, star);
|
2017-08-11 09:45:32 +00:00
|
|
|
DEFINE_CMD_DESCRIPTOR_SPECIAL (core, ., dot);
|
|
|
|
DEFINE_CMD_DESCRIPTOR_SPECIAL (core, =, equal);
|
2017-07-27 12:52:17 +00:00
|
|
|
DEFINE_CMD_DESCRIPTOR (core, b);
|
|
|
|
DEFINE_CMD_DESCRIPTOR (core, k);
|
|
|
|
DEFINE_CMD_DESCRIPTOR (core, r);
|
|
|
|
DEFINE_CMD_DESCRIPTOR (core, u);
|
|
|
|
DEFINE_CMD_DESCRIPTOR (core, y);
|
2017-07-25 07:11:29 +00:00
|
|
|
cmd_descriptor_init (core);
|
2009-02-05 21:08:46 +00:00
|
|
|
}
|