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 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 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