1
0
mirror of https://github.com/PDP-10/stacken.git synced 2026-02-19 13:55:12 +00:00
Files
PDP-10.stacken/files/stacken-tape-backup/dskb:10_335/tftpd.mac
Lars Brinkhoff 6e18f5ebef Extract files from tape images.
Some tapes could not be extracted.
2021-01-29 10:47:33 +01:00

481 lines
9.7 KiB
Plaintext

title tftpd -- simple tftp daemon.
search jobdat, uuosym, macten
search udpsym
opdef udp.[call[sixbit 'udp.']]
.text "/symseg:low/locals"
define bug.(msg),<
jrst[ outstr[ asciz 'msg']
outstr[ byte (7) 15, 12, 0]
monrt.
exit]
>
define errmsg(code, text),<
..len==0
irpc text,<..len==..len+1>
repeat 0,<
movei t1,..len+1
movei t2,[asciz "text"]
pushj p,snderr
>
move t1,[byte (16) 5,code]
movem t1,buffer
movei t1,..len+1
move t2,[point 7,[asciz "text"]]
movei t4,..len+1
move t5,[point 8,buffer+1]
extend t1,[movslj]
jfcl
movei t1,..len+5
movem t1,argblk+.udcnt
movei t1,buffer
movem t1,argblk+.udbuf
movei t1,.udwri
movem t1,argblk+.udfnc
movei t1,argblk
udp. t1,
jfcl
popj p,
>
udp==1 ;I/O channel for UDP:
tty==2 ;I/O channel for TTY:
dsk==3 ;(temp) I/O channel for disk files.
t1==1
t2==2
t3==3
t4==4
t5==5
t6==6
p==17
debugf: exp 0 ;Debugging flag, normally off.
busy: exp 0 ;non-zero if a transfer is going on.
pdl: block <pdllen==^D100>
argblk: block .udlen
buflen==<^D512 + ^D4>
buffer: block <buflen + 3> / 4
dskibh: block 3
nulctr: exp 0 ;Count of deferred null chars from file.
nxtchr: exp 0 ;Deferred non-null char from file.
remadr: block 1 ;Remote address.
remprt: block 1 ;Remove port.
vector:!
vecudp: exp udpint, 0, 0, 0
vecdsk: exp dskint, 0, 0, 0
vectmr: exp tmrint, 0, 0, 0
vectty: exp ttyint, 0, 0, 0
udpflg: exp 0 ;Interrupt flag for UPD:
tmrflg: exp 0 ;Interrupt flag for timer.
dskflg: exp 0 ;(temp) Interrupt flag for DSK:
ttyflg: exp 0 ;Interrupt flag for TTY:
slploc: block 1 ;Holds <sleep t1,> or <jfcl>.
seq: block 1 ;Sequence number of output data.
file: exp 6, path ;Lookup block.
zbeg==.
f.nam: block 1 ;Parsed file name.
f.ext: block 1 ;Parsed extension.
block 1 ;Junk.
f.siz: block 1 ;Size, from lookup.
f.dev: block 1 ;Parsed device.
path:! block 2 ;Couple of words.
f.ppn: block 1 ;Parsed PPN.
f.pth: block 6 ;Parsed list of SFD's.
zend==.-1
tftpd: jfcl
reset
move p,[
iowd pdllen, pdl]
movei t1,vector
piini. t1,
bug. "Can't init PSI system."
movx t1,ps.fon
pisys. t1,
bug. "Can't turn PSI system on."
open udp,[
exp .iobyt+uu.aio
sixbit "udp"
xwd 0,0]
bug. "Can't open UDP:"
move t1,[
ps.fac+[exp udp
xwd <vecudp-vector>,ps.rid
xwd 0,0]]
pisys. t1,
bug. "Can't add UDP: to PSI system."
open tty,[
exp .ioasc+uu.aio
sixbit "tty"
xwd 0,0]
bug. "Can't open TTY:"
move t1,[
ps.fac+[exp tty
xwd <vectty-vector>,ps.rid+ps.ria
xwd 0,0]]
pisys. t1,
bug. "Can't add TTY: to PSI system."
skpinc
jfcl
movei t1,.udset
movem t1,argblk+.udfnc;Function code.
movei t1,udp
movem t1,argblk+.uddev;Channel.
setzm argblk+.udlad ;Unspecified local address.
movei t1,^D69 ;TFTP port number.
movem t1,argblk+.udlpr
setom argblk+.udrad ;ARGH, this is a bug.
setom argblk+.udrpr ;ARGH, this is a bug.
movei t1,argblk
udp. t1,
bug. "Can't set parameters for UDP:"
loop: movx t1,<sleep t1,>
movem t1,slploc
skipe ttyflg ;Any terminal activity?
pushj p,ttyhnd ; Maybe, handle it.
skipe udpflg ;Any UDP: activity?
pushj p,udphnd ; Maybe, handle it.
skipe tmrflg ;Timer tick?
pushj p,tmrhnd ; Yes, handle it.
skipe dskflg ;Any disk activity?
pushj p,dskhnd ; Think so, handle it.
movei t1,^D60 ;One minute.
xct slploc ;Execute the sleep.
jrst loop ;Back to work.
ttyhnd: setzm ttyflg ;Clear interrupt flag.
inchrs t1
popj p,
skipn busy ;Busy?
jrst[ outstr[ asciz "Idle."]
jrst pcrlf]
outstr[ asciz "sending, seq = "]
move t1,seq
pushj p,prdec
outstr[ asciz ", remote = "]
move t1,remadr
pushj p,pripa
outstr[ asciz "/"]
move t1,remprt
pushj p,prdec
jrst pcrlf
udphnd: setzm udpflg ;Clear interrupt flag.
udph.2: movei t1,.udrea
movem t1,argblk+.udfnc
movei t1,udp
movem t1,argblk+.uddev
movei t1,buffer
movem t1,argblk+.udbuf
movei t1,buflen
movem t1,argblk+.udcnt
movei t1,argblk
udp. t1, ;Try to read next datagram.
popj p,
movei t1,.udset ;Since we most certainly want to talk to -
movem t1,argblk+.udfnc; this guy again, -
movei t1,argblk ; set him up as remote.
udp. t1,
bug. "Can't set remote address/port."
skipe debugf ;If debugging, -
pushj p,prdata ; print stats from datagram.
ldb t1,[point 16,buffer, 15]
caile t1,5
movei t1,0
pushj p,@[
exp op.ill, op.rrq, op.wrq, op.data, op.ack, op.err](t1)
jrst udph.2 ;Loop for more.
op.ill: errmsg (4, Illegal TFTP opcode)
popj p,
op.wrq: errmsg (0, Not implemented)
popj p,
op.dat: errmsg (0, Not expected)
popj p,
op.err: popj p,
tmrhnd: setzm tmrflg ;Clear request flag.
; Handle timing here.
popj p, ;Done.
dskhnd: setzm dskflg ;Clear request flag.
; Try to do disk i/o here.
popj p, ;Done.
udpint: setom udpflg
jrst dismis
ttyint: setom ttyflg
jrst dismis
tmrint: setom tmrflg
jrst dismis
dskint: ;Find process that owns interrupting channel.
setom dskflg
dismis: movem t1,slploc
movx t1,<jfcl>
exch t1,slploc
debrk.
jfcl
popj p,
prdec: idivi t1,^D10
push p,t2
skipe t1
pushj p,prdec
pop p,t2
addi t2,"0"
outchr t2
popj p,
pripa: push p,t1
ldb t1,[point 8,(p),7]
pushj p,prdec
pushj p,prper
ldb t1,[point 8,(p),15]
pushj p,prdec
pushj p,prper
ldb t1,[point 8,(p),23]
pushj p,prdec
pushj p,prper
ldb t1,[point 8,(p),31]
pushj p,prdec
pop p,(p)
popj p,
pcrlf: outstr[ byte (7) 15, 12, 0]
popj p,
prper: outchr[ exp "."]
popj p,
prdata: outstr[ asciz "Datagram ("]
move t1,argblk+.udcnt
pushj p,prdec
outstr[ asciz " bytes) from "]
move t1,argblk+.udrad
pushj p,pripa
outstr[ asciz " port "]
move t1,argblk+.udrpr
pushj p,prdec
pushj p,pcrlf
outstr[ asciz "TFTP opcode = "]
ldb t1,[point 16,buffer, 15]
pushj p,prdec
pushj p,pcrlf
popj p,
op.ack: move t1,argblk+.udrad;Get remote address.
move t2,argblk+.udrpr;Get remote port.
camn t1,remadr ;Our remote address?
came t2,remprt ; Our remote port?
popj p, ; No, bug.
skipl f.siz ;More to send?
jrst snddat ; Yes, go fill next buffer.
setzm busy ;Clear active flag.
popj p, ;rejoin loop, accept more queries.
; This routine gets the next byte to send. It also handles expansion of
; bare CR or LF's, as well as stripping trailing nulls.
nxtraw: sosge f.siz ;Any more in file?
popj p, ; No.
nxtr.2: sosge dskibh+.bfctr
jrst[ in dsk,
jrst nxtr.2
popj p,]
ildb t1,dskibh+.bfptr
aos (p)
popj p,
nxtbyt: skipge f.siz ;End of file?
popj p, ; Yes.
movei t1,0 ;Get a null.
skiple nulctr ;Any null char queued up?
jrst[ sos nulctr
jrst cpopj1]
exch t1,nxtchr ;Clear and get look-ahead.
jumpn t1,cpopj1 ;Return look-ahead if any.
pushj p,nxtraw
popj p,
jumpe t1,nxt.00 ;<NULL>?
cain t1,15 ;<CR>?
jrst nxt.cr
cpopj1: aos (p)
popj p,
nxt.00: aos nulctr
skipge f.siz
popj p,
pushj p,nxtraw
popj p,
jumpe t1,nxt.00
movem t1,nxtchr
movei t1,0
jrst cpopj1
nxt.cr: pushj p,nxtraw
jrst[ aos nulctr
movei t1,15
jrst cpopj1]
movem t1,nxtchr
caie t1,12
aos nulctr
movei t1,15
jrst cpopj1
op.rrq: skipn debugf ;Want debugging output?
jrst rrq.6 ; No, keep quiet.
move t4,[point 8, buffer, 15]
outstr[ asciz "filename = "]
rrq.2: ildb t1,t4
jumpe t1,rrq.3
outchr t1
jrst rrq.2
rrq.3: outstr[ asciz ", mode = "]
rrq.4: ildb t1,t4
jumpe t1,rrq.5
outchr t1
jrst rrq.4
rrq.5: pushj p,pcrlf
rrq.6: skipe busy ;Are we already active?
jrst[ errmsg (0, Already active)
popj p,]
move t4,[point 8, buffer, 15]
pushj p,filprs
movx t1,.ioasc
move t2,f.dev
movx t3,<0,,dskibh>
open dsk,t1
jrst[ errmsg (1, Can't open device)
popj p,]
lookup dsk,file
jrst[ errmsg (1, Can't lookup file)
popj p,]
movei t1,5
imulm t1,f.siz ;Size is in bytes now.
setzm seq ;Init sequence number.
setzm nxtchr ;No look-ahead.
setzm nulctr ;No queued up nulls.
setom busy ;We are busy now.
move t1,argblk+.udrad;Get remote address.
movem t1,remadr ;Save for later.
move t1,argblk+.udrpr;Get remote port.
movem t1,remprt ;Save for later.
snddat: movei t1,3 ;Opcode 3 = data.
dpb t1,[point 16, buffer, 15]
aos t1,seq ;Next seqence number.
dpb t1,[point 16, buffer, 31]
movei t3,0 ;Byte count, 0 so far.
move t4,[point 8, buffer+1]
snd.2: caige t3,^D512 ;Filled a buffer?
pushj p,nxtbyt ; No, get next byte.
jrst snd.9 ; Full or no more, quit now.
idpb t1,t4 ;Store in buffer.
aoja t3,snd.2 ;Count and loop.
snd.9: addi t3,4 ;Include TFTP header size.
movem t3,argblk+.udcnt
movei t1,buffer
movem t1,argblk+.udbuf
movei t1,.udwri
movem t1,argblk+.udfnc
movei t1,argblk
udp. t1,
halt
popj p,
; t1/ char.
; t2/ state.
; t3/ scratch.
; t4/ input pointer.
; t5/ number.
; t6/ word.
filprs: move t1,[zbeg,,zbeg+1]
setzb t2,zbeg
blt t1,zend
movsi t3,-6
movx t1,<sixbit 'dsk'>
movem t1,f.dev
fillup: pushj p,atom
cain t1,":"
movei t2,4
xct[ skipe f.nam
hllzm t6,f.ext
hrlm t5,f.ppn
aobjn t3,[
xct[ hrrm t5,f.ppn
movem t6,f.pth
movem t6,f.pth+1
movem t6,f.pth+2
movem t6,f.pth+3
movem t6,f.pth+4]-1(t3)
jrst .+1]
movem t6,f.dev](t2)
tdza t2,t2
movem t6,f.nam
cain t1,"."
aoja t2,fillup
caie t1,"<"
cain t1,"["
movei t2,2
cain t1,","
movei t2,3
jumpn t1,fillup
popj p,
atom: setzb t5,t6
push p,[point 6,t6]
atom.2: ildb t1,t4
cail t1,141
trz t1,40
caig t1,"Z"
caige t1,"A"
caig t1,"9"
caige t1,"0"
jrst atom.4
lsh t5,3
tro t5,-"0"(t1)
trc t1,40
trnn t6,77
idpb t1,(p)
jrst atom.2
atom.4: pop p,(p)
popj p,
end tftpd