Proof of concept attempt to implement KAuth.
This commit is contained in:
parent
e7b0192630
commit
47429dd1bf
|
@ -57,6 +57,7 @@ find_package(Qt5 ${QT_MIN_VERSION} CONFIG REQUIRED COMPONENTS
|
|||
|
||||
# Load the frameworks we need
|
||||
find_package(KF5 REQUIRED
|
||||
Auth
|
||||
I18n
|
||||
CoreAddons
|
||||
WidgetsAddons
|
||||
|
|
|
@ -44,6 +44,7 @@ target_link_libraries( kpmcore
|
|||
${BLKID_LIBRARIES}
|
||||
${LIBATASMART_LIBRARIES}
|
||||
Qt5::DBus
|
||||
KF5::Auth
|
||||
KF5::I18n
|
||||
KF5::CoreAddons
|
||||
KF5::WidgetsAddons
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#include <QStringList>
|
||||
#include <QString>
|
||||
#include <QVector>
|
||||
#include <QThread>
|
||||
|
||||
#include <KLocalizedString>
|
||||
#include <KPluginFactory>
|
||||
|
@ -33,6 +34,8 @@
|
|||
CoreBackendManager::CoreBackendManager() :
|
||||
m_Backend(nullptr)
|
||||
{
|
||||
m_KAuthThread = new QThread();
|
||||
kauthThread()->start();
|
||||
}
|
||||
|
||||
CoreBackendManager* CoreBackendManager::self()
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
|
||||
#include <QVector>
|
||||
|
||||
class QThread;
|
||||
class QString;
|
||||
class QStringList;
|
||||
class KPluginMetaData;
|
||||
|
@ -77,8 +78,16 @@ public:
|
|||
return m_Backend;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return a pointer to the thread where ExternalCommand will start KAuth job
|
||||
*/
|
||||
QThread* kauthThread() {
|
||||
return m_KAuthThread;
|
||||
}
|
||||
|
||||
private:
|
||||
CoreBackend* m_Backend;
|
||||
QThread* m_KAuthThread;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -177,10 +177,10 @@ bool fat16::updateUUID(Report& report, const QString& deviceNode) const
|
|||
|
||||
ExternalCommand cmd(report, QStringLiteral("dd"), { QStringLiteral("of=") + deviceNode , QStringLiteral("bs=1"), QStringLiteral("count=4"), QStringLiteral("seek=39") });
|
||||
|
||||
if (!cmd.start())
|
||||
if (!cmd.write(QByteArray(uuid, sizeof(uuid))))
|
||||
return false;
|
||||
|
||||
if (cmd.write(uuid, sizeof(uuid)) != sizeof(uuid))
|
||||
if (!cmd.start())
|
||||
return false;
|
||||
|
||||
return cmd.waitFor(-1);
|
||||
|
|
|
@ -59,10 +59,10 @@ bool fat32::updateUUID(Report& report, const QString& deviceNode) const
|
|||
// HACK: replace this hack with fatlabel "-i" (dosfstools 4.2)
|
||||
ExternalCommand cmd(report, QStringLiteral("dd"), { QStringLiteral("of=") + deviceNode, QStringLiteral("bs=1"), QStringLiteral("count=4"), QStringLiteral("seek=67") });
|
||||
|
||||
if (!cmd.start())
|
||||
if (!cmd.write(QByteArray(uuid, sizeof(uuid))))
|
||||
return false;
|
||||
|
||||
if (cmd.write(uuid, sizeof(uuid)) != sizeof(uuid))
|
||||
if (!cmd.start())
|
||||
return false;
|
||||
|
||||
return cmd.waitFor(-1);
|
||||
|
|
|
@ -34,6 +34,7 @@
|
|||
#include <KLocalizedString>
|
||||
|
||||
#include <QFileInfo>
|
||||
#include <QStandardPaths>
|
||||
#include <QStorageInfo>
|
||||
|
||||
const std::array< QColor, FileSystem::__lastType > FileSystem::defaultColorCode =
|
||||
|
@ -548,13 +549,14 @@ bool FileSystem::unmount(Report& report, const QString& deviceNode)
|
|||
return false;
|
||||
}
|
||||
|
||||
// FIXME: args and expectedCode is now unused.
|
||||
bool FileSystem::findExternal(const QString& cmdName, const QStringList& args, int expectedCode)
|
||||
{
|
||||
ExternalCommand cmd(cmdName, args);
|
||||
if (!cmd.run())
|
||||
return false;
|
||||
QString cmd = QStandardPaths::findExecutable(cmdName);
|
||||
if (cmd.isEmpty())
|
||||
cmd = QStandardPaths::findExecutable(cmdName, { QStringLiteral("/sbin/"), QStringLiteral("/usr/sbin/"), QStringLiteral("/usr/local/sbin/") });
|
||||
|
||||
return cmd.exitCode() == 0 || cmd.exitCode() == expectedCode;
|
||||
return !cmd.isEmpty();
|
||||
}
|
||||
|
||||
bool FileSystem::supportToolFound() const
|
||||
|
|
|
@ -96,7 +96,7 @@ qint64 jfs::readUsedCapacity(const QString& deviceNode) const
|
|||
{
|
||||
ExternalCommand cmd(QStringLiteral("jfs_debugfs"), QStringList() << deviceNode);
|
||||
|
||||
if (cmd.start() && cmd.write("dm") == 2 && cmd.waitFor()) {
|
||||
if (cmd.write(QByteArrayLiteral("dm")) && cmd.start() && cmd.waitFor()) {
|
||||
qint64 blockSize = -1;
|
||||
QRegularExpression re(QStringLiteral("Block Size: (\\d+)"));
|
||||
QRegularExpressionMatch reBlockSize = re.match(cmd.output());
|
||||
|
|
|
@ -127,8 +127,8 @@ bool luks::create(Report& report, const QString& deviceNode)
|
|||
QStringLiteral("--force-password"),
|
||||
QStringLiteral("luksFormat"),
|
||||
deviceNode });
|
||||
if (!( createCmd.start(-1) &&
|
||||
createCmd.write(m_passphrase.toLocal8Bit() + '\n') == m_passphrase.toLocal8Bit().length() + 1 &&
|
||||
if (!( createCmd.write(m_passphrase.toLocal8Bit() + '\n') &&
|
||||
createCmd.start(-1) &&
|
||||
createCmd.waitFor() && createCmd.exitCode() == 0))
|
||||
{
|
||||
return false;
|
||||
|
@ -139,7 +139,7 @@ bool luks::create(Report& report, const QString& deviceNode)
|
|||
deviceNode,
|
||||
suggestedMapperName(deviceNode) });
|
||||
|
||||
if (!( openCmd.start(-1) && openCmd.write(m_passphrase.toLocal8Bit() + '\n') == m_passphrase.toLocal8Bit().length() + 1 && openCmd.waitFor()))
|
||||
if (!( openCmd.write(m_passphrase.toLocal8Bit() + '\n') && openCmd.start(-1) && openCmd.waitFor()))
|
||||
return false;
|
||||
|
||||
scan(deviceNode);
|
||||
|
@ -261,8 +261,8 @@ bool luks::cryptOpen(QWidget* parent, const QString& deviceNode)
|
|||
deviceNode,
|
||||
suggestedMapperName(deviceNode) });
|
||||
|
||||
if (!( openCmd.start(-1) &&
|
||||
openCmd.write(passphrase.toLocal8Bit() + '\n') == passphrase.toLocal8Bit().length() + 1 &&
|
||||
if (!( openCmd.write(passphrase.toLocal8Bit() + '\n') &&
|
||||
openCmd.start(-1) &&
|
||||
openCmd.waitFor() && openCmd.exitCode() == 0) )
|
||||
return false;
|
||||
|
||||
|
|
|
@ -125,8 +125,7 @@ qint64 ntfs::readUsedCapacity(const QString& deviceNode) const
|
|||
|
||||
bool ntfs::writeLabel(Report& report, const QString& deviceNode, const QString& newLabel)
|
||||
{
|
||||
ExternalCommand writeCmd(report, QStringLiteral("ntfslabel"), { QStringLiteral("--force"), deviceNode, newLabel });
|
||||
writeCmd.setProcessChannelMode(QProcess::SeparateChannels);
|
||||
ExternalCommand writeCmd(report, QStringLiteral("ntfslabel"), { QStringLiteral("--force"), deviceNode, newLabel }, QProcess::SeparateChannels);
|
||||
|
||||
if (!writeCmd.run(-1))
|
||||
return false;
|
||||
|
|
|
@ -113,9 +113,9 @@ bool ocfs2::create(Report& report, const QString& deviceNode)
|
|||
{
|
||||
ExternalCommand cmd(report, QStringLiteral("mkfs.ocfs2"), { deviceNode });
|
||||
|
||||
if (cmd.start())
|
||||
if (cmd.write("y\n"))
|
||||
{
|
||||
cmd.write("y\n");
|
||||
cmd.start();
|
||||
cmd.waitFor(-1);
|
||||
|
||||
return cmd.exitCode() == 0;
|
||||
|
|
|
@ -154,12 +154,12 @@ bool reiserfs::resize(Report& report, const QString& deviceNode, qint64 length)
|
|||
ExternalCommand cmd(report, QStringLiteral("resize_reiserfs"),
|
||||
{ deviceNode, QStringLiteral("-q"), QStringLiteral("-s"), QString::number(length) });
|
||||
|
||||
bool rval = cmd.start(-1);
|
||||
bool rval = cmd.write(QByteArrayLiteral("y\n"));
|
||||
|
||||
if (!rval)
|
||||
return false;
|
||||
|
||||
if (cmd.write("y\n", 2) != 2)
|
||||
if (!cmd.start(-1))
|
||||
return false;
|
||||
|
||||
return cmd.waitFor(-1) && (cmd.exitCode() == 0 || cmd.exitCode() == 256);
|
||||
|
|
|
@ -47,8 +47,9 @@ void udf::init()
|
|||
|
||||
if (m_Create == cmdSupportFileSystem) {
|
||||
// Detect old mkudffs prior to version 1.1 by lack of --label option
|
||||
ExternalCommand cmd(QStringLiteral("mkudffs"), { QStringLiteral("--help") });
|
||||
oldMkudffsVersion = cmd.run(-1) && !cmd.output().contains(QStringLiteral("--label"));
|
||||
// ExternalCommand cmd(QStringLiteral("mkudffs"), { QStringLiteral("--help") });
|
||||
// oldMkudffsVersion = cmd.run(-1) && !cmd.output().contains(QStringLiteral("--label"));
|
||||
oldMkudffsVersion = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -74,8 +74,8 @@ bool SfdiskDevice::createPartitionTable(Report& report, const PartitionTable& pt
|
|||
tableType = ptable.typeName().toLocal8Bit();
|
||||
|
||||
ExternalCommand createCommand(report, QStringLiteral("sfdisk"), { m_device->deviceNode() } );
|
||||
if ( createCommand.start(-1) && createCommand.write(QByteArrayLiteral("label: ") + tableType +
|
||||
QByteArrayLiteral("\nwrite\n")) && createCommand.waitFor() ) {
|
||||
if ( createCommand.write(QByteArrayLiteral("label: ") + tableType +
|
||||
QByteArrayLiteral("\nwrite\n")) && createCommand.start(-1) && createCommand.waitFor() ) {
|
||||
return createCommand.output().contains(QStringLiteral("Script header accepted."));
|
||||
}
|
||||
|
||||
|
@ -112,7 +112,7 @@ bool SfdiskDevice::writeData(QByteArray& buffer, qint64 offset)
|
|||
QStringLiteral("bs=1M"),
|
||||
QStringLiteral("oflag=seek_bytes"),
|
||||
QStringLiteral("conv=fsync") }, QProcess::SeparateChannels);
|
||||
if ( ddCommand.start(-1) && ddCommand.write(buffer) == buffer.size() && ddCommand.waitFor() && ddCommand.exitCode() == 0 ) {
|
||||
if ( ddCommand.write(buffer) && ddCommand.start(-1) && ddCommand.waitFor() && ddCommand.exitCode() == 0 ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -74,9 +74,9 @@ QString SfdiskPartitionTable::createPartition(Report& report, const Partition& p
|
|||
|
||||
// NOTE: at least on GPT partition types "are" partition flags
|
||||
ExternalCommand createCommand(report, QStringLiteral("sfdisk"), { QStringLiteral("--force"), QStringLiteral("--append"), partition.devicePath() } );
|
||||
if ( createCommand.start(-1) && createCommand.write(QByteArrayLiteral("start=") + QByteArray::number(partition.firstSector()) +
|
||||
if ( createCommand.write(QByteArrayLiteral("start=") + QByteArray::number(partition.firstSector()) +
|
||||
type +
|
||||
QByteArrayLiteral(" size=") + QByteArray::number(partition.length()) + QByteArrayLiteral("\nwrite\n")) && createCommand.waitFor() ) {
|
||||
QByteArrayLiteral(" size=") + QByteArray::number(partition.length()) + QByteArrayLiteral("\nwrite\n")) && createCommand.start(-1) && createCommand.waitFor() ) {
|
||||
QRegularExpression re(QStringLiteral("Created a new partition (\\d)"));
|
||||
QRegularExpressionMatch rem = re.match(createCommand.output());
|
||||
if (rem.hasMatch())
|
||||
|
@ -101,10 +101,10 @@ bool SfdiskPartitionTable::deletePartition(Report& report, const Partition& part
|
|||
bool SfdiskPartitionTable::updateGeometry(Report& report, const Partition& partition, qint64 sectorStart, qint64 sectorEnd)
|
||||
{
|
||||
ExternalCommand sfdiskCommand(report, QStringLiteral("sfdisk"), { QStringLiteral("--force"), partition.devicePath(), QStringLiteral("-N"), QString::number(partition.number()) } );
|
||||
if ( sfdiskCommand.start(-1) && sfdiskCommand.write(QByteArrayLiteral("start=") + QByteArray::number(sectorStart) +
|
||||
if ( sfdiskCommand.write(QByteArrayLiteral("start=") + QByteArray::number(sectorStart) +
|
||||
QByteArrayLiteral(" size=") + QByteArray::number(sectorEnd - sectorStart + 1) +
|
||||
QByteArrayLiteral("\nY\n"))
|
||||
&& sfdiskCommand.waitFor() && sfdiskCommand.exitCode() == 0) {
|
||||
&& sfdiskCommand.start(-1) && sfdiskCommand.waitFor() && sfdiskCommand.exitCode() == 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -16,3 +16,10 @@ set(UTIL_LIB_HDRS
|
|||
util/htmlreport.h
|
||||
util/report.h
|
||||
)
|
||||
|
||||
add_executable(kpmcore_externalcommand util/externalcommandhelper.cpp)
|
||||
target_link_libraries(kpmcore_externalcommand KF5::Auth)
|
||||
install(TARGETS kpmcore_externalcommand DESTINATION ${KAUTH_HELPER_INSTALL_DIR})
|
||||
|
||||
kauth_install_helper_files(kpmcore_externalcommand org.kde.kpmcore.externalcommand root)
|
||||
kauth_install_actions(org.kde.kpmcore.externalcommand util/org.kde.kpmcore.externalcommand.actions)
|
||||
|
|
|
@ -16,14 +16,20 @@
|
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>.*
|
||||
*************************************************************************/
|
||||
|
||||
#include "backend/corebackendmanager.h"
|
||||
#include "util/externalcommand.h"
|
||||
|
||||
#include "util/report.h"
|
||||
|
||||
#include <QDebug>
|
||||
#include <QEventLoop>
|
||||
#include <QtGlobal>
|
||||
#include <QStandardPaths>
|
||||
#include <QString>
|
||||
#include <QStringList>
|
||||
#include <QTimer>
|
||||
#include <QThread>
|
||||
|
||||
#include <KAuth>
|
||||
#include <KLocalizedString>
|
||||
|
||||
/** Creates a new ExternalCommand instance without Report.
|
||||
|
@ -31,7 +37,6 @@
|
|||
@param args the arguments to pass to the command
|
||||
*/
|
||||
ExternalCommand::ExternalCommand(const QString& cmd, const QStringList& args, const QProcess::ProcessChannelMode processChannelMode) :
|
||||
QProcess(),
|
||||
m_Report(nullptr),
|
||||
m_Command(cmd),
|
||||
m_Args(args),
|
||||
|
@ -47,7 +52,6 @@ ExternalCommand::ExternalCommand(const QString& cmd, const QStringList& args, co
|
|||
@param args the arguments to pass to the command
|
||||
*/
|
||||
ExternalCommand::ExternalCommand(Report& report, const QString& cmd, const QStringList& args, const QProcess::ProcessChannelMode processChannelMode) :
|
||||
QProcess(),
|
||||
m_Report(report.newChild()),
|
||||
m_Command(cmd),
|
||||
m_Args(args),
|
||||
|
@ -59,11 +63,11 @@ ExternalCommand::ExternalCommand(Report& report, const QString& cmd, const QStri
|
|||
|
||||
void ExternalCommand::setup(const QProcess::ProcessChannelMode processChannelMode)
|
||||
{
|
||||
setEnvironment(QStringList() << QStringLiteral("LC_ALL=C") << QStringLiteral("PATH=") + QString::fromLocal8Bit(getenv("PATH")) << QStringLiteral("LVM_SUPPRESS_FD_WARNINGS=1"));
|
||||
setProcessChannelMode(processChannelMode);
|
||||
arguments.insert(QStringLiteral("environment"), QStringList() << QStringLiteral("LC_ALL=C") << QStringLiteral("LVM_SUPPRESS_FD_WARNINGS=1"));
|
||||
arguments.insert(QStringLiteral("processChannelMode"), processChannelMode);
|
||||
|
||||
connect(this, qOverload<int, QProcess::ExitStatus>(&QProcess::finished), this, &ExternalCommand::onFinished);
|
||||
connect(this, &ExternalCommand::readyReadStandardOutput, this, &ExternalCommand::onReadOutput);
|
||||
// connect(this, qOverload<int, QProcess::ExitStatus>(&QProcess::finished), this, &ExternalCommand::onFinished);
|
||||
// connect(this, &ExternalCommand::readyReadStandardOutput, this, &ExternalCommand::onReadOutput);
|
||||
}
|
||||
|
||||
/** Starts the external command.
|
||||
|
@ -72,19 +76,61 @@ void ExternalCommand::setup(const QProcess::ProcessChannelMode processChannelMod
|
|||
*/
|
||||
bool ExternalCommand::start(int timeout)
|
||||
{
|
||||
QProcess::start(command(), args());
|
||||
this->moveToThread(CoreBackendManager::self()->kauthThread());
|
||||
QTimer::singleShot(0, this, &ExternalCommand::execute);
|
||||
QEventLoop loop;
|
||||
connect(this, &ExternalCommand::finished, &loop, &QEventLoop::quit);
|
||||
loop.exec();
|
||||
return true;
|
||||
}
|
||||
|
||||
/** Executes the external command in kauthThread() thread.
|
||||
*/
|
||||
void ExternalCommand::execute()
|
||||
{
|
||||
if (report()) {
|
||||
report()->setCommand(xi18nc("@info:status", "Command: %1 %2", command(), args().join(QStringLiteral(" "))));
|
||||
}
|
||||
|
||||
if (!waitForStarted(timeout))
|
||||
{
|
||||
if (report())
|
||||
report()->line() << xi18nc("@info:status", "(Command timeout while starting)");
|
||||
return false;
|
||||
QString cmd = QStandardPaths::findExecutable(command());
|
||||
if (cmd.isEmpty())
|
||||
cmd = QStandardPaths::findExecutable(command(), { QStringLiteral("/sbin/"), QStringLiteral("/usr/sbin/"), QStringLiteral("/usr/local/sbin/") });
|
||||
|
||||
KAuth::Action action(QStringLiteral("org.kde.kpmcore.externalcommand.start"));
|
||||
action.setHelperId(QStringLiteral("org.kde.kpmcore.externalcommand"));
|
||||
arguments.insert(QStringLiteral("command"), cmd);
|
||||
arguments.insert(QStringLiteral("input"), m_Input);
|
||||
arguments.insert(QStringLiteral("arguments"), args());
|
||||
action.setArguments(arguments);
|
||||
|
||||
KAuth::ExecuteJob *job = action.execute();
|
||||
if (!job->exec()) {
|
||||
qWarning() << "KAuth returned an error code: " << job->errorString();
|
||||
// return false;
|
||||
emit finished();
|
||||
return;
|
||||
}
|
||||
|
||||
m_Output = job->data()[QStringLiteral("output")].toByteArray();
|
||||
setExitCode(job->data()[QStringLiteral("exitCode")].toInt());
|
||||
|
||||
// QProcess::start(command(), args());
|
||||
|
||||
// FIXME
|
||||
// if (!waitForStarted(timeout))
|
||||
// {
|
||||
// if (report())
|
||||
// report()->line() << xi18nc("@info:status", "(Command timeout while starting)");
|
||||
// return false;
|
||||
// }
|
||||
|
||||
// return true;
|
||||
emit finished();
|
||||
}
|
||||
|
||||
bool ExternalCommand::write(const QByteArray& input)
|
||||
{
|
||||
m_Input = input;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -94,15 +140,15 @@ bool ExternalCommand::start(int timeout)
|
|||
*/
|
||||
bool ExternalCommand::waitFor(int timeout)
|
||||
{
|
||||
closeWriteChannel();
|
||||
|
||||
// closeWriteChannel();
|
||||
/*
|
||||
if (!waitForFinished(timeout)) {
|
||||
if (report())
|
||||
report()->line() << xi18nc("@info:status", "(Command timeout while running)");
|
||||
return false;
|
||||
}
|
||||
}*/
|
||||
|
||||
onReadOutput();
|
||||
// onReadOutput();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -112,23 +158,23 @@ bool ExternalCommand::waitFor(int timeout)
|
|||
*/
|
||||
bool ExternalCommand::run(int timeout)
|
||||
{
|
||||
return start(timeout) && waitFor(timeout) && exitStatus() == 0;
|
||||
return start(timeout) && waitFor(timeout)/* && exitStatus() == 0*/;
|
||||
}
|
||||
|
||||
void ExternalCommand::onReadOutput()
|
||||
{
|
||||
const QByteArray s = readAllStandardOutput();
|
||||
|
||||
if(m_Output.length() > 10*1024*1024) { // prevent memory overflow for badly corrupted file systems
|
||||
if (report())
|
||||
report()->line() << xi18nc("@info:status", "(Command is printing too much output)");
|
||||
return;
|
||||
}
|
||||
|
||||
m_Output += s;
|
||||
|
||||
if (report())
|
||||
*report() << QString::fromLocal8Bit(s);
|
||||
// const QByteArray s = readAllStandardOutput();
|
||||
//
|
||||
// if(m_Output.length() > 10*1024*1024) { // prevent memory overflow for badly corrupted file systems
|
||||
// if (report())
|
||||
// report()->line() << xi18nc("@info:status", "(Command is printing too much output)");
|
||||
// return;
|
||||
// }
|
||||
//
|
||||
// m_Output += s;
|
||||
//
|
||||
// if (report())
|
||||
// *report() << QString::fromLocal8Bit(s);
|
||||
}
|
||||
|
||||
void ExternalCommand::onFinished(int exitCode, QProcess::ExitStatus exitStatus)
|
||||
|
|
|
@ -21,10 +21,12 @@
|
|||
|
||||
#include "util/libpartitionmanagerexport.h"
|
||||
|
||||
#include <QDebug>
|
||||
#include <QtGlobal>
|
||||
#include <QProcess>
|
||||
#include <QStringList>
|
||||
#include <QString>
|
||||
#include <QtGlobal>
|
||||
#include <QVariant>
|
||||
|
||||
class Report;
|
||||
|
||||
|
@ -35,13 +37,14 @@ class Report;
|
|||
@author Volker Lanz <vl@fidra.de>
|
||||
@author Andrius Štikonas <andrius@stikonas.eu>
|
||||
*/
|
||||
class LIBKPMCORE_EXPORT ExternalCommand : public QProcess
|
||||
class LIBKPMCORE_EXPORT ExternalCommand : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_DISABLE_COPY(ExternalCommand)
|
||||
|
||||
public:
|
||||
explicit ExternalCommand(const QString& cmd = QString(), const QStringList& args = QStringList(), const QProcess::ProcessChannelMode processChannelMode = MergedChannels);
|
||||
explicit ExternalCommand(Report& report, const QString& cmd = QString(), const QStringList& args = QStringList(), const QProcess::ProcessChannelMode processChannelMode = MergedChannels);
|
||||
explicit ExternalCommand(const QString& cmd = QString(), const QStringList& args = QStringList(), const QProcess::ProcessChannelMode processChannelMode = QProcess::MergedChannels);
|
||||
explicit ExternalCommand(Report& report, const QString& cmd = QString(), const QStringList& args = QStringList(), const QProcess::ProcessChannelMode processChannelMode = QProcess::MergedChannels);
|
||||
|
||||
public:
|
||||
void setCommand(const QString& cmd) { m_Command = cmd; } /**< @param cmd the command to run */
|
||||
|
@ -50,6 +53,7 @@ public:
|
|||
void addArg(const QString& s) { m_Args << s; } /**< @param s the argument to add */
|
||||
const QStringList& args() const { return m_Args; } /**< @return the arguments */
|
||||
void setArgs(const QStringList& args) { m_Args = args; } /**< @param args the new arguments */
|
||||
bool write(const QByteArray& input); /**< @param input the input for the program */
|
||||
|
||||
bool start(int timeout = 30000);
|
||||
bool waitFor(int timeout = 30000);
|
||||
|
@ -71,7 +75,12 @@ public:
|
|||
return m_Report; /**< @return pointer to the Report or nullptr */
|
||||
}
|
||||
|
||||
Q_SIGNALS:
|
||||
void finished();
|
||||
|
||||
protected:
|
||||
void execute();
|
||||
|
||||
void setExitCode(int i) {
|
||||
m_ExitCode = i;
|
||||
}
|
||||
|
@ -81,11 +90,14 @@ protected:
|
|||
void onReadOutput();
|
||||
|
||||
private:
|
||||
QVariantMap arguments;
|
||||
|
||||
Report *m_Report;
|
||||
QString m_Command;
|
||||
QStringList m_Args;
|
||||
int m_ExitCode;
|
||||
QByteArray m_Output;
|
||||
QByteArray m_Input;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -0,0 +1,59 @@
|
|||
/*************************************************************************
|
||||
* Copyright (C) 2017 by Andrius Štikonas <andrius@stikonas.eu> *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU General Public License as *
|
||||
* published by the Free Software Foundation; either version 3 of *
|
||||
* the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This program is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License *
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.*
|
||||
*************************************************************************/
|
||||
|
||||
#include "externalcommandhelper.h"
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
ActionReply ExternalCommandHelper::start(const QVariantMap& args)
|
||||
{
|
||||
ActionReply reply;
|
||||
QString command = args[QStringLiteral("command")].toString();
|
||||
QStringList arguments = args[QStringLiteral("arguments")].toStringList();
|
||||
QStringList environment = args[QStringLiteral("environment")].toStringList();
|
||||
QByteArray input = args[QStringLiteral("input")].toByteArray();
|
||||
|
||||
// connect(&cmd, &QProcess::readyReadStandardOutput, this, &ExternalCommandHelper::onReadOutput);
|
||||
|
||||
cmd.setEnvironment(environment);
|
||||
cmd.start(command, arguments);
|
||||
cmd.write(input);
|
||||
cmd.waitForFinished(-1);
|
||||
QByteArray output = cmd.readAllStandardOutput();
|
||||
reply.addData(QStringLiteral("output"), output);
|
||||
reply.addData(QStringLiteral("exitCode"), cmd.exitCode());
|
||||
|
||||
return reply;
|
||||
}
|
||||
|
||||
void ExternalCommandHelper::onReadOutput()
|
||||
{
|
||||
// const QByteArray s = cmd.readAllStandardOutput();
|
||||
|
||||
// if(output.length() > 10*1024*1024) { // prevent memory overflow for badly corrupted file systems
|
||||
// if (report())
|
||||
// report()->line() << xi18nc("@info:status", "(Command is printing too much output)");
|
||||
// return;
|
||||
// }
|
||||
|
||||
// output += s;
|
||||
|
||||
// if (report())
|
||||
// *report() << QString::fromLocal8Bit(s);
|
||||
}
|
||||
|
||||
KAUTH_HELPER_MAIN("org.kde.kpmcore.externalcommand", ExternalCommandHelper)
|
|
@ -0,0 +1,42 @@
|
|||
/*************************************************************************
|
||||
* Copyright (C) 2017 by Andrius Štikonas <andrius@stikonas.eu> *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU General Public License as *
|
||||
* published by the Free Software Foundation; either version 3 of *
|
||||
* the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This program is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License *
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.*
|
||||
*************************************************************************/
|
||||
|
||||
#ifndef KPMCORE_EXTERNALCOMMANDHELPER_H
|
||||
|
||||
#define KPMCORE_EXTERNALCOMMANDHELPER_H
|
||||
|
||||
#include <KAuth>
|
||||
|
||||
#include <QProcess>
|
||||
|
||||
using namespace KAuth;
|
||||
|
||||
class ExternalCommandHelper : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public Q_SLOTS:
|
||||
ActionReply start(const QVariantMap& args);
|
||||
|
||||
private:
|
||||
void onReadOutput();
|
||||
|
||||
QProcess cmd;
|
||||
// QByteArray output;
|
||||
};
|
||||
|
||||
#endif
|
|
@ -0,0 +1,5 @@
|
|||
[org.kde.kpmcore.externalcommand.start]
|
||||
Name=Run external command action
|
||||
Description=Run external command as privileged user
|
||||
Policy=auth_admin
|
||||
Persistence=session
|
|
@ -45,3 +45,10 @@ add_test(NAME testlist COMMAND testlist ${BACKEND})
|
|||
|
||||
kpm_test(testdevicescanner testdevicescanner.cpp)
|
||||
add_test(NAME testdevicescanner COMMAND testdevicescanner ${BACKEND})
|
||||
|
||||
find_package (Threads)
|
||||
###
|
||||
#
|
||||
# Execute external commands as root
|
||||
kpm_test(testexternalcommand testexternalcommand.cpp)
|
||||
add_test(NAME testexternalcommand COMMAND testexternalcommand ${BACKEND})
|
||||
|
|
|
@ -0,0 +1,66 @@
|
|||
/*************************************************************************
|
||||
* Copyright 2017 by Andrius Štikonas <andrius@stikonas.eu> *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU General Public License as *
|
||||
* published by the Free Software Foundation; either version 3 of *
|
||||
* the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This program is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License *
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.*
|
||||
*************************************************************************/
|
||||
|
||||
// SPDX-License-Identifier: GPL-3.0+
|
||||
|
||||
|
||||
#include "helpers.h"
|
||||
#include "backend/corebackendmanager.h"
|
||||
#include "util/externalcommand.h"
|
||||
|
||||
#include <QApplication>
|
||||
#include <QDebug>
|
||||
#include <QThread>
|
||||
|
||||
class runcmd : public QThread {
|
||||
public:
|
||||
|
||||
void run()
|
||||
{
|
||||
ExternalCommand blkidCmd(QStringLiteral("blkid"), {});
|
||||
blkidCmd.run();
|
||||
qDebug().noquote() << blkidCmd.output();
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
class runcmd2 : public QThread {
|
||||
public:
|
||||
|
||||
void run()
|
||||
{
|
||||
ExternalCommand lsblkCmd(QStringLiteral("lsblk"), { QStringLiteral("--nodeps"), QStringLiteral("--json") });
|
||||
lsblkCmd.run();
|
||||
qDebug().noquote() << lsblkCmd.output();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
int main( int argc, char **argv )
|
||||
{
|
||||
QApplication app(argc, argv);
|
||||
KPMCoreInitializer i(QStringLiteral("pmsfdiskbackendplugin"));
|
||||
|
||||
runcmd a;
|
||||
runcmd2 b;
|
||||
a.start();
|
||||
a.wait();
|
||||
b.start();
|
||||
b.wait();
|
||||
|
||||
return 0;
|
||||
}
|
Loading…
Reference in New Issue