aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ChangeLog7
-rw-r--r--Makefile.in1
-rw-r--r--configure.in2
-rw-r--r--lib/dup2.c132
-rw-r--r--lib/gnulib.mk11
-rw-r--r--m4/dup2.m476
-rw-r--r--m4/gl-comp.m45
-rw-r--r--src/ChangeLog5
-rw-r--r--src/sysdep.c31
9 files changed, 237 insertions, 33 deletions
diff --git a/ChangeLog b/ChangeLog
index 8a908f6b95..4bf89e3577 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
+2011-06-25 Paul Eggert <[email protected]>
+
+ Use gnulib's dup2 module instead of rolling our own.
+ * Makefile.in (GNULIB_MODULES): Add dup2.
+ * configure.in: Do not check for dup2; gnulib does that now.
+ * lib/dup2.c, m4/dup2.m4: New files, from gnulib.
+
2011-06-23 Paul Eggert <[email protected]>
* lib/getopt.c, lib/stat.c, m4/gl-comp.m4: Merge from gnulib.
diff --git a/Makefile.in b/Makefile.in
index 40d7610439..457b5d6472 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -334,6 +334,7 @@ DOS_gnulib_comp.m4 = gl-comp.m4
GNULIB_MODULES = \
alloca-opt \
careadlinkat crypto/md5 crypto/sha1 crypto/sha256 crypto/sha512 dtoastr \
+ dup2 \
filemode getloadavg getopt-gnu ignore-value intprops lstat mktime readlink \
socklen stdarg stdio strftime strtoumax symlink sys_stat
GNULIB_TOOL_FLAGS = \
diff --git a/configure.in b/configure.in
index fdeae8e615..0e9f031c16 100644
--- a/configure.in
+++ b/configure.in
@@ -2645,7 +2645,7 @@ esac
AC_SUBST(BLESSMAIL_TARGET)
-AC_CHECK_FUNCS(gethostname getdomainname dup2 \
+AC_CHECK_FUNCS(gethostname getdomainname \
rename closedir mkdir rmdir sysinfo getrusage get_current_dir_name \
random lrand48 logb frexp fmod rint cbrt ftime setsid \
strerror fpathconf select euidaccess getpagesize tzset setlocale \
diff --git a/lib/dup2.c b/lib/dup2.c
new file mode 100644
index 0000000000..e00dc7b2e3
--- /dev/null
+++ b/lib/dup2.c
@@ -0,0 +1,132 @@
+/* Duplicate an open file descriptor to a specified file descriptor.
+
+ Copyright (C) 1999, 2004-2007, 2009-2011 Free Software Foundation, Inc.
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+/* written by Paul Eggert */
+
+#include <config.h>
+
+/* Specification. */
+#include <unistd.h>
+
+#include <errno.h>
+#include <fcntl.h>
+
+#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
+/* Get declarations of the Win32 API functions. */
+# define WIN32_LEAN_AND_MEAN
+# include <windows.h>
+#endif
+
+#if HAVE_DUP2
+
+# undef dup2
+
+int
+rpl_dup2 (int fd, int desired_fd)
+{
+ int result;
+# if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
+ /* If fd is closed, mingw hangs on dup2 (fd, fd). If fd is open,
+ dup2 (fd, fd) returns 0, but all further attempts to use fd in
+ future dup2 calls will hang. */
+ if (fd == desired_fd)
+ {
+ if ((HANDLE) _get_osfhandle (fd) == INVALID_HANDLE_VALUE)
+ {
+ errno = EBADF;
+ return -1;
+ }
+ return fd;
+ }
+ /* Wine 1.0.1 return 0 when desired_fd is negative but not -1:
+ http://bugs.winehq.org/show_bug.cgi?id=21289 */
+ if (desired_fd < 0)
+ {
+ errno = EBADF;
+ return -1;
+ }
+# elif !defined __linux__
+ /* On Haiku, dup2 (fd, fd) mistakenly clears FD_CLOEXEC. */
+ if (fd == desired_fd)
+ return fcntl (fd, F_GETFL) == -1 ? -1 : fd;
+# endif
+ result = dup2 (fd, desired_fd);
+# ifdef __linux__
+ /* Correct a Linux return value.
+ <http://git.kernel.org/?p=linux/kernel/git/stable/linux-2.6.30.y.git;a=commitdiff;h=2b79bc4f7ebbd5af3c8b867968f9f15602d5f802>
+ */
+ if (fd == desired_fd && result == (unsigned int) -EBADF)
+ {
+ errno = EBADF;
+ result = -1;
+ }
+# endif
+ if (result == 0)
+ result = desired_fd;
+ /* Correct a cygwin 1.5.x errno value. */
+ else if (result == -1 && errno == EMFILE)
+ errno = EBADF;
+# if REPLACE_FCHDIR
+ if (fd != desired_fd && result != -1)
+ result = _gl_register_dup (fd, result);
+# endif
+ return result;
+}
+
+#else /* !HAVE_DUP2 */
+
+/* On older platforms, dup2 did not exist. */
+
+# ifndef F_DUPFD
+static int
+dupfd (int fd, int desired_fd)
+{
+ int duplicated_fd = dup (fd);
+ if (duplicated_fd < 0 || duplicated_fd == desired_fd)
+ return duplicated_fd;
+ else
+ {
+ int r = dupfd (fd, desired_fd);
+ int e = errno;
+ close (duplicated_fd);
+ errno = e;
+ return r;
+ }
+}
+# endif
+
+int
+dup2 (int fd, int desired_fd)
+{
+ int result = fcntl (fd, F_GETFL) < 0 ? -1 : fd;
+ if (result == -1 || fd == desired_fd)
+ return result;
+ close (desired_fd);
+# ifdef F_DUPFD
+ result = fcntl (fd, F_DUPFD, desired_fd);
+# if REPLACE_FCHDIR
+ if (0 <= result)
+ result = _gl_register_dup (fd, result);
+# endif
+# else
+ result = dupfd (fd, desired_fd);
+# endif
+ if (result == -1 && (errno == EMFILE || errno == EINVAL))
+ errno = EBADF;
+ return result;
+}
+#endif /* !HAVE_DUP2 */
diff --git a/lib/gnulib.mk b/lib/gnulib.mk
index 0fd7f520ac..18abe4536f 100644
--- a/lib/gnulib.mk
+++ b/lib/gnulib.mk
@@ -9,7 +9,7 @@
# the same distribution terms as the rest of that program.
#
# Generated by gnulib-tool.
-# Reproduce by: gnulib-tool --import --dir=. --lib=libgnu --source-base=lib --m4-base=m4 --doc-base=doc --tests-base=tests --aux-dir=. --makefile-name=gnulib.mk --conditional-dependencies --no-libtool --macro-prefix=gl --no-vc-files alloca-opt careadlinkat crypto/md5 crypto/sha1 crypto/sha256 crypto/sha512 dtoastr filemode getloadavg getopt-gnu ignore-value intprops lstat mktime readlink socklen stdarg stdio strftime strtoumax symlink sys_stat
+# Reproduce by: gnulib-tool --import --dir=. --lib=libgnu --source-base=lib --m4-base=m4 --doc-base=doc --tests-base=tests --aux-dir=. --makefile-name=gnulib.mk --conditional-dependencies --no-libtool --macro-prefix=gl --no-vc-files alloca-opt careadlinkat crypto/md5 crypto/sha1 crypto/sha256 crypto/sha512 dtoastr dup2 filemode getloadavg getopt-gnu ignore-value intprops lstat mktime readlink socklen stdarg stdio strftime strtoumax symlink sys_stat
MOSTLYCLEANFILES += core *.stackdump
@@ -159,6 +159,15 @@ EXTRA_libgnu_a_SOURCES += ftoastr.c
## end gnulib module dtoastr
+## begin gnulib module dup2
+
+
+EXTRA_DIST += dup2.c
+
+EXTRA_libgnu_a_SOURCES += dup2.c
+
+## end gnulib module dup2
+
## begin gnulib module filemode
libgnu_a_SOURCES += filemode.c
diff --git a/m4/dup2.m4 b/m4/dup2.m4
new file mode 100644
index 0000000000..8d7f62c887
--- /dev/null
+++ b/m4/dup2.m4
@@ -0,0 +1,76 @@
+#serial 13
+dnl Copyright (C) 2002, 2005, 2007, 2009-2011 Free Software Foundation, Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+
+AC_DEFUN([gl_FUNC_DUP2],
+[
+ AC_REQUIRE([gl_UNISTD_H_DEFAULTS])
+ AC_REQUIRE([AC_CANONICAL_HOST])
+ m4_ifdef([gl_FUNC_DUP2_OBSOLETE], [
+ AC_CHECK_FUNCS_ONCE([dup2])
+ if test $ac_cv_func_dup2 = no; then
+ HAVE_DUP2=0
+ AC_LIBOBJ([dup2])
+ fi
+ ], [
+ AC_DEFINE([HAVE_DUP2], [1], [Define to 1 if you have the 'dup2' function.])
+ ])
+ if test $HAVE_DUP2 = 1; then
+ AC_CACHE_CHECK([whether dup2 works], [gl_cv_func_dup2_works],
+ [AC_RUN_IFELSE([
+ AC_LANG_PROGRAM([[#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>]],
+ [int result = 0;
+#ifdef FD_CLOEXEC
+ if (fcntl (1, F_SETFD, FD_CLOEXEC) == -1)
+ result |= 1;
+#endif
+ if (dup2 (1, 1) == 0)
+ result |= 2;
+#ifdef FD_CLOEXEC
+ if (fcntl (1, F_GETFD) != FD_CLOEXEC)
+ result |= 4;
+#endif
+ close (0);
+ if (dup2 (0, 0) != -1)
+ result |= 8;
+ /* Many gnulib modules require POSIX conformance of EBADF. */
+ if (dup2 (2, 1000000) == -1 && errno != EBADF)
+ result |= 16;
+ return result;
+ ])
+ ],
+ [gl_cv_func_dup2_works=yes], [gl_cv_func_dup2_works=no],
+ [case "$host_os" in
+ mingw*) # on this platform, dup2 always returns 0 for success
+ gl_cv_func_dup2_works=no;;
+ cygwin*) # on cygwin 1.5.x, dup2(1,1) returns 0
+ gl_cv_func_dup2_works=no;;
+ linux*) # On linux between 2008-07-27 and 2009-05-11, dup2 of a
+ # closed fd may yield -EBADF instead of -1 / errno=EBADF.
+ gl_cv_func_dup2_works=no;;
+ freebsd*) # on FreeBSD 6.1, dup2(1,1000000) gives EMFILE, not EBADF.
+ gl_cv_func_dup2_works=no;;
+ haiku*) # on Haiku alpha 2, dup2(1, 1) resets FD_CLOEXEC.
+ gl_cv_func_dup2_works=no;;
+ *) gl_cv_func_dup2_works=yes;;
+ esac])
+ ])
+ if test "$gl_cv_func_dup2_works" = no; then
+ gl_REPLACE_DUP2
+ fi
+ fi
+])
+
+AC_DEFUN([gl_REPLACE_DUP2],
+[
+ AC_REQUIRE([gl_UNISTD_H_DEFAULTS])
+ AC_CHECK_FUNCS_ONCE([dup2])
+ if test $ac_cv_func_dup2 = yes; then
+ REPLACE_DUP2=1
+ fi
+ AC_LIBOBJ([dup2])
+])
diff --git a/m4/gl-comp.m4 b/m4/gl-comp.m4
index 84b3a0962e..16bb02e686 100644
--- a/m4/gl-comp.m4
+++ b/m4/gl-comp.m4
@@ -37,6 +37,7 @@ AC_DEFUN([gl_EARLY],
# Code from module crypto/sha512:
# Code from module dosname:
# Code from module dtoastr:
+ # Code from module dup2:
# Code from module extensions:
AC_REQUIRE([gl_USE_SYSTEM_EXTENSIONS])
# Code from module filemode:
@@ -102,6 +103,8 @@ gl_SHA1
gl_SHA256
gl_SHA512
AC_REQUIRE([gl_C99_STRTOLD])
+gl_FUNC_DUP2
+gl_UNISTD_MODULE_INDICATOR([dup2])
gl_FILEMODE
gl_GETLOADAVG
if test $HAVE_GETLOADAVG = 0; then
@@ -404,6 +407,7 @@ AC_DEFUN([gl_FILE_LIST], [
lib/careadlinkat.h
lib/dosname.h
lib/dtoastr.c
+ lib/dup2.c
lib/filemode.c
lib/filemode.h
lib/ftoastr.c
@@ -453,6 +457,7 @@ AC_DEFUN([gl_FILE_LIST], [
m4/00gnulib.m4
m4/alloca.m4
m4/c-strtod.m4
+ m4/dup2.m4
m4/extensions.m4
m4/filemode.m4
m4/getloadavg.m4
diff --git a/src/ChangeLog b/src/ChangeLog
index b8b3d2a1a9..792208f7c2 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,8 @@
+2011-06-25 Paul Eggert <[email protected]>
+
+ Use gnulib's dup2 module instead of rolling our own.
+ * sysdep.c (dup2) [!HAVE_DUP2]: Remove; gnulib now does this.
+
2011-06-24 Juanma Barranquero <[email protected]>
Move DEFSYM to lisp.h and use everywhere.
diff --git a/src/sysdep.c b/src/sysdep.c
index 5ad3389dd8..3a73b1a467 100644
--- a/src/sysdep.c
+++ b/src/sysdep.c
@@ -2012,37 +2012,6 @@ perror (void)
}
#endif /* HPUX and not HAVE_PERROR */
-#ifndef HAVE_DUP2
-
-/*
- * Emulate BSD dup2. First close newd if it already exists.
- * Then, attempt to dup oldd. If not successful, call dup2 recursively
- * until we are, then close the unsuccessful ones.
- */
-
-int
-dup2 (int oldd, int newd)
-{
- register int fd, ret;
-
- emacs_close (newd);
-
-#ifdef F_DUPFD
- return fcntl (oldd, F_DUPFD, newd);
-#else
- fd = dup (old);
- if (fd == -1)
- return -1;
- if (fd == new)
- return new;
- ret = dup2 (old,new);
- emacs_close (fd);
- return ret;
-#endif
-}
-
-#endif /* not HAVE_DUP2 */
-
/*
* Gettimeofday. Simulate as much as possible. Only accurate
* to nearest second. Emacs doesn't use tzp so ignore it for now.