summaryrefslogtreecommitdiff
path: root/core/launcher/applauncher.cpp
Unidiff
Diffstat (limited to 'core/launcher/applauncher.cpp') (more/less context) (ignore whitespace changes)
-rw-r--r--core/launcher/applauncher.cpp83
1 files changed, 40 insertions, 43 deletions
diff --git a/core/launcher/applauncher.cpp b/core/launcher/applauncher.cpp
index 5a5517c..7000346 100644
--- a/core/launcher/applauncher.cpp
+++ b/core/launcher/applauncher.cpp
@@ -6,80 +6,77 @@
6** This file may be distributed and/or modified under the terms of the 6** This file may be distributed and/or modified under the terms of the
7** GNU General Public License version 2 as published by the Free Software 7** GNU General Public License version 2 as published by the Free Software
8** Foundation and appearing in the file LICENSE.GPL included in the 8** Foundation and appearing in the file LICENSE.GPL included in the
9** packaging of this file. 9** packaging of this file.
10** 10**
11** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE 11** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
12** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 12** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
13** 13**
14** See http://www.trolltech.com/gpl/ for GPL licensing information. 14** See http://www.trolltech.com/gpl/ for GPL licensing information.
15** 15**
16** Contact info@trolltech.com if any conditions of this licensing are 16** Contact info@trolltech.com if any conditions of this licensing are
17** not clear to you. 17** not clear to you.
18** 18**
19**********************************************************************/ 19**********************************************************************/
20 20
21#ifndef QTOPIA_INTERNAL_PRELOADACCESS 21#ifndef QTOPIA_INTERNAL_PRELOADACCESS
22#define QTOPIA_INTERNAL_PRELOADACCESS 22#define QTOPIA_INTERNAL_PRELOADACCESS
23#endif 23#endif
24#ifndef QTOPIA_INTERNAL_FILEOPERATIONS 24#ifndef QTOPIA_INTERNAL_FILEOPERATIONS
25#define QTOPIA_INTERNAL_FILEOPERATIONS 25#define QTOPIA_INTERNAL_FILEOPERATIONS
26#endif 26#endif
27#ifndef QTOPIA_PROGRAM_MONITOR 27#ifndef QTOPIA_PROGRAM_MONITOR
28#define QTOPIA_PROGRAM_MONITOR 28#define QTOPIA_PROGRAM_MONITOR
29#endif 29#endif
30
31#include "applauncher.h"
32#include "documentlist.h"
33
34/* OPIE */
35#include <opie2/odebug.h>
30#include <opie2/oglobal.h> 36#include <opie2/oglobal.h>
37#include <qtopia/qcopenvelope_qws.h>
38#include <qtopia/qpeapplication.h>
39using namespace Opie::Core;
31 40
32#ifndef Q_OS_WIN32 41/* QT */
42#include <qtimer.h>
43#include <qwindowsystem_qws.h>
44#include <qmessagebox.h>
45#include <qfileinfo.h>
46
47/* STD */
33#include <sys/stat.h> 48#include <sys/stat.h>
34#include <sys/wait.h> 49#include <sys/wait.h>
35#include <sys/file.h> 50#include <sys/file.h>
36#include <unistd.h> 51#include <unistd.h>
37#include <sys/time.h> 52#include <sys/time.h>
38#include <sys/resource.h> 53#include <sys/resource.h>
39#include <errno.h> 54#include <errno.h>
40#else
41#include <process.h>
42#include <windows.h>
43#include <winbase.h>
44#endif
45
46#include <signal.h> 55#include <signal.h>
47#include <sys/types.h> 56#include <sys/types.h>
48#include <stdlib.h> 57#include <stdlib.h>
49 58
50#include <qtimer.h>
51#include <qwindowsystem_qws.h>
52#include <qmessagebox.h>
53#include <qfileinfo.h>
54
55#include <qtopia/qcopenvelope_qws.h>
56#include <qtopia/qpeapplication.h>
57
58#include "applauncher.h"
59#include "documentlist.h"
60
61using namespace Opie::Core;
62const int AppLauncher::RAISE_TIMEOUT_MS = 5000; 59const int AppLauncher::RAISE_TIMEOUT_MS = 5000;
63 60
64//--------------------------------------------------------------------------- 61//---------------------------------------------------------------------------
65 62
66static AppLauncher* appLauncherPtr; 63static AppLauncher* appLauncherPtr;
67 64
68const int appStopEventID = 1290; 65const int appStopEventID = 1290;
69 66
70class AppStoppedEvent : public QCustomEvent 67class AppStoppedEvent : public QCustomEvent
71{ 68{
72public: 69public:
73 AppStoppedEvent(int pid, int status) 70 AppStoppedEvent(int pid, int status)
74 : QCustomEvent( appStopEventID ), mPid(pid), mStatus(status) { } 71 : QCustomEvent( appStopEventID ), mPid(pid), mStatus(status) { }
75 72
76 int pid() { return mPid; } 73 int pid() { return mPid; }
77 int status() { return mStatus; } 74 int status() { return mStatus; }
78 75
79private: 76private:
80 int mPid, mStatus; 77 int mPid, mStatus;
81}; 78};
82 79
83AppLauncher::AppLauncher(QObject *parent, const char *name) 80AppLauncher::AppLauncher(QObject *parent, const char *name)
84 : QObject(parent, name), qlPid(0), qlReady(FALSE), 81 : QObject(parent, name), qlPid(0), qlReady(FALSE),
85 appKillerBox(0) 82 appKillerBox(0)
@@ -106,350 +103,350 @@ AppLauncher::AppLauncher(QObject *parent, const char *name)
106 runningApps[::getpid()] = tmp; 103 runningApps[::getpid()] = tmp;
107 104
108 appLauncherPtr = this; 105 appLauncherPtr = this;
109 106
110 QTimer::singleShot( 1000, this, SLOT(createQuickLauncher()) ); 107 QTimer::singleShot( 1000, this, SLOT(createQuickLauncher()) );
111} 108}
112 109
113AppLauncher::~AppLauncher() 110AppLauncher::~AppLauncher()
114{ 111{
115 appLauncherPtr = 0; 112 appLauncherPtr = 0;
116#ifndef Q_OS_WIN32 113#ifndef Q_OS_WIN32
117 signal(SIGCHLD, SIG_DFL); 114 signal(SIGCHLD, SIG_DFL);
118#endif 115#endif
119 if ( qlPid ) { 116 if ( qlPid ) {
120 int status; 117 int status;
121 ::kill( qlPid, SIGTERM ); 118 ::kill( qlPid, SIGTERM );
122 waitpid( qlPid, &status, 0 ); 119 waitpid( qlPid, &status, 0 );
123 } 120 }
124} 121}
125 122
126/* We use the QCopChannel of the app as an indicator of when it has been launched 123/* We use the QCopChannel of the app as an indicator of when it has been launched
127 so that we can disable the busy indicators */ 124 so that we can disable the busy indicators */
128void AppLauncher::newQcopChannel(const QString& channelName) 125void AppLauncher::newQcopChannel(const QString& channelName)
129{ 126{
130// qDebug("channel %s added", channelName.data() ); 127// odebug << "channel " << channelName.data() << " added" << oendl;
131 QString prefix("QPE/Application/"); 128 QString prefix("QPE/Application/");
132 if (channelName.startsWith(prefix)) { 129 if (channelName.startsWith(prefix)) {
133 { 130 {
134 QCopEnvelope e("QPE/System", "newChannel(QString)"); 131 QCopEnvelope e("QPE/System", "newChannel(QString)");
135 e << channelName; 132 e << channelName;
136 } 133 }
137 QString appName = channelName.mid(prefix.length()); 134 QString appName = channelName.mid(prefix.length());
138 if ( appName != "quicklauncher" ) { 135 if ( appName != "quicklauncher" ) {
139 emit connected( appName ); 136 emit connected( appName );
140 QCopEnvelope e("QPE/System", "notBusy(QString)"); 137 QCopEnvelope e("QPE/System", "notBusy(QString)");
141 e << appName; 138 e << appName;
142 } 139 }
143 } else if (channelName.startsWith("QPE/QuickLauncher-")) { 140 } else if (channelName.startsWith("QPE/QuickLauncher-")) {
144 qDebug("Registered %s", channelName.latin1()); 141 odebug << "Registered " << channelName << "" << oendl;
145 int pid = channelName.mid(18).toInt(); 142 int pid = channelName.mid(18).toInt();
146 if (pid == qlPid) 143 if (pid == qlPid)
147 qlReady = TRUE; 144 qlReady = TRUE;
148 } 145 }
149} 146}
150 147
151void AppLauncher::removedQcopChannel(const QString& channelName) 148void AppLauncher::removedQcopChannel(const QString& channelName)
152{ 149{
153 if (channelName.startsWith("QPE/Application/")) { 150 if (channelName.startsWith("QPE/Application/")) {
154 QCopEnvelope e("QPE/System", "removedChannel(QString)"); 151 QCopEnvelope e("QPE/System", "removedChannel(QString)");
155 e << channelName; 152 e << channelName;
156 } 153 }
157} 154}
158 155
159void AppLauncher::received(const QCString& msg, const QByteArray& data) 156void AppLauncher::received(const QCString& msg, const QByteArray& data)
160{ 157{
161 QDataStream stream( data, IO_ReadOnly ); 158 QDataStream stream( data, IO_ReadOnly );
162 if ( msg == "execute(QString)" ) { 159 if ( msg == "execute(QString)" ) {
163 QString t; 160 QString t;
164 stream >> t; 161 stream >> t;
165 if ( !executeBuiltin( t, QString::null ) ) 162 if ( !executeBuiltin( t, QString::null ) )
166 execute(t, QString::null); 163 execute(t, QString::null);
167 } else if ( msg == "execute(QString,QString)" ) { 164 } else if ( msg == "execute(QString,QString)" ) {
168 QString t,d; 165 QString t,d;
169 stream >> t >> d; 166 stream >> t >> d;
170 if ( !executeBuiltin( t, d ) ) 167 if ( !executeBuiltin( t, d ) )
171 execute( t, d ); 168 execute( t, d );
172 } else if ( msg == "processQCop(QString)" ) { // from QPE/Server 169 } else if ( msg == "processQCop(QString)" ) { // from QPE/Server
173 QString t; 170 QString t;
174 stream >> t; 171 stream >> t;
175 if ( !executeBuiltin( t, QString::null ) ) 172 if ( !executeBuiltin( t, QString::null ) )
176 execute( t, QString::null, TRUE); 173 execute( t, QString::null, TRUE);
177 } else if ( msg == "raise(QString)" ) { 174 } else if ( msg == "raise(QString)" ) {
178 QString appName; 175 QString appName;
179 stream >> appName; 176 stream >> appName;
180 177
181 if ( !executeBuiltin( appName, QString::null ) ) { 178 if ( !executeBuiltin( appName, QString::null ) ) {
182 if ( !waitingHeartbeat.contains( appName ) && appKillerName != appName ) { 179 if ( !waitingHeartbeat.contains( appName ) && appKillerName != appName ) {
183 //qDebug( "Raising: %s", appName.latin1() ); 180 //odebug << "Raising: " << appName << "" << oendl;
184 QCString channel = "QPE/Application/"; 181 QCString channel = "QPE/Application/";
185 channel += appName.latin1(); 182 channel += appName.latin1();
186 183
187 // Need to lock it to avoid race conditions with QPEApplication::processQCopFile 184 // Need to lock it to avoid race conditions with QPEApplication::processQCopFile
188 QFile f("/tmp/qcop-msg-" + appName); 185 QFile f("/tmp/qcop-msg-" + appName);
189 if ( f.open(IO_WriteOnly | IO_Append) ) { 186 if ( f.open(IO_WriteOnly | IO_Append) ) {
190#ifndef Q_OS_WIN32 187#ifndef Q_OS_WIN32
191 flock(f.handle(), LOCK_EX); 188 flock(f.handle(), LOCK_EX);
192#endif 189#endif
193 QDataStream ds(&f); 190 QDataStream ds(&f);
194 QByteArray b; 191 QByteArray b;
195 QDataStream bstream(b, IO_WriteOnly); 192 QDataStream bstream(b, IO_WriteOnly);
196 ds << channel << QCString("raise()") << b; 193 ds << channel << QCString("raise()") << b;
197 f.flush(); 194 f.flush();
198#ifndef Q_OS_WIN32 195#ifndef Q_OS_WIN32
199 flock(f.handle(), LOCK_UN); 196 flock(f.handle(), LOCK_UN);
200#endif 197#endif
201 f.close(); 198 f.close();
202 } 199 }
203 bool alreadyRunning = isRunning( appName ); 200 bool alreadyRunning = isRunning( appName );
204 if ( execute(appName, QString::null) ) { 201 if ( execute(appName, QString::null) ) {
205 int id = startTimer(RAISE_TIMEOUT_MS + alreadyRunning?2000:0); 202 int id = startTimer(RAISE_TIMEOUT_MS + alreadyRunning?2000:0);
206 waitingHeartbeat.insert( appName, id ); 203 waitingHeartbeat.insert( appName, id );
207 } 204 }
208 } 205 }
209 } 206 }
210 } else if ( msg == "sendRunningApps()" ) { 207 } else if ( msg == "sendRunningApps()" ) {
211 QStringList apps; 208 QStringList apps;
212 QMap<int,QString>::Iterator it; 209 QMap<int,QString>::Iterator it;
213 for( it = runningApps.begin(); it != runningApps.end(); ++it ) 210 for( it = runningApps.begin(); it != runningApps.end(); ++it )
214 apps.append( *it ); 211 apps.append( *it );
215 QCopEnvelope e( "QPE/Desktop", "runningApps(QStringList)" ); 212 QCopEnvelope e( "QPE/Desktop", "runningApps(QStringList)" );
216 e << apps; 213 e << apps;
217 } else if ( msg == "appRaised(QString)" ) { 214 } else if ( msg == "appRaised(QString)" ) {
218 QString appName; 215 QString appName;
219 stream >> appName; 216 stream >> appName;
220 qDebug("Got a heartbeat from %s", appName.latin1()); 217 odebug << "Got a heartbeat from " << appName << "" << oendl;
221 QMap<QString,int>::Iterator it = waitingHeartbeat.find(appName); 218 QMap<QString,int>::Iterator it = waitingHeartbeat.find(appName);
222 if ( it != waitingHeartbeat.end() ) { 219 if ( it != waitingHeartbeat.end() ) {
223 killTimer( *it ); 220 killTimer( *it );
224 waitingHeartbeat.remove(it); 221 waitingHeartbeat.remove(it);
225 } 222 }
226 // Check to make sure we're not waiting on user input... 223 // Check to make sure we're not waiting on user input...
227 if ( appKillerBox && appName == appKillerName ) { 224 if ( appKillerBox && appName == appKillerName ) {
228 // If we are, we kill the dialog box, and the code waiting on the result 225 // If we are, we kill the dialog box, and the code waiting on the result
229 // will clean us up (basically the user said "no"). 226 // will clean us up (basically the user said "no").
230 delete appKillerBox; 227 delete appKillerBox;
231 appKillerBox = 0; 228 appKillerBox = 0;
232 appKillerName = QString::null; 229 appKillerName = QString::null;
233 } 230 }
234 } 231 }
235} 232}
236 233
237void AppLauncher::signalHandler(int) 234void AppLauncher::signalHandler(int)
238{ 235{
239#ifndef Q_OS_WIN32 236#ifndef Q_OS_WIN32
240 int status; 237 int status;
241 pid_t pid = waitpid(-1, &status, WNOHANG); 238 pid_t pid = waitpid(-1, &status, WNOHANG);
242/* if (pid == 0 || &status == 0 ) { 239/* if (pid == 0 || &status == 0 ) {
243 qDebug("hmm, could not get return value from signal"); 240 odebug << "hmm, could not get return value from signal" << oendl;
244 } 241 }
245*/ 242*/
246 QApplication::postEvent(appLauncherPtr, new AppStoppedEvent(pid, status) ); 243 QApplication::postEvent(appLauncherPtr, new AppStoppedEvent(pid, status) );
247#else 244#else
248 qDebug("Unhandled signal see by AppLauncher::signalHandler(int)"); 245 odebug << "Unhandled signal see by AppLauncher::signalHandler(int)" << oendl;
249#endif 246#endif
250} 247}
251 248
252bool AppLauncher::event(QEvent *e) 249bool AppLauncher::event(QEvent *e)
253{ 250{
254 if ( e->type() == appStopEventID ) { 251 if ( e->type() == appStopEventID ) {
255 AppStoppedEvent *ae = (AppStoppedEvent *) e; 252 AppStoppedEvent *ae = (AppStoppedEvent *) e;
256 sigStopped(ae->pid(), ae->status() ); 253 sigStopped(ae->pid(), ae->status() );
257 return TRUE; 254 return TRUE;
258 } 255 }
259 256
260 return QObject::event(e); 257 return QObject::event(e);
261} 258}
262 259
263void AppLauncher::timerEvent( QTimerEvent *e ) 260void AppLauncher::timerEvent( QTimerEvent *e )
264{ 261{
265 int id = e->timerId(); 262 int id = e->timerId();
266 QMap<QString,int>::Iterator it; 263 QMap<QString,int>::Iterator it;
267 for ( it = waitingHeartbeat.begin(); it != waitingHeartbeat.end(); ++it ) { 264 for ( it = waitingHeartbeat.begin(); it != waitingHeartbeat.end(); ++it ) {
268 if ( *it == id ) { 265 if ( *it == id ) {
269 if ( appKillerBox ) // we're already dealing with one 266 if ( appKillerBox ) // we're already dealing with one
270 return; 267 return;
271 268
272 appKillerName = it.key(); 269 appKillerName = it.key();
273 killTimer( id ); 270 killTimer( id );
274 waitingHeartbeat.remove( it ); 271 waitingHeartbeat.remove( it );
275 272
276 // qDebug("Checking in on %s", appKillerName.latin1()); 273 // odebug << "Checking in on " << appKillerName << "" << oendl;
277 274
278 // We store this incase the application responds while we're 275 // We store this incase the application responds while we're
279 // waiting for user input so we know not to delete ourselves. 276 // waiting for user input so we know not to delete ourselves.
280 appKillerBox = new QMessageBox(tr("Application Problem"), 277 appKillerBox = new QMessageBox(tr("Application Problem"),
281 tr("<p>%1 is not responding.</p>").arg(appKillerName) + 278 tr("<p>%1 is not responding.</p>").arg(appKillerName) +
282 tr("<p>Would you like to force the application to exit?</p>"), 279 tr("<p>Would you like to force the application to exit?</p>"),
283 QMessageBox::Warning, QMessageBox::Yes, 280 QMessageBox::Warning, QMessageBox::Yes,
284 QMessageBox::No | QMessageBox::Default, 281 QMessageBox::No | QMessageBox::Default,
285 QMessageBox::NoButton); 282 QMessageBox::NoButton);
286 if (appKillerBox->exec() == QMessageBox::Yes) { 283 if (appKillerBox->exec() == QMessageBox::Yes) {
287 // qDebug("Killing the app!!! Bwuhahahaha!"); 284 // odebug << "Killing the app!!! Bwuhahahaha!" << oendl;
288 int pid = pidForName(appKillerName); 285 int pid = pidForName(appKillerName);
289 if ( pid > 0 ) 286 if ( pid > 0 )
290 kill( pid ); 287 kill( pid );
291 } 288 }
292 appKillerName = QString::null; 289 appKillerName = QString::null;
293 delete appKillerBox; 290 delete appKillerBox;
294 appKillerBox = 0; 291 appKillerBox = 0;
295 return; 292 return;
296 } 293 }
297 } 294 }
298 295
299 QObject::timerEvent( e ); 296 QObject::timerEvent( e );
300} 297}
301 298
302#ifndef Q_OS_WIN32 299#ifndef Q_OS_WIN32
303void AppLauncher::sigStopped(int sigPid, int sigStatus) 300void AppLauncher::sigStopped(int sigPid, int sigStatus)
304{ 301{
305 int exitStatus = 0; 302 int exitStatus = 0;
306 303
307 bool crashed = WIFSIGNALED(sigStatus); 304 bool crashed = WIFSIGNALED(sigStatus);
308 if ( !crashed ) { 305 if ( !crashed ) {
309 if ( WIFEXITED(sigStatus) ) 306 if ( WIFEXITED(sigStatus) )
310 exitStatus = WEXITSTATUS(sigStatus); 307 exitStatus = WEXITSTATUS(sigStatus);
311 } else { 308 } else {
312 exitStatus = WTERMSIG(sigStatus); 309 exitStatus = WTERMSIG(sigStatus);
313 } 310 }
314 311
315 QMap<int,QString>::Iterator it = runningApps.find( sigPid ); 312 QMap<int,QString>::Iterator it = runningApps.find( sigPid );
316 if ( it == runningApps.end() ) { 313 if ( it == runningApps.end() ) {
317 if ( sigPid == qlPid ) { 314 if ( sigPid == qlPid ) {
318 qDebug( "quicklauncher stopped" ); 315 odebug << "quicklauncher stopped" << oendl;
319 qlPid = 0; 316 qlPid = 0;
320 qlReady = FALSE; 317 qlReady = FALSE;
321 QFile::remove("/tmp/qcop-msg-quicklauncher" ); 318 QFile::remove("/tmp/qcop-msg-quicklauncher" );
322 QTimer::singleShot( 2000, this, SLOT(createQuickLauncher()) ); 319 QTimer::singleShot( 2000, this, SLOT(createQuickLauncher()) );
323 } 320 }
324/* 321/*
325 if ( sigPid == -1 ) 322 if ( sigPid == -1 )
326 qDebug("non-qtopia application exited (disregarded)"); 323 odebug << "non-qtopia application exited (disregarded)" << oendl;
327 else 324 else
328 qDebug("==== no pid matching %d in list, definite bug", sigPid); 325 odebug << "==== no pid matching " << sigPid << " in list, definite bug" << oendl;
329*/ 326*/
330 return; 327 return;
331 } 328 }
332 QString appName = *it; 329 QString appName = *it;
333 runningApps.remove(it); 330 runningApps.remove(it);
334 331
335 QMap<QString,int>::Iterator hbit = waitingHeartbeat.find(appName); 332 QMap<QString,int>::Iterator hbit = waitingHeartbeat.find(appName);
336 if ( hbit != waitingHeartbeat.end() ) { 333 if ( hbit != waitingHeartbeat.end() ) {
337 killTimer( *hbit ); 334 killTimer( *hbit );
338 waitingHeartbeat.remove( hbit ); 335 waitingHeartbeat.remove( hbit );
339 } 336 }
340 if ( appName == appKillerName ) { 337 if ( appName == appKillerName ) {
341 appKillerName = QString::null; 338 appKillerName = QString::null;
342 delete appKillerBox; 339 delete appKillerBox;
343 appKillerBox = 0; 340 appKillerBox = 0;
344 } 341 }
345 342
346 /* we must disable preload for an app that crashes as the system logic relies on preloaded apps 343 /* we must disable preload for an app that crashes as the system logic relies on preloaded apps
347 actually being loaded. If eg. the crash happened in the constructor, we can't automatically reload 344 actually being loaded. If eg. the crash happened in the constructor, we can't automatically reload
348 the app (withouth some timeout value for eg. 3 tries (which I think is a bad solution) 345 the app (withouth some timeout value for eg. 3 tries (which I think is a bad solution)
349 */ 346 */
350 bool preloadDisabled = FALSE; 347 bool preloadDisabled = FALSE;
351 if ( !DocumentList::appLnkSet ) return; 348 if ( !DocumentList::appLnkSet ) return;
352 const AppLnk* app = DocumentList::appLnkSet->findExec( appName ); 349 const AppLnk* app = DocumentList::appLnkSet->findExec( appName );
353 if ( !app ) return; // QCop messages processed to slow? 350 if ( !app ) return; // QCop messages processed to slow?
354 if ( crashed && app->isPreloaded() ) { 351 if ( crashed && app->isPreloaded() ) {
355 Config cfg("Launcher"); 352 Config cfg("Launcher");
356 cfg.setGroup("Preload"); 353 cfg.setGroup("Preload");
357 QStringList apps = cfg.readListEntry("Apps",','); 354 QStringList apps = cfg.readListEntry("Apps",',');
358 QString exe = app->exec(); 355 QString exe = app->exec();
359 apps.remove(exe); 356 apps.remove(exe);
360 cfg.writeEntry("Apps",apps,','); 357 cfg.writeEntry("Apps",apps,',');
361 preloadDisabled = TRUE; 358 preloadDisabled = TRUE;
362 } 359 }
363 360
364 // clean up 361 // clean up
365 if ( exitStatus ) { 362 if ( exitStatus ) {
366 QCopEnvelope e("QPE/System", "notBusy(QString)"); 363 QCopEnvelope e("QPE/System", "notBusy(QString)");
367 e << app->exec(); 364 e << app->exec();
368 } 365 }
369/* 366/*
370 // debug info 367 // debug info
371 for (it = runningApps.begin(); it != runningApps.end(); ++it) { 368 for (it = runningApps.begin(); it != runningApps.end(); ++it) {
372 qDebug("running according to internal list: %s, with pid %d", (*it).data(), it.key() ); 369 odebug << "running according to internal list: " << (*it).data() << ", with pid " << it.key() << "" << oendl;
373 } 370 }
374*/ 371*/
375 372
376#ifdef QTOPIA_PROGRAM_MONITOR 373#ifdef QTOPIA_PROGRAM_MONITOR
377 if ( crashed ) { 374 if ( crashed ) {
378 QString sig; 375 QString sig;
379 switch( exitStatus ) { 376 switch( exitStatus ) {
380 case SIGABRT: sig = "SIGABRT"; break; 377 case SIGABRT: sig = "SIGABRT"; break;
381 case SIGALRM: sig = "SIGALRM"; break; 378 case SIGALRM: sig = "SIGALRM"; break;
382 case SIGBUS: sig = "SIGBUS"; break; 379 case SIGBUS: sig = "SIGBUS"; break;
383 case SIGFPE: sig = "SIGFPE"; break; 380 case SIGFPE: sig = "SIGFPE"; break;
384 case SIGHUP: sig = "SIGHUP"; break; 381 case SIGHUP: sig = "SIGHUP"; break;
385 case SIGILL: sig = "SIGILL"; break; 382 case SIGILL: sig = "SIGILL"; break;
386 case SIGKILL: sig = "SIGKILL"; break; 383 case SIGKILL: sig = "SIGKILL"; break;
387 case SIGPIPE: sig = "SIGPIPE"; break; 384 case SIGPIPE: sig = "SIGPIPE"; break;
388 case SIGQUIT: sig = "SIGQUIT"; break; 385 case SIGQUIT: sig = "SIGQUIT"; break;
389 case SIGSEGV: sig = "SIGSEGV"; break; 386 case SIGSEGV: sig = "SIGSEGV"; break;
390 case SIGTERM: sig = "SIGTERM"; break; 387 case SIGTERM: sig = "SIGTERM"; break;
391 case SIGTRAP: sig = "SIGTRAP"; break; 388 case SIGTRAP: sig = "SIGTRAP"; break;
392 default: sig = QString("Unkown %1").arg(exitStatus); 389 default: sig = QString("Unkown %1").arg(exitStatus);
393 } 390 }
394 if ( preloadDisabled ) 391 if ( preloadDisabled )
395 sig += tr("<qt><p>Fast loading has been disabled for this application. Tap and hold the application icon to reenable it.</qt>"); 392 sig += tr("<qt><p>Fast loading has been disabled for this application. Tap and hold the application icon to reenable it.</qt>");
396 393
397 QString str = tr("<qt><b>%1</b> was terminated due to signal code %2</qt>").arg( app->name() ).arg( sig ); 394 QString str = tr("<qt><b>%1</b> was terminated due to signal code %2</qt>").arg( app->name() ).arg( sig );
398 QMessageBox::information(0, tr("Application terminated"), str ); 395 QMessageBox::information(0, tr("Application terminated"), str );
399 } else { 396 } else {
400 if ( exitStatus == 255 ) { //could not find app (because global returns -1) 397 if ( exitStatus == 255 ) { //could not find app (because global returns -1)
401 QMessageBox::information(0, tr("Application not found"), tr("<qt>Could not locate application <b>%1</b></qt>").arg( app->exec() ) ); 398 QMessageBox::information(0, tr("Application not found"), tr("<qt>Could not locate application <b>%1</b></qt>").arg( app->exec() ) );
402 } else { 399 } else {
403 QFileInfo fi(QString::fromLatin1("/tmp/qcop-msg-") + appName); 400 QFileInfo fi(QString::fromLatin1("/tmp/qcop-msg-") + appName);
404 if ( fi.exists() && fi.size() ) { 401 if ( fi.exists() && fi.size() ) {
405 emit terminated(sigPid, appName); 402 emit terminated(sigPid, appName);
406 qWarning("Re executing obmitted for %s", appName.latin1() ); 403 owarn << "Re executing obmitted for " << appName << "" << oendl;
407 // execute( appName, QString::null ); 404 // execute( appName, QString::null );
408 return; 405 return;
409 } 406 }
410 } 407 }
411 } 408 }
412 409
413#endif 410#endif
414 411
415 emit terminated(sigPid, appName); 412 emit terminated(sigPid, appName);
416} 413}
417#else 414#else
418void AppLauncher::sigStopped(int sigPid, int sigStatus) 415void AppLauncher::sigStopped(int sigPid, int sigStatus)
419{ 416{
420 qDebug("Unhandled signal : AppLauncher::sigStopped(int sigPid, int sigStatus)"); 417 odebug << "Unhandled signal : AppLauncher::sigStopped(int sigPid, int sigStatus)" << oendl;
421} 418}
422#endif // Q_OS_WIN32 419#endif // Q_OS_WIN32
423 420
424bool AppLauncher::isRunning(const QString &app) 421bool AppLauncher::isRunning(const QString &app)
425{ 422{
426 for (QMap<int,QString>::ConstIterator it = runningApps.begin(); it != runningApps.end(); ++it) { 423 for (QMap<int,QString>::ConstIterator it = runningApps.begin(); it != runningApps.end(); ++it) {
427 if ( *it == app ) { 424 if ( *it == app ) {
428#ifdef Q_OS_UNIX 425#ifdef Q_OS_UNIX
429 pid_t t = ::__getpgid( it.key() ); 426 pid_t t = ::__getpgid( it.key() );
430 if ( t == -1 ) { 427 if ( t == -1 ) {
431 qDebug("appLauncher bug, %s believed running, but pid %d is not existing", app.data(), it.key() ); 428 odebug << "appLauncher bug, " << app.data() << " believed running, but pid " << it.key() << " is not existing" << oendl;
432 runningApps.remove( it.key() ); 429 runningApps.remove( it.key() );
433 return FALSE; 430 return FALSE;
434 } 431 }
435#endif 432#endif
436 return TRUE; 433 return TRUE;
437 } 434 }
438 } 435 }
439 436
440 return FALSE; 437 return FALSE;
441} 438}
442 439
443bool AppLauncher::executeBuiltin(const QString &c, const QString &document) 440bool AppLauncher::executeBuiltin(const QString &c, const QString &document)
444{ 441{
445 Global::Command* builtin = OGlobal::builtinCommands(); 442 Global::Command* builtin = OGlobal::builtinCommands();
446 QGuardedPtr<QWidget> *running = OGlobal::builtinRunning(); 443 QGuardedPtr<QWidget> *running = OGlobal::builtinRunning();
447 444
448 // Attempt to execute the app using a builtin class for the app 445 // Attempt to execute the app using a builtin class for the app
449 if (builtin) { 446 if (builtin) {
450 for (int i = 0; builtin[i].file; i++) { 447 for (int i = 0; builtin[i].file; i++) {
451 if ( builtin[i].file == c ) { 448 if ( builtin[i].file == c ) {
452 if ( running[i] ) { 449 if ( running[i] ) {
453 if ( !document.isNull() && builtin[i].documentary ) 450 if ( !document.isNull() && builtin[i].documentary )
454 Global::setDocument(running[i], document); 451 Global::setDocument(running[i], document);
455 running[i]->raise(); 452 running[i]->raise();
@@ -460,49 +457,49 @@ bool AppLauncher::executeBuiltin(const QString &c, const QString &document)
460 } 457 }
461#ifndef QT_NO_COP 458#ifndef QT_NO_COP
462 QCopEnvelope e("QPE/System", "notBusy(QString)" ); 459 QCopEnvelope e("QPE/System", "notBusy(QString)" );
463 e << c; // that was quick ;-) 460 e << c; // that was quick ;-)
464#endif 461#endif
465 return TRUE; 462 return TRUE;
466 } 463 }
467 } 464 }
468 } 465 }
469 466
470 // Convert the command line in to a list of arguments 467 // Convert the command line in to a list of arguments
471 QStringList list = QStringList::split(QRegExp(" *"),c); 468 QStringList list = QStringList::split(QRegExp(" *"),c);
472 QString ap=list[0]; 469 QString ap=list[0];
473 470
474 if ( ap == "suspend" ) { // No tr 471 if ( ap == "suspend" ) { // No tr
475 QWSServer::processKeyEvent( 0xffff, Qt::Key_F34, FALSE, TRUE, FALSE ); 472 QWSServer::processKeyEvent( 0xffff, Qt::Key_F34, FALSE, TRUE, FALSE );
476 return TRUE; 473 return TRUE;
477 } 474 }
478 475
479 return FALSE; 476 return FALSE;
480} 477}
481 478
482bool AppLauncher::execute(const QString &c, const QString &docParam, bool noRaise) 479bool AppLauncher::execute(const QString &c, const QString &docParam, bool noRaise)
483{ 480{
484 qWarning("AppLauncher::execute '%s' '%s'", (const char*) c, (const char*) docParam ); 481 owarn << "AppLauncher::execute '" << c << "' '" << docParam << "'" << oendl;
485 // Convert the command line in to a list of arguments 482 // Convert the command line in to a list of arguments
486 QStringList list = QStringList::split(QRegExp(" *"),c); 483 QStringList list = QStringList::split(QRegExp(" *"),c);
487 QStringList arglist = QStringList::split(QRegExp(" *"),docParam); 484 QStringList arglist = QStringList::split(QRegExp(" *"),docParam);
488 for ( QStringList::Iterator it = arglist.begin(); it != arglist.end(); ++it ) 485 for ( QStringList::Iterator it = arglist.begin(); it != arglist.end(); ++it )
489 list.append( *it ); 486 list.append( *it );
490 487
491 QString appName = list[0]; 488 QString appName = list[0];
492 if ( isRunning(appName) ) { 489 if ( isRunning(appName) ) {
493 QCString channel = "QPE/Application/"; 490 QCString channel = "QPE/Application/";
494 channel += appName.latin1(); 491 channel += appName.latin1();
495 492
496 // Need to lock it to avoid race conditions with QPEApplication::processQCopFile 493 // Need to lock it to avoid race conditions with QPEApplication::processQCopFile
497 QFile f(QString::fromLatin1("/tmp/qcop-msg-") + appName); 494 QFile f(QString::fromLatin1("/tmp/qcop-msg-") + appName);
498 if ( !noRaise && f.open(IO_WriteOnly | IO_Append) ) { 495 if ( !noRaise && f.open(IO_WriteOnly | IO_Append) ) {
499#ifndef Q_OS_WIN32 496#ifndef Q_OS_WIN32
500 flock(f.handle(), LOCK_EX); 497 flock(f.handle(), LOCK_EX);
501#endif 498#endif
502 499
503 QDataStream ds(&f); 500 QDataStream ds(&f);
504 QByteArray b; 501 QByteArray b;
505 QDataStream bstream(b, IO_WriteOnly); 502 QDataStream bstream(b, IO_WriteOnly);
506 if ( !f.size() ) { 503 if ( !f.size() ) {
507 ds << channel << QCString("raise()") << b; 504 ds << channel << QCString("raise()") << b;
508 if ( !waitingHeartbeat.contains( appName ) && appKillerName != appName ) { 505 if ( !waitingHeartbeat.contains( appName ) && appKillerName != appName ) {
@@ -527,99 +524,99 @@ bool AppLauncher::execute(const QString &c, const QString &docParam, bool noRais
527 return TRUE; 524 return TRUE;
528 } 525 }
529 526
530#ifdef QT_NO_QWS_MULTIPROCESS 527#ifdef QT_NO_QWS_MULTIPROCESS
531 QMessageBox::warning( 0, tr("Error"), tr("<qt>Could not find the application %1</qt>").arg(c), 528 QMessageBox::warning( 0, tr("Error"), tr("<qt>Could not find the application %1</qt>").arg(c),
532 tr("OK"), 0, 0, 0, 1 ); 529 tr("OK"), 0, 0, 0, 1 );
533#else 530#else
534 531
535 QStrList slist; 532 QStrList slist;
536 unsigned j; 533 unsigned j;
537 for ( j = 0; j < list.count(); j++ ) 534 for ( j = 0; j < list.count(); j++ )
538 slist.append( list[j].utf8() ); 535 slist.append( list[j].utf8() );
539 536
540 const char **args = new const char *[slist.count() + 1]; 537 const char **args = new const char *[slist.count() + 1];
541 for ( j = 0; j < slist.count(); j++ ) 538 for ( j = 0; j < slist.count(); j++ )
542 args[j] = slist.at(j); 539 args[j] = slist.at(j);
543 args[j] = NULL; 540 args[j] = NULL;
544 541
545#ifndef Q_OS_WIN32 542#ifndef Q_OS_WIN32
546#ifdef Q_OS_MACX 543#ifdef Q_OS_MACX
547 if ( qlPid && qlReady && QFile::exists( QPEApplication::qpeDir()+"plugins/application/lib"+args[0] + ".dylib" ) ) { 544 if ( qlPid && qlReady && QFile::exists( QPEApplication::qpeDir()+"plugins/application/lib"+args[0] + ".dylib" ) ) {
548#else 545#else
549 if ( qlPid && qlReady && QFile::exists( QPEApplication::qpeDir()+"plugins/application/lib"+args[0] + ".so" ) ) { 546 if ( qlPid && qlReady && QFile::exists( QPEApplication::qpeDir()+"plugins/application/lib"+args[0] + ".so" ) ) {
550#endif /* Q_OS_MACX */ 547#endif /* Q_OS_MACX */
551 qDebug( "Quick launching: %s", args[0] ); 548 odebug << "Quick launching: " << args[0] << "" << oendl;
552 if ( getuid() == 0 ) 549 if ( getuid() == 0 )
553 setpriority( PRIO_PROCESS, qlPid, 0 ); 550 setpriority( PRIO_PROCESS, qlPid, 0 );
554 QCString qlch("QPE/QuickLauncher-"); 551 QCString qlch("QPE/QuickLauncher-");
555 qlch += QString::number(qlPid); 552 qlch += QString::number(qlPid);
556 QCopEnvelope env( qlch, "execute(QStrList)" ); 553 QCopEnvelope env( qlch, "execute(QStrList)" );
557 env << slist; 554 env << slist;
558 runningApps[qlPid] = QString(args[0]); 555 runningApps[qlPid] = QString(args[0]);
559 emit launched(qlPid, QString(args[0])); 556 emit launched(qlPid, QString(args[0]));
560 QCopEnvelope e("QPE/System", "busy()"); 557 QCopEnvelope e("QPE/System", "busy()");
561 qlPid = 0; 558 qlPid = 0;
562 qlReady = FALSE; 559 qlReady = FALSE;
563 QTimer::singleShot( getuid() == 0 ? 800 : 1500, this, SLOT(createQuickLauncher()) ); 560 QTimer::singleShot( getuid() == 0 ? 800 : 1500, this, SLOT(createQuickLauncher()) );
564 } else { 561 } else {
565 int pid = ::vfork(); 562 int pid = ::vfork();
566 if ( !pid ) { 563 if ( !pid ) {
567 for ( int fd = 3; fd < 100; fd++ ) 564 for ( int fd = 3; fd < 100; fd++ )
568 ::close( fd ); 565 ::close( fd );
569 ::setpgid( ::getpid(), ::getppid() ); 566 ::setpgid( ::getpid(), ::getppid() );
570 // Try bindir first, so that foo/bar works too 567 // Try bindir first, so that foo/bar works too
571 ::execv( QPEApplication::qpeDir()+"bin/"+args[0], (char * const *)args ); 568 ::execv( QPEApplication::qpeDir()+"bin/"+args[0], (char * const *)args );
572 ::execvp( args[0], (char * const *)args ); 569 ::execvp( args[0], (char * const *)args );
573 _exit( -1 ); 570 _exit( -1 );
574 } 571 }
575 572
576 runningApps[pid] = QString(args[0]); 573 runningApps[pid] = QString(args[0]);
577 emit launched(pid, QString(args[0])); 574 emit launched(pid, QString(args[0]));
578 QCopEnvelope e("QPE/System", "busy()"); 575 QCopEnvelope e("QPE/System", "busy()");
579 } 576 }
580#else 577#else
581 QProcess *proc = new QProcess(this); 578 QProcess *proc = new QProcess(this);
582 if (proc){ 579 if (proc){
583 for (int i=0; i < slist.count(); i++) 580 for (int i=0; i < slist.count(); i++)
584 proc->addArgument(args[i]); 581 proc->addArgument(args[i]);
585 connect(proc, SIGNAL(processExited()), this, SLOT(processExited())); 582 connect(proc, SIGNAL(processExited()), this, SLOT(processExited()));
586 if (!proc->start()){ 583 if (!proc->start()){
587 qDebug("Unable to start application %s", args[0]); 584 odebug << "Unable to start application " << args[0] << "" << oendl;
588 }else{ 585 }else{
589 PROCESS_INFORMATION *procInfo = (PROCESS_INFORMATION *)proc->processIdentifier(); 586 PROCESS_INFORMATION *procInfo = (PROCESS_INFORMATION *)proc->processIdentifier();
590 if (procInfo){ 587 if (procInfo){
591 DWORD pid = procInfo->dwProcessId; 588 DWORD pid = procInfo->dwProcessId;
592 runningApps[pid] = QString(args[0]); 589 runningApps[pid] = QString(args[0]);
593 runningAppsProc.append(proc); 590 runningAppsProc.append(proc);
594 emit launched(pid, QString(args[0])); 591 emit launched(pid, QString(args[0]));
595 QCopEnvelope e("QPE/System", "busy()"); 592 QCopEnvelope e("QPE/System", "busy()");
596 }else{ 593 }else{
597 qDebug("Unable to read process inforation #1 for %s", args[0]); 594 odebug << "Unable to read process inforation #1 for " << args[0] << "" << oendl;
598 } 595 }
599 } 596 }
600 }else{ 597 }else{
601 qDebug("Unable to create process for application %s", args[0]); 598 odebug << "Unable to create process for application " << args[0] << "" << oendl;
602 return FALSE; 599 return FALSE;
603 } 600 }
604#endif 601#endif
605#endif //QT_NO_QWS_MULTIPROCESS 602#endif //QT_NO_QWS_MULTIPROCESS
606 603
607 delete [] args; 604 delete [] args;
608 return TRUE; 605 return TRUE;
609} 606}
610 607
611void AppLauncher::kill( int pid ) 608void AppLauncher::kill( int pid )
612{ 609{
613#ifndef Q_OS_WIN32 610#ifndef Q_OS_WIN32
614 ::kill( pid, SIGTERM ); 611 ::kill( pid, SIGTERM );
615#else 612#else
616 for ( QProcess *proc = runningAppsProc.first(); proc; proc = runningAppsProc.next() ) { 613 for ( QProcess *proc = runningAppsProc.first(); proc; proc = runningAppsProc.next() ) {
617 if ( proc->processIdentifier() == pid ) { 614 if ( proc->processIdentifier() == pid ) {
618 proc->kill(); 615 proc->kill();
619 break; 616 break;
620 } 617 }
621 } 618 }
622#endif 619#endif
623} 620}
624 621
625int AppLauncher::pidForName( const QString &appName ) 622int AppLauncher::pidForName( const QString &appName )
@@ -657,66 +654,66 @@ void AppLauncher::createQuickLauncher()
657 * LD_BIND_NOW will change the behaviour of ld.so and dlopen 654 * LD_BIND_NOW will change the behaviour of ld.so and dlopen
658 * RTLD_LAZY will be made RTLD_NOW which leads to problem 655 * RTLD_LAZY will be made RTLD_NOW which leads to problem
659 * with miscompiled libraries... if LD_BIND_NOW is set.. there 656 * with miscompiled libraries... if LD_BIND_NOW is set.. there
660 * is no way back.. We will wait for numbers from TT to see 657 * is no way back.. We will wait for numbers from TT to see
661 * if using LD_BIND_NOW is worth it - zecke 658 * if using LD_BIND_NOW is worth it - zecke
662 */ 659 */
663 //setenv( "LD_BIND_NOW", "1", 1 ); 660 //setenv( "LD_BIND_NOW", "1", 1 );
664 ::execv( QPEApplication::qpeDir()+"bin/quicklauncher", args ); 661 ::execv( QPEApplication::qpeDir()+"bin/quicklauncher", args );
665 ::execvp( "quicklauncher", args ); 662 ::execvp( "quicklauncher", args );
666 delete []args; 663 delete []args;
667 disabled = TRUE; 664 disabled = TRUE;
668 _exit( -1 ); 665 _exit( -1 );
669 } else if ( qlPid == -1 ) { 666 } else if ( qlPid == -1 ) {
670 qlPid = 0; 667 qlPid = 0;
671 } else { 668 } else {
672 if ( getuid() == 0 ) 669 if ( getuid() == 0 )
673 setpriority( PRIO_PROCESS, qlPid, 19 ); 670 setpriority( PRIO_PROCESS, qlPid, 19 );
674 } 671 }
675} 672}
676 673
677// Used only by Win32 674// Used only by Win32
678void AppLauncher::processExited() 675void AppLauncher::processExited()
679{ 676{
680#ifdef Q_OS_WIN32 677#ifdef Q_OS_WIN32
681 qDebug("AppLauncher::processExited()"); 678 odebug << "AppLauncher::processExited()" << oendl;
682 bool found = FALSE; 679 bool found = FALSE;
683 QProcess *proc = (QProcess *) sender(); 680 QProcess *proc = (QProcess *) sender();
684 if (!proc){ 681 if (!proc){
685 qDebug("Interanl error NULL proc"); 682 odebug << "Interanl error NULL proc" << oendl;
686 return; 683 return;
687 } 684 }
688 685
689 QString appName = proc->arguments()[0]; 686 QString appName = proc->arguments()[0];
690 qDebug("Removing application %s", appName.latin1()); 687 odebug << "Removing application " << appName << "" << oendl;
691 runningAppsProc.remove(proc); 688 runningAppsProc.remove(proc);
692 689
693 QMap<QString,int>::Iterator hbit = waitingHeartbeat.find(appName); 690 QMap<QString,int>::Iterator hbit = waitingHeartbeat.find(appName);
694 if ( hbit != waitingHeartbeat.end() ) { 691 if ( hbit != waitingHeartbeat.end() ) {
695 killTimer( *hbit ); 692 killTimer( *hbit );
696 waitingHeartbeat.remove( hbit ); 693 waitingHeartbeat.remove( hbit );
697 } 694 }
698 if ( appName == appKillerName ) { 695 if ( appName == appKillerName ) {
699 appKillerName = QString::null; 696 appKillerName = QString::null;
700 delete appKillerBox; 697 delete appKillerBox;
701 appKillerBox = 0; 698 appKillerBox = 0;
702 } 699 }
703 700
704 // Search for the app to find its PID 701 // Search for the app to find its PID
705 QMap<int, QString>::Iterator it; 702 QMap<int, QString>::Iterator it;
706 for (it = runningApps.begin(); it!= runningApps.end(); ++it){ 703 for (it = runningApps.begin(); it!= runningApps.end(); ++it){
707 if (it.data() == appName){ 704 if (it.data() == appName){
708 found = TRUE; 705 found = TRUE;
709 break; 706 break;
710 } 707 }
711 } 708 }
712 709
713 if (found){ 710 if (found){
714 emit terminated(it.key(), it.data()); 711 emit terminated(it.key(), it.data());
715 runningApps.remove(it.key()); 712 runningApps.remove(it.key());
716 }else{ 713 }else{
717 qDebug("Internal error application %s not listed as running", appName.latin1()); 714 odebug << "Internal error application " << appName << " not listed as running" << oendl;
718 } 715 }
719 716
720#endif 717#endif
721} 718}
722 719