Back to index

nagios-plugins  1.4.16
Defines | Functions
fcntl.c File Reference
#include <config.h>
#include <fcntl.h>
#include <errno.h>
#include <limits.h>
#include <stdarg.h>
#include <unistd.h>

Go to the source code of this file.

Defines

#define rpl_fcntl   fcntl

Functions

int rpl_fcntl (int fd, int action,...)

Define Documentation

#define rpl_fcntl   fcntl

Definition at line 31 of file fcntl.c.


Function Documentation

int rpl_fcntl ( int  fd,
int  action,
  ... 
)

Definition at line 166 of file fcntl.c.

{
  va_list arg;
  int result = -1;
  va_start (arg, action);
  switch (action)
    {

#if !HAVE_FCNTL
    case F_DUPFD:
      {
        int target = va_arg (arg, int);
        result = dupfd (fd, target, 0);
        break;
      }
#elif FCNTL_DUPFD_BUGGY || REPLACE_FCHDIR
    case F_DUPFD:
      {
        int target = va_arg (arg, int);
        /* Detect invalid target; needed for cygwin 1.5.x.  */
        if (target < 0 || getdtablesize () <= target)
          errno = EINVAL;
        else
          {
            result = fcntl (fd, action, target);
# if REPLACE_FCHDIR
            if (0 <= result)
              result = _gl_register_dup (fd, result);
# endif
          }
        break;
      } /* F_DUPFD */
#endif /* FCNTL_DUPFD_BUGGY || REPLACE_FCHDIR */

    case F_DUPFD_CLOEXEC:
      {
        int target = va_arg (arg, int);

#if !HAVE_FCNTL
        result = dupfd (fd, target, O_CLOEXEC);
        break;
#else /* HAVE_FCNTL */
        /* Try the system call first, if the headers claim it exists
           (that is, if GNULIB_defined_F_DUPFD_CLOEXEC is 0), since we
           may be running with a glibc that has the macro but with an
           older kernel that does not support it.  Cache the
           information on whether the system call really works, but
           avoid caching failure if the corresponding F_DUPFD fails
           for any reason.  0 = unknown, 1 = yes, -1 = no.  */
        static int have_dupfd_cloexec = GNULIB_defined_F_DUPFD_CLOEXEC ? -1 : 0;
        if (0 <= have_dupfd_cloexec)
          {
            result = fcntl (fd, action, target);
            if (0 <= result || errno != EINVAL)
              {
                have_dupfd_cloexec = 1;
# if REPLACE_FCHDIR
                if (0 <= result)
                  result = _gl_register_dup (fd, result);
# endif
              }
            else
              {
                result = rpl_fcntl (fd, F_DUPFD, target);
                if (result < 0)
                  break;
                have_dupfd_cloexec = -1;
              }
          }
        else
          result = rpl_fcntl (fd, F_DUPFD, target);
        if (0 <= result && have_dupfd_cloexec == -1)
          {
            int flags = fcntl (result, F_GETFD);
            if (flags < 0 || fcntl (result, F_SETFD, flags | FD_CLOEXEC) == -1)
              {
                int saved_errno = errno;
                close (result);
                errno = saved_errno;
                result = -1;
              }
          }
        break;
#endif /* HAVE_FCNTL */
      } /* F_DUPFD_CLOEXEC */

#if !HAVE_FCNTL
    case F_GETFD:
      {
# if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
        HANDLE handle = (HANDLE) _get_osfhandle (fd);
        DWORD flags;
        if (handle == INVALID_HANDLE_VALUE
            || GetHandleInformation (handle, &flags) == 0)
          errno = EBADF;
        else
          result = (flags & HANDLE_FLAG_INHERIT) ? 0 : FD_CLOEXEC;
# else /* !W32 */
        /* Use dup2 to reject invalid file descriptors.  No way to
           access this information, so punt.  */
        if (0 <= dup2 (fd, fd))
          result = 0;
# endif /* !W32 */
        break;
      } /* F_GETFD */
#endif /* !HAVE_FCNTL */

      /* Implementing F_SETFD on mingw is not trivial - there is no
         API for changing the O_NOINHERIT bit on an fd, and merely
         changing the HANDLE_FLAG_INHERIT bit on the underlying handle
         can lead to odd state.  It may be possible by duplicating the
         handle, using _open_osfhandle with the right flags, then
         using dup2 to move the duplicate onto the original, but that
         is not supported for now.  */

    default:
      {
#if HAVE_FCNTL
        void *p = va_arg (arg, void *);
        result = fcntl (fd, action, p);
#else
        errno = EINVAL;
#endif
        break;
      }
    }
  va_end (arg);
  return result;
}

Here is the call graph for this function: