DIRECTORY Arpa, ArpaNameBuf USING [domainPort, Port], ArpaName USING [AddressToName, AliasToName, MyName, NameToAddress, ReplyStatus], ArpaNameSupport USING [IsAddressRope], ArpaNameQuery USING [ARR, NsRR, CNameRR, PtrRR, MbRR, MgRR, MrRR, MdRR, MfRR, SoaRR, WksRR, HinfoRR, MinfoRR, MxRR, Error, Protocol, QClass, QType, Query, QuestionRecord, RRClass, RRType, Reply, ResourceRecord, Seconds], ArpaUDP USING [Milliseconds], Atom USING [GetPName], Buttons USING [Button, ButtonProc, Create, Destroy, SetDisplayStyle], Commander USING [CommandProc, Register], Containers USING [ChildXBound, ChildYBound, Create], Convert USING [CardFromRope], ConvertExtras USING [RopeFromArpaAddress], IO USING [Flush, PutF, PutFR, PutRope, STREAM, Value], Labels USING [Create], Loader USING [BCDBuildTime], Rope USING [ROPE, IsEmpty], 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]; ArpaNameTool: CEDAR MONITOR IMPORTS ArpaName, ArpaNameSupport, ArpaNameQuery, Atom, Buttons, Commander, Containers, Convert, 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, class: ArpaNameQuery.QClass _ in, protocol: ArpaNameQuery.Protocol _ udpOnly, recursionDesired: BOOL _ FALSE, showErr: BOOL _ TRUE, target, timeout, query: Viewer _ NIL ]; sequenceNumber: CARDINAL _ 0; defaultDomainServer: ROPE _ "Arisia"; Create: Commander.CommandProc = TRUSTED { data: ClientData _ NEW[ClientDataRep _ []]; viewer, buttons, log: Viewer _ NIL; viewer _ ViewerOps.CreateViewer [ flavor: $Container, info: [name: "ArpaNameTool", column: right, iconic: TRUE, scrollable: FALSE]]; ViewerOps.AddProp[viewer, $ArpaNameTool, data]; { -- Kludge to find Button size temp: Buttons.Button = Buttons.Create[ info: [name: "Length:", 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: "ArpaNameTool.log", wy: 27+4, parent: viewer, border: FALSE], FALSE]; [data.in, data.log] _ ViewerIO.CreateViewerStreams [ name: "ArpaNameTool.log", backingFile: "ArpaNameTool.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, "ArpaNameTool of %G.\n", [time[Loader.BCDBuildTime[Create]]]]; 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.target _ MakeLabeledText[ parent: kids, sibling: child, name: "Server:", data: defaultDomainServer, prev: data.target ]; child _ data.query _ MakeLabeledText[ parent: kids, sibling: child, name: "Query:", data: ArpaName.MyName[], prev: data.query]; child _ data.timeout _ MakeLabeledText[ parent: kids, sibling: child, name: "Timeout:", data: "30000", prev: data.timeout ]; child _ MakeRule[kids, child]; child _ MakeBool[kids, child, data, "recurse", NEW[BOOL _ FALSE], RecurseP]; child _ MakeBool[kids, child, data, "errors", NEW[BOOL _ TRUE], ShowErr]; child _ MakeSelector[kids, child, data, LIST[$in, $ch, $star], " QClass ", NEW[ATOM _ $in], QClassP]; child _ MakeSelector[kids, child, data, LIST[$udp, $tcp], " Protocol ", NEW[ATOM _ $udp], ProtocolP]; child _ MakeRule[kids, child]; child _ MakeLabel[kids, child, "QType:"]; child _ MakeButton[kids, child, data, " A ", Address]; child _ MakeButton[kids, child, data, "NS", Server]; child _ MakeButton[kids, child, data, "CN", CName]; child _ MakeButton[kids, child, data, "MX", MX]; child _ MakeButton[kids, child, data, "SOA", SOA]; child _ MakeButton[kids, child, data, " * ", Star]; child _ MakeRule[kids, child]; child _ MakeButton[kids, child, data, "Inv", Inverse]; child _ MakeButton[kids, child, data, "MB", MB]; child _ MakeButton[kids, child, data, "MG", MG]; child _ MakeButton[kids, child, data, "MR", MR]; child _ MakeButton[kids, child, data, "Null", Null]; child _ MakeButton[kids, child, data, "WKS", Wks]; child _ MakeRule[kids, child]; child _ MakeButton[kids, child, data, "Ptr", Ptr]; child _ MakeButton[kids, child, data, "HInfo", HInfo]; child _ MakeButton[kids, child, data, "MInfo", MInfo]; child _ MakeButton[kids, child, data, "MailA", Maila]; child _ MakeButton[kids, child, data, "MailB", Mailb]; child _ MakeButton[kids, child, data, "AXFR", Axfr]; 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]; }; }; QClassP: SelectorProc = TRUSTED { data: ClientData _ NARROW[clientData]; data.class _ SELECT value FROM $in => in, $ch => ch, ENDCASE => star; }; ProtocolP: SelectorProc = TRUSTED { data: ClientData _ NARROW[clientData]; data.protocol _ SELECT value FROM $udp => udpOnly, ENDCASE => tcpOnly; }; RecurseP: BoolProc = TRUSTED { data: ClientData _ NARROW[clientData]; data.recursionDesired _ value; }; ShowErr: BoolProc = TRUSTED { data: ClientData _ NARROW[clientData]; data.showErr _ value; }; Address: Buttons.ButtonProc = TRUSTED { data: ClientData _ NARROW[clientData]; Query[data, a]; }; Server: Buttons.ButtonProc = TRUSTED { data: ClientData _ NARROW[clientData]; Query[data, ns]; }; CName: Buttons.ButtonProc = TRUSTED { data: ClientData _ NARROW[clientData]; Query[data, cName]; }; Star: Buttons.ButtonProc = TRUSTED { data: ClientData _ NARROW[clientData]; Query[data, star]; }; SOA: Buttons.ButtonProc = TRUSTED { data: ClientData _ NARROW[clientData]; Query[data, soa]; }; MX: Buttons.ButtonProc = TRUSTED { data: ClientData _ NARROW[clientData]; Query[data, mx]; }; MB: Buttons.ButtonProc = TRUSTED { data: ClientData _ NARROW[clientData]; Query[data, mb]; }; MG: Buttons.ButtonProc = TRUSTED { data: ClientData _ NARROW[clientData]; Query[data, mg]; }; MR: Buttons.ButtonProc = TRUSTED { data: ClientData _ NARROW[clientData]; Query[data, mr]; }; Null: Buttons.ButtonProc = TRUSTED { data: ClientData _ NARROW[clientData]; Query[data, null]; }; Wks: Buttons.ButtonProc = TRUSTED { data: ClientData _ NARROW[clientData]; Query[data, wks]; }; Ptr: Buttons.ButtonProc = TRUSTED { data: ClientData _ NARROW[clientData]; Query[data, ptr]; }; HInfo: Buttons.ButtonProc = TRUSTED { data: ClientData _ NARROW[clientData]; Query[data, hinfo]; }; MInfo: Buttons.ButtonProc = TRUSTED { data: ClientData _ NARROW[clientData]; Query[data, minfo]; }; Maila: Buttons.ButtonProc = TRUSTED { data: ClientData _ NARROW[clientData]; Query[data, maila]; }; Mailb: Buttons.ButtonProc = TRUSTED { data: ClientData _ NARROW[clientData]; Query[data, mailb]; }; Axfr: Buttons.ButtonProc = TRUSTED { data: ClientData _ NARROW[clientData]; Query[data, axfr]; }; Inverse: Buttons.ButtonProc = TRUSTED { data: ClientData _ NARROW[clientData]; log: IO.STREAM _ data.log; serverName: ROPE = ViewerTools.GetContents[data.target]; rope: ROPE _ ViewerTools.GetContents[data.query]; port: ArpaNameBuf.Port _ ArpaNameBuf.domainPort; timeoutRope: ROPE _ ViewerTools.GetContents[data.timeout]; timeout: ArpaUDP.Milliseconds _ Convert.CardFromRope[timeoutRope]; server, address, source: Arpa.Address; query: ROPE; reply: ArpaNameQuery.Reply _ NIL; status: ArpaName.ReplyStatus; IF Rope.IsEmpty[serverName] THEN RETURN; IF Rope.IsEmpty[rope] THEN RETURN; [server, status, source] _ ArpaName.NameToAddress[serverName]; SELECT status FROM bogus => {Report[log, serverName, ": not a valid name (", ArpaName.AddressToName[source].name, ").\n"]; RETURN}; down => {Report[log, "Name servers not responding.\n"]; RETURN}; other => {Report[log, serverName, ": no address for this name (", ArpaName.AddressToName[source].name, ").\n"]; RETURN}; ENDCASE; IF server = Arpa.nullAddress THEN {Report[log, serverName, ": unable to lookup name.\n"]}; IF ~ArpaNameSupport.IsAddressRope[rope] THEN {Report[log, "Needs to be an Arpa address.\n"]; RETURN}; address _ ArpaName.NameToAddress[rope].addr; IF address = Arpa.nullAddress THEN {Report[log, "Needs to be an Arpa address.\n"]; RETURN}; query _ IO.PutFR["%G.%G.%G.%G.IN-ADDR.ARPA", [integer[address.d]], [integer[address.c]], [integer[address.b]], [integer[address.a]]]; PrintOutgoing[server, serverName, query, ptr, data.class, data.recursionDesired, log]; reply _ DoQuery[server, query, ptr, data.class, data.protocol, data.recursionDesired, port, timeout, data.showErr, log]; PrintReply[server, reply, log]; }; Query: PROC [data: ClientData, type: ArpaNameQuery.QType] = { log: IO.STREAM _ data.log; server, source: Arpa.Address; reply: ArpaNameQuery.Reply _ NIL; serverName: ROPE = ViewerTools.GetContents[data.target]; query: ROPE _ ViewerTools.GetContents[data.query]; port: ArpaNameBuf.Port _ ArpaNameBuf.domainPort; timeoutRope: ROPE _ ViewerTools.GetContents[data.timeout]; timeout: ArpaUDP.Milliseconds _ Convert.CardFromRope[timeoutRope]; status: ArpaName.ReplyStatus; IF Rope.IsEmpty[serverName] THEN RETURN; IF Rope.IsEmpty[query] THEN RETURN; [server, status, source] _ ArpaName.NameToAddress[serverName]; SELECT status FROM bogus => {Report[log, serverName, ": not a valid name (", ArpaName.AddressToName[source].name, ").\n"]; RETURN}; down => {Report[log, "Name servers not responding.\n"]; RETURN}; other => {Report[log, serverName, ": no address for this name (", ArpaName.AddressToName[source].name, ").\n"]; RETURN}; ENDCASE; IF server = Arpa.nullAddress THEN {Report[log, serverName, ": unable to lookup name.\n"]}; PrintOutgoing[server, serverName, query, type, data.class, data.recursionDesired, log]; reply _ DoQuery[server, query, type, data.class, data.protocol, data.recursionDesired, port, timeout, data.showErr, log]; PrintReply[server, reply, log]; }; DoQuery: PROC [ server: Arpa.Address, query: Rope.ROPE, type: ArpaNameQuery.QType, class: ArpaNameQuery.QClass, protocol: ArpaNameQuery.Protocol, recurDesired: BOOL, port: ArpaNameBuf.Port, timeout: ArpaUDP.Milliseconds, showErrs: BOOL, log: IO.STREAM] RETURNS[reply: ArpaNameQuery.Reply] = { {ENABLE {UNWIND => NULL; ArpaNameQuery.Error => {PrintCode[code, log]; GOTO Quit}}; reply _ ArpaNameQuery.Query[server: server, query: query, type: type, class: class, recurDesired: recurDesired, protocol: protocol, port: port, timeout: timeout, retry: 0, acceptErrors: showErrs]; }; EXITS Quit => {}; }; PrintCode: PROC [code: ATOM, log: IO.STREAM] = { SELECT code FROM $destUnreachable => Report[log, "\nError: Destination unreachable.\n"]; $badRemoteAddress => Report[log, "\nError: Attempt to use broadcast address.\n"]; $nullDestination => Report[log, "\nError: Attempt to use null address.\n"]; $netUnreachable => Report[log, "\nICMP message: Net unreachable.\n"]; $hostUnreachable => Report[log, "\nICMP message: Host unreachable.\n"]; $portUnreachable => Report[log, "\nICMP message: Port unreachable.\n"]; $mustFragment => Report[log, "\nICMP message: Must fragment.\n"]; $sourceRouteFailure => Report[log, "\nICMP message: Source route failure.\n"]; $timeoutTimeToLive => Report[log, "\nICMP message: Timeout TimeToLive.\n"]; $parameterProblem => Report[log, "\nICMP message: Parameter problem.\n"]; $sourceQuench => Report[log, "\nICMP message: Source quench.\n"]; ENDCASE => Report[log, "\nError: ", Atom.GetPName[code], "\n"]; }; PrintOutgoing: PROC [ server: Arpa.Address, serverName: ROPE, query: Rope.ROPE, type: ArpaNameQuery.QType, class: ArpaNameQuery.QClass, recurDesired: BOOLEAN, log: IO.STREAM] = { IF log = NIL THEN RETURN; IF ArpaNameSupport.IsAddressRope[serverName] THEN Report[log, "\nAsking ", serverName, " = ", ArpaName.AddressToName[server].name, "\n"] ELSE Report[log, "\nAsking ", ArpaName.AliasToName[serverName].name, " = ", ConvertExtras.RopeFromArpaAddress[server], "\n"]; PrintQuery[query, type, class, log]; Report[log, "Recursion desired: "]; SELECT recurDesired FROM TRUE => Report[log, "TRUE\n"]; ENDCASE => Report[log, "FALSE\n"]; Report[log, "\n"]; IO.Flush[log]; }; Report: PROC [log: IO.STREAM, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10: ROPE _ NIL] = { IF log = NIL THEN RETURN; IF r1 # NIL THEN {IO.PutRope[log, r1]}; IF r2 # NIL THEN {IO.PutRope[log, r2]}; IF r3 # NIL THEN {IO.PutRope[log, r3]}; IF r4 # NIL THEN {IO.PutRope[log, r4]}; IF r5 # NIL THEN {IO.PutRope[log, r5]}; IF r6 # NIL THEN {IO.PutRope[log, r6]}; IF r7 # NIL THEN {IO.PutRope[log, r7]}; IF r8 # NIL THEN {IO.PutRope[log, r8]}; IF r9 # NIL THEN {IO.PutRope[log, r9]}; IF r10 # NIL THEN {IO.PutRope[log, r10]}; }; PrintReply: PROC [server: Arpa.Address, reply: ArpaNameQuery.Reply, log: IO.STREAM] = { IF log = NIL THEN RETURN; IF reply = NIL THEN {Report[log, "No reply to query.\n"]; RETURN;}; IF reply.source # server THEN Report[log, IO.PutFR["Strange source address: expected %G, found %G.\n", [rope[ConvertExtras.RopeFromArpaAddress[server]]], [rope[ConvertExtras.RopeFromArpaAddress[reply.source]]]]]; Report[log, "Reply: \n"]; SELECT reply.hdr.qr FROM query => Report[log, "qr: query, "]; response => Report[log, "qr: response, "]; ENDCASE => ERROR; SELECT reply.hdr.opcode FROM query => Report[log, "opcode: query"]; iquery => Report[log, "opcode: iquery"]; cquerym => Report[log, "opcode: cquerym"]; cqueryu => Report[log, "opcode: cqueryu"]; ENDCASE => ERROR; Report[log, IO.PutFR[", length: %G bytes.\n", [integer[reply.domainPacketLength]]]]; Report[log, IO.PutFR["aa: %G, tc: %G, rd: %G, ra: %G, ", [boolean[reply.hdr.authoritative]], [boolean[reply.hdr.truncated]], [boolean[reply.hdr.recurDesired]], [boolean[reply.hdr.recurAvail]]]]; SELECT reply.hdr.rcode FROM ok => Report[log, "rcode: ok"]; format => Report[log, "rcode: format"]; serverFailed => Report[log, "rcode: serverFailed"]; nameError => Report[log, "rcode: nameError"]; notImplemented => Report[log, "rcode: notImplemented"]; refused => Report[log, "rcode: refused"]; ENDCASE => ERROR; IF reply.hdr.truncated THEN Report[log, " ** TRUNCATED **"]; Report[log, "\n"]; Report[log, IO.PutFR["qdCount: %G, anCount: %G, nsCount: %G, arCount: %G\n", [integer[reply.hdr.qdCount]], [integer[reply.hdr.anCount]], [integer[reply.hdr.nsCount]], [integer[reply.hdr.arCount]]]]; IF reply.hdr.qdCount # reply.qdCount THEN Report[log, IO.PutFR[" ** INCORRECT QUERY RECORD COUNT.\n ** Query records found: %g.\n", [integer[reply.qdCount]]]]; IF reply.hdr.anCount # reply.anCount THEN Report[log, IO.PutFR[" ** INCORRECT ANSWER RR COUNT.\n ** Answer RRs found: %g.\n", [integer[reply.anCount]]]]; IF reply.hdr.nsCount # reply.nsCount THEN Report[log, IO.PutFR[" ** INCORRECT AUTHORITY RR COUNT.\n ** Authority RRs found: %g.\n", [integer[reply.nsCount]]]]; IF reply.hdr.arCount # reply.arCount THEN Report[log, IO.PutFR[" ** INCORRECT ADDITIONAL RR COUNT.\n ** Additional RRs found: %g.\n", [integer[reply.arCount]]]]; PrintQueries[reply, log]; PrintAnswerRRs[reply, log]; PrintAuthorityRRs[reply, log]; PrintAdditionalRRs[reply, log]; Report[log, "\n"]; Report[log, IO.PutFR["The response time was %G ms.\n", [integer[reply.responseTime]]]]; Report[log, "\n"]; IO.Flush[log]; }; PrintQueries: PROC [reply: ArpaNameQuery.Reply, log: IO.STREAM] = { IF reply.questions = NIL THEN RETURN; FOR i: INT IN[0..reply.qdCount) DO q: ArpaNameQuery.QuestionRecord _ reply.questions[i]; IF q = NIL THEN RETURN; PrintQuery[q.name, q.type, q.class, log]; ENDLOOP; }; PrintQuery: PROC [name: ROPE, type: ArpaNameQuery.QType, class: ArpaNameQuery.QClass, log: IO.STREAM] = { Report[log, IO.PutFR["Query Name: \"%G\", ", [rope[name]]]]; PrintQType[log, "Type: %G, ", type]; PrintQClass[log, "Class: %G\n", class]; }; PrintAnswerRRs: PROC [reply: ArpaNameQuery.Reply, log: IO.STREAM] = { IF reply.answers = NIL THEN RETURN; FOR i: INT IN[0..reply.anCount) DO an: ArpaNameQuery.ResourceRecord _ reply.answers[i]; IF an = NIL THEN RETURN; PrintRR[an, log]; ENDLOOP; }; PrintAuthorityRRs: PROC [reply: ArpaNameQuery.Reply, log: IO.STREAM] = { IF reply.authority = NIL THEN RETURN; FOR i: INT IN[0..reply.nsCount) DO ns: ArpaNameQuery.ResourceRecord _ reply.authority[i]; IF ns = NIL THEN RETURN; PrintRR[ns, log]; ENDLOOP; }; PrintAdditionalRRs: PROC [reply: ArpaNameQuery.Reply, log: IO.STREAM] = { IF reply.additional = NIL THEN RETURN; FOR i: INT IN[0..reply.arCount) DO ar: ArpaNameQuery.ResourceRecord _ reply.additional[i]; IF ar = NIL THEN RETURN; PrintRR[ar, log]; ENDLOOP; }; PrintRR: PROC [thisRR: ArpaNameQuery.ResourceRecord, log: IO.STREAM] = { OPEN ArpaNameQuery; name: ROPE _ thisRR.name; type: RRType _ thisRR.type; class: RRClass _ thisRR.class; ttl: ArpaNameQuery.Seconds _ thisRR.ttl; rDataLength: CARDINAL _ thisRR.dataLength; Report[log, IO.PutFR["RR Name: \"%G\", ", [rope[name]]]]; PrintRRType[log, "Type: %G, ", type]; PrintRRClass[log, "Class: %G", class]; Report[log, ".\n"]; Report[log, IO.PutFR[" TTL: %G, ", [cardinal[ttl]]]]; Report[log, IO.PutFR["RDataLength: %G", [integer[rDataLength]]]]; WITH thisRR SELECT FROM rr: ARR => { IF rDataLength = 4 THEN { rope: ROPE _ ConvertExtras.RopeFromArpaAddress[rr.address]; IO.PutF[log, " Addr: %G\n", [rope[rope]]]; } ELSE { Report[log, "Funny Length for type A.\n"]; }; }; rr: NsRR => IO.PutF[log, " Server is \"%G\".\n", [rope[rr.serverRope]]]; rr: MdRR => IO.PutF[log, " Mail Host is \"%G\".\n", [rope[rr.mdRope]]]; rr: MfRR => IO.PutF[log, " Forwarding Host is \"%G\".\n", [rope[rr.mfRope]]]; rr: CNameRR => IO.PutF[log, " Alias for \"%G\".\n", [rope[rr.cNameRope]]]; rr: SoaRR => { IO.PutRope[log, "\n"]; IO.PutF[log, " Primary server is \"%G\".\n", [rope[rr.soaRec.primaryServer]]]; IO.PutF[log, " Contact is \"%G\".\n", [rope[rr.soaRec.domainContact]]]; IO.PutF[log, " Serial: %G", [cardinal[rr.soaRec.serial]]]; IO.PutF[log, ", Refresh: %G", [cardinal[rr.soaRec.refresh]]]; IO.PutF[log, ", Retry: %G", [cardinal[rr.soaRec.retry]]]; IO.PutF[log, ", Expire: %G", [cardinal[rr.soaRec.expire]]]; IO.PutF[log, ", Min TTL: %G\n", [cardinal[rr.soaRec.minTtl]]]; }; rr: MbRR => IO.PutF[log, " Mail Host \"%G\".\n", [rope[rr.mbRope]]]; rr: MgRR => IO.PutF[log, " Member is \"%G\".\n", [rope[rr.mgRope]]]; rr: MrRR => IO.PutF[log, " New Name is \"%G\".\n", [rope[rr.mrRope]]]; rr: WksRR => { rope: ROPE _ ConvertExtras.RopeFromArpaAddress[rr.wksRec.address]; IO.PutF[log, " Addr: %G\n", [rope[rope]]]; IO.PutF[log, " Protocol: %G, Ports: ", [integer[rr.wksRec.protocol]]]; FOR i: INT IN [0..rr.wksRec.nPorts) DO IO.PutF[log, " %G ", [integer[rr.wksRec.ports[i]]]]; ENDLOOP; IO.PutRope[log, "\n"]; }; rr: PtrRR => IO.PutF[log, " PTR is \"%G\".\n", [rope[rr.ptrRope]]]; rr: HinfoRR => { IO.PutF[log, " CPU: %G, OS: %G.\n", [rope[rr.hinfoRec.cpu]], [rope[rr.hinfoRec.os]]];}; rr: MinfoRR => { IO.PutF[log, " List owner: %G, Errors-To: %G.\n", [rope[rr.minfoRec.rmailbx]], [rope[rr.minfoRec.emailbx]]];}; rr: MxRR => { IO.PutF[log, " Preference Value: %G,", [cardinal[rr.mxRec.preference]]]; IO.PutF[log, " Host Name: \"%G\".\n", [rope[rr.mxRec.host]]]}; ENDCASE => { IO.PutRope[log, ", Unknown Type.\n"]; }; }; PrintQType: PROC [ log: IO.STREAM, arg: ROPE, type: ArpaNameQuery.QType] = { text: ROPE _ SELECT type FROM a => "a", ns => "ns", md => "md", mf => "mf", cName => "cName", soa => "soa", mb => "mb", mg => "mg", mr => "mr", null => "null", wks => "wks", ptr => "ptr", hinfo => "hinfo", minfo => "minfo", mx => "mx", axfr => "axfr", mailb => "mailb", maila => "maila", star => "*", ENDCASE => " * Unknown Query Type *"; IO.PutF[log, arg, [rope[text]]]; }; PrintQClass: PROC [ log: IO.STREAM, arg: ROPE, class: ArpaNameQuery.QClass] = { text: ROPE _ SELECT class FROM in => "in", cs => "cs", ch => "ch", star => "*", ENDCASE => " * Unknown Query Class *"; IO.PutF[log, arg, [rope[text]]]; }; PrintRRType: PROC [ log: IO.STREAM, arg: ROPE, type: ArpaNameQuery.RRType] = { text: ROPE _ SELECT type FROM a => "a", ns => "ns", md => "md", mf => "mf", cName => "cName", soa => "soa", mb => "mb", mg => "mg", mr => "mr", null => "null", wks => "wks", ptr => "ptr", hinfo => "hinfo", minfo => "minfo", mx => "mx", ENDCASE => " * Unknown RR Type *"; IO.PutF[log, arg, [rope[text]]]; }; PrintRRClass: PROC [ log: IO.STREAM, arg: ROPE, class: ArpaNameQuery.RRClass] = { text: ROPE _ SELECT class FROM in => "in", cs => "cs", ch => "ch", ENDCASE => " * Unknown RR Class *"; IO.PutF[log, arg, [rope[text]]]; }; 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]; }; 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 [parent, sibling: Viewer, clientData: REF _ NIL, values: LIST OF ATOM, name: ROPE, init: REF ATOM _ NIL, change: SelectorProc _ NIL] 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: sibling.wx + buttonWidth - 1, wy: sibling.wy] ]; 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 _ LIST[child] ELSE { last.rest _ LIST[child]; 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 [parent, sibling: Viewer, clientData: REF _ NIL, name: ROPE, init: REF BOOL _ NIL, change: BoolProc _ NIL] RETURNS [child: Viewer] = { bool: Bool _ NEW [BoolRec _ [ value: IF init = NIL THEN NEW [BOOL _ FALSE] ELSE init, change: change, clientData: clientData, button: NIL ] ]; child _ Buttons.Create[ info: [name: name, parent: parent, border: TRUE, wx: sibling.wx + buttonWidth - 1, wy: sibling.wy, ww: buttonWidth], 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["ArpaNameTool", Create, "Probe Arpa Name Servers."]; END. ”ArpaNameTool.mesa Copyright c 1987 by Xerox Corporation. All rights reserved. John Larson, August 11, 1988 8:45:11 pm PDT Viewer layout parameters parent: REF, clientData: REF, value: BOOL parent: REF, clientData: REF, value: BOOL parent: REF, clientData: REF, value: BOOL parent: REF, clientData: REF, value: 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 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 Κ$˜šœ™Icodešœ Οmœ1™Jšœžœ˜šœ!˜!Jšœžœžœ'˜^—J˜%J˜šœ&˜&J˜ J˜J˜Jšœ˜Jšœ˜J˜—šœ%˜%J˜ J˜J˜Jšœ˜Jšœ˜J˜—šœ'˜'J˜ J˜J˜J˜Jšœ˜˜J˜——J˜J˜Jšœ/žœžœžœ ˜LJšœ.žœžœžœ ˜IJ˜Jš œ(žœ žœžœžœ ˜fJ˜Jš œ(žœžœžœžœ ˜fJ˜J˜J˜J˜)Jšœ6˜6Jšœ4˜4Jšœ3˜3Jšœ,žœ˜0Jšœ-žœ˜2Jšœ3˜3J˜Jšœ6˜6Jšœ,žœ˜0Jšœ,žœ˜0Jšœ,žœ˜0Jšœ4˜4Jšœ2˜2J˜Jšœ2˜2Jšœ6˜6Jšœ6˜6Jšœ6˜6Jšœ6˜6Jšœ4˜4J˜J™J˜šœ˜Jšœžœ˜Jšœžœ˜)Kšœnžœ˜uJ˜CJšžœžœ(˜>JšœR˜R—J˜J˜J˜—šŸœžœ˜!Jšœžœžœ ž™)Jšœžœ ˜&šœ ˜ šžœž˜J˜ J˜ Jšžœ ˜——Jšœ˜J˜J˜—šŸ œžœ˜#Jšœžœžœ ž™)Jšœžœ ˜&šœ˜šžœž˜J˜Jšžœ ˜——Jšœ˜J˜J˜J˜J˜J˜J˜—šŸœ žœ˜Jšœžœžœ ž™)Jšœžœ ˜&Jšœ˜Jšœ˜J˜—šŸœ žœ˜Jšœžœžœ ž™)Jšœžœ ˜&Jšœ˜Jšœ˜J˜J˜J˜J˜J˜—š œžœ˜'Jšœžœžœ,ž™LJšœžœ ˜&Jšœ˜J˜—š œžœ˜&Jšœžœžœ,ž™LJšœžœ ˜&Jšœ˜J˜—šŸœžœ˜%Jšœžœžœ,ž™LJšœžœ ˜&Jšœ˜J˜J˜—š œžœ˜$Jšœžœžœ,ž™LJšœžœ ˜&Jšœ˜—šΠbkœžœ˜#Jšœžœžœ,ž™LJšœžœ ˜&Jšœ˜—š’œžœ˜"Jšœžœžœ,ž™LJšœžœ ˜&Jšœ˜Jšœ˜J˜J˜—šŸœžœ˜"Jšœžœžœ,ž™LJšœžœ ˜&Jšœ˜Jšœ˜J˜J˜J˜—šŸœžœ˜"Jšœžœžœ,ž™LJšœžœ ˜&Jšœ˜Jšœ˜J˜J˜—šŸœžœ˜"Jšœžœžœ,ž™LJšœžœ ˜&Jšœ˜Jšœ˜J˜J˜—šŸœžœ˜$Jšœžœžœ,ž™LJšœžœ ˜&Jšœ˜Jšœ˜J˜J˜—šŸœžœ˜#Jšœžœžœ,ž™LJšœžœ ˜&Jšœ˜Jšœ˜J˜J˜—šŸœžœ˜#Jšœžœžœ,ž™LJšœžœ ˜&Jšœ˜Jšœ˜J˜—šŸœžœ˜%Jšœžœžœ,ž™LJšœžœ ˜&Jšœ˜Jšœ˜J˜—šŸœžœ˜%Jšœžœžœ,ž™LJšœžœ ˜&Jšœ˜Jšœ˜J˜J˜—šŸœžœ˜%Jšœžœžœ,ž™LJšœžœ ˜&Jšœ˜Jšœ˜J˜J˜—šŸœžœ˜%Jšœžœžœ,ž™LJšœžœ ˜&Jšœ˜Jšœ˜J˜—šŸœžœ˜$Jšœžœžœ,ž™LJšœžœ ˜&Jšœ˜Jšœ˜J˜J˜J˜J˜—š œžœ˜'Jšœžœžœ,ž™LJšœžœ ˜&Jšœžœžœ ˜Jšœ žœ(˜8Jšœžœ'˜1Jšœ0˜0Jšœ žœ)˜:JšœB˜BJšœ&˜&Jšœžœ˜ Jšœžœ˜!Jšœ˜J˜Jšžœžœžœ˜(Jšžœžœžœ˜"J˜Jšœ>˜>šžœž˜Jšœižœ˜rJšœ8žœ˜AJšœqžœ˜zJšž˜—J˜Jšžœžœ<˜]Jšžœ&žœ1žœ˜eJšœ,˜,Jšœžœ1žœ˜[J˜Jšœžœ{˜…JšœV˜VJšœx˜xJ˜J˜J˜J˜—š œžœ2˜=Jšœžœžœ ˜Jšœ˜Jšœžœ˜!Jšœ žœ(˜8Jšœžœ'˜2Jšœ0˜0Jšœ žœ)˜:JšœB˜BJšœ˜J˜Jšžœžœžœ˜(Jšžœžœžœ˜#J˜Jšœ>˜>šžœž˜Jšœižœ˜rJšœ8žœ˜AJšœqžœ˜zJšž˜—J˜Jšžœžœ<˜]JšœW˜WJšœy˜yJ˜J˜J˜J˜J˜J˜—š œžœ˜Jšœ˜Jšœ žœ˜Jšœ˜Jšœ˜Jšœ!˜!Jšœžœ˜Jšœ˜Jšœ˜Jšœ žœ˜Jšœžœžœ)˜7š œžœžœžœ0žœ ˜TJšœΔ˜ΔJ˜—šž˜J˜ —J˜J˜J˜J˜—š   œžœžœžœžœ˜1šžœžœ˜JšœH˜HJšœR˜RJšœL˜LJšœF˜FJšœH˜HJšœH˜HJšœB˜BJšœO˜OJšœL˜LJšœJ˜JJšœB˜BJšžœ9˜@—Jšœ˜J˜J˜—š Ÿœžœ˜Jšœ˜Jšœ žœ˜Jšœ žœ˜Jšœ˜Jšœ˜Jšœžœ˜Jšœžœžœ˜Jšžœžœžœžœ˜J˜šžœ+ž˜1JšœV˜V—šž˜Jšœx˜x—J˜J˜Jšœ$˜$Jšœ#˜#šžœž˜Jšžœ˜Jšžœ˜"—Jšœ˜Jšžœ ˜Jšœ˜J˜J˜—š Ÿœžœžœžœ+žœžœ˜WJšžœžœžœžœ˜Jšžœžœžœžœ˜'Jšžœžœžœžœ˜'Jšžœžœžœžœ˜'Jšžœžœžœžœ˜'Jšžœžœžœžœ˜'Jšžœžœžœžœ˜'Jšžœžœžœžœ˜'Jšžœžœžœžœ˜'Jšžœžœžœžœ˜'Jšžœžœžœžœ˜)Jšœ˜J˜J˜J˜—š  œžœ9žœžœ˜XJšžœžœžœžœ˜Jšžœ žœžœ'žœ˜CJ˜šžœž˜šœ žœ:˜HJšœ3˜3Jšœ;˜;——Jšœ˜J˜šžœž˜Jšœ$˜$Jšœ*˜*Jšžœžœ˜—šžœž˜Jšœ&˜&Jšœ(˜(Jšœ*˜*Jšœ*˜*Jšžœžœ˜—Jšœ žœF˜Tšœ žœ*˜8Jšœ‰˜‰—šžœž˜Jšœ˜Jšœ'˜'Jšœ3˜3Jšœ-˜-Jšœ7˜7Jšœ)˜)Jšžœžœ˜—Jšžœžœ"˜=Jšœ˜J˜šœ žœ>˜LJšœy˜yJ˜—Jšžœ#žœ~˜§Jšžœ#žœx˜‘Jšžœ#žœ~˜§Jšžœ#žœ€˜©J˜Jšœ˜Jšœ˜Jšœ˜Jšœ˜Jšœ˜Jšœ žœI˜WJšœ˜J˜Jšœ˜J˜J˜—šŸ œžœ#žœžœ˜DJšžœžœžœžœ˜%šžœžœžœž˜"Jšœ5˜5Jšžœžœžœžœ˜J˜)Jšžœ˜—J˜J˜J˜—š Ÿ œžœžœ?žœžœ˜jJšœ žœ.˜J˜J˜Jšœ žœ˜ J˜—Jšœžœžœžœ˜#JšœAžœ6˜|š žœžœžœžœžœžœž˜5šœ˜Kšœ=žœ-˜nJšœ2žœ žœ˜E—Jšžœžœžœžœ˜8Jšžœžœ˜3Jšžœžœ/˜PJšžœ˜ ——J˜š œ˜&Jšœžœžœ,ž™LJšœžœ ˜&Jšœžœ ˜(Jšœ žœžœ#˜3š žœžœžœžœžœžœž˜>šžœžœ˜J˜Jšžœžœžœ<˜YJšœ8˜8—Jšžœ7˜;J˜Jšžœ˜ ——J˜Jš œ žœžœžœ žœ˜EJšœžœžœ ˜šœ žœžœ˜Jšœžœžœ˜Jšœ˜Jšœ žœ˜Jšœ˜—J˜šŸœž˜Kšœ&žœžœžœžœžœžœžœ˜jKšžœ˜šœ žœ ˜Jšœžœžœžœžœžœžœžœ˜7J˜Jšœ˜Jšœžœ˜—šœ˜Kšœ+žœE˜tJšœ*žœ žœ˜=—Jšœ˜Jšžœ žœ2˜E—J˜š  œ˜"Jšœžœžœ,ž™LJšœžœ ˜&Jšœ žœ ˜ Jšœ˜Jšžœ žœ4˜GJšžœ5˜9Jšžœžœžœ<˜U—šŸ œžœ!žœžœ˜Q˜šœ+žœ˜1Jšœžœ žœžœ˜QJ˜—Jšœžœ˜——J˜šŸœžœ˜Jš œ%žœžœžœžœ˜jJš œžœžœ žœžœ˜AJš œžœžœ žœžœ ˜I˜&šœ>žœ˜CJš œžœžœžœžœ˜AJšœžœ˜J˜ —Jšœžœ˜—Jšœ&˜&˜Jšœ=žœ˜RJšœ0žœ žœ˜E—Jšžœ ˜J˜—š œ˜'Jšœžœžœ,ž™LJšœžœ ˜"šžœ ž˜Jšœ&žœ˜+Jšœ žœ˜Jšœ(žœ"žœ˜TJšžœžœ˜——J˜šœG˜GJ˜—Jšžœ˜J˜J˜J˜—J˜—…—f&‹ή