Trailing-Edge
-
PDP-10 Archives
-
BB-R598A-RM_1983
-
swskit-v3/vax-mail/vmail.mac
There are 6 other files named vmail.mac in the archive. Click here to see a list.
;<MIERSWA.DECNET.SWSKIT.VAX-MAIL>VMAIL.MAC.6, 4-Jan-82 11:49:01, EDIT BY GRANT
;Fix test for null line in REPEAT:
;<STEVENS.VMAILR>VMAIL.MAC.76 25-Nov-81 16:18:00 Edit by STEVENS
; Repaired error in PRSUSR routine which cause TOOBUF to be wrong
;<STEVENS.VMAILR>VMAIL.MAC.75 25-Nov-81 14:57:00 Edit by STEVENS
; Change last part of error string to VAX to a SOUTR monitor
; call to force transmission of the error string
;<STEVENS.VMAILR>VMAIL.MAC.74 25-Nov-81 12:23:00 Edit by STEVENS
; Fixed error in checking username to check for RC%NOM
;<STEVENS.VMAILR>VMAIL.MAC.73 23-Nov-81 10:54:00 Edit by STEVENS
; Repaired error in clearing temp1
;<STEVENS.VMAILR>VMAIL.MAC.72 23-Nov-81 10:02:00 Edit by STEVENS
; Fix receive to prevent buffer overflow and clear buffer before
; receive to ensure ASCIZ
;<STEVENS.VMAILR>VMAIL.MAC.71 20-Nov-81 14:24:00 Edit by STEVENS
; Fix headers so host name appears
;<STEVENS.VMAILR>VMAIL.MAC.70 20-Nov-81 13:29:00 Edit by STEVENS
; Add blank line between headers and body of message
;<STEVENS.VMAILR>VMAIL.MAC.69 20-Nov-81 13:13:00 Edit by STEVENS
; Set file byte size and remove extra crlf in mail file
;<STEVENS.VMAILR>VMAIL.MAC.68 20-Nov-81 12:04:00 Edit by STEVENS
; Fix filnam on forwarding to always take next higher generation
;<STEVENS.VMAILR>VMAIL.MAC.67 20-Nov-81 11:19:00 Edit by STEVENS
; Put file byte count on forwarding file
;<STEVENS.VMAILR>VMAIL.MAC.66 20-Nov-81 10:00:00 Edit by STEVENS
; Repaired assorted problem in forwarding message
;<STEVENS.VMAILR>VMAIL.MAC.65 20-Nov-81 09:30:00 Edit by STEVENS
; Cleaned up quefil routine by inserting jerr of fatals
;<STEVENS.VMAILR>VMAIL.MAC.64 20-Nov-81 09:01:00 Edit by STEVENS
; REPAIRED BUG IN QUEFIL ROUTINE (JFCL AFTER GETJI)
Title Vmail - Vax Mail Listener
Search Macsym,Monsym
.require Sys:Macrel
Sall
.directive Flblst
T1=1
T2=2
T3=3
T4=4
T5=5
P1=6
P2=7
P3=10
P4=11
P5=12
Ptr=13 ;Global Byte Pointer To Receive Mail
Cnt=14 ;Global Byte Count For Same
Cx=16
P=17
.ver==1
.edt==^D89
Loc 137
Exp <.ver>B11+.edt
Reloc
Define Jerr(String),<
Xlist
Erjmp [ Hrroi T1,[Asciz /Vmail Error: /]
Esout%
Hrroi T1,[Asciz /String/]
Psout%
Hrroi T1,[Asciz / Because: /]
Psout%
Movx T1,.priou
Hrloi T2,.fhslf
Erstr%
Jfcl
Jfcl
Call Lgcrlf
Call Dtstmp ;; Log This Lossage Also
Log <String>
Log < Because: >
Move T1,Logjfn
Hrloi T2,.fhslf
Erstr%
Jfcl
Jfcl
CALL LGCRLF
Jrst Fatal]
List
>
Define Log(String),< ;; Put Message Into Log File
Xlist
Hrroi T1,[Asciz \String\] ;; So It Can Type Slashes
Call Logmsg
List
>
Define Debug(String),<
Skipe Dbugsw
Jrst [ Hrroi T1,[Asciz /String/]
Psout%
Jrst .+1 ]
>
Define Debstr(String),<
Skipe Dbugsw
Jrst [ Hrroi T1,String
Psout%
Jrst .+1 ]
>
Define Clrbuf(bufnam,Buflen),<
Setzm Bufnam
Move T1,[Bufnam,,Bufnam+1]
Blt T1,Bufnam+buflen-1
>
Define Nchar ,<
Move T1,Netjfn
Bin%
jerr <BIN from network failed>
Move T1,T2
>
Define Nrecord(Buffer,Nchar),<
Move T1,Netjfn
Hrroi T2,Buffer
Movni T3,Nchar
Setz T4,
Sinr%
Jerr <Sinr failed at Nrecord>
>
Define Vaxsuccess,<
Move T1,Netjfn
Hrroi T2,[Ascii//]
Movei T3,-4
Setz T4,
Soutr%
jerr <soutr to network failed>
>
Define Vaxerr(Errmsg),<
Move T1,Netjfn
Hrroi T2,[Ascii//]
Movei T3,-4
Setz T4,
Sout%
jerr <sout to network failed>
Move T1,Netjfn
Hrroi T2,[Asciz /Errmsg/]
Setzb T3,T4
Sout%
jerr <sout to network failed>
Hrroi T2,Atmbuf
Setzb T3,T4
Sout%
jerr <sout to network failed>
Hrroi T2,[Asciz/ At Node /]
Setzb T3,T4
Sout%
jerr <sout to network failed>
Hrroi T2,ournam
Setzb T3,T4
Sout% ; force string transmission
jerr <sout to network failed>
Hrroi T2,[0]
Movei T3,-1
Setz T4,
Soutr%
jerr <soutr to network failed>
>
Define Die(String),< ;; Fatal Internal Error
Xlist
Jrst [ Hrroi T1,[Asciz /Vmail Fatal Internal Error: /]
Esout%
Hrroi T1,[Asciz /String/]
Psout%
Hrroi T1,[Asciz /
/]
Psout%
Call Lgcrlf ;; Log This Error
Call Dtstmp ;; Time Stamp It
Hrroi T1,[Asciz /Fatal Error: /]
Call Logmsg
Hrroi T1,[Asciz /String/]
Call Logmsg
Jrst Fatal]
List
>
Define Herald(Ver,Edt),<
Xlist
; Tmsg <Vmail Version Ver(Edt) Running>
Hrroi T1,[Asciz /
Vmail Version Ver(Edt) Running/]
Call Logmsg
List
>
Define Log(String),<
Xlist
Hrroi T1,[Asciz \String\]
Call Logmsg
List
>
;Storage
FLGPAG==600 ;page into which we map DECNET-MAILER.FLAGS
FLGADR==FLGPAG*1000 ;address of DECNET-MAILER.FLAGS
Tmplen==50 ; Temporary Storage
Natmbf==40 ; Length Of Atom Buffer In Words
Bbflen==40000 ; Length Of Big Buffer Into Which Mail Is Read
Nfrmbf==20 ; Length Of Sender Name Buffer
Timen==^d180000 ; Milliseconds Before Sender Declared Tardy
Stklen==200 ; Size Of Stack
Dbugsw: 0 ; -1 If Debug
Flgjfn: Block 1 ;Jfn of Decnet-mailer.flags
Atmbuf: Block Natmbf ; Atom Buffer
Subbuf: Block Natmbf ; Subject Buffer
Toocnt: Block 1 ; Count of recipients per line in TOOBUF
Tooptr: Block 1 ; Pointer to current position in TOOBUF
Toobuf: Block Natmbf ; To Names Buffer
Bigbuf: Block Bbflen ; Where It All Is Combined To
Nodtab: Block ^D101 ; Table space for tbluk call
Nodstr: Block ^D200 ; String space for recipient nodes
Ulist: Block ^D200 ; Where To Store Mailbox Directory Numbers
Frmmsg: Block 20 ; String To Type On Recipient'S Terminal
Frmbuf: Block Nfrmbf ; Where To Put Sender'S Name Plus Host
Frmnam: Block Nfrmbf ; Where To Put Sender'S Name
Ournam: Block 2 ; Our Host Name
Hstnam: Block 2 ; Host name we are sending to
Usrnum: Block 1 ; User number we are sending to
Filnam: Block 1 ; File name for forwarded mail
Temp1: Block Tmplen
Temp2: Block Tmplen
Gtinf: Block 20 ; Getji Block
Stack: Block Stklen ; One Stack For Each Fork
Netjfn: Block 1 ; Network File Jfn
Logjfn: Block 1 ; Log File Jfn
Ntime: Block 1 ; Time Receipt Of Mail Initiated (For Status)
Elptim: Block 1 ; Elapsed Time For Receipt Of Mail
Bytcnt: Block 1 ; Length Of Mail In Bytes
Capenb: Block 1 ; Saved Capabilities
Pc1: Block 1 ; Pc Save Location For Psi Code
Pc2: Block 1
Pc3: Block 1
Levtab: Pc1
Pc2
Pc3
Chntab: 2,,Conect ; Connect Initiate On Level 2
1,,Timout ; Timeout Psi On Level 1
Xlist ; Nothing Else
Repeat ^d34,<Exp 0>
List
Vmail:: Reset%
Move P,[-Stklen,,Stack]
Move T1,[Sixbit /Vmail/]
Move T2,[Sixbit /Vmail/]
; Setsn% ; Declare Our Name For Statistics
; Jfcl
MOVX T1,GJ%SHT!GJ%PHY ;find mailer flags, physical-only please
HRROI T2,[ASCIZ /SYSTEM:DECNET-MAILER.FLAGS.1;P777777/]
GTJFN%
Jerr<Can't find SYSTEM:DECNET-MAILER.FLAGS.1>
MOVX T2,<440000,,0>!OF%RD!OF%WR!OF%THW
OPENF% ;open thawed (so updates OK)
Jerr<Can't OPENF PS:<SYSTEM>DECNET-MAILER.FLAGS>
MOVEM T1,FLGJFN ;remember handle
HRLZ T1,T1 ;from file page zero
MOVE T2,[.FHSLF,,FLGPAG] ;to fork page FLGPAG
MOVX T3,PM%RD!PM%WR ;read and write access
PMAP% ;get the page in
jerr <Can't PMAP SYSTEM:DECNET-MAILER.FLAGS>
Movx T1,.ndgln ; Get Local Node Name Function
Move T2,[Point 7,Ournam]
Movem T2,1(P) ; Put Pointer On Stack
Movei T2,1(P) ; And Point To It
Node% ; Get Node Name
Jerr <Can'T Get Local Node Name>
Movx T1,.fhslf ; This Process
Move T2,[Levtab,,Chntab]
Sir% ; Init Psi System
Eir%
Call Opnlog ; Open Log File
Movem T1,Logjfn ; Save Jfn
Call Dtstmp ; Time Stamp It
Herald \.ver,\.edt
Log< On Node >
; Tmsg < On Node >
; Hrroi T1,Ournam
; Psout
; Tmsg <
;>
Hrroi T1,Ournam
Call Logmsg
Call Lgcrlf ; Crlf To Log File
Vmail0: Call Opnlsn ; Open Connection And Set Interrupt Up
Move T1,Logjfn ; Close Log File For Perusers
Closf%
Jfcl
Wait% ; For Connect Initiate
;Here When Connection Initiated
Conect: Move P,[-Stklen,,Stack] ; Reset Stack
Call Timeit ; Time This Guy
Call Opnlog ; Open Log File
Movem T1,Logjfn
Call Dtstmp ; Time Stamp This Transaction
Log <----Connect From >
Debug <----Connect From >
Call T4nhst ; Type Foreign Host Name At Log File
Call Lgcrlf ; Log A Crlf
Clrbuf Subbuf,Natmbf
Move T1,Netjfn ; Accept Connection
Movx T2,.mocc
Setzb T3,T4 ; No Additional Data
Mtopr%
Jerr <Couldn'T Accept Net Connection>
def: move t1,netjfn
MOVEI T2,.MORLS ;GET LINK STATUS
MTOPR%
JERR <Couldn't get link status after accepting a connection>
txne t3,mo%con ;is the link connected?
jrst abc ;yes
movei t1,^d1000
disms%
jrst def
abc: Movx T1,.hpelp ; Elapsed Time Since System Startup
Hptim% ; Snarf It
Jerr <Hptim Failed>
Movem T1,Ntime ; Remember Time This Reception Started
Call Parse ; Parse The Mail
Jrst Errxit ; Failed, Quit Now
Call Dtstmp ; Time Stamp Log
Log <Message From >
Hrroi T1,Frmbuf ; Sender'S Name
Call Logmsg ; Log It
Log < Received >
Call Lgcrlf
Call Lstats ; Log Statistics
Call Mailit ; Send The Mail Off
Die <Failure Returned From Mailit>
Errxit: Call Clznet ; Close And Reopen Net Link
Call Cncltm ; Cancel Timeout Request
Call Dtstmp
Log <----Connection Closed
>
Move T1,Logjfn
Closf% ; Close Log File For Perusers
Jfcl
Debrk% ; Return To Background
; Parse Mail Received. Place Sender Name In Frmbuf, Recipient Directory
; Numbers In Ulist, Terminated With A Zero Entry
; Headers Must Appear In The Following Order.
; From, To, Cc
; Returns +1: Failure
; +2: Success
;
;PROGRAM FLOW DESCRIPTION NOT ALL ITEMS IN FLOW ARE IN THIS ROUTINE BUT
;IT DOES REPRESENT THE PROCEDURE TO SEND TO A VAX WHICH IS WHY IT IS
;INCLUDED HERE
;
; RECEIVE FROM FIELD FROM VAX
; PARSE FROM FIELD CONVERTING IT TO MS TYPE FIELD IN FRMBUF
; REPEAT UNTIL NULL RECEIVED
; : RECEIVE A RECIPIENT NAME FOR VERIFICATION
; : IF NULL RECEIVED
; : : THEN
; : : : EXIT REPEAT LOOP
; : ENDIF
; : PARSE USER NAME AND NODE
; : IF NODE SAME AS THIS NODE
; : : THEN
; : : : IF USER IS ON THIS SYSTEM
; : : : : THEN
; : : : : : SEND SUCCESS CODE TO VAX
; : : : : : PUT USER NUMBER INTO ULIST
; : : : : ELSE
; : : : : : SEND FAILURE CODE TO VAX
; : : : : : SEND ERROR MESSAGE TO VAX
; : : : : : SEND NULL TERMINATING ERROR MESSAGE TO VAX
; : : : : : RETURN FROM ROUTINE
; : : : ENDIF
; : : ELSE
; : : : SEND SUCCESS TO VAX (MESSAGE WILL BE QUEUED)
; : : : PUT -1 INTO ULIST
; : : : PUT NODE NAME INTO NODLST
; : ENDIF
; END REPEAT
; RECEIVE TO FIELD FROM VAX
; PARSE TO FIELD CONVERTING IT TO MS TYPE FIELD IN TOOBUF
; RECEIVE SUBJECT FIELD FROM VAX
; BEGIN FORMATING MESSAGE INTO MS TYPE MESSAGE
; REPEAT UNTIL NULL RECEIVED
; : RECEIVE A LINE FROM VAX
; : IF NULL RECEIVED
; : : THEN
; : : : EXIT REPEAT LOOP
; : ENDIF
; : OUTPUT TO MS MESSAGE BUFFER
; END REPEAT
; REPEAT UNTIL NULL DETECTED
; : GET FIRST ITEM IN ULIST
; : IF FIRST ITEM IN ULIST = -1
; : : THEN
; : : : GET NODE FROM NODLST
; : : : PUT MAIL INTO FILE FOR DMAILR
; : : : SET FLAG IN DECNET-FLAGS SO FILE GETS SENT
; : : ELSE
; : : : PUT MAIL INTO USERS MAIL FILE
; : : : SPLAT OBNOXIOUS MESSAGE ACCRESS USERS SCREEN
; : ENDIF
; : IF NO ERROR
; : : THEN
; : : : SEND POSITIVE ACKNOWLEDGEMENT TO VAX
; : : ELSE
; : : : SEND NEGATIVE ACKNOWLEDGEMENT TO VAX
; : : : SEND ERROR MESSAGE TO VAX
; : : : SEND NULL TERMINATOR TO VAX
; : ENDIF
; END REPEAT
; RETURN +2
Parse: Clrbuf Frmnam,Nfrmbf
Move T1,Netjfn ; Save It
Movei T2,.morss ; Read Max Record Size
Mtopr%
JERR <Failed to read record size with MTOPR in PARSE>
Nrecord <Frmnam>,<Nfrmbf*5-1> ; Read From Field
Hrroi T1,Temp1 ; Setup Default Host
Hrroi T2,Hstnam
Setzb T3,T4
Sout%
Hrroi T1,Frmbuf ;Parse from field, results to FRMBUF
Move T2,[Point 7,Frmnam]
Call Prsnam
Setzm Toobuf ; Clear first location of TOOBUF
Hrroi T1,Toobuf ; Setup pointer to TOOBUF
Movem T1,Tooptr
Movei T1,2 ; Setup count of recipients per line in TOOBUF
Movem T1,Toocnt
Movei T1,^D100 ; Setup TBLUK table for PRSUSR
Movem T1,Nodtab
Movsi P1,-^D100 ; Maximum Of 100 Names In List
Parse3: Clrbuf Atmbuf,Natmbf ; Clear receive area
Nrecord <Atmbuf>,<Natmbf*5-1> ; Receive recipient from VAX
Skipn Atmbuf ; Skip if not end of list
Jrst Parse6 ; End of recipient list
Call Prsusr ; Parse recipient
Jrst [ Call Dtstmp ; None Found, Complain
Vaxerr <%network Mail Error : No Such User >
Log <%network Mail Error : No Such User >
Hrroi T1,Atmbuf ; Also Log Losing Name
Call Logmsg
Call Lgcrlf
Ret] ; Failure Return
Movem T1,Ulist(P1) ; Save number returned for mailing
Vaxsuccess ; Send VAX the success code
Aobjn P1,Parse3 ; Jump if not too many recipients
Call Dtstmp ; Woops, Too Many
Hrroi T1,Atmbuf ; Also Tell Log File
Call Logmsg
Call Lgcrlf
Ret ; Failure return
Parse6: Setzm Ulist(P1) ; Tie Off Recipient List
;
; Now Get Mailed To Field With Node Name And Subject
;
Clrbuf Atmbuf,Natmbf
Nrecord <Atmbuf>,<Natmbf*5-1>
Nrecord <Subbuf>,<Natmbf*5-1>
; Now Conbine It All Into Bigbuf
Setzm Bytcnt
Hrroi T1,Bigbuf
Hrroi T2,[Asciz /Date: /]
Setzb T3,T4
Sout%
Seto T2,
Movsi T3,(Ot%4yr!Ot%spa!Ot%nco!Ot%nsc!Ot%scl!Ot%tmz)
Odtim%
Hrroi T2,[Asciz/
From: /]
Setzb T3,T4
Sout%
Hrroi T2,Frmbuf
Setzb T3,T4
Sout%
Hrroi T2,[Asciz/
To: /]
Setzb T3,T4
Sout%
Hrroi T2,Toobuf
Setzb T3,T4
Sout%
Hrroi T2,[Asciz/
Subject: /]
Setzb T3,T4
Sout%
Hrroi T2,Subbuf
Setzb T3,T4
Sout%
Hrroi T2,[Asciz/
Mailed to: /]
Setzb T3,T4
Sout%
Hrroi T2,Atmbuf
Setzb T3,T4
Sout%
Hrroi T2,[Asciz/
/]
Setzb T3,T4
Sout%
Move T5,T1
Repeat: Clrbuf Temp1,Tmplen ; Clear storage area
Nrecord <Temp1>,<Tmplen*5-1> ; Get a message line from the VAX
CAMN T3,[-<TMPLEN*5-1>] ;WAS IT A BLANK LINE?
Jrst Crlf ; Yes, output CRLF
Skipn Temp1 ; End of message ?
Jrst Done ; Yes
Move T1,T5 ; Output message line to BIGBUF
Hrroi T2,Temp1
Setzb T3,T4
Sout%
Move T5,T1
Crlf: Move T1,T5 ; Output CRLF to BIGBUF
Hrroi T2,[Asciz/
/]
Setzb T3,T4
Sout%
Move T5,T1
Jrst Repeat
Done: Move T1,T5 ; Close off message
Hrroi T2,[Asciz/ --------
/]
Setzb T3,T4
Sout%
Call Gtbfsz ; Get Buffer Size Into Bigbug
Debug <
>
Debstr <Bigbuf>
Retskp ; All Done!
;
;Store Size Of Bigbuf Into Bytcnt
;
Gtbfsz: Setz T3,
Setz T2,
Move T1,[Point 7,Bigbuf]
Geta: Ildb T2,T1
Jumpe T2,Go
Addi T3,1
Jrst Geta
Go: Movem T3,Bytcnt
Jrst R
;Routine to parse a node and user name and convert it to a TOPS-20
;string compatable with MS
;
;CALL:
; T1 = STRING POINTER TO THE DESTINATION
; T2 = STRING POINTER TO FIELD RECEIVED
; CALL PRSNAM
;
;VARIABLES RETURNED ON SUCCESSFUL COMPLETION
; DESTINATION CONTAINS THE MS STRING
; TEMP1 = HOST
; TEMP2 = USER NAME
; T1 = UPDATED STRING POINTER
;
;RETURNS:
; +1 ALWAYS
PRSNAM:
ACVAR <SPTR,DPTR> ; STORAGE FOR SOURCE/DEST. POINTERS
MOVEM T1,DPTR ; SAVE DESTINATION POINTER
MOVEM T2,SPTR ; SAVE SOURCE POINTER
PRSNM1: MOVE T1,[POINT 7,TEMP2] ; GET POINTER TO WHERE TO STORE STRING
PRSNM2: ILDB T3,SPTR ; GET CHARACTER
JUMPE T3,PRSNMD ; NULL, DONE
CAIN T3,":" ; END OF NODE SPECIFIER
JRST [ ILDB T3,SPTR ; YES, EAT NEXT COLON
SETZ T3, ; TERMINATE STRING
IDPB T3,T1
HRROI T1,TEMP1 ; UPDATE ORIGINATING HOST
HRROI T2,TEMP2
SETZB T3,T4
SOUT
JRST PRSNM1 ]
IDPB T3,T1 ; SAVE CHARACTER IN TEMP2
JRST PRSNM2
PRSNMD: IDPB T3,T1 ; TERMINATE STRING
MOVE T1,DPTR ; BUILD STRING IN DESTINATION BUFFER
HRROI T2,TEMP2 ; OUTPUT USER NAME
SETZB T3,T4
SOUT%
HRROI T2,[ASCIZ/ AT /] ; OUTPUT SEPARATOR
SOUT%
HRROI T2,TEMP1 ; OUTPUT NODE NAME
SOUT%
RET ; SUCCESS RETURN
;Routine to parse addressing of VAX mail and build TO string in TOOBUF
;
;CALL:
; ATMBUF = ADDRESS STRING RECEIVED FROM THE VAX
; CALL PRSUSR
;
;VARIABLES RETURNED ON SUCCESS:
; TEMP1 = NODE OF RECIPIENT
; TEMP2 = NAME OF RECIPIENT
; T1 = USER NUMBER IF ON CURRENT NODE OR
; TBLUK ENTRY IF ON A REMOTE NODE OR
; -1 IF ON A REMOTE NODE ALREADY RECEIVEING MESSAGE
;
;RETURNS:
; +1: ERROR, MAIL WAS ADDRESSED TO THIS NODE AND USER WAS UNKNOWN
; +2: OK, ALL RETURNED VARIABLES VALID
PRSUSR:
ACVAR <PRSTMP> ; TEMPORARY STORAGE
MOVE T1,TOOPTR ; GET POINTER TO TOOBUF
SKIPN TOOBUF ; SKIP IF TOOBUF NOT EMPTY
JRST PRSUS1
SOSN TOOCNT ; SUBTRACT FROM COUNT/LINE - SKIP IF .NE. 0
JRST [ HRROI T2,[ASCIZ/,
/] ; START A NEW LINE
SETZB T3,T4
SOUT%
MOVEI T2,3 ; RESET COUNT OF USERS PER LINE IN TOOBUF
MOVEM T2,TOOCNT
JRST PRSUS1 ]
HRROI T2,[ASCIZ/, /] ; OUTPUT SEPARATOR
SETZB T3,T4
SOUT%
PRSUS1: MOVEM T1,TOOPTR ; SAVE STRING DESTINATION POINTER
HRROI T1,TEMP1 ; SETUP DEFAULT HOST
HRROI T2,OURNAM
SETZB T3,T4
SOUT%
MOVE T1,TOOPTR ; GET DESTINATION POINTER
MOVE T2,[POINT 7,ATMBUF] ; GET POINTER IN INPUT STRING
CALL PRSNAM ; GET TOPS-20 MS STRING
MOVEM T1,TOOPTR ; SAVE POINTER TO TOOBUF
HRROI T1,OURNAM ; GET POINTER TO THIS SYSTEMS NODE NAME
HRROI T2,TEMP1 ; GET HOST NAME FROM FIELD
STCMP% ; IS MESSAGE FOR THIS HOST ?
JUMPE T1,PRSUS2 ; JUMP IF FOR THIS HOST
;MAIL IS FOR A REMOTE HOST. SETUP TO QUEUE MESSAGE.
MOVEI T1,NODTAB ; GET START OF NODE TABLE
HRROI T2,TEMP1 ; GET NODE SENDING TO
TBLUK% ; IS MAIL ALREADY BEING QUEUE TO THIS NODE ?
TXNE T2,TL%EXM ; SKIP IF NOT
JRST [ SETO T1, ; YES, RETURN FLAG SAYING SO
RETSKP ] ; AND GIVE SUCCESS RETURN
HLRZ T2,NODTAB ; CREATE ADDRESS TO STORE NODE STRING
ASH T2,1
MOVEI PRSTMP,NODSTR(T2) ; SAVE ADDRESS OF NODE STRING
HRRO T1,PRSTMP ; PUT NODE NAME INTO NODE STRING TABLE
HRROI T2,TEMP1
SETZB T3,T4
SOUT%
MOVEI T1,NODTAB ; ADD ENTRY TO NODTAB FOR TBLUK
HRLZ T2,PRSTMP
TBADD% ; ADD IT IN
RETSKP ; RETURN ADDRESS OF TBLUK ENTRY
;MAIL IS FOR THIS SYSTEM. CHECK TO SEE IF USER NAME IS VALID.
PRSUS2: HRROI T2,TEMP2 ; POINT TO USER NAME STRING
MOVX T1,RC%EMO ; EXACT MATCH ONLY
RCUSR% ; IS THIS USER NAME VALID ?
ERJMP R ; NO, ERROR
TXNE T1,RC%NOM ; SKIP IF USERNAME FOUND
RET ; NO SUCH USER - ERROR
MOVE T1,T3 ; RETURN DIRECTORY NUMBER IN T1
RETSKP ; RETURN SUCCESS
; Here To Actually Append The Mail To Users' Mail.txt Files
; Also Type Annoying Message On Their Terminal If They'Re Logged In
; Returns +1: Problems Of Some Sort
; +2: Ok
Mailit: Hrroi T1,Frmmsg ; Build Annoying Msg To Splat Across Screems
Hrroi T2,[Asciz /
[You Have Netmail From /]
Setzb T3,T4
Sout%
Hrroi T2,Frmbuf ; Name Of Sender
Sout%
Hrroi T2,[Asciz/ At /]
Setz T3,
Sout%
Seto T2,
Move T3,[Ot%nda!Ot%12h!Ot%nsc!Ot%scl]
Odtim%
Hrroi T2,[Asciz /]
/]
Setz T3,
Sout%
Setzb P1,P2 ; Init Index And Failure Flag
Mailt1: Move T1,Ulist(P1) ; Get Next Recipient
Jumpe T1,Mailt5 ; End Of List
Aoje T1,Mailt2 ; Jump if already queued
Sos T1
Call Sendit ; Use Code Stolen From Mailer To Do It
Jrst Mailt3 ; Send failure
Mailt2: Vaxsuccess
Aoja P1,Mailt1
Mailt3: Seto P2, ; Remember That A Failure Occured
Hrroi T1,Temp1 ; Build error string for VAX
Hrroi T2,[Asciz/%SNDERR - Unable to send message to /]
Sout%
Skipl T2,Ulist(P1) ; Get dirnum/pointer
Jrst [ Hlro T2,0(T2)
Sout%
Jrst Mailt4 ]
Dirst%
Jerr <Dirst Failure>
Mailt4: Move T1,Netjfn ; Send failure code to VAX
Hrroi T2,[Asciz//]
Movni T3,4
Setz T4,
Sout%
jerr <Error sending failure code on the logical link>
Hrroi T2,Temp1 ; Output error string
Setzb T3,T4
Sout%
jerr <Error sending failure code on the logical link>
Hrroi T2,[0]
Movni T3,1
Setz T4,
Soutr%
jerr <Error sending failure code on the logical link>
Aoja P1,Mailt1
Mailt5: Skipe P2 ; Any Problems?
Jrst Rskp ; Yes, Don'T Log Success Then
Skipn P1 ; Anything Sent?
Jrst [ Call Dtstmp ; Yes, Loc Lack Of Local Users
Log <No Local Electronic Recipients>
Call Lgcrlf
Jrst .+1]
Call Dtstmp ; log success
Log <sent OK>
Call Lgcrlf ; CRLF the log file
Retskp
; Append Mail To User'S Mail File
; Call With User Number Of Recipient In T1
Sendit: Acvar <W6>
Stkvar <<Getsiz,2>,Eofptr,Usrno,Dirnum>
Movem T1,Usrno ; Save Recipients User Number
Skipl Usrno ; Forwarded Mail?
Jrst Quefil ; Yes, queue mail to remote host
Hrroi T1,Filnam ; Where To Build Filespec String
Hrroi T2,[Asciz /Ps:</] ; Prefix
Setzb T3,T4
Sout%
Jerr <Sout Failed At Sendit>
Move W6,T1 ; Preserve String Pointer
Call Dtstmp ; Time Stamp Log File
Hrroi T1,[Asciz /Sending To /]
Call Logmsg
Move T1,Logjfn ; Write Username To Log File
Move T2,Usrno ; ..
Dirst%
Jerr <Dirst Failure To Log File>
Call Lgcrlf ; Crlf To The Log File
Move T1,W6 ; Restore String Pointer
Move T2,Usrno ; Get User Number
Dirst% ; Add User Name
Jerr <Dirst Failure>
Hrroi T2,[Asciz />Mail.txt/]
Setzb T3,T4
Sout%
Jerr <Sout Failed At Sendr 2>
Movx T1,Gj%sht!Gj%del+1
Hrroi T2,Filnam ; Where Filespec Lives
Gtjfn%
Jerr <Can'T Gtjfn Mail.txt>
Movei W6,^D40 ; Number Of 1/2 Sec. Intervals To Wait
; Jrst Sendt1
Sendt1: Move T2,[070000,,300000]
Move T3,T1 ; Preserve Jfn In Case Openf Loses
Openf%
Erjmp [Cain T1,Opnx9 ; Message File Busy?
Sojge W6,[Movei T1,^D500 ; Yes, If Not Too Long
Disms ; Wait 1/2 Second
Move T1,T3 ; Restore Jfn
Jrst Sendt1] ; And Retry Openf
Call Dtstmp
Ret] ;Failure Return
Move T2,[2,,.fbbyv] ; Get 2 Words
Movei T3,Getsiz ; Where To Get It
Gtfdb% ; Read File Data
Load T3,Fb%bsz,Getsiz ; Get File Byte Size
Cain T3,7 ; Already Have 7-Bit Byte Count?
Jrst [ Move T2,1+Getsiz ; Yes, Fetch It
Jrst Sendt2] ; Skip Fancy Gyrations
Movei T2,44 ; No, Get Bits Per Word
Idivi T2,0(T3) ; Compute Total Bytes Per Word
Exch T2,1+Getsiz ; Get Bytes In B
Idiv T2,1+Getsiz ; Compute Words
Imuli T2,5 ; Now Compute # Of Characters
Sendt2: Movem T2,Eofptr ; Save It
Sfptr% ; Set To Eof
Jfcl
Call Capoff ; Disable Caps, So Quota Is Checked
Setom T2 ; Get Date And Time
Movsi T3,(Ot%tmz) ; In This Form
Odtim%
Erjmp Ovrqta ; Error
Movei T2,","
Bout% ; Separate Time From Count
Erjmp Ovrqta ; Error
Rfptr% ; Read Position In File
Jfcl
Addi T2,6 ; At Least 6 Digits For Count
Idivi T2,5 ; Get Part Of Word In C
Movns T3 ; Get Negitive Remainder
Addi T3,5+6 ; Get Width Of Count Field
Hrl T3,T3 ; Get In Right Position For Nout
Txo T3,No%lfl!No%zro ; Put In Leading Zeros
Move T2,Bytcnt ; Number Of Chars
Hrri T3,12 ; In Decimal
Nout%
Erjmp Ovrqta ; Error
Hrroi T2,[Asciz /;000000000000
/]
Movei T3,0 ; Put On The Flag Field
Sout%
Erjmp Ovrqta ; Error
Move T2,[Point 7,Bigbuf]
Movn T3,Bytcnt ; Get Negative Byte Count
Sout%
Erjmp Ovrqta ; Error
Call Capon ; Enable Again
Call Updfil ; Update File Pages
Hrli T1,.fbctl ; Change Status Bits
Movx T2,Fb%del ; Change Deleted Bit
Setz T3, ; Make It A Zero(Undelete)
Txo T1,Cf%nud ; Don'T Update Dir (Sfust/Closf Will)
Chfdb% ; Do It
Movx T2,Fb%prm ; Change Permanent Bit
Movx T3,Fb%prm ; To Be Set
Chfdb%
Movei T1,(T1) ; Jfn Only
Move W6,T1 ; preserve JFN
Hrroi T1,Temp1 ; where to put string
Call Quote ; move ctrl-V'ed "from" string to TEMP1
Move T1,W6 ; restore JFN
Hrli T1,.sflwr ;set last writer
Hrroi T2,Temp1 ;sender string
Sfust%
Jerr <Sfust Failure>
Movei T1,(T1) ; Jfn Only
Closf% ;Close The Output File
Jfcl
Setz W6, ; Init Job Number For Scan
Topdir: Movei T1,0(W6) ; Job Number
Move T2,[-<.jicpj-.jitno+1>,,Gtinf] ; Get Values From Monitor
Movei T3,.jitno ; Get Term # And Logged In Dir
Getji% ; Get Them
Erjmp [Cain T1,Gtjix3 ; Out Of Range?
Jrst Rskp ; Yes, All Done -- Success Return
Aoja W6,Topdir] ; No. Do Next One Then
Skipl <.jicpj-.jitno>+Gtinf ; Is This A Pty?
Aoja W6,Topdir ; Yes. Skip It Then
Dmove T1,Gtinf ; Get Getji Data In Regs
Jumpl T1,[Aoja W6,Topdir] ; If Detached, Go On.
Came T2,Usrno ; Is This Logged Into The Same Dir?
Aoja W6,Topdir ; No. Skip It Then
Tro T1,(1b0) ; Make It A Device Designator
Rfmod% ; Get Mode Bits
Txne T2,Tt%dam ; Is He In Ascii?
Txnn T2,Tt%alk ; Is He Accepting?
Aoja W6,Topdir ; No. Don'T Tell Him Then
Movei T2,.mornt ; See If He Wants Messages
Mtopr%
Jumpn T3,Incdir ; Jump If No Message
Hrroi T2,Frmmsg ; Get Message Block
Ttmsg% ; Send To This User
Incdir: Aoja W6,Topdir ; Do All Jobs
;Sending to a remote host.
Quefil: Seto T1, ; Build file name string for forwarding
Hrroi T2,Dirnum ; Results to DIRNUM
Movei T3,17
Getji%
Jerr <Getji Failure>
Hrroi T1,Filnam
Move T2,Dirnum ; Get name of login directory
Dirst%
Jerr <Dirst Failure>
Hrroi T2,[Asciz/[--Decnet-Mail--]./]
Setzb T3,T4
Sout%
Move T2,Usrno ; Output host message is being forwarded to
Hlro T2,0(T2)
Sout%
Hrroi T2,[Asciz/.-1/]
Setzb T3,T4
Sout%
Call Dtstmp ; Time Stamp Log File
Hrroi T1,[Asciz / Forwarding Mail To /]
Call Logmsg
Move T2,Usrno
Hlro T1,0(T2)
Call Logmsg
Call Lgcrlf
Movx T1,<Gj%sht!Gj%new> ; Get jfn of queue file
Hrroi T2,Filnam
Gtjfn%
Jerr <Can't Gtjfn to forward message>
Movx T2,<Fld(7,Of%bsz)+Of%rd+Of%wr> ; Open queue file
Openf%
Jerr <Can't Openf to forward message>
Call Capoff ; Disable Caps, So Quota Is Checked
Move T2,[Point 7,Bigbuf] ; Shove message into queue file
Movn T3,Bytcnt ; Get negative byte count
Sout%
Erjmp Ovrqta
Call Capon ; Enable Again
Hrli T1,.fbbyv ; Set generation retention count to zero
Txo T1,Cf%nud ; Don't update disk yet
Movx T2,Fb%ret
Setz T3,
Chfdb%
Hrli T1,.fbbyv ; Set file byte size
Txo T1,Cf%nud ; Don't update disk yet
Movx T2,Fb%bsz
Movx T3,<Fld(7,Fb%bsz)>
Chfdb%
Hrli T1,.fbsiz ; Set file byte count
Seto T2,
Move T3,Bytcnt
Chfdb%
Hrrzi T1,(T1) ; Jfn only
Closf% ; Close the output file
Jfcl
MOVE T4,[IORM T3,FLGADR(T1)] ; light it (in case not lit now)
HRRZ T1,DIRNUM ;get directory number
IDIVI T1,^D36 ;get word number in DECNET-MAILER.FLAGS
MOVSI T3,400000 ;bit zero
MOVN T2,T2 ;negate bit number
LSH T3,(T2) ;position bit correctly
XCT T4 ; light or clear it appropriately
RETSKP ;all done
;Here to copy (and quote) "from" string into area pointed to by T1
; Quotes all characters (to save trouble of checking need for it)
QUOTE: MOVE T2,[POINT 7,FRMBUF]
TLC T1,-1 ; lh of byte pointer all ones?
TLCN T1,-1 ; ..
HRLI T1,(POINT 7,) ; yes, make real byte pointer
MOVEI T4,<24*5>-1 ; maximum characters allowed in string
QUOTE1: MOVEI T3,"" ; quote character
IDPB T3,T1 ; stuff it
ILDB T3,T2 ; next char of source string
IDPB T3,T1 ; stuff it
JUMPE T3,[MOVNI T2,1 ; if zero, back up over last ctrl-V
ADJBP T2,T1 ; ..
DPB T3,T1 ; wipe it out with null
RET] ; and return
SOJGE T4,QUOTE1 ; insure no overflow
DIE <QUOTE overflow>
;Routine To Force Write Of Pages Just Written In Case Of Crash
;Call: T1/Jfn
;Return +1: Always
Updfil: Rfbsz% ; Get Byte Size
Jfcl
Movei T3,^D36 ; Bits In A Word
Idivi T3,(T2) ; Compute Bytes In A Word
Movem T3,Temp2 ; Save For Later
Rfptr% ; Get Eof Pointer
Jfcl
Idiv T2,T3 ; Compute Words In File
Skipn T3 ; Even Number Of Words?
Subi T2,1 ; Yes, Don'T Cross Over To Nonex. Page
Move T3,Eofptr ; Get Original Eof Pointer
Idiv T3,Temp2 ; Compute Original Word Count
Lsh T2,-^D9 ; Compute Page Number Just Written
Lsh T3,-^D9 ; Compute Original Last Page Number
Move T4,T2 ; Copy Page No. Just Written
Subi T4,(T3) ; Pages Written
Addi T4,1 ; Plus One For Partial Page
Hrlzs T1 ; Jfn In Lh For Ufpgs
Hrri T1,(T3) ; First Page To Update
Movei T2,(T4) ; Page Count
Txo T2,Uf%now ; Don'T Block
Ufpgs% ; Write These Pages To Disk
Jerr <Ufpgs Failure>
Hlrzs T1 ; Restore T1 To Good State
Ret ; And Return
;Here On Quota Error
; T1/ Jfn
Ovrqta: Call Capon ; Re-Enable Caps
Rfbsz% ; Get Current Byte Size
Jfcl
Movei T3,^D36 ; Compute Bytes Per Word
Idivi T3,(T2) ; ..
Movem T3,Temp2 ; Save
Rfptr% ; Get Current Eof Pointer
Jfcl
Idiv T2,Temp2 ; Compute Words
Lsh T2,-11 ; Make It A Page Number
Move T3,Eofptr ; Get Original Pointer
Idiv T3,Temp2 ; Compute Word Number
Lsh T3,-11 ; Get Page Number
Sub T2,T3 ; Compute No. Of Pages Added
Jumpe T2,Ovrqt2 ; If None Added, All Set
Exch T3,T2 ; Put Count In Proper Register
Txo T3,1b0 ; Repeat Count For Pmap
Hrl T2,T1
Addi T2,1 ; Starting Page
Setom T1
Pmap% ; Zap The File Pages
Hlrz T1,T2 ; Jfn Again
;Extra Pages Now Deleted. Set Byte Count In Fdb
Ovrqt2: Hrli T1,.fbbyv ; Word Containing Byte Size
Movx T2,Fb%bsz ; Set Byte Size
Movx T3,Fld(7,Fb%bsz) ; To 7 Bits
Chfdb% ; If Failed, Quit Now
Erjmp Ovrqt0
Hrli T1,.fbsiz ; Set Size Of File
Seto T2, ; Entire Word
Move T3,Eofptr ; To Original Count
Chfdb% ; Zap
Jfcl
Ovrqt0: Closf% ; Close The File
Jfcl
Call Dtstmp ; Pretty Up The Log File
Move T1,Logjfn
Dirst%
Jerr <Dirst Failure>
Ret
;Open Log File
Opnlog: Movx T1,Gj%sht ; Try Logical Name First
Hrroi T2,[Asciz /Decnet-Log:Vmail.log/]
Gtjfn%
Ercal [Movx T1,Gj%sht ; Failed, Write Onto System:
Hrroi T2,[Asciz /System:Vmail.log/]
Gtjfn
Erjmp Opnerr
Ret]
Movx T2,<070000,,0>+Of%app
Openf% ; Open For Append
Erjmp Opnerr
Hrrz T1,T1 ; Return Jfn Only
Ret
Opnerr: Hrroi T1,[Asciz /Vmail: Can'T Open Log File Because: /]
Esout%
Movx T1,.priou
Hrloi T2,.fhslf
Erstr%
Jfcl
Jfcl
Jrst Fatal
;Time Stamp Log File
Dtstmp: Move T1,Logjfn
Seto T2, ; Current Time
Setz T3, ; Default Format
Odtim%
Erjmp [Hrroi T1,[Asciz /Vmail: Odtim Failed: /]
Esout%
Movx T1,.priou
Hrloi T2,.fhslf
Erstr%
Jfcl
Jfcl
Tmsg <
Dtstmp Called From >
Movx T1,.priou ; Type Pc Of Caller On Terminal
Hrrz T2,(P)
Movx T3,^D8 ; In Octal
Nout%
Jfcl
Jrst Fatal] ; Go Fire Up The World Again
Movei T2," " ; Space
Bout%
Ret
;Write Asciz String Pointed To By T1 To Log File
Logmsg: Move T2,T1 ; Copy String Pointer
Move T1,Logjfn
Setzb T3,T4
Sout%
Jerr <Can'T Write To Log File>
Move T1,T2
Ret
;Crlf To Log File
Lgcrlf: Move T1,Logjfn
Movei T2,15
Bout%
Jerr <Can'T Write To Log File>
Movei T2,12
Bout%
Jerr <Can'T Write To Log File>
Ret
;Write Statistics To Log File
Lstats: Stkvar<Elptm0>
; Move T1,Logjfn
; Move T2,Elptim ; Elapsed Time For Mail Receipt
; Fltr T2,T2 ; Flost It
; Fdvr T2,[100000.0] ; Compute Seconds
; Movx T3,<1b1+Fl%one+Fl%pnt+3b23+3b29>
; Flout% ; Type Seconds
; Erjmp [Haltf] ; Never Happens
; Movem T2,Elptm0 ; Save Time
; Log < Seconds, >
Log < : >
Move T1,Logjfn
Move T2,Bytcnt ; Byte Count
Movx T3,^D10 ; Base 10
Nout%
Erjmp [Haltf]
Log < Chars
>
; Move T1,Logjfn
; Fltr T2,Bytcnt ; Float Byte Count
; Fdvr T2,Elptm0 ; Compute Bytes Per Second
; Movx T3,<1b1+Fl%one+Fl%pnt+5b23+3b29>
; Flout%
; Jerr <Flout Failure
; Log < Chars/Sec/
;>
Ret
;Close Net Connection And Reopen It. Re-Enable For Interrupts
; On Connect Initiate Messages
Clznet: Move T1,Netjfn ; Normal Close
Closf%
jrst [move t1,netjfn
txo t1,cz%abt
closf%
jerr <Abort close failed at CLZNET>
jrst .+1]
Call Opnlsn ; Open Connection Again
Ret ; Return
;Open The Net Connection And Listen For Connect Initiates
Opnlsn: Movx T1,Gj%sht
Hrroi T2,[Asciz /Srv:27/] ; Magic Number For Vax Mail Server
Gtjfn%
Jerr <Can'T Get Net Jfn For Server>
Movx T2,Of%rd!Of%wr!<070000,,0> ; 7-Bit Bytes
Openf%
Jerr <Can'T Open Net Jfn>
Movem T1,Netjfn
Movx T2,.moacn ; Enable For Psi On Network Transitions
Movx T3,0b8+<.mocia>B17+<.mocia>B26 ; Channel Zero
Mtopr%
Movx T1,.fhslf
Movx T2,1b0 ; Activate Channel Zero
Aic%
Ret
;Log Name Of Foreign Host
T4nhst: Setzm Hstnam ; Zero This String
Setzm 1+Hstnam ; ..
Move T1,Netjfn ; Get Net Jfn
Movx T2,.morhn ; Return Host Name
Hrroi T3,Hstnam ; Where To Put It
Mtopr%
Erjmp [Hrroi T1,[Asciz /Unknown-Host/]
Call Logmsg
Ret] ; Log Confusion
Hrroi T1,Hstnam ; Copy Name To Log File
Skipe Dbugsw
Psout%
Hrroi T1,Hstnam ; Copy Name To Log File
Call Logmsg ; ..
Ret
;Set Up To Time Out If Network Too Slow
Timeit: Move T1,[.fhslf,,.timel]
Move T2,[Timen] ; Milliseconds To Allow
Movei T3,1 ; Channel One
Timer%
Jerr <Can'T Time Myself>
Movx T1,.fhslf ; Activate Timer Channel
Movx T2,<1b1>
Aic%
Ret
;Cancel Above Timer Request
Cncltm: Move T1,[.fhslf,,.timal] ; Remove All Pending Timer Requests
Movei T3,1 ; For This Channel
Timer%
Jerr <Can'T Remove Pending Timer Request>
Ret
;Here On Timeout
Timout:
; Call Dtstmp
DIE <Timeout Occured>
;Here If Net Link Dies While Outputting To It
Dmplnk: Cis ; Zap Things
Call Lgcrlf ; Log A Crlf
Movx T1,Cz%abt ; Abort The Net Jfn
Hrr T1,Netjfn ; ..
Closf% ; ..
Jfcl ; Don'T Care
Call Dtstmp
Log <----Connection Aborted
>
Movx T1,.fhslf ; Deactivate Connect Initiate Channel
Movx T2,<1b0> ; ..
Dic% ; ..
Call Cncltm ; Cancel Pending Timer Requests
Move T1,Logjfn ; Close Log File
Closf%
Jfcl
Jrst Vmail0 ; Go Wait For New Mail
;Here On Fatal Wipeout (Jsys Which Can'T Fail Does, For Instance)
Fatal: Movx T1,.fhslf
Dir% ; Disbale Interrupts
Cis% ; Clear Interrupts
Move T1,Netjfn ; Type A Record To Force Net Buffers Out
Hrroi T2,[Asciz /
?Vmail Internal Error/]
Setzb T3,T4 ; Add Question Mark So Mail Isn'T Requeued
Soutr% ; ..
Erjmp .+1
Movei T1,^D5000 ; Wait Five Seconds
Disms%
Movx T1,.fhslf ; Abort All Jfns
Clzff% ; ..
Call Opnlog ; Reopen Log File
Movem T1,Logjfn
Call Lgcrlf
Call Dtstmp
Log <Error Restart...
>
Tmsg <Vmail Error Restart...
>
MOVE T1,LOGJFN
CLOSF
JFCL
Movei T1,^D5000 ; Wait Some More
Disms%
Jrst Vmail ; And Fire Up The World Again
;Disable Capabilities So Quota-Checking Happens
Capoff: Push P,T1 ; Don'T Clobber
Movx T1,.fhslf ; Get My Caps
Rpcap%
Movem T3,Capenb ; Remember For Later
Setz T3, ; No Caps At All
Epcap%
Pop P,T1 ; Restore
Ret
;Re-Enable Caps
Capon: Push P,T1 ; No Clobberage
Movx T1,.fhslf
Move T3,Capenb ; Caps We Had Before
Epcap%
Pop P,T1
Ret
End Vmail