00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #ifdef HAVE_CONFIG_H
00020 #include <config.h>
00021 #endif
00022
00023 #include <stdio.h>
00024 #include <unistd.h>
00025 #include <stdlib.h>
00026 #include <errno.h>
00027 #include <signal.h>
00028 #include <sys/time.h>
00029
00030 #include <qfile.h>
00031
00032 #include <kconfig.h>
00033 #include <kdebug.h>
00034 #include <klibloader.h>
00035 #include <klocale.h>
00036 #include <kprotocolmanager.h>
00037 #include <kprotocolinfo.h>
00038 #include <krun.h>
00039 #include <kstandarddirs.h>
00040 #include <ktempfile.h>
00041 #include <kurl.h>
00042
00043 #if defined Q_WS_X11 && ! defined K_WS_QTONLY
00044 #include <kstartupinfo.h>
00045 #endif
00046
00047
00048 #include "kio/global.h"
00049 #include "kio/connection.h"
00050 #include "kio/slaveinterface.h"
00051
00052 #include "klauncher.h"
00053 #include "klauncher_cmds.h"
00054
00055
00056 #ifdef Q_WS_X11
00057
00058 #include <X11/Xlib.h>
00059 #endif
00060
00061
00062 #define SLAVE_MAX_IDLE 30
00063
00064 using namespace KIO;
00065
00066 template class QPtrList<KLaunchRequest>;
00067 template class QPtrList<IdleSlave>;
00068
00069 IdleSlave::IdleSlave(KSocket *socket)
00070 {
00071 mConn.init(socket);
00072 mConn.connect(this, SLOT(gotInput()));
00073 mConn.send( CMD_SLAVE_STATUS );
00074 mPid = 0;
00075 mBirthDate = time(0);
00076 mOnHold = false;
00077 }
00078
00079 void
00080 IdleSlave::gotInput()
00081 {
00082 int cmd;
00083 QByteArray data;
00084 if (mConn.read( &cmd, data) == -1)
00085 {
00086
00087 kdError(7016) << "SlavePool: No communication with slave." << endl;
00088 delete this;
00089 }
00090 else if (cmd == MSG_SLAVE_ACK)
00091 {
00092 delete this;
00093 }
00094 else if (cmd != MSG_SLAVE_STATUS)
00095 {
00096 kdError(7016) << "SlavePool: Unexpected data from slave." << endl;
00097 delete this;
00098 }
00099 else
00100 {
00101 QDataStream stream( data, IO_ReadOnly );
00102 pid_t pid;
00103 QCString protocol;
00104 QString host;
00105 Q_INT8 b;
00106 stream >> pid >> protocol >> host >> b;
00107
00108 if (!stream.atEnd())
00109 {
00110 KURL url;
00111 stream >> url;
00112 mOnHold = true;
00113 mUrl = url;
00114 }
00115
00116 mPid = pid;
00117 mConnected = (b != 0);
00118 mProtocol = protocol;
00119 mHost = host;
00120 emit statusUpdate(this);
00121 }
00122 }
00123
00124 void
00125 IdleSlave::connect(const QString &app_socket)
00126 {
00127 QByteArray data;
00128 QDataStream stream( data, IO_WriteOnly);
00129 stream << app_socket;
00130 mConn.send( CMD_SLAVE_CONNECT, data );
00131
00132 }
00133
00134 void
00135 IdleSlave::reparseConfiguration()
00136 {
00137 mConn.send( CMD_REPARSECONFIGURATION );
00138 }
00139
00140 bool
00141 IdleSlave::match(const QString &protocol, const QString &host, bool connected)
00142 {
00143 if (mOnHold) return false;
00144 if (protocol != mProtocol) return false;
00145 if (host.isEmpty()) return true;
00146 if (host != mHost) return false;
00147 if (!connected) return true;
00148 if (!mConnected) return false;
00149 return true;
00150 }
00151
00152 bool
00153 IdleSlave::onHold(const KURL &url)
00154 {
00155 if (!mOnHold) return false;
00156 return (url == mUrl);
00157 }
00158
00159 int
00160 IdleSlave::age(time_t now)
00161 {
00162 return (int) difftime(now, mBirthDate);
00163 }
00164
00165 KLauncher::KLauncher(int _kdeinitSocket, bool new_startup)
00166 : KApplication( false, false ),
00167 DCOPObject("klauncher"),
00168 kdeinitSocket(_kdeinitSocket), mAutoStart( new_startup ),
00169 dontBlockReading(false), newStartup( new_startup )
00170 {
00171 #ifdef Q_WS_X11
00172 mCached_dpy = NULL;
00173 #endif
00174 connect(&mAutoTimer, SIGNAL(timeout()), this, SLOT(slotAutoStart()));
00175 requestList.setAutoDelete(true);
00176 mSlaveWaitRequest.setAutoDelete(true);
00177 dcopClient()->setNotifications( true );
00178 connect(dcopClient(), SIGNAL( applicationRegistered( const QCString &)),
00179 this, SLOT( slotAppRegistered( const QCString &)));
00180 dcopClient()->connectDCOPSignal( "DCOPServer", "", "terminateKDE()",
00181 objId(), "terminateKDE()", false );
00182
00183 QString prefix = locateLocal("socket", "klauncher");
00184 KTempFile domainname(prefix, QString::fromLatin1(".slave-socket"));
00185 if (domainname.status() != 0)
00186 {
00187
00188 qDebug("KLauncher: Fatal error, can't create tempfile!");
00189 ::exit(1);
00190 }
00191 mPoolSocketName = domainname.name();
00192 #ifdef __CYGWIN__
00193 domainname.close();
00194 domainname.unlink();
00195 #endif
00196 mPoolSocket = new KServerSocket(QFile::encodeName(mPoolSocketName));
00197 connect(mPoolSocket, SIGNAL(accepted( KSocket *)),
00198 SLOT(acceptSlave(KSocket *)));
00199
00200 connect(&mTimer, SIGNAL(timeout()), SLOT(idleTimeout()));
00201
00202 kdeinitNotifier = new QSocketNotifier(kdeinitSocket, QSocketNotifier::Read);
00203 connect(kdeinitNotifier, SIGNAL( activated( int )),
00204 this, SLOT( slotKDEInitData( int )));
00205 kdeinitNotifier->setEnabled( true );
00206 lastRequest = 0;
00207 bProcessingQueue = false;
00208
00209 mSlaveDebug = getenv("KDE_SLAVE_DEBUG_WAIT");
00210 if (!mSlaveDebug.isEmpty())
00211 {
00212 qWarning("Klauncher running in slave-debug mode for slaves of protocol '%s'", mSlaveDebug.data());
00213 }
00214 mSlaveValgrind = getenv("KDE_SLAVE_VALGRIND");
00215 if (!mSlaveValgrind.isEmpty())
00216 {
00217 mSlaveValgrindSkin = getenv("KDE_SLAVE_VALGRIND_SKIN");
00218 qWarning("Klauncher running slaves through valgrind for slaves of protocol '%s'", mSlaveValgrind.data());
00219 }
00220 klauncher_header request_header;
00221 request_header.cmd = LAUNCHER_OK;
00222 request_header.arg_length = 0;
00223 write(kdeinitSocket, &request_header, sizeof(request_header));
00224
00225 {
00226 QString browser(::getenv("BROWSER"));
00227 if( browser.isEmpty() || browser == "/usr/bin/xbrowser" )
00228 {
00229 KConfig config("kdeglobals", true);
00230 config.setGroup("General");
00231 browser = config.readEntry("BrowserApplication");
00232 if (!browser.isEmpty())
00233 {
00234 if (browser.startsWith("!"))
00235 browser = browser.mid(1);
00236 }
00237 else
00238 browser = "/usr/bin/kfmclient openProfile webbrowsing";
00239 setLaunchEnv("BROWSER", browser.latin1());
00240
00241 QString help_browser(::getenv("HELP_BROWSER"));
00242 if( help_browser.isEmpty() )
00243 {
00244 setLaunchEnv("HELP_BROWSER", browser.latin1());
00245 }
00246 }
00247 QString mailer(::getenv("MAILER"));
00248 if( mailer.isEmpty() )
00249 {
00250 KConfig config("emaildefaults");
00251 config.setGroup("Defaults");
00252 QString group = config.readEntry("Profile","Default");
00253 config.setGroup( QString("PROFILE_%1").arg(group) );
00254 mailer = config.readPathEntry("EmailClient");
00255
00256 if( mailer.isEmpty() )
00257 {
00258 mailer = "kmail";
00259 }
00260 setLaunchEnv("MAILER", mailer.latin1());
00261 }
00262 }
00263 }
00264
00265 KLauncher::~KLauncher()
00266 {
00267 close();
00268 }
00269
00270 void KLauncher::close()
00271 {
00272 if (!mPoolSocketName.isEmpty())
00273 {
00274 QCString filename = QFile::encodeName(mPoolSocketName);
00275 unlink(filename.data());
00276 }
00277 #if defined Q_WS_X11 && ! defined K_WS_QTONLY
00278
00279 if( mCached_dpy != NULL )
00280 XCloseDisplay( mCached_dpy );
00281 #endif
00282 }
00283
00284 void
00285 KLauncher::destruct(int exit_code)
00286 {
00287 if (kapp) ((KLauncher*)kapp)->close();
00288
00289 ::exit(exit_code);
00290 }
00291
00292 bool
00293 KLauncher::process(const QCString &fun, const QByteArray &data,
00294 QCString &replyType, QByteArray &replyData)
00295 {
00296 if ((fun == "exec_blind(QCString,QValueList<QCString>)")
00297 || (fun == "exec_blind(QCString,QValueList<QCString>,QValueList<QCString>,QCString)"))
00298 {
00299 QDataStream stream(data, IO_ReadOnly);
00300 replyType = "void";
00301 QCString name;
00302 QValueList<QCString> arg_list;
00303 QCString startup_id = "0";
00304 QValueList<QCString> envs;
00305 stream >> name >> arg_list;
00306 if( fun == "exec_blind(QCString,QValueList<QCString>,QValueList<QCString>,QCString)" )
00307 stream >> envs >> startup_id;
00308 kdDebug(7016) << "KLauncher: Got exec_blind('" << name << "', ...)" << endl;
00309 exec_blind( name, arg_list, envs, startup_id);
00310 return true;
00311 }
00312 if ((fun == "start_service_by_name(QString,QStringList)") ||
00313 (fun == "start_service_by_desktop_path(QString,QStringList)")||
00314 (fun == "start_service_by_desktop_name(QString,QStringList)")||
00315 (fun == "kdeinit_exec(QString,QStringList)") ||
00316 (fun == "kdeinit_exec_wait(QString,QStringList)") ||
00317 (fun == "start_service_by_name(QString,QStringList,QValueList<QCString>,QCString)") ||
00318 (fun == "start_service_by_desktop_path(QString,QStringList,QValueList<QCString>,QCString)")||
00319 (fun == "start_service_by_desktop_name(QString,QStringList,QValueList<QCString>,QCString)") ||
00320 (fun == "start_service_by_name(QString,QStringList,QValueList<QCString>,QCString,bool)") ||
00321 (fun == "start_service_by_desktop_path(QString,QStringList,QValueList<QCString>,QCString,bool)")||
00322 (fun == "start_service_by_desktop_name(QString,QStringList,QValueList<QCString>,QCString,bool)") ||
00323 (fun == "kdeinit_exec(QString,QStringList,QValueList<QCString>)") ||
00324 (fun == "kdeinit_exec_wait(QString,QStringList,QValueList<QCString>)") ||
00325 (fun == "kdeinit_exec(QString,QStringList,QValueList<QCString>,QCString)") ||
00326 (fun == "kdeinit_exec_wait(QString,QStringList,QValueList<QCString>,QCString)"))
00327 {
00328 QDataStream stream(data, IO_ReadOnly);
00329 bool bNoWait = false;
00330 QString serviceName;
00331 QStringList urls;
00332 QValueList<QCString> envs;
00333 QCString startup_id = "";
00334 DCOPresult.result = -1;
00335 DCOPresult.dcopName = 0;
00336 DCOPresult.error = QString::null;
00337 DCOPresult.pid = 0;
00338 stream >> serviceName >> urls;
00339 if ((fun == "start_service_by_name(QString,QStringList,QValueList<QCString>,QCString,bool)") ||
00340 (fun == "start_service_by_desktop_path(QString,QStringList,QValueList<QCString>,QCString,bool)")||
00341 (fun == "start_service_by_desktop_name(QString,QStringList,QValueList<QCString>,QCString,bool)"))
00342 stream >> envs >> startup_id >> bNoWait;
00343 else if ((fun == "start_service_by_name(QString,QStringList,QValueList<QCString>,QCString)") ||
00344 (fun == "start_service_by_desktop_path(QString,QStringList,QValueList<QCString>,QCString)")||
00345 (fun == "start_service_by_desktop_name(QString,QStringList,QValueList<QCString>,QCString)"))
00346 stream >> envs >> startup_id;
00347 else if ((fun == "kdeinit_exec(QString,QStringList,QValueList<QCString>)") ||
00348 (fun == "kdeinit_exec_wait(QString,QStringList,QValueList<QCString>)"))
00349 stream >> envs;
00350 else if ((fun == "kdeinit_exec(QString,QStringList,QValueList<QCString>,QCString)") ||
00351 (fun == "kdeinit_exec_wait(QString,QStringList,QValueList<QCString>,QCString)"))
00352 stream >> envs >> startup_id;
00353 bool finished;
00354 if (strncmp(fun, "start_service_by_name(", 22) == 0)
00355 {
00356 kdDebug(7016) << "KLauncher: Got start_service_by_name('" << serviceName << "', ...)" << endl;
00357 finished = start_service_by_name(serviceName, urls, envs, startup_id, bNoWait);
00358 }
00359 else if (strncmp(fun, "start_service_by_desktop_path(", 30) == 0)
00360 {
00361 kdDebug(7016) << "KLauncher: Got start_service_by_desktop_path('" << serviceName << "', ...)" << endl;
00362 finished = start_service_by_desktop_path(serviceName, urls, envs, startup_id, bNoWait);
00363 }
00364 else if (strncmp(fun, "start_service_by_desktop_name(", 30) == 0)
00365 {
00366 kdDebug(7016) << "KLauncher: Got start_service_by_desktop_name('" << serviceName << "', ...)" << endl;
00367 finished = start_service_by_desktop_name(serviceName, urls, envs, startup_id, bNoWait );
00368 }
00369 else if ((fun == "kdeinit_exec(QString,QStringList)")
00370 || (fun == "kdeinit_exec(QString,QStringList,QValueList<QCString>)")
00371 || (fun == "kdeinit_exec(QString,QStringList,QValueList<QCString>,QCString)"))
00372 {
00373 kdDebug(7016) << "KLauncher: Got kdeinit_exec('" << serviceName << "', ...)" << endl;
00374 finished = kdeinit_exec(serviceName, urls, envs, startup_id, false);
00375 }
00376 else
00377 {
00378 kdDebug(7016) << "KLauncher: Got kdeinit_exec_wait('" << serviceName << "', ...)" << endl;
00379 finished = kdeinit_exec(serviceName, urls, envs, startup_id, true);
00380 }
00381 if (!finished)
00382 {
00383 replyType = "serviceResult";
00384 QDataStream stream2(replyData, IO_WriteOnly);
00385 stream2 << DCOPresult.result << DCOPresult.dcopName << DCOPresult.error << DCOPresult.pid;
00386 }
00387 return true;
00388 }
00389 else if (fun == "requestSlave(QString,QString,QString)")
00390 {
00391 QDataStream stream(data, IO_ReadOnly);
00392 QString protocol;
00393 QString host;
00394 QString app_socket;
00395 stream >> protocol >> host >> app_socket;
00396 replyType = "QString";
00397 QString error;
00398 pid_t pid = requestSlave(protocol, host, app_socket, error);
00399 QDataStream stream2(replyData, IO_WriteOnly);
00400 stream2 << pid << error;
00401 return true;
00402 }
00403 else if (fun == "requestHoldSlave(KURL,QString)")
00404 {
00405 QDataStream stream(data, IO_ReadOnly);
00406 KURL url;
00407 QString app_socket;
00408 stream >> url >> app_socket;
00409 replyType = "pid_t";
00410 pid_t pid = requestHoldSlave(url, app_socket);
00411 QDataStream stream2(replyData, IO_WriteOnly);
00412 stream2 << pid;
00413 return true;
00414 }
00415 else if (fun == "waitForSlave(pid_t)")
00416 {
00417 QDataStream stream(data, IO_ReadOnly);
00418 pid_t pid;
00419 stream >> pid;
00420 waitForSlave(pid);
00421 replyType = "void";
00422 return true;
00423
00424 }
00425 else if (fun == "setLaunchEnv(QCString,QCString)")
00426 {
00427 QDataStream stream(data, IO_ReadOnly);
00428 QCString name;
00429 QCString value;
00430 stream >> name >> value;
00431 setLaunchEnv(name, value);
00432 replyType = "void";
00433 return true;
00434 }
00435 else if (fun == "reparseConfiguration()")
00436 {
00437 KGlobal::config()->reparseConfiguration();
00438 kdDebug(7016) << "KLauncher::process : reparseConfiguration" << endl;
00439 KProtocolManager::reparseConfiguration();
00440 IdleSlave *slave;
00441 for(slave = mSlaveList.first(); slave; slave = mSlaveList.next())
00442 slave->reparseConfiguration();
00443 replyType = "void";
00444 return true;
00445 }
00446 else if (fun == "terminateKDE()")
00447 {
00448 ::signal( SIGHUP, SIG_IGN);
00449 ::signal( SIGTERM, SIG_IGN);
00450 kdDebug() << "KLauncher::process ---> terminateKDE" << endl;
00451 klauncher_header request_header;
00452 request_header.cmd = LAUNCHER_TERMINATE_KDE;
00453 request_header.arg_length = 0;
00454 write(kdeinitSocket, &request_header, sizeof(request_header));
00455 destruct(0);
00456 }
00457 else if (fun == "autoStart()")
00458 {
00459 kdDebug() << "KLauncher::process ---> autoStart" << endl;
00460 autoStart(1);
00461 replyType = "void";
00462 return true;
00463 }
00464 else if (fun == "autoStart(int)")
00465 {
00466 kdDebug() << "KLauncher::process ---> autoStart(int)" << endl;
00467 QDataStream stream(data, IO_ReadOnly);
00468 int phase;
00469 stream >> phase;
00470 autoStart(phase);
00471 replyType = "void";
00472 return true;
00473 }
00474
00475 if (DCOPObject::process(fun, data, replyType, replyData))
00476 {
00477 return true;
00478 }
00479 kdWarning(7016) << "Got unknown DCOP function: " << fun << endl;
00480 return false;
00481 }
00482
00483 QCStringList
00484 KLauncher::interfaces()
00485 {
00486 QCStringList ifaces = DCOPObject::interfaces();
00487 ifaces += "KLauncher";
00488 return ifaces;
00489 }
00490
00491 QCStringList
00492 KLauncher::functions()
00493 {
00494 QCStringList funcs = DCOPObject::functions();
00495 funcs << "void exec_blind(QCString,QValueList<QCString>)";
00496 funcs << "void exec_blind(QCString,QValueList<QCString>,QValueList<QCString>,QCString)";
00497 funcs << "serviceResult start_service_by_name(QString,QStringList)";
00498 funcs << "serviceResult start_service_by_desktop_path(QString,QStringList)";
00499 funcs << "serviceResult start_service_by_desktop_name(QString,QStringList)";
00500 funcs << "serviceResult kdeinit_exec(QString,QStringList)";
00501 funcs << "serviceResult kdeinit_exec_wait(QString,QStringList)";
00502 funcs << "serviceResult start_service_by_name(QString,QStringList,QValueList<QCString>,QCString)";
00503 funcs << "serviceResult start_service_by_desktop_path(QString,QStringList,QValueList<QCString>,QCString)";
00504 funcs << "serviceResult start_service_by_desktop_name(QString,QStringList,QValueList<QCString>,QCString)";
00505 funcs << "serviceResult start_service_by_name(QString,QStringList,QValueList<QCString>,QCString,bool)";
00506 funcs << "serviceResult start_service_by_desktop_path(QString,QStringList,QValueList<QCString>,QCString,bool)";
00507 funcs << "serviceResult start_service_by_desktop_name(QString,QStringList,QValueList<QCString>,QCString,bool)";
00508 funcs << "serviceResult kdeinit_exec(QString,QStringList,QValueList<QCString>)";
00509 funcs << "serviceResult kdeinit_exec_wait(QString,QStringList,QValueList<QCString>)";
00510 funcs << "QString requestSlave(QString,QString,QString)";
00511 funcs << "pid_t requestHoldSlave(KURL,QString)";
00512 funcs << "void waitForSlave(pid_t)";
00513 funcs << "void setLaunchEnv(QCString,QCString)";
00514 funcs << "void reparseConfiguration()";
00515
00516 funcs << "void autoStart()";
00517 funcs << "void autoStart(int)";
00518 return funcs;
00519 }
00520
00521 void KLauncher::setLaunchEnv(const QCString &name, const QCString &_value)
00522 {
00523 QCString value(_value);
00524 if (value.isNull())
00525 value = "";
00526 klauncher_header request_header;
00527 QByteArray requestData(name.length()+value.length()+2);
00528 memcpy(requestData.data(), name.data(), name.length()+1);
00529 memcpy(requestData.data()+name.length()+1, value.data(), value.length()+1);
00530 request_header.cmd = LAUNCHER_SETENV;
00531 request_header.arg_length = requestData.size();
00532 write(kdeinitSocket, &request_header, sizeof(request_header));
00533 write(kdeinitSocket, requestData.data(), request_header.arg_length);
00534 }
00535
00536
00537
00538
00539
00540 static int
00541 read_socket(int sock, char *buffer, int len)
00542 {
00543 ssize_t result;
00544 int bytes_left = len;
00545 while ( bytes_left > 0)
00546 {
00547 result = read(sock, buffer, bytes_left);
00548 if (result > 0)
00549 {
00550 buffer += result;
00551 bytes_left -= result;
00552 }
00553 else if (result == 0)
00554 return -1;
00555 else if ((result == -1) && (errno != EINTR))
00556 return -1;
00557 }
00558 return 0;
00559 }
00560
00561
00562 void
00563 KLauncher::slotKDEInitData(int)
00564 {
00565 klauncher_header request_header;
00566 QByteArray requestData;
00567 if( dontBlockReading )
00568 {
00569
00570
00571
00572
00573 fd_set in;
00574 timeval tm = { 0, 0 };
00575 FD_ZERO ( &in );
00576 FD_SET( kdeinitSocket, &in );
00577 select( kdeinitSocket + 1, &in, 0, 0, &tm );
00578 if( !FD_ISSET( kdeinitSocket, &in ))
00579 return;
00580 }
00581 dontBlockReading = false;
00582 int result = read_socket(kdeinitSocket, (char *) &request_header,
00583 sizeof( request_header));
00584 if (result == -1)
00585 {
00586 kdDebug() << "Exiting on read_socket errno: " << errno << endl;
00587 ::signal( SIGHUP, SIG_IGN);
00588 ::signal( SIGTERM, SIG_IGN);
00589 destruct(255);
00590 }
00591 requestData.resize(request_header.arg_length);
00592 result = read_socket(kdeinitSocket, (char *) requestData.data(),
00593 request_header.arg_length);
00594
00595 if (request_header.cmd == LAUNCHER_DIED)
00596 {
00597 long *request_data;
00598 request_data = (long *) requestData.data();
00599 processDied(request_data[0], request_data[1]);
00600 return;
00601 }
00602 if (lastRequest && (request_header.cmd == LAUNCHER_OK))
00603 {
00604 long *request_data;
00605 request_data = (long *) requestData.data();
00606 lastRequest->pid = (pid_t) (*request_data);
00607 kdDebug(7016) << lastRequest->name << " (pid " << lastRequest->pid <<
00608 ") up and running." << endl;
00609 switch(lastRequest->dcop_service_type)
00610 {
00611 case KService::DCOP_None:
00612 {
00613 lastRequest->status = KLaunchRequest::Running;
00614 break;
00615 }
00616
00617 case KService::DCOP_Unique:
00618 {
00619 lastRequest->status = KLaunchRequest::Launching;
00620 break;
00621 }
00622
00623 case KService::DCOP_Wait:
00624 {
00625 lastRequest->status = KLaunchRequest::Launching;
00626 break;
00627 }
00628
00629 case KService::DCOP_Multi:
00630 {
00631 lastRequest->status = KLaunchRequest::Launching;
00632 break;
00633 }
00634 }
00635 lastRequest = 0;
00636 return;
00637 }
00638 if (lastRequest && (request_header.cmd == LAUNCHER_ERROR))
00639 {
00640 lastRequest->status = KLaunchRequest::Error;
00641 if (!requestData.isEmpty())
00642 lastRequest->errorMsg = QString::fromUtf8((char *) requestData.data());
00643 lastRequest = 0;
00644 return;
00645 }
00646
00647 kdWarning(7016) << "Unexpected command from KDEInit (" << (unsigned int) request_header.cmd
00648 << ")" << endl;
00649 }
00650
00651 void
00652 KLauncher::processDied(pid_t pid, long )
00653 {
00654 KLaunchRequest *request = requestList.first();
00655 for(; request; request = requestList.next())
00656 {
00657 if (request->pid == pid)
00658 {
00659 if (request->dcop_service_type == KService::DCOP_Wait)
00660 request->status = KLaunchRequest::Done;
00661 else if ((request->dcop_service_type == KService::DCOP_Unique) &&
00662 (dcopClient()->isApplicationRegistered(request->dcop_name)))
00663 request->status = KLaunchRequest::Running;
00664 else
00665 request->status = KLaunchRequest::Error;
00666 requestDone(request);
00667 return;
00668 }
00669 }
00670 }
00671
00672 void
00673 KLauncher::slotAppRegistered(const QCString &appId)
00674 {
00675 const char *cAppId = appId.data();
00676 if (!cAppId) return;
00677
00678 KLaunchRequest *request = requestList.first();
00679 KLaunchRequest *nextRequest;
00680 for(; request; request = nextRequest)
00681 {
00682 nextRequest = requestList.next();
00683 if (request->status != KLaunchRequest::Launching)
00684 continue;
00685
00686
00687 if ((request->dcop_service_type == KService::DCOP_Unique) &&
00688 ((appId == request->dcop_name) ||
00689 dcopClient()->isApplicationRegistered(request->dcop_name)))
00690 {
00691 request->status = KLaunchRequest::Running;
00692 requestDone(request);
00693 continue;
00694 }
00695
00696 const char *rAppId = request->dcop_name.data();
00697 if (!rAppId) continue;
00698
00699 int l = strlen(rAppId);
00700 if ((strncmp(rAppId, cAppId, l) == 0) &&
00701 ((cAppId[l] == '\0') || (cAppId[l] == '-')))
00702 {
00703 request->dcop_name = appId;
00704 request->status = KLaunchRequest::Running;
00705 requestDone(request);
00706 continue;
00707 }
00708 }
00709 }
00710
00711 void
00712 KLauncher::autoStart(int phase)
00713 {
00714 if( mAutoStart.phase() >= phase )
00715 return;
00716 mAutoStart.setPhase(phase);
00717 if( newStartup )
00718 {
00719 if (phase == 0)
00720 mAutoStart.loadAutoStartList();
00721 }
00722 else
00723 {
00724 if (phase == 1)
00725 mAutoStart.loadAutoStartList();
00726 }
00727 mAutoTimer.start(0, true);
00728 }
00729
00730 void
00731 KLauncher::slotAutoStart()
00732 {
00733 KService::Ptr s;
00734 do
00735 {
00736 QString service = mAutoStart.startService();
00737 if (service.isEmpty())
00738 {
00739
00740 if( !mAutoStart.phaseDone())
00741 {
00742 mAutoStart.setPhaseDone();
00743
00744 if( newStartup )
00745 {
00746 QCString autoStartSignal;
00747 autoStartSignal.sprintf( "autoStart%dDone()", mAutoStart.phase());
00748 emitDCOPSignal(autoStartSignal, QByteArray());
00749 }
00750 else
00751 {
00752 QCString autoStartSignal( "autoStartDone()" );
00753 int phase = mAutoStart.phase();
00754 if ( phase > 1 )
00755 autoStartSignal.sprintf( "autoStart%dDone()", phase );
00756 emitDCOPSignal(autoStartSignal, QByteArray());
00757 }
00758 }
00759 return;
00760 }
00761 s = new KService(service);
00762 }
00763 while (!start_service(s, QStringList(), QValueList<QCString>(), "0", false, true));
00764
00765 }
00766
00767 void
00768 KLauncher::requestDone(KLaunchRequest *request)
00769 {
00770 if ((request->status == KLaunchRequest::Running) ||
00771 (request->status == KLaunchRequest::Done))
00772 {
00773 DCOPresult.result = 0;
00774 DCOPresult.dcopName = request->dcop_name;
00775 DCOPresult.error = QString::null;
00776 DCOPresult.pid = request->pid;
00777 }
00778 else
00779 {
00780 DCOPresult.result = 1;
00781 DCOPresult.dcopName = "";
00782 DCOPresult.error = i18n("KDEInit could not launch '%1'.").arg(request->name);
00783 if (!request->errorMsg.isEmpty())
00784 DCOPresult.error += ":\n" + request->errorMsg;
00785 DCOPresult.pid = 0;
00786
00787 #if defined Q_WS_X11 && ! defined K_WS_QTONLY
00788
00789 if (!request->startup_dpy.isEmpty())
00790 {
00791 Display* dpy = NULL;
00792 if( (mCached_dpy != NULL) &&
00793 (request->startup_dpy == XDisplayString( mCached_dpy )))
00794 dpy = mCached_dpy;
00795 if( dpy == NULL )
00796 dpy = XOpenDisplay( request->startup_dpy );
00797 if( dpy )
00798 {
00799 KStartupInfoId id;
00800 id.initId( request->startup_id );
00801 KStartupInfo::sendFinishX( dpy, id );
00802 if( mCached_dpy != dpy && mCached_dpy != NULL )
00803 XCloseDisplay( mCached_dpy );
00804 mCached_dpy = dpy;
00805 }
00806 }
00807 #endif
00808 }
00809
00810 if (request->autoStart)
00811 {
00812 mAutoTimer.start(0, true);
00813 }
00814
00815 if (request->transaction)
00816 {
00817 QByteArray replyData;
00818 QCString replyType;
00819 replyType = "serviceResult";
00820 QDataStream stream2(replyData, IO_WriteOnly);
00821 stream2 << DCOPresult.result << DCOPresult.dcopName << DCOPresult.error << DCOPresult.pid;
00822 dcopClient()->endTransaction( request->transaction,
00823 replyType, replyData);
00824 }
00825 requestList.removeRef( request );
00826 }
00827
00828 void
00829 KLauncher::requestStart(KLaunchRequest *request)
00830 {
00831 requestList.append( request );
00832
00833 klauncher_header request_header;
00834 QByteArray requestData;
00835 int length = 0;
00836 length += sizeof(long);
00837 length += request->name.length() + 1;
00838 for(QValueList<QCString>::Iterator it = request->arg_list.begin();
00839 it != request->arg_list.end();
00840 it++)
00841 {
00842 length += (*it).length() + 1;
00843 }
00844 length += sizeof(long);
00845 for(QValueList<QCString>::ConstIterator it = request->envs.begin();
00846 it != request->envs.end();
00847 it++)
00848 {
00849 length += (*it).length() + 1;
00850 }
00851 length += sizeof( long );
00852 #ifdef Q_WS_X11
00853 bool startup_notify = !request->startup_id.isNull() && request->startup_id != "0";
00854 if( startup_notify )
00855 length += request->startup_id.length() + 1;
00856 #endif
00857 if (!request->cwd.isEmpty())
00858 length += request->cwd.length() + 1;
00859
00860 requestData.resize( length );
00861
00862 char *p = requestData.data();
00863 long l = request->arg_list.count()+1;
00864 memcpy(p, &l, sizeof(long));
00865 p += sizeof(long);
00866 strcpy(p, request->name.data());
00867 p += strlen(p) + 1;
00868 for(QValueList<QCString>::Iterator it = request->arg_list.begin();
00869 it != request->arg_list.end();
00870 it++)
00871 {
00872 strcpy(p, (*it).data());
00873 p += strlen(p) + 1;
00874 }
00875 l = request->envs.count();
00876 memcpy(p, &l, sizeof(long));
00877 p += sizeof(long);
00878 for(QValueList<QCString>::ConstIterator it = request->envs.begin();
00879 it != request->envs.end();
00880 it++)
00881 {
00882 strcpy(p, (*it).data());
00883 p += strlen(p) + 1;
00884 }
00885 l = 0;
00886 memcpy(p, &l, sizeof(long));
00887 p += sizeof(long);
00888 #ifdef Q_WS_X11
00889 if( startup_notify )
00890 {
00891 strcpy(p, request->startup_id.data());
00892 p += strlen( p ) + 1;
00893 }
00894 #endif
00895 if (!request->cwd.isEmpty())
00896 {
00897 strcpy(p, request->cwd.data());
00898 p += strlen( p ) + 1;
00899 }
00900 #ifdef Q_WS_X11
00901 request_header.cmd = startup_notify ? LAUNCHER_EXT_EXEC : LAUNCHER_EXEC_NEW;
00902 #else
00903 request_header.cmd = LAUNCHER_EXEC_NEW;
00904 #endif
00905 request_header.arg_length = length;
00906 write(kdeinitSocket, &request_header, sizeof(request_header));
00907 write(kdeinitSocket, requestData.data(), request_header.arg_length);
00908
00909
00910 lastRequest = request;
00911 dontBlockReading = false;
00912 do {
00913 slotKDEInitData( kdeinitSocket );
00914 }
00915 while (lastRequest != 0);
00916 dontBlockReading = true;
00917 }
00918
00919 void
00920 KLauncher::exec_blind( const QCString &name, const QValueList<QCString> &arg_list,
00921 const QValueList<QCString> &envs, const QCString& startup_id )
00922 {
00923 KLaunchRequest *request = new KLaunchRequest;
00924 request->autoStart = false;
00925 request->name = name;
00926 request->arg_list = arg_list;
00927 request->dcop_name = 0;
00928 request->dcop_service_type = KService::DCOP_None;
00929 request->pid = 0;
00930 request->status = KLaunchRequest::Launching;
00931 request->transaction = 0;
00932 request->envs = envs;
00933
00934 KService::Ptr service = KService::serviceByDesktopName( name.mid( name.findRev( '/' ) + 1 ));
00935 if (service != NULL)
00936 send_service_startup_info( request, service,
00937 startup_id, QValueList< QCString >());
00938 else
00939 cancel_service_startup_info( request, startup_id, envs );
00940
00941 requestStart(request);
00942
00943 requestDone(request);
00944 }
00945
00946
00947 bool
00948 KLauncher::start_service_by_name(const QString &serviceName, const QStringList &urls,
00949 const QValueList<QCString> &envs, const QCString& startup_id, bool blind)
00950 {
00951 KService::Ptr service = 0;
00952
00953 service = KService::serviceByName(serviceName);
00954 if (!service)
00955 {
00956 DCOPresult.result = ENOENT;
00957 DCOPresult.error = i18n("Could not find service '%1'.").arg(serviceName);
00958 cancel_service_startup_info( NULL, startup_id, envs );
00959 return false;
00960 }
00961 return start_service(service, urls, envs, startup_id, blind);
00962 }
00963
00964 bool
00965 KLauncher::start_service_by_desktop_path(const QString &serviceName, const QStringList &urls,
00966 const QValueList<QCString> &envs, const QCString& startup_id, bool blind)
00967 {
00968 KService::Ptr service = 0;
00969
00970 if (serviceName[0] == '/')
00971 {
00972
00973 service = new KService(serviceName);
00974 }
00975 else
00976 {
00977 service = KService::serviceByDesktopPath(serviceName);
00978 }
00979 if (!service)
00980 {
00981 DCOPresult.result = ENOENT;
00982 DCOPresult.error = i18n("Could not find service '%1'.").arg(serviceName);
00983 cancel_service_startup_info( NULL, startup_id, envs );
00984 return false;
00985 }
00986 return start_service(service, urls, envs, startup_id, blind);
00987 }
00988
00989 bool
00990 KLauncher::start_service_by_desktop_name(const QString &serviceName, const QStringList &urls,
00991 const QValueList<QCString> &envs, const QCString& startup_id, bool blind)
00992 {
00993 KService::Ptr service = 0;
00994
00995 service = KService::serviceByDesktopName(serviceName);
00996 if (!service)
00997 {
00998 DCOPresult.result = ENOENT;
00999 DCOPresult.error = i18n("Could not find service '%1'.").arg(serviceName);
01000 cancel_service_startup_info( NULL, startup_id, envs );
01001 return false;
01002 }
01003 return start_service(service, urls, envs, startup_id, blind);
01004 }
01005
01006 bool
01007 KLauncher::start_service(KService::Ptr service, const QStringList &_urls,
01008 const QValueList<QCString> &envs, const QCString& startup_id, bool blind, bool autoStart)
01009 {
01010 QStringList urls = _urls;
01011 if (!service->isValid())
01012 {
01013 DCOPresult.result = ENOEXEC;
01014 DCOPresult.error = i18n("Service '%1' is malformatted.").arg(service->desktopEntryPath());
01015 cancel_service_startup_info( NULL, startup_id, envs );
01016 return false;
01017 }
01018 KLaunchRequest *request = new KLaunchRequest;
01019 request->autoStart = autoStart;
01020
01021 if ((urls.count() > 1) && !service->allowMultipleFiles())
01022 {
01023
01024
01025
01026
01027
01028 QStringList::ConstIterator it = urls.begin();
01029 for(++it;
01030 it != urls.end();
01031 ++it)
01032 {
01033 QStringList singleUrl;
01034 singleUrl.append(*it);
01035 QCString startup_id2 = startup_id;
01036 if( !startup_id2.isEmpty() && startup_id2 != "0" )
01037 startup_id2 = "0";
01038 start_service( service, singleUrl, envs, startup_id2, true);
01039 }
01040 QString firstURL = *(urls.begin());
01041 urls.clear();
01042 urls.append(firstURL);
01043 }
01044 createArgs(request, service, urls);
01045
01046
01047 if (!request->arg_list.count())
01048 {
01049 DCOPresult.result = ENOEXEC;
01050 DCOPresult.error = i18n("Service '%1' is malformatted.").arg(service->desktopEntryPath());
01051 delete request;
01052 cancel_service_startup_info( NULL, startup_id, envs );
01053 return false;
01054 }
01055
01056 request->name = request->arg_list.first();
01057 request->arg_list.remove(request->arg_list.begin());
01058
01059 request->dcop_service_type = service->DCOPServiceType();
01060
01061 if ((request->dcop_service_type == KService::DCOP_Unique) ||
01062 (request->dcop_service_type == KService::DCOP_Multi))
01063 {
01064 QVariant v = service->property("X-DCOP-ServiceName");
01065 if (v.isValid())
01066 request->dcop_name = v.toString().utf8();
01067 if (request->dcop_name.isEmpty())
01068 {
01069 request->dcop_name = QFile::encodeName(KRun::binaryName(service->exec(), true));
01070 }
01071 }
01072
01073 request->pid = 0;
01074 request->transaction = 0;
01075 request->envs = envs;
01076 send_service_startup_info( request, service, startup_id, envs );
01077
01078
01079 if (!blind && !autoStart)
01080 {
01081 request->transaction = dcopClient()->beginTransaction();
01082 }
01083 queueRequest(request);
01084 return true;
01085 }
01086
01087 void
01088 KLauncher::send_service_startup_info( KLaunchRequest *request, KService::Ptr service, const QCString& startup_id,
01089 const QValueList<QCString> &envs )
01090 {
01091 #if defined Q_WS_X11 && ! defined K_WS_QTONLY
01092
01093 request->startup_id = "0";
01094 if( startup_id == "0" )
01095 return;
01096 bool silent;
01097 QCString wmclass;
01098 if( !KRun::checkStartupNotify( QString::null, service, &silent, &wmclass ))
01099 return;
01100 KStartupInfoId id;
01101 id.initId( startup_id );
01102 const char* dpy_str = NULL;
01103 for( QValueList<QCString>::ConstIterator it = envs.begin();
01104 it != envs.end();
01105 ++it )
01106 if( strncmp( *it, "DISPLAY=", 8 ) == 0 )
01107 dpy_str = static_cast< const char* >( *it ) + 8;
01108 Display* dpy = NULL;
01109 if( dpy_str != NULL && mCached_dpy != NULL
01110 && qstrcmp( dpy_str, XDisplayString( mCached_dpy )) == 0 )
01111 dpy = mCached_dpy;
01112 if( dpy == NULL )
01113 dpy = XOpenDisplay( dpy_str );
01114 request->startup_id = id.id();
01115 if( dpy == NULL )
01116 {
01117 cancel_service_startup_info( request, startup_id, envs );
01118 return;
01119 }
01120
01121 request->startup_dpy = dpy_str;
01122
01123 KStartupInfoData data;
01124 data.setName( service->name());
01125 data.setIcon( service->icon());
01126 data.setDescription( i18n( "Launching %1" ).arg( service->name()));
01127 if( !wmclass.isEmpty())
01128 data.setWMClass( wmclass );
01129 if( silent )
01130 data.setSilent( KStartupInfoData::Yes );
01131
01132 KStartupInfo::sendStartupX( dpy, id, data );
01133 if( mCached_dpy != dpy && mCached_dpy != NULL )
01134 XCloseDisplay( mCached_dpy );
01135 mCached_dpy = dpy;
01136 return;
01137 #else
01138 return;
01139 #endif
01140 }
01141
01142 void
01143 KLauncher::cancel_service_startup_info( KLaunchRequest* request, const QCString& startup_id,
01144 const QValueList<QCString> &envs )
01145 {
01146 #if defined Q_WS_X11 && ! defined K_WS_QTONLY
01147
01148 if( request != NULL )
01149 request->startup_id = "0";
01150 if( !startup_id.isEmpty() && startup_id != "0" )
01151 {
01152 const char* dpy_str = NULL;
01153 for( QValueList<QCString>::ConstIterator it = envs.begin();
01154 it != envs.end();
01155 ++it )
01156 if( strncmp( *it, "DISPLAY=", 8 ) == 0 )
01157 dpy_str = static_cast< const char* >( *it ) + 8;
01158 Display* dpy = NULL;
01159 if( dpy_str != NULL && mCached_dpy != NULL
01160 && qstrcmp( dpy_str, XDisplayString( mCached_dpy )) == 0 )
01161 dpy = mCached_dpy;
01162 if( dpy == NULL )
01163 dpy = XOpenDisplay( dpy_str );
01164 if( dpy == NULL )
01165 return;
01166 KStartupInfoId id;
01167 id.initId( startup_id );
01168 KStartupInfo::sendFinishX( dpy, id );
01169 if( mCached_dpy != dpy && mCached_dpy != NULL )
01170 XCloseDisplay( mCached_dpy );
01171 mCached_dpy = dpy;
01172 }
01173 #endif
01174 }
01175
01176 bool
01177 KLauncher::kdeinit_exec(const QString &app, const QStringList &args,
01178 const QValueList<QCString> &envs, QCString startup_id, bool wait)
01179 {
01180 KLaunchRequest *request = new KLaunchRequest;
01181 request->autoStart = false;
01182
01183 for(QStringList::ConstIterator it = args.begin();
01184 it != args.end();
01185 it++)
01186 {
01187 QString arg = *it;
01188 request->arg_list.append(arg.local8Bit());
01189 }
01190
01191 request->name = app.local8Bit();
01192
01193 if (wait)
01194 request->dcop_service_type = KService::DCOP_Wait;
01195 else
01196 request->dcop_service_type = KService::DCOP_None;
01197 request->dcop_name = 0;
01198 request->pid = 0;
01199 #ifdef Q_WS_X11
01200 request->startup_id = startup_id;
01201 #endif
01202 request->envs = envs;
01203 if( app != "kbuildsycoca" )
01204 {
01205
01206 KService::Ptr service = KService::serviceByDesktopName( app.mid( app.findRev( '/' ) + 1 ));
01207 if (service != NULL)
01208 send_service_startup_info( request, service,
01209 startup_id, QValueList< QCString >());
01210 else
01211 cancel_service_startup_info( request, startup_id, envs );
01212 }
01213 request->transaction = dcopClient()->beginTransaction();
01214 queueRequest(request);
01215 return true;
01216 }
01217
01218 void
01219 KLauncher::queueRequest(KLaunchRequest *request)
01220 {
01221 requestQueue.append( request );
01222 if (!bProcessingQueue)
01223 {
01224 bProcessingQueue = true;
01225 QTimer::singleShot(0, this, SLOT( slotDequeue() ));
01226 }
01227 }
01228
01229 void
01230 KLauncher::slotDequeue()
01231 {
01232 do {
01233 KLaunchRequest *request = requestQueue.take(0);
01234
01235 request->status = KLaunchRequest::Launching;
01236 requestStart(request);
01237 if (request->status != KLaunchRequest::Launching)
01238 {
01239
01240 requestDone( request );
01241 continue;
01242 }
01243 } while(requestQueue.count());
01244 bProcessingQueue = false;
01245 }
01246
01247 void
01248 KLauncher::createArgs( KLaunchRequest *request, const KService::Ptr service ,
01249 const QStringList &urls)
01250 {
01251 QStringList params = KRun::processDesktopExec(*service, urls, false);
01252
01253 for(QStringList::ConstIterator it = params.begin();
01254 it != params.end(); ++it)
01255 {
01256 request->arg_list.append((*it).local8Bit());
01257 }
01258 request->cwd = QFile::encodeName(service->path());
01259 }
01260
01262
01263 pid_t
01264 KLauncher::requestHoldSlave(const KURL &url, const QString &app_socket)
01265 {
01266 IdleSlave *slave;
01267 for(slave = mSlaveList.first(); slave; slave = mSlaveList.next())
01268 {
01269 if (slave->onHold(url))
01270 break;
01271 }
01272 if (slave)
01273 {
01274 mSlaveList.removeRef(slave);
01275 slave->connect(app_socket);
01276 return slave->pid();
01277 }
01278 return 0;
01279 }
01280
01281
01282 pid_t
01283 KLauncher::requestSlave(const QString &protocol,
01284 const QString &host,
01285 const QString &app_socket,
01286 QString &error)
01287 {
01288 IdleSlave *slave;
01289 for(slave = mSlaveList.first(); slave; slave = mSlaveList.next())
01290 {
01291 if (slave->match(protocol, host, true))
01292 break;
01293 }
01294 if (!slave)
01295 {
01296 for(slave = mSlaveList.first(); slave; slave = mSlaveList.next())
01297 {
01298 if (slave->match(protocol, host, false))
01299 break;
01300 }
01301 }
01302 if (!slave)
01303 {
01304 for(slave = mSlaveList.first(); slave; slave = mSlaveList.next())
01305 {
01306 if (slave->match(protocol, QString::null, false))
01307 break;
01308 }
01309 }
01310 if (slave)
01311 {
01312 mSlaveList.removeRef(slave);
01313 slave->connect(app_socket);
01314 return slave->pid();
01315 }
01316
01317 QString _name = KProtocolInfo::exec(protocol);
01318 if (_name.isEmpty())
01319 {
01320 error = i18n("Unknown protocol '%1'.\n").arg(protocol);
01321 return 0;
01322 }
01323
01324 QCString name = _name.latin1();
01325 QCString arg1 = protocol.latin1();
01326 QCString arg2 = QFile::encodeName(mPoolSocketName);
01327 QCString arg3 = QFile::encodeName(app_socket);
01328 QValueList<QCString> arg_list;
01329 arg_list.append(arg1);
01330 arg_list.append(arg2);
01331 arg_list.append(arg3);
01332
01333
01334 if (mSlaveDebug == arg1)
01335 {
01336 klauncher_header request_header;
01337 request_header.cmd = LAUNCHER_DEBUG_WAIT;
01338 request_header.arg_length = 0;
01339 write(kdeinitSocket, &request_header, sizeof(request_header));
01340 }
01341 if (mSlaveValgrind == arg1)
01342 {
01343 arg_list.prepend(QFile::encodeName(KLibLoader::findLibrary(name)));
01344 arg_list.prepend(QFile::encodeName(locate("exe", "kioslave")));
01345 name = "valgrind";
01346 if (!mSlaveValgrindSkin.isEmpty()) {
01347 arg_list.prepend(QCString("--tool=") + mSlaveValgrindSkin);
01348 } else
01349 arg_list.prepend("--tool=memcheck");
01350 }
01351
01352 KLaunchRequest *request = new KLaunchRequest;
01353 request->autoStart = false;
01354 request->name = name;
01355 request->arg_list = arg_list;
01356 request->dcop_name = 0;
01357 request->dcop_service_type = KService::DCOP_None;
01358 request->pid = 0;
01359 #ifdef Q_WS_X11
01360 request->startup_id = "0";
01361 #endif
01362 request->status = KLaunchRequest::Launching;
01363 request->transaction = 0;
01364 requestStart(request);
01365 pid_t pid = request->pid;
01366
01367
01368
01369
01370 requestDone(request);
01371 if (!pid)
01372 {
01373 error = i18n("Error loading '%1'.\n").arg(name);
01374 }
01375 return pid;
01376 }
01377
01378 void
01379 KLauncher::waitForSlave(pid_t pid)
01380 {
01381 IdleSlave *slave;
01382 for(slave = mSlaveList.first(); slave; slave = mSlaveList.next())
01383 {
01384 if (slave->pid() == pid)
01385 return;
01386 }
01387 SlaveWaitRequest *waitRequest = new SlaveWaitRequest;
01388 waitRequest->transaction = dcopClient()->beginTransaction();
01389 waitRequest->pid = pid;
01390 mSlaveWaitRequest.append(waitRequest);
01391 }
01392
01393 void
01394 KLauncher::acceptSlave(KSocket *slaveSocket)
01395 {
01396 IdleSlave *slave = new IdleSlave(slaveSocket);
01397
01398 mSlaveList.append(slave);
01399 connect(slave, SIGNAL(destroyed()), this, SLOT(slotSlaveGone()));
01400 connect(slave, SIGNAL(statusUpdate(IdleSlave *)),
01401 this, SLOT(slotSlaveStatus(IdleSlave *)));
01402 if (!mTimer.isActive())
01403 {
01404 mTimer.start(1000*10);
01405 }
01406 }
01407
01408 void
01409 KLauncher::slotSlaveStatus(IdleSlave *slave)
01410 {
01411 SlaveWaitRequest *waitRequest = mSlaveWaitRequest.first();
01412 while(waitRequest)
01413 {
01414 if (waitRequest->pid == slave->pid())
01415 {
01416 QByteArray replyData;
01417 QCString replyType;
01418 replyType = "void";
01419 dcopClient()->endTransaction( waitRequest->transaction, replyType, replyData);
01420 mSlaveWaitRequest.removeRef(waitRequest);
01421 waitRequest = mSlaveWaitRequest.current();
01422 }
01423 else
01424 {
01425 waitRequest = mSlaveWaitRequest.next();
01426 }
01427 }
01428 }
01429
01430 void
01431 KLauncher::slotSlaveGone()
01432 {
01433 IdleSlave *slave = (IdleSlave *) sender();
01434 mSlaveList.removeRef(slave);
01435 if ((mSlaveList.count() == 0) && (mTimer.isActive()))
01436 {
01437 mTimer.stop();
01438 }
01439 }
01440
01441 void
01442 KLauncher::idleTimeout()
01443 {
01444 bool keepOneFileSlave=true;
01445 time_t now = time(0);
01446 IdleSlave *slave;
01447 for(slave = mSlaveList.first(); slave; slave = mSlaveList.next())
01448 {
01449 if ((slave->protocol()=="file") && (keepOneFileSlave))
01450 keepOneFileSlave=false;
01451 else if (slave->age(now) > SLAVE_MAX_IDLE)
01452 {
01453
01454 delete slave;
01455 }
01456 }
01457 }
01458
01459 #include "klauncher.moc"