/*
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 KIO ;
template class TQPtrList < KLaunchRequest > ;
template class TQPtrList < IdleSlave > ;
IdleSlave : : IdleSlave ( KSocket * 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 )
// : KApplication( false, false ), // No Styles, No GUI
: KApplication ( 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 KServerSocket ( static_cast < const char * > ( TQFile : : encodeName ( mPoolSocketName ) ) ) ;
connect ( mPoolSocket , TQT_SIGNAL ( accepted ( KSocket * ) ) ,
TQT_SLOT ( acceptSlave ( KSocket * ) ) ) ;
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() " )
{
KGlobal : : 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 ( KSocket * 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"