redir.pp 25 KB

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