-- 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.