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

KInit

klauncher.cpp

Go to the documentation of this file.
00001 /*
00002   This file is part of the KDE libraries
00003   Copyright (c) 1999 Waldo Bastian <bastian@kde.org>
00004 
00005   This library is free software; you can redistribute it and/or
00006   modify it under the terms of the GNU Library General Public
00007   License version 2 as published by the Free Software Foundation.
00008 
00009   This library is distributed in the hope that it will be useful,
00010   but WITHOUT ANY WARRANTY; without even the implied warranty of
00011   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012   Library General Public License for more details.
00013 
00014   You should have received a copy of the GNU Library General Public License
00015   along with this library; see the file COPYING.LIB.  If not, write to
00016   the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00017   Boston, MA 02110-1301, USA.
00018 */
00019 
00020 #define QT_NO_CAST_FROM_ASCII
00021 
00022 #include "klauncher.h"
00023 #include "klauncher_cmds.h"
00024 #include "klauncher_adaptor.h"
00025 
00026 #include <config.h>
00027 
00028 #include <stdio.h>
00029 #include <unistd.h>
00030 #include <stdlib.h>
00031 #include <errno.h>
00032 #include <signal.h>
00033 #include <sys/time.h>
00034 
00035 #ifdef Q_WS_X11
00036 #include <kstartupinfo.h>
00037 #include <X11/Xlib.h>
00038 #endif
00039 
00040 #include <QtCore/QFile>
00041 
00042 #include <kconfig.h>
00043 #include <kdebug.h>
00044 #include <kde_file.h>
00045 #include <klibrary.h>
00046 #include <klocale.h>
00047 #include <kprotocolmanager.h>
00048 #include <kprotocolinfo.h>
00049 #include <krun.h>
00050 #include <kstandarddirs.h>
00051 #include <ktemporaryfile.h>
00052 #include <kdesktopfile.h>
00053 #include <kurl.h>
00054 
00055 #include <kio/global.h>
00056 #include <kio/connection.h>
00057 #include <kio/slaveinterface.h>
00058 
00059 // Dispose slaves after being idle for SLAVE_MAX_IDLE seconds
00060 #define SLAVE_MAX_IDLE  30
00061 
00062 // #define KLAUNCHER_VERBOSE_OUTPUT
00063 
00064 static const char* const s_DBusStartupTypeToString[] =
00065     { "DBusNone", "DBusUnique", "DBusMulti", "DBusWait", "ERROR" };
00066 
00067 using namespace KIO;
00068 
00069 IdleSlave::IdleSlave(QObject *parent)
00070     : QObject(parent)
00071 {
00072    QObject::connect(&mConn, SIGNAL(readyRead()), this, SLOT(gotInput()));
00073    // Send it a SLAVE_STATUS command.
00074    mConn.send( CMD_SLAVE_STATUS );
00075    mPid = 0;
00076    mBirthDate = time(0);
00077    mOnHold = false;
00078 }
00079 
00080 template<int T> struct PIDType { typedef pid_t PID_t; } ;
00081 template<> struct PIDType<2> { typedef qint16 PID_t; } ;
00082 template<> struct PIDType<4> { typedef qint32 PID_t; } ;
00083 
00084 void
00085 IdleSlave::gotInput()
00086 {
00087    int cmd;
00088    QByteArray data;
00089    if (mConn.read( &cmd, data) == -1)
00090    {
00091       // Communication problem with slave.
00092       kError(7016) << "SlavePool: No communication with slave." << endl;
00093       deleteLater();
00094    }
00095    else if (cmd == MSG_SLAVE_ACK)
00096    {
00097       deleteLater();
00098    }
00099    else if (cmd != MSG_SLAVE_STATUS)
00100    {
00101       kError(7016) << "SlavePool: Unexpected data from slave." << endl;
00102       deleteLater();
00103    }
00104    else
00105    {
00106       QDataStream stream( data );
00107       PIDType<sizeof(pid_t)>::PID_t stream_pid;
00108       pid_t pid;
00109       QByteArray protocol;
00110       QString host;
00111       qint8 b;
00112       stream >> stream_pid >> protocol >> host >> b;
00113       pid = stream_pid;
00114 // Overload with (bool) onHold, (KUrl) url.
00115       if (!stream.atEnd())
00116       {
00117          KUrl url;
00118          stream >> url;
00119          mOnHold = true;
00120          mUrl = url;
00121       }
00122 
00123       mPid = pid;
00124       mConnected = (b != 0);
00125       mProtocol = QString::fromLatin1(protocol);
00126       mHost = host;
00127       emit statusUpdate(this);
00128    }
00129 }
00130 
00131 void
00132 IdleSlave::connect(const QString &app_socket)
00133 {
00134    QByteArray data;
00135    QDataStream stream( &data, QIODevice::WriteOnly);
00136    stream << app_socket;
00137    mConn.send( CMD_SLAVE_CONNECT, data );
00138    // Timeout!
00139 }
00140 
00141 void
00142 IdleSlave::reparseConfiguration()
00143 {
00144    mConn.send( CMD_REPARSECONFIGURATION );
00145 }
00146 
00147 bool
00148 IdleSlave::match(const QString &protocol, const QString &host, bool needConnected)
00149 {
00150    if (mOnHold || protocol != mProtocol) {
00151       return false;
00152    }
00153    if (host.isEmpty()) {
00154       return true;
00155    }
00156    return (host == mHost) && (!needConnected || mConnected);
00157 }
00158 
00159 bool
00160 IdleSlave::onHold(const KUrl &url)
00161 {
00162    if (!mOnHold) return false;
00163    return (url == mUrl);
00164 }
00165 
00166 int
00167 IdleSlave::age(time_t now)
00168 {
00169    return (int) difftime(now, mBirthDate);
00170 }
00171 
00172 static KLauncher* g_klauncher_self;
00173 
00174 #ifndef USE_KPROCESS_FOR_KIOSLAVES
00175 KLauncher::KLauncher(int _kdeinitSocket)
00176   : QObject(0),
00177     kdeinitSocket(_kdeinitSocket)
00178 #else
00179 KLauncher::KLauncher()
00180   : QObject(0)
00181 #endif
00182 {
00183 #ifdef Q_WS_X11
00184    mCached_dpy = NULL;
00185 #endif
00186    Q_ASSERT( g_klauncher_self == NULL );
00187    g_klauncher_self = this;
00188 
00189    mAutoTimer.setSingleShot(true);
00190    new KLauncherAdaptor(this);
00191    QDBusConnection::sessionBus().registerObject(QLatin1String("/KLauncher"), this); // same as ktoolinvocation.cpp
00192 
00193    connect(&mAutoTimer, SIGNAL(timeout()), this, SLOT(slotAutoStart()));
00194    connect(QDBusConnection::sessionBus().interface(),
00195            SIGNAL(serviceOwnerChanged(QString,QString,QString)),
00196            SLOT(slotNameOwnerChanged(QString,QString,QString)));
00197 
00198    mConnectionServer.listenForRemote();
00199    connect(&mConnectionServer, SIGNAL(newConnection()), SLOT(acceptSlave()));
00200    if (!mConnectionServer.isListening())
00201    {
00202       // Severe error!
00203       qDebug("KLauncher: Fatal error, can't create tempfile!");
00204       ::_exit(1);
00205    }
00206 
00207    connect(&mTimer, SIGNAL(timeout()), SLOT(idleTimeout()));
00208 
00209 #ifndef USE_KPROCESS_FOR_KIOSLAVES
00210    kdeinitNotifier = new QSocketNotifier(kdeinitSocket, QSocketNotifier::Read);
00211    connect(kdeinitNotifier, SIGNAL( activated( int )),
00212            this, SLOT( slotKDEInitData( int )));
00213    kdeinitNotifier->setEnabled( true );
00214 #endif
00215    lastRequest = 0;
00216    bProcessingQueue = false;
00217 
00218    mSlaveDebug = QString::fromLocal8Bit(qgetenv("KDE_SLAVE_DEBUG_WAIT"));
00219    if (!mSlaveDebug.isEmpty())
00220    {
00221       qWarning("Klauncher running in slave-debug mode for slaves of protocol '%s'", qPrintable(mSlaveDebug));
00222    }
00223    mSlaveValgrind = QString::fromLocal8Bit(qgetenv("KDE_SLAVE_VALGRIND"));
00224    if (!mSlaveValgrind.isEmpty())
00225    {
00226       mSlaveValgrindSkin = QString::fromLocal8Bit(qgetenv("KDE_SLAVE_VALGRIND_SKIN"));
00227       qWarning("Klauncher running slaves through valgrind for slaves of protocol '%s'", qPrintable(mSlaveValgrind));
00228    }
00229 #ifdef USE_KPROCESS_FOR_KIOSLAVES
00230    kDebug(7016) << "LAUNCHER_OK";
00231 #else
00232    klauncher_header request_header;
00233    request_header.cmd = LAUNCHER_OK;
00234    request_header.arg_length = 0;
00235    write(kdeinitSocket, &request_header, sizeof(request_header));
00236 #endif
00237 }
00238 
00239 KLauncher::~KLauncher()
00240 {
00241    close();
00242    g_klauncher_self = NULL;
00243 }
00244 
00245 void KLauncher::close()
00246 {
00247 #ifdef Q_WS_X11
00248    if( mCached_dpy != NULL )
00249    {
00250        XCloseDisplay( mCached_dpy );
00251        mCached_dpy = NULL;
00252    }
00253 #endif
00254 }
00255 
00256 void
00257 KLauncher::destruct()
00258 {
00259     if (g_klauncher_self)
00260         g_klauncher_self->close();
00261     // We don't delete the app here, that's intentional.
00262     ::_exit(255);
00263 }
00264 
00265 void KLauncher::setLaunchEnv(const QString &name, const QString &value)
00266 {
00267 #ifndef USE_KPROCESS_FOR_KIOSLAVES
00268    klauncher_header request_header;
00269    QByteArray requestData;
00270    requestData.append(name.toLocal8Bit()).append('\0').append(value.toLocal8Bit()).append('\0');
00271    request_header.cmd = LAUNCHER_SETENV;
00272    request_header.arg_length = requestData.size();
00273    write(kdeinitSocket, &request_header, sizeof(request_header));
00274    write(kdeinitSocket, requestData.data(), request_header.arg_length);
00275 #else
00276    Q_UNUSED(name);
00277    Q_UNUSED(value);
00278 #endif
00279 }
00280 
00281 #ifndef USE_KPROCESS_FOR_KIOSLAVES
00282 /*
00283  * Read 'len' bytes from 'sock' into buffer.
00284  * returns -1 on failure, 0 on no data.
00285  */
00286 static int
00287 read_socket(int sock, char *buffer, int len)
00288 {
00289   ssize_t result;
00290   int bytes_left = len;
00291     while (bytes_left > 0) {
00292         // in case we get a request to start an application and data arrive
00293         // to kdeinitSocket at the same time, requestStart() will already
00294         // call slotKDEInitData(), so we must check there's still something
00295         // to read, otherwise this would block
00296 
00297         // Same thing if kdeinit dies without warning.
00298 
00299         fd_set in;
00300         timeval tm = { 30, 0 }; // 30 seconds timeout, so we're not stuck in case kdeinit dies on us
00301         FD_ZERO ( &in );
00302         FD_SET( sock, &in );
00303         select( sock + 1, &in, 0, 0, &tm );
00304         if( !FD_ISSET( sock, &in )) {
00305             kDebug(7016) << "read_socket" << sock << "nothing to read, kdeinit4 must be dead";
00306             return -1;
00307         }
00308 
00309      result = read(sock, buffer, bytes_left);
00310      if (result > 0)
00311      {
00312         buffer += result;
00313         bytes_left -= result;
00314      }
00315      else if (result == 0)
00316         return -1;
00317      else if ((result == -1) && (errno != EINTR))
00318         return -1;
00319   }
00320   return 0;
00321 }
00322 #endif
00323 
00324 void
00325 KLauncher::slotKDEInitData(int)
00326 {
00327 #ifndef USE_KPROCESS_FOR_KIOSLAVES
00328    klauncher_header request_header;
00329    QByteArray requestData;
00330 
00331    int result = read_socket(kdeinitSocket, (char *) &request_header,
00332                             sizeof( request_header));
00333    if (result == -1)
00334    {
00335       kDebug(7016) << "Exiting on read_socket errno:" << errno;
00336       KDE_signal( SIGHUP, SIG_IGN);
00337       KDE_signal( SIGTERM, SIG_IGN);
00338       destruct(); // Exit!
00339    }
00340    requestData.resize(request_header.arg_length);
00341    result = read_socket(kdeinitSocket, (char *) requestData.data(),
00342                         request_header.arg_length);
00343 
00344    processRequestReturn(request_header.cmd,requestData);
00345 #endif
00346 }
00347 
00348 void KLauncher::processRequestReturn(int status, const QByteArray &requestData)
00349 {
00350    if (status == LAUNCHER_CHILD_DIED)
00351    {
00352      long *request_data;
00353      request_data = (long *) requestData.data();
00354      processDied(request_data[0], request_data[1]);
00355      return;
00356    }
00357    if (lastRequest && (status == LAUNCHER_OK))
00358    {
00359      long *request_data;
00360      request_data = (long *) requestData.data();
00361      lastRequest->pid = (pid_t) (*request_data);
00362      kDebug(7016).nospace() << lastRequest->name << " (pid " << lastRequest->pid <<
00363         ") up and running.";
00364      switch(lastRequest->dbus_startup_type)
00365      {
00366        case KService::DBusNone:
00367          lastRequest->status = KLaunchRequest::Running;
00368          break;
00369        case KService::DBusUnique:
00370        case KService::DBusWait:
00371        case KService::DBusMulti:
00372          lastRequest->status = KLaunchRequest::Launching;
00373          break;
00374      }
00375      lastRequest = 0;
00376      return;
00377    }
00378    if (lastRequest && (status == LAUNCHER_ERROR))
00379    {
00380      lastRequest->status = KLaunchRequest::Error;
00381      kDebug(7016) << lastRequest->name << " failed." << endl;
00382      if (!requestData.isEmpty())
00383         lastRequest->errorMsg = QString::fromUtf8((char *) requestData.data());
00384      lastRequest = 0;
00385      return;
00386    }
00387 
00388    kWarning(7016)<< "Unexpected request return" << (unsigned int) status;
00389 }
00390 
00391 void
00392 KLauncher::processDied(pid_t pid, long exitStatus)
00393 {
00394 #ifdef KLAUNCHER_VERBOSE_OUTPUT
00395     kDebug(7016) << pid << "exitStatus=" << exitStatus;
00396 #else
00397     Q_UNUSED(exitStatus);
00398     // We should probably check the exitStatus for the uniqueapp case?
00399 #endif
00400    foreach (KLaunchRequest *request, requestList)
00401    {
00402 #ifdef KLAUNCHER_VERBOSE_OUTPUT
00403        kDebug(7016) << "  had pending request" << request->pid;
00404 #endif
00405       if (request->pid == pid)
00406       {
00407          if (request->dbus_startup_type == KService::DBusWait)
00408              request->status = KLaunchRequest::Done;
00409          else if ((request->dbus_startup_type == KService::DBusUnique)
00410                   && QDBusConnection::sessionBus().interface()->isServiceRegistered(request->dbus_name)) {
00411              request->status = KLaunchRequest::Running;
00412 #ifdef KLAUNCHER_VERBOSE_OUTPUT
00413              kDebug(7016) << pid << "running as a unique app";
00414 #endif
00415          } else {
00416              request->status = KLaunchRequest::Error;
00417 #ifdef KLAUNCHER_VERBOSE_OUTPUT
00418              kDebug(7016) << pid << "died, requestDone. status=" << request->status;
00419 #endif
00420          }
00421          requestDone(request);
00422          return;
00423       }
00424    }
00425 #ifdef KLAUNCHER_VERBOSE_OUTPUT
00426    kDebug(7016) << "found no pending requests for PID" << pid;
00427 #endif
00428 }
00429 
00430 static bool matchesPendingRequest(const QString& appId, const QString& pendingAppId)
00431 {
00432     // appId just registered, e.g. org.koffice.kword-12345
00433     // Let's see if this is what pendingAppId (e.g. org.koffice.kword or *.kword) was waiting for.
00434 
00435     const QString newAppId = appId.left(appId.lastIndexOf(QLatin1Char('-'))); // strip out the -12345 if present.
00436 
00437     //kDebug() << "appId=" << appId << "newAppId=" << newAppId << "pendingAppId=" << pendingAppId;
00438 
00439     if (pendingAppId.startsWith(QLatin1String("*."))) {
00440         const QString pendingName = pendingAppId.mid(2);
00441         const QString appName = newAppId.mid(newAppId.lastIndexOf(QLatin1Char('.'))+1);
00442         //kDebug() << "appName=" << appName;
00443         return appName == pendingName;
00444     }
00445 
00446     return newAppId == pendingAppId;
00447 }
00448 
00449 void
00450 KLauncher::slotNameOwnerChanged(const QString &appId, const QString &oldOwner,
00451                                 const QString &newOwner)
00452 {
00453    Q_UNUSED(oldOwner);
00454    if (appId.isEmpty() || newOwner.isEmpty())
00455       return;
00456 
00457 #ifdef KLAUNCHER_VERBOSE_OUTPUT
00458    kDebug(7016) << "new app" << appId;
00459 #endif
00460    foreach (KLaunchRequest *request, requestList)
00461    {
00462       if (request->status != KLaunchRequest::Launching)
00463          continue;
00464 
00465 #ifdef KLAUNCHER_VERBOSE_OUTPUT
00466       kDebug(7016) << "had pending request" << request->name << s_DBusStartupTypeToString[request->dbus_startup_type] << "dbus_name" << request->dbus_name << request->tolerant_dbus_name;
00467 #endif
00468       // For unique services check the requested service name first
00469       if (request->dbus_startup_type == KService::DBusUnique) {
00470           if ((appId == request->dbus_name) || // just started
00471               QDBusConnection::sessionBus().interface()->isServiceRegistered(request->dbus_name)) { // was already running
00472               request->status = KLaunchRequest::Running;
00473 #ifdef KLAUNCHER_VERBOSE_OUTPUT
00474               kDebug(7016) << "OK, unique app" << request->dbus_name << "is running";
00475 #endif
00476               requestDone(request);
00477               continue;
00478           } else {
00479 #ifdef KLAUNCHER_VERBOSE_OUTPUT
00480               kDebug(7016) << "unique app" << request->dbus_name << "not running yet";
00481 #endif
00482           }
00483       }
00484 
00485       const QString rAppId = !request->tolerant_dbus_name.isEmpty() ? request->tolerant_dbus_name : request->dbus_name;
00486 #ifdef KLAUNCHER_VERBOSE_OUTPUT
00487       //kDebug(7016) << "using" << rAppId << "for matching";
00488 #endif
00489       if (rAppId.isEmpty())
00490           continue;
00491 
00492       if (matchesPendingRequest(appId, rAppId)) {
00493 #ifdef KLAUNCHER_VERBOSE_OUTPUT
00494          kDebug(7016) << "ok, request done";
00495 #endif
00496          request->dbus_name = appId;
00497          request->status = KLaunchRequest::Running;
00498          requestDone(request);
00499          continue;
00500       }
00501    }
00502 }
00503 
00504 void
00505 KLauncher::autoStart(int phase)
00506 {
00507    if( mAutoStart.phase() >= phase )
00508        return;
00509    mAutoStart.setPhase(phase);
00510    if (phase == 0)
00511       mAutoStart.loadAutoStartList();
00512    mAutoTimer.start(0);
00513 }
00514 
00515 void
00516 KLauncher::slotAutoStart()
00517 {
00518    KService::Ptr s;
00519    do
00520    {
00521       QString service = mAutoStart.startService();
00522       if (service.isEmpty())
00523       {
00524          // Done
00525      if( !mAutoStart.phaseDone())
00526      {
00527         mAutoStart.setPhaseDone();
00528             switch( mAutoStart.phase())
00529                 {
00530                 case 0:
00531                     emit autoStart0Done();
00532                     break;
00533                 case 1:
00534                     emit autoStart1Done();
00535                     break;
00536                 case 2:
00537                     emit autoStart2Done();
00538                     break;
00539                 }
00540      }
00541          return;
00542       }
00543       s = new KService(service);
00544    }
00545    while (!start_service(s, QStringList(), QStringList(), "0", false, true, QDBusMessage()));
00546    // Loop till we find a service that we can start.
00547 }
00548 
00549 void
00550 KLauncher::requestDone(KLaunchRequest *request)
00551 {
00552    if ((request->status == KLaunchRequest::Running) ||
00553        (request->status == KLaunchRequest::Done))
00554    {
00555       requestResult.result = 0;
00556       requestResult.dbusName = request->dbus_name;
00557       requestResult.error = QString::fromLatin1(""); // not null, cf assert further down
00558       requestResult.pid = request->pid;
00559    }
00560    else
00561    {
00562       requestResult.result = 1;
00563       requestResult.dbusName.clear();
00564       requestResult.error = i18n("KDEInit could not launch '%1'.", request->name);
00565       if (!request->errorMsg.isEmpty())
00566           requestResult.error += QString::fromLatin1(":\n") + request->errorMsg;
00567       requestResult.pid = 0;
00568 
00569 #ifdef Q_WS_X11
00570       if (!request->startup_dpy.isEmpty())
00571       {
00572          Display* dpy = NULL;
00573          if( (mCached_dpy != NULL) &&
00574               (request->startup_dpy == XDisplayString( mCached_dpy )))
00575             dpy = mCached_dpy;
00576          if( dpy == NULL )
00577             dpy = XOpenDisplay(request->startup_dpy);
00578          if( dpy )
00579          {
00580             KStartupInfoId id;
00581             id.initId(request->startup_id);
00582             KStartupInfo::sendFinishX( dpy, id );
00583             if( mCached_dpy != dpy && mCached_dpy != NULL )
00584                XCloseDisplay( mCached_dpy );
00585             mCached_dpy = dpy;
00586          }
00587       }
00588 #endif
00589    }
00590 
00591    if (request->autoStart)
00592    {
00593       mAutoTimer.start(0);
00594    }
00595 
00596    if (request->transaction.type() != QDBusMessage::InvalidMessage)
00597    {
00598       if ( requestResult.dbusName.isNull() ) // null strings can't be sent
00599           requestResult.dbusName.clear();
00600       Q_ASSERT( !requestResult.error.isNull() );
00601       PIDType<sizeof(pid_t)>::PID_t stream_pid = requestResult.pid;
00602       QDBusConnection::sessionBus().send(request->transaction.createReply(QVariantList() << requestResult.result
00603                                      << requestResult.dbusName
00604                                      << requestResult.error
00605                                      << stream_pid));
00606    }
00607 #ifdef KLAUNCHER_VERBOSE_OUTPUT
00608    kDebug(7016) << "removing done request" << request->name << "PID" << request->pid;
00609 #endif
00610 
00611    requestList.removeAll( request );
00612    delete request;
00613 }
00614 
00615 static void appendLong(QByteArray &ba, long l)
00616 {
00617    const int sz = ba.size();
00618    ba.resize(sz + sizeof(long));
00619    memcpy(ba.data() + sz, &l, sizeof(long));
00620 }
00621 
00622 void
00623 KLauncher::requestStart(KLaunchRequest *request)
00624 {
00625 #ifdef USE_KPROCESS_FOR_KIOSLAVES
00626    requestList.append( request );
00627    lastRequest = request;
00628 
00629    KProcess *process  = new KProcess;
00630    process->setOutputChannelMode(KProcess::MergedChannels);
00631    connect(process ,SIGNAL(readyReadStandardOutput()),this, SLOT(slotGotOutput()) );
00632    connect(process ,SIGNAL(finished(int, QProcess::ExitStatus)),this, SLOT(slotFinished(int, QProcess::ExitStatus)) );
00633    request->process = process;
00634 
00635 // process.setEnvironment(envlist);
00636    QStringList args;
00637    foreach (const QString &arg, request->arg_list)
00638       args << arg;
00639 
00640    QString executable = request->name;
00641 #ifdef Q_WS_MAC
00642    const QString bundlepath = KStandardDirs::findExe(executable);
00643    if (!bundlepath.isEmpty())
00644       executable = bundlepath;
00645 #endif
00646    process->setProgram(executable,args);
00647    process->start();
00648 
00649    if (!process->waitForStarted())
00650    {
00651        processRequestReturn(LAUNCHER_ERROR,"");
00652    }
00653    else
00654    {
00655        request->pid = process->pid();
00656        QByteArray data((char *)&request->pid, sizeof(int));
00657        processRequestReturn(LAUNCHER_OK,data);
00658    }
00659    return;
00660 
00661 #else
00662    requestList.append( request );
00663    // Send request to kdeinit.
00664    klauncher_header request_header;
00665    QByteArray requestData;
00666    requestData.reserve(1024);
00667 
00668    appendLong(requestData, request->arg_list.count() + 1);
00669    requestData.append(request->name.toLocal8Bit());
00670    requestData.append('\0');
00671    foreach (const QString &arg, request->arg_list)
00672        requestData.append(arg.toLocal8Bit()).append('\0');
00673    appendLong(requestData, request->envs.count());
00674    foreach (const QString &env, request->envs)
00675        requestData.append(env.toLocal8Bit()).append('\0');
00676    appendLong(requestData, 0); // avoid_loops, always false here
00677 #ifdef Q_WS_X11
00678    bool startup_notify = !request->startup_id.isNull() && request->startup_id != "0";
00679    if( startup_notify )
00680        requestData.append(request->startup_id).append('\0');
00681 #endif
00682    if (!request->cwd.isEmpty())
00683        requestData.append(QFile::encodeName(request->cwd)).append('\0');
00684 
00685 #ifdef Q_WS_X11
00686    request_header.cmd = startup_notify ? LAUNCHER_EXT_EXEC : LAUNCHER_EXEC_NEW;
00687 #else
00688    request_header.cmd = LAUNCHER_EXEC_NEW;
00689 #endif
00690    request_header.arg_length = requestData.length();
00691 
00692 #ifdef KLAUNCHER_VERBOSE_OUTPUT
00693    kDebug(7016) << "Asking kdeinit to start" << request->name << request->arg_list
00694                 << "cmd=" << commandToString(request_header.cmd);
00695 #endif
00696 
00697    write(kdeinitSocket, &request_header, sizeof(request_header));
00698    write(kdeinitSocket, requestData.data(), requestData.length());
00699 
00700    // Wait for pid to return.
00701    lastRequest = request;
00702    do {
00703       slotKDEInitData( kdeinitSocket );
00704    }
00705    while (lastRequest != 0);
00706 #endif
00707 }
00708 
00709 void KLauncher::exec_blind(const QString &name, const QStringList &arg_list, const QStringList &envs, const QString &startup_id)
00710 {
00711    KLaunchRequest *request = new KLaunchRequest;
00712    request->autoStart = false;
00713    request->name = name;
00714    request->arg_list =  arg_list;
00715    request->dbus_startup_type = KService::DBusNone;
00716    request->pid = 0;
00717    request->status = KLaunchRequest::Launching;
00718    request->envs = envs;
00719    // Find service, if any - strip path if needed
00720    KService::Ptr service = KService::serviceByDesktopName( name.mid( name.lastIndexOf(QLatin1Char('/')) + 1 ));
00721    if (service)
00722        send_service_startup_info(request, service, startup_id.toLocal8Bit(), QStringList());
00723    else // no .desktop file, no startup info
00724        cancel_service_startup_info( request, startup_id.toLocal8Bit(), envs );
00725 
00726    requestStart(request);
00727    // We don't care about this request any longer....
00728    requestDone(request);
00729 }
00730 
00731 
00732 // KDE5: remove
00733 bool
00734 KLauncher::start_service_by_name(const QString &serviceName, const QStringList &urls,
00735     const QStringList &envs, const QString& startup_id, bool blind, const QDBusMessage &msg)
00736 {
00737    KService::Ptr service;
00738    // Find service
00739 #ifndef KDE_NO_DEPRECATED
00740    service = KService::serviceByName(serviceName);
00741 #endif
00742    if (!service)
00743    {
00744       requestResult.result = ENOENT;
00745       requestResult.error = i18n("Could not find service '%1'.", serviceName);
00746       cancel_service_startup_info( NULL, startup_id.toLocal8Bit(), envs ); // cancel it if any
00747       return false;
00748    }
00749    return start_service(service, urls, envs, startup_id.toLocal8Bit(), blind, false, msg);
00750 }
00751 
00752 bool
00753 KLauncher::start_service_by_desktop_path(const QString &serviceName, const QStringList &urls,
00754     const QStringList &envs, const QString& startup_id, bool blind, const QDBusMessage &msg)
00755 {
00756    KService::Ptr service;
00757    // Find service
00758    const QFileInfo fi(serviceName);
00759    if (fi.isAbsolute() && fi.exists())
00760    {
00761       // Full path
00762       service = new KService(serviceName);
00763    }
00764    else
00765    {
00766       service = KService::serviceByDesktopPath(serviceName);
00767       // TODO?
00768       //if (!service)
00769       //    service = KService::serviceByStorageId(serviceName); // This method should be named start_service_by_storage_id ideally...
00770    }
00771    if (!service)
00772    {
00773       requestResult.result = ENOENT;
00774       requestResult.error = i18n("Could not find service '%1'.", serviceName);
00775       cancel_service_startup_info( NULL, startup_id.toLocal8Bit(), envs ); // cancel it if any
00776       return false;
00777    }
00778    return start_service(service, urls, envs, startup_id.toLocal8Bit(), blind, false, msg);
00779 }
00780 
00781 bool
00782 KLauncher::start_service_by_desktop_name(const QString &serviceName, const QStringList &urls,
00783     const QStringList &envs, const QString& startup_id, bool blind, const QDBusMessage &msg)
00784 {
00785    KService::Ptr service = KService::serviceByDesktopName(serviceName);
00786    if (!service)
00787    {
00788       requestResult.result = ENOENT;
00789       requestResult.error = i18n("Could not find service '%1'.", serviceName);
00790       cancel_service_startup_info( NULL, startup_id.toLocal8Bit(), envs ); // cancel it if any
00791       return false;
00792    }
00793    return start_service(service, urls, envs, startup_id.toLocal8Bit(), blind, false, msg);
00794 }
00795 
00796 bool
00797 KLauncher::start_service(KService::Ptr service, const QStringList &_urls,
00798                          const QStringList &envs, const QByteArray &startup_id,
00799                          bool blind, bool autoStart, const QDBusMessage &msg)
00800 {
00801    QStringList urls = _urls;
00802    bool runPermitted = KDesktopFile::isAuthorizedDesktopFile(service->entryPath());
00803 
00804    if (!service->isValid() || !runPermitted)
00805    {
00806       requestResult.result = ENOEXEC;
00807       if (service->isValid())
00808          requestResult.error = i18n("Service '%1' must be executable to run.", service->entryPath());
00809       else
00810          requestResult.error = i18n("Service '%1' is malformatted.", service->entryPath());
00811       cancel_service_startup_info( NULL, startup_id, envs ); // cancel it if any
00812       return false;
00813    }
00814    KLaunchRequest *request = new KLaunchRequest;
00815    request->autoStart = autoStart;
00816 
00817    if ((urls.count() > 1) && !service->allowMultipleFiles())
00818    {
00819       // We need to launch the application N times. That sucks.
00820       // We ignore the result for application 2 to N.
00821       // For the first file we launch the application in the
00822       // usual way. The reported result is based on this
00823       // application.
00824       QStringList::ConstIterator it = urls.constBegin();
00825       for(++it;
00826           it != urls.constEnd();
00827           ++it)
00828       {
00829          QStringList singleUrl;
00830          singleUrl.append(*it);
00831          QByteArray startup_id2 = startup_id;
00832          if( !startup_id2.isEmpty() && startup_id2 != "0" )
00833              startup_id2 = "0"; // can't use the same startup_id several times // krazy:exclude=doublequote_chars
00834          start_service( service, singleUrl, envs, startup_id2, true, false, msg);
00835       }
00836       QString firstURL = *(urls.begin());
00837       urls.clear();
00838       urls.append(firstURL);
00839    }
00840    createArgs(request, service, urls);
00841 
00842    // We must have one argument at least!
00843    if (!request->arg_list.count())
00844    {
00845       requestResult.result = ENOEXEC;
00846       requestResult.error = i18n("Service '%1' is malformatted.", service->entryPath());
00847       delete request;
00848       cancel_service_startup_info( NULL, startup_id, envs );
00849       return false;
00850    }
00851 
00852    request->name = request->arg_list.takeFirst();
00853 
00854    if (request->name.endsWith(QLatin1String("/kioexec"))) {
00855        // Special case for kioexec; if createArgs said we were going to use it,
00856        // then we have to expect a kioexec-PID, not a org.kde.finalapp...
00857        // Testcase: konqueror www.kde.org, RMB on link, open with, kruler.
00858 
00859        request->dbus_startup_type = KService::DBusMulti;
00860        request->dbus_name = QString::fromLatin1("org.kde.kioexec");
00861    } else {
00862        request->dbus_startup_type = service->dbusStartupType();
00863 
00864        if ((request->dbus_startup_type == KService::DBusUnique) ||
00865            (request->dbus_startup_type == KService::DBusMulti)) {
00866            const QVariant v = service->property(QLatin1String("X-DBUS-ServiceName"));
00867            if (v.isValid()) {
00868                request->dbus_name = v.toString();
00869            }
00870            if (request->dbus_name.isEmpty()) {
00871                const QString binName = KRun::binaryName(service->exec(), true);
00872                request->dbus_name = QString::fromLatin1("org.kde.") + binName;
00873                request->tolerant_dbus_name = QString::fromLatin1("*.") + binName;
00874            }
00875        }
00876    }
00877 
00878 #ifdef KLAUNCHER_VERBOSE_OUTPUT
00879    kDebug(7016) << "name=" << request->name << "dbus_name=" << request->dbus_name
00880                 << "startup type=" << s_DBusStartupTypeToString[request->dbus_startup_type];
00881 #endif
00882 
00883    request->pid = 0;
00884    request->envs = envs;
00885    send_service_startup_info( request, service, startup_id, envs );
00886 
00887    // Request will be handled later.
00888    if (!blind && !autoStart)
00889    {
00890       msg.setDelayedReply(true);
00891       request->transaction = msg;
00892    }
00893    queueRequest(request);
00894    return true;
00895 }
00896 
00897 void
00898 KLauncher::send_service_startup_info( KLaunchRequest *request, KService::Ptr service, const QByteArray& startup_id,
00899     const QStringList &envs )
00900 {
00901 #ifdef Q_WS_X11
00902     request->startup_id = "0";// krazy:exclude=doublequote_chars
00903     if (startup_id == "0")
00904         return;
00905     bool silent;
00906     QByteArray wmclass;
00907     if( !KRun::checkStartupNotify( QString(), service.data(), &silent, &wmclass ))
00908         return;
00909     KStartupInfoId id;
00910     id.initId(startup_id);
00911     QByteArray dpy_str;
00912     foreach (const QString &env, envs) {
00913         if (env.startsWith(QLatin1String("DISPLAY=")))
00914             dpy_str = env.mid(8).toLocal8Bit();
00915     }
00916     Display* dpy = NULL;
00917     if (!dpy_str.isEmpty() && mCached_dpy != NULL && dpy_str != XDisplayString(mCached_dpy))
00918         dpy = mCached_dpy;
00919     if (dpy == NULL)
00920         dpy = XOpenDisplay(dpy_str);
00921     request->startup_id = id.id();
00922     if (dpy == NULL) {
00923         cancel_service_startup_info( request, startup_id, envs );
00924         return;
00925     }
00926 
00927     request->startup_dpy = dpy_str;
00928 
00929     KStartupInfoData data;
00930     data.setName( service->name());
00931     data.setIcon( service->icon());
00932     data.setDescription( i18n( "Launching %1" ,  service->name()));
00933     if( !wmclass.isEmpty())
00934         data.setWMClass( wmclass );
00935     if( silent )
00936         data.setSilent( KStartupInfoData::Yes );
00937     data.setApplicationId( service->entryPath());
00938     // the rest will be sent by kdeinit
00939     KStartupInfo::sendStartupX( dpy, id, data );
00940     if( mCached_dpy != dpy && mCached_dpy != NULL )
00941         XCloseDisplay( mCached_dpy );
00942     mCached_dpy = dpy;
00943     return;
00944 #else
00945     return;
00946 #endif
00947 }
00948 
00949 void
00950 KLauncher::cancel_service_startup_info( KLaunchRequest* request, const QByteArray& startup_id,
00951     const QStringList &envs )
00952 {
00953 #ifdef Q_WS_X11
00954     if( request != NULL )
00955         request->startup_id = "0"; // krazy:exclude=doublequote_chars
00956     if( !startup_id.isEmpty() && startup_id != "0" )
00957     {
00958         QString dpy_str;
00959         foreach (const QString &env, envs) {
00960             if (env.startsWith(QLatin1String("DISPLAY=")))
00961                 dpy_str = env.mid(8);
00962         }
00963         Display* dpy = NULL;
00964         if( !dpy_str.isEmpty() && mCached_dpy != NULL
00965             && dpy_str != QLatin1String(XDisplayString( mCached_dpy )) )
00966             dpy = mCached_dpy;
00967         if( dpy == NULL )
00968             dpy = XOpenDisplay( dpy_str.toLatin1().constData() );
00969         if( dpy == NULL )
00970             return;
00971         KStartupInfoId id;
00972         id.initId(startup_id);
00973         KStartupInfo::sendFinishX( dpy, id );
00974         if( mCached_dpy != dpy && mCached_dpy != NULL )
00975            XCloseDisplay( mCached_dpy );
00976         mCached_dpy = dpy;
00977     }
00978 #endif
00979 }
00980 
00981 bool
00982 KLauncher::kdeinit_exec(const QString &app, const QStringList &args,
00983                         const QString& workdir, const QStringList &envs,
00984                         const QString &startup_id, bool wait, const QDBusMessage &msg)
00985 {
00986    KLaunchRequest *request = new KLaunchRequest;
00987    request->autoStart = false;
00988    request->arg_list = args;
00989    request->name = app;
00990    if (wait)
00991       request->dbus_startup_type = KService::DBusWait;
00992    else
00993       request->dbus_startup_type = KService::DBusNone;
00994    request->pid = 0;
00995 #ifdef Q_WS_X11
00996    request->startup_id = startup_id.toLocal8Bit();
00997 #endif
00998    request->envs = envs;
00999    request->cwd = workdir;
01000 #ifdef Q_WS_X11
01001    if (!app.endsWith(QLatin1String("kbuildsycoca4"))) { // avoid stupid loop
01002        // Find service, if any - strip path if needed
01003        const QString desktopName = app.mid(app.lastIndexOf(QLatin1Char('/')) + 1);
01004        KService::Ptr service = KService::serviceByDesktopName(desktopName);
01005        if (service)
01006            send_service_startup_info(request, service,
01007                                      request->startup_id, envs);
01008        else // no .desktop file, no startup info
01009            cancel_service_startup_info(request, request->startup_id, envs);
01010    }
01011 #endif
01012    msg.setDelayedReply(true);
01013    request->transaction = msg;
01014    queueRequest(request);
01015    return true;
01016 }
01017 
01018 void
01019 KLauncher::queueRequest(KLaunchRequest *request)
01020 {
01021    requestQueue.append( request );
01022    if (!bProcessingQueue)
01023    {
01024       bProcessingQueue = true;
01025       QTimer::singleShot(0, this, SLOT( slotDequeue() ));
01026    }
01027 }
01028 
01029 void
01030 KLauncher::slotDequeue()
01031 {
01032    do {
01033       KLaunchRequest *request = requestQueue.takeFirst();
01034       // process request
01035       request->status = KLaunchRequest::Launching;
01036       requestStart(request);
01037       if (request->status != KLaunchRequest::Launching)
01038       {
01039          // Request handled.
01040 #ifdef KLAUNCHER_VERBOSE_OUTPUT
01041          kDebug(7016) << "Request handled already";
01042 #endif
01043          requestDone( request );
01044          continue;
01045       }
01046    } while(requestQueue.count());
01047    bProcessingQueue = false;
01048 }
01049 
01050 void
01051 KLauncher::createArgs( KLaunchRequest *request, const KService::Ptr service ,
01052                        const QStringList &urls)
01053 {
01054   const QStringList params = KRun::processDesktopExec(*service, urls);
01055 
01056   for(QStringList::ConstIterator it = params.begin();
01057       it != params.end(); ++it)
01058   {
01059      request->arg_list.append(*it);
01060   }
01061   request->cwd = service->path();
01062 }
01063 
01065 
01066 pid_t
01067 KLauncher::requestHoldSlave(const KUrl &url, const QString &app_socket)
01068 {
01069     IdleSlave *slave = 0;
01070     foreach (IdleSlave *p, mSlaveList)
01071     {
01072        if (p->onHold(url))
01073        {
01074           slave = p;
01075           break;
01076        }
01077     }
01078     if (slave)
01079     {
01080        mSlaveList.removeAll(slave);
01081        slave->connect(app_socket);
01082        return slave->pid();
01083     }
01084     return 0;
01085 }
01086 
01087 pid_t
01088 KLauncher::requestSlave(const QString &protocol,
01089                         const QString &host,
01090                         const QString &app_socket,
01091                         QString &error)
01092 {
01093     IdleSlave *slave = 0;
01094     foreach (IdleSlave *p, mSlaveList)
01095     {
01096        if (p->match(protocol, host, true))
01097        {
01098           slave = p;
01099           break;
01100        }
01101     }
01102     if (!slave)
01103     {
01104        foreach (IdleSlave *p, mSlaveList)
01105        {
01106           if (p->match(protocol, host, false))
01107           {
01108              slave = p;
01109              break;
01110           }
01111        }
01112     }
01113     if (!slave)
01114     {
01115        foreach (IdleSlave *p, mSlaveList)
01116        {
01117           if (p->match(protocol, QString(), false))
01118           {
01119              slave = p;
01120              break;
01121           }
01122        }
01123     }
01124     if (slave)
01125     {
01126        mSlaveList.removeAll(slave);
01127        slave->connect(app_socket);
01128        return slave->pid();
01129     }
01130 
01131     QString name = KProtocolInfo::exec(protocol);
01132     if (name.isEmpty())
01133     {
01134     error = i18n("Unknown protocol '%1'.\n", protocol);
01135         return 0;
01136     }
01137 
01138     QStringList arg_list;
01139 #ifdef USE_KPROCESS_FOR_KIOSLAVES
01140     arg_list << name;
01141     arg_list << protocol;
01142     arg_list << mConnectionServer.address();
01143     arg_list << app_socket;
01144     name = KStandardDirs::findExe(QLatin1String("kioslave"));
01145 #else
01146     QString arg1 = protocol;
01147     QString arg2 = mConnectionServer.address();
01148     QString arg3 = app_socket;
01149     arg_list.append(arg1);
01150     arg_list.append(arg2);
01151     arg_list.append(arg3);
01152 #endif
01153 
01154     kDebug(7016) << "KLauncher: launching new slave " << name << " with protocol=" << protocol
01155      << " args=" << arg_list << endl;
01156 
01157 #ifdef Q_OS_UNIX
01158     if (mSlaveDebug == protocol)
01159     {
01160 #ifndef USE_KPROCESS_FOR_KIOSLAVES
01161        klauncher_header request_header;
01162        request_header.cmd = LAUNCHER_DEBUG_WAIT;
01163        request_header.arg_length = 0;
01164        write(kdeinitSocket, &request_header, sizeof(request_header));
01165 #else
01166       name = QString::fromLatin1("gdb");
01167 #endif
01168     }
01169     if (mSlaveValgrind == protocol) {
01170 #ifndef USE_KPROCESS_FOR_KIOSLAVES // otherwise we've already done this
01171        KLibrary lib(name, KGlobal::mainComponent());
01172        arg_list.prepend(lib.fileName());
01173        arg_list.prepend(KStandardDirs::locate("exe", QString::fromLatin1("kioslave")));
01174 #endif
01175        name = QString::fromLatin1("valgrind");
01176 
01177        if (!mSlaveValgrindSkin.isEmpty()) {
01178            arg_list.prepend(QLatin1String("--tool=") + mSlaveValgrindSkin);
01179        } else
01180        arg_list.prepend(QLatin1String("--tool=memcheck"));
01181     }
01182 #endif
01183     KLaunchRequest *request = new KLaunchRequest;
01184     request->autoStart = false;
01185     request->name = name;
01186     request->arg_list =  arg_list;
01187     request->dbus_startup_type = KService::DBusNone;
01188     request->pid = 0;
01189 #ifdef Q_WS_X11
01190     request->startup_id = "0"; // krazy:exclude=doublequote_chars
01191 #endif
01192     request->status = KLaunchRequest::Launching;
01193     requestStart(request);
01194     pid_t pid = request->pid;
01195 
01196 //    kDebug(7016) << "Slave launched, pid = " << pid;
01197 
01198     // We don't care about this request any longer....
01199     requestDone(request);
01200     if (!pid)
01201     {
01202        error = i18n("Error loading '%1'.\n", name);
01203     }
01204     return pid;
01205 }
01206 
01207 void
01208 KLauncher::waitForSlave(int pid, const QDBusMessage &msg)
01209 {
01210     foreach (IdleSlave *slave, mSlaveList)
01211     {
01212         if (slave->pid() == static_cast<pid_t>(pid))
01213            return; // Already here.
01214     }
01215     SlaveWaitRequest *waitRequest = new SlaveWaitRequest;
01216     msg.setDelayedReply(true);
01217     waitRequest->transaction = msg;
01218     waitRequest->pid = static_cast<pid_t>(pid);
01219     mSlaveWaitRequest.append(waitRequest);
01220 }
01221 
01222 void
01223 KLauncher::acceptSlave()
01224 {
01225     IdleSlave *slave = new IdleSlave(this);
01226     mConnectionServer.setNextPendingConnection(&slave->mConn);
01227     mSlaveList.append(slave);
01228     connect(slave, SIGNAL(destroyed()), this, SLOT(slotSlaveGone()));
01229     connect(slave, SIGNAL(statusUpdate(IdleSlave *)),
01230            this, SLOT(slotSlaveStatus(IdleSlave *)));
01231     if (!mTimer.isActive())
01232     {
01233        mTimer.start(1000*10);
01234     }
01235 }
01236 
01237 void
01238 KLauncher::slotSlaveStatus(IdleSlave *slave)
01239 {
01240     QMutableListIterator<SlaveWaitRequest *> it(mSlaveWaitRequest);
01241     while(it.hasNext())
01242     {
01243        SlaveWaitRequest *waitRequest = it.next();
01244        if (waitRequest->pid == slave->pid())
01245        {
01246            QDBusConnection::sessionBus().send(waitRequest->transaction.createReply());
01247           it.remove();
01248           delete waitRequest;
01249        }
01250     }
01251 }
01252 
01253 void
01254 KLauncher::slotSlaveGone()
01255 {
01256     IdleSlave *slave = (IdleSlave *) sender();
01257     mSlaveList.removeAll(slave);
01258     if ((mSlaveList.count() == 0) && (mTimer.isActive()))
01259     {
01260        mTimer.stop();
01261     }
01262 }
01263 
01264 void
01265 KLauncher::idleTimeout()
01266 {
01267     bool keepOneFileSlave=true;
01268     time_t now = time(0);
01269     foreach (IdleSlave *slave, mSlaveList)
01270     {
01271         if ((slave->protocol()==QLatin1String("file")) && (keepOneFileSlave))
01272            keepOneFileSlave=false;
01273         else if (slave->age(now) > SLAVE_MAX_IDLE)
01274         {
01275            // killing idle slave
01276            delete slave;
01277         }
01278     }
01279 }
01280 
01281 void KLauncher::reparseConfiguration()
01282 {
01283    KProtocolManager::reparseConfiguration();
01284    foreach (IdleSlave *slave, mSlaveList)
01285       slave->reparseConfiguration();
01286 }
01287 
01288 
01289 void
01290 KLauncher::slotGotOutput()
01291 {
01292 #ifdef USE_KPROCESS_FOR_KIOSLAVES
01293   KProcess *p = static_cast<KProcess *>(sender());
01294   QByteArray _stdout = p->readAllStandardOutput();
01295   kDebug(7016) << _stdout.data();
01296 #endif
01297 }
01298 
01299 void
01300 KLauncher::slotFinished(int exitCode, QProcess::ExitStatus exitStatus )
01301 {
01302 #ifdef USE_KPROCESS_FOR_KIOSLAVES
01303     KProcess *p = static_cast<KProcess *>(sender());
01304     kDebug(7016) << "process finished exitcode=" << exitCode << "exitStatus=" << exitStatus;
01305 
01306     foreach (KLaunchRequest *request, requestList)
01307     {
01308         if (request->process == p)
01309         {
01310 #ifdef KLAUNCHER_VERBOSE_OUTPUT
01311             kDebug(7016) << "found KProcess, request done";
01312 #endif
01313             if (exitCode == 0  && exitStatus == QProcess::NormalExit)
01314                 request->status = KLaunchRequest::Done;
01315             else
01316                 request->status = KLaunchRequest::Error;
01317             requestDone(request);
01318             request->process = 0;
01319         }
01320     }
01321     delete p;
01322 #else
01323    Q_UNUSED(exitCode);
01324    Q_UNUSED(exitStatus);
01325 #endif
01326 }
01327 
01328 
01329 void KLauncher::terminate_kdeinit()
01330 {
01331     kDebug(7016);
01332 #ifndef USE_KPROCESS_FOR_KIOSLAVES
01333     klauncher_header request_header;
01334     request_header.cmd = LAUNCHER_TERMINATE_KDEINIT;
01335     request_header.arg_length = 0;
01336     write(kdeinitSocket, &request_header, sizeof(request_header));
01337 #endif
01338 }
01339 
01340 #include "klauncher.moc"

KInit

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

kdelibs

Skip menu "kdelibs"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • Kate
  • 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
Generated for kdelibs by doxygen 1.7.3
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal