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