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