redir.pp 24 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073
  1. {
  2. This file is part of the Free Pascal Test Suite
  3. Copyright (c) 1999-2000 by Pierre Muller
  4. Unit to redirect output and error to files
  5. Adapted from code donated to public domain by Schwartz Gabriel 20/03/1993
  6. See the file COPYING.FPC, included in this distribution,
  7. for details about the copyright.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  11. **********************************************************************}
  12. Unit Redir;
  13. Interface
  14. {$mode objfpc}
  15. {$H+}
  16. {$R-}
  17. {$ifndef Linux}
  18. {$ifndef Unix}
  19. {$S-}
  20. {$endif}
  21. {$endif}
  22. {$ifdef Go32v2}
  23. {$define implemented}
  24. {$endif}
  25. {$ifdef OS2}
  26. {$define shell_implemented}
  27. {$endif}
  28. {$ifdef windows}
  29. {$define implemented}
  30. {$endif}
  31. {$ifdef linux}
  32. {$define implemented}
  33. {$endif}
  34. {$ifdef BSD}
  35. {$define implemented}
  36. {$endif}
  37. {$ifdef BEOS}
  38. {$define implemented}
  39. {$endif}
  40. {$ifdef macos}
  41. {$define shell_implemented}
  42. {$endif}
  43. {$ifdef sunos}
  44. {$define implemented}
  45. {$endif}
  46. Var
  47. IOStatus : Integer;
  48. RedirErrorOut,RedirErrorIn,
  49. RedirErrorError : Integer;
  50. ExecuteResult : Longint;
  51. {------------------------------------------------------------------------------}
  52. procedure InitRedir;
  53. function ExecuteRedir (Const ProgName, ComLine : String; RedirStdIn, RedirStdOut, RedirStdErr: String): boolean;
  54. procedure DosExecute(ProgName, ComLine : String);
  55. function ChangeRedirOut(Const Redir : String; AppendToFile : Boolean) : Boolean;
  56. procedure RestoreRedirOut;
  57. procedure DisableRedirOut;
  58. procedure EnableRedirOut;
  59. function ChangeRedirIn(Const Redir : String) : Boolean;
  60. procedure RestoreRedirIn;
  61. procedure DisableRedirIn;
  62. procedure EnableRedirIn;
  63. function ChangeRedirError(Const Redir : String; AppendToFile : Boolean) : Boolean;
  64. procedure RestoreRedirError;
  65. procedure DisableRedirError;
  66. procedure EnableRedirError;
  67. procedure RedirDisableAll;
  68. procedure RedirEnableAll;
  69. { unused in UNIX }
  70. const
  71. UseComSpec : boolean = true;
  72. Implementation
  73. //or defined(windows)
  74. {$if defined(macos) or defined(shell_implemented) or defined(go32v2)}
  75. {$define usedos}
  76. {$endif}
  77. {$if defined(windows) and not defined(usedos)}
  78. {$ifdef ver2_4}
  79. {$define redirexecuteprocess}
  80. {$endif}
  81. {$endif}
  82. Uses
  83. {$ifdef go32v2}
  84. go32,
  85. {$endif go32v2}
  86. {$ifdef windows}
  87. windows,
  88. {$endif windows}
  89. {$ifdef unix}
  90. baseunix,
  91. unix,
  92. {$endif unix}
  93. {$ifdef redirexecuteprocess}
  94. sysconst,
  95. {$endif}
  96. {$ifdef usedos}
  97. dos;
  98. {$else}
  99. sysutils;
  100. {$endif}
  101. Const
  102. {$ifdef UNIX}
  103. DirSep='/';
  104. listsep = [';',':'];
  105. exeext = '';
  106. {$else UNIX}
  107. {$ifdef MACOS}
  108. DirSep=':';
  109. listsep = [','];
  110. exeext = '';
  111. {$else MACOS}
  112. DirSep='\';
  113. listsep = [';'];
  114. exeext = '.exe';
  115. {$endif MACOS}
  116. {$endif UNIX}
  117. {$ifndef usedos}
  118. { code from: }
  119. { Lithuanian Text Tool version 0.9.0 (2001-04-19) }
  120. { Copyright (c) 1999-2001 Marius Gedminas <[email protected]> }
  121. { (GPLv2 or later) }
  122. function FExpand(const S: string): string;
  123. begin
  124. FExpand := ExpandFileName(S);
  125. end;
  126. type
  127. PathStr = string;
  128. DirStr = string;
  129. NameStr = string;
  130. ExtStr = string;
  131. procedure FSplit(Path: PathStr; var Dir: DirStr; var Name: NameStr; var Ext: ExtStr);
  132. begin
  133. Dir := ExtractFilePath(Path);
  134. Name := ChangeFileExt(ExtractFileName(Path), '');
  135. Ext := ExtractFileExt(Path);
  136. end;
  137. {$endif}
  138. var
  139. FIN,FOUT,FERR : ^File;
  140. RedirStdErrToStdOut,
  141. RedirChangedOut,
  142. RedirChangedIn : Boolean;
  143. RedirChangedError : Boolean;
  144. InRedirDisabled,OutRedirDisabled,ErrorRedirDisabled : Boolean;
  145. {*****************************************************************************
  146. Helpers
  147. *****************************************************************************}
  148. function FixPath(const s:string):string;
  149. var
  150. i : longint;
  151. begin
  152. { Fix separator }
  153. setlength(fixpath,length(s));
  154. for i:=1 to length(s) do
  155. if s[i] in ['/','\'] then
  156. fixpath[i]:=DirSep
  157. else
  158. fixpath[i]:=s[i];
  159. end;
  160. {*****************************************************************************
  161. Dos
  162. *****************************************************************************}
  163. {$ifdef implemented}
  164. {$ifndef usedos}
  165. {$if defined(ver2_4_0) or defined(ver2_4_1)}
  166. Type
  167. TExecuteFlags= set of (ExecInheritsHandles);
  168. {$ifdef redirexecuteprocess}
  169. function ExecuteProcess(Const Path: AnsiString; Const ComLine: AnsiString;Flags:TExecuteFlags=[]):integer;
  170. // win specific function
  171. var
  172. SI: TStartupInfo;
  173. PI: TProcessInformation;
  174. Proc : THandle;
  175. l : DWord;
  176. CommandLine : ansistring;
  177. e : EOSError;
  178. ExecInherits : longbool;
  179. begin
  180. FillChar(SI, SizeOf(SI), 0);
  181. SI.cb:=SizeOf(SI);
  182. SI.wShowWindow:=1;
  183. { always surround the name of the application by quotes
  184. so that long filenames will always be accepted. But don't
  185. do it if there are already double quotes, since Win32 does not
  186. like double quotes which are duplicated!
  187. }
  188. if pos('"',path)=0 then
  189. CommandLine:='"'+path+'"'
  190. else
  191. CommandLine:=path;
  192. if ComLine <> '' then
  193. CommandLine:=Commandline+' '+ComLine+#0
  194. else
  195. CommandLine := CommandLine + #0;
  196. ExecInherits:=ExecInheritsHandles in Flags;
  197. if not CreateProcess(nil, pchar(CommandLine),
  198. Nil, Nil, ExecInherits,$20, Nil, Nil, SI, PI) then
  199. begin
  200. e:=EOSError.CreateFmt(SExecuteProcessFailed,[CommandLine,GetLastError]);
  201. e.ErrorCode:=GetLastError;
  202. raise e;
  203. end;
  204. Proc:=PI.hProcess;
  205. if WaitForSingleObject(Proc, dword($ffffffff)) <> $ffffffff then
  206. begin
  207. GetExitCodeProcess(Proc,l);
  208. CloseHandle(Proc);
  209. CloseHandle(PI.hThread);
  210. result:=l;
  211. end
  212. else
  213. begin
  214. e:=EOSError.CreateFmt(SExecuteProcessFailed,[CommandLine,GetLastError]);
  215. e.ErrorCode:=GetLastError;
  216. CloseHandle(Proc);
  217. CloseHandle(PI.hThread);
  218. raise e;
  219. end;
  220. end;
  221. {$else}
  222. function ExecuteProcess(Const Path: AnsiString; Const ComLine: AnsiString;Flags:TExecuteFlags=[]):integer;
  223. begin
  224. result:=ExecuteProcess(path,comline);
  225. end;
  226. {$endif}
  227. {$ifend}
  228. {$endif}
  229. {$ifndef windows}
  230. var
  231. TempHOut, TempHIn,TempHError : longint;
  232. {$endif ndef windows}
  233. {
  234. For Unix the following functions exist
  235. Function fpdup(oldfile:longint;var newfile:longint):Boolean;
  236. Function fpdup2(oldfile,newfile:longint):Boolean;
  237. Function fpClose(fd:longint):boolean;
  238. }
  239. {$ifdef go32v2}
  240. function fpdup(fh : longint) : longint;
  241. var
  242. Regs : Registers;
  243. begin
  244. Regs.ah:=$45;
  245. Regs.bx:=fh;
  246. MsDos (Regs);
  247. If (Regs.Flags and fCarry)=0 then
  248. fpdup:=Regs.Ax
  249. else
  250. fpdup:=-1;
  251. end;
  252. function fpdup2(fh,nh : longint) : longint;
  253. var
  254. Regs : Registers;
  255. begin
  256. fpdup2:=0;
  257. If fh=nh then
  258. exit;
  259. Regs.ah:=$46;
  260. Regs.bx:=fh;
  261. Regs.cx:=nh;
  262. MsDos (Regs);
  263. If (Regs.Flags and fCarry)<>0 then
  264. fpdup2:=-1;
  265. end;
  266. Function fpclose (Handle : Longint) : boolean;
  267. var Regs: registers;
  268. begin
  269. Regs.Eax := $3e00;
  270. Regs.Ebx := Handle;
  271. MsDos(Regs);
  272. fpclose:=(Regs.Flags and fCarry)=0;
  273. end;
  274. {$endif def go32v2}
  275. {$ifdef windows}
  276. Function fpclose (Handle : Longint) : boolean;
  277. begin
  278. { Do we need this ?? }
  279. fpclose:=true;
  280. end;
  281. {$endif}
  282. {$ifdef os2}
  283. Function fpclose (Handle : Longint) : boolean;
  284. begin
  285. { Do we need this ?? }
  286. fpclose:=true;
  287. end;
  288. {$endif}
  289. {$I-}
  290. function FileExist(const FileName : PathStr) : Boolean;
  291. {$ifdef usedos}
  292. var
  293. f : file;
  294. Attr : word;
  295. {$endif}
  296. begin
  297. {$ifdef usedos}
  298. Assign(f, FileName);
  299. GetFAttr(f, Attr);
  300. FileExist := DosError = 0;
  301. {$else}
  302. FileExist := Sysutils.FileExists(filename);
  303. {$endif}
  304. end;
  305. function CompleteDir(const Path: string): string;
  306. begin
  307. { keep c: untouched PM }
  308. if (Path<>'') and (Path[Length(Path)]<>DirSep) and
  309. (Path[Length(Path)]<>':') then
  310. CompleteDir:=Path+DirSep
  311. else
  312. CompleteDir:=Path;
  313. end;
  314. function LocateExeFile(var FileName:string): boolean;
  315. var
  316. dir,s: string;
  317. d: dirstr;
  318. n: namestr;
  319. e: extstr;
  320. i : longint;
  321. begin
  322. LocateExeFile:=False;
  323. if FileExist(FileName) then
  324. begin
  325. LocateExeFile:=true;
  326. Exit;
  327. end;
  328. Fsplit(Filename,d,n,e);
  329. if (e='') and FileExist(FileName+exeext) then
  330. begin
  331. FileName:=FileName+exeext;
  332. LocateExeFile:=true;
  333. Exit;
  334. end;
  335. {$ifdef usedos}
  336. S:=GetEnv('PATH');
  337. {$else}
  338. S:=GetEnvironmentVariable('PATH');
  339. {$endif}
  340. While Length(S)>0 do
  341. begin
  342. i:=1;
  343. While (i<=Length(S)) and not (S[i] in ListSep) do
  344. Inc(i);
  345. Dir:=CompleteDir(Copy(S,1,i-1));
  346. if i<Length(S) then
  347. Delete(S,1,i)
  348. else
  349. S:='';
  350. if FileExist(Dir+FileName) then
  351. Begin
  352. FileName:=Dir+FileName;
  353. LocateExeFile:=true;
  354. Exit;
  355. End;
  356. end;
  357. end;
  358. {............................................................................}
  359. function ChangeRedirOut(Const Redir : String; AppendToFile : Boolean) : Boolean;
  360. begin
  361. ChangeRedirOut:=False;
  362. If Redir = '' then Exit;
  363. Assign (FOUT^, Redir);
  364. If AppendToFile and FileExist(Redir) then
  365. Begin
  366. Reset(FOUT^,1);
  367. Seek(FOUT^,FileSize(FOUT^));
  368. End else Rewrite (FOUT^);
  369. RedirErrorOut:=IOResult;
  370. IOStatus:=RedirErrorOut;
  371. If IOStatus <> 0 then Exit;
  372. {$ifndef FPC}
  373. Handles:=Ptr (prefseg, PWord (Ptr (prefseg, $34))^);
  374. OldHandleOut:=Handles^[StdOutputHandle];
  375. Handles^[StdOutputHandle]:=Handles^[FileRec (FOUT^).Handle];
  376. ChangeRedirOut:=True;
  377. OutRedirDisabled:=False;
  378. {$else}
  379. {$ifdef windows}
  380. if SetStdHandle(Std_Output_Handle,FileRec(FOUT^).Handle) then
  381. {$else not windows}
  382. TempHOut:=fpdup(StdOutputHandle);
  383. fpdup2(FileRec(FOUT^).Handle,StdOutputHandle);
  384. if (TempHOut<>UnusedHandle) and
  385. (StdOutputHandle<>UnusedHandle) then
  386. {$endif not windows}
  387. begin
  388. ChangeRedirOut:=True;
  389. OutRedirDisabled:=False;
  390. end;
  391. {$endif def FPC}
  392. RedirChangedOut:=True;
  393. end;
  394. function ChangeRedirIn(Const Redir : String) : Boolean;
  395. begin
  396. ChangeRedirIn:=False;
  397. If Redir = '' then Exit;
  398. Assign (FIN^, Redir);
  399. Reset(FIN^,1);
  400. RedirErrorIn:=IOResult;
  401. IOStatus:=RedirErrorIn;
  402. If IOStatus <> 0 then Exit;
  403. {$ifndef FPC}
  404. Handles:=Ptr (prefseg, PWord (Ptr (prefseg, $34))^);
  405. OldHandleIn:=Handles^[StdInputHandle];
  406. Handles^[StdInputHandle]:=Handles^[FileRec (FIN^).Handle];
  407. ChangeRedirIn:=True;
  408. InRedirDisabled:=False;
  409. {$else}
  410. {$ifdef windows}
  411. if SetStdHandle(Std_Input_Handle,FileRec(FIN^).Handle) then
  412. {$else not windows}
  413. TempHIn:=fpdup(StdInputHandle);
  414. fpdup2(FileRec(FIn^).Handle,StdInputHandle);
  415. if (TempHIn<>UnusedHandle) and
  416. (StdInputHandle<>UnusedHandle) then
  417. {$endif not windows}
  418. begin
  419. ChangeRedirIn:=True;
  420. InRedirDisabled:=False;
  421. end;
  422. {$endif def FPC}
  423. RedirChangedIn:=True;
  424. end;
  425. function ChangeRedirError(Const Redir : String; AppendToFile : Boolean) : Boolean;
  426. var
  427. PF : ^File;
  428. begin
  429. ChangeRedirError:=False;
  430. If Redir = '' then
  431. Exit;
  432. RedirStdErrToStdOut:=(Redir='stdout');
  433. if RedirStdErrToStdOut then
  434. begin
  435. PF:=FOut;
  436. end
  437. else
  438. begin
  439. Assign (FERR^, Redir);
  440. If AppendToFile and FileExist(Redir) then
  441. Begin
  442. Reset(FERR^,1);
  443. Seek(FERR^,FileSize(FERR^));
  444. End
  445. else
  446. Rewrite (FERR^);
  447. RedirErrorError:=IOResult;
  448. IOStatus:=RedirErrorError;
  449. If IOStatus <> 0 then Exit;
  450. PF:=FErr;
  451. end;
  452. {$ifndef FPC}
  453. Handles:=Ptr (prefseg, PWord (Ptr (prefseg, $34))^);
  454. OldHandleError:=Handles^[StdErrorHandle];
  455. Handles^[StdErrorHandle]:=Handles^[FileRec (PF^).Handle];
  456. ChangeRedirError:=True;
  457. ErrorRedirDisabled:=False;
  458. {$else}
  459. {$ifdef windows}
  460. if SetStdHandle(Std_Error_Handle,FileRec(PF^).Handle) then
  461. {$else not windows}
  462. TempHError:=fpdup(StdErrorHandle);
  463. fpdup2(FileRec(PF^).Handle,StdErrorHandle);
  464. if (TempHError<>UnusedHandle) and
  465. (StdErrorHandle<>UnusedHandle) then
  466. {$endif not windows}
  467. begin
  468. ChangeRedirError:=True;
  469. ErrorRedirDisabled:=False;
  470. end;
  471. {$endif}
  472. RedirChangedError:=True;
  473. end;
  474. procedure RestoreRedirOut;
  475. begin
  476. If not RedirChangedOut then Exit;
  477. {$ifdef windows}
  478. SetStdHandle(Std_Output_Handle,StdOutputHandle);
  479. {$else not windows}
  480. fpdup2(TempHOut,StdOutputHandle);
  481. {$endif not windows}
  482. Close (FOUT^);
  483. {$ifndef windows}
  484. fpclose(TempHOut);
  485. {$endif ndef windows}
  486. RedirChangedOut:=false;
  487. end;
  488. {............................................................................}
  489. procedure RestoreRedirIn;
  490. begin
  491. If not RedirChangedIn then Exit;
  492. {$ifndef FPC}
  493. Handles^[StdInputHandle]:=OldHandleIn;
  494. OldHandleIn:=StdInputHandle;
  495. {$else}
  496. {$ifdef windows}
  497. SetStdHandle(Std_Input_Handle,StdInputHandle);
  498. {$else not windows}
  499. fpdup2(TempHIn,StdInputHandle);
  500. {$endif not windows}
  501. {$endif}
  502. Close (FIn^);
  503. {$ifndef windows}
  504. fpclose(TempHIn);
  505. {$endif ndef windows}
  506. RedirChangedIn:=false;
  507. end;
  508. {............................................................................}
  509. procedure DisableRedirIn;
  510. begin
  511. If not RedirChangedIn then Exit;
  512. If InRedirDisabled then Exit;
  513. {$ifndef FPC}
  514. Handles^[StdInputHandle]:=OldHandleIn;
  515. {$else}
  516. {$ifdef windows}
  517. SetStdHandle(Std_Input_Handle,StdInputHandle);
  518. {$else not windows}
  519. fpdup2(TempHIn,StdInputHandle);
  520. {$endif not windows}
  521. {$endif}
  522. InRedirDisabled:=True;
  523. end;
  524. {............................................................................}
  525. procedure EnableRedirIn;
  526. begin
  527. If not RedirChangedIn then Exit;
  528. If not InRedirDisabled then Exit;
  529. {$ifndef FPC}
  530. Handles:=Ptr (prefseg, PWord (Ptr (prefseg, $34))^);
  531. Handles^[StdInputHandle]:=Handles^[FileRec (FIn^).Handle];
  532. {$else}
  533. {$ifdef windows}
  534. SetStdHandle(Std_Input_Handle,FileRec(FIn^).Handle);
  535. {$else not windows}
  536. fpdup2(FileRec(FIn^).Handle,StdInputHandle);
  537. {$endif not windows}
  538. {$endif}
  539. InRedirDisabled:=False;
  540. end;
  541. {............................................................................}
  542. procedure DisableRedirOut;
  543. begin
  544. If not RedirChangedOut then Exit;
  545. If OutRedirDisabled then Exit;
  546. {$ifndef FPC}
  547. Handles^[StdOutputHandle]:=OldHandleOut;
  548. {$else}
  549. {$ifdef windows}
  550. SetStdHandle(Std_Output_Handle,StdOutputHandle);
  551. {$else not windows}
  552. fpdup2(TempHOut,StdOutputHandle);
  553. {$endif not windows}
  554. {$endif}
  555. OutRedirDisabled:=True;
  556. end;
  557. {............................................................................}
  558. procedure EnableRedirOut;
  559. begin
  560. If not RedirChangedOut then Exit;
  561. If not OutRedirDisabled then Exit;
  562. {$ifndef FPC}
  563. Handles:=Ptr (prefseg, PWord (Ptr (prefseg, $34))^);
  564. Handles^[StdOutputHandle]:=Handles^[FileRec (FOut^).Handle];
  565. {$else}
  566. {$ifdef windows}
  567. SetStdHandle(Std_Output_Handle,FileRec(FOut^).Handle);
  568. {$else not windows}
  569. fpdup2(FileRec(FOut^).Handle,StdOutputHandle);
  570. {$endif not windows}
  571. {$endif}
  572. OutRedirDisabled:=False;
  573. end;
  574. {............................................................................}
  575. procedure RestoreRedirError;
  576. begin
  577. If not RedirChangedError then Exit;
  578. {$ifndef FPC}
  579. Handles^[StdErrorHandle]:=OldHandleError;
  580. OldHandleError:=StdErrorHandle;
  581. {$else}
  582. {$ifdef windows}
  583. SetStdHandle(Std_Error_Handle,StdErrorHandle);
  584. {$else not windows}
  585. fpdup2(TempHError,StdErrorHandle);
  586. {$endif not windows}
  587. {$endif}
  588. { don't close when redirected to STDOUT }
  589. if not RedirStdErrToStdOut then
  590. Close (FERR^);
  591. {$ifndef windows}
  592. fpclose(TempHError);
  593. {$endif ndef windows}
  594. RedirChangedError:=false;
  595. end;
  596. {............................................................................}
  597. procedure DisableRedirError;
  598. begin
  599. If not RedirChangedError then Exit;
  600. If ErrorRedirDisabled then Exit;
  601. {$ifndef FPC}
  602. Handles^[StdErrorHandle]:=OldHandleError;
  603. {$else}
  604. {$ifdef windows}
  605. SetStdHandle(Std_Error_Handle,StdErrorHandle);
  606. {$else not windows}
  607. fpdup2(TempHError,StdErrorHandle);
  608. {$endif not windows}
  609. {$endif}
  610. ErrorRedirDisabled:=True;
  611. end;
  612. {............................................................................}
  613. procedure EnableRedirError;
  614. begin
  615. If not RedirChangedError then Exit;
  616. If not ErrorRedirDisabled then Exit;
  617. {$ifndef FPC}
  618. Handles:=Ptr (prefseg, PWord (Ptr (prefseg, $34))^);
  619. Handles^[StdErrorHandle]:=Handles^[FileRec (FErr^).Handle];
  620. {$else}
  621. {$ifdef windows}
  622. SetStdHandle(Std_Error_Handle,FileRec(FErr^).Handle);
  623. {$else not windows}
  624. fpdup2(FileRec(FERR^).Handle,StdErrorHandle);
  625. {$endif not windows}
  626. {$endif}
  627. ErrorRedirDisabled:=False;
  628. end;
  629. {............................................................................}
  630. function ExecuteRedir (Const ProgName, ComLine : String; RedirStdIn, RedirStdOut, RedirStdErr: String): boolean;
  631. Begin
  632. RedirErrorOut:=0; RedirErrorIn:=0; RedirErrorError:=0;
  633. ExecuteResult:=0;
  634. IOStatus:=0;
  635. if RedirStdIn<>'' then
  636. ChangeRedirIn(RedirStdIn);
  637. if RedirStdOut<>'' then
  638. ChangeRedirOut(RedirStdOut,false);
  639. if RedirStdErr<>'stderr' then
  640. ChangeRedirError(RedirStdErr,false);
  641. DosExecute(ProgName,ComLine);
  642. RestoreRedirOut;
  643. RestoreRedirIn;
  644. RestoreRedirError;
  645. ExecuteRedir:=(IOStatus=0) and (RedirErrorOut=0) and
  646. (RedirErrorIn=0) and (RedirErrorError=0) and
  647. (ExecuteResult=0);
  648. End;
  649. {............................................................................}
  650. procedure RedirDisableAll;
  651. begin
  652. If RedirChangedIn and not InRedirDisabled then
  653. DisableRedirIn;
  654. If RedirChangedOut and not OutRedirDisabled then
  655. DisableRedirOut;
  656. If RedirChangedError and not ErrorRedirDisabled then
  657. DisableRedirError;
  658. end;
  659. {............................................................................}
  660. procedure RedirEnableAll;
  661. begin
  662. If RedirChangedIn and InRedirDisabled then
  663. EnableRedirIn;
  664. If RedirChangedOut and OutRedirDisabled then
  665. EnableRedirOut;
  666. If RedirChangedError and ErrorRedirDisabled then
  667. EnableRedirError;
  668. end;
  669. procedure InitRedir;
  670. begin
  671. end;
  672. {$else not implemented}
  673. {*****************************************************************************
  674. Fake
  675. *****************************************************************************}
  676. {$IFDEF SHELL_IMPLEMENTED}
  677. {$I-}
  678. function FileExist(const FileName : PathStr) : Boolean;
  679. var
  680. f : file;
  681. Attr : word;
  682. begin
  683. Assign(f, FileName);
  684. GetFAttr(f, Attr);
  685. FileExist := DosError = 0;
  686. end;
  687. function CompleteDir(const Path: string): string;
  688. begin
  689. { keep c: untouched PM }
  690. if (Path<>'') and (Path[Length(Path)]<>DirSep) and
  691. (Path[Length(Path)]<>':') then
  692. CompleteDir:=Path+DirSep
  693. else
  694. CompleteDir:=Path;
  695. end;
  696. function LocateExeFile(var FileName:string): boolean;
  697. var
  698. {$IFDEF USEDOS}
  699. dir,s,d,n,e : shortstring;
  700. {$ELSE USEDOS}
  701. dir,s,d,n,e : string;
  702. {$ENDIF USEDOS}
  703. i : longint;
  704. begin
  705. LocateExeFile:=False;
  706. if FileExist(FileName) then
  707. begin
  708. LocateExeFile:=true;
  709. Exit;
  710. end;
  711. Fsplit(Filename,d,n,e);
  712. if (e='') and FileExist(FileName+exeext) then
  713. begin
  714. FileName:=FileName+exeext;
  715. LocateExeFile:=true;
  716. Exit;
  717. end;
  718. {$ifdef macos}
  719. S:=GetEnv('Commands');
  720. {$else}
  721. S:=GetEnv('PATH');
  722. {$endif}
  723. While Length(S)>0 do
  724. begin
  725. i:=1;
  726. While (i<=Length(S)) and not (S[i] in ListSep) do
  727. Inc(i);
  728. Dir:=CompleteDir(Copy(S,1,i-1));
  729. if i<Length(S) then
  730. Delete(S,1,i)
  731. else
  732. S:='';
  733. if FileExist(Dir+FileName) then
  734. Begin
  735. FileName:=Dir+FileName;
  736. LocateExeFile:=true;
  737. Exit;
  738. End;
  739. end;
  740. end;
  741. function ExecuteRedir (Const ProgName, ComLine : String; RedirStdIn, RedirStdOut, RedirStdErr: String): boolean;
  742. var
  743. CmdLine2: string;
  744. begin
  745. {$ifdef macos}
  746. if Lowercase(RedirStdIn) = 'stdin' then RedirStdIn := 'Dev:StdIn';
  747. if Lowercase(RedirStdOut) = 'stdout' then RedirStdOut := 'Dev:Output';
  748. if Lowercase(RedirStdOut) = 'stderr' then RedirStdOut := 'Dev:Error';
  749. if Lowercase(RedirStdErr) = 'stdout' then RedirStdErr := 'Dev:Output';
  750. if Lowercase(RedirStdErr) = 'stderr' then RedirStdErr := 'Dev:Error';
  751. {$endif macos}
  752. CmdLine2 := ComLine;
  753. if RedirStdIn <> '' then CmdLine2 := CmdLine2 + ' < ' + RedirStdIn;
  754. {$ifndef macos}
  755. if RedirStdOut <> '' then CmdLine2 := CmdLine2 + ' > ' + RedirStdOut;
  756. if RedirStdErr <> '' then
  757. begin
  758. if RedirStdErr = RedirStdOut then
  759. CmdLine2 := CmdLine2 + ' 2>&1'
  760. else
  761. CmdLine2 := CmdLine2 + ' 2> ' + RedirStdErr;
  762. end;
  763. {$else macos}
  764. if RedirStdErr <> RedirStdOut then
  765. if RedirStdOut <> '' then CmdLine2 := CmdLine2 + ' > ' + RedirStdOut;
  766. if RedirStdErr <> '' then
  767. begin
  768. if RedirStdErr = RedirStdOut then
  769. CmdLine2 := CmdLine2 + ' ' + #183 + ' ' + RedirStdErr {#183 is "capital sigma" char in MacRoman}
  770. else
  771. CmdLine2 := CmdLine2 + ' ' + #179 + ' ' + RedirStdErr; {#179 is "greater or equal" char in MacRoman}
  772. end;
  773. {$endif macos}
  774. DosExecute (ProgName, CmdLine2);
  775. ExecuteRedir:=(IOStatus=0) and (ExecuteResult=0);
  776. end;
  777. {$ELSE SHELL_IMPLEMENTED}
  778. function ExecuteRedir (Const ProgName, ComLine : String; RedirStdIn, RedirStdOut, RedirStdErr: String): boolean;
  779. begin
  780. ExecuteRedir:=false;
  781. end;
  782. {$ENDIF SHELL_IMPLEMENTED}
  783. function ChangeRedirOut(Const Redir : String; AppendToFile : Boolean) : Boolean;
  784. begin
  785. ChangeRedirOut:=false;
  786. end;
  787. procedure RestoreRedirOut;
  788. begin
  789. end;
  790. procedure DisableRedirOut;
  791. begin
  792. end;
  793. procedure EnableRedirOut;
  794. begin
  795. end;
  796. function ChangeRedirIn(Const Redir : String) : Boolean;
  797. begin
  798. ChangeRedirIn:=false;
  799. end;
  800. procedure RestoreRedirIn;
  801. begin
  802. end;
  803. procedure DisableRedirIn;
  804. begin
  805. end;
  806. procedure EnableRedirIn;
  807. begin
  808. end;
  809. function ChangeRedirError(Const Redir : String; AppendToFile : Boolean) : Boolean;
  810. begin
  811. ChangeRedirError:=false;
  812. end;
  813. procedure RestoreRedirError;
  814. begin
  815. end;
  816. procedure DisableRedirError;
  817. begin
  818. end;
  819. procedure EnableRedirError;
  820. begin
  821. end;
  822. procedure RedirDisableAll;
  823. begin
  824. end;
  825. procedure RedirEnableAll;
  826. begin
  827. end;
  828. procedure InitRedir;
  829. begin
  830. end;
  831. {$endif not implemented}
  832. {............................................................................}
  833. procedure DosExecute(ProgName, ComLine : String);
  834. Begin
  835. {$IfDef MsDos}
  836. SmallHeap;
  837. {$EndIf MsDos}
  838. {$ifdef usedos}
  839. SwapVectors;
  840. {$endif usedos}
  841. { Must use shell() for linux for the wildcard expansion (PFV) }
  842. {$ifdef UNIX}
  843. IOStatus:=0;
  844. ExecuteResult:=Shell(FixPath(Progname)+' '+Comline);
  845. if ExecuteResult<0 then
  846. begin
  847. IOStatus:=(-ExecuteResult) and $7f;
  848. ExecuteResult:=((-ExecuteResult) and $ff00) shr 8;
  849. end;
  850. {$else}
  851. {$ifdef windows}
  852. { Avoid dialog boxes if dll loading fails }
  853. SetErrorMode(SEM_FAILCRITICALERRORS);
  854. {$endif windows}
  855. If UseComSpec then
  856. begin
  857. {$ifndef usedos}
  858. try
  859. ExecuteResult:=ExecuteProcess (Getenvironmentvariable('COMSPEC'),'/C '+FixPath(progname)+' '+Comline,[ExecInheritsHandles])
  860. except
  861. on e : exception do
  862. IOStatus:=2;
  863. end;
  864. {$else}
  865. DosError:=0;
  866. Exec (Getenv('COMSPEC'),'/C '+FixPath(progname)+' '+Comline);
  867. IOStatus:=DosError;
  868. ExecuteResult:=DosExitCode;
  869. {$endif}
  870. end
  871. else
  872. begin
  873. if LocateExeFile(progname) then
  874. begin
  875. {$ifndef usedos}
  876. try
  877. ExecuteResult:=ExecuteProcess(ProgName,Comline,[execinheritshandles])
  878. except
  879. on e : exception do
  880. IOStatus:=2;
  881. end;
  882. {$else}
  883. doserror:=0;
  884. {$ifdef macos}
  885. Dos.Exec(''''+ProgName+'''',Comline); {Quotes needed !}
  886. {$else}
  887. Dos.Exec(ProgName,Comline);
  888. {$endif}
  889. IOStatus:=DosError;
  890. ExecuteResult:=DosExitCode;
  891. {$endif}
  892. end
  893. else
  894. IOStatus:=2
  895. ;
  896. end;
  897. {$ifdef windows}
  898. SetErrorMode(0);
  899. {$endif windows}
  900. {$endif}
  901. {$ifdef usedos}
  902. SwapVectors;
  903. {$endif}
  904. {$ifdef CPU86}
  905. { reset the FPU }
  906. {$asmmode att}
  907. asm
  908. fninit
  909. end;
  910. {$endif CPU86}
  911. {$IfDef MsDos}
  912. Fullheap;
  913. {$EndIf MsDos}
  914. End;
  915. {*****************************************************************************
  916. Initialize
  917. *****************************************************************************}
  918. initialization
  919. New(FIn); New(FOut); New(FErr);
  920. finalization
  921. Dispose(FIn); Dispose(FOut); Dispose(FErr);
  922. End.