process.pp 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923
  1. {
  2. $Id$
  3. This file is part of the Free Component Library (FCL)
  4. Copyright (c) 1999-2000 by the Free Pascal development team
  5. See the file COPYING.FPC, included in this distribution,
  6. for details about the copyright.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  10. **********************************************************************}
  11. {$mode objfpc}
  12. {$h+}
  13. unit process;
  14. interface
  15. Uses Classes,
  16. pipes,
  17. {$ifdef Unix}
  18. {$ifdef ver1_0}
  19. Linux,
  20. {$else}
  21. unix,
  22. {$endif}
  23. {$else}
  24. Windows,
  25. {$endif}
  26. SysUtils;
  27. Type
  28. TProcessOption = (poRunSuspended,poWaitOnExit,
  29. poUsePipes,poStderrToOutPut,
  30. poNoConsole,poNewConsole,
  31. poDefaultErrorMode,poNewProcessGroup,
  32. poDebugProcess,poDebugOnlyThisProcess);
  33. TShowWindowOptions = (swoNone,swoHIDE,swoMaximize,swoMinimize,swoRestore,swoShow,
  34. swoShowDefault,swoShowMaximized,swoShowMinimized,
  35. swoshowMinNOActive,swoShowNA,swoShowNoActivate,swoShowNormal);
  36. TStartupOption = (suoUseShowWindow,suoUseSize,suoUsePosition,
  37. suoUseCountChars,suoUseFillAttribute);
  38. TProcessPriority = (ppHigh,ppIdle,ppNormal,ppRealTime);
  39. TProcessOptions = Set of TPRocessOption;
  40. TstartUpoptions = set of TStartupOption;
  41. {$ifdef unix}
  42. Const
  43. STARTF_USESHOWWINDOW = 1; // Ignored
  44. STARTF_USESIZE = 2;
  45. STARTF_USEPOSITION = 4;
  46. STARTF_USECOUNTCHARS = 8; // Ignored
  47. STARTF_USEFILLATTRIBUTE = $10;
  48. STARTF_RUNFULLSCREEN = $20; // Ignored
  49. STARTF_FORCEONFEEDBACK = $40; // Ignored
  50. STARTF_FORCEOFFFEEDBACK = $80; // Ignored
  51. STARTF_USESTDHANDLES = $100; // Ignored
  52. STARTF_USEHOTKEY = $200; // Ignored
  53. Type
  54. PProcessInformation = ^TProcessInformation;
  55. TProcessInformation = record
  56. hProcess: THandle;
  57. hThread: THandle;
  58. dwProcessId: DWORD;
  59. dwThreadId: DWORD;
  60. end;
  61. PStartupInfo = ^TStartupInfo;
  62. TStartupInfo = Record
  63. cb: DWORD;
  64. lpReserved: Pointer;
  65. lpDesktop: Pointer;
  66. lpTitle: Pointer;
  67. dwX: DWORD;
  68. dwY: DWORD;
  69. dwXSize: DWORD;
  70. dwYSize: DWORD;
  71. dwXCountChars: DWORD;
  72. dwYCountChars: DWORD;
  73. dwFillAttribute: DWORD;
  74. dwFlags: DWORD;
  75. wShowWindow: Word;
  76. cbReserved2: Word;
  77. lpReserved2: PByte;
  78. hStdInput: THandle;
  79. hStdOutput: THandle;
  80. hStdError: THandle;
  81. end;
  82. PSecurityAttributes = ^TSecurityAttributes;
  83. TSecurityAttributes = Record
  84. nlength : Integer;
  85. lpSecurityDescriptor : Pointer;
  86. BinheritHandle : Boolean;
  87. end;
  88. Const piInheritablePipe : TSecurityAttributes = (
  89. nlength:SizeOF(TSecurityAttributes);
  90. lpSecurityDescriptor:Nil;
  91. Binherithandle:True);
  92. piNonInheritablePipe : TSecurityAttributes = (
  93. nlength:SizeOF(TSecurityAttributes);
  94. lpSecurityDescriptor:Nil;
  95. Binherithandle:False);
  96. {$endif}
  97. Type
  98. TProcess = Class (TComponent)
  99. Private
  100. {$ifndef unix}
  101. FAccess : Cardinal;
  102. {$endif}
  103. FApplicationName : string;
  104. FChildErrorStream : TOutPutPipeStream;
  105. FChildInputSTream : TInputPipeStream;
  106. FChildOutPutStream : TOutPutPipeStream;
  107. FConsoleTitle : String;
  108. FProcessOptions : TProcessOptions;
  109. FStartUpOptions : TStartupOptions;
  110. FCommandLine : String;
  111. FCurrentDirectory : String;
  112. FDeskTop : String;
  113. FEnvironment : Tstrings;
  114. FExitCode : Cardinal;
  115. FHandle : THandle;
  116. FShowWindow : TShowWindowOptions;
  117. FInherithandles : LongBool;
  118. FParentErrorStream : TInputPipeStream;
  119. FParentInputSTream : TInputPipeStream;
  120. FParentOutputStream : TOutPutPipeStream;
  121. FRunning : Boolean;
  122. FThreadAttributes : PSecurityAttributes;
  123. FProcessAttributes : PSecurityAttributes;
  124. FProcessInformation : TProcessInformation;
  125. FPRocessPriority : TProcessPriority;
  126. FStartupInfo : TStartupInfo;
  127. Procedure FreeStreams;
  128. Function GetExitStatus : Integer;
  129. Function GetHandle : THandle;
  130. Function GetRunning : Boolean;
  131. Function GetProcessAttributes : TSecurityAttributes;
  132. Function GetThreadAttributes : TSecurityAttributes;
  133. Procedure SetProcessAttributes (Value : TSecurityAttributes);
  134. Procedure SetThreadAttributes (Value : TSecurityAttributes);
  135. Function GetWindowRect : TRect;
  136. Procedure SetWindowRect (Value : TRect);
  137. Procedure SetFillAttribute (Value : Cardinal);
  138. Procedure SetShowWindow (Value : TShowWindowOptions);
  139. Procedure SetWindowColumns (Value : Cardinal);
  140. Procedure SetWindowHeight (Value : Cardinal);
  141. Procedure SetWindowLeft (Value : Cardinal);
  142. Procedure SetWindowRows (Value : Cardinal);
  143. Procedure SetWindowTop (Value : Cardinal);
  144. Procedure SetWindowWidth (Value : Cardinal);
  145. procedure CreateStreams;
  146. function GetCreationFlags: Cardinal;
  147. function GetStartupFlags: Cardinal;
  148. procedure SetApplicationname(const Value: String);
  149. procedure SetPRocessOptions(const Value: TProcessOptions);
  150. procedure SetActive(const Value: Boolean);
  151. procedure SetEnvironment(const Value: TStrings);
  152. {$ifdef unix}
  153. function PeekLinuxExitStatus: Boolean;
  154. {$endif}
  155. Public
  156. Constructor Create (AOwner : TComponent);override;
  157. Destructor Destroy; override;
  158. Procedure Execute; virtual;
  159. Function Resume : Integer; virtual;
  160. Function Suspend : Integer; virtual;
  161. Function Terminate (AExitCode : Integer): Boolean; virtual;
  162. Function WaitOnExit : DWord;
  163. Property WindowRect : Trect Read GetWindowRect Write SetWindowRect;
  164. Property StartupInfo : TStartupInfo Read FStartupInfo;
  165. Property ProcessAttributes : TSecurityAttributes Read GetProcessAttributes Write SetProcessAttributes;
  166. Property ProcessInformation : TProcessInformation Read FPRocessInformation;
  167. Property Handle : THandle Read FProcessInformation.hProcess;
  168. Property ThreadHandle : THandle Read FprocessInformation.hThread;
  169. Property Input : TOutPutPipeStream Read FParentOutPutStream;
  170. Property OutPut : TInputPipeStream Read FParentInputStream;
  171. Property StdErr : TinputPipeStream Read FParentErrorStream;
  172. Property ExitStatus : Integer Read GetExitStatus;
  173. Property InheritHandles : LongBool Read FInheritHandles Write FInheritHandles;
  174. Property ThreadAttributes : TSecurityAttributes Read GetThreadAttributes Write SetThreadAttributes;
  175. Published
  176. Property Active : Boolean Read Getrunning Write SetActive;
  177. Property ApplicationName : String Read FApplicationname Write SetApplicationname;
  178. Property CommandLine : String Read FCommandLine Write FCommandLine;
  179. Property ConsoleTitle : String Read FConsoleTitle Write FConsoleTitle;
  180. Property CurrentDirectory : String Read FCurrentDirectory Write FCurrentDirectory;
  181. Property DeskTop : String Read FDeskTop Write FDeskTop;
  182. Property Environment : TStrings Read FEnvironment Write SetEnvironment;
  183. Property FillAttribute : Cardinal Read FStartupInfo.dwFillAttribute Write SetFillAttribute;
  184. Property Options : TProcessOptions Read FProcessOptions Write SetPRocessOptions;
  185. Property Priority : TProcessPriority Read FProcessPriority Write FProcessPriority;
  186. Property StartUpOptions : TStartUpOptions Read FStartUpOptions Write FStartupOptions;
  187. Property Running : Boolean Read GetRunning;
  188. Property ShowWindow : TShowWindowOptions Read FShowWindow Write SetShowWindow;
  189. Property WindowColumns : Cardinal Read FStartupInfo.dwXCountchars Write SetWindowColumns;
  190. Property WindowHeight : Cardinal Read FStartupInfo.dwYsize Write SetWindowHeight;
  191. Property WindowLeft : Cardinal Read FStartupInfo.dwx Write SetWindowLeft;
  192. Property WindowRows : Cardinal Read FStartupInfo.dwYcountChars Write SetWindowRows;
  193. Property WindowTop : Cardinal Read FStartupInfo.dwy Write SetWindowTop ;
  194. Property WindowWidth : Cardinal Read FStartupInfo.dwXsize Write SetWindowWidth;
  195. end;
  196. {$ifdef unix}
  197. Const
  198. PriorityConstants : Array [TProcessPriority] of Integer =
  199. (20,20,0,-20);
  200. Const
  201. GeometryOption : String = '-geometry';
  202. TitleOption : String ='-title';
  203. {$else}
  204. Const
  205. PriorityConstants : Array [TProcessPriority] of Cardinal =
  206. (HIGH_PRIORITY_CLASS,IDLE_PRIORITY_CLASS,
  207. NORMAL_PRIORITY_CLASS,REALTIME_PRIORITY_CLASS);
  208. {$endif}
  209. implementation
  210. Constructor TProcess.Create (AOwner : TComponent);
  211. begin
  212. Inherited;
  213. {$ifndef unix}
  214. FAccess:=PROCESS_ALL_ACCESS;
  215. {$endif}
  216. FProcessPriority:=ppNormal;
  217. FShowWindow:=swoNone;
  218. FStartupInfo.cb:=SizeOf(TStartupInfo);
  219. FInheritHandles:=True;
  220. FEnvironment:=TStringList.Create;
  221. end;
  222. Destructor TProcess.Destroy;
  223. begin
  224. If assigned (FProcessAttributes) then Dispose (FPRocessAttributes);
  225. If assigned (FThreadAttributes) then Dispose (FThreadAttributes);
  226. FEnvironment.Free;
  227. FreeStreams;
  228. Inherited;
  229. end;
  230. Procedure TProcess.FreeStreams;
  231. var FreedStreams: TList;
  232. procedure FreeStream(var AnObject: TObject);
  233. begin
  234. if FreedStreams.IndexOf(AnObject)<0 then
  235. begin
  236. FreedStreams.Add(AnObject);
  237. AnObject.Free;
  238. end;
  239. AnObject:=nil;
  240. end;
  241. begin
  242. FreedStreams:=TList.Create;
  243. try
  244. FreeStream(FParentErrorStream);
  245. FreeStream(FParentInputStream);
  246. FreeStream(FParentOutputStream);
  247. FreeStream(FChildErrorStream);
  248. FreeStream(FChildInputStream);
  249. FreeStream(FChildOutputStream);
  250. finally
  251. FreedStreams.Free;
  252. end;
  253. end;
  254. Function TProcess.GetExitStatus : Integer;
  255. begin
  256. If FRunning then
  257. {$ifdef unix}
  258. PeekLinuxExitStatus;
  259. {$else}
  260. GetExitCodeProcess(Handle,FExitCode);
  261. {$endif}
  262. Result:=FExitCode;
  263. end;
  264. Function TProcess.GetHandle : THandle;
  265. begin
  266. {$ifndef unix}
  267. If FHandle=0 Then
  268. FHandle:=OpenProcess (FAccess,True,FProcessInformation.dwProcessId);
  269. {$endif}
  270. Result:=FHandle
  271. end;
  272. Function TProcess.GetProcessAttributes : TSecurityAttributes;
  273. Var P : PSecurityAttributes;
  274. begin
  275. IF not Assigned(FProcessAttributes) then
  276. begin
  277. // Provide empty dummy value;
  278. New(p);
  279. Fillchar(p^,Sizeof(TSecurityAttributes),0);
  280. Result:=p^;
  281. end
  282. else
  283. REsult:=FProcessAttributes^;
  284. end;
  285. {$ifdef unix}
  286. Function TProcess.PeekLinuxExitStatus : Boolean;
  287. begin
  288. Result:=WaitPID(Handle,@FExitCode,WNOHANG)=Handle;
  289. If Result then
  290. FExitCode:=wexitstatus(FExitCode)
  291. else
  292. FexitCode:=0;
  293. end;
  294. {$endif}
  295. Function TProcess.GetRunning : Boolean;
  296. begin
  297. IF FRunning then
  298. begin
  299. {$ifdef unix}
  300. FRunning:=Not PeekLinuxExitStatus;
  301. {$else}
  302. Frunning:=GetExitStatus=Still_Active;
  303. {$endif}
  304. end;
  305. Result:=FRunning;
  306. end;
  307. Function TProcess.GetThreadAttributes : TSecurityAttributes;
  308. Var P : PSecurityAttributes;
  309. begin
  310. IF not Assigned(FThreadAttributes) then
  311. begin
  312. // Provide empty dummy value;
  313. New(p);
  314. Fillchar(p^,Sizeof(TSecurityAttributes),0);
  315. Result:=p^;
  316. end
  317. else
  318. Result:=FThreadAttributes^;
  319. end;
  320. Procedure TProcess.SetProcessAttributes (Value : TSecurityAttributes);
  321. begin
  322. If not Assigned (FProcessAttributes) then
  323. New(FProcessAttributes);
  324. FPRocessAttributes^:=VAlue;
  325. end;
  326. Procedure TProcess.SetThreadAttributes (Value : TSecurityAttributes);
  327. begin
  328. If not Assigned (FThreadAttributes) then
  329. New(FThreadAttributes);
  330. FThreadAttributes^:=VAlue;
  331. end;
  332. Procedure TProcess.CreateStreams;
  333. begin
  334. FreeStreams;
  335. CreatePipeStreams (FChildInputSTream,FParentOutPutStream); //,@piInheritablePipe,1024);
  336. CreatePipeStreams (FParentInputStream,FChildOutPutStream); //,@piInheritablePipe,1024);
  337. if Not (poStdErrToOutPut in FProcessOptions) then
  338. CreatePipeStreams (FParentErrorStream,FChildErrorStream) //,@piInheritablePipe,1024)
  339. else
  340. begin
  341. FChildErrorStream:=FChildOutPutStream;
  342. FParentErrorStream:=FParentInputStream;
  343. end;
  344. FStartupInfo.dwFlags:=FStartupInfo.dwFlags or Startf_UseStdHandles;
  345. FStartupInfo.hStdInput:=FChildInputStream.Handle;
  346. FStartupInfo.hStdOutput:=FChildOutPutStream.Handle;
  347. FStartupInfo.hStdError:=FChildErrorStream.Handle;
  348. end;
  349. Function TProcess.GetCreationFlags : Cardinal;
  350. begin
  351. Result:=0;
  352. {$ifndef unix}
  353. if poNoConsole in FProcessOptions then
  354. Result:=Result or Detached_Process;
  355. if poNewConsole in FProcessOptions then
  356. Result:=Result or Create_new_console;
  357. if poNewProcessGroup in FProcessOptions then
  358. Result:=Result or CREATE_NEW_PROCESS_GROUP;
  359. If poRunSuspended in FProcessOptions Then
  360. Result:=Result or Create_Suspended;
  361. if poDebugProcess in FProcessOptions Then
  362. Result:=Result or DEBUG_PROCESS;
  363. if poDebugOnlyThisProcess in FProcessOptions Then
  364. Result:=Result or DEBUG_ONLY_THIS_PROCESS;
  365. if poDefaultErrorMode in FProcessOptions Then
  366. Result:=Result or CREATE_DEFAULT_ERROR_MODE;
  367. result:=result or PriorityConstants[FProcessPriority];
  368. {$endif}
  369. end;
  370. Function TProcess.GetStartupFlags : Cardinal;
  371. begin
  372. Result:=0;
  373. if poUsePipes in FProcessOptions then
  374. Result:=Result or Startf_UseStdHandles;
  375. if suoUseShowWindow in FStartupOptions then
  376. Result:=Result or startf_USESHOWWINDOW;
  377. if suoUSESIZE in FStartupOptions then
  378. Result:=Result or startf_usesize;
  379. if suoUsePosition in FStartupOptions then
  380. Result:=Result or startf_USEPOSITION;
  381. if suoUSECOUNTCHARS in FStartupoptions then
  382. Result:=Result or startf_usecountchars;
  383. if suoUsefIllAttribute in FStartupOptions then
  384. Result:=Result or startf_USEFILLATTRIBUTE;
  385. end;
  386. Type
  387. {$ifndef unix}
  388. PPChar = ^PChar;
  389. {$endif}
  390. TPCharArray = Array[Word] of pchar;
  391. PPCharArray = ^TPcharArray;
  392. Function StringsToPCharList(List : TStrings) : PPChar;
  393. Var
  394. I : Integer;
  395. S : String;
  396. begin
  397. I:=(List.Count)+1;
  398. GetMem(Result,I*sizeOf(PChar));
  399. PPCharArray(Result)^[List.Count]:=Nil;
  400. For I:=0 to List.Count-1 do
  401. begin
  402. S:=List[i];
  403. Result[i]:=StrNew(PChar(S));
  404. end;
  405. end;
  406. Procedure FreePCharList(List : PPChar);
  407. Var
  408. I : integer;
  409. begin
  410. I:=0;
  411. While List[i]<>Nil do
  412. begin
  413. StrDispose(List[i]);
  414. Inc(I);
  415. end;
  416. FreeMem(List);
  417. end;
  418. {$ifdef unix}
  419. Procedure CommandToList(S : String; List : TStrings);
  420. Function GetNextWord : String;
  421. Const
  422. WhiteSpace = [' ',#8,#10];
  423. Literals = ['"',''''];
  424. Var
  425. Wstart,wend : Integer;
  426. InLiteral : Boolean;
  427. LastLiteral : char;
  428. begin
  429. WStart:=1;
  430. While (WStart<=Length(S)) and (S[WStart] in WhiteSpace) do
  431. Inc(WStart);
  432. WEnd:=WStart;
  433. InLiteral:=False;
  434. LastLiteral:=#0;
  435. While (Wend<=Length(S)) and (Not (S[Wend] in WhiteSpace) or InLiteral) do
  436. begin
  437. if S[Wend] in Literals then
  438. If InLiteral then
  439. InLiteral:=Not (S[Wend]=LastLiteral)
  440. else
  441. begin
  442. InLiteral:=True;
  443. LastLiteral:=S[Wend];
  444. end;
  445. inc(wend);
  446. end;
  447. Result:=Copy(S,WStart,WEnd-WStart);
  448. Result:=StringReplace(Result,'"','',[rfReplaceAll]);
  449. Result:=StringReplace(Result,'''','',[rfReplaceAll]);
  450. While (WEnd<=Length(S)) and (S[Wend] in WhiteSpace) do
  451. inc(Wend);
  452. Delete(S,1,WEnd-1);
  453. end;
  454. Var
  455. W : String;
  456. begin
  457. While Length(S)>0 do
  458. begin
  459. W:=GetNextWord;
  460. If (W<>'') then
  461. List.Add(W);
  462. end;
  463. end;
  464. Function MakeCommand(Var AppName,CommandLine : String;
  465. StartupOptions : TStartUpOptions;
  466. ProcessOptions : TProcessOptions;
  467. StartupInfo : TStartupInfo) : PPchar;
  468. Const
  469. SNoCommandLine = 'Cannot execute empty command-line';
  470. Var
  471. S : TStringList;
  472. G : String;
  473. begin
  474. if (AppName='') then
  475. begin
  476. If (CommandLine='') then
  477. Raise Exception.Create(SNoCommandline)
  478. end
  479. else
  480. begin
  481. If (CommandLine='') then
  482. CommandLine:=AppName;
  483. end;
  484. S:=TStringList.Create;
  485. try
  486. CommandToList(CommandLine,S);
  487. if poNewConsole in ProcessOptions then
  488. begin
  489. S.Insert(0,'-e');
  490. If (AppName<>'') then
  491. begin
  492. S.Insert(0,AppName);
  493. S.Insert(0,'-title');
  494. end;
  495. if suoUseCountChars in StartupOptions then
  496. With StartupInfo do
  497. begin
  498. S.Insert(0,Format('%dx%d',[dwXCountChars,dwYCountChars]));
  499. S.Insert(0,'-geometry');
  500. end;
  501. S.Insert(0,'xterm');
  502. end;
  503. if (AppName<>'') then
  504. begin
  505. S.Add(TitleOption);
  506. S.Add(AppName);
  507. end;
  508. With StartupInfo do
  509. begin
  510. G:='';
  511. if (suoUseSize in StartupOptions) then
  512. g:=format('%dx%d',[dwXSize,dwYsize]);
  513. if (suoUsePosition in StartupOptions) then
  514. g:=g+Format('+%d+%d',[dwX,dwY]);
  515. if G<>'' then
  516. begin
  517. S.Add(GeometryOption);
  518. S.Add(g);
  519. end;
  520. end;
  521. Result:=StringsToPcharList(S);
  522. AppName:=S[0];
  523. Finally
  524. S.free;
  525. end;
  526. end;
  527. Function CreateProcess (PName,PCommandLine,PDir : String;
  528. FEnv : PPChar;
  529. StartupOptions : TStartupOptions;
  530. ProcessOptions : TProcessOptions;
  531. const FStartupInfo : TStartupInfo;
  532. Var ProcessInfo : TProcessInformation) : boolean;
  533. Var
  534. PID : Longint;
  535. Argv : PPChar;
  536. fd : Integer;
  537. begin
  538. Result:=True;
  539. Argv:=MakeCommand(Pname,PCommandLine,StartupOptions,ProcessOptions,FStartupInfo);
  540. if (pos('/',PName)<>1) then
  541. PName:=FileSearch(Pname,GetEnv('PATH'));
  542. Pid:=fork;
  543. if Pid=0 then
  544. begin
  545. { We're in the child }
  546. if (PDir<>'') then
  547. ChDir(PDir);
  548. if PoUsePipes in ProcessOptions then
  549. begin
  550. dup2(FStartupInfo.hStdInput,0);
  551. dup2(FStartupInfo.hStdOutput,1);
  552. dup2(FStartupInfo.hStdError,2);
  553. end
  554. else if poNoConsole in ProcessOptions then
  555. begin
  556. fd:=FileOpen('/dev/null',fmOpenReadWrite);
  557. dup2(fd,0);
  558. dup2(fd,1);
  559. dup2(fd,2);
  560. end;
  561. if (poRunSuspended in ProcessOptions) then
  562. sigraise(SIGSTOP);
  563. if FEnv<>Nil then
  564. Execve(PChar(PName),Argv,Fenv)
  565. else
  566. Execv(Pchar(PName),argv);
  567. Halt(127);
  568. end
  569. else
  570. begin
  571. FreePcharList(Argv);
  572. // Copy process information.
  573. ProcessInfo.hProcess:=PID;
  574. ProcessInfo.hThread:=PID;
  575. ProcessInfo.dwProcessId:=PID;
  576. ProcessInfo.dwThreadId:=PID;
  577. end;
  578. end;
  579. {$endif}
  580. {$ifdef unix}
  581. Function GetLastError : Integer;
  582. begin
  583. Result:=-1;
  584. end;
  585. {$endif}
  586. Procedure TProcess.Execute;
  587. Var
  588. {$ifndef unix}
  589. PName,PDir,PCommandLine : PChar;
  590. {$endif}
  591. FEnv : PPChar;
  592. FCreationFlags : Cardinal;
  593. begin
  594. If poUsePipes in FProcessOptions then
  595. CreateStreams;
  596. FCreationFlags:=GetCreationFlags;
  597. FStartupInfo.dwFlags:=GetStartupFlags;
  598. {$ifndef unix}
  599. PName:=Nil;
  600. PCommandLine:=Nil;
  601. PDir:=Nil;
  602. If FApplicationName<>'' then
  603. PName:=Pchar(FApplicationName);
  604. If FCommandLine<>'' then
  605. PCommandLine:=Pchar(FCommandLine);
  606. If FCurrentDirectory<>'' then
  607. PDir:=Pchar(FCurrentDirectory);
  608. {$endif}
  609. if FEnvironment.Count<>0 then
  610. FEnv:=StringsToPcharList(FEnvironment)
  611. else
  612. FEnv:=Nil;
  613. FInheritHandles:=True;
  614. {$ifdef unix}
  615. if Not CreateProcess (FApplicationName,FCommandLine,FCurrentDirectory,FEnv,
  616. FStartupOptions,FProcessOptions,FStartupInfo,
  617. fProcessInformation) then
  618. {$else}
  619. If Not CreateProcess (PName,PCommandLine,FProcessAttributes,FThreadAttributes,
  620. FInheritHandles,FCreationFlags,FEnv,PDir,FStartupInfo,
  621. fProcessInformation) then
  622. {$endif}
  623. Raise Exception.CreateFmt('Failed to execute %s : %d',[FCommandLine,GetLastError]);
  624. if POUsePipes in FProcessOptions then
  625. begin
  626. FileClose(FStartupInfo.hStdInput);
  627. FileClose(FStartupInfo.hStdOutput);
  628. FileClose(FStartupInfo.hStdError);
  629. end;
  630. {$ifdef unix}
  631. Fhandle:=fprocessinformation.hProcess;
  632. {$endif}
  633. FRunning:=True;
  634. If FEnv<>Nil then
  635. FreePCharList(FEnv);
  636. if not (csDesigning in ComponentState) and // This would hang the IDE !
  637. (poWaitOnExit in FProcessOptions) and
  638. not (poRunSuspended in FProcessOptions) then
  639. WaitOnExit;
  640. end;
  641. Function TProcess.WaitOnExit : Dword;
  642. begin
  643. {$ifdef unix}
  644. Result:=WaitPid(Handle,@FExitCode,0);
  645. If Result=Handle then
  646. FExitCode:=WexitStatus(FExitCode);
  647. {$else}
  648. Result:=WaitForSingleObject (FprocessInformation.hProcess,Infinite);
  649. If Result<>Wait_Failed then
  650. GetExitStatus;
  651. {$endif}
  652. FRunning:=False;
  653. end;
  654. Function TProcess.Suspend : Longint;
  655. begin
  656. {$ifdef unix}
  657. If kill(Handle,SIGSTOP)<>0 then
  658. Result:=-1
  659. else
  660. Result:=1;
  661. {$else}
  662. Result:=SuspendThread(ThreadHandle);
  663. {$endif}
  664. end;
  665. Function TProcess.Resume : LongInt;
  666. begin
  667. {$ifdef unix}
  668. If kill(Handle,SIGCONT)<>0 then
  669. Result:=-1
  670. else
  671. Result:=0;
  672. {$else}
  673. Result:=ResumeThread(ThreadHandle);
  674. {$endif}
  675. end;
  676. Function TProcess.Terminate(AExitCode : Integer) : Boolean;
  677. begin
  678. Result:=False;
  679. {$ifdef unix}
  680. Result:=kill(Handle,SIGTERM)=0;
  681. If Result then
  682. begin
  683. If Running then
  684. Result:=Kill(Handle,SIGKILL)=0;
  685. end;
  686. GetExitStatus;
  687. {$else}
  688. If ExitStatus=Still_active then
  689. Result:=TerminateProcess(Handle,AexitCode);
  690. {$endif}
  691. end;
  692. Procedure TProcess.SetFillAttribute (Value : Cardinal);
  693. begin
  694. FStartupInfo.dwFlags:=FStartupInfo.dwFlags or Startf_UseFillAttribute;
  695. FStartupInfo.dwFillAttribute:=Value;
  696. end;
  697. Procedure TProcess.SetShowWindow (Value : TShowWindowOptions);
  698. {$ifndef unix}
  699. Const
  700. SWC : Array [TShowWindowOptions] of Cardinal =
  701. (0,SW_HIDE,SW_Maximize,SW_Minimize,SW_Restore,SW_Show,
  702. SW_ShowDefault,SW_ShowMaximized,SW_ShowMinimized,
  703. SW_showMinNOActive,SW_ShowNA,SW_ShowNoActivate,SW_ShowNormal);
  704. {$endif}
  705. begin
  706. FShowWindow:=Value;
  707. if Value<>swoNone then
  708. FStartupInfo.dwFlags:=FStartupInfo.dwFlags or Startf_UseShowWindow
  709. else
  710. FStartupInfo.dwFlags:=FStartupInfo.dwFlags and not Startf_UseShowWindow;
  711. {$ifndef unix}
  712. FStartupInfo.wShowWindow:=SWC[Value];
  713. {$endif}
  714. end;
  715. Procedure TProcess.SetWindowColumns (Value : Cardinal);
  716. begin
  717. if Value<>0 then
  718. Include(FStartUpOptions,suoUseCountChars);
  719. FStartupInfo.dwXCountChars:=Value;
  720. end;
  721. Procedure TProcess.SetWindowHeight (Value : Cardinal);
  722. begin
  723. if Value<>0 then
  724. include(FStartUpOptions,suoUsePosition);
  725. FStartupInfo.dwYsize:=Value;
  726. end;
  727. Procedure TProcess.SetWindowLeft (Value : Cardinal);
  728. begin
  729. if Value<>0 then
  730. Include(FStartUpOptions,suoUseSize);
  731. FStartupInfo.dwx:=Value;
  732. end;
  733. Procedure TProcess.SetWindowTop (Value : Cardinal);
  734. begin
  735. if Value<>0 then
  736. Include(FStartUpOptions,suoUsePosition);
  737. FStartupInfo.dwy:=Value;
  738. end;
  739. Procedure TProcess.SetWindowWidth (Value : Cardinal);
  740. begin
  741. If (Value<>0) then
  742. Include(FStartUpOptions,suoUseSize);
  743. FStartupInfo.dwxsize:=Value;
  744. end;
  745. Function TProcess.GetWindowRect : TRect;
  746. begin
  747. With Result do
  748. With FStartupInfo do
  749. begin
  750. Left:=dwx;
  751. Right:=dwx+dwxSize;
  752. Top:=dwy;
  753. Bottom:=dwy+dwysize;
  754. end;
  755. end;
  756. Procedure TProcess.SetWindowRect (Value : Trect);
  757. begin
  758. Include(FStartupOptions,suouseSize);
  759. Include(FStartupOptions,suoUsePosition);
  760. With Value do
  761. With FStartupInfo do
  762. begin
  763. dwx:=Left;
  764. dwxSize:=Right-Left;
  765. dwy:=Top;
  766. dwySize:=Bottom-top;
  767. end;
  768. end;
  769. Procedure TProcess.SetWindowRows (Value : Cardinal);
  770. begin
  771. FStartupInfo.dwFlags:=FStartupInfo.dwFlags or Startf_UseCountChars;
  772. FStartupInfo.dwYCountChars:=Value;
  773. end;
  774. procedure TProcess.SetApplicationname(const Value: String);
  775. begin
  776. FApplicationname := Value;
  777. If (csdesigning in ComponentState) and
  778. (FCommandLine='') then
  779. FCommandLine:=Value;
  780. end;
  781. procedure TProcess.SetProcessOptions(const Value: TProcessOptions);
  782. begin
  783. FProcessOptions := Value;
  784. If poNewConsole in FPRocessOptions then
  785. Exclude(FProcessoptions,poNoConsole);
  786. if poRunSuspended in FProcessOptions then
  787. Exclude(FPRocessoptions,poWaitOnExit);
  788. end;
  789. procedure TProcess.SetActive(const Value: Boolean);
  790. begin
  791. if (Value<>GetRunning) then
  792. If Value then
  793. Execute
  794. else
  795. Terminate(0);
  796. end;
  797. procedure TProcess.SetEnvironment(const Value: TStrings);
  798. begin
  799. FEnvironment.Assign(Value);
  800. end;
  801. end.
  802. {
  803. $Log$
  804. Revision 1.13 2002-09-07 15:15:25 peter
  805. * old logs removed and tabs fixed
  806. }