• Skip to content
  • Skip to link menu
Trinity API Reference
  • Trinity API Reference
  • tdeinit
 

tdeinit

  • tdeinit
tdelauncher.cpp
1/*
2 This file is part of the KDE libraries
3 Copyright (c) 1999 Waldo Bastian <bastian@kde.org>
4
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Library General Public
7 License version 2 as published by the Free Software Foundation.
8
9 This library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Library General Public License for more details.
13
14 You should have received a copy of the GNU Library General Public License
15 along with this library; see the file COPYING.LIB. If not, write to
16 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 Boston, MA 02110-1301, USA.
18*/
19#ifdef HAVE_CONFIG_H
20#include <config.h>
21#endif
22
23#include <stdio.h>
24#include <unistd.h>
25#include <stdlib.h>
26#include <errno.h>
27#include <signal.h>
28#include <sys/time.h>
29
30#include <tqfile.h>
31
32#include <tdeconfig.h>
33#include <kdebug.h>
34#include <klibloader.h>
35#include <tdelocale.h>
36#include <tdeprotocolmanager.h>
37#include <kprotocolinfo.h>
38#include <krun.h>
39#include <tdestandarddirs.h>
40#include <tdetempfile.h>
41#include <kurl.h>
42
43#if defined TQ_WS_X11 && ! defined K_WS_QTONLY
44#include <tdestartupinfo.h> // schroder
45#endif
46
47
48#include "tdeio/global.h"
49#include "tdeio/connection.h"
50#include "tdeio/slaveinterface.h"
51
52#include "tdelauncher.h"
53#include "tdelauncher_cmds.h"
54
55//#if defined TQ_WS_X11 && ! defined K_WS_QTONLY
56#ifdef TQ_WS_X11
57//#undef K_WS_QTONLY
58#include <X11/Xlib.h> // schroder
59#endif
60
61// Dispose slaves after being idle for SLAVE_MAX_IDLE seconds
62#define SLAVE_MAX_IDLE 30
63
64using namespace TDEIO;
65
66template class TQPtrList<TDELaunchRequest>;
67template class TQPtrList<IdleSlave>;
68
69IdleSlave::IdleSlave(TDESocket *socket)
70{
71 mConn.init(socket);
72 mConn.connect(this, TQ_SLOT(gotInput()));
73 mConn.send( CMD_SLAVE_STATUS );
74 mPid = 0;
75 mBirthDate = time(0);
76 mOnHold = false;
77}
78
79void
80IdleSlave::gotInput()
81{
82 int cmd;
83 TQByteArray data;
84 if (mConn.read( &cmd, data) == -1)
85 {
86 // Communication problem with slave.
87 kdError(7016) << "SlavePool: No communication with slave." << endl;
88 delete this;
89 }
90 else if (cmd == MSG_SLAVE_ACK)
91 {
92 delete this;
93 }
94 else if (cmd != MSG_SLAVE_STATUS)
95 {
96 kdError(7016) << "SlavePool: Unexpected data from slave." << endl;
97 delete this;
98 }
99 else
100 {
101 TQDataStream stream( data, IO_ReadOnly );
102 pid_t pid;
103 TQCString protocol;
104 TQString host;
105 TQ_INT8 b;
106 stream >> pid >> protocol >> host >> b;
107// Overload with (bool) onHold, (KURL) url.
108 if (!stream.atEnd())
109 {
110 KURL url;
111 stream >> url;
112 mOnHold = true;
113 mUrl = url;
114 }
115
116 mPid = pid;
117 mConnected = (b != 0);
118 mProtocol = protocol;
119 mHost = host;
120 emit statusUpdate(this);
121 }
122}
123
124void
125IdleSlave::connect(const TQString &app_socket)
126{
127 TQByteArray data;
128 TQDataStream stream( data, IO_WriteOnly);
129 stream << app_socket;
130 mConn.send( CMD_SLAVE_CONNECT, data );
131 // Timeout!
132}
133
134void
135IdleSlave::reparseConfiguration()
136{
137 mConn.send( CMD_REPARSECONFIGURATION );
138}
139
140bool
141IdleSlave::match(const TQString &protocol, const TQString &host, bool connected)
142{
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;
149 return true;
150}
151
152bool
153IdleSlave::onHold(const KURL &url)
154{
155 if (!mOnHold) return false;
156 return (url == mUrl);
157}
158
159int
160IdleSlave::age(time_t now)
161{
162 return (int) difftime(now, mBirthDate);
163}
164
165TDELauncher::TDELauncher(int _tdeinitSocket, bool new_startup)
166// : TDEApplication( false, false ), // No Styles, No GUI
167 : TDEApplication( false, true ), // TQClipboard tries to construct a TQWidget so a GUI is technically needed, even though it is not used
168 DCOPObject("tdelauncher"),
169 tdeinitSocket(_tdeinitSocket), mAutoStart( new_startup ),
170 dontBlockReading(false), newStartup( new_startup )
171{
172#ifdef TQ_WS_X11
173 mCached_dpy = NULL;
174#endif
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 );
183
184 TQString prefix = locateLocal("socket", "tdelauncher");
185 KTempFile domainname(prefix, TQString::fromLatin1(".slave-socket"));
186 if (domainname.status() != 0)
187 {
188 // Sever error!
189 tqDebug("TDELauncher: Fatal error, can't create tempfile!");
190 ::exit(1);
191 }
192 mPoolSocketName = domainname.name();
193#ifdef __CYGWIN__
194 domainname.close();
195 domainname.unlink();
196#endif
197 mPoolSocket = new TDEServerSocket(static_cast<const char*>(TQFile::encodeName(mPoolSocketName)));
198 connect(mPoolSocket, TQ_SIGNAL(accepted( TDESocket *)),
199 TQ_SLOT(acceptSlave(TDESocket *)));
200
201 connect(&mTimer, TQ_SIGNAL(timeout()), TQ_SLOT(idleTimeout()));
202
203 tdeinitNotifier = new TQSocketNotifier(tdeinitSocket, TQSocketNotifier::Read);
204 connect(tdeinitNotifier, TQ_SIGNAL( activated( int )),
205 this, TQ_SLOT( slotKDEInitData( int )));
206 tdeinitNotifier->setEnabled( true );
207 lastRequest = 0;
208 bProcessingQueue = false;
209
210 mSlaveDebug = getenv("TDE_SLAVE_DEBUG_WAIT");
211 if (!mSlaveDebug.isEmpty())
212 {
213 tqWarning("Klauncher running in slave-debug mode for slaves of protocol '%s'", mSlaveDebug.data());
214 }
215 mSlaveValgrind = getenv("TDE_SLAVE_VALGRIND");
216 if (!mSlaveValgrind.isEmpty())
217 {
218 mSlaveValgrindSkin = getenv("TDE_SLAVE_VALGRIND_SKIN");
219 tqWarning("Klauncher running slaves through valgrind for slaves of protocol '%s'", mSlaveValgrind.data());
220 }
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));
225}
226
227TDELauncher::~TDELauncher()
228{
229 close();
230}
231
232void TDELauncher::close()
233{
234 if (!mPoolSocketName.isEmpty())
235 {
236 TQCString filename = TQFile::encodeName(mPoolSocketName);
237 unlink(filename.data());
238 }
239#if defined TQ_WS_X11 && ! defined K_WS_QTONLY
240//#ifdef TQ_WS_X11
241 if( mCached_dpy != NULL )
242 XCloseDisplay( mCached_dpy );
243#endif
244}
245
246void
247TDELauncher::destruct(int exit_code)
248{
249 if (tdeApp) ((TDELauncher*)tdeApp)->close();
250 // We don't delete tdeApp here, that's intentional.
251 ::exit(exit_code);
252}
253
254bool
255TDELauncher::process(const TQCString &fun, const TQByteArray &data,
256 TQCString &replyType, TQByteArray &replyData)
257{
258 if ((fun == "exec_blind(TQCString,TQValueList<TQCString>)")
259 || (fun == "exec_blind(TQCString,TQValueList<TQCString>,TQValueList<TQCString>,TQCString)"))
260 {
261 TQDataStream stream(data, IO_ReadOnly);
262 replyType = "void";
263 TQCString name;
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);
272 return true;
273 }
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)"))
289 {
290 TQDataStream stream(data, IO_ReadOnly);
291 bool bNoWait = false;
292 TQString serviceName;
293 TQStringList urls;
294 TQValueList<TQCString> envs;
295 TQCString startup_id = "";
296 DCOPresult.result = -1;
297 DCOPresult.dcopName = 0;
298 DCOPresult.error = TQString::null;
299 DCOPresult.pid = 0;
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>)"))
311 stream >> envs;
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;
315 bool finished;
316 if (strncmp(fun, "start_service_by_name(", 22) == 0)
317 {
318 kdDebug(7016) << "TDELauncher: Got start_service_by_name('" << serviceName << "', ...)" << endl;
319 finished = start_service_by_name(serviceName, urls, envs, startup_id, bNoWait);
320 }
321 else if (strncmp(fun, "start_service_by_desktop_path(", 30) == 0)
322 {
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);
325 }
326 else if (strncmp(fun, "start_service_by_desktop_name(", 30) == 0)
327 {
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 );
330 }
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)"))
334 {
335 kdDebug(7016) << "TDELauncher: Got tdeinit_exec('" << serviceName << "', ...)" << endl;
336 finished = tdeinit_exec(serviceName, urls, envs, startup_id, false);
337 }
338 else
339 {
340 kdDebug(7016) << "TDELauncher: Got tdeinit_exec_wait('" << serviceName << "', ...)" << endl;
341 finished = tdeinit_exec(serviceName, urls, envs, startup_id, true);
342 }
343 if (!finished)
344 {
345 replyType = "serviceResult";
346 TQDataStream stream2(replyData, IO_WriteOnly);
347 stream2 << DCOPresult.result << DCOPresult.dcopName << DCOPresult.error << DCOPresult.pid;
348 }
349 return true;
350 }
351 else if (fun == "requestSlave(TQString,TQString,TQString)")
352 {
353 TQDataStream stream(data, IO_ReadOnly);
354 TQString protocol;
355 TQString host;
356 TQString app_socket;
357 stream >> protocol >> host >> app_socket;
358 replyType = "TQString";
359 TQString error;
360 pid_t pid = requestSlave(protocol, host, app_socket, error);
361 TQDataStream stream2(replyData, IO_WriteOnly);
362 stream2 << pid << error;
363 return true;
364 }
365 else if (fun == "requestHoldSlave(KURL,TQString)")
366 {
367 TQDataStream stream(data, IO_ReadOnly);
368 KURL url;
369 TQString app_socket;
370 stream >> url >> app_socket;
371 replyType = "pid_t";
372 pid_t pid = requestHoldSlave(url, app_socket);
373 TQDataStream stream2(replyData, IO_WriteOnly);
374 stream2 << pid;
375 return true;
376 }
377 else if (fun == "waitForSlave(pid_t)")
378 {
379 TQDataStream stream(data, IO_ReadOnly);
380 pid_t pid;
381 stream >> pid;
382 waitForSlave(pid);
383 replyType = "void";
384 return true;
385
386 }
387 else if (fun == "setLaunchEnv(TQCString,TQCString)")
388 {
389 TQDataStream stream(data, IO_ReadOnly);
390 TQCString name;
391 TQCString value;
392 stream >> name >> value;
393 setLaunchEnv(name, value);
394 replyType = "void";
395 return true;
396 }
397 else if (fun == "reparseConfiguration()")
398 {
399 TDEGlobal::config()->reparseConfiguration();
400 kdDebug(7016) << "TDELauncher::process : reparseConfiguration" << endl;
401 KProtocolManager::reparseConfiguration();
402 IdleSlave *slave;
403 for(slave = mSlaveList.first(); slave; slave = mSlaveList.next())
404 slave->reparseConfiguration();
405 replyType = "void";
406 return true;
407 }
408 else if (fun == "terminateTDE()")
409 {
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));
417 destruct(0);
418 }
419 else if (fun == "autoStart()")
420 {
421 kdDebug() << "TDELauncher::process ---> autoStart" << endl;
422 autoStart(1);
423 replyType = "void";
424 return true;
425 }
426 else if (fun == "autoStart(int)")
427 {
428 kdDebug() << "TDELauncher::process ---> autoStart(int)" << endl;
429 TQDataStream stream(data, IO_ReadOnly);
430 int phase;
431 stream >> phase;
432 autoStart(phase);
433 replyType = "void";
434 return true;
435 }
436
437 if (DCOPObject::process(fun, data, replyType, replyData))
438 {
439 return true;
440 }
441 kdWarning(7016) << "Got unknown DCOP function: " << fun << endl;
442 return false;
443}
444
445QCStringList
446TDELauncher::interfaces()
447{
448 QCStringList ifaces = DCOPObject::interfaces();
449 ifaces += "TDELauncher";
450 return ifaces;
451}
452
453QCStringList
454TDELauncher::functions()
455{
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()";
477// funcs << "void terminateTDE()";
478 funcs << "void autoStart()";
479 funcs << "void autoStart(int)";
480 return funcs;
481}
482
483void TDELauncher::setLaunchEnv(const TQCString &name, const TQCString &_value)
484{
485 TQCString value(_value);
486 if (value.isNull())
487 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);
496}
497
498/*
499 * Read 'len' bytes from 'sock' into buffer.
500 * returns -1 on failure, 0 on no data.
501 */
502static int
503read_socket(int sock, char *buffer, int len)
504{
505 ssize_t result;
506 int bytes_left = len;
507 while ( bytes_left > 0)
508 {
509 result = read(sock, buffer, bytes_left);
510 if (result > 0)
511 {
512 buffer += result;
513 bytes_left -= result;
514 }
515 else if (result == 0)
516 return -1;
517 else if ((result == -1) && (errno != EINTR))
518 return -1;
519 }
520 return 0;
521}
522
523
524void
525TDELauncher::slotKDEInitData(int)
526{
527 tdelauncher_header request_header;
528 TQByteArray requestData;
529 if( dontBlockReading )
530 {
531 // in case we get a request to start an application and data arrive
532 // to tdeinitSocket at the same time, requestStart() will already
533 // call slotKDEInitData(), so we must check there's still something
534 // to read, otherwise this would block
535 fd_set in;
536 timeval tm = { 0, 0 };
537 FD_ZERO ( &in );
538 FD_SET( tdeinitSocket, &in );
539 select( tdeinitSocket + 1, &in, 0, 0, &tm );
540 if( !FD_ISSET( tdeinitSocket, &in ))
541 return;
542 }
543 dontBlockReading = false;
544 int result = read_socket(tdeinitSocket, (char *) &request_header,
545 sizeof( request_header));
546 if (result == -1)
547 {
548 kdDebug() << "Exiting on read_socket errno: " << errno << endl;
549 ::signal( SIGHUP, SIG_IGN);
550 ::signal( SIGTERM, SIG_IGN);
551 destruct(255); // Exit!
552 }
553 requestData.resize(request_header.arg_length);
554 result = read_socket(tdeinitSocket, (char *) requestData.data(),
555 request_header.arg_length);
556
557 if (request_header.cmd == LAUNCHER_DIED)
558 {
559 long *request_data;
560 request_data = (long *) requestData.data();
561 processDied(request_data[0], request_data[1]);
562 return;
563 }
564 if (lastRequest && (request_header.cmd == LAUNCHER_OK))
565 {
566 long *request_data;
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)
572 {
573 case KService::DCOP_None:
574 {
575 lastRequest->status = TDELaunchRequest::Running;
576 break;
577 }
578
579 case KService::DCOP_Unique:
580 {
581 lastRequest->status = TDELaunchRequest::Launching;
582 break;
583 }
584
585 case KService::DCOP_Wait:
586 {
587 lastRequest->status = TDELaunchRequest::Launching;
588 break;
589 }
590
591 case KService::DCOP_Multi:
592 {
593 lastRequest->status = TDELaunchRequest::Launching;
594 break;
595 }
596 }
597 lastRequest = 0;
598 return;
599 }
600 if (lastRequest && (request_header.cmd == LAUNCHER_ERROR))
601 {
602 lastRequest->status = TDELaunchRequest::Error;
603 if (!requestData.isEmpty())
604 lastRequest->errorMsg = TQString::fromUtf8((char *) requestData.data());
605 lastRequest = 0;
606 return;
607 }
608
609 kdWarning(7016) << "Unexpected command from TDEInit (" << (unsigned int) request_header.cmd
610 << ")" << endl;
611}
612
613void
614TDELauncher::processDied(pid_t pid, long /* exitStatus */)
615{
616 TDELaunchRequest *request = requestList.first();
617 for(; request; request = requestList.next())
618 {
619 if (request->pid == pid)
620 {
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;
626 else
627 request->status = TDELaunchRequest::Error;
628 requestDone(request);
629 return;
630 }
631 }
632}
633
634void
635TDELauncher::slotAppRegistered(const TQCString &appId)
636{
637 const char *cAppId = appId.data();
638 if (!cAppId) return;
639
640 TDELaunchRequest *request = requestList.first();
641 TDELaunchRequest *nextRequest;
642 for(; request; request = nextRequest)
643 {
644 nextRequest = requestList.next();
645 if (request->status != TDELaunchRequest::Launching)
646 continue;
647
648 // For unique services check the requested service name first
649 if ((request->dcop_service_type == KService::DCOP_Unique) &&
650 ((appId == request->dcop_name) ||
651 dcopClient()->isApplicationRegistered(request->dcop_name)))
652 {
653 request->status = TDELaunchRequest::Running;
654 requestDone(request);
655 continue;
656 }
657
658 const char *rAppId = request->dcop_name.data();
659 if (!rAppId) continue;
660
661 int l = strlen(rAppId);
662 if ((strncmp(rAppId, cAppId, l) == 0) &&
663 ((cAppId[l] == '\0') || (cAppId[l] == '-')))
664 {
665 request->dcop_name = appId;
666 request->status = TDELaunchRequest::Running;
667 requestDone(request);
668 continue;
669 }
670 }
671}
672
673void
674TDELauncher::autoStart(int phase)
675{
676 if( mAutoStart.phase() >= phase )
677 return;
678 mAutoStart.setPhase(phase);
679 if( newStartup )
680 {
681 if (phase == 0)
682 mAutoStart.loadAutoStartList();
683 }
684 else
685 {
686 if (phase == 1)
687 mAutoStart.loadAutoStartList();
688 }
689 mAutoTimer.start(0, true);
690}
691
692void
693TDELauncher::slotAutoStart()
694{
695 KService::Ptr s;
696 do
697 {
698 TQString service = mAutoStart.startService();
699 if (service.isEmpty())
700 {
701 // Done
702 if( !mAutoStart.phaseDone())
703 {
704 mAutoStart.setPhaseDone();
705 // Emit signal
706 if( newStartup )
707 {
708 TQCString autoStartSignal;
709 autoStartSignal.sprintf( "autoStart%dDone()", mAutoStart.phase());
710 emitDCOPSignal(autoStartSignal, TQByteArray());
711 }
712 else
713 {
714 TQCString autoStartSignal( "autoStartDone()" );
715 int phase = mAutoStart.phase();
716 if ( phase > 1 )
717 autoStartSignal.sprintf( "autoStart%dDone()", phase );
718 emitDCOPSignal(autoStartSignal, TQByteArray());
719 }
720 }
721 return;
722 }
723 s = new KService(service);
724 }
725 while (!start_service(s, TQStringList(), TQValueList<TQCString>(), "0", false, true));
726 // Loop till we find a service that we can start.
727}
728
729void
730TDELauncher::requestDone(TDELaunchRequest *request)
731{
732 if ((request->status == TDELaunchRequest::Running) ||
733 (request->status == TDELaunchRequest::Done))
734 {
735 DCOPresult.result = 0;
736 DCOPresult.dcopName = request->dcop_name;
737 DCOPresult.error = TQString::null;
738 DCOPresult.pid = request->pid;
739 }
740 else
741 {
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;
747 DCOPresult.pid = 0;
748
749#if defined TQ_WS_X11 && ! defined K_WS_QTONLY
750//#ifdef TQ_WS_X11
751 if (!request->startup_dpy.isEmpty())
752 {
753 Display* dpy = NULL;
754 if( (mCached_dpy != NULL) &&
755 (request->startup_dpy == XDisplayString( mCached_dpy )))
756 dpy = mCached_dpy;
757 if( dpy == NULL )
758 dpy = XOpenDisplay( request->startup_dpy );
759 if( dpy )
760 {
761 TDEStartupInfoId id;
762 id.initId( request->startup_id );
763 TDEStartupInfo::sendFinishX( dpy, id );
764 if( mCached_dpy != dpy && mCached_dpy != NULL )
765 XCloseDisplay( mCached_dpy );
766 mCached_dpy = dpy;
767 }
768 }
769#endif
770 }
771
772 if (request->autoStart)
773 {
774 mAutoTimer.start(0, true);
775 }
776
777 if (request->transaction)
778 {
779 TQByteArray replyData;
780 TQCString replyType;
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);
786 }
787 requestList.removeRef( request );
788}
789
790void
791TDELauncher::requestStart(TDELaunchRequest *request)
792{
793 requestList.append( request );
794 // Send request to tdeinit.
795 tdelauncher_header request_header;
796 TQByteArray requestData;
797 int length = 0;
798 length += sizeof(long); // Nr of. Args
799 length += request->name.length() + 1; // Cmd
800 for(TQValueList<TQCString>::Iterator it = request->arg_list.begin();
801 it != request->arg_list.end();
802 it++)
803 {
804 length += (*it).length() + 1; // Args...
805 }
806 length += sizeof(long); // Nr of. envs
807 for(TQValueList<TQCString>::ConstIterator it = request->envs.begin();
808 it != request->envs.end();
809 it++)
810 {
811 length += (*it).length() + 1; // Envs...
812 }
813 length += sizeof( long ); // avoid_loops
814#ifdef TQ_WS_X11
815 bool startup_notify = !request->startup_id.isNull() && request->startup_id != "0";
816 if( startup_notify )
817 length += request->startup_id.length() + 1;
818#endif
819 if (!request->cwd.isEmpty())
820 length += request->cwd.length() + 1;
821
822 requestData.resize( length );
823
824 char *p = requestData.data();
825 long l = request->arg_list.count()+1;
826 memcpy(p, &l, sizeof(long));
827 p += sizeof(long);
828 strcpy(p, request->name.data());
829 p += strlen(p) + 1;
830 for(TQValueList<TQCString>::Iterator it = request->arg_list.begin();
831 it != request->arg_list.end();
832 it++)
833 {
834 strcpy(p, (*it).data());
835 p += strlen(p) + 1;
836 }
837 l = request->envs.count();
838 memcpy(p, &l, sizeof(long));
839 p += sizeof(long);
840 for(TQValueList<TQCString>::ConstIterator it = request->envs.begin();
841 it != request->envs.end();
842 it++)
843 {
844 strcpy(p, (*it).data());
845 p += strlen(p) + 1;
846 }
847 l = 0; // avoid_loops, always false here
848 memcpy(p, &l, sizeof(long));
849 p += sizeof(long);
850#ifdef TQ_WS_X11
851 if( startup_notify )
852 {
853 strcpy(p, request->startup_id.data());
854 p += strlen( p ) + 1;
855 }
856#endif
857 if (!request->cwd.isEmpty())
858 {
859 strcpy(p, request->cwd.data());
860 p += strlen( p ) + 1;
861 }
862#ifdef TQ_WS_X11
863 request_header.cmd = startup_notify ? LAUNCHER_EXT_EXEC : LAUNCHER_EXEC_NEW;
864#else
865 request_header.cmd = LAUNCHER_EXEC_NEW;
866#endif
867 request_header.arg_length = length;
868 write(tdeinitSocket, &request_header, sizeof(request_header));
869 write(tdeinitSocket, requestData.data(), request_header.arg_length);
870
871 // Wait for pid to return.
872 lastRequest = request;
873 dontBlockReading = false;
874 do {
875 slotKDEInitData( tdeinitSocket );
876 }
877 while (lastRequest != 0);
878 dontBlockReading = true;
879}
880
881void
882TDELauncher::exec_blind( const TQCString &name, const TQValueList<TQCString> &arg_list,
883 const TQValueList<TQCString> &envs, const TQCString& startup_id )
884{
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;
891 request->pid = 0;
892 request->status = TDELaunchRequest::Launching;
893 request->transaction = 0; // No confirmation is send
894 request->envs = envs;
895 // Find service, if any - strip path if needed
896 KService::Ptr service = KService::serviceByDesktopName( name.mid( name.findRev( '/' ) + 1 ));
897 if (service != NULL)
898 send_service_startup_info( request, service,
899 startup_id, TQValueList< TQCString >());
900 else // no .desktop file, no startup info
901 cancel_service_startup_info( request, startup_id, envs );
902
903 requestStart(request);
904 // We don't care about this request any longer....
905 requestDone(request);
906}
907
908
909bool
910TDELauncher::start_service_by_name(const TQString &serviceName, const TQStringList &urls,
911 const TQValueList<TQCString> &envs, const TQCString& startup_id, bool blind)
912{
913 KService::Ptr service = 0;
914 // Find service
915 service = KService::serviceByName(serviceName);
916 if (!service)
917 {
918 DCOPresult.result = ENOENT;
919 DCOPresult.error = i18n("Could not find service '%1'.").arg(serviceName);
920 cancel_service_startup_info( NULL, startup_id, envs ); // cancel it if any
921 return false;
922 }
923 return start_service(service, urls, envs, startup_id, blind);
924}
925
926bool
927TDELauncher::start_service_by_desktop_path(const TQString &serviceName, const TQStringList &urls,
928 const TQValueList<TQCString> &envs, const TQCString& startup_id, bool blind)
929{
930 KService::Ptr service = 0;
931 // Find service
932 if (serviceName[0] == '/')
933 {
934 // Full path
935 service = new KService(serviceName);
936 }
937 else
938 {
939 service = KService::serviceByDesktopPath(serviceName);
940 }
941 if (!service)
942 {
943 DCOPresult.result = ENOENT;
944 DCOPresult.error = i18n("Could not find service '%1'.").arg(serviceName);
945 cancel_service_startup_info( NULL, startup_id, envs ); // cancel it if any
946 return false;
947 }
948 return start_service(service, urls, envs, startup_id, blind);
949}
950
951bool
952TDELauncher::start_service_by_desktop_name(const TQString &serviceName, const TQStringList &urls,
953 const TQValueList<TQCString> &envs, const TQCString& startup_id, bool blind)
954{
955 KService::Ptr service = 0;
956 // Find service
957 service = KService::serviceByDesktopName(serviceName);
958 if (!service)
959 {
960 DCOPresult.result = ENOENT;
961 DCOPresult.error = i18n("Could not find service '%1'.").arg(serviceName);
962 cancel_service_startup_info( NULL, startup_id, envs ); // cancel it if any
963 return false;
964 }
965 return start_service(service, urls, envs, startup_id, blind);
966}
967
968bool
969TDELauncher::start_service(KService::Ptr service, const TQStringList &_urls,
970 const TQValueList<TQCString> &envs, const TQCString& startup_id, bool blind, bool autoStart)
971{
972 TQStringList urls = _urls;
973 if (!service->isValid())
974 {
975 DCOPresult.result = ENOEXEC;
976 DCOPresult.error = i18n("Service '%1' is malformatted.").arg(service->desktopEntryPath());
977 cancel_service_startup_info( NULL, startup_id, envs ); // cancel it if any
978 return false;
979 }
980 TDELaunchRequest *request = new TDELaunchRequest;
981 request->autoStart = autoStart;
982
983 if ((urls.count() > 1) && !service->allowMultipleFiles())
984 {
985 // We need to launch the application N times. That sucks.
986 // We ignore the result for application 2 to N.
987 // For the first file we launch the application in the
988 // usual way. The reported result is based on this
989 // application.
990 TQStringList::ConstIterator it = urls.begin();
991 for(++it;
992 it != urls.end();
993 ++it)
994 {
995 TQStringList singleUrl;
996 singleUrl.append(*it);
997 TQCString startup_id2 = startup_id;
998 if( !startup_id2.isEmpty() && startup_id2 != "0" )
999 startup_id2 = "0"; // can't use the same startup_id several times
1000 start_service( service, singleUrl, envs, startup_id2, true);
1001 }
1002 TQString firstURL = *(urls.begin());
1003 urls.clear();
1004 urls.append(firstURL);
1005 }
1006 createArgs(request, service, urls);
1007
1008 // We must have one argument at least!
1009 if (!request->arg_list.count())
1010 {
1011 DCOPresult.result = ENOEXEC;
1012 DCOPresult.error = i18n("Service '%1' is malformatted.").arg(service->desktopEntryPath());
1013 delete request;
1014 cancel_service_startup_info( NULL, startup_id, envs );
1015 return false;
1016 }
1017
1018 request->name = request->arg_list.first();
1019 request->arg_list.remove(request->arg_list.begin());
1020
1021 request->dcop_service_type = service->DCOPServiceType();
1022
1023 if ((request->dcop_service_type == KService::DCOP_Unique) ||
1024 (request->dcop_service_type == KService::DCOP_Multi))
1025 {
1026 TQVariant v = service->property("X-DCOP-ServiceName");
1027 if (v.isValid())
1028 request->dcop_name = v.toString().utf8();
1029 if (request->dcop_name.isEmpty())
1030 {
1031 request->dcop_name = TQFile::encodeName(KRun::binaryName(service->exec(), true));
1032 }
1033 }
1034
1035 request->pid = 0;
1036 request->transaction = 0;
1037 request->envs = envs;
1038 send_service_startup_info( request, service, startup_id, envs );
1039
1040 // Request will be handled later.
1041 if (!blind && !autoStart)
1042 {
1043 request->transaction = dcopClient()->beginTransaction();
1044 }
1045 queueRequest(request);
1046 return true;
1047}
1048
1049void
1050TDELauncher::send_service_startup_info( TDELaunchRequest *request, KService::Ptr service, const TQCString& startup_id,
1051 const TQValueList<TQCString> &envs )
1052{
1053#if defined TQ_WS_X11 && ! defined K_WS_QTONLY
1054//#ifdef TQ_WS_X11 // TDEStartup* isn't implemented for Qt/Embedded yet
1055 request->startup_id = "0";
1056 if( startup_id == "0" )
1057 return;
1058 bool silent;
1059 TQCString wmclass;
1060 if( !KRun::checkStartupNotify( TQString::null, service, &silent, &wmclass ))
1061 return;
1062 TDEStartupInfoId id;
1063 id.initId( startup_id );
1064 const char* dpy_str = NULL;
1065 for( TQValueList<TQCString>::ConstIterator it = envs.begin();
1066 it != envs.end();
1067 ++it )
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 )
1073 dpy = mCached_dpy;
1074 if( dpy == NULL )
1075 dpy = XOpenDisplay( dpy_str );
1076 request->startup_id = id.id();
1077 if( dpy == NULL )
1078 {
1079 cancel_service_startup_info( request, startup_id, envs );
1080 return;
1081 }
1082
1083 request->startup_dpy = dpy_str;
1084
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 );
1091 if( silent )
1092 data.setSilent( TDEStartupInfoData::Yes );
1093 // the rest will be sent by tdeinit
1094 TDEStartupInfo::sendStartupX( dpy, id, data );
1095 if( mCached_dpy != dpy && mCached_dpy != NULL )
1096 XCloseDisplay( mCached_dpy );
1097 mCached_dpy = dpy;
1098 return;
1099#else
1100 return;
1101#endif
1102}
1103
1104void
1105TDELauncher::cancel_service_startup_info( TDELaunchRequest* request, const TQCString& startup_id,
1106 const TQValueList<TQCString> &envs )
1107{
1108#if defined TQ_WS_X11 && ! defined K_WS_QTONLY
1109//#ifdef TQ_WS_X11 // TDEStartup* isn't implemented for Qt/Embedded yet
1110 if( request != NULL )
1111 request->startup_id = "0";
1112 if( !startup_id.isEmpty() && startup_id != "0" )
1113 {
1114 const char* dpy_str = NULL;
1115 for( TQValueList<TQCString>::ConstIterator it = envs.begin();
1116 it != envs.end();
1117 ++it )
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 )
1123 dpy = mCached_dpy;
1124 if( dpy == NULL )
1125 dpy = XOpenDisplay( dpy_str );
1126 if( dpy == NULL )
1127 return;
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 );
1133 mCached_dpy = dpy;
1134 }
1135#endif
1136}
1137
1138bool
1139TDELauncher::tdeinit_exec(const TQString &app, const TQStringList &args,
1140 const TQValueList<TQCString> &envs, TQCString startup_id, bool wait)
1141{
1142 TDELaunchRequest *request = new TDELaunchRequest;
1143 request->autoStart = false;
1144
1145 for(TQStringList::ConstIterator it = args.begin();
1146 it != args.end();
1147 it++)
1148 {
1149 TQString arg = *it;
1150 request->arg_list.append(arg.local8Bit());
1151 }
1152
1153 request->name = app.local8Bit();
1154
1155 if (wait)
1156 request->dcop_service_type = KService::DCOP_Wait;
1157 else
1158 request->dcop_service_type = KService::DCOP_None;
1159 request->dcop_name = 0;
1160 request->pid = 0;
1161#ifdef TQ_WS_X11
1162 request->startup_id = startup_id;
1163#endif
1164 request->envs = envs;
1165 if( app != "tdebuildsycoca" ) // avoid stupid loop
1166 {
1167 // Find service, if any - strip path if needed
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 >());
1172 else // no .desktop file, no startup info
1173 cancel_service_startup_info( request, startup_id, envs );
1174 }
1175 request->transaction = dcopClient()->beginTransaction();
1176 queueRequest(request);
1177 return true;
1178}
1179
1180void
1181TDELauncher::queueRequest(TDELaunchRequest *request)
1182{
1183 requestQueue.append( request );
1184 if (!bProcessingQueue)
1185 {
1186 bProcessingQueue = true;
1187 TQTimer::singleShot(0, this, TQ_SLOT( slotDequeue() ));
1188 }
1189}
1190
1191void
1192TDELauncher::slotDequeue()
1193{
1194 do {
1195 TDELaunchRequest *request = requestQueue.take(0);
1196 // process request
1197 request->status = TDELaunchRequest::Launching;
1198 requestStart(request);
1199 if (request->status != TDELaunchRequest::Launching)
1200 {
1201 // Request handled.
1202 requestDone( request );
1203 continue;
1204 }
1205 } while(requestQueue.count());
1206 bProcessingQueue = false;
1207}
1208
1209void
1210TDELauncher::createArgs( TDELaunchRequest *request, const KService::Ptr service ,
1211 const TQStringList &urls)
1212{
1213 TQStringList params = KRun::processDesktopExec(*service, urls, false);
1214
1215 for(TQStringList::ConstIterator it = params.begin();
1216 it != params.end(); ++it)
1217 {
1218 request->arg_list.append((*it).local8Bit());
1219 }
1220 request->cwd = TQFile::encodeName(service->path());
1221}
1222
1224
1225pid_t
1226TDELauncher::requestHoldSlave(const KURL &url, const TQString &app_socket)
1227{
1228 IdleSlave *slave;
1229 for(slave = mSlaveList.first(); slave; slave = mSlaveList.next())
1230 {
1231 if (slave->onHold(url))
1232 break;
1233 }
1234 if (slave)
1235 {
1236 mSlaveList.removeRef(slave);
1237 slave->connect(app_socket);
1238 return slave->pid();
1239 }
1240 return 0;
1241}
1242
1243
1244pid_t
1245TDELauncher::requestSlave(const TQString &protocol,
1246 const TQString &host,
1247 const TQString &app_socket,
1248 TQString &error)
1249{
1250 IdleSlave *slave;
1251 for(slave = mSlaveList.first(); slave; slave = mSlaveList.next())
1252 {
1253 if (slave->match(protocol, host, true))
1254 break;
1255 }
1256 if (!slave)
1257 {
1258 for(slave = mSlaveList.first(); slave; slave = mSlaveList.next())
1259 {
1260 if (slave->match(protocol, host, false))
1261 break;
1262 }
1263 }
1264 if (!slave)
1265 {
1266 for(slave = mSlaveList.first(); slave; slave = mSlaveList.next())
1267 {
1268 if (slave->match(protocol, TQString::null, false))
1269 break;
1270 }
1271 }
1272 if (slave)
1273 {
1274 mSlaveList.removeRef(slave);
1275 slave->connect(app_socket);
1276 return slave->pid();
1277 }
1278
1279 TQString _name = KProtocolInfo::exec(protocol);
1280 if (_name.isEmpty())
1281 {
1282 error = i18n("Unknown protocol '%1'.\n").arg(protocol);
1283 return 0;
1284 }
1285
1286 TQCString name = _name.latin1(); // ex: "tdeio_ftp"
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);
1294
1295// kdDebug(7016) << "TDELauncher: launching new slave " << _name << " with protocol=" << protocol << endl;
1296 if (mSlaveDebug == arg1)
1297 {
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));
1302 }
1303 if (mSlaveValgrind == arg1)
1304 {
1305 arg_list.prepend(TQFile::encodeName(KLibLoader::findLibrary(name)));
1306 arg_list.prepend(TQFile::encodeName(locate("exe", "tdeioslave")));
1307 name = "valgrind";
1308 if (!mSlaveValgrindSkin.isEmpty()) {
1309 arg_list.prepend(TQCString("--tool=") + mSlaveValgrindSkin);
1310 } else
1311 arg_list.prepend("--tool=memcheck");
1312 }
1313
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;
1320 request->pid = 0;
1321#ifdef TQ_WS_X11
1322 request->startup_id = "0";
1323#endif
1324 request->status = TDELaunchRequest::Launching;
1325 request->transaction = 0; // No confirmation is send
1326 requestStart(request);
1327 pid_t pid = request->pid;
1328
1329// kdDebug(7016) << "Slave launched, pid = " << pid << endl;
1330
1331 // We don't care about this request any longer....
1332 requestDone(request);
1333 if (!pid)
1334 {
1335 error = i18n("Error loading '%1'.\n").arg(TQString(name));
1336 }
1337 return pid;
1338}
1339
1340void
1341TDELauncher::waitForSlave(pid_t pid)
1342{
1343 IdleSlave *slave;
1344 for(slave = mSlaveList.first(); slave; slave = mSlaveList.next())
1345 {
1346 if (slave->pid() == pid)
1347 return; // Already here.
1348 }
1349 SlaveWaitRequest *waitRequest = new SlaveWaitRequest;
1350 waitRequest->transaction = dcopClient()->beginTransaction();
1351 waitRequest->pid = pid;
1352 mSlaveWaitRequest.append(waitRequest);
1353}
1354
1355void
1356TDELauncher::acceptSlave(TDESocket *slaveSocket)
1357{
1358 IdleSlave *slave = new IdleSlave(slaveSocket);
1359 // Send it a SLAVE_STATUS command.
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())
1365 {
1366 mTimer.start(1000*10);
1367 }
1368}
1369
1370void
1371TDELauncher::slotSlaveStatus(IdleSlave *slave)
1372{
1373 SlaveWaitRequest *waitRequest = mSlaveWaitRequest.first();
1374 while(waitRequest)
1375 {
1376 if (waitRequest->pid == slave->pid())
1377 {
1378 TQByteArray replyData;
1379 TQCString replyType;
1380 replyType = "void";
1381 dcopClient()->endTransaction( waitRequest->transaction, replyType, replyData);
1382 mSlaveWaitRequest.removeRef(waitRequest);
1383 waitRequest = mSlaveWaitRequest.current();
1384 }
1385 else
1386 {
1387 waitRequest = mSlaveWaitRequest.next();
1388 }
1389 }
1390}
1391
1392void
1393TDELauncher::slotSlaveGone()
1394{
1395 IdleSlave *slave = (IdleSlave *) sender();
1396 mSlaveList.removeRef(slave);
1397 if ((mSlaveList.count() == 0) && (mTimer.isActive()))
1398 {
1399 mTimer.stop();
1400 }
1401}
1402
1403void
1404TDELauncher::idleTimeout()
1405{
1406 bool keepOneFileSlave=true;
1407 time_t now = time(0);
1408 IdleSlave *slave;
1409 for(slave = mSlaveList.first(); slave; slave = mSlaveList.next())
1410 {
1411 if ((slave->protocol()=="file") && (keepOneFileSlave))
1412 keepOneFileSlave=false;
1413 else if (slave->age(now) > SLAVE_MAX_IDLE)
1414 {
1415 // killing idle slave
1416 delete slave;
1417 }
1418 }
1419}
1420
1421#include "tdelauncher.moc"

tdeinit

Skip menu "tdeinit"
  • Main Page
  • File List
  • Related Pages

tdeinit

Skip menu "tdeinit"
  • arts
  • dcop
  • dnssd
  • interfaces
  •   kspeech
  •     interface
  •     library
  •   tdetexteditor
  • kate
  • kded
  • kdoctools
  • kimgio
  • kjs
  • libtdemid
  • libtdescreensaver
  • tdeabc
  • tdecmshell
  • tdecore
  • tdefx
  • tdehtml
  • tdeinit
  • tdeio
  •   bookmarks
  •   httpfilter
  •   kpasswdserver
  •   kssl
  •   tdefile
  •   tdeio
  •   tdeioexec
  • tdeioslave
  •   http
  • tdemdi
  •   tdemdi
  • tdenewstuff
  • tdeparts
  • tdeprint
  • tderandr
  • tderesources
  • tdespell2
  • tdesu
  • tdeui
  • tdeunittest
  • tdeutils
  • tdewallet
Generated for tdeinit by doxygen 1.9.4
This website is maintained by Timothy Pearson.