Back to index

nagios-plugins  1.4.16
dup2.c
Go to the documentation of this file.
00001 /* Duplicate an open file descriptor to a specified file descriptor.
00002 
00003    Copyright (C) 1999, 2004-2007, 2009-2010 Free Software Foundation, Inc.
00004 
00005    This program is free software: you can redistribute it and/or modify
00006    it under the terms of the GNU General Public License as published by
00007    the Free Software Foundation; either version 3 of the License, or
00008    (at your option) any later version.
00009 
00010    This program is distributed in the hope that it will be useful,
00011    but WITHOUT ANY WARRANTY; without even the implied warranty of
00012    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013    GNU General Public License for more details.
00014 
00015    You should have received a copy of the GNU General Public License
00016    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
00017 
00018 /* written by Paul Eggert */
00019 
00020 #include <config.h>
00021 
00022 /* Specification.  */
00023 #include <unistd.h>
00024 
00025 #include <errno.h>
00026 #include <fcntl.h>
00027 
00028 #if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
00029 /* Get declarations of the Win32 API functions.  */
00030 # define WIN32_LEAN_AND_MEAN
00031 # include <windows.h>
00032 #endif
00033 
00034 #if HAVE_DUP2
00035 
00036 # undef dup2
00037 
00038 int
00039 rpl_dup2 (int fd, int desired_fd)
00040 {
00041   int result;
00042 # if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
00043   /* If fd is closed, mingw hangs on dup2 (fd, fd).  If fd is open,
00044      dup2 (fd, fd) returns 0, but all further attempts to use fd in
00045      future dup2 calls will hang.  */
00046   if (fd == desired_fd)
00047     {
00048       if ((HANDLE) _get_osfhandle (fd) == INVALID_HANDLE_VALUE)
00049         {
00050           errno = EBADF;
00051           return -1;
00052         }
00053       return fd;
00054     }
00055   /* Wine 1.0.1 return 0 when desired_fd is negative but not -1:
00056      http://bugs.winehq.org/show_bug.cgi?id=21289 */
00057   if (desired_fd < 0)
00058     {
00059       errno = EBADF;
00060       return -1;
00061     }
00062 # endif
00063   result = dup2 (fd, desired_fd);
00064 # ifdef __linux__
00065   /* Correct a Linux return value.
00066      <http://git.kernel.org/?p=linux/kernel/git/stable/linux-2.6.30.y.git;a=commitdiff;h=2b79bc4f7ebbd5af3c8b867968f9f15602d5f802>
00067    */
00068   if (fd == desired_fd && result == (unsigned int) -EBADF)
00069     {
00070       errno = EBADF;
00071       result = -1;
00072     }
00073 # endif
00074   if (result == 0)
00075     result = desired_fd;
00076   /* Correct a cygwin 1.5.x errno value.  */
00077   else if (result == -1 && errno == EMFILE)
00078     errno = EBADF;
00079 # if REPLACE_FCHDIR
00080   if (fd != desired_fd && result != -1)
00081     result = _gl_register_dup (fd, result);
00082 # endif
00083   return result;
00084 }
00085 
00086 #else /* !HAVE_DUP2 */
00087 
00088 /* On older platforms, dup2 did not exist.  */
00089 
00090 # ifndef F_DUPFD
00091 static int
00092 dupfd (int fd, int desired_fd)
00093 {
00094   int duplicated_fd = dup (fd);
00095   if (duplicated_fd < 0 || duplicated_fd == desired_fd)
00096     return duplicated_fd;
00097   else
00098     {
00099       int r = dupfd (fd, desired_fd);
00100       int e = errno;
00101       close (duplicated_fd);
00102       errno = e;
00103       return r;
00104     }
00105 }
00106 # endif
00107 
00108 int
00109 dup2 (int fd, int desired_fd)
00110 {
00111   int result = fcntl (fd, F_GETFL) < 0 ? -1 : fd;
00112   if (result == -1 || fd == desired_fd)
00113     return result;
00114   close (desired_fd);
00115 # ifdef F_DUPFD
00116   result = fcntl (fd, F_DUPFD, desired_fd);
00117 #  if REPLACE_FCHDIR
00118   if (0 <= result)
00119     result = _gl_register_dup (fd, result);
00120 #  endif
00121 # else
00122   result = dupfd (fd, desired_fd);
00123 # endif
00124   if (result == -1 && (errno == EMFILE || errno == EINVAL))
00125     errno = EBADF;
00126   return result;
00127 }
00128 #endif /* !HAVE_DUP2 */