redir.pp 25 KB

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