* io.c (rb_open_file): encoding in mode string was ignored if perm is
[ruby-svn.git] / ext / socket / extconf.rb
blob35ed282e17b3b9a32239821dbc456abf5ddf08c5
1 require 'mkmf'
3 case RUBY_PLATFORM
4 when /(ms|bcc)win32|mingw/
5   test_func = "WSACleanup"
6   have_library("ws2_32", "WSACleanup")
7 when /cygwin/
8   test_func = "socket"
9 when /beos/
10   test_func = "socket"
11   have_library("net", "socket")
12 when /haiku/
13   test_func = "socket"
14   have_library("network", "socket")
15 when /i386-os2_emx/
16   test_func = "socket"
17   have_library("socket", "socket")
18 else
19   test_func = "socket"
20   have_library("nsl", "t_open")
21   have_library("socket", "socket")
22 end
24 unless $mswin or $bccwin or $mingw
25   headers = %w<sys/types.h netdb.h string.h sys/socket.h netinet/in.h>
26 end
27 if /solaris/ =~ RUBY_PLATFORM and !try_compile("")
28   # bug of gcc 3.0 on Solaris 8 ?
29   headers << "sys/feature_tests.h"
30 end
31 if have_header("arpa/inet.h")
32   headers << "arpa/inet.h"
33 end
35 ipv6 = false
36 default_ipv6 = /cygwin|beos|haiku/ !~ RUBY_PLATFORM
37 if enable_config("ipv6", default_ipv6)
38   if checking_for("ipv6") {try_link(<<EOF)}
39 #include <sys/types.h>
40 #include <sys/socket.h>
41 int
42 main()
44   socket(AF_INET6, SOCK_STREAM, 0);
46 EOF
47     $defs << "-DENABLE_IPV6" << "-DINET6"
48     ipv6 = true
49   end
50 end
52 if ipv6
53   ipv6lib = nil
54   class << (fmt = "unknown")
55     def %(s) s || self end
56   end
57   idirs, ldirs = dir_config("inet6", %w[/usr/inet6 /usr/local/v6].find {|d| File.directory?(d)})
58   checking_for("ipv6 type", fmt) do
59     if have_macro("IPV6_INRIA_VERSION", "netinet/in.h")
60       "inria"
61     elsif have_macro("__KAME__", "netinet/in.h")
62       have_library(ipv6lib = "inet6")
63       "kame"
64     elsif have_macro("_TOSHIBA_INET6", "sys/param.h")
65       have_library(ipv6lib = "inet6") and "toshiba"
66     elsif have_macro("__V6D__", "sys/v6config.h")
67       have_library(ipv6lib = "v6") and "v6d"
68     elsif have_macro("_ZETA_MINAMI_INET6", "sys/param.h")
69       have_library(ipv6lib = "inet6") and "zeta"
70     elsif ipv6lib = with_config("ipv6-lib")
71       warn <<EOS
72 --with-ipv6-lib and --with-ipv6-libdir option will be obsolete, use
73 --with-inet6lib and --with-inet6-{include,lib} options instead.
74 EOS
75       find_library(ipv6lib, nil, with_config("ipv6-libdir", ldirs)) and
76         ipv6lib
77     elsif have_library("inet6")
78       "inet6"
79     end
80   end or not ipv6lib or abort <<EOS
82 Fatal: no #{ipv6lib} library found.  cannot continue.
83 You need to fetch lib#{ipv6lib}.a from appropriate
84 ipv6 kit and compile beforehand.
85 EOS
86 end
88 if have_struct_member("struct sockaddr_in", "sin_len", headers)
89   $defs[-1] = "-DHAVE_SIN_LEN"
90 end
92 #   doug's fix, NOW add -Dss_family... only if required!
93 doug = proc {have_struct_member("struct sockaddr_storage", "ss_family", headers)}
94 if (doug[] or
95     with_cppflags($CPPFLAGS + " -Dss_family=__ss_family -Dss_len=__ss_len", &doug))
96   $defs[-1] = "-DHAVE_SOCKADDR_STORAGE"
97 end
99 if have_struct_member("struct sockaddr", "sa_len", headers)
100   $defs[-1] = "-DHAVE_SA_LEN "
103 have_header("netinet/tcp.h") if not /cygwin/ =~ RUBY_PLATFORM # for cygwin 1.1.5
104 have_header("netinet/udp.h")
106 if have_func("sendmsg") | have_func("recvmsg")
107   have_struct_member('struct msghdr', 'msg_control', ['sys/types.h', 'sys/socket.h'])
108   have_struct_member('struct msghdr', 'msg_accrights', ['sys/types.h', 'sys/socket.h'])
111 getaddr_info_ok = enable_config("wide-getaddrinfo") do
112   checking_for("wide getaddrinfo") {try_run(<<EOF)}
113 #{cpp_include(headers)}
114 #include <stdlib.h>
116 #ifndef EXIT_SUCCESS
117 #define EXIT_SUCCESS 0
118 #endif
119 #ifndef EXIT_FAILURE
120 #define EXIT_FAILURE 1
121 #endif
123 #ifndef AF_LOCAL
124 #define AF_LOCAL AF_UNIX
125 #endif
128 main()
130   int passive, gaierr, inet4 = 0, inet6 = 0;
131   struct addrinfo hints, *ai, *aitop;
132   char straddr[INET6_ADDRSTRLEN], strport[16];
133 #ifdef _WIN32
134   WSADATA retdata;
136   WSAStartup(MAKEWORD(2, 0), &retdata);
137 #endif
139   for (passive = 0; passive <= 1; passive++) {
140     memset(&hints, 0, sizeof(hints));
141     hints.ai_family = AF_UNSPEC;
142     hints.ai_protocol = IPPROTO_TCP;
143     hints.ai_flags = passive ? AI_PASSIVE : 0;
144     hints.ai_socktype = SOCK_STREAM;
145     if ((gaierr = getaddrinfo(NULL, "54321", &hints, &aitop)) != 0) {
146       (void)gai_strerror(gaierr);
147       goto bad;
148     }
149     for (ai = aitop; ai; ai = ai->ai_next) {
150       if (ai->ai_family == AF_LOCAL) continue;
151       if (ai->ai_addr == NULL)
152         goto bad;
153 #if defined(_AIX)
154       if (ai->ai_family == AF_INET6 && passive) {
155         inet6++;
156         continue;
157       }
158       ai->ai_addr->sa_len = ai->ai_addrlen;
159       ai->ai_addr->sa_family = ai->ai_family;
160 #endif
161       if (ai->ai_addrlen == 0 ||
162           getnameinfo(ai->ai_addr, ai->ai_addrlen,
163                       straddr, sizeof(straddr), strport, sizeof(strport),
164                       NI_NUMERICHOST|NI_NUMERICSERV) != 0) {
165         goto bad;
166       }
167       if (strcmp(strport, "54321") != 0) {
168         goto bad;
169       }
170       switch (ai->ai_family) {
171       case AF_INET:
172         if (passive) {
173           if (strcmp(straddr, "0.0.0.0") != 0) {
174             goto bad;
175           }
176         } else {
177           if (strcmp(straddr, "127.0.0.1") != 0) {
178             goto bad;
179           }
180         }
181         inet4++;
182         break;
183       case AF_INET6:
184         if (passive) {
185           if (strcmp(straddr, "::") != 0) {
186             goto bad;
187           }
188         } else {
189           if (strcmp(straddr, "::1") != 0) {
190             goto bad;
191           }
192         }
193         inet6++;
194         break;
195       case AF_UNSPEC:
196         goto bad;
197         break;
198       default:
199         /* another family support? */
200         break;
201       }
202     }
203   }
205   if (!(inet4 == 0 || inet4 == 2))
206     goto bad;
207   if (!(inet6 == 0 || inet6 == 2))
208     goto bad;
210   if (aitop)
211     freeaddrinfo(aitop);
212   exit(EXIT_SUCCESS);
214  bad:
215   if (aitop)
216     freeaddrinfo(aitop);
217   exit(EXIT_FAILURE);
221 if ipv6 and not getaddr_info_ok
222   abort <<EOS
224 Fatal: --enable-ipv6 is specified, and your OS seems to support IPv6 feature.
225 But your getaddrinfo() and getnameinfo() are appeared to be broken.  Sorry,
226 you cannot compile IPv6 socket classes with broken these functions.
227 You can try --enable-wide-getaddrinfo.
231 case with_config("lookup-order-hack", "UNSPEC")
232 when "INET"
233   $defs << "-DLOOKUP_ORDER_HACK_INET"
234 when "INET6"
235   $defs << "-DLOOKUP_ORDER_HACK_INET6"
236 when "UNSPEC"
237   # nothing special
238 else
239   abort <<EOS
241 Fatal: invalid value for --with-lookup-order-hack (expected INET, INET6 or UNSPEC)
245 $objs = ["socket.#{$OBJEXT}"]
247 unless getaddr_info_ok and have_func("getnameinfo", "netdb.h") and have_func("getaddrinfo", "netdb.h")
248   if have_struct_member("struct in6_addr", "s6_addr8", headers)
249     $defs[-1] = "-DHAVE_ADDR8"
250   end
251   $CPPFLAGS="-I. "+$CPPFLAGS
252   $objs += ["getaddrinfo.#{$OBJEXT}"]
253   $objs += ["getnameinfo.#{$OBJEXT}"]
254   have_func("inet_ntop") or have_func("inet_ntoa")
255   have_func("inet_pton") or have_func("inet_aton")
256   have_func("getservbyport")
257   have_header("arpa/nameser.h")
258   have_header("resolv.h")
261 unless have_type("socklen_t", headers)
262   $defs << "-Dsocklen_t=int"
265 have_header("sys/un.h")
266 have_header("sys/uio.h")
268 $distcleanfiles << "constants.h"
270 if have_func(test_func)
271   have_func("hsterror")
272   have_func("getipnodebyname") or have_func("gethostbyname2")
273   have_func("socketpair")
274   unless have_func("gethostname")
275     have_func("uname")
276   end
277   if enable_config("socks", ENV["SOCKS_SERVER"])
278     if have_library("socks5", "SOCKSinit")
279       $defs << "-DSOCKS5" << "-DSOCKS"
280     elsif have_library("socks", "Rconnect")
281       $defs << "-DSOCKS"
282     end
283   end
284   create_makefile("socket")