1
0
mirror of https://github.com/PDP-10/its.git synced 2026-01-19 09:29:15 +00:00
PDP-10.its/src/sysnet/mails.54
2018-10-09 18:36:34 +02:00

585 lines
13 KiB
Plaintext
Executable File
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

;;;-*- Mode:MIDAS -*-
title MAILS - Chaosnet Mail Server
f=0
a=1
b=2
c=3
d=4
e=5
t=10
tt=11
p=17
call==:<pushj p,>
ret==:<popj p,>
calret==:jrst
.insrt system;chsdef
$$hst3==1
$$chaos==1
$$arpa==1
$$hstmap==1
$$ownhst==1
$$hostnm==1
.insrt sysnet;netwrk
$$out==1
$$outf==1
$$outt==1
$$outz==1
$$rfc==1
.insrt dsk:syseng;datime
nw%chs==7 ;standard network number for chaosnet
dskoch==0 ;output channel for mail queue file
errich==1 ;input channel for ERR: device
dski==2 ;input channel for HOSTS3
chaich==10 ;chaosnet input channel
chaoch==11 ;chaosnet output channel
ranch==12 ;random channel
define punt &string
jrst [ movei tt,<.length string>
move t,[440700,,[ascii string]]
calret refuse ]
termin
;;;interrupt handler
tsint: loc 42
-tsintl,,tsint
loc tsint
p
%pirlt ? 0 ? -1 ? -1 ? timer ;handle realtime clock
%piioc ? 0 ? -1 ? -1 ? iocerr ;handle ioc errors
tsintl==.-tsint
;;;internal error handler
die: 0 ;jsr here
skipe debug
.value
passon: .logout ;natural causes
.value
sndpkt: setz ? 'PKTIOT ? movei chaoch ? setzi chapkt
rcvpkt: setz ? 'PKTIOT ? movei chaich ? setzi chapkt
;;;main program
go: .close 1, ;this can still be open from loading us
move p,[-npdl,,pdl-1]
.suset [.roption,,t]
tlo t,optint ;new style interrupts
.suset [.soption,,t]
move tt,[%rlfls\%rlset,,tick]
.realt tt,
.suset [.smask,,[%pirlt\%piioc]] ;arm interrupts
.call [setz ? 'CHAOSO ? movei chaich ? movei chaoch ? setzi 5]
jsr die
move t,[.byte 8 ? %colsn ? 0 ? 0 ? 4]
movem t,chapkt
move t,[.byte 8 ? "M ? "A ? "I ? "L]
movem t,chapkt+%cpkdt
rfcwat: .call sndpkt
jsr die
movei t,30.*60.
skipe debug
hrloi t,177777 ;wait forever if debugging
.call [setz ? 'NETBLK ? movei chaich ? movei %cslsn ? t ? setzm t]
jsr die
caie t,%csrfc ;did we get an rfc for this?
jsr die
.call rcvpkt ;yes, read it in
jsr die
okayp: ldb t,[chapkt+$cpksa] ;get source host address
movem t,fgnhst
call bloatp ;Don't accept mail if directory is full
punt "Sorry, our mail system is too busy right now"
call asshol ;Don't accept mail from nasty hosts
punt "Service has been administratively denied to your host."
move t,fgnhst
move tt,[sixbit /000C00/] ;convert host number to sixbit
dpb t,[220300,,tt]
lsh t,-3
dpb t,[300300,,tt]
lsh t,-3
dpb t,[360300,,tt]
.suset [.ruind,,t] ;incoroporate user index also
dpb t,[000300,,tt]
lsh t,-3
dpb t,[060300,,tt]
move t,tt ;save copy for xuname
movei a,100(tt) ;loop only 100 times
skipe debug ;If debugging
jrst accept ; just get with it.
login: cain tt,(a)
jsr die ;can't log in, must be broken somehow
.call [setz
sixbit /LOGIN/
tt ? [sixbit /CHAOS/] ? setz t]
aoja tt,login ;error, perhaps need to try other uname
.suset [.sjname,,[sixbit /MAIL/]]
.call [setz ? 'DETACH ? movei %jself ? andi 3 ]
jsr die
;;;looks ok to accept the rfc
accept: .call [ setz
sixbit /OPEN/
movsi .uao
moves errcod
movei dskoch
[sixbit /DSK/]
[sixbit /_MAILS/]
[sixbit /OUTPUT/]
setz [sixbit /.MAIL./]]
jrst calerr ;error opening file, return CLS
movei a,[asciz /NET-MAIL-FROM-HOST:/]
call dsksou
ldb a,[chapkt+$cpksa] ;foreign host
hrli a,nw%chs_9
call dsknou ;output number
movei a,[asciz /
/]
call dsksou
movei t,%coopn
dpb t,[chapkt+$cpkop]
.call sndpkt
jsr die
;;;read the names of all the recipients
rcplup: call charch ;get a character
jsr die
cain b,215 ;end of line
jrst txtmsg ;yes, go get text of message
push p,b
movei a,[asciz /RCPT:/]
call dsksou
pop p,b
namlup: call dskwch
call charch
jsr die
caie b,215 ;end of one?
jrst namlup ;no, keep reading this name
rcplp1: movei a,[asciz /
/]
call dsksou ;end line
movei a,[asciz /+Recipient name accepted./]
call netsou
jrst rcplup ;go get some more
;;; Now make up a "Received from" line and output the msg TEXT.
txtmsg: move d,[440700,,rcvfbf] ;Received from buffer.
move a,[440700,,[asciz "TEXT;-1
Received: from "]]
call aszcpy
movei a,hstpag ;Map in the HOSTS3 database.
movei b,dski
call netwrk"hstmap
jfcl
hrrz b,fgnhst ;Get user host addr from packet.
ior b,[netwrk"nw%chs] ;Host is on Chaosnet.
skipe netwrk"hstadr ;If host table is not available
movem d,e ;Don't smash Bp.
call netwrk"hstsrc ; or foreign host name unknown
jrst [ move d,e
call octdpb ; just use octal chaos addr as name.
jrst txtms1]
hrli a,440700 ;Put in host name if known.
move d,e
call aszcpy
txtms1: move a,[440700,,[asciz " by "]]
call aszcpy
move a,[netwrk"nw%chs]
call netwrk"ownhst ;Find our own addr on Chaosnet.
.lose ; (Which we are obviously on).
move b,a
skipe netwrk"hstadr ;If not HOSTS3 use number.
movem d,e
call netwrk"hstsrc
jrst [ move d,e
call octdpb
jrst txtms2]
hrli a,440700 ;Put in host name if known.
move d,e
call aszcpy
txtms2: move a,[440700,,[asciz " via Chaosnet; "]]
call aszcpy
call datime"timget
camn a,[-1]
jrst [ move a,[440700,,[asciz "time unknown"]]
call aszcpy
jrst txtms3 ]
call datime"timrfc ;7 AUG 1984 08:31:12 EDT
txtms3: move a,[440700,,[asciz "
"]]
call aszcpy
movei t,0 ;Then tie off.
idpb t,d
movei a,rcvfbf
call dsksou ;Write the mess out.
txtlp1: call charch ;get next character
jrst txtlp2 ;eof, finish up
cain b,215 ;cr?
jrst [ movei b,15
call dskwch
movei b,12
jrst .+1]
call dskwch ;output it
jrst txtlp1
txtlp2: call dskwbf ;force out buffered file output
.call [ setz
sixbit /RENMWO/
moves errcod
movei dskoch
[sixbit /MAIL/]
setz [sixbit />/]]
jrst calerr
.call [ setz ;Write out directory to disk
sixbit /FINISH/
moves errcod
setzi dskoch ]
jrst calerr
.call [ setz
sixbit /CLOSE/
moves errcod
setzi dskoch]
jrst calerr
movei a,[asciz /+Mail queued successfully./]
call netsou
.call [ setz
sixbit /FINISH/
setzi chaoch]
jrst passon
.close chaoch,
.close chaich,
jrst passon
;;;ioc error comes here
iocerr: aosn iocflg ;recursive ioc error?
jsr die ;yes, just die
.suset [.rbchn,,t]
caie t,dskoch ;only meaningful for dsk output channel
jsr die ;else just go away
setom iocflg ;mark to detect recursive ioc errors
move a,-2(p) ;previous DF1 word
.suset [.sdf1,,a]
move a,-1(p) ;previous DF2 word
.suset [.sdf2,,a]
jrst dskerr
;;;error opening, or ioc error, return a CLS of the error message
calerr: movei tt,3 ;get error from .call
skipa t,errcod
dskerr: movei tt,2 ;enter here with offending channel in t
snderr: .call [ setz
sixbit /OPEN/
movsi .uai
movei errich
[sixbit /ERR/]
movei (tt)
setz t]
jsr die
move a,[441000,,chapkt+%cpkdt]
movei b,0
snderl: .iot errich,tt
caige tt,40 ;stop on first control char
jrst snderc
idpb tt,a
aoja b,snderl
snderc: .close errich,
dpb b,[chapkt+$cpknb]
movei b,%cocls
dpb b,[chapkt+$cpkop]
.call sndpkt
jsr die
jrst passon
;;;output a string to the network, address of asciz string in a, should be short since this
;;;is slow. follows string with newline.
netsou: hrli a,440700
netso1: ildb b,a
jumpe b,netso2
.iot chaoch,b
jrst netso1
netso2: .iot chaoch,[215] ;newline
.nets chaoch,
ret
;;;output a string to the mail file, address of asciz string in a
dsksou: hrli a,440700
dskso1: ildb b,a
jumpe b,cpopj
call dskwch
jrst dskso1
;;;output a number to the mail file, number in a
dsknou: jumpe a,cpopj
idivi a,10
push p,b
call dsknou
pop p,b
addi b,"0
call dskwch
cpopj: ret
;;; Deposit number in B as octal down ASCII Bp in D.
octdpb: move t,b
idivi t,8.
octdp1: addi tt,"0
caile tt,"9
addi tt,<"A-10.-"0>
jumpe t,octdp2
hrlm tt,(p)
idivi t,8.
call octdp1
hlrz tt,(p)
octdp2: idpb tt,d
ret
;;; Copy ASCIZ string from A down D.
aszcpy: ildb t,a
jumpe t,cpopj
idpb t,d
jrst aszcpy
;;;get a character from the network, skip returns with char in b, single
;;; return for eof
charch: sosge netcnt ;still some characters in the buffer?
jrst charcb ;no, get a new buffer
ildb b,netbfp
cpop1j: aos (p)
ret
charcb: .call rcvpkt ;refill buffer, actually read another packet
jsr die
setom alive ; Remember that we saw signs of life
ldb t,[chapkt+$cpkop]
cain t,%coeof ;eof?
ret ;yes, single return for that
caige t,%codat ;must otherwise be data
jsr die
move t,[440800,,chapkt+%cpkdt]
movem t,netbfp
ldb t,[chapkt+$cpknb]
movem t,netcnt
jrst charch ;go return first char
;;;output a character to the disk file, character in b
dskwch: idpb b,dskbfp
sosle dskcnt ;room in output buffer for more?
ret ;yes, return
dskwbf: move t,[440700,,dskbuf] ;force out buffered disk output
movem t,dskbfp
movei tt,dbfsiz
subm tt,dskcnt
exch tt,dskcnt ;get count of characters to output
.call [ setz
sixbit /SIOT/
moves errcod
movei dskoch
t ? setz tt]
jrst calerr
ret
refuse: dpb tt,[chapkt+$cpknb]
movei tt,%cocls
dpb tt,[chapkt+$cpkop]
hrli t,440700
move a,[440800,,chapkt+%cpkdt]
refus1: ildb tt,t
idpb tt,a
jumpn tt,refus1
.call sndpkt
jsr die
jsr die
;;;Various checks to see if we want the mail or not
; Refuse to accept mail if mailer directory is close to full.
; This is an attempt to avoid bloating the mailer so the dir fills up and
; it dies needing human intervention.
.INSRT DSK:SYSENG;FSDEFS >
.VECTOR UFD(<LUFD==:2000>+1) ; OK, so the server is a page larger now...
UFDBMX==:<LUFD-UDDESC>*UFDBPW ; Max number of bytes in a directory
IFN UFDBYT-6, .ERR UFDBYT HAS CHANGED!
UFDBPS: 440600,,UFD+UDDESC
360600,,UFD+UDDESC
300600,,UFD+UDDESC
220600,,UFD+UDDESC
140600,,UFD+UDDESC
060600,,UFD+UDDESC
BLOATP: PUSH P,A
PUSH P,B
PUSH P,C
PUSH P,D
PUSH P,E
.CALL [ SETZ ? SIXBIT /OPEN/ ? [.BII,,RANCH] ? [SIXBIT /DSK/]
[SIXBIT /.FILE./] ? [SIXBIT /(DIR)/] ? SETZ [SIXBIT /.MAIL./]]
JRST BLOTP9
MOVE A,[-<LUFD+1>,,UFD]
.IOT RANCH,A
CAME A,[-1,,UFD+LUFD]
JRST BLOTP9
.CLOSE RANCH,
MOVEI C,UFDBMX ; C: available room in bytes
SKIPA A,UFD+UDNAMP ; A: -> current name block
BLOTP1: ADDI A,LUNBLK
CAIL A,LUFD
JRST BLOTP7
SKIPN UFD+UNFN1(A)
JRST BLOTP1
SUBI C,LUNBLK*UFDBPW
MOVE B,UFD+UNRNDM(A)
LDB D,[UNDSCP B]
IDIVI D,UFDBPW
ADD D,UFDBPS(E)
TLNE B,UNLINK
JRST BLOTP5
BLOTP3: ILDB B,D
SOJ C,
JUMPE B,BLOTP1
TRNN B,40
JRST BLOTP3
REPEAT NXLBYT, ILDB B,D ? SOJ C,
JRST BLOTP3
BLOTP5: ILDB B,D
SOJ C,
JUMPE B,BLOTP1
CAIE B,':
JRST BLOTP5
ILDB B,D
SOJA C,BLOTP5
BLOTP7: ; Leave dir 25% free. This is about the right amount of room to
; allow LISTS MSGS to get garbage collected even if it gets huge
; (like 1700 blocks or more). Of course this is a function of how
; fragmented the disk is -- your results may vary...
CAIL C,<UFDBMX*25.>/100.
BLOTP9: AOS -5(P)
POP P,E
POP P,D
POP P,C
POP P,B
POP P,A
POPJ P,
IFN 0,[ ; Old version that tries to count MAIL files.
;Refuse to accept the mail if more than 30 queued mail files.
;Skip if not bloated
;This is an attempt to avoid bloating the mailer so the dir fills
;up and it dies needing human intervention.
bloatp: .call [ setz ? sixbit/OPEN/ ? [.uai,,ranch] ? [sixbit/DSK/]
[sixbit/MAIL/] ? [SIXBIT/>/] ? setz [sixbit/.MAIL./]]
jrst blotp9
.call [ setz ? sixbit/RFNAME/ ? movei ranch
movem b ? movem b ? setzm b ]
.lose %lssys
.close ranch,
.call [ setz ? sixbit/OPEN/ ? [.uai,,ranch] ? [sixbit/DSK/]
[sixbit/MAIL/] ? [SIXBIT/</] ? setz [sixbit/.MAIL./]]
jrst blotp9
.call [ setz ? sixbit/RFNAME/ ? movei ranch
movem c ? movem c ? setzm c ]
.lose %lssys
.close ranch,
;At this point B has the largest version mail request
;and C has the smallest.
trnn b,77 ;Right-justify (can't be zero)
jrst [ lsh b,-6 ? jrst .-1 ]
trnn c,77
jrst [ lsh c,-6 ? jrst .-1 ]
trnn c,7700 ;Make sure 2 digits
tro c,'00
addi c,300 ;Add 30
ldb a,[060600,,c] ;Carry
caile a,'9
addi c,<1_12.>-<':_6>
;Don't worry about additional carries, close enough for gov't work
camg b,c
blotp9: aos (p)
ret
] ; IFN 0
;Feature where we refuse to talk to uncooperative hosts.
;A/ foreign host address
;Skip if the host is OK.
asshol: move t,fgnhst ;Get foreign host.
jumpe t,cpop1j ;If zero, it's OK.
movsi tt,-luzrl ;Get AOBJN ptr to losers.
assho1: camn t,luzrs(tt) ;Is the host a loser?
jrst cpopj ; Yes, non-skip return.
aobjn tt,assho1 ;Else keep checking.
assho8: jrst cpop1j ;Skip return if host is cool.
;;;Timer
tick: 3.*60.*60. ; Three minutes with no activity is the limit.
timer: aosg alive
jrst timerx
skipn debug ; Time ran out, unless debugging
jsr die
timerx: .call [ setz ? sixbit /DISMIS/ ? setz p ]
.lose %lssys
;;;Storage
npdl==37
pdl: block npdl
debug: 0 ;non-zero => .value on barfage
errcod: 0 ;error code
iocflg: 0 ;detect recursive ioc errors
netcnt: 0 ;number of characters in network buffer
netbfp: 0 ;byte pointer to that
dskcnt: dbfsiz ;room in disk output buffer
dskbfp: 440700,,dskbuf ;output byte pointer
fgnhst: 0 ;net addr of user host
alive: -1 ;set to -1 by signs of life
luzrl==3.
luzrs: block luzrl
chapkt: block %cpmxw ;chaosnet packet goes here
dbfsiz==2000
dskbuf: block dbfsiz+4/5
rcvfbf: block 43 ;about 256 chars
constants
variables
theend: -1 ; Make memory exist (*sigh*)
hstpag==<.+1777>/2000 ;Start mapping databases here.
end go