• Skip to content
  • Skip to link menu
KDE 3.5 API Reference
  • KDE API Reference
  • API Reference
  • Sitemap
  • 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 #ifdef HAVE_CONFIG_H
00020 #include <config.h>
00021 #endif
00022 
00023 #include <stdio.h>
00024 #include <unistd.h>
00025 #include <stdlib.h>
00026 #include <errno.h>
00027 #include <signal.h>
00028 #include <sys/time.h>
00029 
00030 #include <qfile.h>
00031 
00032 #include <kconfig.h>
00033 #include <kdebug.h>
00034 #include <klibloader.h>
00035 #include <klocale.h>
00036 #include <kprotocolmanager.h>
00037 #include <kprotocolinfo.h>
00038 #include <krun.h>
00039 #include <kstandarddirs.h>
00040 #include <ktempfile.h>
00041 #include <kurl.h>
00042 
00043 #if defined Q_WS_X11 && ! defined K_WS_QTONLY
00044 #include <kstartupinfo.h> // schroder
00045 #endif
00046 
00047 
00048 #include "kio/global.h"
00049 #include "kio/connection.h"
00050 #include "kio/slaveinterface.h"
00051 
00052 #include "klauncher.h"
00053 #include "klauncher_cmds.h"
00054 
00055 //#if defined Q_WS_X11 && ! defined K_WS_QTONLY
00056 #ifdef Q_WS_X11
00057 //#undef K_WS_QTONLY
00058 #include <X11/Xlib.h> // schroder
00059 #endif
00060 
00061 // Dispose slaves after being idle for SLAVE_MAX_IDLE seconds
00062 #define SLAVE_MAX_IDLE  30
00063 
00064 using namespace KIO;
00065 
00066 template class QPtrList<KLaunchRequest>;
00067 template class QPtrList<IdleSlave>;
00068 
00069 IdleSlave::IdleSlave(KSocket *socket)
00070 {
00071    mConn.init(socket);
00072    mConn.connect(this, SLOT(gotInput()));
00073    mConn.send( CMD_SLAVE_STATUS );
00074    mPid = 0;
00075    mBirthDate = time(0);
00076    mOnHold = false;
00077 }
00078 
00079 void
00080 IdleSlave::gotInput()
00081 {
00082    int cmd;
00083    QByteArray data;
00084    if (mConn.read( &cmd, data) == -1)
00085    {
00086       // Communication problem with slave.
00087       kdError(7016) << "SlavePool: No communication with slave." << endl;
00088       delete this;
00089    }
00090    else if (cmd == MSG_SLAVE_ACK)
00091    {
00092       delete this;
00093    }
00094    else if (cmd != MSG_SLAVE_STATUS)
00095    {
00096       kdError(7016) << "SlavePool: Unexpected data from slave." << endl;
00097       delete this;
00098    }
00099    else
00100    {
00101       QDataStream stream( data, IO_ReadOnly );
00102       pid_t pid;
00103       QCString protocol;
00104       QString host;
00105       Q_INT8 b;
00106       stream >> pid >> protocol >> host >> b;
00107 // Overload with (bool) onHold, (KURL) url.
00108       if (!stream.atEnd())
00109       {
00110          KURL url;
00111          stream >> url;
00112          mOnHold = true;
00113          mUrl = url;
00114       }
00115 
00116       mPid = pid;
00117       mConnected = (b != 0);
00118       mProtocol = protocol;
00119       mHost = host;
00120       emit statusUpdate(this);
00121    }
00122 }
00123 
00124 void
00125 IdleSlave::connect(const QString &app_socket)
00126 {
00127    QByteArray data;
00128    QDataStream stream( data, IO_WriteOnly);
00129    stream << app_socket;
00130    mConn.send( CMD_SLAVE_CONNECT, data );
00131    // Timeout!
00132 }
00133 
00134 void
00135 IdleSlave::reparseConfiguration()
00136 {
00137    mConn.send( CMD_REPARSECONFIGURATION );
00138 }
00139 
00140 bool
00141 IdleSlave::match(const QString &protocol, const QString &host, bool connected)
00142 {
00143    if (mOnHold) return false;
00144    if (protocol != mProtocol) return false;
00145    if (host.isEmpty()) return true;
00146    if (host != mHost) return false;
00147    if (!connected) return true;
00148    if (!mConnected) return false;
00149    return true;
00150 }
00151 
00152 bool
00153 IdleSlave::onHold(const KURL &url)
00154 {
00155    if (!mOnHold) return false;
00156    return (url == mUrl);
00157 }
00158 
00159 int
00160 IdleSlave::age(time_t now)
00161 {
00162    return (int) difftime(now, mBirthDate);
00163 }
00164 
00165 KLauncher::KLauncher(int _kdeinitSocket, bool new_startup)
00166   : KApplication( false, false ), // No Styles, No GUI
00167     DCOPObject("klauncher"),
00168     kdeinitSocket(_kdeinitSocket), mAutoStart( new_startup ),
00169     dontBlockReading(false), newStartup( new_startup )
00170 {
00171 #ifdef Q_WS_X11
00172    mCached_dpy = NULL;
00173 #endif
00174    connect(&mAutoTimer, SIGNAL(timeout()), this, SLOT(slotAutoStart()));
00175    requestList.setAutoDelete(true);
00176    mSlaveWaitRequest.setAutoDelete(true);
00177    dcopClient()->setNotifications( true );
00178    connect(dcopClient(), SIGNAL( applicationRegistered( const QCString &)),
00179            this, SLOT( slotAppRegistered( const QCString &)));
00180    dcopClient()->connectDCOPSignal( "DCOPServer", "", "terminateKDE()",
00181                                     objId(), "terminateKDE()", false );
00182 
00183    QString prefix = locateLocal("socket", "klauncher");
00184    KTempFile domainname(prefix, QString::fromLatin1(".slave-socket"));
00185    if (domainname.status() != 0)
00186    {
00187       // Sever error!
00188       qDebug("KLauncher: Fatal error, can't create tempfile!");
00189       ::exit(1);
00190    }
00191    mPoolSocketName = domainname.name();
00192 #ifdef __CYGWIN__
00193    domainname.close();
00194    domainname.unlink();
00195 #endif
00196    mPoolSocket = new KServerSocket(QFile::encodeName(mPoolSocketName));
00197    connect(mPoolSocket, SIGNAL(accepted( KSocket *)),
00198            SLOT(acceptSlave(KSocket *)));
00199 
00200    connect(&mTimer, SIGNAL(timeout()), SLOT(idleTimeout()));
00201 
00202    kdeinitNotifier = new QSocketNotifier(kdeinitSocket, QSocketNotifier::Read);
00203    connect(kdeinitNotifier, SIGNAL( activated( int )),
00204            this, SLOT( slotKDEInitData( int )));
00205    kdeinitNotifier->setEnabled( true );
00206    lastRequest = 0;
00207    bProcessingQueue = false;
00208 
00209    mSlaveDebug = getenv("KDE_SLAVE_DEBUG_WAIT");
00210    if (!mSlaveDebug.isEmpty())
00211    {
00212       qWarning("Klauncher running in slave-debug mode for slaves of protocol '%s'", mSlaveDebug.data());
00213    }
00214    mSlaveValgrind = getenv("KDE_SLAVE_VALGRIND");
00215    if (!mSlaveValgrind.isEmpty())
00216    {
00217       mSlaveValgrindSkin = getenv("KDE_SLAVE_VALGRIND_SKIN");
00218       qWarning("Klauncher running slaves through valgrind for slaves of protocol '%s'", mSlaveValgrind.data());
00219    }
00220    klauncher_header request_header;
00221    request_header.cmd = LAUNCHER_OK;
00222    request_header.arg_length = 0;
00223    write(kdeinitSocket, &request_header, sizeof(request_header));
00224 }
00225 
00226 KLauncher::~KLauncher()
00227 {
00228    close();
00229 }
00230 
00231 void KLauncher::close()
00232 {
00233    if (!mPoolSocketName.isEmpty())
00234    {
00235       QCString filename = QFile::encodeName(mPoolSocketName);
00236       unlink(filename.data());
00237    }
00238 #if defined Q_WS_X11 && ! defined K_WS_QTONLY
00239 //#ifdef Q_WS_X11
00240    if( mCached_dpy != NULL )
00241        XCloseDisplay( mCached_dpy );
00242 #endif
00243 }
00244 
00245 void
00246 KLauncher::destruct(int exit_code)
00247 {
00248    if (kapp) ((KLauncher*)kapp)->close();
00249    // We don't delete kapp here, that's intentional.
00250    ::exit(exit_code);
00251 }
00252 
00253 bool
00254 KLauncher::process(const QCString &fun, const QByteArray &data,
00255                    QCString &replyType, QByteArray &replyData)
00256 {
00257    if ((fun == "exec_blind(QCString,QValueList<QCString>)")
00258        || (fun == "exec_blind(QCString,QValueList<QCString>,QValueList<QCString>,QCString)"))
00259    {
00260       QDataStream stream(data, IO_ReadOnly);
00261       replyType = "void";
00262       QCString name;
00263       QValueList<QCString> arg_list;
00264       QCString startup_id = "0";
00265       QValueList<QCString> envs;
00266       stream >> name >> arg_list;
00267       if( fun == "exec_blind(QCString,QValueList<QCString>,QValueList<QCString>,QCString)" )
00268           stream >> envs >> startup_id;
00269       kdDebug(7016) << "KLauncher: Got exec_blind('" << name << "', ...)" << endl;
00270       exec_blind( name, arg_list, envs, startup_id);
00271       return true;
00272    }
00273    if ((fun == "start_service_by_name(QString,QStringList)") ||
00274        (fun == "start_service_by_desktop_path(QString,QStringList)")||
00275        (fun == "start_service_by_desktop_name(QString,QStringList)")||
00276        (fun == "kdeinit_exec(QString,QStringList)") ||
00277        (fun == "kdeinit_exec_wait(QString,QStringList)") ||
00278        (fun == "start_service_by_name(QString,QStringList,QValueList<QCString>,QCString)") ||
00279        (fun == "start_service_by_desktop_path(QString,QStringList,QValueList<QCString>,QCString)")||
00280        (fun == "start_service_by_desktop_name(QString,QStringList,QValueList<QCString>,QCString)") ||
00281        (fun == "start_service_by_name(QString,QStringList,QValueList<QCString>,QCString,bool)") ||
00282        (fun == "start_service_by_desktop_path(QString,QStringList,QValueList<QCString>,QCString,bool)")||
00283        (fun == "start_service_by_desktop_name(QString,QStringList,QValueList<QCString>,QCString,bool)") ||
00284        (fun == "kdeinit_exec(QString,QStringList,QValueList<QCString>)") ||
00285        (fun == "kdeinit_exec_wait(QString,QStringList,QValueList<QCString>)") ||
00286        (fun == "kdeinit_exec(QString,QStringList,QValueList<QCString>,QCString)") ||
00287        (fun == "kdeinit_exec_wait(QString,QStringList,QValueList<QCString>,QCString)"))
00288    {
00289       QDataStream stream(data, IO_ReadOnly);
00290       bool bNoWait = false;
00291       QString serviceName;
00292       QStringList urls;
00293       QValueList<QCString> envs;
00294       QCString startup_id = "";
00295       DCOPresult.result = -1;
00296       DCOPresult.dcopName = 0;
00297       DCOPresult.error = QString::null;
00298       DCOPresult.pid = 0;
00299       stream >> serviceName >> urls;
00300       if ((fun == "start_service_by_name(QString,QStringList,QValueList<QCString>,QCString,bool)") ||
00301           (fun == "start_service_by_desktop_path(QString,QStringList,QValueList<QCString>,QCString,bool)")||
00302           (fun == "start_service_by_desktop_name(QString,QStringList,QValueList<QCString>,QCString,bool)"))
00303          stream >> envs >> startup_id >> bNoWait;
00304       else if ((fun == "start_service_by_name(QString,QStringList,QValueList<QCString>,QCString)") ||
00305           (fun == "start_service_by_desktop_path(QString,QStringList,QValueList<QCString>,QCString)")||
00306           (fun == "start_service_by_desktop_name(QString,QStringList,QValueList<QCString>,QCString)"))
00307          stream >> envs >> startup_id;
00308       else if ((fun == "kdeinit_exec(QString,QStringList,QValueList<QCString>)") ||
00309           (fun == "kdeinit_exec_wait(QString,QStringList,QValueList<QCString>)"))
00310          stream >> envs;
00311       else if ((fun == "kdeinit_exec(QString,QStringList,QValueList<QCString>,QCString)") ||
00312           (fun == "kdeinit_exec_wait(QString,QStringList,QValueList<QCString>,QCString)"))
00313          stream >> envs >> startup_id;
00314       bool finished;
00315       if (strncmp(fun, "start_service_by_name(", 22) == 0)
00316       {
00317          kdDebug(7016) << "KLauncher: Got start_service_by_name('" << serviceName << "', ...)" << endl;
00318          finished = start_service_by_name(serviceName, urls, envs, startup_id, bNoWait);
00319       }
00320       else if (strncmp(fun, "start_service_by_desktop_path(", 30) == 0)
00321       {
00322          kdDebug(7016) << "KLauncher: Got start_service_by_desktop_path('" << serviceName << "', ...)" << endl;
00323          finished = start_service_by_desktop_path(serviceName, urls, envs, startup_id, bNoWait);
00324       }
00325       else if (strncmp(fun, "start_service_by_desktop_name(", 30) == 0)
00326       {
00327          kdDebug(7016) << "KLauncher: Got start_service_by_desktop_name('" << serviceName << "', ...)" << endl;
00328          finished = start_service_by_desktop_name(serviceName, urls, envs, startup_id, bNoWait );
00329       }
00330       else if ((fun == "kdeinit_exec(QString,QStringList)")
00331               || (fun == "kdeinit_exec(QString,QStringList,QValueList<QCString>)")
00332               || (fun == "kdeinit_exec(QString,QStringList,QValueList<QCString>,QCString)"))
00333       {
00334          kdDebug(7016) << "KLauncher: Got kdeinit_exec('" << serviceName << "', ...)" << endl;
00335          finished = kdeinit_exec(serviceName, urls, envs, startup_id, false);
00336       }
00337       else
00338       {
00339          kdDebug(7016) << "KLauncher: Got kdeinit_exec_wait('" << serviceName << "', ...)" << endl;
00340          finished = kdeinit_exec(serviceName, urls, envs, startup_id, true);
00341       }
00342       if (!finished)
00343       {
00344          replyType = "serviceResult";
00345          QDataStream stream2(replyData, IO_WriteOnly);
00346          stream2 << DCOPresult.result << DCOPresult.dcopName << DCOPresult.error << DCOPresult.pid;
00347       }
00348       return true;
00349    }
00350    else if (fun == "requestSlave(QString,QString,QString)")
00351    {
00352       QDataStream stream(data, IO_ReadOnly);
00353       QString protocol;
00354       QString host;
00355       QString app_socket;
00356       stream >> protocol >> host >> app_socket;
00357       replyType = "QString";
00358       QString error;
00359       pid_t pid = requestSlave(protocol, host, app_socket, error);
00360       QDataStream stream2(replyData, IO_WriteOnly);
00361       stream2 << pid << error;
00362       return true;
00363    }
00364    else if (fun == "requestHoldSlave(KURL,QString)")
00365    {
00366       QDataStream stream(data, IO_ReadOnly);
00367       KURL url;
00368       QString app_socket;
00369       stream >> url >> app_socket;
00370       replyType = "pid_t";
00371       pid_t pid = requestHoldSlave(url, app_socket);
00372       QDataStream stream2(replyData, IO_WriteOnly);
00373       stream2 << pid;
00374       return true;
00375    }
00376    else if (fun == "waitForSlave(pid_t)")
00377    {
00378       QDataStream stream(data, IO_ReadOnly);
00379       pid_t pid;
00380       stream >> pid;
00381       waitForSlave(pid);
00382       replyType = "void";
00383       return true;
00384 
00385    }
00386    else if (fun == "setLaunchEnv(QCString,QCString)")
00387    {
00388       QDataStream stream(data, IO_ReadOnly);
00389       QCString name;
00390       QCString value;
00391       stream >> name >> value;
00392       setLaunchEnv(name, value);
00393       replyType = "void";
00394       return true;
00395    }
00396    else if (fun == "reparseConfiguration()")
00397    {
00398       KGlobal::config()->reparseConfiguration();
00399       kdDebug(7016) << "KLauncher::process : reparseConfiguration" << endl;
00400       KProtocolManager::reparseConfiguration();
00401       IdleSlave *slave;
00402       for(slave = mSlaveList.first(); slave; slave = mSlaveList.next())
00403           slave->reparseConfiguration();
00404       replyType = "void";
00405       return true;
00406    }
00407    else if (fun == "terminateKDE()")
00408    {
00409       ::signal( SIGHUP, SIG_IGN);
00410       ::signal( SIGTERM, SIG_IGN);
00411       kdDebug() << "KLauncher::process ---> terminateKDE" << endl;
00412       klauncher_header request_header;
00413       request_header.cmd = LAUNCHER_TERMINATE_KDE;
00414       request_header.arg_length = 0;
00415       write(kdeinitSocket, &request_header, sizeof(request_header));
00416       destruct(0);
00417    }
00418    else if (fun == "autoStart()")
00419    {
00420       kdDebug() << "KLauncher::process ---> autoStart" << endl;
00421       autoStart(1);
00422       replyType = "void";
00423       return true;
00424    }
00425    else if (fun == "autoStart(int)")
00426    {
00427       kdDebug() << "KLauncher::process ---> autoStart(int)" << endl;
00428       QDataStream stream(data, IO_ReadOnly);
00429       int phase;
00430       stream >> phase;
00431       autoStart(phase);
00432       replyType = "void";
00433       return true;
00434    }
00435 
00436    if (DCOPObject::process(fun, data, replyType, replyData))
00437    {
00438       return true;
00439    }
00440    kdWarning(7016) << "Got unknown DCOP function: " << fun << endl;
00441    return false;
00442 }
00443 
00444 QCStringList
00445 KLauncher::interfaces()
00446 {
00447     QCStringList ifaces = DCOPObject::interfaces();
00448     ifaces += "KLauncher";
00449     return ifaces;
00450 }
00451 
00452 QCStringList
00453 KLauncher::functions()
00454 {
00455     QCStringList funcs = DCOPObject::functions();
00456     funcs << "void exec_blind(QCString,QValueList<QCString>)";
00457     funcs << "void exec_blind(QCString,QValueList<QCString>,QValueList<QCString>,QCString)";
00458     funcs << "serviceResult start_service_by_name(QString,QStringList)";
00459     funcs << "serviceResult start_service_by_desktop_path(QString,QStringList)";
00460     funcs << "serviceResult start_service_by_desktop_name(QString,QStringList)";
00461     funcs << "serviceResult kdeinit_exec(QString,QStringList)";
00462     funcs << "serviceResult kdeinit_exec_wait(QString,QStringList)";
00463     funcs << "serviceResult start_service_by_name(QString,QStringList,QValueList<QCString>,QCString)";
00464     funcs << "serviceResult start_service_by_desktop_path(QString,QStringList,QValueList<QCString>,QCString)";
00465     funcs << "serviceResult start_service_by_desktop_name(QString,QStringList,QValueList<QCString>,QCString)";
00466     funcs << "serviceResult start_service_by_name(QString,QStringList,QValueList<QCString>,QCString,bool)";
00467     funcs << "serviceResult start_service_by_desktop_path(QString,QStringList,QValueList<QCString>,QCString,bool)";
00468     funcs << "serviceResult start_service_by_desktop_name(QString,QStringList,QValueList<QCString>,QCString,bool)";
00469     funcs << "serviceResult kdeinit_exec(QString,QStringList,QValueList<QCString>)";
00470     funcs << "serviceResult kdeinit_exec_wait(QString,QStringList,QValueList<QCString>)";
00471     funcs << "QString requestSlave(QString,QString,QString)";
00472     funcs << "pid_t requestHoldSlave(KURL,QString)";
00473     funcs << "void waitForSlave(pid_t)";
00474     funcs << "void setLaunchEnv(QCString,QCString)";
00475     funcs << "void reparseConfiguration()";
00476 //    funcs << "void terminateKDE()";
00477     funcs << "void autoStart()";
00478     funcs << "void autoStart(int)";
00479     return funcs;
00480 }
00481 
00482 void KLauncher::setLaunchEnv(const QCString &name, const QCString &_value)
00483 {
00484    QCString value(_value);
00485    if (value.isNull())
00486       value = "";
00487    klauncher_header request_header;
00488    QByteArray requestData(name.length()+value.length()+2);
00489    memcpy(requestData.data(), name.data(), name.length()+1);
00490    memcpy(requestData.data()+name.length()+1, value.data(), value.length()+1);
00491    request_header.cmd = LAUNCHER_SETENV;
00492    request_header.arg_length = requestData.size();
00493    write(kdeinitSocket, &request_header, sizeof(request_header));
00494    write(kdeinitSocket, requestData.data(), request_header.arg_length);
00495 }
00496 
00497 /*
00498  * Read 'len' bytes from 'sock' into buffer.
00499  * returns -1 on failure, 0 on no data.
00500  */
00501 static int
00502 read_socket(int sock, char *buffer, int len)
00503 {
00504   ssize_t result;
00505   int bytes_left = len;
00506   while ( bytes_left > 0)
00507   {
00508      result = read(sock, buffer, bytes_left);
00509      if (result > 0)
00510      {
00511         buffer += result;
00512         bytes_left -= result;
00513      }
00514      else if (result == 0)
00515         return -1;
00516      else if ((result == -1) && (errno != EINTR))
00517         return -1;
00518   }
00519   return 0;
00520 }
00521 
00522 
00523 void
00524 KLauncher::slotKDEInitData(int)
00525 {
00526    klauncher_header request_header;
00527    QByteArray requestData;
00528    if( dontBlockReading )
00529    {
00530    // in case we get a request to start an application and data arrive
00531    // to kdeinitSocket at the same time, requestStart() will already
00532    // call slotKDEInitData(), so we must check there's still something
00533    // to read, otherwise this would block
00534       fd_set in;
00535       timeval tm = { 0, 0 };
00536       FD_ZERO ( &in );
00537       FD_SET( kdeinitSocket, &in );
00538       select( kdeinitSocket + 1, &in, 0, 0, &tm );
00539       if( !FD_ISSET( kdeinitSocket, &in ))
00540          return;
00541    }
00542    dontBlockReading = false;
00543    int result = read_socket(kdeinitSocket, (char *) &request_header,
00544                             sizeof( request_header));
00545    if (result == -1)
00546    {
00547       kdDebug() << "Exiting on read_socket errno: " << errno << endl;
00548       ::signal( SIGHUP, SIG_IGN);
00549       ::signal( SIGTERM, SIG_IGN);
00550       destruct(255); // Exit!
00551    }
00552    requestData.resize(request_header.arg_length);
00553    result = read_socket(kdeinitSocket, (char *) requestData.data(),
00554                         request_header.arg_length);
00555 
00556    if (request_header.cmd == LAUNCHER_DIED)
00557    {
00558      long *request_data;
00559      request_data = (long *) requestData.data();
00560      processDied(request_data[0], request_data[1]);
00561      return;
00562    }
00563    if (lastRequest && (request_header.cmd == LAUNCHER_OK))
00564    {
00565      long *request_data;
00566      request_data = (long *) requestData.data();
00567      lastRequest->pid = (pid_t) (*request_data);
00568      kdDebug(7016) << lastRequest->name << " (pid " << lastRequest->pid <<
00569         ") up and running." << endl;
00570      switch(lastRequest->dcop_service_type)
00571      {
00572        case KService::DCOP_None:
00573        {
00574          lastRequest->status = KLaunchRequest::Running;
00575          break;
00576        }
00577 
00578        case KService::DCOP_Unique:
00579        {
00580          lastRequest->status = KLaunchRequest::Launching;
00581          break;
00582        }
00583 
00584        case KService::DCOP_Wait:
00585        {
00586          lastRequest->status = KLaunchRequest::Launching;
00587          break;
00588        }
00589 
00590        case KService::DCOP_Multi:
00591        {
00592          lastRequest->status = KLaunchRequest::Launching;
00593          break;
00594        }
00595      }
00596      lastRequest = 0;
00597      return;
00598    }
00599    if (lastRequest && (request_header.cmd == LAUNCHER_ERROR))
00600    {
00601      lastRequest->status = KLaunchRequest::Error;
00602      if (!requestData.isEmpty())
00603         lastRequest->errorMsg = QString::fromUtf8((char *) requestData.data());
00604      lastRequest = 0;
00605      return;
00606    }
00607 
00608    kdWarning(7016) << "Unexpected command from KDEInit (" << (unsigned int) request_header.cmd
00609                  << ")" << endl;
00610 }
00611 
00612 void
00613 KLauncher::processDied(pid_t pid, long /* exitStatus */)
00614 {
00615    KLaunchRequest *request = requestList.first();
00616    for(; request; request = requestList.next())
00617    {
00618       if (request->pid == pid)
00619       {
00620          if (request->dcop_service_type == KService::DCOP_Wait)
00621             request->status = KLaunchRequest::Done;
00622          else if ((request->dcop_service_type == KService::DCOP_Unique) &&
00623         (dcopClient()->isApplicationRegistered(request->dcop_name)))
00624             request->status = KLaunchRequest::Running;
00625          else
00626             request->status = KLaunchRequest::Error;
00627          requestDone(request);
00628          return;
00629       }
00630    }
00631 }
00632 
00633 void
00634 KLauncher::slotAppRegistered(const QCString &appId)
00635 {
00636    const char *cAppId = appId.data();
00637    if (!cAppId) return;
00638 
00639    KLaunchRequest *request = requestList.first();
00640    KLaunchRequest *nextRequest;
00641    for(; request; request = nextRequest)
00642    {
00643       nextRequest = requestList.next();
00644       if (request->status != KLaunchRequest::Launching)
00645          continue;
00646 
00647       // For unique services check the requested service name first
00648       if ((request->dcop_service_type == KService::DCOP_Unique) &&
00649           ((appId == request->dcop_name) ||
00650            dcopClient()->isApplicationRegistered(request->dcop_name)))
00651       {
00652          request->status = KLaunchRequest::Running;
00653          requestDone(request);
00654          continue;
00655       }
00656 
00657       const char *rAppId = request->dcop_name.data();
00658       if (!rAppId) continue;
00659 
00660       int l = strlen(rAppId);
00661       if ((strncmp(rAppId, cAppId, l) == 0) &&
00662           ((cAppId[l] == '\0') || (cAppId[l] == '-')))
00663       {
00664          request->dcop_name = appId;
00665          request->status = KLaunchRequest::Running;
00666          requestDone(request);
00667          continue;
00668       }
00669    }
00670 }
00671 
00672 void
00673 KLauncher::autoStart(int phase)
00674 {
00675    if( mAutoStart.phase() >= phase )
00676        return;
00677    mAutoStart.setPhase(phase);
00678    if( newStartup )
00679    {
00680       if (phase == 0)
00681          mAutoStart.loadAutoStartList();
00682    }
00683    else
00684    {
00685       if (phase == 1)
00686          mAutoStart.loadAutoStartList();
00687    }
00688    mAutoTimer.start(0, true);
00689 }
00690 
00691 void
00692 KLauncher::slotAutoStart()
00693 {
00694    KService::Ptr s;
00695    do
00696    {
00697       QString service = mAutoStart.startService();
00698       if (service.isEmpty())
00699       {
00700          // Done
00701      if( !mAutoStart.phaseDone())
00702      {
00703         mAutoStart.setPhaseDone();
00704         // Emit signal
00705             if( newStartup )
00706             {
00707            QCString autoStartSignal;
00708                autoStartSignal.sprintf( "autoStart%dDone()", mAutoStart.phase());
00709                emitDCOPSignal(autoStartSignal, QByteArray());
00710             }
00711             else
00712             {
00713            QCString autoStartSignal( "autoStartDone()" );
00714            int phase = mAutoStart.phase();
00715            if ( phase > 1 )
00716                autoStartSignal.sprintf( "autoStart%dDone()", phase );
00717                emitDCOPSignal(autoStartSignal, QByteArray());
00718             }
00719      }
00720          return;
00721       }
00722       s = new KService(service);
00723    }
00724    while (!start_service(s, QStringList(), QValueList<QCString>(), "0", false, true));
00725    // Loop till we find a service that we can start.
00726 }
00727 
00728 void
00729 KLauncher::requestDone(KLaunchRequest *request)
00730 {
00731    if ((request->status == KLaunchRequest::Running) ||
00732        (request->status == KLaunchRequest::Done))
00733    {
00734       DCOPresult.result = 0;
00735       DCOPresult.dcopName = request->dcop_name;
00736       DCOPresult.error = QString::null;
00737       DCOPresult.pid = request->pid;
00738    }
00739    else
00740    {
00741       DCOPresult.result = 1;
00742       DCOPresult.dcopName = "";
00743       DCOPresult.error = i18n("KDEInit could not launch '%1'.").arg(request->name);
00744       if (!request->errorMsg.isEmpty())
00745          DCOPresult.error += ":\n" + request->errorMsg;
00746       DCOPresult.pid = 0;
00747 
00748 #if defined Q_WS_X11 && ! defined K_WS_QTONLY
00749 //#ifdef Q_WS_X11
00750       if (!request->startup_dpy.isEmpty())
00751       {
00752          Display* dpy = NULL;
00753          if( (mCached_dpy != NULL) &&
00754               (request->startup_dpy == XDisplayString( mCached_dpy )))
00755             dpy = mCached_dpy;
00756          if( dpy == NULL )
00757             dpy = XOpenDisplay( request->startup_dpy );
00758          if( dpy )
00759          {
00760             KStartupInfoId id;
00761             id.initId( request->startup_id );
00762             KStartupInfo::sendFinishX( dpy, id );
00763             if( mCached_dpy != dpy && mCached_dpy != NULL )
00764                XCloseDisplay( mCached_dpy );
00765             mCached_dpy = dpy;
00766          }
00767       }
00768 #endif
00769    }
00770 
00771    if (request->autoStart)
00772    {
00773       mAutoTimer.start(0, true);
00774    }
00775 
00776    if (request->transaction)
00777    {
00778       QByteArray replyData;
00779       QCString replyType;
00780       replyType = "serviceResult";
00781       QDataStream stream2(replyData, IO_WriteOnly);
00782       stream2 << DCOPresult.result << DCOPresult.dcopName << DCOPresult.error << DCOPresult.pid;
00783       dcopClient()->endTransaction( request->transaction,
00784                                     replyType, replyData);
00785    }
00786    requestList.removeRef( request );
00787 }
00788 
00789 void
00790 KLauncher::requestStart(KLaunchRequest *request)
00791 {
00792    requestList.append( request );
00793    // Send request to kdeinit.
00794    klauncher_header request_header;
00795    QByteArray requestData;
00796    int length = 0;
00797    length += sizeof(long); // Nr of. Args
00798    length += request->name.length() + 1; // Cmd
00799    for(QValueList<QCString>::Iterator it = request->arg_list.begin();
00800        it != request->arg_list.end();
00801        it++)
00802    {
00803       length += (*it).length() + 1; // Args...
00804    }
00805    length += sizeof(long); // Nr of. envs
00806    for(QValueList<QCString>::ConstIterator it = request->envs.begin();
00807        it != request->envs.end();
00808        it++)
00809    {
00810       length += (*it).length() + 1; // Envs...
00811    }
00812    length += sizeof( long ); // avoid_loops
00813 #ifdef Q_WS_X11
00814    bool startup_notify = !request->startup_id.isNull() && request->startup_id != "0";
00815    if( startup_notify )
00816        length += request->startup_id.length() + 1;
00817 #endif
00818    if (!request->cwd.isEmpty())
00819        length += request->cwd.length() + 1;
00820 
00821    requestData.resize( length );
00822 
00823    char *p = requestData.data();
00824    long l = request->arg_list.count()+1;
00825    memcpy(p, &l, sizeof(long));
00826    p += sizeof(long);
00827    strcpy(p, request->name.data());
00828    p += strlen(p) + 1;
00829    for(QValueList<QCString>::Iterator it = request->arg_list.begin();
00830        it != request->arg_list.end();
00831        it++)
00832    {
00833       strcpy(p, (*it).data());
00834       p += strlen(p) + 1;
00835    }
00836    l = request->envs.count();
00837    memcpy(p, &l, sizeof(long));
00838    p += sizeof(long);
00839    for(QValueList<QCString>::ConstIterator it = request->envs.begin();
00840        it != request->envs.end();
00841        it++)
00842    {
00843       strcpy(p, (*it).data());
00844       p += strlen(p) + 1;
00845    }
00846    l = 0; // avoid_loops, always false here
00847    memcpy(p, &l, sizeof(long));
00848    p += sizeof(long);
00849 #ifdef Q_WS_X11
00850    if( startup_notify )
00851    {
00852       strcpy(p, request->startup_id.data());
00853       p += strlen( p ) + 1;
00854    }
00855 #endif
00856    if (!request->cwd.isEmpty())
00857    {
00858       strcpy(p, request->cwd.data());
00859       p += strlen( p ) + 1;
00860    }
00861 #ifdef Q_WS_X11
00862    request_header.cmd = startup_notify ? LAUNCHER_EXT_EXEC : LAUNCHER_EXEC_NEW;
00863 #else
00864    request_header.cmd = LAUNCHER_EXEC_NEW;
00865 #endif
00866    request_header.arg_length = length;
00867    write(kdeinitSocket, &request_header, sizeof(request_header));
00868    write(kdeinitSocket, requestData.data(), request_header.arg_length);
00869 
00870    // Wait for pid to return.
00871    lastRequest = request;
00872    dontBlockReading = false;
00873    do {
00874       slotKDEInitData( kdeinitSocket );
00875    }
00876    while (lastRequest != 0);
00877    dontBlockReading = true;
00878 }
00879 
00880 void
00881 KLauncher::exec_blind( const QCString &name, const QValueList<QCString> &arg_list,
00882     const QValueList<QCString> &envs, const QCString& startup_id )
00883 {
00884    KLaunchRequest *request = new KLaunchRequest;
00885    request->autoStart = false;
00886    request->name = name;
00887    request->arg_list =  arg_list;
00888    request->dcop_name = 0;
00889    request->dcop_service_type = KService::DCOP_None;
00890    request->pid = 0;
00891    request->status = KLaunchRequest::Launching;
00892    request->transaction = 0; // No confirmation is send
00893    request->envs = envs;
00894    // Find service, if any - strip path if needed
00895    KService::Ptr service = KService::serviceByDesktopName( name.mid( name.findRev( '/' ) + 1 ));
00896    if (service != NULL)
00897        send_service_startup_info( request,  service,
00898            startup_id, QValueList< QCString >());
00899    else // no .desktop file, no startup info
00900        cancel_service_startup_info( request, startup_id, envs );
00901 
00902    requestStart(request);
00903    // We don't care about this request any longer....
00904    requestDone(request);
00905 }
00906 
00907 
00908 bool
00909 KLauncher::start_service_by_name(const QString &serviceName, const QStringList &urls,
00910     const QValueList<QCString> &envs, const QCString& startup_id, bool blind)
00911 {
00912    KService::Ptr service = 0;
00913    // Find service
00914    service = KService::serviceByName(serviceName);
00915    if (!service)
00916    {
00917       DCOPresult.result = ENOENT;
00918       DCOPresult.error = i18n("Could not find service '%1'.").arg(serviceName);
00919       cancel_service_startup_info( NULL, startup_id, envs ); // cancel it if any
00920       return false;
00921    }
00922    return start_service(service, urls, envs, startup_id, blind);
00923 }
00924 
00925 bool
00926 KLauncher::start_service_by_desktop_path(const QString &serviceName, const QStringList &urls,
00927     const QValueList<QCString> &envs, const QCString& startup_id, bool blind)
00928 {
00929    KService::Ptr service = 0;
00930    // Find service
00931    if (serviceName[0] == '/')
00932    {
00933       // Full path
00934       service = new KService(serviceName);
00935    }
00936    else
00937    {
00938       service = KService::serviceByDesktopPath(serviceName);
00939    }
00940    if (!service)
00941    {
00942       DCOPresult.result = ENOENT;
00943       DCOPresult.error = i18n("Could not find service '%1'.").arg(serviceName);
00944       cancel_service_startup_info( NULL, startup_id, envs ); // cancel it if any
00945       return false;
00946    }
00947    return start_service(service, urls, envs, startup_id, blind);
00948 }
00949 
00950 bool
00951 KLauncher::start_service_by_desktop_name(const QString &serviceName, const QStringList &urls,
00952     const QValueList<QCString> &envs, const QCString& startup_id, bool blind)
00953 {
00954    KService::Ptr service = 0;
00955    // Find service
00956    service = KService::serviceByDesktopName(serviceName);
00957    if (!service)
00958    {
00959       DCOPresult.result = ENOENT;
00960       DCOPresult.error = i18n("Could not find service '%1'.").arg(serviceName);
00961       cancel_service_startup_info( NULL, startup_id, envs ); // cancel it if any
00962       return false;
00963    }
00964    return start_service(service, urls, envs, startup_id, blind);
00965 }
00966 
00967 bool
00968 KLauncher::start_service(KService::Ptr service, const QStringList &_urls,
00969     const QValueList<QCString> &envs, const QCString& startup_id, bool blind, bool autoStart)
00970 {
00971    QStringList urls = _urls;
00972    if (!service->isValid())
00973    {
00974       DCOPresult.result = ENOEXEC;
00975       DCOPresult.error = i18n("Service '%1' is malformatted.").arg(service->desktopEntryPath());
00976       cancel_service_startup_info( NULL, startup_id, envs ); // cancel it if any
00977       return false;
00978    }
00979    KLaunchRequest *request = new KLaunchRequest;
00980    request->autoStart = autoStart;
00981 
00982    if ((urls.count() > 1) && !service->allowMultipleFiles())
00983    {
00984       // We need to launch the application N times. That sucks.
00985       // We ignore the result for application 2 to N.
00986       // For the first file we launch the application in the
00987       // usual way. The reported result is based on this
00988       // application.
00989       QStringList::ConstIterator it = urls.begin();
00990       for(++it;
00991           it != urls.end();
00992           ++it)
00993       {
00994          QStringList singleUrl;
00995          singleUrl.append(*it);
00996          QCString startup_id2 = startup_id;
00997          if( !startup_id2.isEmpty() && startup_id2 != "0" )
00998              startup_id2 = "0"; // can't use the same startup_id several times
00999          start_service( service, singleUrl, envs, startup_id2, true);
01000       }
01001       QString firstURL = *(urls.begin());
01002       urls.clear();
01003       urls.append(firstURL);
01004    }
01005    createArgs(request, service, urls);
01006 
01007    // We must have one argument at least!
01008    if (!request->arg_list.count())
01009    {
01010       DCOPresult.result = ENOEXEC;
01011       DCOPresult.error = i18n("Service '%1' is malformatted.").arg(service->desktopEntryPath());
01012       delete request;
01013       cancel_service_startup_info( NULL, startup_id, envs );
01014       return false;
01015    }
01016 
01017    request->name = request->arg_list.first();
01018    request->arg_list.remove(request->arg_list.begin());
01019 
01020    request->dcop_service_type =  service->DCOPServiceType();
01021 
01022    if ((request->dcop_service_type == KService::DCOP_Unique) ||
01023        (request->dcop_service_type == KService::DCOP_Multi))
01024    {
01025       QVariant v = service->property("X-DCOP-ServiceName");
01026       if (v.isValid())
01027          request->dcop_name = v.toString().utf8();
01028       if (request->dcop_name.isEmpty())
01029       {
01030          request->dcop_name = QFile::encodeName(KRun::binaryName(service->exec(), true));
01031       }
01032    }
01033 
01034    request->pid = 0;
01035    request->transaction = 0;
01036    request->envs = envs;
01037    send_service_startup_info( request, service, startup_id, envs );
01038 
01039    // Request will be handled later.
01040    if (!blind && !autoStart)
01041    {
01042       request->transaction = dcopClient()->beginTransaction();
01043    }
01044    queueRequest(request);
01045    return true;
01046 }
01047 
01048 void
01049 KLauncher::send_service_startup_info( KLaunchRequest *request, KService::Ptr service, const QCString& startup_id,
01050     const QValueList<QCString> &envs )
01051 {
01052 #if defined Q_WS_X11 && ! defined K_WS_QTONLY
01053 //#ifdef Q_WS_X11 // KStartup* isn't implemented for Qt/Embedded yet
01054     request->startup_id = "0";
01055     if( startup_id == "0" )
01056         return;
01057     bool silent;
01058     QCString wmclass;
01059     if( !KRun::checkStartupNotify( QString::null, service, &silent, &wmclass ))
01060         return;
01061     KStartupInfoId id;
01062     id.initId( startup_id );
01063     const char* dpy_str = NULL;
01064     for( QValueList<QCString>::ConstIterator it = envs.begin();
01065          it != envs.end();
01066          ++it )
01067         if( strncmp( *it, "DISPLAY=", 8 ) == 0 )
01068             dpy_str = static_cast< const char* >( *it ) + 8;
01069     Display* dpy = NULL;
01070     if( dpy_str != NULL && mCached_dpy != NULL
01071         && qstrcmp( dpy_str, XDisplayString( mCached_dpy )) == 0 )
01072         dpy = mCached_dpy;
01073     if( dpy == NULL )
01074         dpy = XOpenDisplay( dpy_str );
01075     request->startup_id = id.id();
01076     if( dpy == NULL )
01077     {
01078         cancel_service_startup_info( request, startup_id, envs );
01079         return;
01080     }
01081 
01082     request->startup_dpy = dpy_str;
01083 
01084     KStartupInfoData data;
01085     data.setName( service->name());
01086     data.setIcon( service->icon());
01087     data.setDescription( i18n( "Launching %1" ).arg( service->name()));
01088     if( !wmclass.isEmpty())
01089         data.setWMClass( wmclass );
01090     if( silent )
01091         data.setSilent( KStartupInfoData::Yes );
01092     // the rest will be sent by kdeinit
01093     KStartupInfo::sendStartupX( dpy, id, data );
01094     if( mCached_dpy != dpy && mCached_dpy != NULL )
01095         XCloseDisplay( mCached_dpy );
01096     mCached_dpy = dpy;
01097     return;
01098 #else
01099     return;
01100 #endif
01101 }
01102 
01103 void
01104 KLauncher::cancel_service_startup_info( KLaunchRequest* request, const QCString& startup_id,
01105     const QValueList<QCString> &envs )
01106 {
01107 #if defined Q_WS_X11 && ! defined K_WS_QTONLY
01108 //#ifdef Q_WS_X11 // KStartup* isn't implemented for Qt/Embedded yet
01109     if( request != NULL )
01110         request->startup_id = "0";
01111     if( !startup_id.isEmpty() && startup_id != "0" )
01112     {
01113         const char* dpy_str = NULL;
01114         for( QValueList<QCString>::ConstIterator it = envs.begin();
01115              it != envs.end();
01116              ++it )
01117             if( strncmp( *it, "DISPLAY=", 8 ) == 0 )
01118                 dpy_str = static_cast< const char* >( *it ) + 8;
01119         Display* dpy = NULL;
01120         if( dpy_str != NULL && mCached_dpy != NULL
01121             && qstrcmp( dpy_str, XDisplayString( mCached_dpy )) == 0 )
01122             dpy = mCached_dpy;
01123         if( dpy == NULL )
01124             dpy = XOpenDisplay( dpy_str );
01125         if( dpy == NULL )
01126             return;
01127         KStartupInfoId id;
01128         id.initId( startup_id );
01129         KStartupInfo::sendFinishX( dpy, id );
01130         if( mCached_dpy != dpy && mCached_dpy != NULL )
01131            XCloseDisplay( mCached_dpy );
01132         mCached_dpy = dpy;
01133     }
01134 #endif
01135 }
01136 
01137 bool
01138 KLauncher::kdeinit_exec(const QString &app, const QStringList &args,
01139    const QValueList<QCString> &envs, QCString startup_id, bool wait)
01140 {
01141    KLaunchRequest *request = new KLaunchRequest;
01142    request->autoStart = false;
01143 
01144    for(QStringList::ConstIterator it = args.begin();
01145        it != args.end();
01146        it++)
01147    {
01148        QString arg = *it;
01149        request->arg_list.append(arg.local8Bit());
01150    }
01151 
01152    request->name = app.local8Bit();
01153 
01154    if (wait)
01155       request->dcop_service_type = KService::DCOP_Wait;
01156    else
01157       request->dcop_service_type = KService::DCOP_None;
01158    request->dcop_name = 0;
01159    request->pid = 0;
01160 #ifdef Q_WS_X11
01161    request->startup_id = startup_id;
01162 #endif
01163    request->envs = envs;
01164    if( app != "kbuildsycoca" ) // avoid stupid loop
01165    {
01166        // Find service, if any - strip path if needed
01167        KService::Ptr service = KService::serviceByDesktopName( app.mid( app.findRev( '/' ) + 1 ));
01168        if (service != NULL)
01169            send_service_startup_info( request,  service,
01170                startup_id, QValueList< QCString >());
01171        else // no .desktop file, no startup info
01172            cancel_service_startup_info( request, startup_id, envs );
01173    }
01174    request->transaction = dcopClient()->beginTransaction();
01175    queueRequest(request);
01176    return true;
01177 }
01178 
01179 void
01180 KLauncher::queueRequest(KLaunchRequest *request)
01181 {
01182    requestQueue.append( request );
01183    if (!bProcessingQueue)
01184    {
01185       bProcessingQueue = true;
01186       QTimer::singleShot(0, this, SLOT( slotDequeue() ));
01187    }
01188 }
01189 
01190 void
01191 KLauncher::slotDequeue()
01192 {
01193    do {
01194       KLaunchRequest *request = requestQueue.take(0);
01195       // process request
01196       request->status = KLaunchRequest::Launching;
01197       requestStart(request);
01198       if (request->status != KLaunchRequest::Launching)
01199       {
01200          // Request handled.
01201          requestDone( request );
01202          continue;
01203       }
01204    } while(requestQueue.count());
01205    bProcessingQueue = false;
01206 }
01207 
01208 void
01209 KLauncher::createArgs( KLaunchRequest *request, const KService::Ptr service ,
01210                        const QStringList &urls)
01211 {
01212   QStringList params = KRun::processDesktopExec(*service, urls, false);
01213 
01214   for(QStringList::ConstIterator it = params.begin();
01215       it != params.end(); ++it)
01216   {
01217      request->arg_list.append((*it).local8Bit());
01218   }
01219   request->cwd = QFile::encodeName(service->path());
01220 }
01221 
01223 
01224 pid_t
01225 KLauncher::requestHoldSlave(const KURL &url, const QString &app_socket)
01226 {
01227     IdleSlave *slave;
01228     for(slave = mSlaveList.first(); slave; slave = mSlaveList.next())
01229     {
01230        if (slave->onHold(url))
01231           break;
01232     }
01233     if (slave)
01234     {
01235        mSlaveList.removeRef(slave);
01236        slave->connect(app_socket);
01237        return slave->pid();
01238     }
01239     return 0;
01240 }
01241 
01242 
01243 pid_t
01244 KLauncher::requestSlave(const QString &protocol,
01245                         const QString &host,
01246                         const QString &app_socket,
01247                         QString &error)
01248 {
01249     IdleSlave *slave;
01250     for(slave = mSlaveList.first(); slave; slave = mSlaveList.next())
01251     {
01252        if (slave->match(protocol, host, true))
01253           break;
01254     }
01255     if (!slave)
01256     {
01257        for(slave = mSlaveList.first(); slave; slave = mSlaveList.next())
01258        {
01259           if (slave->match(protocol, host, false))
01260              break;
01261        }
01262     }
01263     if (!slave)
01264     {
01265        for(slave = mSlaveList.first(); slave; slave = mSlaveList.next())
01266        {
01267           if (slave->match(protocol, QString::null, false))
01268              break;
01269        }
01270     }
01271     if (slave)
01272     {
01273        mSlaveList.removeRef(slave);
01274        slave->connect(app_socket);
01275        return slave->pid();
01276     }
01277 
01278     QString _name = KProtocolInfo::exec(protocol);
01279     if (_name.isEmpty())
01280     {
01281     error = i18n("Unknown protocol '%1'.\n").arg(protocol);
01282         return 0;
01283     }
01284 
01285     QCString name = _name.latin1(); // ex: "kio_ftp"
01286     QCString arg1 = protocol.latin1();
01287     QCString arg2 = QFile::encodeName(mPoolSocketName);
01288     QCString arg3 = QFile::encodeName(app_socket);
01289     QValueList<QCString> arg_list;
01290     arg_list.append(arg1);
01291     arg_list.append(arg2);
01292     arg_list.append(arg3);
01293 
01294 //    kdDebug(7016) << "KLauncher: launching new slave " << _name << " with protocol=" << protocol << endl;
01295     if (mSlaveDebug == arg1)
01296     {
01297        klauncher_header request_header;
01298        request_header.cmd = LAUNCHER_DEBUG_WAIT;
01299        request_header.arg_length = 0;
01300        write(kdeinitSocket, &request_header, sizeof(request_header));
01301     }
01302     if (mSlaveValgrind == arg1)
01303     {
01304        arg_list.prepend(QFile::encodeName(KLibLoader::findLibrary(name)));
01305        arg_list.prepend(QFile::encodeName(locate("exe", "kioslave")));
01306        name = "valgrind";
01307        if (!mSlaveValgrindSkin.isEmpty()) {
01308            arg_list.prepend(QCString("--tool=") + mSlaveValgrindSkin);
01309        } else
01310        arg_list.prepend("--tool=memcheck");
01311     }
01312 
01313     KLaunchRequest *request = new KLaunchRequest;
01314     request->autoStart = false;
01315     request->name = name;
01316     request->arg_list =  arg_list;
01317     request->dcop_name = 0;
01318     request->dcop_service_type = KService::DCOP_None;
01319     request->pid = 0;
01320 #ifdef Q_WS_X11
01321     request->startup_id = "0";
01322 #endif
01323     request->status = KLaunchRequest::Launching;
01324     request->transaction = 0; // No confirmation is send
01325     requestStart(request);
01326     pid_t pid = request->pid;
01327 
01328 //    kdDebug(7016) << "Slave launched, pid = " << pid << endl;
01329 
01330     // We don't care about this request any longer....
01331     requestDone(request);
01332     if (!pid)
01333     {
01334        error = i18n("Error loading '%1'.\n").arg(name);
01335     }
01336     return pid;
01337 }
01338 
01339 void
01340 KLauncher::waitForSlave(pid_t pid)
01341 {
01342     IdleSlave *slave;
01343     for(slave = mSlaveList.first(); slave; slave = mSlaveList.next())
01344     {
01345         if (slave->pid() == pid)
01346            return; // Already here.
01347     }
01348     SlaveWaitRequest *waitRequest = new SlaveWaitRequest;
01349     waitRequest->transaction = dcopClient()->beginTransaction();
01350     waitRequest->pid = pid;
01351     mSlaveWaitRequest.append(waitRequest);
01352 }
01353 
01354 void
01355 KLauncher::acceptSlave(KSocket *slaveSocket)
01356 {
01357     IdleSlave *slave = new IdleSlave(slaveSocket);
01358     // Send it a SLAVE_STATUS command.
01359     mSlaveList.append(slave);
01360     connect(slave, SIGNAL(destroyed()), this, SLOT(slotSlaveGone()));
01361     connect(slave, SIGNAL(statusUpdate(IdleSlave *)),
01362         this, SLOT(slotSlaveStatus(IdleSlave *)));
01363     if (!mTimer.isActive())
01364     {
01365        mTimer.start(1000*10);
01366     }
01367 }
01368 
01369 void
01370 KLauncher::slotSlaveStatus(IdleSlave *slave)
01371 {
01372     SlaveWaitRequest *waitRequest = mSlaveWaitRequest.first();
01373     while(waitRequest)
01374     {
01375        if (waitRequest->pid == slave->pid())
01376        {
01377           QByteArray replyData;
01378           QCString replyType;
01379           replyType = "void";
01380           dcopClient()->endTransaction( waitRequest->transaction, replyType, replyData);
01381           mSlaveWaitRequest.removeRef(waitRequest);
01382           waitRequest = mSlaveWaitRequest.current();
01383        }
01384        else
01385        {
01386           waitRequest = mSlaveWaitRequest.next();
01387        }
01388     }
01389 }
01390 
01391 void
01392 KLauncher::slotSlaveGone()
01393 {
01394     IdleSlave *slave = (IdleSlave *) sender();
01395     mSlaveList.removeRef(slave);
01396     if ((mSlaveList.count() == 0) && (mTimer.isActive()))
01397     {
01398        mTimer.stop();
01399     }
01400 }
01401 
01402 void
01403 KLauncher::idleTimeout()
01404 {
01405     bool keepOneFileSlave=true;
01406     time_t now = time(0);
01407     IdleSlave *slave;
01408     for(slave = mSlaveList.first(); slave; slave = mSlaveList.next())
01409     {
01410         if ((slave->protocol()=="file") && (keepOneFileSlave))
01411            keepOneFileSlave=false;
01412         else if (slave->age(now) > SLAVE_MAX_IDLE)
01413         {
01414            // killing idle slave
01415            delete slave;
01416         }
01417     }
01418 }
01419 
01420 #include "klauncher.moc"

KInit

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

API Reference

Skip menu "API Reference"
  • dcop
  • DNSSD
  • interfaces
  • Kate
  • kconf_update
  • KDECore
  • KDED
  • kdefx
  • KDEsu
  • kdeui
  • KDocTools
  • KHTML
  • KImgIO
  • KInit
  • kio
  • kioslave
  • KJS
  • KNewStuff
  • KParts
  • KUtils
Generated for API Reference by doxygen 1.5.9
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