(root)/
gettext-0.22.4/
gettext-tools/
gnulib-tests/
freopen.c
       1  /* Open a stream to a file.
       2     Copyright (C) 2007-2023 Free Software Foundation, Inc.
       3  
       4     This file is free software: you can redistribute it and/or modify
       5     it under the terms of the GNU Lesser General Public License as
       6     published by the Free Software Foundation, either version 3 of the
       7     License, or (at your option) any later version.
       8  
       9     This file is distributed in the hope that it will be useful,
      10     but WITHOUT ANY WARRANTY; without even the implied warranty of
      11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      12     GNU Lesser General Public License for more details.
      13  
      14     You should have received a copy of the GNU Lesser General Public License
      15     along with this program.  If not, see <https://www.gnu.org/licenses/>.  */
      16  
      17  /* Written by Bruno Haible <bruno@clisp.org>, 2007.  */
      18  
      19  /* If the user's config.h happens to include <stdio.h>, let it include only
      20     the system's <stdio.h> here, so that orig_freopen doesn't recurse to
      21     rpl_freopen.  */
      22  #define _GL_ALREADY_INCLUDING_STDIO_H
      23  #include <config.h>
      24  
      25  /* Get the original definition of freopen.  It might be defined as a macro.  */
      26  #include <stdio.h>
      27  #undef _GL_ALREADY_INCLUDING_STDIO_H
      28  
      29  #include <errno.h>
      30  
      31  static FILE *
      32  orig_freopen (const char *filename, const char *mode, FILE *stream)
      33  {
      34    return freopen (filename, mode, stream);
      35  }
      36  
      37  /* Specification.  */
      38  /* Write "stdio.h" here, not <stdio.h>, otherwise OSF/1 5.1 DTK cc eliminates
      39     this include because of the preliminary #include <stdio.h> above.  */
      40  #include "stdio.h"
      41  
      42  #include <fcntl.h>
      43  #include <string.h>
      44  #include <unistd.h>
      45  
      46  FILE *
      47  rpl_freopen (const char *filename, const char *mode, FILE *stream)
      48  {
      49    FILE *result;
      50  #if defined _WIN32 && ! defined __CYGWIN__
      51    char const *null_device = "NUL";
      52    if (filename && strcmp (filename, "/dev/null") == 0)
      53      filename = null_device;
      54  #else
      55    char const *null_device = "/dev/null";
      56  #endif
      57  
      58  #ifdef __KLIBC__
      59    errno = 0;
      60  #endif
      61  
      62    result = orig_freopen (filename, mode, stream);
      63  
      64    if (!result)
      65      {
      66  #ifdef __KLIBC__
      67        /* On OS/2 kLIBC, freopen returns NULL even if it is successful
      68           if filename is NULL. */
      69        if (!filename && !errno)
      70          result = stream;
      71  #endif
      72      }
      73    else if (filename)
      74      {
      75        int fd = fileno (result);
      76        if (dup2 (fd, fd) < 0 && errno == EBADF)
      77          {
      78            int nullfd = open (null_device, O_RDONLY | O_CLOEXEC);
      79            int err = 0;
      80            if (nullfd != fd)
      81              {
      82                if (dup2 (nullfd, fd) < 0)
      83                  err = 1;
      84                close (nullfd);
      85              }
      86            if (!err)
      87              result = orig_freopen (filename, mode, result);
      88          }
      89      }
      90  
      91    return result;
      92  }