-- Laurel subsystem - Grapevine-watcher --

-- GVWatcher.mesa (derived from Chat.mesa)

-- Andrew Birrell, 18-Feb-82 11:26:48

DIRECTORY
Ascii		USING[ CR ],
IODefs		USING[ WriteChar, WriteLine, WriteString ],
LaurelExecDefs,
NameInfoDefs	USING[ Close, ConnectInfo, Enumerate, GetConnect,
		       GetMembers, MemberInfo ],
ProcessDefs	USING[ Abort ],
PupDefs,
PupStream,
PupTypes,
Stream,
Time		USING[ AppendCurrent ];

GVWatcher: MONITOR

IMPORTS IODefs, LaurelExecDefs, NameInfoDefs, ProcessDefs, PupStream,
        Stream, Time =

BEGIN

OPEN IODefs;

serverScript: STRING = "dsdpdhq
";

serverList: STRING = "gv.gv";

DoConnection: PROCEDURE[serverName: STRING] RETURNS[done: BOOLEAN] =
  BEGIN

  addr: PupDefs.PupAddress;
  serverStream: Stream.Handle ← NIL;

  setPageLength: Stream.SubSequenceType = 3;
  timingMark: Stream.SubSequenceType = 5;
  timingMarkReply: Stream.SubSequenceType = 6;

  UserToServer: PROCEDURE =
    BEGIN
    ENABLE ABORTED, PupStream.StreamClosing => GOTO return;
    SendStringToServer[serverScript];
    EXITS return => NULL;
    END;

  AcceptFromServer: PROC[serverStream: Stream.Handle] =
    BEGIN
    userToServer: PROCESS = FORK UserToServer[];
    DO ENABLE
         BEGIN
         ABORTED, PupStream.StreamClosing =>
           { ProcessDefs.Abort[userToServer] };
         UNWIND => JOIN userToServer-- outside the Pup pkg monitor! --;
         END;
       buffer: STRING ← [200];
       why: Stream.CompletionCode;
       mySST: Stream.SubSequenceType;
       [buffer.length, why, mySST] ←
         Stream.GetBlock[serverStream, [@buffer.text, 0, buffer.maxlength]];
       WriteString[buffer];
       IF why = sstChange AND mySST = timingMark
       THEN Stream.SetSST[serverStream, timingMarkReply];
    ENDLOOP;
    END;

  SendStringToServer: PROCEDURE[s: STRING] =
    BEGIN
    FOR i: CARDINAL IN [0 .. s.length) DO
      Stream.PutChar[serverStream, s[i]];
      ENDLOOP;
    Stream.SendNow[serverStream];
    END;

  WriteCRStringHost: PROCEDURE[s: STRING] =
    BEGIN
    WriteChar[Ascii.CR];
    WriteString[s];
    WriteString[serverName];
    END;

  FinishStringWithErrorMsg: PROCEDURE[errorMsg: STRING] =
    BEGIN
    IF errorMsg # NIL THEN
      BEGIN
        WriteString[": "L];
        WriteString[errorMsg];
      END;
    WriteChar['.];
    END;

  done ← FALSE;

  WriteString["

----------
"];
  WriteCRStringHost["Connecting to "L]; WriteString[" ... "L];
  BEGIN
      connect: STRING = [64];
      info: NameInfoDefs.ConnectInfo =
               NameInfoDefs.GetConnect[serverName, connect];
      SELECT info FROM
        allDown =>
          { WriteString["no R-Server available"L]; GOTO failed };
        notFound, group =>
          { WriteString["not an individual"L]; GOTO failed };
        individual =>
          NULL;
      ENDCASE => ERROR;
      -- remove socket number, if any --
      FOR i: CARDINAL DECREASING IN [0..connect.length)
      DO IF connect[i] = '# THEN { connect.length ← i+1; EXIT };
         IF connect[i] = '+ THEN { connect.length ← i; EXIT };
      ENDLOOP;
      WriteString[connect]; WriteString[" ... "L];
      addr.socket ← PupTypes.telnetSoc; -- default socket number --
      PupStream.GetPupAddress[@addr, connect ! PupStream.PupNameTrouble =>
          BEGIN
          WriteString["Can't find host name"L];
          FinishStringWithErrorMsg[e];
          GOTO failed;
          END];
      serverStream ← PupStream.PupByteStreamCreate
        [addr, PupDefs.veryLongWait ! PupStream.StreamClosing =>
          BEGIN
          WriteString["Can't connect to host"L];
          FinishStringWithErrorMsg[text];
          GOTO failed;
          END];
      WriteLine["open."L];
  END;
  Stream.SetInputOptions[serverStream, [TRUE,FALSE,FALSE,FALSE,FALSE] ];
  AcceptFromServer[serverStream ! PupStream.StreamClosing =>
        BEGIN
        WriteCRStringHost["Connection closed by "L];
        FinishStringWithErrorMsg[text];
        CONTINUE
        END ];
  serverStream.delete[serverStream];
  EXITS failed => NULL;
  END--DoConnection--;


WriteHerald: PROCEDURE =
  BEGIN
  s: STRING = [22]; -- 18-Feb-82 11:45:46 PST --
  WriteChar[Ascii.CR];
  WriteString["Grapevine Statistics Watcher, started at "L];
  Time.AppendCurrent[s,TRUE];
  WriteString[s];
  END;  -- of WriteHerald --


-- main program

LaurelExecDefs.MakeMenuCommandCallable[newMail];
LaurelExecDefs.MakeMenuCommandCallable[user];
LaurelExecDefs.MakeMenuCommandCallable[mailFile];
LaurelExecDefs.MakeMenuCommandCallable[display];
LaurelExecDefs.MakeMenuCommandCallable[delete];
LaurelExecDefs.MakeMenuCommandCallable[undelete];
LaurelExecDefs.MakeMenuCommandCallable[moveTo];
LaurelExecDefs.MakeMenuCommandCallable[copy];
WriteHerald[];

BEGIN
  info: NameInfoDefs.MemberInfo = NameInfoDefs.GetMembers[serverList];
  WITH i: info SELECT FROM
    allDown => WriteString["Can't expand server-list"L];
    notFound, individual => WriteString["Incorrect server-list"L];
    group =>
      BEGIN
      NameInfoDefs.Enumerate[i.members, DoConnection];
      NameInfoDefs.Close[i.members];
      END;
  ENDCASE => ERROR;
END;

WriteString["

-----
"];

END.