2! PROGRAM : CNODE.B2S 5! VERSION : V1.1 6! EDIT : 04 7! EDIT DATE : 10-Nov-90 10 EXTEND 11 ! & & & ! C O P Y R I G H T & & & ! Copyright (C) 1990 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 21-Jun-90 Initial coding for field test. & ! V1.0-01 05-Aug-90 It's official - release it. & ! T1.1-02 27-Sep-90 Allow leading/trailing spaces in & ! the configuration file. & ! T1.1-03 27-Sep-90 Correct typos, punct. in error msgs. & ! V1.1-04 10-Nov-90 Handle L argument in config. file & & & 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. & ! ackdly% Delay in seconds before acknowledging multicast & ! bcount Byte count returned from Ethernet handler & ! cclmode% Flag indicating we are running as a CCL & ! e$ Text of error message to display & ! e.itml% Length of System ID component & ! e.itmn% Number of System ID component & ! e.itmv$ Value of System ID component & ! e.len% Length of data portion of MOP message & ! enet$ Ethernet controller filename & ! eptr% Pointer to current System ID component & ! erno% Error message number & ! ether$ Ethernet data record for load/dump messages & ! flip% Byte which toggles between 0 and 1 for sequencing & ! 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 & ! lodall% Flag for whether we should load unknown servers & ! maplis$() Translation of requested load image to RSTS filespec & ! newflip% Next state of flip% & ! nummap% Number of entries in maplis$ & ! numser% Number of entries in serlis$ & ! seradd$ DECnet address of current server & ! serasc$ ASCII value of server address & ! 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% Console keyboard & & & 50 ! & & & ! F U N C T I O N U S A G E & & & ! FUNCTION USAGE & ! fnbin$($) Convert 2 ASCII hex digits to binary & ! fne$(%) Return the error message text of argument & ! fnhex$($) Convert the argument to an octet-style string & ! geteth Returns an Ethernet message. Workaround for RECORD & ! bug in older BP2 versions & ! puteth Like geteth, but for writes & & & 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 Main program & ! 30000-30999 CCL entry point & ! 32000-32599 Error handling & ! 32767-32767 Exit processing & & & 1000 ! Entry point if "RUN" & & on error goto 32000 & \ 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-04" & \ print "CNODE ";vers$;" ";fne$(0%) unless cclmode%=1% & \ escfix$=chr$(0%) & \ escfix$=escfix$+chr$(i%) for i%=1% to 13% & \ escfix$=escfix$+chr$(142%)+chr$(143%) & \ escfix$=escfix$+chr$(i%) for i%=16% to 26% & \ escfix$=escfix$+chr$(155%) & \ escfix$=escfix$+chr$(i%) for i%=28% to 255% & ! 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 "?CNODE requires SWCTL privilege." & \ goto 32767 & ! Drop temporary privs & ! Ensure user has SWCTL priv. & 1020 a$=sys(chr$(6%)+chr$(-21%)+chr$(0%)) & \ a$=sys(chr$(6%)+chr$(-29%)) & \ enet$="XE0:" & \ enet$="XH0:" if (swap%(cvt$%(mid(a$,21%,2%))) and 32%) & \ enet$=enet$+"/CL:4/PO:608/MO:0" & ! See if we are a Unibus system. Set Ethernet device name accordingly & 1050 open "MOP$:MOPSRV.CNF" for input as file #2% & ! Open the configuration file & 1060 input line #2%,a$ & \ a$=cvt$$(a$,32%) & \ a$=mid(a$,1%,len(a$)-2%) & \ goto 1210 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 1060 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 print "?Error in configuration file - "+e$+":" & \ print" "+a$ & \ print " " & \ 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 & 1210 open "KB:" as file #3% & \ a$=node$ & \ goto 1217 if cclmode%=1% & ! Initially open keyboard in normal mode & ! If user entered via CCL, skip the prompt & 1215 print #3%,"" & \ print #3%,"Node: "; & \ input line #3%,a$ & \ a$=cvt$$(mid(a$,1%,len(a$)-2%),32%) & 1217 for i%=0% to numser%-1% & \ goto 1220 if serlis$(i%,3%)=a$ & \ next i% & \ print "?No such node is defined..." & \ goto 1215 unless cclmode%=1% & \ goto 32767 & ! Ask for a node name. Look it up and return the index into the & ! server list. & 1220 close #3% & \ open "KB:" as file #3%, mode 1% & \ open enet$ as file #1%, recordsize 1514% & \ field #1%, 1514% as ether$ & ! Open the terminal in binary mode so we do the right thing with & ! ^C, escape sequences, etc. & ! Open a channel to the Ethernet device protocol 60-02 (MOP Console) & 1230 serasc$=serlis$(i%,1%) & \ seradd$="" & \ for j%=1% to 16% step 3% & \ seradd$=seradd$+fnbin$(mid(serasc$,j%,2%)) & \ next j% & ! Convert the address to binary in seradd$ & 1240 lset ether$=seradd$+string$(10%,0%)+chr$(13%)+string$(8%,0%) & \ call puteth(1%,ether$,1514%,25%) & \ lset ether$=seradd$+string$(10%,0%)+chr$(5%)+string$(3%,0%) & \ call puteth(1%,ether$,1514%,20%) & ! Send Reserve console and Request ID messages & 1250 call geteth(1%,ether$,1514%,8192%) & \ goto 1250 if mid(ether$,7%,6%)<>seradd$ & \ goto 1260 if mid(ether$,17%,1%)=chr$(7%) & \ print #3%,"?Received unexpected message number "; & num1$(ascii(mid(ether$,17%,1%))) & \ goto 1340 & ! Await a response. If not from the server we want, toss it. & ! Make sure it's the _right_ response. & 1260 e.len%=swap%(cvt$%(mid(ether$,15%,2%))) & \ eptr%=21% & ! Get the length of the data portion of the packet. & ! Set a pointer to the start of the parameter region. & 1270 goto 1280 if eptr% > e.len%+14% & \ e.itmn%=swap%(cvt$%(mid(ether$,eptr%,2%))) & \ e.itml%=ascii(mid(ether$,eptr%+2%,1%)) & \ e.itmv$=mid(ether$,eptr%+3%,e.itml%) & \ goto 1275 if e.itmn%<>3% & \ goto 1275 if e.itmv$=mid(ether$,1%,6%) & \ print #3%,"?Console carrier in use by ";fnhex$(e.itmv$) & \ goto 1340 & ! Start picking apart items. See if the current item is the console & ! user field. If not, skip. Otherwise, see if it's us or not. If not, & ! print an error message and re-prompt for new node & 1275 eptr%=eptr%+e.itml%+3% & \ goto 1270 & ! Update pointer information. 1280 flip%=1% & \ print #3%,"Console connected (press CTRL/D when finished)" & ! Set the message number field & ! Tell him what a lucky guy he is & 1300 get #3%, record 8192% & \ field #3%, recount as a$ & \ goto 1340 if instr(1%,a$,chr$(4%)) & \ goto 1330 & ! Do a no-stall read. If it completes, check for ^D and exit if set. & 1310 sleep 1% & ! Wait a second to reduce CPU loading & 1315 lset ether$=seradd$+string$(10%,0%)+chr$(17%)+chr$(flip%) & \ call puteth(1%,ether$,1514%,18%) & \ newflip%=1% if flip%=0% & \ newflip%=0% if flip%=1% & \ flip%=newflip% & ! Send a null console carrier message & 1320 call geteth(1%,ether$,1514%,8192%) & \ goto 1320 if mid(ether$,7%,6%)<>seradd$ & \ goto 1320 if mid(ether$,17%,1%)<>chr$(19%) & \ e.len%=swap%(cvt$%(mid(ether$,15%,2%)))-2% & \ goto 1300 if e.len%=0% & \ a$=xlate(mid(ether$,19%,e.len%),escfix$) & \ print #3%, a$; & \ goto 1315 & ! Since we sent something, we need to read a response. & ! Loop if not desired source or wrong protocol. & ! See if any data was passed. Go wait if not. Otherwise print it & ! and send an immediate ack in case there's more. & 1330 lset ether$=seradd$+string$(10%,0%)+chr$(17%)+chr$(flip%)+a$ & \ call puteth(1%,ether$,1514%,18%+len(a$)) & \ newflip%=1% if flip%=0% & \ newflip%=0% if flip%=1% & \ flip%=newflip% & \ goto 1320 & ! Send the user's data. Go receive response from server. & 1340 print #3%,"" & \ close #3% & \ goto 32767 if cclmode%=1% & \ goto 1210 & ! We got a ^D, end binary mode. & ! If in CCL mode, exit, otherwise go get a new node name & 20000 ! Functions & & ! Return error message text & & def* fne$(erno%) & \ fne$=cvt$$(right(sys(chr$(6%)+chr$(9%)+chr$(erno%)),3%),5%) & \ fnend & 20020 & ! Convert octet format ASCII to binary data & & def* fnbin$(text$) & \ a$="" & \ i%=16%*(instr(1%,htab$,mid(text$,1%,1%))-1%)+ & (instr(1%,htab$,mid(text$,2%,1%))-1%) & \ fnbin$=chr$(i%) & \ fnend & 20030 & ! 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 & 30000 ! CCL entry point & & req$=sys(chr$(7%)) & \ i%=instr(1%,req$," ") & \ if i%=0% then cclmode%=0% & \ goto 1000 & ! Do a get core common & ! Any argument specified? & ! If not, then treat sort of like a RUN & 30010 node$=mid(req$,i%+1%,len(req$)) & \ cclmode%=1% & \ goto 1000 & ! Strip off the CCL name & ! Say we're in CCL mode & ! Go handle like a RUN & 32000 ! Error handlers & ! & erno%=err ! Error number & \ resume 1210 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 32767 if erl=1215 ! Eof at Node: & \ resume 32030 if erl=1220 ! Protocol in use & \ resume 1310 if erl=1300 and erno%=13% ! No data at KB: & \ goto 32020 & 32010 print "?Missing configuration file - can't continue" & \ print "" & \ goto 32767 & ! Complain about missing file and exit & 32020 print fne$(erno%)+" at line "+num1$(erl)+"." & \ resume 32767 & ! Error we don't handle, simply report it & 32030 print "?Console carrier in use by another job" & \ print "" & \ goto 32767 & 32767 end ! Not as simple as it looked, eh?