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