DIRECTORY Arpa USING [Address, nullAddress], ArpaConfig USING [ resolv ], ArpaName USING [NameToAddress, ReplyStatus], ArpaTCP USING [AbortTCPStream, CreateTCPStream, Error, ErrorFromStream, neverTimeout, Reason, Timeout, WaitForListenerOpen], IO USING [Close, EndOf, EndOfStream, Error, Flush, GetChar, PutFR, PutChar, PutRope, rope, RopeFromROS, ROS, STREAM], Rope USING [ROPE, Cat, Concat, IsEmpty, Fetch, Find, Length, Substr], Process USING [SecondsToTicks], QueryServices; QueryServicesImpl: CEDAR MONITOR IMPORTS ArpaConfig, ArpaName, ArpaTCP, IO, Process, Rope EXPORTS QueryServices = BEGIN OPEN QueryServices; whoIsSocket: INT = 43; fingerSocket: INT = 79; whoisServerDefault: Rope.ROPE = "SRI-NIC.ARPA"; nRetries: INT _ 4; seconds: CARDINAL _ 2; Whois: PUBLIC PROC [pattern: Rope.ROPE, server: Rope.ROPE _ NIL, abort: REF BOOL] RETURNS[rope: Rope.ROPE] = { whoisServer: Rope.ROPE _ IF ~Rope.IsEmpty[server] THEN server ELSE whoisServerDefault; rope _ QueryWait[whoisServer, pattern, whoIsSocket, abort]; IF rope # NIL THEN RETURN[rope]; IF abort^ THEN RETURN[NIL]; RETURN[IO.PutFR["Problems connecting to %g. Try again later.", IO.rope[whoisServer]]]; }; Finger: PUBLIC PROC [pattern: Rope.ROPE, abort: REF BOOL] RETURNS[rope: Rope.ROPE] = { host, user: Rope.ROPE _ NIL; IF Rope.Find[pattern,"@"] > -1 THEN [user, host] _ BreakName[pattern, '@] ELSE host _ pattern; IF host = NIL THEN RETURN["Please provide host name."]; IF Rope.Find[host, "."] = -1 THEN host _ Rope.Concat[host, ".ARPA"]; rope _ QueryWait[host, user, fingerSocket, abort]; IF rope # NIL THEN RETURN[rope]; IF abort^ THEN RETURN[NIL]; RETURN[IO.PutFR["Problems connecting to %g. Try again later.", IO.rope[host]]]; }; QueryWait: ENTRY PROC [host, pattern: Rope.ROPE, socket: INT, abort: REF BOOL] RETURNS[rope: Rope.ROPE_NIL] = { snooz: CONDITION _ [timeout: Process.SecondsToTicks[seconds]]; FOR i: INT IN [0..nRetries) DO rope _ QueryOnce[host, pattern, socket, abort]; IF rope # NIL THEN EXIT; IF abort^ THEN EXIT; WAIT snooz; ENDLOOP; }; QueryOnce: PROC [host, pattern: Rope.ROPE, socket: INT, abort: REF BOOL] RETURNS[rope: Rope.ROPE_NIL] = { server: IO.STREAM; status: ArpaName.ReplyStatus; cr: ArpaTCP.Reason _ neverOpen; out: IO.STREAM _ IO.ROS[]; where: Arpa.Address; lastChar: CHAR _ '1; i: INT _ 0; IF host = NIL THEN RETURN["Need host name."]; [where, status,] _ ArpaName.NameToAddress[host, ArpaConfig.resolv^]; SELECT status FROM bogus => RETURN[IO.PutFR["%g is not a valid name.", IO.rope[host]]]; down => RETURN[IO.PutFR["Name servers for %g are down. Try again later", IO.rope[host]]]; other => { RETURN[IO.PutFR["%g has no address", IO.rope[host]]]; }; ENDCASE; IF where = Arpa.nullAddress THEN { RETURN[IO.PutFR["Can't find IP Address for %G.", IO.rope[host]]]; }; BEGIN ENABLE { ArpaTCP.Timeout => { out.PutRope["[TCP.Timeout.]\n"]; GO TO GiveUp; }; ArpaTCP.Error => { out.PutRope["[TCP.Error.]\n"]; cr _ reason; GO TO GiveUp; }; IO.Error => { cr _ ArpaTCP.ErrorFromStream[server]; GO TO GiveUp; }}; server _ ArpaTCP.CreateTCPStream[[ matchLocalPort: FALSE, localPort: 0, matchForeignAddr: TRUE, foreignAddress: where, matchForeignPort: TRUE, foreignPort: socket, active: TRUE, timeout: 140000]]; ArpaTCP.WaitForListenerOpen[server, ArpaTCP.neverTimeout]; IF abort^ THEN GOTO Abort; IF pattern # NIL THEN server.PutRope[pattern]; server.PutRope["\n\l"]; server.Flush[]; WHILE NOT server.EndOf[] DO c: CHAR _ server.GetChar[ ! IO.EndOfStream => EXIT]; IF c # '\l THEN out.PutChar[c] ELSE { IF lastChar # '\n THEN out.PutChar['\n]}; -- Unix, convert LF to CR lastChar _ c; ENDLOOP; rope _ IO.RopeFromROS[out]; server.Close[]; out.Close[]; EXITS GiveUp => { IF server # NIL THEN ArpaTCP.AbortTCPStream[server]; IF out # NIL THEN out.Close[]; SELECT cr FROM remoteAbort => RETURN[Rope.Cat[host, " refused connection.\n"]]; ENDCASE => RETURN[NIL];}; Abort => { IF server # NIL THEN ArpaTCP.AbortTCPStream[server]; IF out # NIL THEN out.Close[]; RETURN[NIL]}; END; }; BreakName: PROC[name: Rope.ROPE, char: CHAR _ '.] RETURNS[left, right: Rope.ROPE] = BEGIN length: INT = name.Length[]; FOR i: INT DECREASING IN [0..length) DO IF name.Fetch[i] = char THEN RETURN[ left: name.Substr[start: 0, len: i], right: name.Substr[start: i+1, len: length-(i+1)] ]; ENDLOOP; RETURN[left: NIL, right: NIL]; END; END.  QueryServicesImpl.mesa Copyright c 1985 by Xerox Corporation. All rights reserved. Hal Murray May 16, 1985 3:20:40 am PDT John Larson, March 13, 1988 7:48:02 pm PST Doug Terry, September 23, 1987 3:17:06 pm PDT Sharon Johnson, August 5, 1988 11:58:33 am PDT Κκ– "cedar" style˜headšœ™Icodešœ Οmœ1™šžœžœžœž˜Mšœ/˜/Mšžœžœžœžœ˜Mšžœžœžœ˜Mšžœ˜ Mšžœ˜—Mšœ˜M˜—š Ÿ œžœžœ žœ žœžœ˜IMšžœ žœžœ˜ Mšœžœžœ˜Mšœ˜Mšœ˜Mš œžœžœžœžœ˜Mšœ˜Mšœ žœ˜Mšœžœ˜ Mšžœžœžœžœ˜-JšœCž˜Dšžœž˜Jšœ žœžœ"žœ˜DJšœ žœžœ8žœ˜Zšœ ˜ šžœžœžœ˜5Mšœ˜——Jšžœ˜—M˜šžœžœ˜"Mšžœžœ(žœ˜AMšœ˜—šž˜šžœ˜šœ˜Mšœ ˜ Mšžœžœ ˜—šœ˜Mšœ˜M˜ Mšžœžœ ˜—šžœ ˜ Mšœ%˜%Mšžœžœ ˜—M˜——šœ"˜"Mšœžœ˜Mšœ ˜ Mšœžœ˜Mšœ˜Mšœžœ˜Mšœ˜Mšœžœ˜ Mšœ˜—Mšœ:˜:Mšžœžœžœ˜M˜Mšžœ žœžœ˜.Mšœ˜M˜šžœžœž˜Mšœžœžœžœ˜4šžœ žœžœ˜&MšžœžœΟc˜D—M˜ Mšžœ˜M˜—Mšœžœ˜Mšœ˜Mšœ ˜ šžœ˜šœ ˜ Mšžœ žœžœ ˜4Mšžœžœžœ ˜šžœž˜Mšœžœ+˜@Mšžœžœžœ˜——šœ ˜ Mšžœ žœžœ ž˜5Mšžœžœžœ ˜Mšžœžœ˜ ——Mšžœ˜Mšœ˜M˜M˜—š Ÿ œžœ žœžœžœžœ˜SJšž˜Jšœžœ˜š žœžœž œžœ ž˜'šžœžœžœ˜$Jšœ$˜$Jšœ4˜4—Jšžœ˜—Jšžœžœ žœ˜Jšžœ˜J˜—M˜Mšžœ˜——…—ΰΤ