<> <> <> <> DIRECTORY BasicTime USING [Now], Commander USING [CommandProc, Register], GVBasics USING [RName], GVNames USING [ConnectInfo, GetConnect, GetMembers, MemberInfo], IO USING [Close, EndOfStream, Flush, GetChar, LF, PutChar, PutF, PutRope, STREAM], Process USING [Abort, Detach], Rope USING [ROPE], Pup USING [Address], PupName USING [Error, NameLookup], PupStream USING [ConsumeMark, Create, SendMark, StreamClosing, waitForever], PupWKS USING [telnet], ViewerIO USING [CreateViewerStreams]; GVWatcher: CEDAR PROGRAM IMPORTS BasicTime, Commander, GVNames, IO, Process, PupName, PupStream, ViewerIO = { MemberInfo: TYPE = GVNames.MemberInfo; serverScript: Rope.ROPE = "dtdsdpdhq\n"; serverList: Rope.ROPE = "gv.gv"; DoConnection: PROC [out: IO.STREAM, serverName: Rope.ROPE] = { addr: Pup.Address; serverStream: IO.STREAM _ NIL; setPageLength: [0..256) = 3; timingMark: [0..256) = 5; timingMarkReply: [0..256) = 6; UserToServer: PROC = { ENABLE ABORTED, PupStream.StreamClosing => CONTINUE; IO.PutRope[serverStream, serverScript]; IO.Flush[serverStream]; }; AcceptFromServer: PROC [serverStream: IO.STREAM] = { userToServer: PROCESS; TRUSTED { userToServer _ FORK UserToServer[]; }; DO BEGIN ENABLE BEGIN ABORTED, PupStream.StreamClosing => TRUSTED { Process.Abort[userToServer]; }; UNWIND => TRUSTED { JOIN userToServer; }; -- outside the Pup pkg monitor! IO.EndOfStream => GOTO Mark; END; c: CHAR = IO.GetChar[serverStream]; IF c # IO.LF THEN IO.PutChar[out, c]; EXITS Mark => BEGIN value: [0..256) = PupStream.ConsumeMark[serverStream]; IF value = timingMark THEN PupStream.SendMark[serverStream, timingMarkReply]; END; END; ENDLOOP; }; IO.PutF[out, "\n\n----------\n\nConnecting to %g ... ", [rope[serverName]] ]; BEGIN connect: Rope.ROPE; info: GVNames.ConnectInfo; [info, connect] _ GVNames.GetConnect[serverName]; SELECT info FROM allDown => { IO.PutRope[out, "no R-Server available"]; GOTO Failed; }; notFound, group => { IO.PutRope[out, "not an individual"]; GOTO Failed; }; individual => NULL; ENDCASE => ERROR; IO.PutF[out, "%g ... ", [rope[connect]]]; addr _ PupName.NameLookup[connect, PupWKS.telnet ! PupName.Error => BEGIN IO.PutF[out, "Can't find host name: %g.", [rope[text]]]; GOTO Failed; END]; addr.socket _ PupWKS.telnet; -- force socket number serverStream _ PupStream.Create[addr, PupStream.waitForever, PupStream.waitForever ! PupStream.StreamClosing => BEGIN IO.PutF[out, "Can't connect to host: %g.", [rope[text]]]; GOTO Failed; END]; IO.PutRope[out, "open."]; END; AcceptFromServer[serverStream ! PupStream.StreamClosing => BEGIN IO.PutF[out, "\nConnection closed by %g", [rope[serverName]] ]; IF text # NIL THEN out.PutF[": %g", [rope[text]] ]; CONTINUE END ]; IO.Close[serverStream]; EXITS Failed => NULL; }; <
> DoIt: Commander.CommandProc = { <<[cmd: Handle] RETURNS [result: REF _ NIL, msg: Rope.ROPE _ NIL]>> TRUSTED { Process.Detach[FORK ReallyDoit[]]; }; }; ReallyDoit: PROC = { out: IO.STREAM = ViewerIO.CreateViewerStreams["GV Statistics watcher"].out; info: MemberInfo = GVNames.GetMembers[serverList]; IO.PutF[ out, "\nGrapevine Statistics Watcher started at %g%l", [time[BasicTime.Now[]]], [rope["f"]] ]; SELECT info.type FROM allDown => IO.PutRope[out, "\nCan't expand server-list"]; notFound => IO.PutRope[out, "\nIncorrect server-list"]; individual => IO.PutRope[out, "\nIncorrect server-list"]; group => { group: group MemberInfo = NARROW[info, group MemberInfo]; FOR members: LIST OF Rope.ROPE _ group.members, members.rest UNTIL members = NIL DO DoConnection[out, members.first]; ENDLOOP; }; ENDCASE => ERROR; IO.PutRope[out, "\n\n-----\n"]; }; Commander.Register[key: "GVWatcher", proc: DoIt, doc: "Get statistics from Grapevine servers"]; }.