static char *
process_substitute (string, open_for_read_in_child)
     char *string;
     int open_for_read_in_child;
{
  char *pathname;
  int fd, result;
  pid_t old_pid, pid;
#if defined (HAVE_DEV_FD)
  int parent_pipe_fd, child_pipe_fd;
  int fildes[2];
#endif /* HAVE_DEV_FD */
#if defined (JOB_CONTROL)
  pid_t old_pipeline_pgrp;
#endif

  if (!string || !*string || wordexp_only)
    return ((char *)NULL);

#if !defined (HAVE_DEV_FD)
  pathname = make_named_pipe ();
#else /* HAVE_DEV_FD */
  if (pipe (fildes) < 0)
    {
      sys_error ("%s", _("cannot make pipe for process substitution"));
      return ((char *)NULL);
    }
  /* If OPEN_FOR_READ_IN_CHILD == 1, we want to use the write end of
     the pipe in the parent, otherwise the read end. */
  parent_pipe_fd = fildes[open_for_read_in_child];
  child_pipe_fd = fildes[1 - open_for_read_in_child];
  /* Move the parent end of the pipe to some high file descriptor, to
     avoid clashes with FDs used by the script. */
  parent_pipe_fd = move_to_high_fd (parent_pipe_fd, 1, 64);

  pathname = make_dev_fd_filename (parent_pipe_fd);
#endif /* HAVE_DEV_FD */

  if (pathname == 0)
    {
      sys_error ("%s", _("cannot make pipe for process substitution"));
      return ((char *)NULL);
    }

  old_pid = last_made_pid;

#if defined (JOB_CONTROL)
  old_pipeline_pgrp = pipeline_pgrp;
  if (pipeline_pgrp == 0 || (subshell_environment & (SUBSHELL_PIPE|SUBSHELL_FORK|SUBSHELL_ASYNC)) == 0)
    pipeline_pgrp = shell_pgrp;
  save_pipeline (1);
#endif /* JOB_CONTROL */

  pid = make_child ((char *)NULL, 1);
  if (pid == 0)
    {
      reset_terminating_signals ();	/* XXX */
      free_pushed_string_input ();
      /* Cancel traps, in trap.c. */
      restore_original_signals ();	/* XXX - what about special builtins? bash-4.2 */
      QUIT;	/* catch any interrupts we got post-fork */
      setup_async_signals ();
      subshell_environment |= SUBSHELL_COMSUB|SUBSHELL_PROCSUB;

      /* if we're expanding a redirection, we shouldn't have access to the
	 temporary environment, but commands in the subshell should have
	 access to their own temporary environment. */
      if (expanding_redir)
        flush_temporary_env ();
    }

#if defined (JOB_CONTROL)
  set_sigchld_handler ();
  stop_making_children ();
  /* XXX - should we only do this in the parent? (as in command subst) */
  pipeline_pgrp = old_pipeline_pgrp;
#else
  stop_making_children ();
#endif /* JOB_CONTROL */

  if (pid < 0)
    {
      sys_error ("%s", _("cannot make child for process substitution"));
      free (pathname);
#if defined (HAVE_DEV_FD)
      close (parent_pipe_fd);
      close (child_pipe_fd);
#endif /* HAVE_DEV_FD */
      return ((char *)NULL);
    }

  if (pid > 0)
    {
#if defined (JOB_CONTROL)
      if (last_procsub_child)
	discard_last_procsub_child ();
      last_procsub_child = restore_pipeline (0);
#endif

#if !defined (HAVE_DEV_FD)
      fifo_list[nfifo-1].proc = pid;
#endif

      last_made_pid = old_pid;

#if defined (JOB_CONTROL) && defined (PGRP_PIPE)
      close_pgrp_pipe ();
#endif /* JOB_CONTROL && PGRP_PIPE */

#if defined (HAVE_DEV_FD)
      close (child_pipe_fd);
#endif /* HAVE_DEV_FD */

      return (pathname);
    }

  set_sigint_handler ();

#if defined (JOB_CONTROL)
  set_job_control (0);
#endif /* JOB_CONTROL */

#if !defined (HAVE_DEV_FD)
  /* Open the named pipe in the child. */
  fd = open (pathname, open_for_read_in_child ? O_RDONLY : O_WRONLY);
  if (fd < 0)
    {
      /* Two separate strings for ease of translation. */
      if (open_for_read_in_child)
	sys_error (_("cannot open named pipe %s for reading"), pathname);
      else
	sys_error (_("cannot open named pipe %s for writing"), pathname);

      exit (127);
    }
  if (open_for_read_in_child)
    {
      if (sh_unset_nodelay_mode (fd) < 0)
	{
	  sys_error (_("cannot reset nodelay mode for fd %d"), fd);
	  exit (127);
	}
    }
#else /* HAVE_DEV_FD */
  fd = child_pipe_fd;
#endif /* HAVE_DEV_FD */

  /* Discard  buffered stdio output before replacing the underlying file
     descriptor. */
  if (open_for_read_in_child == 0)
    fpurge (stdout);

  if (dup2 (fd, open_for_read_in_child ? 0 : 1) < 0)
    {
      sys_error (_("cannot duplicate named pipe %s as fd %d"), pathname,
	open_for_read_in_child ? 0 : 1);
      exit (127);
    }

  if (fd != (open_for_read_in_child ? 0 : 1))
    close (fd);

  /* Need to close any files that this process has open to pipes inherited
     from its parent. */
  if (current_fds_to_close)
    {
      close_fd_bitmap (current_fds_to_close);
      current_fds_to_close = (struct fd_bitmap *)NULL;
    }

#if defined (HAVE_DEV_FD)
  /* Make sure we close the parent's end of the pipe and clear the slot
     in the fd list so it is not closed later, if reallocated by, for
     instance, pipe(2). */
  close (parent_pipe_fd);
  dev_fd_list[parent_pipe_fd] = 0;
#endif /* HAVE_DEV_FD */

  /* subshells shouldn't have this flag, which controls using the temporary
     environment for variable lookups.  We have already flushed the temporary
     environment above in the case we're expanding a redirection, so processes
     executed by this command need to be able to set it independently of their
     parent. */
  expanding_redir = 0;

  subshell_level++;
  result = parse_and_execute (string, "process substitution", (SEVAL_NONINT|SEVAL_NOHIST));
  subshell_level--;

#if !defined (HAVE_DEV_FD)
  /* Make sure we close the named pipe in the child before we exit. */
  close (open_for_read_in_child ? 0 : 1);
#endif /* !HAVE_DEV_FD */

  last_command_exit_value = result;
  result = run_exit_trap ();
  exit (result);
  /*NOTREACHED*/