<<>> <> <> <> <> DIRECTORY Commander, CommanderOps, Convert, HostAndTerminalOps, IO, NetAddressing, PFS, Process, Rope, TerminalMultiServing; RemoteTerminalCommands: CEDAR PROGRAM IMPORTS Commander, CommanderOps, Convert, HostAndTerminalOps, IO, NetAddressing, PFS, Process, Rope, TerminalMultiServing = BEGIN OPEN HAT:HostAndTerminalOps, NA:NetAddressing, TMS:TerminalMultiServing; ROPE: TYPE ~ Rope.ROPE; ParseResult: TYPE ~ RECORD [msg: ROPE ¬ NIL, addr: NA.Address ¬ NA.nullAddress]; instDir: PFS.PATH ~ PFS.GetWDir[]; Prepare: PROC [cmd: Commander.Handle, pkg: ROPE] RETURNS [msg: ROPE ¬ NIL] ~ { Installit: PROC ~ { IF CommanderOps.DoCommand[Rope.Concat["Install ", pkg], cmd] = $Failure THEN msg ¬ Rope.Cat["Failed to install ", pkg, " in ", PFS.RopeFromPath[instDir]]; RETURN}; PFS.DoInWDir[instDir, Installit]; RETURN}; ConnectTo: PROC [cmd: Commander.Handle] RETURNS [result: REF ANY ¬ NIL, msg: ROPE ¬ NIL] --Commander.CommandProc-- ~ { argv: CommanderOps.ArgumentVector ~ CommanderOps.Parse[cmd]; FOR i: NAT IN [1 .. argv.argc) DO {pr: ParseResult ~ NiceParse[argv[i]]; IF pr.msg#NIL THEN {msg ¬ pr.msg; GOTO Dun}; {whyNot: ROPE ~ TMS.ServeHost[pr.addr, IF cmd.procData.clientData = $Secondary THEN secondary ELSE primary]; IF whyNot#NIL THEN cmd.err.PutRope[whyNot]; cmd.err.PutRope["\n"]}; EXITS Dun => result ¬ $Failure; }ENDLOOP; RETURN}; Disconnect: PROC [cmd: Commander.Handle] RETURNS [result: REF ANY ¬ NIL, msg: ROPE ¬ NIL] --Commander.CommandProc-- ~ { argv: CommanderOps.ArgumentVector ~ CommanderOps.Parse[cmd]; IF argv.argc > 1 THEN { FOR i: NAT IN [1 .. argv.argc) DO {pr: ParseResult ~ NiceParse[argv[i]]; IF pr.msg#NIL THEN {msg ¬ pr.msg; GOTO Dun}; TMS.DontServeHost[pr.addr]; EXITS Dun => result ¬ $Failure; }ENDLOOP; } ELSE TMS.ServeNoHosts[]; RETURN}; ListHosts: PROC [cmd: Commander.Handle] RETURNS [result: REF ANY ¬ NIL, msg: ROPE ¬ NIL] --Commander.CommandProc-- ~ { Print: PROC [addr: NA.Address] ~ { cmd.out.PutF1["%g\n", [rope[NA.FormatAddress[addr, TRUE]]]]; RETURN}; TMS.EnumerateHosts[Print]; RETURN}; PrintVersions: PROC [cmd: Commander.Handle] RETURNS [result: REF ANY ¬ NIL, msg: ROPE ¬ NIL] --Commander.CommandProc-- ~ { Print: PROC [protocol: ROPE, pvr: HAT.ProtocolVersionRange] ~ { cmd.out.PutF["%g: [%g .. %g]\n", [rope[protocol]], [integer[pvr.min]], [integer[pvr.max]] ]; RETURN}; HAT.EnumerateProtocolVersionsOfSide[SELECT cmd.procData.clientData FROM $Host => Host, $Terminal => Terminal, ENDCASE => ERROR, Print]; }; VersionsAtHost: PROC [cmd: Commander.Handle] RETURNS [result: REF ANY ¬ NIL, msg: ROPE ¬ NIL] --Commander.CommandProc-- ~ { argv: CommanderOps.ArgumentVector ~ CommanderOps.Parse[cmd]; IF argv.argc#2 THEN RETURN [$Failure, "Usage: VersionsAt HostName"]; {pr: ParseResult ~ NiceParse[argv[1]]; IF pr.msg#NIL THEN RETURN [$Failure, pr.msg]; msg ¬ TMS.GetHisVersions[pr.addr].ans; RETURN}}; GetHostsTerminal: PROC [cmd: Commander.Handle] RETURNS [result: REF ANY ¬ NIL, msg: ROPE ¬ NIL] --Commander.CommandProc-- ~ { argv: CommanderOps.ArgumentVector ~ CommanderOps.Parse[cmd]; IF argv.argc#2 THEN RETURN [$Failure, "Usage: GetHostsTerminal HostName"]; {pr: ParseResult ~ NiceParse[argv[1]]; IF pr.msg#NIL THEN RETURN [$Failure, pr.msg]; msg ¬ TMS.GetHisTerminal[pr.addr].ans; RETURN}}; PrintMe: PROC [cmd: Commander.Handle] RETURNS [result: REF ANY ¬ NIL, msg: ROPE ¬ NIL] --Commander.CommandProc-- ~ { ProcessBytes: NAT ~ BYTES[PROCESS]; me: PACKED ARRAY [0..ProcessBytes) OF BYTE ~ LOOPHOLE[Process.GetCurrent[]]; cmd.out.PutRope["Running in process "]; FOR i: NAT IN [0..ProcessBytes) DO IF i>0 AND (i MOD 4) = 0 THEN cmd.out.PutChar[',]; cmd.out.PutF1["%02x", [cardinal[me[i]]]]; ENDLOOP; cmd.out.PutRope[".\n"]; RETURN}; NiceParse: PROC [name: ROPE] RETURNS [r: ParseResult ¬ []] ~ TRUSTED { {ENABLE { IO.Error, Convert.Error => {r.msg ¬ "address parse&lookup failed"; CONTINUE}; NA.Error => {r.msg ¬ IO.PutFR1["Address parse/lookup failed: %g", [rope[NA.FormatError[codes, msg]]] ]; CONTINUE}; }; r.addr ¬ NA.ParseAddress[name]; IF r.addr = NA.nullAddress THEN r.msg ¬ "Lookup failed" ELSE { IF r.addr.socket.Length[] = 0 THEN r.addr.socket ¬ "58812"; r.addr ¬ NA.Canonicalize[r.addr]; }; }; IF r.msg#NIL THEN r.msg ¬ r.msg.Cat[" for ", name]}; Commander.Register["RemoteTerminalConnectTo", ConnectTo, " --- establishes RemoteTerminal connection", $Primary]; Commander.Register["RTConnectTo", ConnectTo, " --- establishes RemoteTerminal connection", $Primary]; Commander.Register["RTCT", ConnectTo, " --- establishes RemoteTerminal connection", $Primary]; Commander.Register["RemoteTerminalObserve", ConnectTo, " --- observe output from Host", $Secondary]; Commander.Register["RTObserve", ConnectTo, " --- observe output from Host", $Secondary]; Commander.Register["RemoteTerminalDisconnect", Disconnect, "--- tears down a RemoteTerminal connection from the Terminal side"]; Commander.Register["RTDisconnect", Disconnect, "--- tears down a RemoteTerminal connection from the Terminal side"]; Commander.Register["RTD", Disconnect, "--- tears down a RemoteTerminal connection from the Terminal side"]; Commander.Register["ListHosts", ListHosts, "--- lists hosts that we're being a terminal for"]; Commander.Register["HostVersions", PrintVersions, "--- prints installed protocol versions for Host side of RemoteTerminal system", $Host]; Commander.Register["TerminalVersions", PrintVersions, "--- prints installed protocol versions for Terminal side of RemoteTerminal system", $Terminal]; Commander.Register["VersionsAtHost", VersionsAtHost, " --- queries given host about protocol versions"]; Commander.Register["GetHostsTerminal", GetHostsTerminal, " --- queries given host about its terminal location"]; Commander.Register["PrintProcess", PrintMe, "prints the current PROCESS (in hex)"]; END.