{ Routines to allow access to files on another filestore } { Genealogy: RWT begat eftp, } { and RDW ripped off bits for the first version of sethost, } { and FDC expanded it somewhat } { and RWT some more } %owninteger used ports = 1<<0 + 1<<1 {reserve those two} %routine deallocate port(%integer p) p = 1<

deadline %false %end %predicate gotdtx(%integer port) ! Wait for DTX and return TRUE, FALSE when fed up. %integer bit,deadline bit = 1<deadline %false %end %constant %integer Max Fs = 5 %constant %string (16) %array FNames(1:Max Fs) = "Alpha", "Bravo", "Charlie", "Met", "Vax" %constant %integer %array FNumbers(1:Max Fs) = 16_14, 16_15, 16_1B, 16_44, 16_72 {---------- FILESTORE NAME ----------} { Convert a filestore's ether address into its textual name. { If that address does not appear in the above table, { then just return a 2-digit hex string. %string (255) %function Filestore Name (%integer n) %integer i %string (3) s %integerfn h (%integer n) n = n&15; n = n+7 %if n>9; %result = n+'0' %end %for i = 1, 1, Max Fs %cycle %result = FNames(i) %if FNumbers(i) = n %repeat s = tostring(h(n>>4)) s = s.tostring(h(n)) %result = s %end {Filestore Name} {---------- FILESTORE NUMBER ----------} { Convert a filestore name into its ether address. { If the name does not appear in the table, try to { interpret it as a hex string. %integer %function Filestore Number (%string (*) %name Fs) %integer i,k,n %predicate Prefix Match(%string (*) %name s1, s2) { Does s1 match a prefix of s2 ? } %integer i %false %if Length(s1) > Length(s2) %for i = 1, 1, Length(s1) %cycle %false %if (charno(s1, i) ! 32) # (charno(s2, i) ! 32) %repeat %true %end { Prefix Match } %for i = 1, 1, Max Fs %cycle %result = FNumbers(i) %if Prefix Match(Fs, FNames(i)) %repeat n = 0 %for i = 1,1,length(fs) %cycle k = charno(fs,i)!32 %if '0'<=k<='9' %then n = n<<4+k-'0' - %elseif 'a'<=k<='f' %then n = n<<4+k-'a'+10 - %else n = 0 %repeat %result = n %unless n=0 %signal 10, 0, 1, "Filestore ".Fs." unknown" %end {Filestore Number} {---------- CURRENT HOST ----------} { Returns a token which identifies the current host. } { LSAP . RDTE . RSAP . USERNO } %integer %function Current Host userno = userno&255 %result = ((lsap<<8+rdte)<<8+rsap)<<8+userno %end {---------- SELECT HOST ----------} { Switches to the filestore identified by 'token'. } { 'token' must have been returned by Current Host or Connect to Host. } %routine Select Host(%integer token) userno = token & 255 rsap = token>>8 & 255 rdte = token>>16 & 255 lsap = token>>24 fsport = lsap %end {---------- CONNECT TO HOST ----------} { Given a generalised directory name, this function logs on to it } { and returns a token which can be used in calls to Select Host, } { and which must be used in a call to Disconnect Host before the } { caller terminates. It is the caller's responsibility to save } { Current Host before calling this function and reselect it before } { terminating. } { = ::, / { :::, { = Alpha / Bravo / Charlie / Portable / Vax { = Up to 6 alphanumerics { = Any string { Filestore Name default to Bravo, Directory Name defaults to PUB } { and Password defaults to "". } { Events: 10 0 1 - Unknown filestore } { Events: 10 0 2 - No response from filestore } { 10 0 3 - Illegal connect attempted } %integer %function Connect to Host(%string (255) GDir) %string (255) Name, Dir Pass, message %integer Number, i, free port %byte facil = 2 %byte %array buff(0:63) %label dunparsin Name = "" Dir Pass = "" -> dunparsin %if GDir = "" %if GDir -> Name.("::").Dir Pass %start -> dunparsin %if Length(Dir Pass) = 0 { e.g. B:: } -> dunparsin %if Dir Pass -> Name.(":").Dir Pass { ::B:D } -> dunparsin { B::D or ::B } %else Dir Pass = GDir %finish dunparsin: Name = "Bravo" %if Length(Name) = 0 Number = Filestore Number(Name) %if Number # RDTE %or Dir Pass # "" %start Dir Pass = "PUB" %if Length(Dir Pass) = 0 free port = allocate port etheropen(free port, Number << 8) etherwrite(free port, facil, 1) %if %not gotack(free port) %and gotdtx(free port) %then %c %signal 10, 0, 2, "No response from ".Name."::" i = etherread(free port, buff(0), 64) %if i # 2 %or buff(1) # 10 %or buff(0) < '0' %start %if buff(0)='-' %and i>2 %start buff(0) = i-2 message = string(addr(buff(0))) message = "Error (".message message = message.")" %else message = "Error" %finish message = message." while connnecting to ::" message = message.Name %signal 10, 0, 3, message %finish buff(0) = buff(0) - '0' etheropen(free port, (Number << 8) ! buff(0)) rdte = number rsap = buff(0) lsap = free port fsport = lsap userno = fcomm('L0', Dir Pass) %finish %result = Current Host %end {---------- DISCONNECT HOST ----------} { Disconnect from the host identified by 'token' } %routine Disconnect Host(%integer Token) %byte eot = 12 %integer curtok curtok = current host select host(token) etherwrite(lsap, eot, 1) %if gotack(lsap) %start etherclose(lsap) deallocate port(lsap) %finish selecthost(curtok) %end