summaryrefslogtreecommitdiff
path: root/src/os.cpp
diff options
context:
space:
mode:
authorpants <niklasjo2004@gmail.com>2026-09-21 14:18:06 -0700
committerpants <niklasjo2004@gmail.com>2026-09-21 14:18:06 -0700
commit83d5ba42f8a98fc0df177efef4333f74a0481f61 (patch)
tree6f1fcff64ec9adb2fc51a7cfcc451eb22a103fb3 /src/os.cpp
Diffstat (limited to 'src/os.cpp')
-rw-r--r--src/os.cpp126
1 files changed, 126 insertions, 0 deletions
diff --git a/src/os.cpp b/src/os.cpp
new file mode 100644
index 0000000..af37a0e
--- /dev/null
+++ b/src/os.cpp
@@ -0,0 +1,126 @@
+// Display images inside a terminal
+// Copyright (C) 2023 JustKidding
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+#include "os.hpp"
+#include "util/ptr.hpp"
+
+#include <array>
+#include <cstdlib>
+#include <system_error>
+
+#include <cerrno>
+#include <cstdio>
+#include <poll.h>
+#include <unistd.h>
+
+auto os::exec(const std::string &cmd) -> std::string
+{
+ const int bufsize = 128;
+ std::array<char, bufsize> buffer{};
+ std::string result;
+ const c_unique_ptr<FILE, &pclose> pipe{popen(cmd.c_str(), "r")};
+ if (!pipe) {
+ throw std::system_error(errno, std::generic_category());
+ }
+ while (fgets(buffer.data(), buffer.size(), pipe.get()) != nullptr) {
+ result.append(buffer.data());
+ }
+ if (!result.empty()) {
+ result.erase(result.length() - 1);
+ }
+ return result;
+}
+
+auto os::read_data_from_fd(int filde, char sep) -> std::string
+{
+ using std::errc;
+ std::string response;
+ char readch = 0;
+
+ while (true) {
+ const auto status = read(filde, &readch, 1);
+ if (status == -1) {
+ throw std::system_error(errno, std::system_category());
+ }
+ if (status == 0 || readch == sep) {
+ if (response.empty()) {
+ throw std::system_error(EIO, std::system_category());
+ }
+ break;
+ }
+ response.push_back(readch);
+ }
+ return response;
+}
+
+auto os::read_data_from_stdin(char sep) -> std::string
+{
+ return read_data_from_fd(STDIN_FILENO, sep);
+}
+
+auto os::wait_for_data_on_fd(int filde, int waitms) -> bool
+{
+ struct pollfd fds;
+ fds.fd = filde;
+ fds.events = POLLIN;
+
+ poll(&fds, 1, waitms);
+
+ if ((fds.revents & (POLLERR | POLLNVAL | POLLHUP)) != 0) {
+ throw std::system_error(EIO, std::generic_category());
+ }
+
+ return (fds.revents & POLLIN) != 0;
+}
+
+auto os::wait_for_data_on_stdin(int waitms) -> bool
+{
+ return wait_for_data_on_fd(STDIN_FILENO, waitms);
+}
+
+auto os::getenv(const std::string &var) -> std::optional<std::string>
+{
+ const char *env_p = std::getenv(var.c_str()); // NOLINT
+ if (env_p == nullptr) {
+ return {};
+ }
+ return env_p;
+}
+
+auto os::get_pid() -> int
+{
+ return getpid();
+}
+
+auto os::get_ppid() -> int
+{
+ return getppid();
+}
+
+void os::daemonize()
+{
+ const int pid = fork();
+ if (pid < 0) {
+ std::exit(EXIT_FAILURE); // NOLINT
+ }
+ if (pid > 0) {
+ std::exit(EXIT_SUCCESS); // NOLINT
+ }
+ const int status = setsid();
+ if (status < 0) {
+ std::exit(EXIT_FAILURE); // NOLINT
+ }
+}