DIRECTORY Arpa, ArpaExtras, ArpaName, ArpaNameCache, ArpaNameSupport, ArpaNameLogSupport, ArpaNameQuery, BasicTime USING [GMT, Now, Period], Buttons USING [Button, ButtonProc, Create, Destroy, SetDisplayStyle], Commander USING [CommandProc, Register], Containers USING [ChildXBound, ChildYBound, Create], ConvertExtras USING [ArpaAddressFromRope, RopeFromArpaAddress], IO USING [Flush, PutF, PutRope, STREAM, Value], Labels USING [Create], Loader USING [BCDBuildTime], Rope USING [Cat, Equal, IsEmpty, ROPE], Rules USING [Create], TypeScript USING [ChangeLooks, Create], ViewerClasses USING [Viewer], ViewerIO USING [CreateViewerStreams], ViewerOps USING [AddProp, ComputeColumn, CreateViewer, MoveViewer, OpenIcon, SetOpenHeight], ViewerTools USING [GetContents, MakeNewTextViewer, SetContents, SetSelection]; ArpaNameCacheTool: CEDAR MONITOR IMPORTS ArpaExtras, ArpaName, ArpaNameCache, ArpaNameLogSupport, ArpaNameSupport, BasicTime, Buttons, Commander, Containers, ConvertExtras, IO, Labels, Loader, Rope, Rules, TypeScript, ViewerIO, ViewerOps, ViewerTools = BEGIN ROPE: TYPE = Rope.ROPE; STREAM: TYPE = IO.STREAM; Viewer: TYPE = ViewerClasses.Viewer; buttonHeight: INTEGER _ 0; buttonWidth: INTEGER _ 0; ClientData: TYPE = REF ClientDataRep; ClientDataRep: TYPE = RECORD [ log: STREAM _ NIL, in: STREAM _ NIL, key: Viewer, value: Viewer]; sequenceNumber: CARDINAL _ 0; NameEntry: TYPE = ArpaNameCache.NameEntry; AliasEntry: TYPE = ArpaNameCache.AliasEntry; MXEntry: TYPE = ArpaNameCache.MXEntry; BogusNameEntry: TYPE = ArpaNameCache.BogusNameEntry; DownNameEntry: TYPE = ArpaNameCache.DownNameEntry; AddressEntry: TYPE = ArpaNameCache.AddressEntry; BogusAddressEntry: TYPE = ArpaNameCache.BogusAddressEntry; DownAddressEntry: TYPE = ArpaNameCache.DownAddressEntry; DownServerEntry: TYPE = ArpaNameCache.DownServerEntry; ZoneEntry: TYPE = ArpaNameCache.ZoneEntry; SoaEntry: TYPE = ArpaNameCache.SoaEntry; Create: Commander.CommandProc = { CreateOne[]; }; CreateOne: PROC = { data: ClientData _ NEW[ClientDataRep _ []]; viewer, buttons, log: Viewer _ NIL; viewer _ ViewerOps.CreateViewer [ flavor: $Container, info: [name: "ArpaNameCacheTool", column: left, iconic: TRUE, scrollable: FALSE]]; ViewerOps.AddProp[viewer, $ArpaNameCacheTool, data]; { -- Kludge to find Button size temp: Buttons.Button = Buttons.Create[ info: [name: "Aliases:", parent: viewer, border: FALSE, wx: 0, wy: 0], proc: NIL, clientData: NIL, fork: FALSE, paint: FALSE]; buttonWidth _ temp.ww; buttonHeight _ temp.wh; Buttons.Destroy[temp]; }; log _ TypeScript.Create[ [name: "ArpaNameCacheTool.log", wy: 27+4, parent: viewer, border: FALSE], FALSE]; [data.in, data.log] _ ViewerIO.CreateViewerStreams [ name: "ArpaNameCacheTool.log", backingFile: "ArpaNameCacheTool.log", viewer: log, editedStream: FALSE]; Containers.ChildXBound[viewer, log]; Containers.ChildYBound[viewer, log]; CreateButtons[data, viewer, log]; TypeScript.ChangeLooks[log, 'f]; IO.PutF[data.log, "ArpaNameCache Tool of %G.\n", [time[Loader.BCDBuildTime[Create]]]]; IF FALSE THEN ViewerOps.OpenIcon[viewer]; }; CreateButtons: 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 _ data.key _ MakeLabeledText[ parent: kids, sibling: child, name: "Key:", data: "Xerox.COM", prev: data.key]; child _ data.value _ MakeLabeledText[ parent: kids, sibling: child, name: "Value:", data: "[a.b.c.d]", prev: data.value]; child _ MakeRule[kids, child]; child _ MakeLabel[kids, child, "Query:"]; child _ MakeButton[kids, child, data, "N=>A", N2A]; child _ MakeButton[kids, child, data, "N=>MX", N2MX]; child _ MakeButton[kids, child, data, "N=>N", N2N]; child _ MakeButton[kids, child, data, "N=>S", N2Servers]; child _ MakeButton[kids, child, data, "N=>I", N2Info]; child _ MakeButton[kids, child, data, "A=>N", A2N]; child _ MakeLabel[kids, child, "Cache:"]; child _ MakeButton[kids, child, data, "PrSlot", PrintSlot]; child _ MakeButton[kids, child, data, "PrOne", PrintOne]; child _ MakeButton[kids, child, data, "PrAll", Quick]; child _ MakeButton[kids, child, data, "ZapSlot", FlushEntry]; child _ MakeButton[kids, child, data, "ZapOne", FlushCache]; child _ MakeButton[kids, child, data, "ZapAll", Zap]; child _ MakeButton[kids, child, data, "AddV", AddV]; 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]; }; }; Zap: Buttons.ButtonProc = { data: ClientData _ NARROW[clientData]; log: IO.STREAM _ data.log; ArpaNameCache.FlushAll[]; IO.PutRope[log, "Zapped all name and server caches.\n\n"]; }; AddV: Buttons.ButtonProc = { data: ClientData _ NARROW[clientData]; log: IO.STREAM _ data.log; key: ROPE _ ViewerTools.GetContents[data.key]; value: ROPE _ ViewerTools.GetContents[data.value]; addr: Arpa.Address _ ConvertExtras.ArpaAddressFromRope[value]; addrList: LIST OF Arpa.Address _ LIST[addr]; IF Rope.IsEmpty[key] THEN RETURN; IF Rope.IsEmpty[value] THEN RETURN; IF addrList.first = Arpa.nullAddress THEN RETURN; [] _ ArpaNameCache.UpdateName[key, ArpaExtras.MyAddress[], 1333, FALSE, addrList]; IO.PutRope[log, key]; PrintListOfAddresses[log, " => ", addrList]; }; FlushCache: Buttons.ButtonProc = { data: ClientData _ NARROW[clientData]; log: IO.STREAM _ data.log; cacheRope: ROPE _ ViewerTools.GetContents[data.key]; cache: ArpaNameCache.CacheType; IF Rope.IsEmpty[cacheRope] THEN RETURN; SELECT TRUE FROM Rope.Equal[cacheRope, "name", FALSE] => cache _ name; Rope.Equal[cacheRope, "alias", FALSE] => cache _ alias; Rope.Equal[cacheRope, "mx", FALSE] => cache _ mx; Rope.Equal[cacheRope, "zone", FALSE] => cache _ zone; Rope.Equal[cacheRope, "soa", FALSE] => cache _ soa; Rope.Equal[cacheRope, "downName", FALSE] => cache _ downName; Rope.Equal[cacheRope, "bogusName", FALSE] => cache _ bogusName; Rope.Equal[cacheRope, "address", FALSE] => cache _ address; Rope.Equal[cacheRope, "downAddress", FALSE] => cache _ downAddress; Rope.Equal[cacheRope, "bogusAddress", FALSE] => cache _ bogusAddress; Rope.Equal[cacheRope, "downServer", FALSE] => cache _ downServer; ENDCASE; ArpaNameCache.FlushCache[cache]; IO.PutRope[log, "Zapped "]; IO.PutRope[log, cacheRope]; IO.PutRope[log, " cache.\n\n"]; }; FlushEntry: Buttons.ButtonProc = { data: ClientData _ NARROW[clientData]; log: IO.STREAM _ data.log; entry: ROPE _ ViewerTools.GetContents[data.key]; IF Rope.IsEmpty[entry] THEN RETURN; FOR cache: ArpaNameCache.CacheType IN [ArpaNameCache.CacheType.FIRST..ArpaNameCache.CacheType.LAST] DO ArpaNameCache.Delete[entry, cache]; ENDLOOP; IO.PutRope[log, "Zapped entry.\n\n"]; }; N2A: Buttons.ButtonProc = { data: ClientData _ NARROW[clientData]; log: IO.STREAM _ data.log; query: ROPE _ ViewerTools.GetContents[data.key]; addresses: LIST OF Arpa.Address; status: ArpaName.ReplyStatus; [addresses, status, ] _ ArpaName.NameToAddressList[query]; SELECT status FROM bogus => {IO.PutRope[log, Rope.Cat[query, " => bogus\n"]]; RETURN}; down => {IO.PutRope[log, Rope.Cat[query, " => down\n"]]; RETURN}; other => {IO.PutRope[log, Rope.Cat[query, " => other\n"]]; RETURN}; ENDCASE; IO.PutRope[log, query]; PrintListOfAddresses[log, " => ", addresses]; }; N2N: Buttons.ButtonProc = { data: ClientData _ NARROW[clientData]; log: IO.STREAM _ data.log; query: ROPE _ ViewerTools.GetContents[data.key]; name: ROPE; status: ArpaName.ReplyStatus; [name, status, ] _ ArpaName.AliasToName[query]; SELECT status FROM bogus => {IO.PutRope[log, Rope.Cat[query, " => bogus\n"]]; RETURN}; down => {IO.PutRope[log, Rope.Cat[query, " => down\n"]]; RETURN}; other => {IO.PutRope[log, Rope.Cat[query, " => other\n"]]; RETURN}; ENDCASE; IO.PutF[log, "%G => %G.\n", [rope[query]], [rope[name]]]; }; N2Servers: Buttons.ButtonProc = { data: ClientData _ NARROW[clientData]; log: IO.STREAM _ data.log; query: ROPE _ ViewerTools.GetContents[data.key]; status: ArpaName.ReplyStatus; servers: LIST OF ROPE; [servers, status, ] _ ArpaName.DomainServers[query]; SELECT status FROM bogus => {IO.PutRope[log, Rope.Cat[query, " => bogus\n"]]; RETURN}; down => {IO.PutRope[log, Rope.Cat[query, " => down\n"]]; RETURN}; other => {IO.PutRope[log, Rope.Cat[query, " => other\n"]]; RETURN}; ENDCASE; IO.PutF[log, "%G => ", [rope[query]]]; PrintListOfNames[log, "servers are: ", servers]; IO.PutRope[log, "\n"]; }; N2Info: Buttons.ButtonProc = { data: ClientData _ NARROW[clientData]; log: IO.STREAM _ data.log; query: ROPE _ ViewerTools.GetContents[data.key]; status: ArpaName.ReplyStatus; contact: ROPE; primaryServer: ROPE; [contact, primaryServer, status, ] _ ArpaName.DomainInfo[query]; SELECT status FROM bogus => {IO.PutRope[log, Rope.Cat[query, " => bogus\n"]]; RETURN}; down => {IO.PutRope[log, Rope.Cat[query, " => down\n"]]; RETURN}; other => {IO.PutRope[log, Rope.Cat[query, " => other\n"]]; RETURN}; ENDCASE; IO.PutF[log, "%G => ", [rope[query]]]; IO.PutF[log, " contact: %G, ", [rope[contact]]]; IO.PutF[log, " server: %G.\n", [rope[primaryServer]]]; IO.PutRope[log, "\n"]; }; N2MX: Buttons.ButtonProc = { data: ClientData _ NARROW[clientData]; log: IO.STREAM _ data.log; query: ROPE _ ViewerTools.GetContents[data.key]; status: ArpaName.ReplyStatus; mxEntry: ArpaNameCache.MXEntry _ NIL; Log: PROC [rope: ROPE] ~ { IO.PutRope[log, rope]; IO.Flush[log]}; status _ ArpaName.NameToMailHostList[query].status; SELECT status FROM bogus => {IO.PutRope[log, Rope.Cat[query, " => bogus\n"]]; RETURN}; down => {IO.PutRope[log, Rope.Cat[query, " => down\n"]]; RETURN}; other => {IO.PutRope[log, Rope.Cat[query, " => other\n"]]; RETURN}; ENDCASE; [,, mxEntry] _ ArpaNameCache.FetchMX[query]; IF mxEntry # NIL THEN ArpaNameLogSupport.MXSummaryLine[mxEntry, FALSE, TRUE, Log]; }; A2N: Buttons.ButtonProc = { data: ClientData _ NARROW[clientData]; log: IO.STREAM _ data.log; query: ROPE _ ViewerTools.GetContents[data.key]; where: LIST OF Arpa.Address _ ArpaName.NameToAddressList[query].addrs; name: Rope.ROPE; status: ArpaName.ReplyStatus; [where, status,] _ ArpaName.NameToAddressList[query]; SELECT status FROM bogus => {IO.PutRope[log, Rope.Cat[query, " => bogus\n"]]; RETURN}; down => {IO.PutRope[log, Rope.Cat[query, " => down\n"]]; RETURN}; other => {IO.PutRope[log, Rope.Cat[query, " => other\n"]]; RETURN}; ENDCASE; IF where = NIL THEN { IO.PutF[log, "\"Query\" needs to be a valid Address.\n"]; RETURN[]; }; name _ ArpaName.AddressToName[where.first].name; IO.PutF[log, "%G => %G.\n", [rope[ConvertExtras.RopeFromArpaAddress[where.first]]], [rope[name]]]; }; PrintOne: Buttons.ButtonProc = { ENABLE UNWIND => NULL; data: ClientData _ NARROW[clientData]; log: IO.STREAM _ data.log; cacheRope: ROPE _ ViewerTools.GetContents[data.key]; cache: ArpaNameCache.CacheType; SummaryEnum: ArpaNameCache.EnumerateProc = { WITH val SELECT FROM e: ArpaNameCache.NameEntry => ArpaNameLogSupport.NameSummaryLine[e, FALSE, TRUE, Log]; e: ArpaNameCache.AliasEntry => ArpaNameLogSupport.AliasSummaryLine[e, FALSE, TRUE, Log]; e: ArpaNameCache.AddressEntry => ArpaNameLogSupport.AddressSummaryLine[e, FALSE, TRUE, Log]; e: ArpaNameCache.MXEntry => ArpaNameLogSupport.MXSummaryLine[e, FALSE, TRUE, Log]; e: ArpaNameCache.ZoneEntry => ArpaNameLogSupport.ZoneSummaryLine[e, FALSE, TRUE, Log]; e: ArpaNameCache.SoaEntry => ArpaNameLogSupport.SoaSummaryLine[e, FALSE, TRUE, Log]; e: ArpaNameCache.BogusNameEntry => ArpaNameLogSupport.BogusNameSummaryLine[e, FALSE, TRUE, Log]; e: ArpaNameCache.BogusAddressEntry => ArpaNameLogSupport.BogusAddressSummaryLine[e, FALSE, TRUE, Log]; e: ArpaNameCache.DownNameEntry => ArpaNameLogSupport.DownNameSummaryLine[e, FALSE, TRUE, Log]; e: ArpaNameCache.DownAddressEntry => ArpaNameLogSupport.DownAddressSummaryLine[e, FALSE, TRUE, Log]; e: ArpaNameCache.DownServerEntry => ArpaNameLogSupport.DownServerSummaryLine[e, FALSE, TRUE, Log]; ENDCASE; }; Log: PROC [rope: ROPE] ~ { IO.PutRope[log, rope]; IO.Flush[log]}; IF Rope.IsEmpty[cacheRope] THEN RETURN; IO.PutRope[log, "\n"]; IO.PutRope[log, cacheRope]; IO.PutRope[log, " cache Summary:\n"]; SELECT TRUE FROM Rope.Equal[cacheRope, "name", FALSE] => cache _ name; Rope.Equal[cacheRope, "alias", FALSE] => cache _ alias; Rope.Equal[cacheRope, "mx", FALSE] => cache _ mx; Rope.Equal[cacheRope, "zone", FALSE] => cache _ zone; Rope.Equal[cacheRope, "soa", FALSE] => cache _ soa; Rope.Equal[cacheRope, "downName", FALSE] => cache _ downName; Rope.Equal[cacheRope, "bogusName", FALSE] => cache _ bogusName; Rope.Equal[cacheRope, "address", FALSE] => cache _ address; Rope.Equal[cacheRope, "downAddress", FALSE] => cache _ downAddress; Rope.Equal[cacheRope, "bogusAddress", FALSE] => cache _ bogusAddress; Rope.Equal[cacheRope, "downServer", FALSE] => cache _ downServer; ENDCASE; IF ArpaNameCache.CountCache[cache] = 0 THEN IO.PutRope[log, "empty."] ELSE { IO.PutRope[log, "\n"]; ArpaNameCache.EnumerateCache[cache, SummaryEnum]}; }; Quick: Buttons.ButtonProc = { ENABLE UNWIND => NULL; data: ClientData _ NARROW[clientData]; log: IO.STREAM _ data.log; SummaryEnum: ArpaNameCache.EnumerateProc = { WITH val SELECT FROM e: ArpaNameCache.NameEntry => ArpaNameLogSupport.NameSummaryLine[e, FALSE, TRUE, Log]; e: ArpaNameCache.AliasEntry => ArpaNameLogSupport.AliasSummaryLine[e, FALSE, TRUE, Log]; e: ArpaNameCache.AddressEntry => ArpaNameLogSupport.AddressSummaryLine[e, FALSE, TRUE, Log]; e: ArpaNameCache.MXEntry => ArpaNameLogSupport.MXSummaryLine[e, FALSE, TRUE, Log]; e: ArpaNameCache.ZoneEntry => ArpaNameLogSupport.ZoneSummaryLine[e, FALSE, TRUE, Log]; e: ArpaNameCache.SoaEntry => ArpaNameLogSupport.SoaSummaryLine[e, FALSE, TRUE, Log]; e: ArpaNameCache.BogusNameEntry => ArpaNameLogSupport.BogusNameSummaryLine[e, FALSE, TRUE, Log]; e: ArpaNameCache.BogusAddressEntry => ArpaNameLogSupport.BogusAddressSummaryLine[e, FALSE, TRUE, Log]; e: ArpaNameCache.DownNameEntry => ArpaNameLogSupport.DownNameSummaryLine[e, FALSE, TRUE, Log]; e: ArpaNameCache.DownAddressEntry => ArpaNameLogSupport.DownAddressSummaryLine[e, FALSE, TRUE, Log]; e: ArpaNameCache.DownServerEntry => ArpaNameLogSupport.DownServerSummaryLine[e, FALSE, TRUE, Log]; ENDCASE; }; Log: PROC [rope: ROPE] ~ { IO.PutRope[log, rope]; IO.Flush[log]}; IO.PutRope[log, "\nCache Summary:\n"]; IO.PutRope[log, "\nNames: "]; IF ArpaNameCache.CountCache[name] = 0 THEN IO.PutRope[log, "empty."] ELSE { IO.PutRope[log, "\n"]; ArpaNameCache.EnumerateCache[name, SummaryEnum]}; IO.PutRope[log, "\nAliases:"]; IF ArpaNameCache.CountCache[alias] = 0 THEN IO.PutRope[log, "empty."] ELSE { IO.PutRope[log, "\n"]; ArpaNameCache.EnumerateCache[alias, SummaryEnum]}; IO.PutRope[log, "\nMXs:"]; IF ArpaNameCache.CountCache[mx] = 0 THEN IO.PutRope[log, "empty."] ELSE { IO.PutRope[log, "\n"]; ArpaNameCache.EnumerateCache[mx, SummaryEnum]}; IO.PutRope[log, "\nZoneServers:"]; IF ArpaNameCache.CountCache[zone] = 0 THEN IO.PutRope[log, "empty."] ELSE { IO.PutRope[log, "\n"]; ArpaNameCache.EnumerateCache[zone, SummaryEnum]}; IO.PutRope[log, "\nZoneInfo:"]; IF ArpaNameCache.CountCache[soa] = 0 THEN IO.PutRope[log, "empty."] ELSE { IO.PutRope[log, "\n"]; ArpaNameCache.EnumerateCache[soa, SummaryEnum]}; IO.PutRope[log, "\nBogus Names:"]; IF ArpaNameCache.CountCache[bogusName] = 0 THEN IO.PutRope[log, "empty."] ELSE { IO.PutRope[log, "\n"]; ArpaNameCache.EnumerateCache[bogusName, SummaryEnum]}; IO.PutRope[log, "\nDown Names:"]; IF ArpaNameCache.CountCache[downName] = 0 THEN IO.PutRope[log, "empty."] ELSE { IO.PutRope[log, "\n"]; ArpaNameCache.EnumerateCache[downName, SummaryEnum]}; IO.PutRope[log, "\nAddresses:"]; IF ArpaNameCache.CountCache[address] = 0 THEN IO.PutRope[log, "empty."] ELSE { IO.PutRope[log, "\n"]; ArpaNameCache.EnumerateCache[address, SummaryEnum]}; IO.PutRope[log, "\nBogus Addresses:"]; IF ArpaNameCache.CountCache[bogusAddress] = 0 THEN IO.PutRope[log, "empty."] ELSE { IO.PutRope[log, "\n"]; ArpaNameCache.EnumerateCache[bogusAddress, SummaryEnum]}; IO.PutRope[log, "\nDown Addresses:"]; IF ArpaNameCache.CountCache[downAddress] = 0 THEN IO.PutRope[log, "empty."] ELSE { IO.PutRope[log, "\n"]; ArpaNameCache.EnumerateCache[downAddress, SummaryEnum]}; IO.PutRope[log, "\nDown Servers:"]; IF ArpaNameCache.CountCache[downServer] = 0 THEN IO.PutRope[log, "empty."] ELSE { IO.PutRope[log, "\n"]; ArpaNameCache.EnumerateCache[downServer, SummaryEnum]}; IO.PutRope[log, "\n\n"]; IO.Flush[log]; }; PrintSlot: Buttons.ButtonProc = { ENABLE UNWIND => NULL; this: NameEntry; alias: AliasEntry; mx: MXEntry; bogusName: BogusNameEntry; downName: DownNameEntry; zone: ZoneEntry; soa: SoaEntry; address: AddressEntry; downAddress: DownAddressEntry; bogusAddress: BogusAddressEntry; downServer: DownServerEntry; data: ClientData _ NARROW[clientData]; log: IO.STREAM _ data.log; found: BOOLEAN _ FALSE; query: ROPE _ ViewerTools.GetContents[data.key]; SELECT ArpaNameSupport.IsAddressRope[query] FROM FALSE => { this _ ArpaNameCache.FetchName[query].entry; alias _ ArpaNameCache.FetchAlias[query].entry; mx _ ArpaNameCache.FetchMX[query].entry; bogusName _ ArpaNameCache.FetchBogusName[query].entry; downName _ ArpaNameCache.FetchDownName[query].entry; zone _ ArpaNameCache.FetchZone[query].entry; soa _ ArpaNameCache.FetchSoa[query].entry; }; TRUE => { address _ ArpaNameCache.FetchAddressRope[query].entry; downAddress _ ArpaNameCache.FetchDownAddressRope[query].entry; bogusAddress _ ArpaNameCache.FetchBogusAddressRope[query].entry; downServer _ ArpaNameCache.FetchDownServerRope[query].entry; }; ENDCASE; IO.PutRope[log, "\n"]; IF this # NIL THEN { now: BasicTime.GMT _ BasicTime.Now[]; source: ROPE _ ArpaName.AddressToName[this.source].name; expires: INT _ BasicTime.Period[from: now, to: this.expires]; found _ TRUE; IO.PutF[log, "Name Loaded: %G, From: %G", [time[this.loaded]], [rope[source]]]; IF ~this.authoritative THEN IO.PutF[log, ", NOT Authoritative **"]; IO.PutRope[log, ".\n"]; IO.PutF[log, " Referenced: %G, Expires: %G, TTL: %G.\n", [time[this.referenced]], [integer[expires]],[integer[this.ttl]]]; IO.PutF[log, " Name: %G.\n", [rope[this.key]]]; PrintListOfAddresses[log, " Addresses: ", this.addresses]; IO.PutRope[log, "\n"];}; IF alias # NIL THEN { now: BasicTime.GMT _ BasicTime.Now[]; source: ROPE _ ArpaName.AddressToName[alias.source].name; expires: INT _ BasicTime.Period[from: now, to: alias.expires]; found _ TRUE; IO.PutF[log, "Alias Loaded: %G, From: %G", [time[alias.loaded]], [rope[source]]]; IF ~alias.authoritative THEN IO.PutF[log, ", NOT Authoritative **"]; IO.PutRope[log, ".\n"]; IO.PutF[log, " Referenced: %G, Expires: %G, TTL: %G.\n", [time[alias.referenced]], [integer[expires]], [integer[alias.ttl]]]; IO.PutF[log, " Alias: %G.\n", [rope[alias.key]]]; IO.PutF[log, " Canonical Name: %G.\n", [rope[alias.canonicalName]]]; IO.PutRope[log, "\n"];}; IF mx # NIL THEN { now: BasicTime.GMT _ BasicTime.Now[]; source: ROPE _ ArpaName.AddressToName[mx.source].name; expires: INT _ BasicTime.Period[from: now, to: mx.expires]; found _ TRUE; IO.PutF[log, "MX Loaded: %G, From: %G", [time[mx.loaded]], [rope[source]]]; IF ~mx.authoritative THEN IO.PutF[log, ", NOT Authoritative **"]; IO.PutRope[log, ".\n"]; IO.PutF[log, " Referenced: %G, Expires: %G, TTL: %G.\n", [time[mx.referenced]], [integer[expires]], [integer[mx.ttl]]]; IO.PutF[log, " Name: %G.\n", [rope[mx.key]]]; FOR list: LIST OF ArpaNameQuery.MailForwardRecord _ mx.mxList, list.rest UNTIL list = NIL DO IO.PutF[log, " MX Host: %G", [rope[list.first.host]]]; IO.PutF[log,", Preference: %G", [integer[list.first.preference]]]; IO.PutRope[log, "\n"]; ENDLOOP; IO.PutRope[log, "\n"]; }; IF bogusName # NIL THEN { now: BasicTime.GMT _ BasicTime.Now[]; source: ROPE _ ArpaName.AddressToName[bogusName.source].name; expires: INT _ BasicTime.Period[from: now, to: bogusName.expires]; found _ TRUE; IO.PutF[log, "Bogus Name Loaded: %G, From: %G", [time[bogusName.loaded]], [rope[source]]]; IF ~bogusName.authoritative THEN IO.PutF[log, ", NOT Authoritative **"]; IO.PutRope[log, ".\n"]; IO.PutF[log, " Referenced: %G, Expires: %G, TTL: %G.\n", [time[bogusName.referenced]], [integer[expires]], [integer[bogusName.ttl]]]; IO.PutF[log, " Bogus Name: %G.\n", [rope[bogusName.key]]]; IO.PutRope[log, "\n"];}; IF downName # NIL THEN { now: BasicTime.GMT _ BasicTime.Now[]; expires: INT _ BasicTime.Period[from: now, to: downName.expires]; found _ TRUE; IO.PutF[log, "Down Name Loaded: %G", [time[downName.loaded]]]; IO.PutRope[log, ".\n"]; IO.PutF[log, " Referenced: %G, Expires: %G, TTL: %G.\n", [time[downName.referenced]], [integer[expires]], [integer[downName.ttl]]]; IO.PutF[log, " Down Name: %G.\n", [rope[downName.key]]]; IO.PutRope[log, "\n"];}; IF zone # NIL THEN { now: BasicTime.GMT _ BasicTime.Now[]; source: ROPE _ ArpaName.AddressToName[zone.source].name; expires: INT _ BasicTime.Period[from: now, to: zone.expires]; found _ TRUE; IO.PutF[log, "Zone Loaded: %G, From: %G", [time[zone.loaded]], [rope[source]]]; IF ~zone.authoritative THEN IO.PutF[log, ", NOT Authoritative **"]; IO.PutRope[log, ".\n"]; IO.PutF[log, " Referenced: %G, Expires: %G, TTL: %G.\n", [time[zone.referenced]], [integer[expires]], [integer[zone.ttl]]]; IO.PutF[log, " Zone: %G.\n", [rope[zone.key]]]; PrintListOfNames[log, " Servers: ", zone.servers]; IO.PutRope[log, "\n"];}; IF soa # NIL THEN { now: BasicTime.GMT _ BasicTime.Now[]; source: ROPE _ ArpaName.AddressToName[soa.source].name; expires: INT _ BasicTime.Period[from: now, to: soa.expires]; found _ TRUE; IO.PutF[log, "Soa Loaded: %G, From: %G", [time[soa.loaded]], [rope[source]]]; IF ~soa.authoritative THEN IO.PutF[log, ", NOT Authoritative **"]; IO.PutRope[log, ".\n"]; IO.PutF[log, " Referenced: %G, Expires: %G, TTL: %G.\n", [time[soa.referenced]], [integer[expires]], [integer[soa.ttl]]]; IO.PutF[log, " Soa: %G.\n", [rope[soa.key]]]; IO.PutF[log, " Domain contact: %G.\n", [rope[soa.soaRef.domainContact]]]; IO.PutF[log, " Primary server: %G.\n", [rope[soa.soaRef.primaryServer]]]; IO.PutRope[log, "\n"];}; IF address # NIL THEN { now: BasicTime.GMT _ BasicTime.Now[]; source: ROPE _ ArpaName.AddressToName[address.source].name; expires: INT _ BasicTime.Period[from: now, to: address.expires]; found _ TRUE; IO.PutF[log, "Address Loaded: %G, From: %G", [time[address.loaded]], [rope[source]]]; IF ~address.authoritative THEN IO.PutF[log, ", NOT Authoritative **"]; IO.PutRope[log, ".\n"]; IO.PutF[log, " Referenced: %G, Expires: %G, TTL: %G.\n", [time[address.referenced]], [integer[expires]], [integer[address.ttl]]]; IO.PutF[log, " Address: %G.\n", [rope[address.key]]]; PrintListOfNames[log, " Name: ", address.names]; IO.PutRope[log, "\n"];}; IF downAddress # NIL THEN { now: BasicTime.GMT _ BasicTime.Now[]; source: ROPE _ ArpaName.AddressToName[downAddress.source].name; expires: INT _ BasicTime.Period[from: now, to: downAddress.expires]; found _ TRUE; IO.PutF[log, "Address Loaded: %G, From: %G", [time[downAddress.loaded]], [rope[source]]]; IF ~downAddress.authoritative THEN IO.PutF[log, ", NOT Authoritative **"]; IO.PutRope[log, ".\n"]; IO.PutF[log, " Referenced: %G, Expires: %G, TTL: %G.\n", [time[downAddress.referenced]], [integer[expires]], [integer[downAddress.ttl]]]; IO.PutF[log, " Down Address: %G.\n", [rope[downAddress.key]]]; IO.PutF[log, " Name: %G.\n", [rope[ArpaName.AddressRopeToName[downAddress.key].name]]]; IO.PutRope[log, "\n"];}; IF bogusAddress # NIL THEN { now: BasicTime.GMT _ BasicTime.Now[]; source: ROPE _ ArpaName.AddressToName[bogusAddress.source].name; expires: INT _ BasicTime.Period[from: now, to: bogusAddress.expires]; found _ TRUE; IO.PutF[log, "Address Loaded: %G, From: %G", [time[bogusAddress.loaded]], [rope[source]]]; IF ~bogusAddress.authoritative THEN IO.PutF[log, ", NOT Authoritative **"]; IO.PutRope[log, ".\n"]; IO.PutF[log, " Referenced: %G, Expires: %G, TTL: %G.\n", [time[bogusAddress.referenced]], [integer[expires]], [integer[bogusAddress.ttl]]]; IO.PutF[log, " Bogus Address: %G.\n", [rope[bogusAddress.key]]]; IO.PutRope[log, "\n"];}; IF downServer # NIL THEN { now: BasicTime.GMT _ BasicTime.Now[]; source: ROPE _ ArpaName.AddressToName[downServer.source].name; expires: INT _ BasicTime.Period[from: now, to: downServer.expires]; found _ TRUE; IO.PutF[log, "Address Loaded: %G, From: %G", [time[downServer.loaded]], [rope[source]]]; IF ~downServer.authoritative THEN IO.PutF[log, ", NOT Authoritative **"]; IO.PutRope[log, ".\n"]; IO.PutF[log, " Referenced: %G, Expires: %G, TTL: %G.\n", [time[downServer.referenced]], [integer[expires]], [integer[downServer.ttl]]]; IO.PutF[log, " Down Server: %G.\n", [rope[downServer.key]]]; IO.PutF[log, " Name: %G.\n", [rope[ArpaName.AddressRopeToName[downServer.key].name]]]; IO.PutRope[log, "\n"];}; IF ~found THEN IO.PutRope[log, "Entry not found.\n"]; IO.PutRope[log, "\n"]; IO.Flush[log]; }; Addrs: Buttons.ButtonProc = { ENABLE UNWIND => NULL; data: ClientData _ NARROW[clientData]; log: IO.STREAM _ data.log; IO.Flush[log]; }; Aliases: Buttons.ButtonProc = { ENABLE UNWIND => NULL; data: ClientData _ NARROW[clientData]; log: IO.STREAM _ data.log; IO.Flush[log]; }; MXs: Buttons.ButtonProc = { ENABLE UNWIND => NULL; data: ClientData _ NARROW[clientData]; log: IO.STREAM _ data.log; IO.Flush[log]; }; Bogus: Buttons.ButtonProc = { ENABLE UNWIND => NULL; data: ClientData _ NARROW[clientData]; log: IO.STREAM _ data.log; IO.Flush[log]; }; Down: Buttons.ButtonProc = { ENABLE UNWIND => NULL; data: ClientData _ NARROW[clientData]; log: IO.STREAM _ data.log; IO.Flush[log]; }; Names: Buttons.ButtonProc = { ENABLE UNWIND => NULL; data: ClientData _ NARROW[clientData]; log: IO.STREAM _ data.log; IO.Flush[log]; }; Zones: Buttons.ButtonProc = { ENABLE UNWIND => NULL; data: ClientData _ NARROW[clientData]; log: IO.STREAM _ data.log; IO.Flush[log]; }; ListLength: PROCEDURE [arg: REF ANY] RETURNS [length: INT _ 0] = TRUSTED { FOR list: LIST OF REF ANY _ LOOPHOLE[arg], list.rest UNTIL list = NIL DO length _ length + 1; ENDLOOP; }; PrintListOfRopes: PROC [log: IO.STREAM, header: ROPE, ropes: LIST OF ROPE] = { IO.PutRope[log, header]; FOR list: LIST OF ROPE _ ropes, list.rest UNTIL list = NIL DO IF list # ropes THEN IO.PutRope[log, ", "]; IO.PutF[log, "\"%G\"", [rope[list.first]]]; ENDLOOP; IO.PutRope[log, "\n"]; }; PrintListOfAddresses: PROC [log: IO.STREAM, header: ROPE, addresses: LIST OF Arpa.Address] = { IO.PutRope[log, header]; FOR list: LIST OF Arpa.Address _ addresses, list.rest UNTIL list = NIL DO IF list # addresses THEN IO.PutRope[log, ", "]; IO.PutRope[log, ConvertExtras.RopeFromArpaAddress[list.first]]; ENDLOOP; IO.PutRope[log, "\n"]; }; PrintListOfNames: PROC [log: IO.STREAM, header: ROPE _ NIL, names: LIST OF ROPE] = { IF header # NIL THEN IO.PutRope[log, header]; FOR list: LIST OF ROPE _ names, list.rest UNTIL list = NIL DO IF list # names THEN IO.PutRope[log, ", "]; IO.PutRope[log, list.first]; ENDLOOP; IO.PutRope[log, "\n"]; }; 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] RETURNS[child: Viewer] = { child _ Buttons.Create[ info: [name: name, parent: parent, border: TRUE, wy: sibling.wy, wx: sibling.wx + buttonWidth - 1, ww: buttonWidth], proc: proc, clientData: data, fork: TRUE, paint: FALSE]; }; 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 [parent, sibling: Viewer, clientData: REF _ NIL, name: ROPE, init: REF BOOL, change: BoolProc _ NIL, x, y: INTEGER _ 0] RETURNS [child: Viewer] = { bool: Bool _ NEW [BoolRec _ [ value: IF init # NIL THEN init ELSE NEW [BOOL _ TRUE], change: change, clientData: clientData, button: NIL ] ]; IF y = 0 THEN y _ sibling.wy + sibling.wh; IF x = 0 THEN x _ 2; 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], paint: FALSE ]; }; MakeLabeledText: PROC [ parent, sibling: Viewer, name, data: ROPE, prev: Viewer, newline: BOOL _ TRUE] RETURNS [child: Viewer] = { 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: 999, scrollable: TRUE, data: IF prev = NIL THEN data ELSE ViewerTools.GetContents[prev], border: FALSE, wx: x + buttonWidth + 2, wy: y], paint: FALSE ]; Containers.ChildXBound[parent, child]; [] _ 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["ArpaNameCacheTool", Create, "ArpaName Cache Tool."]; END. '@ArpaNameCacheTool.mesa John Larson, November 9, 1987 8:37:00 pm PST Viewer layout parameters child _ MakeButton[kids, child, data, "Names", Names]; child _ MakeButton[kids, child, data, "Addrs", Addrs]; child _ MakeButton[kids, child, data, "Aliases", Aliases]; child _ MakeButton[kids, child, data, "MXs", MXs]; child _ MakeButton[kids, child, data, "Bogus", Bogus]; child _ MakeButton[kids, child, data, "Down", Down]; child _ MakeButton[kids, child, data, "Zones", Zones]; 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 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 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 PROC [key: ROPE, val: Entry] RETURNS [quit: BOOL_FALSE] parent: REF, clientData: REF, mouseButton: MouseButton, shift, control: BOOL PROC [key: ROPE, val: Entry] RETURNS [quit: BOOL_FALSE] parent: REF, clientData: REF, mouseButton: MouseButton, shift, control: BOOL parent: REF, clientData: REF, mouseButton: MouseButton, shift, control: BOOL addresses: LIST OF AddressEntry = ArpaNameCache.GetAddresses[]; now: BasicTime.GMT _ BasicTime.Now[]; n: INT _ 0; FOR list: LIST OF AddressEntry _ addresses, list.rest UNTIL list = NIL DO this: AddressEntry _ list.first; source: ROPE _ ArpaName.AddressToName[this.source].addr; expires: INT _ BasicTime.Period[from: now, to: this.expires]; n _ n + 1; IO.PutF[log, "Address slot %G.\n", [integer[n]]]; IO.PutF[log, " Loaded: %G, From: %G", [time[this.loaded]], [rope[source]]]; IF ~this.authoritative THEN IO.PutF[log, ", NOT Authoritative **"]; IO.PutRope[log, ".\n"]; IO.PutF[log, " Referenced: %G, Expires: %G, TTL: %G.\n", [time[this.referenced]], [integer[expires]], [integer[this.ttl]]]; IO.PutF[log, " Address: %G.\n", [rope[ArpaName.AddressToRope[this.address]]]]; PrintListOfRopes[log, " Names: ", this.names]; IO.PutRope[log, "\n"]; ENDLOOP; parent: REF, clientData: REF, mouseButton: MouseButton, shift, control: BOOL aliases: LIST OF AliasEntry = ArpaNameCache.GetAliases[]; now: BasicTime.GMT _ BasicTime.Now[]; n: INT _ 0; FOR list: LIST OF AliasEntry _ aliases, list.rest UNTIL list = NIL DO this: AliasEntry _ list.first; source: ROPE _ ArpaName.AddressToName[this.source].addr; expires: INT _ BasicTime.Period[from: now, to: this.expires]; n _ n + 1; IO.PutF[log, "Alias slot %G.\n", [integer[n]]]; IO.PutF[log, " Loaded: %G, From: %G", [time[this.loaded]], [rope[source]]]; IF ~this.authoritative THEN IO.PutF[log, ", NOT Authoritative **"]; IO.PutRope[log, ".\n"]; IO.PutF[log, " Referenced: %G, Expires: %G, TTL: %G.\n", [time[this.referenced]], [integer[expires]], [integer[this.ttl]]]; IO.PutF[log, " Alias: %G.\n", [rope[this.alias]]]; IO.PutF[log, " Name: %G.\n", [rope[this.name]]]; IO.PutRope[log, "\n"]; ENDLOOP; parent: REF, clientData: REF, mouseButton: MouseButton, shift, control: BOOL mxList: LIST OF MXEntry = ArpaNameCache.GetMXList[]; now: BasicTime.GMT _ BasicTime.Now[]; n: INT _ 0; FOR list: LIST OF MXEntry _ mxList, list.rest UNTIL list = NIL DO mx: MXEntry _ list.first; source: ROPE _ ArpaName.AddressToName[mx.source].addr; expires: INT _ BasicTime.Period[from: now, to: mx.expires]; n _ n + 1; IO.PutF[log, "MX slot %G.\n", [integer[n]]]; IO.PutF[log, "Loaded: %G, From: %G", [time[mx.loaded]], [rope[source]]]; IF ~mx.authoritative THEN IO.PutF[log, ", NOT Authoritative **"]; IO.PutRope[log, ".\n"]; IO.PutF[log, " Referenced: %G, Expires: %G, TTL: %G.\n", [time[mx.referenced]], [integer[expires]], [integer[mx.ttl]]]; IO.PutF[log, " Name: %G.\n", [rope[mx.name]]]; FOR list: LIST OF ArpaNameCache.MXHostInfo _ mx.mxHosts, list.rest UNTIL list = NIL DO IO.PutF[log, " MX Host: %G", [rope[list.first.host]]]; IO.PutF[log, ", Preference: %G", [integer[list.first.preference]]]; IO.PutRope[log, "\n"]; ENDLOOP; IO.PutRope[log, "\n"]; ENDLOOP; parent: REF, clientData: REF, mouseButton: MouseButton, shift, control: BOOL bogusAddresses: LIST OF BogusAddressEntry = ArpaNameCache.GetBogusAddresses[]; bogusNames: LIST OF BogusNameEntry = ArpaNameCache.GetBogusNames[]; now: BasicTime.GMT _ BasicTime.Now[]; n: INT _ 0; FOR list: LIST OF BogusNameEntry _ bogusNames, list.rest UNTIL list = NIL DO this: BogusNameEntry _ list.first; source: ROPE _ ArpaName.AddressToName[this.source].addr; expires: INT _ BasicTime.Period[from: now, to: this.expires]; n _ n + 1; IO.PutF[log, "Bogus slot %G.\n", [integer[n]]]; IO.PutF[log, " Loaded: %G, From: %G", [time[this.loaded]], [rope[source]]]; IF ~this.authoritative THEN IO.PutF[log, ", NOT Authoritative **"]; IO.PutRope[log, ".\n"]; IO.PutF[log, " Referenced: %G, Expires: %G, TTL: %G.\n", [time[this.referenced]], [integer[expires]], [integer[this.ttl]]]; IO.PutF[log, " Name: %G.\n", [rope[this.bogus]]]; IO.PutRope[log, "\n"]; ENDLOOP; FOR list: LIST OF BogusAddressEntry _ bogusAddresses, list.rest UNTIL list = NIL DO this: BogusAddressEntry _ list.first; source: ROPE _ ArpaName.AddressToName[this.source].addr; expires: INT _ BasicTime.Period[from: now, to: this.expires]; n _ n + 1; IO.PutF[log, "Bogus slot %G.\n", [integer[n]]]; IO.PutF[log, " Loaded: %G, From: %G", [time[this.loaded]], [rope[source]]]; IF ~this.authoritative THEN IO.PutF[log, ", NOT Authoritative **"]; IO.PutRope[log, ".\n"]; IO.PutF[log, " Referenced: %G, Expires: %G, TTL: %G.\n", [time[this.referenced]], [integer[expires]], [integer[this.ttl]]]; IO.PutF[log, " Address: %G.\n", [rope[ArpaName.AddressToRope[this.bogus]]]]; IO.PutRope[log, "\n"]; ENDLOOP; parent: REF, clientData: REF, mouseButton: MouseButton, shift, control: BOOL downAddresses: LIST OF DownAddressEntry = ArpaNameCache.GetDownAddresses[]; downNames: LIST OF DownNameEntry = ArpaNameCache.GetDownNames[]; downServers: LIST OF DownServerEntry = ArpaNameCache.GetDownServers[]; now: BasicTime.GMT _ BasicTime.Now[]; n: INT _ 0; FOR list: LIST OF DownNameEntry _ downNames, list.rest UNTIL list = NIL DO this: DownNameEntry _ list.first; expires: INT _ BasicTime.Period[from: now, to: this.expires]; n _ n + 1; IO.PutF[log, "Down name slot %G.\n", [integer[n]]]; IO.PutF[log, " Loaded: %G", [time[this.loaded]]]; IO.PutRope[log, ".\n"]; IO.PutF[log, " Referenced: %G, Expires: %G, TTL: %G.\n", [time[this.referenced]], [integer[expires]], [integer[this.ttl]]]; IO.PutF[log, " Name: %G.\n", [rope[this.name]]]; IO.PutRope[log, "\n\n"]; ENDLOOP; n _ 0; FOR list: LIST OF DownAddressEntry _ downAddresses, list.rest UNTIL list = NIL DO this: DownAddressEntry _ list.first; expires: INT _ BasicTime.Period[from: now, to: this.expires]; n _ n + 1; IO.PutF[log, "Down address slot %G.\n", [integer[n]]]; IO.PutF[log, " Loaded: %G", [time[this.loaded]]]; IO.PutRope[log, ".\n"]; IO.PutF[log, " Referenced: %G, Expires: %G, TTL: %G.\n", [time[this.referenced]], [integer[expires]], [integer[this.ttl]]]; IO.PutF[log, " Address: %G.\n", [rope[ArpaName.AddressToRope[this.address]]]]; IO.PutRope[log, "\n\n"]; ENDLOOP; n _ 0; FOR list: LIST OF DownServerEntry _ downServers, list.rest UNTIL list = NIL DO this: DownServerEntry _ list.first; expires: INT _ BasicTime.Period[from: now, to: this.expires]; n _ n + 1; IO.PutF[log, "Down server slot %G.\n", [integer[n]]]; IO.PutF[log, " Loaded: %G", [time[this.loaded]]]; IO.PutRope[log, ".\n"]; IO.PutF[log, " Referenced: %G, Expires: %G, TTL: %G.\n", [time[this.referenced]], [integer[expires]], [integer[this.ttl]]]; IO.PutF[log, " Address: %G.\n", [rope[ArpaName.AddressToRope[this.address]]]]; IO.PutRope[log, "\n"]; ENDLOOP; parent: REF, clientData: REF, mouseButton: MouseButton, shift, control: BOOL names: LIST OF NameEntry = ArpaNameCache.GetNames[]; now: BasicTime.GMT _ BasicTime.Now[]; n: INT _ 0; FOR list: LIST OF NameEntry _ names, list.rest UNTIL list = NIL DO this: NameEntry _ list.first; source: ROPE _ ArpaName.AddressToName[this.source].addr; expires: INT _ BasicTime.Period[from: now, to: this.expires]; n _ n + 1; IO.PutF[log, "Name slot %G.\n", [integer[n]]]; IO.PutF[log, " Loaded: %G, From: %G", [time[this.loaded]], [rope[source]]]; IF ~this.authoritative THEN IO.PutF[log, ", NOT Authoritative **"]; IO.PutRope[log, ".\n"]; IO.PutF[log, " Referenced: %G, Expires: %G, TTL: %G.\n", [time[this.referenced]], [integer[expires]], [integer[this.ttl]]]; IO.PutF[log, " Name: %G.\n", [rope[this.name]]]; PrintListOfAddresses[log, " Addresses: ", this.addresses]; IO.PutRope[log, "\n"]; ENDLOOP; parent: REF, clientData: REF, mouseButton: MouseButton, shift, control: BOOL servers: LIST OF ZoneEntry = ArpaNameCache.GetZones[]; now: BasicTime.GMT _ BasicTime.Now[]; n: INT _ 0; FOR list: LIST OF ZoneEntry _ servers, list.rest UNTIL list = NIL DO this: ZoneEntry _ list.first; source: ROPE _ ArpaName.AddressToName[this.source].addr; expires: INT _ BasicTime.Period[from: now, to: this.expires]; n _ n + 1; IO.PutF[log, "Zone slot %G.\n", [integer[n]]]; IO.PutF[log, " Loaded: %G, From: %G", [time[this.loaded]], [rope[source]]]; IF ~this.authoritative THEN IO.PutF[log, ", NOT Authoritative **"]; IO.PutF[log, ".\n"]; IO.PutF[data.log, " Referenced: %G, Expires: %G, TTL: %G.\n", [time[this.referenced]], [integer[expires]], [integer[this.ttl]]]; IO.PutF[log, " Zone: %G\n", [rope[this.zone]]]; PrintListOfRopes[log, " Servers: ", this.servers]; IO.PutRope[log, "\n"]; ENDLOOP; parent: REF, clientData: REF, mouseButton: MouseButton, shift, control: BOOL parent: REF, clientData: REF, mouseButton: MouseButton, shift, control: BOOL Ê)˜šœ™Icode™,—J˜šÏk ˜ Jšœ˜Jšœ ˜ Jšœ ˜ Jšœ˜Jšœ˜Jšœ˜Jšœ˜Jšœ œœ˜#Jšœœ8˜EJšœ œ˜(Jšœ œ$˜4Jšœœ,˜?Jšœœœ ˜/Jšœœ ˜Jšœœ˜Jšœœ œ œ˜'Jšœœ ˜Jšœ œ˜'Jšœœ ˜Jšœ œ˜%Jšœ œM˜\šœ œ=˜NJ˜——šÏnœœ˜ š˜Jšœ‚œN˜Ô—Jš˜J˜Jšœœœ˜Jšœœœœ˜šœœ˜$J˜—™Jšœœ˜Jšœ œ˜J˜—Jšœ œœ˜%šœœœ˜Jšœœœ˜Jšœœœ˜Jšœ ˜ Jšœ˜J˜—šœœ˜J˜—Jšœ œ˜*Jšœ œ˜,Jšœ œ˜&Jšœœ ˜4Jšœœ˜2Jšœœ˜0Jšœœ#˜:Jšœœ"˜8Jšœœ!˜6Jšœ œ˜*šœ œ˜(J˜J˜—JšÐbnœ+˜1J˜šŸ œœ˜Jšœœ˜+Jšœœ˜#J˜šœ!˜!J˜Jšœ8œœ˜S—Jšœ4˜4J˜šœÏc˜˜&šœ1œ˜7J˜—Jš œœœœ œ˜7—J˜J˜Jšœ˜—šœ˜JšœBœœ˜Q—šœ4˜4Jšœ`œ˜gJ˜—Jšœ$˜$Jšœ$˜$Jšœ!˜!Jšœ ˜ JšœT˜VJšœœœ ˜-J˜—šž œœ+˜>Jšœœ˜šœ!˜!Jšœœœ'˜^—J˜%J˜šœ#˜#J˜ J˜J˜ Jšœ˜Jšœ˜J˜—šœ%˜%J˜ J˜J˜Jšœ˜Jšœ˜J˜—J˜J˜)Jšœ3˜3Jšœ5˜5Jšœ3˜3Jšœ9˜9Jšœ6˜6Jšœ3˜3J˜J˜)Jšœ;˜;Jšœ9˜9Jšœ6˜6J˜Jšœ6™6Jšœ6™6Jšœ:™:Jšœ2™2Jšœ6™6Jšœ4™4Jšœ6™6J™Jšœ=˜=Jšœ<˜JšœR˜R—J˜J˜—šŸœ˜JšœL™LJšœœ ˜&Jšœœœ ˜Jšœ˜Jšœ;˜=J˜—šžœ˜Jšœœœ,™LJšœœ ˜&Jšœœœ ˜Jšœœ%˜.Jšœœ'˜2Jšœ>˜>Jšœ œœœ˜,Jšœœœ˜!Jšœœœ˜#Jšœ#œœ˜1JšœAœ ˜RJšœ˜Jšœ/˜/J˜J˜J˜—šž œ˜#Jšœœœ,™LJšœœ ˜&Jšœœœ ˜Jšœ œ%˜4Jšœœ˜Jšœœœ˜'šœœ˜Jšœœ˜5Jšœœ˜7Jšœœ˜1Jšœœ˜5Jšœœ˜3Jšœ"œ˜=Jšœ#œ˜?Jšœ!œ˜;Jšœ%œ˜CJšœ&œ˜EJšœ$œ˜AJšœ˜—Jšœ ˜ Jšœ˜Jšœ˜Jšœ ˜"J˜J˜—šž œ˜#Jšœœœ,™LJšœœ ˜&Jšœœœ ˜Jšœœ%˜0Jšœœœ˜#š œ œœœ˜fJšœ#˜#Jšœ˜—Jšœ&˜(J˜J˜—šŸœ˜JšœL™LJšœœ ˜&Jšœœœ ˜Jšœœ%˜0Jšœ œœ˜ Jšœ˜Jšœ:˜:J˜šœ˜Kšœ œ/œ˜CKšœ œ.œ˜AKšœ œ/œ˜CKšœ˜K˜—Jšœ˜Jšœ0˜0J˜—šŸœ˜JšœL™LJšœœ ˜&Jšœœœ ˜Jšœœ%˜0Jšœœ˜ Jšœ˜Jšœ/˜/šœ˜Kšœ œ/œ˜CKšœ œ.œ˜AKšœ œ/œ˜CKšœ˜K˜—Jšœ:˜—Jšœ˜J˜˜J˜———šžœœœ˜Kšœ˜Kšœ ˜K˜—Jšœœœ˜'Jšœ˜Jšœ˜J˜Jšœ#˜%šœœ˜Jšœœ˜5Jšœœ˜7Jšœœ˜1Jšœœ˜5Jšœœ˜3Jšœ"œ˜=Jšœ#œ˜?Jšœ!œ˜;Jšœ%œ˜CJšœ&œ˜EJšœ$œ˜AJšœ˜—Jšœ%œœ˜Ešœ˜Jšœ˜Jšœ2˜2—J˜J˜J˜—šŸœ˜JšœL™LJšœœœ˜Jšœœ ˜&Jšœœœ ˜J˜šž œ!˜,Jš œœœœœ™7šœœ˜šœ˜Jšœ&œœ˜8—šœ˜Jšœ'œœ˜9—šœ!˜!Jšœ)œœ˜;—šœ˜Jšœ$œœ˜6—šœ˜Jšœ&œœ˜8—šœ˜Jšœ%œœ˜7—šœ#˜#Jšœ+œœ˜=—šœ%˜%Jšœ.œœ˜@—šœ"˜"Jšœ*œœ˜<—šœ%˜%Jšœ-œœ˜?—šœ$˜$Jšœ,œœ˜>—Jšœ˜J˜˜J˜———šžœœœ˜Kšœ˜Kšœ ˜K˜K˜—Jšœ$˜&J˜Jšœ˜Jšœ$œœ˜Dšœ˜Jšœ˜Jšœ1˜1—J˜Jšœ˜Jšœ%œœ˜Ešœ˜Jšœ˜Jšœ2˜2—J˜Jšœ˜Jšœ"œœ˜Bšœ˜Jšœ˜Jšœ/˜/—J˜Jšœ ˜"Jšœ$œœ˜Dšœ˜Jšœ˜Jšœ1˜1—J˜Jšœ˜Jšœ#œœ˜Cšœ˜Jšœ˜Jšœ0˜0—J˜Jšœ ˜"Jšœ)œœ˜Išœ˜Jšœ˜Jšœ6˜6—J˜Jšœ˜!Jšœ(œœ˜Hšœ˜Jšœ˜Jšœ5˜5—J˜Jšœ˜ Jšœ'œœ˜Gšœ˜Jšœ˜Jšœ4˜4—J˜Jšœ$˜&Jšœ,œœ˜Lšœ˜Jšœ˜Jšœ9˜9—J˜Jšœ#˜%Jšœ+œœ˜Kšœ˜Jšœ˜Jšœ8˜8—J˜Jšœ!˜#Jšœ*œœ˜Jšœ˜Jšœ˜Jšœ7˜7—J˜Jšœ˜Jšœ˜J˜J˜—šŸ œ˜!JšœL™LJšœœœ˜Jšœ˜Jšœ˜Jšœ ˜ Jšœ˜Jšœ˜Jšœ˜Jšœ˜Jšœ˜Jšœ˜Jšœ ˜ Jšœ˜Jšœœ ˜&Jšœœœ ˜Jšœœœ˜Jšœœ%˜0J˜šœ&˜0šœ˜ Jšœ,˜,Jšœ.˜.Jšœ(˜(Jšœ6˜6Jšœ4˜4Jšœ,˜,Jšœ*˜*Jšœ˜—šœ˜ Jšœ6˜6Jšœ?˜?Jšœ@˜@Jšœ<˜Jšœœ˜ JšœO˜QJšœœœ%˜DJšœ˜Jšœ|˜~Jšœ0˜2JšœC˜EJšœ˜J˜—šœœœ˜Jšœœ˜%Jšœœ*˜6Jšœ œ/˜;Jšœœ˜ JšœI˜KJšœœœ%˜AJšœ˜Jšœv˜xJšœ,˜.š œœœ8œœ˜\Jšœ6˜8Jšœ@˜BJšœ˜Jšœ˜—Jšœ˜J˜J˜—šœ œœ˜Jšœœ˜%Jšœœ1˜=Jšœ œ6˜BJšœœ˜ JšœX˜ZJšœœœ%˜HJšœ˜Jšœ„˜†Jšœ9˜;Jšœ˜J˜—šœ œœ˜Jšœœ˜%Jšœ œ5˜AJšœœ˜ Jšœ<˜>Jšœ˜Jšœ‚˜„Jšœ7˜9Jšœ˜J˜—J˜šœœœ˜Jšœœ˜%Jšœœ,˜8Jšœ œ1˜=Jšœœ˜ JšœM˜OJšœœœ%˜CJšœ˜Jšœz˜|Jšœ.˜0Jšœ4˜4Jšœ˜J˜J˜—šœœœ˜Jšœœ˜%Jšœœ+˜7Jšœ œ0˜Jšœ œ7˜CJšœœ˜ JšœV˜XJšœœœ%˜IJšœ˜Jšœ†˜ˆJšœ;˜=JšœU˜WJšœ˜J˜J˜—Jšœœœ$˜5Jšœ˜Jšœ˜J˜J˜—šŸœ˜JšœL™LJšœœœ˜Jšœœ ˜&Jšœœœ ˜J˜Jšœ œœ-™?Jšœœ™%Jšœœ™ J™š œœœ%œœ™IJšœ ™ Jšœœ,™8Jšœ œ1™=J™ Jšœ/™1JšœJ™LJšœœœ%™CJšœ™Jšœz™|JšœM™OJšœ/™/Jšœ™Jšœ™J™—Jšœ˜J˜—šŸœ˜JšœL™LJšœœœ˜Jšœœ ˜&Jšœœœ ˜J˜Jšœ œœ)™9Jšœœ™%Jšœœ™ š œœœ!œœ™EJšœ™Jšœœ,™8Jšœ œ1™=J™ Jšœ-™/JšœJ™LJšœœœ%™CJšœ™Jšœz™|Jšœ1™3Jšœ/™1Jšœ™Jšœ™J™—Jšœ˜J˜—šžœ˜JšœL™LJšœœœ˜Jšœœ ˜&Jšœœœ ˜Jšœœœ%™4Jšœœ™%J™Jšœœ™ š œœœœœ™AJšœ™Jšœœ*™6Jšœ œ/™;J™ Jšœ*™,JšœF™HJšœœœ%™AJšœ™Jšœv™xJšœ-™/š œœœ2œœ™VJšœ6™8JšœA™CJšœ™Jšœ™—Jšœ™Jšœ™J™—Jšœ˜J˜J˜—šŸœ˜JšœL™LJšœœœ˜Jšœœ ˜&Jšœœœ ˜J˜Jšœœœ7™NJšœ œœ0™CJšœœ™%Jšœœ™ š œœœ(œœ™LJšœ"™"Jšœœ,™8Jšœ œ1™=J™ Jšœ-™/JšœJ™LJšœœœ%™CJšœ™Jšœz™|Jšœ0™2Jšœ™Jšœ™J™—š œœœ/œœ™SJšœ%™%Jšœœ,™8Jšœ œ1™=J™ Jšœ-™/JšœJ™LJšœœœ%™CJšœ™Jšœz™|JšœK™MJšœ™Jšœ™J™—Jšœ˜J˜—šœŸœ˜JšœL™LJšœœœ˜Jšœœ ˜&Jšœœœ ˜Jšœœœ5™KJšœ œœ.™@Jšœ œœ2™FJ™Jšœœ™%Jšœœ™ š œœœ&œœ™JJšœ!™!Jšœ œ1™=J™ Jšœ1™3Jšœ0™2Jšœ™Jšœz™|Jšœ/™1Jšœ™Jšœ™J™J™—š œœœ-œœ™QJšœ$™$Jšœ œ1™=J™ Jšœ4™6Jšœ0™2Jšœ™Jšœz™|JšœM™OJšœ™Jšœ™J™—J™š œœœ*œœ™NJšœ#™#Jšœ œ1™=J™ Jšœ3™5Jšœ0™2Jšœ™Jšœz™|JšœM™OJšœ™Jšœ™J˜—šœ˜J˜——šŸœ˜JšœL™LJšœœœ˜Jšœœ ˜&Jšœœœ ˜J˜Jšœœœ&™4Jšœœ™%Jšœœ™ š œœœœœ™BJšœ™Jšœœ,™8Jšœ œ1™=J™ Jšœ,™.JšœJ™LJšœœœ%™CJšœ™Jšœz™|Jšœ/™1Jšœ;™;Jšœ™Jšœ™J™—Jšœ˜J˜—šŸœ˜JšœL™LJšœœœ˜Jšœœ ˜&Jšœœœ ˜J˜Jšœ œœ&™6Jšœœ™%Jšœœ™ š œœœ œœ™DJšœ™Jšœœ,™8Jšœ œ1™=J™ Jšœ,™.JšœJ™LJšœœœ%™CJšœ™Jšœ™Jšœ.™0Jšœ3™3Jšœ™Jšœ™J™—Jšœ˜J˜—šž œ œœœœ œœ˜Jšœœœœœœœœ˜HJšœ˜Jšœ˜ J˜——šžœœœœ œ œœœ˜NJšœ˜š œœœœœœ˜=Jšœœœ˜+Jšœ)˜+Jšœ˜—Jšœ˜J˜—šžœœœœ œ œœ˜^Jšœ˜š œœœ%œœ˜IJšœœœ˜/Jšœ=˜?Jšœ˜—Jšœ˜J˜—šžœœœœ œœ œœœ˜TJšœ œœœ˜-š œœœœœœ˜=Jšœœœ˜+Jšœ˜Jšœ˜—Jšœ˜J˜J˜—šžœœœ˜D˜šœœ˜%Jš œœ œœœ;˜[—Jšœœ˜—Jšœ)˜)J˜—š ž œœ!œœœœ˜z˜šœ+œ˜0J˜C—J˜ J˜Jšœœ˜ Jšœœ˜J˜——Jš œ œœœ œ˜EJšœœœ ˜šœ œœ˜Jšœœœ˜Jšœ˜Jšœ œ˜Jšœ˜J˜—šžœ˜Jšœ&œœœœœœœ˜wJšœ˜šœ œ ˜Jšœœœœœœœœ˜6J˜Jšœ˜Jšœœ˜—Jšœœ˜*Jšœœ˜šœ˜Jšœ+œ˜?Jšœ*œ œ˜=—Jšœ˜Jšœ œ2˜EJ˜—šŸ œ˜"JšœL™LJšœœ ˜&Jšœ œ ˜ Jšœ˜Jšœ œ4˜GJšœ5˜9Jšœœœ<˜UJ˜—šž œœ!œœ˜Q˜šœ+œ˜1Jšœœ œœ˜QJ˜—Jšœœ˜J˜——šžœœ˜Jš œ%œœœœ˜jJš œœœ œœ˜AJš œœœ œœ ˜I˜&šœ>œ˜CJš œœœœœ˜AJšœœ˜J˜ —Jšœœ˜—Jšœ&˜&˜Jšœ=œ˜RJšœ0œ œ˜E—Jšœ ˜J˜—šŸœ˜'JšœL™LJšœœ ˜"šœ ˜Jšœ&œ˜+Jšœ œ˜Jšœ(œ"œ˜TJšœœ˜——J˜šœH˜HJ˜—Jšœ˜J˜J˜J˜—J˜—…—vŒÆÒ