parent
06b152504d
commit
6f34f5cdc2
@ -0,0 +1,122 @@
|
|||||||
|
Description: Enable bidirectional communication
|
||||||
|
lxqt-sudo shows you what an executed process prints to stdout/stderr, but it
|
||||||
|
doesn't send anything written to lxqt-sudo's stdin to the child process. This
|
||||||
|
patch fixes that and adds some small miscellaneous improvements.
|
||||||
|
Origin: https://github.com/ArrayBolt3/lxqt-sudo/compare/d69855c2900d10c2aae4d39678b71aadf37dc37c...4f430cb0fe240566e74ade15e1657b1f99177c12
|
||||||
|
Forwarded: https://github.com/lxqt/lxqt-sudo/pull/210
|
||||||
|
Last-Update: 2024-01-11
|
||||||
|
---
|
||||||
|
This patch header follows DEP-3: http://dep.debian.net/deps/dep3/
|
||||||
|
diff --git a/sudo.cpp b/sudo.cpp
|
||||||
|
index d12f77c..eebcf5c 100644
|
||||||
|
--- a/sudo.cpp
|
||||||
|
+++ b/sudo.cpp
|
||||||
|
@@ -68,6 +68,7 @@ namespace
|
||||||
|
const QString doas_prog{QStringLiteral(LXQTSUDO_DOAS)};
|
||||||
|
const QString pwd_prompt_end{QStringLiteral(": ")};
|
||||||
|
const QChar nl{QLatin1Char('\n')};
|
||||||
|
+ constexpr int term_eol_size = 2;
|
||||||
|
|
||||||
|
void usage(QString const & err = QString())
|
||||||
|
{
|
||||||
|
@@ -374,12 +375,14 @@ int Sudo::parent()
|
||||||
|
}
|
||||||
|
|
||||||
|
QTextStream child_str{pwd_f};
|
||||||
|
+ // pseudoterminal echoes everything written into it's input; we don't want duplicating input
|
||||||
|
+ int inhibit_count = 0;
|
||||||
|
|
||||||
|
QObject::connect(mDlg.data(), &QDialog::finished, [&] (int result)
|
||||||
|
{
|
||||||
|
if (QDialog::Accepted == result)
|
||||||
|
{
|
||||||
|
- child_str << mDlg->password().append(nl);
|
||||||
|
+ child_str << mDlg->password() << nl;
|
||||||
|
child_str.flush();
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
@@ -388,6 +391,8 @@ int Sudo::parent()
|
||||||
|
});
|
||||||
|
|
||||||
|
QString last_line;
|
||||||
|
+ QString const & error_check = QStringLiteral("%1:").arg(backendName());
|
||||||
|
+ QTextStream stderr_str{stderr, QIODevice::WriteOnly};
|
||||||
|
QScopedPointer<QSocketNotifier> pwd_watcher{new QSocketNotifier{mPwdFd, QSocketNotifier::Read}};
|
||||||
|
auto reader = [&]
|
||||||
|
{
|
||||||
|
@@ -396,11 +401,10 @@ int Sudo::parent()
|
||||||
|
{
|
||||||
|
pwd_watcher.reset(nullptr); //stop the notifications events
|
||||||
|
|
||||||
|
- QString const & prog = backendName();
|
||||||
|
- if (last_line.startsWith(QStringLiteral("%1:").arg(prog)))
|
||||||
|
+ if (last_line.startsWith(error_check))
|
||||||
|
{
|
||||||
|
QMessageBox(QMessageBox::Critical, mDlg->windowTitle()
|
||||||
|
- , tr("Child '%1' process failed!\n%2").arg(prog).arg(last_line), QMessageBox::Ok).exec();
|
||||||
|
+ , tr("Child '%1' process failed!\n%2").arg(backendName()).arg(last_line), QMessageBox::Ok).exec();
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
@@ -414,18 +418,56 @@ int Sudo::parent()
|
||||||
|
if (!(ECHO & tios.c_lflag))
|
||||||
|
{
|
||||||
|
mDlg->show();
|
||||||
|
- return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
- QTextStream{stderr, QIODevice::WriteOnly} << line;
|
||||||
|
- //assuming text oriented output
|
||||||
|
- QStringList lines = line.split(nl, Qt::SkipEmptyParts);
|
||||||
|
- last_line = lines.isEmpty() ? QString() : lines.back();
|
||||||
|
+ if (inhibit_count > 0)
|
||||||
|
+ {
|
||||||
|
+ if (inhibit_count < line.count())
|
||||||
|
+ {
|
||||||
|
+ stderr_str << line.right(line.count() - inhibit_count);
|
||||||
|
+ stderr_str.flush();
|
||||||
|
+ inhibit_count = 0;
|
||||||
|
+ } else
|
||||||
|
+ {
|
||||||
|
+ inhibit_count -= line.count();
|
||||||
|
+ }
|
||||||
|
+ } else
|
||||||
|
+ {
|
||||||
|
+ stderr_str << line;
|
||||||
|
+ stderr_str.flush();
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ //assuming text oriented output; find the last non-empty line
|
||||||
|
+ auto i = line.crbegin(), i_end = line.crbegin(), i_crend = line.crend();
|
||||||
|
+ do {
|
||||||
|
+ i_end = i + 1;
|
||||||
|
+ i = std::find(i_end, i_crend, nl);
|
||||||
|
+ } while (i != i_crend && std::distance(i, i_end) == 0);
|
||||||
|
+
|
||||||
|
+ last_line.clear();
|
||||||
|
+ last_line.reserve(std::distance(i, i_end));
|
||||||
|
+ std::for_each(i.base(), i_end.base(), [&last_line](decltype (*i.base()) val) { last_line.append(val); });
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
+ QTextStream stdin_str{stdin, QIODevice::ReadOnly};
|
||||||
|
+ QScopedPointer<QSocketNotifier> stdin_watcher{new QSocketNotifier{STDIN_FILENO, QSocketNotifier::Read}};
|
||||||
|
+ auto writer = [&]
|
||||||
|
+ {
|
||||||
|
+ QString line = stdin_str.readLine();
|
||||||
|
+ if (line.isEmpty()) {
|
||||||
|
+ stdin_watcher.reset(nullptr); //stop the notification events
|
||||||
|
+ } else
|
||||||
|
+ {
|
||||||
|
+ inhibit_count += line.count() + term_eol_size;
|
||||||
|
+ child_str << line << nl;
|
||||||
|
+ child_str.flush();
|
||||||
|
+ }
|
||||||
|
+ };
|
||||||
|
+
|
||||||
|
QObject::connect(pwd_watcher.data(), &QSocketNotifier::activated, reader);
|
||||||
|
+ QObject::connect(stdin_watcher.data(), &QSocketNotifier::activated, writer);
|
||||||
|
|
||||||
|
std::unique_ptr<std::thread> child_waiter;
|
||||||
|
QTimer::singleShot(0, [&child_waiter, this] {
|
@ -1 +1,2 @@
|
|||||||
bypass-envvar-allowlist.patch
|
bypass-envvar-allowlist.patch
|
||||||
|
enable-bidirectional-communication.patch
|
||||||
|
Loading…
Reference in new issue