Subject: v07i014: Binary (file) patcher/viewer Newsgroups: mod.sources Approved: mirror!rs Submitted by: pyramid!lukeII!itkin (Steven List) Mod.sources: Volume 7, Issue 14 Archive-name: bpatch [ See me notes at the end of the README. --r$ ] #!/bin/sh # This is a shell archive. Remove anything before this line, # then unpack it by saving it in a file and typing "sh file". # Exit status; set to 1 on "wc" errors or if would overwrite. STATUS=0 # Contents: README Makefile bpatch.1 bpatch.c echo x - README if test -f README ; then echo README exists, putting output in $$README OUT=$$README STATUS=1 else OUT=README fi sed 's/^XX//' > $OUT <<'@//E*O*F README//' XXHerewith find BPATCH - a marvelously utile utility. While not of XXmy original creation, I have been given permission to place in the XXpublic domain. I have made substantial modifications to the original XXsource given to me. Specifically I cleaned it up a bit and made it XXwork with SVR2 curses. Personally, I think it's pretty neat. XXOK - for those of you who may scream by now "WHAT THE HELL IS IT ALREADY?" XXI respond that it is a binary file editor and dump utility! That's XXright! You can dump your file in the nicely laid out side-by-side XXhex and ascii format or you can actually EDIT it at your terminal! XXYes, I have seen the BED editor that came across the network. XXUnfortunately, it converted the entire file before and after editing. XXBpatch, on the other hand, works with one 256 byte page at a time. XXIt is marvelously useful for looking at things like raw disk UNIFY XXdatabases and even raw disks! While the man page may not be absolutely XXup to date, the online help is. Try the question mark (?) command. XXAs always, I would love to hear about bugs/changes/enhancements/requests. XX Steven List @ Benetics Corporation, Mt. View, CA XX Just part of the stock at "Uncle Bene's Farm" XX {cdp,engfocus,idi,oliveb,opusys,plx,pyramid,tolerant}!bene!luke!itkin XXAddition by the moderator: XXI have added code, surrounded by #ifdef MOD_HAX, that gets bpatch XX(barely?) working on my 4.2 system. I would be very interested in XXpublishing a set of diffs that's less of a hack. Oh yeah: I also XXwrote the Makefile. XX /Rich $alz @//E*O*F README// chmod u=rw,g=rw,o=rw $OUT echo x - Makefile if test -f Makefile ; then echo Makefile exists, putting output in $$Makefile OUT=$$Makefile STATUS=1 else OUT=Makefile fi sed 's/^XX//' > $OUT <<'@//E*O*F Makefile//' XX# This may have to change on your system. XX# You may have to fiddle with various combinations of curses, termcap, XX# terminfo, etc. Good luck! XXLIBS = -lcurses -ltermcap XX#LIBS = -ltermlib XX#LIBS = -lterminfo XX# However you need getopt. XXGETOPT = -lgetopt XX# If you're running on a 4.[23] system, you probably want this. XXWORK = -DMOD_HAX XXCFLAGS = -O $(WORK) XXbpatch: bpatch.o XX $(CC) -o bpatch $(CFLAGS) bpatch.o $(GETOPT) $(LIBS) XXinstall: XX @echo Use cp to put things where you want them @//E*O*F Makefile// chmod u=rw,g=rw,o=rw $OUT echo x - bpatch.1 if test -f bpatch.1 ; then echo bpatch.1 exists, putting output in $$bpatch.1 OUT=$$bpatch.1 STATUS=1 else OUT=bpatch.1 fi sed 's/^XX//' > $OUT <<'@//E*O*F bpatch.1//' XX.TH "bpatch" "1" "Benetics Local" XX.if t .nr LL 7i XX.if t .nr IN .8i XX.if n .nr LL 70 XX.if n .nr IN 8 XX.fi XX.ad b XX.SH NAME XXbpatch - binary patch and dump file utility XX.SH SYNOPSIS XXbpatch [ -b blksize ] [ -d ] [ -D pagecnt ] [ -e ] [ -p ] [ -r reclen ] [ -s ] [ -x ] file... XX.SH DESCRIPTION XX\fIBpatch\fR allows the viewing and/or modification of files, independent of XXfile type (text, executable, data file, and so forth). \fIBpatch\fR XXallows the data to either be examined at the terminal, dumped to a print XXdevice or file, or edited in the general manner of \fIvi(1)\fR. The XXdata in the file is dumped or displayed in \fIpages\fR of 256 bytes. XX.SS Options XX.IP "-b blksize" 12 XXThe \fI-b\fR option specifies the blocksize of the data file. This is used XXprimarily with tapes, and is allowed only with one of the dump (\fI-d\fR XXor \fI-D\fR) options. When this option is specified, the file is opened XXin readonly mode. XX.IP "-d" 12 XXThe \fI-d\fR option indicates that a dump (no terminal manipulation) is XXto be performed. The entire file will be dumped to standard output. No XXediting of the data is allowed and the file is opened in readonly mode. XX.IP "-D pagecnt" 12 XXThe \fI-D\fR option is similar to the \fI-d\fR option, with the XXfollowing exception: the pagecnt argument limits the dump to the XXspecified number of \fIpages\fR. XX.IP "-e" 12 XXThe \fI-e\fR option indicates that the file contains EBCDIC data and XXshould be converted in the character portion of the dump. XX.IP "-p" 12 XXUsed with one of the \fIdump\fR options, this option causes the program XXto pause between \fIpages\fR. The program will then wait for the user XXto press either the \fIreturn\fR key to continue, or the \fIDEL\fR (or XX\fIrubout\fR) key to stop the dump. XX.IP "-r reclen" 12 XXThe \fI-r\fR option indicates the record length of the data within the XXdump. When specified, this option causes \fIbpatch\fR to place a colon XX(:) between the last byte of one record and the first byte of the next. XX.IP "-s" 12 XXThis option turns on the byte swap option. It may be toggled dynamically XXduring execution (see \fI-x\fP under Commands below). XX.IP "-x" 12 XXThis option specifies the suppression of pages that contain only NUL XXcharacters. The result is that only the page header (name and page XXnumber) will appear for such a page. This option may only be used with XXone of the dump options. XX.SS Arguments XX.IP file 12 XXAny number of files may be specified. XX.SS Commands XXAll commands are valid only in the non-dump, interactive mode. Commands XXmay be entered in either upper or lower case. Commands of the form '^x' XXindicate that the control character \fIx\fR is to be entered. XX.P XXAll commands that request movement within a file or between files cannot XXbe executed if any changes have been made. To proceed in this case, the XXuser must either enter the \fIw\fR command, the \fIu\fR command, or the XX\fIr\fR command. XX.P XXRequesting a next or previous file when there is no such will cause the XXissuance of an error message. XX.P XXNote that certain commands allow/require either some text or numeric XXvalue. In those cases, the user should type in characters and end the XXstring with either a or . XX.IP ? 6 XXDisplay the help screen. The help screen will remain until the user XXeither redraws the screen (see \fI^r\fR) or changes pages or files. XX.IP ! 6 XXExecute the following command in the shell. XX.IP backslash 6 XXDisplay the previous page. XX.IP 6 XXDisplay the next page. XX.IP DEL 6 XXQuit the program if no changes have been made. XX.IP / 6 XXThis command initiates an ASCII search. The text entered on the command XXline will be used as a search string, and the file will be searched XXstarting with the current page. When the string is found, the page XXcontaining the string will be displayed. If the string is not found, an XXapapropriate message will be displayed. XX.IP ^f 6 XXOpen a named file whose name will be entered on the command line and XXfollowed either by or DEL. XX.IP ^n 6 XXOpen the next file and display the first page. XX.IP ^p 6 XXOpen the previous file and display the first page. XX.IP ^q 6 XXQuit without writing current changes. XX.IP ^r 6 XXRedraw the screen. XX.IP NNN 6 XXEntering a numeric value requests that the specified page be displayed. XX.IP -x 6 XXToggle the command line option represented by \fIx\fR: XX.RS 12 XX.IP a 6 XXToggle display to ascii (assume data is ascii). XX.IP e 6 XXToggle display to dbcdic (assume data is ebcdic). XX.IP s 6 XXToggle byte swap. XX.RE XX.IP a 6 XXEdit the ASCII display. End edits by pressing the DEL key. All other XXcharacters will be treated as valid input. Cursor movement keys (arrows XXand home) allow movement within the edit window. Nonprinting XXcharacters are displayed as dot (.) in this window. XX.IP f 6 XXDisplay the first page in the current file. XX.IP g 6 XXDisplay the page containing the byte address typed in following the command. XX.IP h 6 XXEdit the HEXADECIMAL display. End edits by pressing DEL key. Cursor XXmovement keys (arrows and home) allow movement within the edit window. XXTwo keystrokes are required to modify a byte, and both must be valid XXhexadecimal values (0-9 and a-f). To cancel a change after typing one XXcharacter, press DEL. XX.IP l 6 XXDisplay the last page in the current file. XX.IP q 6 XXQuit the file. A warning will be issued if any changes have been made XXbut not written out. XX.IP r 6 XXReread the current page. XX.IP u 6 XXUndo all changes to the current page. XX.IP w 6 XXWrite out the current page. XX.SH "SEE ALSO" XXod(1) @//E*O*F bpatch.1// chmod u=rw,g=rw,o=rw $OUT echo x - bpatch.c if test -f bpatch.c ; then echo bpatch.c exists, putting output in $$bpatch.c OUT=$$bpatch.c STATUS=1 else OUT=bpatch.c fi sed 's/^XX//' > $OUT <<'@//E*O*F bpatch.c//' XX/*T bpatch - A binary file patch/dump utility */ XX/*S Introduction */ XX/*F bpatch *********************************************************** XX* bpatch XX* by Garry M Johnson - 09/17/84 XX* (C) Copyright 1984, 1985 XX* XX* Change History: XX* 03/05/86 - added further terminal independence XX* added use of ioctl (see main and mstdin) XX* added -D versus -d command line option XX* added use of standard getopt XX* cleaned up code, eliminated function "ikf" XX* added original versions of ezlib functions, such as XX* icc, setterm, cm, mstdin, erase, length, move XX* added ^R, ^Q, ^N, and ^P commands XX* added ^F, !, and ^X (-X) commands XX* changed name to "bpatch" XX* added direct address command (g) XX* added ASCII search capability XX* 07/07/86 - converted to use curses XX* modified direct addressing to use suffixes XX* updated HELP function XX* XX* Steven List @ Benetics Corporation, Mt. View, CA XX* {cdp,engfocus,idi,oliveb,plx,tolerant}!bene!luke!itkin XX*********************************************************************/ XX/*E*/ XX/*S includes, globals, and defines */ XX/*Page Eject*/ XX#include XX#include XX#include XX#include XX#include XX#include XXstatic int pbrk = 0; XXstruct stat sb; XXvoid icc (); XXvoid copyrec (); XXvoid schwapp (); XX /* ------------------------------------------------------------ */ XX /* Some defines added by the moderator to get it work on 4.2 */ XX /* ------------------------------------------------------------ */ XX#ifdef MOD_HAX XX /* Fifos? We ain't got no steenkin' fifos. */ XX#define S_IFIFO 123450 XX /* "Spelling differences." */ XX#define beep() fprintf (stderr, "\007") XX#define cbreak() crmode() XX /* Our curses doesn't translate keypad keys to single characters. */ XX#define keypad(a, b) /* null */ XX#define KEY_UP '^' XX#define KEY_DOWN 'v' XX#define KEY_LEFT '<' XX#define KEY_RIGHT '>' XX#define KEY_HOME '@' XX#endif /* MOD_HAX */ XX /* ------------------------------------------------------------ */ XX /* Some convenient defines */ XX /* ------------------------------------------------------------ */ XX#define DEL '\177' XX#define HEX 1 XX#define ALPHA 0 XX /* ------------------------------------------------------------ */ XX /* general purpose identification and control variables */ XX /* ------------------------------------------------------------ */ XXchar filename[64]; /* current file being examined */ XXchar record[16][16]; /* record (page) buffer */ XXchar unch_rec[16][16]; /* record before any changes */ XXint zp; /* current input character */ XXint block = 0; /* block size if -b in command */ XXint block_spec; /* true if file is block special */ XXint bytes = 0; /* number of bytes from last read */ XXint char_spec; /* true if file is char special */ XXint debug = 0; /* true if debug is turned on */ XXint dir_spec; /* true if file is directory */ XXint dump = 0; /* nonzero if dump instead of change*/ XXint ebcdic = 0; /* true if -e option */ XXint fifo_spec; /* true if file is fifo */ XXint honly = 0; /* true if dump is to be hex only */ XXint mod = 0; /* true if record has been modified */ XXint pause = 0; /* true if -p option */ XXint rawfile = 0; /* true if file is c/b/p */ XXint reclen = 0; /* record length, if -r */ XXint recno = 0; /* current record (page) number */ XXint stay = 0; /* true if no position change */ XXint swab = 0; /* true if byte swapping is on */ XXint windowed = 0; /* true if windowing - not dump */ XXlong position = 0; /* byte address in file */ XXWINDOW *hexwin = NULL; XXWINDOW *alphawin = NULL; XXWINDOW *errwin = NULL; XX/*S main - control all the work from here */ XX/*H main ************************************************************* XX* XX* main XX* XX* set up the globals, initilize the state, and process the file XX* XX*********************************************************************/ XX/*E*/ XXmain (argc, argv) XXint argc; XXchar *argv[]; XX{ XX extern WINDOW *subwin (); XX extern WINDOW *newwin (); XX#ifdef MOD_HAX XX#else /* use original code... */ XX struct termio asis; XX#endif /* MOD_HAX */ XX register char *cp; /* general purpose char ptr */ XX extern char *gets (); /* get string from stdin */ XX char m = '\017'; /* mask for hex edit */ XX char response[512]; /* general purpose buffer */ XX int z; /* character read in */ XX XX int breakp (); /* signal trapping function */ XX int c; /* current screen column */ XX int change = 0; /* true if cmd line option toggled */ XX int fid; /* file descriptor */ XX int firstfile; /* arg # of first file in cmd line */ XX int h; /* temp for hex edit */ XX int i; /* general purpose loop index */ XX int j; /* general purpose loop index */ XX int r; /* current screen row */ XX int hexc; /* current cursor column in hexwin */ XX long byteaddr; /* planned byte address for 'G' */ XX long size; /* file size in bytes */ XX long status; /* EOF if at end of file or error */ XX extern int optind; /* getopt index into argv */ XX extern char *optarg; /* getopt pointer to opt arg */ XX extern long getnum (); XX extern char *instr (); /* get a string from the cmd line */ XX extern int reset (); /* exit function - reset terminal */ XX /* ------------------------------------------------------------ */ XX /* set up signal handling */ XX /* ------------------------------------------------------------ */ XX if (!dump) signal (SIGINT, breakp); XX signal (SIGTERM, reset); XX /* ------------------------------------------------------------ */ XX /* process command line arguments */ XX /* ------------------------------------------------------------ */ XX while ((i = getopt (argc, argv, "r:dD:b:pxXse")) != EOF) XX { XX switch (i) XX { XX case 'b': /* blocking */ XX block = atoi (optarg); XX if (block < 1 || block > 10240) XX { XX fprintf (stderr, XX "invalid block size: %d\n", block); XX exit (1); XX } XX break; XX case 'd': /* straight dump - no limit */ XX dump = -1; XX break; XX case 'D': /* dump - page count spec */ XX dump = atoi (optarg); XX break; XX case 'e': /* file is ebcdic */ XX ebcdic = 1; XX break; XX case 'p': /* pause between pages - dump */ XX pause = 1; XX break; XX case 'r': /* record length for dump */ XX reclen = atoi (optarg); XX break; XX case 's': /* byte swapping required */ XX swab = 1; XX break; XX case 'x': /* hex dump only */ XX honly = 1; XX break; XX case 'X': XX debug = 1; XX break; XX default: /* uhoh */ XX fprintf (stderr, XX"usage: bpatch [ -b blocksz ] [ -d ] [ -D pagecnt ] [ -e ]\n"); XX fprintf (stderr, XX" [ -p ] [ -r reclen ] [ -s ] [ -x ]\n"); XX exit (1); XX } XX } XX /* ------------------------------------------------------------ */ XX /* check for valid combinations of options */ XX /* ------------------------------------------------------------ */ XX if ((honly || block || reclen || pause ) && !dump) XX { XX fprintf (stderr, "-x|-b|-r|-p requires -d or -D\n"); XX exit (2); XX } XX /* ------------------------------------------------------------ */ XX /* At least one file name must be specified on the cmd line */ XX /* ------------------------------------------------------------ */ XX if (optind == argc) XX { XX fprintf (stderr, "no file name(s) specified\n"); XX exit (2); XX } XX /* ------------------------------------------------------------ */ XX /* set up the screen, if this is an interactive session */ XX /* ------------------------------------------------------------ */ XX if (!dump) XX { XX windowed = 1; XX initscr (); XX nonl (); XX noecho (); XX cbreak (); XX keypad (stdscr, TRUE); XX hexwin = subwin (stdscr, 16, 48, 4, 4); XX keypad (hexwin, TRUE); XX alphawin = subwin (stdscr, 16, 16, 4, 57); XX keypad (alphawin, TRUE); XX errwin = subwin (stdscr, 1, 80, 23, 0); XX#ifdef MOD_HAX XX /* This is not exactly what the original code does, XX but it's good enough. -r$ */ XX raw(); XX#else /* use original code... */ XX ioctl (0, TCGETA, &asis); XX asis.c_cc[VINTR] = '\0'; XX asis.c_iflag &= ~IXON; XX asis.c_iflag &= ~IXOFF; XX asis.c_iflag &= ~IXANY; XX ioctl (0, TCSETA, &asis); XX#endif /* MOD_HAX */ XX } XX /* ------------------------------------------------------------ */ XX /* save the first file's index for backing up later */ XX /* ------------------------------------------------------------ */ XX firstfile = optind; XX /* ------------------------------------------------------------ */ XX /* open the first file */ XX /* ------------------------------------------------------------ */ XX for (fid = -1; fid < 0 && optind < argc;) XX { XX fid = ckfile (argv[optind], &size); XX if (fid < 0) optind++; XX } XX if (fid < 0) XX { XX fprintf (stderr, "could not handle the file list\n"); XX exit (2); XX } XX strncpy (filename, argv[optind], sizeof filename); XX if (block != 0) XX { XX size = -1; XX } XX recno = 0; XX stay = 0; XX mod = 0; XX status = 0; XX /* ------------------------------------------------------------ */ XX /* Until the user exits... */ XX /* ------------------------------------------------------------ */ XX if (!dump) clear (); XX while (status != EOF) XX { XX /* ------------------------------------------------------------ */ XX /* change of location - read and display */ XX /* ------------------------------------------------------------ */ XX if (stay == 0) XX { XX position = lseek (fid, (long)(recno * 256), 0); XX if ((bytes = bread (fid, record, 256, block)) < 0) XX { XX errmsg ("error on reading file %s", filename); XX status = EOF; XX continue; XX } XX if (bytes > 0) XX { XX if (swab) schwapp (record, 256); XX copyrec (record, unch_rec, sizeof record); XX show (bytes, record, filename, size, recno, XX position, m,reclen, dump, ebcdic, swab, XX block, honly); XX } XX mod = 0; XX } XX /* ------------------------------------------------------------ */ XX /* not interactive - keep dumping or open next file */ XX /* ------------------------------------------------------------ */ XX if (dump) XX { XX if ((dump < 0 && bytes == 0) || (--dump == 0)) XX { XX if (optind == argc) status = EOF; XX else XX { XX close (fid); XX fid = -1; XX for (optind++; fid < 0 && optind < argc;) XX { XX fid = ckfile (argv[optind], &size); XX if (fid < 0) optind++; XX } XX strncpy (filename, argv[optind], sizeof filename); XX if (block != 0) XX { XX size = -1; XX } XX recno = 0; XX stay = 0; XX status = lseek (fid, (long)0, 0); XX } XX } XX ++recno; XX /* ------------------------------------------------------------ */ XX /* if pause, beep and wait */ XX /* ------------------------------------------------------------ */ XX if (status != EOF && pause) XX { XX pbrk = 0; XX fprintf (stderr, "\007"); XX gets (response); XX if (pbrk) status = EOF; XX } XX continue; XX } XX /* ------------------------------------------------------------ */ XX /* if we got here, this is an interactive session */ XX /* ------------------------------------------------------------ */ XX stay = 0; XX move (22, 0); XX /* ------------------------------------------------------------ */ XX /* get the user's command */ XX /* ------------------------------------------------------------ */ XX response[0] = EOF; XX mvaddstr (22, 0, "> "); XX clrtoeol (); XX refresh (); XX zp = getch (); XX if (debug && !dump) XX { XX if (isascii (zp) && isprint (zp)) XX errmsg ("command entered is %c", zp); XX else errmsg ("command entered is ^%c (%#x)", zp + '@', zp); XX getch (); XX } XX if (isascii (zp) && isalpha (zp) && islower (zp)) XX zp = toupper (zp); XX /* ------------------------------------------------------------ */ XX /* here we go - what does the user want? */ XX /* ------------------------------------------------------------ */ XX refresh (); XX switch (zp) XX { XX case '!': /* shell escape */ XX echo (); XX move (23,0); XX clrtoeol (); XX addstr ("shell command: "); XX refresh (); XX getstr (response); XX erase (); XX refresh (); XX nl (); XX system (response); XX noecho (); XX nonl (); XX move (23,0); XX standout (); XX addstr (" "); XX standend (); XX clrtoeol (); XX refresh (); XX getch (); XX clear (); XX break; XX case '?': /* HELP */ XX dbg_msg ("Help"); XX dohelp (); XX touchwin (stdscr); XX refresh (); XX stay = 1; XX break; XX case '/': /* search for a string */ XX stay = 1; XX if (mod) XX { XX errmsg ("No write since last change"); XX } XX else search (fid, zp); XX break; XX case '-': /* toggle options */ XX zp = getch (); XX stay = 1; XX change = 0; XX switch (zp) XX { XX case 'a': /* ascii */ XX if (ebcdic) XX { XX dbg_msg ("toggle to ascii"); XX change = 1; XX } XX ebcdic = 0; XX break; XX case 'e': /* ebcdic */ XX if (ebcdic == 0) XX { XX dbg_msg ("toggle to ebcdic"); XX change = 1; XX } XX ebcdic = 1; XX break; XX case 's': /* swab */ XX dbg_msg ("toggle byte swap"); XX change = 1; XX schwapp (record, 256); XX swab = !swab; XX break; XX } XX if (change) XX { XX show (bytes, record, filename, size, XX recno, position, m,reclen, dump, XX ebcdic, swab, block, honly); XX } XX break; XX case '\022': /* redraw screen (^R) */ XX clear (); XX show (bytes, record, filename, size, recno, XX position, m, reclen, dump, ebcdic, XX swab, block, honly); XX stay = 1; XX break; XX XX case '\030': /* toggle debug (^X) */ XX debug = !debug; XX break; XX case '\006': /* new file (^F) */ XX close (fid); XX fid = ckfile (cp = instr (), &size); XX if (fid < 0) XX { XX fid = ckfile (filename, &size); XX } XX else XX { XX strncpy (filename, cp, sizeof filename); XX stay = 0; XX recno = 0; XX } XX break; XX case '\016': /* next file (^N) */ XX if (mod) XX { XX errmsg ("No write since last change"); XX stay = 1; XX } XX else if (optind == (argc - 1)) XX { XX errmsg ("No more files"); XX stay = 1; XX } XX else XX { XX close (fid); XX for (fid = -1, optind++; fid < 0 && optind < argc;) XX { XX fid = ckfile (argv[optind], &size); XX if (fid < 0) optind++; XX } XX if (fid < 0) XX { XX errmsg ("could not handle the file list"); XX reset (0); XX } XX strncpy (filename, argv[optind], sizeof filename); XX stay = 0; XX recno = 0; XX } XX break; XX case '\020': /* prev file (^P) */ XX if (mod) XX { XX errmsg ("No write since last change"); XX stay = 1; XX } XX else if (optind == firstfile) XX { XX errmsg ("No previous file"); XX stay = 1; XX } XX else XX { XX close (fid); XX for (fid = -1, optind--; fid < 0 && optind >= firstfile;) XX { XX fid = ckfile (argv[optind], &size); XX if (fid < 0) optind--; XX } XX if (fid < 0) XX { XX errmsg ("could not handle the file list"); XX reset (0); XX } XX strncpy (filename, argv[optind], sizeof filename); XX stay = 0; XX recno = 0; XX } XX break; XX case '\021': /* quit absolutely (^Q) */ XX status = EOF; XX break; XX case DEL: /* quit with check */ XX case 'Q': /* quit */ XX if (mod) XX { XX errmsg ("No write since last change!"); XX stay = 1; XX } XX else XX { XX status = EOF; XX } XX break; XX case '\\': /* back up 1 record */ XX if (mod) XX { XX errmsg ("No write since last change"); XX stay = 1; XX } XX else XX { XX if (recno > 0) XX { XX --recno; XX stay = 0; XX status = lseek (fid, (long)recno*256, 0); XX if (status < 0) XX { XX move (22, 0); XX clrtoeol (); XX perror (filename); XX errmsg ("error positioning in file"); XX beep (); XX ++recno; XX stay = 1; XX } XX } XX else XX { XX errmsg ("No previous records"); XX beep (); XX stay = 1; XX } XX } XX break; XX case 'F': /* go to first record */ XX if (mod) XX { XX errmsg ("No write since last change"); XX stay = 1; XX } XX else XX { XX status = lseek (fid, (long)0, 0); XX recno = 0; XX } XX break; XX case 'L': /* go to last record */ XX if (mod) XX { XX errmsg ("No write since last change"); XX stay = 1; XX } XX else XX { XX position = lseek (fid, (long)0, 2); XX recno = position / 256; XX j = position % 256; XX if (j == 0) --recno; XX status = lseek (fid, (long)(recno*256), 0); XX } XX break; XX case 'U': /* undo changes */ XX stay = 1; XX mod = 0; XX copyrec (unch_rec, record, sizeof record); XX show (bytes, record, filename, size, recno, XX position, m,reclen, dump, ebcdic, swab, XX block, honly); XX break; XX case 'R': /* re-read record */ XX status = lseek (fid, (long)recno*256, 0); XX break; XX case '0': /* go to some address */ XX case '1': XX case '2': XX case '3': XX case '4': XX case '5': XX case '6': XX case '7': XX case '8': XX case '9': XX if (mod) XX { XX errmsg ("No write since last change"); XX stay = 1; XX } XX else XX { XX byteaddr = getnum (zp, FALSE); XX stay = 1; XX errmsg ("Position to byte %ld", byteaddr); XX if (!rawfile && byteaddr > size) XX { XX errmsg ("Address outside file"); XX beep (); XX } XX else if (byteaddr / 256 != recno) XX { XX recno = byteaddr / 256; XX status = lseek (fid, (long)recno * 256, 0); XX stay = 0; XX } XX } XX break; XX case 'A': /* alpha modify */ XX stay = 1; XX r = c = 0; XX dbg_msg ("edit ascii"); XX if (bytes == 0) break; XX touchwin (stdscr); XX refresh (); XX wmove (alphawin, r, c); XX wrefresh (alphawin); XX while ((z = wgetch (alphawin)) != DEL) XX { XX if (!arrow (z, &r, &c)) XX { XX if (isascii (z)) XX { XX if (isprint (z)) waddch (alphawin, z); XX else waddch (alphawin, '.'); XX if (ebcdic) icc (&z, 1,"AE"); XX record[r][c] = z; XX mod = 1; XX hexc = c * 3; XX wmove (hexwin, r, hexc); XX if (record[r][c] < '\0') XX { XX wprintw (hexwin, "%x%x", XX (record[r][c] >> 4) & m, XX record[r][c] & m); XX } XX else XX { XX wprintw (hexwin, "%02x", record[r][c]); XX } XX wrefresh (hexwin); XX } XX else XX { XX beep (); XX } XX if (c == 15) XX { XX if (r == 15) beep (); XX else XX { XX c = 0; XX ++r; XX } XX } XX else XX { XX c++; XX } XX } XX if (r * 16 + c >= bytes) XX { XX beep (); XX r = (bytes - 1) / 16; XX c = (bytes - 1) % 16; XX } XX wmove (alphawin, r, c); XX wrefresh (alphawin); XX } XX break; XX case 'H': /* hex modify */ XX dbg_msg ("edit hex"); XX stay = 1; XX r = c = hexc = 0; XX if (bytes == 0) break; XX touchwin (stdscr); XX refresh (); XX wmove (hexwin, r, hexc); XX wrefresh (hexwin); XX while ((z = wgetch (hexwin)) != DEL) XX { XX if (!arrow (z, &r, &c)) XX { XX hexc = c * 3; XX z = toupper (z); XX if (!isxdigit (z)) XX { XX beep (); XX } XX else XX { XX waddch (hexwin, tolower (z)); XX wrefresh (hexwin); XX if (z > '9') z -= 7; XX h = (z & m) << 4; XX while (2) XX { XX z = EOF; XX z = getch (); XX if (z == EOF) XX { XX pbrk = 0; XX h = -1; XX break; XX } XX z = toupper (z); XX if (!isxdigit (z)) XX { XX beep (); XX } XX else XX { XX waddch (hexwin, tolower (z)); XX wrefresh (hexwin); XX if (z > '9') z -= 7; XX h |= z & m; XX break; XX } XX } XX if (h < 0) XX { XX wmove (hexwin, r, hexc); XX if (record[r][c] < '\0') XX { XX wprintw (hexwin, "%x%x", XX (record[r][c] >> 4) & m, XX record[r][c] & m); XX } XX else XX { XX wprintw (hexwin, "%02x", record[r][c]); XX } XX wrefresh (hexwin); XX break; XX } XX record[r][c] = z = h; XX mod = 1; XX if (ebcdic) icc (&z, 1,"EA"); XX wmove (alphawin, r, c); XX if (isascii (z) && isprint (z)) XX waddch (alphawin, z); XX else waddch (alphawin, '.'); XX wrefresh (alphawin); XX if (c == 15) XX { XX if (r == 15) beep (); XX else XX { XX c = 0; XX ++r; XX } XX } XX else XX { XX c++; XX } XX } XX } XX if (r * 16 + c >= bytes) XX { XX beep (); XX r = (bytes - 1) / 16; XX c = (bytes - 1) % 16; XX } XX hexc = c * 3; XX wmove (hexwin, r, hexc); XX wrefresh (hexwin); XX } XX break; XX case 'W': /* write record */ XX stay = 1; XX status = lseek (fid, position, 0); XX if (status != position) XX { XX move (22, 0); XX clrtoeol (); XX perror (filename); XX errmsg ("error positioning in file"); XX beep (); XX } XX if (swab) schwapp (record, 256); XX if (write (fid, record, bytes) != bytes) XX { XX errmsg ("error writing to file"); XX sleep (1); XX reset (0); XX exit (0); XX } XX if (swab) schwapp (record, 256); XX mod = 0; XX errmsg ("Record written"); XX break; XX case '\n': /* newline - next page */ XX case '\r': XX if (mod) XX { XX errmsg ("No write since last change"); XX stay = 1; XX } XX else XX { XX ++recno; XX if (!rawfile && (recno * 256) >= size) XX { XX recno--; XX beep (); XX errmsg ("No more records in file"); XX stay = 1; XX } XX else stay = 0; XX } XX break; XX default: XX if (isascii (zp) && isprint (zp)) XX errmsg ("Unknown command: %d", zp); XX else XX errmsg ("Unknown command: %d", zp + '@'); XX beep (); XX stay = 1; XX break; XX } /* end switch zp */ XX refresh (); XX } XX if (windowed) XX { XX reset (0); XX } XX status = close (fid); XX exit (status); XX} XX/*S show - display a record on the terminal */ XX/*H show */ XX/*E*/ XXshow (bytes, record, filename, size, recno, position, XX m,reclen, dump, ebcdic, swab, block, honly) XXint bytes; XXint size; XXint recno; XXint position; XXint m; XXint reclen; XXint dump; XXint ebcdic; XXint swab; XXint honly; XXchar record[16][16]; XXchar *filename; XX{ XX int i; XX int j; XX char s; XX char temp[16]; XX char *look = NULL; XX int row = 0; XX int col = 0; XX if (dump) printf ("\n\n"); XX if (debug) XX { XX getyx (stdscr, row, col); XX move (23,0); XX printw ("show: %d|%d|%s|%d|%d|%d|%#x|%d|%d|%d|%d|%d|%d", XX bytes, record, filename, size, recno, position, XX m, reclen, dump, ebcdic, swab, block, honly); XX move (row, col); XX row = col = 0; XX } XX if (!dump) move (0, 0); XX outstr ("FILE: %s ", filename); XX if (block_spec) outstr ("(block special)"); XX else if (char_spec) outstr ("(character special)"); XX else if (fifo_spec) outstr ("(fifo (named pipe))"); XX else if (dir_spec) outstr ("(directory - %ld)", size); XX else outstr ("(%ld)", size); XX if (ebcdic) outstr (" - EBCDIC"); XX else outstr (" - ASCII"); XX if (swab) outstr (" - SWAP"); XX if (block) outstr (" - BLOCK (%d)", block); XX if (reclen) outstr (" - RECORD (%d)", reclen); XX if (!dump) XX { XX clrtoeol (); XX move (1,0); XX printw ("PAGE: %d (%d)", recno, position); XX clrtoeol (); XX row = 2; XX } XX else XX { XX printf ("\nPAGE: %d (%d)\n", recno, position); XX } XX if (honly) XX { XX look = (char *) record; XX for (j=0;j<256;++j) XX { XX if (*look++ != '\0') XX { XX look = NULL; XX break; XX } XX } XX } XX if (!dump) move (row, col); XX outstr (" x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xa xb xc xd xe xf"); XX outstr (" 0123456789abcdef"); XX if (!dump) XX { XX row += 2; XX move (row, col); XX } XX else XX { XX printf ("\n\n"); XX } XX for (i=0; i<=bytes/16; ++i) XX { XX if (honly && look != NULL) XX { XX i = 16; XX continue; XX } XX if (i*16+1 > bytes) continue; XX outstr ("%02x: ", i); XX for (j=0; j<16; ++j) XX { XX if (i*16+j < bytes) XX { XX if (record[i][j] < '\0') XX outstr ("%x%x ", XX (record[i][j] >> 4) & m, record[i][j] & m); XX else XX outstr ("%02x ", record[i][j]); XX s = ' '; XX if (reclen > 0 && (position+i*16+j+1)%reclen == 0) XX s = ':'; XX if (block > 0 && (position+i*16+j+1)%block == 0) XX { XX if (s == ' ') XX s = '/'; XX else XX s = '%'; XX } XX if (s != ' ') XX outstr ("\b%c", s); XX } XX else XX { XX outstr (" "); XX } XX } XX outstr (" "); XX copyrec (record[i], temp, 16); XX if (ebcdic) icc (temp, 16, "EA"); XX for (j = 0; j < 16 && i*16+j < bytes; ++j) XX { XX if (temp[j] < ' ') outch ('.'); XX else outstr ("%c", temp[j]); XX } XX if (!dump) XX { XX move (++row, col); XX } XX else XX { XX printf ("\n"); XX } XX } XX if (!dump) XX { XX clrtobot (); XX refresh (); XX } XX return; XX} XX/*S breakp - set pbrk on interrupt */ XX/*H breakp */ XX/*E*/ XXint breakp (i) XXint i; XX{ XX int s; XX extern int pbrk; XX s = (int) signal (SIGINT, breakp); XX pbrk = i; XX} XX/*S bread - buffered read */ XX/*H bread */ XX/*E*/ XXint bread (fid, record, want, block) XXint fid, want, block; XXchar *record; XX{ XX int i, j, k; XX int what, bytes, orig; XX static char buffer[10240]; XX static int left, arrow; XX static int flag = 1; XX if (flag) XX { XX left = 0; XX arrow = 0; XX flag = 0; XX } XX if (block == 0) XX return (read (fid, record, want)); XX if (block & 1) ++block; XX orig = what = want; XX while (1) XX { XX if (left < want) XX { XX if (left) XX { XX copyrec (&buffer[arrow], record, left); XX record += left; XX want -= left; XX } XX arrow = 0; XX left = 0; XX if ((bytes = read (fid, buffer, block)) < 0) XX { XX what = bytes; XX break; XX } XX if (bytes == 0) XX { XX what = orig - want; XX break; XX } XX left = bytes; XX } XX else XX { XX copyrec (&buffer[arrow], record, want); XX arrow += want; XX left -= want; XX break; XX } XX } XX return (what); XX} XX/*S schwapp - swap bytes in place */ XX/*H schwapp */ XX/*E*/ XXvoid XXschwapp (ptr, nch) XXregister char *ptr; XXregister int nch; XX{ XX register int i; XX register char c; XX register char *ptra = ptr + 1; XX if (nch & 1) --nch; XX for (i = 0; i < nch; i += 2, ptr += 2, ptra += 2) XX { XX c = *ptr; XX *ptr = *ptra; XX *ptra = c; XX } XX return; XX} XX/*S copyrec - transfer bytes from f to t for nbytes bytes */ XX/*H copyrec */ XX/*E*/ XXvoid XXcopyrec (f, t, nbytes) XXregister char *f; XXregister char *t; XXregister int nbytes; XX{ XX register int i; XX for (i = 0; i < nbytes; i++, f++, t++) *t = *f; XX return; XX} XX/*S ebcdic codes corresponding to ascii - translation table */ XX/*Page Eject*/ XXchar ebcdic_codes[] = { XX0, 0x1, 0x2, 0x3, 0x37, 0x2d, 0x2e, 0x2f, 0x16, XX0x5, 0x25, 0xb, 0xc, 0xd, 0xe, 0xf, 0x10, 0x11, XX0x12, 0x13, 0x3c, 0x3d, 0x32, 0x26, 0x18, 0x19, 0x3f, XX0x27, 0x1c, 0x1d, 0x1e, 0x1f, 0x40, 0x5a, 0x7f, 0x7b, XX0x5b, 0x6c, 0x50, 0x7d, 0x4d, 0x5d, 0x5c, 0x4e, 0x6b, XX0x60, 0x4b, 0x61, 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, XX0xf6, 0xf7, 0xf8, 0xf9, 0x7a, 0x5e, 0x4c, 0x7e, 0x6e, XX0x6f, 0x7c, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, XX0xc8, 0xc9, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, XX0xd8, 0xd9, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, XX0xe9, 0xad, 0xe0, 0xbd, 0x9a, 0x6d, 0x79, 0x81, 0x82, XX0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x91, 0x92, XX0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0xa2, 0xa3, XX0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xc0, 0x4f, 0xd0, XX0x5f, 0x7 }; XX/*S icc - internal code conversion */ XX/*H icc */ XX/*E*/ XXvoid XXicc (buf, nch, type) XXregister char *buf; XXregister int nch; XXchar *type; XX{ XX register int i; XX register int j; XX if (!strcmp (type, "AE")) XX { XX for (i = 0; i < nch; i++, buf++) XX { XX *buf = ebcdic_codes[*buf]; XX } XX } XX else if (!strcmp (type, "EA")) XX { XX for (i = 0; i < nch; i++, buf++) XX { XX for (j = 0; j < 128; j++) XX { XX if (*buf == ebcdic_codes[j]) XX { XX *buf = j; XX break; XX } XX } XX } XX } XX return; XX} XX/*S ckfile - check on existence, accessibility, and type of file */ XX/*H ckfile */ XX/*E*/ XXckfile (filename, sizep) XXchar *filename; XXlong *sizep; XX{ XX register int fid = 0; XX if (access (filename, 0) < 0) XX { XX errmsg ("file not found (%s)", filename); XX fid = -1; XX } XX if (block || pause || dump) XX { XX fid = open (filename, O_RDONLY, 0); XX } XX else XX { XX fid = open (filename, O_RDWR, 0); XX } XX if (fid < 0) XX { XX errmsg ("error opening file %s", filename); XX perror (filename); XX fid = -1; XX } XX else XX { XX errmsg ("File %s opened successfully ", filename); XX if (fstat (fid, &sb) == -1) XX { XX fprintf (stderr, "Can't stat\n"); XX perror (filename); XX fid = -1; XX } XX else XX { XX block_spec = (sb.st_mode & S_IFMT) == S_IFBLK; XX char_spec = (sb.st_mode & S_IFMT) == S_IFCHR; XX fifo_spec = (sb.st_mode & S_IFMT) == S_IFIFO; XX dir_spec = (sb.st_mode & S_IFMT) == S_IFDIR; XX rawfile = block_spec || char_spec || fifo_spec; XX if (rawfile) *sizep = -1; XX else XX { XX if (sb.st_size == 0) XX { XX fprintf (stderr, XX "file %s is empty (zero bytes)\n", XX filename); XX fid = -1; XX } XX *sizep = sb.st_size; XX } XX } XX } XX return fid; XX} XX/*S dohelp - display help text */ XX/*H dohelp */ XX/*E*/ XXdohelp () XX{ XX static char *helptxt[] = { XX "! - execute command in the shell", "a - edit ascii portion", XX "-x - toggle command line option", "f - display first page of file", XX " - display next page", NULL, XX "? - display this help text", "h - edit hexadecimal portion", XX "DEL - quit the program", "l - display last page of file", XX "\\ - display previous page", "nnn - direct addressing", XX "/ - search for ASCII string", "q - quit the program", XX "^f - select named file", "r - reread the current page", XX "^n - select next file", "u - undo all changes to page", XX "^p - select previous file", "w - write out changed page", XX "^q - quit without writing changes", NULL, XX "^r - redraw the screen", NULL, XX "^x - turn on debug", NULL, XX "----------------------------------------------------------------", NULL, XX "direct addressing: nnnS, where nnn = some number, and", NULL, XX " S = type suffix", "b = block (512)", XX NULL, "k = kilobyte (1024)", XX NULL, "l = long word (4)", XX NULL, "p = page (256)", XX NULL, "w = word (2)", XX NULL, " = byte", XX }; XX static int nmsg = sizeof helptxt / sizeof (char *); XX register int row = 0; XX register int i; XX register WINDOW *helpwin; XX extern WINDOW *newwin (); XX helpwin = newwin (LINES, COLS, 0, 0); XX werase (helpwin); XX wrefresh (helpwin); XX wmove (helpwin, 0, 1); XX waddstr (helpwin, XX"---------------------------------- HELP ----------------------------------"); XX for (row = 1, i = 0; i < nmsg; i+=2) XX { XX if (helptxt[i]) XX { XX wmove (helpwin, row, 1); XX waddstr (helpwin, helptxt[i]); XX } XX if (i+1 <= nmsg && helptxt[i+1]) XX { XX wmove (helpwin, row, 41); XX waddstr (helpwin, helptxt[i+1]); XX } XX row++; XX } XX wmove (helpwin, 23, 0); XX wstandout (helpwin); XX waddstr (helpwin, " "); XX wstandend (helpwin); XX wclrtoeol (helpwin); XX wrefresh (helpwin); XX wgetch (helpwin); XX werase (helpwin); XX wrefresh (helpwin); XX delwin (helpwin); XX return; XX} XX/*S reset - reset terminal to original state */ XX/*H reset */ XX/*E*/ XXreset (sig) XXint sig; XX{ XX move (23, 0); XX refresh (); XX endwin (); XX if (sig) fprintf (stderr, "killed with signal %d\n", sig); XX exit (sig); XX} XX/*S arrow - determine if current character is a cursor control key */ XX/*H arrow */ XX/*E*/ XXarrow (k, r, c, type) XXregister int k; XXregister int *r; XXregister int *c; XXregister int type; XX{ XX register ret = 1; XX if (k == KEY_UP) XX { XX if (*r == 0) beep (); XX else (*r)--; XX } XX else if (k == KEY_DOWN || k == '\n') XX { XX if (*r == 15) beep (); XX else (*r)++; XX } XX else if (k == KEY_LEFT || k == '\b' ) XX { XX if (*c == 0) XX { XX if (*r == 0) beep (); XX else XX { XX *c = 15; XX (*r)--; XX } XX } XX else (*c)--; XX } XX else if (k == KEY_RIGHT) XX { XX if (*c == 15) XX { XX if (*r == 15) beep (); XX else XX { XX *c = 0; XX (*r)++; XX } XX } XX else (*c)++; XX } XX else if (k == KEY_HOME) XX { XX *r = *c = 0; XX } XX else XX { XX ret = 0; XX } XX return ret; XX} XX/*S dbg_msg - print a debug message */ XX/*H dbg_msg */ XX/*E*/ XXdbg_msg (msg) XXregister char *msg; XX{ XX if (debug && !dump) XX { XX errmsg (msg); XX } XX return; XX} XX/*S instr - get a character string from the terminal */ XX/*H instr */ XX/*E*/ XXchar * XXinstr () XX{ XX static char buf[512]; XX register int c; XX register char *p = buf; XX register int col = 0; XX move (22, 0); XX clrtoeol (); XX refresh (); XX while ((c = getch ()) != '\r') XX { XX if (isascii (c) && isprint (c)) XX { XX move (22, col); XX addch (c); XX *p++ = c; XX col++; XX } XX else if (c == '\b') XX { XX p--; XX col--; XX move (22, col); XX addch (' '); XX move (22, col); XX } XX refresh (); XX } XX refresh (); XX *p = '\0'; XX return buf; XX} XX/*S getnum - retrieve a number from the terminal */ XX/*H getnum */ XX/*E*/ XXlong XXgetnum (frst_char, hex) XXregister int frst_char; XXregister int hex; XX{ XX static char buf[64]; XX register int c; XX register char *p = buf; XX register int col = 0; XX register long retval = 0; XX move (22, 0); XX clrtoeol (); XX if (frst_char) XX { XX addch (frst_char); XX *p++ = frst_char; XX col++; XX refresh (); XX } XX while ((c = getch()) != '\r') XX { XX if (isascii (c)) XX { XX if ((hex && isxdigit (c)) || isdigit (c)) XX { XX move (22, col); XX addch (c); XX *p++ = c; XX col++; XX } XX else if (c == '\b') XX { XX p--; XX col--; XX move (22, col); XX addch (' '); XX move (22, col); XX } XX else XX { XX break; /* some character typing the value */ XX } XX refresh (); XX } XX } XX *p = '\0'; XX retval = atol (buf); XX mvprintw (22, 0, "%ld", retval); XX switch (c) XX { XX case 'b': /* block - 512 bytes */ XX retval *= 512; XX break; XX case 'k': /* 1024 bytes */ XX retval *= 1024; XX break; XX case 'l': /* long word - 4 bytes */ XX retval *= 4; XX break; XX case 'p': /* page - 256 bytes */ XX retval *= 256; XX break; XX case 'w': /* word - 2 bytes */ XX retval *= 2; XX break; XX case '\r': /* just clear it for display */ XX c = '\0'; XX break; XX } XX printw ("%c -> %ld byte offset", c, retval); XX clrtoeol (); XX refresh (); XX return retval; XX} XX/*S search - look for an ascii string in the file */ XX/*H search */ XX/*E*/ XXsearch (fid) XXregister int fid; XX{ XX long curpos = position; XX long currec = recno; XX char lrecord[sizeof record + 1]; XX register int i; XX register int matched = 0; XX register int srch_len; XX register char *cp = instr (); XX register char *rp; XX int row, col; XX srch_len = strlen (cp); XX copyrec (record, lrecord, sizeof record); XX lrecord[256] = '\0'; XX pbrk = 0; XX wmove (errwin, 0, 0); XX wstandout (errwin); XX wmove (errwin, 0, 40); XX wstandend (errwin); XX wmove (errwin, 0, 1); XX waddstr (errwin, "..searching record "); XX getyx (errwin, row, col); XX do XX { XX mvwprintw (errwin, row, col, "%ld", currec); XX wrefresh (errwin); XX for (i = 0, rp = lrecord, matched = 0; XX !matched && i < 256; XX rp++, i++) XX { XX if (*cp == *rp && !strncmp (cp, rp, srch_len)) XX { XX matched = 1; XX break; XX } XX } XX if (!matched) XX { XX bytes = bread (fid, lrecord, 256, block); XX currec++; XX lrecord[256] = '\0'; XX } XX } while (!pbrk && bytes && !matched); XX if (matched) XX { XX recno = currec; XX stay = 0; XX copyrec (record, unch_rec, sizeof record); XX werase (errwin); XX wrefresh (errwin); XX } XX else XX { XX errmsg ("String %s not found", cp); XX stay = 1; XX } XX return; XX} XXerrmsg (fmt, arg1, arg2, arg3, arg4) XXregister char *fmt; XXregister char *arg1; XXregister char *arg2; XXregister char *arg3; XXregister char *arg4; XX{ XX int y, x; XX if (!dump) XX { XX getyx (stdscr, y, x); XX wmove (errwin, 0, 0); XX wstandout (errwin); XX wprintw (errwin, fmt, arg1, arg2, arg3, arg4); XX wstandend (errwin); XX wclrtoeol (errwin); XX wrefresh (errwin); XX move (y, x); XX } XX else XX { XX fprintf (stderr, fmt, arg1, arg2, arg3, arg4); XX } XX return; XX} XXoutstr (fmt, arg1, arg2, arg3, arg4, arg5, arg6, arg7) XXregister char *fmt; XXregister char *arg1; XXregister char *arg2; XXregister char *arg3; XXregister char *arg4; XXregister char *arg5; XXregister char *arg6; XXregister char *arg7; XX{ XX if (dump) printf (fmt, arg1, arg2, arg3, arg4, arg5, arg6, arg7); XX else printw (fmt, arg1, arg2, arg3, arg4, arg5, arg6, arg7); XX return; XX} XXoutch (ch) XXregister char ch; XX{ XX if (dump) putchar (ch); XX else addch (ch); XX return; XX} @//E*O*F bpatch.c// chmod u=rw,g=rw,o=rw $OUT echo Inspecting for damage in transit... temp=/tmp/sharin$$; dtemp=/tmp/sharout$$ trap "rm -f $temp $dtemp; exit" 0 1 2 3 15 cat > $temp <<\!!! 28 259 1521 README 20 83 485 Makefile 138 990 5412 bpatch.1 1749 5447 35893 bpatch.c 1935 6779 43311 total !!! wc README Makefile bpatch.1 bpatch.c | sed 's=[^ ]*/==' | diff -b $temp - >$dtemp if test -s $dtemp ; then echo "Ouch [diff of wc output]:" cat $dtemp STATUS=1 elif test $STATUS = 0 ; then echo "No problems found." else echo "WARNING -- PROBLEMS WERE FOUND..." fi exit $STATUS