Google
 

Trailing-Edge - PDP-10 Archives - decuslib20-10 - decus/20-186/imgspl.mac
There is 1 other file named imgspl.mac in the archive. Click here to see a list.
	TITLE IMGSPL - TOPS-20 IMAGEN LASER PRINTER SPOOLER
	SEARCH MACSYM, MONSYM, ACTSYM
	SEARCH GLXMAC, QSRMAC, ORNMAC
	EXTERN .JBOPS
	.REQUIRE SYS:MACREL
	SALL


COMMENT ^

; SEQUENCE PACKET PROTOCOL IS USED FOR TERMINAL LINES.
; SERIAL PROTOCOL IS USED FOR TCP DEVICES.
;
; THE SPOOLER USES DEVICE "node-LSRn:" WHERE "n" IS THE UNIT NUMBER
; AND "node" IS THE DESTINATION NODE.
;
; THE /DEVICE: FIELD TO THE OPR START COMMAND IS IGNORED TO
; ALLOW EASY DESTINATION ROUTING.
;
; ACCOUNTING IS DONE WITH THE USAGE% JSYS, WITH THE QUEUE NAME
; SET TO "LSR".  DISABLED WITH THE ACCTSW SWITCH.  ACCOUNTING
; INFORMATION IS OBTAINED FROM THE PRINTER AND IS UNAVAILABLE
; WITH TCP PRINTERS.
;
; FOR OPEN SHOPS, WHEN THE PRINTER GOES OFF LINE, THE USER
; WHO REQUESTED THE CURRENT JOB IS NOTIFIED BY AN ON-LINE
; MESSAGE.  DISABLED WITH THE OFFLSW SWITCH.
;
; FOR TCP PRINTERS, THE DESTINATION IS ASSUMED TO BE EITHER
; A PRINTER OR A REMOTE SERVER.  IF IT IS A SERVER, THE
; REMSPL SWITCH MUST BE SET NON-ZERO IFF THE SERVER SENDS
; A HERALD.  REMSLP SHOULD BE ZERO IF ACTUAL PRINTERS ARE
; USED.
;
; THE PUNCHED CARD QUEUE IS USED.
THE SPOOLER USES THE FOLLOWING IN THE FP BLOCK OF THE EXTERNAL
QUEUE ENTRY.


	!=======================================================!
.FPLEN	! LENGTH OF FILE-PARAM AREA !				!
	!-------------------------------------------------------!
.FPINF	!FILE FMT !PAPR FMT!SPACING !    FLAGS    !   COPIES    !
	!-------------------------------------------------------!
.FPFST	!         STARTING INFORMATION 			        !
	!-------------------------------------------------------!
.FPFR1	!         FORMWIDTH         !       FORMLENGTH          !
	!-------------------------------------------------------!
.FPFR2	!           FLAGS           !       LEFTMARGIN          !
	!=======================================================!

FILE FORMAT:

	.FPFAS==1		ASCII FORMAT
	.FPFAI==4		TEKTRONIX FORMAT
	.FPFIM==7		IMPRESS FORMAT
	.FPF8B==10		DAISY FORMAT

PAPER FORMAT:

	%FPLAR==1		ARROW MODE
	%FPLAS==2		STRAIGHT ASCII

FLAGS IN .FPINF:

	FP.DEL==1B18		DELETE FILE
	FP.SPL==1B21		SPOOLED FILE
	FP.REV==1B24		PAGEREVERSAL
	FP.COL==1B25		PAGECOLLATION
	FP.2PG==1B26		TWO FORMS PER PAGE

FLAGS IN .FPFR2:

	FP.SDP==1B0		JOB IS A SCREEN DUMP
	FP.RUL==1B1		RULES YES
	FP.OTL==1B2		OUTLINES YES
	FP.MAN==1B3		MANUAL PAPER FEED
	TEXT UTILITIES

THE TEXT UTILITY USED IS:

	TEXT (ROUTINE,<STRING>)

WHERE ROUTINE IS THE SUBROUTINE WHICH WILL RECEIVE THE CHARACTERS
FROM THE STRING IN AC1.  THIS ROUTINE MAY MESS WITH AC1-AC16 AND
SHOULD RETURN WITH A POPJ P,.  

THE STRING MAY USE CODES OF THE FORM "%Xn" WHERE "n" IS 1..5 TO SPECIFY
AC1..AC5 AND "X" IS ONE OF THE FOLLOWING:

	"U"	USER NAME STRING FOR USER NUMBER IN AC.
	"F"	FILE NAME FOR JFN IN AC. (DEV, DIR, NAM, TYP, GEN)
	"f"	FILE NAME FOR JFN IN AC. (NAM, TYP, GEN)
	"N"	DECIMAL NUMBER IN AC.
	"O"	OCTAL NUMBER IN AC.
	"6"	SIXBIT WORD IN AC.
	"T"	TIME FOR UDT IN AC.
	"D"	DATE FOR UDT IN AC.
	"E"	ERROR STRING FOR ERROR NUMBER IN AC.
	"S"	STRING WITH POINTER IN AC.
	"_"	ADD CRLF AND QUIT
	"%"	"%"

A CRLF IS NOT ADDED TO THE END OF THE STRING UNLESS %_ IS USED.





		WTO'S

WTO'S HAVE THE FORMAT:

	WTO (<FIRST STRING>,<SECOND STRING>)

THE FIRST STRING MUST EXIST, THE SECOND STRING MAY.
WTO, WTOJ, LOG, AND ACK ARE DEFINED. WTOR IS NOT.

^
	SUBTTL DEFINITIONS

; ACS
F==0
A==1
B==2
C==3
D==4
P1==10
P2==11
P3==12
P==17

DBUGSW==0			;NON-ZERO TO ENABLE DEBUGGING INFORMATION
				;SENT TO THE TERMINAL.

ACCTSW==-1			;NON-ZERO TO ENABLE SYSTEM ACCOUNTING.
				;NO ACCOUNTING IS DONE FOR TCP PRINTERS.

OFFLSW==-1			;NON-ZERO TO SEND A MESSAGE TO THE JOB
				;OWNER WHEN THE PRINTER GOES OFF LINE

REMSPL==-1			;NON-ZERO IF THE OTHER SIDE OF TCP CONNECTIONS
				;ARE EXPECTED TO BE REMOTE SPOOLERS SENDING
				;A HERALD.

%IMG==1				;MAJOR VERSION
%MINOR==0			;MINOR VERSION
%EDIT==0			;EDIT NUMBER
VERSION==<%IMG>B11+<%MINOR>B17+%EDIT


IF1,<
IFN DBUGSW,< PRINTX Debugging code enabled >
IFN ACCTSW,< PRINTX Accouting enabled >
IFN OFFLSW,< PRINTX Offline user notification enabled >
>

.DVTCP==25			;CAN'T FIND THIS IN MONSYM
.DVCHA==26			;THIS EITHER

OBJTYP==.OTCDP			;GALAXY OBJECT TYPE
MSGPAG==600			;PAGE FOR IPCF MESSAGES
MSG==MSGPAG*1K			;LOCATION OF IPCF MESSAGES

STKLEN==200			;LENGTH OF STACK
PDBLEN==4			;LENGTH OF PACKET DESCRIPTOR BLOCKS
MAXPKT==177			;MAX PACKET NUMBER
PKTLEN==50			;MAX LENGTH OF INPUT PACKET
; PARAMETERS (TIME IN MSEC)

MINWIN==^D116			;MINIMUM WINDOW SIZE
				;ALLOWED FOR THE PRINTER

DATSIZ==^D114			;GOOD LENGTH FOR THE
				;DATA PORTION OF A PACKET

OSPCNT==40			;NUMBER OF OUTSTANDING
				;(UNACK'D) PACKETS ALLOWED

TCPGLX==^D500			;NUMBER OF CHARACTERS TO SEND TO TCP
				;PRINTER BEFORE CHECKING FOR GALAXY MESSAGE

TCPSLP==^D10000			;TIME TO WAIT BEFORE RETRYING A
				;FAILED OPENF FOR TCP PRINTER

PIDSLP==^D60000			;TIME TO WAIT BEFORE RESTARTING
				;AFTER FAILURE TO SET UP PIDS

PRVSLP==^D5000			;TIME TO WAIT FOR PRIVATE
				;QUASAR AND ORION TO START

JOBSLP==^D5000			;TIME TO WAIT FOR NEW JOB WHEN IDLE

RSVSLP==^D3000			;TIME TO WAIT FOR PRINTER TO
				;RESPOND TO AN RSVP PACKET

NAKSLP==^D3000			;TIME TO WAIT BETWEEN RECEIVING A
				;NAK PACKET AND GIVING A CFIBF

WINSLP==^D2000			;TIME TO WAIT FOR PRINTER BUFFER SIZE
				;TOO SMALL AND CHECKING AGAIN

CHRSLP==^D1000			;MAX TIME TO WAIT FOR A MID-PACKET
				;CHARACTER TO COME FROM THE PRINTER

WRPSLP==^D2000			;TIME TO WAIT AFTER WRAPAROUND DETECTED

EOFSLP==^D5000			;RSVP DELAY DURING EOF PROCESSING

MAXJOB==^D100			;MAX JOB NUMBER EXPECTED ON THE SYSTEM

OFLTMX==554			;TIME IN UDT FORMAT TO WAIT BEFORE SENDING
				;ANOTHER OFF LINE NOTIFICATION.
				;2 MINUTES HERE.
; PRINTER FLAGS
F%HDR==1B10			;HEADER IS BEING SENT
F%EOF==1B11			;EOF PACKET SENT
F%PAB==1B12			;TELL PRINTER TO ABORT
F%JIP==1B13			;JOB IN PROGRESS ON PRINTER
F%OFL==1B14			;PRINTER IS OFF LINE
F%PGC==1B15			;PAGE COUNT IS VALID
F%TCP==1B16			;PRINTER IS A TCP HOST
F%OPN==1B17			;TCP CONNECTION OPEN

; LOCAL FLAGS
F%FAT==1B0			;FATAL ERROR
F%F1==1B1
F%F2==1B2
F%F3==1B3

; FILE FLAGS
F%IMP==1B20			;FILE IS IMPRESS
F%ASC==1B21			;FILE IS ASCII
F%DSY==1B22			;FILE IS DIABLO
F%TEK==1B23			;FILE IS TEKTRONIX
F%ARO==1B24			;WANT ASCII ARROW MODE
F%CPF==1B25			;CAN'T PRINT FILE

; JOB FLAGS
F%UP== 1B28			;DEVICE IS STARTED
F%JOB==1B29			;JOB IS ASSIGNED
F%REQ==1B30			;REQUEUE JOB WHEN RELEASING
F%SYN==1B32			;PRINTER ABORTED
F%CAN==1B33			;JOB CANCELED
F%LST==1B35			;LAST FILE IS BEING PROCESSED
; PACKET PARAMETERS
PK%BGN==176			;PACKET BEGIN CHARACTER
PK%END==12			;PACKET END CHARACTER
PK%DAT=="1"			;PACKET DATA MARK
PK%EOF=="B"			;PACKET END OF FILE MARK
PK%QUO==175			;QUOTE CHARACTER
QUO%BP=="A"			;QUOTE ARGUMENT FOR PK%BGN
QUO%EP=="B"			;QUOTE ARGUMENT FOR PK%END
QUO%QT=="C"			;QUOTE ARGUMENT FOR PK%QUO

; OFFSETS INTO PACKETS
.PKLEN==1			;PACKET LENGTH
.TYPE==3			;PACKET TYPE
.PKTNM==4			;PACKET NUMBER
.WINDO==5			;WINDOW COUNT
.PKDAT==7			;FIRST DATA BYTE
.PKTCD==9			;PACKET ACK CODE
.PSTAT==^D11			;PRINTER STATUS
.LSRCT==^D12			;PAGE COUNT

STACK:	BLOCK STKLEN		;STACK SPACE
DUMPAC:	BLOCK 20		;SAVED AC'S FOR CRASH DUMP
DMPSTR:	BLOCK 50		;ERROR STRING FOR DUMP
HOSTNM:	BLOCK 20		;LOCAL HOST NAME
; STORAGE FOR GALAXY INTERFACE

DEVNAM:	BLOCK 20		;DEVICE NAME
DEVPTR:	BLOCK 1			;DEVICE NAME POINTER
LSRJFN:	BLOCK 1			;DEVICE JFN

NFILES:	BLOCK 1			;NUMBER OF FILES IN REQUEST
FILCNT:	BLOCK 1			;LOCAL FILE COUNTER

JOBTIM:	BLOCK 1			;TIME JOB WAS STARTED
RUNTIM:	BLOCK 1			;RUN TIME WHEN STARTING A JOB
JOBCNT:	BLOCK 1			;PAGE COUNT OF THE JOB
JOBPRI:	BLOCK 1			;JOB PRIORITY

FILPTR:	BLOCK 1			;ADDRESS OF CURRENT FILE PARAMETER BLOCK
JOBINF:	BLOCK 1K		;CURRENT EXTERNAL QUEUE ENTRY

OBJBLK:	BLOCK 3			;OBJECT DESCRIPTOR BLOCK
OBJRPT:	BLOCK 1			;REPORT OBJECT BLOCK FLAG

WTOADR:	BLOCK 1			;WTO TEMP VARIABLES
WTOPTR:	BLOCK 1
WTOACS:	BLOCK 5
; IPCF STORAGE

MYPID:	BLOCK 1			;LOCAL PID
QSRPID:	BLOCK 1			;QUASAR'S PID
ORNPID:	BLOCK 1			;ORION'S PID

MUTBLK:	EXP .MUSPQ		;MUTIL ARG BLOCK
	EXP -1			;GET MAX NUMBER OF PIDS FOR THIS JOB
	EXP ^D15		;SET TO 15.

SNDPDB:	BLOCK PDBLEN		;PDB FOR SENDS TO QUASAR AND ORION

PAGRCV:	EXP IP%CFR!IP%CFV	;PDB FOR PAGE RECEIVES
	EXP 0
	EXP MYPID
	XWD 1K,MSGPAG

SHTRCV:	EXP IP%CFR		;PDB FOR SHORT RECEIVES
	EXP 0
	EXP MYPID
	XWD 1K,MSG

PRVPDB:	EXP IP%CFS		;PDB FOR PRIVATE SYSTEM SETUP
	EXP MYPID
	EXP 0
	EXP PRVMSG

PRVMSG:	EXP .IPCIW		;PACKET TO <SYSTEM>INFO
PRVMS1:	BLOCK 1
PRVMS2:	BLOCK 50

HELLO:	XWD HELLEN,.QOHEL	;HELLO MESSAGE TO QUASAR
	EXP 0
	EXP 0
	SIXBIT "IMGSPL"		;PROGRAM NAME
	XWD %%.QSR,0		;QUASAR VERSION, FLAGS
	XWD 1,1			;NUMBER OF OBJECTS, MAX NUMBER OF JOBS
	XWD 0,OBJTYP		;OBJECT LIST
HELLEN==.-HELLO
; STORAGE FOR FILE OUTPUT ROUTINES

INJFN:	BLOCK 1			;JFN OF FILE BEING PRINTED
TMPJFN:	BLOCK 1			;TEMP FILE JFN FOR ERRORS
FILTIM:	BLOCK 1			;TIME WHEN FILE WAS STARTED
PAGCNT:	BLOCK 1			;PAGE COUNT OF FILE
ARGBLK:	BLOCK 5			;CHKAC ARGUMENT BLOCK

PKTTBL:	BLOCK MAXPKT+1		;PACKET ACK TABLE
PACKET:	BLOCK 240		;OUTPUT PACKET BUFFER
LSRPKT:	BLOCK PKTLEN		;INPUT PACKET BUFFER
PKTNUM:	BLOCK 1			;CURRENT PACKET NUMBER
LSTACK:	BLOCK 1			;LAST ACK'D PACKET NUMBER

HDRTXT:	BLOCK 400		;HEADER BUFFER
HDRPTR:	BLOCK 1			;POINTER INTO HDRTXT

NOTMSG:	BLOCK 50		;OFFLINE NOTIFICATION MESSAGE
NOTPTR:	BLOCK 1			;OFFLINE NOTIFICATION POINTER
OFLTIM:	BLOCK 1			;TIME OF LAST NOTIFICATION

STSBUF:	BLOCK 100		;STATUS BUFFER
STSPTR:	BLOCK 1			;STATUS BUFFER POINTER
TXTBUF:	BLOCK 100		;TEXT UTILITY BUFFER
	SUBTTL MACROS

; SPOOLER STATUS
DEFINE STATUS (STR) <
	JRST [	PUSH P,A
		MOVE A,[POINT 7,STSBUF]
		MOVEM A,STSPTR
		POP P,A
		TEXT (STSTXT,<STR>)
		CALL CHKPNT
		JRST .+1 ]
	>


; FATAL ERROR
DEFINE FATAL <
	CALL [	TXNE F,F%FAT	;;ALREADY LOST?
		 JRST FATAL9	;;YES
		EXCH C,(P)	;;RETURN ADDRESS IN C
		PUSH P,B	;;SAVE THE REST
		PUSH P,A
		MOVE B,[POINT 7,STSBUF]
		MOVEM B,STSPTR	;;INITIALIZE POINTER
		HRRZS C
		SOS C		;;ADDRESS OF ERROR IN C
		MOVEI A,.FHSLF
		GETER		;;GET LAST ERROR
		HRRZS B
		TEXT (STSTXT,<?IMGSPL Fatal error at %O3: %E2>)
		POP P,A		;RESTORE THINGS
		POP P,B
		EXCH C,(P)
		JRST .FATAL ]
	>


; SPOOLER ERROR
DEFINE SPLERR (STR) <
	CALL [	TXNE F,F%FAT	;;ALREADY LOST?
		 JRST FATAL9	;;YES
		EXCH C,(P)	;;RETURN ADDRESS IN C
		PUSH P,B	;;SAVE THIS
		MOVE B,[POINT 7,STSBUF]
		MOVEM B,STSPTR	;;INITIALIZE POINTER
		POP P,B
		HRRZS C
		SOS C		;;ADDRESS OF ERROR IN C
		TEXT (STSTXT,<?IMGSPL Fatal error at %O3%_>)
		POP P,C
		TEXT (STSTXT,<   STR>)
		JRST .FATAL ]
	>
; DEBUG INFO
DEFINE DBGINF (STR) <
IFN DBUGSW,< CALL TEXT.
	      JUMP DBGTXT
	      JUMP [ASCIZ \STR'%_\]
	     >
         >

DBGTXT:	PBOUT
	RET


; TEXT UTILITY
DEFINE TEXT (X1,X2) <
	CALL TEXT.
	 JUMP X1
	 JUMP [ASCIZ \X2\]
	>


; WRITE TO OPERATOR
DEFINE WTO (X1,X2) <
	CALL .WTO.
	 JUMP [ASCIZ \X1\]
IFB  <X2>,<JUMP 0>
IFNB <X2>,<JUMP [ASCIZ \X2\]>
	>


; ACKNOWLEDGE OPERATOR
DEFINE ACK (X1,X2) <
	CALL .ACK.
	 JUMP [ASCIZ \X1\]
IFB  <X2>,<JUMP 0>
IFNB <X2>,<JUMP [ASCIZ \X2\]>
	>


; WRITE TO OPERATOR - JOB MESSAGE
DEFINE WTOJ (X1,X2) <
	CALL .WTOJ.
	 JUMP [ASCIZ \X1\]
IFB  <X2>,<JUMP 0>
IFNB <X2>,<JUMP [ASCIZ \X2\]>
	>



; WRITE TO OPERATOR - LOG MESSAGE
DEFINE LOG (X1,X2) <
	CALL .LOG.
	 JUMP [ASCIZ \X1\]
IFB  <X2>,<JUMP 0>
IFNB <X2>,<JUMP [ASCIZ \X2\]>
	>
	SUBTTL INITIALIZATION

ENTVEC:	JRST START		;STARTING LOCATION
	JRST START		;REENTER LOCATION
	VERSION



START:	RESET
	MOVEI A,.FHSLF		;THIS PROCESS
	SETOB B,C		;ENABLE EVERYTHING
	EPCAP
	MOVX A,.MSIIC		;IGNORE STRUCTURE ACCOUNTING
	MSTR
	 ERJMP .+1
	SETZ F,			;NO FLAGS
	SETZM OBJRPT		;CLEAR REPORT FLAG
	MOVE P,[IOWD STKLEN,STACK]
	MOVEI A,3		;LENGTH OF BLOCK
	MOVEI B,MUTBLK		;ADDRESS OF BLOCK
	MUTIL			;BUMP PID QUOTA
	 JFCL			;MAYBE DOESN'T MATTER
	CALL GETHST		;GET LOCAL HOST NAME
	MOVEI C,.MUCRE		;CREATE A PID
	MOVEM C,MSG
	MOVEI C,.FHSLF		;THIS PROCESS
	MOVEM C,MSG+1
	MOVEI A,3		;LENGTH
	MOVEI B,MSG		;ADDRESS
	MUTIL			;GET IT
	 JRST NOPIDS		;CAN'T
	MOVE C,MSG+2		;PICK UP THE PID
	MOVEM C,MYPID		;STORE IT

	SKIPN .JBOPS		;PRIVATE SYSTEM?
	 CALL SYSPID		;NO, GET SYSTEM PIDS
	SKIPE .JBOPS
	 CALL PRVPID		;YES, GET PRIVATE PIDS

	MOVE A,[HELLO,,MSG]	;GET THE HELLO MESSAGE
	BLT A,MSG+HELLEN	;MOVE IT INTO THE MESSAGE BUFFER
	CALL SNDQSR		;SIGN ON
;	JRST MAIN
	SUBTTL MAIN LOOP

MAIN:	CALL GETMSG		;GET A MESSAGE
	TXNN F,F%UP		;DEVICE STARTED?
	 JRST MAIN		;NO, GET ANOTHER
	JRST MAIN2		;YES, DO SOMETHING

MAIN1:	MOVEI A,JOBSLP		;WAIT SOME
	DISMS
MAIN2:	TXNN F,F%UP		;STILL STARTED?
	 JRST MAIN		;NO, BACK TO THE TOP
	CALL CHKMSG		;CHECK FOR A MESSAGE
	TXNN F,F%JOB		;WE HAVE A JOB?
	 JRST MAIN1		;NO, NOTHING TO DO
	TXZ F,F%REQ!F%CAN	;RESET THESE
	CALL DOJOB		;DO THE JOB
	CALL DOACT		;DO THE ACCOUNTING
	CALL RELJOB		;RELEASE THE JOB
	JRST MAIN2		;LOOP BACK
	SUBTTL IPCF MESSAGE RECEIVER

; GETMSG - WAITS FOR AND READS A MESSAGE FROM QUASAR OR ORION.
; CHKMSG - LOOKS FOR A MESSAE AND PROCESSES IT IF ONE IS WAITING.
;	   MESSAGES ARE PROCESSED AS SOON AS THEY ARE READ.

CHKMSG:	CALL DORPT		;REPORT OBJECT BLOCK
	TXZA F,F%F1		;F1 - ON IF WE MUST READ A MESSAGE
GETMSG:	TXO F,F%F1
	TRVAR <NXTMSG>
GETMS1:	MOVEI A,PDBLEN		;LENGTH OF PDB
	MOVEI B,PAGRCV		;TRY FOR A PAGE
	MOVX C,IP%CFB		;GET THE DONT-BLOCK FLAG
	TXNE F,F%F1		;WANT TO WAIT?
	 ANDCAM C,.IPCFL(B)	;YES
	TXNN F,F%F1
	 ORM C,.IPCFL(B)
	MRECV			;GET THE MESSAGE
	 JRST [	CAIN A,IPCFX2	;NO MESSAGE AVAILABLE?
		 RET		;YES, QUIT NOW
		CAIE A,IPCF16	;DATA MODES DIFFERENT?
		 JRST NORECV	;NO, CAN'T CONTINUE
		MOVEI A,PDBLEN	;SAME LENGTH
		MOVEI B,SHTRCV	;TRY FOR A SHORT MESSAGE
		MOVE C,[1K,,MSG];RESET THIS
		MOVEM C,SHTRCV+.IPCFP
		MRECV		;GET IT
		 JRST NORECV	;CON'T
		JRST .+1 ]	;DONTINUE
	MOVEM A,NXTMSG		;SAVE FLAGS FOR THE NEXT ONE
	MOVE A,.IPCFS(B)	;GET THE SENDER
	CAME A,QSRPID		;FROM QUASAR?
	CAMN A,ORNPID		;OR ORION?
	 SKIPA			;YES
	 JRST GETMS1		;NO, GET ANOTHER ONE
	HRRZ A,MSG+.MSTYP	;GET THE MESSAGE TYPE
	MOVE D,[-TYPNUM,,TYPTAB]
GETMS2:	HRRZ B,(D)		;GET THE NEXT MESSAGE TYPE
	CAMN A,B		;A MATCH?
	 JRST GETMS3		;YES
	AOBJN D,GETMS2		;NO, TRY AGAIN
	JRST GETMS1		;NOT A MATCH, GET ANOTHER MESSAGE

GETMS3:	HLRZ A,(D)		;GET THE ROUTINE ADDRESS
	CALL (A)		;DO IT
	SKIPE NXTMSG		;IS THERE A MESSAGE WAITING?
	 JRST GETMS1		;YES, DO IT TOO
	RET			;DONE


NORECV:	SPLERR <?IMGSPL Can't receive IPCF messages: %E1>
	HALTF
	RET
; GALAXY MESSAGES WE WILL PAY ATTENTION TO

TYPTAB:	XWD	SETUP,.QOSUP	;SETUP OR SHUTDOWN
	XWD	NXTJOB,.QONEX	;NEXT JOB DESCRIPTION
	XWD	ECANCL,.QOABO	;EXEC CANCEL COMMAND
	XWD	OCANCL,.OMCAN	;OPR ABORT COMMAND
	XWD	REQUEU,.OMREQ	;OPR REQUEUE COMMAND
	XWD	CHKPNT,.QORCK	;QUASAR CHECKPOINT REQUEST
TYPNUM==.-TYPTAB
	SUBTTL REPORT OBJECT DESCRIPTOR BLOCK TO TTY

DORPT:	SKIPN OBJRPT		;WANT THIS?
	 RET			;NO
	TXNN F,F%UP		;STARTED?
	 JRST [	TEXT (OBJTXT,<IMGSPL - Not started%_>)
		RET ]
	PUSH P,A		;SAVE THESE
	PUSH P,B
	MOVE A,OBJBLK+OBJ.UN	;GET THE UNIT NUMBER
	MOVE B,OBJBLK+OBJ.ND	;GET THE NODE NAME
	TEXT (OBJTXT,<IMGSPL - Node %62, Unit %O1%_>)
	POP P,B			;RESTORE THINGS
	POP P,A
	SETZM OBJRPT		;CLEAR FLAG
	RET			;DONE

OBJTXT:	PBOUT			;TEXT ROUTINE FOR OBJECT REPORT
	RET
	SUBTTL JOB ABORT REQUESTED BY USER OR OPERATOR

; JOB CANCELED BY THE USER

ECANCL:	TXO F,F%CAN		;SET CANCEL FLAG
	RET			;DONE



; JOB ABORTED BY THE OPERATOR

OCANCL:	TXNN F,F%JOB		;HAVE A JOB?
	 JRST [	WTO (<Say What?>,<No job to abort>)
		RET ]
	MOVE A,JOBINF+.EQJBB	;GET THE JOB NAME
	ACK (<Aborting>,<Job %61 aborting>)
	TXO F,F%CAN		;SAY CANCELED
	TXNE F,F%TCP		;TCP PRINTER?
	 RET			;YES, HANDLE IN TCP CODE
	CALL RELJOB		;RELEASE THE JOB
	TXZ F,F%REQ!F%CAN!F%JOB
	MOVE P,[IOWD STKLEN,STACK]
	JRST MAIN2		;RESTART EVERYTHING
	SUBTTL REQUEUE REQUESTED BY OPERATOR

REQUEU:	TXOE F,F%REQ		;ALREADY REQUEUED?
	 JRST REQUE1		;YES
	MOVE A,JOBINF+.EQJBB	;GET THE JOB NAME
	ACK (<Job requeued>,<Job %61 requeued>)
	RET			;DONE

REQUE1:	MOVE A,JOBINF+.EQJBB	;GET THE JOB NAME
	ACK (<Job Not Requeued>,<Job %61 finishing up>)
	RET
	SUBTTL NEXT JOB DESCRIPTION

NXTJOB:	TXOE F,F%JOB		;ALREADY HAVE A JOB?
	 RET			;YES, IGNORE THIS ONE
	MOVE A,[MSG,,JOBINF]	;GET THE JOB INFORMATION
	HLRZ B,MSG		;GET THE MESSAGE LENGTH
	BLT A,JOBINF(B)		;MOVE IT INTO THE JOB INFO BLOCK
	RET			;DONE
	SUBTTL DEVICE SETUP AND SHUTDOWN

SETUP:	MOVE A,MSG+SUP.FL	;GET THE FLAGS
	TXNE A,SUFSHT		;REALLY A SETUP?
	 JRST SHTDWN		;NO, SHUTDOWN MESSAGE

	MOVE A,MSG+SUP.TY	;GET THE OBJECT TYPE
	CAIE A,OBJTYP		;OUR OBJECT TYPE?
	 JRST SETBAD
	MOVEM A,OBJBLK		;SAVE IT
	DMOVE A,MSG+SUP.UN	;UNIT AND NODE
	DMOVEM A,OBJBLK+1
	CALL GETDEV		;GET THE DEVICE
	 JRST SETBAD		;CAN'T
	TXO F,F%UP		;WE'RE UP
	WTO <Started>		;TELL ORION WE'RE OK
	MOVEI A,%RSUOK		;GET OK CODE
	SETZM MSG+RSU.CD
	JRST SETUP1		;TELL QUASAR WE'RE OK

SETBAD:	SKIPE A			;ANY ERROR CODE RETURNED?
	 MOVEI A,DIAGX2		;NO, SAY NOT AVAILABLE
	WTO (<Not available>,<%E1>)
	MOVEM A,MSG+RSU.CD
	MOVEI A,%RSUNA		;SAY NOT AVAILABLE

SETUP1:	MOVEM A,MSG+RSU.CO	;STORE THE RESPONSE CODE
	DMOVE A,OBJBLK		;GET THE OBJECT BLOCK
	DMOVEM A,MSG+RSU.TY	;STORE IT
	MOVE A,OBJBLK+2
	MOVEM A,MSG+RSU.NO
	MOVEI A,%LOWER		;SAY LOWER CASE
	HRLM A,MSG+RSU.DA	;SO QUASAR WILL SCHEDULE FOR US
	SETZM MSG+RSU.PN	;NO PROTYPE NODE NAME
	MOVE A,[RSU.SZ,,.QORSU]	;GET HEADER INFORMATION
	MOVEM A,MSG
	CALL SNDQSR		;SEND IT TO QUASAR
	RET			;DONE


SHTDWN:	TXNE F,F%JOB		;HAVE A JOB?
	 RET			;YES, DON'T SHUTDOWN
	MOVE A,MSG+SUP.TY	;GET THE OBJECT TYPE
	CAIE A,OBJTYP		;OUR OBJECT TYPE?
	 RET			;NO, DON'T SHUTDOWN
	TXZN F,F%UP		;NOT UP NOW
	 RET			;AND WEREN'T UP BEFORE
	TXNE F,F%TCP		;TCP DEVICE?
	 RET			;YES, NO JFN TO CLOSE
	MOVE A,LSRJFN		;GET THE JFN
	CLOSF
	 WTO (<Can't release printer>,<%E1: Shutting down anyway>)
	RET			;DONE

GETDEV:	MOVE A,OBJBLK+OBJ.ND	;GET THE NODE NAME
	MOVE B,OBJBLK+OBJ.UN	;GET THE UNIT NUMBER
	MOVE C,[POINT 7,DEVNAM]	;INITIALIZE POINTER
	MOVEM C,DEVPTR
	TEXT (DEVTXT,<%61-LSR%O2:>)

	MOVX A,GJ%SHT		;GET A JFN FOR THE PRINTER
	HRROI B,DEVNAM
	GTJFN
	 RET			;CAN'T
	MOVEM A,LSRJFN		;STORE THE JFN
	TXO F,F%TCP		;ASSUME TCP
	DVCHR			;GET DEVICE CHARACTERISTICS
	LDB A,[POINT 9,B,17]	;GET DEVICE TYPE
	CAIE A,.DVTCP		;TCP?
	CAIN A,.DVCHA		;OR CHAOS?
	 JRST GETDV2		;YES, DON'T OPEN IT
	TXZ F,F%TCP		;SAY NOT TCP
	MOVE A,LSRJFN		;GET JFN
	MOVE B,[FLD(8,OF%BSZ)!OF%WR!OF%RD]
	OPENF			;OPEN IT
	 JRST [	PUSH P,A	;CAN'T SAVE ERROR CODE
		MOVE A,LSRJFN	;GET THE JFN
		RLJFN		;RELEASE IT
		 JFCL
		POP P,A		;RESTORE ERROR CODE
		RET ]
	RFMOD			;GET THE MODE WORD
	TXZ B,TT%DAM!TT%PGM	;BINARY MODE
	SFMOD
	STPAR
	MOVE B,[525252,,525252]
	MOVE C,B		;PASS EVERYTHING
	SFCOC
GETDV1:	AOS (P)			;GIVE SKIP RETURN
	RET			;DONE

GETDV2:	MOVE A,LSRJFN		;GET THE TCP JFN
	RLJFN			;RELEASE IT
	 JFCL
	AOS (P)
	RET

; TEXT ROUTINE TO BUILD DEVICE NAME

DEVTXT:	IDPB A,DEVPTR		;STORE BYTE
	PUSH P,DEVPTR
	MOVEI A,0
	IDPB A,DEVPTR		;ASCIZ THE STRING
	POP P,DEVPTR
	RET			;DONE
	SUBTTL JOB CHECKPOINT

CHKPNT:	PUSH P,A
	PUSH P,B
	PUSH P,C
	MOVE A,JOBINF+.QEITN	;GET THE TASK NAME
	MOVEM A,MSG+CHE.IT	;STORE IT
	MOVX A,CH.FCH!CH.FST	;GET SOME FLAGS
	MOVEM A,MSG+CHE.FL	;STORE IT
	HRROI A,MSG+CHE.ST	;POINT TO THE STATUS MESSAGE
	HRROI B,STSBUF		;AND TO THE STATUS STRING
	SETZ C,
	SOUT			;WRITE IT OUT
	IDPB C,A		;ASCIZ IT
	HRRZS A			;GET ADDRESS OF LAST WORD
	SUBI A,MSG-1		;GET THE MESSAGE LENGTH
	HRLZM A,MSG		;STORE IT
	MOVEI A,.QOCHE		;GET CHECKPOINT TYPE
	HRRM A,MSG		;STORE IT
	CALL SNDQSR		;SEND IT TO QUASAR
	POP P,C
	POP P,B
	POP P,A
	RET			;DONE
	SUBTTL DEVICE STATUS UPDATE

DEVSTS:	DMOVE A,OBJBLK		;GET THE OBJECT BLOCK
	DMOVEM A,MSG+STU.RB
	MOVE A,OBJBLK+2
	MOVEM A,MSG+STU.RB+2
	MOVX A,%ACTIV		;ASSUME DEVICE IS ACTIVE
	TXNE F,F%OFL		;IS IT OFF LINE?
	 MOVX A,%OFLNE		;YES
	TXNN F,F%UP		;STARTED?
	 MOVX A,%IDLE		;NO
	MOVEM A,MSG+STU.CD
	MOVE A,[STU.SZ,,.QOSTU]	;GET THE HEADER WORD
	MOVEM A,MSG		;STORE IT
	CALL SNDQSR		;SEND IT OFF
	RET			;DONE
	SUBTTL SNDQSR/SNDORN - SEND A MESSAGE TO QUASAR OR ORION

SNDQSR:	SKIPA A,QSRPID		;GET QUASAR'S PID
SNDORN:	MOVE A,ORNPID		;GET ORION'S PID

	SETZM MSG+1		;NO FLAGS
	SETZM MSG+2		;NO ACK CODE
	MOVEM A,SNDPDB+.IPCFR	;SAVE RECEIVER PID
	MOVE A,MYPID		;GET OUR PID
	MOVEM A,SNDPDB+.IPCFS	;SAVE AS SENDER PID
	SETZM SNDPDB		;NO FLAGS
	HLLZ A,MSG		;GET LENGTH OF MESSAGE
	HRRI A,MSG		;AND ADDRESS
	MOVEM A,SNDPDB+.IPCFP	;STORE IT
	MOVEI A,4		;LENGTH OF PDB
	MOVEI B,SNDPDB		;ADDRESS OF PDB
	MSEND			;SEND IT OFF
	 SKIPA
	RET			;DONE

	CAIE A,IPCF24		;INVALID MESSAGE SIZE?
	 SPLERR <?IMGSPL Send to Quasar or Orion failed: %E1>
	MOVEM A,SNDPDB+.IPCFL	;TRY SENDING THE PAGE
	MOVE A,[1K,,MSGPAG]
	MOVEM A,SNDPDB+.IPCFP
	MOVEI A,4		;LOAD THESE AGAIN
	MOVEI B,SNDPDB
	MSEND			;SEND IT OFF
	 SKIPA
	RET			;DONE

	SPLERR <?IMGSPL Send to Quasar or Orion failed: %E1>
	SUBTTL GALAXY INITIALIZATION

; SYSPID - GET PIDS FOR SYSTEM QUASAR AND ORION

SYSPID:	MOVEI A,3		;LENGTH OF BLOCK
	MOVEI B,MSG		;ADDRESS OF BLOCK
	MOVEI C,.MURSP		;READ FROM PID TABLE
	MOVEM C,MSG
	MOVEI C,.SPQSR		;READ QUASAR'S PID
	MOVEM C,MSG+1
	MUTIL			;GET QUASAR'S PID
	 JRST NOPIDS
	MOVE C,MSG+2		;GET QUASARS PID
	MOVEM C,QSRPID		;SAVE IT

	MOVEI C,.SPOPR		;READ ORION'S PID
	MOVEM C,MSG+1
	MUTIL
	 JRST NOPIDS
	MOVE C,MSG+2		;GET ORION'S PID
	MOVEM C,ORNPID		;SAVE IT
	RET			;DONE


; PRVPID - GET PIDS FOR PRIVATE QUASAR AND ORION

PRVPID:	HRROI A,[ASCIZ /QUASAR/]
	CALL PRVGET
	MOVEM A,QSRPID
	HRROI A,[ASCIZ /ORION/]
	CALL PRVGET
	MOVEM A,ORNPID
	RET


; PRVGET - GET PRIVATE PID FOR PROCESS. NAME POINTER IN A.

PRVGET:	TXZ F,F%F1
PRVGT1:	PUSH P,A
	MOVE P3,[POINT 7,PRVMS2]
	GJINF
	MOVE B,(P)
	TEXT (PRVTXT,<[%U1]%S2>)
	SETZ A,
	IDPB A,P3
	HRRZS P3
	SUBI P3,PRVMSG-1
	HRLM P3,PRVPDB+.IPCFP
	SETZM PRVMS1
	MOVEI A,4
	MOVEI B,PRVPDB
	MSEND
	 JRST NOPIDS
	MOVEI A,4
	MOVEI B,SHTRCV
	MRECV
	 JRST NOPIDS
	POP P,C
	MOVE A,MSG+1
	LDB B,[POINT 6,SHTRCV,29]
	CAIE B,76
	 RET
	MOVE P3,[POINT 7,STSBUF]
	TEXT (PRVTXT,<%%SPOOL: Waiting for %S3 to start%_>)
	SETZ A,
	IDPB A,P3
	HRROI A,STSBUF
	TXON F,F%F1
	 PSOUT
	MOVEI A,PRVSLP
	DISMS
	MOVE A,C
	JRST PRVGT1

PRVTXT:	IDPB A,P3
	RET


NOPIDS:	TMSG <%IMGSPL: Having trouble getting pids, will retry>
	MOVEI A,PIDSLP		;WAIT
	DISMS
	JRST START		;START OVER
	SUBTTL GET LOCAL HOST NAME

IFNDEF CHANM,<OPDEF CHANM [JSYS 460]>

GETHST:	MOVX A,GJ%SHT!GJ%OLD	;TRY FOR THE HOST NAME FILE
	HRROI B,[ASCIZ /SYSTEM:HOSTNAME.TXT/]
	GTJFN
	 JRST GETHS3		;NOT FOUND, TRY CHAOS
	PUSH P,A		;SAVE THE JFN
	MOVE B,[FLD(7,OF%BSZ)!OF%RD]
	OPENF			;OPEN IT UP
	 JRST [	POP P,A		;CAN'T, RESTORE JFN
		RLJFN		;AND RELEASE IT
		 JFCL
		JRST GETHS3 ]	;AND TRY CHAOS
	MOVE C,[POINT 7,HOSTNM]
GETHS1:	BIN			;GET NEXT CHARACTER
	 ERJMP GETHS2		;END OF FILE
	CAIE B,.CHSPC		;QUIT ON A SPACE
	CAIN B,.CHCRT		;OR A RETURN
	 JRST GETHS2
	IDPB B,C		;STORE IT
	JRST GETHS1		;LOOP BACK
GETHS2:	POP P,A			;RESTORE THE JFN
	CLOSF			;CLOSE THE FILE
	 JFCL
	RET			;DONE

GETHS3:	SETZ A,			;TRY FOR CHAOS PRIMARY NAME
	HRROI B,HOSTNM
	CHANM
	 ERJMP GETHS9		;NOPE
	RET			;DONE

GETHS9:	HRROI A,HOSTNM		;NEITHER
	HRROI B,[ASCIZ /TOPS-20/]
	SETZ C,
	SOUT
	RET
	SUBTTL RELEASE THE CURRENT JOB

RELJOB:	TXZ F,F%JOB		;NO MORE JOBS
	TXNE F,F%REQ		;IS THIS A REQUEUE?
	 JRST REQJOB		;YES, REQUEUE IT INSTEAD
	MOVE A,[REL.SZ,,.QOREL]	;GET HEADER WORD
	MOVEM A,MSG		;STORE IT
	MOVE A,JOBINF+.EQITN	;GET THE INTERNAL TASK NAME
	MOVEM A,MSG+REL.IT	;STORE IT
	SETZM MSG+REL.FL	;NO FALGS
	SETZM MSG+REL.TX	;NO TEXT
	MOVE A,[MSG+REL.TX,,MSG+REL.TX+1]
	BLT A,MSG+REL.SZ	;ZERO THE BLOCK
	CALL SNDQSR		;SEND IT OFF
	RET			;DONE

REQJOB:	MOVE A,[REQ.SZ,,.QOREQ]	;GET THE FUNCTION
	MOVEM A,MSG		;STORE IT
	MOVE A,JOBINF+.EQITN	;GET THE TASK NAME
	MOVEM A,MSG+REQ.IT	;STORE IT
	MOVX A,RQ.HBO		;HAVE OPR HOLD IT
	MOVEM A,MSG+REQ.FL
	CALL SNDORN		;SEND IT OFF
	RET			;DONE
	SUBTTL ORION MESSAGES


.WTO.:	PUSH P,[0]		;NO FLAGS
	PUSH P,[.OMWTO]		;WTO CODE
	JRST WTOX

.ACK.:	PUSH P,[WT.SJI]		;ACK FLAG
	PUSH P,[.OMACK]		;ACK CODE
	JRST WTOX

.WTOJ.:	PUSH P,[WT.JOB]		;JOB FLAG
	PUSH P,[.OMWTO]		;WTO CODE
	JRST WTOX

.LOG.:	PUSH P,[0]		;NO FLAGS
	PUSH P,[.OMLOG]		;LOG CODE
	JRST WTOX

WTOX:	POP P,MSG		;FILL IN THE MESSAGE TYPE
	POP P,MSG+.OFLAG	;FILL IN THE FLAGS
	MOVE P1,[1,,WTOACS]	;SAVE CALLERS ACS
	BLT P1,WTOACS+4		;SAVE AC1 - AC5
	MOVE A,[4,,.WTOBJ]	;START WITH THE OBJECT BLOCK
	MOVE B,OBJBLK
	DMOVEM A,MSG+5
	DMOVE A,OBJBLK+1
	DMOVEM A,MSG+7
	MOVEI A,1		;ONE ARGUMENT SO FAR
	MOVEM A,MSG+.OARGC	;SAVE IT
	MOVEI A,MSG+11		;NEXT FREE ADDRESS
	MOVEM A,WTOADR		;SAVE IT
	MOVE A,(P)		;GET THE RETURN ADDRESS
	HRRZ A,(A)		;GET THE STRING
	MOVEI B,.WTTYP		;TYPE FIELD
	CALL WTOTXT		;FILL IT IN
	MOVE A,(P)		;GET RETURN ADDRESS
	HRRZ A,1(A)		;GET SECOND STRING
	MOVEI B,.WTTXT		;TEXT FIELD
	CALL WTOTXT		;FILL IT IN
	MOVE A,WTOADR		;GET NEXT FREE ADDRESS
	SUBI A,MSG		;GET TOTAL ADDRESS
	HRLM A,MSG		;SAVE IT
	CALL SNDORN		;SEND IT OFF
	MOVE P1,[WTOACS,,1]	;RESTORE CALLERS ACS
	BLT P1,5
	RET			;DONE
WTOTXT:	SKIPN A			;ANY STRING?
	 RET			;NO, DONE
	AOS MSG+.OARGC		;BUMP THE ARGUMENT COUNT
	MOVEM B,@WTOADR		;FILL IN NEXT FIELD TYPE
	PUSH P,WTOADR		;SAVE THIS ADDRESS
	AOS B,WTOADR		;BUMP FREE ADDRESS
	HLL B,[POINT 7,0]	;MAKE A STRING POINTER
	MOVEM B,WTOPTR		;SAVE IT
	MOVE P2,A		;GET THE STRING
	MOVE P1,[WTOACS,,1]	;RESTORE CALLERS ACS
	BLT P1,5
	CALL TEXT.		;EXPAND THE TEXT
	 JUMP WTOFIL
	 JUMP (P2)
	MOVE P1,[1,,WTOACS]	;SAVE CALLERS ACS AGAIN
	BLT P1,WTOACS+4
	SETZ A,			;ASCIZ THE STRING
	IDPB A,WTOPTR
	HRRZ B,WTOPTR		;GET LAST ADDRESS USED
	AOS B			;ADJUST
	MOVEM B,WTOADR		;SAVE IT
	POP P,A			;GET FIRST ADDRESS
	SUB B,A			;GET LENGTH OF FIELD
	HRLM B,(A)		;FILL IT IN
	RET			;DONE


WTOFIL:	IDPB A,WTOPTR		;SAVE THE BYTE
	RET			;RETURN
	SUBTTL JOB PROCESSING

DOJOB:	MOVEI A,.FHSLF		;GET OUR RUN TIME
	RUNTM
	MOVNM A,RUNTIM		;SAVE FOR LATER
	GTAD			;GET CURRENT DATE AND TIME
	MOVEM A,JOBTIM		;SAVE FOR LATER
	SETZM JOBCNT		;NO PAGES PRINTED YET
	SETZM FILCNT		;NO FILES PRINTED YET
	HRRZ A,JOBINF+.EQSPC	;GET NUMBER OF FILES IN REQUEST
	MOVEM A,NFILES		;SAVE IT
	HRRZ A,JOBINF+.EQLEN	;GET LENGTH OF THE EQ HEADER
	ADDI A,JOBINF		;GET ADDRESS OF FIRST FILE
	MOVEM A,FILPTR		;SAVE IT
	MOVE A,JOBINF+.EQOID	;GET THE USER NUMBER
	MOVE B,JOBINF+.EQJBB	;GET THE JOB NAME
	MOVE C,JOBINF+.EQRID	;GET THE REQUEST ID
	WTOJ (<Begin>,<job %62, Req #%N3 for %U1>)
	TXZ F,F%LST!F%OFL	;RESET THESE
	CALL DEVSTS		;SAY ON LINE

DOJOB1:	AOS A,FILCNT		;BUMP THE FILE COUNT
	CAMN A,NFILES		;THIS THE LAST ONE?
	 TXO F,F%LST		;YES, FLAG IT
	CALL DOFILE		;PRINT THIS FILE
	MOVE A,FILCNT		;GET THE NUMBER OF FILES PRINTED
	CAML A,NFILES		;DONE THEM ALL?
	 JRST DOJOB2		;YES, QUIT
	MOVE A,FILPTR		;GET POINTER TO LAST FILE
	HLRZ B,.FPLEN(A)	;GET THE LENGTH OF THE FP
	ADD A,B			;MOVE TO THE FD
	HLRZ B,.FDLEN(A)	;GET LENGTH OF THE FD
	ADD A,B			;MOVE TO NEXT FILE
	MOVEM A,FILPTR
	JRST DOJOB1		;LOOP BACK

DOJOB2:	SETZM FILCNT		;START OVER
	HRRZ A,JOBINF+.EQSPC	;GET NUMBER OF FILES IN REQUEST
	MOVEM A,NFILES		;SAVE IT
	HRRZ A,JOBINF+.EQLEN	;GET LENGTH OF THE EQ HEADER
	ADDI A,JOBINF		;GET ADDRESS OF FIRST FILE
	MOVEM A,FILPTR		;SAVE IT

DOJOB3:	AOS FILCNT		;BUMP THE FILE COUNT
	CALL DELFIL		;CHECK FOR DELETION
	MOVE A,FILCNT		;GET THE NUMBER OF FILES PRINTED
	CAML A,NFILES		;DONE THEM ALL?
	 JRST DOJOB4		;YES, QUIT
	MOVE A,FILPTR		;GET POINTER TO LAST FILE
	HLRZ B,.FPLEN(A)	;GET THE LENGTH OF THE FP
	ADD A,B			;MOVE TO THE FD
	HLRZ B,.FDLEN(A)	;GET LENGTH OF THE FD
	ADD A,B			;MOVE TO NEXT FILE
	MOVEM A,FILPTR
	JRST DOJOB3		;LOOP BACK
DOJOB4:	RET			;DONE

DELFIL:	MOVE D,FILPTR		;POINT TO THE FILE PARAMETER BLOCK
	MOVE A,.FPFR2(D)	;GET FLAGS
	TXNE A,FP.SDP		;SCREEN DUMP?
	 JRST DELFL0		;YES, DELETE IT
	MOVE A,.FPINF(D)	;GET PARAMETERS
	TXNN A,FP.SPL!FP.DEL	;/DELETE OR SPOOLED?
	 RET			;NO, DON'T DELETE IT
DELFL0:	HLRZ B,.FPLEN(D)	;GET LENGTH OF THE FP
	ADD B,D			;MOVE TO THE FD
	AOS B			;MOVE TO THE FILE NAME
	MOVE C,B		;SAVE IT HERE TOO
	HRROS B			;MAKE IT A POINTER
	MOVX A,GJ%SHT!GJ%OLD	;GET A JFN AGAIN
	GTJFN
	 JRST [	LOG (<Can't delete file>,<%S3: %E1>)
		RET ]		;QUIT
	MOVEM A,INJFN		;SAVE THE JFN

	MOVE D,FILPTR		;POINT TO THE FILE PARAMETER BLOCK
	MOVE A,.FPFR2(D)	;GET FLAGS
	TXNE A,FP.SDP		;SCREEN DUMP?
	 JRST DELFL1		;YES, NO ACCESS CHECK
	MOVE A,.FPINF(D)	;GET PARAMETERS
	TXNE A,FP.SPL		;SPOOLED?
	 JRST DELFL1		;YES, ALWAYS DELETE
	CALL DLACES		;ACCESS ALLOWED?
	 JRST [	LOG (<Can't delete file>,<%S3: CHKAC said not to>)
		JRST DELFL2 ]	;NO
	LOG (<Deleting file>,<%S3>)
DELFL1:	MOVE A,INJFN		;GET JFN
	TXO A,DF%EXP		;EXPUNGE ALSO
	DELF
	 JRST [	LOG (<Can't delete file>,<%S3: %E1>)
		JRST DELFL2 ]
	RET			;DONE

DELFL2:	MOVE A,INJFN		;GET THE JFN
	RLJFN			;RELEASE IT
	 JFCL
	RET			;DONE
	SUBTTL ACCOUNTING


DOACT:	MOVE A,JOBINF+.EQOID	;GET THE USER NUMBER
	MOVE B,JOBINF+.EQJBB	;GET THE JOB NAME
	MOVE C,JOBINF+.EQRID	;GET THE REQUEST ID
	TXNE F,F%TCP		;REMOTE JOB?
	 JRST [	WTOJ (<End>,<job %62, Req #%N3 for %U1 (TCP printer)>)
		RET ]
	MOVE D,JOBCNT		;GET THE PAGE COUNT
	CAIE D,1
	 WTOJ (<End>,<job %62, Req #%N3 for %U1 (%N4 pages)>)
	CAIN D,1
	 WTOJ (<End>,<job %62, Req #%N3 for %U1 (%N4 page)>)

DOACT1:	MOVX A,.FHSLF		;THIS FORK
	RUNTM			;GET OUR RUNTIME
	ADDM A,RUNTIM		;GET TIME USED
	LDB A,[POINT 6,JOBINF+.EQSEQ,35]
	MOVEM A,JOBPRI		;STORE JOB PRIORITY
	MOVX A,.USENT		;WRITE AN ENTRY
	MOVEI B,ACTLST		;POINT TO THE LIST
IFN ACCTSW,<
	USAGE			;DO IT
	 ERJMP ACTERR		;RATS
>;IFN ACCTSW
	RET			;DONE

ACTERR:	SETO A,			;TELL ORION WHAT WENT WRONG
	WTO (<Accounting Error>,<USAGE%% failed: %E1>)
	RET			;DONE

ACTLST:	USENT.	(.UTOUT,1,1,0)
	USTAD.	(-1)			;CURRENT DATE/TIME
	USPNM.	(<SIXBIT/IMGSPL/>,US%IMM) ;PROGRAM NAME
	USPVR.	(%IMG,US%IMM)		;PROGRAM VERSION
	USAMV.	(-1)			;ACCOUNTING MODULE VERSION
	USNOD.	(JOBINF+.EQROB+.ROBND)	;NODE NAME
	USSRT.	(RUNTIM)		;RUN TIME
	USSDR.	(0,US%IMM)		;DISK READS
	USSDW.	(0,US%IMM)		;DISK WRITES
	USJNM.	(JOBINF+.EQJOB)		;JOB NAME
	USQNM.	(<SIXBIT /LSR/>,US%IMM)	;QUEUE NAME
	USSDV.	(DEVNAM)		;DEVICE NAME
	USSSN.	(JOBINF+.EQRID)		;JOB SEQUENCE NUMBER
	USSUN.	(PAGCNT)		;TOTAL PAGES PRINTED
	USSNF.	(NFILES)		;TOTAL FILES PROCESSED
	USCRT.	(JOBINF+.EQAFT)		;CREATION DATE/TIME OF REQUEST
	USSCD.	(JOBTIM)		;SCHEDULED DATE/TIME
	USFRM.	(<SIXBIT /LETTER/>,US%IMM) ;FORMS TYPE
	USDSP.	(<SIXBIT/NORMAL/>,US%IMM)  ;DISPOSITION
	USPRI.	(JOBPRI)		;JOB PRIORITY
	USJNO.	(-1)			;JOB NUMBER
	USTRM.	(-1)			;TERMINAL DESIGNATOR
	USLNO.	(-1)			;TTY LINE NUMBER
	USTXT.	(<-1,,[ASCIZ / /]>)	;SYSTEM TEXT
	USNM2.	(<POINT 7,JOBINF+.EQOWN>) ;USER NAME
	USACT.	(<POINT 7,JOBINF+.EQACT>) ;ACCOUNT STRING POINTER
	0				;END OF LIST
	SUBTTL FILE OUTPUT - MAIN LOOP

DOFILE:	GTAD			;GET THE TIME
	MOVEM A,FILTIM		;STORE IT
	STATUS <Printing, Started at %T1>
	CALL OPNFIL		;OPEN THE OUTPUT FILES
	CALL SETFIL		;SET FILE PARAMETERS
	CALL FIXHDR		;BUILD A HEADER COMMAND
	CALL FIXFIL		;FIX THE FILE
	DBGINF <Starting file>
	TXNE F,F%TCP		;TCP PRINTER?
	 JRST TCPOUT		;YES, DO DIFERENT
	CALL CLRTBL		;CLEAR THE PACKET TABLE
	SETOM LSTACK		;NOTHING ACK'D YET
	TXZ F,F%SYN		;NO SYNC YET
	CALL DOSYNC		;SYNC WITH THE PRINTER
	DBGINF <Sync Received>
	MOVE A,FILTIM		;GET START TIME
	STATUS <Printing, Started at %T1>
	TXZ F,F%EOF!F%HDR!F%PAB!F%JIP
	SETZM PKTNUM		;ZERO THE PACKET NUMBER
	CALL SNDHDR		;SEND THE HEADER
	DBGINF <Header Sent>

DOFIL1:	TXNE F,F%SYN!F%CAN
	 JRST DOFIL3		;SOMETHING'S WRONG
	CALL CHKLSR		;CHECK THE PRINTER
	CALL GETPKT		;GET A PACKET
	 JRST [	MOVEI A,WRPSLP	;WRAP AROUND
		DISMS
		DBGINF <Wrap around wait>
		CALL RSVP	;GOOSE A REPLY
		MOVEI A,RSVSLP
		DISMS
		JRST DOFIL1 ]
	 JRST DOFIL2		;END OF FILE
	CALL SNDPKT		;SEND IT OUT
	JRST DOFIL1		;LOOP BACK

DOFIL2:	CALL RSVP		;SEND AN RSVP
	MOVEI A,RSVSLP
	DISMS
	PUSH P,PKTNUM		;SAVE THE PACKET NUMBER
	CALL CHKLSR		;CHECK THE PRINTER
	POP P,A			;GET OLD PACKET NUMBER
	CAME A,PKTNUM		;ANY REDO'S?
	 JRST DOFIL1		;YES
	SOS A			;LOOK AT LAST PACKET SENT
	ANDI A,MAXPKT
	SKIPL PKTTBL(A)		;LAST ONE ACK'D?
	 JRST [	MOVEI A,EOFSLP	;NO, WAIT SOME
		DISMS
		JRST DOFIL2 ]	;TRY AGAIN
	MOVE A,FILTIM
	STATUS <Printing, started at %T1>
	DBGINF <Sending EOF packet>
	CALL DOEOF		;SEND END OF FILE PACKET
	MOVE A,INJFN		;GET THE JFN
	CLOSF			;CLOSE IT
	 JFCL
	CALL GETCNT		;GET THE PAGE COUNT
	RET			;DONE

DOFIL3:	SETO A,			;USE CURRENT TIME
	TXNE F,F%SYN		;PRINTER ABORT?
	 STATUS <Printer problem, aborted at %T1>
	TXNE F,F%CAN		;CANCELED?
	 STATUS <Canceled at %T1>
	TXO F,F%PAB		;SET ABORT FLAG
	CALL RSVP		;TELL PRINTER TO ABORT
	MOVEI A,RSVSLP
	DISMS
	TXZ F,F%PAB		;RESET FLAG
	CALL DOEOF		;SEND EOF
	MOVE A,INJFN		;GET INPUT FILE
	CLOSF			;CLOSE IT
	 JFCL
	TXNE F,F%CAN		;CANCELED BY USER?
	 CALL GETCNT		;YES, DO ACCOUNTING
	RET			;DONE
	SUBTTL FILE OUTPUT - TCP PRINTER

TCPOUT:	STATUS <Waiting for printer>
TCPOT1:	CALL CHKMSG		;CHECK FOR GALAXY MESSAGE
	TXNE F,F%CAN		;STILL GOING?
	 JRST TCPOT8		;NO
	MOVX A,GJ%SHT		;GET THE PRINTER
	HRROI B,DEVNAM
	GTJFN
	 FATAL
	MOVEM A,LSRJFN		;SAVE PRINTER JFN
	MOVE B,[FLD(8,OF%BSZ)!OF%WR!OF%RD]
	OPENF			;OPEN THE CONNECTION
	 JRST [	  PUSH P,A
		  MOVE A,[POINT 7,STSBUF]
		  MOVEM A,STSPTR
		  POP P,A
		  TEXT (STSTXT,<Waiting for printer, %E1>)
		  CALL CHKPNT
		MOVE A,LSRJFN	;CAN'T, GET JFN BACK
		RLJFN		;RELEASE IT
		 JFCL
		MOVEI A,TCPSLP
		DISMS		;WAIT A WHILE
		JRST TCPOT1 ]	;AND TRY AGAIN
	TXO F,F%OPN		;SAY CONNECTION OPEN

IFN REMSPL,<
	MOVE A,OBJBLK+OBJ.ND	;GET THE NODE NAME
	CAMN A,[SIXBIT /LOCAL/]	;LOCAL NODE?
	 JRST TCPOTX		;YES, NO BACKTALK
	STATUS <Waiting for remote spooler>
	MOVE D,[POINT 7,PACKET]	;USE THE PACKET BUFFER FOR A WHILE
TCPOT0:	MOVE A,LSRJFN		;LISTEN TO THE CONNECTION
	BIN			;GET NEXT BYTE
	CAIE B,.CHCRT		;RETURN?
	CAIN B,.CHLFD		;OR LINE FEED?
	 SKIPA			;YES, DON'T STORE IT
	IDPB B,D		;STORE CHARACTER
	SIBE			;ANY MORE
	 JRST TCPOT0		;YES
	SETZ B,
	IDPB B,D
	HRROI A,PACKET
	LOG (<Signon to remote spooler>,<%S1>)
>;IFN REMSPL
TCPOTX:	MOVE A,FILTIM
	STATUS <Sending file, Started at %T1>
	TXZ F,F%EOF!F%HDR!F%PAB!F%JIP

	CALL CHKMSG		;CHECK FOR GALAXY MESSAGE
	TXNE F,F%CAN		;STILL GOING?
	 JRST TCPOT8		;NO
	MOVE A,LSRJFN		;GET THE PRINTER
	MOVE B,[POINT 7,HDRTXT]	;POINT TO THE HEADER
	IBP B			;SKIP TO GOOD STUFF
	SETZ C,
	SOUT			;SEND IT
	 ERJMP TCPOT8

TCPOT2:	MOVEI C,TCPGLX		;CHECK GALAXY EVERY NOW AND THEN
	CALL CHKMSG
	TXNE F,F%CAN		;STILL GOING?
	 JRST TCPOT8		;NO
TCPOT3:	MOVE A,INJFN		;GET NEXT INPUT BYTE
	BIN
	 ERJMP TCPOT4		;END OF FILE
	TXNE F,F%ARO		;ARROW MODE?
	 CALL CHKARO		;YES, CHECK CHARACTER
	MOVE A,LSRJFN		;SEND IT TO THE PRINTER
	BOUT
	 ERJMP TCPOT8
	SOSLE C
	 JRST TCPOT3		;LOOP BACK
	JRST TCPOT2		;CHECK GALAXY

TCPOT4:	MOVE A,LSRJFN		;END OF FILE
	HRROI B,[ASCIZ //]
	SETZ C,
	SOUTR			;FLUSH EVERYTHING
	STATUS <Transfer complete>
	MOVE A,LSRJFN
	CLOSF			;CLOSE THE CONNECTION
	 JFCL
	MOVE A,INJFN		;CLOSE THE INPUT FILE
	CLOSF
	 JFCL
	TXZ F,F%OPN		;CONNECTION NOT OPENED
	RET			;DONE



TCPOT8:	SETO A,			;CURRENT TIME
	TXNN F,F%CAN		;ERROR?
	 STATUS <Aborted due to connection error at %T1>
	TXNE F,F%CAN		;CANCELED?
	 STATUS <Canceled at %T1>
	MOVE A,LSRJFN		;GET THE JFN
	TXO A,CZ%ABT		;KEEP THE JFN AND ABORT THE CONNECTION
	TXZE F,F%OPN		;WAS CONNECTION OPEN?
	CLOSF			;YES, CLOSE IT
	 JFCL
	RET
	SUBTTL FILE OUTPUT - PRINTER STATUS

; CHKLSR - CHECKS THE PRINTERS PROGRESS

CHKLSR:	CALL CHKMSG		;CHECK FOR A GALAXY MESSAGE
	CALL CHKPKT		;ANY PACKETS WAITING?
	 RET			;NO, ASSUME EVERYTHING OK
	CALL RCVPKT		;GET THE PACKET
	 JRST CHKLSR		;CAN'T
	DBGINF <Received packet>
	DMOVE A,LSRPKT+.TYPE	;GET THE PACKET TYPE
	CAIE A,"S"		;STATUS PACKET?
	 JRST CHKLSR		;NO, TRY AGAIN
	CAIN B,"i"		;INFO?
	 JRST LSRINF		;YES
	CAIN B,"n"		;NAK?
	 JRST LSRNAK		;YES
	CAIN B,"s"		;SYNC?
	 TXO F,F%SYN		;YES, MARK IT
	CAIN B,"#"		;ACCOUNTING RESPONSE?
	 JRST LSRPGC		;YES
	JRST CHKLSR		;NONE OF THESE, TRY FOR ANOTHER

LSRNAK:	MOVEI A,LSRPKT+.PKTCD	;GET THE PACKET CODE
	CALL GETHEX		;GET THE NUMBER
	CALL RELPKT		;RELEASE OK'D PACKETS
	AOS A			;BUMP TO BAD ONE
	ANDI A,MAXPKT		;TRIM IT DOWN
	CALL REDOPK		;RESEND THE PACKET
	MOVEI A,NAKSLP		;WAIT A WHILE
	DISMS
	MOVE A,LSRJFN		;GET THE JFN
	CFIBF			;CLEAR ALL NAK PACKETS
	JRST CHKLSR		;TRY AGAIN

LSRINF:	MOVEI A,LSRPKT+.PKTCD	;GET THE PACKET CODE
	CALL GETHEX		;GET THE NUMBER
	CALL RELPKT		;RELEASE OK'D PACKETS
LSRWND:	MOVEI A,LSRPKT+.WINDO	;GET THE WINDOW SIZE
	CALL GETHEX		;TOP HALF
	LSH A,8			;MOVE IT OVER
	MOVE B,A		;SAVE IT
	MOVEI A,LSRPKT+.WINDO+2	;BOTTOM HALF
	CALL GETHEX
	OR A,B			;GET WINDOW SIZE
	CAIGE A,MINWIN		;ENOUGH FOR ANOTHER PACKET?
	 JRST LSRWAT		;NO, WAIT SOME
	MOVE A,LSRPKT+.PSTAT	;GET STATUS CODE
	SUBI A," "		;SUBTRACT THE SPACE
	TXNE A,17		;PRINTER OK?
	 CALL OFFLIN		;NO, SAY OFFLINE
	TXNN A,17		;ON LINE?
	 CALL ONLINE		;YES, SAY SO
	TXZ F,F%JIP		;SAY NO JOB IN PROGRESS
	TXNE A,1B30!1B31	;JOB IN PROGRESS?
	 TXO F,F%JIP		;YES
	JRST CHKLSR		;CHECK AGAIN
LSRWAT:	CALL RSVP		;SEND AN RSVP PACKET
	MOVEI A,WINSLP		;WAIT A WHILE
	DISMS
	JRST CHKLSR		;CHECK AGAIN


LSRPGC:	MOVEI A,LSRPKT+.LSRCT	;POINT TO THE NUMBER
	CALL GETHEX		;GET TOP HALF
	MOVE B,A		;SAVE IT
	MOVEI A,LSRPKT+.LSRCT+2
	CALL GETHEX		;GET BOTTOM HALF
	LSH B,8			;MOVE THINGS OVER
	OR A,B			;GET WHOLE NUMBER
	MOVEM A,PAGCNT		;SAVE THE COUNT
	TXO F,F%PGC		;SAY NUMBER IS VALID
	JRST CHKLSR		;TRY FOR ANOTHER
; CHKPKT - CHECKS FOR A PACKET FROM THE PRINTER.
;          RETURNS +1 IF ONE IS THERE, + 2 IF NOT.

CHKPKT:	MOVE A,LSRJFN		;GET PRINTER JFN
	SIBE			;INPUT BUFFER EMPTY?
	 AOS (P)		;NO, GIVE SKIP RETURN
	RET			;DONE


; RCVPKT - RECEIVES A PACKET FROM THE PRINTER.
;	   RETURNS +2 IF GOOD PACKET IS READ.

RCVPKT:	MOVE D,[-PKTLEN,,LSRPKT]
RCVPK1:	MOVE A,LSRJFN		;GET THE PRINTER
	SIBE			;ANYTHING THERE?
	 SKIPA			;YES
	 JRST [	MOVEI A,CHRSLP	;NO, WAIT
		DISMS
		MOVE A,LSRJFN
		SIBE		;STILL EMPTY?
		 JRST .+1	;NO
		RET ]		;YES
	BIN			;GET NEXT BYTE
	CAIN B,PK%BGN		;PACKET BEGIN CHARACTER?
	 MOVE D,[-PKTLEN,,LSRPKT] ;YES, RESET COUNTER
	MOVEM B,(D)		;SAVE BYTE
	CAIN B,PK%END		;END OF PACKET?
	 JRST RCVPK2		;YES
	AOBJN D,RCVPK1		;NO, TRY AGAIN
	RET			;TOO LONG, QUIT
RCVPK2:	SETZM 1(D)		;END THE PACKET
	MOVE A,LSRPKT		;GET FIRST CHARACTER
	CAIE A,PK%BGN		;LOOK GOOD?
	 RET			;NO
	MOVE A,LSRPKT+.PKLEN	;GET LENGTH
	CAIE A,"1"		;RIGHT?
	 RET			;NO
	MOVE A,LSRPKT+.PKLEN+1	;LOW DIGIT OF LENGTH
	CAIE A,"1"		;"1" FOR STATUS
	CAIN A,"5"		;"5" FOR ACCOUNTING
	SKIPA			;OK
	 RET			;BAD
	MOVE A,LSRPKT+.TYPE	;PACKET TYPE
	CAIE A,"S"		;STATUS?
	 RET			;NO
	MOVE B,[-4,,LSRPKT+.WINDO]
RCVPK3:	MOVE A,(B)		;CHECK WINDOW SIZE
	CALL ISNUM
	 RET
	AOBJN B,RCVPK3
	MOVE A,LSRPKT+.PKTCD	;ACK CODE
	CAIL A,"0"		;0..7
	CAILE A,"7"
	 RET
	MOVE A,LSRPKT+.PKTCD+1
	CALL ISNUM
	 RET
	MOVE B,[-4,,LSRPKT+.LSRCT]
	MOVE A,LSRPKT+.TYPE+1	;GET TYPE
	CAIN A,"#"		;ACCOUNTING RESPONSE?
	 ADDI B,4		;YES, SKIP COUNT
RCVPK4:	MOVE A,(B)
	CALL ISNUM
	 RET
	AOBJN B,RCVPK4
	MOVE A,(B)		;CHECK FOR END
	CAIE A,PK%END
	 RET
	AOS(P)			;LOOKS GOOD
	RET


; ISNUM - RETURNS +2 IF THE CHARACTER IN A IS A HEX DIGIT

ISNUM:	CAIL A,"0"
	CAILE A,"9"
	SKIPA			;NOT A DIGIT
	 JRST ISNUM1
	CAIL A,"A"
	CAILE A,"F"
	RET			;NOT A LETTER
ISNUM1:	AOS (P)
	RET
; OFFLIN - PROCESS AN OFF LINE SIGNAL FROM THE PRINTER

OFFLIN:	PUSH P,A
	TXOE F,F%OFL		;ALREADY OFF LINE?
	 JRST OFFLN1		;YES
	CALL DEVSTS		;TELL QUASAR
	WTO <Offline>		;TELL ORION
	GTAD			;GET CURRENT TIME
	MOVEM A,OFLTIM		;SAVE IT
	CALL OFLNOT		;NOTIFY USER
	DBGINF <  Printer is off line>
	POP P,A
	RET			;DONE

OFFLN1:	GTAD			;GET CURRENT TIME
	SUB A,OFLTIM		;GET TIME SINCE LAST NOTIFICATION
	CAIG A,OFLTMX		;BEEN TOO LONG?
	 JRST OFFLN2		;NO
	ADDM A,OFLTIM		;SAVE NEW TIME
	CALL OFLNOT		;NOTIFY AGAIN
OFFLN2:	POP P,A
	RET


; ONLINE - PROCESS AN ON LINE SIGNAL FROM THE PRINTER

ONLINE:	TXZN F,F%OFL		;OFF LINE BEFORE?
	 RET			;NO
	PUSH P,A
	CALL DEVSTS		;TELL QUASAR
	POP P,A
	DBGINF <  Printer is on line>
	RET			;DONE
; DOSYNC - SEND A SYNC PACKET TO THE PRINTER.
;          RETURNS AFTER THE PRINTER HAS RETURNED A SYNC.

DOSYNC:	STATUS <Requesting Sync>
DOSYN1:	MOVE A,[SYNCPK,,PACKET]	;GET THE SYNC PACKET
	BLT A,PACKET+SYNCLN	;PUT IN BUFFER
	MOVEI A,SYNCLN		;GET THE LENGTH
	CALL SNDPKT		;SEND IT OFF
	MOVEI A,RSVSLP		;WAIT
	DISMS
	CALL CHKLSR		;CHECK THE PRINTER
	TXZN F,F%SYN		;RECEIVE SYNC?
	 JRST DOSYN1		;NO
	STATUS <Sync received>
	RET			;DONE

SYNCPK:	EXP PK%BGN		;BEGIN PACKET
	EXP "1","1"		;LENGTH
	EXP "S"			;STATUS
	EXP "s"			;SYNC REQUEST
	EXP "F","F","F","F"	;WINDOW SIZE
	EXP "F","F"		;PACKET CODE
	EXP " "			;ERROR TYPE
	EXP 0,0,0,0		;CHECKSUM
	EXP PK%END		;END OF PACKET
SYNCLN==.-SYNCPK




; RSVP - SEND AN RSVP PACKET.

RSVP:	DBGINF <Sending RSVP>
	MOVE A,[RSVPPK,,PACKET]	;GET THE RSVP PACKET
	BLT A,PACKET+RSVPLN	;PUT IN BUFFER
	MOVEI A,0		;GET ABORT CODE
	TXNE F,F%PAB		;NEED TO TELL PRINTER TO ABORT?
	 MOVEM A,PACKET+.PSTAT	;YES
	MOVEI A,RSVPLN		;GET THE LENGTH
	CALL SNDPKT		;SEND IT OFF
	RET			;DONE

RSVPPK:	EXP PK%BGN		;BEGIN PACKET
	EXP "1","1"		;LENGTH
	EXP "S"			;STATUS
	EXP "r"			;SYNC REQUEST
	EXP "F","F","F","F"	;WINDOW SIZE
	EXP "F","F"		;PACKET CODE
	EXP " "			;ERROR TYPE
	EXP 0,0,0,0		;CHECKSUM
	EXP PK%END		;END OF PACKET
RSVPLN==.-RSVPPK
	SUBTTL FILE OUTPUT - PACKET SENDING

; SNDPKT - SENDS A PACKET TO THE PRINTER.
;	   PACKET IS IN THE PACKET BUFFER, LENGTH IN A.

SNDPKT:	MOVE B,PKTNUM
	DBGINF <Sending packet # %O2, Length %O1>
	CALL CHKSUM		;COMPUTE THE CHECKSUM
	MOVN C,A		;GET THE LENGTH IN C
	MOVE A,LSRJFN		;GET PRINTER JFN
	MOVE B,[POINT 36,PACKET]
	SOUT			;WRITE IT OUT
	RET			;DONE


; CHKSUM - COMPUTES CHECKSUM FOR THE PACKET BUFFER.
;	   LENGTH OF PACKET IN A.

CHKSUM:	PUSH P,A		;SAVE LENGTH
	SUBI A,5		;CHOP OFF CHECKSUM BYTES AND END CHAR
	MOVN D,A		;NEGATE INTO D
	HRLZS D			;PUT IN LEFT HALF
	HRRI D,PACKET		;GET ADDRESS OF BUFFER
	SETZ B,			;B IS THE CHECKSUM
CHKSM1:	LSH B,1			;LEFT SHIFT ONE
	TXZE B,1B19		;OVERFLOW?
	 TXO B,1B35		;YES, ROTATE IT
	ADD B,(D)		;ADD IN THIS BYTE
	ANDI B,177777		;TRIM DOWN TO 16 BITS
	AOBJN D,CHKSM1		;LOOP BACK
	LSH B,1			;ROTATE ONCE MORE
	TXZE B,1B19		;OVERFLOW?
	 TXO B,1B35		;YES, ROTATE IT
	ADDI B,PK%END		;ACCOUNT FOR END CHARACTER
	ANDI B,177777		;TRIM IT DOWN
	MOVE A,D		;GET ADDRESS OF WHERE TO PUT IT
	HLL A,[POINT 36,0]	;MAKE IT A POINTER
	MOVE C,[NO%LFL!NO%ZRO!FLD(4,NO%COL)!FLD(^D16,NO%RDX)]
	NOUT			;ADD IT TO THE PACKET IN HEX
	 FATAL			;CAN'T
	MOVEI B,PK%END
	IDPB B,A		;NOUT ZEROED THE END CHAR
	POP P,A			;GET LENGTH BACK
	RET			;DONE
; GETHEX - READS TWO BYTE ASCII HEX NUMBER
;	   A POINTS TO TEXT, NUMBER RETURNED IN A.

GETHEX:	PUSH P,B		;SAVE THIS
	MOVE B,(A)		;GET THE FIRST CHARACTER
	CAIL B,"A"		;LETTER?
	 SUBI B,7		;YES, ADJUST
	SUBI B,"0"		;CONVERT TO BINARY
	LSH B,4			;MOVE IT OVER
	PUSH P,B		;SAVE IT
	MOVE B,1(A)		;GET SECOND CHARACTER
	CAIL B,"A"		;LETTER?
	 SUBI B,7		;YES, ADJUST
	SUBI B,"0"		;CONVERT TO BINARY
	POP P,A			;GET FIRST PART
	OR A,B			;GET FULL BYTE
	POP P,B
	RET			;DONE
	SUBTTL FILE OUTPUT - FINISH UP

; DOEOF - SENDS EOF TO THE PRINTER AND WAITS FOR IT
;	  TO FINISH THE JOB.

DOEOF:	TRVAR <EOFCTR>
	TXO F,F%EOF		;SAY SENDING EOF
	CALL SNDEOF		;SEND THE EOF PACKET
	MOVEI A,^D10		;10 TIMES MAX THROUGH FIRST LOOP
	MOVEM A,EOFCTR

DOEOF1:	CALL RSVP		;SEND AN RSVP
	MOVEI A,RSVSLP
	DISMS
	CALL CHKLSR		;CHECK THE PRINTER
	TXNE F,F%JIP		;JOB IN PROGRESS?
	 JRST DOEOF2		;YES
	MOVEI A,EOFSLP		;NOT PRINTING YET
	DISMS
	SOSLE EOFCTR		;BUMP COUNTER
	 JRST DOEOF1		;TRY AGAIN
	WTO (<Could be trouble>,<F%%JIP never came on in DOEOF1 loop>)

DOEOF2:	CALL CHKMSG		;CHECK FOR ABORT
	CALL RSVP		;SEND AN RSVP
	MOVEI A,RSVSLP
	DISMS
	CALL CHKLSR		;CHECK THE PRINTER
	TXNN F,F%JIP		;STILL PRINTING?
	 JRST DOEOF3		;NO
	MOVEI A,EOFSLP		;WAIT A WHILE
	DISMS
	JRST DOEOF2		;TRY AGAIN

DOEOF3:	TXZ F,F%EOF		;NO EOF IN PROGRESS NOW
	RET			;ALL DONE
; SNDEOF - SENDS AN EOF PACKET

SNDEOF:	MOVE A,[EOFPKT,,PACKET]	;GET THE EOF PACKET
	BLT A,PACKET+EOFLEN	;PUT IN BUFFER
	MOVE B,PKTNUM		;GET PACKET NUMBER
	MOVE A,[POINT 36,PACKET+.PKTNM]
	MOVE C,[NO%LFL!NO%ZRO!FLD(2,NO%COL)!FLD(^D16,NO%RDX)]
	NOUT			;ADD IT TO THE PACKET IN HEX
	 FATAL			;CAN'T
	MOVEI B,PK%EOF		;NOUT CLEARED THIS
	IDPB B,A
	MOVEI A,EOFLEN		;GET THE LENGTH
	CALL SNDPKT		;SEND IT OFF
	DBGINF <EOF packet SENT>
	RET			;DONE

EOFPKT:	EXP PK%BGN		;BEGIN PACKET
	EXP "0","C"		;LENGTH
	EXP "D"			;DATA
	EXP 0,0			;PACKET NUMBER
	EXP PK%EOF		;END OF FILE MARK
	EXP 0,0,0,0		;CHECKSUM
	EXP PK%END		;END OF PACKET
EOFLEN==.-EOFPKT
	SUBTTL FILE OUTPUT - PACKET MANAGEMENT

; RELPKT - RELEASE ACK'D PACKETS.
;	   HIGHEST ACK'D PACKET NUMBER IN A.

RELPKT:	DBGINF <RELPKT called with %O1>
	CAMN A,LSTACK		;SAME AS LAST TIME?
	 RET			;YES
	SKIPGE PKTTBL(A)	;ALREADY ACK'D?
	 RET			;YES
	EXCH A,LSTACK		;GET LAST ACKED ONE
	AOS A			;MOVE TO NEXT ONE
	ANDI A,MAXPKT		;TRIM IT DOWN
RELPK1:	SETOM PKTTBL(A)		;ACK THIS ONE
	CAMN A,LSTACK		;REACHED THE END?
	 JRST RELPK2		;YES
	AOS A			;MOVE TO NEXT ONE
	ANDI A,MAXPKT		;TRIM IT DOWN
	JRST RELPK1		;NO, DO IT
RELPK2:	RET			;DONE



; CLRTBL - CLEARS THE PACKET TABLE

CLRTBL:	DBGINF <Clearing packet table>
	SETOM PKTTBL
	MOVE A,[PKTTBL,,PKTTBL+1]
	BLT A,PKTTBL+MAXPKT
	RET
; GETPKT - GETS THE NEXT PACKET TO BE SENT
;	   RETURNS +3 WITH LENGTH IN A
;		   +2 IF AT EOF
;		   +1 IF WRAPAROUND WAIT IS NEEDED
;
; GETPKX - GETS THE NEXT PACKET TO BE SENT WITHOUT
;	   CHECKING FOR EOF OR WRAPAROUND, RETURNS +1

GETPKT:	MOVE B,PKTNUM		;GET LAST PACKET NUMBER
	AOS B			;BUMP TO NEXT ONE
	HRLI B,-<MAXPKT+1-OSPCNT>
GETPK0:	AND B,[-1,,MAXPKT]	;TRIM PACKET NUMBER
	SKIPL PKTTBL(B)		;THIS ONE FREE
	 RET			;NO, QUIT
	AOBJN B,GETPK0		;LOOP BACK
	AOS (P)			;SKIP AT LEAST ONE ON RETURN

	TXNE F,F%HDR		;SENDING THE HEADER?
	 JRST [	LDB A,HDRPTR	;YES, GET LAST BYTE SEEN
		JUMPN A,GETPK1	;SKIP IF NOT AT END
		RET ]		;END OF HEADER
	MOVE A,INJFN		;GET THE INPUT FILE
	GTSTS			;GET FILE STATUS
	TXNE B,GS%EOF		;AT END OF FILE?
	 RET			;YES

GETPK1:	AOS (P)			;RETURN +3
	CALL GETPKX		;GET THE PACKET
	AOS B,PKTNUM		;BUMP THE PACKET NUMBER
	ANDI B,MAXPKT		;TRIM IT DOWN
	MOVEM B,PKTNUM
	RET			;DONE
GETPKX:	MOVE A,[DATINI,,PACKET]	;GET DATA PACKET INITIALIZATION
	BLT A,PACKET+DATLEN	;MOVE INTO THE PACKET BUFFER
	MOVE A,[POINT 36,PACKET+.PKTNM]
	MOVE B,PKTNUM		;GET THE NUMBER
	MOVE C,[NO%LFL!NO%ZRO!FLD(2,NO%COL)!FLD(^D16,NO%RDX)]
	NOUT			;ADD IT TO THE PACKET IN HEX
	 FATAL			;CAN'T
	MOVEI C,PK%DAT		;NOUT CLEARED THIS
	IDPB C,A
	MOVE C,B		;SAVE PACKET NUMBER
	MOVE A,INJFN		;GET THE INPUT FILE
	RFPTR			;GET THE POINTER
	 FATAL
	TXNE F,F%HDR		;IS THIS THE HEADER?
	 MOVE B,HDRPTR		;YES
	MOVEM B,PKTTBL(C)	;MARK PACKET
	DBGINF <Building packet %O3  (FP = %O2)>
	CALL FILPKT		;FILL IN THE DATA
	PUSH P,A		;SAVE LENGTH
	MOVE B,A		;AND PUT IT HERE
	MOVE A,[POINT 36,PACKET+.PKLEN]
	MOVE C,[NO%LFL!NO%ZRO!FLD(2,NO%COL)!FLD(^D16,NO%RDX)]
	NOUT			;ADD LENGTH
	 FATAL			;CAN'T
	MOVEI B,"D"		;NOUT CLEARED THIS
	IDPB B,A
	POP P,A			;GET LENGTH BACK
	MOVEI B,PK%END		;GET END OF PACKET CHARACTER
	MOVEM B,PACKET-1(A)	;FILL IT IN
	RET			;DONE


; DATA PACKET HEADER

DATINI:	EXP PK%BGN		;BEGIN PACKET
	EXP 0,0			;LENGTH
	EXP "D"			;DATA PACKET
	EXP PK%DAT		;NOT EOF
DATLEN==.-DATINI		;LENGTH
; FILPKT - FILLS IN A DATA PACKET
;	   OVERALL LENGTH OF PACKET IS RETURNED IN A

FILPKT:	MOVE D,[-DATSIZ,,0]
FILPK1:	TXNE F,F%HDR		;SENDING HEADER?
	 JRST [	ILDB B,HDRPTR	;YES, GET NEXT BYTE
		JUMPE B, FILPK3	;END OF HEADER
		JRST FILPK2 ]
	MOVE A,INJFN		;GET THE INPUT FILE
	BIN			;GET NEXT CHARACTER
	 ERJMP FILPK3		;END OF FILE
FILPK2:	MOVEI C,PK%QUO		;GET A QUOTE CHARACTER
	CAIN B,PK%BGN		;PACKET BEGIN?
	 JRST [	MOVEM C,PACKET+.PKDAT(D)
		MOVEI B,QUO%BP
		AOBJN D,.+1
		JRST .+1 ]
	CAIN B,PK%END		;PACKET END?
	 JRST [	MOVEM C,PACKET+.PKDAT(D)
		MOVEI B,QUO%EP
		AOBJN D,.+1
		JRST .+1 ]
	CAIN B,PK%QUO		;QUOTE CHARACTER?
	 JRST [	MOVEM C,PACKET+.PKDAT(D)
		MOVEI B,QUO%QT
		AOBJN D,.+1
		JRST .+1 ]
	TXNE F,F%ARO		;ARROW MODE?
	CALL CHKARO		;YES, CHECK CHARACTER
	MOVEM B,PACKET+.PKDAT(D)
	AOBJN D,FILPK1		;LOOP BACK

FILPK3:	HRRZ A,D		;GET END LENGTH
	ADDI A,.PKDAT+5		;ACCOUNT FOR OVERHEAD
	RET			;DONE
; CHKARO - CHECK FOR ASCII ARROW MODE

CHKARO:	CAIL B," "	;CONTROL CHARACTER?
	 RET		;NO, RETURN
	CAIE B,.CHBSP	;^H?
	CAIN B,.CHTAB	;OR TAB?
	 RET		;YES
	CAIE B,.CHLFD	;LINE FEED?
	CAIN B,.CHFFD	;OR FORM FEED?
	 RET		;YES
	CAIN B,.CHCRT	;RETURN?
	 RET		;YES
	CAIN B,.CHESC	;ESCAPE?
	 JRST [	MOVEI B,"$"
		RET ]
	PUSH P,B	;SAVE CHARACTER
	MOVEI B,"^"	;GET THE ARROW
	TXNE F,F%TCP	;TCP DEVICE?
	 JRST CHKAR1	;YES
	MOVEM B,PACKET+.PKDAT(D)
	AOBJN D,.+1
	JRST CHKAR2

CHKAR1:	MOVE A,LSRJFN		;GET TCP JFN
	BOUT			;OUTPUT THE ARROW
	 ERJMP .+1

CHKAR2:	POP P,B			;GET CHARACTER BACK
	ADDI B,100		;MAKE IT A LETTER
	RET			;DONE
; REDOPK - RESEND A PACKET, PACKET NUMBER IN A.

REDOPK:	DBGINF <REDOPK called with %O1>
	TXNE F,F%EOF		;EOF PACKET SENT?
	 JRST [	CALL SNDEOF	;YES, RESEND IT
		DBGINF <Resending EOF packet>
		RET ]		;AND QUIT
	TXNE F,F%HDR		;THIS THE HEADER?
	 JRST [	DBGINF <Resending packet # %O1  (Header)>
		MOVEM A,PKTNUM	;RESET PACKET NUMBER
		MOVE A,PKTTBL(A)
		MOVEM A,HDRPTR	;RESET TEXT POINTER
		CALL CLRTBL	;CLEAR THE PACKET TABLE
		CALL GETPKX	;GET PACKET
		CALL SNDPKT	;SEND IT OFF
		RET ]		;DONE
	SKIPGE B,PKTTBL(A)	;ANYTHING THERE?
	 RET			;NO, SOMETHING ELSE WRONG
	STATUS <Resending packet %O1>
	DBGINF <Resending packet # %O1  (FP reset to %O2)>
	MOVEM A,PKTNUM		;STORE NEW PACKET NUMBER
	MOVE A,INJFN
	SFPTR			;SET FILE TO RIGHT SPOT
	 FATAL
	CALL CLRTBL		;CLEAR THE PACKET TABLE
	MOVE A,FILTIM		;RESET THE STATUS
	STATUS <Printing, Started at %T1>
	RET			;DONE
	SUBTTL FILE OUTPUT - GET INPUT FILE

; OPNFIL - OPENS THE INPUT FILE

OPNFIL:	TXZ F,F%CPF		;ASSUME EVERYTHING OK
	MOVE D,FILPTR		;POINT TO THE FILE PARAMETER BLOCK
	HLRZ B,.FPLEN(D)	;GET LENGTH OF THE FP
	ADD B,D			;MOVE TO THE FD
	AOS B			;MOVE TO THE FILE NAME
	MOVE C,B		;SAVE IT IN CASE OF ERROR
	HRROS B			;MAKE IT A POINTER
	MOVX A,GJ%SHT!GJ%OLD!GJ%DEL
	GTJFN			;GET A JFN ON IT
	 JRST [	LOG (<Can't print file>,<%S3: %E1>)
		CALL OPNTMP	;GET A TEMP FILE
		TEXT (TMP,<Can't print %S3: %E1>)
		SETZM INJFN	;SAY WE NEVER GOT IT
		CALL CLSTMP
		TXO F,F%CPF	;MARK IT
		RET ]		;QUIT
	MOVEM A,INJFN		;SAVE THE JFN
	PUSH P,C		;SAVE FILE NAME POINTER

	MOVE A,.FPINF(D)	;GET FLAGS
	TXNE A,FP.SPL		;SPOOLED FILE?
	 JRST OPNFL1		;YES, NO ACCESS CHECK
	CALL RDACES		;CHECK USER ACCESS TO THIS FILE
	 JRST [	LOG (<Can't print file>,<%S3: Read access required>)
		MOVE A,INJFN
		RLJFN		;RELEASE THE JFN
		 JFCL
		CALL OPNTMP	;GET A TEMP FILE
		TEXT (TMP,<Can't print %S3: Read access required>)
		SETZM INJFN	;SAY WE DON'T HAVE IT
		CALL CLSTMP
		TXO F,F%CPF	;MARK IT
		ADJSP P,-1	;BALANCE THE STACK
		RET ]		;QUIT

OPNFL1:	MOVE A,INJFN		;GET THE JFN
	MOVE B,[1,,.FBBYV]	;GET THE IO FLAGS
	MOVEI C,D
	GTFDB
	POP P,C			;RESTORE THE NAME POINTER
	LDB A,[POINT 6,D,11]	;PICK UP THE BYTE SIZE
	MOVE B,[FLD(7,OF%BSZ)!OF%RD]
	CAIN A,8		;EIGHT BIT BYTES?
	 MOVE B,[FLD(8,OF%BSZ)!OF%RD]
	MOVE A,INJFN		;GET THE JFN
	OPENF			;OPEN THE FILE
	 JRST [	LOG (<Can't print file>,<%S3: %E1>)
		CALL OPNTMP	;GET A TEMP FILE
		TEXT (TMP,<Can't print %S3: %E1>)
		CALL CLSTMP
		TXO F,F%CPF	;MARK IT
		RET ]		;QUIT
	RET			;DONE

; OPNTMP - OPEN THE ERROR MESSAGE FILE
OPNTMP:	PUSH P,A
	PUSH P,B
	MOVX A,GJ%SHT!GJ%NEW!GJ%FOU
	HRROI B,[ASCIZ /PS:<SPOOL>IMGSPL-ERROR.FILE/]
	GTJFN
	 SPLERR <Can't get temp file: %E1>
	MOVEM A,TMPJFN
	MOVE B,[FLD(7,OF%BSZ)!OF%WR]
	OPENF
	 SPLERR <Can't open temp file: %E1>
	POP P,B
	POP P,A
	RET


; CLOSE TEMP FILE
CLSTMP:	MOVE A,TMPJFN		;GET TEH JFN
	TXO A,CO%NRJ		;KEEP THE JFN
	CLOSF
	 SPLERR <Can't close temp file: %E1>
	SKIPE A,INJFN		;GET REAL INPUT FILE
	RLJFN			;RELEASE IT IF IT'S THERE
	 JFCL
	MOVE A,TMPJFN		;GET TEMP JFN
	MOVE B,[FLD(7,OF%BSZ)!OF%RD]
	OPENF			;OPEN TEMP FILE FOR READ
	 SPLERR <Can't open temp file for read: %E1>
	MOVEM A,INJFN		;SAVE JFN
	RET			;DONE


; TEXT ROUTINE FOR TEMP FILES
TMP:	MOVE B,A		;GET BYTE
	MOVE A,TMPJFN		;GET JFN
	BOUT			;WRITE IT OUT
	RET			;DONE
; SETFIL - SET LOCAL FILE FLAGS

SETFIL:	TXZ F,F%IMP!F%ASC!F%TEK!F%DSY!F%ARO
	MOVE D,FILPTR		;POINT TO THE FILE BLOCKS
	TXNE F,F%CPF		;PROBLEMS WITH THE FILE?
	 JRST [	SETZM .FPINF(D)	;YES, ZAP FILE TYPE
		RET ]		;AND QUIT
	LDB A,[POINT 6,.FPINF(D),5]
	CAIN A,.FPFAS		;ASCII FORMAT?
	 TXO F,F%ASC
	CAIN A,.FPFIM		;BINARY?
	 TXO F,F%IMP
	CAIN A,.FPFAI		;TEK?
	 TXO F,F%TEK
	CAIN A,.FPF8B		;DAISY?
	 TXO F,F%DSY
	TXNN F,F%IMP!F%ASC!F%DSY!F%TEK
	 TXO F,F%IMP		;DEFAULT TO IMPRESS
	TXNN F,F%ASC		;ASCII FILE?
	 RET			;NO, SKIP THIS
	LDB A,[POINT 6,.FPINF(D),11]
	CAIN A,%FPLAR		;ARROW MODE REQUESTED?
	 TXO F,F%ARO		;YES
	RET			;DONE
	SUBTTL FILE OUTPUT - REMOVE OLD STYLE IMPRINT-10 HEADERS

FIXFIL:	TXNE F,F%CPF		;FILE OK SO FAR?
	 RET			;NO, DON'T DO THIS
	TXNN F,F%IMP		;IMPRESS FILE?
	 RET			;NO
	MOVE A,INJFN		;LOOK AT THE FILE
	BIN			;GET FIRST BYTE
	CAIL B,"0"		;A DIGIT
	CAILE B,"9"
	 JRST [	SETZ B,		;NO, IT'S OK
		SFPTR		;RESET POINTER
		 JFCL
		RET ]		;DONE
	BIN			;FLUSH STRING
	JUMPN B,.-1
	MOVE B,[POINT 1,PACKET]	;FLUSH 8 MORE
	MOVNI C,8
	SIN
	RET			;DONE
	SUBTTL FILE OUTPUT - ACCESS CHECKING

; RDACES - CHECKS ACCESS TO THE FILE FOR PRINTING
; DLACES - CHECK ACCESS TO THE FILE FOR /DELETE

DLACES:	SKIPA A,[.CKAAP]	;WANT APPEND ACCESS FOR DELETE
RDACES:	MOVX A,.CKARD		;WANT READ ACCESS
	MOVEM A,ARGBLK+.CKAAC
	MOVE A,JOBINF+.EQSEQ	;GET EXTERNAL VALUES
	TXNE A,QE.PRV		;USER ENABLED?
	 JRST CHKAC1		;YES
	SETZM A,ARGBLK+.CKAEC	;NO
	MOVE A,INJFN		;GET THE JFN
	MOVEM A,ARGBLK+.CKAUD
	MOVE A,JOBINF+.EQOID	;SET THE USER NUMBER
	MOVEM A,ARGBLK+.CKALD
	HRROI A,JOBINF+.EQCON	;SET DIRECTORY POINTER
	MOVEM A,ARGBLK+.CKACD
	MOVEI A,5		;LENGTH OF ARGUMENT BLOCK
	TXO A,CK%JFN		;SAY WE HAVE A JFN
	MOVEI B,ARGBLK		;ADDRESS OF ARGUMENT BLOCK
	CHKAC
	 JRST CHKAC1		;FAILED, ASSUME OK
	SKIPE A			;ACCESS ALLOWED?
CHKAC1:	 AOS (P)		;YES, SKIP RETURN
	RET			;DONE
	SUBTTL FILE OUTPUT - HEADER BUILDING

; FIXHDR - BUILD THE HEADER STRING

FIXHDR:	MOVE A,[POINT 7,HDRTXT]
	MOVEM A,HDRPTR		;SET THINGS UP
	SETO A,
	IDPB A,HDRPTR		;INSURE A NON-ZERO BYTE

	MOVE C,FILPTR		;GET FILE FLAGS
	MOVE B,.FPFR2(C)
	TXNE B,FP.SDP		;THIS A SCREEN DUMP?
	 JRST [	TEXT (HEADER,<@DOCUMENT(Language Impress, Name "Screendump")>)
		RET ]
	MOVE A,JOBINF+.EQOID	;USER NUMBER
	TXNE F,F%IMP
	 TEXT (HEADER,<@DOCUMENT(Language Impress, Owner "%U1">)
	TXNE F,F%ASC!F%CPF
	 TEXT (HEADER,<@DOCUMENT(Language Printer, Owner "%U1">)
	TXNE F,F%TEK
	 TEXT (HEADER,<@DOCUMENT(Language Tektronix, Owner "%U1">)
	TXNE F,F%DSY
	 TEXT (HEADER,<@DOCUMENT(Language Daisy, Owner "%U1">)
	SETO B,
	TEXT (HEADER,<, Date "%D2 %T2">)
	MOVE B,INJFN		;JFN
	MOVE A,.FPINF(C)	;GET FLAGS
	TXNN A,FP.SPL		;SPOOLED?
	 TEXT (HEADER,<, Name "%f2">)
	TXNE A,FP.SPL
	 JRST [	MOVE B,JOBINF+.EQJBB
		TEXT (HEADER,<, Name "Spooled %62 job">)
		JRST .+1 ]
	HLRZ B,.FPLEN(C)	;STEP TO FILE NAME
	ADD B,C
	AOS B
	HRROS B
	TXNE A,F%CPF		;SOMETHING WRONG?
	 TEXT (HEADER,<, Name "%S2">)
	HRROI B,HOSTNM
	TXNE F,F%TCP		;ON A TCP PRINTER?
	 TEXT (HEADER,<, Host "%S2">)
	LDB B,[POINT 9,.FPINF(C),35]
	CAILE B,1		;WANT MORE THAN ONE COPY?
	 JRST [	TEXT (HEADER,<, Copies %N2>)
		MOVE A,.FPINF(C)
		TXNE A,FP.COL	;WANT PAGE COLLATION?
		 TEXT (HEADER,<, Pagecollation Yes>)
		JRST .+1 ]
	MOVE A,.FPINF(C)	;GET FILE INFO BITS
	TXNE A,FP.REV		;WANT PAGE REVERSAL?
	 TEXT (HEADER,<, Pagereversal Yes>)
	TXNE A,FP.COL		;COLLATION ON?
	 JRST [	TXNN A,FP.REV	;YES, FORCE REVERSE OFF IF SPECIFIED
		 TEXT (HEADER,<, Pagereversal No>)
		JRST .+1 ]
	TXNE F,F%LST		;THIS THE LAST FILE?
	 TEXT (HEADER,<, Jobheader Yes>)
	TXNN F,F%LST
	 TEXT (HEADER,<, Jobheader No>)
	MOVE A,.FPFR2(C)	;WANT MANUAL PAPER FEED?
	TXNE A,FP.MAN
	 TEXT (HEADER,<, Inputbin Manual>)
	TXNE F,F%IMP		;THIS AN IMPRESS FILE?
	 JRST FIXHD1		;YES, SKIP THE REST

	HRRZ B,.FPFR1(C)	;GET THE LINES PER PAGE
	SKIPE B			;DEFAULT?
	 TEXT (HEADER,<, Formlength %N2>)
	HLRZ B,.FPFR1(C)	;GET FORMWIDTH
	SKIPE B			;DEFAULT?
	 TEXT (HEADER,<, Formwidth %N2>)
	HRRZ B,.FPFR2(C)	;GET LEFT MARGIN
	SKIPE B			;DEFAULT?
	 TEXT (HEADER,<, Leftmargin %N2>)
	MOVE B,.FPINF(C)
	TXNE B,FP.2PG		;WANT TO FORMS?
	 TEXT (HEADER,<, Formsperpage 2>)
	MOVE B,.FPFR2(C)
	TXNE B,FP.RUL		;WANT RULES?
	 TEXT (HEADER,<, Rules>)
	TXNE B,FP.OTL		;WANT OUTLINES?
	 TEXT (HEADER,<, Outlines>)

FIXHD1:	TEXT (HEADER,<)>)	;END THE HEADER
	RET			;DONE



; TEXT ROUTINE FOR HEADERS
HEADER:	IDPB A,HDRPTR
	SETZ A,
	PUSH P,HDRPTR
	IDPB A,HDRPTR
	POP P,HDRPTR
	RET
	SUBTTL FILE OUTPUT - SEND HEADER

; SNDHDR - SENDS THE HEADER

SNDHDR:	MOVE A,[POINT 7,HDRTXT]	;POINT TO THE BUFFER
	MOVEM A,HDRPTR		;SAVE THE POINTER
	IBP HDRPTR		;SKIP PAST NON-ZERO BYTE
	TXO F,F%HDR		;SAY SENDING HEADER
SNDHD1:	CALL CHKLSR		;CHECK THINGS
	CALL GETPKT		;GET A PACKET
	 JRST SNDHD1		;WRAP AROUND
	 JRST SNDHD2		;END OF HEADER
	CALL SNDPKT		;SEND IT OUT
	JRST SNDHD1		;LOOP BACK

SNDHD2:	CALL RSVP		;SEND AN RSVP
	MOVEI A,RSVSLP
	DISMS
	CALL CHKLSR		;GET STATUS
	MOVE A,PKTNUM		;GET PACKET NUMBER
	SOS A			;GET ACTUAL NUMBER
	ANDI A,MAXPKT		;NOT NEEDED HERE
	SKIPGE PKTTBL(A)	;HEADER ACK'D?
	 JRST SNDHD3		;YES
	MOVEI A,RSVSLP		;NO, WAIT SOME
	DISMS
	JRST SNDHD1		;LOOK AGAIN, CHECK FOR NAKS

SNDHD3:	TXZ F,F%HDR		;NO LONGER SENDING HEADER
	RET			;DONE
	SUBTTL FILE OUTPUT - ACCOUNTING

; GETCNT - GETS THE PAGE COUNT FOR THE FILE

GETCNT:	TXZ F,F%PGC		;COUNT NOT VALID NOW
	DBGINF <Getting page count>
GETCT1:	MOVE A,[PGCPKT,,PACKET]	;GET THE REQUEST PACKET
	BLT A,PACKET+PGCLEN	;PUT IN BUFFER
	MOVEI A,PGCLEN		;GET THE LENGTH
	CALL SNDPKT		;SEND IT OFF
	MOVEI A,RSVSLP		;WAIT FOR REPLY
	DISMS
	CALL CHKLSR		;CHECK THE PRINTER
	TXZN F,F%PGC		;GET THE COUNT?
	 JRST GETCT1		;NO
	MOVE A,PAGCNT		;YES, GET THE COUNT
	ADDM A,JOBCNT		;ADD IT IN
	STATUS <Pages printed: %N1>
	DBGINF <Pages printed: %N1>
	RET			;DONE

PGCPKT:	EXP PK%BGN		;BEGIN PACKET
	EXP "1","1"		;LENGTH
	EXP "S"			;STATUS
	EXP "a"			;SYNC REQUEST
	EXP "F","F","F","F"	;WINDOW SIZE
	EXP "F","F"		;PACKET CODE
	EXP " "			;ERROR TYPE
	EXP 0,0,0,0		;CHECKSUM
	EXP PK%END		;END OF PACKET
PGCLEN==.-PGCPKT
	SUBTTL FILE OUTPUT - CHECKPOINT

; STSTXT - TEXT ROUTINE FOR STATUS

STSTXT:	IDPB A,STSPTR
	SETZ A,
	PUSH P,STSPTR
	IDPB A,STSPTR
	POP P,STSPTR
	RET
	SUBTTL TEXT UTILITY

TEXT.:	MOVEM P,TXTBUF		;SAVE THE STACK POINTER
	TRVAR <TXTRTN,TXTPTR,<TXTACS,5>>
	PUSH P,P1
	MOVEI P1,TXTACS		;GET ADDRESS OF SAVED AC BUFFER
	HRLI P1,1		;MAKE BLT POINTER
	BLT P1,4+TXTACS		;SAVE AC1 - AC5
	POP P,P1		;RESTORE THIS
	MOVE C,TXTBUF		;GET STACK POINTER
	MOVE C,(C)		;POINT TO ARGS
	HRRZ A,(C)		;GET ROUTINE ADDRESS
	MOVEM A,TXTRTN		;SAVE IT
	MOVEI B,@1(C)		;GET STRING ADDRESS
	HLL B,[POINT 7,0]	;MAKE IT A POINTER
	MOVEM B,TXTPTR

TEXT1:	ILDB A,TXTPTR		;GET NEXT BYTE
TEXT1A:	JUMPE A,TXTEND		;END ON A ZERO BYTE
	CAIN A,"%"		;SOME THING SPECIAL?
	 JRST TEXT2		;YES
TEXT1B:	CALL @TXTRTN		;PROCESS THIS CHARACTER
	JRST TEXT1		;LOOP BACK

TXTEN1:	MOVEI A,.CHCRT		;END OF STRING, SEND A CRLF
	CALL @TXTRTN
	MOVEI A,.CHLFD		;SEND A LF
	CALL @TXTRTN
TXTEND:	HRLI 5,TXTACS		;GET POINTER TO THE ACS
	HRRI 5,A		;MAKE BLT POINTER
	BLT 5,5			;RESTORE
	RET			;ALL DONE


; HERE TO PROCESS THE "%" CHARACTER

TEXT2:	ILDB A,TXTPTR		;GET ARGUMENT
	CAIN A,"U"		;USER NAME?
	 JRST TEXT.U
	CAIN A,"F"		;FILE NAME?
	 JRST TXT.FF
	CAIN A,"f"
	 JRST TXT.FS
	CAIN A,"N"		;DECIMAL NUMBER?
	 JRST TEXT.N
	CAIN A,"O"		;OCTAL NUMBER?
	 JRST TEXT.O
	CAIN A,"6"		;SIXBIT WORD?
	 JRST TEXT.6
	CAIN A,"E"		;ERROR STRING?
	 JRST TEXT.E
	CAIN A,"T"		;TIME?
	 JRST TEXT.T
	CAIN A,"D"		;DATE?
	 JRST TEXT.D
	CAIN A,"S"		;STRING?
	 JRST TEXT.S
	CAIN A,"_"		;CRLF AND QUIT?
	 JRST TXTEN1
	CAIN A,"%"		;A "%"?
	 JRST TEXT1B
	JRST TEXT1A		;NONE OF THESE, PROCESS THE CHARACTER



; GETAC - RETURNS THE VALUE IN B FOR THE NEXT AC NUMBER.

GETAC:	ILDB A,TXTPTR		;GET THE CHARACTER
	CAIL A,"1"		;TOO LOW?
	CAILE A,"5"		;OR TOO HIGH?
	 JRST GETAC1		;YES
	SUBI A,"1"		;CONVERT TO BINARY AND SUBTRACT ONE
	MOVEI B,TXTACS		;GET POINTER TO AC BUFFER
	ADD B,A			;GET ADDRESS OF THE ONE WE WANT
	MOVE B,(B)		;GET THE VALUE
	RET			;RETURN IT

GETAC1:	ADJSP P,-1		;BAD VALUE, BALANCE THE STACK
	JRST TEXT1A		;PROCESS THIS ONE


; "U" - USER NAME

TEXT.U:	CALL GETAC		;GET THE NUMBER
	HRROI A,TXTBUF		;POINT TO THE TEXT BUFFER
	DIRST			;WRITE IT OUT
	 JRST TEXT1		;CAN'T
	JRST TXTOUT		;SEND THE BUFFER


; "F" - FILE NAME

TXT.FS:	SKIPA C,[JS%NAM!JS%TYP!JS%GEN!JS%PAF]
TXT.FF:	MOVX C,JS%DEV!JS%DIR!JS%NAM!JS%TYP!JS%GEN!JS%PAF
	CALL GETAC		;GET THE JFN
	HRROI A,TXTBUF
	JFNS			;WRITE IT OUT
	 ERJMP TEXT1		;FAILED
	JRST TXTOUT		;SEND THE BUFFER


; "N" - DECIMAL NUMBER
; "O" - OCTAL NUMBER

TEXT.N:	SKIPA C,[^D10]		;DECIMAL
TEXT.O:	MOVEI C,10		;OCTAL
	CALL GETAC		;GET THE NUMBER
	HRROI A,TXTBUF
	NOUT			;WRITE IT OUT
	 JRST TEXT1
	JRST TXTOUT		;SEND IT OUT
; "6" - SIXBIT WORD

TEXT.6:	CALL GETAC		;GET THE WORD
	MOVEI C,6		;SEE HOW MANY CHATACTERS TO PRINT
	TRNE B,77
	 JRST TEXT60
	MOVEI C,5
	TRNE B,7700
	 JRST TEXT60
	MOVEI C,4
	TRNE B,77000
	 JRST TEXT60
	MOVEI C,3
	TLNE B,77
	 JRST TEXT60
	MOVEI C,2
	TLNE B,7700
	 JRST TEXT60
	MOVEI C,1
	TLNN B,770000
	 RET			;NOTHING THERE
TEXT60:	PUSH P,B		;SAVE THE WORD
	PUSH P,C		;SND THE COUNT
	PUSH P,[POINT 6,-2(P)]	;SAVE A POINTER
TEXT6A:	ILDB A,(P)		;GET THE NEXT BYTE
	ADDI A,40		;CONVERT TO ASCII
	CALL @TXTRTN		;PROCESS IT
	SOSLE -1(P)		;ANY LEFT?
	 JRST TEXT6A		;YES, DO THEM
	ADJSP P,-3		;FLUSH THE STACK
	JRST TEXT1		;DONE


; "E" - ERROR STRING

TEXT.E:	CALL GETAC		;GET THE ERROR NUMBER
	HRLI B,.FHSLF		;THIS FORK
	HRROI A,TXTBUF		;POINT TO THE BUFFER
	SETZ C,			;NO LIMIT
	ERSTR			;WRITE IT OUT
	 JRST TEXT1		;CANT
	 JRST TEXT1
	JRST TXTOUT		;SEND IT OUT

; "T" - TIME
; "D" - DATE

TEXT.T:	SKIPA C,[OT%NDA!]	;TIME ONLY
TEXT.D:	MOVX C,OT%NTM		;DATE ONLY
	CALL GETAC		;GET THE TIME
	HRROI A,TXTBUF		;POINT TO THE BUFFER
	ODTIM			;OUTPUT IT
	JRST TXTOUT		;SEND IT OUT
; "S" - STRING

TEXT.S:	CALL GETAC		;GET THE STRING ADDRESS
	HLL B,[POINT 7,0]	;MAKE IT A POINTER
	PUSH P,B		;SAVE IT
	JRST TXTOT1		;JOIN COPY CODE


TXTOUT:	SETZ B,			;ASCIZ THE STRING
	IDPB B,A
	PUSH P,[POINT 7,TXTBUF]	;SAVE A POINTER
TXTOT1:	ILDB A,(P)		;GET NEXT CHARACTER
	JUMPE A,TXTOT2		;END ON A ZERO BYTE
	CALL @TXTRTN		;PROCESS IT
	JRST TXTOT1		;LOOP BACK
TXTOT2:	SETZM TXTBUF		;ZERO THE BUFFER
	ADJSP P,-1		;BALANCE THE STACK
	JRST TEXT1		;LOOP BACK
	SUBTTL USER OFFLINE NOTIFICATION

OFLNOT:
IFE OFFLSW,< RET >
	JFCL			;SO FILDDT AND DISABLE EASY
	TXNE F,F%TCP		;TCP PRINTER?
	 RET			;YES, DO NOTHING
	MOVE A,FILPTR		;POINT TO CURRENT FP
	MOVE B,.FPFR2(A)	;GET FLAGS
	MOVE D,.FPINF(A)	;MORE FLAGS
	TXNE B,FP.SDP		;THIS A SCREEN DUMP?
	 RET			;YES, DO NOTHING
	MOVE B,[POINT 7,NOTMSG]
	MOVEM B,NOTPTR
	HLRZ B,.FPLEN(A)	;GET LENGTH OF THE FP
	ADD B,A			;MOVE TO THE FD
	AOS B			;MOVE TO THE FILE NAME
	MOVE A,OBJBLK+OBJ.UN	;GET THE UNIT NUMBER
	MOVE C,JOBINF+.EQJBB	;GET JOB NAME
	TXNN D,FP.SPL		;SPOOLED?
	 TEXT (OFLTXT,<
[Laser printer %O1 offline while printing %S2]%_>)
	TXNE D,FP.SPL
	 TEXT (OFLTXT,<
[Laser printer %O1 offline while printing %63 job]%_>)
	SETZ A,
	IDPB A,NOTPTR		;END THHE STRING
	MOVE P1,[-MAXJOB,,0]	;MAKE JOB POINTER
OFLNT1:	HRRZ A,P1		;GET THE JOB NUMBER
	MOVE B,[-2,,P2]		;GET TWO WORDS, PUT IN P2 AND P3
	MOVX C,.JITNO		;GET USER AND TERMINAL NUMBER
	GETJI			;TRY FOR IT
	 JRST OFLNT2		;NO SUCH JOB
	CAME P3,JOBINF+.EQOID	;RIGHT USER?
	 JRST OFLNT2		;NO
	HRRZS P2
	CAMN P2,[0,,-1]		;DETACHED?
	 JRST OFLNT2		;YES
	MOVE A,P2		;GET THE TERMINAL NUMBER
	TXO A,.TTDES		;MAKE IT A DEVICE DESIGNATOR
	MOVX B,.MORNT		;GET SYSTEM-MESSAGES BIT
	MTOPR
	 ERJMP OFLNT2
	CAIE C,.MOSMY		;RECEIVE?
	 JRST OFLNT2		;NO
	HRROI B,NOTMSG		;POINT TO THE MESSAGE
	TTMSG			;SEND IT OUT
	 ERJMP .+1		;IGNORE ERRORS
OFLNT2:	AOBJN P1,OFLNT1		;LOOP BACK
	RET			;DONE



OFLTXT:	IDPB A,NOTPTR
	RET
	SUBTTL FATAL ERRORS

LITSPC:	LIT			;SAVE LITERALS IN DUMP

.FATAL:	TXO F,F%FAT		;MARK FATAL ERROR SEEN
	MOVEM 17,DUMPAC+17	;SAVE THE AC'S
	MOVE 17,[0,,DUMPAC]
	BLT 17,DUMPAC+16
	HRROI A,STSBUF		;POINT TO THE STRING
	WTO (<Imgspl Crash>,<%S1>)
	HRROI A,DMPSTR		;COPY THE STRING
	HRROI B,STSBUF
	SETZ C,
	SOUT
	SETO A,
	STATUS <Spooler crash at %T1>
FATAL1:	MOVX A,GJ%SHT!GJ%NEW!GJ%FOU
	HRROI B,[ASCIZ /IMGSPL-CRASH.DUMP/]
	GTJFN
	 JRST [	TMSG <?IMGSPL Can't get JFN for dump file>
		HALTF ]
	HRLI A,.FHSLF		;THIS PROCESS
	MOVE B,[-1000,,0]	;SAVE EVERYTHING
	SSAVE
	 ERJMP [TMSG <?IMGSPL Save failed>
		JRST .+1]
	RESET			;RELEASE EVERYTHING
	HALTF			;QUIT
	 JRST .-1

FATAL9:	TMSG <?IMGSPL ERROR WITHIN AN ERROR>
	JRST FATAL1


	END <3,,ENTVEC>