• Skip to content
  • Skip to link menu
KDE 4.1 API Reference
  • KDE API Reference
  • kdelibs
  • Sitemap
  • Contact Us
 

KInit

kinit_win.cpp

Go to the documentation of this file.
00001 /*
00002  * This file is part of the KDE libraries
00003  * Copyright (c) 1999-2000 Waldo Bastian <bastian@kde.org>
00004  *                 (c) 1999 Mario Weilguni <mweilguni@sime.com>
00005  *                 (c) 2001 Lubos Lunak <l.lunak@kde.org>
00006  *                 (c) 2006 Ralf Habacker <ralf.habacker@freenet.de>
00007  *
00008  * This library is free software; you can redistribute it and/or
00009  * modify it under the terms of the GNU Library General Public
00010  * License version 2 as published by the Free Software Foundation.
00011  *
00012  * This library is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.    See the GNU
00015  * Library General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU Library General Public License
00018  * along with this library; see the file COPYING.LIB.    If not, write to
00019  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00020  * Boston, MA 02110-1301, USA.
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 //#define ENABLE_SUICIDE 
00045 //#define ENABLE_EXIT
00046 
00047 #define KDED_EXENAME "kded4"
00048 
00049 static KComponentData *s_instance = 0;
00050 
00051 // print verbose messages
00052 int verbose=0;
00053 
00055 QList<QProcess*> startedProcesses;
00056 
00057 class ProcessListEntry {
00058     public:
00059        ProcessListEntry(HANDLE _handle,char *_path, int _pid ) 
00060        {    
00061            QFileInfo p(_path);
00062            path = p.absolutePath();
00063            name = p.baseName();
00064            handle = _handle; 
00065            pid = _pid; 
00066        }
00067        QString name;
00068        QString path;
00069        int pid;
00070        HANDLE handle;
00071        friend QDebug operator <<(QDebug out, const ProcessListEntry &c);
00072 };
00073 
00074 QDebug operator <<(QDebug out, const ProcessListEntry &c)
00075 {
00076     out << "(ProcessListEntry" 
00077         << "name" << c.name
00078         << "path" << c.path
00079         << "pid" << c.pid
00080         << "handle" << c.handle
00081         << ")";
00082     return out;
00083 }    
00084 
00088 class ProcessList {
00089     public:
00090        ProcessList() {initProcessList(); }
00091        ~ProcessList();
00092        ProcessListEntry *hasProcessInList(const QString &name);
00093        bool terminateProcess(const QString &name);
00094        QList<ProcessListEntry *> &list() { return processList; }
00095     private:
00096        void initProcessList();
00097        void getProcessNameAndID( DWORD processID );
00098        QList<ProcessListEntry *> processList;
00099 };
00100 
00101 
00102 void ProcessList::getProcessNameAndID( DWORD processID )
00103 {
00104     char szProcessName[MAX_PATH];
00105 
00106     // Get a handle to the process.
00107 
00108     HANDLE hProcess = OpenProcess( SYNCHRONIZE|PROCESS_QUERY_INFORMATION |
00109                                    PROCESS_VM_READ | PROCESS_TERMINATE,
00110                                    false, processID );
00111 
00112     // Get the process name.
00113     int ret;
00114 
00115     if (NULL != hProcess )
00116     {
00117        HMODULE hMod;
00118        DWORD cbNeeded;
00119 
00120        if ( EnumProcessModules( hProcess, &hMod, sizeof(hMod),
00121               &cbNeeded) )
00122        {
00123             ret = GetModuleFileNameExA( hProcess, hMod, szProcessName,
00124                                            sizeof(szProcessName)/sizeof(TCHAR) );
00125        }
00126     }
00127     if (ret > 0)
00128     {
00129         processList << new ProcessListEntry(hProcess,szProcessName,processID );
00130     }
00131 }
00132 
00133 
00137 void ProcessList::initProcessList()
00138 {
00139     // Get the list of process identifiers.
00140 
00141     DWORD aProcesses[1024], cbNeeded, cProcesses;
00142     unsigned int i;
00143 
00144     if ( !EnumProcesses( aProcesses, sizeof(aProcesses), &cbNeeded ) )
00145         return;
00146 
00147     // Calculate how many process identifiers were returned.
00148 
00149     cProcesses = cbNeeded / sizeof(DWORD);
00150 
00151     // Print the name and process identifier for each process.
00152 
00153     for ( i = 0; i < cProcesses; i++ )
00154         if( aProcesses[i] != 0 )
00155             getProcessNameAndID( aProcesses[i] );
00156 }
00157 
00158 
00159 ProcessList::~ProcessList()
00160 {
00161     ProcessListEntry *ple;
00162     foreach(ple,processList) {
00163         CloseHandle(ple->handle);
00164         delete ple;
00165     }
00166 }
00167 
00171 ProcessListEntry *ProcessList::hasProcessInList(const QString &name)
00172 {
00173     ProcessListEntry *ple;
00174     foreach(ple,processList) {
00175         if (ple->name == name || ple->name == name + ".exe") {
00176             return ple;
00177         }
00178     }
00179     return NULL;
00180 }
00181 
00185 bool ProcessList::terminateProcess(const QString &name)
00186 {
00187     ProcessListEntry *p = hasProcessInList(name);
00188     if (!p)
00189         return false;
00190     return TerminateProcess(p->handle,0) ? true : false;
00191 }
00192 
00193 // internal launch function
00194 int launch(const QString &cmd)
00195 {
00196     QProcess *proc = new QProcess();
00197     proc->start(cmd);
00198     proc->waitForStarted();
00199     startedProcesses << proc;
00200     _PROCESS_INFORMATION* _pid = proc->pid();
00201     int pid = _pid ? _pid->dwProcessId : 0;
00202     if (verbose) {
00203         fprintf(stderr,"%s",proc->readAllStandardError().constData());
00204         fprintf(stderr,"%s",proc->readAllStandardOutput().constData());
00205     }
00206     if (pid) {
00207        if (verbose)
00208            fprintf(stderr, "kdeinit4: Launched %s, pid = %ld\n", qPrintable(cmd),(long) pid);
00209     }
00210     else {
00211        if (verbose)
00212            fprintf(stderr, "kdeinit4: could not launch %s, exiting",qPrintable(cmd));
00213     }
00214     return pid;
00215 }
00216 
00218 bool checkIfRegisteredInDBus(const QString &name, int _timeout=10)
00219 {
00220     int timeout = _timeout * 5;
00221     while(timeout) {
00222         if ( QDBusConnection::sessionBus().interface()->isServiceRegistered( name ) )
00223             break;
00224         Sleep(200);
00225         timeout--;
00226     }
00227         if (!timeout) {
00228             if (verbose)
00229                 fprintf(stderr,"not registered %s in dbus after %d secs\n",qPrintable(name),_timeout);
00230             return false;
00231         }
00232         if (verbose)
00233             fprintf(stderr,"%s is registered in dbus\n",qPrintable(name));
00234     return true;
00235 }
00236 
00237 void listAllRunningKDEProcesses(ProcessList &processList)
00238 {
00239     ProcessListEntry *ple;
00240     QString installPrefix = KStandardDirs::installPath("kdedir");
00241 
00242     foreach(ple,processList.list()) 
00243     {
00244         if (ple->path.toLower().startsWith(installPrefix.toLower()))
00245             fprintf(stderr,"path: %s name: %s pid: %u\n", ple->path.toLatin1().data(), ple->name.toLatin1().data(), ple->pid);
00246     }
00247 }
00248 
00249 void terminateAllRunningKDEProcesses(ProcessList &processList)
00250 {
00251     ProcessListEntry *ple;
00252     QString installPrefix = KStandardDirs::installPath("kdedir");
00253 
00254     foreach(ple,processList.list()) 
00255     {
00256         if (ple->path.toLower().startsWith(installPrefix.toLower())) 
00257         {
00258             if (verbose)
00259                 fprintf(stderr,"terminating path: %s name: %s pid: %u\n", ple->path.toLatin1().data(), ple->name.toLatin1().data(), ple->pid);
00260             processList.terminateProcess(ple->name);
00261         }
00262     }
00263 }
00264 
00265 void listAllNamedAppsInDBus()
00266 {
00267     QDBusConnection connection = QDBusConnection::sessionBus();
00268     QDBusConnectionInterface *bus = connection.interface();
00269     const QStringList services = bus->registeredServiceNames();
00270     foreach(const QString &service, services) {
00271         if (service.startsWith("org.freedesktop.DBus") || service.startsWith(':'))
00272             continue;
00273         fprintf(stderr, "%s \n", service.toLatin1().data());
00274     }
00275 }
00276 
00277 void quitApplicationsOverDBus()
00278 {
00279     QDBusConnection connection = QDBusConnection::sessionBus();
00280     QDBusConnectionInterface *bus = connection.interface();
00281     const QStringList services = bus->registeredServiceNames();
00282     foreach(const QString &service, services) {
00283         if (service.startsWith("org.freedesktop.DBus") || service.startsWith(':'))
00284             continue;
00285         QDBusInterface *iface = new QDBusInterface(service,
00286                                QLatin1String("/MainApplication"),
00287 //  see http://lists.kde.org/?l=kde-core-devel&m=121641642911291&w=2
00288 #if QT_VERSION < 0x040402
00289                                QLatin1String(""),
00290 #else                             
00291                                QLatin1String("org.kde.KApplication"),
00292 #endif
00293                                connection);
00294         if (!iface->isValid()) {
00295             if (verbose)
00296                 fprintf(stderr, "invalid interface of service %s\n", service.toLatin1().data());
00297             continue;
00298         }
00299         iface->call("quit");
00300         if (iface->lastError().isValid()) {
00301             if (verbose)
00302                 fprintf(stderr,"killing %s with result\n", iface->lastError().message().toLatin1().data());
00303         }
00304         delete iface;
00305     }
00306 }
00307 
00308 int main(int argc, char **argv, char **envp)
00309 {
00310     pid_t pid;
00311     bool launch_dbus = true;
00312     bool launch_klauncher = true;
00313     bool launch_kded = true;
00314     bool suicide = false;
00315     bool listProcesses = false;
00316     bool killProcesses = false;
00317     bool listAppsInDBus = false;
00318     bool quitAppsOverDBus = false;
00319     bool shutdown = false;
00320 
00322     char **safe_argv = (char **) malloc( sizeof(char *) * argc);
00323     for(int i = 0; i < argc; i++)
00324     {
00325         safe_argv[i] = strcpy((char*)malloc(strlen(argv[i])+1), argv[i]);
00326         if (strcmp(safe_argv[i], "--no-dbus") == 0)
00327             launch_dbus = false;
00328         if (strcmp(safe_argv[i], "--no-klauncher") == 0)
00329             launch_klauncher = false;
00330         if (strcmp(safe_argv[i], "--no-kded") == 0)
00331             launch_kded = false;
00332         if (strcmp(safe_argv[i], "--suicide") == 0)
00333             suicide = true;
00334 #ifdef ENABLE_EXIT
00335         if (strcmp(safe_argv[i], "--exit") == 0)
00336             keep_running = 0;
00337 #endif            
00338         if (strcmp(safe_argv[i], "--verbose") == 0)
00339             verbose = 1;
00340         if (strcmp(safe_argv[i], "--help") == 0)
00341         {
00342            printf("Usage: kdeinit4 [options]\n");
00343 #ifdef ENABLE_EXIT
00344            printf("   --exit                     Terminate when kded has run\n");
00345 #endif
00346            printf("   --help                     this help page\n");
00347            printf("   --list                     list kde processes\n");
00348            printf("   --list-dbus-apps           list all applications registered in dbus\n");
00349            printf("   --quit-over-dbus           quit all application registered in dbus\n");
00350            printf("   --no-dbus                  do not start dbus-daemon\n");
00351            printf("   --no-klauncher             do not start klauncher\n");
00352            printf("   --no-kded                  do not start kded\n");
00353            printf("   --shutdown                 safe shutdown of all running kde processes\n");
00354            printf("                              first over dbus, then using hard kill\n");
00355 #ifdef ENABLE_SUICIDE
00356            printf("    --suicide                 terminate when no KDE applications are left running\n");
00357 #endif
00358            printf("   --terminate                hard kill of *all* running kde processes\n");
00359            printf("   --verbose                  print verbose messages\n");
00360            exit(0);
00361         }
00362         if (strcmp(safe_argv[i], "--list") == 0)
00363             listProcesses = true;
00364         if (strcmp(safe_argv[i], "--shutdown") == 0)
00365             shutdown = true;
00366         if (strcmp(safe_argv[i], "--terminate") == 0 || strcmp(safe_argv[i], "--kill") == 0)
00367             killProcesses = true;
00368         if (strcmp(safe_argv[i], "--list-dbus-apps") == 0)
00369             listAppsInDBus = true;
00370         if (strcmp(safe_argv[i], "--quit-over-dbus") == 0)
00371             quitAppsOverDBus = true;
00372     }
00373 
00374     ProcessList processList;
00375 
00376     if (listProcesses) {
00377         listAllRunningKDEProcesses(processList);
00378         return 0;
00379     }
00380     else if (killProcesses) {
00381         terminateAllRunningKDEProcesses(processList);
00382         return 0;
00383     }
00384     else if (listAppsInDBus) {
00385         listAllNamedAppsInDBus();
00386         return 0;
00387     }
00388     else if (quitAppsOverDBus) {
00389         quitApplicationsOverDBus();
00390         return 0;
00391     }
00392     else if (shutdown) {
00393         quitApplicationsOverDBus();
00394         Sleep(2000);
00395         terminateAllRunningKDEProcesses(processList);
00396     }
00397     
00399     s_instance = new KComponentData("kdeinit4", QByteArray(), KComponentData::SkipMainComponentRegistration);
00400 
00401     if (launch_dbus && !processList.hasProcessInList("dbus-daemon"))
00402     {
00403           pid = launch("dbus-launch.exe");
00404           if (!pid)
00405               pid = launch("dbus-launch.bat");
00406           if (!pid)
00407               exit(1);
00408     }
00409 
00410     if (launch_klauncher && !processList.hasProcessInList("klauncher"))
00411     {
00412           pid = launch("klauncher");
00413           if (!pid || !checkIfRegisteredInDBus("org.kde.klauncher",10))
00414               exit(1);
00415     }
00416 
00417 
00418     if (launch_kded && !processList.hasProcessInList(KDED_EXENAME))
00419     {
00420         pid = launch(KDED_EXENAME);
00421         if (!pid || !checkIfRegisteredInDBus("org.kde.kded",10))
00422             exit(1);
00423     }
00424 
00425     for(int i = 1; i < argc; i++)
00426     {
00427         if (safe_argv[i][0] == '+')
00428         {
00429             pid = launch(safe_argv[i]+1);
00430         }
00431         else if (safe_argv[i][0] == '-')
00432         {
00433             // Ignore
00434         }
00435         else
00436         {
00437             pid = launch( safe_argv[i]);
00438         }
00439     }
00440 
00442     for(int i = 0; i < argc; i++)
00443     {
00444           free(safe_argv[i]);
00445     }
00446     free (safe_argv);
00447 
00449 #ifdef ENABLE_SUICIDE
00450     if (suicide) {
00451         QProcess *proc;
00452         int can_exit=1;
00453         do {
00454            foreach(proc,startedProcesses) {
00455              if (proc->state() != QProcess::NotRunning)
00456                 can_exit = 0;
00457            }
00458            if (!can_exit)
00459              Sleep(2000);
00460         } while(!can_exit);
00461         return 0;
00462     }
00463 #endif    
00464     return 0;
00465 }

KInit

Skip menu "KInit"
  • Main Page
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Class Members
  • Related Pages

kdelibs

Skip menu "kdelibs"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • Kate
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • KIO
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • Kross
  • KUtils
  • Nepomuk
  • Solid
  • Sonnet
  • ThreadWeaver
Generated for kdelibs by doxygen 1.5.4
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal