feat: add env option and refactor command generate method

Signed-off-by: ComixHe <heyuming@deepin.org>
This commit is contained in:
ComixHe 2023-08-30 18:36:52 +08:00 committed by Comix
parent 8ab6adc290
commit 1fb4539792
6 changed files with 191 additions and 27 deletions

View File

@ -80,7 +80,14 @@
Extra options can be passed in `options` argument: Extra options can be passed in `options` argument:
1. `uid` (type u): 1. `uid` (type u):
The user id as who is that application will be run. The user id as who is that application will be run.
This option might request a polikit authentication." This option might request a polikit authentication.
2. `env` (type s):
passing some specific environment variables to Launch
this application, eg. 'LANG=en_US;PATH=xxx:yyy;'
NOTE:
when application try to be launched by other user identity,
all environment variables will be ignored.
/> />
</method> </method>
</interface> </interface>

View File

@ -42,4 +42,8 @@ constexpr auto ApplicationManagerInterface = "org.desktopspec.ApplicationManager
constexpr auto InstanceInterface = "org.desktopspec.ApplicationManager1.Instance"; constexpr auto InstanceInterface = "org.desktopspec.ApplicationManager1.Instance";
constexpr auto ApplicationInterface = "org.desktopspec.ApplicationManager1.Application"; constexpr auto ApplicationInterface = "org.desktopspec.ApplicationManager1.Application";
constexpr auto systemdOption = u8"systemd";
constexpr auto splitOption = u8"split";
constexpr auto AppExecOption = u8"appExec";
#endif #endif

View File

@ -6,7 +6,7 @@
#include "APPobjectmanager1adaptor.h" #include "APPobjectmanager1adaptor.h"
#include "applicationmanager1service.h" #include "applicationmanager1service.h"
#include "dbus/instanceadaptor.h" #include "dbus/instanceadaptor.h"
#include "pwd.h" #include "launchoptions.h"
#include <QUuid> #include <QUuid>
#include <QStringList> #include <QStringList>
#include <QList> #include <QList>
@ -125,27 +125,13 @@ QDBusObjectPath ApplicationService::Launch(const QString &action, const QStringL
} }
} }
auto [bin, cmds, res] = unescapeExec(execStr, fields); auto cmds = generateCommand(options);
uid_t uid; auto [bin, execCmds, res] = unescapeExec(execStr, fields);
auto it = options.find("uid");
if (it != options.cend()) {
uid = it->toUInt(&ok);
if (!ok) {
qWarning() << "convert uid string to uint failed: " << *it;
return {};
}
if (uid != getCurrentUID()) { cmds.append(std::move(execCmds));
cmds.prepend(userNameLookup(uid));
cmds.prepend("--user");
cmds.prepend("pkexec");
}
} else {
uid = getCurrentUID();
}
cmds.prepend("--"); qDebug() << "run application with:" << cmds;
auto &jobManager = static_cast<ApplicationManager1Service *>(parent())->jobManager(); auto &jobManager = static_cast<ApplicationManager1Service *>(parent())->jobManager();
@ -348,12 +334,6 @@ void ApplicationService::resetEntry(DesktopEntry *newEntry) noexcept
m_entry.reset(newEntry); m_entry.reset(newEntry);
} }
QString ApplicationService::userNameLookup(uid_t uid)
{
auto *pws = getpwuid(uid);
return pws->pw_name;
}
LaunchTask ApplicationService::unescapeExec(const QString &str, const QStringList &fields) LaunchTask ApplicationService::unescapeExec(const QString &str, const QStringList &fields)
{ {
LaunchTask task; LaunchTask task;

View File

@ -97,7 +97,6 @@ private:
DesktopFile m_desktopSource; DesktopFile m_desktopSource;
QSharedPointer<DesktopEntry> m_entry{nullptr}; QSharedPointer<DesktopEntry> m_entry{nullptr};
QMap<QDBusObjectPath, QSharedPointer<InstanceService>> m_Instances; QMap<QDBusObjectPath, QSharedPointer<InstanceService>> m_Instances;
static QString userNameLookup(uid_t uid);
[[nodiscard]] LaunchTask unescapeExec(const QString &str, const QStringList &fields); [[nodiscard]] LaunchTask unescapeExec(const QString &str, const QStringList &fields);
[[nodiscard]] QVariant findEntryValue(const QString &group, [[nodiscard]] QVariant findEntryValue(const QString &group,
const QString &valueKey, const QString &valueKey,

101
src/launchoptions.cpp Normal file
View File

@ -0,0 +1,101 @@
// SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd.
//
// SPDX-License-Identifier: LGPL-3.0-or-later
#include <pwd.h>
#include <vector>
#include <cstring>
#include "global.h"
#include "launchoptions.h"
QStringList generateCommand(const QVariantMap &props) noexcept
{
std::vector<std::unique_ptr<LaunchOption>> options;
for (const auto &[key, value] : props.asKeyValueRange()) {
if (key == setUserLaunchOption::key()) {
options.push_back(std::make_unique<setUserLaunchOption>(value));
} else if (key == setEnvLaunchOption::key()) {
options.push_back(std::make_unique<setEnvLaunchOption>(value));
} else {
qWarning() << "unsupported options" << key;
}
}
options.push_back(std::make_unique<splitLaunchOption>());
std::sort(options.begin(),
options.end(),
[](const std::unique_ptr<LaunchOption> &lOption, const std::unique_ptr<LaunchOption> &rOption) {
if (lOption->type() == AppExecOption and rOption->type() == systemdOption) {
return false;
}
if (lOption->type() == AppExecOption and rOption->type() == splitOption) {
return false;
}
if (lOption->type() == splitOption and rOption->type() == systemdOption) {
return false;
}
return true;
});
QStringList ret;
std::for_each(options.begin(), options.end(), [&ret](const std::unique_ptr<LaunchOption> &option) {
auto str = option->generateCommandLine();
if (!str.isEmpty()) {
ret.append(std::move(str));
}
});
return ret;
}
QStringList setUserLaunchOption::generateCommandLine() const noexcept
{
QStringList ret;
bool ok{false};
auto uid = m_val.toUInt(&ok);
if (!ok) {
return ret;
}
auto curUID = getCurrentUID();
if (uid == curUID) {
return ret;
}
ret.append("pkexec");
ret.append("--user");
struct passwd *destUser = getpwuid(uid);
QString userName = destUser->pw_name;
ret.append(userName);
struct passwd *curUser = getpwuid(curUID);
ret.append("env");
ret.append("DISPLAY=:0");
auto authFile = qgetenv("XAUTHORITY");
ret.append(QString{"XAUTHORITY=%1"}.arg(authFile));
return ret;
}
QStringList splitLaunchOption::generateCommandLine() const noexcept
{
return QStringList{m_val.toString()};
}
QStringList setEnvLaunchOption::generateCommandLine() const noexcept
{
auto str = m_val.toString();
if (str.isEmpty()) {
return {};
}
return QStringList{QString{"--Environment=%1"}.arg(str)};
}

73
src/launchoptions.h Normal file
View File

@ -0,0 +1,73 @@
// SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd.
//
// SPDX-License-Identifier: LGPL-3.0-or-later
#include <QVariantMap>
#include "constant.h"
struct LaunchOption
{
explicit LaunchOption(QVariant v)
: m_val(std::move(v))
{
}
virtual ~LaunchOption() = default;
[[nodiscard]] virtual QStringList generateCommandLine() const noexcept = 0;
[[nodiscard]] static const QString &key() noexcept
{
static QString none;
return none;
};
[[nodiscard]] virtual const QString &type() const noexcept = 0;
QVariant m_val;
};
struct setUserLaunchOption : public LaunchOption
{
using LaunchOption::LaunchOption;
[[nodiscard]] const QString &type() const noexcept override
{
static QString tp{AppExecOption};
return tp;
}
[[nodiscard]] static const QString &key() noexcept
{
static QString uid{"uid"};
return uid;
}
[[nodiscard]] QStringList generateCommandLine() const noexcept override;
};
struct setEnvLaunchOption : public LaunchOption
{
using LaunchOption::LaunchOption;
[[nodiscard]] const QString &type() const noexcept override
{
static QString tp{systemdOption};
return tp;
}
[[nodiscard]] static const QString &key() noexcept
{
static QString env{"env"};
return env;
}
[[nodiscard]] QStringList generateCommandLine() const noexcept override;
};
struct splitLaunchOption : public LaunchOption
{
splitLaunchOption()
: LaunchOption(QString{"--"})
{
}
[[nodiscard]] const QString &type() const noexcept override
{
static QString tp{splitOption};
return tp;
}
[[nodiscard]] QStringList generateCommandLine() const noexcept override;
};
QStringList generateCommand(const QVariantMap &props) noexcept;