• Skip to content
  • Skip to link menu
Trinity API Reference
  • Trinity API Reference
  • kinit
 

kinit

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

kinit

Skip menu "kinit"
  • Main Page
  • File List
  • Related Pages

kinit

Skip menu "kinit"
  • arts
  • dcop
  • dnssd
  • interfaces
  •     interface
  •     library
  •   kspeech
  •   ktexteditor
  • kabc
  • kate
  • kcmshell
  • kdecore
  • kded
  • kdefx
  • kdeprint
  • kdesu
  • kdeui
  • kdoctools
  • khtml
  • kimgio
  • kinit
  • kio
  •   bookmarks
  •   httpfilter
  •   kfile
  •   kio
  •   kioexec
  •   kpasswdserver
  •   kssl
  • kioslave
  •   http
  • kjs
  • kmdi
  •   kmdi
  • knewstuff
  • kparts
  • krandr
  • kresources
  • kspell2
  • kunittest
  • kutils
  • kwallet
  • libkmid
  • libkscreensaver
Generated for kinit by doxygen 1.7.6.1
This website is maintained by Timothy Pearson.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. |