Logo Search packages:      
Sourcecode: radare2 version File versions  Download package

cmd.c

/* radare - LGPL - Copyright 2009-2011 // nibble<.ds@gmail.com>, pancake<nopcode.org> */

#include "r_core.h"
#include "r_io.h"
#include "r_flags.h"
#include "r_hash.h"
#include "r_asm.h"
#include "r_anal.h"
#include "r_util.h"
#include "r_bp.h"

#include <sys/types.h>
#include <stdarg.h>
#if HAVE_LIB_MAGIC
#include <magic.h>
#endif

static int printzoomcallback(void *user, int mode, ut64 addr, ut8 *bufz, ut64 size) {
      RCore *core = (RCore *) user;
      int j, ret = 0;
      RListIter *iter;
      RFlagItem *flag;

      switch (mode) {
      case 'p':
            for (j=0; j<size; j++)
                  if (IS_PRINTABLE (bufz[j]))
                        ret++;
            break;
      case 'f':
            r_list_foreach (core->flags->flags, iter, flag)
                  if (flag->offset <= addr  && addr < flag->offset+flag->size)
                        ret++;
            break;
      case 's':
            j = r_flag_space_get (core->flags, "strings");
            r_list_foreach (core->flags->flags, iter, flag) {
                  if (flag->space == j && ((addr <= flag->offset
                              && flag->offset < addr+size)
                              || (addr <= flag->offset+flag->size
                              && flag->offset+flag->size < addr+size)))
                        ret++;
            }
            break;
      case '0': // 0xFF
            for (j=0; j<size; j++)
                  if (bufz[j] == 0)
                        ret++;
            break;
      case 'F': // 0xFF
            for (j=0; j<size; j++)
                  if (bufz[j] == 0xff)
                        ret++;
            break;
      case 'e': // entropy
            ret = (ut8) (r_hash_entropy_fraction (bufz, size)*255);
            break;
      case 'h': //head
      default:
            ret = *bufz;
      }
      return ret;
}

static int checkbpcallback(RCore *core) {
      ut64 pc = r_debug_reg_get (core->dbg, "pc");
      RBreakpointItem *bpi = r_bp_get (core->dbg->bp, pc);
      if (bpi) {
            if (bpi->data)
                  r_core_cmd (core, bpi->data, 0);
            return R_TRUE;
      }
      return R_FALSE;
}

static int bypassbp(RCore *core) {
      ut64 addr;
      r_debug_reg_sync (core->dbg, R_REG_TYPE_GPR, R_FALSE);
      addr = r_debug_reg_get (core->dbg, "pc");
      RBreakpointItem *bpi = r_bp_get (core->dbg->bp, addr);
      if (!bpi)
            return R_FALSE;
      /* XXX 2 if libr/debug/debug.c:226 is enabled */
      r_debug_step (core->dbg, 1);
      return R_TRUE;
}

static void printoffset(ut64 off, int show_color) {
      if (show_color)
            r_cons_printf (Color_GREEN"0x%08"PFMT64x"  "Color_RESET, off);
      else r_cons_printf ("0x%08"PFMT64x"  ", off);
}

// TODO: move somewhere else
R_API RAsmOp *r_core_disassemble (RCore *core, ut64 addr) {
      ut8 buf[4096];
      static RBuffer *b = NULL; // XXX: never freed and non-thread safe. move to RCore
      RAsmOp *op = R_NEW (RAsmOp);
      if (b == NULL) {
            b = r_buf_new ();
            if (r_core_read_at (core, addr, buf, sizeof (buf))) {
                  b->base = addr;
                  r_buf_set_bytes (b, buf, 4096);
            } else return NULL;
      } else {
            if (addr < b->base || addr > b->base+b->length-32) {
                  if (r_core_read_at (core, addr, buf, sizeof (buf))) {
                        b->base = addr;
                        r_buf_set_bytes (b, buf, 4096);
                  } else return NULL;
            }
      }
      if (r_asm_disassemble (core->assembler, op, b->buf, b->length)<1) {
            free (op);
            return NULL;
      }
      return op;
}

static char *filter_refline(const char *str) {
      char *p, *s = strdup (str);
      p = strstr (s, "->");
      if (p) p[0]=p[1]=' ';
      p = strstr (s, "=<");
      if (p) p[0]=p[1]=' ';
      for (p=s;*p;p++) {
            if (*p=='`') *p = '|';
            if (*p=='-') *p = ' ';
            if (*p=='=') *p = '|';
      }
      return s;
}

/* TODO: move to print/disasm.c */
static void r_print_disasm(RPrint *p, RCore *core, ut64 addr, ut8 *buf, int len, int l) {
      RAnalCC cc = {0};
      RAnalFcn *f = NULL;
      int ret, idx, i, j, k, lines, ostackptr, stackptr = 0;
      int counter = 0;
      int middle = 0;
      char str[128], strsub[128];
      char *line = NULL, *comment, *opstr, *osl = NULL; // old source line
      char *refline = NULL;
      RAsmOp asmop;
      RAnalOp analop;
      RFlagItem *flag;
      RMetaItem *mi;
      ut64 dest = UT64_MAX;

      // TODO: import values from debugger is possible
      // TODO: allow to get those register snapshots from traces
      // TODO: per-function register state trace

      // TODO: All those options must be print flags
      int show_color = r_config_get_i (core->config, "scr.color");
      int decode = r_config_get_i (core->config, "asm.decode");
      int pseudo = r_config_get_i (core->config, "asm.pseudo");
      int filter = r_config_get_i (core->config, "asm.filter");
      int varsub = r_config_get_i (core->config, "asm.varsub");
      int show_lines = r_config_get_i (core->config, "asm.lines");
      int show_dwarf = r_config_get_i (core->config, "asm.dwarf");
      int show_linescall = r_config_get_i (core->config, "asm.linescall");
      int show_trace = r_config_get_i (core->config, "asm.trace");
      int linesout = r_config_get_i (core->config, "asm.linesout");
      int adistrick = r_config_get_i (core->config, "asm.middle"); // TODO: find better name
      int show_offset = r_config_get_i (core->config, "asm.offset");
      int show_bytes = r_config_get_i (core->config, "asm.bytes");
      int show_comments = r_config_get_i (core->config, "asm.comments");
      int show_stackptr = r_config_get_i (core->config, "asm.stackptr");
      int show_xrefs = r_config_get_i (core->config, "asm.xrefs");
      int show_functions = r_config_get_i (core->config, "asm.functions");
      int cursor, nb, nbytes = r_config_get_i (core->config, "asm.nbytes");
      int lbytes = r_config_get_i (core->config, "asm.lbytes");
      int linesopts = 0;
      const char *pre = "  ";
      
      nb = (nbytes*2);
      core->inc = 0;

      if (core->print->cur_enabled) {
            if (core->print->cur<0)
                  core->print->cur = 0;
            cursor = core->print->cur;
      } else cursor = -1;

      if (r_config_get_i (core->config, "asm.linesstyle"))
            linesopts |= R_ANAL_REFLINE_TYPE_STYLE;
      if (r_config_get_i (core->config, "asm.lineswide"))
            linesopts |= R_ANAL_REFLINE_TYPE_WIDE;

      // uhm... is this necesary? imho can be removed
      r_asm_set_pc (core->assembler, addr);
#if 0
      /* find last function else stackptr=0 */
      {
            RAnalFcn *fcni;
            RListIter *iter;

            r_list_foreach (core->anal.fcns, iter, fcni) {
                  if (addr >= fcni->addr && addr<(fcni->addr+fcni->size)) {
                        stack_ptr = fcni->stack;
                        r_cons_printf ("/* function: %s (%d) */\n", fcni->name, fcni->size, stack_ptr);
                        break;
                  }
            }
      }
#endif
      if (core->print->cur_enabled) {
            // TODO: support in-the-middle-of-instruction too
            if (r_anal_op (core->anal, &analop, core->offset+core->print->cur,
                  buf+core->print->cur, (int)(len-core->print->cur))) {
                  // TODO: check for analop.type and ret
                  dest = analop.jump;
#if 0
                  switch (analop.type) {
                  case R_ANAL_OP_TYPE_JMP:
                  case R_ANAL_OP_TYPE_CALL:
                        dest = analop.jump;
                        break;
                  }
#endif
            }
      }
      // TODO: make anal->reflines implicit
      free (core->reflines); // TODO: leak
      free (core->reflines2); // TODO: leak
      core->reflines = r_anal_reflines_get (core->anal, addr, buf, len, -1, linesout, show_linescall);
      core->reflines2 = r_anal_reflines_get (core->anal, addr, buf, len, -1, linesout, 1);
      for (lines=i=idx=ret=0; idx < len && lines < l; idx+=ret,i++, lines++) {
            ut64 at = addr + idx;
            r_asm_set_pc (core->assembler, at);
            line = r_anal_reflines_str (core->anal, core->reflines, at, linesopts);
            refline = filter_refline (line);

            if (show_functions)
                  f = r_anal_fcn_find (core->anal, at, R_ANAL_FCN_TYPE_NULL);
            else f = NULL;
            if (show_comments)
            if ((comment = r_meta_get_string (core->anal->meta, R_META_TYPE_COMMENT, at))) {
                  r_cons_strcat (refline);
                  r_cons_strcat ("        ");
                  r_cons_strcat (comment);
                  free (comment);
            }
            // TODO : line analysis must respect data types! shouldnt be interpreted as code
            ret = r_asm_disassemble (core->assembler, &asmop, buf+idx, len-idx);
            if (ret<1) {
                  ret = 1;
                  //eprintf ("** invalid opcode at 0x%08"PFMT64x" **\n",
                  //    core->assembler->pc + ret);
                  continue;
            }
if (core->inc == 0)
      core->inc = ret;
            r_anal_op (core->anal, &analop, at, buf+idx, (int)(len-idx));
            // Show xrefs
            if (show_xrefs) {
                  RList *xrefs;
                  RAnalRef *refi;
                  RListIter *iter;
                  if ((xrefs = r_anal_xref_get (core->anal, at))) {
                        r_list_foreach (xrefs, iter, refi) {
                              RAnalFcn *fun = r_anal_fcn_find (core->anal, refi->addr, R_ANAL_FCN_TYPE_NULL);
                              r_cons_printf ("%s%s", pre, refline);
                              if (show_color)
                              r_cons_printf (Color_TURQOISE"; %s XREF 0x%08"PFMT64x" (%s)"Color_RESET"\n",
                                          refi->type==R_ANAL_REF_TYPE_CODE?"CODE (JMP)":
                                          refi->type==R_ANAL_REF_TYPE_CALL?"CODE (CALL)":"DATA", refi->addr,
                                          fun?fun->name:"unk");
                              else r_cons_printf ("; %s XREF 0x%08"PFMT64x" (%s)\n",
                                          refi->type==R_ANAL_REF_TYPE_CODE?"CODE (JMP)":
                                          refi->type==R_ANAL_REF_TYPE_CALL?"CODE (CALL)":"DATA", refi->addr,
                                          fun?fun->name:"unk");
                        }
                        r_list_destroy (xrefs);
                  }
            }
            if (adistrick)
                  middle = r_anal_reflines_middle (core->anal,
                              core->reflines, at, analop.length);
            /* XXX: This is really cpu consuming.. need to be fixed */
            if (show_functions) {
                  if (f) {
                        pre = "  ";
                        if (f->addr == at) {
                              char *sign = r_anal_fcn_to_string (core->anal, f);
                              r_cons_printf ("/ %s: %s (%d)\n| ",
                                    (f->type==R_ANAL_FCN_TYPE_FCN||f->type==R_ANAL_FCN_TYPE_SYM)?"function":
                                    (f->type==R_ANAL_FCN_TYPE_IMP)?"import":"loc",
                                    f->name, f->size);
                              if (sign) r_cons_printf ("// %s\n", sign);
                              free (sign);
                              pre = "| ";
                              stackptr = 0;
                        } else if (f->addr+f->size-1 == at) {
                              r_cons_printf ("\\ ");
                        } else if (at > f->addr && at < f->addr+f->size-1) {
                              r_cons_printf ("| ");
                              pre = "| ";
                        } else f = NULL;
                  } else r_cons_printf ("  ");
            }
            flag = r_flag_get_i (core->flags, at);
            //if (flag && !show_bytes) {
            if (flag) {
                  if (show_lines && refline)
                        r_cons_strcat (refline);
                  if (show_offset)
                        printoffset (at, show_color);
                  if (show_functions)
                        r_cons_printf ("%s:\n%s", flag->name, f?"| ":"  ");
                  else r_cons_printf ("%s:\n", flag->name);
            }
            if (show_lines && line)
                  r_cons_strcat (line);
            if (show_offset) {
                  if (at == dest)
                        r_cons_invert (R_TRUE, R_TRUE);
                  printoffset (at, show_color);
            }
            if (show_trace) {
                  RDebugTracepoint *tp = r_debug_trace_get (core->dbg, at);
                  r_cons_printf ("%02x:%04x ", tp?tp->times:0, tp?tp->count:0);
            }
            if (show_stackptr) {
                  r_cons_printf ("%3d%s  ", stackptr,
                        analop.type==R_ANAL_OP_TYPE_CALL?">":
                        stackptr>ostackptr?"+":stackptr<ostackptr?"-":" ");
                  ostackptr = stackptr;
                  stackptr += analop.stackptr;
                  /* XXX if we reset the stackptr 'ret 0x4' has not effect.
                   * Use RAnalFcn->RAnalOp->stackptr? */
                  if (analop.type == R_ANAL_OP_TYPE_RET)
                        stackptr = 0;
            }
            // TODO: implement ranged meta find (if not at the begging of function..
            mi = r_meta_find (core->anal->meta, at, R_META_TYPE_ANY, R_META_WHERE_HERE);
            if (mi)
            switch (mi->type) {
            case R_META_TYPE_STRING:
                  // TODO: filter string (r_str_unscape)
                  {
                  char *out = r_str_unscape (mi->str);
                  r_cons_printf ("string (%"PFMT64d"): \"%s\"\n%s", mi->size, out, pre);
                  free (out);
                  }
                  ret = (int)mi->size;
                  free (line);
                  free (refline);
                  line = refline = NULL;
                  continue;
            case R_META_TYPE_DATA:
                  {
                  int delta = at-mi->from;
                        core->print->flags &= ~R_PRINT_FLAGS_HEADER;
                        r_cons_printf ("hex length=%lld delta=%d\n", mi->size , delta);
                        r_print_hexdump (core->print, at, buf+idx, mi->size-delta, 16, 1);
                  core->inc = 16;
                        core->print->flags |= R_PRINT_FLAGS_HEADER;
                        ret = (int)mi->size-delta;
                        free (line);
                        free (refline);
                        line = refline = NULL;
                  }
                  continue;
            case R_META_TYPE_FORMAT:
                  r_print_format (core->print, at, buf+idx, len-idx, mi->str);
                  ret = (int)mi->size;
                  free (line);
                  free (refline);
                  line = refline = NULL;
                  continue;
            }
            if (show_bytes) {
                  char *str, pad[64];
                  char extra[64];
                  strcpy (extra, " ");
flag = NULL; // HACK
                  if (!flag) {
                        str = strdup (asmop.buf_hex);
                        if (r_str_ansi_len (str) > nb) {
                              char *p = (char *)r_str_ansi_chrn (str, nb);
                              if (p)  {
                                    p[0] = '.';
                                    p[1] = '\0';
                              }
                              *extra = 0;
                        }
                        k = nb-r_str_ansi_len (str);
                        if (k<0) k = 0;
                        if (lbytes && str[strlen(str)-1]!='.') k = k + 1;
                        for (j=0; j<k; j++)
                              pad[j] = ' ';
                        pad[j] = '\0';
                        if (lbytes) {
                              // hack to align bytes left
                              strcpy (extra, pad);
                              *pad=0;
                        }
                        if (show_color) {
                              char *nstr;
                              p->cur_enabled = cursor!=-1;
                              //p->cur = cursor;
                              nstr = r_print_hexpair (p, str, idx);
                              free (str);
                              str = nstr;
                        }
                  } else {
                        str = strdup (flag->name);
                        k = nb-strlen (str)-2;
                        if (k<0) k = 0;
                        for (j=0; j<k; j++)
                              pad[j] = ' ';
                        pad[j] = '\0';
                  }
                  if (0) { // if (flag)
                        if (show_color)
                              r_cons_printf (Color_BWHITE"*[ %s%s]  "Color_RESET, pad, str);
                        else r_cons_printf ("*[ %s%s]  ", pad, str);
                  } else {
                        if (show_color)
                              r_cons_printf (" %s %s %s"Color_RESET, pad, str, extra);
                        else r_cons_printf (" %s %s %s", pad, str, extra);
                  }
                  if (!show_color) free (str);
            }

            if (show_color) {
                  switch (analop.type) {
                  case R_ANAL_OP_TYPE_NOP:
                        r_cons_printf (Color_BLUE);
                        break;
                  case R_ANAL_OP_TYPE_JMP:
                  case R_ANAL_OP_TYPE_CJMP:
                  case R_ANAL_OP_TYPE_UJMP:
                        r_cons_printf (Color_GREEN);
                        break;
                  case R_ANAL_OP_TYPE_CMP:
                        r_cons_printf (Color_BMAGENTA);
                        break;
                  case R_ANAL_OP_TYPE_UCALL:
                  case R_ANAL_OP_TYPE_CALL:
                        r_cons_printf (Color_BGREEN);
                        break;
                  case R_ANAL_OP_TYPE_SWI:
                        r_cons_printf (Color_MAGENTA);
                        break;
                  case R_ANAL_OP_TYPE_RET:
                        r_cons_printf (Color_RED);
                        break;
                  case R_ANAL_OP_TYPE_LOAD:
                        r_cons_printf (Color_YELLOW);
                        break;
                  case R_ANAL_OP_TYPE_STORE:
                        r_cons_printf (Color_BYELLOW);
                        break;
                  }
            }
            if (decode) {
                  // TODO: Use data from code analysis..not raw analop here
                  // if we want to get more information
                  opstr = r_anal_op_to_string (core->anal, &analop);
            } else if (pseudo) {
                  r_parse_parse (core->parser, asmop.buf_asm, str);
                  opstr = str;
            } else if (filter) {
                  r_parse_filter (core->parser, core->flags, asmop.buf_asm, str, sizeof (str));
                  opstr = str;
            } else opstr = asmop.buf_asm;
            if (varsub) {
                  RAnalFcn *f = r_anal_fcn_find (core->anal, at, R_ANAL_FCN_TYPE_NULL);
                  if (f) {
                        r_parse_varsub (core->parser, f, opstr, strsub, sizeof (strsub));
                        if (decode) free (opstr);
                        opstr = strsub;
                  }
            }
            r_cons_strcat (opstr);
            if (decode && !varsub)
                  free (opstr);
            if (show_color)
                  r_cons_strcat (Color_RESET);
            if (show_dwarf) {
                  char *sl = r_bin_meta_get_source_line (core->bin, at);
                  int len = strlen (opstr);
                  if (len<30) len = 30-len;
                  if (sl) {
                        if ((!osl || (osl && strcmp (sl, osl)))) {
                              while (len--)
                                    r_cons_strcat (" ");
                              if (show_color)
                                    r_cons_printf (Color_TURQOISE"  ; %s"Color_RESET"%s", sl, pre);
                              else r_cons_printf ("  ; %s\n%s", sl, pre);
                              free (osl);
                              osl = sl;
                        }
                  } else {
                        eprintf ("Warning: Forced asm.dwarf=false because of error\n");
                        show_dwarf = R_FALSE;
                        r_config_set (core->config, "asm.dwarf", "false");
                  }
            }
            if (middle != 0) {
                  ret -= middle;
                  r_cons_printf (" ;  *middle* %d", ret);
            }
            if (core->assembler->syntax != R_ASM_SYNTAX_INTEL) {
                  RAsmOp ao; /* disassemble for the vm .. */
                  int os = core->assembler->syntax;
                  r_asm_set_syntax (core->assembler, R_ASM_SYNTAX_INTEL);
                  ret = r_asm_disassemble (core->assembler, &ao, buf+idx, len-idx);
                  r_asm_set_syntax (core->assembler, os);
            }

            if (!r_anal_cc_update (core->anal, &cc, &analop)) {
                  if (show_functions) {
                        char *ccstr = r_anal_cc_to_string (core->anal, &cc);
                        r_cons_printf ("\n%s%s    ; %s", pre, refline, ccstr);
                        free (ccstr);
                  }
                  r_anal_cc_reset (&cc);
            }

            switch (analop.type) {
            case R_ANAL_OP_TYPE_JMP:
            case R_ANAL_OP_TYPE_CJMP:
            case R_ANAL_OP_TYPE_CALL:
                  counter++;
                  if (counter<10){
                        core->asmqjmps[counter] = analop.jump;
                        r_cons_printf (" [%d]", counter);
                  } else r_cons_strcat (" [?]");
                  break;
            }

            if (analop.refptr) {
                  ut32 word = 0;
                  int ret = r_io_read_at (core->io, analop.ref, (void *)&word, sizeof (word));
                  if (ret == sizeof (word)) {
                        RMetaItem *mi2 = r_meta_find (core->anal->meta, (ut64)word,
                              R_META_TYPE_ANY, R_META_WHERE_HERE);
                        if (!mi2) {
                              mi2 = r_meta_find (core->anal->meta, (ut64)analop.ref,
                                    R_META_TYPE_ANY, R_META_WHERE_HERE);
                              if (mi2) {
                                    char *str = r_str_unscape (mi2->str);
                                    r_cons_printf (" (at=0x%08"PFMT64x") (len=%"PFMT64d") \"%s\" ", analop.ref, mi2->size, str);
                                    free (str);
                              } else r_cons_printf ("; => 0x%08x ", word);
                        } else {
                              if (mi2->type == R_META_TYPE_STRING) {
                                    char *str = r_str_unscape (mi2->str);
                                    r_cons_printf (" (at=0x%08x) (len=%"PFMT64d") \"%s\" ", word, mi2->size, str);
                                    free (str);
                              } else r_cons_printf ("unknown type '%c'\n", mi2->type);
                        }
                  } else r_cons_printf ("; err [0x%"PFMT64x"]", analop.ref);
            }
            r_cons_newline ();
            if (line) {
                  if (show_lines && analop.type == R_ANAL_OP_TYPE_RET) {
                        if (strchr (line, '>'))
                              memset (line, ' ', strlen (line));
                        r_cons_printf ("%s%s; ------------\n", show_functions?"  ":"", line);
                  }
                  free (line);
                  free (refline);
                  line = refline = NULL;
            }
      }
      free (osl);
}

static int cmd_project(void *data, const char *input) {
      RCore *core = (RCore *)data;
      const char *arg = input+1;
      char *str = strdup (r_config_get (core->config, "file.project"));
      if (*arg==' ') arg++;
      switch (input[0]) {
      case 'o': r_core_project_open (core, input[1]?arg:str); break;
      case 's': r_core_project_save (core, input[1]?arg:str); break;
      case 'i': free (r_core_project_info (core, input[1]?arg:str)); break;
      default:
            r_cons_printf (
            "Usage: P[osi] [file]\n"
            " Po [file]  open project\n"
            " Ps [file]  save project\n"
            " Pi [file]  info\n");
            break;
      }
      free (str);
      return R_TRUE;
}

static int cmd_zign(void *data, const char *input) {
      RCore *core = (RCore *)data;
      RAnalFcn *fcni;
      RListIter *iter;
      RSignItem *item;
      int i, fd, len;
      char *ptr, *name;

      switch (input[0]) {
      case 'g':
            if (input[1]==' ' && input[2]) {
                  ptr = strchr (input+2, ' ');
                  if (ptr) {
                        *ptr = '\0';
                        fd = open (ptr+1, O_RDWR|O_CREAT|O_TRUNC, 0644);
                        if (fd == -1) {
                              eprintf ("Cannot open %s in read-write\n", ptr+1);
                              return R_FALSE;
                        }
                        r_cons_singleton ()->fdout = fd;
                        r_cons_strcat ("# Signatures\n");
                  }
                  r_cons_printf ("zp %s\n", input+2);
                  r_list_foreach (core->anal->fcns, iter, fcni) {
                        ut8 buf[128];
                        if (r_io_read_at (core->io, fcni->addr, buf, sizeof (buf)) == sizeof (buf)) {
                              RFlagItem *flag = r_flag_get_i (core->flags, fcni->addr);
                              if (flag) {
                                    name = flag->name;
                                    r_cons_printf ("zb %s ", name);
                                    len = (fcni->size>sizeof (buf))?sizeof (buf):fcni->size;
                                    for (i=0; i<len; i++) {
                                          r_cons_printf ("%02x", buf[i]);
                                    }
                                    r_cons_newline ();
                              } else eprintf ("Unnamed function at 0x%08"PFMT64x"\n", fcni->addr);
                        } else eprintf ("Cannot read at 0x%08"PFMT64x"\n", fcni->addr);
                  }
                  r_cons_strcat ("zp-\n");
                  if (ptr) {
                        r_cons_flush ();
                        r_cons_singleton ()->fdout = 1;
                        close (fd);
                  }
            } else eprintf ("Usage: zg libc [libc.sig]\n");
            break;
      case 'p':
            if (!input[1])
                  r_cons_printf ("%s", core->sign->prefix);
            else if (!strcmp ("-", input+1))
                  r_sign_prefix (core->sign, "");
            else r_sign_prefix (core->sign, input+2);
            break;
      case 'a':
      case 'b':
      case 'h':
      case 'f':
            ptr = strchr (input+3, ' ');
            if (ptr) {
                  *ptr = 0;
                  r_sign_add (core->sign, core->anal, (int)*input, input+2, ptr+1);
            } else eprintf ("Usage: z%c [name] [arg]\n", *input);
            break;
      case 'c':
            item = r_sign_check (core->sign, core->block, core->blocksize);
            if (item)
                  r_cons_printf ("f sign.%s @ 0x%08"PFMT64x"\n", item->name, core->offset);
            break;
      case '-':
            if (input[1] == '*')
                  r_sign_reset (core->sign);
            else eprintf ("TODO\n");
            break;
      case '/':
            {
                  // TODO: parse arg0 and arg1
                  ut8 *buf;
                  int len, idx;
                  ut64 ini, fin;
                  RSignItem *si;
                  RIOSection *s;
                  if (input[1]) {
                        char *ptr = strchr (input+2, ' ');
                        if (ptr) {
                              *ptr = '\0';
                              ini = r_num_math (core->num, input+2);
                              fin = r_num_math (core->num, ptr+1);
                        } else {
                              ini = core->offset;
                              fin = ini+r_num_math (core->num, input+2);
                        }
                  } else {
                        s = r_io_section_get (core->io, core->io->off);
                        if (s) {
                              ini = core->io->va?s->vaddr:s->offset;
                              fin = ini + (core->io->va?s->vsize:s->size);
                        } else {
                              eprintf ("No section identified, please provide range.\n");
                              return R_FALSE;
                        }
                  }
                  if (ini>=fin) {
                        eprintf ("Invalid range (0x%"PFMT64x"-0x%"PFMT64x").\n", ini, fin);
                        return R_FALSE;
                  }
                  len = fin-ini;
                  buf = malloc (len);
                  if (buf != NULL) {
                        eprintf ("Ranges are: 0x%08"PFMT64x" 0x%08"PFMT64x"\n", ini, fin);
                        r_cons_printf ("f-sign*\n");
                        if (r_io_read_at (core->io, ini, buf, len) == len) {
                              for (idx=0; idx<len; idx++) {
                                    si = r_sign_check (core->sign, buf+idx, len-idx);
                                    if (si) {
                                          if (si->type == 'f')
                                                r_cons_printf ("f sign.fun_%s_%d @ 0x%08"PFMT64x"\n",
                                                      si->name, idx, ini+idx); //core->offset);
                                          else r_cons_printf ("f sign.%s @ 0x%08"PFMT64x"\n",
                                                si->name, ini+idx); //core->offset+idx);
                                    }
                              }
                        } else eprintf ("Cannot read %d bytes at 0x%08"PFMT64x"\n", len, ini);
                        free (buf);
                  } else eprintf ("Cannot alloc %d bytes\n", len);
            }
            break;
      case '\0':
      case '*':
            r_sign_list (core->sign, (input[0]=='*'));
            break;
      default:
      case '?':
            r_cons_printf (
                  "Usage: z[abcp/*-] [arg]\n"
                  " z              show status of zignatures\n"
                  " z*             display all zignatures\n"
                  " zp             display current prefix\n"
                  " zp prefix      define prefix for following zignatures\n"
                  " zp-            unset prefix\n"
                  " z-prefix       unload zignatures prefixed as\n"
                  " z-*            unload all zignatures\n"
                  " za ...         define new zignature for analysis\n"
                  " zf name fmt    define function zignature (fast/slow, args, types)\n"
                  " zb name bytes  define zignature for bytes\n"
                  " zh name bytes  define function header zignature\n"
                  " zg pfx [file]  generate signature for current file\n"
                  " .zc @ fcn.foo  flag signature if matching (.zc@@fcn)\n"
                  " z/ [ini] [end] search zignatures between these regions\n"
                  "NOTE: bytes can contain '.' (dots) to specify a binary mask\n");
            break;
      }
      return 0;
}

static int cmd_rap(void *data, const char *input) {
      RCore *core = (RCore *)data;
      switch (input[0]) {
      case '\0':
            r_core_rtr_list(core);
            break;
      case '?':
            r_core_rtr_help(core);
            break;
      case '+':
            r_core_rtr_add(core, input+1);
            break;
      case '-':
            r_core_rtr_remove(core, input+1);
            break;
      case '=':
            r_core_rtr_session(core, input+1);
            break;
      case '<':
            r_core_rtr_pushout (core, input+1);
            break;
      case '!':
            r_io_system (core->io, input+1);
            break;
      default:
            r_core_rtr_cmd (core, input);
      }
#if 0
      switch (input[0]) {
      case '\0':
            r_lib_list (core->lib);
            r_io_plugin_list (core->io);
            break;
      case '?':
            eprintf ("usage: =[fd] [cmd]\n"
                  "TODO: import the rest of functionality from r1\n");
            break;
      default:
            r_io_set_fd (core->io, core->file->fd);
            if (input[0]==' ')
                  input++;
            r_io_system (core->io, input);
            break;
      }
#endif
      return R_TRUE;
}

static void cmd_reg(RCore *core, const char *str) {
      struct r_reg_item_t *r;
      const char *name;
      char *arg;
      int size, i, type = R_REG_TYPE_GPR;
      switch (str[0]) {
      case '?':
            if (str[1]) {
                  r_debug_reg_sync (core->dbg, R_REG_TYPE_GPR, R_FALSE);
                  r = r_reg_get (core->dbg->reg, str+1, R_REG_TYPE_GPR);
                  if (r == NULL) eprintf ("Unknown register (%s)\n", str+1);
                  else r_cons_printf ("0x%08"PFMT64x"\n", r_reg_get_value (core->dbg->reg, r));
            } else
            eprintf ("Usage: dr[*] [type] [size] - get/set registers\n"
                  " dr?        display this help message\n"
                  " dr         show registers in rows\n"
                  " dr=        show registers in columns\n"
                  " dr?eax     show value of eax register\n"
                  " .dr*       include common register values in flags\n"
                  " .dr-       unflag all registers\n"
                  " drp [file] load register metadata file\n"
                  " drp        display current register profile\n"
                  " drb [type] display hexdump of gpr arena (WIP)\n"
                  " dr         show 'gpr' registers\n"
                  " drt        show all register types\n"
                  " drn [pc]   get register name for pc,sp,bp,a0-3\n"
                  " dro        show previous (old) values of registers\n"
                  " dr all     show all registers\n"
                  " dr flg 1   show flag registers ('flg' is type, see drt)\n"
                  " dr 16      show 16 bit registers\n"
                  " dr 32      show 32 bit registers\n"
                  " dr eax=33  set register value. eax = 33\n");
            // TODO: 'drs' to swap register arenas and display old register valuez
            break;
      case 'b':
            { // WORK IN PROGRESS // DEBUG COMMAND
            int len;
            const ut8 *buf = r_reg_get_bytes (core->dbg->reg, R_REG_TYPE_GPR, &len);
            r_print_hexdump (core->print, 0LL, buf, len, 16, 16);
            }
            break;
      case 'p':
            if (!str[1]) {
                  if (core->dbg->reg_profile)
                        r_cons_printf ("%s\n", core->dbg->reg_profile);
                  else eprintf ("No register profile defined. Try 'dr.'\n");
            } else r_reg_set_profile (core->dbg->reg, str+2);
            core->anal->reg = core->dbg->reg;
            break;
      case 't':
            for (i=0; (name=r_reg_get_type (i));i++)
                  r_cons_printf ("%s\n", name);
            break;
      case 'n':
            name = r_reg_get_name (core->dbg->reg, r_reg_get_name_idx (str+2));
            if (name && *name)
                  r_cons_printf ("%s\n", name);
            else eprintf ("Oops. try dn [pc|sp|bp|a0|a1|a2|a3]\n");
            break;
      case 'd':
            r_debug_reg_list (core->dbg, R_REG_TYPE_GPR, 32, 3); // XXX detect which one is current usage
            break;
      case 'o':
            r_reg_arena_swap (core->dbg->reg, R_FALSE);
            r_debug_reg_list (core->dbg, R_REG_TYPE_GPR, 32, 0); // XXX detect which one is current usage
            r_reg_arena_swap (core->dbg->reg, R_FALSE);
            break;
      case '=':
            if (r_debug_reg_sync (core->dbg, R_REG_TYPE_GPR, R_FALSE)) {
                  r_debug_reg_list (core->dbg, R_REG_TYPE_GPR, 32, 2); // XXX detect which one is current usage
                  r_debug_reg_list (core->dbg, R_REG_TYPE_GPR, 64, 2);
            } else eprintf ("Cannot retrieve registers from pid %d\n", core->dbg->pid);
            break;
      case '*':
            if (r_debug_reg_sync (core->dbg, R_REG_TYPE_GPR, R_FALSE)) {
                  r_debug_reg_list (core->dbg, R_REG_TYPE_GPR, 32, 1); // XXX detect which one is current usage
                  r_debug_reg_list (core->dbg, R_REG_TYPE_GPR, 64, 1);
            } else eprintf ("Cannot retrieve registers from pid %d\n", core->dbg->pid);
            break;
      case '\0':
            if (r_debug_reg_sync (core->dbg, R_REG_TYPE_GPR, R_FALSE)) {
                  r_debug_reg_list (core->dbg, R_REG_TYPE_GPR, 32, 0);
                  r_debug_reg_list (core->dbg, R_REG_TYPE_GPR, 64, 0);
            } else eprintf ("Cannot retrieve registers from pid %d\n", core->dbg->pid);
            break;
      case ' ':
            arg = strchr (str+1, '=');
            if (arg) {
                  *arg = 0;
                  r = r_reg_get (core->dbg->reg, str+1, R_REG_TYPE_GPR);
                  if (r) {
                        //eprintf ("SET(%s)(%s)\n", str, arg+1);
                        r_cons_printf ("0x%08"PFMT64x" ->", str,
                              r_reg_get_value (core->dbg->reg, r));
                        r_reg_set_value (core->dbg->reg, r,
                              r_num_math (core->num, arg+1));
                        r_debug_reg_sync (core->dbg, R_REG_TYPE_GPR, R_TRUE);
                        r_cons_printf ("0x%08"PFMT64x"\n",
                              r_reg_get_value (core->dbg->reg, r));
                  } else eprintf ("Unknown register '%s'\n", str+1);
                  return;
            }
            size = atoi (str+1);
            if (size==0) {
                  arg = strchr (str+1, ' ');
                  if (arg && size==0) {
                        *arg='\0';
                        size = atoi (arg);
                  } else size = 32;
                  //eprintf ("ARG(%s)\n", str+1);
                  type = r_reg_type_by_name (str+1);
            }
            //printf("type = %d\nsize = %d\n", type, size);
            if (type != R_REG_TYPE_LAST) {
                  r_debug_reg_sync (core->dbg, type, R_FALSE);
                  r_debug_reg_list (core->dbg, type, size, str[0]=='*');
            } else eprintf ("cmd_reg: Unknown type\n");
      }
}

static void r_core_cmd_bp(RCore *core, const char *input) {
      RBreakpointItem *bp;
      int hwbp = r_config_get_i (core->config, "dbg.hwbp");
      switch (input[1]) {
      case 't':
            {
            int i = 0;
            RList *list = r_debug_frames (core->dbg);
            RListIter *iter = r_list_iterator (list);
            while (r_list_iter_next (iter)) {
                  RDebugFrame *frame = r_list_iter_get (iter);
                  r_cons_printf ("%d  0x%08"PFMT64x"  %d\n", i++, frame->addr, frame->size);
            }
            r_list_destroy (list);
            }
            break;
      case '\0':
            r_bp_list (core->dbg->bp, input[1]=='*');
            break;
      case '-':
            r_bp_del (core->dbg->bp, r_num_math (core->num, input+2));
            break;
      case 'c': {
                  ut64 off = r_num_math (core->num, input+2);
                  RBreakpointItem *bpi = r_bp_get (core->dbg->bp, off);
                  if (bpi) {
                        char *arg = strchr (input+2, ' ');
                        if (arg) {
                              free (bpi->data);
                              bpi->data = strdup (arg+1);
                        } else {
                              free (bpi->data);
                              bpi->data = NULL;
                        }
                  } else eprintf ("No breakpoint defined at 0x%08"PFMT64x"\n", off);
            }
            break;
      case 'e':
            r_bp_enable (core->dbg->bp, r_num_math (core->num, input+2), 1);
            break;
      case 'd':
            r_bp_enable (core->dbg->bp, r_num_math (core->num, input+2), 0);
            break;
      case 'h':
            if (input[2]==' ') {
                  if (!r_bp_use (core->dbg->bp, input+3))
                        eprintf ("Invalid name: '%s'.\n", input+3);
            } else r_bp_plugin_list (core->dbg->bp);
            break;
      case '?':
            r_cons_printf (
            "Usage: db[ecdht] [[-]addr] [len] [rwx] [condstring]\n"
            "db                ; list breakpoints\n"
            "db sym.main       ; add breakpoint into sym.main\n"
            "db 0x804800       ; add breakpoint\n"
            "db -0x804800      ; remove breakpoint\n"
            "dbe 0x8048000     ; enable breakpoint\n"
            "dbc 0x8048000 cmd ; run command when breakpoint is hit\n"
            "dbd 0x8048000     ; disable breakpoint\n"
            "dbh x86           ; set/list breakpoint plugin handlers\n"
            "Unrelated:\n"
            "dbt               ; debug backtrace\n");
            break;
      default:
            {
                  ut64 addr = r_num_math (core->num, input+2);
                  if (hwbp) bp = r_bp_add_hw (core->dbg->bp, addr, 1, R_BP_PROT_EXEC);
                  else bp = r_bp_add_sw (core->dbg->bp, addr, 1, R_BP_PROT_EXEC);
                  if (!bp) eprintf ("Cannot set breakpoint (%s)\n", input+2);
            }
            break;
      }
}

/* TODO: this should be moved to the core->yank api */
// TODO: arg must be const !!! use strdup here
static int cmd_yank_to(RCore *core, char *arg) {
      ut64 src = core->offset;
      ut64 len = 0;
      ut64 pos = -1;
      char *str;
      ut8 *buf;

      while (*arg==' ')
            arg = arg+1;
      str = strchr (arg, ' ');
      if (str) {
            str[0]='\0';
            len = r_num_math (core->num, arg);
            pos = r_num_math (core->num, str+1);
            str[0]=' ';
      }
      if ((str == NULL) || (pos == -1) || (len == 0)) {
            eprintf ("Usage: yt [len] [dst-addr]\n");
            return 1;
      }
#if 0
      if (!config_get("file.write")) {
            eprintf("You are not in read-write mode.\n");
            return 1;
      }
#endif
      buf = (ut8*)malloc (len);
      r_core_read_at (core, src, buf, len);
      r_core_write_at (core, pos, buf, len);
      free (buf);

      core->offset = src;
      r_core_block_read (core, 0);
      return 0;
}

static int cmd_mount(void *data, const char *_input) {
      ut64 off = 0;
      char *input, *oinput, *ptr, *ptr2;
      RList *list;
      RListIter *iter;
      RFSFile *file;
      RFSRoot *root;
      RFSPlugin *plug;
      RFSPartition *part;
      RCore *core = (RCore *)data;
      input = oinput = strdup (_input);

      switch (*input) {
      case ' ':
            input++;
            if (input[0]==' ')
                  input++;
            ptr = strchr (input, ' ');
            if (ptr) {
                  *ptr = 0;
                  ptr++;
                  ptr2 = strchr (ptr, ' ');
                  if (ptr2) {
                        *ptr2 = 0;
                        off = r_num_math (core->num, ptr2+1);
                  }
                  //r_io_bind (core->io, &(core->fs->iob));
                  r_fs_mount (core->fs, input, ptr, off);
            } else eprintf ("Usage: m ext2 /mnt");
            break;
      case '-':
            r_fs_umount (core->fs, input+1);
            break;
      case '*':
            eprintf ("List commands in radare format\n");
            r_list_foreach (core->fs->roots, iter, root) {
                  r_cons_printf ("m %s 0x%"PFMT64x" %s\n", root->p->name, root->delta, root->path);
            }
            break;
      case '\0':
            r_list_foreach (core->fs->roots, iter, root) {
                  r_cons_printf ("%s\t0x%"PFMT64x"\t%s\n", root->p->name, root->delta, root->path);
            }
            break;
      case 'l': // list of plugins
            r_list_foreach (core->fs->plugins, iter, plug) {
                  r_cons_printf ("%s\t%s\n", plug->name, plug->desc);
            }
            break;
      case 'd':
            input++;
            if (input[0]==' ')
                  input++;
            list = r_fs_dir (core->fs, input);
            if (list) {
                  r_list_foreach (list, iter, file) {
                        r_cons_printf ("%c %s\n", file->type, file->name);
                  }
                  r_list_free (list);
            } else eprintf ("Cannot open '%s' directory\n", input);
            break;
      case 'p':
            input++;
            if (*input == ' ')
                  input++;
            ptr = strchr (input, ' ');
            if (ptr) {
                  *ptr = 0;
                  off = r_num_math (core->num, ptr+1);
            }
            list = r_fs_partitions (core->fs, input, off);
            if (list) {
                  r_list_foreach (list, iter, part) {
                        r_cons_printf ("%d %02x 0x08%"PFMT64x" 0x08%"PFMT64x"\n", part->number,
                              part->type, part->start, part->start+part->length);
                  }
                  r_list_free (list);
            } else eprintf ("Cannot read partition\n");
            break;
      case 'o':
            input++;
            if (input[0]==' ')
                  input++;
            file = r_fs_open (core->fs, input);
            if (file) {
                  // XXX: dump to file or just pipe?
                  r_fs_read (core->fs, file, 0, file->size);
                  r_cons_printf ("f file %d 0x%08"PFMT64x"\n", file->size, file->off);
                  r_fs_close (core->fs, file);
            } else eprintf ("Cannot open file\n");
            break;
      case 'g':
            input++;
            if (input[0]==' ')
                  input++;
            file = r_fs_open (core->fs, input);
            if (file) {
                  // XXX: dump to file or just pipe?
                  r_fs_read (core->fs, file, 0, file->size);
                  write (1, file->data, file->size);
                  r_fs_close (core->fs, file);
                  write (1, "\n", 1);
            } else eprintf ("Cannot open file\n");
            break;
      case 's':
            input++;
            if (input[0]==' ')
                  input++;
            r_fs_prompt (core->fs, input);
            break;
      case 'y':
            eprintf ("TODO\n");
            break;
      case '?':
            r_cons_printf (
            "Usage: m[-?*dgy] [...]\n"
            " m              ; list all mountpoints in human readable format\n"
            " m*             ; same as above, but in r2 commands\n"
            " ml             ; list filesystem plugins\n"
            " m ext2 /mnt 0  ; mount ext2 fs at /mnt with delta 0 on IO\n"
            " m-/            ; umount given path (/)\n"
            " my             ; yank contents of file into clipboard\n"
            " mo /foo        ; get offset and size of given file\n"
            " mg /foo        ; get contents of file dumped to disk (XXX?)\n"
            " md /           ; list directory contents for path\n"
            " mp             ; list all supported partition types\n"
            " mp msdos 0     ; show partitions in msdos format at offset 0\n"
            " ms /mnt        ; open filesystem prompt at /mnt\n"
            " m?             ; show this help\n"
            "TODO: support multiple mountpoints and RFile IO's (need io+core refactor)\n"
            );
            break;
      }
      free (oinput);
      return 0;
}

static int cmd_yank(void *data, const char *input) {
      int i;
      RCore *core = (RCore *)data;
      switch (input[0]) {
      case ' ':
            r_core_yank (core, core->offset, atoi(input+1));
            break;
      case 'y':
            r_core_yank_paste (core, r_num_math(core->num, input+2), 0);
            break;
      case 'p':
            r_cons_memcat ((const char*)core->yank, core->yank_len);
            r_cons_newline ();
            break;
      case 't':
            { /* hacky implementation */
                  char *arg = strdup(input+1);
                  cmd_yank_to(core, arg);
                  free(arg);
            }
            break;
      case '\0':
            if (core->yank) {
                  r_cons_printf ("0x%08"PFMT64x" %d ",
                        core->yank_off, core->yank_len);
                  for (i=0; i<core->yank_len; i++)
                        r_cons_printf ("%02x", core->yank[i]);
                  r_cons_newline ();
            } else eprintf ("No buffer yanked already\n");
            break;
      default:
            r_cons_printf (
            "Usage: y[y] [len] [[@]addr]\n"
            " 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"
            " yp           ; print contents of clipboard\n"
            " yt 0x200     ; paste clipboard to 0x200\n"
            " yy 0x3344    ; paste clipboard\n");
            break;
      }
      return R_TRUE;
}

static int cmd_quit(void *data, const char *input) {
      RCore *core = (RCore *)data;
      switch (input[0]) {
      case '?':
            r_cons_printf (
            "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 '!':
            input++;
      case '\0':
            // TODO
      default:
            r_line_hist_save (".radare2_history");
            if (*input)
                  r_num_math (core->num, input);
            else core->num->value = 0LL;
            //exit (*input?r_num_math (core->num, input+1):0);
            return -2;
      }
      return R_FALSE;
}

static int cmd_interpret(void *data, const char *input) {
      char *str, *ptr, *eol;
      RCore *core = (RCore *)data;
      switch (input[0]) {
      case '\0':
            /* repeat last command */
            /* NOTE: Plugind in r_core_cmd with ugly strcmp */
            break;
      case ' ':
            if (!r_core_cmd_file (core, input+1))
                  eprintf ("Cannot interpret file.\n");
            break;
      case '!':
            /* from command */
            r_core_cmd_command (core, input+1);
            break;
      case '(':
            //eprintf ("macro call (%s)\n", input+1);
            r_cmd_macro_call (&core->cmd->macro, input+1);
            break;
      case '?':
            r_cons_printf (
            "Usage: . [file] | [!command] | [(macro)]\n"
            " . foo.rs          ; interpret r script\n"
            " .!rabin -ri $FILE ; interpret output of command\n"
            " .(foo 1 2 3)      ; run macro 'foo' with args 1, 2, 3\n"
            " ./ ELF            ; interpret output of command /m ELF as r. commands\n");
            break;
      default:
            ptr = str = r_core_cmd_str (core, input);
            for (;;) {
                  eol = strchr (ptr, '\n');
                  if (eol) eol[0]='\0';
                  r_core_cmd (core, ptr, 0);
                  if (!eol) break;
                  ptr = eol+1;
            }
            free (str);
            break;
      }
      return 0;
}

static int cmd_section(void *data, const char *input) {
      RCore *core = (RCore *)data;
      switch (input[0]) {
      case '?':
            r_cons_printf (
            " S                ; list sections\n"
            " S*               ; list sections (in radare commands)\n"
            " S=               ; list sections (in nice ascii-art bars)\n"
            " S [offset] [vaddr] [size] [vsize] [name] [rwx] ; adds new section\n"
            " S -[offset]      ; remove this section definition\n");
            break;
      case ' ':
            switch (input[1]) {
            case '-': // remove
                  if (input[2]=='?' || input[2]=='\0')
                        eprintf ("Usage: S -N   # where N is the section index\n");
                  else r_io_section_rm (core->io, atoi (input+1));
                  break;
            default:
                  {
                  int i, rwx = 7;
                  char *ptr = strdup(input+1);
                  const char *name = NULL;
                  ut64 vaddr = 0LL;
                  ut64 offset = 0LL;
                  ut64 size = 0LL;
                  ut64 vsize = 0LL;

                  i = r_str_word_set0 (ptr);
                  switch (i) {
                  case 6: // get rwx
                        rwx = r_str_rwx (r_str_word_get0 (ptr, 5));
                  case 5: // get name
                        name = r_str_word_get0 (ptr, 4);
                  case 4: // get vsize
                        vsize = r_num_math (core->num, r_str_word_get0 (ptr, 3));
                  case 3: // get size
                        size = r_num_math (core->num, r_str_word_get0 (ptr, 2));
                  case 2: // get vaddr
                        vaddr = r_num_math (core->num, r_str_word_get0 (ptr, 1));
                  case 1: // get offset
                        offset = r_num_math (core->num, r_str_word_get0 (ptr, 0));
                  }
                  r_io_section_add (core->io, offset, vaddr, size, vsize, rwx, name);
                  free (ptr);
                  }
                  break;
            }
            break;
      case '=':
            r_io_section_list_visual (core->io, core->offset, core->blocksize);
            break;
      case '\0':
            r_io_section_list (core->io, core->offset, 0);
            break;
      case '*':
            r_io_section_list (core->io, core->offset, 1);
            break;
      }
      return 0;
}

static int cmd_seek(void *data, const char *input) {
      RCore *core = (RCore *)data;
      char *cmd, *p;
      ut64 off;

      if (input[0]=='r') {
            if (input[1] && input[2]) {
                  off = r_debug_reg_get (core->dbg, input+2);
                  r_core_seek (core, off, 1);
                  r_io_sundo_push (core->io);
            } else eprintf ("Usage: 'sr pc' ; seek to register\n");
      } else
      if (input[0]) { // && input[1]) {
            st32 delta = (input[1]==' ')?2:1;
            off = r_num_math (core->num, input + delta);
            if (input[0]==' ' && (input[1]=='+'||input[1]=='-'))
                  input = input+1;
            switch (input[0]) {
            case ' ':
                  r_core_seek (core, off, 1);
                  r_io_sundo_push (core->io);
                  break;
            case '*':
                  r_io_sundo_list (core->io);
                  break;
            case '+':
                  if (input[1]!='\0') {
                        if (input[1]=='+') delta = core->blocksize; else delta = off;
                        r_core_seek_delta (core, delta);
                  } else if (r_io_sundo_redo (core->io))
                        r_core_seek (core, core->io->off, 0);
                  break;
            case '-':
                  if (input[1]!='\0') {
                        if (input[1]=='-') delta = -core->blocksize; else delta = -off;
                        r_core_seek_delta (core, delta);
                  } else if (r_io_sundo (core->io))
                        r_core_seek (core, core->io->off, 0);
                  break;
            case 'a':
                  off = core->blocksize;
                  if (input[1]&&input[2]) {
                        cmd = strdup (input);
                        p = strchr (cmd+2, ' ');
                        if (p) {
                              off = r_num_math (core->num, p+1);;
                              *p = '\0';
                        }
                        cmd[0] = 's';
                        // perform real seek if provided
                        r_cmd_call (core->cmd, cmd);
                        free (cmd);
                  }
                  r_core_seek_align (core, off, 0);
                  break;
            case 'b':
                  r_core_anal_bb_seek (core, off);
                  break;
            case '?':
                  r_cons_printf (
                  "Usage: s[+-] [addr]\n"
                  " s 0x320    ; seek to this address\n"
                  " s-         ; undo seek\n"
                  " s+         ; redo seek\n"
                  " s*         ; list undo seek history\n"
                  " s++        ; seek blocksize bytes forward\n"
                  " s--        ; seek blocksize bytes backward\n"
                  " s+ 512     ; seek 512 bytes forward\n"
                  " s- 512     ; seek 512 bytes backward\n"
                  " sa [[+-]a] [asz] ; seek asz (or bsize) aligned to addr\n"
                  " sb         ; seek aligned to bb start\n"
                  " sr pc      ; seek to register\n");
                  break;
            }
      } else r_cons_printf ("0x%"PFMT64x"\n", core->offset);
      return 0;
}

static int cmd_help(void *data, const char *input) {
      int i;
      RCore *core = (RCore *)data;
      char out[65];
      ut64 n;
      switch (input[0]) {
      case 'b':
            {
            n = r_num_get (core->num, input+1);
            r_num_to_bits (out, n);
            r_cons_printf ("%s\n", out);
            }
            break;
      case 'f':
            if (input[1]==' ') {
                  char *q, *p = strdup (input+2);
                  if (!p) {
                        eprintf ("Cannot strdup\n");
                        return 0;
                  }
                  q = strchr (p, ' ');
                  if (q) {
                        *q = 0;
                        n = r_num_get (core->num, p);
                        r_str_bits (out, (const ut8*)&n, sizeof (n), q+1);
                        r_cons_printf ("%s\n", out);
                  } else eprintf ("Usage: \"?b value bitstring\"\n");
                  free (p);
            } else eprintf ("Whitespace expected after '?b'\n");
            break;
      case ' ':
            n = r_num_math (core->num, input+1);
            r_cons_printf ("%"PFMT64d" 0x%"PFMT64x"\n", n,n);
            break;
      case '=':
            r_num_math (core->num, input+1);
            break;
      case '+':
            if (input[1]) {
                  if (core->num->value & UT64_GT0)
                        r_core_cmd (core, input+1, 0);
            } else r_cons_printf ("0x%"PFMT64x"\n", core->num->value);
            break;
      case '-':
            if (input[1]) {
                  if (core->num->value & UT64_LT0)
                        r_core_cmd (core, input+1, 0);
            } else r_cons_printf ("0x%"PFMT64x"\n", core->num->value);
            break;
      case '!': // ??
            if (input[1]) {
                  if (core->num->value != UT64_MIN)
                        r_core_cmd (core, input+1, 0);
            } else r_cons_printf ("0x%"PFMT64x"\n", core->num->value);
            break;
      case '$':
            return cmd_help (data, " $?");
      case 'V':
            r_cons_printf ("r2-%s\n", R2_VERSION);
            break;
      case 'z':
            for (input++; input[0]==' '; input++);
            core->num->value = strlen (input);
            break;
      case 'X':
            {
                  for (input++; input[0]==' '; input++);
                  ut64 n = r_num_math (core->num, input);
                  r_cons_printf ("%"PFMT64x"\n", n);
            }
            break;
      case 'x':
            for (input++; input[0]==' '; input++);
            if (!memcmp (input, "0x", 2) || (*input>='0' && *input<='9')) {
                  ut64 n = r_num_math (core->num, input);
                  int bits = r_num_to_bits (NULL, n) / 8;
                  for (i=0; i<bits; i++)
                        r_cons_printf ("%02x", (ut8)((n>>(i*8)) &0xff));
                  r_cons_newline ();
            } else {
                  for (i=0; input[i]; i++)
                        r_cons_printf ("%02x", input[i]);
                  r_cons_newline ();
            }
            break;
      case 'e': // echo
            for (input++; *input==' '; input++);
            r_cons_printf ("%s\n", input);
            break;
      case 's': // sequence from to step
            {
            ut64 from, to, step;
            char *p, *p2;
            for (input++; *input==' '; input++);
            p = strchr (input, ' ');
            if (p) {
                  *p='\0';
                  from = r_num_math (core->num, input);
                  p2 = strchr (p+1, ' ');
                  if (p2) {
                        *p2='\0';
                        step = r_num_math (core->num, p2+1);
                  } else step = 1;
                  to = r_num_math (core->num, p+1);
                  for (;from<=to;from+=step)
                        r_cons_printf ("%"PFMT64d" ", from);
                  r_cons_newline();
            }
            }
            break;
      case 'i': // input num
            {
            char foo[1024];
            for (input++; *input==' '; input++);
            eprintf ("%s: ", input);
            fgets (foo, sizeof (foo)-1, stdin);
            core->num->value = r_num_math (core->num, foo);
            }
            break;
      case 't': {
            struct r_prof_t prof;
            r_prof_start (&prof);
            r_core_cmd (core, input+1, 0);
            r_prof_end (&prof);
            core->num->value = (ut64)prof.result;
            eprintf ("%lf\n", prof.result);
            } break;
      case '?': // ???
            if (input[1]=='?') {
                  r_cons_printf (
                  "Usage: ?[?[?]] expression\n"
                  " ? eip-0x804800  ; calculate result for this math expr\n"
                  " ?= eip-0x804800 ; same as above without user feedback\n"
                  " ?? [cmd]        ; ? == 0  run command when math matches\n"
                  " ?i prompt       ; prompt for number and store in $$?\n"
                  " ?e string       ; echo string\n"
                  " ?b [num]        ; show binary value of number\n"
                  " ?f [num] [str]  ; map each bit of the number as flag string index\n"
                  " ?s from to step ; sequence of numbers from to by steps\n"
                  " ?x num|0xnum|str; returns the hexpair of number or string\n"
                  " ?X num|expr     ; returns the hexadecimal value numeric expr\n"
                  " ?z str          ; returns the length of string (0 if null)\n"
                  " ?t cmd          ; returns the time to run a command\n"
                  " ?! [cmd]        ; ? != 0\n"
                  " ?+ [cmd]        ; ? > 0\n"
                  " ?- [cmd]        ; ? < 0\n"
                  " ???             ; show this help\n"
                  "$variables:\n"
                  " $$  = here (current seek)\n"
                  " $o  = here (current io offset)\n"
                  " $s  = file size\n"
                  " $b  = block size\n"
                  " $j  = jump address\n"
                  " $f  = address of next opcode\n"
                  " $r  = opcode reference pointer\n"
                  " $e  = 1 if end of block, else 0\n"
                  " ${eval} = get value of eval variable\n"
                  " $?  = last comparision value\n");
                  return 0;
            } else
            if (input[1]) {
                  if (core->num->value == UT64_MIN)
                        r_core_cmd (core, input+1, 0);
            } else r_cons_printf ("0x%"PFMT64x"\n", core->num->value);
            break;
      case '\0':
      default:
            r_cons_printf (
            " a                 ; perform analysis of code\n"
            " b [bsz]           ; get or change block size\n"
            " c[dqxXfg] [arg]   ; compare block with given data\n"
            " C[Cf..]           ; Code metadata management\n"
            " d[hrscb]          ; debugger commands\n"
            " e [a[=b]]         ; list/get/set config evaluable vars\n"
            " f [name][sz][at]  ; set flag at current address\n"
            " s [addr]          ; seek to address\n"
            " S?[size] [vaddr]  ; IO section manipulation information\n"
            " i [file]          ; get info about opened file\n"
            " o [file] (addr)   ; open file at optional address\n"
            " p?[len]           ; print current block with format and length\n"
            " V[vcmds]          ; enter visual mode (vcmds=visualvisual  keystrokes)\n"
            " w[mode] [arg]     ; multiple write operations\n"
            " x [len]           ; alias for 'px' (print hexadecimal)\n"
            " y [len] [off]     ; yank/paste bytes from/to memory\n"
            " r[+- ][len]       ; resize file\n"
            " ? [expr]          ; help or evaluate math expression\n"
            " /[xmp/]           ; search for bytes, regexps, patterns, ..\n"
            " ![cmd]            ; run given command as in system(3)\n"
            " = [cmd]           ; run this command via rap://\n"
            " #[algo] [len]     ; calculate hash checksum of current block\n"
            " .[ file|!cmd|cmd|(macro)]  ; interpret as radare cmds\n"
            " :command          ; list or execute a plugin command\n"
            " (macro arg0 arg1) ; define scripting macros\n"
            " q [ret]           ; quit program with a return value\n"
            "Use '?""?""?' evaluation, special vars and scripting facilities\n"
            "Append '?' to any char command to get detailed help\n"
            "Suffix '@ addr[:bsize]' for a temporary seek and/or bsize\n"
            "Suffix '~string:linenumber[column]' to filter output\n"
            );
            break;
      }
      return 0;
}

static int cmd_bsize(void *data, const char *input) {
      RFlagItem *flag;
      RCore *core = (RCore *)data;
      switch (input[0]) {
      case 'f':
            if (input[1]==' ') {
                  flag = r_flag_get (core->flags, input+2);
                  if (flag)
                        r_core_block_size (core, flag->size);
                  else eprintf ("bf: Cannot find flag named '%s'\n", input+2);
            } else eprintf ("Usage: bf [flagname]\n");
            break;
      case '\0':
            r_cons_printf ("0x%x\n", core->blocksize);
            break;
      case '?':
            r_cons_printf ("Usage: b[f] [arg]\n"
                  " b        # display current block size\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");
            break;
      default:
            //input = r_str_clean(input);
            r_core_block_size (core, r_num_math (core->num, input));
            break;
      }
      return 0;
}

// move it out // r_diff maybe?
static int radare_compare(RCore *core, const ut8 *f, const ut8 *d, int len) {
      int i, eq = 0;
      for (i=0;i<len;i++) {
            if (f[i]==d[i]) {
                  eq++;
                  continue;
            }
            r_cons_printf ("0x%08"PFMT64x" (byte=%.2d)   %02x '%c'  ->  %02x '%c'\n",
                  core->offset+i, i+1,
                  f[i], (IS_PRINTABLE(f[i]))?f[i]:' ',
                  d[i], (IS_PRINTABLE(d[i]))?d[i]:' ');
      }
      eprintf ("Compare %d/%d equal bytes\n", eq, len);
      return len-eq;
}

static int cmd_cmp(void *data, const char *input) {
      RCore *core = data;
      FILE *fd;
      ut8 *buf;
      int ret;
      ut32 v32;
      ut64 v64;

      switch (*input) {
      case ' ':
            radare_compare (core, core->block, (ut8*)input+1, strlen (input+1)+1);
            break;
      case 'x':
            if (input[1]!=' ') {
                  eprintf ("Usage: cx 001122'\n");
                  return 0;
            }
            buf = (ut8*)malloc (strlen (input+2));
            ret = r_hex_str2bin (input+2, buf);
            if (ret<1) eprintf ("Cannot parse hexpair\n");
            else radare_compare (core, core->block, buf, ret);
            free (buf);
            break;
      case 'X':
            buf = malloc (core->blocksize);
            ret = r_io_read_at (core->io, r_num_math (core->num, input+1), buf, core->blocksize);
            radare_compare (core, core->block, buf, ret);
            free (buf);
            break;
      case 'f':
            if (input[1]!=' ') {
                  eprintf ("Please. use 'cf [file]'\n");
                  return 0;
            }
            fd = fopen (input+2, "rb");
            if (fd == NULL) {
                  eprintf ("Cannot open file '%s'\n", input+2);
                  return 0;
            }
            buf = (ut8 *)malloc (core->blocksize);
            fread (buf, 1, core->blocksize, fd);
            fclose (fd);
            radare_compare (core, core->block, buf, core->blocksize);
            free (buf);
            break;
      case 'q':
            v64 = (ut64) r_num_math (core->num, input+1);
            radare_compare (core, core->block, (ut8*)&v64, sizeof (v64));
            break;
      case 'd':
            v32 = (ut32) r_num_math (core->num, input+1);
            radare_compare (core, core->block, (ut8*)&v32, sizeof (v32));
            break;
#if 0
      case 'c':
            radare_compare_code (
                  r_num_math (core->num, input+1),
                  core->block, core->blocksize);
            break;
      case 'D':
            { // XXX ugly hack
            char cmd[1024];
            sprintf (cmd, "radiff -b %s %s", ".curblock", input+2);
            r_file_dump (".curblock", config.block, config.block_size);
            radare_system(cmd);
            unlink(".curblock");
            }
            break;
#endif
      case 'g':
            {
            RCore *core2;
            char *file2 = (char*)r_str_chop_ro (input+1);

            if (!(core2 = r_core_new ())) {
                  eprintf ("Cannot init diff core\n");
                  return R_FALSE;
            }
            core2->io->va = core->io->va;
            core2->anal->split = core->anal->split;
            if (!r_core_file_open (core2, file2, 0, 0LL)) {
                  eprintf ("Cannot open diff file '%s'\n", file2);
                  r_core_free (core2);
                  return R_FALSE;
            }
            r_core_bin_load (core2, file2);
            r_core_gdiff (core, core2);
            r_core_free (core2);
            }
            break;
      case '?':
            r_cons_strcat (
            "Usage: c[?cdfx] [argument]\n"
            " c  [string]   Compares a plain with escaped chars string\n"
            //" cc [offset]   Code bindiff current block against offset\n"
            " cd [value]    Compare a doubleword from a math expression\n"
            //" cD [file]     Like above, but using radiff -b\n");
            " cq [value]    Compare a quadword from a math expression\n"
            " cx [hexpair]  Compare hexpair string\n"
            " cX [addr]     Like 'cc' but using hexdiff output\n"
            " cf [file]     Compare contents of file at current seek\n"
            " cg [file]     Graphdiff current file and [file]\n");
            break;
      default:
            eprintf ("Usage: c[?Ddxf] [argument]\n");
      }

      return 0;
}

static int cmd_info(void *data, const char *input) {
      RCore *core = (RCore *)data;
      char buf[1024];
      switch (*input) {
      case 's':
      case 'i':
      case 'I':
      case 'e':
      case 'S':
      case 'z':
            snprintf (buf, sizeof (buf), "rabin2 -%c%s%s '%s'", input[0],
                  input[1]=='*'?"r":"", core->io->va?"v":"", core->file->filename);
            r_sys_cmd (buf);
            break;
      case '?':
            r_cons_printf (
            "Usage: i[eiIsSz]*      ; get info from opened file (rabin2)\n"
            "; Append a '*' to get the output in radare commands\n"
            " ii    ; imports\n"
            " iI    ; binary info\n"
            " ie    ; entrypoint\n"
            " is    ; symbols\n"
            " iS    ; sections\n"
            " iz    ; strings\n");
            break;
      case '*':
            break;
      default:
            if (core->file) {
                  r_cons_printf ("uri: %s\n", core->file->uri);
                  r_cons_printf ("fd: %d\n", core->file->fd->fd);
                  r_cons_printf ("filesize: 0x%x\n", core->file->size);
                  r_cons_printf ("blocksize: 0x%x\n", core->blocksize);
            } else eprintf ("No selected file\n");
      }
      return 0;
}

static void r_core_magic_at(RCore *core, const char *file, ut64 addr, int depth, int v) {
#if HAVE_LIB_MAGIC
      char *fmt, *q, *p;
      const char *str;
      magic_t ck;

      if (depth--<0)
            return;
      if (addr != core->offset)
            r_core_seek (core, addr, R_TRUE);
      if (*file == ' ') file++;
      if (!*file) file = NULL;
      ck = magic_open (0);
      if (magic_load (ck, file) == -1) {
            eprintf ("r_core_magic(\"%s\") %s\n", file, magic_error (ck));
            return;
      }
      if (v) r_cons_printf ("# pm %s @ 0x%"PFMT64x"\n", file?file:"", addr);
      str = magic_buffer (ck, core->block, core->blocksize);
      if (str) {
            if (!v && !strcmp (str, "data"))
                  return;
            p = strdup (str);
            // processing newlinez
            for (q=p; *q; q++)
                  if (q[0]=='\\' && q[1]=='n') {
                        *q = '\n';
                        strcpy (q+1, q+((q[2]==' ')?3:2));
                  }
            r_cons_printf ("%s\n", p);
            // walking childs
            for (q=p; *q; q++) {
                  switch (*q) {
                  case ' ':
                        fmt = q+1;
                        break;
                  case '@':
                        *q = 0;
                        if (!memcmp (q+1, "0x", 2))
                              sscanf (q+3, "%"PFMT64x, &addr);
                        else sscanf (q+1, "%"PFMT64d, &addr);
                        r_core_magic_at (core, fmt, addr, depth, v);
                        *q = '@';
                  }
            }
            free (p);
      }
      magic_close (ck);
#else
      eprintf ("r_core_magic: Compiled without magic :(\n");
#endif
}

static void r_core_magic(RCore *core, const char *file, int v) {
      int depth = r_config_get_i (core->config, "magic.depth");
      ut64 addr = core->offset;
      r_core_magic_at (core, file, addr, depth, v);
      if (addr != core->offset)
            r_core_seek (core, addr, R_TRUE);
}

static int cmd_print(void *data, const char *input) {
      RCore *core = (RCore *)data;
      int i, l, len = core->blocksize;
      ut32 tbs = core->blocksize;

      /* TODO: Change also blocksize for 'pd'.. */
      if (input[0] && input[1]) {
            l = (int) r_num_math (core->num, input+2);
            /* except disasm and memoryfmt (pd, pm) */
            if (input[0] != 'd' && input[0] != 'm') {
                  if (l>0) len = l;
                  if (l>tbs) r_core_block_size (core, l);
                  l = len;
            }
      } else l = len;

      switch (input[0]) {
      case '%':
            {
                  ut64 off = core->io->off;
                  ut64 s = core->file?core->file->size:0;
                  ut64 piece = 0;
                  int w = core->print->cols * 4;
                  piece = s/w;
                  r_cons_strcat ("  [");
                  for (i=0; i<w; i++) {
                        ut64 from = (piece*i);
                        ut64 to = from+piece;
                        if (off>=from && off<to)
                              r_cons_memcat ("#", 1);
                        else r_cons_memcat (".", 1);
                        // TODO: print where flags are.. code, ..
                  }
                  r_cons_strcat ("]\n");
            }
            break;
      case '=':
            for (i=0; i<core->blocksize; i++) {
                  int pc = (core->block[i]*100)/255;
                  r_print_addr (core->print, core->offset+i);
                  r_cons_printf ("%02x", core->block[i]);
                  r_print_progressbar (core->print, pc, 70);
                  r_cons_newline ();
            }
            break;
      case 'b':
            {
            char *buf;
            int size = core->blocksize * 8;
            buf = malloc (size);
            if (buf) {
                  r_str_bits (buf, core->block, size, NULL);
                  r_cons_printf ("%s\n", buf);
                  free (buf);
            } else eprintf ("ERROR: Cannot malloc %d bytes\n", size);
            }
            break;
      case 'D':
      case 'd':
            if (input[1]=='f') {
                  RAnalFcn *f = r_anal_fcn_find (core->anal, core->offset,
                              R_ANAL_FCN_TYPE_FCN|R_ANAL_FCN_TYPE_SYM);
                  if (f) {
                        ut8 *block = malloc (f->size+1);
                        if (block) {
                              r_core_read_at (core, f->addr, block, f->size);
                              r_print_disasm (core->print, core, f->addr, block, f->size, 9999);
                              free (block);
                        }
                  } else eprintf ("Cannot find function at 0x%08"PFMT64x"\n", core->offset);
            } if (l<0) {
                  RList *bwdhits;
                  RListIter *iter;
                  RCoreAsmHit *hit;
                  ut8 *block = malloc (core->blocksize);
                  if (block) {
                        l = -l;
                        bwdhits = r_core_asm_bwdisassemble (core, core->offset, l, core->blocksize);
                        if (bwdhits) {
                              r_list_foreach (bwdhits, iter, hit) {
                                    r_core_read_at (core, hit->addr, block, core->blocksize);
                                    r_print_disasm (core->print, core, hit->addr, block, core->blocksize, l);
                                    r_cons_printf ("------\n");
                              }
                              r_list_free (bwdhits);
                        }
                        free (block);
                  }
            } else r_print_disasm (core->print, core, core->offset, core->block, len, l);
            break;
      case 's':
            if (input[1]=='p') {
                  int mylen = core->block[0];
                  // TODO: add support for 2-4 byte length pascal strings
                  r_print_string (core->print, core->offset, core->block+1, mylen, 0, 1, 0); //, 78, 1);
            } else r_print_string (core->print, core->offset, core->block, len, 0, 1, 0); //, 78, 1);
            break;
      case 'S':
            r_print_string (core->print, core->offset, core->block, len, 1, 1, 0); //, 78, 1);
            break;
      case 'm':
            r_core_magic (core, input+1, R_TRUE);
            break;
      case 'u':
            r_print_string (core->print, core->offset, core->block, len, 0, 1, 1); //, 78, 1);
            break;
      case 'U':
            r_print_string (core->print, core->offset, core->block, len, 1, 1, 1); //, 78, 1);
            break;
      case 'c':
            r_print_code (core->print, core->offset, core->block, len); //, 78, 1);
            break;
      case 'r':
            r_print_raw (core->print, core->block, len);
            break;
      case 'o':
            r_print_hexdump (core->print, core->offset, core->block, len, 8, 1); //, 78, !(input[1]=='-'));
            break;
      case 'x':
            r_print_hexdump (core->print, core->offset, core->block, len, 16, 1); //, 78, !(input[1]=='-'));
            break;
      case '6':
            {
            int malen = (core->blocksize*4)+1;
            ut8 *buf = malloc (malen);
            memset (buf, 0, malen);
            switch (input[1]) {
            case 'e':
                  r_base64_encode (buf, core->block, core->blocksize);
                  printf ("%s\n", buf);
                  break;
            case 'd':
                  if (r_base64_decode (buf, core->block, core->blocksize))
                        printf ("%s\n", buf);
                  else eprintf ("r_base64_decode: invalid stream\n");
                  break;
            default:
                  eprintf ("Usage: p6[ed] [len]  ; base 64 encode/decode\n");
                  break;
            }
            free (buf);
            }
            break;
      case '8':
            r_print_bytes (core->print, core->block, len, "%02x");
            break;
      case 'f':
            r_print_format (core->print, core->offset, core->block, len, input+1);
            break;
      case 'n': // easter penis
            for (l=0; l<10; l++) {
                  printf ("\r8");
                  for (len=0;len<l;len++)
                        printf ("=");
                  printf ("D");
                  r_sys_usleep (100000);
                  fflush (stdout);
            }
            for (l=0; l<3; l++) {
                  printf ("~");
                  fflush (stdout);
                  r_sys_usleep (100000);
            }
            printf ("\n");
            break;
      case 't':
            switch (input[1]) {
                  case ' ':
                  case '\0':
                        for (l=0; l<len; l+=sizeof (time_t))
                              r_print_date_unix (core->print, core->block+l, sizeof (time_t));
                        break;
                  case 'd':
                        for (l=0; l<len; l+=4)
                              r_print_date_dos (core->print, core->block+l, 4);
                        break;
                  case 'n':
                        for (l=0; l<len; l+=sizeof (ut64))
                              r_print_date_w32 (core->print, core->block+l, sizeof (ut64));
                        break;
            case '?':
                  r_cons_printf (
                  "Usage: pt[dn?]\n"
                  " pt      print unix time\n"
                  " ptd     print dos time\n"
                  " ptn     print ntfs time\n"
                  " pt?     show help message\n");
                  break;
            }
            break;
      case 'Z':
            if (input[1]=='?') {
                  r_cons_printf (
                  "Usage: pZ [len]\n"
                  " print N bytes where each byte represents a block of filesize/N\n"
                  "Configuration:\n"
                  " zoom.from  : start address\n"
                  " zoom.to    : end address\n"
                  " zoom.byte  : specify how to calculate each byte\n"
                  "   p : number of printable chars\n"
                  "   f : count of flags in block\n"
                  "   s : strings in range\n"
                  "   0 : number of bytes with value '0'\n"
                  "   F : number of bytes with value 0xFF\n"
                  "   e : calculate entropy and expand to 0-255 range\n"
                  "   h : head (first byte value)\n"
                  "WARNING: On big files, use 'zoom.byte=h' or restrict ranges\n"
                  );
            } else {
                  const char *mode = r_config_get (core->config, "zoom.byte");
                  ut64 from = r_config_get_i (core->config, "zoom.from");
                  ut64 to = r_config_get_i (core->config, "zoom.to");
                  if (mode) r_print_zoom (core->print, core, printzoomcallback,
                        from, to, *mode, core->blocksize);
                  else eprintf ("No zoom.byte defined\n");
            }
            break;
      default:
            r_cons_printf (
            "Usage: p[fmt] [len]\n"
            " p= [len]     print byte percentage bars\n"
            " p6[de] [len] base64 decode/encode\n"
            " p8 [len]     8bit hexpair list of bytes\n"
            " pb [len]     bitstream of N bytes\n"
            " pd [len]     disassemble N opcodes\n"
            " pD [len]     disassemble N bytes\n"
            " po [len]     octal dump of N bytes\n"
            " pc [len]     output C format\n"
            " pf [fmt]     print formatted data\n"
            " pm [magic]   print libmagic data\n"
            " ps [len]     print string\n"
            " psp          print pascal string\n"
            " pS [len]     print wide string\n"
            " pt [len]     print diferent timestamps\n"
            " pr [len]     print N raw bytes\n"
            " pu [len]     print N url encoded bytes\n"
            " pU [len]     print N wide url encoded bytes\n"
            " px [len]     hexdump of N bytes\n"
            " pZ [len]     print zoom view (see pZ? for help)\n");
            break;
      }
      if (tbs != core->blocksize)
            r_core_block_size (core, tbs);
      return 0;
}

static int cmd_hexdump(void *data, const char *input) {
      return cmd_print (data, input-1);
}

static int cmd_flag(void *data, const char *input) {
      RCore *core = (RCore *)data;
      int len = strlen (input)+1;
      char *str = alloca (len);
      ut64 off = core->offset;
      memcpy (str, input+1, len);

      switch (input[0]) {
      case '+':
            r_flag_set (core->flags, str, off, core->blocksize, 1);
            break;
      case ' ': {
            char *s = NULL, *s2 = NULL;
            ut32 bsze = core->blocksize;
            s = strchr (str, ' ');
            if (s) {
                  *s = '\0';
                  s2 = strchr (s+1, ' ');
                  if (s2) {
                        *s2 = '\0';
                        if (s2[1]&&s2[2])
                              off = r_num_math (core->num, s2+1);
                  }
                  bsze = r_num_math (core->num, s+1);
            }
            r_flag_set (core->flags, str, off, bsze, 0);
            if (s) *s=' ';
            if (s2) *s2=' ';
            }
            break;
      case '-':
            if (input[1]) r_flag_unset (core->flags, input+1);
            else r_flag_unset_i (core->flags, off);
            break;
      case 'S':
            r_flag_sort (core->flags, (input[1]=='n'));
            break;
      case 's':
            if (input[1]==' ') r_flag_space_set (core->flags, input+2);
            else r_flag_space_list (core->flags);
            break;
      case 'o':
            {
                  char *file = PREFIX"/share/doc/radare2/fortunes";
                  char *line = r_file_slurp_random_line (file);
                  if (line) {
                        r_cons_printf (" -- %s\n", line);
                        free (line);
                  }
            }
            break;
      case 'r':
            {
                  char *old, *new;
                  RFlagItem *item;
                  old = str+1;
                  new = strchr (old, ' ');
                  if (new) {
                        *new = 0;
                        new++;
                        item = r_flag_get (core->flags, old);
                  } else {
                        new = old;
                        item = r_flag_get_i (core->flags, core->offset);
                  }
                  if (item) r_flag_item_rename (item, new);
                  else eprintf ("Cannot find flag\n");
            }
            break;
      case '*':
            r_flag_list (core->flags, 1);
            break;
      case '\0':
            r_flag_list (core->flags, 0);
            break;
      case '?':
            r_cons_printf (
            "Usage: f[?] [flagname]\n"
            " f name 12 @ 33   ; set flag 'name' with size 12 at 33\n"
            " f name 12 33     ; same as above\n"
            " f+name 12 @ 33   ; like above but creates new one if doesnt exist\n"
            " f-name           ; remove flag 'name'\n"
            " f-@addr          ; remove flag at address expression\n"
            " f                ; list flags\n"
            " f*               ; list flags in r commands\n"
            " fr [old] [new]   ; rename flag\n"
            " fs functions     ; set flagspace\n"
            " fs *             ; set no flagspace\n"
            " fs               ; display flagspaces\n"
            " fS[on]           ; sort flags by offset or name\n");
            break;
      }
      return 0;
}

static void cmd_syscall_do(RCore *core, int num) {
      int i;
      char str[64];
      RSyscallItem *item = r_syscall_get (core->anal->syscall, num, -1);
      if (item == NULL) {
            r_cons_printf ("%d = unknown ()", num);
            return;
      }
      r_cons_printf ("%d = %s (", item->num, item->name);
      // TODO: move this to r_syscall
      for (i=0; i<item->args; i++) {
            ut64 arg = r_debug_arg_get (core->dbg, R_TRUE, i+1);
            if (item->sargs==NULL)
                  r_cons_printf ("0x%08"PFMT64x"", arg);
            else
            switch (item->sargs[i]) {
            case 'p': // pointer
                  r_cons_printf ("0x%08"PFMT64x"", arg);
                  break;
            case 'i':
                  r_cons_printf ("%"PFMT64d"", arg);
                  break;
            case 'z':
                  r_io_read_at (core->io, arg, (ut8*)str, sizeof (str));
                  // TODO: filter zero terminated string
                  str[63] = '\0';
                  r_str_filter (str, strlen (str));
                  r_cons_printf ("\"%s\"", str);
                  break;
            default:
                  r_cons_printf ("0x%08"PFMT64x"", arg);
                  break;
            }
            if (i+1<item->args)
                  r_cons_printf (", ");
      }
      r_cons_printf (")\n");
}


#if 1
/* TODO: Move into cmd_anal() */
static void var_help() {
      eprintf("Try afv?\n");
      eprintf(" afv 12 int buffer[3]\n");
      eprintf(" afv 12 byte buffer[1024]\n");
      eprintf("Try af[aAv][gs] [delta] [[addr]]\n");
      eprintf(" afag 0  = arg0 get\n");
      eprintf(" afvs 12 = var12 set\n");
      eprintf("a = arg, A = fastarg, v = var\n");
      eprintf("TODO: [[addr]] is not yet implemented. use @\n");
}

static int var_cmd(RCore *core, const char *str) {
      RAnalFcn *fcn = r_anal_fcn_find (core->anal, core->offset,
                  R_ANAL_FCN_TYPE_FCN|R_ANAL_FCN_TYPE_SYM);
      char *p,*p2,*p3;
      int type, delta, len = strlen(str)+1;

      p = alloca (len); // XXX: remove this alloca
      memcpy (p, str, len);
      str = p;

      switch (*str) {
      case 'V': // show vars in human readable format
            r_anal_var_list_show (core->anal, fcn, core->offset);
            return 0;
      case '?':
            var_help ();
            return 0;
      case 'v': // frame variable
      case 'a': // stack arg
      case 'A': // fastcall arg
            // XXX nested dup
            switch (*str) {
            case 'v': type = R_ANAL_VAR_TYPE_LOCAL|R_ANAL_VAR_DIR_NONE; break;
            case 'a': type = R_ANAL_VAR_TYPE_ARG|R_ANAL_VAR_DIR_IN; break;
            case 'A': type = R_ANAL_VAR_TYPE_ARGREG|R_ANAL_VAR_DIR_IN; break;
            default:
                  eprintf ("Unknown type\n");
                  return 0;
            }

            /* Variable access CFvs = set fun var */
            switch(str[1]) {
            case '\0': r_anal_var_list (core->anal, fcn, 0, 0); return 0;
            case '?': var_help(); return 0;
            case '.': r_anal_var_list (core->anal, fcn, core->offset, 0); return 0;
            case 's':
            case 'g':
                  if (str[2]!='\0') {
                        if (fcn != NULL) {
                              RAnalVar *var = r_anal_var_get (core->anal, fcn, atoi (str+2), R_ANAL_VAR_TYPE_LOCAL);
                              if (var != NULL)
                                    return r_anal_var_access_add (core->anal, var, atoi (str+2), (str[1]=='g')?0:1);
                              eprintf ("Can not find variable in: '%s'\n", str);
                        } else eprintf ("Unknown variable in: '%s'\n", str);
                        return R_FALSE;
                  } else eprintf ("Missing argument for a%c\n");
                  break;
            }
            str++;
            if (str[0]==' ') str++;
            delta = atoi (str);
            p = strchr (str, ' ');
            if (p==NULL) {
                  var_help();
                  return 0;
            }
            p[0]='\0'; p++;
            p2 = strchr (p, ' ');
            if (p2) {
                  p2[0]='\0'; p2 = p2+1;
                  p3 = strchr (p2,'[');
                  if (p3 != NULL) {
                        p3[0]='\0';
                        p3=p3+1;
                  }
                  r_anal_var_add (core->anal, fcn, core->offset, delta, type, p, p2, p3?atoi(p3):0);
            } else var_help ();
            break;
      default:
            var_help ();
            break;
      }
      return 0;
}
#endif

static int cmd_anal(void *data, const char *input) {
      const char *ptr;
      RCore *core = (RCore *)data;
      int l, len = core->blocksize;
      ut64 addr = core->offset;
      ut32 tbs = core->blocksize;

      if (input[0] && input[1]) {
            l = (int) r_num_get (core->num, input+2);
            if (l>0) len = l;
            if (l>tbs) {
                  r_core_block_size (core, l);
                  len = l;
            }
      }

      switch (input[0]) {
      case 'o':
            if (input[1] == '?') {
                  r_cons_printf (
                  "Usage: ao[e?] [len]\n"
                  " aoe      ; emulate opcode at current offset\n"
                  " aoe 4    ; emulate 4 opcodes starting at current offset\n"
                  " ao 5     ; display opcode analysis of 5 opcodes\n");
            } else
            if (input[1] == 'e') {
                  eprintf ("TODO: r_anal_op_execute\n");
            } else {
                  int ret, idx;
                  ut8 *buf = core->block;
                  RAnalOp op;

                  for (idx=ret=0; idx<len; idx+=ret) {
                        ret = r_anal_op (core->anal, &op,
                              core->offset+idx, buf + idx, (len-idx));
                        if (ret<1) {
                              eprintf ("Oops at 0x%08"PFMT64x"\n", core->offset+idx);
                              break;
                        }
                        r_cons_printf ("addr: 0x%08"PFMT64x"\n", core->offset+idx);
                        r_cons_printf ("size: %d\n", op.length);
                        r_cons_printf ("type: %d\n", op.type); // TODO: string
                        r_cons_printf ("eob: %d\n", op.eob);
                        r_cons_printf ("jump: 0x%08"PFMT64x"\n", op.jump);
                        r_cons_printf ("fail: 0x%08"PFMT64x"\n", op.fail);
                        r_cons_printf ("stack: %d\n", op.stackop); // TODO: string
                        r_cons_printf ("cond: %d\n", op.cond); // TODO: string
                        r_cons_printf ("family: %d\n", op.family);
                        r_cons_printf ("\n");
                        //r_cons_printf ("false: 0x%08"PFMT64x"\n", core->offset+idx);
                  }
            }
            break;
      case 'f':
            switch (input[1]) {
            case '-':
                  r_anal_fcn_del (core->anal, r_num_math (core->num, input+2));
                  break;
            case '+':
                  {
                  char *ptr = strdup(input+3), *ptr2;
                  int n = r_str_word_set0 (ptr);
                  const char *name = NULL;
                  ut64 addr = -1LL;
                  ut64 size = 0LL;
                  RAnalDiff *diff = NULL;
                  int type = R_ANAL_FCN_TYPE_FCN;
                  
                  if (n > 2) {
                        switch(n) {
                        case 5:
                              ptr2 = r_str_word_get0 (ptr, 4);
                              if (!(diff = r_anal_diff_new ())) {
                                    eprintf ("error: Cannot init RAnalDiff\n");
                                    free (ptr);
                                    return R_FALSE;
                              }
                              if (ptr2[0] == 'm')
                                    diff->type = R_ANAL_DIFF_TYPE_MATCH;
                              else if (ptr2[0] == 'u')
                                    diff->type = R_ANAL_DIFF_TYPE_UNMATCH;
                        case 4:
                              ptr2 = r_str_word_get0 (ptr, 3);
                              if (strchr (ptr2, 'l'))
                                    type = R_ANAL_FCN_TYPE_LOC;
                              else if (strchr (ptr2, 'i'))
                                    type = R_ANAL_FCN_TYPE_IMP;
                              else if (strchr (ptr2, 's'))
                                    type = R_ANAL_FCN_TYPE_SYM;
                              else type = R_ANAL_FCN_TYPE_FCN;
                        case 3:
                              name = r_str_word_get0 (ptr, 2);
                        case 2:
                              size = r_num_math (core->num, r_str_word_get0 (ptr, 1));
                        case 1:
                              addr = r_num_math (core->num, r_str_word_get0 (ptr, 0));
                        }
                        if (!r_anal_fcn_add (core->anal, addr, size, name, type, diff))
                              eprintf ("Cannot add function (duplicated)\n");
                  }
                  r_anal_diff_free (diff);
                  free (ptr);
                  }
                  break;
            case 'l':
                  r_core_anal_fcn_list (core, input+2, 0);
                  break;
            case '*':
                  r_core_anal_fcn_list (core, input+2, 1);
                  break;
            case 's': {
                  ut64 addr;
                  RAnalFcn *f;
                  const char *arg = input+3;
                  if (input[2] && (addr = r_num_math (core->num, arg))) {
                        arg = strchr (arg, ' ');
                        if (arg) arg++;
                  } else addr = core->offset;
                  if ((f = r_anal_fcn_find (core->anal, addr, R_ANAL_FCN_TYPE_NULL))) {
                        if (arg && *arg) {
                              r_anal_fcn_from_string (core->anal, f, arg);
                        } else {
                              char *str = r_anal_fcn_to_string (core->anal, f);
                              r_cons_printf ("%s\n", str);
                              free (str);
                        }
                  } else eprintf("No function defined at 0x%08"PFMT64x"\n", addr);
                  }
                  break;
            case 'a':
            case 'A':
            case 'v':
                  var_cmd (core, input+1);
                  break;
            case 'c':
                  {
                  RAnalFcn *fcn;
                  int cc;
                  if ((fcn = r_anal_get_fcn_at (core->anal, core->offset)) != NULL) {
                        cc = r_anal_fcn_cc (fcn);
                        r_cons_printf ("Cyclomatic Complexity at 0x%08"PFMT64x" = %i\n", core->offset, cc);
                  } else r_cons_printf ("Error: function not found\n");
                  }
                  break;
            case 'b':
                  {
                  char *ptr = strdup(input+3), *ptr2 = NULL;
                  ut64 fcnaddr = -1LL, addr = -1LL;
                  ut64 size = 0LL;
                  ut64 jump = -1LL;
                  ut64 fail = -1LL;
                  int type = R_ANAL_BB_TYPE_NULL;
                  RAnalFcn *fcn = NULL;
                  RAnalDiff *diff = NULL;

                  switch(r_str_word_set0 (ptr)) {
                  case 7:
                        ptr2 = r_str_word_get0 (ptr, 6);
                        if (!(diff = r_anal_diff_new ())) {
                              eprintf ("error: Cannot init RAnalDiff\n");
                              free (ptr);
                              return R_FALSE;
                        }
                        if (ptr2[0] == 'm')
                              diff->type = R_ANAL_DIFF_TYPE_MATCH;
                        else if (ptr2[0] == 'u')
                              diff->type = R_ANAL_DIFF_TYPE_UNMATCH;
                  case 6:
                        ptr2 = r_str_word_get0 (ptr, 5);
                        if (strchr (ptr2, 'h'))
                              type |= R_ANAL_BB_TYPE_HEAD;
                        if (strchr (ptr2, 'b'))
                              type |= R_ANAL_BB_TYPE_BODY;
                        if (strchr (ptr2, 'l'))
                              type |= R_ANAL_BB_TYPE_LAST;
                        if (strchr (ptr2, 'f'))
                              type |= R_ANAL_BB_TYPE_FOOT;
                  case 5: // get fail
                        fail = r_num_math (core->num, r_str_word_get0 (ptr, 4));
                  case 4: // get jump
                        jump = r_num_math (core->num, r_str_word_get0 (ptr, 3));
                  case 3: // get size
                        size = r_num_math (core->num, r_str_word_get0 (ptr, 2));
                  case 2: // get addr
                        addr = r_num_math (core->num, r_str_word_get0 (ptr, 1));
                  case 1: // get fcnaddr
                        fcnaddr = r_num_math (core->num, r_str_word_get0 (ptr, 0));
                  }
                  if ((fcn = r_anal_get_fcn_at (core->anal, fcnaddr)) == NULL ||
                        !r_anal_fcn_add_bb (fcn, addr, size, jump, fail, type, diff))
                        eprintf ("Error: Cannot add bb\n");
                  r_anal_diff_free (diff);
                  free (ptr);
                  }
                  break;
            case '?':
                  r_cons_printf (
                  "Usage: af[?+-l*]\n"
                  " af @ [addr]               ; Analyze functions (start at addr)\n"
                  " af+ addr size name [type] [diff] ; Add function\n"
                  " afb fcnaddr addr size name [type] [diff] ; Add bb to function @ fcnaddr\n"
                  " af- [addr]                ; Clean all function analysis data (or function at addr)\n"
                  " afl [fcn name]            ; List functions\n"
                  " afs [addr] [fcnsign]      ; Get/set function signature at current address\n"
                  " af[aAv][?] [arg]          ; Manipulate args, fastargs and variables in function\n"
                  " afc @ [addr]              ; Calculate the Cyclomatic Complexity (starting at addr)\n"
                  " af*                       ; Output radare commands\n");
                  break;
            default:
                  r_core_anal_fcn (core, core->offset, -1, R_ANAL_REF_TYPE_NULL,
                              r_config_get_i (core->config, "anal.depth"));
            }
            break;
      case 'g':
            switch (input[1]) {
            case 'c':
                  r_core_anal_refs (core, r_num_math (core->num, input+2), 1);
                  break;
            case 'l':
                  r_core_anal_graph (core, r_num_math (core->num, input+2), R_CORE_ANAL_GRAPHLINES);
                  break;
            case 'a':
                  r_core_anal_graph (core, r_num_math (core->num, input+2), 0);
                  break;
            case 'd':
                  r_core_anal_graph (core, r_num_math (core->num, input+2),
                              R_CORE_ANAL_GRAPHBODY|R_CORE_ANAL_GRAPHDIFF);
                  break;
            case '?':
                  r_cons_printf (
                  "Usage: ag[?f]\n"
                  " ag [addr]       ; Output graphviz code (bb at addr and childs)\n"
                  " aga [addr]      ; Idem, but only addresses\n"
                  " agc [addr]      ; Output graphviz call graph of function\n"
                  " agl [fcn name]  ; Output graphviz code using meta-data\n"
                  " agd [fcn name]  ; Output graphviz code of diffed function\n"
                  " agfl [fcn name] ; Output graphviz code of function using meta-data\n");
                  break;
            default:
                  r_core_anal_graph (core, r_num_math (core->num, input+1),
                        R_CORE_ANAL_GRAPHBODY);
            }
            break;
      case 't':
            switch (input[1]) {
            case '?':
                  r_cons_strcat ("Usage: at[*] [addr]\n"
                  " at?                ; show help message\n"
                  " at                 ; list all traced opcode ranges\n"
                  " at-                ; reset the tracing information\n"
                  " at*                ; list all traced opcode offsets\n"
                  " at+ [addr] [times] ; add trace for address N times\n"
                  " at [addr]          ; show trace info at address\n"
                  " att [tag]          ; select trace tag (no arg unsets)\n"
                  " at%                ; TODO\n"
                  " ata 0x804020 ...   ; only trace given addresses\n"
                  " atr                ; show traces as range commands (ar+)\n"
                  " atd                ; show disassembly trace\n"
                  " atD                ; show dwarf trace (at*|rsc dwarf-traces $FILE)\n");
                  eprintf ("Current Tag: %d\n", core->dbg->trace->tag);
                  break;
            case 'a':
                  eprintf ("NOTE: Ensure given addresses are in 0x%%08llx format\n");
                  r_debug_trace_at (core->dbg, input+2);
                  break;
            case 't':
                  r_debug_trace_tag (core->dbg, atoi (input+2));
                  break;
            case 'd':
                  //trace_show (2, trace_tag_get());
                  eprintf ("TODO\n");
                  break;
            case 'D':
                  // XXX: not yet tested..and rsc dwarf-traces comes from r1
                  r_core_cmd (core, "at*|rsc dwarf-traces $FILE", 0);
                  break;
            case '+':
                  ptr = input+3;
                  addr = r_num_math (core->num, ptr);
                  ptr = strchr (ptr, ' ');
                  if (ptr != NULL) {
                        RAnalOp *op = r_core_op_anal (core, addr);
                        if (op != NULL) {
                              //eprintf("at(0x%08llx)=%d (%s)\n", addr, atoi(ptr+1), ptr+1);
                              //trace_set_times(addr, atoi(ptr+1));
                              RDebugTracepoint *tp = r_debug_trace_add (core->dbg, addr, op->length);
                              tp->count = atoi (ptr+1);
                              r_anal_trace_bb (core->anal, addr);
                              r_anal_op_free (op);
                        } else eprintf ("Cannot analyze opcode at 0x%"PFMT64x"\n", addr);
                  }
                  break;
            case '-':
                  r_debug_trace_free (core->dbg);
                  core->dbg->trace = r_debug_trace_new (core->dbg);
                  break;
            case ' ': {
                  RDebugTracepoint *t = r_debug_trace_get (core->dbg,
                        r_num_math (core->num, input+1));
                  if (t != NULL) {
                        r_cons_printf ("offset = 0x%"PFMT64x"\n", t->addr);
                        r_cons_printf ("opsize = %d\n", t->size);
                        r_cons_printf ("times = %d\n", t->times);
                        r_cons_printf ("count = %d\n", t->count);
                        //TODO cons_printf("time = %d\n", t->tm);
                  } }
                  break;
            case '*':
                  r_debug_trace_list (core->dbg, 1);
                  break;
            case 'r':
                  eprintf ("TODO\n");
                  //trace_show(-1, trace_tag_get());
                  break;
            default:
                  r_debug_trace_list (core->dbg, 0);
            }
            break;
      case 's':
            switch (input[1]) {
            case 'l':
                  r_syscall_list (core->anal->syscall);
                  break;
            case '\0': {
                  int a0 = (int)r_debug_reg_get (core->dbg, "oeax"); //XXX
                  cmd_syscall_do (core, a0);
                  } break;
            case ' ':
                  cmd_syscall_do (core, (int)r_num_get (core->num, input+2));
                  break;
            default:
            case '?':
                  r_cons_printf (
                  "Usage: as[?]\n"
                  " as       Display syscall and arguments\n"
                  " as 4     Show syscall 4 based on asm.os\n"
                  " asl      List of syscalls by asm.os and asm.arch\n");
                  break;
            }
            break;
      case 'r':
            switch(input[1]) {
            case '?':
                  r_cons_printf (
                  "Usage: ar[?d-l*]\n"
                  " ar addr [at]   ; Add code ref\n"
                  " ard addr [at]  ; Add dara ref\n"
                  " ar- [at]       ; Clean all refs (or refs from addr)\n"
                  " arl            ; List refs\n"
                  " ar*            ; Output radare commands\n");
                  break;
            case '-':
                  r_anal_ref_del (core->anal, r_num_math (core->num, input+2));
                  break;
            case 'l':
                  r_core_anal_ref_list (core, R_FALSE);
                  break;
            case '*':
                  r_core_anal_ref_list (core, R_TRUE);
                  break;
            default:
                  {
                  char *ptr = strdup (r_str_trim_head ((char*)input+2));
                  int n = r_str_word_set0 (ptr);
                  ut64 at = core->offset;
                  ut64 addr = -1LL;
                  switch (n) {
                  case 2: // get at
                        at = r_num_math (core->num, r_str_word_get0 (ptr, 1));
                  case 1: // get addr
                        addr = r_num_math (core->num, r_str_word_get0 (ptr, 0));
                        break;
                  default:
                        return R_FALSE;
                  }
                  r_anal_ref_add (core->anal, addr, at,
                              input[1]=='d'?R_ANAL_REF_TYPE_DATA:R_ANAL_REF_TYPE_CODE);
                  free (ptr);
                  }
            }
            break;
      case 'a':
            r_core_anal_all (core);
            break;
      case 'p':
            {
                  const char *arch = r_config_get (core->config, "asm.arch");
                  int bits = r_config_get_i (core->config, "asm.bits");
                  // TODO: this is x86 only
                  // TODO: allow interruptible search
                  char *o = strdup (r_config_get (core->config, "search.prefix"));
                  r_config_set (core->config, "search.prefix", "pre.");
                  r_core_cmd0 (core, "fs preludes");
                  if (!strstr (arch, "x86")) {
                        switch (bits) {
                        case 32:
                              r_core_cmd0 (core, "./x 5589e5 && af @@ pre.");
                              break;
                        case 64:
                              r_core_cmd0 (core, "./x 554989e5 && af @@ pre.");
                              break;
                        }
                  } else {
                        eprintf ("ap: Unsupported asm.arch and asm.bits\n");
                  }
                  r_config_set (core->config, "search.prefix", o);
                  free (o);
            }
            break;
      default:
            r_cons_printf (
            "Usage: a[?obfrgtv]\n"
            " aa              ; Analyze all (fcns + bbs)\n"
            " ap              ; Find and analyze function preludes\n"
            " as [num]        ; Analyze syscall using dbg.reg\n"
            " ao[e?] [len]    ; Analyze Opcodes (or emulate it)\n"
            " ab[?+-l*]       ; Analyze Basic blocks\n"
            " af[?+-l*]       ; Analyze Functions\n"
            " ar[?d-l*]       ; Manage refs/xrefs\n"
            " ag[?f]          ; Output Graphviz code\n"
            " at[trd+-*?] [.] ; Analyze execution Traces\n");
            break;
      }
      if (tbs != core->blocksize)
            r_core_block_size (core, tbs);
      return 0;
}

/* TODO: simplify using r_write */
static int cmd_write(void *data, const char *input) {
      ut8 *buf;
      const char *arg;
      int i, size, len = strlen (input);
      char *tmp, *str = alloca (len)+1;
      RCore *core = (RCore *)data;
      memcpy (str, input+1, len);
      switch (*input) {
      case 'A':
            switch (input[1]) {
            case ' ':
                  if (input[2] && input[3]==' ') {
                        r_asm_set_pc (core->assembler, core->offset);
                        eprintf ("modify (%c)=%s\n", input[2], input+4);
                        len = r_asm_modify (core->assembler, core->block, input[2],
                              r_num_math (core->num, input+4));
                        eprintf ("len=%d\n", len);
                        if (len>0)
                              r_core_write_at (core, core->offset, core->block, len);
                        else eprintf ("r_asm_modify = %d\n", len);
                  } else eprintf ("Usage: wA [type] [value]\n");
                  break;
            case '?':
            default:
                  r_cons_printf ("Usage: wA [type] [value]\n"
                  "Types:\n"
                  " r   raw write value\n"
                  " v   set value (taking care of current address)\n"
                  " d   destination register\n"
                  " 0   1st src register\n"
                  " 1   2nd src register\n"
                  "Example: wA r 0 # e800000000\n");
                  break;
            }
            break;
      case 'c':
            switch (input[1]) {
            case 'i':
                  r_io_cache_commit (core->io);
                  break;
            case 'r':
                  r_io_cache_reset (core->io, R_TRUE);
                  break;
            case '?':
                  r_cons_printf (
                  "Usage: wc[ir*?]\n"
                  " wc       list all write changes\n"
                  " wc*      \"\" in radare commands\n"
                  " wcr      reset all write changes in cache\n"
                  " wci      commit write cache\n"
                  "NOTE: Needs io.cache=true\n");
                  break;
            case '*':
                  r_io_cache_list (core->io, R_TRUE);
                  break;
            case '\0':
                  r_io_cache_list (core->io, R_FALSE);
                  break;
            }
            break;
      case ' ':
            /* write string */
            len = r_str_escape (str);
            r_io_set_fd (core->io, core->file->fd);
            r_io_write_at (core->io, core->offset, (const ut8*)str, len);
            r_core_block_read (core, 0);
            break;
      case 't':
            /* TODO: support userdefined size? */
            arg = (const char *)(input+((input[1]==' ')?2:1));
            r_file_dump (arg, core->block, core->blocksize);
            break;
      case 'T':
            eprintf ("TODO\n");
            break;
      case 'f':
            arg = (const char *)(input+((input[1]==' ')?2:1));
            if ((buf = (ut8*) r_file_slurp (arg, &size))) {
                  r_io_set_fd (core->io, core->file->fd);
                  r_io_write_at (core->io, core->offset, buf, size);
                  free(buf);
                  r_core_block_read (core, 0);
            } else eprintf ("Cannot open file '%s'\n", arg);
            break;
      case 'F':
            arg = (const char *)(input+((input[1]==' ')?2:1));
            if ((buf = r_file_slurp_hexpairs (arg, &size))) {
                  r_io_set_fd (core->io, core->file->fd);
                  r_io_write_at (core->io, core->offset, buf, size);
                  free (buf);
                  r_core_block_read (core, 0);
            } else eprintf ("Cannot open file '%s'\n", arg);
            break;
      case 'w':
            str = str+1;
            len = (len-1)<<1;
            tmp = alloca (len);
            for (i=0;i<len;i++) {
                  if (i%2) tmp[i] = 0;
                  else tmp[i] = str[i>>1];
            }
            str = tmp;
            r_io_set_fd (core->io, core->file->fd);
            r_io_write_at (core->io, core->offset, (const ut8*)str, len);
            r_core_block_read (core, 0);
            break;
      case 'x':
            {
            int len = strlen (input);
            ut8 *buf = alloca (len);
            len = r_hex_str2bin (input+1, buf);
            if (len != -1) {
                  r_core_write_at (core, core->offset, buf, len);
                  r_core_block_read (core, 0);
            } else eprintf ("Error: invalid hexpair string\n");
            }
            break;
      case 'a':
            {
            RAsmCode *acode;
            /* XXX ULTRAUGLY , needs fallback support in rasm */
            r_asm_use (core->assembler, "x86.olly");
            r_asm_set_pc (core->assembler, core->offset);
            if (input[1]==' ') input=input+1;
            acode = r_asm_massemble (core->assembler, input+1);
            if (acode) {
                  eprintf ("Written %d bytes (%s)=wx %s\n", acode->len, input+1, acode->buf_hex);
                  r_core_write_at (core, core->offset, acode->buf, acode->len);
                  r_asm_code_free (acode);
                  r_core_block_read (core, 0);
                  r_asm_use (core->assembler, "x86"); /* XXX */
                  r_core_block_read (core, 0);
            }
            }
            break;
      case 'b':
            {
            int len = strlen (input);
            ut8 *buf = alloca (len);
            len = r_hex_str2bin (input+1, buf);
            r_mem_copyloop (core->block, buf, core->blocksize, len);
            r_core_write_at (core, core->offset, core->block, core->blocksize);
            r_core_block_read (core, 0);
            }
            break;
      case 'm':
            size = r_hex_str2bin (input+1, (ut8*)str);
            switch (input[1]) {
            case '\0':
                  eprintf ("Current write mask: TODO\n");
                  // TODO
                  break;
            case '?':
                  break;
            case '-':
                  r_io_set_write_mask(core->io, 0, 0);
                  eprintf ("Write mask disabled\n");
                  break;
            case ' ':
                  if (size>0) {
                        r_io_set_fd (core->io, core->file->fd);
                        r_io_set_write_mask (core->io, (const ut8*)str, size);
                        eprintf ("Write mask set to '");
                        for (i=0;i<size;i++)
                              eprintf ("%02x", str[i]);
                        eprintf ("'\n");
                  } else eprintf ("Invalid string\n");
                  break;
            }
            break;
      case 'v':
            {
            ut64 off = r_num_math (core->num, input+1);
            r_io_set_fd (core->io, core->file->fd);
            r_io_seek (core->io, core->offset, R_IO_SEEK_SET);
            if (off&UT64_32U) {
                  /* 8 byte addr */
                  ut64 addr8;
                  memcpy((ut8*)&addr8, (ut8*)&off, 8); // XXX needs endian here
            //    endian_memcpy((ut8*)&addr8, (ut8*)&off, 8);
                  r_io_write(core->io, (const ut8 *)&addr8, 8);
            } else {
                  /* 4 byte addr */
                  ut32 addr4, addr4_ = (ut32)off;
                  //drop_endian((ut8*)&addr4_, (ut8*)&addr4, 4); /* addr4_ = addr4 */
                  //endian_memcpy((ut8*)&addr4, (ut8*)&addr4_, 4); /* addr4 = addr4_ */
                  memcpy ((ut8*)&addr4, (ut8*)&addr4_, 4); // XXX needs endian here too
                  r_io_write (core->io, (const ut8 *)&addr4, 4);
            }
            r_core_block_read (core, 0);
            }
            break;
      case 'o':
                switch (input[1]) {
                case 'a':
                case 's':
                case 'A':
                case 'x':
                case 'r':
                case 'l':
                case 'm':
                case 'd':
                case 'o':
                        if (input[2]!=' ') {
                                eprintf ("Usage: 'wo%c 00 11 22'\n", input[1]);
                                return 0;
                        }
                case '2':
                case '4':
                        r_core_write_op (core, input+3, input[1]);
                  r_core_block_read (core, 0);
                        break;
                case '\0':
                case '?':
                default:
                        r_cons_printf (
                        "Usage: wo[xrlasmd] [hexpairs]\n"
                        "Example: wox 90    ; xor cur block with 90\n"
                        "Example: woa 02 03 ; add 2, 3 to all bytes of cur block\n"
                        "Supported operations:\n"
                        "  woa  addition            +=\n"
                        "  wos  substraction        -=\n"
                        "  wom  multiply            *=\n"
                        "  wod  divide              /=\n"
                        "  wox  xor                 ^=\n"
                        "  woo  or                  |=\n"
                        "  woA  and                 &=\n"
                        "  wor  shift right         >>=\n"
                        "  wol  shift left          <<=\n"
                        "  wo2  2 byte endian swap  2=\n"
                        "  wo4  4 byte endian swap  4=\n"
                        );
                        break;
                }
                break;
      default:
      case '?':
            if (core->oobi) {
                  eprintf ("Writing oobi buffer!\n");
                  r_io_set_fd (core->io, core->file->fd);
                  r_io_write (core->io, core->oobi, core->oobi_len);
                  r_core_block_read (core, 0);
            } else r_cons_printf (
                  "Usage: w[x] [str] [<file] [<<EOF] [@addr]\n"
                  " w foobar     write string 'foobar'\n"
                  " ww foobar    write wide string 'f\\x00o\\x00o\\x00b\\x00a\\x00r\\x00'\n"
                  " wa push ebp  write opcode, separated by ';' (use '\"' around the command)\n"
                  " wA r 0       alter/modify opcode at current seek (see wA?)\n"
                  " wb 010203    fill current block with cyclic hexpairs\n"
                  " wc[ir*?]     write cache commit/reset/list\n"
                  " wx 9090      write two intel nops\n"
                  " wv eip+34    write 32-64 bit value\n"
                  " wo[] hex     write in block with operation. 'wo?' fmi\n"
                  " wm f0ff      set binary mask hexpair to be used as cyclic write mask\n"
                  " wf file      write contents of file at current offset\n"
                  " wF file      write contents of hexpairs file here\n"
                  " wt file      write current block to file\n");
                  //TODO: add support for offset+seek
                  // " wf file o s ; write contents of file from optional offset 'o' and size 's'.\n"
            break;
      }
      return 0;
}

static int cmd_resize(void *data, const char *input) {
      RCore *core = (RCore *)data;
      st64 delta=0;
      int grow;
      ut64 oldsize,newsize;

      oldsize = core->file->size;

      switch (input[0]) {
      case ' ':
            newsize = r_num_math (core->num, input+1);
            break;
      case '+':
      case '-':
            delta = (st64)r_num_math (NULL, input);
            newsize = oldsize + delta;
            break;
      case '?':
      default:
            r_cons_printf (
                  "Usage: r[ size|+insert|-remove]\n"
                  " r size   set filesize to size, extending or truncating\n"
                  " r-num    remove num bytes, move following data down\n"
                  " r+num    insert num bytes, move following data up\n");
            return R_TRUE;
      }

      grow = (newsize > oldsize);

      if (grow) {
            r_io_resize (core->io, newsize);
            core->file->size = newsize;
      }

      if (delta && core->offset < newsize)
            r_io_shift (core->io, core->offset, grow?newsize:oldsize, delta);

      if (!grow) {
            r_io_resize (core->io, newsize);
            core->file->size = newsize;
      }

      if (newsize < core->offset+core->blocksize ||
                  oldsize < core->offset+core->blocksize)
            r_core_block_read (core, 0);

      return R_TRUE;
}

static const char *cmdhit = NULL;
static const char *searchprefix = NULL;

static int __cb_hit(RSearchKeyword *kw, void *user, ut64 addr) {
      RCore *core = (RCore *)user;
      r_cons_printf ("f %s%d_%d %d 0x%08"PFMT64x"\n", searchprefix,
            kw->kwidx, kw->count, kw->keyword_length, addr);
      if (!strnull (cmdhit)) {
            ut64 here = core->offset;
            r_core_seek (core, addr, R_FALSE);
            r_core_cmd (core, cmdhit, 0);
            r_core_seek (core, here, R_TRUE);
      }
      return R_TRUE;
}

static int cmd_search(void *data, const char *input) {
      RCore *core = (RCore *)data;
      ut64 at, from, to;
      //RIOSection *section;
      int ret, dosearch = R_FALSE;
      int aes_search = R_FALSE;
      ut32 n32;
      ut8 *buf;

      // TODO: repeat last search doesnt works for /a
      from = r_config_get_i (core->config, "search.from");
      to = r_config_get_i (core->config, "search.to");
      core->search->align = r_config_get_i (core->config, "search.align");
      //TODO: handle section ranges if from&&to==0
/*
      section = r_io_section_get (core->io, core->offset);
      if (section) {
            from += section->vaddr;
            //fin = ini + s->size;
      }
*/
      searchprefix = r_config_get (core->config, "search.prefix");
      /* XXX: Think how to get the section ranges here */
      if (from == 0LL)
            from = core->offset;
      if (to == 0LL)
            to = 0xFFFFFFFF; //core->file->size+0x8048000;

      switch (*input) {
      case 'a':
            if (input[1]==' ')
                  r_core_anal_search (core, from, to, r_num_math (core->num, input+2));
            else r_core_anal_search (core, from, to, core->offset);
            break;
      case 'A':
            dosearch = aes_search = R_TRUE;
            break;
      case '/':
            r_search_begin (core->search);
            dosearch = R_TRUE;
            break;
      case 'm':
#if HAVE_LIB_MAGIC
            /* XXX: This is pretty sloow */
            dosearch = R_FALSE;
            if (input[1]==' ') {
                  const char *file = input+2;
                  ut64 addr = from;
                  for (; addr<to; addr++) {
                        r_core_seek (core, addr, R_TRUE);
                        r_core_magic (core, file, R_FALSE);
                  }
            } else eprintf ("Usage: /m [file]\n");
#else
            eprintf ("r_core_magic: Compiled without magic :(\n");
#endif
            break;
      case 'p':
            {
                  int ps = atoi (input+1);
                  if (ps>1) {
                        r_search_pattern_size (core->search, ps);
                        r_search_pattern (core->search, from, to);
                  } else eprintf ("Invalid pattern size (must be >0)\n");
            }
            break;
      case 'v':
            r_search_reset (core->search, R_SEARCH_KEYWORD);
            r_search_set_distance (core->search, (int)
                  r_config_get_i (core->config, "search.distance"));
            n32 = (ut32)r_num_math (core->num, input+1);
// TODO: Add support for /v4 /v8 /v2
            r_search_kw_add (core->search, 
                  r_search_keyword_new ((const ut8*)&n32, 4, NULL, 0, NULL));
            r_search_begin (core->search);
            dosearch = 1;
            break;
      case 'w': /* search wide string */
            if (input[1]==' ') {
                  int len = strlen (input+2);
                  const char *p2;
                  char *p, *str = malloc ((len+1)*2);
                  for (p2=input+2,p=str; *p2; p+=2, p2++) {
                        p[0] = *p2;
                        p[1] = 0;
                  }
                  r_search_reset (core->search, R_SEARCH_KEYWORD);
                  r_search_set_distance (core->search, (int)
                        r_config_get_i (core->config, "search.distance"));
                  r_search_kw_add (core->search, 
                        r_search_keyword_new ((const ut8*)str, len*2, NULL, 0, NULL));
                  r_search_begin (core->search);
                  dosearch = 1;
            }
            break;
      case ' ': /* search string */
            r_search_reset (core->search, R_SEARCH_KEYWORD);
            r_search_set_distance (core->search, (int)
                  r_config_get_i (core->config, "search.distance"));
            r_search_kw_add (core->search, 
                  r_search_keyword_new_str (input+1, "", NULL));
            r_search_begin (core->search);
            dosearch = 1;
            break;
      case 'e': /* match regexp */
            {
            char *inp = strdup (input+2);
            char *res = r_str_lchr (inp+1, inp[0]);
            char *opt = NULL;
            if (res > inp) {
                  opt = strdup(res+1);
                  res[1]='\0';
            }
            r_search_reset (core->search, R_SEARCH_REGEXP);
            r_search_set_distance (core->search, (int)
                  r_config_get_i (core->config, "search.distance"));
            r_search_kw_add (core->search, 
                  r_search_keyword_new_str (inp, opt, NULL));
            r_search_begin (core->search);
            dosearch = 1;
            free(inp);
            free(opt);
            }
            break;
      case 'x': /* search hex */
            r_search_reset (core->search, R_SEARCH_KEYWORD);
            r_search_set_distance (core->search, (int)
                  r_config_get_i (core->config, "search.distance"));
            r_search_kw_add (core->search, 
                  r_search_keyword_new_hexmask (input+2, NULL));
            r_search_begin (core->search);
            dosearch = 1;
            break;
      case 'c': /* search asm */
            {
            /* TODO: Move to a separate function */
            int asmstr = r_config_get_i (core->config, "search.asmstr");
            if (asmstr) {
                  RCoreAsmHit *hit;
                  RListIter *iter;
                  int count = 0;
                  RList *hits;
                  if ((hits = r_core_asm_strsearch (core, input+2, from, to))) {
                        r_list_foreach (hits, iter, hit) {
                              r_cons_printf ("f %s_%i @ 0x%08"PFMT64x"   # %s (%i)\n",
                                    searchprefix, count, hit->addr, hit->code, hit->len);
                              count++;
                        }
                        r_list_destroy (hits);
                  }
                  dosearch = 0;
            } else {
                  char *kwd;
                  if (!(kwd = r_core_asm_search (core, input+2, from, to)))
                        return R_FALSE;
                  r_search_reset (core->search, R_SEARCH_KEYWORD);
                  r_search_set_distance (core->search, (int)
                              r_config_get_i (core->config, "search.distance"));
                  r_search_kw_add (core->search, 
                              r_search_keyword_new_hexmask (kwd, NULL));
                  r_search_begin (core->search);
                  free (kwd);
                  dosearch = 1;
            }
            }
            break;
      default:
            r_cons_printf (
            "Usage: /[amx/] [arg]\n"
            " / foo           ; search for string 'foo'\n"
            " /w foo          ; search for wide string 'f\\0o\\0o\\0'\n"
            " /e /E.F/i       ; match regular expression\n"
            " /x ff0033       ; search for hex string\n"
            " /c jmp [esp]    ; search for asm code (see search.asmstr)\n"
            " /A              ; search for AES expanded keys\n"
            " /a sym.printf   ; analyze code referencing an offset\n"
            " /m magicfile    ; search for matching magic file (use blocksize)\n"
            " /p patternsize  ; search for pattern of given size\n"
            " /v num          ; look for a asm.bigendian 32bit value\n"
            " //              ; repeat last search\n"
            " ./ hello        ; search 'hello string' and import flags\n"
            "Configuration:\n"
            " e search.distance = 0 ; search string distance\n"
            " e search.align = 4    ; only catch aligned search hits\n"
            " e search.from = 0     ; start address\n"
            " e search.to = 0       ; end address\n"
            " e search.asmstr = 0   ; search string instead of assembly\n");
            break;
      }
      if (dosearch) {
            if (core->search->n_kws>0 || aes_search) {
                  RSearchKeyword aeskw;
                  if (aes_search) {
                        memset (&aeskw, 0, sizeof (aeskw));
                        aeskw.keyword_length = 31;
                  }
                  /* set callback */
                  /* TODO: handle last block of data */
                  /* TODO: handle ^C */
                  /* TODO: launch search in background support */
                  buf = (ut8 *)malloc (core->blocksize);
                  r_search_set_callback (core->search, &__cb_hit, core);
                  cmdhit = r_config_get (core->config, "cmd.hit");
                  r_cons_break (NULL, NULL);
                  // XXX required? imho nor_io_set_fd (core->io, core->file->fd);
                  for (at = from; at < to; at += core->blocksize) {
                        if (r_cons_singleton ()->breaked)
                              break;
                        ret = r_io_read_at (core->io, at, buf, core->blocksize);
                        if (ret != core->blocksize)
                              break;
                        if (aes_search) {
                              int delta = r_search_aes_update (core->search, at, buf, ret);
                              if (delta != -1) {
                                    r_search_hit_new (core->search, &aeskw, at+delta);
                                    aeskw.count++;
                              }
                        } else
                        if (r_search_update (core->search, &at, buf, ret) == -1) {
                              eprintf ("search: update read error\n");
                              break;
                        }
                  }
                  r_cons_break_end ();
                  free (buf);
            } else eprintf ("No keywords defined\n");
      }
      return R_TRUE;
}

static int cmd_eval(void *data, const char *input) {
      RCore *core = (RCore *)data;
      switch (input[0]) {
      case '\0':
            r_config_list (core->config, NULL, 0);
            break;
      case '!':
            input = r_str_chop_ro(input+1);
            if (!r_config_swap (core->config, input))
                  eprintf ("r_config: '%s' is not a boolean variable.\n", input);
            break;
      case '-':
            r_core_config_init (core);
            eprintf ("BUG: 'e-' command locks the eval hashtable. patches are welcome :)\n");
            break;
      case '*':
            r_config_list (core->config, NULL, 1);
            break;
      case '?':
            r_cons_printf (
            "Usage: e[?] [var[=value]]\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"
            "  e a   ; get value of var 'a'\n"
            "  e a=b ; set var 'a' the 'b' value\n");
            //r_cmd_help(core->cmd, "e");
            break;
      case ' ':
            r_config_eval (core->config, input+1);
            break;
      default:
            r_config_eval (core->config, input);
      }
      return 0;
}

static int cmd_hash(void *data, const char *input) {
      char *p, algo[32];
      RCore *core = (RCore *)data;
      ut32 i, len = core->blocksize;
      const char *ptr;

      if (input[0]=='!') {
#if 0
      TODO: Honor OOBI
            #!lua < file
            #!lua <<EOF
            #!lua
            #!lua foo bar
                        //r_lang_run (core->lang, p+1, strlen (p+1));
                                //core->oobi, core->oobi_len);
#endif
            if (input[1]=='?' || input[1]=='*' || input[1]=='\0') {
                  r_lang_list (core->lang);
                  return R_TRUE;
            }
            p = strchr (input+1, ' ');
            if (p) *p=0;
            // TODO: set argv here
            if (r_lang_use (core->lang, input+1)) {
                  r_lang_setup (core->lang);
                  if (p) r_lang_run_file (core->lang, p+1);
                  else r_lang_prompt (core->lang);
            } else eprintf ("Invalid hashbang plugin name. Try '#!'\n");
            return R_TRUE;
      }

      ptr = strchr (input, ' ');
      sscanf (input, "%31s", algo);
      if (ptr != NULL)
            len = r_num_math (core->num, ptr+1);
      /* TODO: Simplify this spaguetti monster */
      if (!r_str_ccmp (input, "md4", ' ')) {
            RHash *ctx = r_hash_new (R_TRUE, R_HASH_MD4);
            const ut8 *c = r_hash_do_md4 (ctx, core->block, len);
            for (i=0; i<R_HASH_SIZE_MD4; i++) r_cons_printf ("%02x", c[i]);
            r_cons_newline ();
            r_hash_free (ctx);
      } else
      if (!r_str_ccmp (input, "md5", ' ')) {
            RHash *ctx = r_hash_new (R_TRUE, R_HASH_MD5);
            const ut8 *c = r_hash_do_md5 (ctx, core->block, len);
            for (i=0; i<R_HASH_SIZE_MD5; i++) r_cons_printf ("%02x", c[i]);
            r_cons_newline ();
            r_hash_free (ctx);
      } else
      if (!r_str_ccmp (input, "sha1", ' ')) {
            RHash *ctx = r_hash_new (R_TRUE, R_HASH_SHA1);
            const ut8 *c = r_hash_do_sha1 (ctx, core->block, len);
            for (i=0; i<R_HASH_SIZE_SHA1;i++) r_cons_printf ("%02x", c[i]);
            r_cons_newline ();
            r_hash_free (ctx);
      } else
      if (!r_str_ccmp (input, "sha256", ' ')) {
            RHash *ctx = r_hash_new (R_TRUE, R_HASH_SHA256);
            const ut8 *c = r_hash_do_sha256 (ctx, core->block, len);
            for (i=0; i<R_HASH_SIZE_SHA256;i++) r_cons_printf ("%02x", c[i]);
            r_cons_newline ();
            r_hash_free (ctx);
      } else
      if (!r_str_ccmp (input, "sha512", ' ')) {
            RHash *ctx = r_hash_new (R_TRUE, R_HASH_SHA512);
            const ut8 *c = r_hash_do_sha512 (ctx, core->block, len);
            for (i=0; i<R_HASH_SIZE_SHA512;i++) r_cons_printf ("%02x", c[i]);
            r_cons_newline ();
            r_hash_free (ctx);
      } else
      if (!r_str_ccmp (input, "entropy", ' ')) {
            r_cons_printf ("%lf\n", r_hash_entropy (core->block, len));
      } else
      if (!r_str_ccmp (input, "hamdist", ' ')) {
            r_cons_printf ("%d\n", r_hash_hamdist (core->block, len));
      } else
      if (!r_str_ccmp (input, "pcprint", ' ')) {
            r_cons_printf ("%d\n", r_hash_pcprint (core->block, len));
      } else
      if (!r_str_ccmp (input, "crc32", ' ')) {
            r_cons_printf ("%04x\n", r_hash_crc32 (core->block, len));
      } else
      if (!r_str_ccmp (input, "xor", ' ')) {
            r_cons_printf ("%02x\n", r_hash_xor (core->block, len));
      } else
      if (!r_str_ccmp (input, "crc16", ' ')) {
            r_cons_printf ("%02x\n", r_hash_crc16 (0, core->block, len));
      } else
      if (input[0]=='?') {
            r_cons_printf (
            "Usage: #algo <size> @ addr\n"
            " #xor                 ; calculate xor of all bytes in current block\n"
            " #crc32               ; calculate crc32 of current block\n"
            " #crc32 < /etc/fstab  ; calculate crc32 of this file\n"
            " #pcprint             ; count printable chars in current block\n"
            " #hamdist             ; calculate hamming distance in current block\n"
            " #entropy             ; calculate entropy of current block\n"
            " #md4                 ; calculate md4\n"
            " #md5 128K @ edi      ; calculate md5 of 128K from 'edi'\n"
            " #sha1                ; calculate SHA-1\n"
            " #sha256              ; calculate SHA-256\n"
            " #sha512              ; calculate SHA-512\n"
            "Usage #!interpreter [<args>] [<file] [<<eof]\n"
            " #!                   ; list all available interpreters\n"
            " #!python             ; run python commandline\n"
            " #!python < foo.py    ; run foo.py python script\n"
            " #!python <<EOF       ; get python code until 'EOF' mark\n"
            " #!python arg0 a1 <<q ; set arg0 and arg1 and read until 'q'\n"
            "Comments:\n"
            " # this is a comment  ; note the space after the sharp sign\n");
      }

      return 0;
}

static int cmd_visual(void *data, const char *input) {
      return r_core_visual ((RCore *)data, input);
}

static int cmd_system(void *data, const char *input) {
      int ret = 0;
      if (*input!='?') {
            char *cmd = r_core_sysenv_begin ((RCore*)data, input);
            if (cmd) {
                  ret = r_sys_cmd (cmd);
                  r_core_sysenv_end ((RCore*)data, input);
                  free (cmd);
            } else eprintf ("Error setting up system environment\n");
      } else r_core_sysenv_help ();
      return ret;
}

static int cmd_open(void *data, const char *input) {
      RCore *core = (RCore*)data;
      RCoreFile *file;
      ut64 addr;
      char *ptr;
      int num;

      switch (*input) {
      case '\0':
            r_core_file_list (core);
            break;
      case ' ':
            ptr = strchr (input+1, ' ');
            if (ptr) {
                  *ptr = '\0';
                  addr = r_num_math (core->num, ptr+1);
            } else {
                  num = atoi (input+1);
                  addr = 0LL;
            }
            if (num<=0) {
                  file = r_core_file_open (core, input+1, R_IO_READ, addr);
                  if (file) {
                        //eprintf ("Map '%s' in 0x%08"PFMT64x" with size 0x%"PFMT64x"\n",
                        //    input+1, addr, file->size);
                  } else eprintf ("Cannot open file '%s'\n", input+1);
            } else r_io_raise (core->io, num);
            r_core_block_read (core, 0);
            break;
      case '-':
            if (!r_core_file_close_fd (core, atoi (input+1)))
                  eprintf ("Unable to find filedescriptor %d\n", atoi (input+1));
            r_core_block_read (core, 0);
            break;
      case '?':
      default:
            eprintf ("Usage: o [file] ([offset])\n"
            " o                   ; list opened files\n"
            " o /bin/ls           ; open /bin/ls file\n"
            " o /bin/ls 0x8048000 ; map file\n"
            " o 4                 ; priorize io on fd 4 (bring to front)\n"
            " o-1                 ; close file index 1\n");
            break;
      }
      return 0;
}

// XXX this command is broken. output of _list is not compatible with input
static int cmd_meta(void *data, const char *input) {
      RAnalVarType *var;
      RListIter *iter;
      RCore *core = (RCore*)data;
      int i, ret, line = 0;
      ut64 addr_end = 0LL;
      ut64 addr = core->offset;
      char file[1024];
      switch (*input) {
      case '*':
            r_meta_list (core->anal->meta, R_META_TYPE_ANY);
            break;
      case 't':
            switch (input[1]) {
            case '-':
                  r_anal_var_type_del (core->anal, input+2);
                  break;
            case ' ':
                  {
                  int size;
                  const char *fmt = NULL;
                  const char *ptr, *name = input+2;
                  ptr = strchr (name, ' ');
                  if (ptr) {
                        size = atoi (ptr+1);
                        ptr = strchr (ptr+2, ' ');
                        if (ptr)
                              fmt = ptr+1;
                  }
                  if (fmt==NULL)
                        eprintf ("Usage: Ct name size format\n");
                  else r_anal_var_type_add (core->anal, name, size, fmt);
                  }
                  break;
            case '\0':
                  r_list_foreach (core->anal->vartypes, iter, var) {
                        r_cons_printf ("Ct %s %d %s\n", var->name, var->size, var->fmt);
                  }
                  break;
            default:
                  eprintf ("Usage: Ct[..]\n"
                        " Ct-int       : remove 'int' type\n"
                        " Ct int 4 d   : define int type\n");
                  break;
            }
            break;
      case 'L': // debug information of current offset
            ret = r_bin_meta_get_line (core->bin, core->offset, file, 1023, &line);
            if (ret) {
                  r_cons_printf ("file %s\nline %d\n", file, line);
                  ret = (line<5)? 5-line: 5;
                  line -= 2;
                  for (i = 0; i<ret; i++) {
                        char *row = r_file_slurp_line (file, line+i, 0);
                        r_cons_printf ("%c %.3x  %s\n", (i==2)?'>':' ', line+i, row);
                        free (row);
                  }
            } else eprintf ("Cannot find meta information at 0x%08"PFMT64x"\n", core->offset);
            break;
      // XXX: use R_META_TYPE_XXX here
      case 'C': /* comment */
      case 's': /* string */
      case 'd': /* data */
      case 'm': /* magic */
      case 'f': /* formatted */
            switch (input[1]) {
            case '-':
                  if (input[2]==' ')
                        addr = r_num_math (core->num, input+3);
                  r_meta_del (core->anal->meta, input[0], addr, addr+1, NULL);
                  break;
            case '\0':
            case '*':
                  r_meta_list (core->anal->meta, input[0]);
                  break;
            default: {
                  char *t, *p, name[128];
                  int type = input[0];
                  t = strdup (input+2);
                  p = strchr (t, ' ');
                  if (p) {
                        *p = '\0';
                        strncpy (name, p+1, sizeof (name));
                  } else
                  switch (type) {
                  case 's':
                        // TODO: filter \n and so on :)
                        r_core_read_at (core, addr, (ut8*)name, sizeof (name));
                        break;
                  default:
                        {
                        RFlagItem *fi = r_flag_get_i (core->flags, addr);
                        if (fi) strncpy (name, fi->name, sizeof (name));
                        else sprintf (name, "ptr_%08"PFMT64x"", addr);
                        }
                  }
                  addr_end = addr + atoi (input+1);
                  free (t);
                  r_meta_add (core->anal->meta, type, addr, addr_end, name);
                  }
            }
            break;
      case 'v':
            switch (input[1]) {
            case '-':
                  {
                  RAnalFcn *f;
                  RListIter *iter;
                  ut64 offset;
                  if (input[2]==' ') {
                        offset = r_num_math (core->num, input+3);
                        if ((f = r_anal_fcn_find (core->anal, offset, R_ANAL_FCN_TYPE_NULL)) != NULL)
                              memset (f->varsubs, 0, sizeof(f->varsubs));
                  } else if (input[2]=='*') {
                        r_list_foreach (core->anal->fcns, iter, f)
                              memset (f->varsubs, 0, sizeof(f->varsubs));
                  }
}
                  break;
            case '*':
                  {
                  RAnalFcn *f;
                  RListIter *iter;
                  r_list_foreach (core->anal->fcns, iter, f) {
                        for (i = 0; i < R_ANAL_VARSUBS; i++) {
                              if (f->varsubs[i].pat[0] != '\0')
                                    r_cons_printf ("Cv 0x%08llx %s %s\n", f->addr, f->varsubs[i].pat, f->varsubs[i].sub);
                              else break;
                        }
                  }
                  }
                  break;
            default:
                  {
                  RAnalFcn *f;
                  char *ptr = strdup(input+2), *pattern, *varsub;
                  ut64 offset = -1LL;
                  int n = r_str_word_set0 (ptr), i;
                  
                  if (n > 2) {
                        switch(n) {
                        case 3:
                              varsub = r_str_word_get0 (ptr, 2);
                        case 2:
                              pattern = r_str_word_get0 (ptr, 1);
                        case 1:
                              offset = r_num_math (core->num, r_str_word_get0 (ptr, 0));
                        }
                        if ((f = r_anal_fcn_find (core->anal, offset, R_ANAL_FCN_TYPE_NULL)) != NULL) {
                              for (i = 0; i < R_ANAL_VARSUBS; i++)
                                    if (f->varsubs[i].pat[0] == '\0' || !strcmp (f->varsubs[i].pat, pattern)) {
                                          strncpy (f->varsubs[i].pat, pattern, 1024);
                                          strncpy (f->varsubs[i].sub, varsub, 1024);
                                          break;
                                    }
                        } else eprintf ("Error: Function not found\n");
                  }
                  free (ptr);
                  }
            break;
            }
      case '-':
            if (input[1]!='*') {
                  if (input[1]==' ')
                        addr = r_num_math (core->num, input+2);
                  r_meta_del (core->anal->meta, R_META_TYPE_ANY, addr, 1, "");
            } else r_meta_cleanup (core->anal->meta, 0LL, UT64_MAX);
            break;
      case '\0':
      case '?':
            eprintf (
            "Usage: C[-LCvsdfm?] [...]\n"
            " C*                     # List meta info in r2 commands\n"
            " C-[@][ addr]           # delete metadata at given address\n"
            " CL[-] [addr]           # show 'code line' information (bininfo)\n"
            " CC [string]            # add comment\n"
            " Cv[-] offset reg name  # add var substitution\n"
            " Cs[-] [size] [[addr]]  # add string\n"
            " Cd[-] [size]           # hexdump data\n"
            " Cf[-] [sz] [fmt..]     # format memory (see pf?)\n"
            " Cm[-] [sz] [fmt..]     # magic parse (see pm?)\n");
            break;
      case 'F':
            {
            RAnalFcn *f = r_anal_fcn_find (core->anal, core->offset,
                        R_ANAL_FCN_TYPE_FCN|R_ANAL_FCN_TYPE_SYM);
            if (f) r_anal_fcn_from_string (core->anal, f, input+2);
            else eprintf ("Cannot find function here\n");
            }
            break;
      }
      return R_TRUE;
}

static int cmd_macro(void *data, const char *input) {
      char *buf = NULL;
      char *p, *ptr = (char *)input;
      RCore *core = (RCore*)data;
      switch (*input) {
      case ')':
            r_cmd_macro_break (&core->cmd->macro, input+1);
            break;
      case '-':
            r_cmd_macro_rm (&core->cmd->macro, input+1);
            break;
      case '\0':
            r_cmd_macro_list (&core->cmd->macro);
            break;
      case '?':
            eprintf (
            "Usage: (foo\\n..cmds..\\n)\n"
            " Record macros grouping commands\n"
            " (foo args\\n ..)     ; define a macro\n"
            " (-foo)              ; remove a macro\n"
            " .(foo)              ; to call it\n"
            " ()                  ; break inside macro\n"
            " (                   ; list all defined macros\n"
            "Argument support:\n"
            " (foo x y\\n$1 @ $2)  ; define fun with args\n"
            " .(foo 128 0x804800) ; call it with args\n"
            "Iterations:\n"
            " .(foo\\n() $@)       ; define iterator returning iter index\n"
            " x @@ .(foo)         ; iterate over them\n"
            );
            break;
      default:
            if (input[strlen (input)-1] != ')') {
                  buf = malloc (4096); // XXX: possible heap overflow here
                  strcpy (buf, input);
                  do {
                        ptr = buf + strlen (buf);
                        strcpy (ptr, ",");
                        ptr++;
                        fgets (ptr, 1024, stdin); // XXX: possible overflow // TODO: use r_cons here
                        p = strchr (ptr, '#');
                        if (p) *p = 0;
                        else ptr[strlen (ptr)-1] = 0; // chop \n
                        if (feof (stdin))
                              break;
                  } while (ptr[strlen (ptr)-1] != ')');
                  ptr = buf;
            }
            r_cmd_macro_add (&core->cmd->macro, ptr);
            free (buf);
            break;
      }
      return 0;
}

static int r_core_cmd_pipe(RCore *core, char *radare_cmd, char *shell_cmd) {
#if __UNIX__
      int fds[2];
      int stdout_fd, status;

      stdout_fd = dup (1);
      pipe (fds);
      radare_cmd = r_str_trim_head (radare_cmd);
      shell_cmd = r_str_trim_head (shell_cmd);
      if (fork ()) {
            dup2 (fds[1], 1);
            close (fds[1]);
            close (fds[0]);
            r_core_cmd (core, radare_cmd, 0);
            r_cons_flush ();
            close (1);
            wait (&status);
            dup2 (stdout_fd, 1);
            close (stdout_fd);
      } else {
            close (fds[1]);
            dup2 (fds[0], 0);
            dup2 (2, 1);
            execl ("/bin/sh", "sh", "-c", shell_cmd, NULL);
      }
      return status;
#else
#warning r_core_cmd_pipe UNIMPLEMENTED FOR THIS PLATFORM
      eprintf ("r_core_cmd_pipe: unimplemented for this platform\n");
      return -1;
#endif
}

static int r_core_cmd_subst(RCore *core, char *cmd) {
      char *ptr, *ptr2, *str;
      int i, len = strlen (cmd), pipefd, ret;

      if (!*cmd || cmd[0]=='\0')
            return 0;
      cmd = r_str_trim_head_tail (cmd);

      /* quoted / raw command */
      if (cmd[0] =='.' && cmd[1] == '"') { /* interpret */
            ret = r_cmd_call (core->cmd, cmd);
            return ret;
      }
      if (cmd[0] == '"') {
            if (cmd[len-1] != '"') {
                  eprintf ("parse: Missing ending '\"'\n");
                  return -1;
            }
            cmd[len-1]='\0';
            ret = r_cmd_call (core->cmd, cmd+1);
            return ret;
      }

      /* comments */
      if (*cmd!='#') {
            ptr = strrchr (cmd, '#');
            if (ptr) ptr[0]='\0';
      }

      /* multiple commands */
      ptr = strrchr (cmd, ';');
      if (ptr) {
            ptr[0]='\0';
            if (r_core_cmd_subst (core, cmd) == -1) 
                  return -1;
            cmd = ptr+1;
            r_cons_flush ();
      }

      /* pipe console to shell process */
      ptr = strchr (cmd, '|');
      if (ptr) {
            ptr[0] = '\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;
      }

      /* bool conditions */
      ptr = strchr(cmd, '&');
      while (ptr&&ptr[1]=='&') {
            ptr[0]='\0';
            ret = r_cmd_call (core->cmd, cmd);
            if (ret == -1){
                  eprintf ("command error(%s)\n", cmd);
                  return ret;
            }
            for (cmd=ptr+2;cmd&&cmd[0]==' ';cmd=cmd+1);
            ptr = strchr (cmd, '&');
      }

      /* Out Of Band Input */
      free (core->oobi);
      core->oobi = NULL;
      ptr = strchr (cmd, '<');
      if (ptr) {
            ptr[0] = '\0';
            if (ptr[1]=='<') {
                  /* this is a bit mess */
                  const char *oprompt = r_line_singleton ()->prompt;
                  oprompt = ">";
                  for (str=ptr+2; str[0]==' '; str=str+1);
                  eprintf ("==> Reading from stdin until '%s'\n", str);
                  free (core->oobi);
                  core->oobi = malloc (1);
                  core->oobi[0] = '\0';
                  core->oobi_len = 0;
                  for (;;) {
                        char buf[1024];
                        int ret;
                        write (1, "> ", 2);
                        fgets (buf, sizeof (buf)-1, stdin); // XXX use r_line ??
                        if (feof (stdin))
                              break;
                        buf[strlen (buf)-1]='\0';
                        ret = strlen (buf);
                        core->oobi_len += ret;
                        core->oobi = realloc (core->oobi, core->oobi_len+1);
                        if (!strcmp (buf, str))
                              break;
                        strcat ((char *)core->oobi, buf);
                  }
                  r_line_singleton ()->prompt = oprompt;
            } else {
                  for (str=ptr+1;str[0]== ' ';str=str+1);
                  eprintf ("SLURPING FILE '%s'\n", str);
                  core->oobi = (ut8*)r_file_slurp (str, &core->oobi_len);
                  if (core->oobi == NULL)
                        eprintf ("Cannot open file\n");
                  else if (ptr == cmd)
                        return r_core_cmd_buffer (core, (const char *)core->oobi);
            }
      }

      /* pipe console to file */
      ptr = strchr (cmd, '>');
      if (ptr) {
            ptr[0] = '\0';
            str = r_str_trim_head_tail (ptr+1+(ptr[1]=='>'));
            pipefd = r_cons_pipe_open (str, ptr[1]=='>');
            ret = r_core_cmd_subst (core, cmd);
            r_cons_flush ();
            r_cons_pipe_close (pipefd);
            return ret;
      }

      /* sub commands */
      ptr = strchr (cmd, '`');
      if (ptr) {
            ptr2 = strchr (ptr+1, '`');
            if (!ptr2) {
                  eprintf ("parse: Missing 'ยด' in expression.\n");
                  return -1;
            } else {
                  ptr[0] = '\0';
                  ptr2[0] = '\0';
                  str = r_core_cmd_str (core, ptr+1);
                  for(i=0;str[i];i++)
                        if (str[i]=='\n') str[i]=' ';
                  cmd = r_str_concat (strdup (cmd), r_str_concat (str, ptr2+1));
                  ret = r_core_cmd_subst (core, cmd);
                  free (cmd);
                  free (str);
                  return ret;
            }
      }

      /* grep the content */
      ptr = strchr (cmd, '~');
      if (ptr) {
            ptr[0]='\0';
            r_cons_grep (ptr+1);
      } else r_cons_grep (NULL);

      /* seek commands */
      if (cmd[0]!='('&& cmd[0]!='"')
            ptr = strchr (cmd, '@');
      else ptr = NULL;
      if (ptr) {
            ut64 tmpoff, tmpbsz;
            char *ptr2 = strchr (ptr+1, ':');
            *ptr = '\0';
            cmd = r_str_clean (cmd);
            tmpoff = core->offset;
            tmpbsz = core->blocksize;
            if (ptr2) {
                  *ptr2 = '\0';
                  r_core_block_size (core, r_num_math (core->num, ptr2+1));
            }

            if (ptr[1]=='@') {
                  // TODO: remove temporally seek (should be done by cmd_foreach)
                  ret = r_core_cmd_foreach (core, cmd, ptr+2);
                  //ret = -1; /* do not run out-of-foreach cmd */
            } else {
                  if (!ptr[1] || r_core_seek (core, r_num_math (core->num, ptr+1), 1))
                        ret = r_cmd_call (core->cmd, r_str_trim_head (cmd));
                  else ret = 0;
            }
            if (ptr2) {
                  *ptr2 = ':';
                  r_core_block_size (core, tmpbsz);
            }
            r_core_seek (core, tmpoff, 1);
            *ptr = '@';
            return ret;
      }

      ret = r_cmd_call (core->cmd, r_str_trim_head (cmd));
      return ret;
}

R_API int r_core_cmd_foreach(RCore *core, const char *cmd, char *each) {
      int i=0,j;
      char ch;
      char *word = NULL;
      char *str, *ostr;
      RListIter *iter;
      RFlagItem *flag;
      ut64 oseek, addr;

      for (; *each==' '; each++);
      for (; *cmd==' '; cmd++);

      oseek = core->offset;
      ostr = str = strdup(each);
      //radare_controlc();

      switch (each[0]) {
      case '?':
            r_cons_printf (
            "Foreach '@@' iterator command:\n"
            " This command is used to repeat a command over a list of offsets.\n"
            " x @@ sym.           Run 'x' over all flags matching 'sym.'\n"
            " 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");
            break;
      case '=':
            /* foreach list of items */
            each = str+1;
            do {
                  while (each[0]==' ')
                        each = each+1;
                  if (!*each) break;
                  str = strchr (each, ' ');
                  if (str) {
                        str[0]='\0';
                        addr = r_num_math (core->num, each);
                        str[0]=' ';
                  } else addr = r_num_math (core->num, each);
                  eprintf ("; 0x%08"PFMT64x":\n", addr);
                  each = str+1;
                  r_core_seek (core, addr, 1);
                  r_core_cmd (core, cmd, 0);
                  r_cons_flush ();
            } while (str != NULL);
            break;
      case '.':
            if (each[1]=='(') {
                  char cmd2[1024];
                  // TODO: use controlc() here
                  // XXX whats this 999 ?
                  for(core->cmd->macro.counter=0;i<999;core->cmd->macro.counter++) {
                        r_cmd_macro_call (&core->cmd->macro, each+2);
                        if (core->cmd->macro.brk_value == NULL)
                              break;

                        addr = core->cmd->macro._brk_value;
                        sprintf (cmd2, "%s @ 0x%08"PFMT64x"", cmd, addr);
                        eprintf ("0x%08"PFMT64x" (%s)\n", addr, cmd2);
                        r_core_seek (core, addr, 1);
                        r_core_cmd (core, cmd2, 0);
                        i++;
                  }
            } else {
                  char buf[1024];
                  char cmd2[1024];
                  FILE *fd = fopen (each+1, "r");
                  if (fd) {
                        core->cmd->macro.counter=0;
                        while (!feof (fd)) {
                              buf[0] = '\0';
                              if (fgets (buf, 1024, fd) == NULL)
                                    break;
                              addr = r_num_math (core->num, buf);
                              eprintf ("0x%08"PFMT64x": %s\n", addr, cmd);
                              sprintf (cmd2, "%s @ 0x%08"PFMT64x"", cmd, addr);
                              r_core_seek (core, addr, 1); // XXX
                              r_core_cmd (core, cmd2, 0);
                              core->cmd->macro.counter++;
                        }
                        fclose (fd);
                  } else eprintf ("Cannot open file '%s' to read offsets\n", each+1);
            }
            break;
      default:
            core->cmd->macro.counter = 0;
            //while(str[i]) && !core->interrupted) {
            while (str[i]) {
                  j = i;
                  for (;str[j]&&str[j]==' ';j++); // skip spaces
                  for (i=j;str[i]&&str[i]!=' ';i++); // find EOS
                  ch = str[i];
                  str[i] = '\0';
                  word = strdup (str+j);
                  if (word == NULL)
                        break;
                  str[i] = ch;
                  if (strchr (word, '*')) {
#if 0
                        /* for all flags in current flagspace */
                        list_for_each(pos, &flags) {
                              flag_t *flag = (flag_t *)list_entry(pos, flag_t, list);
                              //if (core->interrupted)
                              //    break;
                              /* filter per flag spaces */
      //                      if ((flag_space_idx != -1) && (flag->space != flag_space_idx))
      //                            continue;

                              core->offset = flag->offset;
                              radare_read(0);
                              cons_printf("; @@ 0x%08"PFMT64x" (%s)\n", core->offset, flag->name);
                              radare_cmd(cmd,0);
                        }
#else
                        eprintf ("No flags foreach implemented\n");
#endif
                  } else {
                        /* for all flags in current flagspace */
                        r_list_foreach (core->flags->flags, iter, flag) {
                              if (r_cons_singleton()->breaked)
                                    break;
                              /* filter per flag spaces */
                              if ((core->flags->space_idx != -1) && (flag->space != core->flags->space_idx))
                                    continue;
                              if (word[0]=='\0' || strstr(flag->name, word) != NULL) {
                                    r_core_seek (core, flag->offset, 1);
                                    // TODO: Debug mode print
                                    //r_cons_printf ("# @@ 0x%08"PFMT64x" (%s)\n", core->offset, flag->name);
                                    r_core_cmd (core, cmd, 0);
                              }
                        }
      #if 0
                        /* ugly copypasta from tmpseek .. */
                        if (strstr(word, each)) {
                              if (word[i]=='+'||word[i]=='-')
                                    core->offset = core->offset + r_num_math (get_math(core->num, word);
                              else  core->offset = r_num_math (get_math(core->num, word);
                              radare_read(0);
                              cons_printf("; @@ 0x%08"PFMT64x"\n", core->offset);
                              radare_cmd(cmd,0);
                        }
      #endif
                        r_cons_break (NULL, NULL);

                        core->cmd->macro.counter++ ;
                        free (word);
                        word = NULL;
                  }
            }
      }
      r_cons_break_end ();
      // XXX: use r_core_seek here
      core->offset = oseek;

      free (word);
      free (ostr);
      return R_TRUE;
}

R_API int r_core_cmd(RCore *core, const char *command, int log) {
      int len, rep, ret = R_FALSE;
      char *cmd, *ocmd;
      if (command != NULL) {
            /* list command plugins */
            if (!strcmp (command, ":")) {
                  RListIter *iter = r_list_iterator (core->cmd->plist);
                  while (r_list_iter_next (iter)) {
                        RCmdPlugin *cp = (RCmdPlugin*) r_list_iter_get (iter);
                        r_cons_printf ("%s: %s\n", cp->name, cp->desc);
                  }
                  return 0;
            }
            len = strlen (command)+1;
            ocmd = cmd = malloc (len+8192);
            if (ocmd == NULL)
                  return R_FALSE;
            memcpy (cmd, command, len);
            cmd = r_str_trim_head_tail (cmd);

            rep = atoi (cmd);
            if (rep<1) rep = 1;
            if (rep>0) {
                  ret = R_TRUE;
                  while (*cmd>='0'&&*cmd<='9')
                        cmd++;
                  while (rep--) {
                        ret = r_core_cmd_subst (core, cmd);
                        if (ret<0)
                              break;
                  }
            }

            if (log) r_line_hist_add (command);

            free (core->oobi);
            free (ocmd);
            core->oobi = NULL;
            core->oobi_len = 0;
      }
      return ret;
}

R_API int r_core_cmd_file(RCore *core, const char *file) {
      int ret = R_TRUE;
      char *data, *odata = r_file_slurp (file, NULL);
      if (odata != NULL) {
            char *nl = strchr (odata, '\n');
            if (nl) {
                  data = odata;
                  do {
                        *nl = '\0';
                        if (r_core_cmd (core, data, 0) == -1) {
                              eprintf ("r_core_cmd_file: Failed to run '%s'\n", data);
                              ret = R_FALSE;
                              break;
                        }
                        data = nl+1;
                  } while ((nl = strchr (data, '\n')));
            }
            free (odata);
      } else ret = R_FALSE;
      return ret;
}

R_API int r_core_cmd_command(RCore *core, const char *command) {
      int len;
      char *buf, *rcmd, *ptr;
      rcmd = ptr = buf = r_sys_cmd_str (command, 0, &len);
      if (buf == NULL)
            return -1;
      while ((ptr = strstr (rcmd, "\n"))) {
            *ptr = '\0';
            if (r_core_cmd (core, rcmd, 0) == -1) {
                  eprintf ("Error running command '%s'\n", rcmd);
                  break;
            }
            rcmd += strlen (rcmd)+1;
      }
      r_str_free(buf);
      return 0;
}

static void cmd_dm(RCore *core, const char *input) {
      switch (input[0]) {
      case '?':
            r_cons_printf (
            "Usage: dm [size]\n"
            " dm         List memory maps of target process\n"
            " dm*        Same as above but in radare commands\n"
            " dm 4096    Allocate 4096 bytes in child process\n"
            " dm-0x8048  Deallocate memory map of address 0x8048\n"
            " dmi [addr|libname] [symname]   List symbols of target lib\n"
            " dmi* [addr|libname] [symname]  Same as above but in radare commands\n"
            //" dm rw- esp 9K  set 9KB of the stack as read+write (no exec)\n"
            "TODO: map files in process memory.\n");
            break;
      case 'i':
            { // Move to a separate function
            ut64 addr = 0LL;
            char *libname = NULL, *symname = NULL;
            char *ptr = strdup (r_str_trim_head ((char*)input+2));
            char cmd[1024], *cmdret;
            int i, len;

            i = r_str_word_set0 (ptr);
            switch (i) {
                  case 2: // get symname
                        symname = r_str_word_get0 (ptr, 1);
                  case 1: // get addr|libname
                        addr = r_num_math (core->num, r_str_word_get0 (ptr, 0));
                        if (!addr) libname = r_str_word_get0 (ptr, 0);
            }
            r_debug_map_sync (core->dbg); // update process memory maps
            RListIter *iter = r_list_iterator (core->dbg->maps);
            while (r_list_iter_next (iter)) {
                  RDebugMap *map = r_list_iter_get (iter);
                  if ((addr != -1 && (addr >= map->addr && addr < map->addr_end)) ||
                        (libname != NULL && (strstr (map->name, libname)))) {
                        if (symname)
                              snprintf (cmd, sizeof (cmd), "rabin2 -b 0x%08"PFMT64x" -s%svn %s %s",
                                          map->addr, input[1]=='*'?"r":"", symname, map->name);
                        else
                              snprintf (cmd, sizeof (cmd), "rabin2 -b 0x%08"PFMT64x" -s%sv %s",
                                          map->addr, input[1]=='*'?"r":"", map->name);
                        if ((cmdret = r_sys_cmd_str (cmd, 0, &len))) {
                              r_cons_printf (cmdret);
                              free (cmdret);
                        }
                        break;
                  }
            }
            free (ptr);
            }
            break;
      case '*':
      case '-':
      case ' ':
            eprintf ("TODO\n");
            break;
      default:
            r_debug_map_sync (core->dbg); // update process memory maps
            r_debug_map_list (core->dbg, core->offset);
            break;
      }
}

static int step_until(RCore *core, ut64 addr) {
      ut64 off = r_debug_reg_get (core->dbg, "pc");
      if (off == 0LL) {
            eprintf ("Cannot 'drn pc'\n");
            return R_FALSE;
      }
      if (addr == 0LL) {
            eprintf ("Cannot continue until address 0\n");
            return R_FALSE;
      }
      do {
            r_debug_step (core->dbg, 1);
            if (checkbpcallback (core)) {
                  eprintf ("Interrupted by a breakpoint\n");
                  break;
            }
            off = r_debug_reg_get (core->dbg, "pc");
            // check breakpoint here
      } while (off != addr);
      return R_TRUE;
      
}

static int step_line(RCore *core, int times) {
      char file[512], file2[512];
      int find_meta, line, line2;
      ut64 off = r_debug_reg_get (core->dbg, "pc");
      if (off == 0LL) {
            eprintf ("Cannot 'drn pc'\n");
            return R_FALSE;
      }
      if (r_bin_meta_get_line (core->bin, off, file, sizeof (file), &line)) {
            eprintf ("--> 0x%08"PFMT64x" %s : %d\n", off, file, line);
            eprintf ("--> %s\n", r_file_slurp_line (file, line, 0));
            find_meta = R_FALSE;
      } else {
            eprintf ("--> Stepping until dwarf line\n");
            find_meta = R_TRUE;
      }
      do {
            r_debug_step (core->dbg, 1);
            if (checkbpcallback (core)) {
                  eprintf ("Interrupted by a breakpoint\n");
                  break;
            }
            off = r_debug_reg_get (core->dbg, "pc");
            if (!r_bin_meta_get_line (core->bin, off, file2, sizeof (file2), &line2)) {
                  if (find_meta)
                        continue;
                  eprintf ("Cannot retrieve dwarf info at 0x%08"PFMT64x"\n", off);
                  return R_FALSE;
            }
      } while (!strcmp (file, file2) && line == line2);
      eprintf ("--> 0x%08"PFMT64x" %s : %d\n", off, file2, line2);
      eprintf ("--> %s\n", r_file_slurp_line (file2, line2, 0));
      return R_TRUE;
}

static void cmd_debug_pid(RCore *core, const char *input) {
      const char *ptr;
      int pid, sig;
      switch (input[1]) {
      case 'k':
            /* XXX: not for threads? signal is for a whole process!! */
            /* XXX: but we want fine-grained access to process resources */
            pid = atoi (input+2);
            ptr = strchr (input, ' ');
            if (ptr) sig = atoi (ptr+1);
            else sig = 0;
            if (pid > 0) {
                  eprintf ("Sending signal '%d' to pid '%d'\n",
                        sig, pid);
                  r_debug_kill (core->dbg, R_FALSE, sig);
            } else eprintf ("Invalid arguments\n");
            break;
      case 'n':
            eprintf ("TODO: debug_fork: %d\n", r_debug_fork (core->dbg));
            break;
      case 't':
            if (input[2] == 'n') {
                  eprintf ("TODO: debug_clone: %d\n", r_debug_clone (core->dbg));
            } else
            if (input[2]=='=' || input[2]==' ')
                  r_debug_select (core->dbg, core->dbg->pid,
                        (int) r_num_math (core->num, input+3));
            else r_debug_thread_list (core->dbg, core->dbg->pid);
            break;
      case '?':
            r_cons_printf ("Usage: dp[=][pid]\n"
                  " dp      list current pid and childrens\n"
                  " dp 748  list childs of pid\n"
                  " dp*     list all attachable pids\n"
                  " dpa 377 attach and select this pid\n"
                  " dp=748  select this pid\n"
                  " dpn     Create new process (fork)\n"
                  " dpnt    Create new thread (clone)\n"
                  " dpt     List threads of current pid\n"
                  " dpt 74  List threads of given process\n"
                  " dpt=64  Attach to thread\n"
                  " dpk P S send signal S to P process id\n");
            break;
      case 'a':
            r_debug_attach (core->dbg,
                  (int) r_num_math (core->num, input+2));
            r_debug_select (core->dbg, core->dbg->pid, core->dbg->tid);
            break;
      case 'f':
            r_debug_select (core->dbg, core->file->fd->fd, core->dbg->tid);
            break;
      case '=':
            r_debug_select (core->dbg,
                  (int) r_num_math (core->num, input+2), core->dbg->tid);
            break;
      case '*':
            r_debug_pid_list (core->dbg, 0);
            break;
      case ' ':
            r_debug_pid_list (core->dbg,
                  (int) r_num_math (core->num, input+2));
            break;
      default:
            r_debug_pid_list (core->dbg, core->dbg->pid);
            break;
      }
}

static int cmd_debug(void *data, const char *input) {
      RCore *core = (RCore *)data;
      struct r_anal_op_t analop;
      int len, times, sig;
      ut64 addr;
      char *ptr;

      switch (input[0]) {
      case 'x': // XXX : only for testing
            r_debug_execute (core->dbg, (ut8*)
                  "\xc7\xc0\x03\x00\x00\x00\x33\xdb\x33"
                  "\xcc\xc7\xc2\x10\x00\x00\x00\xcd\x80", 18);
            break;
      case 't':
            // TODO: Add support to change the tag
            if (input[1]=='r') {
                  r_debug_trace_free (core->dbg);
                  core->dbg->trace = r_debug_trace_new ();
            } else r_debug_trace_list (core->dbg, -1);
            break;
      case 'd':
            eprintf ("TODO: dd: file descriptors\n");
            switch (input[1]) {
            case 0:
                  // r_debug_desc_list()
                  break;
            case '*':
                  // r_debug_desc_list(1)
                  break;
            case 's':
                  // r_debug_desc_seek()
                  break;
            case 'd':
                  // r_debug_desc_dup()
                  break;
            case 'r':
                  // r_debug_desc_read()
                  break;
            case 'w':
                  // r_debug_desc_write()
                  break;
            case '-':
                  // close file
                  break;
            case ' ':
                  // open file
                  break;
            }
            break;
      case 's':
            times = atoi (input+2);
            if (times<1) times = 1;
            switch (input[1]) {
            case '?':
                  r_cons_printf ("Usage: ds[ol] [count]\n"
                        " ds       step one instruction\n"
                        " ds 4     step 4 instructions\n"
                        " dso 3    step over 3 instructions\n"
                        " dsu addr step until address\n"
                        " dsl      step one source line\n"
                        " dsl 40   step 40 source lines\n");
                  break;
            case 'u':
                  r_reg_arena_swap (core->dbg->reg, R_TRUE);
                  step_until (core, r_num_math (core->num, input+2)); // XXX dupped by times
                  break;
            case 'o':
                  r_reg_arena_swap (core->dbg->reg, R_TRUE);
                  r_debug_step_over (core->dbg, times);
                  if (checkbpcallback (core)) {
                        eprintf ("Interrupted by a breakpoint\n");
                        break;
                  }
                  break;
            case 'l':
                  r_reg_arena_swap (core->dbg->reg, R_TRUE);
                  step_line (core, times);
                  break;
            default:
                  r_reg_arena_swap (core->dbg->reg, R_TRUE);
                  r_debug_reg_sync (core->dbg, R_REG_TYPE_GPR, R_FALSE);
                  r_debug_step (core->dbg, times);
                  if (checkbpcallback (core)) {
                        eprintf ("Interrupted by a breakpoint\n");
                        break;
                  }
            }
            break;
      case 'b':
            r_core_cmd_bp (core, input);
            break;
      case 'H':
            eprintf ("TODO: transplant process\n");
            break;
      case 'c':
            switch (input[1]) {
            case '?':
                  eprintf("Usage: dc[?]  -- continue execution\n"
                        " dc?              show this help\n"
                        " dc               continue execution of all childs\n"
                        " dcf              continue until fork (TODO)\n"
                        " dct [len]        traptrace from curseek to len, no argument to list\n"
                        " dcu [addr]       continue until address\n"
                        " dco [num]        step over N instructions\n"
                        " dcs [num]        continue until syscall\n"
                        " dcc              continue until call (use step into)\n"
                        " dcr              continue until ret (uses step over)\n"
                        " dck [sig] [pid]  continue sending kill 9 to process\n"
                        " dc [pid]         continue execution of pid\n"
                        " dc[-pid]         stop execution of pid\n"
                        "TODO: dcu/dcr needs dbg.untilover=true??\n"
                        "TODO: same for only user/libs side, to avoid steping into libs\n"
                        "TODO: support for threads?\n");
                  break;
            case 'c':
                  r_reg_arena_swap (core->dbg->reg, R_TRUE);
                  r_debug_continue_until_optype (core->dbg, R_ANAL_OP_TYPE_CALL, 0);
                  checkbpcallback (core);
                  break;
            case 'r':
                  r_reg_arena_swap (core->dbg->reg, R_TRUE);
                  r_debug_continue_until_optype (core->dbg, R_ANAL_OP_TYPE_RET, 1);
                  checkbpcallback (core);
                  break;
            case 'k':
                  // select pid and r_debug_continue_kill (core->dbg, 
                  r_reg_arena_swap (core->dbg->reg, R_TRUE);
                  ptr = strchr (input+3, ' ');
                  if (ptr) {
                        bypassbp (core);
                        int old_pid = core->dbg->pid;
                        int old_tid = core->dbg->tid;
                        int pid = atoi (ptr+1);
                        int tid = pid; // XXX
                        *ptr = 0;
                        r_debug_select (core->dbg, pid, tid);
                        r_debug_continue_kill (core->dbg, atoi (input+2));
                        r_debug_select (core->dbg, old_pid, old_tid);
                  } else r_debug_continue_kill (core->dbg, atoi (input+2));
                  checkbpcallback (core);
                  break;
            case 's':
                  sig = r_num_math (core->num, input+2);
                  eprintf ("Continue until syscall %d\n", sig);
                  r_reg_arena_swap (core->dbg->reg, R_TRUE);
                  r_debug_continue_syscall (core->dbg, sig);
                  checkbpcallback (core);
                  /* TODO : use r_syscall here, to retrieve syscall info */
                  break;
            case 'u':
                  addr = r_num_math (core->num, input+2);
                  if (addr) {
                        eprintf ("Continue until 0x%08"PFMT64x"\n", addr);
                        bypassbp (core);
                        r_reg_arena_swap (core->dbg->reg, R_TRUE);
                        r_bp_add_sw (core->dbg->bp, addr, 1, R_BP_PROT_EXEC);
                        r_debug_continue (core->dbg);
                        checkbpcallback (core);
                        r_bp_del (core->dbg->bp, addr);
                  } else eprintf ("Cannot continue until address 0\n");
                  break;
            case ' ':
                  {
                        int old_pid = core->dbg->pid;
                        int pid = atoi (input+2);
                        bypassbp (core);
                        r_reg_arena_swap (core->dbg->reg, R_TRUE);
                        r_debug_select (core->dbg, pid, core->dbg->tid);
                        r_debug_continue (core->dbg);
                        r_debug_select (core->dbg, old_pid, core->dbg->tid);
                        checkbpcallback (core);
                  }
                  break;
            case 't':
                  len = r_num_math (core->num, input+2);
                  if (len == 0) {
                        r_bp_traptrace_list (core->dbg->bp);
                  } else {
                        ut64 oaddr = 0LL;
                        eprintf ("Trap tracing 0x%08"PFMT64x"-0x%08"PFMT64x"\n", core->offset, core->offset+len);
                        r_reg_arena_swap (core->dbg->reg, R_TRUE);
                        r_bp_traptrace_reset (core->dbg->bp, R_TRUE);
                        r_bp_traptrace_add (core->dbg->bp, core->offset, core->offset+len);
                        r_bp_traptrace_enable (core->dbg->bp, R_TRUE);
                        do {
                              ut8 buf[32];
                              r_debug_continue (core->dbg);
                              if (checkbpcallback (core)) {
                                    eprintf ("Interrupted by breakpoint\n");
                                    break;
                              }
                              addr = r_debug_reg_get (core->dbg, "pc");
                              if (addr == 0LL) {
                                    eprintf ("pc=0\n");
                                    break;
                              }
                              if (addr == oaddr) {
                                    eprintf ("pc=opc\n");
                                    break;
                              }
                              oaddr = addr;
                              /* XXX Bottleneck..we need to reuse the bytes read by traptrace */
                              // XXX Do asm.arch should define the max size of opcode?
                              r_core_read_at (core, addr, buf, 32); // XXX longer opcodes?
                              r_anal_op (core->anal, &analop, addr, buf, sizeof (buf));
                        } while (r_bp_traptrace_at (core->dbg->bp, addr, analop.length));
                        r_bp_traptrace_enable (core->dbg->bp, R_FALSE);
                  }
                  break;
            default:
                  bypassbp (core);
                  r_reg_arena_swap (core->dbg->reg, R_TRUE);
                  r_debug_continue (core->dbg);
                  checkbpcallback (core);
            }
            break;
      case 'm':
            cmd_dm (core, input+1);
            break;
      case 'r':
            cmd_reg (core, input+1);
            //r_core_cmd (core, "|reg", 0);
            break;
      case 'p':
            cmd_debug_pid (core, input);
            break;
      case 'h':
            if (input[1]==' ')
                  r_debug_use (core->dbg, input+2);
            else r_debug_plugin_list (core->dbg);
            break;
      default:
            r_cons_printf ("Usage: d[sbhcrbo] [arg]\n"
            " dh [handler]   list or set debugger handler\n"
            " dH [handler]   transplant process to a new handler\n"
            " dd             file descriptors (!fd in r1)\n"
            " ds[ol] N       step, over, source line\n"
            " dp[=*?t][pid]  list, attach to process or thread id\n"
            " dc[?]          continue execution. dc? for more\n"
            " dr[?]          cpu registers, dr? for extended help\n"
            " db[?]          breakpoints\n"
            " dbt            display backtrace\n"
            " dt[r] [tag]    display instruction traces (dtr=reset)\n"
            " dm             show memory maps\n");
            break;
      }
      return 0;
}

//TODO: Fix disasm loop is mandatory
R_API char *r_core_disassemble_instr(RCore *core, ut64 addr, int l) {
      char *cmd, *ret = NULL;
      cmd = r_str_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;
}

R_API int r_core_cmd_buffer(void *user, const char *buf) {
      char *ptr, *optr, *str = strdup (buf);
      optr = str;
      ptr = strchr (str, '\n');
      while (ptr) {
            ptr[0]='\0';
            r_core_cmd (user, optr, 0);
            optr = ptr+1;
            ptr = strchr (str, '\n');
      }
      r_core_cmd (user, optr, 0);
      free (str);
      return R_TRUE;
}

R_API int r_core_cmdf(void *user, const char *fmt, ...) {
      char string[1024];
      int ret;
      va_list ap;
      va_start (ap, fmt);
      vsnprintf (string, sizeof (string), fmt, ap);
      ret = r_core_cmd ((RCore *)user, string, 0);
      va_end(ap);
      return ret;
}

R_API int r_core_cmd0(void *user, const char *cmd) {
      return r_core_cmd ((RCore *)user, cmd, 0);
}

/* return: pointer to a buffer with the output of the command */
R_API char *r_core_cmd_str(RCore *core, const char *cmd) {
      char *retstr = NULL;
      r_cons_reset ();
      if (r_core_cmd (core, cmd, 0) == -1) {
            eprintf ("Invalid command: %s\n", cmd);
            retstr = strdup ("");
      } else {
            r_cons_filter ();
            const char *static_str = r_cons_get_buffer ();
            retstr = strdup (static_str?static_str:"");
            r_cons_reset ();
      }
      return retstr;
}

void r_core_cmd_init(RCore *core) {
      core->cmd = r_cmd_new ();
      core->cmd->macro.num = core->num;
      core->cmd->macro.user = core;
      core->cmd->macro.cmd = r_core_cmd0;
      r_cmd_set_data (core->cmd, core);
      r_cmd_add (core->cmd, "x",        "alias for px", &cmd_hexdump);
      r_cmd_add (core->cmd, "mount",    "mount filesystem", &cmd_mount);
      r_cmd_add (core->cmd, "analysis", "analysis", &cmd_anal);
      r_cmd_add (core->cmd, "flag",     "get/set flags", &cmd_flag);
      r_cmd_add (core->cmd, "debug",    "debugger operations", &cmd_debug);
      r_cmd_add (core->cmd, "info",     "get file info", &cmd_info);
      r_cmd_add (core->cmd, "cmp",      "compare memory", &cmd_cmp);
      r_cmd_add (core->cmd, "seek",     "seek to an offset", &cmd_seek);
      r_cmd_add (core->cmd, "zign",     "zignatures", &cmd_zign);
      r_cmd_add (core->cmd, "Section",  "setup section io information", &cmd_section);
      r_cmd_add (core->cmd, "bsize",    "change block size", &cmd_bsize);
      r_cmd_add (core->cmd, "eval",     "evaluate configuration variable", &cmd_eval);
      r_cmd_add (core->cmd, "print",    "print current block", &cmd_print);
      r_cmd_add (core->cmd, "write",    "write bytes", &cmd_write);
      r_cmd_add (core->cmd, "Code",     "code metadata", &cmd_meta);
      r_cmd_add (core->cmd, "Project",  "project", &cmd_project);
      r_cmd_add (core->cmd, "open",     "open or map file", &cmd_open);
      r_cmd_add (core->cmd, "yank",     "yank bytes", &cmd_yank);
      r_cmd_add (core->cmd, "resize",   "change file size", &cmd_resize);
      r_cmd_add (core->cmd, "Visual",   "enter visual mode", &cmd_visual);
      r_cmd_add (core->cmd, "!",        "run system command", &cmd_system);
      r_cmd_add (core->cmd, "=",        "io pipe", &cmd_rap); 
      r_cmd_add (core->cmd, "#",        "calculate hash", &cmd_hash);
      r_cmd_add (core->cmd, "?",        "help message", &cmd_help);
      r_cmd_add (core->cmd, ".",        "interpret", &cmd_interpret);
      r_cmd_add (core->cmd, "/",        "search kw, pattern aes", &cmd_search);
      r_cmd_add (core->cmd, "(",        "macro", &cmd_macro);
      r_cmd_add (core->cmd, "quit",     "exit program session", &cmd_quit);
}

Generated by  Doxygen 1.6.0   Back to index