home *** CD-ROM | disk | FTP | other *** search
/ Big Green CD 8 / BGCD_8_Dev.iso / NEXTSTEP / UNIX / Networking / ncftp-2.4.2-MIHS / src / Sio.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-10-18  |  4.2 KB  |  210 lines

  1. /* Sio.c */
  2.  
  3. #include "Sys.h"
  4.  
  5. #include <errno.h>
  6. #include <signal.h>
  7. #include <setjmp.h>
  8.  
  9. #include "Sio.h"
  10.  
  11. #ifndef EPIPE
  12. #    define EPIPE 0
  13. #endif
  14. #ifndef ETIMEDOUT
  15. #    define ETIMEDOUT 0
  16. #endif
  17.  
  18. jmp_buf gNetTimeoutJmp;
  19. jmp_buf gPipeJmp;
  20.  
  21. static void
  22. SIOHandler(int sigNum)
  23. {
  24.     if (sigNum == SIGPIPE)
  25.         longjmp(gPipeJmp, 1);
  26.     longjmp(gNetTimeoutJmp, 1);
  27. }    /* SIOHandler */
  28.  
  29.  
  30.  
  31.  
  32. /* Read up to "size" bytes on sfd before "tlen" seconds.
  33.  *
  34.  * If "retry" is on, after a successful read of less than "size"
  35.  * bytes, it will attempt to read more, upto "size."
  36.  *
  37.  * If the timer elapses and one or more bytes were read, it returns
  38.  * that number, otherwise a timeout error is returned.
  39.  *
  40.  * Although "retry" would seem to indicate you may want to always
  41.  * read "size" bytes or else it is an error, even with that on you
  42.  * may get back a value < size.  Set "retry" to 0 when you want to
  43.  * return as soon as there is a chunk of data whose size is <= "size".
  44.  */
  45.  
  46. int
  47. Sread(int sfd, char *buf0, size_t size, int tlen, int retry)
  48. {
  49.     int nread;
  50.     volatile int nleft;
  51.     int tleft;
  52.     vsio_sigproc_t sigalrm, sigpipe;
  53.     time_t done, now;
  54.     char *volatile buf;
  55.  
  56.     buf = buf0;
  57.     if (setjmp(gNetTimeoutJmp) != 0) {
  58.         alarm(0);
  59.         (void) signal(SIGALRM, (sio_sigproc_t) sigalrm);
  60.         (void) signal(SIGPIPE, (sio_sigproc_t) sigpipe);
  61.         nread = size - nleft;
  62.         if (nread > 0)
  63.             return (nread);
  64.         errno = ETIMEDOUT;
  65.         return (kTimeoutErr);
  66.     }
  67.  
  68.     if (setjmp(gPipeJmp) != 0) {
  69.         alarm(0);
  70.         (void) signal(SIGALRM, (sio_sigproc_t) sigalrm);
  71.         (void) signal(SIGPIPE, (sio_sigproc_t) sigpipe);
  72.         nread = size - nleft;
  73.         if (nread > 0)
  74.             return (nread);
  75.         errno = EPIPE;
  76.         return (kBrokenPipeErr);
  77.     }
  78.  
  79.     sigalrm = (vsio_sigproc_t) signal(SIGALRM, SIOHandler);
  80.     sigpipe = (vsio_sigproc_t) signal(SIGPIPE, SIOHandler);
  81.     errno = 0;
  82.  
  83.     nleft = (int) size;
  84.     time(&now);
  85.     done = now + tlen;
  86.     while (1) {
  87.         tleft = (int) (done - now);
  88.         if (tleft < 1) {
  89.             nread = size - nleft;
  90.             if (nread == 0) {
  91.                 nread = kTimeoutErr;
  92.                 errno = ETIMEDOUT;
  93.             }
  94.             goto done;
  95.         }
  96.         (void) alarm((unsigned int) tleft);
  97.         nread = read(sfd, buf, nleft);
  98.         (void) alarm(0);
  99.         if (nread <= 0) {
  100.             if (nread == 0) {
  101.                 /* EOF */
  102.                 nread = size - nleft;
  103.                 goto done;
  104.             } else if (errno != EINTR) {
  105.                 nread = size - nleft;
  106.                 if (nread == 0)
  107.                     nread = -1;
  108.                 goto done;
  109.             } else {
  110.                 errno = 0;
  111.                 nread = 0;
  112.                 /* Try again. */
  113.             }
  114.         }
  115.         nleft -= nread;
  116.         if ((nleft <= 0) || (retry == 0))
  117.             break;
  118.         buf += nread;
  119.         time(&now);
  120.     }
  121.     nread = size - nleft;
  122.  
  123. done:
  124.     (void) signal(SIGALRM, (sio_sigproc_t) sigalrm);
  125.     (void) signal(SIGPIPE, (sio_sigproc_t) sigpipe);
  126.  
  127.     return (nread);
  128. }    /* Sread */
  129.  
  130.  
  131.  
  132.  
  133. int
  134. Swrite(int sfd, char *buf0, size_t size, int tlen)
  135. {
  136.     volatile int nleft;
  137.     int nwrote, tleft;
  138.     vsio_sigproc_t sigalrm, sigpipe;
  139.     time_t done, now;
  140.     char *volatile buf;
  141.  
  142.     buf = buf0;
  143.     if (setjmp(gNetTimeoutJmp) != 0) {
  144.         alarm(0);
  145.         (void) signal(SIGALRM, (sio_sigproc_t) sigalrm);
  146.         (void) signal(SIGPIPE, (sio_sigproc_t) sigpipe);
  147.         nwrote = size - nleft;
  148.         if (nwrote > 0)
  149.             return (nwrote);
  150.         errno = ETIMEDOUT;
  151.         return (kTimeoutErr);
  152.     }
  153.  
  154.     if (setjmp(gPipeJmp) != 0) {
  155.         alarm(0);
  156.         (void) signal(SIGALRM, (sio_sigproc_t) sigalrm);
  157.         (void) signal(SIGPIPE, (sio_sigproc_t) sigpipe);
  158.         nwrote = size - nleft;
  159.         if (nwrote > 0)
  160.             return (nwrote);
  161.         errno = EPIPE;
  162.         return (kBrokenPipeErr);
  163.     }
  164.  
  165.     sigalrm = (vsio_sigproc_t) signal(SIGALRM, SIOHandler);
  166.     sigpipe = (vsio_sigproc_t) signal(SIGPIPE, SIOHandler);
  167.  
  168.     nleft = (int) size;
  169.     time(&now);
  170.     done = now + tlen;
  171.     while (1) {
  172.         tleft = (int) (done - now);
  173.         if (tleft < 1) {
  174.             nwrote = size - nleft;
  175.             if (nwrote == 0) {
  176.                 nwrote = kTimeoutErr;
  177.                 errno = ETIMEDOUT;
  178.             }
  179.             goto done;
  180.         }
  181.         (void) alarm((unsigned int) tleft);
  182.         nwrote = write(sfd, buf, nleft);
  183.         (void) alarm(0);
  184.         if (nwrote < 0) {
  185.             if (errno != EINTR) {
  186.                 nwrote = size - nleft;
  187.                 if (nwrote == 0)
  188.                     nwrote = -1;
  189.                 goto done;
  190.             } else {
  191.                 errno = 0;
  192.                 nwrote = 0;
  193.                 /* Try again. */
  194.             }
  195.         }
  196.         nleft -= nwrote;
  197.         if (nleft <= 0)
  198.             break;
  199.         buf += nwrote;
  200.         time(&now);
  201.     }
  202.     nwrote = size - nleft;
  203.  
  204. done:
  205.     (void) signal(SIGALRM, (sio_sigproc_t) sigalrm);
  206.     (void) signal(SIGPIPE, (sio_sigproc_t) sigpipe);
  207.  
  208.     return (nwrote);
  209. }    /* Swrite */
  210.