1 #include "syshdrs.h"
2 
3 #ifndef NO_SIGNALS
4 extern volatile Sjmp_buf gNetTimeoutJmp;
5 extern volatile Sjmp_buf gPipeJmp;
6 #endif
7 
8 #ifndef NO_SIGNALS
9 
10 int
SRecv(int sfd,char * const buf0,size_t size,int fl,int tlen,int retry)11 SRecv(int sfd, char *const buf0, size_t size, int fl, int tlen, int retry)
12 {
13 	int nread;
14 	volatile int nleft;
15 	char *volatile buf = buf0;
16 	int tleft;
17 	vsio_sigproc_t sigalrm, sigpipe;
18 	time_t done, now;
19 
20 	if (SSetjmp(gNetTimeoutJmp) != 0) {
21 		alarm(0);
22 		(void) SSignal(SIGALRM, (sio_sigproc_t) sigalrm);
23 		(void) SSignal(SIGPIPE, (sio_sigproc_t) sigpipe);
24 		nread = size - nleft;
25 		if ((nread > 0) && (retry == kFullBufferNotRequired))
26 			return (nread);
27 		errno = ETIMEDOUT;
28 		return (kTimeoutErr);
29 	}
30 
31 	if (SSetjmp(gPipeJmp) != 0) {
32 		alarm(0);
33 		(void) SSignal(SIGALRM, (sio_sigproc_t) sigalrm);
34 		(void) SSignal(SIGPIPE, (sio_sigproc_t) sigpipe);
35 		nread = size - nleft;
36 		if ((nread > 0) && (retry == kFullBufferNotRequired))
37 			return (nread);
38 		errno = EPIPE;
39 		return (kBrokenPipeErr);
40 	}
41 
42 	sigalrm = (vsio_sigproc_t) SSignal(SIGALRM, SIOHandler);
43 	sigpipe = (vsio_sigproc_t) SSignal(SIGPIPE, SIOHandler);
44 	errno = 0;
45 
46 	nleft = (int) size;
47 	time(&now);
48 	done = now + tlen;
49 	forever {
50 		tleft = (int) (done - now);
51 		if (tleft < 1) {
52 			nread = size - nleft;
53 			if ((nread == 0) || (retry == kFullBufferRequired)) {
54 				nread = kTimeoutErr;
55 				errno = ETIMEDOUT;
56 			}
57 			goto done;
58 		}
59 		(void) alarm((unsigned int) tleft);
60 		nread = recv(sfd, (char *) buf, nleft, fl);
61 		(void) alarm(0);
62 		if (nread <= 0) {
63 			if (nread == 0) {
64 				/* EOF */
65 				if (retry == kFullBufferRequiredExceptLast)
66 					nread = size - nleft;
67 				goto done;
68 			} else if (errno != EINTR) {
69 				nread = size - nleft;
70 				if (nread == 0)
71 					nread = -1;
72 				goto done;
73 			} else {
74 				errno = 0;
75 				nread = 0;
76 				/* Try again. */
77 			}
78 		}
79 		nleft -= nread;
80 		if ((nleft <= 0) || ((retry == 0) && (nleft != (int) size)))
81 			break;
82 		buf += nread;
83 		time(&now);
84 	}
85 	nread = size - nleft;
86 
87 done:
88 	(void) SSignal(SIGALRM, (sio_sigproc_t) sigalrm);
89 	(void) SSignal(SIGPIPE, (sio_sigproc_t) sigpipe);
90 
91 	return (nread);
92 }	/* SRecv */
93 
94 #else
95 
96 int
SRecv(int sfd,char * const buf0,size_t size,int fl,int tlen,int retry)97 SRecv(int sfd, char *const buf0, size_t size, int fl, int tlen, int retry)
98 {
99 	int nread;
100 	int nleft;
101 	char *buf = buf0;
102 	int tleft;
103 	time_t done, now;
104 	fd_set ss;
105 	struct timeval tv;
106 	int result;
107 
108 	errno = 0;
109 
110 	nleft = (int) size;
111 	time(&now);
112 	done = now + tlen;
113 	forever {
114 		tleft = (int) (done - now);
115 		if (tleft < 1) {
116 			nread = size - nleft;
117 			if ((nread == 0) || (retry == kFullBufferRequired)) {
118 				nread = kTimeoutErr;
119 				errno = ETIMEDOUT;
120 				SETWSATIMEOUTERR
121 			}
122 			goto done;
123 		}
124 
125 		forever {
126 			errno = 0;
127 			FD_ZERO(&ss);
128 			FD_SET(sfd, &ss);
129 			tv.tv_sec = tlen;
130 			tv.tv_usec = 0;
131 			result = select(sfd + 1, SELECT_TYPE_ARG234 &ss, NULL, NULL, SELECT_TYPE_ARG5 &tv);
132 			if (result == 1) {
133 				/* ready */
134 				break;
135 			} else if (result == 0) {
136 				/* timeout */
137 				nread = size - nleft;
138 				if ((nread > 0) && (retry == kFullBufferNotRequired))
139 					return (nread);
140 				errno = ETIMEDOUT;
141 				SETWSATIMEOUTERR
142 				return (kTimeoutErr);
143 			} else if (errno != EINTR) {
144 				return (-1);
145 			}
146 		}
147 
148 #if defined(WIN32) || defined(_WINDOWS)
149 		nread = recv(sfd, (char *) buf, nleft, fl);
150 #else
151 		nread = recv(sfd, (char *) buf, nleft, fl);
152 #endif
153 
154 		if (nread <= 0) {
155 			if (nread == 0) {
156 				/* EOF */
157 				if (retry == kFullBufferRequiredExceptLast)
158 					nread = size - nleft;
159 				goto done;
160 			} else if (errno != EINTR) {
161 				nread = size - nleft;
162 				if (nread == 0)
163 					nread = -1;
164 				goto done;
165 			} else {
166 				errno = 0;
167 				nread = 0;
168 				/* Try again. */
169 			}
170 		}
171 		nleft -= nread;
172 		if ((nleft <= 0) || ((retry == 0) && (nleft != (int) size)))
173 			break;
174 		buf += nread;
175 		time(&now);
176 	}
177 	nread = size - nleft;
178 
179 done:
180 	return (nread);
181 }	/* SRecv */
182 
183 #endif
184 
185