2! PROGRAM : MOPSRV.B2S 5! VERSION : V1.1 6! EDIT : 13 7! EDIT DATE : 13-Dec-92 10 EXTEND 11 ! & & & ! C O P Y R I G H T & & & ! Copyright (C) 1990, 1992 by Terence M. Kennedy, & ! All Rights Reserved. & ! & ! & ! This software is furnished under a license and may be used and & ! copied only in accordance with the terms of such license and & ! with the inclusion of the above copyright notice. This & ! software or any other copies thereof may not be provided or & ! otherwise made available to any other person. No title to and & ! ownership of the software is hereby transferred. & ! & ! The information in this software is subject to change without & ! notice and should not be construed as a commitment by either & ! Terence M. Kennedy or Saint Peter's College. & ! & !******************************************************************* & & 20 ! & & & ! M O D I F I C A T I O N H I S T O R Y & & & ! VER/ED EDIT DATE REASON & ! T1.0-00 09-Jun-90 Initial coding for field test. & ! T1.0-01 15-Jun-90 Added Q/U test, logging code. & ! T1.0-02 17-Jun-90 Rough cut of load support completed. & ! T1.0-03 20-Jun-90 Remove hardwired assumptions. & ! T1.0-04 03-Jul-90 Convert GETs to macro for old BP2's, & ! do dump as well as load, honor LODALL & ! flag to deny load/dump of unknown & ! server. & ! T1.0-05 05-Jul-90 Add pseudo-timeout code, handle multi- & ! ple simultaneous requests gracefully. & ! T1.0-06 06-Jul-90 Fixed logfile operation, added detach- & ! operation. Move the PUTs to macro as & ! well (ugh). Tested with 10 servers at & ! one time. This one goes to beta sites. & ! T1.0-07 20-Jul-90 Add DS5xx support, as well as trans- & ! parent support for other devices that & ! do not supply a software ID field, & ! work around bogus controller resets & ! in the device driver. & ! V1.0-08 05-Aug-90 It's official - release it. & ! T1.1-09 27-Sep-90 Start work on V1.1 - .SYS bugfix, log & ! event as single broadcast, add switch & ! to reduce console messages, tolerate & ! trailing blanks in .CNF file, check & ! for existing server at startup. & ! T1.1-10 27-Sep-90 Correct typos, punct. in error msgs. & ! T1.1-11 10-Nov-90 Add extra CR/LF in event broadcast. & ! V1.1-12 03-Dec-90 Store crash info in MOP$:MOPSRV.DMP. & ! V1.1-13 13-Dec-92 Fix MOPMAC to handle DATERR errors. & & & 30 ! & & & ! V A R I A B L E U S A G E & & & ! VARIABLE USAGE & ! a$,b$,c$ Dummy variables for SYS() calls, etc. & ! a.frad$ ASCII value of server's Ethernet address & ! a.prot$ ASCII value of Ethernet protocol field & ! a.toad$ ASCII value of host's Ethernet address & ! ackdly% Delay in seconds before acknowledging multicast & ! bcount Byte count returned from Ethernet handler & ! crlf$ Just what it says... & ! debug% Debugging flag & ! dmpimg$ RSTS filename of dump image & ! e$ Text of error message to display & ! e.frad$ Binary value of server's Ethernet address & ! e.func% MOP function code & ! e.imag$ Name of load image requested by server & ! e.len% Length of data portion of MOP message & ! e.prot$ Binary value of Ethernet protocol field & ! e.toad$ Binary value of host's Ethernet address & ! enet$ Ethernet controller filename & ! erno% Error message number & ! ether$ Ethernet data record for load/dump messages & ! hstadd% DECnet address of host (this) node & ! hstnam$ DECnet node name of host (this) node & ! htab$ ASCII values of hex digits & ! i%,j% Scratch variables & ! job% Job number of this job & ! lastim% Time of last packet for timeout code & ! lodall% Flag for whether we should load unknown servers & ! lodbas% Base address for load (incremented as we go) & ! lodbyt() Alternative representation of lodbas% & ! loddat$ Disk data record for load/dump messages & ! lodimg$ RSTS filename of load image (translated e.imag$) & ! lodxfr% Transfer address for loaded image & ! loglvl% Logging level & ! maplis$() Translation of requested load image to RSTS filespec & ! msgbuf$ Temporary buffer for console message & ! nummap% Number of entries in maplis$ & ! numser% Number of entries in serlis$ & ! segno% Segment number of load/dump message & ! seradd$ DECnet address of current server & ! serlis$() List of servers we will download upon request & ! sernam$ DECnet node name of current server & ! text$ Prototype for string functions & ! vers$ Version of this program & & & 40 ! & & & ! I / O C H A N N E L U S A G E & & & ! CHANNEL USAGE & ! #1% Ethernet interface & ! #2% Configuration file, read on startup & ! #3% Log file of MOP transactions & ! #4% Load/Dump file for server image & ! #5% MOPSRV crash dump information & & & 50 ! & & & ! F U N C T I O N U S A G E & & & ! FUNCTION USAGE & ! fne$(%) Return the error message text of argument & ! fnevent$($) Generate a pseudo-event to the log & ! fnhex$($) Convert the argument to an octet-style string & ! fnlog$($) Write the argument to the log console and file & ! fntimeout% Simulate timeout processing for Ethernet reads & ! geteth Returns an Ethernet message. Workaround for RECORD & ! bug in older BP2 versions & ! puteth Like geteth, but for writes & ! setmul Enables multicast address for dump/load assist & & & 60 ! & & & ! M A J O R P R O G R A M S E C T I O N S & & & ! SECTION USAGE & ! 1000- 1999 Declarations, RUN trap, packet listener & ! 2000- 2999 Process load solicits & ! 3000- 3999 Process dump solicits & ! 4000- 4999 Process explicit load/dump requests & ! 5000- 5999 Process explicit loads & ! 6000- 6999 Process explicit dumps & ! 32000-32599 Error handling & ! 32767-32767 Exit processing & & & 1000 ! Entry point if "RUN" & & on error goto 32000 & \ map (lodbp2) byte lodbyt(3%) & \ map (lodbp2) long lodbas% & \ declare long lodxfr% & \ declare long hstadd% & \ external word bcount & \ external sub setmul by ref & \ external sub geteth by ref (word, string, word, word) & \ external sub puteth by ref (word, string, word, word) & \ dim serlis$(255%,3%) & \ dim maplis$(32%,2%) & \ lodall%=1% & \ numser%=0% & \ nummap%=0% & \ ackdly%=0% & \ hstadd%=0% & \ hstnam$=fne$(0%) & \ htab$="0123456789ABCDEF" & \ vers$="V1.1-13" & \ crlf$=chr$(13%)+chr$(10%) & \ debug%=0% & \ print "MOPSRV ";vers$;" ";fne$(0%);crlf$ & ! Print our welcome banner & 1010 a$=sys(chr$(6%)+chr$(-21%)+chr$(255%)) & \ a$=sys(chr$(6%)+chr$(32%)+chr$(1%)+chr$(0%)+chr$(0%)+chr$(0%)+ & "SWCTL") & \ goto 1020 if mid(a$,3%,1%)=chr$(0%) & \ print "?MOPSRV requires SWCTL privilege." & \ goto 32767 & ! Drop temporary privs & ! Ensure user has SWCTL priv. & 1020 a$=sys(chr$(6%)+chr$(-21%)+chr$(0%)) & \ i%=peek(peek(156%)+2%) & \ job%=peek(518%)/2% & ! Regain temporary privs & ! Save job number for later detach message & 1030 a$=sys(chr$(6%)+chr$(-29%)) & \ enet$="XE0:" & \ enet$="XH0:" if (swap%(cvt$%(mid(a$,21%,2%))) and 32%) & \ enet$=enet$+"/CL:4/PO:352/MO:0" & ! See if we are a Unibus system. Set Ethernet device name accordingly & 1040 open "MOP$:MOPSRV.LOG" as file #3%, mode 2% & \ print #3%," " & \ print #3%,"MOPSRV ";vers$;" ";fne$(0%);" started on ";date$(0%);" "; & time$(0%) & \ print #3%," " & \ close #3% & \ open "MOP$:MOPSRV.LOG" as file #3%, mode 2% & ! This will give us an error if another copy is already running & 1050 open "MOP$:MOPSRV.CNF" for input as file #2% & ! Open the configuration file & 1060 input line #2%,a$ & \ a$=cvt$$(a$,184%) & \ a$=mid(a$,1%,len(a$)-2%) & \ goto 1180 if a$="Q" & \ goto 1060 if left(a$,1%)="!" & \ goto 1070 if left(a$,1%)="E" & \ goto 1080 if left(a$,1%)="S" & \ goto 1100 if left(a$,1%)="M" & \ goto 1110 if left(a$,1%)="W" & \ goto 1120 if left(a$,1%)="H" & \ goto 1140 if left(a$,1%)="D" & \ goto 1160 if left(a$,1%)="L" & \ e$="unrecognized keyword" & \ goto 1090 & ! Read and pre-parse options in the configuration file & 1070 enet$=mid(a$,3%,len(a$)) & \ goto 1060 & ! Set new Ethernet device (should never be needed, but...) & 1080 c$=mid(a$,3%,len(a$)) & \ i%=instr(1%,c$," ") & \ e$="incorrectly delimited S record" & \ goto 1090 if i%=0% & \ b$=mid(c$,1%,i%-1%) & \ c$=mid(c$,i%+1%,len(c$)) & \ e$="invalid Ethernet address" & \ goto 1090 if len(b$)<>17% & \ for i%=1% to 16% step 3% & \ goto 1090 if instr(1%,htab$,mid(b$,i%,1%))=0% & \ goto 1090 if instr(1%,htab$,mid(b$,i%+1%,1%))=0% & \ goto 1090 if mid(b$,i%+2%,1%)<>"-" and i%<>16% & \ next i% & \ serlis$(numser%,1%)=b$ & \ i%=instr(1%,c$," ") & \ e$="bad or missing node name" & \ goto 1090 if i%=0% & \ b$=mid(c$,1%,i%-1%) & \ c$=mid(c$,i%+1%,len(c$)) & \ serlis$(numser%,2%)=b$ & \ serlis$(numser%,3%)=c$ & \ numser%=numser%+1% & \ goto 1060 & ! Split line into Ethernet address, node number, node name & ! Sort-of validate the Ethernet address & ! If valid, add to list, else complain & 1090 msgbuf$="?Error in configuration file - "+e$+":" & \ msgbuf$=msgbuf$+crlf$+" "+a$ & \ b$=fnlog$(msgbuf$) & \ goto 1060 & 1100 a$=mid(a$,3%,len(a$)) & \ i%=instr(1%,a$," ") & \ b$=mid(a$,1%,i%-1%) & \ a$=mid(a$,i%+1%,len(a$)) & \ maplis$(nummap%,1%)=b$ & \ maplis$(nummap%,2%)=a$ & \ nummap%=nummap%+1% & \ goto 1060 & ! Build list of translations between server requests and RSTS filespec & 1110 b$=mid(a$,3%,1%) & \ lodall%=1% if b$="Y" & \ lodall%=0% if b$="N" & \ goto 1060 if b$="Y" or b$="N" & \ e$="W flag not Y or N" & \ goto 1090 & ! Process wildcard flag & 1120 c$=mid(a$,3%,len(a$)) & \ i%=instr(1%,c$," ") & \ e$="incorrectly delimited H record" & \ goto 1090 if i%=0% & \ hstnam$=mid(c$,i%+1%,len(c$)) & \ c$=mid(c$,1%,i%-1%) & \ i%=instr(1%,c$,".") & \ goto 1090 if i%=0% & \ hstadd%=val(mid(c$,1%,i%-1%))*1024%+val(mid(c$,i%+1%,len(c$))) & \ goto 1060 & ! Split line into host node number, node name & 1130 e$="Invalid DECnet address in H record" & \ goto 1090 & 1140 b$=mid(a$,3%,len(a$)) & \ ackdly%=val(b$) & \ goto 1060 if ackdly%>=0% & \ ackdly%=0% & ! Evaluate delay value & ! Only positive values need apply... & 1150 e$="invalid delay interval in D record" & \ goto 1090 & 1160 b$=mid(a$,3%,len(a$)) & \ loglvl%=val(b$) & \ goto 1060 if loglvl%>=0% and loglvl%<3% & \ loglvl%=0% & ! Evaluate logging level & ! Only small positive values need apply... & 1170 e$="invalid logging level in L record" & \ goto 1090 & 1180 close #2% & \ print #3%,"Configuration file processed - " & \ print #3%," Ethernet device: ";enet$ & \ goto 1190 if lodall%=0% & \ print #3%," Unregistered load/dump requests will be honored" & \ goto 1200 & 1190 print #3%," Unregistered load/dump requests will be refused" & 1200 print #3%," The following are the registered server addresses:" & \ print #3%," Server address Node # Node name" & \ for i%=0% to numser%-1% & \ print #3%," ";serlis$(i%,1%);tab(25%);serlis$(i%,2%);tab(36%); & serlis$(i%,3%) & \ next i% & \ print #3%," The following translations will be used for loading:" & \ print #3%," Load image name RSTS filespec" & \ for i%=0% to nummap%-1% & \ print #3%," ";maplis$(i%,1%);tab(23%);maplis$(i%,2%) & \ next i% & \ goto 1210 if ackdly%<>0% & \ print #3%," No delay will be used before responding to requests" & \ goto 1220 & 1210 print #3%," A ";num1$(ackdly%);" second delay will be used before "; & "responding to requests" & 1220 print #3%," Server will respond as host address "; & num1$(hstadd%/1024%);".";num1$(hstadd% and 1023%);" name "; & hstnam$ & \ print #3%," "; & \ print #3%,"All"; if loglvl%=0% & \ print #3%,"All events except solicit"; if loglvl%=1% & \ print #3%,"No"; if loglvl%=2% & \ print #3%," events will be logged" & \ b$=fnlog$(" ") & 1230 open enet$ as file #1%, recordsize 1514% & \ field #1%, 1514% as ether$ & ! Open a channel to the Ethernet device protocol 60-01 (MOP Dump/Load) & 1240 goto 1250 if debug%=1% & \ print "MOPSRV will detach and run as job";job% & \ a$=sys(chr$(6%)+chr$(7%)) & ! Print jobno and detach unless debugging & 1250 call setmul & ! Enable multicast reception for AB-00-00-01-00-00 (Dump/Load Assist) & 1260 call geteth(1%,ether$,1514%,8192%) & ! Read an initial server request. & 1270 lastim%=peek(514%) & \ lastim%=1440% if lastim%=0% & ! Store the time this happened at for future timeouts & ! Special case for midnight & ! This is also the re-entry point for a timeout & 1280 e.toad$=mid(ether$,1%,6%) & \ a.toad$=fnhex$(e.toad$) & \ e.frad$=mid(ether$,7%,6%) & \ a.frad$=fnhex$(e.frad$) & \ e.prot$=mid(ether$,13%,2%) & \ a.prot$=fnhex$(e.prot$) & \ e.len%=swap%(cvt$%(mid(ether$,15%,2%))) & \ e.func%=ascii(mid(ether$,17%,1%)) & \ e.imag$="" & \ e.imag$=mid(ether$,22%,ascii(mid(ether$,21%,1%)))+".SYS" if & e.func%=8% & \ goto 1290 if mid(ether$,21%,1%)=chr$(255%) & \ goto 1290 if mid(ether$,21%,1%)=chr$(0%) & \ goto 1300 & ! Split the message into some useful parts for later & ! If a software ID field was specified, use that. Otherwise, & ! construct one from the 6 Ethernet octets. & 1290 e.imag$=mid(a.frad$,1%,2%)+mid(a.frad$,4%,2%)+mid(a.frad$,7%,2%)+ & mid(a.frad$,10%,2%)+mid(a.frad$,13%,2%)+mid(a.frad$,16%,2%)+".SYS" & 1300 goto 1260 if a.prot$<>"60-01" & \ goto 1260 if e.func%=10% & \ goto 4000 if mid(a.toad$,1%,2%)<>"AB" & \ goto 1310 if e.func%=8% & \ goto 1310 if e.func%=12% & \ goto 1260 & ! Sanity check the protocol number & ! If we just finished a load, there's a bogus read pending, flush it & ! If this is a specific request to us, go handle it & ! See if this is a solicit load or solicit dump. If neither, ignore it & 1310 b$=fnevent$("Solicited") & \ goto 1260 if sernam$="UNKNWN" and lodall%=0% & \ sleep ackdly% if ackdly%<>0% & \ goto 2000 if e.func%=8% & \ goto 3000 if e.func%=12% & \ goto 1260 & ! Spit out the requesting address & ! If we don't know the server and aren't doing wildcards, skip & ! Delay an appropriate amount (can you say "sleepy VAX"?) & ! Decide if this is a load or a dump for futher processing & 2000 ! We were solicited for a load. Check for image and respond if we have & ! something useful to send the server & & for i%=0% to nummap%-1% & \ goto 2010 if maplis$(i%,1%)=e.imag$ & \ next i% & \ goto 1260 & ! Traverse our database of image names. If we know about the requested & ! image, proceed, else ignore the request. & 2010 lodimg$=maplis$(i%,2%) & \ open lodimg$ for input as file #4% & \ close #4% & ! Try opening the file. If we fail, we'll ignore this request & 2020 lset ether$=e.frad$+string$(10%,0%)+chr$(3%) & \ call puteth(1%,ether$,1514%,17%) & \ goto 1260 & ! Say we'll do it & 3000 ! We were solicited for a dump. Respond in the affirmative. & & lset ether$=e.frad$+string$(10%,0%)+chr$(3%) & \ call puteth(1%,ether$,1514%,17%) & \ goto 1260 & ! Say we'll do it & ! I know this could be common with 2000, but this allows some flex- & ! ibility in supporting loads but not dumps or vice versa. & 4000 ! If we get here, we have a request addressed explicitly to us & & b$=fnevent$("Requested") & \ goto 5000 if e.func%=8% & \ goto 6000 if e.func%=12% & \ goto 1260 & ! Log the request & ! Dispatch to either the load or dump processors & ! If not load or dump, ignore it & 5000 ! We are doing a load. Prepare to deliver the file & & open lodimg$ for input as file #4%, recordsize 512% & \ field #4%, 512% as loddat$ & \ segno%=0% & \ get #4% & \ lodbas%=swap%(cvt$%(mid(loddat$,9%,2%))) & \ lodxfr%=swap%(cvt$%(mid(loddat$,233%,2%))) & \ i%=swap%(cvt$%(mid(loddat$,241%,2%))) & \ goto 5010 if i%=1% & \ for j%=1% to i%-1% & \ get #4% & \ next j% & ! Open the load image file & ! Read the header and process it & ! If this is a single-block header, we're done & ! Otherwise, discard additional header blocks & 5010 get #4% & ! Read the next load record & 5020 lset ether$=e.frad$+string$(10%,0%)+chr$(2%)+chr$(segno%)+ & chr$(lodbyt(0%))+chr$(lodbyt(1%))+chr$(lodbyt(2%))+ & chr$(lodbyt(3%))+loddat$ & \ call puteth(1%,ether$,1514%,534%) & \ segno%=segno%+1% & \ segno%=0% if segno%=256% & \ lodbas%=lodbas%+512% & ! Send it out as Memory Load command & 5030 call geteth(1%,ether$,1514%,8192%) & \ i%=fntimeout% & \ goto 1260 if i%=2% & \ goto 1270 if i%=1% & ! Read the next data packet & ! Do timeout processing, bail out if we timed out & 5040 goto 5010 & ! Wait for the acknowledgement from the server & ! When we get it, go loop in next record & 5050 lodbas%=lodxfr% & \ a$=e.frad$+string$(10%,0%)+chr$(20%)+chr$(segno%)+ & chr$(1%)+chr$(len(sernam$))+sernam$+chr$(2%)+chr$(2%) & \ i%=instr(1%,seradd$,".") & \ goto 5060 if i%=0% & \ j%=val(mid(seradd$,1%,i%-1%))*1024%+ & val(mid(seradd$,i%+1%,len(seradd$))) & \ goto 5070 & ! Build the constant part of the Parameter Load w/ Xfer message & ! Try to construct a valid DECnet address & 5060 j%=0% & ! Couldn't get a valid DECnet address, use 0.0 & 5070 a$=a$+cvt%$(swap%(j%))+chr$(3%)+chr$(len(hstnam$))+hstnam$+chr$(4%)+ & chr$(2%)+cvt%$(swap%(hstadd%))+chr$(5%)+chr$(10%) & \ a$=a$+chr$(19%) & \ b$=sys(chr$(6%)+chr$(20%)+chr$(0%)+chr$(0%)+chr$(255%)+chr$(0%)+ & string$(10%,0%)+chr$(0%)+chr$(0%)+chr$(255%)+chr$(0%)) & \ a$=a$+chr$(val(mid(b$,7%,2%)))+ & chr$(val(mid(b$,10%,2%)))+ & chr$(val(mid(b$,13%,2%)))+ & chr$(val(mid(b$,21%,2%)))+ & chr$(val(mid(b$,24%,2%)))+ & chr$(0%)+chr$(0%)+chr$(0%)+chr$(0%)+ & chr$(0%)+chr$(lodbyt(0%))+chr$(lodbyt(1%))+chr$(lodbyt(2%))+ & chr$(lodbyt(3%)) & \ lset ether$=a$ & \ call puteth(1%,ether$,1514%,len(a$)) & ! Append host name, address, server name, address, host time, & ! transfer address to message and send & 5080 b$=fnevent$("Successful") & \ close #4% & \ goto 1260 & ! All done with load, go back to main poll loop & 6000 ! We are doing a dump. Prepare to receive a dump & & dmpimg$="MOP$:"+mid(a.frad$,10%,2%)+mid(a.frad$,13%,2%)+ & mid(a.frad$,16%,2%)+".DMP" & \ dmpimg$="MOP$:"+sernam$+".DMP" unless sernam$="UNKNWN" & \ open dmpimg$ for output as file #4% & \ lodbyt(0%)=ascii(mid(ether$,20%,1%)) & \ lodbyt(1%)=ascii(mid(ether$,21%,1%)) & \ lodbyt(2%)=ascii(mid(ether$,22%,1%)) & \ lodbyt(3%)=ascii(mid(ether$,23%,1%)) & \ lodxfr%=lodbas% & \ lodbas%=0% & ! Open the dump image file & ! Pre-set some useful constants & 6010 lset ether$=e.frad$+string$(10%,0%)+chr$(4%)+chr$(lodbyt(0%))+ & chr$(lodbyt(1%))+chr$(lodbyt(2%))+chr$(lodbyt(3%))+ & cvt%$(swap%(512%)) & \ call puteth(1%,ether$,1514%,23%) & ! Build a Request Memory Dump command and transmit it & 6020 call geteth(1%,ether$,1514%,8192%) & \ i%=fntimeout% & \ goto 1260 if i%=2% & \ goto 1270 if i%=1% & ! Read the next data packet & ! Do timeout processing, bail out if we timed out & 6030 print #4%, mid(ether$,22%,512%); & \ lodbas%=lodbas%+512% & \ goto 6040 if lodbas%>=lodxfr% & \ goto 6010 & ! See if we are at the end of the server's memory & ! Grab the dump data and write it to the dump file & ! Increment the memory address and repeat the process & 6040 lset ether$=e.frad$+string$(10%,0%)+chr$(1%) & \ call puteth(1%,ether$,1514%,17%) & \ b$=fnevent$("Successful") & \ close #4% & \ goto 1260 & ! All done with dump, go back to main poll loop & 20000 ! Functions & & ! Return error message text & & def* fne$(erno%) & \ fne$=cvt$$(right(sys(chr$(6%)+chr$(9%)+chr$(erno%)),3%),5%) & \ fnend & 20010 & ! Log a message to the logfile and to the console & & def* fnlog$(text$) & \ print #3%,text$+crlf$ & \ print text$ if debug%=1% & \ goto 20013 if debug%=1% & \ a$=text$+crlf$+crlf$ & ! Log the message in the logfile & ! See if we are in debug mode & ! If not, just print the text, otherwise log it to KB0: & 20011 b$=sys(chr$(6%)+chr$(-5%)+chr$(0%)+a$) & \ if recount then a$=right(a$,len(a$)-recount+1%) & \ goto 20013 if ascii(mid(sys(chr$(6%)+chr$(16%)),28%,1%))=255% & \ sleep 1% & \ goto 20011 & ! If not, do a broadcast to KB0: & ! If it was a partial, do the rest after checking for /NOBROADCAST & 20013 close #3% & \ open "MOP$:MOPSRV.LOG" as file #3%, mode 2% & ! Log the message to the logging file and console & ! If this is an end-of-event line, flush the file by closing and & ! re-opening it (any suggestions?) & 20015 fnlog$="" & \ fnend & 20020 & ! Convert binary data to octet format ASCII & & def* fnhex$(text$) & \ a$="" & \ for i%=1% to len(text$) & \ j%=ascii(mid(text$,i%,1%)) & \ a$=a$+mid(htab$,(j%/16%)+1%,1%)+mid(htab$,(j% and 15%)+1%,1%)+"-" & \ next i% & \ a$=mid(a$,1%,len(a$)-1%) & \ fnhex$=a$ & \ fnend & 20030 & ! Log an "Event" message & & def* fnevent$(text$) & \ goto 20075 if loglvl%=2% & \ goto 20075 if loglvl%=1% and text$="Solicited" & \ msgbuf$="Event type 0.3, Automatic line service" & \ a$="Occurred "+date$(0%)+" "+time$(0%) & \ a$=a$+" on node "+num1$(hstadd%/1024%)+"."+num1$(hstadd% and 1023%)+ & " ("+hstnam$+")" if hstadd%<>0% & \ msgbuf$=msgbuf$+crlf$+a$ & \ a$="X" & \ a$="U" if mid(enet$,2%,1%)="E" & \ a$="Q" if mid(enet$,2%,1%)="H" & \ a$=a$+"NA-"+mid(enet$,3%,1%) & \ a$="Circuit "+a$+", " & \ a$=a$+"Load" if e.func%=8% & \ a$=a$+"Dump" if e.func%=12% & \ a$=a$+", "+text$ & \ goto 20050 if numser%=0% & \ seradd$="0.0" & \ sernam$="UNKNWN" & \ for i%=0% to numser%-1% & \ goto 20040 if serlis$(i%,1%)=a.frad$ & \ next i% & \ goto 20050 & ! Log the easy stuff & ! Preset server address, name to unknown values & ! Look up the requesting server in our database & 20040 seradd$=serlis$(i%,2%) & \ sernam$=serlis$(i%,3%) & \ a$=a$+", Node = "+seradd$+" ("+sernam$+")" & ! Tack on the node number and address & 20050 msgbuf$=msgbuf$+crlf$+a$ & \ goto 20060 if e.func%<>8% & \ msgbuf$=msgbuf$+crlf$+"File = "+e.imag$+", Operating system" & ! Tack on the requested image if this is a load & 20060 goto 20070 if e.func%<>12% or text$<>"Successful" & \ msgbuf$=msgbuf$+crlf$+"File = "+dmpimg$+", Crash dump" & ! Tack on the dumpfile name if this is a dump & 20070 msgbuf$=msgbuf$+crlf$+"Ethernet address = "+a.frad$ & \ b$=fnlog$(msgbuf$) & 20075 fnevent$=b$ & \ fnend & 20080 & ! Perform timeout processing & & ! Since there is no timout processing available from the monitor, & ! we have to simulate it here. We do this as follows: & ! On every Ethernet read completion but the first one, we check to & ! see if it has been more than two minutes since the previous read & ! completed. If it has, we assume the server we were talking to isn't & ! interested in talking to us any more, and we take the data we got & ! and go back to the initial entry and use it as the start of a new & ! request. If we haven't timed out (less than two minutes) and the & ! read returned a different Ethernet address, we'll ignore it, ass- & ! uming that it's from another server (after all it _better_ be a & ! different server). If that server is really interested in talking to & ! us, it will come bother us later (and hopefully we'll be done with & ! the current request by then). & & def* fntimeout% & 20085 i%=peek(514%) & \ goto 20090 if lastim%-i%<=2% & \ j%=2% & \ j%=1% if mid(ether$,7%,1%)=chr$(171%) & \ goto 20100 & ! Get the current time & ! Skip this if within 2 minutes of present time & ! Otherwise set timeout indicator (reread needed) & ! If this was a multicast message (AB-) modify to no reread needed & ! Goto common exit code & 20090 goto 20095 if e.frad$<>mid(ether$,7%,6%) & \ lastim%=i% & \ lastim%=1440% if lastim%=0% & \ j%=0% & \ goto 20100 & ! Go perform a reread on the Ethernet if a different node responded & ! Update the timout value & ! Special case for midnight & ! Set no timeout flag & ! Goto common exit code & 20095 call geteth(1%,ether$,1514%,8192%) & \ goto 20085 & ! Read another packet & ! Go see if we got a timeout yet & 20100 fntimeout%=j% & \ fnend & ! Return the appropriate status to our caller & 32000 ! Error handlers & ! & erno%=err ! Error number & \ resume 32030 if erl=1040 ! Not 1st copy & \ resume 1180 if erl=1060 ! EOF on config file & \ resume 32010 if erl=1050 ! No config file & \ resume 1120 if erl=1110 ! Invalid DECnet addr & \ resume 1150 if erl=1140 ! Invalid delay & \ resume 32030 if erl=1230 ! Not 1st copy & \ resume 1260 if erl=2010 ! No load image & \ resume 5050 if erl=5010 ! EOF on load image & \ resume 5060 if erl=5050 ! Bad server address & \ goto 32020 & 32010 msgbuf$="?Missing configuration file - can't continue" & \ b$=fnlog$(msgbuf$) & \ goto 32767 & ! Complain about missing file and exit & 32020 open "MOP$:MOPSRV.DMP" for output as file #5% & \ print #5%,"MOPSRV crash at "+time$(0%)+" on "+date$(0%) & \ print #5%,fne$(erno%)+" at line "+num1$(erl)+"." & \ close #5% & \ print fne$(erno%)+" at line "+num1$(erl)+"." & \ resume 32767 & ! Error we don't handle, simply report it & 32030 print "?Another MOPSRV is already running" & \ goto 32767 & ! Another one? & 32767 end ! Not as simple as it looked, eh?