-- Copyright (C) 1983 by Xerox Corporation. All rights reserved. -- RemoteTTY.mesa, HGM, 21-Dec-83 3:29:52 DIRECTORY Ascii USING [CR, BEL], Process USING [Detach, EnableAborts, MsecToTicks, SetTimeout], PupStream USING [RejectThisRequest], Stream USING [ defaultObject, Delete, DeleteProcedure, GetBlock, GetProcedure, Handle, Object, PutByte, PutChar, PutProcedure, PutString, SendAttention, SendAttentionProcedure, SetSSTProcedure, WaitAttentionProcedure, WaitForAttention], String USING [AppendString], TelnetStream USING [ AppendHostName, ConnectProc, FilterProc, Listen], TTY USING [Handle], TTYConstants USING [aborted, blinkDisplay]; RemoteTTY: MONITOR IMPORTS Process, PupStream, Stream, String, TelnetStream EXPORTS TTY = BEGIN first: BOOLEAN ¬ FALSE; local: Stream.Object ¬ Stream.defaultObject; remote: Stream.Handle ¬ NIL; waitForInput: CONDITION; CreateTTYInstance: PUBLIC ENTRY PROCEDURE [ name: LONG STRING, backingStream: Stream.Handle, tty: TTY.Handle] RETURNS [ttyImpl, backing: Stream.Handle] = BEGIN ENABLE UNWIND => NULL; IF ~first THEN BEGIN FOR i: CARDINAL IN [0..2) UNTIL remote # NIL DO WAIT waitForInput; ENDLOOP; RETURN[@local, NIL]; -- might be phoney END; UNTIL remote # NIL DO WAIT waitForInput; ENDLOOP; RETURN[@local, NIL]; END; Delete: PUBLIC ENTRY Stream.DeleteProcedure = BEGIN ENABLE UNWIND => NULL; IF first THEN BEGIN IF remote # NIL THEN Stream.Delete[remote]; remote ¬ NIL; END; first ¬ TRUE; END; PutBlock: ENTRY Stream.PutProcedure = BEGIN ENABLE UNWIND => NULL; IF remote = NIL THEN RETURN; FOR i: CARDINAL IN [block.startIndex..block.stopIndexPlusOne) DO Stream.PutByte[remote, block.blockPointer[i] ! ABORTED => EXIT]; ENDLOOP; END; GetBlock: Stream.GetProcedure = BEGIN IF remote = NIL THEN WaitForConnection[]; -- phoney connection [bytesTransferred, why, sst] ¬ Stream.GetBlock[remote, block]; END; WaitForConnection: ENTRY PROCEDURE = BEGIN ENABLE UNWIND => NULL; UNTIL remote # NIL DO WAIT waitForInput; ENDLOOP; END; SetSST: Stream.SetSSTProcedure = BEGIN IF sst = TTYConstants.blinkDisplay THEN Stream.PutChar[@local, Ascii.BEL]; END; SendAttention: ENTRY Stream.SendAttentionProcedure = BEGIN ENABLE UNWIND => NULL; IF remote # NIL THEN Stream.SendAttention[remote, byte]; END; WaitForAttention: ENTRY Stream.WaitAttentionProcedure = BEGIN ENABLE UNWIND => NULL; IF remote = NIL THEN RETURN[TTYConstants.aborted]; RETURN[Stream.WaitForAttention[remote]]; END; Connect: ENTRY TelnetStream.ConnectProc = BEGIN ENABLE UNWIND => NULL; IF remote = NIL THEN BEGIN remote ¬ sH; BROADCAST waitForInput; END; IF remote # sH THEN BEGIN -- Maybe tell him what's going on.... him: STRING = [100]; Stream.PutString[sH, "Sorry, talking to "L ! ABORTED => CONTINUE]; TelnetStream.AppendHostName[sH, him ! ABORTED => CONTINUE]; Stream.PutString[sH, him ! ABORTED => CONTINUE]; Stream.PutChar[sH, Ascii.CR ! ABORTED => CONTINUE]; Stream.Delete[sH]; END; END; Filter: ENTRY TelnetStream.FilterProc = BEGIN ENABLE UNWIND => NULL; IF remote # NIL THEN BEGIN temp: STRING = [100]; String.AppendString[temp, "Sorry, talking to "L]; TelnetStream.AppendHostName[remote, temp ! ABORTED => CONTINUE]; ERROR PupStream.RejectThisRequest[temp]; END; END; -- Initialization local.put ¬ PutBlock; local.get ¬ GetBlock; local.setSST ¬ SetSST; local.sendAttention ¬ SendAttention; local.waitAttention ¬ WaitForAttention; local.delete ¬ Delete; Process.EnableAborts[@waitForInput]; Process.SetTimeout[@waitForInput, Process.MsecToTicks[10000]]; Process.Detach[FORK TelnetStream.Listen[Connect, Filter]]; -- Don't quite hang on 981 END...