-- Copyright (C) 1981, 1984  by Xerox Corporation. All rights reserved. 
-- MSMail.mesa, Transport Mechanism Mail Server - Reading Internal Mail.

-- HGM, 11-Dec-84  0:00:52 
-- Andrew Birrell,  24-Dec-81 12:05:21 

DIRECTORY
  BodyDefs USING [ItemHeader, maxRNameLength, Password, RName],
  EnquiryDefs USING [],
  LocalNameDefs USING [ReadMSName],
  LogDefs USING [WriteLogEntry],
  MailboxDefs USING [FlushCacheAndRemail, InaccessibleArchive],
  PolicyDefs USING [EndOperation, Wait, WaitOperation],
  Process USING [SecondsToTicks],
  RestartDefs USING [],
  RetrieveDefs USING [
    AccessProcs, Failed, Handle, Create, NewUser, NextServer, ServerName,
    ServerState, WaitForMail],
  String USING [AppendString];

MSMail: MONITOR
  IMPORTS
    LocalNameDefs, LogDefs, MailboxDefs, PolicyDefs, Process, RetrieveDefs, String
  EXPORTS EnquiryDefs --LoginMSMail-- , RestartDefs --PROGRAM-- =

  BEGIN

  handle: RetrieveDefs.Handle = RetrieveDefs.Create[pollingInterval: 300];

  LoginMSMail: PUBLIC ENTRY PROC =
    BEGIN
    myName: BodyDefs.RName;
    myPassword: STRING;
    [myName, myPassword, ] ← LocalNameDefs.ReadMSName[];
    RetrieveDefs.NewUser[handle: handle, user: myName, password: myPassword];
    DO
      sName: BodyDefs.RName = [BodyDefs.maxRNameLength];
      noMore: BOOLEAN;
      [noMore, , ] ← RetrieveDefs.NextServer[handle];
      IF noMore THEN EXIT;
      LogInboxSite["MS inbox-site: "L];
      ENDLOOP;
    END;

  LogInboxSite: INTERNAL PROC [s: STRING] =
    BEGIN
    log: STRING = [64];
    server: STRING = [64];
    RetrieveDefs.ServerName[handle, server];
    String.AppendString[log, s];
    server.length ← MIN[server.length, log.maxlength - log.length];
    String.AppendString[log, server];
    LogDefs.WriteLogEntry[log];
    END;

  mbxInterval: CONDITION ← [timeout: Process.SecondsToTicks[300]];
  -- wait on this if mailbox reading fails --

  FetchMail: ENTRY PROC =
    BEGIN
    DO
      noMore: BOOLEAN;
      state: RetrieveDefs.ServerState;
      gv: RetrieveDefs.AccessProcs;
      [noMore, state, gv] ← RetrieveDefs.NextServer[handle];
      IF noMore THEN EXIT;
      IF state # notEmpty THEN LOOP;
      BEGIN
      ENABLE RetrieveDefs.Failed => CONTINUE;
      allGood: BOOLEAN ← TRUE;
      WHILE CheckMessage[handle, @gv] DO
        BEGIN
        DO
          header: BodyDefs.ItemHeader = gv.nextItem[handle];
          name: BodyDefs.RName = [BodyDefs.maxRNameLength];
          SELECT header.type FROM
            LastItem => EXIT;
            reMail =>
              BEGIN
              length: CARDINAL = gv.nextBlock[
                handle, DESCRIPTOR[@(name.text), name.maxlength]];
              name.length ← MIN[name.maxlength, length];
              MailboxDefs.FlushCacheAndRemail[
                name ! MailboxDefs.InaccessibleArchive => GOTO trouble];
              END;
            ENDCASE => NULL;
          ENDLOOP --each item-- ;
        gv.deleteMessage[handle];
        EXITS trouble => allGood ← FALSE;
        END;
        ENDLOOP --each message-- ;
      IF allGood THEN gv.accept[handle] ELSE WAIT mbxInterval;
      END;
      ENDLOOP --each server-- ;
    END;

  ReadMail: PROCEDURE =
    BEGIN
    LoginMSMail[];
    DO
      RetrieveDefs.WaitForMail[handle];
      PolicyDefs.WaitOperation[MSReadMail];
      FetchMail[];
      PolicyDefs.EndOperation[MSReadMail];
      PolicyDefs.Wait[mins: 3];
      ENDLOOP --each new mail-- ;
    END;

  CheckMessage: PROCEDURE [
    handle: RetrieveDefs.Handle, gv: POINTER TO RetrieveDefs.AccessProcs]
    RETURNS [BOOLEAN] =
    BEGIN
    DO
      msgExists, archived, deleted: BOOLEAN;
      [msgExists, archived, deleted] ← gv.nextMessage[handle];
      IF deleted THEN LOOP;
      IF msgExists THEN {gv.startMessage[handle]; RETURN[TRUE]} ELSE RETURN[FALSE]
      ENDLOOP;
    END;

  ReadMailProcess: PROCESS = FORK ReadMail[];


  END.