Google
 

Trailing-Edge - PDP-10 Archives - integ_tools_tops20_v7_30-apr-86_dumper - tools/vmail/vmail.mac
There are 6 other files named vmail.mac in the archive. Click here to see a list.
;EMILY::DORK20:<SOURCES>VMAIL.MAC.3 7-Nov-83, Edit by MDLyons
; Increase TIMEN to 10 minutes to minimize the timeouts. Edit 156.
;USER:<TORREY>VMAIL.MAC.5  9-Sep-83 16:18:49 by TORREY
;USER:<TORREY>VMAIL.MAC.4  9-Sep-83 16:16:23 by TORREY
;[JHT] increase other buffers too
;USER:<TORREY>VMAIL.MAC.2  9-Sep-83 15:33:31 by TORREY
;[JHT] increase TMPLEN from 50 to 500 for long VAX record lengths
;PS:<MDLYONS.VMAILR>VMAIL.MAC.7 1-Aug-83 15:34:43, Edit by MDLYONS
; Put in a check for aborted connections at CONCT1 + 3 1/2.
; Make BBFLEN (size of big buffer) really big. Should fix the
;	code..Maybe later... Edit 154.
;LANG:<DYER-BENNET.VMAIL>VMAIL.MAC.9 28-Jul-83 14:36:52, Edit by DYER-BENNET
; Change JERR to DIE at TIMOUT+1.  Edit 153 (from Larry Campbell via
; George Stevens).
;<DYER-BENNET.WORK>VMAIL.MAC.3 28-Jun-83 12:31:37, Edit by DYER-BENNET
; PUT JERR after SOUT at CRLF+3.  Edit 152. (died on KL2102)
;LANG:<DYER-BENNET.VMAIL>VMAIL.MAC.7 21-Mar-83 14:35:43, Edit by DYER-BENNET
; Put JERR after SOUT at REPEAT+22, which died on KL2137 with
; "No such device" error.  Edit 151.
;LANG:<DYER-BENNET.VMAIL>VMAIL.MAC.4  4-Feb-83 10:23:14, Edit by DYER-BENNET
; Put ERJMP after some more JSYS's.  Use Jerr to give more useful
; error messages when things fail.  Edit 150.
;LANG:<DYER-BENNET.VMAIL>VMAIL.MAC.3  3-Feb-83 10:09:29, Edit by DYER-BENNET
; Put ERJMP after two ODTIM's.  Clair Grant reports that the 2102 VMAIL
; hung after failing at one of them.  Edit 147.
;<DYER-BENNET.VANILLA>VMAIL.MAC.2  2-Feb-83 14:18:35, Edit by DYER-BENNET
; Put in edit suggested by STEVENS in FATAL routine to avoid hanging in CLZFF.
; Add ERJMP FATAL to two MTOPR's which Clair Grant says could fail, which
; currently have no error check.
;<STEVENS.VMAILR>VMAIL.MAC.88 27-May-82 15:36:00 Edit by STEVENS
; User name improperly terminated when personal name present.
; Added code to terminate string in PRSNAM.
;<STEVENS.VMAILR>VMAIL.MAC.87 27-May-82 14:47:00 Edit by STEVENS
; Updated the CLZNET routine by stealing the code from NMAIL.
;<STEVENS.VMAILR>VMAIL.MAC.86 26-May-82 22:35:00 Edit by STEVENS
; Fixed initial value of TOOCNT set near PARSE so that 3 names
; appear on the first line of the TO filed.
;<STEVENS.VMAILR>VMAIL.MAC.85 26-May-82 21:22:00 Edit by STEVENS
; Finished adding code to convert RSTS personal names to MS
; format in routine PRSNAM, created subroutine PRSNMS.
; Repaired problem when sending to more than one remote system
; by saving address pointer to node string itself and not the
; pointer to the TBLUK entry.  Routines effected PRSUSR and
; QUEFIL.
; Added dead mans timer in routine TIMOUT to prevent disconnects
; during reception of long messages.  Created variable KEPLIV.
;<STEVENS.VMAILR>VMAIL.MAC.84 25-May-82 21:10:00 Edit by STEVENS
; Removed space in line after header to that header is properly
; terminated after Mailed to field.
; Started adding code to convert RSTS personal names to MS
; format for personal names in routine PRSNAM.
;<STEVENS.VMAILR>VMAIL.MAC.83 19-Jan-82 11:51:00 Edit by STEVENS
; Changed CAME to CAMN at comparison for blank line near REPEAT:
;<STEVENS.VMAILR>VMAIL.MAC.82 07-Jan-82 15:45:00 Edit by STEVENS
; Changed "AT" in from field in routine PRSNMD to "at"
;<STEVENS.VMAILR>VMAIL.MAC.81 04-Jan-82 10:20:00 Edit by STEVENS
; Corrected comparison for blank line near REPEAT:
;<STEVENS.VMAILR>VMAIL.MAC.80 15-Dec-81 15:32:00 Edit by STEVENS
; Added code in conect to ensure link is connected before
; calling parse.
;<STEVENS.VMAILR>VMAIL.MAC.79  2-Nov-81 14:06:00 Edit by STEVENS
; Corrected error in setting decnet-mailer.flags for queued mail
;<STEVENS.VMAILR>VMAIL.MAC.78 30-Nov-81 12:36:00 Edit by STEVENS
; Restart in connection is aborted!!!!!
;<STEVENS.VMAILR>VMAIL.MAC.77 30-Nov-81 10:55:00 Edit by STEVENS
; File queued messages to ps:<spool>
;<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==156

	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
		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
	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 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==500			; Temporary Storage
Natmbf==100			; Length Of Atom Buffer In Words
;[154] Bbflen==40000			; Length Of Big Buffer Into Which Mail Is Read
Bbflen==300000			;[154] Length Of Big Buffer Into Which Mail Is Read
Nfrmbf==70			; Length Of Sender Name Buffer
Timen==^d600000			; 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
Kepliv:	Block 1			; Keep alive count for dead mans timer
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

	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>
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 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 <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,^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
	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
		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
	    Jerr <Couldn't get current date-time at PARSE6+n>

	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
	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
	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

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
;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
	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
;		 ADDRESS WHERE NODE STRING IS STORED 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
	HLRZ  T1,0(T1)		; GET ADDRESS OF NODE STRING
	RETSKP			; RETURN ADDRESS

;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
	    Jerr <Couldn't get current date-time at MAILIT+n> ; [147] This may fail

	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,
	Soutr

	Hrroi T2,Temp1		; Output error string
	Setzb T3,T4
	Soutr

	Hrroi T2,[0]
	Movni T3,1
	Setz  T4,
	Soutr

	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 Sendr>
	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
	  Jerr <Couldn't see if recipient wants terminal messages> ; This could fail...

	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>
	MOVX  T1,RC%EMO		; EXACT MATCH ONLY
	HRROI T2,[ASCIZ/PS:<SPOOL>/] ; GET DIRECTORY NUMBER OF SPOOL
	SETZ  T3
	RCDIR
	TXNE  T1,<RC%NOM!RC%AMB!RC%NMD>	; SKIP IF NO ERRORS
	 JERR <Rcdir failure while translating PS:<SPOOL>>
	MOVEM T3,DIRNUM		; SAVE DIRECTORY NUMBER
	Hrroi T1,Filnam
	Move  T2,Dirnum		; Get name of login directory
	Dirst
	 Jerr <Dirst Failure>
	Hrroi T2,[Asciz/[--Decnet-Mail--]./]
	Setzb T3,T4
	Sout
	Hrro  T2,Usrno		; Output host message is being forwarded to
	Sout
	Hrroi T2,[Asciz/.-1/]
	Setzb T3,T4
	Sout
	Call  Dtstmp		; Time Stamp Log File
	Hrroi T1,[Asciz / Forwarding Mail To /]
	Call  Logmsg
	Hrro  T1,Usrno
	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:	MOVEI T1,^D4000		; Give pipe four seconds to empty
	DISMS			;  ..
	MOVE T1,NETJFN		; normal close
	CLOSF
;	 JERR <Badness while closing NET connection>
	 ERJMP [CALL DTSTMP		; We should complain about these
		LOG <%Close error for net link: >
		MOVE T1,LOGJFN
		HRLOI T2,.FHSLF
		ERSTR
		 JFCL
		 JFCL
		CALL LGCRLF
		MOVE T1,NETJFN
		TXO T1,CZ%ABT		; Try real hard to close it
		CLOSF			;  so we don't eat all job 0 JFNs
		 JFCL
		MOVE T1,NETJFN
		RLJFN
		 JFCL
		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
	 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
	 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
	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
	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
	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
	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  Lgcrlf
	Call  Dtstmp
	Log <Error Restart...
>
	Tmsg <Vmail Error Restart...
>
	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