Jari Aalto | 3185942 | 2009-01-12 13:36:28 +0000 | [diff] [blame] | 1 | /* zread - read data from file descriptor into buffer with retries */ |
| 2 | |
Jari Aalto | 7117c2d | 2002-07-17 14:10:11 +0000 | [diff] [blame] | 3 | /* Copyright (C) 1999-2002 Free Software Foundation, Inc. |
Jari Aalto | bb70624 | 2000-03-17 21:46:59 +0000 | [diff] [blame] | 4 | |
| 5 | This file is part of GNU Bash, the Bourne Again SHell. |
| 6 | |
Jari Aalto | 3185942 | 2009-01-12 13:36:28 +0000 | [diff] [blame] | 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. |
Jari Aalto | bb70624 | 2000-03-17 21:46:59 +0000 | [diff] [blame] | 11 | |
Jari Aalto | 3185942 | 2009-01-12 13:36:28 +0000 | [diff] [blame] | 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 | */ |
Jari Aalto | bb70624 | 2000-03-17 21:46:59 +0000 | [diff] [blame] | 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 | |
Chet Ramey | ac50fba | 2014-02-26 09:36:43 -0500 | [diff] [blame] | 29 | #include <signal.h> |
Jari Aalto | bb70624 | 2000-03-17 21:46:59 +0000 | [diff] [blame] | 30 | #include <errno.h> |
| 31 | |
| 32 | #if !defined (errno) |
Ricardo Cerqueira | a02fbff | 2013-07-25 22:35:34 +0100 | [diff] [blame] | 33 | #include <errno.h> |
Jari Aalto | bb70624 | 2000-03-17 21:46:59 +0000 | [diff] [blame] | 34 | #endif |
| 35 | |
| 36 | #ifndef SEEK_CUR |
| 37 | # define SEEK_CUR 1 |
| 38 | #endif |
| 39 | |
Chet Ramey | ac50fba | 2014-02-26 09:36:43 -0500 | [diff] [blame] | 40 | extern void check_signals_and_traps (void); |
| 41 | extern int signal_is_trapped (int); |
| 42 | |
Jari Aalto | bb70624 | 2000-03-17 21:46:59 +0000 | [diff] [blame] | 43 | /* Read LEN bytes from FD into BUF. Retry the read on EINTR. Any other |
| 44 | error causes the loop to break. */ |
Jari Aalto | f73dda0 | 2001-11-13 17:56:06 +0000 | [diff] [blame] | 45 | ssize_t |
Jari Aalto | bb70624 | 2000-03-17 21:46:59 +0000 | [diff] [blame] | 46 | zread (fd, buf, len) |
| 47 | int fd; |
| 48 | char *buf; |
| 49 | size_t len; |
| 50 | { |
Jari Aalto | f73dda0 | 2001-11-13 17:56:06 +0000 | [diff] [blame] | 51 | ssize_t r; |
Jari Aalto | bb70624 | 2000-03-17 21:46:59 +0000 | [diff] [blame] | 52 | |
Chet Ramey | ac50fba | 2014-02-26 09:36:43 -0500 | [diff] [blame] | 53 | #if 0 |
| 54 | #if defined (HAVE_SIGINTERRUPT) |
| 55 | if (signal_is_trapped (SIGCHLD)) |
| 56 | siginterrupt (SIGCHLD, 1); |
| 57 | #endif |
| 58 | #endif |
| 59 | |
Jari Aalto | bb70624 | 2000-03-17 21:46:59 +0000 | [diff] [blame] | 60 | while ((r = read (fd, buf, len)) < 0 && errno == EINTR) |
Chet Ramey | ac50fba | 2014-02-26 09:36:43 -0500 | [diff] [blame] | 61 | check_signals_and_traps (); /* XXX - should it be check_signals()? */ |
| 62 | |
| 63 | #if 0 |
| 64 | #if defined (HAVE_SIGINTERRUPT) |
| 65 | siginterrupt (SIGCHLD, 0); |
| 66 | #endif |
| 67 | #endif |
| 68 | |
Jari Aalto | bb70624 | 2000-03-17 21:46:59 +0000 | [diff] [blame] | 69 | return r; |
| 70 | } |
| 71 | |
| 72 | /* Read LEN bytes from FD into BUF. Retry the read on EINTR, up to three |
| 73 | interrupts. Any other error causes the loop to break. */ |
| 74 | |
| 75 | #ifdef NUM_INTR |
| 76 | # undef NUM_INTR |
| 77 | #endif |
| 78 | #define NUM_INTR 3 |
| 79 | |
Jari Aalto | f73dda0 | 2001-11-13 17:56:06 +0000 | [diff] [blame] | 80 | ssize_t |
Jari Aalto | 17345e5 | 2009-02-19 22:21:29 +0000 | [diff] [blame] | 81 | zreadretry (fd, buf, len) |
Jari Aalto | bb70624 | 2000-03-17 21:46:59 +0000 | [diff] [blame] | 82 | int fd; |
| 83 | char *buf; |
| 84 | size_t len; |
| 85 | { |
Jari Aalto | f73dda0 | 2001-11-13 17:56:06 +0000 | [diff] [blame] | 86 | ssize_t r; |
| 87 | int nintr; |
Jari Aalto | bb70624 | 2000-03-17 21:46:59 +0000 | [diff] [blame] | 88 | |
| 89 | for (nintr = 0; ; ) |
| 90 | { |
| 91 | r = read (fd, buf, len); |
| 92 | if (r >= 0) |
Jari Aalto | 28ef6c3 | 2001-04-06 19:14:31 +0000 | [diff] [blame] | 93 | return r; |
Jari Aalto | bb70624 | 2000-03-17 21:46:59 +0000 | [diff] [blame] | 94 | if (r == -1 && errno == EINTR) |
| 95 | { |
Jari Aalto | 17345e5 | 2009-02-19 22:21:29 +0000 | [diff] [blame] | 96 | if (++nintr >= NUM_INTR) |
Jari Aalto | bb70624 | 2000-03-17 21:46:59 +0000 | [diff] [blame] | 97 | return -1; |
| 98 | continue; |
| 99 | } |
| 100 | return r; |
| 101 | } |
| 102 | } |
| 103 | |
Jari Aalto | 17345e5 | 2009-02-19 22:21:29 +0000 | [diff] [blame] | 104 | /* Call read(2) and allow it to be interrupted. Just a stub for now. */ |
| 105 | ssize_t |
| 106 | zreadintr (fd, buf, len) |
| 107 | int fd; |
| 108 | char *buf; |
| 109 | size_t len; |
| 110 | { |
| 111 | return (read (fd, buf, len)); |
| 112 | } |
| 113 | |
Jari Aalto | bb70624 | 2000-03-17 21:46:59 +0000 | [diff] [blame] | 114 | /* Read one character from FD and return it in CP. Return values are as |
| 115 | in read(2). This does some local buffering to avoid many one-character |
| 116 | calls to read(2), like those the `read' builtin performs. */ |
| 117 | |
Jari Aalto | f73dda0 | 2001-11-13 17:56:06 +0000 | [diff] [blame] | 118 | static char lbuf[128]; |
| 119 | static size_t lind, lused; |
Jari Aalto | bb70624 | 2000-03-17 21:46:59 +0000 | [diff] [blame] | 120 | |
Jari Aalto | f73dda0 | 2001-11-13 17:56:06 +0000 | [diff] [blame] | 121 | ssize_t |
Jari Aalto | bb70624 | 2000-03-17 21:46:59 +0000 | [diff] [blame] | 122 | zreadc (fd, cp) |
| 123 | int fd; |
| 124 | char *cp; |
| 125 | { |
Jari Aalto | f73dda0 | 2001-11-13 17:56:06 +0000 | [diff] [blame] | 126 | ssize_t nr; |
Jari Aalto | bb70624 | 2000-03-17 21:46:59 +0000 | [diff] [blame] | 127 | |
| 128 | if (lind == lused || lused == 0) |
| 129 | { |
Jari Aalto | f73dda0 | 2001-11-13 17:56:06 +0000 | [diff] [blame] | 130 | nr = zread (fd, lbuf, sizeof (lbuf)); |
Jari Aalto | bb70624 | 2000-03-17 21:46:59 +0000 | [diff] [blame] | 131 | lind = 0; |
Jari Aalto | f73dda0 | 2001-11-13 17:56:06 +0000 | [diff] [blame] | 132 | if (nr <= 0) |
| 133 | { |
| 134 | lused = 0; |
| 135 | return nr; |
| 136 | } |
| 137 | lused = nr; |
Jari Aalto | bb70624 | 2000-03-17 21:46:59 +0000 | [diff] [blame] | 138 | } |
| 139 | if (cp) |
Jari Aalto | f73dda0 | 2001-11-13 17:56:06 +0000 | [diff] [blame] | 140 | *cp = lbuf[lind++]; |
Jari Aalto | bb70624 | 2000-03-17 21:46:59 +0000 | [diff] [blame] | 141 | return 1; |
| 142 | } |
| 143 | |
Jari Aalto | 17345e5 | 2009-02-19 22:21:29 +0000 | [diff] [blame] | 144 | /* Don't mix calls to zreadc and zreadcintr in the same function, since they |
| 145 | use the same local buffer. */ |
| 146 | ssize_t |
| 147 | zreadcintr (fd, cp) |
| 148 | int fd; |
| 149 | char *cp; |
| 150 | { |
| 151 | ssize_t nr; |
| 152 | |
| 153 | if (lind == lused || lused == 0) |
| 154 | { |
| 155 | nr = zreadintr (fd, lbuf, sizeof (lbuf)); |
| 156 | lind = 0; |
| 157 | if (nr <= 0) |
| 158 | { |
| 159 | lused = 0; |
| 160 | return nr; |
| 161 | } |
| 162 | lused = nr; |
| 163 | } |
| 164 | if (cp) |
| 165 | *cp = lbuf[lind++]; |
| 166 | return 1; |
| 167 | } |
| 168 | |
Chet Ramey | ac50fba | 2014-02-26 09:36:43 -0500 | [diff] [blame] | 169 | /* Like zreadc, but read a specified number of characters at a time. Used |
| 170 | for `read -N'. */ |
| 171 | ssize_t |
| 172 | zreadn (fd, cp, len) |
| 173 | int fd; |
| 174 | char *cp; |
| 175 | size_t len; |
| 176 | { |
| 177 | ssize_t nr; |
| 178 | |
| 179 | if (lind == lused || lused == 0) |
| 180 | { |
| 181 | if (len > sizeof (lbuf)) |
| 182 | len = sizeof (lbuf); |
| 183 | nr = zread (fd, lbuf, len); |
| 184 | lind = 0; |
| 185 | if (nr <= 0) |
| 186 | { |
| 187 | lused = 0; |
| 188 | return nr; |
| 189 | } |
| 190 | lused = nr; |
| 191 | } |
| 192 | if (cp) |
| 193 | *cp = lbuf[lind++]; |
| 194 | return 1; |
| 195 | } |
| 196 | |
Jari Aalto | bb70624 | 2000-03-17 21:46:59 +0000 | [diff] [blame] | 197 | void |
| 198 | zreset () |
| 199 | { |
| 200 | lind = lused = 0; |
| 201 | } |
| 202 | |
| 203 | /* Sync the seek pointer for FD so that the kernel's idea of the last char |
| 204 | read is the last char returned by zreadc. */ |
| 205 | void |
| 206 | zsyncfd (fd) |
| 207 | int fd; |
| 208 | { |
Chet Ramey | ea6616c | 2012-03-13 15:11:43 -0400 | [diff] [blame] | 209 | off_t off, r; |
Jari Aalto | bb70624 | 2000-03-17 21:46:59 +0000 | [diff] [blame] | 210 | |
| 211 | off = lused - lind; |
Jari Aalto | 95732b4 | 2005-12-07 14:08:12 +0000 | [diff] [blame] | 212 | r = 0; |
Jari Aalto | bb70624 | 2000-03-17 21:46:59 +0000 | [diff] [blame] | 213 | if (off > 0) |
Jari Aalto | 95732b4 | 2005-12-07 14:08:12 +0000 | [diff] [blame] | 214 | r = lseek (fd, -off, SEEK_CUR); |
| 215 | |
Chet Ramey | ea6616c | 2012-03-13 15:11:43 -0400 | [diff] [blame] | 216 | if (r != -1) |
Jari Aalto | 95732b4 | 2005-12-07 14:08:12 +0000 | [diff] [blame] | 217 | lused = lind = 0; |
Jari Aalto | bb70624 | 2000-03-17 21:46:59 +0000 | [diff] [blame] | 218 | } |