home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD1.mdf / pascal / library / dos / files / fileman / mdel / mdel.pas < prev   
Encoding:
Pascal/Delphi Source File  |  1988-09-03  |  24.4 KB  |  796 lines

  1. {
  2.                        F i l e    I n f o r m a t i o n
  3.  
  4. * DESCRIPTION
  5. MDEL (version T1.0) by Michael Miller is a replacement for the
  6. DOS DELete command. Written in Turbo Pascal 4.0. MDEL emulates
  7. the VAX/VMS delete utility, which includes several options not
  8. available in the DOS version.
  9.  
  10. * ASSOCIATED FILES
  11. MDEL.PAS
  12. MDEL.DOC
  13. MDEL.EXE
  14.  
  15. ==========================================================================
  16. }
  17. program mdel;
  18. {
  19.   Copyright by
  20.    Michael M. Miller
  21.    Box 293
  22.    Hecker,Il,62248
  23.    2 Mar 1988
  24.    All Rights Reserved
  25.    Released for non-commercial use only
  26. }
  27. uses dos;
  28.  
  29. type
  30.   string8 = string[8];
  31.   userspec = string[64];
  32.   filename = string[13];
  33.   entry_type = record
  34.                 dirname : string[13];
  35.                 level : integer;
  36.                end;
  37.   stack_ptr = ^stack;
  38.   stack = record
  39.             entry : entry_type;
  40.             next : stack_ptr;
  41.           end;
  42.  
  43. var
  44.   transferrec : searchrec;
  45.  
  46.   excl_spec,matchptrn,path,pathtmp : userspec;
  47.  
  48.   excl_nam,exc_nam,exc_ext,
  49.   match_nam,match_ext,retname,file_nam : filename;
  50.  
  51.   exc_flag,place,pcnt,
  52.   a_date,b_date,
  53.   current_lvl,match_flag,lvl : integer;
  54.  
  55.   confirm ,log, after, before,exclude,
  56.   nofind,lastfile,empty,excl_mult,
  57.    multiple,subdirec : boolean;
  58.  
  59.   stk : stack_ptr;
  60.  
  61.   dir_rec : entry_type;
  62.  
  63.   dirpath : array[1..20] of filename;
  64.  
  65. procedure error(status : byte);
  66.  
  67. begin
  68.   write(^G,'Error --');
  69.   case status of
  70.      1 : writeln(' Invalid function');
  71.      2 : writeln(' File not found');
  72.      3 : writeln(' Path not found');
  73.      4 : writeln(' Too many open files');
  74.      5 : writeln(' Access denied');
  75.      6 : writeln(' Invalid file handle');
  76.      7 : writeln(' Arena trashed');
  77.      8 : writeln(' Not enough memory');
  78.      9 : writeln(' Invalid block');
  79.      10 : writeln(' No environment');
  80.      11 : writeln(' No format');
  81.      12 : writeln(' Invalid access code');
  82.      13 : writeln(' Invalid data');
  83.      15 : writeln(' Invalid drive');
  84.      16 : writeln(' Can not remove current directory');
  85.      17 : writeln(' Not same device');
  86.      18 : writeln(' No more files');
  87.      20 : writeln(' Invalid number of parameters.');
  88.   end;
  89.   halt;   {no return from here}
  90. end;
  91.  
  92.  
  93. function get_current_drive:byte;
  94. { get default drive spec }
  95.  var regs : registers;
  96.  
  97. begin
  98.   with regs do
  99.    begin
  100.      ax := $1900;       {set DOS function}
  101.      msdos(regs);
  102.      get_current_drive := lo(ax);       {return drive #}
  103.    end;
  104. end;
  105.  
  106. procedure give_help;
  107. var ans : char;
  108. begin
  109.    writeln('MDEL  File delete utility');
  110.    writeln('Command format:');
  111.    writeln('mdel[/l][/c][/a=mm-dd-yy][/b=mm-dd-yy][/e=[path]filename] [path]filename');
  112.    writeln(' (brackets indicate optional items)');
  113.    writeln('Parameters and switches');
  114.    writeln('  /l              list files as they are deleted. Default for *.* filename');
  115.    writeln('  /c              confirm that this file is to be deleted');
  116.    writeln('  /e              exclude specified files from being deleted');
  117.    writeln('  /a  /b          allows before and after dates to select which');
  118.    writeln('                   files are to be deleted. date format is mm-dd-yy');
  119.    write('Press return for more...');
  120.    readln(ans);
  121.    writeln('  Path format');
  122.    writeln('  path\filename             delete specified file');
  123.    writeln('  drv:\dirnam...\filename   delete file(s) from directory and all subtrees');
  124.    writeln('  drv:\*...\filename        delete file(s) on entire given drive');
  125.    writeln('  *...\filename             delete file(s) on entire default drive');
  126.    writeln('  ...\filename              delete file(s) from current directory & subtrees');
  127.    writeln('  Filename format');
  128.    writeln('   name.ext          any valid file name');
  129.    writeln('   [*].ext           delete all files that end with ext');
  130.    writeln('   name[.*]          delete all files that start with name');
  131.    writeln('   [*cc*][.*cc*]     delete files based on a combination of wildcards');
  132.    writeln('                     wildcards can be at the beginning or end of each part of');
  133.    writeln('                     the filename but not at the same time. For example:');
  134.    writeln('                       *trek.p*  is valid   *tre*.pas  is invalid');
  135.    writeln(' Copyright 1988  Michael M. Miller');
  136.    halt;  { do nothing else if help given}
  137. end;
  138.  
  139.  
  140. procedure push (var top: stack_ptr;
  141.                     new_entry: entry_type);
  142. { This routine pushes an entry onto a stack. }
  143.  
  144.   var
  145.     temp: stack_ptr;       {temporary record}
  146.  
  147.   begin
  148.     new(temp);   {create a new record}
  149.     temp^.entry := new_entry; {fill the record with the entry information} 
  150.     temp^.next := top;    {link the new record to the top of the stack}
  151.     top := temp;   {set the top of the stack to the new record}
  152.   end;   { push }
  153.  
  154. procedure pop (var top: stack_ptr;
  155.            var top_entry: entry_type;
  156.              var empty_stack: boolean);
  157. { This routine pops the top record off of the stack and
  158. returns the value of its contents.  If the stack is empty,
  159. an error flag is set. }
  160.  
  161.  
  162.   var
  163.     temp: stack_ptr;        {temporary record}
  164.  
  165.   begin
  166.     if top = nil then   {if the stack is empty, set error flag}
  167.       empty_stack := true
  168.     else
  169.       begin
  170.         empty_stack := false;
  171.         top_entry := top^.entry;  {fill record from top of stack }
  172.         temp := top; {remember the current stack top for later disposal}
  173.         top := top^.next;  {move the top down}
  174.         dispose (temp);    {dispose of the old top record}
  175.       end;
  176.   end;  { pop }
  177.  
  178. procedure string_to_date (in_date: string8;
  179.               var day,month,year : integer;
  180.               var date_error: boolean);
  181. {
  182.     This procedure converts a date in string form to
  183.     its component parts.
  184.  
  185. parameters:
  186.     in_date (in) - the date input (mm-dd-yy)
  187.     day (out) - the day of the month [1-31]
  188.     month (out) - the month of the year [1-12]
  189.     year (out) - [1980-2099]
  190.     date_error (out) - flag showing if the numbers were bad
  191.  
  192. }
  193.  
  194.     var
  195.       VALCODE: integer;                   {the string convert error code}
  196.  
  197.     begin
  198.       date_error := false;
  199.       val(copy (in_date, 1, 2), month, valcode);  {convert the month}
  200.       if valcode <> 0 then
  201.     date_error := true
  202.       else
  203.     begin
  204.       val(copy (in_date, 4, 2), day, valcode);  {convert the day}
  205.       if valcode <> 0 then
  206.         date_error := true
  207.       else
  208.         begin
  209.           val(copy (in_date, 7, 2), year, valcode);  {convert the year}
  210.           if valcode <> 0 then
  211.         date_error := true;
  212.         end;
  213.     end;
  214.     end;
  215.  
  216. function set_match_date (day,month,year :integer): integer;
  217. {
  218.     This routine converts the input date to the format used
  219.     in the files FCB.
  220.  
  221. parameters:
  222.     day (in) - day of the month [1-31]
  223.     month (in) - month of the year [1-12]
  224.     year (in) - [1980-2099]
  225.     set_match_date(out) converted date
  226. }
  227. var match_date :integer;
  228.  
  229. begin   {convert date to internal format}
  230.   match_date := (year - 80) shl 9;
  231.   match_date := match_date + (month shl 5);
  232.   set_match_date := match_date + day;
  233. end;
  234.  
  235. procedure parse_sw(var count,index : integer);
  236. {this procedure decodes any command line option switches
  237.   and sets global variables for them. it also passes
  238.   back a modified parameter count and an index to the
  239.   file specification.
  240.  
  241. parameters
  242.  count (out)                   count of parameters left to process
  243.  index (out)                   postion of the file specification on
  244.                 the command line
  245.  confirm  (global)              boolean switches for the
  246.  log (global)                     various command line
  247.  after (global)                     switches that are
  248.  before (global)                       possible
  249.  a_date (global)                after date
  250.  b_date (global)                before date
  251.  
  252. }
  253. var
  254.   swf,err : boolean;      {flags that switches were found}
  255.   day,month,year,
  256.   s_count,i,x,j : integer;  {counters}
  257.   t_date : string8;    {temporary for any input date strings}
  258.   temp : userspec;     {temporary for the options}
  259.  
  260. begin
  261.   count := paramcount;   {make working copy}
  262.   if count <> 0
  263.    then begin
  264.     if count > 2 then error(20);
  265.     swf := false;
  266.     for x := 1 to count do
  267.     begin
  268.       if pos('/',paramstr(x)) = 1   { check for switches }
  269.       then begin
  270.     temp := paramstr(x);    {copy the switch string}
  271.     s_count:=0;
  272.     for i := 1 to length(temp) do
  273.     begin                    {get switch count}
  274.       if temp[i] = '/' then s_count := s_count + 1;
  275.       temp[i] := upcase(temp[i]);
  276.     end;
  277.     i := 2;  {set switch index}
  278.     for j := 1 to s_count do
  279.       case temp[i] of
  280.          'C' : begin
  281.              confirm := true;
  282.              i := i + 2;
  283.            end;
  284.          'L' : begin
  285.              log := true;
  286.              i := i + 2;
  287.            end;
  288.      'A','B' : begin
  289.              t_date := copy(temp,i+2,8);
  290.              string_to_date(t_date,day,month,year,err);
  291.              if not err
  292.              then begin
  293.                if temp[i] = 'A' then
  294.              begin
  295.               a_date := set_match_date(day,month,year);
  296.               after := true;
  297.              end
  298.                else begin
  299.              b_date := set_match_date(day,month,year);
  300.              before := true;
  301.             end;
  302.                i := i +11;
  303.                end
  304.              else begin
  305.               writeln('Error in date parameter');
  306.               halt;
  307.              end;
  308.            end;
  309.          'E' : begin
  310.              excl_spec := copy(temp,i+2,length(temp));
  311.              if pos('/',excl_spec) <> 0  {if not the last switch}
  312.                then begin                {keep only the exclude stuff}
  313.              excl_spec:=copy(excl_spec,1,pos('/',excl_spec)-1);
  314.              i:=i+length(excl_spec)+3;
  315.                end;
  316.              exclude:=true;
  317.            end;
  318.       end; {case}
  319.     swf := true;   { flag that a switch was found }
  320.       end;
  321.     end;        {for}
  322.     if swf and (count = 2)  {now set index to file spec if needed }
  323.      then index := 2
  324.      else if swf and (count = 1)
  325.          then count := 0
  326.          else index := 1;
  327.    end;
  328. end;   {parse_sw}
  329.  
  330.  
  331. procedure parse_path(var filnam : filename;
  332.              var rootnam : userspec;
  333.              var multple : boolean);
  334. { this routine will parse the input parameters and seperate the path name
  335.    from the file name.
  336.  
  337.  
  338. parameters
  339.  filnam (out)                   file to search for
  340.  rootnam (in/out)               (in) data to parse
  341.                 (out) search path start point
  342.  multple (out)                  single or multiple directory flag
  343.  paramstr(x) (global)           command line parameter(s)
  344. }
  345.  
  346. var
  347.  temp : userspec;
  348.  posinstr,i : integer;
  349.  ans : char;
  350. begin
  351.     temp := rootnam;        {make copy of input file spec}
  352.     if temp = '?' then give_help;
  353.     if (pos('\',temp) = 0) and (pos(':',temp) = 0) then   {only filename given}
  354.      begin
  355.        getdir(0,rootnam);
  356.        multple := false;
  357.        if (length(rootnam)=3) and (pos(':',rootnam) = 2) and (pos('\',rootnam) = 3)
  358.       then rootnam := chr(65+get_current_drive) + ':';
  359.        if (pos('.',temp) = 0) then temp := temp + '.*';
  360.        if pos('.',temp) = 1 then temp := '*' + temp;
  361.        filnam := '\' + temp;
  362.      end
  363.     else
  364.      begin      {extract path from input data}
  365.        if pos('\',temp)=0
  366.      then begin
  367.        posinstr:=pos(':',temp);
  368.        filnam := '\' + copy(temp,posinstr+1,length(temp));
  369.        rootnam := copy(temp,1,2);
  370.        end
  371.      else begin
  372.        posinstr:=length(temp);
  373.        while temp[posinstr] <> '\' do posinstr :=posinstr-1;
  374.        if (pos('\',temp)<>posinstr)
  375.        then begin
  376.          filnam := copy(temp,posinstr,length(temp));
  377.          rootnam := copy(temp,1,posinstr-1);
  378.         end
  379.        else begin
  380.          if (pos('\',temp) = 1) or (pos(':\',temp) = 2)
  381.            then begin
  382.              rootnam := copy(temp,1,length(temp));
  383.              filnam :='\*.*';
  384.              end
  385.            else begin
  386.              rootnam := copy(temp,1,posinstr-1);
  387.              filnam := copy(temp,posinstr,length(temp));
  388.            end;
  389.         end;
  390.       end;
  391.        if ((length(filnam)=1) and (filnam = '\')) then filnam :='\*.*';
  392.        if (pos('.',filnam) = 0) then filnam := filnam + '.*';
  393.        if pos('\.',filnam) = 1 then filnam := '\*' + copy(filnam,2,length(filnam));
  394.        if pos(':',rootnam) = 0
  395.      then if (pos('\',rootnam) = 1) or (length(rootnam) = 0)
  396.          then rootnam := chr(65+get_current_drive) + ':' + rootnam
  397.          else begin
  398.           getdir(0,temp);
  399.           if length(temp) = 0
  400.            then rootnam := chr(65+get_current_drive) + ':\' + rootnam
  401.            else rootnam := temp + '\' + rootnam;
  402.          end;
  403.        multple := false;        {say no wild card search for now}
  404.        posinstr := pos('*...',rootnam); {check for wild cards}
  405.        if posinstr > 0 then
  406.     begin
  407.       rootnam := copy(rootnam,1,2);
  408.       multple := true;
  409.     end
  410.        else
  411.     begin
  412.       posinstr := pos('...',rootnam); {check for other wild cards}
  413.       if posinstr > 0 then
  414.        begin
  415.         if rootnam[posinstr-1]='\'
  416.          then rootnam := copy(rootnam,1,posinstr-2)
  417.          else rootnam := copy(rootnam,1,posinstr-1);
  418.          multple := true;
  419.        end;
  420.     end;
  421.      end;
  422.     if pos('\*.*',filnam) > 0
  423.      then begin
  424.        write('Are you sure[Y/N]? ');
  425.        readln(ans);
  426.        if upcase(ans) = 'Y'
  427.      then log := true
  428.      else halt;
  429.        if not confirm
  430.        then begin
  431.      write('Do you wish to confirm each deletion[Y/N]?');
  432.      readln(ans);
  433.      if upcase(ans) = 'Y'
  434.        then confirm := true;
  435.        end;
  436.      end;
  437.     for i:= 1 to length(filnam) do
  438.      filnam[i] := upcase(filnam[i]); {convert to upper case}
  439.     for i:= 1 to length(rootnam) do
  440.      rootnam[i] := upcase(rootnam[i]); {convert to upper case}
  441. end;    {parsecmd}
  442.  
  443. procedure parsefil(var filnam:filename;
  444.                    var result_nam : filename;
  445.                    var result_ext : filename;
  446.                    var result_flag : integer);
  447. { this procedure parses the input file looking for wild cards and
  448.  sets a code specifing which action to take based on wild cards found.
  449.  
  450. parameters
  451.   filnam(in)             input filename
  452.   result_nam(out)        name porition of the filename
  453.   result_ext(out)        extension porition
  454.   result_flag(out)       action code used to match files
  455. }
  456.  
  457. var
  458.  nam_pos,ext_pos,dot_cnt :integer;
  459.  
  460.  
  461. begin
  462.   result_flag := 0;
  463.   dot_cnt := pos('.',filnam);   {get split point}
  464.   result_nam := copy(filnam,2,dot_cnt-2);
  465.   result_ext := copy(filnam,dot_cnt+1,3);
  466.   nam_pos := pos('*',result_nam);
  467.   ext_pos := pos('*',result_ext);
  468.   if ((nam_pos + ext_pos)=0)
  469.    then result_flag:=0  {no wild cards}
  470.    else
  471.     if ((nam_pos - ext_pos)=0) and (length(filnam)=4)
  472.      then result_flag:=1    {both wild}
  473.      else
  474.       begin
  475.         if nam_pos > 0 then
  476.          begin        {wild card in name}
  477.            if result_nam='*' then result_flag:=2
  478.            else
  479.             if result_nam[1]='*' then
  480.              begin
  481.                result_nam:=copy(result_nam,2,length(result_nam)-1);
  482.                result_flag:=3;         {wild 1st char}
  483.              end
  484.             else
  485.              begin
  486.                result_nam:=copy(result_nam,1,nam_pos-1);
  487.                result_flag:=4;         {wild last char}
  488.              end;
  489.          end;
  490.     if ext_pos > 0 then
  491.          begin        {wild card in ext}
  492.            if result_ext='*' then
  493.                  if result_flag = 0 then result_flag:=5
  494.                                     else result_flag:=result_flag+6
  495.            else
  496.             if result_ext[1]='*' then
  497.              begin
  498.                result_ext:=copy(result_ext,2,length(result_ext)-1);
  499.                if result_flag=0
  500.                 then result_flag:=6         {wild 1st char}
  501.                 else result_flag:=result_flag+10;
  502.              end
  503.             else
  504.              begin
  505.                result_ext:=copy(result_ext,1,ext_pos-1);
  506.                if result_flag=0
  507.                 then result_flag:=7         {wild last char}
  508.                 else result_flag:=result_flag+20;
  509.              end;
  510.          end;
  511.       end;
  512.   filnam := '\*.*'; {change input to catch everything}
  513. end; {parsefil}
  514.  
  515. procedure fndfirst(pattern : userspec; var found : filename;
  516.   var nomatch : boolean; var lastone : boolean;
  517.   var subdir :boolean);
  518.  
  519. var
  520.   count : integer;
  521.  
  522. begin
  523.  findfirst(pattern,anyfile,transferrec);
  524.  if doserror > 0 then
  525.   begin
  526.     case doserror of
  527.       2 : begin {no match}
  528.         nomatch:=true;
  529.         lastone:=true;
  530.       end;
  531.      18 : begin {no more files}
  532.         nomatch:=false;
  533.         lastone:=true;
  534.       end;
  535.     else error(doserror);
  536.     end; {case}
  537.   end
  538.   else
  539.    begin
  540.      nomatch:=false;
  541.      lastone:=false;
  542.    end;
  543.  if (not nomatch) then
  544.   with transferrec do
  545.   begin
  546.     found:=name;
  547.     if (attr and directory) > 10 {test to see if it is a subdirectory}
  548.      then
  549.       begin
  550.     subdir:=true;
  551.     if (found <> '.') and (found <> '..') then
  552.      begin   { found a subdir so put it on the stack }
  553.        dir_rec.dirname := found;
  554.        dir_rec.level := current_lvl;
  555.        push(stk,dir_rec);
  556.      end;
  557.       end
  558.      else begin
  559.        subdir:=false;
  560.      end;
  561.     for count:=length(found) +1 to 13
  562.       do found:=found + ' ';
  563.   end;
  564. end; {fndfirst}
  565.  
  566. procedure fndnext(var found : filename;
  567.   var lastone : boolean; var subdir : boolean);
  568.  
  569. var
  570.   count : integer;
  571.  
  572. begin
  573.   findnext(transferrec);
  574.   if doserror > 0 then
  575.    if doserror = 18 then lastone:=true
  576.             else error(doserror)
  577.   else lastone :=false;
  578.   if not lastone then
  579.    begin
  580.      with transferrec do
  581.      begin
  582.        found:=name;
  583.        if (attr and directory) > 10
  584.     then
  585.      begin
  586.        subdir:=true;
  587.        if (found <> '.') and (found <> '..') then
  588.         begin  { found a subdir so put it on the stack }
  589.           dir_rec.dirname := found;
  590.           dir_rec.level := current_lvl;
  591.           push(stk,dir_rec);
  592.         end;
  593.      end
  594.     else begin
  595.       subdir:=false;
  596.        end;
  597.        for count:=length(found) +1 to 13
  598.      do found:=found + ' ';
  599.      end; {with transferec}
  600.    end;
  601. end; {fndnext}
  602.  
  603. function check_file_name (file_name,chk_nam,chk_ext : filename;
  604.               chk_flag : integer) : boolean;
  605. { check the input filename against what was specified by the user
  606.   using the match code from parsefil
  607. }
  608.  var
  609.   tst_nam,tst_ext : filename;
  610.  
  611.  begin
  612.    check_file_name:=false;   {assume false until true}
  613.    tst_nam:=copy(file_name,1,pos('.',file_name)-1);  {extract the good}
  614.    tst_ext:=copy(file_name,pos('.',file_name)+1,3);  {  parts}
  615.    case chk_flag of  {now check for a valid file name}
  616.      0: if (chk_nam = tst_nam) and (chk_ext = tst_ext)
  617.           then check_file_name:=true;
  618.      1: check_file_name:=true;
  619.      2: if chk_ext = tst_ext then check_file_name:=true;
  620.      3: if (pos(chk_nam + '.',tst_nam + '.') > 0) and
  621.        (chk_ext = tst_ext) then check_file_name:=true;
  622.      4: if (pos(chk_nam,tst_nam) =1) and
  623.        (chk_ext = tst_ext) then check_file_name:=true;
  624.      5: if chk_nam = tst_nam then check_file_name:=true;
  625.      6: if (chk_nam = tst_nam) and (pos(chk_ext,tst_ext) >=1)
  626.            then check_file_name:=true;
  627.      7: if (chk_nam = tst_nam) and (pos('.'+chk_ext,'.'+tst_ext)>0)
  628.            then check_file_name:=true;
  629.      9: if (pos(chk_nam + '.',tst_nam + '.') > 0) then check_file_name:=true;
  630.     10: if (pos(chk_nam,tst_nam) =1) then check_file_name:=true;
  631.     12: if (pos(chk_ext,tst_ext) >=1) then check_file_name:=true;
  632.     13: if (pos(chk_nam + '.',tst_nam + '.') > 0) and
  633.        (pos(chk_ext,tst_ext) >=1) then check_file_name:=true;
  634.     14: if (pos(chk_nam,tst_nam) =1) and
  635.        (pos(chk_ext,tst_ext) >=1) then check_file_name:=true;
  636.     22: if  (pos('.'+chk_ext,'.'+tst_ext)>0) then check_file_name:=true;
  637.     23: if (pos(chk_nam + '.',tst_nam + '.') > 0) and
  638.        (pos('.'+chk_ext,'.'+tst_ext)>0) then check_file_name:=true;
  639.     24: if (pos(chk_nam,tst_nam) =1) and
  640.        (pos('.'+chk_ext,'.'+tst_ext)>0) then check_file_name:=true;
  641.    end;                {case of chk_flag}
  642.  end;    {check_file_name}
  643.  
  644. procedure delete_file (filename: userspec);
  645. {
  646.     This routine deletes the file specified.
  647.  
  648. parameters:
  649.     filename (in) - the file to delete
  650.     confirm  (global)   boolean switches for the
  651.     log (global)          various command line
  652.     after (global)          switches that are
  653.     before (global)           possible
  654.  
  655.  
  656. }
  657.   var
  658.     regs: registers;
  659.     ok_to_delete : boolean;
  660.     ans : char;
  661.     status : byte;
  662.     fdate : datetime;
  663.     filedate : integer;
  664.  
  665. begin
  666.     ok_to_delete := true;
  667.     if before or after   {check file date if needed}
  668.       then with transferrec do
  669.        begin
  670.      unpacktime(time,fdate);  {convert date to FCB format}
  671.      filedate := set_match_date(fdate.day,fdate.month,fdate.year-1900);
  672.      if after       {after date flag set}
  673.       then if  filedate < a_date then ok_to_delete := false
  674.                      else ok_to_delete := true;
  675.      if before       {before date flag set}
  676.       then if  filedate > b_date then ok_to_delete := false
  677.                      else ok_to_delete := true;
  678.      if before and after    {both date flags set}
  679.        then if (filedate <= b_date) and (filedate >= a_date)
  680.            then ok_to_delete := true
  681.            else ok_to_delete := false;
  682.        end; {with transferrec}
  683.     if confirm and ok_to_delete
  684.       then begin
  685.     write('Delete ',filename,' [Y/N/Q]? ');
  686.     readln(ans); ans:=upcase(ans);
  687.     if ans = 'Y' then ok_to_delete := true
  688.              else ok_to_delete := false;
  689.     if ans = 'Q' then halt;
  690.        end;
  691.     if ok_to_delete
  692.       then with regs do
  693.       begin  {convert the file name to delete to asciiz and set the registers
  694.         to delete the file}
  695.        filename := filename + chr(0);     {convert to asciiz}
  696.        ax := $4100;                       {DOS function code}
  697.        ds := seg(filename[1]);
  698.        dx := ofs(filename[1]);
  699.        msdos(regs);  {delete the file}
  700.        if ((1 and flags) = 1) then    {test status}
  701.        error(lo(ax));             {error if carry flag set}
  702.       end;
  703.     if log and ok_to_delete
  704.        then writeln('File ',filename,' deleted');
  705.   end; {delete_file}
  706.  
  707. procedure pad(var extension : filename; ext_code : integer);
  708. {
  709.   This procedure pads the input filename extension if it is
  710.   less than 3 characters. This allows easier matching to what
  711.   DOS returns in the check_file_name function.
  712. }
  713. begin
  714.   case ext_code of
  715.    0,2,3,4 : while length(extension) < 3
  716.               do extension := extension + ' ';
  717.   end; {case}
  718. end; {pad}
  719.  
  720. begin {main}
  721.   stk := nil; {init the globals}
  722.   confirm := false;
  723.   log := false;
  724.   after := false;
  725.   before := false;
  726.   exclude := false;
  727.   current_lvl := 1;
  728.   parse_sw(pcnt,place);  {process command line options}
  729.   if pcnt = 0 then
  730.     begin  { no input data so halt }
  731.       writeln(^G'*** Input Filename Missing. ***');
  732.       writeln;
  733.       give_help;
  734.     end;
  735.   if exclude
  736.    then begin
  737.      parse_path(excl_nam,excl_spec,excl_mult);   {process exclude file spec}
  738.      parsefil(excl_nam,exc_nam,exc_ext,exc_flag); {and filename}
  739.      if length(exc_ext) < 3
  740.         then pad(exc_ext,exc_flag);
  741.    end;
  742.   path:=paramstr(place);                {get input file spec}
  743.   parse_path(file_nam,path,multiple);   {parse path spec}
  744.   parsefil(file_nam,match_nam,match_ext,match_flag);  {now check the filename}
  745.                                                       {for wildcards}
  746.   if length(match_ext) < 3
  747.      then pad(match_ext,match_flag);
  748.   matchptrn := path + file_nam;
  749.   pathtmp := path;
  750.   repeat
  751.     fndfirst(matchptrn,retname,nofind,lastfile,subdirec);
  752.     if nofind or lastfile then writeln('No Files Found')
  753.      else
  754.       begin
  755.         while (not lastfile) do
  756.         begin
  757.      if exclude
  758.       then begin
  759.          if (excl_mult and (pos(excl_spec,pathtmp)>0)) or (excl_spec = pathtmp)
  760.              then begin
  761.           if not check_file_name(retname,exc_nam,exc_ext,exc_flag)
  762.              then if (check_file_name(retname,match_nam,match_ext,match_flag)
  763.                   and (not subdirec) and (not((transferrec.attr and volumeid)=8)))
  764.                  then Delete_file(pathtmp + '\' + retname);
  765.            end
  766.          else if (check_file_name(retname,match_nam,match_ext,match_flag)
  767.              and (not subdirec) and (not((transferrec.attr and volumeid)=8)))
  768.              then Delete_file(pathtmp + '\' + retname);
  769.       end
  770.       else begin
  771.        if (check_file_name(retname,match_nam,match_ext,match_flag)
  772.            and (not subdirec) and (not((transferrec.attr and volumeid)=8)))
  773.           then Delete_file(pathtmp + '\' + retname);
  774.       end;
  775.      fndnext(retname,lastfile,subdirec);
  776.         end;
  777.       end;
  778.     if multiple then    {multiple subdirectories where specified}
  779.      begin
  780.        pop(stk,dir_rec,empty); {see if any where found}
  781.        if not empty then       {if so build a new pathname}
  782.         begin
  783.           dirpath[dir_rec.level] := dir_rec.dirname;
  784.           matchptrn := path;
  785.           for lvl := 1 to dir_rec.level do
  786.            matchptrn := matchptrn + '\' + dirpath[lvl];
  787.           pathtmp := matchptrn;
  788.           matchptrn := matchptrn + file_nam;
  789.           current_lvl := dir_rec.level + 1; {set new current level}
  790.         end;
  791.      end;
  792.   until (not multiple or empty);
  793. end.
  794.  
  795. 
  796.