]>
Commit | Line | Data |
---|---|---|
3185942a JA |
1 | /* zread - read data from file descriptor into buffer with retries */ |
2 | ||
d233b485 | 3 | /* Copyright (C) 1999-2017 Free Software Foundation, Inc. |
bb70624e JA |
4 | |
5 | This file is part of GNU Bash, the Bourne Again SHell. | |
6 | ||
3185942a JA |
7 | Bash is free software: you can redistribute it and/or modify |
8 | it under the terms of the GNU General Public License as published by | |
9 | the Free Software Foundation, either version 3 of the License, or | |
10 | (at your option) any later version. | |
11 | ||
12 | Bash is distributed in the hope that it will be useful, | |
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
15 | GNU General Public License for more details. | |
16 | ||
17 | You should have received a copy of the GNU General Public License | |
18 | along with Bash. If not, see <http://www.gnu.org/licenses/>. | |
19 | */ | |
bb70624e JA |
20 | |
21 | #include <config.h> | |
22 | ||
23 | #include <sys/types.h> | |
24 | ||
25 | #if defined (HAVE_UNISTD_H) | |
26 | # include <unistd.h> | |
27 | #endif | |
28 | ||
ac50fbac | 29 | #include <signal.h> |
bb70624e JA |
30 | #include <errno.h> |
31 | ||
32 | #if !defined (errno) | |
33 | extern int errno; | |
34 | #endif | |
35 | ||
36 | #ifndef SEEK_CUR | |
37 | # define SEEK_CUR 1 | |
38 | #endif | |
39 | ||
c9f1b046 CR |
40 | extern int executing_builtin; |
41 | ||
ac50fbac | 42 | extern void check_signals_and_traps (void); |
c9f1b046 | 43 | extern void check_signals (void); |
ac50fbac CR |
44 | extern int signal_is_trapped (int); |
45 | ||
bb70624e JA |
46 | /* Read LEN bytes from FD into BUF. Retry the read on EINTR. Any other |
47 | error causes the loop to break. */ | |
f73dda09 | 48 | ssize_t |
bb70624e JA |
49 | zread (fd, buf, len) |
50 | int fd; | |
51 | char *buf; | |
52 | size_t len; | |
53 | { | |
f73dda09 | 54 | ssize_t r; |
bb70624e | 55 | |
d233b485 | 56 | check_signals (); /* check for signals before a blocking read */ |
bb70624e | 57 | while ((r = read (fd, buf, len)) < 0 && errno == EINTR) |
c9f1b046 CR |
58 | /* XXX - bash-5.0 */ |
59 | /* We check executing_builtin and run traps here for backwards compatibility */ | |
60 | if (executing_builtin) | |
61 | check_signals_and_traps (); /* XXX - should it be check_signals()? */ | |
62 | else | |
63 | check_signals (); | |
ac50fbac | 64 | |
bb70624e JA |
65 | return r; |
66 | } | |
67 | ||
68 | /* Read LEN bytes from FD into BUF. Retry the read on EINTR, up to three | |
69 | interrupts. Any other error causes the loop to break. */ | |
70 | ||
71 | #ifdef NUM_INTR | |
72 | # undef NUM_INTR | |
73 | #endif | |
74 | #define NUM_INTR 3 | |
75 | ||
f73dda09 | 76 | ssize_t |
17345e5a | 77 | zreadretry (fd, buf, len) |
bb70624e JA |
78 | int fd; |
79 | char *buf; | |
80 | size_t len; | |
81 | { | |
f73dda09 JA |
82 | ssize_t r; |
83 | int nintr; | |
bb70624e JA |
84 | |
85 | for (nintr = 0; ; ) | |
86 | { | |
87 | r = read (fd, buf, len); | |
88 | if (r >= 0) | |
28ef6c31 | 89 | return r; |
bb70624e JA |
90 | if (r == -1 && errno == EINTR) |
91 | { | |
17345e5a | 92 | if (++nintr >= NUM_INTR) |
bb70624e JA |
93 | return -1; |
94 | continue; | |
95 | } | |
96 | return r; | |
97 | } | |
98 | } | |
99 | ||
17345e5a JA |
100 | /* Call read(2) and allow it to be interrupted. Just a stub for now. */ |
101 | ssize_t | |
102 | zreadintr (fd, buf, len) | |
103 | int fd; | |
104 | char *buf; | |
105 | size_t len; | |
106 | { | |
d233b485 | 107 | check_signals (); |
17345e5a JA |
108 | return (read (fd, buf, len)); |
109 | } | |
110 | ||
bb70624e JA |
111 | /* Read one character from FD and return it in CP. Return values are as |
112 | in read(2). This does some local buffering to avoid many one-character | |
113 | calls to read(2), like those the `read' builtin performs. */ | |
114 | ||
f73dda09 JA |
115 | static char lbuf[128]; |
116 | static size_t lind, lused; | |
bb70624e | 117 | |
f73dda09 | 118 | ssize_t |
bb70624e JA |
119 | zreadc (fd, cp) |
120 | int fd; | |
121 | char *cp; | |
122 | { | |
f73dda09 | 123 | ssize_t nr; |
bb70624e JA |
124 | |
125 | if (lind == lused || lused == 0) | |
126 | { | |
f73dda09 | 127 | nr = zread (fd, lbuf, sizeof (lbuf)); |
bb70624e | 128 | lind = 0; |
f73dda09 JA |
129 | if (nr <= 0) |
130 | { | |
131 | lused = 0; | |
132 | return nr; | |
133 | } | |
134 | lused = nr; | |
bb70624e JA |
135 | } |
136 | if (cp) | |
f73dda09 | 137 | *cp = lbuf[lind++]; |
bb70624e JA |
138 | return 1; |
139 | } | |
140 | ||
17345e5a JA |
141 | /* Don't mix calls to zreadc and zreadcintr in the same function, since they |
142 | use the same local buffer. */ | |
143 | ssize_t | |
144 | zreadcintr (fd, cp) | |
145 | int fd; | |
146 | char *cp; | |
147 | { | |
148 | ssize_t nr; | |
149 | ||
150 | if (lind == lused || lused == 0) | |
151 | { | |
152 | nr = zreadintr (fd, lbuf, sizeof (lbuf)); | |
153 | lind = 0; | |
154 | if (nr <= 0) | |
155 | { | |
156 | lused = 0; | |
157 | return nr; | |
158 | } | |
159 | lused = nr; | |
160 | } | |
161 | if (cp) | |
162 | *cp = lbuf[lind++]; | |
163 | return 1; | |
164 | } | |
165 | ||
ac50fbac CR |
166 | /* Like zreadc, but read a specified number of characters at a time. Used |
167 | for `read -N'. */ | |
168 | ssize_t | |
169 | zreadn (fd, cp, len) | |
170 | int fd; | |
171 | char *cp; | |
172 | size_t len; | |
173 | { | |
174 | ssize_t nr; | |
175 | ||
176 | if (lind == lused || lused == 0) | |
177 | { | |
178 | if (len > sizeof (lbuf)) | |
179 | len = sizeof (lbuf); | |
180 | nr = zread (fd, lbuf, len); | |
181 | lind = 0; | |
182 | if (nr <= 0) | |
183 | { | |
184 | lused = 0; | |
185 | return nr; | |
186 | } | |
187 | lused = nr; | |
188 | } | |
189 | if (cp) | |
190 | *cp = lbuf[lind++]; | |
191 | return 1; | |
192 | } | |
193 | ||
bb70624e JA |
194 | void |
195 | zreset () | |
196 | { | |
197 | lind = lused = 0; | |
198 | } | |
199 | ||
200 | /* Sync the seek pointer for FD so that the kernel's idea of the last char | |
201 | read is the last char returned by zreadc. */ | |
202 | void | |
203 | zsyncfd (fd) | |
204 | int fd; | |
205 | { | |
ea6616c0 | 206 | off_t off, r; |
bb70624e JA |
207 | |
208 | off = lused - lind; | |
95732b49 | 209 | r = 0; |
bb70624e | 210 | if (off > 0) |
95732b49 JA |
211 | r = lseek (fd, -off, SEEK_CUR); |
212 | ||
ea6616c0 | 213 | if (r != -1) |
95732b49 | 214 | lused = lind = 0; |
bb70624e | 215 | } |