Project

General

Profile

Statistics
| Branch: | Revision:

root / prex-0.9.0 / usr / lib / libc / stdio / freopen.c @ 03e9c04a

History | View | Annotate | Download (4.27 KB)

1 03e9c04a Brad Neuman
/*-
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. Neither the name of the University nor the names of its contributors
17
 *    may be used to endorse or promote products derived from this software
18
 *    without specific prior written permission.
19
 *
20
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30
 * SUCH DAMAGE.
31
 */
32
33
#include <sys/types.h>
34
#include <sys/stat.h>
35
#include <fcntl.h>
36
#include <errno.h>
37
#include <unistd.h>
38
#include <stdio.h>
39
#include <stdlib.h>
40
#include "local.h"
41
42
/*
43
 * Re-direct an existing, open (probably) file to some other file.
44
 * ANSI is written such that the original file gets closed if at
45
 * all possible, no matter what.
46
 */
47
FILE *
48
freopen(file, mode, fp)
49
        const char *file, *mode;
50
        FILE *fp;
51
{
52
        int f;
53
        int flags, isopen, oflags, sverrno, wantfd;
54
55
        if ((flags = __sflags(mode, &oflags)) == 0) {
56
                (void) fclose(fp);
57
                return (NULL);
58
        }
59
60
        if (!__sdidinit)
61
                __sinit();
62
63
        /*
64
         * There are actually programs that depend on being able to "freopen"
65
         * descriptors that weren't originally open.  Keep this from breaking.
66
         * Remember whether the stream was open to begin with, and which file
67
         * descriptor (if any) was associated with it.  If it was attached to
68
         * a descriptor, defer closing it; freopen("/dev/stdin", "r", stdin)
69
         * should work.  This is unnecessary if it was not a Unix file.
70
         */
71
        if (fp->_flags == 0) {
72
                fp->_flags = __SEOF;        /* hold on to it */
73
                isopen = 0;
74
                wantfd = -1;
75
        } else {
76
                /* flush the stream; ANSI doesn't require this. */
77
                if (fp->_flags & __SWR)
78
                        (void) __sflush(fp);
79
                /* if close is NULL, closing is a no-op, hence pointless */
80
                isopen = 1;
81
                if ((wantfd = fp->_file) < 0 && isopen) {
82
                        (void) __sclose(fp);
83
                        isopen = 0;
84
                }
85
        }
86
87
        /* Get a new descriptor to refer to the new file. */
88
        f = open(file, oflags, DEFFILEMODE);
89
        if (f < 0 && isopen) {
90
                /* If out of fd's close the old one and try again. */
91
                if (errno == ENFILE || errno == EMFILE) {
92
                        (void) __sclose(fp);
93
                        isopen = 0;
94
                        f = open(file, oflags, DEFFILEMODE);
95
                }
96
        }
97
        sverrno = errno;
98
99
        /*
100
         * Finish closing fp.  Even if the open succeeded above, we cannot
101
         * keep fp->_base: it may be the wrong size.  This loses the effect
102
         * of any setbuffer calls, but stdio has always done this before.
103
         */
104
        if (isopen)
105
                (void) __sclose(fp);
106
        if (fp->_flags & __SMBF)
107
                free((char *)fp->_bf._base);
108
        fp->_w = 0;
109
        fp->_r = 0;
110
        fp->_p = NULL;
111
        fp->_bf._base = NULL;
112
        fp->_bf._size = 0;
113
        if (HASUB(fp))
114
                FREEUB(fp);
115
        fp->_ub._size = 0;
116
117
        if (f < 0) {                        /* did not get it after all */
118
                fp->_flags = 0;                /* set it free */
119
                errno = sverrno;        /* restore in case _close clobbered */
120
                return (NULL);
121
        }
122
123
        /*
124
         * If reopening something that was open before on a real file, try
125
         * to maintain the descriptor.  Various C library routines (perror)
126
         * assume stderr is always fd STDERR_FILENO, even if being freopen'd.
127
         */
128
        if (wantfd >= 0 && f != wantfd) {
129
                if (dup2(f, wantfd) >= 0) {
130
                        (void) close(f);
131
                        f = wantfd;
132
                }
133
        }
134
135
        fp->_flags = flags;
136
        fp->_file = f;
137
        return (fp);
138
}