35 Commits
Author SHA1 Message Date
pancake bb011f88af Release 0.6 2016-12-12 00:22:39 +01:00
pancake c5498bd961 Add llvm bitcode build target 2015-06-19 10:13:03 +02:00
pancake a173daa812 Add -c and -q 2013-09-16 03:51:14 +02:00
pancake 9096ed5126 Add 'ired.js' target 2013-09-16 03:05:13 +02:00
pancake b074f2280d Initial import of calc.c . needs cleanup 2013-07-08 04:10:42 +02:00
pancake ec8e0225c3 Many bug fixes for vired. Added 'd' command to disassemble 2013-07-08 03:43:44 +02:00
pancake 2dca803f6d Release 0.5 - Fix minor C warning 2013-07-08 01:04:45 +02:00
pancake fba8f8e1a7 'make dist' uses git now 2013-06-10 02:01:56 +02:00
pancake afbe2e04f6 Fix write command 2013-05-17 18:24:06 +02:00
pancake 085b908d37 Initial support for return values in commands 2013-05-17 17:16:25 +02:00
pancake 4f1d810e98 Fix < command using io_seek 2013-05-17 14:26:25 +02:00
pancake bed1916abc Use markdown in readme and update copyleft timestamps 2013-02-18 17:33:19 +01:00
pancake 36e027fe48 Remove deprecated gitpush.sh 2012-06-29 00:57:11 +02:00
pancake 3fef4efbb5 Fix makefile dependencies and make tests work on osx 2012-06-29 00:50:55 +02:00
pancake 0e0f906f66 Still broken but a bit little fixed 2012-06-27 18:44:13 +02:00
pancake 5fee57d158 * Fix ired 2012-06-27 18:28:28 +02:00
pancake 75b31677e4 * fix -v output and free() warning 2012-03-07 11:56:37 +01:00
pancake 687644afdd * Fix make install when ired is running
* Minor fixes in README
2011-07-28 18:18:07 +02:00
pancake ac04c6e95e * Add initial gitpush script for github integration 2011-07-28 18:09:51 +02:00
pancake 204dbde78e * Properly fix all those signed/unsigned issues 2011-07-28 18:04:01 +02:00
pancake b6db2f859f * Fix search for bytes >0x7f. Thanks Dreyer! 2011-07-26 11:06:41 +02:00
pancake@dazo 6e0f3122b6 * Add patch from @jsegura fixing make clean 2010-09-22 19:51:20 +02:00
pancake@dazo 718330da85 * merge 2010-09-22 19:50:52 +02:00
pancake fca56e2c20 * Fix seeking on scripts 2010-07-22 14:49:36 +02:00
pancake@dazo 4d81079a14 * hexdump output is easily parseable
* Add hexparse.c
2010-06-14 00:45:16 +02:00
pancake@dazo 5a5595ced6 * Add missing TODO file 2010-05-12 10:05:06 +02:00
pancake@dazo f6a4705bf7 * Fix segfault when hexdumping -1 bytes 2010-05-12 10:00:07 +02:00
pancake@dazo b6649372ab * Various syntax fixes (like in suckless.org style)
* Update license headers (we are in 2010)
* Fix slurp in bdiff.c
2010-04-29 11:25:37 +02:00
pancake@flubox2 8bdc8dc92d * Merge heads 2010-02-09 17:33:55 +01:00
pancake@dazo 88c93994a0 * Initial import of 'bdiff'
* Added test suite for bdiff
* Looks like its buggy in some situations
2010-02-06 18:48:51 +01:00
pancake@dazo 0f9a7f7a1b * Added 'r+' command to resize file N bytes at curseek
* Increase the maximum length of input buffers
2010-02-06 14:02:06 +01:00
pancake@flubox 4ddf34f1f8 * Fix make dist for old versions of mercurial 2009-12-22 13:58:24 +01:00
pancake@flubox 6d744e39a7 * Bump revision to 0.5
* Default install directory is /usr/local
* Rename red.h to ired.h

--HG--
rename : red.h => ired.h
2009-12-22 13:56:01 +01:00
pancake@flubox 28d49ebd95 * Release ired 0.4
* Set PATH in vired to run it from current directory
2009-12-22 13:50:45 +01:00
[email protected] 4312ed31c8 * Updated manpages with documentation about environment
* Lot of small code cleanups (reduce code to 500LOC)
  - Sort include directives
  - Fix return value when file open fails
  - Reduce function exit points
  - More use of the ? operator
  - Bigger buffers for variables
* Add more checks in many places
  - Show errors when something is wrong
  - Check for negative values
  - Use ut8 and ut64 when possible
2009-10-07 02:48:18 +02:00
21 changed files with 1318 additions and 334 deletions

No files matched your search

+28 -12
View File
@@ -1,16 +1,31 @@
CC?=gcc
VERSION=0.6git
CCw32?=i486-mingw32-gcc
CFLAGS+=-O2 -Wall
PREFIX?=/usr
#CFLAGS+=-DVERSION=\"${VERSION}\"
PREFIX?=/usr/local
DESTDIR?=
all:
${CC} ${CFLAGS} ired.c -o ired
all: ired bdiff
bdiff: bdiff.o
${CC} ${CFLAGS} bdiff.o -o bdiff
ired.o: calc.c cmd.c io.c util.c hexparse.c
ired.js:
emcc -o ired.js ired.c
ired.bc:
clang -emit-llvm -o ired.bc -c ired.c
ired: ired.o
${CC} ${CFLAGS} ired.o -o ired
dist:
if [ -z "${VERSION}" ]; then echo "make dist VERSION=0.3" ; exit 1 ; fi
mkdir -p ired-${VERSION}
cd ired-${VERSION} ; hg clone .. . ; rm -rf .hg
@if [ -z "${VERSION}" ]; then echo "Try: make dist VERSION=0.5" ; exit 1 ; fi
git clone . ired-${VERSION}
rm -rf ired-${VERSION}/.git
tar czvf ired-${VERSION}.tar.gz ired-${VERSION}
rm -rf ired-${VERSION}
@@ -21,17 +36,18 @@ loc:
@wc -l *.c *.h | grep total
clean:
rm -f ired ired.o
rm -f ired ired.o bdiff bdiff.o
install:
mkdir -p ${DESTDIR}${PREFIX}/bin
cp ired ${DESTDIR}${PREFIX}/bin
cp vired ${DESTDIR}${PREFIX}/bin
cp -f ired ${DESTDIR}${PREFIX}/bin
cp -f bdiff ${DESTDIR}${PREFIX}/bin
cp -f vired ${DESTDIR}${PREFIX}/bin
mkdir -p ${DESTDIR}${PREFIX}/share/man/man1
cp ired.1 ${DESTDIR}${PREFIX}/share/man/man1
cp vired.1 ${DESTDIR}${PREFIX}/share/man/man1
cp -f ired.1 ${DESTDIR}${PREFIX}/share/man/man1
cp -f vired.1 ${DESTDIR}${PREFIX}/share/man/man1
uninstall:
deinstall uninstall:
rm -f ${DESTDIR}${PREFIX}/bin/ired
rm -f ${DESTDIR}${PREFIX}/bin/vired
rm -f ${DESTDIR}${PREFIX}/share/man/man1/ired.1
-44
View File
@@ -1,44 +0,0 @@
RED stands for the raw editor
============================= --pancake
red aims to be a minimalistic reimplementation of the radare shell
without much complexity and relaying all the extensibility to
external applications trying to keep the source as small as possible.
COMMANDS
========
? is for help get help or evaluate numeric expression
x hexdump hexdump
X dword dump hexpair dump
> file dump current block to file
< file slurp file into current block
w "string\x00" write string
w 023839400 write hexpairs
b 30 set block size
s addr seek address
r [size|-rmv] get filesize, truncate file to size, or -remove bytes
p [bwWdDqQiIF.] print formatted the current block
q quit
WORK IN PROGRESS
================
print command
b/w/d/q byte, word, dword, qword (little endian)
B/W/D/Q byte, word, dword, qword (big endian)
i/I/f/F int32 (lil, big), float (lil, big)
z/Z zero-terminatted strings (ascii, widechar)
./: skip 1 or 4 chars
* repeat last value until death
TODO:
=====
- support for escapped characters in string write and search ops
- Add support for simple math ops (+,-,*,/) no parenthesis plz :)
TODO/TOTHINK
============
- Remove '.' command? do it suckless
- Add .! command that runs !foo > file and then .file
- Support for multiple commands in a single line (';' separator)
+55
View File
@@ -0,0 +1,55 @@
IRED stands for the independent raw editor
==========================================
red aims to be a minimalistic reimplementation of the radare shell
without much complexity and relaying all the extensibility to external
applications trying to keep the source as small as possible.
AUTHOR
------
pancake<nopcode.org>
COMMANDS
========
? is for help get help or evaluate numeric expression
/ search search strings or hexpairs
!cmd run command from shell
x hexdump hexdump
X dword dump hexpair dump
> file dump current block to file
< file slurp file into current block
w "string\x00" write string
w 023839400 write hexpairs
b 30 set block size
s addr seek address
r [size|-rmv] get filesize, truncate file to size, or -remove bytes
p [bwWdDqQiIF.] print formatted the current block
q quit
WORK IN PROGRESS
================
print command
b/w/d/q byte, word, dword, qword (little endian)
B/W/D/Q byte, word, dword, qword (big endian)
i/I/f/F int32 (lil, big), float (lil, big)
z/Z zero-terminatted strings (ascii, widechar)
./: skip 1 or 4 chars
* repeat last value until death
PORTABILITY
===========
ired is known to build and run on several OS.
- GNU, Linux, OSX, Windows (mingw), cygwin, Solaris, BSD, ...
TODO:
=====
- support for escapped characters in string write and search ops
- Add support for simple math ops (+,-,*,/) no parenthesis plz :)
TODO/TOTHINK
============
- Remove '.' command? to make it suck less
- Add .! command that runs !foo > file and then .file
- Support for multiple commands in a single line (';' separator)
+13
View File
@@ -0,0 +1,13 @@
* We need a way to work with block based data like the 'wo' cmd in r1
* Implement formatted structs with named arguments in p command
* getcurblock can manage its own memory.. all those free's can be removed
* Find a way to return original value if str2ut64 fails (2nd arg..)
* Add math support to '?' command
* w<- should write from stdin
Commands can:
-1 - fail
0 - quit
1 - run fine
2 - run with issues
+360
View File
@@ -0,0 +1,360 @@
/* bdiff - MIT - Copyright 2010-2013 - pancake */
/* Adapted code from:
bdiff.c - efficient binary diff extension for Mercurial
Copyright 2005, 2006 Matt Mackall <[email protected]>
This software may be used and distributed according to the terms of
the GNU General Public License, incorporated herein by reference.
Based roughly on Python difflib
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
struct line {
int h, len, n, e;
const char *l;
};
struct pos {
int pos, len;
};
struct hunk {
int a1, a2, b1, b2;
};
struct hunklist {
struct hunk *base, *head;
};
static int splitlines(const char *a, int len, struct line **lr) {
int h, i;
const char *p, *b = a;
const char * const plast = a + len - 1;
struct line *l;
/* count the lines */
i = 1; /* extra line for sentinel */
for(p = a; p < a + len; p++)
if(*p == '\n' || p == plast)
i++;
*lr = l = (struct line *)malloc(sizeof(struct line) * i);
if(!l)
return -1;
/* build the line array and calculate hashes */
h = 0;
for(p = a; p < a + len; p++) {
/* Leonid Yuriev's hash */
h = (h * 1664525) + *p + 1013904223;
if(*p == '\n' || p == plast) {
l->h = h;
h = 0;
l->len = p - b + 1;
l->l = b;
l->n = INT_MAX;
l++;
b = p + 1;
}
}
/* set up a sentinel */
l->h = l->len = 0;
l->l = a + len;
return i - 1;
}
static int inline cmp(struct line *a, struct line *b) {
return a->h != b->h || a->len != b->len || memcmp(a->l, b->l, a->len);
}
static int equatelines(struct line *a, int an, struct line *b, int bn) {
int i, j, buckets = 1, t, scale;
struct pos *h = NULL;
/* build a hash table of the next highest power of 2 */
while(buckets < bn + 1)
buckets *= 2;
/* try to allocate a large hash table to avoid collisions */
for(scale = 4; scale; scale /= 2) {
h = (struct pos *)malloc(scale * buckets * sizeof(struct pos));
if(h)
break;
}
if(!h)
return 0;
buckets = buckets * scale - 1;
/* clear the hash table */
for(i = 0; i <= buckets; i++) {
h[i].pos = INT_MAX;
h[i].len = 0;
}
/* add lines to the hash table chains */
for(i = bn - 1; i >= 0; i--) {
/* find the equivalence class */
for(j = b[i].h & buckets; h[j].pos != INT_MAX;
j = (j + 1) & buckets)
if(!cmp(b + i, b + h[j].pos))
break;
/* add to the head of the equivalence class */
b[i].n = h[j].pos;
b[i].e = j;
h[j].pos = i;
h[j].len++; /* keep track of popularity */
}
/* compute popularity threshold */
t = (bn >= 4000) ? bn / 1000 : bn + 1;
/* match items in a to their equivalence class in b */
for(i = 0; i < an; i++) {
/* find the equivalence class */
for(j = a[i].h & buckets; h[j].pos != INT_MAX;
j = (j + 1) & buckets)
if(!cmp(a + i, b + h[j].pos))
break;
a[i].e = j; /* use equivalence class for quick compare */
if(h[j].len <= t)
a[i].n = h[j].pos; /* point to head of match list */
else a[i].n = INT_MAX; /* too popular */
}
/* discard hash tables */
free(h);
return 1;
}
static int longest_match(struct line *a, struct line *b, struct pos *pos,
int a1, int a2, int b1, int b2, int *omi, int *omj) {
int mi = a1, mj = b1, mk = 0, mb = 0, i, j, k;
for(i = a1; i < a2; i++) {
/* skip things before the current block */
for(j = a[i].n; j < b1; j = b[j].n)
;
/* loop through all lines match a[i] in b */
for(; j < b2; j = b[j].n) {
/* does this extend an earlier match? */
if(i > a1 && j > b1 && pos[j - 1].pos == i - 1)
k = pos[j - 1].len + 1;
else k = 1;
pos[j].pos = i;
pos[j].len = k;
/* best match so far? */
if(k > mk) {
mi = i;
mj = j;
mk = k;
}
}
}
if(mk) {
mi = mi - mk + 1;
mj = mj - mk + 1;
}
/* expand match to include neighboring popular lines */
while(mi - mb > a1 && mj - mb > b1 &&
a[mi - mb - 1].e == b[mj - mb - 1].e)
mb++;
while(mi + mk < a2 && mj + mk < b2 &&
a[mi + mk].e == b[mj + mk].e)
mk++;
*omi = mi - mb;
*omj = mj - mb;
return mk + mb;
}
static void recurse(struct line *a, struct line *b, struct pos *pos,
int a1, int a2, int b1, int b2, struct hunklist *l) {
int i, j, k;
/* find the longest match in this chunk */
k = longest_match(a, b, pos, a1, a2, b1, b2, &i, &j);
if(!k)
return;
/* and recurse on the remaining chunks on either side */
recurse(a, b, pos, a1, i, b1, j, l);
l->head->a1 = i;
l->head->a2 = i + k;
l->head->b1 = j;
l->head->b2 = j + k;
l->head++;
recurse(a, b, pos, i + k, a2, j + k, b2, l);
}
static struct hunklist diff(struct line *a, int an, struct line *b, int bn) {
struct hunklist l;
struct hunk *curr;
struct pos *pos;
int t;
/* allocate and fill arrays */
t = equatelines(a, an, b, bn);
pos = (struct pos *)calloc(bn ? bn : 1, sizeof(struct pos));
/* we can't have more matches than lines in the shorter file */
l.head = l.base = (struct hunk *)malloc(sizeof(struct hunk) *
((an<bn ? an:bn) + 1));
if(pos && l.base && t) {
/* generate the matching block list */
recurse(a, b, pos, 0, an, 0, bn, &l);
l.head->a1 = l.head->a2 = an;
l.head->b1 = l.head->b2 = bn;
l.head++;
}
free(pos);
/* normalize the hunk list, try to push each hunk towards the end */
for(curr = l.base; curr != l.head; curr++) {
struct hunk *next = curr+1;
int shift = 0;
if(next == l.head)
break;
if(curr->a2 == next->a1)
while(curr->a2+shift < an && curr->b2+shift < bn
&& !cmp(a+curr->a2+shift, b+curr->b2+shift))
shift++;
else if(curr->b2 == next->b1)
while(curr->b2+shift < bn && curr->a2+shift < an
&& !cmp(b+curr->b2+shift, a+curr->a2+shift))
shift++;
if(!shift)
continue;
curr->b2 += shift;
next->b1 += shift;
curr->a2 += shift;
next->a1 += shift;
}
return l;
}
char *slurp(const char *str, int *usz) {
char *ret;
long sz, n, num = 0;
FILE *fd = fopen(str, "rb");
if(fd == NULL)
return NULL;
fseek(fd, 0, SEEK_END);
sz = ftell(fd);
fseek(fd, 0, SEEK_SET);
ret = (char *)malloc(sz+1);
do {
n = fread(ret, 1, sz, fd);
if(n<1)
break;
num += n;
} while(num < sz);
ret[num] = '\0';
fclose(fd);
if(usz)
*usz = (int)sz;
return ret;
}
int bdiff(const char *filea, const char *fileb) {
char *sa, *sb;
int i, an, bn, offa, rlen, offb, len = 0;
int la, lb, hits = 0;
struct line *al, *bl;
struct hunklist l = { NULL, NULL };
struct hunk *h;
if((sa = slurp(filea, &la)) == NULL)
return fprintf(stderr, "Cannot open %s\n", filea), 0;
if((sb = slurp(fileb, &lb)) == NULL)
return fprintf(stderr, "Cannot open %s\n", fileb), 0;
/* TODO: split to function here */
an = splitlines(sa, la, &al);
bn = splitlines(sb, lb, &bl);
if(!al || !bl)
return -1;
l = diff(al, an, bl, bn);
if(!l.head)
return -1;
la = lb = 0;
for(h = l.base; h != l.head; h++) {
if(h->a1 != la || h->b1 != lb) {
len = bl[h->b1].l - bl[lb].l;
offa = al[la].l - al->l;
offb = al[h->a1].l - al->l;
rlen = offb-offa;
//fprintf(stderr, "all: %d %d\n", );
//fprintf(stderr, "len: %d %d\n", len, rlen);
//fprintf(stderr, "off: %d %d\n", offa, offb);
if(rlen>len)
printf("r-%d@%d\n", (rlen-len), offa);
else printf("r+%d@%d\n", (len-rlen), offb);
if(len == rlen) {
for(i=0; i<len; i++) {
if(bl[lb].l[i] != bl[la].l[i])
fprintf(stderr, "%02x %02x\n",
(unsigned char)
bl[lb].l[i],
(unsigned char)
bl[la].l[i]);
}
// XXX fprintf(stderr, "%02x @ 0x%x\n", bl[la].l[i], offa);
fprintf(stderr, "WARNING: Binary patch failed\n");
}
if(len > 0) {
printf("w ");
for(i=0;i<len;i++)
printf("%02x", (unsigned char)bl[lb].l[i]);
printf("@%d#len\n", offa);
} else
if(rlen > 0) {
printf("w ");
for(i=0; i<rlen; i++)
printf("%02x", (unsigned char)bl[la].l[i]);
printf("@%d#rlen\n", offa);
}
}
la = h->a2;
lb = h->b2;
}
free(al);
free(bl);
free(l.base);
return hits;
}
int main(int argc, const char **argv) {
int ret = 1;
if(argc == 3) {
if(bdiff(argv[1], argv[2]) == -1)
fprintf(stderr, "Out of memory\n");
else ret = 0;
} else fprintf(stderr, "bdiff [file] [file2] > patch.ired\n");
return ret;
}
+346
View File
@@ -0,0 +1,346 @@
/* ported to C by pancake for r2 in 2012-2013 */
// TODO: integrate floating point support
// TODO: do not use global variables
/*
Reference Chapter 6:
"The C++ Programming Language", Special Edition.
Bjarne Stroustrup,Addison-Wesley Pub Co; 3 edition (February 15, 2000)
ISBN: 0201700735
*/
#include <ctype.h>
#include <stdio.h>
#include <unistd.h>
#define R_API
#define R_NUMCALC_STRSZ 4096
typedef struct {
double d;
ut64 n;
} RNumCalcValue;
typedef enum {
RNCNAME, RNCNUMBER, RNCEND, RNCINC, RNCDEC,
RNCPLUS='+', RNCMINUS='-', RNCMUL='*', RNCDIV='/',
//RNCXOR='^', RNCOR='|', RNCAND='&',
RNCPRINT=';', RNCASSIGN='=', RNCLEFTP='(', RNCRIGHTP=')'
} RNumCalcToken;
typedef struct r_num_calc_t {
RNumCalcToken curr_tok;
RNumCalcValue number_value;
char string_value[R_NUMCALC_STRSZ];
int errors;
char oc;
const char *calc_err;
int calc_i;
const char *calc_buf;
int calc_len;
} RNumCalc;
typedef struct r_num_t {
ut64 (*callback)(struct r_num_t *userptr, const char *str, int *ok);
// RNumCallback callback;
ut64 value;
double fvalue;
void *userptr;
RNumCalc nc;
} RNum;
/* accessors */
static inline RNumCalcValue Nset(ut64 v) { RNumCalcValue n; n.d = (double)v; n.n = v; return n; }
static inline RNumCalcValue Nsetf(double v) { RNumCalcValue n; n.d = v; n.n = (ut64)v; return n; }
static inline RNumCalcValue Naddf(RNumCalcValue n, double v) { n.d += v; n.n += (ut64)v; return n; }
static inline RNumCalcValue Naddi(RNumCalcValue n, ut64 v) { n.d += (double)v; n.n += v; return n; }
static inline RNumCalcValue Nsubi(RNumCalcValue n, ut64 v) { n.d -= (double)v; n.n -= v; return n; }
static inline RNumCalcValue Nadd(RNumCalcValue n, RNumCalcValue v) { n.d += v.d; n.n += v.n; return n; }
static inline RNumCalcValue Nsub(RNumCalcValue n, RNumCalcValue v) { n.d -= v.d; n.n -= v.n; return n; }
static inline RNumCalcValue Nmul(RNumCalcValue n, RNumCalcValue v) { n.d *= v.d; n.n *= v.n; return n; }
static inline RNumCalcValue Ndiv(RNumCalcValue n, RNumCalcValue v) {
if (v.d) n.d /= v.d; else n.d = 0;
if (v.n) n.n /= v.n; else n.n = 0;
return n;
}
static RNumCalcValue expr(RNum*, RNumCalc*, int);
static RNumCalcValue term(RNum*, RNumCalc*, int);
static void error(RNum*, RNumCalc*, const char *);
static RNumCalcValue prim(RNum*, RNumCalc*, int);
static RNumCalcToken get_token(RNum*, RNumCalc*);
static void error(RNum *num, RNumCalc *nc, const char *s) {
nc->errors++;
nc->calc_err = s;
//fprintf (stderr, "error: %s\n", s);
}
static RNumCalcValue expr(RNum *num, RNumCalc *nc, int get) {
RNumCalcValue left = term (num, nc, get);
for (;;) {
if (nc->curr_tok == RNCPLUS)
left = Nadd (left, term (num, nc, 1));
else if (nc->curr_tok == RNCMINUS)
left = Nsub (left, term (num, nc, 1));
else break;
}
return left;
}
static RNumCalcValue term(RNum *num, RNumCalc *nc, int get) {
RNumCalcValue left = prim (num, nc, get);
for (;;) {
if (nc->curr_tok == RNCMUL) {
left = Nmul (left, prim (num, nc, 1));
} else
if (nc->curr_tok == RNCDIV) {
RNumCalcValue d = prim (num, nc, 1);
if (!d.d) {
error (num, nc, "divide by 0");
return d;
}
left = Ndiv (left, d);
} else return left;
}
}
static RNumCalcValue prim(RNum *num, RNumCalc *nc, int get) {
char *p;
RNumCalcValue v = {0};
if (get) get_token (num, nc);
switch (nc->curr_tok) {
case RNCNUMBER:
v = nc->number_value;
get_token (num, nc);
return v;
case RNCNAME:
for(p=nc->string_value;*p&&*p==' ';p++) {};
v = Nset (str2ut64 (nc->string_value));
get_token (num, nc);
if (nc->curr_tok == RNCASSIGN)
v = expr (num, nc, 1);
if (nc->curr_tok == RNCINC) Naddi (v, 1);
if (nc->curr_tok == RNCDEC) Nsubi (v, 1);
return v;
case RNCINC: return Naddi (prim (num, nc, 1), 1);
case RNCDEC: return Naddi (prim (num, nc, 1), -1);
case RNCMINUS: return Nsub (v, prim (num, nc, 1));
case RNCLEFTP:
v = expr (num, nc, 1);
if (nc->curr_tok == RNCRIGHTP)
get_token (num, nc);
else error (num, nc, " ')' expected");
case RNCEND:
case RNCPLUS:
case RNCMUL:
case RNCDIV:
case RNCPRINT:
case RNCASSIGN:
case RNCRIGHTP:
return v;
//default: error (num, nc, "primary expected");
}
return v;
}
static void cin_putback (RNum *num, RNumCalc *nc, char c) {
nc->oc = c;
}
R_API const char *r_num_calc_index (RNum *num, const char *p) {
if (num == NULL)
return NULL;
if (p) {
num->nc.calc_buf = p;
num->nc.calc_len = strlen (p);
num->nc.calc_i = 0;
}
//if (num->nc.calc_i>num->nc.calc_len) return NULL;
return num->nc.calc_buf + num->nc.calc_i;
}
static int cin_get(RNumCalc *nc, char *c) {
if (nc->oc) {
*c = nc->oc;
nc->oc = 0;
} else {
if (!nc->calc_buf)
return 0;
//if (nc->calc_i>nc->calc_len) return 0;
*c = nc->calc_buf[nc->calc_i];
if (*c) nc->calc_i++;
else return 0;
}
return 1;
}
static int cin_get_num(RNum *num, RNumCalc *nc, RNumCalcValue *n) {
char c, str[R_NUMCALC_STRSZ];
double d;
int i = 0;
str[0] = 0;
while (cin_get (nc, &c)) {
if (c!=':' && c!='.' && !isalnum (c)) {
cin_putback (num, nc, c);
break;
}
if (i<R_NUMCALC_STRSZ)
str[i++] = c;
}
str[i] = 0;
*n = Nset (str2ut64 (str));
if (*str>='0' && *str<='9' && strchr (str, '.')) {
if (sscanf (str, "%lf", &d)<1)
return 0;
*n = Nsetf (d);
}
#if 0
// XXX: use r_num_get here
if (str[0]=='0' && str[1]=='x') {
ut64 x = 0;
if (sscanf (str+2, "%llx", &x)<1)
return 0;
*n = Nset (x);
} else
if (strchr (str, '.')) {
if (sscanf (str, "%lf", &d)<1)
return 0;
*n = Nsetf (d);
} else {
ut64 u;
if (sscanf (str, "%"PFMT64d, &u)<1)
return 0;
*n = Nset (u);
}
#endif
return 1;
}
static RNumCalcToken get_token(RNum *num, RNumCalc *nc) {
char ch = 0, c = 0;
do { if (!cin_get (nc, &ch)) return nc->curr_tok = RNCEND;
} while (ch!='\n' && isspace (ch));
switch (ch) {
case 0:
case ';':
case '\n':
return nc->curr_tok = RNCEND;
case '+': // added for ++name and name++
if (cin_get (nc, &c) && c == '+')
return nc->curr_tok = RNCINC;
cin_putback (num, nc, c);
return nc->curr_tok = (RNumCalcToken) ch;
case '-':
if (cin_get (nc, &c) && c == '-')
return nc->curr_tok = RNCDEC;
cin_putback (num, nc, c);
return nc->curr_tok = (RNumCalcToken) ch;
case '*':
case '/':
case '(':
case ')':
case '=':
return nc->curr_tok = (RNumCalcToken) ch;
case '0':case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
case '.':
cin_putback (num, nc, ch);
if (!cin_get_num (num, nc, &nc->number_value)) {
error (num, nc, "invalid number conversion");
return 1;
}
return nc->curr_tok = RNCNUMBER;
default:
#define isvalidchar(x) \
(isalnum(x) || x==':' || x=='$' || x=='.' || x=='_' || x=='?' || x=='\\' \
|| x==' ' || x=='[' || x==']' || x=='}' || x=='{' || x=='/' || (x>='0'&&x<='9'))
{
int i = 0;
nc->string_value[i++] = ch;
if (ch == '[') {
while (cin_get (nc, &ch) && ch!=']') {
if (i>=R_NUMCALC_STRSZ) {
error (num, nc, "string too long");
return 0;
}
nc->string_value[i++] = ch;
}
nc->string_value[i++] = ch;
} else {
while (cin_get (nc, &ch) && isvalidchar (ch)) {
if (i>=R_NUMCALC_STRSZ) {
error (num, nc, "string too long");
return 0;
}
nc->string_value[i++] = ch;
}
}
nc->string_value[i] = 0;
cin_putback (num, nc, ch);
return nc->curr_tok = RNCNAME;
}
//}
error (num, nc, "bad token");
return nc->curr_tok = RNCPRINT;
}
}
static void load_token(RNum *num, RNumCalc *nc, const char *s) {
nc->calc_i = 0;
nc->calc_len = 0;
nc->calc_buf = s;
nc->calc_err = NULL;
}
R_API ut64 r_num_calc (RNum *num, const char *str, const char **err) {
RNumCalcValue n;
RNumCalc *nc, nc_local;
if (!str || !*str)
return 0LL;
if (num == NULL)
nc = &nc_local;
else nc = &num->nc;
/* init */
nc->curr_tok = RNCPRINT;
nc->number_value.d = 0.0;
nc->number_value.n = 0LL;
nc->errors = 0;
nc->oc = 0;
nc->calc_err = NULL;
nc->calc_i = 0;
nc->calc_len = 0;
nc->calc_buf = NULL;
load_token (num, nc, str);
get_token (num, nc);
n = expr (num, nc, 0);
if (err) *err = nc->calc_err;
//if (nc->curr_tok == RNCEND) return 0LL; // XXX: Error
//if (nc->curr_tok == RNCPRINT) //return 0LL; // XXX: the fuck
// n = expr (num, nc, 0);
if (n.d != ((double)(ut64)n.d)) {
if (num) num->fvalue = n.d;
} else if (num) num->fvalue = (double)n.n;
return n.n;
}
#if 0
int main(int argc, char* argv[]) {
RNumCalcValue n;
RNumCalc nc;
while (!feof (stdin)) {
get_token (nc);
if (nc.curr_tok == RNCEND) break;
if (nc.curr_tok == RNCPRINT) continue;
n = expr (num, nc, 0);
if (n.d == ((double)(int)n.d))
printf ("%llx\n", n.n);
else printf ("%lf\n", n.d);
}
return nc->errors;
}
#endif
+183 -119
View File
@@ -1,20 +1,22 @@
/* Copyleft 2009 -- pancake /at/ nopcode /dot/ org */
/* Copyleft 2009-2013 -- pancake /at/ nopcode /dot/ org */
static void cmd_hexdump(char *arg) {
unsigned int len = bsize;
unsigned char *buf = getcurblk(arg, &len);
if (buf) {
static int cmd_hexdump(char *arg) {
int len = bsize;
ut8 *buf = getcurblk(arg, &len);
if(buf && len>0) {
hexdump(buf, len, 16);
free(buf);
return 1;
}
return 2;
}
static void cmd_print(char *arg) {
unsigned char *buf;
unsigned int len = bsize;
if (*arg) {
static int cmd_print(char *arg) {
ut8 *buf;
int len = bsize;
if(*arg) {
buf = getcurblk(arg, &len);
if (!buf) return;
if(!buf) return 2;
print_fmt(buf, arg, len);
free(buf);
} else printf(
@@ -23,167 +25,229 @@ static void cmd_print(char *arg) {
"s/S short int16 (lil, big)\n"
"z/Z zero-terminatted string (ascii, wide-ascii)\n"
"./:/* skip 1 or 4 chars, repeat last format instead of cycle\n");
return 1;
}
static void cmd_bytedump(char *arg) {
unsigned int i, len = bsize;
unsigned char *buf = getcurblk(arg, &len);
if (!buf) return;
static int cmd_bytedump(const char *arg) {
int i, len = bsize;
ut8 *buf = getcurblk(arg, &len);
if(!buf) return 2;
for(i=0;i<len;i++)
printf("%02x", buf[i]);
printf("\n");
free(buf);
return 1;
}
void cmd_search(char *arg) {
unsigned char *buf;
unsigned int i, len, hit=0;
arg = skipspaces(arg);
if (*arg=='"') {
static int cmd_search(const char *arg) {
ut8 *buf, *barg;
size_t len;
int i, hit = 0;
SKIPSPACES(arg);
if(*arg=='"') {
arg++;
len = strlen(arg)-1;
arg[len]='\0';
} else len = hexstr2raw(arg);
if ((buf = getcurblk("", &bsize)))
barg = (ut8*)strdup(arg);
len = strlen((const char *)barg)-1;
// TODO: ensure last char is '"'
barg[len]='\0';
} else {
barg = (ut8*)strdup(arg);
len = hexstr2raw(barg);
}
if((buf = getcurblk("", &bsize)))
do {
for(i=0;i<bsize;i++) {
if (arg[hit++]!=buf[i]) hit = 0;
else if (hit == len)
if(barg[hit++]!=buf[i]) hit = 0;
else if(hit == len)
printf("0x%"LLF"x\n", curseek+i-len+1);
}
curseek += bsize;
} while(io_read(buf, bsize)>0);
free(buf);
free(barg);
return 1;
}
static void cmd_bsize(char *arg) {
if (!*arg) printf("%d\n", bsize);
else if (*arg=='+') bsize += (int)str2ut64(arg+1);
else if (*arg=='-') bsize -= (int)str2ut64(arg+1);
static int cmd_bsize(char *arg) {
if(!*arg) printf("%d\n", bsize);
else if(*arg=='+') bsize += (int)str2ut64(arg+1);
else if(*arg=='-') bsize -= (int)str2ut64(arg+1);
else bsize = str2ut64(arg);
if (bsize<1) bsize = 1;
if(bsize<1) bsize = 1;
obsize = bsize;
return 1;
}
static void cmd_seek(char *arg) {
if (!*arg) printf("%"LLF"d\n", curseek);
else if (*arg=='+') curseek += str2ut64(arg+1);
else if (*arg=='-') curseek -= str2ut64(arg+1);
static int cmd_seek(char *arg) {
if(!*arg) printf("%"LLF"d\n", curseek);
else if(*arg=='+') curseek += str2ut64(arg+1);
else if(*arg=='-') curseek -= str2ut64(arg+1);
else curseek = str2ut64(arg);
oldseek = curseek;
io_seek((oldseek=curseek), 0);
return 1;
}
static void cmd_dump(char *file) {
unsigned int len = bsize;
void *buf = getcurblk("", &len);
FILE *fd = fopen(file, "wb");
if (fwrite(buf, len, 1, fd)<len)
perror("fwrite");
fclose(fd);
free(buf);
static int cmd_dump(char *file) {
int len = bsize;
ut8 *buf = getcurblk("", &len);
if(len<1 || buf) {
FILE *fd = fopen(file, "wb");
if (!fd) {
free (buf);
return -1;
}
if(fwrite(buf, len, 1, fd)<len) {
perror("fwrite");
return -1;
}
fclose(fd);
free(buf);
} else perror("getcurblk");
return 1;
}
static void cmd_load(char *file) {
int len;
void *buf;
static int cmd_load(char *file) {
FILE *fd = fopen(file, "rb");
if (!fd) return;
buf = malloc(bsize);
if (!buf) return;
len = fread(buf, 1, bsize, fd);
if (len<bsize)
perror("fread");
if (io_write(buf, len)<len)
perror("io_write");
fclose(fd);
free(buf);
if(fd) {
void *buf = malloc(bsize);
if(bsize>0 && buf) {
int len = fread(buf, 1, bsize, fd);
if(len<bsize)
perror("fread");
io_seek (curseek, SEEK_SET);
if(io_write(buf, len)<len) {
perror("io_write");
return -1;
}
} else perror("malloc");
free(buf);
fclose(fd);
} else perror("fopen");
return 1;
}
static void cmd_write(char *arg) {
unsigned int len;
arg = skipspaces(arg);
if (*arg=='"') {
arg++;
len = strlen(arg)-1;
arg[len]='\0';
} else len = hexstr2raw(arg);
static int cmd_write(const char *arg) {
ut8 *barg;
int len;
SKIPSPACES(arg);
if(*arg=='"') {
barg = (ut8*)strdup (arg+1);
len = strlen(++arg)-1;
// TODO: ensure last char is "
barg[len] = '\0';
} else {
barg = (ut8*)strdup (arg);
len = hexstr2raw(barg);
}
if (len<2) {
printf ("Invalid hexpair\n");
return 2;
}
io_seek(curseek, SEEK_SET);
if (io_write(arg, len)<len)
if(len<1 || io_write(barg, len)<len) {
perror("io_write");
return -1;
}
//free ((void*)arg);
return 1;
}
static void cmd_help(char *arg) {
if (*arg) {
ut64 ret = str2ut64(arg);
static int cmd_help(char *arg) {
if(*arg) {
ut64 ret = r_num_calc (NULL, arg, NULL);
printf("0x%"LLF"x %"LLF"d 0%"LLF"o\n", ret, ret, ret);
} else printf(
"s[+-addr] seek to relative or absolute address\n"
"b[+-size] change block size\n"
"w[hex|\"str\"] write hexpair or string\n"
"/[hex|\"str\"] search hexpair or string\n"
"x[size] hexdump\n"
"X[size] hexpair dump\n"
"p[fmt] print formatted current block ('p' for help)\n"
"r[-[num]] truncate or -remove N bytes\n"
".[file] interpret file\n"
"<[file] load file in current seek\n"
">[file] dump current block to file\n"
"!cmd run shell command\n"
"?expr calculate numeric expression\n"
"q quit\n");
"s[+-addr] seek to relative or absolute address\n"
"b[+-size] change block size\n"
"w[hex|\"str\"] write hexpair or string\n"
"/[hex|\"str\"] search hexpair or string\n"
"x[size] hexdump\n"
"X[size] hexpair dump\n"
"p[fmt] print formatted current block ('p' for help)\n"
"d[size] disasemble\n"
"r[+-[num]] truncate or -remove N bytes\n"
".[file] interpret file\n"
"<[file] load file in current seek\n"
">[file] dump current block to file\n"
"!cmd run shell command\n"
"?expr calculate numeric expression\n"
"q quit\n");
return 1;
}
static void cmd_resize(char *arg) {
unsigned int len;
int ret = 0;
if (!*arg) printf("%"LLF"d\n", (long long int)io_seek(0, SEEK_END));
else if (*arg=='-') {
ut8 *buf = malloc(bsize);
if (buf) {
ut64 i, n = str2ut64(arg+1);
for(i=0;;i+=len) {
static int cmd_resize(char *arg) {
ut8 *buf;
ut64 tail, n;
int i, len, ret = 0;
switch(*arg) {
case '\0':
printf("%"LLF"d\n", (ut64)io_seek(0, SEEK_END));
break;
case '+': // XXX: needs cleanup
n = str2ut64(arg+1);
len = (ut64)io_seek(0, SEEK_END);
tail = len-curseek;
if((buf=malloc(tail))) { // XXX: Use block
io_seek(curseek, SEEK_SET);
io_read(buf, tail);
io_seek(curseek+n, SEEK_SET);
io_write(buf, tail);
free (buf);
} else perror("malloc");
break;
case '-':
buf = malloc(bsize);
if(buf) {
n = str2ut64(arg+1);
for(i=0;!ret;i+=len) {
io_seek(curseek+n+i, SEEK_SET);
len = io_read(buf, bsize);
if (len<1) break;
io_seek(curseek+i, SEEK_SET);
if (io_write(buf, len)<len)
perror("io_write");
if((len = io_read(buf, bsize))>0) {
io_seek(curseek+i, SEEK_SET);
if(io_write(buf, len)<len)
perror("io_write"),ret=-1;
} else break; //perror("io_read"), ret=-1;
}
free(buf);
ret = io_truncate(io_seek(0, SEEK_END)-n);
}
} else ret = io_truncate(str2ut64(arg));
if (ret<0)
perror("truncate");
if((ret = io_seek(0, SEEK_END))>n)
ret = io_truncate(ret-n);
} else perror("malloc");
break;
default:
ret = io_truncate(str2ut64(arg));
}
if(ret<0) perror("truncate");
return 1;
}
static void cmd_system(char *arg) {
unsigned int len = bsize;
char *buf = NULL, str[64];
if (strstr(arg, "BLOCK")) {
FILE *fd = fopen(".curblk", "w");
if (fd) {
buf = getcurblk("", &len);
if (buf) {
static int cmd_system(char *arg) {
int len = bsize;
char str[1024];
ut8 *buf;
if(strstr(arg, "BLOCK")) {
FILE *fd = fopen(".curblk", "wb");
if(fd) {
if((buf = getcurblk("", &len))) {
setenv("BLOCK", ".curblk", 1);
if (fwrite(buf, len, 1, fd)<len)
perror("fwrite");
fclose(fd);
fwrite(buf, len, 1, fd);
free(buf);
buf = NULL;
}
fclose(fd);
}
}
if (strstr(arg, "OFFSET")) {
if(strstr(arg, "BSIZE")) {
sprintf(str, "%d", len);
setenv("BSIZE", str, 1);
}
if(strstr(arg, "OFFSET")) {
sprintf(str, "%"LLF"d", curseek);
setenv("OFFSET", str, 1); // XXX
setenv("OFFSET", str, 1);
}
if (strstr(arg, "XOFFSET")) {
if(strstr(arg, "XOFFSET")) {
sprintf(str, "0x%"LLF"x", curseek);
setenv("XOFFSET", str, 1); // XXX
setenv("XOFFSET", str, 1);
}
if (io_system(arg)<0)
if(io_system(arg)<0)
perror("system");
unlink(".curblk");
free(buf);
return 1;
}
+20
View File
@@ -0,0 +1,20 @@
#include <unistd.h>
int main() {
char next=0, ch, och=0;
while (read (0, &ch, 1)==1) {
if (next) {
if (ch==next)
next = 0;
continue;
}
if (och == ' ' && ch==' ')
next = '\n';
if (och == '0' && ch=='x')
next = ':';
if (!next && ch!=' ')
write (1, &ch, 1);
och = ch;
}
return 0;
}
+30 -8
View File
@@ -1,24 +1,44 @@
/* Copyleft 2009 -- pancake /at/ nopcode /dot/ org */
#include <sys/types.h>
#include <unistd.h>
#define DEMO 0
#if DEMO
int bo = 0;
char b[4096];
static inline int io_open(char *file) {
memset (b, 0, sizeof (b));
return 10;
}
static int io_read(void *x,int y) {
memcpy (x, b+bo, y);
return y;
}
#define io_write(x,y) memcpy (b+bo, x,y)
static int io_seek (int x,int y) {
bo=((y==2)?sizeof(b):(y==1)?bo+x:x);
return bo;
}
#define io_close() printf("close: TODO\n")
#define io_system(x) system(x)
#define io_truncate(x) printf("truncate: TODO\n");
#else
#if __WIN32__
#include <windows.h>
static HANDLE _fd = NULL;
#define setenv(x,y,z) SetEnvironmentVariable(x, y)
static inline int io_open(char *file) {
_fd = CreateFile(file, GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ|FILE_SHARE_WRITE,
NULL, OPEN_ALWAYS, 0, NULL);
if (_fd == INVALID_HANDLE_VALUE)
if(_fd == INVALID_HANDLE_VALUE)
_fd = CreateFile(file, GENERIC_READ, FILE_SHARE_READ,
NULL, OPEN_ALWAYS, 0, NULL);
return (_fd==INVALID_HANDLE_VALUE)?-1:0;
}
static int io_read(void *x, int y) {
static inline int io_read(void *x, int y) {
DWORD ret;
return ReadFile(_fd,x,y,&ret,NULL)?ret:-1;
return ReadFile(_fd, x, y, &ret, NULL)?ret:-1;
}
#define setenv(x,y,z) SetEnvironmentVariable(x, y)
#define io_write(x,y) WriteFile(_fd, x, y, NULL, NULL)
#define io_seek(x,y) SetFilePointer(_fd,x,0,!y?FILE_BEGIN:y==1?FILE_CURRENT:FILE_END)
#define io_close() CloseHandle(_fd)
@@ -33,7 +53,7 @@ static int io_read(void *x, int y) {
static int _fd = -1;
static inline int io_open(char *file) {
_fd = open(file, O_RDWR|O_CREAT, 0644);
if (_fd == -1) _fd = open(file, O_RDONLY);
if(_fd == -1) _fd = open(file, O_RDONLY);
return _fd;
}
#define io_read(x,y) read(_fd, x, y)
@@ -41,5 +61,7 @@ static inline int io_open(char *file) {
#define io_seek(x,y) lseek(_fd, x, y)
#define io_close() close(_fd)
#define io_system(x) system(x)
#define io_truncate(x) ftruncate(_fd,(unsigned long)x)
#define io_truncate(x) ftruncate(_fd, (unsigned long)x)
#endif
#endif
+10 -2
View File
@@ -1,4 +1,4 @@
.Dd Sep 1, 2009
.Dd Oct 7, 2009
.Dt IRED 1
.Os
.Th IRED 1
@@ -95,7 +95,15 @@ dump current block to file
.It !cmd
run shell command
.Pp
> !cp $BLOCK $FILE.curblock # save current block
The following environment variables are defined when found in the command string:
.Pp
FILE is the filename of the current working file
.Pp
BLOCK points to the temporal filename with the current block dump
.Pp
OFFSET and XOFFSET are decimal and hexadecimal values of the current seek
.Pp
> !cp $BLOCK $FILE-$XOFFSET.curblock # save current block
.It ?expr
calculate numeric expression
.Pp
+95 -63
View File
@@ -1,122 +1,154 @@
/* Copyleft 2009 -- pancake /at/ nopcode /dot/ org */
/* Copyleft 2009-2013 -- pancake /at/ nopcode /dot/ org */
#define ut64 unsigned long long
#define ut8 unsigned char
static int earlyquit = 0;
static int verbose = 1;
static char *script = 0;
static int scriptn = 0;
static const char **scripts = 0;
static int cmdn = 0;
static char **cmds = 0;
static ut64 oldseek, curseek = 0LL;
static unsigned int obsize, bsize = 256;
static int obsize, bsize = 256;
static int red_cmd(char *cmd); // XXX : recursive depenency
#define BUFSZ 128*1024
#include "red.h"
#include "ired.h"
#include "util.c"
#include "calc.c"
#include "cmd.c"
int red_slurpin() {
int len;
unsigned char buf[4096];
static void red_slurpin() {
ut8 buf[BUFSZ];
for(;;) {
len = read(0, buf, 4096);
if (len<1) break;
int len = read(0, buf, sizeof(buf));
if(len<1) break;
hexdump(buf, len, 16);
curseek += len;
}
return 0;
}
static char *red_interpret(char *file) {
char buf[1024];
static int red_interpret(const char *file) {
char buf[BUFSZ];
FILE *fd = fopen(file, "r");
if (fd != NULL) {
file = NULL;
if(fd != NULL) {
for(;;) {
if (fgets(buf, 1023, fd) == NULL)
if(fgets(buf, sizeof(buf), fd) == NULL)
break;
red_cmd(buf);
}
fclose(fd);
} else fprintf(stderr, "Cannot open script file '%s'\n", file);
return file;
} else if (file)
fprintf(stderr, "Cannot open script file '%s'\n", file);
return 1;
}
static int red_cmd(char *cmd) {
char *arg = cmd+1;
SKIPSPACES(arg);
switch(*cmd) {
case ';': case '#': break; // comment
case 'q': return 0;
case '>': cmd_dump(cmd+1); break;
case '<': cmd_load(cmd+1); break;
case '.': red_interpret(skipspaces(cmd+1)); break;
case 's': cmd_seek(cmd+1); break;
case 'b': cmd_bsize(cmd+1); break;
case '/': cmd_search(cmd+1); break;
case 'p': cmd_print(cmd+1); break;
case 'r': cmd_resize(cmd+1); break;
case 'x': cmd_hexdump(cmd+1); break;
case 'X': cmd_bytedump(cmd+1); break;
case 'w': cmd_write(cmd+1); break;
case '!': cmd_system(cmd+1); break;
case '?': cmd_help(cmd+1); break;
case ';': case '#': break; // comment
case '>': return cmd_dump(arg); break;
case '<': return cmd_load(arg); break;
case '.': return red_interpret(arg); break;
case 's': return cmd_seek(arg); break;
case 'b': return cmd_bsize(arg); break;
case '/': return cmd_search(arg); break;
case 'd': return cmd_system ("echo X | ired -n $BLOCK | rasm2 -o $OFFSET -D - |head -n $(($LINES-1))");
case 'p': return cmd_print(arg); break;
case 'r': return cmd_resize(arg); break;
case 'x': return cmd_hexdump(arg); break;
case 'X': return cmd_bytedump(arg); break;
case 'w': return cmd_write(arg); break;
case '!': return cmd_system(arg); break;
case 'V': return cmd_system("vired $FILE"); break;
case '?': return cmd_help(arg); break;
default: fprintf(stderr, "? %s\n", cmd);
}
return 1;
}
static int red_prompt() {
char *at, *at2, line[4096];
if (verbose) {
char *at, *at2, line[BUFSZ];
if(verbose) {
printf("[0x%08"LLF"x]> ", curseek);
fflush(stdout);
}
if (fgets(line, 4095, stdin) == NULL)
if(fgets(line, sizeof(line), stdin) == NULL)
return 0;
line[strlen(line)-1] = 0;
if (line[0] != '!') {
line[strlen(line)-1] = '\0';
if(*line != '!') {
at = strchr(line, '@');
oldseek = curseek;
obsize = bsize;
if (at) {
*at = 0; at++;
at2 = strchr(at, ':');
if (at2) {
if(at) {
*at = 0;
at2 = strchr(++at, ':');
if(at2) {
*at2 = 0; at2++;
if (*at2) bsize = (int)str2ut64(at2);
if(*at2) bsize = (int)str2ut64(at2);
}
if (*at) curseek = str2ut64(at);
if(*at) curseek = str2ut64(at);
}
}
return red_cmd(skipspaces(line));
at = line;
SKIPSPACES(at);
return red_cmd(at);
}
static void red_open(char *file) {
oldseek = 0;
setenv("FILE", file, 1);
if (io_open(file) != -1) {
if (script)
script = red_interpret(script);
while(red_prompt()) {
static int red_open(char *file) {
int ret = io_open(file);
if(ret != -1) {
oldseek = 0;
setenv("FILE", file, 1);
if(scripts)
for (ret=0;ret<scriptn;ret++)
red_interpret(scripts[ret]);
if(cmds)
for (ret=0;ret<cmdn;ret++)
red_cmd(cmds[ret]);
if(earlyquit)
return 0;
while((ret=red_prompt())>0) {
curseek = oldseek;
bsize = obsize;
}
io_close();
} else fprintf(stderr, "Cannot open '%s'\n", file);
} else if (file)
fprintf(stderr, "Cannot open '%s'\n", file);
return ret==-1 ?1:0;
}
static int red_help() {
puts("ired [-hnv] [-i script] [file] [..]");
puts("ired [-qhnv] [-c cmd] [-i script] [-|file ..]");
return 0;
}
int main(int argc, char **argv) {
int i;
if (argc>1)
for(i=1;i<argc;i++) {
if (argv[i][0]=='-')
int i, ret = 1;
argc++;
cmdn = 0;
scriptn = 0;
scripts = malloc(sizeof(const char*)*argc);
cmds = malloc(sizeof(const char*)*argc);
if(argc>1 && argv[1])
for(i=1; i<argc; i++) {
if(argv[i] && argv[i][0]=='-')
switch(argv[i][1]) {
case 'i': script = argv[++i]; break;
case 'q': earlyquit = 1; break;
case 'i': scripts[scriptn++] = argv[++i]; break;
case 'c': cmds[cmdn++] = argv[++i]; break;
case 'n': verbose = 0; break;
case 'v': puts("red "VERSION" 2009"); return 0;
case 'h': return red_help();
case 0x0: return red_slurpin();
} else red_open(argv[i]);
} else return red_help();
return 0;
case 'v': puts(VERSION); ret = 0; break;
case 'h': ret = red_help(); break;
case 0x0: red_slurpin(); ret = 0; break;
} else {
if (!argv[i]) break;
ret = red_open(argv[i]);
}
} else ret = red_help();
free(scripts);
return ret;
}
+7 -8
View File
@@ -1,23 +1,22 @@
#define VERSION "0.3"
#define VERSION "0.6"
#include <unistd.h>
#include <sys/types.h>
#include "io.c"
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <stdlib.h>
#define SKIPSPACES(x) for(;*(x)==' '||*(x)=='\t';x++) {};
#if(plan9)
static int setenv(char *var, char *val, int force) {
char str[128];
char str[256];
snprintf(str, sizeof(str), "echo %s > /env/%s", var, val);
if (system(str)<0)
perror("system");
return force;
return system(str);
}
#define LLF "L"
#else
#define LLF "ll"
#endif
#include "util.c"
#include "cmd.c"
+5
View File
@@ -0,0 +1,5 @@
all:
sh test.sh
clean:
rm -f tmp tmp.ired
+5
View File
@@ -0,0 +1,5 @@
Hello world
soor
loop
is fucking awesome
and new as shit
+5
View File
@@ -0,0 +1,5 @@
Hello world
loop
soor
is fucking awesome
and new as shit
+4
View File
@@ -0,0 +1,4 @@
Hello world
sardina
is fucking awesome
and new as shit
+3
View File
@@ -0,0 +1,3 @@
Hello world
is fucking awesome
and new as shit
Executable
+53
View File
@@ -0,0 +1,53 @@
#!/bin/sh
FILES=4
jot 1 >/dev/null
if [ $? = 0 ]; then
SEQ=`jot $FILES 1 $FILES`
else
md5=`seq 1 $FILES`
fi
md5sum -h 2>/dev/null
if [ $? = 0 ]; then
md5=md5sum
else
md5=md5
fi
function hash {
$md5 $1 | awk '{print $1}'
}
function btest {
cp $1 tmp
../bdiff $1 $2 > tmp.ired
../ired -n tmp < tmp.ired
test `hash tmp` = `hash $2`
ret=$?
echo $ret $1 $2
if [ $ret = 1 ]; then
if [ -n "`echo $1| grep file`" ]; then
diff -u $2 tmp
fi
fi
#/ rm -f tmp.ired tmp
}
(cd .. && make -s)
if [ -n "$2" ]; then
btest $1 $2
else
for i in $SEQ ; do
for j in $SEQ ; do
btest file$i file$j
done
done
fi
#btest /etc/services /etc/fstab
#btest /bin/true /bin/false
#radiff /bin/false tmp
+51 -61
View File
@@ -1,105 +1,95 @@
/* Copyleft 2009 -- pancake /at/ nopcode /dot/ org */
/* ired - Copyleft 2009-2013 -- pancake */
#include <ctype.h>
static inline char *skipspaces(char *arg) {
while (*arg==' '||*arg=='\t') arg++;
return arg;
}
static inline void hexdump(const ut8 *buf, unsigned int len, int w) {
unsigned int i, j;
for(i=0;i<len;i+=w) {
printf("0x%08" LLF "x ", curseek+i);
printf("0x%08"LLF"x: ", curseek+i);
for(j=i;j<i+w;j++) {
if (j>=len) {
printf(j%2?" ":" ");
continue;
}
printf("%02x", buf[j]);
if (j%2) printf(" ");
}
for(j=i;j<i+w;j++) {
if (j>=len) printf(" ");
else printf("%c", isprint(buf[j])?buf[j]:'.');
if(j<len) printf(j%2?"%02x ":"%02x", buf[j]);
else printf(j%2?" ":" ");
}
printf(" ");
for(j=i;j<i+w;j++)
printf("%c", isprint(buf[j])?buf[j]:'.');
printf("\n");
}
}
static void print_fmt(const ut8 *buf, char *fmt, unsigned int len) {
unsigned int i, inc=0, lup=0, up, rep = 0;
unsigned int i, up, inc = 0, lup = 0, rep = 0;
char *ofmt = fmt;
do { /* TODO: needs cleanup */
for(;(*fmt||rep);fmt++) {
up = rep?rep:*fmt;
switch(up) {
case 'i': if (len>3) printf("%d\n", ((buf[0]<<24) | (buf[1]<<16) | (buf[2]<<8) | buf[3])); inc=4; break;
case 'I': if (len>3) printf("%d\n", ((buf[3]<<24) | (buf[2]<<16) | (buf[1]<<8) | buf[0])); inc=4; break;
case 's': if (len>1) printf("%d\n", (buf[0]<<8 | buf[1])); inc=2; break;
case 'S': if (len>1) printf("%d\n", (buf[1]<<8 | buf[0])); inc=2; break;
case 'o': if (len>0) printf("0%o\n", buf[0]); inc=1; break;
case 'b': if (len>0) printf("0x%02x\n", buf[0]); inc=1; break;
case 'w': if (len>1) printf("0x%02x%02x\n", buf[1], buf[0]); inc=2; break;
case 'W': if (len>1) printf("0x%02x%02x\n", buf[0], buf[1]); inc=2; break;
case 'd': if (len>3) printf("0x%02x%02x%02x%02x\n",buf[3], buf[2], buf[1], buf[0]); inc=4; break;
case 'D': if (len>3) printf("0x%02x%02x%02x%02x\n", buf[0], buf[1], buf[2], buf[3]); inc=4; break;
case 'q': if (len>7) printf("0x%02x%02x%02x%02x%02x%02x%02x%02x\n",
case 'i': if(len>3) printf("%d\n", ((buf[0]<<24) | (buf[1]<<16) | (buf[2]<<8) | buf[3])); inc=4; break;
case 'I': if(len>3) printf("%d\n", ((buf[3]<<24) | (buf[2]<<16) | (buf[1]<<8) | buf[0])); inc=4; break;
case 's': if(len>1) printf("%d\n", (buf[0]<<8 | buf[1])); inc=2; break;
case 'S': if(len>1) printf("%d\n", (buf[1]<<8 | buf[0])); inc=2; break;
case 'o': if(len>0) printf("0%o\n", buf[0]); inc=1; break;
case 'b': if(len>0) printf("0x%02x\n", buf[0]); inc=1; break;
case 'w': if(len>1) printf("0x%02x%02x\n", buf[1], buf[0]); inc=2; break;
case 'W': if(len>1) printf("0x%02x%02x\n", buf[0], buf[1]); inc=2; break;
case 'd': if(len>3) printf("0x%02x%02x%02x%02x\n",buf[3], buf[2], buf[1], buf[0]); inc=4; break;
case 'D': if(len>3) printf("0x%02x%02x%02x%02x\n", buf[0], buf[1], buf[2], buf[3]); inc=4; break;
case 'q': if(len>7) printf("0x%02x%02x%02x%02x%02x%02x%02x%02x\n",
buf[7], buf[6], buf[5], buf[4], buf[3], buf[2], buf[1], buf[0]); inc=8; break;
case 'Q': if (len>7) printf("0x%02x%02x%02x%02x%02x%02x%02x%02x\n",
case 'Q': if(len>7) printf("0x%02x%02x%02x%02x%02x%02x%02x%02x\n",
buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7]); inc=8; break;
case '.': inc=1; break;
case ':': inc=4; break;
case 'z': for(i=0; inc<len && isascii(buf[0]);i++) { printf("%c", buf[0]); buf++; inc++; } if(i)printf("\n"); break;
case 'Z': for(i=0; inc<len && isascii(buf[0]);i++) { printf("%c", buf[0]); buf+=2; inc+=2; } if(i)printf("\n"); break;
case 'z': for(i=0; inc<len && isascii(buf[0]);i++) { printf(i?"%c\n":"%c", buf[0]); buf++; } inc++; break;
case 'Z': for(i=0; inc<len && isascii(buf[0]);i++) { printf(i?"%c\n":"%c", buf[0]); buf+=2; } inc+=2; break;
case '*': rep = lup; break;
default: fprintf(stderr, "Unknown format '%c' (%d)\n", up, up);
return;
}
if (!rep) lup = up;
if(!rep) lup = up;
buf += inc;
if (inc>len) break;
if(inc>len) break;
len -= inc;
}
fmt = ofmt;
} while(!rep && inc && inc <len);
} while(!rep && inc && inc<len);
}
static ut64 str2ut64(char *str) {
static ut64 str2ut64(const char *str) {
ut64 ret = 0LL;
str = skipspaces(str);
if (str[0]=='b'&&str[1]==0)
SKIPSPACES(str);
if(str[0]=='b'&&str[1]=='\0')
ret = bsize;
else if (str[0]=='0') {
if (str[1]=='x') sscanf(str, "0x%"LLF"x", &ret);
else if(str[0]=='0') {
if(str[1]=='x') sscanf(str, "0x%"LLF"x", &ret);
else sscanf(str, "0x%"LLF"o", &ret);
} else sscanf(str, "%"LLF"u", &ret);
str+=strlen(str)-1;
if (*str=='K') ret *= 1024;
else if (*str=='M') ret *= 1024*1024;
else if (*str=='G') ret *= 1024*1024*1024;
str += strlen(str)-1;
if(*str=='K') ret *= 1024;
else if(*str=='M') ret *= 1024*1024;
else if(*str=='G') ret *= 1024*1024*1024;
return ret;
}
static int hex2byte(ut8 *val, ut8 c) {
if ('0' <= c && c <= '9') *val = (ut8)(*val) * 16 + ( c - '0');
else if (c >= 'A' && c <= 'F') *val = (ut8)(*val) * 16 + ( c - 'A' + 10);
else if (c >= 'a' && c <= 'f') *val = (ut8)(*val) * 16 + ( c - 'a' + 10);
if('0' <= c && c <= '9') *val = (ut8)(*val) * 16 + ( c - '0');
else if(c >= 'A' && c <= 'F') *val = (ut8)(*val) * 16 + ( c - 'A' + 10);
else if(c >= 'a' && c <= 'f') *val = (ut8)(*val) * 16 + ( c - 'a' + 10);
else return 1;
return 0;
}
static int hexstr2raw(char *arg) {
ut8 *ptr, c = 0, d;
static unsigned int hexstr2raw(ut8 *arg) {
ut8 *ptr, d, c = 0;
unsigned int j = 0, len = 0;
for (ptr=(ut8 *)arg;*ptr;ptr++) {
if (*ptr==' ') continue;
for(ptr=(ut8 *)arg; *ptr; ptr++) {
if(*ptr==' ') continue;
d = c;
if (hex2byte(&c, *ptr))
if(hex2byte(&c, *ptr))
return -1;
c |= d;
if (!j++) c <<= 4;
else if (j==2) {
if(!j++) c <<= 4;
else if(j==2) {
arg[len++] = c;
c = j = 0;
}
@@ -107,14 +97,14 @@ static int hexstr2raw(char *arg) {
return len;
}
static void *getcurblk(char *arg, unsigned int *len) {
void *buf;
if (*arg) {
*len = (int)str2ut64(arg);
if (*len <1) *len = bsize;
static ut8 *getcurblk(const char *arg, int *len) {
ut8 *buf = NULL;
if(*arg) {
*len = (int)str2ut64((const char *)arg);
if(*len<1) *len = bsize;
}
if ((buf = malloc(*len)) != NULL) {
if (io_seek((int)curseek, SEEK_SET)<0) {
if(*len>0 && (buf = malloc(*len)) != NULL) {
if(io_seek((int)curseek, SEEK_SET)<0) {
free(buf);
buf = NULL;
} else *len = io_read(buf, *len);
+42 -16
View File
@@ -1,49 +1,75 @@
#!/bin/sh
# vired: the visual raw editor
# copyleft: pancake at nopcode dot org @ 2009
# copyleft: pancake at nopcode dot org @ 2009-2013
if [ -n "$1" ]; then
$0 | ired -n $@
PATH=.:$PATH
ttyset=`stty -g`
bye() {
[ -n "$ttyset" ] && stty $ttyset
exit 0
fi
}
case "$1" in
-) : ; ;;
'') echo "vired [-hv] [file]" ; exit 1 ; ;;
*) $0 - | ired -n $@ ; bye ; ;;
esac
ttyset=`stty -g`
stty -echo -icanon min 1
trap bye 2
getkey() {
echo "` stty -echo -icanon min 1 ; dd if=/dev/tty count=1 bs=1 2>/dev/null`"
}
getstr() {
stty icanon echo
read A
echo $A
echo "$A"
stty -icanon -echo
}
OLINES=0
autobs() {
LINES=`tput lines`
if [ "${OLINES}" != "${LINES}" ]; then
[ -n "${LINES}" ] && \
echo "b"$((($LINES-1)*16))
OLINES=${LINES}
fi
}
trap autobs 28
P=''
echo "b 256"
while : ; do
autobs
echo "!clear"
case $P in
'd') echo '!echo X | ired -n $BLOCK | rasm2 -o $OFFSET -d -' ;;
#'d') echo '!echo X | ired -n $| rasm2 -o $OFFSET -vd -|head -n '$LINES ; ;;
d) echo d ;;
*) echo x ;;
esac
A=`dd if=/dev/tty count=1 bs=1 2>/dev/null`
case $A in
case "`getkey`" in
'j') echo "s+16" ;;
'k') echo "s-16" ;;
'J') echo "s+b" ;;
'K') echo "s-b" ;;
'h') echo "s-1" ;;
'l') echo "s+1" ;;
'q') stty $ttyset; exit ;;
'b') printf 'b '>/dev/tty; echo b `getstr` ;;
'w') printf 'w '>/dev/tty; echo w `getstr` ;;
's') printf 's '>/dev/tty; echo s `getstr` ;;
'r') printf 'r '>/dev/tty; echo r `getstr` ;;
':') printf ': '>/dev/tty; echo `getstr`; read A ;;
'?') echo '?'; read A ;;
'q') bye ; ;;
'b') printf 'b'>/dev/tty; echo b`getstr` ;;
'w') printf 'w'>/dev/tty; echo w`getstr` ;;
's') printf 's'>/dev/tty; echo s`getstr` ;;
'r') printf 'r '>/dev/tty; echo r`getstr` ;;
':') printf ': '>/dev/tty; getstr; getkey >/dev/null ; ;;
'?') echo '?'; getkey >/dev/null; ;;
'+') echo "b+1" ;;
'-') echo "b-1" ;;
'*') echo "b+16" ;;
'/') echo "b-16" ;;
'p') if [ -n "$P" ]; then P=''; else P=d; fi ;;
p|P) if [ -n "$P" ]; then P=''; else P=d; fi ;;
esac
done
+3 -1
View File
@@ -1,4 +1,4 @@
.Dd Sep 1, 2009
.Dd Oct 7, 2009
.Dt VIRED 1
.Os
.Th VIRED 1
@@ -26,6 +26,8 @@ prompt seek address
prompt for resize, remove command
.It p
change print mode
.It :
enter raw ired command
.It ?
show help
.It q