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