process.inc 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383
  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 EProcess.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 cint;
  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 EProcess.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 EProcess.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. fpclose(HI[peWrite]);
  244. fpdup2(HI[peRead],0);
  245. fpclose(HO[peRead]);
  246. fpdup2(HO[peWrite],1);
  247. if (poStdErrToOutPut in Options) then
  248. fpdup2(HO[peWrite],2)
  249. else
  250. begin
  251. fpclose(HE[peRead]);
  252. fpdup2(HE[peWrite],2);
  253. end
  254. end
  255. else if poNoConsole in Options then
  256. begin
  257. fd:=FileOpen('/dev/null',fmOpenReadWrite);
  258. fpdup2(fd,0);
  259. fpdup2(fd,1);
  260. fpdup2(fd,2);
  261. end;
  262. if (poRunSuspended in Options) then
  263. sigraise(SIGSTOP);
  264. if FEnv<>Nil then
  265. fpexecve(PName,Argv,Fenv)
  266. else
  267. fpexecv(PName,argv);
  268. Halt(127);
  269. end
  270. Finally
  271. FreePcharList(Argv);
  272. end;
  273. Finally
  274. If (FEnv<>Nil) then
  275. FreePCharList(FEnv);
  276. end;
  277. Finally
  278. if POUsePipes in FProcessOptions then
  279. begin
  280. FileClose(HO[peWrite]);
  281. FileClose(HI[peRead]);
  282. if Not (poStdErrToOutPut in FProcessOptions) then
  283. FileClose(HE[peWrite]);
  284. CreateStreams(HI[peWrite],HO[peRead],HE[peRead]);
  285. end;
  286. end;
  287. FRunning:=True;
  288. if not (csDesigning in ComponentState) and // This would hang the IDE !
  289. (poWaitOnExit in FProcessOptions) and
  290. not (poRunSuspended in FProcessOptions) then
  291. WaitOnExit;
  292. end;
  293. Function TProcess.WaitOnExit : Dword;
  294. begin
  295. Result:=fpWaitPid(Handle,@FExitCode,0);
  296. If Result=Handle then
  297. FExitCode:=WexitStatus(FExitCode);
  298. FRunning:=False;
  299. end;
  300. Function TProcess.Suspend : Longint;
  301. begin
  302. If fpkill(Handle,SIGSTOP)<>0 then
  303. Result:=-1
  304. else
  305. Result:=1;
  306. end;
  307. Function TProcess.Resume : LongInt;
  308. begin
  309. If fpKill(Handle,SIGCONT)<>0 then
  310. Result:=-1
  311. else
  312. Result:=0;
  313. end;
  314. Function TProcess.Terminate(AExitCode : Integer) : Boolean;
  315. begin
  316. Result:=False;
  317. Result:=fpkill(Handle,SIGTERM)=0;
  318. If Result then
  319. begin
  320. If Running then
  321. Result:=fpkill(Handle,SIGKILL)=0;
  322. end;
  323. GetExitStatus;
  324. end;
  325. Procedure TProcess.SetShowWindow (Value : TShowWindowOptions);
  326. begin
  327. FShowWindow:=Value;
  328. end;