1 /* 2 * freopen.c - open a file and associate a stream with it 3 */ 4 /* $Header$ */ 5 6 #if defined(_POSIX_SOURCE) 7 #include <sys/types.h> 8 #endif 9 #include <stdio.h> 10 #include <stdlib.h> 11 #include "loc_incl.h" 12 #include <sys/stat.h> 13 14 #define PMODE 0666 15 16 /* Do not "optimize" this file to use the open with O_CREAT if the file 17 * does not exist. The reason is given in fopen.c. 18 */ 19 #define O_RDONLY 0 20 #define O_WRONLY 1 21 #define O_RDWR 2 22 23 #define O_CREAT 0x010 24 #define O_TRUNC 0x020 25 #define O_APPEND 0x040 26 27 int _open(const char *path, int flags); 28 int _creat(const char *path, mode_t mode); 29 int _close(int d); 30 31 FILE * 32 freopen(const char *name, const char *mode, FILE *stream) 33 { 34 register int i; 35 struct stat st; 36 int rwmode = 0, rwflags = 0; 37 int fd, flags = stream->_flags & (_IONBF | _IOFBF | _IOLBF | _IOMYBUF); 38 39 (void) fflush(stream); /* ignore errors */ 40 (void) _close(fileno(stream)); 41 42 /* Find the slot the stream had, if any. */ 43 for(i = 0; i < FOPEN_MAX; i++) 44 if (stream == __iotab[i]) 45 break; 46 47 /* If none, it might've been fclose()d; find a new slot for it. */ 48 if(i >= FOPEN_MAX) { 49 for (i = 0; __iotab[i] != 0 ; i++) { 50 if ( i >= FOPEN_MAX-1 ) 51 return (FILE *)NULL; 52 } 53 } 54 55 /* If it was valid, it isn't any more until the freopen() succeeds. */ 56 __iotab[i] = 0; 57 58 switch(*mode++) { 59 case 'r': 60 flags |= _IOREAD; 61 rwmode = O_RDONLY; 62 break; 63 case 'w': 64 flags |= _IOWRITE; 65 rwmode = O_WRONLY; 66 rwflags = O_CREAT | O_TRUNC; 67 break; 68 case 'a': 69 flags |= _IOWRITE | _IOAPPEND; 70 rwmode = O_WRONLY; 71 rwflags |= O_APPEND | O_CREAT; 72 break; 73 default: 74 goto loser; 75 } 76 77 while (*mode) { 78 switch(*mode++) { 79 case 'b': 80 continue; 81 case '+': 82 rwmode = O_RDWR; 83 flags |= _IOREAD | _IOWRITE; 84 continue; 85 /* The sequence may be followed by aditional characters */ 86 default: 87 break; 88 } 89 break; 90 } 91 92 if ((rwflags & O_TRUNC) 93 || (((fd = _open(name, rwmode)) < 0) 94 && (rwflags & O_CREAT))) { 95 if (((fd = _creat(name, PMODE)) < 0) && flags | _IOREAD) { 96 (void) _close(fd); 97 fd = _open(name, rwmode); 98 } 99 } 100 101 if (fd < 0) { 102 goto loser; 103 } 104 105 if ( fstat( fd, &st ) == 0 ) { 106 if ( S_ISFIFO(st.st_mode) ) flags |= _IOFIFO; 107 } else { 108 goto loser; 109 } 110 111 stream->_count = 0; 112 stream->_fd = fd; 113 stream->_flags = flags; 114 __iotab[i] = stream; 115 return stream; 116 117 loser: 118 if (stream != stdin && stream != stdout && stream != stderr) 119 free((void *)stream); 120 return (FILE *)NULL; 121 } 122