From f85138a27d1916ad42aedacee5daa48a72e75730 Mon Sep 17 00:00:00 2001
From: Recolic <git@me.recolic.net>
Date: Thu, 6 Mar 2025 16:27:31 -0800
Subject: [PATCH 1/5] .

---
 functional.hpp     | 13 ++++++++++++-
 sys/unix_handy.hpp | 43 +++++++++++++++++++++++++++++++++++++------
 2 files changed, 49 insertions(+), 7 deletions(-)

diff --git a/functional.hpp b/functional.hpp
index 891230a..26d4946 100644
--- a/functional.hpp
+++ b/functional.hpp
@@ -44,7 +44,18 @@ namespace rlib {
         auto begin = std::chrono::high_resolution_clock::now();
         f(std::forward<Args>(args) ...);
         auto end = std::chrono::high_resolution_clock::now();
-        return ::std::chrono::duration<double>(end - begin).count(); 
+        return std::chrono::duration<double>(end - begin).count(); 
+    }
+    template <typename Func, typename... Args>
+    static inline auto timeout(double timeout_seconds, Func&& func, Args&&... args) {
+        using ReturnType = decltype(func(args...));
+        auto future = std::async(std::launch::async, std::forward<Func>(func), std::forward<Args>(args)...);
+    
+        if (future.wait_for(std::chrono::seconds(timeout_seconds)) == std::future_status::timeout) {
+            return ReturnType {};
+        }
+    
+        return future.get();
     }
 
     template <class Func, typename... Args>
diff --git a/sys/unix_handy.hpp b/sys/unix_handy.hpp
index c65110b..bcab553 100644
--- a/sys/unix_handy.hpp
+++ b/sys/unix_handy.hpp
@@ -2,18 +2,17 @@
 #define RLIB_UNIX_HANDY_HPP_
 
 #include <unistd.h>
-
-#include <sys/socket.h>
-#include <sys/types.h>
-#include <netdb.h>
-#include <rlib/scope_guard.hpp>
-#include <rlib/string.hpp>
+#include <string>
+#include <stdexcept>
 
 #include <rlib/sys/os.hpp>
 #if RLIB_OS_ID == OS_WINDOWS
 #error rlib/sys/unix_handy.hpp is not for Windows.
 #endif
 
+// For shell_run
+#include <sstream>
+
 namespace rlib {
     // args DOES NOT contain the "$0".
     inline void execs(std::string path, std::vector<std::string> args) {
@@ -28,10 +27,42 @@ namespace rlib {
     
         ::execv(path.c_str(), arr);
     }
+
+    struct shell_result {
+        int status;
+        std::string stdout_;
+    };
+    
+    // Execute command with shell and capture stdout.
+    // Note: stderr would be discarded. Use `2>&1` if needed.
+    shell_result shell_run(const std::string& command) {
+        char buffer[128];
+    
+        FILE *pipe = popen(command.c_str(), "r");
+        if (!pipe) {
+            return {-errno, ""};
+        }
+    
+        shell_result res;
+
+        while (fgets(buffer, sizeof(buffer), pipe) != nullptr) {
+            res.stdout_ += buffer;
+        }
+    
+        res.status = pclose(pipe);
+        res.status = WIFEXITED(status) ? WEXITSTATUS(status) : -errno;
+    
+        return res;
+    }
 }
 
 // Deprecated. Use sys/sio.hpp
 #if 1+1 == 4
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <netdb.h>
+#include <rlib/scope_guard.hpp>
+#include <rlib/string.hpp>
 namespace rlib {
     namespace impl {
         using rlib::literals::operator""_format;
-- 
GitLab


From a10a9f4afdd189e9456c281c24fedf83863c3e86 Mon Sep 17 00:00:00 2001
From: Recolic <git@me.recolic.net>
Date: Thu, 6 Mar 2025 16:33:38 -0800
Subject: [PATCH 2/5] .

---
 functional.hpp     | 1 +
 sys/unix_handy.hpp | 2 +-
 2 files changed, 2 insertions(+), 1 deletion(-)

diff --git a/functional.hpp b/functional.hpp
index 26d4946..138a055 100644
--- a/functional.hpp
+++ b/functional.hpp
@@ -9,6 +9,7 @@
 #include <list>
 #include <functional>
 #include <chrono>
+#include <future>
 #include <stdexcept>
 
 namespace rlib {
diff --git a/sys/unix_handy.hpp b/sys/unix_handy.hpp
index bcab553..7ebf7c9 100644
--- a/sys/unix_handy.hpp
+++ b/sys/unix_handy.hpp
@@ -50,7 +50,7 @@ namespace rlib {
         }
     
         res.status = pclose(pipe);
-        res.status = WIFEXITED(status) ? WEXITSTATUS(status) : -errno;
+        res.status = WIFEXITED(res.status) ? WEXITSTATUS(res.status) : -errno;
     
         return res;
     }
-- 
GitLab


From e87a5b9eefdec84a70c0a6a8f83e20c714c3abb8 Mon Sep 17 00:00:00 2001
From: Recolic <git@me.recolic.net>
Date: Thu, 6 Mar 2025 16:34:56 -0800
Subject: [PATCH 3/5] .

---
 sys/unix_handy.hpp | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/sys/unix_handy.hpp b/sys/unix_handy.hpp
index 7ebf7c9..f18b618 100644
--- a/sys/unix_handy.hpp
+++ b/sys/unix_handy.hpp
@@ -54,6 +54,10 @@ namespace rlib {
     
         return res;
     }
+
+    auto get_shell_name() {
+        return shell_run("echo $0").stdout_;
+    }
 }
 
 // Deprecated. Use sys/sio.hpp
-- 
GitLab


From baf3471e4dae6fb5a1a965ee6b69c438541be5dd Mon Sep 17 00:00:00 2001
From: Recolic <git@me.recolic.net>
Date: Thu, 6 Mar 2025 16:37:00 -0800
Subject: [PATCH 4/5] .

---
 sys/unix_handy.hpp | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/sys/unix_handy.hpp b/sys/unix_handy.hpp
index f18b618..faedefd 100644
--- a/sys/unix_handy.hpp
+++ b/sys/unix_handy.hpp
@@ -4,6 +4,7 @@
 #include <unistd.h>
 #include <string>
 #include <stdexcept>
+#include <vector>
 
 #include <rlib/sys/os.hpp>
 #if RLIB_OS_ID == OS_WINDOWS
@@ -56,7 +57,7 @@ namespace rlib {
     }
 
     auto get_shell_name() {
-        return shell_run("echo $0").stdout_;
+        return shell_run("echo -n $0").stdout_;
     }
 }
 
-- 
GitLab


From 5fb20249909628f96575ee278e1cd9f3bba26a16 Mon Sep 17 00:00:00 2001
From: Recolic <git@me.recolic.net>
Date: Thu, 6 Mar 2025 16:38:32 -0800
Subject: [PATCH 5/5] .

---
 functional.hpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/functional.hpp b/functional.hpp
index 138a055..8e60871 100644
--- a/functional.hpp
+++ b/functional.hpp
@@ -48,7 +48,7 @@ namespace rlib {
         return std::chrono::duration<double>(end - begin).count(); 
     }
     template <typename Func, typename... Args>
-    static inline auto timeout(double timeout_seconds, Func&& func, Args&&... args) {
+    static inline auto timeout(int timeout_seconds, Func&& func, Args&&... args) {
         using ReturnType = decltype(func(args...));
         auto future = std::async(std::launch::async, std::forward<Func>(func), std::forward<Args>(args)...);
     
-- 
GitLab