summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog216
-rw-r--r--Makerules4
-rw-r--r--NEWS4
-rw-r--r--argp.h1
-rw-r--r--argp/argp-help.c324
-rw-r--r--argp/argp-namefrob.h2
-rw-r--r--argp/argp-parse.c31
-rw-r--r--argp/argp-test.c98
-rw-r--r--argp/argp.h66
-rw-r--r--elf/dl-hash.h69
-rw-r--r--elf/dl-load.c2
-rw-r--r--elf/dl-lookup.c187
-rw-r--r--elf/dl-version.c13
-rw-r--r--elf/dlvsym.c18
-rw-r--r--elf/link.h23
-rw-r--r--errno.h23
-rw-r--r--inet/Makefile3
-rw-r--r--inet/getnameinfo.c238
-rw-r--r--inet/in6_addr.c28
-rw-r--r--inet/net/ethernet.h76
-rw-r--r--intl/l10nflist.c3
-rw-r--r--io/ftw.h4
-rw-r--r--locale/Makefile1
-rw-r--r--locale/duplocale.c2
-rw-r--r--locale/programs/ld-monetary.c8
-rw-r--r--locale/programs/ld-numeric.c5
-rw-r--r--locale/programs/linereader.c1
-rw-r--r--locale/programs/locale.c353
-rw-r--r--locale/setlocale.c33
-rw-r--r--login/utmp.h2
-rw-r--r--malloc/obstack.h8
-rw-r--r--misc/libgen.h6
-rw-r--r--misc/search.h8
-rw-r--r--misc/sys/syslog.h104
-rw-r--r--nis/nss_nis/nis-ethers.c10
-rw-r--r--nss/digits_dots.c5
-rw-r--r--nss/nss.h4
-rw-r--r--nss/nsswitch.c7
-rw-r--r--posix/Makefile2
-rw-r--r--posix/regex.h13
-rw-r--r--resolv/gethnamaddr.c2
-rw-r--r--resolv/netdb.h8
-rw-r--r--shadow/sgetspent_r.c9
-rw-r--r--stdio-common/bug10.c2
-rw-r--r--stdlib/qsort.c2
-rw-r--r--stdlib/testrand.c2
-rw-r--r--string/test-ffs.c4
-rw-r--r--string/testcopy.c4
-rw-r--r--sunrpc/clnt_simp.c3
-rw-r--r--sunrpc/rpc/auth_des.h6
-rw-r--r--sunrpc/rpc/pmap_rmt.h7
-rw-r--r--sunrpc/rpc/rpc_msg.h2
-rw-r--r--sysdeps/alpha/dl-machine.h2
-rw-r--r--sysdeps/generic/netinet/ip.h (renamed from inet/netinet/ip.h)5
-rw-r--r--sysdeps/generic/netinet/tcp.h (renamed from inet/netinet/tcp.h)0
-rw-r--r--sysdeps/i386/dl-machine.h2
-rw-r--r--sysdeps/m68k/dl-machine.h2
-rw-r--r--sysdeps/mips/dl-machine.h2
-rw-r--r--sysdeps/posix/gai_strerror.c52
-rw-r--r--sysdeps/posix/getaddrinfo.c289
-rw-r--r--sysdeps/stub/gai_strerror.c28
-rw-r--r--sysdeps/stub/msync.c30
-rw-r--r--sysdeps/unix/bsd/sigsuspend.c30
-rw-r--r--sysdeps/unix/bsd/sun/sunos4/resourcebits.h6
-rw-r--r--sysdeps/unix/mman/syscalls.list2
-rw-r--r--sysdeps/unix/sysv/linux/Dist8
-rw-r--r--sysdeps/unix/sysv/linux/Makefile7
-rw-r--r--sysdeps/unix/sysv/linux/net/if_arp.h1
-rw-r--r--sysdeps/unix/sysv/linux/net/if_slip.h6
-rw-r--r--sysdeps/unix/sysv/linux/netatalk/atalk.h27
-rw-r--r--sysdeps/unix/sysv/linux/netinet/icmp.h25
-rw-r--r--sysdeps/unix/sysv/linux/netinet/if_ether.h112
-rw-r--r--sysdeps/unix/sysv/linux/netinet/if_fddi.h37
-rw-r--r--sysdeps/unix/sysv/linux/netinet/if_tr.h41
-rw-r--r--sysdeps/unix/sysv/linux/netinet/igmp.h93
-rw-r--r--sysdeps/unix/sysv/linux/netinet/in.h100
-rw-r--r--sysdeps/unix/sysv/linux/netinet/ip.h254
-rw-r--r--sysdeps/unix/sysv/linux/netinet/ip_fw.h187
-rw-r--r--sysdeps/unix/sysv/linux/netinet/ip_icmp.h210
-rw-r--r--sysdeps/unix/sysv/linux/netinet/tcp.h162
-rw-r--r--sysdeps/unix/sysv/linux/netinet/udp.h46
-rw-r--r--sysdeps/unix/sysv/linux/netipx/ipx.h28
-rw-r--r--sysdeps/unix/sysv/linux/sys/reboot.h5
-rw-r--r--time/test_time.c4
84 files changed, 3259 insertions, 600 deletions
diff --git a/ChangeLog b/ChangeLog
index 34bc623943..7e805491ed 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,219 @@
+1997-02-19 03:28  Miles Bader  <miles@gnu.ai.mit.edu>
+
+	* argp/argp-help.c: Add support for user provided filter of help
+	messages.
+	* argp/argp-parse.c: Likewise.
+	* argp/argp.h: Likewise.
+	* argp/argp-namefrob.h: Define __argp_input.
+
+	* argp/argp-test.c: Add example for filter.
+
+1997-02-19 02:58  Ulrich Drepper  <drepper@cygnus.com>
+
+	* argp.h: New file.
+	* locale/programs/locale.c: Switch to use argp.
+
+	* errno.h: Make it possible to get definition of error_t even
+	after having errno.h already.
+
+	* elf/dl-hash.h: New file.  ELF hashing function.  Extracted
+	from dl-lookup.c.
+	* elf/dl-lookup.c (_dl_elf_hash): Remove definition.
+
+	* elf/dl-load.c: Rename _dl_does_name_match_p to _dl_name_match_p.
+	* elf/dl-version.c: Likewise.
+
+	* elf/dl-lookup.c: Implement new versioning lookup scheme.
+	* elf/dl-version.c (_dl_check_map_versions): Initialize new field
+	in l_versions member.
+
+	* elf/dlvsym.c: Correct call of _dl_lookup_versioned_symbol_skip
+	and _dl_lookup_versioned_symbol.
+
+	* elf/link.h: Rename hash_name_pair to struct r_found_version.
+	* sysdeps/alpha/dl-machine.h: Likewise.
+	* sysdeps/i386/dl-machine.h: Likewise.
+	* sysdeps/m68k/dl-machine.h: Likewise.
+	* sysdeps/mips/dl-machine.h: Likewise.
+
+	* intl/l10nflist.c: (_nl_make_l10nflist): Fix bug in computation of
+	length of abs_filename.
+
+	* locale/Makefile (CPPFLAGS): Define LOCALE_ALIAS_PATH.
+
+	* locale/programs/ld-monetary.c (monetary_add): Allow value 0
+	in mon_grouping information.  This means no more grouping.
+	* locale/programs/ld-numeric.c (numeric_add): Write value \377
+	when seein value 0 in grouping information.
+	* locale/programs/linereader.c (lr_close): Don't free fname since
+	it might be used in error messages.
+
+	* locale/programs/locale.c: Check whether output of `locale -a'
+	really is locale directory.  Also print locale aliases.
+
+	* misc/search.h (__action_fn_t): Parameters VALUE and LEVEL cannot
+	be const.
+
+1997-02-19 02:16  Ulrich Drepper  <drepper@cygnus.com>
+
+	* sysdeps/unix/bsd/sun/sunos4/resourcebits.h: Correct #defin to
+	#define.  Reported by Rick Flower <FLOWER@sdvax2.sdd.TRW.COM>.
+
+1997-02-19 01:37  Erik Troan  <ewt@redhat.com>
+
+	* shadow/sgetspent_r.c: Accept empty third, fourth and fifth fields.
+
+1997-02-19 01:02  Ulrich Drepper  <drepper@cygnus.com>
+
+	* sysdeps/unix/mman/syscalls.list: msync takes 3 arguments.
+	Reported by Andreas Jaeger <aj@arthur.pfalz.de>.
+
+	* sysdeps/stub/msync.c (msync): Add missing third parameter.
+
+1997-02-19 00:29  Ulrich Drepper  <drepper@cygnus.com>
+
+	* sysdeps/unix/bsd/sigsuspend.c: Call __sigpause with needed
+	additional argument.
+
+1997-02-18 22:13  Ulrich Drepper  <drepper@cygnus.com>
+
+	* inet/net/ethernet.h: New file.
+	* sysdeps/unix/sysv/linux/netinet/if_ether.c: Add BSD compatibility.
+	* sysdeps/unix/sysv/linux/net/if_slip.h: New file.
+	Contributed by a sun <asun@zoology.washington.edu>.
+
+	* sysdeps/unix/sysv/linux/net/if_arp.h: Include <sys/socket.h>.
+	* sunrpc/rpc/rpc_msg.h: Include <rpc/clnt.h>.
+	Reported by a sun <asun@zoology.washington.edu>.
+
+1997-02-16 14:25  Andreas Schwab  <schwab@issan.informatik.uni-dortmund.de>
+
+	* Makerules ((common-objpfx)distinfo-$(subdir)): Depend on sysdep
+	makefiles which may change the distinfo variables.
+
+1997-02-16 14:03  Andreas Schwab  <schwab@issan.informatik.uni-dortmund.de>
+
+	* sysdeps/unix/sysv/linux/Makefile (sysdep_headers)
+	[$(subdir)=misc]: Add sys/quota.h.
+	(sysdep_headers) [$(subdir)=inet]: Add netinet/udp.h.
+
+1997-02-17 13:12  aleph1@dfw.net
+
+	* sunrpc/clnt_simp.c (callrpc): Prevent buffer overflow by using
+	strncpy.
+
+1997-02-18 03:28  Ulrich Drepper  <drepper@cygnus.com>
+
+	* stdio-common/bug10.c (main): Correct parameter.
+
+1997-02-17 02:51  Ulrich Drepper  <drepper@cygnus.com>
+
+	* malloc/obstack.h: Add `extern "C"' protection.
+	* posix/regex.h: Likewise.
+	* io/ftw.h: Likewise.
+	* misc/libgen.h: Likewise.
+	* login/utmp.h: Likewise.
+	* sysdeps/unix/sysv/linux/sys/reboot.h: Likewise.
+	* sysdeps/unix/sysv/linux/netinet/in.h: Likewise.
+	* sunrpc/rpc/pmap_rmt.h: Likewise.
+	* sunrpc/rpc/auth_des.h: Likewise.
+	* elf/link.h: Likewise.
+	Reported by HJ Lu.
+
+1997-02-17 01:45  a sun  <asun@zoology.washington.edu>
+
+	Linux specific network headers.
+	* sysdeps/unix/sysv/linux/netinet/if_fddi.h: New file.
+	* sysdeps/unix/sysv/linux/netinet/if_tr.h: New file.
+	* sysdeps/unix/sysv/linux/netinet/ip_icmp.h: New file.
+	* sysdeps/unix/sysv/linux/netinet/ip_fw.h: New file.
+	* sysdeps/unix/sysv/linux/netinet/igmp.h: New file.
+	* sysdeps/unix/sysv/linux/netinet/icmp.h: New file.
+	* sysdeps/unix/sysv/linux/netinet/ip.h: New file.
+	* sysdeps/unix/sysv/linux/netinet/tcp.h: New file.
+	* sysdeps/unix/sysv/linux/netipx/ipx.h: New file.
+	* sysdeps/unix/sysv/linux/netatalk/atalk.h: New file.
+	* sysdeps/unix/sysv/linux/Dist: Add new network headers.
+	* sysdeps/unix/sysv/linux/Makefile [$(subdir)=misc] (sysdep_headers):
+	Add sys/quota.h.
+	[$(subdir)=inet] (sysdep_headers): Add new network header.
+
+	* sysdeps/unix/sysv/linux/netinet/udp.h: Add Linux specific changes.
+
+	* inet/netinet/ip.h: Move to sysdeps/generic.
+	* inet/netinet/tcp.h: Likewise.
+	* sysdeps/generic/netinet/ip.h: Moved to here from inet/netinet.
+	* sysdeps/generic/netinet/tcp.h: Likewise.
+
+1997-02-17 01:18  Ulrich Drepper  <drepper@cygnus.com>
+
+	* misc/sys/syslog.h (prioritynames): Correct definition to use
+	braces where necessary.
+	(facilitynames): Likewise.
+	Patch by Ronald F. Guilmette <rfg@monkeys.com>.
+	Comment and beautify declarations.
+
+1997-02-16 19:54 1997  Philip Blundell  <Philip.Blundell@pobox.com>
+
+	* inet/Makefile (routines): Add in6_addr, getnameinfo.
+	* inet/getnameinfo.c: New file.  Implementation of getnameinfo()
+	by Craig Metz.
+	* inet/in6_addr.c: New file.  IPv6 addressing constants.
+	* posix/Makefile (routines): Add gai_strerror.
+	* resolv/netdb.h: Add more constants for IPv6 basic API.
+	* sysdeps/posix/gai_strerror.c: New file.
+	* sysdeps/stub/gai_strerror.c New file.
+	* sysdeps/unix/sysv/linux/netinet/in.h: Add definitions for IPv6
+	basic API.
+
+	* sysdeps/posix/getaddrinfo.c: Update from latest version by
+	Craig Metz and use reentrant getXXbyYY functions.
+
+1997-02-15 14:32 Andreas Jaeger  <aj@arthur.pfalz.de>
+
+	* argp/argp.h: Declare argp_program_version as const char.
+	* argp/argp-test.c: Likewise
+
+	* stdlib/testrand.c (main): Declare main prototype.
+	* stdlib/testdiv.c (main): Likewise.
+	* string/testcopy.c (main): Likewise.
+	* string/test-ffs.c (main): Likewise.
+	* time/test_time.c (main): Likewise.
+
+	* locale/duplocale.c (__duplocale): Return result.
+
+1997-02-16 03:54  Ulrich Drepper  <drepper@cygnus.com>
+
+	* sysdeps/unix/sysv/linux/netinet/in.h: Declare bindresvport.
+	Reported by fabsoft@fabserver1.zarm.uni-bremen.de.
+
+	* nss/nss.h: Remove declaration of __nss_shlib_revision.
+	* nss/nsswitch.c: Don't use NSS_SHLIB_VERSION macro.
+
+1997-02-16 03:48  Thorsten Kukuk  <kukuk@weber.uni-paderborn.de>
+
+	* nis/nss_nis/nis-ethers.c (_nss_nis_getethernam_r): Rename to
+	_nss_nis_gethostton_r.
+	(_nss_nis_getetherbyaddr_r): Rename to _nss_nis_getntohost_r.
+
+1997-02-15 22:37  Andy Berkheimer  <andy@tho.org>
+
+	* resolv/gethnamaddr.c (gethostbyname2): Test for ':' in name before
+	trying to resolv name as numeric IPv6 address.
+	* nss/digits_dots.c: Likewise.
+
+Sat Feb 15 04:51:08 1997  Ulrich Drepper  <drepper@cygnus.com>
+
+	* locale/setlocale.c (setlocale): Don't try to be clever about
+	unused locales.  When the existence of the locale files isn't
+	tested the result of setlocale might be different.
+
+1997-02-15 03:34  Ulrich Drepper  <drepper@cygnus.com>
+
+	* locale/setlocale.c (setlocale): Don't increment usage_count of
+	new locale if it already has the value MAX_USAGE_COUNT (it might
+	be the C locale data which is read-only).
+
 1997-02-15 02:41  Miles Bader  <miles@gnu.ai.mit.edu>
 
 	* argp/argp-help.c: Gettextize sources.
diff --git a/Makerules b/Makerules
index 5c3d1295cb..3854af79a7 100644
--- a/Makerules
+++ b/Makerules
@@ -889,7 +889,9 @@ dist: $(filter-out %.c %.S %.s,$(distribute))
 # environment get too large.  Instead, we write all the information into
 # a generated makefile fragment `distinfo', and then include it with -f in
 # the sub-make that makes the distribution (above).
-$(common-objpfx)distinfo-$(subdir): Makefile $(..)Makerules
+$(common-objpfx)distinfo-$(subdir): Makefile $(..)Makerules \
+				    $(wildcard $(foreach dir,$(sysdirs),\
+						         $(dir)/Makefile))
 	$(distinfo-vars)
 	mv -f $@.new $@
 .PHONY: subdir_distinfo distinfo
diff --git a/NEWS b/NEWS
index 4a83310811..6e1ba7edd5 100644
--- a/NEWS
+++ b/NEWS
@@ -10,9 +10,9 @@ Please send GNU C library bug reports using the `glibcbug' script to
 Version 2.1
 
 * An additional locale model to support C++ Standard Library locale
-  model an probably more was implemented by Ulrich Drepper.
+  model and probably more was implemented by Ulrich Drepper.
 
-* Eric Youngdale and Ulrich Drepper implement versioning of objects on
+* Eric Youngdale and Ulrich Drepper implemented versioning of objects on
   symbol level.
 
 * Miles Bader provided the `argp' function family to support hierachical
diff --git a/argp.h b/argp.h
new file mode 100644
index 0000000000..92be5f90f1
--- /dev/null
+++ b/argp.h
@@ -0,0 +1 @@
+#include <argp/argp.h>
diff --git a/argp/argp-help.c b/argp/argp-help.c
index 5d7df5454a..84f9ca51c9 100644
--- a/argp/argp-help.c
+++ b/argp/argp-help.c
@@ -169,6 +169,9 @@ struct hol_entry
 
   /* The cluster of options this entry belongs to, or 0 if none.  */
   struct hol_cluster *cluster;
+
+  /* The argp from which this option came.  */
+  const struct argp *argp;
 };
 
 /* A cluster of entries to reflect the argp tree structure.  */
@@ -190,6 +193,9 @@ struct hol_cluster
      level.  */
   struct hol_cluster *parent;
 
+  /* The argp from which this cluster is (eventually) derived.  */
+  const struct argp *argp;
+
   /* The distance this cluster is from the root.  */
   int depth;
 
@@ -215,13 +221,14 @@ struct hol
   struct hol_cluster *clusters;
 };
 
-/* Create a struct hol from an array of struct argp_option.  CLUSTER is the
+/* Create a struct hol from the options in ARGP.  CLUSTER is the
    hol_cluster in which these entries occur, or 0, if at the root.  */
 static struct hol *
-make_hol (const struct argp_option *opt, struct hol_cluster *cluster)
+make_hol (const struct argp *argp, struct hol_cluster *cluster)
 {
   char *so;
   const struct argp_option *o;
+  const struct argp_option *opts = argp->options;
   struct hol_entry *entry;
   unsigned num_short_options = 0;
   struct hol *hol = malloc (sizeof (struct hol));
@@ -231,15 +238,15 @@ make_hol (const struct argp_option *opt, struct hol_cluster *cluster)
   hol->num_entries = 0;
   hol->clusters = 0;
 
-  if (opt)
+  if (opts)
     {
       int cur_group = 0;
 
       /* The first option must not be an alias.  */
-      assert (! oalias (opt));
+      assert (! oalias (opts));
 
       /* Calculate the space needed.  */
-      for (o = opt; ! oend (o); o++)
+      for (o = opts; ! oend (o); o++)
 	{
 	  if (! oalias (o))
 	    hol->num_entries++;
@@ -254,7 +261,7 @@ make_hol (const struct argp_option *opt, struct hol_cluster *cluster)
 
       /* Fill in the entries.  */
       so = hol->short_options;
-      for (o = opt, entry = hol->entries; ! oend (o); entry++)
+      for (o = opts, entry = hol->entries; ! oend (o); entry++)
 	{
 	  entry->opt = o;
 	  entry->num = 0;
@@ -266,6 +273,7 @@ make_hol (const struct argp_option *opt, struct hol_cluster *cluster)
 	       ? cur_group + 1
 	       : cur_group);
 	  entry->cluster = cluster;
+	  entry->argp = argp;
 
 	  do
 	    {
@@ -285,10 +293,10 @@ make_hol (const struct argp_option *opt, struct hol_cluster *cluster)
 
 /* Add a new cluster to HOL, with the given GROUP and HEADER (taken from the
    associated argp child list entry), INDEX, and PARENT, and return a pointer
-   to it.  */
+   to it.  ARGP is the argp that this cluster results from.  */
 static struct hol_cluster *
 hol_add_cluster (struct hol *hol, int group, const char *header, int index,
-		 struct hol_cluster *parent)
+		 struct hol_cluster *parent, const struct argp *argp)
 {
   struct hol_cluster *cl = malloc (sizeof (struct hol_cluster));
   if (cl)
@@ -298,6 +306,7 @@ hol_add_cluster (struct hol *hol, int group, const char *header, int index,
 
       cl->index = index;
       cl->parent = parent;
+      cl->argp = argp;
 
       cl->next = hol->clusters;
       hol->clusters = cl;
@@ -657,8 +666,8 @@ hol_append (struct hol *hol, struct hol *more)
 		if (oshort (opt) && ch == opt->key)
 		  /* The next short option in MORE_SO, CH, is from OPT.  */
 		  {
-		    if (! find_char (ch,
-				     short_options, short_options + hol_so_len))
+		    if (! find_char (ch, short_options,
+				     short_options + hol_so_len))
 		      /* The short option CH isn't shadowed by HOL's options,
 			 so add it to the sum.  */
 		      *so++ = ch;
@@ -689,6 +698,18 @@ indent_to (argp_fmtstream_t stream, unsigned col)
     __argp_fmtstream_putc (stream, ' ');
 }
 
+/* Output to STREAM either a space, or a newline if there isn't room for at
+   least ENSURE characters before the right margin.  */
+static void
+space (argp_fmtstream_t stream, size_t ensure)
+{
+  if (__argp_fmtstream_point (stream) + ensure
+      >= __argp_fmtstream_rmargin (stream))
+    __argp_fmtstream_putc (stream, '\n');
+  else
+    __argp_fmtstream_putc (stream, ' ');
+}
+
 /* If the option REAL has an argument, we print it in using the printf
    format REQ_FMT or OPT_FMT depending on whether it's a required or
    optional argument.  */
@@ -715,44 +736,79 @@ struct pentry_state
   struct hol_entry **prev_entry;
   int *sep_groups;
 
-  int first;			/* True if nothing's been printed so far.  */
+  /* True if nothing's been printed so far.  */
+  int first;
+
+  /* If non-zero, the state that was used to print this help.  */
+  const struct argp_state *state;
 };
 
+/* If a user doc filter should be applied to DOC, do so.  */
+static const char *
+filter_doc (const char *doc, int key, const struct argp *argp,
+	    struct pentry_state *pest)
+{
+  if (argp->help_filter)
+    /* We must apply a user filter to this output.  */
+    {
+      void *input = __argp_input (argp, pest->state);
+      return (*argp->help_filter) (key, doc, input);
+    }
+  else
+    /* No filter.  */
+    return (char *)doc;
+}
+
 /* Prints STR as a header line, with the margin lines set appropiately, and
-   notes the fact that groups should be separated with a blank line.  Note
+   notes the fact that groups should be separated with a blank line.  ARGP is
+   the argp that should dictate any user doc filtering to take place.  Note
    that the previous wrap margin isn't restored, but the left margin is reset
    to 0.  */
 static void
-print_header (const char *str, struct pentry_state *st)
+print_header (const char *str, const struct argp *argp,
+	      struct pentry_state *pest)
 {
-  if (*str)
+  const char *tstr = gettext (str);
+  const char *fstr = filter_doc (tstr, ARGP_KEY_HELP_HEADER, argp, pest);
+
+  if (fstr)
     {
-      if (st->prev_entry && *st->prev_entry)
-	__argp_fmtstream_putc (st->stream, '\n'); /* Precede with a blank line.  */
-      indent_to (st->stream, HEADER_COL);
-      __argp_fmtstream_set_lmargin (st->stream, HEADER_COL);
-      __argp_fmtstream_set_wmargin (st->stream, HEADER_COL);
-      __argp_fmtstream_puts (st->stream, str);
-      __argp_fmtstream_set_lmargin (st->stream, 0);
+      if (*fstr)
+	{
+	  if (pest->prev_entry && *pest->prev_entry)
+	    /* Precede with a blank line.  */
+	    __argp_fmtstream_putc (pest->stream, '\n');
+	  indent_to (pest->stream, HEADER_COL);
+	  __argp_fmtstream_set_lmargin (pest->stream, HEADER_COL);
+	  __argp_fmtstream_set_wmargin (pest->stream, HEADER_COL);
+	  __argp_fmtstream_puts (pest->stream, fstr);
+	  __argp_fmtstream_set_lmargin (pest->stream, 0);
+	  __argp_fmtstream_putc (pest->stream, '\n');
+	}
+
+      if (pest->sep_groups)
+	*pest->sep_groups = 1;	/* Separate subsequent groups. */
     }
 
-  if (st->sep_groups)
-    *st->sep_groups = 1;	/* Separate subsequent groups. */
+  if (fstr != tstr)
+    free ((char *) fstr);
 }
 
 /* Inserts a comma if this isn't the first item on the line, and then makes
-   sure we're at least to column COL.  Also clears FIRST.  */
+   sure we're at least to column COL.  If this *is* the first item on a line,
+   prints any pending whitespace/headers that should precede this line. Also
+   clears FIRST.  */
 static void
-comma (unsigned col, struct pentry_state *st)
+comma (unsigned col, struct pentry_state *pest)
 {
-  if (st->first)
+  if (pest->first)
     {
-      const struct hol_entry *pe = st->prev_entry ? *st->prev_entry : 0;
-      const struct hol_cluster *cl = st->entry->cluster;
+      const struct hol_entry *pe = pest->prev_entry ? *pest->prev_entry : 0;
+      const struct hol_cluster *cl = pest->entry->cluster;
 
-      if (st->sep_groups && *st->sep_groups
-	  && pe && st->entry->group != pe->group)
-	__argp_fmtstream_putc (st->stream, '\n');
+      if (pest->sep_groups && *pest->sep_groups
+	  && pe && pest->entry->group != pe->group)
+	__argp_fmtstream_putc (pest->stream, '\n');
 
       if (pe && cl && pe->cluster != cl && cl->header && *cl->header
 	  && !hol_cluster_is_child (pe->cluster, cl))
@@ -761,18 +817,17 @@ comma (unsigned col, struct pentry_state *st)
 	   (in which case we had just popped into a sub-cluster for a bit).
 	   If so, then print the cluster's header line.  */
 	{
-	  int old_wm = __argp_fmtstream_wmargin (st->stream);
-	  print_header (cl->header, st);
-	  __argp_fmtstream_putc (st->stream, '\n');
-	  __argp_fmtstream_set_wmargin (st->stream, old_wm);
+	  int old_wm = __argp_fmtstream_wmargin (pest->stream);
+	  print_header (cl->header, cl->argp, pest);
+	  __argp_fmtstream_set_wmargin (pest->stream, old_wm);
 	}
 
-      st->first = 0;
+      pest->first = 0;
     }
   else
-    __argp_fmtstream_puts (st->stream, ", ");
+    __argp_fmtstream_puts (pest->stream, ", ");
 
-  indent_to (st->stream, col);
+  indent_to (pest->stream, col);
 }
 
 /* Print help for ENTRY to STREAM.  *PREV_ENTRY should contain the last entry
@@ -781,15 +836,19 @@ comma (unsigned col, struct pentry_state *st)
    printed before any output.  *SEP_GROUPS is also set to true if a
    user-specified group header is printed.  */
 static void
-hol_entry_help (struct hol_entry *entry, argp_fmtstream_t stream,
+hol_entry_help (struct hol_entry *entry, const struct argp_state *state,
+		argp_fmtstream_t stream,
 		struct hol_entry **prev_entry, int *sep_groups)
 {
   unsigned num;
   const struct argp_option *real = entry->opt, *opt;
   char *so = entry->short_options;
+  /* Saved margins.  */
   int old_lm = __argp_fmtstream_set_lmargin (stream, 0);
   int old_wm = __argp_fmtstream_wmargin (stream);
-  struct pentry_state pest = { entry, stream, prev_entry, sep_groups, 1 };
+  /* PEST is a state block holding some of our variables that we'd like to
+     share with helper functions.  */
+  struct pentry_state pest = { entry, stream, prev_entry, sep_groups, 1, state };
 
   /* First emit short options.  */
   __argp_fmtstream_set_wmargin (stream, SHORT_OPT_COL); /* For truly bizarre cases. */
@@ -809,7 +868,7 @@ hol_entry_help (struct hol_entry *entry, argp_fmtstream_t stream,
 
   /* Now, long options.  */
   if (odoc (real))
-    /* Really a `documentation' option.  */
+    /* A `documentation' option.  */
     {
       __argp_fmtstream_set_wmargin (stream, DOC_OPT_COL);
       for (opt = real, num = entry->num; num > 0; opt++, num--)
@@ -823,7 +882,7 @@ hol_entry_help (struct hol_entry *entry, argp_fmtstream_t stream,
 	  }
     }
   else
-    /* A realy long option.  */
+    /* A real long option.  */
     {
       __argp_fmtstream_set_wmargin (stream, LONG_OPT_COL);
       for (opt = real, num = entry->num; num > 0; opt++, num--)
@@ -835,39 +894,45 @@ hol_entry_help (struct hol_entry *entry, argp_fmtstream_t stream,
 	  }
     }
 
+  /* Next, documentation strings.  */
   __argp_fmtstream_set_lmargin (stream, 0);
+
   if (pest.first)
     /* Didn't print any switches, what's up?  */
-    if (!oshort (real) && !real->name && real->doc)
+    if (!oshort (real) && !real->name)
       /* This is a group header, print it nicely.  */
-      print_header (real->doc, &pest);
+      print_header (real->doc, entry->argp, &pest);
     else
       /* Just a totally shadowed option or null header; print nothing.  */
       goto cleanup;		/* Just return, after cleaning up.  */
-  else if (real->doc)
-    /* Now the option documentation.  */
+  else
     {
-      unsigned col = __argp_fmtstream_point (stream);
-      const char *doc = real->doc;
+      const char *tstr = real->doc ? gettext (real->doc) : 0;
+      const char *fstr = filter_doc (tstr, real->key, entry->argp, &pest);
+      if (fstr && *fstr)
+	{
+	  unsigned col = __argp_fmtstream_point (stream);
 
-      __argp_fmtstream_set_lmargin (stream, OPT_DOC_COL);
-      __argp_fmtstream_set_wmargin (stream, OPT_DOC_COL);
+	  __argp_fmtstream_set_lmargin (stream, OPT_DOC_COL);
+	  __argp_fmtstream_set_wmargin (stream, OPT_DOC_COL);
 
-      if (col > OPT_DOC_COL + 3)
-	__argp_fmtstream_putc (stream, '\n');
-      else if (col >= OPT_DOC_COL)
-	__argp_fmtstream_puts (stream, "   ");
-      else
-	indent_to (stream, OPT_DOC_COL);
+	  if (col > OPT_DOC_COL + 3)
+	    __argp_fmtstream_putc (stream, '\n');
+	  else if (col >= OPT_DOC_COL)
+	    __argp_fmtstream_puts (stream, "   ");
+	  else
+	    indent_to (stream, OPT_DOC_COL);
 
-      __argp_fmtstream_puts (stream, doc);
+	  __argp_fmtstream_puts (stream, fstr);
+	}
+      if (fstr && fstr != tstr)
+	free ((char *) fstr);
 
       /* Reset the left margin.  */
       __argp_fmtstream_set_lmargin (stream, 0);
+      __argp_fmtstream_putc (stream, '\n');
     }
 
-  __argp_fmtstream_putc (stream, '\n');
-
   if (prev_entry)
     *prev_entry = entry;
 
@@ -878,7 +943,8 @@ cleanup:
 
 /* Output a long help message about the options in HOL to STREAM.  */
 static void
-hol_help (struct hol *hol, argp_fmtstream_t stream)
+hol_help (struct hol *hol, const struct argp_state *state,
+	  argp_fmtstream_t stream)
 {
   unsigned num;
   struct hol_entry *entry;
@@ -886,7 +952,7 @@ hol_help (struct hol *hol, argp_fmtstream_t stream)
   int sep_groups = 0;		/* True if we should separate different
 				   sections with blank lines.   */
   for (entry = hol->entries, num = hol->num_entries; num > 0; entry++, num--)
-    hol_entry_help (entry, stream, &last_entry, &sep_groups);
+    hol_entry_help (entry, state, stream, &last_entry, &sep_groups);
 }
 
 /* Helper functions for hol_usage.  */
@@ -927,11 +993,7 @@ usage_argful_short_opt (const struct argp_option *opt,
 	{
 	  /* Manually do line wrapping so that it (probably) won't
 	     get wrapped at the embedded space.  */
-	  if (__argp_fmtstream_point (stream) + 6 + strlen (arg)
-	      >= __argp_fmtstream_rmargin (stream))
-	    __argp_fmtstream_putc (stream, '\n');
-	  else
-	    __argp_fmtstream_putc (stream, ' ');
+	  space (stream, 6 + strlen (arg));
 	  __argp_fmtstream_printf (stream, "[-%c %s]", opt->key, arg);
 	}
     }
@@ -1008,7 +1070,7 @@ static struct hol *
 argp_hol (const struct argp *argp, struct hol_cluster *cluster)
 {
   const struct argp_child *child = argp->children;
-  struct hol *hol = make_hol (argp->options, cluster);
+  struct hol *hol = make_hol (argp, cluster);
   if (child)
     while (child->argp)
       {
@@ -1016,7 +1078,7 @@ argp_hol (const struct argp *argp, struct hol_cluster *cluster)
 	  ((child->group || child->header)
 	   /* Put CHILD->argp within its own cluster.  */
 	   ? hol_add_cluster (hol, child->group, child->header,
-			      child - argp->children, cluster)
+			      child - argp->children, cluster, argp)
 	   /* Just merge it into the parent's cluster.  */
 	   : cluster);
 	hol_append (hol, argp_hol (child->argp, child_cluster)) ;
@@ -1075,11 +1137,7 @@ argp_args_usage (const struct argp *argp, char **levels, int advance,
 
       /* Manually do line wrapping so that it (probably) won't get wrapped at
 	 any embedded spaces.  */
-      if (__argp_fmtstream_point (stream) + 1 + nl - doc
-	  >= __argp_fmtstream_rmargin (stream))
-	__argp_fmtstream_putc (stream, '\n');
-      else
-	__argp_fmtstream_putc (stream, ' ');
+      space (stream, 1 + nl - doc);
 
       __argp_fmtstream_write (stream, doc, nl - doc);
     }
@@ -1111,46 +1169,98 @@ argp_args_usage (const struct argp *argp, char **levels, int advance,
    then the first is as well.  If FIRST_ONLY is true, only the first
    occurance is output.  Returns true if anything was output.  */
 static int
-argp_doc (const struct argp *argp, int post, int pre_blank, int first_only,
+argp_doc (const struct argp *argp, const struct argp_state *state,
+	  int post, int pre_blank, int first_only,
 	  argp_fmtstream_t stream)
 {
-  const struct argp_child *child = argp->children;
-  const char *doc = argp->doc;
+  const char *text;
+  const char *inp_text;
+  void *input = 0;
   int anything = 0;
+  size_t inp_text_limit = 0;
+  const char *doc = gettext (argp->doc);
+  const struct argp_child *child = argp->children;
 
   if (doc)
     {
       char *vt = strchr (doc, '\v');
+      inp_text = post ? (vt ? vt + 1 : 0) : doc;
+      inp_text_limit = (!post && vt) ? (vt - doc) : 0;
+    }
+  else
+    inp_text = 0;
 
-      if (pre_blank && (vt || !post))
+  if (argp->help_filter)
+    /* We have to filter the doc strings.  */
+    {
+      if (inp_text_limit)
+	/* Copy INP_TEXT so that it's nul-terminated.  */
+	inp_text = strndup (inp_text, inp_text_limit);
+      input = __argp_input (argp, state);
+      text =
+	(*argp->help_filter) (post
+			      ? ARGP_KEY_HELP_POST_DOC
+			      : ARGP_KEY_HELP_PRE_DOC,
+			      inp_text, input);
+    }
+  else
+    text = (const char *) inp_text;
+
+  if (text)
+    {
+      if (pre_blank)
 	__argp_fmtstream_putc (stream, '\n');
 
-      if (vt)
-	if (post)
-	  __argp_fmtstream_puts (stream, vt + 1);
-	else
-	  __argp_fmtstream_write (stream, doc, vt - doc);
+      if (text == inp_text && inp_text_limit)
+	__argp_fmtstream_write (stream, inp_text, inp_text_limit);
       else
-	if (! post)
-	  __argp_fmtstream_puts (stream, doc);
+	__argp_fmtstream_puts (stream, text);
+
       if (__argp_fmtstream_point (stream) > __argp_fmtstream_lmargin (stream))
 	__argp_fmtstream_putc (stream, '\n');
 
       anything = 1;
     }
+
+  if (text && text != inp_text)
+    free ((char *) text);	/* Free TEXT returned from the help filter.  */
+  if (inp_text && inp_text_limit && argp->help_filter)
+    free ((char *) inp_text);	/* We copied INP_TEXT, so free it now.  */
+
+  if (post && argp->help_filter)
+    /* Now see if we have to output a ARGP_KEY_HELP_EXTRA text.  */
+    {
+      text = (*argp->help_filter) (ARGP_KEY_HELP_EXTRA, 0, input);
+      if (text)
+	{
+	  if (anything || pre_blank)
+	    __argp_fmtstream_putc (stream, '\n');
+	  __argp_fmtstream_puts (stream, text);
+	  free ((char *) text);
+	  if (__argp_fmtstream_point (stream)
+	      > __argp_fmtstream_lmargin (stream))
+	    __argp_fmtstream_putc (stream, '\n');
+	  anything = 1;
+	}
+    }
+
   if (child)
     while (child->argp && !(first_only && anything))
       anything |=
-	argp_doc ((child++)->argp, post, anything || pre_blank, first_only,
+	argp_doc ((child++)->argp, state,
+		  post, anything || pre_blank, first_only,
 		  stream);
 
   return anything;
 }
 
-/* Output a usage message for ARGP to STREAM.  FLAGS are from the set
-   ARGP_HELP_*.  NAME is what to use wherever a `program name' is needed. */
-void __argp_help (const struct argp *argp, FILE *stream,
-		  unsigned flags, char *name)
+/* Output a usage message for ARGP to STREAM.  If called from
+   argp_state_help, STATE is the relevent parsing state.  FLAGS are from the
+   set ARGP_HELP_*.  NAME is what to use wherever a `program name' is
+   needed. */
+static void
+_help (const struct argp *argp, const struct argp_state *state, FILE *stream,
+       unsigned flags, char *name)
 {
   int anything = 0;		/* Whether we've output anything.  */
   struct hol *hol = 0;
@@ -1190,7 +1300,8 @@ void __argp_help (const struct argp *argp, FILE *stream,
 	  char *levels = pattern_levels;
 
 	  __argp_fmtstream_printf (fs, "%s %s",
-				   first_pattern ? "Usage:" : "  or: ", name);
+				   _(first_pattern ? "Usage:" : "  or: "),
+				   name);
 
 	  /* We set the lmargin as well as the wmargin, because hol_usage
 	     manually wraps options with newline to avoid annoying breaks.  */
@@ -1200,7 +1311,7 @@ void __argp_help (const struct argp *argp, FILE *stream,
 	    /* Just show where the options go.  */
 	    {
 	      if (hol->num_entries > 0)
-		__argp_fmtstream_puts (fs, " [OPTION...]");
+		__argp_fmtstream_puts (fs, _(" [OPTION...]"));
 	    }
 	  else
 	    /* Actually print the options.  */
@@ -1223,13 +1334,13 @@ void __argp_help (const struct argp *argp, FILE *stream,
     }
 
   if (flags & ARGP_HELP_PRE_DOC)
-    anything |= argp_doc (argp, 0, 0, 1, fs);
+    anything |= argp_doc (argp, state, 0, 0, 1, fs);
 
   if (flags & ARGP_HELP_SEE)
     {
-      __argp_fmtstream_printf (fs,
-	       "Try `%s --help' or `%s --usage' for more information.\n",
-	       name, name);
+      __argp_fmtstream_printf (fs, _("\
+Try `%s --help' or `%s --usage' for more information.\n"),
+			       name, name);
       anything = 1;
     }
 
@@ -1241,20 +1352,21 @@ void __argp_help (const struct argp *argp, FILE *stream,
 	{
 	  if (anything)
 	    __argp_fmtstream_putc (fs, '\n');
-	  hol_help (hol, fs);
+	  hol_help (hol, state, fs);
 	  anything = 1;
 	}
     }
 
   if (flags & ARGP_HELP_POST_DOC)
     /* Print any documentation strings at the end.  */
-    anything |= argp_doc (argp, 1, anything, 0, fs);
+    anything |= argp_doc (argp, state, 1, anything, 0, fs);
 
   if ((flags & ARGP_HELP_BUG_ADDR) && argp_program_bug_address)
     {
       if (anything)
 	__argp_fmtstream_putc (fs, '\n');
-      __argp_fmtstream_printf (fs, "Report bugs to %s.\n", argp_program_bug_address);
+      __argp_fmtstream_printf (fs, _("Report bugs to %s.\n"),
+ 			       argp_program_bug_address);
       anything = 1;
     }
 
@@ -1263,6 +1375,14 @@ void __argp_help (const struct argp *argp, FILE *stream,
 
   __argp_fmtstream_free (fs);
 }
+
+/* Output a usage message for ARGP to STREAM.  FLAGS are from the set
+   ARGP_HELP_*.  NAME is what to use wherever a `program name' is needed. */
+void __argp_help (const struct argp *argp, FILE *stream,
+		  unsigned flags, char *name)
+{
+  _help (argp, 0, stream, flags, name);
+}
 #ifdef weak_alias
 weak_alias (__argp_help, argp_help)
 #endif
@@ -1277,8 +1397,8 @@ __argp_state_help (struct argp_state *state, FILE *stream, unsigned flags)
       if (state && (state->flags & ARGP_LONG_ONLY))
 	flags |= ARGP_HELP_LONG_ONLY;
 
-      __argp_help (state ? state->argp : 0, stream, flags,
-		   state ? state->name : program_invocation_name);
+      _help (state ? state->argp : 0, state, stream, flags,
+	     state ? state->name : program_invocation_short_name);
 
       if (!state || ! (state->flags & ARGP_NO_EXIT))
 	{
@@ -1307,7 +1427,7 @@ __argp_error (struct argp_state *state, const char *fmt, ...)
 	{
 	  va_list ap;
 
-	  fputs (state ? state->name : program_invocation_name, stream);
+	  fputs (state ? state->name : program_invocation_short_name, stream);
 	  putc (':', stream);
 	  putc (' ', stream);
 
@@ -1343,7 +1463,7 @@ __argp_failure (struct argp_state *state, int status, int errnum,
 
       if (stream)
 	{
-	  fputs (state ? state->name : program_invocation_name, stream);
+	  fputs (state ? state->name : program_invocation_short_name, stream);
 
 	  if (fmt)
 	    {
diff --git a/argp/argp-namefrob.h b/argp/argp-namefrob.h
index fab7c9d94a..983ae9fc0a 100644
--- a/argp/argp-namefrob.h
+++ b/argp/argp-namefrob.h
@@ -30,6 +30,8 @@
 #define __option_is_end _option_is_end
 #undef __option_is_short
 #define __option_is_short _option_is_short
+#undef __argp_input
+#define __argp_input _argp_input
 
 /* argp-help functions */
 #undef __argp_help
diff --git a/argp/argp-parse.c b/argp/argp-parse.c
index f1f4ce9dfc..af27757273 100644
--- a/argp/argp-parse.c
+++ b/argp/argp-parse.c
@@ -106,7 +106,7 @@ argp_default_parser (int key, char *arg, struct argp_state *state)
       break;
 
     case OPT_PROGNAME:		/* Set the program name.  */
-      program_invocation_name = arg;
+      program_invocation_short_name = arg;
 
       /* [Note that some systems only have PROGRAM_INVOCATION_SHORT_NAME (aka
 	 __PROGNAME), in which case, PROGRAM_INVOCATION_NAME is just defined
@@ -119,7 +119,8 @@ argp_default_parser (int key, char *arg, struct argp_state *state)
 
       if ((state->flags & (ARGP_PARSE_ARGV0 | ARGP_NO_ERRS))
 	  == ARGP_PARSE_ARGV0)
-	state->argv[0] = program_invocation_name; /* Update what getopt uses too.  */
+	/* Update what getopt uses too.  */
+	state->argv[0] = program_invocation_short_name;
 
       break;
 
@@ -231,6 +232,9 @@ struct group
   /* This group's parsing function.  */
   argp_parser_t parser;
 
+  /* Which argp this group is from.  */
+  const struct argp *argp;
+
   /* Points to the point in SHORT_OPTS corresponding to the end of the short
      options for this group.  We use it to determine from which group a
      particular short options is from.  */
@@ -380,6 +384,7 @@ convert_options (const struct argp *argp,
 	    }
 
       group->parser = argp->parser;
+      group->argp = argp;
       group->short_end = cvt->short_end;
       group->args_processed = 0;
       group->parent = parent;
@@ -526,6 +531,7 @@ parser_init (struct parser *parser, const struct argp *argp,
   parser->state.err_stream = stderr;
   parser->state.out_stream = stdout;
   parser->state.next = 0;	/* Tell getopt to initialize.  */
+  parser->state.pstate = parser;
 
   /* Call each parser for the first time, giving it a chance to propagate
      values to child parsers.  */
@@ -848,3 +854,24 @@ __argp_parse (const struct argp *argp, int argc, char **argv, unsigned flags,
 #ifdef weak_alias
 weak_alias (__argp_parse, argp_parse)
 #endif
+
+/* Return the input field for ARGP in the parser corresponding to STATE; used
+   by the help routines.  */
+void *
+__argp_input (const struct argp *argp, const struct argp_state *state)
+{
+  if (state)
+    {
+      struct group *group;
+      struct parser *parser = state->pstate;
+
+      for (group = parser->groups; group < parser->egroup; group++)
+	if (group->argp == argp)
+	  return group->input;
+    }
+
+  return 0;
+}
+#ifdef weak_alias
+weak_alias (__argp_input, _argp_input)
+#endif
diff --git a/argp/argp-test.c b/argp/argp-test.c
index ae72b2230c..1ce48c3e3f 100644
--- a/argp/argp-test.c
+++ b/argp/argp-test.c
@@ -22,9 +22,12 @@
 #include <config.h>
 #endif
 
+#include <stdlib.h>
+#include <time.h>
+#include <string.h>
 #include <argp.h>
 
-char *argp_program_version = "argp-test 1.0";
+const char *argp_program_version = "argp-test 1.0";
 
 struct argp_option sub_options[] =
 {
@@ -64,10 +67,27 @@ sub_parse_opt (int key, char *arg, struct argp_state *state)
   return 0;
 }
 
+static char *
+sub_help_filter (int key, const char *text, void *input)
+{
+  if (key == ARGP_KEY_HELP_EXTRA)
+    return strdup ("This is some extra text from the sub parser (note that it \
+is preceded by a blank line).");
+  else
+    return (char *)text;
+}
+
 static struct argp sub_argp = {
-  sub_options, sub_parse_opt, sub_args_doc, sub_doc
+  sub_options, sub_parse_opt, sub_args_doc, sub_doc, 0, sub_help_filter
 };
 
+/* Structure used to communicate with the parsing functions.  */
+struct params
+{
+  unsigned foonly;		/* Value parsed for foonly.  */
+  unsigned foonly_default;	/* Default value for it.  */
+};
+
 #define OPT_PGRP 1
 #define OPT_SESS 2
 
@@ -89,7 +109,7 @@ struct argp_option options[] =
 				   " the current process)" },
 
   {0,0,0,0, "Here are some more options:"},
-  {"foonly", 'f', "ZOT", 0, "Glork a foonly"},
+  {"foonly", 'f', "ZOT", OPTION_ARG_OPTIONAL, "Glork a foonly"},
   {"zaza", 'z', 0, 0, "Snit a zar"},
 
   {0}
@@ -98,11 +118,28 @@ struct argp_option options[] =
 static const char args_doc[] = "STRING";
 static const char doc[] = "Test program for argp."
  "\vThis doc string comes after the options."
- "\nHey!  Some manual formatting!";
+ "\nHey!  Some manual formatting!"
+ "\nThe current time is: %s";
+
+static void
+popt (int key, char *arg)
+{
+  char buf[10];
+  if (isprint (key))
+    sprintf (buf, "%c", key);
+  else
+    sprintf (buf, "%d", key);
+  if (arg)
+    printf ("KEY %s: %s\n", buf, arg);
+  else
+    printf ("KEY %s\n", buf);
+}
 
 static error_t
 parse_opt (int key, char *arg, struct argp_state *state)
 {
+  struct params *params = state->input;
+
   switch (key)
     {
     case ARGP_KEY_NO_ARGS:
@@ -115,19 +152,17 @@ parse_opt (int key, char *arg, struct argp_state *state)
       printf ("ARG: %s\n", arg);
       break;
 
+    case 'f':
+      if (arg)
+	params->foonly = atoi (arg);
+      else
+	params->foonly = params->foonly_default;
+      popt (key, arg);
+      break;
+
     case 'p': case 'P': case OPT_PGRP: case 'x': case 'Q':
-    case 'r': case OPT_SESS: case 'f': case 'z':
-      {
-	char buf[10];
-	if (isprint (key))
-	  sprintf (buf, "%c", key);
-	else
-	  sprintf (buf, "%d", key);
-	if (arg)
-	  printf ("KEY %s: %s\n", buf, arg);
-	else
-	  printf ("KEY %s\n", buf);
-      }
+    case 'r': case OPT_SESS: case 'z':
+      popt (key, arg);
       break;
 
     default:
@@ -136,12 +171,39 @@ parse_opt (int key, char *arg, struct argp_state *state)
   return 0;
 }
 
+static char *
+help_filter (int key, const char *text, void *input)
+{
+  char *new_text;
+  struct params *params = input;
+
+  if (key == ARGP_KEY_HELP_POST_DOC && text)
+    {
+      time_t now = time (0);
+      asprintf (&new_text, text, ctime (&now));
+    }
+  else if (key == 'f')
+    /* Show the default for the --foonly option.  */
+    asprintf (&new_text, "%s (ZOT defaults to %x)",
+	      text, params->foonly_default);
+  else
+    new_text = (char *) text;
+
+  return new_text;
+}
+
 static struct argp_child argp_children[] = { { &sub_argp }, { 0 } };
-static struct argp argp = { options, parse_opt, args_doc, doc, argp_children };
+static struct argp argp = {
+  options, parse_opt, args_doc, doc, argp_children, help_filter
+};
 
 int
 main (int argc, char **argv)
 {
-  argp_parse (&argp, argc, argv, 0, 0, 0);
+  struct params params;
+  params.foonly = 0;
+  params.foonly_default = random ();
+  argp_parse (&argp, argc, argv, 0, 0, &params);
+  printf ("After parsing: foonly = %x\n", params.foonly);
   return 0;
 }
diff --git a/argp/argp.h b/argp/argp.h
index be727561a1..2e20ea67f3 100644
--- a/argp/argp.h
+++ b/argp/argp.h
@@ -22,14 +22,20 @@
 #define __ARGP_H__
 
 #include <stdio.h>
-#include <errno.h>
 #include <ctype.h>
 #include <getopt.h>
 
+#define __need_error_t
+#include <errno.h>
+
 #ifndef __const
 #define __const const
 #endif
 
+#ifndef __error_t_defined
+typedef int error_t;
+#endif
+
 #ifndef __P
 # if (defined (__STDC__) && __STDC__) || defined (__cplusplus)
 #  define __P(args)	args
@@ -194,7 +200,26 @@ struct argp
      their own argp structure, which you want to use in conjunction with your
      own.  */
   __const struct argp_child *children;
+
+  /* If non-zero, this should be a function to filter the output of help
+     messages.  KEY is either a key from an option, in which case TEXT is
+     that option's help text, or a special key from the ARGP_KEY_HELP_
+     defines, below, describing which other help text TEXT is.  The function
+     should return either TEXT, if it should be used as-is, a replacement
+     string, which should be malloced, and will be freed by argp, or NULL,
+     meaning `print nothing'.  The value for TEXT is *after* any translation
+     has been done, so if any of the replacement text also needs translation,
+     that should be done by the filter function.  INPUT is either the input
+     supplied to argp_parse, or NULL, if argp_help was called directly.  */
+  char *(*help_filter)(int __key, __const char *__text, void *__input);
 };
+
+/* Possible KEY arguments to a help filter function.  */
+#define ARGP_KEY_HELP_PRE_DOC	0x2000001 /* Help text preceeding options. */
+#define ARGP_KEY_HELP_POST_DOC	0x2000002 /* Help text following options. */
+#define ARGP_KEY_HELP_HEADER	0x2000003 /* Option header string. */
+#define ARGP_KEY_HELP_EXTRA	0x2000004 /* After all other documentation;
+					     TEXT is NULL for this key.  */
 
 /* When an argp has a non-zero CHILDREN field, it should point to a vector of
    argp_child structures, each of which describes a subsidiary argp.  */
@@ -265,6 +290,8 @@ struct argp_state
   /* Streams used when argp prints something.  */
   FILE *err_stream;		/* For errors; initialized to stderr. */
   FILE *out_stream;		/* For information; initialized to stdout. */
+
+  void *pstate;			/* Private, for use by argp.  */
 };
 
 /* Flags for argp_parse (note that the defaults are those that are
@@ -318,20 +345,20 @@ struct argp_state
    routine returned a non-zero value, it is returned; otherwise 0 is
    returned.  This function may also call exit unless the ARGP_NO_HELP flag
    is set.  INPUT is a pointer to a value to be passed in to the parser.  */
-error_t argp_parse __P ((__const struct argp *__argp,
-			 int __argc, char **__argv, unsigned __flags,
-			 int *__arg_index, void *__input));
-error_t __argp_parse __P ((__const struct argp *__argp,
-			   int __argc, char **__argv, unsigned __flags,
-			   int *__arg_index, void *__input));
+extern error_t argp_parse __P ((__const struct argp *__argp,
+				int __argc, char **__argv, unsigned __flags,
+				int *__arg_index, void *__input));
+extern error_t __argp_parse __P ((__const struct argp *__argp,
+				  int __argc, char **__argv, unsigned __flags,
+				  int *__arg_index, void *__input));
 
 /* Global variables.  */
 
 /* If defined or set by the user program to a non-zero value, then a default
    option --version is added (unless the ARGP_NO_HELP flag is used), which
-   will print this this string followed by a newline and exit (unless the
+   will print this string followed by a newline and exit (unless the
    ARGP_NO_EXIT flag is used).  Overridden by ARGP_PROGRAM_VERSION_HOOK.  */
-extern char *argp_program_version;
+extern const char *argp_program_version;
 
 /* If defined or set by the user program to a non-zero value, then a default
    option --version is added (unless the ARGP_NO_HELP flag is used), which
@@ -406,9 +433,11 @@ extern void __argp_usage __P ((struct argp_state *__state));
 /* If appropriate, print the printf string FMT and following args, preceded
    by the program name and `:', to stderr, and followed by a `Try ... --help'
    message, then exit (1).  */
-void argp_error __P ((struct argp_state *__state, __const char *__fmt, ...))
+extern void argp_error __P ((struct argp_state *__state, __const char *__fmt,
+			     ...))
      __attribute__ ((__format__ (__printf__, 2, 3)));
-void __argp_error __P ((struct argp_state *__state, __const char *__fmt, ...))
+extern void __argp_error __P ((struct argp_state *__state,
+			       __const char *__fmt, ...))
      __attribute__ ((__format__ (__printf__, 2, 3)));
 
 /* Similar to the standard gnu error-reporting function error(), but will
@@ -419,11 +448,11 @@ void __argp_error __P ((struct argp_state *__state, __const char *__fmt, ...))
    difference between this function and argp_error is that the latter is for
    *parsing errors*, and the former is for other problems that occur during
    parsing but don't reflect a (syntactic) problem with the input.  */
-void argp_failure __P ((struct argp_state *__state,
-			int __status, int __errnum, __const char *__fmt, ...))
+extern void argp_failure __P ((struct argp_state *__state, int __status,
+			       int __errnum, __const char *__fmt, ...))
      __attribute__ ((__format__ (__printf__, 4, 5)));
-void __argp_failure __P ((struct argp_state *__state,
-			  int __status, int __errnum, __const char *__fmt, ...))
+extern void __argp_failure __P ((struct argp_state *__state, int __status,
+				 int __errnum, __const char *__fmt, ...))
      __attribute__ ((__format__ (__printf__, 4, 5)));
 
 /* Returns true if the option OPT is a valid short option.  */
@@ -434,6 +463,13 @@ extern int __option_is_short __P ((__const struct argp_option *__opt));
    options array.  */
 extern int _option_is_end __P ((__const struct argp_option *__opt));
 extern int __option_is_end __P ((__const struct argp_option *__opt));
+
+/* Return the input field for ARGP in the parser corresponding to STATE; used
+   by the help routines.  */
+extern void *_argp_input __P ((__const struct argp *argp,
+			       __const struct argp_state *state));
+extern void *__argp_input __P ((__const struct argp *argp,
+				__const struct argp_state *state));
 
 #ifdef __OPTIMIZE__
 
diff --git a/elf/dl-hash.h b/elf/dl-hash.h
new file mode 100644
index 0000000000..007f192a23
--- /dev/null
+++ b/elf/dl-hash.h
@@ -0,0 +1,69 @@
+/* Compute hash alue for given string according to ELF standard.
+   Copyright (C) 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 Library General Public License as
+   published by the Free Software Foundation; either version 2 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
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If not,
+   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#ifndef _DL_HASH_H
+#define _DL_HASH_H	1
+
+
+/* This is the hashing function specified by the ELF ABI.  In the
+   first five operations now overflow is possible so we optimized it a
+   bit.  */
+static inline unsigned
+_dl_elf_hash (const char *name)
+{
+  unsigned long int hash = 0;
+  if (*name != '\0')
+    {
+      hash = (hash << 4) + *name++;
+      if (*name != '\0')
+	{
+	  hash = (hash << 4) + *name++;
+	  if (*name != '\0')
+	    {
+	      hash = (hash << 4) + *name++;
+	      if (*name != '\0')
+		{
+		  hash = (hash << 4) + *name++;
+		  if (*name != '\0')
+		    {
+		      hash = (hash << 4) + *name++;
+		      while (*name != '\0')
+			{
+			  unsigned long int hi;
+			  hash = (hash << 4) + *name++;
+			  hi = hash & 0xf0000000;
+			  if (hi != 0)
+			    {
+			      hash ^= hi >> 24;
+			      /* The ELF ABI says `hash &= ~hi', but
+				 this is equivalent in this case and
+				 on some machines one insn instead of
+				 two.  */
+			      hash ^= hi;
+			    }
+			}
+		    }
+		}
+	    }
+	}
+    }
+  return hash;
+}
+
+#endif /* dl-hash.h */
diff --git a/elf/dl-load.c b/elf/dl-load.c
index e3de0764ec..a103d38548 100644
--- a/elf/dl-load.c
+++ b/elf/dl-load.c
@@ -540,7 +540,7 @@ _dl_map_object (struct link_map *loader, const char *name, int type,
 
   /* Look for this name among those already loaded.  */
   for (l = _dl_loaded; l; l = l->l_next)
-    if (_dl_does_name_match_p (name, l) ||
+    if (_dl_name_match_p (name, l) ||
 	/* If the requested name matches the soname of a loaded object,
 	   use that object.  */
 	(l->l_info[DT_SONAME] &&
diff --git a/elf/dl-lookup.c b/elf/dl-lookup.c
index 06d1d09b90..8702a85bbb 100644
--- a/elf/dl-lookup.c
+++ b/elf/dl-lookup.c
@@ -22,6 +22,7 @@
 #include <assert.h>
 #include <string.h>
 
+#include <dl-hash.h>
 #include "../stdio-common/_itoa.h"
 
 #define VERSTAG(tag)	(DT_NUM + DT_PROCNUM + DT_VERSIONTAGIDX (tag))
@@ -33,58 +34,32 @@ struct sym_val
   };
 
 
-/* This is the hashing function specified by the ELF ABI.  In the
-   first five operations now overflow is possible so we optimized it a
-   bit.  */
-static inline unsigned
-_dl_elf_hash (const char *name)
-{
-  unsigned long int hash = 0;
-  if (*name != '\0')
-    {
-      hash = (hash << 4) + *name++;
-      if (*name != '\0')
-	{
-	  hash = (hash << 4) + *name++;
-	  if (*name != '\0')
-	    {
-	      hash = (hash << 4) + *name++;
-	      if (*name != '\0')
-		{
-		  hash = (hash << 4) + *name++;
-		  if (*name != '\0')
-		    {
-		      hash = (hash << 4) + *name++;
-		      while (*name != '\0')
-			{
-			  unsigned long int hi;
-			  hash = (hash << 4) + *name++;
-			  hi = hash & 0xf0000000;
-			  if (hi != 0)
-			    {
-			      hash ^= hi >> 24;
-			      /* The ELF ABI says `hash &= ~hi', but
-				 this is equivalent in this case and
-				 on some machines one insn instead of
-				 two.  */
-			      hash ^= hi;
-			    }
-			}
-		    }
-		}
-	    }
-	}
-    }
-  return hash;
-}
-
-
-/* Inner part of the lookup functions.  */
-static inline ElfW(Addr)
+#define make_string(string, rest...) \
+  ({									      \
+    const char *all[] = { string, ## rest };				      \
+    size_t len, cnt;							      \
+    char *result, *cp;							      \
+									      \
+    len = 1;								      \
+    for (cnt = 0; cnt < sizeof (all) / sizeof (all[0]); ++cnt)		      \
+      len += strlen (all[cnt]);						      \
+									      \
+    cp = result = alloca (len);						      \
+    for (cnt = 0; cnt < sizeof (all) / sizeof (all[0]); ++cnt)		      \
+      cp = stpcpy (cp, all[cnt]);					      \
+									      \
+    result;								      \
+  })
+
+
+/* Inner part of the lookup functions.  We return a value > 0 if we
+   found the symbol, the value 0 if nothing is found and < 0 if
+   something bad happened.  */
+static inline int
 do_lookup (const char *undef_name, unsigned long int hash,
 	   const ElfW(Sym) **ref, struct sym_val *result,
 	   struct link_map *list[], size_t i, size_t n,
-	   const char *reference_name, const hash_name_pair *version,
+	   const char *reference_name, const struct r_found_version *version,
 	   struct link_map *skip, int flags)
 {
   struct link_map *map;
@@ -108,8 +83,7 @@ do_lookup (const char *undef_name, unsigned long int hash,
 
       symtab = ((void *) map->l_addr + map->l_info[DT_SYMTAB]->d_un.d_ptr);
       strtab = ((void *) map->l_addr + map->l_info[DT_STRTAB]->d_un.d_ptr);
-      if (version != NULL
-	  && map->l_nversions > 0 && map->l_info[VERSTAG (DT_VERSYM)] != NULL)
+      if (map->l_nversions > 0 && map->l_info[VERSTAG (DT_VERSYM)] != NULL)
 	verstab = ((void *) map->l_addr
 		   + map->l_info[VERSTAG (DT_VERSYM)]->d_un.d_ptr);
       else
@@ -143,13 +117,41 @@ do_lookup (const char *undef_name, unsigned long int hash,
 	    /* Not the symbol we are looking for.  */
 	    continue;
 
-	  if (verstab != NULL)
+	  if (version == NULL)
 	    {
-	      /* We can match the version information.  */
-	      ElfW(Half) ndx = verstab[symidx] & 0x7fff;
-	      if (map->l_versions[ndx].hash != version->hash
-		  || strcmp (map->l_versions[ndx].name, version->name))
-	      continue;
+	      /* No specific version is selected.  When the object
+		 file also does not define a version we have a match.
+		 Otherwise we only accept the default version, i.e.,
+		 the version which name is "".  */
+	      if (verstab != NULL)
+		{
+		  ElfW(Half) ndx = verstab[symidx] & 0x7fff;
+		  if (map->l_versions[ndx].hash != 0)
+		    continue;
+		}
+	    }
+	  else
+	    {
+	      if (verstab == NULL)
+		{
+		  /* We need a versioned system but haven't found any.
+		     If this is the object which is referenced in the
+		     verneed entry it is a bug in the library since a
+		     symbol must not simply disappear.  */
+		  if (version->filename != NULL
+		      && _dl_name_match_p (version->filename, map))
+		    return -1;
+		  /* Otherwise we accept the symbol.  */
+		}
+	      else
+		{
+		  /* We can match the version information.  */
+		  ElfW(Half) ndx = verstab[symidx] & 0x7fff;
+		  if (map->l_versions[ndx].hash != version->hash
+		      || strcmp (map->l_versions[ndx].name, version->name))
+		    /* It's not the version we want.  */
+		    continue;
+		}
 	    }
 
 	  switch (ELFW(ST_BIND) (sym->st_info))
@@ -173,6 +175,12 @@ do_lookup (const char *undef_name, unsigned long int hash,
 	      break;
 	    }
 	}
+
+      /* If this current is the one mentioned in the verneed entry it
+	 is a bug.  */
+      if (version != NULL && version->filename != NULL
+	  && _dl_name_match_p (version->filename, map))
+	return -1;
     }
 
   /* We have not found anything until now.  */
@@ -204,15 +212,9 @@ _dl_lookup_symbol (const char *undef_name, const ElfW(Sym) **ref,
 
   if (current_value.s == NULL &&
       (*ref == NULL || ELFW(ST_BIND) ((*ref)->st_info) != STB_WEAK))
-    {
-      /* We could find no value for a strong reference.  */
-      static const char msg[] = "undefined symbol: ";
-      const size_t len = strlen (undef_name);
-      char buf[sizeof msg + len];
-      memcpy (buf, msg, sizeof msg - 1);
-      memcpy (&buf[sizeof msg - 1], undef_name, len + 1);
-      _dl_signal_error (0, reference_name, buf);
-    }
+    /* We could find no value for a strong reference.  */
+    _dl_signal_error (0, reference_name,
+		      make_string ("undefined symbol: ", undef_name));
 
   *ref = current_value.s;
   return current_value.a;
@@ -264,7 +266,7 @@ ElfW(Addr)
 _dl_lookup_versioned_symbol (const char *undef_name, const ElfW(Sym) **ref,
 			     struct link_map *symbol_scope[],
 			     const char *reference_name,
-			     const hash_name_pair *version, int flags)
+			     const struct r_found_version *version, int flags)
 {
   const unsigned long int hash = _dl_elf_hash (undef_name);
   struct sym_val current_value = { 0, NULL };
@@ -272,28 +274,30 @@ _dl_lookup_versioned_symbol (const char *undef_name, const ElfW(Sym) **ref,
 
   /* Search the relevant loaded objects for a definition.  */
   for (scope = symbol_scope; *scope; ++scope)
-    if (do_lookup (undef_name, hash, ref, &current_value,
-		   (*scope)->l_searchlist, 0, (*scope)->l_nsearchlist,
-		   reference_name, version, NULL, flags))
-      break;
+    {
+      int res = do_lookup (undef_name, hash, ref, &current_value,
+			   (*scope)->l_searchlist, 0, (*scope)->l_nsearchlist,
+			   reference_name, version, NULL, flags);
+      if (res > 0)
+	break;
+
+      if (res < 0)
+	/* Oh, oh.  The file named in the relocation entry does not
+	   contain the needed symbol.  */
+	_dl_signal_error (0, *reference_name ? reference_name : NULL,
+			  make_string ("symbol ", undef_name, ", version ",
+				       version->name,
+				       " not defined in file ",
+				       version->filename,
+				       " with link time reference"));
+    }
 
   if (current_value.s == NULL &&
       (*ref == NULL || ELFW(ST_BIND) ((*ref)->st_info) != STB_WEAK))
-    {
-      /* We could find no value for a strong reference.  */
-      static const char msg1[] = "undefined symbol: ";
-      const size_t len = strlen (undef_name);
-      static const char msg2[] = ", version ";
-      const size_t verslen = strlen (version->name ?: "") + 1;
-      char buf[sizeof msg1 - 1 + len + sizeof msg2 - 1 + verslen];
-
-      memcpy (buf, msg1, sizeof msg1 - 1);
-      memcpy (&buf[sizeof msg1 - 1], undef_name, len + 1);
-      memcpy (&buf[sizeof msg1 - 1 + len], msg2, sizeof msg2 - 1);
-      memcpy (&buf[sizeof msg1 - 1 + len + sizeof msg2 - 1], version->name,
-	      verslen);
-      _dl_signal_error (0, reference_name, buf);
-    }
+    /* We could find no value for a strong reference.  */
+    _dl_signal_error (0, reference_name,
+		      make_string ("undefined symbol: ", undef_name,
+				   ", version ", version->name ?: NULL));
 
   *ref = current_value.s;
   return current_value.a;
@@ -307,20 +311,15 @@ _dl_lookup_versioned_symbol_skip (const char *undef_name,
 				  const ElfW(Sym) **ref,
 				  struct link_map *symbol_scope[],
 				  const char *reference_name,
-				  const char *version_name,
+				  const struct r_found_version *version,
 				  struct link_map *skip_map,
 				  int flags)
 {
   const unsigned long int hash = _dl_elf_hash (undef_name);
   struct sym_val current_value = { 0, NULL };
   struct link_map **scope;
-  hash_name_pair version;
   size_t i;
 
-  /* First convert the VERSION_NAME into a `hash_name_pair' value.  */
-  version.hash = _dl_elf_hash (version_name);
-  version.name = version_name;
-
   /* Search the relevant loaded objects for a definition.  */
   scope = symbol_scope;
   for (i = 0; (*scope)->l_dupsearchlist[i] != skip_map; ++i)
@@ -328,11 +327,11 @@ _dl_lookup_versioned_symbol_skip (const char *undef_name,
 
   if (! do_lookup (undef_name, hash, ref, &current_value,
 		   (*scope)->l_dupsearchlist, i, (*scope)->l_ndupsearchlist,
-		   reference_name, &version, skip_map, flags))
+		   reference_name, version, skip_map, flags))
     while (*++scope)
       if (do_lookup (undef_name, hash, ref, &current_value,
 		     (*scope)->l_dupsearchlist, 0, (*scope)->l_ndupsearchlist,
-		     reference_name, &version, skip_map, flags))
+		     reference_name, version, skip_map, flags))
 	break;
 
   *ref = current_value.s;
diff --git a/elf/dl-version.c b/elf/dl-version.c
index 4382a4c0ae..ae1c2f34f7 100644
--- a/elf/dl-version.c
+++ b/elf/dl-version.c
@@ -58,7 +58,7 @@ find_needed (struct link_map *map, const char *name)
   unsigned int n;
 
   for (n = 0; n < map->l_nsearchlist; ++n)
-    if (_dl_does_name_match_p (name, map->l_searchlist[n]))
+    if (_dl_name_match_p (name, map->l_searchlist[n]))
       return map->l_searchlist[n];
 
   /* Should never happen.  */
@@ -246,13 +246,14 @@ _dl_check_map_versions (struct link_map *map, int verbose)
       /* Now we are ready to build the array with the version names
 	 which can be indexed by the version index in the VERSYM
 	 section.  */
-      map->l_versions = (hash_name_pair*) malloc ((ndx_high + 1)
-						  * sizeof (hash_name_pair));
-      memset (map->l_versions, '\0', (ndx_high + 1) * sizeof (hash_name_pair));
+      map->l_versions = (struct r_found_version *)
+	malloc ((ndx_high + 1) * sizeof (*map->l_versions));
+      memset (map->l_versions, '\0',
+	      (ndx_high + 1) * sizeof (*map->l_versions));
       if (map->l_versions == NULL)
 	{
 	  _dl_signal_error (ENOMEM, (*map->l_name ? map->l_name : _dl_argv[0]),
-			    "cannot allocate version name table");
+			    "cannot allocate version reference table");
 	  result = 1;
 	}
       else
@@ -273,6 +274,7 @@ _dl_check_map_versions (struct link_map *map, int verbose)
 		      ElfW(Half) ndx = aux->vna_other & 0x7fff;
 		      map->l_versions[ndx].hash = aux->vna_hash;
 		      map->l_versions[ndx].name = &strtab[aux->vna_name];
+		      map->l_versions[ndx].filename = &strtab[ent->vn_file];
 
 		      if (aux->vna_next == 0)
 			/* No more symbols.  */
@@ -308,6 +310,7 @@ _dl_check_map_versions (struct link_map *map, int verbose)
 		      ElfW(Half) ndx = ent->vd_ndx & 0x7fff;
 		      map->l_versions[ndx].hash = ent->vd_hash;
 		      map->l_versions[ndx].name = &strtab[aux->vda_name];
+		      map->l_versions[ndx].filename = NULL;
 		    }
 
 		  if (ent->vd_next == 0)
diff --git a/elf/dlvsym.c b/elf/dlvsym.c
index 5063b3ba0d..922a6eed1f 100644
--- a/elf/dlvsym.c
+++ b/elf/dlvsym.c
@@ -1,4 +1,4 @@
-/* Look up a symbol in a shared object loaded by `dlopen'.
+/* Look up a versioned symbol in a shared object loaded by `dlopen'.
    Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
@@ -22,12 +22,14 @@
 #include <dlfcn.h>
 #include <setjmp.h>
 
+#include <dl-hash.h>
 
 void *
-__dlvsym (void *handle, const char *name, const char *version)
+__dlvsym (void *handle, const char *name, const char *version_str)
 {
   ElfW(Addr) caller = (ElfW(Addr)) __builtin_return_address (0);
   ElfW(Addr) loadbase;
+  struct r_found_version version;
   const ElfW(Sym) *ref = NULL;
   void doit (void)
     {
@@ -35,7 +37,7 @@ __dlvsym (void *handle, const char *name, const char *version)
 	/* Search the global scope.  */
 	loadbase = _dl_lookup_versioned_symbol
 	  (name, &ref, &(_dl_global_scope ?: _dl_default_scope)[2], NULL,
-	   version, 0);
+	   &version, 0);
       else if (handle == RTLD_NEXT)
 	{
 	  struct link_map *l, *match;
@@ -55,7 +57,7 @@ RTLD_NEXT used in code not dynamically loaded"));
 	    l = l->l_loader;
 
 	  loadbase = _dl_lookup_versioned_symbol_skip
-	    (name, &ref, &_dl_loaded, NULL, version, l, 0);
+	    (name, &ref, &_dl_loaded, NULL, &version, l, 0);
 	}
       else
 	{
@@ -63,10 +65,16 @@ RTLD_NEXT used in code not dynamically loaded"));
 	  struct link_map *map = handle;
 	  struct link_map *mapscope[2] = { map, NULL };
 	  loadbase = _dl_lookup_versioned_symbol
-	    (name, &ref, mapscope, map->l_name, version, 0);
+	    (name, &ref, mapscope, map->l_name, &version, 0);
 	}
     }
 
+  /* Compute hash value to the version string.  */
+  version.name = version_str;
+  version.hash = _dl_elf_hash (version_str);
+  /* We don't have a specific file where the symbol can be found.  */
+  version.filename = NULL;
+
   return _dlerror_run (doit) ? NULL : (void *) (loadbase + ref->st_value);
 }
 weak_alias (__dlvsym, dlvsym)
diff --git a/elf/link.h b/elf/link.h
index 58041332e9..b0b920074b 100644
--- a/elf/link.h
+++ b/elf/link.h
@@ -25,6 +25,8 @@
 
 #include <elf.h>
 
+__BEGIN_DECLS
+
 /* We use this macro to refer to ELF types independent of the native wordsize.
    `ElfW(TYPE)' is used in place of `Elf32_TYPE' or `Elf64_TYPE'.  */
 #define ElfW(type)	_ElfW (Elf, __ELF_NATIVE_CLASS, type)
@@ -76,11 +78,13 @@ extern ElfW(Dyn) _DYNAMIC[];
 
 /* For the version handling we need an array with only names and their
    hash values.  */
-typedef struct
-{
-  const char *name;
-  ElfW(Word) hash;
-} hash_name_pair;
+struct r_found_version
+  {
+    const char *name;
+    ElfW(Word) hash;
+
+    const char *filename;
+  };
 
 /* Structure describing a loaded shared object.  The `l_next' and `l_prev'
    members form a chain of all the shared objects loaded at startup.
@@ -153,14 +157,14 @@ struct link_map
 
     /* Array with version names.  */
     unsigned int l_nversions;
-    hash_name_pair *l_versions;
+    struct r_found_version *l_versions;
   };
 
 
 /* Test whether given NAME matches any of the names of the given object.  */
 static inline int
 __attribute__ ((unused))
-_dl_does_name_match_p (const char *__name, struct link_map *__map)
+_dl_name_match_p (const char *__name, struct link_map *__map)
 {
   int __found = strcmp (__name, __map->l_name) == 0;
   struct libname_list *__runp = __map->l_libname;
@@ -301,7 +305,7 @@ extern ElfW(Addr) _dl_lookup_versioned_symbol (const char *undef,
 					       const ElfW(Sym) **sym,
 					       struct link_map *symbol_scope[],
 					       const char *reference_name,
-					       const hash_name_pair *version,
+					       const struct r_found_version *version,
 					       int flags);
 
 /* For handling RTLD_NEXT we must be able to skip shared objects.  */
@@ -318,7 +322,7 @@ extern ElfW(Addr) _dl_lookup_versioned_symbol_skip (const char *undef,
 						    const ElfW(Sym) **sym,
 						    struct link_map *symbol_scope[],
 						    const char *reference_name,
-						    const char *version_name,
+						    const struct r_found_version *version,
 						    struct link_map *skip_this,
 						    int flags);
 
@@ -398,5 +402,6 @@ extern void _dl_debug_state (void);
    in the `r_ldbase' member.  Returns the address of the structure.  */
 extern struct r_debug *_dl_debug_initialize (ElfW(Addr) ldbase);
 
+__END_DECLS
 
 #endif /* link.h */
diff --git a/errno.h b/errno.h
index f7736ba8d0..b8486728b7 100644
--- a/errno.h
+++ b/errno.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 1991, 92, 93, 94, 95, 96 Free Software Foundation, Inc.
+/* Copyright (C) 1991, 92, 93, 94, 95, 96, 97 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
@@ -49,13 +49,6 @@ extern int errno;
 
 #ifdef __USE_GNU
 
-/* The Hurd <errnos.h> defines `error_t' as an enumerated type
-   so that printing `error_t' values in the debugger shows the names.  */
-#ifndef __error_t_defined
-typedef int error_t;
-#define __error_t_defined	1
-#endif
-
 /* The full and simple forms of the name with which the program was
    invoked.  These variables are set up automatically at startup based on
    the value of ARGV[0] (this works only if you use GNU ld).  */
@@ -65,4 +58,16 @@ extern char *program_invocation_name, *program_invocation_short_name;
 
 __END_DECLS
 
-#endif /* errno.h	*/
+#endif /* _ERRNO_H */
+
+/* The Hurd <errnos.h> defines `error_t' as an enumerated type so that
+   printing `error_t' values in the debugger shows the names.  We
+   might need this definition sometimes even if this file was included
+   before.  */
+#if defined __USE_GNU || defined __need_error_t
+# ifndef __error_t_defined
+typedef int error_t;
+#  define __error_t_defined	1
+# endif
+# undef __need_error_t
+#endif
diff --git a/inet/Makefile b/inet/Makefile
index e965390a63..02e10335f4 100644
--- a/inet/Makefile
+++ b/inet/Makefile
@@ -43,7 +43,8 @@ routines := ntohl ntohs htonl htons		\
 	    ether_ntoa ether_ntoa_r ether_ntoh \
 	    rcmd rexec ruserpass \
 	    getnetgrent_r getnetgrent \
-	    getaliasent_r getaliasent getaliasname getaliasname_r
+	    getaliasent_r getaliasent getaliasname getaliasname_r \
+	    in6_addr getnameinfo
 
 # No warnings about losing BSD code.
 CFLAGS-rcmd.c = -w
diff --git a/inet/getnameinfo.c b/inet/getnameinfo.c
new file mode 100644
index 0000000000..b9454f6396
--- /dev/null
+++ b/inet/getnameinfo.c
@@ -0,0 +1,238 @@
+/* The Inner Net License, Version 2.00
+
+  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:
+
+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. All advertising materials mentioning features or use of this software
+   must display the following acknowledgement with the name(s) of the
+   authors as specified in the copyright notice(s) substituted where
+   indicated:
+
+	This product includes software developed by <name(s)>, The Inner
+	Net, and other contributors.
+
+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.
+
+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.  */
+
+#define INET6 1
+#define LOCAL 1
+#define HOSTTABLE 0
+
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#include <netinet/in.h>
+#if LOCAL
+#include <sys/un.h>
+#include <sys/utsname.h>
+#endif /* LOCAL */
+#include <netdb.h>
+#include <errno.h>
+#include <string.h>
+#include <stdio.h>
+#include <unistd.h>
+
+#ifndef AF_LOCAL
+#define AF_LOCAL AF_UNIX
+#endif /* AF_LOCAL */
+
+#if HOSTTABLE
+struct hostent *_addr2hostname_hosts(const char *, int, int);
+#endif /* HOSTTABLE */
+
+#ifndef MAXHOSTNAMELEN
+#define MAXHOSTNAMELEN 128
+#endif
+
+#ifndef min
+#define min(x,y) (((x) > (y)) ? (y) : (x))
+#endif /* min */
+
+static char *domain;
+static char domainbuffer[MAXHOSTNAMELEN];
+
+
+static char *
+nrl_domainname (void)
+{
+  static int first = 1;
+
+  if (first) {
+    char *c;
+    struct hostent *h;
+
+    first = 0;
+
+    if ((h = gethostbyname("localhost")) && (c = strchr(h->h_name, '.')))
+      return strcpy(domain = domainbuffer, ++c);
+
+    if (!gethostname(domainbuffer, sizeof(domainbuffer))) {
+      if (c = strchr(domainbuffer, '.'))
+        return (domain = ++c);
+
+      if ((h = gethostbyname(domainbuffer)) && (c = strchr(h->h_name, '.')))
+        return strcpy(domain = domainbuffer, ++c);
+    }
+
+    {
+      struct in_addr in_addr;
+
+      in_addr.s_addr = htonl(0x7f000001);
+
+      if ((h = gethostbyaddr((const char *)&in_addr, sizeof(struct in_addr), AF_INET)) && (c = strchr(h->h_name, '.')))
+        return strcpy(domain = domainbuffer, ++c);
+    }
+
+    return NULL;
+  };
+
+  return domain;
+};
+
+int getnameinfo(const struct sockaddr *sa, size_t addrlen, char *host, size_t hostlen, char *serv, size_t servlen, int flags)
+{
+  int serrno = errno;
+
+  if (!sa)
+    return -1;
+
+  if (host && (hostlen > 0))
+    switch(sa->sa_family) {
+      case AF_INET:
+#if INET6
+      case AF_INET6:
+#endif /* INET6 */
+	if (!(flags & NI_NUMERICHOST)) {
+	  struct hostent *h = NULL;
+#if HOSTTABLE
+#if INET6
+	  if (sa->sa_family == AF_INET6)
+	    h = _addr2hostname_hosts((void *)&(((struct sockaddr_in6 *)sa)->sin6_addr), sizeof(struct in6_addr), AF_INET6);
+	  else
+#endif /* INET6 */
+	    h = _addr2hostname_hosts((void *)&(((struct sockaddr_in *)sa)->sin_addr), sizeof(struct in_addr), AF_INET);
+#endif /* HOSTTABLE */
+
+#if RESOLVER
+	  if (!h) {
+#if INET6
+	    if (sa->sa_family == AF_INET6)
+	      h = gethostbyaddr((void *)&(((struct sockaddr_in6 *)sa)->sin6_addr), sizeof(struct in6_addr), AF_INET6);
+	    else
+#endif /* INET6 */
+	      h = gethostbyaddr((void *)&(((struct sockaddr_in *)sa)->sin_addr), sizeof(struct in_addr), AF_INET);
+	    endhostent();
+	  };
+#endif /* RESOLVER */
+
+	  if (h) {
+	    if (flags & NI_NOFQDN) {
+	      char *c;
+	      if ((c = nrl_domainname()) && (c = strstr(h->h_name, c)) && (c != h->h_name) && (*(--c) == '.')) {
+		strncpy(host, h->h_name, min(hostlen, (c - h->h_name)));
+		break;
+	      };
+	    };
+	    strncpy(host, h->h_name, hostlen);
+	    break;
+	  };
+	};
+
+	if (flags & NI_NAMEREQD)
+	  goto fail;
+
+        {
+	  const char *c;
+#if INET6
+	  if (sa->sa_family == AF_INET6)
+	    c = inet_ntop(AF_INET6, (void *)&(((struct sockaddr_in6 *)sa)->sin6_addr), host, hostlen);
+	  else
+#endif /* INET6 */
+	    c = inet_ntop(AF_INET, (void *)&(((struct sockaddr_in *)sa)->sin_addr), host, hostlen);
+
+	  if (!c)
+	    goto fail;
+	};
+	break;
+#if LOCAL
+      case AF_LOCAL:
+	if (!(flags & NI_NUMERICHOST)) {
+	  struct utsname utsname;
+
+	  if (!uname(&utsname)) {
+	    strncpy(host, utsname.nodename, hostlen);
+	    break;
+	  };
+	};
+
+	if (flags & NI_NAMEREQD)
+	  goto fail;
+
+	strncpy(host, "localhost", hostlen);
+	break;
+#endif /* LOCAL */
+      default:
+        return -1;
+    };
+
+  if (serv && (servlen > 0))
+    switch(sa->sa_family) {
+      case AF_INET:
+#if INET6
+      case AF_INET6:
+#endif /* INET6 */
+	if (!(flags & NI_NUMERICSERV)) {
+	  struct servent *s;
+	  if (s = getservbyport(((struct sockaddr_in *)sa)->sin_port, (flags & NI_DGRAM) ? "udp" : "tcp")) {
+	    strncpy(serv, s->s_name, servlen);
+	    break;
+	  };
+	};
+	snprintf(serv, servlen, "%d", ntohs(((struct sockaddr_in *)sa)->sin_port));
+	break;
+#if LOCAL
+      case AF_LOCAL:
+	strncpy(serv, ((struct sockaddr_un *)sa)->sun_path, servlen);
+	break;
+#endif /* LOCAL */
+    };
+
+  if (host && (hostlen > 0))
+    host[hostlen-1] = 0;
+  if (serv && (servlen > 0))
+    serv[servlen-1] = 0;
+  errno = serrno;
+  return 0;
+
+fail:
+  errno = serrno;
+  return -1;
+};
diff --git a/inet/in6_addr.c b/inet/in6_addr.c
new file mode 100644
index 0000000000..a68990e160
--- /dev/null
+++ b/inet/in6_addr.c
@@ -0,0 +1,28 @@
+/* Copyright (C) 1996, 1997 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Philip Blundell <pjb27@cam.ac.uk>, 1997.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public License as
+   published by the Free Software Foundation; either version 2 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
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If not,
+   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#include <netinet/in.h>
+
+const struct in6_addr in6addr_any = { { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } };
+const struct in6_addr in6addr_loopback = { { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1 } };
+
+int inet6_isipv4mapped(const struct in6_addr *addr)
+{
+  return IN6_IS_ADDR_V4MAPPED(addr);
+}
diff --git a/inet/net/ethernet.h b/inet/net/ethernet.h
new file mode 100644
index 0000000000..89a92c53f1
--- /dev/null
+++ b/inet/net/ethernet.h
@@ -0,0 +1,76 @@
+/* Copyright (C) 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 Library General Public License as
+   published by the Free Software Foundation; either version 2 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
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If not,
+   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+/* Based on the FreeBSD version of this file. Curiously, that file
+   lacks a copyright in the header. */
+
+#ifndef __NET_ETHERNET_H
+#define __NET_ETHERNET_H 1
+
+#include <sys/cdefs.h>
+#include <sys/types.h>
+#include <linux/if_ether.h>     /* IEEE 802.3 Ethernet constants */
+
+__BEGIN_DECLS
+
+/* This is a name for the 48 bit ethernet address available on many
+   systems.  */
+struct ether_addr
+{
+  u_int8_t ether_addr_octet[ETH_ALEN];
+};
+
+/* 10Mb/s ethernet header */
+struct ether_header
+{
+  u_int8_t  ether_dhost[ETH_ALEN];	/* destination eth addr	*/
+  u_int8_t  ether_shost[ETH_ALEN];	/* source ether addr	*/
+  u_int16_t ether_type;		        /* packet type ID field	*/
+};
+
+/* Ethernet protocol ID's */
+#define	ETHERTYPE_PUP		0x0200          /* Xerox PUP */
+#define	ETHERTYPE_IP		0x0800		/* IP */
+#define	ETHERTYPE_ARP		0x0806		/* Address resolution */
+#define	ETHERTYPE_REVARP	0x8035		/* Reverse ARP */
+
+#define	ETHER_ADDR_LEN	ETH_ALEN                 /* size of ethernet addr */
+#define	ETHER_TYPE_LEN	2                        /* bytes in type field */
+#define	ETHER_CRC_LEN	4                        /* bytes in CRC field */
+#define	ETHER_HDR_LEN	ETH_HLEN                 /* total octets in header */
+#define	ETHER_MIN_LEN	(ETH_ZLEN + ETH_CRC_LEN) /* min packet length */
+#define	ETHER_MAX_LEN	(ETH_FRAME_LEN + ETH_CRC_LEN) /* max packet length */
+
+/* make sure ethenet length is valid */
+#define	ETHER_IS_VALID_LEN(foo)	\
+	((foo) >= ETHER_MIN_LEN && (foo) <= ETHER_MAX_LEN)
+
+/*
+ * The ETHERTYPE_NTRAILER packet types starting at ETHERTYPE_TRAIL have
+ * (type-ETHERTYPE_TRAIL)*512 bytes of data followed
+ * by an ETHER type (as given above) and then the (variable-length) header.
+ */
+#define	ETHERTYPE_TRAIL		0x1000		/* Trailer packet */
+#define	ETHERTYPE_NTRAILER	16
+
+#define	ETHERMTU	ETH_DATA_LEN
+#define	ETHERMIN	(ETHER_MIN_LEN-ETHER_HDR_LEN-ETHER_CRC_LEN)
+
+__END_DECLS
+
+#endif /* net/ethernet.h */
diff --git a/intl/l10nflist.c b/intl/l10nflist.c
index d16bff01fa..4f45d3db4e 100644
--- a/intl/l10nflist.c
+++ b/intl/l10nflist.c
@@ -206,7 +206,8 @@ _nl_make_l10nflist (l10nfile_list, dirlist, dirlist_len, mask, language,
 				     ? strlen (modifier) + 1 : 0)
 				  + ((mask & CEN_SPECIAL) != 0
 				     ? strlen (special) + 1 : 0)
-				  + ((mask & (CEN_SPONSOR | CEN_REVISION) != 0)
+				  + (((mask & CEN_SPONSOR) != 0
+				      || (mask & CEN_REVISION) != 0)
 				     ? (1 + ((mask & CEN_SPONSOR) != 0
 					     ? strlen (sponsor) + 1 : 0)
 					+ ((mask & CEN_REVISION) != 0
diff --git a/io/ftw.h b/io/ftw.h
index 0bfdf37431..e6d0b63626 100644
--- a/io/ftw.h
+++ b/io/ftw.h
@@ -34,6 +34,8 @@
 #define FTW_DNR	2		/* Unreadable directory.  */
 #define FTW_NS	3		/* Unstatable file.  */
 
+__BEGIN_DECLS
+
 /* Call a function on every element in a directory tree.  */
 extern int ftw __P ((__const char *__dir,
 		     int (*__func) (__const char *__file,
@@ -41,4 +43,6 @@ extern int ftw __P ((__const char *__dir,
 				    int __flag),
 		     int __descriptors));
 
+__END_DECLS
+
 #endif	/* ftw.h */
diff --git a/locale/Makefile b/locale/Makefile
index dcf469f689..7acef573d6 100644
--- a/locale/Makefile
+++ b/locale/Makefile
@@ -74,6 +74,7 @@ localepath = "$(localedir):$(i18ndir)"
 
 CPPFLAGS := -DLOCALE_PATH='$(localepath)' \
 	    -DLOCALEDIR='"$(localedir)"' \
+	    -DLOCALE_ALIAS_PATH='"$(localedir):$(i18ndir)"' \
 	    -DCHARMAP_PATH='"$(i18ndir)/charmaps"' \
 	    -DLOCSRCDIR='"$(i18ndir)/locales"' -DHAVE_CONFIG_H \
 	    -Iprograms $(CPPFLAGS)
diff --git a/locale/duplocale.c b/locale/duplocale.c
index 494c2ec829..f22c4dee95 100644
--- a/locale/duplocale.c
+++ b/locale/duplocale.c
@@ -52,4 +52,6 @@ __duplocale (__locale_t dataset)
 
   /* It's done.  */
   __libc_lock_unlock (__libc_setlocale_lock);
+
+  return result;
 }
diff --git a/locale/programs/ld-monetary.c b/locale/programs/ld-monetary.c
index ce83b18dba..cd30125a5a 100644
--- a/locale/programs/ld-monetary.c
+++ b/locale/programs/ld-monetary.c
@@ -364,9 +364,11 @@ field `%s' in category `%s' declared more than once"),			      \
 	  if (code->tok == tok_minus1)
 	    monetary->mon_grouping[monetary->mon_grouping_act++] = '\177';
 	  else if (code->val.num == 0)
-	    lr_error (lr, _("\
-values for field `%s' in category `%s' must not be zero"),
-		      "mon_grouping", "LC_MONETARY");
+	    /* A value of 0 disables grouping from here on but we must
+	       not store a NUL character since this terminates the
+	       string.  Use something different which must not be used
+	       otherwise.  */
+	    monetary->mon_grouping[monetary->mon_grouping_act++] = '\377';
 	  else if (code->val.num > 126)
 	    lr_error (lr, _("\
 values for field `%s' in category `%s' must be smaller than 127"),
diff --git a/locale/programs/ld-numeric.c b/locale/programs/ld-numeric.c
index 375635aafc..2454281a4d 100644
--- a/locale/programs/ld-numeric.c
+++ b/locale/programs/ld-numeric.c
@@ -195,6 +195,11 @@ field `%s' in category `%s' declared more than once"),			      \
 
       if (code->tok == tok_minus1)
 	numeric->grouping[numeric->grouping_act++] = '\177';
+      else if (code->val.num == 0)
+	/* A value of 0 disables grouping from here on but we must
+	   not store a NUL character since this terminates the string.
+	   Use something different which must not be used otherwise.  */
+	numeric->grouping[numeric->grouping_act++] = '\377';
       else if (code->val.num > 126)
 	lr_error (lr, _("\
 values for field `%s' in category `%s' must be smaller than 127"),
diff --git a/locale/programs/linereader.c b/locale/programs/linereader.c
index edb5a51f5c..83679b7655 100644
--- a/locale/programs/linereader.c
+++ b/locale/programs/linereader.c
@@ -108,7 +108,6 @@ void
 lr_close (struct linereader *lr)
 {
   fclose (lr->fp);
-  free ((char *) lr->fname);
   free (lr->buf);
   free (lr);
 }
diff --git a/locale/programs/locale.c b/locale/programs/locale.c
index 8587345bf2..5a68c562ef 100644
--- a/locale/programs/locale.c
+++ b/locale/programs/locale.c
@@ -1,4 +1,4 @@
-/* locale - Implementation of the locale program according to POSIX 1003.2
+/* Implementation of the locale program according to POSIX 1003.2.
    Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@gnu.ai.mit.edu>, 1995.
@@ -22,18 +22,21 @@
 # include <config.h>
 #endif
 
+#include <argp.h>
+#include <argz.h>
 #include <dirent.h>
+#include <errno.h>
 #include <error.h>
-#include <getopt.h>
 #include <langinfo.h>
 #include <libintl.h>
 #include <limits.h>
 #include <locale.h>
+#include <search.h>
 #include <stdio.h>
 #include <stdlib.h>
-#include <unistd.h>
-#include <errno.h>
 #include <string.h>
+#include <unistd.h>
+#include <sys/stat.h>
 
 #include "localeinfo.h"
 
@@ -44,16 +47,44 @@ static int show_category_name;
 /* If set print the name of the item.  */
 static int show_keyword_name;
 
-/* Long options.  */
-static const struct option long_options[] =
+/* Print names of all available locales.  */
+static int do_all;
+
+/* Print names of all available character maps.  */
+static int do_charmaps = 0;
+
+/* Name and version of program.  */
+static void print_version (FILE *stream, struct argp_state *state);
+void (*argp_program_version_hook) (FILE *, struct argp_state *) = print_version;
+
+/* Definitions of arguments for argp functions.  */
+static struct argp_option options[] =
 {
-  { "all-locales", no_argument, NULL, 'a' },
-  { "category-name", no_argument, &show_category_name, 1 },
-  { "charmaps", no_argument, NULL, 'm' },
-  { "help", no_argument, NULL, 'h' },
-  { "keyword-name", no_argument, &show_keyword_name, 1 },
-  { "version", no_argument, NULL, 'V' },
-  { NULL, 0, NULL, 0 }
+  { NULL, 0, NULL, 0, "System information:" },
+  { "all-locales", 'a', NULL, 0, "Write names of available locales" },
+  { "charmaps", 'm', NULL, 0, "Write names of available charmaps" },
+  { NULL, 0, NULL, 0, "Modify output format:" },
+  { "category-name", 'c', NULL, 0, "Write names of selected categories" },
+  { "keyword-name", 'k', NULL, 0, "Write names of selected keywords" },
+  { NULL, 0, NULL, 0, NULL }
+};
+
+/* Short description of program.  */
+static const char doc[] = "Get locale-specific information.";
+
+/* Strings for arguments in help texts.  */
+static const char args_doc[] = "NAME\n[-a|-m]";
+
+/* Prototype for option handler.  */
+static error_t parse_opt (int key, char *arg, struct argp_state *state);
+
+/* Function to print some extra text in the help message.  */
+static char *more_help (int key, const char *text, void *input);
+
+/* Data structure to communicate with argp functions.  */
+static struct argp argp =
+{
+  options, parse_opt, args_doc, doc, NULL, more_help
 };
 
 
@@ -124,7 +155,6 @@ extern void locale_special (const char *name, int show_category_name,
 			    int show_keyword_name);
 
 /* Prototypes for local functions.  */
-static void usage (int status) __attribute__ ((noreturn));
 static void write_locales (void);
 static void write_charmaps (void);
 static void show_locale_vars (void);
@@ -134,12 +164,6 @@ static void show_info (const char *name);
 int
 main (int argc, char *argv[])
 {
-  int optchar;
-  int do_all = 0;
-  int do_help = 0;
-  int do_version = 0;
-  int do_charmaps = 0;
-
   /* Set initial values for global variables.  */
   show_category_name = 0;
   show_keyword_name = 0;
@@ -152,55 +176,13 @@ main (int argc, char *argv[])
   /* Initialize the message catalog.  */
   textdomain (PACKAGE);
 
-  while ((optchar = getopt_long (argc, argv, "achkmV", long_options, NULL))
-         != -1)
-    switch (optchar)
-      {
-      case '\0':		/* Long option.  */
-	break;
-      case 'a':
-	do_all = 1;
-	break;
-      case 'c':
-	show_category_name = 1;
-	break;
-      case 'h':
-	do_help = 1;
-	break;
-      case 'k':
-	show_keyword_name = 1;
-	break;
-      case 'm':
-	do_charmaps = 1;
-	break;
-      case 'V':
-	do_version = 1;
-	break;
-      default:
-	usage (EXIT_FAILURE);
-      }
-
-  /* Version information is requested.  */
-  if (do_version)
-    {
-      printf ("locale (GNU %s) %s\n", PACKAGE, VERSION);
-      printf (_("\
-Copyright (C) %s Free Software Foundation, Inc.\n\
-This is free software; see the source for copying conditions.  There is NO\n\
-warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\
-"), "1995, 1996, 1997");
-      printf (_("Written by %s.\n"), "Ulrich Drepper");
-
-      exit (EXIT_SUCCESS);
-    }
-
-  /* Help is requested.  */
-  if (do_help)
-    usage (EXIT_SUCCESS);
+  /* Parse and process arguments.  */
+  argp_parse (&argp, argc, argv, 0, 0, NULL);
 
   /* `-a' requests the names of all available locales.  */
   if (do_all != 0)
     {
+      setlocale (LC_COLLATE, "");
       write_locales ();
       exit (EXIT_SUCCESS);
     }
@@ -233,61 +215,219 @@ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\
 }
 
 
-/* Display usage information and exit.  */
-static void
-usage (int status)
+/* Handle program arguments.  */
+static error_t
+parse_opt (int key, char *arg, struct argp_state *state)
 {
-  if (status != EXIT_SUCCESS)
-    fprintf (stderr, gettext ("Try `%s --help' for more information.\n"),
-	     __progname);
-  else
+  switch (key)
     {
-      printf (gettext ("\
-Usage: %s [OPTION]... name\n\
-Mandatory arguments to long options are mandatory for short options too.\n\
-  -h, --help            display this help and exit\n\
-  -V, --version         output version information and exit\n\
-\n\
-  -a, --all-locales     write names of available locales\n\
-  -m, --charmaps        write names of available charmaps\n\
-\n\
-  -c, --category-name   write names of selected categories\n\
-  -k, --keyword-name    write names of selected keywords\n"),
-	      __progname);
-      fputs (gettext ("\
-Report bugs using the `glibcbug' script to <bugs@gnu.ai.mit.edu>.\n"),
-	     stdout);
+    case 'a':
+      do_all = 1;
+      break;
+    case 'c':
+      show_category_name = 1;
+      break;
+    case 'm':
+      do_charmaps = 1;
+      break;
+    case 'k':
+      show_keyword_name = 1;
+      break;
+    default:
+      return ARGP_ERR_UNKNOWN;
     }
+  return 0;
+}
+
+
+static char *
+more_help (int key, const char *text, void *input)
+{
+  switch (key)
+    {
+    case ARGP_KEY_HELP_EXTRA:
+      /* We print some extra information.  */
+      return strdup (gettext ("\
+Report bugs using the `glibcbug' script to <bugs@gnu.ai.mit.edu>.\n"));
+    default:
+      break;
+    }
+  return (char *) text;
+}
+
+/* Print the version information.  */
+static void
+print_version (FILE *stream, struct argp_state *state)
+{
+  fprintf (stream, "locale (GNU %s) %s\n", PACKAGE, VERSION);
+  fprintf (stream, gettext ("\
+Copyright (C) %s Free Software Foundation, Inc.\n\
+This is free software; see the source for copying conditions.  There is NO\n\
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\
+"), "1995, 1996, 1997");
+  fprintf (stream, gettext ("Written by %s.\n"), "Ulrich Drepper");
+}
 
-  exit (status);
+
+/* Simple action function which prints arguments as strings.  */
+static void
+print_names (const void *nodep, VISIT value, int level)
+{
+  if (value == postorder || value == leaf)
+    puts (*(char **) nodep);
 }
 
 
-/* Write the names of all available locales to stdout.  */
+/* Write the names of all available locales to stdout.  We have some
+   sources of the information: the contents of the locale directory
+   and the locale.alias file.  To avoid duplicates and print the
+   result is a reasonable order we put all entries is a search tree
+   and print them afterwards.  */
 static void
 write_locales (void)
 {
+  void *all_data = NULL;
   DIR *dir;
   struct dirent *dirent;
+  char *alias_path;
+  size_t alias_path_len;
+  char *entry;
 
-  /* `POSIX' locale is always available (POSIX.2 4.34.3).  */
-  puts ("POSIX");
+#define PUT(name) tsearch ((name), &all_data, \
+			   (int (*) (const void *, const void *)) strcoll)
 
-  dir = opendir (LOCALE_PATH);
+  dir = opendir (LOCALEDIR);
   if (dir == NULL)
     {
       error (1, errno, gettext ("cannot read locale directory `%s'"),
-	     LOCALE_PATH);
+	     LOCALEDIR);
       return;
     }
 
+  /* `POSIX' locale is always available (POSIX.2 4.34.3).  */
+  PUT ("POSIX");
+  /* And so is the "C" locale.  */
+  PUT ("C");
+
   /* Now we can look for all files in the directory.  */
   while ((dirent = readdir (dir)) != NULL)
     if (strcmp (dirent->d_name, ".") != 0
 	&& strcmp (dirent->d_name, "..") != 0)
-      puts (dirent->d_name);
+      {
+	mode_t mode;
+#ifdef _DIRENT_HAVE_D_TYPE
+	if (dirent->d_type != DT_UNKNOWN)
+	  mode = DTTOIF (dirent->d_type);
+	else
+#endif
+	  {
+	    struct stat st;
+	    char buf[sizeof (LOCALEDIR) + strlen (dirent->d_name) + 1];
+
+	    stpcpy (stpcpy (stpcpy (buf, LOCALEDIR), "/"), dirent->d_name);
+
+	    if (stat (buf, &st) < 0)
+	      continue;
+	    mode = st.st_mode;
+	  }
+
+	if (S_ISDIR (mode))
+	  PUT (strdup (dirent->d_name));
+      }
 
   closedir (dir);
+
+  /* Now read the locale.alias files.  */
+  if (argz_create_sep (LOCALE_ALIAS_PATH, ':', &alias_path, &alias_path_len))
+    error (1, errno, gettext ("while preparing output"));
+
+  entry = NULL;
+  while ((entry = argz_next (alias_path, alias_path_len, entry)))
+    {
+      static const char aliasfile[] = "/locale.alias";
+      FILE *fp;
+      char full_name[strlen (entry) + sizeof aliasfile];
+
+      stpcpy (stpcpy (full_name, entry), aliasfile);
+      fp = fopen (full_name, "r");
+      if (fp == NULL)
+	/* Ignore non-existing files.  */
+	continue;
+
+      while (! feof (fp))
+	{
+	  /* It is a reasonable approach to use a fix buffer here
+	     because
+	     a) we are only interested in the first two fields
+	     b) these fields must be usable as file names and so must
+	        not be that long  */
+	  char buf[BUFSIZ];
+	  char *alias;
+	  char *value;
+	  char *cp;
+
+	  if (fgets (buf, BUFSIZ, fp) == NULL)
+	    /* EOF reached.  */
+	    break;
+
+	  cp = buf;
+	  /* Ignore leading white space.  */
+	  while (isspace (cp[0]))
+	    ++cp;
+
+	  /* A leading '#' signals a comment line.  */
+	  if (cp[0] != '\0' && cp[0] != '#')
+	    {
+	      alias = cp++;
+	      while (cp[0] != '\0' && !isspace (cp[0]))
+		++cp;
+	      /* Terminate alias name.  */
+	      if (cp[0] != '\0')
+		*cp++ = '\0';
+
+	      /* Now look for the beginning of the value.  */
+	      while (isspace (cp[0]))
+		++cp;
+
+	      if (cp[0] != '\0')
+		{
+		  value = cp++;
+		  while (cp[0] != '\0' && !isspace (cp[0]))
+		    ++cp;
+		  /* Terminate value.  */
+		  if (cp[0] == '\n')
+		    {
+		      /* This has to be done to make the following
+			 test for the end of line possible.  We are
+			 looking for the terminating '\n' which do not
+			 overwrite here.  */
+		      *cp++ = '\0';
+		      *cp = '\n';
+		    }
+		  else if (cp[0] != '\0')
+		    *cp++ = '\0';
+
+		  /* Add the alias.  */
+		  PUT (strdup (alias));
+		}
+	    }
+
+	  /* Possibly not the whole line fits into the buffer.
+	     Ignore the rest of the line.  */
+	  while (strchr (cp, '\n') == NULL)
+	    {
+	      cp = buf;
+	      if (fgets (buf, BUFSIZ, fp) == NULL)
+		/* Make sure the inner loop will be left.  The outer
+		   loop will exit at the `feof' test.  */
+		*cp = '\n';
+	    }
+	}
+
+      fclose (fp);
+    }
+
+  twalk (all_data, print_names);
 }
 
 
@@ -295,6 +435,7 @@ write_locales (void)
 static void
 write_charmaps (void)
 {
+  void *all_data = NULL;
   DIR *dir;
   struct dirent *dirent;
 
@@ -310,9 +451,31 @@ write_charmaps (void)
   while ((dirent = readdir (dir)) != NULL)
     if (strcmp (dirent->d_name, ".") != 0
 	&& strcmp (dirent->d_name, "..") != 0)
-      puts (dirent->d_name);
+      {
+	mode_t mode;
+#ifdef _DIRENT_HAVE_D_TYPE
+	if (dirent->d_type != DT_UNKNOWN)
+	  mode = DTTOIF (dirent->d_type);
+	else
+#endif
+	  {
+	    struct stat st;
+	    char buf[sizeof (CHARMAP_PATH) + strlen (dirent->d_name) + 1];
+
+	    stpcpy (stpcpy (stpcpy (buf, CHARMAP_PATH), "/"), dirent->d_name);
+
+	    if (stat (buf, &st) < 0)
+	      continue;
+	    mode = st.st_mode;
+	  }
+
+	if (S_ISREG (mode))
+	  PUT (strdup (dirent->d_name));
+      }
 
   closedir (dir);
+
+  twalk (all_data, print_names);
 }
 
 
diff --git a/locale/setlocale.c b/locale/setlocale.c
index 368027f743..12e6569384 100644
--- a/locale/setlocale.c
+++ b/locale/setlocale.c
@@ -314,28 +314,19 @@ setlocale (int category, const char *locale)
 
       /* Load the new data for each category.  */
       while (category-- > 0)
-	/* Only actually load the data if anything will use it.  */
-	if (_nl_current[category] != NULL)
-	  {
-	    newdata[category] = _nl_find_locale (locale_path, locale_path_len,
-						 category,
-						 &newnames[category]);
-
-	    if (newdata[category] == NULL)
-	      break;
-
-	    /* We must not simply free a global locale since we have
-	       no control over the usage.  So we mark it as
-	       un-deletable.  */
+	{
+	  newdata[category] = _nl_find_locale (locale_path, locale_path_len,
+					       category,
+					       &newnames[category]);
+
+	  if (newdata[category] == NULL)
+	    break;
+
+	  /* We must not simply free a global locale since we have no
+	     control over the usage.  So we mark it as un-deletable.  */
+	  if (newdata[category]->usage_count != MAX_USAGE_COUNT)
 	    newdata[category]->usage_count = MAX_USAGE_COUNT;
-	  }
-	else
-	  {
-	    /* The data is never used; just change the name.  */
-	    newnames[category] = clever_copy (newnames[category]);
-	    if (newnames[category] == NULL)
-	      break;
-	  }
+	}
 
       /* Create new composite name.  */
       if (category >= 0
diff --git a/login/utmp.h b/login/utmp.h
index 6fd89ddc28..2e87070537 100644
--- a/login/utmp.h
+++ b/login/utmp.h
@@ -25,6 +25,8 @@
 #include <sys/types.h>
 
 
+__BEGIN_DECLS
+
 /* Get system dependent values and data structures.  */
 #include <utmpbits.h>
 
diff --git a/malloc/obstack.h b/malloc/obstack.h
index 0e7eb09054..b67f0545f1 100644
--- a/malloc/obstack.h
+++ b/malloc/obstack.h
@@ -106,6 +106,10 @@ Summary:
 
 #ifndef __OBSTACK_H__
 #define __OBSTACK_H__
+
+#ifdef __cpluscplus
+extern "C" {
+#endif
 
 /* We use subtraction of (char *) 0 instead of casting to int
    because on word-addressable machines a simple cast to int
@@ -578,4 +582,8 @@ __extension__								\
 
 #endif /* not __GNUC__ or not __STDC__ */
 
+#ifdef __cplusplus
+}	/* C++ */
+#endif
+
 #endif /* not __OBSTACK_H__ */
diff --git a/misc/libgen.h b/misc/libgen.h
index be8258e72a..2c5d642e15 100644
--- a/misc/libgen.h
+++ b/misc/libgen.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 1996 Free Software Foundation, Inc.
+/* Copyright (C) 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
@@ -21,10 +21,14 @@
 #define _LIBGEN_H	1
 #include <sys/cdefs.h>
 
+__BEGIN_DECLS
+
 /* Return directory part of PATH or "." if none is available.  */
 extern char *dirname __P ((char *__path));
 
 /* Return filename part of PATH.  */
 extern char *basename __P ((__const char *__path));
 
+__END_DECLS
+
 #endif /* libgen.h */
diff --git a/misc/search.h b/misc/search.h
index d0097429e9..8ce33515d9 100644
--- a/misc/search.h
+++ b/misc/search.h
@@ -1,5 +1,5 @@
-/* search.h -- declarations for System V style searching functions.
-   Copyright (C) 1995, 1996 Free Software Foundation, Inc.
+/* Declarations for System V style searching functions.
+   Copyright (C) 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
@@ -124,8 +124,8 @@ extern void *__tdelete __P ((__const void * __key, void ** __rootp,
 #ifndef __ACTION_FN_T
 #define __ACTION_FN_T
 typedef void (*__action_fn_t) __P ((__const void *__nodep,
-				    __const VISIT __value,
-				    __const int __level));
+				    VISIT __value,
+				    int __level));
 #endif
 
 extern void twalk __P ((__const void * __root, __action_fn_t action));
diff --git a/misc/sys/syslog.h b/misc/sys/syslog.h
index 241a74d52c..6da3a3b4c3 100644
--- a/misc/sys/syslog.h
+++ b/misc/sys/syslog.h
@@ -67,21 +67,22 @@ typedef struct _code {
 	int	c_val;
 } CODE;
 
-CODE prioritynames[] = {
-	"alert",	LOG_ALERT,
-	"crit",		LOG_CRIT,
-	"debug",	LOG_DEBUG,
-	"emerg",	LOG_EMERG,
-	"err",		LOG_ERR,
-	"error",	LOG_ERR,		/* DEPRECATED */
-	"info",		LOG_INFO,
-	"none",		INTERNAL_NOPRI,		/* INTERNAL */
-	"notice",	LOG_NOTICE,
-	"panic", 	LOG_EMERG,		/* DEPRECATED */
-	"warn",		LOG_WARNING,		/* DEPRECATED */
-	"warning",	LOG_WARNING,
-	NULL,		-1,
-};
+CODE prioritynames[] =
+  {
+    { "alert", LOG_ALERT },
+    { "crit", LOG_CRIT },
+    { "debug", LOG_DEBUG },
+    { "emerg", LOG_EMERG },
+    { "err", LOG_ERR },
+    { "error", LOG_ERR },		/* DEPRECATED */
+    { "info", LOG_INFO },
+    { "none", INTERNAL_NOPRI },		/* INTERNAL */
+    { "notice", LOG_NOTICE },
+    { "panic", LOG_EMERG },		/* DEPRECATED */
+    { "warn", LOG_WARNING },		/* DEPRECATED */
+    { "warning", LOG_WARNING },
+    { NULL, -1 }
+  };
 #endif
 
 /* facility codes */
@@ -114,31 +115,32 @@ CODE prioritynames[] = {
 #define	LOG_FAC(p)	(((p) & LOG_FACMASK) >> 3)
 
 #ifdef SYSLOG_NAMES
-CODE facilitynames[] = {
-	"auth",		LOG_AUTH,
-	"authpriv",	LOG_AUTHPRIV,
-	"cron", 	LOG_CRON,
-	"daemon",	LOG_DAEMON,
-	"ftp",		LOG_FTP,
-	"kern",		LOG_KERN,
-	"lpr",		LOG_LPR,
-	"mail",		LOG_MAIL,
-	"mark", 	INTERNAL_MARK,		/* INTERNAL */
-	"news",		LOG_NEWS,
-	"security",	LOG_AUTH,		/* DEPRECATED */
-	"syslog",	LOG_SYSLOG,
-	"user",		LOG_USER,
-	"uucp",		LOG_UUCP,
-	"local0",	LOG_LOCAL0,
-	"local1",	LOG_LOCAL1,
-	"local2",	LOG_LOCAL2,
-	"local3",	LOG_LOCAL3,
-	"local4",	LOG_LOCAL4,
-	"local5",	LOG_LOCAL5,
-	"local6",	LOG_LOCAL6,
-	"local7",	LOG_LOCAL7,
-	NULL,		-1,
-};
+CODE facilitynames[] =
+  {
+    { "auth", LOG_AUTH },
+    { "authpriv", LOG_AUTHPRIV },
+    { "cron", LOG_CRON },
+    { "daemon", LOG_DAEMON },
+    { "ftp", LOG_FTP },
+    { "kern", LOG_KERN },
+    { "lpr", LOG_LPR },
+    { "mail", LOG_MAIL },
+    { "mark", INTERNAL_MARK },		/* INTERNAL */
+    { "news", LOG_NEWS },
+    { "security", LOG_AUTH },		/* DEPRECATED */
+    { "syslog", LOG_SYSLOG },
+    { "user", LOG_USER },
+    { "uucp", LOG_UUCP },
+    { "local0", LOG_LOCAL0 },
+    { "local1", LOG_LOCAL1 },
+    { "local2", LOG_LOCAL2 },
+    { "local3", LOG_LOCAL3 },
+    { "local4", LOG_LOCAL4 },
+    { "local5", LOG_LOCAL5 },
+    { "local6", LOG_LOCAL6 },
+    { "local7", LOG_LOCAL7 },
+    { NULL, -1 }
+  };
 #endif
 
 #ifdef KERNEL
@@ -186,11 +188,23 @@ CODE facilitynames[] = {
 #include <sys/cdefs.h>
 
 __BEGIN_DECLS
-void	closelog __P((void));
-void	openlog __P((const char *, int, int));
-int	setlogmask __P((int));
-void	syslog __P((int, const char *, ...));
-void	vsyslog __P((int, const char *, _BSD_VA_LIST_));
+
+/* Close desriptor used to write to system logger.  */
+extern void closelog __P ((void));
+
+/* Open connection to system logger.  */
+extern void openlog __P ((__const char *__ident, int __option,
+			  int __facility));
+
+/* Set the log mask level.  */
+extern int setlogmask __P ((int __mask));
+
+/* Generate a log message using FMT string and option arguments.  */
+extern void syslog __P ((int __pri, __const char *__fmt, ...));
+
+/* Generate a log message using FMT and using arguments pointed to by AP.  */
+extern void vsyslog __P ((int __pri, __const char *__fmt, _BSD_VA_LIST_ __ap));
+
 __END_DECLS
 
 #endif /* !KERNEL */
diff --git a/nis/nss_nis/nis-ethers.c b/nis/nss_nis/nis-ethers.c
index 25f77f5f82..d257cd7e4b 100644
--- a/nis/nss_nis/nis-ethers.c
+++ b/nis/nss_nis/nis-ethers.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1996 Free Software Foundation, Inc.
+/* Copyright (C) 1996, 1997 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Thorsten Kukuk <kukuk@vt.uni-paderborn.de>, 1996.
 
@@ -156,8 +156,8 @@ _nss_nis_getetherent_r (struct ether *result, char *buffer, size_t buflen)
 }
 
 enum nss_status
-_nss_nis_getethernam_r (const char *name, struct ether *eth,
-			char *buffer, size_t buflen)
+_nss_nis_gethostton_r (const char *name, struct ether *eth,
+		       char *buffer, size_t buflen)
 {
   struct parser_data *data = (void *) buffer;
   enum nss_status retval;
@@ -210,8 +210,8 @@ _nss_nis_getethernam_r (const char *name, struct ether *eth,
 }
 
 enum nss_status
-_nss_nis_getetherbyaddr_r (struct ether_addr *addr, struct ether *eth,
-			   char *buffer, size_t buflen)
+_nss_nis_getntohost_r (struct ether_addr *addr, struct ether *eth,
+		       char *buffer, size_t buflen)
 {
   struct parser_data *data = (void *) buffer;
   enum nss_status retval;
diff --git a/nss/digits_dots.c b/nss/digits_dots.c
index b86f66cf4d..c953fc6ec6 100644
--- a/nss/digits_dots.c
+++ b/nss/digits_dots.c
@@ -236,7 +236,10 @@
 	    {
 	      if (!*cp)
 		{
-		  if (*--cp == '.') break;
+		  if (*--cp == '.')
+		    break;
+		  if (!strchr (name, ':'))
+		    break;
 
 		  /* All-IPv6-legal, no dot at the end. Fake up a
 		     hostent as if we'd actually done a lookup.  */
diff --git a/nss/nss.h b/nss/nss.h
index 8cf2565275..b36c53d05c 100644
--- a/nss/nss.h
+++ b/nss/nss.h
@@ -24,10 +24,6 @@
 #define _NSS_H	1
 #include <features.h>
 
-/* Revision number of NSS interface (must be a string).  */
-#define NSS_SHLIB_REVISION __nss_shlib_revision
-extern const char *const __nss_shlib_revision;
-
 
 __BEGIN_DECLS
 
diff --git a/nss/nsswitch.c b/nss/nsswitch.c
index 201a2bccfe..77fc4f0916 100644
--- a/nss/nsswitch.c
+++ b/nss/nsswitch.c
@@ -65,8 +65,7 @@ __libc_lock_define_initialized (static, lock)
 
 
 /* String with revision number of the shared object files.  */
-const char *const __nss_shlib_revision = LIBNSS_FILES_SO + 15;
-
+static const char *const __nss_shlib_revision = LIBNSS_FILES_SO + 15;
 
 /* The root of the whole data base.  */
 static name_database *service_table;
@@ -332,7 +331,7 @@ nss_lookup_function (service_user *ni, const char *fct_name)
 	    {
 	      /* Load the shared library.  */
 	      size_t shlen = (7 + strlen (ni->library->name) + 3
-			      + strlen (NSS_SHLIB_REVISION) + 1);
+			      + strlen (__nss_shlib_revision) + 1);
 	      char shlib_name[shlen];
 
 	      void do_open (void)
@@ -345,7 +344,7 @@ nss_lookup_function (service_user *ni, const char *fct_name)
 	      __stpcpy (__stpcpy (__stpcpy (__stpcpy (shlib_name, "libnss_"),
 					    ni->library->name),
 				  ".so"),
-			NSS_SHLIB_REVISION);
+			__nss_shlib_revision);
 
 	      if (nss_dlerror_run (do_open) != 0)
 		/* Failed to load the library.  */
diff --git a/posix/Makefile b/posix/Makefile
index 565561c57a..d4ae754702 100644
--- a/posix/Makefile
+++ b/posix/Makefile
@@ -46,7 +46,7 @@ routines :=								      \
 	getopt getopt1 getopt_init					      \
 	sched_setp sched_getp sched_sets sched_gets sched_yield sched_primax  \
 	sched_primin sched_rr_gi					      \
-	getaddrinfo
+	getaddrinfo gai_strerror
 
 aux		:= init-posix environ
 tests		:= tstgetopt testfnm
diff --git a/posix/regex.h b/posix/regex.h
index 565d24e09d..80f9c6d64a 100644
--- a/posix/regex.h
+++ b/posix/regex.h
@@ -1,6 +1,6 @@
 /* Definitions for data structures and routines for the regular
    expression library, version 0.12.
-   Copyright (C) 1985,89,90,91,92,93,95,96 Free Software Foundation, Inc.
+   Copyright (C) 1985,89,90,91,92,93,95,96,97 Free Software Foundation, Inc.
 
    This file is part of the GNU C Library.  Its master source is NOT part of
    the C library, however.  The master source lives in /gd/gnu/lib.
@@ -23,6 +23,11 @@
 #ifndef __REGEXP_LIBRARY_H__
 #define __REGEXP_LIBRARY_H__
 
+/* Allow the use in C++ code.  */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 /* POSIX says that <sys/types.h> must be included (by the caller) before
    <regex.h>.  */
 
@@ -32,7 +37,6 @@
 #include <stddef.h>
 #endif
 
-
 /* The following bits are used to determine the regexp syntax we
    recognize.  The set/not-set meanings are chosen so that Emacs syntax
    remains the value 0.  The bits are given in alphabetical order, and
@@ -487,6 +491,11 @@ extern size_t regerror
              size_t errbuf_size));
 extern void regfree _RE_ARGS ((regex_t *preg));
 
+
+#ifdef __cplusplus
+}
+#endif	/* C++ */
+
 #endif /* not __REGEXP_LIBRARY_H__ */
 
 /*
diff --git a/resolv/gethnamaddr.c b/resolv/gethnamaddr.c
index 424a6690ee..114875b910 100644
--- a/resolv/gethnamaddr.c
+++ b/resolv/gethnamaddr.c
@@ -513,6 +513,8 @@ gethostbyname2(name, af)
 			if (!*cp) {
 				if (*--cp == '.')
 					break;
+				if (!strchr(name, ':'))
+					break;
 				/*
 				 * All-IPv6-legal, no dot at the end.
 				 * Fake up a hostent as if we'd actually
diff --git a/resolv/netdb.h b/resolv/netdb.h
index b60f923229..41faa75e36 100644
--- a/resolv/netdb.h
+++ b/resolv/netdb.h
@@ -396,6 +396,14 @@ struct addrinfo
 #define	EAI_MEMORY	-10	/* Memory allocation failure.  */
 #define	EAI_SYSTEM	-11	/* System error returned in `errno'.  */
 
+#define NI_MAXHOST      1025
+#define NI_MAXSERV      32
+
+#define NI_NUMERICHOST 1
+#define NI_NUMERICSERV 2
+#define NI_NOFQDN 4
+#define NI_NAMEREQD 8
+#define NI_DGRAM 16
 
 /* Translate name of a service location and/or a service name to set of
    socket addresses.  */
diff --git a/shadow/sgetspent_r.c b/shadow/sgetspent_r.c
index ba2e8186bc..8678ac816a 100644
--- a/shadow/sgetspent_r.c
+++ b/shadow/sgetspent_r.c
@@ -51,9 +51,12 @@ LINE_PARSER
  else
    {
      STRING_FIELD (result->sp_pwdp, ISCOLON, 0);
-     INT_FIELD (result->sp_lstchg, ISCOLON, 0, 10, (long int));
-     INT_FIELD (result->sp_min, ISCOLON, 0, 10, (long int));
-     INT_FIELD (result->sp_max, ISCOLON, 0, 10, (long int));
+     INT_FIELD_MAYBE_NULL (result->sp_lstchg, ISCOLON, 0, 10, (long int),
+			   (long int) -1);
+     INT_FIELD_MAYBE_NULL (result->sp_min, ISCOLON, 0, 10, (long int),
+			   (long int) -1);
+     INT_FIELD_MAYBE_NULL (result->sp_max, ISCOLON, 0, 10, (long int),
+			   (long int -1);
      while (isspace (*line))
        ++line;
      if (*line == '\0')
diff --git a/stdio-common/bug10.c b/stdio-common/bug10.c
index 3e15526a43..c4f328d4cb 100644
--- a/stdio-common/bug10.c
+++ b/stdio-common/bug10.c
@@ -1,7 +1,7 @@
 #include <stdio.h>
 
 int
-main (int arc, char *argv)
+main (int arc, char *argv[])
 {
   int n, res;
   unsigned int val;
diff --git a/stdlib/qsort.c b/stdlib/qsort.c
index 72d6b244df..498230b38f 100644
--- a/stdlib/qsort.c
+++ b/stdlib/qsort.c
@@ -83,7 +83,7 @@ _quicksort (pbase, total_elems, size, cmp)
      void *const pbase;
      size_t total_elems;
      size_t size;
-     int (*cmp) __P ((const void *, const void *));
+     __compar_fn_t cmp;
 {
   register char *base_ptr = (char *) pbase;
 
diff --git a/stdlib/testrand.c b/stdlib/testrand.c
index 05835b2ba8..b5c186462d 100644
--- a/stdlib/testrand.c
+++ b/stdlib/testrand.c
@@ -20,7 +20,7 @@
 #include <stdio.h>
 
 int
-main ()
+main (void)
 {
   int i1, i2;
   int j1, j2;
diff --git a/string/test-ffs.c b/string/test-ffs.c
index f691d7f22d..9618408ae2 100644
--- a/string/test-ffs.c
+++ b/string/test-ffs.c
@@ -23,9 +23,7 @@
 #include <string.h>
 
 int
-main (argc, argv)
-     int argc;
-     char **argv;
+main (void)
 {
   int failures = 0;
   int i;
diff --git a/string/testcopy.c b/string/testcopy.c
index b1c491e62c..030b229794 100644
--- a/string/testcopy.c
+++ b/string/testcopy.c
@@ -23,9 +23,7 @@
 #include <malloc.h>
 
 int
-main (argc, argv)
-     int argc;
-     char **argv;
+main (void)
 {
   char *mem, *memp;
   char *rand_mem;
diff --git a/sunrpc/clnt_simp.c b/sunrpc/clnt_simp.c
index dd2ae75f1e..42ab1a28f8 100644
--- a/sunrpc/clnt_simp.c
+++ b/sunrpc/clnt_simp.c
@@ -118,7 +118,8 @@ callrpc(host, prognum, versnum, procnum, inproc, in, outproc, out)
 		crp->valid = 1;
 		crp->oldprognum = prognum;
 		crp->oldversnum = versnum;
-		(void) strcpy(crp->oldhost, host);
+		(void) strncpy(crp->oldhost, host, 255);
+		crp->oldhost[256] = '\0';
 	}
 	tottimeout.tv_sec = 25;
 	tottimeout.tv_usec = 0;
diff --git a/sunrpc/rpc/auth_des.h b/sunrpc/rpc/auth_des.h
index 097eb68771..8c2f794691 100644
--- a/sunrpc/rpc/auth_des.h
+++ b/sunrpc/rpc/auth_des.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 1996 Free Software Foundation, Inc.
+/* Copyright (C) 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
@@ -21,6 +21,8 @@
 #define _RPC_AUTH_DES_H	1
 #include <sys/cdefs.h>
 
+__BEGIN_DECLS
+
 /* This is no complete version of this header.  More definitions with
    the real authentication stuff will come in 1997.  For now we only
    need to define the function for handling public keys.  */
@@ -39,4 +41,6 @@ extern int getpublickey __P ((__const char *__name, char *__key));
 extern int getsecretkey __P ((__const char *__name, char *__key,
 			      __const char *__passwd));
 
+__END_DECLS
+
 #endif /* rpc/auth_des.h */
diff --git a/sunrpc/rpc/pmap_rmt.h b/sunrpc/rpc/pmap_rmt.h
index f5d4af110b..2e1af7e3d0 100644
--- a/sunrpc/rpc/pmap_rmt.h
+++ b/sunrpc/rpc/pmap_rmt.h
@@ -41,13 +41,15 @@
 #include <features.h>
 
 
+__BEGIN_DECLS
+
 struct rmtcallargs {
 	u_long prog, vers, proc, arglen;
 	caddr_t args_ptr;
 	xdrproc_t xdr_args;
 };
 
-bool_t xdr_rmtcall_args __P ((XDR *__xdrs, struct rmtcallargs *__crp));
+extern bool_t xdr_rmtcall_args __P ((XDR *__xdrs, struct rmtcallargs *__crp));
 
 struct rmtcallres {
 	u_long *port_ptr;
@@ -56,7 +58,8 @@ struct rmtcallres {
 	xdrproc_t xdr_results;
 };
 
-bool_t xdr_rmtcallres __P ((XDR *__xdrs, struct rmtcallres *__crp));
+extern bool_t xdr_rmtcallres __P ((XDR *__xdrs, struct rmtcallres *__crp));
 
+__END_DECLS
 
 #endif /* rpc/pmap_rmt.h */
diff --git a/sunrpc/rpc/rpc_msg.h b/sunrpc/rpc/rpc_msg.h
index 48ae1f988d..8f6b6a9da4 100644
--- a/sunrpc/rpc/rpc_msg.h
+++ b/sunrpc/rpc/rpc_msg.h
@@ -33,6 +33,8 @@
 #define _RPC_MSG_H 1
 #include <sys/cdefs.h>
 
+#include <rpc/clnt.h>
+
 /*
  * rpc_msg.h
  * rpc message definition
diff --git a/sysdeps/alpha/dl-machine.h b/sysdeps/alpha/dl-machine.h
index 316f717e01..fc9f9712cb 100644
--- a/sysdeps/alpha/dl-machine.h
+++ b/sysdeps/alpha/dl-machine.h
@@ -325,7 +325,7 @@ static inline void
 elf_machine_rela (struct link_map *map,
 		  const Elf64_Rela *reloc,
 		  const Elf64_Sym *sym,
-		  const hash_name_pair *version)
+		  const struct r_found_version *version)
 {
   Elf64_Addr * const reloc_addr = (void *)(map->l_addr + reloc->r_offset);
   unsigned long const r_info = ELF64_R_TYPE (reloc->r_info);
diff --git a/inet/netinet/ip.h b/sysdeps/generic/netinet/ip.h
index 191ac8e9c8..a119c629f7 100644
--- a/inet/netinet/ip.h
+++ b/sysdeps/generic/netinet/ip.h
@@ -33,6 +33,9 @@
  *	@(#)ip.h	8.1 (Berkeley) 6/10/93
  */
 
+#ifndef _NETINET_IP_H
+#define _NETINET_IP_H
+
 #include <gnu/types.h>
 #include <endian.h>
 #include <netinet/in.h>
@@ -165,3 +168,5 @@ struct	ip_timestamp {
 #define	IPTTLDEC	1		/* subtracted when forwarding */
 
 #define	IP_MSS		576		/* default maximum segment size */
+
+#endif /* netinet/ip.h. */
diff --git a/inet/netinet/tcp.h b/sysdeps/generic/netinet/tcp.h
index e5011b053c..e5011b053c 100644
--- a/inet/netinet/tcp.h
+++ b/sysdeps/generic/netinet/tcp.h
diff --git a/sysdeps/i386/dl-machine.h b/sysdeps/i386/dl-machine.h
index 570e0d9066..90ec6ce9f9 100644
--- a/sysdeps/i386/dl-machine.h
+++ b/sysdeps/i386/dl-machine.h
@@ -204,7 +204,7 @@ _dl_start_user:\n\
 
 static inline void
 elf_machine_rel (struct link_map *map, const Elf32_Rel *reloc,
-		 const Elf32_Sym *sym, const hash_name_pair *version)
+		 const Elf32_Sym *sym, const struct r_found_version *version)
 {
   Elf32_Addr *const reloc_addr = (void *) (map->l_addr + reloc->r_offset);
   Elf32_Addr loadbase;
diff --git a/sysdeps/m68k/dl-machine.h b/sysdeps/m68k/dl-machine.h
index 95a8342574..0c9b6acb6d 100644
--- a/sysdeps/m68k/dl-machine.h
+++ b/sysdeps/m68k/dl-machine.h
@@ -200,7 +200,7 @@ _dl_start_user:
 
 static inline void
 elf_machine_rela (struct link_map *map, const Elf32_Rela *reloc,
-		  const Elf32_Sym *sym, const hash_name_pair *version)
+		  const Elf32_Sym *sym, const struct r_found_version *version)
 {
   Elf32_Addr *const reloc_addr = (void *) (map->l_addr + reloc->r_offset);
   Elf32_Addr loadbase;
diff --git a/sysdeps/mips/dl-machine.h b/sysdeps/mips/dl-machine.h
index a4a02bfd97..39a1cc8be6 100644
--- a/sysdeps/mips/dl-machine.h
+++ b/sysdeps/mips/dl-machine.h
@@ -423,7 +423,7 @@ _dl_start_user:\n\
 
 static inline void
 elf_machine_rel (struct link_map *map, const ElfW(Rel) *reloc,
-		 const ElfW(Sym) *sym, const hash_name_pair *version)
+		 const ElfW(Sym) *sym, const struct r_found_version *version)
 {
   ElfW(Addr) *const reloc_addr = (void *) (map->l_addr + reloc->r_offset);
   ElfW(Addr) loadbase, undo;
diff --git a/sysdeps/posix/gai_strerror.c b/sysdeps/posix/gai_strerror.c
new file mode 100644
index 0000000000..b89a1f6889
--- /dev/null
+++ b/sysdeps/posix/gai_strerror.c
@@ -0,0 +1,52 @@
+/* Copyright (C) 1997 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Philip Blundell <pjb27@cam.ac.uk>, 1997.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public License as
+   published by the Free Software Foundation; either version 2 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
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If not,
+   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#include <stdio.h>
+#include <netdb.h>
+
+static struct
+  {
+    int code;
+    const char *msg;
+  }
+values[] =
+  {
+    { EAI_ADDRFAMILY, N_("Address family for hostname not supported") },
+    { EAI_AGAIN, N_("Temporary failure in name resolution") },
+    { EAI_BADFLAGS, N_("Bad value for ai_flags") },
+    { EAI_FAIL, N_("Non-recoverable failure in name resolution") },
+    { EAI_FAMILY, N_("ai_family not supported") },
+    { EAI_MEMORY, N_("Memory allocation failure") },
+    { EAI_NODATA, N_("No address associated with hostname") },
+    { EAI_NONAME, N_("Name or service not known") },
+    { EAI_SERVICE, N_("Servname not supported for ai_socktype") },
+    { EAI_SOCKTYPE, N_("ai_socktype not supported") },
+    { EAI_SYSTEM, N_("System error") }
+  };
+
+char *
+gai_strerror (int code)
+{
+  int i;
+  for (i = 0; i < sizeof (values) / sizeof (values[0]); ++i)
+    if (values[i].code == code)
+      return (char *) values[i].msg;
+
+  return (char *) _("Unknown error");
+}
diff --git a/sysdeps/posix/getaddrinfo.c b/sysdeps/posix/getaddrinfo.c
index 90af24fb61..042e0a5ef8 100644
--- a/sysdeps/posix/getaddrinfo.c
+++ b/sysdeps/posix/getaddrinfo.c
@@ -42,21 +42,43 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 /* This software is Copyright 1996 by Craig Metz, All Rights Reserved.  */
 
+/* getaddrinfo() v1.13 */
+
+/* To do what POSIX says, even when it's broken: */
+/* #define BROKEN_LIKE_POSIX 1 */
+#define LOCAL 1
+#define INET6 1
+#define HOSTTABLE 0
+#define RESOLVER 1
+
 #include <sys/types.h>
-#include <sys/socket.h>
 #include <stdlib.h>
+#include <unistd.h>
+#include <sys/socket.h>
+#if LOCAL
+#include <stdio.h>
+#include <string.h>
+#include <sys/utsname.h>
+#include <sys/un.h>
+#endif /* LOCAL */
 #include <netinet/in.h>
-#ifdef INET6
-#include <netinet6/in6.h>
-#endif /* INET6 */
 #include <netdb.h>
-#include <arpa/inet.h>
-#include <string.h>
+#include <errno.h>
+
+#ifndef AF_LOCAL
+#define AF_LOCAL AF_UNIX
+#endif /* AF_LOCAL */
+#ifndef PF_LOCAL
+#define PF_LOCAL PF_UNIX
+#endif /* PF_LOCAL */
+#ifndef UNIX_PATH_MAX
+#define UNIX_PATH_MAX 108
+#endif /* UNIX_PATH_MAX */
 
 #define GAIH_OKIFUNSPEC 0x0100
 #define GAIH_EAI        ~(GAIH_OKIFUNSPEC)
 
-#ifdef HOSTTABLE
+#if HOSTTABLE
 struct hostent *_hostname2addr_hosts(const char *name, int);
 struct hostent *_addr2hostname_hosts(const char *name, int, int);
 #endif /* HOSTTABLE */
@@ -66,7 +88,7 @@ static struct addrinfo nullreq =
 
 struct gaih_service {
   char *name;
-  unsigned long num;
+  int num;
 };
 
 struct gaih_servtuple {
@@ -86,18 +108,69 @@ struct gaih_addrtuple {
   char addr[16];
 };
 
-static struct gaih_addrtuple nulladdr;
-
 struct gaih_typeproto {
   int socktype;
   int protocol;
-  const char *name;
+  char *name;
 };
 
+#if LOCAL
+static int gaih_local(const char *name, const struct gaih_service *service,
+		     const struct addrinfo *req, struct addrinfo **pai)
+{
+  struct utsname utsname;
+
+  if (name || (req->ai_flags & AI_CANONNAME))
+    if (uname(&utsname))
+      return -EAI_SYSTEM;
+  if (name) {
+    if (strcmp(name, "localhost") && strcmp(name, "local") && strcmp(name, "unix") && strcmp(name, utsname.nodename))
+      return (GAIH_OKIFUNSPEC | -EAI_NONAME);
+  };
+
+  if (!(*pai = malloc(sizeof(struct addrinfo) + sizeof(struct sockaddr_un) + ((req->ai_flags & AI_CANONNAME) ? (strlen(utsname.nodename) + 1): 0))))
+    return -EAI_MEMORY;
+
+  (*pai)->ai_next = NULL;
+  (*pai)->ai_flags = req->ai_flags;
+  (*pai)->ai_family = AF_LOCAL;
+  (*pai)->ai_socktype = req->ai_socktype ? req->ai_socktype : SOCK_STREAM;
+  (*pai)->ai_protocol = req->ai_protocol;
+  (*pai)->ai_addrlen = sizeof(struct sockaddr_un);
+  (*pai)->ai_addr = (void *)(*pai) + sizeof(struct addrinfo);
+#if SALEN
+  ((struct sockaddr_un *)(*pai)->ai_addr)->sun_len = sizeof(struct sockaddr_un);
+#endif /* SALEN */
+  ((struct sockaddr_un *)(*pai)->ai_addr)->sun_family = AF_LOCAL;
+  memset(((struct sockaddr_un *)(*pai)->ai_addr)->sun_path, 0, UNIX_PATH_MAX);
+  if (service) {
+    char *c;
+    if (c = strchr(service->name, '/')) {
+      if (strlen(service->name) >= sizeof(((struct sockaddr_un *)(*pai)->ai_addr)->sun_path))
+        return (GAIH_OKIFUNSPEC | -EAI_SERVICE);
+      strcpy(((struct sockaddr_un *)(*pai)->ai_addr)->sun_path, service->name);
+    } else {
+      if (strlen(P_tmpdir "/") + 1 + strlen(service->name) >= sizeof(((struct sockaddr_un *)(*pai)->ai_addr)->sun_path))
+        return (GAIH_OKIFUNSPEC | -EAI_SERVICE);
+      strcpy(((struct sockaddr_un *)(*pai)->ai_addr)->sun_path, P_tmpdir "/");
+      strcat(((struct sockaddr_un *)(*pai)->ai_addr)->sun_path, service->name);
+    };
+  } else {
+    if (!tmpnam(((struct sockaddr_un *)(*pai)->ai_addr)->sun_path))
+      return -EAI_SYSTEM;
+  };
+  if (req->ai_flags & AI_CANONNAME)
+    strcpy((*pai)->ai_canonname = (char *)(*pai) + sizeof(struct addrinfo) + sizeof(struct sockaddr_un), utsname.nodename);
+  else
+    (*pai)->ai_canonname = NULL;
+  return 0;
+};
+#endif /* LOCAL */
+
 static struct gaih_typeproto gaih_inet_typeproto[] = {
   { 0, 0, NULL },
-  { SOCK_STREAM, IPPROTO_TCP, "tcp" },
-  { SOCK_DGRAM, IPPROTO_UDP, "udp" },
+  { SOCK_STREAM, IPPROTO_TCP, (char *)"tcp" },
+  { SOCK_DGRAM, IPPROTO_UDP, (char *)"udp" },
   { 0, 0, NULL }
 };
 
@@ -124,12 +197,12 @@ static int gaih_inet(const char *name, const struct gaih_service *service,
 {
   struct gaih_typeproto *tp = gaih_inet_typeproto;
   struct gaih_servtuple *st = &nullserv;
-  struct gaih_addrtuple *at = &nulladdr;
+  struct gaih_addrtuple *at = NULL;
   int i;
 
   if (req->ai_protocol || req->ai_socktype) {
     for (tp++; tp->name &&
-	  ((req->ai_socktype != tp->socktype) || !req->ai_socktype) &&
+	  ((req->ai_socktype != tp->socktype) || !req->ai_socktype) && 
 	  ((req->ai_protocol != tp->protocol) || !req->ai_protocol); tp++);
     if (!tp->name)
       if (req->ai_socktype)
@@ -139,7 +212,7 @@ static int gaih_inet(const char *name, const struct gaih_service *service,
   }
 
   if (service) {
-    if (service->name) {
+    if (service->num < 0) {
       if (tp->name) {
 	if (i = gaih_inet_serv(service->name, tp, &st))
 	  return i;
@@ -182,18 +255,18 @@ static int gaih_inet(const char *name, const struct gaih_service *service,
       if (inet_pton(AF_INET, name, at->addr) > 0)
 	at->family = AF_INET;
 
-#ifdef INET6
+#if INET6
     if (!at->family && (!req->ai_family || (req->ai_family == AF_INET6)))
       if (inet_pton(AF_INET6, name, at->addr) > 0)
 	at->family = AF_INET6;
 #endif /* INET6 */
 
-#ifdef HOSTTABLE
+#if HOSTTABLE
     if (!at->family) {
       struct hostent *h;
       struct gaih_addrtuple **pat = &at;
 
-#ifdef INET6
+#if INET6
       if (!req->ai_family || (req->ai_family == AF_INET6))
 	if (h = _hostname2addr_hosts(name, AF_INET6)) {
 	  for (i = 0; h->h_addr_list[i]; i++) {
@@ -229,14 +302,35 @@ static int gaih_inet(const char *name, const struct gaih_service *service,
     }
 #endif /* HOSTTABLE */
 
-#ifdef RESOLVER
+#if RESOLVER
     if (!at->family) {
       struct hostent *h;
       struct gaih_addrtuple **pat = &at;
 
-#ifdef INET6
-      if (!req->ai_family || (req->ai_family == AF_INET6))
-	if (h = gethostbyname2(name, AF_INET6)) {
+#if INET6
+      if (!req->ai_family || (req->ai_family == AF_INET6)) {
+	int herrno;
+	int tmpbuflen = 1024;
+	struct hostent th;
+	char *tmpbuf = __alloca(tmpbuflen);
+	while (__gethostbyname2_r(name, AF_INET6, &th, tmpbuf, tmpbuflen,
+				  &h, &herrno)) {
+	  if (herrno == NETDB_INTERNAL) {
+	    if (errno == ERANGE) {
+	      /* Need more buffer */
+	      tmpbuflen *= 2;
+	      tmpbuf = __alloca(tmpbuflen);
+	    } else {
+	      /* Bail out */
+	      __set_h_errno(herrno);
+	      i = -EAI_SYSTEM;
+	      goto ret;
+	    }
+	  } else {
+	    break;
+	  }
+	}
+	if (h) {
 	  for (i = 0; h->h_addr_list[i]; i++) {
 	    if (!*pat) {
 	      if (!(*pat = malloc(sizeof(struct gaih_addrtuple)))) {
@@ -250,10 +344,32 @@ static int gaih_inet(const char *name, const struct gaih_service *service,
 	    pat = &((*pat)->next);
 	  }
 	}
+      }
 #endif /* INET6 */
 
-      if (!req->ai_family || (req->ai_family == AF_INET))
-	if (h = gethostbyname2(name, AF_INET)) {
+      if (!req->ai_family || (req->ai_family == AF_INET)) {
+	int herrno;
+	struct hostent th;
+	int tmpbuflen = 1024;
+	char *tmpbuf = __alloca(tmpbuflen);
+	while (__gethostbyname2_r(name, AF_INET, &th, tmpbuf, tmpbuflen,
+				&h, &herrno)) {
+	  if (herrno == NETDB_INTERNAL) {
+	    if (errno == ERANGE) {
+	      /* Need more buffer */
+	      tmpbuflen *= 2;
+	      tmpbuf = __alloca(tmpbuflen);
+	    } else {
+	      /* Bail out */
+	      __set_h_errno(herrno);
+	      i = -EAI_SYSTEM;
+	      goto ret;
+	    }
+	  } else {
+	    break;
+	  }
+	}
+	if (h) {
 	  for (i = 0; h->h_addr_list[i]; i++) {
 	    if (!*pat) {
 	      if (!(*pat = malloc(sizeof(struct gaih_addrtuple)))) {
@@ -267,20 +383,39 @@ static int gaih_inet(const char *name, const struct gaih_service *service,
 	    pat = &((*pat)->next);
 	  }
 	}
+      }
     }
 #endif /* RESOLVER */
 
     if (!at->family)
       return (GAIH_OKIFUNSPEC | -EAI_NONAME);
   } else {
-    memset(&nulladdr, 0, sizeof(nulladdr));
-#ifdef INET6
-    if (!req->ai_family || (req->ai_family == AF_INET6))
-      nulladdr.family = AF_INET6;
-    else
+    if (!(at = malloc(sizeof(struct gaih_addrtuple)))) {
+      i = -EAI_MEMORY;
+      goto ret;
+    };
+
+    memset(at, 0, sizeof(struct gaih_addrtuple));
+
+#if INET6
+    if (!(at->next = malloc(sizeof(struct gaih_addrtuple)))) {
+      i = -EAI_MEMORY;
+      goto ret;
+    };
+
+    at->family = AF_INET6;
+
+    memset(at->next, 0, sizeof(struct gaih_addrtuple));
+    at->next->family = AF_INET;
+#else /* INET6 */
+    at->family = AF_INET;
 #endif /* INET6 */
-    nulladdr.family = AF_INET;
-  }
+  };
+
+  if (!pai) {
+    i = 0;
+    goto ret; 
+  };
 
   {
     const char *c = NULL;
@@ -288,7 +423,7 @@ static int gaih_inet(const char *name, const struct gaih_service *service,
     struct gaih_addrtuple *at2 = at;
     int j;
 #ifndef MAXHOSTNAMELEN
-# define MAXHOSTNAMELEN 128
+#define MAXHOSTNAMELEN 128
 #endif /* MAXHOSTNAMELEN */
     char buffer[MAXHOSTNAMELEN];
 
@@ -296,24 +431,44 @@ static int gaih_inet(const char *name, const struct gaih_service *service,
       if (req->ai_flags & AI_CANONNAME) {
         struct hostent *h = NULL;
 
-#ifdef RESOLVER
-	h = gethostbyaddr(at2->addr,
-#ifdef INET6
-	    (at2->family == AF_INET6) ? sizeof(struct in6_addr) :
+#if RESOLVER
+        int herrno;
+	struct hostent th;
+	int tmpbuflen = 1024;
+	char *tmpbuf = __alloca(tmpbuflen);
+	while (__gethostbyaddr_r(at2->addr,
+#if INET6
+	    (at2->family == AF_INET6) ? sizeof(struct in6_addr) : 
 #endif /* INET6 */
-	    sizeof(struct in_addr), at2->family);
+				 sizeof(struct in_addr), at2->family, 
+				 &th, tmpbuf, tmpbuflen, &h, &herrno)) {
+	  if (herrno == NETDB_INTERNAL) {
+	    if (errno == ERANGE) {
+	      /* Need more buffer */
+	      tmpbuflen *= 2;
+	      tmpbuf = __alloca(tmpbuflen);
+	    } else {
+	      /* Bail out */
+	      __set_h_errno(herrno);
+	      i = -EAI_SYSTEM;
+	      goto ret;
+	    }
+	  } else {
+	    break; 
+	  }
+	}
 #endif /* RESOLVER */
-#ifdef HOSTTABLE
+#if HOSTTABLE
 	if (!h)
 	  h = _addr2hostname_hosts(at2->addr,
-#ifdef INET6
-	    (at2->family == AF_INET6) ? sizeof(struct in6_addr) :
+#if INET6
+	    (at2->family == AF_INET6) ? sizeof(struct in6_addr) : 
 #endif /* INET6 */
 	    sizeof(struct in_addr), at2->family);
 #endif /* HOSTTABLE */
 
 	if (!h)
-	  c = inet_ntop(at2->family, at2->addr, buffer, sizeof(buffer));
+          c = inet_ntop(at2->family, at2->addr, buffer, sizeof(buffer));
 	else
           c = h->h_name;
 
@@ -326,7 +481,7 @@ static int gaih_inet(const char *name, const struct gaih_service *service,
       } else
 	j = 0;
 
-#ifdef INET6
+#if INET6
       if (at2->family == AF_INET6)
 	i = sizeof(struct sockaddr_in6);
       else
@@ -351,7 +506,7 @@ static int gaih_inet(const char *name, const struct gaih_service *service,
 	((struct sockaddr_in *)(*pai)->ai_addr)->sin_family = at2->family;
 	((struct sockaddr_in *)(*pai)->ai_addr)->sin_port = st2->port;
 
-#ifdef INET6
+#if INET6
 	if (at2->family == AF_INET6) {
 	  ((struct sockaddr_in6 *)(*pai)->ai_addr)->sin6_flowinfo = 0;
 	  memcpy(&((struct sockaddr_in6 *)(*pai)->ai_addr)->sin6_addr, at2->addr, sizeof(struct in6_addr));
@@ -361,7 +516,7 @@ static int gaih_inet(const char *name, const struct gaih_service *service,
 	  memcpy(&((struct sockaddr_in *)(*pai)->ai_addr)->sin_addr, at2->addr, sizeof(struct in_addr));
 	  memset(((struct sockaddr_in *)(*pai)->ai_addr)->sin_zero, 0, sizeof(((struct sockaddr_in *)(*pai)->ai_addr)->sin_zero));
 	}
-
+	
 	if (c) {
 	  (*pai)->ai_canonname = (void *)(*pai) + sizeof(struct addrinfo) + i;
 	  strcpy((*pai)->ai_canonname, c);
@@ -388,7 +543,7 @@ ret:
       st = st2;
     }
   }
-  if (at != &nulladdr) {
+  if (at) {
     struct gaih_addrtuple *at2 = at;
     while(at) {
       at2 = at->next;
@@ -406,24 +561,34 @@ struct gaih {
 };
 
 static struct gaih gaih[] = {
-#ifdef INET6
+#if INET6
   { PF_INET6, gaih_inet },
 #endif /* INET6 */
   { PF_INET, gaih_inet },
+#if LOCAL
+  { PF_LOCAL, gaih_local },
+#endif /* LOCAL */
   { PF_UNSPEC, NULL }
 };
 
 int getaddrinfo(const char *name, const char *service,
 		const struct addrinfo *req, struct addrinfo **pai)
 {
-  int i = 0;
-  int j = 0;
-  struct addrinfo *p = NULL, **end = &p;
+  int i = 0, j = 0;
+  struct addrinfo *p = NULL, **end;
   struct gaih *g = gaih, *pg = NULL;
   struct gaih_service gaih_service, *pservice;
 
+  if (name && (name[0] == '*') && !name[1])
+    name = NULL;
+
+  if (service && (service[0] == '*') && !service[1])
+    service = NULL;
+
+#if BROKEN_LIKE_POSIX
   if (!name && !service)
     return EAI_NONAME;
+#endif /* BROKEN_LIKE_POSIX */
 
   if (!req)
     req = &nullreq;
@@ -437,26 +602,35 @@ int getaddrinfo(const char *name, const char *service,
   if (service && *service) {
     char *c;
     gaih_service.num = strtoul(gaih_service.name = (void *)service, &c, 10);
-    if (!*c) {
-      if (!req->ai_socktype)
-	return EAI_SERVICE;
-      gaih_service.name = NULL;
+    if (*c) {
+      gaih_service.num = -1;
     }
+#if BROKEN_LIKE_POSIX
+      else
+        if (!req->ai_socktype)
+          return EAI_SERVICE;
+#endif /* BROKEN_LIKE_POSIX */
     pservice = &gaih_service;
   } else
     pservice = NULL;
 
+  if (pai)
+    end = &p;
+  else
+    end = NULL;
+
   while(g->gaih) {
     if ((req->ai_family == g->family) || !req->ai_family) {
       j++;
       if (!((pg && (pg->gaih == g->gaih)))) {
 	pg = g;
-	if ((i = g->gaih(name, pservice, req, end))) {
+	if (i = g->gaih(name, pservice, req, end)) {
 	  if (!req->ai_family && (i & GAIH_OKIFUNSPEC))
 	    continue;
 	  goto gaih_err;
 	}
-	while(*end) end = &((*end)->ai_next);
+	if (end)
+          while(*end) end = &((*end)->ai_next);
       }
     }
     g++;
@@ -470,6 +644,9 @@ int getaddrinfo(const char *name, const char *service,
     return 0;
   }
 
+  if (!pai && !i)
+    return 0;
+
 gaih_err:
   if (p)
     freeaddrinfo(p);
diff --git a/sysdeps/stub/gai_strerror.c b/sysdeps/stub/gai_strerror.c
new file mode 100644
index 0000000000..b63f0e2623
--- /dev/null
+++ b/sysdeps/stub/gai_strerror.c
@@ -0,0 +1,28 @@
+/* Copyright (C) 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 Library General Public License as
+   published by the Free Software Foundation; either version 2 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
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If not,
+   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#include <errno.h>
+#include <netdb.h>
+
+char *
+gai_strerror (int code)
+{
+  static char buffer[128];
+  snprintf (buffer, sizeof buffer, "Unknown error (%d)", code);
+  return buffer;
+}
diff --git a/sysdeps/stub/msync.c b/sysdeps/stub/msync.c
index 21421b73f1..c8cbe430a5 100644
--- a/sysdeps/stub/msync.c
+++ b/sysdeps/stub/msync.c
@@ -1,20 +1,20 @@
-/* Copyright (C) 1994, 1995, 1996 Free Software Foundation, Inc.
-This file is part of the GNU C Library.
+/* Copyright (C) 1994, 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 Library General Public License as
-published by the Free Software Foundation; either version 2 of the
-License, or (at your option) any later version.
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public License as
+   published by the Free Software Foundation; either version 2 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
-Library General Public License for more details.
+   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
+   Library General Public License for more details.
 
-You should have received a copy of the GNU Library General Public
-License along with the GNU C Library; see the file COPYING.LIB.  If
-not, write to the Free Software Foundation, Inc., 675 Mass Ave,
-Cambridge, MA 02139, USA.  */
+   You should have received a copy of the GNU Library General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If not,
+   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
 
 #include <sys/types.h>
 #include <sys/mman.h>
@@ -25,7 +25,7 @@ Cambridge, MA 02139, USA.  */
    unpredictable before this is done.  */
 
 int
-msync (caddr_t addr, size_t len)
+msync (caddr_t addr, size_t len, int flags)
 {
   __set_errno (ENOSYS);
   return -1;
diff --git a/sysdeps/unix/bsd/sigsuspend.c b/sysdeps/unix/bsd/sigsuspend.c
index 4c045aa663..d416a5f6c7 100644
--- a/sysdeps/unix/bsd/sigsuspend.c
+++ b/sysdeps/unix/bsd/sigsuspend.c
@@ -1,20 +1,20 @@
-/* Copyright (C) 1991, 1996 Free Software Foundation, Inc.
-This file is part of the GNU C Library.
+/* Copyright (C) 1991, 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 Library General Public License as
-published by the Free Software Foundation; either version 2 of the
-License, or (at your option) any later version.
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public License as
+   published by the Free Software Foundation; either version 2 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
-Library General Public License for more details.
+   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
+   Library General Public License for more details.
 
-You should have received a copy of the GNU Library General Public
-License along with the GNU C Library; see the file COPYING.LIB.  If
-not, write to the Free Software Foundation, Inc., 675 Mass Ave,
-Cambridge, MA 02139, USA.  */
+   You should have received a copy of the GNU Library General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If not,
+   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
 
 #include <errno.h>
 #include <signal.h>
@@ -42,5 +42,5 @@ sigsuspend (set)
     if (__sigismember (set, sig))
       mask |= sigmask (sig);
 
-  return __sigpause (mask);
+  return __sigpause (mask, 0);
 }
diff --git a/sysdeps/unix/bsd/sun/sunos4/resourcebits.h b/sysdeps/unix/bsd/sun/sunos4/resourcebits.h
index d0d177c6ff..ff55773e69 100644
--- a/sysdeps/unix/bsd/sun/sunos4/resourcebits.h
+++ b/sysdeps/unix/bsd/sun/sunos4/resourcebits.h
@@ -1,5 +1,5 @@
 /* Bit values for resource limits.  SunOS 4 version.
-   Copyright (C) 1994, 1996 Free Software Foundation, Inc.
+   Copyright (C) 1994, 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
@@ -49,8 +49,8 @@ enum __rlimit_resource
     /* Number of open files.  */
     RLIMIT_NOFILE,
     RLIMIT_OFILE = RLIMIT_NOFILE, /* BSD name for same.  */
-#defin	RLIMIT_NOFILE	RLIMIT_NOFILE
-#defin	RLIMIT_OFILE	RLIMIT_OFILE
+#define	RLIMIT_NOFILE	RLIMIT_NOFILE
+#define	RLIMIT_OFILE	RLIMIT_OFILE
 
     RLIM_NLIMITS,
 
diff --git a/sysdeps/unix/mman/syscalls.list b/sysdeps/unix/mman/syscalls.list
index a5f44e465b..dc63d89d7d 100644
--- a/sysdeps/unix/mman/syscalls.list
+++ b/sysdeps/unix/mman/syscalls.list
@@ -3,5 +3,5 @@
 madvise		-	madvise		3	madvise
 mmap		-	mmap		6	__mmap		mmap
 mprotect	-	mprotect	3	__mprotect	mprotect
-msync		-	msync		2	__libc_msync	msync
+msync		-	msync		3	__libc_msync	msync
 munmap		-	munmap		2	__munmap	munmap
diff --git a/sysdeps/unix/sysv/linux/Dist b/sysdeps/unix/sysv/linux/Dist
index 0660b247ef..0c5903dc89 100644
--- a/sysdeps/unix/sysv/linux/Dist
+++ b/sysdeps/unix/sysv/linux/Dist
@@ -11,8 +11,16 @@ net/if_ppp.h
 net/ppp-comp.h
 net/ppp_defs.h
 net/route.h
+netatalk/atalk.h
+netinet/icmp.h
+netinet/if_fddi.h
+netinet/if_tr.h
+netinet/igmp.h
 netinet/in_systm.h
+netinet/ip_fw.h
+netinet/ip_icmp.h
 netinet/udp.h
+netipx/ipx.h
 nfs/nfs.h
 sys/acct.h
 sys/debugreg.h
diff --git a/sysdeps/unix/sysv/linux/Makefile b/sysdeps/unix/sysv/linux/Makefile
index e02ee8cfe4..ad77f8872c 100644
--- a/sysdeps/unix/sysv/linux/Makefile
+++ b/sysdeps/unix/sysv/linux/Makefile
@@ -10,7 +10,8 @@ sysdep_routines += sysctl clone llseek
 sysdep_headers += sys/mount.h sys/acct.h sys/sysctl.h sys/mtio.h \
 		  sys/module.h sys/io.h sys/klog.h sys/kdaemon.h \
 		  sys/user.h syscall-list.h sys/sysmacros.h sys/procfs.h \
-		  sys/debugreg.h sys/kd.h sys/soundcard.h sys/vt.h
+		  sys/debugreg.h sys/kd.h sys/soundcard.h sys/vt.h \
+		  sys/quota.h
 
 # Generate the list of SYS_* macros for the system calls (__NR_* macros).
 $(objpfx)syscall-%.h $(objpfx)syscall-%.d: ../sysdeps/unix/sysv/linux/sys/syscall.h
@@ -52,7 +53,9 @@ inhibit-siglist := yes
 endif
 
 ifeq ($(subdir),inet)
-sysdep_headers += netinet/in_systm.h sys/socketvar.h
+sysdep_headers += netinet/in_systm.h netinet/udp.h netinet/icmp.h \
+		  netinet/if_fddi.h netinet/if_tr.h netinet/igmp.h \
+		  netinet/ip_fw.h  netinet/ip_icmp.h sys/socketvar.h
 endif
 
 # Don't compile the ctype glue code, since there is no old non-GNU C library.
diff --git a/sysdeps/unix/sysv/linux/net/if_arp.h b/sysdeps/unix/sysv/linux/net/if_arp.h
index cf48f10f79..b1cd18360e 100644
--- a/sysdeps/unix/sysv/linux/net/if_arp.h
+++ b/sysdeps/unix/sysv/linux/net/if_arp.h
@@ -26,6 +26,7 @@
 #include <sys/cdefs.h>
 
 #include <sys/types.h>
+#include <sys/socket.h>
 
 __BEGIN_DECLS
 
diff --git a/sysdeps/unix/sysv/linux/net/if_slip.h b/sysdeps/unix/sysv/linux/net/if_slip.h
new file mode 100644
index 0000000000..2670427dbe
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/net/if_slip.h
@@ -0,0 +1,6 @@
+#ifndef __NET_SLIP_H
+#define __NET_SLIP_H 1
+
+#include <linux/if_slip.h>
+
+#endif
diff --git a/sysdeps/unix/sysv/linux/netatalk/atalk.h b/sysdeps/unix/sysv/linux/netatalk/atalk.h
new file mode 100644
index 0000000000..be3a72d48f
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/netatalk/atalk.h
@@ -0,0 +1,27 @@
+/* Copyright (C) 1991, 92, 93, 95, 96, 97 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 Library General Public License as
+   published by the Free Software Foundation; either version 2 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
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If not,
+   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#ifndef __NETATALK_ATALK_H
+#define __NETATALK_ATALK_H 1
+
+#include <asm/types.h>
+#include <linux/atalk.h>
+
+#define SOL_ATALK       258     /* sockopt level for atalk */
+
+#endif
diff --git a/sysdeps/unix/sysv/linux/netinet/icmp.h b/sysdeps/unix/sysv/linux/netinet/icmp.h
new file mode 100644
index 0000000000..f6b2d8ad94
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/netinet/icmp.h
@@ -0,0 +1,25 @@
+/* Copyright (C) 1991, 92, 93, 95, 96, 97 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 Library General Public License as
+   published by the Free Software Foundation; either version 2 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
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If not,
+   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#ifndef _NETINET_ICMP_H
+#define	_NETINET_ICMP_H 1
+
+#include <asm/types.h>
+#include <linux/icmp.h>
+
+#endif	/* netinet/icmp.h */
diff --git a/sysdeps/unix/sysv/linux/netinet/if_ether.h b/sysdeps/unix/sysv/linux/netinet/if_ether.h
index 0da5a5aea9..7194490f53 100644
--- a/sysdeps/unix/sysv/linux/netinet/if_ether.h
+++ b/sysdeps/unix/sysv/linux/netinet/if_ether.h
@@ -1,35 +1,109 @@
-/* Copyright (C) 1996 Free Software Foundation, Inc.
-This file is part of the GNU C Library.
+/* Copyright (C) 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 Library General Public License as
-published by the Free Software Foundation; either version 2 of the
-License, or (at your option) any later version.
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public License as
+   published by the Free Software Foundation; either version 2 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
-Library General Public License for more details.
+   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
+   Library General Public License for more details.
 
-You should have received a copy of the GNU Library General Public
-License along with the GNU C Library; see the file COPYING.LIB.  If
-not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA.  */
+   You should have received a copy of the GNU Library General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If not,
+   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
 
 #ifndef __NETINET_IF_ETHER_H
 
 #define __NETINET_IF_ETHER_H	1
 #include <features.h>
+#include <sys/types.h>
 
 /* Get definitions from kernel header file.  */
 #include <linux/if_ether.h>
 
+#ifdef __USE_BSD
+/*
+ * Copyright (c) 1982, 1986, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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_ether.h	8.3 (Berkeley) 5/2/95
+ *	$FreeBSD$
+ */
 
-/* This is a name for the 48 bit ethernet address available on many
-   systems.  */
-struct ether_addr
-{
-  unsigned char ether_addr_octet[ETH_ALEN];
+#include <net/ethernet.h>
+#include <net/if_arp.h>
+
+__BEGIN_DECLS
+/*
+ * Ethernet Address Resolution Protocol.
+ *
+ * See RFC 826 for protocol description.  Structure below is adapted
+ * to resolving internet addresses.  Field names used correspond to
+ * RFC 826.
+ */
+struct	ether_arp {
+	struct	arphdr ea_hdr;		/* fixed-size header */
+	u_int8_t arp_sha[ETH_ALEN];	/* sender hardware address */
+	u_int8_t arp_spa[4];		/* sender protocol address */
+	u_int8_t arp_tha[ETH_ALEN];	/* target hardware address */
+	u_int8_t arp_tpa[4];		/* target protocol address */
 };
+#define	arp_hrd	ea_hdr.ar_hrd
+#define	arp_pro	ea_hdr.ar_pro
+#define	arp_hln	ea_hdr.ar_hln
+#define	arp_pln	ea_hdr.ar_pln
+#define	arp_op	ea_hdr.ar_op
+
+/*
+ * Macro to map an IP multicast address to an Ethernet multicast address.
+ * The high-order 25 bits of the Ethernet address are statically assigned,
+ * and the low-order 23 bits are taken from the low end of the IP address.
+ */
+#define ETHER_MAP_IP_MULTICAST(ipaddr, enaddr) \
+	/* struct in_addr *ipaddr; */ \
+	/* u_char enaddr[ETH_ALEN];	   */ \
+{ \
+	(enaddr)[0] = 0x01; \
+	(enaddr)[1] = 0x00; \
+	(enaddr)[2] = 0x5e; \
+	(enaddr)[3] = ((u_int8_t *)ipaddr)[1] & 0x7f; \
+	(enaddr)[4] = ((u_int8_t *)ipaddr)[2]; \
+	(enaddr)[5] = ((u_int8_t *)ipaddr)[3]; \
+}
+
+__END_DECLS
+#endif /* __USE_BSD */
 
 #endif /* netinet/if_ether.h */
diff --git a/sysdeps/unix/sysv/linux/netinet/if_fddi.h b/sysdeps/unix/sysv/linux/netinet/if_fddi.h
new file mode 100644
index 0000000000..d5d6dbdbe2
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/netinet/if_fddi.h
@@ -0,0 +1,37 @@
+/* Copyright (C) 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 Library General Public License as
+   published by the Free Software Foundation; either version 2 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
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If not,
+   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#ifndef _NETINET_IF_FDDI_H
+#define	_NETINET_IF_FDDI_H 1
+
+#include <sys/cdefs.h>
+#include <sys/types.h>
+#include <asm/types.h>
+
+#include <linux/if_fddi.h>
+
+#ifdef __USE_BSD
+
+struct fddi_header {
+  u_int8_t fddi_fc;                    /* Frame Control (FC) value */
+  u_int8_t fddi_dhost[FDDI_K_ALEN];    /* Destination host */
+  u_int8_t fddi_shost[FDDI_K_ALEN];    /* Source host */
+};
+#endif
+
+#endif	/* netinet/if_fddi.h */
diff --git a/sysdeps/unix/sysv/linux/netinet/if_tr.h b/sysdeps/unix/sysv/linux/netinet/if_tr.h
new file mode 100644
index 0000000000..3c1be2102f
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/netinet/if_tr.h
@@ -0,0 +1,41 @@
+/* Copyright (C) 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 Library General Public License as
+   published by the Free Software Foundation; either version 2 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
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If not,
+   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#ifndef _NETINET_IF_TR_H
+#define	_NETINET_IF_TR_H 1
+
+#include <sys/cdefs.h>
+#include <sys/types.h>
+#include <asm/types.h>
+
+#include <linux/if_tr.h>
+
+#ifdef __USE_BSD
+
+struct trn_hdr {
+  u_int8_t trn_ac;                /* access control field */
+  u_int8_t trn_fc;                /* field control field */
+  u_int8_t trn_dhost[TR_ALEN];    /* destination host */
+  u_int8_t trn_shost[TR_ALEN];    /* source host */
+  u_int16_t trn_rcf;              /* route control field */
+  u_int16_t trn_rseg[8];          /* routing registers */
+};
+
+#endif
+
+#endif	/* netinet/if_tr.h */
diff --git a/sysdeps/unix/sysv/linux/netinet/igmp.h b/sysdeps/unix/sysv/linux/netinet/igmp.h
new file mode 100644
index 0000000000..7a6ed6e8c6
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/netinet/igmp.h
@@ -0,0 +1,93 @@
+/* Copyright (C) 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 Library General Public License as
+   published by the Free Software Foundation; either version 2 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
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If not,
+   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#ifndef _NETINET_IGMP_H
+#define	_NETINET_IGMP_H 1
+
+#include <sys/cdefs.h>
+#include <sys/types.h>
+
+#include <asm/types.h>
+#include <linux/igmp.h>
+
+#ifdef __USE_BSD
+
+#include <netinet/in.h>
+
+__BEGIN_DECLS
+
+/*
+ * Copyright (c) 1988 Stephen Deering.
+ * Copyright (c) 1992, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Stephen Deering of Stanford University.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
+ *
+ *	@(#)igmp.h	8.1 (Berkeley) 6/10/93
+ *	$FreeBSD$
+ */
+
+struct igmp {
+  u_int8_t igmp_type;             /* IGMP type */
+  u_int8_t igmp_code;             /* routing code */
+  u_int16_t igmp_cksum;           /* checksum */
+  struct in_addr igmp_group;      /* group address */
+};
+
+/*
+ * Message types, including version number.
+ */
+#define IGMP_MEMBERSHIP_QUERY   	0x11	/* membership query         */
+#define IGMP_V1_MEMBERSHIP_REPORT	0x12	/* Ver. 1 membership report */
+#define IGMP_V2_MEMBERSHIP_REPORT	0x16	/* Ver. 2 membership report */
+#define IGMP_V2_LEAVE_GROUP		0x17	/* Leave-group message	    */
+
+__END_DECLS
+
+#endif
+
+#endif	/* netinet/igmp.h */
diff --git a/sysdeps/unix/sysv/linux/netinet/in.h b/sysdeps/unix/sysv/linux/netinet/in.h
index 0fec8ce3dd..53be934968 100644
--- a/sysdeps/unix/sysv/linux/netinet/in.h
+++ b/sysdeps/unix/sysv/linux/netinet/in.h
@@ -22,8 +22,11 @@
 #include <features.h>
 
 #include <sys/socket.h>
+#include <sys/types.h>
 
 
+__BEGIN_DECLS
+
 /* Standard well-defined IP protocols.  */
 enum
   {
@@ -134,6 +137,32 @@ struct in_addr
 #endif
 
 
+/* IPv6 address */
+struct in6_addr
+  {
+    union
+      {
+	u_int8_t	u6_addr8[16];
+	u_int16_t	u6_addr16[8];
+	u_int32_t	u6_addr32[4];
+#if (~0UL) > 0xffffffff
+	u_int64_t	u6_addr64[2];
+#endif
+      } in6_u;
+#define s6_addr			in6_u.u6_addr8
+#define s6_addr16		in6_u.u6_addr16
+#define s6_addr32		in6_u.u6_addr32
+#define s6_addr64		in6_u.u6_addr64
+  };
+
+extern const struct in6_addr in6addr_any;        /* :: */
+extern const struct in6_addr in6addr_loopback;   /* ::1 */
+#define IN6ADDR_ANY_INIT { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }
+#define IN6ADDR_LOOPBACK_INIT { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1 }
+
+#define INET_ADDRSTRLEN 16
+#define INET6_ADDRSTRLEN 46
+
 /* Get the definition of the macro to define the common sockaddr members.  */
 #include <sockaddrcom.h>
 
@@ -152,6 +181,25 @@ struct sockaddr_in
 			   sizeof(struct in_addr)];
   };
 
+/* Ditto, for IPv6.  */
+struct sockaddr_in6
+  {
+    __SOCKADDR_COMMON (sin6_);
+    u_int16_t		sin6_port;      /* Transport layer port # */
+    u_int32_t		sin6_flowinfo;  /* IPv6 flow information */
+    struct in6_addr	sin6_addr;      /* IPv6 address */
+  };
+
+/* IPv6 multicast request.  */
+struct ipv6_mreq
+  {
+    /* IPv6 multicast address of group */
+    struct in6_addr ipv6mr_multiaddr;
+
+    /* local IPv6 address of interface */
+    int		ipv6mr_ifindex;
+  };
+
 
 /* Options for use with `getsockopt' and `setsockopt' at the IP level.
    The first word in the comment at the right is the data type used;
@@ -203,4 +251,56 @@ extern unsigned short int htons __P ((unsigned short int));
 #define	htons(x)	(x)
 #endif
 
+
+/* IPV6 socket options.  */
+#define IPV6_ADDRFORM		1
+#define IPV6_RXINFO		2
+#define IPV6_RXHOPOPTS		3
+#define IPV6_RXDSTOPTS		4
+#define IPV6_RXSRCRT		5
+#define IPV6_PKTOPTIONS		6
+#define IPV6_CHECKSUM		7
+#define IPV6_HOPLIMIT		8
+
+#define IPV6_TXINFO		IPV6_RXINFO
+#define SCM_SRCINFO		IPV6_TXINFO
+#define SCM_SRCRT		IPV6_RXSRCRT
+
+#define IPV6_UNICAST_HOPS	16
+#define IPV6_MULTICAST_IF	17
+#define IPV6_MULTICAST_HOPS	18
+#define IPV6_MULTICAST_LOOP	19
+#define IPV6_ADD_MEMBERSHIP	20
+#define IPV6_DROP_MEMBERSHIP	21
+
+#define IN6_IS_ADDR_UNSPECIFIED(a) \
+        ((((u_int32_t *)(a))[0] == 0) && ((u_int32_t *)(a))[1] == 0) && \
+         (((u_int32_t *)(a))[2] == 0) && ((u_int32_t *)(a))[3] == 0))
+
+#define IN6_IS_ADDR_LOOPBACK(a) \
+        ((((u_int32_t *)(a))[0] == 0) && ((u_int32_t *)(a))[1] == 0) && \
+         (((u_int32_t *)(a))[2] == 0) && ((u_int32_t *)(a))[3] == htonl(1)))
+
+#define IN6_IS_ADDR_MULTICAST(a) (((u_int8_t *)(a))[0] == 0xff)
+
+#define IN6_IS_ADDR_LINKLOCAL(a) \
+        ((((u_int32_t *)(a))[0] & htonl(0xffc00000)) == htonl(0xfe800000))
+
+#define IN6_IS_ADDR_SITELOCAL(a) \
+        ((((u_int32_t *)(a))[0] & htonl(0xffc00000)) == htonl(0xfec00000))
+
+#define IN6_IS_ADDR_V4MAPPED(a) \
+        ((((u_int32_t *)(a))[0] == 0) && (((u_int32_t *)(a))[1] == 0) && \
+         (((u_int32_t *)(a))[2] == htonl(0xffff)))
+
+#define IN6_IS_ADDR_V4COMPAT(a) \
+        ((((u_int32_t *)(a))[0] == 0) && (((u_int32_t *)(a))[1] == 0) && \
+         (((u_int32_t *)(a))[2] == 0) && (ntohl(((u_int32_t *)(a))[3]) > 1))
+
+
+/* Bind socket to a priviledged IP port.  */
+extern int bindresvport __P ((int __sockfd, struct sockaddr_in *__sin));
+
+__END_DECLS
+
 #endif	/* netinet/in.h */
diff --git a/sysdeps/unix/sysv/linux/netinet/ip.h b/sysdeps/unix/sysv/linux/netinet/ip.h
new file mode 100644
index 0000000000..c779db4e87
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/netinet/ip.h
@@ -0,0 +1,254 @@
+/* Copyright (C) 1991, 92, 93, 95, 96, 97 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 Library General Public License as
+   published by the Free Software Foundation; either version 2 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
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If not,
+   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#ifndef __NETINET_IP_H
+#define __NETINET_IP_H 1
+
+#include <sys/cdefs.h>
+#include <sys/types.h>
+
+#include <netinet/in.h>
+
+__BEGIN_DECLS
+
+struct timestamp {
+	u_int8_t	len;
+	u_int8_t	ptr;
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+	u_int8_t	flags:4,
+		overflow:4;
+#elif __BYTE_ORDER == __BIG_ENDIAN
+	u_int8_t	overflow:4,
+		flags:4;
+#else
+#error	"Please fix <bytesex.h>"
+#endif						
+	u_int32_t	data[9];
+};
+
+struct ip_options {
+  u_int32_t	faddr;		/* Saved first hop address */
+  u_int8_t	optlen;
+  u_int8_t srr;
+  u_int8_t rr;
+  u_int8_t ts;
+  u_int8_t is_setbyuser:1,	/* Set by setsockopt?			*/
+                is_data:1,	/* Options in __data, rather than skb	*/
+                is_strictroute:1, /* Strict source route		*/
+                srr_is_hit:1,	/* Packet destination addr was our one	*/
+                is_changed:1,	/* IP checksum more not valid		*/	
+                rr_needaddr:1,	/* Need to record addr of outgoing dev	*/
+                ts_needtime:1,	/* Need to record timestamp		*/
+                ts_needaddr:1;	/* Need to record addr of outgoing dev  */
+  u_int8_t router_alert;
+  u_int8_t __pad1;
+  u_int8_t __pad2;
+  u_int8_t __data[0];
+};
+
+struct iphdr {
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+	u_int8_t	ihl:4,
+		version:4;
+#elif __BYTE_ORDER == __BIG_ENDIAN
+	u_int8_t	version:4,
+  		ihl:4;
+#else
+#error	"Please fix <bytesex.h>"
+#endif
+	u_int8_t	tos;
+	u_int16_t	tot_len;
+	u_int16_t	id;
+	u_int16_t	frag_off;
+	u_int8_t	ttl;
+	u_int8_t	protocol;
+	u_int16_t	check;
+	u_int32_t	saddr;
+	u_int32_t	daddr;
+	/*The options start here. */
+};
+
+#ifdef __USE_BSD
+/*
+ * Copyright (c) 1982, 1986, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
+ *
+ *	@(#)ip.h	8.1 (Berkeley) 6/10/93
+ */
+
+/*
+ * Definitions for internet protocol version 4.
+ * Per RFC 791, September 1981.
+ */
+
+/*
+ * Structure of an internet header, naked of options.
+ */
+struct ip {
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+	u_int8_t  ip_hl:4,		/* header length */
+		  ip_v:4;		/* version */
+#endif
+#if __BYTE_ORDER == __BIG_ENDIAN
+	u_int8_t  ip_v:4,		/* version */
+		  ip_hl:4;		/* header length */
+#endif
+	u_int8_t  ip_tos;		/* type of service */
+	u_short ip_len;		/* total length */
+	u_short ip_id;		/* identification */
+	u_short ip_off;		/* fragment offset field */
+#define	IP_RF 0x8000			/* reserved fragment flag */
+#define	IP_DF 0x4000			/* dont fragment flag */
+#define	IP_MF 0x2000			/* more fragments flag */
+#define	IP_OFFMASK 0x1fff		/* mask for fragmenting bits */
+	u_int8_t  ip_ttl;		/* time to live */
+	u_int8_t  ip_p;			/* protocol */
+	u_short ip_sum;		/* checksum */
+	struct	  in_addr ip_src, ip_dst; /* source and dest address */
+};
+
+/*
+ * Time stamp option structure.
+ */
+struct	ip_timestamp {
+	u_int8_t ipt_code;		/* IPOPT_TS */
+	u_int8_t ipt_len;		/* size of structure (variable) */
+	u_int8_t ipt_ptr;		/* index of current entry */
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+	u_int8_t ipt_flg:4,		/* flags, see below */
+		 ipt_oflw:4;		/* overflow counter */
+#endif
+#if __BYTE_ORDER == __BIG_ENDIAN
+	u_int8_t ipt_oflw:4,		/* overflow counter */
+		 ipt_flg:4;		/* flags, see below */
+#endif
+	u_int32_t data[9];
+};
+#endif /* __USE_BSD */
+
+#define	IPVERSION	4               /* IP version number */
+#define	IP_MAXPACKET	65535		/* maximum packet size */
+
+/*
+ * Definitions for IP type of service (ip_tos)
+ */
+#define	IPTOS_LOWDELAY		0x10
+#define	IPTOS_THROUGHPUT	0x08
+#define	IPTOS_RELIABILITY	0x04
+#define	IPTOS_LOWCOST		0x02
+#define	IPTOS_MINCOST		IPTOS_LOWCOST
+
+/*
+ * Definitions for IP precedence (also in ip_tos) (hopefully unused)
+ */
+#define	IPTOS_PREC_NETCONTROL		0xe0
+#define	IPTOS_PREC_INTERNETCONTROL	0xc0
+#define	IPTOS_PREC_CRITIC_ECP		0xa0
+#define	IPTOS_PREC_FLASHOVERRIDE	0x80
+#define	IPTOS_PREC_FLASH		0x60
+#define	IPTOS_PREC_IMMEDIATE		0x40
+#define	IPTOS_PREC_PRIORITY		0x20
+#define	IPTOS_PREC_ROUTINE		0x00
+
+/*
+ * Definitions for options.
+ */
+#define	IPOPT_COPIED(o)		((o)&0x80)
+#define	IPOPT_CLASS(o)		((o)&0x60)
+#define	IPOPT_NUMBER(o)		((o)&0x1f)
+
+#define	IPOPT_CONTROL		0x00
+#define	IPOPT_RESERVED1		0x20
+#define	IPOPT_DEBMEAS		0x40
+#define	IPOPT_RESERVED2		0x60
+
+#define	IPOPT_EOL		0		/* end of option list */
+#define	IPOPT_NOP		1		/* no operation */
+
+#define	IPOPT_RR		7		/* record packet route */
+#define	IPOPT_TS		68		/* timestamp */
+#define	IPOPT_SECURITY		130		/* provide s,c,h,tcc */
+#define	IPOPT_LSRR		131		/* loose source route */
+#define	IPOPT_SATID		136		/* satnet id */
+#define	IPOPT_SSRR		137		/* strict source route */
+
+/*
+ * Offsets to fields in options other than EOL and NOP.
+ */
+#define	IPOPT_OPTVAL		0		/* option ID */
+#define	IPOPT_OLEN		1		/* option length */
+#define	IPOPT_OFFSET		2		/* offset within option */
+#define	IPOPT_MINOFF		4		/* min value of above */
+
+#define	MAX_IPOPTLEN		40
+
+/* flag bits for ipt_flg */
+#define	IPOPT_TS_TSONLY		0		/* timestamps only */
+#define	IPOPT_TS_TSANDADDR	1		/* timestamps and addresses */
+#define	IPOPT_TS_PRESPEC	3		/* specified modules only */
+
+/* bits for security (not byte swapped) */
+#define	IPOPT_SECUR_UNCLASS	0x0000
+#define	IPOPT_SECUR_CONFID	0xf135
+#define	IPOPT_SECUR_EFTO	0x789a
+#define	IPOPT_SECUR_MMMM	0xbc4d
+#define	IPOPT_SECUR_RESTR	0xaf13
+#define	IPOPT_SECUR_SECRET	0xd788
+#define	IPOPT_SECUR_TOPSECRET	0x6bc5
+
+/*
+ * Internet implementation parameters.
+ */
+#define	MAXTTL		255		/* maximum time to live (seconds) */
+#define	IPDEFTTL	64		/* default ttl, from RFC 1340 */
+#define	IPFRAGTTL	60		/* time to live for frags, slowhz */
+#define	IPTTLDEC	1		/* subtracted when forwarding */
+
+#define	IP_MSS		576		/* default maximum segment size */
+
+__END_DECLS
+
+#endif /* netinet/ip.h */
diff --git a/sysdeps/unix/sysv/linux/netinet/ip_fw.h b/sysdeps/unix/sysv/linux/netinet/ip_fw.h
new file mode 100644
index 0000000000..3887ca8992
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/netinet/ip_fw.h
@@ -0,0 +1,187 @@
+/* Copyright (C) 1991, 92, 93, 95, 96, 97 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 Library General Public License as
+   published by the Free Software Foundation; either version 2 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
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If not,
+   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+/* This header file was taken from linux (2.1.26) sources and modified
+ * to work under GNU LIBC 2.0.
+ */
+
+/*
+ * Copyright (c) 1993 Daniel Boulet
+ * Copyright (c) 1994 Ugen J.S.Antsilevich
+ *
+ * Redistribution and use in source forms, with and without modification,
+ * are permitted provided that this entire comment appears intact.
+ *
+ * Redistribution in binary form may occur without any restrictions.
+ * Obviously, it would be nice if you gave credit where credit is due
+ * but requiring it would be too onerous.
+ *
+ * This software is provided ``AS IS'' without any warranties of any kind.
+ */
+
+/*
+ * 	Format of an IP firewall descriptor
+ *
+ * 	src, dst, src_mask, dst_mask are always stored in network byte order.
+ * 	flags and num_*_ports are stored in host byte order (of course).
+ * 	Port numbers are stored in HOST byte order.
+ */
+ 
+#ifndef _NETINET_FW_H
+#define _NETINET_FW_H
+
+#include <sys/cdefs.h>
+#include <sys/types.h>
+
+#include <netinet/icmp.h>
+#include <netinet/in.h>
+#include <netinet/ip.h>
+#include <netinet/tcp.h>
+#include <netinet/udp.h>
+
+__BEGIN_DECLS
+
+struct ip_fw {
+  struct ip_fw  *fw_next;		/* Next firewall on chain */
+  struct in_addr fw_src, fw_dst;	/* Source and destination IP addr */
+  struct in_addr fw_smsk, fw_dmsk;	/* Mask for src and dest IP addr */
+  struct in_addr fw_via;		/* IP address of interface "via" */
+  void *fw_viadev;	                /* device of interface "via" */
+  u_int16_t fw_flg;		        /* Flags word */
+  u_int16_t fw_nsp, fw_ndp;             /* N'of src ports and # of dst ports */
+					/* in ports array (dst ports follow */
+    					/* src ports; max of 10 ports in all;*/
+    					/* count of 0 means match all ports) */
+#define IP_FW_MAX_PORTS	10      	/* A reasonable maximum */
+  u_int16_t fw_pts[IP_FW_MAX_PORTS];    /* Array of port numbers to match */
+  u_int32_t fw_pcnt, fw_bcnt;		/* Packet and byte counters */
+  u_int8_t fw_tosand, fw_tosxor;	/* Revised packet priority */
+  char fw_vianame[IFNAMSIZ];	        /* name of interface "via" */
+};
+
+/*
+ *	Values for "flags" field .
+ */
+
+#define IP_FW_F_ALL	0x0000	/* This is a universal packet firewall*/
+#define IP_FW_F_TCP	0x0001	/* This is a TCP packet firewall      */
+#define IP_FW_F_UDP	0x0002	/* This is a UDP packet firewall      */
+#define IP_FW_F_ICMP	0x0003	/* This is a ICMP packet firewall     */
+#define IP_FW_F_KIND	0x0003	/* Mask to isolate firewall kind      */
+#define IP_FW_F_ACCEPT	0x0004	/* This is an accept firewall (as     *
+				 *         opposed to a deny firewall)*
+				 *                                    */
+#define IP_FW_F_SRNG	0x0008	/* The first two src ports are a min  *
+				 * and max range (stored in host byte *
+				 * order).                            *
+				 *                                    */
+#define IP_FW_F_DRNG	0x0010	/* The first two dst ports are a min  *
+				 * and max range (stored in host byte *
+				 * order).                            *
+				 * (ports[0] <= port <= ports[1])     *
+				 *                                    */
+#define IP_FW_F_PRN	0x0020	/* In verbose mode print this firewall*/
+#define IP_FW_F_BIDIR	0x0040	/* For bidirectional firewalls        */
+#define IP_FW_F_TCPSYN	0x0080	/* For tcp packets-check SYN only     */
+#define IP_FW_F_ICMPRPL 0x0100	/* Send back icmp unreachable packet  */
+#define IP_FW_F_MASQ	0x0200	/* Masquerading			      */
+#define IP_FW_F_TCPACK	0x0400	/* For tcp-packets match if ACK is set*/
+#define IP_FW_F_REDIR	0x0800	/* Redirect to local port fw_pts[n]   */
+#define IP_FW_F_ACCTIN  0x1000	/* Account incoming packets only.     */
+#define IP_FW_F_ACCTOUT 0x2000	/* Account outgoing packets only.     */
+
+#define IP_FW_F_MASK	0x3FFF	/* All possible flag bits mask        */
+
+/*    
+ *	New IP firewall options for [gs]etsockopt at the RAW IP level.
+ *	Unlike BSD Linux inherits IP options so you don't have to use
+ *	a raw socket for this. Instead we check rights in the calls.
+ */     
+
+#define IP_FW_BASE_CTL  	64	/* base for firewall socket options */
+
+#define IP_FW_COMMAND		0x00FF	/* mask for command without chain */
+#define IP_FW_TYPE		0x0300	/* mask for type (chain) */
+#define IP_FW_SHIFT		8	/* shift count for type (chain) */
+
+#define IP_FW_FWD		0
+#define IP_FW_IN		1
+#define IP_FW_OUT		2
+#define IP_FW_ACCT		3
+#define IP_FW_CHAINS		4	/* total number of ip_fw chains */
+
+#define IP_FW_INSERT		(IP_FW_BASE_CTL)
+#define IP_FW_APPEND		(IP_FW_BASE_CTL+1)
+#define IP_FW_DELETE		(IP_FW_BASE_CTL+2)
+#define IP_FW_FLUSH		(IP_FW_BASE_CTL+3)
+#define IP_FW_ZERO		(IP_FW_BASE_CTL+4)
+#define IP_FW_POLICY		(IP_FW_BASE_CTL+5)
+#define IP_FW_CHECK		(IP_FW_BASE_CTL+6)
+#define IP_FW_MASQ_TIMEOUTS	(IP_FW_BASE_CTL+7)
+
+#define IP_FW_INSERT_FWD	(IP_FW_INSERT | (IP_FW_FWD << IP_FW_SHIFT))
+#define IP_FW_APPEND_FWD	(IP_FW_APPEND | (IP_FW_FWD << IP_FW_SHIFT))
+#define IP_FW_DELETE_FWD	(IP_FW_DELETE | (IP_FW_FWD << IP_FW_SHIFT))
+#define IP_FW_FLUSH_FWD		(IP_FW_FLUSH  | (IP_FW_FWD << IP_FW_SHIFT))
+#define IP_FW_ZERO_FWD		(IP_FW_ZERO   | (IP_FW_FWD << IP_FW_SHIFT))
+#define IP_FW_POLICY_FWD	(IP_FW_POLICY | (IP_FW_FWD << IP_FW_SHIFT))
+#define IP_FW_CHECK_FWD		(IP_FW_CHECK  | (IP_FW_FWD << IP_FW_SHIFT))
+
+#define IP_FW_INSERT_IN		(IP_FW_INSERT | (IP_FW_IN << IP_FW_SHIFT))
+#define IP_FW_APPEND_IN		(IP_FW_APPEND | (IP_FW_IN << IP_FW_SHIFT))
+#define IP_FW_DELETE_IN		(IP_FW_DELETE | (IP_FW_IN << IP_FW_SHIFT))
+#define IP_FW_FLUSH_IN		(IP_FW_FLUSH  | (IP_FW_IN << IP_FW_SHIFT))
+#define IP_FW_ZERO_IN		(IP_FW_ZERO   | (IP_FW_IN << IP_FW_SHIFT))
+#define IP_FW_POLICY_IN		(IP_FW_POLICY | (IP_FW_IN << IP_FW_SHIFT))
+#define IP_FW_CHECK_IN		(IP_FW_CHECK  | (IP_FW_IN << IP_FW_SHIFT))
+
+#define IP_FW_INSERT_OUT	(IP_FW_INSERT | (IP_FW_OUT << IP_FW_SHIFT))
+#define IP_FW_APPEND_OUT	(IP_FW_APPEND | (IP_FW_OUT << IP_FW_SHIFT))
+#define IP_FW_DELETE_OUT	(IP_FW_DELETE | (IP_FW_OUT << IP_FW_SHIFT))
+#define IP_FW_FLUSH_OUT		(IP_FW_FLUSH  | (IP_FW_OUT << IP_FW_SHIFT))
+#define IP_FW_ZERO_OUT		(IP_FW_ZERO   | (IP_FW_OUT << IP_FW_SHIFT))
+#define IP_FW_POLICY_OUT	(IP_FW_POLICY | (IP_FW_OUT << IP_FW_SHIFT))
+#define IP_FW_CHECK_OUT		(IP_FW_CHECK  | (IP_FW_OUT << IP_FW_SHIFT))
+
+#define IP_ACCT_INSERT		(IP_FW_INSERT | (IP_FW_ACCT << IP_FW_SHIFT))
+#define IP_ACCT_APPEND		(IP_FW_APPEND | (IP_FW_ACCT << IP_FW_SHIFT))
+#define IP_ACCT_DELETE		(IP_FW_DELETE | (IP_FW_ACCT << IP_FW_SHIFT))
+#define IP_ACCT_FLUSH		(IP_FW_FLUSH  | (IP_FW_ACCT << IP_FW_SHIFT))
+#define IP_ACCT_ZERO		(IP_FW_ZERO   | (IP_FW_ACCT << IP_FW_SHIFT))
+
+struct ip_fwpkt
+{
+  struct iphdr fwp_iph;			/* IP header */
+  union {
+    struct tcphdr fwp_tcph;		/* TCP header or */
+    struct udphdr fwp_udph;		/* UDP header */
+    struct icmphdr fwp_icmph;	        /* ICMP header */
+  } fwp_protoh;
+  struct in_addr fwp_via;	        /* interface address */
+  char fwp_vianame[IFNAMSIZ];	        /* interface name */
+};
+
+/*
+ * timeouts for ip masquerading
+ */
+
+struct ip_fw_masq;
+  
+__END_DECLS
+
+#endif /* _NETINET_IP_FW_H */
diff --git a/sysdeps/unix/sysv/linux/netinet/ip_icmp.h b/sysdeps/unix/sysv/linux/netinet/ip_icmp.h
new file mode 100644
index 0000000000..cb50193b37
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/netinet/ip_icmp.h
@@ -0,0 +1,210 @@
+/* Copyright (C) 1991, 92, 93, 95, 96, 97 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 Library General Public License as
+   published by the Free Software Foundation; either version 2 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
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If not,
+   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#ifndef __NETINET_IP_ICMP_H
+#define __NETINET_IP_ICMP_H    1
+
+#include <sys/cdefs.h>
+#include <sys/types.h>
+
+__BEGIN_DECLS
+
+/*
+ * Copyright (c) 1982, 1986, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
+ *
+ *	@(#)ip_icmp.h	8.1 (Berkeley) 6/10/93
+ */
+
+#include <netinet/in.h>
+#include <netinet/ip.h>
+
+/*
+ * Internal of an ICMP Router Advertisement
+ */
+struct icmp_ra_addr {
+	u_int32_t ira_addr;
+	u_int32_t ira_preference;
+};
+
+struct icmp {
+  u_int8_t  icmp_type;	/* type of message, see below */
+  u_int8_t  icmp_code;	/* type sub code */
+  u_int16_t icmp_cksum;	/* ones complement checksum of struct */
+  union {
+    u_char ih_pptr;		/* ICMP_PARAMPROB */
+    struct in_addr ih_gwaddr;	/* gateway address */
+    struct ih_idseq {		/* echo datagram */	
+      u_int16_t icd_id;
+      u_int16_t icd_seq;
+    } ih_idseq;
+    u_int32_t ih_void;
+
+    /* ICMP_UNREACH_NEEDFRAG -- Path MTU Discovery (RFC1191) */
+    struct ih_pmtu {	
+      u_int16_t ipm_void;
+      u_int16_t ipm_nextmtu;
+    } ih_pmtu;
+
+    struct ih_rtradv {
+      u_int8_t irt_num_addrs;
+      u_int8_t irt_wpa;
+      u_int16_t irt_lifetime;
+    } ih_rtradv;
+  } icmp_hun;
+#define	icmp_pptr	icmp_hun.ih_pptr
+#define	icmp_gwaddr	icmp_hun.ih_gwaddr
+#define	icmp_id		icmp_hun.ih_idseq.icd_id
+#define	icmp_seq	icmp_hun.ih_idseq.icd_seq
+#define	icmp_void	icmp_hun.ih_void
+#define	icmp_pmvoid	icmp_hun.ih_pmtu.ipm_void
+#define	icmp_nextmtu	icmp_hun.ih_pmtu.ipm_nextmtu
+#define	icmp_num_addrs	icmp_hun.ih_rtradv.irt_num_addrs
+#define	icmp_wpa	icmp_hun.ih_rtradv.irt_wpa
+#define	icmp_lifetime	icmp_hun.ih_rtradv.irt_lifetime
+  union {
+    struct {
+      u_int32_t its_otime;
+      u_int32_t its_rtime;
+      u_int32_t its_ttime;
+    } id_ts;
+    struct {
+      struct ip idi_ip;
+      /* options and then 64 bits of data */
+    } id_ip;
+    struct icmp_ra_addr id_radv;
+    u_int32_t   id_mask;
+    u_int8_t    id_data[1];
+  } icmp_dun;
+#define	icmp_otime	icmp_dun.id_ts.its_otime
+#define	icmp_rtime	icmp_dun.id_ts.its_rtime
+#define	icmp_ttime	icmp_dun.id_ts.its_ttime
+#define	icmp_ip		icmp_dun.id_ip.idi_ip
+#define	icmp_radv	icmp_dun.id_radv
+#define	icmp_mask	icmp_dun.id_mask
+#define	icmp_data	icmp_dun.id_data
+};
+
+/*
+ * Lower bounds on packet lengths for various types.
+ * For the error advice packets must first insure that the
+ * packet is large enough to contain the returned ip header.
+ * Only then can we do the check to see if 64 bits of packet
+ * data have been returned, since we need to check the returned
+ * ip header length.
+ */
+#define	ICMP_MINLEN	8				/* abs minimum */
+#define	ICMP_TSLEN	(8 + 3 * sizeof (n_time))	/* timestamp */
+#define	ICMP_MASKLEN	12				/* address mask */
+#define	ICMP_ADVLENMIN	(8 + sizeof (struct ip) + 8)	/* min */
+#ifndef _IP_VHL
+#define	ICMP_ADVLEN(p)	(8 + ((p)->icmp_ip.ip_hl << 2) + 8)
+	/* N.B.: must separately check that ip_hl >= 5 */
+#else
+#define	ICMP_ADVLEN(p)	(8 + (IP_VHL_HL((p)->icmp_ip.ip_vhl) << 2) + 8)
+	/* N.B.: must separately check that header length >= 5 */
+#endif
+
+/* Definition of type and code fields. */
+#define	ICMP_ECHOREPLY		0		/* echo reply */
+#define	ICMP_UNREACH		3		/* dest unreachable, codes: */
+#define	ICMP_SOURCEQUENCH	4		/* packet lost, slow down */
+#define	ICMP_REDIRECT		5		/* shorter route, codes: */
+#define	ICMP_ECHO		8		/* echo service */
+#define	ICMP_ROUTERADVERT	9		/* router advertisement */
+#define	ICMP_ROUTERSOLICIT	10		/* router solicitation */
+#define	ICMP_TIMXCEED		11		/* time exceeded, code: */
+#define	ICMP_PARAMPROB		12		/* ip header bad */
+#define	ICMP_TSTAMP		13		/* timestamp request */
+#define	ICMP_TSTAMPREPLY	14		/* timestamp reply */
+#define	ICMP_IREQ		15		/* information request */
+#define	ICMP_IREQREPLY		16		/* information reply */
+#define	ICMP_MASKREQ		17		/* address mask request */
+#define	ICMP_MASKREPLY		18		/* address mask reply */
+
+#define	ICMP_MAXTYPE		18
+
+/* UNREACH codes */
+#define	ICMP_UNREACH_NET	        0	/* bad net */
+#define	ICMP_UNREACH_HOST	        1	/* bad host */
+#define	ICMP_UNREACH_PROTOCOL	        2	/* bad protocol */
+#define	ICMP_UNREACH_PORT	        3	/* bad port */
+#define	ICMP_UNREACH_NEEDFRAG	        4	/* IP_DF caused drop */
+#define	ICMP_UNREACH_SRCFAIL	        5	/* src route failed */
+#define	ICMP_UNREACH_NET_UNKNOWN        6	/* unknown net */
+#define	ICMP_UNREACH_HOST_UNKNOWN       7	/* unknown host */
+#define	ICMP_UNREACH_ISOLATED	        8	/* src host isolated */
+#define	ICMP_UNREACH_NET_PROHIB	        9	/* net denied */
+#define	ICMP_UNREACH_HOST_PROHIB        10	/* host denied */
+#define	ICMP_UNREACH_TOSNET	        11	/* bad tos for net */
+#define	ICMP_UNREACH_TOSHOST	        12	/* bad tos for host */
+#define	ICMP_UNREACH_FILTER_PROHIB      13	/* admin prohib */
+#define	ICMP_UNREACH_HOST_PRECEDENCE    14	/* host prec vio. */
+#define	ICMP_UNREACH_PRECEDENCE_CUTOFF  15	/* prec cutoff */
+
+/* REDIRECT codes */
+#define	ICMP_REDIRECT_NET	0		/* for network */
+#define	ICMP_REDIRECT_HOST	1		/* for host */
+#define	ICMP_REDIRECT_TOSNET	2		/* for tos and net */
+#define	ICMP_REDIRECT_TOSHOST	3		/* for tos and host */
+
+/* TIMEXCEED codes */
+#define	ICMP_TIMXCEED_INTRANS	0		/* ttl==0 in transit */
+#define	ICMP_TIMXCEED_REASS	1		/* ttl==0 in reass */
+
+/* PARAMPROB code */
+#define	ICMP_PARAMPROB_OPTABSENT 1		/* req. opt. absent */
+
+#define	ICMP_INFOTYPE(type) \
+	((type) == ICMP_ECHOREPLY || (type) == ICMP_ECHO || \
+	(type) == ICMP_ROUTERADVERT || (type) == ICMP_ROUTERSOLICIT || \
+	(type) == ICMP_TSTAMP || (type) == ICMP_TSTAMPREPLY || \
+	(type) == ICMP_IREQ || (type) == ICMP_IREQREPLY || \
+	(type) == ICMP_MASKREQ || (type) == ICMP_MASKREPLY)
+
+__END_DECLS
+
+#endif /* netinet/ip_icmp.h */
diff --git a/sysdeps/unix/sysv/linux/netinet/tcp.h b/sysdeps/unix/sysv/linux/netinet/tcp.h
new file mode 100644
index 0000000000..b7bf0857b8
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/netinet/tcp.h
@@ -0,0 +1,162 @@
+/*
+ * Copyright (c) 1982, 1986, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
+ *
+ *	@(#)tcp.h	8.1 (Berkeley) 6/10/93
+ */
+
+#ifndef _NETINET_TCP_H
+#define _NETINET_TCP_H	1
+
+#include <sys/cdefs.h>
+#include <sys/types.h>
+
+__BEGIN_DECLS
+
+#ifdef __FAVOR_BSD
+typedef	u_int32_t	tcp_seq;
+/*
+ * TCP header.
+ * Per RFC 793, September, 1981.
+ */
+struct tcphdr {
+	u_int16_t	th_sport;		/* source port */
+	u_int16_t	th_dport;		/* destination port */
+	tcp_seq	th_seq;			/* sequence number */
+	tcp_seq	th_ack;			/* acknowledgement number */
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+	u_int8_t	th_x2:4,		/* (unused) */
+		th_off:4;		/* data offset */
+#endif
+#if __BYTE_ORDER == __BIG_ENDIAN
+	u_int8_t	th_off:4,		/* data offset */
+		th_x2:4;		/* (unused) */
+#endif
+	u_int8_t	th_flags;
+#define	TH_FIN	0x01
+#define	TH_SYN	0x02
+#define	TH_RST	0x04
+#define	TH_PUSH	0x08
+#define	TH_ACK	0x10
+#define	TH_URG	0x20
+	u_int16_t	th_win;			/* window */
+	u_int16_t	th_sum;			/* checksum */
+	u_int16_t	th_urp;			/* urgent pointer */
+};
+
+#else /* !__FAVOR_BSD */
+struct tcphdr {
+	u_int16_t	source;
+	u_int16_t	dest;
+	u_int32_t	seq;
+	u_int32_t	ack_seq;
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+	u_int16_t	res1:4,
+		doff:4,
+		fin:1,
+		syn:1,
+		rst:1,
+		psh:1,
+		ack:1,
+		urg:1,
+		res2:2;
+#elif __BYTE_ORDER == __BIG_ENDIAN
+	u_int16_t	doff:4,
+		res1:4,
+		res2:2,
+		urg:1,
+		ack:1,
+		psh:1,
+		rst:1,
+		syn:1,
+		fin:1;
+#else
+#error	"Adjust your <bytesex.h> defines"
+#endif	
+	u_int16_t	window;
+	u_int16_t	check;
+	u_int16_t	urg_ptr;
+};
+#endif /* __FAVOR_BSD */
+
+enum {
+  TCP_ESTABLISHED = 1,
+  TCP_SYN_SENT,
+  TCP_SYN_RECV,
+  TCP_FIN_WAIT1,
+  TCP_FIN_WAIT2,
+  TCP_TIME_WAIT,
+  TCP_CLOSE,
+  TCP_CLOSE_WAIT,
+  TCP_LAST_ACK,
+  TCP_LISTEN,
+  TCP_CLOSING   /* now a valid state */
+};
+
+#define	TCPOPT_EOL		0
+#define	TCPOPT_NOP		1
+#define	TCPOPT_MAXSEG		2
+#define    TCPOLEN_MAXSEG		4
+#define TCPOPT_WINDOW		3
+#define    TCPOLEN_WINDOW		3
+#define TCPOPT_SACK_PERMITTED	4		/* Experimental */
+#define    TCPOLEN_SACK_PERMITTED	2
+#define TCPOPT_SACK		5		/* Experimental */
+#define TCPOPT_TIMESTAMP	8
+#define    TCPOLEN_TIMESTAMP		10
+#define    TCPOLEN_TSTAMP_APPA		(TCPOLEN_TIMESTAMP+2) /* appendix A */
+
+#define TCPOPT_TSTAMP_HDR	\
+    (TCPOPT_NOP<<24|TCPOPT_NOP<<16|TCPOPT_TIMESTAMP<<8|TCPOLEN_TIMESTAMP)
+
+/*
+ * Default maximum segment size for TCP.
+ * With an IP MSS of 576, this is 536,
+ * but 512 is probably more convenient.
+ * This should be defined as MIN(512, IP_MSS - sizeof (struct tcpiphdr)).
+ */
+#define	TCP_MSS	512
+
+#define	TCP_MAXWIN	65535	/* largest value for (unscaled) window */
+
+#define TCP_MAX_WINSHIFT	14	/* maximum window shift */
+
+/*
+ * User-settable options (used with setsockopt).
+ */
+#define	TCP_NODELAY	0x01	/* don't delay send to coalesce packets */
+#define	TCP_MAXSEG	0x02	/* set maximum segment size */
+
+#define SOL_TCP		6	/* TCP level */
+
+__END_DECLS
+
+#endif /* netinet/tcp.h */
diff --git a/sysdeps/unix/sysv/linux/netinet/udp.h b/sysdeps/unix/sysv/linux/netinet/udp.h
index b088838ccb..9ee66f0fce 100644
--- a/sysdeps/unix/sysv/linux/netinet/udp.h
+++ b/sysdeps/unix/sysv/linux/netinet/udp.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 1997 Free Software Foundation, Inc.
+/* Copyright (C) 1991, 92, 93, 95, 96, 97 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
@@ -16,20 +16,40 @@
    write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
    Boston, MA 02111-1307, USA.  */
 
-#ifndef _NETINET_UDP_H
-#define _NETINET_UDP_H	1
+/*
+ * Copyright (c) 1982, 1986 Regents of the University of California.
+ * All rights reserved.  The Berkeley software License Agreement
+ * specifies the terms and conditions for redistribution.
+ */
 
-#include <sys/types.h>
+#ifndef __NETINET_UDP_H
+#define __NETINET_UDP_H    1
 
-/* The Internet RFC 768 specifies this format for the UDP protocol.  */
-struct udphdr
-  {
-    u_short uh_sport;		/* Source port.  */
-    u_short uh_dport;		/* Destination port.  */
-    u_short uh_ulen;		/* UDP length.  */
-    u_short uh_sum;		/* UDP checksum.  */
-  };
+#include <sys/cdefs.h>
+#include <sys/types.h>
 
-#define SOL_UDP		17	/* UDP level.  */
+__BEGIN_DECLS
+
+/* UDP header as specified by RFC 768, August 1980. */
+#ifdef __FAVOR_BSD
+struct udphdr {
+         u_int16_t uh_sport;           /* source port */
+         u_int16_t uh_dport;           /* destination port */
+         u_int16_t uh_ulen;            /* udp length */
+         u_int16_t uh_sum;             /* udp checksum */
+};
+#else
+
+struct udphdr {
+  u_int16_t	source;
+  u_int16_t	dest;
+  u_int16_t	len;
+  u_int16_t	check;
+};
+#endif
+
+#define SOL_UDP            17      /* sockopt level for UDP */
+
+__END_DECLS
 
 #endif /* netinet/udp.h */
diff --git a/sysdeps/unix/sysv/linux/netipx/ipx.h b/sysdeps/unix/sysv/linux/netipx/ipx.h
new file mode 100644
index 0000000000..170dfdf134
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/netipx/ipx.h
@@ -0,0 +1,28 @@
+/* Copyright (C) 1991, 92, 93, 95, 96, 97 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 Library General Public License as
+   published by the Free Software Foundation; either version 2 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
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If not,
+   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#ifndef __NETIPX_IPX_H
+#define __NETIPX_IPX_H 1
+
+#include <asm/types.h>
+#include <linux/ipx.h>
+
+#define SOL_IPX    256          /* sockopt level */
+#define IPX_TYPE   1
+
+#endif /* netipx/ipx.h */
diff --git a/sysdeps/unix/sysv/linux/sys/reboot.h b/sysdeps/unix/sysv/linux/sys/reboot.h
index 8783b2767e..4d249aaaaa 100644
--- a/sysdeps/unix/sysv/linux/sys/reboot.h
+++ b/sysdeps/unix/sysv/linux/sys/reboot.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 1996 Free Software Foundation, Inc.
+/* Copyright (C) 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
@@ -36,8 +36,11 @@
 /* Disable reboot using Ctrl-Alt-Delete keystroke.  */
 #define RB_DISABLE_CAD	0
 
+__BEGIN_DECLS
 
 /* Reboot or halt the system.  */
 extern int reboot __P ((int __howto));
 
+__END_DECLS
+
 #endif	/* _SYS_REBOOT_H */
diff --git a/time/test_time.c b/time/test_time.c
index 2d7b8fe8e2..b6f7305c71 100644
--- a/time/test_time.c
+++ b/time/test_time.c
@@ -22,9 +22,7 @@
 
 
 int
-main (argc, argv)
-     int argc;
-     char **argv;
+main (int argc, char **argv)
 {
   time_t t;
   register struct tm *tp;