freopen.c - vx32 - Local 9vx git repository for patches.
 (HTM) git clone git://r-36.net/vx32
 (DIR) Log
 (DIR) Files
 (DIR) Refs
       ---
       freopen.c (5040B)
       ---
            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 rcsid[] = "$OpenBSD: freopen.c,v 1.3 1996/08/19 08:32:45 tholo Exp $";
           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 && f != wantfd)
          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 }