OSDN Git Service

add UCLIBC_SUSV2_LEGACY to hide valloc
[uclinux-h8/uClibc.git] / libc / stdlib / system.c
index 7026a8d..151a229 100644 (file)
@@ -5,6 +5,7 @@
  */
 
 #include <stdio.h>
+#include <string.h>
 #include <stddef.h>
 #include <signal.h>
 #include <unistd.h>
 #include <sysdep-cancel.h>
 #endif
 
+extern __typeof(system) __libc_system;
 
-#if !defined __UCLIBC_HAS_THREADS_NATIVE__
-/* uClinux-2.0 has vfork, but Linux 2.0 doesn't */
-#include <sys/syscall.h>
-#ifndef __NR_vfork
-# define vfork fork
-#endif
+/* TODO: the cancellable version breaks on sparc currently,
+ * need to figure out why still
+ */
+#if !defined __UCLIBC_HAS_THREADS_NATIVE__ || defined __sparc__
 
-extern __typeof(system) __libc_system;
 int __libc_system(const char *command)
 {
        int wait_val, pid;
-       __sighandler_t save_quit, save_int, save_chld;
+       struct sigaction sa, save_quit, save_int;
+       sigset_t save_mask;
 
        if (command == 0)
                return 1;
 
-       save_quit = signal(SIGQUIT, SIG_IGN);
-       save_int = signal(SIGINT, SIG_IGN);
-       save_chld = signal(SIGCHLD, SIG_DFL);
+       memset(&sa, 0, sizeof(sa));
+       sa.sa_handler = SIG_IGN;
+       /* __sigemptyset(&sa.sa_mask); - done by memset() */
+       /* sa.sa_flags = 0; - done by memset() */
+
+       sigaction(SIGQUIT, &sa, &save_quit);
+       sigaction(SIGINT, &sa, &save_int);
+       __sigaddset(&sa.sa_mask, SIGCHLD);
+       sigprocmask(SIG_BLOCK, &sa.sa_mask, &save_mask);
 
        if ((pid = vfork()) < 0) {
-               signal(SIGQUIT, save_quit);
-               signal(SIGINT, save_int);
-               signal(SIGCHLD, save_chld);
-               return -1;
+               wait_val = -1;
+               goto out;
        }
        if (pid == 0) {
-               signal(SIGQUIT, SIG_DFL);
-               signal(SIGINT, SIG_DFL);
-               signal(SIGCHLD, SIG_DFL);
+               sigaction(SIGQUIT, &save_quit, NULL);
+               sigaction(SIGINT, &save_int, NULL);
+               sigprocmask(SIG_SETMASK, &save_mask, NULL);
 
                execl("/bin/sh", "sh", "-c", command, (char *) 0);
                _exit(127);
        }
-       /* Signals are not absolutly guarenteed with vfork */
-       signal(SIGQUIT, SIG_IGN);
-       signal(SIGINT, SIG_IGN);
 
 #if 0
        __printf("Waiting for child %d\n", pid);
 #endif
 
-       if (wait4(pid, &wait_val, 0, 0) == -1)
+       if (__wait4_nocancel(pid, &wait_val, 0, 0) == -1)
                wait_val = -1;
 
-       signal(SIGQUIT, save_quit);
-       signal(SIGINT, save_int);
-       signal(SIGCHLD, save_chld);
+out:
+       sigaction(SIGQUIT, &save_quit, NULL);
+       sigaction(SIGINT, &save_int, NULL);
+       sigprocmask(SIG_SETMASK, &save_mask, NULL);
        return wait_val;
 }
 #else
@@ -123,9 +125,10 @@ do_system (const char *line)
   struct sigaction sa;
   sigset_t omask;
 
+  memset(&sa, 0, sizeof(sa));
   sa.sa_handler = SIG_IGN;
-  sa.sa_flags = 0;
-  __sigemptyset (&sa.sa_mask);
+  /*sa.sa_flags = 0; - done by memset */
+  /*__sigemptyset (&sa.sa_mask); - done by memset */
 
   DO_LOCK ();
   if (ADD_REF () == 0)