	.mcall	.MODULE
	.MODULE SNOOP,comment=<Device snoop>,release=V09,version=07

;**************************************************************;
;                                                              ;
;   Copyright (c) 1987, 1988      Bob Schor                    ;
;                                 Eye and Ear Hospital         ;
;                                 230 Lothrop St.              ;
;                                 Pittsburgh, PA   15213       ;
;                                                              ;
; All rights reserved.  May not be copied without this notice. ;
;                                                              ;
;**************************************************************;

;**************************************************************;
;                                                              ;
;   Copyright (c) 1989            Bob Schor                    ;
;                                 Eye and Ear Institute        ;
;                                 203 Lothrop St.              ;
;                                 Pittsburgh, PA   15213       ;
;                                                              ;
; All rights reserved.  May not be copied without this notice. ;
;                                                              ;
;**************************************************************;

;Search for and announce device blocks matching pattern

;b schor	oct, 1987

;modifications --
;	oct, 1987	First incarnation, from RKCOPY v7.10
;	oct, 1987	Incorporate multiple snoop options (SNOOP 0 .. 3)
;	nov, 1987	Works with multiple devices, files
;	nov, 1987	Improved output for sub-device files
;	dec, 1987	Minor format improvements
;	nov, 1988	Sub-devices, traverse directory chain to find size
;	dec, 1988	Debug made 0/1 choice, always defined
;			Bug fix, prevent block number wrap-around (DU:)
;	jul, 1989	Psects $CODE and $DATA added


;define our .psects before calling SUMAC to force ours low

	.psect	$code	ro,i,lcl,rel,con
	.psect	$data	rw,d,lcl,rel,con

;uses SUMAC for structured macro code

	.library	/lib:sumac/	;use external macro definition file

	.mcall	SUMAC
	SUMAC				;initialization macro

	.dsabl	gbl			;if undefined symbol, force error


HEAD	sysmac, <system macros>
	.mcall	.PRINT			;to announce identification
	.mcall	.EXIT			;return to RT-11 on errors
	.mcall	.READ, .WAIT, .CLOSE
	.mcall	.GTLIN, .DSTATUS, .CSISPC
	.mcall	.LOOKUP, .SPFUN


HEAD	condit, <assembly conditionals>
;	debug	=	1		;define for debugging code
.iif ndf	debug	debug	=	0
.iif ne		debug	debug	=	1


HEAD	const, <constant declarations>
	succs$	=	1		;success, no errors
	error$	=	4		;error
	fatal$	=	10		;fatal error

	blksiz	=	^d256		;block size, in words
	blfact	=	10		;blocking factor
	bufsiz	=	blfact*blksiz	;total buffer size
	maxch	=	20		;possibly-available channels

	jsw	=	44		;location of Job Status Word
	edit$	=	20		;to turn off Single Line Editor

	errbyt	=	52		;error byte in monitor
	userrb	=	53		;user error byte

;devices supporting variable-sized records return varsz$ after .DSTATUS

	varsz$	=	400		;handler supports variable-size volume

;devices supporting variable-size records -- byte returned by .DSTATUS

	spsize	=	373		;special function to return size
	

	.psect	$data

HEAD	devrec, <device records>

dv.chn:	.word	-1			;channel number
dv.blk:	.word	0			;current block number
dv.eof:	.word	0			;end-of-file flag, 0 if false
dv.sta:	.word	0			;status information
	.word	0			;handler size, not needed
dv.lod:	.word	0			;load address, <>0 if handler resident
dv.siz:	.word	0			;size of disk, in blocks
dv.nam:	.blkb	20			;device name goes here

HEAD	var, <Miscellaneous variables>
option:	.word	0			;holds processing option number
sno.op:	.word	0			;snoop option number
stack:	.word	0			;saves stack around .CSISPC call
filspc:					;file specs, from csi
	.blkw	3*5			;other output dbs
dv.db:	.blkw	4			;disk has input slot
	.blkw	5*4			;other input dbs
defalt:	.word	0, 0, 0, 0		;default i/o extensions

modnam:	.NLCSI				;generates .asciz module string
reply:	.blkb	^d 61			;space for .GTLIN reply
	.even

emtblk:	.blkw	10			;emt argument block


	.psect	$code

HEAD	iosubs, <low level i/o routines>

PROCED	getline, <get line from terminal>
;this routine incorporates a subtle "bug/feature" in RT-11.  If SL is on and
;.GTLIN is used in non-prompt mode, after a .PRINT terminated in <200>,
;the output from the .PRINT is suppressed.  The solution is to turn
;off SL around the .GTLIN call.

	bis	#edit$, @#jsw		;turn off SL, fix .GTLIN "bug"
	.GTLIN	#reply
	bic	#edit$, @#jsw		;can allow back now
ENDPROC


PROCED	seterr, <set error for exit>
	movb	#error$, @#userrb	;set error exit
	PNOTE	<SNOOP - E - >
ENDPROC


PROCED	setfat, <set fatal error for exit>
	movb	#fatal$, @#userrb	;set fatal error exit
	PNOTE	<SNOOP - F - >
ENDPROC


PROCED	isyes, <get reply, see if yes>
;set carry on yes, clear on no
	INVOKE	getline
	IFB	reply, eq, #'Y
	ORB	reply, eq, #'y
		sec			;set carry on yes
	ELSE
		clc			;clear carry on no
	ENDIF
ENDPROC


PROCED	getchn, <get channels for i/o>
	clr	dv.chn			;find free channel for tape
	.WAIT	dv.chn			;try to do a wait
	WHILE	cc			;if return OK, channel exists
	ORB	@#errbyt, ne		;implies real i/o error
		inc	dv.chn		;try next channel
		IF	dv.chn, eq, #maxch	;if trial count exceeded
			INVOKE	setfat		;signal fatal error
			NOTE	<No i/o channel>
			jmp	exit
		ENDIF
		.WAIT	dv.chn		;try another channel
	ENDWHILE
.if ne	debug
	PNOTE	<I/O channel -- >
	TYP.8	dv.chn
	NOTE
.endc
ENDPROC


PROCED	getdev, <get device specification>
	PNOTE	<Enter device name -- >
	INVOKE	getline
	mov	#reply, r2		;save name
	mov	#dv.nam, r3
	WHILEB	(r2), ne
		movb	(r2)+, (r3)+
	ENDWHILE
	IF	r3, eq, #dv.nam
		INVOKE	seterr
		NOTE	<Need device name>
		jmp	exit
	ENDIF
	IFB	-1(r2), ne, #':		;if missing colon,
		movb	#':, (r3)+
	ENDIF
	movb	#200, (r3)		;make asciz
	mov	sp, stack
	.CSISPC	#filspc, #defalt, #dv.nam	;parse csi string
	mov	stack, sp
	IF	cs
		INVOKE	setfat		;signal fatal error
		PNOTE	<CSI error -- >
		.PRINT	#dv.nam
		jmp	exit
	ENDIF
	IF	dv.db, eq		;if default device
		mov	#^RDK , dv.db	;make DK:
	ENDIF
	.DSTAT	#dv.sta, #dv.db		;get status
	IF	cs
		INVOKE	setfat		;signal fatal error
		PNOTE	<Device >
		.PRINT	#dv.nam
		NOTE	< not in tables>
		jmp	exit
	ENDIF
	IF	dv.lod, eq		;make sure device resident
		INVOKE	setfat		;signal fatal error
		PNOTE	<Must load >
		.PRINT	#dv.nam
		jmp	exit
	ENDIF
	IF	dv.db+2, eq		;if output to device,
		INVOKE	lok.dv		;open for reading
		bit	#varsz$, dv.sta	;see if variable-size device
		IF	ne		;if so,
.if ne	debug
			NOTE	<Variable-size device>
.endc
			.SPFUN	#emtblk, dv.chn, #spsize, #dv.siz, #1, #0
			IF	cs
				INVOKE	setfat	;signal fatal error
				NOTE	<Cannot determine device size>
				jmp	exit
			ENDIF
		ENDIF
	ELSE
		INVOKE	setfat		;signal fatal error
		PNOTE	<Device >
		.PRINT	#dv.nam
		NOTE	< must not include file name>
		jmp	exit
	ENDIF
.if ne	debug
	PNOTE	<Device status word -- >
	TYP.8	dv.sta
	NOTE
.endc
;	mov	#^d53720, dv.siz	;force proper sizes
	PNOTE	<Device size -- >
	TYP.8	dv.siz
	PNOTE	< (>
	IF	dv.siz, his, #^d10000
		mov	dv.siz, r3
		clr	r2
		div	#^d10000, r2
		TYP.10	r2				
		IF	r3, lo, #^d10
			PNOTE	<000>
		ELSIF	r3, lo, #^d100
			PNOTE	<00>
		ELSIF	r3, lo, #^d1000
			PNOTE	<0>
		ENDIF
		TYP.10	r3
	ELSE
		TYP.10	dv.siz
	ENDIF
	NOTE	<.) blocks>
	NOTE
ENDPROC


PROCED	lok.dv, <open device for non-file structured i/o>
.if eq	debug				;"real" code
	.LOOKUP	#emtblk, dv.chn, #dv.db
	IF	cs
		INVOKE	seterr		;signal error
		NOTE	<Lookup error>
		jmp	exit
	ENDIF
.endc
ENDPROC


PROCED	outoct, <output r5 in octal, leading zeros>
	IF	r5, lo, #10
		PNOTE	<     >
	ELSIF	r5, lo, #100
		PNOTE	<    >
	ELSIF	r5, lo, #1000
		PNOTE	<   >
	ELSIF	r5, lo, #10000
		PNOTE	<  >
	ELSIF	r5, lo, #100000
		PNOTE	< >
	ENDIF
	TYP.8	r5
ENDPROC


PROCED	outdec, <output r5 in decimal, leading zeros>
	IF	r5, lo, #^d10
		PNOTE	<    >
	ELSIF	r5, lo, #^d100
		PNOTE	<   >
	ELSIF	r5, lo, #^d1000
		PNOTE	<  >
	ELSIF	r5, lo, #^d10000
		PNOTE	< >
	ENDIF
	IF	r5, his, #^d10000
		PUSH	<r2, r3>	;save registers
		mov	r5, r3
		clr	r2
		div	#^d10000, r2
		TYP.10	r2				
		IF	r3, lo, #^d10
			PNOTE	<000>
		ELSIF	r3, lo, #^d100
			PNOTE	<00>
		ELSIF	r3, lo, #^d1000
			PNOTE	<0>
		ENDIF
		TYP.10	r3
		POP	<r3, r2>
	ELSE
		TYP.10	r5
	ENDIF
ENDPROC


PROCED	inp.dv, <read from device>
.if eq	debug				;"real" code
	.READ	#emtblk, dv.chn, #buff, #bufsiz, dv.blk
	IF	cs
		NOTE	<Probable early EOF on device>
		PNOTE	<Words read = >
		TYP.8	r0
		PNOTE	<, expected >
		TYP.8	#bufsiz
	ENDIF
	.WAIT	dv.chn
	IF	cs			;check for error, set eof
		INVOKE	seterr		;signal error
		NOTE	<Input error>
		mov	#buff, r4
		mov	dv.blk, r5
		WHILE	r4, lo, #end.bf
		AND	dv.eof, eq
			.READ	#emtblk, dv.chn, r4, #blksiz, r5
			.WAIT	dv.chn
			IF	cs
				PNOTE	<Input error, block >
				INVOKE	outoct				
				PNOTE	< (>
				INVOKE	outdec
				NOTE	<.)>
			ENDIF
			add	#2*blksiz, r4
			inc	r5
			IF	r5, his, dv.siz
				inc	dv.eof
			ENDIF
		ENDWHILE
	ENDIF
.endc
	add	#blfact, dv.blk
	IF	dv.blk, his, dv.siz	;if end-of-device reached,
	OR	dv.blk, lo, #blfact	;(guard against block wrap-around)
		inc	dv.eof		;set flag
	ENDIF
ENDPROC


PROCED	close, <close all files>
.if ne	debug
	NOTE	<Close files>
.endc
	.CLOSE	dv.chn
ENDPROC


PROCED	in.blk, <read one block from device>
;enter with block in r5
.if eq	debug				;"real" code
	.READ	#emtblk, dv.chn, #devbuf, #blksiz, r5
	.WAIT	dv.chn
	IF	cs			;check for error, set eof
		INVOKE	seterr		;signal error
		PNOTE	<Input error, block >
		INVOKE	outoct				
		PNOTE	< (>
		INVOKE	outdec
		NOTE	<.)>
	ENDIF
.endc
ENDPROC


PROCED	shodev, <show some device file characteristics>
;enter with first block number in r5
;attempt to calculate device size, give volume ID and owner name
	PUSH	r5			;save probable first device block
	add	#6, r5			;point to directory
	INVOKE	in.blk			;read first segment
	mov	#devbuf, r1		;point to block contents
	mov	#devfil, r2		;point to data area
	FOR	r3, #1, #5		;save first 5 words
		mov	(r1)+, (r2)+
	ENDFOR
	asl	d.tota			;convert segments to blocks
	add	#<2*7>, d.extr		;compute entry offset
	clr	d.next			;use as counter
	dec	d.high			;compute offset from first segment
	asl	d.high			;convert to blocks
	add	d.high, r5		;point to last segment
	INVOKE	in.blk			;read last segment
	WHILE	devbuf+2, ne		;ensure at end of directory chain
		mov	devbuf+2, r5	;compute next segment block
		dec	r5		;offset from first segment
		asl	r5		;segment = 2 blocks
		add	(sp), r5	;add starting device block
		add	#6, r5		;add offset to directory
		INVOKE	in.blk		;read another directory segment		
	ENDWHILE
	mov	#devbuf+10, r1		;point to starting segment block
	mov	(r1)+, d.strt		;reset starting block
	WHILE	e.stat(r1), ne, #4000	;while not end-of-segment
		add	e.leng(r1), d.strt	;keep running total of size
		add	d.extr, r1	;bump to next entry
		IF	r1, his, #buff	;if into next block,
			inc	r5	;point to next block
			inc	d.next	;count it
			IF	d.next, lt, #2	;if still in segment,
				INVOKE	in.blk	;read second half
				sub	#2*blksiz, r1	;reset pointer
			ELSE
				mov	#4000, e.stat(r1)	;force eos
				clr	d.strt		;reset to 0, flag
			ENDIF
		ENDIF
	ENDWHILE
	mov	d.strt, r5		;now output size
	PNOTE	<  Size >
	INVOKE	outoct
	PNOTE	< (>
	INVOKE	outdec
	PNOTE	<.)>
	PNOTE	<  >			;space before ID
	mov	(sp), r5		;reset to start of device
	inc	r5			;point to home block
	INVOKE	in.blk			;read home block
	mov	#devbuf, r1		;point to block contents
	add	#730, r1		;offset to volume ID
	FOR	r2, #730, #743		;for each potential character
		movb	(r1)+, r0	;get character
		IFB			;if null,
			movb	#' , r0	;output spaces
			FOR	r2, r2, #743
				.TTYOUT
			ENDFOR
		ELSE
			.TTYOUT		;type out volume ID
		ENDIF
	ENDFOR
	PNOTE	<, >
	mov	#devbuf, r1		;point to block contents
	add	#744, r1		;offset to owner name
	FOR	r2, #744, #757		;for each potential character
		movb	(r1)+, r0	;get character
		IFB			;if null,
			movb	#' , r0	;output spaces
			FOR	r2, r2, #757
				.TTYOUT
			ENDFOR
		ELSE
			.TTYOUT		;type out volume ID
		ENDIF
	ENDFOR
	NOTE
	POP	r5			;reset stack, restore register
ENDPROC


LABEL	devfil, <device file characteristics>
d.tota:	.word	0			;total number of segments
d.next:	.word	0			;pointer to next segment
d.high:	.word	0			;highest segment in use
d.extr:	.word	0			;extra bytes/entry
d.strt:	.word	0			;starting block number for segment
	e.stat	=	0		;offset for status
	e.leng	=	10		;offset for file length

PROCED	match, <do pattern match>
;enter with buffer pointer in r4, block # in r5
	CASE	sno.op, <sn.op1, sn.op2, sn.op3, sn.op4>
sn.op1:
;If part of device block, 760 - 773 will contain "DECRT11A    "
		mov	r4, r2
		add	#760, r2	;offset to right area
		mov	#patrn1, r3	;get pattern
		clr	r0		;use as "mismatch" flag
		REPEAT
			IFB	(r2)+, ne, (r3)+	;flag mismatch
				inc	r0
			ENDIF
		UNTIL	r0, ne		;mismatch
		ORB	(r3), eq	;or end of pattern
		sub	r4, r2		;determine offset within block
		IF	r2, his, #774	;if entire pattern matches,
			PNOTE	<From >
			PUSH	r5	;save block on entry
			dec	r5	;point to previous block
			INVOKE	outoct
			PNOTE	< (>
			INVOKE	outdec
			PNOTE	<.)>
			INVOKE	shodev	;show device name, size
			POP	r5	;restore block
		ENDIF
	ENDEL
sn.op2:
;look for all-ascii block
		mov	r4, r2
		IFB	(r2), eq	;if initial null,
			clr	r0	;not ascii
		ELSE
			FOR	r1, #1, #2*blksiz	;for each byte,
				IFB	(r2), lt 	;if high bit set 
					mov	#4*blksiz, r1	;"mismatch"	
				ELSIFB	(r2), ne	;nulls are OK
					IFB	(r2), lt, #11	;< tab
						mov	#4*blksiz, r1	
					ELSIFB	(r2), gt, #15	;> cr
					ANDB	(r2), lt, #40
						mov	#4*blksiz, r1	
					ENDIF
				ENDIF
				inc	r2	;bump pointer
			ENDFOR
			IF	r1, lo, #4*blksiz	;if no mismatch 
				mov	#1, r0		;set "ascii" flag
			ELSE
				clr	r0		;else clear flag
			ENDIF
		ENDIF
		IF	r0, ne, ascflg	;if status changes,
			mov	r0, ascflg	;save new status
			IF	r0, ne		;if found ascii,
				PNOTE	<ASCII, block >
				PUSH	r5		;save block on entry
				INVOKE	outoct
				PNOTE	< (>
				INVOKE	outdec
				PNOTE	<.)>
				POP	r5		;restore block
			ELSE
				PNOTE	< to >
				PUSH	r5		;save block on entry
				dec	r5		;ends previous block
				INVOKE	outoct
				PNOTE	< (>
				INVOKE	outdec
				NOTE	<.)>
				POP	r5		;restore block
			ENDIF
		ENDIF			
	ENDEL
sn.op3:
;look for .SAV file, non-zero in 40-66, zero in 70-356, bit-map in 360-377
;make educated guess about file size
		clr	r0		;clear "non-zero" flag
		mov	#40, r1		;offset pointer
		mov	r4, r2
		add	#40, r2		;start at location 40 in block
		REPEAT
			IF	(r2)+, ne
				inc	r0	;set "non-zero" flag
			ENDIF
			add	#2, r1	;count
		UNTIL	r0, ne
		OR	r1, eq, #70
		IF	r0, eq		;if entire block empty,
			QUIT		;exit, not .SAV file
		ENDIF
		clr	r0		;reset flag
		mov	#70, r1		;and pointer
		mov	r4, r2
		add	#70, r2		;start at location 70 in block
		REPEAT			;now make sure all clear until 360
			IF	(r2)+, ne
				inc	r0	;set "non-zero" flag
			ENDIF
			add	#2, r1	;count
		UNTIL	r0, ne
		OR	r1, eq, #360
		IF	r0, ne		;if not empty,
			QUIT		;exit, not .SAV file
		ENDIF
		clr	r0		;now use as bit counter
		mov	#360, r1	;reset pointer
		mov	r4, r2
		add	#360, r2	;start at location 360 in block
		REPEAT
			mov	(r2)+, r3	;get word in bit map
			WHILE	r3, ne		;for each bit in word,
				IF	r3, lt	;if bit set,
					inc	r0	;count it
				ENDIF
				asl	r3	;discard top bit
			ENDWHILE
			add	#2, r1		;count
		UNTIL	r1, eq, #400
		IF	r0, eq		;if bit map empty,
			QUIT		;exit, not a save file
		ENDIF
		PNOTE	<Probable .SAV file, block >		
		PUSH	r5		;save block on entry
		INVOKE	outoct
		PNOTE	< (>
		INVOKE	outdec
		PNOTE	<.)>
		PNOTE	<, size perhaps >
		mov	50(r4), r5	;get high address
		bis	#777, r5		
		inc	r5		;round up
		swab	r5		;form block count one way
		asr	r5		;divide by 1000
		IF	r0, gt, r5	;if bit map measure larger,
			mov	r0, r5	;use it instead
		ENDIF	
		INVOKE	outoct
		PNOTE	< (>
		INVOKE	outdec
		NOTE	<.) blocks>
		POP	r5		;restore block
	ENDEL
sn.op4:
;look for .SYS file
;non-zero in 40-76, non-zero in 110, zero in 120-170, bit-map in 360-377
;make educated guess about file size
		clr	r0		;clear "non-zero" flag
		mov	#40, r1		;offset pointer
		mov	r4, r2
		add	#40, r2		;start at location 40 in block
		REPEAT
			IF	(r2)+, ne
				inc	r0	;set "non-zero" flag
			ENDIF
			add	#2, r1	;count
		UNTIL	r0, ne
		OR	r1, eq, #70
		IF	r0, eq		;if entire block empty,
			QUIT		;exit, not .SYS file
		ENDIF
		IF	110(r4), eq	;if null release name,
			QUIT		;not .SYS file
		ENDIF
		clr	r0		;reset flag
		mov	#120, r1	;and pointer
		mov	r4, r2
		add	#120, r2	;start at location 120 in block
		REPEAT			;now make sure all clear until 170
			IF	(r2)+, ne
				inc	r0	;set "non-zero" flag
			ENDIF
			add	#2, r1	;count
		UNTIL	r0, ne
		OR	r1, eq, #170
		IF	r0, ne		;if not empty,
			QUIT		;exit, not .SYS file
		ENDIF
		clr	r0		;now use as bit counter
		mov	#360, r1	;reset pointer
		mov	r4, r2
		add	#360, r2	;start at location 360 in block
		REPEAT
			mov	(r2)+, r3	;get word in bit map
			WHILE	r3, ne		;for each bit in word,
				IF	r3, lt	;if bit set,
					inc	r0	;count it
				ENDIF
				asl	r3	;discard top bit
			ENDWHILE
			add	#2, r1		;count
		UNTIL	r1, eq, #400
		IF	r0, eq		;if bit map empty,
			QUIT		;exit, not a save file
		ENDIF
		PNOTE	<Probable .SYS file, block >		
		PUSH	r5		;save block on entry
		INVOKE	outoct
		PNOTE	< (>
		INVOKE	outdec
		PNOTE	<.)>
		PNOTE	<, size perhaps >
		mov	50(r4), r5	;get high address
		bis	#777, r5		
		inc	r5		;round up
		swab	r5		;form block count one way
		asr	r5		;divide by 1000
		IF	r0, gt, r5	;if bit map measure larger,
			mov	r0, r5	;use it instead
		ENDIF	
		INVOKE	outoct
		PNOTE	< (>
		INVOKE	outdec
		NOTE	<.) blocks>
		POP	r5		;restore block
	ENDEL
	ENDCASE
ENDPROC


LABEL	patrn1, <pattern to match>
	.asciz	"DECRT11A    "
	.even


PROCED	snoop, <look at buffer, announce blocks which pattern-match>
;enter with snoop block (at end of buffer) on stack
	mov	2(sp), r5		;get final block
	dec	r5			;move to previous "chunk"
	clr	r4
	div	#blfact, r4		;calculate how many "reads"
	mul	#blfact, r4		;should now point to begining
	mov	#buff, r4		;r4 points to buffer, r5 to block
	WHILE	r4, lo, #end.bf
	AND	r5, lo, dv.siz
		INVOKE	match
		add	#2*blksiz, r4	;move buffer pointer
		inc	r5		;and block pointer
	ENDWHILE
	POP	(sp)			;discard argument
ENDPROC


PROCED	ending, <handle end-of-device>
	CASE	sno.op, <en.op1, en.op2, en.op3, en.op4>
en.op1:
;look for sub-device
;no special code
	ENDEL
en.op2:
;look for all-ascii block
		IF	ascflg, ne	;if currently doing ascii,
			PNOTE	< to >
			mov	dv.siz, r5	;use device size as last block
			dec	r5		;ends previous block
			INVOKE	outoct
			PNOTE	< (>
			INVOKE	outdec
			NOTE	<.)>
		ENDIF			
	ENDEL
en.op3:
;look for .SAV file
;no special code
	ENDEL
en.op4:
;look for .SYS file
;no special code
	ENDEL
	ENDCASE
ENDPROC


LABEL	ascflg, <ascii flag>
	.word	0			;1 if found ascii, 0 if not


LABEL	begin, <main routine>
	NOTE
	.PRINT	#modnam			;identify module
	NOTE
	INVOKE	getchn			;first, get some i/o channels
	INVOKE	getdev			;get input device
	movb	#succs$, @#userrb	;assume successful exit
	clr	ascflg			;clear ascii flag
	PNOTE	<Look for sub-devices? >
	INVOKE	isyes
	IF	cs
		mov	#1, sno.op
	ELSE
		PNOTE	<Look for ascii regions? >
		INVOKE	isyes
		IF	cs
			mov	#2, sno.op
		ELSE
			PNOTE	<Look for .SAV files? >
			INVOKE	isyes
			IF	cs
				mov	#3, sno.op
			ELSE
				PNOTE	<Look for .SYS files? >
				INVOKE	isyes
				IF	cs
					mov	#4, sno.op
				ELSE
					mov	#0, sno.op
				ENDIF
			ENDIF
		ENDIF
	ENDIF
	IF	sno.op, gt	;if we made a choice
		NOTE
		REPEAT
			INVOKE	inp.dv		;read
			PUSH	dv.blk		;pass block to snoop
			INVOKE	snoop		;check buffer, announce blocks
			bit	dv.blk, #3777
			IF	eq
			AND	ascflg, eq	;and not doing ascii
				PNOTE	<Block >
				TYP.8	dv.blk
				NOTE
			ENDIF
		UNTIL	dv.eof, ne		;until end of input
		INVOKE	ending			;handle endings
		INVOKE	close			;close all files
		NOTE
		NOTE	<Snoop complete>
	ENDIF
	jmp	exit			;and quit


LABEL	exit, <ending routine>
	INVOKE	close			;close all channels
	NOTE
	.EXIT

	.psect	$data

LABEL	devbuf, <tiny buffer for device file decoding>
	.blkw	blksiz


LABEL	buff, <main input buffer>
	.blkw	bufsiz

	end.bf	=	.		;end of i/o buffers


	ENDEND

	.end	begin
