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