-- SendPress.mesa, Edit: Johnsson, 15-Apr-81 18:01:59
DIRECTORY
EFTPDefs USING [
EFTPAbortSending, EFTPFinishSending, EFTPOpenForSending,
EFTPSendBlock, EFTPTimeOut, EFTPTroubleSending],
Inline USING [LongDivMod],
LongString USING [AppendString],
PressFormat USING [DDV, PressPasswd],
PressUtilities USING [hardcopyUserName, ParameterProc],
PupDefs USING [GetPupAddress, PupAddress, PupPackageDestroy, PupPackageMake],
PupTypes USING [eftpReceiveSoc],
Runtime USING [IsBound],
Segments USING [
DeleteSegment, FHandle, SegmentAddress,
SHandle, GetFileLength, LockFile, NewFile, NewSegment, Read,
ReleaseFile, SwapIn, Unlock, UnlockFile],
Streams USING [CreateStream, Destroy, GetBlock, Handle],
System USING [gmtEpoch, GreenwichMeanTime];
SendPress: PROGRAM
IMPORTS EFTPDefs, Inline, LongString, PressUtilities, Runtime, Segments, Streams, PupDefs
EXPORTS PressUtilities =
BEGIN
ServerBusy: PUBLIC SIGNAL = CODE;
ServerTimeout: PUBLIC SIGNAL = CODE;
ServerTrouble: PUBLIC ERROR [message: STRING] = CODE;
wordsPerPressRecord: CARDINAL = 256;
bytesPerPressRecord: CARDINAL = 512;
FileNotPressFormat: PUBLIC ERROR = CODE;
IsPressFile: PUBLIC PROCEDURE [fh: Segments.FHandle]
RETURNS [isPressFile: BOOLEAN, lastPage: CARDINAL] =
BEGIN OPEN Segments;
seg: SHandle;
p: LONG POINTER TO ARRAY OF CARDINAL;
byte: CARDINAL;
[lastPage, byte] ← Inline.LongDivMod[GetFileLength[fh], bytesPerPressRecord];
IF byte # 0 THEN RETURN[FALSE, 0];
seg ← NewSegment[fh, lastPage, 1, Read];
SwapIn[seg];
p ← SegmentAddress[seg];
isPressFile ← p[0] = PressFormat.PressPasswd AND p[1] = lastPage;
Unlock[seg];
LockFile[fh];
DeleteSegment[seg];
UnlockFile[fh];
RETURN
END;
SendPressFile: PUBLIC PROCEDURE [
fileName, host: LONG STRING, copies: CARDINAL ← 1,
parameterProc: PressUtilities.ParameterProc ← NIL] =
BEGIN OPEN Segments;
shortName: STRING = [40];
fh: FHandle;
lastPage: CARDINAL;
isPressFormat: BOOLEAN;
LongString.AppendString[shortName, fileName];
fh ← NewFile[shortName, Read];
[isPressFormat, lastPage] ← IsPressFile[fh];
IF ~isPressFormat THEN BEGIN ReleaseFile[fh]; ERROR FileNotPressFormat END
ELSE
BEGIN
sh: Streams.Handle ← Streams.CreateStream[fh];
SendPressStream[
sh, lastPage, host, copies, parameterProc ! UNWIND => Streams.Destroy[sh]];
Streams.Destroy[sh];
END;
RETURN
END;
SendPressStream: PUBLIC PROCEDURE [
stream: Streams.Handle, nPages: CARDINAL, host: LONG STRING,
copies: CARDINAL ← 1, parameterProc: PressUtilities.ParameterProc ← NIL,
fileName: LONG STRING ← NIL, date: System.GreenwichMeanTime ← System.gmtEpoch] =
BEGIN OPEN EFTPDefs;
ENABLE UNWIND => EFTPAbortSending[""]; -- oops, this may be too often
ba: ARRAY [0..wordsPerPressRecord) OF WORD;
buffer: POINTER TO ARRAY [0..wordsPerPressRecord) OF WORD ← @ba;
who: PupDefs.PupAddress ← [, , PupTypes.eftpReceiveSoc];
shortName: STRING = [40];
PupDefs.PupPackageMake[];
LongString.AppendString[shortName, host];
PupDefs.GetPupAddress[@who, shortName];
EFTPOpenForSending[
who ! EFTPTimeOut => {SIGNAL ServerTimeout; RESUME};
EFTPTroubleSending => {
IF e = eftpReceiverBusyAbort THEN {SIGNAL ServerBusy; RETRY};
ERROR ServerTrouble[s]}];
IF parameterProc # NIL THEN
BEGIN
bytes: CARDINAL ← parameterProc[buffer];
IF bytes # 0 THEN EFTPSendBlock[buffer, bytes !
EFTPTimeOut => ERROR ServerTrouble["Timeout"L];
EFTPTroubleSending => ERROR ServerTrouble[s]];
END;
FOR i: CARDINAL IN [1..nPages] DO
SELECT Streams.GetBlock[stream, buffer, wordsPerPressRecord] FROM
wordsPerPressRecord =>
BEGIN
IF i = nPages THEN FillInDDV[LOOPHOLE[buffer], copies];
EFTPSendBlock[buffer, bytesPerPressRecord !
EFTPTimeOut => ERROR ServerTrouble["Timeout"L];
EFTPTroubleSending => ERROR ServerTrouble[s]];
END;
0 => EXIT;
ENDCASE => ERROR FileNotPressFormat; -- must be whole records
ENDLOOP;
EFTPFinishSending[];
PupDefs.PupPackageDestroy[];
END;
FillInDDV: PROCEDURE [ddv: POINTER TO PressFormat.DDV, copies: CARDINAL] =
BEGIN OPEN PressUtilities;
IF ddv.Passwd # PressFormat.PressPasswd THEN ERROR FileNotPressFormat;
IF Runtime.IsBound[@hardcopyUserName] AND hardcopyUserName # NIL AND
hardcopyUserName.length < LENGTH[ddv.CreatStr]*2 THEN {
p: POINTER TO PACKED ARRAY [0..0) OF CHARACTER = LOOPHOLE[@ddv.CreatStr];
FOR i: CARDINAL IN [0..hardcopyUserName.length) DO p[i+1] ← hardcopyUserName[i] ENDLOOP;
p[0] ← LOOPHOLE[hardcopyUserName.length]};
ddv.fCopy ← 1;
ddv.lCopy ← copies;
END;
END.