1 /* Open a stream to a file. 2 Copyright (C) 2007-2018 Free Software Foundation, Inc. 3 4 This program is free software: you can redistribute it and/or modify 5 it under the terms of the GNU General Public License as published by 6 the Free Software Foundation; either version 3 of the License, or 7 (at your option) any later version. 8 9 This program 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 General Public License for more details. 13 14 You should have received a copy of the GNU 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 } 93