00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include <config.h>
00024
00025
00026 #include <errno.h>
00027 #include <stdio.h>
00028 #include <stdlib.h>
00029 #include <string.h>
00030
00031 #include <windows.h>
00032 #include <psapi.h>
00033
00034
00035 #include <QtCore/QProcess>
00036 #include <QtCore/QFileInfo>
00037 #include <QtDBus/QtDBus>
00038
00039 #include <kcomponentdata.h>
00040 #include <kstandarddirs.h>
00041 #include <kapplication.h>
00042 #include <kdeversion.h>
00043
00044
00045 #define KDED_EXENAME "kded4"
00046 #define KNOTIFY_EXENAME "knotify4"
00047
00048 static KComponentData *s_instance = 0;
00049
00050
00051 int verbose=0;
00052
00054 QList<QProcess*> startedProcesses;
00055
00056
00057 int launch(const QString &cmd)
00058 {
00059 QProcess *proc = new QProcess();
00060 proc->start(cmd);
00061 proc->waitForStarted();
00062 startedProcesses << proc;
00063 _PROCESS_INFORMATION* _pid = proc->pid();
00064 int pid = _pid ? _pid->dwProcessId : 0;
00065 if (verbose) {
00066 fprintf(stderr,"%s",proc->readAllStandardError().constData());
00067 fprintf(stderr,"%s",proc->readAllStandardOutput().constData());
00068 }
00069 if (pid) {
00070 if (verbose)
00071 fprintf(stderr, "kdeinit4: Launched %s, pid = %ld\n", qPrintable(cmd),(long) pid);
00072 }
00073 else {
00074 if (verbose)
00075 fprintf(stderr, "kdeinit4: could not launch %s, exiting",qPrintable(cmd));
00076 }
00077 return pid;
00078 }
00079
00081 bool checkIfRegisteredInDBus(const QString &name, int _timeout=10)
00082 {
00083 int timeout = _timeout * 5;
00084 while(timeout) {
00085 if ( QDBusConnection::sessionBus().interface()->isServiceRegistered( name ) )
00086 break;
00087 Sleep(200);
00088 timeout--;
00089 }
00090 if (!timeout) {
00091 if (verbose)
00092 fprintf(stderr,"not registered %s in dbus after %d secs\n",qPrintable(name),_timeout);
00093 return false;
00094 }
00095 if (verbose)
00096 fprintf(stderr,"%s is registered in dbus\n",qPrintable(name));
00097 return true;
00098 }
00099
00100 class ProcessListEntry {
00101 public:
00102 ProcessListEntry(HANDLE _handle,char *_path, int _pid )
00103 {
00104 QFileInfo p(_path);
00105 path = p.absolutePath();
00106 name = p.baseName();
00107 handle = _handle;
00108 pid = _pid;
00109 }
00110 QString name;
00111 QString path;
00112 int pid;
00113 HANDLE handle;
00114 };
00115
00119 class ProcessList {
00120 public:
00121 ProcessList() {initProcessList(); }
00122 ~ProcessList();
00123 ProcessListEntry *hasProcessInList(const QString &name);
00124 bool terminateProcess(const QString &name);
00125 void dumpList();
00126 private:
00127 void initProcessList();
00128 void getProcessNameAndID( DWORD processID );
00129 QList<ProcessListEntry *> processList;
00130 };
00131
00132
00133 void ProcessList::getProcessNameAndID( DWORD processID )
00134 {
00135 char szProcessName[MAX_PATH];
00136
00137
00138
00139 HANDLE hProcess = OpenProcess( SYNCHRONIZE|PROCESS_QUERY_INFORMATION |
00140 PROCESS_VM_READ | PROCESS_TERMINATE,
00141 false, processID );
00142
00143
00144
00145 if (NULL != hProcess )
00146 {
00147 HMODULE hMod;
00148 DWORD cbNeeded;
00149
00150 if ( EnumProcessModules( hProcess, &hMod, sizeof(hMod),
00151 &cbNeeded) )
00152 {
00153 GetModuleFileNameExA( hProcess, hMod, szProcessName,
00154 sizeof(szProcessName)/sizeof(TCHAR) );
00155 }
00156 }
00157
00158 processList << new ProcessListEntry(hProcess,szProcessName,processID );
00159
00160 if (verbose)
00161 fprintf(stderr,"%s (PID: %u)\n", szProcessName, processID );
00162 }
00163
00164
00168 void ProcessList::initProcessList()
00169 {
00170
00171
00172 DWORD aProcesses[1024], cbNeeded, cProcesses;
00173 unsigned int i;
00174
00175 if ( !EnumProcesses( aProcesses, sizeof(aProcesses), &cbNeeded ) )
00176 return;
00177
00178
00179
00180 cProcesses = cbNeeded / sizeof(DWORD);
00181
00182
00183
00184 for ( i = 0; i < cProcesses; i++ )
00185 if( aProcesses[i] != 0 )
00186 getProcessNameAndID( aProcesses[i] );
00187 }
00188
00189
00190 ProcessList::~ProcessList()
00191 {
00192 ProcessListEntry *ple;
00193 foreach(ple,processList) {
00194 CloseHandle(ple->handle);
00195 delete ple;
00196 }
00197 }
00198
00199
00200 void ProcessList::dumpList()
00201 {
00202 ProcessListEntry *ple;
00203 foreach(ple,processList) {
00204 fprintf(stdout,"%s (PID: %u)\n", ple->name.toLatin1().data(), ple->pid);
00205 }
00206 }
00207
00211 ProcessListEntry *ProcessList::hasProcessInList(const QString &name)
00212 {
00213 ProcessListEntry *ple;
00214 foreach(ple,processList) {
00215 if (ple->name == name || ple->name == name + ".exe") {
00216 if (verbose)
00217 fprintf(stderr,"found %s with pid=%d\n",qPrintable(ple->name),ple->pid);
00218 return ple;
00219 }
00220 }
00221 return NULL;
00222 }
00223
00224 bool ProcessList::terminateProcess(const QString &name)
00225 {
00226 ProcessListEntry *p = hasProcessInList(name);
00227 if (p) {
00228 int ret = TerminateProcess(p->handle,0) ? true : false;
00229 if (verbose)
00230 fprintf(stderr,"process %s terminated %d %d\n",qPrintable(name),ret,GetLastError());
00231 return ret;
00232 }
00233 else {
00234 if (verbose)
00235 fprintf(stderr,"process %s not found\n",qPrintable(name));
00236 return false;
00237 }
00238 }
00239
00240
00241 int main(int argc, char **argv, char **envp)
00242 {
00243 pid_t pid;
00244 bool launch_dbus = true;
00245 bool launch_klauncher = true;
00246 bool launch_kded = true;
00247 bool suicide = false;
00248
00249
00250 ProcessList processList;
00251
00253 char **safe_argv = (char **) malloc( sizeof(char *) * argc);
00254 for(int i = 0; i < argc; i++)
00255 {
00256 safe_argv[i] = strcpy((char*)malloc(strlen(argv[i])+1), argv[i]);
00257 if (strcmp(safe_argv[i], "--no-dbus") == 0)
00258 launch_dbus = false;
00259 if (strcmp(safe_argv[i], "--no-klauncher") == 0)
00260 launch_klauncher = false;
00261 if (strcmp(safe_argv[i], "--no-kded") == 0)
00262 launch_kded = false;
00263 if (strcmp(safe_argv[i], "--suicide") == 0)
00264 suicide = true;
00265
00266
00267 if (strcmp(safe_argv[i], "--verbose") == 0)
00268 verbose = 1;
00269 if (strcmp(safe_argv[i], "--help") == 0)
00270 {
00271 printf("Usage: kdeinit4 [options]\n");
00272 printf(" --no-dbus Do not start dcopserver\n");
00273 printf(" --no-klauncher Do not start klauncher\n");
00274 printf(" --no-kded Do not start kded\n");
00275 printf(" --suicide Terminate when no KDE applications are left running\n");
00276 printf(" --terminate Terminate all running kde processes\n");
00277 printf(" --verbose print verbose messages\n");
00278 printf(" --list list system process for which the user has the right to terminate\n");
00279
00280 exit(0);
00281 }
00282 if (strcmp(safe_argv[i], "--list") == 0) {
00283 processList.dumpList();
00284 exit(0);
00285 }
00286 if (strcmp(safe_argv[i], "--terminate") == 0) {
00287 QStringList appList;
00288 appList << KDED_EXENAME << KNOTIFY_EXENAME << "nepomukdaemon"
00289 << "kuiserver" << "kioslave" << "klauncher" << "dbus-daemon";
00290
00291 foreach(QString app, appList)
00292 processList.terminateProcess(app);
00293 exit(0);
00294 }
00295 }
00296
00300 s_instance = new KComponentData("kdeinit4", QByteArray(), KComponentData::SkipMainComponentRegistration);
00301
00302 if (launch_dbus && !processList.hasProcessInList("dbus-daemon"))
00303 {
00304 pid = launch("dbus-launch.exe");
00305 if (!pid)
00306 pid = launch("dbus-launch.bat");
00307 if (!pid)
00308 exit(1);
00309 }
00310
00311 if (launch_klauncher && !processList.hasProcessInList("klauncher"))
00312 {
00313 pid = launch("klauncher");
00314 if (!pid || !checkIfRegisteredInDBus("org.kde.klauncher",10))
00315 exit(1);
00316 }
00317
00318
00319 if (launch_kded && !processList.hasProcessInList(KDED_EXENAME))
00320 {
00321 pid = launch(KDED_EXENAME);
00322 if (!pid || !checkIfRegisteredInDBus("org.kde.kded",10))
00323 exit(1);
00324 }
00325
00326 for(int i = 1; i < argc; i++)
00327 {
00328 if (safe_argv[i][0] == '+')
00329 {
00330 pid = launch(safe_argv[i]+1);
00331 }
00332 else if (safe_argv[i][0] == '-')
00333 {
00334
00335 }
00336 else
00337 {
00338 pid = launch( safe_argv[i]);
00339 }
00340 }
00341
00343 for(int i = 0; i < argc; i++)
00344 {
00345 free(safe_argv[i]);
00346 }
00347 free (safe_argv);
00348
00350 if (suicide) {
00351 QProcess *proc;
00352 int can_exit=1;
00353 do {
00354 foreach(proc,startedProcesses) {
00355 if (proc->state() != QProcess::NotRunning)
00356 can_exit = 0;
00357 }
00358 if (!can_exit)
00359 Sleep(2000);
00360 } while(!can_exit);
00361 return 0;
00362 }
00363 return 0;
00364 }