xref: /csrg-svn/lib/libc/stdio/wbuf.c (revision 9721)
1 /* @(#)wbuf.c	4.4 (Berkeley) 12/15/82 */
2 #include	<stdio.h>
3 #include	<sys/types.h>
4 #include	<sys/stat.h>
5 
6 char	*malloc();
7 
8 _flsbuf(c, iop)
9 register FILE *iop;
10 {
11 	register char *base;
12 	register n, rn;
13 	char c1;
14 	int size;
15 	struct stat stbuf;
16 	extern char _sobuf[];
17 
18 	if (iop->_flag & _IORW) {
19 		iop->_flag |= _IOWRT;
20 		iop->_flag &= ~_IOEOF;
21 	}
22 
23 	if ((iop->_flag&_IOWRT)==0)
24 		return(EOF);
25 tryagain:
26 	if (iop->_flag&_IOLBF) {
27 		base = iop->_base;
28 		*iop->_ptr++ = c;
29 		if (iop->_ptr >= base+iop->_bufsiz || c == '\n') {
30 			n = write(fileno(iop), base, rn = iop->_ptr - base);
31 			iop->_ptr = base;
32 		} else
33 			rn = n = 0;
34 		iop->_cnt = 0;
35 	} else if (iop->_flag&_IONBF) {
36 		c1 = c;
37 		rn = 1;
38 		n = write(fileno(iop), &c1, rn);
39 		iop->_cnt = 0;
40 	} else {
41 		if ((base=iop->_base)==NULL) {
42 			if (fstat(fileno(iop), &stbuf) < 0 ||
43 			    stbuf.st_blksize <= NULL)
44 				size = BUFSIZ;
45 			else
46 				size = stbuf.st_blksize;
47 			if (iop==stdout) {
48 				if (isatty(fileno(stdout)))
49 					iop->_flag |= _IOLBF;
50 				iop->_base = _sobuf;
51 				iop->_ptr = _sobuf;
52 				iop->_bufsiz = size;
53 				goto tryagain;
54 			}
55 			if ((iop->_base=base=malloc(size)) == NULL) {
56 				iop->_flag |= _IONBF;
57 				goto tryagain;
58 			}
59 			iop->_flag |= _IOMYBUF;
60 			iop->_bufsiz = size;
61 			rn = n = 0;
62 		} else if ((rn = n = iop->_ptr - base) > 0) {
63 			iop->_ptr = base;
64 			n = write(fileno(iop), base, n);
65 		}
66 		iop->_cnt = iop->_bufsiz-1;
67 		*base++ = c;
68 		iop->_ptr = base;
69 	}
70 	if (rn != n) {
71 		iop->_flag |= _IOERR;
72 		return(EOF);
73 	}
74 	return(c);
75 }
76 
77 fflush(iop)
78 register struct _iobuf *iop;
79 {
80 	register char *base;
81 	register n;
82 
83 	if ((iop->_flag&(_IONBF|_IOWRT))==_IOWRT
84 	 && (base=iop->_base)!=NULL && (n=iop->_ptr-base)>0) {
85 		iop->_ptr = base;
86 		iop->_cnt = (iop->_flag&(_IOLBF|_IONBF)) ? 0 : iop->_bufsiz;
87 		if (write(fileno(iop), base, n)!=n) {
88 			iop->_flag |= _IOERR;
89 			return(EOF);
90 		}
91 	}
92 	return(0);
93 }
94 
95 /*
96  * Flush buffers on exit
97  */
98 
99 _cleanup()
100 {
101 	register struct _iobuf *iop;
102 	extern struct _iobuf *_lastbuf;
103 
104 	for (iop = _iob; iop < _lastbuf; iop++)
105 		fclose(iop);
106 }
107 
108 /*
109  * fclose(*iop) - Close an open stdio stream without side effects.
110  *
111  * As per Dennis Ricthie's mail, fclose is defined to leave in a "virgin" state,
112  * the structure pointed to by the parameter, *iop.  This means that
113  * all flags are cleared, counters set to 0 and Pointers set to NULL.
114  *
115  * Which implies:
116  *		foo = fopen...
117  *		setbuf (foo, some_buffer);
118  *		.....
119  *		fclose(foo);
120  *
121  *	Will leave the buffer stucture cleared.  If the user wishes to
122  * reuse the *iop (foo) when he opens another file he must AGAIN call setbuf(3)
123  * if he again wishes to supply his own buffer.
124  *
125  *	The old method allowed the above case but had a nasty side effect
126  * of leaving data around if the phase of the moon was right.  The correct
127  * solution is to sanitize everything with the fclose.
128  *	Clem Cole 12-15-82
129  */
130 
131 fclose(iop)
132 register struct _iobuf *iop;
133 {
134 	register int r;
135 
136 	r = EOF;
137 	/*
138 	 * Is this an open file structure as opposed to being String.
139 	 */
140 	if (iop->_flag&(_IOREAD|_IOWRT|_IORW) && (iop->_flag&_IOSTRG)==0) {
141 		/*
142 		 * flush out any pending I/O
143 		 */
144 		r = fflush(iop);
145 		/*
146 		 * tell UNIX that it can free up the file descriptor
147 		 */
148 		if (close(fileno(iop)) < 0)
149 			r = EOF;
150 		/*
151 		 * if we had done a malloc(3) in flsbuf or filbuf we need
152 		 * to give the buffer back to the system
153 		 */
154 		if (iop->_flag&_IOMYBUF)
155 			free(iop->_base);
156 	}
157 	/*
158 	 * finially sanitize the buffer structure
159 	 */
160 	iop->_cnt = 0;
161 	iop->_base = (char *)NULL;
162 	iop->_ptr = (char *)NULL;
163 	iop->_bufsiz = 0;
164 	iop->_flag = 0;
165 	iop->_file = 0;
166 
167 	return(r);
168 }
169