Title VMAIL - MMAILR / TOPS-20 Mail-11 Listener
Subttl LCampbell/GStevens/DDyer-Bennet/MDLyons/JHTorrey/PLBudne/MRCrispin
Search Macsym,Monsym
.require Sys:Macrel
Sall
.directive Flblst
.text "/NOINITIAL"
.text "VMAIL/SAVE"
IFNDEF OT%822,OT%822==:1
; This program is derived from the VMAIL distributed on the
; "integration tools tape". It listens on DECnet object 27 for mail
; from the VMS MAIL Utility. When a VMS user says "MAIL NODE::USER" A
; connection is established then and there, and text is sent one line
; at a time. A problem is that this server is single thread, and one
; VMS user can tie up the port, making all other mail to the '20
; fail!!
; At the current time the addressee must be a valid TOPS-20 username,
; since the destination is stored as a user number. I never finished
; an interface to MMAILBOX to vaildate full MMAILR addresses.
; Another interesting problem is that there may be no reply path for
; mail. I had thought of taking the VMAILR program and hacking it to
; be the delivery agent for a #Special domain. At BU we run software
; tools mail on most VMS systems, so this is not a problem.
IFNDEF FTRCVD,FTRCVD==1 ;INCLUDE RECIEVED: HEADER
IFNDEF MBXF,MBXF==0 ;INCOMPLETE!!
IFN MBXF,<
.REQUIRE VMAMBX ;INTERFACE TO MMAILBOX
EXTERNAL MBXFRK,MBXVFY
;MBXF
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==6
.mvr==1
.edt==^D82
Loc 137
Exp <.ver>B11+<.mvr>B17+1B18+.edt
Reloc
Define Jerr(String),<
Xlist
IFJER.
Hrroi T1,[Asciz /VMAIL error: /]
Esout
Hrroi T1,[Asciz /String/]
Psout
Hrroi T1,[Asciz / because: /]
Psout
Movx T1,.priou
Hrloi T2,.fhslf
Erstr
Erjmp .+2
Erjmp .+1
Call Dtstmp ;; Log This Lossage Also
Log <String>
Log < Because: >
Move T1,LogJFN
Hrloi T2,.fhslf
Erstr
Erjmp .+2
Erjmp .+1
Jrst Fatal
ENDIF.
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),<
Skipn Dbugsw
IFSKP.
Hrroi T1,[Asciz /String/]
Psout
ENDIF.
Define Debstr(String),<
Skipn Dbugsw
IFSKP.
Hrroi T1,String
Psout
ENDIF.
Define Clrbuf(bufnam,Buflen),<
Setzm Bufnam
Move T1,[Bufnam,,Bufnam+1]
Blt T1,Bufnam+buflen-1
Define Nchar,<
Move T1,NetJFN
Bin
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
Define Vaxerr(Errmsg),<
Move T1,NetJFN
Hrroi T2,[Ascii//]
Movei T3,-4
Setz T4,
Soutr
Move T1,NetJFN
Hrroi T2,[Asciz /Errmsg/]
Setzb T3,T4
Sout
Hrroi T2,Atmbuf
Setzb T3,T4
Sout
Hrroi T2,[Asciz/ At Node /]
Setzb T3,T4
Sout
Hrroi T2,ournam
Setzb T3,T4
Soutr ; force string transmission
Hrroi T2,[0]
Movei T3,-1
Setz T4,
Soutr
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 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
Tmplen==500 ; Temporary Storage
Natmbf==100 ; Length Of Atom Buffer In Words
Bbflen==300000 ;[154] Length Of Big Mail Buffer
Nfrmbf==70 ; Length Of Sender Name Buffer
Timen==^D<10*60*1000> ; Milliseconds Before Sender Declared Tardy
Stklen==200 ; Size Of Stack
Dbugsw: 0 ; -1 If Debug
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
Nodstr: Block ^D200 ; String space for recipient nodes/USERS
NODPTR: BLOCK 1 ;[BUDD] BP INTO NODSTR
Ulist: Block ^D200 ; Where To Store Mailbox Directory Numbers
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
MYPID: BLOCK 1 ;[BUDD] OUR IPCF PID
BUFFER: BLOCK 10 ;[BUDD] IPCF BUFFER
IPCBLK: BLOCK 4 ;[BUDD] IPCF DESCR BLOCK
OURJOB: BLOCK 1 ;[BUDD] OUR JOB NUMBER
QUEJFN: BLOCK 1 ;[BUDD] MMAILR QUEUE JFN
Filnam: Block 1 ;[BUDD] File name for MMAILR QUEUE FILE
Temp1: Block Tmplen
Temp2: Block Tmplen
Stack: Block Stklen ; One Stack For Each Fork
NetJFN: Block 1 ; Network File JFN
LogJFN: Block 1 ; Log File JFN
LOGP: BLOCK 1 ; Non-zero if keeping logs
Ntime: Block 1 ; Time Receipt Of Mail Initiated (For Status)
Elptim: Block 1 ; Elapsed Time For Receipt Of Mail
Kepliv: Block 1 ; Keep alive count for dead mans timer
Bytcnt: Block 1 ; Length Of Mail In Bytes
Capenb: Block 1 ; Saved Capabilities
IFN MBXF,< ;[BUDD]
GOTMBX: BLOCK 1 ;[BUDD] -1 IF HAVE MBX FORK
;[BUDD] MBX
Pc1: Block 1 ; Pc Save Location For Psi Level
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]
GJINF ;[BUDD]
Movem T3,OurJob ;[BUDD]
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
ifjer.
tmsg <?No DECnet in this monitor>
haltf%
endif.
IFN MBXF,SETZM GOTMBX ;[BUDD] CLEAR MBX AVAIL FLAG
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
VMAIL0: Call Opnlsn ; Open Connection And Set Interrupt Up
Move T1,LogJFN ; Close Log File For Perusers
Closf
Erjmp .+1
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
Clrbuf Subbuf,Natmbf
Move T1,NetJFN ; Accept Connection
Movx T2,.mocc
Setzb T3,T4 ; No Additional Data
Mtopr
Jerr <Couldn't accept net connection>
Conct1: Move T1,NetJFN ; Get network link status
Movei T2,.morls
Mtopr
Jerr <Couldn't get link status>
TXNE T3,MO%ABT ; [154] Has the link been aborted?
JRST DMPLNK ; [154] Yes, get rid of it.
Txne T3,Mo%con ; Skip if link not connected
Jrst Conct2
Movei T1,^D1000 ; Wait a second and try again
Disms
Jrst Conct1
Conct2: 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 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
Erjmp .+1
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 <Couldn't read max record size> ; This could fail...
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,3 ; Setup count of recipients per line in TOOBUF
Movem T1,Toocnt
MOVEI T1,NODSTR ;[BUDD]
Movem T1,NodPTR ;[BUDD]
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
Aos Kepliv ; Increment keep alive count
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
CallRet Logmsg]
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
CallRet Logmsg
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
IFN FTRCVD,< ;[BUDD]
Hrroi T2,[Asciz /Received: from /] ;[BUDD] now, write Received line
Setz T3, ;[BUDD]
SOUT ;[BUDD]
Hrroi T2,HSTNAM ;[BUDD]
SOUT ;[BUDD]
HRROI T2,[ASCIZ ' by '] ;[BUDD]
SOUT ;[BUDD]
HRROI T2,OURNAM ;[BUDD]
SOUT ;[BUDD]
Hrroi T2,[Asciz ' using MAIL-11 '] ;[BUDD]
SOUT ;[BUDD]
Seto T2, ;[BUDD] output current date/time
MovX T3,OT%DAY!OT%SPA!OT%TMZ!OT%SCL!OT%822
ODTIM ;[BUDD] RFC 822 standard date
JERR <ODTIM in recieved line failed> ;[BUDD]
Hrroi T2,CRLF0 ;[BUDD]
Setz T3, ;[BUDD]
SOUT ;[BUDD]
;IFN FTRCVD
Hrroi T2,[Asciz /Date: /]
Setz T3,
Sout
Seto T2,
MovX T3,OT%DAY!OT%SPA!OT%TMZ!OT%SCL!OT%822
Odtim
Jerr <Couldn't get current date-time at PARSE6+n>
Hrroi T2,[Asciz/
From: /]
Setz T3,
Sout
Hrroi T2,Frmbuf
Setz T3,
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: /] ;[BUDD]
Setzb T3,T4
Sout
Hrroi T2,Atmbuf
Setz T3,
Sout
Hrroi T2,CRLF0
SOUT
Hrroi T2,CRLF0
SOUT
Move T5,T1
Repeat: Clrbuf Temp1,Tmplen ; Clear storage area
Nrecord <Temp1>,<Tmplen*5-1> ; Get a message line from the VAX
Aos Kepliv ; Increment keep alive count
Camn T3,[-<tmplen*5-1>] ; 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
Jerr <SOUT failed at REPEAT+a few> ; [151] Add error check
Move T5,T1
Crlf: Move T1,T5 ; Output CRLF to BIGBUF
Hrroi T2,[Asciz/
/]
Setzb T3,T4
Sout
Jerr <SOUT failed at CRLF+3> ;[152] Add error check
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," " ; SPACE SEPARATOR?
JRST PRSNM3 ; YES, LOOK FOR PERSONAL NAME
CAIE T3,":" ; END OF NODE SPECIFIER?
IFSKP.
ILDB T3,SPTR ; YES, EAT NEXT COLON
SETZ T3, ; TERMINATE STRING
IDPB T3,T1
HRROI T1,TEMP1 ; UPDATE ORIGINATING HOST
HRROI T2,TEMP2
SOUT
JRST PRSNM1
ENDIF.
IDPB T3,T1 ; SAVE CHARACTER IN TEMP2
JRST PRSNM2
PRSNM3: SETZ T3, ; TERMINATE STRING
IDPB T3,T1
PRSNM4: ILDB T3,SPTR ; GET CHARACTER FROM INPUT STRING
JUMPE T3,PRSNMD ; STRING EXHAUSTED
CAIE T3,42 ; IS CHARACTER START OF PERSONAL NAME?
JRST PRSNM4 ; NO, LOOP TILL STRING EXHAUSTED OR '"' FOUND
MOVE T1,DPTR ; GET DESTINATION POINTER
MOVE T2,SPTR ; GET SOURCE POINTER
SETZ T3,
MOVEI T4,42 ; TILL '"'
SOUT
MOVEI T2," " ; CHANGE '"' TO SPACE
DPB T2,T1
MOVEI T2,"<" ; OUTPUT START OF USERNAME at NODE STRING
IDPB T2,T1
CALL PRSNMS ; CALL ROUTINE TO OUTPUT USERNAME at NODE
MOVEI T2,">" ; OUTPUT END OF USERNAME at NODE STRING
IDPB T2,T1
SETZ T2, ; TERMINATE THE OUTPUT STRING
IDPB T2,T1
RET ; SUCCESS RETURN
PRSNMD: IDPB T3,T1 ; TERMINATE STRING
MOVE T1,DPTR ; BUILD STRING IN DESTINATION BUFFER
CALLRET PRSNMS
ENDAV.
;Routine to create user name at node string in output buffer.
;
;CALL:
; T1 = STRING POINTER TO WHERE TO STORE THE OUTPUT
; TEMP2 = USER NAME
; TEMP1 = NODE NAME
; CALL PRSNMS
;
;VARIABLES RETURNED:
; T1 = UPDATED STRING POINTER
;
;RETURNS:
; +1 ALWAYS
PRSNMS: HRROI T2,TEMP2 ; OUTPUT USER NAME
SETZB T3,T4
SOUT
;; HRROI T2,[ASCIZ/ at /] ; OUTPUT SEPARATOR
;; SOUT
MOVEI T2,"@"
BOUT
HRROI T2,TEMP1 ; OUTPUT NODE NAME
SOUT
HRROI T2,[asciz/.#DECnet/]
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
; PTR TO NODE // '\0' // USER FOR 4N HOST
;
;RETURNS:
; +1: ERROR, MAIL WAS ADDRESSED TO THIS NODE AND USER WAS UNKNOWN
; +2: OK, ALL RETURNED VARIABLES VALID
PRSUSR:
MOVE T1,TOOPTR ; GET POINTER TO TOOBUF
SKIPN TOOBUF ; SKIP IF TOOBUF NOT EMPTY
JRST PRSUS1
SOSE TOOCNT ; SUBTRACT FROM COUNT/LINE - SKIP IF .NE. 0
IFSKP.
HRROI T2,[BYTE (7) ",", "M"-100, "J"-100,
"I"-100]
SETZ T3,
SOUT
MOVEI T2,3 ; RESET COUNT OF USERS PER LINE IN TOOBUF
MOVEM T2,TOOCNT
JRST PRSUS1
ENDIF.
HRROI T2,[ASCIZ/, /] ; OUTPUT SEPARATOR
SETZ T3,
SOUT
PRSUS1: MOVEM T1,TOOPTR ; SAVE STRING DESTINATION POINTER
HRROI T1,TEMP1 ; SETUP DEFAULT HOST
HRROI T2,OURNAM
SETZ T3,
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. GET HOST,,USER STRING POINTERS
HRRZ T4,NODPTR ;GET POINTER TO STRING SPACE
HRRO T1,T4 ;PUT NODE NAME INTO NODE STRING SPACE
HRROI T2,TEMP1
SETZ T3,
SOUT
IDPB T3,T1 ;GET TERMINATOR
HRROI T2,TEMP2 ;GET USER
SOUT
IDPB T3,T1
HRRZM T1,NODPTR
MOVE T1,T4 ;GET STRING POINTER
RETSKP ; RETURN ADDRESS
;MAIL IS FOR THIS SYSTEM. CHECK TO SEE IF USER NAME IS VALID.
PRSUS2:
IFE MBXF,<
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 USER NUMBER IN T1
;IFE MBXF
IFN MBXF,<
PRINTX NEED CODE AT PRSUS2
;IFN MBXF
RETSKP ; RETURN SUCCESS
; Here To create MMAILR queue file
; Returns +1: Problems Of Some Sort
; +2: Ok
Mailit: Hrroi T1,FILNAM
Hrroi T2,[Asciz 'MAILQ:[--QUEUED-MAIL--].NEW-']
Setz T3,
SOUT
Move T2,T1
GTAD
Exch T1,T2
Movei T3,10
NOUT
Trn
Hrroi T2,[Asciz '-VMAIL-J']
Setz T3,
SOUT
Move T2,OURJOB
Move T3,[3,,^D10]
NOUT
Trn
Hrroi T2,[Asciz '.-1;P770000']
Setz T3,
SOUT
Idpb T2,T3
Movsi T1,(GJ%SHT+GJ%FOU)
Hrroi T2,FILNAM
GTJFN
JERR <Could not get queue JFN>
Movem T1,QUEJFN
Move T2,[fld(7,OF%BSZ)+OF%WR]
OPENF
JERR <Could not open queue JFN>
Hrroi T2,[Asciz ' =NET-MAIL-FROM-HOST:']
Setz T3,
SOUT
Hrroi T2,HstNam
SOUT
Hrroi T2,CRLF0
SOUT
Hrroi T2,[Asciz ' =RETURN-PATH:']
SOUT
Hrroi T2,FRMBUF
SOUT
Hrroi T2,CRLF0
SOUT
;; This is not documented -- but it makes MMAILR splat your TTY right!
Hrroi T2,[Asciz ' _']
SOUT
Hrroi T2,HstNam
SOUT
Hrroi T2,[ASCIZ/.#DECnet
/]
SOUT
Move T3,[Point 7,FrmNam]
DO.
Ildb T2,T3
Jumpe T2,ENDLP.
Cain T2," "
EXIT.
BOUT
LOOP.
OD.
Hrroi T2,CRLF0
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
Call Sendit ; ADD NAME TO TOP OF QUEUE FILE
TRN
Mailt2: Vaxsuccess
Aoja P1,Mailt1
Mailt5: Jumpn P2, Rskp ; Don'T Log Success on error
;; Skipe P1 ; Anything Sent?
;; IFSKP.
;; Call Dtstmp ; Yes, Loc Lack Of Local Users
;; Log <No local electronic recipients>
;; ENDIF.
Move T1,QUEJFN ; Get MMAILR queue JFN
;;[76] Hrroi T2,CRLF0
;;[76] Setz T3,
;;[76] SOUT ;Sendit now has been fixed!!
Movei T2,"L"-100
BOUT
Hrroi T2,CRLF0
SOUT
Move T2,[Point 7,Bigbuf] ; Shove message into queue file
Movn T3,Bytcnt ; Get negative byte count
SOUT
Erjmp .+1
CLOSF
TRN
CALL WAKEUP
Retskp
; Append Mail To User'S Mail File
; Call With User Number Of Recipient In T1
Sendit: Stkvar <Usrno>
Movem T1,Usrno ; Save Recipients User Number
Jumpg T1,Quefil ; 4n host
Move T1,QueJFN ; Get QUEUE file
Movei T2,"L"-100 ; Get <FF>
BOUT
Hrroi T2,OurNam
Setz T3,
SOUT
Hrroi T2,CRLF0
SOUT
Move T2,UsrNo
DIRST
ERJMP .+1 ;[76] DIRST% always gives +1 return
Hrroi T2,CRLF0
SOUT
Retskp
;Sending to a remote host.
Quefil: MOVE T1,QUEJFN
MOVEI T2,"L"-100
BOUT
HRRO T2,USRNO ;GET HOST BP
SETZ T3,
SOUT
MOVEM T2,USRNO ;SAVE BP TO USER
HRROI T2,CRLF0
SOUT
MOVE T2,USRNO ;GET USER BP
SOUT
HRROI T2,CRLF0
SOUT
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,"V"-100 ; 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>
;Open Log File
Opnlog: MOVX T1,.NULIO ; No logs unless
SKIPN LOGP ; LOGP is set non-zero
RET ; Oh well
Movx T1,Gj%sht ; Try Logical Name First
Hrroi T2,[Asciz /MAIL:VMAIL.LOG/]
GtJFN
Erjmp Opnerr
Movx T2,<070000,,0>+Of%app
Openf ; Open For Append
Erjmp Opnerr
Ret
Opnerr: Hrroi T1,[Asciz /VMAIL: Can't open log file because: /]
Esout
Movx T1,.priou
Hrloi T2,.fhslf
Erstr
Erjmp .+1
Erjmp .+1
Jrst Fatal
;Time Stamp Log File
Dtstmp: Move T1,LogJFN
HRROI T2,[ASCIZ/
/]
SETZ T3,
SOUT%
Jerr <Can't write to log file>
Seto T2, ; Current Time
Odtim
IFJER.
Hrroi T1,[Asciz /VMAIL: Odtim Failed: /]
Esout
Movx T1,.priou
Hrloi T2,.fhslf
Erstr
Erjmp .+2
Erjmp .+1
Tmsg <
DTSTMP called from >
Movx T1,.priou ; Type Pc Of Caller On Terminal
Hrrz T2,(P)
Movx T3,^D8 ; In Octal
Nout
Erjmp .+1
Jrst Fatal ; Go Fire Up The World Again
ENDIF.
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
;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
Jerr <NOUT failure>
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: MOVEI T1,^D4000 ; Give pipe four seconds to empty
DISMS ; ..
MOVE T1,NETJFN ; normal close
CLOSF
IFJER.
CALL DTSTMP ; We should complain about these
LOG <%Close error for net link: >
MOVE T1,LOGJFN
HRLOI T2,.FHSLF
ERSTR
ERJMP .+1
ERJMP .+1
MOVE T1,NETJFN
TXO T1,CZ%ABT ; Try real hard to close it
CLOSF ; so we don't eat all job 0 JFNs
ERJMP .+1
MOVE T1,NETJFN
RLJFN
ERJMP .+1
ENDIF.
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!<100000,,0>
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
Jerr <Can't enable for PSI on network transitions>
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
IFJER.
Hrroi T1,[Asciz /???/]
Callret Logmsg ; Log confusion
ENDIF.
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
Skipn KEPLIV ; Skip if still alive
Die <Timeout Occured> ; [153] No activity, dead
Setzm KEPLIV ; Clear keep alive flag
Push P,T1 ; Save ACs before calling Timeit
Push P,T2
Push P,T3
Call Timeit ; Start new timer
Pop P,T3 ; Restore ACs before resuming
Pop P,T2
Pop P,T1
Debrk ; Allow things to continue
;Here If Net Link Dies While Outputting To It
Dmplnk: Cis ; Zap Things
Movx T1,Cz%abt ; Abort The Net JFN
Hrr T1,NetJFN ; ..
Closf ; ..
Erjmp .+1 ; 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
Erjmp .+1
; Jrst VMAIL0 ; Go Wait For New Mail
Jrst VMAIL ; Restart on connection abort
;Here On Fatal Wipeout (Jsys Which Can'T Fail Does, For Instance)
Fatal: Movx T1,.fhslf
Dir ; Disbale Interrupts
Cis ; Clear Interrupts
; Remove out-of-synch message on fatal error
;; 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
skipe t1,logJFN
Closf
Erjmp .+1
setzm logJFN
Movx T1,.fhslf!cz%abt ; Abort All JFNs
Clzff ; ..
ERJMP .+1 ; Ignore errors in the fatal error routine
Call Opnlog ; Reopen Log File
Movem T1,LogJFN
Call Dtstmp
Log <Error restart...
Tmsg <VMAIL error restart...
Move T1,LogJFN
CLOSF%
ERJMP .+1
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
CRLF0: ASCIZ /
/
; FROM DMASER.MAC
A==1
B==2
C==3
WAKEUP: SKIPE T2,MYPID ; have a PID already?
TDZA T1,T1 ; yes, use it
MOVX T1,IP%CPD ; no, create a PID
MOVEM T1,IPCBLK+.IPCFL
MOVEM T2,IPCBLK+.IPCFS ; PID to use if one there
SETZM IPCBLK+.IPCFR ; send to INFO
MOVX T1,<.IPCI2+3,,BUFFER> ; length of INFO msg,,where INFO msg is
MOVEM T1,IPCBLK+.IPCFP
MOVX T1,.IPCIW ; return PID associated with name
MOVEM T1,BUFFER+.IPCI0
SETZM BUFFER+.IPCI1 ; duplicate copy not needed
DMOVE T1,[ASCII/[SYSTEM]MM/] ; 1st part of PID to look up
DMOVEM T1,BUFFER+.IPCI2
MOVE T1,[ASCII/AILR/] ; 2nd part of PID to look up
MOVEM T1,BUFFER+.IPCI2+2
MOVX T1,.IPCFP+1 ; length of block
MOVEI T2,IPCBLK ; get MMailr's PID
MSEND%
ERJMP R ; looks like INFO isn't there
MOVE T1,IPCBLK+.IPCFS ; get the PID I made
MOVEM T1,MYPID ; remember it for next time
DO.
SETZM IPCBLK+.IPCFL ; no flags
SETZM IPCBLK+.IPCFS ; any sender
MOVE T1,MYPID ; I'm the receiver
MOVEM T1,IPCBLK+.IPCFR
MOVX T1,<10,,BUFFER> ; place to put the reply
MOVEM T1,IPCBLK+.IPCFP
MOVX T1,.IPCFP+1 ; length of block
MOVEI T2,IPCBLK ; get reply from INFO
MRECV%
ERJMP R ; failure irrelevant here
LOAD T1,IP%CFC,IPCBLK+.IPCFL ; see who sent message
CAIE T1,.IPCCC ; from <SYSTEM>IPCF?
CAIN T1,.IPCCF ; no, from <SYSTEM>INFO?
IFSKP.
LOOP. ; no, get another message
ENDIF.
ENDDO.
JN <IP%CFE,IP%CFM>,IPCBLK+.IPCFL,R ; give up if undeliverable
SETZM IPCBLK+.IPCFL ; no flags
MOVE T1,MYPID ; I'm the sender
MOVEM T1,IPCBLK+.IPCFS
MOVE T1,BUFFER+.IPCI1 ; MMailr is the recipient
MOVEM T1,IPCBLK+.IPCFR
MOVX T1,<1,,BUFFER> ; one word from BUFFER
MOVEM T1,IPCBLK+.IPCFP
MOVX T1,'PICKUP' ; magic word to wake up MMailr
MOVEM T1,BUFFER
MOVX C,^D20
DO.
MOVX T1,.IPCFP+1 ; length
MOVEI T2,IPCBLK ; send wakeup to MMailr
MSEND%
IFJER.
MOVEI T1,^D1000 ; failed, wait a bit
DISMS%
SOJG C,TOP. ; try a few times
RET ; failed, give up
ENDIF.
ENDDO.
MOVX T1,.MUQRY ; query function for MUTIL%
MOVEM T1,BUFFER
MOVE T1,MYPID ; query packets for our PID
MOVEM T1,BUFFER+1
MOVX C,^D20 ; number of retries
DO.
MOVX T1,.IPCFP+2 ; number of words to return
MOVEI T2,BUFFER ; argument block in BUFFER
MUTIL%
IFJER.
MOVEI T1,^D1000 ; wait a bit
DISMS%
SOJG C,TOP. ; retry a few times
RET
ENDIF.
ENDDO.
DO.
SETZM IPCBLK+.IPCFL ; no flags
SETZM IPCBLK+.IPCFS ; sender is filled in by monitor
MOVE T1,MYPID ; I'm the receiver
MOVEM T1,IPCBLK+.IPCFR
MOVX T1,<10,,BUFFER> ; where MMailr reply will go
MOVEM T1,IPCBLK+.IPCFP
MOVX T1,.IPCFP+1 ; size of block
MOVEI T2,IPCBLK ; get reply from MMailr
MRECV%
ERJMP .+1 ; error uninteresting here
LOAD T1,IP%CFC,IPCBLK+.IPCFP ; get sender code
IFN. T1 ; special sender?
CAIE T2,.IPCCF ; from <SYSTEM>INFO
CAIN T2,.IPCCP ; or private <SYSTEM>INFO?
LOOP. ; yes, try for another message
ENDIF.
ENDDO.
RET
End VMAIL