159d13433e7cbc810a6268d38141b0d1db353fa6edarylm/** @file
259d13433e7cbc810a6268d38141b0d1db353fa6edarylm  Worker functions for the setlocale function.
359d13433e7cbc810a6268d38141b0d1db353fa6edarylm
459d13433e7cbc810a6268d38141b0d1db353fa6edarylm  Copyright (c) 2010 - 2011, Intel Corporation. All rights reserved.<BR>
559d13433e7cbc810a6268d38141b0d1db353fa6edarylm  This program and the accompanying materials are licensed and made available under
659d13433e7cbc810a6268d38141b0d1db353fa6edarylm  the terms and conditions of the BSD License that accompanies this distribution.
759d13433e7cbc810a6268d38141b0d1db353fa6edarylm  The full text of the license may be found at
859d13433e7cbc810a6268d38141b0d1db353fa6edarylm  http://opensource.org/licenses/bsd-license.
959d13433e7cbc810a6268d38141b0d1db353fa6edarylm
1059d13433e7cbc810a6268d38141b0d1db353fa6edarylm  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
1159d13433e7cbc810a6268d38141b0d1db353fa6edarylm  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
122aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm
132aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm * Copyright (c) 1991, 1993
142aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm *  The Regents of the University of California.  All rights reserved.
152aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm *
162aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm * This code is derived from software contributed to Berkeley by
172aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm * Paul Borman at Krystal Technologies.
182aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm *
192aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm * Redistribution and use in source and binary forms, with or without
202aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm * modification, are permitted provided that the following conditions
212aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm * are met:
222aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm * 1. Redistributions of source code must retain the above copyright
232aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm *    notice, this list of conditions and the following disclaimer.
242aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm * 2. Redistributions in binary form must reproduce the above copyright
252aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm *    notice, this list of conditions and the following disclaimer in the
262aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm *    documentation and/or other materials provided with the distribution.
272aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm * 3. Neither the name of the University nor the names of its contributors
282aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm *    may be used to endorse or promote products derived from this software
292aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm *    without specific prior written permission.
302aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm *
312aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
322aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
332aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
342aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
352aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
362aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
372aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
382aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
392aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
402aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
412aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm * SUCH DAMAGE.
4259d13433e7cbc810a6268d38141b0d1db353fa6edarylm
4359d13433e7cbc810a6268d38141b0d1db353fa6edarylm    setlocale.c 8.1 (Berkeley) 7/4/93
4459d13433e7cbc810a6268d38141b0d1db353fa6edarylm *  NetBSD: setlocale.c,v 1.50 2006/02/16 19:19:49 tnozaki Exp
4559d13433e7cbc810a6268d38141b0d1db353fa6edarylm**/
462aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm#include  <LibConfig.h>
472aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm#include  <sys/EfiCdefs.h>
482aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm
492aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm#if defined(_MSC_VER)
502aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  // Disable warnings about assignment within conditional expressions.
512aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  #pragma warning ( disable : 4706 )
522aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm#endif
532aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm
542aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm#define _CTYPE_PRIVATE
552aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm
562aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm#include  "namespace.h"
572aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm#include  <sys/localedef.h>
582aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm#include  <sys/types.h>
592aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm#include  <sys/stat.h>
602aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm#include  <assert.h>
612aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm#include  <limits.h>
622aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm#include  <ctype.h>
632aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm#define __SETLOCALE_SOURCE__
642aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm#include  <locale.h>
652aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm#include  <paths.h>
662aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm#include  <stdio.h>
672aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm#include  <stdlib.h>
682aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm#include  <string.h>
690c1992fbccd139e9d3bb730c19a79847c6a5a246darylm#include  <unistd.h>
702aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm#include  "rune.h"
712aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm#ifdef WITH_RUNE
722aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  #include "rune_local.h"
732aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm#else
742aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  #include "ctypeio.h"
752aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm#endif
762aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm
772aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm#ifdef CITRUS
782aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  #include <citrus/citrus_namespace.h>
792aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  #include <citrus/citrus_region.h>
802aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  #include <citrus/citrus_lookup.h>
812aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  #include <citrus/citrus_bcs.h>
822aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm#else
832aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  #include "aliasname_local.h"
842aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  #define _lookup_alias(p, a, b, s, c)  __unaliasname((p), (a), (b), (s))
852aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  #define _bcs_strcasecmp(a, b)   strcasecmp((a), (b))
862aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm#endif
872aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm
882aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm#define _LOCALE_SYM_FORCE "/force"
892aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm
902aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm#ifndef WITH_RUNE
912aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  const char *_PathLocale = NULL;
922aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm#endif
932aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm
9459d13433e7cbc810a6268d38141b0d1db353fa6edarylm/** Category names for getenv(). **/
952aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylmstatic const char *const categories[_LC_LAST] = {
962aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm    "LC_ALL",
972aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm    "LC_COLLATE",
982aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm    "LC_CTYPE",
992aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm    "LC_MONETARY",
1002aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm    "LC_NUMERIC",
1012aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm    "LC_TIME",
1022aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm    "LC_MESSAGES"
1032aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm};
1042aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm
10559d13433e7cbc810a6268d38141b0d1db353fa6edarylm/** Current locales for each category.  **/
1062aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylmstatic char current_categories[_LC_LAST][32] = {
1072aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm    "C",
1082aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm    "C",
1092aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm    "C",
1102aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm    "C",
1112aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm    "C",
1122aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm    "C",
1132aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm    "C"
1142aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm};
1152aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm
1162aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm/*
1172aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm * The locales we are going to try and load
1182aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm */
1192aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylmstatic char new_categories[_LC_LAST][32];
1202aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm
1212aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylmstatic char current_locale_string[_LC_LAST * 33];
1222aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm
1232aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylmstatic char *currentlocale(void);
1242aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylmstatic void revert_to_default(int);
1252aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylmstatic int force_locale_enable(int);
1262aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylmstatic int load_locale_sub(int, const char *, int);
1272aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylmstatic char *loadlocale(int);
1282aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylmstatic const char *__get_locale_env(int);
1292aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm
1302aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylmchar *
1312aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm__setlocale(int category, const char *locale)
1322aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm{
1332aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  int i, loadlocale_success;
1342aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  size_t len;
1352aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  const char *env, *r;
1362aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm
1372aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  //if (issetugid() ||
1382aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  //    (!_PathLocale && !(_PathLocale = getenv("PATH_LOCALE"))))
1392aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  //  _PathLocale = _PATH_LOCALE;
1402aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm
1412aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  if (category < 0 || category >= _LC_LAST)
1422aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm    return (NULL);
1432aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm
1442aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  if (!locale)
1452aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm    return (category ?
1462aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm        current_categories[category] : currentlocale());
1472aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm
1482aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  /*
1492aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm   * Default to the current locale for everything.
1502aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm   */
1512aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  for (i = 1; i < _LC_LAST; ++i)
1522aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm    (void)strncpyX(new_categories[i], current_categories[i],
1532aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm        sizeof(new_categories[i]));
1542aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm
1552aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  /*
1562aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm   * Now go fill up new_categories from the locale argument
1572aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm   */
1582aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  if (!*locale) {
1592aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm    if (category == LC_ALL) {
1602aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm      for (i = 1; i < _LC_LAST; ++i) {
1612aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm        env = __get_locale_env(i);
1622aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm        (void)strncpyX(new_categories[i], env,
1632aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm            sizeof(new_categories[i]));
1642aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm      }
1652aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm    }
1662aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm    else {
1672aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm      env = __get_locale_env(category);
1682aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm      (void)strncpyX(new_categories[category], env,
1692aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm        sizeof(new_categories[category]));
1702aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm    }
1712aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  } else if (category) {
1722aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm    (void)strncpyX(new_categories[category], locale,
1732aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm        sizeof(new_categories[category]));
1742aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  } else {
1752aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm    if ((r = strchr(locale, '/')) == 0) {
1762aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm      for (i = 1; i < _LC_LAST; ++i) {
1772aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm        (void)strncpyX(new_categories[i], locale,
1782aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm            sizeof(new_categories[i]));
1792aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm      }
1802aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm    } else {
1812aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm      for (i = 1;;) {
1822aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm        _DIAGASSERT(*r == '/' || *r == 0);
1832aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm        _DIAGASSERT(*locale != 0);
1842aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm        if (*locale == '/')
1852aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm          return (NULL);  /* invalid format. */
1862aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm        len = r - locale;
1872aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm        if (len + 1 > sizeof(new_categories[i]))
1882aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm          return (NULL);  /* too long */
1892aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm        (void)memcpy(new_categories[i], locale, len);
1902aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm        new_categories[i][len] = '\0';
1912aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm        if (*r == 0)
1922aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm          break;
1932aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm        _DIAGASSERT(*r == '/');
1942aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm        if (*(locale = ++r) == 0)
1952aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm          /* slash followed by NUL */
1962aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm          return (NULL);
1972aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm        /* skip until NUL or '/' */
1982aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm        while (*r && *r != '/')
1992aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm          r++;
2002aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm        if (++i == _LC_LAST)
2012aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm          return (NULL);  /* too many slashes. */
2022aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm      }
2032aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm      if (i + 1 != _LC_LAST)
2042aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm        return (NULL);  /* too few slashes. */
2052aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm    }
2062aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  }
2072aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm
2082aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  if (category)
2092aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm    return (loadlocale(category));
2102aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm
2112aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  loadlocale_success = 0;
2122aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  for (i = 1; i < _LC_LAST; ++i) {
2132aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm    if (loadlocale(i) != NULL)
2142aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm      loadlocale_success = 1;
2152aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  }
2162aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm
2172aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  /*
2182aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm   * If all categories failed, return NULL; we don't need to back
2192aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm   * changes off, since none happened.
2202aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm   */
2212aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  if (!loadlocale_success)
2222aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm    return NULL;
2232aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm
2242aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  return (currentlocale());
2252aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm}
2262aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm
2272aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylmstatic char *
2282aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylmcurrentlocale()
2292aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm{
2302aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  int i;
2312aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm
2322aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  (void)strncpyX(current_locale_string, current_categories[1],
2332aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm      sizeof(current_locale_string));
2342aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm
2352aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  for (i = 2; i < _LC_LAST; ++i)
2362aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm    if (strcmp(current_categories[1], current_categories[i])) {
2372aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm      (void)snprintf(current_locale_string,
2382aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm          sizeof(current_locale_string), "%s/%s/%s/%s/%s/%s",
2392aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm          current_categories[1], current_categories[2],
2402aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm          current_categories[3], current_categories[4],
2412aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm          current_categories[5], current_categories[6]);
2422aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm      break;
2432aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm    }
2442aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  return (current_locale_string);
2452aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm}
2462aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm
2472aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylmstatic void
2482aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylmrevert_to_default(int category)
2492aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm{
2502aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  switch (category) {
2512aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  case LC_CTYPE:
2522aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm#ifdef WITH_RUNE
2532aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm    (void)_xpg4_setrunelocale("C");
2542aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm    (void)__runetable_to_netbsd_ctype("C");
2552aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm#else
2562aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm    if (_cClass != _C_CharClassTable) {
2572aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm      /* LINTED const castaway */
2582aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm      free((void *)_cClass);
2592aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm      _cClass = _C_CharClassTable;
2602aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm    }
2612aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm    if (_uConvT != _C_ToUpperTable) {
2622aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm      /* LINTED const castaway */
2632aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm      free((void *)_uConvT);
2642aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm      _uConvT = _C_ToUpperTable;
2652aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm    }
2662aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm    if (_lConvT != _C_ToLowerTable) {
2672aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm      /* LINTED const castaway */
2682aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm      free((void *)_lConvT);
2692aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm      _lConvT = _C_ToLowerTable;
2702aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm    }
2712aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm#endif
2722aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm    break;
2732aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  case LC_MESSAGES:
2742aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  case LC_COLLATE:
2752aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  case LC_MONETARY:
2762aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  case LC_NUMERIC:
2772aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  case LC_TIME:
2782aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm    break;
2792aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  }
2802aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm}
2812aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm
2822aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylmstatic int
2832aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylmforce_locale_enable(int category)
2842aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm{
2852aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  revert_to_default(category);
2862aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm
2872aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  return 0;
2882aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm}
2892aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm
2902aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylmstatic int
2912aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylmload_locale_sub(
2922aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  int category,
2932aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  const char *locname,
2942aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  int isspecial
2952aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  )
2962aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm{
2972aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  char name[PATH_MAX];
2982aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm
2992aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  /* check for the default locales */
3002aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  if (!strcmp(new_categories[category], "C") ||
3012aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm      !strcmp(new_categories[category], "POSIX")) {
3022aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm    revert_to_default(category);
3032aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm    return 0;
3042aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  }
3052aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm
3062aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  /* check whether special symbol */
3072aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  if (isspecial && _bcs_strcasecmp(locname, _LOCALE_SYM_FORCE) == 0)
3082aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm    return force_locale_enable(category);
3092aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm
3102aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  /* sanity check */
3112aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  if (strchr(locname, '/') != NULL)
3122aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm    return -1;
3132aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm
3142aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  (void)snprintf(name, sizeof(name), "%s/%s/%s",
3152aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm           _PathLocale, locname, categories[category]);
3162aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm
3172aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  switch (category) {
3182aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  case LC_CTYPE:
3192aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm#ifdef WITH_RUNE
3202aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm    if (_xpg4_setrunelocale(__UNCONST(locname)))
3212aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm      return -1;
3222aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm    if (__runetable_to_netbsd_ctype(locname)) {
3232aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm      /* very unfortunate, but need to go to "C" locale */
3242aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm      revert_to_default(category);
3252aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm      return -1;
3262aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm    }
3272aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm#else
3282aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm    if (!__loadctype(name))
3292aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm      return -1;
3302aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm#endif
3312aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm    break;
3322aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm
3332aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  case LC_MESSAGES:
3342aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm    /*
3352aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm     * XXX we don't have LC_MESSAGES support yet,
3362aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm     * but catopen may use the value of LC_MESSAGES category.
3372aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm     * so return successfully if locale directory is present.
3382aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm     */
3392aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm    (void)snprintf(name, sizeof(name), "%s/%s",
3402aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm      _PathLocale, locname);
3412aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm    /* local */
3422aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm    {
3432aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm      struct stat st;
3442aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm      if (stat(name, &st) < 0)
3452aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm        return -1;
3462aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm      if (!S_ISDIR(st.st_mode))
3472aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm        return -1;
3482aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm    }
3492aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm    break;
3502aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm
3512aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  case LC_COLLATE:
3522aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  case LC_MONETARY:
3532aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  case LC_NUMERIC:
3542aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  case LC_TIME:
3552aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm    return -1;
3562aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  }
3572aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm
3582aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  return 0;
3592aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm}
3602aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm
3612aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylmstatic char *
3622aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylmloadlocale(int category)
3632aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm{
3642aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  //char aliaspath[PATH_MAX], loccat[PATH_MAX], buf[PATH_MAX];
3652aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  //const char *alias;
3662aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm
3672aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  _DIAGASSERT(0 < category && category < _LC_LAST);
3682aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm
3692aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  if (strcmp(new_categories[category], current_categories[category]) == 0)
3702aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm    return (current_categories[category]);
3712aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm
3722aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  /* (1) non-aliased file */
3732aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  if (!load_locale_sub(category, new_categories[category], 0))
3742aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm    goto success;
3752aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm
3762aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  ///* (2) lookup locname/catname type alias */
3772aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  //(void)snprintf(aliaspath, sizeof(aliaspath),
3782aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  //         "%s/" _LOCALE_ALIAS_NAME, _PathLocale);
3792aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  //(void)snprintf(loccat, sizeof(loccat), "%s/%s",
3802aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  //         new_categories[category], categories[category]);
3812aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  //alias = _lookup_alias(aliaspath, loccat, buf, sizeof(buf),
3822aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  //          _LOOKUP_CASE_SENSITIVE);
3832aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  //if (!load_locale_sub(category, alias, 1))
3842aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  //  goto success;
3852aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm
3862aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  ///* (3) lookup locname type alias */
3872aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  //alias = _lookup_alias(aliaspath, new_categories[category],
3882aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  //          buf, sizeof(buf), _LOOKUP_CASE_SENSITIVE);
3892aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  //if (!load_locale_sub(category, alias, 1))
3902aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  //  goto success;
3912aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm
3922aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  return NULL;
3932aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm
3942aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylmsuccess:
3952aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  (void)strncpyX(current_categories[category],
3962aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm    new_categories[category],
3972aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm    sizeof(current_categories[category]));
3982aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  return current_categories[category];
3992aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm}
4002aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm
4012aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylmstatic const char *
4022aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm__get_locale_env(int category)
4032aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm{
4042aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  const char *env;
4052aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm
4062aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  //_DIAGASSERT(category != LC_ALL);
4072aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm
4082aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  ///* 1. check LC_ALL. */
4092aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  //env = getenv(categories[0]);
4102aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm
4112aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  ///* 2. check LC_* */
4122aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  //if (!env || !*env)
4132aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  //  env = getenv(categories[category]);
4142aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm
4152aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  ///* 3. check LANG */
4162aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  //if (!env || !*env)
4172aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  //  env = getenv("LANG");
4182aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm
4192aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  ///* 4. if none is set, fall to "C" */
4202aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  //if (!env || !*env || strchr(env, '/'))
4212aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm    env = "C";
4222aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm
4232aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  return env;
4242aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm}
425