]> git.ipfire.org Git - thirdparty/bash.git/blame - lib/sh/zread.c
bash-5.0 distribution sources and documentation
[thirdparty/bash.git] / lib / sh / zread.c
CommitLineData
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)
33extern int errno;
34#endif
35
36#ifndef SEEK_CUR
37# define SEEK_CUR 1
38#endif
39
c9f1b046
CR
40extern int executing_builtin;
41
ac50fbac 42extern void check_signals_and_traps (void);
c9f1b046 43extern void check_signals (void);
ac50fbac
CR
44extern 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 48ssize_t
bb70624e
JA
49zread (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 76ssize_t
17345e5a 77zreadretry (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. */
101ssize_t
102zreadintr (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
115static char lbuf[128];
116static size_t lind, lused;
bb70624e 117
f73dda09 118ssize_t
bb70624e
JA
119zreadc (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. */
143ssize_t
144zreadcintr (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'. */
168ssize_t
169zreadn (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
194void
195zreset ()
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. */
202void
203zsyncfd (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}