32 #include <tdeconfig.h>
34 #include <klibloader.h>
35 #include <tdelocale.h>
36 #include <tdeprotocolmanager.h>
37 #include <kprotocolinfo.h>
39 #include <kstandarddirs.h>
40 #include <tdetempfile.h>
43 #if defined TQ_WS_X11 && ! defined K_WS_QTONLY
44 #include <tdestartupinfo.h>
48 #include "tdeio/global.h"
49 #include "tdeio/connection.h"
50 #include "tdeio/slaveinterface.h"
52 #include "tdelauncher.h"
53 #include "tdelauncher_cmds.h"
62 #define SLAVE_MAX_IDLE 30
64 using namespace TDEIO;
66 template class TQPtrList<TDELaunchRequest>;
67 template class TQPtrList<IdleSlave>;
69 IdleSlave::IdleSlave(TDESocket *socket)
72 mConn.connect(
this, TQ_SLOT(gotInput()));
73 mConn.send( CMD_SLAVE_STATUS );
84 if (mConn.read( &cmd, data) == -1)
87 kdError(7016) <<
"SlavePool: No communication with slave." << endl;
90 else if (cmd == MSG_SLAVE_ACK)
94 else if (cmd != MSG_SLAVE_STATUS)
96 kdError(7016) <<
"SlavePool: Unexpected data from slave." << endl;
101 TQDataStream stream( data, IO_ReadOnly );
106 stream >> pid >> protocol >> host >> b;
117 mConnected = (b != 0);
118 mProtocol = protocol;
120 emit statusUpdate(
this);
125 IdleSlave::connect(
const TQString &app_socket)
128 TQDataStream stream( data, IO_WriteOnly);
129 stream << app_socket;
130 mConn.send( CMD_SLAVE_CONNECT, data );
135 IdleSlave::reparseConfiguration()
137 mConn.send( CMD_REPARSECONFIGURATION );
141 IdleSlave::match(
const TQString &protocol,
const TQString &host,
bool connected)
143 if (mOnHold)
return false;
144 if (protocol != mProtocol)
return false;
145 if (host.isEmpty())
return true;
146 if (host != mHost)
return false;
147 if (!connected)
return true;
148 if (!mConnected)
return false;
153 IdleSlave::onHold(
const KURL &url)
155 if (!mOnHold)
return false;
156 return (url == mUrl);
160 IdleSlave::age(time_t now)
162 return (
int) difftime(now, mBirthDate);
165 TDELauncher::TDELauncher(
int _tdeinitSocket,
bool new_startup)
167 : TDEApplication( false, true ),
168 DCOPObject(
"tdelauncher"),
169 tdeinitSocket(_tdeinitSocket), mAutoStart( new_startup ),
170 dontBlockReading(false), newStartup( new_startup )
175 connect(&mAutoTimer, TQ_SIGNAL(timeout()),
this, TQ_SLOT(slotAutoStart()));
176 requestList.setAutoDelete(
true);
177 mSlaveWaitRequest.setAutoDelete(
true);
178 dcopClient()->setNotifications(
true );
179 connect(dcopClient(), TQ_SIGNAL( applicationRegistered(
const TQCString &)),
180 this, TQ_SLOT( slotAppRegistered(
const TQCString &)));
181 dcopClient()->connectDCOPSignal(
"DCOPServer",
"",
"terminateTDE()",
182 objId(),
"terminateTDE()",
false );
184 TQString prefix = locateLocal(
"socket",
"tdelauncher");
185 KTempFile domainname(prefix, TQString::fromLatin1(
".slave-socket"));
186 if (domainname.status() != 0)
189 tqDebug(
"TDELauncher: Fatal error, can't create tempfile!");
192 mPoolSocketName = domainname.name();
197 mPoolSocket =
new TDEServerSocket(
static_cast<const char*
>(TQFile::encodeName(mPoolSocketName)));
198 connect(mPoolSocket, TQ_SIGNAL(accepted( TDESocket *)),
199 TQ_SLOT(acceptSlave(TDESocket *)));
201 connect(&mTimer, TQ_SIGNAL(timeout()), TQ_SLOT(idleTimeout()));
203 tdeinitNotifier =
new TQSocketNotifier(tdeinitSocket, TQSocketNotifier::Read);
204 connect(tdeinitNotifier, TQ_SIGNAL( activated(
int )),
205 this, TQ_SLOT( slotKDEInitData(
int )));
206 tdeinitNotifier->setEnabled(
true );
208 bProcessingQueue =
false;
210 mSlaveDebug = getenv(
"TDE_SLAVE_DEBUG_WAIT");
211 if (!mSlaveDebug.isEmpty())
213 tqWarning(
"Klauncher running in slave-debug mode for slaves of protocol '%s'", mSlaveDebug.data());
215 mSlaveValgrind = getenv(
"TDE_SLAVE_VALGRIND");
216 if (!mSlaveValgrind.isEmpty())
218 mSlaveValgrindSkin = getenv(
"TDE_SLAVE_VALGRIND_SKIN");
219 tqWarning(
"Klauncher running slaves through valgrind for slaves of protocol '%s'", mSlaveValgrind.data());
221 tdelauncher_header request_header;
222 request_header.cmd = LAUNCHER_OK;
223 request_header.arg_length = 0;
224 write(tdeinitSocket, &request_header,
sizeof(request_header));
227 TDELauncher::~TDELauncher()
232 void TDELauncher::close()
234 if (!mPoolSocketName.isEmpty())
236 TQCString filename = TQFile::encodeName(mPoolSocketName);
237 unlink(filename.data());
239 #if defined TQ_WS_X11 && ! defined K_WS_QTONLY
241 if( mCached_dpy != NULL )
242 XCloseDisplay( mCached_dpy );
247 TDELauncher::destruct(
int exit_code)
249 if (kapp) ((TDELauncher*)kapp)->close();
255 TDELauncher::process(
const TQCString &fun,
const TQByteArray &data,
256 TQCString &replyType, TQByteArray &replyData)
258 if ((fun ==
"exec_blind(TQCString,TQValueList<TQCString>)")
259 || (fun ==
"exec_blind(TQCString,TQValueList<TQCString>,TQValueList<TQCString>,TQCString)"))
261 TQDataStream stream(data, IO_ReadOnly);
264 TQValueList<TQCString> arg_list;
265 TQCString startup_id =
"0";
266 TQValueList<TQCString> envs;
267 stream >> name >> arg_list;
268 if( fun ==
"exec_blind(TQCString,TQValueList<TQCString>,TQValueList<TQCString>,TQCString)" )
269 stream >> envs >> startup_id;
270 kdDebug(7016) <<
"TDELauncher: Got exec_blind('" << name <<
"', ...)" << endl;
271 exec_blind( name, arg_list, envs, startup_id);
274 if ((fun ==
"start_service_by_name(TQString,TQStringList)") ||
275 (fun ==
"start_service_by_desktop_path(TQString,TQStringList)")||
276 (fun ==
"start_service_by_desktop_name(TQString,TQStringList)")||
277 (fun ==
"tdeinit_exec(TQString,TQStringList)") ||
278 (fun ==
"tdeinit_exec_wait(TQString,TQStringList)") ||
279 (fun ==
"start_service_by_name(TQString,TQStringList,TQValueList<TQCString>,TQCString)") ||
280 (fun ==
"start_service_by_desktop_path(TQString,TQStringList,TQValueList<TQCString>,TQCString)")||
281 (fun ==
"start_service_by_desktop_name(TQString,TQStringList,TQValueList<TQCString>,TQCString)") ||
282 (fun ==
"start_service_by_name(TQString,TQStringList,TQValueList<TQCString>,TQCString,bool)") ||
283 (fun ==
"start_service_by_desktop_path(TQString,TQStringList,TQValueList<TQCString>,TQCString,bool)")||
284 (fun ==
"start_service_by_desktop_name(TQString,TQStringList,TQValueList<TQCString>,TQCString,bool)") ||
285 (fun ==
"tdeinit_exec(TQString,TQStringList,TQValueList<TQCString>)") ||
286 (fun ==
"tdeinit_exec_wait(TQString,TQStringList,TQValueList<TQCString>)") ||
287 (fun ==
"tdeinit_exec(TQString,TQStringList,TQValueList<TQCString>,TQCString)") ||
288 (fun ==
"tdeinit_exec_wait(TQString,TQStringList,TQValueList<TQCString>,TQCString)"))
290 TQDataStream stream(data, IO_ReadOnly);
291 bool bNoWait =
false;
292 TQString serviceName;
294 TQValueList<TQCString> envs;
295 TQCString startup_id =
"";
296 DCOPresult.result = -1;
297 DCOPresult.dcopName = 0;
298 DCOPresult.error = TQString::null;
300 stream >> serviceName >> urls;
301 if ((fun ==
"start_service_by_name(TQString,TQStringList,TQValueList<TQCString>,TQCString,bool)") ||
302 (fun ==
"start_service_by_desktop_path(TQString,TQStringList,TQValueList<TQCString>,TQCString,bool)")||
303 (fun ==
"start_service_by_desktop_name(TQString,TQStringList,TQValueList<TQCString>,TQCString,bool)"))
304 stream >> envs >> startup_id >> bNoWait;
305 else if ((fun ==
"start_service_by_name(TQString,TQStringList,TQValueList<TQCString>,TQCString)") ||
306 (fun ==
"start_service_by_desktop_path(TQString,TQStringList,TQValueList<TQCString>,TQCString)")||
307 (fun ==
"start_service_by_desktop_name(TQString,TQStringList,TQValueList<TQCString>,TQCString)"))
308 stream >> envs >> startup_id;
309 else if ((fun ==
"tdeinit_exec(TQString,TQStringList,TQValueList<TQCString>)") ||
310 (fun ==
"tdeinit_exec_wait(TQString,TQStringList,TQValueList<TQCString>)"))
312 else if ((fun ==
"tdeinit_exec(TQString,TQStringList,TQValueList<TQCString>,TQCString)") ||
313 (fun ==
"tdeinit_exec_wait(TQString,TQStringList,TQValueList<TQCString>,TQCString)"))
314 stream >> envs >> startup_id;
316 if (strncmp(fun,
"start_service_by_name(", 22) == 0)
318 kdDebug(7016) <<
"TDELauncher: Got start_service_by_name('" << serviceName <<
"', ...)" << endl;
319 finished = start_service_by_name(serviceName, urls, envs, startup_id, bNoWait);
321 else if (strncmp(fun,
"start_service_by_desktop_path(", 30) == 0)
323 kdDebug(7016) <<
"TDELauncher: Got start_service_by_desktop_path('" << serviceName <<
"', ...)" << endl;
324 finished = start_service_by_desktop_path(serviceName, urls, envs, startup_id, bNoWait);
326 else if (strncmp(fun,
"start_service_by_desktop_name(", 30) == 0)
328 kdDebug(7016) <<
"TDELauncher: Got start_service_by_desktop_name('" << serviceName <<
"', ...)" << endl;
329 finished = start_service_by_desktop_name(serviceName, urls, envs, startup_id, bNoWait );
331 else if ((fun ==
"tdeinit_exec(TQString,TQStringList)")
332 || (fun ==
"tdeinit_exec(TQString,TQStringList,TQValueList<TQCString>)")
333 || (fun ==
"tdeinit_exec(TQString,TQStringList,TQValueList<TQCString>,TQCString)"))
335 kdDebug(7016) <<
"TDELauncher: Got tdeinit_exec('" << serviceName <<
"', ...)" << endl;
336 finished = tdeinit_exec(serviceName, urls, envs, startup_id,
false);
340 kdDebug(7016) <<
"TDELauncher: Got tdeinit_exec_wait('" << serviceName <<
"', ...)" << endl;
341 finished = tdeinit_exec(serviceName, urls, envs, startup_id,
true);
345 replyType =
"serviceResult";
346 TQDataStream stream2(replyData, IO_WriteOnly);
347 stream2 << DCOPresult.result << DCOPresult.dcopName << DCOPresult.error << DCOPresult.pid;
351 else if (fun ==
"requestSlave(TQString,TQString,TQString)")
353 TQDataStream stream(data, IO_ReadOnly);
357 stream >> protocol >> host >> app_socket;
358 replyType =
"TQString";
360 pid_t pid = requestSlave(protocol, host, app_socket, error);
361 TQDataStream stream2(replyData, IO_WriteOnly);
362 stream2 << pid << error;
365 else if (fun ==
"requestHoldSlave(KURL,TQString)")
367 TQDataStream stream(data, IO_ReadOnly);
370 stream >> url >> app_socket;
372 pid_t pid = requestHoldSlave(url, app_socket);
373 TQDataStream stream2(replyData, IO_WriteOnly);
377 else if (fun ==
"waitForSlave(pid_t)")
379 TQDataStream stream(data, IO_ReadOnly);
387 else if (fun ==
"setLaunchEnv(TQCString,TQCString)")
389 TQDataStream stream(data, IO_ReadOnly);
392 stream >> name >> value;
393 setLaunchEnv(name, value);
397 else if (fun ==
"reparseConfiguration()")
399 TDEGlobal::config()->reparseConfiguration();
400 kdDebug(7016) <<
"TDELauncher::process : reparseConfiguration" << endl;
401 KProtocolManager::reparseConfiguration();
403 for(slave = mSlaveList.first(); slave; slave = mSlaveList.next())
404 slave->reparseConfiguration();
408 else if (fun ==
"terminateTDE()")
410 ::signal( SIGHUP, SIG_IGN);
411 ::signal( SIGTERM, SIG_IGN);
412 kdDebug() <<
"TDELauncher::process ---> terminateTDE" << endl;
413 tdelauncher_header request_header;
414 request_header.cmd = LAUNCHER_TERMINATE_KDE;
415 request_header.arg_length = 0;
416 write(tdeinitSocket, &request_header,
sizeof(request_header));
419 else if (fun ==
"autoStart()")
421 kdDebug() <<
"TDELauncher::process ---> autoStart" << endl;
426 else if (fun ==
"autoStart(int)")
428 kdDebug() <<
"TDELauncher::process ---> autoStart(int)" << endl;
429 TQDataStream stream(data, IO_ReadOnly);
437 if (DCOPObject::process(fun, data, replyType, replyData))
441 kdWarning(7016) <<
"Got unknown DCOP function: " << fun << endl;
446 TDELauncher::interfaces()
448 QCStringList ifaces = DCOPObject::interfaces();
449 ifaces +=
"TDELauncher";
454 TDELauncher::functions()
456 QCStringList funcs = DCOPObject::functions();
457 funcs <<
"void exec_blind(TQCString,TQValueList<TQCString>)";
458 funcs <<
"void exec_blind(TQCString,TQValueList<TQCString>,TQValueList<TQCString>,TQCString)";
459 funcs <<
"serviceResult start_service_by_name(TQString,TQStringList)";
460 funcs <<
"serviceResult start_service_by_desktop_path(TQString,TQStringList)";
461 funcs <<
"serviceResult start_service_by_desktop_name(TQString,TQStringList)";
462 funcs <<
"serviceResult tdeinit_exec(TQString,TQStringList)";
463 funcs <<
"serviceResult tdeinit_exec_wait(TQString,TQStringList)";
464 funcs <<
"serviceResult start_service_by_name(TQString,TQStringList,TQValueList<TQCString>,TQCString)";
465 funcs <<
"serviceResult start_service_by_desktop_path(TQString,TQStringList,TQValueList<TQCString>,TQCString)";
466 funcs <<
"serviceResult start_service_by_desktop_name(TQString,TQStringList,TQValueList<TQCString>,TQCString)";
467 funcs <<
"serviceResult start_service_by_name(TQString,TQStringList,TQValueList<TQCString>,TQCString,bool)";
468 funcs <<
"serviceResult start_service_by_desktop_path(TQString,TQStringList,TQValueList<TQCString>,TQCString,bool)";
469 funcs <<
"serviceResult start_service_by_desktop_name(TQString,TQStringList,TQValueList<TQCString>,TQCString,bool)";
470 funcs <<
"serviceResult tdeinit_exec(TQString,TQStringList,TQValueList<TQCString>)";
471 funcs <<
"serviceResult tdeinit_exec_wait(TQString,TQStringList,TQValueList<TQCString>)";
472 funcs <<
"TQString requestSlave(TQString,TQString,TQString)";
473 funcs <<
"pid_t requestHoldSlave(KURL,TQString)";
474 funcs <<
"void waitForSlave(pid_t)";
475 funcs <<
"void setLaunchEnv(TQCString,TQCString)";
476 funcs <<
"void reparseConfiguration()";
478 funcs <<
"void autoStart()";
479 funcs <<
"void autoStart(int)";
483 void TDELauncher::setLaunchEnv(
const TQCString &name,
const TQCString &_value)
485 TQCString value(_value);
488 tdelauncher_header request_header;
489 TQByteArray requestData(name.length()+value.length()+2);
490 memcpy(requestData.data(), name.data(), name.length()+1);
491 memcpy(requestData.data()+name.length()+1, value.data(), value.length()+1);
492 request_header.cmd = LAUNCHER_SETENV;
493 request_header.arg_length = requestData.size();
494 write(tdeinitSocket, &request_header,
sizeof(request_header));
495 write(tdeinitSocket, requestData.data(), request_header.arg_length);
503 read_socket(
int sock,
char *buffer,
int len)
506 int bytes_left = len;
507 while ( bytes_left > 0)
509 result = read(sock, buffer, bytes_left);
513 bytes_left -= result;
515 else if (result == 0)
517 else if ((result == -1) && (errno != EINTR))
525 TDELauncher::slotKDEInitData(
int)
527 tdelauncher_header request_header;
528 TQByteArray requestData;
529 if( dontBlockReading )
536 timeval tm = { 0, 0 };
538 FD_SET( tdeinitSocket, &in );
539 select( tdeinitSocket + 1, &in, 0, 0, &tm );
540 if( !FD_ISSET( tdeinitSocket, &in ))
543 dontBlockReading =
false;
544 int result = read_socket(tdeinitSocket, (
char *) &request_header,
545 sizeof( request_header));
548 kdDebug() <<
"Exiting on read_socket errno: " << errno << endl;
549 ::signal( SIGHUP, SIG_IGN);
550 ::signal( SIGTERM, SIG_IGN);
553 requestData.resize(request_header.arg_length);
554 result = read_socket(tdeinitSocket, (
char *) requestData.data(),
555 request_header.arg_length);
557 if (request_header.cmd == LAUNCHER_DIED)
560 request_data = (
long *) requestData.data();
561 processDied(request_data[0], request_data[1]);
564 if (lastRequest && (request_header.cmd == LAUNCHER_OK))
567 request_data = (
long *) requestData.data();
568 lastRequest->pid = (pid_t) (*request_data);
569 kdDebug(7016) << lastRequest->name <<
" (pid " << lastRequest->pid <<
570 ") up and running." << endl;
571 switch(lastRequest->dcop_service_type)
573 case KService::DCOP_None:
575 lastRequest->status = TDELaunchRequest::Running;
579 case KService::DCOP_Unique:
581 lastRequest->status = TDELaunchRequest::Launching;
585 case KService::DCOP_Wait:
587 lastRequest->status = TDELaunchRequest::Launching;
591 case KService::DCOP_Multi:
593 lastRequest->status = TDELaunchRequest::Launching;
600 if (lastRequest && (request_header.cmd == LAUNCHER_ERROR))
602 lastRequest->status = TDELaunchRequest::Error;
603 if (!requestData.isEmpty())
604 lastRequest->errorMsg = TQString::fromUtf8((
char *) requestData.data());
609 kdWarning(7016) <<
"Unexpected command from TDEInit (" << (
unsigned int) request_header.cmd
614 TDELauncher::processDied(pid_t pid,
long )
616 TDELaunchRequest *request = requestList.first();
617 for(; request; request = requestList.next())
619 if (request->pid == pid)
621 if (request->dcop_service_type == KService::DCOP_Wait)
622 request->status = TDELaunchRequest::Done;
623 else if ((request->dcop_service_type == KService::DCOP_Unique) &&
624 (dcopClient()->isApplicationRegistered(request->dcop_name)))
625 request->status = TDELaunchRequest::Running;
627 request->status = TDELaunchRequest::Error;
628 requestDone(request);
635 TDELauncher::slotAppRegistered(
const TQCString &appId)
637 const char *cAppId = appId.data();
640 TDELaunchRequest *request = requestList.first();
641 TDELaunchRequest *nextRequest;
642 for(; request; request = nextRequest)
644 nextRequest = requestList.next();
645 if (request->status != TDELaunchRequest::Launching)
649 if ((request->dcop_service_type == KService::DCOP_Unique) &&
650 ((appId == request->dcop_name) ||
651 dcopClient()->isApplicationRegistered(request->dcop_name)))
653 request->status = TDELaunchRequest::Running;
654 requestDone(request);
658 const char *rAppId = request->dcop_name.data();
659 if (!rAppId)
continue;
661 int l = strlen(rAppId);
662 if ((strncmp(rAppId, cAppId, l) == 0) &&
663 ((cAppId[l] ==
'\0') || (cAppId[l] ==
'-')))
665 request->dcop_name = appId;
666 request->status = TDELaunchRequest::Running;
667 requestDone(request);
674 TDELauncher::autoStart(
int phase)
676 if( mAutoStart.phase() >= phase )
678 mAutoStart.setPhase(phase);
682 mAutoStart.loadAutoStartList();
687 mAutoStart.loadAutoStartList();
689 mAutoTimer.start(0,
true);
693 TDELauncher::slotAutoStart()
698 TQString service = mAutoStart.startService();
699 if (service.isEmpty())
702 if( !mAutoStart.phaseDone())
704 mAutoStart.setPhaseDone();
708 TQCString autoStartSignal;
709 autoStartSignal.sprintf(
"autoStart%dDone()", mAutoStart.phase());
710 emitDCOPSignal(autoStartSignal, TQByteArray());
714 TQCString autoStartSignal(
"autoStartDone()" );
715 int phase = mAutoStart.phase();
717 autoStartSignal.sprintf(
"autoStart%dDone()", phase );
718 emitDCOPSignal(autoStartSignal, TQByteArray());
723 s =
new KService(service);
725 while (!start_service(s, TQStringList(), TQValueList<TQCString>(),
"0",
false,
true));
730 TDELauncher::requestDone(TDELaunchRequest *request)
732 if ((request->status == TDELaunchRequest::Running) ||
733 (request->status == TDELaunchRequest::Done))
735 DCOPresult.result = 0;
736 DCOPresult.dcopName = request->dcop_name;
737 DCOPresult.error = TQString::null;
738 DCOPresult.pid = request->pid;
742 DCOPresult.result = 1;
743 DCOPresult.dcopName =
"";
744 DCOPresult.error = i18n(
"TDEInit could not launch '%1'.").arg(TQString(request->name));
745 if (!request->errorMsg.isEmpty())
746 DCOPresult.error +=
":\n" + request->errorMsg;
749 #if defined TQ_WS_X11 && ! defined K_WS_QTONLY
751 if (!request->startup_dpy.isEmpty())
754 if( (mCached_dpy != NULL) &&
755 (request->startup_dpy == XDisplayString( mCached_dpy )))
758 dpy = XOpenDisplay( request->startup_dpy );
762 id.initId( request->startup_id );
763 TDEStartupInfo::sendFinishX( dpy,
id );
764 if( mCached_dpy != dpy && mCached_dpy != NULL )
765 XCloseDisplay( mCached_dpy );
772 if (request->autoStart)
774 mAutoTimer.start(0,
true);
777 if (request->transaction)
779 TQByteArray replyData;
781 replyType =
"serviceResult";
782 TQDataStream stream2(replyData, IO_WriteOnly);
783 stream2 << DCOPresult.result << DCOPresult.dcopName << DCOPresult.error << DCOPresult.pid;
784 dcopClient()->endTransaction( request->transaction,
785 replyType, replyData);
787 requestList.removeRef( request );
791 TDELauncher::requestStart(TDELaunchRequest *request)
793 requestList.append( request );
795 tdelauncher_header request_header;
796 TQByteArray requestData;
798 length +=
sizeof(long);
799 length += request->name.length() + 1;
800 for(TQValueList<TQCString>::Iterator it = request->arg_list.begin();
801 it != request->arg_list.end();
804 length += (*it).length() + 1;
806 length +=
sizeof(long);
807 for(TQValueList<TQCString>::ConstIterator it = request->envs.begin();
808 it != request->envs.end();
811 length += (*it).length() + 1;
813 length +=
sizeof( long );
815 bool startup_notify = !request->startup_id.isNull() && request->startup_id !=
"0";
817 length += request->startup_id.length() + 1;
819 if (!request->cwd.isEmpty())
820 length += request->cwd.length() + 1;
822 requestData.resize( length );
824 char *p = requestData.data();
825 long l = request->arg_list.count()+1;
826 memcpy(p, &l,
sizeof(
long));
828 strcpy(p, request->name.data());
830 for(TQValueList<TQCString>::Iterator it = request->arg_list.begin();
831 it != request->arg_list.end();
834 strcpy(p, (*it).data());
837 l = request->envs.count();
838 memcpy(p, &l,
sizeof(
long));
840 for(TQValueList<TQCString>::ConstIterator it = request->envs.begin();
841 it != request->envs.end();
844 strcpy(p, (*it).data());
848 memcpy(p, &l,
sizeof(
long));
853 strcpy(p, request->startup_id.data());
854 p += strlen( p ) + 1;
857 if (!request->cwd.isEmpty())
859 strcpy(p, request->cwd.data());
860 p += strlen( p ) + 1;
863 request_header.cmd = startup_notify ? LAUNCHER_EXT_EXEC : LAUNCHER_EXEC_NEW;
865 request_header.cmd = LAUNCHER_EXEC_NEW;
867 request_header.arg_length = length;
868 write(tdeinitSocket, &request_header,
sizeof(request_header));
869 write(tdeinitSocket, requestData.data(), request_header.arg_length);
872 lastRequest = request;
873 dontBlockReading =
false;
875 slotKDEInitData( tdeinitSocket );
877 while (lastRequest != 0);
878 dontBlockReading =
true;
882 TDELauncher::exec_blind(
const TQCString &name,
const TQValueList<TQCString> &arg_list,
883 const TQValueList<TQCString> &envs,
const TQCString& startup_id )
885 TDELaunchRequest *request =
new TDELaunchRequest;
886 request->autoStart =
false;
887 request->name = name;
888 request->arg_list = arg_list;
889 request->dcop_name = 0;
890 request->dcop_service_type = KService::DCOP_None;
892 request->status = TDELaunchRequest::Launching;
893 request->transaction = 0;
894 request->envs = envs;
896 KService::Ptr service = KService::serviceByDesktopName( name.mid( name.findRev(
'/' ) + 1 ));
898 send_service_startup_info( request, service,
899 startup_id, TQValueList< TQCString >());
901 cancel_service_startup_info( request, startup_id, envs );
903 requestStart(request);
905 requestDone(request);
910 TDELauncher::start_service_by_name(
const TQString &serviceName,
const TQStringList &urls,
911 const TQValueList<TQCString> &envs,
const TQCString& startup_id,
bool blind)
913 KService::Ptr service = 0;
915 service = KService::serviceByName(serviceName);
918 DCOPresult.result = ENOENT;
919 DCOPresult.error = i18n(
"Could not find service '%1'.").arg(serviceName);
920 cancel_service_startup_info( NULL, startup_id, envs );
923 return start_service(service, urls, envs, startup_id, blind);
927 TDELauncher::start_service_by_desktop_path(
const TQString &serviceName,
const TQStringList &urls,
928 const TQValueList<TQCString> &envs,
const TQCString& startup_id,
bool blind)
930 KService::Ptr service = 0;
932 if (serviceName[0] ==
'/')
935 service =
new KService(serviceName);
939 service = KService::serviceByDesktopPath(serviceName);
943 DCOPresult.result = ENOENT;
944 DCOPresult.error = i18n(
"Could not find service '%1'.").arg(serviceName);
945 cancel_service_startup_info( NULL, startup_id, envs );
948 return start_service(service, urls, envs, startup_id, blind);
952 TDELauncher::start_service_by_desktop_name(
const TQString &serviceName,
const TQStringList &urls,
953 const TQValueList<TQCString> &envs,
const TQCString& startup_id,
bool blind)
955 KService::Ptr service = 0;
957 service = KService::serviceByDesktopName(serviceName);
960 DCOPresult.result = ENOENT;
961 DCOPresult.error = i18n(
"Could not find service '%1'.").arg(serviceName);
962 cancel_service_startup_info( NULL, startup_id, envs );
965 return start_service(service, urls, envs, startup_id, blind);
969 TDELauncher::start_service(KService::Ptr service,
const TQStringList &_urls,
970 const TQValueList<TQCString> &envs,
const TQCString& startup_id,
bool blind,
bool autoStart)
972 TQStringList urls = _urls;
973 if (!service->isValid())
975 DCOPresult.result = ENOEXEC;
976 DCOPresult.error = i18n(
"Service '%1' is malformatted.").arg(service->desktopEntryPath());
977 cancel_service_startup_info( NULL, startup_id, envs );
980 TDELaunchRequest *request =
new TDELaunchRequest;
981 request->autoStart = autoStart;
983 if ((urls.count() > 1) && !service->allowMultipleFiles())
990 TQStringList::ConstIterator it = urls.begin();
995 TQStringList singleUrl;
996 singleUrl.append(*it);
997 TQCString startup_id2 = startup_id;
998 if( !startup_id2.isEmpty() && startup_id2 !=
"0" )
1000 start_service( service, singleUrl, envs, startup_id2,
true);
1002 TQString firstURL = *(urls.begin());
1004 urls.append(firstURL);
1006 createArgs(request, service, urls);
1009 if (!request->arg_list.count())
1011 DCOPresult.result = ENOEXEC;
1012 DCOPresult.error = i18n(
"Service '%1' is malformatted.").arg(service->desktopEntryPath());
1014 cancel_service_startup_info( NULL, startup_id, envs );
1018 request->name = request->arg_list.first();
1019 request->arg_list.remove(request->arg_list.begin());
1021 request->dcop_service_type = service->DCOPServiceType();
1023 if ((request->dcop_service_type == KService::DCOP_Unique) ||
1024 (request->dcop_service_type == KService::DCOP_Multi))
1026 TQVariant v = service->property(
"X-DCOP-ServiceName");
1028 request->dcop_name = v.toString().utf8();
1029 if (request->dcop_name.isEmpty())
1031 request->dcop_name = TQFile::encodeName(KRun::binaryName(service->exec(),
true));
1036 request->transaction = 0;
1037 request->envs = envs;
1038 send_service_startup_info( request, service, startup_id, envs );
1041 if (!blind && !autoStart)
1043 request->transaction = dcopClient()->beginTransaction();
1045 queueRequest(request);
1050 TDELauncher::send_service_startup_info( TDELaunchRequest *request, KService::Ptr service,
const TQCString& startup_id,
1051 const TQValueList<TQCString> &envs )
1053 #if defined TQ_WS_X11 && ! defined K_WS_QTONLY
1055 request->startup_id =
"0";
1056 if( startup_id ==
"0" )
1060 if( !KRun::checkStartupNotify( TQString::null, service, &silent, &wmclass ))
1062 TDEStartupInfoId id;
1063 id.initId( startup_id );
1064 const char* dpy_str = NULL;
1065 for( TQValueList<TQCString>::ConstIterator it = envs.begin();
1068 if( strncmp( *it,
"DISPLAY=", 8 ) == 0 )
1069 dpy_str =
static_cast< const char*
>( *it ) + 8;
1070 Display* dpy = NULL;
1071 if( dpy_str != NULL && mCached_dpy != NULL
1072 && qstrcmp( dpy_str, XDisplayString( mCached_dpy )) == 0 )
1075 dpy = XOpenDisplay( dpy_str );
1076 request->startup_id =
id.id();
1079 cancel_service_startup_info( request, startup_id, envs );
1083 request->startup_dpy = dpy_str;
1085 TDEStartupInfoData data;
1086 data.setName( service->name());
1087 data.setIcon( service->icon());
1088 data.setDescription( i18n(
"Launching %1" ).arg( service->name()));
1089 if( !wmclass.isEmpty())
1090 data.setWMClass( wmclass );
1092 data.setSilent( TDEStartupInfoData::Yes );
1094 TDEStartupInfo::sendStartupX( dpy,
id, data );
1095 if( mCached_dpy != dpy && mCached_dpy != NULL )
1096 XCloseDisplay( mCached_dpy );
1105 TDELauncher::cancel_service_startup_info( TDELaunchRequest* request,
const TQCString& startup_id,
1106 const TQValueList<TQCString> &envs )
1108 #if defined TQ_WS_X11 && ! defined K_WS_QTONLY
1110 if( request != NULL )
1111 request->startup_id =
"0";
1112 if( !startup_id.isEmpty() && startup_id !=
"0" )
1114 const char* dpy_str = NULL;
1115 for( TQValueList<TQCString>::ConstIterator it = envs.begin();
1118 if( strncmp( *it,
"DISPLAY=", 8 ) == 0 )
1119 dpy_str =
static_cast< const char*
>( *it ) + 8;
1120 Display* dpy = NULL;
1121 if( dpy_str != NULL && mCached_dpy != NULL
1122 && qstrcmp( dpy_str, XDisplayString( mCached_dpy )) == 0 )
1125 dpy = XOpenDisplay( dpy_str );
1128 TDEStartupInfoId id;
1129 id.initId( startup_id );
1130 TDEStartupInfo::sendFinishX( dpy,
id );
1131 if( mCached_dpy != dpy && mCached_dpy != NULL )
1132 XCloseDisplay( mCached_dpy );
1139 TDELauncher::tdeinit_exec(
const TQString &app,
const TQStringList &args,
1140 const TQValueList<TQCString> &envs, TQCString startup_id,
bool wait)
1142 TDELaunchRequest *request =
new TDELaunchRequest;
1143 request->autoStart =
false;
1145 for(TQStringList::ConstIterator it = args.begin();
1150 request->arg_list.append(arg.local8Bit());
1153 request->name = app.local8Bit();
1156 request->dcop_service_type = KService::DCOP_Wait;
1158 request->dcop_service_type = KService::DCOP_None;
1159 request->dcop_name = 0;
1162 request->startup_id = startup_id;
1164 request->envs = envs;
1165 if( app !=
"tdebuildsycoca" )
1168 KService::Ptr service = KService::serviceByDesktopName( app.mid( app.findRev(
'/' ) + 1 ));
1169 if (service != NULL)
1170 send_service_startup_info( request, service,
1171 startup_id, TQValueList< TQCString >());
1173 cancel_service_startup_info( request, startup_id, envs );
1175 request->transaction = dcopClient()->beginTransaction();
1176 queueRequest(request);
1181 TDELauncher::queueRequest(TDELaunchRequest *request)
1183 requestQueue.append( request );
1184 if (!bProcessingQueue)
1186 bProcessingQueue =
true;
1187 TQTimer::singleShot(0,
this, TQ_SLOT( slotDequeue() ));
1192 TDELauncher::slotDequeue()
1195 TDELaunchRequest *request = requestQueue.take(0);
1197 request->status = TDELaunchRequest::Launching;
1198 requestStart(request);
1199 if (request->status != TDELaunchRequest::Launching)
1202 requestDone( request );
1205 }
while(requestQueue.count());
1206 bProcessingQueue =
false;
1210 TDELauncher::createArgs( TDELaunchRequest *request,
const KService::Ptr service ,
1211 const TQStringList &urls)
1213 TQStringList params = KRun::processDesktopExec(*service, urls,
false);
1215 for(TQStringList::ConstIterator it = params.begin();
1216 it != params.end(); ++it)
1218 request->arg_list.append((*it).local8Bit());
1220 request->cwd = TQFile::encodeName(service->path());
1226 TDELauncher::requestHoldSlave(
const KURL &url,
const TQString &app_socket)
1229 for(slave = mSlaveList.first(); slave; slave = mSlaveList.next())
1231 if (slave->onHold(url))
1236 mSlaveList.removeRef(slave);
1237 slave->connect(app_socket);
1238 return slave->pid();
1245 TDELauncher::requestSlave(
const TQString &protocol,
1246 const TQString &host,
1247 const TQString &app_socket,
1251 for(slave = mSlaveList.first(); slave; slave = mSlaveList.next())
1253 if (slave->match(protocol, host,
true))
1258 for(slave = mSlaveList.first(); slave; slave = mSlaveList.next())
1260 if (slave->match(protocol, host,
false))
1266 for(slave = mSlaveList.first(); slave; slave = mSlaveList.next())
1268 if (slave->match(protocol, TQString::null,
false))
1274 mSlaveList.removeRef(slave);
1275 slave->connect(app_socket);
1276 return slave->pid();
1279 TQString _name = KProtocolInfo::exec(protocol);
1280 if (_name.isEmpty())
1282 error = i18n(
"Unknown protocol '%1'.\n").arg(protocol);
1286 TQCString name = _name.latin1();
1287 TQCString arg1 = protocol.latin1();
1288 TQCString arg2 = TQFile::encodeName(mPoolSocketName);
1289 TQCString arg3 = TQFile::encodeName(app_socket);
1290 TQValueList<TQCString> arg_list;
1291 arg_list.append(arg1);
1292 arg_list.append(arg2);
1293 arg_list.append(arg3);
1296 if (mSlaveDebug == arg1)
1298 tdelauncher_header request_header;
1299 request_header.cmd = LAUNCHER_DEBUG_WAIT;
1300 request_header.arg_length = 0;
1301 write(tdeinitSocket, &request_header,
sizeof(request_header));
1303 if (mSlaveValgrind == arg1)
1305 arg_list.prepend(TQFile::encodeName(KLibLoader::findLibrary(name)));
1306 arg_list.prepend(TQFile::encodeName(locate(
"exe",
"tdeioslave")));
1308 if (!mSlaveValgrindSkin.isEmpty()) {
1309 arg_list.prepend(TQCString(
"--tool=") + mSlaveValgrindSkin);
1311 arg_list.prepend(
"--tool=memcheck");
1314 TDELaunchRequest *request =
new TDELaunchRequest;
1315 request->autoStart =
false;
1316 request->name = name;
1317 request->arg_list = arg_list;
1318 request->dcop_name = 0;
1319 request->dcop_service_type = KService::DCOP_None;
1322 request->startup_id =
"0";
1324 request->status = TDELaunchRequest::Launching;
1325 request->transaction = 0;
1326 requestStart(request);
1327 pid_t pid = request->pid;
1332 requestDone(request);
1335 error = i18n(
"Error loading '%1'.\n").arg(TQString(name));
1341 TDELauncher::waitForSlave(pid_t pid)
1344 for(slave = mSlaveList.first(); slave; slave = mSlaveList.next())
1346 if (slave->pid() == pid)
1349 SlaveWaitRequest *waitRequest =
new SlaveWaitRequest;
1350 waitRequest->transaction = dcopClient()->beginTransaction();
1351 waitRequest->pid = pid;
1352 mSlaveWaitRequest.append(waitRequest);
1356 TDELauncher::acceptSlave(TDESocket *slaveSocket)
1358 IdleSlave *slave =
new IdleSlave(slaveSocket);
1360 mSlaveList.append(slave);
1361 connect(slave, TQ_SIGNAL(destroyed()),
this, TQ_SLOT(slotSlaveGone()));
1362 connect(slave, TQ_SIGNAL(statusUpdate(IdleSlave *)),
1363 this, TQ_SLOT(slotSlaveStatus(IdleSlave *)));
1364 if (!mTimer.isActive())
1366 mTimer.start(1000*10);
1371 TDELauncher::slotSlaveStatus(IdleSlave *slave)
1373 SlaveWaitRequest *waitRequest = mSlaveWaitRequest.first();
1376 if (waitRequest->pid == slave->pid())
1378 TQByteArray replyData;
1379 TQCString replyType;
1381 dcopClient()->endTransaction( waitRequest->transaction, replyType, replyData);
1382 mSlaveWaitRequest.removeRef(waitRequest);
1383 waitRequest = mSlaveWaitRequest.current();
1387 waitRequest = mSlaveWaitRequest.next();
1393 TDELauncher::slotSlaveGone()
1395 IdleSlave *slave = (IdleSlave *) sender();
1396 mSlaveList.removeRef(slave);
1397 if ((mSlaveList.count() == 0) && (mTimer.isActive()))
1404 TDELauncher::idleTimeout()
1406 bool keepOneFileSlave=
true;
1407 time_t now = time(0);
1409 for(slave = mSlaveList.first(); slave; slave = mSlaveList.next())
1411 if ((slave->protocol()==
"file") && (keepOneFileSlave))
1412 keepOneFileSlave=
false;
1413 else if (slave->age(now) > SLAVE_MAX_IDLE)
1421 #include "tdelauncher.moc"