mirror of
				https://gitlab.com/freepascal.org/fpc/source.git
				synced 2025-11-04 16:39:24 +01:00 
			
		
		
		
	
		
			
				
	
	
		
			591 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			ObjectPascal
		
	
	
	
	
	
			
		
		
	
	
			591 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			ObjectPascal
		
	
	
	
	
	
{
 | 
						|
    rmwait - remove (delete) file(s) with optional retries
 | 
						|
    Copyright (C) 2009-2011 by Tomas Hajny, member of the Free Pascal team
 | 
						|
 | 
						|
    This tool tries to mimic behaviour of GNU rm, but it provides
 | 
						|
    the additional feature of retries and it also fixes some issues
 | 
						|
    appearing at least with the Win32 port of version 3.13.
 | 
						|
 | 
						|
    See the file COPYING, included in this distribution,
 | 
						|
    for details about the copyright.
 | 
						|
 | 
						|
    This program is distributed in the hope that it will be useful,
 | 
						|
    but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
						|
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 | 
						|
}
 | 
						|
 | 
						|
program rmwait;
 | 
						|
{$D
 | 
						|
Remove (delete) file(s) with optional retries.
 | 
						|
}
 | 
						|
 | 
						|
{ $DEFINE DONOTHING}
 | 
						|
 | 
						|
uses
 | 
						|
{$IFDEF GO32V2}
 | 
						|
  Go32,
 | 
						|
{$ENDIF GO32V2}
 | 
						|
{$IFDEF OS2}
 | 
						|
  DosCalls,
 | 
						|
{$ENDIF OS2}
 | 
						|
{$IFDEF WINDOWS}
 | 
						|
  Windows,
 | 
						|
{$ENDIF WINDOWS}
 | 
						|
{$IFDEF UNIX}
 | 
						|
  BaseUnix,
 | 
						|
{$ENDIF UNIX}
 | 
						|
  Dos;
 | 
						|
 | 
						|
const
 | 
						|
  OptDirectories: boolean = false;
 | 
						|
  OptForce: boolean = false;
 | 
						|
  OptInteractive: boolean = false;
 | 
						|
  OptRecursive: boolean = false;
 | 
						|
  OptVerbose: boolean = false;
 | 
						|
  OptRetries: longint = 1;
 | 
						|
  OptWait: longint = 5;
 | 
						|
  OptsStop: boolean = false;
 | 
						|
  RmWaitEnvVarName = 'RMWAIT_OPTS';
 | 
						|
 | 
						|
 | 
						|
var
 | 
						|
  OldExit: pointer;
 | 
						|
  Deleted: cardinal;
 | 
						|
 | 
						|
procedure VerbLine (S: string); inline;
 | 
						|
begin
 | 
						|
  if OptVerbose then
 | 
						|
    WriteLn (S);
 | 
						|
end;
 | 
						|
 | 
						|
 | 
						|
procedure ForceErrorLn (S: string); inline;
 | 
						|
begin
 | 
						|
  WriteLn (ParamStr (0), ': ', S);
 | 
						|
end;
 | 
						|
 | 
						|
 | 
						|
procedure ErrorLn (S: string); inline;
 | 
						|
begin
 | 
						|
{  if not (OptForce) then}
 | 
						|
   ForceErrorLn (S);
 | 
						|
end;
 | 
						|
 | 
						|
 | 
						|
procedure GenericErrorLn (S: string; N: longint); inline;
 | 
						|
begin
 | 
						|
  if not (OptForce) then
 | 
						|
   WriteLn (ParamStr (0), ': ', S, ' (', N, ')');
 | 
						|
end;
 | 
						|
 | 
						|
 | 
						|
procedure ClearIO; inline;
 | 
						|
begin
 | 
						|
  if IOResult <> 0 then ;
 | 
						|
end;
 | 
						|
 | 
						|
 | 
						|
procedure Wait (Seconds: Cardinal);
 | 
						|
{$IFDEF GO32v2}
 | 
						|
var
 | 
						|
  R: Registers;
 | 
						|
  T0, T1, T2: int64;
 | 
						|
  DayOver: boolean;
 | 
						|
begin
 | 
						|
(* Sleep is supposed to give up time slice - DOS Idle Interrupt chosen
 | 
						|
   because it should be supported in all DOS versions. *)
 | 
						|
  R.AH := $2C;
 | 
						|
  RealIntr($21, R);
 | 
						|
  T0 := R.CH * 3600 + R.CL * 60 + R.DH;
 | 
						|
  T2 := T0 + Seconds;
 | 
						|
  DayOver := T2 > (24 * 3600);
 | 
						|
  repeat
 | 
						|
    Intr ($28, R);
 | 
						|
(*    R.AH := $2C; - should be preserved. *)
 | 
						|
    RealIntr($21, R);
 | 
						|
    T1 := R.CH * 3600 + R.CL * 60 + R.DH;
 | 
						|
    if DayOver and (T1 < T0) then
 | 
						|
     Inc (T1, 24 * 3600);
 | 
						|
  until T1 >= T2;
 | 
						|
end;
 | 
						|
{$ELSE GO32v2}
 | 
						|
 {$IFDEF OS2}
 | 
						|
begin
 | 
						|
  DosSleep (Seconds * 1000);
 | 
						|
end;
 | 
						|
 {$ELSE OS2}
 | 
						|
  {$IFDEF UNIX}
 | 
						|
begin
 | 
						|
  fpSleep (Seconds * 1000);
 | 
						|
end;
 | 
						|
  {$ELSE UNIX}
 | 
						|
   {$IFDEF WINDOWS}
 | 
						|
begin
 | 
						|
  Sleep (Seconds * 1000);
 | 
						|
end;
 | 
						|
   {$ELSE WINDOWS}
 | 
						|
var
 | 
						|
  T0, T1, T2: int64;
 | 
						|
begin
 | 
						|
{$WARNING No sleeping is performed with this platform!}
 | 
						|
  T0 := GetMSCount;
 | 
						|
  T2 := T0 + Seconds * 1000;
 | 
						|
  repeat
 | 
						|
    T1 := GetMSCount;
 | 
						|
(* GetMSCount returning lower value than in the first check indicates overflow
 | 
						|
   and is treated as end of the waiting period due to undefined range. *)
 | 
						|
  until (T1 >= T2) or (T1 < T0);
 | 
						|
end;
 | 
						|
   {$ENDIF WINDOWS}
 | 
						|
  {$ENDIF UNIX}
 | 
						|
 {$ENDIF OS2}
 | 
						|
{$ENDIF GO32v2}
 | 
						|
 | 
						|
 | 
						|
procedure ClearAttribs (var F: file); inline;
 | 
						|
var
 | 
						|
  W: word;
 | 
						|
begin
 | 
						|
{$I-}
 | 
						|
  GetFAttr (F, W);
 | 
						|
  if W and (ReadOnly or SysFile) <> 0 then
 | 
						|
    SetFAttr (F, W and not ReadOnly and not SysFile);
 | 
						|
  ClearIO;
 | 
						|
{$I+}
 | 
						|
end;
 | 
						|
 | 
						|
 | 
						|
function StrF (U: cardinal): string; inline;
 | 
						|
begin
 | 
						|
  Str (U, StrF);
 | 
						|
end;
 | 
						|
 | 
						|
 | 
						|
function CheckOK (Msg: string; FN: PathStr): boolean;
 | 
						|
var
 | 
						|
  Resp: string;
 | 
						|
begin
 | 
						|
  Write (ParamStr (0), ': ', Msg, '''', FN, '''? ');
 | 
						|
  ReadLn (Resp);
 | 
						|
  CheckOK := (Length (Resp) > 0) and (UpCase (Resp [1]) = 'Y');
 | 
						|
end;
 | 
						|
 | 
						|
 | 
						|
procedure DelFile (FN: PathStr); inline;
 | 
						|
var
 | 
						|
  F: file;
 | 
						|
  R, Tries: longint;
 | 
						|
begin
 | 
						|
  VerbLine ('removing ''' + FN + '''');
 | 
						|
  Inc (Deleted);
 | 
						|
  if not (OptInteractive) or CheckOK ('remove ', FN) then
 | 
						|
    begin
 | 
						|
      Assign (F, FN);
 | 
						|
      if OptForce then
 | 
						|
        ClearAttribs (F);
 | 
						|
      Tries := 1;
 | 
						|
      repeat
 | 
						|
{$I-}
 | 
						|
{$IFDEF DONOTHING}
 | 
						|
        WriteLn ('Debug: ', FN);
 | 
						|
{$ELSE DONOTHING}
 | 
						|
        Erase (F);
 | 
						|
{$ENDIF DONOTHING}
 | 
						|
        R := IOResult;
 | 
						|
{$I+}
 | 
						|
        Inc (Tries);
 | 
						|
        if (R = 5) and (Tries <= OptRetries) then
 | 
						|
         begin
 | 
						|
          VerbLine ('Removal attempt failed, waiting ' + StrF (OptWait) + ' seconds before trying again...');
 | 
						|
          Wait (OptWait);
 | 
						|
         end;
 | 
						|
 | 
						|
      until (R <> 5) or (Tries > OptRetries);
 | 
						|
      case R of
 | 
						|
        0: ;
 | 
						|
        2: ErrorLn (FN + ': No such file or directory');
 | 
						|
        5: ErrorLn (FN + ': Permission denied');
 | 
						|
      else
 | 
						|
       GenericErrorLn (FN + ': Cannot be removed', R);
 | 
						|
      end;
 | 
						|
    end;
 | 
						|
end;
 | 
						|
 | 
						|
 | 
						|
procedure DelDir (FN: PathStr); inline;
 | 
						|
var
 | 
						|
  F: file;
 | 
						|
  R, Tries: longint;
 | 
						|
begin
 | 
						|
  VerbLine ('removing ''' + FN + '''');
 | 
						|
  Inc (Deleted);
 | 
						|
  if not (OptInteractive) or CheckOK ('remove directory ', FN) then
 | 
						|
    begin
 | 
						|
      if OptForce then
 | 
						|
        begin
 | 
						|
          Assign (F, FN);
 | 
						|
          ClearAttribs (F);
 | 
						|
        end;
 | 
						|
      Tries := 1;
 | 
						|
      repeat
 | 
						|
{$I-}
 | 
						|
{$IFDEF DONOTHING}
 | 
						|
        WriteLn ('Debug: Directory ', FN);
 | 
						|
{$ELSE DONOTHING}
 | 
						|
        RmDir (FN);
 | 
						|
{$ENDIF DONOTHING}
 | 
						|
        R := IOResult;
 | 
						|
{$I+}
 | 
						|
        Inc (Tries);
 | 
						|
        if (R = 5) and (Tries <= OptRetries) then
 | 
						|
         begin
 | 
						|
          VerbLine ('Removal attempt failed, waiting ' + StrF (OptWait) + ' seconds before trying again...');
 | 
						|
          Wait (OptWait);
 | 
						|
         end;
 | 
						|
      until (R <> 5) or (Tries > OptRetries);
 | 
						|
      case R of
 | 
						|
        0: ;
 | 
						|
        5: ErrorLn (FN + ': Permission denied');
 | 
						|
      else
 | 
						|
       GenericErrorLn (FN + ': Cannot be removed', R);
 | 
						|
      end;
 | 
						|
    end;
 | 
						|
end;
 | 
						|
 | 
						|
 | 
						|
procedure Syntax;
 | 
						|
begin
 | 
						|
  WriteLn;
 | 
						|
  WriteLn ('RmWait - remove (delete) file(s) with optional retries');
 | 
						|
  WriteLn;
 | 
						|
  WriteLn ('Syntax:');
 | 
						|
  WriteLn (ParamStr (0) + ' [<options>...] [<file specifications>...]');
 | 
						|
  WriteLn;
 | 
						|
  WriteLn ('<file specifications> may contain wildcards ''*'' and ''?''.');
 | 
						|
  WriteLn;
 | 
						|
  WriteLn ('Options:');
 | 
						|
  WriteLn (' -d, --directory                 remove directory. even if non-empty');
 | 
						|
  WriteLn (' -f, --force                     ignore non-existent files, never prompt');
 | 
						|
  WriteLn (' -i, --interactive               prompt before any removal');
 | 
						|
  WriteLn (' -r, -R, --recursive             remove the contents of directories recursively');
 | 
						|
  WriteLn (' -v, --verbose                   explain what is being done');
 | 
						|
  WriteLn (' --version                       output version information and exit');
 | 
						|
  WriteLn (' -h, -?, --help                  display this help and exit');
 | 
						|
  WriteLn (' -t[<N>[,<T>]], --try[<N>[,<T>]] in case of errors, retry deleting N times');
 | 
						|
  WriteLn ('                                 (default 3 times) waiting T seconds between');
 | 
						|
  WriteLn ('                                 individual attempts (default 5 seconds)');
 | 
						|
  WriteLn (' --                              stop processing of options');
 | 
						|
  WriteLn;
 | 
						|
  WriteLn ('Options may also be passed via environment variable RMWAIT_OPTS.');
 | 
						|
  WriteLn;
 | 
						|
  WriteLn ('To remove a file whose name starts with a ''-'', for example ''-file'',');
 | 
						|
  WriteLn ('use one of these commands:');
 | 
						|
  WriteLn (' rm -- -file');
 | 
						|
  WriteLn (' rm ./-file');
 | 
						|
  WriteLn;
 | 
						|
  Halt;
 | 
						|
end;
 | 
						|
 | 
						|
 | 
						|
procedure ParError (S: string); inline;
 | 
						|
begin
 | 
						|
  ForceErrorLn (S);
 | 
						|
  WriteLn;
 | 
						|
  Syntax;
 | 
						|
end;
 | 
						|
 | 
						|
 | 
						|
procedure ProcessFSpec (FN: PathStr);
 | 
						|
var
 | 
						|
  SR: SearchRec;
 | 
						|
  D, BaseDir: DirStr;
 | 
						|
  N, BaseName: NameStr;
 | 
						|
  E: ExtStr;
 | 
						|
  RemFNDir: boolean;
 | 
						|
begin
 | 
						|
  RemFNDir := false;
 | 
						|
{$IF NOT DEFINED (OS2) and NOT DEFINED (WINDOWS) and NOT DEFINED (DPMI) and NOT DEFINED (UNIX) and NOT DEFINED (MACOS) and NOT DEFINED (AMIGA) and NOT DEFINED (NETWARE)}
 | 
						|
 {$WARNING Proper behaviour for this target platform has not been checked!}
 | 
						|
{$ENDIF}
 | 
						|
{$IF NOT DEFINED (MACOS) and NOT DEFINED (AMIGA)}
 | 
						|
(* Special case - root directory needs to be treated in a special way. *)
 | 
						|
 {$IFDEF UNIX}
 | 
						|
 if (Length (FN) = 1)
 | 
						|
 {$ELSE UNIX}
 | 
						|
  {$IF DEFINED (OS2) or DEFINED (WINDOWS) or DEFINED (DPMI)}
 | 
						|
 if (((Length (FN) = 3) and (FN [2] = DriveSeparator))
 | 
						|
        or ((Length (FN) = 2) and (FN [1] = DirectorySeparator)))
 | 
						|
(* Root of UNC path - nonsense, but changing it to root of current drive would be dangerous. *)
 | 
						|
  {$ELSE}
 | 
						|
   {$IFDEF NETWARE}
 | 
						|
 if (Length (FN) = Pos (DirectorySeparator, FN))
 | 
						|
   {$ENDIF NETWARE}
 | 
						|
  {$ENDIF}
 | 
						|
      and (FN [Length (FN)] = DirectorySeparator) then
 | 
						|
 {$ENDIF UNIX}
 | 
						|
  if OptRecursive then
 | 
						|
    begin
 | 
						|
      BaseDir := FN;
 | 
						|
      BaseName := AllFilesMask;
 | 
						|
    end
 | 
						|
  else
 | 
						|
    begin
 | 
						|
      ErrorLn (FN + ': is a directory');
 | 
						|
      Exit;
 | 
						|
    end
 | 
						|
 else
 | 
						|
{$ENDIF}
 | 
						|
  begin
 | 
						|
(* Check if the specification directly corresponds to a directory *)
 | 
						|
  if FN [Length (FN)] = DirectorySeparator then
 | 
						|
    Delete (FN, Length (FN), 1);
 | 
						|
  FSplit (FN, D, N, E);
 | 
						|
  FindFirst (FN, (AnyFile or Directory) and not VolumeID, SR);
 | 
						|
  if (DosError = 0) and (SR.Attr and Directory = Directory) and
 | 
						|
                                                ((SR.Name = N + E) or
 | 
						|
(* Checking equal names is not sufficient with case preserving file systems. *)
 | 
						|
                              (Pos ('?', FN) = 0) and (Pos ('*', FN) = 0)) then
 | 
						|
    if OptRecursive then
 | 
						|
     begin
 | 
						|
      BaseDir := FN;
 | 
						|
      if BaseDir [Length (BaseDir)] <> DirectorySeparator then
 | 
						|
       BaseDir := BaseDir + DirectorySeparator;
 | 
						|
      BaseName := AllFilesMask;
 | 
						|
      RemFNDir := true;
 | 
						|
     end
 | 
						|
    else
 | 
						|
     if OptDirectories then
 | 
						|
      RemFNDir := true
 | 
						|
     else
 | 
						|
      begin
 | 
						|
       ErrorLn (FN + ': is a directory');
 | 
						|
       Exit;
 | 
						|
      end
 | 
						|
  else
 | 
						|
    begin
 | 
						|
      BaseDir := D;
 | 
						|
      BaseName := N + E;
 | 
						|
    end;
 | 
						|
  FindClose (SR);
 | 
						|
 end;
 | 
						|
  FindFirst (BaseDir + BaseName, AnyFile and not Directory and not VolumeID, SR);
 | 
						|
  while DosError = 0 do
 | 
						|
    begin
 | 
						|
      DelFile (BaseDir + SR.Name);
 | 
						|
      FindNext (SR);
 | 
						|
    end;
 | 
						|
  FindClose (SR);
 | 
						|
 | 
						|
  if OptRecursive then
 | 
						|
    begin
 | 
						|
      FindFirst (BaseDir + BaseName, (AnyFile or Directory) and not VolumeID, SR);
 | 
						|
      while DosError = 0 do
 | 
						|
        begin
 | 
						|
          if (SR.Attr and Directory > 0) and
 | 
						|
           ((Length (SR.Name) <> 1) or (SR.Name [1] <> '.')) and
 | 
						|
           ((Length (SR.Name) <> 2) or (SR.Name [1] <> '.') or (SR.Name [2] <> '.')) and
 | 
						|
           (not (OptInteractive) or CheckOK ('descend directory ', BaseDir + SR.Name)) then
 | 
						|
            ProcessFSpec (BaseDir + SR.Name);
 | 
						|
          FindNext (SR);
 | 
						|
        end;
 | 
						|
      FindClose (SR);
 | 
						|
    end;
 | 
						|
  if RemFNDir then
 | 
						|
    DelDir (FN);
 | 
						|
end;
 | 
						|
 | 
						|
 | 
						|
procedure NewExit; {$IFNDEF FPC} far;{$ENDIF FPC}
 | 
						|
begin
 | 
						|
  ExitProc := OldExit;
 | 
						|
  if (ErrorAddr <> nil) or (ExitCode <> 0) then
 | 
						|
    begin
 | 
						|
      ErrorAddr := nil;
 | 
						|
      case ExitCode of
 | 
						|
        202: WriteLn ('Directory tree too deep!!');
 | 
						|
        4: WriteLn ('Increase the FILES directive in CONFIG.SYS!!');
 | 
						|
        5, 101, 150..152, 154, 156..158, 160..162: WriteLn ('I/O error (',
 | 
						|
                                                              ExitCode, ')!!');
 | 
						|
      else
 | 
						|
        WriteLn ('Internal error (', ExitCode, ')!!');
 | 
						|
      end;
 | 
						|
      WriteLn;
 | 
						|
    end;
 | 
						|
end;
 | 
						|
 | 
						|
 | 
						|
procedure AllowSlash (var S: string); inline;
 | 
						|
var
 | 
						|
  I: byte;
 | 
						|
begin
 | 
						|
  if DirectorySeparator <> '/' then
 | 
						|
    for I := 1 to Length (S) do
 | 
						|
      begin
 | 
						|
        if S [I] = '/' then
 | 
						|
         S [I] := DirectorySeparator;
 | 
						|
      end;
 | 
						|
end;
 | 
						|
 | 
						|
 | 
						|
procedure ProcessOpts (S: string);
 | 
						|
var
 | 
						|
  I: longint;
 | 
						|
 | 
						|
  procedure ParseOptTries; inline;
 | 
						|
  var
 | 
						|
    SN: string;
 | 
						|
    J, N, Err: longint;
 | 
						|
  begin
 | 
						|
    J := Succ (I);
 | 
						|
    while (J <= Length (S)) and (S [J] in ['0'..'9']) do
 | 
						|
     Inc (J);
 | 
						|
    if J = Succ (I) then
 | 
						|
     OptRetries := 3
 | 
						|
    else
 | 
						|
     begin
 | 
						|
      SN := Copy (S, Succ (I), J - I - 1);
 | 
						|
      Val (SN, N, Err);
 | 
						|
      if Err <> 0 then
 | 
						|
       ParError ('invalid value for retry attempts ''' + SN + '''');
 | 
						|
      OptRetries := N;
 | 
						|
      I := Pred (J);
 | 
						|
      if (J < Length (S)) and (S [J] = ',') then
 | 
						|
       begin
 | 
						|
        Inc (J);
 | 
						|
        Inc (I);
 | 
						|
        while (J <= Length (S)) and (S [J] in ['0'..'9']) do
 | 
						|
         Inc (J);
 | 
						|
        if J > Succ (I) then
 | 
						|
         begin
 | 
						|
          SN := Copy (S, Succ (I), J - I - 1);
 | 
						|
          Val (SN, N, Err);
 | 
						|
          if Err <> 0 then
 | 
						|
           ParError ('invalid value for retry wait time ''' + SN + '''');
 | 
						|
          OptWait := N;
 | 
						|
          I := Pred (J);
 | 
						|
         end;
 | 
						|
       end;
 | 
						|
     end;
 | 
						|
  end;
 | 
						|
 | 
						|
begin
 | 
						|
  if S [2] = '-' then
 | 
						|
   if Length (S) = 2 then
 | 
						|
    OptsStop := true
 | 
						|
   else
 | 
						|
    begin
 | 
						|
      Delete (S, 1, 2);
 | 
						|
      for I := 1 to Length (S) do
 | 
						|
       S [I] := Upcase (S [I]);
 | 
						|
      if S = 'HELP' then Syntax;
 | 
						|
      if S = 'DIRECTORY' then
 | 
						|
       OptDirectories := true
 | 
						|
      else if S = 'FORCE' then
 | 
						|
       OptForce := true
 | 
						|
      else if S = 'INTERACTIVE' then
 | 
						|
       OptInteractive := true
 | 
						|
      else if S = 'RECURSIVE' then
 | 
						|
       OptRecursive := true
 | 
						|
      else if S = 'VERBOSE' then
 | 
						|
       OptVerbose := true
 | 
						|
      else if S = 'VERSION' then
 | 
						|
       begin
 | 
						|
        WriteLn ('rmwait - version 20110104');
 | 
						|
        Halt;
 | 
						|
       end
 | 
						|
      else if Copy (S, 1, 3) = 'TRY' then
 | 
						|
       begin
 | 
						|
        I := 3;
 | 
						|
        ParseOptTries;
 | 
						|
        if I <> Length (S) then
 | 
						|
         ParError ('unrecognized option ''' + S + '''');
 | 
						|
       end
 | 
						|
      else
 | 
						|
       ParError ('unrecognized option ''' + S + '''');
 | 
						|
    end
 | 
						|
  else
 | 
						|
   begin
 | 
						|
    I := 2;
 | 
						|
    repeat
 | 
						|
      case Upcase (S [I]) of
 | 
						|
       'H', '?': Syntax;
 | 
						|
       'D': OptDirectories := true;
 | 
						|
       'F': OptForce := true;
 | 
						|
       'I': OptInteractive := true;
 | 
						|
       'R': OptRecursive := true;
 | 
						|
       'V': OptVerbose := true;
 | 
						|
       'T': ParseOptTries;
 | 
						|
      else
 | 
						|
       ParError ('invalid option -- ' + S [I])
 | 
						|
      end;
 | 
						|
      Inc (I);
 | 
						|
    until (I > Length (S));
 | 
						|
   end;
 | 
						|
end;
 | 
						|
 | 
						|
var
 | 
						|
  J, K, L: longint;
 | 
						|
  EnvOpts, Par: string;
 | 
						|
 | 
						|
begin
 | 
						|
{$IFDEF OS2}
 | 
						|
  DosCalls.DosError (0);
 | 
						|
{$ENDIF}
 | 
						|
 | 
						|
  OldExit := ExitProc;
 | 
						|
  ExitProc := @NewExit;
 | 
						|
 | 
						|
  EnvOpts := GetEnv (RmWaitEnvVarName);
 | 
						|
  K := 1;
 | 
						|
  while (K < Length (EnvOpts)) and not OptsStop do
 | 
						|
   begin
 | 
						|
    while (EnvOpts [K] = ' ') and (K < Length (EnvOpts)) do
 | 
						|
     Inc (K);
 | 
						|
    if EnvOpts [K] = '-' then
 | 
						|
     begin
 | 
						|
      L := Succ (K);
 | 
						|
      while ((L <= Length (EnvOpts)) and (EnvOpts [L] <> ' ')) do
 | 
						|
       Inc (L);
 | 
						|
      Par := Copy (EnvOpts, K, L - K);
 | 
						|
      ProcessOpts (Par);
 | 
						|
      K := Succ (L);
 | 
						|
     end
 | 
						|
    else
 | 
						|
     Syntax;
 | 
						|
    if OptsStop then
 | 
						|
     begin
 | 
						|
      EnvOpts := '';
 | 
						|
      OptsStop := false;
 | 
						|
     end;
 | 
						|
   end;
 | 
						|
 | 
						|
  J := ParamCount;
 | 
						|
  if J = 0 then
 | 
						|
    Syntax
 | 
						|
  else
 | 
						|
   begin
 | 
						|
    K := 1;
 | 
						|
    Par := ParamStr (K);
 | 
						|
 | 
						|
    while (K <= J) and (Par [1] = '-') and (Length (Par) > 1) and not OptsStop do
 | 
						|
      begin
 | 
						|
        ProcessOpts (Par);
 | 
						|
        Inc (K);
 | 
						|
        Par := ParamStr (K);
 | 
						|
      end;
 | 
						|
 | 
						|
    if K > J then
 | 
						|
     Syntax
 | 
						|
    else
 | 
						|
     repeat
 | 
						|
       AllowSlash (Par);
 | 
						|
       Deleted := 0;
 | 
						|
       ProcessFSpec (FExpand (Par));
 | 
						|
       if Deleted = 0 then
 | 
						|
        ErrorLn (ParamStr (K) + ': No such file or directory');
 | 
						|
       Inc (K);
 | 
						|
       Par := ParamStr (K);
 | 
						|
     until K > J;
 | 
						|
   end;
 | 
						|
end.
 |