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

KInit

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

KDE's Doxygen guidelines are available online.

KInit

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

kdelibs-4.10.5 API Reference

Skip menu "kdelibs-4.10.5 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
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • KPty
  • Kross
  • KUnitConversion
  • KUtils
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver
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