xref: /original-bsd/lib/libc/stdio/wbuf.c (revision 76210d32)
1 /*
2  * Copyright (c) 1980 Regents of the University of California.
3  * All rights reserved.  The Berkeley software License Agreement
4  * specifies the terms and conditions for redistribution.
5  */
6 
7 #if defined(LIBC_SCCS) && !defined(lint)
8 static char sccsid[] = "@(#)wbuf.c	5.5 (Berkeley) 06/18/90";
9 #endif LIBC_SCCS and not lint
10 
11 #include	<stdio.h>
12 #include	<sys/types.h>
13 #include	<sys/stat.h>
14 
15 char	*malloc();
16 
17 _flsbuf(c, iop)
18 unsigned char c;
19 register FILE *iop;
20 {
21 	register char *base;
22 	register n, rn;
23 	char c1;
24 	int size;
25 	struct stat stbuf;
26 
27 	if (iop->_flag & _IORW) {
28 		iop->_flag |= _IOWRT;
29 		iop->_flag &= ~(_IOEOF|_IOREAD);
30 	}
31 
32 	if ((iop->_flag&_IOWRT)==0)
33 		return(EOF);
34 tryagain:
35 	if (iop->_flag&_IOLBF) {
36 		base = iop->_base;
37 		*iop->_ptr++ = c;
38 		if ((rn = iop->_ptr - base) >= iop->_bufsiz || c == '\n') {
39 			iop->_ptr = base;
40 			iop->_cnt = 0;
41 		} else {
42 			/* we got here because _cnt is wrong, so fix it */
43 			iop->_cnt = -rn;
44 			rn = n = 0;
45 		}
46 	} else if (iop->_flag&_IONBF) {
47 		c1 = c;
48 		rn = 1;
49 		base = &c1;
50 		iop->_cnt = 0;
51 	} else {
52 		if ((base=iop->_base)==NULL) {
53 			if (fstat(fileno(iop), &stbuf) < 0 ||
54 			    stbuf.st_blksize <= NULL)
55 				size = BUFSIZ;
56 			else
57 				size = stbuf.st_blksize;
58 			if ((iop->_base=base=malloc(size)) == NULL) {
59 				iop->_flag |= _IONBF;
60 				goto tryagain;
61 			}
62 			iop->_flag |= _IOMYBUF;
63 			iop->_bufsiz = size;
64 			if (iop==stdout && isatty(fileno(stdout))) {
65 				iop->_flag |= _IOLBF;
66 				iop->_ptr = base;
67 				goto tryagain;
68 			}
69 			rn = n = 0;
70 		} else
71 			rn = iop->_ptr - base;
72 		iop->_ptr = base;
73 		iop->_cnt = iop->_bufsiz;
74 	}
75 	while (rn > 0) {
76 		if ((n = write(fileno(iop), base, rn)) <= 0) {
77 			iop->_flag |= _IOERR;
78 			return(EOF);
79 		}
80 		rn -= n;
81 		base += n;
82 	}
83 	if ((iop->_flag&(_IOLBF|_IONBF)) == 0) {
84 		iop->_cnt--;
85 		*iop->_ptr++ = c;
86 	}
87 	return(c);
88 }
89 
90 fpurge(iop)
91 register FILE *iop;
92 {
93 	iop->_ptr = iop->_base;
94 	iop->_cnt = iop->_flag&(_IOLBF|_IONBF|_IOREAD) ? 0 : iop->_bufsiz;
95 	return(0);
96 }
97 
98 fflush(iop)
99 register FILE *iop;
100 {
101 	register char *base;
102 	register n, rn;
103 
104 	if ((iop->_flag&(_IONBF|_IOWRT))==_IOWRT &&
105 	    (base = iop->_base) != NULL && (rn = n = iop->_ptr - base) > 0) {
106 		iop->_ptr = base;
107 		iop->_cnt = (iop->_flag&(_IOLBF|_IONBF)) ? 0 : iop->_bufsiz;
108 		do {
109 			if ((n = write(fileno(iop), base, rn)) <= 0) {
110 				iop->_flag |= _IOERR;
111 				return(EOF);
112 			}
113 			rn -= n;
114 			base += n;
115 		} while (rn > 0);
116 	}
117 	return(0);
118 }
119 
120 fclose(iop)
121 	register FILE *iop;
122 {
123 	register int r;
124 
125 	r = EOF;
126 	if (iop->_flag&(_IOREAD|_IOWRT|_IORW) && (iop->_flag&_IOSTRG)==0) {
127 		r = fflush(iop);
128 		if (close(fileno(iop)) < 0)
129 			r = EOF;
130 		if (iop->_flag&_IOMYBUF)
131 			free(iop->_base);
132 	}
133 	iop->_cnt = 0;
134 	iop->_base = (char *)NULL;
135 	iop->_ptr = (char *)NULL;
136 	iop->_bufsiz = 0;
137 	iop->_flag = 0;
138 	iop->_file = 0;
139 	return(r);
140 }
141 
142 _cleanup()
143 {
144 	extern int _fwalk();
145 
146 	_fwalk(fclose);
147 }
148