DIRECTORY Arpa USING [Address], ArpaConfig USING [ specialDomains, topLevelDomains, validDomains, bitnetGateway, csnetGateway, uucpGateway, resolv ], ArpaName USING [AddressToName, AliasToName, NameToAddress, NameToMailHostList, ReplyStatus], ArpaQuery, ArpaQueryRpcControl, Commander USING [CommandProc, Register], IO USING [PutF, PutFR, rope], LupineRuntime USING [BindingError], Rope USING [ ROPE, Cat, Concat, Equal, Fetch, Find, Length, Substr ], RPC USING [ Conversation, EncryptionKey, ExportFailed, MakeKey, matchAllVersions, unencrypted ], QueryServices; ArpaQueryServerImpl: CEDAR PROGRAM IMPORTS ArpaConfig, ArpaName, ArpaQueryRpcControl, Commander, LupineRuntime, Rope, RPC, IO, QueryServices EXPORTS ArpaQuery = { OPEN ArpaQuery; ROPE: TYPE = Rope.ROPE; CheckName: PUBLIC PROC [ shh: RPC.Conversation_RPC.unencrypted, name: Rope.ROPE, abort: REF BOOL] RETURNS [rope: Rope.ROPE _ NIL] = { newName: ROPE; rootDomain: ROPE; server: ROPE; addr, source: Arpa.Address; valid: BOOLEAN _ FALSE; hostList: LIST OF ROPE _ NIL; status: ArpaName.ReplyStatus; IF Rope.Find[name,"@"] > -1 THEN name _ BreakName[name, '@].right; IF Rope.Find[name, "."] = -1 THEN { rope _ Rope.Cat[rope, "\nNeed top level domain. The mail gateway default is \".ARPA\".\n"]; name _ Rope.Concat[name, ".ARPA"];}; [valid, rootDomain] _ ValidDomain[name]; IF ~valid THEN { rope _ Rope.Cat[rope, IO.PutFR["\n%g => \"%g\" is not a known top level domain.\n\nArpanet top level domains we currently know about are:\n", IO.rope[name], IO.rope[BreakName[name].right]]]; FOR list: LIST OF Rope.ROPE _ ArpaConfig.topLevelDomains, list.rest UNTIL list = NIL DO topLevelDomain: Rope.ROPE _ list.first; rope _ Rope.Cat[rope, topLevelDomain, " "]; ENDLOOP; rope _ Rope.Cat[rope, "\n\nSpecial locally recognized domains are:\n\n"]; FOR list: LIST OF Rope.ROPE _ ArpaConfig.specialDomains, list.rest UNTIL list = NIL DO specialDomain: Rope.ROPE _ list.first; rope _ Rope.Cat[rope, specialDomain, " "]; ENDLOOP; rope _ Rope.Cat[rope, "\n\nMail forwarding is supported locally for these domains with the following translation rules.\n Local address => Arpanet address\n\n"]; FOR list: LIST OF Rope.ROPE _ ArpaConfig.specialDomains, list.rest UNTIL list = NIL DO specialDomain: Rope.ROPE _ list.first; rope _ Rope.Cat[rope, " ", "user@host."]; SELECT TRUE FROM Rope.Equal["UUCP", specialDomain, FALSE] => { rope _ Rope.Cat[rope, specialDomain, " => user%host.", specialDomain]; rope _ Rope.Cat[rope, "@", ArpaConfig.uucpGateway, "\n"];}; Rope.Equal["Bitnet", specialDomain, FALSE] => { rope _ Rope.Cat[rope, specialDomain, " => user%host.", specialDomain]; rope _ Rope.Cat[rope, "@", ArpaConfig.bitnetGateway, "\n"];}; Rope.Equal["CSNET", specialDomain, FALSE] => { rope _ Rope.Cat[rope, specialDomain, " => user%host.", specialDomain]; rope _ Rope.Cat[rope, "@", ArpaConfig.csnetGateway, "\n"];}; ENDCASE; ENDLOOP; RETURN[rope]; }; IF LocalDomain[rootDomain] THEN { gateway: ROPE; host: ROPE _ BreakName[name].left; SELECT TRUE FROM Rope.Equal["UUCP", rootDomain, FALSE] => gateway _ ArpaConfig.uucpGateway; Rope.Equal["Bitnet", rootDomain, FALSE] => gateway _ ArpaConfig.bitnetGateway; Rope.Equal["CSNET", rootDomain, FALSE] => gateway _ ArpaConfig.csnetGateway; ENDCASE; rope _ Rope.Cat[rope, IO.PutFR["\n\"%g\" is not a valid Arpanet name, but Grapevine mail to \"user@%g\" is forwarded by the Arpanet mail gateway to the Arpanet address \"user%%%g@%g\". ", IO.rope[name], IO.rope[name], IO.rope[name], IO.rope[gateway]]]; rope _ Rope.Cat[rope, IO.PutFR["To find out if %g is likely to recognize this name, check the %g host table with:\n\n QFind %g [Indigo]%g>%g-hosts.txt\n", IO.rope[gateway], IO.rope[rootDomain], IO.rope[host], IO.rope[rootDomain], IO.rope[rootDomain]]]; RETURN[rope]; }; IF abort^ THEN RETURN[NIL]; [newName, status, source] _ ArpaName.AliasToName[name, ArpaConfig.resolv^]; server _ ArpaName.AddressToName[source, ArpaConfig.resolv^].name; SELECT status FROM down => { rope _ Rope.Cat[rope, IO.PutFR["\n%g => Name servers not responding. Try again later.\n", [rope[name]]]]; RETURN[rope]; }; bogus => { rope _ Rope.Cat[rope, IO.PutFR["\n%g => not valid. \n(Name server: %g)\n", IO.rope[name], IO.rope[server]]]; RETURN[rope]; }; ok => { IF ~Rope.Equal[newName, name, FALSE] THEN { rope _ Rope.Cat[rope, IO.PutFR["\n%g => Alias for %g.\n(Name server: %g)\n", IO.rope[name], IO.rope[newName], IO.rope[server]]]; RETURN[rope]}; }; ENDCASE; IF abort^ THEN RETURN[NIL]; [hostList, status, source] _ ArpaName.NameToMailHostList[name, ArpaConfig.resolv^]; server _ ArpaName.AddressToName[source, ArpaConfig.resolv^].name; SELECT status FROM down => { rope _ Rope.Cat[rope, IO.PutFR["\n%g => Name servers not responding. Try again later.\n", [rope[name]]]]; RETURN[rope]; }; bogus => { rope _ Rope.Cat[rope, IO.PutFR["\n%g => not valid. \n(Name server: %g)\n", IO.rope[name], IO.rope[server]]]; RETURN[rope]; }; ok => { rope _ Rope.Cat[rope, IO.PutFR["\n%g => ok. \n(Name server: %g)\n", IO.rope[name], IO.rope[server]]]; RETURN[rope]; }; ENDCASE; IF abort^ THEN RETURN[NIL]; [addr, status, source] _ ArpaName.NameToAddress[name, ArpaConfig.resolv^]; server _ ArpaName.AddressToName[source, ArpaConfig.resolv^].name; SELECT status FROM down => { rope _ Rope.Cat[rope, IO.PutFR["\n%g => Name servers not responding. Try again later.\n", [rope[name]]]]; RETURN[rope]; }; bogus => { rope _ Rope.Cat[rope, IO.PutFR["\n%g => not valid. \n(Name server: %g)\n", IO.rope[name], IO.rope[server]]]; RETURN[rope]; }; ok => { rope _ Rope.Cat[rope, IO.PutFR["\n%g => ok. \n(Name server: %g)\n", IO.rope[name], IO.rope[server]]]; RETURN[rope]; }; ENDCASE => { rope _ Rope.Cat[rope, IO.PutFR["\n%g => Domain name, not valid for mail.\n(Name server: %g)\n", IO.rope[name], IO.rope[server]]]; RETURN[rope]; }; }; Whois: PUBLIC PROC [ shh: RPC.Conversation_RPC.unencrypted, pattern: Rope.ROPE, server: Rope.ROPE _ NIL, abort: REF BOOL] RETURNS [rope: Rope.ROPE] = { rope _ QueryServices.Whois[pattern, server, abort]; }; ArpaFinger: PUBLIC PROC [ shh: RPC.Conversation_RPC.unencrypted, pattern: Rope.ROPE, abort: REF BOOL] RETURNS [rope: Rope.ROPE] = { rope _ QueryServices.Finger[pattern, abort]; }; LocalDomain: PROC[domain: Rope.ROPE] RETURNS[BOOLEAN] = { FOR list: LIST OF Rope.ROPE _ ArpaConfig.specialDomains, list.rest UNTIL list = NIL DO specialDomain: Rope.ROPE _ list.first; IF Rope.Equal[specialDomain, domain, FALSE] THEN RETURN[TRUE]; ENDLOOP; RETURN[FALSE];}; ValidDomain: PROC [name: ROPE] RETURNS [valid: BOOLEAN_FALSE, domain: Rope.ROPE_NIL] = { FOR list: LIST OF Rope.ROPE _ ArpaConfig.validDomains, list.rest UNTIL list = NIL DO domain: Rope.ROPE _ list.first; IF DotTailed[name, domain] THEN RETURN[TRUE, domain]; ENDLOOP; RETURN[FALSE, NIL];}; Tailed: PROC [body, tail: Rope.ROPE] RETURNS [match: BOOL] = { bodyLength: INT = Rope.Length[body]; tailLength: INT = Rope.Length[tail]; back: Rope.ROPE; IF bodyLength <= tailLength THEN RETURN[FALSE]; back _ Rope.Substr[body, bodyLength-tailLength, tailLength]; IF ~Rope.Equal[back, tail, FALSE] THEN RETURN[FALSE]; RETURN[TRUE]; }; DotTailed: PROC [body, tail: ROPE] RETURNS [match: BOOL] = { IF ~Tailed[body, tail] THEN RETURN[FALSE]; IF Rope.Fetch[body, Rope.Length[body]-Rope.Length[tail]-1] # '. THEN RETURN[FALSE]; RETURN[TRUE]; }; 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; serverInterfaceName: ArpaQueryRpcControl.InterfaceName; serverPassword: RPC.EncryptionKey; serverInstance: ROPE _ "ArpaGateway.ms"; ArpaQueryServerInit: Commander.CommandProc = { ENABLE RPC.ExportFailed => { cmd.out.PutF["ArpaQuery export failed"]; GOTO Failed; }; serverInterfaceName _ [ type: serverInstance, instance: serverInstance]; serverPassword _ RPC.MakeKey["Security??"]; ArpaQueryRpcControl.UnexportInterface[!LupineRuntime.BindingError=>CONTINUE]; ArpaQueryRpcControl.ExportInterface[ interfaceName: serverInterfaceName, user: serverInterfaceName.instance, password: serverPassword]; cmd.out.PutF["Export[ArpaQuery, %g]\n", IO.rope[serverInterfaceName.instance]]; EXITS Failed => ArpaQueryRpcControl.UnexportInterface[!LupineRuntime.BindingError=>CONTINUE]; }; Commander.Register["ArpaQueryServer", ArpaQueryServerInit, "ArpaQueryServer\nInitialize and Export ArpaQuery"]; }. ˆArpaQueryServerImpl.mesa Copyright c 1986 by Xerox Corporation. All rights reserved. John Larson, March 13, 1988 7:43:48 pm PST Κ 4˜šœ™Icodešœ Οmœ1™Jšžœ˜—Jšžœžœ˜J˜—code2šŸ œžœžœžœ žœžœžœžœ˜Xš žœžœžœžœ&žœžœž˜TJšœ žœ˜Jšžœžœžœžœ ˜5Jšžœ˜—Jšžœžœžœ˜J˜—š Ÿœžœžœžœ žœ˜>Jšœ žœ˜$Jšœ žœ˜$Jšœ žœ˜Jšžœžœžœžœ˜/Jšœ<˜žœžœžœ˜SJšžœžœ˜J˜J˜—š Ÿ œžœ žœžœžœžœ˜SJšž˜Jšœžœ˜š žœžœž œžœ ž˜'šžœžœžœ˜$Jšœ$˜$Jšœ4˜4—Jšžœ˜—Jšžœžœ žœ˜Jšžœ˜J˜—J˜Jšœ7˜7Jšœžœ˜"Jšœžœ˜(J˜šŸœ˜.šž˜Jšžœ<žœ ˜NJ˜—J˜šœ˜Jšœ˜Jšœ˜J˜—šœžœ˜+J˜—JšœCžœ˜Mšœ$˜$Jšœ#˜#Jšœ#˜#Jšœ˜J˜—Jšœ(žœ%˜Ošž˜JšœMžœ˜W—J˜—J˜šœ:˜:Jšœ4˜4—J˜Jšœ˜J˜—…—!€,<