summaryrefslogtreecommitdiff
authorsandman <sandman>2002-12-17 00:29:22 (UTC)
committer sandman <sandman>2002-12-17 00:29:22 (UTC)
commit2d39ff65b27c1a680a56c1b70b534e3cb767e08f (patch) (side-by-side diff)
tree09e5cc3f7157681fe51fe83bb54ebbaa548d8c64
parent70090722d240bed8c390281e072c9bcfc5ba7782 (diff)
downloadopie-2d39ff65b27c1a680a56c1b70b534e3cb767e08f.zip
opie-2d39ff65b27c1a680a56c1b70b534e3cb767e08f.tar.gz
opie-2d39ff65b27c1a680a56c1b70b534e3cb767e08f.tar.bz2
replaced the simple fork and execv method of starting applications with a
more sophisticated method (mostly taken from K/OProcess, because we can't use libopie in libqpe). We can detect now, if apps can not be started.
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--library/global.cpp65
1 files changed, 54 insertions, 11 deletions
diff --git a/library/global.cpp b/library/global.cpp
index d6ba84f..68a3a75 100644
--- a/library/global.cpp
+++ b/library/global.cpp
@@ -21,48 +21,49 @@
#include <qpe/qpedebug.h>
#include <qpe/global.h>
#include <qpe/qdawg.h>
#include <qpe/qpeapplication.h>
#include <qpe/resource.h>
#include <qpe/storage.h>
#include <qpe/applnk.h>
#include <qpe/qcopenvelope_qws.h>
#include <qfile.h>
#include <qlabel.h>
#include <qtimer.h>
#include <qmap.h>
#include <qdict.h>
#include <qdir.h>
#include <qmessagebox.h>
#include <qregexp.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <fcntl.h>
#include <unistd.h>
+#include <errno.h>
#include <qwindowsystem_qws.h> // for qwsServer
#include <qdatetime.h>
#include <qfile.h>
namespace {
// checks if the storage should be searched
bool checkStorage(const QString &path ){ // this is a small Config replacement cause config is too limited -zecke
QFile file(path );
if(!file.open(IO_ReadOnly ) )
return true;
QByteArray array = file.readAll();
QStringList list = QStringList::split('\n', QString( array ) );
for(QStringList::Iterator it = list.begin(); it != list.end(); ++it ){
if( (*it).startsWith("autocheck = 0" ) ){
return false;
}else if( (*it).startsWith("autocheck = 1" ) ){
return true;
}
}
return true;
}
@@ -582,60 +583,102 @@ void Global::invoke(const QString &c)
QStrList slist;
unsigned int j;
for ( j = 0; j < list.count(); j++ )
slist.append( list[j].utf8() );
const char **args = new (const char *)[slist.count() + 1];
for ( j = 0; j < slist.count(); j++ )
args[j] = slist.at(j);
args[j] = NULL;
#if !defined(QT_NO_COP)
// an attempt to show a wait...
// more logic should be used, but this will be fine for the moment...
QCopEnvelope ( "QPE/System", "busy()" );
#endif
#ifdef HAVE_QUICKEXEC
QString libexe = qpeDir()+"/binlib/lib"+args[0] + ".so";
qDebug("libfile = %s", libexe.latin1() );
if ( QFile::exists( libexe ) ) {
qDebug("calling quickexec %s", libexe.latin1() );
quickexecv( libexe.utf8().data(), (const char **)args );
} else
#endif
- {
- if ( !::vfork() ) {
- for ( int fd = 3; fd < 100; fd++ )
- ::close( fd );
- ::setpgid( ::getpid(), ::getppid() );
- // Try bindir first, so that foo/bar works too
- ::execv( qpeDir()+"/bin/"+args[0], (char * const *)args );
- ::execvp( args[0], (char * const *)args );
- _exit( -1 );
- }
+ {
+ bool success = false;
+ int pfd [2];
+ if ( ::pipe ( pfd ) < 0 )
+ pfd [0] = pfd [1] = -1;
+
+ pid_t pid = ::fork ( );
+
+ if ( pid == 0 ) { // child
+ for ( int fd = 3; fd < 100; fd++ ) {
+ if ( fd != pfd [1] )
+ ::close ( fd );
+ }
+ ::setpgid ( ::getpid ( ), ::getppid ( ));
+
+ // Closing of fd[1] indicates that the execvp succeeded!
+ if ( pfd [1] >= 0 )
+ ::fcntl ( pfd [1], F_SETFD, FD_CLOEXEC );
+
+ // Try bindir first, so that foo/bar works too
+ ::execv ( qpeDir ( ) + "/bin/" + args [0], (char * const *) args );
+ ::execvp ( args [0], (char * const *) args );
+
+ char resultByte = 1;
+ if ( pfd [1] >= 0 )
+ ::write ( pfd [1], &resultByte, 1 );
+ ::_exit ( -1 );
+ }
+ else if ( pid > 0 ) {
+ success = true;
+
+ if ( pfd [1] >= 0 )
+ ::close ( pfd [1] );
+ if ( pfd [0] >= 0 ) {
+ while ( true ) {
+ char resultByte;
+ int n = ::read ( pfd [0], &resultByte, 1 );
+ if ( n == 1 ) {
+ success = false;
+ break;
+ }
+ if (( n == -1 ) && (( errno == ECHILD ) || ( errno == EINTR )))
+ continue;
+
+ break; // success
+ }
+ ::close ( pfd [0] );
+ }
+ }
+ if ( success )
+ StartingAppList::add( list[0] );
+ else
+ QMessageBox::warning( 0, "Error", "Could not start the application " + c, "Ok", 0, 0, 0, 1 );
}
- StartingAppList::add( list[0] );
#endif //QT_NO_QWS_MULTIPROCESS
}
/*!
Executes the application identfied by \a c, passing \a
document if it isn't null.
Note that a better approach might be to send a QCop message to the
application's QPE/Application/\e{appname} channel.
*/
void Global::execute( const QString &c, const QString& document )
{
if ( qApp->type() != QApplication::GuiServer ) {
// ask the server to do the work
#if !defined(QT_NO_COP)
if ( document.isNull() ) {
QCopEnvelope e( "QPE/System", "execute(QString)" );
e << c;
} else {
QCopEnvelope e( "QPE/System", "execute(QString,QString)" );
e << c << document;
}
#endif