2
/***************************************************************************
5
A unit to manage command lines issue used inside the ide
7
***************************************************************************/
9
***************************************************************************
11
* This source is free software; you can redistribute it and/or modify *
12
* it under the terms of the GNU General Public License as published by *
13
* the Free Software Foundation; either version 2 of the License, or *
14
* (at your option) any later version. *
16
* This code is distributed in the hope that it will be useful, but *
17
* WITHOUT ANY WARRANTY; without even the implied warranty of *
18
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
19
* General Public License for more details. *
21
* A copy of the GNU General Public License is available on the World *
22
* Wide Web at <http://www.gnu.org/copyleft/gpl.html>. You can also *
23
* obtain it by writing to the Free Software Foundation, *
24
* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
26
***************************************************************************
28
Author: Mattias Gaertner
30
This unit manages the command line parameters for lazarus and startlazarus,
40
Classes, SysUtils, FileUtil, lazutf8classes, LazConf, LCLProc,
41
LazarusIDEStrConsts, IDECmdLine;
43
procedure ParseGuiCmdLineParams(var SkipAutoLoadingLastProject,
44
StartedByStartLazarus,
51
EnableRemoteControlOpt='--remote-control';
53
EnableRemoteControl: boolean = false;
55
function SetupMainIDEInstance: boolean; // false if this is a secondary instance
56
function GetPidFile: string;
57
function IsLazarusPIDRunning(aPID: int64): boolean;
58
function GetRemoteControlFilename: string;
59
procedure CleanUpPIDFile;
64
{$DEFINE UseProcFileSystem}
66
{$IF defined(FreeBSD) and defined(VER2_5)}
67
{$DEFINE UseFreeBSDKernProc}
68
uses FreeBSD, BaseUnix;
71
{$DEFINE UseCarbonProc}
72
uses MacOSAll, CarbonProc;
75
function IsLazarusPIDRunning(aPID: int64): boolean;
77
function CheckProcFileSystem: boolean;
83
Filename:='/proc/'+IntToStr(aPID)+'/cmdline';
84
if not FileExists(Filename) then exit;
85
sl:=TStringList.Create;
88
sl.LoadFromFile(Filename);
89
if sl.Count=0 then exit;
90
if Pos('lazarus',lowercase(sl[0]))<1 then exit;
99
{$IFDEF UseFreeBSDKernProc}
100
function CheckFreeBSDKernProc: boolean;
104
Result:=(kernproc_getpath(aPID,s)<>-1)
105
and (Pos('lazarus',lowercase(s))>0);
109
{$IFDEF UseCarbonProc}
110
function CheckCarbonProc: boolean;
112
psn: ProcessSerialNumber;
113
info: ProcessInfoRec;
114
processName: CFStringRef;
118
if GetProcessForPID(aPid,psn)<>noErr then exit;
119
FillByte(info,SizeOf(info),0);
120
if GetProcessInformation(psn,info)<>noErr then exit;
122
if CopyProcessName(psn, processName)<>noErr then exit;
123
if processName<>nil then begin
124
s:=CFStringToStr(processName);
125
CFRelease(processName);
126
Result:=Pos('lazarus',lowercase(s))>0;
133
{$IFDEF UseFreeBSDKernProc}
134
if CheckFreeBSDKernProc then exit;
136
{$IFDEF UseProcFileSystem}
137
if CheckProcFileSystem then exit;
139
{$IFDEF UseCarbonProc}
140
if CheckCarbonProc then exit;
145
function GetPidFile: string;
147
Result:=AppendPathDelim(GetPrimaryConfigPath)+'pid.txt';
150
procedure ParseGuiCmdLineParams(var SkipAutoLoadingLastProject,
151
StartedByStartLazarus, EnableRemoteControl, ShowSplashScreen, Setup: Boolean);
155
ParseNoGuiCmdLineParams;
156
for i:= 1 to ParamCount do
158
//DebugLn(['ParseGuiCmdLineParams ',i,' "',ParamStrUTF8(i),'"']);
159
if ParamIsOption(i, NoSplashScreenOptLong) or
160
ParamIsOption(i, NoSplashScreenOptShort) then
161
ShowSplashScreen := false
162
else if ParamIsOption(i, ShowSetupDialogOptLong) then
164
else if ParamIsOption(i, SkipLastProjectOpt) then
165
SkipAutoLoadingLastProject := true
166
else if ParamIsOption(i, StartedByStartLazarusOpt) then
167
StartedByStartLazarus := true
168
else if ParamIsOption(i, EnableRemoteControlOpt) then
169
EnableRemoteControl := true;
173
function SetupMainIDEInstance: boolean;
175
procedure WritePIDFile(const Filename: string; aPID: int64);
180
debugln(['WritePIDFile File="',Filename,'" PID=',aPID]);
181
sl:=TStringListUTF8.Create;
183
sl.Add(IntToStr(aPID));
185
Dir:=ChompPathDelim(ExtractFilePath(Filename));
186
if not DirectoryExistsUTF8(Dir) then begin
187
if not CreateDirUTF8(Dir) then
188
debugln(['WritePIDFile failed to create directory ',Dir]);
191
sl.SaveToFile(Filename);
193
on E: Exception do begin
194
debugln(['WritePIDFile "',Filename,'" failed:']);
203
function ReadPIDFile(const Filename: string; out ConfigPID: int64): boolean;
209
debugln(['ReadPIDFile ',Filename]);
210
if not FileExistsUTF8(Filename) then exit;
211
sl:=TStringListUTF8.Create;
214
sl.LoadFromFile(Filename);
215
ConfigPID:=StrToInt64(sl[0]);
217
debugln(['ReadPIDFile ConfigPID=',ConfigPID]);
219
on E: Exception do begin
220
debugln(['ReadPIDFile "',Filename,'" failed:']);
229
procedure SendCmdlineActionsToMainInstance;
236
sl:=TStringListUTF8.Create;
239
for i:=1 to Paramcount do begin
240
Param:=ParamStrUTF8(i);
241
if (Param='') or (Param[1]='-') then continue;
242
sl.Add('Open '+Param);
244
Filename:=GetRemoteControlFilename;
246
debugln(['SendCmdlineActionsToMainInstance Commands="',sl.Text,'"']);
247
sl.SaveToFile(Filename);
249
on E: Exception do begin
250
debugln(['SendCmdlineActionsToMainInstance failed to write ',Filename]);
261
MyPID, ConfigPID: int64;
265
if not EnableRemoteControl then exit;
267
// check if another IDE (of this user and same configuration) is already
268
// running. Request it to handle the show and handle the command line
269
// parameters (e.g. open files). And if successful return false.
270
// Otherwise become the main instance.
271
PIDFilename:=GetPidFile;
274
PIDRead:=ReadPIDFile(PIDFilename,ConfigPID);
275
if PIDRead and (ConfigPID<>MyPID) then begin
276
// there is a pid file from another instance
277
if not IsLazarusPIDRunning(ConfigPID) then begin
279
DeleteFileUTF8(PIDFilename);
283
if not FileExistsUTF8(PIDFilename) then begin
284
// try to become the main instance
285
WritePIDFile(PIDFilename,MyPID);
289
PIDRead:=ReadPIDFile(PIDFilename,ConfigPID);
290
if ConfigPID=MyPID then begin
291
// this is the main instance
294
// this is a second instance
297
SendCmdlineActionsToMainInstance;
300
function GetRemoteControlFilename: string;
302
Result:=AppendPathDelim(GetPrimaryConfigPath)+'ideremotecontrol.txt';
305
procedure CleanUpPIDFile;
307
if EnableRemoteControl then
308
DeleteFileUTF8(GetRemoteControlFilename);