redir.pp 23 KB

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