1*9721Sclemc /* @(#)wbuf.c 4.4 (Berkeley) 12/15/82 */ 22003Swnj #include <stdio.h> 38326Smckusick #include <sys/types.h> 48326Smckusick #include <sys/stat.h> 52003Swnj 62003Swnj char *malloc(); 72003Swnj 82003Swnj _flsbuf(c, iop) 92003Swnj register FILE *iop; 102003Swnj { 112003Swnj register char *base; 122003Swnj register n, rn; 132003Swnj char c1; 148326Smckusick int size; 158326Smckusick struct stat stbuf; 162003Swnj extern char _sobuf[]; 172003Swnj 183163Stoy if (iop->_flag & _IORW) { 193163Stoy iop->_flag |= _IOWRT; 203163Stoy iop->_flag &= ~_IOEOF; 213163Stoy } 223163Stoy 232003Swnj if ((iop->_flag&_IOWRT)==0) 242003Swnj return(EOF); 252003Swnj tryagain: 262003Swnj if (iop->_flag&_IOLBF) { 272003Swnj base = iop->_base; 282003Swnj *iop->_ptr++ = c; 298326Smckusick if (iop->_ptr >= base+iop->_bufsiz || c == '\n') { 302003Swnj n = write(fileno(iop), base, rn = iop->_ptr - base); 312003Swnj iop->_ptr = base; 322003Swnj } else 332003Swnj rn = n = 0; 342003Swnj iop->_cnt = 0; 352003Swnj } else if (iop->_flag&_IONBF) { 362003Swnj c1 = c; 372003Swnj rn = 1; 382003Swnj n = write(fileno(iop), &c1, rn); 392003Swnj iop->_cnt = 0; 402003Swnj } else { 412003Swnj if ((base=iop->_base)==NULL) { 428326Smckusick if (fstat(fileno(iop), &stbuf) < 0 || 438326Smckusick stbuf.st_blksize <= NULL) 448326Smckusick size = BUFSIZ; 458326Smckusick else 468326Smckusick size = stbuf.st_blksize; 472003Swnj if (iop==stdout) { 482003Swnj if (isatty(fileno(stdout))) 492003Swnj iop->_flag |= _IOLBF; 502003Swnj iop->_base = _sobuf; 512003Swnj iop->_ptr = _sobuf; 528326Smckusick iop->_bufsiz = size; 532003Swnj goto tryagain; 542003Swnj } 558326Smckusick if ((iop->_base=base=malloc(size)) == NULL) { 562003Swnj iop->_flag |= _IONBF; 572003Swnj goto tryagain; 582003Swnj } 592003Swnj iop->_flag |= _IOMYBUF; 608326Smckusick iop->_bufsiz = size; 612003Swnj rn = n = 0; 622003Swnj } else if ((rn = n = iop->_ptr - base) > 0) { 632003Swnj iop->_ptr = base; 642003Swnj n = write(fileno(iop), base, n); 652003Swnj } 668326Smckusick iop->_cnt = iop->_bufsiz-1; 672003Swnj *base++ = c; 682003Swnj iop->_ptr = base; 692003Swnj } 702003Swnj if (rn != n) { 712003Swnj iop->_flag |= _IOERR; 722003Swnj return(EOF); 732003Swnj } 742003Swnj return(c); 752003Swnj } 762003Swnj 772003Swnj fflush(iop) 782003Swnj register struct _iobuf *iop; 792003Swnj { 802003Swnj register char *base; 812003Swnj register n; 822003Swnj 832003Swnj if ((iop->_flag&(_IONBF|_IOWRT))==_IOWRT 842003Swnj && (base=iop->_base)!=NULL && (n=iop->_ptr-base)>0) { 852003Swnj iop->_ptr = base; 868326Smckusick iop->_cnt = (iop->_flag&(_IOLBF|_IONBF)) ? 0 : iop->_bufsiz; 872003Swnj if (write(fileno(iop), base, n)!=n) { 882003Swnj iop->_flag |= _IOERR; 892003Swnj return(EOF); 902003Swnj } 912003Swnj } 922003Swnj return(0); 932003Swnj } 942003Swnj 952003Swnj /* 962003Swnj * Flush buffers on exit 972003Swnj */ 982003Swnj 992003Swnj _cleanup() 1002003Swnj { 1012003Swnj register struct _iobuf *iop; 1022003Swnj extern struct _iobuf *_lastbuf; 1032003Swnj 1042003Swnj for (iop = _iob; iop < _lastbuf; iop++) 1052003Swnj fclose(iop); 1062003Swnj } 1072003Swnj 108*9721Sclemc /* 109*9721Sclemc * fclose(*iop) - Close an open stdio stream without side effects. 110*9721Sclemc * 111*9721Sclemc * As per Dennis Ricthie's mail, fclose is defined to leave in a "virgin" state, 112*9721Sclemc * the structure pointed to by the parameter, *iop. This means that 113*9721Sclemc * all flags are cleared, counters set to 0 and Pointers set to NULL. 114*9721Sclemc * 115*9721Sclemc * Which implies: 116*9721Sclemc * foo = fopen... 117*9721Sclemc * setbuf (foo, some_buffer); 118*9721Sclemc * ..... 119*9721Sclemc * fclose(foo); 120*9721Sclemc * 121*9721Sclemc * Will leave the buffer stucture cleared. If the user wishes to 122*9721Sclemc * reuse the *iop (foo) when he opens another file he must AGAIN call setbuf(3) 123*9721Sclemc * if he again wishes to supply his own buffer. 124*9721Sclemc * 125*9721Sclemc * The old method allowed the above case but had a nasty side effect 126*9721Sclemc * of leaving data around if the phase of the moon was right. The correct 127*9721Sclemc * solution is to sanitize everything with the fclose. 128*9721Sclemc * Clem Cole 12-15-82 129*9721Sclemc */ 130*9721Sclemc 1312003Swnj fclose(iop) 1322003Swnj register struct _iobuf *iop; 1332003Swnj { 134*9721Sclemc register int r; 1352003Swnj 1362003Swnj r = EOF; 137*9721Sclemc /* 138*9721Sclemc * Is this an open file structure as opposed to being String. 139*9721Sclemc */ 1403163Stoy if (iop->_flag&(_IOREAD|_IOWRT|_IORW) && (iop->_flag&_IOSTRG)==0) { 141*9721Sclemc /* 142*9721Sclemc * flush out any pending I/O 143*9721Sclemc */ 1442003Swnj r = fflush(iop); 145*9721Sclemc /* 146*9721Sclemc * tell UNIX that it can free up the file descriptor 147*9721Sclemc */ 1482003Swnj if (close(fileno(iop)) < 0) 1492003Swnj r = EOF; 150*9721Sclemc /* 151*9721Sclemc * if we had done a malloc(3) in flsbuf or filbuf we need 152*9721Sclemc * to give the buffer back to the system 153*9721Sclemc */ 1542003Swnj if (iop->_flag&_IOMYBUF) 1552003Swnj free(iop->_base); 1562003Swnj } 157*9721Sclemc /* 158*9721Sclemc * finially sanitize the buffer structure 159*9721Sclemc */ 1602003Swnj iop->_cnt = 0; 161*9721Sclemc iop->_base = (char *)NULL; 162*9721Sclemc iop->_ptr = (char *)NULL; 163*9721Sclemc iop->_bufsiz = 0; 164*9721Sclemc iop->_flag = 0; 165*9721Sclemc iop->_file = 0; 166*9721Sclemc 1672003Swnj return(r); 1682003Swnj } 169