summaryrefslogtreecommitdiffstats
path: root/dbus/dbus-sysdeps-unix.c
diff options
context:
space:
mode:
Diffstat (limited to 'dbus/dbus-sysdeps-unix.c')
-rw-r--r--dbus/dbus-sysdeps-unix.c42
1 files changed, 42 insertions, 0 deletions
diff --git a/dbus/dbus-sysdeps-unix.c b/dbus/dbus-sysdeps-unix.c
index 2e129826..5f94c6a5 100644
--- a/dbus/dbus-sysdeps-unix.c
+++ b/dbus/dbus-sysdeps-unix.c
@@ -2712,6 +2712,48 @@ _dbus_close (int fd,
}
/**
+ * Duplicates a file descriptor. Makes sure the fd returned is >= 3
+ * (i.e. avoids stdin/stdout/stderr). Sets O_CLOEXEC.
+ *
+ * @param fd the file descriptor to duplicate
+ * @returns duplicated file descriptor
+ * */
+int
+_dbus_dup(int fd,
+ DBusError *error)
+{
+ int new_fd;
+
+#ifdef F_DUPFD_CLOEXEC
+ dbus_bool_t cloexec_done;
+
+ new_fd = fcntl(fd, F_DUPFD_CLOEXEC, 3);
+ cloexec_done = new_fd >= 0;
+
+ if (new_fd < 0 && errno == EINVAL)
+#endif
+ {
+ new_fd = fcntl(fd, F_DUPFD, 3);
+ }
+
+ if (new_fd < 0) {
+
+ dbus_set_error (error, _dbus_error_from_errno (errno),
+ "Could not duplicate fd %d", fd);
+ return -1;
+ }
+
+#ifndef F_DUPFD_CLOEXEC
+ if (!cloexec_done)
+#endif
+ {
+ _dbus_fd_set_close_on_exec(new_fd);
+ }
+
+ return new_fd;
+}
+
+/**
* Sets a file descriptor to be nonblocking.
*
* @param fd the file descriptor.