Blame lib/freopen.c

Packit 33f14e
/* Open a stream to a file.
Packit 33f14e
   Copyright (C) 2007-2017 Free Software Foundation, Inc.
Packit 33f14e
Packit 33f14e
   This program is free software: you can redistribute it and/or modify
Packit 33f14e
   it under the terms of the GNU General Public License as published by
Packit 33f14e
   the Free Software Foundation; either version 3 of the License, or
Packit 33f14e
   (at your option) any later version.
Packit 33f14e
Packit 33f14e
   This program is distributed in the hope that it will be useful,
Packit 33f14e
   but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 33f14e
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit 33f14e
   GNU General Public License for more details.
Packit 33f14e
Packit 33f14e
   You should have received a copy of the GNU General Public License
Packit 33f14e
   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
Packit 33f14e
Packit 33f14e
/* Written by Bruno Haible <bruno@clisp.org>, 2007.  */
Packit 33f14e
Packit 33f14e
/* If the user's config.h happens to include <stdio.h>, let it include only
Packit 33f14e
   the system's <stdio.h> here, so that orig_freopen doesn't recurse to
Packit 33f14e
   rpl_freopen.  */
Packit 33f14e
#define _GL_ALREADY_INCLUDING_STDIO_H
Packit 33f14e
#include <config.h>
Packit 33f14e
Packit 33f14e
/* Get the original definition of freopen.  It might be defined as a macro.  */
Packit 33f14e
#include <stdio.h>
Packit 33f14e
#undef _GL_ALREADY_INCLUDING_STDIO_H
Packit 33f14e
Packit 33f14e
#include <errno.h>
Packit 33f14e
Packit 33f14e
static FILE *
Packit 33f14e
orig_freopen (const char *filename, const char *mode, FILE *stream)
Packit 33f14e
{
Packit 33f14e
  return freopen (filename, mode, stream);
Packit 33f14e
}
Packit 33f14e
Packit 33f14e
/* Specification.  */
Packit 33f14e
/* Write "stdio.h" here, not <stdio.h>, otherwise OSF/1 5.1 DTK cc eliminates
Packit 33f14e
   this include because of the preliminary #include <stdio.h> above.  */
Packit 33f14e
#include "stdio.h"
Packit 33f14e
Packit 33f14e
#include <fcntl.h>
Packit 33f14e
#include <string.h>
Packit 33f14e
#include <unistd.h>
Packit 33f14e
Packit 33f14e
FILE *
Packit 33f14e
rpl_freopen (const char *filename, const char *mode, FILE *stream)
Packit 33f14e
{
Packit 33f14e
  FILE *result;
Packit 33f14e
#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
Packit 33f14e
  char const *null_device = "NUL";
Packit 33f14e
  if (filename && strcmp (filename, "/dev/null") == 0)
Packit 33f14e
    filename = null_device;
Packit 33f14e
#else
Packit 33f14e
  char const *null_device = "/dev/null";
Packit 33f14e
#endif
Packit 33f14e
Packit 33f14e
#ifdef __KLIBC__
Packit 33f14e
  errno = 0;
Packit 33f14e
#endif
Packit 33f14e
Packit 33f14e
  result = orig_freopen (filename, mode, stream);
Packit 33f14e
Packit 33f14e
  if (!result)
Packit 33f14e
    {
Packit 33f14e
#ifdef __KLIBC__
Packit 33f14e
      /* On OS/2 kLIBC, freopen returns NULL even if it is successful
Packit 33f14e
         if filename is NULL. */
Packit 33f14e
      if (!filename && !errno)
Packit 33f14e
        result = stream;
Packit 33f14e
#endif
Packit 33f14e
    }
Packit 33f14e
  else if (filename)
Packit 33f14e
    {
Packit 33f14e
      int fd = fileno (result);
Packit 33f14e
      if (dup2 (fd, fd) < 0 && errno == EBADF)
Packit 33f14e
        {
Packit 33f14e
          int nullfd = open (null_device, O_RDONLY | O_CLOEXEC);
Packit 33f14e
          int err = 0;
Packit 33f14e
          if (nullfd != fd)
Packit 33f14e
            {
Packit 33f14e
              if (dup2 (nullfd, fd) < 0)
Packit 33f14e
                err = 1;
Packit 33f14e
              close (nullfd);
Packit 33f14e
            }
Packit 33f14e
          if (!err)
Packit 33f14e
            result = orig_freopen (filename, mode, result);
Packit 33f14e
        }
Packit 33f14e
    }
Packit 33f14e
Packit 33f14e
  return result;
Packit 33f14e
}