daily update
[external/binutils.git] / gdb / ser-pipe.c
index 58a77b6..77c3a08 100644 (file)
@@ -1,5 +1,6 @@
 /* Serial interface for a pipe to a separate program
-   Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc.
+   Copyright (C) 1999, 2000, 2001, 2007, 2008, 2009, 2010
+   Free Software Foundation, Inc.
 
    Contributed by Cygnus Solutions.
 
@@ -7,7 +8,7 @@
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
+   the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.
 
    This program is distributed in the hope that it will be useful,
@@ -16,9 +17,7 @@
    GNU General Public License for more details.
 
    You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 51 Franklin Street, Fifth Floor,
-   Boston, MA 02110-1301, USA.  */
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
 
 #include "defs.h"
 #include "serial.h"
@@ -62,9 +61,16 @@ pipe_open (struct serial *scb, const char *name)
    * published in UNIX Review, Vol. 6, No. 8.
    */
   int pdes[2];
+  int err_pdes[2];
   int pid;
   if (socketpair (AF_UNIX, SOCK_STREAM, 0, pdes) < 0)
     return -1;
+  if (socketpair (AF_UNIX, SOCK_STREAM, 0, err_pdes) < 0)
+    {
+      close (pdes[0]);
+      close (pdes[1]);
+      return -1;
+    }
 
   /* Create the child process to run the command in.  Note that the
      apparent call to vfork() below *might* actually be a call to
@@ -77,9 +83,18 @@ pipe_open (struct serial *scb, const char *name)
     {
       close (pdes[0]);
       close (pdes[1]);
+      close (err_pdes[0]);
+      close (err_pdes[1]);
       return -1;
     }
 
+  if (fcntl (err_pdes[0], F_SETFL, O_NONBLOCK) == -1)
+    {
+      close (err_pdes[0]);
+      close (err_pdes[1]);
+      err_pdes[0] = err_pdes[1] = -1;
+    }
+
   /* Child. */
   if (pid == 0)
     {
@@ -91,6 +106,13 @@ pipe_open (struct serial *scb, const char *name)
          close (pdes[1]);
        }
       dup2 (STDOUT_FILENO, STDIN_FILENO);
+
+      if (err_pdes[0] != -1)
+       {
+         close (err_pdes[0]);
+         dup2 (err_pdes[1], STDERR_FILENO);
+         close (err_pdes[1]);
+       }
 #if 0
       /* close any stray FD's - FIXME - how? */
       /* POSIX.2 B.3.2.2 "popen() shall ensure that any streams
@@ -105,10 +127,13 @@ pipe_open (struct serial *scb, const char *name)
 
   /* Parent. */
   close (pdes[1]);
+  if (err_pdes[1] != -1)
+    close (err_pdes[1]);
   /* :end chunk */
   state = XMALLOC (struct pipe_state);
   state->pid = pid;
   scb->fd = pdes[0];
+  scb->error_fd = err_pdes[0];
   scb->state = state;
 
   /* If we don't do this, GDB simply exits when the remote side dies.  */
@@ -126,10 +151,15 @@ pipe_close (struct serial *scb)
       int pid = state->pid;
       close (scb->fd);
       scb->fd = -1;
+      if (scb->error_fd != -1)
+       close (scb->error_fd);
+      scb->error_fd = -1;
       xfree (state);
       scb->state = NULL;
       kill (pid, SIGTERM);
-      /* Might be useful to check that the child does die. */
+      /* Might be useful to check that the child does die,
+        and while we're waiting for it to die print any remaining
+        stderr output.  */
     }
 }