Google
 

Trailing-Edge - PDP-10 Archives - BB-FP64A-SB_1986 - 10,7/who/whosrv.mac
There are 4 other files named whosrv.mac in the archive. Click here to see a list.
	TITLE	WHOSRV - SRVF INTERFACE FOR WHOSRV

	SEARCH	WHOMAC
	$SETUP	(WHOSRV)

; Dummy definitions if loading without the server
IFE FTSERV,<

SRVPUT::!			;COMMAND BUFFER PUTTER
SRVTAK::!			;COMMAND BUFFER TAKER
SRVTYO::!			;OUTPUT TO SOME TASK
SRVXIT::!POPJ P,		;EXIT ROUTINE

> ;END IFE FTSERV

IFN FTSERV,<
	SUBTTL	Table of Contents


;               TABLE OF CONTENTS FOR WHOSRV
;
;
;                        SECTION                                   PAGE
;    1. Table of Contents.........................................   2
;    2. System server
;         2.1   CHKSRV - Check FRCLIN startup.....................   3
;         2.2   SRVSYS - Start up server..........................   4
;         2.3   LGNJOB - Login a job..............................   5
;    3. User server
;         3.1   SRVUSR - Initiate server connects.................   6
;    4. Server loop
;         4.1   WHOSRV - Top level................................   7
;         4.2   TINI - INIT TYPE IN AND STORAGE...................   8
;    5. SCAN interface
;         5.1   .ISCAN block......................................   9
;         5.2   SRVCHR - Character typeout........................  10
;         5.3   TYPIN - Character typein..........................  11
;    6. Server loop
;         6.1   GMSG - Get an IPCF message........................  12
;         6.2   SMSG - Send an IPCF message.......................  13
;    7. Buffer control
;         7.1   Definitions.......................................  14
;         7.2   SRVCMD/SRVTYP - Initialize character storage......  15
;         7.3   ADVBUF - Advance buffers..........................  16
;         7.4   SRVPUT/TYPPUT - Character putters.................  17
;         7.5   CMDTAK/TYPTAK - Character takers..................  18
;    8. Task I/O
;         8.1   Dispatch vectors..................................  19
;         8.2   Initialization....................................  20
;         8.3   IPCF..............................................  22
;         8.4   ANF10.............................................  24
;         8.5   DECnet............................................  26
;    9. Storage...................................................  27
	SUBTTL	System server -- CHKSRV - Check FRCLIN startup


CHKSRV::MOVNI	T1,1			;-1 MEANS US
	PUSHJ	P,UTRMNO##		;GET OUR LINE NUMBER
	  PJRST	SRVCMD			;DETACHED--INIT COMMAND BUFFER
	MOVE	T2,T1			;COPY IT
	ANDX	T2,UX.UNT		;KEEP JUST THE UNIT NUMBER
	MOVX	T1,%CNFLN		;GETTAB TO RETURN FRCLIN TTY NUMBER
	PUSHJ	P,GTAB##		;GET IT
	CAME	T1,T2			;ARE WE RUNNING ON FRCLIN ?
	  PJRST	SRVCMD			;NO--INIT COMMAND BUFFER
	HRLZS	T2			;SETUP LINE#,,0 FOR DETACH
	ATTACH	T2,			;DETACH FROM FRCLIN
	  JFCL				;OH WELL...
	MOVSI	T1,.STWTC		;GET FUNCTION CODE TO SET WATCH
	SETUUO	T1,			;SET WATCH NONE
	  JFCL				;HOPE NOTHING TYPES OUT
	PUSHJ	P,SRVSYS		;SET UP SYSTEM SERVERS
	PJRST	SRVLOP			;AND START DOING THE WORK
	SUBTTL	System server -- SRVSYS - Start up server


SRVSYS::TLO	F,(FL.WHOSRV)		;FLAG THE WHOSRVER
	PUSHJ	P,LGNJOB		;MAKE SURE WE'RE LOGGED IN
	PUSHJ	P,SETME##		;SET UP OUR PRIV AND JOB FLAGS
	MOVE	T1,[LN$IBLK##,,ISBLK##]	;POINT TO .ISCAN BLOCK
	PUSHJ	P,.ISCAN##		;INIT SCAN
	PUSHJ	P,OUTDEF##		;SET UP THE LOG FILE SPEC
	PUSHJ	P,OPNLST##		;OPEN THE LOG FILE
	PUSHJ	P,LOGHDR		;PUT A HEADER OUT
	PUSHJ	P,.SAVE2##		;SAVE P1 AND P2
	MOVSI	P1,-.TSNUM+1		;AOBJN POINTER

SRVS.1:	MOVE	P2,TSKTAB(P1)		;GET TASK DISPATCH VECTOR
	TDNN	F,.TSFET(P2)		;HAVE THE NECESSARY MONITOR FEATURES?
	JRST	SRVS.2			;NO
	SETZ	T1,			;PASSIVE TASK
	MOVE	T2,.TSTIM(P2)		;GET TIMEOUT VALUE
	STORE	T2,T1,TS.TIM		;SAVE IT
	MOVE	T2,.TSTYP(P2)		;GET TASK TYPE
	STORE	T2,T1,TS.TYP		;SAVE IT
	MOVEI	T2,0			;0 TO ACCEPT CONNECTS FROM ALL NODES
	PUSHJ	P,OPNTSK		;OPEN A TASK
	  SKIPA	T1,[LOGSTE]		;FAILED
	MOVEI	T1,LOGSTA		;STARTED WITHOUT ERRORS
	PUSHJ	P,(T1)			;LOG THE START OR FAILURE

SRVS.2:	AOBJN	P1,SRVS.1		;LOOP
	MOVE	T1,F			;COPY FLAGS
	AND	T1,[FL.SRVFLG+FR.OPEN]	;KEEP ONLY SPECIAL SERVER JOB FLAGS
	MOVEM	T1,SRVFLG		;SAVE FOR LATER
	PUSHJ	P,CLSLST##		;CLOSE SERVER LOG
	POPJ	P,			;RETURN
	SUBTTL	System server -- LGNJOB - Login a job


LGNJOB:	TLNE	F,(FL.LOGIN)		;ALREADY LOGGED IN?
	POPJ	P,			;YES
	MOVE	T1,OPRPPN##		;GET OPERATOR PPN
	MOVEM	T1,LOGDAT+0		;SAVE IT
	SETOM	LOGDAT+1		;WANT ALL DEC AND CUSTOMER PRIVS
	MOVE	T1,['WHO-SE']		;USER NAME
	MOVEM	T1,LOGDAT+2		; (WORD 1)
	MOVE	T1,['RVER  ']		;USER NAME
	MOVEM	T1,LOGDAT+3		; (WORD 2)
	SETZM	LOGDAT+4		;NO CHARGE NUMBER
	MOVE	T1,[-5,,LOGDAT]		;POINT TO ARGS
	LOGIN	T1,			;TURN ON JLOG, TOO BAD IT CLEARS JACCT
	POPJ	P,			;BET YOU THOUGHT LOGIN UUO SKIPPED!
	SUBTTL	System server -- SRVDEF - Set up log file


SRVDEF::SETOM	PRVFLG##		;TELL WHOIO TO USE FILOP PRIVS
	MOVE	T1,[O.SPEC##,,O.SPEC##+1] ;SET UP BLT
	SETZM	O.SPEC##		;CLEAR FIRST WORD
	BLT	T1,O.SPEC+.FZLEN##-1	;CLEAR ENTIRE SCAN BLOCK

	MOVEI	T1,O.SPEC##		;POINT TO OUTPUT SCAN BLOCK
	MOVSI	T2,'SSL'		;DEVICE
	MOVEM	T2,.FXDEV(T1)		;SET IT
	MOVE	T2,[SIXBIT/WHO/]	;FILE NAME
	MOVEM	T2,.FXNAM(T1)		;SET IT
	SETOM	.FXNMM(T1)		;NOT WILD
	HRLOI	T2,'LOG'		;EXTENSION AND MASK
	MOVEM	T2,.FXEXT(T1)		;SET IT
	MOVE	T2,QUEPPN##		;GET PPN
	MOVEM	T2,.FXDIR(T1)		;SET IT
	SETOM	.FXDIM(T1)		;NOT WILD
	MOVE	T2,.JBVER		;GET OUR VERSION
	MOVEM	T2,.FXVER(T1)		;SET IT
	SETOM	.FXEST(T1)		;NO ESTIMATED LENGTH

	MOVX	T2,FX.DIR+FX.PHY	;DIRECTORY SPECIFIED, /PHYSICAL
	MOVE	T3,SPLPRT##		;GET SPOOLED FILE PROTECTION CODE
	LSH	T3,-<ALIGN.(RB.PRV)>	;RIGHT JUSTIFY
	DPB	T3,[POINTR (T2,FX.PRO)]	;STORE PROTECTION CODE
	MOVEM	T2,.FXMOD(T1)		;SET BITS
	TXO	T2,FX.PRO		;TELL SCAN A PROTECTION WAS SPECIFIED
	MOVEM	T2,.FXMOM(T1)		;SET THE MODIFIER MASK

	MOVE	T1,[.FZLEN##,,O.SPEC##]	;POINT TO OUTPUT SPEC
	MOVEI	T2,O.OPEN##		;POINT TO OPEN BLOCK
	MOVE	T3,[LN$LEN,,O.ENTER##]	;POINT TO ENTER BLOCK
	MOVEI	T4,O.PATH##		;POINT TO OUTPUT PATH. BLOCK
	PUSHJ	P,.STOPB##		;CONVERT SCAN BLOCKS
	  JFCL				;CANNOT FAIL
	MOVSI	T1,'WHO'		;GET PROGRAM NAME
	MOVEM	T1,O.ENTER##+.RBSPL	;STORE AS SPOOLED NAME
	MOVEI	T1,1			;GET "YES"
	MOVEM	T1,S.APPEND##		;TURN ON /APPEND
	POPJ	P,			;AND RETURN
	SUBTTL	System server - LOGHDR - Write a log file header


LOGHDR:	AOS	T1,HDRFLG		;GET HEADER FLAG
	SOJN	T1,.POPJ##		;RETURN IF ALREADY HAVE DONE THIS
	MOVEI	T1,CHRFIL		;WANT LOG FILE ONLY OUTPUT
	PUSHJ	P,.TYOCH##		;TELL SCAN
	PUSH	P,T1			;SAVE OLD TYPER
	MOVEI	T1,NEWPAG		;POINT TO NEW PAGE TEXT
	PUSHJ	P,.TSTRG##		;TYPE IT
	MOVEI	T1,STARS		;POINT TO A STRING OF STARS
	PUSHJ	P,.TSTRG##		;TYPE IT
	MOVEI	T1,[ASCIZ |		WHO server log file	|]
	PUSHJ	P,.TSTRG##		;TYPE INTRODUCTION
	PUSHJ	P,.GTNOW##		;GET UDT
	PUSHJ	P,.TDTTM##		;AND TYPE THE CURRENT DATE AND TIME
	PUSHJ	P,.TCRLF##		;CRLF
	PUSHJ	P,.TCRLF##		;ONE MORE
	MOVEI	T1,[ASCIZ |Server:	|]
	PUSHJ	P,.TSTRG##		;TYPE INTRO
	PUSHJ	P,WRTUSR		;WRITE OUT USER INFO
	MOVEI	T1,[ASCIZ | running |]
	PUSHJ	P,.TSTRG##		;TYPE SEPARATOR
	PUSHJ	P,WRTPGM		;WRITE OUT OUR NAME AND VERSION
	PUSHJ	P,.TCRLF##		;CRLF
	MOVEI	T1,[ASCIZ |System:	|]
	PUSHJ	P,.TSTRG##		;TYPE INTRO
	PUSHJ	P,WRTSYS		;WRITE OUT OUR SYSTEM NAME
	PUSHJ	P,.TCRLF##		;CRLF
	MOVEI	T1,[ASCIZ |File:	|]
	PUSHJ	P,.TSTRG##		;TYPE INTRO
	MOVEI	T1,O.FILOP##		;POINT TO FILOP BLOCK
	PUSHJ	P,.TFLPB##		;TYPE FILESPEC
	PUSHJ	P,.TCRLF##		;CRLF
	MOVEI	T1,STARS		;POINT TO A STRING OF STARS
	PUSHJ	P,.TSTRG##		;TERMINATE HEADER
	POP	P,T1			;GET OLD TYPER
	PJRST	.TYOCH##		;RESET SCAN AND RETURN


; Start of page text
NEWPAG:	BYTE(7)	.CHCRT,.CHFFD,0		;<CR><FF>


; Stars for log file header
STARS:	ASCIZ	|
**********************************************************************
|
	SUBTTL	System server -- LOGBEG/LOGEND - begin and end log file I/O


LOGBEG:	PUSH	P,T1			;SAVE KEYWORD STAMP
	MOVEI	T1,CHRFIL##		;WANT FILE OUTPUT ONLY
	PUSHJ	P,.TYOCH##		;TELL SCAN
	MOVEM	T1,LOGTYO		;SAVE TYPER
	PUSHJ	P,.TTIMN##		;PUT OUT TIME STAMP
	PUSHJ	P,.TSPAC##		;SPACE OVER
	POP	P,T1			;GET KEYWORD STAMP
	PUSHJ	P,.TSIXN##		;TYPE IT
	PJRST	.TTABC##		;TAB OVER AND RETURN


LOGEND:	MOVE	T1,LOGTYO		;GET OLD TYPER
	PJRST	.TYOCH##		;TYPE IT AND RETURN
	SUBTTL	System server -- LOGSTA/LOGSTE - Log starting message


LOGSTA:	MOVE	T1,[SIXBIT /START/]	;STAMP
	PUSHJ	P,LOGBEG		;SET UP FOR LOG FILE OUTPUT
	MOVEI	T1,[ASCIZ |Starting |]
	JRST	LOGSTX			;ENTER COMMON CODE

LOGSTE:	MOVE	T1,[SIXBIT /ERROR/]	;STAMP
	PUSHJ	P,LOGBEG		;SET UP FOR LOG FILE OUTPUT
	MOVEI	T1,[ASCIZ |Failed to start|]

LOGSTX:	PUSHJ	P,.TSTRG##		;TYPE TEXT
	MOVE	T1,T.DISP		;GET DISPATCH
	MOVE	T1,.TSNAM(T1)		;GET TASK NAME
	PUSHJ	P,.TSTRG##		;TYPE IT
	MOVEI	T1,[ASCIZ | server|]
	PUSHJ	P,.TSTRG##		;TYPE TEXT
	PUSHJ	P,.TCRLF##		;CRLF
	PJRST	LOGEND			;END LOG FILE I/O
	SUBTTL	System server -- LOGCON - Log CONNECT


LOGCON:	MOVE	T1,[SIXBIT /CONNEC/]	;STAMP
	PUSHJ	P,LOGBEG		;START BEGIN LOG FILE I/O
	MOVE	T1,T.DISP		;GET DISPATCH
	MOVE	T1,.TSNAM(T1)		;GET TASK NAME
	PUSHJ	P,.TSTRG##		;TYPE IT
	MOVEI	T1,[ASCIZ | running in sequence #|]
	PUSHJ	P,.TSTRG##		;TYPE TEXT
	MOVE	T1,T.SEQN		;GET SEQUENCE NUMBER
	PUSHJ	P,.TDECW##		;TYPE IT
	PUSHJ	P,.TCRLF##		;CRLF
	PJRST	LOGEND			;END LOG FILE I/O
	SUBTTL	System server -- LOGDSC - Log DISCONNECT


LOGDSC:	MOVE	T1,[SIXBIT /DISCON/]	;STAMP
	PUSHJ	P,LOGBEG		;BEGIN LOG FILE I/O
	MOVE	T1,T.DISP		;GET DISPATCH
	MOVE	T1,.TSNAM(T1)		;GET TASK NAME
	PUSHJ	P,.TSTRG##		;TYPE IT
	PUSHJ	P,.TCRLF##		;CRLF
	PJRST	LOGEND			;END LOG FILE I/O
	SUBTTL	System server -- LOGRMT - Log REMOTE


LOGREM:	MOVE	T1,[SIXBIT /REMOTE/]	;STAMP
	PUSHJ	P,LOGBEG		;BEGIN LOG FILE I/O
	MOVEI	T1,[ASCIZ |Remote data|]
	PUSHJ	P,.TSTRG##		;TYPE INTRO
	PUSHJ	P,.TCRLF##		;CRLF
	PUSHJ	P,.SAVE1##		;SAVE P1
	MOVE	P1,[-DATLEN,,DATTAB]	;AOBJN POINTER TO TABLE

LOGRE1:	HRRZ	T1,.DTFLG(P1)		;POINT TO DATA STORAGE
	SKIPN	(T1)			;HAVE SOMETHING THERE?
	JRST	LOGRE2			;NO
	PUSHJ	P,.TTABC##		;TAB
	PUSHJ	P,.TTABC##		;ONE MORE
	HLLZ	T1,.DTNAM(P1)		;GET DATA ITEM NAME
	PUSHJ	P,.TSIXN##		;TYPE IT
	PUSHJ	P,.TSPAC##		;SPACE
	HRRZ	T1,.DTFLG(P1)		;GET STORAGE ADDRESS
	PUSHJ	P,.TSTRG##		;TYPE DATA
	PUSHJ	P,.TCRLF##		;CRLF

LOGRE2:	ADD	P1,[.DTMAX-1,,.DTMAX-1]	;ACCOUNT FOR MULTIPLE WORD ENTRIES
	AOBJN	P1,LOGRE1		;LOOP
	PJRST	LOGEND			;END LOG FILE I/O
	SUBTTL	System server -- LOGCMD - Log COMMAND


LOGCMD:	MOVE	T1,[SIXBIT /COMMAN/]	;STAMP
	PUSHJ	P,LOGBEG		;BEGIN LOG FILE I/O
	PUSHJ	P,SRVSET		;RESET BYTE POINTER

LOGCM1:	PUSHJ	P,SRVTAK		;GET A CHARACTER
	SKIPN	T1,C			;COPY IT
	JRST	LOGCM2			;DONE
	PUSHJ	P,.TCHAR##		;LOG IT
	JRST	LOGCM1			;LOOP BACK FOR MORE

LOGCM2:	PUSHJ	P,.TCRLF##		;CRLF
	PJRST	LOGEND			;END LOG FILE I/O
	SUBTTL	User server -- SRVUSR - Initiate server connects


SRVUSR::SKIPL	T1,S.SERVER##+.SVFLG	;WAS /SERVER TYPED?
	TLNE	F,(FL.WHOSRV)		;OR ARE WE A SERVER?
	JRST	.POPJ1##		;JUST A NORMAL COMMAND
	SETOM	S.DPY##			;NEVER LOOP IN DPY MODE
	SETOM	S.REPEAT##		;NEVER LOOP IN REPEAT MODE
	MOVE	T1,S.SERVER##+.SVNOD	;GET NODE
	CAMN	T1,[EXP	-1]		;OUR GOT ONE?
	MOVE	T1,CENSTA##		;NO--DEFAULT TO CENTRAL STATION
	PUSHJ	P,NODINF##		;SEE WHAT TYPE IT IS
	  $FATAL (NSN,<No such node ">,E.NSN)
	MOVEM	T1,S.SERVER##+.SVNOD	;UPDATE NODE NAME
	TXNN	T3,NT.ONL		;IS IT REALLY ONLINE (DECNET)?
	$FATAL	(NNO,<Node not online ">,E.NSN)
	MOVE	T3,TSKNET(T3)		;TRANSLATE NETWORK TYPE TO TASK TYPE
	SKIPGE	T4,S.SERVER##+.SVTYP	;GET CONNECT TYPE
	MOVE	T4,T3			;DEFAULT TASK TYPE TO MATCH NODE TYPE
	TLNN	F,(FL.NETWORKS)		;HAVE NETWORK SUPPORT?
	MOVEI	T4,.TSIPC		;NO--THEN WE CAN ONLY DO IPCF
	CAIN	T4,.TSIPC		;IPCF CONNECT?
	MOVE	T3,T4			;YES
	CAME	T3,T4			;MATCH?
	$FATAL	(NCM,<Network node type and connect type mismatch>)
	MOVEM	T4,S.SERVER##+.SVTYP	;SAVE FOR LATER
	MOVX	T1,TS.ACT		;ACTIVE TASK
	STORE	T4,T1,TS.TYP		;STORE CONNECT TYPE
	MOVE	T4,TSKTAB(T4)		;GET DISPATCH VECTOR FOR THIS TASK
	SKIPG	T2,S.SERVER##+.SVTIM	;GET TIMEOUT IN SECONDS
	MOVE	T2,.TSTIM(T4)		;DEFAULT IT
	STORE	T2,T1,TS.TIM		;STORE IT
	MOVE	T2,S.SERVER##+.SVNOD	;GET TARGET NODE
	PUSHJ	P,OPNTSK		;OPEN A TASK
	  $FATAL (TOF,<Task open failed>)
	$INFO	(CTS,<Connecting to server, >,CONMSG)
	PUSHJ	P,XMTDAT		;TRANSMIT LOCAL DATA TO REMOTE
	  JRST	SRVU.E			;TASK ERROR
	PUSHJ	P,SRVSET		;RESET COMMAND BYTE POINTER
SRVU.1:	PUSHJ	P,SRVTAK		;GET A CHARACTER
	MOVE	T1,C			;COPY IT
	PUSHJ	P,TSKTYO		;PUT A CHARACTER
SRVU.E:	  $FATAL (SOE,<Output error to server>,SRVU.4)
	JUMPN	T1,SRVU.1		;LOOP
	PUSHJ	P,OUTTSK		;FORCE BUFFERS OUT
	  JRST	SRVU.E			;CAN'T
	PUSHJ	P,RCVDAT		;RECEIVE AND PROCESS REMOTE DATA
	  SKIPA	T1,DATERR		;GET DATA ERROR TYPE
	JRST	SRVU.2			;PROTOCOL OK
	MOVE	T1,DATETB-1(T1)		;POINT TO ASSOCIATED TEXT
	$FATAL	(TPE,<Task protocol error; >,.TSTRG##)

SRVU.2:	PUSHJ	P,TYPDAT		;TYPE REMOTE DATA

SRVU.3:	PUSHJ	P,TSKTYI		;GET A CHARACTER
	  $FATAL (SIE,<Input error from server>,CLSTSK)
	JUMPE	T1,SRVU.4		;DONE?
	PUSHJ	P,.TCHAR##		;TYPE IT
	JRST	SRVU.3			;LOOP

SRVU.4:	PUSHJ	P,CLSTSK		;CLOSE THE TASK
	  JFCL				;IGNORE ERRORS
	POPJ	P,			;RETURN

E.NSN:	MOVE	T1,S.SERVER##+.SVNOD	;GET NODE NAME
	PUSHJ	P,.TSIXN##		;TYPE IT
	MOVEI	T1,""""			;CLOSING QUOTE
	PJRST	.TCHAR##		;TYPE IT AND RETURN
	SUBTTL	Server loop -- SRVLOP - Top level


SRVLOP:	MOVE	P,[IOWD	LN$PDL,PDL##]	;RESET STACK
	MOVX	T1,HB.IPC!HB.RIO	;WAKE UP BITS
	SKIPN	T.ATTN			;ANYTHING TO DO?
	HIBER	T1,			;ZZZZZZ
	  JFCL				;ERROR?

SRVL.1:	MOVE	P,[IOWD LN$PDL,PDL##]	;RESET STACK
	SKIPN	T.ATTN			;ANY ACTIVITY?
	JRST	SRVLOP			;NO--SPURRIOUS WAKEUP
	MOVEI	T1,0			;DON'T KNOW THAT TYPE OF TASK YET
	SKIPE	DCNATN			;DECNET?
	MOVEI	T1,DCNTSK		;YES
	SKIPE	ANFATN			;ANF10?
	MOVEI	T1,ANFTSK		;YES
	SKIPE	IPCATN			;IPCF?
	MOVEI	T1,IPCTSK		;YES
	JUMPE	T1,SRVL.4		;HAVE SOMETHING?
	MOVEM	T1,T.DISP		;SET UP DISPATCH
	PUSHJ	P,SRVCMD		;SET UP COMMAND BUFFERS
	AOS	T.SEQN			;BUMP SEQUENCE NUMBER
	PUSHJ	P,LOGCON		;LOG THE CONNECT
	TLZ	F,(FL.SRVJOB)		;CLEAR OUT ALL PRIV AND JOB FLAGS
	PUSHJ	P,PRVTSK		;SET ONLY THOSE WHICH APPLY THIS TASK
	PUSHJ	P,RCVDAT		;RECEIVE LOCAL DATA FROM REMOTE
	  JRST	SRVL.3			;TASK ERROR
	PUSHJ	P,LOGREM		;LOG REMOTE DATA

SRVL.2:	PUSHJ	P,TSKTYI		;GET A CHARACTER
	  JRST	SRVL.3			;INPUT ERROR
	MOVE	C,T1			;COPY
	PUSHJ	P,SRVPUT		;PUT A CHARACTER
	JUMPN	C,SRVL.2		;LOOP READING FROM REMOTE
	PUSHJ	P,LOGCMD		;LOG THE COMMAND
	PUSHJ	P,XMTDAT		;TRANSMIT LOCAL DATA TO REMOTE
	  JRST	SRVL.3			;TASK ERROR
	PUSHJ	P,SRVSET		;RESET THE POINTERS
	MOVE	T1,[LN$IBLK##,,ISBLK##]	;POINT TO .ISCAN BLOCK
	PUSHJ	P,.ISCAN##		;INITIALIZE COMMAND SCANNER
	MOVEI	T1,CHRLST##		;POINT TO SCAN'S CHARACTER LISTER
	MOVEM	T1,.TOUTZ##		;STORE
	PUSHJ	P,CMDLOP##		;PROCESS A COMMAND
	  JFCL				;SHOULDN'T HAPPEN


SRVXIT::!
SRVL.3:	SKIPN	T.DISP			;TASK ACTIVE?
	JRST	SRVL.4			;NO
	PUSHJ	P,OUTTSK		;FORCE OUTPUT
	  JFCL				;IGNORE ERRORS
	PUSHJ	P,LOGDSC		;LOG THE DISCONNECT
	PUSHJ	P,CLSLST##		;CLOSE THE LOG FILE
	PUSH	P,T.DISP		;SAVE OLD DISPATCH
	PUSHJ	P,CLSTSK		;CLOSE TASK
	  JFCL				;IGNORE ERRORS
	POP	P,T.DISP		;RESTORE DISPATCH
	DMOVE	T1,T.OARG		;GET SAVED OPEN ARGUMENTS
	PUSHJ	P,OPNTSK		;RE-OPEN THE TASK
	  HALT	.

SRVL.4:	SOS	T.ATTN			;COUNT DOWN
	JRST	SRVL.1			;LOOP BACK FOR MORE
	SUBTTL	Server loop -- GMSG - Get an IPCF message


GMSG:	SETZM	PDB+.IPCFL		;FLAGS
	SETZM	PDB+.IPCFS		;SENDER
	SETZM	PDB+.IPCFR		;RECEIVER
	MOVE	T1,[12,,BUFFER]		;BUFFER
	MOVEM	T1,PDB+.IPCFP		;STORE
	MOVE	T1,[6,,PDB]		;POINT TO PDB
	IPCFR.	T1,			;GET SOMETHING
	 JRST	GMSG.1			;NOPE
	MOVE	T1,PDB+.IPCFS		;GET SENDER
	MOVEM	T1,SPID			;SAVE FOR LATER
	LOAD	T1,PDB+.IPCFC,IP.SJN	;GET SENDERS JOB
	MOVEM	T1,MYJOB##		;AND AS MYJOB
	MOVE	T1,[POINT 7,BUFFER+2]	;POINT TO DATA
	POPJ	P,			;AND RETURN

; The IPCF receive shouldn't have failed.  Since it's ugly to
; HALT, we'll sleep a little and try it again.  If we're in a
; loop, this will give others a chance to run.

GMSG.1:	MOVEI	T1,^D10			;10 SECONDS
	SLEEP	T1,			;ZZZZZZ
	JRST	GMSG			;TRY AGAIN
	SUBTTL	Server loop -- SMSG - Send an IPCF message


SMSG:	MOVEI	T1,0			;TERMINATE
	IDPB	T1,TXTPTR		;STORE
	MOVX	T1,IP.CFV		;WE SEND PAGES
	MOVEM	T1,PDB+.IPCFL		;SET FLAGS
	MOVE	T1,SPID			;GET SENDERS PID
	MOVEM	T1,PDB+.IPCFR		;NOW HE WILL RECEIVE IT
	SETZM	PDB+.IPCFS		;ZERO SENDER
	MOVE	T1,TXTPAG		;GET THE PAGE
	HRLI	T1,1000			;ITS LENGTH
	MOVEM	T1,PDB+.IPCFP		;STORE
	MOVE	T1,[4,,PDB]		;POINT TO PDB
	IPCFS.	T1,			;SEND IT
	 JFCL
	POPJ	P,			;AND RETURN
	SUBTTL	Buffer control -- SRVCMD/SRVSET - Initialize character storage


; Init command buffer after call to .ISCAN in WHO
SRVINI::LDB	T1,CMDPTR		;GET LAST SCANNED CHARACTER
	PUSH	P,T1			;SAVE IT
	PUSHJ	P,SRVCMD		;RESET COMMAND BUFFER
	POP	P,T1			;RESTORE CHARACTER
	JUMPLE	T1,.POPJ##		;RETURN ON EOL OR EOF
	CAIE	T1,.CHESC		;ESCAPE?
	CAIN	T1,.CHLFD		;LINE-FEED?
	POPJ	P,			;YES
	CAIN	T1,"("			;OR MAYBE .R WHO(FOO)?
	POPJ	P,			;YES TO EITHER
	MOVE	C,T1			;COPY CHARACTER
	PJRST	SRVPUT			;STORE IT AND RETURN


; Set up command buffer
SRVCMD::MOVE	T1,[CMDTAB,,CMDTAB+1]	;SET UP BLT
	SETZM	CMDTAB			;CLEAR FIRST WORD
	BLT	T1,CMDTAB+LN$SBT-1	;CLEAR BUFFER TABLE
	MOVE	T1,[CMDBUF,,CMDBUF+1]	;SET UP BLT
	SETZM	CMDBUF			;CLEAR FIRST WORD
	BLT	T1,CMDBUF+LN$SCB-1	;CLEAR OUT INTERNAL COMMAND BUFFER


; Here to just reset the pointers
SRVSET::SETOM	CMDIDX			;SET BUFFER TABLE INDEX
	MOVEI	T1,CMDBUF		;POINT TO INTERNAL BUFFER
	MOVEM	T1,CMDTAB		;MAKE IT THE FIRST BUFFER TO USE
	HRLI	T1,(POINT 7,)		;BYTE POINTER TO BUFFER
	MOVEM	T1,CMDPTR		;SAVE IT
	MOVEI	T1,<LN$SCB*5>-1		;GET LENGTH OF BUFFER IN CHARACTERS
	MOVEM	T1,CMDCTR		;SAVE COUNT
	POPJ	P,			;RETURN


; Output a character
SRVTYO::PUSHJ	P,TSKTYO		;OUTPUT TO TASK
	  JFCL				;CATCH ERRORS ELSEWHERE??
	POPJ	P,			;RETURN
	SUBTTL	Buffer control -- ADVBUF - Advance buffers


; Call:	PUSHJ	P,ADVBUF
;	  <NON-SKIP>			;OVERFLOW
;	<SKIP>				;BUFFERS ADVANCED
;
ADVBUF:	PUSHJ	P,.SAVE1##		;SAVE P1
	PUSH	P,T1			;SAVE T1 AND SCAN FROM DESTRUCTION
	AOS	P1,CMDIDX		;GET TABLE INDEX
	CAIL	P1,LN$SBT		;HAVE ROOM FOR ANOTHER BUFFER?
	JRST	ADVBU2			;NO--ERROR
	ADDI	P1,CMDTAB		;INDEX INTO THE TABLE
	SKIPE	T1,(P1)			;GET PAGE ADDRESS (IF ANY)
	JRST	ADVBU1			;THERE ISN'T ONE
	PUSHJ	P,M$GPAG##		;GET A PAGE
	  JRST	ADVBU2			;LOSE
	MOVEM	T1,(P1)			;SAVE PAGE ADDRESS

ADVBU1:	HRLI	T1,(POINT 7,)		;MAKE A BYTE POINTER
	MOVEM	T1,CMDPTR		;SAVE IT
	MOVEI	T1,<1000*5>-1		;BYTE COUNT
	MOVEM	T1,CMDCTR		;SAVE IT
	AOS	-1(P)			;SKIP

ADVBU2:	POP	P,T1			;RESTORE T1
	POPJ	P,			;RETURN
	SUBTTL	Buffer control -- SRVPUT/SRVTAK - Character putter & taker


; Put a character in the command buffer
SRVPUT::SOSGE	CMDCTR			;COUNT CHARACTERS
	JRST	SRVPU1			;BUFFER FULL
	IDPB	C,CMDPTR		;STORE CHARACTER
	POPJ	P,			;RETURN

SRVPU1:	PUSHJ	P,ADVBUF		;ADVANCE BUFFER
	  $FATAL (SCO,<Server command buffer overflow>)
	JRST	SRVPUT			;GO BACK AND STORE CHARACTER


; Take a character from the command buffer
SRVTAK::SOSGE	CMDCTR			;COUNT CHRACTERS
	JRST	SRVTA1			;BUFFER EMPTY
	ILDB	C,CMDPTR		;GET A CHARACTER
	POPJ	P,			;RETURN

SRVTA1:	PUSHJ	P,ADVBUF		;ADVANCE BUFFERS
	  $STOP	(NNB,<No next server buffer>)
	JRST	SRVTAK			;GO BACK AND GET A CHARACTER
	SUBTTL	Task service -- Dispatch vectors


; Table of dispatch vector addresses (indexed by task type)
TSKTAB:	EXP	IPCTSK,	ANFTSK,	DCNTSK


; Network to task type translation table (indexed by network type)
TSKNET:	EXP	.TSIPC,	.TSANF,	.TSDCN


; Dispatch vectors
;	Name	Prefix	 Type	Network	Timeout	Feature
TASK	IPCF,	IPC,	.TSIPC,	.NTNON,	  15,	-1
TASK	ANF10,	ANF,	.TSANF,	.NTANF,	  30,	FL.ANF10
TASK	DECnet,	DCN,	.TSDCN,	.NTDCN,	  60,	FL.DECNET
	SUBTTL	Task service -- I/O operations


OPNTSK:	PUSHJ	P,.SAVE2##		;SAVE P1 AND P2
	DMOVE	P1,T1			;COPY FLAGS AND NODE NAME
	DMOVEM	P1,T.OARG		;SAVE FOR POSTERITY
	LOAD	T1,P1,TS.TIM		;GET TIMEOUT
	MOVEM	T1,T.TIME		;SAVE IT
	LOAD	T1,P1,TS.TYP		;GET TYPE OF TASK
	HRRZ	T2,TSKTAB(T1)		;GET DISPATCH TABLE
	MOVEM	T2,T.DISP		;SAVE IT
	SKIPA	T1,[.TSOPN]		;OPEN OFFSET

CLSTSK:	MOVEI	T1,.TSCLS		;CLOSE OFFSET
	PJRST	TSKIO			;ENTER COMMON CODE
INPTSK:	SKIPA	T1,[.TSINP]		;OFFSET TO INPUT
OUTTSK:	MOVEI	T1,.TSOUT		;OFFSET TO OUTPUT
	JRST	TSKIO			;ENTER COMMON CODE
PRVTSK:	MOVEI	T1,.TSPRV		;OFFSET TO PRIV CODE
TSKIO:	PUSH	P,T.TIME		;GET COUNT DOWN TIMER
	POP	P,T.WAIT		;SET IT UP
	ADD	T1,T.DISP		;INDEX INTO TABLE
	PUSHJ	P,@(T1)			;DO I/O
	  POPJ	P,			;PROPAGATE ERROR BACK
	JRST	.POPJ1##		;RETURN
	SUBTTL	Task service -- Common routines


; Set up PSI vector
; Call:	MOVE	T1, vector offset
;	MOVE	T2, interrupt address
;	PUSHJ	P,TSKVEC
;
TSKVEC:	ADDI	T1,VECTOR##		;OFFSET INTO VECTOR BLOCKS
	MOVEM	T2,.PSVNP(T1)		;SAVE NEW PC
	SETZM	.PSVOP(T1)		;CLEAR OLD PC
	MOVX	T2,PS.VPO		;DISABLE ALL INTERRUPTS
	MOVEM	T2,.PSVFL(T1)		;SAVE FLAGS
	SETZM	.PSVIS(T1)		;CLEAR INTERRUPT STATUS
	POPJ	P,			;RETURN


; Turn on or off interrupts
TSKPSI:	PISYS.	T1,			;
	  $STOP	(PSI,<Can't turn on/off PSI; PISYS. error >,.TOCTW##)
	POPJ	P,			;RETURN


; Dismiss interrupts
TSKJEN:	DEBRK.				;DISMISS AND RE-ENABLE PSI
	  JFCL				;UUO NOT INPLEMENTED??
	  POPJ	P,			;HOPE WE GOT HERE VIA A PUSHJ


; Task wait
TSKWAI:	SOSGE	T.WAIT			;WAIT TIME EXPIRED?
	POPJ	P,			;YES
	MOVEI	T1,1			;ONE SECOND
	SLEEP	T1,			;ZZZZZZ
	JRST	.POPJ1##		;RETURN
	SUBTTL	Task service -- TSKTYI - Character input


; Input a character
TSKTYI:	MOVE	T1,T.DISP		;GET DISPATCH
	MOVE	T1,.TSIBR(T1)		;POINT TO INPUT BUFFER RING HEADER
	SOSGE	.BFCTR(T1)		;COUNT CHARACTERS
	JRST	TSKTI1			;BUFFER EMPTY
	ILDB	T1,.BFPTR(T1)		;GET A CHARACTER
	JRST	.POPJ1##		;RETURN
TSKTI1:	PUSHJ	P,INPTSK		;INPUT A BUFFER
	  SKIPA	T1,T.IOST		;INPUT ERROR--GET I/O STATUS
	JRST	TSKTYI			;GO BACK AND GET A CHARACTER
	TXNN	T1,IO.EOF		;EOF?
	POPJ	P,			;NO--A REAL ERROR
	MOVEI	T1,.CHNUL		;GET A NUL TO TERMINATE I/O
	JRST	.POPJ1##		;AND RETURN
	SUBTTL	Task service -- TSKTYO - Character output


; Output a character
TSKTYO::MOVEM	T1,T.CHAR		;SAVE CHARACTER
TSKTO1:	MOVE	T1,T.DISP		;GET DISPATCH
	MOVE	T1,.TSOBR(T1)		;POINT TO OUTPUT BUFFER RING HEADER
	SOSGE	.BFCTR(T1)		;COUNT CHARACTERS
	JRST	TSKTO2			;BUFFER FULL
	MOVEI	T1,.BFPTR(T1)		;GET BYTE POINTER ADDRESS
	EXCH	T1,T.CHAR		;SWAP WITH SAVED CHARACTER
	IDPB	T1,@T.CHAR		;PUT A CHARACTER
	JRST	.POPJ1##		;RETURN
TSKTO2:	PUSHJ	P,OUTTSK		;OUTPUT A BUFFER
	  POPJ	P,			;OUTPUT ERROR
	JRST	TSKTO1			;GO BACK AND STORE CHARACTER
	SUBTTL	Task service -- IPCF


; Turn interrupts on or off
IPCON:	SKIPA	T1,[PS.FON!PS.FAC+IPCPSI] ;TURN ON
IPCOFF:	MOVE	T1,[PS.FOF!PS.FRC+IPCPSI] ;TURN OFF
	JRST	TSKPSI			;GO TURN ON OR OFF CONDITION

IPCPSI:	EXP	.PCIPC			;IPCF
	XWD	.IVIPC,0		;OFFSET,,REASONS
	XWD	0,0			;PRIORITY 0,,RESERVED


; Here on an interrupt
IPCINT::HALT	.
	JRST	TSKJEN			;DISMISS INTERRUPT
; Open an IPCF task.  This routine will become [SYSTEM]WHOSRV
; if passive requested.  If active requested, then the PID of
; [SYSTEM]WHOSRV will be found.
;
IPCOPN:	MOVE	T1,[I.SRV,,I.SRV+1]	;SET UP BLT
	SETZM	I.SRV			;CLEAR FIRST WORD
	BLT	T1,I.SRV+11		;CLEAR OUT BLOCK
	TXNE	P1,TS.ACT		;WHAT MODE?
	SKIPA	T1,['WHO',,.IPCIW]	;ACTIVE
	MOVE	T1,['WHO',,.IPCII]	;PASSIVE
	MOVEM	T1,I.SRV+0		;SAVE IT
	SETZM	I.SRV+1			;NO PID FOR COPY

IPCOP1:	MOVEI	T1,[IDPB T1,I.PTR
		    POPJ  P,]		;CHARACTER TYPER
	PUSHJ	P,.TYOCH##		;TELL SCAN
	PUSH	P,T1			;SAVE OLD TYPER
	MOVE	T1,[POINT 7,I.SRV+2]	;WHERE TO PUT THE NAME
	MOVEM	T1,I.PTR		;SAVE IT
	MOVE	T1,.MYPPN##		;GET OUR PPN
	TXNE	P1,TS.ACT		;ACTIVE?
	JRST	IPCOP2			;YES--SKIP AROUND LISTENER STUFF
	CAMN	T1,OPRPPN##		;YES--ARE WE THE OPERATOR?
	MOVE	T1,['SYSTEM']		;THEN MAKE IT [SYSTEM]WHOSRV

IPCOP2:	PUSHJ	P,.TPPNW##		;TYPE PPN WORD
	MOVE	T1,['WHOSRV']		;GET SERVER NAME
	PUSHJ	P,.TSIXN##		;TYPE IT
	POP	P,T1			;RESTORE TYPER
	PUSHJ	P,.TYOCH##		;TELL SCAN

	SETZM	I.PDB+.IPCFL		;NO FLAGS
	SETZM	I.PDB+.IPCFS		;TO SYSINF
	SETZM	I.PDB+.IPCFR		;NO RECIEVER
	MOVE	T1,[12,,I.SRV]		;LENGTH,,PACKET ADDRESS
	MOVEM	T1,I.PDB+.IPCFP		;STORE

IPCOP3:	MOVE	T1,[4,,I.PDB]		;POINT TO MESSAGE
	IPCFS.	T1,			;SEND IT
	 $FATAL	(STS,<Send to [SYSTEM]INFO failed>)
	MOVE	T1,[12,,I.PKT]		;POINT TO BUFFER
	PUSHJ	P,IPCRCV		;RECEIVE A PACKET
	 $FATAL	(RFS,<Receive from [SYSTEM]INFO failed>)
	HLRZ	T1,I.PKT		;GET ACK CODE
	CAIE	T1,'WHO'		;OURS?
	JRST	IPCOP3			;NO--TRY AGAIN
	MOVE	T1,I.PKT+1		;GET RETURNED PID
	MOVEM	T1,I.PID		;SAVE IT
	AOS	IPCFLG			;TASK INITIALIZED
	JRST	.POPJ1##		;RETURN
; Close an IPCF task
IPCCLS:	SETZM	IPCFLG			;TASK DONE
	SETZM	T.DISP			;CLEAR DISPATCH
	JRST	.POPJ1##		;RETURN


; Input from an IPCF task (IPCF receive)
IPCINP:	HALT	.


; Output to an IPCF task (IPCF send)
IPCOUT:	HALT	.
; Send an IPCF packet
; Call:	MOVE	T1,[LEN,,ADDR]
;	PUSHJ	P,IPCSND
;	  <ERROR>
;	<NORMAL>
;
IPCSND:	PUSHJ	P,.SAVE1##		;SAVE P1
	SKIPA	P1,T1			;SAVE USERS ADDRESS INCASE OF ERROR

IPCSE1:	MOVE	T1,P1			;GET USERS ADDRESS
	IPCFS.	T1,			;SEND IT
	  SKIPA				;FAILED
	JRST	.POPJ1##		;RETURN
	CAIE	T1,IPCRS%		;SENDERS QUOTA EXCEEDED?
	CAIN	T1,IPCRR%		;OR RECIEVERS?
	JRST	IPCSE2			;YES--TRY TO RESEND
	CAIE	T1,IPCRY%		;FREE SPACE EXHAUSTED?
	POPJ	P,			;NO--RETURN ERROR TO USER

IPCSE2:	PUSHJ	P,TSKWAI		;ZZZZZZ
	  POPJ	P,			;TIMED OUT
	JRST	IPCSE1			;AND TRY AGAIN
; Receive an IPCF packet
; Call:	MOVE	T1,[length,,address]
;	PUSHJ	P,IPCRCV
;	  <ERROR>
;	<NORMAL>
;
IPCRCV:	PUSHJ	P,.SAVE1##		;SAVE P1
	MOVE	P1,T1			;COPY POINTER
	MOVEM	T1,I.PDB+.IPCFP		;SAVE LENGTH AND ADDRESS
	HLRZS	T1			;GET LENGTH
	CAIE	T1,1000			;A PAGE?
	TDZA	T1,T1			;NO
	MOVX	T1,IP.CFV		;ASSUME PAGE
	MOVEM	T1,I.PDB+.IPCFL		;SAVE
	SETZM	I.PDB+.IPCFS		;CLEAR PIDS
	SETZM	I.PDB+.IPCFR		;..
	SETZM	I.PDB+.IPCFU		;CLEAR PPN
	SETZM	I.PDB+.IPCFC		;CLEAR CAPABILITY WORD
	MOVE	T1,[4,,I.PDB]		;POINT TO PDB
	IPCFR.	T1,			;RECEIVE
	  POPJ	P,			;FAILED
	MOVE	T1,P1			;RESTORE POINTER
	JRST	.POPJ1##		;RETURN
; Set/clear privs and job information
IPCPRV:	IOR	F,SRVFLG		;RESET OUR JOB'S FLAGS
	POPJ	P,			;RETURN
	SUBTTL	Task service -- ANF10


; Turn interrupts on or off
ANFON:	SKIPA	T1,[PS.FON!PS.FAC+ANFPSI] ;TURN ON
ANFOFF:	MOVE	T1,[PS.FOF!PS.FRC+ANFPSI] ;TURN OFF
	JRST	TSKPSI			;GO TURN ON OR OFF CONDITION

ANFPSI:	EXP	TSK			;ANF10 I/O CHANNEL
	XWD	.IVANF,PS.RID!PS.ROD	;OFFSET,,REASONS
	XWD	0,0			;PRIORITY 0,,RESERVED


; Here on an interrupt
ANFINT::AOS	ANFATN			;REMEMBER THE INTERRUPT
	AOS	T.ATTN			;HERE TOO
	JRST	TSKJEN			;DISMISS INTERRUPT
; Open an ANF10 task channel
ANFOPN:	TLNN	F,(FL.ANF10)		;HAVE ANF10 SUPPORT?
	POPJ	P,			;NO
	MOVE	T1,[UU.PHS!UU.AIO+.IOASC] ;PHYSICAL ASYNC I/O IN ASCII MODE
	MOVEM	T1,ANFOBK+.OPMOD	;SAVE MODE WORD
	MOVSI	T1,'TSK'		;DEVICE
	MOVEM	T1,ANFOBK+.OPDEV	;SAVE IT
	MOVE	T1,[ANFOBR,,ANFIBR]	;BUFFER RING HEADERS
	MOVEM	T1,ANFOBK+.OPBUF	;SAVE ADDRESSES
	SKIPN	T1,P2			;GET NODE NAME
	JRST	ANFOP1			;THERE ISN'T ONE
	PUSHJ	P,ANODE##		;TRANSLATE TO NODE NUMBER
	  POPJ	P,			;NO SUCH NODE
	TRNN	T1,777700		;MUST
	LSH	T1,3			; LEFT
	TRNN	T1,777700		;  JUSTIFY
	LSH	T1,3			;    IN RH WORD
	PUSHJ	P,OCTSIX##		;CONVERT OCTAL TO SIXBIT
	  MOVE	T1,P2			;HMMM.  MUSTA BEEN OCTAL
	HRRM	T1,ANFOBK+.OPDEV	;STORE RH OF DEVICE NAME

ANFOP1:	OPEN	TSK,ANFOBK		;OPEN A TSK CHANNEL
	  POPJ	P,			;CAN'T
	SKIPE	T1,ANFBFS		;ALREADY HAVE BUFFERS ALLOCATED?
	JRST	ANFOP2			;YES
	MOVEI	T1,ANFOBK		;POINT TO OPEN BLOCK
	DEVSIZ	T1,			;FIND DEVICE SIZE
	  MOVE	T1,[2,,103]		;ASSUME 2 TSK BUFFERS
	HLRZ	T2,T1			;GET NUMBER OF BUFFERS
	IMULI	T1,(T2)			;COMPUTE SIZE
	PUSHJ	P,M$ALLOC##		;ALLOCATE CORE
	MOVEM	T1,ANFBFS		;SAVE ADDRESS OF BUFFERS

ANFOP2:	EXCH	T1,.JBFF		;SAVE .JBFF, POINT MONITOR AT BUFFERS
	OUTBUF	TSK,1			;BUILD OUTPUT BUFFERS
	INBUF	TSK,1			;BUILD INPUT BUFFERS
	MOVEM	T1,.JBFF		;RESTORE .JBFF

ANFOP3:	MOVE	T1,['WHOSRV']		;TASK NAME
	MOVEM	T1,ANFLEB+0		;SAVE IT
	SETZM	ANFLEB+1		;NO EXTENSION
	SETZM	ANFLEB+2		;CLEAR JUNK HERE
	SETZB	T1,ANFLEB+3		;ASSUME ACTIVE (WE'LL TALK TO ANYONE)
	TXNE	P1,TS.ACT		;ACTIVE?
	JRST	ANFOP4			;YES--SKIP AROUND LISTENER STUFF
	MOVE	T1,.MYPPN##		;GET OUR PPN
	CAMN	T1,OPRPPN##		;ARE WE THE OPERATOR?
	MOVNI	T1,1			;ACCEPT CONNECTS FROM [*,*]

ANFOP4:	MOVEM	T1,ANFLEB+3		;SET PPN WORD
	TXNE	P1,TS.ACT		;WHAT MODE?
	SKIPA	T1,[ENTER  TSK,ANFLEB]	;ACTIVE
	MOVE	T1,[LOOKUP TSK,ANFLEB]	;PASSIVE
	XCT	T1			;DO ENTER OR LOOKUP
	  POPJ	P,			;CAN'T
	TXNE	P1,TS.ACT		;ACTIVE?
	JRST	ANFOP5			;YES--FINISH UP
	MOVEI	T1,.IVANF		;ANF10 VECTOR OFFSET
	MOVEI	T2,ANFINT		;ANF10 INTERRUPT ADDRESS
	PUSHJ	P,TSKVEC		;SET UP VECTOR
	PUSHJ	P,ANFON			;PASSIVE NEEDS PSI TURNED ON
	PUSHJ	P,ANFINP		;PRIME THE PUMP
	  JFCL				;NOT REALLY A FAILURE

ANFOP5:	AOS	ANFFLG			;TASK INITIALIZED
	JRST	.POPJ1##		;RETURN
; Close an ANF10 task channel
ANFCLS:	PUSHJ	P,ANFOFF		;TURN OFF PSI
	CLOSE	TSK,			;CLOSE
	RELEAS	TSK,			;RELEASE CHANNEL
	SETZM	ANFATN			;CLEAR ATTENTION FLAG
	SETZM	ANFFLG			;TASK DONE
	SETZM	T.DISP			;CLEAR DISPATCH ADDRESS
	JRST	.POPJ1##		;RETURN


; Input from an ANF10 task
ANFINP:	IN	TSK,			;READ A BUFFER
	JRST	.POPJ1##		;RETURN SUCESSFUL
	GETSTS	TSK,T1			;GET CHANNEL STATUS
	MOVEM	T1,T.IOST		;UPDATE I/O STATUS
	TXNN	T1,IO.ERR!IO.EOF	;ANY ERRORS OR EOF?
	PUSHJ	P,TSKWAI		;NO--WAIT A SECOND
	  POPJ	P,			;INPUT ERRORS OR TIMED OUT
	JRST	ANFINP			;TRY THE READ AGAIN


; Output to an ANF10 task
ANFOUT:	OUT	TSK,			;WRITE A BUFFER
	JRST	.POPJ1##		;RETURN SUCESSFUL
	GETSTS	TSK,T1			;GET CHANNEL STATUS
	TXNN	T1,IO.ERR		;ANY ERRORS?
	PUSHJ	P,TSKWAI		;NO--WAIT A SECOND
	  POPJ	P,			;OUTPUT ERRORS OR TIMED OUT
	JRST	ANFOUT			;TRY THE READ AGAIN
; Set/clear privs and job information
ANFPRV:	MOVSI	T1,(FL.SPY)		;GET PRIVS
	HRR	T1,SRVFLG		;GET RANDOM INTERNAL BITS
	AND	T1,SRVFLG		;BUT ONLY IF WE HAVE THEM TO BEGIN WITH
	TDO	F,T1			;SET FLAGS
	POPJ	P,			;RETURN
	SUBTTL	Task service -- DECnet


; Turn interrupts on or off
DCNON:	SKIPA	T1,[PS.FON!PS.FAC+DCNPSI] ;TURN ON
DCNOFF:	MOVE	T1,[PS.FOF!PS.FRC+DCNPSI] ;TURN OFF
	JRST	TSKPSI			;GO TURN ON OR OFF CONDITION

DCNPSI:	EXP	.PCNSP			;DECNET I/O
	XWD	.IVDCN,0		;OFFSET,,REASONS
	XWD	0,0			;PRIORITY 0,,RESERVED


; Here on an interrupt
DCNINT::HALT	.
	JRST	TSKJEN			;DISMISS INTERRUPT
; Open a DECnet task
DCNOPN:	TLNN	F,(FL.DECNET)		;HAVE DECNET?
	POPJ	P,			;NO
	AOS	DCNFLG			;TASK INITIALIZED
	HALT	.


; Close a DECnet task
DCNCLS:	SETZM	DCNFLG			;TASK DONE
	JRST	.POPJ1##		;RETURN

DCNINP:	HALT	.
DCNOUT:	HALT	.


; Set/clear privs and job information
DCNPRV:	IOR	F,SRVFLG		;RESET OUR JOB'S FLAGS
	POPJ	P,			;RETURN
	SUBTTL	Message generation -- Connect


CONMSG:	MOVEI	T1,[ASCIZ |Type:|]	;FIRST THE TYPE
	PUSHJ	P,.TSTRG##		;TYPE TEXT
	MOVE	T1,T.DISP		;GET DISPATCH ADDRESS
	MOVE	T1,.TSNAM(T1)		;POINT TO TASK NAME
	PUSHJ	P,.TSTRG##		;TYPE IT
	MOVEI	T1,[ASCIZ |  Node:|]	;NEXT THE NODE NAME
	PUSHJ	P,.TSTRG##		;TYPE TEXT
	MOVE	T1,T.OARG+1		;GET NODE NAME
	PUSHJ	P,.TSIXN##		;TYPE IT
	MOVEI	T1,[ASCIZ |  Timeout:|]	;FINALLY THE TIMEOUT
	PUSHJ	P,.TSTRG##		;TYPE TEXT
	MOVE	T1,T.TIME		;GET TIMEOUT VALUE
	PJRST	.TDECW##		;TYPE SECONDS AND RETURN


CONTYP:	ASCIZ	|WHO server connect|
CONLEN==.-CONTYP			;LENGTH OF CONNECT "TYPE" TEXT
	SUBTTL	Message generation -- Error


ERRMSG:	POPJ	P,


ERRTYP:	ASCIZ	|WHO server error|
ERRLEN==.-ERRTYP			;LENGTH OF ERROR "TYPE" TEXT
	SUBTTL	Message generation -- Disconnect


DISMSG:	POPJ	P,


DISTYP:	ASCIZ	|WHO server disconnect|
DISLEN==.-DISTYP			;LENGTH OF DISCONNECT "TYPE" TEXT
	SUBTTL	Message generation -- Miscellaneous routines


; Init buffer
MSGINI:	MOVEI	T1,<LN$SMB*5>-1		;GET CHARACTER COUNT
	MOVEM	T1,MSGCTR		;SAVE IT
	MOVE	T1,[POINT 7,MSGBUF]	;GET BYTE POINTER
	MOVEM	T1,MSGPTR		;SAVE IT
	MOVE	T1,[MSGBUF,,MSGBUF+1]	;SET UP BLT
	SETZM	MSGBUF			;CLEAR FIRST WORD
	BLT	T1,MSGBUF+LN$SMB-1	;CLEAR ENTIRE BUFFER
	MOVEI	T1,MSGTYO		;GET CHARACTER TYPER
	PUSHJ	P,.TYOCH##		;TELL SCAN
	MOVEM	T1,MSGTYP		;SAVE OLD TYPER
	POPJ	P,			;RETURN


; Character typer
MSGTYO:	SOSLE	MSGCTR			;COUNT DOWN
	IDPB	T1,MSGPTR		;STORE CHARACTER
	POPJ	P,			;RETURN

; Exit
MSGXIT:	MOVE	T1,MSGTYP		;GET OLD TYPER
	PUSHJ	P,.TYOCH##		;RESET SCAN
	POPJ	P,			;RETURN
	SUBTTL	Protocol -- Data definitions


; Data table (DATTAB) entry offsets
	.DTNAM==0			;SIXBIT NAME,,ASCIZ TEXT
	.DTFLG==1			;LENGTH AND STORAGE ADDRESS
	   DT.CRL==1B0			   ;CRLF PREFIXES TEXT
	   DT.NTY==1B1			   ;DATA ITEM NOT TYPED OUT
	   DT.FLG==777B8		   ;MASK OF ALL FLAGS
	   DT.LEN==777B17		   ;MASK OF BUFFER LENGTH IN CHARACTERS
	.DTIOS==2			;READ,,WRITE I/O SUBROUTINES
	.DTMAX==3			;LENGTH OF ENTRY


DEFINE	$DATA,<
X	(DTM,025,<Packet transmitted at >,<DT.CRL>)
X	(USR,039,<User >,<DT.CRL>)
X	(PGM,048,< running >,<0>)
X	(SEQ,006,< in sequence >,<0>)
X	(SYS,073,<System is >,<DT.CRL>)
X	(IPC,044,<IPCF process-ID >,<DT.CRL>)
X	(ANF,034,<ANF10 node/task >,<DT.CRL>)
X	(DCN,015,<DECnet node/task >,<DT.CRL>)
X	(MOD,006,<Mode>,<DT.NTY>)
X	(END,050,<Comment>,<0>)
> ;END $DATA MACRO

DEFINE	X	(NAM,LEN,TXT,FLG),<
	XWD	''NAM'',[ASCIZ |TXT|]
	EXP	FLG+<XWD ^D<LEN>,NAM'BUF>
	XWD	RED'NAM,WRT'NAM
>

DATTAB:	$DATA
DATLEN==.-DATTAB

DATETB:	[ASCIZ	|I/O error|]
	[ASCIZ	|Format error|]
; Write DTM
WRTDTM:	PUSHJ	P,XB$UDT##		;GET DATE/TIME
	PJRST	.TDTTM##		;TYPE IT AND RETURN


; Read DTM
REDDTM:	POPJ	P,


; Write PGM
WRTPGM:	HRROI	T1,.GTPRG		;WANT OUR PROGRAM NAME
	PUSHJ	P,GTAB##		;GET IT
	PUSHJ	P,.TSIXN##		;SEND IT OUT
	MOVEI	T1,[ASCIZ | %|]		;TYPE
	PUSHJ	P,.TSTRG##		; SEPARATOR
	MOVE	T1,.JBVER		;GET OUR VERSION
	PUSHJ	P,.TVERW##		;TYPE IT
	SKIPN	.JBCST			;HAVE A CUSTOMER VERSION?
	POPJ	P,			;NO
	MOVEI	T1,"/"			;GET A SLASH
	PUSHJ	P,.TCHAR##		;TYPE IT
	MOVE	T1,.JBCST		;GET CUSTOMER VERSION
	PJRST	.TVERW##		;TYPE IT AND RETURN


; Read PGM
REDPGM:	POPJ	P,


; Write USR
WRTUSR:	HRROI	T1,.GTNM1		;USER NAME (WORD 1)
	PUSHJ	P,GTAB##		;GET IT
	PUSH	P,T1			;SAVE FOR LATER
	HRROI	T1,.GTNM2		;USER NAME (WORD 2)
	PUSHJ	P,GTAB##		;GET IT
	JUMPE	T1,WRTUS1		;2 WORD?
	EXCH	T1,(P)			;YES--SWAP
	MOVEI	T3,6			;SIX CHARACTERS
	PUSHJ	P,.TSIXJ##		;TYPE IT

WRTUS1:	POP	P,T1			;GET NAME
	PUSHJ	P,.TSIXN		;OUTPUT
	PUSHJ	P,.TSPAC##		;SPACE OVER
	MOVE	T1,.MYPPN##		;GET OUR PPN
	PJRST	.TPPNW##		;TYPE IT AND RETURN


; Read USR
REDUSR:	POPJ	P,


; Write IPC
WRTIPC:	POPJ	P,


; Read IPC
REDIPC:	POPJ	P,


; Write ANF
WRTANF:	TLNN	F,(FL.ANF10)		;HAVE ANF10 SUPPORT?
	POPJ	P,			;NO
	MOVE	T1,CENSTA##		;GET OUR NODE NUMBER
	PUSHJ	P,ANODE##		;CONVERT TO NODE NAME
	  MOVE	T1,[SIXBIT/??????/]	;HMMM
	PUSHJ	P,.TSIXN##		;TYPE IT
	PUSHJ	P,.TLPRN##		;TYPE "("
	MOVE	T1,CENSTA##		;GET NODE NUMBER AGAIN
	PUSHJ	P,.TOCTW##		;TYPE IT
	PUSHJ	P,.TRPRN##		;TYPE ")"
	PUSHJ	P,.TSPAC##		;SPACE
	MOVE	T1,['WHOSRV']		;TASK NAME
	PUSHJ	P,.TSIXN##		;TYPE IT
	MOVE	T1,.MYPPN##		;GET PPN
	PJRST	.TPPNW##		;TYPE IT AND RETURN


; Read ANF
REDANF:	POPJ	P,


; Write DCN
WRTDCN:	POPJ	P,


; Read DCN
REDDCN:	POPJ	P,


; Write SYS
WRTSYS:	MOVEI	T1,[ASCIZ |TOPS-10 %|]	;TYPE
	PUSHJ	P,.TSTRG##		; INTRODUCTION
	PUSHJ	P,XB$DVN##		;GET DEC VERSION NUMBER
	PUSHJ	P,.TVERW##		;TYPE IT
	PUSHJ	P,XB$CVN##		;GET CUSTOMER VERSION
	JUMPE	T1,WRTSY1		;HAVE ONE?
	PUSH	P,T1			;YES--SAVE IT
	MOVEI	T1,"/"			;GET SLASH
	PUSHJ	P,.TCHAR##		;TYPE IT
	POP	P,T1			;GET BACK CUSTOMER VERSION
	PUSHJ	P,.TVERW##		;TYPE IT
WRTSY1:	MOVEI	T1,[ASCIZ |, |]		;TYPE
	PUSHJ	P,.TSTRG##		; SEPARATOR
	PUSHJ	P,XB$NAM##		;GET MONITOR NAME
	PJRST	.TSTRG##		;TYPE IT AND RETURN


; Read SYS
REDSYS:	POPJ	P,


; Write SEQ
WRTSEQ:	MOVE	T1,T.SEQN		;GET SEQUENCE NUMBER
	PJRST	.TDECW##		;TYPE IT AND RETURN


; Read SEQ
REDSEQ:	POPJ	P,


; Write MOD
WRTMOD:	MOVE	T1,MON.T##(M)		;GET THE MODE NAME
	PJRST	.TSIXN##		;TYPE IT AND RETURN


; Read MOD
REDMOD:	SETZ	T1,			;CLEAR DESTINATION
	MOVE	T3,[POINT 7,MODBUF]	;POINT TO MOD STORAGE
	MOVE	T4,[POINT 6,T1]		;POINT TO MOD CONVERSION STORAGE

REDMO1:	ILDB	T2,T3			;GET A CARACTER
	JUMPE	T2,REDMO2		;DONE?
	SUBI	T2,40			;CONVERT TO SIXBIT
	TRNN	T1,77			;WORD FULL?
	IDPB	T2,T4			;STORE CHARACTER
	JRST	REDMO1			;LOOP

REDMO2:	MOVE	N,T1			;GET MODE KEYWORD
	MOVE	T1,[IOWD MON.L##,MON.T##] ;POINT TO COMMAND TABLE
	PUSHJ	P,.NAME##		;LOOKUP NAME
	  TDZA	T1,T1			;DON'T KNOW THIS ONE
	SUBI	T1,MON.T##		;INDEX INTO TABLE
	ANDI	T1,-1			;NO JUNK
	PJRST	SETMOD##		;SET UP AC 'M' WITH MODE INDEX


; Write END
WRTEND:	POPJ	P,			;NO "END" COMMENTS


; Read END
REDEND:	POPJ	P,
	SUBTTL	Protocol -- XMTDAT - Transmit local data to remote


XMTDAT:	PUSHJ	P,.SAVE1##		;SAVE P1
	TRO	F,FR.TASK		;FLAG TASK I/O
	MOVEI	T1,CHRLST##		;POINT TO CHARACTER TYPER
	PUSHJ	P,.TYOCH##		;TELL SCAN
	PUSH	P,T1			;SAVE OLD TYPER
	MOVE	P1,[-DATLEN,,DATTAB]	;AOBJN POINTER TO TABLE

XMTD.1:	PUSHJ	P,.TDOT##		;SEND OUT A PERIOD TO START LINE
	HLLZ	T1,.DTNAM(P1)		;GET DATA ITEM NAME
	PUSHJ	P,.TSIXN##		;SEND TO REMOTE
	PUSHJ	P,.TSPAC##		;FOLLOW BY A SPACE
	HRRZ	T1,.DTIOS(P1)		;GET ROUTINE TO WRITE
	PUSHJ	P,(T1)			;PUT DATA INTO THE BUFFER
	PUSHJ	P,.TCRLF##		;END LINE WITH A CRLF
	ADD	P1,[.DTMAX-1,,.DTMAX-1]	;ACCOUNT FOR MULTIPLE WORD ENTRIES
	AOBJN	P1,XMTD.1		;LOOP
	POP	P,T1			;GET OLD TYPER BACK
	PUSHJ	P,.TYOCH##		;RESET SCAN
	TRZ	F,FR.TASK		;CELAR TASK I/O FLAG
	JRST	.POPJ1##		;RETURN
	SUBTTL	Protocol -- RCVDAT - Receive local data from remote


RCVDAT:	PUSHJ	P,.SAVE1##		;SAVE P1
	SETZM	DATBFS			;CLEAR A WORD
	MOVE	T1,[DATBFS,,DATBFS+1]	;SET UP BLT
	BLT	T1,DATBFE-1		;CLEAR DATA BUFFERS

RCVD.1:	MOVE	T3,[POINT 6,T4]		;BYTE POINTER
	SETZ	T4,			;CLEAR DESTINATION
	PUSHJ	P,TSKTYI		;GET A CHARACTER
	  PJRST	RCVIOE			;I/O ERROR
	CAIE	T1,"."			;MUST BEGIN WITH A PERIOD
	PJRST	RCVPFE			;PROTOCOL FORMAT ERROR

RCVD.2:	PUSHJ	P,TSKTYI		;GET A CHARACTER
	  PJRST	RCVIOE			;I/O ERROR
	CAIE	T1,.CHNUL		;EOF?
	CAIN	T1," "			;END OF NAMED DATA ITEM?
	JRST	RCVD.3			;YES
	SUBI	T1," "			;CONVERT ASCII TO SIXBIT
	TRNN	T4,777777		;OVERFLOW? (POSSIBLE JUNK)
	IDPB	T1,T3			;STORE CHARACTER
	JRST	RCVD.2			;LOOP BACK FOR MORE

RCVD.3:	MOVE	P1,[-DATLEN,,DATTAB]	;AOBJN POINTER TO TABLE

RCVD.4:	HLLZ	T1,.DTNAM(P1)		;GET A NAME
	CAME	T1,T4			;MATCH?
	AOBJN	P1,RCVD.4		;NO--LOOP
	JUMPGE	P1,RCVD.6		;PROTOCOL FORMAT ERROR
	MOVE	T1,.DTFLG(P1)		;POINT TO LENGTH AND ADDRESS
	TLZ	T1,(DT.FLG)		;CLEAR OUT TYPEOUT FLAGS
	PUSHJ	P,CHRSET##		;SET UP BYTE COUNT AND POINTER

RCVD.5:	PUSHJ	P,TSKTYI		;GET A CHARACTER
	  PJRST	RCVIOE			;I/O ERROR
	CAIN	T1,.CHCRT		;CARRIAGE RETURN?
	JRST	RCVD.5			;YES--IGNORE IT
	CAIN	T1,.CHLFD		;LINE FEED?
	JRST	RCVD.7			;YES
	PUSHJ	P,CHRPUT##		;STORE IT AWAY
	JRST	RCVD.5			;LOOP BACK FOR MORE

RCVD.6:	PUSHJ	P,TSKTYI		;GET A CHARACTER
	  PJRST	RCVIOE			;I/O ERROR
	JUMPE	T1,RCVPFE		;PROTOCOL FORMAT ERROR
	CAIE	T1,.CHLFD		;EOL?
	JRST	RCVD.6			;LOOP BACK AND EAT MORE CHARACTERS
	JRST	RCVD.1			;FINALLY DONE WITH THIS ONE

RCVD.7:	PUSHJ	P,CHRNUL##		;FORCE A NUL INTO THE BUFFER
	HLRZ	T1,.DTIOS(P1)		;GET ROUTINE TO READ
	PUSHJ	P,(T1)			;READ DATA FROM BUFFER
	HLRZ	T1,.DTNAM(P1)		;GET ITEM NAME
	CAIE	T1,'END'		;LAST ONE?
	JRST	RCVD.1			;NO--GO BACK FOR ANOTHER DATA ITEM
	SETZM	DATERR			;CLEAR ERROR FLAG
	JRST	.POPJ1##		;AND RETURN

RCVIOE:	SKIPA	T1,[EXP 1]		;DATA I/O ERROR
RCVPFE:	MOVEI	T1,2			;PROTOCOL FORMAT ERROR
	MOVEM	T1,DATERR		;SET ERROR FLAG
	POPJ	P,			;AND RETURN
	SUBTTL	Protocol -- TYPDAT - Type local data from remote


TYPDAT:	PUSHJ	P,.SAVE2##		;SAVE P1 AND P2
	MOVE	P1,[-DATLEN,,DATTAB]	;AOBJN POINTER TO TABLE

TYPD.1:	HRRZ	T1,.DTFLG(P1)		;POINT TO STORAGE ADDRESS
	SKIPN	(T1)			;HAVE THIS ONE?
	JRST	TYPD.2			;NO
	MOVE	P2,.DTFLG(P1)		;GET FLAGS
	TLNE	P2,(DT.NTY)		;NEVER TYPE THIS ONE?
	JRST	TYPD.2			;THATS RIGHT
	TLNE	P2,(DT.CRL)		;PREFIX WITH A CRLF?
	PUSHJ	P,.TCRLF##		;YES
	HRRZ	T1,.DTNAM(P1)		;GET ITEM NAME
	PUSHJ	P,.TSTRG##		;TYPE IT
	HRRZ	T1,.DTFLG(P1)		;POINT TO DATA STORAGE
	PUSHJ	P,.TSTRG##		;TYPE IT

TYPD.2:	ADD	P1,[.DTMAX-1,,.DTMAX-1]	;ACCOUNT FOR MULTIPLE WORD ENTRIES
	AOBJN	P1,TYPD.1		;LOOP
	PUSHJ	P,.TCRLF##		;CRLF
	PJRST	.TCRLF##		;ONE MORE AND RETURN
	SUBTTL	Storage


SRVLGO::BLOCK	1		;NON-ZERO IF OK TO USE /SERVE LOGGED OUT

	$LOW

HDRFLG:	BLOCK	1		;NON-ZERO IF HAVE OUTPUT LOG HEADER

; Command buffer data
CMDIDX:	BLOCK	1		;TABLE INDEX
CMDTAB:	BLOCK	LN$SBT		;TABLE
CMDCTR:	BLOCK	1		;BYTE COUNT
CMDPTR:	BLOCK	1		;BYTE POINTER
CMDBUF:	BLOCK	LN$SCB		;BUFFER

; Message buffer data
MSGCTR:	BLOCK	1		;BYTE COUNT
MSGPTR:	BLOCK	1		;BYTE POINTER
MSGBUF:	BLOCK	LN$SMB		;BUFFER
MSGTYP:	BLOCK	1		;OLD CHARACTER TYPER

LOGDAT:	BLOCK	5		;LOGIN ARGUMENT BLOCK
LOGTYO:	BLOCK	1		;OLD TYPER USED BY LOG FILE I/O ROUTINES
SAVCHR:	BLOCK	1		;SAVED CHARACTER
SRVFLG:	BLOCK	1		;SPECIAL SERVER JOB FLAGS

TXTPTR:	BLOCK	1
TXTCNT:	BLOCK	1
TXTPAG:	BLOCK	1

SPID:	BLOCK	1
PDB:	BLOCK	6
BUFFER:	BLOCK	12


DEFINE	X	(NAM,LEN,TXT,FLG),<
NAM'BUF:	BLOCK	<^D<LEN>/5>+1
>
DATERR:	BLOCK	1		;DATA ERROR ON RECEIVE
DATBFS:!$DATA			;BUILD DATA BUFFERS
DATBFE:!			;END OF DATA BUFFERS


; Task independant data
T.OARG:	BLOCK	2		;SAVED OPEN ARGUMENTS
T.SEQN:	BLOCK	1		;SEQUENCE NUMBER
T.ATTN:	BLOCK	1		;TOTAL INTERRUPT(S) NEEDING ATTENTION
T.TIME:	BLOCK	1		;TIMEOUT IN SECONDS
T.WAIT:	BLOCK	1		;WORKING COPY OF COUNTDOWN TIMER
T.DISP:	BLOCK	1		;DISPATCH ADDRESS
T.CHAR:	BLOCK	1		;TEMPORARY CHARACTER STORAGE
T.IOST:	BLOCK	1		;SAVED I/O STATUS AFTER AN ERROR


; IPCF data
I.PDB:	BLOCK	6		;PACKET DESCRIPTOR BLOCK
I.PKT:	BLOCK	12		;PACKET
I.PTR:	BLOCK	1		;BYTE POINTER TO NAME
I.SRV:	BLOCK	12		;PID/NAME PACKET
I.PID:	BLOCK	1		;PID
IPCATN:	BLOCK	1		;INTERRUPT(S) NEEDING ATTENTION
IPCFLG:	BLOCK	1		;TASK INITIALIZED FLAG
IPCNAM:	BLOCK	<^D29/5>+1	;PID NAME
IPCOBR:	BLOCK	3		;OUTPUT BUFFER RING HEADER
IPCIBR:	BLOCK	3		;INPUT BUFFER RING HEADER


; ANF10 data
ANFATN:	BLOCK	1		;INTERRUPT(S) NEEDING ATTENTION
ANFFLG:	BLOCK	1		;TASK INITIALIZED FLAG
ANFOBK:	BLOCK	3		;OPEN BLOCK
ANFOBR:	BLOCK	3		;OUTPUT BUFFER RING HEADER
ANFIBR:	BLOCK	3		;INPUT BUFFER RING HEADER
ANFLEB:	BLOCK	4		;LOOKUP/ENTER BLOCK
ANFBFS:	BLOCK	1		;ADDRESS OF BUFFERS


; DECnet data
DCNATN:	BLOCK	1		;INTERRUPT(S) NEEDING ATTENTION
DCNFLG:	BLOCK	1		;TASK INITIALIZED FLAG
DCNOBR:	BLOCK	3		;OUTPUT BUFFER RING HEADER
DCNIBR:	BLOCK	3		;INPUT BUFFER RING HEADER


> ;END IFN FTSERV FROM WAY BACK

	END