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