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 KLauncher::~KLauncher()
00227 {
00228 close();
00229 }
00230
00231 void KLauncher::close()
00232 {
00233 if (!mPoolSocketName.isEmpty())
00234 {
00235 QCString filename = QFile::encodeName(mPoolSocketName);
00236 unlink(filename.data());
00237 }
00238 #if defined Q_WS_X11 && ! defined K_WS_QTONLY
00239
00240 if( mCached_dpy != NULL )
00241 XCloseDisplay( mCached_dpy );
00242 #endif
00243 }
00244
00245 void
00246 KLauncher::destruct(int exit_code)
00247 {
00248 if (kapp) ((KLauncher*)kapp)->close();
00249
00250 ::exit(exit_code);
00251 }
00252
00253 bool
00254 KLauncher::process(const QCString &fun, const QByteArray &data,
00255 QCString &replyType, QByteArray &replyData)
00256 {
00257 if ((fun == "exec_blind(QCString,QValueList<QCString>)")
00258 || (fun == "exec_blind(QCString,QValueList<QCString>,QValueList<QCString>,QCString)"))
00259 {
00260 QDataStream stream(data, IO_ReadOnly);
00261 replyType = "void";
00262 QCString name;
00263 QValueList<QCString> arg_list;
00264 QCString startup_id = "0";
00265 QValueList<QCString> envs;
00266 stream >> name >> arg_list;
00267 if( fun == "exec_blind(QCString,QValueList<QCString>,QValueList<QCString>,QCString)" )
00268 stream >> envs >> startup_id;
00269 kdDebug(7016) << "KLauncher: Got exec_blind('" << name << "', ...)" << endl;
00270 exec_blind( name, arg_list, envs, startup_id);
00271 return true;
00272 }
00273 if ((fun == "start_service_by_name(QString,QStringList)") ||
00274 (fun == "start_service_by_desktop_path(QString,QStringList)")||
00275 (fun == "start_service_by_desktop_name(QString,QStringList)")||
00276 (fun == "kdeinit_exec(QString,QStringList)") ||
00277 (fun == "kdeinit_exec_wait(QString,QStringList)") ||
00278 (fun == "start_service_by_name(QString,QStringList,QValueList<QCString>,QCString)") ||
00279 (fun == "start_service_by_desktop_path(QString,QStringList,QValueList<QCString>,QCString)")||
00280 (fun == "start_service_by_desktop_name(QString,QStringList,QValueList<QCString>,QCString)") ||
00281 (fun == "start_service_by_name(QString,QStringList,QValueList<QCString>,QCString,bool)") ||
00282 (fun == "start_service_by_desktop_path(QString,QStringList,QValueList<QCString>,QCString,bool)")||
00283 (fun == "start_service_by_desktop_name(QString,QStringList,QValueList<QCString>,QCString,bool)") ||
00284 (fun == "kdeinit_exec(QString,QStringList,QValueList<QCString>)") ||
00285 (fun == "kdeinit_exec_wait(QString,QStringList,QValueList<QCString>)") ||
00286 (fun == "kdeinit_exec(QString,QStringList,QValueList<QCString>,QCString)") ||
00287 (fun == "kdeinit_exec_wait(QString,QStringList,QValueList<QCString>,QCString)"))
00288 {
00289 QDataStream stream(data, IO_ReadOnly);
00290 bool bNoWait = false;
00291 QString serviceName;
00292 QStringList urls;
00293 QValueList<QCString> envs;
00294 QCString startup_id = "";
00295 DCOPresult.result = -1;
00296 DCOPresult.dcopName = 0;
00297 DCOPresult.error = QString::null;
00298 DCOPresult.pid = 0;
00299 stream >> serviceName >> urls;
00300 if ((fun == "start_service_by_name(QString,QStringList,QValueList<QCString>,QCString,bool)") ||
00301 (fun == "start_service_by_desktop_path(QString,QStringList,QValueList<QCString>,QCString,bool)")||
00302 (fun == "start_service_by_desktop_name(QString,QStringList,QValueList<QCString>,QCString,bool)"))
00303 stream >> envs >> startup_id >> bNoWait;
00304 else if ((fun == "start_service_by_name(QString,QStringList,QValueList<QCString>,QCString)") ||
00305 (fun == "start_service_by_desktop_path(QString,QStringList,QValueList<QCString>,QCString)")||
00306 (fun == "start_service_by_desktop_name(QString,QStringList,QValueList<QCString>,QCString)"))
00307 stream >> envs >> startup_id;
00308 else if ((fun == "kdeinit_exec(QString,QStringList,QValueList<QCString>)") ||
00309 (fun == "kdeinit_exec_wait(QString,QStringList,QValueList<QCString>)"))
00310 stream >> envs;
00311 else if ((fun == "kdeinit_exec(QString,QStringList,QValueList<QCString>,QCString)") ||
00312 (fun == "kdeinit_exec_wait(QString,QStringList,QValueList<QCString>,QCString)"))
00313 stream >> envs >> startup_id;
00314 bool finished;
00315 if (strncmp(fun, "start_service_by_name(", 22) == 0)
00316 {
00317 kdDebug(7016) << "KLauncher: Got start_service_by_name('" << serviceName << "', ...)" << endl;
00318 finished = start_service_by_name(serviceName, urls, envs, startup_id, bNoWait);
00319 }
00320 else if (strncmp(fun, "start_service_by_desktop_path(", 30) == 0)
00321 {
00322 kdDebug(7016) << "KLauncher: Got start_service_by_desktop_path('" << serviceName << "', ...)" << endl;
00323 finished = start_service_by_desktop_path(serviceName, urls, envs, startup_id, bNoWait);
00324 }
00325 else if (strncmp(fun, "start_service_by_desktop_name(", 30) == 0)
00326 {
00327 kdDebug(7016) << "KLauncher: Got start_service_by_desktop_name('" << serviceName << "', ...)" << endl;
00328 finished = start_service_by_desktop_name(serviceName, urls, envs, startup_id, bNoWait );
00329 }
00330 else if ((fun == "kdeinit_exec(QString,QStringList)")
00331 || (fun == "kdeinit_exec(QString,QStringList,QValueList<QCString>)")
00332 || (fun == "kdeinit_exec(QString,QStringList,QValueList<QCString>,QCString)"))
00333 {
00334 kdDebug(7016) << "KLauncher: Got kdeinit_exec('" << serviceName << "', ...)" << endl;
00335 finished = kdeinit_exec(serviceName, urls, envs, startup_id, false);
00336 }
00337 else
00338 {
00339 kdDebug(7016) << "KLauncher: Got kdeinit_exec_wait('" << serviceName << "', ...)" << endl;
00340 finished = kdeinit_exec(serviceName, urls, envs, startup_id, true);
00341 }
00342 if (!finished)
00343 {
00344 replyType = "serviceResult";
00345 QDataStream stream2(replyData, IO_WriteOnly);
00346 stream2 << DCOPresult.result << DCOPresult.dcopName << DCOPresult.error << DCOPresult.pid;
00347 }
00348 return true;
00349 }
00350 else if (fun == "requestSlave(QString,QString,QString)")
00351 {
00352 QDataStream stream(data, IO_ReadOnly);
00353 QString protocol;
00354 QString host;
00355 QString app_socket;
00356 stream >> protocol >> host >> app_socket;
00357 replyType = "QString";
00358 QString error;
00359 pid_t pid = requestSlave(protocol, host, app_socket, error);
00360 QDataStream stream2(replyData, IO_WriteOnly);
00361 stream2 << pid << error;
00362 return true;
00363 }
00364 else if (fun == "requestHoldSlave(KURL,QString)")
00365 {
00366 QDataStream stream(data, IO_ReadOnly);
00367 KURL url;
00368 QString app_socket;
00369 stream >> url >> app_socket;
00370 replyType = "pid_t";
00371 pid_t pid = requestHoldSlave(url, app_socket);
00372 QDataStream stream2(replyData, IO_WriteOnly);
00373 stream2 << pid;
00374 return true;
00375 }
00376 else if (fun == "waitForSlave(pid_t)")
00377 {
00378 QDataStream stream(data, IO_ReadOnly);
00379 pid_t pid;
00380 stream >> pid;
00381 waitForSlave(pid);
00382 replyType = "void";
00383 return true;
00384
00385 }
00386 else if (fun == "setLaunchEnv(QCString,QCString)")
00387 {
00388 QDataStream stream(data, IO_ReadOnly);
00389 QCString name;
00390 QCString value;
00391 stream >> name >> value;
00392 setLaunchEnv(name, value);
00393 replyType = "void";
00394 return true;
00395 }
00396 else if (fun == "reparseConfiguration()")
00397 {
00398 KGlobal::config()->reparseConfiguration();
00399 kdDebug(7016) << "KLauncher::process : reparseConfiguration" << endl;
00400 KProtocolManager::reparseConfiguration();
00401 IdleSlave *slave;
00402 for(slave = mSlaveList.first(); slave; slave = mSlaveList.next())
00403 slave->reparseConfiguration();
00404 replyType = "void";
00405 return true;
00406 }
00407 else if (fun == "terminateKDE()")
00408 {
00409 ::signal( SIGHUP, SIG_IGN);
00410 ::signal( SIGTERM, SIG_IGN);
00411 kdDebug() << "KLauncher::process ---> terminateKDE" << endl;
00412 klauncher_header request_header;
00413 request_header.cmd = LAUNCHER_TERMINATE_KDE;
00414 request_header.arg_length = 0;
00415 write(kdeinitSocket, &request_header, sizeof(request_header));
00416 destruct(0);
00417 }
00418 else if (fun == "autoStart()")
00419 {
00420 kdDebug() << "KLauncher::process ---> autoStart" << endl;
00421 autoStart(1);
00422 replyType = "void";
00423 return true;
00424 }
00425 else if (fun == "autoStart(int)")
00426 {
00427 kdDebug() << "KLauncher::process ---> autoStart(int)" << endl;
00428 QDataStream stream(data, IO_ReadOnly);
00429 int phase;
00430 stream >> phase;
00431 autoStart(phase);
00432 replyType = "void";
00433 return true;
00434 }
00435
00436 if (DCOPObject::process(fun, data, replyType, replyData))
00437 {
00438 return true;
00439 }
00440 kdWarning(7016) << "Got unknown DCOP function: " << fun << endl;
00441 return false;
00442 }
00443
00444 QCStringList
00445 KLauncher::interfaces()
00446 {
00447 QCStringList ifaces = DCOPObject::interfaces();
00448 ifaces += "KLauncher";
00449 return ifaces;
00450 }
00451
00452 QCStringList
00453 KLauncher::functions()
00454 {
00455 QCStringList funcs = DCOPObject::functions();
00456 funcs << "void exec_blind(QCString,QValueList<QCString>)";
00457 funcs << "void exec_blind(QCString,QValueList<QCString>,QValueList<QCString>,QCString)";
00458 funcs << "serviceResult start_service_by_name(QString,QStringList)";
00459 funcs << "serviceResult start_service_by_desktop_path(QString,QStringList)";
00460 funcs << "serviceResult start_service_by_desktop_name(QString,QStringList)";
00461 funcs << "serviceResult kdeinit_exec(QString,QStringList)";
00462 funcs << "serviceResult kdeinit_exec_wait(QString,QStringList)";
00463 funcs << "serviceResult start_service_by_name(QString,QStringList,QValueList<QCString>,QCString)";
00464 funcs << "serviceResult start_service_by_desktop_path(QString,QStringList,QValueList<QCString>,QCString)";
00465 funcs << "serviceResult start_service_by_desktop_name(QString,QStringList,QValueList<QCString>,QCString)";
00466 funcs << "serviceResult start_service_by_name(QString,QStringList,QValueList<QCString>,QCString,bool)";
00467 funcs << "serviceResult start_service_by_desktop_path(QString,QStringList,QValueList<QCString>,QCString,bool)";
00468 funcs << "serviceResult start_service_by_desktop_name(QString,QStringList,QValueList<QCString>,QCString,bool)";
00469 funcs << "serviceResult kdeinit_exec(QString,QStringList,QValueList<QCString>)";
00470 funcs << "serviceResult kdeinit_exec_wait(QString,QStringList,QValueList<QCString>)";
00471 funcs << "QString requestSlave(QString,QString,QString)";
00472 funcs << "pid_t requestHoldSlave(KURL,QString)";
00473 funcs << "void waitForSlave(pid_t)";
00474 funcs << "void setLaunchEnv(QCString,QCString)";
00475 funcs << "void reparseConfiguration()";
00476
00477 funcs << "void autoStart()";
00478 funcs << "void autoStart(int)";
00479 return funcs;
00480 }
00481
00482 void KLauncher::setLaunchEnv(const QCString &name, const QCString &_value)
00483 {
00484 QCString value(_value);
00485 if (value.isNull())
00486 value = "";
00487 klauncher_header request_header;
00488 QByteArray requestData(name.length()+value.length()+2);
00489 memcpy(requestData.data(), name.data(), name.length()+1);
00490 memcpy(requestData.data()+name.length()+1, value.data(), value.length()+1);
00491 request_header.cmd = LAUNCHER_SETENV;
00492 request_header.arg_length = requestData.size();
00493 write(kdeinitSocket, &request_header, sizeof(request_header));
00494 write(kdeinitSocket, requestData.data(), request_header.arg_length);
00495 }
00496
00497
00498
00499
00500
00501 static int
00502 read_socket(int sock, char *buffer, int len)
00503 {
00504 ssize_t result;
00505 int bytes_left = len;
00506 while ( bytes_left > 0)
00507 {
00508 result = read(sock, buffer, bytes_left);
00509 if (result > 0)
00510 {
00511 buffer += result;
00512 bytes_left -= result;
00513 }
00514 else if (result == 0)
00515 return -1;
00516 else if ((result == -1) && (errno != EINTR))
00517 return -1;
00518 }
00519 return 0;
00520 }
00521
00522
00523 void
00524 KLauncher::slotKDEInitData(int)
00525 {
00526 klauncher_header request_header;
00527 QByteArray requestData;
00528 if( dontBlockReading )
00529 {
00530
00531
00532
00533
00534 fd_set in;
00535 timeval tm = { 0, 0 };
00536 FD_ZERO ( &in );
00537 FD_SET( kdeinitSocket, &in );
00538 select( kdeinitSocket + 1, &in, 0, 0, &tm );
00539 if( !FD_ISSET( kdeinitSocket, &in ))
00540 return;
00541 }
00542 dontBlockReading = false;
00543 int result = read_socket(kdeinitSocket, (char *) &request_header,
00544 sizeof( request_header));
00545 if (result == -1)
00546 {
00547 kdDebug() << "Exiting on read_socket errno: " << errno << endl;
00548 ::signal( SIGHUP, SIG_IGN);
00549 ::signal( SIGTERM, SIG_IGN);
00550 destruct(255);
00551 }
00552 requestData.resize(request_header.arg_length);
00553 result = read_socket(kdeinitSocket, (char *) requestData.data(),
00554 request_header.arg_length);
00555
00556 if (request_header.cmd == LAUNCHER_DIED)
00557 {
00558 long *request_data;
00559 request_data = (long *) requestData.data();
00560 processDied(request_data[0], request_data[1]);
00561 return;
00562 }
00563 if (lastRequest && (request_header.cmd == LAUNCHER_OK))
00564 {
00565 long *request_data;
00566 request_data = (long *) requestData.data();
00567 lastRequest->pid = (pid_t) (*request_data);
00568 kdDebug(7016) << lastRequest->name << " (pid " << lastRequest->pid <<
00569 ") up and running." << endl;
00570 switch(lastRequest->dcop_service_type)
00571 {
00572 case KService::DCOP_None:
00573 {
00574 lastRequest->status = KLaunchRequest::Running;
00575 break;
00576 }
00577
00578 case KService::DCOP_Unique:
00579 {
00580 lastRequest->status = KLaunchRequest::Launching;
00581 break;
00582 }
00583
00584 case KService::DCOP_Wait:
00585 {
00586 lastRequest->status = KLaunchRequest::Launching;
00587 break;
00588 }
00589
00590 case KService::DCOP_Multi:
00591 {
00592 lastRequest->status = KLaunchRequest::Launching;
00593 break;
00594 }
00595 }
00596 lastRequest = 0;
00597 return;
00598 }
00599 if (lastRequest && (request_header.cmd == LAUNCHER_ERROR))
00600 {
00601 lastRequest->status = KLaunchRequest::Error;
00602 if (!requestData.isEmpty())
00603 lastRequest->errorMsg = QString::fromUtf8((char *) requestData.data());
00604 lastRequest = 0;
00605 return;
00606 }
00607
00608 kdWarning(7016) << "Unexpected command from KDEInit (" << (unsigned int) request_header.cmd
00609 << ")" << endl;
00610 }
00611
00612 void
00613 KLauncher::processDied(pid_t pid, long )
00614 {
00615 KLaunchRequest *request = requestList.first();
00616 for(; request; request = requestList.next())
00617 {
00618 if (request->pid == pid)
00619 {
00620 if (request->dcop_service_type == KService::DCOP_Wait)
00621 request->status = KLaunchRequest::Done;
00622 else if ((request->dcop_service_type == KService::DCOP_Unique) &&
00623 (dcopClient()->isApplicationRegistered(request->dcop_name)))
00624 request->status = KLaunchRequest::Running;
00625 else
00626 request->status = KLaunchRequest::Error;
00627 requestDone(request);
00628 return;
00629 }
00630 }
00631 }
00632
00633 void
00634 KLauncher::slotAppRegistered(const QCString &appId)
00635 {
00636 const char *cAppId = appId.data();
00637 if (!cAppId) return;
00638
00639 KLaunchRequest *request = requestList.first();
00640 KLaunchRequest *nextRequest;
00641 for(; request; request = nextRequest)
00642 {
00643 nextRequest = requestList.next();
00644 if (request->status != KLaunchRequest::Launching)
00645 continue;
00646
00647
00648 if ((request->dcop_service_type == KService::DCOP_Unique) &&
00649 ((appId == request->dcop_name) ||
00650 dcopClient()->isApplicationRegistered(request->dcop_name)))
00651 {
00652 request->status = KLaunchRequest::Running;
00653 requestDone(request);
00654 continue;
00655 }
00656
00657 const char *rAppId = request->dcop_name.data();
00658 if (!rAppId) continue;
00659
00660 int l = strlen(rAppId);
00661 if ((strncmp(rAppId, cAppId, l) == 0) &&
00662 ((cAppId[l] == '\0') || (cAppId[l] == '-')))
00663 {
00664 request->dcop_name = appId;
00665 request->status = KLaunchRequest::Running;
00666 requestDone(request);
00667 continue;
00668 }
00669 }
00670 }
00671
00672 void
00673 KLauncher::autoStart(int phase)
00674 {
00675 if( mAutoStart.phase() >= phase )
00676 return;
00677 mAutoStart.setPhase(phase);
00678 if( newStartup )
00679 {
00680 if (phase == 0)
00681 mAutoStart.loadAutoStartList();
00682 }
00683 else
00684 {
00685 if (phase == 1)
00686 mAutoStart.loadAutoStartList();
00687 }
00688 mAutoTimer.start(0, true);
00689 }
00690
00691 void
00692 KLauncher::slotAutoStart()
00693 {
00694 KService::Ptr s;
00695 do
00696 {
00697 QString service = mAutoStart.startService();
00698 if (service.isEmpty())
00699 {
00700
00701 if( !mAutoStart.phaseDone())
00702 {
00703 mAutoStart.setPhaseDone();
00704
00705 if( newStartup )
00706 {
00707 QCString autoStartSignal;
00708 autoStartSignal.sprintf( "autoStart%dDone()", mAutoStart.phase());
00709 emitDCOPSignal(autoStartSignal, QByteArray());
00710 }
00711 else
00712 {
00713 QCString autoStartSignal( "autoStartDone()" );
00714 int phase = mAutoStart.phase();
00715 if ( phase > 1 )
00716 autoStartSignal.sprintf( "autoStart%dDone()", phase );
00717 emitDCOPSignal(autoStartSignal, QByteArray());
00718 }
00719 }
00720 return;
00721 }
00722 s = new KService(service);
00723 }
00724 while (!start_service(s, QStringList(), QValueList<QCString>(), "0", false, true));
00725
00726 }
00727
00728 void
00729 KLauncher::requestDone(KLaunchRequest *request)
00730 {
00731 if ((request->status == KLaunchRequest::Running) ||
00732 (request->status == KLaunchRequest::Done))
00733 {
00734 DCOPresult.result = 0;
00735 DCOPresult.dcopName = request->dcop_name;
00736 DCOPresult.error = QString::null;
00737 DCOPresult.pid = request->pid;
00738 }
00739 else
00740 {
00741 DCOPresult.result = 1;
00742 DCOPresult.dcopName = "";
00743 DCOPresult.error = i18n("KDEInit could not launch '%1'.").arg(request->name);
00744 if (!request->errorMsg.isEmpty())
00745 DCOPresult.error += ":\n" + request->errorMsg;
00746 DCOPresult.pid = 0;
00747
00748 #if defined Q_WS_X11 && ! defined K_WS_QTONLY
00749
00750 if (!request->startup_dpy.isEmpty())
00751 {
00752 Display* dpy = NULL;
00753 if( (mCached_dpy != NULL) &&
00754 (request->startup_dpy == XDisplayString( mCached_dpy )))
00755 dpy = mCached_dpy;
00756 if( dpy == NULL )
00757 dpy = XOpenDisplay( request->startup_dpy );
00758 if( dpy )
00759 {
00760 KStartupInfoId id;
00761 id.initId( request->startup_id );
00762 KStartupInfo::sendFinishX( dpy, id );
00763 if( mCached_dpy != dpy && mCached_dpy != NULL )
00764 XCloseDisplay( mCached_dpy );
00765 mCached_dpy = dpy;
00766 }
00767 }
00768 #endif
00769 }
00770
00771 if (request->autoStart)
00772 {
00773 mAutoTimer.start(0, true);
00774 }
00775
00776 if (request->transaction)
00777 {
00778 QByteArray replyData;
00779 QCString replyType;
00780 replyType = "serviceResult";
00781 QDataStream stream2(replyData, IO_WriteOnly);
00782 stream2 << DCOPresult.result << DCOPresult.dcopName << DCOPresult.error << DCOPresult.pid;
00783 dcopClient()->endTransaction( request->transaction,
00784 replyType, replyData);
00785 }
00786 requestList.removeRef( request );
00787 }
00788
00789 void
00790 KLauncher::requestStart(KLaunchRequest *request)
00791 {
00792 requestList.append( request );
00793
00794 klauncher_header request_header;
00795 QByteArray requestData;
00796 int length = 0;
00797 length += sizeof(long);
00798 length += request->name.length() + 1;
00799 for(QValueList<QCString>::Iterator it = request->arg_list.begin();
00800 it != request->arg_list.end();
00801 it++)
00802 {
00803 length += (*it).length() + 1;
00804 }
00805 length += sizeof(long);
00806 for(QValueList<QCString>::ConstIterator it = request->envs.begin();
00807 it != request->envs.end();
00808 it++)
00809 {
00810 length += (*it).length() + 1;
00811 }
00812 length += sizeof( long );
00813 #ifdef Q_WS_X11
00814 bool startup_notify = !request->startup_id.isNull() && request->startup_id != "0";
00815 if( startup_notify )
00816 length += request->startup_id.length() + 1;
00817 #endif
00818 if (!request->cwd.isEmpty())
00819 length += request->cwd.length() + 1;
00820
00821 requestData.resize( length );
00822
00823 char *p = requestData.data();
00824 long l = request->arg_list.count()+1;
00825 memcpy(p, &l, sizeof(long));
00826 p += sizeof(long);
00827 strcpy(p, request->name.data());
00828 p += strlen(p) + 1;
00829 for(QValueList<QCString>::Iterator it = request->arg_list.begin();
00830 it != request->arg_list.end();
00831 it++)
00832 {
00833 strcpy(p, (*it).data());
00834 p += strlen(p) + 1;
00835 }
00836 l = request->envs.count();
00837 memcpy(p, &l, sizeof(long));
00838 p += sizeof(long);
00839 for(QValueList<QCString>::ConstIterator it = request->envs.begin();
00840 it != request->envs.end();
00841 it++)
00842 {
00843 strcpy(p, (*it).data());
00844 p += strlen(p) + 1;
00845 }
00846 l = 0;
00847 memcpy(p, &l, sizeof(long));
00848 p += sizeof(long);
00849 #ifdef Q_WS_X11
00850 if( startup_notify )
00851 {
00852 strcpy(p, request->startup_id.data());
00853 p += strlen( p ) + 1;
00854 }
00855 #endif
00856 if (!request->cwd.isEmpty())
00857 {
00858 strcpy(p, request->cwd.data());
00859 p += strlen( p ) + 1;
00860 }
00861 #ifdef Q_WS_X11
00862 request_header.cmd = startup_notify ? LAUNCHER_EXT_EXEC : LAUNCHER_EXEC_NEW;
00863 #else
00864 request_header.cmd = LAUNCHER_EXEC_NEW;
00865 #endif
00866 request_header.arg_length = length;
00867 write(kdeinitSocket, &request_header, sizeof(request_header));
00868 write(kdeinitSocket, requestData.data(), request_header.arg_length);
00869
00870
00871 lastRequest = request;
00872 dontBlockReading = false;
00873 do {
00874 slotKDEInitData( kdeinitSocket );
00875 }
00876 while (lastRequest != 0);
00877 dontBlockReading = true;
00878 }
00879
00880 void
00881 KLauncher::exec_blind( const QCString &name, const QValueList<QCString> &arg_list,
00882 const QValueList<QCString> &envs, const QCString& startup_id )
00883 {
00884 KLaunchRequest *request = new KLaunchRequest;
00885 request->autoStart = false;
00886 request->name = name;
00887 request->arg_list = arg_list;
00888 request->dcop_name = 0;
00889 request->dcop_service_type = KService::DCOP_None;
00890 request->pid = 0;
00891 request->status = KLaunchRequest::Launching;
00892 request->transaction = 0;
00893 request->envs = envs;
00894
00895 KService::Ptr service = KService::serviceByDesktopName( name.mid( name.findRev( '/' ) + 1 ));
00896 if (service != NULL)
00897 send_service_startup_info( request, service,
00898 startup_id, QValueList< QCString >());
00899 else
00900 cancel_service_startup_info( request, startup_id, envs );
00901
00902 requestStart(request);
00903
00904 requestDone(request);
00905 }
00906
00907
00908 bool
00909 KLauncher::start_service_by_name(const QString &serviceName, const QStringList &urls,
00910 const QValueList<QCString> &envs, const QCString& startup_id, bool blind)
00911 {
00912 KService::Ptr service = 0;
00913
00914 service = KService::serviceByName(serviceName);
00915 if (!service)
00916 {
00917 DCOPresult.result = ENOENT;
00918 DCOPresult.error = i18n("Could not find service '%1'.").arg(serviceName);
00919 cancel_service_startup_info( NULL, startup_id, envs );
00920 return false;
00921 }
00922 return start_service(service, urls, envs, startup_id, blind);
00923 }
00924
00925 bool
00926 KLauncher::start_service_by_desktop_path(const QString &serviceName, const QStringList &urls,
00927 const QValueList<QCString> &envs, const QCString& startup_id, bool blind)
00928 {
00929 KService::Ptr service = 0;
00930
00931 if (serviceName[0] == '/')
00932 {
00933
00934 service = new KService(serviceName);
00935 }
00936 else
00937 {
00938 service = KService::serviceByDesktopPath(serviceName);
00939 }
00940 if (!service)
00941 {
00942 DCOPresult.result = ENOENT;
00943 DCOPresult.error = i18n("Could not find service '%1'.").arg(serviceName);
00944 cancel_service_startup_info( NULL, startup_id, envs );
00945 return false;
00946 }
00947 return start_service(service, urls, envs, startup_id, blind);
00948 }
00949
00950 bool
00951 KLauncher::start_service_by_desktop_name(const QString &serviceName, const QStringList &urls,
00952 const QValueList<QCString> &envs, const QCString& startup_id, bool blind)
00953 {
00954 KService::Ptr service = 0;
00955
00956 service = KService::serviceByDesktopName(serviceName);
00957 if (!service)
00958 {
00959 DCOPresult.result = ENOENT;
00960 DCOPresult.error = i18n("Could not find service '%1'.").arg(serviceName);
00961 cancel_service_startup_info( NULL, startup_id, envs );
00962 return false;
00963 }
00964 return start_service(service, urls, envs, startup_id, blind);
00965 }
00966
00967 bool
00968 KLauncher::start_service(KService::Ptr service, const QStringList &_urls,
00969 const QValueList<QCString> &envs, const QCString& startup_id, bool blind, bool autoStart)
00970 {
00971 QStringList urls = _urls;
00972 if (!service->isValid())
00973 {
00974 DCOPresult.result = ENOEXEC;
00975 DCOPresult.error = i18n("Service '%1' is malformatted.").arg(service->desktopEntryPath());
00976 cancel_service_startup_info( NULL, startup_id, envs );
00977 return false;
00978 }
00979 KLaunchRequest *request = new KLaunchRequest;
00980 request->autoStart = autoStart;
00981
00982 if ((urls.count() > 1) && !service->allowMultipleFiles())
00983 {
00984
00985
00986
00987
00988
00989 QStringList::ConstIterator it = urls.begin();
00990 for(++it;
00991 it != urls.end();
00992 ++it)
00993 {
00994 QStringList singleUrl;
00995 singleUrl.append(*it);
00996 QCString startup_id2 = startup_id;
00997 if( !startup_id2.isEmpty() && startup_id2 != "0" )
00998 startup_id2 = "0";
00999 start_service( service, singleUrl, envs, startup_id2, true);
01000 }
01001 QString firstURL = *(urls.begin());
01002 urls.clear();
01003 urls.append(firstURL);
01004 }
01005 createArgs(request, service, urls);
01006
01007
01008 if (!request->arg_list.count())
01009 {
01010 DCOPresult.result = ENOEXEC;
01011 DCOPresult.error = i18n("Service '%1' is malformatted.").arg(service->desktopEntryPath());
01012 delete request;
01013 cancel_service_startup_info( NULL, startup_id, envs );
01014 return false;
01015 }
01016
01017 request->name = request->arg_list.first();
01018 request->arg_list.remove(request->arg_list.begin());
01019
01020 request->dcop_service_type = service->DCOPServiceType();
01021
01022 if ((request->dcop_service_type == KService::DCOP_Unique) ||
01023 (request->dcop_service_type == KService::DCOP_Multi))
01024 {
01025 QVariant v = service->property("X-DCOP-ServiceName");
01026 if (v.isValid())
01027 request->dcop_name = v.toString().utf8();
01028 if (request->dcop_name.isEmpty())
01029 {
01030 request->dcop_name = QFile::encodeName(KRun::binaryName(service->exec(), true));
01031 }
01032 }
01033
01034 request->pid = 0;
01035 request->transaction = 0;
01036 request->envs = envs;
01037 send_service_startup_info( request, service, startup_id, envs );
01038
01039
01040 if (!blind && !autoStart)
01041 {
01042 request->transaction = dcopClient()->beginTransaction();
01043 }
01044 queueRequest(request);
01045 return true;
01046 }
01047
01048 void
01049 KLauncher::send_service_startup_info( KLaunchRequest *request, KService::Ptr service, const QCString& startup_id,
01050 const QValueList<QCString> &envs )
01051 {
01052 #if defined Q_WS_X11 && ! defined K_WS_QTONLY
01053
01054 request->startup_id = "0";
01055 if( startup_id == "0" )
01056 return;
01057 bool silent;
01058 QCString wmclass;
01059 if( !KRun::checkStartupNotify( QString::null, service, &silent, &wmclass ))
01060 return;
01061 KStartupInfoId id;
01062 id.initId( startup_id );
01063 const char* dpy_str = NULL;
01064 for( QValueList<QCString>::ConstIterator it = envs.begin();
01065 it != envs.end();
01066 ++it )
01067 if( strncmp( *it, "DISPLAY=", 8 ) == 0 )
01068 dpy_str = static_cast< const char* >( *it ) + 8;
01069 Display* dpy = NULL;
01070 if( dpy_str != NULL && mCached_dpy != NULL
01071 && qstrcmp( dpy_str, XDisplayString( mCached_dpy )) == 0 )
01072 dpy = mCached_dpy;
01073 if( dpy == NULL )
01074 dpy = XOpenDisplay( dpy_str );
01075 request->startup_id = id.id();
01076 if( dpy == NULL )
01077 {
01078 cancel_service_startup_info( request, startup_id, envs );
01079 return;
01080 }
01081
01082 request->startup_dpy = dpy_str;
01083
01084 KStartupInfoData data;
01085 data.setName( service->name());
01086 data.setIcon( service->icon());
01087 data.setDescription( i18n( "Launching %1" ).arg( service->name()));
01088 if( !wmclass.isEmpty())
01089 data.setWMClass( wmclass );
01090 if( silent )
01091 data.setSilent( KStartupInfoData::Yes );
01092
01093 KStartupInfo::sendStartupX( dpy, id, data );
01094 if( mCached_dpy != dpy && mCached_dpy != NULL )
01095 XCloseDisplay( mCached_dpy );
01096 mCached_dpy = dpy;
01097 return;
01098 #else
01099 return;
01100 #endif
01101 }
01102
01103 void
01104 KLauncher::cancel_service_startup_info( KLaunchRequest* request, const QCString& startup_id,
01105 const QValueList<QCString> &envs )
01106 {
01107 #if defined Q_WS_X11 && ! defined K_WS_QTONLY
01108
01109 if( request != NULL )
01110 request->startup_id = "0";
01111 if( !startup_id.isEmpty() && startup_id != "0" )
01112 {
01113 const char* dpy_str = NULL;
01114 for( QValueList<QCString>::ConstIterator it = envs.begin();
01115 it != envs.end();
01116 ++it )
01117 if( strncmp( *it, "DISPLAY=", 8 ) == 0 )
01118 dpy_str = static_cast< const char* >( *it ) + 8;
01119 Display* dpy = NULL;
01120 if( dpy_str != NULL && mCached_dpy != NULL
01121 && qstrcmp( dpy_str, XDisplayString( mCached_dpy )) == 0 )
01122 dpy = mCached_dpy;
01123 if( dpy == NULL )
01124 dpy = XOpenDisplay( dpy_str );
01125 if( dpy == NULL )
01126 return;
01127 KStartupInfoId id;
01128 id.initId( startup_id );
01129 KStartupInfo::sendFinishX( dpy, id );
01130 if( mCached_dpy != dpy && mCached_dpy != NULL )
01131 XCloseDisplay( mCached_dpy );
01132 mCached_dpy = dpy;
01133 }
01134 #endif
01135 }
01136
01137 bool
01138 KLauncher::kdeinit_exec(const QString &app, const QStringList &args,
01139 const QValueList<QCString> &envs, QCString startup_id, bool wait)
01140 {
01141 KLaunchRequest *request = new KLaunchRequest;
01142 request->autoStart = false;
01143
01144 for(QStringList::ConstIterator it = args.begin();
01145 it != args.end();
01146 it++)
01147 {
01148 QString arg = *it;
01149 request->arg_list.append(arg.local8Bit());
01150 }
01151
01152 request->name = app.local8Bit();
01153
01154 if (wait)
01155 request->dcop_service_type = KService::DCOP_Wait;
01156 else
01157 request->dcop_service_type = KService::DCOP_None;
01158 request->dcop_name = 0;
01159 request->pid = 0;
01160 #ifdef Q_WS_X11
01161 request->startup_id = startup_id;
01162 #endif
01163 request->envs = envs;
01164 if( app != "kbuildsycoca" )
01165 {
01166
01167 KService::Ptr service = KService::serviceByDesktopName( app.mid( app.findRev( '/' ) + 1 ));
01168 if (service != NULL)
01169 send_service_startup_info( request, service,
01170 startup_id, QValueList< QCString >());
01171 else
01172 cancel_service_startup_info( request, startup_id, envs );
01173 }
01174 request->transaction = dcopClient()->beginTransaction();
01175 queueRequest(request);
01176 return true;
01177 }
01178
01179 void
01180 KLauncher::queueRequest(KLaunchRequest *request)
01181 {
01182 requestQueue.append( request );
01183 if (!bProcessingQueue)
01184 {
01185 bProcessingQueue = true;
01186 QTimer::singleShot(0, this, SLOT( slotDequeue() ));
01187 }
01188 }
01189
01190 void
01191 KLauncher::slotDequeue()
01192 {
01193 do {
01194 KLaunchRequest *request = requestQueue.take(0);
01195
01196 request->status = KLaunchRequest::Launching;
01197 requestStart(request);
01198 if (request->status != KLaunchRequest::Launching)
01199 {
01200
01201 requestDone( request );
01202 continue;
01203 }
01204 } while(requestQueue.count());
01205 bProcessingQueue = false;
01206 }
01207
01208 void
01209 KLauncher::createArgs( KLaunchRequest *request, const KService::Ptr service ,
01210 const QStringList &urls)
01211 {
01212 QStringList params = KRun::processDesktopExec(*service, urls, false);
01213
01214 for(QStringList::ConstIterator it = params.begin();
01215 it != params.end(); ++it)
01216 {
01217 request->arg_list.append((*it).local8Bit());
01218 }
01219 request->cwd = QFile::encodeName(service->path());
01220 }
01221
01223
01224 pid_t
01225 KLauncher::requestHoldSlave(const KURL &url, const QString &app_socket)
01226 {
01227 IdleSlave *slave;
01228 for(slave = mSlaveList.first(); slave; slave = mSlaveList.next())
01229 {
01230 if (slave->onHold(url))
01231 break;
01232 }
01233 if (slave)
01234 {
01235 mSlaveList.removeRef(slave);
01236 slave->connect(app_socket);
01237 return slave->pid();
01238 }
01239 return 0;
01240 }
01241
01242
01243 pid_t
01244 KLauncher::requestSlave(const QString &protocol,
01245 const QString &host,
01246 const QString &app_socket,
01247 QString &error)
01248 {
01249 IdleSlave *slave;
01250 for(slave = mSlaveList.first(); slave; slave = mSlaveList.next())
01251 {
01252 if (slave->match(protocol, host, true))
01253 break;
01254 }
01255 if (!slave)
01256 {
01257 for(slave = mSlaveList.first(); slave; slave = mSlaveList.next())
01258 {
01259 if (slave->match(protocol, host, false))
01260 break;
01261 }
01262 }
01263 if (!slave)
01264 {
01265 for(slave = mSlaveList.first(); slave; slave = mSlaveList.next())
01266 {
01267 if (slave->match(protocol, QString::null, false))
01268 break;
01269 }
01270 }
01271 if (slave)
01272 {
01273 mSlaveList.removeRef(slave);
01274 slave->connect(app_socket);
01275 return slave->pid();
01276 }
01277
01278 QString _name = KProtocolInfo::exec(protocol);
01279 if (_name.isEmpty())
01280 {
01281 error = i18n("Unknown protocol '%1'.\n").arg(protocol);
01282 return 0;
01283 }
01284
01285 QCString name = _name.latin1();
01286 QCString arg1 = protocol.latin1();
01287 QCString arg2 = QFile::encodeName(mPoolSocketName);
01288 QCString arg3 = QFile::encodeName(app_socket);
01289 QValueList<QCString> arg_list;
01290 arg_list.append(arg1);
01291 arg_list.append(arg2);
01292 arg_list.append(arg3);
01293
01294
01295 if (mSlaveDebug == arg1)
01296 {
01297 klauncher_header request_header;
01298 request_header.cmd = LAUNCHER_DEBUG_WAIT;
01299 request_header.arg_length = 0;
01300 write(kdeinitSocket, &request_header, sizeof(request_header));
01301 }
01302 if (mSlaveValgrind == arg1)
01303 {
01304 arg_list.prepend(QFile::encodeName(KLibLoader::findLibrary(name)));
01305 arg_list.prepend(QFile::encodeName(locate("exe", "kioslave")));
01306 name = "valgrind";
01307 if (!mSlaveValgrindSkin.isEmpty()) {
01308 arg_list.prepend(QCString("--tool=") + mSlaveValgrindSkin);
01309 } else
01310 arg_list.prepend("--tool=memcheck");
01311 }
01312
01313 KLaunchRequest *request = new KLaunchRequest;
01314 request->autoStart = false;
01315 request->name = name;
01316 request->arg_list = arg_list;
01317 request->dcop_name = 0;
01318 request->dcop_service_type = KService::DCOP_None;
01319 request->pid = 0;
01320 #ifdef Q_WS_X11
01321 request->startup_id = "0";
01322 #endif
01323 request->status = KLaunchRequest::Launching;
01324 request->transaction = 0;
01325 requestStart(request);
01326 pid_t pid = request->pid;
01327
01328
01329
01330
01331 requestDone(request);
01332 if (!pid)
01333 {
01334 error = i18n("Error loading '%1'.\n").arg(name);
01335 }
01336 return pid;
01337 }
01338
01339 void
01340 KLauncher::waitForSlave(pid_t pid)
01341 {
01342 IdleSlave *slave;
01343 for(slave = mSlaveList.first(); slave; slave = mSlaveList.next())
01344 {
01345 if (slave->pid() == pid)
01346 return;
01347 }
01348 SlaveWaitRequest *waitRequest = new SlaveWaitRequest;
01349 waitRequest->transaction = dcopClient()->beginTransaction();
01350 waitRequest->pid = pid;
01351 mSlaveWaitRequest.append(waitRequest);
01352 }
01353
01354 void
01355 KLauncher::acceptSlave(KSocket *slaveSocket)
01356 {
01357 IdleSlave *slave = new IdleSlave(slaveSocket);
01358
01359 mSlaveList.append(slave);
01360 connect(slave, SIGNAL(destroyed()), this, SLOT(slotSlaveGone()));
01361 connect(slave, SIGNAL(statusUpdate(IdleSlave *)),
01362 this, SLOT(slotSlaveStatus(IdleSlave *)));
01363 if (!mTimer.isActive())
01364 {
01365 mTimer.start(1000*10);
01366 }
01367 }
01368
01369 void
01370 KLauncher::slotSlaveStatus(IdleSlave *slave)
01371 {
01372 SlaveWaitRequest *waitRequest = mSlaveWaitRequest.first();
01373 while(waitRequest)
01374 {
01375 if (waitRequest->pid == slave->pid())
01376 {
01377 QByteArray replyData;
01378 QCString replyType;
01379 replyType = "void";
01380 dcopClient()->endTransaction( waitRequest->transaction, replyType, replyData);
01381 mSlaveWaitRequest.removeRef(waitRequest);
01382 waitRequest = mSlaveWaitRequest.current();
01383 }
01384 else
01385 {
01386 waitRequest = mSlaveWaitRequest.next();
01387 }
01388 }
01389 }
01390
01391 void
01392 KLauncher::slotSlaveGone()
01393 {
01394 IdleSlave *slave = (IdleSlave *) sender();
01395 mSlaveList.removeRef(slave);
01396 if ((mSlaveList.count() == 0) && (mTimer.isActive()))
01397 {
01398 mTimer.stop();
01399 }
01400 }
01401
01402 void
01403 KLauncher::idleTimeout()
01404 {
01405 bool keepOneFileSlave=true;
01406 time_t now = time(0);
01407 IdleSlave *slave;
01408 for(slave = mSlaveList.first(); slave; slave = mSlaveList.next())
01409 {
01410 if ((slave->protocol()=="file") && (keepOneFileSlave))
01411 keepOneFileSlave=false;
01412 else if (slave->age(now) > SLAVE_MAX_IDLE)
01413 {
01414
01415 delete slave;
01416 }
01417 }
01418 }
01419
01420 #include "klauncher.moc"