2 * This file is part of the KDE libraries
3 * Copyright (c) 1999-2000 Waldo Bastian <bastian@kde.org>
4 * (c) 1999 Mario Weilguni <mweilguni@sime.com>
5 * (c) 2001 Lubos Lunak <l.lunak@kde.org>
6 * (c) 2006 Ralf Habacker <ralf.habacker@freenet.de>
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Library General Public
10 * License version 2 as published by the Free Software Foundation.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Library General Public License for more details.
17 * You should have received a copy of the GNU Library General Public License
18 * along with this library; see the file COPYING.LIB. If not, write to
19 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20 * Boston, MA 02110-1301, USA.
35 #include <QtCore/QProcess>
36 #include <QtCore/QFileInfo>
37 #include <QtDBus/QtDBus>
39 #include <kcomponentdata.h>
40 #include <kstandarddirs.h>
41 #include <kapplication.h>
42 #include <kdeversion.h>
45 #define KDED_EXENAME "kded4"
46 #define KNOTIFY_EXENAME "knotify4"
48 static KComponentData
*s_instance
= 0;
50 // print verbose messages
53 /// holds process list for suicide mode
54 QList
<QProcess
*> startedProcesses
;
56 // internal launch function
57 int launch(const QString
&cmd
)
59 QProcess
*proc
= new QProcess();
61 proc
->waitForStarted();
62 startedProcesses
<< proc
;
63 _PROCESS_INFORMATION
* _pid
= proc
->pid();
64 int pid
= _pid
? _pid
->dwProcessId
: 0;
66 fprintf(stderr
,"%s",proc
->readAllStandardError().constData());
67 fprintf(stderr
,"%s",proc
->readAllStandardOutput().constData());
71 fprintf(stderr
, "kdeinit4: Launched %s, pid = %ld\n", qPrintable(cmd
),(long) pid
);
75 fprintf(stderr
, "kdeinit4: could not launch %s, exiting",qPrintable(cmd
));
80 /// check dbus registration
81 bool checkIfRegisteredInDBus(const QString
&name
, int _timeout
=10)
83 int timeout
= _timeout
* 5;
85 if ( QDBusConnection::sessionBus().interface()->isServiceRegistered( name
) )
92 fprintf(stderr
,"not registered %s in dbus after %d secs\n",qPrintable(name
),_timeout
);
96 fprintf(stderr
,"%s is registered in dbus\n",qPrintable(name
));
100 class ProcessListEntry
{
102 ProcessListEntry(HANDLE _handle
,char *_path
, int _pid
)
105 path
= p
.absolutePath();
117 holds system process list
121 ProcessList() {initProcessList(); }
123 ProcessListEntry
*hasProcessInList(const QString
&name
);
124 bool terminateProcess(const QString
&name
);
127 void initProcessList();
128 void getProcessNameAndID( DWORD processID
);
129 QList
<ProcessListEntry
*> processList
;
133 void ProcessList::getProcessNameAndID( DWORD processID
)
135 char szProcessName
[MAX_PATH
];
137 // Get a handle to the process.
139 HANDLE hProcess
= OpenProcess( SYNCHRONIZE
|PROCESS_QUERY_INFORMATION
|
140 PROCESS_VM_READ
| PROCESS_TERMINATE
,
143 // Get the process name.
145 if (NULL
!= hProcess
)
150 if ( EnumProcessModules( hProcess
, &hMod
, sizeof(hMod
),
153 GetModuleFileNameExA( hProcess
, hMod
, szProcessName
,
154 sizeof(szProcessName
)/sizeof(TCHAR
) );
158 processList
<< new ProcessListEntry(hProcess
,szProcessName
,processID
);
161 fprintf(stderr
,"%s (PID: %u)\n", szProcessName
, processID
);
166 read process list from system and fill in global var aProcessList
168 void ProcessList::initProcessList()
170 // Get the list of process identifiers.
172 DWORD aProcesses
[1024], cbNeeded
, cProcesses
;
175 if ( !EnumProcesses( aProcesses
, sizeof(aProcesses
), &cbNeeded
) )
178 // Calculate how many process identifiers were returned.
180 cProcesses
= cbNeeded
/ sizeof(DWORD
);
182 // Print the name and process identifier for each process.
184 for ( i
= 0; i
< cProcesses
; i
++ )
185 if( aProcesses
[i
] != 0 )
186 getProcessNameAndID( aProcesses
[i
] );
190 ProcessList::~ProcessList()
192 ProcessListEntry
*ple
;
193 foreach(ple
,processList
) {
194 CloseHandle(ple
->handle
);
200 void ProcessList::dumpList()
202 ProcessListEntry
*ple
;
203 foreach(ple
,processList
) {
204 fprintf(stdout
,"%s (PID: %u)\n", ple
->name
.toLatin1().data(), ple
->pid
);
209 return process list entry of given name
211 ProcessListEntry
*ProcessList::hasProcessInList(const QString
&name
)
213 ProcessListEntry
*ple
;
214 foreach(ple
,processList
) {
215 if (ple
->name
== name
|| ple
->name
== name
+ ".exe") {
217 fprintf(stderr
,"found %s with pid=%d\n",qPrintable(ple
->name
),ple
->pid
);
224 bool ProcessList::terminateProcess(const QString
&name
)
226 ProcessListEntry
*p
= hasProcessInList(name
);
228 int ret
= TerminateProcess(p
->handle
,0) ? true : false;
230 fprintf(stderr
,"process %s terminated %d %d\n",qPrintable(name
),ret
,GetLastError());
235 fprintf(stderr
,"process %s not found\n",qPrintable(name
));
241 int main(int argc
, char **argv
, char **envp
)
244 bool launch_dbus
= true;
245 bool launch_klauncher
= true;
246 bool launch_kded
= true;
247 bool suicide
= false;
248 // bool terminate_kde = false; // unused atm
250 ProcessList processList
;
252 /** Save arguments first... **/
253 char **safe_argv
= (char **) malloc( sizeof(char *) * argc
);
254 for(int i
= 0; i
< argc
; i
++)
256 safe_argv
[i
] = strcpy((char*)malloc(strlen(argv
[i
])+1), argv
[i
]);
257 if (strcmp(safe_argv
[i
], "--no-dbus") == 0)
259 if (strcmp(safe_argv
[i
], "--no-klauncher") == 0)
260 launch_klauncher
= false;
261 if (strcmp(safe_argv
[i
], "--no-kded") == 0)
263 if (strcmp(safe_argv
[i
], "--suicide") == 0)
265 // if (strcmp(safe_argv[i], "--exit") == 0)
267 if (strcmp(safe_argv
[i
], "--verbose") == 0)
269 if (strcmp(safe_argv
[i
], "--help") == 0)
271 printf("Usage: kdeinit4 [options]\n");
272 printf(" --no-dbus Do not start dcopserver\n");
273 printf(" --no-klauncher Do not start klauncher\n");
274 printf(" --no-kded Do not start kded\n");
275 printf(" --suicide Terminate when no KDE applications are left running\n");
276 printf(" --terminate Terminate all running kde processes\n");
277 printf(" --verbose print verbose messages\n");
278 printf(" --list list system process for which the user has the right to terminate\n");
279 // printf(" --exit Terminate when kded has run\n");
282 if (strcmp(safe_argv
[i
], "--list") == 0) {
283 processList
.dumpList();
286 if (strcmp(safe_argv
[i
], "--terminate") == 0) {
288 appList
<< KDED_EXENAME
<< KNOTIFY_EXENAME
<< "nepomukdaemon"
289 << "kuiserver" << "kioslave" << "klauncher" << "dbus-daemon";
291 foreach(QString app
, appList
)
292 processList
.terminateProcess(app
);
297 /** Make process group leader (for shutting down children later) **/
299 /** Create our instance **/
300 s_instance
= new KComponentData("kdeinit4", QByteArray(), KComponentData::SkipMainComponentRegistration
);
302 if (launch_dbus
&& !processList
.hasProcessInList("dbus-daemon"))
304 pid
= launch("dbus-launch.exe");
306 pid
= launch("dbus-launch.bat");
311 if (launch_klauncher
&& !processList
.hasProcessInList("klauncher"))
313 pid
= launch("klauncher");
314 if (!pid
|| !checkIfRegisteredInDBus("org.kde.klauncher",10))
319 if (launch_kded
&& !processList
.hasProcessInList(KDED_EXENAME
))
321 pid
= launch(KDED_EXENAME
);
322 if (!pid
|| !checkIfRegisteredInDBus("org.kde.kded",10))
326 for(int i
= 1; i
< argc
; i
++)
328 if (safe_argv
[i
][0] == '+')
330 pid
= launch(safe_argv
[i
]+1);
332 else if (safe_argv
[i
][0] == '-')
338 pid
= launch( safe_argv
[i
]);
342 /** Free arguments **/
343 for(int i
= 0; i
< argc
; i
++)
349 /** wait for termination of all (core) processes */
354 foreach(proc
,startedProcesses
) {
355 if (proc
->state() != QProcess::NotRunning
)