home *** CD-ROM | disk | FTP | other *** search
/ Columbia Kermit / kermit.zip / pub / ucsdwdme / recsw.text < prev    next >
Text File  |  2020-01-01  |  12KB  |  369 lines

  1.  
  2. (* RECEIVE SECTION *)
  3. UCSD Pascal KERMIT for the Terak p-System, from Kate MacGregor, Cornell U
  4.  
  5. segment procedure recsw(var rec_ok: boolean);
  6.  
  7. function rdata: char;
  8.  
  9. (* send file data *)
  10.  
  11. var num, len: integer;
  12.     ch: char;
  13.  
  14.   begin
  15.  
  16.     repeat
  17.         if numtry > maxtry then
  18.           begin
  19.             debugwrite('too many intial retries in rdata');
  20.             state := 'a';
  21.             exit(rdata)
  22.           end;
  23.  
  24.         num_try := num_try + 1;
  25.  
  26.         ch := rpack(len,num,recpkt);   (* receive a packet *)
  27.         if debug and (ch<>chr(0)) then packetwrite(recpkt,len);
  28.  
  29.         refresh_screen(numtry,n);
  30.  
  31.         if (ch = 'D') then             (* got data packet *)
  32.           begin
  33.             if (num <> (n mod 64)) then (* wrong packet *)
  34.               begin
  35.                 if (oldtry > maxtry) then
  36.                   begin
  37.                     debugwrite('too many data retries in rdata');
  38.                     rdata := 'a';      (* too many tries, abort *)
  39.                     exit(rdata)
  40.                   end; (* if *)
  41.  
  42.                 n := n - 1;
  43.  
  44.                 if (num = (n mod 64)) then (* previous packet again *)
  45.                   begin                (* so re-ACK it *)
  46.                     debugint('re-acking ',num);
  47.                     spack('Y',num,6,packet);
  48.                     numtry := 0;       (* reset try counter *)
  49.                                        (* stay in same state *)
  50.                   end (* if *)
  51.                 else begin             (* wrong number *)
  52.                     debugwrite('wrong data sequence no. in rdata');
  53.                     state := 'a'       (* so abort *)
  54.                     end
  55.               end (* if *)
  56.             else                       (* right packet *)
  57.               begin
  58.                 bufemp(recpkt,f,len);  (* write data to file *)
  59.                 spack('Y',(n mod 64),0,packet); (* ACK packet *)
  60.                 oldtry := numtry;      (* reset try counters *)
  61.                 if numtry > 1 then
  62.                     if istbrr then     (* clear buffer *)
  63.                       begin
  64.                         ch:=rcvbbt;
  65.                         ch:='D';
  66.                       end;
  67.                 numtry := 0;
  68.                 n := n + 1             (* bump packet number *)
  69.                                        (* stay in data send state *)
  70.               end (* else *)
  71.           end (* if 'D' *)
  72.         else if (ch = 'F') then        (* file header *)
  73.           begin
  74.             if (oldtry > maxtry) then
  75.               begin
  76.                 debugwrite('too many file head tries in rdata');
  77.                 rdata := 'a';          (* too many tries, abort *)
  78.                 exit(rdata)
  79.               end; (* if *)
  80.  
  81.             n := n - 1;
  82.  
  83.             if (num = (n mod 64)) then (* previous packet again *)
  84.               begin                    (* so re-ACK it *)
  85.                 debugint('re-acking file header ',num);
  86.                 spack('Y',num,0,packet);
  87.                 if istbrr then begin
  88.                   ch:=rcvbbt; (* and empty out buffer *)
  89.                   ch:='F';
  90.                   end;
  91.                 numtry := 0;           (* reset try counter *)
  92.                 state := state;        (* stay in same state *)
  93.               end (* if *)
  94.             else begin
  95.               debugwrite('file info not previous packet in rdata');
  96.                 state := 'a'           (* not previous packet, abort *)
  97.                 end
  98.           end (* if 'F' *)
  99.         else if (ch = 'Z') then        (* end of file *)
  100.           begin
  101.             if (num <> (n mod 64)) then(* wrong packet, abort *)
  102.               begin
  103.                 debugwrite('wrong eof packet in rdata');
  104.                 rdata := 'a';
  105.                 exit(rdata)
  106.               end; (* if *)
  107.             spack('Y',n mod 64,0,packet); (* ok, ACK it *)
  108.             close(f,lock);             (* close up the file *)
  109.             n :=  n + 1;               (* bump packet counter *)
  110.             state := 'f';              (* go to complete state *)
  111.           end (* else if 'Z' *)
  112.         else if (ch = 'E') then        (* error packet *)
  113.           begin
  114.             error(recpkt,len);         (* display error *)
  115.             state := 'a'               (* and abort *)
  116.           end (* if 'E' *)
  117.         else if (ch <> chr(0)) then begin (* some other packet type, *)
  118.             state := 'a';                 (* abort *)
  119.             debugwrite('wierd rdata packet');
  120.             end
  121.     until (state <> 'd');
  122.     rdata := state
  123.   end; (* rdata *)
  124.  
  125. function rfile: char;
  126.  
  127. (* receive file header *)
  128.  
  129. var num, len: integer;
  130.     ch: char;
  131.     oldfn: string;
  132.     i: integer;
  133.  
  134. procedure makename(recpkt: packettype; var fn: string; l: integer);
  135.  
  136. function exist(fn: string): boolean;
  137.  
  138. (* returns true if file named fn exists *)
  139.  
  140. var f: file;
  141.  
  142.   begin
  143.     (*$I-*) (* turn off i/o checking *)
  144.     reset(f,fn);
  145.     exist := (ioresult = 0)
  146.     (*$I+*)
  147.   end; (* exist *)
  148.  
  149. procedure checkname(var fn: string);
  150.  
  151. (* if file fn exists, makes a new name which doesn't *)
  152. (* does this by changing letters in file name until it *)
  153. (* finds some combination which doesn't exitst *)
  154.  
  155. var ch: char;
  156.     i: integer;
  157.  
  158.   begin
  159.     i := 1;
  160.     while (i <= length(fn)) and exist(fn) do
  161.       begin
  162.         ch := 'A';
  163.         while (ch in ['A'..'Z']) and exist(fn) do
  164.           begin
  165.             fn[i] := ch;
  166.             ch := succ(ch);
  167.           end; (* while *)
  168.         i := i + 1
  169.       end; (* while *)
  170.     end; (* checkname *)
  171.  
  172.   begin (* makename *)
  173.     fn := copy('               ',1,15);    (* stretch length *)
  174.     moveleft(recpkt[0],fn[1],l);           (* get filename from packet *)
  175.     oldfn := copy(fn, 1,l);                (* save fn sent to show user *)
  176.     fn := copy(fn,1,min(15,l));            (* set length of filename *)
  177.                                            (* and make sure <= 15 *)
  178.     uppercase(fn);
  179.     if pos('.TEXT',fn) <> length(fn)-4 then
  180.       begin
  181.         if length(fn) > 10 then
  182.             fn := copy(fn,1,10);           (* can only be 15 long in all *)
  183.         fn := concat(fn,'.TEXT');          (* and we'll add .TEXT *)
  184.       end; (* if *)
  185.     if fwarn then                          (* if file warning is on *)
  186.         checkname(fn);                       (* must check that name unique *)
  187.   end; (* makename *)
  188.  
  189.   begin (* rfile *)
  190.     if debug then
  191.         debugwrite('rfile');
  192.  
  193.     if (numtry > maxtry) then         (* if too many tries, give up *)
  194.       begin
  195.         rfile := 'a';
  196.         exit(rfile)
  197.       end;
  198.     numtry := numtry + 1;
  199.  
  200.     ch := rpack(len,num,recpkt);      (* receive a packet *)
  201.     if debug and (ch<>chr(0)) then packetwrite(recpkt,len);
  202.     refresh_screen(numtry,n);
  203.  
  204.     if ch = 'S' then                  (* send init, maybe our ACK lost *)
  205.       begin
  206.         if (oldtry > maxtry) then     (* too many tries, abort *)
  207.           begin
  208.             debugwrite('too many tries in rfile init');
  209.             rfile := 'a';
  210.             exit(rfile)
  211.           end; (* if *)
  212.  
  213.         n := n - 1;
  214.  
  215.         if num = (n mod 64) then      (* previous packet mod 64? *)
  216.           begin                       (* yes, ACK it again *)
  217.             debugint('re-acking init ',num);
  218.             spar(packet);             (* with our send init params *)
  219.             spack('Y',num,7,packet);
  220.             numtry := 0;              (* reset try counter *)
  221.             rfile := state;           (* stay in same state *)
  222.           end (* if *)
  223.         else                          (* not previous packet, abort *)
  224.           state := 'a'
  225.       end (* if 'S' *)
  226.     else if (ch = 'Z') then           (* end of file *)
  227.       begin
  228.         if (oldtry > maxtry) then     (* too many tries, abort *)
  229.           begin
  230.             debugwrite('too many tries in filehead eof');
  231.             rfile := 'a';
  232.             exit(rfile)
  233.           end; (* if *)
  234.  
  235.         n := n - 1;
  236.  
  237.         if num = (n mod 64) then       (* previous packet mod 64? *)
  238.           begin                       (* yes, ACK it again *)
  239.             debugint('re-acking eof ',num);
  240.             spack('Y',num,0,packet);
  241.             numtry := 0;
  242.             rfile := state            (* stay in same state *)
  243.           end (* if *)
  244.         else
  245.             rfile := 'a'              (* no, abort *)
  246.       end (* else if *)
  247.     else if (ch = 'F') then           (* file header *)
  248.       begin                           (* which is what we really want *)
  249.         if (num <> (n mod 64)) then   (* if wrong packet, abort *)
  250.           begin
  251.             debugwrite('wrong seq. of file header');
  252.             rfile := 'a';
  253.             exit(rfile)
  254.           end;
  255.  
  256.         makename(recpkt,filename,len); (* get filename, make unique if filew *)
  257.         gotoxy(filepos,fileline);
  258.         write(oldfn,' ==> ',filename);
  259.  
  260.         if not getfil(filename) then  (* try to open new file *)
  261.           begin
  262.             ioerror(ioresult);        (* if unsuccessful, tell them *)
  263.             rfile := 'a';             (* and abort *)
  264.             exit(rfile)
  265.           end; (* if *)
  266.  
  267.         spack('Y',n mod 64,0,packet); (* ACK file header *)
  268.         oldtry := numtry;             (* reset try counters *)
  269.         numtry := 0;
  270.         n := n + 1;                   (* bump packet number *)
  271.         rfile := 'd';                 (* switch to data state *)
  272.       end (* else if *)
  273.     else if ch = 'B' then             (* break transmission *)
  274.       begin
  275.         if (num <> (n mod 64)) then            (* wrong packet, abort *)
  276.           begin
  277.             debugwrite('wrong sequence in break packet');
  278.             rfile := 'a';
  279.             exit(rfile)
  280.           end;
  281.         spack('Y',n mod 64,0,packet); (* say ok *)
  282.         rfile := 'c'                  (* go to complete state *)
  283.       end (* else if *)
  284.     else if (ch = 'E') then
  285.       begin
  286.         error(recpkt,len);
  287.         rfile := 'a'
  288.       end
  289.     else if (ch = chr(0)) then        (* returned false *)
  290.         rfile := state                (* so stay in same state *)
  291.     else begin                        (* some weird state, so abort *)
  292.         rfile := 'a';
  293.         debugwrite('wierd rfile packet');
  294.         end
  295.   end; (* rfile *)
  296.  
  297. function rinit: char;
  298.  
  299. (* receive initialization *)
  300.  
  301. var num, len: integer;  (* packet number and length *)
  302.     ch: char;
  303.  
  304.   begin
  305.     if debug then
  306.         debugwrite('rinit');
  307.  
  308.     numtry := numtry + 1;
  309.  
  310.     ch := rpack(len,num,recpkt); (* receive a packet *)
  311.     if debug and (ch<>chr(0)) then packetwrite(recpkt,len);
  312.     refresh_screen(num_try,n);
  313.  
  314.     if (ch = 'S') then           (* send init packet *)
  315.       begin
  316.         rpar(recpkt);            (* get other side's init data *)
  317.         spar(packet);            (* fill packet with my init data *)
  318.         ctl_set := [chr(1)..chr(31),chr(del),quote];
  319.         spack('Y',n mod 64,7,packet); (* ACK with my params *)
  320.         oldtry := numtry;        (* save old try count *)
  321.         numtry := 0;             (* start a new counter *)
  322.         n := n + 1;              (* bump packet number *)
  323.         rinit := 'f';            (* enter file send state *)
  324.       end (* if 'S' *)
  325.     else if (ch = 'E') then
  326.       begin
  327.         rinit := 'a';
  328.         error(recpkt,len)
  329.       end (* if 'E' *)
  330.     else if (ch = chr(0)) then
  331.         rinit := 'r'             (* stay in same state *)
  332.     else begin
  333.         rinit := 'a';             (* abort *)
  334.         debugwrite('wierd rinit packet');
  335.         end
  336.   end; (* rinit *)
  337.  
  338. (* state table switcher for receiving packets *)
  339.  
  340.   begin (* recswok *)
  341.     writescreen('Receiving');
  342.     state := 'r';            (* initial state is send *)
  343.     n := 0;                  (* set packet # *)
  344.     numtry := 0;             (* no tries yet *)
  345.  
  346.     while true do
  347.         if state in ['d', 'f', 'r', 'c', 'a'] then
  348.           case state of
  349.               'd': state := rdata;
  350.               'f': state := rfile;
  351.               'r': state := rinit;
  352.               'c': begin
  353.                      rec_ok := true;
  354.                      exit(recsw)
  355.                    end; (* case c *)
  356.               'a': begin
  357.                      rec_ok := false;
  358.                      exit(recsw)
  359.                    end (* case a *)
  360.             end (* case *)
  361.         else (* state not in legal states *)
  362.           begin
  363.             rec_ok := false;
  364.             exit(recsw)
  365.           end (* else *)
  366.   end; (* recsw *)
  367.  
  368.  
  369.