bpe - binary patch editor
Wm E. Davidsen Jr
davidsen at sixhub.UUCP
Mon Oct 29 13:40:03 AEST 1990
I'm posting this because a number of people have asked me to mail it
and I can't. I will post it to comp.sources.misc when the new moderator
is in place.
The DOS version has been on cbip in the past.
#!/bin/sh
# shar: Shell Archiver (v1.27)
#
# Run the following text with /bin/sh to create:
# bpe.c
# hexsrch.c
# makefile
# readme
# bpe.1
#
sed 's/^X//' << 'SHAR_EOF' > bpe.c &&
X/***************************************************************************
X
XVersion History:
X
XVer.No Comment By
X===========================================================================
X1.0 first version (seems to do things right) andy at mssx
X1.1 some bugs fixed (tks to Maarten) andy at mssx.uucp
X maart at cs.vu.nl
X1.2 works with NOKEYPAD in all cases davidsen at crdos1.uucp
X make + and - move in 2 line increments
X add 'L' look for hex byte
X end edit with ^E, ^C gives signal in BSD
X / remembers the last search string, can repeat
X1.3 integrate 1.2 (davidsen) and 1.2 (andy/jon) davidsen at crdos1.uucp
X find hex string code added, author jon at joblab
X
XBUG REPORTS:
X============
X - The offset count in the first column is wrong,
X except for the first line; it's 0x10 too high.
X (fixed)
X - The test in disp() if a char is printable, fails
X for chars >= 0177.
X (fixed)
X
X - Help message for 'H' incorrect (fixed)
X
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 at mssx (mcvax!tuvie!mssx!andy)
X
X
X*****************************************************************************/
X
X#include <stdio.h>
X#include <curses.h>
X#include <fcntl.h>
X#include <signal.h>
X#include <ctype.h>
X
X/* this is needed for MS-DOS compilation */
X#ifndef O_BINARY
X#define O_BINARY 0
X#endif
X
X#define CTRL(c) ((c) & 037)
X#define DEL '\177'
X
X#ifdef NOKEYPAD
X#define KEY_LEFT CTRL('H')
X#define KEY_DOWN CTRL('J')
X#define KEY_UP CTRL('K')
X#define KEY_RIGHT CTRL('L')
X#ifndef O_RDWR
X#define O_RDWR 2
X#endif
X#define cbreak() crmode()
X#define beep() putchar(7)
X#endif
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 */
Xunsigned char 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 if (argc != 2) {
X fprintf(stderr,"Usage: %s filename\n",argv[0]);
X exit(1);
X }
X if (( path = open(argv[1],O_RDWR|O_BINARY)) == -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#ifdef SIGQUIT
X signal(SIGQUIT,donix);
X#endif /* no QUIT in MS-DOS */
X cbreak(); /* set single char input */
X noecho();
X#ifndef NOKEYPAD
X keypad(stdscr,TRUE);
X#endif
X filpos = 0; /* set global position to 0 */
X length = 0;
X command();
X clear();
X refresh();
X endwin();
X close(path);
X}
X
Xcommand()
X{
X int inval;
X
X header("BPE Version 1.3",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 find_hex();
X dump();
X break;
X case '?':
X help();
X break;
X case 'f':
X case 'F':
X case '/':
X find_string();
X dump();
X break;
X case '+':
X filpos += 32;
X dump();
X break;
X case 'n':
X case 'N':
X filpos += 256;
X dump();
X break;
X case '-':
X filpos -= 32;
X if (filpos < 0)
X filpos = 0;
X dump();
X break;
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
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#ifdef NOKEYPAD
X printw("Left ^H - down ^J - up ^K - right ^L - end editing with ^E");
X#else
X printw("End editing with ^E");
X#endif
X curx = cury = 0;
X while (inval != CTRL('E')) {
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 char *hexvals = "0123456789ABCDEF";
X char *strchr(), *wkptr;
X
X inlen = 0;
X while (inlen < 2) {
X val = getch();
X if (val > 0xff) return(val);
X if (islower(val)) val = toupper(val);
X wkptr = strchr(hexvals, val);
X if (wkptr == NULL) return(val|0x2000);
X else val = wkptr - hexvals;
X
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 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#ifdef NOKEYPAD
X printw("Left ^H - down ^J - up ^K - right ^L - end editing with ^E");
X#else
X printw("End editing with ^E");
X#endif
X curx = cury = 0;
X while (inval != -1) {
X move(HEXY+cury,HEXX+curx*3);
X refresh();
X inval = gethex(cury,curx);
X if (inval > 0xff) {
X /* this is control information */
X if (inval > 0x1fff)
X inval &= 0xff;
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 case CTRL('E'):
X inval = -1;
X break;
X }
X }
X else {
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 }
X move(2,0);
X clrtoeol();
X}
X
Xfind_string()
X{
X int stlen;
X char string[60];
Xstatic char laststring[60];
Xstatic int re_search = 0, old_filpos;
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 if (strlen(string) == 0) {
X if (strlen(laststring) > 0)
X strcpy(string, laststring);
X else {
X beep();
X return;
X }
X }
X else {
X strcpy(laststring, string);
X }
X noecho();
X move(2,0);
X clrtoeol();
X printw("Searching for '%s'",string);
X found = 0;
X searchpos = (filpos == old_filpos ? re_search : 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 old_filpos = filpos;
X#ifdef CLINES
X if (filpos >= 16*CLINES) {
X filpos -= 16*CLINES;
X }
X else {
X filpos = 0;
X }
X#endif /* context lines */
X#ifdef ALLIGN
X filpos &= ~0xf;
X#endif /* allign */
X re_search = old_filpos - filpos + 1;
X old_filpos = filpos;
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 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, c;
X
X /* output headings adjusted for the starting position */
X mvprintw(4,0, " ADDRESS ");
X for (i = 0, j = filpos & 0x0f; i < 16; ++i) {
X printw(" 0%c", "0123456789ABCDEF"[j]);
X j = (j + 1) % 16;
X }
X printw(" ASCII");
X
X mvprintw(5,0, "%s%s",
X "=======================================",
X "========================================");
X
X for ( i = 0; i < 16; i++) {
X mvprintw(ASCY+i,0,"%08lX",filpos+i*16);
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 (' ' <= (c = secbuf[i * 16 + j]) && c < DEL)
X mvprintw(ASCY+i,ASCX+j,"%c", c);
X else
X mvprintw(ASCY+i,ASCX+j,".");
X }
X }
XDisp2:
X refresh();
X}
X
X
Xdump()
X{
X int i,j;
X
X length = rdsec();
X disp(length);
X return(length);
X}
X
Xrdsec()
X{
X mvprintw(2,55,"Rel. Position : %08lX",filpos);
X refresh();
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 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,
X "F - Find string in file (beginning from curr. position)");
X mvwprintw(win,8,15,
X "H - locate hex bytes in file (beginning from curr. position)");
X mvwprintw(win,9,15,"N - Display next sector");
X mvwprintw(win,10,15,"P - Display previous sector");
X mvwprintw(win,11,15,"+ - Scroll forward 2 lines");
X mvwprintw(win,12,15,"- - Scroll back 2 lines");
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,16,15,"Q - Quit Program");
X mvwprintw(win,18,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}
X
SHAR_EOF
chmod 0664 bpe.c || echo "restore of bpe.c fails"
sed 's/^X//' << 'SHAR_EOF' > hexsrch.c &&
X
X/* Added by Jon LaBadie jon at jonlab.UUCP
X to implement the H (hex search) option */
X
X#include <stdio.h>
X#include <ctype.h>
X#include <curses.h>
X#define beep() putchar(7)
X
X/*
X** hex_2_byte returns the integer value of a byte
X** represented by the two characters passed to it.
X** For example, passed an '8' and an 'A', it will
X** return 170 (8 * 16 + 10). Returns -1 on any error.
X*/
X
Xint
Xhex_2_byte(a, b)
Xchar a, b;
X{
X int v = 0;
X
X if (!isxdigit(a) || !isxdigit(b))
X return -1;
X
X a = toupper(a);
X b = toupper(b);
X
X if (isdigit(a))
X v = (a - '0') * 16;
X else
X v = (a - 'A' + 10) * 16;
X
X if (isdigit(b))
X v += (b - '0');
X else
X v += (b - 'A' + 10);
X
X return v;
X}
X
X
X/* Take two strings as arguments.
X** First is a sequence of hex digit pairs.
X** Each pair is to be converted into the
X** equivalent unsigned 1 byte value and
X** stored in the second array.
X*/
X
Xint
Xcvt_str(s, h)
Xchar *s;
Xunsigned char *h;
X{
X int c;
X int len = 0;
X
X while(*s != '\0')
X {
X if (*(s+1) == '\0')
X return -1;
X c = hex_2_byte(*s, *(s+1));
X if (c >= 0)
X *h++ = c;
X else
X return -1;
X len++;
X s += 2;
X }
X *h = '\0';
X return len;
X}
X
Xfind_hex()
X{
X int stlen;
X char string[60];
X char *strstart;
Xstatic char laststring[60];
Xstatic int re_search = 0, old_filpos;
X unsigned char hexstr[30];
X unsigned char *up;
X int found;
X int searchpos;
X extern char secbuf[];
X extern long filpos;
X
X move(2,0);
X clrtoeol();
X printw("HEX string to search for: ");
X refresh();
X echo();
X string[0] = '0';
X getstr(&string[1]);
X if (strlen(string) == 1) {
X if (strlen(laststring) > 0)
X strcpy(string, laststring);
X else {
X beep();
X return;
X }
X }
X else {
X strcpy(laststring, string);
X }
X noecho();
X move(2,0);
X clrtoeol();
X if (strlen(string) % 2)
X strstart = &string[1];
X else
X strstart = &string[0];
X stlen = cvt_str(strstart, hexstr);
X if (stlen < 0)
X {
X printw("Invalid Hex string: %s", strstart);
X refresh();
X sleep(1);
X return;
X }
X printw("Searching for '%s'", strstart);
X refresh();
X found = 0;
X searchpos = 1;
X while (found == 0) {
X while ((256 - searchpos) >= stlen) {
X if (secbuf[searchpos] != hexstr[0] || memcmp(secbuf + searchpos + 1, hexstr + 1, stlen - 1))
X searchpos++;
X else {
X filpos += searchpos;
X#ifdef CLINES
X if (filpos >= 16*CLINES) {
X filpos -= 16*CLINES;
X }
X else {
X filpos = 0;
X }
X#endif /* context lines */
X#ifdef ALLIGN
X filpos &= ~0xf;
X#endif /* allign */
X re_search = old_filpos - filpos + 1;
X old_filpos = filpos;
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}
SHAR_EOF
chmod 0644 hexsrch.c || echo "restore of hexsrch.c fails"
sed 's/^X//' << 'SHAR_EOF' > makefile &&
X#________________ Start customizing here ________________
X#
X# If your Terminals and your curses lib supports keypad()
X# comment out the next line. You probably need it for BSD.
XNKEYPAD = -DNOKEYPAD
X
X# if you want the search operations to show found patterns in context,
X# set CLINES to the number of line of data to display before the pattern.
X# else comment out the next line
X# CLINES = -DCLINES=1
X
X# if you want the search operations to start the display on a mod 16
X# boundary, leave the next line, else comment out
X#ALLIGN = -DALLIGN
X
X# libraries to make curses work on your machine. Probably just curses
X# for V.2 and later, as is for BSD. You could try termlib instead of
X# termcap if the termcap library is not available.
XLIBES = -lcurses -ltermcap
X
X# local compilation and link options needed, such a 286 model selection, etc
XLOCAL =
X#
X# ________________ Stop customizing here ________________
X
X
XCFLAGS = -O $(NKEYPAD) $(CLINES) $(ALLIGN)
XOBJS = bpe.o hexsrch.o
XSRCS = bpe.c hexsrch.c
XEXEC = bpe
X
X# for making a shar file
XSHARLIST = $(SRCS) makefile readme bpe.1
XSHAR = shar
X
X$(EXEC): $(OBJS)
X $(CC) -o $(EXEC) $(LOCAL) $(OBJS) $(LIBES)
X
X#$(OBJS): $(SRCS)
X# $(CC) -c $(CFLAGS) $(LOCAL) $(SRCS)
X# special makerules here, portable
X.c.o:
X $(CC) -c $(CFLAGS) $(LOCAL) $?
X
Xshar: bpe.shar
Xbpe.shar: $(SHARLIST)
X $(SHAR) $(SHARLIST) > bpe.shar
X
Xarc: bpe.arc
Xbpe.arc: bpe.exe bpe.doc
X arc a bpe $?
X rm bpe.doc
X
Xbpe.doc: bpe.1
X nroff -man -Tlp bpe.1 | col > bpe.doc
SHAR_EOF
chmod 0644 makefile || echo "restore of makefile fails"
sed 's/^X//' << 'SHAR_EOF' > readme &&
XThis is Version 1.1 for the BPE Program I wrote some time ago,
Xthere has been some bug fixes(tks to maart at cs.vu.nl).
X
XTo generate the new Version of the BPE program type
X
X ed <bpe.diffs bpe.c
X
Xthen look at the new makefile, and correct the NKEYPAD value to
Xsuit for your System.
X
X
X
XAny further comments and bug reports are welcomed.
X
X
X
X
XAndreas Pleschutznig
XMicro Systems Software
XGraz, Austria
Xandy at mssx
X________________________________________________________________
X
XComments on v1.2:
X
X The changes to work without KEYPAD defined failed on my system. After
Xmaking changes to get them functional, I rewrote part of the makefile. I
Xwanted to have found strings in context, so I added an option to leave
Xsome data before the found string. I also added an option to start the
Xdisplay after find on a 16 byte boundary to allow matching with other
Xdumps.
X
X Then I added search for a byte, since I wanted that several times
Xwhile debugging, and finally after trying to move it to a BSD system I
Xchanged the "end edit" key to ^E instead of ^C, since ^C is normally the
Xinterrupt character on most of the systems I use, and signals are
Xignored. The CTRL macro wasn't quite correct, and I cleaned up the
Xgethex procedure, which didn't quite work on my systems.
X
X Oh yes, I wrote a man page for it, too. I still have a wish list if
Xanyone feels ambitious.
X
X bill davidsen, 3/1/89 (davidsen at crdos1.uucp)
X________________________________________________________________
X
XI sent my changes back to the original author, and he sent me *his*
Xversion 1.2 with other enhancements over 1.1. He asked me to merge them,
Xand after looking at his changes and mine I added the code to find a hex
Xstring to my code. We had fixed many of the same things and my makefile
Xseemed a bit cleaner. I also added a number of shell scripts to perform
Xmakes, including MS-DOS. The man page has been updated to reflect the
Xcombined version.
X
X bill davidsen (davidsen at crdos1.uucp)
X
SHAR_EOF
chmod 0644 readme || echo "restore of readme fails"
sed 's/^X//' << 'SHAR_EOF' > bpe.1 &&
X.TH BPE 1 LOCAL
X.SH NAME
X\fBbpe\fR - examine and patch binary files
X.SH SYNOPSIS
X\fBbpe\fR allows a file to be searched and modified in either ASCII or
Xhexadecimal. Each buffer is displayed in both modes.
X.SH DESCRIPTION
Xbpe binary.file
X.ne 15
X.SS Commands
X.nf
XD - Dump one page from current file position
XS - Set current file pointer
XF - Find string in file (beginning from curr. position)
X/ - Same as F
XH - locate hex bytes in file (beginning from curr. position)
XN - Display next sector
XP - Display previous sector
X+ - Scroll forward 2 lines
X- - Scroll back 2 lines
Xe - Edit ASCII portion of file
XE - Edit binary portion of file
XW - Write modified sector back to disk
XQ - Quit Program
X? - help
X.fi
X.ne 5
X.SS Editing a file
XEnter an editing mode by typing 'e' (for ASCII edit) or 'E' for hex
Xedit. The cursor may be moved either by the arrow keys or the vi-style
X^H, ^J, ^K, ^L keys, depending on compilation options. Place the cursor
Xon the byte to change and type either a printing ASCII character or two
Xdigit hex value. Exit either edit mode by typing ^E. When you are
Xsatisfied with your editing, enter the W command to write the modified
Xportion of the file back to disk.
X.ne 5
X.SS Searching for data
XYou may search for hex data by giving the h command and entering a
Xstring of hex digits. The search procedes forward from the current
Xlocation until a matching string is found. The display is adjusted to
Xput the first byte at the top of the screen (but see configuration
Xoptions). If no pattern is specified the previous pattern is used.
X.P
XTo search for a string, enter the F (for find) command, or the vi style
X/ command. At the prompt type in a string and press return. The search
Xprocedes as with a hex byte search. If you wish to repeat a string
Xsearch, enter the F command again and press return. This will repeat the
Xsearch for the previous string. If the starting position has not been
Xadjusted the search will start one character past the location of the
Xlast occurence found.
X.SS Configuration options
XThe makefile contains configuration option, identifiable by comments.
XThese are all at the top of the makefile. If your curses supports KEYPAD
Xdefinition for your terminal, you may use the cursor keys on the keypad.
XThis is generally only found in SysV systems with termlib versions of
Xcurses. If you don't have that feature the NOKEYPAD option will allow
Xuse of vi style cursor keys.
X.P
XWhen searching, if you prefer to see the pattern in context you may set
Xthe CLINES to the number of lines of context displayed before the
Xpattern found. This may cause problems doing hex searches. In addition,
Xif you want the display to start on a 16 byte boundary, to match od or
Xhd output, you may enable the ALLIGN option.
X.SH WARNINGS
XIllegal commands are flagged as such.
X.SH SEE ALSO
Xod, hd, possibly adb.
X.SH DIAGNOSTICS
X.SH LIMITATIONS
XIf the l or L commands are used with no pattern specified before a
Xpattern has been specified the value zero will be used.
X.ne 15
X.SH AUTHOR
X.nf
XOriginal author:
X Andreas Pleschutznig
X Teichhofweg 2
X 8044 Graz
X Austria
XContributions by:
X maart at cs.vu.nl
Xv1.2 features added by:
X Bill Davidsen, Box 8 KW-C206, Schenectady NY 12345
X
XComments and bug reports to:
X andy at mssx (mcvax!tuvie!mssx!andy)
XBugs in features documented as being added in v1.2 to
X davidsen at crdos1.uucp (uunet!crd.ge.com!davidsen)
X.fi
SHAR_EOF
chmod 0644 bpe.1 || echo "restore of bpe.1 fails"
exit 0
--
bill davidsen - davidsen at sixhub.uucp (uunet!crdgw1!sixhub!davidsen)
sysop *IX BBS and Public Access UNIX
moderator of comp.binaries.ibm.pc and 80386 mailing list
"Stupidity, like virtue, is its own reward" -me
More information about the Alt.sources
mailing list