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

KDED

kded.cpp

Go to the documentation of this file.
00001 // vim: expandtab sw=4 ts=4
00002 /*  This file is part of the KDE libraries
00003  *  Copyright (C) 1999 David Faure <faure@kde.org>
00004  *  Copyright (C) 2000 Waldo Bastian <bastian@kde.org>
00005  *
00006  *  This library is free software; you can redistribute it and/or
00007  *  modify it under the terms of the GNU Library General Public
00008  *  License version 2 as published by the Free Software Foundation;
00009  *
00010  *  This library is distributed in the hope that it will be useful,
00011  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013  *  Library General Public License for more details.
00014  *
00015  *  You should have received a copy of the GNU Library General Public License
00016  *  along with this library; see the file COPYING.LIB.  If not, write to
00017  *  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00018  *  Boston, MA 02110-1301, USA.
00019  **/
00020 
00021 #include "kded.h"
00022 #include "kdedadaptor.h"
00023 #include "kdedmodule.h"
00024 
00025 #include "kresourcelist.h"
00026 #include <kcrash.h>
00027 
00028 #include <unistd.h>
00029 #include <stdlib.h>
00030 #include <signal.h>
00031 #include <time.h>
00032 
00033 #include <QtCore/QDir>
00034 #include <QtCore/QFile>
00035 #include <QtCore/QTimer>
00036 
00037 #include <QtDBus/QtDBus>
00038 
00039 #include <kuniqueapplication.h>
00040 #include <kapplication.h>
00041 #include <kcmdlineargs.h>
00042 #include <kaboutdata.h>
00043 #include <klocale.h>
00044 #include <kglobal.h>
00045 #include <kconfig.h>
00046 #include <kconfiggroup.h>
00047 #include <kdebug.h>
00048 #include <kdirwatch.h>
00049 #include <kstandarddirs.h>
00050 #include <kservicetypetrader.h>
00051 #include <ktoolinvocation.h>
00052 #include <kde_file.h>
00053 #include "klauncher_iface.h"
00054 
00055 #ifdef Q_WS_X11
00056 #include <qx11info_x11.h>
00057 #include <X11/Xlib.h>
00058 #include <fixx11h.h>
00059 #endif
00060 
00061 #define KDED_EXENAME "kded4"
00062 
00063 #define MODULES_PATH "/modules/"
00064 
00065 Kded *Kded::_self = 0;
00066 
00067 static bool checkStamps = true;
00068 static bool delayedCheck = false;
00069 
00070 extern QDBUS_EXPORT void qDBusAddSpyHook(void (*)(const QDBusMessage&));
00071 
00072 static void runBuildSycoca(QObject *callBackObj=0, const char *callBackSlot=0)
00073 {
00074    const QString exe = KStandardDirs::findExe(KBUILDSYCOCA_EXENAME);
00075    Q_ASSERT(!exe.isEmpty());
00076    QStringList args;
00077    args.append("--incremental");
00078    if(checkStamps)
00079       args.append("--checkstamps");
00080    if(delayedCheck)
00081       args.append("--nocheckfiles");
00082    else
00083       checkStamps = false; // useful only during kded startup
00084    if (callBackObj)
00085    {
00086       QVariantList argList;
00087       argList << exe << args << QStringList() << QString();
00088       KToolInvocation::klauncher()->callWithCallback("kdeinit_exec_wait", argList, callBackObj,
00089                                                          callBackSlot);
00090    }
00091    else
00092    {
00093       KToolInvocation::kdeinitExecWait( exe, args );
00094    }
00095 }
00096 
00097 static void runKonfUpdate()
00098 {
00099    KToolInvocation::kdeinitExecWait( "kconf_update", QStringList(), 0, 0, "0" /*no startup notification*/ );
00100 }
00101 
00102 static void runDontChangeHostname(const QByteArray &oldName, const QByteArray &newName)
00103 {
00104    QStringList args;
00105    args.append(QFile::decodeName(oldName));
00106    args.append(QFile::decodeName(newName));
00107    KToolInvocation::kdeinitExecWait( "kdontchangethehostname", args );
00108 }
00109 
00110 Kded::Kded(bool checkUpdates)
00111   : b_checkUpdates(checkUpdates),
00112     m_needDelayedCheck(false)
00113 {
00114   _self = this;
00115 
00116   new KBuildsycocaAdaptor(this);
00117   new KdedAdaptor(this);
00118 
00119   QDBusConnection session = QDBusConnection::sessionBus();
00120   session.registerObject("/kbuildsycoca", this);
00121   session.registerObject("/kded", this);
00122 
00123   qDBusAddSpyHook(messageFilter);
00124 
00125   m_pTimer = new QTimer(this);
00126   m_pTimer->setSingleShot( true );
00127   connect(m_pTimer, SIGNAL(timeout()), this, SLOT(recreate()));
00128 
00129   m_pDirWatch = 0;
00130 
00131   m_recreateCount = 0;
00132   m_recreateBusy = false;
00133 }
00134 
00135 Kded::~Kded()
00136 {
00137   _self = 0;
00138   m_pTimer->stop();
00139   delete m_pTimer;
00140   delete m_pDirWatch;
00141 
00142   for (QHash<QByteArray,KDEDModule*>::iterator
00143            it(m_modules.begin()), itEnd(m_modules.end());
00144        it != itEnd; ++it)
00145   {
00146       KDEDModule* module(it.value());
00147 
00148       // first disconnect otherwise slotKDEDModuleRemoved() is called
00149       // and changes m_modules while we're iterating over it
00150       disconnect(module, SIGNAL(moduleDeleted(KDEDModule*)),
00151                  this, SLOT(slotKDEDModuleRemoved(KDEDModule*)));
00152 
00153       delete module;
00154   }
00155 }
00156 
00157 // on-demand module loading
00158 // this function is called by the D-Bus message processing function before
00159 // calls are delivered to objects
00160 void Kded::messageFilter(const QDBusMessage &message)
00161 {
00162   if (message.type() != QDBusMessage::MethodCallMessage)
00163      return;
00164 
00165   QString obj = message.path();
00166   if (!obj.startsWith(MODULES_PATH))
00167      return;
00168 
00169   obj = obj.mid(strlen(MODULES_PATH));
00170   if (obj == "ksycoca")
00171      return; // Ignore this one.
00172 
00173   if (self()->m_dontLoad.value(obj, 0))
00174      return;
00175 
00176   KDEDModule *module = self()->loadModule(obj, true);
00177   Q_UNUSED(module);
00178 }
00179 
00180 void Kded::initModules()
00181 {
00182      m_dontLoad.clear();
00183      bool kde_running = !qgetenv( "KDE_FULL_SESSION" ).isEmpty();
00184     // not the same user like the one running the session (most likely we're run via sudo or something)
00185     const QByteArray sessionUID = qgetenv( "KDE_SESSION_UID" );
00186     if( !sessionUID.isEmpty() && uid_t( sessionUID.toInt() ) != getuid())
00187         kde_running = false;
00188      // Preload kded modules.
00189      KService::List kdedModules = KServiceTypeTrader::self()->query("KDEDModule");
00190      for(KService::List::ConstIterator it = kdedModules.begin(); it != kdedModules.end(); ++it)
00191      {
00192          KService::Ptr service = *it;
00193          // Should the the service load on startup?
00194          bool autoload = isModuleAutoloaded(service);
00195 
00196          // see ksmserver's README for description of the phases
00197          QVariant phasev = service->property("X-KDE-Kded-phase", QVariant::Int );
00198          int phase = phasev.isValid() ? phasev.toInt() : 2;
00199          bool prevent_autoload = false;
00200          switch( phase )
00201          {
00202              case 0: // always autoload
00203                  break;
00204              case 1: // autoload only in KDE
00205                  if( !kde_running )
00206                      prevent_autoload = true;
00207                  break;
00208              case 2: // autoload delayed, only in KDE
00209              default:
00210                  prevent_autoload = true;
00211                  break;
00212          }
00213 
00214         // Load the module if necessary and allowed
00215          if (autoload && !prevent_autoload)
00216             loadModule(service, false);
00217 
00218          // Remember if the module is allowed to load on demand
00219          bool loadOnDemand = isModuleLoadedOnDemand(service);
00220          if (!loadOnDemand)
00221             noDemandLoad(service->desktopEntryName());
00222 
00223          // In case of reloading the configuration it is possible for a module
00224          // to run even if it is now allowed to. Stop it then.
00225          if (!loadOnDemand && !autoload)
00226             unloadModule(service->desktopEntryName().toLatin1());
00227      }
00228 }
00229 
00230 void Kded::loadSecondPhase()
00231 {
00232      kDebug(7020) << "Loading second phase autoload";
00233      KSharedConfig::Ptr config = KGlobal::config();
00234      KService::List kdedModules = KServiceTypeTrader::self()->query("KDEDModule");
00235      for(KService::List::ConstIterator it = kdedModules.begin(); it != kdedModules.end(); ++it)
00236      {
00237          KService::Ptr service = *it;
00238          bool autoload = service->property("X-KDE-Kded-autoload", QVariant::Bool).toBool();
00239          KConfigGroup cg(config, QString("Module-%1").arg(service->desktopEntryName()));
00240          autoload = cg.readEntry("autoload", autoload);
00241          QVariant phasev = service->property("X-KDE-Kded-phase", QVariant::Int );
00242          int phase = phasev.isValid() ? phasev.toInt() : 2;
00243          if( phase == 2 && autoload )
00244             loadModule(service, false);
00245      }
00246 }
00247 
00248 void Kded::noDemandLoad(const QString &obj)
00249 {
00250   m_dontLoad.insert(obj.toLatin1(), this);
00251 }
00252 
00253 void Kded::setModuleAutoloading(const QString &obj, bool autoload)
00254 {
00255     KSharedConfig::Ptr config = KGlobal::config();
00256     // Ensure the service exists.
00257     KService::Ptr service = KService::serviceByDesktopPath("kded/"+obj+".desktop");
00258     if (!service) 
00259         return;
00260     KConfigGroup cg(config, QString("Module-%1").arg(service->desktopEntryName()));
00261     cg.writeEntry("autoload", autoload);
00262     cg.sync();
00263 }
00264 
00265 bool Kded::isModuleAutoloaded(const QString &obj) const
00266 {
00267     KService::Ptr s = KService::serviceByDesktopPath("kded/"+obj+".desktop");
00268     if (!s) 
00269         return false;
00270     return isModuleAutoloaded(s);
00271 }
00272 
00273 bool Kded::isModuleAutoloaded(const KService::Ptr &module) const
00274 {
00275     KSharedConfig::Ptr config = KGlobal::config();
00276     bool autoload = module->property("X-KDE-Kded-autoload", QVariant::Bool).toBool();
00277     KConfigGroup cg(config, QString("Module-%1").arg(module->desktopEntryName()));
00278     autoload = cg.readEntry("autoload", autoload);
00279     return autoload;
00280 }
00281 
00282 bool Kded::isModuleLoadedOnDemand(const QString &obj) const
00283 {
00284     KService::Ptr s = KService::serviceByDesktopPath("kded/"+obj+".desktop");
00285     if (!s) 
00286         return false;
00287     return isModuleLoadedOnDemand(s);
00288 }
00289 
00290 bool Kded::isModuleLoadedOnDemand(const KService::Ptr &module) const
00291 {
00292     KSharedConfig::Ptr config = KGlobal::config();
00293     bool loadOnDemand = true;
00294     QVariant p = module->property("X-KDE-Kded-load-on-demand", QVariant::Bool);
00295     if (p.isValid() && (p.toBool() == false))
00296         loadOnDemand = false;
00297     return loadOnDemand;
00298 }
00299 
00300 KDEDModule *Kded::loadModule(const QString &obj, bool onDemand)
00301 {
00302   KDEDModule *module = m_modules.value(obj, 0);
00303   if (module)
00304      return module;
00305   KService::Ptr s = KService::serviceByDesktopPath("kded/"+obj+".desktop");
00306   return loadModule(s, onDemand);
00307 }
00308 
00309 KDEDModule *Kded::loadModule(const KService::Ptr& s, bool onDemand)
00310 {
00311     if (s && !s->library().isEmpty())
00312     {
00313         QString obj = s->desktopEntryName();
00314         KDEDModule *oldModule = m_modules.value(obj, 0);
00315         if (oldModule)
00316             return oldModule;
00317 
00318         if (onDemand)
00319         {
00320             QVariant p = s->property("X-KDE-Kded-load-on-demand", QVariant::Bool);
00321             if (p.isValid() && (p.toBool() == false))
00322             {
00323                 noDemandLoad(s->desktopEntryName());
00324                 return 0;
00325             }
00326         }
00327 
00328         KDEDModule *module = 0;
00329         QString libname = "kded_"+s->library();
00330         KPluginLoader loader(libname);
00331 
00332         KPluginFactory *factory = loader.factory();
00333         if (!factory) {
00334             // kde3 compat
00335             QString factoryName = s->property("X-KDE-FactoryName", QVariant::String).toString();
00336             if (factoryName.isEmpty())
00337                 factoryName = s->library();
00338             factoryName = "create_" + factoryName;
00339             KLibrary* lib = KLibLoader::self()->library(libname);
00340             KDEDModule* (*create)();
00341             if (lib) {
00342                 create = (KDEDModule* (*)())lib->resolveFunction(QFile::encodeName(factoryName));
00343                 if (create)
00344                     module = create();
00345             }
00346             if (!module) {
00347                 kWarning() << "Could not load library" << libname << ". ["
00348                            << loader.errorString() << "]";
00349             }
00350         } else {
00351             // create the module
00352             module = factory->create<KDEDModule>(this);
00353         }
00354         if (module) {
00355             module->setModuleName(obj);
00356             m_modules.insert(obj, module);
00357             //m_libs.insert(obj, lib);
00358             connect(module, SIGNAL(moduleDeleted(KDEDModule *)), SLOT(slotKDEDModuleRemoved(KDEDModule *)));
00359             kDebug(7020) << "Successfully loaded module" << obj;
00360             return module;
00361         } else {
00362             kDebug(7020) << "Could not load module" << obj;
00363             //loader.unload();
00364         }
00365     }
00366     return 0;
00367 }
00368 
00369 bool Kded::unloadModule(const QString &obj)
00370 {
00371   KDEDModule *module = m_modules.value(obj, 0);
00372   if (!module)
00373      return false;
00374   kDebug(7020) << "Unloading module" << obj;
00375   m_modules.remove(obj);
00376   delete module;
00377   return true;
00378 }
00379 
00380 QStringList Kded::loadedModules()
00381 {
00382     return m_modules.keys();
00383 }
00384 
00385 void Kded::slotKDEDModuleRemoved(KDEDModule *module)
00386 {
00387   m_modules.remove(module->moduleName());
00388   //KLibrary *lib = m_libs.take(module->moduleName());
00389   //if (lib)
00390   //   lib->unload();
00391 }
00392 
00393 void Kded::slotApplicationRemoved(const QString &name, const QString &oldOwner,
00394                                   const QString &newOwner)
00395 {
00396 #if 0 // see kdedmodule.cpp (KDED_OBJECTS)
00397   foreach( KDEDModule* module, m_modules )
00398   {
00399      module->removeAll(appId);
00400   }
00401 #endif
00402   if (oldOwner.isEmpty() || !newOwner.isEmpty())
00403      return;
00404 
00405   const QList<qlonglong> windowIds = m_windowIdList.value(name);
00406   for( QList<qlonglong>::ConstIterator it = windowIds.begin();
00407        it != windowIds.end(); ++it)
00408   {
00409       qlonglong windowId = *it;
00410       m_globalWindowIdList.remove(windowId);
00411       foreach( KDEDModule* module, m_modules )
00412       {
00413           emit module->windowUnregistered(windowId);
00414       }
00415   }
00416   m_windowIdList.remove(name);
00417 }
00418 
00419 void Kded::updateDirWatch()
00420 {
00421   if (!b_checkUpdates) return;
00422 
00423   delete m_pDirWatch;
00424   m_pDirWatch = new KDirWatch;
00425 
00426   QObject::connect( m_pDirWatch, SIGNAL(dirty(const QString&)),
00427            this, SLOT(update(const QString&)));
00428   QObject::connect( m_pDirWatch, SIGNAL(created(const QString&)),
00429            this, SLOT(update(const QString&)));
00430   QObject::connect( m_pDirWatch, SIGNAL(deleted(const QString&)),
00431            this, SLOT(dirDeleted(const QString&)));
00432 
00433   // For each resource
00434   for( QStringList::ConstIterator it = m_allResourceDirs.begin();
00435        it != m_allResourceDirs.end();
00436        ++it )
00437   {
00438      readDirectory( *it );
00439   }
00440 }
00441 
00442 void Kded::updateResourceList()
00443 {
00444   delete KSycoca::self();
00445 
00446   if (!b_checkUpdates) return;
00447 
00448   if (delayedCheck) return;
00449 
00450   const QStringList dirs = KSycoca::self()->allResourceDirs();
00451   // For each resource
00452   for( QStringList::ConstIterator it = dirs.begin();
00453        it != dirs.end();
00454        ++it )
00455   {
00456      if (!m_allResourceDirs.contains(*it))
00457      {
00458         m_allResourceDirs.append(*it);
00459         readDirectory(*it);
00460      }
00461   }
00462 }
00463 
00464 void Kded::recreate()
00465 {
00466    recreate(false);
00467 }
00468 
00469 void Kded::runDelayedCheck()
00470 {
00471    if( m_needDelayedCheck )
00472       recreate(false);
00473    m_needDelayedCheck = false;
00474 }
00475 
00476 void Kded::recreate(bool initial)
00477 {
00478    m_recreateBusy = true;
00479    // Using KLauncher here is difficult since we might not have a
00480    // database
00481 
00482    if (!initial)
00483    {
00484       updateDirWatch(); // Update tree first, to be sure to miss nothing.
00485       runBuildSycoca(this, SLOT(recreateDone()));
00486    }
00487    else
00488    {
00489       if(!delayedCheck)
00490          updateDirWatch(); // this would search all the directories
00491       runBuildSycoca();
00492       recreateDone();
00493       if(delayedCheck)
00494       {
00495          // do a proper ksycoca check after a delay
00496          QTimer::singleShot( 60000, this, SLOT(runDelayedCheck()));
00497          m_needDelayedCheck = true;
00498          delayedCheck = false;
00499       }
00500       else
00501          m_needDelayedCheck = false;
00502    }
00503 }
00504 
00505 void Kded::recreateDone()
00506 {
00507    updateResourceList();
00508 
00509    for(; m_recreateCount; m_recreateCount--)
00510    {
00511       QDBusMessage msg = m_recreateRequests.takeFirst();
00512       QDBusConnection::sessionBus().send(msg.createReply());
00513    }
00514    m_recreateBusy = false;
00515 
00516    // Did a new request come in while building?
00517    if (!m_recreateRequests.isEmpty())
00518    {
00519       m_pTimer->start(2000);
00520       m_recreateCount = m_recreateRequests.count();
00521    }
00522 }
00523 
00524 void Kded::dirDeleted(const QString& path)
00525 {
00526   update(path);
00527 }
00528 
00529 void Kded::update(const QString& )
00530 {
00531   if (!m_recreateBusy)
00532   {
00533     m_pTimer->start( 10000 );
00534   }
00535 }
00536 
00537 void Kded::recreate(const QDBusMessage &msg)
00538 {
00539    if (!m_recreateBusy)
00540    {
00541       if (m_recreateRequests.isEmpty())
00542       {
00543          m_pTimer->start(0);
00544          m_recreateCount = 0;
00545       }
00546       m_recreateCount++;
00547    }
00548    msg.setDelayedReply(true);
00549    m_recreateRequests.append(msg);
00550    return;
00551 }
00552 
00553 
00554 void Kded::readDirectory( const QString& _path )
00555 {
00556   QString path( _path );
00557   if ( !path.endsWith( '/' ) )
00558     path += '/';
00559 
00560   if ( m_pDirWatch->contains( path ) ) // Already seen this one?
00561      return;
00562 
00563   m_pDirWatch->addDir(path,KDirWatch::WatchFiles|KDirWatch::WatchSubDirs);          // add watch on this dir
00564   return; // KDirWatch now claims to also support recursive watching
00565 #if 0
00566   QDir d( _path, QString(), QDir::Unsorted, QDir::Readable | QDir::Executable | QDir::Dirs | QDir::Hidden );
00567   // set QDir ...
00568 
00569 
00570   //************************************************************************
00571   //                           Setting dirs
00572   //************************************************************************
00573 
00574   if ( !d.exists() )                            // exists&isdir?
00575   {
00576     kDebug(7020) << "Does not exist:" << _path;
00577     return;                             // return false
00578   }
00579 
00580   // Note: If some directory is gone, dirwatch will delete it from the list.
00581 
00582   //************************************************************************
00583   //                               Reading
00584   //************************************************************************
00585   QString file;
00586   unsigned int i;                           // counter and string length.
00587   unsigned int count = d.count();
00588   for( i = 0; i < count; i++ )                        // check all entries
00589   {
00590      if (d[i] == "." || d[i] == ".." || d[i] == "magic")
00591        continue;                          // discard those ".", "..", "magic"...
00592 
00593      file = path;                           // set full path
00594      file += d[i];                          // and add the file name.
00595 
00596      readDirectory( file );      // yes, dive into it.
00597   }
00598 #endif
00599 }
00600 
00601 /*
00602 bool Kded::isWindowRegistered(long windowId) const
00603 {
00604   return m_globalWindowIdList.contains(windowId);
00605 
00606 }
00607 */
00608 
00609 void Kded::registerWindowId(qlonglong windowId, const QString &sender)
00610 {
00611   m_globalWindowIdList.insert(windowId);
00612   QList<qlonglong> windowIds = m_windowIdList.value(sender);
00613   windowIds.append(windowId);
00614   m_windowIdList.insert(sender, windowIds);
00615 
00616   foreach( KDEDModule* module, m_modules )
00617   {
00618      emit module->windowRegistered(windowId);
00619   }
00620 }
00621 
00622 void Kded::unregisterWindowId(qlonglong windowId, const QString &sender)
00623 {
00624   m_globalWindowIdList.remove(windowId);
00625   QList<qlonglong> windowIds = m_windowIdList.value(sender);
00626   if (!windowIds.isEmpty())
00627   {
00628      windowIds.removeAll(windowId);
00629      if (windowIds.isEmpty())
00630         m_windowIdList.remove(sender);
00631      else
00632         m_windowIdList.insert(sender, windowIds);
00633   }
00634 
00635   foreach( KDEDModule* module, m_modules )
00636   {
00637     emit module->windowUnregistered(windowId);
00638   }
00639 }
00640 
00641 
00642 static void sighandler(int /*sig*/)
00643 {
00644     if (qApp)
00645        qApp->quit();
00646 }
00647 
00648 KUpdateD::KUpdateD()
00649 {
00650     m_pDirWatch = new KDirWatch;
00651     m_pTimer = new QTimer;
00652     m_pTimer->setSingleShot( true );
00653     connect(m_pTimer, SIGNAL(timeout()), this, SLOT(runKonfUpdate()));
00654     QObject::connect( m_pDirWatch, SIGNAL(dirty(const QString&)),
00655            this, SLOT(slotNewUpdateFile()));
00656 
00657     QStringList dirs = KGlobal::dirs()->findDirs("data", "kconf_update");
00658     for( QStringList::ConstIterator it = dirs.begin();
00659          it != dirs.end();
00660          ++it )
00661     {
00662        QString path = *it;
00663        if (path[path.length()-1] != '/')
00664           path += '/';
00665 
00666        if (!m_pDirWatch->contains(path))
00667           m_pDirWatch->addDir(path,KDirWatch::WatchFiles|KDirWatch::WatchSubDirs);
00668     }
00669 }
00670 
00671 KUpdateD::~KUpdateD()
00672 {
00673     delete m_pDirWatch;
00674     delete m_pTimer;
00675 }
00676 
00677 void KUpdateD::runKonfUpdate()
00678 {
00679     ::runKonfUpdate();
00680 }
00681 
00682 void KUpdateD::slotNewUpdateFile()
00683 {
00684     m_pTimer->start( 500 );
00685 }
00686 
00687 KHostnameD::KHostnameD(int pollInterval)
00688 {
00689     m_Timer.start(pollInterval); // repetitive timer (not single-shot)
00690     connect(&m_Timer, SIGNAL(timeout()), this, SLOT(checkHostname()));
00691     checkHostname();
00692 }
00693 
00694 KHostnameD::~KHostnameD()
00695 {
00696     // Empty
00697 }
00698 
00699 void KHostnameD::checkHostname()
00700 {
00701     char buf[1024+1];
00702     if (gethostname(buf, 1024) != 0)
00703        return;
00704     buf[sizeof(buf)-1] = '\0';
00705 
00706     if (m_hostname.isEmpty())
00707     {
00708        m_hostname = buf;
00709        return;
00710     }
00711 
00712     if (m_hostname == buf)
00713        return;
00714 
00715     QByteArray newHostname = buf;
00716 
00717     runDontChangeHostname(m_hostname, newHostname);
00718     m_hostname = newHostname;
00719 }
00720 
00721 
00722 #if 0
00723 // Thiago: I have no idea what the following class is here for
00724 // David: the commit log was:
00725 //       Disable DCOP-Qt bridge but make sure that "dcopquit kded" continues to work.
00726 //       (see the setQtBridgeEnabled below)
00727 class KDEDQtDCOPObject : public DCOPObject
00728 {
00729 public:
00730   KDEDQtDCOPObject() : DCOPObject("qt/kded") { }
00731 
00732   virtual bool process(const DCOPCString &fun, const QByteArray &data,
00733                        DCOPCString& replyType, QByteArray &replyData)
00734     {
00735       if (qApp && (fun == "quit()"))
00736       {
00737         qApp->quit();
00738         replyType = "void";
00739         return true;
00740       }
00741       return DCOPObject::process(fun, data, replyType, replyData);
00742     }
00743 
00744   DCOPCStringList functions()
00745     {
00746        DCOPCStringList res = DCOPObject::functions();
00747        res += "void quit()";
00748        return res;
00749     }
00750 };
00751 #endif
00752 
00753 KBuildsycocaAdaptor::KBuildsycocaAdaptor(QObject *parent)
00754    : QDBusAbstractAdaptor(parent)
00755 {
00756 }
00757 
00758 void KBuildsycocaAdaptor::recreate(const QDBusMessage &msg)
00759 {
00760    Kded::self()->recreate(msg);
00761 }
00762 
00763 class KDEDApplication : public KUniqueApplication
00764 {
00765 public:
00766   KDEDApplication() : KUniqueApplication( )
00767     {
00768        startup = true;
00769     }
00770 
00771   int newInstance()
00772     {
00773        if (startup) {
00774           startup = false;
00775           Kded::self()->initModules();
00776        } else
00777           runBuildSycoca();
00778 
00779        return 0;
00780     }
00781 
00782   bool startup;
00783 };
00784 
00785 extern "C" KDE_EXPORT int kdemain(int argc, char *argv[])
00786 {
00787      KAboutData aboutData( "kded" /*don't change this one to kded4! dbus registration should be org.kde.kded etc.*/,
00788         "kdelibs4", ki18n("KDE Daemon"),
00789         "$Id: kded.cpp 833971 2008-07-17 18:27:59Z mjansen $",
00790         ki18n("KDE Daemon - triggers Sycoca database updates when needed"));
00791 
00792      KCmdLineOptions options;
00793      options.add("check", ki18n("Check Sycoca database only once"));
00794 
00795      KCmdLineArgs::init(argc, argv, &aboutData);
00796 
00797      KUniqueApplication::addCmdLineOptions();
00798 
00799      KCmdLineArgs::addCmdLineOptions( options );
00800 
00801      // WABA: Make sure not to enable session management.
00802      putenv(strdup("SESSION_MANAGER="));
00803 
00804      // Parse command line before checking DCOP
00805      KCmdLineArgs *args = KCmdLineArgs::parsedArgs();
00806 
00807      KComponentData componentData(&aboutData);
00808      KSharedConfig::Ptr config = componentData.config(); // Enable translations.
00809 
00810      KConfigGroup cg(config, "General");
00811      if (args->isSet("check"))
00812      {
00813         // KUniqueApplication not wanted here.
00814         KApplication app;
00815         checkStamps = cg.readEntry("CheckFileStamps", true);
00816         runBuildSycoca();
00817         runKonfUpdate();
00818         return 0;
00819      }
00820 
00821      if (!KUniqueApplication::start())
00822      {
00823         fprintf(stderr, "KDE Daemon (kded) already running.\n");
00824         return 0;
00825      }
00826 
00827      // Thiago: reenable if such a thing exists in QtDBus in the future
00828      //KUniqueApplication::dcopClient()->setQtBridgeEnabled(false);
00829 
00830      int HostnamePollInterval = cg.readEntry("HostnamePollInterval", 5000);
00831      bool bCheckSycoca = cg.readEntry("CheckSycoca", true);
00832      bool bCheckUpdates = cg.readEntry("CheckUpdates", true);
00833      bool bCheckHostname = cg.readEntry("CheckHostname", true);
00834      checkStamps = cg.readEntry("CheckFileStamps", true);
00835      delayedCheck = cg.readEntry("DelayedCheck", false);
00836 
00837      Kded *kded = new Kded(bCheckSycoca); // Build data base
00838 
00839      KDE_signal(SIGTERM, sighandler);
00840      KDE_signal(SIGHUP, sighandler);
00841      KDEDApplication k;
00842      k.setQuitOnLastWindowClosed(false);
00843 
00844      KCrash::setFlags(KCrash::AutoRestart);
00845 
00846      // Not sure why kded is created before KDEDApplication
00847      // but if it has to be, then it needs to be moved to the main thread
00848      // before it can use timers (DF)
00849      kded->moveToThread( k.thread() );
00850 
00851      kded->recreate(true); // initial
00852 
00853      if (bCheckUpdates)
00854         (void) new KUpdateD; // Watch for updates
00855 
00856 #ifdef Q_WS_X11
00857      XEvent e;
00858      e.xclient.type = ClientMessage;
00859      e.xclient.message_type = XInternAtom( QX11Info::display(), "_KDE_SPLASH_PROGRESS", False );
00860      e.xclient.display = QX11Info::display();
00861      e.xclient.window = QX11Info::appRootWindow();
00862      e.xclient.format = 8;
00863      strcpy( e.xclient.data.b, "kded" );
00864      XSendEvent( QX11Info::display(), QX11Info::appRootWindow(), False, SubstructureNotifyMask, &e );
00865 #endif
00866 
00867      runKonfUpdate(); // Run it once.
00868 
00869 #ifdef Q_WS_X11
00870      e.xclient.type = ClientMessage;
00871      e.xclient.message_type = XInternAtom( QX11Info::display(), "_KDE_SPLASH_PROGRESS", False );
00872      e.xclient.display = QX11Info::display();
00873      e.xclient.window = QX11Info::appRootWindow();
00874      e.xclient.format = 8;
00875      strcpy( e.xclient.data.b, "confupdate" );
00876      XSendEvent(