aboutsummaryrefslogtreecommitdiff
path: root/gcc/ada/socket.c
diff options
context:
space:
mode:
authorMartin Liska <mliska@suse.cz>2022-01-18 09:54:35 +0100
committerMartin Liska <mliska@suse.cz>2022-01-18 10:18:51 +0100
commit903e846578b8a97c311a6e120edbd116a8b3f992 (patch)
tree3d2da3ff95ab1b0c6063d3cb08bac81243669df4 /gcc/ada/socket.c
parent27404a02508b99d641840b031429385d0a92b114 (diff)
downloadgcc-903e846578b8a97c311a6e120edbd116a8b3f992.zip
gcc-903e846578b8a97c311a6e120edbd116a8b3f992.tar.gz
gcc-903e846578b8a97c311a6e120edbd116a8b3f992.tar.bz2
Revert Ada .cc renaming renaming.
gcc/ada/ChangeLog: * Make-generated.in: Revert renaming changes. * Makefile.rtl: Likewise. * adadecode.cc: Moved to... * adadecode.c: ...here. * affinity.cc: Moved to... * affinity.c: ...here. * argv-lynxos178-raven-cert.cc: Moved to... * argv-lynxos178-raven-cert.c: ...here. * argv.cc: Moved to... * argv.c: ...here. * aux-io.cc: Moved to... * aux-io.c: ...here. * cio.cc: Moved to... * cio.c: ...here. * cstreams.cc: Moved to... * cstreams.c: ...here. * env.cc: Moved to... * env.c: ...here. * exit.cc: Moved to... * exit.c: ...here. * expect.cc: Moved to... * expect.c: ...here. * final.cc: Moved to... * final.c: ...here. * gcc-interface/Makefile.in: * init.cc: Moved to... * init.c: ...here. * initialize.cc: Moved to... * initialize.c: ...here. * libgnarl/thread.cc: Moved to... * libgnarl/thread.c: ...here. * link.cc: Moved to... * link.c: ...here. * locales.cc: Moved to... * locales.c: ...here. * mkdir.cc: Moved to... * mkdir.c: ...here. * raise.cc: Moved to... * raise.c: ...here. * rtfinal.cc: Moved to... * rtfinal.c: ...here. * rtinit.cc: Moved to... * rtinit.c: ...here. * s-oscons-tmplt.c (CND): Revert renaming changes. * seh_init.cc: Moved to... * seh_init.c: ...here. * sigtramp-armdroid.cc: Moved to... * sigtramp-armdroid.c: ...here. * sigtramp-ios.cc: Moved to... * sigtramp-ios.c: ...here. * sigtramp-qnx.cc: Moved to... * sigtramp-qnx.c: ...here. * sigtramp-vxworks.cc: Moved to... * sigtramp-vxworks.c: ...here. * socket.cc: Moved to... * socket.c: ...here. * tracebak.cc: Moved to... * tracebak.c: ...here. * version.cc: Moved to... * version.c: ...here. * vx_stack_info.cc: Moved to... * vx_stack_info.c: ...here.
Diffstat (limited to 'gcc/ada/socket.c')
-rw-r--r--gcc/ada/socket.c829
1 files changed, 829 insertions, 0 deletions
diff --git a/gcc/ada/socket.c b/gcc/ada/socket.c
new file mode 100644
index 0000000..720b1d3
--- /dev/null
+++ b/gcc/ada/socket.c
@@ -0,0 +1,829 @@
+/****************************************************************************
+ * *
+ * GNAT COMPILER COMPONENTS *
+ * *
+ * S O C K E T *
+ * *
+ * C Implementation File *
+ * *
+ * Copyright (C) 2003-2022, Free Software Foundation, Inc. *
+ * *
+ * GNAT is free software; you can redistribute it and/or modify it under *
+ * terms of the GNU General Public License as published by the Free Soft- *
+ * ware Foundation; either version 3, or (at your option) any later ver- *
+ * sion. GNAT is distributed in the hope that it will be useful, but WITH- *
+ * OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY *
+ * or FITNESS FOR A PARTICULAR PURPOSE. *
+ * *
+ * As a special exception under Section 7 of GPL version 3, you are granted *
+ * additional permissions described in the GCC Runtime Library Exception, *
+ * version 3.1, as published by the Free Software Foundation. *
+ * *
+ * You should have received a copy of the GNU General Public License and *
+ * a copy of the GCC Runtime Library Exception along with this program; *
+ * see the files COPYING3 and COPYING.RUNTIME respectively. If not, see *
+ * <http://www.gnu.org/licenses/>. *
+ * *
+ * GNAT was originally developed by the GNAT team at New York University. *
+ * Extensive contributions were provided by Ada Core Technologies Inc. *
+ * *
+ ****************************************************************************/
+
+/* This file provides a portable binding to the sockets API */
+
+#define ATTRIBUTE_UNUSED __attribute__((unused))
+
+/* Ensure access to errno is thread safe. */
+#ifndef _REENTRANT
+#define _REENTRANT
+#endif
+#define _THREAD_SAFE
+
+#include "gsocket.h"
+
+#if defined (__FreeBSD__) || defined (__DragonFly__) \
+ || defined (__NetBSD__) || defined (__OpenBSD__)
+typedef unsigned int IOCTL_Req_T;
+#else
+typedef int IOCTL_Req_T;
+#endif
+
+#if defined(HAVE_SOCKETS)
+
+/* Include all the necessary system-specific headers and define the
+ * necessary macros (shared with gen-oscons).
+ */
+
+#if !defined(SO_NOSIGPIPE) && !defined (MSG_NOSIGNAL)
+#include <signal.h>
+#endif
+/* Required if we will be calling signal() in __gnat_disable_all_sigpipes() */
+
+#include "raise.h"
+/* Required for __gnat_malloc() */
+
+#include <string.h>
+/* Required for memcpy() */
+
+extern void __gnat_disable_sigpipe (int fd);
+extern void __gnat_disable_all_sigpipes (void);
+extern int __gnat_create_signalling_fds (int *fds);
+extern int __gnat_read_signalling_fd (int rsig);
+extern int __gnat_write_signalling_fd (int wsig);
+extern void __gnat_close_signalling_fd (int sig);
+extern void __gnat_last_socket_in_set (fd_set *, int *);
+extern void __gnat_get_socket_from_set (fd_set *, int *, int *);
+extern void __gnat_insert_socket_in_set (fd_set *, int);
+extern int __gnat_is_socket_in_set (fd_set *, int);
+extern fd_set *__gnat_new_socket_set (fd_set *);
+extern void __gnat_remove_socket_from_set (fd_set *, int);
+extern void __gnat_reset_socket_set (fd_set *);
+extern int __gnat_get_h_errno (void);
+extern int __gnat_socket_ioctl (int, IOCTL_Req_T, int *);
+
+extern char * __gnat_servent_s_name (struct servent *);
+extern char * __gnat_servent_s_alias (struct servent *, int index);
+extern unsigned short __gnat_servent_s_port (struct servent *);
+extern char * __gnat_servent_s_proto (struct servent *);
+
+extern char * __gnat_hostent_h_name (struct hostent *);
+extern char * __gnat_hostent_h_alias (struct hostent *, int);
+extern int __gnat_hostent_h_addrtype (struct hostent *);
+extern int __gnat_hostent_h_length (struct hostent *);
+extern char * __gnat_hostent_h_addr (struct hostent *, int);
+
+extern int __gnat_getaddrinfo(
+ const char *node,
+ const char *service,
+ const struct addrinfo *hints,
+ struct addrinfo **res);
+int __gnat_getnameinfo(
+ const struct sockaddr *sa, socklen_t salen,
+ char *host, size_t hostlen,
+ char *serv, size_t servlen, int flags);
+extern void __gnat_freeaddrinfo(struct addrinfo *res);
+extern const char * __gnat_gai_strerror(int errcode);
+
+#ifndef HAVE_INET_PTON
+extern int __gnat_inet_pton (int, const char *, void *);
+#endif
+
+#ifndef HAVE_INET_NTOP
+extern const char *
+__gnat_inet_ntop(int, const void *, char *, socklen_t);
+#endif
+
+/* Disable the sending of SIGPIPE for writes on a broken stream */
+
+void
+__gnat_disable_sigpipe (int fd ATTRIBUTE_UNUSED)
+{
+#ifdef SO_NOSIGPIPE
+ int val = 1;
+ (void) setsockopt (fd, SOL_SOCKET, SO_NOSIGPIPE, &val, sizeof val);
+#endif
+}
+
+void
+__gnat_disable_all_sigpipes (void)
+{
+#if !defined(SO_NOSIGPIPE) && !defined(MSG_NOSIGNAL) && defined(SIGPIPE)
+ (void) signal (SIGPIPE, SIG_IGN);
+#endif
+}
+
+#if defined (_WIN32) || defined (__vxworks)
+/*
+ * Signalling FDs operations are implemented in Ada for these platforms
+ * (see subunit GNAT.Sockets.Thin.Signalling_Fds).
+ */
+#else
+/*
+ * Create a pair of connected file descriptors fds[0] and fds[1] used for
+ * signalling by a Selector object. fds[0] is the read end, and fds[1] the
+ * write end.
+ */
+int
+__gnat_create_signalling_fds (int *fds) {
+ return pipe (fds);
+}
+
+/*
+ * Read one byte of data from rsig, the read end of a pair of signalling fds
+ * created by __gnat_create_signalling_fds.
+ */
+int
+__gnat_read_signalling_fd (int rsig) {
+ char c;
+ return read (rsig, &c, 1);
+}
+
+/*
+ * Write one byte of data to wsig, the write end of a pair of signalling fds
+ * created by __gnat_create_signalling_fds.
+ */
+int
+__gnat_write_signalling_fd (int wsig) {
+ char c = 0;
+ return write (wsig, &c, 1);
+}
+
+/*
+ * Close one end of a pair of signalling fds
+ */
+void
+__gnat_close_signalling_fd (int sig) {
+ (void) close (sig);
+}
+#endif
+
+/*
+ * Handling of gethostbyname, gethostbyaddr, getservbyname and getservbyport
+ * =========================================================================
+ *
+ * This module exposes __gnat_getXXXbyYYY operations with the same signature
+ * as the reentrant variant getXXXbyYYY_r.
+ *
+ * On platforms where getXXXbyYYY is intrinsically reentrant, the provided user
+ * buffer argument is ignored.
+ *
+ * When getXXXbyYYY is not reentrant but getXXXbyYYY_r exists, the latter is
+ * used, and the provided buffer argument must point to a valid, thread-local
+ * buffer (usually on the caller's stack).
+ *
+ * When getXXXbyYYY is not reentrant and no reentrant getXXXbyYYY_r variant
+ * is available, the non-reentrant getXXXbyYYY is called, the provided user
+ * buffer is ignored, and the caller is expected to take care of mutual
+ * exclusion.
+ */
+
+#ifdef HAVE_GETxxxBYyyy_R
+int
+__gnat_gethostbyname (const char *name,
+ struct hostent *ret, char *buf, size_t buflen,
+ int *h_errnop)
+{
+ struct hostent *rh;
+ int ri;
+
+#if defined(__linux__) || defined(__GLIBC__) || defined(__rtems__)
+ (void) gethostbyname_r (name, ret, buf, buflen, &rh, h_errnop);
+#else
+ rh = gethostbyname_r (name, ret, buf, buflen, h_errnop);
+#endif
+ ri = (rh == NULL) ? -1 : 0;
+ return ri;
+}
+
+int
+__gnat_gethostbyaddr (const char *addr, int len, int type,
+ struct hostent *ret, char *buf, size_t buflen,
+ int *h_errnop)
+{
+ struct hostent *rh;
+ int ri;
+
+#if defined(__linux__) || defined(__GLIBC__) || defined(__rtems__)
+ (void) gethostbyaddr_r (addr, len, type, ret, buf, buflen, &rh, h_errnop);
+#else
+ rh = gethostbyaddr_r (addr, len, type, ret, buf, buflen, h_errnop);
+#endif
+ ri = (rh == NULL) ? -1 : 0;
+ return ri;
+}
+
+int
+__gnat_getservbyname (const char *name, const char *proto,
+ struct servent *ret, char *buf, size_t buflen)
+{
+ struct servent *rh;
+ int ri;
+
+#if defined(__linux__) || defined(__GLIBC__) || defined(__rtems__)
+ (void) getservbyname_r (name, proto, ret, buf, buflen, &rh);
+#else
+ rh = getservbyname_r (name, proto, ret, buf, buflen);
+#endif
+ ri = (rh == NULL) ? -1 : 0;
+ return ri;
+}
+
+int
+__gnat_getservbyport (int port, const char *proto,
+ struct servent *ret, char *buf, size_t buflen)
+{
+ struct servent *rh;
+ int ri;
+
+#if defined(__linux__) || defined(__GLIBC__) || defined(__rtems__)
+ (void) getservbyport_r (port, proto, ret, buf, buflen, &rh);
+#else
+ rh = getservbyport_r (port, proto, ret, buf, buflen);
+#endif
+ ri = (rh == NULL) ? -1 : 0;
+ return ri;
+}
+#elif defined (__vxworks)
+static char vxw_h_name[MAXHOSTNAMELEN + 1];
+static char *vxw_h_aliases[1] = { NULL };
+static int vxw_h_addr;
+static char *vxw_h_addr_list[2] = { (char*) &vxw_h_addr, NULL };
+
+int
+__gnat_gethostbyname (const char *name,
+ struct hostent *ret, char *buf, size_t buflen,
+ int *h_errnop)
+{
+ vxw_h_addr = hostGetByName (name);
+ if (vxw_h_addr == ERROR) {
+ *h_errnop = __gnat_get_h_errno ();
+ return -1;
+ }
+ ret->h_name = name;
+ ret->h_aliases = &vxw_h_aliases;
+ ret->h_addrtype = AF_INET;
+ ret->h_length = 4;
+ ret->h_addr_list = &vxw_h_addr_list;
+ return 0;
+}
+
+int
+__gnat_gethostbyaddr (const char *addr, int len, int type,
+ struct hostent *ret, char *buf, size_t buflen,
+ int *h_errnop)
+{
+ if (type != AF_INET) {
+ *h_errnop = EAFNOSUPPORT;
+ return -1;
+ }
+
+ if (addr == NULL || len != 4) {
+ *h_errnop = EINVAL;
+ return -1;
+ }
+
+ if (hostGetByAddr (*(int*)addr, &vxw_h_name) != OK) {
+ *h_errnop = __gnat_get_h_errno ();
+ return -1;
+ }
+
+ vxw_h_addr = addr;
+
+ ret->h_name = &vxw_h_name;
+ ret->h_aliases = &vxw_h_aliases;
+ ret->h_addrtype = AF_INET;
+ ret->h_length = 4;
+ ret->h_addr_list = &vxw_h_addr_list;
+ return 0;
+}
+
+int
+__gnat_getservbyname (const char *name, const char *proto,
+ struct servent *ret, char *buf, size_t buflen)
+{
+ /* Not available under VxWorks */
+ return -1;
+}
+
+int
+__gnat_getservbyport (int port, const char *proto,
+ struct servent *ret, char *buf, size_t buflen)
+{
+ /* Not available under VxWorks */
+ return -1;
+}
+#else
+int
+__gnat_gethostbyname (const char *name, struct hostent *ret,
+ char *buf ATTRIBUTE_UNUSED, size_t buflen ATTRIBUTE_UNUSED,
+ int *h_errnop)
+{
+ struct hostent *rh;
+ rh = gethostbyname (name);
+ if (rh == NULL) {
+ *h_errnop = __gnat_get_h_errno ();
+ return -1;
+ }
+ *ret = *rh;
+ *h_errnop = 0;
+ return 0;
+}
+
+int
+__gnat_gethostbyaddr (const char *addr, int len, int type, struct hostent *ret,
+ char *buf ATTRIBUTE_UNUSED, size_t buflen ATTRIBUTE_UNUSED,
+ int *h_errnop)
+{
+ struct hostent *rh;
+ rh = gethostbyaddr (addr, len, type);
+ if (rh == NULL) {
+ *h_errnop = __gnat_get_h_errno ();
+ return -1;
+ }
+ *ret = *rh;
+ *h_errnop = 0;
+ return 0;
+}
+
+int
+__gnat_getservbyname (const char *name, const char *proto, struct servent *ret,
+ char *buf ATTRIBUTE_UNUSED, size_t buflen ATTRIBUTE_UNUSED)
+{
+ struct servent *rh;
+ rh = getservbyname (name, proto);
+ if (rh == NULL)
+ return -1;
+ *ret = *rh;
+ return 0;
+}
+
+int
+__gnat_getservbyport (int port, const char *proto, struct servent *ret,
+ char *buf ATTRIBUTE_UNUSED, size_t buflen ATTRIBUTE_UNUSED)
+{
+ struct servent *rh;
+ rh = getservbyport (port, proto);
+ if (rh == NULL)
+ return -1;
+ *ret = *rh;
+ return 0;
+}
+#endif
+
+/* Find the largest socket in the socket set SET. This is needed for
+ `select'. LAST is the maximum value for the largest socket. This hint is
+ used to avoid scanning very large socket sets. On return, LAST is the
+ actual largest socket in the socket set. */
+
+void
+__gnat_last_socket_in_set (fd_set *set, int *last)
+{
+ int l;
+ l = -1;
+
+#ifdef _WIN32
+ /* More efficient method for NT. */
+ for (unsigned int s = 0; s < set->fd_count; s++)
+ if ((int) set->fd_array[s] > l)
+ l = set->fd_array[s];
+
+#else
+
+ for (int s = *last; s != -1; s--)
+ if (FD_ISSET (s, set))
+ {
+ l = s;
+ break;
+ }
+#endif
+
+ *last = l;
+}
+
+/* Get last socket and remove it from the socket set SET. LAST is the
+ maximum value of the largest socket. This hint is used to avoid scanning
+ very large socket sets. On return, LAST is set to the actual largest
+ socket in the socket set. */
+
+void
+__gnat_get_socket_from_set (fd_set *set, int *last, int *socket)
+{
+ *socket = *last;
+ FD_CLR (*socket, set);
+ __gnat_last_socket_in_set (set, last);
+}
+
+/* Insert SOCKET in the socket set SET. */
+
+void
+__gnat_insert_socket_in_set (fd_set *set, int socket)
+{
+ FD_SET (socket, set);
+}
+
+/* Check whether a given SOCKET is in the socket set SET. */
+
+int
+__gnat_is_socket_in_set (fd_set *set, int socket)
+{
+ return FD_ISSET (socket, set);
+}
+
+/* Remove SOCKET from the socket set SET. */
+
+void
+__gnat_remove_socket_from_set (fd_set *set, int socket)
+{
+ FD_CLR (socket, set);
+}
+
+/* Reset SET */
+void
+__gnat_reset_socket_set (fd_set *set)
+{
+ FD_ZERO (set);
+}
+
+/* Get the value of the last host error */
+
+int
+__gnat_get_h_errno (void) {
+#ifdef __vxworks
+ int vxw_errno = errno;
+
+ switch (vxw_errno) {
+ case 0:
+ return 0;
+
+#ifdef S_hostLib_HOST_NOT_FOUND
+ case S_hostLib_HOST_NOT_FOUND:
+#endif
+ case S_hostLib_UNKNOWN_HOST:
+ return HOST_NOT_FOUND;
+
+#ifdef S_hostLib_TRY_AGAIN
+ case S_hostLib_TRY_AGAIN:
+ return TRY_AGAIN;
+#endif
+
+#ifdef S_hostLib_NO_RECOVERY
+ case S_hostLib_NO_RECOVERY:
+#endif
+#ifdef S_hostLib_NETDB_INTERNAL
+ case S_hostLib_NETDB_INTERNAL:
+#endif
+ case S_hostLib_INVALID_PARAMETER:
+ return NO_RECOVERY;
+
+ default:
+ return -1;
+ }
+
+#elif defined (__rtems__)
+ /* At this stage in the tool build, no networking .h files are available.
+ * Newlib does not provide networking .h files and RTEMS is not built yet.
+ * So we need to explicitly extern h_errno to access it.
+ */
+ extern int h_errno;
+ return h_errno;
+
+#else
+ return h_errno;
+#endif
+}
+
+/* Wrapper for ioctl(2), which is a variadic function */
+
+int
+__gnat_socket_ioctl (int fd, IOCTL_Req_T req, int *arg) {
+#if defined (_WIN32)
+ return ioctlsocket (fd, req, (unsigned long *)arg);
+#elif defined (__APPLE__)
+ /*
+ * On Darwin, req is an unsigned long, and we want to convert without sign
+ * extension to get the proper bit pattern in the case of a 64 bit kernel.
+ */
+ return ioctl (fd, (unsigned int) req, arg);
+#else
+ return ioctl (fd, req, arg);
+#endif
+}
+
+#ifndef HAVE_INET_PTON
+
+int
+__gnat_inet_pton (int af, const char *src, void *dst) {
+ switch (af) {
+#if defined (_WIN32) && defined (AF_INET6)
+ case AF_INET6:
+#endif
+ case AF_INET:
+ break;
+ default:
+ errno = EAFNOSUPPORT;
+ return -1;
+ }
+
+#if defined (__vxworks)
+ return (inet_aton (src, dst) == OK);
+
+#elif defined (_WIN32)
+ struct sockaddr_storage ss;
+ int sslen = sizeof ss;
+ int rc;
+
+ ss.ss_family = af;
+ rc = WSAStringToAddressA ((char *)src, af, NULL, (struct sockaddr *)&ss,
+ &sslen);
+ if (rc == 0) {
+ switch (af) {
+ case AF_INET:
+ *(struct in_addr *)dst = ((struct sockaddr_in *)&ss)->sin_addr;
+ break;
+#ifdef AF_INET6
+ case AF_INET6:
+ *(struct in6_addr *)dst = ((struct sockaddr_in6 *)&ss)->sin6_addr;
+ break;
+#endif
+ }
+ }
+ return (rc == 0);
+
+#elif defined (__hpux__)
+ in_addr_t addr;
+ int rc = -1;
+
+ if (src == NULL || dst == NULL) {
+ errno = EINVAL;
+
+ } else if (!strcmp (src, "255.255.255.255")) {
+ addr = 0xffffffff;
+ rc = 1;
+
+ } else {
+ addr = inet_addr (src);
+ rc = (addr != 0xffffffff);
+ }
+ if (rc == 1) {
+ *(in_addr_t *)dst = addr;
+ }
+ return rc;
+
+#else
+ return -1;
+#endif
+}
+#endif
+
+#ifndef HAVE_INET_NTOP
+
+const char *
+__gnat_inet_ntop(int af, const void *src, char *dst, socklen_t size)
+{
+#ifdef _WIN32
+ struct sockaddr_storage ss;
+ int sslen = sizeof ss;
+ memset(&ss, 0, sslen);
+ ss.ss_family = af;
+
+ switch (af) {
+ case AF_INET6:
+ ((struct sockaddr_in6 *)&ss)->sin6_addr = *(struct in6_addr *)src;
+ break;
+ case AF_INET:
+ ((struct sockaddr_in *)&ss)->sin_addr = *(struct in_addr *)src;
+ break;
+ default:
+ errno = EAFNOSUPPORT;
+ return NULL;
+ }
+
+ DWORD sz = size;
+
+ if (WSAAddressToStringA((struct sockaddr*)&ss, sslen, 0, dst, &sz) != 0) {
+ return NULL;
+ }
+ return dst;
+#else
+ return NULL;
+#endif
+}
+#endif
+
+/*
+ * Accessor functions for struct hostent.
+ */
+
+char * __gnat_hostent_h_name (struct hostent * h) {
+ return h->h_name;
+}
+
+char * __gnat_hostent_h_alias (struct hostent * h, int index) {
+ return h->h_aliases[index];
+}
+
+int __gnat_hostent_h_addrtype (struct hostent * h) {
+ return h->h_addrtype;
+}
+
+int __gnat_hostent_h_length (struct hostent * h) {
+ return h->h_length;
+}
+
+char * __gnat_hostent_h_addr (struct hostent * h, int index) {
+ return h->h_addr_list[index];
+}
+
+/*
+ * Accessor functions for struct servent.
+ *
+ * These are needed because servent has different representations on different
+ * platforms, and we don't want to deal with that on the Ada side. For example,
+ * on Linux, we have (see /usr/include netdb.h):
+ *
+ * struct servent
+ * {
+ * char *s_name;
+ * char **s_aliases;
+ * int s_port;
+ * char *s_proto;
+ * };
+ *
+ * and on Windows (see mingw's socket.h):
+ *
+ * struct servent {
+ * char *s_name;
+ * char **s_aliases;
+ * #ifdef _WIN64
+ * char *s_proto;
+ * short s_port;
+ * #else
+ * short s_port;
+ * char *s_proto;
+ * #endif
+ * };
+ */
+
+char *
+__gnat_servent_s_name (struct servent * s)
+{
+ return s->s_name;
+}
+
+char *
+__gnat_servent_s_alias (struct servent * s, int index)
+{
+ return s->s_aliases[index];
+}
+
+unsigned short
+__gnat_servent_s_port (struct servent * s)
+{
+ return s->s_port;
+}
+
+char *
+__gnat_servent_s_proto (struct servent * s)
+{
+ return s->s_proto;
+}
+
+#if defined(AF_INET6) && !defined(__rtems__)
+
+int __gnat_getaddrinfo(
+ const char *node,
+ const char *service,
+ const struct addrinfo *hints,
+ struct addrinfo **res)
+{
+ return getaddrinfo(node, service, hints, res);
+}
+
+int __gnat_getnameinfo(
+ const struct sockaddr *sa, socklen_t salen,
+ char *host, size_t hostlen,
+ char *serv, size_t servlen, int flags)
+{
+ return getnameinfo(sa, salen, host, hostlen, serv, servlen, flags);
+}
+
+void __gnat_freeaddrinfo(struct addrinfo *res) {
+ freeaddrinfo(res);
+}
+
+const char * __gnat_gai_strerror(int errcode) {
+#if defined(_WIN32) || defined(__vxworks)
+ // gai_strerror thread usafe on Windows and is not available on some vxWorks
+ // versions
+
+ switch (errcode) {
+ case EAI_AGAIN:
+ return "Temporary failure in name resolution.";
+ case EAI_BADFLAGS:
+ return "Invalid value for ai_flags.";
+ case EAI_FAIL:
+ return "Nonrecoverable failure in name resolution.";
+ case EAI_FAMILY:
+ return "The ai_family member is not supported.";
+ case EAI_MEMORY:
+ return "Memory allocation failure.";
+#ifdef EAI_NODATA
+ // Could be not defined under the vxWorks
+ case EAI_NODATA:
+ return "No address associated with nodename.";
+#endif
+#if EAI_NODATA != EAI_NONAME
+ /* with mingw64 runtime EAI_NODATA and EAI_NONAME have the same value.
+ This applies to both win32 and win64 */
+ case EAI_NONAME:
+ return "Neither nodename nor servname provided, or not known.";
+#endif
+ case EAI_SERVICE:
+ return "The servname parameter is not supported for ai_socktype.";
+ case EAI_SOCKTYPE:
+ return "The ai_socktype member is not supported.";
+#ifdef EAI_SYSTEM
+ // Could be not defined, at least on Windows
+ case EAI_SYSTEM:
+ return "System error returned in errno";
+#endif
+ default:
+ return "Unknown error.";
+ }
+#else
+ return gai_strerror(errcode);
+#endif
+}
+
+#else
+
+int __gnat_getaddrinfo(
+ const char *node,
+ const char *service,
+ const struct addrinfo *hints,
+ struct addrinfo **res)
+{
+ return -1;
+}
+
+int __gnat_getnameinfo(
+ const struct sockaddr *sa, socklen_t salen,
+ char *host, size_t hostlen,
+ char *serv, size_t servlen, int flags)
+{
+ return -1;
+}
+
+void __gnat_freeaddrinfo(struct addrinfo *res) {
+}
+
+const char * __gnat_gai_strerror(int errcode) {
+ return "getaddinfo functions family is not supported";
+}
+
+#endif
+
+int __gnat_minus_500ms() {
+#if defined (_WIN32)
+ // Windows Server 2019 and Windows 8.0 do not need 500 millisecond socket
+ // timeout correction.
+ if (IsWindowsServer()) {
+ OSVERSIONINFO osvi;
+ ZeroMemory(&osvi, sizeof(OSVERSIONINFO));
+ osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
+ // Documentation proposes to use IsWindowsVersionOrGreater(10, 0, 17763)
+ // but it does not compare by the build number (last parameter).
+ GetVersionEx(&osvi);
+ return osvi.dwMajorVersion < 10
+ || (osvi.dwMajorVersion == 10
+ && osvi.dwMinorVersion == 0
+ && osvi.dwBuildNumber < 17763);
+ } else {
+ return !IsWindows8OrGreater();
+ }
+#else
+ return 0;
+#endif
+}
+
+#endif /* defined(HAVE_SOCKETS) */