home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Power Programming
/
powerprogramming1994.iso
/
progtool
/
pibterm
/
pibt41s4.arc
/
RECEIVK1.MOD
< prev
next >
Wrap
Text File
|
1988-02-26
|
29KB
|
688 lines
(*----------------------------------------------------------------------*)
(* Receive_Kermit_File --- Download file using Kermit *)
(*----------------------------------------------------------------------*)
PROCEDURE Receive_Kermit_File;
(*----------------------------------------------------------------------*)
(* *)
(* Procedure: Receive_Kermit_File *)
(* *)
(* Purpose: Downloads file to PC using Kermit protocol *)
(* *)
(* Calling Sequence: *)
(* *)
(* Receive_Kermit_File; *)
(* *)
(*----------------------------------------------------------------------*)
CONST
Receive_Quit_Item = 9;
VAR
Buffer_Pos : INTEGER;
Buffer_Size : INTEGER;
Write_Count : INTEGER;
Err : INTEGER;
Local_Save : Saved_Screen_Ptr;
Local_Save_2 : Saved_Screen_Ptr;
Kermit_Menu : Menu_Type;
I : INTEGER;
J : INTEGER;
Kermit_Done : BOOLEAN;
Menu_Choice : INTEGER;
Host_Count : INTEGER;
Long_Buffer : BOOLEAN;
Buffer_Length : INTEGER;
Write_Buffer : File_Handle_Buffer_Ptr;
Receiving_File : BOOLEAN;
Cur_Drive : CHAR;
Cur_Path : AnyStr;
Buffer_Total : LONGINT;
Abort_Done : BOOLEAN;
Toss_File : BOOLEAN;
Full_Name : AnyStr;
Do_A_Receive : BOOLEAN;
Remote_Comm : AnyStr;
Buffer_Num_Actual : LONGINT;
Total_Time : LONGINT;
(*----------------------------------------------------------------------*)
(* Kermit_Construct_Message --- Construct message packet *)
(*----------------------------------------------------------------------*)
PROCEDURE Kermit_Construct_Message( S: AnyStr );
(*----------------------------------------------------------------------*)
(* *)
(* Procedure: Kermit_Construct_Message *)
(* *)
(* Purpose: Constructs message packet *)
(* *)
(* Calling Sequence: *)
(* *)
(* Kermit_Construct_Message( S: AnyStr ); *)
(* *)
(* S --- Message to be constructed *)
(* *)
(*----------------------------------------------------------------------*)
VAR
LS : INTEGER;
BEGIN (* Kermit_Construct_Message *)
LS := LENGTH( S );
MOVE( S[1], Send_Packet_Ptr^[4], LS );
Send_Packet_Length := LS + 3;
Build_Packet;
Send_Packet;
END (* Kermit_Construct_Message *);
(*----------------------------------------------------------------------*)
(* Expand_Packet_To_String --- Expand data in Kermit packet to string *)
(*----------------------------------------------------------------------*)
FUNCTION Expand_Packet_To_String( Rec_Packet_Ptr : Kermit_Packet_Ptr;
Rec_Packet_Length : INTEGER ) : AnyStr;
(*----------------------------------------------------------------------*)
(* *)
(* Function: Expand_Packet_To_String *)
(* *)
(* Purpose: Expands data in Kermit packet to a string *)
(* *)
(* Calling Sequence: *)
(* *)
(* Rec_Str := Expand_Packet_To_String( Rec_Packet_Ptr : *)
(* Kermit_Packet_Ptr; *)
(* Rec_Packet_Length : *)
(* INTEGER; *)
(* ) : AnyStr; *)
(* *)
(* Rec_Packet_Ptr --- points to unexpanded packet data *)
(* Rec_Packet_Length --- length of unexpanded data *)
(* Rec_Str --- resultant expanded data as string *)
(* *)
(*----------------------------------------------------------------------*)
VAR
InPos : INTEGER;
OutPos : INTEGER;
Q8Bit : BOOLEAN;
Temp : CHAR;
B_Temp : BYTE ABSOLUTE Temp;
Temp2 : CHAR;
Repeat_Count : INTEGER;
I : INTEGER;
Rec_Packet_String : AnyStr;
BEGIN (* Expand_Packet_To_String *)
(* Initialize *)
InPos := 1;
OutPos := 0;
WHILE ( ( InPos <= Rec_Packet_Length ) AND ( OutPos < 256 ) ) DO
BEGIN
(* Repeat count 1 by default *)
Repeat_Count := 1;
(* Get next character in packet *)
Temp := Rec_Packet_Ptr^[ InPos ];
(* Check for repeat data character *)
IF Repeating THEN
IF ( Temp = His_Repeat_Char ) THEN
BEGIN
InPos := SUCC( InPos );
Repeat_Count := ORD( Rec_Packet_Ptr^[ InPos ] ) - 32;
InPos := SUCC( InPos );
Temp := Rec_Packet_Ptr^[ InPos ];
END;
(* Check for 8-bit quote character *)
IF ( Temp = His_Quote_8_Char ) AND Quoting THEN
BEGIN
Q8Bit := TRUE;
InPos := SUCC( InPos );
Temp := Rec_Packet_Ptr^[ InPos ];
END
ELSE
Q8Bit := FALSE;
(* Check for control quote character *)
IF ( Temp = His_Quote_Char ) THEN
BEGIN
InPos := SUCC( InPos );
Temp := Rec_Packet_Ptr^[ InPos ];
(* Convert to control character EXCEPT *)
(* for quoting characters. *)
Temp2 := CHR( B_Temp AND $7F );
IF ( Temp2 <> His_Quote_Char ) AND
( NOT ( Repeating AND ( Temp2 = His_Repeat_Char ) ) ) AND
( NOT ( Quoting AND ( Temp2 = His_Quote_8_Char ) ) ) THEN
B_Temp := B_Temp XOR 64;
END;
(* Turn on 8th bit if required *)
IF Q8Bit THEN
B_Temp := B_Temp OR $80;
(* Append character to output string. *)
(* If repeat count, add it in given *)
(* number of times. *)
FOR I := 1 TO Repeat_Count DO
BEGIN
OutPos := SUCC( OutPos );
IF ( OutPos < 256 ) THEN
Rec_Packet_String[ OutPos ] := Temp;
END;
(* Point to next input character *)
InPos := SUCC( InPos );
END (* WHILE *);
Rec_Packet_String[0] := CHR( MIN( OutPos , 255 ) );
Expand_Packet_To_String := Rec_Packet_String;
END (* Expand_Packet_To_String *);
(*----------------------------------------------------------------------*)
(* Expand_Packet --- Expand data in Kermit packet *)
(*----------------------------------------------------------------------*)
FUNCTION Expand_Packet( Rec_Packet_Ptr : Kermit_Packet_Ptr;
Rec_Packet_Length : INTEGER ) : BOOLEAN;
(*----------------------------------------------------------------------*)
(* *)
(* Function: Expand_Packet *)
(* *)
(* Purpose: Expands data in Kermit packet *)
(* *)
(* Calling Sequence: *)
(* *)
(* OK := Expand_Packet : BOOLEAN; *)
(* *)
(*----------------------------------------------------------------------*)
VAR
InPos : INTEGER;
Q8Bit : BOOLEAN;
Temp : CHAR;
B_Temp : BYTE ABSOLUTE Temp;
Temp2 : CHAR;
Repeat_Count : INTEGER;
I : INTEGER;
L : INTEGER;
Err : INTEGER;
Write_Count : INTEGER;
Len_Packet : INTEGER;
BEGIN (* Expand_Packet *)
(* Start of received packet *)
InPos := 1;
Len_Packet := Rec_Packet_Length;
Expand_Packet := TRUE;
Err := 0;
WHILE ( InPos <= Len_Packet ) DO
BEGIN
(* Repeat count 1 by default *)
Repeat_Count := 1;
(* Get next character in packet *)
Temp := Rec_Packet_Ptr^[ InPos ];
(* Check for repeat data character *)
IF Repeating THEN
IF ( Temp = His_Repeat_Char ) THEN
BEGIN
InPos := SUCC( InPos );
Repeat_Count := ORD( Rec_Packet_Ptr^[ InPos ] ) - 32;
InPos := SUCC( InPos );
Temp := Rec_Packet_Ptr^[ InPos ];
END;
(* Check for 8-bit quote character *)
IF ( Temp = His_Quote_8_Char ) AND Quoting THEN
BEGIN
Q8Bit := TRUE;
InPos := SUCC( InPos );
Temp := Rec_Packet_Ptr^[ InPos ];
END
ELSE
Q8Bit := FALSE;
(* Check for control quote character *)
IF ( Temp = His_Quote_Char ) THEN
BEGIN
InPos := SUCC( InPos );
Temp := Rec_Packet_Ptr^[ InPos ];
(* Convert to control character EXCEPT *)
(* for quoting characters. *)
Temp2 := CHR( B_Temp AND $7F );
IF ( Temp2 <> His_Quote_Char ) AND
( NOT ( Repeating AND ( Temp2 = His_Repeat_Char ) ) ) AND
( NOT ( Quoting AND ( Temp2 = His_Quote_8_Char ) ) ) THEN
B_Temp := B_Temp XOR 64;
END;
(* Turn on 8th bit if required *)
IF Q8Bit THEN
B_Temp := B_Temp OR $80;
(* Append character to output buffer. *)
(* If repeat count, add it in given *)
(* number of times. *)
IF ( NOT Kermit_Screen_Write ) THEN
FOR I := 1 TO Repeat_Count DO
BEGIN
IF ( Buffer_Pos >= Buffer_Size ) THEN
BEGIN
BlockWrite( XFile, Write_Buffer^, Buffer_Size, Write_Count );
Err := Int24Result;
Buffer_Pos := 0;
Expand_Packet := ( Err = 0 ) AND
( Write_Count = Buffer_Size );
END;
Buffer_Pos := SUCC( Buffer_Pos );
Write_Buffer^[Buffer_Pos] := B_Temp;
END
ELSE
FOR I := 1 TO Repeat_Count DO
Display_Character( Temp );
(* Increment received bytes count *)
Buffer_Num := Buffer_Num + Repeat_Count;
Buffer_Num_Actual := Buffer_Num_Actual + 1;
(* Point to next input character *)
InPos := SUCC( InPos );
END (* WHILE *);
END (* Expand_Packet *);
(*----------------------------------------------------------------------*)
(* Kermit_Receive_Header --- get file header packet for Kermit *)
(*----------------------------------------------------------------------*)
PROCEDURE Kermit_Receive_Header;
(*----------------------------------------------------------------------*)
(* *)
(* Procedure: Kermit_Receive_Header *)
(* *)
(* Purpose: Get file header packet for Kermit *)
(* *)
(* Calling Sequence: *)
(* *)
(* Kermit_Receive_Header; *)
(* *)
(* Remarks: *)
(* *)
(* This procedure receives packets and looks for the file header *)
(* packet. If a good file header packet is found, this routine *)
(* tries to open the file. If the file opens successfully, the *)
(* state changes to 'Receive_File'. If the file cannot be *)
(* opened (the file open procedure attempts to create a unique *)
(* filename if the specified file already exists) an error *)
(* packet is returned to the requesting kermit. This procedure *)
(* also handles 'Send Init' and 'Break' packets as specified in *)
(* the Kermit Protocol Manual. *)
(* *)
(*----------------------------------------------------------------------*)
VAR
Try : INTEGER;
Get_Pack : BOOLEAN;
Rec_Packet_String : AnyStr;
BEGIN (* Kermit_Receive_Header *)
(* If we already have header, use it *)
Get_Pack := ( Kermit_Packet_Type <> Header_Pack ) AND
( Kermit_Packet_Type <> Text_Pack );
REPEAT (* Get a packet *)
IF Get_Pack THEN
Receive_Packet;
Get_Pack := TRUE;
(* If recognized, perform required *)
(* function based upon packet type *)
IF Packet_OK THEN
CASE Kermit_Packet_Type OF
Header_Pack : BEGIN
(* Try opening file *)
Kermit_Screen_Write := FALSE;
Rec_Packet_String := Expand_Packet_To_String(
Rec_Packet_Ptr ,
Rec_Packet_Length );
Open_File( Write_Open,
Rec_Packet_String,
Full_Name );
(* If OK, then shift to receive state *)
IF Open_OK THEN
BEGIN
Buffer_Pos := 0;
Toss_File := FALSE;
Packet_Num := Rec_Packet_Num;
Display_Kermit_Message('Receiving ' +
Rec_Packet_String );
Send_ACK;
Kermit_State := Receive_File;
END
(* Not ok open -- send error packet *)
(* to remote Kermit. *)
ELSE
BEGIN
Kermit_Construct_Message( 'ECannot open file' );
Kermit_Abort := TRUE;
IF ( Kermit_Abort_Level = No_Abort ) THEN
Kermit_Abort_Level := One_File;
Display_Kermit_Message( 'Cannot open file: '
+ Rec_Packet_String );
END;
END;
Text_Pack : BEGIN
Kermit_Screen_Write := TRUE;
Buffer_Pos := 0;
File_Open := FALSE;
Toss_File := FALSE;
Packet_Num := Rec_Packet_Num;
Send_ACK;
Kermit_State := Receive_File;
IF Display_Status THEN
BEGIN
Display_Status := FALSE;
Restore_Screen_And_Colors( Kermit_Local_Save );
END;
PibTerm_Window( 1, 1, Max_Screen_Col, Max_Screen_Line - 1 );
Clear_Window;
GoToXY( 1 , 1 );
END;
Send_Pack : BEGIN
Packet_Num := Rec_Packet_Num;
Send_ACK;
END;
Break_Pack : BEGIN
Packet_Num := Rec_Packet_Num;
Send_ACK;
Receive_Done := TRUE;
Display_Kermit_Message('Completed.');
END;
End_Pack : BEGIN
Packet_Num := Rec_Packet_Num;
Send_ACK;
END;
ELSE BEGIN
Kermit_Abort := TRUE;
IF ( Kermit_Abort_Level = No_Abort ) THEN
Kermit_Abort_Level := One_File;
Packet_Num := Rec_Packet_Num;
Kermit_Construct_Message( 'EUnknown packet type.' );
Display_Kermit_Message('Error - Unknown packet type.');
END;
END (* CASE *);
IF ( Kermit_Abort_Level = Entire_Protocol ) THEN
Display_Kermit_Message('Cancelling Kermit protocol.')
ELSE IF ( Kermit_Abort_Level = All_Files ) THEN
BEGIN
Packet_Num := ( Packet_Num + 1 ) MOD 64;
Send_Packet_Ptr^[4] := 'B';
Send_Packet_Length := 4;
Build_Packet;
Send_Packet;
Display_Kermit_Message('Cancelling transfer of current batch of files.');
END
ELSE
IF ( NOT Packet_OK ) THEN
BEGIN
Try := SUCC( Try );
Packets_Bad := Packets_Bad + 1;
Send_NAK;
IF ( Try = Kermit_MaxTry ) THEN
BEGIN
Kermit_Abort := TRUE;
IF ( Kermit_Abort_Level = No_Abort ) THEN
Kermit_Abort_Level := One_File;
Packet_Num := 0;
Kermit_Construct_Message( 'ECannot get file header.' );
Display_Kermit_Message('Cannot get file header.');
END;
END;
UNTIL Kermit_Abort OR ( Kermit_State = Receive_File ) OR Receive_Done;
END (* Kermit_Receive_Header *);
(*----------------------------------------------------------------------*)
(* Kermit_Get --- Initiate server mode receive for Kermit *)
(*----------------------------------------------------------------------*)
PROCEDURE Kermit_Get;
(*----------------------------------------------------------------------*)
(* *)
(* Procedure: Kermit_Get *)
(* *)
(* Purpose: Initiate server mode receive for Kermit *)
(* *)
(* Calling Sequence: *)
(* *)
(* Kermit_Get; *)
(* *)
(* Remarks: *)
(* *)
(* This procedure attempts to initiate a server receive. *)
(* First, Kermit_Get sends an 'R' packet with the selected *)
(* file name. If a valid 'Send Init' packet is received, then *)
(* the Kermit state is changed to Receive_Header. If a valid *)
(* 'Send Init' is NOT received, then an error packet is sent to *)
(* the other Kermit after the specified number of retries. *)
(* *)
(*----------------------------------------------------------------------*)
VAR
Try : INTEGER;
Init_OK : BOOLEAN;
BEGIN (* Kermit_Get *)
(* Send 'Get File' packet *)
Packet_Num := 0;
Try := LENGTH( FileName );
His_Chk_Type := '1';
Send_Packet_Ptr^[4] := 'R';
MOVE( FileName[1], Send_Packet_Ptr^[5], Try );
Send_Packet_Length := Try + 4;
Build_Packet;
Try := 0;
REPEAT
Send_Packet;
Receive_Packet;
IF Packet_OK AND ( Kermit_Packet_Type = Send_Pack ) THEN
BEGIN
Packet_Num := Rec_Packet_Num;
Check_Init( Init_OK );
IF Init_OK THEN
BEGIN
Send_ACK;
Kermit_State := Receive_Header;
END;
END;
IF ( Kermit_Packet_Type = Error_Pack ) THEN
BEGIN
Display_Kermit_Message( Expand_Packet_To_String( Rec_Packet_Ptr,
Rec_Packet_Length ) );
Kermit_Abort := TRUE;
IF ( Kermit_Abort_Level = No_Abort ) THEN
Kermit_Abort_Level := One_File;
END;
IF NOT ( Init_OK OR Kermit_Abort ) THEN
BEGIN
Packets_Bad := Packets_Bad + 1;
Try := SUCC( Try );
Send_NAK;
END;
IF ( ( Try = Kermit_MaxTry ) OR Kermit_Abort ) THEN
BEGIN
Kermit_Abort := TRUE;
IF ( Kermit_Abort_Level = No_Abort ) THEN
Kermit_Abort_Level := One_File;
Kermit_Construct_Message( 'ECannot get send init packet.' );
Display_Kermit_Message('Cannot get send_init packet.');
END;
UNTIL Kermit_Abort OR ( Kermit_State = Receive_Header );
END (* Kermit_Get *);
(*----------------------------------------------------------------------*)
(* Kermit_Receive_Init --- get Send Init packet for Kermit receives *)
(*----------------------------------------------------------------------*)
PROCEDURE Kermit_Receive_Init;
(*----------------------------------------------------------------------*)
(* *)
(* Procedure: Kermit_Receive_Init *)
(* *)
(* Purpose: get 'Send Init' for Kermit receives *)
(* *)
(* Calling Sequence: *)
(* *)
(* Kermit_Receive_Init; *)
(* *)
(* Remarks: *)
(* *)
(* This procedure waits for a 'Send Init' packet; it will hang *)
(* here until a valid 'Send Init' packet is received, or an *)
(* Alt-R is entered at the keyboard to abort the transfer. *)
(* *)
(*----------------------------------------------------------------------*)
VAR
Try : INTEGER;
Init_OK : BOOLEAN;
Save_CHK: CHAR;
Get_Pack: BOOLEAN;
BEGIN (* Kermit_Receive_Init *)
(* Initialize display *)
Initialize_Display;
Try := 0;
Get_Pack := ( Kermit_Packet_Type <> Send_Pack );
REPEAT
(* Init packet always has block *)
(* check type one. *)
IF Get_Pack THEN
BEGIN
Save_CHK := His_Chk_Type;
His_Chk_Type := '1';
Receive_Packet;
His_Chk_Type := Save_CHK;
END;
Get_Pack := TRUE;
IF Packet_OK AND ( Kermit_Packet_Type = Send_Pack ) THEN
BEGIN
Packet_Num := Rec_Packet_Num;
Check_Init( Init_OK );
IF Init_OK THEN
BEGIN
Send_ACK;
Kermit_State := Receive_Header;
END
ELSE
BEGIN
Packets_Bad := Packets_Bad + 1;
IF ( NOT Kermit_Retry ) THEN
Send_NAK;
Try := SUCC( Try );
IF ( Try = Kermit_MaxTry ) THEN
BEGIN
Kermit_Abort := TRUE;
IF ( Kermit_Abort_Level = No_Abort ) THEN
Kermit_Abort_Level := One_File;
Kermit_Construct_Message( 'ECannot get send init packet.' );
Display_Kermit_Message('Cannot get send_init packet.');
END;
END;
END;
UNTIL Kermit_Abort OR ( Kermit_State = Receive_Header );
END (* Kermit_Receive_Init *);