;***************************************************************************;
;									    ;
;				    OPEN				    ;
;		      Displays open files on the system			    ;
;									    ;
;***************************************************************************;
;Copyright (C) 1988 UltraSoft Corporation.  All Rights Reserved.
;
;Written by: David Pallmann
;
;Edit History:
;2.0(100)  complete rewrite (works much, much better). /DFP
;
;Assembly Notes:
;
;	OPEN requires no special files, other than those that are normally
;	distributed with AMOS.  You DO have to link OPEN after assembly,
;	however:
;
;			Step 1:		.M68 OPEN
;			Step 2:		.LNKLIT OPEN
;
;How OPEN works:
;
;	Regrettably, AMOS doesn't keep track of which files are open
;	(unless you're running LOKSER).  OPEN finds open files anyhow
;	by using the following brute-force technique:  The memory
;	partition for each job is scanned for what looks like a file
;	DDB.  If enough fields in the alleged-DDB check out, OPEN assumes
;	it has a bonafide open file, and outputs information about it.
;
;	This is the only way to hunt out open files currently; if OPEN has
;	to scan a job with a particularly large memory partition, you may
;	notice some delays.  Again, this can't be helped.
;
;	This version of OPEN is much more effective than the previous
;	version, which assumed that I/O buffers for files were always
;	separate memory modules.  This is not the case in AlphaWRITE,
;	AlphaBASIC, and many other applications.  The new OPEN properly
;	identifies ALL open files to the best of our knowledge.
;
;	The following is the current definition for what OPEN considers
;	an open file:
;
;		A region of memory is considered a DDB if:
;
;			1. The area of memory is in a job's partition.
;			2. The longword D.DDB(address) contains 512.
;			3. The byte D.OPN(address) contains 1, 2, 4, or 8.
;			4. The longword D.BUF(address) is an address that
;			   resides in the same user partition as the DDB.
;
;	This definition should suffice for just about all files opened
;	under AMOS.

;********************
;*  version number  *
;********************

	VMAJOR=2
	VMINOR=0
	VSUB=0
	VEDIT=100.
	VWHO=0

;***************
;*  externals  *
;***************

	ASMMSG	"After assembly, enter:  .LNKLIT OPEN"
	EXTERN	$ODTIM

;****************
;*  universals  *
;****************

	SEARCH	SYS
	SEARCH	SYSSYM

;************************************
;*  register usage throughout OPEN  *
;************************************
;
;	D0 - unused			A0 - index into job table (JOBTBL)
;	D1 - used for OCVT calls	A1 - buffer address
;	D2 - unused			A2 - current index into job memory
;	D3 - used for $ODTIM call	A3 - end of job memory
;	D4 - used for $ODTIM call	A4 - JCB address of current job
;	D5 - used for $ODTIM call	A5 - unused

;************
;*  macros  *
;************

DEFINE	OUTNAM	ADDR
	SAVE	A1-A2
	SUB	#8.,SP
	LEA	A1,ADDR
	MOV	SP,A2
	UNPACK
	UNPACK
	CLRB	@A2
	TTYL	@SP
	ADD	#8.,SP
	REST	A1-A2
	ENDM

;********************
;*  program header  *
;********************

START:	PHDR	-1,,PH$REE!PH$REU	; reentrant & reusable (as always)

;******************************************
;*  clear screen and print column titles  *
;******************************************

HEADER:	MOVW	#<-1_8.>,D1		; clear
	TCRT				;  screen
	TYPESP	Open Files as of
	CLR	D3
	CLR	D4
	MOV	#-1,D5
	MOV	#0,A2
	CALL	$ODTIM
	CRLF
	CRLF
	TYPECR	Job     Term    Prog    DDB Address  Access  File
	TYPECR	------  ------  ------  -----------  ------  --------------------------

;***************************
;*  loop to scan all jobs  *
;***************************

ALLJOB:	MOV	JOBTBL,A0		; point to job table
10$:	CTRLC	20$			; branch on control-C
	MOV	(A0)+,D7		; get JCB address
	BEQ	10$			; deallocated job - skip
	BMI	20$			; end of job table - all done
	MOV	D7,A4			; put JCB in A4 for subroutines
	CALL	SCAN			; scan the job @A4 for open files
	BR	10$			; proceed to the next job
20$:	CRLF				; we're done, print a blank line
	EXIT				; exit to AMOS

;*************************************
;*  scan the job @A4 for open files  *
;*************************************

SCAN:	TST	JOBSIZ(A4)		; does this job have any memory?
	JEQ	SCNRTN			;  no
	MOV	JOBBAS(A4),A2		; A2 := base of job's memory
	MOV	A2,A3			; copy base
SCNWLK:	TST	@A3			; end of job's memory map?
	BEQ	SCNDDB			;  yes
	ADD	@A3,A3			;  no - skip next module
	BR	SCNWLK			;       and loop
SCNDDB:	CMP	A2,A3			; end of partition?
	JHIS	SCNRTN			;  yes - we are done w/this job
	CMP	D.SIZ(A2),#512.		; is this a DDB - rec size 512?
	BNE	SCNNXT			;  no, this isn't a DDB
	MOV	D.BUF(A2),A1		; get buffer address
	CMM	A1,JOBBAS(A4)		; is buffer address in user memory?
	BLO	SCNNXT			;  no (too low) - can't be a DDB
	CMP	A1,A3			; is buffer address in user memory?
	BHIS	SCNNXT			;  no (too high) - can't be a DDB
	MOVB	D.OPN(A2),D4		; get OPEN code
	CMPB	D4,#1			; open for input?
	BEQ	SCNFIL			;  yes - valid DDB
	CMPB	D4,#2			; open for output?
	BEQ	SCNFIL			;  yes - valid DDB
	CMPB	D4,#4			; open for random I/O?
	BEQ	SCNFIL			;  yes - valid DDB
	CMPB	D4,#10			; open for appending?
	BNE	SCNNXT			;  no - not avalid DDB
SCNFIL:	CALL	DISPLAY			; output the DDB we found
SCNNXT:	CTRLC	SCNRTN
	ADD	#2,A2
	BR	SCNDDB
SCNRTN:	RTN

;*************************************************************************
;*  display line - DDB address is @A2, JCB address @A4, open code in D4  *
;*************************************************************************

DISPLAY:
	OUTNAM	JOBNAM(A4)		; *** output job name
	TYPE	<  >
	MOV	JOBTRM(A4),A6		; *** output terminal name
	OUTNAM	-4(A6)
	TYPE	<  >
	OUTNAM	JOBPRG(A4)		; *** output program name
	TYPE	<  >
	MOV	A2,D1			; *** output DDB addr
	OCVT	13,OT$TRM!OT$ZER
	TYPE	<  >
	CMPB	D4,#1			; *** output file access
	BEQ	10$
	CMPB	D4,#2
	BEQ	20$
	CMPB	D4,#4
	BEQ	30$
	TYPE	<append>
	BR	40$
10$:	TYPE	<input >
	BR	40$
20$:	TYPE	<output>
	BR	40$
30$:	TYPE	<random>
40$:	TYPE	<  >
	PFILE	@A2			; *** output filename
	CRLF
	RTN

	ASCIZ	/Copyright (C) 1988 UltraSoft Corp.  All Rights Reserved./
	EVEN

	END