xref: /csrg-svn/lib/libc/stdio/wbuf.c (revision 9721)
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