Commit 43fb6f4e authored by David Jarvie's avatar David Jarvie
Browse files

Improve error messages; formatting

parent cffcdf51
Pipeline #33473 passed with stage
in 36 minutes and 20 seconds
/*
* shellprocess.cpp - execute a shell process
* Program: kalarm
* SPDX-FileCopyrightText: 2004, 2005, 2007, 2008 David Jarvie <djarvie@kde.org>
* SPDX-FileCopyrightText: 2004-2020 David Jarvie <djarvie@kde.org>
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
......@@ -44,8 +44,7 @@ bool ShellProcess::start(OpenMode openMode)
connect(this, SIGNAL(finished(int,QProcess::ExitStatus)), SLOT(slotExited(int,QProcess::ExitStatus)));
connect(this, &QProcess::readyReadStandardOutput, this, &ShellProcess::stdoutReady);
connect(this, &QProcess::readyReadStandardError, this, &ShellProcess::stderrReady);
QStringList args;
args << QStringLiteral("-c") << mCommand;
const QStringList args{ QStringLiteral("-c"), mCommand };
QProcess::start(QLatin1String(shellName()), args, openMode);
if (!waitForStarted())
{
......@@ -75,7 +74,7 @@ void ShellProcess::slotExited(int exitCode, QProcess::ExitStatus exitStatus)
else
{
// Some shells report if the command couldn't be found, or is not executable
if ((mShellName == "bash" && (exitCode == 126 || exitCode == 127))
if (((mShellName == "bash" || mShellName == "zsh") && (exitCode == 126 || exitCode == 127))
|| (mShellName == "ksh" && exitCode == 127))
{
qCWarning(KALARM_LOG) << "ShellProcess::slotExited:" << mCommand << ":" << mShellName << ": not found or not executable";
......@@ -144,8 +143,9 @@ QString ShellProcess::errorMessage() const
case UNAUTHORISED:
return i18nc("@info", "Failed to execute command (shell access not authorized)");
case START_FAIL:
case NOT_FOUND:
return i18nc("@info", "Failed to execute command");
case NOT_FOUND:
return i18nc("@info", "Failed to execute command (not found or not executable)");
case DIED:
return i18nc("@info", "Command execution error");
case SUCCESS:
......
/*
* shellprocess.h - execute a process through the shell
* Program: kalarm
* SPDX-FileCopyrightText: 2004-2019 David Jarvie <djarvie@kde.org>
* SPDX-FileCopyrightText: 2004-2020 David Jarvie <djarvie@kde.org>
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
......@@ -39,97 +39,104 @@
*/
class ShellProcess : public KProcess
{
Q_OBJECT
public:
/** Current status of the shell process.
* @li INACTIVE - start() has not yet been called to run the command.
* @li RUNNING - the command is currently running.
* @li SUCCESS - the command appears to have exited successfully.
* @li UNAUTHORISED - shell commands are not authorised for this user.
* @li DIED - the command didn't exit cleanly, i.e. was killed or died.
* @li NOT_FOUND - the command was either not found or not executable.
* @li START_FAIL - the command couldn't be started for other reasons.
*/
enum Status {
INACTIVE, // start() has not yet been called to run the command
RUNNING, // command is currently running
SUCCESS, // command appears to have exited successfully
UNAUTHORISED, // shell commands are not authorised for this user
DIED, // command didn't exit cleanly, i.e. was killed or died
NOT_FOUND, // command either not found or not executable
START_FAIL // command couldn't be started for other reasons
};
/** Constructor.
* @param command The command line to be run when start() is called.
*/
explicit ShellProcess(const QString& command);
/** Executes the configured command.
* @param openMode WriteOnly for stdin only, ReadOnly for stdout/stderr only, else ReadWrite.
*/
bool start(OpenMode = ReadWrite);
/** Returns the current status of the shell process. */
Status status() const { return mStatus; }
/** Returns the shell exit code. Only valid if status() == SUCCESS or NOT_FOUND. */
int exitCode() const { return mExitCode; }
/** Returns whether the command was run successfully.
* @return True if the command has been run and appears to have exited successfully.
*/
bool normalExit() const { return mStatus == SUCCESS; }
/** Returns the command configured to be run. */
const QString& command() const { return mCommand; }
/** Returns the error message corresponding to the command exit status.
* @return Error message if an error occurred. Null string if the command has not yet
* exited, or if the command ran successfully.
*/
QString errorMessage() const;
/** Writes a string to the process's STDIN. */
void writeStdin(const char* buffer, int bufflen);
/** Tell the process to exit once any outstanding STDIN strings have been written. */
void stdinExit();
/** Returns whether the user is authorised to run shell commands. Shell commands may
* be prohibited in kiosk mode, for example.
*/
static bool authorised();
/** Determines which shell to use.
* @return file name of shell, excluding path.
*/
static const QByteArray& shellName() { shellPath(); return mShellName; }
/** Determines which shell to use.
* @return path name of shell.
*/
static const QByteArray& shellPath();
Q_SIGNALS:
/** Signal emitted when the shell process execution completes. It is not emitted
* if start() did not attempt to start the command execution, e.g. in kiosk mode.
*/
void shellExited(ShellProcess*);
/** Signal emitted when input is available from the process's stdout. */
void receivedStdout(ShellProcess*);
/** Signal emitted when input is available from the process's stderr. */
void receivedStderr(ShellProcess*);
private Q_SLOTS:
void writtenStdin(qint64 bytes);
void stdoutReady() { Q_EMIT receivedStdout(this); }
void stderrReady() { Q_EMIT receivedStderr(this); }
void slotExited(int exitCode, QProcess::ExitStatus);
private:
// Prohibit the following inherited methods
ShellProcess& operator<<(const QString&);
ShellProcess& operator<<(const QStringList&);
static QByteArray mShellName; // name of shell to be used
static QByteArray mShellPath; // path of shell to be used
static bool mInitialised; // true once static data has been initialised
static bool mAuthorised; // true if shell commands are authorised
QString mCommand; // copy of command to be executed
QQueue<QByteArray> mStdinQueue; // queued strings to send to STDIN
qint64 mStdinBytes {0}; // bytes still to be written from first queued string
int mExitCode; // shell exit value (if mStatus == SUCCESS or NOT_FOUND)
Status mStatus {INACTIVE}; // current execution status
bool mStdinExit {false}; // exit once STDIN queue has been written
Q_OBJECT
public:
/** Current status of the shell process. */
enum Status
{
INACTIVE, //!< start() has not yet been called to run the command
RUNNING, //!< command is currently running
SUCCESS, //!< command appears to have exited successfully
UNAUTHORISED, //!< shell commands are not authorised for this user
DIED, //!< command didn't exit cleanly, i.e. was killed or died
NOT_FOUND, //!< command either not found or not executable
START_FAIL //!< command couldn't be started for other reasons
};
/** Constructor.
* @param command The command line to be run when start() is called.
*/
explicit ShellProcess(const QString& command);
/** Executes the configured command.
* @param openMode WriteOnly for stdin only, ReadOnly for stdout/stderr only, else ReadWrite.
*/
bool start(OpenMode = ReadWrite);
/** Returns the current status of the shell process. */
Status status() const { return mStatus; }
/** Returns the shell exit code. Only valid if status() == SUCCESS or NOT_FOUND. */
int exitCode() const { return mExitCode; }
/** Returns whether the command was run successfully.
* @return True if the command has been run and appears to have exited successfully.
*/
bool normalExit() const { return mStatus == SUCCESS; }
/** Returns the command configured to be run. */
const QString& command() const { return mCommand; }
/** Returns the error message corresponding to the command exit status.
* @return Error message if an error occurred. Null string if the command has not yet
* exited, or if the command ran successfully.
*/
QString errorMessage() const;
/** Writes a string to the process's STDIN. */
void writeStdin(const char* buffer, int bufflen);
/** Tell the process to exit once any outstanding STDIN strings have been written. */
void stdinExit();
/** Returns whether the user is authorised to run shell commands. Shell commands may
* be prohibited in kiosk mode, for example.
*/
static bool authorised();
/** Determines which shell to use.
* @return file name of shell, excluding path.
*/
static const QByteArray& shellName() { shellPath(); return mShellName; }
/** Determines which shell to use.
* @return path name of shell.
*/
static const QByteArray& shellPath();
Q_SIGNALS:
/** Signal emitted when the shell process execution completes. It is not emitted
* if start() did not attempt to start the command execution, e.g. in kiosk mode.
*/
void shellExited(ShellProcess*);
/** Signal emitted when input is available from the process's stdout. */
void receivedStdout(ShellProcess*);
/** Signal emitted when input is available from the process's stderr. */
void receivedStderr(ShellProcess*);
private Q_SLOTS:
void writtenStdin(qint64 bytes);
void stdoutReady() { Q_EMIT receivedStdout(this); }
void stderrReady() { Q_EMIT receivedStderr(this); }
void slotExited(int exitCode, QProcess::ExitStatus);
private:
// Prohibit the following inherited methods
ShellProcess& operator<<(const QString&);
ShellProcess& operator<<(const QStringList&);
static QByteArray mShellName; // name of shell to be used
static QByteArray mShellPath; // path of shell to be used
static bool mInitialised; // true once static data has been initialised
static bool mAuthorised; // true if shell commands are authorised
QString mCommand; // copy of command to be executed
QQueue<QByteArray> mStdinQueue; // queued strings to send to STDIN
qint64 mStdinBytes {0}; // bytes still to be written from first queued string
int mExitCode; // shell exit value (if mStatus == SUCCESS or NOT_FOUND)
Status mStatus {INACTIVE}; // current execution status
bool mStdinExit {false}; // exit once STDIN queue has been written
};
#endif // SHELLPROCESS_H
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment