home *** CD-ROM | disk | FTP | other *** search
/ ftp.ncftp.com / ftp.ncftp.com.zip / ftp.ncftp.com / libncftp / older_versions / libncftp-3.1.5-src.tar.gz / libncftp-3.1.5-src.tar / libncftp-3.1.5 / sio / SRead.c < prev    next >
C/C++ Source or Header  |  2002-06-28  |  6KB  |  224 lines

  1. #include "syshdrs.h"
  2. #ifdef PRAGMA_HDRSTOP
  3. #    pragma hdrstop
  4. #endif
  5.  
  6. static const char UNUSED(gSioVersion[]) = "@(#) sio 6.1.4 ** Copyright 1992-2002 Mike Gleason. All rights reserved.";
  7.  
  8. #ifdef NO_SIGNALS
  9. static const char UNUSED(gNoSignalsMarker[]) = "@(#) sio - NO_SIGNALS";
  10. #else
  11. extern Sjmp_buf gNetTimeoutJmp;
  12. extern Sjmp_buf gPipeJmp;
  13. #endif
  14.  
  15. /* Read up to "size" bytes on sfd before "tlen" seconds.
  16.  *
  17.  * If "retry" is on, after a successful read of less than "size"
  18.  * bytes, it will attempt to read more, upto "size."
  19.  *
  20.  * If the timer elapses and one or more bytes were read, it returns
  21.  * that number, otherwise a timeout error is returned.
  22.  *
  23.  * Although "retry" would seem to indicate you may want to always
  24.  * read "size" bytes or else it is an error, even with that on you
  25.  * may get back a value < size.  Set "retry" to 0 when you want to
  26.  * return as soon as there is a chunk of data whose size is <= "size".
  27.  */
  28.  
  29. #ifndef NO_SIGNALS
  30.  
  31. int
  32. SRead(int sfd, char *const buf0, size_t size, int tlen, int retry)
  33. {
  34.     read_return_t nread;
  35.     volatile read_size_t nleft;
  36.     char *volatile buf = buf0;
  37.     alarm_time_t tleft;
  38.     vsio_sigproc_t sigalrm, sigpipe;
  39.     time_t done, now;
  40.  
  41.     if (SSetjmp(gNetTimeoutJmp) != 0) {
  42.         alarm(0);
  43.         (void) SSignal(SIGALRM, (sio_sigproc_t) sigalrm);
  44.         (void) SSignal(SIGPIPE, (sio_sigproc_t) sigpipe);
  45.         nread = (read_return_t) size - (read_return_t) nleft;
  46.         if ((nread > 0) && ((retry & (kFullBufferRequired|kFullBufferRequiredExceptLast)) == 0))
  47.             return ((int) nread);
  48.         errno = ETIMEDOUT;
  49.         return (kTimeoutErr);
  50.     }
  51.  
  52.     if (SSetjmp(gPipeJmp) != 0) {
  53.         alarm(0);
  54.         (void) SSignal(SIGALRM, (sio_sigproc_t) sigalrm);
  55.         (void) SSignal(SIGPIPE, (sio_sigproc_t) sigpipe);
  56.         nread = (read_return_t) size - (read_return_t) nleft;
  57.         if ((nread > 0) && ((retry & (kFullBufferRequired|kFullBufferRequiredExceptLast)) == 0))
  58.             return ((int) nread);
  59.         errno = EPIPE;
  60.         return (kBrokenPipeErr);
  61.     }
  62.  
  63.     sigalrm = (vsio_sigproc_t) SSignal(SIGALRM, SIOHandler);
  64.     sigpipe = (vsio_sigproc_t) SSignal(SIGPIPE, SIOHandler);
  65.     errno = 0;
  66.  
  67.     nleft = (read_size_t) size;
  68.     time(&now);
  69.     done = now + tlen;
  70.     forever {
  71.         tleft = (done < now) ? ((alarm_time_t) (done - now)) : 0;
  72.         if (tleft < 1) {
  73.             nread = (read_return_t) size - (read_return_t) nleft;
  74.             if ((nread == 0) || ((retry & (kFullBufferRequired)) != 0)) {
  75.                 nread = kTimeoutErr;
  76.                 errno = ETIMEDOUT;
  77.             }
  78.             goto done;
  79.         }
  80.         (void) alarm(tleft);
  81.         nread = read(sfd, (char *) buf, nleft);
  82.         (void) alarm(0);
  83.         if (nread <= 0) {
  84.             if (nread == 0) {
  85.                 /* EOF */
  86.                 if (retry == ((retry & (kFullBufferRequiredExceptLast)) != 0))
  87.                     nread = (read_return_t) size - (read_return_t) nleft;
  88.                 goto done;
  89.             } else if (errno != EINTR) {
  90.                 nread = (read_return_t) size - (read_return_t) nleft;
  91.                 if (nread == 0)
  92.                     nread = (read_return_t) -1;
  93.                 goto done;
  94.             } else {
  95.                 errno = 0;
  96.                 nread = 0;
  97.                 /* Try again. */
  98.  
  99.                 /* Ignore this line... */
  100.                 LIBSIO_USE_VAR(gSioVersion);
  101.             }
  102.         }
  103.         nleft -= (read_size_t) nread;
  104.         if ((nleft == 0) || (((retry & (kFullBufferRequired|kFullBufferRequiredExceptLast)) == 0) && (nleft != (read_size_t) size)))
  105.             break;
  106.         buf += nread;
  107.         time(&now);
  108.     }
  109.     nread = (read_return_t) size - (read_return_t) nleft;
  110.  
  111. done:
  112.     (void) SSignal(SIGALRM, (sio_sigproc_t) sigalrm);
  113.     (void) SSignal(SIGPIPE, (sio_sigproc_t) sigpipe);
  114.  
  115.     return ((int) nread);
  116. }    /* SRead */
  117.  
  118. #else
  119.  
  120. int
  121. SRead(int sfd, char *const buf0, size_t size, int tlen, int retry)
  122. {
  123.     read_return_t nread;
  124.     read_size_t nleft;
  125.     char *buf = buf0;
  126.     int tleft;
  127.     time_t done, now;
  128.     fd_set ss;
  129.     struct timeval tv;
  130.     int result, firstRead;
  131.  
  132.     errno = 0;
  133.  
  134.     nleft = (read_size_t) size;
  135.     time(&now);
  136.     done = now + tlen;
  137.     firstRead = 1;
  138.  
  139.     forever {
  140.         tleft = (int) (done - now);
  141.         if (tleft < 1) {
  142.             nread = (read_return_t) size - (read_return_t) nleft;
  143.             if ((nread == 0) || ((retry & (kFullBufferRequired|kFullBufferRequiredExceptLast)) != 0)) {
  144.                 nread = kTimeoutErr;
  145.                 errno = ETIMEDOUT;
  146.                 SETWSATIMEOUTERR
  147.             }
  148.             goto done;
  149.         }
  150.         
  151.         if (!firstRead || ((retry & kNoFirstSelect) == 0)) {
  152.             forever {
  153.                 errno = 0;
  154.                 MY_FD_ZERO(&ss);
  155. #if defined(__DECC) || defined(__DECCXX)
  156. #pragma message save
  157. #pragma message disable trunclongint
  158. #endif
  159.                 MY_FD_SET(sfd, &ss);
  160. #if defined(__DECC) || defined(__DECCXX)
  161. #pragma message restore
  162. #endif
  163.                 tv.tv_sec = (tv_sec_t) tlen;
  164.                 tv.tv_usec = 0;
  165.                 result = select(sfd + 1, SELECT_TYPE_ARG234 &ss, NULL, NULL, SELECT_TYPE_ARG5 &tv);
  166.                 if (result == 1) {
  167.                     /* ready */
  168.                     break;
  169.                 } else if (result == 0) {
  170.                     /* timeout */        
  171.                     nread = (read_return_t) size - (read_return_t) nleft;
  172.                     if ((nread > 0) && ((retry & (kFullBufferRequired|kFullBufferRequiredExceptLast)) == 0))
  173.                         return ((int) nread);
  174.                     errno = ETIMEDOUT;
  175.                     SETWSATIMEOUTERR
  176.                         return (kTimeoutErr);
  177.                 } else if (errno != EINTR) {
  178.                     return (-1);
  179.                 }
  180.             }
  181.             firstRead = 0;
  182.         }
  183.  
  184. #if (defined(WIN32) || defined(_WINDOWS)) && !defined(__CYGWIN__)
  185.         nread = recv(sfd, (char *) buf, (recv_size_t) nleft, 0);
  186. #else
  187.         nread = read(sfd, (char *) buf, nleft);
  188. #endif
  189.  
  190.         if (nread <= 0) {
  191.             if (nread == 0) {
  192.                 /* EOF */
  193.                 if (retry == ((retry & (kFullBufferRequiredExceptLast)) != 0))
  194.                     nread = (read_return_t) size - (read_return_t) nleft;
  195.                 goto done;
  196.             } else if (errno != EINTR) {
  197.                 nread = (read_return_t) size - (read_return_t) nleft;
  198.                 if (nread == 0)
  199.                     nread = (read_return_t) -1;
  200.                 goto done;
  201.             } else {
  202.                 errno = 0;
  203.                 nread = 0;
  204.                 /* Try again. */
  205.  
  206.                 /* Ignore these two lines */
  207.                 LIBSIO_USE_VAR(gSioVersion);
  208.                 LIBSIO_USE_VAR(gNoSignalsMarker);
  209.             }
  210.         }
  211.         nleft -= (read_size_t) nread;
  212.         if ((nleft == 0) || (((retry & (kFullBufferRequired|kFullBufferRequiredExceptLast)) == 0) && (nleft != (read_size_t) size)))
  213.             break;
  214.         buf += nread;
  215.         time(&now);
  216.     }
  217.     nread = (read_return_t) size - (read_return_t) nleft;
  218.  
  219. done:
  220.     return ((int) nread);
  221. }    /* SRead */
  222.  
  223. #endif
  224.