1 #include "syshdrs.h"
2 
3 #if !defined(NO_SIGNALS) && defined(SIGPIPE)
4 extern volatile Sjmp_buf gPipeJmp;
5 #endif
6 
7 /* Read up to "size" bytes on sfd.
8  *
9  * If "retry" is on, after a successful read of less than "size"
10  * bytes, it will attempt to read more, upto "size."
11  *
12  * Although "retry" would seem to indicate you may want to always
13  * read "size" bytes or else it is an error, even with that on you
14  * may get back a value < size.  Set "retry" to 0 when you want to
15  * return as soon as there is a chunk of data whose size is <= "size".
16  */
17 
18 int
PRead(int sfd,char * const buf0,size_t size,int retry)19 PRead(int sfd, char *const buf0, size_t size, int retry)
20 {
21 	int nread;
22 	volatile int nleft;
23 	char *volatile buf = buf0;
24 #if !defined(NO_SIGNALS) && defined(SIGPIPE)
25 	vsio_sigproc_t sigpipe;
26 
27 	if (SSetjmp(gPipeJmp) != 0) {
28 		(void) SSignal(SIGPIPE, (sio_sigproc_t) sigpipe);
29 		nread = size - nleft;
30 		if (nread > 0)
31 			return (nread);
32 		errno = EPIPE;
33 		return (kBrokenPipeErr);
34 	}
35 
36 	sigpipe = (vsio_sigproc_t) SSignal(SIGPIPE, SIOHandler);
37 #endif
38 	errno = 0;
39 
40 	nleft = (int) size;
41 	forever {
42 		nread = read(sfd, buf, nleft);
43 		if (nread <= 0) {
44 			if (nread == 0) {
45 				/* EOF */
46 				nread = size - nleft;
47 				goto done;
48 			} else if (errno != EINTR) {
49 				nread = size - nleft;
50 				if (nread == 0)
51 					nread = -1;
52 				goto done;
53 			} else {
54 				errno = 0;
55 				nread = 0;
56 				/* Try again. */
57 			}
58 		}
59 		nleft -= nread;
60 		if ((nleft <= 0) || (retry == 0))
61 			break;
62 		buf += nread;
63 	}
64 	nread = size - nleft;
65 
66 done:
67 #if !defined(NO_SIGNALS) && defined(SIGPIPE)
68 	(void) SSignal(SIGPIPE, (sio_sigproc_t) sigpipe);
69 #endif
70 	return (nread);
71 }	/* PRead */
72