xref: /original-bsd/lib/libc/stdio/refill.c (revision 7f8f2e51)
1 /*-
2  * Copyright (c) 1990 The Regents of the University of California.
3  * All rights reserved.
4  *
5  * This code is derived from software contributed to Berkeley by
6  * Chris Torek.
7  *
8  * %sccs.include.redist.c%
9  */
10 
11 #if defined(LIBC_SCCS) && !defined(lint)
12 static char sccsid[] = "@(#)refill.c	5.2 (Berkeley) 02/01/91";
13 #endif /* LIBC_SCCS and not lint */
14 
15 #include <errno.h>
16 #include <stdio.h>
17 #include "local.h"
18 
19 static
20 lflush(fp)
21 	FILE *fp;
22 {
23 
24 	if ((fp->_flags & (__SLBF|__SWR)) == __SLBF|__SWR)
25 		return (__sflush(fp));
26 	return (0);
27 }
28 
29 /*
30  * Refill a stdio buffer.
31  * Return EOF on eof or error, 0 otherwise.
32  */
33 __srefill(fp)
34 	register FILE *fp;
35 {
36 
37 	/* make sure stdio is set up */
38 	if (!__sdidinit)
39 		__sinit();
40 
41 	fp->_r = 0;		/* largely a convenience for callers */
42 
43 	/* SysV does not make this test; take it out for compatibility */
44 	if (fp->_flags & __SEOF)
45 		return (EOF);
46 
47 	/* if not already reading, have to be reading and writing */
48 	if ((fp->_flags & __SRD) == 0) {
49 		if ((fp->_flags & __SRW) == 0) {
50 			errno = EBADF;
51 			return (EOF);
52 		}
53 		/* switch to reading */
54 		if (fp->_flags & __SWR) {
55 			if (__sflush(fp))
56 				return (EOF);
57 			fp->_flags &= ~__SWR;
58 			fp->_w = 0;
59 			fp->_lbfsize = 0;
60 		}
61 		fp->_flags |= __SRD;
62 	} else {
63 		/*
64 		 * We were reading.  If there is an ungetc buffer,
65 		 * we must have been reading from that.  Drop it,
66 		 * restoring the previous buffer (if any).  If there
67 		 * is anything in that buffer, return.
68 		 */
69 		if (HASUB(fp)) {
70 			FREEUB(fp);
71 			if ((fp->_r = fp->_ur) != 0) {
72 				fp->_p = fp->_up;
73 				return (0);
74 			}
75 		}
76 	}
77 
78 	if (fp->_bf._base == NULL)
79 		__smakebuf(fp);
80 
81 	/*
82 	 * Before reading from a line buffered or unbuffered file,
83 	 * flush all line buffered output files, per the ANSI C
84 	 * standard.
85 	 */
86 	if (fp->_flags & (__SLBF|__SNBF))
87 		(void) _fwalk(lflush);
88 	fp->_p = fp->_bf._base;
89 	fp->_r = (*fp->_read)(fp->_cookie, (char *)fp->_p, fp->_bf._size);
90 	fp->_flags &= ~__SMOD;	/* buffer contents are again pristine */
91 	if (fp->_r <= 0) {
92 		if (fp->_r == 0)
93 			fp->_flags |= __SEOF;
94 		else {
95 			fp->_r = 0;
96 			fp->_flags |= __SERR;
97 		}
98 		return (EOF);
99 	}
100 	return (0);
101 }
102