home *** CD-ROM | disk | FTP | other *** search
/ ftp.ncftp.com / ftp.ncftp.com.zip / ftp.ncftp.com / libncftp / libncftp-3.2.5-src.zip / libncftp-3.2.5 / sio / SClose.c < prev    next >
C/C++ Source or Header  |  2004-07-10  |  2KB  |  118 lines

  1. #include "syshdrs.h"
  2. #ifdef PRAGMA_HDRSTOP
  3. #    pragma hdrstop
  4. #endif
  5.  
  6. int
  7. SCloseSocket(int sfd)
  8. {
  9.     int result;
  10.     DECL_SIGPIPE_VARS
  11.     
  12.     IGNORE_SIGPIPE
  13.     result = closesocket(sfd);
  14.     RESTORE_SIGPIPE
  15.     
  16.     return (result);
  17. }    /* SCloseSocket */
  18.  
  19.  
  20.  
  21. #ifndef NO_SIGNALS
  22. extern Sjmp_buf gNetTimeoutJmp;
  23. #endif
  24.  
  25. int
  26. SClose(int sfd, int tlen)
  27. {
  28. #ifdef UNIX_SIGNALS
  29.     volatile sio_sigproc_t sigalrm = (sio_sigproc_t) 0;
  30.     volatile sio_sigproc_t sigpipe = (sio_sigproc_t) 0;
  31.     volatile alarm_time_t oalarm = 0;
  32.     int result;
  33.     int oerrno;
  34.     
  35.     if (sfd < 0) {
  36.         errno = EBADF;
  37.         return (-1);
  38.     }
  39.  
  40.     if (GetSocketLinger(sfd, NULL) <= 0) {
  41.         /* Linger wasn't on, so close shouldn't block.
  42.          * Take the regular way out.
  43.          */
  44.         return (SCloseSocket(sfd));
  45.     }
  46.     
  47.     if (tlen < 1) {
  48.         /* Don't time it, shut it down now. */
  49.         if (SetSocketLinger(sfd, 0, 0) == 0) {
  50.             /* Linger disabled, so close()
  51.              * should not block.
  52.              */
  53.             return (SCloseSocket(sfd));
  54.         } else {
  55.             /* This may result in a fd leak,
  56.              * but it's either that or hang forever.
  57.              */
  58.             (void) shutdown(sfd, 2);
  59.             return (SCloseSocket(sfd));
  60.         }
  61.     }
  62.  
  63.     if (SSetjmp(gNetTimeoutJmp) != 0) {
  64.         (void) alarm(0);
  65.         (void) SetSocketLinger(sfd, 0, 0);
  66.         errno = 0;
  67.         (void) shutdown(sfd, 2);
  68.         result = closesocket(sfd);
  69.         oerrno = errno;
  70.         (void) SSignal(SIGALRM, (sio_sigproc_t) sigalrm);
  71.         (void) SSignal(SIGPIPE, (sio_sigproc_t) sigpipe);
  72.         (void) alarm(oalarm);
  73.         errno = oerrno;
  74.         return (result);
  75.     }
  76.  
  77.     sigalrm = (sio_sigproc_t) SSignal(SIGALRM, SIOHandler);
  78.     sigpipe = (sio_sigproc_t) SSignal(SIGPIPE, SIG_IGN);
  79.  
  80.     oalarm = alarm((alarm_time_t) tlen);
  81.     for (errno = 0;;) {
  82.         result = closesocket(sfd);
  83.         if (result == 0)
  84.             break;
  85.         if (errno != EINTR)
  86.             break;
  87.     }
  88.     oerrno = errno;
  89.     (void) alarm(0);
  90.  
  91.     if ((result != 0) && (errno != EBADF)) {
  92.         (void) SetSocketLinger(sfd, 0, 0);
  93.         (void) shutdown(sfd, 2);
  94.         result = closesocket(sfd);
  95.         oerrno = errno;
  96.     }
  97.     
  98.     (void) SSignal(SIGALRM, (sio_sigproc_t) sigalrm);
  99.     (void) SSignal(SIGPIPE, (sio_sigproc_t) sigpipe);
  100.     (void) alarm(oalarm);
  101.     errno = oerrno;
  102.     
  103.     return (result);
  104. #else    /* ! UNIX_SIGNALS */
  105.     if (sfd < 0) {
  106.         errno = EBADF;
  107.         return (-1);
  108.     }
  109.     
  110.     /* Sorry... it's up to you to make sure you don't block forever
  111.      * on closesocket() since this platform doesn't have alarm().
  112.      * Even so, it shouldn't be a problem unless you use linger mode
  113.      * on the socket, and nobody does that these days.
  114.      */
  115.     return (SCloseSocket(sfd));
  116. #endif
  117. }    /* SClose */
  118.