1 /*- 2 * Copyright (c) 1990 The Regents of the University of California. 3 * All rights reserved. 4 * 5 * This code is derived from software contributed to Berkeley by 6 * Chris Torek. 7 * 8 * %sccs.include.redist.c% 9 */ 10 11 #if defined(LIBC_SCCS) && !defined(lint) 12 static char sccsid[] = "@(#)freopen.c 5.4 (Berkeley) 02/01/91"; 13 #endif /* LIBC_SCCS and not lint */ 14 15 #include <sys/types.h> 16 #include <sys/file.h> 17 #include <sys/stat.h> 18 #include <errno.h> 19 #include <stdio.h> 20 #include <stdlib.h> 21 #include "local.h" 22 23 /* 24 * Re-direct an existing, open (probably) file to some other file. 25 * ANSI is written such that the original file gets closed if at 26 * all possible, no matter what. 27 */ 28 FILE * 29 freopen(file, mode, fp) 30 char *file, *mode; 31 register FILE *fp; 32 { 33 register int f; 34 int flags, isopen, oflags, sverrno, wantfd; 35 36 if ((flags = __sflags(mode, &oflags)) == 0) { 37 (void) fclose(fp); 38 return (NULL); 39 } 40 41 if (!__sdidinit) 42 __sinit(); 43 44 /* 45 * There are actually programs that depend on being able to "freopen" 46 * descriptors that weren't originally open. Keep this from breaking. 47 * Remember whether the stream was open to begin with, and which file 48 * descriptor (if any) was associated with it. If it was attached to 49 * a descriptor, defer closing it; freopen("/dev/stdin", "r", stdin) 50 * should work. This is unnecessary if it was not a Unix file. 51 */ 52 if (fp->_flags == 0) { 53 fp->_flags = __SEOF; /* hold on to it */ 54 isopen = 0; 55 wantfd = -1; 56 } else { 57 /* flush the stream; ANSI doesn't require this. */ 58 if (fp->_flags & __SWR) 59 (void) __sflush(fp); 60 /* if close is NULL, closing is a no-op, hence pointless */ 61 isopen = fp->_close != NULL; 62 if ((wantfd = fp->_file) < 0 && isopen) { 63 (void) (*fp->_close)(fp->_cookie); 64 isopen = 0; 65 } 66 } 67 68 /* Get a new descriptor to refer to the new file. */ 69 f = open(file, oflags, DEFFILEMODE); 70 if (f < 0 && isopen) { 71 /* If out of fd's close the old one and try again. */ 72 if (errno == ENFILE || errno == EMFILE) { 73 (void) (*fp->_close)(fp->_cookie); 74 isopen = 0; 75 f = open(file, oflags, DEFFILEMODE); 76 } 77 } 78 sverrno = errno; 79 80 /* 81 * Finish closing fp. Even if the open succeeded above, we cannot 82 * keep fp->_base: it may be the wrong size. This loses the effect 83 * of any setbuffer calls, but stdio has always done this before. 84 */ 85 if (isopen) 86 (void) (*fp->_close)(fp->_cookie); 87 if (fp->_flags & __SMBF) 88 free((char *)fp->_bf._base); 89 fp->_w = 0; 90 fp->_r = 0; 91 fp->_p = NULL; 92 fp->_bf._base = NULL; 93 fp->_bf._size = 0; 94 fp->_lbfsize = 0; 95 if (HASUB(fp)) 96 FREEUB(fp); 97 fp->_ub._size = 0; 98 if (HASLB(fp)) 99 FREELB(fp); 100 fp->_lb._size = 0; 101 102 if (f < 0) { /* did not get it after all */ 103 fp->_flags = 0; /* set it free */ 104 errno = sverrno; /* restore in case _close clobbered */ 105 return (NULL); 106 } 107 108 /* 109 * If reopening something that was open before on a real file, try 110 * to maintain the descriptor. Various C library routines (perror) 111 * assume stderr is always fd STDERR_FILENO, even if being freopen'd. 112 */ 113 if (wantfd >= 0 && f != wantfd) { 114 if (dup2(f, wantfd) >= 0) { 115 (void) close(f); 116 f = wantfd; 117 } 118 } 119 120 fp->_flags = flags; 121 fp->_file = f; 122 fp->_cookie = fp; 123 fp->_read = __sread; 124 fp->_write = __swrite; 125 fp->_seek = __sseek; 126 fp->_close = __sclose; 127 return (fp); 128 } 129