• Skip to content
  • Skip to link menu
KDE 4.3 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 
00191     bool ret = TerminateProcess(p->handle,0);
00192     if (ret) {
00193         CloseHandle(p->handle);
00194         delete p;
00195         return true;
00196     } else {
00197         return false;
00198     }
00199 }
00200 
00201 // internal launch function
00202 int launch(const QString &cmd)
00203 {
00204     QProcess *proc = new QProcess();
00205     proc->start(cmd);
00206     proc->waitForStarted();
00207     startedProcesses << proc;
00208     _PROCESS_INFORMATION* _pid = proc->pid();
00209     int pid = _pid ? _pid->dwProcessId : 0;
00210     if (verbose) {
00211         fprintf(stderr,"%s",proc->readAllStandardError().constData());
00212         fprintf(stderr,"%s",proc->readAllStandardOutput().constData());
00213     }
00214     if (pid) {
00215        if (verbose)
00216            fprintf(stderr, "kdeinit4: Launched %s, pid = %ld\n", qPrintable(cmd),(long) pid);
00217     }
00218     else {
00219        if (verbose)
00220            fprintf(stderr, "kdeinit4: could not launch %s, exiting",qPrintable(cmd));
00221     }
00222     return pid;
00223 }
00224 
00226 bool checkIfRegisteredInDBus(const QString &name, int _timeout=10)
00227 {
00228     int timeout = _timeout * 5;
00229     while(timeout) {
00230         if ( QDBusConnection::sessionBus().interface()->isServiceRegistered( name ) )
00231             break;
00232         Sleep(200);
00233         timeout--;
00234     }
00235         if (!timeout) {
00236             if (verbose)
00237                 fprintf(stderr,"not registered %s in dbus after %d secs\n",qPrintable(name),_timeout);
00238             return false;
00239         }
00240         if (verbose)
00241             fprintf(stderr,"%s is registered in dbus\n",qPrintable(name));
00242     return true;
00243 }
00244 
00245 void listAllRunningKDEProcesses(ProcessList &processList)
00246 {
00247     ProcessListEntry *ple;
00248     QString installPrefix = KStandardDirs::installPath("kdedir");
00249 
00250     foreach(ple,processList.list()) 
00251     {
00252         if (ple->path.toLower().startsWith(installPrefix.toLower()))
00253             fprintf(stderr,"path: %s name: %s pid: %u\n", ple->path.toLatin1().data(), ple->name.toLatin1().data(), ple->pid);
00254     }
00255 }
00256 
00257 void terminateAllRunningKDEProcesses(ProcessList &processList)
00258 {
00259     ProcessListEntry *ple;
00260     QString installPrefix = KStandardDirs::installPath("kdedir");
00261 
00262     foreach(ple,processList.list()) 
00263     {
00264         if (ple->path.toLower().startsWith(installPrefix.toLower())) 
00265         {
00266             if (verbose)
00267                 fprintf(stderr,"terminating path: %s name: %s pid: %u\n", ple->path.toLatin1().data(), ple->name.toLatin1().data(), ple->pid);
00268             processList.terminateProcess(ple->name);
00269         }
00270     }
00271 }
00272 
00273 void listAllNamedAppsInDBus()
00274 {
00275     QDBusConnection connection = QDBusConnection::sessionBus();
00276     QDBusConnectionInterface *bus = connection.interface();
00277     const QStringList services = bus->registeredServiceNames();
00278     foreach(const QString &service, services) {
00279         if (service.startsWith("org.freedesktop.DBus") || service.startsWith(':'))
00280             continue;
00281         fprintf(stderr, "%s \n", service.toLatin1().data());
00282     }
00283 }
00284 
00285 void quitApplicationsOverDBus()
00286 {
00287     QDBusConnection connection = QDBusConnection::sessionBus();
00288     QDBusConnectionInterface *bus = connection.interface();
00289     const QStringList services = bus->registeredServiceNames();
00290     foreach(const QString &service, services) {
00291         if (service.startsWith("org.freedesktop.DBus") || service.startsWith(':'))
00292             continue;
00293         QDBusInterface *iface = new QDBusInterface(service,
00294                                QLatin1String("/MainApplication"),
00295 //  see http://lists.kde.org/?l=kde-core-devel&m=121641642911291&w=2
00296 #if QT_VERSION < 0x040402
00297                                QLatin1String(""),
00298 #else                             
00299                                QLatin1String("org.kde.KApplication"),
00300 #endif
00301                                connection);
00302         if (!iface->isValid()) {
00303             if (verbose)
00304                 fprintf(stderr, "invalid interface of service %s\n", service.toLatin1().data());
00305             continue;
00306         }
00307         iface->call("quit");
00308         if (iface->lastError().isValid()) {
00309             if (verbose)
00310                 fprintf(stderr,"killing %s with result\n", iface->lastError().message().toLatin1().data());
00311         }
00312         delete iface;
00313     }
00314 }
00315 
00316 int main(int argc, char **argv, char **envp)
00317 {
00318     pid_t pid = 0;
00319     bool launch_dbus = true;
00320     bool launch_klauncher = true;
00321     bool launch_kded = true;
00322     bool suicide = false;
00323     bool listProcesses = false;
00324     bool killProcesses = false;
00325     bool listAppsInDBus = false;
00326     bool quitAppsOverDBus = false;
00327     bool shutdown = false;
00328 
00330     char **safe_argv = (char **) malloc( sizeof(char *) * argc);
00331     for(int i = 0; i < argc; i++)
00332     {
00333         safe_argv[i] = strcpy((char*)malloc(strlen(argv[i])+1), argv[i]);
00334         if (strcmp(safe_argv[i], "--no-dbus") == 0)
00335             launch_dbus = false;
00336         if (strcmp(safe_argv[i], "--no-klauncher") == 0)
00337             launch_klauncher = false;
00338         if (strcmp(safe_argv[i], "--no-kded") == 0)
00339             launch_kded = false;
00340         if (strcmp(safe_argv[i], "--suicide") == 0)
00341             suicide = true;
00342 #ifdef ENABLE_EXIT
00343         if (strcmp(safe_argv[i], "--exit") == 0)
00344             keep_running = 0;
00345 #endif            
00346         if (strcmp(safe_argv[i], "--verbose") == 0)
00347             verbose = 1;
00348         if (strcmp(safe_argv[i], "--version") == 0) 
00349         { 
00350             printf("Qt: %s\n",qVersion()); 
00351             printf("KDE: %s\n", KDE_VERSION_STRING); 
00352             exit(0);
00353         } 
00354         if (strcmp(safe_argv[i], "--help") == 0)
00355         {
00356            printf("Usage: kdeinit4 [options]\n");
00357 #ifdef ENABLE_EXIT
00358            printf("   --exit                     Terminate when kded has run\n");
00359 #endif
00360            printf("   --help                     this help page\n");
00361            printf("   --list                     list kde processes\n");
00362            printf("   --list-dbus-apps           list all applications registered in dbus\n");
00363            printf("   --quit-over-dbus           quit all application registered in dbus\n");
00364            printf("   --no-dbus                  do not start dbus-daemon\n");
00365            printf("   --no-klauncher             do not start klauncher\n");
00366            printf("   --no-kded                  do not start kded\n");
00367            printf("   --shutdown                 safe shutdown of all running kde processes\n");
00368            printf("                              first over dbus, then using hard kill\n");
00369 #ifdef ENABLE_SUICIDE
00370            printf("    --suicide                 terminate when no KDE applications are left running\n");
00371 #endif
00372            printf("   --terminate                hard kill of *all* running kde processes\n");
00373            printf("   --verbose                  print verbose messages\n");
00374        printf("   --version                  Show version information\n");
00375            exit(0);
00376         }
00377         if (strcmp(safe_argv[i], "--list") == 0)
00378             listProcesses = true;
00379         if (strcmp(safe_argv[i], "--shutdown") == 0)
00380             shutdown = true;
00381         if (strcmp(safe_argv[i], "--terminate") == 0 || strcmp(safe_argv[i], "--kill") == 0)
00382             killProcesses = true;
00383         if (strcmp(safe_argv[i], "--list-dbus-apps") == 0)
00384             listAppsInDBus = true;
00385         if (strcmp(safe_argv[i], "--quit-over-dbus") == 0)
00386             quitAppsOverDBus = true;
00387     }
00388 
00389     ProcessList processList;
00390 
00391     if (listProcesses) {
00392         listAllRunningKDEProcesses(processList);
00393         return 0;
00394     }
00395     else if (killProcesses) {
00396         terminateAllRunningKDEProcesses(processList);
00397         return 0;
00398     }
00399     else if (listAppsInDBus) {
00400         listAllNamedAppsInDBus();
00401         return 0;
00402     }
00403     else if (quitAppsOverDBus) {
00404         quitApplicationsOverDBus();
00405         return 0;
00406     }
00407     else if (shutdown) {
00408         quitApplicationsOverDBus();
00409         Sleep(2000);
00410         terminateAllRunningKDEProcesses(processList);
00411     }
00412     
00414     s_instance = new KComponentData("kdeinit4", QByteArray(), KComponentData::SkipMainComponentRegistration);
00415 
00416 #ifdef _DEBUG
00417     // first try to launch dbus-daemond in debug mode
00418     if (launch_dbus && processList.hasProcessInList("dbus-daemond"))
00419           launch_dbus = false;
00420     if (launch_dbus)
00421     {
00422           pid = launch("dbus-launchd.exe");
00423           if (!pid)
00424               pid = launch("dbus-launchd.bat");
00425           launch_dbus = (pid == 0);
00426     }
00427 #endif
00428     if (launch_dbus && !processList.hasProcessInList("dbus-daemon"))
00429     {
00430           if (!pid)
00431               pid = launch("dbus-launch.exe");
00432           if (!pid)
00433               pid = launch("dbus-launch.bat");
00434           if (!pid)
00435               exit(1);
00436     }
00437 
00438     if (launch_klauncher && !processList.hasProcessInList("klauncher"))
00439     {
00440           pid = launch("klauncher");
00441           if (!pid || !checkIfRegisteredInDBus("org.kde.klauncher",10))
00442               exit(1);
00443     }
00444 
00445 
00446     if (launch_kded && !processList.hasProcessInList(KDED_EXENAME))
00447     {
00448         pid = launch(KDED_EXENAME);
00449         if (!pid || !checkIfRegisteredInDBus("org.kde.kded",10))
00450             exit(1);
00451     }
00452 
00453     for(int i = 1; i < argc; i++)
00454     {
00455         if (safe_argv[i][0] == '+')
00456         {
00457             pid = launch(safe_argv[i]+1);
00458         }
00459         else if (safe_argv[i][0] == '-')
00460         {
00461             // Ignore
00462         }
00463         else
00464         {
00465             pid = launch( safe_argv[i]);
00466         }
00467     }
00468 
00470     for(int i = 0; i < argc; i++)
00471     {
00472           free(safe_argv[i]);
00473     }
00474     free (safe_argv);
00475 
00477 #ifdef ENABLE_SUICIDE
00478     if (suicide) {
00479         QProcess *proc;
00480         int can_exit=1;
00481         do {
00482            foreach(proc,startedProcesses) {
00483              if (proc->state() != QProcess::NotRunning)
00484                 can_exit = 0;
00485            }
00486            if (!can_exit)
00487              Sleep(2000);
00488         } while(!can_exit);
00489         return 0;
00490     }
00491 #endif    
00492     return 0;
00493 }

KInit

Skip menu "KInit"
  • Main Page
  • 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
  • KPty
  • Kross
  • KUtils
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver
Generated for kdelibs by doxygen 1.6.1
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