DIRECTORY Atom USING [GetPName], BasicTime USING [Now], Buttons USING [Button, ButtonProc, Create, SetDisplayStyle], Commander USING [CommandProc, Register], Containers USING [ChildXBound, ChildYBound, Create], Convert USING [RopeFromTime], IO USING [Close, Flush, PutF, PutFR, PutRope, STREAM], Labels USING [Create], Loader USING [BCDBuildTime], Process USING [MsecToTicks, Pause, priorityForeground, SetPriority, Ticks], PupHop USING [GetRouting, RoutingTableEntry, unreachable], PupName USING [HisName], Rope USING [Find, ROPE], Rules USING [Create], TypeScript USING [ChangeLooks, Create], VFonts USING [FontHeight, StringWidth], ViewerClasses USING [Viewer], ViewerEvents USING [EventProc, RegisterEventProc], ViewerIO USING [CreateViewerStreams], ViewerOps USING [AddProp, ComputeColumn, CreateViewer, FetchProp, MoveViewer, OpenIcon, SetOpenHeight], ViewerTools USING [GetContents, MakeNewTextViewer, SetContents, SetSelection]; PupNetWatcher: CEDAR MONITOR IMPORTS Atom, BasicTime, Buttons, Commander, Containers, Convert, IO, Labels, Loader, Process, PupHop, PupName, Rope, Rules, TypeScript, VFonts, ViewerEvents, ViewerIO, ViewerOps, ViewerTools = { BYTE: TYPE = [0..100H); ROPE: TYPE = Rope.ROPE; STREAM: TYPE = IO.STREAM; Viewer: TYPE = ViewerClasses.Viewer; buttonHeight: INT _ VFonts.FontHeight[] + 3; buttonWidth: INT _ VFonts.StringWidth["Route"] + 2*3; watcherLog: STREAM _ NIL; pleaseStopWatcher: BOOLEAN _ FALSE; watcher: PROCESS _ NIL; ClientData: TYPE = REF ClientDataRep; ClientDataRep: TYPE = RECORD [ log: STREAM _ NIL, in: STREAM _ NIL, pleaseStop: BOOLEAN _ FALSE ]; global: ClientData _ NIL; -- debugging Create: Commander.CommandProc = { viewer, buttons, log: Viewer _ NIL; data: ClientData _ NEW[ClientDataRep _ []]; global _ data; viewer _ ViewerOps.CreateViewer [ flavor: $Container, info: [name: "PupNetWatcher", column: right, iconic: TRUE, scrollable: FALSE]]; [] _ ViewerEvents.RegisterEventProc[Poof, destroy, viewer, TRUE]; ViewerOps.AddProp[viewer, $PupNetWatcher, data]; log _ TypeScript.Create[ [name: "PupNetWatcher.log", wy: 27+4, parent: viewer, border: FALSE], FALSE]; [data.in, data.log] _ ViewerIO.CreateViewerStreams [ name: "PupNetWatcher.log", backingFile: "///Temp/PupNetWatcher.log", viewer: log, editedStream: FALSE]; IF watcherLog = NIL THEN { watcherLog _ data.log; StartWatcher[]; }; Containers.ChildXBound[viewer, log]; Containers.ChildYBound[viewer, log]; CreateButtons[data, viewer, log]; TypeScript.ChangeLooks[log, 'f]; IO.PutF[data.log, "PupNetWatcher of %G.\n", [time[Loader.BCDBuildTime[Create]]]]; ViewerOps.OpenIcon[viewer]; }; CreateButtons: ENTRY PROC[data: ClientData, parent, log: Viewer] = { child: Viewer _ NIL; kids: Viewer = Containers.Create[ info: [parent: parent, border: FALSE, scrollable: FALSE, wx: 0, wy: -9999, ww: 9999, wh: 0] ]; Containers.ChildXBound[parent, kids]; child _ MakeRule[kids, child]; child _ MakeLabel[kids, child, "What: "]; child _ MakeButton[kids, child, data, "Route", RouteProc]; child _ MakeRule[kids, child]; { kidsY: INTEGER = 2; kidsH: INTEGER = child.wy + child.wh + 2; ViewerOps.MoveViewer[viewer: log, x: 0, y: kidsY + kidsH, w: log.ww, h: parent.ch - (kids.wy + kidsH), paint: FALSE]; ViewerOps.SetOpenHeight[parent, kidsY + kidsH + 12 * buttonHeight]; IF ~parent.iconic THEN ViewerOps.ComputeColumn[parent.column]; ViewerOps.MoveViewer[viewer: kids, x: kids.wx, y: kidsY, w: kids.ww, h: kidsH]; }; }; Poof: ViewerEvents.EventProc = { data: ClientData _ NARROW[ViewerOps.FetchProp[viewer, $PupNetWatcher]]; IF event # destroy OR before # TRUE THEN ERROR; IF data.log = watcherLog THEN { StopWatcher[]; watcherLog _ NIL; }; IO.Close[data.log]; IO.Close[data.in]; }; StartWatcher: ENTRY PROC = { IF watcher # NIL THEN RETURN; pleaseStopWatcher _ FALSE; watcher _ FORK Watcher[]; }; StopWatcher: ENTRY PROC = { IF watcher = NIL THEN RETURN; pleaseStopWatcher _ TRUE; IF watcher # NIL THEN TRUSTED { JOIN watcher; watcher _ NIL; }; }; Watcher: PROC = { oneSecond: Process.Ticks = Process.MsecToTicks[1000]; old: ARRAY [0..256) OF PupHop.RoutingTableEntry; Process.SetPriority[Process.priorityForeground]; FOR n: NAT IN [0..256) DO old[n] _ PupHop.GetRouting[[n]]; old[n].time _ 0; ENDLOOP; UNTIL pleaseStopWatcher DO FOR n: NAT IN [0..256) DO temp: PupHop.RoutingTableEntry _ PupHop.GetRouting[[n]]; temp.time _ 0; IF temp # old[n] THEN { netName: ROPE _ PupName.HisName[[[n],[0],[0,0,0,0]]]; IF Rope.Find[netName, "#"] = -1 THEN netName _ IO.PutFR["%G (%B##)", [rope[netName]], [integer[n]] ]; IO.PutRope[watcherLog, Convert.RopeFromTime[ BasicTime.Now[], hours, seconds, FALSE, FALSE, FALSE]]; IF temp.hop = PupHop.unreachable THEN IO.PutF[watcherLog, " Net %G is unreachable.\n", [rope[netName]] ] ELSE IO.PutF[watcherLog, " Net %G is %G hops via %G.\n", [rope[netName]], [integer[temp.hop]], [rope[PupName.HisName[temp.immediate]]] ]; IO.Flush[watcherLog]; }; old[n] _ temp; ENDLOOP; FOR i: NAT IN [0..30) UNTIL pleaseStopWatcher DO Process.Pause[oneSecond]; ENDLOOP; ENDLOOP; }; RouteProc: Buttons.ButtonProc = { data: ClientData _ NARROW[clientData]; Route[data]; }; Route: PROC [data: ClientData] = { PrintOne: PROC [net: BYTE] = { rte: PupHop.RoutingTableEntry _ PupHop.GetRouting[[net]]; IF rte.hop = PupHop.unreachable THEN RETURN; nets _ nets + 1; IF k = 0 THEN IO.PutF[data.log, "|"]; IO.PutF[data.log, "%3B%4B#%3B#%4D |", [integer[net]], [integer[rte.immediate.net]], [integer[rte.immediate.host]], [integer[rte.hop]] ]; IF (k _ k + 1) = 3 THEN { IO.PutF[data.log, "\n"]; k _ 0; }; }; k, nets: INT _ 0; IO.PutF[data.log, "\n Local Pup Routing Table.\n"]; IO.PutF[data.log, "| Net Via Hops | Net Via Hops | Net Via Hops |\n"]; IO.PutF[data.log, "|-----------------|-----------------|-----------------|\n"]; FOR net: BYTE IN BYTE DO PrintOne[net]; ENDLOOP; IF k # 0 THEN IO.PutF[data.log, "\n"]; IF nets > 1 THEN IO.PutF[data.log, "There are %D active networks.\n", [integer[nets]]]; }; MakeRule: PROC [parent, sibling: Viewer] RETURNS [child: Viewer] = { child _ Rules.Create[ info: [parent: parent, border: FALSE, wy: IF sibling = NIL THEN 0 ELSE sibling.wy + sibling.wh + 2, wx: 0, ww: parent.ww, wh: 1], paint: FALSE ]; Containers.ChildXBound[parent, child]; }; MakeButton: PROC [parent, sibling: Viewer, data: REF ANY, name: ROPE, proc: Buttons.ButtonProc, guarded: BOOL _ FALSE] RETURNS[child: Viewer] = { child _ Buttons.Create[ info: [name: name, parent: parent, border: TRUE, wy: sibling.wy, wx: sibling.wx + sibling.ww - 1, ww: buttonWidth], proc: proc, clientData: data, fork: TRUE, guarded: guarded, paint: FALSE]; }; SelectorProc: TYPE = PROC [parent: Viewer, clientData: REF, value: ATOM]; Selector: TYPE = REF SelectorRec; SelectorRec: TYPE = RECORD [ value: REF ATOM, change: PROC [parent: Viewer, clientData: REF, value: ATOM], clientData: REF, buttons: LIST OF Buttons.Button, values: LIST OF ATOM ]; MakeSelector: PROC [name: ROPE, values: LIST OF ATOM, init: REF ATOM _ NIL, change: SelectorProc _ NIL, clientData: REF _ NIL, parent: Viewer, x, y: INTEGER] RETURNS [child: Viewer] = { selector: Selector _ NEW [SelectorRec _ [ value: IF init # NIL THEN init ELSE NEW [ATOM _ values.first], change: change, clientData: clientData, buttons: NIL, values: values ] ]; last: LIST OF Buttons.Button _ NIL; child _ Labels.Create[info: [name: name, parent: parent, border: FALSE, wx: x, wy: y] ]; FOR a: LIST OF ATOM _ values, a.rest UNTIL a = NIL DO child _ Buttons.Create[ info: [name: Atom.GetPName[a.first], parent: parent, border: TRUE, wx: child.wx + child.ww + 2, wy: child.wy], proc: SelectorHelper, clientData: selector, fork: TRUE, paint: TRUE]; IF last = NIL THEN last _ selector.buttons _ CONS[first: child, rest: NIL] ELSE { last.rest _ CONS[first: child, rest: NIL]; last _ last.rest }; IF a.first = selector.value^ THEN Buttons.SetDisplayStyle[child, $WhiteOnBlack]; ENDLOOP; }; SelectorHelper: Buttons.ButtonProc = { self: Buttons.Button = NARROW[parent]; selector: Selector = NARROW[clientData]; buttons: LIST OF Buttons.Button _ selector.buttons; FOR a: LIST OF ATOM _ selector.values, a.rest UNTIL a = NIL DO IF self = buttons.first THEN { selector.value^ _ a.first; IF selector.change # NIL THEN selector.change[self.parent, selector.clientData, a.first]; Buttons.SetDisplayStyle[buttons.first, $WhiteOnBlack]; } ELSE Buttons.SetDisplayStyle[buttons.first, $BlackOnWhite]; buttons _ buttons.rest; ENDLOOP; }; BoolProc: TYPE = PROC [parent: Viewer, clientData: REF, value: BOOL]; Bool: TYPE = REF BoolRec; BoolRec: TYPE = RECORD [ value: REF BOOL, change: BoolProc, clientData: REF, button: Viewer ]; MakeBool: PROC [name: ROPE, init: REF BOOL, change: BoolProc _ NIL, clientData: REF _ NIL, parent: Viewer, x, y: INTEGER] RETURNS [child: Viewer] = { bool: Bool _ NEW [BoolRec _ [ value: IF init # NIL THEN init ELSE NEW [BOOL _ TRUE], change: change, clientData: clientData, button: NIL ] ]; child _ Buttons.Create[ info: [name: name, parent: parent, border: TRUE, wx: x, wy: y], proc: BoolHelper, clientData: bool, fork: TRUE, paint: TRUE]; bool.button _ child; IF bool.value^ THEN Buttons.SetDisplayStyle[child, $WhiteOnBlack]; }; BoolHelper: Buttons.ButtonProc = { self: Buttons.Button = NARROW[parent]; bool: Bool = NARROW[clientData]; bool.value^ _ ~bool.value^; IF bool.value^ THEN Buttons.SetDisplayStyle[bool.button, $WhiteOnBlack] ELSE Buttons.SetDisplayStyle[bool.button, $BlackOnWhite]; IF bool.change # NIL THEN bool.change[self.parent, bool.clientData, bool.value^]; }; MakeLabel: PROC [parent, sibling: Viewer, name: ROPE] RETURNS [child: Viewer] = { child _ Labels.Create[ info: [name: name, parent: parent, border: FALSE, wy: sibling.wy + sibling.wh + (IF sibling.class.flavor = $Button THEN -1 ELSE 2), wx: 2, ww: VFonts.StringWidth[name] + 2*3 + 2], paint: FALSE ]; }; MakeLabeledText: PROC [ parent, sibling: Viewer, name, data: ROPE, prev: Viewer, width: INT, newline: BOOL _ TRUE] RETURNS [child: Viewer] = { buttonWidth: INT _ VFonts.StringWidth[name] + 2*3; x: INTEGER = IF newline THEN 2 ELSE sibling.wx + sibling.ww + 10; y: INTEGER = IF newline THEN sibling.wy + sibling.wh + 1 ELSE sibling.wy; child _ ViewerTools.MakeNewTextViewer[ info: [ parent: parent, wh: buttonHeight, ww: width+10, data: IF prev = NIL THEN data ELSE ViewerTools.GetContents[prev], border: FALSE, wx: x + buttonWidth + 2, wy: y, scrollable: FALSE ], paint: FALSE ]; [] _ Buttons.Create[ info: [name: name, parent: parent, wh: buttonHeight, border: FALSE, wx: x, wy: y], proc: LabeledTextProc, clientData: child, fork: FALSE, paint: FALSE]; RETURN[child]; }; LabeledTextProc: Buttons.ButtonProc = { text: Viewer = NARROW[clientData]; SELECT mouseButton FROM red => ViewerTools.SetSelection[text, NIL]; yellow => NULL; blue => { ViewerTools.SetContents[text, NIL]; ViewerTools.SetSelection[text, NIL] }; ENDCASE => ERROR; }; Commander.Register["PupNetWatcher", Create, "Watch Pup Routing table."]; }. ~PupNetWatcher.mesa Copyright c 1985, 1986 by Xerox Corporation. All rights reserved. Hal Murray, December 20, 1986 9:22:04 pm PST Viewer layout parameters Server data (global) Note: This server goes in on top of the builtin one [viewer: ViewerClasses.Viewer, event: ViewerEvent, before: BOOL] RETURNS[abort: BOOL _ FALSE] parent: REF, clientData: REF, mouseButton: MouseButton, shift, control: BOOL parent: REF, clientData: REF, mouseButton: MouseButton, shift, control: BOOL parent: REF, clientData: REF, mouseButton: MouseButton, shift, control: BOOL parent: REF, clientData: REF, mouseButton: MouseButton, shift, control: BOOL Κ ˜šœ™Icodešœ Οmœ7™BK™,—J˜šΟk ˜ Jšœžœ ˜Jšœ žœ˜Jšœžœ/˜˜KJšœžœ.˜:Jšœžœ ˜Jšœžœžœ˜Jšœžœ ˜Jšœ žœ˜'Jšœžœ˜'Jšœžœ ˜Jšœ žœ ˜2Jšœ žœ˜%Jšœ žœX˜gJšœ žœ=˜NJ˜—šœžœž˜šž˜Jšœ:žœ˜»—J˜Jšžœžœ ˜J˜Jšžœžœžœ˜Jšžœžœžœžœ˜Jšœžœ˜%™Jšœžœ˜,Jšœ žœ%˜5—J˜J™™3Jšœ žœžœ˜Jšœžœžœ˜#Jšœ žœžœ˜—J˜Jšœ žœžœ˜%šœžœžœ˜Jšœžœžœ˜Jšœžœžœ˜Jšœ žœžœ˜—J˜JšœžœΟc ˜'šΟbœ˜!Jšœžœ˜#Jšœžœ˜+J˜šœ!˜!J˜Jšœ5žœžœ˜P—Jšœ;žœ˜AJšœ0˜0šœ˜Jšœ>žœžœ˜M—šœ4˜4Jšœ`žœ˜g—Jšžœžœžœ,˜DJšœ$˜$Jšœ$˜$Jšœ!˜!Jšœ ˜ JšžœO˜QJšœ˜J˜—šΟn œžœžœ+˜DJšœžœ˜šœ!˜!Jšœžœžœ'˜^—J˜%J˜J˜)Jšœ:˜:J˜šœ˜Jšœžœ˜Jšœžœ˜)Kšœnžœ˜uJ˜CJšžœžœ(˜>JšœR˜R—J˜—š œ˜ Jšœ;žœ™@Jšžœžœžœ™Jšœžœ.˜GJš žœžœ žœžœžœ˜/Jšžœžœžœ˜CJšžœ˜Jšžœ˜J˜J˜—š‘ œžœžœ˜Jšžœ žœžœžœ˜Jšœžœ˜Jšœ žœ ˜Jšœ˜J˜—š‘ œžœžœ˜Jšžœ žœžœžœ˜Jšœžœ˜Jš žœ žœžœžœžœžœ˜?Jšœ˜J˜—š‘œžœ˜Jšœ5˜5Jšœžœ žœ˜0Jšœ0˜0šžœžœžœ ž˜Jšœ ˜ J˜Jšžœ˜—šžœž˜šžœžœžœ ž˜Jšœ8˜8J˜šžœžœ˜Jšœ žœ(˜5šžœž˜$Jšœ žœ4˜@—šžœ*˜,Jšœ!žœžœžœ˜7—šžœ ž˜&JšžœA˜C—šžœžœ2˜9JšœP˜P—Jšžœ˜—Jšœ˜Jšžœ˜—š žœžœžœ žœž˜0Jšœ˜Jšžœ˜—Jšžœ˜—Jšœ˜J˜—š  œ˜!JšœL™LJšœžœ ˜&Jšœ˜J˜—š‘œžœ˜"š‘œžœžœ˜Jšœ9˜9Jšžœžœžœ˜,Jšœ˜Jšžœžœžœ˜%Jšžœ†˜ˆJšžœžœžœ#˜?—Jšœ žœ˜Jšžœ2˜4JšžœM˜OJšžœM˜Oš žœžœžœžœž˜Jšœ˜Jšžœ˜—Jšžœžœžœ˜&Jšžœ žœžœD˜WJšœ˜—J˜š‘œžœžœ˜D˜šœžœ˜%Jš œžœ žœžœžœ;˜[—Jšœžœ˜—Jšœ&˜&Jšœ˜J˜—š‘ œžœ!žœžœžœ%žœžœžœ˜‘˜šœ+žœ˜0J˜B—J˜ J˜Jšœžœ˜ Jšœ˜Jšœžœ˜—Jšœ˜J˜—Jš ‘ œžœžœžœ žœ˜IJšœ žœžœ ˜!šœ žœžœ˜Jšœžœžœ˜Jšœžœžœ žœ˜J˜J˜Jšœ žœ˜ J˜—Jšœžœžœžœ˜#JšœAžœ˜Xš žœžœžœžœžœžœž˜5šœ˜Kšœ=žœ-˜nJšœ2žœ žœ˜E—Jš žœžœžœžœžœ˜JJšžœžœžœ˜EJšžœžœ/˜PJšžœ˜ ——J˜š œ˜&JšœL™LJšœžœ ˜&Jšœžœ ˜(Jšœ žœžœ#˜3š žœžœžœžœžœžœž˜>šžœžœ˜J˜Jšžœžœžœ<˜YJšœ8˜8—Jšžœ7˜;J˜Jšžœ˜ ——J˜Jš ‘œžœžœžœ žœ˜EJšœžœžœ ˜šœ žœžœ˜Jšœžœžœ˜Jšœ˜Jšœ žœ˜Jšœ˜—J˜š‘œž˜Kšœžœžœžœžœžœžœžœ˜jKšžœ˜šœ žœ ˜Jšœžœžœžœžœžœžœžœ˜6J˜Jšœ˜Jšœžœ˜—šœ˜Kšœ+žœ˜?Jšœ*žœ žœ˜=—Jšœ˜Jšžœ žœ2˜E—J˜š  œ˜"JšœL™LJšœžœ ˜&Jšœ žœ ˜ Jšœ˜Jšžœ žœ4˜GJšžœ5˜9Jšžœžœžœ<˜U—š‘ œžœ!žœžœ˜Q˜šœ+žœ˜1Jšœžœ žœžœ˜QJ˜Jšœ(˜(—Jšœžœ˜——J˜š‘œžœ˜Jš œ%žœžœ žœžœžœ˜vJšœ žœ"˜2Jš œžœžœ žœžœ˜AJš œžœžœ žœžœ ˜I˜&šœ˜Jšœ/˜/Jš œžœžœžœžœ˜AJšœžœ˜J˜Jšœ žœ˜—Jšœžœ˜—˜Jšœ=žœ˜RJšœ0žœ žœ˜E—Jšžœ ˜J˜—š œ˜'JšœL™LJšœžœ ˜"šžœ ž˜Jšœ&žœ˜+Jšœ žœ˜Jšœ(žœ"žœ˜TJšžœžœ˜——J˜šœH˜HJ˜—Jšœ˜J˜J˜J˜——…—*’: