sl@0: /* FREOPEN.C
sl@0:  * 
sl@0:  * Portions Copyright (c) 1990-1999 Nokia Corporation and/or its subsidiary(-ies).
sl@0:  * All rights reserved.
sl@0:  */
sl@0: 
sl@0: /*
sl@0:  * Copyright (c) 1990 The Regents of the University of California.
sl@0:  * All rights reserved.
sl@0:  *
sl@0:  * Redistribution and use in source and binary forms are permitted
sl@0:  * provided that the above copyright notice and this paragraph are
sl@0:  * duplicated in all such forms and that any documentation,
sl@0:  * advertising materials, and other materials related to such
sl@0:  * distribution and use acknowledge that the software was developed
sl@0:  * by the University of California, Berkeley.  The name of the
sl@0:  * University may not be used to endorse or promote products derived
sl@0:  * from this software without specific prior written permission.
sl@0:  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
sl@0:  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
sl@0:  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
sl@0:  */
sl@0: 
sl@0: /*
sl@0: FUNCTION
sl@0: <<freopen>>---open a file using an existing file descriptor
sl@0: 
sl@0: INDEX
sl@0: 	freopen
sl@0: 
sl@0: ANSI_SYNOPSIS
sl@0: 	#include <stdio.h>
sl@0: 	FILE *freopen(const char *<[file]>, const char *<[mode]>,
sl@0: 		      FILE *<[fp]>);
sl@0: 
sl@0: TRAD_SYNOPSIS
sl@0: 	#include <stdio.h>
sl@0: 	FILE *freopen(<[file]>, <[mode]>, <[fp]>)
sl@0: 	char *<[file]>;
sl@0: 	char *<[mode]>;
sl@0: 	FILE *<[fp]>;
sl@0: 
sl@0: DESCRIPTION
sl@0: Use this variant of <<fopen>> if you wish to specify a particular file
sl@0: descriptor <[fp]> (notably <<stdin>>, <<stdout>>, or <<stderr>>) for
sl@0: the file.
sl@0: 
sl@0: If <[fp]> was associated with another file or stream, <<freopen>>
sl@0: closes that other file or stream (but ignores any errors while closing
sl@0: it).
sl@0: 
sl@0: <[file]> and <[mode]> are used just as in <<fopen>>.
sl@0: 
sl@0: RETURNS
sl@0: If successful, the result is the same as the argument <[fp]>.  If the
sl@0: file cannot be opened as specified, the result is <<NULL>>.
sl@0: 
sl@0: PORTABILITY
sl@0: ANSI C requires <<freopen>>.
sl@0: 
sl@0: Supporting OS subroutines required: <<close>>, <<fstat>>, <<isatty>>,
sl@0: <<lseek>>, <<open>>, <<read>>, <<sbrk>>, <<write>>.
sl@0: */
sl@0: 
sl@0: #include <time.h>
sl@0: #include <stdio_r.h>
sl@0: #include <fcntl.h>
sl@0: #include <stdlib_r.h>
sl@0: #include "LOCAL.H"
sl@0: #include <errno.h>
sl@0: 
sl@0: /*
sl@0:  * Re-direct an existing, open (probably) file to some other file.
sl@0:  */
sl@0: 
sl@0: #define MaxFullName 255
sl@0: 
sl@0: /**
sl@0: Reopen a stream with a different file and mode.
sl@0: @return If the file has been succesfully reopened the function returns a pointer to the file.
sl@0: Otherwise a NULL pointer is returned.
sl@0: @param file name of the file to be opened. 
sl@0: This paramenter must follow operating system's specifications and can include a path 
sl@0: if the system supports it.
sl@0: @param mode type of access requested.
sl@0: @param fp pointer to open file that has to be reopened.
sl@0: */
sl@0: EXPORT_C FILE * freopen (const char *file, const char *mode, FILE *fp)
sl@0: {
sl@0:   	wchar_t _wfile[MaxFullName+1];	
sl@0: 	wchar_t _wmode[MaxFullName+1];
sl@0: 	struct _reent *ptr;
sl@0: 
sl@0: 	if ((-1 != mbstowcs(_wfile, file, MaxFullName)) && 
sl@0: 		(-1 != mbstowcs(_wmode, mode, MaxFullName)))
sl@0: 	{
sl@0: 		return wfreopen(_wfile, _wmode, fp);
sl@0: 	}
sl@0: 
sl@0: 	CHECK_INIT (fp);
sl@0: 	ptr = fp->_data;
sl@0: 	ptr->_errno = EILSEQ;
sl@0: 	return NULL;
sl@0: }
sl@0: 
sl@0: EXPORT_C FILE * wfreopen (const wchar_t *file, const wchar_t *mode, FILE *fp)
sl@0: {
sl@0:   register int f;
sl@0:   int isopen, flags, oflags, e;
sl@0:   struct _reent *ptr;
sl@0: 
sl@0:   CHECK_INIT (fp);
sl@0:   ptr = fp->_data;
sl@0: 
sl@0:   if ((flags = __sflags (ptr, mode, &oflags)) == 0)
sl@0:     {
sl@0:       (void) fclose (fp);
sl@0:       return NULL;
sl@0:     }
sl@0: 
sl@0:   /*
sl@0:    * Remember whether the stream was open to begin with, and
sl@0:    * which file descriptor (if any) was associated with it.
sl@0:    * If it was attached to a descriptor, defer closing it,
sl@0:    * so that, e.g., freopen("/dev/stdin", "r", stdin) works.
sl@0:    * This is unnecessary if it was not a Unix file.
sl@0:    */
sl@0: 
sl@0:   if (fp->_flags == 0)
sl@0:     {
sl@0:       fp->_flags = __SEOF;	/* hold on to it */
sl@0:       isopen = 0;
sl@0:     }
sl@0:   else
sl@0:     {
sl@0:       if (fp->_flags & __SWR)
sl@0: 	(void) fflush (fp);
sl@0:       /* if close is NULL, closing is a no-op, hence pointless */
sl@0:       isopen = fp->_close != NULL;
sl@0:       if (fp->_file < 0 && isopen)
sl@0: 	{
sl@0: 	  (void) (*fp->_close) (fp->_cookie);
sl@0: 	  isopen = 0;
sl@0: 	}
sl@0:     }
sl@0: 
sl@0:   /*
sl@0:    * Now get a new descriptor to refer to the new file.
sl@0:    */
sl@0: 
sl@0:   f = _wopen_r (ptr, (wchar_t *)file, oflags, 0666);
sl@0:   if (f < 0 && isopen)
sl@0:     {
sl@0:       /*
sl@0:        * May have used up all descriptors, so close the old
sl@0:        * and try again.
sl@0:        */
sl@0:       (void) (*fp->_close) (fp->_cookie);
sl@0:       isopen = 0;
sl@0:       f = _wopen_r (ptr, (wchar_t *) file, oflags, 0666);
sl@0:     }
sl@0:   e = ptr->_errno;
sl@0: 
sl@0:   /*
sl@0:    * Finish closing fp.  Even if the open succeeded above,
sl@0:    * we cannot keep fp->_base: it may be the wrong size.
sl@0:    * This loses the effect of any setbuffer calls,
sl@0:    * but stdio has always done this before.
sl@0:    */
sl@0: 
sl@0:   if (isopen)
sl@0:     (void) (*fp->_close) (fp->_cookie);
sl@0:   if (fp->_flags & __SMBF)
sl@0:     _free_r (ptr, (char *) fp->_bf._base);
sl@0:   fp->_w = 0;
sl@0:   fp->_r = 0;
sl@0:   fp->_p = NULL;
sl@0:   fp->_bf._base = NULL;
sl@0:   fp->_bf._size = 0;
sl@0:   fp->_lbfsize = 0;
sl@0:   if (HASUB (fp))
sl@0:     FREEUB (fp);
sl@0:   fp->_ub._size = 0;
sl@0:   if (HASLB (fp))
sl@0:     FREELB (fp);
sl@0:   fp->_lb._size = 0;
sl@0: 
sl@0:   if (f < 0)
sl@0:     {				/* did not get it after all */
sl@0:       fp->_flags = 0;		/* set it free */
sl@0:       ptr->_errno = e;		/* restore in case _close clobbered */
sl@0:       return NULL;
sl@0:     }
sl@0: 
sl@0:   fp->_flags = (short)flags;
sl@0:   fp->_file = (short)f;
sl@0:   fp->_cookie = (void*) fp;
sl@0:   fp->_read = __sread;
sl@0:   fp->_write = __swrite;
sl@0:   fp->_seek = __sseek;
sl@0:   fp->_close = __sclose;
sl@0:   return fp;
sl@0: }