home *** CD-ROM | disk | FTP | other *** search
/ Columbia Kermit / kermit.zip / archives / ucsdpecan.zip / receiver.text < prev    next >
Text File  |  1990-08-05  |  21KB  |  581 lines

  1. $D AFS-}       {indicates for compile to run without Adv. File Sys.
  2.  
  3. unit receiver;
  4.  
  5. interface
  6.  
  7. {Change log:
  8. 18 May 89, V1.1: Added debugdate to reread file dates (fixed date bug[??]) RTC
  9. 13 May 89, V1.1: Misc. cleanup to debug messages   RTC
  10. 30 Apr 89, V1.1: Fixed receiver won't stop on maxtry bug   RTC
  11. 26 Apr 89, V1.1: minor cleanups   RTC
  12. 16 Apr 89, V1.1: Fixed "garbage in buffer" bug       RTC
  13. 16 Apr 89, V1.1: Fixed "short text filename" bug.   RTC
  14. 15 Apr 89, V1.1: Added GET protocol & debug logging of date set result    RTC
  15. 13 Apr 89, V1.1: Added version message          RTC
  16. 17 Aug 88: Fixed garbage after partial last block of bin. file    RTC
  17. 07 Aug 88: Added conditional compilation for AFS/SFS differences   RTC
  18. 31 Jul 88: Added Attribute Packets & user discard requests to sender   RTC
  19. 10 Jul 88: Converted to use screenops unit     RTC
  20. 10 Jul 88: Fixed cleareol problem on filenames     RTC
  21. 02 Jul 88: Added binary file transfer & discard protocol   RTC
  22.  
  23. }
  24.  
  25.   procedure recsw(var rec_ok: boolean; get_from_server : boolean);
  26.  
  27.   procedure rec_version;
  28.  
  29.  
  30. implementation
  31.  
  32. uses
  33.    screenops,   {RTC, 10 Jul 88}
  34.    {$U kermglob.code} kermglob,
  35.    {$U kermutil.code} kermutil,
  36.    {$U kermpack.code} kermpack,
  37.    {$B AFS+}
  38.    {$U syslibr:attribute.code} attributes;
  39.    {$E AFS+} {$B AFS-}
  40.    {$U syslibr:wild.code} wild,
  41.    {$U syslibr:dir.info.code} dirinfo;
  42.    {$E AFS-}
  43.  
  44. const
  45.   my_version = '   Receiver Unit V1.1, 18 May 89';
  46.  
  47. $B AFS-
  48. procedure debugdate;
  49.  
  50.   var
  51.     heap : ^integer;
  52.     list : D_listp;
  53.     rslt : D_result;
  54.  
  55.   begin {debugdate}
  56.     mark(heap);
  57.     rslt := D_dirlist(xfilename,[Dvol..Ddir],list,false);
  58.     if rslt <> D_okay then debugwrite('Can''t Access File Date');
  59.     if debug then with list^,D_date do
  60.       begin
  61.         debugwrite('');
  62.         write(debf,'File ',D_volume,':',D_title,' Current Date = ',
  63.               month,'/',day,'/',year)
  64.       end;
  65.     release(heap)
  66.   end {debugdate};
  67. $E AFS-
  68.  
  69. procedure recsw{(var rec_ok: boolean; get_from_server : boolean)};
  70.  
  71. var
  72.   date_attr : record
  73.                 valid : boolean;
  74.                 value : {$B AFS+} FA_chron {$E AFS+}
  75.                         {$B AFS-} D_daterec {$E AFS-}
  76.               end;
  77.  
  78. function bufattr(buffer : packettype; len : integer) : integer;
  79.  
  80.   var
  81.     sp_pos,i,j,buffered : integer;
  82.     tempattr : string;
  83.  
  84.   begin {bufattr}
  85.     packet[0] := 'Y'; buffered := 1;    {agree to accept file}
  86.     i := 0; while i < len do
  87.       begin
  88.         if buffer[i] in ['#'] then      {acceptable attribute}
  89.           begin
  90.             tempattr := '';
  91.             for j := 1 to ord(unchar(buffer[succ(i)])) do
  92.               begin
  93.                 tempattr := concat(tempattr,' ');
  94.                 tempattr[length(tempattr)] := buffer[succ(i) + j]
  95.               end;
  96.             case buffer[i] of
  97.               '#' : with date_attr,value {$B AFS+},date,time{$E AFS+} do
  98.                 begin
  99.                   sp_pos := pos(' ',tempattr);
  100.                   if sp_pos = 0 then sp_pos := succ(length(tempattr));
  101.                   year := (ord(tempattr[sp_pos-6]) - ord('0')) * 10
  102.                         + (ord(tempattr[sp_pos-5]) - ord('0'));
  103.                   month := (ord(tempattr[sp_pos-4]) - ord('0')) * 10
  104.                          + (ord(tempattr[sp_pos-3]) - ord('0'));
  105.                   day := (ord(tempattr[sp_pos-2]) - ord('0')) * 10
  106.                        + (ord(tempattr[sp_pos-1]) - ord('0'));
  107.                   {$B AFS+}
  108.                   if length(tempattr) > sp_pos then
  109.                     begin
  110.                       hour := (ord(tempattr[sp_pos+1]) - ord('0')) * 10
  111.                             + (ord(tempattr[sp_pos+2]) - ord('0'));
  112.                       min := (ord(tempattr[sp_pos+4]) - ord('0')) * 10
  113.                             + (ord(tempattr[sp_pos+5]) - ord('0'))
  114.                     end
  115.                   else          {no time provided}
  116.                     begin
  117.                       hour := 24 {non-valid time}; min := 0
  118.                     end;
  119.                   {$E AFS+}
  120.                   valid := true
  121.                 end
  122.             end {case}
  123.           end
  124.         else                            {reject attribute}
  125.           begin
  126.             packet[buffered] := buffer[i];
  127.             buffered := succ(buffered)
  128.           end;
  129.         i := succ(succ(i) + ord(unchar(buffer[succ(i)])))
  130.       end;
  131.     bufattr := buffered
  132.   end {bufattr};
  133.  
  134. function rdata: char;
  135.  
  136. (* receive file data *)
  137.  
  138. var dummy, num, len: integer;
  139.     ch: char;
  140.     {$B AFS+}
  141.     did_attr : boolean;
  142.     {$E AFS+}
  143.     i: integer;
  144.  
  145.   begin
  146.  
  147.     repeat
  148.         debugwrite('rdata');
  149.  
  150.         if numtry > maxtry then
  151.           begin
  152.             currstate := 'a';
  153.             exit(rdata)
  154.           end;
  155.         num_try := num_try + 1;
  156.  
  157.         ch := rpack(len,num,recpkt);   (* receive a packet *)
  158.  
  159.         refresh_screen(numtry,n);
  160.  
  161.         if (ch = 'D') then             (* got data packet *)
  162.           begin
  163.             if (num <> (n mod 64)) then (* wrong packet *)
  164.               begin
  165.                 if (oldtry > maxtry) then
  166.                   begin
  167.                     rdata := 'a';      (* too many tries, abort *)
  168.                     exit(rdata)
  169.                   end; (* if *)
  170.  
  171.                 if (num = (pred(n) mod 64)) then (* previous packet again *)
  172.                   begin                (* so re-ACK it *)
  173.                     spack('Y',num,0,packet);
  174.                     numtry := 0;       (* reset try counter *)
  175.                                        (* stay in same state *)
  176.                   end (* if *)
  177.                 else                   (* wrong number *)
  178.                     currstate := 'a'       (* so abort *)
  179.               end (* if *)
  180.             else                       (* right packet *)
  181.               begin
  182.                 bufemp(recpkt,len);  (* write data to file *)
  183.                 if read_ch(keyport, ch) then {check if user wants to can}
  184.                   packet[0] := ctl(ch);
  185.                 spack('Y',(n mod 64),ord(ord(ch) in [can_cur,can_all]),
  186.                       packet); (* ACK packet *)
  187.                 oldtry := numtry;      (* reset try counters *)
  188.                 numtry := 0;
  189.                 n := n + 1             (* bump packet number *)
  190.                                        (* stay in data receive state *)
  191.               end (* else *)
  192.           end (* if 'D' *)
  193.         else if ch = 'A' then           { Attributes }
  194.           begin
  195.             if (num <> (n mod 64)) then (* wrong packet *)
  196.               begin
  197.                 if (oldtry > maxtry) then
  198.                   begin
  199.                     rdata := 'a';      (* too many tries, abort *)
  200.                     exit(rdata)
  201.                   end; (* if *)
  202.  
  203.                 if (num = (pred(n) mod 64)) then (* previous packet again *)
  204.                   begin                (* so re-ACK it *)
  205.                     spack('Y',num,0,packet);
  206.                     numtry := 0;       (* reset try counter *)
  207.                                        (* stay in same state *)
  208.                   end (* if *)
  209.                 else                   (* wrong number *)
  210.                     currstate := 'a'       (* so abort *)
  211.               end (* if *)
  212.             else                       (* right packet *)
  213.               begin
  214.                 spack('Y',(n mod 64),bufattr(recpkt,len),packet); (* ACK packet *)
  215.                 oldtry := numtry;      (* reset try counters *)
  216.                 numtry := 0;
  217.                 n := n + 1             (* bump packet number *)
  218.                                        (* stay in data receive state *)
  219.               end (* else *)
  220.           end {if 'A'}
  221.         else if (ch = 'F') then        (* file header *)
  222.           begin
  223.             if (oldtry > maxtry) then
  224.               begin
  225.                 rdata := 'a';          (* too many tries, abort *)
  226.                 exit(rdata)
  227.               end; (* if *)
  228.  
  229.             if (num = (pred(n) mod 64)) then (* previous packet again *)
  230.               begin                    (* so re-ACK it *)
  231.                 spack('Y',num,0,packet);
  232.                 numtry := 0;           (* reset try counter *)
  233.                                                (* stay in same state *)
  234.               end (* if *)
  235.             else
  236.                 currstate := 'a'           (* not previous packet, abort *)
  237.           end (* if 'F' *)
  238.         else if (ch = 'Z') then        (* end of file *)
  239.           begin
  240.             if (num <> (n mod 64)) then(* wrong packet, abort *)
  241.               begin
  242.                 rdata := 'a';
  243.                 exit(rdata)
  244.               end; (* if *)
  245.             spack('Y',n mod 64,0,packet); (* ok, ACK it *)
  246.             if (len = 1) and (recpkt[0] = 'D')
  247.               then
  248.                 begin
  249.                   debugwrite(concat('Discarding ',xfilename));
  250.                   if f_is_binary               {discard the file}
  251.                     then close(b_file)
  252.                     else close(t_file)
  253.                 end
  254.               else
  255.                 begin
  256.                   debugwrite(concat('Closing ',xfilename));
  257.                   if f_is_binary               (* close up the file *)
  258.                     then
  259.                       begin
  260.                         if bufpos > 1               {data in last block}
  261.                           then
  262.                             begin
  263.                               for dummy := bufpos to blksize do
  264.                                 filebuf[dummy] := chr(0);
  265.                               dummy := blockwrite(b_file,filebuf,1);
  266.                               dummy := pred(bufpos);
  267.                               {$B AFS+}
  268.                               did_attr :=
  269.                                   put_attribute(b_file,FA_lastvalidbyte,dummy)
  270.                               {$E AFS+}
  271.                             end;
  272.                         {$B AFS+}
  273.                         with date_attr do if valid then {set date}
  274.                           did_attr :=
  275.                               put_attribute(b_file,FA_revisiondate,value);
  276.                         {$E AFS+}
  277.                         close(b_file,lock)
  278.                       end
  279.                     else
  280.                       begin
  281.                         {$B AFS+}
  282.                         with date_attr do if valid then {set date}
  283.                           did_attr :=
  284.                               put_attribute(t_file,FA_creationdate,value);
  285.                         {$E AFS+}
  286.                         close(t_file,lock)
  287.                       end;
  288.                   {$B AFS-}
  289.                   debugdate;
  290.                   with date_attr do if valid then {set date}
  291.                     case D_changedate(xfilename,value,
  292.                          [D_code,D_text,D_data,D_svol]) of
  293.                       D_okay :      debugwrite('Date set OK');
  294.                       D_notfound :  debugwrite('No such File, Date not set');
  295.                       D_nameerror : debugwrite('Name error, Date not set');
  296.                       D_offline :   debugwrite('Volume offline, Date not set');
  297.                       D_other :     debugwrite('Unknown error, Date not set');
  298.                     end {case};
  299.                   debugdate;
  300.                   {$E AFS-}
  301.                 end;
  302.             bufpos := 1;                {clean up binary file buffer}
  303.             n :=  n + 1;               (* bump packet counter *)
  304.             currstate := 'f';              (* go to complete state *)
  305.           end (* else if 'Z' *)
  306.         else if (ch = 'E') then        (* error packet *)
  307.           begin
  308.             error(recpkt,len);         (* display error *)
  309.             currstate := 'a'               (* and abort *)
  310.           end (* if 'E' *)
  311.         else if (ch <> chr(0)) then    (* some other packet type, *)
  312.             currstate := 'a'               (* abort *)
  313.     until (currstate <> 'd');
  314.     rdata := currstate
  315.   end; (* rdata *)
  316.  
  317. function rfile: char;
  318.  
  319. (* receive file header *)
  320.  
  321. var num, len: integer;
  322.     ch: char;
  323.     oldfn: string255;
  324.     i: integer;
  325.  
  326. procedure makename(recpkt: packettype; var fn: string255; l: integer);
  327.  
  328. function exist(fn: string255): boolean;
  329.  
  330. (* returns true if file named fn exists *)
  331.  
  332. var f: file;
  333.  
  334.   begin
  335.     (*$I-*) (* turn off i/o checking *)
  336.     reset(f,fn);
  337.     exist := (ioresult = 0);
  338.     (*$I+*)
  339.   end; (* exist *)
  340.  
  341. procedure checkname(var fn: string255);
  342.  
  343. (* if file fn exists, makes a new name which doesn't *)
  344. (* does this by changing letters in file name until it *)
  345. (* finds some combination which doesn't exitst *)
  346.  
  347. var ch: char;
  348.     i: integer;
  349.  
  350.   begin
  351.     i := 1;
  352.     while (i <= length(fn)) and exist(fn) do
  353.       begin
  354.         ch := succ(fn[i]);    {RTC, 13 May 89}
  355.         if not (ch in ['A'..'Z']) then ch := 'A';
  356.         while (ch in ['A'..'Z']) and exist(fn) do
  357.           begin
  358.             fn[i] := ch;
  359.             ch := succ(ch);
  360.           end; (* while *)
  361.         i := i + 1
  362.       end; (* while *)
  363.     end; (* checkname *)
  364.  
  365.   begin (* makename *)
  366.     fn := copy('               ',1,15);    (* stretch length *)
  367.     moveleft(recpkt[0],fn[1],l);           (* get filename from packet *)
  368.     oldfn := copy(fn, 1,l);                (* save fn sent to show user *)
  369.     fn := copy(fn,1,min(15,l));            (* set length of filename *)
  370.                                            (* and make sure <= 15 *)
  371.     uppercase(fn);
  372.     if not f_is_binary then
  373.         if (pos('.TEXT',fn) <> length(fn)-4) or (length(fn) < 5) then
  374.       begin
  375.         if length(fn) > 10 then
  376.             fn := copy(fn,1,10);           (* can only be 15 long in all *)
  377.         fn := concat(fn,'.TEXT');          (* and we'll add .TEXT *)
  378.       end; (* if *)
  379.     if fwarn then                          (* if file warning is on *)
  380.         checkname(fn);                     (* must check that name unique *)
  381.   end; (* makename *)
  382.  
  383.   begin (* rfile *)
  384.     debugwrite('rfile');
  385.  
  386.     if (numtry > maxtry) then         (* if too many tries, give up *)
  387.       begin
  388.         rfile := 'a';
  389.         exit(rfile)
  390.       end;
  391.     numtry := numtry + 1;
  392.  
  393.     ch := rpack(len,num,recpkt);      (* receive a packet *)
  394.  
  395.     refresh_screen(numtry,n);
  396.  
  397.     if ch = 'S' then                  (* send init, maybe our ACK lost *)
  398.       begin
  399.         if (oldtry > maxtry) then     (* too many tries, abort *)
  400.           begin
  401.             rfile := 'a';
  402.             exit(rfile)
  403.           end; (* if *)
  404.  
  405.         if num = (pred(n) mod 64) then      (* previous packet mod 64? *)
  406.           begin                       (* yes, ACK it again *)
  407.             spar(packet);             (* with our send init params *)
  408.             spack('Y',num,10,packet);
  409.             numtry := 0;              (* reset try counter *)
  410.             rfile := currstate;           (* stay in same state *)
  411.           end (* if *)
  412.         else                          (* not previous packet, abort *)
  413.           rfile := 'a'
  414.       end (* if 'S' *)
  415.     else if (ch = 'Z') then           (* end of file *)
  416.       begin
  417.         if (oldtry > maxtry) then     (* too many tries, abort *)
  418.           begin
  419.             rfile := 'a';
  420.             exit(rfile)
  421.           end; (* if *)
  422.  
  423.         if num = (pred(n) mod 64) then       (* previous packet mod 64? *)
  424.           begin                       (* yes, ACK it again *)
  425.             spack('Y',num,0,packet);
  426.             numtry := 0;
  427.             rfile := currstate            (* stay in same state *)
  428.           end (* if *)
  429.         else
  430.             rfile := 'a'              (* no, abort *)
  431.       end (* else if *)
  432.     else if (ch = 'F') then           (* file header *)
  433.       begin                           (* which is what we really want *)
  434.         if (num <> (n mod 64)) then   (* if wrong packet, abort *)
  435.           begin
  436.             rfile := 'a';
  437.             exit(rfile)
  438.           end;
  439.  
  440.         makename(recpkt,xfilename,len); (* get filename, make unique if filew *)
  441.         SC_erase_to_EOL(filepos,fileline);
  442.         write(oldfn,' ==> ',xfilename);
  443.  
  444.         if not getfil(xfilename) then  (* try to open new file *)
  445.           begin
  446.             ioerror(ioresult);        (* if unsuccessful, tell them *)
  447.             rfile := 'a';             (* and abort *)
  448.             exit(rfile)
  449.           end; (* if *)
  450.  
  451.         spack('Y',n mod 64,0,packet); (* ACK file header *)
  452.  
  453.         {initializations for file attribute data}
  454.         date_attr.valid := false;
  455.         {end of initializations for file attribute data}
  456.  
  457.         oldtry := numtry;             (* reset try counters *)
  458.         numtry := 0;
  459.         n := n + 1;                   (* bump packet number *)
  460.         rfile := 'd';                 (* switch to data state *)
  461.       end (* else if *)
  462.     else if ch = 'B' then             (* break transmission *)
  463.       begin
  464.         if (num <> (n mod 64)) then            (* wrong packet, abort *)
  465.           begin
  466.             rfile := 'a';
  467.             exit(rfile)
  468.           end;
  469.         spack('Y',n mod 64,0,packet); (* say ok *)
  470.         rfile := 'c'                  (* go to complete state *)
  471.       end (* else if *)
  472.     else if (ch = 'E') then
  473.       begin
  474.         error(recpkt,len);
  475.         rfile := 'a'
  476.       end
  477.     else if (ch = chr(0)) then        (* returned false *)
  478.         rfile := currstate                (* so stay in same state *)
  479.     else                              (* some weird state, so abort *)
  480.         rfile := 'a'
  481.   end; (* rfile *)
  482.  
  483. function rinit: char;
  484.  
  485. (* receive initialization *)
  486.  
  487. var num, len: integer;  (* packet number and length *)
  488.     ch: char;
  489.     fn : packettype;
  490.  
  491.   begin
  492.     debugwrite('rinit');
  493.  
  494.     if (numtry > maxtry) then         (* if too many tries, give up *)
  495.       begin
  496.         rinit := 'a';
  497.         exit(rinit)
  498.       end;
  499.     numtry := numtry + 1;
  500.  
  501.     if get_from_server then {ask server for files}
  502.       begin
  503.         len := length(xfilename);
  504.         moveleft(xfilename[1],fn[0],len);
  505.         spack('R', n mod 64, len, fn)
  506.       end;
  507.  
  508.     ch := rpack(len,num,recpkt); (* receive a packet *)
  509.     refresh_screen(num_try,n);
  510.  
  511.     if (ch = 'S') then           (* send init packet *)
  512.       begin
  513.         rpar(recpkt,len);            (* get other side's init data *)
  514.         spar(packet);            (* fill packet with my init data *)
  515.         ctl_set := [chr(0)..chr(31),chr(del),quote];
  516.         if en_qbin then ctl_set := ctl_set + [qbin];
  517.         spack('Y',n mod 64,10,packet); (* ACK with my params *)
  518.         get_from_server := false;
  519.         oldtry := numtry;        (* save old try count *)
  520.         numtry := 0;             (* start a new counter *)
  521.         n := n + 1;              (* bump packet number *)
  522.         rinit := 'f';            (* enter file receive state *)
  523.       end (* if 'S' *)
  524.     else if ch = 'Y' then
  525.       begin
  526.         rinit := 'r';
  527.         if n mod 64 = num then {we have the right ACK}
  528.           begin
  529.             get_from_server := false;
  530.             numtry := 0;
  531.             n := n + 1
  532.           end
  533.       end {if 'Y'}
  534.     else if (ch = 'E') then
  535.       begin
  536.         rinit := 'a';
  537.         error(recpkt,len)
  538.       end (* if 'E' *)
  539.     else if (ch = chr(0)) or (ch = 'N')  then
  540.         rinit := 'r'             (* stay in same state *)
  541.     else
  542.         rinit := 'a'             (* abort *)
  543.   end; (* rinit *)
  544.  
  545. (* state table switcher for receiving packets *)
  546.  
  547.   begin (* recswok *)
  548.     rec_ok := false;
  549.     writescreen('Receiving');
  550.     currstate := 'r';            (* initial state is receive *)
  551.     n := 0;                  (* set packet # *)
  552.     numtry := 0;             (* no tries yet *)
  553.     flush_comm;         {flush any garbage in buffer}
  554.  
  555.     while true do
  556.         if currstate in ['d', 'f', 'r', 'c', 'a'] then
  557.           case currstate of
  558.               'd': currstate := rdata;
  559.               'f': currstate := rfile;
  560.               'r': currstate := rinit;
  561.               'c': begin
  562.                      rec_ok := true;
  563.                      exit(recsw)
  564.                    end; (* case c *)
  565.               'a': exit(recsw)
  566.             end (* case *)
  567.         else (* state not in legal states *)
  568.           begin
  569.             debugwrite('Unknown State');
  570.             exit(recsw)
  571.           end (* else *)
  572.   end; (* recsw *)
  573.  
  574. procedure rec_version;
  575.  
  576.   begin
  577.     writeln(my_version)
  578.   end {rec_version};
  579.  
  580. end. { receiver }
  581.