Updated from GMP 1.906.7
[kopensolaris-gnu/glibc.git] / sysdeps / posix / pipestream.c
index e5103cf..53595f5 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (C) 1991 Free Software Foundation, Inc.
+/* Copyright (C) 1991, 1992, 1993 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
@@ -33,17 +33,39 @@ Cambridge, MA 02139, USA.  */
 /* Structure describing a popen child.  */
 struct child
   {
-    /* It is important that the first member of this structure be an `int' that
-       is the file descriptor.  This is because the `fileno' function assumes
-       that __cookie(STREAM) points to the file descriptor.  */
-    int fd;
-    pid_t pid;
+    pid_t pid;                 /* PID of the child.  */
+    __ptr_t cookie;            /* Original cookie from fdopen.  */
+    __io_functions funcs;      /* Original functions from fdopen.  */
   };
 
-#ifndef        FORK
-#define        FORK    fork
-#endif
+/* io_functions for pipe streams.
+   These all simply call the corresponding
+   original function with the original cookie.  */
+
+#define FUNC(type, name, args)                                               \
+  static type DEFUN(__CONCAT(child_,name), args, __CONCAT(name,decl))        \
+  {                                                                          \
+    struct child *c = (struct child *) cookie;                               \
+    {                                                                        \
+      __ptr_t cookie = c->cookie;                                            \
+      return (*c->funcs.__CONCAT(__,name)) args;                             \
+    }                                                                        \
+  }
 
+#define readdecl PTR cookie AND register char *buf AND register size_t n
+FUNC (int, read, (cookie, buf, n))
+#define writedecl PTR cookie AND register CONST char *buf AND register size_t n
+FUNC (int, write, (cookie, buf, n))
+#define seekdecl PTR cookie AND fpos_t *pos AND int whence
+FUNC (int, seek, (cookie, pos, whence))
+#define closedecl PTR cookie
+FUNC (int, close, (cookie))
+#define filenodecl PTR cookie
+FUNC (int, fileno, (cookie))
+
+static const __io_functions child_funcs
+  = { child_read, child_write, child_seek, child_close, child_fileno };
+\f
 /* Open a new stream that is a one-way pipe to a
    child process running the given shell command.  */
 FILE *
@@ -65,12 +87,12 @@ DEFUN(popen, (command, mode), CONST char *command AND CONST char *mode)
     return NULL;
 
   /* Fork off the child.  */
-  pid = FORK();
+  pid = __vfork ();
   if (pid == (pid_t) -1)
     {
       /* The fork failed.  */
-      (void) close(pipedes[0]);
-      (void) close(pipedes[1]);
+      (void) close (pipedes[0]);
+      (void) close (pipedes[1]);
       return NULL;
     }
   else if (pid == (pid_t) 0)
@@ -80,8 +102,8 @@ DEFUN(popen, (command, mode), CONST char *command AND CONST char *mode)
 
       CONST char *new_argv[4];
 
-      if ((*mode == 'r' ? dup2(pipedes[STDIN_FILENO], STDOUT_FILENO) :
-         dup2(pipedes[STDOUT_FILENO], STDIN_FILENO)) < 0)
+      if ((*mode == 'w' ? dup2(pipedes[STDIN_FILENO], STDIN_FILENO) :
+         dup2(pipedes[STDOUT_FILENO], STDOUT_FILENO)) < 0)
        _exit(127);
 
       /* Close the pipe descriptors.  */
@@ -101,44 +123,63 @@ DEFUN(popen, (command, mode), CONST char *command AND CONST char *mode)
   /* We are the parent side.  */
 
   /* Close the irrelevant side of the pipe and open the relevant side as a
-     new stream.  Mark our side of the pipe to close on exec, so new popen
-     children won't see it.  */
+     new stream.  Mark our side of the pipe to close on exec, so new children
+     won't see it.  */
   if (*mode == 'r')
     {
-      (void) close(pipedes[STDOUT_FILENO]);
+      (void) close (pipedes[STDOUT_FILENO]);
       (void) fcntl (pipedes[STDIN_FILENO], F_SETFD, FD_CLOEXEC);
-      stream = fdopen(pipedes[STDIN_FILENO], mode);
+      stream = fdopen (pipedes[STDIN_FILENO], mode);
     }
   else
     {
-      (void) close(pipedes[STDIN_FILENO]);
+      (void) close (pipedes[STDIN_FILENO]);
       (void) fcntl (pipedes[STDOUT_FILENO], F_SETFD, FD_CLOEXEC);
-      stream = fdopen(pipedes[STDOUT_FILENO], mode);
+      stream = fdopen (pipedes[STDOUT_FILENO], mode);
     }
 
   if (stream == NULL)
     goto error;
 
-  child = (struct child *) malloc(sizeof(struct child));
+  child = (struct child *) malloc (sizeof (struct child));
   if (child == NULL)
     goto error;
-  child->fd = fileno(stream);
+
+  {
+    /* Make sure STREAM has its functions set before
+       we try to squirrel them away in CHILD.  */
+    extern void __stdio_check_funcs __P ((FILE *));
+    __stdio_check_funcs (stream);
+  }
+
   child->pid = pid;
+  child->cookie = stream->__cookie;
+  child->funcs = stream->__io_funcs;
   stream->__cookie = (PTR) child;
+  stream->__io_funcs = child_funcs;
   stream->__ispipe = 1;
   return stream;
 
- error:;
+ error:
   {
     /* The stream couldn't be opened or the child structure couldn't be
        allocated.  Kill the child and close the other side of the pipe.  */
     int save = errno;
-    (void) kill(pid, SIGKILL);
+    (void) kill (pid, SIGKILL);
     if (stream == NULL)
-      (void) close(pipedes[*mode == 'r' ? STDOUT_FILENO : STDIN_FILENO]);
+      (void) close (pipedes[*mode == 'r' ? STDOUT_FILENO : STDIN_FILENO]);
     else
-      (void) fclose(stream);
-    (void) waitpid(pid, (int *) NULL, 0);
+      (void) fclose (stream);
+#ifndef        NO_WAITPID
+    (void) waitpid (pid, (int *) NULL, 0);
+#else
+    {
+      pid_t dead;
+      do
+       dead = wait ((int *) NULL);
+      while (dead > 0 && dead != pid);
+    }
+#endif
     errno = save;
     return NULL;
   }
@@ -149,7 +190,8 @@ DEFUN(popen, (command, mode), CONST char *command AND CONST char *mode)
 int
 DEFUN(pclose, (stream), register FILE *stream)
 {
-  pid_t pid;
+  struct child *c;
+  pid_t pid, dead;
   int status;
 
   if (!__validfp(stream) || !stream->__ispipe)
@@ -158,14 +200,24 @@ DEFUN(pclose, (stream), register FILE *stream)
       return -1;
     }
 
-  pid = ((struct child *) stream->__cookie)->pid;
-  free(stream->__cookie);
-  stream->__cookie = (PTR) &stream->__fileno;
+  c = (struct child *) stream->__cookie;
+  pid = c->pid;
+  stream->__cookie = c->cookie;
+  stream->__io_funcs = c->funcs;
+  free ((PTR) c);
   stream->__ispipe = 0;
-  if (fclose(stream))
+  if (fclose (stream))
     return -1;
 
-  if (waitpid(pid, &status, 0) != pid)
+#ifndef        NO_WAITPID
+  dead = waitpid (pid, &status, 0);
+#else
+  do
+    dead = wait (&status);
+  while (dead > 0 && dead != pid);
+#endif
+  if (dead != pid)
     status = -1;
+
   return status;
 }