about summary refs log tree commit diff
path: root/intl/dcigettext.c
diff options
context:
space:
mode:
Diffstat (limited to 'intl/dcigettext.c')
-rw-r--r--intl/dcigettext.c34
1 files changed, 23 insertions, 11 deletions
diff --git a/intl/dcigettext.c b/intl/dcigettext.c
index e11fd06147..be312ce967 100644
--- a/intl/dcigettext.c
+++ b/intl/dcigettext.c
@@ -1,9 +1,6 @@
 /* Implementation of the internal dcigettext function.
    Copyright (C) 1995-1999, 2000 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 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
@@ -99,6 +96,11 @@ void free ();
 /* Thread safetyness.  */
 #ifdef _LIBC
 # include <bits/libc-lock.h>
+#else
+/* Provide dummy implementation if this is outside glibc.  */
+# define __libc_lock_define_initialized (CLASS, NAME)
+# define __libc_lock_lock(NAME)
+# define __libc_lock_unlock(NAME)
 #endif
 
 /* @@ end of prolog @@ */
@@ -306,6 +308,9 @@ struct block_list
 # define DCIGETTEXT dcigettext__
 #endif
 
+/* Lock variable to protect the global data in the gettext implementation.  */
+__libc_rwlock_define_initialized (, _nl_state_lock)
+
 /* Checking whether the binaries runs SUID must be done and glibc provides
    easier methods therefore we make a difference here.  */
 #ifdef _LIBC
@@ -358,6 +363,8 @@ DCIGETTEXT (domainname, msgid1, msgid2, plural, n, category)
   if (msgid1 == NULL)
     return NULL;
 
+  __libc_rwlock_rdlock (_nl_state_lock);
+
 #if defined HAVE_TSEARCH || defined _LIBC
   if (plural == 0)
     {
@@ -372,7 +379,10 @@ DCIGETTEXT (domainname, msgid1, msgid2, plural, n, category)
 
       foundp = (struct known_translation_t **) tfind (search, &root, transcmp);
       if (foundp != NULL && (*foundp)->counter == _nl_msg_cat_cntr)
-	return (char *) (*foundp)->translation;
+	{
+	  __libc_rwlock_unlock (_nl_state_lock);
+	  return (char *) (*foundp)->translation;
+	}
     }
 #endif
 
@@ -501,6 +511,7 @@ DCIGETTEXT (domainname, msgid1, msgid2, plural, n, category)
 	  || strcmp (single_locale, "POSIX") == 0)
 	{
 	  FREE_BLOCKS (block_list);
+	  __libc_rwlock_unlock (_nl_state_lock);
 	  __set_errno (saved_errno);
 	  return (plural == 0
 		  ? (char *) msgid1
@@ -539,7 +550,10 @@ DCIGETTEXT (domainname, msgid1, msgid2, plural, n, category)
 	      foundp = (struct known_translation_t **) tfind (search, &root,
 							      transcmp);
 	      if (foundp != NULL && (*foundp)->counter == _nl_msg_cat_cntr)
-		return (char *) (*foundp)->translation;
+		{
+		  __libc_rwlock_unlock (_nl_state_lock);
+		  return (char *) (*foundp)->translation;
+		}
 	    }
 #endif
 
@@ -596,6 +610,7 @@ DCIGETTEXT (domainname, msgid1, msgid2, plural, n, category)
 		  (*foundp)->translation = retval;
 		}
 #endif
+	      __libc_rwlock_unlock (_nl_state_lock);
 	      return retval;
 	    }
 	}
@@ -981,12 +996,9 @@ free_mem (void)
   struct binding *runp;
 
   for (runp = _nl_domain_bindings; runp != NULL; runp = runp->next)
-    {
-      free (runp->domainname);
-      if (runp->dirname != _nl_default_dirname)
-	/* Yes, this is a pointer comparison.  */
-	free (runp->dirname);
-    }
+    if (runp->dirname != _nl_default_dirname)
+      /* Yes, this is a pointer comparison.  */
+      free (runp->dirname);
 
   if (_nl_current_default_domain != _nl_default_default_domain)
     /* Yes, again a pointer comparison.  */