home *** CD-ROM | disk | FTP | other *** search
/ Frostbyte's 1980s DOS Shareware Collection / floppyshareware.zip / floppyshareware / USCX / TBBS8502.ARC / FILESYS.INC < prev    next >
Text File  |  1985-10-06  |  25KB  |  850 lines

  1. (* ------------------------------------------------ FILESYS.INC ---------------------------------------------------*)
  2.  
  3. PROCEDURE filesys;
  4.  
  5.   const
  6.     mostfiles = 200;
  7.     soh = 1;
  8.     stx = 2;
  9.     eot = 4;
  10.     ack = 6;
  11.     nak = $15;
  12.     can = $18;
  13.     C   = $43;
  14.     ksize = 1; {minimum increment of file size in Kbytes}
  15.  
  16.   type
  17.     filerec = record
  18.                title    : name;
  19.                submit   : integer;
  20.                date     : name;
  21.                size     : integer;
  22.                accesses : integer;
  23.                ASCII    : boolean;
  24.                section  : byte;
  25.                public   : boolean;
  26.                progdesc : string[40];
  27.              end;
  28.     channel = array[0..127] of byte;
  29.     channelx = array[0..1023] of byte;
  30.  
  31.   var
  32.     filefile: file of filerec;
  33.     filetab: array[0..mostfiles] of filerec;
  34.     filebuff: array [0..16] of channel;
  35.     filebuffx: channelx;
  36.     datafile: file;
  37.     chksum: byte;
  38.     CRC: integer;
  39.     ymodem,
  40.     crcmode   : boolean;
  41.     junk,
  42.     enddir    : integer;
  43.     comch     : char;
  44.     hh, mm, ss: string[2];
  45.     tstr      : string[8];
  46.  
  47.  
  48.   PROCEDURE xmit(x:byte);
  49.     begin
  50.       xmitchar(chr(x));
  51.     end;
  52.  
  53.   FUNCTION inbyte: byte;
  54.  
  55.     var temp: char;
  56.  
  57.     begin
  58.       repeat until inready or not cts;
  59.       if keypressed then read(kbd, temp) else temp := recvchar;
  60.       inbyte := ord(temp);
  61.     end;
  62.  
  63.   PROCEDURE calcCRC(data:byte);
  64.  
  65.     var
  66.       carry: boolean;
  67.       i: byte;
  68.  
  69.     begin
  70.       chksum := lo(chksum + data);
  71.       for i := 0 to 7 do begin
  72.         carry := (crc and $8000) <> 0;
  73.         crc := crc shl 1;
  74.         if (data and $80) <> 0 then crc := crc or $0001;
  75.         if carry then crc := crc xor $1021;
  76.         data := lo(data shl 1);
  77.       end;
  78.     end;
  79.  
  80.   procedure soundbell;
  81.    var
  82.    junk : byte;
  83.  
  84.    begin
  85.      for junk := 1 to 3 do begin
  86.               charout(bell);
  87.               delay(600);
  88.               end;
  89.    end;
  90.  
  91.   PROCEDURE sendcalc(ch : byte);
  92.  
  93.     begin
  94.       xmit(ch);
  95.       calcCRC(ch);
  96.     end;
  97.  
  98.   PROCEDURE acknak(var inch: byte; time: integer);
  99.  
  100.     var loop, loopend: integer;
  101.  
  102.     begin
  103.       loopend := 100 * time;
  104.       loop := 0;
  105.       inch := 0;
  106.       repeat
  107.         delay(10);
  108.         if inready then inch := inbyte;
  109.         loop :=loop + 1;
  110.       until (inch in [ack, nak, can, C]) or (loop >= loopend) or not cts;
  111.     end;
  112.  
  113.   FUNCTION acknakout(ch : byte): boolean;
  114.  
  115.     var  times, loops: integer;
  116.  
  117.     begin
  118.       times := 0;
  119.       repeat
  120.         loops := 0;
  121.         xmit(ch);
  122.         while (loops < 10) and not timedin do loops := loops + 1;
  123.         times := times + 1;
  124.       until inready or (times > 9) or not cts;
  125.       acknakout := inready and cts;
  126.     end;
  127.  
  128.   PROCEDURE download (var successful: boolean);
  129.  
  130.     var
  131.       inch: byte;
  132.       loop, maxblock, maxxblock, numblocks, blocknum, period, tries: integer;
  133.       done: boolean;
  134.       temp: line;
  135.  
  136.     begin
  137.       reset(datafile);
  138.       if ymodem then str((filesize(datafile) div 8):4, temp) else begin
  139.            str(filesize(datafile):4, temp);
  140.            end;
  141.       if not ymodem then begin
  142.          lineout('Ready for XMODEM transfer:');
  143.          maxblock := 127;
  144.          maxxblock := 255;
  145.          numblocks := 1;
  146.          end else begin
  147.            lineout('Ready for YMODEM transfer:');
  148.            maxblock := 1023;
  149.            maxxblock := 2047;
  150.            numblocks := 8;
  151.            end;
  152.       lineout('File open:' + temp + ' records;');
  153.       lineout('To cancel: type CTL-X until you return to command prompt.');
  154.       {$I-} blockread(datafile, filebuffx[0], numblocks) {$I+};
  155.       if IOresult <> 0 then write('');
  156.       done := false;
  157.       tries := 0;
  158.       blocknum := 1;
  159.       repeat
  160.         acknak(inch, 60);
  161.         if inch = 0 then inch := can;
  162.         if inch = C then begin
  163.           crcmode := true;
  164.           writeln('CRC mode requested');
  165.         end;
  166.         if inch = ack then begin
  167.           if eof(datafile) then done := true else begin
  168.             write(cr + 'Sent #', blocknum:4);
  169.             {$I-} blockread(datafile, filebuffx[0], numblocks) {$I+};
  170.             if IOresult <> 0 then write('');
  171.             blocknum := blocknum + 1;
  172.             tries := 0;
  173.           end;
  174.         end
  175.         else tries := tries + 1;
  176.         if (inch <> can) and cts and not done then begin
  177.           if ymodem then xmit(stx) else xmit(soh);
  178.           xmit(lo(blocknum));
  179.           xmit(maxxblock-lo(blocknum));
  180.           chksum := 0;
  181.           crc := 0;
  182.           for loop := 0 to maxblock do sendcalc(filebuffx[loop]);
  183.           calcCRC(0);
  184.           calcCRC(0);
  185.           if crcmode then begin xmit(hi(crc)); xmit(lo(crc)); end
  186.             else xmit(chksum);
  187.         end;
  188.         if tries = 5 then crcmode := not crcmode;
  189.         if not crcmode and (tries = 5) then begin
  190.          ymodem := false;
  191.          maxblock := 127;
  192.          maxxblock := 255;
  193.          numblocks := 1;
  194.          end;
  195.       until (inch = can) or done or (tries= 10) or not cts;
  196.       successful := done;
  197.       tries := 0;
  198.       if successful and cts then repeat
  199.         xmit(eot);
  200.         acknak(inch, 10);
  201.         tries := tries + 1;
  202.       until (inch=ack) or (tries > 10) or not cts;
  203.       if cts and (inch <> can) and not successful then xmit(can);
  204.       close(datafile);
  205.     end;
  206.  
  207.  
  208.   FUNCTION recchar(var error: boolean): byte;
  209.  
  210.     var temp: byte;
  211.  
  212.     begin
  213.       temp := 0;
  214.       if not cts then error := true;
  215.       if not error then begin
  216.         if not timedin then error := true
  217.         else begin
  218.           temp := inbyte;
  219.           calcCRC(temp);
  220.           recchar := temp;
  221.         end;
  222.       end;
  223.     end;
  224.  
  225.   PROCEDURE clearline;
  226.  
  227.     var junk: byte;
  228.  
  229.     begin
  230.       while timedin do junk := inbyte;
  231.     end;
  232.  
  233. {$I-}
  234.   PROCEDURE upload(var successful: boolean);
  235.  
  236.     var
  237.       blocknum, tries, byteloc : integer;
  238.       comp, locblock, crc2     : integer;
  239.       fatal, error, done       : boolean;
  240.       opening, inch, locrc     : byte;
  241.       hicrc, csum2, mode       : byte;
  242.  
  243.     begin
  244.       lineout('Beginning XMODEM protocol upload:');
  245.       lineout('To cancel: type CTRL-X until you return to command prompt.');
  246.       tries := 0;
  247.       done := false;
  248.       opening := 0;
  249.       locblock := 1;
  250.       rewrite(datafile);
  251.       fatal := ioresult > 0;
  252.       if crcmode then mode := C else mode := nak;
  253.       if cts and not fatal then fatal := not acknakout(mode);
  254.       while cts and not (done or fatal) do begin
  255.         tries := tries + 1;
  256.         error := false;
  257.         opening := recchar(error);
  258.         if opening = can then fatal := true;
  259.         if opening = eot then done := true;
  260.         if (opening <> eot) and (opening <> soh) and not fatal
  261.           then error := true;
  262.         if cts and not (error or fatal or done) then begin
  263.           blocknum := recchar(error);
  264.           comp := recchar(error);
  265.           if lo(comp + blocknum + opening) <> 0 then error := true;
  266.           byteloc := 0;
  267.           crc := 0;
  268.           chksum := 0;
  269.           while (byteloc < 128) and not (error or fatal) do begin
  270.             filebuff[0][byteloc] := recchar(error);
  271.             byteloc := byteloc + 1;
  272.           end;
  273.           if cts and not (error or fatal) then begin
  274.             calcCRC(0);
  275.             calcCRC(0);
  276.             crc2 := crc;
  277.             csum2 := chksum;
  278.             hicrc := recchar(error);
  279.             if crcmode then begin
  280.               locrc := recchar(error);
  281.               if (lo(crc2) <> locrc) or (hi(crc2) <> hicrc) then error := true;
  282.             end else if csum2 <> hicrc then error := true;
  283.             if (lo(locblock) <> blocknum)
  284.               and (lo(locblock) <> lo(blocknum+1))
  285.               and not error
  286.               then fatal := true;
  287.             if (lo(locblock) = blocknum) and not (error or fatal) then begin
  288.               blockwrite(datafile, filebuff[0], 1);
  289.               write(cr + ' Received #', blocknum:4);
  290.               if IOresult <> 0 then fatal := true;
  291.               tries := 0;
  292.               locblock := locblock + 1;
  293.             end;
  294.           end;
  295.         end;
  296.         if not (fatal or error) then flush else clearline;
  297.         if done or not (error or fatal) then fatal := not acknakout(ack);
  298.         if error and not fatal then begin
  299.           fatal := not acknakout(nak);
  300.           if tries > 6 then crcmode := not crcmode;
  301.         end;
  302.       end;
  303.       if fatal then xmit(can);
  304.       if done then xmit(ack);
  305.       close(datafile);
  306.       successful := (IOresult = 0) and done and not fatal;
  307.       if not successful then erase(datafile);
  308.     end;
  309.  
  310.   PROCEDURE storebuff(var buffernum: byte; var paused, aborted: boolean);
  311.  
  312.     var loop: byte;
  313.  
  314.     begin
  315.       loop := 0;
  316.       while (loop < buffernum) and not aborted do begin
  317.         blockwrite(datafile, filebuff[loop], 1);
  318.         if IOresult > 0 then aborted := true;
  319.         loop := loop + 1;
  320.       end;
  321.       if buffernum in [1..16] then filebuff[0] := filebuff[buffernum];
  322.       buffernum := 0;
  323.       repeat xmit(17) until timedin;
  324.       paused := false;
  325.     end;
  326.  
  327.   PROCEDURE textcap(var successful: boolean);
  328.  
  329.     var
  330.       buffernum, where, loop  : byte;
  331.       cc, cz, paused          : boolean;
  332.       withecho, done, aborted : boolean;
  333.       temp                    : byte;
  334.  
  335.     begin
  336.       withecho := (getcap('Do you want your text echoed (Y/N) ? ') = 'Y');
  337.       lineout('Beginning text capture: two CTRL-Cs abort, two CTRL-Zs end.');
  338.       cc := false;
  339.       cz := false;
  340.       done := false;
  341.       paused := false;
  342.       buffernum := 0;
  343.       where := 0;
  344.       rewrite(datafile);
  345.       aborted := (IOresult > 0);
  346.       while cts and not (done or aborted) do begin
  347.         if paused then
  348.           if not timedin then storebuff(buffernum, paused, aborted);
  349.         temp := inbyte;
  350.         if not cts then aborted := true;
  351.         if withecho and outready then xmit(temp);
  352.         if temp = 3 then begin if cc then aborted := true else cc := true; end
  353.           else cc := false;
  354.         if temp = 26 then begin if cz then done := true else cz := true; end
  355.           else cz := false;
  356.         filebuff[buffernum][where] := temp;
  357.         where := where + 1;
  358.         if where > 127 then begin
  359.           where := 0;
  360.           buffernum := buffernum + 1;
  361.         end;
  362.         if buffernum > 14 then begin
  363.           xmit(19);
  364.           paused := true;
  365.         end;
  366.         if buffernum > 16 then aborted := true;
  367.       end;
  368.       if done and cts and not aborted then begin
  369.         buffernum := buffernum + 1;
  370.         storebuff(buffernum, paused, aborted);
  371.       end;
  372.       close(datafile);
  373.       if aborted and (IOresult = 0) then erase(datafile);
  374.     successful := done and (IOresult=0) and not aborted;
  375.     end;
  376. {$I+}
  377.  
  378.   FUNCTION exists(filename: name): boolean;
  379.  
  380.     var found: boolean;
  381.  
  382.     begin
  383.       assign(datafile, filename);
  384.       {$I-} reset(datafile) {$I+};
  385.       found := (IOresult = 0);
  386.       if found then close(datafile);
  387.       exists := found;
  388.     end;
  389.  
  390.   FUNCTION alpha(filename: name): boolean;
  391.  
  392.     var strpos: integer;
  393.         okay:   boolean;
  394.         dots:   byte;
  395.  
  396.     begin
  397.       dots := 0;
  398.       alpha := true;
  399.       if length(filename) > 0 then
  400.         for strpos := 1 to length(filename) do begin
  401.           if filename[strpos] = '.' then dots := dots + 1;
  402.           if not (filename[strpos] in ['.', '-', '_', '0'..'9', 'A'..'Z'])
  403.             then alpha := false;
  404.         end;
  405.       if dots > 1 then alpha := false;
  406.     end;
  407.  
  408.   FUNCTION getlegal: name;
  409.  
  410.     var filename:  name;
  411.         dotpos: integer;
  412.         comfile: file of line;
  413.         head : line;
  414.  
  415.     begin
  416.       repeat
  417.         filename := allcaps(getinput('Enter name of file ? ', 12, echo));
  418.         dotpos := pos('.', filename);
  419.       until ((dotpos < 10) and (dotpos <> 1)
  420.        and (not((dotpos = 0) and (length(filename) > 8)))
  421.        and (not((dotpos > 0) and (length(filename) > dotpos + 3)))
  422.        and alpha(filename))
  423.        or (filename = '');
  424.       getlegal := filename;
  425.  
  426.  { WRITE AN AUDIT RECORD IN THE COMMENT FILE FOR ANY FILE ACCESS }
  427.       if (caller <> 'SYSOP') then begin
  428.         assign(comfile, 'comments.bbs');
  429.         {$I-} reset(comfile) {$I+};
  430.         if IOresult <> 0 then rewrite(comfile);
  431.         seek(comfile, filesize(comfile));
  432.         head := caller;
  433.         if clockin then head := head + ' ' + timeon + ' ' + filename
  434.                    else head := head + ' ' + filename;
  435.         write(comfile, head);
  436.         close(comfile);
  437.       end;
  438.     end;
  439.  
  440.   FUNCTION dirpos(filename: name): integer;
  441.  
  442.     var loopvar: integer;
  443.  
  444.     begin
  445.       dirpos := 0;
  446.       loopvar := 0;
  447.       repeat
  448.         loopvar := loopvar + 1;
  449.       until (filetab[loopvar].title = filename) or (loopvar >= enddir);
  450.     if filetab[loopvar].title = filename then dirpos := loopvar;
  451.     end;
  452.  
  453.   FUNCTION getsect: byte;
  454.  
  455.     var temp: integer;
  456.  
  457.     begin
  458.       if sectsin then repeat
  459.         temp := getint(numsects, 0, 'Which section (0 for all, ? for list) ? ');
  460.         if temp = -1 then listsections else getsect := temp;
  461.       until (temp <> -1) or not cts
  462.       else getsect := 1;
  463.     end;
  464.  
  465.  
  466.   PROCEDURE addfile(filename: name; sectnum: byte; xmodem: boolean);
  467.  
  468.     begin
  469.       with filetab[enddir + 1] do begin
  470.         title    := filename;
  471.         submit   := usernum;
  472.         progdesc := getinput('Enter brief description of file? ', 41, echo);
  473.         if clockin then date := timeon;
  474.         assign(datafile, filedrive + filename);
  475.         reset(datafile);
  476.         size := filesize(datafile);
  477.         close(datafile);
  478.         accesses := 0;
  479.         ASCII := not xmodem;
  480.         section := sectnum;
  481.         public := false;
  482.       end;
  483.     end;
  484.  
  485.   PROCEDURE newfile(xmodem: boolean);
  486.  
  487.     var
  488.       filename: name;
  489.       successful: boolean;
  490.       sectnum: byte;
  491.  
  492.     begin
  493.       clearsc;
  494.       if access < reg then lineout('You can not send a file yet.  Use [A]pply command.')
  495.        else begin
  496.       if enddir >= mostfiles then lineout('No file space available.')
  497.       else begin
  498.         stringout('Upload: ');
  499.         filename := getlegal;
  500.         if filename <> '' then begin
  501.           if exists(filedrive + filename) then lineout('File name in use.')
  502.           else begin
  503.             repeat sectnum := getsect until (sectnum <> 0) or not cts;
  504.             assign(datafile, filedrive + filename);
  505.             if cts then begin
  506.               if xmodem then upload(successful)
  507.                 else textcap(successful);
  508.               if successful then addfile(filename, sectnum, xmodem);
  509.               clearline;
  510.               if successful then enddir := enddir + 1
  511.                 else lineout('Fatal transfer error or disk full...');
  512.             end;
  513.           end;
  514.         end;
  515.       end;
  516.     end;
  517.    end;
  518.  
  519.   FUNCTION legaltab(prompt: line): integer;
  520.  
  521.     var filename: name;
  522.         tabloc:   integer;
  523.  
  524.     begin
  525.       tabloc := 0;
  526.       clearsc;
  527.       stringout(prompt);
  528.       filename := getlegal;
  529.       if filename <> '' then begin
  530.         tabloc := dirpos(filename);
  531.         if tabloc <> 0 then
  532.           if not (filetab[tabloc].public or (access > paying)) then tabloc := 0;
  533.         if tabloc <> 0 then assign(datafile, filedrive + filename)
  534.           else if filename <> '' then lineout('No such file available.');
  535.       end;
  536.       legaltab := tabloc;
  537.     end;
  538.  
  539.   PROCEDURE transmitfile;
  540.  
  541.     var
  542.       successful: boolean;
  543.       tabloc    : integer;
  544.       filetime  : real;
  545.       timeok    : boolean;
  546.       temp      : line;
  547.  
  548.     begin
  549.      if access < reg then lineout('You can not receive a file yet.  Use [A]pply command.')
  550.      else begin
  551.       timeok := false;
  552.       calcconnect(usehour, usemin, usesec);
  553.       tottime := (usehour * 3600) + (usemin * 60) + usesec;
  554.       tabloc := legaltab('Download: ');
  555.       if tabloc > 0 then begin
  556.         {$I-} reset(datafile) {$I+};
  557.         if IOresult = 0 then timeok := true;
  558.         filetime := filesize(datafile) * 1.35;
  559.         if baud = slow then filetime := filesize(datafile) * 5.4;
  560.         str(filetime:4:0, temp);
  561.         lineout('Transfer time ' + temp + ' seconds');
  562.         if maxtime < (tottime + filetime) then timeok := false;
  563.         if not timeok then lineout('Transfer time to long for time remaining') else begin
  564.             download(successful);
  565.             if successful then with filetab[tabloc] do begin
  566.               accesses := accesses + 1;
  567.               soundbell;
  568.             end else lineout('Transfer failed.');
  569.         end;
  570.       end;
  571.     end;
  572.    end;
  573.  
  574.   procedure textdump;
  575.  
  576.     var
  577.       junk,
  578.       tabloc : integer;
  579.       libname: longname;
  580.  
  581.     begin
  582.      if access < reg then lineout('You can not receive a file yet.  Use [A]pply command.')
  583.       else begin
  584.       tabloc := legaltab('ASCII text dump: ');
  585.       lineout(space);
  586.       if tabloc > 0 then with filetab[tabloc] do begin
  587.         libname := title;
  588.         if pos('.LBR', title) > 1 then begin
  589.           lineout(title + ' is a library file: please select a member: ');
  590.           libname := getlegal;
  591.           if libname = '' then libname := 'DIR';
  592.           libname := copy(title, 1, length(title)-4) + '/' + libname;
  593.         end;
  594.         typefile(filedrive + libname, false);
  595.         if not cancelled then begin
  596.           soundbell;
  597.           accesses := accesses + 1;
  598.         end;
  599.       end;
  600.     end;
  601.    end;
  602.  
  603. PROCEDURE showspace;
  604.  
  605. type                            { TYPE declarations }
  606.   RegRec =
  607.     record           { register pack Used in MSDos call }
  608.       AX, BX, CX, DX, BP, SI, DI, DS, ES, Flags : Integer;
  609.     end;
  610.  
  611. var
  612.   Tracks,                              { number of available Tracks }
  613.   Drive,                               { Drive number }
  614.   Bytes,                               { number of Bytes in one sector }
  615.   Sectors              : Integer;      { number of total Sectors }
  616.   TotalBytes           : real;
  617.   Regs                 : RegRec;
  618.   temp                 : line;
  619.  
  620.  
  621.  begin
  622.   Drive := 0;                             { Initialize Drive }
  623.   Regs.AX := $3600;               { Get Disk free space }
  624.   Regs.DX := Drive;               { Store Drive number }
  625.   MSDos( Regs );                  { Call MSDos to get disk info }
  626.   Tracks := Regs.BX;              { Get number of Tracks Used }
  627.   Bytes := Regs.CX;                {  "    "    "  Bytes per sector }
  628.   Sectors := Regs.AX;              {  "    "    "  Sectors per cluster }
  629.   TotalBytes := (( Sectors * Bytes * 1.0 ) * Tracks);
  630.   str(totalbytes:8:0, temp);
  631.   if cts then lineout(cr + lf + temp + ' bytes available');
  632.  end;
  633.  
  634. PROCEDURE dir(sectnum: byte);
  635.  
  636.     var loop, spaces : byte;
  637.         howbig, sectmin : integer;
  638.         any  : boolean;
  639.         temp : line;
  640.  
  641.     begin
  642.       any := false;
  643.       sectmin := ksize shl 3;
  644.       lineout_withpause(space);
  645.       if sectsin then lineout_withpause('Section ' + sect[sectnum] + ':');
  646.       if enddir > 0 then for loop := 1 to enddir do with filetab[loop] do begin
  647.         howbig := (size + sectmin - 1) div sectmin;
  648.         if cts and (public or (access = sysop) or (submit = usernum))
  649.          and (sectnum = section) then begin
  650.           str(howbig:4, temp);
  651.           for spaces := length(title) to 13 do temp := ' ' + temp;
  652.           stringout(title + temp + 'K ');
  653.           if clockin then stringout(' ' + date + ' ');
  654.           if not public then stringout('* Private * ');
  655.           lineout_withpause(progdesc);
  656.           if (access = sysop) or (submit = usernum) then begin
  657.             str(accesses:4, temp);
  658.             lineout_withpause('Accesses: ' + temp + '    From: ' + getname(submit));
  659.           end;
  660.           any := true;
  661.         end;
  662.       end;
  663.       if cts and not any then lineout_withpause('No files found.');
  664.     end;
  665.  
  666.  
  667.   PROCEDURE directory;
  668.  
  669.     var sectnum : byte;
  670.  
  671.     begin
  672.       linecnt := 0;
  673.       stringout('Directory: ');
  674.       sectnum := getsect;
  675.       if sectnum > 0 then dir(sectnum)
  676.         else for sectnum := 1 to numsects do dir(sectnum);
  677.       showspace;
  678.     end;
  679.  
  680.   PROCEDURE ldir;
  681.  
  682.     var
  683.       tabloc : integer;
  684.  
  685.     begin
  686.       tabloc := legaltab('Library directory: ');
  687.       lineout(space);
  688.       if tabloc > 0 then typefile(filedrive + filetab[tabloc].title + '/DIR', false);
  689.     end;
  690.  
  691.   PROCEDURE killfile;
  692.  
  693.     var loop, tabloc: integer;
  694.  
  695.     begin
  696.       tabloc := legaltab('Delete: ');
  697.       if tabloc > 0 then begin
  698.         if enddir > tabloc then for loop := tabloc + 1 to enddir do
  699.           filetab[loop - 1] := filetab[loop];
  700.         enddir := enddir - 1;
  701.       end;
  702.     end;
  703.  
  704.   PROCEDURE installfile;
  705.  
  706.     var filename : name;
  707.         sectnum  : byte;
  708.  
  709.     begin
  710.       if enddir < mostfiles then begin
  711.         filename := getlegal;
  712.         if filename <> '' then begin
  713.           if exists(filedrive+filename) and (dirpos(filename) = 0) then begin
  714.             repeat sectnum := getsect until (sectnum <> 0) or not cts;
  715.             addfile(filename, sectnum, true);
  716.             enddir := enddir + 1;
  717.             lineout('File installed.');
  718.           end;
  719.         end;
  720.       end;
  721.     end;
  722.  
  723.   FUNCTION newname(tabloc: integer): name;
  724.  
  725.     var filename: name;
  726.  
  727.     begin
  728.       newname := filetab[tabloc].title;
  729.       stringout('New name? ');
  730.       filename := getlegal;
  731.       if (filename <> '') then begin
  732.         if not exists(filedrive + filename) then begin
  733.           assign(datafile, filedrive + filetab[tabloc].title);
  734.           rename(datafile, filename);
  735.           newname := filename;
  736.           stringout('File renamed.');
  737.         end
  738.         else lineout('Name in use - cannot rename.');
  739.       end;
  740.     end;
  741.  
  742.  
  743.   PROCEDURE editheader;
  744.  
  745.     var tabloc: integer;
  746.         filename: name;
  747.         innum: integer;
  748.         sectstring: name;
  749.  
  750.     begin
  751.       tabloc := legaltab('Edit: ');
  752.       if tabloc > 0 then with filetab[tabloc] do begin
  753.         repeat
  754.           str(section:3, sectstring);
  755.           lineout(space);
  756.           lineout('1- Name    : ' + title);
  757.           lineout('2- From    : ' + getname(submit));
  758.           lineout('3- Section : ' + sectstring);
  759.           lineout('4- Public? : ' + yn[public]);
  760.           lineout('5- Desc.   : ' + progdesc);
  761.           lineout(space);
  762.           innum := getint(5, 0, 'Number of parameter to change? ');
  763.           case innum of
  764.             1: title    := newname(tabloc);
  765.             2: submit   := getid('Name of submitter? ');
  766.             3: repeat section := getsect until (section <> 0) or not cts;
  767.             4: public   := not public;
  768.             5: progdesc := getinput('Enter brief description of file? ', 41, echo);
  769.           end;
  770.         until (innum = 0) or not cts;
  771.         assign(datafile, filedrive + title);
  772.         reset(datafile);
  773.         size := filesize(datafile);
  774.         close(datafile);
  775.       end else lineout('File not in directory.');
  776.     end;
  777.  
  778.   PROCEDURE initfile;
  779.  
  780.     var
  781.       loopvar: integer;
  782.       temp: name;
  783.  
  784.     begin
  785.       lineout('Initializing file system...');
  786.       loopvar := 0;
  787.       assign(filefile, 'FILES.BBS');
  788.       {$I-} reset(filefile) {$I+};
  789.       if IOresult = 0 then begin
  790.         while not eof(filefile) do begin
  791.           loopvar := loopvar + 1;
  792.           read(filefile, filetab[loopvar]);
  793.         end;
  794.         close(filefile);
  795.       end;
  796.       enddir := loopvar;
  797.       filesopen := true;
  798.     end;
  799.  
  800.   PROCEDURE closefile;
  801.  
  802.       var
  803.         loopvar: integer;
  804.  
  805.     begin
  806.       rewrite(filefile);
  807.       if enddir > 0 then
  808.         for loopvar := 1 to enddir do write(filefile, filetab[loopvar]);
  809.       close(filefile);
  810.       filesopen := false;
  811.     end;
  812.  
  813.   begin
  814.     clearsc;
  815.     initfile;
  816.     if not expert then outfile(filemenu);
  817.     repeat
  818.       checktime;
  819.       lineout(space);
  820.       str(usehour:2,hh);
  821.       str(usemin:2,mm);
  822.       str(usesec:2,ss);
  823.       tstr := hh + ':' + mm + ':' + ss;
  824.       for junk := 1 to 8 do
  825.         if tstr[junk] = ' ' then tstr[junk] := '0';
  826.       if not expert then comch := getcap('File Section ' + tstr + ' (A,C,D,G,H,L,Q,S,T,U,X,Y,?) ? ')
  827.         else comch := getcap('File Section ' + tstr + ' ? ');
  828.       case comch of
  829.        'D' : directory;
  830.        'Y' : begin ymodem := true;  crcmode := true; transmitfile; end;
  831.        'S' : begin ymodem := false; transmitfile; end;
  832.        'T' : textdump;
  833.        'H' : outfile(filehelp);
  834.        'G' : disconnect;
  835.        '?' : outfile(filemenu);
  836.        'X' : expert := not expert;
  837.        'L' : ldir;
  838.        'U' : begin crcmode := true; newfile(true); end;
  839.        'C' : begin crcmode := false; newfile(true); end;
  840.        'A' : newfile(false);
  841.        'K' : if access = sysop then killfile;
  842.        'I' : if access = sysop then installfile;
  843.        'E' : if access = sysop then editheader;
  844.       end;
  845.     until (comch = 'Q') or not cts;
  846.     if cts then lineout('Closing file system...');
  847.     closefile;
  848.   end;
  849.  
  850.