redir.pp 26 KB

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