From 1e5cab1ee7a82d3381f55963a0ff768c30215602 Mon Sep 17 00:00:00 2001 From: Thomas Voss Date: Sun, 13 Nov 2022 12:58:20 +0100 Subject: [PATCH] Set child stdout and stderr to /dev/null (#1000) Some scripts or utilities check to see if stdout or stderr are connected to a TTY or not to determine certain behaviors (for example, you might want to prompt a user for input with fzf(1) if in a terminal but tofi(1) or wofi(1) when spawned from your WM). Since hyprland never closes these output streams for spawned processes, they end up just spewing their output onto the TTY while giving the user no real way to have a script detect if it's being run from the shell or WM. Instead of just closing stdout and stderr though, we close them and then proceed to reopen them but connect them to /dev/null. This allows scripts and processes to not fail when attempting to write, but for that writing to simply have no effect. --- src/managers/KeybindManager.cpp | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/src/managers/KeybindManager.cpp b/src/managers/KeybindManager.cpp index a529da97..86248861 100644 --- a/src/managers/KeybindManager.cpp +++ b/src/managers/KeybindManager.cpp @@ -1,5 +1,7 @@ #include "KeybindManager.hpp" +#include +#include #include CKeybindManager::CKeybindManager() { @@ -526,6 +528,25 @@ void CKeybindManager::spawn(std::string args) { // run in grandchild close(socket[0]); close(socket[1]); + close(STDOUT_FILENO); + close(STDERR_FILENO); + + int devnull = open(_PATH_DEVNULL, O_WRONLY); + if (devnull == -1) { + Debug::log(LOG, "Unable to open /dev/null for writing"); + return; + } + + if (dup2(devnull, STDOUT_FILENO) == -1) { + Debug::log(LOG, "Unable to duplicate /dev/null to stdout"); + return; + } + if (dup2(devnull, STDERR_FILENO) == -1) { + Debug::log(LOG, "Unable to duplicate /dev/null to stderr"); + return; + } + + close(devnull); execl("/bin/sh", "/bin/sh", "-c", args.c_str(), nullptr); // exit grandchild _exit(0);