Trailing-Edge
-
PDP-10 Archives
-
cuspjul86upd_bb-jf24a-bb
-
10,7/decmai/mx/lisvax.mac
There are 26 other files named lisvax.mac 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
GOTRU0: ILDB T3,T10 ;Get the first character
CAIN T3,QUOTE ;Is it a quote?
CALL SKIPQT ;Don't parse the 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
TXNE T4,SNQTS ;Have I seen any special characters?
JRST GOTRU1 ;Yes, skip these tests
CAIN T3,"(" ;Is it a special character?
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,"\"
JRST NEEDQT
CAIN T3,QUOTE
JRST NEEDQT
CAIN T3,"["
JRST NEEDQT
CAIN T3,"]"
JRST NEEDQT
GOTRU1: CAIE T3,":" ;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
;Set the "Sender needs quotes" bit
NEEDQT: TXO T4,SNQTS
JRST GOTRU1
SKIPQT: ILDB T3,T10 ;Get the next character
CAIN T3,QUOTE ;Is it a quote?
RET ;Yes...
CAIE T3,0 ;Is it a null?
JRST SKIPQT ;No, keep looking
MOVNI T1,1 ;Yes. Back the pointer up. -1 into T1
ADJBP T1,T10 ;T1 now contains the backed up pointer
MOVE T10,T1 ;Store the updated pointer in T10
TXO T4,SNQTS ;Set the sender needs quotes bit
RET ;All done
;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
TRANSN: SETZ T6, ;BYTE COUNT
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
TXNN T4,SNQTS ;Skip if quotes are needed
TRANS2: ILDB T3,T1 ;GET THE NEXT CHARACTER
CAIN T3,0 ;END OF THE SENDER NAME?
JRST TRSNOD ;YES, GET THE NODE NAME
CAIN T3," " ;END OF THE SENDER NAME?
JRST TRSNOD ;YES, GET THE NODE NAME
IDPB T3,T5 ;PLACE IN THE SENDER RECORD
AOS T6 ;INCREMENT THE BYTE COUNT
JRST TRANS2 ;GET THE NEXT CHARACTER
;COPY OVER TO THE SENDER RECORD THE NODE NAME FOUND, IF THERE IS ONE
TRSNOD: 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
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
MOVE T10,T5 ;T10 POINTS TO THE RECIPIENT NAME
SETZ T7, ;ASSUME NO NODE NAME
NXTCHR: ILDB T1,T5 ;GET THE NEXT RECIPIENT STRING BYTE
CAIN T1,0 ;END OF THE STRING?
JRST CHKNDE ;YES, CHECK IF NODE NAME IS PRESENT
CAIN T1," " ;END OF THE STRING?
JRST CHKNDE ;YES, CHECK IF NODE NAME IS PRESENT
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
CHKNDE: SKIPN T7 ;NODE NAME PRESENT?
JRST GETUSR ;NO, VALIDATE THE RECIPIENT
MOVE T4,WRKBUF(VARPTR) ;ADDRESS OF WORKING BUFFER
HRLI T4,(POINT 7) ;MAKE INTO A POINTER
MOVE T5,T4 ;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
COLFND: SETZ T1, ;ASCIZ TERMINATION CHARACTER
IDPB T1,T5 ;MAKE NODE NAME ASCIZ
MOVE T7,T4 ;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
GETUSR: SETZ T4, ;NUMBER OF CHARACTERS IN NAME
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
GETUS2: ILDB T1,T10 ;GET THE NEXT RECIPIENT CHARACTER
AOS T4 ;INCREMENT THE BYTE COUNT
CAIN T1,0 ;END OF THE NAME?
JRST VALIDU ;YES, VALIDATE IT, IF NO NODE NAME
CAIN T1," " ;END OF THE NAME?
JRST VALIDU ;YES, VALIDATE IT, IF NO NODE NAME
IDPB T1,T6 ;NO, PLACE IN THE RECIPIENT RECORD
JRST GETUS2 ;NO, GET THE NEXT CHARACTER
VALIDU: 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
MOVEI T2,[ASCIZ/Mailed to: /] ;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