From 14709b3d5c63bc45a8f0bce53133f65c5543352d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Florian=20Mei=C3=9Fner?= <florian.meissner@mailbox.org>
Date: Mon, 29 May 2023 20:54:34 +0200
Subject: [PATCH] system(): on command == NULL, return nonzero if shell exists

---
 src/header/stdlib/mod.rs                        | 16 +++++++++++-----
 tests/expected/bins_static/stdlib/system.stdout |  1 +
 tests/stdlib/system.c                           | 12 +++++++++++-
 3 files changed, 23 insertions(+), 6 deletions(-)

diff --git a/src/header/stdlib/mod.rs b/src/header/stdlib/mod.rs
index bf290f69..7ce19825 100644
--- a/src/header/stdlib/mod.rs
+++ b/src/header/stdlib/mod.rs
@@ -1170,13 +1170,19 @@ pub unsafe extern "C" fn strtoll(
 pub unsafe extern "C" fn system(command: *const c_char) -> c_int {
     //TODO: share code with popen
 
+    // handle shell detection on command == NULL
+    if command.is_null() {
+        let status = system("exit 0\0".as_ptr() as *const c_char);
+        if status == 0 {
+            return 1;
+        } else {
+            return 0;
+        }
+    }
+
     let child_pid = unistd::fork();
     if child_pid == 0 {
-        let command_nonnull = if command.is_null() {
-            "exit 0\0".as_ptr()
-        } else {
-            command as *const u8
-        };
+        let command_nonnull = command as *const u8;
 
         let shell = "/bin/sh\0".as_ptr();
 
diff --git a/tests/expected/bins_static/stdlib/system.stdout b/tests/expected/bins_static/stdlib/system.stdout
index a6d3f18a..90f99da2 100644
--- a/tests/expected/bins_static/stdlib/system.stdout
+++ b/tests/expected/bins_static/stdlib/system.stdout
@@ -1 +1,2 @@
+shell found: 1
 test of system
diff --git a/tests/stdlib/system.c b/tests/stdlib/system.c
index 8b7d0220..821c216f 100644
--- a/tests/stdlib/system.c
+++ b/tests/stdlib/system.c
@@ -3,6 +3,16 @@
 #include "test_helpers.h"
 
 int main(void) {
-    int status = system("echo test of system");
+    // testing shell detection
+    // this means, because we don't detect if a shell actually exists but just assume it does, this test case breaks in
+    // environments without `sh`. I think that is a reasonable tradeoff.
+    // (And if there isn't a shell, system() won't work anyways)
+    int status = system(NULL);
+    printf("shell found: %i\n", status);
+    fflush(stdout);
+    ERROR_IF(system, status, == 0);
+
+    // base case
+    status = system("echo test of system");
     ERROR_IF(system, status, == -1);
 }
-- 
GitLab