Git conversion: Make reactos the root directory, move rosapps, rostests, wallpapers...
[reactos.git] / modules / rosapps / applications / net / ncftp / sio / SRecv.c
diff --git a/modules/rosapps/applications/net/ncftp/sio/SRecv.c b/modules/rosapps/applications/net/ncftp/sio/SRecv.c
new file mode 100644 (file)
index 0000000..4f7c233
--- /dev/null
@@ -0,0 +1,184 @@
+#include "syshdrs.h"
+
+#ifndef NO_SIGNALS
+extern volatile Sjmp_buf gNetTimeoutJmp;
+extern volatile Sjmp_buf gPipeJmp;
+#endif
+
+#ifndef NO_SIGNALS
+
+int
+SRecv(int sfd, char *const buf0, size_t size, int fl, int tlen, int retry)
+{
+       int nread;
+       volatile int nleft;
+       char *volatile buf = buf0;
+       int tleft;
+       vsio_sigproc_t sigalrm, sigpipe;
+       time_t done, now;
+
+       if (SSetjmp(gNetTimeoutJmp) != 0) {
+               alarm(0);
+               (void) SSignal(SIGALRM, (sio_sigproc_t) sigalrm);
+               (void) SSignal(SIGPIPE, (sio_sigproc_t) sigpipe);
+               nread = size - nleft;
+               if ((nread > 0) && (retry == kFullBufferNotRequired))
+                       return (nread);
+               errno = ETIMEDOUT;
+               return (kTimeoutErr);
+       }
+
+       if (SSetjmp(gPipeJmp) != 0) {
+               alarm(0);
+               (void) SSignal(SIGALRM, (sio_sigproc_t) sigalrm);
+               (void) SSignal(SIGPIPE, (sio_sigproc_t) sigpipe);
+               nread = size - nleft;
+               if ((nread > 0) && (retry == kFullBufferNotRequired))
+                       return (nread);
+               errno = EPIPE;
+               return (kBrokenPipeErr);
+       }
+
+       sigalrm = (vsio_sigproc_t) SSignal(SIGALRM, SIOHandler);
+       sigpipe = (vsio_sigproc_t) SSignal(SIGPIPE, SIOHandler);
+       errno = 0;
+
+       nleft = (int) size;
+       time(&now);
+       done = now + tlen;
+       forever {
+               tleft = (int) (done - now);
+               if (tleft < 1) {
+                       nread = size - nleft;
+                       if ((nread == 0) || (retry == kFullBufferRequired)) {
+                               nread = kTimeoutErr;
+                               errno = ETIMEDOUT;
+                       }
+                       goto done;
+               }
+               (void) alarm((unsigned int) tleft);
+               nread = recv(sfd, (char *) buf, nleft, fl);
+               (void) alarm(0);
+               if (nread <= 0) {
+                       if (nread == 0) {
+                               /* EOF */
+                               if (retry == kFullBufferRequiredExceptLast)
+                                       nread = size - nleft;
+                               goto done;
+                       } else if (errno != EINTR) {
+                               nread = size - nleft;
+                               if (nread == 0)
+                                       nread = -1;
+                               goto done;
+                       } else {
+                               errno = 0;
+                               nread = 0;
+                               /* Try again. */
+                       }
+               }
+               nleft -= nread;
+               if ((nleft <= 0) || ((retry == 0) && (nleft != (int) size)))
+                       break;
+               buf += nread;
+               time(&now);
+       }
+       nread = size - nleft;
+
+done:
+       (void) SSignal(SIGALRM, (sio_sigproc_t) sigalrm);
+       (void) SSignal(SIGPIPE, (sio_sigproc_t) sigpipe);
+
+       return (nread);
+}      /* SRecv */
+
+#else
+
+int
+SRecv(int sfd, char *const buf0, size_t size, int fl, int tlen, int retry)
+{
+       int nread;
+       int nleft;
+       char *buf = buf0;
+       int tleft;
+       time_t done, now;
+       fd_set ss;
+       struct timeval tv;
+       int result;
+
+       errno = 0;
+
+       nleft = (int) size;
+       time(&now);
+       done = now + tlen;
+       forever {
+               tleft = (int) (done - now);
+               if (tleft < 1) {
+                       nread = size - nleft;
+                       if ((nread == 0) || (retry == kFullBufferRequired)) {
+                               nread = kTimeoutErr;
+                               errno = ETIMEDOUT;
+                               SETWSATIMEOUTERR
+                       }
+                       goto done;
+               }
+
+               forever {
+                       errno = 0;
+                       FD_ZERO(&ss);
+                       FD_SET(sfd, &ss);
+                       tv.tv_sec = tlen;
+                       tv.tv_usec = 0;
+                       result = select(sfd + 1, SELECT_TYPE_ARG234 &ss, NULL, NULL, SELECT_TYPE_ARG5 &tv);
+                       if (result == 1) {
+                               /* ready */
+                               break;
+                       } else if (result == 0) {
+                               /* timeout */
+                               nread = size - nleft;
+                               if ((nread > 0) && (retry == kFullBufferNotRequired))
+                                       return (nread);
+                               errno = ETIMEDOUT;
+                               SETWSATIMEOUTERR
+                               return (kTimeoutErr);
+                       } else if (errno != EINTR) {
+                               return (-1);
+                       }
+               }
+
+#if defined(WIN32) || defined(_WINDOWS)
+               nread = recv(sfd, (char *) buf, nleft, fl);
+#else
+               nread = recv(sfd, (char *) buf, nleft, fl);
+#endif
+
+               if (nread <= 0) {
+                       if (nread == 0) {
+                               /* EOF */
+                               if (retry == kFullBufferRequiredExceptLast)
+                                       nread = size - nleft;
+                               goto done;
+                       } else if (errno != EINTR) {
+                               nread = size - nleft;
+                               if (nread == 0)
+                                       nread = -1;
+                               goto done;
+                       } else {
+                               errno = 0;
+                               nread = 0;
+                               /* Try again. */
+                       }
+               }
+               nleft -= nread;
+               if ((nleft <= 0) || ((retry == 0) && (nleft != (int) size)))
+                       break;
+               buf += nread;
+               time(&now);
+       }
+       nread = size - nleft;
+
+done:
+       return (nread);
+}      /* SRecv */
+
+#endif
+