• 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 <kstandarddirs.h>
40 #include <tdetempfile.h>
41 #include <kurl.h>
42 
43 #if defined Q_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 Q_WS_X11 && ! defined K_WS_QTONLY
56 #ifdef Q_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 
64 using namespace TDEIO;
65 
66 template class TQPtrList<TDELaunchRequest>;
67 template class TQPtrList<IdleSlave>;
68 
69 IdleSlave::IdleSlave(TDESocket *socket)
70 {
71  mConn.init(socket);
72  mConn.connect(this, TQT_SLOT(gotInput()));
73  mConn.send( CMD_SLAVE_STATUS );
74  mPid = 0;
75  mBirthDate = time(0);
76  mOnHold = false;
77 }
78 
79 void
80 IdleSlave::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 
124 void
125 IdleSlave::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 
134 void
135 IdleSlave::reparseConfiguration()
136 {
137  mConn.send( CMD_REPARSECONFIGURATION );
138 }
139 
140 bool
141 IdleSlave::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 
152 bool
153 IdleSlave::onHold(const KURL &url)
154 {
155  if (!mOnHold) return false;
156  return (url == mUrl);
157 }
158 
159 int
160 IdleSlave::age(time_t now)
161 {
162  return (int) difftime(now, mBirthDate);
163 }
164 
165 TDELauncher::TDELauncher(int _tdeinitSocket, bool new_startup)
166 // : TDEApplication( false, false ), // No Styles, No GUI
167  : TDEApplication( false, true ), // TQClipboard tries to construct a QWidget 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 Q_WS_X11
173  mCached_dpy = NULL;
174 #endif
175  connect(&mAutoTimer, TQT_SIGNAL(timeout()), this, TQT_SLOT(slotAutoStart()));
176  requestList.setAutoDelete(true);
177  mSlaveWaitRequest.setAutoDelete(true);
178  dcopClient()->setNotifications( true );
179  connect(dcopClient(), TQT_SIGNAL( applicationRegistered( const TQCString &)),
180  this, TQT_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, TQT_SIGNAL(accepted( TDESocket *)),
199  TQT_SLOT(acceptSlave(TDESocket *)));
200 
201  connect(&mTimer, TQT_SIGNAL(timeout()), TQT_SLOT(idleTimeout()));
202 
203  tdeinitNotifier = new TQSocketNotifier(tdeinitSocket, TQSocketNotifier::Read);
204  connect(tdeinitNotifier, TQT_SIGNAL( activated( int )),
205  this, TQT_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 
227 TDELauncher::~TDELauncher()
228 {
229  close();
230 }
231 
232 void TDELauncher::close()
233 {
234  if (!mPoolSocketName.isEmpty())
235  {
236  TQCString filename = TQFile::encodeName(mPoolSocketName);
237  unlink(filename.data());
238  }
239 #if defined Q_WS_X11 && ! defined K_WS_QTONLY
240 //#ifdef Q_WS_X11
241  if( mCached_dpy != NULL )
242  XCloseDisplay( mCached_dpy );
243 #endif
244 }
245 
246 void
247 TDELauncher::destruct(int exit_code)
248 {
249  if (kapp) ((TDELauncher*)kapp)->close();
250  // We don't delete kapp here, that's intentional.
251  ::exit(exit_code);
252 }
253 
254 bool
255 TDELauncher::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 
445 QCStringList
446 TDELauncher::interfaces()
447 {
448  QCStringList ifaces = DCOPObject::interfaces();
449  ifaces += "TDELauncher";
450  return ifaces;
451 }
452 
453 QCStringList
454 TDELauncher::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 
483 void 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  */
502 static int
503 read_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 
524 void
525 TDELauncher::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 
613 void
614 TDELauncher::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 
634 void
635 TDELauncher::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 
673 void
674 TDELauncher::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 
692 void
693 TDELauncher::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 
729 void
730 TDELauncher::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 Q_WS_X11 && ! defined K_WS_QTONLY
750 //#ifdef Q_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 
790 void
791 TDELauncher::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 Q_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 Q_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 Q_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 
881 void
882 TDELauncher::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 
909 bool
910 TDELauncher::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 
926 bool
927 TDELauncher::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 
951 bool
952 TDELauncher::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 
968 bool
969 TDELauncher::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 
1049 void
1050 TDELauncher::send_service_startup_info( TDELaunchRequest *request, KService::Ptr service, const TQCString& startup_id,
1051  const TQValueList<TQCString> &envs )
1052 {
1053 #if defined Q_WS_X11 && ! defined K_WS_QTONLY
1054 //#ifdef Q_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 
1104 void
1105 TDELauncher::cancel_service_startup_info( TDELaunchRequest* request, const TQCString& startup_id,
1106  const TQValueList<TQCString> &envs )
1107 {
1108 #if defined Q_WS_X11 && ! defined K_WS_QTONLY
1109 //#ifdef Q_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 
1138 bool
1139 TDELauncher::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 Q_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 
1180 void
1181 TDELauncher::queueRequest(TDELaunchRequest *request)
1182 {
1183  requestQueue.append( request );
1184  if (!bProcessingQueue)
1185  {
1186  bProcessingQueue = true;
1187  TQTimer::singleShot(0, this, TQT_SLOT( slotDequeue() ));
1188  }
1189 }
1190 
1191 void
1192 TDELauncher::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 
1209 void
1210 TDELauncher::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 
1225 pid_t
1226 TDELauncher::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 
1244 pid_t
1245 TDELauncher::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 Q_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 
1340 void
1341 TDELauncher::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 
1355 void
1356 TDELauncher::acceptSlave(TDESocket *slaveSocket)
1357 {
1358  IdleSlave *slave = new IdleSlave(slaveSocket);
1359  // Send it a SLAVE_STATUS command.
1360  mSlaveList.append(slave);
1361  connect(slave, TQT_SIGNAL(destroyed()), this, TQT_SLOT(slotSlaveGone()));
1362  connect(slave, TQT_SIGNAL(statusUpdate(IdleSlave *)),
1363  this, TQT_SLOT(slotSlaveStatus(IdleSlave *)));
1364  if (!mTimer.isActive())
1365  {
1366  mTimer.start(1000*10);
1367  }
1368 }
1369 
1370 void
1371 TDELauncher::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 
1392 void
1393 TDELauncher::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 
1403 void
1404 TDELauncher::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"
TDEIO

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
  •     tdecore
  • tdeabc
  • tdecmshell
  • tdecore
  • tdefx
  • tdehtml
  • tdeinit
  • tdeio
  •   bookmarks
  •   httpfilter
  •   kpasswdserver
  •   kssl
  • tdeioslave
  •   http
  •   tdefile
  •   tdeio
  •   tdeioexec
  • tdemdi
  •   tdemdi
  • tdenewstuff
  • tdeparts
  • tdeprint
  • tderandr
  • tderesources
  • tdespell2
  • tdesu
  • tdeui
  • tdeunittest
  • tdeutils
  • tdewallet
Generated for tdeinit by doxygen 1.8.8
This website is maintained by Timothy Pearson.