+
+ psl = XNEW (struct status_list);
+ psl->pid = cpid;
+ psl->status = *status;
+ if (time != NULL)
+ psl->time = pt;
+ psl->next = (struct status_list *) obj->sysdep;
+ obj->sysdep = (void *) psl;
+ }
+}
+
+#endif /* ! defined (HAVE_WAITPID) */
+#endif /* ! defined (HAVE_WAIT4) */
+
+static int pex_unix_open_read (struct pex_obj *, const char *, int);
+static int pex_unix_open_write (struct pex_obj *, const char *, int, int);
+static pid_t pex_unix_exec_child (struct pex_obj *, int, const char *,
+ char * const *, char * const *,
+ int, int, int, int,
+ const char **, int *);
+static int pex_unix_close (struct pex_obj *, int);
+static int pex_unix_wait (struct pex_obj *, pid_t, int *, struct pex_time *,
+ int, const char **, int *);
+static int pex_unix_pipe (struct pex_obj *, int *, int);
+static FILE *pex_unix_fdopenr (struct pex_obj *, int, int);
+static FILE *pex_unix_fdopenw (struct pex_obj *, int, int);
+static void pex_unix_cleanup (struct pex_obj *);
+
+/* The list of functions we pass to the common routines. */
+
+const struct pex_funcs funcs =
+{
+ pex_unix_open_read,
+ pex_unix_open_write,
+ pex_unix_exec_child,
+ pex_unix_close,
+ pex_unix_wait,
+ pex_unix_pipe,
+ pex_unix_fdopenr,
+ pex_unix_fdopenw,
+ pex_unix_cleanup
+};
+
+/* Return a newly initialized pex_obj structure. */
+
+struct pex_obj *
+pex_init (int flags, const char *pname, const char *tempbase)
+{
+ return pex_init_common (flags, pname, tempbase, &funcs);
+}
+
+/* Open a file for reading. */
+
+static int
+pex_unix_open_read (struct pex_obj *obj ATTRIBUTE_UNUSED, const char *name,
+ int binary ATTRIBUTE_UNUSED)
+{
+ return open (name, O_RDONLY);
+}
+
+/* Open a file for writing. */
+
+static int
+pex_unix_open_write (struct pex_obj *obj ATTRIBUTE_UNUSED, const char *name,
+ int binary ATTRIBUTE_UNUSED, int append)
+{
+ /* Note that we can't use O_EXCL here because gcc may have already
+ created the temporary file via make_temp_file. */
+ return open (name, O_WRONLY | O_CREAT
+ | (append ? O_APPEND : O_TRUNC), PUBLIC_MODE);
+}
+
+/* Close a file. */
+
+static int
+pex_unix_close (struct pex_obj *obj ATTRIBUTE_UNUSED, int fd)
+{
+ return close (fd);
+}
+
+/* Execute a child. */
+
+#if defined(HAVE_SPAWNVE) && defined(HAVE_SPAWNVPE)
+/* Implementation of pex->exec_child using the Cygwin spawn operation. */
+
+/* Subroutine of pex_unix_exec_child. Move OLD_FD to a new file descriptor
+ to be stored in *PNEW_FD, save the flags in *PFLAGS, and arrange for the
+ saved copy to be close-on-exec. Move CHILD_FD into OLD_FD. If CHILD_FD
+ is -1, OLD_FD is to be closed. Return -1 on error. */
+
+static int
+save_and_install_fd(int *pnew_fd, int *pflags, int old_fd, int child_fd)
+{
+ int new_fd, flags;
+
+ flags = fcntl (old_fd, F_GETFD);
+
+ /* If we could not retrieve the flags, then OLD_FD was not open. */
+ if (flags < 0)
+ {
+ new_fd = -1, flags = 0;
+ if (child_fd >= 0 && dup2 (child_fd, old_fd) < 0)
+ return -1;
+ }
+ /* If we wish to close OLD_FD, just mark it CLOEXEC. */
+ else if (child_fd == -1)
+ {
+ new_fd = old_fd;
+ if ((flags & FD_CLOEXEC) == 0 && fcntl (old_fd, F_SETFD, FD_CLOEXEC) < 0)
+ return -1;
+ }
+ /* Otherwise we need to save a copy of OLD_FD before installing CHILD_FD. */
+ else
+ {
+#ifdef F_DUPFD_CLOEXEC
+ new_fd = fcntl (old_fd, F_DUPFD_CLOEXEC, 3);
+ if (new_fd < 0)
+ return -1;
+#else
+ /* Prefer F_DUPFD over dup in order to avoid getting a new fd
+ in the range 0-2, right where a new stderr fd might get put. */
+ new_fd = fcntl (old_fd, F_DUPFD, 3);
+ if (new_fd < 0)
+ return -1;
+ if (fcntl (new_fd, F_SETFD, FD_CLOEXEC) < 0)
+ return -1;
+#endif
+ if (dup2 (child_fd, old_fd) < 0)
+ return -1;
+ }
+
+ *pflags = flags;
+ if (pnew_fd)
+ *pnew_fd = new_fd;
+ else if (new_fd != old_fd)
+ abort ();
+
+ return 0;
+}
+
+/* Subroutine of pex_unix_exec_child. Move SAVE_FD back to OLD_FD
+ restoring FLAGS. If SAVE_FD < 0, OLD_FD is to be closed. */
+
+static int
+restore_fd(int old_fd, int save_fd, int flags)
+{
+ /* For SAVE_FD < 0, all we have to do is restore the
+ "closed-ness" of the original. */
+ if (save_fd < 0)
+ return close (old_fd);
+
+ /* For SAVE_FD == OLD_FD, all we have to do is restore the
+ original setting of the CLOEXEC flag. */
+ if (save_fd == old_fd)
+ {
+ if (flags & FD_CLOEXEC)
+ return 0;
+ return fcntl (old_fd, F_SETFD, flags);
+ }
+
+ /* Otherwise we have to move the descriptor back, restore the flags,
+ and close the saved copy. */
+#ifdef HAVE_DUP3
+ if (flags == FD_CLOEXEC)
+ {
+ if (dup3 (save_fd, old_fd, O_CLOEXEC) < 0)
+ return -1;