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

Skip menu "kdelibs-4.10.2 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