PageRenderTime 40ms CodeModel.GetById 14ms RepoModel.GetById 0ms app.codeStats 0ms

/ncftp-3.2.5/sio/SClose.c

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