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