00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
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;
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" );
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
00132
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;
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
00161 if( getenv( "TDE_SESSION_UID" ) != NULL && uid_t( atoi( getenv( "TDE_SESSION_UID" ))) != getuid())
00162 tde_running = false;
00163
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
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:
00197 break;
00198 case 1:
00199 if( !tde_running )
00200 prevent_autoload = true;
00201 break;
00202 case 2:
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
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
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
00307 void *create = lib->symbol(TQFile::encodeName(factory));
00308
00309 if (create)
00310 {
00311
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
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
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
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) {
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
00478
00479
00480 if (!initial)
00481 {
00482 updateDirWatch();
00483 runBuildSycoca(this, TQT_SLOT(recreateDone()));
00484 }
00485 else
00486 {
00487 if(!delayedCheck)
00488 updateDirWatch();
00489 runBuildSycoca();
00490 recreateDone();
00491 if(delayedCheck)
00492 {
00493
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
00519 if (!m_recreateRequests.isEmpty())
00520 {
00521 m_pTimer->start(2000, true );
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 );
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 );
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 ) )
00572 return;
00573
00574 TQDir d( _path, TQString::null, TQDir::Unsorted, TQDir::Readable | TQDir::Executable | TQDir::Dirs | TQDir::Hidden );
00575
00576
00577
00578
00579
00580
00581
00582 m_pDirWatch->addDir(path);
00583
00584 if ( !d.exists() )
00585 {
00586 kdDebug(7020) << TQString(TQString("Does not exist! (%1)").arg(_path)) << endl;
00587 return;
00588 }
00589
00590
00591
00592
00593
00594
00595 TQString file;
00596 unsigned int i;
00597 unsigned int count = d.count();
00598 for( i = 0; i < count; i++ )
00599 {
00600 if (d[i] == "." || d[i] == ".." || d[i] == "magic")
00601 continue;
00602
00603 file = path;
00604 file += d[i];
00605
00606 readDirectory( file );
00607 }
00608 }
00609
00610 bool Kded::isWindowRegistered(long windowId)
00611 {
00612 return m_globalWindowIdList.find(windowId) != 0;
00613
00614 }
00615
00616
00617 void Kded::registerWindowId(long windowId)
00618 {
00619 m_globalWindowIdList.replace(windowId, &windowId);
00620 TQCString sender = callingDcopClient()->senderId();
00621 if( sender.isEmpty())
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
00639 void Kded::unregisterWindowId(long windowId)
00640 {
00641 m_globalWindowIdList.remove(windowId);
00642 TQCString sender = callingDcopClient()->senderId();
00643 if( sender.isEmpty())
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 )
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 );
00702 }
00703
00704 KHostnameD::KHostnameD(int pollInterval)
00705 {
00706 m_Timer.start(pollInterval, false );
00707 connect(&m_Timer, TQT_SIGNAL(timeout()), this, TQT_SLOT(checkHostname()));
00708 checkHostname();
00709 }
00710
00711 KHostnameD::~KHostnameD()
00712 {
00713
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
00894 TDELocale::setMainCatalogue("tdelibs");
00895
00896
00897 putenv(strdup("SESSION_MANAGER="));
00898
00899
00900 TDECmdLineArgs *args = TDECmdLineArgs::parsedArgs();
00901
00902
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();
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"));
00942
00943 signal(SIGTERM, sighandler);
00944 signal(SIGHUP, sighandler);
00945 KDEDApplication k;
00946
00947 kded->recreate(true);
00948
00949 if (bCheckUpdates)
00950 (void) new KUpdateD;
00951
00952 runKonfUpdate();
00953
00954 if (bCheckHostname)
00955 (void) new KHostnameD(HostnamePollInterval);
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
00964
00965
00966
00967
00968
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();
00983
00984 delete kded;
00985 delete instance;
00986
00987 return result;
00988 }
00989
00990 #include "kded.moc"