diff options
Diffstat (limited to 'kinit/klauncher.cpp')
-rw-r--r-- | kinit/klauncher.cpp | 1421 |
1 files changed, 0 insertions, 1421 deletions
diff --git a/kinit/klauncher.cpp b/kinit/klauncher.cpp deleted file mode 100644 index 8c66789e7..000000000 --- a/kinit/klauncher.cpp +++ /dev/null @@ -1,1421 +0,0 @@ -/* - This file is part of the KDE libraries - Copyright (c) 1999 Waldo Bastian <bastian@kde.org> - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License version 2 as published by the Free Software Foundation. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public License - along with this library; see the file COPYING.LIB. If not, write to - the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - Boston, MA 02110-1301, USA. -*/ -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <stdio.h> -#include <unistd.h> -#include <stdlib.h> -#include <errno.h> -#include <signal.h> -#include <sys/time.h> - -#include <tqfile.h> - -#include <kconfig.h> -#include <kdebug.h> -#include <klibloader.h> -#include <klocale.h> -#include <kprotocolmanager.h> -#include <kprotocolinfo.h> -#include <krun.h> -#include <kstandarddirs.h> -#include <ktempfile.h> -#include <kurl.h> - -#if defined Q_WS_X11 && ! defined K_WS_QTONLY -#include <kstartupinfo.h> // schroder -#endif - - -#include "kio/global.h" -#include "kio/connection.h" -#include "kio/slaveinterface.h" - -#include "klauncher.h" -#include "klauncher_cmds.h" - -//#if defined Q_WS_X11 && ! defined K_WS_QTONLY -#ifdef Q_WS_X11 -//#undef K_WS_QTONLY -#include <X11/Xlib.h> // schroder -#endif - -// Dispose slaves after being idle for SLAVE_MAX_IDLE seconds -#define SLAVE_MAX_IDLE 30 - -using namespace TDEIO; - -template class TQPtrList<KLaunchRequest>; -template class TQPtrList<IdleSlave>; - -IdleSlave::IdleSlave(TDESocket *socket) -{ - mConn.init(socket); - mConn.connect(this, TQT_SLOT(gotInput())); - mConn.send( CMD_SLAVE_STATUS ); - mPid = 0; - mBirthDate = time(0); - mOnHold = false; -} - -void -IdleSlave::gotInput() -{ - int cmd; - TQByteArray data; - if (mConn.read( &cmd, data) == -1) - { - // Communication problem with slave. - kdError(7016) << "SlavePool: No communication with slave." << endl; - delete this; - } - else if (cmd == MSG_SLAVE_ACK) - { - delete this; - } - else if (cmd != MSG_SLAVE_STATUS) - { - kdError(7016) << "SlavePool: Unexpected data from slave." << endl; - delete this; - } - else - { - TQDataStream stream( data, IO_ReadOnly ); - pid_t pid; - TQCString protocol; - TQString host; - TQ_INT8 b; - stream >> pid >> protocol >> host >> b; -// Overload with (bool) onHold, (KURL) url. - if (!stream.atEnd()) - { - KURL url; - stream >> url; - mOnHold = true; - mUrl = url; - } - - mPid = pid; - mConnected = (b != 0); - mProtocol = protocol; - mHost = host; - emit statusUpdate(this); - } -} - -void -IdleSlave::connect(const TQString &app_socket) -{ - TQByteArray data; - TQDataStream stream( data, IO_WriteOnly); - stream << app_socket; - mConn.send( CMD_SLAVE_CONNECT, data ); - // Timeout! -} - -void -IdleSlave::reparseConfiguration() -{ - mConn.send( CMD_REPARSECONFIGURATION ); -} - -bool -IdleSlave::match(const TQString &protocol, const TQString &host, bool connected) -{ - if (mOnHold) return false; - if (protocol != mProtocol) return false; - if (host.isEmpty()) return true; - if (host != mHost) return false; - if (!connected) return true; - if (!mConnected) return false; - return true; -} - -bool -IdleSlave::onHold(const KURL &url) -{ - if (!mOnHold) return false; - return (url == mUrl); -} - -int -IdleSlave::age(time_t now) -{ - return (int) difftime(now, mBirthDate); -} - -KLauncher::KLauncher(int _tdeinitSocket, bool new_startup) -// : TDEApplication( false, false ), // No Styles, No GUI - : TDEApplication( false, true ), // TQClipboard tries to construct a QWidget so a GUI is technically needed, even though it is not used - DCOPObject("klauncher"), - tdeinitSocket(_tdeinitSocket), mAutoStart( new_startup ), - dontBlockReading(false), newStartup( new_startup ) -{ -#ifdef Q_WS_X11 - mCached_dpy = NULL; -#endif - connect(&mAutoTimer, TQT_SIGNAL(timeout()), this, TQT_SLOT(slotAutoStart())); - requestList.setAutoDelete(true); - mSlaveWaitRequest.setAutoDelete(true); - dcopClient()->setNotifications( true ); - connect(dcopClient(), TQT_SIGNAL( applicationRegistered( const TQCString &)), - this, TQT_SLOT( slotAppRegistered( const TQCString &))); - dcopClient()->connectDCOPSignal( "DCOPServer", "", "terminateKDE()", - objId(), "terminateKDE()", false ); - - TQString prefix = locateLocal("socket", "klauncher"); - KTempFile domainname(prefix, TQString::fromLatin1(".slave-socket")); - if (domainname.status() != 0) - { - // Sever error! - tqDebug("KLauncher: Fatal error, can't create tempfile!"); - ::exit(1); - } - mPoolSocketName = domainname.name(); -#ifdef __CYGWIN__ - domainname.close(); - domainname.unlink(); -#endif - mPoolSocket = new TDEServerSocket(static_cast<const char*>(TQFile::encodeName(mPoolSocketName))); - connect(mPoolSocket, TQT_SIGNAL(accepted( TDESocket *)), - TQT_SLOT(acceptSlave(TDESocket *))); - - connect(&mTimer, TQT_SIGNAL(timeout()), TQT_SLOT(idleTimeout())); - - tdeinitNotifier = new TQSocketNotifier(tdeinitSocket, TQSocketNotifier::Read); - connect(tdeinitNotifier, TQT_SIGNAL( activated( int )), - this, TQT_SLOT( slotKDEInitData( int ))); - tdeinitNotifier->setEnabled( true ); - lastRequest = 0; - bProcessingQueue = false; - - mSlaveDebug = getenv("TDE_SLAVE_DEBUG_WAIT"); - if (!mSlaveDebug.isEmpty()) - { - tqWarning("Klauncher running in slave-debug mode for slaves of protocol '%s'", mSlaveDebug.data()); - } - mSlaveValgrind = getenv("TDE_SLAVE_VALGRIND"); - if (!mSlaveValgrind.isEmpty()) - { - mSlaveValgrindSkin = getenv("TDE_SLAVE_VALGRIND_SKIN"); - tqWarning("Klauncher running slaves through valgrind for slaves of protocol '%s'", mSlaveValgrind.data()); - } - klauncher_header request_header; - request_header.cmd = LAUNCHER_OK; - request_header.arg_length = 0; - write(tdeinitSocket, &request_header, sizeof(request_header)); -} - -KLauncher::~KLauncher() -{ - close(); -} - -void KLauncher::close() -{ - if (!mPoolSocketName.isEmpty()) - { - TQCString filename = TQFile::encodeName(mPoolSocketName); - unlink(filename.data()); - } -#if defined Q_WS_X11 && ! defined K_WS_QTONLY -//#ifdef Q_WS_X11 - if( mCached_dpy != NULL ) - XCloseDisplay( mCached_dpy ); -#endif -} - -void -KLauncher::destruct(int exit_code) -{ - if (kapp) ((KLauncher*)kapp)->close(); - // We don't delete kapp here, that's intentional. - ::exit(exit_code); -} - -bool -KLauncher::process(const TQCString &fun, const TQByteArray &data, - TQCString &replyType, TQByteArray &replyData) -{ - if ((fun == "exec_blind(TQCString,TQValueList<TQCString>)") - || (fun == "exec_blind(TQCString,TQValueList<TQCString>,TQValueList<TQCString>,TQCString)")) - { - TQDataStream stream(data, IO_ReadOnly); - replyType = "void"; - TQCString name; - TQValueList<TQCString> arg_list; - TQCString startup_id = "0"; - TQValueList<TQCString> envs; - stream >> name >> arg_list; - if( fun == "exec_blind(TQCString,TQValueList<TQCString>,TQValueList<TQCString>,TQCString)" ) - stream >> envs >> startup_id; - kdDebug(7016) << "KLauncher: Got exec_blind('" << name << "', ...)" << endl; - exec_blind( name, arg_list, envs, startup_id); - return true; - } - if ((fun == "start_service_by_name(TQString,TQStringList)") || - (fun == "start_service_by_desktop_path(TQString,TQStringList)")|| - (fun == "start_service_by_desktop_name(TQString,TQStringList)")|| - (fun == "tdeinit_exec(TQString,TQStringList)") || - (fun == "tdeinit_exec_wait(TQString,TQStringList)") || - (fun == "start_service_by_name(TQString,TQStringList,TQValueList<TQCString>,TQCString)") || - (fun == "start_service_by_desktop_path(TQString,TQStringList,TQValueList<TQCString>,TQCString)")|| - (fun == "start_service_by_desktop_name(TQString,TQStringList,TQValueList<TQCString>,TQCString)") || - (fun == "start_service_by_name(TQString,TQStringList,TQValueList<TQCString>,TQCString,bool)") || - (fun == "start_service_by_desktop_path(TQString,TQStringList,TQValueList<TQCString>,TQCString,bool)")|| - (fun == "start_service_by_desktop_name(TQString,TQStringList,TQValueList<TQCString>,TQCString,bool)") || - (fun == "tdeinit_exec(TQString,TQStringList,TQValueList<TQCString>)") || - (fun == "tdeinit_exec_wait(TQString,TQStringList,TQValueList<TQCString>)") || - (fun == "tdeinit_exec(TQString,TQStringList,TQValueList<TQCString>,TQCString)") || - (fun == "tdeinit_exec_wait(TQString,TQStringList,TQValueList<TQCString>,TQCString)")) - { - TQDataStream stream(data, IO_ReadOnly); - bool bNoWait = false; - TQString serviceName; - TQStringList urls; - TQValueList<TQCString> envs; - TQCString startup_id = ""; - DCOPresult.result = -1; - DCOPresult.dcopName = 0; - DCOPresult.error = TQString::null; - DCOPresult.pid = 0; - stream >> serviceName >> urls; - if ((fun == "start_service_by_name(TQString,TQStringList,TQValueList<TQCString>,TQCString,bool)") || - (fun == "start_service_by_desktop_path(TQString,TQStringList,TQValueList<TQCString>,TQCString,bool)")|| - (fun == "start_service_by_desktop_name(TQString,TQStringList,TQValueList<TQCString>,TQCString,bool)")) - stream >> envs >> startup_id >> bNoWait; - else if ((fun == "start_service_by_name(TQString,TQStringList,TQValueList<TQCString>,TQCString)") || - (fun == "start_service_by_desktop_path(TQString,TQStringList,TQValueList<TQCString>,TQCString)")|| - (fun == "start_service_by_desktop_name(TQString,TQStringList,TQValueList<TQCString>,TQCString)")) - stream >> envs >> startup_id; - else if ((fun == "tdeinit_exec(TQString,TQStringList,TQValueList<TQCString>)") || - (fun == "tdeinit_exec_wait(TQString,TQStringList,TQValueList<TQCString>)")) - stream >> envs; - else if ((fun == "tdeinit_exec(TQString,TQStringList,TQValueList<TQCString>,TQCString)") || - (fun == "tdeinit_exec_wait(TQString,TQStringList,TQValueList<TQCString>,TQCString)")) - stream >> envs >> startup_id; - bool finished; - if (strncmp(fun, "start_service_by_name(", 22) == 0) - { - kdDebug(7016) << "KLauncher: Got start_service_by_name('" << serviceName << "', ...)" << endl; - finished = start_service_by_name(serviceName, urls, envs, startup_id, bNoWait); - } - else if (strncmp(fun, "start_service_by_desktop_path(", 30) == 0) - { - kdDebug(7016) << "KLauncher: Got start_service_by_desktop_path('" << serviceName << "', ...)" << endl; - finished = start_service_by_desktop_path(serviceName, urls, envs, startup_id, bNoWait); - } - else if (strncmp(fun, "start_service_by_desktop_name(", 30) == 0) - { - kdDebug(7016) << "KLauncher: Got start_service_by_desktop_name('" << serviceName << "', ...)" << endl; - finished = start_service_by_desktop_name(serviceName, urls, envs, startup_id, bNoWait ); - } - else if ((fun == "tdeinit_exec(TQString,TQStringList)") - || (fun == "tdeinit_exec(TQString,TQStringList,TQValueList<TQCString>)") - || (fun == "tdeinit_exec(TQString,TQStringList,TQValueList<TQCString>,TQCString)")) - { - kdDebug(7016) << "KLauncher: Got tdeinit_exec('" << serviceName << "', ...)" << endl; - finished = tdeinit_exec(serviceName, urls, envs, startup_id, false); - } - else - { - kdDebug(7016) << "KLauncher: Got tdeinit_exec_wait('" << serviceName << "', ...)" << endl; - finished = tdeinit_exec(serviceName, urls, envs, startup_id, true); - } - if (!finished) - { - replyType = "serviceResult"; - TQDataStream stream2(replyData, IO_WriteOnly); - stream2 << DCOPresult.result << DCOPresult.dcopName << DCOPresult.error << DCOPresult.pid; - } - return true; - } - else if (fun == "requestSlave(TQString,TQString,TQString)") - { - TQDataStream stream(data, IO_ReadOnly); - TQString protocol; - TQString host; - TQString app_socket; - stream >> protocol >> host >> app_socket; - replyType = "TQString"; - TQString error; - pid_t pid = requestSlave(protocol, host, app_socket, error); - TQDataStream stream2(replyData, IO_WriteOnly); - stream2 << pid << error; - return true; - } - else if (fun == "requestHoldSlave(KURL,TQString)") - { - TQDataStream stream(data, IO_ReadOnly); - KURL url; - TQString app_socket; - stream >> url >> app_socket; - replyType = "pid_t"; - pid_t pid = requestHoldSlave(url, app_socket); - TQDataStream stream2(replyData, IO_WriteOnly); - stream2 << pid; - return true; - } - else if (fun == "waitForSlave(pid_t)") - { - TQDataStream stream(data, IO_ReadOnly); - pid_t pid; - stream >> pid; - waitForSlave(pid); - replyType = "void"; - return true; - - } - else if (fun == "setLaunchEnv(TQCString,TQCString)") - { - TQDataStream stream(data, IO_ReadOnly); - TQCString name; - TQCString value; - stream >> name >> value; - setLaunchEnv(name, value); - replyType = "void"; - return true; - } - else if (fun == "reparseConfiguration()") - { - TDEGlobal::config()->reparseConfiguration(); - kdDebug(7016) << "KLauncher::process : reparseConfiguration" << endl; - KProtocolManager::reparseConfiguration(); - IdleSlave *slave; - for(slave = mSlaveList.first(); slave; slave = mSlaveList.next()) - slave->reparseConfiguration(); - replyType = "void"; - return true; - } - else if (fun == "terminateKDE()") - { - ::signal( SIGHUP, SIG_IGN); - ::signal( SIGTERM, SIG_IGN); - kdDebug() << "KLauncher::process ---> terminateKDE" << endl; - klauncher_header request_header; - request_header.cmd = LAUNCHER_TERMINATE_KDE; - request_header.arg_length = 0; - write(tdeinitSocket, &request_header, sizeof(request_header)); - destruct(0); - } - else if (fun == "autoStart()") - { - kdDebug() << "KLauncher::process ---> autoStart" << endl; - autoStart(1); - replyType = "void"; - return true; - } - else if (fun == "autoStart(int)") - { - kdDebug() << "KLauncher::process ---> autoStart(int)" << endl; - TQDataStream stream(data, IO_ReadOnly); - int phase; - stream >> phase; - autoStart(phase); - replyType = "void"; - return true; - } - - if (DCOPObject::process(fun, data, replyType, replyData)) - { - return true; - } - kdWarning(7016) << "Got unknown DCOP function: " << fun << endl; - return false; -} - -QCStringList -KLauncher::interfaces() -{ - QCStringList ifaces = DCOPObject::interfaces(); - ifaces += "KLauncher"; - return ifaces; -} - -QCStringList -KLauncher::functions() -{ - QCStringList funcs = DCOPObject::functions(); - funcs << "void exec_blind(TQCString,TQValueList<TQCString>)"; - funcs << "void exec_blind(TQCString,TQValueList<TQCString>,TQValueList<TQCString>,TQCString)"; - funcs << "serviceResult start_service_by_name(TQString,TQStringList)"; - funcs << "serviceResult start_service_by_desktop_path(TQString,TQStringList)"; - funcs << "serviceResult start_service_by_desktop_name(TQString,TQStringList)"; - funcs << "serviceResult tdeinit_exec(TQString,TQStringList)"; - funcs << "serviceResult tdeinit_exec_wait(TQString,TQStringList)"; - funcs << "serviceResult start_service_by_name(TQString,TQStringList,TQValueList<TQCString>,TQCString)"; - funcs << "serviceResult start_service_by_desktop_path(TQString,TQStringList,TQValueList<TQCString>,TQCString)"; - funcs << "serviceResult start_service_by_desktop_name(TQString,TQStringList,TQValueList<TQCString>,TQCString)"; - funcs << "serviceResult start_service_by_name(TQString,TQStringList,TQValueList<TQCString>,TQCString,bool)"; - funcs << "serviceResult start_service_by_desktop_path(TQString,TQStringList,TQValueList<TQCString>,TQCString,bool)"; - funcs << "serviceResult start_service_by_desktop_name(TQString,TQStringList,TQValueList<TQCString>,TQCString,bool)"; - funcs << "serviceResult tdeinit_exec(TQString,TQStringList,TQValueList<TQCString>)"; - funcs << "serviceResult tdeinit_exec_wait(TQString,TQStringList,TQValueList<TQCString>)"; - funcs << "TQString requestSlave(TQString,TQString,TQString)"; - funcs << "pid_t requestHoldSlave(KURL,TQString)"; - funcs << "void waitForSlave(pid_t)"; - funcs << "void setLaunchEnv(TQCString,TQCString)"; - funcs << "void reparseConfiguration()"; -// funcs << "void terminateKDE()"; - funcs << "void autoStart()"; - funcs << "void autoStart(int)"; - return funcs; -} - -void KLauncher::setLaunchEnv(const TQCString &name, const TQCString &_value) -{ - TQCString value(_value); - if (value.isNull()) - value = ""; - klauncher_header request_header; - TQByteArray requestData(name.length()+value.length()+2); - memcpy(requestData.data(), name.data(), name.length()+1); - memcpy(requestData.data()+name.length()+1, value.data(), value.length()+1); - request_header.cmd = LAUNCHER_SETENV; - request_header.arg_length = requestData.size(); - write(tdeinitSocket, &request_header, sizeof(request_header)); - write(tdeinitSocket, requestData.data(), request_header.arg_length); -} - -/* - * Read 'len' bytes from 'sock' into buffer. - * returns -1 on failure, 0 on no data. - */ -static int -read_socket(int sock, char *buffer, int len) -{ - ssize_t result; - int bytes_left = len; - while ( bytes_left > 0) - { - result = read(sock, buffer, bytes_left); - if (result > 0) - { - buffer += result; - bytes_left -= result; - } - else if (result == 0) - return -1; - else if ((result == -1) && (errno != EINTR)) - return -1; - } - return 0; -} - - -void -KLauncher::slotKDEInitData(int) -{ - klauncher_header request_header; - TQByteArray requestData; - if( dontBlockReading ) - { - // in case we get a request to start an application and data arrive - // to tdeinitSocket at the same time, requestStart() will already - // call slotKDEInitData(), so we must check there's still something - // to read, otherwise this would block - fd_set in; - timeval tm = { 0, 0 }; - FD_ZERO ( &in ); - FD_SET( tdeinitSocket, &in ); - select( tdeinitSocket + 1, &in, 0, 0, &tm ); - if( !FD_ISSET( tdeinitSocket, &in )) - return; - } - dontBlockReading = false; - int result = read_socket(tdeinitSocket, (char *) &request_header, - sizeof( request_header)); - if (result == -1) - { - kdDebug() << "Exiting on read_socket errno: " << errno << endl; - ::signal( SIGHUP, SIG_IGN); - ::signal( SIGTERM, SIG_IGN); - destruct(255); // Exit! - } - requestData.resize(request_header.arg_length); - result = read_socket(tdeinitSocket, (char *) requestData.data(), - request_header.arg_length); - - if (request_header.cmd == LAUNCHER_DIED) - { - long *request_data; - request_data = (long *) requestData.data(); - processDied(request_data[0], request_data[1]); - return; - } - if (lastRequest && (request_header.cmd == LAUNCHER_OK)) - { - long *request_data; - request_data = (long *) requestData.data(); - lastRequest->pid = (pid_t) (*request_data); - kdDebug(7016) << lastRequest->name << " (pid " << lastRequest->pid << - ") up and running." << endl; - switch(lastRequest->dcop_service_type) - { - case KService::DCOP_None: - { - lastRequest->status = KLaunchRequest::Running; - break; - } - - case KService::DCOP_Unique: - { - lastRequest->status = KLaunchRequest::Launching; - break; - } - - case KService::DCOP_Wait: - { - lastRequest->status = KLaunchRequest::Launching; - break; - } - - case KService::DCOP_Multi: - { - lastRequest->status = KLaunchRequest::Launching; - break; - } - } - lastRequest = 0; - return; - } - if (lastRequest && (request_header.cmd == LAUNCHER_ERROR)) - { - lastRequest->status = KLaunchRequest::Error; - if (!requestData.isEmpty()) - lastRequest->errorMsg = TQString::fromUtf8((char *) requestData.data()); - lastRequest = 0; - return; - } - - kdWarning(7016) << "Unexpected command from KDEInit (" << (unsigned int) request_header.cmd - << ")" << endl; -} - -void -KLauncher::processDied(pid_t pid, long /* exitStatus */) -{ - KLaunchRequest *request = requestList.first(); - for(; request; request = requestList.next()) - { - if (request->pid == pid) - { - if (request->dcop_service_type == KService::DCOP_Wait) - request->status = KLaunchRequest::Done; - else if ((request->dcop_service_type == KService::DCOP_Unique) && - (dcopClient()->isApplicationRegistered(request->dcop_name))) - request->status = KLaunchRequest::Running; - else - request->status = KLaunchRequest::Error; - requestDone(request); - return; - } - } -} - -void -KLauncher::slotAppRegistered(const TQCString &appId) -{ - const char *cAppId = appId.data(); - if (!cAppId) return; - - KLaunchRequest *request = requestList.first(); - KLaunchRequest *nextRequest; - for(; request; request = nextRequest) - { - nextRequest = requestList.next(); - if (request->status != KLaunchRequest::Launching) - continue; - - // For unique services check the requested service name first - if ((request->dcop_service_type == KService::DCOP_Unique) && - ((appId == request->dcop_name) || - dcopClient()->isApplicationRegistered(request->dcop_name))) - { - request->status = KLaunchRequest::Running; - requestDone(request); - continue; - } - - const char *rAppId = request->dcop_name.data(); - if (!rAppId) continue; - - int l = strlen(rAppId); - if ((strncmp(rAppId, cAppId, l) == 0) && - ((cAppId[l] == '\0') || (cAppId[l] == '-'))) - { - request->dcop_name = appId; - request->status = KLaunchRequest::Running; - requestDone(request); - continue; - } - } -} - -void -KLauncher::autoStart(int phase) -{ - if( mAutoStart.phase() >= phase ) - return; - mAutoStart.setPhase(phase); - if( newStartup ) - { - if (phase == 0) - mAutoStart.loadAutoStartList(); - } - else - { - if (phase == 1) - mAutoStart.loadAutoStartList(); - } - mAutoTimer.start(0, true); -} - -void -KLauncher::slotAutoStart() -{ - KService::Ptr s; - do - { - TQString service = mAutoStart.startService(); - if (service.isEmpty()) - { - // Done - if( !mAutoStart.phaseDone()) - { - mAutoStart.setPhaseDone(); - // Emit signal - if( newStartup ) - { - TQCString autoStartSignal; - autoStartSignal.sprintf( "autoStart%dDone()", mAutoStart.phase()); - emitDCOPSignal(autoStartSignal, TQByteArray()); - } - else - { - TQCString autoStartSignal( "autoStartDone()" ); - int phase = mAutoStart.phase(); - if ( phase > 1 ) - autoStartSignal.sprintf( "autoStart%dDone()", phase ); - emitDCOPSignal(autoStartSignal, TQByteArray()); - } - } - return; - } - s = new KService(service); - } - while (!start_service(s, TQStringList(), TQValueList<TQCString>(), "0", false, true)); - // Loop till we find a service that we can start. -} - -void -KLauncher::requestDone(KLaunchRequest *request) -{ - if ((request->status == KLaunchRequest::Running) || - (request->status == KLaunchRequest::Done)) - { - DCOPresult.result = 0; - DCOPresult.dcopName = request->dcop_name; - DCOPresult.error = TQString::null; - DCOPresult.pid = request->pid; - } - else - { - DCOPresult.result = 1; - DCOPresult.dcopName = ""; - DCOPresult.error = i18n("KDEInit could not launch '%1'.").arg(TQString(request->name)); - if (!request->errorMsg.isEmpty()) - DCOPresult.error += ":\n" + request->errorMsg; - DCOPresult.pid = 0; - -#if defined Q_WS_X11 && ! defined K_WS_QTONLY -//#ifdef Q_WS_X11 - if (!request->startup_dpy.isEmpty()) - { - Display* dpy = NULL; - if( (mCached_dpy != NULL) && - (request->startup_dpy == XDisplayString( mCached_dpy ))) - dpy = mCached_dpy; - if( dpy == NULL ) - dpy = XOpenDisplay( request->startup_dpy ); - if( dpy ) - { - KStartupInfoId id; - id.initId( request->startup_id ); - KStartupInfo::sendFinishX( dpy, id ); - if( mCached_dpy != dpy && mCached_dpy != NULL ) - XCloseDisplay( mCached_dpy ); - mCached_dpy = dpy; - } - } -#endif - } - - if (request->autoStart) - { - mAutoTimer.start(0, true); - } - - if (request->transaction) - { - TQByteArray replyData; - TQCString replyType; - replyType = "serviceResult"; - TQDataStream stream2(replyData, IO_WriteOnly); - stream2 << DCOPresult.result << DCOPresult.dcopName << DCOPresult.error << DCOPresult.pid; - dcopClient()->endTransaction( request->transaction, - replyType, replyData); - } - requestList.removeRef( request ); -} - -void -KLauncher::requestStart(KLaunchRequest *request) -{ - requestList.append( request ); - // Send request to tdeinit. - klauncher_header request_header; - TQByteArray requestData; - int length = 0; - length += sizeof(long); // Nr of. Args - length += request->name.length() + 1; // Cmd - for(TQValueList<TQCString>::Iterator it = request->arg_list.begin(); - it != request->arg_list.end(); - it++) - { - length += (*it).length() + 1; // Args... - } - length += sizeof(long); // Nr of. envs - for(TQValueList<TQCString>::ConstIterator it = request->envs.begin(); - it != request->envs.end(); - it++) - { - length += (*it).length() + 1; // Envs... - } - length += sizeof( long ); // avoid_loops -#ifdef Q_WS_X11 - bool startup_notify = !request->startup_id.isNull() && request->startup_id != "0"; - if( startup_notify ) - length += request->startup_id.length() + 1; -#endif - if (!request->cwd.isEmpty()) - length += request->cwd.length() + 1; - - requestData.resize( length ); - - char *p = requestData.data(); - long l = request->arg_list.count()+1; - memcpy(p, &l, sizeof(long)); - p += sizeof(long); - strcpy(p, request->name.data()); - p += strlen(p) + 1; - for(TQValueList<TQCString>::Iterator it = request->arg_list.begin(); - it != request->arg_list.end(); - it++) - { - strcpy(p, (*it).data()); - p += strlen(p) + 1; - } - l = request->envs.count(); - memcpy(p, &l, sizeof(long)); - p += sizeof(long); - for(TQValueList<TQCString>::ConstIterator it = request->envs.begin(); - it != request->envs.end(); - it++) - { - strcpy(p, (*it).data()); - p += strlen(p) + 1; - } - l = 0; // avoid_loops, always false here - memcpy(p, &l, sizeof(long)); - p += sizeof(long); -#ifdef Q_WS_X11 - if( startup_notify ) - { - strcpy(p, request->startup_id.data()); - p += strlen( p ) + 1; - } -#endif - if (!request->cwd.isEmpty()) - { - strcpy(p, request->cwd.data()); - p += strlen( p ) + 1; - } -#ifdef Q_WS_X11 - request_header.cmd = startup_notify ? LAUNCHER_EXT_EXEC : LAUNCHER_EXEC_NEW; -#else - request_header.cmd = LAUNCHER_EXEC_NEW; -#endif - request_header.arg_length = length; - write(tdeinitSocket, &request_header, sizeof(request_header)); - write(tdeinitSocket, requestData.data(), request_header.arg_length); - - // Wait for pid to return. - lastRequest = request; - dontBlockReading = false; - do { - slotKDEInitData( tdeinitSocket ); - } - while (lastRequest != 0); - dontBlockReading = true; -} - -void -KLauncher::exec_blind( const TQCString &name, const TQValueList<TQCString> &arg_list, - const TQValueList<TQCString> &envs, const TQCString& startup_id ) -{ - KLaunchRequest *request = new KLaunchRequest; - request->autoStart = false; - request->name = name; - request->arg_list = arg_list; - request->dcop_name = 0; - request->dcop_service_type = KService::DCOP_None; - request->pid = 0; - request->status = KLaunchRequest::Launching; - request->transaction = 0; // No confirmation is send - request->envs = envs; - // Find service, if any - strip path if needed - KService::Ptr service = KService::serviceByDesktopName( name.mid( name.findRev( '/' ) + 1 )); - if (service != NULL) - send_service_startup_info( request, service, - startup_id, TQValueList< TQCString >()); - else // no .desktop file, no startup info - cancel_service_startup_info( request, startup_id, envs ); - - requestStart(request); - // We don't care about this request any longer.... - requestDone(request); -} - - -bool -KLauncher::start_service_by_name(const TQString &serviceName, const TQStringList &urls, - const TQValueList<TQCString> &envs, const TQCString& startup_id, bool blind) -{ - KService::Ptr service = 0; - // Find service - service = KService::serviceByName(serviceName); - if (!service) - { - DCOPresult.result = ENOENT; - DCOPresult.error = i18n("Could not find service '%1'.").arg(serviceName); - cancel_service_startup_info( NULL, startup_id, envs ); // cancel it if any - return false; - } - return start_service(service, urls, envs, startup_id, blind); -} - -bool -KLauncher::start_service_by_desktop_path(const TQString &serviceName, const TQStringList &urls, - const TQValueList<TQCString> &envs, const TQCString& startup_id, bool blind) -{ - KService::Ptr service = 0; - // Find service - if (serviceName[0] == '/') - { - // Full path - service = new KService(serviceName); - } - else - { - service = KService::serviceByDesktopPath(serviceName); - } - if (!service) - { - DCOPresult.result = ENOENT; - DCOPresult.error = i18n("Could not find service '%1'.").arg(serviceName); - cancel_service_startup_info( NULL, startup_id, envs ); // cancel it if any - return false; - } - return start_service(service, urls, envs, startup_id, blind); -} - -bool -KLauncher::start_service_by_desktop_name(const TQString &serviceName, const TQStringList &urls, - const TQValueList<TQCString> &envs, const TQCString& startup_id, bool blind) -{ - KService::Ptr service = 0; - // Find service - service = KService::serviceByDesktopName(serviceName); - if (!service) - { - DCOPresult.result = ENOENT; - DCOPresult.error = i18n("Could not find service '%1'.").arg(serviceName); - cancel_service_startup_info( NULL, startup_id, envs ); // cancel it if any - return false; - } - return start_service(service, urls, envs, startup_id, blind); -} - -bool -KLauncher::start_service(KService::Ptr service, const TQStringList &_urls, - const TQValueList<TQCString> &envs, const TQCString& startup_id, bool blind, bool autoStart) -{ - TQStringList urls = _urls; - if (!service->isValid()) - { - DCOPresult.result = ENOEXEC; - DCOPresult.error = i18n("Service '%1' is malformatted.").arg(service->desktopEntryPath()); - cancel_service_startup_info( NULL, startup_id, envs ); // cancel it if any - return false; - } - KLaunchRequest *request = new KLaunchRequest; - request->autoStart = autoStart; - - if ((urls.count() > 1) && !service->allowMultipleFiles()) - { - // We need to launch the application N times. That sucks. - // We ignore the result for application 2 to N. - // For the first file we launch the application in the - // usual way. The reported result is based on this - // application. - TQStringList::ConstIterator it = urls.begin(); - for(++it; - it != urls.end(); - ++it) - { - TQStringList singleUrl; - singleUrl.append(*it); - TQCString startup_id2 = startup_id; - if( !startup_id2.isEmpty() && startup_id2 != "0" ) - startup_id2 = "0"; // can't use the same startup_id several times - start_service( service, singleUrl, envs, startup_id2, true); - } - TQString firstURL = *(urls.begin()); - urls.clear(); - urls.append(firstURL); - } - createArgs(request, service, urls); - - // We must have one argument at least! - if (!request->arg_list.count()) - { - DCOPresult.result = ENOEXEC; - DCOPresult.error = i18n("Service '%1' is malformatted.").arg(service->desktopEntryPath()); - delete request; - cancel_service_startup_info( NULL, startup_id, envs ); - return false; - } - - request->name = request->arg_list.first(); - request->arg_list.remove(request->arg_list.begin()); - - request->dcop_service_type = service->DCOPServiceType(); - - if ((request->dcop_service_type == KService::DCOP_Unique) || - (request->dcop_service_type == KService::DCOP_Multi)) - { - TQVariant v = service->property("X-DCOP-ServiceName"); - if (v.isValid()) - request->dcop_name = v.toString().utf8(); - if (request->dcop_name.isEmpty()) - { - request->dcop_name = TQFile::encodeName(KRun::binaryName(service->exec(), true)); - } - } - - request->pid = 0; - request->transaction = 0; - request->envs = envs; - send_service_startup_info( request, service, startup_id, envs ); - - // Request will be handled later. - if (!blind && !autoStart) - { - request->transaction = dcopClient()->beginTransaction(); - } - queueRequest(request); - return true; -} - -void -KLauncher::send_service_startup_info( KLaunchRequest *request, KService::Ptr service, const TQCString& startup_id, - const TQValueList<TQCString> &envs ) -{ -#if defined Q_WS_X11 && ! defined K_WS_QTONLY -//#ifdef Q_WS_X11 // KStartup* isn't implemented for Qt/Embedded yet - request->startup_id = "0"; - if( startup_id == "0" ) - return; - bool silent; - TQCString wmclass; - if( !KRun::checkStartupNotify( TQString::null, service, &silent, &wmclass )) - return; - KStartupInfoId id; - id.initId( startup_id ); - const char* dpy_str = NULL; - for( TQValueList<TQCString>::ConstIterator it = envs.begin(); - it != envs.end(); - ++it ) - if( strncmp( *it, "DISPLAY=", 8 ) == 0 ) - dpy_str = static_cast< const char* >( *it ) + 8; - Display* dpy = NULL; - if( dpy_str != NULL && mCached_dpy != NULL - && qstrcmp( dpy_str, XDisplayString( mCached_dpy )) == 0 ) - dpy = mCached_dpy; - if( dpy == NULL ) - dpy = XOpenDisplay( dpy_str ); - request->startup_id = id.id(); - if( dpy == NULL ) - { - cancel_service_startup_info( request, startup_id, envs ); - return; - } - - request->startup_dpy = dpy_str; - - KStartupInfoData data; - data.setName( service->name()); - data.setIcon( service->icon()); - data.setDescription( i18n( "Launching %1" ).arg( service->name())); - if( !wmclass.isEmpty()) - data.setWMClass( wmclass ); - if( silent ) - data.setSilent( KStartupInfoData::Yes ); - // the rest will be sent by tdeinit - KStartupInfo::sendStartupX( dpy, id, data ); - if( mCached_dpy != dpy && mCached_dpy != NULL ) - XCloseDisplay( mCached_dpy ); - mCached_dpy = dpy; - return; -#else - return; -#endif -} - -void -KLauncher::cancel_service_startup_info( KLaunchRequest* request, const TQCString& startup_id, - const TQValueList<TQCString> &envs ) -{ -#if defined Q_WS_X11 && ! defined K_WS_QTONLY -//#ifdef Q_WS_X11 // KStartup* isn't implemented for Qt/Embedded yet - if( request != NULL ) - request->startup_id = "0"; - if( !startup_id.isEmpty() && startup_id != "0" ) - { - const char* dpy_str = NULL; - for( TQValueList<TQCString>::ConstIterator it = envs.begin(); - it != envs.end(); - ++it ) - if( strncmp( *it, "DISPLAY=", 8 ) == 0 ) - dpy_str = static_cast< const char* >( *it ) + 8; - Display* dpy = NULL; - if( dpy_str != NULL && mCached_dpy != NULL - && qstrcmp( dpy_str, XDisplayString( mCached_dpy )) == 0 ) - dpy = mCached_dpy; - if( dpy == NULL ) - dpy = XOpenDisplay( dpy_str ); - if( dpy == NULL ) - return; - KStartupInfoId id; - id.initId( startup_id ); - KStartupInfo::sendFinishX( dpy, id ); - if( mCached_dpy != dpy && mCached_dpy != NULL ) - XCloseDisplay( mCached_dpy ); - mCached_dpy = dpy; - } -#endif -} - -bool -KLauncher::tdeinit_exec(const TQString &app, const TQStringList &args, - const TQValueList<TQCString> &envs, TQCString startup_id, bool wait) -{ - KLaunchRequest *request = new KLaunchRequest; - request->autoStart = false; - - for(TQStringList::ConstIterator it = args.begin(); - it != args.end(); - it++) - { - TQString arg = *it; - request->arg_list.append(arg.local8Bit()); - } - - request->name = app.local8Bit(); - - if (wait) - request->dcop_service_type = KService::DCOP_Wait; - else - request->dcop_service_type = KService::DCOP_None; - request->dcop_name = 0; - request->pid = 0; -#ifdef Q_WS_X11 - request->startup_id = startup_id; -#endif - request->envs = envs; - if( app != "kbuildsycoca" ) // avoid stupid loop - { - // Find service, if any - strip path if needed - KService::Ptr service = KService::serviceByDesktopName( app.mid( app.findRev( '/' ) + 1 )); - if (service != NULL) - send_service_startup_info( request, service, - startup_id, TQValueList< TQCString >()); - else // no .desktop file, no startup info - cancel_service_startup_info( request, startup_id, envs ); - } - request->transaction = dcopClient()->beginTransaction(); - queueRequest(request); - return true; -} - -void -KLauncher::queueRequest(KLaunchRequest *request) -{ - requestQueue.append( request ); - if (!bProcessingQueue) - { - bProcessingQueue = true; - TQTimer::singleShot(0, this, TQT_SLOT( slotDequeue() )); - } -} - -void -KLauncher::slotDequeue() -{ - do { - KLaunchRequest *request = requestQueue.take(0); - // process request - request->status = KLaunchRequest::Launching; - requestStart(request); - if (request->status != KLaunchRequest::Launching) - { - // Request handled. - requestDone( request ); - continue; - } - } while(requestQueue.count()); - bProcessingQueue = false; -} - -void -KLauncher::createArgs( KLaunchRequest *request, const KService::Ptr service , - const TQStringList &urls) -{ - TQStringList params = KRun::processDesktopExec(*service, urls, false); - - for(TQStringList::ConstIterator it = params.begin(); - it != params.end(); ++it) - { - request->arg_list.append((*it).local8Bit()); - } - request->cwd = TQFile::encodeName(service->path()); -} - -///// IO-Slave functions - -pid_t -KLauncher::requestHoldSlave(const KURL &url, const TQString &app_socket) -{ - IdleSlave *slave; - for(slave = mSlaveList.first(); slave; slave = mSlaveList.next()) - { - if (slave->onHold(url)) - break; - } - if (slave) - { - mSlaveList.removeRef(slave); - slave->connect(app_socket); - return slave->pid(); - } - return 0; -} - - -pid_t -KLauncher::requestSlave(const TQString &protocol, - const TQString &host, - const TQString &app_socket, - TQString &error) -{ - IdleSlave *slave; - for(slave = mSlaveList.first(); slave; slave = mSlaveList.next()) - { - if (slave->match(protocol, host, true)) - break; - } - if (!slave) - { - for(slave = mSlaveList.first(); slave; slave = mSlaveList.next()) - { - if (slave->match(protocol, host, false)) - break; - } - } - if (!slave) - { - for(slave = mSlaveList.first(); slave; slave = mSlaveList.next()) - { - if (slave->match(protocol, TQString::null, false)) - break; - } - } - if (slave) - { - mSlaveList.removeRef(slave); - slave->connect(app_socket); - return slave->pid(); - } - - TQString _name = KProtocolInfo::exec(protocol); - if (_name.isEmpty()) - { - error = i18n("Unknown protocol '%1'.\n").arg(protocol); - return 0; - } - - TQCString name = _name.latin1(); // ex: "kio_ftp" - TQCString arg1 = protocol.latin1(); - TQCString arg2 = TQFile::encodeName(mPoolSocketName); - TQCString arg3 = TQFile::encodeName(app_socket); - TQValueList<TQCString> arg_list; - arg_list.append(arg1); - arg_list.append(arg2); - arg_list.append(arg3); - -// kdDebug(7016) << "KLauncher: launching new slave " << _name << " with protocol=" << protocol << endl; - if (mSlaveDebug == arg1) - { - klauncher_header request_header; - request_header.cmd = LAUNCHER_DEBUG_WAIT; - request_header.arg_length = 0; - write(tdeinitSocket, &request_header, sizeof(request_header)); - } - if (mSlaveValgrind == arg1) - { - arg_list.prepend(TQFile::encodeName(KLibLoader::findLibrary(name))); - arg_list.prepend(TQFile::encodeName(locate("exe", "kioslave"))); - name = "valgrind"; - if (!mSlaveValgrindSkin.isEmpty()) { - arg_list.prepend(TQCString("--tool=") + mSlaveValgrindSkin); - } else - arg_list.prepend("--tool=memcheck"); - } - - KLaunchRequest *request = new KLaunchRequest; - request->autoStart = false; - request->name = name; - request->arg_list = arg_list; - request->dcop_name = 0; - request->dcop_service_type = KService::DCOP_None; - request->pid = 0; -#ifdef Q_WS_X11 - request->startup_id = "0"; -#endif - request->status = KLaunchRequest::Launching; - request->transaction = 0; // No confirmation is send - requestStart(request); - pid_t pid = request->pid; - -// kdDebug(7016) << "Slave launched, pid = " << pid << endl; - - // We don't care about this request any longer.... - requestDone(request); - if (!pid) - { - error = i18n("Error loading '%1'.\n").arg(TQString(name)); - } - return pid; -} - -void -KLauncher::waitForSlave(pid_t pid) -{ - IdleSlave *slave; - for(slave = mSlaveList.first(); slave; slave = mSlaveList.next()) - { - if (slave->pid() == pid) - return; // Already here. - } - SlaveWaitRequest *waitRequest = new SlaveWaitRequest; - waitRequest->transaction = dcopClient()->beginTransaction(); - waitRequest->pid = pid; - mSlaveWaitRequest.append(waitRequest); -} - -void -KLauncher::acceptSlave(TDESocket *slaveSocket) -{ - IdleSlave *slave = new IdleSlave(slaveSocket); - // Send it a SLAVE_STATUS command. - mSlaveList.append(slave); - connect(slave, TQT_SIGNAL(destroyed()), this, TQT_SLOT(slotSlaveGone())); - connect(slave, TQT_SIGNAL(statusUpdate(IdleSlave *)), - this, TQT_SLOT(slotSlaveStatus(IdleSlave *))); - if (!mTimer.isActive()) - { - mTimer.start(1000*10); - } -} - -void -KLauncher::slotSlaveStatus(IdleSlave *slave) -{ - SlaveWaitRequest *waitRequest = mSlaveWaitRequest.first(); - while(waitRequest) - { - if (waitRequest->pid == slave->pid()) - { - TQByteArray replyData; - TQCString replyType; - replyType = "void"; - dcopClient()->endTransaction( waitRequest->transaction, replyType, replyData); - mSlaveWaitRequest.removeRef(waitRequest); - waitRequest = mSlaveWaitRequest.current(); - } - else - { - waitRequest = mSlaveWaitRequest.next(); - } - } -} - -void -KLauncher::slotSlaveGone() -{ - IdleSlave *slave = (IdleSlave *) sender(); - mSlaveList.removeRef(slave); - if ((mSlaveList.count() == 0) && (mTimer.isActive())) - { - mTimer.stop(); - } -} - -void -KLauncher::idleTimeout() -{ - bool keepOneFileSlave=true; - time_t now = time(0); - IdleSlave *slave; - for(slave = mSlaveList.first(); slave; slave = mSlaveList.next()) - { - if ((slave->protocol()=="file") && (keepOneFileSlave)) - keepOneFileSlave=false; - else if (slave->age(now) > SLAVE_MAX_IDLE) - { - // killing idle slave - delete slave; - } - } -} - -#include "klauncher.moc" |