! COPY with automatic filestore switching
! RWT January 1991
option "-low-nodiag-nocheck"
include "inc:fs.imp"
include "inc:util.imp"
begin
string (255)ins,in,out
predicate done remotely
! Attempt to get the filestore to perform the copying.
! If the input contains a comma (indicating more than one file), or
! if either of the file names begin with ':' (indicating a device name),
! this will fail (result FALSE). Otherwise (result TRUE) the filestore
! will (start to) do the copying (completing it asynchronously).
integer i
on 3 start ; false ; finish
copy(ins,out); true
end
! Parse the parameter, which consists of one or more comma-separated
! input file names, plus an output file name, separated from the input(s)
! by '/' or space.
ins = cliparam
cycle
stopif ins=""
if charno(ins,1)=' ' start
ins = substring(ins,2,length(ins))
elseif charno(ins,length(ins))=' '
ins = substring(ins,1,length(ins)-1)
elseif ins -> in.(", ").ins or ins -> in.(" ,").ins
ins = in.",".ins
elseif ins -> in.(" ").ins
ins = in." ".in
finishelseexit
repeat
ins = in."/".ins if ins -> in.(" ").ins
out = "" unless ins -> ins.("/").out
! Default input(s) or output is the terminal (":").
out = ":" if out=""
ins = ":" if ins=""
stopif done remotely
! End of easy bit.
! If we get here, it's because either there's a problem with the files,
! or device names or concatenation are involved, or explicit or implicit
! inter-filestore transfer is required.
! Ether comms
routine ackwait(integer port)
integer bit=1<<port,marktime=cputime+1000,deadline = marktime+14000
cycle
returnif ack&bit#0
printsymbol('.') and marktime=marktime+1000 if cputime>marktime
repeatuntil cputime>deadline
printline("No ACK/NAK"); signal 9
end
routine dtxwait(integer port)
integer bit=1<<port,marktime=cputime+1000,deadline=marktime+6500
cycle
returnif dtx&bit#0
printsymbol('.') and marktime=marktime+1000 if cputime>marktime
repeatuntil cputime>deadline
printline("No response"); signal 9
end
predicate nacked(integer port)
integer bit=1<<port
falseif nak&bit=0; nak = nak&¬bit; true
end
predicate gotack(integer port)
on 9 start ; false ; finish
ackwait(port); falseif nacked(port); true
end
predicate gotdtx(integer port)
on 9 start ; false ; finish
dtxwait(port); true
end
! Filestore comms
routine disconnect
byte disc = {4}12
returnif rdte=0; rdte = 0; rsap = 0
etherwrite(lsap,disc,1); ackwait(lsap); returnif nacked(lsap)
end
routine connect
string (255)s
integer port
byte con = 2
on 9 start
printline(event_message); return
finish
rsap = 0; fsport = lsap; etheropen(lsap,rdte<<8)
etherwrite(lsap,con,1); ackwait(lsap)
if nacked(lsap) start
printstring("No Ack from station "); phex2(rdte); newline; return
finish
dtxwait(lsap)
length(s) = etherread(lsap,charno(s,1),80)
port = charno(s,1)-'0'
if port<0 start
printline(substring(s,3,length(s))); return
finish
etheropen(lsap,rdte<<8+port)
! check connection
while dtx&1#0 cycle
length(s) = etherread(0,charno(s,1),255)
printline("Spurious port 0 packet ignored")
repeat
s = "M0".snl; etherwrite(lsap,charno(s,1),3)
unless gotack(lsap) start
printline("No M0 ack"); return
finish
unless gotdtx(lsap) start
printline("No M0 response"); return
finish
length(s) = etherread(lsap,charno(s,1),255)
s = "G0".snl; etherwrite(lsap,charno(s,1),3)
unless gotack(lsap) start
printline("No G0 ack"); return
finish
unless gotdtx(lsap) start
printline("No G0 response"); return
finish
length(s) = etherread(lsap,charno(s,1),255)
while charno(s,1)='-' cycle
printline("Ignoring duplicate response")
unless gotdtx(lsap) start
printline("No duplicate response"); return
finish
length(s) = etherread(lsap,charno(s,1),255)
repeat
rsap = port
end
begin
recordformat f(byte ldte,lsap,rdte,rsap)
@#ldte record (f)cur
record (f)array portinfo(1:31)
integer i,inport=1,outport=1
routine select(integer port)
owninteger uno=0
uno = userno if userno#0
userno = 0
userno = uno if port=1
cur = portinfo(port); fsport = port
end
integerfn allocate port
integer i
for i = 1,1,31 cycle
if portinfo(i)_rdte=rdte start
select(i)
result = i
finish
repeat
for i = 2,1,31 cycle
if portinfo(i)_rdte=0 start
lsap = i; fsport = i
connect; select(1) andresult = 0 if rsap=0
portinfo(i) = cur
result = i
finish
repeat
printline("No free local ports"); select(1); result = 0
end
integerfn access(routine open(integer stream,string (255)filename),
string (255)filename)
! Result 0 after error report if failed, otherwise result is port number.
! Parse the filename to determine which filestore is meant, selecting the
! appropriate port, connecting if necessary. Then open the file. If this
! fails with "owner not found" (i.e. event_extra=12), and the filestore in
! question was B or C, then try instead on C or B.
ownbytearray dtetable('A':'Z')=16_14,16_15,16_1B,0(*)
string (255)server,rawfilename
integer dte,port,retried=0,k
on 3 start
selectoutput(0)
retried = 1 unless event_extra=12
if retried=0 start
if dte=dtetable('B') or dte=dtetable('C') start
dte = dtetable('B')+dtetable('C')-dte
finishelse retried=1
finish
if retried#0 start
printline(event_message); result = 0
finish
retried = 1
finish
select(1)
if retried=0 start {first time parse filename}
dte = rdte; rawfilename = filename
if filename -> server.("::").rawfilename start
retried = 1 {no retrying if server specified explicitly}
k = charno(server,1)&95 unless server=""
if length(server)=1 and 'A'<=k<='Z' start
dte = dtetable(k)
else
dte = 0
while server#"" cycle
k = charno(server,1); server = substring(server,2,length(server))
if '0'<=k<='9' start
dte = dte<<4-'0'+k
else
k = k&95; exitunless 'A'<=k<='F'
dte = dte<<4-'A'+k+10
finish
repeat
finish
if dte=0 start
no: select(1); printstring("Unknown server ")
printline(filename); result = 0
finish
finish
finish
rdte = dte; port = allocate port; ->no if port=0
select(port); open(1,rawfilename); selectoutput(0)
result = port
end
routine transfer
bytearray buf(0:4095)
integer n=0,i
on 9 start
closeinput
select(outport); selectoutput(1)
printsymbol(buf(i)) for i = 0,1,n-1
selectoutput(0)
return
finish
cycle
select(inport); selectinput(1)
n = 0
cycle
readsymbol(buf(n)); n = n+1
repeatuntil n=4096
select(outport); selectoutput(1)
printsymbol(buf(i)) for i = 0,1,n-1
repeat
end
! Main program for local copying begins here
portinfo(1) = cur
portinfo(i) = 0 for i = 2,1,31
outport = access(openoutput,out); stopif outport=0
ins = ins.","
while ins -> in.(",").ins cycle
inport = access(openinput,in); continueif inport=0
transfer
repeat
selectoutput(1); closeoutput; selectoutput(0)
for i = 2,1,31 cycle
select(i); disconnect
repeat
select(1)
space{?just to see if it got here ok?}
end
end