process.pp 24 KB

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