about summary refs log tree commit diff
path: root/locale/findlocale.c
diff options
context:
space:
mode:
authorUlrich Drepper <drepper@redhat.com>2001-04-06 17:49:18 +0000
committerUlrich Drepper <drepper@redhat.com>2001-04-06 17:49:18 +0000
commite7f21fa6fbbad55ff2654e39732f54bf147cbfce (patch)
tree9797799d8e0cc2e33746ec176d611cac4571916e /locale/findlocale.c
parentee62473f2bd030dc42b601c06dae78e69b6cdaec (diff)
downloadglibc-e7f21fa6fbbad55ff2654e39732f54bf147cbfce.tar.gz
glibc-e7f21fa6fbbad55ff2654e39732f54bf147cbfce.tar.xz
glibc-e7f21fa6fbbad55ff2654e39732f54bf147cbfce.zip
Update.
2001-04-06  Ulrich Drepper  <drepper@redhat.com>

	* iconv/iconv_open.c: Move strip and upstr definitions...
	* iconv/gconv_charset.h: ...here.  New file.
	* iconv/gconv_db.c (once): Move to file level.
	(do_lookup_alias): Split out from __gconv_find_transform.
	(__gconv_find_transform): Call do_lookup_alias.
	(__gconv_loopup_alias): New function.
	* locale/langinfo.h: Define _NL_*_CODESET values for all categories
	but LC_CTYPE.
	* locale/categories.def: Add entries for new _NL_*_CODESET values.
	* locale/C-ctype.c: Use _nl_C_codeset to initialize CODESET entry.
	* locale/C-address.c: Initialize _NL_*_CODESET element.
	* locale/C-collate.c: Likewise.
	* locale/C-identification.c: Likewise.
	* locale/C-measurement.c: Likewise.
	* locale/C-messages.c: Likewise.
	* locale/C-monetary.c: Likewise.
	* locale/C-name.c: Likewise.
	* locale/C-numeric.c: Likewise.
	* locale/C-paper.c: Likewise.
	* locale/C-telephone.c: Likewise.
	* locale/C-time.c: Likewise.
	* locale/localeinfo.h: Declare _nl_C_codeset.
	* locale/C_name.c: Define _nl_C_codeset.
	* locale/findlocale.c: Before accepting locale check that the used
	charset does not conflict with what the locale name said.
	* locale/programs/ld-address.c: Emit codeset information.
	* locale/programs/ld-collate.c: Likewise.
	* locale/programs/ld-identification.c: Likewise.
	* locale/programs/ld-measurement.c: Likewise.
	* locale/programs/ld-messages.c: Likewise.
	* locale/programs/ld-monetary.c: Likewise.
	* locale/programs/ld-name.c: Likewise.
	* locale/programs/ld-numeric.c: Likewise.
	* locale/programs/ld-paper.c: Likewise.
	* locale/programs/ld-telephone.c: Likewise.
	* locale/programs/ld-time.c: Likewise.

	* localedata/tests-mbwc/tst_funcs.h (TST_HEAD_LOCALE): It is an error
	if the locale data couldn't be found.

	* string/Makefile: Define tst-strxfrm-ENV.

	* ysdeps/unix/sysv/linux/ia64/getcontext.S: Fix comment.
Diffstat (limited to 'locale/findlocale.c')
-rw-r--r--locale/findlocale.c52
1 files changed, 51 insertions, 1 deletions
diff --git a/locale/findlocale.c b/locale/findlocale.c
index 948dee2a46..de2dc2ea66 100644
--- a/locale/findlocale.c
+++ b/locale/findlocale.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1996, 1997, 1998, 1999, 2000 Free Software Foundation, Inc.
+/* Copyright (C) 1996,1997,1998,1999,2000,2001 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996.
 
@@ -17,6 +17,7 @@
    write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
    Boston, MA 02111-1307, USA.  */
 
+#include <assert.h>
 #include <locale.h>
 #include <stdlib.h>
 #include <string.h>
@@ -26,6 +27,7 @@
 #endif
 
 #include "localeinfo.h"
+#include "../iconv/gconv_charset.h"
 
 
 /* Constant data defined in setlocale.c.  */
@@ -164,6 +166,54 @@ _nl_find_locale (const char *locale_path, size_t locale_path_len,
 	return NULL;
     }
 
+  /* The LC_CTYPE category allows to check whether a locale is really
+     usable.  If the locale name contains a charset name and the
+     charset name used in the locale (present in the LC_CTYPE data) is
+     not the same (after resolving aliases etc) we reject the locale
+     since using it would irritate users expecting the charset named
+     in the locale name.  */
+  if (codeset != NULL)
+    {
+      /* Get the codeset information from the locale file.  */
+      static const int codeset_idx[] =
+	{
+	  [__LC_CTYPE] = _NL_ITEM_INDEX (CODESET),
+	  [__LC_NUMERIC] = _NL_ITEM_INDEX (_NL_NUMERIC_CODESET),
+	  [__LC_TIME] = _NL_ITEM_INDEX (_NL_TIME_CODESET),
+	  [__LC_COLLATE] = _NL_ITEM_INDEX (_NL_COLLATE_CODESET),
+	  [__LC_MONETARY] = _NL_ITEM_INDEX (_NL_MONETARY_CODESET),
+	  [__LC_MESSAGES] = _NL_ITEM_INDEX (_NL_MESSAGES_CODESET),
+	  [__LC_PAPER] = _NL_ITEM_INDEX (_NL_PAPER_CODESET),
+	  [__LC_NAME] = _NL_ITEM_INDEX (_NL_NAME_CODESET),
+	  [__LC_ADDRESS] = _NL_ITEM_INDEX (_NL_ADDRESS_CODESET),
+	  [__LC_TELEPHONE] = _NL_ITEM_INDEX (_NL_TELEPHONE_CODESET),
+	  [__LC_MEASUREMENT] = _NL_ITEM_INDEX (_NL_MEASUREMENT_CODESET),
+	  [__LC_IDENTIFICATION] = _NL_ITEM_INDEX (_NL_IDENTIFICATION_CODESET)
+	};
+      const struct locale_data *data;
+      const char *locale_codeset;
+      char *clocale_codeset;
+      char *ccodeset;
+
+      data = (const struct locale_data *) locale_file->data;
+      locale_codeset =
+	(const char *) data->values[codeset_idx[category]].string;
+      assert (locale_codeset != NULL);
+      /* Note the length of the allocated memory: +3 for up to two slashes
+	 and the NUL byte.  */
+      clocale_codeset = (char *) alloca (strlen (locale_codeset) + 3);
+      strip (clocale_codeset, locale_codeset);
+
+      ccodeset = (char *) alloca (strlen (codeset) + 3);
+      strip (ccodeset, codeset);
+
+      if (strcmp (__gconv_lookup_alias (upstr (ccodeset, ccodeset)),
+		  __gconv_lookup_alias (upstr (clocale_codeset,
+					       clocale_codeset))) != 0)
+	/* The codesets are not identical, don't use the locale.  */
+	return NULL;
+    }
+
   /* Determine the locale name for which loading succeeded.  This
      information comes from the file name.  The form is
      <path>/<locale>/LC_foo.  We must extract the <locale> part.  */