+++ /dev/null
-/** @file\r
- Worker functions for the setlocale function.\r
-\r
- Copyright (c) 2010 - 2011, Intel Corporation. All rights reserved.<BR>\r
- This program and the accompanying materials are licensed and made available under\r
- the terms and conditions of the BSD License that accompanies this distribution.\r
- The full text of the license may be found at\r
- http://opensource.org/licenses/bsd-license.\r
-\r
- THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
- WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
-\r
- * Copyright (c) 1991, 1993\r
- * The Regents of the University of California. All rights reserved.\r
- *\r
- * This code is derived from software contributed to Berkeley by\r
- * Paul Borman at Krystal Technologies.\r
- *\r
- * Redistribution and use in source and binary forms, with or without\r
- * modification, are permitted provided that the following conditions\r
- * are met:\r
- * 1. Redistributions of source code must retain the above copyright\r
- * notice, this list of conditions and the following disclaimer.\r
- * 2. Redistributions in binary form must reproduce the above copyright\r
- * notice, this list of conditions and the following disclaimer in the\r
- * documentation and/or other materials provided with the distribution.\r
- * 3. Neither the name of the University nor the names of its contributors\r
- * may be used to endorse or promote products derived from this software\r
- * without specific prior written permission.\r
- *\r
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND\r
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\r
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\r
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE\r
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\r
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS\r
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\r
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT\r
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY\r
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF\r
- * SUCH DAMAGE.\r
-\r
- setlocale.c 8.1 (Berkeley) 7/4/93\r
- * NetBSD: setlocale.c,v 1.50 2006/02/16 19:19:49 tnozaki Exp\r
-**/\r
-#include <LibConfig.h>\r
-#include <sys/EfiCdefs.h>\r
-\r
-#if defined(_MSC_VER)\r
- // Disable warnings about assignment within conditional expressions.\r
- #pragma warning ( disable : 4706 )\r
-#endif\r
-\r
-#define _CTYPE_PRIVATE\r
-\r
-#include "namespace.h"\r
-#include <sys/localedef.h>\r
-#include <sys/types.h>\r
-#include <sys/stat.h>\r
-#include <assert.h>\r
-#include <limits.h>\r
-#include <ctype.h>\r
-#define __SETLOCALE_SOURCE__\r
-#include <locale.h>\r
-#include <paths.h>\r
-#include <stdio.h>\r
-#include <stdlib.h>\r
-#include <string.h>\r
-#include <unistd.h>\r
-#include "rune.h"\r
-#ifdef WITH_RUNE\r
- #include "rune_local.h"\r
-#else\r
- #include "ctypeio.h"\r
-#endif\r
-\r
-#ifdef CITRUS\r
- #include <citrus/citrus_namespace.h>\r
- #include <citrus/citrus_region.h>\r
- #include <citrus/citrus_lookup.h>\r
- #include <citrus/citrus_bcs.h>\r
-#else\r
- #include "aliasname_local.h"\r
- #define _lookup_alias(p, a, b, s, c) __unaliasname((p), (a), (b), (s))\r
- #define _bcs_strcasecmp(a, b) strcasecmp((a), (b))\r
-#endif\r
-\r
-#define _LOCALE_SYM_FORCE "/force"\r
-\r
-#ifndef WITH_RUNE\r
- const char *_PathLocale = NULL;\r
-#endif\r
-\r
-/** Category names for getenv(). **/\r
-static const char *const categories[_LC_LAST] = {\r
- "LC_ALL",\r
- "LC_COLLATE",\r
- "LC_CTYPE",\r
- "LC_MONETARY",\r
- "LC_NUMERIC",\r
- "LC_TIME",\r
- "LC_MESSAGES"\r
-};\r
-\r
-/** Current locales for each category. **/\r
-static char current_categories[_LC_LAST][32] = {\r
- "C",\r
- "C",\r
- "C",\r
- "C",\r
- "C",\r
- "C",\r
- "C"\r
-};\r
-\r
-/*\r
- * The locales we are going to try and load\r
- */\r
-static char new_categories[_LC_LAST][32];\r
-\r
-static char current_locale_string[_LC_LAST * 33];\r
-\r
-static char *currentlocale(void);\r
-static void revert_to_default(int);\r
-static int force_locale_enable(int);\r
-static int load_locale_sub(int, const char *, int);\r
-static char *loadlocale(int);\r
-static const char *__get_locale_env(int);\r
-\r
-char *\r
-__setlocale(int category, const char *locale)\r
-{\r
- int i, loadlocale_success;\r
- size_t len;\r
- const char *env, *r;\r
-\r
- //if (issetugid() ||\r
- // (!_PathLocale && !(_PathLocale = getenv("PATH_LOCALE"))))\r
- // _PathLocale = _PATH_LOCALE;\r
-\r
- if (category < 0 || category >= _LC_LAST)\r
- return (NULL);\r
-\r
- if (!locale)\r
- return (category ?\r
- current_categories[category] : currentlocale());\r
-\r
- /*\r
- * Default to the current locale for everything.\r
- */\r
- for (i = 1; i < _LC_LAST; ++i)\r
- (void)strncpyX(new_categories[i], current_categories[i],\r
- sizeof(new_categories[i]));\r
-\r
- /*\r
- * Now go fill up new_categories from the locale argument\r
- */\r
- if (!*locale) {\r
- if (category == LC_ALL) {\r
- for (i = 1; i < _LC_LAST; ++i) {\r
- env = __get_locale_env(i);\r
- (void)strncpyX(new_categories[i], env,\r
- sizeof(new_categories[i]));\r
- }\r
- }\r
- else {\r
- env = __get_locale_env(category);\r
- (void)strncpyX(new_categories[category], env,\r
- sizeof(new_categories[category]));\r
- }\r
- } else if (category) {\r
- (void)strncpyX(new_categories[category], locale,\r
- sizeof(new_categories[category]));\r
- } else {\r
- if ((r = strchr(locale, '/')) == 0) {\r
- for (i = 1; i < _LC_LAST; ++i) {\r
- (void)strncpyX(new_categories[i], locale,\r
- sizeof(new_categories[i]));\r
- }\r
- } else {\r
- for (i = 1;;) {\r
- _DIAGASSERT(*r == '/' || *r == 0);\r
- _DIAGASSERT(*locale != 0);\r
- if (*locale == '/')\r
- return (NULL); /* invalid format. */\r
- len = r - locale;\r
- if (len + 1 > sizeof(new_categories[i]))\r
- return (NULL); /* too long */\r
- (void)memcpy(new_categories[i], locale, len);\r
- new_categories[i][len] = '\0';\r
- if (*r == 0)\r
- break;\r
- _DIAGASSERT(*r == '/');\r
- if (*(locale = ++r) == 0)\r
- /* slash followed by NUL */\r
- return (NULL);\r
- /* skip until NUL or '/' */\r
- while (*r && *r != '/')\r
- r++;\r
- if (++i == _LC_LAST)\r
- return (NULL); /* too many slashes. */\r
- }\r
- if (i + 1 != _LC_LAST)\r
- return (NULL); /* too few slashes. */\r
- }\r
- }\r
-\r
- if (category)\r
- return (loadlocale(category));\r
-\r
- loadlocale_success = 0;\r
- for (i = 1; i < _LC_LAST; ++i) {\r
- if (loadlocale(i) != NULL)\r
- loadlocale_success = 1;\r
- }\r
-\r
- /*\r
- * If all categories failed, return NULL; we don't need to back\r
- * changes off, since none happened.\r
- */\r
- if (!loadlocale_success)\r
- return NULL;\r
-\r
- return (currentlocale());\r
-}\r
-\r
-static char *\r
-currentlocale()\r
-{\r
- int i;\r
-\r
- (void)strncpyX(current_locale_string, current_categories[1],\r
- sizeof(current_locale_string));\r
-\r
- for (i = 2; i < _LC_LAST; ++i)\r
- if (strcmp(current_categories[1], current_categories[i])) {\r
- (void)snprintf(current_locale_string,\r
- sizeof(current_locale_string), "%s/%s/%s/%s/%s/%s",\r
- current_categories[1], current_categories[2],\r
- current_categories[3], current_categories[4],\r
- current_categories[5], current_categories[6]);\r
- break;\r
- }\r
- return (current_locale_string);\r
-}\r
-\r
-static void\r
-revert_to_default(int category)\r
-{\r
- switch (category) {\r
- case LC_CTYPE:\r
-#ifdef WITH_RUNE\r
- (void)_xpg4_setrunelocale("C");\r
- (void)__runetable_to_netbsd_ctype("C");\r
-#else\r
- if (_cClass != _C_CharClassTable) {\r
- /* LINTED const castaway */\r
- free((void *)_cClass);\r
- _cClass = _C_CharClassTable;\r
- }\r
- if (_uConvT != _C_ToUpperTable) {\r
- /* LINTED const castaway */\r
- free((void *)_uConvT);\r
- _uConvT = _C_ToUpperTable;\r
- }\r
- if (_lConvT != _C_ToLowerTable) {\r
- /* LINTED const castaway */\r
- free((void *)_lConvT);\r
- _lConvT = _C_ToLowerTable;\r
- }\r
-#endif\r
- break;\r
- case LC_MESSAGES:\r
- case LC_COLLATE:\r
- case LC_MONETARY:\r
- case LC_NUMERIC:\r
- case LC_TIME:\r
- break;\r
- }\r
-}\r
-\r
-static int\r
-force_locale_enable(int category)\r
-{\r
- revert_to_default(category);\r
-\r
- return 0;\r
-}\r
-\r
-static int\r
-load_locale_sub(\r
- int category,\r
- const char *locname,\r
- int isspecial\r
- )\r
-{\r
- char name[PATH_MAX];\r
-\r
- /* check for the default locales */\r
- if (!strcmp(new_categories[category], "C") ||\r
- !strcmp(new_categories[category], "POSIX")) {\r
- revert_to_default(category);\r
- return 0;\r
- }\r
-\r
- /* check whether special symbol */\r
- if (isspecial && _bcs_strcasecmp(locname, _LOCALE_SYM_FORCE) == 0)\r
- return force_locale_enable(category);\r
-\r
- /* sanity check */\r
- if (strchr(locname, '/') != NULL)\r
- return -1;\r
-\r
- (void)snprintf(name, sizeof(name), "%s/%s/%s",\r
- _PathLocale, locname, categories[category]);\r
-\r
- switch (category) {\r
- case LC_CTYPE:\r
-#ifdef WITH_RUNE\r
- if (_xpg4_setrunelocale(__UNCONST(locname)))\r
- return -1;\r
- if (__runetable_to_netbsd_ctype(locname)) {\r
- /* very unfortunate, but need to go to "C" locale */\r
- revert_to_default(category);\r
- return -1;\r
- }\r
-#else\r
- if (!__loadctype(name))\r
- return -1;\r
-#endif\r
- break;\r
-\r
- case LC_MESSAGES:\r
- /*\r
- * XXX we don't have LC_MESSAGES support yet,\r
- * but catopen may use the value of LC_MESSAGES category.\r
- * so return successfully if locale directory is present.\r
- */\r
- (void)snprintf(name, sizeof(name), "%s/%s",\r
- _PathLocale, locname);\r
- /* local */\r
- {\r
- struct stat st;\r
- if (stat(name, &st) < 0)\r
- return -1;\r
- if (!S_ISDIR(st.st_mode))\r
- return -1;\r
- }\r
- break;\r
-\r
- case LC_COLLATE:\r
- case LC_MONETARY:\r
- case LC_NUMERIC:\r
- case LC_TIME:\r
- return -1;\r
- }\r
-\r
- return 0;\r
-}\r
-\r
-static char *\r
-loadlocale(int category)\r
-{\r
- //char aliaspath[PATH_MAX], loccat[PATH_MAX], buf[PATH_MAX];\r
- //const char *alias;\r
-\r
- _DIAGASSERT(0 < category && category < _LC_LAST);\r
-\r
- if (strcmp(new_categories[category], current_categories[category]) == 0)\r
- return (current_categories[category]);\r
-\r
- /* (1) non-aliased file */\r
- if (!load_locale_sub(category, new_categories[category], 0))\r
- goto success;\r
-\r
- ///* (2) lookup locname/catname type alias */\r
- //(void)snprintf(aliaspath, sizeof(aliaspath),\r
- // "%s/" _LOCALE_ALIAS_NAME, _PathLocale);\r
- //(void)snprintf(loccat, sizeof(loccat), "%s/%s",\r
- // new_categories[category], categories[category]);\r
- //alias = _lookup_alias(aliaspath, loccat, buf, sizeof(buf),\r
- // _LOOKUP_CASE_SENSITIVE);\r
- //if (!load_locale_sub(category, alias, 1))\r
- // goto success;\r
-\r
- ///* (3) lookup locname type alias */\r
- //alias = _lookup_alias(aliaspath, new_categories[category],\r
- // buf, sizeof(buf), _LOOKUP_CASE_SENSITIVE);\r
- //if (!load_locale_sub(category, alias, 1))\r
- // goto success;\r
-\r
- return NULL;\r
-\r
-success:\r
- (void)strncpyX(current_categories[category],\r
- new_categories[category],\r
- sizeof(current_categories[category]));\r
- return current_categories[category];\r
-}\r
-\r
-static const char *\r
-__get_locale_env(int category)\r
-{\r
- const char *env;\r
-\r
- //_DIAGASSERT(category != LC_ALL);\r
-\r
- ///* 1. check LC_ALL. */\r
- //env = getenv(categories[0]);\r
-\r
- ///* 2. check LC_* */\r
- //if (!env || !*env)\r
- // env = getenv(categories[category]);\r
-\r
- ///* 3. check LANG */\r
- //if (!env || !*env)\r
- // env = getenv("LANG");\r
-\r
- ///* 4. if none is set, fall to "C" */\r
- //if (!env || !*env || strchr(env, '/'))\r
- env = "C";\r
-\r
- return env;\r
-}\r