27 Commits
Author SHA1 Message Date
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
18 changed files with 809 additions and 231 deletions

No files matched your search

+22 -12
View File
@@ -1,16 +1,25 @@
CC?=gcc
VERSION=0.5
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: cmd.c io.c util.c hexparse.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 +30,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;
}
+138 -79
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) {
static int cmd_hexdump(char *arg) {
int len = bsize;
ut8 *buf = getcurblk(arg, &len);
if (buf) {
if(buf && len>0) {
hexdump(buf, len, 16);
free(buf);
return 1;
}
return 2;
}
static void cmd_print(char *arg) {
static int cmd_print(char *arg) {
ut8 *buf;
int len = bsize;
if (*arg) {
if(*arg) {
buf = getcurblk(arg, &len);
if (!buf) return;
if(!buf) return 2;
print_fmt(buf, arg, len);
free(buf);
} else printf(
@@ -23,101 +25,135 @@ 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) {
static int cmd_bytedump(const char *arg) {
int i, len = bsize;
ut8 *buf = getcurblk(arg, &len);
if (buf) {
for(i=0;i<len;i++)
printf("%02x", buf[i]);
printf("\n");
free(buf);
}
if(!buf) return 2;
for(i=0;i<len;i++)
printf("%02x", buf[i]);
printf("\n");
free(buf);
return 1;
}
static void cmd_search(char *arg) {
ut8 *buf;
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) {
static int cmd_dump(char *file) {
int len = bsize;
ut8 *buf = getcurblk("", &len);
if (len<1 || buf) {
if(len<1 || buf) {
FILE *fd = fopen(file, "wb");
if (fd) {
if (fwrite(buf, len, 1, fd)<len)
perror("fwrite");
fclose(fd);
} else perror("fopen");
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) {
static int cmd_load(char *file) {
FILE *fd = fopen(file, "rb");
if (fd) {
if(fd) {
void *buf = malloc(bsize);
if (bsize>0 && buf) {
if(bsize>0 && buf) {
int len = fread(buf, 1, bsize, fd);
if (len<bsize)
if(len<bsize)
perror("fread");
if (io_write(buf, len)<len)
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) {
static int cmd_write(const char *arg) {
ut8 *barg;
int len;
arg = skipspaces(arg);
if (*arg=='"') {
SKIPSPACES(arg);
if(*arg=='"') {
barg = (ut8*)strdup (arg+1);
len = strlen(++arg)-1;
arg[len]='\0';
} else len = hexstr2raw(arg);
// 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 (len<1 || 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) {
static int cmd_help(char *arg) {
if(*arg) {
ut64 ret = str2ut64(arg);
printf("0x%"LLF"x %"LLF"d 0%"LLF"o\n", ret, ret, ret);
} else printf(
@@ -128,63 +164,86 @@ static void cmd_help(char *arg) {
"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"
"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) {
int len, ret = 0;
if (!*arg) printf("%"LLF"d\n", (ut64)io_seek(0, SEEK_END));
else if (*arg=='-') {
ut8 *buf = malloc(bsize);
if (buf) {
ut64 i, n = str2ut64(arg+1);
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);
if ((len = io_read(buf, bsize))>0) {
if((len = io_read(buf, bsize))>0) {
io_seek(curseek+i, SEEK_SET);
if (io_write(buf, len)<len)
if(io_write(buf, len)<len)
perror("io_write"),ret=-1;
} else perror("io_read"), ret=-1;
} else break; //perror("io_read"), ret=-1;
}
free(buf);
if ((ret = io_seek(0, SEEK_END))>n)
if((ret = io_seek(0, SEEK_END))>n)
ret = io_truncate(ret-n);
}
} else ret = io_truncate(str2ut64(arg));
if (ret<0)
perror("truncate");
} else perror("malloc");
break;
default:
ret = io_truncate(str2ut64(arg));
}
if(ret<0) perror("truncate");
return 1;
}
static void cmd_system(char *arg) {
static int cmd_system(char *arg) {
int len = bsize;
char *buf, str[1024];
if (strstr(arg, "BLOCK")) {
char str[1024];
ut8 *buf;
if(strstr(arg, "BLOCK")) {
FILE *fd = fopen(".curblk", "wb");
if (fd) {
if ((buf = getcurblk("", &len))) {
if(fd) {
if((buf = getcurblk("", &len))) {
setenv("BLOCK", ".curblk", 1);
if (fwrite(buf, len, 1, fd)<len)
if(fwrite(buf, len, 1, fd)<len)
perror("fwrite");
free(buf);
}
fclose(fd);
}
}
if (strstr(arg, "OFFSET")) {
if(strstr(arg, "OFFSET")) {
sprintf(str, "%"LLF"d", curseek);
setenv("OFFSET", str, 1);
}
if (strstr(arg, "XOFFSET")) {
if(strstr(arg, "XOFFSET")) {
sprintf(str, "0x%"LLF"x", curseek);
setenv("XOFFSET", str, 1);
}
if (io_system(arg)<0)
if(io_system(arg)<0)
perror("system");
unlink(".curblk");
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;
}
+24 -2
View File
@@ -1,5 +1,26 @@
/* Copyleft 2009 -- pancake /at/ nopcode /dot/ org */
#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>
@@ -8,7 +29,7 @@ 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;
@@ -32,7 +53,7 @@ static inline 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)
@@ -43,3 +64,4 @@ static inline int io_open(char *file) {
#define io_truncate(x) ftruncate(_fd, (unsigned long)x)
#endif
#endif
+54 -42
View File
@@ -1,4 +1,4 @@
/* Copyleft 2009 -- pancake /at/ nopcode /dot/ org */
/* Copyleft 2009-2013 -- pancake /at/ nopcode /dot/ org */
#define ut64 unsigned long long
#define ut8 unsigned char
@@ -8,96 +8,104 @@ static char *script = 0;
static ut64 oldseek, curseek = 0LL;
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 "cmd.c"
static void red_slurpin() {
ut8 buf[4096];
ut8 buf[BUFSZ];
for(;;) {
int 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;
}
}
static void red_interpret(char *file) {
char buf[1024];
static int red_interpret(char *file) {
char buf[BUFSZ];
FILE *fd = fopen(file, "r");
if (fd != 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);
} 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 'q': return 0;
case ';': case '#': break; // comment
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 '>': 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 '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 '?': 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 != '!') {
if(*line != '!') {
at = strchr(line, '@');
oldseek = curseek;
obsize = bsize;
if (at) {
if(at) {
*at = 0;
at2 = strchr(++at, ':');
if (at2) {
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 int red_open(char *file) {
int ret = io_open(file);
if (ret != -1) {
if(ret != -1) {
oldseek = 0;
setenv("FILE", file, 1);
if (script)
if(script)
red_interpret(script);
while(red_prompt()) {
while((ret=red_prompt())>0) {
curseek = oldseek;
bsize = obsize;
}
io_close();
} else fprintf(stderr, "Cannot open '%s'\n", file);
return ret==-1 ?1:0;;
} else if (file)
fprintf(stderr, "Cannot open '%s'\n", file);
return ret==-1 ?1:0;
}
static int red_help() {
@@ -107,16 +115,20 @@ static int red_help() {
int main(int argc, char **argv) {
int i, ret = 1;
if (argc>1)
for(i=1;i<argc;i++) {
if (argv[i][0]=='-')
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 'n': verbose = 0; break;
case 'v': puts("red "VERSION" 2009"); ret = 0; break;
case 'v': puts("ired "VERSION); ret = 0; break;
case 'h': ret = red_help(); break;
case 0x0: red_slurpin(); ret = 0; break;
} else ret = red_open(argv[i]);
} else {
if (!argv[i]) break;
ret = red_open(argv[i]);
}
} else ret = red_help();
return ret;
}
+3 -1
View File
@@ -1,4 +1,4 @@
#define VERSION "0.4"
#define VERSION "0.5"
#include <unistd.h>
#include <sys/types.h>
@@ -8,6 +8,8 @@
#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[256];
+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
+44 -50
View File
@@ -1,27 +1,21 @@
/* 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) {
if(j>=len) {
printf(j%2?" ":" ");
continue;
}
printf(j%2?"%02x ":"%02x", buf[j]);
}
for(j=i;j<i+w;j++) {
if (j>=len) printf(" ");
else printf("%c", isprint(buf[j])?buf[j]:'.');
}
printf(" ");
for(j=i;j<i+w;j++)
printf("%c", isprint(buf[j])?buf[j]:'.');
printf("\n");
}
}
@@ -33,19 +27,19 @@ static void print_fmt(const ut8 *buf, char *fmt, unsigned int len) {
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;
@@ -55,50 +49,50 @@ static void print_fmt(const ut8 *buf, char *fmt, unsigned int len) {
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);
}
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;
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 unsigned int hexstr2raw(char *arg) {
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;
}
@@ -106,14 +100,14 @@ static unsigned int hexstr2raw(char *arg) {
return len;
}
static void *getcurblk(char *arg, int *len) {
void *buf = NULL;
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 (*len>0 && (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);
+1 -1
View File
@@ -1,6 +1,6 @@
#!/bin/sh
# vired: the visual raw editor
# copyleft: pancake at nopcode dot org @ 2009
# copyleft: pancake at nopcode dot org @ 2009-2013
PATH=.:$PATH