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) 32extern 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. */ 41ssize_t 42zread (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 62ssize_t 63zreadretry (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/* Call read(2) and allow it to be interrupted. Just a stub for now. */ 87ssize_t 88zreadintr (fd, buf, len) 89 int fd; 90 char *buf; 91 size_t len; 92{ 93 return (read (fd, buf, len)); 94} 95 96/* Read one character from FD and return it in CP. Return values are as 97 in read(2). This does some local buffering to avoid many one-character 98 calls to read(2), like those the `read' builtin performs. */ 99 100static char lbuf[128]; 101static size_t lind, lused; 102 103ssize_t 104zreadc (fd, cp) 105 int fd; 106 char *cp; 107{ 108 ssize_t nr; 109 110 if (lind == lused || lused == 0) 111 { 112 nr = zread (fd, lbuf, sizeof (lbuf)); 113 lind = 0; 114 if (nr <= 0) 115 { 116 lused = 0; 117 return nr; 118 } 119 lused = nr; 120 } 121 if (cp) 122 *cp = lbuf[lind++]; 123 return 1; 124} 125 126/* Don't mix calls to zreadc and zreadcintr in the same function, since they 127 use the same local buffer. */ 128ssize_t 129zreadcintr (fd, cp) 130 int fd; 131 char *cp; 132{ 133 ssize_t nr; 134 135 if (lind == lused || lused == 0) 136 { 137 nr = zreadintr (fd, lbuf, sizeof (lbuf)); 138 lind = 0; 139 if (nr <= 0) 140 { 141 lused = 0; 142 return nr; 143 } 144 lused = nr; 145 } 146 if (cp) 147 *cp = lbuf[lind++]; 148 return 1; 149} 150 151void 152zreset () 153{ 154 lind = lused = 0; 155} 156 157/* Sync the seek pointer for FD so that the kernel's idea of the last char 158 read is the last char returned by zreadc. */ 159void 160zsyncfd (fd) 161 int fd; 162{ 163 off_t off; 164 int r; 165 166 off = lused - lind; 167 r = 0; 168 if (off > 0) 169 r = lseek (fd, -off, SEEK_CUR); 170 171 if (r >= 0) 172 lused = lind = 0; 173} 174