home *** CD-ROM | disk | FTP | other *** search
/ ftp.barnyard.co.uk / 2015.02.ftp.barnyard.co.uk.tar / ftp.barnyard.co.uk / cpm / walnut-creek-CDROM / CPM / TURBOPAS / TKERMIT.LBR / KSEND.PQS / KSEND.PAS
Pascal/Delphi Source File  |  2000-06-30  |  17KB  |  502 lines

  1.     procedure check_init(var check_ok : boolean); (* check send init packet *)
  2.  
  3.       (* This procedure looks at the send init packet or the ack for one
  4.          and matches the data to see if we can communicate.  IT sets up
  5.          what it can if I can live with what the other guy wants.  I don't
  6.          want to be picky if I can help it.  If he doesn't tell me everything
  7.          I make some assumptions that should allow communications.
  8.       *)
  9.  
  10.       var
  11.         packet_length : integer;
  12.  
  13.       begin  (* we've got a packet we can work with *)
  14.         if rec_packet_num = packet_num mod 64 then
  15.           check_ok := true;
  16.         packet_length := length(rec_packet);
  17.         if packet_length >= 1 then
  18.           begin
  19.             if unchar(rec_packet[1]) in [4..94] then
  20.               packet_size := unchar(rec_packet[1])
  21.             else
  22.               check_ok := false; (* packets < 4 and > 94 make no sense *)
  23.           end;
  24.         if check_ok then (* let's find out what he wants *)
  25.           begin
  26.             if packet_length >= 3 then (* skip timeout, I can't *)
  27.               my_pad_num := unchar(rec_packet[3]); (* number of pad chars *)
  28.             if packet_length >= 4 then
  29.               my_pad_char := ctl(rec_packet[4]);
  30.             if packet_length >= 5 then
  31.               send_eol := unchar(rec_packet[5]);
  32.             if packet_length >= 6 then
  33.               begin
  34.                 if rec_packet[6] = ' ' then
  35.                   his_ctl_quote := quote_char
  36.                 else
  37.                   his_ctl_quote := rec_packet[6];
  38.               end
  39.             else
  40.               his_ctl_quote := quote_char;
  41.             if packet_length >= 7 then
  42.               case rec_packet[7] of
  43.                 'N' : if quoting then (* we're deadlocked *)
  44.                         check_ok := false;
  45.                 'Y' : ; (* we don't care, quoting is all set up *)
  46.                 '!'..'>','`'..'~' : begin (* we'll use his quote char *)
  47.                                       quoting := true;
  48.                                       quote_8 := rec_packet[7];
  49.                                     end;
  50.                 else
  51.                   check_ok := false; (* he didn't send me a valid char *)
  52.               end (* case *)
  53.             else
  54.               if quoting then
  55.                 check_ok := false; (* I'm trying to quote and he won't
  56.                                     acknowledge it *)
  57.           end;
  58.       end; (* check_init *)
  59.  
  60.   procedure check_ack; (* check ack states for most packets *)
  61.  
  62.     begin
  63.       ack_ok := false; (* we'll assume a bad packet and prove otherwise *)
  64.       receive_packet;
  65.       if packet_ok and (not abort) then
  66.         begin
  67.           case packet_type of
  68.             ack_pack : if rec_packet_num = packet_num mod 64 then
  69.                          ack_ok := true; (* we better be exact on this one *)
  70.             nak_pack : begin
  71.                          if rec_packet_num = 0 then
  72.                            rec_packet_num := 63
  73.                          else rec_packet_num := rec_packet_num - 1;
  74.                          if rec_packet_num = (packet_num mod 64) then
  75.                            ack_ok := true; (* nak for next is ack for current *)
  76.                        end;
  77.             error_pack : begin (* he must be upset at me *)
  78.                            gotoxy(1,9);
  79.                            write(rec_packet);
  80.                            abort := true;
  81.                          end;
  82.             else
  83.               ack_ok := false; (* if it's another type try to keep sending
  84.                                   I don't know if this is right, but it
  85.                                   sounds logical. *)
  86.           end; (* case *)
  87.         end
  88.       else
  89.         ack_ok := false;
  90.       if debug then
  91.         begin
  92.           gotoxy(1,16);
  93.           write('ack_ok: ', ack_ok,'  packet_num: ',packet_num,
  94.             '  rec_packet_num: ',rec_packet_num);
  95.         end;
  96.       if ack_ok = false then
  97.         packets_bad := packets_bad + 1;
  98.     end;
  99.  
  100.   procedure send_packet;
  101.  
  102.     (* This will send a packet that has been prepared by build packet, which
  103.        does most of the work.
  104.     *)
  105.  
  106.     var
  107.       temp_char : char;
  108.  
  109.     begin (* send_packet *)
  110.       iobyte := (iobyte and $fc) or port; (* set port *)
  111.       while bios(1) <> 0 do
  112.         bios(2); (* clear input buffer as Columbia recommends *)
  113.       iobyte := (iobyte and $fc) or 1; (* set port to con: *)
  114.       update(packets_sent, packets_bad); (* update the display with new info *)
  115.       if debug then
  116.         begin
  117.           gotoxy(1,17);
  118.           write('Packet length: ', length(packet_buffer));
  119.           gotoxy(1,13);
  120.           write('spack: ');
  121.           for count := 1 to length(packet_buffer) do
  122.             begin
  123.               temp_char := packet_buffer[count]; (* make dummy var *)
  124.               if ord(temp_char) > 127 then       (* 8th bit set *)
  125.                 begin
  126.                   temp_char := chr(ord(temp_char) and $7f); (* strip 8th bit *)
  127.                   write('''');  (* show ' for 8th bit and fall through *)
  128.                 end;
  129.               if temp_char < ' ' then
  130.                 write('^' + ctl(temp_char))
  131.               else write(temp_char);
  132.             end;
  133.         end;
  134.       for count := 1 to length(packet_buffer) do
  135.         send_char(ord(packet_buffer[count]));
  136.     end; (* send_packet *)
  137.  
  138. (*----------------------------------------------------------------*)
  139.  
  140.   procedure build_packet;
  141.  
  142.       (* This procedure tacks on the things we need for a packet such as
  143.          parity, checksum, padding, and the ^A.
  144.       *)
  145.  
  146.       var
  147.         checksum, count, index, bit_count : integer;
  148.         temp_pack : string[150];
  149.  
  150.       begin (* build_packet *)
  151.         checksum := 0;
  152.         packet_buffer := ^A + char40(length(packet_buffer_data) + 2) +
  153.                                 char40(packet_num mod 64) + packet_buffer_data;
  154.         for count := 2 to length(packet_buffer) do
  155.           begin
  156.             checksum := checksum + ord(packet_buffer[count]);
  157.           end;
  158.         checksum := ((checksum + ((checksum and 192) div 64)) and 63);
  159.         packet_buffer := packet_buffer + char40(checksum) + chr(send_eol);
  160.         if my_pad_num > 0 then (* add in the padding requested *)
  161.           for count := 1 to my_pad_num do
  162.             packet_buffer := my_pad_char + packet_buffer;
  163.         case parity_type_var of
  164.           mark_parity : for count := 1 to length(packet_buffer) do
  165.                    packet_buffer[count] := chr(ord(packet_buffer[count]) or $80);
  166.           space_parity : for count := 1 to length(packet_buffer) do
  167.                    packet_buffer[count] := chr(ord(packet_buffer[count]) and $7f);
  168.           even_parity, odd_parity : begin
  169.                         for count := 1 to length(packet_buffer) do
  170.                           begin
  171.                             bit_count := 0;
  172.                             temp_pack := packet_buffer;
  173.                             for index := 1 to 7 do
  174.                               begin
  175.                                 temp_pack[count] := chr(ord(temp_pack[count])
  176.                                    shr 1);
  177.                                 if (ord(temp_pack[count]) and $01 = 1) then
  178.                                   bit_count := bit_count + 1;
  179.                               end;
  180.                             if odd(bit_count) and (parity_type_var =
  181.                               even_parity) then
  182.                               packet_buffer[count] :=
  183.                                 chr(ord(packet_buffer[count]) or $80);
  184.                             if (not odd(bit_count)) and (parity_type_var =
  185.                               odd_parity) then
  186.                               packet_buffer[count] :=
  187.                                 chr(ord(packet_buffer[count]) or $80);
  188.                           end;
  189.                       end;
  190.         end; (* case *)
  191.       end; (* build_packet *)
  192.  
  193. (*----------------------------------------------------------------*)
  194.  
  195.   procedure quit; (* return to CP/M. *)
  196.  
  197.     begin (* quit *)
  198.       gotoxy(1,23); (* get cursor back below display *)
  199.       halt;
  200.     end; (* quit *)
  201.  
  202.   procedure finish; (* finish with server - bye, finish, logout, commands *)
  203.  
  204.     var
  205.       try : integer;
  206.  
  207.     begin (* finish *)
  208.       case line_command[1] of
  209.         'F','f' : packet_buffer_data := 'GF';
  210.         'B','b','L','l' : packet_buffer_data := 'GL';
  211.       end; (* case *)
  212.       packet_num := 0;
  213.       try := 0;
  214.       build_packet;
  215.       repeat
  216.         try := try + 1;
  217.         send_packet;
  218.         check_ack;
  219.       until (abort) or (ack_ok) or (try > maxtry);
  220.       if (try > maxtry) or abort then
  221.         begin
  222.           gotoxy(1,9);
  223.           writeln('Unable to logout server.');
  224.         end
  225.         else
  226.           case line_command[1] of   (* we only halt if 'bye' and we logged out *)
  227.             'B','b' : halt;
  228.           end; (* case *)
  229.       gotoxy(1,23); (* get cursor back below display *)
  230.     end; (* finish *)
  231.  
  232. (*----------------------------------------------------------------*)
  233.  
  234.   procedure send; (* send a file to remote host *)
  235.  
  236.     const
  237.       eof_packet = 'Z';
  238.       break_packet = 'B';
  239.  
  240.     var
  241.       try : integer;
  242.       send_done : boolean;
  243.  
  244.     procedure get_file_data; (* read in the file data *)
  245.  
  246.       var
  247.         char_count : integer;
  248.         temp : char;
  249.         temp_data : string[120];
  250.         end_of_file : boolean;
  251.  
  252.       begin
  253.         packet_buffer_data := 'D';
  254.         char_count := 1;
  255.         end_of_file := false;
  256.         while not (((filepointer > buffersize) and eof(outfile)) or
  257.           (char_count >= (packet_size - 4)) or end_of_file) do
  258.           begin
  259.            if (filepointer > buffersize) then
  260.              begin
  261.                blockread(outfile, filebuffer, 1);
  262.                filepointer := 1;
  263.                buffer_num := buffer_num + 1;
  264.              end;
  265.            temp := filebuffer[filepointer];
  266.            filepointer := filepointer + 1;
  267.            if (ord(temp) > $7f) and quoting then
  268.              begin
  269.                packet_buffer_data := packet_buffer_data + quote_8;  (* add 8 bit quote char *)
  270.                char_count := char_count + 1;
  271.                temp := chr(ord(temp) and $7f);  (* strip high bit *)
  272.              end;                               (* and fall through *)
  273.            if (ord(temp) and $7f) < ord(' ') then
  274.              begin
  275.                packet_buffer_data :=
  276.                  packet_buffer_data + quote_char + ctl(temp);
  277.                char_count := char_count + 2;
  278.              end
  279.            else
  280.              begin
  281.                if (ord(temp) and $7f) = ord(quote_char) then
  282.                  begin
  283.                    packet_buffer_data := packet_buffer_data + quote_char;
  284.                    char_count := char_count + 1;
  285.                  end;
  286.                packet_buffer_data := packet_buffer_data + temp;
  287.                char_count := char_count + 1;
  288.              end;
  289.            if (file_type_var = ascii) then
  290.              if temp = ^Z then
  291.                begin
  292.                  end_of_file := true;
  293.                  delete(packet_buffer_data,length(packet_buffer_data) - 1, 2);
  294.                   (* delete ^Z at end of packet *)
  295.                end;
  296.         end; (* while *)
  297.         if (end_of_file or ((filepointer > buffersize) and eof(outfile))) then
  298.           begin
  299.             file_done := true;
  300.             close(outfile);
  301.           end
  302.         else
  303.           file_done := false;
  304.       end;
  305.  
  306.     procedure sinit; (* do send init packet *)
  307.  
  308.       begin
  309.         packet_num := 0;
  310.         try := 0;
  311.         if (parity_type_var <> no_parity) and (file_type_var = binary) then
  312.             quote_8 := '&'  (* let's try to quote chars with 8'th bit set *)
  313.                             (* We have to if we're to transmit binary *)
  314.         else
  315.           quote_8 := 'Y'; (* I'm willing to quote *)
  316.         if repeating then
  317.           repeat_char := '~'
  318.         else
  319.           repeat_char := ' ';
  320.         packet_buffer_data :=  'S' + char40(packet_size) + char40(timeout)
  321.                                + char40(npad) + ctl(pad) + char40(end_of_line)
  322.                                + quote_char + quote_8 + chk_type
  323.                                + repeat_char;
  324.         build_packet;
  325.         repeat
  326.           ack_ok := false; (* assume its bad until proved otherwise *)
  327.           packets_sent := packets_sent + 1;
  328.           send_packet;
  329.           receive_packet;
  330.           if debug then
  331.             begin
  332.               gotoxy(1,22);
  333.               write('got incoming packet');
  334.             end;
  335.           if (packet_ok and (packet_type = ack_pack) and (not abort)) then
  336.             check_init(ack_ok);
  337.           try := try + 1;
  338.         until ack_ok or abort or (try = maxtry);
  339.         if ack_ok then
  340.           state := send_file_header
  341.         else abort := true;
  342.       end; (* sinit *)
  343.  
  344.     procedure sheader; (* send file header *)
  345.  
  346.       begin
  347.         packet_num := packet_num + 1; (* next packet *)
  348.         packet_buffer_data := 'F' + arg1;
  349.         build_packet;
  350.         try := 0;
  351.         repeat
  352.           send_packet;
  353.           check_ack;
  354.           try := try + 1;
  355.         until ack_ok or abort or (try = maxtry);
  356.         if ack_ok then
  357.           state := send_file
  358.         else
  359.           abort := true;
  360.       end; (* sinit *)
  361.  
  362.  
  363.     procedure sfile; (* send the file data *)
  364.  
  365.       begin
  366.         gotoxy(40,2);
  367.         write('Sending...');
  368.         repeat
  369.           packet_num := packet_num + 1;
  370.           get_file_data;
  371.           if length(packet_buffer_data) > 1 then (* packet has data in it *)
  372.             begin
  373.               build_packet;
  374.               try := 0;
  375.               repeat
  376.                 send_packet;
  377.                 check_ack;
  378.                 try := try + 1;
  379.               until ack_ok or abort or (try = maxtry);
  380.             end;
  381.         until file_done or abort or (try = maxtry);
  382.         if file_done then
  383.           state := send_eof
  384.         else
  385.           abort := true;
  386.       end;
  387.  
  388.     procedure seof; (* send EOF packet *)
  389.  
  390.       begin
  391.         packet_num := (packet_num + 1) mod 64;
  392.         packet_buffer_data := eof_packet;
  393.         build_packet;
  394.         try := 0;
  395.         repeat
  396.           send_packet;
  397.           check_ack;
  398.           try := try + 1;
  399.         until ack_ok or abort or (try = maxtry);
  400.         if ack_ok then
  401.           state := send_break
  402.         else
  403.           abort := true;
  404.       end;
  405.  
  406.     procedure sbreak;
  407.  
  408.       begin
  409.         state := send_break;
  410.         packet_num := (packet_num + 1) mod 64;
  411.         packet_buffer_data := break_packet;
  412.         build_packet;
  413.         try := 0;
  414.         repeat
  415.           send_packet;
  416.           check_ack;
  417.           try := try + 1;
  418.         until ack_ok or abort or ( try = maxtry);
  419.         if ack_ok then
  420.           send_done := true
  421.         else
  422.           abort := true;
  423.         end; (* sbreak *)
  424.  
  425.     begin (* send *)
  426.       clrscr;
  427.       packets_sent := 0;
  428.       packets_bad := 0;
  429.       send_done := false;
  430.       displayt;
  431.       open_file(read_open, arg1);
  432.       if open_ok then
  433.         begin
  434.           filepointer := buffersize + 1; (* postion pointer beyond end of
  435.                                             buffer so we get a record on entry
  436.                                          *)
  437.           state := send_init;
  438.           repeat
  439.             case state of
  440.               send_init : sinit;
  441.               send_file_header : sheader;
  442.               send_file : sfile;
  443.               send_eof : seof;
  444.               send_break : sbreak;
  445.             end; (* case *)
  446.           until abort or send_done;
  447.           if send_done then
  448.             begin
  449.               gotoxy(40,2);
  450.               write('Completed.     ', bell);
  451.             end
  452.           else
  453.             begin
  454.               gotoxy(40,2);
  455.               write('Aborted        ', bell);
  456.             end;
  457.           if abort and debug then
  458.             begin
  459.               gotoxy(1,18);
  460.               writeln('Abort conditions were:');
  461.               writeln('State during abort was: ', state_str[state]);
  462.               writeln('Quoting was: ',quoting);
  463.             end;
  464.         end;
  465.         gotoxy(1,23);
  466.     end; (* send *)
  467.  
  468. (*----------------------------------------------------------------*)
  469.  
  470.   procedure send_ack;
  471.  
  472.     var
  473.       q_var : char;
  474.  
  475.     begin (* send_ack *)
  476.       if (state = receive_init) or (state = get_file) then
  477.         begin
  478.           if quoting then
  479.             q_var := quote_8
  480.           else
  481.             q_var := 'N';
  482.           packet_buffer_data :=  'Y' + char40(packet_size) + char40(timeout)
  483.                                + char40(npad) + ctl(pad) + char40(end_of_line)
  484.                                + quote_char + q_var + chk_type;
  485.  
  486.         end
  487.       else
  488.         packet_buffer_data := 'Y';
  489.       build_packet;
  490.       send_packet;
  491.     end; (* send_ack *)
  492.  
  493. (*----------------------------------------------------------------*)
  494.  
  495.   procedure send_nak;
  496.  
  497.     begin
  498.       packet_buffer_data := 'N';
  499.       build_packet;
  500.       send_packet;
  501.     end;
  502.