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 switch(*mode++) { 43 case 'r': 44 flags |= _IOREAD; 45 rwmode = O_RDONLY; 46 break; 47 case 'w': 48 flags |= _IOWRITE; 49 rwmode = O_WRONLY; 50 rwflags = O_CREAT | O_TRUNC; 51 break; 52 case 'a': 53 flags |= _IOWRITE | _IOAPPEND; 54 rwmode = O_WRONLY; 55 rwflags |= O_APPEND | O_CREAT; 56 break; 57 default: 58 goto loser; 59 } 60 61 while (*mode) { 62 switch(*mode++) { 63 case 'b': 64 continue; 65 case '+': 66 rwmode = O_RDWR; 67 flags |= _IOREAD | _IOWRITE; 68 continue; 69 /* The sequence may be followed by aditional characters */ 70 default: 71 break; 72 } 73 break; 74 } 75 76 if ((rwflags & O_TRUNC) 77 || (((fd = _open(name, rwmode)) < 0) 78 && (rwflags & O_CREAT))) { 79 if (((fd = _creat(name, PMODE)) < 0) && flags | _IOREAD) { 80 (void) _close(fd); 81 fd = _open(name, rwmode); 82 } 83 } 84 85 if (fd < 0) { 86 goto loser; 87 } 88 89 if ( fstat( fd, &st ) == 0 ) { 90 if ( S_ISFIFO(st.st_mode) ) flags |= _IOFIFO; 91 } else { 92 goto loser; 93 } 94 95 stream->_count = 0; 96 stream->_fd = fd; 97 stream->_flags = flags; 98 return stream; 99 100 loser: 101 for( i = 0; i < FOPEN_MAX; i++) { 102 if (stream == __iotab[i]) { 103 __iotab[i] = 0; 104 break; 105 } 106 } 107 if (stream != stdin && stream != stdout && stream != stderr) 108 free((void *)stream); 109 return (FILE *)NULL; 110 } 111