-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathbpatch2
2249 lines (2050 loc) · 52.4 KB
/
bpatch2
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
Subject: v13i074: Binary patch program, ported to 80286 etc.
Newsgroups: comp.sources.unix
Sender: sources
Approved: rsalz@uunet.UU.NET
Submitted-by: rupley!local@ARIZONA.EDU
Posting-number: Volume 13, Issue 74
Archive-name: bpatch2
Neat code and program. Dump or edit files (binary or acsii), displayed by
256-byte records in side-by-side hex and ascii formats. Various other
features (eg, toggled swap within byte pairs). I spent some time tonight
getting bpatch to work well on a Vax (at least one particular Vax) running
BSD4.3 with NFS. The macros in ctype.h gave some problems. The code
attached here compiles both on Microport SysV and BSD4.3, without change,
if the proper Makefile is used. The program appears to work equally in
the two environments. I expect that there should be little problem in
adjusting for other flavors of BSD or SysV.
There are two Makefiles now, for bsd and Sysv. Small changes in README
and the man pages.
John Rupley
uucp: ..{ihnp4 | hao!noao}!arizona!rupley!local
internet: rupley!local@megaron.arizona.edu
telex: 9103508679(JARJAR)
(H) 30 Calle Belleza, Tucson AZ 85716 - (602) 325-4533
(O) Dept. Biochemistry, Univ. Arizona, Tucson AZ 85721 - (602) 621-3929
************************cut here******************************************
# To unbundle, sh this file
echo unbundling README 1>&2
cat >README <<'AlBeRtEiNsTeIn'
BPATCH.C
Original code written by Garry M. Johnson and Steven Lisk.
Neat code and program. Dump or edit files (binary or acsii), displayed
by 256-byte records in side-by-side hex and ascii formats. Various
other features (eg, toggled swap within byte pairs).
Here converted to 80286 (Microport sysV/AT). More details in bpatch.c,
under Change History. Some of the changes also serve to fix code that
appeared to be broken even for a 32-bit environment.
Makefile.sys5 is set for Microport SysV/AT.2.2. The code should compile
under standard SysV environments.
The man pages are changed only slightly from the original distribution.
The code compiles on a Vax running BSD4.3, with Makefile.bsd, of
course. Testing was with an AT compatible logged in as a terminal,
with setenv TERM vt100. There may be curses/terminal problems for
other environments. A terminal which was an adm3a equivalent was ok.
Beware of using the shell escape feature!
Like the previous authors, I would appreciate learning of further
changes and improvements in the code:
John Rupley
uucp: ..{ihnp4 | hao!noao}!arizona!rupley!local
internet: rupley!local@megaron.arizona.edu
telex: 9103508679(JARJAR)
(H) 30 Calle Belleza, Tucson AZ 85716 - (602) 325-4533
(O) Dept. Biochemistry, Univ. Arizona, Tucson AZ 85721 - (602) 621-3929
+++++++++++++++++++++original distribution README+++++++++++++++++++++++
>Herewith find BPATCH - a marvelously utile utility. While not of
>my original creation, I have been given permission to place in the
>public domain. I have made substantial modifications to the original
>source given to me. Specifically I cleaned it up a bit and made it
>work with SVR2 curses. Personally, I think it's pretty neat.
>
>OK - for those of you who may scream by now "WHAT THE HELL IS IT ALREADY?"
>I respond that it is a binary file editor and dump utility! That's
>right! You can dump your file in the nicely laid out side-by-side
>hex and ascii format or you can actually EDIT it at your terminal!
>Yes, I have seen the BED editor that came across the network.
>Unfortunately, it converted the entire file before and after editing.
>Bpatch, on the other hand, works with one 256 byte page at a time.
>It is marvelously useful for looking at things like raw disk UNIFY
>databases and even raw disks! While the man page may not be absolutely
>up to date, the online help is. Try the question mark (?) command.
>
>As always, I would love to hear about bugs/changes/enhancements/requests.
> Steven List @ Benetics Corporation, Mt. View, CA
> Just part of the stock at "Uncle Bene's Farm"
> {cdp,engfocus,idi,oliveb,opusys,plx,pyramid,tolerant}!bene!luke!itkin
>
>Addition by the moderator:
>I have added code, surrounded by #ifdef MOD_HAX, that gets bpatch
>(barely?) working on my 4.2 system. I would be very interested in
>publishing a set of diffs that's less of a hack. Oh yeah: I also
>wrote the Makefile.
> /Rich $alz
+++++++++++++++++++++end of original distribution README++++++++++++++++++++
AlBeRtEiNsTeIn
echo unbundling Makefile.bsd 1>&2
cat >Makefile.bsd <<'AlBeRtEiNsTeIn'
# This may have to change on your system.
# You may have to fiddle with various combinations of curses, termcap,
# terminfo, etc. Good luck!
LIBS = -lcurses -ltermcap
#LIBS = -ltermlib
#LIBS = -lterminfo
#for sysV
#LIBS = -lcurses
# However you need getopt.
#GETOPT = -lgetopt
#not for sysV! (nor for some BSD)
#GETOPT =
# If you're running on a 4.[23] system, you probably want this.
WORK = -DMOD_HAX
#sysV
#WORK =
#BSD or thereabouts
CFLAGS = -O $(WORK)
#Microport sysV/AT, large model, for sdb debugger
#CFLAGS = -g -Ml
bpatch: bpatch.o
$(CC) -o bpatch $(CFLAGS) bpatch.o $(GETOPT) $(LIBS)
install:
@echo Use cp to put things where you want them
AlBeRtEiNsTeIn
echo unbundling Makefile.sys5 1>&2
cat >Makefile.sys5 <<'AlBeRtEiNsTeIn'
# This may have to change on your system.
# You may have to fiddle with various combinations of curses, termcap,
# terminfo, etc. Good luck!
#LIBS = -lcurses -ltermcap
#LIBS = -ltermlib
#LIBS = -lterminfo
#for sysV
LIBS = -lcurses
# However you need getopt.
#GETOPT = -lgetopt
#not for sysV! (nor for some BSD)
#GETOPT =
# If you're running on a 4.[23] system, you probably want this.
#WORK = -DMOD_HAX
#sysV
WORK =
#BSD or thereabouts
#CFLAGS = -O $(WORK)
#Microport sysV/AT, large model, for sdb debugger
CFLAGS = -g -Ml
bpatch: bpatch.o
$(CC) -o bpatch $(CFLAGS) bpatch.o $(GETOPT) $(LIBS)
install:
@echo Use cp to put things where you want them
AlBeRtEiNsTeIn
echo unbundling bpatch.1 1>&2
cat >bpatch.1 <<'AlBeRtEiNsTeIn'
.TH "bpatch" "1" "Benetics Local"
.UC 4
\" .if t .nr LL 7i
\" .if t .nr IN .8i
\" .if n .nr LL 70
\" .if n .nr IN 8
\" .fi
\" .ad b
.SH NAME
bpatch - binary patch and dump file utility
.SH SYNOPSIS
bpatch [ -b blksize ] [ -d ] [ -D pagecnt ] [ -e ] [ -p ] [ -r reclen ] [ -s ] [ -x ] file...
.SH DESCRIPTION
\fIBpatch\fR allows the viewing and/or modification of files, independent of
file type (text, executable, data file, and so forth). \fIBpatch\fR
allows the data to either be examined at the terminal, dumped to a print
device or file, or edited in the general manner of \fIvi(1)\fR. The
data in the file is dumped or displayed in \fIpages\fR of 256 bytes.
.SS Options
.IP "-b blksize" 12
The \fI-b\fR option specifies the blocksize of the data file. This is used
primarily with tapes, and is allowed only with one of the dump (\fI-d\fR
or \fI-D\fR) options. When this option is specified, the file is opened
in readonly mode.
.IP "-d" 12
The \fI-d\fR option indicates that a dump (no terminal manipulation) is
to be performed. The entire file will be dumped to standard output. No
editing of the data is allowed and the file is opened in readonly mode.
<DEL> interrupts a continuous display, producing a pause after the
current record is displayed; at this point, a second <DEL> exits and
and other character begins display of the next file.
.IP "-D pagecnt" 12
The \fI-D\fR option is similar to the \fI-d\fR option, with the
following exception: the pagecnt argument limits the dump to the
specified number of \fIpages\fR.
.IP "-e" 12
The \fI-e\fR option indicates that the file contains EBCDIC data and
should be converted in the character portion of the dump.
.IP "-p" 12
Used with one of the \fIdump\fR options, this option causes the program
to pause between \fIpages\fR. The program will then wait for the user
to press either the \fIreturn\fR key to continue, or the \fIDEL\fR (or
\fIrubout\fR) key to stop the dump.
.IP "-r reclen" 12
The \fI-r\fR option indicates the record length of the data within the
dump. When specified, this option causes \fIbpatch\fR to place a colon
(:) between the last byte of one record and the first byte of the next.
.IP "-s" 12
This option turns on the byte swap option. It may be toggled dynamically
during execution (see \fI-x\fP under Commands below).
.IP "-x" 12
This option specifies the suppression of pages that contain only NUL
characters. The result is that only the page header (name and page
number) will appear for such a page. This option may only be used with
one of the dump options.
.SS Arguments
.IP file 12
Any number of files may be specified.
.SS Commands
All commands are valid only in the non-dump, interactive mode. Commands
may be entered in either upper or lower case. Commands of the form '^x'
indicate that the control character \fIx\fR is to be entered.
.P
All commands that request movement within a file or between files cannot
be executed if any changes have been made. To proceed in this case, the
user must either enter the \fIw\fR command, the \fIu\fR command, or the
\fIr\fR command.
.P
Requesting a next or previous file when there is no such will cause the
issuance of an error message.
.P
Note that certain commands allow/require either some text or numeric
value. In those cases, the user should type in characters and end the
string with either a <cr> or <DEL>.
.IP ? 6
Display the help screen. The help screen will remain until the user
either redraws the screen (see \fI^r\fR) or changes pages or files.
.IP ! 6
Execute the following command in the shell.
.IP backslash 6
Display the previous page.
.IP <cr> 6
Display the next page.
.IP DEL 6
Quit the program if no changes have been made.
.IP / 6
This command initiates an ASCII search. The text entered on the command
line will be used as a search string, and the file will be searched
starting with the current page. When the string is found, the page
containing the string will be displayed. If the string is not found, an
apapropriate message will be displayed.
.IP ^f 6
Open a named file whose name will be entered on the command line and
followed either by <cr> or DEL.
.IP ^n 6
Open the next file and display the first page.
.IP ^p 6
Open the previous file and display the first page.
.IP ^q 6
Quit without writing current changes.
.IP ^r 6
Redraw the screen.
.IP NNN 6
Entering a numeric value requests that the specified page be displayed.
.IP -x 6
Toggle the command line option represented by \fIx\fR:
.RS 12
.IP a 6
Toggle display to ascii (assume data is ascii).
.IP e 6
Toggle display to dbcdic (assume data is ebcdic).
.IP s 6
Toggle byte swap.
.RE
.IP a 6
Edit the ASCII display. End edits by pressing the DEL key. All other
characters will be treated as valid input. Cursor movement keys (arrows
and home) allow movement within the edit window. Nonprinting
characters are displayed as dot (.) in this window.
.IP f 6
Display the first page in the current file.
.IP g 6
Display the page containing the byte address typed in following the command.
.IP h 6
Edit the HEXADECIMAL display. End edits by pressing DEL key. Cursor
movement keys (arrows and home) allow movement within the edit window.
Two keystrokes are required to modify a byte, and both must be valid
hexadecimal values (0-9 and a-f). To cancel a change after typing one
character, press DEL.
.IP l 6
Display the last page in the current file.
.IP q 6
Quit the file. A warning will be issued if any changes have been made
but not written out.
.IP r 6
Reread the current page.
.IP u 6
Undo all changes to the current page.
.IP w 6
Write out the current page.
.SH "SEE ALSO"
od(1)
AlBeRtEiNsTeIn
echo unbundling bpatch.c 1>&2
cat >bpatch.c <<'AlBeRtEiNsTeIn'
/*T bpatch - A binary file patch/dump utility */
/*S Introduction */
/*F bpatch ***********************************************************
* bpatch
* by Garry M Johnson - 09/17/84
* (C) Copyright 1984, 1985
*
* Change History:
*
* 11/29/87 - PORT TO 80286 SYSTEM (MICROPORT SYSV/AT, 2.2)
*
* -> sorted out nonportable int -ne char * and int -ne long (ever-
* annoying problems for the 286); the changes should not have broken
* the code for 32-bit int -eq char * machines; indeed, some of the
* changes fix apparently broken code
* -> calls to outstr() now pass only a string address; where values are to
* be displayed, they are entered into the string with a prior
* sprintf();
* -> calls to errmsg() handled as for outstr(), except there is a second
* parameter, "sleep_time", to specify the length of a sleep after message
* display; this is *not* implemented; call of sleep dumps core -- signal
* handling problem??
* -> after "windowed" is set, forced all exit()'s into passing first
* through reset() and likewise everywhere follow reset() with immediate
* exit()
* -> in the segment following "not interactive - keep dumping ...",
* repaired broken code that controlled flow for the -d and -D options;
* allow DEL interrupt of continuous dump of long file, in order to
* quit or go to next file
* -> in reset(), ioctl'd terminal to be as at entry
* -> in arrow(), added vi-like cursor control
* -> cleaned up code for formats where specification did not agree with
* declared type for variable; same for function parameter lists; checked
* casts and conversions to/from long; miscellaneous general cleanup
* of the code
* -> cleaned up the display, but lots left to be done
*
*
* REMAINING MINOR BUGS AND INFELICITIES AND WISH LIST --
*
* -> spawn a properly working interactive shell; probably just need
* a fork and a full reset() under "!" option
* -> easy repeat of string search to find next occurrence; highlight
* string positions in the display; put edit cursor at start of string
* -> in debug mode, allow backspace over command entered, to cancel it
* -> errmsg() display not nice, if have several messages output in
* sequence; no pause in errmsg() (sleep not working?)
* -> column under pointer not always erased (local clrtoeol problem ??)
* -> irregular passing of pointers to record and related arrays
* -> most of the external vars should be local to main()
* -> signal handling?
* -> file closing?
*
* COMMENTS --
*
* -> thanks to Steven List and Garry Johnson for a very useful program;
* it's a nice way for one who is lazy to avoid a lot of compilation
* when what is wanted is a small change in data; the code is easy to
* read -- again compliments to the authors;
* -> these modifications are hacks of the previous authors' code; the
* modified program has not been hardened, although I tried to check
* its operation under limit conditions; please be careful in using it
* -> like the authors, I would appreciate receiving a copy of any
* improvements
*
* John Rupley, Dept. Biochemistry, Univ. Arizona, Tucson, AZ 85721
* {ihnp4 | hao!noao}!arizona!rupley!local or rupley!local@megaron.arizona.edu
*
******************************************************************************
*
* 03/05/86 - added further terminal independence
* added use of ioctl (see main and mstdin)
* added -D versus -d command line option
* added use of standard getopt
* cleaned up code, eliminated function "ikf"
* added original versions of ezlib functions, such as
* icc, setterm, cm, mstdin, erase, length, move
* added ^R, ^Q, ^N, and ^P commands
* added ^F, !, and ^X (-X) commands
* changed name to "bpatch"
* added direct address command (g)
* added ASCII search capability
* 07/07/86 - converted to use curses
* modified direct addressing to use suffixes
* updated HELP function
*
* Steven List @ Benetics Corporation, Mt. View, CA
* {cdp,engfocus,idi,oliveb,plx,tolerant}!bene!luke!itkin
*********************************************************************/
/*E*/
/*S includes, globals, and defines */
/*Page Eject*/
#include <curses.h>
#include <fcntl.h>
#include <signal.h>
#include <ctype.h>
#include <sys/types.h>
#include <sys/stat.h>
static int pbrk = 0;
struct stat sb;
void icc ();
void copyrec ();
void schwapp ();
/* added declarations, mostly for cleanliness */
extern long lseek();
extern long atol();
extern char *strncpy();
extern void exit();
extern unsigned sleep(); /* signal problems ??? if sleep called */
extern void perror();
/* set up for calls to outstr and errmsg, etc, */
/* by use of sprintf to fill outbuf */
char outbuf[512];
/* ------------------------------------------------------------ */
/* Some defines added by the moderator to get it work on 4.2 */
/* ------------------------------------------------------------ */
#ifdef MOD_HAX
/* Fifos? We ain't got no steenkin' fifos. */
/* #define S_IFIFO 123450 */
/* "Spelling differences." */
#define beep() fprintf (stderr, "\007")
/* #define cbreak() crmode() */
/* Our curses doesn't translate keypad keys to single characters. */
#define keypad(a, b) /* null */ /* orig defines */
#define KEY_UP '\0' /* '^' */ /* by MOD_HAX */
#define KEY_DOWN '\0' /* 'v' */ /* not portable */
#define KEY_LEFT '\0' /* '<' */
#define KEY_RIGHT '\0' /* '>' */
#define KEY_HOME '\0' /* '@' */
#endif /* MOD_HAX */
/* vi-like cursor control = vi keys, as control characters */
/* this is a hack, and I hope does not interfere with keypad() */
#define VI_UP ('K' - 0x40)
#define VI_DOWN ('J' - 0x40)
#define VI_LEFT ('H' - 0x40)
#define VI_RIGHT ('L' - 0x40)
#define VI_HOME ('G' - 0x40)
#define SLEEP_TIME (unsigned )0 /* a small pause after errmsg */
/* does not work -- signals?? */
/* ------------------------------------------------------------ */
/* Some convenient defines */
/* ------------------------------------------------------------ */
#define DEL '\177'
#define HEX 1
#define ALPHA 0
/* ------------------------------------------------------------ */
/* general purpose identification and control variables */
/* ------------------------------------------------------------ */
char filename[64]; /* current file being examined */
char record[16][16]; /* record (page) buffer */
char unch_rec[16][16]; /* record before any changes */
int zp; /* current input character */
int block = 0; /* block size if -b in command */
int block_spec; /* true if file is block special */
int bytes = 0; /* number of bytes from last read */
int char_spec; /* true if file is char special */
int debug = 0; /* true if debug is turned on */
int dir_spec; /* true if file is directory */
int dump = 0; /* nonzero if dump instead of change */
int Dump = 0; /* store of value with -D option */
int ebcdic = 0; /* true if -e option */
int fifo_spec; /* true if file is fifo */
int honly = 0; /* true if dump is to be hex only */
int mod = 0; /* true if record has been modified */
int pause_opt = 0; /* true if -p option */
int rawfile = 0; /* true if file is c/b/p */
int reclen = 0; /* record length, if -r */
int recno = 0; /* current record (page) number */
int stay = 0; /* true if no position change */
int swab_opt = 0; /* true if byte swapping is on */
int windowed = 0; /* true if windowing - not dump */
long position = 0; /* byte address in file */
WINDOW *hexwin = NULL;
WINDOW *alphawin = NULL;
WINDOW *errwin = NULL;
#ifdef MOD_HAX
#else /* use original code... */
/* plus some more for restoring terminal function */
struct termio asis, aswas;
#endif /* MOD_HAX */
/*S main - control all the work from here */
/*H main *************************************************************
*
* main
*
* set up the globals, initilize the state, and process the file
*
*********************************************************************/
/*E*/
main (argc, argv)
int argc;
char *argv[];
{
extern WINDOW *subwin ();
extern WINDOW *newwin ();
register char *cp; /* general purpose char ptr */
extern char *gets (); /* get string from stdin */
char m = '\017'; /* mask for hex edit */
char response[512]; /* general purpose buffer */
int z; /* character read in */
int breakp (); /* signal trapping function */
int c; /* current screen column */
int change = 0; /* true if cmd line option toggled */
int fid; /* file descriptor */
int firstfile; /* arg # of first file in cmd line */
int h; /* temp for hex edit */
int i; /* general purpose loop index */
int j; /* general purpose loop index */
int r; /* current screen row */
int hexc; /* current cursor column in hexwin */
long byteaddr; /* planned byte address for 'G' */
long size; /* file size in bytes */
long status; /* EOF if at end of file or error */
extern int optind; /* getopt index into argv */
extern char *optarg; /* getopt pointer to opt arg */
extern long getnum ();
extern char *instr (); /* get a string from the cmd line */
extern int reset (); /* exit function - reset terminal */
/* ------------------------------------------------------------ */
/* set up signal handling */
/* ------------------------------------------------------------ */
if (!dump) signal (SIGINT, breakp);
signal (SIGTERM, reset);
/* ------------------------------------------------------------ */
/* process command line arguments */
/* ------------------------------------------------------------ */
while ((i = getopt (argc, argv, "r:dD:b:pxXse")) != EOF)
{
switch (i)
{
case 'b': /* blocking */
block = atoi (optarg);
if (block < 1 || block > 10240)
{
fprintf (stderr,
"invalid block size: %d\n", block);
exit (1);
}
break;
case 'd': /* straight dump - no limit */
dump = -1;
break;
case 'D': /* dump - page count spec */
dump = atoi (optarg);
Dump = dump;
break;
case 'e': /* file is ebcdic */
ebcdic = 1;
break;
case 'p': /* pause between pages - dump */
pause_opt = 1;
break;
case 'r': /* record length for dump */
reclen = atoi (optarg);
break;
case 's': /* byte swapping required */
swab_opt = 1;
break;
case 'x': /* hex dump only */
honly = 1;
break;
case 'X':
debug = 1;
break;
default: /* uhoh */
fprintf (stderr,
"usage: bpatch [ -b blocksz ] [ -d<ump> ] [ -D pagecnt ] [ -e<bcdic> ]\n");
fprintf (stderr,
" [ -p<ause> ] [ -r reclen ] [ -s<wap bytes> ] [ -x<only> ]\n");
exit (1);
}
}
/* ------------------------------------------------------------ */
/* check for valid combinations of options */
/* ------------------------------------------------------------ */
if ((honly || block || reclen || pause_opt ) && !dump)
{
fprintf (stderr, "-x|-b|-r|-p requires -d or -D\n");
exit (2);
}
/* ------------------------------------------------------------ */
/* At least one file name must be specified on the cmd line */
/* ------------------------------------------------------------ */
if (optind == argc)
{
fprintf (stderr, "no file name(s) specified\n");
exit (2);
}
/* ------------------------------------------------------------ */
/* set up the screen, if this is an interactive session */
/* ------------------------------------------------------------ */
if (!dump)
{
windowed = 1;
initscr ();
nonl ();
noecho ();
cbreak ();
keypad (stdscr, TRUE);
hexwin = subwin (stdscr, 16, 48, 4, 4);
keypad (hexwin, TRUE);
alphawin = subwin (stdscr, 16, 16, 4, 57);
keypad (alphawin, TRUE);
errwin = subwin (stdscr, 1, 80, 23, 0);
#ifdef MOD_HAX
/* This is not exactly what the original code does,
but it's good enough. -r$ */
raw();
#else /* use original code... */
ioctl (0, TCGETA, &asis);
aswas = asis; /* save termio stuff for later restore */
asis.c_cc[VINTR] = '\0';
asis.c_iflag &= ~IXON;
asis.c_iflag &= ~IXOFF;
asis.c_iflag &= ~IXANY;
ioctl (0, TCSETA, &asis);
#endif /* MOD_HAX */
}
/* ------------------------------------------------------------ */
/* save the first file's index for backing up later */
/* ------------------------------------------------------------ */
firstfile = optind;
/* ------------------------------------------------------------ */
/* open the first file */
/* ------------------------------------------------------------ */
for (fid = -1; fid < 0 && optind < argc;)
{
fid = ckfile (argv[optind], &size);
if (fid < 0) optind++;
}
if (fid < 0)
{
fprintf (stderr, "could not handle the file list\n");
reset (0);
exit (2);
}
strncpy (filename, argv[optind], sizeof filename);
if (block != 0)
{
size = -1;
}
recno = 0;
stay = 0;
mod = 0;
status = 0;
/* ------------------------------------------------------------ */
/* Until the user exits... */
/* ------------------------------------------------------------ */
if (!dump) clear ();
while (status != EOF)
{
/* ------------------------------------------------------------ */
/* change of location - read and display */
/* ------------------------------------------------------------ */
if (stay == 0)
{
position = lseek (fid, ((long )recno) * 256, 0);
if ((bytes = bread (fid, record, 256, block)) < 0)
{
sprintf(outbuf, "error on reading file %s", filename);
errmsg (outbuf, SLEEP_TIME);
status = EOF;
continue;
}
if (bytes > 0)
{
if (swab_opt) schwapp (record, 256);
copyrec (record, unch_rec, sizeof record);
if (!dump) clear ();
show (bytes, record, filename, size, recno,
position, m,reclen, dump, ebcdic, swab_opt,
block, honly);
}
mod = 0;
}
/* ------------------------------------------------------------ */
/* not interactive - keep dumping or open next file */
/* ------------------------------------------------------------ */
/* major changes in control of flow */
/* first records of multiple-files now dump */
/* core is not dumped at end of filelist */
/* can break with DEL into a long dump */
if (dump)
{
if (dump > 0) dump--;
if ((dump < 0 && bytes == 0) || dump == 0)
{
if (Dump) dump = Dump;
if (optind == argc) status = EOF;
else
{
close (fid);
fid = -1;
for (optind++; fid < 0 && optind < argc;)
{
fid = ckfile (argv[optind], &size);
if (fid < 0) optind++;
}
if (fid < 0)
{
status = EOF;
continue;
}
strncpy (filename, argv[optind], sizeof filename);
if (block != 0)
{
size = -1;
}
recno = 0;
stay = 0;
status = lseek (fid, (long)0, 0);
}
}
else
{
++recno;
}
/* ------------------------------------------------------------ */
/* if pause, beep and wait */
/* ------------------------------------------------------------ */
/* settings to bypass show() */
/* and go to read of next file */
/* if type DEL during file display */
if (status != EOF && (pause_opt || pbrk))
{
if (pbrk)
{
bytes = 0;
dump = -1;
stay = 1;
}
pbrk = 0;
fprintf (stderr, "\007");
gets (response);
if (pbrk) status = EOF;
}
continue;
}
/* ------------------------------------------------------------ */
/* if we got here, this is an interactive session */
/* ------------------------------------------------------------ */
stay = 0;
/* ------------------------------------------------------------ */
/* get the user's command */
/* ------------------------------------------------------------ */
response[0] = EOF;
mvaddstr (22, 0, "> ");
clrtoeol ();
refresh ();
zp = getch ();
if (debug && !dump)
{
/* cheap cleanup of errwin */
errmsg ("", SLEEP_TIME);
if (isascii (zp) && isprint (zp))
{
sprintf (outbuf, "command entered is %c", (char )zp);
errmsg (outbuf, 0);
}
else
{
sprintf (outbuf, "command entered is ^%c (%#x)", (char )zp + '@', zp);
errmsg (outbuf, 0);
}
getch ();
}
/* assume normal ascii character sequence */
if ((zp >= 'a') && (zp <= 'z'))
zp = zp - 0x20;
/* ------------------------------------------------------------ */
/* here we go - what does the user want? */
/* ------------------------------------------------------------ */
refresh ();
errmsg ("", SLEEP_TIME);
switch (zp)
{
case '!': /* shell escape */
echo ();
move (23,0);
clrtoeol ();
addstr ("shell command: ");
refresh ();
getstr (response);
clear ();
nl ();
system (response);
noecho ();
nonl ();
move (23,0);
standout ();
addstr (" <Press any key> ");
standend ();
clrtoeol ();
refresh ();
getch ();
break;
case '?': /* HELP */
clear ();
dbg_msg ("Help");
dohelp ();
break;
case '/': /* search for a string */
stay = 1;
if (mod)
{
errmsg ("No write since last change", SLEEP_TIME);
}
else search (fid);
break;
case '-': /* toggle options */
zp = getch ();
stay = 1;
change = 0;
switch (zp)
{
case 'a': /* ascii */
if (ebcdic)
{
dbg_msg ("toggle to ascii");
change = 1;
}
ebcdic = 0;
break;
case 'e': /* ebcdic */
if (ebcdic == 0)
{
dbg_msg ("toggle to ebcdic");
change = 1;
}
ebcdic = 1;
break;
case 's': /* swab */
dbg_msg ("toggle byte swap");
change = 1;
schwapp (record, 256);
swab_opt = !swab_opt;
break;
}
if (change)
{
clear ();
show (bytes, record, filename, size,
recno, position, m,reclen, dump,
ebcdic, swab_opt, block, honly);
}
break;
case '\022': /* redraw screen (^R) */
clear ();
show (bytes, record, filename, size, recno,
position, m, reclen, dump, ebcdic,
swab_opt, block, honly);
stay = 1;
break;
case '\030': /* toggle debug (^X) */
debug = !debug;
stay = 1;
break;
case '\006': /* new file (^F) */
close (fid);
fid = ckfile (cp = instr (), &size);
if (fid < 0)
{
fid = ckfile (filename, &size);
}
else
{
strncpy (filename, cp, sizeof filename);
stay = 0;
recno = 0;
}
break;
case '\016': /* next file (^N) */
if (mod)
{
errmsg ("No write since last change", SLEEP_TIME);
stay = 1;
}
else if (optind == (argc - 1))
{
errmsg ("No more files", SLEEP_TIME);
stay = 1;
}
else
{
close (fid);
for (fid = -1, optind++; fid < 0 && optind < argc;)
{
fid = ckfile (argv[optind], &size);
if (fid < 0) optind++;
}
if (fid < 0)
{
errmsg ("could not handle the file list", SLEEP_TIME);
reset (0);
exit (0);
}
strncpy (filename, argv[optind], sizeof filename);
stay = 0;
recno = 0;
}
break;
case '\020': /* prev file (^P) */
if (mod)
{
errmsg ("No write since last change", SLEEP_TIME);
stay = 1;
}
else if (optind == firstfile)
{
errmsg ("No previous file", SLEEP_TIME);
stay = 1;
}
else
{
close (fid);
for (fid = -1, optind--; fid < 0 && optind >= firstfile;)
{
fid = ckfile (argv[optind], &size);
if (fid < 0) optind--;
}
if (fid < 0)
{
errmsg ("could not handle the file list", SLEEP_TIME);
reset (0);
exit (0);
}
strncpy (filename, argv[optind], sizeof filename);
stay = 0;
recno = 0;