aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorsaturneric <[email protected]>2025-04-18 21:45:10 +0000
committersaturneric <[email protected]>2025-04-18 21:45:10 +0000
commita6bfc4103e3cda98b4c8ebaf279d37a8f71c2d60 (patch)
tree93ce7d77c9e61123d102d44f5d55b0d89f4a67d4
parentfix: init database path and name as soon as possible (diff)
downloadGpgFrontend-a6bfc4103e3cda98b4c8ebaf279d37a8f71c2d60.tar.gz
GpgFrontend-a6bfc4103e3cda98b4c8ebaf279d37a8f71c2d60.zip
fix: gpg agent cannot run as daemon on windows
-rw-r--r--src/core/function/gpg/GpgContext.cpp133
-rw-r--r--src/init.cpp2
2 files changed, 82 insertions, 53 deletions
diff --git a/src/core/function/gpg/GpgContext.cpp b/src/core/function/gpg/GpgContext.cpp
index 5138f71a..1960960f 100644
--- a/src/core/function/gpg/GpgContext.cpp
+++ b/src/core/function/gpg/GpgContext.cpp
@@ -48,6 +48,80 @@
namespace GpgFrontend {
+class GpgAgentProcess {
+ public:
+ explicit GpgAgentProcess(int channel, QString gpg_agent_path, QString db_path)
+ : channel_(channel),
+ db_path_(std::move(db_path)),
+ gpg_agent_path_(std::move(gpg_agent_path)) {}
+
+ auto Start() -> bool {
+ assert(!gpg_agent_path_.isEmpty());
+ assert(!db_path_.isEmpty());
+
+ if (gpg_agent_path_.trimmed().isEmpty()) {
+ LOG_E() << "gpg-agent path is empty!";
+ return false;
+ }
+
+ LOG_D() << "get gpg-agent path: " << gpg_agent_path_;
+ QFileInfo info(gpg_agent_path_);
+ if (!info.exists() || !info.isFile()) {
+ LOG_E() << "gpg-agent is not exists or is not a binary file!";
+ return false;
+ }
+
+ auto args = QStringList{};
+
+ if (!db_path_.isEmpty()) {
+ args.append({"--homedir", QDir::toNativeSeparators(db_path_)});
+ }
+
+ args.append({"--daemon", "--enable-ssh-support"});
+
+ auto pinentry = DecidePinentry();
+ if (!pinentry.trimmed().isEmpty()) {
+ args.append({"--pinentry-program", pinentry});
+ }
+
+ if (channel_ != kGpgFrontendDefaultChannel) {
+ args.append("--disable-scdaemon");
+ }
+
+ LOG_E() << "gpg-agent start args: " << args << "channel:" << channel_;
+
+ process_.setProgram(info.absoluteFilePath());
+ process_.setArguments(args);
+ process_.setProcessChannelMode(QProcess::MergedChannels);
+ process_.start();
+
+ if (!process_.waitForStarted()) {
+ LOG_W() << "timeout starting gpg-agent: " << gpg_agent_path_
+ << "ags: " << args;
+ return false;
+ }
+
+ return true;
+ }
+
+ ~GpgAgentProcess() {
+ if (process_.state() != QProcess::NotRunning) {
+ qInfo() << "killing gpg-agent, channel: " << channel_;
+ process_.terminate();
+ if (!process_.waitForFinished(5000)) {
+ process_.kill();
+ process_.waitForFinished();
+ }
+ }
+ }
+
+ private:
+ int channel_;
+ QProcess process_;
+ QString db_path_;
+ QString gpg_agent_path_;
+};
+
class GpgContext::Impl {
public:
/**
@@ -62,7 +136,11 @@ class GpgContext::Impl {
db_name_(args.db_name),
gpgconf_path_(Module::RetrieveRTValueTypedOrDefault<>(
"core", "gpgme.ctx.gpgconf_path", QString{})),
- database_path_(args.db_path) {
+ database_path_(args.db_path),
+ agent_(parent->GetChannel(),
+ Module::RetrieveRTValueTypedOrDefault<>(
+ "core", "gnupg.components.gpg-agent.path", QString{}),
+ args.db_path) {
init(args);
}
@@ -209,6 +287,7 @@ class GpgContext::Impl {
QString gpgconf_path_;
QString database_path_;
QMap<QString, QString> component_dirs_;
+ GpgAgentProcess agent_;
void init(const GpgContextInitArgs &args) {
assert(!gpgconf_path_.isEmpty());
@@ -472,57 +551,7 @@ class GpgContext::Impl {
}
auto launch_gpg_agent() -> bool {
- const auto gpg_agent = Module::RetrieveRTValueTypedOrDefault<>(
- "core", "gnupg.components.gpg-agent.path", QString{});
-
- if (gpg_agent.trimmed().isEmpty()) {
- LOG_E() << "gpg-agent path is empty!";
- return false;
- }
-
- LOG_D() << "get gpg-agent path: " << gpg_agent;
- QFileInfo info(gpg_agent);
- if (!info.exists() || !info.isFile()) {
- LOG_E() << "gpg-agent is not exists or is not a binary file!";
- return false;
- }
-
- auto args = QStringList{};
-
- if (!HomeDirectory().isEmpty()) {
- args.append({"--homedir", QDir::toNativeSeparators(HomeDirectory())});
- }
-
- args.append({"--daemon", "--enable-ssh-support"});
-
- auto pinentry = DecidePinentry();
- if (!pinentry.trimmed().isEmpty()) {
- args.append({"--pinentry-program", pinentry});
- }
-
- if (parent_->GetChannel() != kGpgFrontendDefaultChannel) {
- args.append("--disable-scdaemon");
- }
-
- LOG_E() << "gpg-agent start args: " << args
- << "channel:" << parent_->GetChannel();
-
- QProcess process;
- process.setProgram(info.absoluteFilePath());
- process.setArguments(args);
- process.setProcessChannelMode(QProcess::MergedChannels);
-
- process.start();
- if (!process.waitForFinished(3000)) {
- LOG_W() << "timeout starting gpg-agent daemon: " << gpg_agent
- << "ags: " << args;
- return false;
- }
-
- QString output = process.readAll();
- LOG_D() << "gpg-agent daemon start output:" << output
- << "exit code: " << process.exitCode();
-
+ agent_.Start();
return true;
}
};
diff --git a/src/init.cpp b/src/init.cpp
index f0481152..ee19553a 100644
--- a/src/init.cpp
+++ b/src/init.cpp
@@ -187,7 +187,7 @@ void ShutdownGlobalBasicEnv(const GFCxtWPtr &p_ctx) {
for (const auto &channel : GpgContext::GetAllChannelId()) {
assert(GpgAdvancedOperator::GetInstance(channel).KillAllGpgComponents());
}
- } else if (!ctx->unit_test_mode && clear_gpg_password_cache) {
+ } else if (clear_gpg_password_cache) {
for (const auto &channel : GpgContext::GetAllChannelId()) {
assert(GpgAdvancedOperator::GetInstance(channel).ClearGpgPasswordCache());
}