• Skip to content
  • Skip to link menu
Trinity API Reference
  • Trinity API Reference
  • kded
 

kded

kded.cpp
00001 /*  This file is part of the KDE libraries
00002  *  Copyright (C) 1999 David Faure <faure@kde.org>
00003  *  Copyright (C) 2000 Waldo Bastian <bastian@kde.org>
00004  *
00005  *  This library is free software; you can redistribute it and/or
00006  *  modify it under the terms of the GNU Library General Public
00007  *  License version 2 as published by the Free Software Foundation;
00008  *
00009  *  This library is distributed in the hope that it will be useful,
00010  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012  *  Library General Public License for more details.
00013  *
00014  *  You should have received a copy of the GNU Library General Public License
00015  *  along with this library; see the file COPYING.LIB.  If not, write to
00016  *  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00017  *  Boston, MA 02110-1301, USA.
00018  **/
00019 
00020 #include <tqdir.h>
00021 
00022 #include "kded.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 <tqfile.h>
00034 #include <tqtimer.h>
00035 
00036 #include <dcopclient.h>
00037 
00038 #include <kuniqueapplication.h>
00039 #include <tdecmdlineargs.h>
00040 #include <tdeaboutdata.h>
00041 #include <tdelocale.h>
00042 #include <tdeglobal.h>
00043 #include <kprocess.h>
00044 #include <kdebug.h>
00045 #include <kdirwatch.h>
00046 #include <kstandarddirs.h>
00047 #include <kdatastream.h>
00048 #include <tdeio/global.h>
00049 #include <kservicetype.h>
00050 
00051 #ifdef Q_WS_X11
00052 #include <X11/Xlib.h>
00053 #include <fixx11h.h>
00054 #endif
00055 
00056 Kded *Kded::_self = 0;
00057 
00058 static bool checkStamps = true;
00059 static bool delayedCheck = false;
00060 
00061 static void runBuildSycoca(TQObject *callBackObj=0, const char *callBackSlot=0)
00062 {
00063    TQStringList args;
00064    args.append("--incremental");
00065    if(checkStamps)
00066       args.append("--checkstamps");
00067    if(delayedCheck)
00068       args.append("--nocheckfiles");
00069    else
00070       checkStamps = false; // useful only during kded startup
00071    if (callBackObj)
00072    {
00073       TQByteArray data;
00074       TQDataStream dataStream( data, IO_WriteOnly );
00075       dataStream << TQString("tdebuildsycoca") << args;
00076       TQCString _launcher = TDEApplication::launcher();
00077 
00078       kapp->dcopClient()->callAsync(_launcher, _launcher, "tdeinit_exec_wait(TQString,TQStringList)", data, callBackObj, callBackSlot);
00079    }
00080    else
00081    {
00082       TDEApplication::tdeinitExecWait( "tdebuildsycoca", args );
00083    }
00084 }
00085 
00086 static void runKonfUpdate()
00087 {
00088    TDEApplication::tdeinitExecWait( "tdeconf_update", TQStringList(), 0, 0, "0" /*no startup notification*/ );
00089 }
00090 
00091 static void runDontChangeHostname(const TQCString &oldName, const TQCString &newName)
00092 {
00093    TQStringList args;
00094    args.append(TQFile::decodeName(oldName));
00095    args.append(TQFile::decodeName(newName));
00096    TDEApplication::tdeinitExecWait( "kdontchangethehostname", args );
00097 }
00098 
00099 Kded::Kded(bool checkUpdates, bool new_startup)
00100   : DCOPObject("tdebuildsycoca"), DCOPObjectProxy(),
00101     b_checkUpdates(checkUpdates),
00102     m_needDelayedCheck(false),
00103     m_newStartup( new_startup )
00104 {
00105   _self = this;
00106   TQCString cPath;
00107   TQCString tdesycoca_env = getenv("TDESYCOCA");
00108   if (tdesycoca_env.isEmpty())
00109      cPath = TQFile::encodeName(TDEGlobal::dirs()->saveLocation("tmp")+"tdesycoca");
00110   else
00111      cPath = tdesycoca_env;
00112   m_pTimer = new TQTimer(this);
00113   connect(m_pTimer, TQT_SIGNAL(timeout()), this, TQT_SLOT(recreate()));
00114 
00115   TQTimer::singleShot(100, this, TQT_SLOT(installCrashHandler()));
00116 
00117   m_pDirWatch = 0;
00118 
00119   m_windowIdList.setAutoDelete(true);
00120 
00121   m_recreateCount = 0;
00122   m_recreateBusy = false;
00123 }
00124 
00125 Kded::~Kded()
00126 {
00127   _self = 0;
00128   m_pTimer->stop();
00129   delete m_pTimer;
00130   delete m_pDirWatch;
00131   // We have to delete the modules while we're still able to process incoming
00132   // DCOP messages, since modules might make DCOP calls in their destructors.
00133   TQAsciiDictIterator<KDEDModule> it(m_modules);
00134   while (!it.isEmpty()) 
00135     delete it.toFirst();
00136 }
00137 
00138 bool Kded::process(const TQCString &obj, const TQCString &fun,
00139                    const TQByteArray &data,
00140                    TQCString &replyType, TQByteArray &replyData)
00141 {
00142   if (obj == "tdesycoca") return false; // Ignore this one.
00143 
00144   if (m_dontLoad[obj])
00145      return false;
00146 
00147   KDEDModule *module = loadModule(obj, true);
00148   if (!module)
00149      return false;
00150 
00151   module->setCallingDcopClient(kapp->dcopClient());
00152   return module->process(fun, data, replyType, replyData);
00153 }
00154 
00155 void Kded::initModules()
00156 {
00157      m_dontLoad.clear();
00158      TDEConfig *config = kapp->config();
00159      bool tde_running = !( getenv( "TDE_FULL_SESSION" ) == NULL || getenv( "TDE_FULL_SESSION" )[ 0 ] == '\0' );
00160     // not the same user like the one running the session (most likely we're run via sudo or something)
00161     if( getenv( "TDE_SESSION_UID" ) != NULL && uid_t( atoi( getenv( "TDE_SESSION_UID" ))) != getuid())
00162         tde_running = false;
00163      // Preload kded modules.
00164      KService::List kdedModules = KServiceType::offers("KDEDModule");
00165      TQString version = getenv( "KDE_SESSION_VERSION" );
00166      TQStringList blacklist;
00167      if ( !(version == NULL) && version >= "4" )
00168      {
00169          kdDebug(7020) << "KDE4 is running:" << endl;
00170          kdDebug(7020) << "  KDE_SESSION_VERSION: " << version << endl;
00171          kdDebug(7020) << "  Blacklisting mediamanager, medianotifier, kmilod, kwrited." << endl;
00172          blacklist << "mediamanager" << "medianotifier" << "kmilod" << "kwrited";
00173      }
00174      for(KService::List::ConstIterator it = kdedModules.begin(); it != kdedModules.end(); ++it)
00175      {
00176          KService::Ptr service = *it;
00177          bool autoload = service->property("X-TDE-Kded-autoload", TQVariant::Bool).toBool();
00178          config->setGroup(TQString("Module-%1").arg(service->desktopEntryName()));
00179          autoload = config->readBoolEntry("autoload", autoload);
00180          for (TQStringList::Iterator module = blacklist.begin(); module != blacklist.end(); ++module)
00181          {
00182             if (service->desktopEntryName() == *module)
00183             {
00184                autoload = false;
00185                break;
00186             }
00187          }
00188          if( m_newStartup )
00189          {
00190             // see ksmserver's README for description of the phases
00191             TQVariant phasev = service->property("X-TDE-Kded-phase", TQVariant::Int );
00192             int phase = phasev.isValid() ? phasev.toInt() : 2;
00193             bool prevent_autoload = false;
00194             switch( phase )
00195             {
00196                 case 0: // always autoload
00197                     break;
00198                 case 1: // autoload only in TDE
00199                     if( !tde_running )
00200                         prevent_autoload = true;
00201                     break;
00202                 case 2: // autoload delayed, only in TDE
00203                 default:
00204                     prevent_autoload = true;
00205                     break;   
00206             }
00207             if (autoload && !prevent_autoload)
00208                loadModule(service, false);
00209          }
00210          else
00211          {
00212             if (autoload && tde_running)
00213                loadModule(service, false);
00214          }
00215          bool dontLoad = false;
00216          TQVariant p = service->property("X-TDE-Kded-load-on-demand", TQVariant::Bool);
00217          if (p.isValid() && (p.toBool() == false))
00218             dontLoad = true;
00219          if (dontLoad)
00220             noDemandLoad(service->desktopEntryName());
00221 
00222          if (dontLoad && !autoload)
00223             unloadModule(service->desktopEntryName().latin1());
00224      }
00225 }
00226 
00227 void Kded::loadSecondPhase()
00228 {
00229      kdDebug(7020) << "Loading second phase autoload" << endl;
00230      TDEConfig *config = kapp->config();
00231      KService::List kdedModules = KServiceType::offers("KDEDModule");
00232      for(KService::List::ConstIterator it = kdedModules.begin(); it != kdedModules.end(); ++it)
00233      {
00234          KService::Ptr service = *it;
00235          bool autoload = service->property("X-TDE-Kded-autoload", TQVariant::Bool).toBool();
00236          config->setGroup(TQString("Module-%1").arg(service->desktopEntryName()));
00237          autoload = config->readBoolEntry("autoload", autoload);
00238          TQVariant phasev = service->property("X-TDE-Kded-phase", TQVariant::Int );
00239          int phase = phasev.isValid() ? phasev.toInt() : 2;
00240          if( phase == 2 && autoload )
00241             loadModule(service, false);
00242      }
00243 }
00244 
00245 void Kded::noDemandLoad(const TQString &obj)
00246 {
00247   m_dontLoad.insert(obj.latin1(), this);
00248 }
00249 
00250 KDEDModule *Kded::loadModule(const TQCString &obj, bool onDemand)
00251 {
00252   KDEDModule *module = m_modules.find(obj);
00253   if (module)
00254      return module;
00255   KService::Ptr s = KService::serviceByDesktopPath("kded/"+obj+".desktop");
00256   return loadModule(s, onDemand);
00257 }
00258 
00259 KDEDModule *Kded::loadModule(const KService *s, bool onDemand)
00260 {
00261   KDEDModule *module = 0;
00262   if (s && !s->library().isEmpty())
00263   {
00264     TQCString obj = s->desktopEntryName().latin1();
00265     KDEDModule *oldModule = m_modules.find(obj);
00266     if (oldModule)
00267        return oldModule;
00268 
00269     if (onDemand)
00270     {
00271       TQVariant p = s->property("X-TDE-Kded-load-on-demand", TQVariant::Bool);
00272       if (p.isValid() && (p.toBool() == false))
00273       {
00274          noDemandLoad(s->desktopEntryName());
00275          return 0;
00276       }
00277     }
00278     // get the library loader instance
00279 
00280     KLibLoader *loader = KLibLoader::self();
00281 
00282     TQVariant v = s->property("X-TDE-FactoryName", TQVariant::String);
00283     TQString factory = v.isValid() ? v.toString() : TQString::null;
00284     if (factory.isEmpty())
00285     {
00286        // Stay bugward compatible
00287        v = s->property("X-TDE-Factory", TQVariant::String);
00288        factory = v.isValid() ? v.toString() : TQString::null;
00289     }
00290     if (factory.isEmpty())
00291       factory = s->library();
00292 
00293     factory = "create_" + factory;
00294     TQString libname = "kded_"+s->library();
00295 
00296     KLibrary *lib = loader->library(TQFile::encodeName(libname));
00297     if (!lib)
00298     {
00299       kdWarning() << k_funcinfo << "Could not load library. [ "
00300           << loader->lastErrorMessage() << " ]" << endl;
00301       libname.prepend("lib");
00302       lib = loader->library(TQFile::encodeName(libname));
00303     }
00304     if (lib)
00305     {
00306       // get the create_ function
00307       void *create = lib->symbol(TQFile::encodeName(factory));
00308 
00309       if (create)
00310       {
00311         // create the module
00312         KDEDModule* (*func)(const TQCString &);
00313         func = (KDEDModule* (*)(const TQCString &)) create;
00314         module = func(obj);
00315         if (module)
00316         {
00317           m_modules.insert(obj, module);
00318           m_libs.insert(obj, lib);
00319           connect(module, TQT_SIGNAL(moduleDeleted(KDEDModule *)), TQT_SLOT(slotKDEDModuleRemoved(KDEDModule *)));
00320           kdDebug(7020) << "Successfully loaded module '" << obj << "'\n";
00321           return module;
00322         }
00323       }
00324       loader->unloadLibrary(TQFile::encodeName(libname));
00325     }
00326     else
00327     {
00328     kdWarning() << k_funcinfo << "Could not load library. [ "
00329             << loader->lastErrorMessage() << " ]" << endl;
00330     }
00331     kdDebug(7020) << "Could not load module '" << obj << "'\n";
00332   }
00333   return 0;
00334 }
00335 
00336 bool Kded::unloadModule(const TQCString &obj)
00337 {
00338   KDEDModule *module = m_modules.take(obj);
00339   if (!module)
00340      return false;
00341   kdDebug(7020) << "Unloading module '" << obj << "'\n";
00342   delete module;
00343   return true;
00344 }
00345 
00346 // DCOP
00347 QCStringList Kded::loadedModules()
00348 {
00349     QCStringList modules;
00350     TQAsciiDictIterator<KDEDModule> it( m_modules );
00351     for ( ; it.current(); ++it)
00352         modules.append( it.currentKey() );
00353 
00354     return modules;
00355 }
00356 
00357 QCStringList Kded::functions()
00358 {
00359     QCStringList res = DCOPObject::functions();
00360     res += "ASYNC recreate()";
00361     return res;
00362 }
00363 
00364 void Kded::slotKDEDModuleRemoved(KDEDModule *module)
00365 {
00366   m_modules.remove(module->objId());
00367   KLibrary *lib = m_libs.take(module->objId());
00368   if (lib)
00369      lib->unload();
00370 }
00371 
00372 void Kded::slotApplicationRemoved(const TQCString &appId)
00373 {
00374   for(TQAsciiDictIterator<KDEDModule> it(m_modules); it.current(); ++it)
00375   {
00376      it.current()->removeAll(appId);
00377   }
00378 
00379   TQValueList<long> *windowIds = m_windowIdList.find(appId);
00380   if (windowIds)
00381   {
00382      for( TQValueList<long>::ConstIterator it = windowIds->begin();
00383           it != windowIds->end(); ++it)
00384      {
00385         long windowId = *it;
00386         m_globalWindowIdList.remove(windowId);
00387         for(TQAsciiDictIterator<KDEDModule> it(m_modules); it.current(); ++it)
00388         {
00389             emit it.current()->windowUnregistered(windowId);
00390         }
00391      }
00392      m_windowIdList.remove(appId);
00393   }
00394 }
00395 
00396 void Kded::updateDirWatch()
00397 {
00398   if (!b_checkUpdates) return;
00399 
00400   delete m_pDirWatch;
00401   m_pDirWatch = new KDirWatch;
00402 
00403   TQObject::connect( m_pDirWatch, TQT_SIGNAL(dirty(const TQString&)),
00404            this, TQT_SLOT(update(const TQString&)));
00405   TQObject::connect( m_pDirWatch, TQT_SIGNAL(created(const TQString&)),
00406            this, TQT_SLOT(update(const TQString&)));
00407   TQObject::connect( m_pDirWatch, TQT_SIGNAL(deleted(const TQString&)),
00408            this, TQT_SLOT(dirDeleted(const TQString&)));
00409 
00410   // For each resource
00411   for( TQStringList::ConstIterator it = m_allResourceDirs.begin();
00412        it != m_allResourceDirs.end();
00413        ++it )
00414   {
00415      readDirectory( *it );
00416   }
00417 }
00418 
00419 void Kded::updateResourceList()
00420 {
00421   delete KSycoca::self();
00422 
00423   if (!b_checkUpdates) return;
00424 
00425   if (delayedCheck) return;
00426 
00427   TQStringList dirs = KSycoca::self()->allResourceDirs();
00428   // For each resource
00429   for( TQStringList::ConstIterator it = dirs.begin();
00430        it != dirs.end();
00431        ++it )
00432   {
00433      if (m_allResourceDirs.find(*it) == m_allResourceDirs.end())
00434      {
00435         m_allResourceDirs.append(*it);
00436         readDirectory(*it);
00437      }
00438   }
00439 }
00440 
00441 void Kded::crashHandler(int)
00442 {
00443    DCOPClient::emergencyClose();
00444    if (_self) { // Don't restart if we were closing down
00445       tqWarning("Last DCOP call before KDED crash was from application '%s'\n"
00446          "to object '%s', function '%s'.",
00447          DCOPClient::postMortemSender(),
00448          DCOPClient::postMortemObject(),
00449          DCOPClient::postMortemFunction());
00450       tqWarning("Restarting KDED...\n");
00451       if (system("kded") < 0) {
00452          tqWarning("Unable to restart KDED!\n");
00453       }
00454    }
00455 }
00456 
00457 void Kded::installCrashHandler()
00458 {
00459    TDECrash::setEmergencySaveFunction(crashHandler);
00460 }
00461 
00462 void Kded::recreate()
00463 {
00464    recreate(false);
00465 }
00466 
00467 void Kded::runDelayedCheck()
00468 {
00469    if( m_needDelayedCheck )
00470       recreate(false);
00471    m_needDelayedCheck = false;
00472 }
00473 
00474 void Kded::recreate(bool initial)
00475 {
00476    m_recreateBusy = true;
00477    // Using TDELauncher here is difficult since we might not have a
00478    // database
00479 
00480    if (!initial)
00481    {
00482       updateDirWatch(); // Update tree first, to be sure to miss nothing.
00483       runBuildSycoca(this, TQT_SLOT(recreateDone()));
00484    }
00485    else
00486    {
00487       if(!delayedCheck)
00488          updateDirWatch(); // this would search all the directories
00489       runBuildSycoca();
00490       recreateDone();
00491       if(delayedCheck)
00492       {
00493          // do a proper tdesycoca check after a delay
00494          TQTimer::singleShot( 60000, this, TQT_SLOT( runDelayedCheck()));
00495          m_needDelayedCheck = true;
00496          delayedCheck = false;
00497       }
00498       else
00499          m_needDelayedCheck = false;
00500    }
00501 }
00502 
00503 void Kded::recreateDone()
00504 {
00505    updateResourceList();
00506 
00507    for(; m_recreateCount; m_recreateCount--)
00508    {
00509       TQCString replyType = "void";
00510       TQByteArray replyData;
00511       DCOPClientTransaction *transaction = m_recreateRequests.first();
00512       if (transaction)
00513          kapp->dcopClient()->endTransaction(transaction, replyType, replyData);
00514       m_recreateRequests.remove(m_recreateRequests.begin());
00515    }
00516    m_recreateBusy = false;
00517 
00518    // Did a new request come in while building?
00519    if (!m_recreateRequests.isEmpty())
00520    {
00521       m_pTimer->start(2000, true /* single shot */ );
00522       m_recreateCount = m_recreateRequests.count();
00523    }
00524 }
00525 
00526 void Kded::dirDeleted(const TQString& path)
00527 {
00528   update(path);
00529 }
00530 
00531 void Kded::update(const TQString& )
00532 {
00533   if (!m_recreateBusy)
00534   {
00535     m_pTimer->start( 2000, true /* single shot */ );
00536   }
00537   else
00538   {
00539     m_recreateRequests.append(0);
00540   }
00541 }
00542 
00543 bool Kded::process(const TQCString &fun, const TQByteArray &data,
00544                            TQCString &replyType, TQByteArray &replyData)
00545 {
00546   if (fun == "recreate()") {
00547     if (!m_recreateBusy)
00548     {
00549        if (m_recreateRequests.isEmpty())
00550        {
00551           m_pTimer->start(0, true /* single shot */ );
00552           m_recreateCount = 0;
00553        }
00554        m_recreateCount++;
00555     }
00556     m_recreateRequests.append(kapp->dcopClient()->beginTransaction());
00557     replyType = "void";
00558     return true;
00559   } else {
00560     return DCOPObject::process(fun, data, replyType, replyData);
00561   }
00562 }
00563 
00564 
00565 void Kded::readDirectory( const TQString& _path )
00566 {
00567   TQString path( _path );
00568   if ( path.right(1) != "/" )
00569     path += "/";
00570 
00571   if ( m_pDirWatch->contains( path ) ) // Already seen this one?
00572      return;
00573 
00574   TQDir d( _path, TQString::null, TQDir::Unsorted, TQDir::Readable | TQDir::Executable | TQDir::Dirs | TQDir::Hidden );
00575   // set TQDir ...
00576 
00577 
00578   //************************************************************************
00579   //                           Setting dirs
00580   //************************************************************************
00581 
00582   m_pDirWatch->addDir(path);          // add watch on this dir
00583 
00584   if ( !d.exists() )                            // exists&isdir?
00585   {
00586     kdDebug(7020) << TQString(TQString("Does not exist! (%1)").arg(_path)) << endl;
00587     return;                             // return false
00588   }
00589 
00590   // Note: If some directory is gone, dirwatch will delete it from the list.
00591 
00592   //************************************************************************
00593   //                               Reading
00594   //************************************************************************
00595   TQString file;
00596   unsigned int i;                           // counter and string length.
00597   unsigned int count = d.count();
00598   for( i = 0; i < count; i++ )                        // check all entries
00599   {
00600      if (d[i] == "." || d[i] == ".." || d[i] == "magic")
00601        continue;                          // discard those ".", "..", "magic"...
00602 
00603      file = path;                           // set full path
00604      file += d[i];                          // and add the file name.
00605 
00606      readDirectory( file );      // yes, dive into it.
00607   }
00608 }
00609 
00610 bool Kded::isWindowRegistered(long windowId)
00611 {
00612   return m_globalWindowIdList.find(windowId) != 0;
00613 
00614 }
00615 
00616 // DCOP
00617 void Kded::registerWindowId(long windowId)
00618 {
00619   m_globalWindowIdList.replace(windowId, &windowId);
00620   TQCString sender = callingDcopClient()->senderId();
00621   if( sender.isEmpty()) // local call
00622       sender = callingDcopClient()->appId();
00623   TQValueList<long> *windowIds = m_windowIdList.find(sender);
00624   if (!windowIds)
00625   {
00626     windowIds = new TQValueList<long>;
00627     m_windowIdList.insert(sender, windowIds);
00628   }
00629   windowIds->append(windowId);
00630 
00631 
00632   for(TQAsciiDictIterator<KDEDModule> it(m_modules); it.current(); ++it)
00633   {
00634      emit it.current()->windowRegistered(windowId);
00635   }
00636 }
00637 
00638 // DCOP
00639 void Kded::unregisterWindowId(long windowId)
00640 {
00641   m_globalWindowIdList.remove(windowId);
00642   TQCString sender = callingDcopClient()->senderId();
00643   if( sender.isEmpty()) // local call
00644       sender = callingDcopClient()->appId();
00645   TQValueList<long> *windowIds = m_windowIdList.find(sender);
00646   if (windowIds)
00647   {
00648      windowIds->remove(windowId);
00649      if (windowIds->isEmpty())
00650         m_windowIdList.remove(sender);
00651   }
00652 
00653   for(TQAsciiDictIterator<KDEDModule> it(m_modules); it.current(); ++it)
00654   {
00655     emit it.current()->windowUnregistered(windowId);
00656   }
00657 }
00658 
00659 
00660 static void sighandler(int /*sig*/)
00661 {
00662     if (kapp)
00663        kapp->quit();
00664 }
00665 
00666 KUpdateD::KUpdateD()
00667 {
00668     m_pDirWatch = new KDirWatch;
00669     m_pTimer = new TQTimer;
00670     connect(m_pTimer, TQT_SIGNAL(timeout()), this, TQT_SLOT(runKonfUpdate()));
00671     TQObject::connect( m_pDirWatch, TQT_SIGNAL(dirty(const TQString&)),
00672            this, TQT_SLOT(slotNewUpdateFile()));
00673 
00674     TQStringList dirs = TDEGlobal::dirs()->findDirs("data", "tdeconf_update");
00675     for( TQStringList::ConstIterator it = dirs.begin();
00676          it != dirs.end();
00677          ++it )
00678     {
00679        TQString path = *it;
00680        if (path[path.length()-1] != '/')
00681           path += "/";
00682 
00683        if (!m_pDirWatch->contains(path))
00684           m_pDirWatch->addDir(path);
00685     }
00686 }
00687 
00688 KUpdateD::~KUpdateD()
00689 {
00690     delete m_pDirWatch;
00691     delete m_pTimer;
00692 }
00693 
00694 void KUpdateD::runKonfUpdate()
00695 {
00696     ::runKonfUpdate();
00697 }
00698 
00699 void KUpdateD::slotNewUpdateFile()
00700 {
00701     m_pTimer->start( 500, true /* single shot */ );
00702 }
00703 
00704 KHostnameD::KHostnameD(int pollInterval)
00705 {
00706     m_Timer.start(pollInterval, false /* repetitive */ );
00707     connect(&m_Timer, TQT_SIGNAL(timeout()), this, TQT_SLOT(checkHostname()));
00708     checkHostname();
00709 }
00710 
00711 KHostnameD::~KHostnameD()
00712 {
00713     // Empty
00714 }
00715 
00716 void KHostnameD::checkHostname()
00717 {
00718     char buf[1024+1];
00719     if (gethostname(buf, 1024) != 0)
00720        return;
00721     buf[sizeof(buf)-1] = '\0';
00722 
00723     if (m_hostname.isEmpty())
00724     {
00725        m_hostname = buf;
00726        return;
00727     }
00728 
00729     if (m_hostname == buf)
00730        return;
00731 
00732     TQCString newHostname = buf;
00733 
00734     runDontChangeHostname(m_hostname, newHostname);
00735     m_hostname = newHostname;
00736 }
00737 
00738 
00739 static TDECmdLineOptions options[] =
00740 {
00741   { "check", I18N_NOOP("Check Sycoca database only once"), 0 },
00742   { "new-startup", "Internal", 0 },
00743   TDECmdLineLastOption
00744 };
00745 
00746 class KDEDQtDCOPObject : public DCOPObject
00747 {
00748 public:
00749   KDEDQtDCOPObject() : DCOPObject("qt/kded") { }
00750 
00751   virtual bool process(const TQCString &fun, const TQByteArray &data,
00752                        TQCString& replyType, TQByteArray &replyData)
00753     {
00754       if ( kapp && (fun == "quit()") )
00755       {
00756         kapp->quit();
00757         replyType = "void";
00758         return true;
00759       }
00760       return DCOPObject::process(fun, data, replyType, replyData);
00761     }
00762 
00763   QCStringList functions()
00764     {
00765        QCStringList res = DCOPObject::functions();
00766        res += "void quit()";
00767        return res;
00768     }
00769 };
00770 
00771 class KDEDApplication : public KUniqueApplication
00772 {
00773 public:
00774   KDEDApplication() : KUniqueApplication( )
00775     {
00776        startup = true;
00777        dcopClient()->connectDCOPSignal( "DCOPServer", "", "terminateTDE()",
00778                                         objId(), "quit()", false );
00779     }
00780 
00781   int newInstance()
00782     {
00783        if (startup) {
00784           startup = false;
00785           if( Kded::self()->newStartup())
00786              Kded::self()->initModules();
00787           else
00788          TQTimer::singleShot(500, Kded::self(), TQT_SLOT(initModules()));
00789        } else 
00790           runBuildSycoca();
00791 
00792        return 0;
00793     }
00794 
00795   QCStringList functions()
00796     {
00797        QCStringList res = KUniqueApplication::functions();
00798        res += "bool loadModule(TQCString)";
00799        res += "bool unloadModule(TQCString)";
00800        res += "void registerWindowId(long int)";
00801        res += "void unregisterWindowId(long int)";
00802        res += "QCStringList loadedModules()";
00803        res += "void reconfigure()";
00804        res += "void loadSecondPhase()";
00805        res += "void quit()";
00806        return res;
00807     }
00808 
00809   bool process(const TQCString &fun, const TQByteArray &data,
00810                TQCString &replyType, TQByteArray &replyData)
00811   {
00812     if (fun == "loadModule(TQCString)") {
00813       TQCString module;
00814       TQDataStream arg( data, IO_ReadOnly );
00815       arg >> module;
00816       bool result = (Kded::self()->loadModule(module, false) != 0);
00817       replyType = "bool";
00818       TQDataStream _replyStream( replyData, IO_WriteOnly );
00819       _replyStream << result;
00820       return true;
00821     }
00822     else if (fun == "unloadModule(TQCString)") {
00823       TQCString module;
00824       TQDataStream arg( data, IO_ReadOnly );
00825       arg >> module;
00826       bool result = Kded::self()->unloadModule(module);
00827       replyType = "bool";
00828       TQDataStream _replyStream( replyData, IO_WriteOnly );
00829       _replyStream << result;
00830       return true;
00831     }
00832     else if (fun == "registerWindowId(long int)") {
00833       long windowId;
00834       TQDataStream arg( data, IO_ReadOnly );
00835       arg >> windowId;
00836       Kded::self()->setCallingDcopClient(callingDcopClient());
00837       Kded::self()->registerWindowId(windowId);
00838       replyType = "void";
00839       return true;
00840     }
00841      else if (fun == "unregisterWindowId(long int)") {
00842       long windowId;
00843       TQDataStream arg( data, IO_ReadOnly );
00844       arg >> windowId;
00845       Kded::self()->setCallingDcopClient(callingDcopClient());
00846       Kded::self()->unregisterWindowId(windowId);
00847       replyType = "void";
00848       return true;
00849     }
00850     else if (fun == "loadedModules()") {
00851       replyType = "QCStringList";
00852       TQDataStream _replyStream(replyData, IO_WriteOnly);
00853       _replyStream << Kded::self()->loadedModules();
00854       return true;
00855     }
00856     else if (fun == "reconfigure()") {
00857       config()->reparseConfiguration();
00858       Kded::self()->initModules();
00859       replyType = "void";
00860       return true;
00861     }
00862     else if (fun == "loadSecondPhase()") {
00863       Kded::self()->loadSecondPhase();
00864       replyType = "void";
00865       return true;
00866     }
00867     else if (fun == "quit()") {
00868       quit();
00869       replyType = "void";
00870       return true;
00871     }
00872     return KUniqueApplication::process(fun, data, replyType, replyData);
00873   }
00874 
00875   bool startup;
00876   KDEDQtDCOPObject kdedQtDcopObject;
00877 };
00878 
00879 extern "C" KDE_EXPORT int kdemain(int argc, char *argv[])
00880 {
00881      TDEAboutData aboutData( "kded", I18N_NOOP("TDE Daemon"),
00882         "$Id$",
00883         I18N_NOOP("TDE Daemon - triggers Sycoca database updates when needed"));
00884 
00885      TDEApplication::installSigpipeHandler();
00886 
00887      TDECmdLineArgs::init(argc, argv, &aboutData);
00888 
00889      KUniqueApplication::addCmdLineOptions();
00890 
00891      TDECmdLineArgs::addCmdLineOptions( options );
00892 
00893      // this program is in tdelibs so it uses tdelibs as catalog
00894      TDELocale::setMainCatalogue("tdelibs");
00895 
00896      // WABA: Make sure not to enable session management.
00897      putenv(strdup("SESSION_MANAGER="));
00898 
00899      // Parse command line before checking DCOP
00900      TDECmdLineArgs *args = TDECmdLineArgs::parsedArgs();
00901 
00902      // Check DCOP communication.
00903      {
00904         DCOPClient testDCOP;
00905         TQCString dcopName = testDCOP.registerAs("kded", false);
00906         if (dcopName.isEmpty())
00907         {
00908            kdFatal() << "DCOP communication problem!" << endl;
00909            return 1;
00910         }
00911      }
00912 
00913      TDEInstance *instance = new TDEInstance(&aboutData);
00914      TDEConfig *config = instance->config(); // Enable translations.
00915 
00916      if (args->isSet("check"))
00917      {
00918         config->setGroup("General");
00919         checkStamps = config->readBoolEntry("CheckFileStamps", true);
00920         runBuildSycoca();
00921         runKonfUpdate();
00922         exit(0);
00923      }
00924 
00925      if (!KUniqueApplication::start())
00926      {
00927         fprintf(stderr, "[kded] Daemon (kded) is already running.\n");
00928         exit(0);
00929      }
00930 
00931      KUniqueApplication::dcopClient()->setQtBridgeEnabled(false);
00932 
00933      config->setGroup("General");
00934      int HostnamePollInterval = config->readNumEntry("HostnamePollInterval", 5000);
00935      bool bCheckSycoca = config->readBoolEntry("CheckSycoca", true);
00936      bool bCheckUpdates = config->readBoolEntry("CheckUpdates", true);
00937      bool bCheckHostname = config->readBoolEntry("CheckHostname", true);
00938      checkStamps = config->readBoolEntry("CheckFileStamps", true);
00939      delayedCheck = config->readBoolEntry("DelayedCheck", false);
00940 
00941      Kded *kded = new Kded(bCheckSycoca, args->isSet("new-startup")); // Build data base
00942 
00943      signal(SIGTERM, sighandler);
00944      signal(SIGHUP, sighandler);
00945      KDEDApplication k;
00946 
00947      kded->recreate(true); // initial
00948 
00949      if (bCheckUpdates)
00950         (void) new KUpdateD; // Watch for updates
00951 
00952      runKonfUpdate(); // Run it once.
00953 
00954      if (bCheckHostname)
00955         (void) new KHostnameD(HostnamePollInterval); // Watch for hostname changes
00956 
00957      DCOPClient *client = kapp->dcopClient();
00958      TQObject::connect(client, TQT_SIGNAL(applicationRemoved(const TQCString&)),
00959              kded, TQT_SLOT(slotApplicationRemoved(const TQCString&)));
00960      client->setNotifications(true);
00961      client->setDaemonMode( true );
00962 
00963      // During startup kdesktop waits for KDED to finish.
00964      // Send a notifyDatabaseChanged signal even if the database hasn't
00965      // changed.
00966      // If the database changed, tdebuildsycoca's signal didn't go anywhere
00967      // anyway, because it was too early, so let's send this signal
00968      // unconditionnally (David)
00969      TQByteArray data;
00970      client->send( "*", "tdesycoca", "notifyDatabaseChanged()", data );
00971      client->send( "ksplash", "", "upAndRunning(TQString)",  TQString("kded"));
00972 #ifdef Q_WS_X11
00973      XEvent e;
00974      e.xclient.type = ClientMessage;
00975      e.xclient.message_type = XInternAtom( tqt_xdisplay(), "_KDE_SPLASH_PROGRESS", False );
00976      e.xclient.display = tqt_xdisplay();
00977      e.xclient.window = tqt_xrootwin();
00978      e.xclient.format = 8;
00979      strcpy( e.xclient.data.b, "kded" );
00980      XSendEvent( tqt_xdisplay(), tqt_xrootwin(), False, SubstructureNotifyMask, &e );
00981 #endif
00982      int result = k.exec(); // keep running
00983 
00984      delete kded;
00985      delete instance; // Deletes config as well
00986 
00987      return result;
00988 }
00989 
00990 #include "kded.moc"

kded

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

kded

Skip menu "kded"
  • arts
  • dcop
  • dnssd
  • interfaces
  •   kspeech
  •     interface
  •     library
  •   tdetexteditor
  • kate
  • kded
  • kdoctools
  • kimgio
  • kjs
  • libtdemid
  • libtdescreensaver
  • tdeabc
  • tdecmshell
  • tdecore
  • tdefx
  • tdehtml
  • tdeinit
  • tdeio
  •   bookmarks
  •   httpfilter
  •   kpasswdserver
  •   kssl
  •   tdefile
  •   tdeio
  •   tdeioexec
  • tdeioslave
  •   http
  • tdemdi
  •   tdemdi
  • tdenewstuff
  • tdeparts
  • tdeprint
  • tderandr
  • tderesources
  • tdespell2
  • tdesu
  • tdeui
  • tdeunittest
  • tdeutils
  • tdewallet
Generated for kded by doxygen 1.7.6.1
This website is maintained by Timothy Pearson.