-- DicentraRS232Impl.mesa -- Copyright (C) 1984, 1985 Xerox Corporation. All rights reserved. -- Tim Diebert: 8-Nov-85 10:15:58 DIRECTORY DicentraRS232CAsync, Process, PupDefs USING [PupAddressLookup, PupNameTrouble], PupStream USING [CloseReason, CreatePupByteStreamListener, PupAddress, PupListener, RejectThisRequest, SecondsToTocks, StreamClosing], Stream, String USING [Copy], TTY; DicentraRS232Impl: MONITOR IMPORTS DicentraRS232CAsync, Process, PupDefs, PupStream, Stream, String = BEGIN rs232Stream: Stream.Handle _ NIL; busy: ARRAY DicentraRS232CAsync.PortNumber OF BOOL ¬ ALL [FALSE]; listener: PupStream.PupListener ¬ NIL; active: BOOL ¬ FALSE; kill, killKeyWatcher: BOOL ¬ FALSE; currentUser: LONG STRING ¬ [255]; wakeUp, bufferFlushed: CONDITION; -- set their timeouts buffer: ARRAY [0 .. 255) OF CHAR; bufferPtr: CARDINAL ¬ 0; KeyWatcher: PROC = { PutIt: ENTRY PROC [c: CHAR] = { WHILE bufferPtr > 255 DO NOTIFY wakeUp; EXIT; -- WAIT bufferFlushed; -- IF killKeyWatcher THEN RETURN; ENDLOOP; IF bufferPtr <= 255 THEN { buffer[bufferPtr] ¬ c; bufferPtr ¬ bufferPtr + 1}; }; DO c: CHAR ¬ rs232Stream.GetChar[]; -- IF killKeyWatcher THEN -- {killKeyWatcher ¬ FALSE; Stream.Delete[rs232Stream]; active ¬ FALSE; RETURN}; PutIt[c]; -- IF killKeyWatcher THEN -- {killKeyWatcher ¬ FALSE; Stream.Delete[rs232Stream]; active ¬ FALSE; RETURN}; ENDLOOP; }; keySenderRunning: BOOL ¬ FALSE; KeySender: ENTRY PROC [s: Stream.Handle] = { ENABLE PupStream.StreamClosing => {GOTO Out}; keySenderRunning ¬ TRUE; DO WAIT wakeUp; IF kill THEN { kill ¬ FALSE; -- killKeyWatcher ¬ TRUE; GOTO Out}; IF bufferPtr = 0 THEN LOOP; FOR i: CARDINAL IN [0 .. bufferPtr) DO s.PutChar[buffer[i]] ENDLOOP; Stream.SendNow[s]; bufferPtr ¬ 0; NOTIFY bufferFlushed; ENDLOOP; EXITS Out => {-- killKeyWatcher ¬ TRUE; kill ¬ FALSE; NOTIFY bufferFlushed; keySenderRunning ¬ FALSE; RETURN}; -- and kill process }; NetWatcher: PROC [s: Stream.Handle] = { ENABLE PupStream.StreamClosing => {kill ¬ TRUE; Note[]; GOTO Out}; DO c: CHAR ¬ s.GetChar[]; rs232Stream.PutChar[c]; ENDLOOP; EXITS Out => {Stream.Delete[s]; RETURN}; }; Note: ENTRY PROC [] = {NOTIFY wakeUp}; InitCommand: PROC [stream: Stream.Handle, pupAddress: PupStream.PupAddress] = BEGIN ENABLE { PupStream.StreamClosing => GOTO Exit; Stream.TimeOut => GOTO Exit}; -- name: STRING = "DicentraRS232.log"L; -- ttyImpl, backing: Stream.Handle; port: DicentraRS232CAsync.PortNumber ¬ LOOPHOLE[Stream.GetChar[stream]]; charLength: DicentraRS232CAsync.CharLength ¬ LOOPHOLE[Stream.GetChar[stream]]; speed: DicentraRS232CAsync.LineSpeed ¬ LOOPHOLE[Stream.GetChar[stream]]; parity: DicentraRS232CAsync.Parity ¬ LOOPHOLE[Stream.GetChar[stream]]; stop: DicentraRS232CAsync.StopBits ¬ LOOPHOLE[Stream.GetChar[stream]]; currentUser.length ¬ 0; PupDefs.PupAddressLookup[currentUser, pupAddress ! PupDefs.PupNameTrouble => {String.Copy[to: currentUser, from: e]; CONTINUE}]; bufferPtr ¬ 0; active ¬ TRUE; -- [ttyImpl, backing] ¬ DicentraRS232CAsync.CreateRS232Instance[name, NIL, -- TTY.nullHandle, [charLength, speed, parity, stop]]; -- rs232Stream ¬ ttyImpl; Stream.PutChar[stream, 'k]; Stream.SendNow[stream]; bufferPtr ¬ 0; -- Process.Detach[FORK KeyWatcher[]]; Process.Detach[FORK KeySender[stream]]; -- Process.Detach[FORK NetWatcher[stream]]; BEGIN ENABLE PupStream.StreamClosing, Stream.TimeOut => {IF keySenderRunning THEN kill ¬ TRUE; Note[]; GOTO Out}; DO c: CHAR ¬ stream.GetChar[]; rs232Stream.PutChar[c]; ENDLOOP; EXITS Out => {Stream.Delete[stream]; GOTO Exit}; END; EXITS Exit => {active ¬ FALSE; RETURN}; END; CheckBusy: PROC [pupAddress: PupStream.PupAddress] = BEGIN IF active THEN ERROR PupStream.RejectThisRequest[currentUser]; END; Init: PROC [] = BEGIN ttyImpl, backing: Stream.Handle; name: STRING = "DicentraRS232.log"L; bufferPtr ¬ 0; [ttyImpl, backing] ¬ DicentraRS232CAsync.CreateRS232Instance[name, NIL, TTY.nullHandle, -- [charLength, speed, parity, stop] --]; rs232Stream ¬ ttyImpl; IF listener = NIL THEN listener ¬ PupStream.CreatePupByteStreamListener[ local: [0, 32B], proc: InitCommand, ticks: PupStream.SecondsToTocks[30*60], filter: CheckBusy]; Process.SetTimeout[@wakeUp, Process.MsecToTicks[250]]; Process.SetTimeout[@bufferFlushed, Process.MsecToTicks[1000]]; Process.Detach[FORK KeyWatcher[]]; END; Init[]; END.