!TITLE Making a terminal locations file ! ! The program described in this section implements the MAKELOCS command, ! used for generating a file which describes the location and ! characteristics of each terminal attached to the network. In fact, ! the characteristics of the terminal are held elsewhere: MAKELOCS just ! stores a unique number for each type of terminal. ! !<Files used ! ! Currently, four input files are required, and a single output file is ! produced. In the descriptions given here, fields marked with * must ! be present, but are ignored. The files are: ! !<The PADs file ! ! This file contains a line for each PAD in the network. It gives ! the name of the PAD, and describes where the PAD may be found. ! ! Each entry contains the following fields, separated by colons: ! ! *PAD number - Line number of entry ! PAD name - Name of PAD, up to 15 characters ! PAD location - Where the PAD may be found ! !> !<The TTYs file ! ! This file contains a line for each terminal in the network. It ! describes the type, building and location of each terminal, and gives ! much other information not needed here. ! ! Each entry contains the following fields, separated by colons: ! ! PAD name - PAD to which the terminal is attached ! *Line type - Multiplexer, PAD or interface type ! *Hardware line - Multiplexer port number or interface number ! Line number - Unique line number of terminal on that PAD ! *Line speed - Usually 'auto' ! *Line interface- Usually '20ma' or 'rs232' ! Line status - Usually 'ok' or 'us' (null also means 'ok') ! Last change - Date this entry was last altered ! Local printer - Nearest printer to the terminal ! Terminal type - Cryptic string (ignore part after comma) ! Building - Building (or part) housing the terminal ! Location - Identification of terminal within building !> !<The locations file ! ! This file contains a line for each possible PAD location, giving ! useful groupings of PADs. ! ! Each entry contains the following fields, separated by colons: ! ! Location A - All PADs in same building have the same number ! in this field ! Location B - A number used to distinguish different PADs in ! the same building ! Description - A string describing the location !> !<The mapping file ! ! This file maps the cryptic terminal type names to the numbers ! actually stored in the output file. It contains one line for each ! mapping. Some mappings are one to one, and some are many to one. ! ! Each entry contains the following fields, separated by colons: ! ! Type name - The name found in the TTYs file ! Type number - The number stored in the output file. !> !<The output file ! ! This is an unstructured data file containing a compressed, easily ! accessed synopsis of the relevant information gleaned from the input ! files. The filename '.' causes the default filename (currently ! TERMLOCFILE) to be used. !> !> !<The MAKELOCS command ! ! This command is used to process the four input files, producing the ! single output file. It is called as follows: ! ! MAKELOCS(padsfile,ttysfile,locationsfile,mappingfile,outputfile) ! ! If a parameter is omitted, a prompt is issued for it. At any stage, a ! reply of ? will cause a short help message to be output. ! ! The program outputs a small number of statistics during the run, which ! concern the number of items found in the input files. !> !*********************************************************************** !* !* Program to set up terminal locations database !* !* Copyright R.D. Eager University of Kent MCMLXXXIII !* !*********************************************************************** ! ! !*********************************************************************** !* !* Constants !* !*********************************************************************** ! constantinteger inchan = 1 constantinteger ssdatafiletype = 4 constantstring (1) snl = " " constantstring (11) default termlocsfile = "TERMLOCFILE" constantstring (85)array params(1:5) = c "PADs file!Give the name of the file containing the names of all the PADs", "TTYs file!Give the name of the file describing all the terminals", "Locns file!Give the name of the file which describes all possible terminal locations", "Map file!Give the name of the file which maps terminal names to types", "Output file!Give the name of the new locations file to be built" ! ! !*********************************************************************** !* !* Record formats !* !*********************************************************************** ! recordformat fdf(integer link,dsnum,byteinteger status,accessroute, valid action,cur state,byteinteger mode of use, mode,file org,dev code,byteinteger rec type,flags, lm,rm,integer asvar,arec,recsize,minrec,maxrec, maxsize,lastrec,conad,currec,cur,end,transfers, darecnum,cursize,datastart,string (31) iden) recordformat hf(integer dataend,datastart,filesize,filetype,sum, datetime,format,mark,npads,padsoffset,nttys, ttysoffset,nlocns,locnsoffset,sp0,sp1) recordformat rf(integer conad,filetype,datastart,dataend) ! recordformat padf(string (15) name,string (31) location, integer maxline,linestart) recordformat ttyf(string (15) loclp,integer type,string (31) building, location) recordformat locnf(halfinteger major,minor,string (31) building) recordformat mapf(string (15) stype,integer ntype) ! ! !*********************************************************************** !* !* Subsystem references !* !*********************************************************************** ! externalroutinespec cherish(string (255) s) systemroutinespec connect(string (31) file,integer mode,hole, prot,record (rf)name r,integername flag) systemroutinespec define(integer chan,string (31) iden, integername afd,flag) systemroutinespec disconnect(string (31) file,integername flag) systemstringfunctionspec failuremessage(integer mess) externalintegerfunctionspec instream systemintegerfunctionspec iocp(integer ep,parm) systemstringfunctionspec itos(integer n) systemintegermapspec mapssfd(integer dsnum) systemroutinespec move(integer length,from,to) systemroutinespec newgen(string (31) file,newfile,integername flag) systemstringfunctionspec nexttemp systemroutinespec outfile(string (31) file,integer size,hole, prot,integername conad,flag) externalintegerfunctionspec outstream systemintegerfunctionspec parmap systemroutinespec permit(string (31) file,string (6) user, integer mode,integername flag) externalroutinespec prompt(string (255) s) systemintegerfunctionspec pstoi(string (63) s) systemroutinespec rename(string (31) file,newfile,integername flag) systemroutinespec setpar(string (255) s) externalroutinespec set return code(integer i) systemroutinespec setwork(integername ad,flag) systemstringfunctionspec spar(integer n) externalstringfunctionspec ucstring(string (255) s) systemroutinespec uctranslate(integer ad,len) ! ! !*********************************************************************** !* !* Service routines !* !*********************************************************************** ! routine closestream(integer chan) ! Private version of 'closestream'. Does not give an error if the ! operation fails. integer flag ! return unless instream # chan # outstream flag = iocp(16,chan) end ; ! of closestream ! !----------------------------------------------------------------------- ! routine clearstream(integer chan) ! Clears out a channel definition, but does not give an error if the ! channel was not defined. record (fdf)name f ! if mapssfd(chan) # 0 then start f == record(mapssfd(chan)) if f_status = 0 then start mapssfd(chan) = 0 f_dsnum = 0; ! Mark descriptor as free finish finish end ; ! of clearstream ! !----------------------------------------------------------------------- ! integerfunction findpad(string (15) name,integer padsad,npads) ! Locates the record describing the PAD called 'name', returning the ! address of that record. If no record exists for the specified PAD, ! zero is returned. integer i record (padf)name pad ! uctranslate(addr(name)+1,length(name)) for i = 1,1,npads cycle pad == record(padsad) if pad_name = name then result = padsad padsad = padsad + sizeof(pad) repeat result = 0 end ; ! of findpad ! !----------------------------------------------------------------------- ! integerfunction otoi(string (7) s) ! Converts the octal number described by 's' to a binary number, ! yielding this number as a result. integer i,n ! n = 0 for i = 1,1,length(s) cycle n = (n << 3)!(charno(s,i) - '0') repeat result = n end ; ! of otoi ! !----------------------------------------------------------------------- ! routine readline(stringname s) ! Reads a line from the currently selected input stream, into 's'. Null ! lines are ignored, and end of file causes ".END" to be returned. integer c ! on event 9 start ; ! Trap 'Input Ended' s = ".END" return finish ! s = "" cycle cycle readsymbol(c) exit if c = nl s <- s.tostring(c) repeat while length(s) # 0 and charno(s,length(s)) = ' ' cycle length(s) = length(s) - 1 repeat while length(s) # 0 and charno(s,1) = ' ' cycle s = substring(s,2,length(s)) repeat repeat until s # "" end ; ! of readline ! !----------------------------------------------------------------------- ! routine getfile(integer n,stringname file) ! Obtains a filename from parameter 'n'. If the parameter is null, the ! filename is read from the currently selected input after prompting ! with a suitable prompt. If the reply '?' is given, a short help ! message is given and the prompt is then re-issued. string (15) pr string (255) help ! file = spar(n) return if file # "" ! params(n) -> pr.("!").help cycle prompt(pr.": ") readline(file) uctranslate(addr(file)+1,length(file)) exit unless file = "?" printstring(help.snl) repeat end ; ! of getfile ! !----------------------------------------------------------------------- ! integerfunction openfile(string (31) file) ! Opens 'file' on stream 'inchan'. Yields a result code indicating ! success or failure. integer flag,afd record (rf) rr ! connect(file,1,0,0,rr,flag) if flag = 0 then define(inchan,file,afd,flag) if flag = 0 then selectinput(inchan) result = flag end ; ! of openfile ! !----------------------------------------------------------------------- ! routine invalid(string (255) s,string (31) file,integer line) ! Prints an error message about an invalid line in one of the input ! files. printstring("Invalid line in file ".file." on line ".itos(line).":".snl) printstring(" ".s.snl) end ; ! of invalid ! ! !*********************************************************************** !* !* M A K E L O C S !* !*********************************************************************** ! externalroutine makelocs(string (255) parms) integer flag,workad,npads,padsad,nttys,ttysad,nlocns,locnsad,nmaps integer mapsad,line,len,i,j,ad,conad,nextline,workbase,size,padsize integer ttysize,locnsize,mapsize,inputline string (31) padsfile,ttysfile,locnsfile,mapsfile,out string (255) s,work1,work2,work3,work4,linestr,typestr,status,loclp string (255) building,location,padstr,work record (hf)name h record (padf)name pad record (ttyf)name tty record (locnf)name locn record (mapf)name map ! setpar(parms) if parmap > 31 then start flag = 263; ! Wrong number of parameters -> err finish ! if parmap = 1 and spar(1) = "?" then start printstring("If no parameters are given, suitable prompts are issued".snl) set return code(0) return finish ! getfile(1,padsfile) getfile(2,ttysfile) getfile(3,locnsfile) getfile(4,mapsfile) getfile(5,out) out = default termlocsfile if out = "." ! padsize = sizeof(pad) ttysize = sizeof(tty) locnsize = sizeof(locn) mapsize = sizeof(map) workad = 0 setwork(workad,flag) -> err if flag # 0 workbase = workad ! ! Read the PADs file, and set up a record array of PAD names and ! locations. ! flag = openfile(padsfile) -> err if flag # 0 npads = 0 padsad = workad inputline = 0 cycle readline(s) exit if s = ".END" inputline = inputline + 1 pad == record(workad) unless s -> work1.(":").padstr.(":").work2 then start invalid(s,padsfile,inputline) continue finish pad_name <- ucstring(padstr) pad_location <- work2 pad_maxline = -1 npads = npads + 1 workad = workad + padsize repeat printstring("Number of PADs: ".itos(npads).snl) selectinput(0) closestream(inchan) ! ! Read the TTYs file, and discover how many lines there are on each PAD. ! This number includes 'dead' lines on a sparsely allocated PAD. ! flag = openfile(ttysfile) -> err if flag # 0 inputline = 0 cycle readline(s) exit if s = ".END" inputline = inputline + 1 continue unless s -> padstr.(":").work1.(":").work2.(":").linestr.(":") len = length(linestr) i = len - 2 i = 1 if i < 1 line = otoi(substring(linestr,i,len)) ad = findpad(padstr,padsad,npads) if ad = 0 then start printstring("PAD not known in entry on line ".itos(inputline)." of file ".ttysfile.":".snl) printstring(" ".s.snl) continue finish pad == record(ad) pad_maxline = line if pad_maxline < line repeat nttys = 0 for i = 0,1,npads-1 cycle pad == record(padsad+padsize*i) nttys = nttys + pad_maxline + 1 repeat printstring("Number of TTYs: ".itos(nttys).snl) selectinput(0) closestream(inchan) ! nextline = 0 ttysad = workad for i = 0,1,npads - 1 cycle pad == record(padsad+padsize*i) pad_linestart = nextline nextline = nextline + pad_maxline + 1 ad = workad workad = workad + ttysize*(pad_maxline+1) for j = 0,1,pad_maxline cycle tty == record(ad) tty = 0 ad = ad + ttysize repeat repeat ! ! Read the locations file, and set up a record array of information ! about PAD locations. ! flag = openfile(locnsfile) -> err if flag # 0 nlocns = 0 locnsad = workad inputline = 0 cycle readline(s) exit if s = ".END" inputline = inputline + 1 locn == record(workad) unless s -> work1.(":").work2.(":").building then start invalid(s,locnsfile,inputline) continue finish i = pstoi(work1) j = pstoi(work2) unless 0 <= i <= 255 and 0 <= j <= 255 then start invalid(s,locnsfile,inputline) continue finish locn_major = i locn_minor = j locn_building <- building nlocns = nlocns + 1 workad = workad + locnsize repeat printstring("Number of locations: ".itos(nlocns).snl) selectinput(0) closestream(inchan) ! ! Read the mapping file, and set up a record array of terminal type ! names and type numbers. ! flag = openfile(mapsfile) -> err if flag # 0 nmaps = 0 mapsad = workad inputline = 0 cycle readline(s) exit if s = ".END" inputline = inputline + 1 map == record(workad) unless s -> work1.(":").work2 then start invalid(s,mapsfile,inputline) continue finish map_stype <- work1 i = pstoi(work2) unless 0 <= i <= 255 then start invalid(s,mapsfile,inputline) continue finish map_ntype = i nmaps = nmaps + 1 workad = workad + mapsize repeat printstring("Number of mappings: ".itos(nmaps).snl) selectinput(0) closestream(inchan) ! ! Re-read the TTYs file, and set up a record array of terminal names, ! locations and other information. ! flag = openfile(ttysfile) -> err if flag # 0 inputline = 0 cycle readline(s) exit if s = ".END" inputline = inputline + 1 unless s -> padstr.(":").work.(":").work1.(":").linestr.c (":").work2.(":").work3.(":").status.(":").work4.(":").loclp.c (":").typestr.(":").building.(":").location then start invalid(s,ttysfile,inputline) continue finish len = length(linestr) i = len - 2 i = 1 if i < 1 line = otoi(substring(linestr,i,len)) ad = findpad(padstr,padsad,npads) continue if ad = 0 pad == record(ad) ad = ttysad + (pad_linestart+line)*ttysize tty == record(ad) uctranslate(addr(status)+1,length(status)) continue unless status = "OK" or status = "" or status = "TEST" uctranslate(addr(loclp)+1,length(loclp)) if loclp = "LPEMAS" or loclp = "LPR" then loclp = "LP" tty_loclp <- loclp tty_building <- building tty_location <- location if typestr = "" then tty_type = 0 else c if ucstring(typestr) = "UNKNOWN" then tty_type = -1 else start if typestr -> typestr.(",") then start ; finish ! Strip rubbish tty_type = 0 ad = mapsad for i = 1,1,nmaps cycle map == record(ad) if typestr = map_stype then start tty_type = map_ntype exit finish ad = ad + mapsize repeat if tty_type = 0 then start printstring("Warning - terminal type '".typestr."' on line ".c itos(inputline)." of file ".ttysfile." not known".snl) finish finish repeat selectinput(0) closestream(inchan) ! ! Now build the output file. ! s = "T#".nexttemp; ! Workfile size = mapsad - workbase + sizeof(h) outfile(s,size,0,0,conad,flag) -> err if flag # 0 h == record(conad) h_dataend = h_filesize h_filetype = ssdatafiletype h_format = 3; ! Un-structured h_mark = 1; ! For future compatibility h_npads = npads h_nttys = nttys h_nlocns = nlocns h_sp0 = 0 h_sp1 = 0 ad = conad + sizeof(h); ! Point beyond header h_padsoffset = ad - conad move(npads*padsize,padsad,ad) ad = ad + npads*padsize h_ttysoffset = ad - conad move(nttys*ttysize,ttysad,ad) ad = ad + nttys*ttysize h_locnsoffset = ad - conad move(nlocns*locnsize,locnsad,ad) disconnect(s,flag) rename(s,out,flag) if flag # 0 then newgen(s,out,flag) -> err if flag # 0 cherish(out) permit(out,"",1,flag); ! Permit in read mode -> err if flag # 0 ! selectinput(0) closestream(inchan) clearstream(inchan) printstring("Finished OK".snl) set return code(0) stop ! err: selectinput(0) closestream(inchan) clearstream(inchan) printstring(snl."MAKELOCS fails -".failuremessage(flag)) set return code(flag) stop end ; ! of makelocs endoffile