From 07882506c0e42758160e4b3b0f56022e4894b7b1 Mon Sep 17 00:00:00 2001 From: Riyyi Date: Sun, 19 Jan 2025 22:08:07 +0100 Subject: [PATCH] Manager: Add ability to detect Xorg/Wayland session for commenting files --- README.org | 14 ++++++-- src/dotfile.cpp | 19 +++++++---- src/machine.cpp | 88 ++++++++++++++++++++++++++++++++++++++++++++++--- src/machine.h | 16 +++++---- 4 files changed, 117 insertions(+), 20 deletions(-) diff --git a/README.org b/README.org index 1432a1e..18adb11 100644 --- a/README.org +++ b/README.org @@ -86,18 +86,26 @@ or uncomments them depending on the machine's configuration. Such a block looks like this: #+BEGIN_SRC shell-script -# >>> distro=arch hostname=arch-desktop user=anon +# >>> distro=arch hostname=arch-desktop user=anon session=xorg export PATH="$PATH:$HOME/.local/bin" # <<< #+END_SRC -This block uses all of the supported configurations, ~distro~, ~hostname~ and - ~user~. These can be used in any combination and order. +This block uses all of the supported configurations, ~distro~, ~hostname~, +~user~ and ~session~. These can be used in any combination and order. If *all* of the given configurations match, manafiles will make sure that the contents of the block are uncommented. If *any* of them do *not* match, then manafiles will make sure that the contents of the block are commented. +***** Usable values for the configurations + +| distro | session | +|--------+---------| +| arch | xorg | +| debian | wayland | +| ubuntu | | + ** Compiling *** Dependencies diff --git a/src/dotfile.cpp b/src/dotfile.cpp index 35c2fac..1a34b46 100644 --- a/src/dotfile.cpp +++ b/src/dotfile.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2021-2022 Riyyi + * Copyright (C) 2021-2022,2025 Riyyi * * SPDX-License-Identifier: MIT */ @@ -15,11 +15,12 @@ #include // geteuid, getlogin, setegid, seteuid #include +#include "ruc/file.h" +#include "ruc/meta/assert.h" + #include "config.h" #include "dotfile.h" #include "machine.h" -#include "ruc/file.h" -#include "ruc/meta/assert.h" Dotfile::Dotfile(s) { @@ -375,15 +376,16 @@ void Dotfile::selectivelyCommentOrUncomment(const std::string& path) { ruc::File dotfile(path); - const std::string search[3] = { + const std::string search[4] = { "distro=", "hostname=", "user=", + "session=", }; // State of the loop bool isFiltering = false; - std::string filter[3]; + std::string filter[4]; std::string commentCharacter; std::string commentTerminationCharacter; size_t positionInFile = 0; @@ -420,7 +422,7 @@ void Dotfile::selectivelyCommentOrUncomment(const std::string& path) if (line.find(">>>") != std::string::npos) { // Find machine info size_t find = 0; - for (size_t i = 0; i < 3; ++i) { + for (size_t i = 0; i < 4; ++i) { find = line.find(search[i]) + search[i].size(); if (find < search[i].size()) { continue; @@ -450,6 +452,7 @@ void Dotfile::selectivelyCommentOrUncomment(const std::string& path) filter[0] = ""; filter[1] = ""; filter[2] = ""; + filter[3] = ""; commentCharacter.clear(); commentTerminationCharacter.clear(); continue; @@ -471,6 +474,10 @@ void Dotfile::selectivelyCommentOrUncomment(const std::string& path) commentOrUncommentLine(line, true); continue; } + else if (filter[3] != Machine::the().session() && !filter[3].empty()) { + commentOrUncommentLine(line, true); + continue; + } commentOrUncommentLine(line, false); } diff --git a/src/machine.cpp b/src/machine.cpp index 6195b79..e9d4c70 100644 --- a/src/machine.cpp +++ b/src/machine.cpp @@ -1,21 +1,25 @@ /* - * Copyright (C) 2022 Riyyi + * Copyright (C) 2022,2025 Riyyi * * SPDX-License-Identifier: MIT */ -#include // getpwnam -#include // istringstream -#include // gethostname, getlogin +#include // int8_t +#include // std::filesystem::path +#include // getpwnam +#include // istringstream +#include // gethostname, getlogin -#include "machine.h" #include "ruc/file.h" +#include "machine.h" + Machine::Machine(s) { fetchDistro(); fetchHostname(); fetchUsername(); + fetchSession(); } Machine::~Machine() @@ -61,3 +65,77 @@ void Machine::fetchUsername() perror("\033[31;1mError:\033[0m getpwnam"); } } + +void Machine::fetchSession() +{ + // Determine if this is an Xorg or Wayland session + int8_t likelyWayland = 0; + + // Detect via environment variable + std::string env; + env = std::string(std::getenv("XDG_SESSION_TYPE")); + if (env == "wayland") { + likelyWayland++; + } + else if (env == "x11") { + likelyWayland--; + } + env = std::string(std::getenv("WAYLAND_DISPLAY")); + if (env.find("wayland-", 0) == 0) { + likelyWayland++; + } + + // Detect via Wayland socket + auto socket = std::filesystem::path("/run/user") / std::to_string(uid()); + if (std::filesystem::exists(socket) && std::filesystem::is_directory(socket)) { + for (const auto& entry : std::filesystem::directory_iterator(socket)) { + if (entry.path().filename().string().find("wayland-", 0) == 0) { + likelyWayland++; + break; + } + } + } + + // Detect via Xorg socket + if (std::filesystem::exists("/tmp/.X11-unix")) { + likelyWayland--; + } + + // Detect via running processes, /proc//comm + std::filesystem::path processes = "/proc"; + if (std::filesystem::exists(processes) && std::filesystem::is_directory(processes)) { + for (const auto& entry : std::filesystem::directory_iterator(processes)) { + if (std::filesystem::is_directory(entry)) { + + std::filesystem::path comm = entry.path() / "comm"; + if (!std::filesystem::exists(comm)) { + continue; + } + + // Read the contents of the "comm" file + std::ifstream stream(comm); + std::string command; + std::getline(stream, command); + + if (command == "Xwayland" || command == "hyprland" || command == "sway") { + likelyWayland++; + break; + } + + if (command == "Xorg" || command == "xinit" || command == "bspwm") { + likelyWayland--; + break; + } + } + } + } + + // If we detected at least 2 ways, we can be fairly certain + m_session = ""; + if (likelyWayland <= -2) { + m_session = "xorg"; + } + else if (likelyWayland >= 2) { + m_session = "wayland"; + } +} diff --git a/src/machine.h b/src/machine.h index 1381599..59627ab 100644 --- a/src/machine.h +++ b/src/machine.h @@ -17,21 +17,25 @@ public: Machine(s); virtual ~Machine(); - const std::string& distroId() { return m_distroId; } - const std::string& distroIdLike() { return m_distroIdLike; } - const std::string& hostname() { return m_hostname; } + const std::string& distroId() const { return m_distroId; } + const std::string& distroIdLike() const { return m_distroIdLike; } + const std::string& hostname() const { return m_hostname; } - std::string username() { return m_passwd->pw_name; } - uint32_t uid() { return m_passwd->pw_uid; } - uint32_t gid() { return m_passwd->pw_gid; } + std::string username() const { return std::string(m_passwd->pw_name); } + uint32_t uid() const { return m_passwd->pw_uid; } + uint32_t gid() const { return m_passwd->pw_gid; } + + const std::string& session() const { return m_session; } private: void fetchDistro(); void fetchHostname(); void fetchUsername(); + void fetchSession(); std::string m_distroId; std::string m_distroIdLike; std::string m_hostname; + std::string m_session; passwd* m_passwd { nullptr }; };