-- Transport Mechanism Mail Server - Reading Internal Mail.

-- [Indigo]<Grapevine>MS>MSMail.mesa

-- Andrew Birrell,  24-Dec-81 12:05:21 

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

MSMail: MONITOR
   IMPORTS LocalNameDefs, MailboxDefs, PolicyDefs, Process, RetrieveDefs
   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];
   END;

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

FetchMail: ENTRY PROC =
   BEGIN
      DO noMore: BOOLEAN;
         state: RetrieveDefs.ServerState;
         procs: RetrieveDefs.AccessProcs;
         gv:    GV RetrieveDefs.AccessProcs;
         [noMore, state, procs] ← RetrieveDefs.NextServer[handle];
         IF noMore THEN EXIT;
         IF state # notEmpty THEN LOOP;
         WITH gvProcs:procs SELECT FROM GV => gv←gvProcs; ENDCASE => 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];
   ENDLOOP--each new mail--;
   END;

CheckMessage: PROCEDURE[handle: RetrieveDefs.Handle,
                        gv: POINTER TO GV 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.