1// SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
2// SPDX-FileCopyrightText: 2022 Harald Sitter <sitter@kde.org>
3
4#include "ksandbox.h"
5
6#include <QDebug>
7#include <QFileInfo>
8
9#include <kcoreaddons_debug.h>
10
11bool KSandbox::isInside()
12{
13 static const bool isInside = isFlatpak() || isSnap();
14 return isInside;
15}
16
17bool KSandbox::isFlatpak()
18{
19 static const bool isFlatpak = QFileInfo::exists(QStringLiteral("/.flatpak-info"));
20 return isFlatpak;
21}
22
23bool KSandbox::isSnap()
24{
25 static const bool isSnap = qEnvironmentVariableIsSet(varName: "SNAP");
26 return isSnap;
27}
28
29bool checkHasFlatpakSpawnPrivileges()
30{
31 QFile f(QStringLiteral("/.flatpak-info"));
32 if (!f.open(flags: QIODevice::ReadOnly)) {
33 return false;
34 }
35
36 return f.readAll().contains(bv: "\norg.freedesktop.Flatpak=talk\n");
37}
38
39KSandbox::ProcessContext KSandbox::makeHostContext(const QProcess &process)
40{
41 if (!KSandbox::isFlatpak()) {
42 return {.program: process.program(), .arguments: process.arguments()};
43 }
44
45 static const bool hasFlatpakSpawnPrivileges = checkHasFlatpakSpawnPrivileges();
46 if (!hasFlatpakSpawnPrivileges) {
47 qCWarning(KCOREADDONS_DEBUG) << "Process execution expects 'org.freedesktop.Flatpak=talk'" << process.program();
48 return {.program: process.program(), .arguments: process.arguments()};
49 }
50
51 QStringList args{QStringLiteral("--watch-bus"), QStringLiteral("--host"), QStringLiteral("--forward-fd=1"), QStringLiteral("--forward-fd=2")};
52 if (!process.workingDirectory().isEmpty()) {
53 args << QStringLiteral("--directory=%1").arg(a: process.workingDirectory());
54 }
55 const auto systemEnvironment = QProcessEnvironment::systemEnvironment().toStringList();
56 const auto processEnvironment = process.processEnvironment().toStringList();
57 for (const auto &variable : processEnvironment) {
58 if (systemEnvironment.contains(str: variable)) {
59 continue;
60 }
61 args << QStringLiteral("--env=%1").arg(a: variable);
62 }
63 if (!process.program().isEmpty()) { // some callers are cheeky and pass no program but put it into the arguments (e.g. konsole)
64 args << process.program();
65 }
66 args += process.arguments();
67 return {QStringLiteral("/usr/bin/flatpak-spawn"), .arguments: args};
68}
69
70KCOREADDONS_EXPORT void KSandbox::startHostProcess(QProcess &process, QProcess::OpenMode mode)
71{
72 const auto context = makeHostContext(process);
73 process.start(program: context.program, arguments: context.arguments, mode);
74}
75

source code of kcoreaddons/src/lib/util/ksandbox.cpp