1/*
2 This file is part of the KDE libraries
3 Copyright (c) 1999 Waldo Bastian <bastian@kde.org>
4
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Library General Public
7 License version 2 as published by the Free Software Foundation.
8
9 This library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Library General Public License for more details.
13
14 You should have received a copy of the GNU Library General Public License
15 along with this library; see the file COPYING.LIB. If not, write to
16 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 Boston, MA 02110-1301, USA.
18*/
19
20#ifndef _KLAUNCHER_H_
21#define _KLAUNCHER_H_
22
23#include "autostart.h"
24
25#include <sys/types.h>
26#include <unistd.h>
27#include <time.h>
28
29#ifdef Q_WS_X11
30#include <X11/Xlib.h>
31#include <fixx11h.h>
32#endif
33
34#if defined(Q_WS_WIN) || defined(Q_WS_MAC)
35#define USE_KPROCESS_FOR_KIOSLAVES
36#endif
37
38#include <QtCore/QString>
39#include <QtCore/QSocketNotifier>
40#include <QtCore/QTimer>
41#include <QtCore/QList>
42#include <QtCore/QObject>
43#include <QtDBus/QtDBus>
44
45#include <kservice.h>
46#include <kprocess.h>
47#include <kurl.h>
48#include <kio/connection.h>
49
50class IdleSlave : public QObject
51{
52 Q_OBJECT
53public:
54 explicit IdleSlave(QObject *parent);
55 bool match( const QString &protocol, const QString &host, bool connected) const;
56 void connect( const QString &app_socket);
57 pid_t pid() const { return mPid;}
58 int age(time_t now) const;
59 void reparseConfiguration();
60 bool onHold(const KUrl &url) const;
61 QString protocol() const {return mProtocol;}
62
63Q_SIGNALS:
64 void statusUpdate(IdleSlave *);
65
66protected Q_SLOTS:
67 void gotInput();
68
69public:
70 KIO::Connection mConn;
71protected:
72 QString mProtocol;
73 QString mHost;
74 bool mConnected;
75 pid_t mPid;
76 time_t mBirthDate;
77 bool mOnHold;
78 KUrl mUrl;
79};
80
81class SlaveWaitRequest
82{
83public:
84 pid_t pid;
85 QDBusMessage transaction;
86};
87
88class KLaunchRequest
89{
90public:
91 QString name;
92 QStringList arg_list;
93 QString dbus_name;
94 QString tolerant_dbus_name;
95 enum status_t { Init = 0, Launching, Running, Error, Done };
96 pid_t pid;
97 status_t status;
98 QDBusMessage transaction;
99 KService::DBusStartupType dbus_startup_type;
100 bool autoStart;
101 QString errorMsg;
102#ifdef Q_WS_X11
103 QByteArray startup_id; // "" is the default, "0" for none
104 QByteArray startup_dpy; // Display to send startup notification to.
105#endif
106 QStringList envs; // env. variables to be app's environment
107 QString cwd;
108#ifdef USE_KPROCESS_FOR_KIOSLAVES
109protected:
110 KProcess *process;
111 friend class KLauncher;
112#endif
113};
114
115struct serviceResult
116{
117 int result; // 0 means success. > 0 means error (-1 means pending)
118 QString dbusName; // Contains DBUS name on success
119 QString error; // Contains error description on failure.
120 pid_t pid;
121};
122
123class KLauncher : public QObject
124{
125 Q_OBJECT
126
127public:
128#ifndef USE_KPROCESS_FOR_KIOSLAVES
129 KLauncher(int kdeinitSocket);
130#else
131 KLauncher();
132#endif
133
134 ~KLauncher();
135
136 void close();
137
138public slots:
139 void destruct(); // exit!
140
141protected:
142 void processDied(pid_t pid, long exitStatus);
143
144 void requestStart(KLaunchRequest *request);
145 void requestDone(KLaunchRequest *request);
146
147 bool start_service(KService::Ptr service, const QStringList &urls,
148 const QStringList &envs, const QByteArray &startup_id,
149 bool blind, bool autoStart, const QDBusMessage &msg );
150
151 void createArgs( KLaunchRequest *request, const KService::Ptr service,
152 const QStringList &url);
153
154 void queueRequest(KLaunchRequest *);
155
156 void send_service_startup_info( KLaunchRequest *request, KService::Ptr service, const QByteArray &startup_id,
157 const QStringList &envs );
158 void cancel_service_startup_info( KLaunchRequest *request, const QByteArray& startup_id,
159 const QStringList &envs );
160
161Q_SIGNALS:
162 void autoStart0Done();
163 void autoStart1Done();
164 void autoStart2Done();
165
166public: // remote methods, called by KLauncherAdaptor
167 void autoStart(int phase = 1);
168
169 /**
170 * Starts a program.
171 * 'envs' are environment variables that will be added
172 * to this program's environment before starting it
173 * 'startup_id' is for application startup notification,
174 * "" is the default, "0" for none
175 */
176 void exec_blind(const QString &name, const QStringList &arg_list, const QStringList &envs, const QString &startup_id);
177 inline void exec_blind(const QString &name, const QStringList &arg_list)
178 { exec_blind(name, arg_list, QStringList(), QLatin1String("0")); }
179
180 bool kdeinit_exec(const QString &app, const QStringList &args,
181 const QString& workdir, const QStringList &envs,
182 const QString &startup_id, bool wait, const QDBusMessage &msg);
183
184 void reparseConfiguration();
185 void setLaunchEnv(const QString &name, const QString &value);
186
187 /**
188 * Start a service by desktop name.
189 *
190 * 'serviceName' refers to a desktop file describing the service.
191 * The service is looked up anywhere in $KDEDIR/applnk and/or
192 * $KDEDIR/services.
193 * E.g. it should have the form "korganizer".
194 *
195 * 'url', if not empty, will be passed to the service as
196 * argument.
197 *
198 * 'envs' are environment variables that will be added
199 * to this program's environment before starting it
200 *
201 * 'startup_id' is for application startup notification,
202 * "" is the default, "0" for none
203 */
204 bool start_service_by_desktop_name(const QString &serviceName, const QStringList &urls, const QStringList &envs, const QString &startup_id, bool blind, const QDBusMessage &msg);
205
206 /**
207 * Start a service by desktop path.
208 *
209 * 'serviceName' refers to a desktop file describing the service.
210 * This may be an absolute path or a path relative to $KDEDIRS/applnk
211 * and/or $KDEDIRS/services
212 * E.g. it should have the form "Applications/korganizer.desktop" or
213 * "/opt/kde/share/applnk/Applications/korganizer.desktop".
214 * Note that for absolute paths the restrictions of
215 * KDesktopFile::isAuthorizedDesktopFile() are obeyed for security.
216 *
217 * 'url', if not empty, will be passed to the service as
218 * argument.
219 *
220 * 'envs' are environment variables that will be added
221 * to this program's environment before starting it
222 *
223 * 'startup_id' is for application startup notification,
224 * "" is the default, "0" for none
225 */
226 bool start_service_by_desktop_path(const QString &serviceName, const QStringList &urls, const QStringList &envs, const QString &startup_id, bool blind, const QDBusMessage &msg);
227
228 /**
229 * Start a service by (translated) name - deprecated
230 *
231 * 'serviceName' refers to the service name as given by·
232 * the Name field in the desktop file describing the service.
233 *
234 * 'url', if not empty, will be passed to the service as
235 * argument.
236 *
237 * 'envs' are environment variables that will be added
238 * to this program's environment before starting it
239 *
240 * 'startup_id' is for application startup notification,
241 * "" is the default, "0" for none
242 *
243 * @deprecated use start_service_by_desktop_path
244 */
245 bool start_service_by_name(const QString &serviceName, const QStringList &urls, const QStringList &envs, const QString &startup_id, bool blind, const QDBusMessage &msg); // KDE5: remove
246
247 pid_t requestHoldSlave(const KUrl &url, const QString &app_socket);
248
249 pid_t requestSlave(const QString &protocol, const QString &host,
250 const QString &app_socket, QString &error);
251 /**
252 * Return true of there is a slave held for @p url.
253 * @since 4.7
254 */
255 bool checkForHeldSlave(const QString &url);
256 void waitForSlave(int pid, const QDBusMessage &msg);
257 void terminate_kdeinit();
258
259public Q_SLOTS:
260 void slotAutoStart();
261 void slotDequeue();
262 void slotKDEInitData(int);
263 void slotNameOwnerChanged(const QString &name, const QString &oldOnwer, const QString &newOwner);
264 void slotSlaveStatus(IdleSlave *);
265 void acceptSlave();
266 void slotSlaveGone();
267 void idleTimeout();
268
269public:
270 serviceResult requestResult; // accessed by the adaptor
271protected:
272 QList<KLaunchRequest*> requestList; // Requests being handled
273 QList<KLaunchRequest*> requestQueue; // Requests waiting to being handled
274 KLaunchRequest *lastRequest;
275 QList<SlaveWaitRequest*> mSlaveWaitRequest;
276#ifndef USE_KPROCESS_FOR_KIOSLAVES
277 int kdeinitSocket;
278 QSocketNotifier *kdeinitNotifier;
279#endif
280 KIO::ConnectionServer mConnectionServer;
281 QList<IdleSlave*> mSlaveList;
282 QTimer mTimer;
283 QTimer mAutoTimer;
284 bool bProcessingQueue;
285 AutoStart mAutoStart;
286 QString mSlaveDebug;
287 QString mSlaveValgrind;
288 QString mSlaveValgrindSkin;
289 bool dontBlockReading;
290#ifdef Q_WS_X11
291 Display *mCached_dpy;
292#endif
293 void processRequestReturn(int status, const QByteArray &requestData);
294
295protected Q_SLOTS:
296 void slotGotOutput();
297 void slotFinished(int exitCode, QProcess::ExitStatus exitStatus);
298};
299#endif
300