1 /* asyn_read() Author: Kees J. Bot 2 * 7 Jul 1997 3 */ 4 #include "asyn.h" 5 #include <signal.h> 6 7 ssize_t asyn_read(asynchio_t *asyn, int fd, void *buf, size_t len) 8 /* Asynchronous read(). Try if a read can be done, if not then set a flag 9 * indicating that select(2) should look out for it. Returns like a normal 10 * read or returns -1 with errno set to EAGAIN. 11 */ 12 { 13 asynfd_t *afd; 14 15 /* Asyn_wait() may block if this counter equals zero indicating that 16 * all of the asyn_* functions are "in progress". 17 */ 18 asyn->asyn_more++; 19 20 if ((unsigned) fd >= FD_SETSIZE) { errno= EBADF; return -1; } 21 afd= &asyn->asyn_afd[fd]; 22 23 /* If this is the first async call on this filedescriptor then 24 * remember its file flags. 25 */ 26 if (!afd->afd_seen) { 27 if ((afd->afd_flags= fcntl(fd, F_GETFL)) < 0) return -1; 28 afd->afd_seen= 1; 29 } 30 31 /* Try to read if I/O is pending. */ 32 if (afd->afd_state[SEL_READ] == PENDING) { 33 sigset_t mask; 34 ssize_t result; 35 int err; 36 37 sigemptyset(&mask); 38 if (sigprocmask(SIG_SETMASK, &mask, &mask) < 0) return -1; 39 (void) fcntl(fd, F_SETFL, afd->afd_flags | O_NONBLOCK); 40 41 /* Try the actual read. */ 42 result= read(fd, buf, len); 43 err= errno; 44 45 (void) fcntl(fd, F_SETFL, afd->afd_flags); 46 (void) sigprocmask(SIG_SETMASK, &mask, nil); 47 48 errno= err; 49 if (result != -1 || errno != EAGAIN) { 50 afd->afd_state[SEL_READ]= IDLE; 51 return result; 52 } 53 } 54 55 /* Record this read as "waiting". */ 56 afd->afd_state[SEL_READ]= WAITING; 57 FD_SET(fd, &asyn->asyn_fdset[SEL_READ]); 58 errno= EAGAIN; 59 asyn->asyn_more--; 60 return -1; 61 } 62