about summary refs log tree commit diff
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2006-06-30 09:16:35 +0000
committerJakub Jelinek <jakub@redhat.com>2006-06-30 09:16:35 +0000
commitac7609f7998add41673e8428cf0bc824a40a1361 (patch)
tree016a7dba118f66dc209b26f930cf9dc4354d7d3b
parent2774ea772499f5779e846646824784a44377c69a (diff)
downloadglibc-cvs/fedora-glibc-2_4_90-12.tar.gz
glibc-cvs/fedora-glibc-2_4_90-12.tar.xz
glibc-cvs/fedora-glibc-2_4_90-12.zip
Updated to fedora-glibc-20060630T0858 cvs/fedora-glibc-2_4_90-12
-rw-r--r--ChangeLog67
-rw-r--r--elf/dl-deps.c12
-rw-r--r--elf/dl-load.c37
-rw-r--r--fedora/branch.mk4
-rw-r--r--fedora/glibc.spec.in22
-rw-r--r--intl/dcigettext.c54
-rw-r--r--misc/Makefile2
-rw-r--r--misc/insremque.c22
-rw-r--r--misc/tst-insremque.c61
-rw-r--r--nis/nis_subr.c73
-rw-r--r--nptl/ChangeLog6
-rw-r--r--nptl/sysdeps/pthread/pthread.h10
-rw-r--r--posix/Makefile3
-rw-r--r--posix/bug-regex25.c57
-rw-r--r--posix/regex_internal.c26
-rw-r--r--string/Makefile3
-rw-r--r--string/_strerror.c7
-rw-r--r--string/bug-envz1.c76
-rw-r--r--string/envz.c4
-rw-r--r--sysdeps/generic/local-setxid.h4
-rw-r--r--sysdeps/i386/Makefile8
-rw-r--r--sysdeps/posix/spawni.c15
-rw-r--r--sysdeps/unix/sysv/linux/local-setxid.h23
23 files changed, 495 insertions, 101 deletions
diff --git a/ChangeLog b/ChangeLog
index 0fca57dc90..520062b8c8 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,70 @@
+2006-06-27  Ulrich Drepper  <drepper@redhat.com>
+
+	* elf/dl-load.c (open_path): Fix test to determine whether DSO is
+	auditing.
+
+	* elf/dl-load.c (_dl_map_object): Try harder to avoid looking at
+	RPATH of main map twice.
+
+2006-06-22  Ulrich Drepper  <drepper@redhat.com>
+
+	* intl/dcigettext.c (DCIGETTEXT): If _nl_find_msg returns -1 don't
+	look further, return original strings.
+	(_nl_find_msg): Do not return found translation if the conversion
+	failed.  Either signal the string is unusable or that something went
+	wrong and the original should be used.
+
+2006-06-21  Ulrich Drepper  <drepper@redhat.com>
+
+	* string/_strerror.c (__strerror_r): Add __builtin_expect.
+
+2006-06-14  Jakub Jelinek  <jakub@redhat.com>
+
+	[BZ #2766]
+	* misc/insremque.c (insque): Handle prev == NULL.
+	* misc/Makefile (tests): Add tst-insremque.
+	* misc/tst-insremque.c: New test.
+
+2006-06-17  Ulrich Drepper  <drepper@redhat.com>
+
+	[BZ #2792]
+	* elf/dl-deps.c (expand_dst): Rename __cnt variable to not
+	conflict with DL_DST_REQUIRED.
+
+2006-06-16  Ulrich Drepper  <drepper@redhat.com>
+
+	* nis/nis_subr.c (nis_getnames): Fix the implementation to better
+	match what Solaris does.
+
+2006-06-04  Ulrich Drepper  <drepper@redhat.com>
+
+	* sysdeps/posix/spawni.c (__spawni): Use local_seteuid and
+	local_setegid instead of seteuid and setegid.
+	* sysdeps/generic/local-setxid.h: New file.
+	* sysdeps/unix/sysv/linux/local-setxid.h: New file.
+
+	* sysdeps/posix/spawni.c (__spawni): Use non-cancelable interfaces.
+
+	* string/Makefile (tests): Add bug-envz1.
+	* string/bug-envz1.c: New file.
+
+2006-06-02  Jakub Jelinek  <jakub@redhat.com>
+
+	* posix/regex_internal.c (re_string_skip_chars): If no character has
+	been converted at all, set *last_wc to WEOF.  If mbrtowc failed, set wc
+	to the byte which couldn't be converted.
+	(re_string_reconstruct): Don't clear valid_raw_len before calling
+	re_string_skip_chars.  If wc is WEOF after re_string_skip_chars, set
+	tip_context using re_string_context_at.
+	* posix/Makefile: Add rules to build and run bug-regex25 test.
+	* posix/bug-regex25.c: New test.
+
+2006-06-02  Ryan S. Arnold  <rsa@us.ibm.com>
+
+	[BZ #2703]
+	* string/envz.c (envz_strip): Correct erroneously reversed src
+	and dest parameters to memmove() invocation.
+
 2006-05-30  Jakub Jelinek  <jakub@redhat.com>
 
 	* nscd/nscd.h (prune_cache): Add fd argument to prototype.
diff --git a/elf/dl-deps.c b/elf/dl-deps.c
index fd3b5243fd..c35cc977fa 100644
--- a/elf/dl-deps.c
+++ b/elf/dl-deps.c
@@ -1,5 +1,5 @@
 /* Load the dependencies of a mapped object.
-   Copyright (C) 1996-2003, 2004, 2005 Free Software Foundation, Inc.
+   Copyright (C) 1996-2003, 2004, 2005, 2006 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
@@ -92,7 +92,7 @@ struct list
   {
     int done;			/* Nonzero if this map was processed.  */
     struct link_map *map;	/* The data.  */
-    struct list *next;	/* Elements for normal list.  */
+    struct list *next;		/* Elements for normal list.  */
   };
 
 
@@ -101,9 +101,9 @@ struct list
   ({									      \
     const char *__str = (str);						      \
     const char *__result = __str;					      \
-    size_t __cnt = DL_DST_COUNT(__str, 0);				      \
+    size_t __dst_cnt = DL_DST_COUNT (__str, 0);				      \
 									      \
-    if (__cnt != 0)							      \
+    if (__dst_cnt != 0)							      \
       {									      \
 	char *__newp;							      \
 									      \
@@ -113,9 +113,9 @@ struct list
 DST not allowed in SUID/SGID programs"));				      \
 									      \
 	__newp = (char *) alloca (DL_DST_REQUIRED (l, __str, strlen (__str),  \
-						   __cnt));		      \
+						   __dst_cnt));		      \
 									      \
-	__result = _dl_dst_substitute (l, __str, __newp, 0);	      \
+	__result = _dl_dst_substitute (l, __str, __newp, 0);		      \
 									      \
 	if (*__result == '\0')						      \
 	  {								      \
diff --git a/elf/dl-load.c b/elf/dl-load.c
index 01e1572f51..902ffc4109 100644
--- a/elf/dl-load.c
+++ b/elf/dl-load.c
@@ -1846,7 +1846,7 @@ open_path (const char *name, size_t namelen, int preloaded,
 		 auditing code.  We must try to disturb the program as
 		 little as possible.  */
 	      else if (loader == NULL
-		       || GL(dl_ns)[loader->l_ns]._ns_loaded->l_audit == 0)
+		       || GL(dl_ns)[loader->l_ns]._ns_loaded->l_auditing == 0)
 		{
 		  /* We failed to open machine dependent library.  Let's
 		     test whether there is any directory at all.  */
@@ -2030,25 +2030,34 @@ _dl_map_object (struct link_map *loader, const char *name, int preloaded,
          RPATHs.  */
       if (loader == NULL || loader->l_info[DT_RUNPATH] == NULL)
 	{
+	  /* This is the executable's map (if there is one).  Make sure that
+	     we do not look at it twice.  */
+	  struct link_map *main_map = GL(dl_ns)[LM_ID_BASE]._ns_loaded;
+	  bool did_main_map = false;
+
 	  /* First try the DT_RPATH of the dependent object that caused NAME
 	     to be loaded.  Then that object's dependent, and on up.  */
-	  for (l = loader; fd == -1 && l; l = l->l_loader)
+	  for (l = loader; l; l = l->l_loader)
 	    if (cache_rpath (l, &l->l_rpath_dirs, DT_RPATH, "RPATH"))
-	      fd = open_path (name, namelen, preloaded, &l->l_rpath_dirs,
-			      &realname, &fb, loader, LA_SER_RUNPATH,
-			      &found_other_class);
+	      {
+		fd = open_path (name, namelen, preloaded, &l->l_rpath_dirs,
+				&realname, &fb, loader, LA_SER_RUNPATH,
+				&found_other_class);
+		if (fd != -1)
+		  break;
+
+		did_main_map |= l == main_map;
+	      }
 
 	  /* If dynamically linked, try the DT_RPATH of the executable
              itself.  NB: we do this for lookups in any namespace.  */
-	  if (fd == -1)
-	    {
-	      l = GL(dl_ns)[LM_ID_BASE]._ns_loaded;
-	      if (l && l->l_type != lt_loaded && l != loader
-		  && cache_rpath (l, &l->l_rpath_dirs, DT_RPATH, "RPATH"))
-		fd = open_path (name, namelen, preloaded, &l->l_rpath_dirs,
-				&realname, &fb, loader ?: l, LA_SER_RUNPATH,
-				&found_other_class);
-	    }
+	  if (fd == -1 && !did_main_map
+	      && main_map != NULL && main_map->l_type != lt_loaded
+	      && cache_rpath (main_map, &main_map->l_rpath_dirs, DT_RPATH,
+			      "RPATH"))
+	    fd = open_path (name, namelen, preloaded, &main_map->l_rpath_dirs,
+			    &realname, &fb, loader ?: main_map, LA_SER_RUNPATH,
+			    &found_other_class);
 	}
 
       /* Try the LD_LIBRARY_PATH environment variable.  */
diff --git a/fedora/branch.mk b/fedora/branch.mk
index 93d7c4f3d8..5bfb701238 100644
--- a/fedora/branch.mk
+++ b/fedora/branch.mk
@@ -3,5 +3,5 @@ glibc-branch := fedora
 glibc-base := HEAD
 DIST_BRANCH := devel
 COLLECTION := dist-fc4
-fedora-sync-date := 2006-05-31 13:22 UTC
-fedora-sync-tag := fedora-glibc-20060531T1322
+fedora-sync-date := 2006-06-30 08:58 UTC
+fedora-sync-tag := fedora-glibc-20060630T0858
diff --git a/fedora/glibc.spec.in b/fedora/glibc.spec.in
index 58760fec40..996510aec6 100644
--- a/fedora/glibc.spec.in
+++ b/fedora/glibc.spec.in
@@ -1,6 +1,5 @@
-%define glibcrelease 11
+%define glibcrelease 12
 %define auxarches i586 i686 athlon sparcv9 alphaev6
-%define prelinkarches noarch
 %define xenarches i686 athlon
 %ifarch %{xenarches}
 %define buildxen 1
@@ -41,10 +40,7 @@ Prereq: basesystem, libgcc
 # This is for building auxiliary programs like memusage, nscd
 # For initial glibc bootstraps it can be commented out
 BuildPreReq: gd-devel libpng-devel zlib-devel texinfo, libselinux-devel >= 1.17.10-1
-BuildPreReq: audit-libs-devel >= 1.1.3, sed >= 3.95, libcap-devel
-%ifarch %{prelinkarches}
-BuildPreReq: prelink >= 0.2.0-5
-%endif
+BuildPreReq: audit-libs-devel >= 1.1.3, sed >= 3.95, libcap-devel, gettext
 # This is to ensure that __frame_state_for is exported by glibc
 # will be compatible with egcs 1.x.y
 BuildPreReq: gcc >= 3.2
@@ -720,11 +716,6 @@ cat > override_headers/asm/unistd.h <<EOF
 #define __NR_vmsplice		278
 #endif
 %endif
-%ifnarch %{ix86} x86_64
-/* FIXME: Reenable it when the kernel side is more stable.  */
-#undef __NR_newfstatat
-#undef __NR_fstatat64
-%endif
 #endif
 EOF
 cat > override_headers/asm/errno.h <<EOF
@@ -1439,6 +1430,15 @@ rm -f *.filelist*
 %endif
 
 %changelog
+* Fri Jun 30 2006 Jakub Jelinek <jakub@redhat.com> 2.4.90-12
+- buildrequire gettext
+- enable fstatat64/newfstatat syscalls even on ppc*/s390*/ia64 (#196494)
+- fix out of memory behavior in gettext (#194321)
+- fix regex on multi-byte non-UTF-8 charsets (#193873)
+- minor NIS+ fixes (#190803)
+- don't use cancellable calls in posix_spawn* and only set{u,g}id
+  current thread if requested (#193631)
+
 * Wed May 31 2006 Jakub Jelinek <jakub@redhat.com> 2.4.90-11
 - don't exit from nscd -i <database> before the database is
   actually invalidated, add locking to prune_cache (#191464)
diff --git a/intl/dcigettext.c b/intl/dcigettext.c
index b56196ccbe..cb2b1813a7 100644
--- a/intl/dcigettext.c
+++ b/intl/dcigettext.c
@@ -611,6 +611,7 @@ DCIGETTEXT (domainname, msgid1, msgid2, plural, n, category)
       if (strcmp (single_locale, "C") == 0
 	  || strcmp (single_locale, "POSIX") == 0)
 	{
+	no_translation:
 	  FREE_BLOCKS (block_list);
 	  __libc_rwlock_unlock (_nl_state_lock);
 	  __set_errno (saved_errno);
@@ -646,6 +647,12 @@ DCIGETTEXT (domainname, msgid1, msgid2, plural, n, category)
 		}
 	    }
 
+	  /* Returning -1 means that some resource problem exists
+	     (likely memory) and that the strings could not be
+	     converted.  Return the original strings.  */
+	  if (__builtin_expect (retval == (char *) -1, 0))
+	    goto no_translation;
+
 	  if (retval != NULL)
 	    {
 	      /* Found the translation of MSGID1 in domain DOMAIN:
@@ -865,21 +872,22 @@ _nl_find_msg (domain_file, domainbinding, msgid, convert, lengthp)
 	     encoding.  */
 	  struct converted_domain *new_conversions =
 	    (struct converted_domain *)
-	    (domain->conversions != NULL
-	     ? realloc (domain->conversions,
-			(nconversions + 1) * sizeof (struct converted_domain))
-	     : malloc ((nconversions + 1) * sizeof (struct converted_domain)));
+	    realloc (domain->conversions,
+		     (nconversions + 1) * sizeof (struct converted_domain));
 
 	  if (__builtin_expect (new_conversions == NULL, 0))
-	    /* Nothing we can do, no more memory.  */
-	    goto converted;
+	    /* Nothing we can do, no more memory.  We cannot use the
+	       translation because it might be encoded incorrectly.  */
+	    return (char *) -1;
+
 	  domain->conversions = new_conversions;
 
 	  /* Copy the 'encoding' string to permanent storage.  */
 	  encoding = strdup (encoding);
 	  if (__builtin_expect (encoding == NULL, 0))
-	    /* Nothing we can do, no more memory.  */
-	    goto converted;
+	    /* Nothing we can do, no more memory.  We cannot use the
+	       translation because it might be encoded incorrectly.  */
+	    return (char *) -1;
 
 	  convd = &new_conversions[nconversions];
 	  convd->encoding = encoding;
@@ -933,10 +941,18 @@ _nl_find_msg (domain_file, domainbinding, msgid, convert, lengthp)
 		    /* We always want to use transliteration.  */
 		    outcharset = norm_add_slashes (outcharset, "TRANSLIT");
 		    charset = norm_add_slashes (charset, "");
-		    if (__gconv_open (outcharset, charset, &convd->conv,
-				      GCONV_AVOID_NOCONV)
-			!= __GCONV_OK)
-		      convd->conv = (__gconv_t) -1;
+		    int r = __gconv_open (outcharset, charset, &convd->conv,
+					  GCONV_AVOID_NOCONV);
+		    if (__builtin_expect (r != __GCONV_OK, 0))
+		      {
+			/* If the output encoding is the same there is
+			   nothing to do.  Otherwise do not use the
+			   translation at all.  */
+			if (__builtin_expect (r != __GCONV_NOCONV, 1))
+			  return NULL;
+
+			convd->conv = (__gconv_t) -1;
+		      }
 # else
 #  if HAVE_ICONV
 		    /* When using GNU libc >= 2.2 or GNU libiconv >= 1.5,
@@ -1000,8 +1016,9 @@ _nl_find_msg (domain_file, domainbinding, msgid, convert, lengthp)
 	    convd->conv_tab = (char **) -1;
 
 	  if (__builtin_expect (convd->conv_tab == (char **) -1, 0))
-	    /* Nothing we can do, no more memory.  */
-	    goto converted;
+	    /* Nothing we can do, no more memory.  We cannot use the
+	       translation because it might be encoded incorrectly.  */
+	    return (char *) -1;
 
 	  if (convd->conv_tab[act] == NULL)
 	    {
@@ -1049,8 +1066,10 @@ _nl_find_msg (domain_file, domainbinding, msgid, convert, lengthp)
 
 		  if (res != __GCONV_FULL_OUTPUT)
 		    {
+		      /* We should not use the translation at all, it
+			 is incorrectly encoded.  */
 		      __libc_lock_unlock (lock);
-		      goto converted;
+		      return NULL;
 		    }
 
 		  inbuf = (const unsigned char *) result;
@@ -1076,7 +1095,7 @@ _nl_find_msg (domain_file, domainbinding, msgid, convert, lengthp)
 		  if (errno != E2BIG)
 		    {
 		      __libc_lock_unlock (lock);
-		      goto converted;
+		      return NULL;
 		    }
 #  endif
 # endif
@@ -1112,7 +1131,7 @@ _nl_find_msg (domain_file, domainbinding, msgid, convert, lengthp)
 		      freemem = NULL;
 		      freemem_size = 0;
 		      __libc_lock_unlock (lock);
-		      goto converted;
+		      return (char *) -1;
 		    }
 
 # ifdef _LIBC
@@ -1151,7 +1170,6 @@ _nl_find_msg (domain_file, domainbinding, msgid, convert, lengthp)
 	}
     }
 
- converted:
   /* The result string is converted.  */
 
 #endif /* _LIBC || HAVE_ICONV */
diff --git a/misc/Makefile b/misc/Makefile
index 63b6d413b3..f9ad0b76fc 100644
--- a/misc/Makefile
+++ b/misc/Makefile
@@ -78,7 +78,7 @@ endif
 gpl2lgpl := error.c error.h
 
 tests := tst-dirname tst-tsearch tst-fdset tst-efgcvt tst-mntent tst-hsearch \
-	 tst-error1 tst-pselect
+	 tst-error1 tst-pselect tst-insremque
 ifeq (no,$(cross-compiling))
 tests: $(objpfx)tst-error1-mem
 endif
diff --git a/misc/insremque.c b/misc/insremque.c
index e366ac8063..7f086cd392 100644
--- a/misc/insremque.c
+++ b/misc/insremque.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1992, 1995, 1996 Free Software Foundation, Inc.
+/* Copyright (C) 1992, 1995, 1996, 2006 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
@@ -24,12 +24,20 @@
 void
 insque (void *elem, void *prev)
 {
-  struct qelem *next = ((struct qelem *) prev)->q_forw;
-  ((struct qelem *) prev)->q_forw = (struct qelem *) elem;
-  if (next != NULL)
-    next->q_back = (struct qelem *) elem;
-  ((struct qelem *) elem)->q_forw = next;
-  ((struct qelem *) elem)->q_back = (struct qelem *) prev;
+  if (prev == NULL)
+    {
+      ((struct qelem *) elem)->q_forw = NULL;
+      ((struct qelem *) elem)->q_back = NULL;
+    }
+  else
+    {
+      struct qelem *next = ((struct qelem *) prev)->q_forw;
+      ((struct qelem *) prev)->q_forw = (struct qelem *) elem;
+      if (next != NULL)
+	next->q_back = (struct qelem *) elem;
+      ((struct qelem *) elem)->q_forw = next;
+      ((struct qelem *) elem)->q_back = (struct qelem *) prev;
+    }
 }
 
 /* Unlink ELEM from the doubly-linked list that it is in.  */
diff --git a/misc/tst-insremque.c b/misc/tst-insremque.c
new file mode 100644
index 0000000000..9f17055ef5
--- /dev/null
+++ b/misc/tst-insremque.c
@@ -0,0 +1,61 @@
+#include <search.h>
+#include <stdio.h>
+#include <string.h>
+
+#define CHECK(cond) \
+  do									\
+    if (! (cond))							\
+      {									\
+	printf ("Condition " #cond " not true on line %d\n", __LINE__);	\
+	ret = 1;							\
+      }									\
+  while (0)
+
+static int
+do_test (void)
+{
+  struct qelem elements[4];
+  int ret = 0;
+
+  /* Linear list.  */
+  memset (elements, 0xff, sizeof (elements));
+  insque (&elements[0], NULL);
+  remque (&elements[0]);
+  insque (&elements[0], NULL);
+  insque (&elements[2], &elements[0]);
+  insque (&elements[1], &elements[0]);
+  insque (&elements[3], &elements[2]);
+  remque (&elements[2]);
+  insque (&elements[2], &elements[0]);
+  CHECK (elements[0].q_back == NULL);
+  CHECK (elements[0].q_forw == &elements[2]);
+  CHECK (elements[1].q_back == &elements[2]);
+  CHECK (elements[1].q_forw == &elements[3]);
+  CHECK (elements[2].q_back == &elements[0]);
+  CHECK (elements[2].q_forw == &elements[1]);
+  CHECK (elements[3].q_back == &elements[1]);
+  CHECK (elements[3].q_forw == NULL);
+
+  /* Circular list.  */
+  memset (elements, 0xff, sizeof (elements));
+  elements[0].q_back = &elements[0];
+  elements[0].q_forw = &elements[0];
+  insque (&elements[2], &elements[0]);
+  insque (&elements[1], &elements[0]);
+  insque (&elements[3], &elements[2]);
+  remque (&elements[2]);
+  insque (&elements[2], &elements[0]);
+  CHECK (elements[0].q_back == &elements[3]);
+  CHECK (elements[0].q_forw == &elements[2]);
+  CHECK (elements[1].q_back == &elements[2]);
+  CHECK (elements[1].q_forw == &elements[3]);
+  CHECK (elements[2].q_back == &elements[0]);
+  CHECK (elements[2].q_forw == &elements[1]);
+  CHECK (elements[3].q_back == &elements[1]);
+  CHECK (elements[3].q_forw == &elements[0]);
+
+  return ret;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/nis/nis_subr.c b/nis/nis_subr.c
index 7e29168111..40c9270501 100644
--- a/nis/nis_subr.c
+++ b/nis/nis_subr.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 1997, 1999, 2000, 2004, 2005 Free Software Foundation, Inc.
+/* Copyright (c) 1997,1999,2000,2004,2005,2006 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Thorsten Kukuk <kukuk@vt.uni-paderborn.de>, 1997.
 
@@ -107,25 +107,23 @@ count_dots (const_nis_name str)
 nis_name *
 nis_getnames (const_nis_name name)
 {
-  nis_name *getnames = NULL;
-  char local_domain[NIS_MAXNAMELEN + 1];
+  const char *local_domain = nis_local_directory ();
+  size_t local_domain_len = strlen (local_domain);
+  size_t name_len = strlen (name);
   char *path;
-  char *cp;
-  int count;
   int pos = 0;
-  int have_point;
   char *saveptr;
+  int have_point;
+  const char *cp;
+  const char *cp2;
 
-  strncpy (local_domain, nis_local_directory (), NIS_MAXNAMELEN);
-  local_domain[NIS_MAXNAMELEN] = '\0';
-
-  count = 1;
-  getnames = malloc ((count + 1) * sizeof (char *));
+  int count = 2;
+  nis_name *getnames = malloc ((count + 1) * sizeof (char *));
   if (__builtin_expect (getnames == NULL, 0))
       return NULL;
 
   /* Do we have a fully qualified NIS+ name ? If yes, give it back */
-  if (name[strlen (name) - 1] == '.')
+  if (name[name_len - 1] == '.')
     {
       if ((getnames[0] = strdup (name)) == NULL)
 	{
@@ -141,6 +139,44 @@ nis_getnames (const_nis_name name)
       return getnames;
     }
 
+  /* If the passed NAME is shared a suffix (the latter of course with
+     a final dot) with each other we pass back NAME with a final
+     dot.  */
+  if (local_domain_len > 2)
+    {
+      have_point = 0;
+      cp = &local_domain[local_domain_len - 2];
+      cp2 = &name[name_len - 1];
+
+      while (*cp == *cp2)
+	{
+	  if (*cp == '.')
+	    have_point = 1;
+	  --cp;
+	  --cp2;
+	  if (cp < local_domain)
+	    {
+	      have_point = cp2 < name || *cp2 == '.';
+	      break;
+	    }
+	  if (cp2 < name)
+	    {
+	      have_point = *cp == '.';
+	      break;
+	    }
+	}
+
+      if (have_point)
+	{
+	  getnames[0] = malloc (name_len + 2);
+	  if (getnames[0] == NULL)
+	    goto free_null;
+
+	  strcpy (stpcpy (getnames[0], name), ".");
+	  ++pos;
+	}
+    }
+
   /* Get the search path, where we have to search "name" */
   path = getenv ("NIS_PATH");
   if (path == NULL)
@@ -148,17 +184,17 @@ nis_getnames (const_nis_name name)
   else
     path = strdupa (path);
 
-  have_point = (strchr (name, '.') != NULL);
+  have_point = strchr (name, '.') != NULL;
 
   cp = __strtok_r (path, ":", &saveptr);
   while (cp)
     {
       if (strcmp (cp, "$") == 0)
 	{
-	  char *cptr = local_domain;
+	  const char *cptr = local_domain;
 	  char *tmp;
 
-	  while ((have_point && *cptr != '\0') || (count_dots (cptr) >= 2))
+	  while (*cptr != '\0' && count_dots (cptr) >= 2)
 	    {
 	      if (pos >= count)
 		{
@@ -169,8 +205,7 @@ nis_getnames (const_nis_name name)
 		    goto free_null;
 		  getnames = newp;
 		}
-	      tmp = malloc (strlen (cptr) + strlen (local_domain) +
-			    strlen (name) + 2);
+	      tmp = malloc (strlen (cptr) + local_domain_len + name_len + 2);
 	      if (__builtin_expect (tmp == NULL, 0))
 		goto free_null;
 
@@ -200,7 +235,7 @@ nis_getnames (const_nis_name name)
 	    {
 	      char *p;
 
-	      tmp = malloc (cplen + strlen (local_domain) + strlen (name) + 2);
+	      tmp = malloc (cplen + local_domain_len + name_len + 2);
 	      if (__builtin_expect (tmp == NULL, 0))
 		goto free_null;
 
@@ -216,7 +251,7 @@ nis_getnames (const_nis_name name)
 	    {
 	      char *p;
 
-	      tmp = malloc (cplen + strlen (name) + 2);
+	      tmp = malloc (cplen + name_len + 2);
 	      if (__builtin_expect (tmp == NULL, 0))
 		goto free_null;
 
diff --git a/nptl/ChangeLog b/nptl/ChangeLog
index 04a4cfad4e..985c92d4e1 100644
--- a/nptl/ChangeLog
+++ b/nptl/ChangeLog
@@ -1,6 +1,10 @@
+2006-06-04  Ulrich Drepper  <drepper@redhat.com>
+
+	* sysdeps/pthread/pthread.h: Add pthread_equal inline version.
+
 2006-05-15  Ulrich Drepper  <drepper@redhat.com>
 
-	* sysdeps/unix/sysv/linux/fork.h: Makr __fork_handlers as hidden.
+	* sysdeps/unix/sysv/linux/fork.h: Mark __fork_handlers as hidden.
 
 2006-05-11  Ulrich Drepper  <drepper@redhat.com>
 
diff --git a/nptl/sysdeps/pthread/pthread.h b/nptl/sysdeps/pthread/pthread.h
index 5f34302e0c..f60ecdee18 100644
--- a/nptl/sysdeps/pthread/pthread.h
+++ b/nptl/sysdeps/pthread/pthread.h
@@ -1100,6 +1100,16 @@ extern int pthread_atfork (void (*__prepare) (void),
 			   void (*__parent) (void),
 			   void (*__child) (void)) __THROW;
 
+
+#ifdef __USE_EXTERN_INLINES
+/* Optimizations.  */
+extern __inline int
+__NTH (pthread_equal (pthread_t __thread1, pthread_t __thread2))
+{
+  return __thread1 == __thread2;
+}
+#endif
+
 __END_DECLS
 
 #endif	/* pthread.h */
diff --git a/posix/Makefile b/posix/Makefile
index 30ade92836..4f76a267e9 100644
--- a/posix/Makefile
+++ b/posix/Makefile
@@ -81,7 +81,7 @@ tests		:= tstgetopt testfnm runtests runptests	     \
 		   bug-regex13 bug-regex14 bug-regex15 bug-regex16 \
 		   bug-regex17 bug-regex18 bug-regex19 bug-regex20 \
 		   bug-regex21 bug-regex22 bug-regex23 bug-regex24 \
-		   tst-nice tst-nanosleep tst-regex2 \
+		   bug-regex25 tst-nice tst-nanosleep tst-regex2 \
 		   transbug tst-rxspencer tst-pcre tst-boost \
 		   bug-ga1 tst-vfork1 tst-vfork2 tst-waitid \
 		   tst-getaddrinfo2 bug-glob1 bug-glob2 tst-sysconf \
@@ -189,6 +189,7 @@ bug-regex19-ENV = LOCPATH=$(common-objpfx)localedata
 bug-regex20-ENV = LOCPATH=$(common-objpfx)localedata
 bug-regex22-ENV = LOCPATH=$(common-objpfx)localedata
 bug-regex23-ENV = LOCPATH=$(common-objpfx)localedata
+bug-regex25-ENV = LOCPATH=$(common-objpfx)localedata
 tst-rxspencer-ARGS = --utf8 rxspencer/tests
 tst-rxspencer-ENV = LOCPATH=$(common-objpfx)localedata
 tst-pcre-ARGS = PCRE.tests
diff --git a/posix/bug-regex25.c b/posix/bug-regex25.c
new file mode 100644
index 0000000000..5e56e49bb5
--- /dev/null
+++ b/posix/bug-regex25.c
@@ -0,0 +1,57 @@
+/* Test re_search in multibyte locale other than UTF-8.
+   Copyright (C) 2006 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Jakub Jelinek <jakub@redhat.com>, 2006.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include <locale.h>
+#include <regex.h>
+#include <stdio.h>
+#include <string.h>
+
+const char *str1 = "\xa3\xd8\xa3\xc9\xa3\xc9";
+const char *str2 = "\xa3\xd8\xa3\xc9";
+
+int
+main (void)
+{
+  setlocale (LC_ALL, "ja_JP.eucJP");
+
+  re_set_syntax (RE_SYNTAX_SED);
+
+  struct re_pattern_buffer re;
+  memset (&re, 0, sizeof (re));
+
+  struct re_registers regs;
+  memset (&regs, 0, sizeof (regs));
+
+  re_compile_pattern ("$", 1, &re);
+
+  int ret = 0, r = re_search (&re, str1, 4, 0, 4, &regs);
+  if (r != 4)
+    {
+      printf ("First re_search returned %d\n", r);
+      ret = 1;
+    }
+  r = re_search (&re, str2, 4, 0, 4, &regs);
+  if (r != 4)
+    {
+      printf ("Second re_search returned %d\n", r);
+      ret = 1;
+    }
+  return ret;
+}
diff --git a/posix/regex_internal.c b/posix/regex_internal.c
index 855497ebf1..ac312db0cd 100644
--- a/posix/regex_internal.c
+++ b/posix/regex_internal.c
@@ -482,7 +482,7 @@ re_string_skip_chars (re_string_t *pstr, int new_raw_idx, wint_t *last_wc)
   mbstate_t prev_st;
   int rawbuf_idx;
   size_t mbclen;
-  wchar_t wc = 0;
+  wchar_t wc = WEOF;
 
   /* Skip the characters which are not necessary to check.  */
   for (rawbuf_idx = pstr->raw_mbs_idx + pstr->valid_raw_len;
@@ -495,7 +495,11 @@ re_string_skip_chars (re_string_t *pstr, int new_raw_idx, wint_t *last_wc)
 			remain_len, &pstr->cur_state);
       if (BE (mbclen == (size_t) -2 || mbclen == (size_t) -1 || mbclen == 0, 0))
 	{
-	  /* We treat these cases as a singlebyte character.  */
+	  /* We treat these cases as a single byte character.  */
+	  if (mbclen == 0 || remain_len == 0)
+	    wc = L'\0';
+	  else
+	    wc = *(unsigned char *) (pstr->raw_mbs + rawbuf_idx);
 	  mbclen = 1;
 	  pstr->cur_state = prev_st;
 	}
@@ -618,7 +622,6 @@ re_string_reconstruct (re_string_t *pstr, int idx, int eflags)
 	    }
 #endif
 	  pstr->valid_len = 0;
-	  pstr->valid_raw_len = 0;
 #ifdef RE_ENABLE_I18N
 	  if (pstr->mb_cur_max > 1)
 	    {
@@ -681,6 +684,16 @@ re_string_reconstruct (re_string_t *pstr, int idx, int eflags)
 
 	      if (wc == WEOF)
 		pstr->valid_len = re_string_skip_chars (pstr, idx, &wc) - idx;
+	      if (wc == WEOF)
+		pstr->tip_context
+		  = re_string_context_at (pstr, pstr->valid_raw_len - 1, eflags);
+	      else
+		pstr->tip_context = ((BE (pstr->word_ops_used != 0, 0)
+				      && IS_WIDE_WORD_CHAR (wc))
+				     ? CONTEXT_WORD
+				     : ((IS_WIDE_NEWLINE (wc)
+					 && pstr->newline_anchor)
+					? CONTEXT_NEWLINE : 0));
 	      if (BE (pstr->valid_len, 0))
 		{
 		  for (wcs_idx = 0; wcs_idx < pstr->valid_len; ++wcs_idx)
@@ -689,17 +702,12 @@ re_string_reconstruct (re_string_t *pstr, int idx, int eflags)
 		    memset (pstr->mbs, 255, pstr->valid_len);
 		}
 	      pstr->valid_raw_len = pstr->valid_len;
-	      pstr->tip_context = ((BE (pstr->word_ops_used != 0, 0)
-				    && IS_WIDE_WORD_CHAR (wc))
-				   ? CONTEXT_WORD
-				   : ((IS_WIDE_NEWLINE (wc)
-				       && pstr->newline_anchor)
-				      ? CONTEXT_NEWLINE : 0));
 	    }
 	  else
 #endif /* RE_ENABLE_I18N */
 	    {
 	      int c = pstr->raw_mbs[pstr->raw_mbs_idx + offset - 1];
+	      pstr->valid_raw_len = 0;
 	      if (pstr->trans)
 		c = pstr->trans[c];
 	      pstr->tip_context = (bitset_contain (pstr->word_char, c)
diff --git a/string/Makefile b/string/Makefile
index 7c11c1ac22..a84ebebcaa 100644
--- a/string/Makefile
+++ b/string/Makefile
@@ -53,7 +53,8 @@ tests		:= tester inl-tester noinl-tester testcopy test-ffs	\
 		   tst-strlen stratcliff tst-svc tst-inlcall		\
 		   bug-strncat1 bug-strspn1 bug-strpbrk1 tst-bswap	\
 		   tst-strtok tst-strxfrm bug-strcoll1 tst-strfry	\
-		   bug-strtok1 $(addprefix test-,$(strop-tests))
+		   bug-strtok1 $(addprefix test-,$(strop-tests))	\
+		   bug-envz1
 distribute	:= memcopy.h pagecopy.h tst-svc.expect test-string.h
 
 
diff --git a/string/_strerror.c b/string/_strerror.c
index f6f16ff2af..cb5d9e3609 100644
--- a/string/_strerror.c
+++ b/string/_strerror.c
@@ -1,4 +1,5 @@
-/* Copyright (C) 1991,93,95,96,97,98,2000,2002 Free Software Foundation, Inc.
+/* Copyright (C) 1991,93,95,96,97,98,2000,2002,2006
+   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
@@ -35,8 +36,8 @@
 char *
 __strerror_r (int errnum, char *buf, size_t buflen)
 {
-  if (errnum < 0 || errnum >= _sys_nerr_internal
-      || _sys_errlist_internal[errnum] == NULL)
+  if (__builtin_expect (errnum < 0 || errnum >= _sys_nerr_internal
+			|| _sys_errlist_internal[errnum] == NULL, 0))
     {
       /* Buffer we use to print the number in.  For a maximum size for
 	 `int' of 8 bytes we never need more than 20 digits.  */
diff --git a/string/bug-envz1.c b/string/bug-envz1.c
new file mode 100644
index 0000000000..e8a60972b5
--- /dev/null
+++ b/string/bug-envz1.c
@@ -0,0 +1,76 @@
+/* Test for bug BZ #2703.  */
+#include <stdio.h>
+#include <envz.h>
+#include <stdlib.h>
+#include <string.h>
+
+static const struct
+{
+  const char *s;
+  int in_result;
+} strs[] =
+{
+  { "a=1", 1 },
+  { "b=2", 1 },
+  { "(*)", 0 },
+  { "(*)", 0 },
+  { "e=5", 1 },
+  { "f=", 1 },
+  { "(*)", 0 },
+  { "h=8", 1 },
+  { "i=9", 1 },
+  { "j", 0 }
+};
+
+#define nstrs (sizeof (strs) / sizeof (strs[0]))
+
+
+static int
+do_test (void)
+{
+
+  size_t size = 0;
+  char *str = malloc (100);
+  if (str == NULL)
+    {
+      puts ("out of memory");
+      return 1;
+    }
+
+  char **argz = &str;
+
+  for (int i = 0; i < nstrs; ++i)
+    argz_add_sep (argz, &size, strs[i].s, '\0');
+
+  printf ("calling envz_strip with size=%zu\n", size);
+  envz_strip (argz, &size);
+
+  int result = 0;
+  printf ("new size=%zu\n", size);
+  for (int i = 0; i < nstrs; ++i)
+    if (strs[i].in_result)
+      {
+        char name[2];
+        name[0] = strs[i].s[0];
+        name[1] = '\0';
+
+        char *e = envz_entry (*argz, size, name);
+        if (e == NULL)
+          {
+            printf ("entry '%s' not found\n", name);
+            result = 1;
+          }
+        else if (strcmp (e, strs[i].s) != 0)
+          {
+            printf ("entry '%s' does not match: is '%s', expected '%s'\n",
+                    name, e, strs[i].s);
+            result = 1;
+          }
+      }
+
+  free (*argz);
+  return result;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/string/envz.c b/string/envz.c
index 5c5804c12b..a9d420212f 100644
--- a/string/envz.c
+++ b/string/envz.c
@@ -1,5 +1,5 @@
 /* Routines for dealing with '\0' separated environment vectors
-   Copyright (C) 1995,96,97,98,2001,02 Free Software Foundation, Inc.
+   Copyright (C) 1995-1998,2001,2002,2006 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Written by Miles Bader <miles@gnu.org>
 
@@ -165,7 +165,7 @@ envz_strip (char **envz, size_t *envz_len)
       left -= entry_len;
       if (! strchr (entry, SEP))
 	/* Null entry. */
-	memmove (entry + entry_len, entry, left);
+	memmove (entry, entry + entry_len, left);
       else
 	entry += entry_len;
     }
diff --git a/sysdeps/generic/local-setxid.h b/sysdeps/generic/local-setxid.h
new file mode 100644
index 0000000000..b70d9ffb32
--- /dev/null
+++ b/sysdeps/generic/local-setxid.h
@@ -0,0 +1,4 @@
+/* No special support.  Fall back to the regular functions.  */
+
+#define local_seteuid(id) seteuid (id)
+#define local_setegid(id) setegid (id)
diff --git a/sysdeps/i386/Makefile b/sysdeps/i386/Makefile
index ddd3d04e07..e192b91dbd 100644
--- a/sysdeps/i386/Makefile
+++ b/sysdeps/i386/Makefile
@@ -64,4 +64,12 @@ endif
 
 ifneq (,$(filter -mno-tls-direct-seg-refs,$(CFLAGS)))
 defines += -DNO_TLS_DIRECT_SEG_REFS
+else
+# .a libraries are not performance critical and so we
+# build them without direct TLS segment references
+# always.
+CPPFLAGS-.o += -DNO_TLS_DIRECT_SEG_REFS
+CFLAGS-.o += -mno-tls-direct-seg-refs
+CPPFLAGS-.oS += -DNO_TLS_DIRECT_SEG_REFS
+CFLAGS-.oS += -mno-tls-direct-seg-refs
 endif
diff --git a/sysdeps/posix/spawni.c b/sysdeps/posix/spawni.c
index 27699f4df8..29803a8461 100644
--- a/sysdeps/posix/spawni.c
+++ b/sysdeps/posix/spawni.c
@@ -1,5 +1,5 @@
 /* Guts of POSIX spawn interface.  Generic POSIX.1 version.
-   Copyright (C) 2000,2001,2002,2003,2004,2005 Free Software Foundation, Inc.
+   Copyright (C) 2000-2005, 2006 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
@@ -26,6 +26,7 @@
 #include <unistd.h>
 #include "spawn_int.h"
 #include <not-cancel.h>
+#include <local-setxid.h>
 
 
 /* The Unix standard contains a long explanation of the way to signal
@@ -155,7 +156,8 @@ __spawni (pid_t *pid, const char *file,
 
   /* Set the effective user and group IDs.  */
   if ((flags & POSIX_SPAWN_RESETIDS) != 0
-      && (seteuid (__getuid ()) != 0 || setegid (__getgid ()) != 0))
+      && (local_seteuid (__getuid ()) != 0
+	  || local_setegid (__getgid ()) != 0))
     _exit (SPAWN_ERROR);
 
   /* Execute the file actions.  */
@@ -177,9 +179,10 @@ __spawni (pid_t *pid, const char *file,
 
 	    case spawn_do_open:
 	      {
-		int new_fd = __open64 (action->action.open_action.path,
-				       action->action.open_action.oflag,
-				       action->action.open_action.mode);
+		int new_fd = open_not_cancel (action->action.open_action.path,
+					      action->action.open_action.oflag
+					      | O_LARGEFILE,
+					      action->action.open_action.mode);
 
 		if (new_fd == -1)
 		  /* The `open' call failed.  */
@@ -193,7 +196,7 @@ __spawni (pid_t *pid, const char *file,
 		      /* The `dup2' call failed.  */
 		      _exit (SPAWN_ERROR);
 
-		    if (__close (new_fd) != 0)
+		    if (close_not_cancel (new_fd) != 0)
 		      /* The `close' call failed.  */
 		      _exit (SPAWN_ERROR);
 		  }
diff --git a/sysdeps/unix/sysv/linux/local-setxid.h b/sysdeps/unix/sysv/linux/local-setxid.h
new file mode 100644
index 0000000000..0579687982
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/local-setxid.h
@@ -0,0 +1,23 @@
+/* SETxID functions which only have to change the local thread and
+   none of the possible other threads.  */
+#include <kernel-features.h>
+#include <sysdep.h>
+
+/* If we can use the syscall directly, use it.  */
+#if __ASSUME_32BITUIDS > 0 && defined __NR_setresuid32
+# define local_seteuid(id) INLINE_SYSCALL (setresuid32, 3, -1, id, -1)
+#elif __ASSUME_SETRESUID_SYSCALL > 0
+# define local_seteuid(id) INLINE_SYSCALL (setresuid, 3, -1, id, -1)
+#else
+# define local_seteuid(id) seteuid (id)
+#endif
+
+
+/* If we can use the syscall directly, use it.  */
+#if __ASSUME_32BITUIDS > 0 && defined __NR_setresgid32
+# define local_setegid(id) INLINE_SYSCALL (setresgid32, 3, -1, id, -1)
+#elif __ASSUME_SETRESGID_SYSCALL > 0
+# define local_setegid(id) INLINE_SYSCALL (setresgid, 3, -1, id, -1)
+#else
+# define local_setegid(id) setegid (id)
+#endif