Commit | Line | Data |
---|---|---|
326b05e3 | 1 | /* win32sck.c |
68dc0745 | 2 | * |
3 | * (c) 1995 Microsoft Corporation. All rights reserved. | |
0d130a44 | 4 | * Developed by hip communications inc. |
68dc0745 | 5 | * Portions (c) 1993 Intergraph Corporation. All rights reserved. |
6 | * | |
7 | * You may distribute under the terms of either the GNU General Public | |
8 | * License or the Artistic License, as specified in the README file. | |
9 | */ | |
0a753a76 | 10 | |
390b85e7 | 11 | #define WIN32IO_IS_STDIO |
55d25626 | 12 | #define WIN32SCK_IS_STDSCK |
0a753a76 | 13 | #define WIN32_LEAN_AND_MEAN |
8fada4f6 | 14 | #define PERLIO_NOT_STDIO 0 |
a835ef8a NIS |
15 | #ifdef __GNUC__ |
16 | #define Win32_Winsock | |
17 | #endif | |
390b85e7 | 18 | #include <windows.h> |
036c1c1e SH |
19 | #include <ws2spi.h> |
20 | ||
0a753a76 | 21 | #include "EXTERN.h" |
22 | #include "perl.h" | |
c69f6586 | 23 | |
58a50f62 | 24 | #include "Win32iop.h" |
0a753a76 | 25 | #include <sys/socket.h> |
26 | #include <fcntl.h> | |
27 | #include <sys/stat.h> | |
28 | #include <assert.h> | |
390b85e7 | 29 | #include <io.h> |
0a753a76 | 30 | |
68dc0745 | 31 | /* thanks to Beverly Brown (beverly@datacube.com) */ |
72e6b643 SH |
32 | #define OPEN_SOCKET(x) win32_open_osfhandle(x,O_RDWR|O_BINARY) |
33 | #define TO_SOCKET(x) _get_osfhandle(x) | |
0a753a76 | 34 | |
326b05e3 GS |
35 | #define StartSockets() \ |
36 | STMT_START { \ | |
37 | if (!wsock_started) \ | |
38 | start_sockets(); \ | |
39 | } STMT_END | |
40 | ||
326b05e3 GS |
41 | #define SOCKET_TEST(x, y) \ |
42 | STMT_START { \ | |
43 | StartSockets(); \ | |
44 | if((x) == (y)) \ | |
45 | errno = WSAGetLastError(); \ | |
46 | } STMT_END | |
47 | ||
48 | #define SOCKET_TEST_ERROR(x) SOCKET_TEST(x, SOCKET_ERROR) | |
49 | ||
137443ea | 50 | static struct servent* win32_savecopyservent(struct servent*d, |
51 | struct servent*s, | |
52 | const char *proto); | |
0a753a76 | 53 | |
326b05e3 | 54 | static int wsock_started = 0; |
68dc0745 | 55 | |
b73db59c GS |
56 | EXTERN_C void |
57 | EndSockets(void) | |
58 | { | |
59 | if (wsock_started) | |
60 | WSACleanup(); | |
61 | } | |
62 | ||
68dc0745 | 63 | void |
326b05e3 | 64 | start_sockets(void) |
68dc0745 | 65 | { |
acfe0abc | 66 | dTHX; |
68dc0745 | 67 | unsigned short version; |
68 | WSADATA retdata; | |
69 | int ret; | |
68dc0745 | 70 | |
68dc0745 | 71 | /* |
72 | * initalize the winsock interface and insure that it is | |
73 | * cleaned up at exit. | |
74 | */ | |
036c1c1e | 75 | version = 0x2; |
326b05e3 | 76 | if(ret = WSAStartup(version, &retdata)) |
4f63d024 | 77 | Perl_croak_nocontext("Unable to locate winsock library!\n"); |
68dc0745 | 78 | if(retdata.wVersion != version) |
036c1c1e | 79 | Perl_croak_nocontext("Could not find version 2.0 of winsock dll\n"); |
68dc0745 | 80 | |
81 | /* atexit((void (*)(void)) EndSockets); */ | |
401ef382 SN |
82 | wsock_started = 1; |
83 | } | |
0a753a76 | 84 | |
68dc0745 | 85 | u_long |
86 | win32_htonl(u_long hostlong) | |
0a753a76 | 87 | { |
326b05e3 GS |
88 | StartSockets(); |
89 | return htonl(hostlong); | |
0a753a76 | 90 | } |
91 | ||
68dc0745 | 92 | u_short |
93 | win32_htons(u_short hostshort) | |
0a753a76 | 94 | { |
326b05e3 GS |
95 | StartSockets(); |
96 | return htons(hostshort); | |
0a753a76 | 97 | } |
98 | ||
68dc0745 | 99 | u_long |
100 | win32_ntohl(u_long netlong) | |
0a753a76 | 101 | { |
326b05e3 GS |
102 | StartSockets(); |
103 | return ntohl(netlong); | |
0a753a76 | 104 | } |
105 | ||
68dc0745 | 106 | u_short |
107 | win32_ntohs(u_short netshort) | |
0a753a76 | 108 | { |
326b05e3 GS |
109 | StartSockets(); |
110 | return ntohs(netshort); | |
0a753a76 | 111 | } |
112 | ||
113 | ||
0a753a76 | 114 | |
68dc0745 | 115 | SOCKET |
116 | win32_accept(SOCKET s, struct sockaddr *addr, int *addrlen) | |
0a753a76 | 117 | { |
68dc0745 | 118 | SOCKET r; |
0a753a76 | 119 | |
326b05e3 | 120 | SOCKET_TEST((r = accept(TO_SOCKET(s), addr, addrlen)), INVALID_SOCKET); |
68dc0745 | 121 | return OPEN_SOCKET(r); |
0a753a76 | 122 | } |
123 | ||
68dc0745 | 124 | int |
125 | win32_bind(SOCKET s, const struct sockaddr *addr, int addrlen) | |
0a753a76 | 126 | { |
68dc0745 | 127 | int r; |
0a753a76 | 128 | |
326b05e3 | 129 | SOCKET_TEST_ERROR(r = bind(TO_SOCKET(s), addr, addrlen)); |
68dc0745 | 130 | return r; |
0a753a76 | 131 | } |
132 | ||
68dc0745 | 133 | int |
134 | win32_connect(SOCKET s, const struct sockaddr *addr, int addrlen) | |
0a753a76 | 135 | { |
68dc0745 | 136 | int r; |
0a753a76 | 137 | |
326b05e3 | 138 | SOCKET_TEST_ERROR(r = connect(TO_SOCKET(s), addr, addrlen)); |
68dc0745 | 139 | return r; |
0a753a76 | 140 | } |
141 | ||
142 | ||
68dc0745 | 143 | int |
144 | win32_getpeername(SOCKET s, struct sockaddr *addr, int *addrlen) | |
0a753a76 | 145 | { |
68dc0745 | 146 | int r; |
0a753a76 | 147 | |
326b05e3 | 148 | SOCKET_TEST_ERROR(r = getpeername(TO_SOCKET(s), addr, addrlen)); |
68dc0745 | 149 | return r; |
0a753a76 | 150 | } |
151 | ||
68dc0745 | 152 | int |
153 | win32_getsockname(SOCKET s, struct sockaddr *addr, int *addrlen) | |
0a753a76 | 154 | { |
68dc0745 | 155 | int r; |
0a753a76 | 156 | |
326b05e3 | 157 | SOCKET_TEST_ERROR(r = getsockname(TO_SOCKET(s), addr, addrlen)); |
68dc0745 | 158 | return r; |
0a753a76 | 159 | } |
160 | ||
68dc0745 | 161 | int |
162 | win32_getsockopt(SOCKET s, int level, int optname, char *optval, int *optlen) | |
0a753a76 | 163 | { |
68dc0745 | 164 | int r; |
0a753a76 | 165 | |
326b05e3 | 166 | SOCKET_TEST_ERROR(r = getsockopt(TO_SOCKET(s), level, optname, optval, optlen)); |
68dc0745 | 167 | return r; |
0a753a76 | 168 | } |
169 | ||
2d7a9237 | 170 | int |
68dc0745 | 171 | win32_ioctlsocket(SOCKET s, long cmd, u_long *argp) |
0a753a76 | 172 | { |
68dc0745 | 173 | int r; |
0a753a76 | 174 | |
326b05e3 | 175 | SOCKET_TEST_ERROR(r = ioctlsocket(TO_SOCKET(s), cmd, argp)); |
68dc0745 | 176 | return r; |
0a753a76 | 177 | } |
178 | ||
68dc0745 | 179 | int |
180 | win32_listen(SOCKET s, int backlog) | |
0a753a76 | 181 | { |
68dc0745 | 182 | int r; |
0a753a76 | 183 | |
326b05e3 | 184 | SOCKET_TEST_ERROR(r = listen(TO_SOCKET(s), backlog)); |
68dc0745 | 185 | return r; |
0a753a76 | 186 | } |
187 | ||
68dc0745 | 188 | int |
189 | win32_recv(SOCKET s, char *buf, int len, int flags) | |
0a753a76 | 190 | { |
68dc0745 | 191 | int r; |
0a753a76 | 192 | |
326b05e3 | 193 | SOCKET_TEST_ERROR(r = recv(TO_SOCKET(s), buf, len, flags)); |
68dc0745 | 194 | return r; |
0a753a76 | 195 | } |
196 | ||
68dc0745 | 197 | int |
198 | win32_recvfrom(SOCKET s, char *buf, int len, int flags, struct sockaddr *from, int *fromlen) | |
0a753a76 | 199 | { |
68dc0745 | 200 | int r; |
e4449fe1 | 201 | int frombufsize = *fromlen; |
0a753a76 | 202 | |
326b05e3 | 203 | SOCKET_TEST_ERROR(r = recvfrom(TO_SOCKET(s), buf, len, flags, from, fromlen)); |
e4449fe1 GS |
204 | /* Winsock's recvfrom() only returns a valid 'from' when the socket |
205 | * is connectionless. Perl expects a valid 'from' for all types | |
206 | * of sockets, so go the extra mile. | |
207 | */ | |
208 | if (r != SOCKET_ERROR && frombufsize == *fromlen) | |
209 | (void)win32_getpeername(s, from, fromlen); | |
68dc0745 | 210 | return r; |
0a753a76 | 211 | } |
212 | ||
68dc0745 | 213 | /* select contributed by Vincent R. Slyngstad (vrs@ibeam.intel.com) */ |
214 | int | |
55d25626 | 215 | win32_select(int nfds, Perl_fd_set* rd, Perl_fd_set* wr, Perl_fd_set* ex, const struct timeval* timeout) |
0a753a76 | 216 | { |
55d25626 | 217 | int r; |
3ead22cb | 218 | int i, fd, save_errno = errno; |
8dc00b2f | 219 | FD_SET nrd, nwr, nex; |
e4d771f5 | 220 | bool just_sleep = TRUE; |
0a753a76 | 221 | |
f2bb5751 | 222 | StartSockets(); |
0a753a76 | 223 | |
68dc0745 | 224 | FD_ZERO(&nrd); |
225 | FD_ZERO(&nwr); | |
226 | FD_ZERO(&nex); | |
227 | for (i = 0; i < nfds; i++) { | |
f7bbabd3 JD |
228 | if (rd && PERL_FD_ISSET(i,rd)) { |
229 | fd = TO_SOCKET(i); | |
47660177 | 230 | FD_SET((unsigned)fd, &nrd); |
e4d771f5 | 231 | just_sleep = FALSE; |
f7bbabd3 JD |
232 | } |
233 | if (wr && PERL_FD_ISSET(i,wr)) { | |
234 | fd = TO_SOCKET(i); | |
47660177 | 235 | FD_SET((unsigned)fd, &nwr); |
e4d771f5 | 236 | just_sleep = FALSE; |
f7bbabd3 JD |
237 | } |
238 | if (ex && PERL_FD_ISSET(i,ex)) { | |
239 | fd = TO_SOCKET(i); | |
47660177 | 240 | FD_SET((unsigned)fd, &nex); |
e4d771f5 | 241 | just_sleep = FALSE; |
f7bbabd3 | 242 | } |
68dc0745 | 243 | } |
244 | ||
e4d771f5 JD |
245 | /* winsock seems incapable of dealing with all three fd_sets being empty, |
246 | * so do the (millisecond) sleep as a special case | |
247 | */ | |
248 | if (just_sleep) { | |
249 | if (timeout) | |
250 | Sleep(timeout->tv_sec * 1000 + | |
251 | timeout->tv_usec / 1000); /* do the best we can */ | |
252 | else | |
253 | Sleep(UINT_MAX); | |
254 | return 0; | |
255 | } | |
256 | ||
1c878075 | 257 | errno = save_errno; |
8dc00b2f | 258 | SOCKET_TEST_ERROR(r = select(nfds, &nrd, &nwr, &nex, timeout)); |
1c878075 | 259 | save_errno = errno; |
0a753a76 | 260 | |
68dc0745 | 261 | for (i = 0; i < nfds; i++) { |
f7bbabd3 JD |
262 | if (rd && PERL_FD_ISSET(i,rd)) { |
263 | fd = TO_SOCKET(i); | |
264 | if (!FD_ISSET(fd, &nrd)) | |
265 | PERL_FD_CLR(i,rd); | |
266 | } | |
267 | if (wr && PERL_FD_ISSET(i,wr)) { | |
268 | fd = TO_SOCKET(i); | |
269 | if (!FD_ISSET(fd, &nwr)) | |
270 | PERL_FD_CLR(i,wr); | |
271 | } | |
272 | if (ex && PERL_FD_ISSET(i,ex)) { | |
273 | fd = TO_SOCKET(i); | |
274 | if (!FD_ISSET(fd, &nex)) | |
275 | PERL_FD_CLR(i,ex); | |
276 | } | |
68dc0745 | 277 | } |
1c878075 | 278 | errno = save_errno; |
68dc0745 | 279 | return r; |
0a753a76 | 280 | } |
281 | ||
68dc0745 | 282 | int |
283 | win32_send(SOCKET s, const char *buf, int len, int flags) | |
0a753a76 | 284 | { |
68dc0745 | 285 | int r; |
0a753a76 | 286 | |
326b05e3 | 287 | SOCKET_TEST_ERROR(r = send(TO_SOCKET(s), buf, len, flags)); |
68dc0745 | 288 | return r; |
0a753a76 | 289 | } |
290 | ||
68dc0745 | 291 | int |
292 | win32_sendto(SOCKET s, const char *buf, int len, int flags, | |
293 | const struct sockaddr *to, int tolen) | |
0a753a76 | 294 | { |
68dc0745 | 295 | int r; |
0a753a76 | 296 | |
326b05e3 | 297 | SOCKET_TEST_ERROR(r = sendto(TO_SOCKET(s), buf, len, flags, to, tolen)); |
68dc0745 | 298 | return r; |
0a753a76 | 299 | } |
300 | ||
68dc0745 | 301 | int |
302 | win32_setsockopt(SOCKET s, int level, int optname, const char *optval, int optlen) | |
0a753a76 | 303 | { |
68dc0745 | 304 | int r; |
0a753a76 | 305 | |
326b05e3 | 306 | SOCKET_TEST_ERROR(r = setsockopt(TO_SOCKET(s), level, optname, optval, optlen)); |
68dc0745 | 307 | return r; |
0a753a76 | 308 | } |
309 | ||
68dc0745 | 310 | int |
311 | win32_shutdown(SOCKET s, int how) | |
0a753a76 | 312 | { |
68dc0745 | 313 | int r; |
0a753a76 | 314 | |
326b05e3 | 315 | SOCKET_TEST_ERROR(r = shutdown(TO_SOCKET(s), how)); |
68dc0745 | 316 | return r; |
0a753a76 | 317 | } |
318 | ||
3a25acb4 GS |
319 | int |
320 | win32_closesocket(SOCKET s) | |
321 | { | |
322 | int r; | |
323 | ||
324 | SOCKET_TEST_ERROR(r = closesocket(TO_SOCKET(s))); | |
325 | return r; | |
326 | } | |
327 | ||
036c1c1e SH |
328 | void |
329 | convert_proto_info_w2a(WSAPROTOCOL_INFOW *in, WSAPROTOCOL_INFOA *out) | |
330 | { | |
331 | Copy(in, out, 1, WSAPROTOCOL_INFOA); | |
332 | wcstombs(out->szProtocol, in->szProtocol, sizeof(out->szProtocol)); | |
333 | } | |
334 | ||
335 | SOCKET | |
336 | open_ifs_socket(int af, int type, int protocol) | |
337 | { | |
1c972609 SH |
338 | dTHX; |
339 | char *s; | |
036c1c1e SH |
340 | unsigned long proto_buffers_len = 0; |
341 | int error_code; | |
342 | SOCKET out = INVALID_SOCKET; | |
343 | ||
1c972609 SH |
344 | if ((s = PerlEnv_getenv("PERL_ALLOW_NON_IFS_LSP")) && atoi(s)) |
345 | return WSASocket(af, type, protocol, NULL, 0, 0); | |
346 | ||
036c1c1e SH |
347 | if (WSCEnumProtocols(NULL, NULL, &proto_buffers_len, &error_code) == SOCKET_ERROR |
348 | && error_code == WSAENOBUFS) | |
349 | { | |
350 | WSAPROTOCOL_INFOW *proto_buffers; | |
351 | int protocols_available = 0; | |
352 | ||
a02a5408 | 353 | Newx(proto_buffers, proto_buffers_len / sizeof(WSAPROTOCOL_INFOW), |
036c1c1e SH |
354 | WSAPROTOCOL_INFOW); |
355 | ||
356 | if ((protocols_available = WSCEnumProtocols(NULL, proto_buffers, | |
357 | &proto_buffers_len, &error_code)) != SOCKET_ERROR) | |
358 | { | |
359 | int i; | |
360 | for (i = 0; i < protocols_available; i++) | |
361 | { | |
362 | WSAPROTOCOL_INFOA proto_info; | |
363 | ||
364 | if ((af != AF_UNSPEC && af != proto_buffers[i].iAddressFamily) | |
365 | || (type != proto_buffers[i].iSocketType) | |
f9169742 SH |
366 | || (protocol != 0 && proto_buffers[i].iProtocol != 0 && |
367 | protocol != proto_buffers[i].iProtocol)) | |
036c1c1e SH |
368 | continue; |
369 | ||
370 | if ((proto_buffers[i].dwServiceFlags1 & XP1_IFS_HANDLES) == 0) | |
371 | continue; | |
372 | ||
373 | convert_proto_info_w2a(&(proto_buffers[i]), &proto_info); | |
374 | ||
375 | out = WSASocket(af, type, protocol, &proto_info, 0, 0); | |
376 | break; | |
377 | } | |
378 | } | |
379 | ||
380 | Safefree(proto_buffers); | |
381 | } | |
382 | ||
383 | return out; | |
384 | } | |
385 | ||
68dc0745 | 386 | SOCKET |
387 | win32_socket(int af, int type, int protocol) | |
0a753a76 | 388 | { |
68dc0745 | 389 | SOCKET s; |
0a753a76 | 390 | |
3a25acb4 | 391 | StartSockets(); |
036c1c1e | 392 | |
72e6b643 | 393 | if((s = open_ifs_socket(af, type, protocol)) == INVALID_SOCKET) |
326b05e3 | 394 | errno = WSAGetLastError(); |
68dc0745 | 395 | else |
396 | s = OPEN_SOCKET(s); | |
0a753a76 | 397 | |
68dc0745 | 398 | return s; |
0a753a76 | 399 | } |
400 | ||
00b02797 JH |
401 | /* |
402 | * close RTL fd while respecting sockets | |
403 | * added as temporary measure until PerlIO has real | |
404 | * Win32 native layer | |
405 | * -- BKS, 11-11-2000 | |
406 | */ | |
407 | ||
408 | int my_close(int fd) | |
409 | { | |
410 | int osf; | |
411 | if (!wsock_started) /* No WinSock? */ | |
412 | return(close(fd)); /* Then not a socket. */ | |
413 | osf = TO_SOCKET(fd);/* Get it now before it's gone! */ | |
414 | if (osf != -1) { | |
415 | int err; | |
416 | err = closesocket(osf); | |
417 | if (err == 0) { | |
00b02797 JH |
418 | (void)close(fd); /* handle already closed, ignore error */ |
419 | return 0; | |
420 | } | |
421 | else if (err == SOCKET_ERROR) { | |
422 | err = WSAGetLastError(); | |
423 | if (err != WSAENOTSOCK) { | |
424 | (void)close(fd); | |
425 | errno = err; | |
426 | return EOF; | |
427 | } | |
428 | } | |
429 | } | |
430 | return close(fd); | |
431 | } | |
432 | ||
fb73857a | 433 | #undef fclose |
434 | int | |
435 | my_fclose (FILE *pf) | |
436 | { | |
4e945249 | 437 | int osf; |
326b05e3 GS |
438 | if (!wsock_started) /* No WinSock? */ |
439 | return(fclose(pf)); /* Then not a socket. */ | |
00b02797 | 440 | osf = TO_SOCKET(win32_fileno(pf));/* Get it now before it's gone! */ |
d3d49e29 GS |
441 | if (osf != -1) { |
442 | int err; | |
443 | win32_fflush(pf); | |
444 | err = closesocket(osf); | |
445 | if (err == 0) { | |
446 | (void)fclose(pf); /* handle already closed, ignore error */ | |
447 | return 0; | |
448 | } | |
449 | else if (err == SOCKET_ERROR) { | |
450 | err = WSAGetLastError(); | |
451 | if (err != WSAENOTSOCK) { | |
452 | (void)fclose(pf); | |
453 | errno = err; | |
454 | return EOF; | |
455 | } | |
456 | } | |
326b05e3 | 457 | } |
d3d49e29 | 458 | return fclose(pf); |
fb73857a | 459 | } |
460 | ||
68dc0745 | 461 | struct hostent * |
462 | win32_gethostbyaddr(const char *addr, int len, int type) | |
0a753a76 | 463 | { |
68dc0745 | 464 | struct hostent *r; |
0a753a76 | 465 | |
326b05e3 | 466 | SOCKET_TEST(r = gethostbyaddr(addr, len, type), NULL); |
68dc0745 | 467 | return r; |
0a753a76 | 468 | } |
469 | ||
68dc0745 | 470 | struct hostent * |
471 | win32_gethostbyname(const char *name) | |
0a753a76 | 472 | { |
68dc0745 | 473 | struct hostent *r; |
0a753a76 | 474 | |
326b05e3 | 475 | SOCKET_TEST(r = gethostbyname(name), NULL); |
68dc0745 | 476 | return r; |
0a753a76 | 477 | } |
478 | ||
68dc0745 | 479 | int |
480 | win32_gethostname(char *name, int len) | |
0a753a76 | 481 | { |
68dc0745 | 482 | int r; |
0a753a76 | 483 | |
326b05e3 | 484 | SOCKET_TEST_ERROR(r = gethostname(name, len)); |
68dc0745 | 485 | return r; |
0a753a76 | 486 | } |
487 | ||
68dc0745 | 488 | struct protoent * |
489 | win32_getprotobyname(const char *name) | |
0a753a76 | 490 | { |
68dc0745 | 491 | struct protoent *r; |
0a753a76 | 492 | |
326b05e3 | 493 | SOCKET_TEST(r = getprotobyname(name), NULL); |
68dc0745 | 494 | return r; |
0a753a76 | 495 | } |
496 | ||
68dc0745 | 497 | struct protoent * |
498 | win32_getprotobynumber(int num) | |
0a753a76 | 499 | { |
68dc0745 | 500 | struct protoent *r; |
0a753a76 | 501 | |
326b05e3 | 502 | SOCKET_TEST(r = getprotobynumber(num), NULL); |
68dc0745 | 503 | return r; |
0a753a76 | 504 | } |
505 | ||
68dc0745 | 506 | struct servent * |
507 | win32_getservbyname(const char *name, const char *proto) | |
0a753a76 | 508 | { |
acfe0abc | 509 | dTHX; |
68dc0745 | 510 | struct servent *r; |
c53bd28a | 511 | |
326b05e3 | 512 | SOCKET_TEST(r = getservbyname(name, proto), NULL); |
68dc0745 | 513 | if (r) { |
3352bfcb | 514 | r = win32_savecopyservent(&w32_servent, r, proto); |
68dc0745 | 515 | } |
516 | return r; | |
0a753a76 | 517 | } |
518 | ||
68dc0745 | 519 | struct servent * |
520 | win32_getservbyport(int port, const char *proto) | |
0a753a76 | 521 | { |
acfe0abc | 522 | dTHX; |
68dc0745 | 523 | struct servent *r; |
0a753a76 | 524 | |
326b05e3 | 525 | SOCKET_TEST(r = getservbyport(port, proto), NULL); |
68dc0745 | 526 | if (r) { |
3352bfcb | 527 | r = win32_savecopyservent(&w32_servent, r, proto); |
68dc0745 | 528 | } |
529 | return r; | |
0a753a76 | 530 | } |
531 | ||
f998180f GS |
532 | int |
533 | win32_ioctl(int i, unsigned int u, char *data) | |
534 | { | |
acfe0abc | 535 | dTHX; |
69a143a6 | 536 | u_long u_long_arg; |
f998180f | 537 | int retval; |
69a143a6 | 538 | |
f998180f | 539 | if (!wsock_started) { |
4f63d024 | 540 | Perl_croak_nocontext("ioctl implemented only on sockets"); |
f998180f GS |
541 | /* NOTREACHED */ |
542 | } | |
543 | ||
69a143a6 YO |
544 | /* mauke says using memcpy avoids alignment issues */ |
545 | memcpy(&u_long_arg, data, sizeof u_long_arg); | |
546 | retval = ioctlsocket(TO_SOCKET(i), (long)u, &u_long_arg); | |
547 | memcpy(data, &u_long_arg, sizeof u_long_arg); | |
548 | ||
f998180f GS |
549 | if (retval == SOCKET_ERROR) { |
550 | if (WSAGetLastError() == WSAENOTSOCK) { | |
4f63d024 | 551 | Perl_croak_nocontext("ioctl implemented only on sockets"); |
f998180f GS |
552 | /* NOTREACHED */ |
553 | } | |
554 | errno = WSAGetLastError(); | |
555 | } | |
556 | return retval; | |
557 | } | |
558 | ||
68dc0745 | 559 | char FAR * |
560 | win32_inet_ntoa(struct in_addr in) | |
0a753a76 | 561 | { |
326b05e3 GS |
562 | StartSockets(); |
563 | return inet_ntoa(in); | |
0a753a76 | 564 | } |
565 | ||
68dc0745 | 566 | unsigned long |
567 | win32_inet_addr(const char FAR *cp) | |
0a753a76 | 568 | { |
326b05e3 GS |
569 | StartSockets(); |
570 | return inet_addr(cp); | |
0a753a76 | 571 | } |
68dc0745 | 572 | |
573 | /* | |
574 | * Networking stubs | |
575 | */ | |
0a753a76 | 576 | |
68dc0745 | 577 | void |
578 | win32_endhostent() | |
0a753a76 | 579 | { |
acfe0abc | 580 | dTHX; |
4f63d024 | 581 | Perl_croak_nocontext("endhostent not implemented!\n"); |
0a753a76 | 582 | } |
583 | ||
68dc0745 | 584 | void |
585 | win32_endnetent() | |
0a753a76 | 586 | { |
acfe0abc | 587 | dTHX; |
4f63d024 | 588 | Perl_croak_nocontext("endnetent not implemented!\n"); |
0a753a76 | 589 | } |
590 | ||
68dc0745 | 591 | void |
592 | win32_endprotoent() | |
0a753a76 | 593 | { |
acfe0abc | 594 | dTHX; |
4f63d024 | 595 | Perl_croak_nocontext("endprotoent not implemented!\n"); |
0a753a76 | 596 | } |
597 | ||
68dc0745 | 598 | void |
599 | win32_endservent() | |
0a753a76 | 600 | { |
acfe0abc | 601 | dTHX; |
4f63d024 | 602 | Perl_croak_nocontext("endservent not implemented!\n"); |
0a753a76 | 603 | } |
604 | ||
605 | ||
68dc0745 | 606 | struct netent * |
607 | win32_getnetent(void) | |
0a753a76 | 608 | { |
acfe0abc | 609 | dTHX; |
4f63d024 | 610 | Perl_croak_nocontext("getnetent not implemented!\n"); |
68dc0745 | 611 | return (struct netent *) NULL; |
0a753a76 | 612 | } |
613 | ||
68dc0745 | 614 | struct netent * |
615 | win32_getnetbyname(char *name) | |
0a753a76 | 616 | { |
acfe0abc | 617 | dTHX; |
4f63d024 | 618 | Perl_croak_nocontext("getnetbyname not implemented!\n"); |
68dc0745 | 619 | return (struct netent *)NULL; |
0a753a76 | 620 | } |
621 | ||
68dc0745 | 622 | struct netent * |
623 | win32_getnetbyaddr(long net, int type) | |
0a753a76 | 624 | { |
acfe0abc | 625 | dTHX; |
4f63d024 | 626 | Perl_croak_nocontext("getnetbyaddr not implemented!\n"); |
68dc0745 | 627 | return (struct netent *)NULL; |
0a753a76 | 628 | } |
629 | ||
68dc0745 | 630 | struct protoent * |
631 | win32_getprotoent(void) | |
0a753a76 | 632 | { |
acfe0abc | 633 | dTHX; |
4f63d024 | 634 | Perl_croak_nocontext("getprotoent not implemented!\n"); |
68dc0745 | 635 | return (struct protoent *) NULL; |
0a753a76 | 636 | } |
637 | ||
68dc0745 | 638 | struct servent * |
639 | win32_getservent(void) | |
0a753a76 | 640 | { |
acfe0abc | 641 | dTHX; |
4f63d024 | 642 | Perl_croak_nocontext("getservent not implemented!\n"); |
68dc0745 | 643 | return (struct servent *) NULL; |
0a753a76 | 644 | } |
645 | ||
68dc0745 | 646 | void |
647 | win32_sethostent(int stayopen) | |
0a753a76 | 648 | { |
acfe0abc | 649 | dTHX; |
4f63d024 | 650 | Perl_croak_nocontext("sethostent not implemented!\n"); |
0a753a76 | 651 | } |
652 | ||
653 | ||
68dc0745 | 654 | void |
655 | win32_setnetent(int stayopen) | |
0a753a76 | 656 | { |
acfe0abc | 657 | dTHX; |
4f63d024 | 658 | Perl_croak_nocontext("setnetent not implemented!\n"); |
0a753a76 | 659 | } |
660 | ||
661 | ||
68dc0745 | 662 | void |
663 | win32_setprotoent(int stayopen) | |
0a753a76 | 664 | { |
acfe0abc | 665 | dTHX; |
4f63d024 | 666 | Perl_croak_nocontext("setprotoent not implemented!\n"); |
0a753a76 | 667 | } |
668 | ||
669 | ||
68dc0745 | 670 | void |
671 | win32_setservent(int stayopen) | |
0a753a76 | 672 | { |
acfe0abc | 673 | dTHX; |
4f63d024 | 674 | Perl_croak_nocontext("setservent not implemented!\n"); |
0a753a76 | 675 | } |
676 | ||
137443ea | 677 | static struct servent* |
678 | win32_savecopyservent(struct servent*d, struct servent*s, const char *proto) | |
679 | { | |
680 | d->s_name = s->s_name; | |
681 | d->s_aliases = s->s_aliases; | |
682 | d->s_port = s->s_port; | |
8cbe99e5 | 683 | if (s->s_proto && strlen(s->s_proto)) |
137443ea | 684 | d->s_proto = s->s_proto; |
0af56dfe | 685 | else |
c69f6586 | 686 | if (proto && strlen(proto)) |
137443ea | 687 | d->s_proto = (char *)proto; |
688 | else | |
689 | d->s_proto = "tcp"; | |
690 | ||
691 | return d; | |
692 | } | |
693 | ||
0a753a76 | 694 |