redir.pp 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083
  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. {$ifdef macos}
  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,d,n,e : string;
  295. i : longint;
  296. begin
  297. LocateExeFile:=False;
  298. if FileExist(FileName) then
  299. begin
  300. LocateExeFile:=true;
  301. Exit;
  302. end;
  303. Fsplit(Filename,d,n,e);
  304. if (e='') and FileExist(FileName+exeext) then
  305. begin
  306. FileName:=FileName+exeext;
  307. LocateExeFile:=true;
  308. Exit;
  309. end;
  310. {$ifdef usedos}
  311. S:=GetEnv('PATH');
  312. {$else}
  313. S:=GetEnvironmentVariable('PATH');
  314. {$endif}
  315. While Length(S)>0 do
  316. begin
  317. i:=1;
  318. While (i<=Length(S)) and not (S[i] in ListSep) do
  319. Inc(i);
  320. Dir:=CompleteDir(Copy(S,1,i-1));
  321. if i<Length(S) then
  322. Delete(S,1,i)
  323. else
  324. S:='';
  325. if FileExist(Dir+FileName) then
  326. Begin
  327. FileName:=Dir+FileName;
  328. LocateExeFile:=true;
  329. Exit;
  330. End;
  331. end;
  332. end;
  333. {............................................................................}
  334. function ChangeRedirOut(Const Redir : String; AppendToFile : Boolean) : Boolean;
  335. begin
  336. ChangeRedirOut:=False;
  337. If Redir = '' then Exit;
  338. Assign (FOUT^, Redir);
  339. If AppendToFile and FileExist(Redir) then
  340. Begin
  341. Reset(FOUT^,1);
  342. Seek(FOUT^,FileSize(FOUT^));
  343. End else Rewrite (FOUT^);
  344. RedirErrorOut:=IOResult;
  345. IOStatus:=RedirErrorOut;
  346. If IOStatus <> 0 then Exit;
  347. {$ifndef FPC}
  348. Handles:=Ptr (prefseg, PWord (Ptr (prefseg, $34))^);
  349. OldHandleOut:=Handles^[StdOutputHandle];
  350. Handles^[StdOutputHandle]:=Handles^[FileRec (FOUT^).Handle];
  351. ChangeRedirOut:=True;
  352. OutRedirDisabled:=False;
  353. {$else}
  354. {$ifdef windows}
  355. if SetStdHandle(Std_Output_Handle,FileRec(FOUT^).Handle) then
  356. {$else not windows}
  357. {$ifdef ver1_0}
  358. dup(StdOutputHandle,TempHOut);
  359. dup2(FileRec(FOUT^).Handle,StdOutputHandle);
  360. {$else}
  361. TempHOut:=fpdup(StdOutputHandle);
  362. fpdup2(FileRec(FOUT^).Handle,StdOutputHandle);
  363. {$endif}
  364. if (TempHOut<>UnusedHandle) and
  365. (StdOutputHandle<>UnusedHandle) then
  366. {$endif not windows}
  367. begin
  368. ChangeRedirOut:=True;
  369. OutRedirDisabled:=False;
  370. end;
  371. {$endif def FPC}
  372. RedirChangedOut:=True;
  373. end;
  374. function ChangeRedirIn(Const Redir : String) : Boolean;
  375. begin
  376. ChangeRedirIn:=False;
  377. If Redir = '' then Exit;
  378. Assign (FIN^, Redir);
  379. Reset(FIN^,1);
  380. RedirErrorIn:=IOResult;
  381. IOStatus:=RedirErrorIn;
  382. If IOStatus <> 0 then Exit;
  383. {$ifndef FPC}
  384. Handles:=Ptr (prefseg, PWord (Ptr (prefseg, $34))^);
  385. OldHandleIn:=Handles^[StdInputHandle];
  386. Handles^[StdInputHandle]:=Handles^[FileRec (FIN^).Handle];
  387. ChangeRedirIn:=True;
  388. InRedirDisabled:=False;
  389. {$else}
  390. {$ifdef windows}
  391. if SetStdHandle(Std_Input_Handle,FileRec(FIN^).Handle) then
  392. {$else not windows}
  393. {$ifdef ver1_0}
  394. dup(StdInputHandle,TempHIn);
  395. dup2(FileRec(FIn^).Handle,StdInputHandle);
  396. {$else}
  397. TempHIn:=fpdup(StdInputHandle);
  398. fpdup2(FileRec(FIn^).Handle,StdInputHandle);
  399. {$endif}
  400. if (TempHIn<>UnusedHandle) and
  401. (StdInputHandle<>UnusedHandle) then
  402. {$endif not windows}
  403. begin
  404. ChangeRedirIn:=True;
  405. InRedirDisabled:=False;
  406. end;
  407. {$endif def FPC}
  408. RedirChangedIn:=True;
  409. end;
  410. function ChangeRedirError(Const Redir : String; AppendToFile : Boolean) : Boolean;
  411. var
  412. PF : ^File;
  413. begin
  414. ChangeRedirError:=False;
  415. If Redir = '' then
  416. Exit;
  417. RedirStdErrToStdOut:=(Redir='stdout');
  418. if RedirStdErrToStdOut then
  419. begin
  420. PF:=FOut;
  421. end
  422. else
  423. begin
  424. Assign (FERR^, Redir);
  425. If AppendToFile and FileExist(Redir) then
  426. Begin
  427. Reset(FERR^,1);
  428. Seek(FERR^,FileSize(FERR^));
  429. End
  430. else
  431. Rewrite (FERR^);
  432. RedirErrorError:=IOResult;
  433. IOStatus:=RedirErrorError;
  434. If IOStatus <> 0 then Exit;
  435. PF:=FErr;
  436. end;
  437. {$ifndef FPC}
  438. Handles:=Ptr (prefseg, PWord (Ptr (prefseg, $34))^);
  439. OldHandleError:=Handles^[StdErrorHandle];
  440. Handles^[StdErrorHandle]:=Handles^[FileRec (PF^).Handle];
  441. ChangeRedirError:=True;
  442. ErrorRedirDisabled:=False;
  443. {$else}
  444. {$ifdef windows}
  445. if SetStdHandle(Std_Error_Handle,FileRec(PF^).Handle) then
  446. {$else not windows}
  447. {$ifdef ver1_0}
  448. dup(StdErrorHandle,TempHError);
  449. dup2(FileRec(PF^).Handle,StdErrorHandle);
  450. {$else}
  451. TempHError:=fpdup(StdErrorHandle);
  452. fpdup2(FileRec(PF^).Handle,StdErrorHandle);
  453. {$endif}
  454. if (TempHError<>UnusedHandle) and
  455. (StdErrorHandle<>UnusedHandle) then
  456. {$endif not windows}
  457. begin
  458. ChangeRedirError:=True;
  459. ErrorRedirDisabled:=False;
  460. end;
  461. {$endif}
  462. RedirChangedError:=True;
  463. end;
  464. {$IfDef MsDos}
  465. {Set HeapEnd Pointer to Current Used Heapsize}
  466. Procedure SmallHeap;assembler;
  467. asm
  468. mov bx,word ptr HeapPtr
  469. shr bx,4
  470. inc bx
  471. add bx,word ptr HeapPtr+2
  472. mov ax,PrefixSeg
  473. sub bx,ax
  474. mov es,ax
  475. mov ah,4ah
  476. int 21h
  477. end;
  478. {Set HeapEnd Pointer to Full Heapsize}
  479. Procedure FullHeap;assembler;
  480. asm
  481. mov bx,word ptr HeapEnd
  482. shr bx,4
  483. inc bx
  484. add bx,word ptr HeapEnd+2
  485. mov ax,PrefixSeg
  486. sub bx,ax
  487. mov es,ax
  488. mov ah,4ah
  489. int 21h
  490. end;
  491. {$EndIf MsDos}
  492. procedure RestoreRedirOut;
  493. begin
  494. If not RedirChangedOut then Exit;
  495. {$ifndef FPC}
  496. Handles^[StdOutputHandle]:=OldHandleOut;
  497. OldHandleOut:=StdOutputHandle;
  498. {$else}
  499. {$ifdef windows}
  500. SetStdHandle(Std_Output_Handle,StdOutputHandle);
  501. {$else not windows}
  502. {$ifdef ver1_0}dup2{$else}fpdup2{$endif}(TempHOut,StdOutputHandle);
  503. {$endif not windows}
  504. {$endif FPC}
  505. Close (FOUT^);
  506. {$ifdef ver1_0}fdclose{$else}fpclose{$endif}(TempHOut);
  507. RedirChangedOut:=false;
  508. end;
  509. {............................................................................}
  510. procedure RestoreRedirIn;
  511. begin
  512. If not RedirChangedIn then Exit;
  513. {$ifndef FPC}
  514. Handles^[StdInputHandle]:=OldHandleIn;
  515. OldHandleIn:=StdInputHandle;
  516. {$else}
  517. {$ifdef windows}
  518. SetStdHandle(Std_Input_Handle,StdInputHandle);
  519. {$else not windows}
  520. {$ifdef ver1_0}dup2{$else}fpdup2{$endif}(TempHIn,StdInputHandle);
  521. {$endif not windows}
  522. {$endif}
  523. Close (FIn^);
  524. {$ifdef ver1_0}fdclose{$else}fpclose{$endif}(TempHIn);
  525. RedirChangedIn:=false;
  526. end;
  527. {............................................................................}
  528. procedure DisableRedirIn;
  529. begin
  530. If not RedirChangedIn then Exit;
  531. If InRedirDisabled then Exit;
  532. {$ifndef FPC}
  533. Handles^[StdInputHandle]:=OldHandleIn;
  534. {$else}
  535. {$ifdef windows}
  536. SetStdHandle(Std_Input_Handle,StdInputHandle);
  537. {$else not windows}
  538. {$ifdef ver1_0}dup2{$else}fpdup2{$endif}(TempHIn,StdInputHandle);
  539. {$endif not windows}
  540. {$endif}
  541. InRedirDisabled:=True;
  542. end;
  543. {............................................................................}
  544. procedure EnableRedirIn;
  545. begin
  546. If not RedirChangedIn then Exit;
  547. If not InRedirDisabled then Exit;
  548. {$ifndef FPC}
  549. Handles:=Ptr (prefseg, PWord (Ptr (prefseg, $34))^);
  550. Handles^[StdInputHandle]:=Handles^[FileRec (FIn^).Handle];
  551. {$else}
  552. {$ifdef windows}
  553. SetStdHandle(Std_Input_Handle,FileRec(FIn^).Handle);
  554. {$else not windows}
  555. {$ifdef ver1_0}dup2{$else}fpdup2{$endif}(FileRec(FIn^).Handle,StdInputHandle);
  556. {$endif not windows}
  557. {$endif}
  558. InRedirDisabled:=False;
  559. end;
  560. {............................................................................}
  561. procedure DisableRedirOut;
  562. begin
  563. If not RedirChangedOut then Exit;
  564. If OutRedirDisabled then Exit;
  565. {$ifndef FPC}
  566. Handles^[StdOutputHandle]:=OldHandleOut;
  567. {$else}
  568. {$ifdef windows}
  569. SetStdHandle(Std_Output_Handle,StdOutputHandle);
  570. {$else not windows}
  571. {$ifdef ver1_0}dup2{$else}fpdup2{$endif}(TempHOut,StdOutputHandle);
  572. {$endif not windows}
  573. {$endif}
  574. OutRedirDisabled:=True;
  575. end;
  576. {............................................................................}
  577. procedure EnableRedirOut;
  578. begin
  579. If not RedirChangedOut then Exit;
  580. If not OutRedirDisabled then Exit;
  581. {$ifndef FPC}
  582. Handles:=Ptr (prefseg, PWord (Ptr (prefseg, $34))^);
  583. Handles^[StdOutputHandle]:=Handles^[FileRec (FOut^).Handle];
  584. {$else}
  585. {$ifdef windows}
  586. SetStdHandle(Std_Output_Handle,FileRec(FOut^).Handle);
  587. {$else not windows}
  588. {$ifdef ver1_0}dup2{$else}fpdup2{$endif}(FileRec(FOut^).Handle,StdOutputHandle);
  589. {$endif not windows}
  590. {$endif}
  591. OutRedirDisabled:=False;
  592. end;
  593. {............................................................................}
  594. procedure RestoreRedirError;
  595. begin
  596. If not RedirChangedError then Exit;
  597. {$ifndef FPC}
  598. Handles^[StdErrorHandle]:=OldHandleError;
  599. OldHandleError:=StdErrorHandle;
  600. {$else}
  601. {$ifdef windows}
  602. SetStdHandle(Std_Error_Handle,StdErrorHandle);
  603. {$else not windows}
  604. {$ifdef ver1_0}dup2{$else}fpdup2{$endif}(TempHError,StdErrorHandle);
  605. {$endif not windows}
  606. {$endif}
  607. { don't close when redirected to STDOUT }
  608. if not RedirStdErrToStdOut then
  609. Close (FERR^);
  610. {$ifdef ver1_0}fdclose{$else}fpclose{$endif}(TempHError);
  611. RedirChangedError:=false;
  612. end;
  613. {............................................................................}
  614. procedure DisableRedirError;
  615. begin
  616. If not RedirChangedError then Exit;
  617. If ErrorRedirDisabled then Exit;
  618. {$ifndef FPC}
  619. Handles^[StdErrorHandle]:=OldHandleError;
  620. {$else}
  621. {$ifdef windows}
  622. SetStdHandle(Std_Error_Handle,StdErrorHandle);
  623. {$else not windows}
  624. {$ifdef ver1_0}dup2{$else}fpdup2{$endif}(TempHError,StdErrorHandle);
  625. {$endif not windows}
  626. {$endif}
  627. ErrorRedirDisabled:=True;
  628. end;
  629. {............................................................................}
  630. procedure EnableRedirError;
  631. begin
  632. If not RedirChangedError then Exit;
  633. If not ErrorRedirDisabled then Exit;
  634. {$ifndef FPC}
  635. Handles:=Ptr (prefseg, PWord (Ptr (prefseg, $34))^);
  636. Handles^[StdErrorHandle]:=Handles^[FileRec (FErr^).Handle];
  637. {$else}
  638. {$ifdef windows}
  639. SetStdHandle(Std_Error_Handle,FileRec(FErr^).Handle);
  640. {$else not windows}
  641. {$ifdef ver1_0}dup2{$else}fpdup2{$endif}(FileRec(FERR^).Handle,StdErrorHandle);
  642. {$endif not windows}
  643. {$endif}
  644. ErrorRedirDisabled:=False;
  645. end;
  646. {............................................................................}
  647. function ExecuteRedir (Const ProgName, ComLine : String; RedirStdIn, RedirStdOut, RedirStdErr: String): boolean;
  648. Begin
  649. RedirErrorOut:=0; RedirErrorIn:=0; RedirErrorError:=0;
  650. ExecuteResult:=0;
  651. IOStatus:=0;
  652. if RedirStdIn<>'' then
  653. ChangeRedirIn(RedirStdIn);
  654. if RedirStdOut<>'' then
  655. ChangeRedirOut(RedirStdOut,false);
  656. if RedirStdErr<>'stderr' then
  657. ChangeRedirError(RedirStdErr,false);
  658. DosExecute(ProgName,ComLine);
  659. RestoreRedirOut;
  660. RestoreRedirIn;
  661. RestoreRedirError;
  662. ExecuteRedir:=(IOStatus=0) and (RedirErrorOut=0) and
  663. (RedirErrorIn=0) and (RedirErrorError=0) and
  664. (ExecuteResult=0);
  665. End;
  666. {............................................................................}
  667. procedure RedirDisableAll;
  668. begin
  669. If RedirChangedIn and not InRedirDisabled then
  670. DisableRedirIn;
  671. If RedirChangedOut and not OutRedirDisabled then
  672. DisableRedirOut;
  673. If RedirChangedError and not ErrorRedirDisabled then
  674. DisableRedirError;
  675. end;
  676. {............................................................................}
  677. procedure RedirEnableAll;
  678. begin
  679. If RedirChangedIn and InRedirDisabled then
  680. EnableRedirIn;
  681. If RedirChangedOut and OutRedirDisabled then
  682. EnableRedirOut;
  683. If RedirChangedError and ErrorRedirDisabled then
  684. EnableRedirError;
  685. end;
  686. procedure InitRedir;
  687. begin
  688. {$ifndef FPC}
  689. PrefSeg:=PrefixSeg;
  690. {$endif FPC}
  691. end;
  692. {$else not implemented}
  693. {*****************************************************************************
  694. Fake
  695. *****************************************************************************}
  696. {$IFDEF SHELL_IMPLEMENTED}
  697. {$I-}
  698. function FileExist(const FileName : PathStr) : Boolean;
  699. var
  700. f : file;
  701. Attr : word;
  702. begin
  703. Assign(f, FileName);
  704. GetFAttr(f, Attr);
  705. FileExist := DosError = 0;
  706. end;
  707. function CompleteDir(const Path: string): string;
  708. begin
  709. { keep c: untouched PM }
  710. if (Path<>'') and (Path[Length(Path)]<>DirSep) and
  711. (Path[Length(Path)]<>':') then
  712. CompleteDir:=Path+DirSep
  713. else
  714. CompleteDir:=Path;
  715. end;
  716. function LocateExeFile(var FileName:string): boolean;
  717. var
  718. dir,s,d,n,e : string;
  719. i : longint;
  720. begin
  721. LocateExeFile:=False;
  722. if FileExist(FileName) then
  723. begin
  724. LocateExeFile:=true;
  725. Exit;
  726. end;
  727. Fsplit(Filename,d,n,e);
  728. if (e='') and FileExist(FileName+exeext) then
  729. begin
  730. FileName:=FileName+exeext;
  731. LocateExeFile:=true;
  732. Exit;
  733. end;
  734. {$ifdef macos}
  735. S:=GetEnv('Commands');
  736. {$else}
  737. S:=GetEnv('PATH');
  738. {$endif}
  739. While Length(S)>0 do
  740. begin
  741. i:=1;
  742. While (i<=Length(S)) and not (S[i] in ListSep) do
  743. Inc(i);
  744. Dir:=CompleteDir(Copy(S,1,i-1));
  745. if i<Length(S) then
  746. Delete(S,1,i)
  747. else
  748. S:='';
  749. if FileExist(Dir+FileName) then
  750. Begin
  751. FileName:=Dir+FileName;
  752. LocateExeFile:=true;
  753. Exit;
  754. End;
  755. end;
  756. end;
  757. function ExecuteRedir (Const ProgName, ComLine : String; RedirStdIn, RedirStdOut, RedirStdErr: String): boolean;
  758. var
  759. CmdLine2: string;
  760. begin
  761. {$ifdef macos}
  762. if Lowercase(RedirStdIn) = 'stdin' then RedirStdIn := 'Dev:StdIn';
  763. if Lowercase(RedirStdOut) = 'stdout' then RedirStdOut := 'Dev:Output';
  764. if Lowercase(RedirStdOut) = 'stderr' then RedirStdOut := 'Dev:Error';
  765. if Lowercase(RedirStdErr) = 'stdout' then RedirStdErr := 'Dev:Output';
  766. if Lowercase(RedirStdErr) = 'stderr' then RedirStdErr := 'Dev:Error';
  767. {$endif macos}
  768. CmdLine2 := ComLine;
  769. if RedirStdIn <> '' then CmdLine2 := CmdLine2 + ' < ' + RedirStdIn;
  770. {$ifndef macos}
  771. if RedirStdOut <> '' then CmdLine2 := CmdLine2 + ' > ' + RedirStdOut;
  772. if RedirStdErr <> '' then
  773. begin
  774. if RedirStdErr = RedirStdOut then
  775. CmdLine2 := CmdLine2 + ' 2>&1'
  776. else
  777. CmdLine2 := CmdLine2 + ' 2> ' + RedirStdErr;
  778. end;
  779. {$else macos}
  780. if RedirStdErr <> RedirStdOut then
  781. if RedirStdOut <> '' then CmdLine2 := CmdLine2 + ' > ' + RedirStdOut;
  782. if RedirStdErr <> '' then
  783. begin
  784. if RedirStdErr = RedirStdOut then
  785. CmdLine2 := CmdLine2 + ' ' + #183 + ' ' + RedirStdErr {#183 is "capital sigma" char in MacRoman}
  786. else
  787. CmdLine2 := CmdLine2 + ' ' + #179 + ' ' + RedirStdErr; {#179 is "greater or equal" char in MacRoman}
  788. end;
  789. {$endif macos}
  790. DosExecute (ProgName, CmdLine2);
  791. ExecuteRedir:=(IOStatus=0) and (ExecuteResult=0);
  792. end;
  793. {$ELSE SHELL_IMPLEMENTED}
  794. function ExecuteRedir (Const ProgName, ComLine : String; RedirStdIn, RedirStdOut, RedirStdErr: String): boolean;
  795. begin
  796. ExecuteRedir:=false;
  797. end;
  798. {$ENDIF SHELL_IMPLEMENTED}
  799. function ChangeRedirOut(Const Redir : String; AppendToFile : Boolean) : Boolean;
  800. begin
  801. ChangeRedirOut:=false;
  802. end;
  803. procedure RestoreRedirOut;
  804. begin
  805. end;
  806. procedure DisableRedirOut;
  807. begin
  808. end;
  809. procedure EnableRedirOut;
  810. begin
  811. end;
  812. function ChangeRedirIn(Const Redir : String) : Boolean;
  813. begin
  814. ChangeRedirIn:=false;
  815. end;
  816. procedure RestoreRedirIn;
  817. begin
  818. end;
  819. procedure DisableRedirIn;
  820. begin
  821. end;
  822. procedure EnableRedirIn;
  823. begin
  824. end;
  825. function ChangeRedirError(Const Redir : String; AppendToFile : Boolean) : Boolean;
  826. begin
  827. ChangeRedirError:=false;
  828. end;
  829. procedure RestoreRedirError;
  830. begin
  831. end;
  832. procedure DisableRedirError;
  833. begin
  834. end;
  835. procedure EnableRedirError;
  836. begin
  837. end;
  838. procedure RedirDisableAll;
  839. begin
  840. end;
  841. procedure RedirEnableAll;
  842. begin
  843. end;
  844. procedure InitRedir;
  845. begin
  846. end;
  847. {$endif not implemented}
  848. {............................................................................}
  849. procedure DosExecute(ProgName, ComLine : String);
  850. {$ifdef windows}
  851. var
  852. StoreInherit : BOOL;
  853. {$endif windows}
  854. Begin
  855. {$IfDef MsDos}
  856. SmallHeap;
  857. {$EndIf MsDos}
  858. {$ifdef usedos}
  859. SwapVectors;
  860. {$endif usedos}
  861. { Must use shell() for linux for the wildcard expansion (PFV) }
  862. {$ifdef UNIX}
  863. IOStatus:=0;
  864. ExecuteResult:=Shell(FixPath(Progname)+' '+Comline);
  865. {$ifdef ver1_0}
  866. { Signal that causes the stop of the shell }
  867. IOStatus:=ExecuteResult and $7F;
  868. { Exit Code seems to be in the second byte,
  869. is this also true for BSD ??
  870. $80 bit is a CoreFlag apparently }
  871. ExecuteResult:=(ExecuteResult and $ff00) shr 8;
  872. {$else}
  873. if ExecuteResult<0 then
  874. begin
  875. IOStatus:=(-ExecuteResult) and $7f;
  876. ExecuteResult:=((-ExecuteResult) and $ff00) shr 8;
  877. end;
  878. {$endif}
  879. {$else}
  880. {$ifdef windows}
  881. StoreInherit:=ExecInheritsHandles;
  882. ExecInheritsHandles:=true;
  883. { Avoid dialog boxes if dll loading fails }
  884. SetErrorMode(SEM_FAILCRITICALERRORS);
  885. {$endif windows}
  886. DosError:=0;
  887. If UseComSpec then
  888. Sysutils.ExecuteProcess (Getenv('COMSPEC'),'/C '+FixPath(progname)+' '+Comline)
  889. else
  890. begin
  891. if LocateExeFile(progname) then
  892. {$ifndef macos}
  893. Sysutils.ExecuteProcess(ProgName,Comline)
  894. {$else}
  895. Dos.Exec(''''+ProgName+'''',Comline) {Quotes needed !}
  896. {$endif}
  897. else
  898. DosError:=2;
  899. end;
  900. {$ifdef windows}
  901. ExecInheritsHandles:=StoreInherit;
  902. SetErrorMode(0);
  903. {$endif windows}
  904. IOStatus:=DosError;
  905. ExecuteResult:=DosExitCode;
  906. {$endif}
  907. {$ifdef usedos}
  908. SwapVectors;
  909. {$endif}
  910. {$ifdef CPU86}
  911. { reset the FPU }
  912. {$asmmode att}
  913. asm
  914. fninit
  915. end;
  916. {$endif CPU86}
  917. {$IfDef MsDos}
  918. Fullheap;
  919. {$EndIf MsDos}
  920. End;
  921. {*****************************************************************************
  922. Initialize
  923. *****************************************************************************}
  924. initialization
  925. New(FIn); New(FOut); New(FErr);
  926. finalization
  927. Dispose(FIn); Dispose(FOut); Dispose(FErr);
  928. End.