redir.pp 24 KB

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