Subversion Repositories shark

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 pj 1
/*-
2
 * Copyright (c) 1990, 1993
3
 *      The Regents of the University of California.  All rights reserved.
4
 *
5
 * This code is derived from software contributed to Berkeley by
6
 * Chris Torek.
7
 *
8
 * Redistribution and use in source and binary forms, with or without
9
 * modification, are permitted provided that the following conditions
10
 * are met:
11
 * 1. Redistributions of source code must retain the above copyright
12
 *    notice, this list of conditions and the following disclaimer.
13
 * 2. Redistributions in binary form must reproduce the above copyright
14
 *    notice, this list of conditions and the following disclaimer in the
15
 *    documentation and/or other materials provided with the distribution.
16
 * 3. All advertising materials mentioning features or use of this software
17
 *    must display the following acknowledgement:
18
 *      This product includes software developed by the University of
19
 *      California, Berkeley and its contributors.
20
 * 4. Neither the name of the University nor the names of its contributors
21
 *    may be used to endorse or promote products derived from this software
22
 *    without specific prior written permission.
23
 *
24
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34
 * SUCH DAMAGE.
35
 */
36
 
37
#if defined(LIBC_SCCS) && !defined(lint)
38
static char sccsid[] = "@(#)freopen.c   8.1 (Berkeley) 6/4/93";
39
#endif /* LIBC_SCCS and not lint */
40
 
41
#include <sys/types.h>
42
#include <sys/stat.h>
43
#include <fcntl.h>
44
#include <errno.h>
45
#include <unistd.h>
46
#include <stdio.h>
47
#include <stdlib.h>
48
#include "local.h"
49
 
50
/*
51
 * Re-direct an existing, open (probably) file to some other file.
52
 * ANSI is written such that the original file gets closed if at
53
 * all possible, no matter what.
54
 */
55
FILE *
56
freopen(file, mode, fp)
57
        const char *file, *mode;
58
        register FILE *fp;
59
{
60
        register int f;
61
        int flags, isopen, oflags, sverrno, wantfd;
62
 
63
        if ((flags = __sflags(mode, &oflags)) == 0) {
64
                (void) fclose(fp);
65
                return (NULL);
66
        }
67
 
68
        if (!__sdidinit)
69
                __sinit();
70
 
71
        /*
72
         * There are actually programs that depend on being able to "freopen"
73
         * descriptors that weren't originally open.  Keep this from breaking.
74
         * Remember whether the stream was open to begin with, and which file
75
         * descriptor (if any) was associated with it.  If it was attached to
76
         * a descriptor, defer closing it; freopen("/dev/stdin", "r", stdin)
77
         * should work.  This is unnecessary if it was not a Unix file.
78
         */
79
        if (fp->_flags == 0) {
80
                fp->_flags = __SEOF;    /* hold on to it */
81
                isopen = 0;
82
                wantfd = -1;
83
        } else {
84
                /* flush the stream; ANSI doesn't require this. */
85
                if (fp->_flags & __SWR)
86
                        (void) __sflush(fp);
87
                /* if close is NULL, closing is a no-op, hence pointless */
88
                isopen = fp->_close != NULL;
89
                if ((wantfd = fp->_file) < 0 && isopen) {
90
                        (void) (*fp->_close)(fp->_cookie);
91
                        isopen = 0;
92
                }
93
        }
94
 
95
        /* Get a new descriptor to refer to the new file. */
96
        f = open(file, oflags, DEFFILEMODE);
97
        if (f < 0 && isopen) {
98
                /* If out of fd's close the old one and try again. */
99
                if (errno == ENFILE || errno == EMFILE) {
100
                        (void) (*fp->_close)(fp->_cookie);
101
                        isopen = 0;
102
                        f = open(file, oflags, DEFFILEMODE);
103
                }
104
        }
105
        sverrno = errno;
106
 
107
        /*
108
         * Finish closing fp.  Even if the open succeeded above, we cannot
109
         * keep fp->_base: it may be the wrong size.  This loses the effect
110
         * of any setbuffer calls, but stdio has always done this before.
111
         */
112
        if (isopen)
113
                (void) (*fp->_close)(fp->_cookie);
114
        if (fp->_flags & __SMBF)
115
                free((char *)fp->_bf._base);
116
        fp->_w = 0;
117
        fp->_r = 0;
118
        fp->_p = NULL;
119
        fp->_bf._base = NULL;
120
        fp->_bf._size = 0;
121
        fp->_lbfsize = 0;
122
        if (HASUB(fp))
123
                FREEUB(fp);
124
        fp->_ub._size = 0;
125
        if (HASLB(fp))
126
                FREELB(fp);
127
        fp->_lb._size = 0;
128
 
129
        if (f < 0) {                    /* did not get it after all */
130
                fp->_flags = 0;         /* set it free */
131
                errno = sverrno;        /* restore in case _close clobbered */
132
                return (NULL);
133
        }
134
 
135
        /*
136
         * If reopening something that was open before on a real file, try
137
         * to maintain the descriptor.  Various C library routines (perror)
138
         * assume stderr is always fd STDERR_FILENO, even if being freopen'd.
139
         */
140
        if (wantfd >= 0 && f != wantfd) {
141
                if (dup2(f, wantfd) >= 0) {
142
                        (void) close(f);
143
                        f = wantfd;
144
                }
145
        }
146
 
147
        fp->_flags = flags;
148
        fp->_file = f;
149
        fp->_cookie = fp;
150
        fp->_read = __sread;
151
        fp->_write = __swrite;
152
        fp->_seek = __sseek;
153
        fp->_close = __sclose;
154
        return (fp);
155
}