Google
 

Trailing-Edge - PDP-10 Archives - tops10_703a_sys_ap115_bb-ju01b-bb - lisvax.x15
There are 6 other files named lisvax.x15 in the archive. Click here to see a list.
	TITLE LISVAX
	TWOSEG
	RELOC	400000

	SEARCH	MACSYM,MSUNV

	EXTERN	DB%VD8,MX%UNQ,MX$VAL,MXERRS,SCAN%P,UF%CLO,UF%OPE,UF%WRI,UM%GET
	EXTERN	UM%REL,UMP%GE,UMP%RE,UN%ABO,UN%ACC,UN%CLO,UN%OPE,UN%REA,UN%STA
	EXTERN	UN%WRI,US%SLE,RELASC,LOG,NODNAM,NMLDIE

    DEFINE $TRACE(S) <
	REPEAT 0,<
		PUSH P,T1
		PUSH P,T2
		PUSH P,T3
		PUSH P,T4
		PUSH P,T5
		MOVEI T1,[ASCIZ /S/]
		PUSH P,T1
		CALL LOG
		POP P,T1
		POP P,T5
		POP P,T4
		POP P,T3
		POP P,T2
		POP P,T1
		>>

;AC Definitions

	TF==0			;SCRATCH REGISTERS
	T1==1
	T2==2
	T3==3
	T4==4
	T5==5
	T6==6
	T7==7
	T10==10
	BUFPTR==11		;POINTER TO MAIL FILE HEADER
	WRDCNT==12		;NUMBER OF WORDS IN THE MESSAGE
;AC 13 AND 15 RESERVED FOR BLISS
	MSGPTR==14		;POINTER INTO MESSAGE BEING BUILT
	VARPTR==16		;POINTS TO VARIABLES AND POINTERS BUFFER
	P==17			;STACK

	FLGWRD==0		;FLAG WORD FOR PROTOCOL OPTIONS
	   USRNOT==1B0		   ;NOTIFY RECEIVING USER
	   USRBLK==1B1		   ;SEND THE MESSAGE IN BLOCKS
	   USRPRE==1B2		   ;MASTER PREFIXES SENDER'S NODE
	   USRCC==1B3		   ;THERE WILL BE A CC LIST
	   SNQTS==1B4		   ;Sender Needs QuoTeS
	UTLPTR==1		;REUSABLE POINTER
	LSTYP==2		;TO:/CC: LIST BEING PROCESSED
	MSGNUM==3		;NUMBER OF PAGES IN THE MESSAGE
	NOMORE==4		;ANY MORE DESTINATION STRINGS OR NOT
	MSGRCT==5		;NUMBER OF RECORDS IN THE MESSAGE
	IDNUM==6		;PACKET ID
	LSTADR==7 		;LAST ENTRY IN THE CURRENT ADDRESS LIST
	NXLST==10		;LAST ADDRESS REACHED IN PREVIOUS PAGE
	NXUSR==11		;IF MORE THAN ONE PAGE, POINTS TO THE
				;FIRST DESTINATION STRING
	MSGSTR==12		;ADDRESS OF BEGINNING OF THE MESSAGE
	SCRAT1==13		;SCRATCH SPACE
	SCRAT2==14
	SCRAT3==15
	SCRAT4==16
	MAIPTR==17		;POINTER TO MAIL FILE SPEC
	FAINDE==20		;POINTER TO UNKNOWN NODE ERROR MESSAGE
	VALUSR==21		;POINTER FOR USE WITH MX$VAL ROUTINE
	SUCMSGF==22		;SUCCESS MESSAGE FOR USER VALIDATION
	FAIMSG==23		;FAILURE MESSAGE FOR USER VALIDATION
	NODENM==24		;POINTS TO LOCAL NODE NAME
	BYTNUM==25		;NUMBER OF BYTES IN FAILURE MESSAGE
	LOCAL==26		;LOCAL NODE FOUND FLAG
	NODE7==27		;POINTS TO LOCAL NODE NAME
	NAMLIN==30		;NUMBER OF NAMES/LINE IN THE TO: LIST
	STABUF==31		;POINTS TO START OF BUFFER
	BUFBYT==32		;NUMBER OF BYTES IN THE BUFFER
	EOFMES==33		;END OF THE VAX MESSAGE HAS BEEN FOUND
	NUMUSR==34		;NUMBER OF RECIPIENTS
	CNNBLK==35		;CONNECT BLOCK ADDRESS
	SNDSTR==36		;FROM STRING POINTER
	NODSTR==37		;NODE NAME POINTER (7 BIT BYTES)
	USRSTR==40		;USER NAME POINTER
	ADRSPA==41		;POINTER TO RECIPIENT LIST
	WRKBUF==42		;WORKING BUFFER ADDRESS
	WRKBU2==43		;SECOND WORKING BUFFER ADDRESS
	FILNB==44		;FILE NUMBER OF MAIL FILE
	DATLNK==45		;LISVAX'S DATA LINK
	NODCNT==46		;NUMBER OF NODE NAMES IN RECIPIENT STRING
	LNKCLO==47		;LINK CLOSED DUE TO INVALID USER
	FAIMG2==50		;SECOND PART OF USER ERROR TEXT
	NODMSG==51		;POINTER TO NODE NAME ERROR TEXT
	STABLK==52		;ADDRESS OF FIRST RECIPIENT STATUS BLOCK
	STAPTR==53		;ADDRESS OF CURRENT RECIPIENT STATUS ENTRY
	FILCLO==54		;MAIL FILE CLOSED
	INVPTR==55		;ADDRESS OF CURRENT RECIPIENT STATUS BLOCK
	NUMVAR==56		;SIZE OF VARIABLE ADDRESS LIST

	VERSNM==3		;VERSION NUMBER OF PROTOCOL
	VAXTYP==7
	VAXOBJ==^D27		;VAX OBJECT TYPE
	MINSIZ==^D12		;MINIMUM SIZE FOR VERSION 3 PROTOCOL
	TOPS20==		;OPERATING SYSTEM TYPE
	OPRESW==4		;NUMBER OF WORDS FOR SLAVE OPTIONAL DATA
	OPRESB==12		;NUMBER OF BYTES FOR SLAVE OPTIONAL DATA
	LSTREC==^D897		;USED TO DETERMINE IF ROOM FOR ANOTHER RECORD
	D2==2			;BLOCK SIZES
	BY2WRD==5		;NUMBER OF 7 BIT BYTES IN A WORD
	NUMTRY==6		;TIMES TO CHECK FOR CLOSED LINK
	SLPTIM==20		;TIME TO SLEEP BETWEEN LINK STATUS CHECK
	D68==^D68
	D70==^D70
	CBKSIZ==^D64		;CONNECTION BLOCK SIZE
	PROVER==377B7		;PROTOCOL VERSION FIELD
	OSTYPE==377B31		;OPERATING SYSTEM TYPE
	MSTSND==1B0		;MASTER WISHES TO SEND MESSAGE IN BLOCKS
	SLVSND==1B1		;SLAVE WILLING TO RECEIVE MESSAGE IN BLOCKS
	MSTPRE==1B2		;MASTER WISHES TO PREFIX NODE NAME TO SEND NAME
	SLVPRE==1B3		;SLAVE WILLING TO ACCEPT NODE NAME PREFIXED
	MSTCC==1B4		;MASTER WISHES TO SEND A CC: LIST
	SLVCC==1B5		;SLAVE WILLING TO ACCEPT A CC: LIST
	SUCBIT==1B25		;SUCCESS BIT
	FAIBIT==1B24		;FAILURE BIT
	ST%CLO==1B33		;LINK WAS CLOSED
	ST%ABT==1B32		;LINK WAS ABORTED
	INVLND==1B35		;INVALID NODE IN RECIPIENT STRING
	INVLUS==1B34		;INVALID RECIPIENT NAME
	QUOTE==42		;ASCII VALUE OF QUOTE CHARACTER
	MAXSND==^D100		;MAXIMUM NUMBER OF RECIPIENTS
	MAXNUM==774		;MAXIMUM SIZE OF ERROR BLOCK
	OPDEF	PJRST	[JUMPA 17,]
	DEFINE TOPS10 <IFN FTUUOS,>
	DEFINE TOPS20 <IFN FTJSYS,>
	FTUUOS==-1		;-1 IF TOPS10 ELSE 0
	FTJSYS==0 		;-1 IF TOPS20 ELSE 0
	.DECNT==1		;Decnet listener's id
TOPS10<	.DCX11=13>
TOPS10<	IP.JAC==1B0>
TOPS10< EXTERN	GETDAT>
TOPS20< SEARCH	MONSYM>
	SALL

;ALLOCATE BUFFER SPACES

LISVAX::$TRACE	<At LISVAX...>
	CALL	GETBUF

;SET UP THE ERROR MESSAGES

	CALL	SETMSG

;DETERMINE THE PROTOCOL VERSION BEING USED AND MAKE THE CONNECTION

LISNXT: $TRACE <At LISNXT...>
	CALL	CONECT


;CREATE AND OPEN THE UNIQUE NAME MAIL FILE.

	CALL	MAIOPN		;OPEN THE MAIL FILE
	JRST	[ $TRACE <Error opening the mail file>
		  CALL FORDIS	  ;AN ERROR OCCURRED, ABORT THE CONNECTION
		  CALL CLSFIL	  ;Release the message file
		  CALL RELMAI	  ;RELEASE SPACE FOR THE MAIL FILE SPEC
		  JRST LISNXT ]	  ;TRY AGAIN
;BUILD THE SENDER RECORD

	CALL	SNDREC		;BUILD THE SENDER RECORD
	JRST	[ $TRACE <Error building the sender record>
		  CALL FORDIS	  ;AN ERROR OCCURRED, ABORT THE CONNECTION
		  CALL CLSFIL	  ;Release the message file
		  CALL RELMAI	  ;RELEASE SPACE FOR THE MAIL FILE SPEC
	       	  JRST LISNXT ]	  ;TRY AGAIN

;BUILD THE DATE AND FROM FIELDS FOR THE MAIL FILE

	CALL	MFHEAD		;BUILD THE FIRST PART OF THE MAIL FILE HEADER

;COMPLETE AND SEND THE MAIL MESSAGE

	CALL	DSTREC		;FINISH THE MESSAGE AND SEND TO MX
	JRST	[ $TRACE <Error return from DSTREC>
		  CALL FORDIS	  ;NO, FORCE A DISCONNECT
		  SKIPN FILCLO(VARPTR) ;SKIP IF MESSAGE FILE IS ALREADY CLOSED
		  CALL CLSFIL	  ;RELEASE THE MESSAGE FILE
		  CALL RELMAI	  ;RELEASE SPACE FOR THE MAIL FILE SPEC
		  CALL RLSEPG	  ;RELEASE ANY ERROR BLOCK PAGES
		  JRST LISNXT ]	  ;WAIT FOR THE NEXT VAX CALL

;DISCONNECT

	CALL	DISCON		;WAIT FOR THE DISCONNECT
	CALL	 RELMAI		;RELEASE SPACE FOR THE MAIL FILE SPEC
	JRST	LISNXT		;GO FOR THE NEXT CONNECTION

SUBTTL GETBUF	GET BUFFERS

;GET SPACE FOR LIST OF ADDRESSES AND POINTERS

GETBUF: $TRACE <At GETBUF...>
	PUSH	P,[NUMVAR]	;GET SPACE FOR THE ADDRESS LIST
	CALL	UM%GET		;DO IT
	ADJSP	P,-1		;RESET THE STACK
	JUMPLE	T1,BUFERR	;AN ERROR OCCURRED
	MOVE	VARPTR,T1	;SAVE THE ADDRESS OF THE LIST

;GET SPACE FOR THE CONNECT BLOCK

	PUSH	P,[CBKSIZ]	;SIZE OF THE CONNECTION BLOCK
	CALL	UM%GET		;GET THE SPACE
	ADJSP	P,-1		;ADJUST THE POINTER
	JUMPLE	T1,BUFERR	;ERROR, HALT
	MOVEM	T1,CNNBLK(VARPTR) ;SAVE THE ADDRESS FOR LATER

;ALLOCATE SPACE FOR USE WITH MX$VAL

	PUSH	P,[^D60]	;THE AMOUNT OF WORDS
	CALL	UM%GET		;GET THEM
	ADJSP	P,-1		;RESET THE STACK
	JUMPLE	T1,BUFERR	;AN ERROR OCCURRED
	HRLI	T1,[POINT 7]	;MAKE INTO A POINTER
	MOVEM	T1,VALUSR(VARPTR) ;SAVE FOR LATER

;ALLOCATE A PAGE FOR MESSAGE TO MX

	CALL	UMP%GET		;GET A PAGE
	JUMPL	T1,BUFERR	;AN ERROR OCCURRED, HALT
	LSH	T1,^D9		;CHANGE PAGE NUMBER TO AN ADDRESS
	MOVEM	T1,MSGSTR(VARPTR) ;ADDRESS OF START OF THE MESSAGE

;ALLOCATE A PAGE FOR INVALID RECIPIENTS

	CALL	UMP%GET		;GET A PAGE
	JUMPL	T1,BUFERR	;AN ERROR OCCURRED, HALT
	LSH	T1,^D9		;CHANGE PAGE NUMBER TO AN ADDRESS
	MOVEM	T1,STABLK(VARPTR) ;ADDRESS OF START OF INVALID RECIPIENT BUFFER

;GET SPACE FOR BUILDING THE MAIL FILE HEADER (DATE, FROM, TO, MAILED TO FIELDS)

	CALL	UMP%GET		;GET A PAGE
	JUMPL	T1,BUFERR	;AN ERROR OCCURRED, HALT
	LSH	T1,^D9		;CHANGE PAGE NUMBER TO AN ADDRESS
	MOVE	BUFPTR,T1	;MAKE INTO
	HRLI	BUFPTR,(POINT 7)  ;A POINTER
	MOVEM	BUFPTR,STABUF(VARPTR) ;SAVE START FOR WRITE TO MAIL FILE

;ALLOCATE SPACE FOR THE FROM STRING

	PUSH	P,[D70]			;AMOUNT OF SPACE NEEDED
	CALL	UM%GET			;GET THE SPACE
	ADJSP	P,-1			;RESET THE STACK
	JUMPLE	T1,BUFERR		;AN ERROR OCCURRED
	HRLI	T1,(POINT 8)		;MAKE A POINTER
	MOVEM	T1,SNDSTR(VARPTR)	;SAVE FOR LATER

;ALLOCATE SPACE FOR THE NODE NAME AND USER NAME

	PUSH	P,[D2]			;TWO WORDS FOR THE NODE NAME
	CALL	UM%GET			;GET THEM
	ADJSP	P,-1			;RESET THE STACK
	JUMPLE	T1,BUFERR		;AN ERROR OCCURRED
	HRLI	T1,(POINT 7)		;MAKE IT INTO A POINTER
	MOVEM	T1,NODSTR(VARPTR)	;SAVE FOR LATER

	PUSH	P,[D68]			;SPACE FOR THE USER NAME
	CALL	UM%GET			;GET THEM
	ADJSP	P,-1			;RESET THE STACK
	JUMPLE	T1,BUFERR		;AN ERROR OCCURRED, HALT
	HRLI	T1,(POINT 7)		;MAKE IT INTO A POINTER
	MOVEM	T1,USRSTR(VARPTR)	;SAVE FOR LATER

;ALLOCATE SPACE FOR THE RECIPIENT BUFFER

	PUSH	P,[^D100]		;GET ROOM FOR THE RECIPIENT
	CALL	UM%GET			;DO IT
	ADJSP	P,-1			;RESET THE STACK POINTER
	JUMPLE	T1,BUFERR		;ERROR, HALT
	HRLI	T1,(POINT 8)		;MAKE IT INTO A POINTER
	MOVEM	T1,ADRSPA(VARPTR)	;SAVE FOR LATER

;ALLOCATE SPACE FOR A WORKING BUFFER

	PUSH	P,[^D100]		;THE NUMBER OF WORDS TO GET
	CALL	UM%GET			;GET THEM
	ADJSP	P,-1			;RESET THE STACK
	JUMPLE	T1,BUFERR		;AN ERROR OCCURRED, HALT
	MOVEM	T1,WRKBUF(VARPTR)	;SAVE FOR LATER

;ALLOCATE SPACE FOR A SECOND WORKING BUFFER

	PUSH	P,[^D100]		;THE NUMBER OF WORDS TO GET
	CALL	UM%GET			;GET THEM
	ADJSP	P,-1			;RESET THE STACK
	JUMPLE	T1,BUFERR		;AN ERROR OCCURRED, HALT
	MOVEM	T1,WRKBU2(VARPTR)	;SAVE FOR LATER
	RET				;RETURN

BUFERR:	PUSH	P,[POINT 7,[ASCIZ /No memory available at BUFERR:(LISVAX)/]]
	PUSHJ	P,NMLDIE		;NO MEMORY AVAILABLE, HALT

SUBTTL	SETMSG - SET UP THE ERROR MESSAGES


;SET UP THE SUCCESS/FAIL MESSAGES

SETMSG: $TRACE <At SETMSG...>
	SETZ	T2,		;ZERO FLAG WORD
	TLO	T2,SUCBIT	;SET THE SUCCESS BIT
	MOVEM	T2,SUCMSG(VARPTR) ;SAVE FOR LATER

	SETZ	T2,		;ZERO THE FLAG WORD
	TLO	T2,FAIBIT	;SET THE FAILURE BIT
	MOVEM	T2,FAIMSG(VARPTR) ;SAVE FOR LATER

	MOVEI	T1,ERMSG3	;ADDRESS OF INVALID NODE NAME TEXT
	HRLI	T1,(POINT 8)	;MAKE INTO A POINTER
	MOVEM	T1,NODMSG(VARPTR) ;SAVE FOR LATER

;MAKE A POINTER TO THE LOCAL NODE NAME TO BE USED IN ERROR MESSAGES AND FOR
;TO: LIST PROCESSING

	MOVEI	T4,NODNAM	;ADDRESS OF THE LOCAL NODE NAME ASCIZ STRING
	HRLI	T4,(POINT 7)	;MAKE INTO A POINTER
	MOVEM	T4,NODE7(VARPTR) ;SAVE FOR LATER
	RET

ERMSG1:	BYTE(8)"%","N","e","t","w","o","r","k"," ","M","a","i","l"," ","E","r"
	BYTE(8)"r","o","r",":"," ","N","o"," ","s","u","c","h"," ","U","s","e"
	BYTE(8)"r"," ","A","t"," ","N","o","d","e"," "

ERMSG3:	BYTE(8)"%","N","e","t","w","o","r","k"," ","M","a","i","l"," ","E","r"
	BYTE(8)"r","o","r"," ","N","o"," ","S","u","c","h"," ","N","o","d","e"
	BYTE(8)" "

SUBTTL	CONECT	DETERMINE THE PROTOCOL AND MAKE THE CONNECTION

;FILL IN THE CONNECT BLOCK

CONECT:	MOVE	T1,CNNBLK(VARPTR) ;GET ADDRESS OF THE DATA BLOCK

	SETZM	0(T1)			;ZERO THE FIRST WORD
	HRLI	T2,0(T1)		;SOURCE WORD
	HRRI	T2,1(T1)		;DESTINATION WORD
	BLT	T2,CBKSIZ-1(T1)		;ZERO THE REST OF THE BLOCK
	MOVX	T2,VAXOBJ		;GET THE OBJECT TYPE
	MOVEM	T2,2(T1)		;AND STORE IT
	PUSH	P,[1]			;CONNECT TYPE 1, TARGET
	PUSH	P,T1			;ADDRESS OF THE CONNECTION BLOCK
	PUSH	P,[0]			;REQUIRED BY UN%OPE
	PUSH	P,[0]			;REQUIRED BY UN%OPE
	PUSH	P,[0]			;REQUIRED BY UN%OPE
	CALL	UN%OPEN			;OPEN AND BLOCK FOR INITIATION
	ADJSP	P,-5			;RESET THE STACK
	SKIPG	T1			;OBTAINED A DATA LINK NUMBER?
	JRST	[ PUSH P,[^D300]	  ;ERROR, SLEEP FOR AWHILE
		  CALL US%SLE
		  ADJSP P,-1		  ;RESET THE STACK
		  JRST CONECT ]		  ;TRY AGAIN
	MOVEM	T1,DATLNK(VARPTR)	;SAVE THE DATA LINK NUMBER

;SET UP TO ACCEPT THE CONNECTION

	SETZM	FLGWRD(VARPTR)	;ASSUME VERSION "0.0"
	JRST	VERO		;FOR NOW, VERSION "0.0"
REPEAT 0,< MOVE	T4,-1(P)	;ANY OPTIONAL DATA SENT
	JUMPE	T4,VER0		;NO, SO VERSION "0.0"
	HRRZ	T5,-2(P)	;GET THE ADDRESS OF THE DATA
	LOAD	T2,PROVER,0(T5)	;GET THE VERSION NUMBER
	CAIE	T2,VERSNM	;IS IT THE EXPECTED PROTOCOL VERSION
	JRST	VER0		;NO, SO ASSUME VERSION "0.0"
	LOAD	T2,OSTYPE,0(T5)	;GET THE TYPE OF OPERATING SYSTEM
	CAIE	T2,VAXTYP	;FROM A VAX
	JRST	VER0		;NO, SO ASSUME VERSION "0.0"
	CAIGE	T4,MINSIZ	;ARE PROTOCOL BYTES PRESENT?
	JRST	VER0		;NO, SO ASSUME VERSION "0.0"

;PROTOCOL VERSION 3.0 BEING USED, CHECK THE OPTIONS

	PUSH	P,[OPRESW]	;ALLOCATE SPACE FOR RESPONSE OPTIONAL DATA
	CALL	UM%GET		;DO IT
	ADJSP	P,-1		;ADJUST THE STACK
	JUMPLE	T1,R		;AN ERROR OCCURRED
	MOVEM	T1,SCRAT1(VARPTR) ;SAVE FOR THE BUFFER RELEASE
	SETZM	0(T1)		;ZERO THE FIRST WORD
	SETZM	1(T1)		;AND THE NEXT

	MOVEI	T2,VERSNM	;GET OUR PROTOCOL VERSION
	STOR	T2,PROVER,0(T1)	;AND STORE IT
	MOVEI	T2,TOPS20	;GET OUR OPERATING SYSTEM TYPE
	STOR	T2,OSTYPE,0(T1)	;AND STORE IT

	SETZM	T2		;PREPARE FOR FLAG WORD
	MOVE	T3,1(T5)	;GET THE MASTER OPTIONS WORD
	TXNE	T3,USRNOT	;USER TO BE NOTIFIED?
	TXO	T2,USRNOT	;YES, SET THE FLAG BIT

	MOVE	T3,2(T5)	;GET THE MASTER MODE WORD
	SETZM	T4		;PREPARE FOR THE SLAVE MODE WORD
	TXNE	T3,MSTPRE	;MASTER TO PREFIX NODE NAME TO SENDER NAME
	TXO	T4,SLVPRE	;YES, SET THE SLAVE MODE WORD
	TXNE	T3,MSTPRE	;MASTER TO PREFIX NODE NAME TO SENDER NAME
	TXO	T2,USRPRE	;YES, SET THE FLAG BIT
	TXNE	T3,MSTCC	;MASTER TO SEND A CC: LIST
	TXO	T4,SLVCC	;YES, SET THE SLAVE MODE WORD
	TXNE	T3,MSTCC	;MASTER TO SEND A CC: LIST
	TXO	T2,USRCC	;YES, SET THE FLAG BIT
	MOVEM	T4,2(T1)	;STORE IN SLAVE MODE WORD
	MOVEM	T2,FLGWRD(VARPTR) ;STORE IN THE FLAG WORD

;ACCEPT THE CONNECTION

	PUSH	P,DATLNK(VARPTR) ;THE DATA LINK IDENTIFIER
	PUSH	P,[OPRESW]	;NUMBER OF BYTES
	HRLI	T1,(POINT 8)	;MAKE IT A POINTER TO THE OPTIONAL DATA
	PUSH	P,T1		;PLACE ON THE STACK
	CALL	UN%ACC		;ACCEPT THE CONNECTION
	ADJSP	P,-3		;RESET THE STACK

	HRRZ	T1,SCRAT1(VARPTR) ;ADDRESS OF BUFFER TO BE RELEASED
	PUSH	P,T1		;PASS AS AN ARGUMENT
	PUSH	P,[OPRESW]	;NUMBER OF WORDS TO BE RELEASED
	CALL	UM%REL		;RELEASE THE BUFFER
	ADJSP	P,-2		;RESET THE STACK
	TRNN	T1,1		;AN ERROR OCCURRED?
	RET			;YES
	RETSKP >		;NO

;USING VERSION "0.0"

VERO:	$TRACE <At VERO...>
	PUSH	P,DATLNK(VARPTR) ;DATA LINK NUMBER
	PUSH	P,[0]		;NO OPTIONAL DATA
	PUSH	P,[0]		;NO OPTIONAL DATA
	CALL	UN%ACC		;ACCEPT THE CONNECTION
	ADJSP	P,-3		;RESTORE THE STACK
	TRNN	T1,1		;O.K.?
	SKIPA			;NO, TRY AGAIN
	RET			;YES
	PUSH	P,[^D60]	;AN ERROR, SLEEP FOR AWHILE
	CALL	US%SLE
	ADJSP 	P,-1		;RESET THE STACK
	JRST	VERO		;TRY AGAIN

SUBTTL	MAIOPN	GET THE MAIL FILE NAME AND OPEN THE MAIL FILE

;GET THE MAIL FILE NAME

MAIOPN:	$TRACE <At MAIOPN...>
	CALL	MX%UNQ 			;GET THE FILE SPEC
	HRLI	T1,(POINT 7)		;MAKE INTO A POINTER
	MOVEM	T1,MAIPTR(VARPTR)	;SAVE FOR LATER

;OPEN THE MAIL FILE

	PUSH	P,T1			;POINTER TO FILE SPEC
	PUSH	P,[2]			;WRITE ACCESS
	PUSH	P,[0]			;NO ERROR BUFFER
	CALL	UF%OPE			;OPEN THE MAIL FILE
	ADJSP	P,-3			;RESTORE THE STACK
	JUMPLE	T1,R			;AN ERROR OCCURRED
	MOVEM	T1,FILNB(VARPTR)	;SAVE THE FILE NUMBER FOR LATER
	RETSKP				;AND RETURN TRUE

SUBTTL	SNDREC - CREATE THE SENDER RECORD

SNDREC: $TRACE <At SNDREC...>
	MOVE	MSGPTR,MSGSTR(VARPTR)	;ADDRESS OF START OF MESSAGE
	SETZM	MSGRCT(VARPTR)		;NO RECORDS YET
	ADDI	MSGPTR,.HDRSZ		;SKIP THE HEADER RECORD FOR NOW
	AOS	T4,MSGRCT(VARPTR)	;INCREMENT THE NUMBER OF RECORDS
	MOVEM	T4,.RECNM(MSGPTR)	;STORE IT
	MOVEI	T4,.SENDR		;GET THE RECORD TYPE
	MOVEM	T4,.RECTY(MSGPTR)	;STORE IT
	MOVEI	WRDCNT,.HDRSZ		;NUMBER OF WORDS = RECORD HEADER SIZE

;GET THE FROM STRING

	PUSH	P,DATLNK(VARPTR)	;DATA LINK NUMBER
	PUSH	P,[^D280]		;MAXIMUM LENGTH OF THE STRING
	MOVE	T7,SNDSTR(VARPTR)	;POINT TO THE FROM STRING
	PUSH	P,T7			;PASS AS AN ARGUMENT
	SETZM	0(T7)			;ZERO START OF BUFFER
	HRLI	T4,0(T7)		;PREPARE FOR THE BLT
	HRRI	T4,1(T7)
	BLT	T4,^D69(T7)		;ZERO OUT THE BUFFER
	CALL	UN%REA			;READ THE STRING
	ADJSP	P,-3			;RESET THE STACK
	JUMPL	T1,R			;AN ERROR OCCURRED, RETURN FALSE

;GO THROUGH THE SENDER STRING AND SET POINTERS TO LAST NODE NAME AND THE
;USER NAME

	MOVE	T1,T7			;ASSUME SENDER NAME
	SETZ	T2,			;ASSUME NO NODE NAME
	SETZ	T4,			;ASSUME NO QUOTES
	SETZM	SCRAT3(VARPTR)		;ASSUME NO PERSONAL NAME
	MOVE	T10,T7			;KEEP T7 FOR ACTUAL TRANSFER

;**;[302] REPLACE 2 LINES WITH 1 AT GOTRU0
;**;[302] ADD 1 LINE AT GOTRU+5
;**;[302] REPLACE 1 LINE AT GOTRU+7
GOTRU0:	SETZ	T6,			;[302] INITIALIZE THE BYTE COUNT
	CALL	SKIPQT			;DONT PARSE WITHIN A QUOTED STRING
GOTRU:	  ILDB	T3,T10			;GET THE NEXT BYTE FROM SENDER STRING
	CAIN	T3," "			;END OF THE SENDER NAME?
	JRST	FNDPER			;YES, CHECK FOR PERSONAL NAME
	CAIN	T3,0			;END OF THE SENDER NAME?
	JRST	TRANSN			;YES, COPY SENDER NAME TO SENDER RECORD
	AOS	T6			;[302] INCREMENT THE BYTE COUNT
	TXNE	T4,SNQTS		;HAVE I SEEN ANY SPECIAL CHARACTERS?
	JRST	GOTRU			;[302] YES, SKIP THESE TESTS
	CAIN	T3,"("			;IS IT A SPECIAL CHARACTER?
	JRST	NEEDQT			;YES.  FLAG IT.
	CAIN	T3,")"
	JRST	NEEDQT
	CAIN	T3,"<"
	JRST	NEEDQT
	CAIN	T3,">"
	JRST	NEEDQT
	CAIN	T3,"@"
	JRST	NEEDQT
	CAIN	T3,","
	JRST	NEEDQT
	CAIN	T3,";"
	JRST	NEEDQT
	CAIN	T3,"\"
	JRST	NEEDQT
	CAIN	T3,QUOTE
	JRST	NEEDQT
	CAIN	T3,"["
	JRST	NEEDQT
	CAIN	T3,"]"
	JRST	NEEDQT
;**;[302]REMOVE SYMBOL GOTRU1.  NO LONGER REFERENCED
	CAIE	T3,":"			;[302] END OF THIS NODE NAME?
	JRST	GOTRU			;NO, GET THE NEXT CHARACTER
	IBP	T10			;POINT TO NEXT NODE OR SENDER NAME
	MOVE	T2,T1			;MAKE USER POINTER THE NODE POINTER
	MOVE	T1,T10			;THE NEW USER POINTER
	JRST	GOTRU0			;CHECK FOR THE NEXT NAME

;**;[302] ADD 1 LINE AT NEEDQT+1 AND UPDATE COMMENT
NEEDQT:	TXO	T4,SNQTS		;[302] SET "SENDER NEEDS QUOTES" BIT
	AOS	T6			;[302] INCREMENT THE BYTE COUNT
	JRST	GOTRU			;CONTINUE

;**;[302] REWRITE SKIPQT
; SKIPQT - SKIPS PAST QUOTED STRING IF PRESENT
; CALLING SEQUENCE
; 	SETZ T6				;CLEAR THE COUNT
;	MOVE T10,POINTER		;PUT THE POINTER IN T10
;	CALL SKIPQT			;DO IT
;LOOP:	ILDB T3,T10			;SCAN NON-QUOTED USERS
;
; REGISTERS / PARAMETERS
;	T3  - CONTAINS THE LAST CHARACTER
;	T4  - WILL HAVE SNQTS SET TO ONE IF NO TRAILING QUOTE WAS SEEN
;	T6  - THE COUNT OF THE NUMBER OF BYTES (INCLUDING QUOTES)
;	T10 - THE ILDB BYTE POINTER TO THE STRING
;
; RETURN: SKIP ALWAYS

SKIPQT: ILDB	T3,T10			;[302] GET THE NEXT CHARACTER
	CAIE	T3,QUOTE		;[302] IS IT A QUOTE?
	RETSKP				;[302] NO

SKLOOP:	AOS	T6			;[302] YES, INCREMENT THE COUNT
	ILDB	T3,T10			;[302] GET NEXT CHARACTER
	CAIN	T3,QUOTE		;[302] IS IT A QUOTE?
	JRST	SKIPDN			;[302] YES, FINISH...
	JUMPN	T3,SKLOOP		;[302] NOT A QUOTE.  IS IT A NULL?
					;[302] HERE IF NO TRAILING QUOTE, SO
	MOVNI	T3,1			;[302] BACK THE POINTER UP. -1 INTO T3
	ADJBP	T3,T10			;[302] T3 NOW HAS THE BACKED UP POINTER
	MOVE	T10,T3			;[302] STORE THE UPDATED POINTER IN T10
        LDB     T3,T10			;[302] PUT THE LAST CHARACTER IN T3
	TXO	T4,SNQTS		;[302] SET THE SENDER NEEDS QUOTES BIT
	RETSKP				;[302] ALL DONE

SKIPDN:	ILDB	T3,T10			;[302] POINT PAST THE QUOTE
	AOS	T6			;[302] INCREMENT THE COUNT
	RETSKP				;[302] RETURN

;DETERMINE IF THERE IS A PERSONAL NAME

FNDPER:	ILDB	T3,T10			;GET THE NEXT CHARACTER
	CAIN	T3,0			;END OF THE SENDER NAME
	JRST	TRANSN			;YES, NO PERSONAL NAME FOUND
	CAIE	T3,QUOTE		;START OF THE PERSONAL NAME?
	JRST	FNDPER			;NO, CHECK THE NEXT CHARACTER
	MOVEM	T10,SCRAT3(VARPTR)	;SAVE POINTER TO PERSONAL NAME

;COPY SENDER NAME TO THE SENDER RECORD
;**;[302] ADD 1 LINE AT TRANSN+3
;**;[302] REPLACE 7 LINES WITH 2 AT TRANS2+1
TRANSN:	MOVEI	T5,.RECTX(MSGPTR)	;SENDER NAME FIELD IN SENDER RECORD
	HRLI	T5,(POINT 7)		;MAKE IT A POINTER
	MOVEI	T3,QUOTE		;PUT A QUOTE IN T3
	PUSH	P,T6			;[302] SAVE THE BYTE COUNT
	TXNN	T4,SNQTS		;SKIP IF QUOTES ARE NEEDED
TRANS2:	ILDB	T3,T1			;GET THE NEXT CHARACTER
	IDPB	T3,T5			;[302] PLACE IN THE SENDER RECORD
	SOJG	T6,TRANS2		;[302] LOOP UNTIL DONE

;COPY OVER TO THE SENDER RECORD THE NODE NAME FOUND, IF THERE IS ONE
;**;[302] ADD 1 LINE AT TRSNOD AND AT TRSNOD+4

TRSNOD:	POP	P,T6			;[302]RESTORE THE BYTE COUNT
	TXNN	T4,SNQTS		;SKIP IF SENDER NEEDS QUOTES
	JRST	TRSNO1			;NO...
	MOVEI	T3,QUOTE		;PICK UP A QUOTE
	IDPB	T3,T5			;WRITE THE CLOSE-QUOTE IN THE SNDER REC
	AOS	T6			;[302] INCLUDE THE END-QUOTE IN COUNT
TRSNO1:	SETZ	T4,			;DONE WITH T4
	MOVEI	T3,"@"			;FIRST, PICK UP AN "AT" SIGN
	IDPB	T3,T5			;PLACE IN THE SENDER RECORD
	AOS	T6			;INCREMENT THE BYTE COUNT
	JUMPE	T2,NONODE		;JUMP IF NO NODE NAME WAS FOUND
TRSNO2:	ILDB	T3,T2			;GET THE NEXT NODE NAME CHARACTER
	CAIN	T3,":"			;FOUND THE END?
	JRST	[ MOVEI T3,0		  ;YES, MAKE IT ASCIZ
		  IDPB T3,T5		  ;PLACE IN SENDER RECORD
		  AOS T6		  ;INCREMENT THE BYTE COUNT
		  JRST NUMWRD ]		  ;FIND THE SENDER RECORD SIZE
	IDPB	T3,T5			;PLACE IN SENDER RECORD
	AOS	T6			;INCREMENT THE CHARACTER COUNT
	JRST	TRSNO2			;GET THE NEXT CHARACTER

;NO NODE NAME IN SENDER STRING. USE THE ONE FROM MX'S DATA BLOCK

NONODE:	MOVE	T7,CNNBLK(VARPTR)	;GET ADDRESS OF THE DATA BLOCK
	ADDI	T7,20			;NODE NAME
	HRLI	T7,(POINT 8)		;MAKE INTO A POINTER
	IBP	T7			;SKIP OVER TO THE NODE NAME
	IBP	T7
	IBP	T7
NONOD2:	ILDB	T1,T7			;GET THE NEXT CHARACTER
	AOS	T6			;INCREMENT THE BYTE COUNT
	IDPB	T1,T5			;PLACE IN THE SENDER RECORD
	CAIE	T1,0			;FINISH?
	JRST	NONOD2			;NO, GET THE NEXT CHARACTER

;FIND THE NUMBER OF WORDS IN THIS RECORD

NUMWRD:	IDIVI	T6,BY2WRD		;FIND THE NUMBER OF WORDS
	SKIPE	T7			;A PARTIAL WORD?
	AOS	T6			;YES, COUNT AS A FULL WORD
	ADDI	T6,.RECHS		;ADD THE RECORD HEADER SIZE
	MOVEM	T6,.RECLN(MSGPTR)	;STORE THE RECORD LENGTH
	MOVEM	MSGPTR,SCRAT4(VARPTR)	;SAVE FOR BUILDING MAIL FILE HEADER
	ADD	MSGPTR,T6		;POINT MSGPTR TO THE NEXT RECORD
	ADD	WRDCNT,T6		;NUMBER OF WORDS IN THIS MESSAGE
	RETSKP				;AND RETURN SUCCESSFULLY

SUBTTL	MFHEAD	BUILD THE DATE AND FROM FIELDS FOR MAIL FILE

;FIRST THE DATE FIELD

MFHEAD:	MOVE	BUFPTR,STABUF(VARPTR)	;POINT TO THE START OF THE BUFFER
	MOVEI	T2,[ASCIZ /Date: /]	;THE FIRST PART OF THE DATE LINE
	HRLI	T2,(POINT 7)		;MAKE INTO A POINTER
	SETZM	BUFBYT(VARPTR)		;NUMBER OF BYTES READ SO FAR
DATELP:	ILDB	T3,T2			;GET THE NEXT BYTE
	CAIN	T3,0			;END OF THE STRING?
	JRST	DATE			;YES, GET THE DATE
	IDPB	T3,BUFPTR		;PLACE BYTE INTO THE BUFFER
	AOS	BUFBYT(VARPTR)		;INCREMENT THE BYTE COUNT
	JRST	DATELP			;READ THE NEXT BYTE

DATE:
TOPS20<	MOVE	T1,BUFPTR		;WHERE TO PLACE THE DATE AND TIME
	SETO	T2,			;CURRENT DATE AND TIME
	MOVSI	T3,(OT%4YR!OT%SPA!OT%NCO!OT%NSC%!OT%SCL!OT%TMZ)	;FORMAT OPTIONS
	ODTIM%
	ERJMP	.+1			;SHOULD NOT HAPPEN
>
TOPS10<	PUSH	P,BUFPTR		;WHERE TO PLACE THE DATE AND TIME
	CALL	GETDAT			;PICK UP THE DATE AND TIME
	ADJSP	P,-1>			;RESET THE STACK

;CALCULATE THE NUMBER OF BYTES IN THE DATE FIELD

BYTCNT:	IBP	BUFPTR			;INCREMENT THE ORIGINAL BUFFER POINTER
	AOS	BUFBYT(VARPTR)		;INCREMENT THE BYTE COUNT
	CAMN	BUFPTR,T1		;EQUAL THE CURRENT BUFFER POINTER?
	JRST	MFHEA2			;YES, CONTINUE
	JRST	BYTCNT			;CHECK AGAIN

;NOW THE FROM FIELD

MFHEA2:	MOVEI	T2,[ASCIZ/
From: /]				;THE FIRST PART OF THE FROM: LINE
	HRLI	T2,(POINT 7)		;MAKE INTO A POINTER
FROMLP:	ILDB	T3,T2			;GET THE NEXT BYTE
	CAIN	T3,0			;END OF THE STRING?
	JRST	SNDCPY			;YES, COPY THE SENDER'S NAME
	IDPB	T3,BUFPTR		;DEPOSIT THE BYTE IN THE BUFFER
	AOS	BUFBYT(VARPTR)		;INCREMENT THE BYTE COUNT
	JRST	FROMLP			;GET THE NEXT BYTE

SNDCPY:	SKIPN	T5,SCRAT3(VARPTR)	;A PERSONAL NAME PRESENT?
	JRST	SNDCP2			;NO, GET THE USER NAME
	MOVEI	T1,QUOTE		;PICK UP A QUOTE CHARACTER
	IDPB	T1,BUFPTR		;PLACE IN THE BUFFER
	AOS	BUFBYT(VARPTR)		;INCREMENT THE BYTE COUNT
TRSPE2:	ILDB	T1,T5			;GET THE NEXT CHARACTER
	CAIN	T1,QUOTE		;POSSIBLE END OF PERSONAL NAME?
	CALL	FINEND			;GO FIND OUT
	JUMPE	T1,FINPER		;FINISH UP THE PERSONAL NAME
	IDPB	T1,BUFPTR		;DEPOSIT THE BYTE IN THE BUFFER
	AOS	BUFBYT(VARPTR)		;INCREMENT THE BYTE COUNT
	JRST	TRSPE2			;GET THE NEXT BYTE

FINPER:	MOVEI	T1," "			;PICK UP A BLANK
	IDPB	T1,BUFPTR		;PLACE IN THE BUFFER
	MOVEI	T1,"<"			;PICK UP A <
	IDPB	T1,BUFPTR		;PLACE IN THE BUFFER
	AOS	BUFBYT(VARPTR)		;INCREMENT THE BYTE COUNT
	AOS	BUFBYT(VARPTR)		;INCREMENT THE BYTE COUNT

SNDCP2:	MOVE	T2,SCRAT4(VARPTR)	;ADDRESS OF SENDER RECORD
	ADDI	T2,.RECHS		;ADDRESS OF FROM STRING
	HRLI	T2,(POINT 7)		;POINT TO FROM STRING
SENDLP:	ILDB	T3,T2			;GET THE NEXT BYTE
	CAIN	T3,0			;END OF THE STRING?
	JRST	CHKPER			;YES, ADD A > IF PERSONAL NAME PRESENT
	IDPB	T3,BUFPTR		;DEPOSIT THE BYTE IN THE BUFFER
	AOS	BUFBYT(VARPTR)		;INCREMENT THE BYTE COUNT
	JRST	SENDLP			;GET THE NEXT BYTE

CHKPER:	JUMPE	T5,TOSETU		;SKIP THIS IS NO PERSONAL NAME PRESENT
	MOVEI	T1,">"			;PICK UP A >
	IDPB	T1,BUFPTR		;PLACE IN THE BUFFER
	AOS	BUFBYT(VARPTR)		;INCRMENT THE BYTE COUNT

;SET UP FIRST PART OF TO: LINE

TOSETU:	MOVEI	T2,[ASCIZ/
To: /]					;THE FIRST PART OF THE TO: LINE
	HRLI	T2,(POINT 7)		;MAKE INTO A POINTER
TOLP:	ILDB	T3,T2			;GET THE NEXT BYTE
	CAIN	T3,0			;END OF THE STRING?
	RET				;YES, RETURN
	IDPB	T3,BUFPTR		;DEPOSIT THE BYTE IN THE BUFFER
	AOS	BUFBYT(VARPTR)		;INCREMENT THE BYTE COUNT
	JRST	TOLP			;GET THE NEXT BYTE

;CHECK FOR END OF THE PERSONAL NAME

FINEND:	MOVE	T2,BUFPTR		;PRESERVE CURRENT BUFFER POINTER
	MOVE	T4,BUFBYT(VARPTR)	;PRESERVE CURRENT BUFFER BYTE COUNT
FINEN2:	IDPB	T1,BUFPTR		;DEPOSIT BYTE IN BUFFER
	AOS	BUFBYT(VARPTR)		;INCREMENT BYTE COUNT
	ILDB	T1,T5			;GET THE NEXT BYTE
	CAIN	T1,0			;END OF THE PERSON NAME?
	JRST	RSTPTR			;YES, RESET THE POINTER AND BYTE COUNT
	CAIN	T1,QUOTE		;ANOTHER QUOTE FOUND?
	JRST	FINEND			;YES, START OVER
	CAIN	T1," "			;A BLANK FOUND
	JRST	FINEN2			;YES, CONTINUE TO LOOK FOR END
	RET				;NO, QUOTE IS PART OF PERSONAL NAME
RSTPTR:	MOVE	BUFPTR,T2		;RESTORE THE BUFFER POINTER
	IBP	BUFPTR			;ACCOUNT FOR THE FINAL QUOTE
	AOS	T4			;ACCOUNT FOR THE FINAL QUOTE
	MOVEM	T4,BUFBYT(VARPTR)	;RESTORE THE BYTE COUNT
	RET

SUBTTL	DSTREC	COMPLETES THE MESSAGE AND SENDS IT TO MX

;DO SOME PRELIMARY SETUPS FIRST

DSTREC:	$TRACE <At DSTREC>
	SETZM	NOMORE(VARPTR)		;ZERO MEANS MESSAGE HAS MORE PAGES
	SETOM	MSGNUM(VARPTR)		;PAGE NUMBER-1 OF CURRENT MESSAGE PAGE
	SETZM	IDNUM(VARPTR)		;ID NUMBER IS ZERO FOR 1ST PAGE OF MSG
	SETZM	FILCLO(VARPTR)		;MAIL FILE HAS NOT BEEN CLOSED
	MOVEI	T1,3			;THE # OF NAMES/LINE IN THE TO: LIST
	MOVEM	T1,NAMLIN(VARPTR)	;SAVE FOR LATER
	SETZM	NUMUSR(VARPTR)		;NO RECIPIENTS YET
	MOVE	T1,STABLK(VARPTR)	;GET ADDRESS OF THE FIRST ERROR BLOCK
	MOVEM	T1,INVPTR(VARPTR)	;IT'S THE SAME AS THE CURRENT ERROR BLK
	CALL	CLRPAG			;CLEAR THE RECIPIENT STATUS BUFFER
NXTSTR:	$TRACE  <At NXTSTR...>
	CAILE	WRDCNT,LSTREC		;ROOM FOR ANOTHER RECORD
	JRST	[ CALL	SNDMSG		;NO, SO SEND OFF THE MESSAGE TO MX
	          RET 			;AN ERROR OCCURRED
		  JRST	NXTST2 ]	;PROCESS THE REMAINING RECIPIENTS
NXTST2:	PUSH	P,DATLNK(VARPTR)	;DATA LINK NUMBER
	PUSH	P,[^D400]		;MAXIMUM LENGTH OF BUFFER
	MOVE	T5,ADRSPA(VARPTR)	;GET THE BUFFER POINTER
	PUSH	P,T5			;PASS AS AN ARGUMENT
	SETZM	0(T5)			;ZERO FIRST WORD OF THE BUFFER
	HRLI	T1,0(T5)		;SET UP THE BLT
	HRRI	T1,1(T5)
	BLT	T1,^D99(T5)		;ZERO THE BUFFER
	CALL	UN%REA			;GET THE NEXT USER
	ADJSP	P,-3			;RESET THE POINTER
	JUMPL	T1,R			;AN ERROR OCCURRED
	MOVE	T5,ADRSPA(VARPTR)	;GET THE BUFFER POINTER
	ILDB	T2,T5			;GET THE FIRST BYTE
	CAIN	T1,1			;ONE BYTE FOR THIS RECIPIENT?
	CAIE	T2,0			;YES, A NULL?
	SKIPA				;ANOTHER RECIPIENT STRING
	JRST	SNDLST			;NO MORE RECIPIENTS
	AOS	NUMUSR(VARPTR)		;INCREMENT THE RECIPIENT COUNT
	MOVE	T5,ADRSPA(VARPTR)	;POINTER TO RECIPIENT STRING

;The following has been zeroed out. This code dealt with transforming
;a recipient string of the form N1::N2::...NN::USER to SMTP format,
;i.e., @N1,@N2,...NN-1:USER@NN. As it turns out, only the last node
;is needed by MX, so the original string is now transformed to USER@NN

REPEAT 0,<
NXTCHR:	SETZ	T10,			;NUMBER OF CHARACTERS IN USER NAME
	MOVE	T4,T3			;POINT TO START OF TEMPORARY STRING
NEXTCH:	ILDB	T2,T5			;GET THE NEXT CHARACTER
	CAIE	T2,":"			;FOUND A NODE?
	JRST	CHKUSR			;NO, MAYBE THE USER NAME

;A NODE HAS BEEN FOUND. IF IT IS THE FIRST NODE VALIDATE IT. IF VALID
;OR NOT THE FIRST NODE, THEN APPEND NODE NAME IN TEMPORARY BUFFER WITH
;A COMMA

	ILDB	T2,T5			;STRIP OFF THE SECOND COLON
	AOS	T2,NODCNT(VARPTR)	;INCREMENT THE NUMBER NODES FOUND
	CAIE	T2,1			;THE FIRST NODE?
	JRST	ADDCOM			;NO, ADD A COMMA

	MOVEI	T2,0			;MAKE NODE NAME INTO ASCIZ STRING
	MOVE	T7,T4			;SAVE CURRENT END OF TEMP. BUFFER
	IDPB	T2,T4			;PLACE INTO THE TEMPORARY BUFFER
	CALL	NODVAL			;VALIDATE THE FIRST NODE
	HRRES	T1			;MAKE THE RETURN CODE A FULL WORD
	JUMPGE	T1,NODEGD		;NODE IS VALID
	CALL	INVNOD			;NODE IS INVALID
	RET				;END THIS SESSION
	JRST	NXTSTR			;GET THE NEXT RECIPIENT

NODEGD:	MOVE	T4,T7			;RESET END OF TEMPORARY BUFFER
ADDCOM:	MOVEI	T2,","			;PICK UP A COMMA
	IDPB	T2,T4			;PLACE IN THE TEMPORARY BUFFER
	MOVE	T3,T4			;POINTER TO NEXT STRING COMPONENT
	JRST	NXTCHR			;GET THE NEXT CHARACTER OF RECIPIENT

;CHECK FOR USER NAME. IF FOUND VALIDATE IT. IF INVALID, GO FOR THE NEXT
;RECIPIENT; IF VALID, MAP THE TEMPORARY BUFFER INTO THE FORM USED BY
;MX

CHKUSR:	AOS	T10			;INCREMENT NUMBER OF CHARACTERS IN NAME
	CAIN	T2," "			;A USER NAME FOUND?
	JRST	VLUSER			;YES, VALIDATE IT
	CAIN	T2,0			;A USER NAME FOUND?
	JRST	VLUSER			;YES, VALIDATE IT
	IDPB	T2,T4			;NO, PLACE CHARACTER INTO TEMP. BUFFER
	JRST	NEXTCH			;GET THE NEXT CHARACTER IN USER NAME

;VALIDATE THE USER NAME

VLUSER: $TRACE <At VLUSER...>
	MOVEI	T2,0			;MAKE INTO AN ASCIZ STRING
	IDPB	T2,T4
	PUSH	P,T3			;DESTROYED BY THE CALL
	PUSH	P,T4			;DESTROYED
	PUSH	P,T5			;DESTROYED
	PUSH	P,T10			;NUMBER OF BYTES IN USER NAME
	PUSH	P,T3			;POINT TO THE USER NAME
	MOVE	T1,VALUSR(VARPTR)	;POINTER TO POBOX STRING (WE DONT NEED)
	PUSH	P,T1			;PASS AS AN ARGUMENT
	CALL	MX$VAL			;VALIDATE THE USER NAME
	ADJSP	P,-3			;RESET THE STACK
	POP	P,T5			;RESTORE
	POP	P,T4			;RESTORE
	POP	P,T3			;RESTORE
	JUMPG	T1,TELVAL		;VALID USER
	CALL	INVUSR			;INVALID USER, TELL THE VAX
	RET				;ERROR, TOO MANY INVALID USERS
	JRST	NXTSTR			;GET THE NEXT RECIPIENT

TELVAL:	$TRACE <At TELVAL...>
	CALL	VUSER			;VALID USER, TELL THE VAX
	RET				;NETWORK ERROR OCCURRED
	AOS	T1,STAPTR(VARPTR)	;INCREMENT THE RECIPIENT COUNT
	HRRZS	T1			;ISOLATE THE ADDRESS
	ANDI	T1,777			;GET THE PAGE OFFSET
	CAILE	T1,MAXNUM		;END OF THIS ERROR BLOCK PAGE?
	CALL	NXTBUF			;YES, GET ANOTHER PAGE
	MOVEM	T3,SCRAT1(VARPTR)	;POINTER TO USER NAME, FOR LOCAL TO:

	MOVE	T2,NODCNT(VARPTR)	;NUMBER OF NODES IN RECIPIENT STRING
	CAIN	T2,0			;NO NODE NAMES?
	SETOM	LOCAL(VARPTR)		;YES, SET LOCAL NODE FLAG FOR LOCAL TO:

;FINISHED THE BUILDING OF THE TEMPORTY BUFFER. NOW COPY IT TO THE RECIPIENT
;RECORD IN THE FORMAT USED BY MX

	SETZ	T7,			;NUMBER OF BYTES IN STRING SO FAR
	MOVE	T4,WRKBUF(VARPTR)	;POINT TO START OF TEMPORARY BUFFER
	HRLI	T4,(POINT 7)		;MAKE IT INTO A POINTER
	SKIPE	T10,NODCNT(VARPTR)	;NODES IN RECIPIENT STRING?
	JRST	NODFND			;YES, PICK UP THE FIRST NODE

;JUST A USER NAME IN THE RECIPIENT STRING, COPY OVER TO RECIPIENT RECORD

CPYNAM:	ILDB	T2,T4			;GET THE NEXT CHARACTER
	AOS	T7			;INCREMENT BYTE COUNT
	CAIN	T2,0			;AT THE END OF THE USER NAME?
	JRST	TRSND1			;YES, TRANSFER THE LOCAL NODE NAME
	IDPB	T2,T6			;PLACE IN THE RECORD
	JRST	CPYNAM			;NO, GET THE NEXT CHARACTER
TRSND1:	MOVEI	T2,"@"			;PICK UP AN AMPERSAND
	IDPB	T2,T6			;PLACE IN THE RECORD
	MOVE	T4,NODE7(VARPTR)	;POINT TO THE LOCAL NODE NAME
TRSND2:	ILDB	T2,T4			;GET THE NEXT NODE NAME CHARACTER
	AOS	T7			;INCREMENT THE BYTE COUNT
	IDPB	T2,T6			;PLACE BYTE IN THE RECORD
	CAIE	T2,0			;END OF THE NODE NAME?
	JRST	TRSND2			;NO, GET THE NEXT CHARACTER
	CALL	FINRCD			;YES, FINISH THE RECORD
	JRST	NXTSTR			;GET THE NEXT RECIPIENT

;AT LEAST ONE NODE NAME IN RECIPIENT STRING

NODFND:	CAIE	T10,1			;ONLY 1 NODE NAME IN RECIPIENT STRING?
	JRST	MRENOD			;NO, PROCESS DIFFERENTLY

;ONLY 1 NODE NAME IN RECIPIENT STRING

	MOVE	T3,T4			;REMEMBER START OF NODE NAME
	CALL	MOVUSR			;COPY NODE,USER TO USER@NODE
	CALL	FINRCD			;GET THE NEXT RECIPIENT STRING
	JRST	NXTSTR			;GET THE NEXT RECIPIENT

;N NODE NAMES IN RECIPIENT STRING. COPY FIRST N-1 OVER TO RECIPIENT RECORD

MRENOD:	SOS	T10			;NUMBER OF NODES - 1
SEVNOD:	MOVEI	T2,"@"			;PICK UP AN @
	IDPB	T2,T6			;PLACE IN THE RECIPIENT RECORD
	AOS	T7			;INCREMENT THE BYTE COUNT

NODMOV:	ILDB	T2,T4			;NEXT CHARACTER FROM TEMPORARY BUFFER
	CAIN	T2,","			;AND OF THIS NODE NAME?
	JRST	ENDNOD			;YES, SEE IF IT IS THE N-1TH NODE NAME
	IDPB	T2,T6			;PLACE IN RECIPIENT RECORD
	AOS	T7			;INCREMENT THE BYTE COUNT
	JRST	NODMOV			;GET THE NEXT CHARACTER

ENDNOD:	SOSE	T10			;N-1TH NODE?
	JRST	[ MOVEI T2,","		  ;NO, GET A COMMA
		  IDPB T2,T6		  ;PLACE IN THE RECORD
		  AOS T7		  ;INCREMENT THE BYTE COUNT
		  JRST	SEVNOD ]          ;GET THE NEXT NODE

;THE LAST NODE NAME HAS BEEN FOUND. MOVE THE USER NAME OVER TO THE RECIPIENT
;RECORD, FOLLOWED BY @NODE-NAME

	MOVEI	T2,":"			;PICK UP A COLON
	IDPB	T2,T6			;APPEND TO THE N-1TH NODE NAME
	AOS	T7			;INCREMENT THE BYTE COUND
	MOVE	T3,T4			;REMEMBER START OF FINAL NODE NAME
	CALL	MOVUSR			;COPY NODE,USER TO USER@NODE
	CALL	FINRCD			;GET THE NEXT RECIPIENT
	JRST	NXTSTR			;GET THE NEXT RECIPIENT

;COPY THE STRING IN THE TEMPORARY BUFFER OF THE FORM "NODE,USER" TO THE
;RECIPIENT RECORD IN THE FORM "USER@NODE"

MOVUSR:	ILDB	T2,T4			;GET  NEXT CHARACTER FROM TEMP. BUFFER
	CAIE	T2,","			;END OF THE LAST NODE NAME?
	JRST	MOVUSR			;NO, TRY AGAIN

NXTONE:	ILDB	T2,T4			;GET NEXT USER NAME CHARACTER
	CAIN	T2,0			;END OF THE USER NAME?
	JRST	LSTNOD			;YES, COPY THE FINAL NODE NAME
	IDPB	T2,T6			;PLACE CHARACTER IN RECIPIENT RECORD
	AOS	T7			;INCREMENT THE CHARTACTER COUNT
	JRST	NXTONE			;GET NEXT USER NAME CHARACTER

;COPY OVER THE FINAL NODE NAME

LSTNOD:	MOVEI	T2,"@"			;PICK UP AN @
	IDPB	T2,T6			;PLACE AFTER THE USER NAME

CPYOVR:	ILDB	T2,T3			;NEXT CHARACTER OF NODE NAME
	AOS	T7			;INCREMENT THE BYTE COUNT
	CAIN	T2,","			;END OF NODE NAME?
	JRST	FINSTR			;YES, FINISH RECIPIENT STRING IN RECORD
	IDPB	T2,T6			;NO, PLACE CHARACTER IN RECORD
	JRST	CPYOVR			;GET THE NEXT CHARACTER

FINSTR:	MOVEI	T2,0			;MAKE RECIPIENT STRING IN RECIPIENT
	IDPB	T2,T6			;RECORD INTO AN ASCIZ STRING
	RET
>; END OF SMTP FORMATTING

;FIND POINTERS TO THE NODE NAME (IF ANY) AND THE RECIPIENT NAME
;**;[302] ADD 8 LINES AT NXTCHR-1
	MOVE	T10,T5			;T10 POINTS TO THE RECIPIENT NAME
	SETZ	T7,			;ASSUME NO NODE NAME
	SETZ	T4,			;[302] CLEAR THE BYTE COUNT
	SETZ	T6,			;[302] CLEAR THE BYTE COUNT FOR SKIPQT
	CALL	SKIPQT			;[302] SKIP THE QUOTED STRING
	  JFCL				;[302] SKIPQT ALWAYS SKIPS
	EXCH	T10,T5			;[302] PUT THINGS IN THE RIGHT PLACE
        EXCH    T3,T1                   ;[302] USE T1 FOR CHAR
	EXCH	T4,T6			;[302] USE T4 FOR COUNT
	SKIPA				;[302] SKIP THE ILDB
NXTCHR:	ILDB	T1,T5			;GET THE NEXT RECIPIENT STRING BYTE
;**;[302] ADD 1 LINE AT NXTCHR+1
;**;[302] DELETE 2 LINES AT NXTCHR+3
;**;[302] ADD 1 LINE AT NXTCHR+5
	CAIE	T1," "			;[302] END OF STRING?
	CAIN	T1,0			;END OF THE STRING?
	JRST	CHKNDE			;YES, CHECK IF NODE NAME IS PRESENT
	AOS	T4			;[302] INCREMENT THE BYTE COUNT
	CAIE	T1,":"			;FOUND A NODE NAME?
	JRST	NXTCHR			;NO, GET THE NEXT CHARACTER

	IBP	T5			;SKIP OVER THE NEXT COLON
	MOVE	T7,T10			;UPDATE THE NODE NAME POINTER
	MOVE	T10,T5			;UPDATE THE RECIPIENT POINTER
	JRST	NXTCHR			;GET THE NEXT CHARACTER

;IF A NODE NAME IS PRESENT, VALIDATE IT; OTHERWISE, VALIDATE THE RECIPIENT

;**;[302] REPLACE CHKNDE+4
CHKNDE:	SKIPN	T7			;NODE NAME PRESENT?
	JRST	GETUSR			;NO, VALIDATE THE RECIPIENT
	MOVE	T6,WRKBUF(VARPTR)	;ADDRESS OF WORKING BUFFER
	HRLI	T6,(POINT 7)		;MAKE INTO A POINTER
	MOVE	T5,T6			;[302] SAVE START OF WORKING BUFFER
TRNSND:	ILDB	T1,T7			;GET THE NEXT NODE NAME CHARACTER
	CAIN	T1,":"			;END OF THE NODE NAME?
	JRST	COLFND			;YES, VALIDATE THE NODE NAME
	IDPB	T1,T5			;NO, PLACE CHARACTER IN WORKING BUFFER
	JRST	TRNSND			;GET THE NEXT CHARACTER

;THE NODE NAME HAS BEEN ISOLATED IN THE WORKING BUFFER, NOW VALIDATE IT

;**;[302]REPLACE COLFND+2
COLFND:	SETZ	T1,			;ASCIZ TERMINATION CHARACTER
	IDPB	T1,T5			;MAKE NODE NAME ASCIZ
	MOVE	T7,T6			;[302] REMEMBER START OF NODE NAME
	CALL	NODVAL			;VALIDATE THE NODE NAME
	HRRES	T1,T1			;MAKE THE RETURN CODE A FULL WORD
	JUMPGE	T1,GETUSR		;VALID NODE, MOVE RECIPIENT TO RECORD
	CALL	INVNOD			;MARK THIS RECIPIENT AS INVALID
	RET				;NETWORK ERROR OCCURRED, TERMINATE
	JRST	NXTSTR			;GET THE NEXT RECIPIENT

;PLACE THE RECIPIENT NAME IN THE RECIPIENT RECORD. IF THERE IS NO NODE
;NAME THEN VALIDATE THE RECIPIENT

;**;[302] REPLACE 1 LINE AT GETUSR
GETUSR:	PUSH	P,T4			;[302] SAVE THE BYTE COUNT
	MOVE	T6,MSGPTR		;ADDRESS OF START OF THIS RECORD
	ADDI	T6,.RECHS		;ADDRESS OF START OF USER NAME STRING
	HRLI	T6,(POINT 7)		;MAKE INTO A POINTER
	MOVE	T5,T6			;SAVE START OF RECIPIENT FIELD

;**;[302] REPLACE 7 LINES WITH 2 AT GETUS2+1
GETUS2:	ILDB	T1,T10			;GET THE NEXT RECIPIENT CHARACTER
	IDPB	T1,T6			;[302] NO, PLACE IN RECIPIENT RECORD
	SOJG	T4,GETUS2		;[302] LOOP UNTIL DONE

VALIDU:	POP	P,T4			;RESTORE THE BYTE COUNT
	MOVE	T10,T6			;SAVE RECORD POSITION FOR NODE NAME
	SETZ	T1,			;ASCIZ TERMINATION CHARACTER
	IDPB	T1,T6			;MAKE RECIPIENT NAME ASCIZ
	SKIPE	T7			;NODE NAME PRESENT?
	JRST	TELVAL			;YES, DON'T VALIDATE RECIPIENT NAME
	PUSH	P,T4			;DESTROYED BY THE CALL
	PUSH	P,T5			;DESTROYED
	PUSH	P,T4			;NUMBER OF BYTES IN USER NAME
	PUSH	P,T5			;POINT TO THE USER NAME
	MOVE	T1,VALUSR(VARPTR)	;POINTER TO POBOX STRING (WE DONT NEED)
	PUSH	P,T1			;PASS AS AN ARGUMENT
	CALL	MX$VAL			;VALIDATE THE USER NAME
	ADJSP	P,-3			;RESET THE STACK
	POP	P,T5			;RESTORE
	POP	P,T4			;RESTORE
	JUMPG	T1,TELVAL		;VALID USER
	CALL	INVUSR			;INVALID USER, TELL THE VAX
	RET				;NETWORK ERROR OCCURRED

	JRST	NXTSTR			;GET THE NEXT RECIPIENT

;The recipient is valid, Send a success message to the VAX and then finish
;building the recipient record

TELVAL:	$TRACE <At TELVAL...>
	CALL	VUSER			;VALID USER, TELL THE VAX
	RET				;NETWORK ERROR OCCURRED
	AOS	STAPTR(VARPTR)		;INCREMENT THE RECIPIENT COUNT
	MOVEI	T1,"@"			;PICK UP AN @
	IDPB	T1,T10			;PLACE IN THE RECIPIENT RECORD
	SKIPN	T7			;NODE NAME IN RECIPIENT NAME?
	MOVE	T7,NODE7(VARPTR)	;NO, USE THE LOCAL NODE NAME

TELVA2:	ILDB	T1,T7			;GET THE NEXT NODE NAME CHARACTER
	AOS	T4			;INCREMENT THE BYTE COUNT
	IDPB	T1,T10			;PLACE IN THE RECIPIENT RECORD
	CAIE	T1,0			;END OF THE NODE NAME?
	JRST	TELVA2			;NO, GET THE NEXT CHARACTER

	CALL	FINRCD			;FINISH THE RECORD
	JRST	NXTSTR			;GET THE NEXT RECIPIENT

NODVAL:	$TRACE <At NODVAL...>

	PUSH	P,T4			;NODE NAME
	PUSH	P,[1]			;LOCAL DOMAIN
	PUSH	P,[-1]			;UNKNOWN DOMAIN
	CALL	DB%VD8			;CHECK OUT THE NODE
	ADJSP	P,-3			;RESET THE STACK
	RET

SUBTTL INVNOD	 INVALID RECIPIENT DETECTED

INVNOD:	MOVX	T2,INVLND		;INVALID NODE NAME DETECTED
	SKIPA
INVUSR:	MOVX	T2,INVLUS		;INVALID RECIPIENT
	MOVE	T1,STAPTR(VARPTR)	;GET POINTER OF CURRENT ENTRY
	MOVEM	T2,0(T1)		;PLACE TYPE OF ERROR IN ENTRY
	AOS	T1			;POINT TO THE NEXT WORD IN ENTRY
	TXNN	T2,INVLND		;INVALID NODE NAME?
	JRST	INVUS2			;NO, GO UPDATE RECIPIENT STATUS ADDRESS
TRSCHR:	ILDB	T2,T7			;GET NEXT NODE CHARACTER
	IDPB	T2,T1			;PLACE IN THE BUFFER
	CAIE	T2,0			;FINISHED?
	JRST	TRSCHR			;NO, GET THE NEXT CHARACTER
	MOVE	T1,STAPTR(VARPTR)	;POINTER TO CURRENT ENTRY
	ADDI	T1,^D3			;POINT TO THE NEXT ENTRY
INVUS2:	MOVEM	T1,STAPTR(VARPTR)	;SAVE FOR THE NEXT INVALID USER
	HRRZS	T1			;ISOLATE THE ADDRESS
	ANDI	T1,777			;GET THE PAGE OFFSET
	CAILE	T1,MAXNUM		;END OF THIS PAGE?
	CALL	NXTBUF			;YES, GET ANOTHER PAGE
	CALL	VUSER			;FAKE OUT THE VAX
INVRET:	RET
	RETSKP				;RETURN TRUE


;VALID USER - TELL THE VAX

VUSER:	$TRACE <At VUSER...>
	PUSH	P,T4			;DESTROYED
	PUSH	P,T5			;DESTROYED
	PUSH	P,DATLNK(VARPTR)	;DATA LINK NUMBER
	PUSH	P,[1]			;END OF MESSAGE FLAG
	PUSH	P,[4]			;NUMBER OF BYTES IN THE MESSAGE
	MOVEI	T1,SUCMSG(VARPTR)	;MESSAGE ADDRESS
	HRLI	T1,(POINT 8)		;MAKE INTO A POINTR
	PUSH	P,T1			;PASS AS AN ARGUMENT
	CALL	UN%WRI			;DO IT
	ADJSP	P,-4			;RESET THE STACK
	POP	P,T5			;RESTORE
	POP	P,T4			;RESTORE
	JUMPLE	T1,R			;AN ERROR, RETURN FALSE
	RETSKP

;GET AN ADDITIONAL PAGE FOR THE RECIPIENT STATUS LIST

NXTBUF:	MOVE	T2,STAPTR(VARPTR)	;GET ADDRESS OF LAST ENTRY
	SETOM	0(T2)			;MARK IT AS THE LAST ENTRY
	CALL	UMP%GET			;GET A PAGE
	JUMPL	T1,[PUSH P,[POINT 7,[ASCIZ /Could not get page at NXTBUF:/]]
		    PUSHJ	P,NMLDIE]	;AN ERROR OCCURRED, HALT
	LSH	T1,^D9			;CHANGE PAGE NUMBER TO AN ADDRESS
	MOVE	T2,INVPTR(VARPTR)	;ADDRESS OF PREVIOUS PAGE
	MOVEM	T1,0(T2)		;PLACE ADDRESS OF CURRENT PAGE IN IT
	MOVEM	T1,INVPTR(VARPTR)	;PLACE IN CURRENT RECIPIENT ADDRESS PTR
	CALL	CLRPAG			;ZERO OUT THE PAGE
	RET

;CLEAR THE INVALID RECIPIENT PAGE UPON DETECTING FIRST INVALID RECIPIENT

CLRPAG:	MOVE	T1,INVPTR(VARPTR)	;GET STARTING ADDRESS OF THE BUFFER
	SETZM	0(T1)			;ZERO THE FIRST WORD
	HRLS	T1			;PLACE STARTING ADR IN CORRECT PLACE
	AOS	T1			;FORM CORRECT DESTINATION ADDRESS
	MOVE	T2,INVPTR(VARPTR)	;DON'T WANT TO USE T1 TWICE IN THE BLT
	BLT	T1,777(T2)		;ZERO THE PAGE
	MOVE	T2,INVPTR(VARPTR)	;GET ADDRESS OF THE BUFFER
	AOS	T2			;FIRST WORD IS THE LINK WORD
	HRLI	T2,(POINT 8)		;MAKE INTO A POINTER TO 1ST RECIPIENT
	MOVEM	T2,STAPTR(VARPTR)	;SAVE FOR LATER
	RET

SUBTTL FINRCD	FINISH THE RECIPIENT RECORD

FINRCD:	$TRACE <At FINRCD...>
	MOVEI	T1,.DESTN		;RECORD TYPE
	MOVEM	T1,.RECTY(MSGPTR)	;PLACE IN THE RECORD
	AOS	T1,MSGRCT(VARPTR)	;INCREMENT NUMBER OF RECORDS
	MOVEM	T1,.RECNM(MSGPTR)	;STORE IN THE RECORD

	MOVE	T7,T5			;SAVE RECIPIENT NAME FOR TO: LIST
	IDIVI	T4,BY2WRD		;FIND THE NUMBER OF WORDS IN RECORD
	SKIPE	T5			;ANY PARTIAL WORDS?
	AOS	T4			;YES, COUNT AS A FULL WORD
	ADDI	T4,.RECHS		;ADD IN THE RECORD HEADER SIZE
	MOVEM	T4,.RECLN(MSGPTR)	;PLACE IN THE RECORD
	ADDM	T4,WRDCNT		;SAVE UPDATED COUNT
	ADD	MSGPTR,T4		;POINTER TO THE NEXT RECORD

;CHECK FOR ROOM ON THIS LINE, IF ALREADY 3 NAMES START A NEW LINE

	SKIPG	NAMLIN(VARPTR)		;SPACE FOR ONE MORE?
	JRST	[ MOVE T1,[POINT 7,[ASCIZ/
    /]]
NEWLIN:		  ILDB T2,T1		;GET THE NEXT CHARACTER
		  CAIN T2,0		;THE LAST CHARACTER?
		  JRST FINLIN		;YES, UPDATE THE BYTE COUNT
		  IDPB T2,BUFPTR	;NO, PLACE IN THE BUFFER
		  JRST NEWLIN		;GET THE NEXT CHARACTER
FINLIN:		  MOVEI T2,6		;NUMBER OF NEW CHARACTERS
		  ADDM  T2,BUFBYT(VARPTR) ;UPDATE THE BYTE COUNT
		  MOVEI	T3,3		  ;NUMBER OF NAMES/LINE
		  MOVEM T3,NAMLIN(VARPTR) ;UPDATE THE COUNTER
		  JRST  COPYNM ]	  ;CONTINUE WITH THE NEXT LINE

;COPY THE NAME

COPYNM:	ILDB	T3,T7			;GET THE NEXT BYTE
	CAIN	T3,0			;END OF THE STRING?
	JRST	COMCPY			;APPEND A COMMA
	IDPB	T3,BUFPTR		;DEPOSIT THE NEXT BYTE
	AOS	BUFBYT(VARPTR)		;INCREMENT THE BYTE COUNT
	JRST	COPYNM			;GET THE NEXT BYTE

COMCPY:	MOVEM	BUFPTR,SCRAT4(VARPTR)	;REMEMBER CURRENT POSITION
	MOVEI	T2,","			;GET THE COMMA FOLLOWING THE NAME
	IDPB	T2,BUFPTR		;PLACE IN THE BUFFER
	MOVEI	T2," "			;GET A BLANK
	IDPB	T2,BUFPTR		;PLACE IN THE BUFFER
	MOVEI	T2,2			;THE NUMBER OF ADDITIONAL BYTES
	ADDM	T2,BUFBYT(VARPTR)	;UPDATE THE BYTE COUNT

;UPDATE PARAMETERS

	SOS	NAMLIN(VARPTR)		;UPDATE NAMES/LINE COUNTER
	RET

SUBTTL	SNDMSG	SEND THE MESSAGE TO MX

;SET UP THE HEADER RECORD

SNDMSG:	$TRACE <At SNDMSG...>
	AOS	T1,MSGNUM(VARPTR)	;ZERO MEANS THE FIRST PAGE OF MESSAGE
	SKIPG	T1			;IS THIS THE FIRST PAGE?
	MOVEI	T2,.POST		;YES, INDICATE SO
	SKIPE	T1			;IS THIS THE FIRST PAGE?
	MOVEI	T2,.CONT		;NO, INDICATE SO
	HRLI	T2,.DECNT		;WE'RE THE DECNET LISTENER
	MOVE	T4,MSGSTR(VARPTR)	;POINT TO BEGINNING OF THE MESSAGE
	MOVEM	T2,.PKTYP(T4)		;STORE IN THE RECORD
	MOVE	T2,IDNUM(VARPTR)	;PICK UP MESSAGE ID NUMBER
	MOVEM	T2,.PKID(T4)		;STORE IN THE RECORD
	AOS	T1			;CURRENT PAGE OF THE MESSAGE
	MOVEM	T1,.PKSEQ(T4)		;STORE IN THE RECORD
	MOVE	T1,NOMORE(VARPTR)	;PICK UP THE LAST PAGE FLAG

	MOVEI	T2,.DONE		;ASSUME THIS IS THE LAST PAGE
	SKIPN	T1			;IS IT?
	MOVE	T2,.MORE		;NO, AT LEAST ONE MORE PAGE
	MOVEM	T2,.PKSTS(T4)		;STORE IN THE RECORD
	MOVE	T2,MSGRCT(VARPTR)	;NUMBER OF RECORDS SO FAR
	SKIPE	T1			;IS THIS CORRECT?
	AOS	T2			;NO, INCLUDE THE FILE SPEC RECORD
	MOVEM	T2,.PKRCT(T4)		;PLACE IN THE RECORD

;IF THIS IS THE LAST PAGE OF THE MESSAGE, THE MAIL FILE MUST BE COMPLETED
;AND THE FILE SPEC RECORD MUST BE MADE BEFORE SENDING OFF THE FINAL PAGE

	JUMPE	T1,SNDOFF		;IF  0 THEN THERE ARE MORE PAGES
	CALL	FILSPC			;FILL IN THE FILE SPEC RECORD
	CALL	FINFIL			;COMPLETE THE MAIL FILE
	RET				;AN ERROR OCCURRED
	CALL	CLOFIL			;CLOSE THE MAIL FILE
	CALL	SNDOFF			;SEND OFF THE FINAL PAGE OF THE MSG
	RET				;AN ERROR OCCURRED
	SETOM	FILCLO(VARPTR)		;INDICATE THE MAIL FILE HAS BEEN CLOSED
	CALL	CFIRM			;SEND THE SUCCESS/FAILURE MESSAGES
	RET				;AN ERROR OCCURRED
	RETSKP				;RETURN SUCCESSFULLY

;SEND OFF THE MESSAGE



SNDOFF: $TRACE <At SNDOFF...>
	MOVE	MSGPTR,MSGSTR(VARPTR)	;POINT TO START OF THE MESSAGE
	PUSH	P,MSGPTR		;PASS AS AN ARGUMENT
	PUSH	P,[0]			;REQUIRED BY SCAN%P
	PUSH	P,[-1,,[ASCIZ/MX Mail-11 Listener/]] ;REQUIRED BY SCAN%P
TOPS20<	PUSH	P,[SC%WHL]	>	;WHEEL PRIVS
TOPS10<	PUSH	P,[IP.JAC]	>	;WHEEL PRIVS
	CALL	SCAN%P			;SEND OFF TO MX
	ADJSP	P,-4			;RESET THE STACK
	CAIN	T1,0			;ERROR?
	RET				;YES, RETURN FALSE

;SET UP FOR THE NEXT PAGE

	SKIPE	NOMORE(VARPTR)		;LAST PAGE?
	RETSKP				;YES, RETURN TRUE
	SETZM	MSGRCT(VARPTR)		;NO RECORDS YET IN THIS MESSAGE
	MOVE	T1,.PKID(MSGPTR)	;GET THE MESSAGE ID
	MOVEM	T1,IDNUM(VARPTR)	;STORE FOR LATER
	RETSKP				;RETURN TRUE

;THE LAST PAGE OF THE MESSAGE HAS BEEN COMPLETED, SEND IT OFF

SNDLST:	$TRACE <At SNDLST...>
	SETOM	NOMORE(VARPTR)		;THIS IS THE LAST PAGE OF THE MESSAGE
	CALL	SNDMSG			;SEND IT OFF
	RET				;AN ERROR OCCURRED
	RETSKP				;RETURN TRUE

SUBTTL FILSPC	CREATE THE FILE SPEC RECORD

FILSPC:	$TRACE <At FILSPC...>
	AOS	T1,MSGRCT(VARPTR)	;PICK UP THE NUMBER OF RECORDS
	MOVEM	T1,.RECNM(MSGPTR)	;STORE IN THE RECORD
	MOVEI	T1,.FLSPC		;FILE SPEC RECORD
	MOVEM	T1,.RECTY(MSGPTR)	;STORE IN THE RECORD

;COPY FILE NAME OVER TO SPEC RECORD

	SETZ	T4,			;NUMBER OF BYTES IN THE FILE NAME
	MOVE	T2,MAIPTR(VARPTR)	;POINT TO THE FILE NAME
	MOVE	T3,[POINT 7,.RECTX(MSGPTR)] ;POINT TO RECORD LOCATION
COPNAM:	ILDB	T1,T2			;GET THE NEXT BYTE
	IDPB	T1,T3			;PLACE THIS BYTE IN THE RECORD
	AOS	T4			;INCREMENT THE BYTE COUNT
	CAIE	T1,0			;IS THIS THE END?
	JRST	COPNAM			;NO, GET THE NEXT CHARACTER

;FIND THE RECORD SIZE

	IDIVI	T4,BY2WRD		;FIND THE NUMBER OF WORDS IN FILE SPEC
	SKIPE	T5			;ANY PARTIAL WORDS
	AOS	T4			;YES, COUNT AS A FULL WORD
	ADDI	T4,.RECHS		;ADD SIZE OF THE FILE HEADER
	MOVEM	T4,.RECLN(MSGPTR)	;STORE LENGTH IN RECORD
	RET

SUBTTL FINFIL	COMPLETE THE MAIL FILE

;GET THE MAILED TO: LIST FROM THE VAX

FINFIL:	$TRACE <At FINFIL...>
	SETZM	EOFMES(VARPTR)		;END OF VAX MESSAGE NOT YET FOUND
	MOVE	BUFPTR,SCRAT4(VARPTR)	;GET RID OF LAST COMMA, BLANK
	MOVEI	T1,15			;REPLACE THE COMMA
	IDPB	T1,BUFPTR		;WITH A CARRIAGE RETURN
	MOVEI	T1,12			;REPLACE THE BLANK
	IDPB	T1,BUFPTR		;WITH A LINE FEED
	MOVE	T6,WRKBU2(VARPTR)	;PREPARE FOR THE CALL
	HRLI	T6,(POINT 8)		;MAKE IT AN 8 BIT BYTE POINTER
	CALL	REALIN			;READ SUBJECT LINE AND COPY TO BUFFER
	RET				;AN ERROR OCCURRED

;GET THE SUBJECT LINE FROM THE VAX

	MOVE	T6,WRKBUF(VARPTR)	;GET THE WORKING BUFFER ADDRESS
	HRLI	T6,(POINT 8)		;MAKE INTO AN 8 BIT BYTE POINTER
	CALL	REALIN			;COPY THE SUBJECT: TO THE BUFFER
	RET				;AN ERROR OCCURRED

;COPY THE SUBJECT LINE

	MOVEI	T2,[ASCIZ/Subject: /]	;ADDRESS OF THE STRING
	HRLI	T2,(POINT 7)		;MAKE INTO A POINTER
SUBJLP:	ILDB	T3,T2			;GET THE NEXT BYTE
	CAIN	T3,0			;END OF THE STRING?
	JRST	SUBCOP			;YES, SAVE THE UPDATED BUFFER POINTER
	IDPB	T3,BUFPTR		;STORE THIS BYTE IN THE BUFFER
	AOS	BUFBYT(VARPTR)		;INCREMENT THE BYTE COUNT
	JRST	SUBJLP			;GET THE NEXT BYTE
SUBCOP:	MOVE	T7,WRKBUF(VARPTR)	;POINT TO THE BUFFER TO BE COPIED
	CALL	CPYBUF			;COPY OVER THE SUBJECT

;COPY THE MAILED TO: LINE TO THE BUFFER

;**;[304]RBW 8-AUG-86 CHANGE 1 LINE AT SUBCOP+2 (REPLACE THE SPACE WITH A '-')
	MOVEI	T2,[ASCIZ/Mailed-to: /]	;[304] LINE TO BE COPIED
	HRLI	T2,(POINT 7)		;MAKE INTO A POINTER
MAILP:	ILDB	T3,T2			;GET THE NEXT BYTE
	CAIN	T3,0			;END OF THE STRING?
	JRST	SAVEPT			;YES, SAVE THE UPDATED BUFFER POINTER
	IDPB	T3,BUFPTR		;STORE THIS BYTE IN THE BUFFER
	AOS	BUFBYT(VARPTR)		;INCREMENT THE BYTE COUNT
	JRST	MAILP			;GET THE NEXT BYTE
SAVEPT:	MOVE	T7,WRKBU2(VARPTR)	;ADDRESS OF THE MAILED TO: LIST
	CALL	CPYBUF			;COPY OVER TO THE BUFFER

;INSERT TWO BLANK LINES

	MOVEI	T7,[ASCIZ/
/]
	CALL	CPYBUF			;COPY OVER TO THE BUFFER
	MOVEI	T1,2			;NUMBER OF NEW CHARACTERS
	ADDM	T1,BUFBYT(VARPTR)	;UPDATE THE BUFFER CHARACTER COUNT

;COPY THE BUFFER TO THE MAIL FILE

	MOVE	T1,STABUF(VARPTR)	;POINT TO START OF BUFFER
	PUSH	P,FILNB(VARPTR)		;FILE NUMBER OF THE MAIL FILE
	PUSH	P,T1			;POINT TO START OF THE BUFFER
	MOVE	T1,BUFBYT(VARPTR)	;NUMBER OF BYTES TO COPY
	PUSH	P,T1			;PASS AS AN ARGUMENT
	PUSH	P,[0]			;NO ERROR BUFFER
	CALL	UF%WRI			;WRITE TO THE MAIL FILE
	ADJSP	P,-4			;RESET THE STACK

;NOW COPY THE MESSAGE TO THE MAIL FILE

CPYMES:	SETZM	BUFBYT(VARPTR)		;NUMBER OF BYTES IN BUFFER SO FAR
	HRR	T6,STABUF(VARPTR)	;ADDRESS TO READ NEXT MSG LINE INTO
	HRLI	T6,(POINT 8)		;MAKE IT AN 8 BIT BYTE POINTER
	CALL	REALIN			;READ THE NEXT LINE
	RET				;AN ERROR OCCURRED, RETURN FALSE
	SKIPE	EOFMES(VARPTR)		;END OF MESSAGE?
	JRST	CPYDSH			;YES, ADD DASHES AT END OF THE MESSAGE
	MOVE	T1,STABUF(VARPTR)	;POINT TO THE START OF THE BUFFER
	MOVE	T2,BUFBYT(VARPTR)	;THE NUMBER OF BYTES TO COPY
	PUSH	P,FILNB(VARPTR)		;FILE NUMBER OF THE MAIL FILE
	PUSH	P,T1			;START OF THE BUFFER
	PUSH	P,T2			;NUMBER OF BYTES TO COPY
	PUSH	P,[0]			;NO ERROR BUFFER
	CALL	UF%WRI			;WRITE THE BUFFER TO THE MAIL FILE
	ADJSP	P,-4			;RESET THE STACK
	JRST	CPYMES			;GET THE NEXT LINE


CPYDSH:	MOVE	T1,STABUF(VARPTR)	;POINT TO THE START OF THE BUFFER
	MOVE	T6,T1			;COPY FOR THE DESTINATION OF THE BLT
	HRLI	T6,FINDSH		;SOURCE OF THE BLT
	BLT	T6,^D3(T1)		;COPY DASHES TO THE BUFFER
	MOVEI	T2,^D13			;NUMBER OF BYTES IN THIS LINE
	PUSH	P,FILNB(VARPTR)		;FILE NUMBER OF THE MAIL FILE
	PUSH	P,T1			;START OF THE BUFFER
	PUSH	P,T2			;NUMBER OF BYTES TO COPY
	PUSH	P,[0]			;NO ERROR BUFFER
	CALL	UF%WRI			;WRITE THE BUFFER TO THE MAIL FILE
	ADJSP	P,-4			;RESET THE STACK
	RETSKP				;FINISHED, RETURN TRUE

FINDSH:	ASCIZ/   --------
/

SUBTTL REALIN	READS NEXT LINE FROM VAX AND PLACES IN THE MAIL FILE

;FIRST, READ IN THE LINE
;THIS ROUTINE IS CALLED WITH T6 POINTING TO WHERE THE DATA IS TO BE READ
;TO (IT MUST BE AN 8 BIT BYTE POINTER)

REALIN:	PUSH	P,DATLNK(VARPTR)	;THE DATA LINK NUMBER
	PUSH	P,[^D400]		;THE NUMBER OF WORDS MAX
	PUSH	P,T6			;WHERE THE LINE IS TO BE READ TO
	SETZM	0(T6)			;ZERO THE FIRST WORD OF THE BUFFER
	HRLI	T7,0(T6)		;PREPARE FOR THE BLT
	HRRI	T7,1(T6)
	BLT	T7,^D99(T6)		;ZERO OUT THE BUFFER
	CALL	UN%REA			;GET THE 8 BIT LINE FROM THE VAX
	ADJSP	P,-3			;RESET THE STACK
        JUMPL	T1,R			;AN ERROR, RETURN FALSE
	MOVE	T7,T6			;SAVE FOR THE SOUT

;TRANSLATE THE 8 BIT LINE TO 7 BITS

	HRR	T5,T6			;GET THE ADDRESS FOR THE 7 BIT LINE
	HRLI	T5,(POINT 7)		;MAKE IT A 7 BIT POINTER

	CAIE	T1,1			;MESSAGE 1 BYTE IN LENGTH?
	JRST	TRNSFR			;NO, NOT END OF MESSAGE
	ILDB	T2,T6			;YES, GET THE BYTE
	CAIE	T2,0			;A NULL?
	JRST	TRNSF2			;NO, CHANGE TO 7 BITS
	SETOM	EOFMES(VARPTR)		;YES, END OF MESSAGE
	RETSKP				;RETURN TRUE

TRNSFR:	ILDB	T2,T6			;GET THE NEXT BYTE
	CAIN	T2,0			;END OF THE LINE?
	JRST	ENDLN			;YES, FINISH UP
TRNSF2:	IDPB	T2,T5			;PLACE IN THE 7 BIT LINE
	AOS	BUFBYT(VARPTR)		;INCREMENT THE BYTE COUNT
	JRST	TRNSFR			;GET THE NEXT BYTE

;FINISH THE LINE WITH A CARRIAGE RETURN, LINE FEED

ENDLN:	MOVEI	T2,15			;GET THE CARRIAGE RETURN
	IDPB	T2,T5			;PLACE IN THE WORKING BUFFER
	MOVEI	T2,12			;GET THE LINE FEED
	IDPB	T2,T5			;PLACE IN THE WORKING BUFFER
	MOVEI	T2,0			;MAKE IT AN ASCIZ STRING
	IDPB	T2,T5			;PLACE IN THE WORKING BUFFER
	MOVEI	T2,2			;NUMBER OF ADDITIONAL BYTES IN BUFFER
	ADDM	T2,BUFBYT(VARPTR)	;UPDATE THE BYTE COUNT
	RETSKP

;COPY THE WORKING BUFFER TO THE BUFFER

CPYBUF:	HRR	T2,T7			;GET ADDRESS OF THE WORKING BUFFER
	HRLI	T2,(POINT 7)		;MAKE INTO A POINTER
BUFLP:	ILDB	T3,T2			;GET THE NEXT WORKING BUFFER BYTE
	CAIN	T3,0			;END OF THE STRING?
	RET				;YES, RETURN
	IDPB	T3,BUFPTR		;STORE THIS BYTE IN THE BUFFER
	JRST	BUFLP			;GET THE NEXT BYTE

SUBTTL CFIRM	SEND SUCCESS/FAILURE MESSAGES

CFIRM:	$TRACE <At CFIRM...>
	MOVN	T7,NUMUSR(VARPTR)	;GET THE NUMBER OF RECIPIENTS
	MOVE	T10,STABLK(VARPTR)	;ADDRESS OF THE RECIPIENT STATUS BUFFER
	MOVE	T6,T10			;SAVE IN CASE THERE IS MORE THAN 1 PAGE
	AOS	T10			;SKIP OVER THE LINK WORD
DONEXT:	MOVE	T1,0(T10)		;GET THE NEXT RECIPIENT STATUS WORD
	JUMPE	T1,CHKSUC		;ZERO MEANS RECIPIENT RECEIVED MAIL
	SKIPG	T1			;THE LAST ENTRY OF THIS PAGE?
	CALL	GTNXBF			;YES, GET THE NEXT PAGE OF STATUSES
	CALL	ERRRCT			;INFORM VAX OF ERROR
	JRST	CFIRET			;NETWORK ERROR OCCURRED
	JRST	CHKNXT			;CHECK STATUS OF NEXT RECIPIENT
CHKSUC:	CALL	SUCRCT			;INFORM VAX RECIPIENT RECEIVED MAIL
	JRST	CFIRET			;NETWORK ERROR OCCURRED
CHKNXT:	AOJN	T7,DONEXT		;CHECK STATUS OF NEXT RECIPIENT
	CALL	RLSEPG			;RELEASE ANY RECIPIENT STATUS PAGES
	RETSKP				;FINISHED, RETURN TRUE
CFIRET:	RET				;NETWORK ERROR OCCURRED, RELEASE
					;RECIPIENT STATUS PAGES LATER

;GET THE ADDRESS OF THE NEXT RECIPIENT STATUS PAGE

GTNXBF:	MOVE	T10,0(T6)		;GET THE ADDRESS FROM THE CURRENT PAGE
	MOVE	T6,T10			;SAVE IN CASE THERE IS ANOTHER PAGE
	AOS	T10			;SKIP OVER THE LINK WORD
	RET

;RELEASE ANY RECIPIENT STATUS PAGES

RLSEPG:	MOVE	T1,STABLK(VARPTR)	;GET ADDRESS OF THE RESIDENT PAGE
	MOVE	T7,0(T1)		;GET CONTENTS OF THE LINK WORD
RLSEP1:	SKIPN	T7			;IS THERE ANY OTHER PAGES?
	RET				;NO, SO QUIT
	MOVE	T1,T7			;GET A COPY OF THE ADDRESS
	MOVE	T7,0(T7)		;GET THE LINK WORD OF THIS PAGE
	LSH	T1,-^D9			;CHANGE ADDRESS TO PAGE NUMBER
	PUSH	P,T1			;PASS THE PAGE NUMBER AS AN ARGUMENT
	CALL	UMP%RE			;RELEASE THE PAGE
	ADJSP	P,-1			;RESET THE STACK
	JUMPL	T1,[PUSH P,[POINT 7,[ASCIZ /Error releasing page at RLSEP1:/]]
		    PUSHJ P,NMLDIE ]		;ERROR IN RELEASING THE PAGE
	JRST	RLSEP1			;RELEASE THE NEXT PAGE, IF ANY

SUBTTL ERRRCT SEND INVALID USER OR NODE MESSAGE

ERRRCT: $TRACE <At ERRRCT...>
INVND2:	PUSH	P,DATLNK(VARPTR)	;DATA LINK NUMBER
	PUSH	P,[1]			;END OF MESSAGE FLAG
	PUSH	P,[4]			;NUMBER OF BYTES IN THE ERROR MESSAGE
	MOVEI	T1,FAIMSG(VARPTR)	;ERROR MESSAGE ADDRESS
	HRLI	T1,(POINT 8)		;MAKE IT INTO A POINTER
	PUSH	P,T1			;PASS AS AN ARGUMENT
	CALL	UN%WRI			;TELL THE VAX
	ADJSP	P,-4			;RESET THE STACK
	JUMPLE	T1,ENINN		;AN ERROR, ABORT THE LINK

	MOVE	T1,0(T10)		;GET THE ERROR FLAG
	TXNN	T1,INVLND		;INVALID NODE NAME?
	JRST	IVUSER			;NO, INVALID USER
	MOVE	T1,WRKBU2(VARPTR)	;ADDRESS OF BUFFER TO BE SENT TO VAX
	HRLI	T1,ERMSG3		;ADDRESS OF FIRST PART OF MESSAGE TEXT
	BLT	T1,10(T1)		;COPY TO THE BUFFER
	MOVE	T1,WRKBU2(VARPTR)	;ADDRESS OF BUFFER TO BE SENT TO VAX
	HRLI	T1,(POINT 8)		;MAKE INTO A POINTER
	ADDI	T1,10			;POINT TO THE CORRECT WORD
	IBP	T1			;SKIP OVER THIS BYTE
	MOVE	T3,T10			;ADDRESS OF CURRENT INVALID NODE ENTRY
	AOS	T3			;ADDRESS OF INVALID NODE NAME
	HRLI	T3,(POINT 8)		;MAKE INTO A POINTER
	MOVEI	T5,^D33			;NUMBER OF BYTES IN MESSAGE SO FAR
CHSIZE:	ILDB	T2,T3			;GET THE NEXT 7 BIT BYTE
	CAIN	T2,0			;END OF THE STRING?
	JRST	SNDNOD			;YES, SEND TO THE VAX
	IDPB	T2,T1			;NO, PLACE IN 8 BIT BYTE NAME BUFFER
	AOS	T5			;INCREMENT BYTE COUNT
	JRST	CHSIZE			;GET THE NEXT BYTE

SNDNOD: $TRACE	<At SNDNOD...>
	PUSH	P,DATLNK(VARPTR)	;GET THE DATA LINK NUMBER
	PUSH	P,[1]			;END OF MESSAGE FLAG
	PUSH	P,T5			;THE LENGTH OF THE MESSAGE
	MOVE	T1,WRKBU2(VARPTR)	;POINT TO THE MESSAGE
	HRLI	T1,(POINT 8)		;MAKE INTO A POINTER
	PUSH	P,T1			;PASS AS AN ARGUMENT
	CALL	UN%WRI			;SEND THE MESSAGE OFF
	ADJSP	P,-4			;ADJUST THE STACK POINTER
	JUMPLE	T1,ENINN		;AN ERROR OCCURRED, RETURN FALSE

	PUSH	P,DATLNK(VARPTR)	;DATA LINK
	PUSH	P,[1]			;END OF MESSAGE
	PUSH	P,[1]			;MESSAGE LENGTH
	MOVEI	T1,[EXP 0]		;THE MESSAGE
	HRLI	T1,(POINT 8)		;MAKE IT INTO A POINTER
	PUSH	P,T1			;PASS AS AN ARGUMENT
	CALL	UN%WRI			;TELL THE VAX
	ADJSP	P,-4			;RESET THE STACK
	JRST	COMCH2			;CHECK FOR ANOTHER INVALID NODE OR USER

IVUSER:	$TRACE <At IVUSER...>
	MOVE	T1,WRKBU2(VARPTR)	;ADDRESS OF BUFFER TO BE SENT TO VAX
	HRLI	T1,ERMSG1		;ADDRESS OF FIRST PART OF MESSAGE TEXT
	HRRZ	T3,WRKBU2(VARPTR)	;ADDRESS FOR THE BLT
	BLT	T1,12(T3)		;COPY TO THE BUFFER
	MOVE	T1,WRKBU2(VARPTR)	;ADDRESS OF BUFFER TO BE SENT TO VAX
	HRLI	T1,(POINT 8)		;MAKE INTO A POINTER
	ADDI	T1,12			;POINT TO THE CORRECT WORD
	IBP	T1			;SKIP OVER THIS BYTE
	IBP	T1			;SKIP OVER THIS BYTE
NXTPT2:	MOVEI	T5,^D42			;SIZE OF THE MESSAGE SO FAR
	MOVE	T3,NODE7(VARPTR)	;POINTER TO NODE NAME
NXTPT3:	ILDB	T2,T3			;GET THE NEXT CHARACTER
	CAIN	T2,0			;END OF THE NODE NAME?
	JRST	INVMSG			;YES, SEND OFF THE MESSAGE
	AOS	T5			;NO, INCREMENT THE BYTE COUNT
	IDPB	T2,T1			;PLACE IN THE BUFFER
	JRST	NXTPT3			;GET THE NEXT CHARACTER

INVMSG:	$TRACE <At INVMSG...>
	PUSH	P,DATLNK(VARPTR)	;DATA LINK
	PUSH	P,[1]			;END OF MESSAGE
	PUSH	P,T5			;MESSAGE LENGTH
	MOVE	T1,WRKBU2(VARPTR)	;ADDRESS OF THE BUFFER
	HRLI	T1,(POINT 8)		;MAKE INTO A POINTER
	PUSH	P,T1			;PASS AS AN ARGUMENT
	CALL	UN%WRI			;TELL THE VAX
	ADJSP	P,-4			;RESET THE STACK
	JUMPLE	T1,ENINN		;NETWORK ERROR, ABORT THE LINK

	PUSH	P,DATLNK(VARPTR)	;DATA LINK
	PUSH	P,[1]			;END OF MESSAGE
	PUSH	P,[1]			;MESSAGE LENGTH
	MOVEI	T1,[EXP 0]		;THE MESSAGE
	HRLI	T1,(POINT 8)		;MAKE IT INTO A POINTER
	PUSH	P,T1			;PASS AS AN ARGUMENT
	CALL	UN%WRI			;TELL THE VAX
	ADJSP	P,-4			;RESET THE STACK
	JUMPLE	T1,ENINN		;NETWORK ERROR
COMCHK:	AOS	T10			;ADDRESS OF THE NEXT STATUS ENTRY
	SKIPA				;GO RETURN
COMCH2:	ADDI	T10,3			;ADDRESS OF THE NEXT STATUS ENTRY
	RETSKP				;RETURN TRUE
ENINN:	RET				;RETURN FALSE, A NETWORK ERROR OCCURRED

;INFORM VAX OF SUCCESSFUL RECIPIENTS

SUCRCT:	PUSH	P,DATLNK(VARPTR)	;DATA LINK NUMBER
	PUSH	P,[1]			;END OF MESSAGE FLAG
	PUSH	P,[4]			;SIZE OF THE MESSAGE
	MOVEI	T2,SUCMSG(VARPTR)	;MESSAGE ADDRESS
	HRLI	T2,(POINT 8)		;MAKE INTO A POINTER
	PUSH	P,T2			;PASS AS AN ARGUMENT

NXTSMG:	$TRACE <At NXTSMG...>
	CALL	UN%WRI			;SEND THE MESSAGE
	ADJSP	P,-4			;RESET THE STACK
	JUMPLE	T1,R			;RETURN NOW IF NETWORK ERROR OCCURRED
	AOS	T10			;ADDRESS OF NEXT STATUS ENTRY
	RETSKP				;AND RETURN

SUBTTL DISCON - DISCONNECT THE CONNECTION

;CLOSE THE LINK

DISCON:	$TRACE <At DISCON...>
	PUSH	P,DATLNK(VARPTR)	;PASS THE DATA LINK NUMBER
	PUSH	P,[0]			;NO OPTIONAL DATA
	PUSH	P,[0]			;NO OPTIONAL DATA POINTER
	CALL	UN%CLO			;CLOSE THE LINK
	ADJSP	P,-3			;RESET THE STACK
	JUMPLE	T1,FORDIS		;ON ERROR, ABORT THE LINK
	RET				;AND RETURN

;FORDIS ABORTS THE LINK DUE TO ANY UNRECOVERABLE ERROR

FORDIS:	$TRACE <At FORDIS...>
	PUSH	P,DATLNK(VARPTR)	;DATA LINK
	PUSH	P,[.DCX11]		;UNDEFINED ERROR
	PUSH	P,[0]			;NO OPTIONAL DATA
	PUSH	P,[0]			;NO OPTIONAL DATA POINTER
	CALL	UN%ABO			;ABORT THE LINK
	ADJSP	P,-4			;RESET THE STACK
	RET				;AND RETURN

;CLSFIL CLOSES AND DELETES THE MAIL FILE DUE TO AN UNRECOVERABLE ERROR

CLSFIL:	$TRACE <At CLSFIL...>
	PUSH	P,FILNB(VARPTR)		;FILE NUMBER OF THE MAIL FILE
	PUSH	P,[1]			;ABORT THE FILE
	PUSH	P,[0]			;NO ERROR STRING
	CALL	UF%CLO			;CLOSE AND DELETE THE MAIL FILE
	ADJSP	P,-3			;RESET THE STACK
	RET				;AND RETURN

;CLOFIL CLOSES THE MAIL FILE PRIOR TO THE LAST MESSAGE PAGE BEING SENT TO MX

CLOFIL:	$TRACE <At CLOFIL...>
	PUSH	P,FILNB(VARPTR)		;FILE NUMBER OF THE MAIL FILE
	PUSH	P,[0]			;DO NOT ABORT THE FILE
	PUSH	P,[0]			;NO ERROR STRING
	CALL	UF%CLO			;CLOSE THE MAIL FILE
	ADJSP	P,-3			;RESET THE STACK
	RET				;AND RETURN

;RELEASE THE SPACE ALLOCATED TO THE MAIL FILE SPEC

RELMAI:	$TRACE <At RELMAI...>
	HRRZ	T1,MAIPTR(VARPTR)	;ADDRESS OF THE SPACE
	PUSH	P,T1			;PASS AS AN ARGUMENT
	CALL	RELASC			;RELEASE IT
	ADJSP	P,-1			;RESET THE STACK
	RET

RSKP:	AOS	0(P)
R:	RET

	END