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 | |
50 | class IdleSlave : public QObject |
51 | { |
52 | Q_OBJECT |
53 | public: |
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 | |
63 | Q_SIGNALS: |
64 | void statusUpdate(IdleSlave *); |
65 | |
66 | protected Q_SLOTS: |
67 | void gotInput(); |
68 | |
69 | public: |
70 | KIO::Connection mConn; |
71 | protected: |
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 | |
81 | class SlaveWaitRequest |
82 | { |
83 | public: |
84 | pid_t pid; |
85 | QDBusMessage transaction; |
86 | }; |
87 | |
88 | class KLaunchRequest |
89 | { |
90 | public: |
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 |
109 | protected: |
110 | KProcess *process; |
111 | friend class KLauncher; |
112 | #endif |
113 | }; |
114 | |
115 | struct 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 | |
123 | class KLauncher : public QObject |
124 | { |
125 | Q_OBJECT |
126 | |
127 | public: |
128 | #ifndef USE_KPROCESS_FOR_KIOSLAVES |
129 | KLauncher(int kdeinitSocket); |
130 | #else |
131 | KLauncher(); |
132 | #endif |
133 | |
134 | ~KLauncher(); |
135 | |
136 | void close(); |
137 | |
138 | public slots: |
139 | void destruct(); // exit! |
140 | |
141 | protected: |
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 | |
161 | Q_SIGNALS: |
162 | void autoStart0Done(); |
163 | void autoStart1Done(); |
164 | void autoStart2Done(); |
165 | |
166 | public: // 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 | |
259 | public 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 | |
269 | public: |
270 | serviceResult requestResult; // accessed by the adaptor |
271 | protected: |
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 | |
295 | protected Q_SLOTS: |
296 | void slotGotOutput(); |
297 | void slotFinished(int exitCode, QProcess::ExitStatus exitStatus); |
298 | }; |
299 | #endif |
300 | |