redir.pp 24 KB

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