From fdddb556aec421bda0fda802fd400d48dbfb1a9a Mon Sep 17 00:00:00 2001 From: Bananymous Date: Sun, 13 Oct 2024 22:03:15 +0300 Subject: [PATCH] LibC: Implement system() more properly Old implementation did not ignore and block needed signals --- userspace/libraries/LibC/stdlib.cpp | 56 ++++++++++++++++++++++++----- 1 file changed, 48 insertions(+), 8 deletions(-) diff --git a/userspace/libraries/LibC/stdlib.cpp b/userspace/libraries/LibC/stdlib.cpp index 18773023..4fc4b561 100644 --- a/userspace/libraries/LibC/stdlib.cpp +++ b/userspace/libraries/LibC/stdlib.cpp @@ -2,13 +2,16 @@ #include #include #include + #include #include #include +#include #include #include #include #include +#include #include #include @@ -26,6 +29,7 @@ void abort(void) fflush(nullptr); fprintf(stderr, "abort()\n"); exit(1); + ASSERT_NOT_REACHED(); } void exit(int status) @@ -395,22 +399,58 @@ char* realpath(const char* __restrict file_name, char* __restrict resolved_name) int system(const char* command) { - // FIXME + // FIXME: maybe implement POSIX compliant shell? + constexpr const char* shell_path = "/bin/Shell"; + if (command == nullptr) - return 1; + { + struct stat st; + if (stat(shell_path, &st) == -1) + return 0; + if (S_ISDIR(st.st_mode)) + return 0; + return !!(st.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH)); + } + + struct sigaction sa; + sa.sa_flags = 0; + sa.sa_handler = SIG_IGN; + sigemptyset(&sa.sa_mask); + + struct sigaction sigint_save, sigquit_save; + sigaction(SIGINT, &sa, &sigint_save); + sigaction(SIGQUIT, &sa, &sigquit_save); + + sigset_t sigchld_save; + sigaddset(&sa.sa_mask, SIGCHLD); + sigprocmask(SIG_BLOCK, &sa.sa_mask, &sigchld_save); int pid = fork(); if (pid == 0) { - execl("/bin/Shell", "Shell", "-c", command, (char*)0); - exit(1); + sigaction(SIGINT, &sigint_save, nullptr); + sigaction(SIGQUIT, &sigquit_save, nullptr); + sigprocmask(SIG_SETMASK, &sigchld_save, nullptr); + execl(shell_path, "sh", "-c", command, nullptr); + exit(127); } - if (pid == -1) - return -1; + int stat_val = -1; + if (pid != -1) + { + while (waitpid(pid, &stat_val, 0) == -1) + { + if (errno == EINTR) + continue; + stat_val = -1; + break; + } + } + + sigaction(SIGINT, &sigint_save, nullptr); + sigaction(SIGQUIT, &sigquit_save, nullptr); + sigprocmask(SIG_SETMASK, &sigchld_save, nullptr); - int stat_val; - waitpid(pid, &stat_val, 0); return stat_val; }