[comp.sources.misc] v03i064: Screen oriented binary patch editor

andy@uunet.UU.NET@mssx.UUCP (Andreas Pleschutznig) (06/28/88)

Posting-number: Volume 3, Issue 64
Submitted-by: "Andreas Pleschutznig" <andy@uunet.UU.NET@mssx.UUCP>
Archive-name: bpe

[The author called this "patch", perhaps he's not aware of lwall's magnum opus.
Having seen "bp" and "bpatch", I named this "bpe" instead.  ++bsa]

I wrote this, because in std unix sometimes i failed to see the struc.
of a file in a format I wanted to see it. I hope this program is useful to
some of you, so i post it to comp.sources.unix to make it available to all
of you. If you have any questions or suggestions or patches please kontact 
me.
	Andreas Pleschutznig
	Micro Systems Software
	8044 Graz, Austria
	Teichhofweg 2

#------------------------------- cut here ---------------------------
# To recreate the file(s) in this archive execute this file with sh
# Do not use csh!!!.  
#
# Created from : andy@mssx
# date:       Mon Jun 27 18:36:30 GMT 1988
echo x - makefile
 sed 's/^X//' >makefile << '+SHAR+MARK+'
XCFLAGS = -O 
XLIBES = -lcurses
XOBJS = bpe.o
XSRCS = bpe.c
XEXEC = bpe
X
X$(EXEC): $(OBJS)
X	cc $(OBJS) -o $(EXEC) $(LIBES)
X
X$(OBJS): $(SRCS)
X	cc -c $(CFLAGS) $(SRCS)
+SHAR+MARK+
echo '-rw-r--r--   1 andy     other        166 Jun  6 12:22 makefile     (as sent)'
chmod u=rw,g=r,o=r makefile
ls -l makefile
echo x - bpe.c
 sed 's/^X//' >bpe.c << '+SHAR+MARK+'
X/***************************************************************************
X
XVersion History:
X
XVer.No	Comment							By
X===========================================================================
X1.0 	first version (seems to to things right)   		andy@mssx
X
XI declare this program as freeware, i.e. you may duplicate it, give it
Xto your friends, and transfer it to any machine you like, as long as
Xyou do not change or delete the build in copyright message.
X
X	Andreas Pleschutznig
X	Teichhofweg 2
X	8044 Graz
X	Austria 
X
XComments and bug reports to:
X	andy@mssx	(mcvax!tuvie!mssx!andy)
X
X
X*****************************************************************************/
X
X
X#include <curses.h>
X#include <fcntl.h>
X#include <signal.h>
X
X#define	BELL	0x07
X#define ASCX	63
X#define ASCY	6
X#define HEXY	6
X#define HEXX	12
X
Xint     path;                   /* path to file to patch */
Xlong	filpos;			/* position in file */
Xchar	secbuf[256];		/* sector read buffer */
X
Xint     donix();                /* default signal handling routine */
Xchar	filename[60];
Xint	length;			/* length of read sector */
X
Xmain(argc,argv)
Xint argc;
Xchar *argv[];
X
X{
X	if (argc != 2) {
X		fprintf(stderr,"Usage: %s filename\n",argv[0]);
X		exit(1);
X		}
X	if (( path = open(argv[1],O_RDWR)) == -1) {
X		fprintf(stderr,"%s: Can't open '%s'\n",argv[0],argv[1]);
X		exit(1);
X		}
X	sprintf(filename,"%s",argv[1]);
X	initscr();
X	refresh();
X	signal(SIGINT,donix);
X	signal(SIGQUIT,donix);
X	cbreak();                       /* set single char input */
X	noecho();
X	keypad(stdscr,TRUE);
X	filpos = 0;			/* set global position to 0 */
X	length = 0;
X	command();
X	endwin();
X	close(path);
X}
X
Xcommand()
X
X{
X	int inval;
X
X	header("PATCH Version 1.0",filename,"(C) 1988 MSS Graz");
X	inval = 0;
X	while ((inval != 'q') && (inval != 'Q')) {
X		move(2,0);
X		mvprintw(2,0,"COMMAND : ");
X		refresh();
X		inval = getch();
X		switch (inval) {
X			case 'q':
X			case 'Q':
X				break;
X			case 'h':
X			case 'H':
X			case '?':
X				help();
X				break;
X			case 'f':
X			case 'F':
X				find_string();
X				dump();
X				break;
X			case '+':
X			case 'n':
X			case 'N':
X				filpos += 256;
X				dump();
X				break;
X			case '-':
X			case 'p':
X			case 'P':
X				filpos -= 256;
X				if (filpos < 0)
X					filpos = 0;
X				dump();
X				break;
X			case 'D':
X			case 'd':
X				dump();
X				break;
X			case 's':
X			case 'S':
X				set();
X				dump();
X				break;
X			case 'e':
X				edit_ascii();
X				break;
X			case 'E':
X				edit_hex();
X				break;
X			case 'w':
X			case 'W':
X				wrsec();
X				break;
X			default:
X				werr("Invalid Command !");
X			}
X		}
X
X}
X
Xedit_ascii()
X{
X	int inval = 0;
X	int cury,curx;
X
X	if (length == 0)
X		length = dump();
X	move(2,0);
X	clrtoeol();
X	printw("End editing with CNTRL-C");
X	curx = cury = 0;
X	while (inval != 0x03) {
X		move(ASCY+cury,ASCX+curx);
X		refresh();
X		inval = getch();
X		switch (inval) {
X			case KEY_UP:
X				if (cury)
X					cury--;
X				else
X					beep();
X				break;
X			case KEY_DOWN:
X				if (cury < 15)
X					cury++;
X				else
X					beep();
X				break;
X			case KEY_RIGHT:
X				if (curx < 15)
X					curx++;
X				else
X					beep();
X				break;
X			case KEY_LEFT:
X				if (curx)
X					curx--;
X				else
X					beep();
X				break;
X			default:
X				if ((inval >= 0x20) && (inval <= 0x7e)) {
X					secbuf[cury*16+curx] =inval;
X					curx++;
X					if (curx > 15) {
X						curx=0;
X						cury++;
X						}
X					if (cury > 15)
X						cury = 0;
X					disp(length);
X					}
X				break;
X			}
X		}
X	move(2,0);
X	clrtoeol();
X}
X
Xgethex(cury,curx)
Xint	cury,curx;
X{
X	int val;
X	int inlen;
X	int value;
X
X	inlen = 0;
X	while (inlen < 2) {
X		val = getch();
X		if (val > 255) 
X			return(val);
X		if (val < '0')
X			return(-1);
X		if (val > '9') val &= ~0x20;
X		if (((val >= '0') && (val <='9')) || 
X		    ((val >= 'A') && (val <= 'F'))) {
X			if (val <= '9')
X				val -= '0';
X			else
X				val = val - 'A' + 0x0a;
X			switch (inlen) {
X				case 0:
X					value = val << 4;
X					secbuf[cury*16+curx] = value;
X					disp(length);
X					move(HEXY+cury,HEXX+curx*3+1);
X					refresh();
X					break;
X				case 1:
X					value += val ;
X					break;
X				}
X			inlen++;
X			}
X		}
X	return(value);
X}
X
Xedit_hex()
X{
X	int inval = 0;
X	int cury,curx;
X
X	if (length == 0)
X		length = dump();
X	move(2,0);
X	clrtoeol();
X	printw("End editing with CNTRL-C");
X	curx = cury = 0;
X	while (inval != -1) {
X		move(HEXY+cury,HEXX+curx*3);
X		refresh();
X		inval = gethex(cury,curx);
X		switch (inval) {
X			case KEY_UP:
X				if (cury)
X					cury--;
X				else
X					beep();
X				break;
X			case KEY_DOWN:
X				if (cury < 15)
X					cury++;
X				else
X					beep();
X				break;
X			case KEY_RIGHT:
X				if (curx < 15)
X					curx++;
X				else
X					beep();
X				break;
X			case KEY_LEFT:
X				if (curx)
X					curx--;
X				else
X					beep();
X				break;
X			default:
X				if ((inval >= 0x00) && (inval <= 0xff)) {
X					secbuf[cury*16+curx] =inval;
X					curx++;
X					if (curx > 15) {
X						curx=0;
X						cury++;
X						}
X					if (cury > 15)
X						cury = 0;
X					disp(length);
X					}
X				break;
X			}
X		}
X	move(2,0);
X	clrtoeol();
X}
X
Xfind_string()
X
X{
X	int 	stlen;
X	char 	string[60];
X	int	found;
X	int 	searchpos;
X
X	move(2,0);
X	clrtoeol();
X	printw("String to search : ");
X	refresh();
X	echo();
X	getstr(string);
X	noecho();
X	move(2,0);
X	clrtoeol();
X	printw("Searching for '%s'",string);
X	found = 0;
X	searchpos = 0;
X	stlen = strlen(string);
X	while (found == 0) {
X		while ((256 - searchpos) >= stlen) {
X			if (testchar(secbuf+searchpos,string,stlen))
X				searchpos++;
X			else {
X				filpos += searchpos;
X				found = 1;
X				break;
X				}
X			}
X		if (found == 0) {
X			filpos += searchpos;
X			searchpos = 0;
X			}
X		if (rdsec() == 0) {
X			found = 1;	
X			}
X		refresh();
X		}
X	move (2,0);
X	clrtoeol();
X}
X
Xtestchar(buffer,string,length)
Xchar	*buffer;
Xchar	*string;
Xint	length;
X{
X	register int i;
X	
X	i = 0;
X	while ( i < length) {
X		if (buffer[i] != string[i])
X			break;
X		i++;
X		}
X	if ( i == length)
X		return(0);
X	return(1);
X}
X
Xset()
X
X{
X	echo();
X	move(2,0);
X	clrtoeol();
X	printw("New File Position : ");
X	refresh();
X	scanw("%lx",&filpos);
X	move(2,0);
X	clrtoeol();
X	noecho();
X}
X
Xdisp(length)
Xint	length;
X{
X	int	i,j;
X
X	j = 0;
X	mvprintw(4,0," ADDRESS    00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F      ASCII");
X	mvprintw(5,0,"===============================================================================");
X	for ( i = 0; i < 16; i++) {
X		mvprintw(ASCY+i,0,"%08lX",filpos+i*16+j);
X		for (j = 0; j < 16; j++) {
X			if (( i*16 + j ) >= length) {
X				clrtoeol();
X				goto Disp1;
X				}
X			mvprintw(ASCY+i,HEXX+j*3,"%02X",secbuf[i*16+j] & 0xFF);
X			}
XDisp1:
X		for (j = 0; j < 16; j++) {
X			if (( i*16 + j ) >= length) {
X				clrtobot();
X				goto Disp2;
X				}
X			if (secbuf[i*16+j] >= ' ')
X				mvprintw(ASCY+i,ASCX+j,"%c",secbuf[i*16+j]);
X			else
X				mvprintw(ASCY+i,ASCX+j,".");
X			}
X		}
XDisp2:
X	refresh();
X}
X
X
Xdump()
X
X{
X	int	i,j;
X
X	length = rdsec();
X	disp(length);
X	return(length);
X}
X
Xrdsec()
X
X{
X	mvprintw(2,55,"Rel. Position : %08lX",filpos);
X	lseek(path,filpos,0);
X	length = read(path,secbuf,256);
X	return(length);
X}
X
Xwrsec()
X{
X	lseek(path,filpos,0);
X	write(path,secbuf,length);
X}
X
Xhelp()
X
X{
X	WINDOW	*win;
X
X	win = newwin(0,0,0,0);
X	wclear(win);
X	mvwprintw(win,3,10,"Valid Commands are :");
X	mvwprintw(win,5,15,"D - Dump one page from current file position");
X	mvwprintw(win,6,15,"S - Set current file pointer");
X	mvwprintw(win,7,15,"F - Find string in file (beginning from curr. position)");
X	mvwprintw(win,8,15,"H - Find hex string in file (beginnig from current position)");
X	mvwprintw(win,9,15,"+ - Display next sector");
X	mvwprintw(win,10,15,"N - Display next sector");
X	mvwprintw(win,11,15,"- - Display previous sector");
X	mvwprintw(win,12,15,"P - Display previous sector");
X	mvwprintw(win,19,15,"Q - Quit Program");
X	mvwprintw(win,13,15,"e - Edit ASCII portion of file");
X	mvwprintw(win,14,15,"E - Edit binary portion of file");
X	mvwprintw(win,15,15,"W - Write modified sector back to disk");
X	mvwprintw(win,20,20,"Continue with any char.");
X	wrefresh(win);
X	getch();
X	delwin(win);
X	touchwin(stdscr);
X	refresh();
X}
X
Xwerr(errstr)
Xchar    *errstr;
X
X{
X	beep();
X	move(LINES-1,0);
X	printw("%s",errstr);
X	refresh();
X	sleep(2);
X	move(LINES-1,0);
X	clrtoeol();
X	refresh();
X}
X
X	
X
Xheader(left,mid,right)
Xchar    *left;
Xchar    *mid;
Xchar    *right;
X
X{
X	mvprintw(0,0,"%s",left);
X	mvprintw(0,79-strlen(right),"%s",right);
X	mvprintw(0,40-strlen(mid)/2,"%s",mid);
X}
X
Xdonix(sig)
Xint sig;
X
X{
X	signal(sig,donix);
X}
+SHAR+MARK+
echo '-rw-rw-r--   1 andy     other       8369 Jun  8 10:49 bpe.c     (as sent)'
chmod u=rw,g=rw,o=r bpe.c
ls -l bpe.c
exit 0