-rw-r--r-- | library/global.cpp | 65 |
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 @@ -33,24 +33,25 @@ #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; @@ -594,36 +595,78 @@ void Global::invoke(const QString &c) // 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 ) |