111695Sache/*- 211695Sache * Copyright (c) 1993 311695Sache * The Regents of the University of California. All rights reserved. 411695Sache * 511695Sache * This code is derived from software contributed to Berkeley by 611695Sache * Paul Borman at Krystal Technologies. 711695Sache * 8227753Stheraven * Copyright (c) 2011 The FreeBSD Foundation 9227753Stheraven * All rights reserved. 10227753Stheraven * Portions of this software were developed by David Chisnall 11227753Stheraven * under sponsorship from the FreeBSD Foundation. 12227753Stheraven * 1311695Sache * Redistribution and use in source and binary forms, with or without 1411695Sache * modification, are permitted provided that the following conditions 1511695Sache * are met: 1611695Sache * 1. Redistributions of source code must retain the above copyright 1711695Sache * notice, this list of conditions and the following disclaimer. 1811695Sache * 2. Redistributions in binary form must reproduce the above copyright 1911695Sache * notice, this list of conditions and the following disclaimer in the 2011695Sache * documentation and/or other materials provided with the distribution. 2111695Sache * 4. Neither the name of the University nor the names of its contributors 2211695Sache * may be used to endorse or promote products derived from this software 2311695Sache * without specific prior written permission. 2411695Sache * 2511695Sache * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 2611695Sache * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2711695Sache * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2811695Sache * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 2911695Sache * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 3011695Sache * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 3111695Sache * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 3211695Sache * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 3311695Sache * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3411695Sache * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3511695Sache * SUCH DAMAGE. 3611695Sache */ 3711695Sache 3892986Sobrien#include <sys/cdefs.h> 3992986Sobrien__FBSDID("$FreeBSD: stable/11/lib/libc/locale/setrunelocale.c 337484 2018-08-08 18:52:37Z bdrewery $"); 4092986Sobrien 41323548Spfg#define __RUNETYPE_INTERNAL 1 42232498Stheraven 43136609Stjr#include <runetype.h> 4411695Sache#include <errno.h> 4511695Sache#include <limits.h> 4611695Sache#include <string.h> 4711695Sache#include <stdio.h> 4811695Sache#include <stdlib.h> 4924694Sache#include <unistd.h> 50121845Stjr#include <wchar.h> 51117270Sache#include "ldpart.h" 52129153Stjr#include "mblocal.h" 5322330Sache#include "setlocale.h" 5411695Sache 55232498Stheraven#undef _CurrentRuneLocale 56232498Stheravenextern _RuneLocale const *_CurrentRuneLocale; 57232498Stheraven#ifndef __NO_TLS 58232498Stheraven/* 59232498Stheraven * A cached version of the runes for this thread. Used by ctype.h 60232498Stheraven */ 61232498Stheraven_Thread_local const _RuneLocale *_ThreadRuneLocale; 62232498Stheraven#endif 63232498Stheraven 64172619Sacheextern int __mb_sb_limit; 65172619Sache 66290494Sbaptextern _RuneLocale *_Read_RuneMagi(const char *); 6711695Sache 68227753Stheravenstatic int __setrunelocale(struct xlocale_ctype *l, const char *); 69117270Sache 70244091Sbrooksstatic void 71244091Sbrooksdestruct_ctype(void *v) 72227753Stheraven{ 73227753Stheraven struct xlocale_ctype *l = v; 74244091Sbrooks 75323548Spfg if (&_DefaultRuneLocale != l->runes) 76227753Stheraven free(l->runes); 77227753Stheraven free(l); 78227753Stheraven} 79232498Stheraven 80244091Sbrooksconst _RuneLocale * 81244091Sbrooks__getCurrentRuneLocale(void) 82227753Stheraven{ 83244091Sbrooks 84323548Spfg return (XLOCALE_CTYPE(__get_locale())->runes); 85227753Stheraven} 86227753Stheraven 87244091Sbrooksstatic void 88244091Sbrooksfree_runes(_RuneLocale *rl) 89236889Stheraven{ 90236889Stheraven if ((rl != &_DefaultRuneLocale) && (rl)) { 91236889Stheraven free(rl); 92236889Stheraven } 93236889Stheraven} 94236889Stheraven 95117270Sachestatic int 96227753Stheraven__setrunelocale(struct xlocale_ctype *l, const char *encoding) 97117270Sache{ 9811695Sache _RuneLocale *rl; 99290494Sbapt int ret; 100290494Sbapt char *path; 101227753Stheraven struct xlocale_ctype saved = *l; 10211695Sache 10311695Sache /* 10411695Sache * The "C" and "POSIX" locale are always here. 10511695Sache */ 106101498Sache if (strcmp(encoding, "C") == 0 || strcmp(encoding, "POSIX") == 0) { 107236889Stheraven free_runes(saved.runes); 108227753Stheraven (void) _none_init(l, (_RuneLocale*)&_DefaultRuneLocale); 109101263Sache return (0); 11011695Sache } 11111695Sache 112117270Sache /* Range checking not needed, encoding length already checked before */ 113337484Sbdrewery if (asprintf(&path, "%s/%s/LC_CTYPE", _PathLocale, encoding) == -1) 114337484Sbdrewery return (errno); 11511695Sache 116290494Sbapt if ((rl = _Read_RuneMagi(path)) == NULL) { 117290494Sbapt free(path); 118290494Sbapt errno = EINVAL; 119290494Sbapt return (errno); 12011695Sache } 121290494Sbapt free(path); 12211695Sache 123227753Stheraven l->__mbrtowc = NULL; 124227753Stheraven l->__mbsinit = NULL; 125290494Sbapt l->__mbsnrtowcs = NULL; 126227753Stheraven l->__wcrtomb = NULL; 127290494Sbapt l->__wcsnrtombs = NULL; 128175586Sache 129136609Stjr rl->__sputrune = NULL; 130136609Stjr rl->__sgetrune = NULL; 131290618Sbapt if (strcmp(rl->__encoding, "NONE:US-ASCII") == 0) 132290618Sbapt ret = _ascii_init(l, rl); 133290618Sbapt else if (strncmp(rl->__encoding, "NONE", 4) == 0) 134227753Stheraven ret = _none_init(l, rl); 135175586Sache else if (strcmp(rl->__encoding, "UTF-8") == 0) 136227753Stheraven ret = _UTF8_init(l, rl); 137290494Sbapt else if (strcmp(rl->__encoding, "EUC-CN") == 0) 138290494Sbapt ret = _EUC_CN_init(l, rl); 139290494Sbapt else if (strcmp(rl->__encoding, "EUC-JP") == 0) 140290494Sbapt ret = _EUC_JP_init(l, rl); 141290494Sbapt else if (strcmp(rl->__encoding, "EUC-KR") == 0) 142290494Sbapt ret = _EUC_KR_init(l, rl); 143290494Sbapt else if (strcmp(rl->__encoding, "EUC-TW") == 0) 144290494Sbapt ret = _EUC_TW_init(l, rl); 145175586Sache else if (strcmp(rl->__encoding, "GB18030") == 0) 146323548Spfg ret = _GB18030_init(l, rl); 147175586Sache else if (strcmp(rl->__encoding, "GB2312") == 0) 148227753Stheraven ret = _GB2312_init(l, rl); 149175586Sache else if (strcmp(rl->__encoding, "GBK") == 0) 150227753Stheraven ret = _GBK_init(l, rl); 151175586Sache else if (strcmp(rl->__encoding, "BIG5") == 0) 152227753Stheraven ret = _BIG5_init(l, rl); 153175586Sache else if (strcmp(rl->__encoding, "MSKanji") == 0) 154227753Stheraven ret = _MSKanji_init(l, rl); 155175586Sache else 156101498Sache ret = EFTYPE; 157175585Sache 158101498Sache if (ret == 0) { 159227753Stheraven /* Free the old runes if it exists. */ 160236889Stheraven free_runes(saved.runes); 161175586Sache } else { 162227753Stheraven /* Restore the saved version if this failed. */ 163227753Stheraven memcpy(l, &saved, sizeof(struct xlocale_ctype)); 164101498Sache free(rl); 165175586Sache } 166101498Sache 167101498Sache return (ret); 16811695Sache} 16911695Sache 170117270Sacheint 171117270Sache__wrap_setrunelocale(const char *locale) 172117270Sache{ 173227753Stheraven int ret = __setrunelocale(&__xlocale_global_ctype, locale); 174117270Sache 175117270Sache if (ret != 0) { 176117270Sache errno = ret; 177117270Sache return (_LDP_ERROR); 178117270Sache } 179227753Stheraven __mb_cur_max = __xlocale_global_ctype.__mb_cur_max; 180227753Stheraven __mb_sb_limit = __xlocale_global_ctype.__mb_sb_limit; 181232498Stheraven _CurrentRuneLocale = __xlocale_global_ctype.runes; 182117270Sache return (_LDP_LOADED); 183117270Sache} 184232498Stheraven 185232498Stheraven#ifndef __NO_TLS 186232498Stheravenvoid 187244091Sbrooks__set_thread_rune_locale(locale_t loc) 188244091Sbrooks{ 189232498Stheraven 190232498Stheraven if (loc == NULL) { 191232498Stheraven _ThreadRuneLocale = &_DefaultRuneLocale; 192264038Stheraven } else if (loc == LC_GLOBAL_LOCALE) { 193264038Stheraven _ThreadRuneLocale = 0; 194232498Stheraven } else { 195232498Stheraven _ThreadRuneLocale = XLOCALE_CTYPE(loc)->runes; 196232498Stheraven } 197232498Stheraven} 198232498Stheraven#endif 199232498Stheraven 200232498Stheravenvoid * 201290494Sbapt__ctype_load(const char *locale, locale_t unused __unused) 202227753Stheraven{ 203227753Stheraven struct xlocale_ctype *l = calloc(sizeof(struct xlocale_ctype), 1); 204244091Sbrooks 205227753Stheraven l->header.header.destructor = destruct_ctype; 206323548Spfg if (__setrunelocale(l, locale)) { 207227753Stheraven free(l); 208323548Spfg return (NULL); 209227753Stheraven } 210323548Spfg return (l); 211227753Stheraven} 212