include "ERCC10.MULTIspecs" record format parmf(integer dest, srce, p1, p2, p3, p4, p5, p6) recordformat rf(integer conad,filetype,datastart,dataend) systemroutinespec connect(string (31) file, integer mode,hole,protect, record (rf)name r, integername flag) systemroutinespec disconnect(string (31) file, integername flag) external routine spec mprintp(record (parmf) p) external routine spec give monitoring(string name tim, integer name secs, nbytes) system string fn spec itos(integer i) external integer fn spec bin(string (255) s) system routine spec uctranslate(integer adr, len) externalintegerfnspec dexecmess(string (6) user,integer sact,len,addr) routine uctran(string name s) uctranslate(addr(s)+1, length(s)) end {uctran} constbyteinteger not used = 255 constinteger oper display size = 22 constinteger max consoles = 127 constbyteinteger info = 0 constbyteinteger activity permitted = 1 constbyteinteger manager = 2 constbyteinteger not logged on = 0 constbyteinteger logged on ok = 1 const string (1) snl=" " conststring (31) manager only = "Manager console access only." conststringname date = x'80C0003F' conststringname time = x'80C0004B' owninteger already connected = 0 owninteger qs = 256 owninteger strms = 256 owninteger rmts = 256 own integer array consoles(0:127)=255(128) recordformat connectionf (string (15) name, string (63) it connection, integer display type, which display, which page, source, string (10) specific user, byteinteger status,type, disabled) own record (connectionf)array connections(0 : max consoles) !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !We now have the declarations wholesale from spoolr. conststring (7) array stream type(0 : 3) = c "Output", "Input", "Job", "Process" conststring (17) array stream status type(0 : 8) = c "Unallocated", "Allocated", "Active", "Connecting", "Disconnecting", "Aborting", "Suspending", "Deallocating", "Aborted" conststring (11) array remote status type(0 : 5) = c "Closed", "Open", "Logging On", "Logged On", "Switching", "Logging Off" constinteger n modes = 2 conststring (3) array modes(0 : n modes) = c "ISO", "EBC", "BIN" conststring (15) array doc state(0 : 6) = c "Deleted", "Queued", "Sending", "Running", "Receiving", "Processing", "Transferring" constinteger n priorities = 5 conststring (5) array priorities(1 : n priorities) = c "VLOW", "LOW", "STD", "HIGH", "VHIGH" constbyteintegerarray connect retry times (0 : 10) = c 0,5,10,10,15,25,40,60,60,60,60 conststring (2) array ocp type(0 : 15) = c "??", "50", "60", "70", "80", "72", "72", "??", "??", "??", "??", "??", "??", "??", "??", "??" conststring (2) array device type(0 : 15) = c "NA", "PP", "PR", "CP", "CR", "MT", "LP", "GP", "OP", "MP", "DO", "NA", "CT", "SU", "FE", "NA" constinteger on = 1 constinteger off = 0 constinteger no = 0 constinteger yes = 1 constinteger locked = 2 conststring (12) array header type(1 : 3) = c "Line Printer", "Paper Tape", "Card Punch" constintegerarray prtys(1 : n priorities) = c 1, 1000001, 2000001, 3000001, 4000001 constinteger max fsys = 99 constinteger no route = 0 constinteger p station = 0 constinteger max documents = 1000; !MAX DOCUMENT DESCRIPTORS ON EACH FILE SYSTEM constinteger document entry size = 256;!SIZE IN BYTES OF A DOCUMENT DESCRIPTOR constinteger info size = 256; !SIZE IN BYTES OF INFO RETURNED TO USERS constinteger max priority = 10000; !PRIORITY ADDED TO BASE PRIORITY IF RESOURCE = 0 constinteger small weight = 4; !THIS SHOULD BE INCREASED TO FAVOUR SMALL JOBS constinteger requested = 255 constinteger ok = 0; !GENERAL SUCCESSFUL REPLY FLAG constinteger rejected = 3 constinteger unused = 0; !DESCRIPTOR STATUS constinteger queued = 1; !DITTO constinteger sending = 2; !DITTO constinteger running = 3; !DITTO constinteger receiving = 4; !DITTO constinteger processing = 5; !DITTO constinteger transferring = 6; !FTP file transfer activity constinteger closed = 0; !REMOTE STATUS constinteger open = 1; !DITTO constinteger logging on = 2; !DITTO constinteger logged on = 3; !DITTO constinteger switching = 4; !DITTO constinteger logging off = 5; !DITTO constinteger unallocated = 0; !STREAM STATUS constinteger allocated = 1; !DITTO constinteger 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 all queues = 1; !WHICH DISPLAY TYPE constinteger all streams = 2; !DITTO constinteger individual queue = 3; !DITTO constinteger individual stream = 4; !DITTO constinteger non empty queues = 5; !DITTO constinteger active streams = 6; !DITTO constinteger individual document = 7; !DITTO constinteger full individual queue = 8;!DITTO constinteger all remotes = 9; !DITTO constinteger logged on remotes = 10; !DITTO constinteger individual remote = 11; !DITTO constinteger file header size = 32; !SS STANDARD FILE HEADER SIZE constinteger r = b'00000001'; !READ PERMITION constinteger w = b'00000010'; !WRITE PERMITION constinteger s = b'00001000' constinteger zerod = b'00000100'; !ZERO FILE ON CREATION constinteger tempfi = b'00000001'; !TEMP FILE ON CREATION constinteger list size = 1000; !SIZE OF QUEUE CELLS LIST constinteger max fep = 7; !MAXIMUM FEPS SUPPORTED constinteger last q per stream = 15; !NUMBER OF QUEUES BEING SERVED BY ONE STREAM constinteger last stream per q = 15; !NUMBER OF LAST STREAM SERVING EACH Q constinteger queue dest = 1 constinteger file dest = 2 constinteger newfile dest = 3 constinteger null dest = 4 ! constinteger output = 0; !serviceINE STREAM TYPE constinteger input = 1; !DITTO constinteger job = 2; !DITTO constinteger process = 3; !DITTO !Now the document property identifers. constbyteinteger dap batch flag = x'01' constbyteinteger media hold = x'01' constbyteinteger dap hold = x'02' constbyteinteger not media = x'fe' constbyteinteger not dap = x'fd' constinteger prelogon tied = 2; !INDICATES TYPE OF PRELOGGED ON STATE OF A REMOTE. constinteger prelogon untied = 1 constinteger unknown type = 0 constinteger NSI type = 1 constinteger X25 type = 2 !* recordformat pe(integer dest, srce, p1, p2, p3, p4, p5, p6) recordformat pointers f(integer queues, queue entry size, queue displ, queue name displ, streams, stream entry size, stream displ, stream name displ, remotes, remote entry size, remote displ, remote name displ, ftp stations, station entry size, ftp station displ) recordformat document descriptorf(byteinteger state, string (6) user, string (15) dest, integer date and time received, date and time started, halfinteger dap mins, dap c exec time, integer date and time deleted, start after date and time, priority, data start, data length, integer time, output limit, 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) or byteintegerarray ftp spares(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, sp1,sp2,sp3,sp4,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 streams(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 remotef(string (15) name, integer status, lowest stream, highest stream, fep, old fep, prelog fep, prelog, timeout, polling, command lock, byteinteger unused1, unused2, network address type, (byteinteger network address len, byteintegerarray network add(0 : 63) c or string (64) x25 address), byteintegerarray fep route value(0:max fep), string (31) description, string (7) password) !* !* !Note that the stream tables (and FTP line tables) are in two sections. !The first gives basic information used on stream 'scans', ie in !response to a QUEUE user command for active documents. The first section !will fit in a single page. The second sections contains the meaty bits. ! recordformat details f(string (15) name, string (7) user) recordformat stream f(string (15) name, string (7) unit name, integer q no, halfintegerarray queues(0 : 15), integer status, bytes sent, bytes to go, block, part blocks, document, string (6) barred user, byteinteger spare1, integer spare3, byteinteger service, user abort, unit size, fep, integer remote, abort retry count, offset, (integer in comms stream or integer comms stream), integer out comms stream, (integer in stream ident or integer ident), integer out stream ident, (integer limit, account, byteinteger device type, device no, forms, lowest priority, header type, header number, batch enable, invoc, string (55) unused or integer transfer status, tcc subtype, in block addr, out block addr, byteinteger activity, station type, station ptr, suspend, in stream status, out stream status, timer, output buffer status, output transfer pending, sp1,sp2,sp3, integer aux document, pre abort status, bytes transferred, record (pe) output transfer record)) !* !* recordformat lcf(integer document, priority, size, (byteinteger station ptr,ftp timer,ftp flags,gen flags or integer flags), integer link,string (7) user) !* recordformat fhf(integer end, start, size, type, free hole, datetime, spare1, spare2) recordformat message f(string (15) remote name, string (63) message) !* 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 integerfn s to i(string (255) 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 = x'80808080' end ; !OF INTEGERFN S TO I !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !The main entry points now follow external routine m initialise(string (63) user,pass,it connection,integer console) record (remote f)arrayformat rarf (1 : rmts) record (remote f)arrayname remotes record (connectionf)name connection record (pointers f)name pointers record (rf)re STRING (63) CALL integer i, entry, flag entry = -1 for i = 0,1,max consoles cycle if consoles(i) = not used then entry = i and exit repeat if entry = -1 start !All consoles in use. iprintstring("Sorry, busy"); inewline ilogoff(console) return finish cycle if pass # "" and (charno(pass,length(pass)) = 13 or charno(pass,length(pass)) = nl) c then length(pass) = length(pass) - 1 else exit repeat connect("SPOOLR.CFILEPTRS",r!s,0,0,re,flag) if flag # 0 and flag # 34 start iprintstring( "CFILEPTRS conn fail ".itos(flag).snl) ilogoff(console) return finish pointers == record(re_conad+file header size) if qs = 256 start !this is the first time in. qs = pointers_queues strms = pointers_streams rmts = pointers_remotes finish connection == connections(entry) consoles(entry) = console connection = 0 connect("SPOOLR.CFILE",r!s,0,0,re,flag) if flag # 0 and flag # 34 start iprintstring("CFILE conn fails ".itos(flag).snl) ilogoff(console) return finish remotes == array(re_conad+pointers_remote displ,rarf) if user -> ("REMOTE ").user start cycle exit unless user -> (" ").user repeat if user = "MANAGER" then user = "LOCAL" cycle i = 1,1,rmts if remotes(i)_name = user then connection_source = i and exit repeat if connection_source = 0 then iprintstring(user." not known".snl) and c ilogoff(console) and return connection_type = activity permitted unless pass -> ("X25").pass or pass -> ("TS").pass then iprintstring("Invalid pass".snl) c and ilogoff(console) and return call = "OPER(".user.")CHECKPASS:".itos(connection_source)."/". c itos(entry)."/".pass flag = dexecmess("SPOOLR",1,length(call),addr(call)+1) if flag # 0 then iprintstring("SPOOLER unavailable".snl) and ilogoff(console) and return if user = "LOCAL" then user = "MANAGER" and connection_source = 0 connection_name = user connection_disabled = locked finish else iprintstring("User name: 'REMOTE <name>'".snl) and c ilogoff(console) and return IPROMPT("<> ") end {m initialise} !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ! external routine m input(string (255) call, integer console) string (255) aaa, bbb, tim integer i, n, secs, nbytes, j, unass, entry, found, flag !* ! R E C O R D A R R A Y F O R M A T S ! - - - - - - - - - - - - - - - - - - record (lcf)arrayformat list cells af(1 : list size) record (details f)arrayformat qnaf(1 : qs) record (queuef)arrayformat qarf(1 : qs) record (details f)arrayformat rnaf(1 : rmts) record (remotef)arrayformat rarf(1 : rmts) record (details f)arrayformat snaf(1 : strms) record (streamf)arrayformat sarf(1 : strms) !* !* ! R E C O R D A R R A Y N A M E S ! - - - - - - - - - - - - - - - - record (lcf)arrayname list cells record (details f)arrayname queue names record (queuef)arrayname queues record (details f)arrayname remote names record (remotef)arrayname remotes record (details f)arrayname stream details record (streamf)arrayname streams !* !* ! R E C O R D S record (connectionf)name connection record (pointers f)name pointers record (rf)re stringfnspec ident to s(integer ident) stringfnspec i to ss(integer i, l) stringfnspec unpack date(integer datetime) stringfnspec unpack time(integer datetime) integerfnspec pack date and time(string (8) date, time) string (15)fnspec hms(integer secs) routinespec interpret command uctran(call) length(call)=length(call)-1 if call#"" and charno(call, length(call))=nl if call="?" or call="HELP" start iprintstring("HELP information will be available soon (ish)".snl) iterminate ! iprintstring("and user-level commands are:") ! inewline ! iprintstring(" PRINT <n>, USERS, SETLOGOUTDELAY<secs>, GETMON, CONSOLES, <n> : <text>") ! inewline ! iprintstring( %c ! "The latter is a means of sending text to another console (from list given by CONSOLES)") ! inewline ! iprintstring("And PRINT <n> is a test routine to send n characters to this terminal") ! INEWLINE finish else if call="CONSOLES" start iprintstring("Logged-on consoles: ".SNL) n=0 for i=0, 1, 127 cycle if consoles(i)#255 then n=n+1 and iprintstring("Console ".itos(consoles(i))." : ".CONNECTIONS(I)_NAME.snl) repeat finish else if call->aaa.("PRINT").bbb start n=bin(bbb) if 0<n<=x'b00' start i=0 cycle aaa=itos(i) aaa="0".aaa while length(aaa)<4 aaa=" ".aaa if ioutpos>60 then aaa=aaa.snl iprintstring(aaa) i=i+length(aaa) exit if i>n repeat finish finish else if call="GETMON" start give monitoring(tim, secs, nbytes) iprintstring(itos(nbytes)." bytes at ".tim." term after ".itos(secs)) finish else if call->aaa.("SETLOGOUTDELAY").bbb start i=bin(bbb) if 0<=i<=60*60 {1hr} then iset logout delay(i) else iprintstring("Invalid value") finish else if call="UNASS" start j=unass finish else if length(call)>2 and call->aaa.(":").bbb and length(aaa)>0 start ! Try for inter-console communication: aaa should be a console number i=bin(aaa) if 0<i<=127 start found=0 for j=0, 1, 127 cycle if consoles(j)=i then connection == connections(j) and found=1 repeat if found=0 then iprintstring("Console ".itos(i)." not connected") else start iselect output(i) iprintstring(snl."From ".itos(console)." (".CONNECTION_NAME. C ") ".": ".bbb.SNL) finish finish else iprintstring("Invalid console number") finish else start !******************** This is the REMOTE user service entry point. cycle i = 0,1,maxconsoles if consoles(i) = console then connection == connections(i) and entry = i and exit if i = max consoles start iprintstring("Console match fail..disaster".snl) return finish repeat if already connected = no start connect("SPOOLR.CFILEPTRS",r!s,0,0,re,flag) if flag # 0 and flag # 34 start iprintstring("CFILEPTRS conn fail ".itos(flag).snl) return finish pointers == record(re_conad+file header size) connect("SPOOLR.CFILE",r!s,0,0,re,flag) if flag # 0 and flag # 34 start iprintstring("CFILE conn fail ".itos(flag).snl) return finish streams == array(re_conad+pointers_stream displ,sarf) already connected = yes finish interpret command iprompt("<> ") return finish routine interpret command !*********************************************************************** !* * !* * !*********************************************************************** constinteger command limit = 67 switch swt(1 : command limit) integer i, j, k, l, strm, rmt, flag, q no, id, op no integer seg, gap, new q no, new id, fsys, command length, link integer flags, next, after, source byteintegerarray net address(0 : 63) record (streamf)name ftp line record (fhf)name file header record (streamf)name stream record (queuef)name queue record (remotef)name remote record (document descriptorf)name document record (pe)p string (15) q, name, ident, recieving queue, user string (15) original queue string (10) specific user string (63) param1, param2 string (63) reply, param, ns1 string (63) array words(1:15) string (255) command integerfnspec find remote(string (255) r) integerfnspec find queue(string (255) q) integerfnspec find stream(string (255) strm) routinespec display queues(integer page,full) routinespec display remotes(integer page,full) routinespec display streams(integer page,full) routinespec display queue(integer q no,page,full,string (10) specific user) routinespec display document(integer line,ident) routinespec display stream(integer strm) routinespec display remote(integer r) routinespec update oper(integer display type,which display,which page,string (10) specific user) conststring (15) array comm(1 : command limit) = c "FE", "LAST", "NEXT", "LOGON", "LOGOFF", "WINDUP", "OPEN", "CLOSE", "TIE", "SWITCH", "POLL", "BROADCAST", "EOF", "START", "STOP", "ATTACH", "DETACH", "ABORT", "BATCHSTREAMS", "RUN", "SELECT", "TIDY", "PRINT", "MON", "PROMPT", "CONFIG", "CHOP", "FEPUP", "FEPDOWN", "STREAM", "S", "STREAMS", "SS", "QUEUE", "Q", "QUEUES", "QS", "DISPLAY", "BATCH", "REMOTES", "RS", "REMOTE", "R", "PRIORITY", "LIMIT", "FORMS", "RUSH", "HOLD", "RELEASE", "DELETE", "MOVE", "COPY", "OFFER", "WITHDRAW", "MSG", "ENABLE", "DISABLE", "CONNECTFE", "A:", "", "","","","","","AUTODAP", "BAR" !The following array of words are param checking flags used as follows: ! x00nnnnnn no checking to be done ! x01nnnnnn do checks ! xnn00nnnn Main oper command only ! xnn01nnnn Main oper and RJE command ! xnn10nnnn RJE command only ! xnn11nnnn Informative command, not checked for RJE access permissions. ! xnnnnllnn minimum number of params ! xnnnnnnll maximum number of params (FF implies any number) constintegerarray comm flags(1 : command limit) = c x'01000000', x'01000000', x'01000000', x'01000103', x'01010001', x'01010001', x'01000101', x'01000101', x'01000101', x'01000303', x'01000000', x'01000101', x'01000101', x'01000101', x'01000001', x'01000303', x'01000303', x'01010101', x'01000102', x'01000202', x'01000101', x'01000101', x'01000001', x'01000101', x'01000101', x'01000002', x'01000101', x'01000101', x'01000101', x'01110101', x'01110101', x'01110001', x'01110001', x'01110103', x'01110103', x'01110001', x'01110001', x'01110101', x'01110000', x'01110001', x'01110001', x'01110101', x'01110101', x'01010202', x'01010202', x'01010202', x'01010101', x'01010101', x'01010101', x'01010102', x'01010304', x'01010303', x'01010101', x'01010101', x'010101FF', x'01100101', x'01100000', x'01000101', x'011100FF', x'01000102', x'01000001', x'01000001', x'01110002', x'01000102', x'01000102', x'01000102', x'01010102' integerfn find document( c string (15) srce, q, name, id, string (6) user, integername q no, ident) !*********************************************************************** !* * !* ATTEMPTS TO FIND THE SPECIFIED DOCUMENT. ANY OR MANY OF THE PARAMS * !* MAY NOT BE SPECIFIED. * !* * !*********************************************************************** integer next cycle q no = 1, 1, qs if q = "" or q = queue names(q no)_name start !THIS Q? next = queues(q no)_head; !FIND FIRST DOCUMENT IN Q while next # 0 cycle ; !SCAN DOWN QUEUE ident = list cells(next)_document !PICK UP DOCUMENT IDENTIFIER result = 0 if id = "" or id = c ident to s(ident) !THIS IDENT? next = list cells(next)_link repeat finish repeat result = 1 end ; !OF INTEGERFN FIND DOCUMENT integerfn check params (string (255) c param, stringname q, name, user, ident) !*********************************************************************** !* * !* * !*********************************************************************** integer i, id, afsys q = ""; name = ""; user = ""; ident = "" if param -> q.(" ").param start ; !Q THE if 1 <= length(q) <= 15 start ; !RIGHT LT if param -> user.(" ").name start result = 0 if length(user) = 6 c and 1 <= length(name) <= 15 finish finish else result = 1 finish if length(param) = 6 start afsys = 0 cycle i = 1, 1, 2 result = 1 unless '0' <= charno(param, i) <= '9' afsys = afsys*10+charno(param, i)-'0' repeat result = 1 unless 0 <= afsys <= max fsys id = 0 cycle i = 3, 1, 6 result = 1 unless '0' <= charno(param, i) <= '9' id = id*10+charno(param, i)-'0' repeat result = 1 unless 1 <= id <= max documents ident = param result = 0 finish result = 1 end ; !OF ROUTINE CHECK PARAM integerfn get document(string (31) param) !*********************************************************************** !* * !* * !*********************************************************************** record (fhf)name file header result = 1 if check params(param, q, name, user, ident) # 0 result = 2 if find document(connection_name, q, name, ident, user,q no, id) # 0 i = (id&x'ff000000')>>24 connect("SPOOLR.SPOOLLIST".itos(i),r!s,0,x'00000080'!(i<<8),re,flag) if flag # 0 and flag # 34 start iprintstring("SPOOLLIST".itos(i)." conn fails ".itos(flag).snl) result = 3 finish file header == record(re_conad) i = re_conad+file header_start+(id&x'ffffff'-1)* c document entry size document == record(i) result = 0 end ; !OF INTEGERFN GET DOCUMENT integerfn map document(integer param) !*********************************************************************** !* * !* * !*********************************************************************** record (fhf)name file header i = (param&x'ff000000')>>24 connect("SPOOLR.SPOOLLIST".itos(i),r!s,0,x'00000080'!(i<<8),re,flag) if flag # 0 and flag # 34 start iprintstring("SPOOLLIST".itos(i)." conn fails ".itos(flag).snl) result = 3 finish file header == record(re_conad) i = re_conad+file header_start+(param&x'ffffff'-1)* c document entry size document == record(i) result = 0 end ; !OF INTEGERFN map DOCUMENT !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !GENERAL ROUTINES FOR THE COMMAND SET INTERPRETATION. integerfn permission(integer type) !THIS CHECKS PERMISSION OF THE FOLLOWING TYPES: ! 1: PERMISSION ON AN INDIVIDUAL DOCUMENT ! 2: PERMISSION ON A STREAM ! 3: PERMISSION ON A QUEUE integer i, j ! {do the info/activity/managr checks here} result = 0 if connection_name = "MANAGER" if type = 1 start !DOCUMENT CHECK if doc string(document,document_srce) # "" start !IT WAS GENERATED BY A REMOTE. cycle i = remotes(source)_lowest stream, 1, remotes(source)_highest stream if stream details(i)_name = doc string(document,document_srce) then result = 0 repeat finish !OK, SO CHECK WETHER DOCUMENT IS IN A QUEUE SERVED(OWNED) BY !THE CALLING REMOTE. cycle i = remotes(source)_lowest stream, 1, remotes(source)_highest stream stream == streams(i) cycle j = 0, 1, last q per stream exit if stream_queues(j) = 0 if queues(stream_queues(j))_name = document_dest then c result = 0 repeat repeat !WELL WE TRIED DIDN'T WE !! result = 1 finish if type = 2 start !STREAM PERMISSION CHECK result = 0 if remotes(source)_lowest stream <= strm <= c remotes(source)_highest stream result = 1 finish if type = 3 start !A QUEUE PERMISSION CHECK. cycle i = remotes(source)_lowest stream, 1, remotes(source)_highest stream stream == streams(i) cycle j = 0, 1, last q per stream exit if stream_queues(j) = 0 result = 0 if q no = stream_queues(j) repeat repeat result = 1 finish ! end integerfn resolve command integer elements; string (127) word ! elements = 0 command = call cycle command -> (" ").command while length(command)>0 and charno(command,1)=' ' exit if command = "" elements = elements + 1 exit if elements = 16 if command -> word.(" ").command then start if length(word)>63 then length(word)=63 words(elements) = word continue finish length(command) = 63 if length(command) > 63 words(elements) = command exit repeat result = elements ! end !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !DO THE INITIAL CHECKS AGAINST THE ATRIBUTES WORD source = connection_source reply = "" command length = resolve command return if command length = 0 link = 0 cycle i = 1, 1, command limit if words(1) = comm(i) then link = i and exit repeat if link = 0 start if call = "QUIT" start connection_source = 0 connection_name = "" return finish reply = "INVALID COMMAND ".words(1) -> error finish flags = comm flags(link) -> skip if flags >> 24 = 0 !IE DO NOT DO INITIAL CHECKS. unless (flags<<16)>>24 <= (command length - 1) <= flags&x'FF' start reply = "NUMBER OF PARAMS ?" -> error finish skip: !now connect the spoolr files we will require. connect("SPOOLR.CFILEPTRS",r!s,0,0,re,flag) if flag #0 and flag # 34 then reply = "CFILEPTRS conn fail ".itos(flag) and -> error pointers == record(re_conad+file header size) connect("SPOOLR.CFILE",r!s,0,0,re,flag) if flag # 0 and flag # 34 then reply = "CFILE conn fail ".itos(flag) and -> error queue names == array(re_conad+pointers_queue name displ, qnaf) queues == array(re_conad+pointers_queue displ, qarf) stream details == array(re_conad+pointers_stream name displ,snaf) streams == array(re_conad+pointers_stream displ, sarf) remote names == array(re_conad+pointers_remote name displ, rnaf) remotes == array(re_conad+pointers_remote displ, rarf) qs = pointers_queues strms = pointers_streams rmts = pointers_remotes disconnect("SPOOLR.CFILEPTRS",flag) connect("SPOOLR.SPOOLLINK",r!s,0,0,re,flag) if flag # 0 and flag # 34 then reply = "SPOOLLINK conn fail ".itos(flag) and -> error list cells == array(re_conad,list cells af) if connection_disabled = yes and link # 56 c then iprintstring("Your terminal is locked out.".snl) and return -> swt(link) ! ! swt(7): swt(8): swt(11): swt(21): swt(23): swt(24): swt(27): swt(28): swt(29): swt(58): swt(61): swt(62): swt(64): swt(65): swt(66): -> call spooler swt(*): iprintstring("No".snl) return !*************************************************** !DISPLAY A SPECIFIED (DEFAULT 0) PAGE OF THE QUEUES. swt(36): swt(37): if command length = 2 start j = stoi(words(2)) param = "PAGE NO." and -> parameter if j < 0 or j > 255 finish else j = 0 if link = 36 then i = all queues else i = non empty queues connection_display type = i connection_which display = 0 connection_which page = j connection_specific user="" -> up oper !***************************** !DISPLAY A SPECIFIED DOCUMENT. swt(38): param = "DOCUMENT" if length(words(2)) = 6 start cycle i = 1, 1, 6 -> parameter unless '0' <= charno(words(2), i) <= '9' repeat i = (charno(words(2), 1)-'0')*10+charno(words(2), 2)-'0' j = (charno(words(2), 3)-'0')*1000+(charno(words(2), 4)-'0')*100 c +(charno(words(2), 5)-'0')*10+charno(words(2), 6)-'0' -> parameter unless 1 <= j <= max documents connection_display type = individual document connection_which page = 0 connection_which display = i<<24!j connection_specific user="" -> up oper finish else -> parameter !********************************************************** !RUSH: PUT A JOB AT MAX PRIORITY WITHIN ITS OWN PRIORITY swt(47): param = "DOCUMENT" flag = get document(words(2)) reply = "DOCUMENT access fails ".i to s(flag) and -> error if flag # 0 -> violation if permission(1) # 0 -> call spooler !************************************* !RELEASE A HELD DOCUMENT swt(49): param = "DOCUMENT" flag = get document(words(2)) reply = "DOCUMENT access fails ".i to s(flag) and -> error if flag # 0 -> violation if permission(1) # 0 -> call spooler !**************** !HOLD A DOCUMENT. swt(48): param = "DOCUMENT" flag = get document(words(2)) reply = "DOCUMENT access fails ".itos(flag) and -> error if flag # 0 -> violation if permission(1) # 0 ->call spooler !************************************************* !DELETE A DOCUMENT OR THE DOCUMENTS INDICATED BY !SUBSEQUENT PARAMETERS. swt(50): specific user = ""; q no = 0 if words(2) -> words(2).(".ALL") start if command length = 3 then start !IE DELETE ALL A USER'S DOCS IN A PARTICULAR QUEUE. q no = find queue(words(3)) param = "QUEUE" and -> parameter if q no = 0 specific user = words(2) param = "USER" and -> parameter if length(specific user) # 6 finish else start q no = find queue(words(2)) param = "QUEUE" and -> parameter if q no = 0 finish finish else start !DELETE A SINGLE DOCUMENT. flag = get document(words(2)) reply = "DOCUMENT access fails ".itos(flag) and -> error if flag # 0 -> violation if permission(1) # 0 -> call spooler finish !COMPLETE THE MULTIPLE DELETE. -> violation if permission(3) # 0 !IE NO ACCESS TO THAT QUEUE. -> call spooler !************************************************* !MOVE A DOCUMENT OR THE DOCUMENTS INDICATED BY !SUBSEQUENT PARAMETERS. swt(51): specific user = ""; q no = 0; recieving queue = "" original queue = ""; new q no = 0 if command length = 5 start !A USER'S DOCS IN A QUEUE TO BE MOVED. param = "WORDING" and -> parameter unless words(4) = "TO" c and words(2) -> specific user.(".ALL") param = "USER" and -> parameter unless length(specific user) = 6 q no = find queue(words(5)) param = "RECIEVING QUEUE" and -> parameter if q no = 0 -> violation unless permission(3) = 0 or queues(q no)_general access = open recieving queue = words(5) new q no = q no q no = find queue(words(3)) original queue = words(3) param = "ORIGINAL QUEUE" and -> parameter if q no = 0 -> violation if permission(3) # 0 finish else start !USER NOT SPECIFIED, MUST BE EITHER SINGLE DOC OR A WHOLE QUEUE. q no = find queue(words(4)) param = "RECIEVING QUEUE" and -> parameter if q no = 0 -> violation unless permission(3) = 0 or queues(q no)_general access = open recieving queue = words(4) new q no = q no unless words(2) -> words(2).(".ALL") start !IT IS A SINGLE DOC MOVE. flag = get document(words(2)) param = "DOCUMENT access fails ".itos(flag) and -> parameter if flag # 0 original queue = document_dest -> violation if permission(1) # 0 -> call spooler finish !FULL QUEUE MOVE. q no = find queue(words(2)) original queue = words(2) param = "ORIGINAL QUEUE " and -> parameter if q no = 0 -> violation if permission(3) # 0 finish !DO THE MOVES. queue == queues(q no) reply = "NOT TO SAME QUEUE !" and -> error if recieving queue c = original queue -> call spooler !************************************************* !CHANGE THE PRIORITY OF A STREAMS OR OF A DOCUMENT swt(44): i = 0 cycle j = 1, 1, n priorities if words(3) = priorities(j) start i = j exit finish repeat param = "PRIORITY" and -> parameter if i = 0 strm = find stream(words(2)) if strm = 0 then start !MUST THEREFORE BE A DOCUMENT if get document(words(2)) # 0 then param = "STREAM/DOCUMENT" and c -> parameter -> violation if permission(1) # 0 -> call spooler finish !A STREAM PRIORITY CHANGE. -> violation unless permission(2) = 0 -> call spooler !*************************************************** !COPY A DOCUMENT TO ANOTHER QUEUE. swt(52): q no = find queue(words(4)) param = "QUEUE" and -> parameter if q no = 0 -> violation unless permission(3) = 0 or queues(q no)_general access = open new q no = q no flag = get document(words(2)) param = "DOCUMENT access fails ".itos(flag) and -> parameter if flag # 0 -> violation unless permission(1) = 0 -> call spooler !****************************************************** !WINDUP ACTIVITY ON STREAMS FOR SPECIFIED REMOTE. (ALL) swt(6): if command length > 1 and words(2) = ".ALL" start -> violation if source # 0 -> call spooler finish else start if command length = 1 then words(2) = connection_name rmt = find remote(words(2)) param = "REMOTE" and -> parameter if rmt = 0 -> call spooler finish return !****************************************************** !ABORT ONE OR ALL STREAMS. swt(18): if words(2) = ".ALL" start -> violation unless source = 0 -> call spooler finish else start strm = find stream(words(2)) param = "STREAM" and -> parameter if strm = 0 -> violation unless permission(2) = 0 reply = "NOT REQUIRED" and -> error if streams(strm)_status < allocated -> call spooler finish return !********************************************************* !START A STREAM (IE REMOVE STOP AND KICK) , OR ALL STREAMS. swt(14): if words(2) = ".ALL" start ; !START ALL STREAMS -> call spooler finish else start strm = find stream(words(2)) param = "STREAM" and -> parameter if strm = 0 -> call spooler finish return !********************************************************* !DISPLAY PAGE OF ALL STREAMS OR ACTIVE STREAMS swt(32): swt(33): if command length > 1 start j = s to i(words(2)) param = "PAGE" and -> parameter if j < 0 or j > 255 finish else j = 0 if i = 32 then i = all streams else i = active streams connection_display type = i connection_which display = 0 connection_which page = j connection_specific user="" -> up oper !******************************************************** !DISPLAY DETAILED PAGE OF QUEUE OR SIMPLE PAGE OF QUEUE swt(34): swt(35): j=0; connection_specific user="" if command length = 2 start q no = find queue(words(2)) param = "QUEUE" and -> parameter if q no = 0 finish else start if words(2) -> words(2).(".ALL") start param = "USER" and -> parameter unless length(words(2)) = 6 c or (words(2) -> reply.("DAP") and (length(reply) = 0 or length(reply) = 7)) connection_specific user = words(2) q no = find queue(words(3)) param = "QUEUE" and -> parameter if q no = 0 if command length = 4 start j = s to i(words(4)) param = "PAGE" and -> parameter unless 0 <= j <= 255 finish finish else start q no = find queue(words(2)) j = s to i(words(3)) if q no = 0 start if 0<=j<=255 start param = "QUEUE" -> parameter finish else start reply = "<USER>.ALL ?" -> error finish finish param = "PAGE" and ->parameter unless 0 <= j <= 255 finish finish if link = 34 then i = full individual queue c else i = individual queue connection_display type = i connection_which display = q no connection_which page = j connection_specific user = "" -> up oper !*********************************************** !REPORT ON STREAM STATUS FULLY OR PARTIALLY swt(30): swt(31): strm = find stream(words(2)) param = "STREAM" and -> parameter if strm = 0 connection_display type = individual stream connection_which display = strm connection_which page = 0 connection_specific user="" -> up oper !***************************************************** !SET A STREAM ATTRIBUTE. FORMS OR LIMIT swt(46): swt(45): strm = find stream(words(2)) param = "STREAM" and -> parameter if strm = 0 -> violation unless permission(2) = 0 i = s to i(words(3)) if link = 45 then j = 10000 else j = 255 param = "VALUE" and -> parameter unless 0<=i<=j -> call spooler !******************************************************************** !Bar (or release) a stream from outputing(and only output streams) !for a particular user. swt(67): strm = find stream(words(2)) param = "STREAM" and -> parameter if strm = 0 -> violation unless permission(2) = 0 -> call spooler !************************************************** !ATTACH A STREAM TO A PARTICULAR QUEUE swt(16): reply = "<STRM> TO <Q> ?" and ->error unless words(3) = "TO" strm = find stream(words(2)) param = "STREAM" and ->parameter if strm = 0 q no = find queue(words(4)) param = "QUEUE" and -> parameter if q no = 0 stream == streams(strm) queue == queues(q no) if stream_service # input start ; !NOT INPUT STREAMS cycle i = 0, 1, last q per stream unless stream_queues(i) = q no start if stream_queues(i) = 0 start cycle j = 0, 1, last stream per q unless queue_streams(j) = strm start if queue_streams(j) = 0 start -> call spooler finish finish else start reply = words(2)." ALREADY ATTACHED" -> error finish repeat reply = words(4)."HAS TOO MANY STREAMS" -> error finish finish else start reply = words(2)." ALREADY ATTACHED" -> error finish repeat reply = words(2)." ATTACHED TO TOO MANY QUEUES" -> error finish else start ; !INPUT STREAMS if stream_queues(0) # 0 start reply = words(2)." ALREADY ATTACHED TO ".queue names(stream_ c queues(0))_name -> error finish -> call spooler finish !************************************************ !DETACH A STREAM FROM A QUEUE. swt(17): reply = "<STRM> FROM <Q> ?" and -> error unless words(3) = "FROM" strm = find stream(words(2)) param = "STREAM" and -> parameter if strm = 0 q no = find queue(words(4)) param = "QUEUE" and -> parameter if q no = 0 stream == streams(strm) queue == queues(q no) if q no=stream_queues(stream_q no) and c stream_document#0 then start !THE STREAM IS CURRENTLY SERVING THE QUEUE IN QUESTION. reply="DETACH FAILS, ".words(2)." SERVING ".words(4) ->error finish if stream_service # input start ; !NOT INPUT STREAMS cycle i = 0, 1, last q per stream exit if stream_queues(i) = 0 if stream_queues(i) = q no start cycle j = 0, 1, last stream per q exit if queue_streams(j) = 0 if queue_streams(j) = strm then -> call spooler repeat reply = words(2)." ATTACHED TO ".words(4)." WRONGLY" -> error finish repeat reply = words(2)." NOT ATTACHED TO ".words(4) -> error finish else start if stream_queues(0) # q no start reply = words(2)." NOT ATTACHED TO ".words(4) -> error finish else -> call spooler return finish !******************************************************** !DISPLAY A PAGE OF INFORMATION ABOUT REMOTES. swt(40): swt(41): if command length = 2 start j = stoi(words(2)) param = "PAGE" and -> parameter if j < 0 or j > 255 finish else j = 0 if link = 40 then i = all remotes else i = logged on remotes connection_display type = i connection_which display = 0 connection_which page = j connection_specific user="" -> up oper !********************************************* !DISPLAY REMOTE STATUS INFORMATION. swt(42): swt(43): rmt = find remote(words(2)) param = "REMOTE" and -> parameter if rmt = 0 connection_display type = individual remote connection_which display = rmt connection_which page = 0 connection_specific user="" -> up oper !****************************************** !LOGOFF REMOTE(S) AS SPECIFIED swt(5): words(2) = connection_name and call = call." ".connection_name if command length = 1 if words(2) = ".ALL" or find remote(words(2)) # 0 c then -> call spooler else param = "REMOTE" and c -> parameter return !******************************************* !DISPLAY LAST PAGE OF CURRENT DISPLAY swt(2): reply = "FIRST PAGE!" and -> error if connection_which page = 0 connection_which page = connection_which page - 1 -> up oper !************************************************ !DISPLAY THE NEXT PAGE OF THE CURRENT DISPLAY. swt(3): reply = "LAST PAGE!" and -> error if connection_which page = 255 connection_which page = connection_which page+1 -> up oper !************************************************************ !SET THE NUMBER OF BATCH STREAMS (AND LIMIT IF REQUIRED) swt(19): i = s to i(words(2)) reply = "0-16 STREAMS ONLY !" and -> error unless 0 <= i <= 16 -> call spooler !*********************************************** !FORCE A SPECIFIC BATCH JOB TO START. swt(20): strm = find stream(words(2)) param = "STREAM" and -> parameter if strm = 0 printstring("Stream already ACTIVE!".snl) and return c if streams(strm)_status > allocated flag = get document(words(3)) param = "DOCUMENT access fails ".itos(flag) and -> parameter if flag # 0 reply = "Not a batch job" and -> error if streams(strm)_service # job if document_dap c exec time # 0 then c reply = "Use SELECT on DAP jobs" and -> error -> call spooler !************************************************* !OFFER OR WITHDRAW A GENERAL QUEUE PARAMETER swt(53): swt(54): q no = find queue(words(2)) param = "QUEUE" and -> parameter if q no = 0 -> violation unless permission(3) = 0 -> call spooler !********************************************** !ENABLE OR DISABLE A REMOTE'S COMMAND INPUT swt(56): swt(57): if connection_name = "MANAGER" then name = "LOCAL" else c name = connection_name rmt = find remote(name) if link = 56 start !ENABLE(REQUIRES A PASSWORD) unless words(2) -> ("X25").words(2) or words(2) -> ("TS").words(2) then param = "PASS" and -> parameter call = "OPER(".connection_name.")CHECKPASS:".itos(connection_source)."/". c itos(entry)."/".words(2) flag = dexecmess("SPOOLR",1,length(call),addr(call)+1) if flag # 0 then iprintstring("SPOOLER unavailable".snl) and ilogoff(console) return finish if link = 57 then connection_disabled = yes return !****************************************************** !LOGON THE SPECIFIED REMOTE THRU THE SPECIFIED FEP AT !THE SPECIFIED ADDRESS swt(4): if connection_name = "MANAGER" then reply = "NO" and -> error if words(2) -> param1.(".").param2 start if length(param1) = 8 then words(2) = "0000".words(2) finish else if length(words(2)) = 8 then words(2) = "0000".words(2) reply = "ALREADY LOGGED ON" and -> error if remotes(connection_source)_status > open !in the next section the FEP no 0 could,from config stage, be !either because it was set to 0 really or NA. Therefore we !ignore FE0 as a logon primitive and use FE? (ie choose) !when we call spoolr. If 0 was wanted and is X25 it will be !chosen anyway by spooler. !NOTE that if the FE is specified by the ops. then this is used. call = "LOGON ".connection_name." FE" if command length >= 3 start unless words(3) -> ("FE").words(3) then reply = "LOGON <addr> FEn ?" and -> error i = stoi(words(3)) unless 0 <= i <= max fep then reply = "Invalid FEP no." and -> error call = call.words(3)." ".words(2) if command length = 4 then call = call." TIED" finish else start if remotes(connection_source)_prelog fep # 0 then call = c call.itos(remotes(connection_source)_prelog fep)." ".words(2) c else call = call."? ".words(2) finish printstring(call.snl) -> call spooler !**************************************** !TIE DOWN A REMOTE TO ITS CURRENT FEP swt(9): rmt = find remote(words(2)) param = "REMOTE" and -> parameter if rmt = 0 or c remotes(rmt)_name = "LOCAL" if remotes(rmt)_status = logged on or remotes(rmt)_status c = switching then start !OK TO TIE DOWN -> call spooler finish else printstring(remotes(rmt)_name." NOT LOGGED ON.".snl) return !************************************************* !SWITCH A REMOTE FROM ONE FEP TO ANOTHER. swt(10): if words(3) = "TO" start reply = "<RMT> TO FEn" and -> error unless c words(4)-> ns1.("FE").words(4) and ns1="" and length(words(4)) = 1 rmt=find remote(words(2)) param = "REMOTE" and -> parameter if rmt = 0 i = charno(words(4), 1) - '0' param = "FEP" and -> parameter unless 0<= i <= max fep if no route < remotes(rmt)_fep route value(i) < requested c and remotes(rmt)_status = logged on and remotes(rmt)_ c prelog < prelogon tied start !OK TO GO AHEAD WITH THE SWITCH. -> call spooler finish else printstring("SWITCH NOT POSSIBLE!!".snl) return finish if words(3) = "FROM" and words(2)= ".ALL" and c length(words(4))=3 and substring(words(4),1,2)="FE" start words(4)->("FE").words(4) i = charno(words(4), 1) - '0' param = "FEP" and -> parameter unless 0 <= i <= max fep -> call spooler finish printstring("<RMT> TO FEn".snl.".ALL FROM FEn".snl) return up oper: update oper(connection_display type,connection_which display, c connection_which page, connection_specific user) return violation: param = "ACCESS" parameter: reply = "INVALID ".param error: iprintstring(reply.snl) return call spooler: call = "OPER(".connection_name.")".call flag = dexecmess("SPOOLR",1,length(call),addr(call)+1) if flag # 0 then iprintstring("SPOOLR call fails ".itos(flag).snl) c else iprintstring("SPOOLR called".snl) return !* !* integerfn find queue(string (255) q) !*********************************************************************** !* * !* RETURNS THE INDEX INTO THE QUEUE ARRAY OF THE SPECIFIED QUEUE * !* RETURNS ZERO IF THE QUEUE IS NOT FOUND * !* * !*********************************************************************** integer i cycle i = 1, 1, qs result = i if queue names(i)_name = q repeat reply = "NO SUCH QUEUE ".q result = 0 end ; !OF INTEGERFN FIND QUEUE !* !* integerfn find remote(string (255) r) !*********************************************************************** !* * !* RETURNS THE INDEX INTO THE REMOTE ARRAY OF THE SPECIFIED REMOTE * !* RETURNS ZERO IF THE REMOTE IS NOT FOUND * !* * !*********************************************************************** integer i cycle i = 1, 1, rmts result = i if remote names(i)_name = r repeat reply = "NO SUCH REMOTE ".r result = 0 end ; !OF INTEGERFN FIND REMOTE !* !* integerfn find stream(string (255) strm) !*********************************************************************** !* * !* RETURNS THE INDEX INTO THE STREAM ARRAY OF THE SPECIFIED STREAM * !* RETURNS ZERO IF THE STREAM IN NOT FOUND * !* * !*********************************************************************** string (255) rmt integer i rmt = "" unless strm -> rmt.(".").strm cycle i = 1, 1, strms result = i if stream details(i)_name = strm and (rmt = "" c or rmt = remote names(streams(i)_remote)_name) repeat strm = rmt.".".strm if rmt # "" reply = "NO SUCH STREAM ".strm result = 0 end ; !OF INTEGERFN FIND STREAM !* !* !* !* routine display queues(integer page, full) !*********************************************************************** !* * !* DISPLAY A SUMMARY OF ALL THE QUEUES STARTING AT THE GIVEN PAGE * !* * !*********************************************************************** record (queuef)name queue integer q no, line, count, limit string (255) s, t s = "Page ".i to s(page) s = s." " while length(s) < 12 if full = yes then s = s."All Queues" else s = s."Queues" iprintstring( s.snl); !TITLE line = 1 count = 0 limit = (oper display size-line)*page cycle q no = 1, 1, qs queue == queues(q no) if full = yes or queue_length # 0 start if count = limit start s = queue_name s = s." " while length(s) < 16 if queue_length # 0 start t = i to ss(queue_length, 4) if queue_length # queue_max length start if queue_length = 1 then t = t." Entry " c else t = t." Entries" finish else t = t." Full " s = s.t if queue_default time <= 0 c then t = i to s((queue_amount+1023)>>10). c "K" else t = hms(queue_amount) t = " ".t while length(t) < 12 s = s.t finish else s = s." Empty" iprintstring( s.snl) line = line+1 exit if line = oper display size finish else count = count+1 finish repeat end ; !OF ROUTINE DISPLAY QUEUES !* !* routine display remotes(integer page, full) !*********************************************************************** !* * !* DISPLAY A SUMMARY OF ALL THE REMOTES STARTING AT THE GIVEN PAGE * !* * !*********************************************************************** record (remotef)name remote integer r, line, count, limit string (255) s s = "Page ".i to s(page) s = s." " while length(s) < 12 if full = yes then s = s."All Remotes" else s = s."Remotes" iprintstring( s.snl); !TITLE line = 1 if full = yes then count = 2 else count = 1 limit = ((oper display size-line)//count)*page count = 0 cycle r = 1, 1, rmts remote == remotes(r) if full = yes or logging on <= remote_status <= logging off start if count = limit start s = remote_name s = s." " while length(s) < 16 s = s.remote status type(remote_status) s = s." FE".i to s(remote_fep) c if remote_network address len > 0 iprintstring( s.snl) line = line+1 if full = yes then iprintstring( " ".remote_description.snl) c and line = line + 1 exit if line > oper display size-1 finish else count = count+1 finish repeat end ; !OF ROUTINE DISPLAY REMOTES !* !* routine display streams(integer page, full) !*********************************************************************** !* * !* DISPLAY A SUMMARY OF ALL THE STREAMS STARTING AT THE GIVEN PAGE * !* * !*********************************************************************** record (streamf)name stream integer strm, line, count, limit string (255) s s = "Page ".i to s(page) s = s." " while length(s) < 12 if full = yes then s = s."All Streams" else s = s."Streams" iprintstring( s.snl); !TITLE line = 1 count = 0 limit = (oper display size-line)*page cycle strm = 1, 1, strms stream == streams(strm) if (connection_name = "MANAGER" or connection_name = remotes(stream_remote) c _name) and (full = yes c or stream_status > allocated) start if count = limit start s = stream_name s = s." " while length(s) < 16 s = s.stream status type(stream_status) if stream_document # 0 start flag = map document(stream_document) if flag # 0 then iprintstring("DOCUMENT access fails ". c itos(flag).snl) and return s = s." For ".document_user s = s." ".ident to s(stream_document) c if stream_status = active finish iprintstring( s.snl) line = line+1 exit if line = oper display size finish else count = count+1 finish repeat end ; !OF ROUTINE DISPLAY STREAMS !* !* routine display queue(integer q no, page, full, string (10) specific user) !*********************************************************************** !* * !* MAKE UP TO DATE THE DISPLAY WHICH HOLDS THE SPECIFIED QUEUE. * !* * !*********************************************************************** record (queuef)name queue integer line, next, i, j, limit, user limit,dap special string (3) p string (255) s, t dap special = no if specific user # "" start if specific user -> specific user.(".DAP") or specific user -> c specific user.("DAP") then dap special = yes finish s = "Page ".i to s(page) s = s." " while length(s) < 10 queue == queues(q no); !MAP THE APPROPRIATE QUEUE s = s."Queue ".queue_name s = s." Full" if queue_length = queue_max length s = s." Empty" if queue_length = 0 iprintstring( s.snl); !TITLE if queue_length = 0 then t = " No" c else t = i to ss(queue_length, 3) s = t." Entries" t = i to ss(queue_max length, 4) s = s.t." Max" t = i to ss(queue_maxacr, 3) s = s.t." MaxACR" if queue_length > 0 and dap special = no start if queue_default time > 0 c then t = hms(queue_amount) c else t = i to s((queue_amount+1023)>>10)."K" t = " ".t while length(t) < 11 s = s.t finish if dap special = yes then s = s." DAP" iprintstring( s.snl) if full = yes start line = 2 iprintstring( "Defaults:".snl) line = line + 1 iprintstring("USER: ".queue_default user.snl) if queue_default user # "" line = line + 1 iprintstring("DELIVERY: ".queue_default delivery) c if queue_default delivery # "" line = line+1 s = "PRIORITY: ".priorities(queue_default priority) s = s." " while length(s) < 20 if queue_default time > 0 c then s = s."TIME: ".i to s(queue_default time). c "S" else start s = s."START: ".i to s(queue_default start) c if queue_default start # 0 finish iprintstring( s.snl) line = line+1 s = "FORMS: ".i to s(queue_default forms) s = s." " while length(s) < 20 iprintstring( s."MODE: ".modes( c queue_default mode).snl) line = line+1 s = "COPIES: ".i to s(queue_default copies) s = s." " while length(s) < 20 if queue_default rerun = no c then s = s."RERUN: No" else s = s."RERUN: Yes" iprintstring( s.snl) line = line+1 and iprintstring("LINES: ".i to s(queue_default output limit).snl) c if queue_default output limit > 0 line = line+1 iprintstring( "Streams:".snl) s = "" cycle i = 0, 1, last stream per q if queue_streams(i) = 0 start line = line+1 and iprintstring( s.snl) if s # "" exit finish if i&1 = 0 start line = line+1 and iprintstring( s.snl) if s # "" s = "" finish else start s = s." " while length(s) < 20 finish if streams(queue_streams(i))_batch enable = open then s = s."* " c else s = s." " s = s.stream details(queue_streams(i))_name." ". c stream status type(streams(queue_streams(i))_ c status) line = line+1 and iprintstring( s.snl) if i = last stream per q repeat finish else line = 1 if queue_head # 0 start s = "POS IDENT USER NAME PRTY " IF QUEUE_DEFAULT TIME <= 0 then s = s."SIZE" c else s = s."TIME" line = line + 1 i = 1 iprintstring(s.snl) next = queue_head line = line+1 limit = (oper display size-line)*page if specific user # "" then start user limit = limit limit = 0 finish else user limit = 0 while next # 0 and line < oper display size cycle if i > limit start if (dap special = no and (specific user="" or c list cells(next)_user=specific user)) or (dap special = yes and c list cells(next)_gen flags&dap batch flag # 0 and ( c specific user = "" or list cells(next)_user = specific user)) start flag = map document(list cells(next)_document) if flag # 0 then iprintstring("DOCUMENT access fails ".itos(flag).snl) and return unless full = no and ((document_start after date and time #0 c and document_start after date and time > c pack date and time(date, time)) or (document_dap c exec time # 0 c and dap special = no)) then start if user limit = 0 then start s = i to ss(i, 3); !CALCULATE QUEUE POSITION s = s." ".ident to s(list cells(next)_document) s = s." ".document_user." ".doc string(document,document_name) length(s) = 29 if length(s) > 29 s = s." " while length(s) < 30 if document_priority < 0 then s = s."HLD" c else start p = "" cycle j = n priorities, -1, 1 if document_priority >= prtys(j) start p <- priorities(j) exit finish repeat s = s.p finish if document_forms # queue_default forms c then s = s."F" else start if document_start after date and time # 0 c and document_start after date and time > c pack date and time(date, time) c then s = s."A" else start if document_order # 0 then s = s."O" c else s = s." " finish finish if document_priority<0 and document_properties&(media hold!dap hold) #0 start t="" if document_drives#0 then c t=i to s(document_drives)." EDU" if document_decks#0 then start if t="" then t=i to s(document_decks). c " MTU" else t="DSPLY" finish if document_dap c exec time#0 start if dap special = yes c then t = itos(document_dap mins)."m" else c if t = "" then t = " DAP" else t = "DSPLY" finish finish else start if document_time > 0 then t = i to s(document_ c time)."S" else t = i to s((document_ c data length+1023)>>10)."K" finish t = " ".t while length(t) < 6 s = s.t iprintstring( s.snl) line = line+1 finish else user limit = user limit -1 finish finish finish i = i+1 next = list cells(next)_link repeat finish end ; !OF ROUTINE DISPLAY QUEUE !* !* routine display document(integer line, ident) !*********************************************************************** !* * !* DISPLAY STARTING AT THE GIVEN LINE THE SPECIFIED DOCUMENT * !* * !*********************************************************************** integer i string (255) s iprintstring( "IDENT: ".ident to s( c ident).snl) flag = map document(ident) if flag # 0 then iprintstring("DOCUMENT access fails ".itos(flag).snl) and return line = line+1 iprintstring( "STATE: ".doc state( c document_state).snl) line = line + 1 s="ORIGIN: " if doc string(document,document_srce) = "" then s=s."USER" else s=s.doc string(document,document_srce) iprintstring( s.snl) line = line + 1 iprintstring( "USER: ".document_ c user.snl) line = line+1 iprintstring( "NAME: ". c doc string(document,document_name).snl) line = line+1 iprintstring( "QUEUE: ".document_ c dest.snl) line = line+1 if document_outdev > 0 start s="OUT: " if document_outdev = queue dest then s=s.doc string(document,document_output) c else s=s."FILE ".doc string(document,document_output) iprintstring( s.snl) line = line + 1 finish iprintstring( "DELIVERY: ". c doc string(document,document_delivery).snl) line = line+1 iprintstring( "RECEIVED: ".unpack date c (document_date and time received)." ".unpack time( c document_date and time received).snl) line = line+1 and iprintstring("AFTER: ".unpack date(document_ c start after date and time)." ".unpack time(document_ c start after date and time).snl) c if document_start after date and time # 0 line = line+1 and iprintstring("STARTED: ".unpack date(document_date and time started). c " ".unpack time(document_date and time started).snl) c if document_date and time started # 0 line = line+1 and iprintstring("DELETED: ".unpack date(document_date and time deleted). c " ".unpack time(document_date and time deleted).snl) c if document_date and time deleted # 0 line = line+1 if document_time <= 0 and document_dap c exec time = 0 start s = "SIZE: ".i to s(document_data length) s = s." " while length(s) < 20 s = s."START: ".i to s(document_data start) c if document_data start # 0 iprintstring( s.snl) finish else start if document_dap c exec time # 0 then iprintstring( "DAP time : ".itos(document_dap mins)." mins".snl) c else iprintstring("TIME: ".itos(document_time)."S".snl) finish line = line + 1 if document_priority < 0 then s = "PRIORITY: Held" c else start cycle i = n priorities, -1, 1 if document_priority >= prtys(i) start s = "PRIORITY: ".priorities(i) exit finish repeat finish if document_forms # 0 start s = s." " while length(s) < 20 s = s."FORMS: ".i to s(document_forms) finish iprintstring( s.snl) if document_ftp alias # 0 start !it is an FTP transfer document line = line + 1 s = "NIFTP-80(B) transfer for ".docstring(document,document_ftp alias) iprintstring(s.snl) finish line = line+1 s = "MODE: ".modes(document_mode) if document_copies > 1 start s = s." " while length(s) < 20 s = s."COPIES: ".i to s(document_copies) finish iprintstring( s.snl) line = line+1 if document_rerun = no then s = "RERUN: No" c else s = "RERUN: Yes" if document_fails # 0 start s = s." " while length(s) < 14 s = s."FAIL ".i to s(document_fails) finish if document_order # 0 start s = s." " while length(s) < 20 s = s."ORDER: ".i to s(document_order) finish iprintstring( s.snl) line = line+1 if document_decks = 0 then s = "" else start s = "DECKS: ".i to s(document_decks) s = s." " while length(s) < 20 finish s = s."DRIVES: ".i to s(document_drives) c if document_drives # 0 s = s."DAP control exec: ".itos(document_dap c exec time)."s" if c document_dap c exec time # 0 if s # "" then iprintstring( s.snl) else return line = line + 1 if document_decks > 0 then start s = "TSNS: " cycle i=1, 1, (8 - document_drives ) if i=4 or i=7 start iprintstring( s.snl) line = line + 1 s=" " finish exit if document_vol label(i)=0 s=s.doc string(document,document_vol label(i))." " repeat iprintstring( s.snl) and line=line+1 c if length(s) > 6 finish if document_drives > 0 start s="DSNS: " cycle i=1, 1, document_drives if i=4 or i=7 start iprintstring( s.snl) line = line + 1 s=" " finish s=s.doc string(document,document_vol label(9-i))." " repeat iprintstring( s.snl) and line=line+1 c if length(s) >6 finish end ; !OF ROUTINE DISPLAY DOCUMENT !* !* routine display stream(integer strm) !*********************************************************************** !* * !* MAKE UP TO DATE THE DISPLAY WHICH HOLDS THE SPECIFIED STREAM. * !* * !*********************************************************************** record (streamf)name stream string (255) s integer line, i stream == streams(strm) s = " ".stream type(stream_service)." Stream ". c stream_name iprintstring( s.snl) line = 1 iprintstring( "Queues:".snl) s = "" cycle i = 0, 1, last q per stream if stream_queues(i) = 0 start line = line+1 and iprintstring(s.snl) if s # "" exit finish if i&1 = 0 start line = line+1 and iprintstring(s.snl) if s # "" s = "" finish else start s = s." " while length(s) < 20 finish s = s.queue names(stream_queues(i))_name s = s." *" if stream_q no = i c and stream_service # input line = line+1 and iprintstring( s.snl) c if i = last q per stream repeat line = line+1 -> end if line >= 10 s = "STATUS: ".stream status type(stream_status) if stream_barred user # "" then s = s." [ ".stream_barred user." barred]" iprintstring( s.snl) line = line+1 -> end if line >= 10 s = "REMOTE: ".remotes(stream_remote)_name." ". c remote status type(remotes(stream_remote)_status) iprintstring( s.snl) if stream_device type # 0 start line = line+1 -> end if line >= 10 s = "TYPE: ".device type(stream_device type).i to s( c stream_device no) if stream_ident&x'FFFF' # 0 start s = s." " while length(s) < 20 s = s."ADAPTR: ".device type(stream_ident>>24).i to s(( c stream_ident>>16)&255)." ".i to s(stream_ident& c x'FFFF') finish iprintstring( s.snl) finish line = line+1 -> end if line >= 10 s = "LIMIT : ".i to s(stream_limit) s = s." " while length(s) < 20 s = s."FORMS: ".i to s(stream_forms) iprintstring( s.snl) line = line+1 -> end if line >= 10 if stream_service # input c then s = "PRTY: ".priorities(stream_lowest priority) c else s = "" if stream_comms stream # 0 start s = s." " while length(s) < 20 s = s."COMMST: ".i to s(stream_comms stream) finish iprintstring( s.snl) line = line+1 -> end if line >= 10 if stream_block # 0 start s = "TO GO: ".i to s(stream_bytes to go)." BYTES" c if stream_service = output s = "RCVD: ".i to s(stream_bytes to go)." BYTES" c if stream_service = input s = s." " while length(s) < 20 finish else s = "" s = s."HEADER: ".header type(stream_header type) c if stream_header type # 0 if s # "" then start iprintstring( s.snl) line = line + 1 -> end if line >= 10 finish s = "UNITSIZE: ".itos(stream_unitsize) if stream_unit name # "" then start s = s." " while length(s) < 20 s = s."UNIT NAME: ".stream_unit name finish iprintstring( s.snl) end: display document(10, stream_document) c if stream_document # 0 end ; !OF ROUTINE DISPLAY STREAM !* !* routine display remote(integer r) !*********************************************************************** !* * !* MAKE UP TO DATE THE DISPLAY WHICH HOLDS THE SPECIFIED REMOTE. * !* * !*********************************************************************** record (remotef)name remote integer i, line string (255) s remote == remotes(r) iprintstring( "Remote ".remote_ c name.snl) line = 1 iprintstring( " ".remote_description.snl) line = 3 iprintstring( "STATUS: ". c remote status type(remote_status).snl) if remote_network address len > 0 start line = line+1 if remote_status <= open then s="PRELOGON FEP: FE". c i to s(remote_prelog fep) else s="FEP: FE". c i to s(remote_fep) if remote_prelog > prelogon untied start s = s." (TIED" if remote_fep=remote_prelog fep then s = s.")" c else s = s." TO FE".itos(remote_prelog fep).")" finish iprintstring( s.snl) s = "NET ADDR: " if remote_network address len > 2 then s = s.remote_X25 address c else start cycle i = 0, 1, remote_network address len-1 s = s.i to s(remote_network add(i))." " repeat finish line = line+1 iprintstring( s.snl) finish line = line+1 iprintstring( "Streams:".snl) cycle i = remote_lowest stream, 1, remote_highest stream if i&1 = remote_lowest stream&1 then s = "" else start s = s." " while length(s) < 20 finish s = s.stream details(i)_name." ".stream status type(streams(i)_ c status) line = line+1 and iprintstring( s.snl) c if i = remote_highest stream or length(s) > 20 repeat end ; !OF ROUTINE DISPLAY STREAM !* !* routine update oper(integer display type, which display, which page, string (10) specific user) !*********************************************************************** !* * !* REFRESH THE SELECTED DISPLAY ON THE OPER SPECIFIED EITHER CALLED * !* INTERNALLY OR CALLED ON A CLOCK TICK. * !* * !*********************************************************************** record (pe)pp integer flag switch type(1 : 12) -> type(display type) type(all queues): display queues( which page, yes) -> return type(non empty queues): display queues( which page, no) -> return type(all streams): display streams( which page, yes) -> return type(active streams): display streams( which page, no) -> return type(individual queue): display queue( which display, which page, no, specific user) -> return type(full individual queue): display queue( which display, which page, yes, specific user) -> return type(individual stream): display stream( which display) -> return type(individual document): display document( 1, which display) -> return type(all remotes): display remotes( which page, yes) -> return type(logged on remotes): display remotes( which page, no) -> return type(individual remote): display remote( which display) -> return return: end ; !OF ROUTINE UPDATE OPER !* !* !* !* !* !* end {of routine interpret command} stringfn ident to s(integer ident) !*********************************************************************** !* * !* TURNS A DOCUMENT IDENTIFIER INTO A STRING OF FIXED FORMAT * !* * !*********************************************************************** string (2) fsys string (4) rest fsys = i to s(ident>>24) fsys = "0".fsys if length(fsys) = 1 rest = i to s(ident&x'FFFFFF') rest = "0".rest while length(rest) < 4 result = fsys.rest end ; !OF STRINGFN IDENT TO S stringfn i to s s(integer i, l) !*********************************************************************** !* * !* TURNS AN INTEGER INTO A STRING OF THE SPECIFIED LENGTH PADDING * !* WITH LEADING SPACES IF NECESSARY. * !* * !*********************************************************************** string (255) s s = i to s(i) s = " ".s while length(s) < l result = s end ; !OF STRINGFN I TO SS !*********************************************************************** !* * !* 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 unpack date(integer p) result = s2(p>>17&x'1F')."/".s2(p>>22&x'F')."/".s2((p>>26& c x'3F')+70) end ; !OF UNPACK DATE stringfn unpack time(integer p) result = s2(p>>12&x'1F').".".s2(p>>6&x'3F').".".s2(p&x'3F') end ; !OF UNPACK TIME integerfn i2(integer ad) !AD POINTS TO THE FIRST OF A PAIR OF DECIMAL CHARACTERS. THE RESULT !IS THE NUMERIC VALUE OF THE CHAS result = 10*(byteinteger(ad)&x'F')+(byteinteger(ad+1)&x'F') end ; !OF I2 integerfn pack date(string (8) date) integer ad ad = addr(date) result = ((i2(ad+7)-70)<<26)!(i2(ad+4)<<22)!(i2(ad+1)<<17) end ; !OF PACK DATE integerfn pack date and time(string (8) date, time) integer at at = addr(time) result = pack date(date)!(i2(at+1)<<12)!(i2(at+4)<<6)!(i2( c at+7)) end ; !OF PACK DATE AND TIME string (15) fn hms(integer secs) !*********************************************************************** !* * !* RETURNS THE GIVEN NUMBER OF SECONDS IN THE FORMAT HH.MM.SS * !* * !*********************************************************************** integer hrs, mins, scs, i string (15) s hrs = secs//3600 i = secs-hrs*3600 mins = i//60 scs = i-mins*60 if hrs > 0 then s = i to s(hrs)."h " else s = "" s = s.i to s(mins)."m " if s # "" or mins > 0 result = s.i to s(scs)."s" end ; !OF STRINGFN HMS !* !* end {m input} external routine m poff message(record (parmf) name p) record (message f)arrayformat message af(1:1000) record (message f)arrayname messages record (rf)re switch activity (20:40) integer remote number, flag, i string (15) for string (63) message iselect output(0) -> activity(p_dest & x'0000ffff') activity(*): return activity(30): connect("SPOOLR.RJEMESS",r!s,0,0,re,flag) if flag # 0 and flag # 34 then monitor messages == array(re_conad+file header size,message af) for = messages(p_p2)_remote name message = messages(p_p2)_message remote number = p_p1 cycle i = 0,1,max consoles if connections(i)_name = "MANAGER" or connections(i)_name = for start iselect output(consoles(i)) if connections(i)_name = "MANAGER" then iprintstring("Message for ".for." (".itos(remote number). c ") ".snl) iprintstring(message.snl) iprompt("<> ") iterminate finish repeat return activity(31): !The reply from the password check by SPOOLR iselect output(consoles(P_p2)) if p_p1 # 0 start iprintstring("Invalid pass".snl) if connections(P_p2)_disabled = locked then ilogoff(consoles(P_p2)) return finish connections(P_p2)_disabled = no iprompt("<> ") iterminate return end {m poff message} external routine m finalise(integer console) integer i for i=0, 1, 127 cycle if consoles(i)=console then consoles(i)=255 repeat end {m finalise} endoffile