+ (void)_close(pdes[1]);
+ return (NULL);
+ }
+
++ if ((cur = malloc(sizeof(struct pid))) == NULL) {
++ (void)fclose(iop);
++ (void)_close(other);
++ return (NULL);
++ }
++
++ if ((err = posix_spawn_file_actions_init(&file_actions)) != 0) {
++ (void)fclose(iop);
++ (void)_close(other);
++ free(cur);
++ errno = err;
++ return (NULL);
++ }
++ if (*type == 'r') {
++ /*
++ * The dup2() to STDIN_FILENO is repeated to avoid
++ * writing to pdes[1], which might corrupt the
++ * parent's copy. This isn't good enough in
++ * general, since the _exit() is no return, so
++ * the compiler is free to corrupt all the local
++ * variables.
++ */
++ (void)posix_spawn_file_actions_addclose(&file_actions, pdes[0]);
++ if (pdes[1] != STDOUT_FILENO) {
++ (void)posix_spawn_file_actions_adddup2(&file_actions, pdes[1], STDOUT_FILENO);
++ (void)posix_spawn_file_actions_addclose(&file_actions, pdes[1]);
++ if (twoway)
++ (void)posix_spawn_file_actions_adddup2(&file_actions, STDOUT_FILENO, STDIN_FILENO);
++ } else if (twoway && (pdes[1] != STDIN_FILENO))
++ (void)posix_spawn_file_actions_adddup2(&file_actions, pdes[1], STDIN_FILENO);
++ } else {
++ if (pdes[0] != STDIN_FILENO) {
++ (void)posix_spawn_file_actions_adddup2(&file_actions, pdes[0], STDIN_FILENO);
++ (void)posix_spawn_file_actions_addclose(&file_actions, pdes[0]);
++ }
++ (void)posix_spawn_file_actions_addclose(&file_actions, pdes[1]);
++ }
++ for (p = pidlist; p; p = p->next) {
++ (void)posix_spawn_file_actions_addclose(&file_actions, p->fd);
++ }
++
+ argv[0] = "sh";
+ argv[1] = "-c";
+ argv[2] = (char *)command;
+ argv[3] = NULL;
+
+- THREAD_LOCK();
+- switch (pid = vfork()) {
+- case -1: /* Error. */
+- THREAD_UNLOCK();
+- (void)_close(pdes[0]);
+- (void)_close(pdes[1]);
++ err = posix_spawn(&pid, _PATH_BSHELL, &file_actions, NULL, argv, environ);
++ posix_spawn_file_actions_destroy(&file_actions);
++
++ if (err == ENOMEM || err == EAGAIN) { /* as if fork failed */
++ (void)fclose(iop);
++ (void)_close(other);
+ free(cur);
++ errno = err;
+ return (NULL);
+- /* NOTREACHED */
+- case 0: /* Child. */
+- if (*type == 'r') {
+- /*
+- * The _dup2() to STDIN_FILENO is repeated to avoid
+- * writing to pdes[1], which might corrupt the
+- * parent's copy. This isn't good enough in
+- * general, since the _exit() is no return, so
+- * the compiler is free to corrupt all the local
+- * variables.
+- */
+- (void)_close(pdes[0]);
+- if (pdes[1] != STDOUT_FILENO) {
+- (void)_dup2(pdes[1], STDOUT_FILENO);
+- (void)_close(pdes[1]);
+- if (twoway)
+- (void)_dup2(STDOUT_FILENO, STDIN_FILENO);
+- } else if (twoway && (pdes[1] != STDIN_FILENO))
+- (void)_dup2(pdes[1], STDIN_FILENO);
+- } else {
+- if (pdes[0] != STDIN_FILENO) {
+- (void)_dup2(pdes[0], STDIN_FILENO);
+- (void)_close(pdes[0]);
+- }
+- (void)_close(pdes[1]);
+- }
+- for (p = pidlist; p; p = p->next) {