-- Copyright (C) 1983, 1985 by Xerox Corporation. All rights reserved. -- RemoteTTY.mesa, HGM, 3-Jul-85 1:49:32 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], PupTelnetStream USING [ AppendHostName, ConnectProc, FilterProc, Listen], TTY USING [Handle], TTYConstants USING [aborted, blinkDisplay]; RemoteTTY: MONITOR IMPORTS Process, PupStream, Stream, String, PupTelnetStream 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 PupTelnetStream.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]; PupTelnetStream.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 PupTelnetStream.FilterProc = BEGIN ENABLE UNWIND => NULL; IF remote # NIL THEN BEGIN temp: STRING = [100]; String.AppendString[temp, "Sorry, talking to "L]; PupTelnetStream.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 PupTelnetStream.Listen[Connect, Filter]]; -- Don't quite hang on 981 END...