1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288 |
- {
- This file is part of the Free Pascal Test Suite
- Copyright (c) 1999-2000 by Pierre Muller
- Unit to redirect output and error to files
- Adapted from code donated to public domain by Schwartz Gabriel 20/03/1993
- See the file COPYING.FPC, 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.
- **********************************************************************}
- Unit Redir;
- Interface
- {$mode objfpc}
- {$H+}
- {$R-}
- {$ifndef Linux}
- {$ifndef Unix}
- {$S-}
- {$endif}
- {$endif}
- {$ifdef Go32v2}
- {$define implemented}
- {$endif}
- {$ifdef OS2}
- {$define implemented}
- {$endif}
- {$ifdef windows}
- {$define implemented}
- {$if (FPC_FULLVERSION > 30300)}
- {$define EXECUTEREDIR_USES_PROCESS}
- {$ENDIF}
- {$define USES_UNIT_PROCESS}
- {$endif}
- {$IFDEF UNIX}
- {$define implemented}
- {$ifndef MACOS}
- {$if (FPC_FULLVERSION > 30300)}
- {$define EXECUTEREDIR_USES_PROCESS}
- {$ENDIF}
- {$define USES_UNIT_PROCESS}
- {$endif}
- {$ENDIF}
- Var
- IOStatus : Integer;
- RedirErrorOut,RedirErrorIn,
- RedirErrorError : Integer;
- ExecuteResult : Longint;
- {------------------------------------------------------------------------------}
- procedure InitRedir;
- function ExecuteRedir (Const ProgName, ComLine : String; RedirStdIn, RedirStdOut, RedirStdErr: String): boolean;
- procedure DosExecute(ProgName, ComLine : String);
- function ChangeRedirOut(Const Redir : String; AppendToFile : Boolean) : Boolean;
- procedure RestoreRedirOut;
- procedure DisableRedirOut;
- procedure EnableRedirOut;
- function ChangeRedirIn(Const Redir : String) : Boolean;
- procedure RestoreRedirIn;
- procedure DisableRedirIn;
- procedure EnableRedirIn;
- function ChangeRedirError(Const Redir : String; AppendToFile : Boolean) : Boolean;
- procedure RestoreRedirError;
- procedure DisableRedirError;
- procedure EnableRedirError;
- procedure RedirDisableAll;
- procedure RedirEnableAll;
- { unused in UNIX }
- const
- UseComSpec : boolean = true;
- Implementation
- //or defined(windows)
- {$if defined(macos) or defined(shell_implemented) or defined(go32v2)}
- {$define usedos}
- {$endif}
- {$if defined(windows) and not defined(usedos)}
- {$ifdef ver2_4}
- {$define redirexecuteprocess}
- {$endif}
- {$endif}
- Uses
- {$ifdef go32v2}
- go32,
- {$endif go32v2}
- {$ifdef windows}
- windows,
- {$endif windows}
- {$IFDEF OS2}
- {$IFNDEF EMX}
- DosCalls,
- {$ENDIF EMX}
- {$ENDIF OS2}
- {$ifdef unix}
- baseunix,
- unix,
- {$endif unix}
- {$ifdef redirexecuteprocess}
- sysconst,
- {$endif}
- {$ifdef USES_UNIT_PROCESS}
- process,
- {$endif USES_UNIT_PROCESS}
- {$ifdef usedos}
- dos;
- {$else}
- sysutils;
- {$endif}
- Const
- {$ifdef UNIX}
- DirSep='/';
- listsep = [';',':'];
- exeext = '';
- {$else UNIX}
- {$ifdef MACOS}
- DirSep=':';
- listsep = [','];
- exeext = '';
- {$else MACOS}
- DirSep='\';
- listsep = [';'];
- exeext = '.exe';
- {$endif MACOS}
- {$endif UNIX}
- {$ifndef usedos}
- { code from: }
- { Lithuanian Text Tool version 0.9.0 (2001-04-19) }
- { Copyright (c) 1999-2001 Marius Gedminas <[email protected]> }
- { (GPLv2 or later) }
- function FExpand(const S: string): string;
- begin
- FExpand := ExpandFileName(S);
- end;
- type
- PathStr = string;
- DirStr = string;
- NameStr = string;
- ExtStr = string;
- procedure FSplit(Path: PathStr; var Dir: DirStr; var Name: NameStr; var Ext: ExtStr);
- begin
- Dir := ExtractFilePath(Path);
- Name := ChangeFileExt(ExtractFileName(Path), '');
- Ext := ExtractFileExt(Path);
- end;
- {$endif}
- var
- FIN,FOUT,FERR : ^File;
- RedirStdErrToStdOut,
- RedirChangedOut,
- RedirChangedIn : Boolean;
- RedirChangedError : Boolean;
- InRedirDisabled,OutRedirDisabled,ErrorRedirDisabled : Boolean;
- {*****************************************************************************
- Helpers
- *****************************************************************************}
- function FixPath(const s:string):string;
- var
- i : longint;
- begin
- { Fix separator }
- setlength(fixpath,length(s));
- for i:=1 to length(s) do
- if s[i] in ['/','\'] then
- fixpath[i]:=DirSep
- else
- fixpath[i]:=s[i];
- end;
- {*****************************************************************************
- Dos
- *****************************************************************************}
- {$ifdef implemented}
- {$ifndef usedos}
- {$if defined(ver2_4_0) or defined(ver2_4_1)}
- Type
- TExecuteFlags= set of (ExecInheritsHandles);
- {$ifdef redirexecuteprocess}
- function ExecuteProcess(Const Path: AnsiString; Const ComLine: AnsiString;Flags:TExecuteFlags=[]):integer;
- // win specific function
- var
- SI: TStartupInfo;
- PI: TProcessInformation;
- Proc : THandle;
- l : DWord;
- CommandLine : ansistring;
- e : EOSError;
- ExecInherits : longbool;
- begin
- FillChar(SI, SizeOf(SI), 0);
- SI.cb:=SizeOf(SI);
- SI.wShowWindow:=1;
- { always surround the name of the application by quotes
- so that long filenames will always be accepted. But don't
- do it if there are already double quotes, since Win32 does not
- like double quotes which are duplicated!
- }
- if pos('"',path)=0 then
- CommandLine:='"'+path+'"'
- else
- CommandLine:=path;
- if ComLine <> '' then
- CommandLine:=Commandline+' '+ComLine+#0
- else
- CommandLine := CommandLine + #0;
- ExecInherits:=ExecInheritsHandles in Flags;
- if not CreateProcess(nil, pchar(CommandLine),
- Nil, Nil, ExecInherits,$20, Nil, Nil, SI, PI) then
- begin
- e:=EOSError.CreateFmt(SExecuteProcessFailed,[CommandLine,GetLastError]);
- e.ErrorCode:=GetLastError;
- raise e;
- end;
- Proc:=PI.hProcess;
- if WaitForSingleObject(Proc, dword($ffffffff)) <> $ffffffff then
- begin
- GetExitCodeProcess(Proc,l);
- CloseHandle(Proc);
- CloseHandle(PI.hThread);
- result:=l;
- end
- else
- begin
- e:=EOSError.CreateFmt(SExecuteProcessFailed,[CommandLine,GetLastError]);
- e.ErrorCode:=GetLastError;
- CloseHandle(Proc);
- CloseHandle(PI.hThread);
- raise e;
- end;
- end;
- {$else}
- {$ifndef USES_UNIT_PROCESS}
- function ExecuteProcess(Const Path: AnsiString; Const ComLine: AnsiString;Flags:TExecuteFlags=[]):integer;
- begin
- result:=ExecuteProcess(path,comline);
- end;
- {$endif ndef USES_UNIT_PROCESS}
- {$endif}
- {$ifend}
- {$endif}
- {$ifndef windows}
- var
- TempHOut, TempHIn,TempHError : longint;
- {$endif ndef windows}
- {
- For Unix the following functions exist
- Function fpdup(oldfile:longint;var newfile:longint):Boolean;
- Function fpdup2(oldfile,newfile:longint):Boolean;
- Function fpClose(fd:longint):boolean;
- }
- {$ifdef go32v2}
- function fpdup(fh : longint) : longint;
- var
- Regs : Registers;
- begin
- Regs.ah:=$45;
- Regs.bx:=fh;
- MsDos (Regs);
- If (Regs.Flags and fCarry)=0 then
- fpdup:=Regs.Ax
- else
- fpdup:=-1;
- end;
- function fpdup2(fh,nh : longint) : longint;
- var
- Regs : Registers;
- begin
- fpdup2:=0;
- If fh=nh then
- exit;
- Regs.ah:=$46;
- Regs.bx:=fh;
- Regs.cx:=nh;
- MsDos (Regs);
- If (Regs.Flags and fCarry)<>0 then
- fpdup2:=-1;
- end;
- Function fpclose (Handle : Longint) : boolean;
- var Regs: registers;
- begin
- Regs.Eax := $3e00;
- Regs.Ebx := Handle;
- MsDos(Regs);
- fpclose:=(Regs.Flags and fCarry)=0;
- end;
- {$endif def go32v2}
- {$ifdef windows}
- Function fpclose (Handle : Longint) : boolean;
- begin
- { Do we need this ?? }
- fpclose:=true;
- end;
- {$endif}
- {$IFDEF OS2}
- {$IFDEF EMX}
- {$ASMMODE INTEL}
- function fpDup (FH: longint): longint; assembler;
- asm
- mov ebx, eax
- mov ah, 45h
- call syscall
- jnc @fpdup_end
- mov eax, -1
- @fpdup_end:
- end;
- function fpDup2 (FH, NH: longint): longint; assembler;
- asm
- cmp eax, edx
- jnz @fpdup2_go
- mov eax, 0
- jmp @fpdup2_end
- @fpdup2_go:
- push ebx
- mov ebx, eax
- mov ecx, edx
- mov ah, 46h
- call syscall
- pop ebx
- jnc @fpdup2_end
- mov eax, -1
- @fpdup2_end:
- end;
- function fpClose (Handle: longint): boolean; assembler;
- asm
- push ebx
- mov ebx, eax
- mov ah, 3Eh
- call syscall
- pop ebx
- mov eax, 1
- jnc @fpclose_end
- dec eax
- end;
- {$ASMMODE DEFAULT}
- {$ELSE EMX}
- function fpDup (FH: longint): longint;
- var
- NH: THandle;
- begin
- NH := THandle (-1);
- if DosDupHandle (THandle (FH), NH) = 0 then
- fpDup := longint (NH)
- else
- fpDup := -1;
- end;
- function fpDup2 (FH, NH: longint): longint;
- begin
- if FH = NH then
- fpDup2 := 0
- else
- if DosDupHandle (THandle (FH), THandle (NH)) <> 0 then
- fpDup2 := -1;
- end;
- function fpClose (Handle: longint): boolean;
- begin
- fpClose := DosClose (THandle (Handle)) = 0;
- end;
- {$ENDIF EMX}
- {$ENDIF OS2}
- {$I-}
- function FileExist(const FileName : PathStr) : Boolean;
- {$ifdef usedos}
- var
- f : file;
- Attr : word;
- {$endif}
- begin
- {$ifdef usedos}
- Assign(f, FileName);
- GetFAttr(f, Attr);
- FileExist := DosError = 0;
- {$else}
- FileExist := Sysutils.FileExists(filename);
- {$endif}
- end;
- function CompleteDir(const Path: string): string;
- begin
- { keep c: untouched PM }
- if (Path<>'') and (Path[Length(Path)]<>DirSep) and
- (Path[Length(Path)]<>':') then
- CompleteDir:=Path+DirSep
- else
- CompleteDir:=Path;
- end;
- function LocateExeFile(var FileName:string): boolean;
- var
- dir,s: string;
- d: dirstr;
- n: namestr;
- e: extstr;
- i : longint;
- begin
- LocateExeFile:=False;
- if FileExist(FileName) then
- begin
- LocateExeFile:=true;
- Exit;
- end;
- Fsplit(Filename,d,n,e);
- if (e='') and FileExist(FileName+exeext) then
- begin
- FileName:=FileName+exeext;
- LocateExeFile:=true;
- Exit;
- end;
- {$ifdef usedos}
- S:=GetEnv('PATH');
- {$else}
- S:=GetEnvironmentVariable('PATH');
- {$endif}
- While Length(S)>0 do
- begin
- i:=1;
- While (i<=Length(S)) and not (S[i] in ListSep) do
- Inc(i);
- Dir:=CompleteDir(Copy(S,1,i-1));
- if i<Length(S) then
- Delete(S,1,i)
- else
- S:='';
- if FileExist(Dir+FileName) then
- Begin
- FileName:=Dir+FileName;
- LocateExeFile:=true;
- Exit;
- End;
- end;
- end;
- {............................................................................}
- function ChangeRedirOut(Const Redir : String; AppendToFile : Boolean) : Boolean;
- begin
- ChangeRedirOut:=False;
- If Redir = '' then Exit;
- Assign (FOUT^, Redir);
- If AppendToFile and FileExist(Redir) then
- Begin
- Reset(FOUT^,1);
- Seek(FOUT^,FileSize(FOUT^));
- End else Rewrite (FOUT^);
- RedirErrorOut:=IOResult;
- IOStatus:=RedirErrorOut;
- If IOStatus <> 0 then Exit;
- {$ifndef FPC}
- Handles:=Ptr (prefseg, PWord (Ptr (prefseg, $34))^);
- OldHandleOut:=Handles^[StdOutputHandle];
- Handles^[StdOutputHandle]:=Handles^[FileRec (FOUT^).Handle];
- ChangeRedirOut:=True;
- OutRedirDisabled:=False;
- {$else}
- {$ifdef windows}
- if SetStdHandle(Std_Output_Handle,FileRec(FOUT^).Handle) then
- {$else not windows}
- TempHOut:=fpdup(StdOutputHandle);
- fpdup2(FileRec(FOUT^).Handle,StdOutputHandle);
- if (TempHOut<>UnusedHandle) and
- (StdOutputHandle<>UnusedHandle) then
- {$endif not windows}
- begin
- ChangeRedirOut:=True;
- OutRedirDisabled:=False;
- end;
- {$endif def FPC}
- RedirChangedOut:=True;
- end;
- function ChangeRedirIn(Const Redir : String) : Boolean;
- begin
- ChangeRedirIn:=False;
- If Redir = '' then Exit;
- Assign (FIN^, Redir);
- Reset(FIN^,1);
- RedirErrorIn:=IOResult;
- IOStatus:=RedirErrorIn;
- If IOStatus <> 0 then Exit;
- {$ifndef FPC}
- Handles:=Ptr (prefseg, PWord (Ptr (prefseg, $34))^);
- OldHandleIn:=Handles^[StdInputHandle];
- Handles^[StdInputHandle]:=Handles^[FileRec (FIN^).Handle];
- ChangeRedirIn:=True;
- InRedirDisabled:=False;
- {$else}
- {$ifdef windows}
- if SetStdHandle(Std_Input_Handle,FileRec(FIN^).Handle) then
- {$else not windows}
- TempHIn:=fpdup(StdInputHandle);
- fpdup2(FileRec(FIn^).Handle,StdInputHandle);
- if (TempHIn<>UnusedHandle) and
- (StdInputHandle<>UnusedHandle) then
- {$endif not windows}
- begin
- ChangeRedirIn:=True;
- InRedirDisabled:=False;
- end;
- {$endif def FPC}
- RedirChangedIn:=True;
- end;
- function ChangeRedirError(Const Redir : String; AppendToFile : Boolean) : Boolean;
- var
- PF : ^File;
- begin
- ChangeRedirError:=False;
- If Redir = '' then
- Exit;
- RedirStdErrToStdOut:=(Redir='stdout');
- if RedirStdErrToStdOut then
- begin
- PF:=FOut;
- end
- else
- begin
- Assign (FERR^, Redir);
- If AppendToFile and FileExist(Redir) then
- Begin
- Reset(FERR^,1);
- Seek(FERR^,FileSize(FERR^));
- End
- else
- Rewrite (FERR^);
- RedirErrorError:=IOResult;
- IOStatus:=RedirErrorError;
- If IOStatus <> 0 then Exit;
- PF:=FErr;
- end;
- {$ifndef FPC}
- Handles:=Ptr (prefseg, PWord (Ptr (prefseg, $34))^);
- OldHandleError:=Handles^[StdErrorHandle];
- Handles^[StdErrorHandle]:=Handles^[FileRec (PF^).Handle];
- ChangeRedirError:=True;
- ErrorRedirDisabled:=False;
- {$else}
- {$ifdef windows}
- if SetStdHandle(Std_Error_Handle,FileRec(PF^).Handle) then
- {$else not windows}
- TempHError:=fpdup(StdErrorHandle);
- fpdup2(FileRec(PF^).Handle,StdErrorHandle);
- if (TempHError<>UnusedHandle) and
- (StdErrorHandle<>UnusedHandle) then
- {$endif not windows}
- begin
- ChangeRedirError:=True;
- ErrorRedirDisabled:=False;
- end;
- {$endif}
- RedirChangedError:=True;
- end;
- procedure RestoreRedirOut;
- begin
- If not RedirChangedOut then Exit;
- {$ifdef windows}
- SetStdHandle(Std_Output_Handle,StdOutputHandle);
- {$else not windows}
- fpdup2(TempHOut,StdOutputHandle);
- {$endif not windows}
- Close (FOUT^);
- {$ifndef windows}
- fpclose(TempHOut);
- {$endif ndef windows}
- RedirChangedOut:=false;
- end;
- {............................................................................}
- procedure RestoreRedirIn;
- begin
- If not RedirChangedIn then Exit;
- {$ifndef FPC}
- Handles^[StdInputHandle]:=OldHandleIn;
- OldHandleIn:=StdInputHandle;
- {$else}
- {$ifdef windows}
- SetStdHandle(Std_Input_Handle,StdInputHandle);
- {$else not windows}
- fpdup2(TempHIn,StdInputHandle);
- {$endif not windows}
- {$endif}
- Close (FIn^);
- {$ifndef windows}
- fpclose(TempHIn);
- {$endif ndef windows}
- RedirChangedIn:=false;
- end;
- {............................................................................}
- procedure DisableRedirIn;
- begin
- If not RedirChangedIn then Exit;
- If InRedirDisabled then Exit;
- {$ifndef FPC}
- Handles^[StdInputHandle]:=OldHandleIn;
- {$else}
- {$ifdef windows}
- SetStdHandle(Std_Input_Handle,StdInputHandle);
- {$else not windows}
- fpdup2(TempHIn,StdInputHandle);
- {$endif not windows}
- {$endif}
- InRedirDisabled:=True;
- end;
- {............................................................................}
- procedure EnableRedirIn;
- begin
- If not RedirChangedIn then Exit;
- If not InRedirDisabled then Exit;
- {$ifndef FPC}
- Handles:=Ptr (prefseg, PWord (Ptr (prefseg, $34))^);
- Handles^[StdInputHandle]:=Handles^[FileRec (FIn^).Handle];
- {$else}
- {$ifdef windows}
- SetStdHandle(Std_Input_Handle,FileRec(FIn^).Handle);
- {$else not windows}
- fpdup2(FileRec(FIn^).Handle,StdInputHandle);
- {$endif not windows}
- {$endif}
- InRedirDisabled:=False;
- end;
- {............................................................................}
- procedure DisableRedirOut;
- begin
- If not RedirChangedOut then Exit;
- If OutRedirDisabled then Exit;
- {$ifndef FPC}
- Handles^[StdOutputHandle]:=OldHandleOut;
- {$else}
- {$ifdef windows}
- SetStdHandle(Std_Output_Handle,StdOutputHandle);
- {$else not windows}
- fpdup2(TempHOut,StdOutputHandle);
- {$endif not windows}
- {$endif}
- OutRedirDisabled:=True;
- end;
- {............................................................................}
- procedure EnableRedirOut;
- begin
- If not RedirChangedOut then Exit;
- If not OutRedirDisabled then Exit;
- {$ifndef FPC}
- Handles:=Ptr (prefseg, PWord (Ptr (prefseg, $34))^);
- Handles^[StdOutputHandle]:=Handles^[FileRec (FOut^).Handle];
- {$else}
- {$ifdef windows}
- SetStdHandle(Std_Output_Handle,FileRec(FOut^).Handle);
- {$else not windows}
- fpdup2(FileRec(FOut^).Handle,StdOutputHandle);
- {$endif not windows}
- {$endif}
- OutRedirDisabled:=False;
- end;
- {............................................................................}
- procedure RestoreRedirError;
- begin
- If not RedirChangedError then Exit;
- {$ifndef FPC}
- Handles^[StdErrorHandle]:=OldHandleError;
- OldHandleError:=StdErrorHandle;
- {$else}
- {$ifdef windows}
- SetStdHandle(Std_Error_Handle,StdErrorHandle);
- {$else not windows}
- fpdup2(TempHError,StdErrorHandle);
- {$endif not windows}
- {$endif}
- { don't close when redirected to STDOUT }
- if not RedirStdErrToStdOut then
- Close (FERR^);
- {$ifndef windows}
- fpclose(TempHError);
- {$endif ndef windows}
- RedirChangedError:=false;
- end;
- {............................................................................}
- procedure DisableRedirError;
- begin
- If not RedirChangedError then Exit;
- If ErrorRedirDisabled then Exit;
- {$ifndef FPC}
- Handles^[StdErrorHandle]:=OldHandleError;
- {$else}
- {$ifdef windows}
- SetStdHandle(Std_Error_Handle,StdErrorHandle);
- {$else not windows}
- fpdup2(TempHError,StdErrorHandle);
- {$endif not windows}
- {$endif}
- ErrorRedirDisabled:=True;
- end;
- {............................................................................}
- procedure EnableRedirError;
- begin
- If not RedirChangedError then Exit;
- If not ErrorRedirDisabled then Exit;
- {$ifndef FPC}
- Handles:=Ptr (prefseg, PWord (Ptr (prefseg, $34))^);
- Handles^[StdErrorHandle]:=Handles^[FileRec (FErr^).Handle];
- {$else}
- {$ifdef windows}
- SetStdHandle(Std_Error_Handle,FileRec(FErr^).Handle);
- {$else not windows}
- fpdup2(FileRec(FERR^).Handle,StdErrorHandle);
- {$endif not windows}
- {$endif}
- ErrorRedirDisabled:=False;
- end;
- {............................................................................}
- {$ifdef EXECUTEREDIR_USES_PROCESS}
- function ExecuteRedir (Const ProgName, ComLine : String; RedirStdIn, RedirStdOut, RedirStdErr: String): boolean;
- const
- max_count = 60000;
- var
- P : TProcess;
- begin
- Result:=false;
- IOstatus:=0;
- P := TProcess.Create(nil);
- try
- P.CommandLine:=Progname + ' ' + ComLine;
- P.InputDescriptor.FileName:=RedirStdIn;
- P.OutputDescriptor.FileName:=RedirStdOut;
- if RedirStdErr='stdout' then
- P.Options:=P.options+[poStdErrToOutput]
- else
- P.ErrorDescriptor.FileName:=RedirStdErr;
- try
- P.Execute;
- Result:=P.WaitOnExit(max_count);
- except
- on e : exception do
- begin
- IOStatus:=2;
- writeln(stderr,'ExecuteRedir generated an exception: ',E.Message);
- end;
- end;
- if Result then
- ExecuteResult:=P.ExitCode
- else if (IOStatus<>0) then
- ExecuteResult:=IOStatus*1000
- else
- begin
- Writeln(stderr,'Terminate requested for ',Progname,' ',ComLine);
- { Issue it also to output, so it gets added to log file
- if ExecuteRedir is in use }
- Writeln('Terminate requested for ',Progname,' ',ComLine);
- Repeat
- P.Terminate(255);
- Sleep(10);
- Until not P.Running;
- ExecuteResult:=1000+P.ExitCode;
- end;
- Result:=ExecuteResult=0;
- finally
- P.Free;
- end;
- end;
- {$ELSE}
- function ExecuteRedir (Const ProgName, ComLine : String; RedirStdIn, RedirStdOut, RedirStdErr: String): boolean;
- Begin
- RedirErrorOut:=0; RedirErrorIn:=0; RedirErrorError:=0;
- ExecuteResult:=0;
- IOStatus:=0;
- if RedirStdIn<>'' then
- ChangeRedirIn(RedirStdIn);
- if RedirStdOut<>'' then
- ChangeRedirOut(RedirStdOut,false);
- if RedirStdErr<>'stderr' then
- ChangeRedirError(RedirStdErr,false);
- DosExecute(ProgName,ComLine);
- RestoreRedirOut;
- RestoreRedirIn;
- RestoreRedirError;
- ExecuteRedir:=(IOStatus=0) and (RedirErrorOut=0) and
- (RedirErrorIn=0) and (RedirErrorError=0) and
- (ExecuteResult=0);
- End;
- {$ENDIF}
- {............................................................................}
- procedure RedirDisableAll;
- begin
- If RedirChangedIn and not InRedirDisabled then
- DisableRedirIn;
- If RedirChangedOut and not OutRedirDisabled then
- DisableRedirOut;
- If RedirChangedError and not ErrorRedirDisabled then
- DisableRedirError;
- end;
- {............................................................................}
- procedure RedirEnableAll;
- begin
- If RedirChangedIn and InRedirDisabled then
- EnableRedirIn;
- If RedirChangedOut and OutRedirDisabled then
- EnableRedirOut;
- If RedirChangedError and ErrorRedirDisabled then
- EnableRedirError;
- end;
- procedure InitRedir;
- begin
- end;
- {$else not implemented}
- {*****************************************************************************
- Fake
- *****************************************************************************}
- {$IFDEF SHELL_IMPLEMENTED}
- {$I-}
- function FileExist(const FileName : PathStr) : Boolean;
- var
- f : file;
- Attr : word;
- begin
- Assign(f, FileName);
- GetFAttr(f, Attr);
- FileExist := DosError = 0;
- end;
- function CompleteDir(const Path: string): string;
- begin
- { keep c: untouched PM }
- if (Path<>'') and (Path[Length(Path)]<>DirSep) and
- (Path[Length(Path)]<>':') then
- CompleteDir:=Path+DirSep
- else
- CompleteDir:=Path;
- end;
- function LocateExeFile(var FileName:string): boolean;
- var
- {$IFDEF USEDOS}
- dir,s,d,n,e : shortstring;
- {$ELSE USEDOS}
- dir,s,d,n,e : string;
- {$ENDIF USEDOS}
- i : longint;
- begin
- LocateExeFile:=False;
- if FileExist(FileName) then
- begin
- LocateExeFile:=true;
- Exit;
- end;
- Fsplit(Filename,d,n,e);
- if (e='') and FileExist(FileName+exeext) then
- begin
- FileName:=FileName+exeext;
- LocateExeFile:=true;
- Exit;
- end;
- {$ifdef macos}
- S:=GetEnv('Commands');
- {$else}
- S:=GetEnv('PATH');
- {$endif}
- While Length(S)>0 do
- begin
- i:=1;
- While (i<=Length(S)) and not (S[i] in ListSep) do
- Inc(i);
- Dir:=CompleteDir(Copy(S,1,i-1));
- if i<Length(S) then
- Delete(S,1,i)
- else
- S:='';
-
- if FileExist(Dir+FileName) then
- Begin
- FileName:=Dir+FileName;
- LocateExeFile:=true;
- Exit;
- End;
- end;
- end;
- function ExecuteRedir (Const ProgName, ComLine : String; RedirStdIn, RedirStdOut, RedirStdErr: String): boolean;
- var
- CmdLine2: string;
- begin
- {$ifdef macos}
- if Lowercase(RedirStdIn) = 'stdin' then RedirStdIn := 'Dev:StdIn';
- if Lowercase(RedirStdOut) = 'stdout' then RedirStdOut := 'Dev:Output';
- if Lowercase(RedirStdOut) = 'stderr' then RedirStdOut := 'Dev:Error';
- if Lowercase(RedirStdErr) = 'stdout' then RedirStdErr := 'Dev:Output';
- if Lowercase(RedirStdErr) = 'stderr' then RedirStdErr := 'Dev:Error';
- {$endif macos}
- CmdLine2 := ComLine;
- if RedirStdIn <> '' then CmdLine2 := CmdLine2 + ' < ' + RedirStdIn;
- {$ifndef macos}
- if RedirStdOut <> '' then CmdLine2 := CmdLine2 + ' > ' + RedirStdOut;
- if RedirStdErr <> '' then
- begin
- if RedirStdErr = RedirStdOut then
- CmdLine2 := CmdLine2 + ' 2>&1'
- else
- CmdLine2 := CmdLine2 + ' 2> ' + RedirStdErr;
- end;
- {$else macos}
- if RedirStdErr <> RedirStdOut then
- if RedirStdOut <> '' then CmdLine2 := CmdLine2 + ' > ' + RedirStdOut;
- if RedirStdErr <> '' then
- begin
- if RedirStdErr = RedirStdOut then
- CmdLine2 := CmdLine2 + ' ' + #183 + ' ' + RedirStdErr {#183 is "capital sigma" char in MacRoman}
- else
- CmdLine2 := CmdLine2 + ' ' + #179 + ' ' + RedirStdErr; {#179 is "greater or equal" char in MacRoman}
- end;
- {$endif macos}
- DosExecute (ProgName, CmdLine2);
- ExecuteRedir:=(IOStatus=0) and (ExecuteResult=0);
- end;
- {$ELSE SHELL_IMPLEMENTED}
- function ExecuteRedir (Const ProgName, ComLine : String; RedirStdIn, RedirStdOut, RedirStdErr: String): boolean;
- begin
- ExecuteRedir:=false;
- end;
- {$ENDIF SHELL_IMPLEMENTED}
- function ChangeRedirOut(Const Redir : String; AppendToFile : Boolean) : Boolean;
- begin
- ChangeRedirOut:=false;
- end;
- procedure RestoreRedirOut;
- begin
- end;
- procedure DisableRedirOut;
- begin
- end;
- procedure EnableRedirOut;
- begin
- end;
- function ChangeRedirIn(Const Redir : String) : Boolean;
- begin
- ChangeRedirIn:=false;
- end;
- procedure RestoreRedirIn;
- begin
- end;
- procedure DisableRedirIn;
- begin
- end;
- procedure EnableRedirIn;
- begin
- end;
- function ChangeRedirError(Const Redir : String; AppendToFile : Boolean) : Boolean;
- begin
- ChangeRedirError:=false;
- end;
- procedure RestoreRedirError;
- begin
- end;
- procedure DisableRedirError;
- begin
- end;
- procedure EnableRedirError;
- begin
- end;
- procedure RedirDisableAll;
- begin
- end;
- procedure RedirEnableAll;
- begin
- end;
- procedure InitRedir;
- begin
- end;
- {$endif not implemented}
- {............................................................................}
- {$ifdef UNIX}
- function TransformfpSystemToShell(s:cint):cint;
- // transforms standarized (fp)System(3) result to the conventions of the old Unix.shell function.
- begin
- if s=-1 then exit(-1);
- if wifexited(s) then
- TransformfpSystemToShell:=wexitstatus(s)
- else if (s>0) then
- TransformfpSystemToShell:=-s
- else
- TransformfpSystemToShell:=s;
- end;
- {$endif def UNIX}
- {****************************************************************************
- Helpers
- ****************************************************************************}
- {$ifdef USES_UNIT_PROCESS}
- const
- max_count = 60000; { should be 60 seconds }
- function ExecuteProcess(const Path: string; const ComLine: string; Flags:TExecuteFlags=[]): integer;
- var
- P: TProcess;
- counter : longint;
- TerminateSentCount : longint;
- begin
- result := -1;
- TerminateSentCount:=0;
- P := TProcess.Create(nil);
- try
- P.CommandLine := Path + ' ' + ComLine;
- P.InheritHandles:=(execinheritshandles in flags);
- P.Execute;
- {$if FPC_FULLVERSION < 30100}
- {$ifdef Windows}
- WaitForSingleObject(P.ProcessHandle,max_count);
- counter:=max_count;
- {$else not Windows}
- counter:=0;
- {$endif not Windows}
- {$else}
- P.WaitOnExit(max_count);
- counter:=max_count;
- {$endif}
- while P.Running do
- begin
- if counter>max_count then
- begin
- P.Terminate(255);
- if TerminateSentCount=0 then
- { also write ComLine in order to know which test is not ended in time }
- begin
- Writeln(stderr,'Terminate requested for ',Path,' ',ComLine);
- { Issue it also to output, so it gets added to log file
- if ExecuteRedir is in use }
- Writeln('Terminate requested for ',Path,' ',ComLine);
- end;
- Inc(TerminateSentCount);
- end;
- Sleep(1);
- inc(counter);
- end;
- { Be sure to return a non-zero value if Terminate was requested }
- if (TerminateSentCount>0) and (P.ExitStatus>=0) then
- result := 1000 + P.ExitStatus
- else
- result := P.ExitStatus;
- finally
- P.Free;
- end;
- end;
- {$endif HAS_UNIT_PROCESS}
- procedure DosExecute(ProgName, ComLine : String);
- Begin
- {$IfDef MsDos}
- SmallHeap;
- {$EndIf MsDos}
- {$ifdef usedos}
- SwapVectors;
- {$endif usedos}
- { Must use shell/fpsystem() for *nix for the wildcard expansion (PFV) }
- {$ifdef UNIX}
- IOStatus:=0;
- ExecuteResult:=Transformfpsystemtoshell(fpsystem((FixPath(Progname)+' '+Comline)));
- if ExecuteResult<0 then
- begin
- IOStatus:=(-ExecuteResult) and $7f;
- ExecuteResult:=((-ExecuteResult) and $ff00) shr 8;
- end;
- {$else}
- {$ifdef windows}
- { Avoid dialog boxes if dll loading fails }
- SetErrorMode(SEM_FAILCRITICALERRORS);
- {$endif windows}
- If UseComSpec then
- begin
- {$ifndef usedos}
- try
- ExecuteResult:=ExecuteProcess (Getenvironmentvariable('COMSPEC'),'/C '+FixPath(progname)+' '+Comline,[ExecInheritsHandles])
- except
- on e : exception do
- IOStatus:=2;
- end;
- {$else}
- DosError:=0;
- Exec (Getenv('COMSPEC'),'/C '+FixPath(progname)+' '+Comline);
- IOStatus:=DosError;
- ExecuteResult:=DosExitCode;
- {$endif}
- end
- else
- begin
- if LocateExeFile(progname) then
- begin
- {$ifndef usedos}
- try
- ExecuteResult:=ExecuteProcess(ProgName,Comline,[execinheritshandles])
- except
- on e : exception do
- IOStatus:=2;
- end;
- {$else}
- doserror:=0;
- {$ifdef macos}
- Dos.Exec(''''+ProgName+'''',Comline); {Quotes needed !}
- {$else}
- Dos.Exec(ProgName,Comline);
- {$endif}
- IOStatus:=DosError;
- ExecuteResult:=DosExitCode;
- {$endif}
- end
- else
- IOStatus:=2
- ;
- end;
- {$ifdef windows}
- SetErrorMode(0);
- {$endif windows}
- {$endif}
- {$ifdef usedos}
- SwapVectors;
- {$endif}
- {$ifdef CPU86}
- { reset the FPU }
- {$asmmode att}
- asm
- fninit
- end;
- {$endif CPU86}
- {$IfDef MsDos}
- Fullheap;
- {$EndIf MsDos}
- End;
- {*****************************************************************************
- Initialize
- *****************************************************************************}
- initialization
- New(FIn); New(FOut); New(FErr);
- finalization
- Dispose(FIn); Dispose(FOut); Dispose(FErr);
- End.
|