2013-01-16 11:17:14 +00:00
|
|
|
|
/* radare - LGPL - Copyright 2009-2013 - nibble, pancake */
|
2009-02-05 21:08:46 +00:00
|
|
|
|
|
2012-07-22 08:00:35 +00:00
|
|
|
|
#include <r_core.h>
|
|
|
|
|
#include <r_anal.h>
|
2009-02-26 14:15:19 +00:00
|
|
|
|
|
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>
|
2010-07-03 01:35:26 +00:00
|
|
|
|
|
2012-02-27 01:40:27 +00:00
|
|
|
|
static void cmd_debug_reg(RCore *core, const char *str);
|
|
|
|
|
#include "cmd_hash.c"
|
|
|
|
|
#include "cmd_debug.c"
|
|
|
|
|
#include "cmd_zign.c"
|
|
|
|
|
#include "cmd_section.c"
|
|
|
|
|
#include "cmd_flag.c"
|
|
|
|
|
#include "cmd_project.c"
|
|
|
|
|
#include "cmd_write.c"
|
|
|
|
|
#include "cmd_cmp.c"
|
|
|
|
|
#include "cmd_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
|
|
|
|
|
2012-09-20 01:38:48 +00:00
|
|
|
|
static int r_core_cmd_nullcallback(void *data) {
|
|
|
|
|
RCore *core = (RCore*) data;
|
2012-09-21 00:25:44 +00:00
|
|
|
|
if (!core->cmdrepeat) return 0;
|
|
|
|
|
r_core_cmd_repeat (core, 1);
|
|
|
|
|
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;
|
2011-02-24 08:40:19 +00:00
|
|
|
|
if (b == NULL) {
|
|
|
|
|
b = r_buf_new ();
|
2013-04-11 23:15:00 +00:00
|
|
|
|
if (!r_core_read_at (core, addr, buf, sizeof (buf)))
|
|
|
|
|
return NULL;
|
|
|
|
|
b->base = addr;
|
|
|
|
|
r_buf_set_bytes (b, buf, sizeof (buf));
|
2011-02-24 08:40:19 +00:00
|
|
|
|
} else {
|
2012-06-14 15:41:07 +00:00
|
|
|
|
if ((addr < b->base) || addr > (b->base+b->length-32)) {
|
2013-04-11 23:15:00 +00:00
|
|
|
|
if (!r_core_read_at (core, addr, buf, sizeof (buf)))
|
|
|
|
|
return NULL;
|
|
|
|
|
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;
|
|
|
|
|
op = R_NEW (RAsmOp);
|
|
|
|
|
r_asm_set_pc (core->assembler, addr);
|
|
|
|
|
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
|
|
|
|
}
|
|
|
|
|
|
2012-12-23 12:52:57 +00:00
|
|
|
|
static int cmd_log(void *data, const char *input) {
|
|
|
|
|
RCore *core = (RCore *)data;
|
2012-12-23 19:51:23 +00:00
|
|
|
|
const char *input2 = input + (*input? (*input==' '? 2: 1): 0);
|
2012-12-23 12:52:57 +00:00
|
|
|
|
char *arg = strchr (input2, ' ');
|
|
|
|
|
int n = atoi (input2);
|
|
|
|
|
int n2 = arg? atoi (arg+1): 0;
|
|
|
|
|
switch (*input) {
|
2012-12-23 14:19:11 +00:00
|
|
|
|
case 'l':
|
|
|
|
|
r_cons_printf ("%d\n", core->log->last-1);
|
|
|
|
|
break;
|
2012-12-23 12:52:57 +00:00
|
|
|
|
case '-':
|
|
|
|
|
r_core_log_del (core, n);
|
|
|
|
|
break;
|
|
|
|
|
case '?':
|
|
|
|
|
r_cons_printf ("Usage: l[-][ num|msg]\n"
|
|
|
|
|
" l new comment 0x80480\n"
|
2012-12-23 14:19:11 +00:00
|
|
|
|
" ll get last log message id\n"
|
2012-12-23 12:52:57 +00:00
|
|
|
|
" l- delete all logs\n"
|
|
|
|
|
" l-123 delete logs before 123\n"
|
|
|
|
|
" l 123 list log from 123 \n"
|
|
|
|
|
" l list all log messages\n"
|
|
|
|
|
" l 10 3 list 3 log messages starting from 10\n"
|
2013-09-18 20:16:18 +00:00
|
|
|
|
" ls list files in current directory (see pwd, cd)\n"
|
2012-12-23 12:52:57 +00:00
|
|
|
|
" lj list in json format\n"
|
|
|
|
|
" l* list in radare commands\n"
|
|
|
|
|
);
|
|
|
|
|
break;
|
|
|
|
|
case ' ':
|
|
|
|
|
if (!n) {
|
|
|
|
|
r_core_log_add (core, input+1);
|
|
|
|
|
break;
|
|
|
|
|
}
|
2013-09-18 20:16:18 +00:00
|
|
|
|
case 's':
|
|
|
|
|
{
|
|
|
|
|
char *name;
|
|
|
|
|
RListIter *iter;
|
|
|
|
|
RList *files = r_sys_dir (".");
|
|
|
|
|
r_list_foreach (files, iter, name) {
|
|
|
|
|
r_cons_printf ("%s%s\n", name,
|
|
|
|
|
r_file_is_directory (name)? "/":"");
|
|
|
|
|
}
|
|
|
|
|
r_list_free (files);
|
|
|
|
|
}
|
|
|
|
|
break;
|
2012-12-23 12:52:57 +00:00
|
|
|
|
case 'j':
|
|
|
|
|
case '*':
|
|
|
|
|
case '\0':
|
|
|
|
|
r_core_log_list (core, n, n2, *input);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2012-10-30 01:49:05 +00:00
|
|
|
|
static int cmd_alias(void *data, const char *input) {
|
|
|
|
|
int i;
|
|
|
|
|
char *p, *q, *buf;
|
|
|
|
|
RCore *core = (RCore *)data;
|
|
|
|
|
if (*input=='?') {
|
|
|
|
|
r_cons_printf ("Usage: -alias[=cmd] [args...]\n"
|
2013-07-12 23:13:23 +00:00
|
|
|
|
" $dis=af,pdf # create command -analyze to show function\n"
|
|
|
|
|
" $dis= # undefine alias\n"
|
|
|
|
|
" $dis# execute the previously defined alias\n"
|
|
|
|
|
" $dis? # show commands aliased by 'analyze'\n"
|
|
|
|
|
" $ # list all defined aliases\n"
|
|
|
|
|
" $* # sas above, but using r2 commands\n");
|
2012-10-30 01:49:05 +00:00
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
i = strlen (input);
|
|
|
|
|
buf = malloc (i+2);
|
|
|
|
|
if (!buf) return 0;
|
2012-12-23 12:52:57 +00:00
|
|
|
|
*buf = '$'; // prefix aliases with a dash
|
2012-10-30 01:49:05 +00:00
|
|
|
|
memcpy (buf+1, input, i+1);
|
|
|
|
|
p = strchr (buf, '=');
|
|
|
|
|
q = strchr (buf, ' ');
|
|
|
|
|
if (p) {
|
2012-10-30 02:22:30 +00:00
|
|
|
|
*p++ = 0;
|
|
|
|
|
if (!q || (q && q>p)) {
|
|
|
|
|
if (*p) r_cmd_alias_set (core->rcmd, buf, p);
|
|
|
|
|
else r_cmd_alias_del (core->rcmd, buf);
|
|
|
|
|
}
|
2012-10-30 01:49:05 +00:00
|
|
|
|
} else
|
2013-07-12 23:13:23 +00:00
|
|
|
|
if (buf[1]=='*') {
|
|
|
|
|
int i, count = 0;
|
|
|
|
|
char **keys = r_cmd_alias_keys (core->rcmd, &count);
|
|
|
|
|
for (i=0; i<count; i++) {
|
|
|
|
|
const char *v = r_cmd_alias_get (core->rcmd, keys[i]);
|
|
|
|
|
r_cons_printf ("%s=%s\n", keys[i], v);
|
|
|
|
|
}
|
|
|
|
|
} else
|
2012-10-30 02:22:30 +00:00
|
|
|
|
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);
|
2012-10-30 01:49:05 +00:00
|
|
|
|
for (i=0; i<count; i++)
|
|
|
|
|
r_cons_printf ("%s\n", keys[i]);
|
|
|
|
|
} else {
|
2013-07-12 23:13:23 +00:00
|
|
|
|
char *describe = strchr (buf, '?');
|
|
|
|
|
char *v;
|
2012-10-30 01:49:05 +00:00
|
|
|
|
if (q) *q = 0;
|
2013-07-12 23:13:23 +00:00
|
|
|
|
if (describe) *describe = 0;
|
2012-10-30 01:49:05 +00:00
|
|
|
|
v = r_cmd_alias_get (core->rcmd, buf);
|
|
|
|
|
if (v) {
|
2013-07-12 23:13:23 +00:00
|
|
|
|
if (describe) {
|
|
|
|
|
r_cons_printf ("%s\n", v);
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
2012-10-30 01:49:05 +00:00
|
|
|
|
if (q) {
|
|
|
|
|
char *out, *args = q+1;
|
|
|
|
|
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);
|
2013-09-11 21:41:40 +00:00
|
|
|
|
r_str_replace_char (out, ',', ';');
|
2012-10-30 01:49:05 +00:00
|
|
|
|
r_core_cmd0 (core, out);
|
2013-09-11 21:41:40 +00:00
|
|
|
|
r_str_replace_char (out, ';', ',');
|
2012-10-30 01:49:05 +00:00
|
|
|
|
free (out);
|
2013-01-16 11:17:14 +00:00
|
|
|
|
} else eprintf ("cannot malloc\n");
|
2012-10-30 01:49:05 +00:00
|
|
|
|
} else {
|
2013-07-12 23:13:23 +00:00
|
|
|
|
r_str_replace_char (v, ',', ';');
|
2012-10-30 01:49:05 +00:00
|
|
|
|
r_core_cmd0 (core, v);
|
2013-07-12 23:13:23 +00:00
|
|
|
|
r_str_replace_char (v, ';', ',');
|
2012-10-30 01:49:05 +00:00
|
|
|
|
}
|
|
|
|
|
} else eprintf ("unknown key '%s'\n", buf);
|
|
|
|
|
}
|
2013-07-12 23:13:23 +00:00
|
|
|
|
return 0;
|
2012-10-30 01:49:05 +00:00
|
|
|
|
}
|
|
|
|
|
|
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) {
|
2012-09-06 01:12:54 +00:00
|
|
|
|
case '\0': r_core_rtr_list (core); break;
|
2013-02-06 09:35:23 +00:00
|
|
|
|
case 'h': r_core_rtr_http (core, 0, input+1); break;
|
2013-01-24 02:48:24 +00:00
|
|
|
|
case 'H':
|
|
|
|
|
while (input[1]==' ') input++;
|
|
|
|
|
r_core_rtr_http (core, 1, input+1); break;
|
2012-09-06 01:12:54 +00:00
|
|
|
|
case '?': r_core_rtr_help (core); break;
|
|
|
|
|
case '+': r_core_rtr_add (core, input+1); break;
|
|
|
|
|
case '-': r_core_rtr_remove (core, input+1); break;
|
|
|
|
|
case '=': r_core_rtr_session (core, input+1); break;
|
2012-11-05 01:00:34 +00:00
|
|
|
|
//case ':': r_core_rtr_cmds (core, input+1); break;
|
2012-09-06 01:12:54 +00:00
|
|
|
|
case '<': r_core_rtr_pushout (core, input+1); break;
|
|
|
|
|
case '!': r_io_system (core->io, input+1); break;
|
|
|
|
|
default: r_core_rtr_cmd (core, input);
|
2010-08-24 09:58:09 +00:00
|
|
|
|
}
|
2009-02-05 21:08:46 +00:00
|
|
|
|
return R_TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
2009-09-25 02:04:51 +00:00
|
|
|
|
static int cmd_yank(void *data, const char *input) {
|
2011-02-23 01:10:28 +00:00
|
|
|
|
int i;
|
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]) {
|
2009-02-18 12:10:59 +00:00
|
|
|
|
case ' ':
|
2012-02-04 23:33:34 +00:00
|
|
|
|
r_core_yank (core, core->offset, r_num_math (core->num, input+1));
|
2009-02-18 12:10:59 +00:00
|
|
|
|
break;
|
|
|
|
|
case 'y':
|
2013-03-07 22:47:41 +00:00
|
|
|
|
while (input[1]==' ') input++;
|
|
|
|
|
n = input[1]? r_num_math (core->num, input+1): core->offset;
|
|
|
|
|
r_core_yank_paste (core, n, 0);
|
2012-02-04 23:33:34 +00:00
|
|
|
|
break;
|
|
|
|
|
case 'x':
|
2012-09-19 12:08:44 +00:00
|
|
|
|
r_print_hexdump (core->print, 0LL, core->yank_buf, core->yank_len, 16, 4);
|
2009-02-18 12:10:59 +00:00
|
|
|
|
break;
|
2011-02-23 01:10:28 +00:00
|
|
|
|
case 'p':
|
2012-09-19 12:08:44 +00:00
|
|
|
|
r_cons_memcat ((const char*)core->yank_buf, core->yank_len);
|
2011-02-23 01:10:28 +00:00
|
|
|
|
r_cons_newline ();
|
|
|
|
|
break;
|
2009-04-15 18:24:19 +00:00
|
|
|
|
case 't':
|
|
|
|
|
{ /* hacky implementation */
|
2012-02-04 23:33:34 +00:00
|
|
|
|
char *arg = strdup (input+1);
|
2012-02-05 00:14:09 +00:00
|
|
|
|
r_core_yank_to (core, arg);
|
2012-02-04 23:33:34 +00:00
|
|
|
|
free (arg);
|
2009-04-15 18:24:19 +00:00
|
|
|
|
}
|
|
|
|
|
break;
|
2009-02-18 12:10:59 +00:00
|
|
|
|
case '\0':
|
2012-09-19 12:08:44 +00:00
|
|
|
|
if (core->yank_buf) {
|
2010-04-14 11:02:23 +00:00
|
|
|
|
r_cons_printf ("0x%08"PFMT64x" %d ",
|
2009-02-18 12:10:59 +00:00
|
|
|
|
core->yank_off, core->yank_len);
|
2011-02-23 01:10:28 +00:00
|
|
|
|
for (i=0; i<core->yank_len; i++)
|
2012-09-19 12:08:44 +00:00
|
|
|
|
r_cons_printf ("%02x", core->yank_buf[i]);
|
2010-02-01 10:55:56 +00:00
|
|
|
|
r_cons_newline ();
|
|
|
|
|
} else eprintf ("No buffer yanked already\n");
|
2009-02-18 12:10:59 +00:00
|
|
|
|
break;
|
|
|
|
|
default:
|
2010-02-28 21:58:21 +00:00
|
|
|
|
r_cons_printf (
|
2012-02-04 23:33:34 +00:00
|
|
|
|
"Usage: y[ptxy] [len] [[@]addr]\n"
|
2009-02-18 12:10:59 +00:00
|
|
|
|
" y ; show yank buffer information (srcoff len bytes)\n"
|
|
|
|
|
" y 16 ; copy 16 bytes into clipboard\n"
|
|
|
|
|
" y 16 0x200 ; copy 16 bytes into clipboard from 0x200\n"
|
|
|
|
|
" y 16 @ 0x200 ; copy 16 bytes into clipboard from 0x200\n"
|
2011-02-23 01:10:28 +00:00
|
|
|
|
" yp ; print contents of clipboard\n"
|
2012-02-04 23:33:34 +00:00
|
|
|
|
" yx ; print contents of clipboard in hexadecimal\n"
|
2012-02-07 00:51:56 +00:00
|
|
|
|
" yt 64 0x200 ; copy 64 bytes from current seek to 0x200\n"
|
2009-02-18 12:10:59 +00:00
|
|
|
|
" yy 0x3344 ; paste clipboard\n");
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
return R_TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
2010-02-22 23:26:13 +00:00
|
|
|
|
static int cmd_quit(void *data, const char *input) {
|
2010-03-30 21:12:19 +00:00
|
|
|
|
RCore *core = (RCore *)data;
|
2011-05-24 13:25:52 +00:00
|
|
|
|
if (input)
|
|
|
|
|
switch (*input) {
|
2009-02-05 21:08:46 +00:00
|
|
|
|
case '?':
|
2010-02-01 10:55:56 +00:00
|
|
|
|
r_cons_printf (
|
2009-02-05 21:08:46 +00:00
|
|
|
|
"Usage: q[!] [retvalue]\n"
|
|
|
|
|
" q ; quit program\n"
|
|
|
|
|
" q! ; force quit (no questions)\n"
|
|
|
|
|
" q 1 ; quit with return value 1\n"
|
|
|
|
|
" q a-b ; quit with return value a-b\n");
|
|
|
|
|
break;
|
|
|
|
|
case ' ':
|
|
|
|
|
case '!':
|
2010-02-28 22:57:55 +00:00
|
|
|
|
input++;
|
|
|
|
|
case '\0':
|
2009-12-30 09:56:41 +00:00
|
|
|
|
// TODO
|
2009-02-05 21:08:46 +00:00
|
|
|
|
default:
|
2013-06-27 17:15:59 +00:00
|
|
|
|
r_line_hist_save (R2_HOMEDIR"/history");
|
2010-02-28 22:57:55 +00:00
|
|
|
|
if (*input)
|
2010-05-19 22:59:42 +00:00
|
|
|
|
r_num_math (core->num, input);
|
|
|
|
|
else core->num->value = 0LL;
|
|
|
|
|
//exit (*input?r_num_math (core->num, input+1):0);
|
2013-02-07 02:09:53 +00:00
|
|
|
|
//if (core->http_up) return R_FALSE; // cancel quit when http is running
|
2010-02-28 21:58:21 +00:00
|
|
|
|
return -2;
|
2009-02-05 21:08:46 +00:00
|
|
|
|
}
|
2010-02-28 21:58:21 +00:00
|
|
|
|
return R_FALSE;
|
2009-02-05 21:08:46 +00:00
|
|
|
|
}
|
|
|
|
|
|
2013-08-17 17:53:04 +00:00
|
|
|
|
R_API int r_core_run_script (RCore *core, const char *file) {
|
2013-09-03 22:35:48 +00:00
|
|
|
|
int ret = R_FALSE;
|
2013-09-03 21:47:18 +00:00
|
|
|
|
RLangPlugin *p;
|
2013-09-03 22:35:48 +00:00
|
|
|
|
if (!strcmp (file, "-")) {
|
|
|
|
|
char *out = r_core_editor (core, NULL);
|
|
|
|
|
if (out) {
|
|
|
|
|
ret = r_core_cmd_lines (core, out);
|
|
|
|
|
free (out);
|
|
|
|
|
}
|
2013-08-29 17:06:23 +00:00
|
|
|
|
return ret;
|
2013-09-03 22:35:48 +00:00
|
|
|
|
}
|
2013-09-03 21:47:18 +00:00
|
|
|
|
if (r_parse_is_c_file (file)) {
|
|
|
|
|
char *out = r_parse_c_file (file);
|
|
|
|
|
if (out) {
|
|
|
|
|
r_cons_strcat (out);
|
|
|
|
|
sdb_query_lines (core->anal->sdb_types, out);
|
|
|
|
|
free (out);
|
|
|
|
|
}
|
|
|
|
|
return out? R_TRUE: R_FALSE;
|
|
|
|
|
}
|
|
|
|
|
p = r_lang_get_by_extension (core->lang, file);
|
2013-08-17 17:53:04 +00:00
|
|
|
|
if (p) {
|
|
|
|
|
r_lang_use (core->lang, p->name);
|
|
|
|
|
return r_lang_run_file (core->lang, file);
|
|
|
|
|
}
|
|
|
|
|
return r_core_cmd_file (core, file);
|
|
|
|
|
}
|
|
|
|
|
|
2013-09-03 23:14:35 +00:00
|
|
|
|
static int cmd_stdin(void *data, const char *input) {
|
|
|
|
|
RCore *core = (RCore *)data;
|
|
|
|
|
if (input[0]=='?') {
|
|
|
|
|
r_cons_printf ("Usage: '-' '.-' '. -' do the same\n");
|
|
|
|
|
return R_FALSE;
|
|
|
|
|
}
|
|
|
|
|
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) {
|
2010-03-19 03:02:23 +00:00
|
|
|
|
case '\0':
|
2011-08-27 18:25:37 +00:00
|
|
|
|
r_core_cmd_repeat (core, 0);
|
|
|
|
|
break;
|
2012-11-05 01:00:34 +00:00
|
|
|
|
case ':':
|
|
|
|
|
if ((ptr = strchr (input+1, ' '))) {
|
|
|
|
|
/* .:port cmd */
|
|
|
|
|
/* .:host:port cmd */
|
2012-11-20 02:59:00 +00:00
|
|
|
|
cmd = ptr+1;
|
2012-11-05 01:00:34 +00:00
|
|
|
|
*ptr = 0;
|
|
|
|
|
eol = strchr (input+1, ':');
|
|
|
|
|
if (eol) {
|
|
|
|
|
*eol = 0;
|
|
|
|
|
host = input+1;
|
|
|
|
|
port = eol+1;
|
|
|
|
|
} else {
|
|
|
|
|
host = "localhost";
|
|
|
|
|
port = input+((input[1]==':')?2:1);
|
|
|
|
|
}
|
|
|
|
|
rbuf = r_core_rtr_cmds_query (core, host, port, cmd);
|
|
|
|
|
if (rbuf) {
|
|
|
|
|
r_cons_printf ("%s", rbuf);
|
|
|
|
|
free (rbuf);
|
|
|
|
|
}
|
|
|
|
|
} else r_core_rtr_cmds (core, input+1);
|
|
|
|
|
break;
|
2011-08-27 18:25:37 +00:00
|
|
|
|
case '.': // same as \n
|
|
|
|
|
r_core_cmd_repeat (core, 1);
|
2010-03-19 03:02:23 +00:00
|
|
|
|
break;
|
2013-09-03 22:35:48 +00:00
|
|
|
|
case '-':
|
2013-09-03 23:14:35 +00:00
|
|
|
|
if (input[1]=='?') {
|
|
|
|
|
r_cons_printf ("Usage: '-' '.-' '. -' do the same\n");
|
|
|
|
|
} else r_core_run_script (core, "-");
|
2013-09-03 22:35:48 +00:00
|
|
|
|
break;
|
2009-02-05 21:08:46 +00:00
|
|
|
|
case ' ':
|
2013-08-17 17:53:04 +00:00
|
|
|
|
r_core_run_script (core, input+1);
|
2009-02-05 21:08:46 +00:00
|
|
|
|
break;
|
|
|
|
|
case '!':
|
|
|
|
|
/* from command */
|
2010-02-22 23:26:13 +00:00
|
|
|
|
r_core_cmd_command (core, input+1);
|
2009-02-05 21:08:46 +00:00
|
|
|
|
break;
|
|
|
|
|
case '(':
|
2012-09-19 12:08:44 +00:00
|
|
|
|
r_cmd_macro_call (&core->rcmd->macro, input+1);
|
2009-02-05 21:08:46 +00:00
|
|
|
|
break;
|
|
|
|
|
case '?':
|
2010-02-01 10:55:56 +00:00
|
|
|
|
r_cons_printf (
|
2009-02-05 21:08:46 +00:00
|
|
|
|
"Usage: . [file] | [!command] | [(macro)]\n"
|
2011-08-27 18:25:37 +00:00
|
|
|
|
" . ; repeat last command backward\n"
|
|
|
|
|
" .. ; repeat last command forward (same as \\n)\n"
|
2012-11-05 01:00:34 +00:00
|
|
|
|
" .:8080 ; listen for commands on given tcp port\n"
|
2013-09-03 23:14:35 +00:00
|
|
|
|
" . foo.r2 ; interpret r2 script\n"
|
|
|
|
|
" .- ; open cfg.editor and interpret tmp file\n"
|
2009-02-05 21:08:46 +00:00
|
|
|
|
" .!rabin -ri $FILE ; interpret output of command\n"
|
2009-02-16 23:09:40 +00:00
|
|
|
|
" .(foo 1 2 3) ; run macro 'foo' with args 1, 2, 3\n"
|
2011-02-25 10:45:05 +00:00
|
|
|
|
" ./ ELF ; interpret output of command /m ELF as r. commands\n");
|
2009-02-16 23:09:40 +00:00
|
|
|
|
break;
|
|
|
|
|
default:
|
2013-08-13 00:28:17 +00:00
|
|
|
|
inp = strdup (input);
|
|
|
|
|
filter = strchr (inp, '~');
|
|
|
|
|
if (filter) *filter = 0;
|
|
|
|
|
ptr = str = r_core_cmd_str (core, inp);
|
|
|
|
|
if (filter) *filter = '~';
|
2012-06-12 00:51:34 +00:00
|
|
|
|
r_cons_break (NULL, NULL);
|
2010-02-01 10:55:56 +00:00
|
|
|
|
for (;;) {
|
2012-06-12 00:51:34 +00:00
|
|
|
|
if (r_cons_singleton()->breaked) break;
|
2010-02-22 23:26:13 +00:00
|
|
|
|
eol = strchr (ptr, '\n');
|
2011-08-27 18:25:37 +00:00
|
|
|
|
if (eol) *eol = '\0';
|
2013-08-13 00:28:17 +00:00
|
|
|
|
if (*ptr) {
|
|
|
|
|
char *p = r_str_concat (strdup (ptr), filter);
|
|
|
|
|
r_core_cmd0 (core, p);
|
|
|
|
|
free (p);
|
|
|
|
|
}
|
2009-02-16 23:09:40 +00:00
|
|
|
|
if (!eol) break;
|
|
|
|
|
ptr = eol+1;
|
|
|
|
|
}
|
2012-06-12 00:51:34 +00:00
|
|
|
|
r_cons_break_end ();
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
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]) {
|
2013-10-19 21:10:08 +00:00
|
|
|
|
case 'm':
|
|
|
|
|
n = r_num_math (core->num, input+1);
|
|
|
|
|
if (n>1) core->blocksize_max = n;
|
|
|
|
|
else r_cons_printf ("0x%x\n", (ut32)core->blocksize_max);
|
|
|
|
|
break;
|
2012-06-22 01:49:25 +00:00
|
|
|
|
case '+':
|
|
|
|
|
n = r_num_math (core->num, input+1);
|
|
|
|
|
r_core_block_size (core, core->blocksize+n);
|
|
|
|
|
break;
|
|
|
|
|
case '-':
|
|
|
|
|
n = r_num_math (core->num, input+1);
|
|
|
|
|
r_core_block_size (core, core->blocksize-n);
|
|
|
|
|
break;
|
2012-02-27 01:40:27 +00:00
|
|
|
|
case 'f':
|
|
|
|
|
if (input[1]==' ') {
|
|
|
|
|
flag = r_flag_get (core->flags, input+2);
|
|
|
|
|
if (flag)
|
|
|
|
|
r_core_block_size (core, flag->size);
|
2013-01-16 11:17:14 +00:00
|
|
|
|
else eprintf ("bf: cannot find flag named '%s'\n", input+2);
|
2012-02-27 01:40:27 +00:00
|
|
|
|
} else eprintf ("Usage: bf [flagname]\n");
|
2011-04-18 22:59:16 +00:00
|
|
|
|
break;
|
2012-02-27 01:40:27 +00:00
|
|
|
|
case '\0':
|
|
|
|
|
r_cons_printf ("0x%x\n", core->blocksize);
|
2011-11-16 01:05:23 +00:00
|
|
|
|
break;
|
2012-02-27 01:40:27 +00:00
|
|
|
|
case '?':
|
|
|
|
|
r_cons_printf ("Usage: b[f] [arg]\n"
|
2013-10-19 21:10:08 +00:00
|
|
|
|
" b display current block size\n"
|
|
|
|
|
" b+3 increase blocksize by 3\n"
|
|
|
|
|
" b-16 decrement blocksize by 3\n"
|
|
|
|
|
" b 33 set block size to 33\n"
|
|
|
|
|
" b eip+4 numeric argument can be an expression\n"
|
|
|
|
|
" bf foo set block size to flag size\n"
|
|
|
|
|
" bm 1M set max block size\n");
|
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;
|
2013-09-26 19:38:03 +00:00
|
|
|
|
ut64 oldsize, newsize=0;
|
2012-02-27 01:40:27 +00:00
|
|
|
|
st64 delta = 0;
|
|
|
|
|
int grow;
|
2009-03-09 13:08:53 +00:00
|
|
|
|
|
2012-02-27 01:40:27 +00:00
|
|
|
|
oldsize = core->file->size;
|
|
|
|
|
while (*input==' ')
|
|
|
|
|
input++;
|
2011-09-02 01:45:50 +00:00
|
|
|
|
switch (*input) {
|
2013-09-18 22:03:39 +00:00
|
|
|
|
case 'm':
|
|
|
|
|
if (input[1]==' ')
|
|
|
|
|
r_file_rm (input+2);
|
|
|
|
|
else eprintf ("Usage: rm [file] # removes a file\n");
|
|
|
|
|
break;
|
2012-02-27 01:40:27 +00:00
|
|
|
|
case '+':
|
|
|
|
|
case '-':
|
2013-02-06 09:35:23 +00:00
|
|
|
|
delta = (st64)r_num_math (core->num, input);
|
2012-02-27 01:40:27 +00:00
|
|
|
|
newsize = oldsize + delta;
|
2010-03-04 00:46:25 +00:00
|
|
|
|
break;
|
2012-02-27 01:40:27 +00:00
|
|
|
|
case '\0':
|
|
|
|
|
case '?':
|
|
|
|
|
r_cons_printf (
|
2012-11-20 02:59:00 +00:00
|
|
|
|
"Usage: r[+-][ size]\n"
|
2013-09-18 22:03:39 +00:00
|
|
|
|
" r size expand or truncate file to given size\n"
|
|
|
|
|
" r-num remove num bytes, move following data down\n"
|
|
|
|
|
" r+num insert num bytes, move following data up\n"
|
|
|
|
|
" rm [file] remove file\n");
|
2012-02-27 01:40:27 +00:00
|
|
|
|
return R_TRUE;
|
2010-03-04 00:46:25 +00:00
|
|
|
|
default:
|
2012-08-13 23:25:50 +00:00
|
|
|
|
newsize = r_num_math (core->num, input);
|
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) {
|
|
|
|
|
r_io_resize (core->io, newsize);
|
|
|
|
|
core->file->size = newsize;
|
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) {
|
|
|
|
|
r_io_resize (core->io, newsize);
|
|
|
|
|
core->file->size = newsize;
|
2011-07-05 23:29:18 +00:00
|
|
|
|
}
|
|
|
|
|
|
2012-02-27 01:40:27 +00:00
|
|
|
|
if (newsize < core->offset+core->blocksize ||
|
2012-09-21 00:25:44 +00:00
|
|
|
|
oldsize < core->offset+core->blocksize) {
|
2012-02-27 01:40:27 +00:00
|
|
|
|
r_core_block_read (core, 0);
|
2012-09-21 00:25:44 +00:00
|
|
|
|
}
|
2012-02-27 01:40:27 +00:00
|
|
|
|
return R_TRUE;
|
2011-10-11 00:13:15 +00:00
|
|
|
|
}
|
|
|
|
|
|
2012-02-27 01:40:27 +00:00
|
|
|
|
static int cmd_eval(void *data, const char *input) {
|
2013-10-08 14:07:17 +00:00
|
|
|
|
char *p;
|
2010-03-30 21:12:19 +00:00
|
|
|
|
RCore *core = (RCore *)data;
|
2010-02-01 10:55:56 +00:00
|
|
|
|
switch (input[0]) {
|
2013-10-06 13:04:19 +00:00
|
|
|
|
case 'x': // exit
|
|
|
|
|
return cmd_quit (data, "");
|
2009-02-05 21:08:46 +00:00
|
|
|
|
case '\0':
|
2010-05-19 22:59:42 +00:00
|
|
|
|
r_config_list (core->config, NULL, 0);
|
2009-02-05 21:08:46 +00:00
|
|
|
|
break;
|
2013-05-22 02:22:49 +00:00
|
|
|
|
case 'c':
|
2013-07-17 01:51:53 +00:00
|
|
|
|
switch (input[1]) {
|
2013-10-08 14:07:17 +00:00
|
|
|
|
case 'h': // echo
|
|
|
|
|
p = strchr (input, ' ');
|
|
|
|
|
if (p) {
|
|
|
|
|
r_cons_strcat (p+1);
|
|
|
|
|
r_cons_newline ();
|
|
|
|
|
}
|
|
|
|
|
break;
|
2013-10-06 13:23:06 +00:00
|
|
|
|
case 'd':
|
|
|
|
|
r_cons_pal_init (NULL);
|
|
|
|
|
break;
|
2013-07-17 01:51:53 +00:00
|
|
|
|
case '?':
|
2013-07-17 17:34:27 +00:00
|
|
|
|
r_cons_printf ("Usage: ec[s?] [key][[=| ]fg] [bg]\n"
|
|
|
|
|
" ec list all color keys\n"
|
|
|
|
|
" ec* (TODO) same as above, but using r2 commands\n"
|
2013-10-06 13:23:06 +00:00
|
|
|
|
" ecd set default palette\n"
|
2013-07-17 20:12:14 +00:00
|
|
|
|
" ecr set random palette\n"
|
2013-07-17 17:34:27 +00:00
|
|
|
|
" ecs show a colorful palette\n"
|
|
|
|
|
" ecf dark|white load white color scheme template\n"
|
|
|
|
|
" ec prompt red change coloro of prompt\n"
|
|
|
|
|
"Available colors:\n"
|
|
|
|
|
" rgb:000 24 bit hexadecimal rgb color\n"
|
|
|
|
|
" red|green|blue|. well known ansi colors\n"
|
|
|
|
|
"See:\n"
|
|
|
|
|
" e scr.rgbcolor = true|false for 256 color cube\n"
|
|
|
|
|
" e scr.truecolor = true|false for 256*256*256 colors\n"
|
|
|
|
|
" $DATADIR/radare2/cons ~/.config/radare2/cons ./\n");
|
2013-07-17 01:51:53 +00:00
|
|
|
|
break;
|
|
|
|
|
case 'f':
|
|
|
|
|
if (input[2] == ' ') {
|
|
|
|
|
char *home, path[512];
|
|
|
|
|
snprintf (path, sizeof (path), ".config/radare2/cons/%s", input+3);
|
|
|
|
|
home = r_str_home (path);
|
|
|
|
|
snprintf (path, sizeof (path), R2_DATDIR"/radare2/"
|
|
|
|
|
R2_VERSION"/cons/%s", input+3);
|
2013-07-17 17:34:27 +00:00
|
|
|
|
if (!r_core_cmd_file (core, home))
|
|
|
|
|
if (!r_core_cmd_file (core, path))
|
|
|
|
|
if (!r_core_cmd_file (core, input+3))
|
|
|
|
|
eprintf ("ecf: cannot open colorscheme profile\n");
|
2013-07-17 01:51:53 +00:00
|
|
|
|
free (home);
|
|
|
|
|
} else {
|
|
|
|
|
// TODO: lof stuff
|
2013-07-17 17:34:27 +00:00
|
|
|
|
eprintf ("Usage: ecf [themename].\n");
|
2013-07-17 01:51:53 +00:00
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case 's': r_cons_pal_show (); break;
|
|
|
|
|
case '*': r_cons_pal_list (1); break;
|
|
|
|
|
case '\0': r_cons_pal_list (0); break;
|
2013-07-17 20:12:14 +00:00
|
|
|
|
case 'r': r_cons_pal_random (); break;
|
|
|
|
|
default: {
|
2013-05-22 02:22:49 +00:00
|
|
|
|
char *p = strdup (input+2);
|
2013-05-23 00:26:48 +00:00
|
|
|
|
char *q = strchr (p, '=');
|
|
|
|
|
if (!q) q = strchr (p, ' ');
|
|
|
|
|
if (q) {
|
|
|
|
|
// set
|
2013-07-17 20:12:14 +00:00
|
|
|
|
*q++ = 0;
|
2013-05-23 00:26:48 +00:00
|
|
|
|
r_cons_pal_set (p, q);
|
2013-05-22 02:22:49 +00:00
|
|
|
|
} else {
|
2013-07-17 17:34:27 +00:00
|
|
|
|
const char *k = r_cons_pal_get (p);
|
|
|
|
|
if (k) eprintf ("(%s)(%sCOLOR"Color_RESET")\n", p, k);
|
2013-05-22 02:22:49 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
2013-07-17 01:51:53 +00:00
|
|
|
|
}
|
2013-05-22 02:22:49 +00:00
|
|
|
|
break;
|
2011-05-21 13:45:43 +00:00
|
|
|
|
case 'e':
|
|
|
|
|
if (input[1]==' ') {
|
|
|
|
|
char *p;
|
2012-12-30 00:05:12 +00:00
|
|
|
|
const char *val;
|
2013-01-02 23:47:58 +00:00
|
|
|
|
const char *input2 = strchr (input+2, ' ');
|
2012-12-30 00:05:12 +00:00
|
|
|
|
if (input2) input2++; else input2 = input+2;
|
|
|
|
|
val = r_config_get (core->config, input2);
|
2011-05-21 13:45:43 +00:00
|
|
|
|
p = r_core_editor (core, val);
|
2013-09-03 22:35:48 +00:00
|
|
|
|
if (p) {
|
|
|
|
|
r_str_replace_char (p, '\n', ';');
|
|
|
|
|
r_config_set (core->config, input2, p);
|
|
|
|
|
}
|
2011-05-21 13:45:43 +00:00
|
|
|
|
} else eprintf ("Usage: ee varname\n");
|
|
|
|
|
break;
|
2009-04-06 22:53:25 +00:00
|
|
|
|
case '!':
|
2011-09-02 01:45:50 +00:00
|
|
|
|
input = r_str_chop_ro (input+1);
|
2010-05-19 22:59:42 +00:00
|
|
|
|
if (!r_config_swap (core->config, input))
|
2010-02-01 10:55:56 +00:00
|
|
|
|
eprintf ("r_config: '%s' is not a boolean variable.\n", input);
|
2009-04-06 22:53:25 +00:00
|
|
|
|
break;
|
2009-02-05 21:08:46 +00:00
|
|
|
|
case '-':
|
2010-02-02 10:09:52 +00:00
|
|
|
|
r_core_config_init (core);
|
|
|
|
|
eprintf ("BUG: 'e-' command locks the eval hashtable. patches are welcome :)\n");
|
2009-02-05 21:08:46 +00:00
|
|
|
|
break;
|
2013-07-17 17:34:27 +00:00
|
|
|
|
case 'v': eprintf ("Invalid command '%s'. Use 'e?'\n", input); break;
|
|
|
|
|
case '*': r_config_list (core->config, NULL, 1); break;
|
2009-02-05 21:08:46 +00:00
|
|
|
|
case '?':
|
2011-09-02 01:45:50 +00:00
|
|
|
|
switch (input[1]) {
|
2013-07-17 17:34:27 +00:00
|
|
|
|
case '?': r_config_list (core->config, input+2, 2); break;
|
|
|
|
|
default: r_config_list (core->config, input+1, 2); break;
|
2011-09-02 01:45:50 +00:00
|
|
|
|
case 0:
|
|
|
|
|
r_cons_printf (
|
|
|
|
|
"Usage: e[?] [var[=value]]\n"
|
2013-10-08 22:29:49 +00:00
|
|
|
|
" e? ; show this help\n"
|
|
|
|
|
" e?asm.bytes ; show description\n"
|
|
|
|
|
" e?? ; list config vars with description\n"
|
|
|
|
|
" e ; list config vars\n"
|
|
|
|
|
" e- ; reset config vars\n"
|
|
|
|
|
" e* ; dump config vars in r commands\n"
|
|
|
|
|
" e!a ; invert the boolean value of 'a' var\n"
|
|
|
|
|
" er [key] ; set config key as readonly. no way back\n"
|
|
|
|
|
" ec [k] [color] ; set color for given key (prompt, offset, ...)\n"
|
|
|
|
|
" e a ; get value of var 'a'\n"
|
|
|
|
|
" e a=b ; set var 'a' the 'b' value\n");
|
2011-01-27 08:31:52 +00:00
|
|
|
|
}
|
2009-02-05 21:08:46 +00:00
|
|
|
|
break;
|
2012-09-07 08:07:41 +00:00
|
|
|
|
case 'r':
|
|
|
|
|
if (input[1]) {
|
|
|
|
|
const char *key = input+((input[1]==' ')?2:1);
|
|
|
|
|
if (!r_config_readonly (core->config, key))
|
2013-01-16 11:17:14 +00:00
|
|
|
|
eprintf ("cannot find key '%s'\n", key);
|
2012-09-07 08:07:41 +00:00
|
|
|
|
} else eprintf ("Usage: er [key]\n");
|
|
|
|
|
break;
|
2013-07-17 17:34:27 +00:00
|
|
|
|
case ' ': r_config_eval (core->config, input+1); break;
|
|
|
|
|
default: r_config_eval (core->config, input); break;
|
2009-02-05 21:08:46 +00:00
|
|
|
|
}
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
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;
|
|
|
|
|
int ret;
|
2013-02-07 02:09:53 +00:00
|
|
|
|
if (core->http_up)
|
|
|
|
|
return R_FALSE;
|
2012-12-22 01:37:01 +00:00
|
|
|
|
if (!r_config_get_i (core->config, "scr.interactive"))
|
|
|
|
|
return R_FALSE;
|
|
|
|
|
ret = r_core_visual ((RCore *)data, input);
|
2012-02-27 01:40:27 +00:00
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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) {
|
2013-07-17 01:51:53 +00:00
|
|
|
|
case '!':
|
|
|
|
|
if (input[1]) {
|
|
|
|
|
int olen;
|
|
|
|
|
char *out = NULL;
|
|
|
|
|
char *cmd = r_core_sysenv_begin (core, input);
|
|
|
|
|
if (cmd) {
|
|
|
|
|
ret = r_sys_cmd_str_full (cmd+1, NULL, &out, &olen, NULL);
|
|
|
|
|
r_core_sysenv_end (core, input);
|
|
|
|
|
r_cons_memcat (out, olen);
|
|
|
|
|
free (out);
|
|
|
|
|
free (cmd);
|
|
|
|
|
} //else eprintf ("Error setting up system environment\n");
|
|
|
|
|
} else {
|
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 '?':
|
|
|
|
|
r_core_sysenv_help ();
|
|
|
|
|
break;
|
|
|
|
|
default:
|
2013-03-14 01:32:53 +00:00
|
|
|
|
n = r_num_math (core->num, input);
|
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
2012-09-06 01:12:54 +00:00
|
|
|
|
R_API int r_core_cmd_pipe(RCore *core, char *radare_cmd, char *shell_cmd) {
|
2012-07-01 22:38:02 +00:00
|
|
|
|
char *_ptr;
|
2010-01-15 16:02:04 +00:00
|
|
|
|
#if __UNIX__
|
2009-12-31 00:27:03 +00:00
|
|
|
|
int fds[2];
|
2012-11-20 02:59:00 +00:00
|
|
|
|
int stdout_fd;
|
2012-07-01 22:38:02 +00:00
|
|
|
|
#endif
|
2013-09-26 23:38:49 +00:00
|
|
|
|
int olen, ret = -1, pipecolor = -1;
|
|
|
|
|
char *str, *out = NULL;
|
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=='!') {
|
|
|
|
|
_ptr = (char *)r_str_lastbut (shell_cmd, '~', "\"");
|
|
|
|
|
//ptr = strchr (cmd, '~');
|
|
|
|
|
if (_ptr) {
|
|
|
|
|
*_ptr = '\0';
|
|
|
|
|
_ptr++;
|
|
|
|
|
}
|
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);
|
2012-08-09 08:26:05 +00:00
|
|
|
|
r_sys_cmd_str_full (shell_cmd+1, str, &out, &olen, NULL);
|
2012-07-01 22:38:02 +00:00
|
|
|
|
r_cons_memcat (out, olen);
|
|
|
|
|
if (_ptr)
|
|
|
|
|
r_cons_grep (_ptr);
|
|
|
|
|
free (out);
|
2012-11-13 10:42:21 +00:00
|
|
|
|
ret = 0;
|
2012-07-01 22:38:02 +00:00
|
|
|
|
}
|
|
|
|
|
#if __UNIX__
|
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
|
|
|
|
|
|
|
|
|
stdout_fd = dup (1);
|
|
|
|
|
pipe (fds);
|
2011-03-01 18:06:22 +00:00
|
|
|
|
if (fork ()) {
|
|
|
|
|
dup2 (fds[1], 1);
|
2010-03-01 09:49:04 +00:00
|
|
|
|
close (fds[1]);
|
|
|
|
|
close (fds[0]);
|
|
|
|
|
r_core_cmd (core, radare_cmd, 0);
|
|
|
|
|
r_cons_flush ();
|
|
|
|
|
close (1);
|
2012-11-13 10:42:21 +00:00
|
|
|
|
wait (&ret);
|
2010-03-01 09:49:04 +00:00
|
|
|
|
dup2 (stdout_fd, 1);
|
|
|
|
|
close (stdout_fd);
|
2009-12-31 00:27:03 +00:00
|
|
|
|
} else {
|
2010-03-01 09:49:04 +00:00
|
|
|
|
close (fds[1]);
|
|
|
|
|
dup2 (fds[0], 0);
|
2012-08-13 11:16:06 +00:00
|
|
|
|
//dup2 (1, 2); // stderr goes to stdout
|
2012-10-19 22:31:18 +00:00
|
|
|
|
r_sandbox_system (shell_cmd, 0);
|
2009-12-31 00:27:03 +00:00
|
|
|
|
}
|
2010-01-15 16:02:04 +00:00
|
|
|
|
#else
|
|
|
|
|
#warning r_core_cmd_pipe UNIMPLEMENTED FOR THIS PLATFORM
|
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);
|
|
|
|
|
return ret;
|
2009-12-31 00:27:03 +00:00
|
|
|
|
}
|
|
|
|
|
|
2012-02-27 01:02:44 +00:00
|
|
|
|
static int r_core_cmd_subst_i(RCore *core, char *cmd);
|
2010-03-30 21:12:19 +00:00
|
|
|
|
static int r_core_cmd_subst(RCore *core, char *cmd) {
|
2012-02-27 01:02:44 +00:00
|
|
|
|
int rep = atoi (cmd);
|
2012-08-13 11:16:06 +00:00
|
|
|
|
char *cmt, *colon, *icmd = strdup (cmd);
|
2012-02-27 01:02:44 +00:00
|
|
|
|
cmd = r_str_trim_head_tail (icmd);
|
2012-12-20 10:31:38 +00:00
|
|
|
|
if (*cmd && cmd[1] && !memcmp (cmd, "# ", 2))
|
2012-08-13 11:16:06 +00:00
|
|
|
|
return 0;
|
2012-12-20 10:31:38 +00:00
|
|
|
|
cmt = *icmd ? strchr (icmd+1, '#'): NULL;
|
2013-02-25 01:35:16 +00:00
|
|
|
|
if (cmt && cmt[1]==' ')
|
2012-08-13 11:16:06 +00:00
|
|
|
|
*cmt = 0;
|
2013-02-25 01:35:16 +00:00
|
|
|
|
if (*cmd != '"') {
|
|
|
|
|
colon = strchr (icmd, ';');
|
|
|
|
|
if (colon)
|
|
|
|
|
*colon = 0;
|
|
|
|
|
} else colon = NULL;
|
2012-02-27 01:02:44 +00:00
|
|
|
|
if (rep>0) {
|
|
|
|
|
while (*cmd>='0' && *cmd<='9')
|
|
|
|
|
cmd++;
|
2012-11-06 08:47:52 +00:00
|
|
|
|
// cannot repeat null cmd
|
|
|
|
|
if (!*cmd) return 0;
|
2012-02-27 01:02:44 +00:00
|
|
|
|
}
|
|
|
|
|
if (rep<1) rep = 1;
|
2012-08-19 01:28:17 +00:00
|
|
|
|
while (rep-- && *cmd) {
|
2012-02-27 01:02:44 +00:00
|
|
|
|
int ret = r_core_cmd_subst_i (core, cmd);
|
|
|
|
|
if (ret) {
|
2012-02-27 02:07:32 +00:00
|
|
|
|
free (icmd);
|
2012-02-27 01:02:44 +00:00
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
}
|
2013-06-11 09:49:15 +00:00
|
|
|
|
if (colon && colon[1]) {
|
2012-11-06 08:47:52 +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 {
|
2013-06-11 09:49:15 +00:00
|
|
|
|
if (icmd && !*icmd)
|
|
|
|
|
r_core_cmd_nullcallback (core);
|
2012-08-19 01:28:17 +00:00
|
|
|
|
}
|
2012-02-27 02:07:32 +00:00
|
|
|
|
free (icmd);
|
2012-02-27 01:02:44 +00:00
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2012-08-19 01:28:17 +00:00
|
|
|
|
static char *find_eoq (char *p) {
|
2012-10-30 01:49:05 +00:00
|
|
|
|
for (; *p; p++) {
|
2012-08-19 01:28:17 +00:00
|
|
|
|
if (*p=='"') break;
|
|
|
|
|
if (*p=='\\' && p[1]=='"')
|
|
|
|
|
p++;
|
|
|
|
|
}
|
|
|
|
|
return p;
|
|
|
|
|
}
|
|
|
|
|
|
2012-02-27 01:02:44 +00:00
|
|
|
|
static int r_core_cmd_subst_i(RCore *core, char *cmd) {
|
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;
|
2013-10-08 22:29:49 +00:00
|
|
|
|
int i, ret, pipefd;
|
2013-01-16 11:17:14 +00:00
|
|
|
|
int usemyblock = 0;
|
2009-02-05 21:08:46 +00:00
|
|
|
|
|
2010-02-22 23:26:13 +00:00
|
|
|
|
cmd = r_str_trim_head_tail (cmd);
|
2009-12-31 00:27:03 +00:00
|
|
|
|
|
2010-08-17 11:15:18 +00:00
|
|
|
|
/* quoted / raw command */
|
2011-06-26 19:24:22 +00:00
|
|
|
|
switch (*cmd) {
|
|
|
|
|
case '.':
|
2013-10-08 22:29:49 +00:00
|
|
|
|
if (cmd[1] == '"') /* interpret */
|
|
|
|
|
return r_cmd_call (core->rcmd, cmd);
|
2011-06-26 19:24:22 +00:00
|
|
|
|
break;
|
|
|
|
|
case '"':
|
2012-08-19 01:28:17 +00:00
|
|
|
|
for (cmd++; *cmd; ) {
|
2013-08-29 17:06:23 +00:00
|
|
|
|
int pipefd;
|
2012-08-19 01:28:17 +00:00
|
|
|
|
ut64 oseek = UT64_MAX;
|
2012-08-21 10:06:56 +00:00
|
|
|
|
char *line, *p = find_eoq (cmd);
|
2013-08-29 17:06:23 +00:00
|
|
|
|
if (p && *p) {
|
2012-08-19 01:28:17 +00:00
|
|
|
|
*p = 0;
|
2013-08-29 17:06:23 +00:00
|
|
|
|
// SKIPSPACES in p+1
|
|
|
|
|
while (IS_WHITESPACE (p[1])) p++;
|
2013-05-23 08:33:21 +00:00
|
|
|
|
if (p[1]=='@' || (p[1] && p[2]=='@')) {
|
2012-08-19 01:28:17 +00:00
|
|
|
|
char *q = strchr (p+1, '"');
|
|
|
|
|
if (q) *q = 0;
|
|
|
|
|
oseek = core->offset;
|
|
|
|
|
r_core_seek (core, r_num_math (
|
|
|
|
|
core->num, p+2), 1);
|
|
|
|
|
if (q) {
|
|
|
|
|
*p = '"';
|
|
|
|
|
p = q;
|
|
|
|
|
} else p = NULL;
|
|
|
|
|
}
|
2013-09-29 23:34:14 +00:00
|
|
|
|
if (p && *p && p[1]=='>') {
|
2013-08-29 17:06:23 +00:00
|
|
|
|
char *str = p+2;
|
|
|
|
|
while (*str=='>') str++;
|
|
|
|
|
while (IS_WHITESPACE (*str)) str++;
|
|
|
|
|
r_cons_flush ();
|
|
|
|
|
pipefd = r_cons_pipe_open (str, p[2]=='>');
|
|
|
|
|
}
|
2012-08-21 10:06:56 +00:00
|
|
|
|
line = strdup (cmd);
|
|
|
|
|
line = r_str_replace (line, "\\\"", "\"", R_TRUE);
|
2013-09-29 23:34:14 +00:00
|
|
|
|
if (p && p[1]=='|') {
|
2013-08-29 17:06:23 +00:00
|
|
|
|
str = p+2;
|
|
|
|
|
while (IS_WHITESPACE (*str))str++;
|
|
|
|
|
r_core_cmd_pipe (core, cmd, str);
|
|
|
|
|
} else {
|
|
|
|
|
r_cmd_call (core->rcmd, line);
|
|
|
|
|
}
|
2012-08-21 10:06:56 +00:00
|
|
|
|
free (line);
|
2012-08-19 01:28:17 +00:00
|
|
|
|
if (oseek != UT64_MAX) {
|
|
|
|
|
r_core_seek (core, oseek, 1);
|
|
|
|
|
oseek = UT64_MAX;
|
|
|
|
|
}
|
2013-09-29 23:14:04 +00:00
|
|
|
|
if (pipefd >0) {//!= -1) {
|
|
|
|
|
r_cons_flush ();
|
|
|
|
|
r_cons_pipe_close (pipefd);
|
2013-08-29 17:06:23 +00:00
|
|
|
|
}
|
2012-08-19 01:28:17 +00:00
|
|
|
|
if (!p) break;
|
|
|
|
|
*p = '"';
|
|
|
|
|
cmd = p+1;
|
|
|
|
|
} else {
|
2013-08-29 17:06:23 +00:00
|
|
|
|
eprintf ("Missing \" in (%s).", cmd);
|
2012-08-19 01:28:17 +00:00
|
|
|
|
return R_FALSE;
|
|
|
|
|
}
|
2009-12-31 00:27:03 +00:00
|
|
|
|
}
|
2012-08-19 01:28:17 +00:00
|
|
|
|
return R_TRUE;
|
2011-06-26 19:24:22 +00:00
|
|
|
|
case '(':
|
2012-02-27 01:02:44 +00:00
|
|
|
|
if (cmd[1] != '*')
|
2012-09-19 12:08:44 +00:00
|
|
|
|
return r_cmd_call (core->rcmd, cmd);
|
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 */
|
2010-08-24 02:09:12 +00:00
|
|
|
|
if (*cmd!='#') {
|
2012-01-31 01:45:17 +00:00
|
|
|
|
ptr = (char *)r_str_lastbut (cmd, '#', quotestr);
|
2012-08-13 11:16:06 +00:00
|
|
|
|
if (ptr && ptr[1]==' ') *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 */
|
2012-01-31 01:45:17 +00:00
|
|
|
|
// TODO: must honor " and ` boundaries
|
|
|
|
|
//ptr = strrchr (cmd, ';');
|
2012-02-27 01:02:44 +00:00
|
|
|
|
if (*cmd!='#') {
|
|
|
|
|
ptr = (char *)r_str_lastbut (cmd, ';', quotestr);
|
|
|
|
|
if (ptr) {
|
|
|
|
|
int ret ;
|
|
|
|
|
*ptr = '\0';
|
|
|
|
|
if (r_core_cmd_subst (core, cmd) == -1)
|
|
|
|
|
return -1;
|
|
|
|
|
cmd = ptr+1;
|
|
|
|
|
ret = r_core_cmd_subst (core, cmd);
|
|
|
|
|
*ptr = ';';
|
|
|
|
|
return ret;
|
|
|
|
|
//r_cons_flush ();
|
|
|
|
|
}
|
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, '`');
|
2012-07-05 16:02:12 +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);
|
|
|
|
|
if (*cmd) r_core_cmd_pipe (core, cmd, ptr+1);
|
|
|
|
|
else r_io_system (core->io, ptr+1);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
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, '&');
|
2011-06-26 21:49:11 +00:00
|
|
|
|
while (ptr && ptr[1]=='&') {
|
|
|
|
|
*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);
|
2009-12-31 00:27:03 +00:00
|
|
|
|
return ret;
|
|
|
|
|
}
|
2011-08-27 18:25:37 +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
|
|
|
|
|
2010-02-22 23:26:13 +00:00
|
|
|
|
ptr = strchr (cmd, '<');
|
2009-02-05 21:08:46 +00:00
|
|
|
|
if (ptr) {
|
|
|
|
|
ptr[0] = '\0';
|
|
|
|
|
if (ptr[1]=='<') {
|
|
|
|
|
/* this is a bit mess */
|
2011-11-01 03:37:13 +00:00
|
|
|
|
//const char *oprompt = strdup (r_line_singleton ()->prompt);
|
|
|
|
|
//oprompt = ">";
|
2011-08-27 18:25:37 +00:00
|
|
|
|
for (str=ptr+2; str[0]==' '; str++);
|
2010-02-28 21:58:21 +00:00
|
|
|
|
eprintf ("==> Reading from stdin until '%s'\n", str);
|
|
|
|
|
free (core->oobi);
|
|
|
|
|
core->oobi = malloc (1);
|
2012-08-19 01:28:17 +00:00
|
|
|
|
if (core->oobi)
|
|
|
|
|
core->oobi[0] = '\0';
|
2009-02-05 21:08:46 +00:00
|
|
|
|
core->oobi_len = 0;
|
|
|
|
|
for (;;) {
|
|
|
|
|
char buf[1024];
|
|
|
|
|
int ret;
|
2011-03-01 18:06:22 +00:00
|
|
|
|
write (1, "> ", 2);
|
2010-08-10 10:34:10 +00:00
|
|
|
|
fgets (buf, sizeof (buf)-1, stdin); // XXX use r_line ??
|
2010-03-01 09:49:04 +00:00
|
|
|
|
if (feof (stdin))
|
2009-02-05 21:08:46 +00:00
|
|
|
|
break;
|
2010-03-01 09:49:04 +00:00
|
|
|
|
buf[strlen (buf)-1]='\0';
|
|
|
|
|
ret = strlen (buf);
|
2011-03-06 14:21:13 +00:00
|
|
|
|
core->oobi_len += ret;
|
2010-02-05 11:21:37 +00:00
|
|
|
|
core->oobi = realloc (core->oobi, core->oobi_len+1);
|
2012-08-19 01:28:17 +00:00
|
|
|
|
if (core->oobi) {
|
|
|
|
|
if (!strcmp (buf, str))
|
|
|
|
|
break;
|
|
|
|
|
strcat ((char *)core->oobi, buf);
|
|
|
|
|
}
|
2009-02-05 21:08:46 +00:00
|
|
|
|
}
|
2011-11-01 03:37:13 +00:00
|
|
|
|
//r_line_set_prompt (oprompt);
|
2009-02-05 21:08:46 +00:00
|
|
|
|
} else {
|
2012-10-30 02:22:30 +00:00
|
|
|
|
for (str=ptr+1; *str== ' '; str++);
|
|
|
|
|
if (!*str) goto next;
|
2012-10-30 01:49:05 +00:00
|
|
|
|
eprintf ("Slurping file '%s'\n", str);
|
2012-08-19 01:28:17 +00:00
|
|
|
|
free (core->oobi);
|
2010-02-05 11:21:37 +00:00
|
|
|
|
core->oobi = (ut8*)r_file_slurp (str, &core->oobi_len);
|
2009-03-14 11:39:37 +00:00
|
|
|
|
if (core->oobi == NULL)
|
2013-01-16 11:17:14 +00:00
|
|
|
|
eprintf ("cannot open file\n");
|
2009-03-14 11:39:37 +00:00
|
|
|
|
else if (ptr == cmd)
|
2010-02-05 11:21:37 +00:00
|
|
|
|
return r_core_cmd_buffer (core, (const char *)core->oobi);
|
2009-02-05 21:08:46 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
2012-10-30 02:22:30 +00:00
|
|
|
|
next:
|
2009-12-31 00:27:03 +00:00
|
|
|
|
|
2012-01-31 01:45:17 +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) {
|
2012-11-13 10:42:21 +00:00
|
|
|
|
int pipecolor = r_config_get_i (core->config, "scr.pipecolor");
|
2012-08-13 15:42:25 +00:00
|
|
|
|
int use_editor = R_FALSE;
|
2012-11-20 02:59:00 +00:00
|
|
|
|
//int scrint = r_cons_singleton()->is_interactive;
|
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';
|
|
|
|
|
str = r_str_trim_head_tail (ptr+1+(ptr[1]=='>'));
|
|
|
|
|
if (!*str) 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. */
|
|
|
|
|
r_cons_set_interactive (R_FALSE);
|
2012-08-13 15:42:25 +00:00
|
|
|
|
if (!strcmp (str, "-")) {
|
|
|
|
|
use_editor = R_TRUE;
|
|
|
|
|
str = r_file_temp ("dumpedit");
|
|
|
|
|
r_config_set (core->config, "scr.color", "false");
|
|
|
|
|
}
|
2010-02-28 21:58:21 +00:00
|
|
|
|
pipefd = r_cons_pipe_open (str, ptr[1]=='>');
|
2013-09-18 22:03:39 +00:00
|
|
|
|
if (pipefd != -1) {
|
|
|
|
|
if (!pipecolor)
|
|
|
|
|
r_config_set_i (core->config, "scr.color", 0);
|
2012-11-13 10:42:21 +00:00
|
|
|
|
|
2013-09-18 22:03:39 +00:00
|
|
|
|
ret = r_core_cmd_subst (core, cmd);
|
|
|
|
|
r_cons_flush ();
|
|
|
|
|
r_cons_pipe_close (pipefd);
|
|
|
|
|
}
|
2012-02-05 00:25:40 +00:00
|
|
|
|
r_cons_set_last_interactive ();
|
2012-11-13 10:42:21 +00:00
|
|
|
|
if (!pipecolor) {
|
|
|
|
|
r_config_set_i (core->config, "scr.color", ocolor);
|
|
|
|
|
}
|
2012-08-13 15:42:25 +00:00
|
|
|
|
if (use_editor) {
|
|
|
|
|
const char *editor = r_config_get (core->config, "cfg.editor");
|
2012-10-30 01:49:05 +00:00
|
|
|
|
if (editor && *editor)
|
2012-08-13 15:42:25 +00:00
|
|
|
|
r_sys_cmdf ("%s '%s'", editor, str);
|
2012-10-30 01:49:05 +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);
|
|
|
|
|
r_file_rm (str);
|
|
|
|
|
free (str);
|
|
|
|
|
}
|
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) {
|
2012-06-22 01:49:25 +00:00
|
|
|
|
int oneline = 1;
|
|
|
|
|
if (ptr[1]=='`') {
|
|
|
|
|
strcpy (ptr, ptr+1);
|
|
|
|
|
oneline = 0;
|
|
|
|
|
}
|
2010-02-05 11:21:37 +00:00
|
|
|
|
ptr2 = strchr (ptr+1, '`');
|
2009-12-31 00:27:03 +00:00
|
|
|
|
if (!ptr2) {
|
2013-08-29 17:46:48 +00:00
|
|
|
|
eprintf ("parse: Missing backtick in expression.\n");
|
2009-12-31 00:27:03 +00:00
|
|
|
|
return -1;
|
|
|
|
|
} else {
|
2011-06-26 21:49:11 +00:00
|
|
|
|
*ptr = '\0';
|
|
|
|
|
*ptr2 = '\0';
|
2012-10-25 10:55:28 +00:00
|
|
|
|
if (ptr[1] == '!') {
|
|
|
|
|
str = r_core_cmd_str_pipe (core, ptr+1);
|
|
|
|
|
} else
|
|
|
|
|
str = r_core_cmd_str (core, ptr+1);
|
2012-06-22 01:49:25 +00:00
|
|
|
|
if (oneline)
|
|
|
|
|
for (i=0; str[i]; i++)
|
|
|
|
|
if (str[i]=='\n')
|
|
|
|
|
str[i]=' ';
|
2012-02-12 22:45:04 +00:00
|
|
|
|
str = r_str_concat (str, ptr2+1);
|
|
|
|
|
cmd = r_str_concat (strdup (cmd), str);
|
2010-02-05 11:21:37 +00:00
|
|
|
|
ret = r_core_cmd_subst (core, cmd);
|
|
|
|
|
free (cmd);
|
|
|
|
|
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 `
|
2009-03-21 22:59:35 +00:00
|
|
|
|
|
2009-12-31 00:27:03 +00:00
|
|
|
|
/* grep the content */
|
2012-01-31 01:45:17 +00:00
|
|
|
|
ptr = (char *)r_str_lastbut (cmd, '~', quotestr);
|
2013-06-24 21:06:32 +00:00
|
|
|
|
if (*cmd!='.' && ptr) {
|
2011-06-26 21:49:11 +00:00
|
|
|
|
*ptr = '\0';
|
2011-08-27 18:25:37 +00:00
|
|
|
|
ptr++;
|
2013-06-24 21:06:32 +00:00
|
|
|
|
r_cons_grep (ptr);
|
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 */
|
2012-12-22 02:37:50 +00:00
|
|
|
|
if (*cmd!='(' && *cmd!='"') {
|
2011-01-26 22:40:16 +00:00
|
|
|
|
ptr = strchr (cmd, '@');
|
2012-12-22 02:37:50 +00:00
|
|
|
|
if (ptr == cmd+1 && *cmd=='?')
|
|
|
|
|
ptr = NULL;
|
|
|
|
|
} else ptr = NULL;
|
2011-09-02 01:45:50 +00:00
|
|
|
|
core->tmpseek = ptr? R_TRUE: R_FALSE;
|
2009-02-05 21:08:46 +00:00
|
|
|
|
if (ptr) {
|
2012-05-30 01:23:53 +00:00
|
|
|
|
ut64 tmpoff, tmpbsz, addr;
|
2012-09-20 01:38:48 +00:00
|
|
|
|
ut8 *buf;
|
2012-07-12 01:55:09 +00:00
|
|
|
|
const char *offstr;
|
2012-12-05 23:55:22 +00:00
|
|
|
|
char *f, *ptr2 = strchr (ptr+1, '!');
|
2012-09-27 17:35:19 +00:00
|
|
|
|
int sz, len;
|
2010-08-10 10:34:10 +00:00
|
|
|
|
tmpoff = core->offset;
|
|
|
|
|
tmpbsz = core->blocksize;
|
2012-12-05 23:55:22 +00:00
|
|
|
|
|
2013-09-15 21:57:22 +00:00
|
|
|
|
*ptr = '\0';
|
|
|
|
|
for (ptr++; *ptr== ' '; ptr++);
|
|
|
|
|
ptr--;
|
2013-01-16 11:17:14 +00:00
|
|
|
|
|
|
|
|
|
arroba = strchr (ptr+2, '@');
|
|
|
|
|
repeat_arroba:
|
|
|
|
|
if (arroba)
|
|
|
|
|
*arroba = 0;
|
2012-09-20 01:38:48 +00:00
|
|
|
|
if (ptr[2]==':') {
|
2013-01-16 11:17:14 +00:00
|
|
|
|
usemyblock = 1;
|
2012-09-20 01:38:48 +00:00
|
|
|
|
switch (ptr[1]) {
|
|
|
|
|
case 'f':
|
|
|
|
|
f = r_file_slurp (ptr+3, &sz);
|
|
|
|
|
if (f) {
|
|
|
|
|
buf = malloc (sz);
|
|
|
|
|
if (buf) {
|
|
|
|
|
free (core->block);
|
|
|
|
|
core->block = buf;
|
|
|
|
|
core->blocksize = sz;
|
|
|
|
|
memcpy (core->block, f, sz);
|
2013-01-16 11:17:14 +00:00
|
|
|
|
} else eprintf ("cannot alloc %d", sz);
|
2012-09-20 01:38:48 +00:00
|
|
|
|
free (f);
|
2013-01-16 11:17:14 +00:00
|
|
|
|
} else eprintf ("cannot open '%s'\n", ptr+3);
|
2012-09-20 01:38:48 +00:00
|
|
|
|
break;
|
|
|
|
|
case '8':
|
|
|
|
|
case 'b':
|
|
|
|
|
buf = malloc (strlen (ptr+2));
|
|
|
|
|
if (!buf) {
|
|
|
|
|
eprintf ("cannot allocate\n");
|
|
|
|
|
return R_FALSE;
|
|
|
|
|
}
|
|
|
|
|
len = r_hex_str2bin (ptr+3, buf);
|
|
|
|
|
r_core_block_size (core, len);
|
2012-10-31 15:37:19 +00:00
|
|
|
|
memcpy (core->block, buf, core->blocksize);
|
2012-09-20 01:38:48 +00:00
|
|
|
|
free (buf);
|
|
|
|
|
break;
|
|
|
|
|
case 's':
|
|
|
|
|
len = strlen (ptr+3);
|
|
|
|
|
r_core_block_size (core, len);
|
|
|
|
|
memcpy (core->block, ptr+3, len);
|
|
|
|
|
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:
|
2012-09-20 01:38:48 +00:00
|
|
|
|
for (ptr++;*ptr== ' ';ptr++); ptr--;
|
|
|
|
|
cmd = r_str_clean (cmd);
|
2010-08-10 10:34:10 +00:00
|
|
|
|
if (ptr2) {
|
2012-12-05 23:55:22 +00:00
|
|
|
|
if (strlen (ptr+1)==13 && strlen (ptr2+1)==6 && \
|
|
|
|
|
!memcmp (ptr+1,"0x", 2) && !memcmp (ptr2+1, "0x", 2)) {
|
|
|
|
|
/* 0xXXXX:0xYYYY */
|
|
|
|
|
} else
|
|
|
|
|
if (strlen (ptr+1)==9 && strlen (ptr2+1)==4) {
|
|
|
|
|
/* XXXX:YYYY */
|
|
|
|
|
} else {
|
|
|
|
|
*ptr2 = '\0';
|
|
|
|
|
r_core_block_size (core, r_num_math (core->num, ptr2+1));
|
|
|
|
|
}
|
2010-08-10 10:34:10 +00:00
|
|
|
|
}
|
|
|
|
|
|
2012-07-12 01:55:09 +00:00
|
|
|
|
offstr = r_str_trim_head (ptr+1);
|
|
|
|
|
|
|
|
|
|
addr = r_num_math (core->num, offstr);
|
2012-05-30 01:23:53 +00:00
|
|
|
|
if (isalpha (ptr[1]) && addr== 0) {
|
|
|
|
|
if (!r_flag_get (core->flags, ptr+1)) {
|
|
|
|
|
eprintf ("Invalid address (%s)\n", ptr+1);
|
|
|
|
|
return R_FALSE;
|
|
|
|
|
}
|
2012-07-12 01:55:09 +00:00
|
|
|
|
} else {
|
|
|
|
|
char ch = *offstr;
|
|
|
|
|
if (ch=='-' || ch=='+')
|
|
|
|
|
addr = core->offset+addr;
|
|
|
|
|
}
|
2013-01-16 11:17:14 +00:00
|
|
|
|
next_arroba:
|
|
|
|
|
if (arroba) {
|
|
|
|
|
ptr = arroba; //-3;
|
|
|
|
|
arroba = NULL;
|
|
|
|
|
goto repeat_arroba;
|
|
|
|
|
}
|
2009-02-05 21:08:46 +00:00
|
|
|
|
if (ptr[1]=='@') {
|
2009-03-21 02:17:43 +00:00
|
|
|
|
// TODO: remove temporally seek (should be done by cmd_foreach)
|
2010-03-05 12:18:44 +00:00
|
|
|
|
ret = r_core_cmd_foreach (core, cmd, ptr+2);
|
|
|
|
|
//ret = -1; /* do not run out-of-foreach cmd */
|
2009-12-31 00:27:03 +00:00
|
|
|
|
} else {
|
2013-01-16 11:17:14 +00:00
|
|
|
|
if (usemyblock) {
|
|
|
|
|
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 {
|
|
|
|
|
if (!ptr[1] || r_core_seek (core, addr, 1)) {
|
|
|
|
|
r_core_block_read (core, 0);
|
|
|
|
|
ret = r_cmd_call (core->rcmd, r_str_trim_head (cmd));
|
|
|
|
|
} else ret = 0;
|
|
|
|
|
}
|
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);
|
|
|
|
|
}
|
2010-02-05 11:21:37 +00:00
|
|
|
|
r_core_seek (core, tmpoff, 1);
|
2010-08-10 10:34:10 +00:00
|
|
|
|
*ptr = '@';
|
2009-12-31 00:27:03 +00:00
|
|
|
|
return ret;
|
2009-02-05 21:08:46 +00:00
|
|
|
|
}
|
2009-03-20 21:05:12 +00:00
|
|
|
|
|
2012-09-19 12:08:44 +00:00
|
|
|
|
return cmd? r_cmd_call (core->rcmd, r_str_trim_head (cmd)): R_FALSE;
|
2009-02-05 21:08:46 +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;
|
2009-03-21 22:59:35 +00:00
|
|
|
|
char *str, *ostr;
|
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
|
|
|
|
|
2010-02-28 21:58:21 +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;
|
2009-03-21 22:59:35 +00:00
|
|
|
|
ostr = str = strdup(each);
|
2011-09-11 01:59:24 +00:00
|
|
|
|
//r_cons_break();
|
2009-03-20 21:05:12 +00:00
|
|
|
|
|
2010-02-28 21:58:21 +00:00
|
|
|
|
switch (each[0]) {
|
2009-03-20 21:05:12 +00:00
|
|
|
|
case '?':
|
2010-02-05 11:21:37 +00:00
|
|
|
|
r_cons_printf (
|
|
|
|
|
"Foreach '@@' iterator command:\n"
|
2012-10-30 02:22:30 +00:00
|
|
|
|
" Repeat a command over a list of offsets.\n"
|
2012-10-28 23:47:20 +00:00
|
|
|
|
" x @@ sym.* Run 'x' over all flags matching 'sym.' in current flagspace\n"
|
2010-02-05 11:21:37 +00:00
|
|
|
|
" x @@.file \"\" over the offsets specified in the file (one offset per line)\n"
|
|
|
|
|
" x @@=off1 off2 .. Manual list of offsets\n"
|
|
|
|
|
" x @@=`pdf~call[0]` Run 'x' at every call offset of the current function\n");
|
2009-03-20 21:05:12 +00:00
|
|
|
|
break;
|
|
|
|
|
case '=':
|
|
|
|
|
/* foreach list of items */
|
2009-03-21 22:59:35 +00:00
|
|
|
|
each = str+1;
|
2009-03-20 21:05:12 +00:00
|
|
|
|
do {
|
2011-08-27 18:25:37 +00:00
|
|
|
|
while (*each==' ') each++;
|
2009-03-21 22:59:35 +00:00
|
|
|
|
if (!*each) break;
|
2010-02-05 11:21:37 +00:00
|
|
|
|
str = strchr (each, ' ');
|
2009-03-21 02:17:43 +00:00
|
|
|
|
if (str) {
|
2011-08-27 18:25:37 +00:00
|
|
|
|
*str = '\0';
|
2010-05-19 22:59:42 +00:00
|
|
|
|
addr = r_num_math (core->num, each);
|
2011-08-27 18:25:37 +00:00
|
|
|
|
*str = ' ';
|
2010-05-19 22:59:42 +00:00
|
|
|
|
} else addr = r_num_math (core->num, each);
|
2013-03-08 00:03:37 +00:00
|
|
|
|
//eprintf ("; 0x%08"PFMT64x":\n", addr);
|
2009-03-20 21:05:12 +00:00
|
|
|
|
each = str+1;
|
2010-02-05 11:21:37 +00:00
|
|
|
|
r_core_seek (core, addr, 1);
|
|
|
|
|
r_core_cmd (core, cmd, 0);
|
|
|
|
|
r_cons_flush ();
|
|
|
|
|
} while (str != NULL);
|
2009-03-20 21:05:12 +00:00
|
|
|
|
break;
|
|
|
|
|
case '.':
|
|
|
|
|
if (each[1]=='(') {
|
|
|
|
|
char cmd2[1024];
|
2011-09-11 01:59:24 +00:00
|
|
|
|
// TODO: use r_cons_break() here
|
2010-02-05 11:21:37 +00:00
|
|
|
|
// XXX whats this 999 ?
|
2011-08-27 18:25:37 +00:00
|
|
|
|
i = 0;
|
2011-09-11 01:59:24 +00:00
|
|
|
|
r_cons_break (NULL, NULL);
|
2012-09-19 12:08:44 +00:00
|
|
|
|
for (core->rcmd->macro.counter=0;i<999;core->rcmd->macro.counter++) {
|
2011-09-11 01:59:24 +00:00
|
|
|
|
if (r_cons_singleton ()->breaked)
|
|
|
|
|
break;
|
2012-09-19 12:08:44 +00:00
|
|
|
|
r_cmd_macro_call (&core->rcmd->macro, each+2);
|
|
|
|
|
if (core->rcmd->macro.brk_value == NULL)
|
2009-03-20 21:05:12 +00:00
|
|
|
|
break;
|
|
|
|
|
|
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++;
|
|
|
|
|
}
|
2011-09-11 01:59:24 +00:00
|
|
|
|
r_cons_break_end();
|
2009-03-20 21:05:12 +00:00
|
|
|
|
} else {
|
|
|
|
|
char buf[1024];
|
|
|
|
|
char cmd2[1024];
|
2012-10-19 22:31:18 +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';
|
2012-06-12 00:51:34 +00:00
|
|
|
|
if (fgets (buf, sizeof (buf), fd) == NULL)
|
2010-02-05 11:21:37 +00:00
|
|
|
|
break;
|
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);
|
2013-01-16 11:17:14 +00:00
|
|
|
|
} else eprintf ("cannot open file '%s' to read offsets\n", each+1);
|
2009-03-20 21:05:12 +00:00
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
default:
|
2012-09-19 12:08:44 +00:00
|
|
|
|
core->rcmd->macro.counter = 0;
|
2010-02-28 21:58:21 +00:00
|
|
|
|
//while(str[i]) && !core->interrupted) {
|
2011-06-07 15:53:15 +00:00
|
|
|
|
// split by keywords
|
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;
|
2010-02-05 11:21:37 +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';
|
2010-02-05 11:21:37 +00:00
|
|
|
|
word = strdup (str+j);
|
2009-03-20 21:05:12 +00:00
|
|
|
|
if (word == NULL)
|
|
|
|
|
break;
|
|
|
|
|
str[i] = ch;
|
2011-06-07 15:53:15 +00:00
|
|
|
|
{
|
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..
|
|
|
|
|
r_list_foreach_prev (core->flags->flags, iter, flag) {
|
2010-02-18 15:36:55 +00:00
|
|
|
|
if (r_cons_singleton()->breaked)
|
2009-03-21 02:17:43 +00:00
|
|
|
|
break;
|
2009-03-20 21:05:12 +00:00
|
|
|
|
/* filter per flag spaces */
|
2010-05-19 22:59:42 +00:00
|
|
|
|
if ((core->flags->space_idx != -1) && (flag->space != core->flags->space_idx))
|
2009-03-20 21:05:12 +00:00
|
|
|
|
continue;
|
2011-06-07 15:53:15 +00:00
|
|
|
|
if (r_str_glob (flag->name, word)) {
|
2010-02-05 11:21:37 +00:00
|
|
|
|
r_core_seek (core, flag->offset, 1);
|
2010-04-14 11:02:23 +00:00
|
|
|
|
//r_cons_printf ("# @@ 0x%08"PFMT64x" (%s)\n", core->offset, flag->name);
|
2013-03-17 23:38:04 +00:00
|
|
|
|
// r_cons_printf ("0x%08"PFMT64x" %s\n", core->offset, flag->name);
|
2013-04-02 10:45:16 +00:00
|
|
|
|
eprintf ("# 0x%08"PFMT64x": %s\n", flag->offset, cmd);
|
2010-02-05 11:21:37 +00:00
|
|
|
|
r_core_cmd (core, cmd, 0);
|
2009-03-20 21:05:12 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
2010-02-05 11:21:37 +00:00
|
|
|
|
r_cons_break (NULL, NULL);
|
2009-03-20 21:05:12 +00:00
|
|
|
|
|
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
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2010-02-05 11:21:37 +00:00
|
|
|
|
r_cons_break_end ();
|
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);
|
2009-04-02 10:23:32 +00:00
|
|
|
|
return R_TRUE;
|
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;
|
2012-02-27 01:40:27 +00:00
|
|
|
|
int ret = R_FALSE;
|
2013-09-11 21:41:40 +00:00
|
|
|
|
|
2011-06-28 22:36:52 +00:00
|
|
|
|
if (cstr==NULL)
|
|
|
|
|
return R_FALSE;
|
2011-08-27 18:25:37 +00:00
|
|
|
|
if (log && *cstr && *cstr!='.') {
|
|
|
|
|
free (core->lastcmd);
|
|
|
|
|
core->lastcmd = strdup (cstr);
|
|
|
|
|
}
|
2011-09-03 00:27:27 +00:00
|
|
|
|
/* list r_cmd plugins */
|
2011-06-04 01:14:04 +00:00
|
|
|
|
if (!strcmp (cstr, ":")) {
|
2012-02-14 17:19:16 +00:00
|
|
|
|
RListIter *iter;
|
|
|
|
|
RCmdPlugin *cp;
|
2012-09-19 12:08:44 +00:00
|
|
|
|
r_list_foreach (core->rcmd->plist, iter, cp) {
|
2011-06-04 01:14:04 +00:00
|
|
|
|
r_cons_printf ("%s: %s\n", cp->name, cp->desc);
|
2010-06-03 09:53:42 +00:00
|
|
|
|
}
|
2011-06-04 01:14:04 +00:00
|
|
|
|
return 0;
|
|
|
|
|
}
|
2013-09-11 21:41:40 +00:00
|
|
|
|
ocmd = cmd = malloc (strlen (cstr)+4096);
|
2011-06-04 01:14:04 +00:00
|
|
|
|
if (ocmd == NULL)
|
|
|
|
|
return R_FALSE;
|
|
|
|
|
r_str_cpy (cmd, cstr);
|
2013-09-11 21:41:40 +00:00
|
|
|
|
|
2011-06-04 01:14:04 +00:00
|
|
|
|
if (log) r_line_hist_add (cstr);
|
|
|
|
|
|
2013-09-11 21:41:40 +00:00
|
|
|
|
for (rcmd = cmd;;) {
|
|
|
|
|
ptr = strstr (rcmd, "\n");
|
|
|
|
|
if (ptr) *ptr = '\0';
|
|
|
|
|
ret = r_core_cmd_subst (core, rcmd);
|
|
|
|
|
if (ret == -1) {
|
|
|
|
|
eprintf ("Error running command '%s'\n", rcmd);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
if (!ptr) break;
|
|
|
|
|
rcmd = ptr+1;
|
|
|
|
|
}
|
|
|
|
|
|
2011-06-04 01:14:04 +00:00
|
|
|
|
free (ocmd);
|
|
|
|
|
free (core->oobi);
|
|
|
|
|
core->oobi = NULL;
|
|
|
|
|
core->oobi_len = 0;
|
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) {
|
2013-09-04 00:31:14 +00:00
|
|
|
|
int r, ret = R_TRUE;
|
2013-09-03 23:14:35 +00:00
|
|
|
|
char *nl, *data, *odata;
|
2013-09-03 22:35:48 +00:00
|
|
|
|
|
|
|
|
|
if (!lines || !*lines) return R_TRUE;
|
2013-09-03 23:14:35 +00:00
|
|
|
|
data = odata = strdup (lines);
|
2012-07-12 23:23:05 +00:00
|
|
|
|
nl = strchr (odata, '\n');
|
|
|
|
|
if (nl) {
|
|
|
|
|
do {
|
|
|
|
|
*nl = '\0';
|
2013-09-04 00:31:14 +00:00
|
|
|
|
r = r_core_cmd (core, data, 0);
|
|
|
|
|
if (r == -1) {
|
2013-09-03 22:35:48 +00:00
|
|
|
|
ret = R_FALSE;
|
2012-07-12 23:23:05 +00:00
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
r_cons_flush ();
|
2012-07-20 15:14:28 +00:00
|
|
|
|
if (data[0]=='q') {
|
|
|
|
|
if (data[1]=='!')
|
|
|
|
|
ret = -1;
|
|
|
|
|
else eprintf ("'q': quit ignored. Use 'q!'\n");
|
2012-07-12 23:23:05 +00:00
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
data = nl+1;
|
|
|
|
|
} while ((nl = strchr (data, '\n')));
|
2013-09-03 23:14:35 +00:00
|
|
|
|
}
|
2013-09-04 00:31:14 +00:00
|
|
|
|
if (data && *data)
|
2013-09-03 23:14:35 +00:00
|
|
|
|
r_core_cmd (core, data, 0);
|
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) {
|
2013-09-11 21:41:40 +00:00
|
|
|
|
char *data, *odata;
|
2013-09-03 22:35:48 +00:00
|
|
|
|
data = r_file_abspath (file);
|
2013-09-04 00:31:14 +00:00
|
|
|
|
if (!data) return R_FALSE;
|
2013-09-03 22:35:48 +00:00
|
|
|
|
odata = r_file_slurp (data, NULL);
|
|
|
|
|
free (data);
|
2013-09-04 00:31:14 +00:00
|
|
|
|
if (!odata) return R_FALSE;
|
2013-09-03 22:35:48 +00:00
|
|
|
|
if (!r_core_cmd_lines (core, odata)) {
|
|
|
|
|
eprintf ("Failed to run script '%s'\n", file);
|
|
|
|
|
return R_FALSE;
|
|
|
|
|
}
|
2012-10-31 09:42:49 +00:00
|
|
|
|
return R_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;
|
|
|
|
|
rcmd = ptr = buf = r_sys_cmd_str (command, 0, &len);
|
2009-12-30 10:03:18 +00:00
|
|
|
|
if (buf == NULL)
|
|
|
|
|
return -1;
|
2013-09-11 21:41:40 +00:00
|
|
|
|
ret = r_core_cmd (core, rcmd, 0);
|
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;
|
|
|
|
|
cmd = r_str_dup_printf ("pd %i @ 0x%08"PFMT64x, l, addr);
|
|
|
|
|
if (cmd) {
|
|
|
|
|
ret = r_core_cmd_str (core, cmd);
|
|
|
|
|
free (cmd);
|
|
|
|
|
}
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
R_API char *r_core_disassemble_bytes(RCore *core, ut64 addr, int b) {
|
|
|
|
|
char *cmd, *ret = NULL;
|
|
|
|
|
cmd = r_str_dup_printf ("pD %i @ 0x%08"PFMT64x, b, addr);
|
|
|
|
|
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);
|
|
|
|
|
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);
|
2009-03-14 11:39:37 +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);
|
2009-03-14 11:39:37 +00:00
|
|
|
|
return R_TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
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) {
|
2012-09-27 17:35:19 +00:00
|
|
|
|
char *s, *tmp;
|
2013-10-08 22:29:49 +00:00
|
|
|
|
r_sandbox_disable (1);
|
2013-10-09 00:53:25 +00:00
|
|
|
|
if (r_sandbox_enable (0))
|
2012-11-27 13:09:53 +00:00
|
|
|
|
return r_core_cmd_str (core, cmd);
|
2012-09-06 01:12:54 +00:00
|
|
|
|
r_cons_reset ();
|
|
|
|
|
if (r_file_mkstemp ("cmd", &tmp)) {
|
|
|
|
|
char *_cmd = strdup (cmd);
|
|
|
|
|
int pipefd = r_cons_pipe_open (tmp, 0);
|
2013-10-08 22:29:49 +00:00
|
|
|
|
r_sandbox_disable (0);
|
2012-09-06 01:12:54 +00:00
|
|
|
|
r_core_cmd_subst (core, _cmd);
|
|
|
|
|
r_cons_flush ();
|
|
|
|
|
r_cons_pipe_close (pipefd);
|
2013-10-08 22:29:49 +00:00
|
|
|
|
r_sandbox_disable (1);
|
2012-09-06 01:12:54 +00:00
|
|
|
|
s = r_file_slurp (tmp, NULL);
|
|
|
|
|
r_file_rm (tmp);
|
2013-10-08 22:29:49 +00:00
|
|
|
|
r_sandbox_disable (0);
|
2012-09-06 01:12:54 +00:00
|
|
|
|
free (tmp);
|
|
|
|
|
free (_cmd);
|
|
|
|
|
return s;
|
|
|
|
|
}
|
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;
|
2010-02-01 10:55:56 +00:00
|
|
|
|
r_cons_reset ();
|
|
|
|
|
if (r_core_cmd (core, cmd, 0) == -1) {
|
|
|
|
|
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: "");
|
|
|
|
|
r_cons_reset ();
|
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) {
|
|
|
|
|
// Alias for ".."
|
|
|
|
|
if (core->lastcmd)
|
|
|
|
|
switch (*core->lastcmd) {
|
|
|
|
|
case 'd': // debug
|
|
|
|
|
r_core_cmd0 (core, core->lastcmd);
|
|
|
|
|
switch (core->lastcmd[1]) {
|
|
|
|
|
case 's':
|
|
|
|
|
case 'c':
|
|
|
|
|
r_core_cmd0 (core, "sr pc && pd 1");
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case 'p': // print
|
|
|
|
|
case 'x':
|
|
|
|
|
r_core_cmd0 (core, next? "s++": "s--");
|
|
|
|
|
r_core_cmd0 (core, core->lastcmd);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
R_API void r_core_cmd_init(RCore *core) {
|
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;
|
2013-02-01 02:15:48 +00:00
|
|
|
|
core->rcmd->macro.printf = (PrintfCallback)r_cons_printf;
|
2012-09-19 12:08:44 +00:00
|
|
|
|
r_cmd_set_data (core->rcmd, core);
|
|
|
|
|
r_cmd_add (core->rcmd, "x", "alias for px", &cmd_hexdump);
|
|
|
|
|
r_cmd_add (core->rcmd, "mount", "mount filesystem", &cmd_mount);
|
|
|
|
|
r_cmd_add (core->rcmd, "analysis", "analysis", &cmd_anal);
|
|
|
|
|
r_cmd_add (core->rcmd, "flag", "get/set flags", &cmd_flag);
|
|
|
|
|
r_cmd_add (core->rcmd, "g", "egg manipulation", &cmd_egg);
|
|
|
|
|
r_cmd_add (core->rcmd, "debug", "debugger operations", &cmd_debug);
|
|
|
|
|
r_cmd_add (core->rcmd, "info", "get file info", &cmd_info);
|
|
|
|
|
r_cmd_add (core->rcmd, "cmp", "compare memory", &cmd_cmp);
|
|
|
|
|
r_cmd_add (core->rcmd, "seek", "seek to an offset", &cmd_seek);
|
2012-12-23 12:52:57 +00:00
|
|
|
|
r_cmd_add (core->rcmd, "log", "log utility", &cmd_log);
|
|
|
|
|
r_cmd_add (core->rcmd, "t", "type information (cparse)", &cmd_type);
|
2012-09-19 12:08:44 +00:00
|
|
|
|
r_cmd_add (core->rcmd, "zign", "zignatures", &cmd_zign);
|
|
|
|
|
r_cmd_add (core->rcmd, "Section", "setup section io information", &cmd_section);
|
|
|
|
|
r_cmd_add (core->rcmd, "bsize", "change block size", &cmd_bsize);
|
|
|
|
|
r_cmd_add (core->rcmd, "eval", "evaluate configuration variable", &cmd_eval);
|
|
|
|
|
r_cmd_add (core->rcmd, "print", "print current block", &cmd_print);
|
|
|
|
|
r_cmd_add (core->rcmd, "write", "write bytes", &cmd_write);
|
|
|
|
|
r_cmd_add (core->rcmd, "Code", "code metadata", &cmd_meta);
|
|
|
|
|
r_cmd_add (core->rcmd, "Project", "project", &cmd_project);
|
|
|
|
|
r_cmd_add (core->rcmd, "open", "open or map file", &cmd_open);
|
|
|
|
|
r_cmd_add (core->rcmd, "yank", "yank bytes", &cmd_yank);
|
|
|
|
|
r_cmd_add (core->rcmd, "resize", "change file size", &cmd_resize);
|
|
|
|
|
r_cmd_add (core->rcmd, "Visual", "enter visual mode", &cmd_visual);
|
|
|
|
|
r_cmd_add (core->rcmd, "!", "run system command", &cmd_system);
|
|
|
|
|
r_cmd_add (core->rcmd, "=", "io pipe", &cmd_rap);
|
|
|
|
|
r_cmd_add (core->rcmd, "#", "calculate hash", &cmd_hash);
|
|
|
|
|
r_cmd_add (core->rcmd, "?", "help message", &cmd_help);
|
2012-12-23 12:52:57 +00:00
|
|
|
|
r_cmd_add (core->rcmd, "$", "alias", &cmd_alias);
|
2012-09-19 12:08:44 +00:00
|
|
|
|
r_cmd_add (core->rcmd, ".", "interpret", &cmd_interpret);
|
|
|
|
|
r_cmd_add (core->rcmd, "/", "search kw, pattern aes", &cmd_search);
|
2013-09-03 23:14:35 +00:00
|
|
|
|
r_cmd_add (core->rcmd, "-", "open cfg.editor and run script", &cmd_stdin);
|
2012-09-19 12:08:44 +00:00
|
|
|
|
r_cmd_add (core->rcmd, "(", "macro", &cmd_macro);
|
|
|
|
|
r_cmd_add (core->rcmd, "quit", "exit program session", &cmd_quit);
|
2009-02-05 21:08:46 +00:00
|
|
|
|
}
|