/* from Dale Schumacher's dLibs */ #include #include #include #include #include __EXTERN void _getbuf __PROTO((FILE *)); /* lowest character device handle # */ #define LAST_DEVICE __SMALLEST_VALID_HANDLE extern int __default_mode__; static FILE *_fopen(filename, mode, fp) const char *filename; const register char *mode; register FILE *fp; /* * INTERNAL FUNCTION. Attempt to open in the given * and attach it to the stream */ { register int h, i, iomode = 0, f = __default_mode__; while(*mode) { switch(*mode++) { case 'r': f |= _IOREAD; break; case 'w': f |= _IOWRT; iomode |= (O_CREAT | O_TRUNC); break; case 'a': f |= _IOWRT; iomode |= (O_CREAT | O_APPEND); break; case '+': f &= ~(_IOREAD | _IOWRT); f |= _IORW; break; case 'b': f |= _IOBIN; break; case 't': f &= ~_IOBIN; break; default: return(NULL); } } if((i = (f & (_IORW | _IOREAD | _IOWRT))) == 0) return(NULL); else if(i == _IOREAD) iomode |= O_RDONLY; else if(i == _IOWRT) iomode |= O_WRONLY; else iomode |= O_RDWR; h = open(filename, iomode, 0644); if(h < __SMALLEST_VALID_HANDLE) { return(NULL); /* file open/create error */ } if(isatty(h)) f |= (_IODEV | _IOLBF); else f |= _IOFBF; fp->_file = h; /* file handle */ fp->_flag = f; /* file status flags */ return(fp); } FILE *fopen(filename, mode) const char *filename, *mode; { register int i; register FILE *fp = NULL; for(i=0; (!fp && (i < _NFILE)); ++i) if(!(_iob[i]._flag & (_IORW | _IOREAD | _IOWRT))) fp = &_iob[i]; /* empty slot */ if(fp != NULL) { if(_fopen(filename, mode, fp) == NULL) return NULL; _getbuf(fp); return fp; } else { errno = EMFILE; return NULL; } } /* * re-coded, foobared code ifdef'ed below * * ++jrb */ FILE *freopen(filename, mode, fp) const char *filename, *mode; FILE *fp; { unsigned int f; if(fp == NULL) return NULL; f = fp->_flag; if((f & (_IORW | _IOREAD | _IOWRT)) != 0) { /* file not closed, close it */ #if 0 if(fflush(fp) != 0) return NULL; /* flush err */ if(close(fp->_file) != 0) return NULL; /* close err */ #else fflush(fp); close(fp->_file); /* ANSI says ignore errors */ #endif } /* save buffer discipline and setbuf settings, and _IOWRT just for determinining line buffering after the next _fopen */ f &= (_IOFBF | _IOLBF | _IONBF | _IOMYBUF | _IOWRT); /* open the new file according to mode */ if((fp = _fopen(filename, mode, fp)) == NULL) return NULL; if(fp->_flag & _IODEV) { /* we are re-opening to a tty */ if((f & _IOFBF) && (f & _IOWRT) && (f & _IOMYBUF)) { /* was a FBF & WRT & !setvbuff'ed */ /* reset to line buffering */ f &= ~_IOFBF; f |= _IOLBF; } } f &= ~_IOWRT; /* get rid of saved _IOWRT flag */ /* put buffering and discipline flags in new fp->_flag */ fp->_flag &= ~(_IONBF | _IOLBF | _IOFBF | _IOMYBUF); fp->_flag |= f; return fp; #ifdef FOOBAR /* this was old incorrect coding */ /* the problem: apart from the requirement that freopen return the same file descriptor that the code below meets, it should also preserve the same buffering discipline, and the same buffer (because the user may have done a setbuf/setvbuf). */ if(fclose(fp)) return(NULL); else return(_fopen(filename, mode, fp)); #endif /* FOOBAR */ }