This commit was generated by cvs2svn to track changes on a CVS vendor
[unix-history] / lib / libpthread / stdio / freopen.c
CommitLineData
8f953e65
CP
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 * 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 = "from: @(#)freopen.c 5.6 (Berkeley) 2/24/91";*/
39static char *rcsid = "$Id: freopen.c,v 1.15 1994/01/27 06:09:19 proven Exp $";
40#endif /* LIBC_SCCS and not lint */
41
42#include <pthread.h>
43#include <sys/types.h>
44#include <sys/stat.h>
45#include <fcntl.h>
46#include <errno.h>
47#include <unistd.h>
48#include <stdio.h>
49#include <stdlib.h>
50#include "local.h"
51
52extern pthread_mutex_t __sfp_mutex;
53extern pthread_cond_t __sfp_cond;
54extern int __sfp_state;
55
56/*
57 * Re-direct an existing, open (probably) file to some other file.
58 * ANSI is written such that the original file gets closed if at
59 * all possible, no matter what.
60 */
61FILE *
62freopen(file, mode, fp)
63 const char *file, *mode;
64 register FILE *fp;
65{
66 int f, flags, oflags;
67 FILE *ret;
68
69 if ((flags = __sflags(mode, &oflags)) == 0) {
70 (void) fclose(fp);
71 return (NULL);
72 }
73
74 pthread_once(&__sdidinit, __sinit);
75
76 /*
77 * There are actually programs that depend on being able to "freopen"
78 * descriptors that weren't originally open. Keep this from breaking.
79 * Remember whether the stream was open to begin with, and which file
80 * descriptor (if any) was associated with it. If it was attached to
81 * a descriptor, defer closing it; freopen("/dev/stdin", "r", stdin)
82 * should work. This is unnecessary if it was not a Unix file.
83 */
84 /* while lock __sfp_mutex, to block out fopen, and other freopen calls */
85 while (pthread_mutex_lock(&__sfp_mutex) == OK) {
86 if (ftrylockfile(fp) == OK) {
87 if (fp->_flags) {
88 /* flush the stream; ANSI doesn't require this. */
89 if (fp->_flags & __SWR)
90 (void) __sflush(fp);
91 __sclose(fp);
92 /*
93 * Finish closing fp. We cannot keep fp->_base:
94 * it may be the wrong size. This loses the effect
95 * of any setbuffer calls, but stdio has always done
96 * this before.
97 * NOTE: We do this even if __ftrylockfilr failed with
98 * an error to avoid memory leaks.
99 */
100 if (fp->_flags & __SMBF)
101 free((char *)fp->_bf._base);
102 fp->_w = 0;
103 fp->_r = 0;
104 fp->_p = NULL;
105 fp->_bf._base = NULL;
106 fp->_bf._size = 0;
107 fp->_lbfsize = 0;
108 if (HASUB(fp))
109 FREEUB(fp);
110 fp->_ub._size = 0;
111 if (HASLB(fp))
112 FREELB(fp);
113 fp->_lb._size = 0;
114 }
115 /* Get a new descriptor to refer to the new file. */
116 if ((f = open(file, oflags, 0666)) < OK)
117 ret = NULL;
118 /*
119 * If reopening something that was open before on a real file, try
120 * to maintain the descriptor. Various C library routines (perror)
121 * assume stderr is always fd STDERR_FILENO, even if being freopen'd.
122 */
123 /* Testing f == fp->_file may no longer be necessary */
124 if (fp->_file >= 0 && f != fp->_file) {
125 if (dup2(f, fp->_file) >= OK) {
126 (void)close(f);
127 f = fp->_file;
128 }
129 }
130 fp->_flags = flags;
131 fp->_file = f;
132 ret = fp;
133 break;
134 } else {
135 /* unlock __sfp_mutex, and try again later */
136 pthread_mutex_unlock(&__sfp_mutex);
137 pthread_yield();
138 continue;
139 }
140 pthread_mutex_unlock(&__sfp_mutex);
141 funlockfile(fp);
142 return(ret);
143 }
144 (void)fclose(fp);
145 return(NULL);
146}