<> <> <> <> <> <> <> <<>> DIRECTORY Commander USING [CommandProc, Register], CommandTool USING [ArgumentVector, Failed, Parse], IO USING [Close, EndOf, EndOfStream, Error, Flush, GetChar, int, PutChar, PutF, PutRope, STREAM], Rope USING [Cat, Find, FromChar, ROPE], UserCredentials USING [Get], IPDefs USING [Address], IPName USING [NameToAddress], TCP USING [AbortTCPStream, CreateTCPStream, Error, ErrorFromStream, neverTimeout, Reason, Timeout, WaitForListenerOpen]; TCPTest: CEDAR PROGRAM IMPORTS Commander, CommandTool, IO, Rope, UserCredentials, IPName, TCP = BEGIN fingerSocket: INT = 79; remoteAddress: IPDefs.Address; remoteSocket: INT _ fingerSocket; running: BOOL _ TRUE; server: PROCESS; SetAddress: Commander.CommandProc = { out: IO.STREAM _ cmd.out; argv: CommandTool.ArgumentVector = CommandTool.Parse[cmd ! CommandTool.Failed => {out.PutRope[errorMsg]; GO TO GiveUp}]; remoteAddresses: LIST OF IPDefs.Address _ IPName.NameToAddress[argv[1]]; IF remoteAddresses=NIL THEN {out.PutRope["Name not found"]; GOTO GiveUp}; remoteAddress _ remoteAddresses.first; out.PutF["[%g.%g.%g.%g]\n", IO.int[remoteAddress[0]], IO.int[remoteAddress[1]], IO.int[remoteAddress[2]], IO.int[remoteAddress[3]]]; EXITS GiveUp => NULL; }; Finger: Commander.CommandProc = { out: IO.STREAM _ cmd.out; fingerStream: IO.STREAM; c: CHAR; cr: TCP.Reason _ neverOpen; { ENABLE { TCP.Timeout => { out.PutRope["[No response.]\n"]; GO TO GiveUp; }; TCP.Error => { cr _ reason; GO TO GiveUp; }; IO.Error => { cr _ TCP.ErrorFromStream[fingerStream]; GOTO GiveUp; }; }; fingerStream _ TCP.CreateTCPStream[[matchLocalPort~FALSE, localPort~0, matchForeignAddr~TRUE, foreignAddress~remoteAddress, matchForeignPort~TRUE, foreignPort~remoteSocket, active~TRUE, timeout~120000]]; TCP.WaitForListenerOpen[fingerStream, TCP.neverTimeout]; fingerStream.PutRope[cmd.commandLine]; fingerStream.PutChar['\l]; -- send the LF as well fingerStream.Flush[]; WHILE NOT fingerStream.EndOf[] DO c _ fingerStream.GetChar[ ! IO.EndOfStream => EXIT]; IF c # '\l THEN out.PutChar[c]; ENDLOOP; fingerStream.Close[]; EXITS GiveUp => SELECT cr FROM remoteAbort => out.PutRope["[Remote host refused to point the finger at its users.]\n"]; ENDCASE => TCP.AbortTCPStream[fingerStream]; }; }; FingerServer: PROC = { ENABLE TCP.Timeout => RESUME; fingerStream: IO.STREAM; WHILE running DO ENABLE BEGIN IO.Error => RETRY; TCP.Timeout => RETRY; TCP.Error => RETRY; END; char: CHAR; rope: Rope.ROPE _ NIL; fingerStream _ TCP.CreateTCPStream[[matchLocalPort: TRUE, localPort: fingerSocket, matchForeignAddr: FALSE, matchForeignPort: FALSE, active: FALSE]]; DO char _ fingerStream.GetChar[]; IF char = '\l THEN EXIT; rope _ Rope.Cat[rope, Rope.FromChar[char]]; ENDLOOP; fingerStream.PutF["User %g logged in on a Dorado.\n\l", [rope[UserCredentials.Get[].name]]]; IF Rope.Find[rope, "Verbose"] # -1 THEN <> THROUGH [0..20) DO fingerStream.PutF[" 123456789 123456789 123456789 123456789 123456789\n\l"]; ENDLOOP; IF Rope.Find[rope, "Super"] # -1 THEN THROUGH [0..200) DO fingerStream.PutF[" 123456789 123456789 123456789 123456789 123456789\n\l"]; ENDLOOP; fingerStream.Flush[]; fingerStream.Close[]; ENDLOOP; }; Commander.Register["SetTCPAddress", SetAddress, "Tell which remote host to use."]; Commander.Register["Finger", Finger, "Who is on host."]; server _ FORK FingerServer[]; END.