Blame lib/freopen.c

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