Skip to content

Commit 41f6344

Browse files
committed
migrate from pkexec to sudo in package_manager and settings_widget
1 parent 31389be commit 41f6344

File tree

3 files changed

+113
-88
lines changed

3 files changed

+113
-88
lines changed

src/core/package_manager.cpp

Lines changed: 37 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
#include "package_manager.h"
2+
#include "auth_manager.h"
23
#include "../utils/logger.h"
34
#include <QStandardPaths>
45
#include <QFile>
@@ -40,7 +41,7 @@ void PackageManager::detectHelper() {
4041
return;
4142
}
4243

43-
// Check for paru - deprecate because paru doesn't allow running with pkexec
44+
// Check for paru - deprecated because paru doesn't allow running as root
4445
// QString paruPath = QStandardPaths::findExecutable("paru");
4546
// if (!paruPath.isEmpty()) {
4647
// m_helper = Helper::Paru;
@@ -72,17 +73,14 @@ void PackageManager::installPackage(const QString& packageName, const QString& r
7273
bool isAUR = repoLower == "aur";
7374
QString helper = getHelperName();
7475

75-
QString command;
7676
if (isAUR && (m_helper == Helper::Yay)) {
77-
// AUR packages - use pkexec to get userpassword before hand
77+
// AUR packages need sudo for yay
7878
// Paru has a problem here, so default to yay
79-
command = QString("pkexec %1 -S %2 --noconfirm").arg(helper, packageName);
79+
executeCommand("sudo", QStringList() << "-S" << helper << "-S" << packageName << "--noconfirm", true);
8080
} else {
8181
// Official repos and chaotic-aur need root access and use pacman
82-
command = QString("pkexec pacman -S %1 --noconfirm").arg(packageName);
82+
executeCommand("sudo", QStringList() << "-S" << "pacman" << "-S" << packageName << "--noconfirm", true);
8383
}
84-
85-
executeCommand("sh", QStringList() << "-c" << command);
8684
}
8785

8886
void PackageManager::uninstallPackage(const QString& packageName, const QString& repository) {
@@ -92,9 +90,7 @@ void PackageManager::uninstallPackage(const QString& packageName, const QString&
9290
emit operationStarted(QString("Uninstalling %1...").arg(packageName));
9391

9492
// Uninstall always needs root (even for AUR packages, they're in the system db once installed)
95-
QString command = QString("pkexec pacman -Rdd %1 --noconfirm").arg(packageName);
96-
97-
executeCommand("sh", QStringList() << "-c" << command);
93+
executeCommand("sudo", QStringList() << "-S" << "pacman" << "-Rdd" << packageName << "--noconfirm", true);
9894
}
9995

10096
void PackageManager::updatePackage(const QString& packageName, const QString& repository) {
@@ -108,16 +104,13 @@ void PackageManager::updatePackage(const QString& packageName, const QString& re
108104
bool isAUR = repoLower == "aur";
109105
QString helper = getHelperName();
110106

111-
QString command;
112107
if (isAUR && (m_helper == Helper::Yay)) {
113-
// AUR packages - run helper as regular user (no pkexec)
114-
command = QString("%1 -S %2 --noconfirm").arg(helper, packageName);
108+
// AUR packages - run helper as regular user (no sudo)
109+
executeCommand(helper, QStringList() << "-S" << packageName << "--noconfirm");
115110
} else {
116111
// Official repos and chaotic-aur need root access and use pacman
117-
command = QString("pkexec pacman -S %1 --noconfirm").arg(packageName);
112+
executeCommand("sudo", QStringList() << "-S" << "pacman" << "-S" << packageName << "--noconfirm", true);
118113
}
119-
120-
executeCommand("sh", QStringList() << "-c" << command);
121114
}
122115

123116
void PackageManager::updateAllPackages() {
@@ -126,35 +119,38 @@ void PackageManager::updateAllPackages() {
126119
Logger::info("Updating all packages");
127120
emit operationStarted("Updating all packages...");
128121

129-
QString command = QString("pkexec %1 -Syu --noconfirm")
130-
.arg(getHelperName());
131-
132-
executeCommand("sh", QStringList() << "-c" << command);
122+
executeCommand("sudo", QStringList() << "-S" << getHelperName() << "-Syu" << "--noconfirm", true);
133123
}
134124

135-
void PackageManager::executeCommand(const QString& command, const QStringList& args) {
125+
void PackageManager::executeCommand(const QString& command, const QStringList& args, bool needsAuth) {
136126
if (m_process->state() != QProcess::NotRunning) {
137127
Logger::warning("Another operation is already running");
138128
emit operationError("Another operation is already in progress");
139129
return;
140130
}
141-
131+
142132
// Merge stdout and stderr so we capture all output
143133
m_process->setProcessChannelMode(QProcess::MergedChannels);
144-
134+
145135
Logger::debug(QString("Executing: %1 %2").arg(command, args.join(" ")));
146-
136+
147137
// Emit the actual command being executed to the UI for visibility
148138
QString fullCommand = command + " " + args.join(" ");
149139
emit operationOutput(QString(">> Executing: %1\n").arg(fullCommand));
150-
140+
151141
m_process->start(command, args);
152-
142+
153143
// Check if process started successfully
154144
if (!m_process->waitForStarted(3000)) {
155145
QString error = QString("Failed to start process: %1").arg(m_process->errorString());
156146
Logger::error(error);
157147
emit operationError(error);
148+
return;
149+
}
150+
151+
// Write stored password to sudo's stdin if this is an elevated operation
152+
if (needsAuth) {
153+
AuthManager::instance().writePasswordToProcess(m_process.get());
158154
}
159155
}
160156

@@ -191,29 +187,35 @@ void PackageManager::cancelRunningOperation() {
191187
if (m_process && m_process->state() != QProcess::NotRunning) {
192188
Logger::warning("Cancelling running operation...");
193189
emit operationOutput("\n>>> Operation cancelled by user <<<\n");
194-
195-
// When using pkexec, we need to kill the actual pacman/yay/paru process
196-
// not just the pkexec wrapper. Use pkill to terminate all package manager processes.
190+
191+
// When using sudo, we need to kill the actual pacman/yay/paru process
192+
// not just the sudo wrapper. Use pkill to terminate all package manager processes.
197193
QProcess killProcess;
198-
killProcess.start("pkexec", QStringList() << "bash" << "-c"
194+
killProcess.start("sudo", QStringList() << "-S" << "bash" << "-c"
199195
<< "pkill -TERM pacman; pkill -TERM yay; pkill -TERM paru");
196+
if (killProcess.waitForStarted(3000)) {
197+
AuthManager::instance().writePasswordToProcess(&killProcess);
198+
}
200199
killProcess.waitForFinished(2000);
201-
200+
202201
// Also terminate the QProcess wrapper
203202
m_process->terminate();
204-
203+
205204
// Wait up to 3 seconds for graceful termination
206205
if (!m_process->waitForFinished(3000)) {
207206
// Force kill if still running
208207
Logger::warning("Process did not terminate gracefully, forcing kill...");
209-
killProcess.start("pkexec", QStringList() << "bash" << "-c"
208+
killProcess.start("sudo", QStringList() << "-S" << "bash" << "-c"
210209
<< "pkill -KILL pacman; pkill -KILL yay; pkill -KILL paru");
210+
if (killProcess.waitForStarted(3000)) {
211+
AuthManager::instance().writePasswordToProcess(&killProcess);
212+
}
211213
killProcess.waitForFinished(2000);
212-
214+
213215
m_process->kill();
214216
m_process->waitForFinished(1000);
215217
}
216-
218+
217219
emit operationCompleted(false, "Operation cancelled by user");
218220
Logger::info("Operation cancelled successfully");
219221
} else {

src/core/package_manager.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ class PackageManager : public QObject {
5454
PackageManager();
5555

5656
void detectHelper();
57-
void executeCommand(const QString& command, const QStringList& args);
57+
void executeCommand(const QString& command, const QStringList& args, bool needsAuth = false);
5858

5959
Helper m_helper = Helper::Pacman;
6060
std::unique_ptr<QProcess> m_process;

0 commit comments

Comments
 (0)