]> git.ipfire.org Git - thirdparty/bash.git/blob - lib/sh/zread.c
94c426ff07f81a652469afb681a84ebf1148f9be
[thirdparty/bash.git] / lib / sh / zread.c
1 /* zread - read data from file descriptor into buffer with retries */
2
3 /* Copyright (C) 1999-2002 Free Software Foundation, Inc.
4
5 This file is part of GNU Bash, the Bourne Again SHell.
6
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 */
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
29 #include <errno.h>
30
31 #if !defined (errno)
32 extern int errno;
33 #endif
34
35 #ifndef SEEK_CUR
36 # define SEEK_CUR 1
37 #endif
38
39 /* Read LEN bytes from FD into BUF. Retry the read on EINTR. Any other
40 error causes the loop to break. */
41 ssize_t
42 zread (fd, buf, len)
43 int fd;
44 char *buf;
45 size_t len;
46 {
47 ssize_t r;
48
49 while ((r = read (fd, buf, len)) < 0 && errno == EINTR)
50 ;
51 return r;
52 }
53
54 /* Read LEN bytes from FD into BUF. Retry the read on EINTR, up to three
55 interrupts. Any other error causes the loop to break. */
56
57 #ifdef NUM_INTR
58 # undef NUM_INTR
59 #endif
60 #define NUM_INTR 3
61
62 ssize_t
63 zreadintr (fd, buf, len)
64 int fd;
65 char *buf;
66 size_t len;
67 {
68 ssize_t r;
69 int nintr;
70
71 for (nintr = 0; ; )
72 {
73 r = read (fd, buf, len);
74 if (r >= 0)
75 return r;
76 if (r == -1 && errno == EINTR)
77 {
78 if (++nintr > NUM_INTR)
79 return -1;
80 continue;
81 }
82 return r;
83 }
84 }
85
86 /* Read one character from FD and return it in CP. Return values are as
87 in read(2). This does some local buffering to avoid many one-character
88 calls to read(2), like those the `read' builtin performs. */
89
90 static char lbuf[128];
91 static size_t lind, lused;
92
93 ssize_t
94 zreadc (fd, cp)
95 int fd;
96 char *cp;
97 {
98 ssize_t nr;
99
100 if (lind == lused || lused == 0)
101 {
102 nr = zread (fd, lbuf, sizeof (lbuf));
103 lind = 0;
104 if (nr <= 0)
105 {
106 lused = 0;
107 return nr;
108 }
109 lused = nr;
110 }
111 if (cp)
112 *cp = lbuf[lind++];
113 return 1;
114 }
115
116 void
117 zreset ()
118 {
119 lind = lused = 0;
120 }
121
122 /* Sync the seek pointer for FD so that the kernel's idea of the last char
123 read is the last char returned by zreadc. */
124 void
125 zsyncfd (fd)
126 int fd;
127 {
128 off_t off;
129 int r;
130
131 off = lused - lind;
132 r = 0;
133 if (off > 0)
134 r = lseek (fd, -off, SEEK_CUR);
135
136 if (r >= 0)
137 lused = lind = 0;
138 }