TDE base libraries and programs
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

252 lines
6.6KB

  1. /*
  2. Copyright (c) 1999 Matthias Hoelzer-Kluepfel <hoelzer@kde.org>
  3. This program is free software; you can redistribute it and/or modify
  4. it under the terms of the GNU General Public License as published by
  5. the Free Software Foundation; either version 2 of the License, or
  6. (at your option) any later version.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. GNU General Public License for more details.
  11. You should have received a copy of the GNU General Public License
  12. along with this program; if not, write to the Free Software
  13. Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  14. */
  15. #include <config.h>
  16. #include "main.h"
  17. #include <unistd.h>
  18. #include <tqfile.h>
  19. #include <tqtimer.h>
  20. #include <tdeapplication.h>
  21. #include <tdecmdlineargs.h>
  22. #include <tdeaboutdata.h>
  23. #include <kservice.h>
  24. #include <klibloader.h>
  25. #include <kdebug.h>
  26. #include <dcopclient.h>
  27. #include <tdeconfig.h>
  28. #include <X11/Xlib.h>
  29. static TDECmdLineOptions options[] =
  30. {
  31. { "list", I18N_NOOP("List modules that are run at startup"), 0 },
  32. { "+module", I18N_NOOP("Configuration module to run"), 0 },
  33. TDECmdLineLastOption
  34. };
  35. static int ready[ 2 ];
  36. static bool startup = false;
  37. static void sendReady()
  38. {
  39. if( ready[ 1 ] == -1 )
  40. return;
  41. char c = 0;
  42. write( ready[ 1 ], &c, 1 );
  43. close( ready[ 1 ] );
  44. ready[ 1 ] = -1;
  45. }
  46. static void waitForReady()
  47. {
  48. char c = 1;
  49. close( ready[ 1 ] );
  50. read( ready[ 0 ], &c, 1 );
  51. close( ready[ 0 ] );
  52. }
  53. bool KCMInit::runModule(const TQString &libName, KService::Ptr service)
  54. {
  55. KLibLoader *loader = KLibLoader::self();
  56. KLibrary *lib = loader->library(TQFile::encodeName(libName));
  57. if (lib) {
  58. // get the init_ function
  59. TQString factory = TQString("init_%1").arg(service->init());
  60. void *init = lib->symbol(factory.utf8());
  61. if (init) {
  62. // initialize the module
  63. kdDebug(1208) << "Initializing " << libName << ": " << factory << endl;
  64. void (*func)() = (void(*)())init;
  65. func();
  66. return true;
  67. }
  68. loader->unloadLibrary(TQFile::encodeName(libName));
  69. }
  70. return false;
  71. }
  72. void KCMInit::runModules( int phase )
  73. {
  74. // look for X-TDE-Init=... entries
  75. for(KService::List::Iterator it = list.begin();
  76. it != list.end();
  77. ++it) {
  78. KService::Ptr service = (*it);
  79. TQString library = service->property("X-TDE-Init-Library", TQVariant::String).toString();
  80. if (library.isEmpty())
  81. library = service->library();
  82. if (library.isEmpty() || service->init().isEmpty())
  83. continue; // Skip
  84. // see ksmserver's README for the description of the phases
  85. TQVariant vphase = service->property("X-TDE-Init-Phase", TQVariant::Int );
  86. int libphase = 1;
  87. if( vphase.isValid() )
  88. libphase = vphase.toInt();
  89. if( phase != -1 && libphase != phase )
  90. continue;
  91. TQString libName = TQString("kcm_%1").arg(library);
  92. // try to load the library
  93. if (! alreadyInitialized.contains( libName.ascii() )) {
  94. if (!runModule(libName, service)) {
  95. libName = TQString("libkcm_%1").arg(library);
  96. if (! alreadyInitialized.contains( libName.ascii() )) {
  97. runModule(libName, service);
  98. alreadyInitialized.append( libName.ascii() );
  99. }
  100. } else
  101. alreadyInitialized.append( libName.ascii() );
  102. }
  103. }
  104. }
  105. KCMInit::KCMInit( TDECmdLineArgs* args )
  106. : DCOPObject( "kcminit" )
  107. {
  108. TQCString arg;
  109. if (args->count() == 1) {
  110. arg = args->arg(0);
  111. }
  112. if (args->isSet("list"))
  113. {
  114. list = KService::allInitServices();
  115. for(KService::List::Iterator it = list.begin();
  116. it != list.end();
  117. ++it)
  118. {
  119. KService::Ptr service = (*it);
  120. if (service->library().isEmpty() || service->init().isEmpty())
  121. continue; // Skip
  122. printf("%s\n", TQFile::encodeName(service->desktopEntryName()).data());
  123. }
  124. return;
  125. }
  126. if (!arg.isEmpty()) {
  127. TQString module = TQFile::decodeName(arg);
  128. if (!module.endsWith(".desktop"))
  129. module += ".desktop";
  130. KService::Ptr serv = KService::serviceByStorageId( module );
  131. if ( !serv || serv->library().isEmpty() ||
  132. serv->init().isEmpty()) {
  133. kdError(1208) << TQString(i18n("Module %1 not found!").arg(module)) << endl;
  134. return;
  135. } else
  136. list.append(serv);
  137. } else {
  138. // locate the desktop files
  139. list = KService::allInitServices();
  140. }
  141. if ( !kapp->dcopClient()->isAttached() )
  142. kapp->dcopClient()->attach();
  143. // This key has no GUI apparently
  144. TDEConfig config("kcmdisplayrc", true );
  145. config.setGroup("X11");
  146. bool multihead = !config.readBoolEntry( "disableMultihead", false) &&
  147. (ScreenCount(tqt_xdisplay()) > 1);
  148. // Pass env. var to tdeinit.
  149. TQCString name = "TDE_MULTIHEAD";
  150. TQCString value = multihead ? "true" : "false";
  151. TQByteArray params;
  152. TQDataStream stream(params, IO_WriteOnly);
  153. stream << name << value;
  154. kapp->dcopClient()->send("tdelauncher", "tdelauncher", "setLaunchEnv(TQCString,TQCString)", params);
  155. setenv( name, value, 1 ); // apply effect also to itself
  156. if( startup )
  157. {
  158. runModules( 0 );
  159. kapp->dcopClient()->send( "ksplash", "", "upAndRunning(TQString)", TQString("kcminit"));
  160. sendReady();
  161. TQTimer::singleShot( 300 * 1000, tqApp, TQT_SLOT( quit())); // just in case
  162. tqApp->exec(); // wait for runPhase1() and runPhase2()
  163. }
  164. else
  165. runModules( -1 ); // all phases
  166. }
  167. KCMInit::~KCMInit()
  168. {
  169. sendReady();
  170. }
  171. void KCMInit::runPhase1()
  172. {
  173. runModules( 1 );
  174. emitDCOPSignal( "phase1Done()", TQByteArray());
  175. }
  176. void KCMInit::runPhase2()
  177. {
  178. runModules( 2 );
  179. emitDCOPSignal( "phase2Done()", TQByteArray());
  180. tqApp->exit( 0 );
  181. }
  182. extern "C" KDE_EXPORT int kdemain(int argc, char *argv[])
  183. {
  184. // tdeinit waits for kcminit to finish, but during KDE startup
  185. // only important kcm's are started very early in the login process,
  186. // the rest is delayed, so fork and make parent return after the initial phase
  187. pipe( ready );
  188. if( fork() != 0 )
  189. {
  190. waitForReady();
  191. return 0;
  192. }
  193. close( ready[ 0 ] );
  194. startup = ( strcmp( argv[ 0 ], "kcminit_startup" ) == 0 ); // started from starttde?
  195. TDELocale::setMainCatalogue("kcontrol");
  196. TDEAboutData aboutData( "kcminit", I18N_NOOP("KCMInit"),
  197. "",
  198. I18N_NOOP("KCMInit - runs startups initialization for Control Modules."));
  199. TDECmdLineArgs::init(argc, argv, &aboutData);
  200. TDECmdLineArgs::addCmdLineOptions( options ); // Add our own options.
  201. TDEApplication app;
  202. app.dcopClient()->registerAs( "kcminit", false );
  203. TDELocale::setMainCatalogue(0);
  204. KCMInit kcminit( TDECmdLineArgs::parsedArgs());
  205. return 0;
  206. }
  207. #include "main.moc"