redir.pp 23 KB

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