constinteger max fsys = 99 recordformat fhf(integer end, start, size, type, free hole, datetime, spare1, spare2) recordformat pe (integer dest,srce,p1,p2,p3,p4,p5,p6) recordformat rf (integer conad,filetype,datastart,dataend) recordformat ftp bits(byteinteger qual, set, halfinteger value) recordformat ftp strings(byteinteger qual, set, string (39) value) recordformat tran document descriptorf(string (7) header, byteinteger state, string (6) user, (string (15) dest or integer spare1,spare2,spare3,spare4), {these spare integers are for ftp use only and will be lost in SPOOLR calls} (integer date and time received, date and time started or c byteinteger FTRANS action, confirm, type, tfsys, integer transfer ident), {the FTRANS units are set by us when requesting SPOOLR to do something} halfinteger dap mins, dap c exec time, integer date and time deleted, start after date and time, priority, data start, data length, integer time, (integer output limit or integer ftp data record), halfinteger mode of access, byteinteger priority requested, forms, mode, copies, order, rerun, decks, drives, fails, outdev, srce, output, delivery, name, byteintegerarray vol label(1:8), byteinteger external user, external password, external name, ftp alias, storage codename, device type, device qualifier, data type, text storage, ftp user flags, ftp file password,special options, auto requeue, guest address, ftp user flags2 ,sp5, byteinteger properties, byteinteger try emas to emas, ftp retry level, (byteinteger string ptr or string (148) string space)) recordformat document descriptorf(byteinteger state, string (6) user, (string (15) dest or integer spare1,spare2,spare3,spare4), {these spare integers are for ftp use only and will be lost in SPOOLR calls} (integer date and time received, date and time started or c byteinteger FTRANS action, confirm, type, tfsys, integer transfer ident), {the FTRANS units are set by us when requesting SPOOLR to do something} halfinteger dap mins, dap c exec time, integer date and time deleted, start after date and time, priority, data start, data length, integer time, (integer output limit or integer ftp data record), halfinteger mode of access, byteinteger priority requested, forms, mode, copies, order, rerun, decks, drives, fails, outdev, srce, output, delivery, name, byteintegerarray vol label(1:8), byteinteger external user, external password, external name, ftp alias, storage codename, device type, device qualifier, data type, text storage, ftp user flags, ftp file password,special options, auto requeue, guest address,ftp user flags2, sp5, byteinteger properties, byteinteger try emas to emas, ftp retry level, (byteinteger string ptr or string (148) string space)) !* !* recordformat queuef(string (15) name, (halfintegerarray ftp lines(0 : 15) or halfintegerarray lines(0 : 15)), string (7) default user, string (31) default delivery, integer default start, default priority, default time, default output limit, default forms, default mode, default copies, default rerun, length, head, max length, maxacr, halfinteger q by, general access, integer resource limit, amount) !* ! recordformat line f(string (15) name, string (7) unit name, string (6) user, byteinteger parity, integer status, bytes sent, bytes to go, block, part blocks, document, integer bin offset, byteinteger service, user abort, unit size, fep, integer abort retry count, offset, station ptr, integerarray ispare(0:2), integer data transfer start {for timing the transfer},account, integer in comms stream, out comms stream, integer in stream ident, out stream ident, integer transfer status, tcc subtype, in block addr, out block addr, byteinteger activity, station type, spb2, suspend, in stream status, out stream status, timer, output buffer status, output transfer pending, new FTP data record, byteintegerarray bspare(0:9), integer aux document, pre abort status, bytes transferred, record (pe) output transfer record) !* !* !* !* recordformat ftp tablef(integer user fsys, binary data record, spare1, spare2, byteinteger emastoemas, data mode,mail,mail to send, mail displ, sp1,sp2,sp3, string (73) stopack message, byteintegerarray emastoemas header (0:31), record (ftp bits) protocol id,mode,data type,text tran code, text format,del pres,max tran rec size,tran limit, file size,facilities,timeout,restart mark, bin word size, bin format, Ispare, record (ftp strings) username,username password,filename,file password, private code name,device type,device type qualifier, special options) !* record format pointers f(integer link list displ, ftp table displ, queues, queue entry size, queue displ, queue name displ, streams, stream entry size, stream displ, hash length, sp1, sp2, sp3, stations, station entry size, station displ, control entry, station addresses displ, guest entry, byte integer array discs(0:max fsys), string (63) dead letters, this full host, integer expanded address displ, integer array hash t(0:1023)) record format FTP station f(byte integer max lines , byteinteger status, byteinteger service , byteinteger connect retry ptr, fep, address type, accounting, byteinteger q lines , integer limit , integer last call, last response, system loaded, connect attempts, connect retry time, integer array ispare(0:4), integer seconds, bytes, integer last q response by us, p transfers, q transfers, p kb, q kb, p mail, q mail, integer name, shortest name, integerarray address(1:4), integer pss entry, integer mail, integer ftp, integer description, (integer queue or integer route), integer flags, byteintegerarray string space(0 : 375){decrement this if more fields added, keep to 512 total}) record format name f(integer link, host entry, string (255) name) !* recordformat lcf(integer document, priority, size, station ptr, (byteinteger spb1,ftp timer,ftp flags,gen flags or integer flags), integer link,string (6) user, byteinteger order) !* conststring (5) this ukac = "UK.AC" constinteger max documents = 1000 constinteger document entry size = 256 constinteger max stations = 512 constinteger max lines = 255 constinteger BASE type = 3 constinteger not assigned = x'80808080' constinteger modes = 5 conststring (8)array mode key(1: modes) = c "MAKE", "REPLACE", "FILE", "OUTPUT", "JOB" constinteger options = 13 conststring (15) array option keys(1 : options) = c ".END", "NOMAIL", "FAILMAIL", "DELIVERY", "FORMS", "PASS", "TERMINATE", "PRIORITY", "SIZE", "ANSI", "SPECIAL", "BINARY", "TXT" constinteger option help lines = 24 conststring (80) array option help(1 : option help lines) = c "NOMAIL: No mail will be given when the transfer ends regardless", " of the reason for termination.", "FAILMAIL: Mail will only be given if the transfer fails.", "PRIORITY: Set the priority of the transfer. Defaults to STD", "SIZE: If the transfer is INcoming then here you can give", " an estimated upper bound on the size (in Kbytes) of", " the file. This will default to 100 Kbytes but it is", " in your interest to set it.", "DELIVERY: Only relevent when the transfer is INto a device", " and sets the delivery information on the listing.", "FORMS: As with DELIVERY, sets special forms requirment.", "PASS: This sets a file password for this transfer.", "ANSI: For INcoming transfers only. Set this if the file", " has ANSI control chars and the transfer of the file has", " already given problems.", "BINARY: An INcoming transfer can be either TEXT or BINARY and it", "TXT: is the the negotiation between the two hosts that determines", " which is the case. With some systems (ie PRIME) you will need", " to specify the type of transfer initially. In this case use", " one of these two options.", "SPECIAL: This field can be set to convey extra information to the", " External System. The use of this field will normally be ", " specified by the External System documentation.", "TERMINATE: This abandons the transfer under construction." constinteger priorities = 5 conststring (5)array priority names(1 : priorities) = c "VLOW", "LOW", "STD", "HIGH", "VHIGH" conststring (1) snl = " " constinteger yes = 1 constinteger r = b'00000001' constinteger sh = b'00001000' constinteger no = 0 !THE FTP USER FLAGS FOLLOW !------------------------- !First set constbyteinteger no mail = x'01' constbyteinteger fail mail = x'02' constbyteinteger overwrite = x'04' constbyteinteger non text or data = x'08' constbyteinteger data = x'20' constbyteinteger ANSI = x'10' constbyteinteger local output = x'40' constbyteinteger binary read only = x'80' !Second set constbyteinteger text read only = x'01' constbyteinteger in = 1 constbyteinteger out = 0 constbyteinteger make = 1 constbyteinteger replace = 2 constbyteinteger file = 3 constbyteinteger output = 4 constbyteinteger job = 5 systemintegerfnspec current packed dt systemintegerfnspec pack date and time(string (8) date, time) systemstring (8) fnspec unpack date(integer p) systemstring (8) fnspec unpack time(integer p) systemroutinespec outfile(string (31) name, integer length, max, prot, c integername conad, flag) externalintegerfnspec uinfi(integer type) externalstringfnspec uinfs(integer type) systemroutinespec connect(string (31) name, integer access, maxbytes, c protection, record (rf) name r, integername flag) systemstringfnspec failure message(integer flag) systemroutinespec disconnect(string (31) s,integername flag) systemroutinespec destroy(string (31) s, integername flag) externalroutinespec journal off alias "s#journaloff" systemroutinespec console(integer ep, integer i,j) externalroutinespec setmode(string (255) s) externalintegerfnspec dexecmess(string (6) user, integer sact,len,addr) systemstringfnspec itos(integer i) externalintegerfnspec dfsys(string (6) user,integername fsys) externalintegerfnspec dspool(record (pe) name p, integer len, addr) externalroutinespec prompt(string (31) s) systemroutinespec move(integer l, f, t) systemroutinespec psysmes(integer root,flag) externalroutine call transfer(string (39) external site, external user, external user password, external filename, local filename, output device, integer directionp, modep, mail, integername document no, stringname info, integer sp option int, string (127) sp option str) !**************************************************************** !* * !* This is a routine to give param call access to file transfer * !* via FTP-B(80). * !* * !**************************************************************** record (fhf)name file header record (pe) p record (rf) r record (tran document descriptorf) document, new doc string (64) reply, s1, s2, s3, lfile, xfilename, lbase string (11) tfile integer flag, direction, conad, pages, mode, another pass, i , j switch mode sw(1 : modes) switch option act(1 : options) switch direction sw(out : in) stringfn doc string(record (tran document descriptor f)name document, byteintegername ptr) if ptr = 0 then result = "" else c result = string(addr(document_string space) + ptr) end integerfn s to i(stringname s) string (255) p, ns1, ns2 integer total, sign, ad, i, j, hex hex = 0; total = 0; sign = 1 ad = addr(p) a: if s ->ns1.(" ").ns2 and ns1="" then s=ns2 and -> a; !CHOP LEADING SPACES if s ->ns1.("-").ns2 and ns1="" then s=ns2 and sign = -1 if s ->ns1.("X").ns2 and ns1="" then s=ns2 and hex = 1 and -> a p = s unless s -> p.(" ").s then s = "" i = 1 while i <= byteinteger(ad) cycle j = byte integer(i+ad) -> fault unless '0' <= j <= '9' or (hex # 0 c and 'A' <= j <= 'F') if hex = 0 then total = 10*total c else total = total<<4+9*j>>6 total = total+j&15; i = i+1 repeat if hex # 0 and i > 9 then -> fault if i > 1 then result = sign*total fault: s = p.s result = not assigned end ; !OF INTEGERFN S TO I stringfn l to u(string (63) s) integer i reply=s cycle i = 1,1,length(reply) byteinteger(addr(reply)+i)=byteinteger(addr(reply)+i)&95 if 'a'<=byteinteger(addr(reply)+i)<='z' repeat result = reply end routine to doc string(record (tran document descriptorf)name document, byteintegername field, stringname value) field = 0 and return if value = "" field = x'ff' and return if document_string ptr + length(value) > 147 field = document_string ptr string(addr(document_string space) + document_string ptr) = value document_string ptr = document_string ptr + length(value) + 1 end routine fail(string (63) s) info <- "File Transfer fails: ".s newline end document = 0 another pass = no document_string ptr = 1 document_dest = "FTP" document_priority = -1 document no = 0 tfile = "" if external site = "" start info <- "Must give the EXTERNAL-SITE name.".snl return finish external site = l to u(external site) to docstring(document,document_ftp alias,external site) unless out <= directionp <= in start info <- "Direction ?: IN = 1; OUT = 0".snl return finish direction = directionp unless make <= modep <= output start info <- "Mode ?: 1-Make; 2-Replace; 3-File; 4-Output".snl return finish mode = modep if direction = in and replace <= mode <= file then document_ftp user flags = c document_ftp user flags ! overwrite if external user # "" c then to docstring(document,document_external user,external user) unless external user password = "" c then to docstring(document,document_external password,external user password) new doc = document unless direction = out and mode = output start if external filename = "" start info <- "Give the filename at ".docstring(document,document_ftp alias).".".snl return finish xfilename = external filename finish unless direction = in and mode = output start lfile = local filename if lfile -> s1.("_").s2 and direction = in then start info <- "Cannot transfer INto PD file".snl return finish lbase = "" if lfile -> s1.(".").s2 then lfile = s2 and lbase = s1."." if lbase # "" and direction = in start info <- "cannot copy INto another user's index.".snl return finish cycle i = 1,1,length(lfile) j = byteinteger(addr(lfile)+i) unless (i > 1 and '0' <= j <= '9') or 'A' <= j&95 <= 'Z' c or ( i>1 and j = '#') then info <- "Invalid local filename".snl and return repeat connect(lbase.lfile,0,0,0,r,flag) if flag # 0 and direction = out start info <- failure message(flag).snl return finish if direction = out start file header == record(r_conad) document_data length = file header_end-file header_start if document_data length = 0 then info <- lfile." empty.".snl c and return document_data start = file header_start finish else document_data length = 100<<10 if flag # 0 and direction = in and mode = replace start info <- lfile." does not exist!".snl return finish if flag = 0 and direction = in start if replace <= mode <= file then c info <- "Overwriting ".lfile.snl if mode = make start info <- lfile." already exists.".snl return finish finish finish -> mode sw(mode) mode sw(1): if direction = in then document_mode of access = x'8002' c else document_mode of access = x'0001' -> direction sw(direction) mode sw(2): if direction = in then document_mode of access = x'8002' else c document_mode of access = x'0002' -> direction sw(direction) mode sw(3): if direction = in then document_mode of access = x'8002' else c document_mode of access = x'0003' -> direction sw(direction) mode sw(4): if direction = in then document_mode of access = x'8002' c else document_mode of access = x'4001' if output device = "" start info <- "Output Device required.".snl return finish to docstring(document,document_device type,output device) -> direction sw(direction) direction sw(in): if mode = output then to docstring(document,document_name,reply) c else to docstring(document,document_name,lfile) to docstring(document,document_external name,xfilename) -> transfer direction sw(out): if r_filetype # 3 then document_ftp user flags = document_ftp user flags ! c non text or data and printstring("Warning, this non text transfer will only succeed with". c " another EMAS 2900.".snl) pages = (integer(r_conad)+4095)>>12 tfile <- "f#".lfile if tfile -> s1.("_").s2 then tfile = s1 outfile(tfile,pages<<12,pages<<12,0,conad,flag) if flag # 0 then fail(failure message(flag)) move(integer(r_conad),r_conad,conad) disconnect(tfile,flag) to docstring(document,document_srce,tfile) to docstring(document,document_name,lfile) unless mode = output then to docstring(document,document_external name,xfilename) transfer: unless mode = output and direction = in then disconnect(lbase.lfile,flag) unless 1 <= mail <= 3 start info <- "MAIL ?: 1-Full; 2-Fail only; 3-None.".snl return finish -> option act(mail) option act(1): -> go option act(2): document_ftp user flags = document_ftp user flags ! no mail -> go option act(3): document_ftp user flags = document_ftp user flags ! fail mail go: document_header = "BINDOC:" p = 0 flag = 0 flag = dspool(p,(5<<24)!264,addr(document)) if flag # 0 and flag # p_p1 then destroy(tfile,flag) c and fail("DSPOOL failure") and return destroy(tfile,flag) if p_p1 = 0 start document no = p_p2 finish else start if p_p1 = 1 then fail("Local user not known !!!") and return if p_p1 = 2 then fail("No free spooler descriptors.") and return if p_p1 = 3 then fail("DTRANSFER/DCONNECT fails") and return if p_p1 = 4 then fail("Unknown external system. ") and return if p_p1 = 5 then fail("Transfer queue full.") and return if p_p1 = 6 then fail("Bad params!") and return if p_p1 = 7 then fail("Unaccepted mode of transfer") and return if p_p1 = 8 then fail("Gateway FTP access barred, accreditation required.") and return fail("Unknown failure") and return finish end externalroutine transfer(string (255) s) !**************************************************************** !* * !* This is a routine to give user access to file transfer * !* via FTP-B(80). * !* * !**************************************************************** externalroutinespec transfers(string (255) s) record (fhf)name file header record (name f)name name entry record (pe) p record (rf) re record (tran document descriptorf) document, new doc record (ftp station f)arrayformat ftpsf(1:max stations) record (ftp station f)arrayname ftp stations record (pointers f)name pointers string (132) s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, options string, residual string (64) lfile, xfilename, lbase,last key checked string (255) reply string (200) message string (11) tfile integer flag, direction, conad, pages, mode, another pass, i, j, k, l, m, extra prompts, prompt input, dummy integer stations, options set,true option, option fault check, help required integer more, first entry integer transfers call integer hash length switch mode sw(1 : modes) switch option act(1 : options) switch lopt(1 : options) switch direction sw(out : in) byteintegerarray set (1 : max stations) integerfnspec get param(stringname sp, integer single param only) stringfn doc string(record (tran document descriptor f)name document, byteintegername ptr) if ptr = 0 then result = "" else c result = string(addr(document_string space) + ptr) end integerfn s to i(stringname s) string (255) p, ns1, ns2 integer total, sign, ad, i, j, hex hex = 0; total = 0; sign = 1 ad = addr(p) a: if s ->ns1.(" ").ns2 and ns1="" then s=ns2 and -> a; !CHOP LEADING SPACES if s ->ns1.("-").ns2 and ns1="" then s=ns2 and sign = -1 if s ->ns1.("X").ns2 and ns1="" then s=ns2 and hex = 1 and -> a p = s unless s -> p.(" ").s then s = "" i = 1 while i <= byteinteger(ad) cycle j = byte integer(i+ad) -> fault unless '0' <= j <= '9' or (hex # 0 c and 'A' <= j <= 'F') if hex = 0 then total = 10*total c else total = total<<4+9*j>>6 total = total+j&15; i = i+1 repeat if hex # 0 and i > 9 then -> fault if i > 1 then result = sign*total fault: s = p.s result = not assigned end ; !OF INTEGERFN S TO I routine all hosts with ( byteintegerarrayname set, stringname key, last) integer link, i, flag string (63) zs string (63) comp comp = key last = comp cycle i = 0, 1, hash length link = pointers_hash t ( i ) while link # -1 cycle name entry == record ( re_conad + link ) if name entry_name -> ( ".".comp."." ) or name entry_name -> zs.( comp ) c or name entry_name -> ( comp ).zs then set(name entry_host entry) = yes link = name entry_link repeat repeat end routine to doc string(record (tran document descriptorf)name document, byteintegername field, stringname value) field = 0 and return if value = "" field = x'ff' and return if document_string ptr + length(value) > 147 field = document_string ptr string(addr(document_string space) + document_string ptr) = value document_string ptr = document_string ptr + length(value) + 1 end routine read prompt reply(stringname reply, integer sig) !This routine reads the reply to an issued prompt. integer i reply=""; !Clear out the reply area. skipsymbol and return if nextsymbol = nl while nextsymbol#nl cycle readsymbol(i) i=i&95 if sig = no and 'a'<=i<='z' reply <- reply.tostring(i) repeat skipsymbol end ; !OF READ PROMPT REPLY. integer fn hashed(string (63) name) integer i, pt, n, h byte integer array x(0:15) const byte integer array prime(1:7)= 23, 19, 11, 7, 5, 13, 17 pt = (addr(x(7))>>3)<<3 longinteger(pt) = 0 n = addr(name) byteinteger(pt+i&7) = byteinteger(pt+i&7)!!byteinteger(n+i) for i = 0, 1, length(name) h = length(name)*29 h = h+prime(i)*byteinteger(pt+i) for i = 1, 1, 7 result = h&hash length end ; !of hashed integer fn lookup hasht(string (63) name) record (name f) name name entry integer h h = hashed(name) if pointers_hasht(h)#-1 start name entry == record(re_conad + pointers_hasht ( h )) cycle if name=name entry_name then result = name entry_host entry exit if name entry_link = -1 name entry == record ( re_conad + name entry_link ) repeat finish result = 0 end ; !of lookup hasht integer fn lookup host(string (63) name) integer i string (63) rest {uctranslate or lc?} i = lookup hasht(name) if i#0 then result = i unless name->(this ukac.".").rest start i = lookup hasht(this ukac.".".name); !prefix uk.ac if i#0 then result = i if name->name.(".").rest then result = lookup hasht(name); !for arpa. finish result = 0 end ; !of lookup host stringfn reverse(string (255) st) !this routine reverses a string string (255) ss integer l, i, addrss, addrst ! printstring(st.snl) result = st if st = "" l = length(st) !write(l,3);newline addrss = addr(ss) addrst = addr(st) + l + 1 l = length(st) cycle i = 1,1,l byteinteger(addrss+i) = byteinteger(addrst-i) repeat length(ss) = l !printstring(ss.snl) !write(length(ss),3);newline result = ss end routine uc tran(stringname string) integer i,j if length(string) > 0 start cycle i = 1,1,length(string) j = byteinteger(addr(string)+i) byteinteger(addr(string)+i) = j&95 if 'a'<=j<='z' repeat finish end ; !of routine UC TRAN routine fail(string (63) s) printstring("Queueing of transfer request fails: ".s) newline stop end routine connect trans db(integername flag) connect("FTRANS.CFILE",r!sh,0,0,re,flag) !connect("TESTFILE",r,0,0,re,flag) if flag # 0 and flag # 34 start printstring("Cannot connect TRANSFER systems database".snl) return finish flag = 0 file header == record(re_conad) pointers == record(re_conad + file header_start) stations = pointers_stations hash length = pointers_hash length ftp stations == array(re_conad + pointers_station displ,ftpsf) end connect trans db(flag) return if flag # 0 document = 0 reply = s if reply -> ("FROMTRANSFERS").reply or (s -> s1.("?").s2 and s1 = "" and s2 # "") c then s = "" and transfers call = yes else transfers call = no another pass = no dummy = 0 option fault check = no help required = no document_string ptr = 1 document_dest = "FTP" document_priority = -1 tfile = "" cycle i = 1,1,stations set(i) = no repeat last key checked = "" extra prompts = yes; prompt input = yes if s = "" or transfers call = yes start if transfers call = no then c printstring("Reply '?' for help after any prompt.".snl) sys: s3 = "" j = 1 more = no first entry = yes cycle if transfers call = no then prompt("External System : ") and c read prompt reply(reply,no) else start if transfers call = yes and first entry = no then prompt(": ") c and read prompt reply(reply,no) finish if reply ->("?").s4 and s4 # "" start m = lookup host(s4) if m # 0 and ftp stations(m)_address type # base type start printstring("This is an External system, do you want full details?:".snl) cycle prompt("yes or no :") read prompt reply(s5,no) exit if s5 ->("Y").s6 or s5->("N").s6 repeat if s5 -> ("Y").s6 start transfers(s4) s3 = s4 more = yes connect trans db(flag) printstring("type '?' to continue; '?key' to start search on 'key'; ") if transfers call = yes then printstring(" <return> terminates".snl) c else printstring(" Or select a system".snl) first entry = no continue finish finish finish if s3 # "" or first entry = no start if reply -> ("?").s4 and s4 #s3 and more = yes start unless s4 = "" and s3 # "" start if s3 = "" then printstring("Full host listing abandoned.") c else printstring("Search on key ".s3." abandoned.") printstring(" New key search on ".s4.snl) j = 1 cycle m = 1,1,stations set(m) = no repeat last key checked = "" finish else printstring("Continuing key search.".snl) and reply = "?".s3 finish finish first entry = no more = no if reply -> ("?").s3 then start if s3 = "" start if transfers call = yes then s1 = "Full list is" else c s1 = "Give the name of the external system you wish to ".snl. c "transfer the file to of from. Currently available are" finish else s1 = "Matches found are" if j = 1 then uc tran(s3) and printstring(snl.s1.": ".snl.snl) c else newline k = 0 all hosts with(set,s3, last key checked) if s3 # "" and s3 # last key checked cycle i = j,1,stations if ftp stations(i)_status < 5 and ftp stations(i)_address type # base type start !We have a service stations. if s3 # "" and set(i) = no start s7 = string(addr(ftp stations(i)_string space(0))+ftp stations(i) _ c description) uc tran(s7) unless s7 -> s1.(s3).s2 then continue finish l = byteinteger(addr(ftp stations(i)_string space(0))+ftp stations(i)_shortest name) printstring(string(addr(ftp stations(i)_string space(0)) c + ftp stations(i)_shortest name)) if l < 17 then spaces(17-l) reply = string(addr(ftp stations(i)_string space(0)) c + ftp stations(i)_description) if reply -> ("~").s1 then reply = s1 printstring("- ".reply.snl) k = k + 1 finish if (k//16)*16 = k and k # 0 and i # stations start printstring(snl."more....type '?' to continue; '?key' to start key search;") if transfers call = yes then printstring(" <return> to terminate.".snl)c else printstring(" Or select a system".snl) more = yes j = i+1 exit finish repeat finish else exit if more = no start printstring("type '?' for full list; '?key' to start search on 'key';") if transfers call = yes then printstring(" <return> terminates".snl) c else printstring(" Or select a host.".snl) s3 = "" more = no j = 1 cycle m = 1,1,stations set(m) = no repeat last key checked = "" finish repeat return if transfers call = yes unless reply ->s1.("[").s2.("]").s3 and s1=s3="" start i = lookup host(reply) if i = 0 then printstring("External System not known".snl) and -> sys finish to docstring(document,document_ftp alias,reply) another: direction = out cycle prompt("Direction : ") read prompt reply(reply,no) ! exit if reply = "IN" or reply = "OUT" printstring(snl."Reply either IN : FROM ".docstring(document,document_ftp alias)) printstring(" TO local EMAS ".snl. c " or OUT : FROM local EMAS TO ".docstring(document,document_ftp alias).snl) repeat if reply = "IN" then direction = in cycle prompt("Mode : ") read prompt reply(reply,no) if length(reply) >= 2 start mode = 0 cycle i = 1,1,modes if mode key(i) -> (reply).s1 then mode = i and exit repeat if direction = in and replace <= mode <= file then document_ftp user flags = c document_ftp user flags ! overwrite exit if mode # 0 finish if direction = in start s1 = "your filespace" s2 = "to a UKCnet device" s3 = "Request output from a SPOOL queue at ".docstring(document,document_ftp alias) s3 = s3.snl." ".s2 finish else start s1 = "the filespace at ". docstring(document,document_ftp alias) s2 = "to a device at ". doc string(document,document_ftp alias).snl." (Not available". c " on all systems)" s3 = "Submit a JOB to run at ".docstring(document,document_ftp alias) finish printstring(snl."There are five modes:".snl) printstring("MAKE Make a new file in ".s1.snl. c "REPLACE Replace an existing file in ".s1.snl) printstring("FILE REPLACE or MAKE a file in ".s1.snl. c "OUTPUT Output the file ".s2.snl) printstring("JOB ".s3.snl) repeat if another pass = no start cycle prompt("External Username : ") read prompt reply(reply,yes) exit unless reply = "?" printstring(snl."Give the username at ".docstring(document,document_ftp alias)." who is the ". c " second party in the transfer.".snl) repeat to docstring(document,document_external user,reply) get pass: cycle prompt("External user pass : ") flag = uinfi(2) if flag = 1 then {foreground} journal off setmode("ECHO=OFF") read prompt reply(reply,yes) setmode("ECHO=ON") if flag = 1 then console(14,dummy,dummy) exit unless reply = "?" printstring(snl.snl."Give the 'External user pass' for ".docstring(document,document_external user). c " at ".docstring(document,document_ftp alias).snl) printstring("If no 'user specific' password is required then hit <return>". c snl."NOTE i) a filename password may be required and this can be ". c snl." set using the 'Option' facility that follows.".snl. c " ii) The user pass on EMAS is the background password.".snl) repeat newline unless reply = "" then to docstring(document,document_external password,reply) if prompt input = no then -> got pass new doc = document finish unless direction = out and mode = output start if mode = job and direction = out then s1 = "jobname" else s1 = "filename" cycle prompt("External ".s1." : ") reply = "" read prompt reply(xfilename,yes) exit unless xfilename = "?" printstring(snl."Give the ".s1." at ".docstring(document,document_ftp alias).".".snl) repeat finish finish else start !we have a single line command if length(s) > 132 then printstring("Command line too long".snl) and return !printstring("Line : ".s.snl) if s = "?" or s = "HELP" or s = "help" then start message = "for example:".snl."TRANSFER( fred, UKC(ecdw12,passy)LP, output)".snl message = message ."and the extended form:".snl."TRANSFER( fred, ukc(ecdw12,passy)" message = message."mill, job,failmail,special(time=30,out=LPtx) )".snl help required = yes and -> fail structure finish prompt input = no s = reverse(s) options set = no extra prompts = no if (s-> s1.("+").s2 and s1 = "") or (s->s1.(",").s2 and s1 = "") then extra prompts = yes and s = s2 s = reverse(s) !Now see if a OPTIONS section is included. cycle i = 1,1,options cycle j = 2,1,length(option keys(i)) s3 = option keys(i); length(s3) = j s3 = ",".s3 cycle k = 1,1,modes cycle l = 2,1,length(mode key(k)) s2 = mode key(k) length(s2) = l s1 = ",".s2.s3 if s -> s7.(s1).s4 and ((s4 -> s5.(",").s6 and s5 = "") or c (s4 -> s5.("(").s6 and s5 = "") or s4 = "") start s = s7.",".mode key(k) options set = yes option fault check = yes options string = option keys(i).s4 !printstring("main string : ".s.snl."options : ".options string.snl) exit finish repeat exit if options set = yes repeat exit if options set = yes repeat exit if options set = yes repeat option fault check = no i = 0; direction = out if s -> s5.("(").s1 start if s5 -> s8.("[").s9.("]").s10 and s8=s10="" then i = pointers_guest entry c else i = lookup host(s5) if i # 0 start !We have found a host. direction = in s2 = "(".s1 s1 = "" finish else start s7 = s s1 = "" cycle exit unless s7 -> s4.(",").s5.("(").s3 if s5 -> s8.("[").s9.("]").s10 and s8=s10="" then i = pointers_guest entry c else i = lookup host(s5) s1 = s1.s4."," s2 = "(".s3 exit if i # 0 {We have found a host} s7 = s5."(".s3 repeat finish finish if i = 0 then message = "Cannot find a reference to a known 'External System'" c and -> fail structure to docstring(document,document_ftp alias,s5) if direction = out start if s1 -> s1.(",").s3 then lfile = s1 else message = "Cannot find the 'Local Name'." c and -> fail structure finish s2 = reverse(s2) unless s2 -> s1.(",").s2 then message = "Cannot find a valid 'Mode'." and -> fail structure s1 = reverse(s1) mode = 0 cycle i = 1,1,modes if mode key(i) -> (s1).residual then mode = i and exit repeat if mode = 0 or length(s1) < 2 then message = "The 'Mode' is not understood." and -> fail structure if direction = in start if replace <= mode <= file then document_ftp user flags = c document_ftp user flags ! overwrite unless s2 -> lfile.(",").s2 then message = "Cannot find the 'Local Name'." and -> fail structure lfile = reverse(lfile) finish s2 = reverse(s2) unless s2 -> ("(").s2.(")").xfilename then message = "Cannot find the 'External Name'." c and -> fail structure s2 = reverse(s2) unless s2 -> s1.(",").s2 then message = "Cannot find the 'External User Pass'." and -> fail structure s1 = reverse(s1) todocstring(document,document_external password,s1) s2 = reverse(s2) todocstring(document,document_external user,s2) ! !Now look at the supplied (if it is ) options string. if options set = yes start option fault check = yes options string = ",".options string cycle true option = no cycle i = 1,1,options cycle j = length(option keys(i)),-1,2 s2 = option keys(i); length(s2) = j s2 = ",".s2 if options string -> s1.(s2).s7 and s1 = "" start options string = s7 true option = yes !printstring("op: ".option keys(i)."; left : ".options string.snl) -> lopt(i) finish continue lopt(1): exit lopt(2): if get param(s4,yes) = 0 then message = "No parameter needed for ". c option keys(i) and -> fail structure !printstring("NO MAIL set".snl) document_ftp user flags = document_ftp user flags ! no mail and exit lopt(3): if get param(s4,yes) = 0 then message = "No parameter needed for ". c option keys(i) and -> fail structure !printstring("FAIL MAIL set".snl) document_ftp user flags = document_ftp user flags ! fail mail and exit lopt(4): if get param(s4,no) # 0 then message = "Parameter needed for ". c option keys(i) and -> fail structure !printstring("DELIVERY set to : ".s4.snl) to docstring(document,document_delivery,s4) and exit lopt(5): if get param(s4,yes) # 0 then message = "Parameter needed for ". c option keys(i) and -> fail structure k = s to i(s4) if 0 <= k <= 255 then document_forms = k {%and printstring("FORMS set to : ".s4.snl)} and exit message = "Forms parameter in range 0 -> 255 please." and -> fail structure lopt(6): if get param(s4,no) # 0 then message = "Parameter needed for ". c option keys(i) and -> fail structure printstring("FILE PASSWORD set to : ".s4.snl) to docstring(document,document_ftp file password,s4) and exit lopt(7): if get param(s4,no) = 0 then message = "No parameter needed for ". c option keys(i) and -> fail structure -> term lopt(8): if get param(s4,yes) # 0 then message = "Parameter needed for ". c option keys(i) and -> fail structure cycle k = 1,1,priorities if priority names(k) = s4 then document_priority = k {%and printstring(} c {"PRIORITY set to : ".s4.snl)} and exit repeat unless document_priority = -1 then exit message = "Invalid PRIORITY parameter" and -> fail structure lopt(9): if get param(s4,yes) # 0 then message = "Parameter needed for ". c option keys(i) and -> fail structure !printstring("SIZE set to : ".s4.snl) k = s to i(s4) document_data length = k<<10 exit lopt(10): lopt(12): lopt(13): if get param(s4,yes) = 0 then message = "No parameter needed for". c " option ".option keys(i) and -> fail structure if direction # in then message = option keys(i)." on INcom". c "ng transfers only." and -> fail structure if i = 10 then document_ftp user flags = document_ftp user flags ! ANSI if i = 12 then document_ftp user flags = document_ftp user flags c ! binary read only if i = 13 then document_ftp user flags2 = document_ftp user c flags2 ! text read only exit lopt(11): if get param(s4,no) # 0 then message = "No parameter for". c " option ".option keys(i) and -> fail structure printstring("SPECIAL set to : ".s4.snl) to docstring(document,document_special options,s4) repeat if options string = "" or true option = yes then exit repeat exit if options string = "" if true option = no then message = "Cannot interpret options : ". c options string and -> fail structure repeat finish option fault check = no if docstring(document,document_external password) = "?" then -> get pass got pass: finish unless direction = in and mode >= output start if prompt input = yes start locn: cycle prompt("Local filename : ") reply = "" read prompt reply(lfile,no) exit unless lfile = "?" printstring(snl."Give the filename on EMAS.".snl) repeat finish if lfile -> s1.("_").s2 and direction = in then start printstring("Cannot transfer INto PD file".snl) -> locn finish lbase = "" if lfile -> s1.(".").s2 then lfile = s2 and lbase = s1."." if lbase # "" and direction = in start printstring("cannot copy INto another user's index.".snl) -> locn finish if direction = in start unless 1<= length(lfile) <= 11 then printstring("Local filename wrong length".snl) c and -> locn cycle i = 1,1,length(lfile) j = byteinteger(addr(lfile)+i) unless (i > 1 and '0' <= j <= '9') or 'A' <= j&95 <= 'Z' c or ( i>1 and j = '#') then printstring("Invalid local filename".snl) and -> locn repeat finish connect(lbase.lfile,0,0,0,re,flag) if flag # 0 and direction = out start PRINTSTRING("***") printstring(failure message(flag).snl) -> locn finish if direction = out start file header == record(re_conad) document_data length = file header_end-file header_start if document_data length = 0 then printstring(lfile." empty.".snl) c and -> locn document_data start = file header_start finish else document_data length = 100<<10 if flag # 0 and direction = in and mode = replace start printstring("Cannot 'REPLACE', ".lfile." does not exist!".snl) -> locn finish if flag = 0 and direction = in start if replace <= mode <= file then c printstring("Overwriting ".lfile.snl) if mode = make start printstring("Cannot 'MAKE', ".lfile." already exists.".snl) -> locn finish finish finish -> mode sw(mode) mode sw(1): if direction = in then document_mode of access = x'8002' c else document_mode of access = x'0001' -> direction sw(direction) mode sw(2): if direction = in then document_mode of access = x'8002' else c document_mode of access = x'0002' -> direction sw(direction) mode sw(3): if direction = in then document_mode of access = x'8002' else c document_mode of access = x'0003' -> direction sw(direction) mode sw(4): if direction = in then document_mode of access = x'8002' c and s1 = "Local " else document_mode of access = x'4001' and s1 = "External " get device: if direction = in then document_ftp user flags = document_ftp user flags ! local output !if set the user flags to say this incomming locally initiated file !transfer is to go to a device that will be plonked in the DEVICE TYPE field. if prompt input = yes start cycle prompt(s1."device name : ") reply = "" read prompt reply(reply,no) if reply = "?" then start if direction = in then printstring(snl."This is an incoming ". c "transfer so the device must be a valid ".snl."UKC printer, ie LP,LPCL..".snl) if direction = out then printstring(snl."This is an outgoing transfer ". c "so you must give a device at".snl.docstring(document, c document_ftp alias).", if in doubt ". c "reply LP and the system at ".docstring(document,document_ftp alias). c " will".snl."be asked to make the choice".snl) finish else exit repeat finish else start if direction = in then reply = lfile else reply = xfilename finish if s1 = "Local " and reply -> (".").s1 then reply = s1 to docstring(document,document_device type,reply) -> direction sw(direction) mode sw(5): !the JOB mode if direction = in start document_mode of access = x'C001' s1 = "local " -> get device finish document_mode of access = x'2001' -> direction sw(direction) direction sw(in): if mode >= output then to docstring(document,document_name,reply) c else to docstring(document,document_name,lfile) to docstring(document,document_external name,xfilename) -> transfer direction sw(out): if re_filetype # 3 and re_filetype # 4 c then document_ftp user flags = document_ftp user flags ! non text or data c and printstring("Warning, this non text transfer will only succeed with". c " EMAS 2900".snl) c else if re_filetype = 4 start document_ftp user flags = document_ftp user flags ! data document_ftp data record = integer(re_conad + 24) !The binary date record structure word. finish pages = (integer(re_conad)+4095)>>12 tfile <- "F#".lfile if tfile -> s1.("_").s2 then tfile = s1 outfile(tfile,pages<<12,pages<<12,0,conad,flag) if flag # 0 then fail(failure message(flag)) move(integer(re_conad),re_conad,conad) disconnect(tfile,flag) to docstring(document,document_srce,tfile) to docstring(document,document_name,lfile) unless mode = output then to docstring(document,document_external name,xfilename) transfer: unless mode >= output and direction = in then disconnect(lbase.lfile,flag) !first pick up any special options. if extra prompts = no then -> skip options cycle prompt("Options :") read prompt reply(reply,no) if reply = "?" start printstring(snl."The option section allows you to set any extra control". c " that may be required.".snl."It is terminated by '.END'".snl. c "The options available are:".snl) s1 = "" cycle i = 1,1,options s1 = s1." ".option keys(i) if length(s1) > 60 then printstring(s1.snl) and s1 = "" repeat if 0 < length(s1) <= 60 then printstring(s1.snl) printstring("NOTE that the first two letters will suffice.".snl. c "reply '?' for FURTHER DETAILS or select an option.".snl) prompt("Options :") read prompt reply(reply,no) if reply -> s1.("?").s2 start printstring("The final result of a transfer is, by default, reported ". c " to the".snl."initiating user via MAIL. There are two options". c " override this.".snl) printstring("All File Transfer activity is handled like other". c " user documents ".snl."and so the subsystem commands DOCUMENTS etc. can be used.".snl) cycle i = 1,1,option help lines printstring(option help(i).snl) repeat continue finish finish cycle i = 1,1,options if length(reply) >= 2 and option keys(i) -> (reply).s1 then -> option act(i) repeat printstring("Invalid option".snl) continue option act(1): exit option act(2): document_ftp user flags = document_ftp user flags ! no mail continue option act(3): document_ftp user flags = document_ftp user flags ! fail mail continue option act(4): cycle prompt("Deliver to: ") read prompt reply(reply,no) if reply = "?" then printstring(snl."Give the delivery information ". c "(for example: J.K.H at SIAE)".snl) and continue to docstring(document,document_delivery,reply) exit repeat continue option act(5): cycle prompt("Forms setting: ") read prompt reply(reply,no) if reply = "?" then printstring(snl."0 -> 255 are valid forms settings".snl) c and continue i = s to i(reply) if 0<=i<=255 then document_forms = i and exit else c printstring("Invalid forms, 0 -> 255 !".snl) repeat continue option act(6): cycle prompt("File password: ") flag = uinfi(2) if flag = 1 then {foreground} journal off setmode("ECHO=OFF") read prompt reply(reply,yes) setmode("ECHO=ON") if flag = 1 then console(14,dummy,dummy) newline if reply = "?" or reply = "" then printstring c ("Give the FTP password that is assigned to the file at ". c docstring(document,document_ftp alias).snl) and continue exit repeat to docstring(document,document_ftp file password,reply) continue option act(7): destroy(tfile,flag) -> term option act(8): cycle prompt("value: ") read prompt reply(reply,no) if length(reply) >1 start cycle i = 1,1,priorities if priority names(i) -> (reply).s1 then start document_priority = i exit finish repeat finish if document_priority = -1 start printstring(snl."Replies:") cycle i = 1,1,priorities printstring(" ".priority names(i)) repeat newline finish else exit repeat continue option act(9): if direction = out then printstring("Not required".snl) and continue cycle prompt("Kbytes: ") read prompt reply(reply,no) i = s to i(reply) if reply = "?" or i < 1 or i > 10000 then c printstring(snl."reply with estimate of total Kbytes of the file".snl) c else exit repeat document_data length = i<<10 continue option act(12): option act(13): option act(10): if direction = out start printstring(snl."Only for INcoming file transfers.".snl) continue finish if i = 10 then document_ftp user flags = document_ftp user flags ! ANSI if i = 12 then document_ftp user flags = document_ftp user flags c ! binary read only if i = 13 then document_ftp user flags2 = document_ftp user c flags2 ! text read only continue option act(11): !Special Options. if direction = in start printstring(snl."Only for OUTgoing file transfers.".snl) continue finish prompt("Value: ") read prompt reply(reply,no) to docstring(document,document_special options,reply) continue repeat skip options: document_header = "BINDOC:" p = 0 flag = 0 flag = dspool(p,(5<<24)!264,addr(document)) if flag # 0 and flag # p_p1 then printstring("File Transfer System not available".snl) c and return if p_p1 = 0 and p_p2 > 0 start printstring("NIFTP-B(80) Transfer queued, entry: T".itos(p_p2).snl) term: return if prompt input = no cycle printstring("Another transfer with ".docstring(document,document_external user). c " at ".docstring(document,document_ftp alias)." ?".snl) prompt(": ") read prompt reply(reply,no) return if reply -> ("N").s1 exit if reply -> ("Y").s1 printstring(snl."Reply YES if you wish to initialise another transfer ".snl. c "with the same user on the same external system else reply NO".snl) repeat another pass = yes document = new doc -> another finish else start if p_p1 = 1 then fail("Local user not known !!!") if p_p1 = 2 then fail("No free spooler descriptors.") if p_p1 = 3 then fail("DTRANSFER/DCONNECT fails") if p_p1 = 4 then fail("Unknown external system. ") if p_p1 = 5 then fail("Transfer queue full.") if p_p1 = 6 then fail("Bad params!") if p_p1 = 7 then fail("Unaccepted mode of transfer") if p_p1 = 8 then fail("Gateway FTP access barred, accreditation required.") fail("Unknown failure") finish fail structure: printstring("TRANSFER help requested or request not understood, The ") if option fault check = no or help required = yes start printstring("command is".snl." TRANSFER(SOURCE,SINK,MODE)".snl) printstring("with substructure of SOURCE and SINK as either".snl) printstring(" 1) A simple EMAS file name, or job name, or UKC device name".snl) printstring("or 2) External System(External User,External User Pass)External Name".snl) printstring(" where External Name is a file/job/device name at the External Site".snl) finish if option fault check = yes or help required = yes start if help required = yes then printstring(snl."Options can ". c "be included on an extended command. The ") printstring("extended ".snl."Command is of the form :".snl. c " Command:TRANSFER( SOURCE, SINK, MODE,option,option,option......)".snl. c "Where 'option' is either 'keyword' or 'keyword(parameter)' .".snl) finish printstring(snl.message.snl) return integerfn get param(stringname sp, integer single param only) string (128) ss,sr,st,sq,su,residual,remainder result = 1 unless options string -> ss.("(").sp and ss = "" options string = "" and result = 1 unless (sp -> sp.("),"). c options string) or (sp -> sp.(")").options string and options string = "") if options string # "" and single param only = yes then c options string = ",".options string result = 0 if options string = "" or single param only = yes options string = "),".options string residual = "" remainder = "" !What we have to do now is sort out in a string x,y(z),a(,b),c which !part is actually parameter and which may be the next keyword. cycle i = 1,1,options cycle j = 2,1,length(option keys(i)) ss = option keys(i) length(ss) = j ss = "),".ss if options string -> st.(ss).sr start if ((sr -> sq.(",").su and sq = "") or (sr -> sq.("(").su c and sq = "") or sr = "") start if length(st) <= length(residual) or residual = "" start !printstring("residual set to : ".st.snl) residual = st remainder = option keys(i); length(remainder) = j remainder = ",".remainder.sr exit if residual = "" finish finish finish repeat if residual = "" and remainder # "" then exit repeat if remainder # "" start options string = remainder sp = sp.",".residual if residual # "" finish else sp = sp.options string and options string = "" !printstring("param : ".sp." remainder : ".options string.snl) result = 0 end end externalroutine transfers(string (255) param) constinteger queued = 1 constinteger unused = 0 constinteger unallocated = 0; !STREAM STATUS constinteger allocated = 1; !DITTO constinteger line active = 2; !DITTO constinteger connecting = 3; !DITTO constinteger disconnecting = 4; !DITTO constinteger aborting = 5; !DITTO constinteger suspending = 6; !DITTO constinteger deallocating = 7; !DITTO constinteger aborted = 8; !used by ftp line only constinteger selected = 9; !USED ONLY FOR ftp STREAMS constinteger awaiting sft = 10 constinteger sft sent = 11 constinteger awaiting stop = 12 constinteger stop sent = 13 constinteger rpos sent = 14 constinteger rneg sent = 15 constinteger stopack sent = 16 constinteger go sent = 17 constinteger receiving data = 18 constinteger transmitting data = 19 constinteger last block sent = 20 constinteger end of data sent = 21 constinteger quit sent = 22 constinteger end data ack sent = 23 constinteger p station = 0 constinteger full list = -1 constinteger current list = -2 constinteger rates = -3 constinteger open = 1 conststring (19)array status (0 : 24) = c "Calling","Calling","Calling","Calling","Call closing with","Call closing with", "Call closing with","Call closing with","Call closing with", "Calling","Called by","Calling","Call closing with", "Call closing with","Transferring with","Call rejected by","Call closing with", "Transferring with","Transferring with","Transferring with", "Transferring with","Transferring with","Call failing with", "Transferring with","Transferring with" record (lcf)arrayformat list cells af(1 : max documents) record (linef)arrayformat larf(1 : max lines) record (ftp stationf) arrayformat ftpsf(1: max stations) recordformat aheadf (integer jobs,nkb) record (aheadf)array ahead(1:MAX STATIONS) record (lcf)arrayname list cells record (lcf)array list cells copy(1:1000) record (pointers f)name pointers record (queuef)name queue record (linef)arrayname ftp lines record (ftp stationf) arrayname ftp stations record (fhf)name file header record (name f)name name entry record (rf) re record (document descriptorf)name document integer header printed, my fsys, flag, i, j, k, next , lines, stations, found, allset, fault count, rate, hash length integer station ptr, address cache addr string (6) my user string (87) entry,s string (132) extra,ex1,ex2 string (6) line integer actcon, active, busy, count, deferred,station specific, guest address set byteintegerarray station set(1:max stations) byteintegerarray station activity(1:max stations) !*********************************************************************** !* * !* THESE FUNCTIONS ALL USE A PACKED FORMAT OF DATE AND TIME OF THE * !* FOLLOWING FORM. BITS ARE NUMBERED FROM 31 (MOST SIGNIFICANT) TO * !* 0 (LEAST SIGNIFICANT) * !* BITS USE * !* 31-26 YEAR-70 (VALID FOR 1970-2033) * !* 25-22 MONTH * !* 21-17 DAY * !* 16-12 HOUR * !* 11- 6 MINUTE * !* 5- 0 SECOND * !* * !*********************************************************************** stringfn s2(integer n) !THIS FUNCTION RETURNS A TWO DIGIT DECIMAL VALUE FOR N integer tens, units tens = n//10 units = n-10*tens result = tostring(tens+'0').tostring(units+'0') end ; !OF S2 stringfn doc string(record (document descriptor f)name document, byteintegername ptr) if ptr = 0 then result = "" else c result = string(addr(document_string space) + ptr) end !* integer fn hashed(string (63) name) integer i, pt, n, h byte integer array x(0:15) const byte integer array prime(1:7)= 23, 19, 11, 7, 5, 13, 17 pt = (addr(x(7))>>3)<<3 longinteger(pt) = 0 n = addr(name) byteinteger(pt+i&7) = byteinteger(pt+i&7)!!byteinteger(n+i) for i = 0, 1, length(name) h = length(name)*29 h = h+prime(i)*byteinteger(pt+i) for i = 1, 1, 7 result = h&hash length end ; !of hashed integer fn lookup hasht(string (63) name) record (name f) name name entry integer h h = hashed(name) if pointers_hasht(h)#-1 start name entry == record(re_conad + pointers_hasht ( h )) cycle if name=name entry_name then result = name entry_host entry exit if name entry_link = -1 name entry == record ( re_conad + name entry_link ) repeat finish result = 0 end ; !of lookup hasht integer fn lookup host(string (63) name) integer i string (63) rest {uctranslate or lc?} i = lookup hasht(name) if i#0 then result = i unless name->(this ukac.".").rest start i = lookup hasht(this ukac.".".name); !prefix uk.ac if i#0 then result = i if name->name.(".").rest then result = lookup hasht(name); !for arpa. finish result = 0 end ; !of lookup host routine connect trans db(integername flag) connect("FTRANS.CFILE",r!sh,0,0,re,flag) !connect("TESTFILE",r,0,0,re,flag) if flag # 0 and flag # 34 start printstring("Cannot connect TRANSFER systems database".snl) return finish flag = 0 file header == record(re_conad) pointers == record(re_conad + file header_start) lines = pointers_streams stations = pointers_stations hash length = pointers_hash length ftp lines == array(re_conad + pointers_stream displ, larf) ftp stations == array(re_conad + pointers_station displ,ftpsf) list cells == array(Re_conad + pointers_link list displ, list cells af) queue == record(Re_conad + pointers_queue displ) address cache addr = re_conad + pointers_station addresses displ end routine fill(integer to length, front, stringname s,string (1) char) integer i, j if length(s) < to length start j = to length - length(s) cycle i = 1,1,j if front = yes then s = char.s else s = s.char repeat finish end routine print doc details(integer document id,ptr,line,jobs,nkb) string (87) t integer size, this entry is guest this entry is guest = no entry = "" s = "T".i to s((document id<<8)>>8) fill(4,yes,s," "); entry = s s = docstring(document,document_name) if length(s) > 11 then length(s) = 11 else fill(11,no,s,".") entry = entry." ".s s = unpack date(document_date and time received) length(s) = 5 entry = entry." ".s s = unpack time(document_date and time received) length(s) = 5 entry = entry." ".s if line = 0 start size = (document_data length+1023)>>10 if size > ftp stations(pointers_control entry)_limit or size > ftp stations(ptr)_ c limit then deferred = yes and s = "Deferred on size" else s = "Queued for" fill(17,no,s,".") entry = entry." ".s finish else start s = status(ftp lines(line)_status) fill(17,no,s,".") entry = entry." ".s finish if ptr = pointers_guest entry start entry = entry." [given address]" this entry is guest = yes guest address set = yes finish else start s = string(addr(ftp stations(ptr)_string space(0))+ftp stations(ptr)_shortest name) if length(s) > 15 then length(s) = 15 fill(15,yes,s,".") entry = entry." ".s finish if line = 0 start s = i to s(jobs) fill(10,yes,s,".") entry = entry." ".s s = itos(nkb) fill(5,yes,s,".") entry = entry." ".s finish else start if ftp lines(line)_status = transmitting data or ftp lines(line)_status c = receiving data start s = itos((ftp lines(line)_bytes transferred+1023)>>10) fill(4,yes,s,"."); entry = entry." ".s." Kb" if ftp lines(line)_status = receiving data then c ENTRY = ENTRY." Received" else ENTRY = ENTRY." Sent" finish finish printstring(entry.snl) return unless this entry is guest = yes printstring(" For: [".docstring(document,document_guest address)."]".snl) end integerfn document addr(integer param) !*********************************************************************** !* * !* * !*********************************************************************** record (fhf)name file header INTEGER I i = (param&x'ff000000')>>24 connect("FTRANS.FTPLIST".itos(i),r!sh,0,x'00000080'!(i<<8),re,flag) if flag # 0 and flag # 34 start printstring("TRANLIST".itos(i)." conn fails ".itos(flag).snl) result = 0 finish file header == record(re_conad) i = re_conad+file header_start+(param&x'ffffff'-1)* c document entry size result = I end ; !OF INTEGERFN map DOCUMENT routine print header printstring("Doc_ Name_______ Submitted__ State____________". c " Ext. System____ Ahead:Docs / Nkb".snl) end !FTP Station STATUS list. !0 General accesss station !1 PSS accreditation (bit 6) required !5 Masked (ALIAS) but can be seen in TRANSFERS(.ALL) enquiries !6 MASKED and is invisable even in TRANSFERS(.ALL) enquiry. !7 As 6 but requires ACR 9 for access at all. connect trans db(flag) return if flag # 0 fault count = 0 again: if fault count = 3 start printstring("There is a 'hard' problem, please submit this monitor to Advisory".snl.snl) monitor return finish station specific = 0; allset = no if param ->("?").extra and extra # "" then param = "FROMTRANSFERS".param c and transfer(param) and return if param = "?" or param = "HELP" or param = "help" start printstring("The optional parameters to the Command TRANSFERS are as follows:".snl.snl) printstring("i) No parameter. In this case all Transfer Requests outstanding for".snl) printstring(" you will be listed together with a summary of the status of both the Local".snl) printstring(" File Transfer System and the External File Transfer Systems for which ".snl) printstring(" you have outstanding requests.".snl.snl) printstring("ii) TRANSFERS('sys') where 'sys' is the name of an External System.".snl) printstring(" In this case all Transfer Requests that you have outstanding for this".snl) printstring(" particular system will be listed together with the status of the Local".snl) printstring(" File Transfer System and that of the External File Transfer System in".snl) printstring(" detail. Note that this can be issued regardless of whether you have".snl) printstring(" Transfer Requests outstanding for the External System in question .".snl) printstring(" For example TRANSFERS(ERCVAX) TRANSFERS(LIVUNIV.VAX2)".snl.snl) printstring("iii) TRANSFERS('?key') This is a more general form of the above.".snl. c " The '?' in '?key' indicates that a general search on the External".snl. c " Host database is required with a search key of value 'key'. Once".snl) printstring(" in this mode any number of searches with any number of keys can be".snl. c " can be undertaken. Example TRANSFERS(?EDINBURGH)".snl.snl) printstring("iv) TRANSFERS(.ALL) This command will give the status of the Local File".snl) printstring(" Transfer System together with the status of all the External File Transfer".snl) printstring(" Systems for which there are requests outstanding or in progress for any".snl) printstring(" user. In effect it gives a complete work profile of the".snl) printstring(" Local File Transfer system.".snl.snl) return finish guest address set = no if param = "RATES" or param = "rates" then station specific = rates if param = "*" then station specific = full list if param -> (".ALL").param or param -> (".all").param then station specific = current list if station specific <= full list then all set = yes and param = "" cycle i = 1,1,stations station activity(i) = no station set(i) = no!allset repeat if param # "" start !We want to look at a specific NRS host. i = lookup host(param) if i # 0 then station specific = i and param = "" finish header printed = no found = no if param # "" start printstring("Invalid parameter...further facilities available soon.".snl) disconnect("FTRANS.CFILE",flag) and return finish my user = uinfs(1) my fsys = -1 flag = dfsys(my user, my fsys) if station specific = rates then -> just rates !General query cycle i = 1,1,lines if ftp lines(i)_document # 0 start station activity(ftp lines(i)_station ptr) = yes if ftp lines(i)_status # selected and ftp lines(i)_document>>24 = my fsys start if ftp lines(i)_user = my user start document == record(document addr(ftp lines(i)_document)) if document_state # unused start !An active transfer for this user if station specific = 0 or ftp lines(i)_station ptr = station specific start if header printed = no then print header and header printed = yes print doc details(ftp lines(i)_document,ftp lines(i)_station ptr,i,0,0) station set(ftp lines(i)_station ptr) = yes found = yes finish finish if ftp lines(I)_status = awaiting sft or c RPOS sent <= ftp lines(i)_status <= STOPACK sent or (ftp lines(i)_station type # c p station and receiving data <= ftp lines(i)_status <= c end data ack sent) then station set(ftp lines(i)_station ptr) = yes c and found = yes finish finish finish repeat cycle i = 1,1,max documents list cells copy(i) = list cells(i) repeat next = queue_head cycle i = 1,1,stations ahead(i) = 0 repeat while next # 0 cycle station ptr = list cells copy(next)_station ptr unless 0< station ptr <= stations start printstring("PROBLEM, (bad pointer ".itos(station ptr)." rechecking".snl) header printed = no fault count = fault count + 1 - > again finish station activity(station ptr) = yes deferred = no if station specific > full list start if list cells copy(next)_document >> 24 = my fsys start document == record(document addr(list cells copy(next)_document)) if document_user = my user start if document_state # queued start printstring("PROBLEM , (bad state ".itos(document_state).") rechecking!".snl) fault count = fault count + 1 header printed = no -> again finish if station specific = 0 or station ptr = c station specific start if header printed = no then print header and header printed = yes print doc details(list cells copy(next)_document,list cells copy (next)_ c station ptr,0,ahead(station ptr)_jobs, c ahead(station ptr)_nkb) station set(station ptr) = yes found = yes finish finish finish if deferred = no start ahead(station ptr)_jobs = ahead(station ptr)_jobs + 1 ahead(station ptr)_nkb = ahead(station ptr)_nkb + (list cells copy(next)_size+1023)>>10 finish finish next = list cells copy(next)_link repeat if station specific > full list start if station specific = 0 then extra = "" else extra = " for ". c string(addr(ftp stations(station specific)_string space(0)) c + ftp stations(station specific)_shortest name) if found = no start printstring("You have no FILE TRANSFER requests".extra.snl) if station specific = 0 then -> out finish finish count = 0 busy = no active = no if guest address set = yes then printstring(snl."NOTE no further". c " details on <given address> requests provided.".snl) cycle i = 1,1,lines count = count + 1 if ftp lines(i)_status >= LINE active and ftp lines(i)_ c station type = p station repeat if count >= ftp stations(pointers_control entry)_max lines - ftp stations(pointers_control entry)_q lines c then busy = yes printstring(snl."*Local Transfer Service is ") unless ftp stations(pointers_control entry)_service = open then printstring("Closed, ") c else printstring("Open, ") and printstring("Limited to ".itos(ftp stations(pointers_control entry)_limit)."kb ") if busy = yes then printstring("[ All LINES ARE IN USE ]") else start printstring("[Records start: ") s = unpack date(ftp stations(pointers_control entry)_system loaded) length(s) = 5 printstring(s." ") s = unpack time(ftp stations(pointers_control entry)_system loaded) length(s) = 5 printstring(s."]") finish newlines(1) if station specific > 0 start i = ftp stations(station specific)_shortest name printstring(string(addr(ftp stations(station specific)_string space(0)) c + ftp stations(station specific)_shortest name)." : ") s = string(addr(ftp stations(station specific)_string space(0)) c + ftp stations(station specific)_description) if s -> ("~").s then s = s printstring(s.snl) printstring("Full Name : ".string(addr(ftp stations(station specific)_ c string space(0)) + ftp stations(station specific)_name).snl) printstring("Primary TS address : ") extra = string(address cache addr+ftp stations(station specific)_address(1)) if extra -> ex1.("(").(",").(")").ex2 then extra = ex1.ex2 printstring(extra.snl) printstring("Accepts transfers". c " up to ".itos(ftp stations(station specific)_limit)."kb") printstring("; maximum of ".itos(ftp stations(station specific)_max lines). c " concurrent transfer(s).".snl) printstring("Transaction Summary:") if FTP stations(station specific)_seconds > 0 start printstring(" {Last ".itos((ftp stations(station specific)_ c bytes+1023)>>10)." kb transferred at average ") rate =FTP stations(station specific)_bytes//FTP stations(station specific)_seconds printstring(itos(rate)." bytes/second}") finish newline printstring("A) with ".string(addr(ftp stations(station specific)_ c string space(0)) + ftp stations(station specific)_shortest name)." as ". c "responder to Local Transfer Requests".snl) if ftp stations(station specific)_P transfers = 0 then c printstring(" No Transfers.".snl) else start printstring(" There have been ".itos(FTP stations(station specific)_P transfers)." transfers") if ftp stations(station specific)_P mail > 0 then c printstring(" ( ".itos(ftp stations(station specific)_P mail)." were MAIL )") newlines(1) printstring(" Total of ".itos( c ftp stations(station specific)_P kb)." Kilobytes transferred ( ") print(ftp stations(station specific)_P kb/ftp stations(station specific)_ c P transfers,1,1) printstring(" Kb/transfer )".snl) finish printstring("B) with Local Transfer Service as responder ". c "to Transfer requests from ".string(addr(ftp stations(station specific)_ c string space(0)) + ftp stations(station specific)_shortest name).snl) if ftp stations(station specific)_last q response by us = -1 then c printstring(" No record of a serviced call from ".string(addr( c ftp stations(station specific)_string space(0)) + ftp stations( c station specific)_shortest name).".".snl) else start printstring(" Last serviced call from ".string(addr( c ftp stations(station specific)_string space(0)) + ftp stations(station specific)_ c shortest name)." was at ") s = unpack date(ftp stations(station specific)_last Q response by us) length(s) = 5 printstring(s." ") s = unpack time(ftp stations(station specific)_last Q response by us) length(s) = 5 printstring(s.snl) finish if ftp stations(station specific)_Q transfers = 0 then printstring( c " No Transfers.") else start printstring(" There have been ".itos(FTP stations(station specific)_Q transfers)." transfers") if ftp stations(station specific)_Q mail > 0 then c printstring(" ( ".itos(ftp stations(station specific)_Q mail)." were MAIL )") newlines(1) printstring(" Total of ".itos( c ftp stations(station specific)_Q kb)." Kilobytes transferred ( ") print(ftp stations(station specific)_Q kb/ftp stations(station specific)_ c Q transfers,1,1) printstring(" Kb/transfer )") finish newlines(2) finish if station specific = current list start cycle i = 1,1,stations if station activity(i) = no then station set(i) = no repeat finish if station specific <= full list then station specific = 0 printstring("Ext. System____ Last Reply__ Last Call__ Line NOTES".snl) if station specific # 0 then actcon = no and i = station specific and -> specific just rates: cycle i = 1,1,stations continue if ftp stations(i)_address type = BASE type { do not look at DIRECTORY entries} actcon = no if station set(i) = yes and ftp stations(i)_status <6 start specific: s = string(addr(ftp stations(i)_string space(0)) + ftp stations(i)_shortest name) fill(15,no,s,".") entry = s if station specific = rates start if FTP stations(i)_seconds > 0 start printstring(entry." Last ".itos((ftp stations(i)_ c bytes+1023)>>10)." kb transferred at average ") rate =FTP stations(i)_bytes//FTP stations(i)_seconds printstring(itos(rate)." bytes/second") newline finish continue finish if ftp stations(i)_last response = -1 then entry = entry." No Record" c else start s = unpack date(ftp stations(i)_last response) length(s) = 5 entry = entry." ".s s = unpack time(ftp stations(i)_last response) length(s) = 5 entry = entry." ".s finish if station activity(i) = no start printstring(entry); printstring(" ........... - IDLE, no transfer requests.".snl) entry = "" actcon = yes finish active = no cycle j = 1,1,lines if ftp lines(j)_document # 0 and ftp lines(j)_station ptr = i start if ftp lines(j)_status = connecting or ftp lines(j)_status = sft sent c or ftp lines(j)_status = selected then active = yes and exit finish repeat if active = no or station activity(i) = no start if ftp stations(i)_last call # 0 and station activity(i) = yes start s = unpack date(ftp stations(i)_last call) length(s) = 5 entry = entry." ".s s = unpack time(ftp stations(i)_last call) length(s) = 5 entry = entry." ".s finish else entry = entry." ..........." finish else entry = entry." ..........." if ftp stations(i)_last call # 0 and ((active = no and station activity(i) = yes) c or active = yes) start s = " ".i to s(ftp stations(i)_connect attempts)." Calls since last reply." entry = entry." - ".s printstring(entry.snl); actcon = yes unless active = yes start if ftp stations(i)_connect retry time = 0 then s = c "Will re-call in a few seconds." else start s = "Will re-call within " k = ftp stations(i)_connect retry time if k = 1 then s = s."a minute." else s = s.itos(k)." mins." finish spaces(43); printstring("- ".s.snl) finish finish cycle j = 1,1,lines line = i to s(j) fill(3,yes,line," ") line = line." " if ftp lines(j)_document # 0 and ftp lines(j)_station ptr = i start if ftp lines(j)_status = selected or ftp lines(j)_status = c connecting or ftp lines(j)_status = sft sent start document == record(document addr(ftp lines(j)_document)) s = line." Calling for " if document_user = my user then s = s."you." else if c document_user = "MAILER" then s = s."MAIL." else s = c s."another user." if actcon = no start entry = entry." ".s printstring(entry.snl); actcon = yes finish else spaces(41) and printstring(s.snl) finish else if ftp lines(j)_status = stop sent or c ftp lines(j)_status = go sent or (ftp lines(j)_station type = c p station and receiving data <= ftp lines(j)_status <= c end data ack sent) start s = line." Currently active for " document == record(document addr(ftp lines(j)_document)) if document_user = my user then s = s."you" else if c document_user = "MAILER" then s = s."MAIL." else c s = s."another user." if actcon = no start entry = entry." ".s printstring(entry.snl); actcon = yes finish else spaces(41) and printstring(s.snl) finish else if ftp lines(j)_status = awaiting sft or c RPOS sent <= ftp lines(j)_status <= STOPACK sent or (ftp lines(j)_station type # c p station and receiving data <= ftp lines(j)_status <= c end data ack sent) start s = line." External call active for " document == record(document addr(ftp lines(j)_document)) if document_user = my user then s = s."you" else if c document_user = "MAILER" then s = s."MAIL." else c s = s."a user." if actcon = no start entry = entry." ".s printstring(entry.snl); actcon = yes finish else spaces(41) and printstring(s.snl) finish else if connecting < ftp lines(j)_status < selected start if actcon = no start entry = entry." ".line." Call closing." printstring(entry.snl); actcon = yes finish else spaces(41) and printstring(line." Call closing.".snl) finish finish repeat if actcon = no start if station activity(i) = yes start if busy = yes then entry = entry." - IDLE, Local Transfer System busy." c else entry = entry." - IDLE, deferred requests only." printstring(entry.snl) finish finish -> out if station specific # 0 finish repeat out: disconnect("FTRANS.CFILE",flag) disconnect("FTRANS.FTPLIST".itos(my fsys),flag) end ; !Of routine TRANSFER endoffile