about summary refs log tree commit diff
diff options
context:
space:
mode:
authorRoland McGrath <roland@gnu.org>1996-07-14 06:04:09 +0000
committerRoland McGrath <roland@gnu.org>1996-07-14 06:04:09 +0000
commit2064087b5f1a0a3a189fcd6a3012376f5545be31 (patch)
tree6f02a4e4364004352f2d785146b5dc12444e83b9
parent842907c6f8e6022f443175072e65bc516eb0973b (diff)
downloadglibc-2064087b5f1a0a3a189fcd6a3012376f5545be31.tar.gz
glibc-2064087b5f1a0a3a189fcd6a3012376f5545be31.tar.xz
glibc-2064087b5f1a0a3a189fcd6a3012376f5545be31.zip
Sun Jul 14 01:51:39 1996 Roland McGrath <roland@delasyd.gnu.ai.mit.edu> cvs/libc-960714
	* manual/Makefile (glibc-targets): Variable and targets removed.

Sat Jul 13 23:50:17 1996  Roland McGrath  <roland@delasyd.gnu.ai.mit.edu>

	* manual/Makefile (lib): New phony target.  Depend on stamp files.
	($(objpfx)stamp%-$(subdir)): New rule to create them when necessary.

1996-07-13  Paul Eggert  <eggert@twinsun.com>

	* time/strftime.c (strftime): Use space padding for %e, %k, %l,
	to match Emacs format-time-string specification.
	(DO_NUMBER_SPACEPAD): Renamed from DO_NUMBER_NOPAD.

Sat Jul 13 20:17:38 1996  Roland McGrath  <roland@delasyd.gnu.ai.mit.edu>

	* elf/dl-deps.c (_dl_map_object_deps): Take new args PRELOADS and
	NPRELOADS, vector of `struct link_map *'s; add them to the searchlist
	between MAP and its deps.
	* elf/link.h: Fix decl.
	* elf/rtld.c (dl_main): If not secure, parse LD_PRELOAD for
	colon-separated list of names, map those and pass vector of ptrs as
	PRELOADS list to _dl_map_object_deps.
	* elf/dl-runtime.c (_dl_object_relocation_scope): Pass new args to
	_dl_map_object_deps with empty preload list.
	* elf/dl-open.c (_dl_open): Likewise.

	* sysdeps/mach/hurd/dl-sysdep.c (_dl_sysdep_open_zero_fill): Function
	removed.
	(__mmap): Pass MACH_PORT_NULL for memobj port when (flags & MAP_ANON).
	* sysdeps/generic/dl-sysdep.c (_dl_sysdep_open_zero_fill):
	Conditionalize defn on [! MAP_ANON].
	* elf/dl-minimal.c (malloc): Conditionalize use of _dl_zerofd
	on [! MAP_ANON].
	* elf/rtld.c (dl_main): Likewise.
	* elf/dl-load.c (_dl_zerofd): Conditionalize defn on [! MAP_ANON].
	(_dl_map_object_from_fd): Conditionalize initialization of _dl_zerofd.

	* elf/dl-fini.c (_dl_fini): Skip finalizer for executable itself.

Sat Jul 13 02:47:53 1996  David Mosberger-Tang  <davidm@azstarnet.com>

	* stdlib/random.c (__random): Declare as int32_t to be in sync
	with declaration.

	* socket/Makefile (headers): Add socketbits.h.

	* misc/mntent.c (endmntent): Allow for NULL stream.  SunOS does
	it that way.

	* grp/initgroups.c (initgroups): Add groups that user is a member
 	of, not the ones he is _not_ a member of.

	* nss/nsswitch.c (known_compare): Make known_compare() a static
 	instead of a local function.  The latter are difficult to debug
 	and slow to execute on certain platforms.

	* sysdeps/posix/ttyname_r.c (ttyname_r): Use sizeof (dev) - 1 in
 	place of sizeof (dev).  The size of a literal string includes the
 	NUL byte.

	* sysdeps/unix/getlogin.c (getlogin): Initialize ut_fd with -1.

Thu Jul 11 16:59:10 1996  David Mosberger-Tang  <davidm@azstarnet.com>

	* misc/mntent.c (addmntent): Seek to end of file before writing
 	entry.  Return 1 on error, not -1.

Tue Jul  9 19:08:05 1996  David Mosberger-Tang  <davidm@azstarnet.com>

	* sysdeps/unix/sysv/linux/syscalls.list: Mark bdflush as EXTRA
	syscall.

Fri Jul  5 18:44:55 1996  David Mosberger-Tang  <davidm@azstarnet.com>

	* sysdeps/unix/sysv/linux/alpha/ioperm.c (port_to_cpu_addr): Size
 	shift amount for Jensen must be 5 not 4.

Sat Jul 13 20:04:28 1996  Roland McGrath  <roland@delasyd.gnu.ai.mit.edu>

	* socket/sys/socket.h (struct osockaddr): New type.

Sat Jul 13 03:50:53 1996  Ulrich Drepper  <drepper@cygnus.com>

	* misc/Makefile (routines): Add qefgcvt and qefgcvt_r.
	* misc/efgcvt.c, misc/efgcvt_r.c: Change code so that the `double'
	and `long double' versions can be generated.
	* misc/qefgcvt.c, misc/qefgcvt_r.c: New files.  Define macros
	so that included efgcvt{,_r}.c file generate `long double'
	versions.
	* stdlib/stdlib.h: Add prototypes for q[efg]cvt() and q[ef]cvt_r()
	functions.

	* manual/startup.texi: Document new getsubopt function.
	* manual/examples/subopt.c: New example program for documenting
	getsubopt function.

Fri Jul 12 23:58:37 1996  Ulrich Drepper  <drepper@cygnus.com>

	* stdlib/Makefile (routines): Add getsubopt.
	* stdlib/stdlib.h: Add prototype for getsubopt.
	* stdlib/getsubopt.c: New file.  Implement getsubopt function
	to handle suboption parsing.
-rw-r--r--ChangeLog111
-rw-r--r--elf/dl-deps.c23
-rw-r--r--elf/dl-fini.c6
-rw-r--r--elf/dl-load.c12
-rw-r--r--elf/dl-minimal.c11
-rw-r--r--elf/dl-open.c2
-rw-r--r--elf/dl-runtime.c2
-rw-r--r--elf/link.h10
-rw-r--r--elf/rtld.c47
-rw-r--r--grp/initgroups.c39
-rw-r--r--manual/Makefile23
-rw-r--r--manual/examples/subopt.c75
-rw-r--r--manual/startup.texi68
-rw-r--r--misc/Makefile2
-rw-r--r--misc/efgcvt.c23
-rw-r--r--misc/efgcvt_r.c38
-rw-r--r--misc/mntent.c11
-rw-r--r--misc/qefgcvt.c26
-rw-r--r--misc/qefgcvt_r.c26
-rw-r--r--nss/nsswitch.c15
-rw-r--r--socket/Makefile2
-rw-r--r--socket/sys/socket.h9
-rw-r--r--stdlib/Makefile2
-rw-r--r--stdlib/getsubopt.c77
-rw-r--r--stdlib/random.c2
-rw-r--r--stdlib/stdlib.h27
-rw-r--r--sys/socket.h1
-rw-r--r--sysdeps/generic/dl-sysdep.c4
-rw-r--r--sysdeps/mach/hurd/dl-sysdep.c12
-rw-r--r--sysdeps/posix/ttyname_r.c10
-rw-r--r--sysdeps/unix/getlogin.c4
-rw-r--r--sysdeps/unix/sysv/linux/alpha/ioperm.c17
-rw-r--r--sysdeps/unix/sysv/linux/syscalls.list2
-rw-r--r--time/strftime.c16
34 files changed, 621 insertions, 134 deletions
diff --git a/ChangeLog b/ChangeLog
index 294d9b0735..77e7e0b546 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,108 @@
+Sun Jul 14 01:51:39 1996  Roland McGrath  <roland@delasyd.gnu.ai.mit.edu>
+
+	* manual/Makefile (glibc-targets): Variable and targets removed.
+
+Sat Jul 13 23:50:17 1996  Roland McGrath  <roland@delasyd.gnu.ai.mit.edu>
+
+	* manual/Makefile (lib): New phony target.  Depend on stamp files.
+	($(objpfx)stamp%-$(subdir)): New rule to create them when necessary.
+
+1996-07-13  Paul Eggert  <eggert@twinsun.com>
+
+	* time/strftime.c (strftime): Use space padding for %e, %k, %l,
+	to match Emacs format-time-string specification.
+	(DO_NUMBER_SPACEPAD): Renamed from DO_NUMBER_NOPAD.
+
+Sat Jul 13 20:17:38 1996  Roland McGrath  <roland@delasyd.gnu.ai.mit.edu>
+
+	* elf/dl-deps.c (_dl_map_object_deps): Take new args PRELOADS and
+	NPRELOADS, vector of `struct link_map *'s; add them to the searchlist
+	between MAP and its deps.
+	* elf/link.h: Fix decl.
+	* elf/rtld.c (dl_main): If not secure, parse LD_PRELOAD for
+	colon-separated list of names, map those and pass vector of ptrs as
+	PRELOADS list to _dl_map_object_deps.
+	* elf/dl-runtime.c (_dl_object_relocation_scope): Pass new args to
+	_dl_map_object_deps with empty preload list.
+	* elf/dl-open.c (_dl_open): Likewise.
+
+	* sysdeps/mach/hurd/dl-sysdep.c (_dl_sysdep_open_zero_fill): Function
+	removed.
+	(__mmap): Pass MACH_PORT_NULL for memobj port when (flags & MAP_ANON).
+	* sysdeps/generic/dl-sysdep.c (_dl_sysdep_open_zero_fill):
+	Conditionalize defn on [! MAP_ANON].
+	* elf/dl-minimal.c (malloc): Conditionalize use of _dl_zerofd
+	on [! MAP_ANON].
+	* elf/rtld.c (dl_main): Likewise.
+	* elf/dl-load.c (_dl_zerofd): Conditionalize defn on [! MAP_ANON].
+	(_dl_map_object_from_fd): Conditionalize initialization of _dl_zerofd.
+
+	* elf/dl-fini.c (_dl_fini): Skip finalizer for executable itself.
+
+Sat Jul 13 02:47:53 1996  David Mosberger-Tang  <davidm@azstarnet.com>
+
+	* stdlib/random.c (__random): Declare as int32_t to be in sync
+	with declaration.
+
+	* socket/Makefile (headers): Add socketbits.h.
+
+	* misc/mntent.c (endmntent): Allow for NULL stream.  SunOS does
+	it that way.
+
+	* grp/initgroups.c (initgroups): Add groups that user is a member
+ 	of, not the ones he is _not_ a member of.
+
+	* nss/nsswitch.c (known_compare): Make known_compare() a static
+ 	instead of a local function.  The latter are difficult to debug
+ 	and slow to execute on certain platforms.
+
+	* sysdeps/posix/ttyname_r.c (ttyname_r): Use sizeof (dev) - 1 in
+ 	place of sizeof (dev).  The size of a literal string includes the
+ 	NUL byte.
+
+	* sysdeps/unix/getlogin.c (getlogin): Initialize ut_fd with -1.
+
+Thu Jul 11 16:59:10 1996  David Mosberger-Tang  <davidm@azstarnet.com>
+
+	* misc/mntent.c (addmntent): Seek to end of file before writing
+ 	entry.  Return 1 on error, not -1.
+
+Tue Jul  9 19:08:05 1996  David Mosberger-Tang  <davidm@azstarnet.com>
+
+	* sysdeps/unix/sysv/linux/syscalls.list: Mark bdflush as EXTRA
+	syscall.
+
+Fri Jul  5 18:44:55 1996  David Mosberger-Tang  <davidm@azstarnet.com>
+
+	* sysdeps/unix/sysv/linux/alpha/ioperm.c (port_to_cpu_addr): Size
+ 	shift amount for Jensen must be 5 not 4.
+
+Sat Jul 13 20:04:28 1996  Roland McGrath  <roland@delasyd.gnu.ai.mit.edu>
+
+	* socket/sys/socket.h (struct osockaddr): New type.
+
+Sat Jul 13 03:50:53 1996  Ulrich Drepper  <drepper@cygnus.com>
+
+	* misc/Makefile (routines): Add qefgcvt and qefgcvt_r.
+	* misc/efgcvt.c, misc/efgcvt_r.c: Change code so that the `double'
+	and `long double' versions can be generated.
+	* misc/qefgcvt.c, misc/qefgcvt_r.c: New files.  Define macros
+	so that included efgcvt{,_r}.c file generate `long double'
+	versions.
+	* stdlib/stdlib.h: Add prototypes for q[efg]cvt() and q[ef]cvt_r()
+	functions.
+
+	* manual/startup.texi: Document new getsubopt function.
+	* manual/examples/subopt.c: New example program for documenting
+	getsubopt function.
+
+Fri Jul 12 23:58:37 1996  Ulrich Drepper  <drepper@cygnus.com>
+
+	* stdlib/Makefile (routines): Add getsubopt.
+	* stdlib/stdlib.h: Add prototype for getsubopt.
+	* stdlib/getsubopt.c: New file.  Implement getsubopt function
+	to handle suboption parsing.
+
 Thu Jul 11 20:09:55 1996  Roland McGrath  <roland@delasyd.gnu.ai.mit.edu>
 
 	* inet/getnetent_r.c: Define NEED_H_ERRNO.
@@ -712,12 +817,6 @@ Fri Jun 28 02:41:08 1996  Roland McGrath  <roland@delasyd.gnu.ai.mit.edu>
 
 	* string/string.h: Don't define memccpy as macro for [__OPTIMIZE__].
 
-Thu Jun 27 23:43:22 1996  Richard Henderson  <rth@tamu.edu>
-
-	* sysdeps/alpha/dl-machine.h (elf_machine_rela):  The Alpha's
-	address-of operation and plt format conspire to require all
-	dynamic relocs to be resolved to actual symbols not plt entries.
-
 Thu Jun 27 02:49:28 1996  Ulrich Drepper  <drepper@cygnus.com>
 
 	* catgets/gencat.c: Add casts to avoid signed<->unsigned warnings.
diff --git a/elf/dl-deps.c b/elf/dl-deps.c
index 9fe974d982..28733ab60d 100644
--- a/elf/dl-deps.c
+++ b/elf/dl-deps.c
@@ -23,20 +23,29 @@ Cambridge, MA 02139, USA.  */
 #include <stdlib.h>
 
 void
-_dl_map_object_deps (struct link_map *map)
+_dl_map_object_deps (struct link_map *map,
+		     struct link_map **preloads, unsigned int npreloads)
 {
   struct list
     {
       struct link_map *map;
       struct list *next;
     };
-  struct list head, *tailp, *scanp;
+  struct list head[1 + npreloads], *tailp, *scanp;
   unsigned int nlist;
 
   /* Start the search list with one element: MAP itself.  */
-  head.map = map;
-  head.next = NULL;
-  nlist = 1;
+  head[0].map = map;
+
+  /* Add the preloaded items after MAP but before any of its dependencies.  */
+  for (nlist = 0; nlist < npreloads; ++nlist)
+    {
+      head[nlist].next = &head[nlist + 1];
+      head[nlist + 1].map = preloads[nlist];
+    }
+
+  /* Terminate the list.  */
+  head[nlist++].next = NULL;
 
   /* We use `l_reserved' as a mark bit to detect objects we have already
      put in the search list and avoid adding duplicate elements later in
@@ -47,7 +56,7 @@ _dl_map_object_deps (struct link_map *map)
      dependencies and appending them to the list as we step through it.
      This produces a flat, ordered list that represents a breadth-first
      search of the dependency tree.  */
-  for (scanp = tailp = &head; scanp; scanp = scanp->next)
+  for (scanp = tailp = head; scanp; scanp = scanp->next)
     {
       struct link_map *l = scanp->map;
 
@@ -91,7 +100,7 @@ _dl_map_object_deps (struct link_map *map)
   map->l_nsearchlist = nlist;
 
   nlist = 0;
-  for (scanp = &head; scanp; scanp = scanp->next)
+  for (scanp = head; scanp; scanp = scanp->next)
     {
       map->l_searchlist[nlist++] = scanp->map;
 
diff --git a/elf/dl-fini.c b/elf/dl-fini.c
index 36b4390663..9f4233aca0 100644
--- a/elf/dl-fini.c
+++ b/elf/dl-fini.c
@@ -25,9 +25,11 @@ _dl_fini (void)
   struct link_map *l;
 
   for (l = _dl_loaded; l; l = l->l_next)
-    if (l->l_init_called && l->l_info[DT_FINI])
+    if (l->l_init_called)
       {
-	(*(void (*) (void)) (l->l_addr + l->l_info[DT_FINI]->d_un.d_ptr)) ();
+	if (l->l_info[DT_FINI] &&
+	    !(l->l_name[0] == '\0' && l->l_type == lt_executable))
+	  (*(void (*) (void)) (l->l_addr + l->l_info[DT_FINI]->d_un.d_ptr)) ();
 	/* Make sure nothing happens if we are called twice.  */
 	l->l_init_called = 0;
       }
diff --git a/elf/dl-load.c b/elf/dl-load.c
index ff7f5cf487..29ac0bfd87 100644
--- a/elf/dl-load.c
+++ b/elf/dl-load.c
@@ -59,7 +59,14 @@ Cambridge, MA 02139, USA.  */
 
 #define STRING(x) #x
 
+#ifdef MAP_ANON
+/* The fd is not examined when using MAP_ANON.  */
+#define ANONFD -1
+#else
 int _dl_zerofd = -1;
+#define ANONFD _dl_zerofd
+#endif
+
 size_t _dl_pagesize;
 
 
@@ -176,6 +183,8 @@ _dl_map_object_from_fd (const char *name, int fd, char *realname,
   if (header->e_phentsize != sizeof (ElfW(Phdr)))
     LOSE ("ELF file's phentsize not the expected size");
 
+#ifndef MAP_ANON
+#define MAP_ANON 0
   if (_dl_zerofd == -1)
     {
       _dl_zerofd = _dl_sysdep_open_zero_fill ();
@@ -185,6 +194,7 @@ _dl_map_object_from_fd (const char *name, int fd, char *realname,
 	  _dl_signal_error (errno, NULL, "cannot open zero fill device");
 	}
     }
+#endif
 
   /* Enter the new object in the list of loaded objects.  */
   l = _dl_new_object (realname, name, l_type);
@@ -329,7 +339,7 @@ _dl_map_object_from_fd (const char *name, int fd, char *realname,
 		caddr_t mapat;
 		mapat = __mmap ((caddr_t) zeropage, zeroend - zeropage,
 				c->prot, MAP_ANON|MAP_PRIVATE|MAP_FIXED,
-				_dl_zerofd, 0);
+				ANONFD, 0);
 		if (mapat == (caddr_t) -1)
 		  lose (errno, "cannot map zero-fill pages");
 	      }
diff --git a/elf/dl-minimal.c b/elf/dl-minimal.c
index fd7bf05497..61615cd9a9 100644
--- a/elf/dl-minimal.c
+++ b/elf/dl-minimal.c
@@ -33,13 +33,18 @@ static void *alloc_ptr, *alloc_end, *alloc_last_block;
 void * weak_function
 malloc (size_t n)
 {
+#ifdef MAP_ANON
+#define	_dl_zerofd (-1)
+#else
   extern int _dl_zerofd;
 
-  if (_dl_pagesize == 0)
-    _dl_pagesize = __getpagesize ();
-
   if (_dl_zerofd == -1)
     _dl_zerofd = _dl_sysdep_open_zero_fill ();
+#define MAP_ANON 0
+#endif
+
+  if (_dl_pagesize == 0)
+    _dl_pagesize = __getpagesize ();
 
   if (alloc_end == 0)
     {
diff --git a/elf/dl-open.c b/elf/dl-open.c
index c24920f933..058c3e5a39 100644
--- a/elf/dl-open.c
+++ b/elf/dl-open.c
@@ -39,7 +39,7 @@ _dl_open (const char *file, int mode)
     return new;
 
   /* Load that object's dependencies.  */
-  _dl_map_object_deps (new);
+  _dl_map_object_deps (new, NULL, 0);
 
 
   /* Relocate the objects loaded.  We do this in reverse order so that copy
diff --git a/elf/dl-runtime.c b/elf/dl-runtime.c
index 8ad2c0ffa4..cdacd756ef 100644
--- a/elf/dl-runtime.c
+++ b/elf/dl-runtime.c
@@ -41,7 +41,7 @@ _dl_object_relocation_scope (struct link_map *l)
 
       if (! l->l_searchlist)
 	/* We must construct the searchlist for this object.  */
-	_dl_map_object_deps (l);
+	_dl_map_object_deps (l, NULL, 0);
 
       /* The primary scope is this object itself and its
 	 dependencies.  */
diff --git a/elf/link.h b/elf/link.h
index 1e0104a4ea..fa96613478 100644
--- a/elf/link.h
+++ b/elf/link.h
@@ -196,9 +196,13 @@ extern int _dlerror_run (void (*operate) (void));
 extern struct link_map *_dl_map_object (struct link_map *loader,
 					const char *name, int type);
 
-/* Call _dl_map_object on the dependencies of MAP, and
-   set up MAP->l_searchlist.  */
-extern void _dl_map_object_deps (struct link_map *map);
+/* Call _dl_map_object on the dependencies of MAP, and set up
+   MAP->l_searchlist.  PRELOADS points to a vector of NPRELOADS previously
+   loaded objects that will be inserted into MAP->l_searchlist after MAP
+   but before its dependencies.  */
+extern void _dl_map_object_deps (struct link_map *map,
+				 struct link_map **preloads,
+				 unsigned int npreloads);
 
 /* Cache the locations of MAP's hash table.  */
 extern void _dl_setup_hash (struct link_map *map);
diff --git a/elf/rtld.c b/elf/rtld.c
index 6baa7a868a..2e23d9cb38 100644
--- a/elf/rtld.c
+++ b/elf/rtld.c
@@ -21,6 +21,7 @@ Cambridge, MA 02139, USA.  */
 #include <stddef.h>
 #include <stdlib.h>
 #include <unistd.h>
+#include <sys/mman.h>		/* Check if MAP_ANON is defined.  */
 #include "../stdio-common/_itoa.h"
 
 
@@ -124,6 +125,8 @@ dl_main (const ElfW(Phdr) *phdr,
   struct link_map *l;
   int lazy;
   int list_only = 0;
+  struct link_map **preloads;
+  unsigned int npreloads;
 
   if (*user_entry == (ElfW(Addr)) &_start)
     {
@@ -247,12 +250,52 @@ of this helper program; chances are you did not intend to run this program.\n",
   l->l_next = &_dl_rtld_map;
   _dl_rtld_map.l_prev = l;
 
-  /* Load all the libraries specified by DT_NEEDED entries.  */
-  _dl_map_object_deps (l);
+  preloads = NULL;
+  npreloads = 0;
+  if (! _dl_secure)
+    {
+      const char *preloadlist = getenv ("LD_PRELOAD");
+      if (preloadlist)
+	{
+	  /* The LD_PRELOAD environment variable gives a colon-separated
+	     list of libraries that are loaded before the executable's
+	     dependencies and prepended to the global scope list.  */
+	  char *list = strdupa (preloadlist);
+	  char *p;
+	  while ((p = strsep (&list, ":")) != NULL)
+	    {
+	      (void) _dl_map_object (NULL, p, lt_library);
+	      ++npreloads;
+	    }
+
+	  if (npreloads != 0)
+	    {
+	      /* Set up PRELOADS with a vector of the preloaded libraries.  */
+	      struct link_map *l;
+	      unsigned int i;
+	      preloads = __alloca (npreloads * sizeof preloads[0]);
+	      l = _dl_rtld_map.l_next; /* End of the chain before preloads.  */
+	      i = 0;
+	      do
+		{
+		  preloads[i++] = l;
+		  l = l->l_next;
+		} while (l);
+	      assert (i == npreloads);
+	    }
+	}
+    }
+
+  /* Load all the libraries specified by DT_NEEDED entries.  If LD_PRELOAD
+     specified some libraries to load, these are inserted before the actual
+     dependencies in the executable's searchlist for symbol resolution.  */
+  _dl_map_object_deps (l, preloads, npreloads);
 
+#ifndef MAP_ANON
   /* We are done mapping things, so close the zero-fill descriptor.  */
   __close (_dl_zerofd);
   _dl_zerofd = -1;
+#endif
 
   /* Remove _dl_rtld_map from the chain.  */
   _dl_rtld_map.l_prev->l_next = _dl_rtld_map.l_next;
diff --git a/grp/initgroups.c b/grp/initgroups.c
index 73c15c6479..35af575ac7 100644
--- a/grp/initgroups.c
+++ b/grp/initgroups.c
@@ -70,28 +70,27 @@ initgroups (user, group)
 	register char **m;
 
 	for (m = g->gr_mem; *m != NULL; ++m)
-	  if (!strcmp (*m, user))
-	    break;
-
-	if (*m == NULL)
-	  {
-	    /* Matched the user.  Insert this group.  */
-	    if (n == ngroups && limit <= 0)
-	      {
-		/* Need a bigger buffer.  */
-		groups = memcpy (__alloca (ngroups * 2 * sizeof *groups),
-				 groups, ngroups * sizeof *groups);
-		ngroups *= 2;
-	      }
-
-	    groups[n++] = g->gr_gid;
-
-	    if (n == limit)
-	      /* Can't take any more groups; stop searching.  */
+	  if (strcmp (*m, user) == 0)
+	    {
+	      /* Matches user.  Insert this group.  */
+	      if (n == ngroups && limit <= 0)
+		{
+		  /* Need a bigger buffer.  */
+		  groups = memcpy (__alloca (ngroups * 2 * sizeof *groups),
+				   groups, ngroups * sizeof *groups);
+		  ngroups *= 2;
+		}
+
+	      groups[n++] = g->gr_gid;
+
+	      if (n == limit)
+		/* Can't take any more groups; stop searching.  */
+		goto done;
+
 	      break;
-	  }
+	    }
       }
-
+done:
   endgrent ();
 
   return setgroups (n, groups);
diff --git a/manual/Makefile b/manual/Makefile
index 7197ecf7a9..eb9fff71ee 100644
--- a/manual/Makefile
+++ b/manual/Makefile
@@ -105,11 +105,6 @@ glibc-doc-$(edition).tar: $(doc-only-dist) $(distribute)
 	uuencode $< < $< > $@.new
 	mv -f $@.new $@
 
-# The parent makefile sometimes invokes us with targets `subdir_REAL-TARGET'.
-subdir_%: % ;
-# For targets we don't define, do nothing.
-subdir_%: ;
-
 .PHONY: mostlyclean distclean realclean clean
 mostlyclean:
 	-rm -f libc.dvi libc.info*
@@ -151,20 +146,22 @@ endif
 TAGS: $(minimal-dist)
 	$(ETAGS) -o $@ $^
 
-# These are targets that each glibc subdirectory is expected to understand.
-# ../Rules defines them for code subdirectories; for us, they are no-ops.
-glibc-targets	:= subdir_lib objects objs others tests subdir_lint.out \
-		   subdir_echo-headers subdir_echo-distinfo stubs
-.PHONY: $(glibc-targets)
-$(glibc-targets):
+# The parent makefile sometimes invokes us with targets `subdir_REAL-TARGET'.
+subdir_%: % ;
+# For targets we don't define, do nothing.
+subdir_%: ;
 
+# Create stamp files if they don't exist, so the parent makefile's rules for
+# updating the library archives are happy with us, and never think we have
+# changed the library.
+.PHONY: lib stubs
+lib: $(foreach o,$(object-suffixes),$(objpfx)stamp$o-$(subdir))
 stubs: $(common-objpfx)stub-manual
-$(common-objpfx)stub-manual ../po/manual.pot:
+$(objpfx)stamp%-$(subdir) $(common-objpfx)stub-manual ../po/manual.pot:
 	cp /dev/null $@
 
 # The top-level glibc Makefile expects subdir_install to update the stubs file.
 subdir_install: stubs
-
 
 # Get rid of these variables if they came from the parent.
 routines =
diff --git a/manual/examples/subopt.c b/manual/examples/subopt.c
new file mode 100644
index 0000000000..4a89f6441e
--- /dev/null
+++ b/manual/examples/subopt.c
@@ -0,0 +1,75 @@
+#include <stdio.h>
+#include <stdlib.h>
+
+int do_all;
+const char *type;
+int read_size;
+int write_size;
+int read_only;
+
+enum
+{
+  RO_OPTION = 0,
+  RW_OPTION,
+  READ_SIZE_OPTION,
+  WRITE_SIZE_OPTION
+};
+
+const char *mount_opts[] =
+{
+  [RO_OPTION] = "ro",
+  [RW_OPTION] = "rw",
+  [READ_SIZE_OPTION] = "rsize",
+  [WRITE_SIZE_OPTION] = "wsize"
+};
+
+int
+main (int argc, char *argv[])
+{
+  char *subopts, *value;
+  int opt;
+
+  while ((opt = getopt (argc, argv, "at:o:")) != EOF)
+    switch (opt)
+      {
+      case 'a':
+        do_all = 1;
+        break;
+      case 't':
+        type = optarg;
+        break;
+      case 'o':
+        subopts = optarg;
+        while (*subopts != '\0')
+          switch (getsubopt (&subopts, mount_opts, &value))
+            {
+            case RO_OPTION:
+              read_only = 1;
+              break;
+            case RW_OPTION:
+              read_only = 0;
+              break;
+            case READ_SIZE_OPTION:
+              if (value == NULL)
+                abort ();
+              read_size = atoi (value);
+              break;
+            case WRITE_SIZE_OPTION:
+              if (value == NULL)
+                abort ();
+              write_size = atoi (value);
+              break;
+            default:
+              /* Unknown suboption.  */
+              printf ("Unknown suboption `%s'\n", value);
+              break;
+            }
+        break;
+      default:
+        abort ();
+      }
+
+  /* Do the real work.  */
+
+  return 0;
+}
diff --git a/manual/startup.texi b/manual/startup.texi
index 654a4e8376..1313d4c2a7 100644
--- a/manual/startup.texi
+++ b/manual/startup.texi
@@ -83,12 +83,14 @@ allow this three-argument form, so to be portable it is best to write
 @code{main} to take two arguments, and use the value of @code{environ}.
 
 @menu
-* Argument Syntax::       By convention, options start with a hyphen.
-* Parsing Options::       The @code{getopt} function.
-* Example of Getopt:: 	  An example of parsing options with @code{getopt}.
-* Long Options::	  GNU suggests utilities accept long-named options.
+* Argument Syntax::             By convention, options start with a hyphen.
+* Parsing Options::             The @code{getopt} function.
+* Example of Getopt::           An example of parsing options with @code{getopt}.
+* Long Options::                GNU suggests utilities accept long-named options.
 			   Here is how to do that.
-* Long Option Example::   An example of using @code{getopt_long}.
+* Long Option Example::         An example of using @code{getopt_long}.
+* Suboptions::                  Some programs need more detailed options.
+* Suboptions Example::          This shows how it could be done for @code{mount}.
 @end menu
 
 @node Argument Syntax
@@ -409,6 +411,58 @@ When @code{getopt_long} has no more options to handle, it returns
 @include longopt.c.texi
 @end smallexample
 
+@node Suboptions
+@subsection Parsing of Suboptions
+
+Having a single level of options is sometimes not enough.  There might
+be too many options which have to be available or a set of options is
+closely related.
+
+For this case some programs use suboptions.  One of the most prominent
+programs is certainly @code{mount}(8).  The @code{-o} option take one
+argument which itself is a comma separated list of options.  To ease the
+programming of code like this the function @code{getsubopt} is
+available.
+
+@comment stdlib.h
+@deftypefun int getsubopt (char **@var{optionp}, const char* const *@var{tokens}, char **@var{valuep})
+
+The @var{optionp} parameter must be a pointer to a variable containing
+the address of the string to process.  When the function returns the
+reference is updated to point to the next suboption or to the
+terminating @samp{\0} character if there is no more suboption available.
+
+The @var{tokens} parameter references an array of strings containing the
+known suboptions.  All strings must be @samp{\0} terminated and to mark
+the end a null pointer must be stored.  When @code{getsubopt} finds a
+possible legal suboption it compares it with all strings available in
+the @var{tokens} array and returns the index in the string as the
+indicator.
+
+In case the suboption has an associated value introduced by a @samp{=}
+character, a pointer to the value is returned in @var{valuep}.  The
+string is @samp{\0} terminated.  If no argument is available
+@var{valuep} is set to the null pointer.  By doing this the caller can
+check whether a necessary value is given or whether no unexpected value
+is present.
+
+In case the next suboption in the string is not mentioned in the
+@var{tokens} array the starting address of the suboption including a
+possible value is returned in @var{valuep} and the return value of the
+function is @samp{-1}.
+@end deftypefun
+
+@node Suboptions Example
+@subsection Parsing of Suboptions Example
+
+The code which might appear in the @code{mount}(8) program is a perfect
+example of the use of @code{getsubopt}:
+
+@smallexample
+@include subopt.c.texi
+@end smallexample
+
+
 @node Environment Variables
 @section Environment Variables
 
@@ -448,9 +502,9 @@ character, since this is assumed to terminate the string.
 
 
 @menu
-* Environment Access::    How to get and set the values of
+* Environment Access::          How to get and set the values of
 			   environment variables.
-* Standard Environment::  These environment variables have
+* Standard Environment::        These environment variables have
 			   standard interpretations.
 @end menu
 
diff --git a/misc/Makefile b/misc/Makefile
index 4ffad986ab..01e223836f 100644
--- a/misc/Makefile
+++ b/misc/Makefile
@@ -52,7 +52,7 @@ routines := brk sbrk sstk ioctl \
 	    insremque getttyent getusershell getpass ttyslot \
 	    syslog syscall daemon \
 	    mmap munmap mprotect msync madvise \
-	    efgcvt efgcvt_r \
+	    efgcvt efgcvt_r qefgcvt qefgcvt_r \
 	    hsearch hsearch_r tsearch lsearch \
 	    err error
 aux := init-misc
diff --git a/misc/efgcvt.c b/misc/efgcvt.c
index e8a05176e6..73be3e1c5c 100644
--- a/misc/efgcvt.c
+++ b/misc/efgcvt.c
@@ -21,11 +21,20 @@ Cambridge, MA 02139, USA.  */
 #include <stdlib.h>
 #include <float.h>
 
+#ifndef FLOAT_TYPE
+#define FLOAT_TYPE double
+#define FUNC_PREFIX
+#define FLOAT_FMT_FLAG
 #define MAXDIG (DBL_DIG + DBL_MAX_10_EXP)
+#endif
+
+#define APPEND(a, b) APPEND2 (a, b)
+#define APPEND2(a, b) a##b
+
 
 char *
-fcvt (value, ndigit, decpt, sign)
-     double value;
+APPEND (FUNC_PREFIX, fcvt) (value, ndigit, decpt, sign)
+     FLOAT_TYPE value;
      int ndigit, *decpt, *sign;
 {
   static char buf[MAXDIG];
@@ -36,8 +45,8 @@ fcvt (value, ndigit, decpt, sign)
 }
 
 char *
-ecvt (value, ndigit, decpt, sign)
-     double value;
+APPEND (FUNC_PREFIX, ecvt) (value, ndigit, decpt, sign)
+     FLOAT_TYPE value;
      int ndigit, *decpt, *sign;
 {
   static char buf[MAXDIG];
@@ -48,11 +57,11 @@ ecvt (value, ndigit, decpt, sign)
 }
 
 char *
-gcvt (value, ndigit, buf)
-     double value;
+APPEND (FUNC_PREFIX, gcvt) (value, ndigit, buf)
+     FLOAT_TYPE value;
      int ndigit;
      char *buf;
 {
-  sprintf (buf, "%.*g", ndigit, value);
+  sprintf (buf, "%.*" FLOAT_FMT_FLAG "g", ndigit, value);
   return buf;
 }
diff --git a/misc/efgcvt_r.c b/misc/efgcvt_r.c
index 6a65583a6a..cbd5c271ba 100644
--- a/misc/efgcvt_r.c
+++ b/misc/efgcvt_r.c
@@ -1,5 +1,5 @@
 /* [efg]cvt -- compatibility functions for floating point formatting,
-   reentrent versions.
+   reentrant versions.
 Copyright (C) 1995, 1996 Free Software Foundation, Inc.
 This file is part of the GNU C Library.
 
@@ -25,9 +25,24 @@ Boston, MA 02111-1307, USA.  */
 #include <math.h>
 #include <stdlib.h>
 
+#ifndef FLOAT_TYPE
+#define FLOAT_TYPE double
+#define FUNC_PREFIX
+#define FLOAT_FMT_FLAG
+#define FLOAT_NAME_EXT
+#endif
+
+#define APPEND(a, b) APPEND2 (a, b)
+#define APPEND2(a, b) a##b
+
+#define FLOOR APPEND(floor, FLOAT_NAME_EXT)
+#define FABS APPEND(fabs, FLOAT_NAME_EXT)
+#define LOG10 APPEND(log10, FLOAT_NAME_EXT)
+
+
 int
-fcvt_r (value, ndigit, decpt, sign, buf, len)
-     double value;
+APPEND (FUNC_PREFIX, fcvt_r) (value, ndigit, decpt, sign, buf, len)
+     FLOAT_TYPE value;
      int ndigit, *decpt, *sign;
      char *buf;
      size_t len;
@@ -44,7 +59,7 @@ fcvt_r (value, ndigit, decpt, sign, buf, len)
   if (*sign)
     value = - value;
 
-  n = snprintf (buf, len, "%.*f", ndigit, value);
+  n = snprintf (buf, len, "%.*" FLOAT_FMT_FLAG "f", ndigit, value);
   if (n < 0)
     return -1;
 
@@ -60,33 +75,34 @@ fcvt_r (value, ndigit, decpt, sign, buf, len)
   return 0;
 }
 
-weak_extern (floor) weak_extern (log10) weak_extern (fabs)
+#define weak_extern2(name) weak_extern (name)
+weak_extern2 (FLOOR) weak_extern2 (LOG10) weak_extern2 (FABS)
 
 int
-ecvt_r (value, ndigit, decpt, sign, buf, len)
-     double value;
+APPEND (FUNC_PREFIX, ecvt_r) (value, ndigit, decpt, sign, buf, len)
+     FLOAT_TYPE value;
      int ndigit, *decpt, *sign;
      char *buf;
      size_t len;
 {
-  double (*log10_function) (double) = &log10;
+  FLOAT_TYPE (*log10_function) (FLOAT_TYPE) = &LOG10;
 
   if (log10_function)
     {
       /* Use the reasonable code if -lm is included.  */
-      ndigit -= (int) floor (log10 (fabs (value)));
+      ndigit -= (int) FLOOR (LOG10 (FABS (value)));
       if (ndigit < 0)
 	ndigit = 0;
     }
   else
     {
       /* Slow code that doesn't require -lm functions.  */
-      double d;
+      FLOAT_TYPE d;
       for (d = value < 0.0 ? - value : value;
 	   ndigit > 0 && d >= 10.0;
 	   d *= 0.1)
 	--ndigit;
     }
 
-  return fcvt_r (value, ndigit, decpt, sign, buf, len);
+  return APPEND (FUNC_PREFIX, fcvt_r) (value, ndigit, decpt, sign, buf, len);
 }
diff --git a/misc/mntent.c b/misc/mntent.c
index 6cf74c2160..0aa1fb8cde 100644
--- a/misc/mntent.c
+++ b/misc/mntent.c
@@ -34,9 +34,9 @@ setmntent (const char *file, const char *mode)
 int
 endmntent (FILE *stream)
 {
-  if (fclose (stream) != 0) 
-      return 0;
-  return 1;
+  if (stream)		/* SunOS 4.x allows for NULL stream */
+    fclose (stream);
+  return 1;		/* SunOS 4.x says to always return 1 */
 }
 
 
@@ -92,6 +92,9 @@ getmntent (FILE *stream)
 int
 addmntent (FILE *stream, const struct mntent *mnt)
 {
+  if (fseek (stream, 0, SEEK_END))
+    return 1;
+
   return (fprintf (stream, "%s %s %s %s %d %d\n",
 		   mnt->mnt_fsname,
 		   mnt->mnt_dir,
@@ -99,7 +102,7 @@ addmntent (FILE *stream, const struct mntent *mnt)
 		   mnt->mnt_opts,
 		   mnt->mnt_freq,
 		   mnt->mnt_passno)
-	  < 0 ? -1 : 0);
+	  < 0 ? 1 : 0);
 }
 
 /* Search MNT->mnt_opts for an option matching OPT.
diff --git a/misc/qefgcvt.c b/misc/qefgcvt.c
new file mode 100644
index 0000000000..2015fb8d4f
--- /dev/null
+++ b/misc/qefgcvt.c
@@ -0,0 +1,26 @@
+/* q[efg]cvt -- compatibility functions for floating point formatting,
+		long double version.
+Copyright (C) 1996 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.  */
+
+#define FLOAT_TYPE long double
+#define FUNC_PREFIX q
+#define FLOAT_FMT_FLAG "L"
+#define MAXDIG (LDBL_DIG + LDBL_MAX_10_EXP)
+
+#include "efgcvt.c"
diff --git a/misc/qefgcvt_r.c b/misc/qefgcvt_r.c
new file mode 100644
index 0000000000..67cf44880c
--- /dev/null
+++ b/misc/qefgcvt_r.c
@@ -0,0 +1,26 @@
+/* [efg]cvt -- compatibility functions for floating point formatting,
+   reentrant, long double versions.
+Copyright (C) 1996 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.  */
+
+#define FLOAT_TYPE long double
+#define FUNC_PREFIX q
+#define FLOAT_FMT_FLAG "L"
+#define FLOAT_NAME_EXT l
+
+#include "efgcvt_r.c"
diff --git a/nss/nsswitch.c b/nss/nsswitch.c
index c92f33b45f..d259165269 100644
--- a/nss/nsswitch.c
+++ b/nss/nsswitch.c
@@ -184,15 +184,18 @@ nss_dlerror_run (void (*operate) (void))
 }
 
 
+/* Comparison function for searching NI->known tree.  */
+static int
+known_compare (const void *p1, const void *p2)
+{
+  return p1 == p2 ? 0 : strcmp (*(const char *const *) p1,
+				*(const char *const *) p2);
+}
+
+
 static void *
 nss_lookup_function (service_user *ni, const char *fct_name)
 {
-  /* Comparison function for searching NI->known tree.  */
-  int known_compare (const void *p1, const void *p2)
-    {
-      return p1 == p2 ? 0 : strcmp (*(const char *const *) p1,
-				    *(const char *const *) p2);
-    }
   void **found, *result;
 
   /* We now modify global data.  Protect it.  */
diff --git a/socket/Makefile b/socket/Makefile
index 78388fd41d..adae887d11 100644
--- a/socket/Makefile
+++ b/socket/Makefile
@@ -21,7 +21,7 @@
 #
 subdir	:= socket
 
-headers	:= sys/socket.h sys/un.h sockaddrcom.h
+headers	:= sys/socket.h sys/un.h sockaddrcom.h socketbits.h
 
 routines := accept bind connect getpeername getsockname getsockopt	\
 	    listen recv recvfrom recvmsg send sendmsg sendto		\
diff --git a/socket/sys/socket.h b/socket/sys/socket.h
index 172c897af7..9c3c3e73fe 100644
--- a/socket/sys/socket.h
+++ b/socket/sys/socket.h
@@ -33,6 +33,15 @@ __BEGIN_DECLS
    `struct msghdr', and `struct linger' types.  */
 #include <socketbits.h>
 
+#ifdef __USE_BSD
+/* This is the 4.3 BSD `struct sockaddr' format, which is used as wire
+   format in the grotty old 4.3 `talk' protocol.  */
+struct osockaddr
+  {
+    unsigned short int sa_family;
+    unsigned char sa_data[14];
+  };
+#endif
 
 /* This is the type we use for generic socket address arguments.
 
diff --git a/stdlib/Makefile b/stdlib/Makefile
index aa072082cc..66f28ffe5c 100644
--- a/stdlib/Makefile
+++ b/stdlib/Makefile
@@ -42,7 +42,7 @@ routines	:=							      \
 	strtof strtod strtold						      \
 	system canonicalize						      \
 	a64l l64a							      \
-	rpmatch strfmon
+	rpmatch strfmon getsubopt
 
 distribute	:= exit.h grouping.h
 tests		:= tst-strtol tst-strtod testmb testrand testsort testdiv \
diff --git a/stdlib/getsubopt.c b/stdlib/getsubopt.c
new file mode 100644
index 0000000000..f5ecea4faa
--- /dev/null
+++ b/stdlib/getsubopt.c
@@ -0,0 +1,77 @@
+/* getsubopt -- parse comma separate list into words
+Copyright (C) 1996 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996.
+
+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 <stdlib.h>
+#include <string.h>
+
+
+/* Parse comma separated suboption from *OPTIONP and match against
+   strings in TOKENS.  If found return index and set *VALUEP to
+   optional value introduced by an equal sign.  If the suboption is
+   not part of TOKENS return in *VALUEP beginning of unknown
+   suboption.  On exit *OPTIONP is set to the beginning of the next
+   otken or at the terminating NUL character.  */
+int
+getsubopt (optionp, tokens, valuep)
+     char **optionp;
+     const char *const *tokens;
+     char **valuep;
+{
+  char *endp, *vstart;
+  int cnt;
+
+  if (**optionp == '\0')
+    return -1;
+
+  /* Find end of next token.  */
+  endp = strchr (*optionp, ',');
+  if (endp == NULL)
+    endp = strchr (*optionp, '\0');
+
+  /* Find start of value.  */
+  vstart = memchr (*optionp, '=', endp - *optionp);
+  if (vstart == NULL)
+    vstart = endp;
+
+  /* Try to match the characters between *OPTIONP and VSTART against
+     one of the TOKENS.  */
+  for (cnt = 0; tokens[cnt] != NULL; ++cnt)
+    if (memcmp (*optionp, tokens[cnt], vstart - *optionp) == 0
+	&& tokens[cnt][vstart - *optionp] == '\0')
+      {
+	/* We found the current option in TOKENS.  */
+	*valuep = vstart != endp ? vstart : NULL;
+
+	if (*endp != '\0')
+	  *endp++ = '\0';
+	*optionp = endp;
+
+	return cnt;
+      }
+
+  /* The current suboption does not match any option.  */
+  *valuep = *optionp;
+
+  if (*endp != '\0')
+    *endp++ = '\0';
+  *optionp = endp;
+
+  return -1;
+}
diff --git a/stdlib/random.c b/stdlib/random.c
index 0ab8f05e5f..6d2ee85f3e 100644
--- a/stdlib/random.c
+++ b/stdlib/random.c
@@ -239,7 +239,7 @@ weak_alias (__setstate, setstate)
    rear pointers can't wrap on the same call by not testing the rear
    pointer if the front one has wrapped.  Returns a 31-bit random number.  */
 
-int
+int32_t
 __random ()
 {
   int32_t retval;
diff --git a/stdlib/stdlib.h b/stdlib/stdlib.h
index 1feedcfae3..5e7f8386b8 100644
--- a/stdlib/stdlib.h
+++ b/stdlib/stdlib.h
@@ -469,12 +469,27 @@ char *fcvt __P ((double __value, int __ndigit, int *__decpt, int *sign));
    be written to BUF.  */
 char *gcvt __P ((double __value, int __ndigit, char *__buf));
 
+/* Long double versions of above functions.  */
+char *qecvt __P ((__long_double_t __value, int __ndigit, int *__decpt,
+		  int *sign));
+char *qfcvt __P ((__long_double_t __value, int __ndigit, int *__decpt,
+		  int *sign));
+char *qgcvt __P ((__long_double_t __value, int __ndigit, char *__buf));
+
+
+#ifdef __USE_REENTRANT
 /* Reentrant version of the functions above which provide their own
    buffers.  */
 int ecvt_r __P ((double __value, int __ndigit, int *__decpt, int *sign,
 		 char *__buf, size_t __len));
 int fcvt_r __P ((double __value, int __ndigit, int *__decpt, int *sign,
 		 char *__buf, size_t __len));
+
+int qecvt_r __P ((__long_double_t __value, int __ndigit, int *__decpt,
+		  int *sign, char *__buf, size_t __len));
+int qfcvt_r __P ((__long_double_t __value, int __ndigit, int *__decpt,
+		  int *sign, char *__buf, size_t __len));
+#endif
 #endif
 
 
@@ -509,6 +524,18 @@ extern int rpmatch __P ((__const char *__response));
 #endif
 
 
+#ifdef __USE_MISC
+/* Parse comma separated suboption from *OPTIONP and match against
+   strings in TOKENS.  If found return index and set *VALUEP to
+   optional value introduced by an equal sign.  If the suboption is
+   not part of TOKENS return in *VALUEP beginning of unknown
+   suboption.  On exit *OPTIONP is set to the beginning of the next
+   otken or at the terminating NUL character.  */
+extern int getsubopt __P ((char **__optionp, __const char *__const *__tokens,
+			   char **__valuep));
+#endif
+
+
 __END_DECLS
 
 #endif /* stdlib.h  */
diff --git a/sys/socket.h b/sys/socket.h
new file mode 100644
index 0000000000..999a683016
--- /dev/null
+++ b/sys/socket.h
@@ -0,0 +1 @@
+#include <socket/sys/socket.h>
diff --git a/sysdeps/generic/dl-sysdep.c b/sysdeps/generic/dl-sysdep.c
index 9fab0f0922..8f9e782205 100644
--- a/sysdeps/generic/dl-sysdep.c
+++ b/sysdeps/generic/dl-sysdep.c
@@ -109,11 +109,15 @@ _dl_sysdep_start_cleanup (void)
 {
 }
 
+#ifndef MAP_ANON
+/* This is only needed if the system doesn't support MAP_ANON.  */
+
 int
 _dl_sysdep_open_zero_fill (void)
 {
   return __open ("/dev/zero", O_RDONLY);
 }
+#endif
 
 void
 _dl_sysdep_fatal (const char *msg, ...)
diff --git a/sysdeps/mach/hurd/dl-sysdep.c b/sysdeps/mach/hurd/dl-sysdep.c
index cffc51e1ce..ee2bf73469 100644
--- a/sysdeps/mach/hurd/dl-sysdep.c
+++ b/sysdeps/mach/hurd/dl-sysdep.c
@@ -210,15 +210,6 @@ _dl_sysdep_start_cleanup (void)
   __mach_port_deallocate (__mach_task_self (), __mach_task_self_);
 }
 
-int
-_dl_sysdep_open_zero_fill (void)
-{
-  /* The minimal mmap below uses the fd as a memory object port.
-     The real mmap used for dlopen ignores the fd for MAP_ANON.  */
-  return (int) MACH_PORT_NULL;
-}
-
-
 void
 _dl_sysdep_fatal (const char *msg, ...)
 {
@@ -523,7 +514,8 @@ __mmap (caddr_t addr, size_t len, int prot, int flags, int fd, off_t offset)
   err = __vm_map (__mach_task_self (),
 		  &mapaddr, (vm_size_t) len, 0 /*ELF_MACHINE_USER_ADDRESS_MASK*/,
 		  !(flags & MAP_FIXED),
-		  (mach_port_t) fd, (vm_offset_t) offset,
+		  (flags & MAP_ANON) ? MACH_PORT_NULL : (mach_port_t) fd,
+		  (vm_offset_t) offset,
 		  flags & (MAP_COPY|MAP_PRIVATE),
 		  vmprot, VM_PROT_ALL,
 		  (flags & MAP_SHARED) ? VM_INHERIT_SHARE : VM_INHERIT_COPY);
diff --git a/sysdeps/posix/ttyname_r.c b/sysdeps/posix/ttyname_r.c
index 30f058314d..4450a83326 100644
--- a/sysdeps/posix/ttyname_r.c
+++ b/sysdeps/posix/ttyname_r.c
@@ -48,7 +48,7 @@ ttyname_r (fd, buf, buflen)
 
   /* Test for the absolute minimal size.  This makes life easier inside
      the loop.  */
-  if (buflen < (int) (sizeof (dev) + 2))
+  if (buflen < (int) (sizeof (dev) + 1))
     {
       errno = EINVAL;
       return -1;
@@ -64,16 +64,16 @@ ttyname_r (fd, buf, buflen)
     return -1;
 
   /* Prepare the result buffer.  */
-  memcpy (buf, dev, sizeof (dev));
-  buf[sizeof (dev)] = '/';
-  buflen -= sizeof (dev) + 1;
+  memcpy (buf, dev, sizeof (dev) - 1);
+  buf[sizeof (dev) - 1] = '/';
+  buflen -= sizeof (dev);
 
   while ((d = readdir (dirstream)) != NULL)
     if (d->d_fileno == myino)
       {
 	char *cp;
 
-	cp = __stpncpy (&buf[sizeof (dev) + 1], d->d_name,
+	cp = __stpncpy (&buf[sizeof (dev)], d->d_name,
 			MIN ((int) (_D_EXACT_NAMLEN (d) + 1), buflen));
 	cp[0] = '\0';
 
diff --git a/sysdeps/unix/getlogin.c b/sysdeps/unix/getlogin.c
index 7446f25786..246b488f51 100644
--- a/sysdeps/unix/getlogin.c
+++ b/sysdeps/unix/getlogin.c
@@ -35,7 +35,7 @@ DEFUN_VOID(getlogin)
   char tty_pathname[2 + 2 * NAME_MAX];
   char *real_tty_path = tty_pathname;
   char *result = NULL;
-  static struct utmp_data utmp_data;
+  static struct utmp_data utmp_data = { ut_fd: -1 };
   struct utmp *ut, line;
 
   {
@@ -48,7 +48,7 @@ DEFUN_VOID(getlogin)
       err = errno;
     (void) close (d);
 
-    if (errno != 0)
+    if (err != 0)
       {
 	errno = err;
 	return NULL;
diff --git a/sysdeps/unix/sysv/linux/alpha/ioperm.c b/sysdeps/unix/sysv/linux/alpha/ioperm.c
index b9630a8273..cee5f482bb 100644
--- a/sysdeps/unix/sysv/linux/alpha/ioperm.c
+++ b/sysdeps/unix/sysv/linux/alpha/ioperm.c
@@ -116,13 +116,9 @@ static inline unsigned long
 port_to_cpu_addr (unsigned long port, int iosys, int size)
 {
   if (iosys == IOSYS_JENSEN)
-    {
-      return (port << 7) + ((size - 1) << 4) + io.base;
-    }
+    return (port << 7) + ((size - 1) << 5) + io.base;
   else
-    {
-      return (port << 5) + ((size - 1) << 3) + io.base;
-    }
+    return (port << 5) + ((size - 1) << 3) + io.base;
 }
 
 
@@ -303,17 +299,18 @@ init_iosys (void)
     }
   else
     {
-      char name[256];
       FILE * fp;
 
       fp = fopen (PATH_CPUINFO, "r");
       if (!fp)
 	return -1;
-      while ((n = fscanf (fp, "%256[^:]: %256[^\n]\n", name, systype)) != EOF)
+      while ((n = fscanf (fp, "system type : %256[^\n]\n", systype))
+	     != EOF)
 	{
-	  if (n == 2 && strncmp (name, "system type", 11) == 0) {
+	  if (n == 1)
 	    break;
-	  }
+	  else
+	    fgets (systype, 256, fp);
 	}
       fclose(fp);
 
diff --git a/sysdeps/unix/sysv/linux/syscalls.list b/sysdeps/unix/sysv/linux/syscalls.list
index d29577ff6c..73b5de9b98 100644
--- a/sysdeps/unix/sysv/linux/syscalls.list
+++ b/sysdeps/unix/sysv/linux/syscalls.list
@@ -1,7 +1,7 @@
 # File name	Caller	Syscall name	# args	Strong name	Weak names
 
 adjtimex	adjtime	adjtimex	1	__adjtimex
-bdflush		-	bdflush		2	bdflush
+bdflush		EXTRA	bdflush		2	bdflush
 create_module	EXTRA	create_module	3	create_module
 delete_module	EXTRA	delete_module	3	delete_module
 fdatasync	-	fdatasync	1	fdatasync
diff --git a/time/strftime.c b/time/strftime.c
index 1af2f83023..69d7103bfb 100644
--- a/time/strftime.c
+++ b/time/strftime.c
@@ -305,8 +305,8 @@ strftime (s, maxsize, format, tp)
 
 #define DO_NUMBER(digits, value) \
 	  maxdigits = digits; number_value = value; goto do_number
-#define DO_NUMBER_NOPAD(digits, value) \
-	  maxdigits = digits; number_value = value; goto do_number_nopad
+#define DO_NUMBER_SPACEPAD(digits, value) \
+	  maxdigits = digits; number_value = value; goto do_number_spacepad
 
 	case 'C':
 	  DO_NUMBER (2, (1900 + tp->tm_year) / 100);
@@ -325,14 +325,14 @@ strftime (s, maxsize, format, tp)
 	  DO_NUMBER (2, tp->tm_mday);
 
 	case 'e':		/* GNU extension: %d, but blank-padded.  */
-	  DO_NUMBER_NOPAD (2, tp->tm_mday);
+	  DO_NUMBER_SPACEPAD (2, tp->tm_mday);
 
 	  /* All numeric formats set MAXDIGITS and NUMBER_VALUE and then
 	     jump to one of these two labels.  */
 
-	do_number_nopad:
-	  /* Force `-' flag.  */
-	  pad = pad_none;
+	do_number_spacepad:
+	  /* Force `_' flag.  */
+	  pad = pad_space;
 
 	do_number:
 	  {
@@ -373,10 +373,10 @@ strftime (s, maxsize, format, tp)
 	  DO_NUMBER (2, hour12);
 
 	case 'k':		/* GNU extension.  */
-	  DO_NUMBER_NOPAD (2, tp->tm_hour);
+	  DO_NUMBER_SPACEPAD (2, tp->tm_hour);
 
 	case 'l':		/* GNU extension.  */
-	  DO_NUMBER_NOPAD (2, hour12);
+	  DO_NUMBER_SPACEPAD (2, hour12);
 
 	case 'j':
 	  DO_NUMBER (3, 1 + tp->tm_yday);