summaryrefslogtreecommitdiff
path: root/Userland
diff options
context:
space:
mode:
authorPeter Elliott <pelliott@ualberta.ca>2021-10-10 16:04:14 -0600
committerAndreas Kling <kling@serenityos.org>2021-10-17 22:18:48 +0200
commit92b6e4fd767145d3bfc408fe036cdf63e09a9d89 (patch)
tree9092030b4bd19c143fdf0a29fd19fbb47c69dcde /Userland
parent7283b0b2141222af43419acb0c1c0c22804a70f4 (diff)
downloadserenity-92b6e4fd767145d3bfc408fe036cdf63e09a9d89.zip
TaskBar+Utilities: Add logout(1) command, and call it in ShutdownDialog
logout kills the session that SystemServer --user was started with.
Diffstat (limited to 'Userland')
-rw-r--r--Userland/Services/Taskbar/ShutdownDialog.cpp2
-rw-r--r--Userland/Utilities/logout.cpp62
2 files changed, 63 insertions, 1 deletions
diff --git a/Userland/Services/Taskbar/ShutdownDialog.cpp b/Userland/Services/Taskbar/ShutdownDialog.cpp
index 35aab6c854..7d6cb8b1b7 100644
--- a/Userland/Services/Taskbar/ShutdownDialog.cpp
+++ b/Userland/Services/Taskbar/ShutdownDialog.cpp
@@ -26,7 +26,7 @@ struct Option {
static const Vector<Option> options = {
{ "Power off computer", { "/bin/shutdown", "--now", nullptr }, true, true },
{ "Reboot", { "/bin/reboot", nullptr }, true, false },
- { "Log out", {}, false, false },
+ { "Log out", { "/bin/logout", nullptr }, true, false },
};
Vector<char const*> ShutdownDialog::show()
diff --git a/Userland/Utilities/logout.cpp b/Userland/Utilities/logout.cpp
new file mode 100644
index 0000000000..0aedb63953
--- /dev/null
+++ b/Userland/Utilities/logout.cpp
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2021, Peter Elliott <pelliott@serenityos.org>
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#include <LibCore/ProcessStatisticsReader.h>
+#include <signal.h>
+
+static Core::ProcessStatistics const& get_proc(Core::AllProcessesStatistics const& stats, pid_t pid)
+{
+ for (auto& proc : stats.processes) {
+ if (proc.pid == pid)
+ return proc;
+ }
+ VERIFY_NOT_REACHED();
+}
+
+int main(int, char**)
+{
+ if (pledge("stdio proc rpath", nullptr) < 0) {
+ perror("pledge");
+ return 1;
+ }
+
+ if (unveil("/proc/all", "r") < 0) {
+ perror("unveil");
+ return 1;
+ }
+
+ if (unveil("/etc/passwd", "r") < 0) {
+ perror("unveil");
+ return 1;
+ }
+
+ unveil(nullptr, nullptr);
+
+ // logout finds the highest session up all nested sessions, and kills it.
+ auto stats = Core::ProcessStatisticsReader::get_all();
+ if (!stats.has_value()) {
+ warnln("couldn't get process statistics");
+ return 1;
+ }
+
+ pid_t sid = getsid(0);
+ while (true) {
+ pid_t parent = get_proc(stats.value(), sid).ppid;
+ pid_t parent_sid = get_proc(stats.value(), parent).sid;
+
+ if (parent_sid == 0)
+ break;
+
+ sid = parent_sid;
+ }
+
+ if (kill(-sid, SIGTERM) == -1) {
+ perror("kill(2)");
+ return 1;
+ }
+
+ return 0;
+}