Updated from GMP 1.906.7
[kopensolaris-gnu/glibc.git] / sysdeps / posix / system.c
index 2505f88..da58be5 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (C) 1991, 1992 Free Software Foundation, Inc.
+/* Copyright (C) 1991, 1992, 1994, 1995 Free Software Foundation, Inc.
 This file is part of the GNU C Library.
 
 The GNU C Library is free software; you can redistribute it and/or
@@ -23,6 +23,7 @@ Cambridge, MA 02139, USA.  */
 #include <sys/wait.h>
 #include <signal.h>
 #include <sys/types.h>
+#include <errno.h>
 
 
 #ifndef        HAVE_GNU_LD
@@ -32,42 +33,63 @@ Cambridge, MA 02139, USA.  */
 #define        SHELL_PATH      "/bin/sh"       /* Path of the shell.  */
 #define        SHELL_NAME      "sh"            /* Name to give it.  */
 
-#ifndef        FORK
-#define        FORK    __fork
-#endif
-
 /* Execute LINE as a shell command, returning its status.  */
 int
 DEFUN(system, (line), register CONST char *line)
 {
-  int status;
+  int status, save;
   pid_t pid;
   struct sigaction sa, intr, quit;
+#ifndef WAITPID_CANNOT_BLOCK_SIGCHLD
   sigset_t block, omask;
+#endif
 
   if (line == NULL)
     return 1;
 
   sa.sa_handler = SIG_IGN;
   sa.sa_flags = 0;
-  if (__sigemptyset(&sa.sa_mask) < 0)
-    return -1;
-  if (__sigaction(SIGINT, &sa, &intr) < 0)
+  __sigemptyset (&sa.sa_mask);
+
+  if (__sigaction (SIGINT, &sa, &intr) < 0)
     return -1;
-  if (__sigaction(SIGQUIT, &sa, &quit) < 0)
+  if (__sigaction (SIGQUIT, &sa, &quit) < 0)
     {
-      (void) __sigaction(SIGINT, &intr, (struct sigaction *) NULL);
+      save = errno;
+      (void) __sigaction (SIGINT, &intr, (struct sigaction *) NULL);
+      errno = save;
       return -1;
     }
-  if (__sigemptyset(&block) < 0 || __sigaddset(&block, SIGCHLD) < 0 ||
-      __sigprocmask(SIG_BLOCK, &block, &omask) < 0)
+
+#ifndef WAITPID_CANNOT_BLOCK_SIGCHLD
+
+/* SCO 3.2v4 has a bug where `waitpid' will never return if SIGCHLD is
+   blocked.  This makes it impossible for `system' to be implemented in
+   compliance with POSIX.2-1992.  They have acknowledged that this is a bug
+   but I have not seen nor heard of any forthcoming fix.  */
+
+  __sigemptyset (&block);
+  __sigaddset (&block, SIGCHLD);
+  save = errno;
+  if (__sigprocmask (SIG_BLOCK, &block, &omask) < 0)
     {
-      (void) __sigaction(SIGINT, &intr, (struct sigaction *) NULL);
-      (void) __sigaction(SIGQUIT, &quit, (struct sigaction *) NULL);
-      return -1;
+      if (errno == ENOSYS)
+       errno = save;
+      else
+       {
+         save = errno;
+         (void) __sigaction (SIGINT, &intr, (struct sigaction *) NULL);
+         (void) __sigaction (SIGQUIT, &quit, (struct sigaction *) NULL);
+         errno = save;
+         return -1;
+       }
     }
+#define UNBLOCK        __sigprocmask (SIG_SETMASK, &omask, (sigset_t *) NULL)
+#else
+#define UNBLOCK 0
+#endif
 
-  pid = FORK();
+  pid = __vfork ();
   if (pid == (pid_t) 0)
     {
       /* Child side.  */
@@ -78,13 +100,13 @@ DEFUN(system, (line), register CONST char *line)
       new_argv[3] = NULL;
 
       /* Restore the signals.  */
-      (void) __sigaction(SIGINT, &intr, (struct sigaction *) NULL);
-      (void) __sigaction(SIGQUIT, &quit, (struct sigaction *) NULL);
-      (void) __sigprocmask(SIG_SETMASK, &omask, (sigset_t *) NULL);
+      (void) __sigaction (SIGINT, &intr, (struct sigaction *) NULL);
+      (void) __sigaction (SIGQUIT, &quit, (struct sigaction *) NULL);
+      (void) UNBLOCK;
 
       /* Exec the shell.  */
-      (void) __execve(SHELL_PATH, (char *CONST *) new_argv, __environ);
-      _exit(127);
+      (void) __execve (SHELL_PATH, (char *CONST *) new_argv, __environ);
+      _exit (127);
     }
   else if (pid < (pid_t) 0)
     /* The fork failed.  */
@@ -105,14 +127,20 @@ DEFUN(system, (line), register CONST char *line)
        } while (child != pid);
     }
 #else
-    if (__waitpid(pid, &status, 0) != pid)
+    if (__waitpid (pid, &status, 0) != pid)
       status = -1;
 #endif
 
-  if ((__sigaction(SIGINT, &intr, (struct sigaction *) NULL) |
-       __sigaction(SIGQUIT, &quit, (struct sigaction *) NULL) |
-       __sigprocmask(SIG_SETMASK, &omask, (sigset_t *) NULL)) != 0)
-    return -1;
+  save = errno;
+  if ((__sigaction (SIGINT, &intr, (struct sigaction *) NULL) |
+       __sigaction (SIGQUIT, &quit, (struct sigaction *) NULL) |
+       UNBLOCK) != 0)
+    {
+      if (errno == ENOSYS)
+       errno = save;
+      else
+       return -1;
+    }
 
   return status;
 }