--- guile-2.2.4/libguile/simpos.c +++ guile-2.2.4/libguile/simpos.c @@ -24,7 +24,10 @@ #endif #include -#include /* for getenv, system, exit, free */ +#include +#include /* for getenv, exit, free */ +#include +#include #include /* for _exit */ #include "libguile/_scm.h" @@ -48,7 +51,11 @@ "indicating whether the command processor is available.") #define FUNC_NAME s_scm_system { - int rv, eno; + int rv, eno, child_errno = 0; + int status; + int errpipe[2]; + ssize_t nread; + pid_t pid; char *c_cmd; if (SCM_UNBNDP (cmd)) @@ -59,11 +66,78 @@ SCM_VALIDATE_STRING (1, cmd); errno = 0; c_cmd = scm_to_locale_string (cmd); - rv = system (c_cmd); - eno = errno; free (c_cmd); errno = eno; - if (rv == -1 || (rv == 127 && errno != 0)) - SCM_SYSERROR; - return scm_from_int (rv); + + if (pipe (errpipe) < 0) + { + eno = errno; free (c_cmd); errno = eno; + SCM_SYSERROR; + } + + if (fcntl (errpipe[1], F_SETFD, FD_CLOEXEC) == -1) + { + eno = errno; + close (errpipe[0]); + close (errpipe[1]); + free (c_cmd); + errno = eno; + SCM_SYSERROR; + } + + pid = fork (); + if (pid == 0) + { + char *argv[] = { (char *) "sh", (char *) "-c", c_cmd, NULL }; + close (errpipe[0]); + execvp ("sh", argv); + child_errno = errno; + if (write (errpipe[1], &child_errno, sizeof (child_errno)) < 0) + ; + _exit (127); + } + else if (pid < 0) + { + eno = errno; + close (errpipe[0]); + close (errpipe[1]); + free (c_cmd); + errno = eno; + SCM_SYSERROR; + } + + close (errpipe[1]); + while ((nread = read (errpipe[0], &child_errno, sizeof (child_errno))) == -1 + && errno == EINTR) + ; + close (errpipe[0]); + if (nread == -1) + { + eno = errno; + free (c_cmd); + errno = eno; + SCM_SYSERROR; + } + if (nread != sizeof (child_errno)) + child_errno = 0; + + while ((rv = waitpid (pid, &status, 0)) == -1 && errno == EINTR) + ; + if (rv == -1) + { + eno = errno; + free (c_cmd); + errno = eno; + SCM_SYSERROR; + } + + free (c_cmd); + + if (child_errno != 0) + { + errno = child_errno; + SCM_SYSERROR; + } + + return scm_from_int (status); } #undef FUNC_NAME #endif /* HAVE_SYSTEM */