File indexing completed on 2024-04-28 15:25:51
0001 /* 0002 This file is part of the KDE libraries 0003 SPDX-FileCopyrightText: 1999 Waldo Bastian <bastian@kde.org> 0004 0005 SPDX-License-Identifier: LGPL-2.0-only 0006 */ 0007 0008 #ifndef _KLAUNCHER_H_ 0009 #define _KLAUNCHER_H_ 0010 0011 #include <qplatformdefs.h> 0012 0013 #include <config-kdeinit.h> // HAVE_X11 0014 0015 #if defined(Q_OS_WIN) || defined(Q_OS_OSX) 0016 #define USE_KPROCESS_FOR_KIOSLAVES 0017 #endif 0018 #ifdef Q_CC_MSVC 0019 typedef unsigned int pid_t; 0020 #endif 0021 0022 #include <QString> 0023 #include <QSocketNotifier> 0024 #include <QTimer> 0025 #include <QList> 0026 #include <QObject> 0027 #include <QProcess> 0028 #include <QDateTime> 0029 #include <QUrl> 0030 #include <QDBusConnection> 0031 #include <QDBusMessage> 0032 #include <QDBusContext> 0033 0034 #include <KService> 0035 #include <kio/idleslave.h> 0036 #include <kio/connectionserver.h> 0037 0038 using KIO::IdleSlave; 0039 0040 class KSlaveLauncherAdaptor; 0041 0042 struct xcb_connection_t; 0043 0044 class SlaveWaitRequest 0045 { 0046 public: 0047 pid_t pid; 0048 QDBusMessage transaction; 0049 }; 0050 0051 class KLaunchRequest 0052 { 0053 public: 0054 QString name; 0055 QStringList arg_list; 0056 QString dbus_name; 0057 QString tolerant_dbus_name; 0058 enum status_t { Init = 0, Launching, Running, Error, Done }; 0059 pid_t pid; 0060 status_t status; 0061 QDBusMessage transaction; 0062 KService::DBusStartupType dbus_startup_type; 0063 bool wait; //wait until the process dies before finishing the request 0064 QString errorMsg; 0065 #if HAVE_X11 0066 QByteArray startup_id; // "" is the default, "0" for none 0067 QByteArray startup_dpy; // Display to send startup notification to. 0068 #endif 0069 QStringList envs; // env. variables to be app's environment 0070 QString cwd; 0071 #ifdef USE_KPROCESS_FOR_KIOSLAVES 0072 protected: 0073 QProcess *process; 0074 friend class KLauncher; 0075 #endif 0076 }; 0077 0078 struct serviceResult { 0079 int result; // 0 means success. > 0 means error (-1 means pending) 0080 QString dbusName; // Contains DBUS name on success 0081 QString error; // Contains error description on failure. 0082 pid_t pid; 0083 }; 0084 0085 class KLauncher : public QObject, protected QDBusContext 0086 { 0087 Q_OBJECT 0088 0089 public: 0090 #ifndef USE_KPROCESS_FOR_KIOSLAVES 0091 KLauncher(int kdeinitSocket); 0092 #else 0093 KLauncher(); 0094 #endif 0095 0096 ~KLauncher() override; 0097 0098 void close(); 0099 0100 public Q_SLOTS: 0101 Q_NORETURN void destruct(); // exit! 0102 0103 protected: 0104 void processDied(pid_t pid, long exitStatus); 0105 0106 void requestStart(KLaunchRequest *request); 0107 void requestDone(KLaunchRequest *request); 0108 0109 bool start_service(KService::Ptr service, const QStringList &urls, 0110 const QStringList &envs, const QByteArray &startup_id, 0111 bool blind, const QDBusMessage &msg); 0112 0113 void createArgs(KLaunchRequest *request, const KService::Ptr service, 0114 const QList<QUrl> &url); 0115 0116 void queueRequest(KLaunchRequest *); 0117 0118 void send_service_startup_info(KLaunchRequest *request, KService::Ptr service, const QByteArray &startup_id, 0119 const QStringList &envs); 0120 void cancel_service_startup_info(KLaunchRequest *request, const QByteArray &startup_id, 0121 const QStringList &envs); 0122 0123 public: // remote methods, called by KLauncherAdaptor 0124 /** 0125 * Starts a program. 0126 * 'envs' are environment variables that will be added 0127 * to this program's environment before starting it 0128 * 'startup_id' is for application startup notification, 0129 * "" is the default, "0" for none 0130 */ 0131 void exec_blind(const QString &name, const QStringList &arg_list, const QStringList &envs, const QString &startup_id); 0132 inline void exec_blind(const QString &name, const QStringList &arg_list) 0133 { 0134 exec_blind(name, arg_list, QStringList(), QStringLiteral("0")); 0135 } 0136 0137 bool kdeinit_exec(const QString &app, const QStringList &args, 0138 const QString &workdir, const QStringList &envs, 0139 const QString &startup_id, bool wait, const QDBusMessage &msg); 0140 0141 void reparseConfiguration(); 0142 void setLaunchEnv(const QString &name, const QString &value); 0143 0144 /** 0145 * Start a service by desktop name. 0146 * 0147 * 'serviceName' refers to a desktop file describing the service. 0148 * The service is looked up anywhere in the applications and services directories 0149 * (see KStandardDirs resource "xdgdata-apps" and "services"). 0150 * E.g. it should have the form "korganizer". 0151 * 0152 * 'url', if not empty, will be passed to the service as 0153 * argument. 0154 * 0155 * 'envs' are environment variables that will be added 0156 * to this program's environment before starting it 0157 * 0158 * 'startup_id' is for application startup notification, 0159 * "" is the default, "0" for none 0160 */ 0161 bool start_service_by_desktop_name(const QString &serviceName, const QStringList &urls, const QStringList &envs, const QString &startup_id, bool blind, const QDBusMessage &msg); 0162 0163 /** 0164 * Start a service by desktop path. 0165 * 0166 * 'serviceName' refers to a desktop file describing the service. 0167 * This may be an absolute path or a path relative to the applications 0168 * and/or services directories (see KStandardDirs) 0169 * E.g. it should have the form "korganizer.desktop" or 0170 * "/opt/kde/share/applications/korganizer.desktop". 0171 * Note that for absolute paths the restrictions of 0172 * KDesktopFile::isAuthorizedDesktopFile() are obeyed for security. 0173 * 0174 * 'url', if not empty, will be passed to the service as 0175 * argument. 0176 * 0177 * 'envs' are environment variables that will be added 0178 * to this program's environment before starting it 0179 * 0180 * 'startup_id' is for application startup notification, 0181 * "" is the default, "0" for none 0182 */ 0183 bool start_service_by_desktop_path(const QString &serviceName, const QStringList &urls, const QStringList &envs, const QString &startup_id, bool blind, const QDBusMessage &msg); 0184 0185 pid_t requestHoldSlave(const QString &url, const QString &app_socket); 0186 0187 pid_t requestSlave(const QString &protocol, const QString &host, 0188 const QString &app_socket, QString &error); 0189 /** 0190 * Return true of there is a slave held for @p url. 0191 * @since 4.7 0192 */ 0193 bool checkForHeldSlave(const QString &url); 0194 void waitForSlave(int pid); 0195 void terminate_kdeinit(); 0196 0197 public Q_SLOTS: 0198 void slotDequeue(); 0199 void slotKDEInitData(int); 0200 void slotNameOwnerChanged(const QString &name, const QString &oldOnwer, const QString &newOwner); 0201 void slotSlaveStatus(IdleSlave *); 0202 void acceptSlave(); 0203 void slotSlaveGone(); 0204 void idleTimeout(); 0205 0206 public: 0207 serviceResult requestResult; // accessed by the adaptor 0208 protected: 0209 QList<KLaunchRequest *> requestList; // Requests being handled 0210 QList<KLaunchRequest *> requestQueue; // Requests waiting to being handled 0211 KLaunchRequest *lastRequest; 0212 QList<SlaveWaitRequest *> mSlaveWaitRequest; 0213 #ifndef USE_KPROCESS_FOR_KIOSLAVES 0214 int kdeinitSocket; 0215 QSocketNotifier *kdeinitNotifier; 0216 #endif 0217 KIO::ConnectionServer mConnectionServer; 0218 QList<IdleSlave *> mSlaveList; 0219 QTimer mTimer; 0220 bool bProcessingQueue; 0221 QString mSlaveDebug; 0222 QString mSlaveValgrind; 0223 QString mSlaveValgrindSkin; 0224 KSlaveLauncherAdaptor *mSlaveLauncherAdaptor; 0225 bool dontBlockReading; 0226 #if HAVE_X11 0227 bool mIsX11; 0228 #endif 0229 void processRequestReturn(int status, const QByteArray &requestData); 0230 0231 protected Q_SLOTS: 0232 void slotGotOutput(); 0233 void slotFinished(int exitCode, QProcess::ExitStatus exitStatus); 0234 0235 private: 0236 #if HAVE_XCB 0237 struct XCBConnection { 0238 XCBConnection() : conn(nullptr), screen(0) { } 0239 0240 operator bool() const { 0241 return conn != nullptr; 0242 } 0243 0244 xcb_connection_t *conn; 0245 int screen; 0246 QByteArray displayName; 0247 } mCached; 0248 0249 XCBConnection getXCBConnection(const QByteArray &displyName); 0250 #endif 0251 }; 0252 #endif