-- Copyright (C) 1981, 1984 by Xerox Corporation. All rights reserved. -- RetrieveInit.mesa, Transport Mechanism: User: initial stages of mail retrieval/polling -- -- HGM: 11-Dec-84 0:02:10 -- Andrew Birrell 28-Apr-81 14:20:56 -- DIRECTORY BodyDefs USING [Connect, maxConnectLength, RName, Timestamp], NameInfoDefs USING [Close, Enumerate, Expand, ExpandInfo, GetConnect, NameType], Process USING [DisableTimeout, InitializeCondition, InitializeMonitor], ProtocolDefs USING [Init, mailServerOutputSocket, MakeKey], PupDefs, PupTypes, RetrieveDefs USING [MBXState, ServerState], RetrieveXDefs USING [ GVClose, Handle, HandleObject, MBXData, MBXPtr, noMBX, NoteChangedMBX, SendPollProcess, SetMBXState], String USING [AppendString], Storage USING [Node, String, Free, FreeString]; RetrieveInit: MONITOR LOCKS handle USING handle: RetrieveXDefs.Handle IMPORTS NameInfoDefs, Process, ProtocolDefs, PupDefs, RetrieveXDefs, String, Storage EXPORTS RetrieveDefs, RetrieveXDefs = BEGIN Handle: PUBLIC TYPE = RetrieveXDefs.Handle; HandleObject: PUBLIC TYPE = RetrieveXDefs.HandleObject; -- low-level utilities: -- KeepString: PROC [keep: POINTER TO STRING, str: STRING] = BEGIN IF keep­ # NIL THEN Storage.FreeString[keep­]; IF str # NIL THEN BEGIN keep­ ¬ Storage.String[str.length]; String.AppendString[keep­, str]; END; END; -- Global state control by the client: -- Create: PUBLIC PROCEDURE [ pollingInterval: CARDINAL, reportChanges: PROCEDURE [RetrieveDefs.MBXState] ¬ NIL] RETURNS [handle: Handle] = BEGIN handle ¬ Storage.Node[SIZE[HandleObject]]; BEGIN handle.MBXChain ¬ RetrieveXDefs.noMBX; handle.mbxKnown ¬ FALSE; handle.notEmptyMBXCount ¬ 0; handle.unknownMBXCount ¬ 0; -- handle.state ¬ ; handle.spareByte ¬ FALSE; -- handle.spareByteValue ¬; -- handle.header ¬ ; handle.currentMBX ¬ RetrieveXDefs.noMBX; handle.messages ¬ 0; handle.currentStr ¬ NIL; handle.ftpUser ¬ NIL; handle.mbxState ¬ badName; handle.polling ¬ FALSE; handle.pollWanted ¬ FALSE; handle.newPollWanted ¬ FALSE; handle.pollReplying ¬ FALSE; -- handle.mbxStateChange ¬; -- handle.pollCond ¬ ; handle.pollID ¬ [0, 1]; -- handle.sendPoll ¬ ; handle.pollStarted ¬ 0; handle.interval ¬ pollingInterval; handle.changes ¬ reportChanges; handle.userName ¬ NIL; handle.userPwd ¬ NIL; handle.userKey ¬ [0, 0, 0, 0]; END; Process.InitializeMonitor[@(handle.LOCK)]; Process.InitializeCondition[@(handle.pollCond), 0]; -- the polling process adjusts the timeout on handle.pollCond -- Process.InitializeCondition[@(handle.mbxStateChange), 0]; Process.DisableTimeout[@(handle.mbxStateChange)]; END; NewUser: PUBLIC ENTRY PROCEDURE [handle: Handle, user, password: STRING] = BEGIN UnsetMailboxes[handle]; IF user = NIL OR user.length = 0 THEN RetrieveXDefs.SetMBXState[handle, badName] ELSE IF password = NIL OR password.length = 0 THEN RetrieveXDefs.SetMBXState[handle, badPwd] ELSE BEGIN KeepString[@(handle.userName), user]; KeepString[@(handle.userPwd), password]; handle.userKey ¬ ProtocolDefs.MakeKey[handle.userPwd]; RestartPoll[handle]; END; END; Destroy: PUBLIC PROCEDURE [handle: Handle] = BEGIN InnerDestroy[handle]; Storage.Free[handle]; END; InnerDestroy: ENTRY PROCEDURE [handle: Handle] = INLINE BEGIN UnsetMailboxes[handle]; KeepString[@handle.userName, NIL]; KeepString[@handle.userPwd, NIL]; END; RestartPoll: INTERNAL PROCEDURE [handle: Handle] = BEGIN handle.pollID.b ¬ handle.pollID.b + 1; --to ignore old poll replies-- IF NOT handle.polling THEN handle.sendPoll ¬ FORK RetrieveXDefs.SendPollProcess[handle]; handle.polling ¬ handle.pollWanted ¬ TRUE; handle.newPollWanted ¬ TRUE; BROADCAST handle.pollCond; END; UnsetMailboxes: INTERNAL PROCEDURE [handle: Handle] = BEGIN IF handle.polling THEN BEGIN handle.pollWanted ¬ FALSE; BROADCAST handle.pollCond; WHILE handle.polling DO WAIT handle.pollCond ENDLOOP; JOIN handle.sendPoll; END; IF handle.currentMBX # RetrieveXDefs.noMBX THEN BEGIN RetrieveXDefs.GVClose[handle]; handle.currentMBX ¬ RetrieveXDefs.noMBX; END; handle.unknownMBXCount ¬ handle.notEmptyMBXCount ¬ 0; RetrieveXDefs.SetMBXState[handle, unknown]; handle.mbxKnown ¬ FALSE; UNTIL handle.MBXChain = RetrieveXDefs.noMBX DO BEGIN next: RetrieveXDefs.MBXPtr = handle.MBXChain.next; IF handle.MBXChain.name # NIL THEN Storage.FreeString[handle.MBXChain.name]; Storage.Free[handle.MBXChain]; handle.MBXChain ¬ next; END; ENDLOOP; END; defaultHost: STRING ¬ NIL; defaultReg: STRING ¬ NIL; SetMTPRetrieveDefault: PUBLIC --ENTRY?-- PROC [host, reg: STRING] = BEGIN KeepString[@defaultHost, IF reg = NIL THEN NIL ELSE host]; KeepString[@defaultReg, IF host = NIL THEN NIL ELSE reg]; END; FindRegistryAndMailboxes: PUBLIC INTERNAL PROCEDURE [ handle: RetrieveXDefs.Handle] = BEGIN IF handle.MBXChain # RetrieveXDefs.noMBX THEN ERROR; FindGVMailboxes[handle]; END; FindGVMailboxes: INTERNAL PROC [handle: RetrieveXDefs.Handle] = BEGIN Work: INTERNAL PROCEDURE [site: BodyDefs.RName] RETURNS [done: BOOLEAN] = BEGIN done ¬ FALSE; FindAddress[handle, AddMBX[handle, site]]; END; info: NameInfoDefs.ExpandInfo = NameInfoDefs.Expand[handle.userName]; WITH info SELECT FROM allDown => RetrieveXDefs.SetMBXState[handle, cantAuth]; notFound => RetrieveXDefs.SetMBXState[handle, badName]; group => BEGIN -- this case include individual with forwarding NameInfoDefs.Close[members]; handle.mbxKnown ¬ TRUE; END; individual => BEGIN NameInfoDefs.Enumerate[sites, Work]; NameInfoDefs.Close[sites]; handle.mbxKnown ¬ TRUE; END; ENDCASE => ERROR; END; AddMBX: INTERNAL PROCEDURE [handle: RetrieveXDefs.Handle, site: BodyDefs.RName] RETURNS [this: RetrieveXDefs.MBXPtr] = BEGIN mbx: POINTER TO RetrieveXDefs.MBXPtr ¬ @(handle.MBXChain); -- skip to end of mailbox chain -- WHILE mbx­ # RetrieveXDefs.noMBX DO mbx ¬ @(mbx­.next); ENDLOOP; mbx­ ¬ Storage.Node[SIZE[RetrieveXDefs.MBXData]]; this ¬ mbx­; this.name ¬ NIL; KeepString[@(this.name), site]; this.next ¬ RetrieveXDefs.noMBX; this.state ¬ unknown; this.replyWanted ¬ TRUE; handle.unknownMBXCount ¬ handle.unknownMBXCount + 1; IF handle.mbxState = allEmpty THEN RetrieveXDefs.SetMBXState[handle, userOK]; this.addrState ¬ unknown; END; FindAddress: PUBLIC INTERNAL PROC [ handle: RetrieveXDefs.Handle, mbx: RetrieveXDefs.MBXPtr] = BEGIN connect: BodyDefs.Connect = [BodyDefs.maxConnectLength]; IF mbx.addrState # unknown THEN ERROR; SELECT NameInfoDefs.GetConnect[mbx.name, connect] FROM individual => NULL; allDown => GOTO noAddr; group, notFound => GOTO badConnect; ENDCASE => ERROR; mbx­.addr.socket ¬ [0, 0]; PupDefs.GetPupAddress[ @(mbx­.addr), connect ! PupDefs.PupNameTrouble => IF code = errorFromServer THEN GOTO badConnect ELSE GOTO noAddr]; mbx.addr.socket ¬ ProtocolDefs.mailServerOutputSocket; mbx.addrState ¬ known; EXITS badConnect => { RetrieveXDefs.NoteChangedMBX[handle, mbx, empty]; mbx.addrState ¬ bad}; noAddr => NULL; END; WaitForMail: PUBLIC ENTRY PROCEDURE [handle: Handle] = BEGIN WHILE handle.mbxState # notEmpty DO WAIT handle.mbxStateChange ENDLOOP; END; ProtocolDefs.Init[]; END.