redir.pp 23 KB

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