xref: /original-bsd/lib/libc/stdio/wbuf.c (revision 9eb838fd)
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.4 (Berkeley) 12/19/88";
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 (iop->_ptr >= base+iop->_bufsiz || c == '\n') {
39 			n = write(fileno(iop), base, rn = iop->_ptr - base);
40 			iop->_ptr = base;
41 			iop->_cnt = 0;
42 		} else
43 			rn = n = 0;
44 	} else if (iop->_flag&_IONBF) {
45 		c1 = c;
46 		rn = 1;
47 		n = write(fileno(iop), &c1, rn);
48 		iop->_cnt = 0;
49 	} else {
50 		if ((base=iop->_base)==NULL) {
51 			if (fstat(fileno(iop), &stbuf) < 0 ||
52 			    stbuf.st_blksize <= NULL)
53 				size = BUFSIZ;
54 			else
55 				size = stbuf.st_blksize;
56 			if ((iop->_base=base=malloc(size)) == NULL) {
57 				iop->_flag |= _IONBF;
58 				goto tryagain;
59 			}
60 			iop->_flag |= _IOMYBUF;
61 			iop->_bufsiz = size;
62 			if (iop==stdout && isatty(fileno(stdout))) {
63 				iop->_flag |= _IOLBF;
64 				iop->_ptr = base;
65 				goto tryagain;
66 			}
67 			rn = n = 0;
68 		} else if ((rn = n = iop->_ptr - base) > 0) {
69 			iop->_ptr = base;
70 			n = write(fileno(iop), base, n);
71 		}
72 		iop->_cnt = iop->_bufsiz-1;
73 		*base++ = c;
74 		iop->_ptr = base;
75 	}
76 	if (rn != n) {
77 		iop->_flag |= _IOERR;
78 		return(EOF);
79 	}
80 	return(c);
81 }
82 
83 fpurge(iop)
84 register FILE *iop;
85 {
86 	iop->_ptr = iop->_base;
87 	iop->_cnt = iop->_flag&(_IOLBF|_IONBF|_IOREAD) ? 0 : iop->_bufsiz;
88 	return(0);
89 }
90 
91 fflush(iop)
92 register FILE *iop;
93 {
94 	register char *base;
95 	register n;
96 
97 	if ((iop->_flag&(_IONBF|_IOWRT))==_IOWRT
98 	 && (base=iop->_base)!=NULL && (n=iop->_ptr-base)>0) {
99 		iop->_ptr = base;
100 		iop->_cnt = (iop->_flag&(_IOLBF|_IONBF)) ? 0 : iop->_bufsiz;
101 		if (write(fileno(iop), base, n)!=n) {
102 			iop->_flag |= _IOERR;
103 			return(EOF);
104 		}
105 	}
106 	return(0);
107 }
108 
109 fclose(iop)
110 	register FILE *iop;
111 {
112 	register int r;
113 
114 	r = EOF;
115 	if (iop->_flag&(_IOREAD|_IOWRT|_IORW) && (iop->_flag&_IOSTRG)==0) {
116 		r = fflush(iop);
117 		if (close(fileno(iop)) < 0)
118 			r = EOF;
119 		if (iop->_flag&_IOMYBUF)
120 			free(iop->_base);
121 	}
122 	iop->_cnt = 0;
123 	iop->_base = (char *)NULL;
124 	iop->_ptr = (char *)NULL;
125 	iop->_bufsiz = 0;
126 	iop->_flag = 0;
127 	iop->_file = 0;
128 	return(r);
129 }
130 
131 _cleanup()
132 {
133 	extern int _fwalk();
134 
135 	_fwalk(fclose);
136 }
137