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