diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index ca728cd97f65991416c38f2e6e369fddfee79ba0..467637a9282048e056dc39b40540eac68cc53cf3 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,25 @@
+2005-03-29  Ian Lance Taylor  <ian@airs.com>
+
+	PR bootstrap/14316
+	* collect2.c: Never include <vfork.h>.
+	(VFORK_STRING, vfork): Don't define.
+	(pid): Remove global variable.
+	(handler): Call raise instead of kill (getpid(), ...).
+	(collect_wait): Add pex parameter.  Change all callers.  Use
+	pex_get_status rather than pwait.
+	(do_wait): Add pex parameter.  Change all callers.
+	(collect_execute): Return struct pex_obj * rather than void.  Use
+	pex routines rather than pexecute.
+	(fork_execute): Get pex_obj from collect_execute, and pass it to
+	do_wait.
+	(scan_prog_file): Use pex routines rather than pipe/vfork/exec.
+	Only declare quit_handler if SIGQUIT is defined.
+	(scan_libraries): Likewise.
+	* collect2.h (collect_execute): Update declaration.
+	(collect_wait): Update declaration.
+	* tlink.c (tlink_execute): Get pex_obj from collect_execute, and
+	pass it to collect_wait.
+
 2005-03-29  Joseph S. Myers  <joseph@codesourcery.com>
 
 	PR c/20672
diff --git a/gcc/collect2.c b/gcc/collect2.c
index 90ad456b5fa2e02ccb5c0781058b1cc6be2ca606..063cb9fbde1c5d5fbb267c630c0b4cffdca6ad20 100644
--- a/gcc/collect2.c
+++ b/gcc/collect2.c
@@ -35,19 +35,6 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 #  define SIGCHLD SIGCLD
 #endif
 
-#ifdef vfork /* Autoconf may define this to fork for us.  */
-# define VFORK_STRING "fork"
-#else
-# define VFORK_STRING "vfork"
-#endif
-#ifdef HAVE_VFORK_H
-#include <vfork.h>
-#endif
-#ifdef VMS
-#define vfork() (decc$$alloc_vfork_blocks() >= 0 ? \
-               lib$get_current_invo_context(decc$$get_vfork_jmpbuf()) : -1)
-#endif /* VMS */
-
 #ifndef LIBRARY_PATH_ENV
 #define LIBRARY_PATH_ENV "LIBRARY_PATH"
 #endif
@@ -217,9 +204,6 @@ static struct head frame_tables;	/* list of frame unwind info tables */
 struct obstack temporary_obstack;
 char * temporary_firstobj;
 
-/* Holds the return value of pexecute and fork.  */
-int pid;
-
 /* Structure to hold all the directories in which to search for files to
    execute.  */
 
@@ -251,7 +235,7 @@ static char *find_a_file (struct path_prefix *, const char *);
 static void add_prefix (struct path_prefix *, const char *);
 static void prefix_from_env (const char *, struct path_prefix *);
 static void prefix_from_string (const char *, struct path_prefix *);
-static void do_wait (const char *);
+static void do_wait (const char *, struct pex_obj *);
 static void fork_execute (const char *, char **);
 static void maybe_unlink (const char *);
 static void add_to_list (struct head *, const char *);
@@ -420,7 +404,7 @@ handler (int signo)
 #endif
 
   signal (signo, SIG_DFL);
-  kill (getpid (), signo);
+  raise (signo);
 }
 
 
@@ -1501,11 +1485,14 @@ main (int argc, char **argv)
 /* Wait for a process to finish, and exit if a nonzero status is found.  */
 
 int
-collect_wait (const char *prog)
+collect_wait (const char *prog, struct pex_obj *pex)
 {
   int status;
 
-  pwait (pid, &status, 0);
+  if (!pex_get_status (pex, 1, &status))
+    fatal_perror ("can't get program status");
+  pex_free (pex);
+
   if (status)
     {
       if (WIFSIGNALED (status))
@@ -1524,9 +1511,9 @@ collect_wait (const char *prog)
 }
 
 static void
-do_wait (const char *prog)
+do_wait (const char *prog, struct pex_obj *pex)
 {
-  int ret = collect_wait (prog);
+  int ret = collect_wait (prog, pex);
   if (ret != 0)
     {
       error ("%s returned %d exit status", prog, ret);
@@ -1537,14 +1524,12 @@ do_wait (const char *prog)
 
 /* Execute a program, and wait for the reply.  */
 
-void
+struct pex_obj *
 collect_execute (const char *prog, char **argv, const char *redir)
 {
-  char *errmsg_fmt;
-  char *errmsg_arg;
-  int redir_handle = -1;
-  int stdout_save = -1;
-  int stderr_save = -1;
+  struct pex_obj *pex;
+  const char *errmsg;
+  int err;
 
   if (vflag || debug)
     {
@@ -1571,47 +1556,35 @@ collect_execute (const char *prog, char **argv, const char *redir)
   if (argv[0] == 0)
     fatal ("cannot find '%s'", prog);
 
-  if (redir)
-    {
-      /* Open response file.  */
-      redir_handle = open (redir, O_WRONLY | O_TRUNC | O_CREAT);
-
-      /* Duplicate the stdout and stderr file handles
-	 so they can be restored later.  */
-      stdout_save = dup (STDOUT_FILENO);
-      if (stdout_save == -1)
-	fatal_perror ("redirecting stdout: %s", redir);
-      stderr_save = dup (STDERR_FILENO);
-      if (stderr_save == -1)
-	fatal_perror ("redirecting stdout: %s", redir);
-
-      /* Redirect stdout & stderr to our response file.  */
-      dup2 (redir_handle, STDOUT_FILENO);
-      dup2 (redir_handle, STDERR_FILENO);
-    }
-
-  pid = pexecute (argv[0], argv, argv[0], NULL, &errmsg_fmt, &errmsg_arg,
-		  (PEXECUTE_FIRST | PEXECUTE_LAST | PEXECUTE_SEARCH));
+  pex = pex_init (0, "collect2", NULL);
+  if (pex == NULL)
+    fatal_perror ("pex_init failed");
 
-  if (redir)
+  errmsg = pex_run (pex,
+		    (PEX_LAST | PEX_SEARCH
+		     | (redir ? PEX_STDERR_TO_STDOUT : 0)),
+		    argv[0], argv, redir, NULL, &err);
+  if (errmsg != NULL)
     {
-      /* Restore stdout and stderr to their previous settings.  */
-      dup2 (stdout_save, STDOUT_FILENO);
-      dup2 (stderr_save, STDERR_FILENO);
-
-      /* Close response file.  */
-      close (redir_handle);
+      if (err != 0)
+	{
+	  errno = err;
+	  fatal_perror (errmsg);
+	}
+      else
+	fatal (errmsg);
     }
 
- if (pid == -1)
-   fatal_perror (errmsg_fmt, errmsg_arg);
+  return pex;
 }
 
 static void
 fork_execute (const char *prog, char **argv)
 {
-  collect_execute (prog, argv, NULL);
-  do_wait (prog);
+  struct pex_obj *pex;
+
+  pex = collect_execute (prog, argv, NULL);
+  do_wait (prog, pex);
 }
 
 /* Unlink a file unless we are debugging.  */
@@ -2033,11 +2006,15 @@ static void
 scan_prog_file (const char *prog_name, enum pass which_pass)
 {
   void (*int_handler) (int);
+#ifdef SIGQUIT
   void (*quit_handler) (int);
+#endif
   char *real_nm_argv[4];
   const char **nm_argv = (const char **) real_nm_argv;
   int argc = 0;
-  int pipe_fd[2];
+  struct pex_obj *pex;
+  const char *errmsg;
+  int err;
   char *p, buf[1024];
   FILE *inf;
 
@@ -2055,13 +2032,6 @@ scan_prog_file (const char *prog_name, enum pass which_pass)
   nm_argv[argc++] = prog_name;
   nm_argv[argc++] = (char *) 0;
 
-  if (pipe (pipe_fd) < 0)
-    fatal_perror ("pipe");
-
-  inf = fdopen (pipe_fd[0], "r");
-  if (inf == (FILE *) 0)
-    fatal_perror ("fdopen");
-
   /* Trace if needed.  */
   if (vflag)
     {
@@ -2077,35 +2047,30 @@ scan_prog_file (const char *prog_name, enum pass which_pass)
   fflush (stdout);
   fflush (stderr);
 
-  /* Spawn child nm on pipe.  */
-  pid = vfork ();
-  if (pid == -1)
-    fatal_perror (VFORK_STRING);
+  pex = pex_init (PEX_USE_PIPES, "collect2", NULL);
+  if (pex == NULL)
+    fatal_perror ("pex_init failed");
 
-  if (pid == 0)			/* child context */
+  errmsg = pex_run (pex, 0, nm_file_name, real_nm_argv, NULL, NULL, &err);
+  if (errmsg != NULL)
     {
-      /* setup stdout */
-      if (dup2 (pipe_fd[1], 1) < 0)
-	fatal_perror ("dup2 %d 1", pipe_fd[1]);
-
-      if (close (pipe_fd[0]) < 0)
-	fatal_perror ("close %d", pipe_fd[0]);
-
-      if (close (pipe_fd[1]) < 0)
-	fatal_perror ("close %d", pipe_fd[1]);
-
-      execv (nm_file_name, real_nm_argv);
-      fatal_perror ("execv %s", nm_file_name);
+      if (err != 0)
+	{
+	  errno = err;
+	  fatal_perror (errmsg);
+	}
+      else
+	fatal (errmsg);
     }
 
-  /* Parent context from here on.  */
   int_handler  = (void (*) (int)) signal (SIGINT,  SIG_IGN);
 #ifdef SIGQUIT
   quit_handler = (void (*) (int)) signal (SIGQUIT, SIG_IGN);
 #endif
 
-  if (close (pipe_fd[1]) < 0)
-    fatal_perror ("close %d", pipe_fd[1]);
+  inf = pex_read_output (pex, 0);
+  if (inf == NULL)
+    fatal_perror ("can't open nm output");
 
   if (debug)
     fprintf (stderr, "\nnm output with constructors/destructors.\n");
@@ -2179,10 +2144,7 @@ scan_prog_file (const char *prog_name, enum pass which_pass)
   if (debug)
     fprintf (stderr, "\n");
 
-  if (fclose (inf) != 0)
-    fatal_perror ("fclose");
-
-  do_wait (nm_file_name);
+  do_wait (nm_file_name, pex);
 
   signal (SIGINT,  int_handler);
 #ifdef SIGQUIT
@@ -2202,11 +2164,15 @@ scan_libraries (const char *prog_name)
   static struct head libraries;		/* list of shared libraries found */
   struct id *list;
   void (*int_handler) (int);
+#ifdef SIGQUIT
   void (*quit_handler) (int);
+#endif
   char *real_ldd_argv[4];
   const char **ldd_argv = (const char **) real_ldd_argv;
   int argc = 0;
-  int pipe_fd[2];
+  struct pex_obj *pex;
+  const char *errmsg;
+  int err;
   char buf[1024];
   FILE *inf;
 
@@ -2221,13 +2187,6 @@ scan_libraries (const char *prog_name)
   ldd_argv[argc++] = prog_name;
   ldd_argv[argc++] = (char *) 0;
 
-  if (pipe (pipe_fd) < 0)
-    fatal_perror ("pipe");
-
-  inf = fdopen (pipe_fd[0], "r");
-  if (inf == (FILE *) 0)
-    fatal_perror ("fdopen");
-
   /* Trace if needed.  */
   if (vflag)
     {
@@ -2243,35 +2202,30 @@ scan_libraries (const char *prog_name)
   fflush (stdout);
   fflush (stderr);
 
-  /* Spawn child ldd on pipe.  */
-  pid = vfork ();
-  if (pid == -1)
-    fatal_perror (VFORK_STRING);
+  pex = pex_init (PEX_USE_PIPES, "collect2", NULL);
+  if (pex == NULL)
+    fatal_perror ("pex_init failed");
 
-  if (pid == 0)			/* child context */
+  errmsg = pex_run (pex, 0, ldd_file_name, real_ldd_argv, NULL, NULL, &err);
+  if (errmsg != NULL)
     {
-      /* setup stdout */
-      if (dup2 (pipe_fd[1], 1) < 0)
-	fatal_perror ("dup2 %d 1", pipe_fd[1]);
-
-      if (close (pipe_fd[0]) < 0)
-	fatal_perror ("close %d", pipe_fd[0]);
-
-      if (close (pipe_fd[1]) < 0)
-	fatal_perror ("close %d", pipe_fd[1]);
-
-      execv (ldd_file_name, real_ldd_argv);
-      fatal_perror ("execv %s", ldd_file_name);
+      if (err != 0)
+	{
+	  errno = err;
+	  fatal_perror (errmsg);
+	}
+      else
+	fatal (errmsg);
     }
 
-  /* Parent context from here on.  */
   int_handler  = (void (*) (int)) signal (SIGINT,  SIG_IGN);
 #ifdef SIGQUIT
   quit_handler = (void (*) (int)) signal (SIGQUIT, SIG_IGN);
 #endif
 
-  if (close (pipe_fd[1]) < 0)
-    fatal_perror ("close %d", pipe_fd[1]);
+  inf = pex_read_output (pex, 0);
+  if (inf == NULL)
+    fatal_perror ("can't open ldd output");
 
   if (debug)
     notice ("\nldd output with constructors/destructors.\n");
@@ -2309,10 +2263,7 @@ scan_libraries (const char *prog_name)
   if (debug)
     fprintf (stderr, "\n");
 
-  if (fclose (inf) != 0)
-    fatal_perror ("fclose");
-
-  do_wait (ldd_file_name);
+  do_wait (ldd_file_name, pex);
 
   signal (SIGINT,  int_handler);
 #ifdef SIGQUIT
diff --git a/gcc/collect2.h b/gcc/collect2.h
index d25009bccaaffb5b06de4d68151ae8896fd0f6c3..9eabc63b25274d16a0c8cb492708d721a5d85db5 100644
--- a/gcc/collect2.h
+++ b/gcc/collect2.h
@@ -1,5 +1,5 @@
 /* Header file for collect/tlink routines.
-   Copyright (C) 1998, 2003, 2004 Free Software Foundation, Inc.
+   Copyright (C) 1998, 2003, 2004, 2005 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -23,11 +23,11 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 
 extern void do_tlink (char **, char **);
 
-extern void collect_execute (const char *, char **, const char *);
+extern struct pex_obj *collect_execute (const char *, char **, const char *);
 
 extern void collect_exit (int) ATTRIBUTE_NORETURN;
 
-extern int collect_wait (const char *);
+extern int collect_wait (const char *, struct pex_obj *);
 
 extern void dump_file (const char *);
 
diff --git a/gcc/tlink.c b/gcc/tlink.c
index f09a8652880622ff897d4c11ad4cf78635cd8db0..bf4e1d757b0f3dcfc9f9f30413a0a300a61e7e21 100644
--- a/gcc/tlink.c
+++ b/gcc/tlink.c
@@ -1,7 +1,7 @@
 /* Scan linker error messages for missing template instantiations and provide
    them.
 
-   Copyright (C) 1995, 1998, 1999, 2000, 2001, 2003, 2004
+   Copyright (C) 1995, 1998, 1999, 2000, 2001, 2003, 2004, 2005
    Free Software Foundation, Inc.
    Contributed by Jason Merrill (jason@cygnus.com).
 
@@ -281,8 +281,10 @@ tlink_init (void)
 static int
 tlink_execute (const char *prog, char **argv, const char *redir)
 {
-  collect_execute (prog, argv, redir);
-  return collect_wait (prog);
+  struct pex_obj *pex;
+
+  pex = collect_execute (prog, argv, redir);
+  return collect_wait (prog, pex);
 }
 
 static char *