• Skip to content
  • Skip to link menu
KDE API Reference
  • KDE API Reference
  • kdelibs API Reference
  • KDE Home
  • Contact Us
 

KInit

  • sources
  • kde-4.12
  • kdelibs
  • kinit
klauncher.cpp
Go to the documentation of this file.
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 
20 #define QT_NO_CAST_FROM_ASCII
21 
22 #include "klauncher.h"
23 #include "klauncher_cmds.h"
24 #include "klauncher_adaptor.h"
25 
26 #include <config.h>
27 
28 #include <stdio.h>
29 #include <unistd.h>
30 #include <stdlib.h>
31 #include <errno.h>
32 #include <signal.h>
33 #include <sys/time.h>
34 
35 #ifdef Q_WS_X11
36 #include <kstartupinfo.h>
37 #include <X11/Xlib.h>
38 #endif
39 
40 #include <QtCore/QFile>
41 #include <qplatformdefs.h>
42 
43 #include <kconfig.h>
44 #include <kdebug.h>
45 #include <kde_file.h>
46 #include <klibrary.h>
47 #include <klocale.h>
48 #include <kprotocolmanager.h>
49 #include <kprotocolinfo.h>
50 #include <krun.h>
51 #include <kstandarddirs.h>
52 #include <ktemporaryfile.h>
53 #include <kdesktopfile.h>
54 #include <kurl.h>
55 
56 #include <kio/global.h>
57 #include <kio/connection.h>
58 #include <kio/slaveinterface.h>
59 
60 // Dispose slaves after being idle for SLAVE_MAX_IDLE seconds
61 #define SLAVE_MAX_IDLE 30
62 
63 // #define KLAUNCHER_VERBOSE_OUTPUT
64 
65 static const char* const s_DBusStartupTypeToString[] =
66  { "DBusNone", "DBusUnique", "DBusMulti", "DBusWait", "ERROR" };
67 
68 using namespace KIO;
69 
70 IdleSlave::IdleSlave(QObject *parent)
71  : QObject(parent)
72 {
73  QObject::connect(&mConn, SIGNAL(readyRead()), this, SLOT(gotInput()));
74  // Send it a SLAVE_STATUS command.
75  mConn.send( CMD_SLAVE_STATUS );
76  mPid = 0;
77  mBirthDate = time(0);
78  mOnHold = false;
79 }
80 
81 template<int T> struct PIDType { typedef pid_t PID_t; } ;
82 template<> struct PIDType<2> { typedef qint16 PID_t; } ;
83 template<> struct PIDType<4> { typedef qint32 PID_t; } ;
84 
85 void
86 IdleSlave::gotInput()
87 {
88  int cmd;
89  QByteArray data;
90  if (mConn.read( &cmd, data) == -1)
91  {
92  // Communication problem with slave.
93  //kError(7016) << "SlavePool: No communication with slave." << endl;
94  deleteLater();
95  }
96  else if (cmd == MSG_SLAVE_ACK)
97  {
98  deleteLater();
99  }
100  else if (cmd != MSG_SLAVE_STATUS)
101  {
102  kError(7016) << "SlavePool: Unexpected data from slave." << endl;
103  deleteLater();
104  }
105  else
106  {
107  QDataStream stream( data );
108  PIDType<sizeof(pid_t)>::PID_t stream_pid;
109  pid_t pid;
110  QByteArray protocol;
111  QString host;
112  qint8 b;
113  stream >> stream_pid >> protocol >> host >> b;
114  pid = stream_pid;
115 // Overload with (bool) onHold, (KUrl) url.
116  if (!stream.atEnd())
117  {
118  KUrl url;
119  stream >> url;
120  mOnHold = true;
121  mUrl = url;
122  }
123 
124  mPid = pid;
125  mConnected = (b != 0);
126  mProtocol = QString::fromLatin1(protocol);
127  mHost = host;
128  emit statusUpdate(this);
129  }
130 }
131 
132 void
133 IdleSlave::connect(const QString &app_socket)
134 {
135  QByteArray data;
136  QDataStream stream( &data, QIODevice::WriteOnly);
137  stream << app_socket;
138  mConn.send( CMD_SLAVE_CONNECT, data );
139  // Timeout!
140 }
141 
142 void
143 IdleSlave::reparseConfiguration()
144 {
145  mConn.send( CMD_REPARSECONFIGURATION );
146 }
147 
148 bool
149 IdleSlave::match(const QString &protocol, const QString &host, bool needConnected) const
150 {
151  if (mOnHold || protocol != mProtocol) {
152  return false;
153  }
154  if (host.isEmpty()) {
155  return true;
156  }
157  return (host == mHost) && (!needConnected || mConnected);
158 }
159 
160 bool
161 IdleSlave::onHold(const KUrl &url) const
162 {
163  if (!mOnHold) return false;
164  return (url == mUrl);
165 }
166 
167 int
168 IdleSlave::age(time_t now) const
169 {
170  return (int) difftime(now, mBirthDate);
171 }
172 
173 static KLauncher* g_klauncher_self;
174 
175 
176 // From qcore_unix_p.h. We could also port to QLocalSocket :)
177 #define K_EINTR_LOOP(var, cmd) \
178  do { \
179  var = cmd; \
180  } while (var == -1 && errno == EINTR)
181 
182 ssize_t kde_safe_write(int fd, const void *buf, size_t count)
183 {
184  ssize_t ret = 0;
185  K_EINTR_LOOP(ret, QT_WRITE(fd, buf, count));
186  if (ret < 0)
187  qWarning() << "write failed:" << strerror(errno);
188  return ret;
189 }
190 
191 #ifndef USE_KPROCESS_FOR_KIOSLAVES
192 KLauncher::KLauncher(int _kdeinitSocket)
193  : QObject(0),
194  kdeinitSocket(_kdeinitSocket)
195 #else
196 KLauncher::KLauncher()
197  : QObject(0)
198 #endif
199 {
200 #ifdef Q_WS_X11
201  mCached_dpy = NULL;
202 #endif
203  Q_ASSERT( g_klauncher_self == NULL );
204  g_klauncher_self = this;
205 
206  mAutoTimer.setSingleShot(true);
207  new KLauncherAdaptor(this);
208  QDBusConnection::sessionBus().registerObject(QLatin1String("/KLauncher"), this); // same as ktoolinvocation.cpp
209 
210  connect(&mAutoTimer, SIGNAL(timeout()), this, SLOT(slotAutoStart()));
211  connect(QDBusConnection::sessionBus().interface(),
212  SIGNAL(serviceOwnerChanged(QString,QString,QString)),
213  SLOT(slotNameOwnerChanged(QString,QString,QString)));
214 
215  mConnectionServer.listenForRemote();
216  connect(&mConnectionServer, SIGNAL(newConnection()), SLOT(acceptSlave()));
217  if (!mConnectionServer.isListening())
218  {
219  // Severe error!
220  qDebug("KLauncher: Fatal error, can't create tempfile!");
221  ::_exit(1);
222  }
223 
224  connect(&mTimer, SIGNAL(timeout()), SLOT(idleTimeout()));
225 
226 #ifndef USE_KPROCESS_FOR_KIOSLAVES
227  kdeinitNotifier = new QSocketNotifier(kdeinitSocket, QSocketNotifier::Read);
228  connect(kdeinitNotifier, SIGNAL(activated(int)),
229  this, SLOT(slotKDEInitData(int)));
230  kdeinitNotifier->setEnabled( true );
231 #endif
232  lastRequest = 0;
233  bProcessingQueue = false;
234 
235  mSlaveDebug = QString::fromLocal8Bit(qgetenv("KDE_SLAVE_DEBUG_WAIT"));
236  if (!mSlaveDebug.isEmpty())
237  {
238  qWarning("Klauncher running in slave-debug mode for slaves of protocol '%s'", qPrintable(mSlaveDebug));
239  }
240  mSlaveValgrind = QString::fromLocal8Bit(qgetenv("KDE_SLAVE_VALGRIND"));
241  if (!mSlaveValgrind.isEmpty())
242  {
243  mSlaveValgrindSkin = QString::fromLocal8Bit(qgetenv("KDE_SLAVE_VALGRIND_SKIN"));
244  qWarning("Klauncher running slaves through valgrind for slaves of protocol '%s'", qPrintable(mSlaveValgrind));
245  }
246 #ifdef USE_KPROCESS_FOR_KIOSLAVES
247  kDebug(7016) << "LAUNCHER_OK";
248 #else
249  klauncher_header request_header;
250  request_header.cmd = LAUNCHER_OK;
251  request_header.arg_length = 0;
252  kde_safe_write(kdeinitSocket, &request_header, sizeof(request_header));
253 #endif
254 }
255 
256 KLauncher::~KLauncher()
257 {
258  close();
259  g_klauncher_self = NULL;
260 }
261 
262 void KLauncher::close()
263 {
264 #ifdef Q_WS_X11
265  if( mCached_dpy != NULL )
266  {
267  XCloseDisplay( mCached_dpy );
268  mCached_dpy = NULL;
269  }
270 #endif
271 }
272 
273 void
274 KLauncher::destruct()
275 {
276  if (g_klauncher_self)
277  g_klauncher_self->close();
278  // We don't delete the app here, that's intentional.
279  ::_exit(255);
280 }
281 
282 void KLauncher::setLaunchEnv(const QString &name, const QString &value)
283 {
284 #ifndef USE_KPROCESS_FOR_KIOSLAVES
285  klauncher_header request_header;
286  QByteArray requestData;
287  requestData.append(name.toLocal8Bit()).append('\0').append(value.toLocal8Bit()).append('\0');
288  request_header.cmd = LAUNCHER_SETENV;
289  request_header.arg_length = requestData.size();
290  kde_safe_write(kdeinitSocket, &request_header, sizeof(request_header));
291  kde_safe_write(kdeinitSocket, requestData.data(), request_header.arg_length);
292 #else
293  Q_UNUSED(name);
294  Q_UNUSED(value);
295 #endif
296 }
297 
298 #ifndef USE_KPROCESS_FOR_KIOSLAVES
299 /*
300  * Read 'len' bytes from 'sock' into buffer.
301  * returns -1 on failure, 0 on no data.
302  */
303 static int
304 read_socket(int sock, char *buffer, int len)
305 {
306  ssize_t result;
307  int bytes_left = len;
308  while (bytes_left > 0) {
309  // in case we get a request to start an application and data arrive
310  // to kdeinitSocket at the same time, requestStart() will already
311  // call slotKDEInitData(), so we must check there's still something
312  // to read, otherwise this would block
313 
314  // Same thing if kdeinit dies without warning.
315 
316  fd_set in;
317  timeval tm = { 30, 0 }; // 30 seconds timeout, so we're not stuck in case kdeinit dies on us
318  FD_ZERO ( &in );
319  FD_SET( sock, &in );
320  select( sock + 1, &in, 0, 0, &tm );
321  if( !FD_ISSET( sock, &in )) {
322  kDebug(7016) << "read_socket" << sock << "nothing to read, kdeinit4 must be dead";
323  return -1;
324  }
325 
326  result = read(sock, buffer, bytes_left);
327  if (result > 0)
328  {
329  buffer += result;
330  bytes_left -= result;
331  }
332  else if (result == 0)
333  return -1;
334  else if ((result == -1) && (errno != EINTR))
335  return -1;
336  }
337  return 0;
338 }
339 #endif
340 
341 void
342 KLauncher::slotKDEInitData(int)
343 {
344 #ifndef USE_KPROCESS_FOR_KIOSLAVES
345  klauncher_header request_header;
346  QByteArray requestData;
347 
348  int result = read_socket(kdeinitSocket, (char *) &request_header,
349  sizeof( request_header));
350  if (result == -1)
351  {
352  kDebug(7016) << "Exiting on read_socket errno:" << errno;
353  KDE_signal( SIGHUP, SIG_IGN);
354  KDE_signal( SIGTERM, SIG_IGN);
355  destruct(); // Exit!
356  }
357  requestData.resize(request_header.arg_length);
358  result = read_socket(kdeinitSocket, (char *) requestData.data(),
359  request_header.arg_length);
360 
361  processRequestReturn(request_header.cmd,requestData);
362 #endif
363 }
364 
365 void KLauncher::processRequestReturn(int status, const QByteArray &requestData)
366 {
367  if (status == LAUNCHER_CHILD_DIED)
368  {
369  long *request_data;
370  request_data = (long *) requestData.data();
371  processDied(request_data[0], request_data[1]);
372  return;
373  }
374  if (lastRequest && (status == LAUNCHER_OK))
375  {
376  long *request_data;
377  request_data = (long *) requestData.data();
378  lastRequest->pid = (pid_t) (*request_data);
379  kDebug(7016).nospace() << lastRequest->name << " (pid " << lastRequest->pid <<
380  ") up and running.";
381  switch(lastRequest->dbus_startup_type)
382  {
383  case KService::DBusNone:
384  lastRequest->status = KLaunchRequest::Running;
385  break;
386  case KService::DBusUnique:
387  case KService::DBusWait:
388  case KService::DBusMulti:
389  lastRequest->status = KLaunchRequest::Launching;
390  break;
391  }
392  lastRequest = 0;
393  return;
394  }
395  if (lastRequest && (status == LAUNCHER_ERROR))
396  {
397  lastRequest->status = KLaunchRequest::Error;
398  kDebug(7016) << lastRequest->name << " failed." << endl;
399  if (!requestData.isEmpty())
400  lastRequest->errorMsg = QString::fromUtf8((char *) requestData.data());
401  lastRequest = 0;
402  return;
403  }
404 
405  kWarning(7016)<< "Unexpected request return" << (unsigned int) status;
406 }
407 
408 void
409 KLauncher::processDied(pid_t pid, long exitStatus)
410 {
411 #ifdef KLAUNCHER_VERBOSE_OUTPUT
412  kDebug(7016) << pid << "exitStatus=" << exitStatus;
413 #else
414  Q_UNUSED(exitStatus);
415  // We should probably check the exitStatus for the uniqueapp case?
416 #endif
417  foreach (KLaunchRequest *request, requestList)
418  {
419 #ifdef KLAUNCHER_VERBOSE_OUTPUT
420  kDebug(7016) << " had pending request" << request->pid;
421 #endif
422  if (request->pid == pid)
423  {
424  if (request->dbus_startup_type == KService::DBusWait)
425  request->status = KLaunchRequest::Done;
426  else if ((request->dbus_startup_type == KService::DBusUnique)
427  && QDBusConnection::sessionBus().interface()->isServiceRegistered(request->dbus_name)) {
428  request->status = KLaunchRequest::Running;
429 #ifdef KLAUNCHER_VERBOSE_OUTPUT
430  kDebug(7016) << pid << "running as a unique app";
431 #endif
432  } else {
433  request->status = KLaunchRequest::Error;
434 #ifdef KLAUNCHER_VERBOSE_OUTPUT
435  kDebug(7016) << pid << "died, requestDone. status=" << request->status;
436 #endif
437  }
438  requestDone(request);
439  return;
440  }
441  }
442 #ifdef KLAUNCHER_VERBOSE_OUTPUT
443  kDebug(7016) << "found no pending requests for PID" << pid;
444 #endif
445 }
446 
447 static bool matchesPendingRequest(const QString& appId, const QString& pendingAppId)
448 {
449  // appId just registered, e.g. org.koffice.kword-12345
450  // Let's see if this is what pendingAppId (e.g. org.koffice.kword or *.kword) was waiting for.
451 
452  const QString newAppId = appId.left(appId.lastIndexOf(QLatin1Char('-'))); // strip out the -12345 if present.
453 
454  //kDebug() << "appId=" << appId << "newAppId=" << newAppId << "pendingAppId=" << pendingAppId;
455 
456  if (pendingAppId.startsWith(QLatin1String("*."))) {
457  const QString pendingName = pendingAppId.mid(2);
458  const QString appName = newAppId.mid(newAppId.lastIndexOf(QLatin1Char('.'))+1);
459  //kDebug() << "appName=" << appName;
460  return appName == pendingName;
461  }
462 
463  return newAppId == pendingAppId;
464 }
465 
466 void
467 KLauncher::slotNameOwnerChanged(const QString &appId, const QString &oldOwner,
468  const QString &newOwner)
469 {
470  Q_UNUSED(oldOwner);
471  if (appId.isEmpty() || newOwner.isEmpty())
472  return;
473 
474 #ifdef KLAUNCHER_VERBOSE_OUTPUT
475  kDebug(7016) << "new app" << appId;
476 #endif
477  foreach (KLaunchRequest *request, requestList)
478  {
479  if (request->status != KLaunchRequest::Launching)
480  continue;
481 
482 #ifdef KLAUNCHER_VERBOSE_OUTPUT
483  kDebug(7016) << "had pending request" << request->name << s_DBusStartupTypeToString[request->dbus_startup_type] << "dbus_name" << request->dbus_name << request->tolerant_dbus_name;
484 #endif
485  // For unique services check the requested service name first
486  if (request->dbus_startup_type == KService::DBusUnique) {
487  if ((appId == request->dbus_name) || // just started
488  QDBusConnection::sessionBus().interface()->isServiceRegistered(request->dbus_name)) { // was already running
489  request->status = KLaunchRequest::Running;
490 #ifdef KLAUNCHER_VERBOSE_OUTPUT
491  kDebug(7016) << "OK, unique app" << request->dbus_name << "is running";
492 #endif
493  requestDone(request);
494  continue;
495  } else {
496 #ifdef KLAUNCHER_VERBOSE_OUTPUT
497  kDebug(7016) << "unique app" << request->dbus_name << "not running yet";
498 #endif
499  }
500  }
501 
502  const QString rAppId = !request->tolerant_dbus_name.isEmpty() ? request->tolerant_dbus_name : request->dbus_name;
503 #ifdef KLAUNCHER_VERBOSE_OUTPUT
504  //kDebug(7016) << "using" << rAppId << "for matching";
505 #endif
506  if (rAppId.isEmpty())
507  continue;
508 
509  if (matchesPendingRequest(appId, rAppId)) {
510 #ifdef KLAUNCHER_VERBOSE_OUTPUT
511  kDebug(7016) << "ok, request done";
512 #endif
513  request->dbus_name = appId;
514  request->status = KLaunchRequest::Running;
515  requestDone(request);
516  continue;
517  }
518  }
519 }
520 
521 void
522 KLauncher::autoStart(int phase)
523 {
524  if( mAutoStart.phase() >= phase )
525  return;
526  mAutoStart.setPhase(phase);
527  if (phase == 0)
528  mAutoStart.loadAutoStartList();
529  mAutoTimer.start(0);
530 }
531 
532 void
533 KLauncher::slotAutoStart()
534 {
535  KService::Ptr s;
536  do
537  {
538  QString service = mAutoStart.startService();
539  if (service.isEmpty())
540  {
541  // Done
542  if( !mAutoStart.phaseDone())
543  {
544  mAutoStart.setPhaseDone();
545  switch( mAutoStart.phase())
546  {
547  case 0:
548  emit autoStart0Done();
549  break;
550  case 1:
551  emit autoStart1Done();
552  break;
553  case 2:
554  emit autoStart2Done();
555  break;
556  }
557  }
558  return;
559  }
560  s = new KService(service);
561  }
562  while (!start_service(s, QStringList(), QStringList(), "0", false, true, QDBusMessage()));
563  // Loop till we find a service that we can start.
564 }
565 
566 void
567 KLauncher::requestDone(KLaunchRequest *request)
568 {
569  if ((request->status == KLaunchRequest::Running) ||
570  (request->status == KLaunchRequest::Done))
571  {
572  requestResult.result = 0;
573  requestResult.dbusName = request->dbus_name;
574  requestResult.error = QString::fromLatin1(""); // not null, cf assert further down
575  requestResult.pid = request->pid;
576  }
577  else
578  {
579  requestResult.result = 1;
580  requestResult.dbusName.clear();
581  requestResult.error = i18n("KDEInit could not launch '%1'", request->name);
582  if (!request->errorMsg.isEmpty())
583  requestResult.error += QString::fromLatin1(":\n") + request->errorMsg;
584  requestResult.pid = 0;
585 
586 #ifdef Q_WS_X11
587  if (!request->startup_dpy.isEmpty())
588  {
589  Display* dpy = NULL;
590  if( (mCached_dpy != NULL) &&
591  (request->startup_dpy == XDisplayString( mCached_dpy )))
592  dpy = mCached_dpy;
593  if( dpy == NULL )
594  dpy = XOpenDisplay(request->startup_dpy);
595  if( dpy )
596  {
597  KStartupInfoId id;
598  id.initId(request->startup_id);
599  KStartupInfo::sendFinishX( dpy, id );
600  if( mCached_dpy != dpy && mCached_dpy != NULL )
601  XCloseDisplay( mCached_dpy );
602  mCached_dpy = dpy;
603  }
604  }
605 #endif
606  }
607 
608  if (request->autoStart)
609  {
610  mAutoTimer.start(0);
611  }
612 
613  if (request->transaction.type() != QDBusMessage::InvalidMessage)
614  {
615  if ( requestResult.dbusName.isNull() ) // null strings can't be sent
616  requestResult.dbusName.clear();
617  Q_ASSERT( !requestResult.error.isNull() );
618  PIDType<sizeof(pid_t)>::PID_t stream_pid = requestResult.pid;
619  QDBusConnection::sessionBus().send(request->transaction.createReply(QVariantList() << requestResult.result
620  << requestResult.dbusName
621  << requestResult.error
622  << stream_pid));
623  }
624 #ifdef KLAUNCHER_VERBOSE_OUTPUT
625  kDebug(7016) << "removing done request" << request->name << "PID" << request->pid;
626 #endif
627 
628  requestList.removeAll( request );
629  delete request;
630 }
631 
632 static void appendLong(QByteArray &ba, long l)
633 {
634  const int sz = ba.size();
635  ba.resize(sz + sizeof(long));
636  memcpy(ba.data() + sz, &l, sizeof(long));
637 }
638 
639 void
640 KLauncher::requestStart(KLaunchRequest *request)
641 {
642 #ifdef USE_KPROCESS_FOR_KIOSLAVES
643  requestList.append( request );
644  lastRequest = request;
645 
646  KProcess *process = new KProcess;
647  process->setOutputChannelMode(KProcess::MergedChannels);
648  connect(process ,SIGNAL(readyReadStandardOutput()),this, SLOT(slotGotOutput()) );
649  connect(process ,SIGNAL(finished(int,QProcess::ExitStatus)),this, SLOT(slotFinished(int,QProcess::ExitStatus)) );
650  request->process = process;
651 
652 // process.setEnvironment(envlist);
653  QStringList args;
654  foreach (const QString &arg, request->arg_list)
655  args << arg;
656 
657  QString executable = request->name;
658 #ifdef Q_WS_MAC
659  const QString bundlepath = KStandardDirs::findExe(executable);
660  if (!bundlepath.isEmpty())
661  executable = bundlepath;
662 #endif
663  process->setProgram(executable,args);
664  process->start();
665 
666  if (!process->waitForStarted())
667  {
668  processRequestReturn(LAUNCHER_ERROR,"");
669  }
670  else
671  {
672  request->pid = process->pid();
673  QByteArray data((char *)&request->pid, sizeof(int));
674  processRequestReturn(LAUNCHER_OK,data);
675  }
676  return;
677 
678 #else
679  requestList.append( request );
680  // Send request to kdeinit.
681  klauncher_header request_header;
682  QByteArray requestData;
683  requestData.reserve(1024);
684 
685  appendLong(requestData, request->arg_list.count() + 1);
686  requestData.append(request->name.toLocal8Bit());
687  requestData.append('\0');
688  foreach (const QString &arg, request->arg_list)
689  requestData.append(arg.toLocal8Bit()).append('\0');
690  appendLong(requestData, request->envs.count());
691  foreach (const QString &env, request->envs)
692  requestData.append(env.toLocal8Bit()).append('\0');
693  appendLong(requestData, 0); // avoid_loops, always false here
694 #ifdef Q_WS_X11
695  bool startup_notify = !request->startup_id.isNull() && request->startup_id != "0";
696  if( startup_notify )
697  requestData.append(request->startup_id).append('\0');
698 #endif
699  if (!request->cwd.isEmpty())
700  requestData.append(QFile::encodeName(request->cwd)).append('\0');
701 
702 #ifdef Q_WS_X11
703  request_header.cmd = startup_notify ? LAUNCHER_EXT_EXEC : LAUNCHER_EXEC_NEW;
704 #else
705  request_header.cmd = LAUNCHER_EXEC_NEW;
706 #endif
707  request_header.arg_length = requestData.length();
708 
709 #ifdef KLAUNCHER_VERBOSE_OUTPUT
710  kDebug(7016) << "Asking kdeinit to start" << request->name << request->arg_list
711  << "cmd=" << commandToString(request_header.cmd);
712 #endif
713 
714  kde_safe_write(kdeinitSocket, &request_header, sizeof(request_header));
715  kde_safe_write(kdeinitSocket, requestData.data(), requestData.length());
716 
717  // Wait for pid to return.
718  lastRequest = request;
719  do {
720  slotKDEInitData( kdeinitSocket );
721  }
722  while (lastRequest != 0);
723 #endif
724 }
725 
726 void KLauncher::exec_blind(const QString &name, const QStringList &arg_list, const QStringList &envs, const QString &startup_id)
727 {
728  KLaunchRequest *request = new KLaunchRequest;
729  request->autoStart = false;
730  request->name = name;
731  request->arg_list = arg_list;
732  request->dbus_startup_type = KService::DBusNone;
733  request->pid = 0;
734  request->status = KLaunchRequest::Launching;
735  request->envs = envs;
736  // Find service, if any - strip path if needed
737  KService::Ptr service = KService::serviceByDesktopName( name.mid( name.lastIndexOf(QLatin1Char('/')) + 1 ));
738  if (service)
739  send_service_startup_info(request, service, startup_id.toLocal8Bit(), QStringList());
740  else // no .desktop file, no startup info
741  cancel_service_startup_info( request, startup_id.toLocal8Bit(), envs );
742 
743  requestStart(request);
744  // We don't care about this request any longer....
745  requestDone(request);
746 }
747 
748 
749 // KDE5: remove
750 bool
751 KLauncher::start_service_by_name(const QString &serviceName, const QStringList &urls,
752  const QStringList &envs, const QString& startup_id, bool blind, const QDBusMessage &msg)
753 {
754  KService::Ptr service;
755  // Find service
756 #ifndef KDE_NO_DEPRECATED
757  service = KService::serviceByName(serviceName);
758 #endif
759  if (!service)
760  {
761  requestResult.result = ENOENT;
762  requestResult.error = i18n("Could not find service '%1'.", serviceName);
763  cancel_service_startup_info( NULL, startup_id.toLocal8Bit(), envs ); // cancel it if any
764  return false;
765  }
766  return start_service(service, urls, envs, startup_id.toLocal8Bit(), blind, false, msg);
767 }
768 
769 bool
770 KLauncher::start_service_by_desktop_path(const QString &serviceName, const QStringList &urls,
771  const QStringList &envs, const QString& startup_id, bool blind, const QDBusMessage &msg)
772 {
773  KService::Ptr service;
774  // Find service
775  const QFileInfo fi(serviceName);
776  if (fi.isAbsolute() && fi.exists())
777  {
778  // Full path
779  service = new KService(serviceName);
780  }
781  else
782  {
783  service = KService::serviceByDesktopPath(serviceName);
784  // TODO?
785  //if (!service)
786  // service = KService::serviceByStorageId(serviceName); // This method should be named start_service_by_storage_id ideally...
787  }
788  if (!service)
789  {
790  requestResult.result = ENOENT;
791  requestResult.error = i18n("Could not find service '%1'.", serviceName);
792  cancel_service_startup_info( NULL, startup_id.toLocal8Bit(), envs ); // cancel it if any
793  return false;
794  }
795  return start_service(service, urls, envs, startup_id.toLocal8Bit(), blind, false, msg);
796 }
797 
798 bool
799 KLauncher::start_service_by_desktop_name(const QString &serviceName, const QStringList &urls,
800  const QStringList &envs, const QString& startup_id, bool blind, const QDBusMessage &msg)
801 {
802  KService::Ptr service = KService::serviceByDesktopName(serviceName);
803  if (!service)
804  {
805  requestResult.result = ENOENT;
806  requestResult.error = i18n("Could not find service '%1'.", serviceName);
807  cancel_service_startup_info( NULL, startup_id.toLocal8Bit(), envs ); // cancel it if any
808  return false;
809  }
810  return start_service(service, urls, envs, startup_id.toLocal8Bit(), blind, false, msg);
811 }
812 
813 bool
814 KLauncher::start_service(KService::Ptr service, const QStringList &_urls,
815  const QStringList &envs, const QByteArray &startup_id,
816  bool blind, bool autoStart, const QDBusMessage &msg)
817 {
818  QStringList urls = _urls;
819  bool runPermitted = KDesktopFile::isAuthorizedDesktopFile(service->entryPath());
820 
821  if (!service->isValid() || !runPermitted)
822  {
823  requestResult.result = ENOEXEC;
824  if (service->isValid())
825  requestResult.error = i18n("Service '%1' must be executable to run.", service->entryPath());
826  else
827  requestResult.error = i18n("Service '%1' is malformatted.", service->entryPath());
828  cancel_service_startup_info( NULL, startup_id, envs ); // cancel it if any
829  return false;
830  }
831  KLaunchRequest *request = new KLaunchRequest;
832  request->autoStart = autoStart;
833 
834  if ((urls.count() > 1) && !service->allowMultipleFiles())
835  {
836  // We need to launch the application N times. That sucks.
837  // We ignore the result for application 2 to N.
838  // For the first file we launch the application in the
839  // usual way. The reported result is based on this
840  // application.
841  QStringList::ConstIterator it = urls.constBegin();
842  for(++it;
843  it != urls.constEnd();
844  ++it)
845  {
846  QStringList singleUrl;
847  singleUrl.append(*it);
848  QByteArray startup_id2 = startup_id;
849  if( !startup_id2.isEmpty() && startup_id2 != "0" )
850  startup_id2 = "0"; // can't use the same startup_id several times // krazy:exclude=doublequote_chars
851  start_service( service, singleUrl, envs, startup_id2, true, false, msg);
852  }
853  QString firstURL = *(urls.begin());
854  urls.clear();
855  urls.append(firstURL);
856  }
857  createArgs(request, service, urls);
858 
859  // We must have one argument at least!
860  if (!request->arg_list.count())
861  {
862  requestResult.result = ENOEXEC;
863  requestResult.error = i18n("Service '%1' is malformatted.", service->entryPath());
864  delete request;
865  cancel_service_startup_info( NULL, startup_id, envs );
866  return false;
867  }
868 
869  request->name = request->arg_list.takeFirst();
870 
871  if (request->name.endsWith(QLatin1String("/kioexec"))) {
872  // Special case for kioexec; if createArgs said we were going to use it,
873  // then we have to expect a kioexec-PID, not a org.kde.finalapp...
874  // Testcase: konqueror www.kde.org, RMB on link, open with, kruler.
875 
876  request->dbus_startup_type = KService::DBusMulti;
877  request->dbus_name = QString::fromLatin1("org.kde.kioexec");
878  } else {
879  request->dbus_startup_type = service->dbusStartupType();
880 
881  if ((request->dbus_startup_type == KService::DBusUnique) ||
882  (request->dbus_startup_type == KService::DBusMulti)) {
883  const QVariant v = service->property(QLatin1String("X-DBUS-ServiceName"));
884  if (v.isValid()) {
885  request->dbus_name = v.toString();
886  }
887  if (request->dbus_name.isEmpty()) {
888  const QString binName = KRun::binaryName(service->exec(), true);
889  request->dbus_name = QString::fromLatin1("org.kde.") + binName;
890  request->tolerant_dbus_name = QString::fromLatin1("*.") + binName;
891  }
892  }
893  }
894 
895 #ifdef KLAUNCHER_VERBOSE_OUTPUT
896  kDebug(7016) << "name=" << request->name << "dbus_name=" << request->dbus_name
897  << "startup type=" << s_DBusStartupTypeToString[request->dbus_startup_type];
898 #endif
899 
900  request->pid = 0;
901  request->envs = envs;
902  send_service_startup_info( request, service, startup_id, envs );
903 
904  // Request will be handled later.
905  if (!blind && !autoStart)
906  {
907  msg.setDelayedReply(true);
908  request->transaction = msg;
909  }
910  queueRequest(request);
911  return true;
912 }
913 
914 void
915 KLauncher::send_service_startup_info( KLaunchRequest *request, KService::Ptr service, const QByteArray& startup_id,
916  const QStringList &envs )
917 {
918 #ifdef Q_WS_X11
919  request->startup_id = "0";// krazy:exclude=doublequote_chars
920  if (startup_id == "0")
921  return;
922  bool silent;
923  QByteArray wmclass;
924  if( !KRun::checkStartupNotify( QString(), service.data(), &silent, &wmclass ))
925  return;
926  KStartupInfoId id;
927  id.initId(startup_id);
928  QByteArray dpy_str;
929  foreach (const QString &env, envs) {
930  if (env.startsWith(QLatin1String("DISPLAY=")))
931  dpy_str = env.mid(8).toLocal8Bit();
932  }
933  Display* dpy = NULL;
934  if (!dpy_str.isEmpty() && mCached_dpy != NULL && dpy_str != XDisplayString(mCached_dpy))
935  dpy = mCached_dpy;
936  if (dpy == NULL)
937  dpy = XOpenDisplay(dpy_str);
938  request->startup_id = id.id();
939  if (dpy == NULL) {
940  cancel_service_startup_info( request, startup_id, envs );
941  return;
942  }
943 
944  request->startup_dpy = dpy_str;
945 
946  KStartupInfoData data;
947  data.setName( service->name());
948  data.setIcon( service->icon());
949  data.setDescription( i18n( "Launching %1" , service->name()));
950  if( !wmclass.isEmpty())
951  data.setWMClass( wmclass );
952  if( silent )
953  data.setSilent( KStartupInfoData::Yes );
954  data.setApplicationId( service->entryPath());
955  // the rest will be sent by kdeinit
956  KStartupInfo::sendStartupX( dpy, id, data );
957  if( mCached_dpy != dpy && mCached_dpy != NULL )
958  XCloseDisplay( mCached_dpy );
959  mCached_dpy = dpy;
960  return;
961 #else
962  return;
963 #endif
964 }
965 
966 void
967 KLauncher::cancel_service_startup_info( KLaunchRequest* request, const QByteArray& startup_id,
968  const QStringList &envs )
969 {
970 #ifdef Q_WS_X11
971  if( request != NULL )
972  request->startup_id = "0"; // krazy:exclude=doublequote_chars
973  if( !startup_id.isEmpty() && startup_id != "0" )
974  {
975  QString dpy_str;
976  foreach (const QString &env, envs) {
977  if (env.startsWith(QLatin1String("DISPLAY=")))
978  dpy_str = env.mid(8);
979  }
980  Display* dpy = NULL;
981  if( !dpy_str.isEmpty() && mCached_dpy != NULL
982  && dpy_str != QLatin1String(XDisplayString( mCached_dpy )) )
983  dpy = mCached_dpy;
984  if( dpy == NULL )
985  dpy = XOpenDisplay( dpy_str.toLatin1().constData() );
986  if( dpy == NULL )
987  return;
988  KStartupInfoId id;
989  id.initId(startup_id);
990  KStartupInfo::sendFinishX( dpy, id );
991  if( mCached_dpy != dpy && mCached_dpy != NULL )
992  XCloseDisplay( mCached_dpy );
993  mCached_dpy = dpy;
994  }
995 #endif
996 }
997 
998 bool
999 KLauncher::kdeinit_exec(const QString &app, const QStringList &args,
1000  const QString& workdir, const QStringList &envs,
1001  const QString &startup_id, bool wait, const QDBusMessage &msg)
1002 {
1003  KLaunchRequest *request = new KLaunchRequest;
1004  request->autoStart = false;
1005  request->arg_list = args;
1006  request->name = app;
1007  if (wait)
1008  request->dbus_startup_type = KService::DBusWait;
1009  else
1010  request->dbus_startup_type = KService::DBusNone;
1011  request->pid = 0;
1012 #ifdef Q_WS_X11
1013  request->startup_id = startup_id.toLocal8Bit();
1014 #endif
1015  request->envs = envs;
1016  request->cwd = workdir;
1017 #ifdef Q_WS_X11
1018  if (!app.endsWith(QLatin1String("kbuildsycoca4"))) { // avoid stupid loop
1019  // Find service, if any - strip path if needed
1020  const QString desktopName = app.mid(app.lastIndexOf(QLatin1Char('/')) + 1);
1021  KService::Ptr service = KService::serviceByDesktopName(desktopName);
1022  if (service)
1023  send_service_startup_info(request, service,
1024  request->startup_id, envs);
1025  else // no .desktop file, no startup info
1026  cancel_service_startup_info(request, request->startup_id, envs);
1027  }
1028 #endif
1029  msg.setDelayedReply(true);
1030  request->transaction = msg;
1031  queueRequest(request);
1032  return true;
1033 }
1034 
1035 void
1036 KLauncher::queueRequest(KLaunchRequest *request)
1037 {
1038  requestQueue.append( request );
1039  if (!bProcessingQueue)
1040  {
1041  bProcessingQueue = true;
1042  QTimer::singleShot(0, this, SLOT(slotDequeue()));
1043  }
1044 }
1045 
1046 void
1047 KLauncher::slotDequeue()
1048 {
1049  do {
1050  KLaunchRequest *request = requestQueue.takeFirst();
1051  // process request
1052  request->status = KLaunchRequest::Launching;
1053  requestStart(request);
1054  if (request->status != KLaunchRequest::Launching)
1055  {
1056  // Request handled.
1057 #ifdef KLAUNCHER_VERBOSE_OUTPUT
1058  kDebug(7016) << "Request handled already";
1059 #endif
1060  requestDone( request );
1061  continue;
1062  }
1063  } while(requestQueue.count());
1064  bProcessingQueue = false;
1065 }
1066 
1067 void
1068 KLauncher::createArgs( KLaunchRequest *request, const KService::Ptr service ,
1069  const QStringList &urls)
1070 {
1071  const QStringList params = KRun::processDesktopExec(*service, urls);
1072 
1073  for(QStringList::ConstIterator it = params.begin();
1074  it != params.end(); ++it)
1075  {
1076  request->arg_list.append(*it);
1077  }
1078  request->cwd = service->path();
1079 }
1080 
1082 
1083 pid_t
1084 KLauncher::requestHoldSlave(const KUrl &url, const QString &app_socket)
1085 {
1086  IdleSlave *slave = 0;
1087  foreach (IdleSlave *p, mSlaveList)
1088  {
1089  if (p->onHold(url))
1090  {
1091  slave = p;
1092  break;
1093  }
1094  }
1095  if (slave)
1096  {
1097  mSlaveList.removeAll(slave);
1098  slave->connect(app_socket);
1099  return slave->pid();
1100  }
1101  return 0;
1102 }
1103 
1104 pid_t
1105 KLauncher::requestSlave(const QString &protocol,
1106  const QString &host,
1107  const QString &app_socket,
1108  QString &error)
1109 {
1110  IdleSlave *slave = 0;
1111  foreach (IdleSlave *p, mSlaveList)
1112  {
1113  if (p->match(protocol, host, true))
1114  {
1115  slave = p;
1116  break;
1117  }
1118  }
1119  if (!slave)
1120  {
1121  foreach (IdleSlave *p, mSlaveList)
1122  {
1123  if (p->match(protocol, host, false))
1124  {
1125  slave = p;
1126  break;
1127  }
1128  }
1129  }
1130  if (!slave)
1131  {
1132  foreach (IdleSlave *p, mSlaveList)
1133  {
1134  if (p->match(protocol, QString(), false))
1135  {
1136  slave = p;
1137  break;
1138  }
1139  }
1140  }
1141  if (slave)
1142  {
1143  mSlaveList.removeAll(slave);
1144  slave->connect(app_socket);
1145  return slave->pid();
1146  }
1147 
1148  QString name = KProtocolInfo::exec(protocol);
1149  if (name.isEmpty())
1150  {
1151  error = i18n("Unknown protocol '%1'.\n", protocol);
1152  return 0;
1153  }
1154 
1155  QStringList arg_list;
1156 #ifdef USE_KPROCESS_FOR_KIOSLAVES
1157  arg_list << name;
1158  arg_list << protocol;
1159  arg_list << mConnectionServer.address();
1160  arg_list << app_socket;
1161  name = KStandardDirs::findExe(QLatin1String("kioslave"));
1162 #else
1163  QString arg1 = protocol;
1164  QString arg2 = mConnectionServer.address();
1165  QString arg3 = app_socket;
1166  arg_list.append(arg1);
1167  arg_list.append(arg2);
1168  arg_list.append(arg3);
1169 #endif
1170 
1171  kDebug(7016) << "KLauncher: launching new slave " << name << " with protocol=" << protocol
1172  << " args=" << arg_list << endl;
1173 
1174 #ifdef Q_OS_UNIX
1175  if (mSlaveDebug == protocol)
1176  {
1177 #ifndef USE_KPROCESS_FOR_KIOSLAVES
1178  klauncher_header request_header;
1179  request_header.cmd = LAUNCHER_DEBUG_WAIT;
1180  request_header.arg_length = 0;
1181  kde_safe_write(kdeinitSocket, &request_header, sizeof(request_header));
1182 #else
1183  name = QString::fromLatin1("gdb");
1184 #endif
1185  }
1186  if (mSlaveValgrind == protocol) {
1187 #ifndef USE_KPROCESS_FOR_KIOSLAVES // otherwise we've already done this
1188  KLibrary lib(name, KGlobal::mainComponent());
1189  arg_list.prepend(lib.fileName());
1190  arg_list.prepend(KStandardDirs::locate("exe", QString::fromLatin1("kioslave")));
1191 #endif
1192  name = QString::fromLatin1("valgrind");
1193 
1194  if (!mSlaveValgrindSkin.isEmpty()) {
1195  arg_list.prepend(QLatin1String("--tool=") + mSlaveValgrindSkin);
1196  } else
1197  arg_list.prepend(QLatin1String("--tool=memcheck"));
1198  }
1199 #endif
1200  KLaunchRequest *request = new KLaunchRequest;
1201  request->autoStart = false;
1202  request->name = name;
1203  request->arg_list = arg_list;
1204  request->dbus_startup_type = KService::DBusNone;
1205  request->pid = 0;
1206 #ifdef Q_WS_X11
1207  request->startup_id = "0"; // krazy:exclude=doublequote_chars
1208 #endif
1209  request->status = KLaunchRequest::Launching;
1210  requestStart(request);
1211  pid_t pid = request->pid;
1212 
1213 // kDebug(7016) << "Slave launched, pid = " << pid;
1214 
1215  // We don't care about this request any longer....
1216  requestDone(request);
1217  if (!pid)
1218  {
1219  error = i18n("Error loading '%1'.\n", name);
1220  }
1221  return pid;
1222 }
1223 
1224 bool KLauncher::checkForHeldSlave(const QString &url)
1225 {
1226  Q_FOREACH (const IdleSlave *p, mSlaveList) {
1227  if (p->onHold(url)) {
1228  return true;
1229  }
1230  }
1231  return false;
1232 }
1233 
1234 void
1235 KLauncher::waitForSlave(int pid, const QDBusMessage &msg)
1236 {
1237  foreach (IdleSlave *slave, mSlaveList)
1238  {
1239  if (slave->pid() == static_cast<pid_t>(pid))
1240  return; // Already here.
1241  }
1242  SlaveWaitRequest *waitRequest = new SlaveWaitRequest;
1243  msg.setDelayedReply(true);
1244  waitRequest->transaction = msg;
1245  waitRequest->pid = static_cast<pid_t>(pid);
1246  mSlaveWaitRequest.append(waitRequest);
1247 }
1248 
1249 void
1250 KLauncher::acceptSlave()
1251 {
1252  IdleSlave *slave = new IdleSlave(this);
1253  mConnectionServer.setNextPendingConnection(&slave->mConn);
1254  mSlaveList.append(slave);
1255  connect(slave, SIGNAL(destroyed()), this, SLOT(slotSlaveGone()));
1256  connect(slave, SIGNAL(statusUpdate(IdleSlave*)),
1257  this, SLOT(slotSlaveStatus(IdleSlave*)));
1258  if (!mTimer.isActive())
1259  {
1260  mTimer.start(1000*10);
1261  }
1262 }
1263 
1264 void
1265 KLauncher::slotSlaveStatus(IdleSlave *slave)
1266 {
1267  QMutableListIterator<SlaveWaitRequest *> it(mSlaveWaitRequest);
1268  while(it.hasNext())
1269  {
1270  SlaveWaitRequest *waitRequest = it.next();
1271  if (waitRequest->pid == slave->pid())
1272  {
1273  QDBusConnection::sessionBus().send(waitRequest->transaction.createReply());
1274  it.remove();
1275  delete waitRequest;
1276  }
1277  }
1278 }
1279 
1280 void
1281 KLauncher::slotSlaveGone()
1282 {
1283  IdleSlave *slave = (IdleSlave *) sender();
1284  mSlaveList.removeAll(slave);
1285  if ((mSlaveList.count() == 0) && (mTimer.isActive()))
1286  {
1287  mTimer.stop();
1288  }
1289 }
1290 
1291 void
1292 KLauncher::idleTimeout()
1293 {
1294  bool keepOneFileSlave=true;
1295  time_t now = time(0);
1296  foreach (IdleSlave *slave, mSlaveList)
1297  {
1298  if ((slave->protocol()==QLatin1String("file")) && (keepOneFileSlave))
1299  keepOneFileSlave=false;
1300  else if (slave->age(now) > SLAVE_MAX_IDLE)
1301  {
1302  // killing idle slave
1303  delete slave;
1304  }
1305  }
1306 }
1307 
1308 void KLauncher::reparseConfiguration()
1309 {
1310  KProtocolManager::reparseConfiguration();
1311  foreach (IdleSlave *slave, mSlaveList)
1312  slave->reparseConfiguration();
1313 }
1314 
1315 
1316 void
1317 KLauncher::slotGotOutput()
1318 {
1319 #ifdef USE_KPROCESS_FOR_KIOSLAVES
1320  KProcess *p = static_cast<KProcess *>(sender());
1321  QByteArray _stdout = p->readAllStandardOutput();
1322  kDebug(7016) << _stdout.data();
1323 #endif
1324 }
1325 
1326 void
1327 KLauncher::slotFinished(int exitCode, QProcess::ExitStatus exitStatus )
1328 {
1329 #ifdef USE_KPROCESS_FOR_KIOSLAVES
1330  KProcess *p = static_cast<KProcess *>(sender());
1331  kDebug(7016) << "process finished exitcode=" << exitCode << "exitStatus=" << exitStatus;
1332 
1333  foreach (KLaunchRequest *request, requestList)
1334  {
1335  if (request->process == p)
1336  {
1337 #ifdef KLAUNCHER_VERBOSE_OUTPUT
1338  kDebug(7016) << "found KProcess, request done";
1339 #endif
1340  if (exitCode == 0 && exitStatus == QProcess::NormalExit)
1341  request->status = KLaunchRequest::Done;
1342  else
1343  request->status = KLaunchRequest::Error;
1344  requestDone(request);
1345  request->process = 0;
1346  }
1347  }
1348  delete p;
1349 #else
1350  Q_UNUSED(exitCode);
1351  Q_UNUSED(exitStatus);
1352 #endif
1353 }
1354 
1355 
1356 void KLauncher::terminate_kdeinit()
1357 {
1358  kDebug(7016);
1359 #ifndef USE_KPROCESS_FOR_KIOSLAVES
1360  klauncher_header request_header;
1361  request_header.cmd = LAUNCHER_TERMINATE_KDEINIT;
1362  request_header.arg_length = 0;
1363  kde_safe_write(kdeinitSocket, &request_header, sizeof(request_header));
1364 #endif
1365 }
1366 
1367 #include "klauncher.moc"
QVariant
KLaunchRequest::errorMsg
QString errorMsg
Definition: klauncher.h:101
i18n
QString i18n(const char *text)
KLauncher::start_service_by_desktop_path
bool start_service_by_desktop_path(const QString &serviceName, const QStringList &urls, const QStringList &envs, const QString &startup_id, bool blind, const QDBusMessage &msg)
Start a service by desktop path.
Definition: klauncher.cpp:770
KLauncher::requestList
QList< KLaunchRequest * > requestList
Definition: klauncher.h:272
KSharedPtr< KService >
klauncher_cmds.h
KLauncher::requestResult
serviceResult requestResult
Definition: klauncher.h:270
LAUNCHER_EXT_EXEC
#define LAUNCHER_EXT_EXEC
Definition: klauncher_cmds.h:123
KProcess
result
char result
Definition: kinit.cpp:135
KLaunchRequest::envs
QStringList envs
Definition: klauncher.h:106
KLaunchRequest::arg_list
QStringList arg_list
Definition: klauncher.h:92
SlaveWaitRequest
Definition: klauncher.h:81
KLauncher::cancel_service_startup_info
void cancel_service_startup_info(KLaunchRequest *request, const QByteArray &startup_id, const QStringList &envs)
Definition: klauncher.cpp:967
kdebug.h
KSharedPtr::data
T * data()
IdleSlave::age
int age(time_t now) const
Definition: klauncher.cpp:168
KLauncher::slotSlaveStatus
void slotSlaveStatus(IdleSlave *)
Definition: klauncher.cpp:1265
KService::DBusNone
kurl.h
IdleSlave::onHold
bool onHold(const KUrl &url) const
Definition: klauncher.cpp:161
KLauncher::autoStart
void autoStart(int phase=1)
Definition: klauncher.cpp:522
KService::serviceByDesktopName
static Ptr serviceByDesktopName(const QString &_name)
AutoStart::setPhaseDone
void setPhaseDone()
Definition: autostart.cpp:62
SLAVE_MAX_IDLE
#define SLAVE_MAX_IDLE
Definition: klauncher.cpp:61
timeout
int timeout
KLauncher::checkForHeldSlave
bool checkForHeldSlave(const QString &url)
Return true of there is a slave held for url.
Definition: klauncher.cpp:1224
KProcess::MergedChannels
KService
KStandardDirs::locate
static QString locate(const char *type, const QString &filename, const KComponentData &cData=KGlobal::mainComponent())
AutoStart::setPhase
void setPhase(int phase)
Definition: autostart.cpp:53
KLauncher::requestHoldSlave
pid_t requestHoldSlave(const KUrl &url, const QString &app_socket)
Definition: klauncher.cpp:1084
IdleSlave::connect
void connect(const QString &app_socket)
Definition: klauncher.cpp:133
kconfig.h
KLauncher::mConnectionServer
KIO::ConnectionServer mConnectionServer
Definition: klauncher.h:280
KLauncher::exec_blind
void exec_blind(const QString &name, const QStringList &arg_list, const QStringList &envs, const QString &startup_id)
Starts a program.
Definition: klauncher.cpp:726
KService::property
QVariant property(const QString &_name, QVariant::Type t) const
KLauncher::kdeinit_exec
bool kdeinit_exec(const QString &app, const QStringList &args, const QString &workdir, const QStringList &envs, const QString &startup_id, bool wait, const QDBusMessage &msg)
Definition: klauncher.cpp:999
g_klauncher_self
static KLauncher * g_klauncher_self
Definition: klauncher.cpp:173
IdleSlave::reparseConfiguration
void reparseConfiguration()
Definition: klauncher.cpp:143
KLauncher::reparseConfiguration
void reparseConfiguration()
Definition: klauncher.cpp:1308
KLauncher::mCached_dpy
Display * mCached_dpy
Definition: klauncher.h:291
kError
static QDebug kError(bool cond, int area=KDE_DEFAULT_DEBUG_AREA)
IdleSlave::mBirthDate
time_t mBirthDate
Definition: klauncher.h:76
KLaunchRequest::transaction
QDBusMessage transaction
Definition: klauncher.h:98
IdleSlave::IdleSlave
IdleSlave(QObject *parent)
Definition: klauncher.cpp:70
KProcess::setOutputChannelMode
void setOutputChannelMode(OutputChannelMode mode)
KLaunchRequest
Definition: klauncher.h:88
SlaveWaitRequest::transaction
QDBusMessage transaction
Definition: klauncher.h:85
QString
IdleSlave::mHost
QString mHost
Definition: klauncher.h:73
KLauncher
Definition: klauncher.h:123
KLaunchRequest::cwd
QString cwd
Definition: klauncher.h:107
AutoStart::phase
int phase() const
Definition: autostart.h:38
IdleSlave::mPid
pid_t mPid
Definition: klauncher.h:75
kdesktopfile.h
KLaunchRequest::Done
Definition: klauncher.h:95
QObject
kDebug
static QDebug kDebug(bool cond, int area=KDE_DEFAULT_DEBUG_AREA)
klocale.h
appendLong
static void appendLong(QByteArray &ba, long l)
Definition: klauncher.cpp:632
KLaunchRequest::startup_id
QByteArray startup_id
Definition: klauncher.h:103
KLaunchRequest::Error
Definition: klauncher.h:95
KLauncher::slotDequeue
void slotDequeue()
Definition: klauncher.cpp:1047
KLauncher::send_service_startup_info
void send_service_startup_info(KLaunchRequest *request, KService::Ptr service, const QByteArray &startup_id, const QStringList &envs)
Definition: klauncher.cpp:915
KLauncher::mSlaveWaitRequest
QList< SlaveWaitRequest * > mSlaveWaitRequest
Definition: klauncher.h:275
KUrl
IdleSlave::mProtocol
QString mProtocol
Definition: klauncher.h:72
KLauncher::lastRequest
KLaunchRequest * lastRequest
Definition: klauncher.h:274
KService::DBusWait
KService::exec
QString exec() const
KDesktopFile::isAuthorizedDesktopFile
static bool isAuthorizedDesktopFile(const QString &path)
KLauncher::slotFinished
void slotFinished(int exitCode, QProcess::ExitStatus exitStatus)
Definition: klauncher.cpp:1327
KService::path
QString path() const
LAUNCHER_EXEC_NEW
#define LAUNCHER_EXEC_NEW
Definition: klauncher_cmds.h:164
LAUNCHER_DEBUG_WAIT
#define LAUNCHER_DEBUG_WAIT
Definition: klauncher_cmds.h:113
KLaunchRequest::dbus_startup_type
KService::DBusStartupType dbus_startup_type
Definition: klauncher.h:99
KLauncher::mAutoTimer
QTimer mAutoTimer
Definition: klauncher.h:283
KService::dbusStartupType
DBusStartupType dbusStartupType() const
KLauncher::start_service_by_desktop_name
bool start_service_by_desktop_name(const QString &serviceName, const QStringList &urls, const QStringList &envs, const QString &startup_id, bool blind, const QDBusMessage &msg)
Start a service by desktop name.
Definition: klauncher.cpp:799
KLauncher::close
void close()
Definition: klauncher.cpp:262
KLauncher::requestSlave
pid_t requestSlave(const QString &protocol, const QString &host, const QString &app_socket, QString &error)
Definition: klauncher.cpp:1105
IdleSlave::mOnHold
bool mOnHold
Definition: klauncher.h:77
KLauncher::mSlaveValgrind
QString mSlaveValgrind
Definition: klauncher.h:287
AutoStart::phaseDone
bool phaseDone() const
Definition: autostart.h:39
QStringList
commandToString
const char * commandToString(int command)
Definition: klauncher_cmds.cpp:23
KLaunchRequest::startup_dpy
QByteArray startup_dpy
Definition: klauncher.h:104
KLauncher::start_service_by_name
bool start_service_by_name(const QString &serviceName, const QStringList &urls, const QStringList &envs, const QString &startup_id, bool blind, const QDBusMessage &msg)
Start a service by (translated) name - deprecated.
Definition: klauncher.cpp:751
KLauncher::destruct
void destruct()
Definition: klauncher.cpp:274
KLauncher::bProcessingQueue
bool bProcessingQueue
Definition: klauncher.h:284
LAUNCHER_CHILD_DIED
#define LAUNCHER_CHILD_DIED
Definition: klauncher_cmds.h:57
KLibrary
IdleSlave::statusUpdate
void statusUpdate(IdleSlave *)
IdleSlave
Definition: klauncher.h:50
KLaunchRequest::name
QString name
Definition: klauncher.h:91
LAUNCHER_TERMINATE_KDEINIT
#define LAUNCHER_TERMINATE_KDEINIT
Definition: klauncher_cmds.h:111
matchesPendingRequest
static bool matchesPendingRequest(const QString &appId, const QString &pendingAppId)
Definition: klauncher.cpp:447
KLibrary::fileName
QString fileName
klauncher_adaptor.h
KLauncher::acceptSlave
void acceptSlave()
Definition: klauncher.cpp:1250
KLauncher::mAutoStart
AutoStart mAutoStart
Definition: klauncher.h:285
s_DBusStartupTypeToString
static const char *const s_DBusStartupTypeToString[]
Definition: klauncher.cpp:65
KLauncher::processDied
void processDied(pid_t pid, long exitStatus)
Definition: klauncher.cpp:409
KService::serviceByDesktopPath
static Ptr serviceByDesktopPath(const QString &_path)
KProcess::start
void start()
KLauncher::mSlaveList
QList< IdleSlave * > mSlaveList
Definition: klauncher.h:281
KService::allowMultipleFiles
bool allowMultipleFiles() const
IdleSlave::mConn
KIO::Connection mConn
Definition: klauncher.h:70
KLaunchRequest::Launching
Definition: klauncher.h:95
KLauncher::mTimer
QTimer mTimer
Definition: klauncher.h:282
KLauncher::setLaunchEnv
void setLaunchEnv(const QString &name, const QString &value)
Definition: klauncher.cpp:282
kprotocolinfo.h
KService::icon
QString icon() const
IdleSlave::match
bool match(const QString &protocol, const QString &host, bool connected) const
Definition: klauncher.cpp:149
IdleSlave::mUrl
KUrl mUrl
Definition: klauncher.h:78
KLauncher::requestQueue
QList< KLaunchRequest * > requestQueue
Definition: klauncher.h:273
KLaunchRequest::tolerant_dbus_name
QString tolerant_dbus_name
Definition: klauncher.h:94
KProtocolInfo::exec
static QString exec(const QString &protocol)
KLaunchRequest::dbus_name
QString dbus_name
Definition: klauncher.h:93
IdleSlave::mConnected
bool mConnected
Definition: klauncher.h:74
IdleSlave::gotInput
void gotInput()
Definition: klauncher.cpp:86
KLauncher::waitForSlave
void waitForSlave(int pid, const QDBusMessage &msg)
Definition: klauncher.cpp:1235
KService::DBusUnique
KLaunchRequest::pid
pid_t pid
Definition: klauncher.h:96
KLauncher::slotKDEInitData
void slotKDEInitData(int)
Definition: klauncher.cpp:342
serviceResult::result
int result
Definition: klauncher.h:117
serviceResult::pid
pid_t pid
Definition: klauncher.h:120
ktemporaryfile.h
klauncher_header::cmd
long cmd
Definition: klauncher_cmds.h:27
KLauncher::autoStart0Done
void autoStart0Done()
KLauncher::KLauncher
KLauncher()
Definition: klauncher.cpp:196
KService::serviceByName
static Ptr serviceByName(const QString &_name)
serviceResult::dbusName
QString dbusName
Definition: klauncher.h:118
K_EINTR_LOOP
#define K_EINTR_LOOP(var, cmd)
Definition: klauncher.cpp:177
KLauncher::requestDone
void requestDone(KLaunchRequest *request)
Definition: klauncher.cpp:567
KLauncher::autoStart1Done
void autoStart1Done()
KLaunchRequest::Running
Definition: klauncher.h:95
IdleSlave::protocol
QString protocol() const
Definition: klauncher.h:61
KLauncher::requestStart
void requestStart(KLaunchRequest *request)
Definition: klauncher.cpp:640
KLauncher::idleTimeout
void idleTimeout()
Definition: klauncher.cpp:1292
kstandarddirs.h
LAUNCHER_ERROR
#define LAUNCHER_ERROR
Definition: klauncher_cmds.h:76
read_socket
static int read_socket(int sock, char *buffer, int len)
Definition: kinit.cpp:1022
AutoStart::startService
QString startService()
Definition: autostart.cpp:105
KLauncher::slotSlaveGone
void slotSlaveGone()
Definition: klauncher.cpp:1281
KLauncher::autoStart2Done
void autoStart2Done()
KStandardDirs::findExe
static QString findExe(const QString &appname, const QString &pathstr=QString(), SearchOptions options=NoSearchOptions)
IdleSlave::pid
pid_t pid() const
Definition: klauncher.h:57
KLaunchRequest::autoStart
bool autoStart
Definition: klauncher.h:100
KGlobal::mainComponent
const KComponentData & mainComponent()
KLauncher::processRequestReturn
void processRequestReturn(int status, const QByteArray &requestData)
Definition: klauncher.cpp:365
KLauncher::queueRequest
void queueRequest(KLaunchRequest *)
Definition: klauncher.cpp:1036
kWarning
static QDebug kWarning(bool cond, int area=KDE_DEFAULT_DEBUG_AREA)
qint32
KLauncher::slotGotOutput
void slotGotOutput()
Definition: klauncher.cpp:1317
LAUNCHER_SETENV
#define LAUNCHER_SETENV
Definition: klauncher_cmds.h:45
KProcess::pid
int pid() const
KLauncher::~KLauncher
~KLauncher()
Definition: klauncher.cpp:256
KService::DBusMulti
klauncher.h
AutoStart::loadAutoStartList
void loadAutoStartList()
Definition: autostart.cpp:79
KLauncher::slotAutoStart
void slotAutoStart()
Definition: klauncher.cpp:533
LAUNCHER_OK
#define LAUNCHER_OK
Definition: klauncher_cmds.h:67
klibrary.h
KLauncher::start_service
bool start_service(KService::Ptr service, const QStringList &urls, const QStringList &envs, const QByteArray &startup_id, bool blind, bool autoStart, const QDBusMessage &msg)
Definition: klauncher.cpp:814
KLauncher::terminate_kdeinit
void terminate_kdeinit()
Definition: klauncher.cpp:1356
serviceResult::error
QString error
Definition: klauncher.h:119
KLauncherAdaptor
Definition: klauncher_adaptor.h:36
KLauncher::createArgs
void createArgs(KLaunchRequest *request, const KService::Ptr service, const QStringList &url)
Definition: klauncher.cpp:1068
klauncher_header::arg_length
long arg_length
Definition: klauncher_cmds.h:28
KLauncher::mSlaveValgrindSkin
QString mSlaveValgrindSkin
Definition: klauncher.h:288
fd
int fd[2]
Definition: kinit.cpp:129
klauncher_header
Definition: klauncher_cmds.h:25
KLauncher::slotNameOwnerChanged
void slotNameOwnerChanged(const QString &name, const QString &oldOnwer, const QString &newOwner)
Definition: klauncher.cpp:467
KLauncher::mSlaveDebug
QString mSlaveDebug
Definition: klauncher.h:286
KLaunchRequest::status
status_t status
Definition: klauncher.h:97
KLaunchRequest::process
KProcess * process
Definition: klauncher.h:110
KProcess::setProgram
void setProgram(const QString &exe, const QStringList &args=QStringList())
kde_safe_write
ssize_t kde_safe_write(int fd, const void *buf, size_t count)
Definition: klauncher.cpp:182
SlaveWaitRequest::pid
pid_t pid
Definition: klauncher.h:84
This file is part of the KDE documentation.
Documentation copyright © 1996-2014 The KDE developers.
Generated on Tue Oct 14 2014 22:49:06 by doxygen 1.8.7 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

KInit

Skip menu "KInit"
  • Main Page
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • File Members
  • Related Pages

kdelibs API Reference

Skip menu "kdelibs API Reference"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDEWebKit
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  • kjsembed
  •   WTF
  • KNewStuff
  • KParts
  • KPty
  • Kross
  • KUnitConversion
  • KUtils
  • Nepomuk
  • Nepomuk-Core
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver

Search



Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal