Glibc networking support (XCC)
authorBarret Rhoden <brho@cs.berkeley.edu>
Mon, 23 Aug 2010 07:33:45 +0000 (00:33 -0700)
committerKevin Klues <klueska@cs.berkeley.edu>
Thu, 3 Nov 2011 00:35:52 +0000 (17:35 -0700)
Glibc now builds its network-support libraries and subdirs.  It wasn't
before, leading to some ugly hacks elsewhere.  While ROS doesn't support
the networking system calls (lots of stubs will just fail, many
silently), at least some codes will be able to compile and eventually
we'll be able to add in the networking support we need.

This also adds some Documentation about how to work with the glibc
build system we have.  Further documentation about glibc/gcc and all of
that is still a TODO: kevin/andrew.

P.S. Rebuild your cross compiler.

21 files changed:
Documentation/glibc.txt [new file with mode: 0644]
kern/include/ros/glibc-asm/ioctl.h [new file with mode: 0644]
kern/include/ros/glibc-asm/ioctls.h [new file with mode: 0644]
kern/include/ros/glibc-asm/socket.h [new file with mode: 0644]
kern/include/ros/glibc-asm/sockios.h [new file with mode: 0644]
kern/include/ros/noivy.h
tools/compilers/gcc-glibc/glibc-2.11.1-ros/nss/Makefile [deleted file]
tools/compilers/gcc-glibc/glibc-2.11.1-ros/sysdeps/ros/Makefile
tools/compilers/gcc-glibc/glibc-2.11.1-ros/sysdeps/ros/Subdirs [new file with mode: 0644]
tools/compilers/gcc-glibc/glibc-2.11.1-ros/sysdeps/ros/bits/ioctls.h [new file with mode: 0644]
tools/compilers/gcc-glibc/glibc-2.11.1-ros/sysdeps/ros/bits/socket.h
tools/compilers/gcc-glibc/glibc-2.11.1-ros/sysdeps/ros/bits/utmp.h [new file with mode: 0644]
tools/compilers/gcc-glibc/glibc-2.11.1-ros/sysdeps/ros/check_native.c [new file with mode: 0644]
tools/compilers/gcc-glibc/glibc-2.11.1-ros/sysdeps/ros/getaddrinfo.c
tools/compilers/gcc-glibc/glibc-2.11.1-ros/sysdeps/ros/getpeername.c [new file with mode: 0644]
tools/compilers/gcc-glibc/glibc-2.11.1-ros/sysdeps/ros/isatty.c
tools/compilers/gcc-glibc/glibc-2.11.1-ros/sysdeps/ros/net/if.h [new file with mode: 0644]
tools/compilers/gcc-glibc/glibc-2.11.1-ros/sysdeps/ros/netpacket/packet.h [new file with mode: 0644]
tools/compilers/gcc-glibc/glibc-2.11.1-ros/sysdeps/ros/ptsname.c [new file with mode: 0644]
tools/compilers/gcc-glibc/glibc-2.11.1-ros/sysdeps/ros/sa_len.c [new file with mode: 0644]
tools/compilers/gcc-glibc/glibc-2.11.1-ros/sysdeps/ros/sys/param.h

diff --git a/Documentation/glibc.txt b/Documentation/glibc.txt
new file mode 100644 (file)
index 0000000..32d4338
--- /dev/null
@@ -0,0 +1,135 @@
+glibc.txt:
+Barret Rhoden
+Last updated: 2010-08-22
+----------------------------------------------
+This document is an attempt to gather knowledge about how to work with the
+glibc port.  This is based on my half-assed struggling with the port done by
+kevin and andrew.
+
+When to recompile (other than when changing libc)
+--------------------------
+Whenever you change a kernel header (something in kern/include/ros),
+technically you should rebuild.  It isn't critical in all places, such as for
+files that aren't included by glibc, or for files that haven't changed
+something that glibc relies on.
+
+After any recompile, don't forget to rebuild userspace apps (make userclean,
+make install-libs) and to refresh your FS.
+
+How to recompile glibc
+--------------------------
+Normally, make x86 (or whatever) works fairly well.  However, sometimes you
+need to rebuild all of glibc.  This might be on a hunch, or to get rid of
+things that might have compiled, but are failing to link and don't seem to
+rebuild.
+
+In this event, the next step is to remove the build directories
+(i686-ros-glibc-*) and also the hidden files (.i686-ros-glibc*).  If you get
+errors from make very early on about not finding some targets (such as
+install-headers), you forgot to delete the hidden files.
+
+Then next step up would be to remove the glibc-XXX folder (whatever the
+version is).  Sometimes you aren't sure if old changes are sitting around in
+this folder that aren't getting overwritten by the real source of our changes,
+the -ros folder.  A lovely example of this is an old Makefile for the nss
+subdir.  It was altered to remove some things, notably the files service,
+which translates into libnss_files - which is needed by other things (nis,
+etc).  To fix this, I had to notice an -ros version of the Makefile (after I
+realized it was the problem), and that the Makefile was being included - it
+was just faulty.
+
+Finally, you can always make clean, but the overall XCC Makefile will clean
+everything - including gcc and binutils.
+
+Note that if you are making a trivial addition to a kernel header, you can get
+away with just copying it to its location in the XCC install directory
+(sys-include).
+
+The -ros folder
+--------------------------
+All changes to glibc must be made in the glibc-XXX-ros folder.  Any changes
+here will be copied over to the real glibc folder when it is made.  If you
+want to remove a file that was originally in the -ros folder, you need to
+manually remove it from the glibc-XXX folder as well.  The updating scripts
+will not remove a file.
+
+The sysdeps folder
+--------------------------
+Most of your changes will go here.  Every system that has a glibc port should
+have one of these folders, with its system-specific ports.  The files here are
+normally files expected elsewhere in libc, and the glibc build system knows to
+look in these places.
+
+Simply dropping a file in here will not get it built.  It will for many files,
+but some others that weren't expected will need to be manually added to a
+Makefile.  If you notice some files not getting compiled, (drop a #error in
+there), you'll need to add it to a Makefile.  In the main sysdeps/Makefile,
+add the filename (minus .c) to the sysdeps var.  Look at sa_len for an
+example.  Sometimes you'll need to be careful about adding it for some
+subdirectories and not others (you probably only want to add a C file for one
+subdir).  Check out Linux's port for help.
+
+Sometimes you have files that you want to change outside of the sysdeps
+folder.  These still go in the glibc-XXX-ros folder, but not in sysdeps.  The
+main example we have right now is features.h.  At one point, I wanted to
+change sys/socket.h.  Simply adding it to sysdeps/ros/sys/socket.h would not
+change the main sys/socket.h, nor would the sysdep version get included first.
+Putting it in the -ros/sys/ folder did it (though ultimately I didn't want the
+change).  The point is, sysdeps doesn't mirror and override the main tree for
+all files - it is behind some others in the search/include path.
+
+Subdirs
+--------------------------
+As a note, these 'subdirectories' are the "primary folders" (i.e. addons),
+such as inet, ncsd, libio, whatever.  These are the root folders in glibc,
+representing some major functionality.  They can be built with the
+--enable-addons switch, which by default builds all of them.  Sort of!
+
+To really get them to even be available for a port, you need to "include" them
+in a certain manner.  There are two ways.  One is the Subdirs file in the
+sysdeps/ros/ directory.  Putting a subdir name in here means glibc will try to
+build it; it is available to be an addon.  Careful with these, since a lot of
+the folders tend to need each other (like most all of the ones in unix/inet).
+
+If you want a massive subsystem, such as "unix/inet" or "posix", you can add
+it to the sysdeps/ros/Implies file.  You will get a bunch of these folders at
+once, plus some other unspecified stuff (necessary for the overall system,
+perhaps?).  If you add "unix/inet", you get more than just its Subdirs.
+
+Also note that these subdirs can depend on each other, noted in the "Depends"
+file.  Presumably this will cause them to get made...
+
+Unimplemented Stubs
+--------------------------
+There are a lot of things we haven't ported, but we have the stub functions so
+that we can at least compile things against it.  When you compile (including
+regular programs), you'll get warnings about this.  
+
+Linux ASM bits
+--------------------------
+We've included some header files from Linux's kernel.  For now, we just need
+something to keep glibc happy, even though ROS doesn't have any networking
+syscalls.  Don't rely on this stuff too much.  These files, and other future
+glibc compatibility kernel headers, are in kern/include/ros/glibc-asm.
+
+Tips, Questions, and Misc Notes
+--------------------------
+- Grep and find are your friend.
+- Watch what Linux does.
+- The kernel headers end up getting installed to the sys-include/ directory,
+  while the regular glib headers go to the include directory.
+- atomic_swap might have issues (warnings about signedness differences)
+- It's not always clear which files in the -ros folder actually need to be
+  there (presumably they all do), and in what manner they were modified and
+  from which original copy.  Ideally, the ROS-specific changes to large files
+  will be commented.
+- the SHARED flag is a bit of a mess - things get compiled differently for
+  shared vs static, and it can get complicated with start.c, tls.c, etc.
+- What things in one file rely heavily on another file?  Are there non-obvious
+  gotchas?  (yes, and no one documented them).
+
+Ghetto Things (Feel free to fix them):
+--------------------------
+- ptsname: we needed to have the sysdep (was being looked for by the login
+  subdir make process), but having the actual functions in it caused a link
+  error (multiple declarations).  So we have an empty file...
diff --git a/kern/include/ros/glibc-asm/ioctl.h b/kern/include/ros/glibc-asm/ioctl.h
new file mode 100644 (file)
index 0000000..0da2c7d
--- /dev/null
@@ -0,0 +1,96 @@
+#ifndef _ASM_GENERIC_IOCTL_H
+#define _ASM_GENERIC_IOCTL_H
+
+/* ioctl command encoding: 32 bits total, command in lower 16 bits,
+ * size of the parameter structure in the lower 14 bits of the
+ * upper 16 bits.
+ * Encoding the size of the parameter structure in the ioctl request
+ * is useful for catching programs compiled with old versions
+ * and to avoid overwriting user space outside the user buffer area.
+ * The highest 2 bits are reserved for indicating the ``access mode''.
+ * NOTE: This limits the max parameter size to 16kB -1 !
+ */
+
+/*
+ * The following is for compatibility across the various Linux
+ * platforms.  The generic ioctl numbering scheme doesn't really enforce
+ * a type field.  De facto, however, the top 8 bits of the lower 16
+ * bits are indeed used as a type field, so we might just as well make
+ * this explicit here.  Please be sure to use the decoding macros
+ * below from now on.
+ */
+#define _IOC_NRBITS    8
+#define _IOC_TYPEBITS  8
+
+/*
+ * Let any architecture override either of the following before
+ * including this file.
+ */
+
+#ifndef _IOC_SIZEBITS
+# define _IOC_SIZEBITS 14
+#endif
+
+#ifndef _IOC_DIRBITS
+# define _IOC_DIRBITS  2
+#endif
+
+#define _IOC_NRMASK    ((1 << _IOC_NRBITS)-1)
+#define _IOC_TYPEMASK  ((1 << _IOC_TYPEBITS)-1)
+#define _IOC_SIZEMASK  ((1 << _IOC_SIZEBITS)-1)
+#define _IOC_DIRMASK   ((1 << _IOC_DIRBITS)-1)
+
+#define _IOC_NRSHIFT   0
+#define _IOC_TYPESHIFT (_IOC_NRSHIFT+_IOC_NRBITS)
+#define _IOC_SIZESHIFT (_IOC_TYPESHIFT+_IOC_TYPEBITS)
+#define _IOC_DIRSHIFT  (_IOC_SIZESHIFT+_IOC_SIZEBITS)
+
+/*
+ * Direction bits, which any architecture can choose to override
+ * before including this file.
+ */
+
+#ifndef _IOC_NONE
+# define _IOC_NONE     0U
+#endif
+
+#ifndef _IOC_WRITE
+# define _IOC_WRITE    1U
+#endif
+
+#ifndef _IOC_READ
+# define _IOC_READ     2U
+#endif
+
+#define _IOC(dir,type,nr,size) \
+       (((dir)  << _IOC_DIRSHIFT) | \
+        ((type) << _IOC_TYPESHIFT) | \
+        ((nr)   << _IOC_NRSHIFT) | \
+        ((size) << _IOC_SIZESHIFT))
+
+#define _IOC_TYPECHECK(t) (sizeof(t))
+
+/* used to create numbers */
+#define _IO(type,nr)           _IOC(_IOC_NONE,(type),(nr),0)
+#define _IOR(type,nr,size)     _IOC(_IOC_READ,(type),(nr),(_IOC_TYPECHECK(size)))
+#define _IOW(type,nr,size)     _IOC(_IOC_WRITE,(type),(nr),(_IOC_TYPECHECK(size)))
+#define _IOWR(type,nr,size)    _IOC(_IOC_READ|_IOC_WRITE,(type),(nr),(_IOC_TYPECHECK(size)))
+#define _IOR_BAD(type,nr,size) _IOC(_IOC_READ,(type),(nr),sizeof(size))
+#define _IOW_BAD(type,nr,size) _IOC(_IOC_WRITE,(type),(nr),sizeof(size))
+#define _IOWR_BAD(type,nr,size)        _IOC(_IOC_READ|_IOC_WRITE,(type),(nr),sizeof(size))
+
+/* used to decode ioctl numbers.. */
+#define _IOC_DIR(nr)           (((nr) >> _IOC_DIRSHIFT) & _IOC_DIRMASK)
+#define _IOC_TYPE(nr)          (((nr) >> _IOC_TYPESHIFT) & _IOC_TYPEMASK)
+#define _IOC_NR(nr)            (((nr) >> _IOC_NRSHIFT) & _IOC_NRMASK)
+#define _IOC_SIZE(nr)          (((nr) >> _IOC_SIZESHIFT) & _IOC_SIZEMASK)
+
+/* ...and for the drivers/sound files... */
+
+#define IOC_IN         (_IOC_WRITE << _IOC_DIRSHIFT)
+#define IOC_OUT                (_IOC_READ << _IOC_DIRSHIFT)
+#define IOC_INOUT      ((_IOC_WRITE|_IOC_READ) << _IOC_DIRSHIFT)
+#define IOCSIZE_MASK   (_IOC_SIZEMASK << _IOC_SIZESHIFT)
+#define IOCSIZE_SHIFT  (_IOC_SIZESHIFT)
+
+#endif /* _ASM_GENERIC_IOCTL_H */
diff --git a/kern/include/ros/glibc-asm/ioctls.h b/kern/include/ros/glibc-asm/ioctls.h
new file mode 100644 (file)
index 0000000..a8ad582
--- /dev/null
@@ -0,0 +1,110 @@
+#ifndef __ASM_GENERIC_IOCTLS_H
+#define __ASM_GENERIC_IOCTLS_H
+
+#include <ros/glibc-asm/ioctl.h>
+
+/*
+ * These are the most common definitions for tty ioctl numbers.
+ * Most of them do not use the recommended _IOC(), but there is
+ * probably some source code out there hardcoding the number,
+ * so we might as well use them for all new platforms.
+ *
+ * The architectures that use different values here typically
+ * try to be compatible with some Unix variants for the same
+ * architecture.
+ */
+
+/* 0x54 is just a magic number to make these relatively unique ('T') */
+
+#define TCGETS         0x5401
+#define TCSETS         0x5402
+#define TCSETSW                0x5403
+#define TCSETSF                0x5404
+#define TCGETA         0x5405
+#define TCSETA         0x5406
+#define TCSETAW                0x5407
+#define TCSETAF                0x5408
+#define TCSBRK         0x5409
+#define TCXONC         0x540A
+#define TCFLSH         0x540B
+#define TIOCEXCL       0x540C
+#define TIOCNXCL       0x540D
+#define TIOCSCTTY      0x540E
+#define TIOCGPGRP      0x540F
+#define TIOCSPGRP      0x5410
+#define TIOCOUTQ       0x5411
+#define TIOCSTI                0x5412
+#define TIOCGWINSZ     0x5413
+#define TIOCSWINSZ     0x5414
+#define TIOCMGET       0x5415
+#define TIOCMBIS       0x5416
+#define TIOCMBIC       0x5417
+#define TIOCMSET       0x5418
+#define TIOCGSOFTCAR   0x5419
+#define TIOCSSOFTCAR   0x541A
+#define FIONREAD       0x541B
+#define TIOCINQ                FIONREAD
+#define TIOCLINUX      0x541C
+#define TIOCCONS       0x541D
+#define TIOCGSERIAL    0x541E
+#define TIOCSSERIAL    0x541F
+#define TIOCPKT                0x5420
+#define FIONBIO                0x5421
+#define TIOCNOTTY      0x5422
+#define TIOCSETD       0x5423
+#define TIOCGETD       0x5424
+#define TCSBRKP                0x5425  /* Needed for POSIX tcsendbreak() */
+#define TIOCSBRK       0x5427  /* BSD compatibility */
+#define TIOCCBRK       0x5428  /* BSD compatibility */
+#define TIOCGSID       0x5429  /* Return the session ID of FD */
+#define TCGETS2                _IOR('T', 0x2A, struct termios2)
+#define TCSETS2                _IOW('T', 0x2B, struct termios2)
+#define TCSETSW2       _IOW('T', 0x2C, struct termios2)
+#define TCSETSF2       _IOW('T', 0x2D, struct termios2)
+#define TIOCGRS485     0x542E
+#define TIOCSRS485     0x542F
+#define TIOCGPTN       _IOR('T', 0x30, unsigned int) /* Get Pty Number (of pty-mux device) */
+#define TIOCSPTLCK     _IOW('T', 0x31, int)  /* Lock/unlock Pty */
+#define TCGETX         0x5432 /* SYS5 TCGETX compatibility */
+#define TCSETX         0x5433
+#define TCSETXF                0x5434
+#define TCSETXW                0x5435
+
+#define FIONCLEX       0x5450
+#define FIOCLEX                0x5451
+#define FIOASYNC       0x5452
+#define TIOCSERCONFIG  0x5453
+#define TIOCSERGWILD   0x5454
+#define TIOCSERSWILD   0x5455
+#define TIOCGLCKTRMIOS 0x5456
+#define TIOCSLCKTRMIOS 0x5457
+#define TIOCSERGSTRUCT 0x5458 /* For debugging only */
+#define TIOCSERGETLSR   0x5459 /* Get line status register */
+#define TIOCSERGETMULTI 0x545A /* Get multiport config  */
+#define TIOCSERSETMULTI 0x545B /* Set multiport config */
+
+#define TIOCMIWAIT     0x545C  /* wait for a change on serial input line(s) */
+#define TIOCGICOUNT    0x545D  /* read serial port __inline__ interrupt counts */
+
+/*
+ * some architectures define FIOQSIZE as 0x545E, which is used for
+ * TIOCGHAYESESP on others
+ */
+#ifndef FIOQSIZE
+# define TIOCGHAYESESP 0x545E  /* Get Hayes ESP configuration */
+# define TIOCSHAYESESP 0x545F  /* Set Hayes ESP configuration */
+# define FIOQSIZE      0x5460
+#endif
+
+/* Used for packet mode */
+#define TIOCPKT_DATA            0
+#define TIOCPKT_FLUSHREAD       1
+#define TIOCPKT_FLUSHWRITE      2
+#define TIOCPKT_STOP            4
+#define TIOCPKT_START           8
+#define TIOCPKT_NOSTOP         16
+#define TIOCPKT_DOSTOP         32
+
+#define TIOCSER_TEMT   0x01    /* Transmitter physically empty */
+
+#endif /* __ASM_GENERIC_IOCTLS_H */
diff --git a/kern/include/ros/glibc-asm/socket.h b/kern/include/ros/glibc-asm/socket.h
new file mode 100644 (file)
index 0000000..2aa53dd
--- /dev/null
@@ -0,0 +1,67 @@
+#ifndef __ASM_GENERIC_SOCKET_H
+#define __ASM_GENERIC_SOCKET_H
+
+#include <ros/glibc-asm/sockios.h>
+
+/* For setsockopt(2) */
+#define SOL_SOCKET     1
+
+#define SO_DEBUG       1
+#define SO_REUSEADDR   2
+#define SO_TYPE                3
+#define SO_ERROR       4
+#define SO_DONTROUTE   5
+#define SO_BROADCAST   6
+#define SO_SNDBUF      7
+#define SO_RCVBUF      8
+#define SO_SNDBUFFORCE 32
+#define SO_RCVBUFFORCE 33
+#define SO_KEEPALIVE   9
+#define SO_OOBINLINE   10
+#define SO_NO_CHECK    11
+#define SO_PRIORITY    12
+#define SO_LINGER      13
+#define SO_BSDCOMPAT   14
+/* To add :#define SO_REUSEPORT 15 */
+
+#ifndef SO_PASSCRED /* powerpc only differs in these */
+#define SO_PASSCRED    16
+#define SO_PEERCRED    17
+#define SO_RCVLOWAT    18
+#define SO_SNDLOWAT    19
+#define SO_RCVTIMEO    20
+#define SO_SNDTIMEO    21
+#endif
+
+/* Security levels - as per NRL IPv6 - don't actually do anything */
+#define SO_SECURITY_AUTHENTICATION             22
+#define SO_SECURITY_ENCRYPTION_TRANSPORT       23
+#define SO_SECURITY_ENCRYPTION_NETWORK         24
+
+#define SO_BINDTODEVICE        25
+
+/* Socket filtering */
+#define SO_ATTACH_FILTER       26
+#define SO_DETACH_FILTER       27
+
+#define SO_PEERNAME            28
+#define SO_TIMESTAMP           29
+#define SCM_TIMESTAMP          SO_TIMESTAMP
+
+#define SO_ACCEPTCONN          30
+
+#define SO_PEERSEC             31
+#define SO_PASSSEC             34
+#define SO_TIMESTAMPNS         35
+#define SCM_TIMESTAMPNS                SO_TIMESTAMPNS
+
+#define SO_MARK                        36
+
+#define SO_TIMESTAMPING                37
+#define SCM_TIMESTAMPING       SO_TIMESTAMPING
+
+#define SO_PROTOCOL            38
+#define SO_DOMAIN              39
+
+#define SO_RXQ_OVFL             40
+#endif /* __ASM_GENERIC_SOCKET_H */
diff --git a/kern/include/ros/glibc-asm/sockios.h b/kern/include/ros/glibc-asm/sockios.h
new file mode 100644 (file)
index 0000000..9a61a36
--- /dev/null
@@ -0,0 +1,13 @@
+#ifndef __ASM_GENERIC_SOCKIOS_H
+#define __ASM_GENERIC_SOCKIOS_H
+
+/* Socket-level I/O control calls. */
+#define FIOSETOWN      0x8901
+#define SIOCSPGRP      0x8902
+#define FIOGETOWN      0x8903
+#define SIOCGPGRP      0x8904
+#define SIOCATMARK     0x8905
+#define SIOCGSTAMP     0x8906          /* Get stamp (timeval) */
+#define SIOCGSTAMPNS   0x8907          /* Get stamp (timespec) */
+
+#endif /* __ASM_GENERIC_SOCKIOS_H */
index 83d4d41..86b7027 100644 (file)
@@ -22,7 +22,9 @@
 #define SOMEREGION         
 #define SAMEREGION         
 #define DELETES_REGION(r)  
-#define GROUP(g)           
+#ifdef ROS_KERNEL
+# define GROUP(g)           
+#endif
 #define NOGROUP            
 #define SOMEGROUP          
 #define SAMEGROUP          
diff --git a/tools/compilers/gcc-glibc/glibc-2.11.1-ros/nss/Makefile b/tools/compilers/gcc-glibc/glibc-2.11.1-ros/nss/Makefile
deleted file mode 100644 (file)
index 3e2a522..0000000
+++ /dev/null
@@ -1,86 +0,0 @@
-# Copyright (C) 1996-1998,2000-2002,2007,2009 Free Software Foundation, Inc.
-# This file is part of the GNU C Library.
-
-# The GNU C Library is free software; you can redistribute it and/or
-# modify it under the terms of the GNU Lesser General Public
-# License as published by the Free Software Foundation; either
-# version 2.1 of the License, or (at your option) any later version.
-
-# The GNU C Library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-# Lesser General Public License for more details.
-
-# You should have received a copy of the GNU Lesser General Public
-# License along with the GNU C Library; if not, write to the Free
-# Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
-# 02111-1307 USA.
-
-#
-#      Makefile for name service switch.
-#
-subdir := nss
-
-headers                        := nss.h
-distribute             := nsswitch.h XXX-lookup.c getXXbyYY.c getXXbyYY_r.c \
-                          getXXent.c getXXent_r.c databases.def \
-                          nsswitch.conf digits_dots.c function.def
-
-# This is the trivial part which goes into libc itself.
-routines               = nsswitch getnssent getnssent_r digits_dots \
-                         $(addsuffix -lookup,$(databases))
-
-# These are the databases that go through nss dispatch.
-# Caution: if you add a database here, you must add its real name
-# in databases.def, too.
-databases              = proto service hosts network grp pwd rpc ethers \
-                         spwd netgrp key alias sgrp
-
-others                  := #getent
-install-bin             := #getent
-
-tests                  = test-netdb
-xtests                 = bug-erange
-
-include ../Makeconfig
-
-ifeq (yes,$(build-static-nss))
-otherlibs += $(nssobjdir)/libnss_files.a $(resolvobjdir)/libnss_dns.a \
-            $(resolvobjdir)/libresolv.a
-endif
-
-# Specify rules for the nss_* modules.  We have some services.
-services               := #files
-
-extra-libs             = $(services:%=libnss_%)
-# These libraries will be built in the `others' pass rather than
-# the `lib' pass, because they depend on libc.so being built already.
-extra-libs-others      = $(extra-libs)
-
-# The sources are found in the appropriate subdir.
-subdir-dirs = $(services:%=nss_%)
-vpath %.c $(subdir-dirs)
-
-
-libnss_files-routines  := $(addprefix files-,$(databases)) \
-                          files-have_o_cloexec
-distribute             += files-XXX.c files-parse.c
-
-
-# Build static module if requested
-ifneq ($(build-static-nss),yes)
-libnss_files-inhibit-o = $(filter-out .os,$(object-suffixes))
-endif
-
-include ../Rules
-
-
-ifeq (yes,$(build-static-nss))
-$(objpfx)getent: $(objpfx)libnss_files.a
-endif
-
-# Depend on libc.so so a DT_NEEDED is generated in the shared objects.
-# This ensures they will load libc.so for needed symbols if loaded by
-# a statically-linked program that hasn't already loaded it.
-$(services:%=$(objpfx)libnss_%.so): $(common-objpfx)libc.so \
-                                   $(common-objpfx)libc_nonshared.a
index 166bbdc..3816eda 100644 (file)
@@ -3,3 +3,9 @@ CPPFLAGS += -DHAVE_MUNMAP=1
 CPPFLAGS += -D_LIBC_REENTRANT=1
 CPPFLAGS += -D_IO_MTSAFE_IO=1
 
+# Any sysdep .c file you want needs to be added here, if it's not somewhere
+# else already.  Many posix-ish .c files already are taken care of.  We also
+# need to be careful to only include some of them for specific subdirs.
+ifeq ($(subdir),socket)
+sysdep_routines += sa_len
+endif
diff --git a/tools/compilers/gcc-glibc/glibc-2.11.1-ros/sysdeps/ros/Subdirs b/tools/compilers/gcc-glibc/glibc-2.11.1-ros/sysdeps/ros/Subdirs
new file mode 100644 (file)
index 0000000..3c439a6
--- /dev/null
@@ -0,0 +1,8 @@
+nss
+inet
+resolv
+sunrpc
+nis
+nscd
+streams
+login
diff --git a/tools/compilers/gcc-glibc/glibc-2.11.1-ros/sysdeps/ros/bits/ioctls.h b/tools/compilers/gcc-glibc/glibc-2.11.1-ros/sysdeps/ros/bits/ioctls.h
new file mode 100644 (file)
index 0000000..fa6851b
--- /dev/null
@@ -0,0 +1,112 @@
+/* Copyright (C) 1996, 1997, 1998, 2003 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#ifndef _SYS_IOCTL_H
+# error "Never use <bits/ioctls.h> directly; include <sys/ioctl.h> instead."
+#endif
+
+/* ROS note: we're including this file from the linux port.  We changed the asm
+ * include to ros/glibc-asm. */
+
+/* Use the definitions from the kernel header files.  */
+#include <ros/glibc-asm/ioctls.h>
+
+/* Routing table calls.  */
+#define SIOCADDRT      0x890B          /* add routing table entry      */
+#define SIOCDELRT      0x890C          /* delete routing table entry   */
+#define SIOCRTMSG      0x890D          /* call to routing system       */
+
+/* Socket configuration controls. */
+#define SIOCGIFNAME    0x8910          /* get iface name               */
+#define SIOCSIFLINK    0x8911          /* set iface channel            */
+#define SIOCGIFCONF    0x8912          /* get iface list               */
+#define SIOCGIFFLAGS   0x8913          /* get flags                    */
+#define SIOCSIFFLAGS   0x8914          /* set flags                    */
+#define SIOCGIFADDR    0x8915          /* get PA address               */
+#define SIOCSIFADDR    0x8916          /* set PA address               */
+#define SIOCGIFDSTADDR 0x8917          /* get remote PA address        */
+#define SIOCSIFDSTADDR 0x8918          /* set remote PA address        */
+#define SIOCGIFBRDADDR 0x8919          /* get broadcast PA address     */
+#define SIOCSIFBRDADDR 0x891a          /* set broadcast PA address     */
+#define SIOCGIFNETMASK 0x891b          /* get network PA mask          */
+#define SIOCSIFNETMASK 0x891c          /* set network PA mask          */
+#define SIOCGIFMETRIC  0x891d          /* get metric                   */
+#define SIOCSIFMETRIC  0x891e          /* set metric                   */
+#define SIOCGIFMEM     0x891f          /* get memory address (BSD)     */
+#define SIOCSIFMEM     0x8920          /* set memory address (BSD)     */
+#define SIOCGIFMTU     0x8921          /* get MTU size                 */
+#define SIOCSIFMTU     0x8922          /* set MTU size                 */
+#define SIOCSIFNAME    0x8923          /* set interface name           */
+#define        SIOCSIFHWADDR   0x8924          /* set hardware address         */
+#define SIOCGIFENCAP   0x8925          /* get/set encapsulations       */
+#define SIOCSIFENCAP   0x8926
+#define SIOCGIFHWADDR  0x8927          /* Get hardware address         */
+#define SIOCGIFSLAVE   0x8929          /* Driver slaving support       */
+#define SIOCSIFSLAVE   0x8930
+#define SIOCADDMULTI   0x8931          /* Multicast address lists      */
+#define SIOCDELMULTI   0x8932
+#define SIOCGIFINDEX   0x8933          /* name -> if_index mapping     */
+#define SIOGIFINDEX    SIOCGIFINDEX    /* misprint compatibility :-)   */
+#define SIOCSIFPFLAGS  0x8934          /* set/get extended flags set   */
+#define SIOCGIFPFLAGS  0x8935
+#define SIOCDIFADDR    0x8936          /* delete PA address            */
+#define        SIOCSIFHWBROADCAST      0x8937  /* set hardware broadcast addr  */
+#define SIOCGIFCOUNT   0x8938          /* get number of devices */
+
+#define SIOCGIFBR      0x8940          /* Bridging support             */
+#define SIOCSIFBR      0x8941          /* Set bridging options         */
+
+#define SIOCGIFTXQLEN  0x8942          /* Get the tx queue length      */
+#define SIOCSIFTXQLEN  0x8943          /* Set the tx queue length      */
+
+
+/* ARP cache control calls. */
+                   /*  0x8950 - 0x8952  * obsolete calls, don't re-use */
+#define SIOCDARP       0x8953          /* delete ARP table entry       */
+#define SIOCGARP       0x8954          /* get ARP table entry          */
+#define SIOCSARP       0x8955          /* set ARP table entry          */
+
+/* RARP cache control calls. */
+#define SIOCDRARP      0x8960          /* delete RARP table entry      */
+#define SIOCGRARP      0x8961          /* get RARP table entry         */
+#define SIOCSRARP      0x8962          /* set RARP table entry         */
+
+/* Driver configuration calls */
+
+#define SIOCGIFMAP     0x8970          /* Get device parameters        */
+#define SIOCSIFMAP     0x8971          /* Set device parameters        */
+
+/* DLCI configuration calls */
+
+#define SIOCADDDLCI    0x8980          /* Create new DLCI device       */
+#define SIOCDELDLCI    0x8981          /* Delete DLCI device           */
+
+/* Device private ioctl calls.  */
+
+/* These 16 ioctls are available to devices via the do_ioctl() device
+   vector.  Each device should include this file and redefine these
+   names as their own. Because these are device dependent it is a good
+   idea _NOT_ to issue them to random objects and hope.  */
+
+#define SIOCDEVPRIVATE                 0x89F0  /* to 89FF */
+
+/*
+ *     These 16 ioctl calls are protocol private
+ */
+
+#define SIOCPROTOPRIVATE 0x89E0 /* to 89EF */
index 23a3f8d..7ff00b9 100644 (file)
@@ -1,5 +1,6 @@
-/* System-specific socket constants and types.  Generic/4.3 BSD version.
-   Copyright (C) 1991,92,1994-1999,2000,2001 Free Software Foundation, Inc.
+/* System-specific socket constants and types.  Linux version.
+   Copyright (C) 1991, 1992, 1994-2001, 2004, 2006, 2007, 2008, 2009
+   Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
    The GNU C Library is free software; you can redistribute it and/or
    02111-1307 USA.  */
 
 #ifndef __BITS_SOCKET_H
-#define __BITS_SOCKET_H        1
+#define __BITS_SOCKET_H
 
-struct cmsghdr
-{
-};
-
-#if !defined _SYS_SOCKET_H && !defined _NETINET_IN_H
+#ifndef _SYS_SOCKET_H
 # error "Never include <bits/socket.h> directly; use <sys/socket.h> instead."
 #endif
 
-#include <limits.h>
-#include <bits/types.h>
+/* ROS note: we're including this file from the linux port.  We changed the asm
+ * include to ros/glibc-asm. */
 
 #define        __need_size_t
 #include <stddef.h>
 
+#include <sys/types.h>
+
 /* Type for length arguments in socket calls.  */
 #ifndef __socklen_t_defined
 typedef __socklen_t socklen_t;
 # define __socklen_t_defined
 #endif
 
-
 /* Types of sockets.  */
 enum __socket_type
 {
@@ -54,43 +52,67 @@ enum __socket_type
 #define SOCK_RAW SOCK_RAW
   SOCK_RDM = 4,                        /* Reliably-delivered messages.  */
 #define SOCK_RDM SOCK_RDM
-  SOCK_SEQPACKET = 5           /* Sequenced, reliable, connection-based,
+  SOCK_SEQPACKET = 5,          /* Sequenced, reliable, connection-based,
                                   datagrams of fixed maximum length.  */
 #define SOCK_SEQPACKET SOCK_SEQPACKET
+  SOCK_DCCP = 6,               /* Datagram Congestion Control Protocol.  */
+#define SOCK_DCCP SOCK_DCCP
+  SOCK_PACKET = 10,            /* Linux specific way of getting packets
+                                  at the dev level.  For writing rarp and
+                                  other similar things on the user level. */
+#define SOCK_PACKET SOCK_PACKET
+
+  /* Flags to be ORed into the type parameter of socket and socketpair and
+     used for the flags parameter of paccept.  */
+
+  SOCK_CLOEXEC = 02000000,     /* Atomically set close-on-exec flag for the
+                                  new descriptor(s).  */
+#define SOCK_CLOEXEC SOCK_CLOEXEC
+  SOCK_NONBLOCK = 04000                /* Atomically mark descriptor(s) as
+                                  non-blocking.  */
+#define SOCK_NONBLOCK SOCK_NONBLOCK
 };
 
 /* Protocol families.  */
 #define        PF_UNSPEC       0       /* Unspecified.  */
 #define        PF_LOCAL        1       /* Local to host (pipes and file-domain).  */
-#define        PF_UNIX         PF_LOCAL /* Old BSD name for PF_LOCAL.  */
-#define        PF_FILE         PF_LOCAL /* POSIX name for PF_LOCAL.  */
+#define        PF_UNIX         PF_LOCAL /* POSIX name for PF_LOCAL.  */
+#define        PF_FILE         PF_LOCAL /* Another non-standard name for PF_LOCAL.  */
 #define        PF_INET         2       /* IP protocol family.  */
-#define        PF_IMPLINK      3       /* ARPAnet IMP protocol.  */
-#define        PF_PUP          4       /* PUP protocols.  */
-#define        PF_CHAOS        5       /* MIT Chaos protocols.  */
-#define        PF_NS           6       /* Xerox NS protocols.  */
-#define        PF_ISO          7       /* ISO protocols.  */
-#define        PF_OSI          PF_ISO
-#define        PF_ECMA         8       /* ECMA protocols.  */
-#define        PF_DATAKIT      9       /* AT&T Datakit protocols.  */
-#define        PF_CCITT        10      /* CCITT protocols (X.25 et al).  */
-#define        PF_SNA          11      /* IBM SNA protocol.  */
-#define        PF_DECnet       12      /* DECnet protocols.  */
-#define        PF_DLI          13      /* Direct data link interface.  */
-#define        PF_LAT          14      /* DEC Local Area Transport protocol.  */
-#define        PF_HYLINK       15      /* NSC Hyperchannel protocol.  */
-#define        PF_APPLETALK    16      /* Don't use this.  */
-#define        PF_ROUTE        17      /* Internal Routing Protocol.  */
-#define        PF_LINK         18      /* Link layer interface.  */
-#define        PF_XTP          19      /* eXpress Transfer Protocol (no AF).  */
-#define        PF_COIP         20      /* Connection-oriented IP, aka ST II.  */
-#define        PF_CNT          21      /* Computer Network Technology.  */
-#define PF_RTIP                22      /* Help Identify RTIP packets.  **/
-#define        PF_IPX          23      /* Novell Internet Protocol.  */
-#define        PF_SIP          24      /* Simple Internet Protocol.  */
-#define PF_PIP         25      /* Help Identify PIP packets.  */
-#define PF_INET6       26      /* IP version 6.  */
-#define        PF_MAX          27
+#define        PF_AX25         3       /* Amateur Radio AX.25.  */
+#define        PF_IPX          4       /* Novell Internet Protocol.  */
+#define        PF_APPLETALK    5       /* Appletalk DDP.  */
+#define        PF_NETROM       6       /* Amateur radio NetROM.  */
+#define        PF_BRIDGE       7       /* Multiprotocol bridge.  */
+#define        PF_ATMPVC       8       /* ATM PVCs.  */
+#define        PF_X25          9       /* Reserved for X.25 project.  */
+#define        PF_INET6        10      /* IP version 6.  */
+#define        PF_ROSE         11      /* Amateur Radio X.25 PLP.  */
+#define        PF_DECnet       12      /* Reserved for DECnet project.  */
+#define        PF_NETBEUI      13      /* Reserved for 802.2LLC project.  */
+#define        PF_SECURITY     14      /* Security callback pseudo AF.  */
+#define        PF_KEY          15      /* PF_KEY key management API.  */
+#define        PF_NETLINK      16
+#define        PF_ROUTE        PF_NETLINK /* Alias to emulate 4.4BSD.  */
+#define        PF_PACKET       17      /* Packet family.  */
+#define        PF_ASH          18      /* Ash.  */
+#define        PF_ECONET       19      /* Acorn Econet.  */
+#define        PF_ATMSVC       20      /* ATM SVCs.  */
+#define PF_RDS         21      /* RDS sockets.  */
+#define        PF_SNA          22      /* Linux SNA Project */
+#define        PF_IRDA         23      /* IRDA sockets.  */
+#define        PF_PPPOX        24      /* PPPoX sockets.  */
+#define        PF_WANPIPE      25      /* Wanpipe API sockets.  */
+#define PF_LLC         26      /* Linux LLC.  */
+#define PF_CAN         29      /* Controller Area Network.  */
+#define PF_TIPC                30      /* TIPC sockets.  */
+#define        PF_BLUETOOTH    31      /* Bluetooth sockets.  */
+#define        PF_IUCV         32      /* IUCV sockets.  */
+#define PF_RXRPC       33      /* RxRPC sockets.  */
+#define PF_ISDN                34      /* mISDN sockets.  */
+#define PF_PHONET      35      /* Phonet sockets.  */
+#define PF_IEEE802154  36      /* IEEE 802.15.4 sockets.  */
+#define        PF_MAX          37      /* For now..  */
 
 /* Address families.  */
 #define        AF_UNSPEC       PF_UNSPEC
@@ -98,33 +120,55 @@ enum __socket_type
 #define        AF_UNIX         PF_UNIX
 #define        AF_FILE         PF_FILE
 #define        AF_INET         PF_INET
-#define        AF_IMPLINK      PF_IMPLINK
-#define        AF_PUP          PF_PUP
-#define        AF_CHAOS        PF_CHAOS
-#define        AF_NS           PF_NS
-#define        AF_ISO          PF_ISO
-#define        AF_OSI          PF_OSI
-#define        AF_ECMA         PF_ECMA
-#define        AF_DATAKIT      PF_DATAKIT
-#define        AF_CCITT        PF_CCITT
-#define        AF_SNA          PF_SNA
-#define        AF_DECnet       PF_DECnet
-#define        AF_DLI          PF_DLI
-#define        AF_LAT          PF_LAT
-#define        AF_HYLINK       PF_HYLINK
+#define        AF_AX25         PF_AX25
+#define        AF_IPX          PF_IPX
 #define        AF_APPLETALK    PF_APPLETALK
+#define        AF_NETROM       PF_NETROM
+#define        AF_BRIDGE       PF_BRIDGE
+#define        AF_ATMPVC       PF_ATMPVC
+#define        AF_X25          PF_X25
+#define        AF_INET6        PF_INET6
+#define        AF_ROSE         PF_ROSE
+#define        AF_DECnet       PF_DECnet
+#define        AF_NETBEUI      PF_NETBEUI
+#define        AF_SECURITY     PF_SECURITY
+#define        AF_KEY          PF_KEY
+#define        AF_NETLINK      PF_NETLINK
 #define        AF_ROUTE        PF_ROUTE
-#define        AF_LINK         PF_LINK
-#define        pseudo_AF_XTP   PF_XTP
-#define        AF_COIP         PF_COIP
-#define        AF_CNT          PF_CNT
-#define pseudo_AF_RTIP PF_RTIP
-#define        AF_IPX          PF_IPX
-#define        AF_SIP          PF_SIP
-#define pseudo_AF_PIP  PF_PIP
-#define AF_INET6       PF_INET6
+#define        AF_PACKET       PF_PACKET
+#define        AF_ASH          PF_ASH
+#define        AF_ECONET       PF_ECONET
+#define        AF_ATMSVC       PF_ATMSVC
+#define AF_RDS         PF_RDS
+#define        AF_SNA          PF_SNA
+#define        AF_IRDA         PF_IRDA
+#define        AF_PPPOX        PF_PPPOX
+#define        AF_WANPIPE      PF_WANPIPE
+#define AF_LLC         PF_LLC
+#define AF_CAN         PF_CAN
+#define AF_TIPC                PF_TIPC
+#define        AF_BLUETOOTH    PF_BLUETOOTH
+#define        AF_IUCV         PF_IUCV
+#define AF_RXRPC       PF_RXRPC
+#define AF_ISDN                PF_ISDN
+#define AF_PHONET      PF_PHONET
+#define AF_IEEE802154  PF_IEEE802154
 #define        AF_MAX          PF_MAX
 
+/* Socket level values.  Others are defined in the appropriate headers.
+
+   XXX These definitions also should go into the appropriate headers as
+   far as they are available.  */
+#define SOL_RAW                255
+#define SOL_DECNET      261
+#define SOL_X25         262
+#define SOL_PACKET     263
+#define SOL_ATM                264     /* ATM layer (cell level).  */
+#define SOL_AAL                265     /* ATM Adaption Layer (packet level).  */
+#define SOL_IRDA       266
+
+/* Maximum queue length specifiable by listen.  */
+#define SOMAXCONN      128
 
 /* Get the definition of the macro to define the common sockaddr members.  */
 #include <bits/sockaddr.h>
@@ -139,11 +183,7 @@ struct sockaddr
 
 /* Structure large enough to hold any socket address (with the historical
    exception of AF_UNIX).  We reserve 128 bytes.  */
-#if ULONG_MAX > 0xffffffff
-# define __ss_aligntype        __uint64_t
-#else
-# define __ss_aligntype        __uint32_t
-#endif
+#define __ss_aligntype unsigned long int
 #define _SS_SIZE       128
 #define _SS_PADSIZE    (_SS_SIZE - (2 * sizeof (__ss_aligntype)))
 
@@ -159,21 +199,47 @@ struct sockaddr_storage
 enum
   {
     MSG_OOB            = 0x01, /* Process out-of-band data.  */
-#define MSG_OOB MSG_OOB
+#define MSG_OOB                MSG_OOB
     MSG_PEEK           = 0x02, /* Peek at incoming messages.  */
-#define MSG_PEEK MSG_PEEK
+#define MSG_PEEK       MSG_PEEK
     MSG_DONTROUTE      = 0x04, /* Don't use local routing.  */
-#define MSG_DONTROUTE MSG_DONTROUTE
-    MSG_EOR            = 0x08, /* Data completes record.  */
-#define MSG_EOR MSG_EOR
-    MSG_TRUNC          = 0x10, /* Data discarded before delivery.  */
-#define MSG_TRUNC MSG_TRUNC
-    MSG_CTRUNC         = 0x20, /* Control data lost before delivery.  */
-#define MSG_CTRUNC MSG_CTRUNC
-    MSG_WAITALL                = 0x40, /* Wait for full request or error.  */
-#define MSG_WAITALL MSG_WAITALL
-    MSG_DONTWAIT       = 0x80  /* This message should be nonblocking.  */
-#define MSG_DONTWAIT MSG_DONTWAIT
+#define MSG_DONTROUTE  MSG_DONTROUTE
+#ifdef __USE_GNU
+    /* DECnet uses a different name.  */
+    MSG_TRYHARD                = MSG_DONTROUTE,
+# define MSG_TRYHARD   MSG_DONTROUTE
+#endif
+    MSG_CTRUNC         = 0x08, /* Control data lost before delivery.  */
+#define MSG_CTRUNC     MSG_CTRUNC
+    MSG_PROXY          = 0x10, /* Supply or ask second address.  */
+#define MSG_PROXY      MSG_PROXY
+    MSG_TRUNC          = 0x20,
+#define        MSG_TRUNC       MSG_TRUNC
+    MSG_DONTWAIT       = 0x40, /* Nonblocking IO.  */
+#define        MSG_DONTWAIT    MSG_DONTWAIT
+    MSG_EOR            = 0x80, /* End of record.  */
+#define        MSG_EOR         MSG_EOR
+    MSG_WAITALL                = 0x100, /* Wait for a full request.  */
+#define        MSG_WAITALL     MSG_WAITALL
+    MSG_FIN            = 0x200,
+#define        MSG_FIN         MSG_FIN
+    MSG_SYN            = 0x400,
+#define        MSG_SYN         MSG_SYN
+    MSG_CONFIRM                = 0x800, /* Confirm path validity.  */
+#define        MSG_CONFIRM     MSG_CONFIRM
+    MSG_RST            = 0x1000,
+#define        MSG_RST         MSG_RST
+    MSG_ERRQUEUE       = 0x2000, /* Fetch message from error queue.  */
+#define        MSG_ERRQUEUE    MSG_ERRQUEUE
+    MSG_NOSIGNAL       = 0x4000, /* Do not generate SIGPIPE.  */
+#define        MSG_NOSIGNAL    MSG_NOSIGNAL
+    MSG_MORE           = 0x8000,  /* Sender will send more.  */
+#define        MSG_MORE        MSG_MORE
+
+    MSG_CMSG_CLOEXEC   = 0x40000000    /* Set close_on_exit for file
+                                           descriptor received through
+                                           SCM_RIGHTS.  */
+#define MSG_CMSG_CLOEXEC MSG_CMSG_CLOEXEC
   };
 
 
@@ -181,70 +247,158 @@ enum
    `sendmsg' and received by `recvmsg'.  */
 struct msghdr
   {
-    __ptr_t msg_name;          /* Address to send to/receive from.  */
+    void *msg_name;            /* Address to send to/receive from.  */
     socklen_t msg_namelen;     /* Length of address data.  */
 
     struct iovec *msg_iov;     /* Vector of data to send/receive into.  */
-    int msg_iovlen;            /* Number of elements in the vector.  */
+    size_t msg_iovlen;         /* Number of elements in the vector.  */
 
-    __ptr_t msg_accrights;     /* Access rights information.  */
-    socklen_t msg_accrightslen;        /* Length of access rights information.  */
+    void *msg_control;         /* Ancillary data (eg BSD filedesc passing). */
+    size_t msg_controllen;     /* Ancillary data buffer length.
+                                  !! The type should be socklen_t but the
+                                  definition of the kernel is incompatible
+                                  with this.  */
 
-    int msg_flags;             /* Flags in received message.  */
+    int msg_flags;             /* Flags on received message.  */
   };
 
+/* Structure used for storage of ancillary data object information.  */
+struct cmsghdr
+  {
+    size_t cmsg_len;           /* Length of data in cmsg_data plus length
+                                  of cmsghdr structure.
+                                  !! The type should be socklen_t but the
+                                  definition of the kernel is incompatible
+                                  with this.  */
+    int cmsg_level;            /* Originating protocol.  */
+    int cmsg_type;             /* Protocol specific type.  */
+#if (!defined __STRICT_ANSI__ && __GNUC__ >= 2) || __STDC_VERSION__ >= 199901L
+    __extension__ unsigned char __cmsg_data __flexarr; /* Ancillary data.  */
+#endif
+  };
+
+/* Ancillary data object manipulation macros.  */
+#if (!defined __STRICT_ANSI__ && __GNUC__ >= 2) || __STDC_VERSION__ >= 199901L
+# define CMSG_DATA(cmsg) ((cmsg)->__cmsg_data)
+#else
+# define CMSG_DATA(cmsg) ((unsigned char *) ((struct cmsghdr *) (cmsg) + 1))
+#endif
+#define CMSG_NXTHDR(mhdr, cmsg) __cmsg_nxthdr (mhdr, cmsg)
+#define CMSG_FIRSTHDR(mhdr) \
+  ((size_t) (mhdr)->msg_controllen >= sizeof (struct cmsghdr)                \
+   ? (struct cmsghdr *) (mhdr)->msg_control : (struct cmsghdr *) 0)
+#define CMSG_ALIGN(len) (((len) + sizeof (size_t) - 1) \
+                        & (size_t) ~(sizeof (size_t) - 1))
+#define CMSG_SPACE(len) (CMSG_ALIGN (len) \
+                        + CMSG_ALIGN (sizeof (struct cmsghdr)))
+#define CMSG_LEN(len)   (CMSG_ALIGN (sizeof (struct cmsghdr)) + (len))
 
-/* Protocol number used to manipulate socket-level options
-   with `getsockopt' and `setsockopt'.  */
-#define        SOL_SOCKET      0xffff
+extern struct cmsghdr *__cmsg_nxthdr (struct msghdr *__mhdr,
+                                     struct cmsghdr *__cmsg) __THROW;
+#ifdef __USE_EXTERN_INLINES
+# ifndef _EXTERN_INLINE
+#  define _EXTERN_INLINE __extern_inline
+# endif
+_EXTERN_INLINE struct cmsghdr *
+__NTH (__cmsg_nxthdr (struct msghdr *__mhdr, struct cmsghdr *__cmsg))
+{
+  if ((size_t) __cmsg->cmsg_len < sizeof (struct cmsghdr))
+    /* The kernel header does this so there may be a reason.  */
+    return 0;
 
-/* Socket-level options for `getsockopt' and `setsockopt'.  */
+  __cmsg = (struct cmsghdr *) ((unsigned char *) __cmsg
+                              + CMSG_ALIGN (__cmsg->cmsg_len));
+  if ((unsigned char *) (__cmsg + 1) > ((unsigned char *) __mhdr->msg_control
+                                       + __mhdr->msg_controllen)
+      || ((unsigned char *) __cmsg + CMSG_ALIGN (__cmsg->cmsg_len)
+         > ((unsigned char *) __mhdr->msg_control + __mhdr->msg_controllen)))
+    /* No more entries.  */
+    return 0;
+  return __cmsg;
+}
+#endif /* Use `extern inline'.  */
+
+/* Socket level message types.  This must match the definitions in
+   <linux/socket.h>.  */
 enum
   {
-    SO_DEBUG = 0x0001,         /* Record debugging information.  */
-#define SO_DEBUG SO_DEBUG
-    SO_ACCEPTCONN = 0x0002,    /* Accept connections on socket.  */
-#define SO_ACCEPTCONN SO_ACCEPTCONN
-    SO_REUSEADDR = 0x0004,     /* Allow reuse of local addresses.  */
-#define SO_REUSEADDR SO_REUSEADDR
-    SO_KEEPALIVE = 0x0008,     /* Keep connections alive and send
-                                  SIGPIPE when they die.  */
-#define SO_KEEPALIVE SO_KEEPALIVE
-    SO_DONTROUTE = 0x0010,     /* Don't do local routing.  */
-#define SO_DONTROUTE SO_DONTROUTE
-    SO_BROADCAST = 0x0020,     /* Allow transmission of
-                                  broadcast messages.  */
-#define SO_BROADCAST SO_BROADCAST
-    SO_USELOOPBACK = 0x0040,   /* Use the software loopback to avoid
-                                  hardware use when possible.  */
-#define SO_USELOOPBACK SO_USELOOPBACK
-    SO_LINGER = 0x0080,                /* Block on close of a reliable
-                                  socket to transmit pending data.  */
-#define SO_LINGER SO_LINGER
-    SO_OOBINLINE = 0x0100,     /* Receive out-of-band data in-band.  */
-#define SO_OOBINLINE SO_OOBINLINE
-    SO_REUSEPORT = 0x0200,     /* Allow local address and port reuse.  */
-#define SO_REUSEPORT SO_REUSEPORT
-    SO_SNDBUF = 0x1001,                /* Send buffer size.  */
-#define SO_SNDBUF SO_SNDBUF
-    SO_RCVBUF = 0x1002,                /* Receive buffer.  */
-#define SO_RCVBUF SO_RCVBUF
-    SO_SNDLOWAT = 0x1003,      /* Send low-water mark.  */
-#define SO_SNDLOWAT SO_SNDLOWAT
-    SO_RCVLOWAT = 0x1004,      /* Receive low-water mark.  */
-#define SO_RCVLOWAT SO_RCVLOWAT
-    SO_SNDTIMEO = 0x1005,      /* Send timeout.  */
-#define SO_SNDTIMEO SO_SNDTIMEO
-    SO_RCVTIMEO = 0x1006,      /* Receive timeout.  */
-#define SO_RCVTIMEO SO_RCVTIMEO
-    SO_ERROR = 0x1007,         /* Get and clear error status.  */
-#define SO_ERROR SO_ERROR
-    SO_STYLE = 0x1008,         /* Get socket connection style.  */
-#define SO_STYLE SO_STYLE
-    SO_TYPE = SO_STYLE         /* Compatible name for SO_STYLE.  */
-#define SO_TYPE SO_TYPE
+    SCM_RIGHTS = 0x01          /* Transfer file descriptors.  */
+#define SCM_RIGHTS SCM_RIGHTS
+#ifdef __USE_GNU
+    , SCM_CREDENTIALS = 0x02   /* Credentials passing.  */
+# define SCM_CREDENTIALS SCM_CREDENTIALS
+#endif
   };
 
+#ifdef __USE_GNU
+/* User visible structure for SCM_CREDENTIALS message */
+struct ucred
+{
+  pid_t pid;                   /* PID of sending process.  */
+  uid_t uid;                   /* UID of sending process.  */
+  gid_t gid;                   /* GID of sending process.  */
+};
+#endif
+
+/* Ugly workaround for unclean kernel headers.  */
+#if !defined __USE_MISC && !defined __USE_GNU
+# ifndef FIOGETOWN
+#  define __SYS_SOCKET_H_undef_FIOGETOWN
+# endif
+# ifndef FIOSETOWN
+#  define __SYS_SOCKET_H_undef_FIOSETOWN
+# endif
+# ifndef SIOCATMARK
+#  define __SYS_SOCKET_H_undef_SIOCATMARK
+# endif
+# ifndef SIOCGPGRP
+#  define __SYS_SOCKET_H_undef_SIOCGPGRP
+# endif
+# ifndef SIOCGSTAMP
+#  define __SYS_SOCKET_H_undef_SIOCGSTAMP
+# endif
+# ifndef SIOCGSTAMPNS
+#  define __SYS_SOCKET_H_undef_SIOCGSTAMPNS
+# endif
+# ifndef SIOCSPGRP
+#  define __SYS_SOCKET_H_undef_SIOCSPGRP
+# endif
+#endif
+
+/* Get socket manipulation related informations from kernel headers.  */
+#include <ros/glibc-asm/socket.h>
+
+#if !defined __USE_MISC && !defined __USE_GNU
+# ifdef __SYS_SOCKET_H_undef_FIOGETOWN
+#  undef __SYS_SOCKET_H_undef_FIOGETOWN
+#  undef FIOGETOWN
+# endif
+# ifdef __SYS_SOCKET_H_undef_FIOSETOWN
+#  undef __SYS_SOCKET_H_undef_FIOSETOWN
+#  undef FIOSETOWN
+# endif
+# ifdef __SYS_SOCKET_H_undef_SIOCATMARK
+#  undef __SYS_SOCKET_H_undef_SIOCATMARK
+#  undef SIOCATMARK
+# endif
+# ifdef __SYS_SOCKET_H_undef_SIOCGPGRP
+#  undef __SYS_SOCKET_H_undef_SIOCGPGRP
+#  undef SIOCGPGRP
+# endif
+# ifdef __SYS_SOCKET_H_undef_SIOCGSTAMP
+#  undef __SYS_SOCKET_H_undef_SIOCGSTAMP
+#  undef SIOCGSTAMP
+# endif
+# ifdef __SYS_SOCKET_H_undef_SIOCGSTAMPNS
+#  undef __SYS_SOCKET_H_undef_SIOCGSTAMPNS
+#  undef SIOCGSTAMPNS
+# endif
+# ifdef __SYS_SOCKET_H_undef_SIOCSPGRP
+#  undef __SYS_SOCKET_H_undef_SIOCSPGRP
+#  undef SIOCSPGRP
+# endif
+#endif
+
 /* Structure used to manipulate the SO_LINGER option.  */
 struct linger
   {
diff --git a/tools/compilers/gcc-glibc/glibc-2.11.1-ros/sysdeps/ros/bits/utmp.h b/tools/compilers/gcc-glibc/glibc-2.11.1-ros/sysdeps/ros/bits/utmp.h
new file mode 100644 (file)
index 0000000..e855ad7
--- /dev/null
@@ -0,0 +1,125 @@
+/* The `struct utmp' type, describing entries in the utmp file.  GNU version.
+   Copyright (C) 1993, 1996, 1997, 1998, 1999, 2002
+   Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#ifndef _UTMP_H
+# error "Never include <bits/utmp.h> directly; use <utmp.h> instead."
+#endif
+
+#include <paths.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <bits/wordsize.h>
+
+
+#define UT_LINESIZE    32
+#define UT_NAMESIZE    32
+#define UT_HOSTSIZE    256
+
+
+/* The structure describing an entry in the database of
+   previous logins.  */
+struct lastlog
+  {
+#if __WORDSIZE == 64 && defined __WORDSIZE_COMPAT32
+    int32_t ll_time;
+#else
+    __time_t ll_time;
+#endif
+    char ll_line[UT_LINESIZE];
+    char ll_host[UT_HOSTSIZE];
+  };
+
+
+/* The structure describing the status of a terminated process.  This
+   type is used in `struct utmp' below.  */
+struct exit_status
+  {
+    short int e_termination;   /* Process termination status.  */
+    short int e_exit;          /* Process exit status.  */
+  };
+
+
+/* The structure describing an entry in the user accounting database.  */
+struct utmp
+{
+  short int ut_type;           /* Type of login.  */
+  pid_t ut_pid;                        /* Process ID of login process.  */
+  char ut_line[UT_LINESIZE];   /* Devicename.  */
+  char ut_id[4];               /* Inittab ID.  */
+  char ut_user[UT_NAMESIZE];   /* Username.  */
+  char ut_host[UT_HOSTSIZE];   /* Hostname for remote login.  */
+  struct exit_status ut_exit;  /* Exit status of a process marked
+                                  as DEAD_PROCESS.  */
+/* The ut_session and ut_tv fields must be the same size when compiled
+   32- and 64-bit.  This allows data files and shared memory to be
+   shared between 32- and 64-bit applications.  */
+#if __WORDSIZE == 64 && defined __WORDSIZE_COMPAT32
+  int32_t ut_session;          /* Session ID, used for windowing.  */
+  struct
+  {
+    int32_t tv_sec;            /* Seconds.  */
+    int32_t tv_usec;           /* Microseconds.  */
+  } ut_tv;                     /* Time entry was made.  */
+#else
+  long int ut_session;         /* Session ID, used for windowing.  */
+  struct timeval ut_tv;                /* Time entry was made.  */
+#endif
+
+  int32_t ut_addr_v6[4];       /* Internet address of remote host.  */
+  char __unused[20];           /* Reserved for future use.  */
+};
+
+/* Backwards compatibility hacks.  */
+#define ut_name                ut_user
+#ifndef _NO_UT_TIME
+/* We have a problem here: `ut_time' is also used otherwise.  Define
+   _NO_UT_TIME if the compiler complains.  */
+# define ut_time       ut_tv.tv_sec
+#endif
+#define ut_xtime       ut_tv.tv_sec
+#define ut_addr                ut_addr_v6[0]
+
+
+/* Values for the `ut_type' field of a `struct utmp'.  */
+#define EMPTY          0       /* No valid user accounting information.  */
+
+#define RUN_LVL                1       /* The system's runlevel.  */
+#define BOOT_TIME      2       /* Time of system boot.  */
+#define NEW_TIME       3       /* Time after system clock changed.  */
+#define OLD_TIME       4       /* Time when system clock changed.  */
+
+#define INIT_PROCESS   5       /* Process spawned by the init process.  */
+#define LOGIN_PROCESS  6       /* Session leader of a logged in user.  */
+#define USER_PROCESS   7       /* Normal process.  */
+#define DEAD_PROCESS   8       /* Terminated process.  */
+
+#define ACCOUNTING     9
+
+/* Old Linux name for the EMPTY type.  */
+#define UT_UNKNOWN     EMPTY
+
+
+/* Tell the user that we have a modern system with UT_HOST, UT_PID,
+   UT_TYPE, UT_ID and UT_TV fields.  */
+#define _HAVE_UT_TYPE  1
+#define _HAVE_UT_PID   1
+#define _HAVE_UT_ID    1
+#define _HAVE_UT_TV    1
+#define _HAVE_UT_HOST  1
diff --git a/tools/compilers/gcc-glibc/glibc-2.11.1-ros/sysdeps/ros/check_native.c b/tools/compilers/gcc-glibc/glibc-2.11.1-ros/sysdeps/ros/check_native.c
new file mode 100644 (file)
index 0000000..6ee356f
--- /dev/null
@@ -0,0 +1,181 @@
+/* Determine whether interfaces use native transport.  Linux version.
+   Copyright (C) 2007 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+/* ROS note: this is the linux version, neutered/commented out.  Needed to let
+ * getaddrinfo compile */
+#include <assert.h>
+#include <errno.h>
+#include <ifaddrs.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <time.h>
+#include <unistd.h>
+#include <net/if.h>
+//#include <net/if_arp.h>
+//#include <sys/ioctl.h>
+
+//#include <asm/types.h>
+//#include <linux/netlink.h>
+//#include <linux/rtnetlink.h>
+
+#include <not-cancel.h>
+
+void
+__check_native (uint32_t a1_index, int *a1_native,
+               uint32_t a2_index, int *a2_native)
+{
+}
+
+#if 0
+void
+__check_native (uint32_t a1_index, int *a1_native,
+               uint32_t a2_index, int *a2_native)
+{
+  int fd = __socket (PF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
+
+  struct sockaddr_nl nladdr;
+  memset (&nladdr, '\0', sizeof (nladdr));
+  nladdr.nl_family = AF_NETLINK;
+
+  socklen_t addr_len = sizeof (nladdr);
+
+  if (fd < 0
+      || __bind (fd, (struct sockaddr *) &nladdr, sizeof (nladdr)) != 0
+      || __getsockname (fd, (struct sockaddr *) &nladdr, &addr_len) != 0)
+    return;
+
+  pid_t pid = nladdr.nl_pid;
+  struct req
+  {
+    struct nlmsghdr nlh;
+    struct rtgenmsg g;
+    /* struct rtgenmsg consists of a single byte.  This means there
+       are three bytes of padding included in the REQ definition.
+       We make them explicit here.  */
+    char pad[3];
+  } req;
+
+  req.nlh.nlmsg_len = sizeof (req);
+  req.nlh.nlmsg_type = RTM_GETLINK;
+  req.nlh.nlmsg_flags = NLM_F_ROOT | NLM_F_MATCH | NLM_F_REQUEST;
+  req.nlh.nlmsg_pid = 0;
+  req.nlh.nlmsg_seq = time (NULL);
+  req.g.rtgen_family = AF_UNSPEC;
+
+  assert (sizeof (req) - offsetof (struct req, pad) == 3);
+  memset (req.pad, '\0', sizeof (req.pad));
+
+  memset (&nladdr, '\0', sizeof (nladdr));
+  nladdr.nl_family = AF_NETLINK;
+
+#ifdef PAGE_SIZE
+  /* Help the compiler optimize out the malloc call if PAGE_SIZE
+     is constant and smaller or equal to PTHREAD_STACK_MIN/4.  */
+  const size_t buf_size = PAGE_SIZE;
+#else
+  const size_t buf_size = __getpagesize ();
+#endif
+  bool use_malloc = false;
+  char *buf;
+
+  if (__libc_use_alloca (buf_size))
+    buf = alloca (buf_size);
+  else
+    {
+      buf = malloc (buf_size);
+      if (buf != NULL)
+       use_malloc = true;
+      else
+       goto out_fail;
+    }
+
+  struct iovec iov = { buf, buf_size };
+
+  if (TEMP_FAILURE_RETRY (__sendto (fd, (void *) &req, sizeof (req), 0,
+                                   (struct sockaddr *) &nladdr,
+                                   sizeof (nladdr))) < 0)
+    goto out_fail;
+
+  bool done = false;
+  do
+    {
+      struct msghdr msg =
+       {
+         (void *) &nladdr, sizeof (nladdr),
+         &iov, 1,
+         NULL, 0,
+         0
+       };
+
+      ssize_t read_len = TEMP_FAILURE_RETRY (__recvmsg (fd, &msg, 0));
+      if (read_len < 0)
+       goto out_fail;
+
+      if (msg.msg_flags & MSG_TRUNC)
+       goto out_fail;
+
+      struct nlmsghdr *nlmh;
+      for (nlmh = (struct nlmsghdr *) buf;
+          NLMSG_OK (nlmh, (size_t) read_len);
+          nlmh = (struct nlmsghdr *) NLMSG_NEXT (nlmh, read_len))
+       {
+         if (nladdr.nl_pid != 0 || (pid_t) nlmh->nlmsg_pid != pid
+             || nlmh->nlmsg_seq != req.nlh.nlmsg_seq)
+           continue;
+
+         if (nlmh->nlmsg_type == RTM_NEWLINK)
+           {
+             struct ifinfomsg *ifim = (struct ifinfomsg *) NLMSG_DATA (nlmh);
+             int native = (ifim->ifi_type != ARPHRD_TUNNEL6
+                           && ifim->ifi_type != ARPHRD_TUNNEL
+                           && ifim->ifi_type != ARPHRD_SIT);
+
+             if (a1_index == ifim->ifi_index)
+               {
+                 *a1_native = native;
+                 a1_index = 0xffffffffu;
+               }
+             if (a2_index == ifim->ifi_index)
+               {
+                 *a2_native = native;
+                 a2_index = 0xffffffffu;
+               }
+
+             if (a1_index == 0xffffffffu
+                 && a2_index == 0xffffffffu)
+               goto out;
+           }
+         else if (nlmh->nlmsg_type == NLMSG_DONE)
+           /* We found the end, leave the loop.  */
+           done = true;
+       }
+    }
+  while (! done);
+
+ out:
+  close_not_cancel_no_status (fd);
+
+  return;
+
+out_fail:
+  if (use_malloc)
+    free (buf);
+}
+#endif
index b51ed3e..ac6772b 100644 (file)
-/* Stub version of getaddrinfo function.
-   Copyright (C) 1996, 2002 Free Software Foundation, Inc.
-   This file is part of the GNU C Library.
+/* The Inner Net License, Version 2.00
 
-   The GNU C Library is free software; you can redistribute it and/or
-   modify it under the terms of the GNU Lesser General Public
-   License as published by the Free Software Foundation; either
-   version 2.1 of the License, or (at your option) any later version.
+  The author(s) grant permission for redistribution and use in source and
+binary forms, with or without modification, of the software and documentation
+provided that the following conditions are met:
 
-   The GNU C Library is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   Lesser General Public License for more details.
+0. If you receive a version of the software that is specifically labelled
+   as not being for redistribution (check the version message and/or README),
+   you are not permitted to redistribute that version of the software in any
+   way or form.
+1. All terms of the all other applicable copyrights and licenses must be
+   followed.
+2. Redistributions of source code must retain the authors' copyright
+   notice(s), this list of conditions, and the following disclaimer.
+3. Redistributions in binary form must reproduce the authors' copyright
+   notice(s), this list of conditions, and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+4. [The copyright holder has authorized the removal of this clause.]
+5. Neither the name(s) of the author(s) nor the names of its contributors
+   may be used to endorse or promote products derived from this software
+   without specific prior written permission.
 
-   You should have received a copy of the GNU Lesser General Public
-   License along with the GNU C Library; if not, write to the Free
-   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
-   02111-1307 USA.  */
+THIS SOFTWARE IS PROVIDED BY ITS AUTHORS AND CONTRIBUTORS ``AS IS'' AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
+  If these license terms cause you a real problem, contact the author.  */
+
+/* This software is Copyright 1996 by Craig Metz, All Rights Reserved.  */
+
+/* ROS note: this is the sysdeps/posix one (not to be confused with the posix/
+ * stub one.  Needed for something or other in the network related subdirs */
+#include <assert.h>
+#include <ctype.h>
 #include <errno.h>
+#include <ifaddrs.h>
 #include <netdb.h>
-#include <resolv/resolv.h>
+#include <nss.h>
+#include <resolv.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdio_ext.h>
+#include <stdlib.h>
+#include <string.h>
 #include <arpa/inet.h>
+#include <net/if.h>
+#include <netinet/in.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/un.h>
+#include <sys/utsname.h>
+#include <unistd.h>
+#include <nsswitch.h>
+#include <bits/libc-lock.h>
+#include <not-cancel.h>
+#include <nscd/nscd-client.h>
+#include <nscd/nscd_proto.h>
+#include <resolv/res_hconf.h>
 
-int __nss_not_use_nscd_passwd = 1;
-int __nss_not_use_nscd_group = 1;
-int __nss_not_use_nscd_hosts = 1;
-int __nss_not_use_nscd_services = 1;
+#ifdef HAVE_LIBIDN
+extern int __idna_to_ascii_lz (const char *input, char **output, int flags);
+extern int __idna_to_unicode_lzlz (const char *input, char **output,
+                                  int flags);
+# include <libidn/idna.h>
+#endif
 
-__thread int h_errno = 0;
-__thread struct __res_state *__libc_resp = NULL;
+#define GAIH_OKIFUNSPEC 0x0100
+#define GAIH_EAI        ~(GAIH_OKIFUNSPEC)
 
-int
-__res_maybe_init (res_state resp, int preinit)
+#ifndef UNIX_PATH_MAX
+# define UNIX_PATH_MAX  108
+#endif
+
+struct gaih_service
+  {
+    const char *name;
+    int num;
+  };
+
+struct gaih_servtuple
+  {
+    struct gaih_servtuple *next;
+    int socktype;
+    int protocol;
+    int port;
+  };
+
+static const struct gaih_servtuple nullserv;
+
+
+struct gaih_typeproto
+  {
+    int socktype;
+    int protocol;
+    uint8_t protoflag;
+    bool defaultflag;
+    char name[8];
+  };
+
+/* Values for `protoflag'.  */
+#define GAI_PROTO_NOSERVICE    1
+#define GAI_PROTO_PROTOANY     2
+
+static const struct gaih_typeproto gaih_inet_typeproto[] =
+{
+  { 0, 0, 0, false, "" },
+  { SOCK_STREAM, IPPROTO_TCP, 0, true, "tcp" },
+  { SOCK_DGRAM, IPPROTO_UDP, 0, true, "udp" },
+#if defined SOCK_DCCP && defined IPPROTO_DCCP
+  { SOCK_DCCP, IPPROTO_DCCP, 0, false, "dccp" },
+#endif
+#ifdef IPPROTO_UDPLITE
+  { SOCK_DGRAM, IPPROTO_UDPLITE, 0, false, "udplite" },
+#endif
+#ifdef IPPROTO_SCTP
+  { SOCK_STREAM, IPPROTO_SCTP, 0, false, "sctp" },
+  { SOCK_SEQPACKET, IPPROTO_SCTP, 0, false, "sctp" },
+#endif
+  { SOCK_RAW, 0, GAI_PROTO_PROTOANY|GAI_PROTO_NOSERVICE, true, "raw" },
+  { 0, 0, 0, false, "" }
+};
+
+struct gaih
+  {
+    int family;
+    int (*gaih)(const char *name, const struct gaih_service *service,
+               const struct addrinfo *req, struct addrinfo **pai,
+               unsigned int *naddrs);
+  };
+
+static const struct addrinfo default_hints =
+  {
+    .ai_flags = AI_DEFAULT,
+    .ai_family = PF_UNSPEC,
+    .ai_socktype = 0,
+    .ai_protocol = 0,
+    .ai_addrlen = 0,
+    .ai_addr = NULL,
+    .ai_canonname = NULL,
+    .ai_next = NULL
+  };
+
+
+static int
+gaih_inet_serv (const char *servicename, const struct gaih_typeproto *tp,
+               const struct addrinfo *req, struct gaih_servtuple *st)
+{
+  struct servent *s;
+  size_t tmpbuflen = 1024;
+  struct servent ts;
+  char *tmpbuf;
+  int r;
+
+  do
+    {
+      tmpbuf = __alloca (tmpbuflen);
+
+      r = __getservbyname_r (servicename, tp->name, &ts, tmpbuf, tmpbuflen,
+                            &s);
+      if (r != 0 || s == NULL)
+       {
+         if (r == ERANGE)
+           tmpbuflen *= 2;
+         else
+           return GAIH_OKIFUNSPEC | -EAI_SERVICE;
+       }
+    }
+  while (r);
+
+  st->next = NULL;
+  st->socktype = tp->socktype;
+  st->protocol = ((tp->protoflag & GAI_PROTO_PROTOANY)
+                 ? req->ai_protocol : tp->protocol);
+  st->port = s->s_port;
+
+  return 0;
+}
+
+#define gethosts(_family, _type) \
+ {                                                                           \
+  int i;                                                                     \
+  int herrno;                                                                \
+  struct hostent th;                                                         \
+  struct hostent *h;                                                         \
+  char *localcanon = NULL;                                                   \
+  no_data = 0;                                                               \
+  while (1) {                                                                \
+    rc = 0;                                                                  \
+    status = DL_CALL_FCT (fct, (name, _family, &th, tmpbuf, tmpbuflen,       \
+                               &rc, &herrno, NULL, &localcanon));            \
+    if (rc != ERANGE || herrno != NETDB_INTERNAL)                            \
+      break;                                                                 \
+    tmpbuf = extend_alloca (tmpbuf, tmpbuflen, 2 * tmpbuflen);               \
+  }                                                                          \
+  if (status == NSS_STATUS_SUCCESS && rc == 0)                               \
+    h = &th;                                                                 \
+  else                                                                       \
+    h = NULL;                                                                \
+  if (rc != 0)                                                               \
+    {                                                                        \
+      if (herrno == NETDB_INTERNAL)                                          \
+       {                                                                     \
+         __set_h_errno (herrno);                                             \
+         _res.options = old_res_options;                                     \
+         return -EAI_SYSTEM;                                                 \
+       }                                                                     \
+      if (herrno == TRY_AGAIN)                                               \
+       no_data = EAI_AGAIN;                                                  \
+      else                                                                   \
+       no_data = herrno == NO_DATA;                                          \
+    }                                                                        \
+  else if (h != NULL)                                                        \
+    {                                                                        \
+      for (i = 0; h->h_addr_list[i]; i++)                                    \
+       {                                                                     \
+         if (*pat == NULL)                                                   \
+           {                                                                 \
+             *pat = __alloca (sizeof (struct gaih_addrtuple));               \
+             (*pat)->scopeid = 0;                                            \
+           }                                                                 \
+         uint32_t *addr = (*pat)->addr;                                      \
+         (*pat)->next = NULL;                                                \
+         (*pat)->name = i == 0 ? strdupa (h->h_name) : NULL;                 \
+         if (_family == AF_INET && req->ai_family == AF_INET6)               \
+           {                                                                 \
+             (*pat)->family = AF_INET6;                                      \
+             addr[3] = *(uint32_t *) h->h_addr_list[i];                      \
+             addr[2] = htonl (0xffff);                                       \
+             addr[1] = 0;                                                    \
+             addr[0] = 0;                                                    \
+           }                                                                 \
+         else                                                                \
+           {                                                                 \
+             (*pat)->family = _family;                                       \
+             memcpy (addr, h->h_addr_list[i], sizeof(_type));                \
+           }                                                                 \
+         pat = &((*pat)->next);                                              \
+       }                                                                     \
+                                                                             \
+      if (localcanon !=        NULL && canon == NULL)                                \
+       canon = strdupa (localcanon);                                         \
+                                                                             \
+      if (_family == AF_INET6 && i > 0)                                              \
+       got_ipv6 = true;                                                      \
+    }                                                                        \
+ }
+
+
+typedef enum nss_status (*nss_gethostbyname4_r)
+  (const char *name, struct gaih_addrtuple **pat,
+   char *buffer, size_t buflen, int *errnop,
+   int *h_errnop, int32_t *ttlp);
+typedef enum nss_status (*nss_gethostbyname3_r)
+  (const char *name, int af, struct hostent *host,
+   char *buffer, size_t buflen, int *errnop,
+   int *h_errnop, int32_t *ttlp, char **canonp);
+typedef enum nss_status (*nss_getcanonname_r)
+  (const char *name, char *buffer, size_t buflen, char **result,
+   int *errnop, int *h_errnop);
+extern service_user *__nss_hosts_database attribute_hidden;
+
+
+static int
+gaih_inet (const char *name, const struct gaih_service *service,
+          const struct addrinfo *req, struct addrinfo **pai,
+          unsigned int *naddrs)
 {
-  __set_errno (ENOSYS);
+  const struct gaih_typeproto *tp = gaih_inet_typeproto;
+  struct gaih_servtuple *st = (struct gaih_servtuple *) &nullserv;
+  struct gaih_addrtuple *at = NULL;
+  int rc;
+  bool got_ipv6 = false;
+  const char *canon = NULL;
+  const char *orig_name = name;
+
+  if (req->ai_protocol || req->ai_socktype)
+    {
+      ++tp;
+
+      while (tp->name[0]
+            && ((req->ai_socktype != 0 && req->ai_socktype != tp->socktype)
+                || (req->ai_protocol != 0
+                    && !(tp->protoflag & GAI_PROTO_PROTOANY)
+                    && req->ai_protocol != tp->protocol)))
+       ++tp;
+
+      if (! tp->name[0])
+       {
+         if (req->ai_socktype)
+           return GAIH_OKIFUNSPEC | -EAI_SOCKTYPE;
+         else
+           return GAIH_OKIFUNSPEC | -EAI_SERVICE;
+       }
+    }
+
+  int port = 0;
+  if (service != NULL)
+    {
+      if ((tp->protoflag & GAI_PROTO_NOSERVICE) != 0)
+       return GAIH_OKIFUNSPEC | -EAI_SERVICE;
+
+      if (service->num < 0)
+       {
+         if (tp->name[0])
+           {
+             st = (struct gaih_servtuple *)
+               __alloca (sizeof (struct gaih_servtuple));
+
+             if ((rc = gaih_inet_serv (service->name, tp, req, st)))
+               return rc;
+           }
+         else
+           {
+             struct gaih_servtuple **pst = &st;
+             for (tp++; tp->name[0]; tp++)
+               {
+                 struct gaih_servtuple *newp;
+
+                 if ((tp->protoflag & GAI_PROTO_NOSERVICE) != 0)
+                   continue;
+
+                 if (req->ai_socktype != 0
+                     && req->ai_socktype != tp->socktype)
+                   continue;
+                 if (req->ai_protocol != 0
+                     && !(tp->protoflag & GAI_PROTO_PROTOANY)
+                     && req->ai_protocol != tp->protocol)
+                   continue;
+
+                 newp = (struct gaih_servtuple *)
+                   __alloca (sizeof (struct gaih_servtuple));
+
+                 if ((rc = gaih_inet_serv (service->name, tp, req, newp)))
+                   {
+                     if (rc & GAIH_OKIFUNSPEC)
+                       continue;
+                     return rc;
+                   }
+
+                 *pst = newp;
+                 pst = &(newp->next);
+               }
+             if (st == (struct gaih_servtuple *) &nullserv)
+               return GAIH_OKIFUNSPEC | -EAI_SERVICE;
+           }
+       }
+      else
+       {
+         port = htons (service->num);
+         goto got_port;
+       }
+    }
+  else
+    {
+    got_port:
+
+      if (req->ai_socktype || req->ai_protocol)
+       {
+         st = __alloca (sizeof (struct gaih_servtuple));
+         st->next = NULL;
+         st->socktype = tp->socktype;
+         st->protocol = ((tp->protoflag & GAI_PROTO_PROTOANY)
+                         ? req->ai_protocol : tp->protocol);
+         st->port = port;
+       }
+      else
+       {
+         /* Neither socket type nor protocol is set.  Return all socket types
+            we know about.  */
+         struct gaih_servtuple **lastp = &st;
+         for (++tp; tp->name[0]; ++tp)
+           if (tp->defaultflag)
+             {
+               struct gaih_servtuple *newp;
+
+               newp = __alloca (sizeof (struct gaih_servtuple));
+               newp->next = NULL;
+               newp->socktype = tp->socktype;
+               newp->protocol = tp->protocol;
+               newp->port = port;
+
+               *lastp = newp;
+               lastp = &newp->next;
+             }
+       }
+    }
+
+  if (name != NULL)
+    {
+      at = __alloca (sizeof (struct gaih_addrtuple));
+
+      at->family = AF_UNSPEC;
+      at->scopeid = 0;
+      at->next = NULL;
+
+#ifdef HAVE_LIBIDN
+      if (req->ai_flags & AI_IDN)
+       {
+         int idn_flags = 0;
+         if (req->ai_flags & AI_IDN_ALLOW_UNASSIGNED)
+           idn_flags |= IDNA_ALLOW_UNASSIGNED;
+         if (req->ai_flags & AI_IDN_USE_STD3_ASCII_RULES)
+           idn_flags |= IDNA_USE_STD3_ASCII_RULES;
+
+         char *p = NULL;
+         rc = __idna_to_ascii_lz (name, &p, idn_flags);
+         if (rc != IDNA_SUCCESS)
+           {
+             if (rc == IDNA_MALLOC_ERROR)
+               return -EAI_MEMORY;
+             if (rc == IDNA_DLOPEN_ERROR)
+               return -EAI_SYSTEM;
+             return -EAI_IDN_ENCODE;
+           }
+         /* In case the output string is the same as the input string
+            no new string has been allocated.  */
+         if (p != name)
+           {
+             name = strdupa (p);
+             free (p);
+           }
+       }
+#endif
+
+      if (__inet_aton (name, (struct in_addr *) at->addr) != 0)
+       {
+         if (req->ai_family == AF_UNSPEC || req->ai_family == AF_INET)
+           at->family = AF_INET;
+         else if (req->ai_family == AF_INET6 && (req->ai_flags & AI_V4MAPPED))
+           {
+             at->addr[3] = at->addr[0];
+             at->addr[2] = htonl (0xffff);
+             at->addr[1] = 0;
+             at->addr[0] = 0;
+             at->family = AF_INET6;
+           }
+         else
+           return -EAI_ADDRFAMILY;
+
+         if (req->ai_flags & AI_CANONNAME)
+           canon = name;
+       }
+      else if (at->family == AF_UNSPEC)
+       {
+         char *namebuf = (char *) name;
+         char *scope_delim = strchr (name, SCOPE_DELIMITER);
+
+         if (__builtin_expect (scope_delim != NULL, 0))
+           {
+             namebuf = alloca (scope_delim - name + 1);
+             *((char *) __mempcpy (namebuf, name, scope_delim - name)) = '\0';
+           }
+
+         if (inet_pton (AF_INET6, namebuf, at->addr) > 0)
+           {
+             if (req->ai_family == AF_UNSPEC || req->ai_family == AF_INET6)
+               at->family = AF_INET6;
+             else if (req->ai_family == AF_INET
+                      && IN6_IS_ADDR_V4MAPPED (at->addr))
+               {
+                 at->addr[0] = at->addr[3];
+                 at->family = AF_INET;
+               }
+             else
+               return -EAI_ADDRFAMILY;
+
+             if (scope_delim != NULL)
+               {
+                 int try_numericscope = 0;
+                 if (IN6_IS_ADDR_LINKLOCAL (at->addr)
+                     || IN6_IS_ADDR_MC_LINKLOCAL (at->addr))
+                   {
+                     at->scopeid = if_nametoindex (scope_delim + 1);
+                     if (at->scopeid == 0)
+                       try_numericscope = 1;
+                   }
+                 else
+                   try_numericscope = 1;
+
+                 if (try_numericscope != 0)
+                   {
+                     char *end;
+                     assert (sizeof (uint32_t) <= sizeof (unsigned long));
+                     at->scopeid = (uint32_t) strtoul (scope_delim + 1, &end,
+                                                       10);
+                     if (*end != '\0')
+                       return GAIH_OKIFUNSPEC | -EAI_NONAME;
+                   }
+               }
+
+             if (req->ai_flags & AI_CANONNAME)
+               canon = name;
+           }
+       }
+
+      if (at->family == AF_UNSPEC && (req->ai_flags & AI_NUMERICHOST) == 0)
+       {
+         struct gaih_addrtuple **pat = &at;
+         int no_data = 0;
+         int no_inet6_data = 0;
+         service_user *nip = NULL;
+         enum nss_status inet6_status = NSS_STATUS_UNAVAIL;
+         enum nss_status status = NSS_STATUS_UNAVAIL;
+         int no_more;
+         int old_res_options;
+
+         /* If we do not have to look for IPv4 and IPv6 together, use
+            the simple, old functions.  */
+         if (req->ai_family == AF_INET
+             || (req->ai_family == AF_INET6
+                 && ((req->ai_flags & AI_V4MAPPED) == 0
+                     || (req->ai_flags & AI_ALL) == 0)))
+           {
+             int family = req->ai_family;
+             size_t tmpbuflen = 512;
+             char *tmpbuf = alloca (tmpbuflen);
+             int rc;
+             struct hostent th;
+             struct hostent *h;
+             int herrno;
+
+           simple_again:
+             while (1)
+               {
+                 rc = __gethostbyname2_r (name, family, &th, tmpbuf,
+                                          tmpbuflen, &h, &herrno);
+                 if (rc != ERANGE || herrno != NETDB_INTERNAL)
+                   break;
+                 tmpbuf = extend_alloca (tmpbuf, tmpbuflen, 2 * tmpbuflen);
+               }
+
+             if (rc == 0)
+               {
+                 if (h == NULL)
+                   {
+                     if (req->ai_family == AF_INET6
+                         && (req->ai_flags & AI_V4MAPPED)
+                         && family == AF_INET6)
+                       {
+                         /* Try again, this time looking for IPv4
+                            addresses.  */
+                         family = AF_INET;
+                         goto simple_again;
+                       }
+                   }
+                 else
+                   {
+                     /* We found data, now convert it into the list.  */
+                     for (int i = 0; h->h_addr_list[i]; ++i)
+                       {
+                         if (*pat == NULL)
+                           {
+                             *pat = __alloca (sizeof (struct gaih_addrtuple));
+                             (*pat)->scopeid = 0;
+                           }
+                         (*pat)->next = NULL;
+                         (*pat)->family = req->ai_family;
+                         if (family == req->ai_family)
+                           memcpy ((*pat)->addr, h->h_addr_list[i],
+                                   h->h_length);
+                         else
+                           {
+                             uint32_t *addr = (uint32_t *) (*pat)->addr;
+                             addr[3] = *(uint32_t *) h->h_addr_list[i];
+                             addr[2] = htonl (0xffff);
+                             addr[1] = 0;
+                             addr[0] = 0;
+                           }
+                         pat = &((*pat)->next);
+                       }
+                   }
+               }
+             else
+               {
+                 if (herrno == NETDB_INTERNAL)
+                   {
+                     __set_h_errno (herrno);
+                     return -EAI_SYSTEM;
+                   }
+                 if (herrno == TRY_AGAIN)
+                   {
+                     return -EAI_AGAIN;
+                   }
+                 /* We made requests but they turned out no data.
+                    The name is known, though.  */
+                 return GAIH_OKIFUNSPEC | -EAI_NODATA;
+               }
+
+             goto process_list;
+           }
+
+#ifdef USE_NSCD
+         if (__nss_not_use_nscd_hosts > 0
+             && ++__nss_not_use_nscd_hosts > NSS_NSCD_RETRY)
+           __nss_not_use_nscd_hosts = 0;
+
+         if (!__nss_not_use_nscd_hosts)
+           {
+             /* Try to use nscd.  */
+             struct nscd_ai_result *air = NULL;
+             int herrno;
+             int err = __nscd_getai (name, &air, &herrno);
+             if (air != NULL)
+               {
+                 /* Transform into gaih_addrtuple list.  */
+                 bool added_canon = (req->ai_flags & AI_CANONNAME) == 0;
+                 char *addrs = air->addrs;
+
+                 for (int i = 0; i < air->naddrs; ++i)
+                   {
+                     socklen_t size = (air->family[i] == AF_INET
+                                       ? INADDRSZ : IN6ADDRSZ);
+                     if (*pat == NULL)
+                       {
+                         *pat = __alloca (sizeof (struct gaih_addrtuple));
+                         (*pat)->scopeid = 0;
+                       }
+                     uint32_t *pataddr = (*pat)->addr;
+                     (*pat)->next = NULL;
+                     if (added_canon || air->canon == NULL)
+                       (*pat)->name = NULL;
+                     else
+                       canon = (*pat)->name = strdupa (air->canon);
+
+                     if (air->family[i] == AF_INET
+                         && req->ai_family == AF_INET6
+                         && (req->ai_flags & AI_V4MAPPED))
+                       {
+                         (*pat)->family = AF_INET6;
+                         pataddr[3] = *(uint32_t *) addrs;
+                         pataddr[2] = htonl (0xffff);
+                         pataddr[1] = 0;
+                         pataddr[0] = 0;
+                         pat = &((*pat)->next);
+                         added_canon = true;
+                       }
+                     else if (req->ai_family == AF_UNSPEC
+                              || air->family[i] == req->ai_family)
+                       {
+                         (*pat)->family = air->family[i];
+                         memcpy (pataddr, addrs, size);
+                         pat = &((*pat)->next);
+                         added_canon = true;
+                         if (air->family[i] == AF_INET6)
+                           got_ipv6 = true;
+                       }
+                     addrs += size;
+                   }
+
+                 free (air);
+
+                 if (at->family == AF_UNSPEC)
+                   return GAIH_OKIFUNSPEC | -EAI_NONAME;
+
+                 goto process_list;
+               }
+             else if (err == 0)
+               /* The database contains a negative entry.  */
+               return 0;
+             else if (__nss_not_use_nscd_hosts == 0)
+               {
+                 if (herrno == NETDB_INTERNAL && errno == ENOMEM)
+                   return -EAI_MEMORY;
+                 if (herrno == TRY_AGAIN)
+                   return -EAI_AGAIN;
+                 return -EAI_SYSTEM;
+               }
+           }
+#endif
+
+         if (__nss_hosts_database != NULL)
+           {
+             no_more = 0;
+             nip = __nss_hosts_database;
+           }
+         else
+           no_more = __nss_database_lookup ("hosts", NULL,
+                                            "dns [!UNAVAIL=return] files",
+                                            &nip);
+
+         /* Initialize configurations.  */
+         if (__builtin_expect (!_res_hconf.initialized, 0))
+           _res_hconf_init ();
+         if (__res_maybe_init (&_res, 0) == -1)
+           no_more = 1;
+
+         /* If we are looking for both IPv4 and IPv6 address we don't
+            want the lookup functions to automatically promote IPv4
+            addresses to IPv6 addresses.  Currently this is decided
+            by setting the RES_USE_INET6 bit in _res.options.  */
+         old_res_options = _res.options;
+         _res.options &= ~RES_USE_INET6;
+
+         size_t tmpbuflen = 1024;
+         char *tmpbuf = alloca (tmpbuflen);
+
+         while (!no_more)
+           {
+             nss_gethostbyname4_r fct4
+               = __nss_lookup_function (nip, "gethostbyname4_r");
+             if (fct4 != NULL)
+               {
+                 int herrno;
+
+                 while (1)
+                   {
+                     rc = 0;
+                     status = DL_CALL_FCT (fct4, (name, pat, tmpbuf,
+                                                  tmpbuflen, &rc, &herrno,
+                                                  NULL));
+                     if (status == NSS_STATUS_SUCCESS)
+                       break;
+                     if (status != NSS_STATUS_TRYAGAIN
+                         || rc != ERANGE || herrno != NETDB_INTERNAL)
+                       {
+                         if (herrno == NETDB_INTERNAL)
+                           {
+                             __set_h_errno (herrno);
+                             _res.options = old_res_options;
+                             return -EAI_SYSTEM;
+                           }
+                         if (herrno == TRY_AGAIN)
+                           no_data = EAI_AGAIN;
+                         else
+                           no_data = herrno == NO_DATA;
+                         break;
+                       }
+                     tmpbuf = extend_alloca (tmpbuf,
+                                             tmpbuflen, 2 * tmpbuflen);
+                   }
+
+                 no_inet6_data = no_data;
+
+                 if (status == NSS_STATUS_SUCCESS)
+                   {
+                     if ((req->ai_flags & AI_CANONNAME) != 0 && canon == NULL)
+                       canon = (*pat)->name;
+
+                     while (*pat != NULL)
+                       pat = &((*pat)->next);
+                   }
+               }
+             else
+               {
+                 nss_gethostbyname3_r fct = NULL;
+                 if (req->ai_flags & AI_CANONNAME)
+                   /* No need to use this function if we do not look for
+                      the canonical name.  The function does not exist in
+                      all NSS modules and therefore the lookup would
+                      often fail.  */
+                   fct = __nss_lookup_function (nip, "gethostbyname3_r");
+                 if (fct == NULL)
+                   /* We are cheating here.  The gethostbyname2_r
+                      function does not have the same interface as
+                      gethostbyname3_r but the extra arguments the
+                      latter takes are added at the end.  So the
+                      gethostbyname2_r code will just ignore them.  */
+                   fct = __nss_lookup_function (nip, "gethostbyname2_r");
+
+                 if (fct != NULL)
+                   {
+                     if (req->ai_family == AF_INET6
+                         || req->ai_family == AF_UNSPEC)
+                       {
+                         gethosts (AF_INET6, struct in6_addr);
+                         no_inet6_data = no_data;
+                         inet6_status = status;
+                       }
+                     if (req->ai_family == AF_INET
+                         || req->ai_family == AF_UNSPEC
+                         || (req->ai_family == AF_INET6
+                             && (req->ai_flags & AI_V4MAPPED)
+                             /* Avoid generating the mapped addresses if we
+                                know we are not going to need them.  */
+                             && ((req->ai_flags & AI_ALL) || !got_ipv6)))
+                       {
+                         gethosts (AF_INET, struct in_addr);
+
+                         if (req->ai_family == AF_INET)
+                           {
+                             no_inet6_data = no_data;
+                             inet6_status = status;
+                           }
+                       }
+
+                     /* If we found one address for AF_INET or AF_INET6,
+                        don't continue the search.  */
+                     if (inet6_status == NSS_STATUS_SUCCESS
+                         || status == NSS_STATUS_SUCCESS)
+                       {
+                         if ((req->ai_flags & AI_CANONNAME) != 0
+                             && canon == NULL)
+                           {
+                             /* If we need the canonical name, get it
+                                from the same service as the result.  */
+                             nss_getcanonname_r cfct;
+                             int herrno;
+
+                             cfct = __nss_lookup_function (nip,
+                                                           "getcanonname_r");
+                             if (cfct != NULL)
+                               {
+                                 const size_t max_fqdn_len = 256;
+                                 char *buf = alloca (max_fqdn_len);
+                                 char *s;
+
+                                 if (DL_CALL_FCT (cfct, (at->name ?: name,
+                                                         buf, max_fqdn_len,
+                                                         &s, &rc, &herrno))
+                                     == NSS_STATUS_SUCCESS)
+                                   canon = s;
+                                 else
+                                   /* Set to name now to avoid using
+                                      gethostbyaddr.  */
+                                   canon = name;
+                               }
+                           }
+
+                         break;
+                       }
+
+                     /* We can have different states for AF_INET and
+                        AF_INET6.  Try to find a useful one for both.  */
+                     if (inet6_status == NSS_STATUS_TRYAGAIN)
+                       status = NSS_STATUS_TRYAGAIN;
+                     else if (status == NSS_STATUS_UNAVAIL
+                              && inet6_status != NSS_STATUS_UNAVAIL)
+                       status = inet6_status;
+                   }
+                 else
+                   status = NSS_STATUS_UNAVAIL;
+               }
+
+             if (nss_next_action (nip, status) == NSS_ACTION_RETURN)
+               break;
+
+             if (nip->next == NULL)
+               no_more = -1;
+             else
+               nip = nip->next;
+           }
+
+         _res.options = old_res_options;
+
+         if (no_data != 0 && no_inet6_data != 0)
+           {
+             /* If both requests timed out report this.  */
+             if (no_data == EAI_AGAIN && no_inet6_data == EAI_AGAIN)
+               return -EAI_AGAIN;
+
+             /* We made requests but they turned out no data.  The name
+                is known, though.  */
+             return GAIH_OKIFUNSPEC | -EAI_NODATA;
+           }
+       }
+
+    process_list:
+      if (at->family == AF_UNSPEC)
+       return GAIH_OKIFUNSPEC | -EAI_NONAME;
+    }
+  else
+    {
+      struct gaih_addrtuple *atr;
+      atr = at = __alloca (sizeof (struct gaih_addrtuple));
+      memset (at, '\0', sizeof (struct gaih_addrtuple));
+
+      if (req->ai_family == AF_UNSPEC)
+       {
+         at->next = __alloca (sizeof (struct gaih_addrtuple));
+         memset (at->next, '\0', sizeof (struct gaih_addrtuple));
+       }
+
+      if (req->ai_family == AF_UNSPEC || req->ai_family == AF_INET6)
+       {
+         at->family = AF_INET6;
+         if ((req->ai_flags & AI_PASSIVE) == 0)
+           memcpy (at->addr, &in6addr_loopback, sizeof (struct in6_addr));
+         atr = at->next;
+       }
+
+      if (req->ai_family == AF_UNSPEC || req->ai_family == AF_INET)
+       {
+         atr->family = AF_INET;
+         if ((req->ai_flags & AI_PASSIVE) == 0)
+           atr->addr[0] = htonl (INADDR_LOOPBACK);
+       }
+    }
+
+  {
+    struct gaih_servtuple *st2;
+    struct gaih_addrtuple *at2 = at;
+    size_t socklen;
+    sa_family_t family;
+
+    /*
+      buffer is the size of an unformatted IPv6 address in printable format.
+     */
+    while (at2 != NULL)
+      {
+       /* Only the first entry gets the canonical name.  */
+       if (at2 == at && (req->ai_flags & AI_CANONNAME) != 0)
+         {
+           if (canon == NULL)
+             {
+               struct hostent *h = NULL;
+               int herrno;
+               struct hostent th;
+               size_t tmpbuflen = 512;
+               char *tmpbuf = NULL;
+
+               do
+                 {
+                   tmpbuf = extend_alloca (tmpbuf, tmpbuflen, tmpbuflen * 2);
+                   rc = __gethostbyaddr_r (at2->addr,
+                                           ((at2->family == AF_INET6)
+                                            ? sizeof (struct in6_addr)
+                                            : sizeof (struct in_addr)),
+                                           at2->family, &th, tmpbuf,
+                                           tmpbuflen, &h, &herrno);
+                 }
+               while (rc == ERANGE && herrno == NETDB_INTERNAL);
+
+               if (rc != 0 && herrno == NETDB_INTERNAL)
+                 {
+                   __set_h_errno (herrno);
+                   return -EAI_SYSTEM;
+                 }
+
+               if (h != NULL)
+                 canon = h->h_name;
+               else
+                 {
+                   assert (orig_name != NULL);
+                   /* If the canonical name cannot be determined, use
+                      the passed in string.  */
+                   canon = orig_name;
+                 }
+             }
+
+#ifdef HAVE_LIBIDN
+           if (req->ai_flags & AI_CANONIDN)
+             {
+               int idn_flags = 0;
+               if (req->ai_flags & AI_IDN_ALLOW_UNASSIGNED)
+                 idn_flags |= IDNA_ALLOW_UNASSIGNED;
+               if (req->ai_flags & AI_IDN_USE_STD3_ASCII_RULES)
+                 idn_flags |= IDNA_USE_STD3_ASCII_RULES;
+
+               char *out;
+               int rc = __idna_to_unicode_lzlz (canon, &out, idn_flags);
+               if (rc != IDNA_SUCCESS)
+                 {
+                   if (rc == IDNA_MALLOC_ERROR)
+                     return -EAI_MEMORY;
+                   if (rc == IDNA_DLOPEN_ERROR)
+                     return -EAI_SYSTEM;
+                   return -EAI_IDN_ENCODE;
+                 }
+               /* In case the output string is the same as the input
+                  string no new string has been allocated and we
+                  make a copy.  */
+               if (out == canon)
+                 goto make_copy;
+             }
+           else
+#endif
+             {
+#ifdef HAVE_LIBIDN
+             make_copy:
+#endif
+               canon = strdup (canon);
+               if (canon == NULL)
+                 return -EAI_MEMORY;
+             }
+         }
+
+       family = at2->family;
+       if (family == AF_INET6)
+         {
+           socklen = sizeof (struct sockaddr_in6);
+
+           /* If we looked up IPv4 mapped address discard them here if
+              the caller isn't interested in all address and we have
+              found at least one IPv6 address.  */
+           if (got_ipv6
+               && (req->ai_flags & (AI_V4MAPPED|AI_ALL)) == AI_V4MAPPED
+               && IN6_IS_ADDR_V4MAPPED (at2->addr))
+             goto ignore;
+         }
+       else
+         socklen = sizeof (struct sockaddr_in);
+
+       for (st2 = st; st2 != NULL; st2 = st2->next)
+         {
+           struct addrinfo *ai;
+           ai = *pai = malloc (sizeof (struct addrinfo) + socklen);
+           if (ai == NULL)
+             {
+               free ((char *) canon);
+               return -EAI_MEMORY;
+             }
+
+           ai->ai_flags = req->ai_flags;
+           ai->ai_family = family;
+           ai->ai_socktype = st2->socktype;
+           ai->ai_protocol = st2->protocol;
+           ai->ai_addrlen = socklen;
+           ai->ai_addr = (void *) (ai + 1);
+
+           /* We only add the canonical name once.  */
+           ai->ai_canonname = (char *) canon;
+           canon = NULL;
+
+#ifdef _HAVE_SA_LEN
+           ai->ai_addr->sa_len = socklen;
+#endif /* _HAVE_SA_LEN */
+           ai->ai_addr->sa_family = family;
+
+           /* In case of an allocation error the list must be NULL
+              terminated.  */
+           ai->ai_next = NULL;
+
+           if (family == AF_INET6)
+             {
+               struct sockaddr_in6 *sin6p =
+                 (struct sockaddr_in6 *) ai->ai_addr;
+
+               sin6p->sin6_port = st2->port;
+               sin6p->sin6_flowinfo = 0;
+               memcpy (&sin6p->sin6_addr,
+                       at2->addr, sizeof (struct in6_addr));
+               sin6p->sin6_scope_id = at2->scopeid;
+             }
+           else
+             {
+               struct sockaddr_in *sinp =
+                 (struct sockaddr_in *) ai->ai_addr;
+               sinp->sin_port = st2->port;
+               memcpy (&sinp->sin_addr,
+                       at2->addr, sizeof (struct in_addr));
+               memset (sinp->sin_zero, '\0', sizeof (sinp->sin_zero));
+             }
+
+           pai = &(ai->ai_next);
+         }
+
+       ++*naddrs;
+
+      ignore:
+       at2 = at2->next;
+      }
+  }
+  return 0;
+}
+
+
+struct sort_result
+{
+  struct addrinfo *dest_addr;
+  /* Using sockaddr_storage is for now overkill.  We only support IPv4
+     and IPv6 so far.  If this changes at some point we can adjust the
+     type here.  */
+  struct sockaddr_in6 source_addr;
+  uint8_t source_addr_len;
+  bool got_source_addr;
+  uint8_t source_addr_flags;
+  uint8_t prefixlen;
+  uint32_t index;
+  int32_t native;
+};
+
+struct sort_result_combo
+{
+  struct sort_result *results;
+  int nresults;
+};
+
+
+#if __BYTE_ORDER == __BIG_ENDIAN
+# define htonl_c(n) n
+#else
+# define htonl_c(n) __bswap_constant_32 (n)
+#endif
+
+static const struct scopeentry
+{
+  union
+  {
+    char addr[4];
+    uint32_t addr32;
+  };
+  uint32_t netmask;
+  int32_t scope;
+} default_scopes[] =
+  {
+    /* Link-local addresses: scope 2.  */
+    { { { 169, 254, 0, 0 } }, htonl_c (0xffff0000), 2 },
+    { { { 127, 0, 0, 0 } }, htonl_c (0xff000000), 2 },
+    /* Site-local addresses: scope 5.  */
+    { { { 10, 0, 0, 0 } }, htonl_c (0xff000000), 5 },
+    { { { 172, 16, 0, 0 } }, htonl_c (0xfff00000), 5 },
+    { { { 192, 168, 0, 0 } }, htonl_c (0xffff0000), 5 },
+    /* Default: scope 14.  */
+    { { { 0, 0, 0, 0 } }, htonl_c (0x00000000), 14 }
+  };
+
+/* The label table.  */
+static const struct scopeentry *scopes;
+
+
+static int
+get_scope (const struct sockaddr_in6 *in6)
+{
+  int scope;
+  if (in6->sin6_family == PF_INET6)
+    {
+      if (! IN6_IS_ADDR_MULTICAST (&in6->sin6_addr))
+       {
+         if (IN6_IS_ADDR_LINKLOCAL (&in6->sin6_addr)
+             /* RFC 4291 2.5.3 says that the loopback address is to be
+                treated like a link-local address.  */
+             || IN6_IS_ADDR_LOOPBACK (&in6->sin6_addr))
+           scope = 2;
+         else if (IN6_IS_ADDR_SITELOCAL (&in6->sin6_addr))
+           scope = 5;
+         else
+           /* XXX Is this the correct default behavior?  */
+           scope = 14;
+       }
+      else
+       scope = in6->sin6_addr.s6_addr[1] & 0xf;
+    }
+  else if (in6->sin6_family == PF_INET)
+    {
+      const struct sockaddr_in *in = (const struct sockaddr_in *) in6;
+
+      size_t cnt = 0;
+      while (1)
+       {
+         if ((in->sin_addr.s_addr & scopes[cnt].netmask)
+             == scopes[cnt].addr32)
+           return scopes[cnt].scope;
+
+         ++cnt;
+       }
+      /* NOTREACHED */
+    }
+  else
+    /* XXX What is a good default?  */
+    scope = 15;
+
+  return scope;
+}
+
+
+struct prefixentry
+{
+  struct in6_addr prefix;
+  unsigned int bits;
+  int val;
+};
+
+
+/* The label table.  */
+static const struct prefixentry *labels;
+
+/* Default labels.  */
+static const struct prefixentry default_labels[] =
+  {
+    /* See RFC 3484 for the details.  */
+    { { .__in6_u
+       = { .__u6_addr8 = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                           0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 } }
+      }, 128, 0 },
+    { { .__in6_u
+       = { .__u6_addr8 = { 0x20, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                           0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
+      }, 16, 2 },
+    { { .__in6_u
+       = { .__u6_addr8 = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                           0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
+      }, 96, 3 },
+    { { .__in6_u
+       = { .__u6_addr8 = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                           0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00 } }
+      }, 96, 4 },
+    /* The next two entries differ from RFC 3484.  We need to treat
+       IPv6 site-local addresses special because they are never NATed,
+       unlike site-locale IPv4 addresses.  If this would not happen, on
+       machines which have only IPv4 and IPv6 site-local addresses, the
+       sorting would prefer the IPv6 site-local addresses, causing
+       unnecessary delays when trying to connect to a global IPv6 address
+       through a site-local IPv6 address.  */
+    { { .__in6_u
+       = { .__u6_addr8 = { 0xfe, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                           0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
+      }, 10, 5 },
+    { { .__in6_u
+       = { .__u6_addr8 = { 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                           0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
+      }, 7, 6 },
+    /* Additional rule for Teredo tunnels.  */
+    { { .__in6_u
+       = { .__u6_addr8 = { 0x20, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                           0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
+      }, 32, 7 },
+    { { .__in6_u
+       = { .__u6_addr8 = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                           0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
+      }, 0, 1 }
+  };
+
+
+/* The precedence table.  */
+static const struct prefixentry *precedence;
+
+/* The default precedences.  */
+static const struct prefixentry default_precedence[] =
+  {
+    /* See RFC 3484 for the details.  */
+    { { .__in6_u
+       = { .__u6_addr8 = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                           0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 } }
+      }, 128, 50 },
+    { { .__in6_u
+       = { .__u6_addr8 = { 0x20, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                           0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
+      }, 16, 30 },
+    { { .__in6_u
+       = { .__u6_addr8 = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
+      }, 96, 20 },
+    { { .__in6_u
+       = { .__u6_addr8 = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                           0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00 } }
+      }, 96, 10 },
+    { { .__in6_u
+       = { .__u6_addr8 = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                           0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
+      }, 0, 40 }
+  };
+
+
+static int
+match_prefix (const struct sockaddr_in6 *in6,
+             const struct prefixentry *list, int default_val)
+{
+  int idx;
+  struct sockaddr_in6 in6_mem;
+
+  if (in6->sin6_family == PF_INET)
+    {
+      const struct sockaddr_in *in = (const struct sockaddr_in *) in6;
+
+      /* Construct a V4-to-6 mapped address.  */
+      in6_mem.sin6_family = PF_INET6;
+      in6_mem.sin6_port = in->sin_port;
+      in6_mem.sin6_flowinfo = 0;
+      memset (&in6_mem.sin6_addr, '\0', sizeof (in6_mem.sin6_addr));
+      in6_mem.sin6_addr.s6_addr16[5] = 0xffff;
+      in6_mem.sin6_addr.s6_addr32[3] = in->sin_addr.s_addr;
+      in6_mem.sin6_scope_id = 0;
+
+      in6 = &in6_mem;
+    }
+  else if (in6->sin6_family != PF_INET6)
+    return default_val;
+
+  for (idx = 0; ; ++idx)
+    {
+      unsigned int bits = list[idx].bits;
+      const uint8_t *mask = list[idx].prefix.s6_addr;
+      const uint8_t *val = in6->sin6_addr.s6_addr;
+
+      while (bits >= 8)
+       {
+         if (*mask != *val)
+           break;
+
+         ++mask;
+         ++val;
+         bits -= 8;
+       }
+
+      if (bits < 8)
+       {
+         if ((*mask & (0xff00 >> bits)) == (*val & (0xff00 >> bits)))
+           /* Match!  */
+           break;
+       }
+    }
+
+  return list[idx].val;
+}
+
+
+static int
+get_label (const struct sockaddr_in6 *in6)
+{
+  /* XXX What is a good default value?  */
+  return match_prefix (in6, labels, INT_MAX);
+}
+
+
+static int
+get_precedence (const struct sockaddr_in6 *in6)
+{
+  /* XXX What is a good default value?  */
+  return match_prefix (in6, precedence, 0);
+}
+
+
+/* Find last bit set in a word.  */
+static int
+fls (uint32_t a)
+{
+  uint32_t mask;
+  int n;
+  for (n = 0, mask = 1 << 31; n < 32; mask >>= 1, ++n)
+    if ((a & mask) != 0)
+      break;
+  return n;
+}
+
+
+static int
+rfc3484_sort (const void *p1, const void *p2, void *arg)
+{
+  const size_t idx1 = *(const size_t *) p1;
+  const size_t idx2 = *(const size_t *) p2;
+  struct sort_result_combo *src = (struct sort_result_combo *) arg;
+  struct sort_result *a1 = &src->results[idx1];
+  struct sort_result *a2 = &src->results[idx2];
+
+  /* Rule 1: Avoid unusable destinations.
+     We have the got_source_addr flag set if the destination is reachable.  */
+  if (a1->got_source_addr && ! a2->got_source_addr)
+    return -1;
+  if (! a1->got_source_addr && a2->got_source_addr)
+    return 1;
+
+
+  /* Rule 2: Prefer matching scope.  Only interesting if both
+     destination addresses are IPv6.  */
+  int a1_dst_scope
+    = get_scope ((struct sockaddr_in6 *) a1->dest_addr->ai_addr);
+
+  int a2_dst_scope
+    = get_scope ((struct sockaddr_in6 *) a2->dest_addr->ai_addr);
+
+  if (a1->got_source_addr)
+    {
+      int a1_src_scope = get_scope (&a1->source_addr);
+      int a2_src_scope = get_scope (&a2->source_addr);
+
+      if (a1_dst_scope == a1_src_scope && a2_dst_scope != a2_src_scope)
+       return -1;
+      if (a1_dst_scope != a1_src_scope && a2_dst_scope == a2_src_scope)
+       return 1;
+    }
+
+
+  /* Rule 3: Avoid deprecated addresses.  */
+  if (a1->got_source_addr)
+    {
+      if (!(a1->source_addr_flags & in6ai_deprecated)
+         && (a2->source_addr_flags & in6ai_deprecated))
+       return -1;
+      if ((a1->source_addr_flags & in6ai_deprecated)
+         && !(a2->source_addr_flags & in6ai_deprecated))
+       return 1;
+    }
+
+  /* Rule 4: Prefer home addresses.  */
+  if (a1->got_source_addr)
+    {
+      if (!(a1->source_addr_flags & in6ai_homeaddress)
+         && (a2->source_addr_flags & in6ai_homeaddress))
+       return 1;
+      if ((a1->source_addr_flags & in6ai_homeaddress)
+         && !(a2->source_addr_flags & in6ai_homeaddress))
+       return -1;
+    }
+
+  /* Rule 5: Prefer matching label.  */
+  if (a1->got_source_addr)
+    {
+      int a1_dst_label
+       = get_label ((struct sockaddr_in6 *) a1->dest_addr->ai_addr);
+      int a1_src_label = get_label (&a1->source_addr);
+
+      int a2_dst_label
+       = get_label ((struct sockaddr_in6 *) a2->dest_addr->ai_addr);
+      int a2_src_label = get_label (&a2->source_addr);
+
+      if (a1_dst_label == a1_src_label && a2_dst_label != a2_src_label)
+       return -1;
+      if (a1_dst_label != a1_src_label && a2_dst_label == a2_src_label)
+       return 1;
+    }
+
+
+  /* Rule 6: Prefer higher precedence.  */
+  int a1_prec
+    = get_precedence ((struct sockaddr_in6 *) a1->dest_addr->ai_addr);
+  int a2_prec
+    = get_precedence ((struct sockaddr_in6 *) a2->dest_addr->ai_addr);
+
+  if (a1_prec > a2_prec)
+    return -1;
+  if (a1_prec < a2_prec)
+    return 1;
+
+
+  /* Rule 7: Prefer native transport.  */
+  if (a1->got_source_addr)
+    {
+      /* The same interface index means the same interface which means
+        there is no difference in transport.  This should catch many
+        (most?) cases.  */
+      if (a1->index != a2->index)
+       {
+         int a1_native = a1->native;
+         int a2_native = a2->native;
+
+         if (a1_native == -1 || a2_native == -1)
+           {
+             uint32_t a1_index;
+             if (a1_native == -1)
+               {
+                 /* If we do not have the information use 'native' as
+                    the default.  */
+                 a1_native = 0;
+                 a1_index = a1->index;
+               }
+             else
+               a1_index = 0xffffffffu;
+
+             uint32_t a2_index;
+             if (a2_native == -1)
+               {
+                 /* If we do not have the information use 'native' as
+                    the default.  */
+                 a2_native = 0;
+                 a2_index = a2->index;
+               }
+             else
+               a2_index = 0xffffffffu;
+
+             __check_native (a1_index, &a1_native, a2_index, &a2_native);
+
+             /* Fill in the results in all the records.  */
+             for (int i = 0; i < src->nresults; ++i)
+               if (src->results[i].index == a1_index)
+                 {
+                   assert (src->results[i].native == -1
+                           || src->results[i].native == a1_native);
+                   src->results[i].native = a1_native;
+                 }
+               else if (src->results[i].index == a2_index)
+                 {
+                   assert (src->results[i].native == -1
+                           || src->results[i].native == a2_native);
+                   src->results[i].native = a2_native;
+                 }
+           }
+
+         if (a1_native && !a2_native)
+           return -1;
+         if (!a1_native && a2_native)
+           return 1;
+       }
+    }
+
+
+  /* Rule 8: Prefer smaller scope.  */
+  if (a1_dst_scope < a2_dst_scope)
+    return -1;
+  if (a1_dst_scope > a2_dst_scope)
+    return 1;
+
+
+  /* Rule 9: Use longest matching prefix.  */
+  if (a1->got_source_addr
+      && a1->dest_addr->ai_family == a2->dest_addr->ai_family)
+    {
+      int bit1 = 0;
+      int bit2 = 0;
+
+      if (a1->dest_addr->ai_family == PF_INET)
+       {
+         assert (a1->source_addr.sin6_family == PF_INET);
+         assert (a2->source_addr.sin6_family == PF_INET);
+
+         /* Outside of subnets, as defined by the network masks,
+            common address prefixes for IPv4 addresses make no sense.
+            So, define a non-zero value only if source and
+            destination address are on the same subnet.  */
+         struct sockaddr_in *in1_dst
+           = (struct sockaddr_in *) a1->dest_addr->ai_addr;
+         in_addr_t in1_dst_addr = ntohl (in1_dst->sin_addr.s_addr);
+         struct sockaddr_in *in1_src
+           = (struct sockaddr_in *) &a1->source_addr;
+         in_addr_t in1_src_addr = ntohl (in1_src->sin_addr.s_addr);
+         in_addr_t netmask1 = 0xffffffffu << (32 - a1->prefixlen);
+
+         if ((in1_src_addr & netmask1) == (in1_dst_addr & netmask1))
+           bit1 = fls (in1_dst_addr ^ in1_src_addr);
+
+         struct sockaddr_in *in2_dst
+           = (struct sockaddr_in *) a2->dest_addr->ai_addr;
+         in_addr_t in2_dst_addr = ntohl (in2_dst->sin_addr.s_addr);
+         struct sockaddr_in *in2_src
+           = (struct sockaddr_in *) &a2->source_addr;
+         in_addr_t in2_src_addr = ntohl (in2_src->sin_addr.s_addr);
+         in_addr_t netmask2 = 0xffffffffu << (32 - a2->prefixlen);
+
+         if ((in2_src_addr & netmask2) == (in2_dst_addr & netmask2))
+           bit2 = fls (in2_dst_addr ^ in2_src_addr);
+       }
+      else if (a1->dest_addr->ai_family == PF_INET6)
+       {
+         assert (a1->source_addr.sin6_family == PF_INET6);
+         assert (a2->source_addr.sin6_family == PF_INET6);
+
+         struct sockaddr_in6 *in1_dst;
+         struct sockaddr_in6 *in1_src;
+         struct sockaddr_in6 *in2_dst;
+         struct sockaddr_in6 *in2_src;
+
+         in1_dst = (struct sockaddr_in6 *) a1->dest_addr->ai_addr;
+         in1_src = (struct sockaddr_in6 *) &a1->source_addr;
+         in2_dst = (struct sockaddr_in6 *) a2->dest_addr->ai_addr;
+         in2_src = (struct sockaddr_in6 *) &a2->source_addr;
+
+         int i;
+         for (i = 0; i < 4; ++i)
+           if (in1_dst->sin6_addr.s6_addr32[i]
+               != in1_src->sin6_addr.s6_addr32[i]
+               || (in2_dst->sin6_addr.s6_addr32[i]
+                   != in2_src->sin6_addr.s6_addr32[i]))
+             break;
+
+         if (i < 4)
+           {
+             bit1 = fls (ntohl (in1_dst->sin6_addr.s6_addr32[i]
+                                ^ in1_src->sin6_addr.s6_addr32[i]));
+             bit2 = fls (ntohl (in2_dst->sin6_addr.s6_addr32[i]
+                                ^ in2_src->sin6_addr.s6_addr32[i]));
+           }
+       }
+
+      if (bit1 > bit2)
+       return -1;
+      if (bit1 < bit2)
+       return 1;
+    }
+
+
+  /* Rule 10: Otherwise, leave the order unchanged.  To ensure this
+     compare with the value indicating the order in which the entries
+     have been received from the services.  NB: no two entries can have
+     the same order so the test will never return zero.  */
+  return idx1 < idx2 ? -1 : 1;
+}
+
+
+static int
+in6aicmp (const void *p1, const void *p2)
+{
+  struct in6addrinfo *a1 = (struct in6addrinfo *) p1;
+  struct in6addrinfo *a2 = (struct in6addrinfo *) p2;
+
+  return memcmp (a1->addr, a2->addr, sizeof (a1->addr));
+}
+
+
+/* Name of the config file for RFC 3484 sorting (for now).  */
+#define GAICONF_FNAME "/etc/gai.conf"
+
+
+/* Non-zero if we are supposed to reload the config file automatically
+   whenever it changed.  */
+static int gaiconf_reload_flag;
+
+/* Non-zero if gaiconf_reload_flag was ever set to true.  */
+static int gaiconf_reload_flag_ever_set;
+
+/* Last modification time.  */
+static __time_t gaiconf_mtime;
+
+
+libc_freeres_fn(fini)
+{
+  if (labels != default_labels)
+    {
+      const struct prefixentry *old = labels;
+      labels = default_labels;
+      free ((void *) old);
+    }
+
+  if (precedence != default_precedence)
+    {
+      const struct prefixentry *old = precedence;
+      precedence = default_precedence;
+      free ((void *) old);
+    }
+
+  if (scopes != default_scopes)
+    {
+      const struct scopeentry *old = scopes;
+      scopes = default_scopes;
+      free ((void *) old);
+    }
+}
+
+
+struct prefixlist
+{
+  struct prefixentry entry;
+  struct prefixlist *next;
+};
+
+
+struct scopelist
+{
+  struct scopeentry entry;
+  struct scopelist *next;
+};
+
+
+static void
+free_prefixlist (struct prefixlist *list)
+{
+  while (list != NULL)
+    {
+      struct prefixlist *oldp = list;
+      list = list->next;
+      free (oldp);
+    }
+}
+
+
+static void
+free_scopelist (struct scopelist *list)
+{
+  while (list != NULL)
+    {
+      struct scopelist *oldp = list;
+      list = list->next;
+      free (oldp);
+    }
+}
+
+
+static int
+prefixcmp (const void *p1, const void *p2)
+{
+  const struct prefixentry *e1 = (const struct prefixentry *) p1;
+  const struct prefixentry *e2 = (const struct prefixentry *) p2;
+
+  if (e1->bits < e2->bits)
+    return 1;
+  if (e1->bits == e2->bits)
+    return 0;
   return -1;
 }
-stub_warning(__res_maybe_init)
-libc_hidden_def (__res_maybe_init)
 
-int
-getaddrinfo (const char *name, const char *service, const struct addrinfo *req,
-            struct addrinfo **pai)
+
+static int
+scopecmp (const void *p1, const void *p2)
 {
-  __set_errno (ENOSYS);
-  return EAI_SYSTEM;
+  const struct scopeentry *e1 = (const struct scopeentry *) p1;
+  const struct scopeentry *e2 = (const struct scopeentry *) p2;
+
+  if (e1->netmask > e2->netmask)
+    return -1;
+  if (e1->netmask == e2->netmask)
+    return 0;
+  return 1;
 }
-stub_warning (getaddrinfo)
-libc_hidden_def (getaddrinfo)
 
-void
-freeaddrinfo (struct addrinfo *ai)
+
+static void
+gaiconf_init (void)
 {
-  /* Nothing.  */
+  struct prefixlist *labellist = NULL;
+  size_t nlabellist = 0;
+  bool labellist_nullbits = false;
+  struct prefixlist *precedencelist = NULL;
+  size_t nprecedencelist = 0;
+  bool precedencelist_nullbits = false;
+  struct scopelist *scopelist =  NULL;
+  size_t nscopelist = 0;
+  bool scopelist_nullbits = false;
+
+  FILE *fp = fopen (GAICONF_FNAME, "rc");
+  if (fp != NULL)
+    {
+      struct stat64 st;
+      if (__fxstat64 (_STAT_VER, fileno (fp), &st) != 0)
+       {
+         fclose (fp);
+         goto no_file;
+       }
+
+      char *line = NULL;
+      size_t linelen = 0;
+
+      __fsetlocking (fp, FSETLOCKING_BYCALLER);
+
+      while (!feof_unlocked (fp))
+       {
+         ssize_t n = __getline (&line, &linelen, fp);
+         if (n <= 0)
+           break;
+
+         /* Handle comments.  No escaping possible so this is easy.  */
+         char *cp = strchr (line, '#');
+         if (cp != NULL)
+           *cp = '\0';
+
+         cp = line;
+         while (isspace (*cp))
+           ++cp;
+
+         char *cmd = cp;
+         while (*cp != '\0' && !isspace (*cp))
+           ++cp;
+         size_t cmdlen = cp - cmd;
+
+         if (*cp != '\0')
+           *cp++ = '\0';
+         while (isspace (*cp))
+           ++cp;
+
+         char *val1 = cp;
+         while (*cp != '\0' && !isspace (*cp))
+           ++cp;
+         size_t val1len = cp - cmd;
+
+         /* We always need at least two values.  */
+         if (val1len == 0)
+           continue;
+
+         if (*cp != '\0')
+           *cp++ = '\0';
+         while (isspace (*cp))
+           ++cp;
+
+         char *val2 = cp;
+         while (*cp != '\0' && !isspace (*cp))
+           ++cp;
+
+         /*  Ignore the rest of the line.  */
+         *cp = '\0';
+
+         struct prefixlist **listp;
+         size_t *lenp;
+         bool *nullbitsp;
+         switch (cmdlen)
+           {
+           case 5:
+             if (strcmp (cmd, "label") == 0)
+               {
+                 struct in6_addr prefix;
+                 unsigned long int bits;
+                 unsigned long int val;
+                 char *endp;
+
+                 listp = &labellist;
+                 lenp = &nlabellist;
+                 nullbitsp = &labellist_nullbits;
+
+               new_elem:
+                 bits = 128;
+                 __set_errno (0);
+                 cp = strchr (val1, '/');
+                 if (cp != NULL)
+                   *cp++ = '\0';
+                 if (inet_pton (AF_INET6, val1, &prefix)
+                     && (cp == NULL
+                         || (bits = strtoul (cp, &endp, 10)) != ULONG_MAX
+                         || errno != ERANGE)
+                     && *endp == '\0'
+                     && bits <= 128
+                     && ((val = strtoul (val2, &endp, 10)) != ULONG_MAX
+                         || errno != ERANGE)
+                     && *endp == '\0'
+                     && val <= INT_MAX)
+                   {
+                     struct prefixlist *newp = malloc (sizeof (*newp));
+                     if (newp == NULL)
+                       {
+                         free (line);
+                         fclose (fp);
+                         goto no_file;
+                       }
+
+                     memcpy (&newp->entry.prefix, &prefix, sizeof (prefix));
+                     newp->entry.bits = bits;
+                     newp->entry.val = val;
+                     newp->next = *listp;
+                     *listp = newp;
+                     ++*lenp;
+                     *nullbitsp |= bits == 0;
+                   }
+               }
+             break;
+
+           case 6:
+             if (strcmp (cmd, "reload") == 0)
+               {
+                 gaiconf_reload_flag = strcmp (val1, "yes") == 0;
+                 if (gaiconf_reload_flag)
+                   gaiconf_reload_flag_ever_set = 1;
+               }
+             break;
+
+           case 7:
+             if (strcmp (cmd, "scopev4") == 0)
+               {
+                 struct in6_addr prefix;
+                 unsigned long int bits;
+                 unsigned long int val;
+                 char *endp;
+
+                 bits = 32;
+                 __set_errno (0);
+                 cp = strchr (val1, '/');
+                 if (cp != NULL)
+                   *cp++ = '\0';
+                 if (inet_pton (AF_INET6, val1, &prefix))
+                   {
+                     bits = 128;
+                     if (IN6_IS_ADDR_V4MAPPED (&prefix)
+                         && (cp == NULL
+                             || (bits = strtoul (cp, &endp, 10)) != ULONG_MAX
+                             || errno != ERANGE)
+                         && *endp == '\0'
+                         && bits >= 96
+                         && bits <= 128
+                         && ((val = strtoul (val2, &endp, 10)) != ULONG_MAX
+                             || errno != ERANGE)
+                         && *endp == '\0'
+                         && val <= INT_MAX)
+                       {
+                         struct scopelist *newp;
+                       new_scope:
+                         newp = malloc (sizeof (*newp));
+                         if (newp == NULL)
+                           {
+                             free (line);
+                             fclose (fp);
+                             goto no_file;
+                           }
+
+                         newp->entry.netmask = htonl (bits != 96
+                                                      ? (0xffffffff
+                                                         << (128 - bits))
+                                                      : 0);
+                         newp->entry.addr32 = (prefix.s6_addr32[3]
+                                               & newp->entry.netmask);
+                         newp->entry.scope = val;
+                         newp->next = scopelist;
+                         scopelist = newp;
+                         ++nscopelist;
+                         scopelist_nullbits |= bits == 96;
+                       }
+                   }
+                 else if (inet_pton (AF_INET, val1, &prefix.s6_addr32[3])
+                          && (cp == NULL
+                              || (bits = strtoul (cp, &endp, 10)) != ULONG_MAX
+                              || errno != ERANGE)
+                          && *endp == '\0'
+                          && bits <= 32
+                          && ((val = strtoul (val2, &endp, 10)) != ULONG_MAX
+                              || errno != ERANGE)
+                          && *endp == '\0'
+                          && val <= INT_MAX)
+                   {
+                     bits += 96;
+                     goto new_scope;
+                   }
+               }
+             break;
+
+           case 10:
+             if (strcmp (cmd, "precedence") == 0)
+               {
+                 listp = &precedencelist;
+                 lenp = &nprecedencelist;
+                 nullbitsp = &precedencelist_nullbits;
+                 goto new_elem;
+               }
+             break;
+           }
+       }
+
+      free (line);
+
+      fclose (fp);
+
+      /* Create the array for the labels.  */
+      struct prefixentry *new_labels;
+      if (nlabellist > 0)
+       {
+         if (!labellist_nullbits)
+           ++nlabellist;
+         new_labels = malloc (nlabellist * sizeof (*new_labels));
+         if (new_labels == NULL)
+           goto no_file;
+
+         int i = nlabellist;
+         if (!labellist_nullbits)
+           {
+             --i;
+             memset (&new_labels[i].prefix, '\0', sizeof (struct in6_addr));
+             new_labels[i].bits = 0;
+             new_labels[i].val = 1;
+           }
+
+         struct prefixlist *l = labellist;
+         while (i-- > 0)
+           {
+             new_labels[i] = l->entry;
+             l = l->next;
+           }
+         free_prefixlist (labellist);
+
+         /* Sort the entries so that the most specific ones are at
+            the beginning.  */
+         qsort (new_labels, nlabellist, sizeof (*new_labels), prefixcmp);
+       }
+      else
+       new_labels = (struct prefixentry *) default_labels;
+
+      struct prefixentry *new_precedence;
+      if (nprecedencelist > 0)
+       {
+         if (!precedencelist_nullbits)
+           ++nprecedencelist;
+         new_precedence = malloc (nprecedencelist * sizeof (*new_precedence));
+         if (new_precedence == NULL)
+           {
+             if (new_labels != default_labels)
+               free (new_labels);
+             goto no_file;
+           }
+
+         int i = nprecedencelist;
+         if (!precedencelist_nullbits)
+           {
+             --i;
+             memset (&new_precedence[i].prefix, '\0',
+                     sizeof (struct in6_addr));
+             new_precedence[i].bits = 0;
+             new_precedence[i].val = 40;
+           }
+
+         struct prefixlist *l = precedencelist;
+         while (i-- > 0)
+           {
+             new_precedence[i] = l->entry;
+             l = l->next;
+           }
+         free_prefixlist (precedencelist);
+
+         /* Sort the entries so that the most specific ones are at
+            the beginning.  */
+         qsort (new_precedence, nprecedencelist, sizeof (*new_precedence),
+                prefixcmp);
+       }
+      else
+       new_precedence = (struct prefixentry *) default_precedence;
+
+      struct scopeentry *new_scopes;
+      if (nscopelist > 0)
+       {
+         if (!scopelist_nullbits)
+           ++nscopelist;
+         new_scopes = malloc (nscopelist * sizeof (*new_scopes));
+         if (new_scopes == NULL)
+           {
+             if (new_labels != default_labels)
+               free (new_labels);
+             if (new_precedence != default_precedence)
+               free (new_precedence);
+             goto no_file;
+           }
+
+         int i = nscopelist;
+         if (!scopelist_nullbits)
+           {
+             --i;
+             new_scopes[i].addr32 = 0;
+             new_scopes[i].netmask = 0;
+             new_scopes[i].scope = 14;
+           }
+
+         struct scopelist *l = scopelist;
+         while (i-- > 0)
+           {
+             new_scopes[i] = l->entry;
+             l = l->next;
+           }
+         free_scopelist (scopelist);
+
+         /* Sort the entries so that the most specific ones are at
+            the beginning.  */
+         qsort (new_scopes, nscopelist, sizeof (*new_scopes),
+                scopecmp);
+       }
+      else
+       new_scopes = (struct scopeentry *) default_scopes;
+
+      /* Now we are ready to replace the values.  */
+      const struct prefixentry *old = labels;
+      labels = new_labels;
+      if (old != default_labels)
+       free ((void *) old);
+
+      old = precedence;
+      precedence = new_precedence;
+      if (old != default_precedence)
+       free ((void *) old);
+
+      const struct scopeentry *oldscope = scopes;
+      scopes = new_scopes;
+      if (oldscope != default_scopes)
+       free ((void *) oldscope);
+
+      gaiconf_mtime = st.st_mtime;
+    }
+  else
+    {
+    no_file:
+      free_prefixlist (labellist);
+      free_prefixlist (precedencelist);
+      free_scopelist (scopelist);
+
+      /* If we previously read the file but it is gone now, free the
+        old data and use the builtin one.  Leave the reload flag
+        alone.  */
+      fini ();
+    }
 }
-stub_warning (freeaddrinfo)
-libc_hidden_def (freeaddrinfo)
 
-int
-inet_pton(int af, const char *src, void *dst)
+
+static void
+gaiconf_reload (void)
 {
-  __set_errno (ENOSYS);
-  return NULL;
+  struct stat64 st;
+  if (__xstat64 (_STAT_VER, GAICONF_FNAME, &st) != 0
+      || memcmp (&st.st_mtime, &gaiconf_mtime, sizeof (gaiconf_mtime)) != 0)
+    gaiconf_init ();
 }
-stub_warning(inet_pton)
-libc_hidden_def (inet_pton)
+
 
 int
-__inet_aton(const char *cp, struct in_addr *addr)
+getaddrinfo (const char *name, const char *service,
+            const struct addrinfo *hints, struct addrinfo **pai)
 {
-  __set_errno (ENOSYS);
-  return NULL;
+  int i = 0, last_i = 0;
+  int nresults = 0;
+  struct addrinfo *p = NULL;
+  struct gaih_service gaih_service, *pservice;
+  struct addrinfo local_hints;
+
+  if (name != NULL && name[0] == '*' && name[1] == 0)
+    name = NULL;
+
+  if (service != NULL && service[0] == '*' && service[1] == 0)
+    service = NULL;
+
+  if (name == NULL && service == NULL)
+    return EAI_NONAME;
+
+  if (hints == NULL)
+    hints = &default_hints;
+
+  if (hints->ai_flags
+      & ~(AI_PASSIVE|AI_CANONNAME|AI_NUMERICHOST|AI_ADDRCONFIG|AI_V4MAPPED
+#ifdef HAVE_LIBIDN
+         |AI_IDN|AI_CANONIDN|AI_IDN_ALLOW_UNASSIGNED
+         |AI_IDN_USE_STD3_ASCII_RULES
+#endif
+         |AI_NUMERICSERV|AI_ALL))
+    return EAI_BADFLAGS;
+
+  if ((hints->ai_flags & AI_CANONNAME) && name == NULL)
+    return EAI_BADFLAGS;
+
+  struct in6addrinfo *in6ai = NULL;
+  size_t in6ailen = 0;
+  bool seen_ipv4 = false;
+  bool seen_ipv6 = false;
+  /* We might need information about what interfaces are available.
+     Also determine whether we have IPv4 or IPv6 interfaces or both.  We
+     cannot cache the results since new interfaces could be added at
+     any time.  */
+  __check_pf (&seen_ipv4, &seen_ipv6, &in6ai, &in6ailen);
+
+  if (hints->ai_flags & AI_ADDRCONFIG)
+    {
+      /* Now make a decision on what we return, if anything.  */
+      if (hints->ai_family == PF_UNSPEC && (seen_ipv4 || seen_ipv6))
+       {
+         /* If we haven't seen both IPv4 and IPv6 interfaces we can
+            narrow down the search.  */
+         if ((! seen_ipv4 || ! seen_ipv6) && (seen_ipv4 || seen_ipv6))
+           {
+             local_hints = *hints;
+             local_hints.ai_family = seen_ipv4 ? PF_INET : PF_INET6;
+             hints = &local_hints;
+           }
+       }
+      else if ((hints->ai_family == PF_INET && ! seen_ipv4)
+              || (hints->ai_family == PF_INET6 && ! seen_ipv6))
+       {
+         /* We cannot possibly return a valid answer.  */
+         free (in6ai);
+         return EAI_NONAME;
+       }
+    }
+
+  if (service && service[0])
+    {
+      char *c;
+      gaih_service.name = service;
+      gaih_service.num = strtoul (gaih_service.name, &c, 10);
+      if (*c != '\0')
+       {
+         if (hints->ai_flags & AI_NUMERICSERV)
+           {
+             free (in6ai);
+             return EAI_NONAME;
+           }
+
+         gaih_service.num = -1;
+       }
+
+      pservice = &gaih_service;
+    }
+  else
+    pservice = NULL;
+
+  struct addrinfo **end = &p;
+
+  unsigned int naddrs = 0;
+  if (hints->ai_family == AF_UNSPEC || hints->ai_family == AF_INET
+      || hints->ai_family == AF_INET6)
+    {
+      last_i = gaih_inet (name, pservice, hints, end, &naddrs);
+      if (last_i != 0)
+       {
+         freeaddrinfo (p);
+         free (in6ai);
+
+         return -(last_i & GAIH_EAI);
+       }
+      while (*end)
+       {
+         end = &((*end)->ai_next);
+         ++nresults;
+       }
+    }
+  else
+    {
+      free (in6ai);
+      return EAI_FAMILY;
+    }
+
+  if (naddrs > 1)
+    {
+      /* Read the config file.  */
+      __libc_once_define (static, once);
+      __typeof (once) old_once = once;
+      __libc_once (once, gaiconf_init);
+      /* Sort results according to RFC 3484.  */
+      struct sort_result results[nresults];
+      size_t order[nresults];
+      struct addrinfo *q;
+      struct addrinfo *last = NULL;
+      char *canonname = NULL;
+
+      /* If we have information about deprecated and temporary addresses
+        sort the array now.  */
+      if (in6ai != NULL)
+       qsort (in6ai, in6ailen, sizeof (*in6ai), in6aicmp);
+
+      int fd = -1;
+      int af = AF_UNSPEC;
+
+      for (i = 0, q = p; q != NULL; ++i, last = q, q = q->ai_next)
+       {
+         results[i].dest_addr = q;
+         results[i].native = -1;
+         order[i] = i;
+
+         /* If we just looked up the address for a different
+            protocol, reuse the result.  */
+         if (last != NULL && last->ai_addrlen == q->ai_addrlen
+             && memcmp (last->ai_addr, q->ai_addr, q->ai_addrlen) == 0)
+           {
+             memcpy (&results[i].source_addr, &results[i - 1].source_addr,
+                     results[i - 1].source_addr_len);
+             results[i].source_addr_len = results[i - 1].source_addr_len;
+             results[i].got_source_addr = results[i - 1].got_source_addr;
+             results[i].source_addr_flags = results[i - 1].source_addr_flags;
+             results[i].prefixlen = results[i - 1].prefixlen;
+             results[i].index = results[i - 1].index;
+           }
+         else
+           {
+             results[i].got_source_addr = false;
+             results[i].source_addr_flags = 0;
+             results[i].prefixlen = 0;
+             results[i].index = 0xffffffffu;
+
+             /* We overwrite the type with SOCK_DGRAM since we do not
+                want connect() to connect to the other side.  If we
+                cannot determine the source address remember this
+                fact.  */
+             if (fd == -1 || (af == AF_INET && q->ai_family == AF_INET6))
+               {
+                 if (fd != -1)
+                 close_retry:
+                   close_not_cancel_no_status (fd);
+                 af = q->ai_family;
+                 fd = __socket (af, SOCK_DGRAM, IPPROTO_IP);
+               }
+             else
+               {
+                 /* Reset the connection.  */
+                 struct sockaddr sa = { .sa_family = AF_UNSPEC };
+                 __connect (fd, &sa, sizeof (sa));
+               }
+
+             socklen_t sl = sizeof (results[i].source_addr);
+             if (fd != -1
+                 && __connect (fd, q->ai_addr, q->ai_addrlen) == 0
+                 && __getsockname (fd,
+                                   (struct sockaddr *) &results[i].source_addr,
+                                   &sl) == 0)
+               {
+                 results[i].source_addr_len = sl;
+                 results[i].got_source_addr = true;
+
+                 if (in6ai != NULL)
+                   {
+                     /* See whether the source address is on the list of
+                        deprecated or temporary addresses.  */
+                     struct in6addrinfo tmp;
+
+                     if (q->ai_family == AF_INET && af == AF_INET)
+                       {
+                         struct sockaddr_in *sinp
+                           = (struct sockaddr_in *) &results[i].source_addr;
+                         tmp.addr[0] = 0;
+                         tmp.addr[1] = 0;
+                         tmp.addr[2] = htonl (0xffff);
+                         tmp.addr[3] = sinp->sin_addr.s_addr;
+                       }
+                     else
+                       {
+                         struct sockaddr_in6 *sin6p
+                           = (struct sockaddr_in6 *) &results[i].source_addr;
+                         memcpy (tmp.addr, &sin6p->sin6_addr, IN6ADDRSZ);
+                       }
+
+                     struct in6addrinfo *found
+                       = bsearch (&tmp, in6ai, in6ailen, sizeof (*in6ai),
+                                  in6aicmp);
+                     if (found != NULL)
+                       {
+                         results[i].source_addr_flags = found->flags;
+                         results[i].prefixlen = found->prefixlen;
+                         results[i].index = found->index;
+                       }
+                   }
+
+                 if (q->ai_family == AF_INET && af == AF_INET6)
+                   {
+                     /* We have to convert the address.  The socket is
+                        IPv6 and the request is for IPv4.  */
+                     struct sockaddr_in6 *sin6
+                       = (struct sockaddr_in6 *) &results[i].source_addr;
+                     struct sockaddr_in *sin
+                       = (struct sockaddr_in *) &results[i].source_addr;
+                     assert (IN6_IS_ADDR_V4MAPPED (sin6->sin6_addr.s6_addr32));
+                     sin->sin_family = AF_INET;
+                     /* We do not have to initialize sin_port since this
+                        fields has the same position and size in the IPv6
+                        structure.  */
+                     assert (offsetof (struct sockaddr_in, sin_port)
+                             == offsetof (struct sockaddr_in6, sin6_port));
+                     assert (sizeof (sin->sin_port)
+                             == sizeof (sin6->sin6_port));
+                     memcpy (&sin->sin_addr,
+                             &sin6->sin6_addr.s6_addr32[3], INADDRSZ);
+                     results[i].source_addr_len = sizeof (struct sockaddr_in);
+                   }
+               }
+             else if (errno == EAFNOSUPPORT && af == AF_INET6
+                      && q->ai_family == AF_INET)
+               /* This could mean IPv6 sockets are IPv6-only.  */
+               goto close_retry;
+             else
+               /* Just make sure that if we have to process the same
+                  address again we do not copy any memory.  */
+               results[i].source_addr_len = 0;
+           }
+
+         /* Remember the canonical name.  */
+         if (q->ai_canonname != NULL)
+           {
+             assert (canonname == NULL);
+             canonname = q->ai_canonname;
+             q->ai_canonname = NULL;
+           }
+       }
+
+      if (fd != -1)
+       close_not_cancel_no_status (fd);
+
+      /* We got all the source addresses we can get, now sort using
+        the information.  */
+      struct sort_result_combo src
+       = { .results = results, .nresults = nresults };
+      if (__builtin_expect (gaiconf_reload_flag_ever_set, 0))
+       {
+         __libc_lock_define_initialized (static, lock);
+
+         __libc_lock_lock (lock);
+         if (old_once && gaiconf_reload_flag)
+           gaiconf_reload ();
+         qsort_r (order, nresults, sizeof (order[0]), rfc3484_sort, &src);
+         __libc_lock_unlock (lock);
+       }
+      else
+       qsort_r (order, nresults, sizeof (order[0]), rfc3484_sort, &src);
+
+      /* Queue the results up as they come out of sorting.  */
+      q = p = results[order[0]].dest_addr;
+      for (i = 1; i < nresults; ++i)
+       q = q->ai_next = results[order[i]].dest_addr;
+      q->ai_next = NULL;
+
+      /* Fill in the canonical name into the new first entry.  */
+      p->ai_canonname = canonname;
+    }
+
+  free (in6ai);
+
+  if (p)
+    {
+      *pai = p;
+      return 0;
+    }
+
+  return last_i ? -(last_i & GAIH_EAI) : EAI_NONAME;
 }
-stub_warning(__inet_aton)
-weak_alias (__inet_aton, inet_aton)
-libc_hidden_def (__inet_aton)
-libc_hidden_weak (inet_aton)
+libc_hidden_def (getaddrinfo)
+
+static_link_warning (getaddrinfo)
+
+void
+freeaddrinfo (struct addrinfo *ai)
+{
+  struct addrinfo *p;
 
-#include <stub-tag.h>
+  while (ai != NULL)
+    {
+      p = ai;
+      ai = ai->ai_next;
+      free (p->ai_canonname);
+      free (p);
+    }
+}
+libc_hidden_def (freeaddrinfo)
diff --git a/tools/compilers/gcc-glibc/glibc-2.11.1-ros/sysdeps/ros/getpeername.c b/tools/compilers/gcc-glibc/glibc-2.11.1-ros/sysdeps/ros/getpeername.c
new file mode 100644 (file)
index 0000000..a02c7b3
--- /dev/null
@@ -0,0 +1,35 @@
+/* Copyright (C) 1991, 1995, 1996, 1997 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include <errno.h>
+#include <sys/socket.h>
+
+/* Put the address of the peer connected to socket FD into *ADDR
+   (which is *LEN bytes long), and its actual length into *LEN.  */
+int
+__getpeername (fd, addr, len)
+     int fd;
+     __SOCKADDR_ARG addr;
+     socklen_t *len;
+{
+  __set_errno (ENOSYS);
+  return -1;
+}
+weak_alias (__getpeername, getpeername)
+stub_warning (getpeername)
+#include <stub-tag.h>
index 5d8a18a..6de6069 100644 (file)
@@ -34,52 +34,3 @@ __isatty (int fd)
   return ret < 0 ? -1 : ((s.st_mode & S_IFCHR) ? 1 : 0);
 }
 weak_alias (__isatty, isatty)
-
-/* Return the pathname of the pseudo terminal slave assoicated with
-   the master FD is open on, or NULL on errors.
-   The returned storage is good until the next call to this function.  */
-char *
-ptsname (int fd)
-{
-  static char buffer[sizeof (_PATH_TTY) + 2];
-  return __ptsname_r (fd, buffer, sizeof (buffer)) != 0 ? NULL : buffer;
-}
-
-
-/* Store at most BUFLEN characters of the pathname of the slave pseudo
-   terminal associated with the master FD is open on in BUF.
-   Return 0 on success, otherwise an error number.  */
-int
-__ptsname_r (int fd, char *buf, size_t buflen)
-{
-  int save_errno = errno;
-  struct stat st;
-
-  if (buf == NULL)
-    {
-      __set_errno (EINVAL);
-      return EINVAL;
-    }
-
-  if (!__isatty (fd))
-    /* We rely on isatty to set errno properly (i.e. EBADF or ENOTTY).  */
-    return errno;
-
-  if (buflen < strlen (_PATH_TTY) + 3)
-    {
-      __set_errno (ERANGE);
-      return ERANGE;
-    }
-
-  if (__ttyname_r (fd, buf, buflen) != 0)
-    return errno;
-
-  buf[sizeof (_PATH_DEV) - 1] = 't';
-
-  if (__stat (buf, &st) < 0)
-    return errno;
-
-  __set_errno (save_errno);
-  return 0;
-}
-weak_alias (__ptsname_r, ptsname_r)
diff --git a/tools/compilers/gcc-glibc/glibc-2.11.1-ros/sysdeps/ros/net/if.h b/tools/compilers/gcc-glibc/glibc-2.11.1-ros/sysdeps/ros/net/if.h
new file mode 100644 (file)
index 0000000..a4d54d0
--- /dev/null
@@ -0,0 +1,207 @@
+/* net/if.h -- declarations for inquiring about network interfaces
+   Copyright (C) 1997,98,99,2000,2001 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#ifndef _NET_IF_H
+#define _NET_IF_H      1
+
+/* ROS note: this is the GNU sysdep's net/if.h, unaltered */
+
+#include <features.h>
+
+#ifdef __USE_MISC
+# include <sys/types.h>
+# include <sys/socket.h>
+#endif
+
+
+/* Length of interface name.  */
+#define IF_NAMESIZE    16
+
+struct if_nameindex
+  {
+    unsigned int if_index;     /* 1, 2, ... */
+    char *if_name;             /* null terminated name: "eth0", ... */
+  };
+
+
+#ifdef __USE_MISC
+/* Standard interface flags. */
+enum
+  {
+    IFF_UP = 0x1,              /* Interface is up.  */
+# define IFF_UP        IFF_UP
+    IFF_BROADCAST = 0x2,       /* Broadcast address valid.  */
+# define IFF_BROADCAST IFF_BROADCAST
+    IFF_DEBUG = 0x4,           /* Turn on debugging.  */
+# define IFF_DEBUG     IFF_DEBUG
+    IFF_LOOPBACK = 0x8,                /* Is a loopback net.  */
+# define IFF_LOOPBACK  IFF_LOOPBACK
+    IFF_POINTOPOINT = 0x10,    /* Interface is point-to-point link.  */
+# define IFF_POINTOPOINT IFF_POINTOPOINT
+    IFF_NOTRAILERS = 0x20,     /* Avoid use of trailers.  */
+# define IFF_NOTRAILERS        IFF_NOTRAILERS
+    IFF_RUNNING = 0x40,                /* Resources allocated.  */
+# define IFF_RUNNING   IFF_RUNNING
+    IFF_NOARP = 0x80,          /* No address resolution protocol.  */
+# define IFF_NOARP     IFF_NOARP
+    IFF_PROMISC = 0x100,       /* Receive all packets.  */
+# define IFF_PROMISC   IFF_PROMISC
+
+    /* Not supported */
+    IFF_ALLMULTI = 0x200,      /* Receive all multicast packets.  */
+# define IFF_ALLMULTI  IFF_ALLMULTI
+
+    IFF_MASTER = 0x400,                /* Master of a load balancer.  */
+# define IFF_MASTER    IFF_MASTER
+    IFF_SLAVE = 0x800,         /* Slave of a load balancer.  */
+# define IFF_SLAVE     IFF_SLAVE
+
+    IFF_MULTICAST = 0x1000,    /* Supports multicast.  */
+# define IFF_MULTICAST IFF_MULTICAST
+
+    IFF_PORTSEL = 0x2000,      /* Can set media type.  */
+# define IFF_PORTSEL   IFF_PORTSEL
+    IFF_AUTOMEDIA = 0x4000,    /* Auto media select active.  */
+# define IFF_AUTOMEDIA IFF_AUTOMEDIA
+    IFF_DYNAMIC = 0x8000       /* Dialup device with changing addresses.  */
+# define IFF_DYNAMIC   IFF_DYNAMIC
+  };
+
+/* The ifaddr structure contains information about one address of an
+   interface.  They are maintained by the different address families,
+   are allocated and attached when an address is set, and are linked
+   together so all addresses for an interface can be located.  */
+
+struct ifaddr
+  {
+    struct sockaddr ifa_addr;  /* Address of interface.  */
+    union
+      {
+       struct sockaddr ifu_broadaddr;
+       struct sockaddr ifu_dstaddr;
+      } ifa_ifu;
+    struct iface *ifa_ifp;     /* Back-pointer to interface.  */
+    struct ifaddr *ifa_next;   /* Next address for interface.  */
+  };
+
+# define ifa_broadaddr ifa_ifu.ifu_broadaddr   /* broadcast address    */
+# define ifa_dstaddr   ifa_ifu.ifu_dstaddr     /* other end of link    */
+
+/* Device mapping structure. I'd just gone off and designed a
+   beautiful scheme using only loadable modules with arguments for
+   driver options and along come the PCMCIA people 8)
+
+   Ah well. The get() side of this is good for WDSETUP, and it'll be
+   handy for debugging things. The set side is fine for now and being
+   very small might be worth keeping for clean configuration.  */
+
+struct ifmap
+  {
+    unsigned long int mem_start;
+    unsigned long int mem_end;
+    unsigned short int base_addr;
+    unsigned char irq;
+    unsigned char dma;
+    unsigned char port;
+    /* 3 bytes spare */
+  };
+
+/* Interface request structure used for socket ioctl's.  All interface
+   ioctl's must have parameter definitions which begin with ifr_name.
+   The remainder may be interface specific.  */
+
+struct ifreq
+  {
+# define IFHWADDRLEN   6
+# define IFNAMSIZ      IF_NAMESIZE
+    union
+      {
+       char ifrn_name[IFNAMSIZ];       /* Interface name, e.g. "en0".  */
+      } ifr_ifrn;
+
+    union
+      {
+       struct sockaddr ifru_addr;
+       struct sockaddr ifru_dstaddr;
+       struct sockaddr ifru_broadaddr;
+       struct sockaddr ifru_netmask;
+       struct sockaddr ifru_hwaddr;
+       short int ifru_flags;
+       int ifru_ivalue;
+       int ifru_mtu;
+       struct ifmap ifru_map;
+       char ifru_slave[IFNAMSIZ];      /* Just fits the size */
+       char ifru_newname[IFNAMSIZ];
+       __caddr_t ifru_data;
+      } ifr_ifru;
+  };
+# define ifr_name      ifr_ifrn.ifrn_name      /* interface name       */
+# define ifr_hwaddr    ifr_ifru.ifru_hwaddr    /* MAC address          */
+# define ifr_addr      ifr_ifru.ifru_addr      /* address              */
+# define ifr_dstaddr   ifr_ifru.ifru_dstaddr   /* other end of p-p lnk */
+# define ifr_broadaddr ifr_ifru.ifru_broadaddr /* broadcast address    */
+# define ifr_netmask   ifr_ifru.ifru_netmask   /* interface net mask   */
+# define ifr_flags     ifr_ifru.ifru_flags     /* flags                */
+# define ifr_metric    ifr_ifru.ifru_ivalue    /* metric               */
+# define ifr_mtu       ifr_ifru.ifru_mtu       /* mtu                  */
+# define ifr_map       ifr_ifru.ifru_map       /* device map           */
+# define ifr_slave     ifr_ifru.ifru_slave     /* slave device         */
+# define ifr_data      ifr_ifru.ifru_data      /* for use by interface */
+# define ifr_ifindex   ifr_ifru.ifru_ivalue    /* interface index      */
+# define ifr_bandwidth ifr_ifru.ifru_ivalue    /* link bandwidth       */
+# define ifr_qlen      ifr_ifru.ifru_ivalue    /* queue length         */
+# define ifr_newname   ifr_ifru.ifru_newname   /* New name             */
+# define _IOT_ifreq    _IOT(_IOTS(char),IFNAMSIZ,_IOTS(char),16,0,0)
+# define _IOT_ifreq_short _IOT(_IOTS(char),IFNAMSIZ,_IOTS(short),1,0,0)
+# define _IOT_ifreq_int        _IOT(_IOTS(char),IFNAMSIZ,_IOTS(int),1,0,0)
+
+
+/* Structure used in SIOCGIFCONF request.  Used to retrieve interface
+   configuration for machine (useful for programs which must know all
+   networks accessible).  */
+
+struct ifconf
+  {
+    int        ifc_len;                        /* Size of buffer.  */
+    union
+      {
+       __caddr_t ifcu_buf;
+       struct ifreq *ifcu_req;
+      } ifc_ifcu;
+  };
+# define ifc_buf       ifc_ifcu.ifcu_buf       /* Buffer address.  */
+# define ifc_req       ifc_ifcu.ifcu_req       /* Array of structures.  */
+# define _IOT_ifconf _IOT(_IOTS(struct ifconf),1,0,0,0,0) /* not right */
+#endif /* Misc.  */
+
+__BEGIN_DECLS
+
+/* Convert an interface name to an index, and vice versa.  */
+extern unsigned int if_nametoindex (__const char *__ifname) __THROW;
+extern char *if_indextoname (unsigned int __ifindex, char *__ifname) __THROW;
+
+/* Return a list of all interfaces and their indices.  */
+extern struct if_nameindex *if_nameindex (void) __THROW;
+
+/* Free the data returned from if_nameindex.  */
+extern void if_freenameindex (struct if_nameindex *__ptr) __THROW;
+
+__END_DECLS
+
+#endif /* net/if.h */
diff --git a/tools/compilers/gcc-glibc/glibc-2.11.1-ros/sysdeps/ros/netpacket/packet.h b/tools/compilers/gcc-glibc/glibc-2.11.1-ros/sysdeps/ros/netpacket/packet.h
new file mode 100644 (file)
index 0000000..8542993
--- /dev/null
@@ -0,0 +1,66 @@
+/* Definitions for use with Linux AF_PACKET sockets.
+   Copyright (C) 1998, 1999 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#ifndef __NETPACKET_PACKET_H
+#define __NETPACKET_PACKET_H   1
+
+/* ROS note: this is the linux one, unaltered */
+
+struct sockaddr_ll
+  {
+    unsigned short int sll_family;
+    unsigned short int sll_protocol;
+    int sll_ifindex;
+    unsigned short int sll_hatype;
+    unsigned char sll_pkttype;
+    unsigned char sll_halen;
+    unsigned char sll_addr[8];
+  };
+
+/* Packet types.  */
+
+#define PACKET_HOST            0               /* To us.  */
+#define PACKET_BROADCAST       1               /* To all.  */
+#define PACKET_MULTICAST       2               /* To group.  */
+#define PACKET_OTHERHOST       3               /* To someone else.  */
+#define PACKET_OUTGOING                4               /* Originated by us . */
+#define PACKET_LOOPBACK                5
+#define PACKET_FASTROUTE       6
+
+/* Packet socket options.  */
+
+#define PACKET_ADD_MEMBERSHIP          1
+#define PACKET_DROP_MEMBERSHIP         2
+#define        PACKET_RECV_OUTPUT              3
+#define        PACKET_RX_RING                  5
+#define        PACKET_STATISTICS               6
+
+struct packet_mreq
+  {
+    int mr_ifindex;
+    unsigned short int mr_type;
+    unsigned short int mr_alen;
+    unsigned char mr_address[8];
+  };
+
+#define PACKET_MR_MULTICAST    0
+#define PACKET_MR_PROMISC      1
+#define PACKET_MR_ALLMULTI     2
+
+#endif /* netpacket/packet.h */
diff --git a/tools/compilers/gcc-glibc/glibc-2.11.1-ros/sysdeps/ros/ptsname.c b/tools/compilers/gcc-glibc/glibc-2.11.1-ros/sysdeps/ros/ptsname.c
new file mode 100644 (file)
index 0000000..237de8e
--- /dev/null
@@ -0,0 +1,82 @@
+/* Copyright (C) 1991, 1995, 1996, 1997 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include <errno.h>
+#include <unistd.h>
+#include <paths.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <ros/syscall.h>
+
+/* ROS: this is a bit odd.  The makescripts want this file to exist (needed for
+ * login/ptsname.o, but if we include the functions, somewhere else has a copy
+ * that conflicts at link time.  This seems to work for now, though we're
+ * missing something here... */
+
+#if 0
+/* Return the pathname of the pseudo terminal slave assoicated with
+   the master FD is open on, or NULL on errors.
+   The returned storage is good until the next call to this function.  */
+char *
+ptsname (int fd)
+{
+  static char buffer[sizeof (_PATH_TTY) + 2];
+  return __ptsname_r (fd, buffer, sizeof (buffer)) != 0 ? NULL : buffer;
+}
+
+
+/* Store at most BUFLEN characters of the pathname of the slave pseudo
+   terminal associated with the master FD is open on in BUF.
+   Return 0 on success, otherwise an error number.  */
+int
+__ptsname_r (int fd, char *buf, size_t buflen)
+{
+  int save_errno = errno;
+  struct stat st;
+
+  if (buf == NULL)
+    {
+      __set_errno (EINVAL);
+      return EINVAL;
+    }
+
+  if (!__isatty (fd))
+    /* We rely on isatty to set errno properly (i.e. EBADF or ENOTTY).  */
+    return errno;
+
+  if (buflen < strlen (_PATH_TTY) + 3)
+    {
+      __set_errno (ERANGE);
+      return ERANGE;
+    }
+
+  if (__ttyname_r (fd, buf, buflen) != 0)
+    return errno;
+
+  buf[sizeof (_PATH_DEV) - 1] = 't';
+
+  if (__stat (buf, &st) < 0)
+    return errno;
+
+  __set_errno (save_errno);
+  return 0;
+}
+weak_alias (__ptsname_r, ptsname_r)
+#endif
diff --git a/tools/compilers/gcc-glibc/glibc-2.11.1-ros/sysdeps/ros/sa_len.c b/tools/compilers/gcc-glibc/glibc-2.11.1-ros/sysdeps/ros/sa_len.c
new file mode 100644 (file)
index 0000000..5e38ee1
--- /dev/null
@@ -0,0 +1,70 @@
+/* Copyright (C) 1998, 1999, 2002, 2007 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include <sys/socket.h>
+
+//#include <netash/ash.h>
+//#include <netatalk/at.h>
+//#include <netax25/ax25.h>
+//#include <neteconet/ec.h>
+#include <netinet/in.h>
+//#include <netipx/ipx.h>
+#include <netpacket/packet.h>
+//#include <netrose/rose.h>
+//#include <netiucv/iucv.h>
+#include <sys/un.h>
+
+int
+__libc_sa_len (sa_family_t af)
+{
+  switch (af)
+    {
+#if 0
+    case AF_APPLETALK:
+      return sizeof (struct sockaddr_at);
+    case AF_ASH:
+      return sizeof (struct sockaddr_ash);
+    case AF_AX25:
+      return sizeof (struct sockaddr_ax25);
+    case AF_ECONET:
+      return sizeof (struct sockaddr_ec);
+#endif
+    case AF_INET:
+      return sizeof (struct sockaddr_in);
+    case AF_INET6:
+      return sizeof (struct sockaddr_in6);
+#if 0
+    case AF_IPX:
+      return sizeof (struct sockaddr_ipx);
+#ifdef NEED_AF_IUCV
+    case AF_IUCV:
+      return sizeof (struct sockaddr_iucv);
+#endif
+    case AF_LOCAL:
+      return sizeof (struct sockaddr_un);
+#endif
+    case AF_PACKET:
+      return sizeof (struct sockaddr_ll);
+#if 0
+    case AF_ROSE:
+      return sizeof (struct sockaddr_rose);
+#endif
+    }
+  return 0;
+}
+INTDEF(__libc_sa_len)
index 35a9a7a..3d2d111 100644 (file)
@@ -7,8 +7,15 @@
 
 #include <limits.h>
 
+/* ROS note: similar to other sysdeps params.h, we pull what we need. */
+
 #define NBBY CHAR_BIT
 
+/* These seem like the linux defaults */
+#ifndef        NGROUPS
+# define NGROUPS       NGROUPS_MAX
+#endif
+
 /* Bit map related macros.  */
 #define setbit(a,i)     ((a)[(i)/NBBY] |= 1<<((i)%NBBY))
 #define clrbit(a,i)     ((a)[(i)/NBBY] &= ~(1<<((i)%NBBY)))