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 / SClose.c < prev    next >
C/C++ Source or Header  |  2001-11-19  |  5KB  |  241 lines

  1. #include "syshdrs.h"
  2. #ifdef PRAGMA_HDRSTOP
  3. #    pragma hdrstop
  4. #endif
  5.  
  6. #ifndef NO_SIGNALS
  7. extern Sjmp_buf gNetTimeoutJmp;
  8. extern Sjmp_buf gPipeJmp;
  9. #endif
  10.  
  11. int
  12. SClose(int sfd, int tlen)
  13. {
  14. #ifndef NO_SIGNALS
  15.     vsio_sigproc_t sigalrm, sigpipe;
  16.  
  17.     if (sfd < 0) {
  18.         errno = EBADF;
  19.         return (-1);
  20.     }
  21.  
  22.     if (tlen < 1) {
  23.         /* Don't time it, shut it down now. */
  24.         if (SetSocketLinger(sfd, 0, 0) == 0) {
  25.             /* Linger disabled, so close()
  26.              * should not block.
  27.              */
  28.             return (closesocket(sfd));
  29.         } else {
  30.             /* This will result in a fd leak,
  31.              * but it's either that or hang forever.
  32.              */
  33.             (void) shutdown(sfd, 2);
  34.             return (closesocket(sfd));
  35.         }
  36.     }
  37.  
  38.     if (SSetjmp(gNetTimeoutJmp) != 0) {
  39.         alarm(0);
  40.         (void) SSignal(SIGALRM, (sio_sigproc_t) sigalrm);
  41.         (void) SSignal(SIGPIPE, (sio_sigproc_t) sigpipe);
  42.         if (SetSocketLinger(sfd, 0, 0) == 0) {
  43.             /* Linger disabled, so close()
  44.              * should not block.
  45.              */
  46.             return closesocket(sfd);
  47.         } else {
  48.             /* This will result in a fd leak,
  49.              * but it's either that or hang forever.
  50.              */
  51.             (void) shutdown(sfd, 2);
  52.             return (closesocket(sfd));
  53.         }
  54.     }
  55.  
  56.     sigalrm = (vsio_sigproc_t) SSignal(SIGALRM, SIOHandler);
  57.     sigpipe = (vsio_sigproc_t) SSignal(SIGPIPE, SIG_IGN);
  58.  
  59.     alarm((alarm_time_t) tlen);
  60.     for (;;) {
  61.         if (closesocket(sfd) == 0) {
  62.             errno = 0;
  63.             break;
  64.         }
  65.         if (errno != EINTR)
  66.             break;
  67.     } 
  68.     alarm(0);
  69.     (void) SSignal(SIGALRM, (sio_sigproc_t) sigalrm);
  70.  
  71.     if ((errno != 0) && (errno != EBADF)) {
  72.         if (SetSocketLinger(sfd, 0, 0) == 0) {
  73.             /* Linger disabled, so close()
  74.              * should not block.
  75.              */
  76.             (void) closesocket(sfd);
  77.         } else {
  78.             /* This will result in a fd leak,
  79.              * but it's either that or hang forever.
  80.              */
  81.             (void) shutdown(sfd, 2);
  82.             (void) closesocket(sfd);
  83.         }
  84.     }
  85.     (void) SSignal(SIGPIPE, (sio_sigproc_t) sigpipe);
  86.  
  87.     return ((errno == 0) ? 0 : (-1));
  88. #else
  89.     struct timeval tv;
  90.     int result;
  91.     time_t done, now;
  92.     fd_set ss, ss2;
  93.  
  94.     if (sfd < 0) {
  95.         errno = EBADF;
  96.         return (-1);
  97.     }
  98.  
  99.     if (tlen < 1) {
  100.         /* Don't time it, shut it down now. */
  101.         if (SetSocketLinger(sfd, 0, 0) == 0) {
  102.             /* Linger disabled, so close()
  103.              * should not block.
  104.              */
  105.             return (closesocket(sfd));
  106.         } else {
  107.             /* This will result in a fd leak,
  108.              * but it's either that or hang forever.
  109.              */
  110.             (void) shutdown(sfd, 2);
  111.             return (closesocket(sfd));
  112.         }
  113.     }
  114.  
  115.     /* Wait until the socket is ready for writing (usually easy). */
  116.     time(&now);
  117.     done = now + tlen;
  118.  
  119.     forever {
  120.         tlen = done - now;
  121.         if (tlen <= 0) {
  122.             /* timeout */
  123.             if (SetSocketLinger(sfd, 0, 0) == 0) {
  124.                 /* Linger disabled, so close()
  125.                  * should not block.
  126.                  */
  127.                 (void) closesocket(sfd);
  128.             } else {
  129.                 /* This will result in a fd leak,
  130.                  * but it's either that or hang forever.
  131.                  */
  132.                 (void) shutdown(sfd, 2);
  133.                 (void) closesocket(sfd);
  134.             }
  135.             errno = ETIMEDOUT;
  136.             return (kTimeoutErr);
  137.         }
  138.  
  139.         errno = 0;
  140.         MY_FD_ZERO(&ss);
  141. #if defined(__DECC) || defined(__DECCXX)
  142. #pragma message save
  143. #pragma message disable trunclongint
  144. #endif
  145.         MY_FD_SET(sfd, &ss);
  146. #if defined(__DECC) || defined(__DECCXX)
  147. #pragma message restore
  148. #endif
  149.         memcpy(&ss2, &ss, sizeof(ss2));
  150.         tv.tv_sec = (tv_sec_t) tlen;
  151.         tv.tv_usec = 0;
  152.         result = select(sfd + 1, NULL, SELECT_TYPE_ARG234 &ss, SELECT_TYPE_ARG234 &ss2, SELECT_TYPE_ARG5 &tv);
  153.         if (result == 1) {
  154.             /* ready */
  155.             break;
  156.         } else if (result == 0) {
  157.             /* timeout */
  158.             if (SetSocketLinger(sfd, 0, 0) == 0) {
  159.                 /* Linger disabled, so close()
  160.                  * should not block.
  161.                  */
  162.                 (void) closesocket(sfd);
  163.             } else {
  164.                 /* This will result in a fd leak,
  165.                  * but it's either that or hang forever.
  166.                  */
  167.                 (void) shutdown(sfd, 2);
  168.                 (void) closesocket(sfd);
  169.             }
  170.             errno = ETIMEDOUT;
  171.             return (kTimeoutErr);
  172.         } else if (errno != EINTR) {
  173.             /* Error, done. This end may have been shutdown. */
  174.             break;
  175.         }
  176.         time(&now);
  177.     }
  178.  
  179.     /* Wait until the socket is ready for reading. */
  180.     forever {
  181.         tlen = done - now;
  182.         if (tlen <= 0) {
  183.             /* timeout */
  184.             if (SetSocketLinger(sfd, 0, 0) == 0) {
  185.                 /* Linger disabled, so close()
  186.                  * should not block.
  187.                  */
  188.                 (void) closesocket(sfd);
  189.             } else {
  190.                 /* This will result in a fd leak,
  191.                  * but it's either that or hang forever.
  192.                  */
  193.                 (void) shutdown(sfd, 2);
  194.                 (void) closesocket(sfd);
  195.             }
  196.             errno = ETIMEDOUT;
  197.             return (kTimeoutErr);
  198.         }
  199.  
  200.         errno = 0;
  201.         MY_FD_ZERO(&ss);
  202. #if defined(__DECC) || defined(__DECCXX)
  203. #pragma message save
  204. #pragma message disable trunclongint
  205. #endif
  206.         MY_FD_SET(sfd, &ss);
  207. #if defined(__DECC) || defined(__DECCXX)
  208. #pragma message restore
  209. #endif
  210.         tv.tv_sec = (tv_sec_t) tlen;
  211.         tv.tv_usec = 0;
  212.         memcpy(&ss2, &ss, sizeof(ss2));
  213.         result = select(sfd + 1, SELECT_TYPE_ARG234 &ss, NULL, SELECT_TYPE_ARG234 &ss2, SELECT_TYPE_ARG5 &tv);
  214.         if (result == 1) {
  215.             /* ready */
  216.             break;
  217.         } else if (result == 0) {
  218.             /* timeout */
  219.             if (SetSocketLinger(sfd, 0, 0) == 0) {
  220.                 /* Linger disabled, so close()
  221.                  * should not block.
  222.                  */
  223.                 (void) closesocket(sfd);
  224.             } else {
  225.                 (void) shutdown(sfd, 2);
  226.                 (void) closesocket(sfd);
  227.             }
  228.             errno = ETIMEDOUT;
  229.             return (kTimeoutErr);
  230.         } else if (errno != EINTR) {
  231.             /* Error, done. This end may have been shutdown. */
  232.             break;
  233.         }
  234.         time(&now);
  235.     }
  236.  
  237.     /* If we get here, close() won't block. */
  238.     return closesocket(sfd);
  239. #endif
  240. }    /* SClose */
  241.