redir.pp 24 KB

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