source: vendor/perl/5.8.8/win32/win32sck.c

Last change on this file was 3181, checked in by bird, 18 years ago

perl 5.8.8

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