Prex Home / Browse Source - Prex Version: 0.9.0

root/usr/lib/libc/stdio/freopen.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. freopen

   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. 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 }

/* [<][>][^][v][top][bottom][index][help] */