home *** CD-ROM | disk | FTP | other *** search
/ Power Programming / powerprogramming1994.iso / progtool / pibterm / pibt41s4.arc / SENDKER1.MOD < prev    next >
Text File  |  1988-01-23  |  29KB  |  715 lines

  1. (*----------------------------------------------------------------------*)
  2. (*              Send_Kermit_File --- Upload file using Kermit           *)
  3. (*----------------------------------------------------------------------*)
  4.  
  5. PROCEDURE Send_Kermit_File;
  6.  
  7. (*----------------------------------------------------------------------*)
  8. (*                                                                      *)
  9. (*     Procedure:  Send_Kermit_File                                     *)
  10. (*                                                                      *)
  11. (*     Purpose:    Uploads file to remote using Kermit protocol         *)
  12. (*                                                                      *)
  13. (*     Calling Sequence:                                                *)
  14. (*                                                                      *)
  15. (*        Send_Kermit_File;                                             *)
  16. (*                                                                      *)
  17. (*----------------------------------------------------------------------*)
  18.  
  19. CONST
  20.    EOF_Packet   = 'Z';
  21.    Break_Packet = 'B';
  22.  
  23. CONST
  24.    Send_Quit_Item = 6;
  25.  
  26. VAR
  27.    Buffer_Pos    : INTEGER;
  28.    Buffer_Size   : INTEGER;
  29.    Write_Count   : INTEGER;
  30.    Err           : INTEGER;
  31.    Local_Save    : Saved_Screen_Ptr;
  32.    Local_Save_2  : Saved_Screen_Ptr;
  33.    File_Pattern  : AnyStr;
  34.    Stop_Send     : BOOLEAN;
  35.    File_Entry    : SearchRec;
  36.    OK_File       : BOOLEAN;
  37.    Try           : INTEGER;
  38.    Send_Done     : BOOLEAN;
  39.    Kermit_Menu   : Menu_Type;
  40.    I             : INTEGER;
  41.    J             : INTEGER;
  42.    Kermit_Done   : BOOLEAN;
  43.    Host_Count    : INTEGER;
  44.    Menu_Choice   : INTEGER;
  45.    Long_Buffer   : BOOLEAN;
  46.    Buffer_Length : INTEGER;
  47.    Read_Buffer   : File_Handle_Buffer_Ptr;
  48.    No_More_Chars : BOOLEAN;
  49.    Buffer_Total  : REAL;
  50.    Full_Name     : AnyStr;
  51.    Buffer_Num_Actual : REAL;
  52.    Total_Time    : REAL;
  53.  
  54. (*----------------------------------------------------------------------*)
  55. (*       Get_Kermit_File_Name --- Construct file name to Kermit form    *)
  56. (*----------------------------------------------------------------------*)
  57.  
  58. PROCEDURE Get_Kermit_File_Name( VAR OK_File : BOOLEAN );
  59.  
  60. (*----------------------------------------------------------------------*)
  61. (*                                                                      *)
  62. (*     Procedure:  Get_Kermit_File_Name                                 *)
  63. (*                                                                      *)
  64. (*     Purpose:    Gets name of next file to be transferred             *)
  65. (*                                                                      *)
  66. (*     Calling Sequence:                                                *)
  67. (*                                                                      *)
  68. (*        Get_Kermit_File_Name( VAR OK_File : BOOLEAN );                *)
  69. (*                                                                      *)
  70. (*           OK_File --- TRUE if file is OK to be transferred           *)
  71. (*                                                                      *)
  72. (*     Calls:                                                           *)
  73. (*                                                                      *)
  74. (*        Scan_Xfer_List                                                *)
  75. (*                                                                      *)
  76. (*     Remarks:                                                         *)
  77. (*                                                                      *)
  78. (*        The global variable 'FileName' gets the file name.            *)
  79. (*                                                                      *)
  80. (*----------------------------------------------------------------------*)
  81.  
  82. VAR
  83.    I: INTEGER;
  84.  
  85. BEGIN (* Get_Kermit_File_Name *)
  86.  
  87.    FileName := File_Entry.Name;
  88.  
  89.    OK_File := ( File_Entry.Attr AND
  90.                 ( VolumeID + Directory ) = 0 );
  91.  
  92.                                    (* If host mode, make sure file *)
  93.                                    (* is on xferlist!              *)
  94.    IF Host_Mode THEN
  95.       IF ( Privilege <> 'S' ) THEN
  96.          OK_File := OK_File AND ( Scan_Xfer_List( FileName ) > 0 );
  97.  
  98. END   (* Get_Kermit_File_Name *);
  99.  
  100. (*----------------------------------------------------------------------*)
  101. (*                 Get_File_Data --- get data from file                 *)
  102. (*----------------------------------------------------------------------*)
  103.  
  104. PROCEDURE Get_File_Data;
  105.  
  106. (*----------------------------------------------------------------------*)
  107. (*                                                                      *)
  108. (*     Procedure:  Get_File_Data                                        *)
  109. (*                                                                      *)
  110. (*     Purpose:    Gets next buffer of data from file being uploaded    *)
  111. (*                                                                      *)
  112. (*     Calling Sequence:                                                *)
  113. (*                                                                      *)
  114. (*        Get_File_Data;                                                *)
  115. (*                                                                      *)
  116. (*     Calls:                                                           *)
  117. (*                                                                      *)
  118. (*     Remarks:                                                         *)
  119. (*                                                                      *)
  120. (*        The global variable 'Send_Packet_Ptr^' gets the next batch    *)
  121. (*        of data.  'Read_Buffer^' holds the current 'Buffer_Size'      *)
  122. (*        characters read in.                                           *)
  123. (*                                                                      *)
  124. (*----------------------------------------------------------------------*)
  125.  
  126. VAR
  127.    Char_Count   : INTEGER;
  128.    Save_Char    : Byte;
  129.    Temp_Data    : STRING[120];
  130.    End_Of_File  : BOOLEAN;
  131.    Err          : INTEGER;
  132.    NRead        : INTEGER;
  133.    Ascii_File   : BOOLEAN;
  134.    L            : INTEGER;
  135.    MaxData      : INTEGER;
  136.    Repeat_Count : INTEGER;
  137.    Packet_Count : INTEGER;
  138.    EChar_Count  : INTEGER;
  139.  
  140. (*----------------------------------------------------------------------*)
  141.  
  142. FUNCTION NextChar: BYTE;
  143.  
  144. BEGIN (* NextChar *)
  145.                                    (* See if current buffer exhausted *)
  146.  
  147.    IF ( Buffer_Pos >= Buffer_Size ) AND ( NOT End_Of_File ) THEN
  148.       BEGIN
  149.                                    (* Read Sector_size chars from file  *)
  150.                                    (* to be sent.                       *)
  151.  
  152.          BlockRead( XFile, Read_Buffer^, Buffer_Size, NRead );
  153.  
  154.          Err         := Int24Result;
  155.          Buffer_Pos  := 0;
  156.          Buffer_Size := NRead;
  157.          End_Of_File := ( NRead <= 0 );
  158.  
  159.       END;
  160.                                    (* See if anything to be sent *)
  161.  
  162.    IF ( Buffer_Pos < Buffer_Size ) THEN
  163.       BEGIN
  164.                                    (* Pick up next character *)
  165.  
  166.          INC( Buffer_Pos );
  167.          NextChar := Read_Buffer^[ Buffer_Pos ];
  168.  
  169.          INC( Char_Count );
  170.          No_More_Chars := FALSE;
  171.  
  172.       END
  173.    ELSE
  174.       BEGIN
  175.          No_More_Chars := TRUE;
  176.          NextChar      := ORD( ^Z );
  177.       END;
  178.  
  179. END   (* NextChar *);
  180.  
  181. (*----------------------------------------------------------------------*)
  182.  
  183. FUNCTION PeekChar : BYTE;
  184.  
  185. BEGIN (* PeekChar *)
  186.  
  187.    IF ( Buffer_Pos < Buffer_Size ) THEN
  188.       PeekChar := Read_Buffer^[Buffer_Pos + 1]
  189.    ELSE
  190.       PeekChar := ( Read_Buffer^[Buffer_Pos] + 1 ) AND $FF;
  191.  
  192. END   (* PeekChar *);
  193.  
  194. (*----------------------------------------------------------------------*)
  195.  
  196. PROCEDURE Encode_Kermit_Character( A: BYTE );
  197.  
  198. VAR
  199.    A8: BYTE;
  200.    A7: BYTE;
  201.  
  202. BEGIN (* Encode_Kermit_Character *)
  203.  
  204.                                    (* Separate 7 bits from high bit *)
  205.    A7 := A AND $7F;
  206.    A8 := A AND $80;
  207.                                    (* Perform 8th bit quoting *)
  208.    IF Quoting THEN
  209.       IF ( A8 <> 0 ) THEN
  210.          BEGIN
  211.             INC( Packet_Count );
  212.             Send_Packet_Ptr^[Packet_Count] := Kermit_Quote_8_Char;
  213.             A                              := A7;
  214.          END;
  215.                                    (* Perform control quoting *)
  216.  
  217.    IF ( A7 < SP ) OR ( A7 = DEL ) THEN
  218.       BEGIN
  219.          INC( Packet_Count );
  220.          Send_Packet_Ptr^[Packet_Count] := Kermit_Quote_Char;
  221.          A                              := A XOR 64;
  222.       END;
  223.                                    (* Prefix the control prefix *)
  224.  
  225.    IF ( A7 = ORD( Kermit_Quote_Char ) ) THEN
  226.       BEGIN
  227.          INC( Packet_Count );
  228.          Send_Packet_Ptr^[Packet_Count] := Kermit_Quote_Char;
  229.       END;
  230.  
  231.    IF Repeating THEN
  232.       IF ( A7 = ORD( His_Repeat_Char ) ) THEN
  233.          BEGIN
  234.             INC( Packet_Count );
  235.             Send_Packet_Ptr^[Packet_Count] := Kermit_Quote_Char;
  236.          END;
  237.                                    (* Prefix the 8-bit quote char *)
  238.    IF Quoting THEN
  239.       IF ( A7 = ORD( Kermit_Quote_8_Char ) ) THEN
  240.          BEGIN
  241.             INC( Packet_Count );
  242.             Send_Packet_Ptr^[Packet_Count] := Kermit_Quote_Char;
  243.          END;
  244.                                    (* Finally, insert either 8-bit or  *)
  245.                                    (* 7-bit version of character into  *)
  246.                                    (* packet.                          *)
  247.  
  248.    INC( Packet_Count );
  249.    Send_Packet_Ptr^[Packet_Count] := CHR( A );
  250.  
  251.                                    (* Increment count of encoded chars *)
  252.    INC( EChar_Count );
  253.  
  254. END   (* Encode_Kermit_Character *);
  255.  
  256. (*----------------------------------------------------------------------*)
  257.  
  258. BEGIN (* Get_File_Data *)
  259.                                    (* Packet length        *)
  260.    IF Kermit_Do_Long_Blocks THEN
  261.       BEGIN
  262.          Packet_Count       := 7;
  263.          MaxData            := His_Kermit_MaxLX1 * 95 + His_Kermit_MaxLX2 - 3;
  264.       END
  265.    ELSE
  266.       BEGIN
  267.          Packet_Count       := 4;
  268.          MaxData            := Kermit_Packet_Size;
  269.       END;
  270.                                    (* Maximum length allowed for data *)
  271.  
  272.    MaxData := MaxData - 3 - ( ORD( Kermit_Chk_Type ) - ORD('0') );
  273.  
  274.    IF Repeating THEN
  275.       MaxData := MaxData - 2;
  276.                                    (* Remember if ascii transfer *)
  277.  
  278.    Ascii_File          := ( Kermit_File_Type_Var = Kermit_Ascii );
  279.  
  280.                                    (* Set data type packet *)
  281.    Send_Packet_Ptr^[4] := 'D';
  282.                                    (* Characters from file *)
  283.    Char_Count          := 0;
  284.                                    (* Encoded characters this packet *)
  285.    EChar_Count         := 0;
  286.                                    (* Repeat count starts at 0 *)
  287.    Repeat_Count        := 0;
  288.                                    (* Not end of file yet *)
  289.    End_Of_File         := FALSE;
  290.                                    (* Get next batch of characters *)
  291.                                    (* from file                    *)
  292.    REPEAT
  293.                                    (* See if anything to be sent *)
  294.       Save_Char := NextChar;
  295.                                    (* Make sure to stop at ^Z = EOF *)
  296.                                    (* on text files.                *)
  297.  
  298.       IF Ascii_File AND ( Save_Char = ORD( ^Z ) ) THEN
  299.          BEGIN
  300.             End_Of_File        := TRUE;
  301.             No_More_Chars      := TRUE;
  302. {
  303.             IF Kermit_Debug THEN
  304.                Write_Log('Found Ctrl-Z for Ascii file.', TRUE, FALSE);
  305. }
  306.          END;
  307.                                    (* Handle repeat quoting here *)
  308.       IF ( NOT No_More_Chars ) THEN
  309.          IF Repeating THEN
  310.             BEGIN
  311.  
  312.                Repeat_Count := 1;
  313.  
  314.                WHILE ( ( PeekChar = Save_Char ) AND ( Repeat_Count < 94 ) ) DO
  315.                   BEGIN
  316.                      Save_Char    := NextChar;
  317.                      INC( Repeat_Count );
  318.                   END;
  319.  
  320.                CASE Repeat_Count OF
  321.                   1:    Encode_Kermit_Character( Save_Char );
  322.                   2:    BEGIN
  323.                            Encode_Kermit_Character( Save_Char );
  324.                            Encode_Kermit_Character( Save_Char );
  325.                         END;
  326.                   ELSE  BEGIN
  327.                            INC( Packet_Count );
  328.                            Send_Packet_Ptr^[Packet_Count]   := His_Repeat_Char;
  329.                            INC( Packet_Count );
  330.                            Send_Packet_Ptr^[Packet_Count]   := CHR( Repeat_Count + 32 );
  331.                            Encode_Kermit_Character( Save_Char );
  332.                         END;
  333.                END (* CASE *);
  334.  
  335.             END
  336.          ELSE                      (* Not a repeated character *)
  337.  
  338.             Encode_Kermit_Character( Save_Char );
  339.  
  340.    UNTIL ( End_Of_File AND No_More_Chars ) OR
  341.          ( Packet_Count >= MaxData );
  342.  
  343.                                    (* Record encoded character count *)
  344.  
  345.    Buffer_Num        := Buffer_Num        + Char_Count;
  346.    Buffer_Num_Actual := Buffer_Num_Actual + EChar_Count;
  347.  
  348.                                    (* Remember length of packet   *)
  349.  
  350.    IF ( Char_Count > 0 ) THEN
  351.       Send_Packet_Length := Packet_Count
  352.    ELSE
  353.       Send_Packet_Length := 0;
  354.                                    (* Remember if end of file AND *)
  355.                                    (* buffer exhausted.           *)
  356.  
  357.    IF ( End_Of_File AND No_More_Chars ) THEN
  358.       BEGIN
  359.          File_Done    := TRUE;
  360.          CLOSE( XFile );
  361.          Err          := Int24Result;
  362.          Buffer_Total := Buffer_Total + Buffer_Num;
  363.       END
  364.    ELSE
  365.       File_Done := FALSE;
  366.  
  367. END    (* Get_File_Data *);
  368.  
  369. (*----------------------------------------------------------------------*)
  370. (*          Kermit_Send_Init --- send initialization packet             *)
  371. (*----------------------------------------------------------------------*)
  372.  
  373. PROCEDURE Kermit_Send_Init;
  374.  
  375. (*----------------------------------------------------------------------*)
  376. (*                                                                      *)
  377. (*     Procedure:  Kermit_Send_Init                                     *)
  378. (*                                                                      *)
  379. (*     Purpose:    Sends transfer initialization packet to host.        *)
  380. (*                                                                      *)
  381. (*     Calling Sequence:                                                *)
  382. (*                                                                      *)
  383. (*        Kermit_Send_Init;                                             *)
  384. (*                                                                      *)
  385. (*     Calls:                                                           *)
  386. (*                                                                      *)
  387. (*        Build_Packet                                                  *)
  388. (*        Send_Packet                                                   *)
  389. (*        Receive_Packet                                                *)
  390. (*                                                                      *)
  391. (*----------------------------------------------------------------------*)
  392.  
  393. VAR
  394.    Quote_8       : CHAR;
  395.    Repeat_Char   : CHAR;
  396.    My_Attributes : CHAR;
  397.    Window_Size   : STRING[1];
  398.    LX1           : CHAR;
  399.    LX2           : CHAR;
  400.    Attributes    : BYTE;
  401.    Do_Win        : BOOLEAN;
  402.    Do_Long       : BOOLEAN;
  403.  
  404. BEGIN (* Kermit_Send_Init *)
  405.  
  406.    Packet_Num   := 0;
  407.    Try          := 0;
  408.    Quoting      := FALSE;
  409.                                    (* Ensure type 1 block check here *)
  410.    His_Chk_Type := '1';
  411.                                    (* 8-bit quoting off for 8,n,1   *)
  412.                                    (* and ascii file type transfers *)
  413.  
  414.    IF ( ( Parity <> 'N' ) OR ( Data_Bits <> 8 ) ) AND
  415.       ( Kermit_File_Type_Var = Kermit_Binary ) THEN
  416.       BEGIN
  417.          Quote_8 := Kermit_Quote_8_Char;
  418.          Quoting := TRUE;
  419.       END
  420.    ELSE                            (* Willing to quote if necessary *)
  421.       Quote_8 := 'Y';
  422.                                    (* If repeating data to be allowed *)
  423.  
  424.    Repeat_Char := Kermit_Repeat_Char;
  425.  
  426.                                    (* Capabilities                    *)
  427.    Attributes  := 8;
  428.                                    (* Set window size, long packets   *)
  429.                                    (* size.                           *)
  430.  
  431.    His_Kermit_Window_Size := Kermit_Window_Size;
  432.    His_Kermit_MaxLX1      := Kermit_Extended_Block DIV 95;
  433.    His_Kermit_MaxLX2      := Kermit_Extended_Block MOD 95;
  434.  
  435.    Window_Size := ' ';
  436.    Do_Win      := ( His_Kermit_Window_Size > 0 );
  437.    Do_Long     := ( ( His_Kermit_MaxLX1 > 0 ) OR ( His_Kermit_MaxLX2 > 0 ) );
  438.  
  439.    IF Do_Win THEN
  440.       BEGIN
  441.          Attributes  := Attributes + 4;
  442.          Window_Size := CHR( His_Kermit_Window_Size + 32 );
  443.       END;
  444.  
  445.    IF Do_Long THEN
  446.       BEGIN
  447.          Attributes := Attributes + 2;
  448.          LX1        := CHR( His_Kermit_MaxLX1 + 32 );
  449.          LX2        := CHR( His_Kermit_MaxLX2 + 32 );
  450.       END;
  451.  
  452.    My_Attributes    := CHR( Attributes + 32 );
  453.  
  454.                                    (* Construct initialization packet *)
  455.  
  456.    Send_Packet_Ptr^[ 4] := 'S';
  457.    Send_Packet_Ptr^[ 5] := CHR( Kermit_Packet_Size + 32         );
  458.    Send_Packet_Ptr^[ 6] := CHR( Kermit_TimeOut     + 32         );
  459.    Send_Packet_Ptr^[ 7] := CHR( Kermit_Npad        + 32         );
  460.    Send_Packet_Ptr^[ 8] := CHR( ORD( Kermit_Pad_Char ) XOR $40  );
  461.    Send_Packet_Ptr^[ 9] := CHR( ORD( Kermit_EOL      ) + 32     );
  462.    Send_Packet_Ptr^[10] := Kermit_Quote_Char;
  463.    Send_Packet_Ptr^[11] := Quote_8;
  464.    Send_Packet_Ptr^[12] := Kermit_Chk_Type;
  465.    Send_Packet_Ptr^[13] := Repeat_Char;
  466.    Send_Packet_Ptr^[14] := My_Attributes;
  467.  
  468.    Send_Packet_Length   := 14;
  469.  
  470.    IF ( Do_Win OR Do_Long ) THEN
  471.       BEGIN
  472.          Send_Packet_Ptr^[15] := Window_Size[1];
  473.          Send_Packet_Length   := 15;
  474.       END;
  475.  
  476.    IF Do_Long THEN
  477.       BEGIN
  478.          Send_Packet_Ptr^[16] := LX1;
  479.          Send_Packet_Ptr^[17] := LX2;
  480.          Send_Packet_Length   := 17;
  481.       END;
  482. {
  483.    IF Kermit_Debug THEN
  484.       Write_Log('My send-init packet = <' +
  485.                 COPY( Send_Packet_Ptr^, 1, Send_Packet_Length ) + '>',
  486.                 FALSE, FALSE );
  487. }
  488.    Build_Packet;
  489.  
  490.    REPEAT
  491.                                    (* Ensure type 1 block check here *)
  492.       His_Chk_Type := '1';
  493.                                    (* Assume bad until proved otherwise *)
  494.       ACK_OK := FALSE;
  495.                                    (* Send initialization packet *)
  496.       Send_Packet;
  497.                                    (* Check response *)
  498.       Receive_Packet;
  499.                                    (* If right response then check *)
  500.                                    (* if received packet jives     *)
  501.                                    (* with what we sent.           *)
  502.       IF ( Packet_OK AND
  503.          ( Kermit_Packet_Type = ACK_Pack ) AND
  504.          ( NOT Kermit_Abort ) ) THEN
  505.          Check_Init( ACK_OK );
  506.                                    (* Increment count of tries     *)
  507.       INC( Try );
  508.  
  509.    UNTIL ACK_OK OR Kermit_Abort OR ( Try = Kermit_MaxTry );
  510.  
  511.                                    (* If OK, then get ready to send  *)
  512.                                    (* file header packet, else abort *)
  513.    IF ACK_OK THEN
  514.       Kermit_State := Send_File_Header
  515.    ELSE
  516.       BEGIN
  517.          Kermit_Abort := TRUE;
  518.          Kermit_State := Send_Break;
  519.       END;
  520.  
  521. END   (* Kermit_Send_Init *);
  522.  
  523. (*----------------------------------------------------------------------*)
  524. (* Build_And_Send_Packet_With_Retry --- Build & send packet with retry  *)
  525. (*----------------------------------------------------------------------*)
  526.  
  527. PROCEDURE Build_And_Send_Packet_With_Retry;
  528.  
  529. (*----------------------------------------------------------------------*)
  530. (*                                                                      *)
  531. (*     Procedure:  Build_And_Send_Packet_With_Retry                     *)
  532. (*                                                                      *)
  533. (*     Purpose:    Sends packet to remote Kermit and retries if         *)
  534. (*                 packet not acknowledged.                             *)
  535. (*                                                                      *)
  536. (*     Calling Sequence:                                                *)
  537. (*                                                                      *)
  538. (*        Build_And_Send_Packet_With_Retry;                             *)
  539. (*                                                                      *)
  540. (*                                                                      *)
  541. (*     Calls:                                                           *)
  542. (*                                                                      *)
  543. (*        Build_Packet                                                  *)
  544. (*        Check_ACK                                                     *)
  545. (*        Async_Flush_Output_Buffer                                     *)
  546. (*                                                                      *)
  547. (*----------------------------------------------------------------------*)
  548.  
  549. BEGIN (* Build_And_Send_Packet_With_Retry *)
  550.  
  551.                                    (* Build the packet *)
  552.    Build_Packet;
  553.                                    (* No tries yet *)
  554.    Try := 0;
  555.                                    (* Begin loop over sending tries *)
  556.    REPEAT
  557.                                    (* Send the packet *)
  558.       Send_Packet;
  559.                                    (* See if it was acknowledged *)
  560.       Check_ACK;
  561.                                    (* Increment count of send packet tries *)
  562.       INC( Try );
  563.                                    (* If we're in a retry mode, and an    *)
  564.                                    (* XOFF was received, the XOFF may be  *)
  565.                                    (* spurious, so clear it before trying *)
  566.                                    (* again.  We also need to flush the   *)
  567.                                    (* comm output buffer at this point    *)
  568.                                    (* as well.                            *)
  569.                                    (*                                     *)
  570.                                    (* If an XOFF wasn't received, perhaps *)
  571.                                    (* the remote system got a spurious    *)
  572.                                    (* XOFF, so we send an XON.            *)
  573.                                    (*                                     *)
  574.  
  575.       IF ( Try > 2 ) THEN
  576.          IF Async_XOff_Received THEN
  577.             BEGIN
  578.                Async_Flush_Output_Buffer;
  579.                Clear_XOff_Received;
  580.             END
  581.          ELSE
  582.             IF Async_Do_XonXoff THEN
  583.                Async_Send_Now( CHR( XON ) );
  584.  
  585.                                    (* Stop if OK, abort requested, or too *)
  586.                                    (* many tries.                         *)
  587.  
  588.    UNTIL ACK_OK OR Kermit_Abort OR ( Try = Kermit_MaxTry );
  589.  
  590. END   (* Build_And_Send_Packet_With_Retry *);
  591.  
  592. (*----------------------------------------------------------------------*)
  593. (*      Kermit_Send_Header --- send file header (file name) packet      *)
  594. (*----------------------------------------------------------------------*)
  595.  
  596. PROCEDURE Kermit_Send_Header;
  597.  
  598. (*----------------------------------------------------------------------*)
  599. (*                                                                      *)
  600. (*     Procedure:  Kermit_Send_Header                                   *)
  601. (*                                                                      *)
  602. (*     Purpose:    Sends file name packet to remote Kermit.             *)
  603. (*                                                                      *)
  604. (*     Calling Sequence:                                                *)
  605. (*                                                                      *)
  606. (*        Kermit_Send_Header;                                           *)
  607. (*                                                                      *)
  608. (*     Calls:                                                           *)
  609. (*                                                                      *)
  610. (*        Build_And_Send_Packet_With_Retry                              *)
  611. (*                                                                      *)
  612. (*----------------------------------------------------------------------*)
  613.  
  614. BEGIN (* Kermit_Send_Header *)
  615.  
  616.                                    (* Construct file name packet *)
  617.  
  618.    Packet_Num          := SUCC( Packet_Num ) MOD 64;
  619.  
  620.    Send_Packet_Ptr^[4] := 'F';
  621.  
  622.    MOVE( FileName[1], Send_Packet_Ptr^[5], LENGTH( FileName ) );
  623.  
  624.    Send_Packet_Length := LENGTH( FileName ) + 4;
  625.  
  626.                                    (* Send the packet *)
  627.  
  628.    Build_And_Send_Packet_With_Retry;
  629.  
  630.                                    (* If it was ACKed, then *)
  631.                                    (* prepare to send file. *)
  632.    IF ACK_OK THEN
  633.       Kermit_State := Send_File
  634.    ELSE
  635.       BEGIN
  636.          Kermit_Abort := TRUE;
  637.          Kermit_State := Send_Break;
  638.       END;
  639.  
  640. END    (* Kermit_Send_Header *);
  641.  
  642. (*----------------------------------------------------------------------*)
  643. (*         Kermit_Send_Attributes --- send file attributes              *)
  644. (*----------------------------------------------------------------------*)
  645.  
  646. PROCEDURE Kermit_Send_Attributes;
  647.  
  648. (*----------------------------------------------------------------------*)
  649. (*                                                                      *)
  650. (*     Procedure:  Kermit_Send_Attributes                               *)
  651. (*                                                                      *)
  652. (*     Purpose:    Sends file attributes packet to remote Kermit.       *)
  653. (*                                                                      *)
  654. (*     Calling Sequence:                                                *)
  655. (*                                                                      *)
  656. (*        Kermit_Send_Attributes;                                       *)
  657. (*                                                                      *)
  658. (*     Calls:                                                           *)
  659. (*                                                                      *)
  660. (*        Build_And_Send_Packet_With_Retry                              *)
  661. (*                                                                      *)
  662. (*----------------------------------------------------------------------*)
  663.  
  664. VAR
  665.    L1               : INTEGER;
  666.    L2               : INTEGER;
  667.    L3               : INTEGER;
  668.    I                : INTEGER;
  669.    Send_Packet_Ptr2 : Kermit_Packet_Ptr;
  670.    Count            : INTEGER;
  671.    CheckSum         : INTEGER;
  672.  
  673. BEGIN  (* Kermit_Send_Attributes *)
  674.  
  675.                                    (* Increment packet number          *)
  676.  
  677.    Packet_Num := SUCC( Packet_Num ) MOD 64;
  678.  
  679.                                    (* We are going to send the file    *)
  680.                                    (* size in 8-bit characters and the *)
  681.                                    (* time and date the file was       *)
  682.                                    (* created.                         *)
  683.  
  684.    L1 := LENGTH( Kermit_CFile_Size );
  685.    L2 := LENGTH( Kermit_CFile_Date );
  686.    L3 := LENGTH( Kermit_CFile_Time );
  687.  
  688.    Send_Packet_Ptr^[ 4] := 'A';
  689.    Send_Packet_Ptr^[ 5] := '1';
  690.    Send_Packet_Ptr^[ 6] := CHR( 32 + L1 );
  691.  
  692.    MOVE( Kermit_CFile_Size[1] , Send_Packet_Ptr^[7] , L1 );
  693.    Send_Packet_Length   := L1 + 7;
  694.  
  695.    Send_Packet_Ptr^[Send_Packet_Length] := '#';
  696.    INC( Send_Packet_Length );
  697.    Send_Packet_Ptr^[Send_Packet_Length] := CHR( 32 + L2 + L3 + 1 );
  698.  
  699.    INC( Send_Packet_Length );
  700.    MOVE( Kermit_CFile_Date[1] , Send_Packet_Ptr^[Send_Packet_Length] , L2 );
  701.    Send_Packet_Length   := Send_Packet_Length + L2;
  702.  
  703.    Send_Packet_Ptr^[Send_Packet_Length] := ' ';
  704.    INC( Send_Packet_Length );
  705.  
  706.    MOVE( Kermit_CFile_Time[1] , Send_Packet_Ptr^[Send_Packet_Length] , L3 );
  707.    Send_Packet_Length   := Send_Packet_Length + L3 - 1;
  708.  
  709.                                    (* Build packet and sent it         *)
  710.  
  711.    Build_And_Send_Packet_With_Retry;
  712.  
  713. END   (* Kermit_Send_Attributes *);
  714.  
  715.