redir.pp 25 KB

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