* gcc.dg/guality/guality.exp: Skip on AIX.
[official-gcc.git] / gcc / ada / socket.c
blob18999b394ea5504b46a926b1fe9fed733ee04736
1 /****************************************************************************
2 * *
3 * GNAT COMPILER COMPONENTS *
4 * *
5 * S O C K E T *
6 * *
7 * C Implementation File *
8 * *
9 * Copyright (C) 2003-2012, Free Software Foundation, Inc. *
10 * *
11 * GNAT is free software; you can redistribute it and/or modify it under *
12 * terms of the GNU General Public License as published by the Free Soft- *
13 * ware Foundation; either version 3, or (at your option) any later ver- *
14 * sion. GNAT is distributed in the hope that it will be useful, but WITH- *
15 * OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY *
16 * or FITNESS FOR A PARTICULAR PURPOSE. *
17 * *
18 * As a special exception under Section 7 of GPL version 3, you are granted *
19 * additional permissions described in the GCC Runtime Library Exception, *
20 * version 3.1, as published by the Free Software Foundation. *
21 * *
22 * You should have received a copy of the GNU General Public License and *
23 * a copy of the GCC Runtime Library Exception along with this program; *
24 * see the files COPYING3 and COPYING.RUNTIME respectively. If not, see *
25 * <http://www.gnu.org/licenses/>. *
26 * *
27 * GNAT was originally developed by the GNAT team at New York University. *
28 * Extensive contributions were provided by Ada Core Technologies Inc. *
29 * *
30 ****************************************************************************/
32 /* This file provides a portable binding to the sockets API */
34 #include "gsocket.h"
36 #if defined(VMS)
38 * For VMS, gsocket.h can't include sockets-related DEC C header files
39 * when building the runtime (because these files are in a DEC C text library
40 * (DECC$RTLDEF.TLB) not accessible to GCC). So, we generate a separate header
41 * file along with s-oscons.ads and include it here.
43 # include "s-oscons.h"
46 * We also need the declaration of struct hostent/servent, which s-oscons
47 * can't provide, so we copy it manually here. This needs to be kept in synch
48 * with the definition of that structure in the DEC C headers, which
49 * hopefully won't change frequently.
51 typedef char *__netdb_char_ptr __attribute__ (( mode (SI) ));
52 typedef __netdb_char_ptr *__netdb_char_ptr_ptr __attribute__ (( mode (SI) ));
54 struct hostent {
55 __netdb_char_ptr h_name;
56 __netdb_char_ptr_ptr h_aliases;
57 int h_addrtype;
58 int h_length;
59 __netdb_char_ptr_ptr h_addr_list;
62 struct servent {
63 __netdb_char_ptr s_name;
64 __netdb_char_ptr_ptr s_aliases;
65 int s_port;
66 __netdb_char_ptr s_proto;
68 #elif defined(__FreeBSD__)
69 typedef unsigned int IOCTL_Req_T;
70 #else
71 typedef int IOCTL_Req_T;
72 #endif
74 #if defined(HAVE_SOCKETS)
76 /* Include all the necessary system-specific headers and define the
77 * necessary macros (shared with gen-oscons).
80 #if !defined(SO_NOSIGPIPE) && !defined (MSG_NOSIGNAL)
81 #include <signal.h>
82 #endif
83 /* Required if we will be calling signal() in __gnat_disable_all_sigpipes() */
85 #include "raise.h"
86 /* Required for __gnat_malloc() */
88 #include <string.h>
89 /* Required for memcpy() */
91 extern void __gnat_disable_sigpipe (int fd);
92 extern void __gnat_disable_all_sigpipes (void);
93 extern int __gnat_create_signalling_fds (int *fds);
94 extern int __gnat_read_signalling_fd (int rsig);
95 extern int __gnat_write_signalling_fd (int wsig);
96 extern void __gnat_close_signalling_fd (int sig);
97 extern void __gnat_last_socket_in_set (fd_set *, int *);
98 extern void __gnat_get_socket_from_set (fd_set *, int *, int *);
99 extern void __gnat_insert_socket_in_set (fd_set *, int);
100 extern int __gnat_is_socket_in_set (fd_set *, int);
101 extern fd_set *__gnat_new_socket_set (fd_set *);
102 extern void __gnat_remove_socket_from_set (fd_set *, int);
103 extern void __gnat_reset_socket_set (fd_set *);
104 extern int __gnat_get_h_errno (void);
105 extern int __gnat_socket_ioctl (int, IOCTL_Req_T, int *);
107 extern char * __gnat_servent_s_name (struct servent *);
108 extern char * __gnat_servent_s_alias (struct servent *, int index);
109 extern unsigned short __gnat_servent_s_port (struct servent *);
110 extern char * __gnat_servent_s_proto (struct servent *);
112 extern char * __gnat_hostent_h_name (struct hostent *);
113 extern char * __gnat_hostent_h_alias (struct hostent *, int);
114 extern int __gnat_hostent_h_addrtype (struct hostent *);
115 extern int __gnat_hostent_h_length (struct hostent *);
116 extern char * __gnat_hostent_h_addr (struct hostent *, int);
118 #ifndef HAVE_INET_PTON
119 extern int __gnat_inet_pton (int, const char *, void *);
120 #endif
122 /* Disable the sending of SIGPIPE for writes on a broken stream */
124 void
125 __gnat_disable_sigpipe (int fd)
127 #ifdef SO_NOSIGPIPE
128 int val = 1;
129 (void) setsockopt (fd, SOL_SOCKET, SO_NOSIGPIPE, &val, sizeof val);
130 #endif
133 void
134 __gnat_disable_all_sigpipes (void)
136 #if !defined(SO_NOSIGPIPE) && !defined(MSG_NOSIGNAL) && defined(SIGPIPE)
137 (void) signal (SIGPIPE, SIG_IGN);
138 #endif
141 #if defined (_WIN32) || defined (__vxworks) || defined (VMS)
143 * Signalling FDs operations are implemented in Ada for these platforms
144 * (see subunit GNAT.Sockets.Thin.Signalling_Fds).
146 #else
148 * Create a pair of connected file descriptors fds[0] and fds[1] used for
149 * signalling by a Selector object. fds[0] is the read end, and fds[1] the
150 * write end.
153 __gnat_create_signalling_fds (int *fds) {
154 return pipe (fds);
158 * Read one byte of data from rsig, the read end of a pair of signalling fds
159 * created by __gnat_create_signalling_fds.
162 __gnat_read_signalling_fd (int rsig) {
163 char c;
164 return read (rsig, &c, 1);
168 * Write one byte of data to wsig, the write end of a pair of signalling fds
169 * created by __gnat_create_signalling_fds.
172 __gnat_write_signalling_fd (int wsig) {
173 char c = 0;
174 return write (wsig, &c, 1);
178 * Close one end of a pair of signalling fds
180 void
181 __gnat_close_signalling_fd (int sig) {
182 (void) close (sig);
184 #endif
187 * Handling of gethostbyname, gethostbyaddr, getservbyname and getservbyport
188 * =========================================================================
190 * This module exposes __gnat_getXXXbyYYY operations with the same signature
191 * as the reentrant variant getXXXbyYYY_r.
193 * On platforms where getXXXbyYYY is intrinsically reentrant, the provided user
194 * buffer argument is ignored.
196 * When getXXXbyYYY is not reentrant but getXXXbyYYY_r exists, the latter is
197 * used, and the provided buffer argument must point to a valid, thread-local
198 * buffer (usually on the caller's stack).
200 * When getXXXbyYYY is not reentrant and no reentrant getXXXbyYYY_r variant
201 * is available, the non-reentrant getXXXbyYYY is called, the provided user
202 * buffer is ignored, and the caller is expected to take care of mutual
203 * exclusion.
206 #ifdef HAVE_GETxxxBYyyy_R
208 __gnat_gethostbyname (const char *name,
209 struct hostent *ret, char *buf, size_t buflen,
210 int *h_errnop)
212 struct hostent *rh;
213 int ri;
215 #if defined(__linux__) || defined(__GLIBC__)
216 (void) gethostbyname_r (name, ret, buf, buflen, &rh, h_errnop);
217 #else
218 rh = gethostbyname_r (name, ret, buf, buflen, h_errnop);
219 #endif
220 ri = (rh == NULL) ? -1 : 0;
221 return ri;
225 __gnat_gethostbyaddr (const char *addr, int len, int type,
226 struct hostent *ret, char *buf, size_t buflen,
227 int *h_errnop)
229 struct hostent *rh;
230 int ri;
232 #if defined(__linux__) || defined(__GLIBC__)
233 (void) gethostbyaddr_r (addr, len, type, ret, buf, buflen, &rh, h_errnop);
234 #else
235 rh = gethostbyaddr_r (addr, len, type, ret, buf, buflen, h_errnop);
236 #endif
237 ri = (rh == NULL) ? -1 : 0;
238 return ri;
242 __gnat_getservbyname (const char *name, const char *proto,
243 struct servent *ret, char *buf, size_t buflen)
245 struct servent *rh;
246 int ri;
248 #if defined(__linux__) || defined(__GLIBC__) || defined(__rtems__)
249 (void) getservbyname_r (name, proto, ret, buf, buflen, &rh);
250 #else
251 rh = getservbyname_r (name, proto, ret, buf, buflen);
252 #endif
253 ri = (rh == NULL) ? -1 : 0;
254 return ri;
258 __gnat_getservbyport (int port, const char *proto,
259 struct servent *ret, char *buf, size_t buflen)
261 struct servent *rh;
262 int ri;
264 #if defined(__linux__) || defined(__GLIBC__) || defined(__rtems__)
265 (void) getservbyport_r (port, proto, ret, buf, buflen, &rh);
266 #else
267 rh = getservbyport_r (port, proto, ret, buf, buflen);
268 #endif
269 ri = (rh == NULL) ? -1 : 0;
270 return ri;
272 #elif defined (__vxworks)
273 static char vxw_h_name[MAXHOSTNAMELEN + 1];
274 static char *vxw_h_aliases[1] = { NULL };
275 static int vxw_h_addr;
276 static char *vxw_h_addr_list[2] = { (char*) &vxw_h_addr, NULL };
279 __gnat_gethostbyname (const char *name,
280 struct hostent *ret, char *buf, size_t buflen,
281 int *h_errnop)
283 vxw_h_addr = hostGetByName (name);
284 if (vxw_h_addr == ERROR) {
285 *h_errnop = __gnat_get_h_errno ();
286 return -1;
288 ret->h_name = name;
289 ret->h_aliases = &vxw_h_aliases;
290 ret->h_addrtype = AF_INET;
291 ret->h_length = 4;
292 ret->h_addr_list = &vxw_h_addr_list;
293 return 0;
297 __gnat_gethostbyaddr (const char *addr, int len, int type,
298 struct hostent *ret, char *buf, size_t buflen,
299 int *h_errnop)
301 if (type != AF_INET) {
302 *h_errnop = EAFNOSUPPORT;
303 return -1;
306 if (addr == NULL || len != 4) {
307 *h_errnop = EINVAL;
308 return -1;
311 if (hostGetByAddr (*(int*)addr, &vxw_h_name) != OK) {
312 *h_errnop = __gnat_get_h_errno ();
313 return -1;
316 vxw_h_addr = addr;
318 ret->h_name = &vxw_h_name;
319 ret->h_aliases = &vxw_h_aliases;
320 ret->h_addrtype = AF_INET;
321 ret->h_length = 4;
322 ret->h_addr_list = &vxw_h_addr_list;
326 __gnat_getservbyname (const char *name, const char *proto,
327 struct servent *ret, char *buf, size_t buflen)
329 /* Not available under VxWorks */
330 return -1;
334 __gnat_getservbyport (int port, const char *proto,
335 struct servent *ret, char *buf, size_t buflen)
337 /* Not available under VxWorks */
338 return -1;
340 #else
342 __gnat_gethostbyname (const char *name,
343 struct hostent *ret, char *buf, size_t buflen,
344 int *h_errnop)
346 struct hostent *rh;
347 rh = gethostbyname (name);
348 if (rh == NULL) {
349 *h_errnop = __gnat_get_h_errno ();
350 return -1;
352 *ret = *rh;
353 *h_errnop = 0;
354 return 0;
358 __gnat_gethostbyaddr (const char *addr, int len, int type,
359 struct hostent *ret, char *buf, size_t buflen,
360 int *h_errnop)
362 struct hostent *rh;
363 rh = gethostbyaddr (addr, len, type);
364 if (rh == NULL) {
365 *h_errnop = __gnat_get_h_errno ();
366 return -1;
368 *ret = *rh;
369 *h_errnop = 0;
370 return 0;
374 __gnat_getservbyname (const char *name, const char *proto,
375 struct servent *ret, char *buf, size_t buflen)
377 struct servent *rh;
378 rh = getservbyname (name, proto);
379 if (rh == NULL)
380 return -1;
381 *ret = *rh;
382 return 0;
386 __gnat_getservbyport (int port, const char *proto,
387 struct servent *ret, char *buf, size_t buflen)
389 struct servent *rh;
390 rh = getservbyport (port, proto);
391 if (rh == NULL)
392 return -1;
393 *ret = *rh;
394 return 0;
396 #endif
398 /* Find the largest socket in the socket set SET. This is needed for
399 `select'. LAST is the maximum value for the largest socket. This hint is
400 used to avoid scanning very large socket sets. On return, LAST is the
401 actual largest socket in the socket set. */
403 void
404 __gnat_last_socket_in_set (fd_set *set, int *last)
406 int s;
407 int l;
408 l = -1;
410 #ifdef _WIN32
411 /* More efficient method for NT. */
412 for (s = 0; s < set->fd_count; s++)
413 if ((int) set->fd_array[s] > l)
414 l = set->fd_array[s];
416 #else
418 for (s = *last; s != -1; s--)
419 if (FD_ISSET (s, set))
421 l = s;
422 break;
424 #endif
426 *last = l;
429 /* Get last socket and remove it from the socket set SET. LAST is the
430 maximum value of the largest socket. This hint is used to avoid scanning
431 very large socket sets. On return, LAST is set to the actual largest
432 socket in the socket set. */
434 void
435 __gnat_get_socket_from_set (fd_set *set, int *last, int *socket)
437 *socket = *last;
438 FD_CLR (*socket, set);
439 __gnat_last_socket_in_set (set, last);
442 /* Insert SOCKET in the socket set SET. */
444 void
445 __gnat_insert_socket_in_set (fd_set *set, int socket)
447 FD_SET (socket, set);
450 /* Check whether a given SOCKET is in the socket set SET. */
453 __gnat_is_socket_in_set (fd_set *set, int socket)
455 return FD_ISSET (socket, set);
458 /* Remove SOCKET from the socket set SET. */
460 void
461 __gnat_remove_socket_from_set (fd_set *set, int socket)
463 FD_CLR (socket, set);
466 /* Reset SET */
467 void
468 __gnat_reset_socket_set (fd_set *set)
470 FD_ZERO (set);
473 /* Get the value of the last host error */
476 __gnat_get_h_errno (void) {
477 #ifdef __vxworks
478 int vxw_errno = errno;
480 switch (vxw_errno) {
481 case 0:
482 return 0;
484 #ifdef S_hostLib_HOST_NOT_FOUND
485 case S_hostLib_HOST_NOT_FOUND:
486 #endif
487 case S_hostLib_UNKNOWN_HOST:
488 return HOST_NOT_FOUND;
490 #ifdef S_hostLib_TRY_AGAIN
491 case S_hostLib_TRY_AGAIN:
492 return TRY_AGAIN;
493 #endif
495 #ifdef S_hostLib_NO_RECOVERY
496 case S_hostLib_NO_RECOVERY:
497 #endif
498 #ifdef S_hostLib_NETDB_INTERNAL
499 case S_hostLib_NETDB_INTERNAL:
500 #endif
501 case S_hostLib_INVALID_PARAMETER:
502 return NO_RECOVERY;
504 default:
505 return -1;
508 #elif defined (VMS)
509 /* h_errno is defined as follows in OpenVMS' version of <netdb.h>.
510 * However this header file is not available when building the GNAT
511 * runtime library using GCC, so we are hardcoding the definition
512 * directly. Note that the returned address is thread-specific.
514 extern int *decc$h_errno_get_addr ();
515 return *decc$h_errno_get_addr ();
517 #elif defined (__rtems__)
518 /* At this stage in the tool build, no networking .h files are available.
519 * Newlib does not provide networking .h files and RTEMS is not built yet.
520 * So we need to explicitly extern h_errno to access it.
522 extern int h_errno;
523 return h_errno;
525 #else
526 return h_errno;
527 #endif
530 /* Wrapper for ioctl(2), which is a variadic function */
533 __gnat_socket_ioctl (int fd, IOCTL_Req_T req, int *arg) {
534 #if defined (_WIN32)
535 return ioctlsocket (fd, req, arg);
536 #elif defined (__APPLE__)
538 * On Darwin, req is an unsigned long, and we want to convert without sign
539 * extension to get the proper bit pattern in the case of a 64 bit kernel.
541 return ioctl (fd, (unsigned int) req, arg);
542 #else
543 return ioctl (fd, req, arg);
544 #endif
547 #ifndef HAVE_INET_PTON
549 #ifdef VMS
550 # define in_addr_t int
551 # define inet_addr decc$inet_addr
552 #endif
555 __gnat_inet_pton (int af, const char *src, void *dst) {
556 switch (af) {
557 #if defined (_WIN32) && defined (AF_INET6)
558 case AF_INET6:
559 #endif
560 case AF_INET:
561 break;
562 default:
563 errno = EAFNOSUPPORT;
564 return -1;
567 #if defined (__vxworks)
568 return (inet_aton (src, dst) == OK);
570 #elif defined (_WIN32)
571 struct sockaddr_storage ss;
572 int sslen = sizeof ss;
573 int rc;
575 ss.ss_family = af;
576 rc = WSAStringToAddressA (src, af, NULL, (struct sockaddr *)&ss, &sslen);
577 if (rc == 0) {
578 switch (af) {
579 case AF_INET:
580 *(struct in_addr *)dst = ((struct sockaddr_in *)&ss)->sin_addr;
581 break;
582 #ifdef AF_INET6
583 case AF_INET6:
584 *(struct in6_addr *)dst = ((struct sockaddr_in6 *)&ss)->sin6_addr;
585 break;
586 #endif
589 return (rc == 0);
591 #elif defined (__hpux__) || defined (VMS)
592 in_addr_t addr;
593 int rc = -1;
595 if (src == NULL || dst == NULL) {
596 errno = EINVAL;
598 } else if (!strcmp (src, "255.255.255.255")) {
599 addr = 0xffffffff;
600 rc = 1;
602 } else {
603 addr = inet_addr (src);
604 rc = (addr != 0xffffffff);
606 if (rc == 1) {
607 *(in_addr_t *)dst = addr;
609 return rc;
610 #endif
612 #endif
615 * Accessor functions for struct hostent.
618 char * __gnat_hostent_h_name (struct hostent * h) {
619 return h->h_name;
622 char * __gnat_hostent_h_alias (struct hostent * h, int index) {
623 return h->h_aliases[index];
626 int __gnat_hostent_h_addrtype (struct hostent * h) {
627 return h->h_addrtype;
630 int __gnat_hostent_h_length (struct hostent * h) {
631 return h->h_length;
634 char * __gnat_hostent_h_addr (struct hostent * h, int index) {
635 return h->h_addr_list[index];
639 * Accessor functions for struct servent.
641 * These are needed because servent has different representations on different
642 * platforms, and we don't want to deal with that on the Ada side. For example,
643 * on Linux, we have (see /usr/include netdb.h):
645 * struct servent
647 * char *s_name;
648 * char **s_aliases;
649 * int s_port;
650 * char *s_proto;
651 * };
653 * and on Windows (see mingw's socket.h):
655 * struct servent {
656 * char *s_name;
657 * char **s_aliases;
658 * #ifdef _WIN64
659 * char *s_proto;
660 * short s_port;
661 * #else
662 * short s_port;
663 * char *s_proto;
664 * #endif
665 * };
668 char *
669 __gnat_servent_s_name (struct servent * s)
671 return s->s_name;
674 char *
675 __gnat_servent_s_alias (struct servent * s, int index)
677 return s->s_aliases[index];
680 unsigned short
681 __gnat_servent_s_port (struct servent * s)
683 return s->s_port;
686 char *
687 __gnat_servent_s_proto (struct servent * s)
689 return s->s_proto;
692 #else
693 # warning Sockets are not supported on this platform
694 #endif /* defined(HAVE_SOCKETS) */