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