• Skip to content
  • Skip to link menu
  • KDE API Reference
  • kdelibs-4.10.5 API Reference
  • KDE Home
  • Contact Us
 

KDED

  • kded
kded.cpp
Go to the documentation of this file.
1 // vim: expandtab sw=4 ts=4
2 /* This file is part of the KDE libraries
3  * Copyright (C) 1999 David Faure <faure@kde.org>
4  * Copyright (C) 2000 Waldo Bastian <bastian@kde.org>
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Library General Public
8  * License version 2 as published by the Free Software Foundation;
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13  * Library General Public License for more details.
14  *
15  * You should have received a copy of the GNU Library General Public License
16  * along with this library; see the file COPYING.LIB. If not, write to
17  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18  * Boston, MA 02110-1301, USA.
19  **/
20 
21 #include "kded.h"
22 #include "kdedadaptor.h"
23 #include "kdedmodule.h"
24 
25 #include <kcrash.h>
26 #include <kdeversion.h>
27 
28 #include <unistd.h>
29 #include <stdlib.h>
30 #include <signal.h>
31 #include <time.h>
32 
33 #include <QtCore/QDir>
34 #include <QtCore/QFile>
35 #include <QtCore/QTimer>
36 
37 #include <QtDBus/QtDBus>
38 
39 #include <kuniqueapplication.h>
40 #include <kapplication.h>
41 #include <kcmdlineargs.h>
42 #include <kaboutdata.h>
43 #ifndef KDE_NO_DEPRECATED
44 #include <klibloader.h>
45 #else
46 #include <klibrary.h>
47 #endif
48 #include <klocale.h>
49 #include <kglobal.h>
50 #include <kconfig.h>
51 #include <kconfiggroup.h>
52 #include <kdebug.h>
53 #include <kdirwatch.h>
54 #include <kstandarddirs.h>
55 #include <kservicetypetrader.h>
56 #include <ktoolinvocation.h>
57 #include <kde_file.h>
58 #include "klauncher_iface.h"
59 
60 #ifdef Q_WS_X11
61 #include <qx11info_x11.h>
62 #include <X11/Xlib.h>
63 #include <fixx11h.h>
64 #endif
65 
66 #define KDED_EXENAME "kded4"
67 
68 #define MODULES_PATH "/modules/"
69 
70 Kded *Kded::_self = 0;
71 
72 static bool checkStamps = true;
73 static bool delayedCheck = false;
74 static int HostnamePollInterval;
75 static bool bCheckSycoca;
76 static bool bCheckUpdates;
77 static bool bCheckHostname;
78 
79 #ifdef Q_DBUS_EXPORT
80 extern Q_DBUS_EXPORT void qDBusAddSpyHook(void (*)(const QDBusMessage&));
81 #else
82 extern QDBUS_EXPORT void qDBusAddSpyHook(void (*)(const QDBusMessage&));
83 #endif
84 
85 static void runBuildSycoca(QObject *callBackObj=0, const char *callBackSlot=0)
86 {
87  const QString exe = KStandardDirs::findExe(KBUILDSYCOCA_EXENAME);
88  Q_ASSERT(!exe.isEmpty());
89  QStringList args;
90  args.append("--incremental");
91  if(checkStamps)
92  args.append("--checkstamps");
93  if(delayedCheck)
94  args.append("--nocheckfiles");
95  else
96  checkStamps = false; // useful only during kded startup
97  if (callBackObj)
98  {
99  QVariantList argList;
100  argList << exe << args << QStringList() << QString();
101  KToolInvocation::klauncher()->callWithCallback("kdeinit_exec_wait", argList, callBackObj,
102  callBackSlot);
103  }
104  else
105  {
106  KToolInvocation::kdeinitExecWait( exe, args );
107  }
108 }
109 
110 static void runKonfUpdate()
111 {
112  KToolInvocation::kdeinitExecWait( "kconf_update", QStringList(), 0, 0, "0" /*no startup notification*/ );
113 }
114 
115 static void runDontChangeHostname(const QByteArray &oldName, const QByteArray &newName)
116 {
117  QStringList args;
118  args.append(QFile::decodeName(oldName));
119  args.append(QFile::decodeName(newName));
120  KToolInvocation::kdeinitExecWait( "kdontchangethehostname", args );
121 }
122 
123 Kded::Kded()
124  : m_needDelayedCheck(false)
125 {
126  _self = this;
127 
128  m_serviceWatcher = new QDBusServiceWatcher(this);
129  m_serviceWatcher->setConnection(QDBusConnection::sessionBus());
130  m_serviceWatcher->setWatchMode(QDBusServiceWatcher::WatchForUnregistration);
131  QObject::connect(m_serviceWatcher, SIGNAL(serviceUnregistered(QString)),
132  this, SLOT(slotApplicationRemoved(QString)));
133 
134  new KBuildsycocaAdaptor(this);
135  new KdedAdaptor(this);
136 
137  QDBusConnection session = QDBusConnection::sessionBus();
138  session.registerObject("/kbuildsycoca", this);
139  session.registerObject("/kded", this);
140 
141  qDBusAddSpyHook(messageFilter);
142 
143  m_pTimer = new QTimer(this);
144  m_pTimer->setSingleShot( true );
145  connect(m_pTimer, SIGNAL(timeout()), this, SLOT(recreate()));
146 
147  m_pDirWatch = 0;
148 
149  m_recreateCount = 0;
150  m_recreateBusy = false;
151 }
152 
153 Kded::~Kded()
154 {
155  _self = 0;
156  m_pTimer->stop();
157  delete m_pTimer;
158  delete m_pDirWatch;
159 
160  for (QHash<QByteArray,KDEDModule*>::iterator
161  it(m_modules.begin()), itEnd(m_modules.end());
162  it != itEnd; ++it)
163  {
164  KDEDModule* module(it.value());
165 
166  // first disconnect otherwise slotKDEDModuleRemoved() is called
167  // and changes m_modules while we're iterating over it
168  disconnect(module, SIGNAL(moduleDeleted(KDEDModule*)),
169  this, SLOT(slotKDEDModuleRemoved(KDEDModule*)));
170 
171  delete module;
172  }
173 }
174 
175 // on-demand module loading
176 // this function is called by the D-Bus message processing function before
177 // calls are delivered to objects
178 void Kded::messageFilter(const QDBusMessage &message)
179 {
180  // This happens when kded goes down and some modules try to clean up.
181  if (!self())
182  return;
183 
184  if (message.type() != QDBusMessage::MethodCallMessage)
185  return;
186 
187  QString obj = message.path();
188  if (!obj.startsWith(MODULES_PATH))
189  return;
190 
191  // Remove the <MODULES_PATH> part
192  obj = obj.mid(strlen(MODULES_PATH));
193  if (obj == "ksycoca")
194  return; // Ignore this one.
195 
196  // Remove the part after the modules name
197  int index = obj.indexOf('/');
198  if (index!=-1) {
199  obj = obj.left(index);
200  }
201 
202  if (self()->m_dontLoad.value(obj, 0))
203  return;
204 
205  KDEDModule *module = self()->loadModule(obj, true);
206  if (!module) {
207  kDebug(7020) << "Failed to load module for " << obj;
208  }
209  Q_UNUSED(module);
210 }
211 
212 static int phaseForModule(const KService::Ptr& service)
213 {
214  const QVariant phasev = service->property("X-KDE-Kded-phase", QVariant::Int );
215  return phasev.isValid() ? phasev.toInt() : 2;
216 }
217 
218 void Kded::initModules()
219 {
220  m_dontLoad.clear();
221  bool kde_running = !qgetenv( "KDE_FULL_SESSION" ).isEmpty();
222  if (kde_running) {
223  // not the same user like the one running the session (most likely we're run via sudo or something)
224  const QByteArray sessionUID = qgetenv( "KDE_SESSION_UID" );
225  if( !sessionUID.isEmpty() && uid_t( sessionUID.toInt() ) != getuid())
226  kde_running = false;
227 
228  // not the same kde version as the current desktop
229  const QByteArray kdeSession = qgetenv("KDE_SESSION_VERSION");
230  if (kdeSession.toInt() != KDE_VERSION_MAJOR)
231  kde_running = false;
232  }
233 
234  // There will be a "phase 2" only if we're in the KDE startup.
235  // If kded is restarted by its crashhandled or by hand,
236  // then there will be no second phase autoload, so load
237  // these modules now, if in a KDE session.
238  const bool loadPhase2Now = (kde_running && qgetenv("KDED_STARTED_BY_KDEINIT").toInt() == 0);
239 
240  // Preload kded modules.
241  const KService::List kdedModules = KServiceTypeTrader::self()->query("KDEDModule");
242  for(KService::List::ConstIterator it = kdedModules.begin(); it != kdedModules.end(); ++it)
243  {
244  KService::Ptr service = *it;
245  // Should the service load on startup?
246  const bool autoload = isModuleAutoloaded(service);
247 
248  // see ksmserver's README for description of the phases
249  bool prevent_autoload = false;
250  switch( phaseForModule(service) )
251  {
252  case 0: // always autoload
253  break;
254  case 1: // autoload only in KDE
255  if (!kde_running) {
256  prevent_autoload = true;
257  }
258  break;
259  case 2: // autoload delayed, only in KDE
260  default:
261  if (!loadPhase2Now) {
262  prevent_autoload = true;
263  }
264  break;
265  }
266 
267  // Load the module if necessary and allowed
268  if (autoload && !prevent_autoload) {
269  if (!loadModule(service, false)) {
270  continue;
271  }
272  }
273 
274  // Remember if the module is allowed to load on demand
275  bool loadOnDemand = isModuleLoadedOnDemand(service);
276  if (!loadOnDemand)
277  noDemandLoad(service->desktopEntryName());
278 
279  // In case of reloading the configuration it is possible for a module
280  // to run even if it is now allowed to. Stop it then.
281  if (!loadOnDemand && !autoload)
282  unloadModule(service->desktopEntryName().toLatin1());
283  }
284 }
285 
286 void Kded::loadSecondPhase()
287 {
288  kDebug(7020) << "Loading second phase autoload";
289  KSharedConfig::Ptr config = KGlobal::config();
290  KService::List kdedModules = KServiceTypeTrader::self()->query("KDEDModule");
291  for(KService::List::ConstIterator it = kdedModules.constBegin(); it != kdedModules.constEnd(); ++it) {
292  const KService::Ptr service = *it;
293  const bool autoload = isModuleAutoloaded(service);
294  if (autoload && phaseForModule(service) == 2) {
295  //kDebug(7020) << "2nd phase: loading" << service->desktopEntryName();
296  loadModule(service, false);
297  }
298  }
299 }
300 
301 void Kded::noDemandLoad(const QString &obj)
302 {
303  m_dontLoad.insert(obj.toLatin1(), this);
304 }
305 
306 void Kded::setModuleAutoloading(const QString &obj, bool autoload)
307 {
308  KSharedConfig::Ptr config = KGlobal::config();
309  // Ensure the service exists.
310  KService::Ptr service = KService::serviceByDesktopPath("kded/"+obj+".desktop");
311  if (!service)
312  return;
313  KConfigGroup cg(config, QString("Module-%1").arg(service->desktopEntryName()));
314  cg.writeEntry("autoload", autoload);
315  cg.sync();
316 }
317 
318 bool Kded::isModuleAutoloaded(const QString &obj) const
319 {
320  KService::Ptr s = KService::serviceByDesktopPath("kded/"+obj+".desktop");
321  if (!s)
322  return false;
323  return isModuleAutoloaded(s);
324 }
325 
326 bool Kded::isModuleAutoloaded(const KService::Ptr &module) const
327 {
328  KSharedConfig::Ptr config = KGlobal::config();
329  bool autoload = module->property("X-KDE-Kded-autoload", QVariant::Bool).toBool();
330  KConfigGroup cg(config, QString("Module-%1").arg(module->desktopEntryName()));
331  autoload = cg.readEntry("autoload", autoload);
332  return autoload;
333 }
334 
335 bool Kded::isModuleLoadedOnDemand(const QString &obj) const
336 {
337  KService::Ptr s = KService::serviceByDesktopPath("kded/"+obj+".desktop");
338  if (!s)
339  return false;
340  return isModuleLoadedOnDemand(s);
341 }
342 
343 bool Kded::isModuleLoadedOnDemand(const KService::Ptr &module) const
344 {
345  KSharedConfig::Ptr config = KGlobal::config();
346  bool loadOnDemand = true;
347  QVariant p = module->property("X-KDE-Kded-load-on-demand", QVariant::Bool);
348  if (p.isValid() && (p.toBool() == false))
349  loadOnDemand = false;
350  return loadOnDemand;
351 }
352 
353 KDEDModule *Kded::loadModule(const QString &obj, bool onDemand)
354 {
355  // Make sure this method is only called with valid module names.
356  Q_ASSERT(obj.indexOf('/')==-1);
357 
358  KDEDModule *module = m_modules.value(obj, 0);
359  if (module)
360  return module;
361  KService::Ptr s = KService::serviceByDesktopPath("kded/"+obj+".desktop");
362  return loadModule(s, onDemand);
363 }
364 
365 KDEDModule *Kded::loadModule(const KService::Ptr& s, bool onDemand)
366 {
367  if (s && !s->library().isEmpty())
368  {
369  QString obj = s->desktopEntryName();
370  KDEDModule *oldModule = m_modules.value(obj, 0);
371  if (oldModule)
372  return oldModule;
373 
374  if (onDemand)
375  {
376  QVariant p = s->property("X-KDE-Kded-load-on-demand", QVariant::Bool);
377  if (p.isValid() && (p.toBool() == false))
378  {
379  noDemandLoad(s->desktopEntryName());
380  return 0;
381  }
382  }
383 
384  KDEDModule *module = 0;
385  QString libname = "kded_"+s->library();
386  KPluginLoader loader(libname);
387 
388  KPluginFactory *factory = loader.factory();
389  if (!factory) {
390  // kde3 compat
391  QString factoryName = s->property("X-KDE-FactoryName", QVariant::String).toString();
392  if (factoryName.isEmpty())
393  factoryName = s->library();
394  factoryName = "create_" + factoryName;
395 #ifndef KDE_NO_DEPRECATED
396  KLibrary* lib = KLibLoader::self()->library(libname);
397  KDEDModule* (*create)();
398  if (lib) {
399  create = (KDEDModule* (*)())lib->resolveFunction(QFile::encodeName(factoryName));
400  if (create)
401  module = create();
402  }
403 #endif
404  if (!module) {
405  kWarning() << "Could not load library" << libname << ". ["
406  << loader.errorString() << "]";
407  }
408  } else {
409  // create the module
410  module = factory->create<KDEDModule>(this);
411  }
412  if (module) {
413  module->setModuleName(obj);
414  m_modules.insert(obj, module);
415  //m_libs.insert(obj, lib);
416  connect(module, SIGNAL(moduleDeleted(KDEDModule*)), SLOT(slotKDEDModuleRemoved(KDEDModule*)));
417  kDebug(7020) << "Successfully loaded module" << obj;
418  return module;
419  } else {
420  kDebug(7020) << "Could not load module" << obj;
421  //loader.unload();
422  }
423  }
424  return 0;
425 }
426 
427 bool Kded::unloadModule(const QString &obj)
428 {
429  KDEDModule *module = m_modules.value(obj, 0);
430  if (!module)
431  return false;
432  kDebug(7020) << "Unloading module" << obj;
433  m_modules.remove(obj);
434  delete module;
435  return true;
436 }
437 
438 QStringList Kded::loadedModules()
439 {
440  return m_modules.keys();
441 }
442 
443 void Kded::slotKDEDModuleRemoved(KDEDModule *module)
444 {
445  m_modules.remove(module->moduleName());
446  //KLibrary *lib = m_libs.take(module->moduleName());
447  //if (lib)
448  // lib->unload();
449 }
450 
451 void Kded::slotApplicationRemoved(const QString &name)
452 {
453 #if 0 // see kdedmodule.cpp (KDED_OBJECTS)
454  foreach( KDEDModule* module, m_modules )
455  {
456  module->removeAll(appId);
457  }
458 #endif
459  m_serviceWatcher->removeWatchedService(name);
460  const QList<qlonglong> windowIds = m_windowIdList.value(name);
461  for( QList<qlonglong>::ConstIterator it = windowIds.begin();
462  it != windowIds.end(); ++it)
463  {
464  qlonglong windowId = *it;
465  m_globalWindowIdList.remove(windowId);
466  foreach( KDEDModule* module, m_modules )
467  {
468  emit module->windowUnregistered(windowId);
469  }
470  }
471  m_windowIdList.remove(name);
472 }
473 
474 void Kded::updateDirWatch()
475 {
476  if (!bCheckUpdates) return;
477 
478  delete m_pDirWatch;
479  m_pDirWatch = new KDirWatch;
480 
481  QObject::connect( m_pDirWatch, SIGNAL(dirty(QString)),
482  this, SLOT(update(QString)));
483  QObject::connect( m_pDirWatch, SIGNAL(created(QString)),
484  this, SLOT(update(QString)));
485  QObject::connect( m_pDirWatch, SIGNAL(deleted(QString)),
486  this, SLOT(dirDeleted(QString)));
487 
488  // For each resource
489  for( QStringList::ConstIterator it = m_allResourceDirs.constBegin();
490  it != m_allResourceDirs.constEnd();
491  ++it )
492  {
493  readDirectory( *it );
494  }
495 }
496 
497 void Kded::updateResourceList()
498 {
499  KSycoca::clearCaches();
500 
501  if (!bCheckUpdates) return;
502 
503  if (delayedCheck) return;
504 
505  const QStringList dirs = KSycoca::self()->allResourceDirs();
506  // For each resource
507  for( QStringList::ConstIterator it = dirs.begin();
508  it != dirs.end();
509  ++it )
510  {
511  if (!m_allResourceDirs.contains(*it))
512  {
513  m_allResourceDirs.append(*it);
514  readDirectory(*it);
515  }
516  }
517 }
518 
519 void Kded::recreate()
520 {
521  recreate(false);
522 }
523 
524 void Kded::runDelayedCheck()
525 {
526  if( m_needDelayedCheck )
527  recreate(false);
528  m_needDelayedCheck = false;
529 }
530 
531 void Kded::recreate(bool initial)
532 {
533  m_recreateBusy = true;
534  // Using KLauncher here is difficult since we might not have a
535  // database
536 
537  if (!initial)
538  {
539  updateDirWatch(); // Update tree first, to be sure to miss nothing.
540  runBuildSycoca(this, SLOT(recreateDone()));
541  }
542  else
543  {
544  if(!delayedCheck)
545  updateDirWatch(); // this would search all the directories
546  if (bCheckSycoca)
547  runBuildSycoca();
548  recreateDone();
549  if(delayedCheck)
550  {
551  // do a proper ksycoca check after a delay
552  QTimer::singleShot( 60000, this, SLOT(runDelayedCheck()));
553  m_needDelayedCheck = true;
554  delayedCheck = false;
555  }
556  else
557  m_needDelayedCheck = false;
558  }
559 }
560 
561 void Kded::recreateDone()
562 {
563  updateResourceList();
564 
565  for(; m_recreateCount; m_recreateCount--)
566  {
567  QDBusMessage msg = m_recreateRequests.takeFirst();
568  QDBusConnection::sessionBus().send(msg.createReply());
569  }
570  m_recreateBusy = false;
571 
572  // Did a new request come in while building?
573  if (!m_recreateRequests.isEmpty())
574  {
575  m_pTimer->start(2000);
576  m_recreateCount = m_recreateRequests.count();
577  }
578 }
579 
580 void Kded::dirDeleted(const QString& path)
581 {
582  update(path);
583 }
584 
585 void Kded::update(const QString& )
586 {
587  if (!m_recreateBusy)
588  {
589  m_pTimer->start( 10000 );
590  }
591 }
592 
593 void Kded::recreate(const QDBusMessage &msg)
594 {
595  if (!m_recreateBusy)
596  {
597  if (m_recreateRequests.isEmpty())
598  {
599  m_pTimer->start(0);
600  m_recreateCount = 0;
601  }
602  m_recreateCount++;
603  }
604  msg.setDelayedReply(true);
605  m_recreateRequests.append(msg);
606  return;
607 }
608 
609 
610 void Kded::readDirectory( const QString& _path )
611 {
612  QString path( _path );
613  if ( !path.endsWith( '/' ) )
614  path += '/';
615 
616  if ( m_pDirWatch->contains( path ) ) // Already seen this one?
617  return;
618 
619  m_pDirWatch->addDir(path,KDirWatch::WatchFiles|KDirWatch::WatchSubDirs); // add watch on this dir
620  return; // KDirWatch now claims to also support recursive watching
621 #if 0
622  QDir d( _path, QString(), QDir::Unsorted, QDir::Readable | QDir::Executable | QDir::Dirs | QDir::Hidden );
623  // set QDir ...
624 
625 
626  //************************************************************************
627  // Setting dirs
628  //************************************************************************
629 
630  if ( !d.exists() ) // exists&isdir?
631  {
632  kDebug(7020) << "Does not exist:" << _path;
633  return; // return false
634  }
635 
636  // Note: If some directory is gone, dirwatch will delete it from the list.
637 
638  //************************************************************************
639  // Reading
640  //************************************************************************
641  QString file;
642  unsigned int i; // counter and string length.
643  unsigned int count = d.count();
644  for( i = 0; i < count; i++ ) // check all entries
645  {
646  if (d[i] == "." || d[i] == ".." || d[i] == "magic")
647  continue; // discard those ".", "..", "magic"...
648 
649  file = path; // set full path
650  file += d[i]; // and add the file name.
651 
652  readDirectory( file ); // yes, dive into it.
653  }
654 #endif
655 }
656 
657 /*
658 bool Kded::isWindowRegistered(long windowId) const
659 {
660  return m_globalWindowIdList.contains(windowId);
661 
662 }
663 */
664 
665 void Kded::registerWindowId(qlonglong windowId, const QString &sender)
666 {
667  if (!m_windowIdList.contains(sender)) {
668  m_serviceWatcher->addWatchedService(sender);
669  }
670 
671  m_globalWindowIdList.insert(windowId);
672  QList<qlonglong> windowIds = m_windowIdList.value(sender);
673  windowIds.append(windowId);
674  m_windowIdList.insert(sender, windowIds);
675 
676  foreach( KDEDModule* module, m_modules )
677  {
678  //kDebug() << module->moduleName();
679  emit module->windowRegistered(windowId);
680  }
681 }
682 
683 void Kded::unregisterWindowId(qlonglong windowId, const QString &sender)
684 {
685  m_globalWindowIdList.remove(windowId);
686  QList<qlonglong> windowIds = m_windowIdList.value(sender);
687  if (!windowIds.isEmpty())
688  {
689  windowIds.removeAll(windowId);
690  if (windowIds.isEmpty()) {
691  m_serviceWatcher->removeWatchedService(sender);
692  m_windowIdList.remove(sender);
693  } else {
694  m_windowIdList.insert(sender, windowIds);
695  }
696  }
697 
698  foreach( KDEDModule* module, m_modules )
699  {
700  //kDebug() << module->moduleName();
701  emit module->windowUnregistered(windowId);
702  }
703 }
704 
705 
706 static void sighandler(int /*sig*/)
707 {
708  if (qApp)
709  qApp->quit();
710 }
711 
712 KUpdateD::KUpdateD()
713 {
714  m_pDirWatch = new KDirWatch;
715  m_pTimer = new QTimer;
716  m_pTimer->setSingleShot( true );
717  connect(m_pTimer, SIGNAL(timeout()), this, SLOT(runKonfUpdate()));
718  QObject::connect( m_pDirWatch, SIGNAL(dirty(QString)),
719  this, SLOT(slotNewUpdateFile()));
720 
721  const QStringList dirs = KGlobal::dirs()->findDirs("data", "kconf_update");
722  for( QStringList::ConstIterator it = dirs.begin();
723  it != dirs.end();
724  ++it )
725  {
726  QString path = *it;
727  if (path[path.length()-1] != '/')
728  path += '/';
729 
730  if (!m_pDirWatch->contains(path))
731  m_pDirWatch->addDir(path,KDirWatch::WatchFiles|KDirWatch::WatchSubDirs);
732  }
733 }
734 
735 KUpdateD::~KUpdateD()
736 {
737  delete m_pDirWatch;
738  delete m_pTimer;
739 }
740 
741 void KUpdateD::runKonfUpdate()
742 {
743  ::runKonfUpdate();
744 }
745 
746 void KUpdateD::slotNewUpdateFile()
747 {
748  m_pTimer->start( 500 );
749 }
750 
751 KHostnameD::KHostnameD(int pollInterval)
752 {
753  m_Timer.start(pollInterval); // repetitive timer (not single-shot)
754  connect(&m_Timer, SIGNAL(timeout()), this, SLOT(checkHostname()));
755  checkHostname();
756 }
757 
758 KHostnameD::~KHostnameD()
759 {
760  // Empty
761 }
762 
763 void KHostnameD::checkHostname()
764 {
765  char buf[1024+1];
766  if (gethostname(buf, 1024) != 0)
767  return;
768  buf[sizeof(buf)-1] = '\0';
769 
770  if (m_hostname.isEmpty())
771  {
772  m_hostname = buf;
773  return;
774  }
775 
776  if (m_hostname == buf)
777  return;
778 
779  QByteArray newHostname = buf;
780 
781  runDontChangeHostname(m_hostname, newHostname);
782  m_hostname = newHostname;
783 }
784 
785 
786 KBuildsycocaAdaptor::KBuildsycocaAdaptor(QObject *parent)
787  : QDBusAbstractAdaptor(parent)
788 {
789 }
790 
791 void KBuildsycocaAdaptor::recreate(const QDBusMessage &msg)
792 {
793  Kded::self()->recreate(msg);
794 }
795 
796 class KDEDApplication : public KUniqueApplication
797 {
798 public:
799  KDEDApplication() : KUniqueApplication( )
800  {
801  startup = true;
802  }
803 
804  int newInstance()
805  {
806  if (startup) {
807  startup = false;
808 
809  // This long initialization has to be here, not in kdemain.
810  // If it was in main, it would cause a dbus timeout when
811  // our parent from KUniqueApplication tries to call our
812  // newInstance method.
813 
814  Kded *kded = Kded::self();
815 
816  kded->recreate(true); // initial
817 
818  if (bCheckUpdates)
819  (void) new KUpdateD; // Watch for updates
820 
821 #ifdef Q_WS_X11
822  XEvent e;
823  e.xclient.type = ClientMessage;
824  e.xclient.message_type = XInternAtom( QX11Info::display(), "_KDE_SPLASH_PROGRESS", False );
825  e.xclient.display = QX11Info::display();
826  e.xclient.window = QX11Info::appRootWindow();
827  e.xclient.format = 8;
828  strcpy( e.xclient.data.b, "kded" );
829  XSendEvent( QX11Info::display(), QX11Info::appRootWindow(), False, SubstructureNotifyMask, &e );
830 #endif
831 
832  runKonfUpdate(); // Run it once.
833 
834 #ifdef Q_WS_X11
835  e.xclient.type = ClientMessage;
836  e.xclient.message_type = XInternAtom( QX11Info::display(), "_KDE_SPLASH_PROGRESS", False );
837  e.xclient.display = QX11Info::display();
838  e.xclient.window = QX11Info::appRootWindow();
839  e.xclient.format = 8;
840  strcpy( e.xclient.data.b, "confupdate" );
841  XSendEvent( QX11Info::display(), QX11Info::appRootWindow(), False, SubstructureNotifyMask, &e );
842 #endif
843 
844  if (bCheckHostname)
845  (void) new KHostnameD(HostnamePollInterval); // Watch for hostname changes
846 
847  kded->initModules();
848  } else
849  runBuildSycoca();
850 
851  return 0;
852  }
853 
854  bool startup;
855 };
856 
857 extern "C" KDE_EXPORT int kdemain(int argc, char *argv[])
858 {
859  KAboutData aboutData( "kded" /*don't change this one to kded4! dbus registration should be org.kde.kded etc.*/,
860  "kdelibs4", ki18n("KDE Daemon"),
861  KDE_VERSION_STRING,
862  ki18n("KDE Daemon - triggers Sycoca database updates when needed"));
863 
864  KCmdLineOptions options;
865  options.add("check", ki18n("Check Sycoca database only once"));
866 
867  KCmdLineArgs::init(argc, argv, &aboutData);
868 
869  KUniqueApplication::addCmdLineOptions();
870 
871  KCmdLineArgs::addCmdLineOptions( options );
872 
873  // WABA: Make sure not to enable session management.
874  putenv(qstrdup("SESSION_MANAGER="));
875 
876  // Parse command line before checking DCOP
877  KCmdLineArgs *args = KCmdLineArgs::parsedArgs();
878 
879  KComponentData componentData(&aboutData);
880  KSharedConfig::Ptr config = componentData.config(); // Enable translations.
881 
882  KConfigGroup cg(config, "General");
883  if (args->isSet("check"))
884  {
885  // KUniqueApplication not wanted here.
886  KApplication app;
887  checkStamps = cg.readEntry("CheckFileStamps", true);
888  runBuildSycoca();
889  runKonfUpdate();
890  return 0;
891  }
892 
893  if (!KUniqueApplication::start())
894  {
895  fprintf(stderr, "KDE Daemon (kded) already running.\n");
896  return 0;
897  }
898 
899  // Thiago: reenable if such a thing exists in QtDBus in the future
900  //KUniqueApplication::dcopClient()->setQtBridgeEnabled(false);
901 
902  HostnamePollInterval = cg.readEntry("HostnamePollInterval", 5000);
903  bCheckSycoca = cg.readEntry("CheckSycoca", true);
904  bCheckUpdates = cg.readEntry("CheckUpdates", true);
905  bCheckHostname = cg.readEntry("CheckHostname", true);
906  checkStamps = cg.readEntry("CheckFileStamps", true);
907  delayedCheck = cg.readEntry("DelayedCheck", false);
908 
909  Kded *kded = new Kded(); // Build data base
910 
911 #ifndef _WIN32_WCE
912  KDE_signal(SIGTERM, sighandler);
913 #endif
914  KDE_signal(SIGHUP, sighandler);
915  KDEDApplication k;
916  k.setQuitOnLastWindowClosed(false);
917 
918  KCrash::setFlags(KCrash::AutoRestart);
919 
920  // Not sure why kded is created before KDEDApplication
921  // but if it has to be, then it needs to be moved to the main thread
922  // before it can use timers (DF)
923  kded->moveToThread( k.thread() );
924 
925  int result = k.exec(); // keep running
926 
927  delete kded;
928 
929  return result;
930 }
931 
932 #include "kded.moc"
This file is part of the KDE documentation.
Documentation copyright © 1996-2013 The KDE developers.
Generated on Tue Jul 16 2013 11:50:39 by doxygen 1.8.1.1 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

KDED

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

kdelibs-4.10.5 API Reference

Skip menu "kdelibs-4.10.5 API Reference"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDEWebKit
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • KPty
  • Kross
  • KUnitConversion
  • KUtils
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver
Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal