process.inc 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427
  1. {
  2. Unix Process .inc.
  3. }
  4. uses
  5. {$ifdef ver1_0}
  6. Linux;
  7. {$else}
  8. Unix,
  9. Baseunix;
  10. {$endif}
  11. Const
  12. PriorityConstants : Array [TProcessPriority] of Integer =
  13. (20,20,0,-20);
  14. Const
  15. GeometryOption : String = '-geometry';
  16. TitleOption : String ='-title';
  17. {$ifdef ver1_0}
  18. // Compatibility functions.
  19. // Change to function, check results..
  20. procedure fpDup2(H1,H2 : Longint);
  21. begin
  22. dup2(H1,H2)
  23. end;
  24. function fpFork : Longint;
  25. begin
  26. end;
  27. function fpGetEnv(S : String) : PChar;
  28. begin
  29. Result:=GetEnv(S : String);
  30. end;
  31. Procedure fpExecve(S : PChar; A,E : PPChar);
  32. begin
  33. ExecVE(S,A,E);
  34. end;
  35. Procedure fpExecv(S : PChar; A : PPChar);
  36. begin
  37. ExecVE(S,A);
  38. end;
  39. Function fpWaitPID(H: Longint; P : Pointer; Opts : Longint) : Integer;
  40. begin
  41. Result:=WaitPID(Handle,@FExitCode,Opts);
  42. end;
  43. Function fpKill(PID,SIG : Longint) : Longint;
  44. begin
  45. Result:=kill(Handle,SIGTERM)=0;
  46. end;
  47. {$endif}
  48. procedure TProcess.CloseProcessHandles;
  49. begin
  50. // Do nothing. Win32 call.
  51. end;
  52. Function TProcess.PeekExitStatus : Boolean;
  53. begin
  54. Result:=fpWaitPid(Handle,@FExitCode,WNOHANG)=Handle;
  55. If Result then
  56. FExitCode:=wexitstatus(FExitCode)
  57. else
  58. FexitCode:=0;
  59. end;
  60. Type
  61. TPCharArray = Array[Word] of pchar;
  62. PPCharArray = ^TPcharArray;
  63. Function StringsToPCharList(List : TStrings) : PPChar;
  64. Var
  65. I : Integer;
  66. S : String;
  67. begin
  68. I:=(List.Count)+1;
  69. GetMem(Result,I*sizeOf(PChar));
  70. PPCharArray(Result)^[List.Count]:=Nil;
  71. For I:=0 to List.Count-1 do
  72. begin
  73. S:=List[i];
  74. Result[i]:=StrNew(PChar(S));
  75. end;
  76. end;
  77. Procedure FreePCharList(List : PPChar);
  78. Var
  79. I : integer;
  80. begin
  81. I:=0;
  82. While List[i]<>Nil do
  83. begin
  84. StrDispose(List[i]);
  85. Inc(I);
  86. end;
  87. FreeMem(List);
  88. end;
  89. Procedure CommandToList(S : String; List : TStrings);
  90. Function GetNextWord : String;
  91. Const
  92. WhiteSpace = [' ',#8,#10];
  93. Literals = ['"',''''];
  94. Var
  95. Wstart,wend : Integer;
  96. InLiteral : Boolean;
  97. LastLiteral : char;
  98. begin
  99. WStart:=1;
  100. While (WStart<=Length(S)) and (S[WStart] in WhiteSpace) do
  101. Inc(WStart);
  102. WEnd:=WStart;
  103. InLiteral:=False;
  104. LastLiteral:=#0;
  105. While (Wend<=Length(S)) and (Not (S[Wend] in WhiteSpace) or InLiteral) do
  106. begin
  107. if S[Wend] in Literals then
  108. If InLiteral then
  109. InLiteral:=Not (S[Wend]=LastLiteral)
  110. else
  111. begin
  112. InLiteral:=True;
  113. LastLiteral:=S[Wend];
  114. end;
  115. inc(wend);
  116. end;
  117. Result:=Copy(S,WStart,WEnd-WStart);
  118. Result:=StringReplace(Result,'"','',[rfReplaceAll]);
  119. Result:=StringReplace(Result,'''','',[rfReplaceAll]);
  120. While (WEnd<=Length(S)) and (S[Wend] in WhiteSpace) do
  121. inc(Wend);
  122. Delete(S,1,WEnd-1);
  123. end;
  124. Var
  125. W : String;
  126. begin
  127. While Length(S)>0 do
  128. begin
  129. W:=GetNextWord;
  130. If (W<>'') then
  131. List.Add(W);
  132. end;
  133. end;
  134. Function MakeCommand(P : TProcess) : PPchar;
  135. Const
  136. SNoCommandLine = 'Cannot execute empty command-line';
  137. Var
  138. Cmd : String;
  139. S : TStringList;
  140. G : String;
  141. begin
  142. if (P.ApplicationName='') then
  143. begin
  144. If (P.CommandLine='') then
  145. Raise Exception.Create(SNoCommandline);
  146. Cmd:=P.CommandLine;
  147. end
  148. else
  149. begin
  150. If (P.CommandLine='') then
  151. Cmd:=P.ApplicationName
  152. else
  153. Cmd:=P.CommandLine;
  154. end;
  155. S:=TStringList.Create;
  156. try
  157. CommandToList(Cmd,S);
  158. if poNewConsole in P.Options then
  159. begin
  160. S.Insert(0,'-e');
  161. If (P.ApplicationName<>'') then
  162. begin
  163. S.Insert(0,P.ApplicationName);
  164. S.Insert(0,'-title');
  165. end;
  166. if suoUseCountChars in P.StartupOptions then
  167. begin
  168. S.Insert(0,Format('%dx%d',[P.dwXCountChars,P.dwYCountChars]));
  169. S.Insert(0,'-geometry');
  170. end;
  171. S.Insert(0,'xterm');
  172. end;
  173. if (P.ApplicationName<>'') then
  174. begin
  175. S.Add(TitleOption);
  176. S.Add(P.ApplicationName);
  177. end;
  178. G:='';
  179. if (suoUseSize in P.StartupOptions) then
  180. g:=format('%dx%d',[P.dwXSize,P.dwYsize]);
  181. if (suoUsePosition in P.StartupOptions) then
  182. g:=g+Format('+%d+%d',[P.dwX,P.dwY]);
  183. if G<>'' then
  184. begin
  185. S.Add(GeometryOption);
  186. S.Add(g);
  187. end;
  188. Result:=StringsToPcharList(S);
  189. Finally
  190. S.free;
  191. end;
  192. end;
  193. Function GetLastError : Integer;
  194. begin
  195. Result:=-1;
  196. end;
  197. Type
  198. TPipeEnd = (peRead,peWrite);
  199. TPipePair = Array[TPipeEnd] of Integer;
  200. Procedure CreatePipes(Var HI,HO,HE : TPipePair; CE : Boolean);
  201. Procedure CreatePair(Var P : TPipePair);
  202. begin
  203. If not CreatePipeHandles(P[peRead],P[peWrite]) then
  204. Raise Exception.Create('Failed to create pipes');
  205. end;
  206. Procedure ClosePair(Var P : TPipePair);
  207. begin
  208. if (P[peRead]<>-1) then
  209. FileClose(P[peRead]);
  210. if (P[peWrite]<>-1) then
  211. FileClose(P[peWrite]);
  212. end;
  213. begin
  214. HO[peRead]:=-1;HO[peWrite]:=-1;
  215. HI[peRead]:=-1;HI[peWrite]:=-1;
  216. HE[peRead]:=-1;HE[peWrite]:=-1;
  217. Try
  218. CreatePair(HO);
  219. CreatePair(HI);
  220. If CE then
  221. CreatePair(HE);
  222. except
  223. ClosePair(HO);
  224. ClosePair(HI);
  225. If CE then
  226. ClosePair(HE);
  227. Raise;
  228. end;
  229. end;
  230. Procedure TProcess.Execute;
  231. Var
  232. HI,HO,HE : TPipePair;
  233. PID : Longint;
  234. FEnv : PPChar;
  235. Argv : PPChar;
  236. fd : Integer;
  237. PName : String;
  238. begin
  239. If (poUsePipes in FProcessOptions) then
  240. CreatePipes(HI,HO,HE,Not (poStdErrToOutPut in FProcessOptions));
  241. Try
  242. if FEnvironment.Count<>0 then
  243. FEnv:=StringsToPcharList(FEnvironment)
  244. else
  245. FEnv:=Nil;
  246. Try
  247. Argv:=MakeCommand(Self);
  248. Try
  249. If (Argv<>Nil) and (ArgV[0]<>Nil) then
  250. PName:=StrPas(Argv[0])
  251. else
  252. begin
  253. // This should never happen, actually.
  254. PName:=ApplicationName;
  255. If (PName='') then
  256. PName:=CommandLine;
  257. end;
  258. if (pos('/',PName)<>1) then
  259. PName:=FileSearch(Pname,fpgetenv('PATH'));
  260. Pid:=fpfork;
  261. if Pid<0 then
  262. Raise Exception.Create('Failed to Fork process');
  263. if (PID>0) then
  264. begin
  265. // Parent process. Copy process information.
  266. FProcessHandle:=PID;
  267. FThreadHandle:=PID;
  268. FProcessId:=PID;
  269. //FThreadId:=PID;
  270. end
  271. else
  272. begin
  273. { We're in the child }
  274. if (FCurrentDirectory<>'') then
  275. ChDir(FCurrentDirectory);
  276. if PoUsePipes in Options then
  277. begin
  278. fpdup2(HI[peRead],0);
  279. fpdup2(HO[peWrite],1);
  280. if (poStdErrToOutPut in Options) then
  281. fpdup2(HO[peWrite],2)
  282. else
  283. fpdup2(HE[peWrite],2);
  284. end
  285. else if poNoConsole in Options then
  286. begin
  287. fd:=FileOpen('/dev/null',fmOpenReadWrite);
  288. fpdup2(fd,0);
  289. fpdup2(fd,1);
  290. fpdup2(fd,2);
  291. end;
  292. if (poRunSuspended in Options) then
  293. sigraise(SIGSTOP);
  294. if FEnv<>Nil then
  295. fpexecve(PName,Argv,Fenv)
  296. else
  297. fpexecv(PName,argv);
  298. Halt(127);
  299. end
  300. Finally
  301. FreePcharList(Argv);
  302. end;
  303. Finally
  304. If (FEnv<>Nil) then
  305. FreePCharList(FEnv);
  306. end;
  307. Finally
  308. if POUsePipes in FProcessOptions then
  309. begin
  310. FileClose(HO[peWrite]);
  311. FileClose(HI[peRead]);
  312. if Not (poStdErrToOutPut in FProcessOptions) then
  313. FileClose(HE[peWrite]);
  314. CreateStreams(HI[peWrite],HO[peRead],HE[peRead]);
  315. end;
  316. end;
  317. FRunning:=True;
  318. if not (csDesigning in ComponentState) and // This would hang the IDE !
  319. (poWaitOnExit in FProcessOptions) and
  320. not (poRunSuspended in FProcessOptions) then
  321. WaitOnExit;
  322. end;
  323. Function TProcess.WaitOnExit : Dword;
  324. begin
  325. Result:=fpWaitPid(Handle,@FExitCode,0);
  326. If Result=Handle then
  327. FExitCode:=WexitStatus(FExitCode);
  328. FRunning:=False;
  329. end;
  330. Function TProcess.Suspend : Longint;
  331. begin
  332. If fpkill(Handle,SIGSTOP)<>0 then
  333. Result:=-1
  334. else
  335. Result:=1;
  336. end;
  337. Function TProcess.Resume : LongInt;
  338. begin
  339. If fpKill(Handle,SIGCONT)<>0 then
  340. Result:=-1
  341. else
  342. Result:=0;
  343. end;
  344. Function TProcess.Terminate(AExitCode : Integer) : Boolean;
  345. begin
  346. Result:=False;
  347. Result:=fpkill(Handle,SIGTERM)=0;
  348. If Result then
  349. begin
  350. If Running then
  351. Result:=fpkill(Handle,SIGKILL)=0;
  352. end;
  353. GetExitStatus;
  354. end;
  355. Procedure TProcess.SetShowWindow (Value : TShowWindowOptions);
  356. begin
  357. FShowWindow:=Value;
  358. end;