// VMemSpy.bcpl // Copyright Xerox Corporation 1980, 1981 // Last modified September 28, 1982 10:23 PM by Boggs get "SysDefs.d" get "BcplFiles.d" get "AltoDefs.d" get "VMemSpy.decl" get "Pup0.decl" get "Pup1.decl" get "PupRtp.decl" get "PupBsp.decl" get "FtpProt.decl" external [ // incoming procedures Spy; Wss; SysErr CreateKeyboardStream; PutTemplate CreateDisplayStream; ShowDisplayStream EraseBits; CharWidth; SetLmarg GetPartner; CreateBSPStream; BSPReadBlock OpenLevel1Socket; CloseLevel1Socket OpenRTPSocket; CloseRTPSocket UserOpen; UserClose; UserRetrieve InitPList; FreePList Gets; Puts; Closes; Resets CallSwat; Zero; MoveBlock; Noop; Idle InitializeZone; AddToZone; Allocate; Free MyFrame; Enqueue; Junta; MultEq; DoubleIncrement TimerHasExpired; SetTimer ExtractSubstring; CopyString InitializeContext; CallContextList; Block InitPupLevel1; InitFtpUtil; InitFtpPList InitBcplRuntime; LoadRam // outgoing statics dt; nt; port; show; noshow sysZone; dsp // incoming statics keys; sysFont RamImage; CtxRunning UserName; UserPassword; lvUserFinishProc ] static [ dt; nt; show; noshow; port savedUFP; lineWords; sysZone; dsp ] manifest stackLimit = 335b structure BBFD: // BB File Descriptor [ name word blank word 3 ] manifest lenBBFD = size BBFD/16 //---------------------------------------------------------------------------- let VMemSpy() be //---------------------------------------------------------------------------- [ let juntaLevel = LoadRam(RamImage) eq 0? levBasic, levBcpl if juntaLevel eq levBasic then InitBcplRuntime() Junta(juntaLevel, AfterJunta) ] //---------------------------------------------------------------------------- and AfterJunta() be //---------------------------------------------------------------------------- [ CreateKeyboardStream() Idle = Block for i = 0 to 7 do cursorBitMap!i = 177400b for i = 8 to 15 do cursorBitMap!i = 377b savedUFP = @lvUserFinishProc; @lvUserFinishProc = SpyFinish let freeBegin = @stackLimit @stackLimit = MyFrame() -200 sysZone = InitializeZone(freeBegin, 77777b, SysErr, 0) AddToZone(sysZone, freeBegin+77777b, @stackLimit-freeBegin-77777b) lineWords = lDCB+10+38*2*((sysFont!-2+1) rshift 1) dsp = CreateDisplayStream(6, Allocate(sysZone, 3*lineWords), 3*lineWords) ShowDisplayStream(dsp, DSalone) Wss(dsp, "VMemSpy of 29 Sept 82") port = Allocate(sysZone, lenPort) nt = Allocate(sysZone, maxOvs); Zero(nt, maxOvs) let ctxQ = Allocate(sysZone, 2); ctxQ!0 = 0 InitPupLevel1(sysZone, ctxQ, 10) InitFtpUtil() InitFtpPList() Enqueue(ctxQ, InitializeContext(Allocate(sysZone, 500), 500, SpyCtx, lenExtraCtx)) CallContextList(ctxQ!0) repeat //forever ] //---------------------------------------------------------------------------- and SpyFinish() be //---------------------------------------------------------------------------- [ manifest kbInterruptBit = 1 lshift 12 @activeInterrupts = @activeInterrupts & not kbInterruptBit @displayInterrupt = @displayInterrupt & not kbInterruptBit @displayListHead = 0 for i = 0 to 30000 loop @lvUserFinishProc = savedUFP ] //---------------------------------------------------------------------------- and Wss(stream, string) be //---------------------------------------------------------------------------- for i = 1 to string>>String.length do Puts(stream, string>>String.char↑i) //---------------------------------------------------------------------------- and SysErr(p1, errNo, p2, p3, p4, p5; numargs na) be //---------------------------------------------------------------------------- [ let t = p1; p1 = errNo; errNo = t (table [ 77403b; 1401b ])("Sys.Errors", lv p1) ] //---------------------------------------------------------------------------- and SpyCtx() be // a context //---------------------------------------------------------------------------- [ let host = GetString("*NIFS name: ", true); if host eq 0 loop unless GetPartner(host, dsp, port, 0, socketFTP) loop Free(sysZone, host) // oepn a BSP connection to the Ftp server Zero(CtxRunning+3, lenExtraCtx) let soc = vec lenBSPSoc CtxRunning>>FtpCtx.bspSoc = soc CtxRunning>>FtpCtx.dspStream = dsp OpenLevel1Socket(soc, 0, port) OpenRTPSocket(soc, 0, modeInitAndReturn) let timer = nil; SetTimer(lv timer, 6000) // 1 minute Block() repeatuntil soc>>RTPSoc.state ne stateRFCOut % (kbdAd!1 & 2) eq 0 % TimerHasExpired(lv timer) unless soc>>RTPSoc.state eq stateOpen do [ PutTemplate(dsp, "*NConnection attempt $S", TimerHasExpired(lv timer)? "timed out", "aborted") CloseRTPSocket(soc, 0) CloseLevel1Socket(soc) loop ] CtxRunning>>FtpCtx.bspStream = CreateBSPStream(soc) CtxRunning>>FtpCtx.lst = lv Noop - offset ST.puts/16 CtxRunning>>FtpCtx.dls = lv Noop - offset ST.puts/16 CtxRunning>>FtpCtx.dbls = CtxRunning>>FtpCtx.bspStream unless UserOpen(Noop) loop // retrieve the symbol table let ok = 0 //0 => in progress; 1 => unretryable; -1 => done until ok do [ if UserName>>String.length eq 0 % UserPassword>>String.length eq 0 then [ let unam = GetString("*NLogin user: ", true); unless unam break CopyString(UserName, unam); Free(sysZone, unam) let upsw = GetString("password: ", false); unless upsw break CopyString(UserPassword, upsw); Free(sysZone, upsw) ] let pList = InitPList() pList>>PL.UNAM = ExtractSubstring(UserName) pList>>PL.UPSW = ExtractSubstring(UserPassword) pList>>PL.SFIL = ExtractSubstring("<System>IFS.syms") let mark = UserRetrieve(pList, Retrieve) FreePList(pList) if mark<<Mark.mark eq markNo test (mark<<Mark.subCode eq 2 % mark<<Mark.subCode eq 20b % mark<<Mark.subCode eq 21b) ifso UserName!0, UserPassword!0 = 0, 0 ifnot break ok = mark eq 0? 1, mark<<Mark.mark eq markEndOfCommand ] UserClose(ok eq 1) unless ok eq -1 loop // SpyCtx (cont'd) // display table dt = Allocate(sysZone, lenDT); Zero(dt, lenDT) for line = 1 to maxLines do [ dt>>DT↑line.bitMap = Allocate(sysZone, lineWords) dt>>DT↑line.ds = CreateDisplayStream(1, dt>>DT↑line.bitMap, lineWords) ShowDisplayStream(dt>>DT↑line.ds) ] // VM stats display let showBitMap = Allocate(sysZone, 4*lineWords) show = CreateDisplayStream(4, showBitMap, 4*lineWords) SetLmarg(show, 120) let noshowBitMap = Allocate(sysZone, 4*lineWords) noshow = CreateDisplayStream(4, noshowBitMap, 4*lineWords) SetLmarg(noshow, 120) Spy() // Spy on server // destroy all display streams except dsp ShowDisplayStream(dsp, DSalone) for i = 0 to 30000 loop //give display task time to notice for line = 1 to maxLines do [ Free(sysZone, dt>>DT↑line.bitMap) Closes(dt>>DT↑line.ds) ] Free(sysZone, dt) Closes(show); Free(sysZone, showBitMap) Closes(noshow); Free(sysZone, noshowBitMap) for i = 0 to maxOvs-1 do if nt!i ne 0 then Free(sysZone, nt!i) Zero(nt, maxOvs) ] repeat //---------------------------------------------------------------------------- and Retrieve(pl) = RetrieveFile //---------------------------------------------------------------------------- //---------------------------------------------------------------------------- and RetrieveFile(pl) = valof //---------------------------------------------------------------------------- // Note that this procedure counts on the fact that the name string area // preceeds the BB file descriptor area in a Syms file. [ PutTemplate(dsp, "*NRetrieving $S...", pl>>PL.SFIL) let bspStream = CtxRunning>>FtpCtx.bspStream let pos = vec 1; Zero(pos, 2) // sym file header let sh = vec lSYmsHeader DoubleIncrement(pos, BSPReadBlock(bspStream, sh, 0, lSYmsHeader*2)) if (sh>>SYmsHeader.version & 177400b) ne 1000b resultis false // names let namePos = vec 1; namePos!0 = 0; namePos!1 = sh>>SYmsHeader.namesAddr*2 until MultEq(pos, namePos) do [ Gets(bspStream); DoubleIncrement(pos) ] let lenNameArea = Gets(bspStream) lshift 8 + Gets(bspStream) let nameArea = Allocate(sysZone, lenNameArea) for i = 1 to lenNameArea-1 do nameArea!i = Gets(bspStream) lshift 8 + Gets(bspStream) DoubleIncrement(pos, lenNameArea) DoubleIncrement(pos, lenNameArea) // BB file descriptors let bbPos = vec 1; bbPos!0 = 0; bbPos!1 = sh>>SYmsHeader.binFilesAddr*2 until MultEq(pos, bbPos) do [ Gets(bspStream); DoubleIncrement(pos) ] let numBBFD = Gets(bspStream) lshift 8 + Gets(bspStream) for numOvs = 0 to numBBFD-1 do [ if numOvs gr maxOvs then CallSwat("Increase maxOvs") let bbfd = vec lenBBFD DoubleIncrement(pos, BSPReadBlock(bspStream, bbfd, 0, lenBBFD*2)) let name = nameArea + bbfd>>BBFD.name nt!numOvs = ExtractSubstring(name, 1, name>>String.length-3) ] Free(sysZone, nameArea) until Gets(bspStream) eq -1 loop Wss(dsp, "Done!") resultis true ] //---------------------------------------------------------------------------- and GetString(prompt, echo) = valof //---------------------------------------------------------------------------- [ Wss(dsp, prompt) let string = vec 128 let count = 0 [ let char = Gets(keys) switchon char into [ case $*S: case $*N: case $*033: [ if count ne 0 then [ Puts(dsp, $*S); break ] endcase ] case $*001: case $*010: [ if count ne 0 then [ if echo then EraseBits(dsp, -CharWidth(dsp, string>>String.char↑count)) count = count -1 ] endcase ] case $*177: [ Wss(dsp, " XXX") count = 0 break ] default: [ if count ls (UserName!-1) lshift 1 -1 then [ count = count +1 string>>String.char↑count = char if echo then Puts(dsp, char) ] endcase ] ] ] repeat if count eq 0 resultis false string>>String.length = count resultis ExtractSubstring(string) ]