PageRenderTime 41ms CodeModel.GetById 31ms app.highlight 8ms 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
  6int
  7SCloseSocket(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
 22extern Sjmp_buf gNetTimeoutJmp;
 23#endif
 24
 25int
 26SClose(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 */