+ 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]);
+ }
+ SLIST_FOREACH(p, &pidlist, next)
+ (void)posix_spawn_file_actions_addclose(&file_actions, p->fd);
+