-- Transport Mechanism - fetches MTP distribution lists -- -- [Juniper]<DMS>MS>DLFetcher.mesa -- Randy Gobbel 19-May-81 13:28:57 -- -- Mike Schroeder September 19, 1980 12:08 PM -- -- Andrew Birrell 30-Sep-80 16:45:56 -- DIRECTORY Ascii, BodyDefs USING[ maxRNameLength, RName, RNameSize ], FTPDefs USING[CommunicationError, FileHandle, FileInfo, FilePrimitives, FilePrimitivesObject, FileType, FileError, FileSystem, FTPCreateUser, FTPDestroyUser, FTPError, FTPOpenConnection, FTPRetrieveFile, FTPUser, Mode, ProtocolError, PupCommunicationPrimitives, UnidentifiedError ], HeapDefs USING[ HeapAbandonWrite, HeapEndWrite, HeapStartRead, HeapStartWrite, HeapWriteData, HeapWriteRName, ObjectNumber, objectStart, ReaderHandle, SetWriterOffset, WriterHandle ], PupDefs USING[ AppendPupAddress, PupAddress ], PupTypes USING[ mailSoc ], ServerDefs USING[ NoSuchServer, ServerAddr, ServerNotUp ], SiteCacheDefs USING[ RecipientInfo ], String USING[ AppendChar, AppendString, StringBoundsFault ]; DLFetcher: PROGRAM IMPORTS BodyDefs, FTPDefs, HeapDefs, PupDefs, ServerDefs, String EXPORTS SiteCacheDefs = BEGIN OPEN Ascii, FTPDefs, String; FetchDL: PROCEDURE[dlName: BodyDefs.RName, host: STRING, owner: BodyDefs.RName] RETURNS[dl: SiteCacheDefs.RecipientInfo] = BEGIN --variables-- ftpUser: FTPUser; myFilePrimitivesObject: FilePrimitivesObject; writer: HeapDefs.WriterHandle; reader: HeapDefs.ReaderHandle; SyntaxError: SIGNAL = CODE; -- my file system -- MyCreateFileSystem: PROCEDURE [bufferSize: CARDINAL] RETURNS [fileSystem: FileSystem] = {RETURN[NIL]}; MyDestroyFileSystem: PROCEDURE [fileSystem: FileSystem] = {}; MyCloseFile: PROCEDURE [fileSystem: FileSystem, fileHandle: FileHandle, aborted: BOOLEAN] = {}; MyOpenFile: PROCEDURE [fileSystem: FileSystem, file: STRING, mode: Mode, fileTypePlease: BOOLEAN, info: FileInfo] RETURNS [fileHandle: FileHandle, fileType: FileType] = BEGIN IF info.author # NIL AND info.author.length # 0 AND owner # NIL THEN AppendString[owner, info.author ! StringBoundsFault => CONTINUE]; RETURN[NIL, unknown]; END; MyWriteFile: PROCEDURE [fileSystem: FileSystem, fileHandle: FileHandle, receiveBlock: PROC [UNSPECIFIED, POINTER, CARDINAL] RETURNS [CARDINAL], receiveBlockData: UNSPECIFIED] = BEGIN colonSeen, semicolonSeen, boundFault: BOOLEAN ← FALSE; position, bytes: CARDINAL; name: BodyDefs.RName = [BodyDefs.maxRNameLength]; bufferLength: CARDINAL = 100; buffer: PACKED ARRAY [0..2*bufferLength) OF CHARACTER; rListLength: CARDINAL ← 0; NextChar: PROCEDURE RETURNS [ch: CHARACTER] = BEGIN IF bytes = 0 THEN ch ← NUL ELSE BEGIN ch ← buffer[position]; position ← position + 1; IF position = bytes THEN BEGIN bytes ← receiveBlock[receiveBlockData,@buffer,bufferLength]; position ← 0 END; END; END; --NextChar-- position ← 0; bytes ← receiveBlock[receiveBlockData,@buffer,bufferLength]; DO c: CHARACTER; name.length ← 0; DO SELECT (c ← NextChar[]) FROM NUL, ', => IF boundFault THEN SIGNAL SyntaxError ELSE EXIT; '; => IF (NOT colonSeen) OR semicolonSeen THEN SIGNAL SyntaxError ELSE {semicolonSeen ← TRUE; EXIT}; ': => IF colonSeen THEN SIGNAL SyntaxError ELSE {boundFault ← FALSE; name.length ← 0; colonSeen ← TRUE}; SP, TAB, CR => NULL; '( => UNTIL ([] ← NextChar[]) = ') DO ENDLOOP; ENDCASE => AppendChar[name, c ! StringBoundsFault => {name.length ← 0; boundFault ← TRUE; CONTINUE}]; ENDLOOP; IF name.length = 0 THEN BEGIN IF c # NUL THEN LOOP; HeapDefs.SetWriterOffset[writer, HeapDefs.objectStart]; SetRListLength[rListLength]; EXIT -- done END ELSE BEGIN --process name rListLength ← rListLength + BodyDefs.RNameSize[name]; HeapDefs.HeapWriteRName[writer, name]; END; ENDLOOP; END; -- of MyWriteFile -- SaveReader: PROCEDURE[obj: HeapDefs.ObjectNumber] = {reader ← HeapDefs.HeapStartRead[obj]}; SetRListLength: PROCEDURE[l: CARDINAL] = INLINE {HeapDefs.HeapWriteData[writer, [@l, SIZE[CARDINAL]]];}; myFilePrimitivesObject.CreateFileSystem ← MyCreateFileSystem; myFilePrimitivesObject.OpenFile ← MyOpenFile; myFilePrimitivesObject.WriteFile ← MyWriteFile; myFilePrimitivesObject.CloseFile ← MyCloseFile; myFilePrimitivesObject.DestroyFileSystem ← MyDestroyFileSystem; ftpUser ← FTPCreateUser[@myFilePrimitivesObject, PupCommunicationPrimitives[]]; BEGIN -- for exits -- FTPOpenConnection[ftpUser, host, files, NIL ! FTPError => SELECT ftpError FROM -- noSuchHost can't happen -- IN CommunicationError, IN ProtocolError, IN UnidentifiedError => {dl ← [allDown[]]; GOTO done;}; ENDCASE => NULL ]; writer ← HeapDefs.HeapStartWrite[temp]; SetRListLength[0]; [] ← FTPRetrieveFile[ftpUser, NIL, dlName, unknown ! SyntaxError => BEGIN HeapDefs.HeapAbandonWrite[writer]; dl ← [notFound[]]; GOTO done; END; FTPError => BEGIN HeapDefs.HeapAbandonWrite[writer]; SELECT ftpError FROM illegalFilename, noSuchFile => {dl ← [notFound[]]; GOTO done;}; IN CommunicationError, IN FileError, IN ProtocolError, IN UnidentifiedError => {dl ← [allDown[]]; GOTO done;}; ENDCASE => NULL; END ]; HeapDefs.HeapEndWrite[writer, SaveReader]; dl ← [foreign[reader]]; IF owner.length # 0 THEN FOR i:CARDINAL IN [0..dlName.length) DO IF dlName[i] = '↑ THEN BEGIN FOR j:CARDINAL IN [i+1..dlName.length) DO AppendChar[owner, dlName[j]]; ENDLOOP; EXIT; END; REPEAT FINISHED => owner.length ← 0; ENDLOOP; EXITS done => NULL; END; FTPDestroyUser[ftpUser]; END; ForeignDL: PUBLIC PROC[ who: BodyDefs.RName, oldInfo: SiteCacheDefs.RecipientInfo ] RETURNS[ newInfo: SiteCacheDefs.RecipientInfo ] = BEGIN -- If "who" is "thing↑.where", oldInfo is info for "where.foreign" -- WITH old: oldInfo SELECT FROM found => BEGIN addr: PupDefs.PupAddress ← ServerDefs.ServerAddr[old.server ! ServerDefs.NoSuchServer => {newInfo ← [notFound[]]; GOTO noAddr }; ServerDefs.ServerNotUp => {newInfo ← [allDown[]]; GOTO noAddr } ]; host: STRING = [11] --377#377#377--; author: BodyDefs.RName ← [BodyDefs.maxRNameLength]; addr.socket ← PupTypes.mailSoc; PupDefs.AppendPupAddress[host, addr]; newInfo ← FetchDL[who, host, author]; EXITS noAddr => NULL; END; ENDCASE => newInfo ← oldInfo; END; END.