LibC: Implement system() more properly

Old implementation did not ignore and block needed signals
This commit is contained in:
Bananymous 2024-10-13 22:03:15 +03:00
parent d36b64e0c8
commit fdddb556ae
1 changed files with 48 additions and 8 deletions

View File

@ -2,13 +2,16 @@
#include <BAN/Limits.h>
#include <BAN/Math.h>
#include <BAN/UTF8.h>
#include <ctype.h>
#include <errno.h>
#include <locale.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <sys/stat.h>
#include <sys/syscall.h>
#include <unistd.h>
@ -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;
}