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