live-bootstrap/steps-guix/guile-2.2.4/patches/use-execvp-sh-in-scm-system.patch

98 lines
2.1 KiB
Diff

--- guile-2.2.4/libguile/simpos.c
+++ guile-2.2.4/libguile/simpos.c
@@ -24,7 +24,10 @@
#endif
#include <errno.h>
-#include <stdlib.h> /* for getenv, system, exit, free */
+#include <fcntl.h>
+#include <stdlib.h> /* for getenv, exit, free */
+#include <sys/types.h>
+#include <sys/wait.h>
#include <unistd.h> /* for _exit */
#include "libguile/_scm.h"
@@ -48,7 +51,10 @@
"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];
+ pid_t pid;
char *c_cmd;
if (SCM_UNBNDP (cmd))
@@ -59,11 +65,67 @@
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))
+
+ 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 ((rv = waitpid (pid, &status, 0)) == -1 && errno == EINTR)
+ ;
+
+ while (read (errpipe[0], &child_errno, sizeof (child_errno)) == -1
+ && errno == EINTR)
+ ;
+ close (errpipe[0]);
+
+ eno = errno;
+ free (c_cmd);
+ errno = eno;
+
+ if (rv == -1)
SCM_SYSERROR;
- return scm_from_int (rv);
+
+ if (child_errno != 0)
+ {
+ errno = child_errno;
+ SCM_SYSERROR;
+ }
+
+ return scm_from_int (status);
}
#undef FUNC_NAME
#endif /* HAVE_SYSTEM */