This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Do some updates also on pod.mak -- which seems to
[perl5.git] / win32 / win32sck.c
... / ...
CommitLineData
1/* win32sck.c
2 *
3 * (c) 1995 Microsoft Corporation. All rights reserved.
4 * Developed by hip communications inc., http://info.hip.com/info/
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 */
10
11#define WIN32IO_IS_STDIO
12#define WIN32SCK_IS_STDSCK
13#define WIN32_LEAN_AND_MEAN
14#define PERLIO_NOT_STDIO 0
15#ifdef __GNUC__
16#define Win32_Winsock
17#endif
18#include <windows.h>
19#include "EXTERN.h"
20#include "perl.h"
21
22#include "Win32iop.h"
23#include <sys/socket.h>
24#include <fcntl.h>
25#include <sys/stat.h>
26#include <assert.h>
27#include <io.h>
28
29/* thanks to Beverly Brown (beverly@datacube.com) */
30#ifdef USE_SOCKETS_AS_HANDLES
31# define OPEN_SOCKET(x) win32_open_osfhandle(x,O_RDWR|O_BINARY)
32# define TO_SOCKET(x) _get_osfhandle(x)
33#else
34# define OPEN_SOCKET(x) (x)
35# define TO_SOCKET(x) (x)
36#endif /* USE_SOCKETS_AS_HANDLES */
37
38#if defined(USE_ITHREADS)
39#define StartSockets() \
40 STMT_START { \
41 if (!wsock_started) \
42 start_sockets(); \
43 set_socktype(); \
44 } STMT_END
45#else
46#define StartSockets() \
47 STMT_START { \
48 if (!wsock_started) { \
49 start_sockets(); \
50 set_socktype(); \
51 } \
52 } STMT_END
53#endif
54
55#define SOCKET_TEST(x, y) \
56 STMT_START { \
57 StartSockets(); \
58 if((x) == (y)) \
59 errno = WSAGetLastError(); \
60 } STMT_END
61
62#define SOCKET_TEST_ERROR(x) SOCKET_TEST(x, SOCKET_ERROR)
63
64static struct servent* win32_savecopyservent(struct servent*d,
65 struct servent*s,
66 const char *proto);
67
68static int wsock_started = 0;
69
70EXTERN_C void
71EndSockets(void)
72{
73 if (wsock_started)
74 WSACleanup();
75}
76
77void
78start_sockets(void)
79{
80 dTHX;
81 unsigned short version;
82 WSADATA retdata;
83 int ret;
84
85 /*
86 * initalize the winsock interface and insure that it is
87 * cleaned up at exit.
88 */
89 version = 0x101;
90 if(ret = WSAStartup(version, &retdata))
91 Perl_croak_nocontext("Unable to locate winsock library!\n");
92 if(retdata.wVersion != version)
93 Perl_croak_nocontext("Could not find version 1.1 of winsock dll\n");
94
95 /* atexit((void (*)(void)) EndSockets); */
96 wsock_started = 1;
97}
98
99void
100set_socktype(void)
101{
102#ifdef USE_SOCKETS_AS_HANDLES
103#if defined(USE_ITHREADS)
104 dTHX;
105 if (!w32_init_socktype) {
106#endif
107 int iSockOpt = SO_SYNCHRONOUS_NONALERT;
108 /*
109 * Enable the use of sockets as filehandles
110 */
111 setsockopt(INVALID_SOCKET, SOL_SOCKET, SO_OPENTYPE,
112 (char *)&iSockOpt, sizeof(iSockOpt));
113#if defined(USE_ITHREADS)
114 w32_init_socktype = 1;
115 }
116#endif
117#endif /* USE_SOCKETS_AS_HANDLES */
118}
119
120
121#ifndef USE_SOCKETS_AS_HANDLES
122#undef fdopen
123FILE *
124my_fdopen(int fd, char *mode)
125{
126 FILE *fp;
127 char sockbuf[256];
128 int optlen = sizeof(sockbuf);
129 int retval;
130
131 if (!wsock_started)
132 return(fdopen(fd, mode));
133
134 retval = getsockopt((SOCKET)fd, SOL_SOCKET, SO_TYPE, sockbuf, &optlen);
135 if(retval == SOCKET_ERROR && WSAGetLastError() == WSAENOTSOCK) {
136 return(fdopen(fd, mode));
137 }
138
139 /*
140 * If we get here, then fd is actually a socket.
141 */
142 Newz(1310, fp, 1, FILE); /* XXX leak, good thing this code isn't used */
143 if(fp == NULL) {
144 errno = ENOMEM;
145 return NULL;
146 }
147
148 fp->_file = fd;
149 if(*mode == 'r')
150 fp->_flag = _IOREAD;
151 else
152 fp->_flag = _IOWRT;
153
154 return fp;
155}
156#endif /* USE_SOCKETS_AS_HANDLES */
157
158
159u_long
160win32_htonl(u_long hostlong)
161{
162 StartSockets();
163 return htonl(hostlong);
164}
165
166u_short
167win32_htons(u_short hostshort)
168{
169 StartSockets();
170 return htons(hostshort);
171}
172
173u_long
174win32_ntohl(u_long netlong)
175{
176 StartSockets();
177 return ntohl(netlong);
178}
179
180u_short
181win32_ntohs(u_short netshort)
182{
183 StartSockets();
184 return ntohs(netshort);
185}
186
187
188
189SOCKET
190win32_accept(SOCKET s, struct sockaddr *addr, int *addrlen)
191{
192 SOCKET r;
193
194 SOCKET_TEST((r = accept(TO_SOCKET(s), addr, addrlen)), INVALID_SOCKET);
195 return OPEN_SOCKET(r);
196}
197
198int
199win32_bind(SOCKET s, const struct sockaddr *addr, int addrlen)
200{
201 int r;
202
203 SOCKET_TEST_ERROR(r = bind(TO_SOCKET(s), addr, addrlen));
204 return r;
205}
206
207int
208win32_connect(SOCKET s, const struct sockaddr *addr, int addrlen)
209{
210 int r;
211
212 SOCKET_TEST_ERROR(r = connect(TO_SOCKET(s), addr, addrlen));
213 return r;
214}
215
216
217int
218win32_getpeername(SOCKET s, struct sockaddr *addr, int *addrlen)
219{
220 int r;
221
222 SOCKET_TEST_ERROR(r = getpeername(TO_SOCKET(s), addr, addrlen));
223 return r;
224}
225
226int
227win32_getsockname(SOCKET s, struct sockaddr *addr, int *addrlen)
228{
229 int r;
230
231 SOCKET_TEST_ERROR(r = getsockname(TO_SOCKET(s), addr, addrlen));
232 return r;
233}
234
235int
236win32_getsockopt(SOCKET s, int level, int optname, char *optval, int *optlen)
237{
238 int r;
239
240 SOCKET_TEST_ERROR(r = getsockopt(TO_SOCKET(s), level, optname, optval, optlen));
241 return r;
242}
243
244int
245win32_ioctlsocket(SOCKET s, long cmd, u_long *argp)
246{
247 int r;
248
249 SOCKET_TEST_ERROR(r = ioctlsocket(TO_SOCKET(s), cmd, argp));
250 return r;
251}
252
253int
254win32_listen(SOCKET s, int backlog)
255{
256 int r;
257
258 SOCKET_TEST_ERROR(r = listen(TO_SOCKET(s), backlog));
259 return r;
260}
261
262int
263win32_recv(SOCKET s, char *buf, int len, int flags)
264{
265 int r;
266
267 SOCKET_TEST_ERROR(r = recv(TO_SOCKET(s), buf, len, flags));
268 return r;
269}
270
271int
272win32_recvfrom(SOCKET s, char *buf, int len, int flags, struct sockaddr *from, int *fromlen)
273{
274 int r;
275 int frombufsize = *fromlen;
276
277 SOCKET_TEST_ERROR(r = recvfrom(TO_SOCKET(s), buf, len, flags, from, fromlen));
278 /* Winsock's recvfrom() only returns a valid 'from' when the socket
279 * is connectionless. Perl expects a valid 'from' for all types
280 * of sockets, so go the extra mile.
281 */
282 if (r != SOCKET_ERROR && frombufsize == *fromlen)
283 (void)win32_getpeername(s, from, fromlen);
284 return r;
285}
286
287/* select contributed by Vincent R. Slyngstad (vrs@ibeam.intel.com) */
288int
289win32_select(int nfds, Perl_fd_set* rd, Perl_fd_set* wr, Perl_fd_set* ex, const struct timeval* timeout)
290{
291 int r;
292#ifdef USE_SOCKETS_AS_HANDLES
293 Perl_fd_set dummy;
294 int i, fd, save_errno = errno;
295 FD_SET nrd, nwr, nex, *prd, *pwr, *pex;
296
297 /* winsock seems incapable of dealing with all three null fd_sets,
298 * so do the (millisecond) sleep as a special case
299 */
300 if (!(rd || wr || ex)) {
301 if (timeout)
302 Sleep(timeout->tv_sec * 1000 +
303 timeout->tv_usec / 1000); /* do the best we can */
304 else
305 Sleep(UINT_MAX);
306 return 0;
307 }
308 StartSockets();
309 PERL_FD_ZERO(&dummy);
310 if (!rd)
311 rd = &dummy, prd = NULL;
312 else
313 prd = &nrd;
314 if (!wr)
315 wr = &dummy, pwr = NULL;
316 else
317 pwr = &nwr;
318 if (!ex)
319 ex = &dummy, pex = NULL;
320 else
321 pex = &nex;
322
323 FD_ZERO(&nrd);
324 FD_ZERO(&nwr);
325 FD_ZERO(&nex);
326 for (i = 0; i < nfds; i++) {
327 fd = TO_SOCKET(i);
328 if (PERL_FD_ISSET(i,rd))
329 FD_SET(fd, &nrd);
330 if (PERL_FD_ISSET(i,wr))
331 FD_SET(fd, &nwr);
332 if (PERL_FD_ISSET(i,ex))
333 FD_SET(fd, &nex);
334 }
335
336 errno = save_errno;
337 SOCKET_TEST_ERROR(r = select(nfds, prd, pwr, pex, timeout));
338 save_errno = errno;
339
340 for (i = 0; i < nfds; i++) {
341 fd = TO_SOCKET(i);
342 if (PERL_FD_ISSET(i,rd) && !FD_ISSET(fd, &nrd))
343 PERL_FD_CLR(i,rd);
344 if (PERL_FD_ISSET(i,wr) && !FD_ISSET(fd, &nwr))
345 PERL_FD_CLR(i,wr);
346 if (PERL_FD_ISSET(i,ex) && !FD_ISSET(fd, &nex))
347 PERL_FD_CLR(i,ex);
348 }
349 errno = save_errno;
350#else
351 SOCKET_TEST_ERROR(r = select(nfds, rd, wr, ex, timeout));
352#endif
353 return r;
354}
355
356int
357win32_send(SOCKET s, const char *buf, int len, int flags)
358{
359 int r;
360
361 SOCKET_TEST_ERROR(r = send(TO_SOCKET(s), buf, len, flags));
362 return r;
363}
364
365int
366win32_sendto(SOCKET s, const char *buf, int len, int flags,
367 const struct sockaddr *to, int tolen)
368{
369 int r;
370
371 SOCKET_TEST_ERROR(r = sendto(TO_SOCKET(s), buf, len, flags, to, tolen));
372 return r;
373}
374
375int
376win32_setsockopt(SOCKET s, int level, int optname, const char *optval, int optlen)
377{
378 int r;
379
380 SOCKET_TEST_ERROR(r = setsockopt(TO_SOCKET(s), level, optname, optval, optlen));
381 return r;
382}
383
384int
385win32_shutdown(SOCKET s, int how)
386{
387 int r;
388
389 SOCKET_TEST_ERROR(r = shutdown(TO_SOCKET(s), how));
390 return r;
391}
392
393int
394win32_closesocket(SOCKET s)
395{
396 int r;
397
398 SOCKET_TEST_ERROR(r = closesocket(TO_SOCKET(s)));
399 return r;
400}
401
402SOCKET
403win32_socket(int af, int type, int protocol)
404{
405 SOCKET s;
406
407#ifndef USE_SOCKETS_AS_HANDLES
408 SOCKET_TEST(s = socket(af, type, protocol), INVALID_SOCKET);
409#else
410 StartSockets();
411 if((s = socket(af, type, protocol)) == INVALID_SOCKET)
412 errno = WSAGetLastError();
413 else
414 s = OPEN_SOCKET(s);
415#endif /* USE_SOCKETS_AS_HANDLES */
416
417 return s;
418}
419
420/*
421 * close RTL fd while respecting sockets
422 * added as temporary measure until PerlIO has real
423 * Win32 native layer
424 * -- BKS, 11-11-2000
425*/
426
427int my_close(int fd)
428{
429 int osf;
430 if (!wsock_started) /* No WinSock? */
431 return(close(fd)); /* Then not a socket. */
432 osf = TO_SOCKET(fd);/* Get it now before it's gone! */
433 if (osf != -1) {
434 int err;
435 err = closesocket(osf);
436 if (err == 0) {
437#if defined(USE_FIXED_OSFHANDLE) || defined(PERL_MSVCRT_READFIX)
438 _set_osfhnd(fd, INVALID_HANDLE_VALUE);
439#endif
440 (void)close(fd); /* handle already closed, ignore error */
441 return 0;
442 }
443 else if (err == SOCKET_ERROR) {
444 err = WSAGetLastError();
445 if (err != WSAENOTSOCK) {
446 (void)close(fd);
447 errno = err;
448 return EOF;
449 }
450 }
451 }
452 return close(fd);
453}
454
455#undef fclose
456int
457my_fclose (FILE *pf)
458{
459 int osf;
460 if (!wsock_started) /* No WinSock? */
461 return(fclose(pf)); /* Then not a socket. */
462 osf = TO_SOCKET(win32_fileno(pf));/* Get it now before it's gone! */
463 if (osf != -1) {
464 int err;
465 win32_fflush(pf);
466 err = closesocket(osf);
467 if (err == 0) {
468#if defined(USE_FIXED_OSFHANDLE) || defined(PERL_MSVCRT_READFIX)
469 _set_osfhnd(win32_fileno(pf), INVALID_HANDLE_VALUE);
470#endif
471 (void)fclose(pf); /* handle already closed, ignore error */
472 return 0;
473 }
474 else if (err == SOCKET_ERROR) {
475 err = WSAGetLastError();
476 if (err != WSAENOTSOCK) {
477 (void)fclose(pf);
478 errno = err;
479 return EOF;
480 }
481 }
482 }
483 return fclose(pf);
484}
485
486#undef fstat
487int
488my_fstat(int fd, Stat_t *sbufptr)
489{
490 /* This fixes a bug in fstat() on Windows 9x. fstat() uses the
491 * GetFileType() win32 syscall, which will fail on Windows 9x.
492 * So if we recognize a socket on Windows 9x, we return the
493 * same results as on Windows NT/2000.
494 * XXX this should be extended further to set S_IFSOCK on
495 * sbufptr->st_mode.
496 */
497 int osf;
498 if (!wsock_started || IsWinNT()) {
499#if defined(WIN64) || defined(USE_LARGE_FILES)
500 return _fstati64(fd, sbufptr);
501#else
502 return fstat(fd, sbufptr);
503#endif
504 }
505
506 osf = TO_SOCKET(fd);
507 if (osf != -1) {
508 char sockbuf[256];
509 int optlen = sizeof(sockbuf);
510 int retval;
511
512 retval = getsockopt((SOCKET)osf, SOL_SOCKET, SO_TYPE, sockbuf, &optlen);
513 if (retval != SOCKET_ERROR || WSAGetLastError() != WSAENOTSOCK) {
514#if defined(__BORLANDC__)&&(__BORLANDC__<=0x520)
515 sbufptr->st_mode = S_IFIFO;
516#else
517 sbufptr->st_mode = _S_IFIFO;
518#endif
519 sbufptr->st_rdev = sbufptr->st_dev = (dev_t)fd;
520 sbufptr->st_nlink = 1;
521 sbufptr->st_uid = sbufptr->st_gid = sbufptr->st_ino = 0;
522 sbufptr->st_atime = sbufptr->st_mtime = sbufptr->st_ctime = 0;
523 sbufptr->st_size = (Off_t)0;
524 return 0;
525 }
526 }
527#if defined(WIN64) || defined(USE_LARGE_FILES)
528 return _fstati64(fd, sbufptr);
529#else
530 return fstat(fd, sbufptr);
531#endif
532}
533
534struct hostent *
535win32_gethostbyaddr(const char *addr, int len, int type)
536{
537 struct hostent *r;
538
539 SOCKET_TEST(r = gethostbyaddr(addr, len, type), NULL);
540 return r;
541}
542
543struct hostent *
544win32_gethostbyname(const char *name)
545{
546 struct hostent *r;
547
548 SOCKET_TEST(r = gethostbyname(name), NULL);
549 return r;
550}
551
552int
553win32_gethostname(char *name, int len)
554{
555 int r;
556
557 SOCKET_TEST_ERROR(r = gethostname(name, len));
558 return r;
559}
560
561struct protoent *
562win32_getprotobyname(const char *name)
563{
564 struct protoent *r;
565
566 SOCKET_TEST(r = getprotobyname(name), NULL);
567 return r;
568}
569
570struct protoent *
571win32_getprotobynumber(int num)
572{
573 struct protoent *r;
574
575 SOCKET_TEST(r = getprotobynumber(num), NULL);
576 return r;
577}
578
579struct servent *
580win32_getservbyname(const char *name, const char *proto)
581{
582 dTHX;
583 struct servent *r;
584
585 SOCKET_TEST(r = getservbyname(name, proto), NULL);
586 if (r) {
587 r = win32_savecopyservent(&w32_servent, r, proto);
588 }
589 return r;
590}
591
592struct servent *
593win32_getservbyport(int port, const char *proto)
594{
595 dTHX;
596 struct servent *r;
597
598 SOCKET_TEST(r = getservbyport(port, proto), NULL);
599 if (r) {
600 r = win32_savecopyservent(&w32_servent, r, proto);
601 }
602 return r;
603}
604
605int
606win32_ioctl(int i, unsigned int u, char *data)
607{
608 dTHX;
609 u_long argp = (u_long)data;
610 int retval;
611
612 if (!wsock_started) {
613 Perl_croak_nocontext("ioctl implemented only on sockets");
614 /* NOTREACHED */
615 }
616
617 retval = ioctlsocket(TO_SOCKET(i), (long)u, &argp);
618 if (retval == SOCKET_ERROR) {
619 if (WSAGetLastError() == WSAENOTSOCK) {
620 Perl_croak_nocontext("ioctl implemented only on sockets");
621 /* NOTREACHED */
622 }
623 errno = WSAGetLastError();
624 }
625 return retval;
626}
627
628char FAR *
629win32_inet_ntoa(struct in_addr in)
630{
631 StartSockets();
632 return inet_ntoa(in);
633}
634
635unsigned long
636win32_inet_addr(const char FAR *cp)
637{
638 StartSockets();
639 return inet_addr(cp);
640}
641
642/*
643 * Networking stubs
644 */
645
646void
647win32_endhostent()
648{
649 dTHX;
650 Perl_croak_nocontext("endhostent not implemented!\n");
651}
652
653void
654win32_endnetent()
655{
656 dTHX;
657 Perl_croak_nocontext("endnetent not implemented!\n");
658}
659
660void
661win32_endprotoent()
662{
663 dTHX;
664 Perl_croak_nocontext("endprotoent not implemented!\n");
665}
666
667void
668win32_endservent()
669{
670 dTHX;
671 Perl_croak_nocontext("endservent not implemented!\n");
672}
673
674
675struct netent *
676win32_getnetent(void)
677{
678 dTHX;
679 Perl_croak_nocontext("getnetent not implemented!\n");
680 return (struct netent *) NULL;
681}
682
683struct netent *
684win32_getnetbyname(char *name)
685{
686 dTHX;
687 Perl_croak_nocontext("getnetbyname not implemented!\n");
688 return (struct netent *)NULL;
689}
690
691struct netent *
692win32_getnetbyaddr(long net, int type)
693{
694 dTHX;
695 Perl_croak_nocontext("getnetbyaddr not implemented!\n");
696 return (struct netent *)NULL;
697}
698
699struct protoent *
700win32_getprotoent(void)
701{
702 dTHX;
703 Perl_croak_nocontext("getprotoent not implemented!\n");
704 return (struct protoent *) NULL;
705}
706
707struct servent *
708win32_getservent(void)
709{
710 dTHX;
711 Perl_croak_nocontext("getservent not implemented!\n");
712 return (struct servent *) NULL;
713}
714
715void
716win32_sethostent(int stayopen)
717{
718 dTHX;
719 Perl_croak_nocontext("sethostent not implemented!\n");
720}
721
722
723void
724win32_setnetent(int stayopen)
725{
726 dTHX;
727 Perl_croak_nocontext("setnetent not implemented!\n");
728}
729
730
731void
732win32_setprotoent(int stayopen)
733{
734 dTHX;
735 Perl_croak_nocontext("setprotoent not implemented!\n");
736}
737
738
739void
740win32_setservent(int stayopen)
741{
742 dTHX;
743 Perl_croak_nocontext("setservent not implemented!\n");
744}
745
746static struct servent*
747win32_savecopyservent(struct servent*d, struct servent*s, const char *proto)
748{
749 d->s_name = s->s_name;
750 d->s_aliases = s->s_aliases;
751 d->s_port = s->s_port;
752#ifndef __BORLANDC__ /* Buggy on Win95 and WinNT-with-Borland-WSOCK */
753 if (!IsWin95() && s->s_proto && strlen(s->s_proto))
754 d->s_proto = s->s_proto;
755 else
756#endif
757 if (proto && strlen(proto))
758 d->s_proto = (char *)proto;
759 else
760 d->s_proto = "tcp";
761
762 return d;
763}
764
765