process.inc 7.6 KB

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