00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include "klauncher.h"
00021 #include "klauncher_cmds.h"
00022 #include "klauncher_adaptor.h"
00023
00024 #include <config.h>
00025
00026 #include <stdio.h>
00027 #include <unistd.h>
00028 #include <stdlib.h>
00029 #include <errno.h>
00030 #include <signal.h>
00031 #include <sys/time.h>
00032
00033 #include <QtCore/QFile>
00034 #ifdef Q_WS_WIN
00035 #include <QtCore/QProcess>
00036 #endif
00037
00038 #include <kconfig.h>
00039 #include <kdebug.h>
00040 #include <klibloader.h>
00041 #include <klocale.h>
00042 #include <kprotocolmanager.h>
00043 #include <kprotocolinfo.h>
00044 #include <krun.h>
00045 #include <kstandarddirs.h>
00046 #include <ktemporaryfile.h>
00047 #include <kurl.h>
00048
00049 #include <kio/global.h>
00050 #include <kio/connection.h>
00051 #include <kio/slaveinterface.h>
00052
00053 #ifdef Q_WS_X11
00054 #include <kstartupinfo.h>
00055 #include <X11/Xlib.h>
00056 #endif
00057
00058 #include <QtCore/QCoreApplication>
00059
00060
00061 #define SLAVE_MAX_IDLE 30
00062
00063 using namespace KIO;
00064
00065 IdleSlave::IdleSlave(QObject *parent)
00066 : QObject(parent)
00067 {
00068 QObject::connect(&mConn, SIGNAL(readyRead()), this, SLOT(gotInput()));
00069
00070 mConn.send( CMD_SLAVE_STATUS );
00071 mPid = 0;
00072 mBirthDate = time(0);
00073 mOnHold = false;
00074 }
00075
00076 template<int T> struct PIDType { typedef pid_t PID_t; } ;
00077 template<> struct PIDType<2> { typedef qint16 PID_t; } ;
00078 template<> struct PIDType<4> { typedef qint32 PID_t; } ;
00079
00080 void
00081 IdleSlave::gotInput()
00082 {
00083 int cmd;
00084 QByteArray data;
00085 if (mConn.read( &cmd, data) == -1)
00086 {
00087
00088 kError(7016) << "SlavePool: No communication with slave." << endl;
00089 delete this;
00090 }
00091 else if (cmd == MSG_SLAVE_ACK)
00092 {
00093 delete this;
00094 }
00095 else if (cmd != MSG_SLAVE_STATUS)
00096 {
00097 kError(7016) << "SlavePool: Unexpected data from slave." << endl;
00098 delete this;
00099 }
00100 else
00101 {
00102 QDataStream stream( data );
00103 PIDType<sizeof(pid_t)>::PID_t stream_pid;
00104 pid_t pid;
00105 QByteArray protocol;
00106 QString host;
00107 qint8 b;
00108 stream >> stream_pid >> protocol >> host >> b;
00109 pid = stream_pid;
00110
00111 if (!stream.atEnd())
00112 {
00113 KUrl url;
00114 stream >> url;
00115 mOnHold = true;
00116 mUrl = url;
00117 }
00118
00119 mPid = pid;
00120 mConnected = (b != 0);
00121 mProtocol = QString::fromLatin1(protocol);
00122 mHost = host;
00123 emit statusUpdate(this);
00124 }
00125 }
00126
00127 void
00128 IdleSlave::connect(const QString &app_socket)
00129 {
00130 QByteArray data;
00131 QDataStream stream( &data, QIODevice::WriteOnly);
00132 stream << app_socket;
00133 mConn.send( CMD_SLAVE_CONNECT, data );
00134
00135 }
00136
00137 void
00138 IdleSlave::reparseConfiguration()
00139 {
00140 mConn.send( CMD_REPARSECONFIGURATION );
00141 }
00142
00143 bool
00144 IdleSlave::match(const QString &protocol, const QString &host, bool connected)
00145 {
00146 if (mOnHold) return false;
00147 if (protocol != mProtocol) return false;
00148 if (host.isEmpty()) return true;
00149 if (host != mHost) return false;
00150 if (!connected) return true;
00151 if (!mConnected) return false;
00152 return true;
00153 }
00154
00155 bool
00156 IdleSlave::onHold(const KUrl &url)
00157 {
00158 if (!mOnHold) return false;
00159 return (url == mUrl);
00160 }
00161
00162 int
00163 IdleSlave::age(time_t now)
00164 {
00165 return (int) difftime(now, mBirthDate);
00166 }
00167
00168 KLauncher::KLauncher(int _kdeinitSocket)
00169 : QObject(0),
00170 kdeinitSocket(_kdeinitSocket), dontBlockReading(false)
00171 {
00172 #ifdef Q_WS_X11
00173 mCached_dpy = NULL;
00174 #endif
00175 mAutoTimer.setSingleShot(true);
00176 new KLauncherAdaptor(this);
00177 QDBusConnection::sessionBus().registerObject("/KLauncher", this);
00178
00179 connect(&mAutoTimer, SIGNAL(timeout()), this, SLOT(slotAutoStart()));
00180 connect(QDBusConnection::sessionBus().interface(),
00181 SIGNAL(serviceOwnerChanged(QString,QString,QString)),
00182 SLOT(slotNameOwnerChanged(QString,QString,QString)));
00183
00184 mConnectionServer.listenForRemote();
00185 connect(&mConnectionServer, SIGNAL(newConnection()), SLOT(acceptSlave()));
00186 if (!mConnectionServer.isListening())
00187 {
00188
00189 qDebug("KLauncher: Fatal error, can't create tempfile!");
00190 ::_exit(1);
00191 }
00192
00193 connect(&mTimer, SIGNAL(timeout()), SLOT(idleTimeout()));
00194
00195 #ifndef Q_WS_WIN
00196 kdeinitNotifier = new QSocketNotifier(kdeinitSocket, QSocketNotifier::Read);
00197 connect(kdeinitNotifier, SIGNAL( activated( int )),
00198 this, SLOT( slotKDEInitData( int )));
00199 kdeinitNotifier->setEnabled( true );
00200 #endif
00201 lastRequest = 0;
00202 bProcessingQueue = false;
00203
00204 mSlaveDebug = getenv("KDE_SLAVE_DEBUG_WAIT");
00205 if (!mSlaveDebug.isEmpty())
00206 {
00207 qWarning("Klauncher running in slave-debug mode for slaves of protocol '%s'", qPrintable(mSlaveDebug));
00208 }
00209 mSlaveValgrind = getenv("KDE_SLAVE_VALGRIND");
00210 if (!mSlaveValgrind.isEmpty())
00211 {
00212 mSlaveValgrindSkin = getenv("KDE_SLAVE_VALGRIND_SKIN");
00213 qWarning("Klauncher running slaves through valgrind for slaves of protocol '%s'", qPrintable(mSlaveValgrind));
00214 }
00215 #ifdef Q_WS_WIN
00216 kDebug(7016) << "LAUNCHER_OK";
00217 #else
00218 klauncher_header request_header;
00219 request_header.cmd = LAUNCHER_OK;
00220 request_header.arg_length = 0;
00221 write(kdeinitSocket, &request_header, sizeof(request_header));
00222 #endif
00223 }
00224
00225 KLauncher::~KLauncher()
00226 {
00227 close();
00228 }
00229
00230 void KLauncher::close()
00231 {
00232 #ifdef Q_WS_X11
00233 if( mCached_dpy != NULL )
00234 XCloseDisplay( mCached_dpy );
00235 #endif
00236 }
00237
00238 void
00239 KLauncher::destruct(int exit_code)
00240 {
00241 if (QCoreApplication::instance()) ((KLauncher*)QCoreApplication::instance())->close();
00242
00243 ::_exit(exit_code);
00244 }
00245
00246 void KLauncher::setLaunchEnv(const QString &name, const QString &value)
00247 {
00248 #ifdef Q_WS_WIN
00249
00250 #else
00251 klauncher_header request_header;
00252 QByteArray requestData;
00253 requestData.append(name.toLocal8Bit()).append('\0').append(value.toLocal8Bit()).append('\0');
00254 request_header.cmd = LAUNCHER_SETENV;
00255 request_header.arg_length = requestData.size();
00256 write(kdeinitSocket, &request_header, sizeof(request_header));
00257 write(kdeinitSocket, requestData.data(), request_header.arg_length);
00258 #endif
00259 }
00260
00261 #ifndef Q_WS_WIN
00262
00263
00264
00265
00266 static int
00267 read_socket(int sock, char *buffer, int len)
00268 {
00269 ssize_t result;
00270 int bytes_left = len;
00271 while ( bytes_left > 0)
00272 {
00273 result = read(sock, buffer, bytes_left);
00274 if (result > 0)
00275 {
00276 buffer += result;
00277 bytes_left -= result;
00278 }
00279 else if (result == 0)
00280 return -1;
00281 else if ((result == -1) && (errno != EINTR))
00282 return -1;
00283 }
00284 return 0;
00285 }
00286
00287
00288 void
00289 KLauncher::slotKDEInitData(int)
00290 {
00291 klauncher_header request_header;
00292 QByteArray requestData;
00293 if( dontBlockReading )
00294 {
00295
00296
00297
00298
00299 fd_set in;
00300 timeval tm = { 0, 0 };
00301 FD_ZERO ( &in );
00302 FD_SET( kdeinitSocket, &in );
00303 select( kdeinitSocket + 1, &in, 0, 0, &tm );
00304 if( !FD_ISSET( kdeinitSocket, &in ))
00305 return;
00306 }
00307 dontBlockReading = false;
00308 int result = read_socket(kdeinitSocket, (char *) &request_header,
00309 sizeof( request_header));
00310 if (result == -1)
00311 {
00312 kDebug(7016) << "Exiting on read_socket errno:" << errno;
00313 ::signal( SIGHUP, SIG_IGN);
00314 ::signal( SIGTERM, SIG_IGN);
00315 destruct(255);
00316 }
00317 requestData.resize(request_header.arg_length);
00318 result = read_socket(kdeinitSocket, (char *) requestData.data(),
00319 request_header.arg_length);
00320
00321 processRequestReturn(request_header.cmd,requestData);
00322
00323 }
00324 #endif
00325
00326 void KLauncher::processRequestReturn(int status, const QByteArray &requestData)
00327 {
00328 if (status == LAUNCHER_DIED)
00329 {
00330 long *request_data;
00331 request_data = (long *) requestData.data();
00332 processDied(request_data[0], request_data[1]);
00333 return;
00334 }
00335 if (lastRequest && (status == LAUNCHER_OK))
00336 {
00337 long *request_data;
00338 request_data = (long *) requestData.data();
00339 lastRequest->pid = (pid_t) (*request_data);
00340 kDebug(7016).nospace() << lastRequest->name << " (pid " << lastRequest->pid <<
00341 ") up and running.";
00342 switch(lastRequest->dbus_startup_type)
00343 {
00344 case KService::DBusNone:
00345 lastRequest->status = KLaunchRequest::Running;
00346 break;
00347 case KService::DBusUnique:
00348 case KService::DBusWait:
00349 case KService::DBusMulti:
00350 lastRequest->status = KLaunchRequest::Launching;
00351 break;
00352 }
00353 lastRequest = 0;
00354 return;
00355 }
00356 if (lastRequest && (status == LAUNCHER_ERROR))
00357 {
00358 lastRequest->status = KLaunchRequest::Error;
00359 kDebug(7016) << lastRequest->name << " failed." << endl;
00360 if (!requestData.isEmpty())
00361 lastRequest->errorMsg = QString::fromUtf8((char *) requestData.data());
00362 lastRequest = 0;
00363 return;
00364 }
00365
00366 kWarning(7016)<< "Unexpected request return" << (unsigned int) status;
00367 }
00368
00369 void
00370 KLauncher::processDied(pid_t pid, long )
00371 {
00372 foreach (KLaunchRequest *request, requestList)
00373 {
00374 if (request->pid == pid)
00375 {
00376 if (request->dbus_startup_type == KService::DBusWait)
00377 request->status = KLaunchRequest::Done;
00378 else if ((request->dbus_startup_type == KService::DBusUnique)
00379 && QDBusConnection::sessionBus().interface()->isServiceRegistered(request->dbus_name))
00380 request->status = KLaunchRequest::Running;
00381 else
00382 request->status = KLaunchRequest::Error;
00383 requestDone(request);
00384 return;
00385 }
00386 }
00387 }
00388
00389 void
00390 KLauncher::slotNameOwnerChanged(const QString &appId, const QString &oldOwner,
00391 const QString &newOwner)
00392 {
00393 Q_UNUSED(oldOwner);
00394 if (appId.isEmpty() || newOwner.isEmpty())
00395 return;
00396
00397 foreach (KLaunchRequest *request, requestList)
00398 {
00399 if (request->status != KLaunchRequest::Launching)
00400 continue;
00401
00402
00403 if ((request->dbus_startup_type == KService::DBusUnique) &&
00404 ((appId == request->dbus_name) ||
00405 QDBusConnection::sessionBus().interface()->isServiceRegistered(request->dbus_name)))
00406 {
00407 request->status = KLaunchRequest::Running;
00408 requestDone(request);
00409 continue;
00410 }
00411
00412 const QString rAppId = request->dbus_name;
00413 if (rAppId.isEmpty())
00414 return;
00415
00416
00417
00418 QChar c = appId.length() > rAppId.length() ? appId.at(rAppId.length()) : QChar();
00419 if (appId.startsWith(rAppId) && ((appId.length() == rAppId.length()) ||
00420 (c == QLatin1Char('-'))))
00421 {
00422 request->dbus_name = appId;
00423 request->status = KLaunchRequest::Running;
00424 requestDone(request);
00425 continue;
00426 }
00427 }
00428 }
00429
00430 void
00431 KLauncher::autoStart(int phase)
00432 {
00433 if( mAutoStart.phase() >= phase )
00434 return;
00435 mAutoStart.setPhase(phase);
00436 if (phase == 0)
00437 mAutoStart.loadAutoStartList();
00438 mAutoTimer.start(0);
00439 }
00440
00441 void
00442 KLauncher::slotAutoStart()
00443 {
00444 KService::Ptr s;
00445 do
00446 {
00447 QString service = mAutoStart.startService();
00448 if (service.isEmpty())
00449 {
00450
00451 if( !mAutoStart.phaseDone())
00452 {
00453 mAutoStart.setPhaseDone();
00454 switch( mAutoStart.phase())
00455 {
00456 case 0:
00457 emit autoStart0Done();
00458 break;
00459 case 1:
00460 emit autoStart1Done();
00461 break;
00462 case 2:
00463 emit autoStart2Done();
00464 break;
00465 }
00466 }
00467 return;
00468 }
00469 s = new KService(service);
00470 }
00471 while (!start_service(s, QStringList(), QStringList(), "0", false, true, QDBusMessage()));
00472
00473 }
00474
00475 void
00476 KLauncher::requestDone(KLaunchRequest *request)
00477 {
00478 if ((request->status == KLaunchRequest::Running) ||
00479 (request->status == KLaunchRequest::Done))
00480 {
00481 requestResult.result = 0;
00482 requestResult.dbusName = request->dbus_name;
00483 requestResult.error = "";
00484 requestResult.pid = request->pid;
00485 }
00486 else
00487 {
00488 requestResult.result = 1;
00489 requestResult.dbusName = "";
00490 requestResult.error = i18n("KDEInit could not launch '%1'.", request->name);
00491 if (!request->errorMsg.isEmpty())
00492 requestResult.error += ":\n" + request->errorMsg;
00493 requestResult.pid = 0;
00494
00495 #ifdef Q_WS_X11
00496 if (!request->startup_dpy.isEmpty())
00497 {
00498 Display* dpy = NULL;
00499 if( (mCached_dpy != NULL) &&
00500 (request->startup_dpy == XDisplayString( mCached_dpy )))
00501 dpy = mCached_dpy;
00502 if( dpy == NULL )
00503 dpy = XOpenDisplay( request->startup_dpy.toLocal8Bit() );
00504 if( dpy )
00505 {
00506 KStartupInfoId id;
00507 id.initId( request->startup_id.toLocal8Bit() );
00508 KStartupInfo::sendFinishX( dpy, id );
00509 if( mCached_dpy != dpy && mCached_dpy != NULL )
00510 XCloseDisplay( mCached_dpy );
00511 mCached_dpy = dpy;
00512 }
00513 }
00514 #endif
00515 }
00516
00517 if (request->autoStart)
00518 {
00519 mAutoTimer.start(0);
00520 }
00521
00522 if (request->transaction.type() != QDBusMessage::InvalidMessage)
00523 {
00524 if ( requestResult.dbusName.isNull() )
00525 requestResult.dbusName = "";
00526 Q_ASSERT( !requestResult.error.isNull() );
00527 PIDType<sizeof(pid_t)>::PID_t stream_pid = requestResult.pid;
00528 QDBusConnection::sessionBus().send(request->transaction.createReply(QVariantList() << requestResult.result
00529 << requestResult.dbusName
00530 << requestResult.error
00531 << stream_pid));
00532 }
00533 requestList.removeAll( request );
00534 delete request;
00535 }
00536
00537 static void appendLong(QByteArray &ba, long l)
00538 {
00539 const int sz = ba.size();
00540 ba.resize(sz + sizeof(long));
00541 memcpy(ba.data() + sz, &l, sizeof(long));
00542 }
00543
00544 void
00545 KLauncher::requestStart(KLaunchRequest *request)
00546 {
00547 #ifdef Q_WS_WIN
00548 requestList.append( request );
00549 lastRequest = request;
00550
00551 QProcess *process = new QProcess;
00552 process->setProcessChannelMode(QProcess::MergedChannels);
00553 connect(process ,SIGNAL(readyReadStandardOutput()),this, SLOT(slotGotOutput()) );
00554 processList << process;
00555
00556
00557 QStringList args;
00558 foreach (QString arg, request->arg_list)
00559 args << arg;
00560
00561 process->start(request->name,args);
00562
00563 _PROCESS_INFORMATION* _pid = process->pid();
00564 int pid = _pid ? _pid->dwProcessId : 0;
00565
00566 if (pid)
00567 {
00568 request->pid = pid;
00569 QByteArray data((char *)&pid, sizeof(int));
00570 processRequestReturn(LAUNCHER_OK,data);
00571 }
00572 else
00573 {
00574 processRequestReturn(LAUNCHER_ERROR,"");
00575 }
00576 return;
00577
00578 #else
00579 requestList.append( request );
00580
00581 klauncher_header request_header;
00582 QByteArray requestData;
00583 requestData.reserve(1024);
00584
00585 appendLong(requestData, request->arg_list.count() + 1);
00586 requestData.append(request->name.toLocal8Bit());
00587 requestData.append('\0');
00588 foreach (QString arg, request->arg_list)
00589 requestData.append(arg.toLocal8Bit()).append('\0');
00590 appendLong(requestData, request->envs.count());
00591 foreach (QString env, request->envs)
00592 requestData.append(env.toLocal8Bit()).append('\0');
00593 appendLong(requestData, 0);
00594 #ifdef Q_WS_X11
00595 bool startup_notify = !request->startup_id.isNull() && request->startup_id != "0";
00596 if( startup_notify )
00597 requestData.append(request->startup_id.toLocal8Bit()).append('\0');
00598 #endif
00599 if (!request->cwd.isEmpty())
00600 requestData.append(request->cwd.toLocal8Bit()).append('\0');
00601
00602 #ifdef Q_WS_X11
00603 request_header.cmd = startup_notify ? LAUNCHER_EXT_EXEC : LAUNCHER_EXEC_NEW;
00604 #else
00605 request_header.cmd = LAUNCHER_EXEC_NEW;
00606 #endif
00607 request_header.arg_length = requestData.length();
00608 write(kdeinitSocket, &request_header, sizeof(request_header));
00609 write(kdeinitSocket, requestData.data(), requestData.length());
00610
00611
00612 lastRequest = request;
00613 dontBlockReading = false;
00614 do {
00615 slotKDEInitData( kdeinitSocket );
00616 }
00617 while (lastRequest != 0);
00618 dontBlockReading = true;
00619 #endif
00620 }
00621
00622 void KLauncher::exec_blind(const QString &name, const QStringList &arg_list, const QStringList &envs, const QString &startup_id)
00623 {
00624 KLaunchRequest *request = new KLaunchRequest;
00625 request->autoStart = false;
00626 request->name = name;
00627 request->arg_list = arg_list;
00628 request->dbus_startup_type = KService::DBusNone;
00629 request->pid = 0;
00630 request->status = KLaunchRequest::Launching;
00631 request->envs = envs;
00632
00633 KService::Ptr service = KService::serviceByDesktopName( name.mid( name.lastIndexOf( '/' ) + 1 ));
00634 if (service)
00635 send_service_startup_info( request, service, startup_id, QStringList());
00636 else
00637 cancel_service_startup_info( request, startup_id, envs );
00638
00639 requestStart(request);
00640
00641 requestDone(request);
00642 }
00643
00644
00645 bool
00646 KLauncher::start_service_by_name(const QString &serviceName, const QStringList &urls,
00647 const QStringList &envs, const QString& startup_id, bool blind, const QDBusMessage &msg)
00648 {
00649 KService::Ptr service;
00650
00651 service = KService::serviceByName(serviceName);
00652 if (!service)
00653 {
00654 requestResult.result = ENOENT;
00655 requestResult.error = i18n("Could not find service '%1'.", serviceName);
00656 cancel_service_startup_info( NULL, startup_id, envs );
00657 return false;
00658 }
00659 return start_service(service, urls, envs, startup_id, blind, false, msg);
00660 }
00661
00662 bool
00663 KLauncher::start_service_by_desktop_path(const QString &serviceName, const QStringList &urls,
00664 const QStringList &envs, const QString& startup_id, bool blind, const QDBusMessage &msg)
00665 {
00666 KService::Ptr service;
00667
00668 if (serviceName.startsWith(QLatin1Char('/')))
00669 {
00670
00671 service = new KService(serviceName);
00672 }
00673 else
00674 {
00675 service = KService::serviceByDesktopPath(serviceName);
00676 }
00677 if (!service)
00678 {
00679 requestResult.result = ENOENT;
00680 requestResult.error = i18n("Could not find service '%1'.", serviceName);
00681 cancel_service_startup_info( NULL, startup_id, envs );
00682 return false;
00683 }
00684 return start_service(service, urls, envs, startup_id, blind, false, msg);
00685 }
00686
00687 bool
00688 KLauncher::start_service_by_desktop_name(const QString &serviceName, const QStringList &urls,
00689 const QStringList &envs, const QString& startup_id, bool blind, const QDBusMessage &msg)
00690 {
00691 KService::Ptr service = KService::serviceByDesktopName(serviceName);
00692 if (!service)
00693 {
00694 requestResult.result = ENOENT;
00695 requestResult.error = i18n("Could not find service '%1'.", serviceName);
00696 cancel_service_startup_info( NULL, startup_id, envs );
00697 return false;
00698 }
00699 return start_service(service, urls, envs, startup_id, blind, false, msg);
00700 }
00701
00702 bool
00703 KLauncher::start_service(KService::Ptr service, const QStringList &_urls,
00704 const QStringList &envs, const QString &startup_id,
00705 bool blind, bool autoStart, const QDBusMessage &msg)
00706 {
00707 QStringList urls = _urls;
00708 if (!service->isValid())
00709 {
00710 requestResult.result = ENOEXEC;
00711 requestResult.error = i18n("Service '%1' is malformatted.", service->entryPath());
00712 cancel_service_startup_info( NULL, startup_id, envs );
00713 return false;
00714 }
00715 KLaunchRequest *request = new KLaunchRequest;
00716 request->autoStart = autoStart;
00717
00718 if ((urls.count() > 1) && !service->allowMultipleFiles())
00719 {
00720
00721
00722
00723
00724
00725 QStringList::ConstIterator it = urls.begin();
00726 for(++it;
00727 it != urls.end();
00728 ++it)
00729 {
00730 QStringList singleUrl;
00731 singleUrl.append(*it);
00732 QString startup_id2 = startup_id;
00733 if( !startup_id2.isEmpty() && startup_id2 != "0" )
00734 startup_id2 = "0";
00735 start_service( service, singleUrl, envs, startup_id2, true, false, msg);
00736 }
00737 QString firstURL = *(urls.begin());
00738 urls.clear();
00739 urls.append(firstURL);
00740 }
00741 createArgs(request, service, urls);
00742
00743
00744 if (!request->arg_list.count())
00745 {
00746 requestResult.result = ENOEXEC;
00747 requestResult.error = i18n("Service '%1' is malformatted.", service->entryPath());
00748 delete request;
00749 cancel_service_startup_info( NULL, startup_id, envs );
00750 return false;
00751 }
00752
00753 request->name = request->arg_list.takeFirst();
00754 request->dbus_startup_type = service->dbusStartupType();
00755
00756 if ((request->dbus_startup_type == KService::DBusUnique) ||
00757 (request->dbus_startup_type == KService::DBusMulti))
00758 {
00759 QVariant v = service->property("X-DBUS-ServiceName");
00760 if (v.isValid())
00761 request->dbus_name = v.toString().toUtf8();
00762 if (request->dbus_name.isEmpty())
00763 {
00764 request->dbus_name = "org.kde." + QFile::encodeName(KRun::binaryName(service->exec(), true));
00765 }
00766 }
00767
00768 request->pid = 0;
00769 request->envs = envs;
00770 send_service_startup_info( request, service, startup_id, envs );
00771
00772
00773 if (!blind && !autoStart)
00774 {
00775 msg.setDelayedReply(true);
00776 request->transaction = msg;
00777 }
00778 queueRequest(request);
00779 return true;
00780 }
00781
00782 void
00783 KLauncher::send_service_startup_info( KLaunchRequest *request, KService::Ptr service, const QString& startup_id,
00784 const QStringList &envs )
00785 {
00786 #ifdef Q_WS_X11
00787 request->startup_id = "0";
00788 if( startup_id == "0" )
00789 return;
00790 bool silent;
00791 QByteArray wmclass;
00792 if( !KRun::checkStartupNotify( QString(), service.data(), &silent, &wmclass ))
00793 return;
00794 KStartupInfoId id;
00795 id.initId( startup_id.toLatin1() );
00796 QString dpy_str;
00797 foreach (QString env, envs) {
00798 if (env.startsWith(QLatin1String("DISPLAY=")))
00799 dpy_str = env.mid(8);
00800 }
00801 Display* dpy = NULL;
00802 if( !dpy_str.isEmpty() && mCached_dpy != NULL
00803 && dpy_str != QLatin1String(XDisplayString(mCached_dpy)) )
00804 dpy = mCached_dpy;
00805 if( dpy == NULL )
00806 dpy = XOpenDisplay( dpy_str.toLatin1().constData() );
00807 request->startup_id = id.id();
00808 if( dpy == NULL )
00809 {
00810 cancel_service_startup_info( request, startup_id, envs );
00811 return;
00812 }
00813
00814 request->startup_dpy = dpy_str;
00815
00816 KStartupInfoData data;
00817 data.setName( service->name());
00818 data.setIcon( service->icon());
00819 data.setDescription( i18n( "Launching %1" , service->name()));
00820 if( !wmclass.isEmpty())
00821 data.setWMClass( wmclass );
00822 if( silent )
00823 data.setSilent( KStartupInfoData::Yes );
00824
00825 KStartupInfo::sendStartupX( dpy, id, data );
00826 if( mCached_dpy != dpy && mCached_dpy != NULL )
00827 XCloseDisplay( mCached_dpy );
00828 mCached_dpy = dpy;
00829 return;
00830 #else
00831 return;
00832 #endif
00833 }
00834
00835 void
00836 KLauncher::cancel_service_startup_info( KLaunchRequest* request, const QString& startup_id,
00837 const QStringList &envs )
00838 {
00839 #ifdef Q_WS_X11
00840 if( request != NULL )
00841 request->startup_id = "0";
00842 if( !startup_id.isEmpty() && startup_id != "0" )
00843 {
00844 QString dpy_str;
00845