Mingw32 + w32api-0.1.5 tweaks
[p5sagit/p5-mst-13.2.git] / ext / Socket / Socket.xs
1 #include "EXTERN.h"
2 #include "perl.h"
3 #include "XSUB.h"
4
5 #ifndef VMS
6 # ifdef I_SYS_TYPES
7 #  include <sys/types.h>
8 # endif
9 #include <sys/socket.h>
10 #ifdef MPE
11 # define PF_INET AF_INET
12 # define PF_UNIX AF_UNIX
13 # define SOCK_RAW 3
14 #endif
15 #ifdef I_SYS_UN
16 #include <sys/un.h>
17 #endif
18 # ifdef I_NETINET_IN
19 #  include <netinet/in.h>
20 # endif
21 #include <netdb.h>
22 #ifdef I_ARPA_INET
23 # include <arpa/inet.h>
24 #endif
25 #else
26 #include "sockadapt.h"
27 #endif
28
29 #ifndef WIN32 /* I_NETINET_TCP */
30 #include <netinet/tcp.h>
31 #endif
32
33 #ifdef I_SYSUIO
34 # include <sys/uio.h>
35 #endif
36
37 #ifndef AF_NBS
38 #undef PF_NBS
39 #endif
40
41 #ifndef AF_X25
42 #undef PF_X25
43 #endif
44
45 #ifndef INADDR_NONE
46 #define INADDR_NONE     0xffffffff
47 #endif /* INADDR_NONE */
48 #ifndef INADDR_BROADCAST
49 #define INADDR_BROADCAST        0xffffffff
50 #endif /* INADDR_BROADCAST */
51 #ifndef INADDR_LOOPBACK
52 #define INADDR_LOOPBACK         0x7F000001
53 #endif /* INADDR_LOOPBACK */
54
55 #ifndef HAS_INET_ATON
56
57 /* 
58  * Check whether "cp" is a valid ascii representation
59  * of an Internet address and convert to a binary address.
60  * Returns 1 if the address is valid, 0 if not.
61  * This replaces inet_addr, the return value from which
62  * cannot distinguish between failure and a local broadcast address.
63  */
64 static int
65 my_inet_aton(register const char *cp, struct in_addr *addr)
66 {
67         register U32 val;
68         register int base;
69         register char c;
70         int nparts;
71         const char *s;
72         unsigned int parts[4];
73         register unsigned int *pp = parts;
74
75         if (!cp)
76                 return 0;
77         for (;;) {
78                 /*
79                  * Collect number up to ``.''.
80                  * Values are specified as for C:
81                  * 0x=hex, 0=octal, other=decimal.
82                  */
83                 val = 0; base = 10;
84                 if (*cp == '0') {
85                         if (*++cp == 'x' || *cp == 'X')
86                                 base = 16, cp++;
87                         else
88                                 base = 8;
89                 }
90                 while ((c = *cp) != '\0') {
91                         if (isDIGIT(c)) {
92                                 val = (val * base) + (c - '0');
93                                 cp++;
94                                 continue;
95                         }
96                         if (base == 16 && (s=strchr(PL_hexdigit,c))) {
97                                 val = (val << 4) + 
98                                         ((s - PL_hexdigit) & 15);
99                                 cp++;
100                                 continue;
101                         }
102                         break;
103                 }
104                 if (*cp == '.') {
105                         /*
106                          * Internet format:
107                          *      a.b.c.d
108                          *      a.b.c   (with c treated as 16-bits)
109                          *      a.b     (with b treated as 24 bits)
110                          */
111                         if (pp >= parts + 3 || val > 0xff)
112                                 return 0;
113                         *pp++ = val, cp++;
114                 } else
115                         break;
116         }
117         /*
118          * Check for trailing characters.
119          */
120         if (*cp && !isSPACE(*cp))
121                 return 0;
122         /*
123          * Concoct the address according to
124          * the number of parts specified.
125          */
126         nparts = pp - parts + 1;        /* force to an int for switch() */
127         switch (nparts) {
128
129         case 1:                         /* a -- 32 bits */
130                 break;
131
132         case 2:                         /* a.b -- 8.24 bits */
133                 if (val > 0xffffff)
134                         return 0;
135                 val |= parts[0] << 24;
136                 break;
137
138         case 3:                         /* a.b.c -- 8.8.16 bits */
139                 if (val > 0xffff)
140                         return 0;
141                 val |= (parts[0] << 24) | (parts[1] << 16);
142                 break;
143
144         case 4:                         /* a.b.c.d -- 8.8.8.8 bits */
145                 if (val > 0xff)
146                         return 0;
147                 val |= (parts[0] << 24) | (parts[1] << 16) | (parts[2] << 8);
148                 break;
149         }
150         addr->s_addr = htonl(val);
151         return 1;
152 }
153
154 #undef inet_aton
155 #define inet_aton my_inet_aton
156
157 #endif /* ! HAS_INET_ATON */
158
159
160 static int
161 not_here(char *s)
162 {
163     croak("Socket::%s not implemented on this architecture", s);
164     return -1;
165 }
166
167 static double
168 constant(char *name, int arg)
169 {
170     errno = 0;
171     switch (*name) {
172     case 'A':
173         if (strEQ(name, "AF_802"))
174 #ifdef AF_802
175             return AF_802;
176 #else
177             goto not_there;
178 #endif
179         if (strEQ(name, "AF_APPLETALK"))
180 #ifdef AF_APPLETALK
181             return AF_APPLETALK;
182 #else
183             goto not_there;
184 #endif
185         if (strEQ(name, "AF_CCITT"))
186 #ifdef AF_CCITT
187             return AF_CCITT;
188 #else
189             goto not_there;
190 #endif
191         if (strEQ(name, "AF_CHAOS"))
192 #ifdef AF_CHAOS
193             return AF_CHAOS;
194 #else
195             goto not_there;
196 #endif
197         if (strEQ(name, "AF_DATAKIT"))
198 #ifdef AF_DATAKIT
199             return AF_DATAKIT;
200 #else
201             goto not_there;
202 #endif
203         if (strEQ(name, "AF_DECnet"))
204 #ifdef AF_DECnet
205             return AF_DECnet;
206 #else
207             goto not_there;
208 #endif
209         if (strEQ(name, "AF_DLI"))
210 #ifdef AF_DLI
211             return AF_DLI;
212 #else
213             goto not_there;
214 #endif
215         if (strEQ(name, "AF_ECMA"))
216 #ifdef AF_ECMA
217             return AF_ECMA;
218 #else
219             goto not_there;
220 #endif
221         if (strEQ(name, "AF_GOSIP"))
222 #ifdef AF_GOSIP
223             return AF_GOSIP;
224 #else
225             goto not_there;
226 #endif
227         if (strEQ(name, "AF_HYLINK"))
228 #ifdef AF_HYLINK
229             return AF_HYLINK;
230 #else
231             goto not_there;
232 #endif
233         if (strEQ(name, "AF_IMPLINK"))
234 #ifdef AF_IMPLINK
235             return AF_IMPLINK;
236 #else
237             goto not_there;
238 #endif
239         if (strEQ(name, "AF_INET"))
240 #ifdef AF_INET
241             return AF_INET;
242 #else
243             goto not_there;
244 #endif
245         if (strEQ(name, "AF_LAT"))
246 #ifdef AF_LAT
247             return AF_LAT;
248 #else
249             goto not_there;
250 #endif
251         if (strEQ(name, "AF_MAX"))
252 #ifdef AF_MAX
253             return AF_MAX;
254 #else
255             goto not_there;
256 #endif
257         if (strEQ(name, "AF_NBS"))
258 #ifdef AF_NBS
259             return AF_NBS;
260 #else
261             goto not_there;
262 #endif
263         if (strEQ(name, "AF_NIT"))
264 #ifdef AF_NIT
265             return AF_NIT;
266 #else
267             goto not_there;
268 #endif
269         if (strEQ(name, "AF_NS"))
270 #ifdef AF_NS
271             return AF_NS;
272 #else
273             goto not_there;
274 #endif
275         if (strEQ(name, "AF_OSI"))
276 #ifdef AF_OSI
277             return AF_OSI;
278 #else
279             goto not_there;
280 #endif
281         if (strEQ(name, "AF_OSINET"))
282 #ifdef AF_OSINET
283             return AF_OSINET;
284 #else
285             goto not_there;
286 #endif
287         if (strEQ(name, "AF_PUP"))
288 #ifdef AF_PUP
289             return AF_PUP;
290 #else
291             goto not_there;
292 #endif
293         if (strEQ(name, "AF_SNA"))
294 #ifdef AF_SNA
295             return AF_SNA;
296 #else
297             goto not_there;
298 #endif
299         if (strEQ(name, "AF_UNIX"))
300 #ifdef AF_UNIX
301             return AF_UNIX;
302 #else
303             goto not_there;
304 #endif
305         if (strEQ(name, "AF_UNSPEC"))
306 #ifdef AF_UNSPEC
307             return AF_UNSPEC;
308 #else
309             goto not_there;
310 #endif
311         if (strEQ(name, "AF_X25"))
312 #ifdef AF_X25
313             return AF_X25;
314 #else
315             goto not_there;
316 #endif
317         break;
318     case 'B':
319         break;
320     case 'C':
321         break;
322     case 'D':
323         break;
324     case 'E':
325         break;
326     case 'F':
327         break;
328     case 'G':
329         break;
330     case 'H':
331         break;
332     case 'I':
333         if (strEQ(name, "IOV_MAX"))
334 #ifdef IOV_MAX
335             return IOV_MAX;
336 #else
337             goto not_there;
338 #endif
339         if (strEQ(name, "IPPROTO_TCP"))
340 #ifdef IPPROTO_TCP
341             return IPPROTO_TCP;
342 #else
343             goto not_there;
344 #endif
345         break;
346     case 'J':
347         break;
348     case 'K':
349         break;
350     case 'L':
351         break;
352     case 'M':
353         if (strEQ(name, "MSG_BCAST"))
354 #ifdef MSG_BCAST
355             return MSG_BCAST;
356 #else
357             goto not_there;
358 #endif
359         if (strEQ(name, "MSG_CTLFLAGS"))
360 #ifdef MSG_CTLFLAGS
361             return MSG_CTLFLAGS;
362 #else
363             goto not_there;
364 #endif
365         if (strEQ(name, "MSG_CTLIGNORE"))
366 #ifdef MSG_CTLIGNORE
367             return MSG_CTLIGNORE;
368 #else
369             goto not_there;
370 #endif
371         if (strEQ(name, "MSG_CTRUNC"))
372 #if defined(MSG_TRUNC) || defined(HAS_MSG_CTRUNC) /* might be an enum */
373             return MSG_CTRUNC;
374 #else
375             goto not_there;
376 #endif
377         if (strEQ(name, "MSG_DONTROUTE"))
378 #if defined(MSG_DONTROUTE) || defined(HAS_MSG_DONTROUTE) /* might be an enum */
379             return MSG_DONTROUTE;
380 #else
381             goto not_there;
382 #endif
383         if (strEQ(name, "MSG_DONTWAIT"))
384 #ifdef MSG_DONTWAIT
385             return MSG_DONTWAIT;
386 #else
387             goto not_there;
388 #endif
389         if (strEQ(name, "MSG_EOF"))
390 #ifdef MSG_EOF
391             return MSG_EOF;
392 #else
393             goto not_there;
394 #endif
395         if (strEQ(name, "MSG_EOR"))
396 #ifdef MSG_EOR
397             return MSG_EOR;
398 #else
399             goto not_there;
400 #endif
401         if (strEQ(name, "MSG_ERRQUEUE"))
402 #ifdef MSG_ERRQUEUE
403             return MSG_ERRQUEUE;
404 #else
405             goto not_there;
406 #endif
407         if (strEQ(name, "MSG_FIN"))
408 #ifdef MSG_FIN
409             return MSG_FIN;
410 #else
411             goto not_there;
412 #endif
413         if (strEQ(name, "MSG_MAXIOVLEN"))
414 #ifdef MSG_MAXIOVLEN
415             return MSG_MAXIOVLEN;
416 #else
417             goto not_there;
418 #endif
419         if (strEQ(name, "MSG_MCAST"))
420 #ifdef MSG_MCAST
421             return MSG_MCAST;
422 #else
423             goto not_there;
424 #endif
425         if (strEQ(name, "MSG_NOSIGNAL"))
426 #ifdef MSG_NOSIGNAL
427             return MSG_NOSIGNAL;
428 #else
429             goto not_there;
430 #endif
431         if (strEQ(name, "MSG_OOB"))
432 #if defined(MSG_OOB) || defined(HAS_MSG_OOB) /* might be an enum */
433             return MSG_OOB;
434 #else
435             goto not_there;
436 #endif
437         if (strEQ(name, "MSG_PEEK"))
438 #if defined(MSG_PEEK) || defined(HAS_MSG_PEEK) /* might be an enum */
439             return MSG_PEEK;
440 #else
441             goto not_there;
442 #endif
443         if (strEQ(name, "MSG_PROXY"))
444 #if defined(MSG_PROXY) || defined(HAS_MSG_PROXY) /* might be an enum */
445             return MSG_PROXY;
446 #else
447             goto not_there;
448 #endif
449         if (strEQ(name, "MSG_RST"))
450 #ifdef MSG_RST
451             return MSG_RST;
452 #else
453             goto not_there;
454 #endif
455         if (strEQ(name, "MSG_SYN"))
456 #ifdef MSG_SYN
457             return MSG_SYN;
458 #else
459             goto not_there;
460 #endif
461         if (strEQ(name, "MSG_TRUNC"))
462 #ifdef MSG_TRUNC
463             return MSG_TRUNC;
464 #else
465             goto not_there;
466 #endif
467         if (strEQ(name, "MSG_WAITALL"))
468 #ifdef MSG_WAITALL
469             return MSG_WAITALL;
470 #else
471             goto not_there;
472 #endif
473         break;
474     case 'N':
475         break;
476     case 'O':
477         break;
478     case 'P':
479         if (strEQ(name, "PF_802"))
480 #ifdef PF_802
481             return PF_802;
482 #else
483             goto not_there;
484 #endif
485         if (strEQ(name, "PF_APPLETALK"))
486 #ifdef PF_APPLETALK
487             return PF_APPLETALK;
488 #else
489             goto not_there;
490 #endif
491         if (strEQ(name, "PF_CCITT"))
492 #ifdef PF_CCITT
493             return PF_CCITT;
494 #else
495             goto not_there;
496 #endif
497         if (strEQ(name, "PF_CHAOS"))
498 #ifdef PF_CHAOS
499             return PF_CHAOS;
500 #else
501             goto not_there;
502 #endif
503         if (strEQ(name, "PF_DATAKIT"))
504 #ifdef PF_DATAKIT
505             return PF_DATAKIT;
506 #else
507             goto not_there;
508 #endif
509         if (strEQ(name, "PF_DECnet"))
510 #ifdef PF_DECnet
511             return PF_DECnet;
512 #else
513             goto not_there;
514 #endif
515         if (strEQ(name, "PF_DLI"))
516 #ifdef PF_DLI
517             return PF_DLI;
518 #else
519             goto not_there;
520 #endif
521         if (strEQ(name, "PF_ECMA"))
522 #ifdef PF_ECMA
523             return PF_ECMA;
524 #else
525             goto not_there;
526 #endif
527         if (strEQ(name, "PF_GOSIP"))
528 #ifdef PF_GOSIP
529             return PF_GOSIP;
530 #else
531             goto not_there;
532 #endif
533         if (strEQ(name, "PF_HYLINK"))
534 #ifdef PF_HYLINK
535             return PF_HYLINK;
536 #else
537             goto not_there;
538 #endif
539         if (strEQ(name, "PF_IMPLINK"))
540 #ifdef PF_IMPLINK
541             return PF_IMPLINK;
542 #else
543             goto not_there;
544 #endif
545         if (strEQ(name, "PF_INET"))
546 #ifdef PF_INET
547             return PF_INET;
548 #else
549             goto not_there;
550 #endif
551         if (strEQ(name, "PF_LAT"))
552 #ifdef PF_LAT
553             return PF_LAT;
554 #else
555             goto not_there;
556 #endif
557         if (strEQ(name, "PF_MAX"))
558 #ifdef PF_MAX
559             return PF_MAX;
560 #else
561             goto not_there;
562 #endif
563         if (strEQ(name, "PF_NBS"))
564 #ifdef PF_NBS
565             return PF_NBS;
566 #else
567             goto not_there;
568 #endif
569         if (strEQ(name, "PF_NIT"))
570 #ifdef PF_NIT
571             return PF_NIT;
572 #else
573             goto not_there;
574 #endif
575         if (strEQ(name, "PF_NS"))
576 #ifdef PF_NS
577             return PF_NS;
578 #else
579             goto not_there;
580 #endif
581         if (strEQ(name, "PF_OSI"))
582 #ifdef PF_OSI
583             return PF_OSI;
584 #else
585             goto not_there;
586 #endif
587         if (strEQ(name, "PF_OSINET"))
588 #ifdef PF_OSINET
589             return PF_OSINET;
590 #else
591             goto not_there;
592 #endif
593         if (strEQ(name, "PF_PUP"))
594 #ifdef PF_PUP
595             return PF_PUP;
596 #else
597             goto not_there;
598 #endif
599         if (strEQ(name, "PF_SNA"))
600 #ifdef PF_SNA
601             return PF_SNA;
602 #else
603             goto not_there;
604 #endif
605         if (strEQ(name, "PF_UNIX"))
606 #ifdef PF_UNIX
607             return PF_UNIX;
608 #else
609             goto not_there;
610 #endif
611         if (strEQ(name, "PF_UNSPEC"))
612 #ifdef PF_UNSPEC
613             return PF_UNSPEC;
614 #else
615             goto not_there;
616 #endif
617         if (strEQ(name, "PF_X25"))
618 #ifdef PF_X25
619             return PF_X25;
620 #else
621             goto not_there;
622 #endif
623         break;
624     case 'Q':
625         break;
626     case 'R':
627         break;
628     case 'S':
629         if (strEQ(name, "SCM_CONNECT"))
630 #ifdef SCM_CONNECT
631             return SCM_CONNECT;
632 #else
633             goto not_there;
634 #endif
635         if (strEQ(name, "SCM_CREDENTIALS"))
636 #ifdef SCM_CREDENTIALS
637             return SCM_CREDENTIALS;
638 #else
639             goto not_there;
640 #endif
641         if (strEQ(name, "SCM_CREDS"))
642 #ifdef SCM_CREDS
643             return SCM_CREDS;
644 #else
645             goto not_there;
646 #endif
647         if (strEQ(name, "SCM_RIGHTS"))
648 #if defined(SCM_RIGHTS) || defined(HAS_SCM_RIGHTS) /* might be an enum */
649             return SCM_RIGHTS;
650 #else
651             goto not_there;
652 #endif
653         if (strEQ(name, "SCM_TIMESTAMP"))
654 #ifdef SCM_TIMESTAMP
655             return SCM_TIMESTAMP;
656 #else
657             goto not_there;
658 #endif
659         if (strEQ(name, "SOCK_DGRAM"))
660 #ifdef SOCK_DGRAM
661             return SOCK_DGRAM;
662 #else
663             goto not_there;
664 #endif
665         if (strEQ(name, "SOCK_RAW"))
666 #ifdef SOCK_RAW
667             return SOCK_RAW;
668 #else
669             goto not_there;
670 #endif
671         if (strEQ(name, "SOCK_RDM"))
672 #ifdef SOCK_RDM
673             return SOCK_RDM;
674 #else
675             goto not_there;
676 #endif
677         if (strEQ(name, "SOCK_SEQPACKET"))
678 #ifdef SOCK_SEQPACKET
679             return SOCK_SEQPACKET;
680 #else
681             goto not_there;
682 #endif
683         if (strEQ(name, "SOCK_STREAM"))
684 #ifdef SOCK_STREAM
685             return SOCK_STREAM;
686 #else
687             goto not_there;
688 #endif
689         if (strEQ(name, "SOL_SOCKET"))
690 #ifdef SOL_SOCKET
691             return SOL_SOCKET;
692 #else
693             goto not_there;
694 #endif
695         if (strEQ(name, "SOMAXCONN"))
696 #ifdef SOMAXCONN
697             return SOMAXCONN;
698 #else
699             goto not_there;
700 #endif
701         if (strEQ(name, "SO_ACCEPTCONN"))
702 #ifdef SO_ACCEPTCONN
703             return SO_ACCEPTCONN;
704 #else
705             goto not_there;
706 #endif
707         if (strEQ(name, "SO_BROADCAST"))
708 #ifdef SO_BROADCAST
709             return SO_BROADCAST;
710 #else
711             goto not_there;
712 #endif
713         if (strEQ(name, "SO_DEBUG"))
714 #ifdef SO_DEBUG
715             return SO_DEBUG;
716 #else
717             goto not_there;
718 #endif
719         if (strEQ(name, "SO_DONTLINGER"))
720 #ifdef SO_DONTLINGER
721             return SO_DONTLINGER;
722 #else
723             goto not_there;
724 #endif
725         if (strEQ(name, "SO_DONTROUTE"))
726 #ifdef SO_DONTROUTE
727             return SO_DONTROUTE;
728 #else
729             goto not_there;
730 #endif
731         if (strEQ(name, "SO_ERROR"))
732 #ifdef SO_ERROR
733             return SO_ERROR;
734 #else
735             goto not_there;
736 #endif
737         if (strEQ(name, "SO_KEEPALIVE"))
738 #ifdef SO_KEEPALIVE
739             return SO_KEEPALIVE;
740 #else
741             goto not_there;
742 #endif
743         if (strEQ(name, "SO_LINGER"))
744 #ifdef SO_LINGER
745             return SO_LINGER;
746 #else
747             goto not_there;
748 #endif
749         if (strEQ(name, "SO_OOBINLINE"))
750 #ifdef SO_OOBINLINE
751             return SO_OOBINLINE;
752 #else
753             goto not_there;
754 #endif
755         if (strEQ(name, "SO_RCVBUF"))
756 #ifdef SO_RCVBUF
757             return SO_RCVBUF;
758 #else
759             goto not_there;
760 #endif
761         if (strEQ(name, "SO_RCVLOWAT"))
762 #ifdef SO_RCVLOWAT
763             return SO_RCVLOWAT;
764 #else
765             goto not_there;
766 #endif
767         if (strEQ(name, "SO_RCVTIMEO"))
768 #ifdef SO_RCVTIMEO
769             return SO_RCVTIMEO;
770 #else
771             goto not_there;
772 #endif
773         if (strEQ(name, "SO_REUSEADDR"))
774 #ifdef SO_REUSEADDR
775             return SO_REUSEADDR;
776 #else
777             goto not_there;
778 #endif
779         if (strEQ(name, "SO_REUSEPORT"))
780 #ifdef SO_REUSEPORT
781             return SO_REUSEPORT;
782 #else
783             goto not_there;
784 #endif
785         if (strEQ(name, "SO_SNDBUF"))
786 #ifdef SO_SNDBUF
787             return SO_SNDBUF;
788 #else
789             goto not_there;
790 #endif
791         if (strEQ(name, "SO_SNDLOWAT"))
792 #ifdef SO_SNDLOWAT
793             return SO_SNDLOWAT;
794 #else
795             goto not_there;
796 #endif
797         if (strEQ(name, "SO_SNDTIMEO"))
798 #ifdef SO_SNDTIMEO
799             return SO_SNDTIMEO;
800 #else
801             goto not_there;
802 #endif
803         if (strEQ(name, "SO_TYPE"))
804 #ifdef SO_TYPE
805             return SO_TYPE;
806 #else
807             goto not_there;
808 #endif
809         if (strEQ(name, "SO_USELOOPBACK"))
810 #ifdef SO_USELOOPBACK
811             return SO_USELOOPBACK;
812 #else
813             goto not_there;
814 #endif
815         break;
816     case 'T':
817         if (strEQ(name, "TCP_KEEPALIVE"))
818 #ifdef TCP_KEEPALIVE
819             return TCP_KEEPALIVE;
820 #else
821             goto not_there;
822 #endif
823         if (strEQ(name, "TCP_MAXRT"))
824 #ifdef TCP_MAXRT
825             return TCP_MAXRT;
826 #else
827             goto not_there;
828 #endif
829         if (strEQ(name, "TCP_MAXSEG"))
830 #ifdef TCP_MAXSEG
831             return TCP_MAXSEG;
832 #else
833             goto not_there;
834 #endif
835         if (strEQ(name, "TCP_NODELAY"))
836 #ifdef TCP_NODELAY
837             return TCP_NODELAY;
838 #else
839             goto not_there;
840 #endif
841         if (strEQ(name, "TCP_STDURG"))
842 #ifdef TCP_STDURG
843             return TCP_STDURG;
844 #else
845             goto not_there;
846 #endif
847         break;
848     case 'U':
849         if (strEQ(name, "UIO_MAXIOV"))
850 #ifdef UIO_MAXIOV
851             return UIO_MAXIOV;
852 #else
853             goto not_there;
854 #endif
855         break;
856     case 'V':
857         break;
858     case 'W':
859         break;
860     case 'X':
861         break;
862     case 'Y':
863         break;
864     case 'Z':
865         break;
866     }
867     errno = EINVAL;
868     return 0;
869
870 not_there:
871     errno = ENOENT;
872     return 0;
873 }
874
875
876 MODULE = Socket         PACKAGE = Socket
877
878 double
879 constant(name,arg)
880         char *          name
881         int             arg
882
883
884 void
885 inet_aton(host)
886         char *  host
887         CODE:
888         {
889         struct in_addr ip_address;
890         struct hostent * phe;
891         int ok = inet_aton(host, &ip_address);
892
893         if (!ok && (phe = gethostbyname(host))) {
894                 Copy( phe->h_addr, &ip_address, phe->h_length, char );
895                 ok = 1;
896         }
897
898         ST(0) = sv_newmortal();
899         if (ok) {
900                 sv_setpvn( ST(0), (char *)&ip_address, sizeof ip_address );
901         }
902         }
903
904 void
905 inet_ntoa(ip_address_sv)
906         SV *    ip_address_sv
907         CODE:
908         {
909         STRLEN addrlen;
910         struct in_addr addr;
911         char * addr_str;
912         char * ip_address = SvPV(ip_address_sv,addrlen);
913         if (addrlen != sizeof(addr)) {
914             croak("Bad arg length for %s, length is %d, should be %d",
915                         "Socket::inet_ntoa",
916                         addrlen, sizeof(addr));
917         }
918
919         Copy( ip_address, &addr, sizeof addr, char );
920         addr_str = inet_ntoa(addr);
921
922         ST(0) = sv_2mortal(newSVpvn(addr_str, strlen(addr_str)));
923         }
924
925 void
926 pack_sockaddr_un(pathname)
927         char *  pathname
928         CODE:
929         {
930 #ifdef I_SYS_UN
931         struct sockaddr_un sun_ad; /* fear using sun */
932         STRLEN len;
933         Zero( &sun_ad, sizeof sun_ad, char );
934         sun_ad.sun_family = AF_UNIX;
935         len = strlen(pathname);
936         if (len > sizeof(sun_ad.sun_path))
937             len = sizeof(sun_ad.sun_path);
938         Copy( pathname, sun_ad.sun_path, len, char );
939         ST(0) = sv_2mortal(newSVpvn((char *)&sun_ad, sizeof sun_ad));
940 #else
941         ST(0) = (SV *) not_here("pack_sockaddr_un");
942 #endif
943         
944         }
945
946 void
947 unpack_sockaddr_un(sun_sv)
948         SV *    sun_sv
949         CODE:
950         {
951 #ifdef I_SYS_UN
952         struct sockaddr_un addr;
953         STRLEN sockaddrlen;
954         char * sun_ad = SvPV(sun_sv,sockaddrlen);
955         char * e;
956
957         if (sockaddrlen != sizeof(addr)) {
958             croak("Bad arg length for %s, length is %d, should be %d",
959                         "Socket::unpack_sockaddr_un",
960                         sockaddrlen, sizeof(addr));
961         }
962
963         Copy( sun_ad, &addr, sizeof addr, char );
964
965         if ( addr.sun_family != AF_UNIX ) {
966             croak("Bad address family for %s, got %d, should be %d",
967                         "Socket::unpack_sockaddr_un",
968                         addr.sun_family,
969                         AF_UNIX);
970         }
971         e = addr.sun_path;
972         while (*e && e < addr.sun_path + sizeof addr.sun_path)
973             ++e;
974         ST(0) = sv_2mortal(newSVpvn(addr.sun_path, e - addr.sun_path));
975 #else
976         ST(0) = (SV *) not_here("unpack_sockaddr_un");
977 #endif
978         }
979
980 void
981 pack_sockaddr_in(port,ip_address)
982         unsigned short  port
983         char *  ip_address
984         CODE:
985         {
986         struct sockaddr_in sin;
987
988         Zero( &sin, sizeof sin, char );
989         sin.sin_family = AF_INET;
990         sin.sin_port = htons(port);
991         Copy( ip_address, &sin.sin_addr, sizeof sin.sin_addr, char );
992
993         ST(0) = sv_2mortal(newSVpvn((char *)&sin, sizeof sin));
994         }
995
996 void
997 unpack_sockaddr_in(sin_sv)
998         SV *    sin_sv
999         PPCODE:
1000         {
1001         STRLEN sockaddrlen;
1002         struct sockaddr_in addr;
1003         unsigned short  port;
1004         struct in_addr  ip_address;
1005         char *  sin = SvPV(sin_sv,sockaddrlen);
1006         if (sockaddrlen != sizeof(addr)) {
1007             croak("Bad arg length for %s, length is %d, should be %d",
1008                         "Socket::unpack_sockaddr_in",
1009                         sockaddrlen, sizeof(addr));
1010         }
1011         Copy( sin, &addr,sizeof addr, char );
1012         if ( addr.sin_family != AF_INET ) {
1013             croak("Bad address family for %s, got %d, should be %d",
1014                         "Socket::unpack_sockaddr_in",
1015                         addr.sin_family,
1016                         AF_INET);
1017         } 
1018         port = ntohs(addr.sin_port);
1019         ip_address = addr.sin_addr;
1020
1021         EXTEND(SP, 2);
1022         PUSHs(sv_2mortal(newSViv((IV) port)));
1023         PUSHs(sv_2mortal(newSVpvn((char *)&ip_address,sizeof ip_address)));
1024         }
1025
1026 void
1027 INADDR_ANY()
1028         CODE:
1029         {
1030         struct in_addr  ip_address;
1031         ip_address.s_addr = htonl(INADDR_ANY);
1032         ST(0) = sv_2mortal(newSVpvn((char *)&ip_address,sizeof ip_address ));
1033         }
1034
1035 void
1036 INADDR_LOOPBACK()
1037         CODE:
1038         {
1039         struct in_addr  ip_address;
1040         ip_address.s_addr = htonl(INADDR_LOOPBACK);
1041         ST(0) = sv_2mortal(newSVpvn((char *)&ip_address,sizeof ip_address));
1042         }
1043
1044 void
1045 INADDR_NONE()
1046         CODE:
1047         {
1048         struct in_addr  ip_address;
1049         ip_address.s_addr = htonl(INADDR_NONE);
1050         ST(0) = sv_2mortal(newSVpvn((char *)&ip_address,sizeof ip_address));
1051         }
1052
1053 void
1054 INADDR_BROADCAST()
1055         CODE:
1056         {
1057         struct in_addr  ip_address;
1058         ip_address.s_addr = htonl(INADDR_BROADCAST);
1059         ST(0) = sv_2mortal(newSVpvn((char *)&ip_address,sizeof ip_address));
1060         }