1 /*
2 * Copyright (c) 1990 The Regents of the University of California.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms are permitted
6 * provided that the above copyright notice and this paragraph are
7 * duplicated in all such forms and that any documentation,
8 * and/or other materials related to such
9 * distribution and use acknowledge that the software was developed
10 * by the University of California, Berkeley. The name of the
11 * University may not be used to endorse or promote products derived
12 * from this software without specific prior written permission.
13 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
14 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
15 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
16 */
17 /* No user fns here. Pesch 15apr92. */
18
19 #define _DEFAULT_SOURCE
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <errno.h>
23 #include "local.h"
24
25 static int
lflush(FILE * fp)26 lflush (FILE *fp)
27 {
28 if ((fp->_flags & (__SLBF | __SWR)) == (__SLBF | __SWR))
29 return fflush ( fp);
30 return 0;
31 }
32
33 /*
34 * Refill a stdio buffer.
35 * Return EOF on eof or error, 0 otherwise.
36 */
37
38 int
_srefill(register FILE * fp)39 _srefill (
40 register FILE * fp)
41 {
42 /* make sure stdio is set up */
43
44 CHECK_INIT (ptr, fp);
45
46 fp->_r = 0; /* largely a convenience for callers */
47
48 /* SysV does not make this test; take it out for compatibility */
49 if (fp->_flags & __SEOF)
50 return EOF;
51
52 /* if not already reading, have to be reading and writing */
53 if ((fp->_flags & __SRD) == 0)
54 {
55 if ((fp->_flags & __SRW) == 0)
56 {
57 _REENT_ERRNO(ptr) = EBADF;
58 fp->_flags |= __SERR;
59 return EOF;
60 }
61 /* switch to reading */
62 if (fp->_flags & __SWR)
63 {
64 if (fflush ( fp))
65 return EOF;
66 fp->_flags &= ~__SWR;
67 fp->_w = 0;
68 fp->_lbfsize = 0;
69 }
70 fp->_flags |= __SRD;
71 }
72 else
73 {
74 /*
75 * We were reading. If there is an ungetc buffer,
76 * we must have been reading from that. Drop it,
77 * restoring the previous buffer (if any). If there
78 * is anything in that buffer, return.
79 */
80 if (HASUB (fp))
81 {
82 FREEUB (ptr, fp);
83 if ((fp->_r = fp->_ur) != 0)
84 {
85 fp->_p = fp->_up;
86 return 0;
87 }
88 }
89 }
90
91 if (fp->_bf._base == NULL)
92 _smakebuf ( fp);
93
94 /*
95 * Before reading from a line buffered or unbuffered file,
96 * flush all line buffered output files, per the ANSI C
97 * standard.
98 */
99 if (fp->_flags & (__SLBF | __SNBF))
100 {
101 /* Ignore this file in _fwalk_sglue to avoid potential deadlock. */
102 short orig_flags = fp->_flags;
103 fp->_flags = 1;
104 (void) _fwalk_sglue (lflush, &__sglue);
105 fp->_flags = orig_flags;
106
107 /* Now flush this file without locking it. */
108 if ((fp->_flags & (__SLBF|__SWR)) == (__SLBF|__SWR))
109 _sflush ( fp);
110 }
111
112 fp->_p = fp->_bf._base;
113 fp->_r = fp->_read (fp->_cookie, (char *) fp->_p, fp->_bf._size);
114 if (fp->_r <= 0)
115 {
116 if (fp->_r == 0)
117 fp->_flags |= __SEOF;
118 else
119 {
120 fp->_r = 0;
121 fp->_flags |= __SERR;
122 }
123 return EOF;
124 }
125 return 0;
126 }
127