diff --git a/src/ProcessInfo.cpp b/src/ProcessInfo.cpp index d88067432..ef49a1f16 100644 --- a/src/ProcessInfo.cpp +++ b/src/ProcessInfo.cpp @@ -28,7 +28,6 @@ // Qt #include #include -#include #include #include #include @@ -53,9 +52,13 @@ ProcessInfo::ProcessInfo(int pid , bool enableEnvironmentRead) , _pid(pid) , _parentPid(0) , _foregroundPid(0) + , _lastError(NoError) { } +ProcessInfo::Error ProcessInfo::error() const { return _lastError; } +void ProcessInfo::setError(Error error) { _lastError = error; } + void ProcessInfo::update() { readProcessInfo(_pid,_enableEnvironmentRead); @@ -67,13 +70,27 @@ QString ProcessInfo::format(const QString& input) const QString output(input); - // search for and replace known markers + // search for and replace known marker output.replace("%u","NOT IMPLEMENTED YET"); output.replace("%n",name(&ok)); output.replace("%c",formatCommand(name(&ok),arguments(&ok),ShortCommandFormat)); output.replace("%C",formatCommand(name(&ok),arguments(&ok),LongCommandFormat)); - output.replace("%D",currentDir(&ok)); - output.replace("%d",formatShortDir(currentDir(&ok))); + + // read current dir, if an error occurs try the parent as the next + // best option + int currentPid = parentPid(&ok); + QString dir = currentDir(&ok); + while ( !ok && currentPid != 0 ) + { + ProcessInfo* current = ProcessInfo::newInstance(currentPid); + current->update(); + currentPid = current->parentPid(&ok); + dir = current->currentDir(&ok); + delete current; + } + + output.replace("%D",dir); + output.replace("%d",formatShortDir(dir)); // remove any remaining %[LETTER] sequences // output.replace(QRegExp("%\\w"),QString::null); @@ -303,38 +320,52 @@ bool UnixProcessInfo::readProcessInfo(int pid , bool enableEnvironmentRead) } else { - qDebug() << __FUNCTION__ << "failed to open stat file"; + setFileError( processInfo.error() ); return false; } // check that data was read successfully bool ok = false; int foregroundPid = foregroundPidString.toInt(&ok); - if (!ok) return false; + if (ok) + setForegroundPid(foregroundPid); int parentPid = parentPidString.toInt(&ok); - if (!ok) return false; + if (ok) + setParentPid(parentPid); - if (processNameString.isEmpty()) return false; + if (!processNameString.isEmpty()) + setName(processNameString); - if (!readArguments(pid)) return false; - - if (!readCurrentDir(pid)) return false; + readArguments(pid); + readCurrentDir(pid); if ( enableEnvironmentRead ) { - if (!readEnvironment(pid)) return false; + readEnvironment(pid); } // update object state setPid(pid); - setName(processNameString); - setForegroundPid(foregroundPid); - setParentPid(parentPid); return true; } +void ProcessInfo::setFileError( QFile::FileError error ) +{ + switch ( error ) + { + case PermissionsError: + setError( PermissionsError ); + break; + case NoError: + setError( NoError ); + break; + default: + setError( UnknownError ); + } +} + ProcessInfo* ProcessInfo::newInstance(int pid,bool enableEnvironmentRead) { #ifdef Q_OS_UNIX @@ -374,6 +405,10 @@ bool UnixProcessInfo::readArguments(int pid) addArgument(entry); } } + else + { + setFileError( argumentsFile.error() ); + } return true; } @@ -381,13 +416,21 @@ bool UnixProcessInfo::readArguments(int pid) bool UnixProcessInfo::readCurrentDir(int pid) { QFileInfo info( QString("/proc/%1/cwd").arg(pid) ); - if ( info.isSymLink() ) + + const bool readable = info.isReadable(); + + if ( readable && info.isSymLink() ) { setCurrentDir( info.symLinkTarget() ); return true; } else { + if ( !readable ) + setError( PermissionsError ); + else + setError( UnknownError ); + return false; } } @@ -422,6 +465,10 @@ bool UnixProcessInfo::readEnvironment(int pid) } } } + else + { + setFileError( environmentFile.error() ); + } return true; } diff --git a/src/ProcessInfo.h b/src/ProcessInfo.h index 4f6e57931..86cc24d6e 100644 --- a/src/ProcessInfo.h +++ b/src/ProcessInfo.h @@ -21,6 +21,7 @@ #define PROCESSINFO_H // Qt +#include #include #include #include @@ -174,6 +175,25 @@ public: */ QString format(const QString& text) const; + /** + * This enum describes the errors which can occur when trying to read + * a process's information. + */ + enum Error + { + /** No error occurred. */ + NoError, + /** The nature of the error is unknown. */ + UnknownError, + /** Konsole does not have permission to obtain the process information. */ + PermissionsError + }; + + /** + * Returns the last error which occurred. + */ + Error error() const; + protected: /** * Constructs a new process instance. You should not call the constructor @@ -215,6 +235,12 @@ protected: /** Sets the current working directory for the process */ void setCurrentDir(const QString& dir); + /** Sets the error */ + void setError( Error error ); + + /** Convenience method. Sets the error based on a QFile error code. */ + void setFileError( QFile::FileError error ); + /** * Adds a commandline argument for the process, as returned * by arguments() @@ -269,6 +295,9 @@ private: int _pid; int _parentPid; int _foregroundPid; + + Error _lastError; + QString _name; QString _currentDir;